Annotation of pgp/rsaref/source/r_enhanc.c, revision 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.