Annotation of pgp/rsaref/source/r_enhanc.c, revision 1.1.1.1

1.1       root        1: /* R_ENHANC.C - cryptographic enhancements for RSAREF
                      2:  */
                      3: 
                      4: /* Copyright (C) RSA Laboratories, a division of RSA Data Security,
                      5:      Inc., created 1991. All rights reserved.
                      6:  */
                      7: 
                      8: #include "global.h"
                      9: #include "rsaref.h"
                     10: #include "r_random.h"
                     11: #include "rsa.h"
                     12: 
                     13: /* DigestInfo encoding is DIGEST_INFO_A, then 2 or 5 (for MD2/MD5),
                     14:    then DIGEST_INFO_B, then 16-byte message digest.
                     15:  */
                     16: 
                     17: static unsigned char DIGEST_INFO_A[] = {
                     18:   0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7,
                     19:   0x0d, 0x02
                     20: };
                     21: #define DIGEST_INFO_A_LEN sizeof (DIGEST_INFO_A)
                     22: 
                     23: static unsigned char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 };
                     24: #define DIGEST_INFO_B_LEN sizeof (DIGEST_INFO_B)
                     25: 
                     26: #define DIGEST_INFO_LEN (DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN + 16)
                     27: 
                     28: static unsigned char *PADDING[] = {
                     29:   (unsigned char *)"", (unsigned char *)"\001", (unsigned char *)"\002\002",
                     30:   (unsigned char *)"\003\003\003", (unsigned char *)"\004\004\004\004",
                     31:   (unsigned char *)"\005\005\005\005\005",
                     32:   (unsigned char *)"\006\006\006\006\006\006", 
                     33:   (unsigned char *)"\007\007\007\007\007\007\007",
                     34:   (unsigned char *)"\010\010\010\010\010\010\010\010"
                     35: };
                     36: 
                     37: #define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN
                     38: 
                     39: static void R_EncodeDigestInfo PROTO_LIST
                     40:   ((unsigned char *, int, unsigned char *));
                     41: static void EncryptPEMUpdateFinal PROTO_LIST
                     42:   ((R_ENVELOPE_CTX *, unsigned char *, unsigned int *, unsigned char *,
                     43:     unsigned int));
                     44: static int DecryptPEMUpdateFinal PROTO_LIST
                     45:   ((R_ENVELOPE_CTX *, unsigned char *, unsigned int *, unsigned char *,
                     46:     unsigned int));
                     47: static int CipherInit PROTO_LIST
                     48:   ((R_ENVELOPE_CTX *, int, unsigned char *, unsigned char *, int));
                     49: static void CipherUpdate PROTO_LIST
                     50:   ((R_ENVELOPE_CTX *, unsigned char *, unsigned char *, unsigned int));
                     51: static void CipherRestart PROTO_LIST ((R_ENVELOPE_CTX *));
                     52: 
                     53: int R_DigestInit (context, digestAlgorithm)
                     54: R_DIGEST_CTX *context;                                       /* new context */
                     55: int digestAlgorithm;                            /* message-digest algorithm */
                     56: {
                     57:   context->digestAlgorithm = digestAlgorithm;
                     58: 
                     59:   switch (digestAlgorithm) {
                     60:   case DA_MD2:
                     61:     MD2Init (&context->context.md2);
                     62:     break;
                     63: 
                     64:   case DA_MD5:
                     65:     MD5Init (&context->context.md5);
                     66:     break;
                     67:   
                     68:   default:
                     69:     return (RE_DIGEST_ALGORITHM);
                     70:   }
                     71: 
                     72:   return (0);
                     73: }
                     74: 
                     75: int R_DigestUpdate (context, partIn, partInLen)
                     76: R_DIGEST_CTX *context;                                           /* context */
                     77: unsigned char *partIn;                                    /* next data part */
                     78: unsigned int partInLen;                         /* length of next data part */
                     79: {
                     80:   if (context->digestAlgorithm == DA_MD2)
                     81:     MD2Update (&context->context.md2, partIn, partInLen);
                     82:   else
                     83:     MD5Update (&context->context.md5, partIn, partInLen);
                     84:   return (0);
                     85: }
                     86: 
                     87: int R_DigestFinal (context, digest, digestLen)
                     88: R_DIGEST_CTX *context;                                           /* context */
                     89: unsigned char *digest;                                    /* message digest */
                     90: unsigned int *digestLen;                        /* length of message digest */
                     91: {
                     92:   *digestLen = 16;
                     93:   if (context->digestAlgorithm == DA_MD2)
                     94:     MD2Final (digest, &context->context.md2);
                     95:   else
                     96:     MD5Final (digest, &context->context.md5);
                     97: 
                     98:   return (0);
                     99: }
                    100: 
                    101: int R_SignInit (context, digestAlgorithm)
                    102: R_SIGNATURE_CTX *context;                                    /* new context */
                    103: int digestAlgorithm;                            /* message-digest algorithm */
                    104: {
                    105:   return (R_DigestInit (&context->digestContext, digestAlgorithm));
                    106: }
                    107: 
                    108: int R_SignUpdate (context, partIn, partInLen)
                    109: R_SIGNATURE_CTX *context;                                        /* context */
                    110: unsigned char *partIn;                                    /* next data part */
                    111: unsigned int partInLen;                         /* length of next data part */
                    112: {
                    113:   return (R_DigestUpdate (&context->digestContext, partIn, partInLen));
                    114: }
                    115: 
                    116: int R_SignFinal (context, signature, signatureLen, privateKey)
                    117: R_SIGNATURE_CTX *context;                                        /* context */
                    118: unsigned char *signature;                                      /* signature */
                    119: unsigned int *signatureLen;                          /* length of signature */
                    120: R_RSA_PRIVATE_KEY *privateKey;                  /* signer's RSA private key */
                    121: {
                    122:   int status;
                    123:   unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN];
                    124:   unsigned int digestLen;
                    125: 
                    126:   do {
                    127:     if ((status = R_DigestFinal (&context->digestContext, digest, &digestLen))
                    128:         != 0)
                    129:       break;
                    130: 
                    131:     R_EncodeDigestInfo
                    132:       (digestInfo, context->digestContext.digestAlgorithm, digest);
                    133:     
                    134:     if (RSAPrivateEncrypt
                    135:         (signature, signatureLen, digestInfo, DIGEST_INFO_LEN, privateKey)
                    136:         != 0) {
                    137:       status = RE_PRIVATE_KEY;
                    138:       break;
                    139:     }
                    140: 
                    141:     /* Reset for another verification. Assume Init won't fail */
                    142:     R_DigestInit
                    143:       (&context->digestContext, context->digestContext.digestAlgorithm);
                    144:   } while (0);
                    145:   
                    146:   /* Zeroize potentially sensitive information.
                    147:    */
                    148:   R_memset ((POINTER)digest, 0, sizeof (digest));
                    149:   R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo));
                    150: 
                    151:   return (status);
                    152: }
                    153: 
                    154: int R_VerifyInit (context, digestAlgorithm)
                    155: R_SIGNATURE_CTX *context;                                    /* new context */
                    156: int digestAlgorithm;                            /* message-digest algorithm */
                    157: {
                    158:   return (R_DigestInit (&context->digestContext, digestAlgorithm));
                    159: }
                    160: 
                    161: int R_VerifyUpdate (context, partIn, partInLen)
                    162: R_SIGNATURE_CTX *context;                                        /* context */
                    163: unsigned char *partIn;                                    /* next data part */
                    164: unsigned int partInLen;                         /* length of next data part */
                    165: {
                    166:   return (R_DigestUpdate (&context->digestContext, partIn, partInLen));
                    167: }
                    168: 
                    169: int R_VerifyFinal (context, signature, signatureLen, publicKey)
                    170: R_SIGNATURE_CTX *context;                                        /* context */
                    171: unsigned char *signature;                                      /* signature */
                    172: unsigned int signatureLen;                           /* length of signature */
                    173: R_RSA_PUBLIC_KEY *publicKey;                     /* signer's RSA public key */
                    174: {
                    175:   int status;
                    176:   unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN],
                    177:     originalDigestInfo[MAX_SIGNATURE_LEN];
                    178:   unsigned int originalDigestInfoLen, digestLen;
                    179:   
                    180:   if (signatureLen > MAX_SIGNATURE_LEN)
                    181:     return (RE_LEN);
                    182: 
                    183:   status = 0;
                    184:   do {
                    185:     if ((status = R_DigestFinal (&context->digestContext, digest, &digestLen))
                    186:         != 0)
                    187:       break;
                    188: 
                    189:     R_EncodeDigestInfo
                    190:       (digestInfo, context->digestContext.digestAlgorithm, digest);
                    191:     
                    192:     if (RSAPublicDecrypt
                    193:         (originalDigestInfo, &originalDigestInfoLen, signature, signatureLen, 
                    194:          publicKey) != 0) {
                    195:       status = RE_PUBLIC_KEY;
                    196:       break;
                    197:     }
                    198:     
                    199:     if ((originalDigestInfoLen != DIGEST_INFO_LEN) ||
                    200:         (R_memcmp 
                    201:          ((POINTER)originalDigestInfo, (POINTER)digestInfo,
                    202:           DIGEST_INFO_LEN))) {
                    203:       status = RE_SIGNATURE;
                    204:       break;
                    205:     }
                    206: 
                    207:     /* Reset for another verification. Assume Init won't fail */
                    208:     R_DigestInit
                    209:       (&context->digestContext, context->digestContext.digestAlgorithm);
                    210:   } while (0);
                    211:   
                    212:   /* Zeroize potentially sensitive information.
                    213:    */
                    214:   R_memset ((POINTER)digest, 0, sizeof (digest));
                    215:   R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo));
                    216:   R_memset ((POINTER)originalDigestInfo, 0, sizeof (originalDigestInfo));
                    217: 
                    218:   return (status);
                    219: }
                    220: 
                    221: /* Caller must ASCII recode the encrypted keys if desired.
                    222:  */
                    223: int R_SealInit
                    224:   (context, encryptedKeys, encryptedKeyLens, iv, publicKeyCount, publicKeys,
                    225:    encryptionAlgorithm, randomStruct)
                    226: R_ENVELOPE_CTX *context;                                     /* new context */
                    227: unsigned char **encryptedKeys;                            /* encrypted keys */
                    228: unsigned int *encryptedKeyLens;                /* lengths of encrypted keys */
                    229: unsigned char iv[8];                               /* initialization vector */
                    230: unsigned int publicKeyCount;                       /* number of public keys */
                    231: R_RSA_PUBLIC_KEY **publicKeys;                               /* public keys */
                    232: int encryptionAlgorithm;                       /* data encryption algorithm */
                    233: R_RANDOM_STRUCT *randomStruct;                          /* random structure */
                    234: {
                    235:   int status;
                    236:   unsigned char key[24];
                    237:   unsigned int keyLen, i;
                    238:   
                    239:   do {
                    240:     context->encryptionAlgorithm = encryptionAlgorithm;
                    241:     
                    242:     keyLen = (encryptionAlgorithm == EA_DES_CBC) ? 8 : 24;
                    243:     if ((status = R_GenerateBytes (key, keyLen, randomStruct)) != 0)
                    244:       break;
                    245:     if ((status = R_GenerateBytes (iv, 8, randomStruct)) != 0)
                    246:       break;
                    247: 
                    248:     if (encryptionAlgorithm == EA_DES_EDE2_CBC)
                    249:       /* Make both E keys the same */
                    250:       R_memcpy ((POINTER)(key + 16), (POINTER)key, 8);
                    251: 
                    252:     if ((status = CipherInit (context, encryptionAlgorithm, key, iv, 1)) != 0)
                    253:       break;
                    254: 
                    255:     for (i = 0; i < publicKeyCount; ++i) {
                    256:       if (RSAPublicEncrypt
                    257:           (encryptedKeys[i], &encryptedKeyLens[i], key, keyLen,
                    258:            publicKeys[i], randomStruct)) {
                    259:         status = RE_PUBLIC_KEY;
                    260:         break;
                    261:       }
                    262:     }
                    263:     if (status != 0)
                    264:       break;
                    265: 
                    266:     context->bufferLen = 0;
                    267:   } while (0);
                    268:   
                    269:   /* Zeroize sensitive information.
                    270:    */
                    271:   R_memset ((POINTER)key, 0, sizeof (key));
                    272: 
                    273:   return (status);
                    274: }
                    275: 
                    276: /* Assume partOut buffer is at least partInLen + 7, since this may flush
                    277:      buffered input.
                    278:  */
                    279: int R_SealUpdate (context, partOut, partOutLen, partIn, partInLen)
                    280: R_ENVELOPE_CTX *context;                                         /* context */
                    281: unsigned char *partOut;                         /* next encrypted data part */
                    282: unsigned int *partOutLen;             /* length of next encrypted data part */
                    283: unsigned char *partIn;                                    /* next data part */
                    284: unsigned int partInLen;                         /* length of next data part */
                    285: {
                    286:   unsigned int tempLen;
                    287: 
                    288:   tempLen = 8 - context->bufferLen;
                    289:   if (partInLen < tempLen) {
                    290:     /* Just accumulate into buffer.
                    291:      */
                    292:     R_memcpy
                    293:       ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
                    294:        partInLen);
                    295:     context->bufferLen += partInLen;
                    296:     *partOutLen = 0;
                    297:     return (0);
                    298:   }
                    299: 
                    300:   /* Fill the buffer and encrypt.
                    301:    */
                    302:   R_memcpy
                    303:     ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
                    304:      tempLen);
                    305:   CipherUpdate (context, partOut, context->buffer, 8);
                    306:   partIn += tempLen;
                    307:   partInLen -= tempLen;
                    308:   partOut += 8;
                    309:   *partOutLen = 8;
                    310: 
                    311:   /* Encrypt as many 8-byte blocks as possible.
                    312:    */
                    313:   tempLen = 8 * (partInLen / 8);
                    314:   CipherUpdate (context, partOut, partIn, tempLen);
                    315:   partIn += tempLen;
                    316:   partInLen -= tempLen;
                    317:   *partOutLen += tempLen;
                    318: 
                    319:   /* Length is now less than 8, so copy remainder to buffer.
                    320:    */
                    321:   R_memcpy
                    322:     ((POINTER)context->buffer, (POINTER)partIn,
                    323:      context->bufferLen = partInLen);
                    324: 
                    325:   return (0);
                    326: }
                    327: 
                    328: /* Assume partOut buffer is at least 8 bytes.
                    329:  */
                    330: int R_SealFinal (context, partOut, partOutLen)
                    331: R_ENVELOPE_CTX *context;                                         /* context */
                    332: unsigned char *partOut;                         /* last encrypted data part */
                    333: unsigned int *partOutLen;             /* length of last encrypted data part */
                    334: {
                    335:   unsigned int padLen;
                    336: 
                    337:   /* Pad and encrypt final block.
                    338:    */
                    339:   padLen = 8 - context->bufferLen;
                    340:   R_memset
                    341:     ((POINTER)(context->buffer + context->bufferLen), (int)padLen, padLen);
                    342:   CipherUpdate (context, partOut, context->buffer, 8);
                    343:   *partOutLen = 8;
                    344: 
                    345:   /* Restart the context.
                    346:    */
                    347:   CipherRestart (context);
                    348:   context->bufferLen = 0;
                    349: 
                    350:   return (0);
                    351: }
                    352: 
                    353: /* Assume caller has already ASCII decoded the encryptedKey if necessary.
                    354:  */
                    355: int R_OpenInit
                    356:   (context, encryptionAlgorithm, encryptedKey, encryptedKeyLen, iv, privateKey)
                    357: R_ENVELOPE_CTX *context;                                     /* new context */
                    358: int encryptionAlgorithm;                       /* data encryption algorithm */
                    359: unsigned char *encryptedKey;               /* encrypted data encryption key */
                    360: unsigned int encryptedKeyLen;                    /* length of encrypted key */
                    361: unsigned char iv[8];                               /* initialization vector */
                    362: R_RSA_PRIVATE_KEY *privateKey;               /* recipient's RSA private key */
                    363: {
                    364:   int status;
                    365:   unsigned char key[MAX_ENCRYPTED_KEY_LEN];
                    366:   unsigned int keyLen;
                    367:   
                    368:   if (encryptedKeyLen > MAX_ENCRYPTED_KEY_LEN)
                    369:     return (RE_LEN);
                    370:   
                    371:   do {
                    372:     context->encryptionAlgorithm = encryptionAlgorithm;
                    373: 
                    374:     if (RSAPrivateDecrypt
                    375:         (key, &keyLen, encryptedKey, encryptedKeyLen, privateKey)) {
                    376:       status = RE_PRIVATE_KEY;
                    377:       break;
                    378:     }
                    379: 
                    380:     if (encryptionAlgorithm == EA_DES_CBC) {    
                    381:       if (keyLen != 8) {
                    382:         status = RE_PRIVATE_KEY;
                    383:         break;
                    384:       }
                    385:     }
                    386:     else {
                    387:       if (keyLen != 24) {
                    388:         status = RE_PRIVATE_KEY;
                    389:         break;
                    390:       }
                    391:     }
                    392:     
                    393:     if ((status = CipherInit (context, encryptionAlgorithm, key, iv, 0)) != 0)
                    394:       break;
                    395: 
                    396:     context->bufferLen = 0;
                    397:   } while (0);
                    398:   
                    399:   /* Zeroize sensitive information.
                    400:    */
                    401:   R_memset ((POINTER)key, 0, sizeof (key));
                    402: 
                    403:   return (status);
                    404: }
                    405: 
                    406: /* Assume partOut buffer is at least partInLen + 7, since this may flush
                    407:      buffered input. Always leaves at least one byte in buffer.
                    408:  */
                    409: int R_OpenUpdate (context, partOut, partOutLen, partIn, partInLen)
                    410: R_ENVELOPE_CTX *context;                                         /* context */
                    411: unsigned char *partOut;                         /* next recovered data part */
                    412: unsigned int *partOutLen;             /* length of next recovered data part */
                    413: unsigned char *partIn;                          /* next encrypted data part */
                    414: unsigned int partInLen;               /* length of next encrypted data part */
                    415: {
                    416:   unsigned int tempLen;
                    417: 
                    418:   tempLen = 8 - context->bufferLen;
                    419:   if (partInLen <= tempLen) {
                    420:     /* Just accumulate into buffer.
                    421:      */
                    422:     R_memcpy
                    423:       ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
                    424:        partInLen);
                    425:     context->bufferLen += partInLen;
                    426:     *partOutLen = 0;
                    427:     return (0);
                    428:   }
                    429: 
                    430:   /* Fill the buffer and decrypt.  We know that there will be more left
                    431:        in partIn after decrypting the buffer.
                    432:    */
                    433:   R_memcpy
                    434:     ((POINTER)(context->buffer + context->bufferLen), (POINTER)partIn,
                    435:      tempLen);
                    436:   CipherUpdate (context, partOut, context->buffer, 8);
                    437:   partIn += tempLen;
                    438:   partInLen -= tempLen;
                    439:   partOut += 8;
                    440:   *partOutLen = 8;
                    441: 
                    442:   /* Decrypt as many 8 byte blocks as possible, leaving at least one byte
                    443:        in partIn.
                    444:    */
                    445:   tempLen = 8 * ((partInLen - 1) / 8);
                    446:   CipherUpdate (context, partOut, partIn, tempLen);
                    447:   partIn += tempLen;
                    448:   partInLen -= tempLen;
                    449:   *partOutLen += tempLen;
                    450: 
                    451:   /* Length is between 1 and 8, so copy into buffer.
                    452:    */
                    453:   R_memcpy
                    454:     ((POINTER)context->buffer, (POINTER)partIn,
                    455:      context->bufferLen = partInLen);
                    456: 
                    457:   return (0);
                    458: }
                    459: 
                    460: /* Assume partOut buffer is at least 7 bytes.
                    461:  */
                    462: int R_OpenFinal (context, partOut, partOutLen)
                    463: R_ENVELOPE_CTX *context;                                         /* context */
                    464: unsigned char *partOut;                         /* last recovered data part */
                    465: unsigned int *partOutLen;             /* length of last recovered data part */
                    466: {
                    467:   int status;
                    468:   unsigned char lastPart[8];
                    469:   unsigned int padLen;
                    470: 
                    471:   status = 0;
                    472:   do {
                    473:     if (context->bufferLen == 0)
                    474:       /* There was no input data to decrypt */
                    475:       *partOutLen = 0;
                    476:     else {
                    477:       if (context->bufferLen != 8) {
                    478:         status = RE_KEY;
                    479:         break;
                    480:       }
                    481: 
                    482:       /* Decrypt and strip padding from final block which is in buffer.
                    483:        */
                    484:       CipherUpdate (context, lastPart, context->buffer, 8);
                    485:     
                    486:       padLen = lastPart[7];
                    487:       if (padLen == 0 || padLen > 8) {
                    488:         status = RE_KEY;
                    489:         break;
                    490:       }
                    491:       if (R_memcmp 
                    492:           ((POINTER)&lastPart[8 - padLen], PADDING[padLen], padLen) != 0) {
                    493:         status = RE_KEY;
                    494:         break;
                    495:       }
                    496:       
                    497:       R_memcpy ((POINTER)partOut, (POINTER)lastPart, *partOutLen = 8 - padLen);
                    498:     }
                    499: 
                    500:     /* Restart the context.
                    501:      */
                    502:     CipherRestart (context);
                    503:     context->bufferLen = 0;
                    504:   } while (0);
                    505: 
                    506:   /* Zeroize sensitive information.
                    507:    */
                    508:   R_memset ((POINTER)lastPart, 0, sizeof (lastPart));
                    509: 
                    510:   return (status);
                    511: }
                    512: 
                    513: int R_SignPEMBlock 
                    514:   (encodedContent, encodedContentLen, encodedSignature, encodedSignatureLen,
                    515:    content, contentLen, recode, digestAlgorithm, privateKey)
                    516: unsigned char *encodedContent;                           /* encoded content */
                    517: unsigned int *encodedContentLen;               /* length of encoded content */
                    518: unsigned char *encodedSignature;                       /* encoded signature */
                    519: unsigned int *encodedSignatureLen;           /* length of encoded signature */
                    520: unsigned char *content;                                          /* content */
                    521: unsigned int contentLen;                               /* length of content */
                    522: int recode;                                                /* recoding flag */
                    523: int digestAlgorithm;                            /* message-digest algorithm */
                    524: R_RSA_PRIVATE_KEY *privateKey;                  /* signer's RSA private key */
                    525: {
                    526:   int status;
                    527:   unsigned char signature[MAX_SIGNATURE_LEN];
                    528:   unsigned int signatureLen;
                    529:   
                    530:   if ((status = R_SignBlock
                    531:        (signature, &signatureLen, content, contentLen, digestAlgorithm,
                    532:         privateKey)) != 0)
                    533:     return (status);
                    534: 
                    535:   R_EncodePEMBlock 
                    536:     (encodedSignature, encodedSignatureLen, signature, signatureLen);
                    537: 
                    538:   if (recode)
                    539:     R_EncodePEMBlock
                    540:     (encodedContent, encodedContentLen, content, contentLen);
                    541: 
                    542:   return (0);
                    543: }
                    544: 
                    545: int R_SignBlock
                    546:   (signature, signatureLen, block, blockLen, digestAlgorithm, privateKey)
                    547: unsigned char *signature;                                      /* signature */
                    548: unsigned int *signatureLen;                          /* length of signature */
                    549: unsigned char *block;                                              /* block */
                    550: unsigned int blockLen;                                   /* length of block */
                    551: int digestAlgorithm;                            /* message-digest algorithm */
                    552: R_RSA_PRIVATE_KEY *privateKey;                  /* signer's RSA private key */
                    553: {
                    554:   R_SIGNATURE_CTX context;
                    555:   int status;
                    556: 
                    557:   do {
                    558:     if ((status = R_SignInit (&context, digestAlgorithm)) != 0)
                    559:       break;
                    560:     if ((status = R_SignUpdate (&context, block, blockLen)) != 0)
                    561:       break;
                    562:     if ((status = R_SignFinal (&context, signature, signatureLen, privateKey))
                    563:         != 0)
                    564:       break;
                    565:   } while (0);
                    566: 
                    567:   /* Zeroize sensitive information. */
                    568:   R_memset ((POINTER)&context, 0, sizeof (context));
                    569: 
                    570:   return (status);
                    571: }
                    572: 
                    573: int R_VerifyPEMSignature 
                    574:   (content, contentLen, encodedContent, encodedContentLen, encodedSignature,
                    575:    encodedSignatureLen, recode, digestAlgorithm, publicKey)
                    576: unsigned char *content;                                          /* content */
                    577: unsigned int *contentLen;                              /* length of content */
                    578: unsigned char *encodedContent;                /* (possibly) encoded content */
                    579: unsigned int encodedContentLen;                /* length of encoded content */
                    580: unsigned char *encodedSignature;                       /* encoded signature */
                    581: unsigned int encodedSignatureLen;            /* length of encoded signature */
                    582: int recode;                                                /* recoding flag */
                    583: int digestAlgorithm;                            /* message-digest algorithm */
                    584: R_RSA_PUBLIC_KEY *publicKey;                     /* signer's RSA public key */
                    585: {
                    586:   unsigned char signature[MAX_SIGNATURE_LEN];
                    587:   unsigned int signatureLen;
                    588:   
                    589:   if (encodedSignatureLen > MAX_PEM_SIGNATURE_LEN)
                    590:     return (RE_SIGNATURE_ENCODING);
                    591:   
                    592:   if (recode) {
                    593:     if (R_DecodePEMBlock
                    594:         (content, contentLen, encodedContent, encodedContentLen))
                    595:       return (RE_CONTENT_ENCODING);
                    596:   }
                    597:   else {
                    598:     content = encodedContent;
                    599:     *contentLen = encodedContentLen;
                    600:   }
                    601:     
                    602:   if (R_DecodePEMBlock
                    603:       (signature, &signatureLen, encodedSignature, encodedSignatureLen))
                    604:     return (RE_SIGNATURE_ENCODING);
                    605:   
                    606:   return (R_VerifyBlockSignature 
                    607:           (content, *contentLen, signature, signatureLen, digestAlgorithm,
                    608:            publicKey));
                    609: }
                    610: 
                    611: int R_VerifyBlockSignature 
                    612:   (block, blockLen, signature, signatureLen, digestAlgorithm, publicKey)
                    613: unsigned char *block;                                              /* block */
                    614: unsigned int blockLen;                                   /* length of block */
                    615: unsigned char *signature;                                      /* signature */
                    616: unsigned int signatureLen;                           /* length of signature */
                    617: int digestAlgorithm;                            /* message-digest algorithm */
                    618: R_RSA_PUBLIC_KEY *publicKey;                     /* signer's RSA public key */
                    619: {
                    620:   R_SIGNATURE_CTX context;
                    621:   int status;
                    622: 
                    623:   do {
                    624:     if ((status = R_VerifyInit (&context, digestAlgorithm)) != 0)
                    625:       break;
                    626:     if ((status = R_VerifyUpdate (&context, block, blockLen)) != 0)
                    627:       break;
                    628:     if ((status = R_VerifyFinal (&context, signature, signatureLen, publicKey))
                    629:         != 0)
                    630:       break;
                    631:   } while (0);
                    632: 
                    633:   /* Zeroize sensitive information. */
                    634:   R_memset ((POINTER)&context, 0, sizeof (context));
                    635: 
                    636:   return (status);
                    637: }
                    638: 
                    639: int R_SealPEMBlock 
                    640:   (encryptedContent, encryptedContentLen, encryptedKey, encryptedKeyLen,
                    641:    encryptedSignature, encryptedSignatureLen, iv, content, contentLen,
                    642:    digestAlgorithm, publicKey, privateKey, randomStruct)
                    643: unsigned char *encryptedContent;              /* encoded, encrypted content */
                    644: unsigned int *encryptedContentLen;                                /* length */
                    645: unsigned char *encryptedKey;                      /* encoded, encrypted key */
                    646: unsigned int *encryptedKeyLen;                                    /* length */
                    647: unsigned char *encryptedSignature;          /* encoded, encrypted signature */
                    648: unsigned int *encryptedSignatureLen;                              /* length */
                    649: unsigned char iv[8];                           /* DES initialization vector */
                    650: unsigned char *content;                                          /* content */
                    651: unsigned int contentLen;                               /* length of content */
                    652: int digestAlgorithm;                           /* message-digest algorithms */
                    653: R_RSA_PUBLIC_KEY *publicKey;                  /* recipient's RSA public key */
                    654: R_RSA_PRIVATE_KEY *privateKey;                  /* signer's RSA private key */
                    655: R_RANDOM_STRUCT *randomStruct;                          /* random structure */
                    656: {
                    657:   R_ENVELOPE_CTX context;
                    658:   R_RSA_PUBLIC_KEY *publicKeys[1];
                    659:   int status;
                    660:   unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN],
                    661:     signature[MAX_SIGNATURE_LEN], *encryptedKeys[1];
                    662:   unsigned int signatureLen, encryptedKeyBlockLen;
                    663:   
                    664:   do {
                    665:     if ((status = R_SignBlock
                    666:          (signature, &signatureLen, content, contentLen, digestAlgorithm,
                    667:           privateKey)) != 0)
                    668:       break;
                    669: 
                    670:     publicKeys[0] = publicKey;
                    671:     encryptedKeys[0] = encryptedKeyBlock;
                    672:     if ((status = R_SealInit
                    673:          (&context, encryptedKeys, &encryptedKeyBlockLen, iv, 1, publicKeys,
                    674:           EA_DES_CBC, randomStruct)) != 0)
                    675:       break;
                    676: 
                    677:     R_EncodePEMBlock 
                    678:       (encryptedKey, encryptedKeyLen, encryptedKeyBlock,
                    679:        encryptedKeyBlockLen);
                    680: 
                    681:     EncryptPEMUpdateFinal
                    682:       (&context, encryptedContent, encryptedContentLen, content,
                    683:        contentLen);
                    684:     
                    685:     EncryptPEMUpdateFinal
                    686:       (&context, encryptedSignature, encryptedSignatureLen, signature,
                    687:        signatureLen);
                    688:   } while (0);
                    689:   
                    690:   /* Zeroize sensitive information.
                    691:    */
                    692:   R_memset ((POINTER)&context, 0, sizeof (context));
                    693:   R_memset ((POINTER)signature, 0, sizeof (signature));
                    694: 
                    695:   return (status);
                    696: }
                    697: 
                    698: int R_OpenPEMBlock
                    699:   (content, contentLen, encryptedContent, encryptedContentLen, encryptedKey,
                    700:    encryptedKeyLen, encryptedSignature, encryptedSignatureLen,
                    701:    iv, digestAlgorithm, privateKey, publicKey)
                    702: unsigned char *content;                                          /* content */
                    703: unsigned int *contentLen;                              /* length of content */
                    704: unsigned char *encryptedContent;              /* encoded, encrypted content */
                    705: unsigned int encryptedContentLen;                                 /* length */
                    706: unsigned char *encryptedKey;                      /* encoded, encrypted key */
                    707: unsigned int encryptedKeyLen;                                     /* length */
                    708: unsigned char *encryptedSignature;          /* encoded, encrypted signature */
                    709: unsigned int encryptedSignatureLen;                               /* length */
                    710: unsigned char iv[8];                           /* DES initialization vector */
                    711: int digestAlgorithm;                           /* message-digest algorithms */
                    712: R_RSA_PRIVATE_KEY *privateKey;               /* recipient's RSA private key */
                    713: R_RSA_PUBLIC_KEY *publicKey;                     /* signer's RSA public key */
                    714: {
                    715:   R_ENVELOPE_CTX context;
                    716:   int status;
                    717:   unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN],
                    718:     signature[MAX_SIGNATURE_LEN];
                    719:   unsigned int encryptedKeyBlockLen, signatureLen;
                    720:   
                    721:   if (encryptedKeyLen > MAX_PEM_ENCRYPTED_KEY_LEN)
                    722:     return (RE_KEY_ENCODING);
                    723:   
                    724:   if (encryptedSignatureLen > MAX_PEM_ENCRYPTED_SIGNATURE_LEN)
                    725:     return (RE_SIGNATURE_ENCODING);
                    726:   
                    727:   do {
                    728:     if (R_DecodePEMBlock 
                    729:         (encryptedKeyBlock, &encryptedKeyBlockLen, encryptedKey,
                    730:          encryptedKeyLen) != 0) {
                    731:       status = RE_KEY_ENCODING;
                    732:       break;
                    733:     }
                    734: 
                    735:     if ((status = R_OpenInit
                    736:          (&context, EA_DES_CBC, encryptedKeyBlock, encryptedKeyBlockLen,
                    737:           iv, privateKey)) != 0)
                    738:       break;
                    739: 
                    740:     if ((status = DecryptPEMUpdateFinal
                    741:          (&context, content, contentLen, encryptedContent,
                    742:           encryptedContentLen)) != 0) {
                    743:       if ((status == RE_LEN || status == RE_ENCODING))
                    744:         status = RE_CONTENT_ENCODING;
                    745:       else
                    746:         status = RE_KEY;
                    747:       break;
                    748:     }
                    749:     
                    750:     if (status = DecryptPEMUpdateFinal
                    751:         (&context, signature, &signatureLen, encryptedSignature,
                    752:          encryptedSignatureLen)) {
                    753:       if ((status == RE_LEN || status == RE_ENCODING))
                    754:         status = RE_SIGNATURE_ENCODING;
                    755:       else
                    756:         status = RE_KEY;
                    757:       break;
                    758:     }
                    759: 
                    760:     if ((status = R_VerifyBlockSignature
                    761:          (content, *contentLen, signature, signatureLen, digestAlgorithm,
                    762:           publicKey)) != 0)
                    763:       break;
                    764:   } while (0);
                    765:   
                    766:   /* Zeroize sensitive information.
                    767:    */
                    768:   R_memset ((POINTER)&context, 0, sizeof (context));
                    769:   R_memset ((POINTER)signature, 0, sizeof (signature));
                    770: 
                    771:   return (status);
                    772: }
                    773: 
                    774: int R_DigestBlock (digest, digestLen, block, blockLen, digestAlgorithm)
                    775: unsigned char *digest;                                    /* message digest */
                    776: unsigned int *digestLen;                        /* length of message digest */
                    777: unsigned char *block;                                              /* block */
                    778: unsigned int blockLen;                                   /* length of block */
                    779: int digestAlgorithm;                            /* message-digest algorithm */
                    780: {
                    781:   R_DIGEST_CTX context;
                    782:   int status;
                    783: 
                    784:   do {
                    785:     if ((status = R_DigestInit (&context, digestAlgorithm)) != 0)
                    786:       break;
                    787:     if ((status = R_DigestUpdate (&context, block, blockLen)) != 0)
                    788:       break;
                    789:     if ((status = R_DigestFinal (&context, digest, digestLen)) != 0)
                    790:       break;
                    791:   } while (0);
                    792: 
                    793:   /* Zeroize sensitive information. */
                    794:   R_memset ((POINTER)&context, 0, sizeof (context));
                    795: 
                    796:   return (status);
                    797: }
                    798: 
                    799: /* Assumes digestAlgorithm is DA_MD2 or DA_MD5 and digest length is 16.
                    800:  */
                    801: static void R_EncodeDigestInfo (digestInfo, digestAlgorithm, digest)
                    802: unsigned char *digestInfo;                           /* DigestInfo encoding */
                    803: int digestAlgorithm;                            /* message-digest algorithm */
                    804: unsigned char *digest;                                    /* message digest */
                    805: {
                    806:   R_memcpy 
                    807:     ((POINTER)digestInfo, (POINTER)DIGEST_INFO_A, DIGEST_INFO_A_LEN);
                    808:   
                    809:   digestInfo[DIGEST_INFO_A_LEN] =
                    810:     (digestAlgorithm == DA_MD2) ? (unsigned char)2 : (unsigned char)5;
                    811: 
                    812:   R_memcpy 
                    813:     ((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1], (POINTER)DIGEST_INFO_B,
                    814:      DIGEST_INFO_B_LEN);
                    815:   
                    816:   R_memcpy 
                    817:     ((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN],
                    818:      (POINTER)digest, 16);
                    819: }
                    820: 
                    821: /* Call SealUpdate and SealFinal on the input and ASCII recode.
                    822:  */
                    823: static void EncryptPEMUpdateFinal
                    824:   (context, output, outputLen, input, inputLen)
                    825: R_ENVELOPE_CTX *context;
                    826: unsigned char *output;                          /* encrypted, encoded block */
                    827: unsigned int *outputLen;                                /* length of output */
                    828: unsigned char *input;                                   /* block to encrypt */
                    829: unsigned int inputLen;                                            /* length */
                    830: {
                    831:   unsigned char encryptedPart[24];
                    832:   unsigned int i, lastPartLen, tempLen, len;
                    833: 
                    834:   /* Choose a buffer size of 24 bytes to hold the temporary encrypted output
                    835:        which will be encoded.
                    836:      Encrypt and encode as many 24-byte blocks as possible.
                    837:    */
                    838:   for (i = 0; i < inputLen / 24; ++i) {
                    839:     /* Assume part out length will equal part in length since it is
                    840:          a multiple of 8.  Also assume no error output. */
                    841:     R_SealUpdate (context, encryptedPart, &tempLen, &input[24*i], 24);
                    842: 
                    843:     /* len is always 32 */
                    844:     R_EncodePEMBlock (&output[32*i], &tempLen, encryptedPart, 24);
                    845:   }
                    846:   
                    847:   /* Encrypt the last part into encryptedPart.
                    848:    */  
                    849:   R_SealUpdate
                    850:     (context, encryptedPart, &lastPartLen, &input[24*i], inputLen - 24*i);
                    851:   R_SealFinal (context, encryptedPart + lastPartLen, &len);
                    852:   lastPartLen += len;
                    853: 
                    854:   R_EncodePEMBlock (&output[32*i], &len, encryptedPart, lastPartLen);
                    855:   *outputLen = 32*i + len;
                    856: 
                    857:   /* Zeroize sensitive information.
                    858:    */
                    859:   R_memset ((POINTER)encryptedPart, 0, sizeof (encryptedPart));
                    860: }
                    861: 
                    862: static int DecryptPEMUpdateFinal (context, output, outputLen, input, inputLen)
                    863: R_ENVELOPE_CTX *context;
                    864: unsigned char *output;                          /* decoded, decrypted block */
                    865: unsigned int *outputLen;                                /* length of output */
                    866: unsigned char *input;                           /* encrypted, encoded block */
                    867: unsigned int inputLen;                                            /* length */
                    868: {
                    869:   int status;
                    870:   unsigned char encryptedPart[24];
                    871:   unsigned int i, len;
                    872:   
                    873:   do {
                    874:     /* Choose a buffer size of 24 bytes to hold the temporary decoded output
                    875:          which will be decrypted.
                    876:        Decode and decrypt as many 32-byte input blocks as possible.
                    877:      */
                    878:     *outputLen = 0;
                    879:     for (i = 0; i < inputLen/32; i++) {
                    880:       /* len is always 24 */
                    881:       if ((status = R_DecodePEMBlock
                    882:            (encryptedPart, &len, &input[32*i], 32)) != 0)
                    883:         break;
                    884: 
                    885:       /* Excpect no error return */
                    886:       R_OpenUpdate (context, output, &len, encryptedPart, 24);
                    887:       output += len;
                    888:       *outputLen += len;
                    889:     }
                    890:     if (status)
                    891:       break;
                    892: 
                    893:     /* Decode the last part */  
                    894:     if ((status = R_DecodePEMBlock
                    895:          (encryptedPart, &len, &input[32*i], inputLen - 32*i)) != 0)
                    896:       break;
                    897: 
                    898:     /* Decrypt the last part.
                    899:      */
                    900:     R_OpenUpdate (context, output, &len, encryptedPart, len);
                    901:     output += len;
                    902:     *outputLen += len;
                    903:     if ((status = R_OpenFinal (context, output, &len)) != 0)
                    904:       break;
                    905:     *outputLen += len;
                    906:   } while (0);
                    907: 
                    908:   /* Zeroize sensitive information.
                    909:    */
                    910:   R_memset ((POINTER)&context, 0, sizeof (context));
                    911:   R_memset ((POINTER)encryptedPart, 0, sizeof (encryptedPart));
                    912: 
                    913:   return (status);
                    914: }
                    915: 
                    916: static int CipherInit (context, encryptionAlgorithm, key, iv, encrypt)
                    917: R_ENVELOPE_CTX *context;
                    918: int encryptionAlgorithm;
                    919: unsigned char *key;                                              /* DES key */
                    920: unsigned char *iv;                             /* DES initialization vector */
                    921: int encrypt;                     /* encrypt flag (1 = encrypt, 0 = decrypt) */
                    922: {
                    923:   switch (encryptionAlgorithm) {
                    924:   case EA_DES_CBC:
                    925:     DES_CBCInit (&context->cipherContext.des, key, iv, encrypt);
                    926:     return (0);
                    927:   case EA_DESX_CBC:
                    928:     DESX_CBCInit (&context->cipherContext.desx, key, iv, encrypt);
                    929:     return (0);
                    930:   case EA_DES_EDE2_CBC:
                    931:   case EA_DES_EDE3_CBC:
                    932:     DES3_CBCInit (&context->cipherContext.des3, key, iv, encrypt);
                    933:     return (0);
                    934: 
                    935:   default:
                    936:     return (RE_ENCRYPTION_ALGORITHM);
                    937:   }
                    938: }
                    939: 
                    940: /* Assume len is a multiple of 8.
                    941:  */
                    942: static void CipherUpdate (context, output, input, len)
                    943: R_ENVELOPE_CTX *context;
                    944: unsigned char *output;                                      /* output block */
                    945: unsigned char *input;                                        /* input block */
                    946: unsigned int len;                      /* length of input and output blocks */
                    947: {
                    948:   if (context->encryptionAlgorithm == EA_DES_CBC)
                    949:     DES_CBCUpdate (&context->cipherContext.des, output, input, len);
                    950:   else if (context->encryptionAlgorithm == EA_DESX_CBC)
                    951:     DESX_CBCUpdate (&context->cipherContext.desx, output, input, len);
                    952:   else
                    953:     DES3_CBCUpdate (&context->cipherContext.des3, output, input, len);
                    954: }
                    955: 
                    956: static void CipherRestart (context)
                    957: R_ENVELOPE_CTX *context;
                    958: {
                    959:   if (context->encryptionAlgorithm == EA_DES_CBC)
                    960:     DES_CBCRestart (&context->cipherContext.des);
                    961:   else if (context->encryptionAlgorithm == EA_DESX_CBC)
                    962:     DESX_CBCRestart (&context->cipherContext.desx);
                    963:   else
                    964:     DES3_CBCRestart (&context->cipherContext.des3);
                    965: }

unix.superglobalmegacorp.com

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