Annotation of rsaref/rdemo/dhdemo.c, revision 1.1.1.1

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:       (&params, "  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:       (&params, "  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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.