|
|
1.1 ! root 1: /* R_ENHANC.C - cryptographic enhancements for RSAREF ! 2: */ ! 3: ! 4: /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data ! 5: Security, Inc. All rights reserved. ! 6: */ ! 7: ! 8: #include "global.h" ! 9: #include "rsaref.h" ! 10: #include "r_encode.h" ! 11: #include "r_random.h" ! 12: #include "rsa.h" ! 13: #include "md2.h" ! 14: #include "md5.h" ! 15: #include "des.h" ! 16: ! 17: /* DigestInfo encoding is DIGEST_INFO_A, then 2 or 5 (for MD2/MD5), ! 18: then DIGEST_INFO_B, then 16-byte message digest. ! 19: */ ! 20: ! 21: static char DIGEST_INFO_A[] = { ! 22: 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, ! 23: 0x0d, 0x02 ! 24: }; ! 25: #define DIGEST_INFO_A_LEN sizeof (DIGEST_INFO_A) ! 26: ! 27: static char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 }; ! 28: #define DIGEST_INFO_B_LEN sizeof (DIGEST_INFO_B) ! 29: ! 30: #define DIGEST_INFO_LEN (DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN + 16) ! 31: ! 32: static unsigned char *PADDING[] = { ! 33: (unsigned char *)"", (unsigned char *)"\001", (unsigned char *)"\002\002", ! 34: (unsigned char *)"\003\003\003", (unsigned char *)"\004\004\004\004", ! 35: (unsigned char *)"\005\005\005\005\005", ! 36: (unsigned char *)"\006\006\006\006\006\006", ! 37: (unsigned char *)"\007\007\007\007\007\007\007", ! 38: (unsigned char *)"\010\010\010\010\010\010\010\010" ! 39: }; ! 40: ! 41: #define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN ! 42: ! 43: static int R_SignBlock PROTO_LIST ! 44: ((unsigned char *, unsigned int *, unsigned char *, unsigned int, int, ! 45: R_RSA_PRIVATE_KEY *)); ! 46: static void R_EncodeDigestInfo PROTO_LIST ! 47: ((unsigned char *, int, unsigned char *)); ! 48: static void R_EncryptPEMBlock PROTO_LIST ! 49: ((unsigned char *, unsigned int *, unsigned char *, unsigned int, ! 50: unsigned char [8], unsigned char [8])); ! 51: static int R_DecryptPEMBlock PROTO_LIST ! 52: ((unsigned char *, unsigned int *, unsigned char *, unsigned int, ! 53: unsigned char [8], unsigned char [8])); ! 54: ! 55: int R_SignPEMBlock ! 56: (encodedContent, encodedContentLen, encodedSignature, encodedSignatureLen, ! 57: content, contentLen, recode, digestAlgorithm, privateKey) ! 58: unsigned char *encodedContent; /* encoded content */ ! 59: unsigned int *encodedContentLen; /* length of encoded content */ ! 60: unsigned char *encodedSignature; /* encoded signature */ ! 61: unsigned int *encodedSignatureLen; /* length of encoded signature */ ! 62: unsigned char *content; /* content */ ! 63: unsigned int contentLen; /* length of content */ ! 64: int recode; /* recoding flag */ ! 65: int digestAlgorithm; /* message-digest algorithm */ ! 66: R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ ! 67: { ! 68: int status; ! 69: unsigned char signature[MAX_SIGNATURE_LEN]; ! 70: unsigned int signatureLen; ! 71: ! 72: if (status = R_SignBlock ! 73: (signature, &signatureLen, content, contentLen, digestAlgorithm, ! 74: privateKey)) ! 75: return (status); ! 76: ! 77: R_EncodePEMBlock ! 78: (encodedSignature, encodedSignatureLen, signature, signatureLen); ! 79: ! 80: if (recode) ! 81: R_EncodePEMBlock ! 82: (encodedContent, encodedContentLen, content, contentLen); ! 83: ! 84: return (0); ! 85: } ! 86: ! 87: int R_VerifyPEMSignature ! 88: (content, contentLen, encodedContent, encodedContentLen, encodedSignature, ! 89: encodedSignatureLen, recode, digestAlgorithm, publicKey) ! 90: unsigned char *content; /* content */ ! 91: unsigned int *contentLen; /* length of content */ ! 92: unsigned char *encodedContent; /* (possibly) encoded content */ ! 93: unsigned int encodedContentLen; /* length of encoded content */ ! 94: unsigned char *encodedSignature; /* encoded signature */ ! 95: unsigned int encodedSignatureLen; /* length of encoded signature */ ! 96: int recode; /* recoding flag */ ! 97: int digestAlgorithm; /* message-digest algorithm */ ! 98: R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ ! 99: { ! 100: int status; ! 101: unsigned char signature[MAX_SIGNATURE_LEN]; ! 102: unsigned int signatureLen; ! 103: ! 104: if (encodedSignatureLen > MAX_PEM_SIGNATURE_LEN) ! 105: return (RE_SIGNATURE_ENCODING); ! 106: ! 107: if (recode) { ! 108: if (status = R_DecodePEMBlock ! 109: (content, contentLen, encodedContent, encodedContentLen)) ! 110: return (RE_CONTENT_ENCODING); ! 111: } ! 112: else { ! 113: content = encodedContent; ! 114: *contentLen = encodedContentLen; ! 115: } ! 116: ! 117: if (status = R_DecodePEMBlock ! 118: (signature, &signatureLen, encodedSignature, encodedSignatureLen)) ! 119: return (RE_SIGNATURE_ENCODING); ! 120: ! 121: return (R_VerifyBlockSignature ! 122: (content, *contentLen, signature, signatureLen, digestAlgorithm, ! 123: publicKey)); ! 124: } ! 125: ! 126: int R_VerifyBlockSignature ! 127: (block, blockLen, signature, signatureLen, digestAlgorithm, publicKey) ! 128: unsigned char *block; /* block */ ! 129: unsigned int blockLen; /* length of block */ ! 130: unsigned char *signature; /* signature */ ! 131: unsigned int signatureLen; /* length of signature */ ! 132: int digestAlgorithm; /* message-digest algorithm */ ! 133: R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ ! 134: { ! 135: int status; ! 136: unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN], ! 137: originalDigestInfo[MAX_SIGNATURE_LEN]; ! 138: unsigned int digestLen, originalDigestInfoLen; ! 139: ! 140: if (signatureLen > MAX_SIGNATURE_LEN) ! 141: return (RE_SIGNATURE); ! 142: ! 143: do { ! 144: if (status = R_DigestBlock ! 145: (digest, &digestLen, block, blockLen, digestAlgorithm)) ! 146: break; ! 147: ! 148: R_EncodeDigestInfo (digestInfo, digestAlgorithm, digest); ! 149: ! 150: if (status = RSAPublicDecrypt ! 151: (originalDigestInfo, &originalDigestInfoLen, signature, signatureLen, ! 152: publicKey)) { ! 153: status = RE_PUBLIC_KEY; ! 154: break; ! 155: } ! 156: ! 157: if ((originalDigestInfoLen != DIGEST_INFO_LEN) || ! 158: (R_memcmp ! 159: ((POINTER)originalDigestInfo, (POINTER)digestInfo, ! 160: DIGEST_INFO_LEN))) { ! 161: status = RE_SIGNATURE; ! 162: break; ! 163: } ! 164: ! 165: } while (0); ! 166: ! 167: /* Zeroize potentially sensitive information. ! 168: */ ! 169: R_memset ((POINTER)digest, 0, sizeof (digest)); ! 170: R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo)); ! 171: R_memset ((POINTER)originalDigestInfo, 0, sizeof (originalDigestInfo)); ! 172: ! 173: return (status); ! 174: } ! 175: ! 176: int R_SealPEMBlock ! 177: (encryptedContent, encryptedContentLen, encryptedKey, encryptedKeyLen, ! 178: encryptedSignature, encryptedSignatureLen, iv, content, contentLen, ! 179: digestAlgorithm, publicKey, privateKey, randomStruct) ! 180: unsigned char *encryptedContent; /* encoded, encrypted content */ ! 181: unsigned int *encryptedContentLen; /* length */ ! 182: unsigned char *encryptedKey; /* encoded, encrypted key */ ! 183: unsigned int *encryptedKeyLen; /* length */ ! 184: unsigned char *encryptedSignature; /* encoded, encrypted signature */ ! 185: unsigned int *encryptedSignatureLen; /* length */ ! 186: unsigned char iv[8]; /* DES initializing vector */ ! 187: unsigned char *content; /* content */ ! 188: unsigned int contentLen; /* length of content */ ! 189: int digestAlgorithm; /* message-digest algorithm */ ! 190: R_RSA_PUBLIC_KEY *publicKey; /* recipient's RSA public key */ ! 191: R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ ! 192: R_RANDOM_STRUCT *randomStruct; /* random structure */ ! 193: { ! 194: int status; ! 195: unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN], key[8], ! 196: signature[MAX_SIGNATURE_LEN]; ! 197: unsigned int encryptedKeyBlockLen, signatureLen; ! 198: ! 199: do { ! 200: if (status = R_SignBlock ! 201: (signature, &signatureLen, content, contentLen, digestAlgorithm, ! 202: privateKey)) ! 203: break; ! 204: ! 205: if ((status = R_GenerateBytes (key, 8, randomStruct)) || ! 206: (status = R_GenerateBytes (iv, 8, randomStruct))) ! 207: break; ! 208: ! 209: R_EncryptPEMBlock ! 210: (encryptedContent, encryptedContentLen, content, contentLen, key, iv); ! 211: ! 212: if (status = RSAPublicEncrypt ! 213: (encryptedKeyBlock, &encryptedKeyBlockLen, key, 8, publicKey, ! 214: randomStruct)) { ! 215: status = RE_PUBLIC_KEY; ! 216: break; ! 217: } ! 218: ! 219: R_EncodePEMBlock ! 220: (encryptedKey, encryptedKeyLen, encryptedKeyBlock, ! 221: encryptedKeyBlockLen); ! 222: ! 223: R_EncryptPEMBlock ! 224: (encryptedSignature, encryptedSignatureLen, signature, signatureLen, ! 225: key, iv); ! 226: ! 227: } while (0); ! 228: ! 229: /* Zeroize sensitive information. ! 230: */ ! 231: R_memset ((POINTER)key, 0, sizeof (key)); ! 232: R_memset ((POINTER)signature, 0, sizeof (signature)); ! 233: ! 234: return (status); ! 235: } ! 236: ! 237: int R_OpenPEMBlock ! 238: (content, contentLen, encryptedContent, encryptedContentLen, encryptedKey, ! 239: encryptedKeyLen, encryptedSignature, encryptedSignatureLen, ! 240: iv, digestAlgorithm, privateKey, publicKey) ! 241: unsigned char *content; /* content */ ! 242: unsigned int *contentLen; /* length of content */ ! 243: unsigned char *encryptedContent; /* encoded, encrypted content */ ! 244: unsigned int encryptedContentLen; /* length */ ! 245: unsigned char *encryptedKey; /* encoded, encrypted key */ ! 246: unsigned int encryptedKeyLen; /* length */ ! 247: unsigned char *encryptedSignature; /* encoded, encrypted signature */ ! 248: unsigned int encryptedSignatureLen; /* length */ ! 249: unsigned char iv[8]; /* DES initializing vector */ ! 250: int digestAlgorithm; /* message-digest algorithm */ ! 251: R_RSA_PRIVATE_KEY *privateKey; /* recipient's RSA private key */ ! 252: R_RSA_PUBLIC_KEY *publicKey; /* signer's RSA public key */ ! 253: { ! 254: int status; ! 255: unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN], ! 256: key[MAX_ENCRYPTED_KEY_LEN], signature[MAX_SIGNATURE_LEN]; ! 257: unsigned int encryptedKeyBlockLen, keyLen, signatureLen; ! 258: ! 259: if (encryptedKeyLen > MAX_PEM_ENCRYPTED_KEY_LEN) ! 260: return (RE_KEY_ENCODING); ! 261: ! 262: if (encryptedSignatureLen > MAX_PEM_ENCRYPTED_SIGNATURE_LEN) ! 263: return (RE_SIGNATURE_ENCODING); ! 264: ! 265: do { ! 266: if (status = R_DecodePEMBlock ! 267: (encryptedKeyBlock, &encryptedKeyBlockLen, encryptedKey, ! 268: encryptedKeyLen)) { ! 269: status = RE_KEY_ENCODING; ! 270: break; ! 271: } ! 272: ! 273: if (status = RSAPrivateDecrypt ! 274: (key, &keyLen, encryptedKeyBlock, encryptedKeyBlockLen, privateKey)) { ! 275: status = RE_PRIVATE_KEY; ! 276: break; ! 277: } ! 278: ! 279: if (keyLen != 8) { ! 280: status = RE_PRIVATE_KEY; ! 281: break; ! 282: } ! 283: ! 284: if (status = R_DecryptPEMBlock ! 285: (content, contentLen, encryptedContent, encryptedContentLen, key, ! 286: iv)) { ! 287: if ((status == RE_LEN || status == RE_ENCODING)) ! 288: status = RE_CONTENT_ENCODING; ! 289: else ! 290: status = RE_KEY; ! 291: break; ! 292: } ! 293: ! 294: if (status = R_DecryptPEMBlock ! 295: (signature, &signatureLen, encryptedSignature, encryptedSignatureLen, ! 296: key, iv)) { ! 297: if ((status == RE_LEN || status == RE_ENCODING)) ! 298: status = RE_SIGNATURE_ENCODING; ! 299: else ! 300: status = RE_KEY; ! 301: } ! 302: ! 303: if (status = R_VerifyBlockSignature ! 304: (content, *contentLen, signature, signatureLen, digestAlgorithm, ! 305: publicKey)) ! 306: break; ! 307: ! 308: } while (0); ! 309: ! 310: /* Zeroize sensitive information. ! 311: */ ! 312: R_memset ((POINTER)key, 0, sizeof (key)); ! 313: R_memset ((POINTER)signature, 0, sizeof (signature)); ! 314: ! 315: return (status); ! 316: } ! 317: ! 318: static int R_SignBlock ! 319: (signature, signatureLen, block, blockLen, digestAlgorithm, privateKey) ! 320: unsigned char *signature; /* signature */ ! 321: unsigned int *signatureLen; /* length of signature */ ! 322: unsigned char *block; /* block */ ! 323: unsigned int blockLen; /* length of block */ ! 324: int digestAlgorithm; /* message-digest algorithm */ ! 325: R_RSA_PRIVATE_KEY *privateKey; /* signer's RSA private key */ ! 326: { ! 327: int status; ! 328: unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN]; ! 329: unsigned int digestLen; ! 330: ! 331: do { ! 332: if (status = R_DigestBlock ! 333: (digest, &digestLen, block, blockLen, digestAlgorithm)) ! 334: break; ! 335: ! 336: R_EncodeDigestInfo (digestInfo, digestAlgorithm, digest); ! 337: ! 338: if (status = RSAPrivateEncrypt ! 339: (signature, signatureLen, digestInfo, DIGEST_INFO_LEN, privateKey)) { ! 340: status = RE_PRIVATE_KEY; ! 341: break; ! 342: } ! 343: ! 344: } while (0); ! 345: ! 346: /* Zeroize potentially sensitive information. ! 347: */ ! 348: R_memset ((POINTER)digest, 0, sizeof (digest)); ! 349: R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo)); ! 350: ! 351: return (status); ! 352: } ! 353: ! 354: int R_DigestBlock (digest, digestLen, block, blockLen, digestAlgorithm) ! 355: unsigned char *digest; /* message digest */ ! 356: unsigned int *digestLen; /* length of message digest */ ! 357: unsigned char *block; /* block */ ! 358: unsigned int blockLen; /* length of block */ ! 359: int digestAlgorithm; /* message-digest algorithm */ ! 360: { ! 361: MD2_CTX md2Context; ! 362: MD5_CTX md5Context; ! 363: int status; ! 364: ! 365: status = 0; ! 366: ! 367: switch (digestAlgorithm) { ! 368: case DA_MD2: ! 369: MD2Init (&md2Context); ! 370: MD2Update (&md2Context, block, blockLen); ! 371: MD2Final (digest, &md2Context); ! 372: *digestLen = 16; ! 373: break; ! 374: ! 375: case DA_MD5: ! 376: MD5Init (&md5Context); ! 377: MD5Update (&md5Context, block, blockLen); ! 378: MD5Final (digest, &md5Context); ! 379: *digestLen = 16; ! 380: break; ! 381: ! 382: default: ! 383: status = RE_DIGEST_ALGORITHM; ! 384: } ! 385: ! 386: return (status); ! 387: } ! 388: ! 389: /* Assumes digestAlgorithm is DA_MD2 or DA_MD5 and digest length is 16. ! 390: */ ! 391: static void R_EncodeDigestInfo (digestInfo, digestAlgorithm, digest) ! 392: unsigned char *digestInfo; /* DigestInfo encoding */ ! 393: int digestAlgorithm; /* message-digest algorithm */ ! 394: unsigned char *digest; /* message digest */ ! 395: { ! 396: R_memcpy ! 397: ((POINTER)digestInfo, (POINTER)DIGEST_INFO_A, DIGEST_INFO_A_LEN); ! 398: ! 399: digestInfo[DIGEST_INFO_A_LEN] = ! 400: (digestAlgorithm == DA_MD2) ? (unsigned char)2 : (unsigned char)5; ! 401: ! 402: R_memcpy ! 403: ((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1], (POINTER)DIGEST_INFO_B, ! 404: DIGEST_INFO_B_LEN); ! 405: ! 406: R_memcpy ! 407: ((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN], ! 408: (POINTER)digest, 16); ! 409: } ! 410: ! 411: static void R_EncryptPEMBlock ! 412: (encryptedBlock, encryptedBlockLen, block, blockLen, key, iv) ! 413: unsigned char *encryptedBlock; /* encrypted, encoded block */ ! 414: unsigned int *encryptedBlockLen; /* length */ ! 415: unsigned char *block; /* block */ ! 416: unsigned int blockLen; /* length of block */ ! 417: unsigned char key[8]; /* DES key */ ! 418: unsigned char iv[8]; /* DES initialization vector */ ! 419: { ! 420: DES_CBC_CTX context; ! 421: unsigned char encryptedPart[24], lastPart[24]; ! 422: unsigned int i, lastPartLen, len, padLen; ! 423: ! 424: DES_CBCInit (&context, key, iv, 1); ! 425: ! 426: for (i = 0; i < blockLen/24; i++) { ! 427: DES_CBCUpdate (&context, encryptedPart, &block[24*i], 24); ! 428: /* len is always 32 */ ! 429: R_EncodePEMBlock (&encryptedBlock[32*i], &len, encryptedPart, 24); ! 430: } ! 431: ! 432: padLen = 8 - (blockLen % 8); ! 433: lastPartLen = blockLen - 24*i + padLen; ! 434: R_memcpy ((POINTER)lastPart, (POINTER)&block[24*i], lastPartLen - padLen); ! 435: R_memcpy ! 436: ((POINTER)&lastPart[lastPartLen - padLen], PADDING[padLen], padLen); ! 437: DES_CBCUpdate (&context, encryptedPart, lastPart, lastPartLen); ! 438: R_EncodePEMBlock ! 439: (&encryptedBlock[32*i], &len, encryptedPart, lastPartLen); ! 440: *encryptedBlockLen = 32*i + len; ! 441: ! 442: DES_CBCFinal (&context); ! 443: ! 444: /* Zeroize sensitive information. ! 445: */ ! 446: R_memset ((POINTER)lastPart, 0, sizeof (lastPart)); ! 447: } ! 448: ! 449: static int R_DecryptPEMBlock ! 450: (block, blockLen, encryptedBlock, encryptedBlockLen, key, iv) ! 451: unsigned char *block; /* block */ ! 452: unsigned int *blockLen; /* length of block */ ! 453: unsigned char *encryptedBlock; /* encrypted, encoded block */ ! 454: unsigned int encryptedBlockLen; /* length */ ! 455: unsigned char key[8]; /* DES key */ ! 456: unsigned char iv[8]; /* DES initialization vector */ ! 457: { ! 458: DES_CBC_CTX context; ! 459: int status; ! 460: unsigned char encryptedPart[24], lastPart[24]; ! 461: unsigned int i, lastPartLen, len, padLen; ! 462: ! 463: if (encryptedBlockLen < 1) ! 464: return (RE_LEN); ! 465: ! 466: DES_CBCInit (&context, key, iv, 0); ! 467: ! 468: status = 0; ! 469: ! 470: do { ! 471: for (i = 0; i < (encryptedBlockLen-1)/32; i++) { ! 472: /* len is always 24 */ ! 473: if (status = R_DecodePEMBlock ! 474: (encryptedPart, &len, &encryptedBlock[32*i], 32)) ! 475: break; ! 476: DES_CBCUpdate (&context, &block[24*i], encryptedPart, 24); ! 477: } ! 478: if (status) ! 479: break; ! 480: ! 481: len = encryptedBlockLen - 32*i; ! 482: if (status = R_DecodePEMBlock ! 483: (encryptedPart, &lastPartLen, &encryptedBlock[32*i], len)) ! 484: break; ! 485: ! 486: if (lastPartLen % 8) { ! 487: status = RE_DATA; ! 488: break; ! 489: } ! 490: ! 491: DES_CBCUpdate (&context, lastPart, encryptedPart, lastPartLen); ! 492: ! 493: padLen = lastPart[lastPartLen - 1]; ! 494: if (padLen > 8) { ! 495: status = RE_DATA; ! 496: break; ! 497: } ! 498: if (R_memcmp ! 499: ((POINTER)&lastPart[lastPartLen - padLen], PADDING[padLen], padLen)) { ! 500: status = RE_DATA; ! 501: break; ! 502: } ! 503: ! 504: R_memcpy ((POINTER)&block[24*i], (POINTER)lastPart, lastPartLen - padLen); ! 505: *blockLen = 24*i + lastPartLen - padLen; ! 506: ! 507: } while (0); ! 508: ! 509: DES_CBCFinal (&context); ! 510: ! 511: /* Zeroize sensitive information. ! 512: */ ! 513: R_memset ((POINTER)lastPart, 0, sizeof (lastPart)); ! 514: ! 515: return (status); ! 516: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.