|
|
1.1 root 1: /* DHDEMO.C - demonstration program for Diffie-Hellman extensions to
2: RSAREF
3: */
4:
5: /* Copyright (C) 1993 RSA Laboratories, a division of RSA Data
6: Security, Inc. All rights reserved.
7: */
8:
9: #include <stdio.h>
10: #include <string.h>
11: #include <stdlib.h>
12: #include "global.h"
13: #include "rsaref.h"
14:
15: int main PROTO_LIST ((int, char **));
16: static int SetOptions PROTO_LIST ((int, char **));
17: static void InitRandomStruct PROTO_LIST ((R_RANDOM_STRUCT *));
18: static void DoSetupAgreement PROTO_LIST ((R_RANDOM_STRUCT *));
19: static void DoComputeAgreedKey PROTO_LIST ((void));
20: static void DoGenerateParams PROTO_LIST ((R_RANDOM_STRUCT *));
21: static void WriteParams2 PROTO_LIST ((void));
22: static void WriteBigInteger PROTO_LIST
23: ((FILE *, unsigned char *, unsigned int));
24: static int ReadBlock PROTO_LIST
25: ((unsigned char *, unsigned int *, unsigned int, char *));
26: static int WriteBlock PROTO_LIST ((unsigned char *, unsigned int, char *));
27: static int GetParams PROTO_LIST ((R_DH_PARAMS **, char *));
28: static void PrintMessage PROTO_LIST ((char *));
29: static void PrintError PROTO_LIST ((char *, int));
30: static void GetCommand PROTO_LIST ((char *, unsigned int, char *));
31:
32: static int SILENT_PROMPT = 0;
33:
34: static unsigned char PRIME1[64] = {
35: 0xd0, 0x45, 0x1f, 0xfe, 0x2c, 0x64, 0xc4, 0xed, 0x6b, 0x0a, 0xe6,
36: 0x36, 0x5b, 0x7f, 0xef, 0x9c, 0x15, 0x42, 0x5e, 0x40, 0xa3, 0x7c,
37: 0xa5, 0xf8, 0x39, 0x86, 0x5e, 0x2c, 0xfb, 0x41, 0x69, 0xa0, 0xd8,
38: 0x25, 0xc9, 0x13, 0x0f, 0x88, 0x64, 0xff, 0xfc, 0xf3, 0xbf, 0xbe,
39: 0xb0, 0x27, 0x36, 0x60, 0x67, 0xaa, 0x27, 0xe2, 0x7b, 0xfc, 0xaf,
40: 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
41: };
42: static unsigned char GENERATOR1[64] = {
43: 0x0a, 0xcf, 0x95, 0x8c, 0x40, 0xd3, 0x01, 0xef, 0xc5, 0x15, 0x3e,
44: 0x7d, 0xcd, 0x5e, 0xf7, 0x5f, 0xec, 0x9e, 0x8f, 0xb0, 0xfa, 0xe6,
45: 0xa8, 0x0e, 0xe5, 0xc3, 0xb8, 0x4b, 0x9c, 0x0e, 0x51, 0x30, 0x51,
46: 0xb2, 0xb7, 0x54, 0x2e, 0x66, 0xb8, 0xd3, 0xa2, 0x5e, 0x93, 0x89,
47: 0x11, 0xad, 0x6b, 0xe5, 0xc2, 0x43, 0x95, 0x09, 0x9c, 0x6d, 0xda,
48: 0xa8, 0x6e, 0x18, 0x94, 0x2f, 0x29, 0x84, 0x27, 0x5a
49: };
50:
51: static R_DH_PARAMS PARAMS1 = {
52: PRIME1, sizeof (PRIME1), GENERATOR1, sizeof (GENERATOR1)
53: };
54: R_DH_PARAMS PARAMS2;
55: int PARAMS2_READY = 0;
56:
57: int main (argc, argv)
58: int argc;
59: char *argv[];
60: {
61: R_RANDOM_STRUCT randomStruct;
62: char command[80];
63: int done = 0;
64:
65: if (SetOptions (argc, argv))
66: return (0);
67:
68: InitRandomStruct (&randomStruct);
69: PrintMessage
70: ("NOTE: When saving to a file, a filename of \"-\" will output to the screen.");
71:
72: while (!done) {
73: PrintMessage ("");
74: PrintMessage ("S - Set up a key agreement");
75: PrintMessage ("C - Compute an agreed-upon key");
76: PrintMessage ("G - Generate parameters (may take a long time)");
77: PrintMessage ("Q - Quit");
78: GetCommand (command, sizeof (command), " Enter choice: ");
79:
80: switch (*command) {
81: case '\0':
82: case '#':
83: /* entered a blank line or a comment */
84: break;
85:
86: case 's':
87: case 'S':
88: DoSetupAgreement (&randomStruct);
89: break;
90:
91: case 'c':
92: case 'C':
93: DoComputeAgreedKey ();
94: break;
95:
96: case 'g':
97: case 'G':
98: DoGenerateParams (&randomStruct);
99: break;
100:
101: case 'Q':
102: case 'q':
103: done = 1;
104: break;
105:
106: default:
107: PrintError ("ERROR: Unrecognized command. Try again.", 0);
108: break;
109: }
110: }
111:
112: R_RandomFinal (&randomStruct);
113: return (0);
114: }
115:
116: /* Set options from command line and return 0 for success, 1 for bad format.
117: */
118: static int SetOptions (argc, argv)
119: int argc;
120: char *argv[];
121: {
122: int i, status = 0;
123:
124: for (i = 1; i < argc; i++) {
125: if (argv[i][0] != '-') {
126: status = 1;
127: break;
128: }
129:
130: if (argv[i][1] == 's')
131: SILENT_PROMPT = 1;
132: else {
133: status = 1;
134: break;
135: }
136: }
137:
138: if (status)
139: puts ("Usage: dhdemo [-s]\n\
140: -s silent prompts");
141:
142: return (status);
143: }
144:
145: /* Initialize the random structure with all zero seed bytes for test purposes.
146: NOTE that this will cause the output of the "random" process to be
147: the same every time. To produce random bytes, the random struct
148: needs random seeds!
149: */
150: static void InitRandomStruct (randomStruct)
151: R_RANDOM_STRUCT *randomStruct;
152: {
153: static unsigned char seedByte = 0;
154: unsigned int bytesNeeded;
155:
156: R_RandomInit (randomStruct);
157:
158: /* Initialize with all zero seed bytes, which will not yield an actual
159: random number output.
160: */
161: while (1) {
162: R_GetRandomBytesNeeded (&bytesNeeded, randomStruct);
163: if (bytesNeeded == 0)
164: break;
165:
166: R_RandomUpdate (randomStruct, &seedByte, 1);
167: }
168: }
169:
170: static void DoSetupAgreement (randomStruct)
171: R_RANDOM_STRUCT *randomStruct;
172: {
173: R_DH_PARAMS *params;
174: char command[80];
175: int status;
176: unsigned char *privateValue, *publicValue;
177: unsigned int privateValueLen;
178:
179: if (GetParams
180: (¶ms, " Set up with parameters 1 or 2? (blank to cancel): "))
181: return;
182:
183: GetCommand
184: (command, sizeof (command),
185: " Enter length in bytes of private value (blank to cancel): ");
186: if (! *command)
187: return;
188: sscanf (command, "%d", &privateValueLen);
189:
190: privateValue = (unsigned char *)malloc (privateValueLen);
191: publicValue = (unsigned char *)malloc (params->primeLen);
192:
193: /* Set up a break point with a do {} while (0) so that we can
194: zeroize the sensitive buffers before exiting.
195: */
196: do {
197: if (status = R_SetupDHAgreement
198: (publicValue, privateValue, privateValueLen, params, randomStruct)) {
199: PrintError ("setting up key agreement", status);
200: break;
201: }
202:
203: if (WriteBlock
204: (publicValue, params->primeLen,
205: " Enter filename to save the public value (blank to cancel): "))
206: break;
207:
208: if (WriteBlock
209: (privateValue, privateValueLen,
210: " Enter filename to save the private value (blank to cancel): "))
211: break;
212: } while (0);
213:
214: memset ((POINTER)privateValue, 0, privateValueLen);
215: free (privateValue);
216: free (publicValue);
217: }
218:
219: static void DoComputeAgreedKey ()
220: {
221: R_DH_PARAMS *params;
222: int status;
223: unsigned char *agreedKey, *otherPublicValue, *privateValue;
224: unsigned int otherPublicValueLen, privateValueLen;
225:
226: if (GetParams
227: (¶ms, " Compute with parameters 1 or 2? (blank to cancel): "))
228: return;
229:
230: otherPublicValue = (unsigned char *)malloc (params->primeLen);
231: privateValue = (unsigned char *)malloc (params->primeLen);
232: agreedKey = (unsigned char *)malloc (params->primeLen);
233:
234: /* Set up a break point with a do {} while (0) so that we can
235: zeroize the sensitive buffers before exiting.
236: */
237: do {
238: if (ReadBlock
239: (otherPublicValue, &otherPublicValueLen, params->primeLen,
240: " Enter filename of other party's public value (blank to cancel): "))
241: break;
242: if (otherPublicValueLen != params->primeLen) {
243: PrintError ("ERROR: Other party's public value has wrong length", 0);
244: break;
245: }
246:
247: if (ReadBlock
248: (privateValue, &privateValueLen, params->primeLen,
249: " Enter filename of private value (blank to cancel): "))
250: break;
251:
252: if (status = R_ComputeDHAgreedKey
253: (agreedKey, otherPublicValue, privateValue, privateValueLen, params)) {
254: PrintError ("computing agreed-upon key", status);
255: break;
256: }
257:
258: if (WriteBlock
259: (agreedKey, params->primeLen,
260: " Enter filename to save the agreed-upon key (blank to cancel): "))
261: break;
262: } while (0);
263:
264: memset ((POINTER)privateValue, 0, privateValueLen);
265: memset ((POINTER)agreedKey, 0, params->primeLen);
266: free (otherPublicValue);
267: free (privateValue);
268: free (agreedKey);
269: }
270:
271: static void DoGenerateParams (randomStruct)
272: R_RANDOM_STRUCT *randomStruct;
273: {
274: char command[80];
275: int status, primeBits, subPrimeBits;
276:
277: GetCommand
278: (command, sizeof (command),
279: " Enter prime size in bits, (16 to 1024) (blank to cancel): ");
280: if (! *command)
281: return;
282: sscanf (command, "%d", &primeBits);
283:
284: GetCommand
285: (command, sizeof (command),
286: " Enter subprime size in bits, (16 to 1024) (blank to cancel): ");
287: if (! *command)
288: return;
289: sscanf (command, "%d", &subPrimeBits);
290:
291: if (PARAMS2_READY) {
292: free (PARAMS2.prime);
293: free (PARAMS2.generator);
294: }
295: PARAMS2.prime = (unsigned char *)malloc (DH_PRIME_LEN (primeBits));
296: PARAMS2.generator = (unsigned char *)malloc (DH_PRIME_LEN (primeBits));
297:
298: if (status = R_GenerateDHParams
299: (&PARAMS2, primeBits, subPrimeBits, randomStruct)) {
300: PrintError ("generating parameters", status);
301: return;
302: }
303:
304: PrintMessage ("Parameters 2 are now ready to use.");
305: PARAMS2_READY = 1;
306:
307: WriteParams2 ();
308: }
309:
310: static void WriteParams2 ()
311: {
312: FILE *file;
313: char filename[256];
314:
315: while (1) {
316: GetCommand
317: (filename, sizeof (filename),
318: "Enter filename to save the parameters (blank to not save): ");
319: if (! *filename)
320: return;
321:
322: if (filename[0] == '-' && filename[1] == '\0') {
323: /* use stdout */
324: file = stdout;
325: break;
326: }
327: if ((file = fopen (filename, "w")) != NULL)
328: /* successfully opened */
329: break;
330:
331: PrintError ("ERROR: Cannot open a file with that name. Try again.", 0);
332: }
333:
334: fprintf (file, "Parameters:\n");
335: fprintf (file, " prime: ");
336: WriteBigInteger (file, PARAMS2.prime, PARAMS2.primeLen);
337: fprintf (file, " generator: ");
338: WriteBigInteger (file, PARAMS2.generator, PARAMS2.generatorLen);
339:
340: if (file != stdout)
341: fclose (file);
342: }
343:
344: /* Write the byte string 'integer' to 'file', skipping over leading zeros.
345: */
346: static void WriteBigInteger (file, integer, integerLen)
347: FILE *file;
348: unsigned char *integer;
349: unsigned int integerLen;
350: {
351: while (*integer == 0 && integerLen > 0) {
352: integer++;
353: integerLen--;
354: }
355:
356: if (integerLen == 0) {
357: /* Special case, just print a zero. */
358: fprintf (file, "00\n");
359: return;
360: }
361:
362: for (; integerLen > 0; integerLen--)
363: fprintf (file, "%02x ", (unsigned int)(*integer++));
364:
365: fprintf (file, "\n");
366: }
367:
368: /* Use the prompt to ask the user to use parameters 1 or 2 and
369: point params to the answer.
370: Return 0 on success or 1 if user cancels by entering a blank.
371: */
372: static int GetParams (params, prompt)
373: R_DH_PARAMS **params;
374: char *prompt;
375: {
376: char command[80];
377:
378: while (1) {
379: GetCommand (command, sizeof (command), prompt);
380:
381: switch (*command) {
382: case '\0':
383: return (1);
384:
385: case '1':
386: *params = &PARAMS1;
387: return (0);
388:
389: case '2':
390: if (!PARAMS2_READY) {
391: PrintError
392: ("ERROR: Parameters 2 have not been generated yet. Try Again.", 0);
393: break;
394: }
395: else {
396: *params = &PARAMS2;
397: return (0);
398: }
399:
400: default:
401: if (PARAMS2_READY)
402: PrintError ("ERROR: Please enter 1 or 2. Try again.", 0);
403: else
404: PrintError ("ERROR: Please enter 1. Try again.", 0);
405: break;
406: }
407: }
408: }
409:
410: /* Read a file of up to length maxBlockLen bytes, storing it in
411: block and returning its length in blockLen.
412: Ask for the filename using the given prompt string.
413: Return 0 on success or 1 if error or if user cancels by entering a blank.
414: */
415: static int ReadBlock (block, blockLen, maxBlockLen, prompt)
416: unsigned char *block;
417: unsigned int *blockLen;
418: unsigned int maxBlockLen;
419: char *prompt;
420: {
421: FILE *file;
422: int status;
423: char filename[256];
424: unsigned char dummy;
425:
426: while (1) {
427: GetCommand (filename, sizeof (filename), prompt);
428: if (! *filename)
429: return (1);
430:
431: if ((file = fopen (filename, "rb")) != NULL)
432: /* successfully opened */
433: break;
434:
435: PrintError ("ERROR: Cannot open a file with that name. Try again.", 0);
436: }
437:
438: /* fread () returns the number of items read in. Expect an end of file
439: after the read.
440: */
441: *blockLen = fread (block, 1, maxBlockLen, file);
442: if (*blockLen == maxBlockLen)
443: /* Read exactly maxBlockLen bytes, so reading one more will set
444: end of file if there were exactly maxBlockLen bytes in the file.
445: */
446: fread (&dummy, 1, 1, file);
447:
448: if (!feof (file)) {
449: PrintError ("ERROR: Cannot read file or file is too large.", 0);
450: status = 1;
451: }
452: else
453: status = 0;
454:
455: fclose (file);
456: return (status);
457: }
458:
459: /* Write block oflength blockLen to a file.
460: Ask for the filename using the given prompt string.
461: Return 0 on success or 1 if error or if user cancels by entering a blank.
462: */
463: static int WriteBlock (block, blockLen, prompt)
464: unsigned char *block;
465: unsigned int blockLen;
466: char *prompt;
467: {
468: FILE *file;
469: int status;
470: char filename[256];
471:
472: while (1) {
473: GetCommand (filename, sizeof (filename), prompt);
474: if (! *filename)
475: return (1);
476:
477: if (filename[0] == '-' && filename[1] == '\0') {
478: /* use stdout */
479: file = stdout;
480: break;
481: }
482: if ((file = fopen (filename, "wb")) != NULL)
483: /* successfully opened */
484: break;
485:
486: PrintError ("ERROR: Cannot open a file with that name. Try again.", 0);
487: }
488:
489: status = 0;
490: if (fwrite (block, 1, blockLen, file) < blockLen) {
491: PrintError ("ERROR: Cannot write file.", 0);
492: status = 1;
493: }
494: else {
495: if (file == stdout)
496: /* Printing to screen, so print a new line. */
497: printf ("\n");
498: }
499:
500: if (file != stdout)
501: fclose (file);
502: return (status);
503: }
504:
505: static void PrintMessage (message)
506: char *message;
507: {
508: if (!SILENT_PROMPT) {
509: puts (message);
510: fflush (stdout);
511: }
512: }
513:
514: /* If type is zero, simply print the task string, otherwise convert the
515: type to a string and print task and type.
516: */
517: static void PrintError (task, type)
518: char *task;
519: int type;
520: {
521: char *typeString, buf[80];
522:
523: if (type == 0) {
524: puts (task);
525: return;
526: }
527:
528: /* Convert the type to a string if it is recognized.
529: */
530: switch (type) {
531: case RE_CONTENT_ENCODING:
532: typeString = "(Encrypted) content has RFC 1113 encoding error";
533: break;
534: case RE_DIGEST_ALGORITHM:
535: typeString = "Message-digest algorithm is invalid";
536: break;
537: case RE_KEY:
538: typeString = "Recovered DES key cannot decrypt encrypted content or encrypt signature";
539: break;
540: case RE_KEY_ENCODING:
541: typeString = "Encrypted key has RFC 1113 encoding error";
542: break;
543: case RE_MODULUS_LEN:
544: typeString = "Modulus length is invalid";
545: break;
546: case RE_NEED_RANDOM:
547: typeString = "Random structure is not seeded";
548: break;
549: case RE_PRIVATE_KEY:
550: typeString = "Private key cannot encrypt message digest, or cannot decrypt encrypted key";
551: break;
552: case RE_PUBLIC_KEY:
553: typeString = "Public key cannot encrypt DES key, or cannot decrypt signature";
554: break;
555: case RE_SIGNATURE:
556: typeString = "Signature on content or block is incorrect";
557: break;
558: case RE_SIGNATURE_ENCODING:
559: typeString = "(Encrypted) signature has RFC 1113 encoding error";
560: break;
561:
562: default:
563: sprintf (buf, "Code 0x%04x", type);
564: typeString = buf;
565: }
566:
567: printf ("ERROR: %s while %s\n", typeString, task);
568: fflush (stdout);
569: }
570:
571: static void GetCommand (command, maxCommandSize, prompt)
572: char *command;
573: unsigned int maxCommandSize;
574: char *prompt;
575: {
576: unsigned int i;
577:
578: if (!SILENT_PROMPT) {
579: printf ("%s\n", prompt);
580: fflush (stdout);
581: }
582:
583: fgets (command, maxCommandSize, stdin);
584:
585: /* Replace the line terminator with a '\0'.
586: */
587: for (i = 0; command[i] != '\0'; i++) {
588: if (command[i] == '\012' || command[i] == '\015' ||
589: i == (maxCommandSize - 1)) {
590: command[i] = '\0';
591: return;
592: }
593: }
594: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.