Annotation of rsaref/source/r_enhanc.c, revision 1.1.1.2

1.1       root        1: /* R_ENHANC.C - cryptographic enhancements for RSAREF
                      2:  */
                      3: 
1.1.1.2 ! root        4: /* Copyright (C) RSA Laboratories, a division of RSA Data Security,
        !             5:      Inc., created 1991. All rights reserved.
1.1       root        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: 
1.1.1.2 ! root       17: static unsigned char DIGEST_INFO_A[] = {
1.1       root       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: 
1.1.1.2 ! root       23: static unsigned char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 };
1.1       root       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 *));
1.1.1.2 ! root       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: }
1.1       root      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:   
1.1.1.2 ! root      530:   if ((status = R_SignBlock
        !           531:        (signature, &signatureLen, content, contentLen, digestAlgorithm,
        !           532:         privateKey)) != 0)
1.1       root      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: 
1.1.1.2 ! root      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: 
1.1       root      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) {
1.1.1.2 ! root      593:     if (R_DecodePEMBlock
1.1       root      594:         (content, contentLen, encodedContent, encodedContentLen))
                    595:       return (RE_CONTENT_ENCODING);
                    596:   }
                    597:   else {
                    598:     content = encodedContent;
                    599:     *contentLen = encodedContentLen;
                    600:   }
                    601:     
1.1.1.2 ! root      602:   if (R_DecodePEMBlock
1.1       root      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: {
1.1.1.2 ! root      620:   R_SIGNATURE_CTX context;
1.1       root      621:   int status;
1.1.1.2 ! root      622: 
1.1       root      623:   do {
1.1.1.2 ! root      624:     if ((status = R_VerifyInit (&context, digestAlgorithm)) != 0)
1.1       root      625:       break;
1.1.1.2 ! root      626:     if ((status = R_VerifyUpdate (&context, block, blockLen)) != 0)
1.1       root      627:       break;
1.1.1.2 ! root      628:     if ((status = R_VerifyFinal (&context, signature, signatureLen, publicKey))
        !           629:         != 0)
1.1       root      630:       break;
                    631:   } while (0);
1.1.1.2 ! root      632: 
        !           633:   /* Zeroize sensitive information. */
        !           634:   R_memset ((POINTER)&context, 0, sizeof (context));
1.1       root      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 */
1.1.1.2 ! root      649: unsigned char iv[8];                           /* DES initialization vector */
1.1       root      650: unsigned char *content;                                          /* content */
                    651: unsigned int contentLen;                               /* length of content */
1.1.1.2 ! root      652: int digestAlgorithm;                           /* message-digest algorithms */
1.1       root      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: {
1.1.1.2 ! root      657:   R_ENVELOPE_CTX context;
        !           658:   R_RSA_PUBLIC_KEY *publicKeys[1];
1.1       root      659:   int status;
1.1.1.2 ! root      660:   unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN],
        !           661:     signature[MAX_SIGNATURE_LEN], *encryptedKeys[1];
        !           662:   unsigned int signatureLen, encryptedKeyBlockLen;
1.1       root      663:   
                    664:   do {
1.1.1.2 ! root      665:     if ((status = R_SignBlock
        !           666:          (signature, &signatureLen, content, contentLen, digestAlgorithm,
        !           667:           privateKey)) != 0)
1.1       root      668:       break;
                    669: 
1.1.1.2 ! root      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)
1.1       root      675:       break;
1.1.1.2 ! root      676: 
1.1       root      677:     R_EncodePEMBlock 
                    678:       (encryptedKey, encryptedKeyLen, encryptedKeyBlock,
                    679:        encryptedKeyBlockLen);
                    680: 
1.1.1.2 ! root      681:     EncryptPEMUpdateFinal
        !           682:       (&context, encryptedContent, encryptedContentLen, content,
        !           683:        contentLen);
        !           684:     
        !           685:     EncryptPEMUpdateFinal
        !           686:       (&context, encryptedSignature, encryptedSignatureLen, signature,
        !           687:        signatureLen);
1.1       root      688:   } while (0);
                    689:   
                    690:   /* Zeroize sensitive information.
                    691:    */
1.1.1.2 ! root      692:   R_memset ((POINTER)&context, 0, sizeof (context));
1.1       root      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 */
1.1.1.2 ! root      710: unsigned char iv[8];                           /* DES initialization vector */
        !           711: int digestAlgorithm;                           /* message-digest algorithms */
1.1       root      712: R_RSA_PRIVATE_KEY *privateKey;               /* recipient's RSA private key */
                    713: R_RSA_PUBLIC_KEY *publicKey;                     /* signer's RSA public key */
                    714: {
1.1.1.2 ! root      715:   R_ENVELOPE_CTX context;
1.1       root      716:   int status;
                    717:   unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN],
1.1.1.2 ! root      718:     signature[MAX_SIGNATURE_LEN];
        !           719:   unsigned int encryptedKeyBlockLen, signatureLen;
