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