|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.