1.1       root      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 {
1.1.1.2 ! root      728:     if (R_DecodePEMBlock 
1.1       root      729:         (encryptedKeyBlock, &encryptedKeyBlockLen, encryptedKey,
1.1.1.2 ! root      730:          encryptedKeyLen) != 0) {
1.1       root      731:       status = RE_KEY_ENCODING;
                    732:       break;
                    733:     }
                    734: 
1.1.1.2 ! root      735:     if ((status = R_OpenInit
        !           736:          (&context, EA_DES_CBC, encryptedKeyBlock, encryptedKeyBlockLen,
        !           737:           iv, privateKey)) != 0)
1.1       root      738:       break;
1.1.1.2 ! root      739: 
        !           740:     if ((status = DecryptPEMUpdateFinal
        !           741:          (&context, content, contentLen, encryptedContent,
        !           742:           encryptedContentLen)) != 0) {
1.1       root      743:       if ((status == RE_LEN || status == RE_ENCODING))
                    744:         status = RE_CONTENT_ENCODING;
                    745:       else
                    746:         status = RE_KEY;
                    747:       break;
                    748:     }
                    749:     
1.1.1.2 ! root      750:     if (status = DecryptPEMUpdateFinal
        !           751:         (&context, signature, &signatureLen, encryptedSignature,
        !           752:          encryptedSignatureLen)) {
1.1       root      753:       if ((status == RE_LEN || status == RE_ENCODING))
                    754:         status = RE_SIGNATURE_ENCODING;
                    755:       else
                    756:         status = RE_KEY;
1.1.1.2 ! root      757:       break;
1.1       root      758:     }
                    759: 
1.1.1.2 ! root      760:     if ((status = R_VerifyBlockSignature
        !           761:          (content, *contentLen, signature, signatureLen, digestAlgorithm,
        !           762:           publicKey)) != 0)
1.1       root      763:       break;
                    764:   } while (0);
                    765:   
                    766:   /* Zeroize sensitive information.
                    767:    */
1.1.1.2 ! root      768:   R_memset ((POINTER)&context, 0, sizeof (context));
1.1       root      769:   R_memset ((POINTER)signature, 0, sizeof (signature));
                    770: 
                    771:   return (status);
                    772: }
                    773: 
1.1.1.2 ! root      774: int R_DigestBlock (digest, digestLen, block, blockLen, digestAlgorithm)
        !           775: unsigned char *digest;                                    /* message digest */
        !           776: unsigned int *digestLen;                        /* length of message digest */
1.1       root      777: unsigned char *block;                                              /* block */
                    778: unsigned int blockLen;                                   /* length of block */
                    779: int digestAlgorithm;                            /* message-digest algorithm */
                    780: {
1.1.1.2 ! root      781:   R_DIGEST_CTX context;
1.1       root      782:   int status;
                    783: 
                    784:   do {
1.1.1.2 ! root      785:     if ((status = R_DigestInit (&context, digestAlgorithm)) != 0)
1.1       root      786:       break;
1.1.1.2 ! root      787:     if ((status = R_DigestUpdate (&context, block, blockLen)) != 0)
        !           788:       break;
        !           789:     if ((status = R_DigestFinal (&context, digest, digestLen)) != 0)
1.1       root      790:       break;
                    791:   } while (0);
                    792: 
1.1.1.2 ! root      793:   /* Zeroize sensitive information. */
        !           794:   R_memset ((POINTER)&context, 0, sizeof (context));
1.1       root      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: 
1.1.1.2 ! root      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 */
1.1       root      830: {
1.1.1.2 ! root      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);
1.1       root      842: 
                    843:     /* len is always 32 */
1.1.1.2 ! root      844:     R_EncodePEMBlock (&output[32*i], &tempLen, encryptedPart, 24);
1.1       root      845:   }
                    846:   
1.1.1.2 ! root      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;
1.1       root      856: 
                    857:   /* Zeroize sensitive information.
                    858:    */
1.1.1.2 ! root      859:   R_memset ((POINTER)encryptedPart, 0, sizeof (encryptedPart));
1.1       root      860: }
                    861: 
1.1.1.2 ! root      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 */
1.1       root      868: {
                    869:   int status;
1.1.1.2 ! root      870:   unsigned char encryptedPart[24];
        !           871:   unsigned int i, len;
1.1       root      872:   
                    873:   do {
1.1.1.2 ! root      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++) {
1.1       root      880:       /* len is always 24 */
1.1.1.2 ! root      881:       if ((status = R_DecodePEMBlock
        !           882:            (encryptedPart, &len, &input[32*i], 32)) != 0)
1.1       root      883:         break;
1.1.1.2 ! root      884: 
        !           885:       /* Excpect no error return */
        !           886:       R_OpenUpdate (context, output, &len, encryptedPart, 24);
        !           887:       output += len;
        !           888:       *outputLen += len;
1.1       root      889:     }
                    890:     if (status)
                    891:       break;
                    892: 
1.1.1.2 ! root      893:     /* Decode the last part */  
        !           894:     if ((status = R_DecodePEMBlock
        !           895:          (encryptedPart, &len, &input[32*i], inputLen - 32*i)) != 0)
1.1       root      896:       break;
                    897: 
1.1.1.2 ! root      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)
1.1       root      904:       break;
1.1.1.2 ! root      905:     *outputLen += len;
1.1       root      906:   } while (0);
                    907: 
                    908:   /* Zeroize sensitive information.
                    909:    */
1.1.1.2 ! root      910:   R_memset ((POINTER)&context, 0, sizeof (context));
        !           911:   R_memset ((POINTER)encryptedPart, 0, sizeof (encryptedPart));
1.1       root      912: 
                    913:   return (status);
                    914: }
1.1.1.2 ! root      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.