|
|
1.1 ! root 1: /* rsaglue.c - These functions wrap and unwrap message digests (MDs) and ! 2: * data encryption keys (DEKs) in padding and RSA-encrypt them into ! 3: * multi-precision integers. This layer was introduced to allow the ! 4: * transparent use of RSAREF for the encryption (in regions where it is ! 5: * legally available - the U.S. and treaty partners), or Philip Zimmermann's ! 6: * mpi library (where permitted by patent law - outside the U.S.). ! 7: * ! 8: * These functions also hide the details of using either PKCS or PGP 2.0 ! 9: * style padding and encodings within the integers. See pgformat.doc ! 10: * for a detailed description of the formats. ! 11: */ ! 12: ! 13: #include <string.h> /* for mem*() */ ! 14: #include "mpilib.h" ! 15: #include "mpiio.h" ! 16: #include "pgp.h" ! 17: #include "rsaglue.h" ! 18: ! 19: #ifdef RSAREF /* defined (or not) in rsaglue.h */ ! 20: #include "rsaref/test/global.h" ! 21: #include "rsaref/source/rsa.h" ! 22: #include "rsaref/source/rsaref.h" ! 23: ! 24: int RSAPublicBlock(byte *dest, unsigned *destbytesptr, ! 25: byte *src, unsigned srcbytes, ! 26: R_RSA_PUBLIC_KEY *PubKey); ! 27: int RSAPrivateBlock(byte *dest, unsigned *destbytesptr, ! 28: byte *src, unsigned srcbytes, ! 29: R_RSA_PRIVATE_KEY *PrivKey); ! 30: ! 31: /* Functions to convert to and from RSAREF's bignum formats */ ! 32: ! 33: void ! 34: rsaref2reg (unitptr to, byte *from, int frombytes) ! 35: /* Convert an RSAREF-style MSB-first array of bytes to an mpi-style ! 36: * native-byte-order integer. (global_precision units long.) ! 37: */ ! 38: { ! 39: int tobytes; ! 40: ! 41: tobytes = units2bytes (global_precision); ! 42: if (tobytes > frombytes) { ! 43: memset(to, 0, tobytes - frombytes); ! 44: memcpy((byte *)to + tobytes - frombytes, from, frombytes); ! 45: } else { ! 46: memcpy((byte *)to, from + frombytes - tobytes, tobytes); ! 47: } ! 48: #ifndef HIGHFIRST ! 49: hiloswap((byte *)to, tobytes); ! 50: #endif ! 51: } /* rsaref2reg */ ! 52: ! 53: void ! 54: reg2rsaref (byte *to, int tobytes, unitptr from) ! 55: /* Convert the other way, mpi format to an array of bytes. */ ! 56: { ! 57: int frombytes; ! 58: ! 59: frombytes = units2bytes(global_precision); ! 60: ! 61: #ifdef HIGHFIRST ! 62: if (tobytes > frombytes) { ! 63: memset(to, 0, tobytes-frombytes); ! 64: memcpy(to + tobytes - frombytes, (byte *)from, frombytes); ! 65: } else { ! 66: memcpy(to, (byte *)from + frombytes - tobytes, tobytes); ! 67: } ! 68: #else ! 69: if (tobytes > frombytes) { ! 70: memcpy(to, (byte *)from, frombytes); ! 71: memset(to + frombytes, 0, tobytes-frombytes); ! 72: } else { ! 73: memcpy(to, (byte *)from, tobytes); ! 74: } ! 75: hiloswap(to, tobytes); ! 76: #endif ! 77: } /* reg2rsaref */ ! 78: ! 79: int ! 80: make_RSA_PUBLIC_KEY(R_RSA_PUBLIC_KEY *rpk, unitptr e, unitptr n) ! 81: /* Given mpi's e and n, fill in an R_RSA_PUBLIC_KEY structure. ! 82: * Returns -1 on error, 0 on success ! 83: */ ! 84: { ! 85: rpk->bits = countbits(n); ! 86: if (rpk->bits > MAX_RSA_MODULUS_BITS) ! 87: return -1; ! 88: ! 89: reg2rsaref(rpk->modulus, MAX_RSA_MODULUS_LEN, n); ! 90: reg2rsaref(rpk->exponent, MAX_RSA_MODULUS_LEN, e); ! 91: return 0; ! 92: } /* make_RSA_PUBLIC_KEY */ ! 93: ! 94: /* Returns -1 on error, 0 on success */ ! 95: int ! 96: make_RSA_PRIVATE_KEY(R_RSA_PRIVATE_KEY *rpk, unitptr e, unitptr d, unitptr p, ! 97: unitptr q, unitptr dp, unitptr dq, unitptr u, unitptr n) ! 98: /* Given a number of necessary mpi's, fill in an R_RSA_PRIVATE_KEY structure. ! 99: * Returns -1 on error, 0 on success ! 100: */ ! 101: { ! 102: rpk->bits = countbits(n); ! 103: if (rpk->bits > MAX_RSA_MODULUS_BITS || ! 104: countbits(p) > MAX_RSA_PRIME_BITS || ! 105: countbits(q) > MAX_RSA_PRIME_BITS) ! 106: return -1; ! 107: ! 108: reg2rsaref(rpk->modulus, MAX_RSA_MODULUS_LEN, n); ! 109: reg2rsaref(rpk->publicExponent, MAX_RSA_MODULUS_LEN, e); ! 110: reg2rsaref(rpk->exponent, MAX_RSA_MODULUS_LEN, d); ! 111: /* The larger prime (p) first */ ! 112: reg2rsaref(rpk->prime[0], MAX_RSA_PRIME_LEN, q); ! 113: reg2rsaref(rpk->prime[1], MAX_RSA_PRIME_LEN, p); ! 114: /* d mod (p-1) and d mod (q-1) */ ! 115: reg2rsaref(rpk->primeExponent[0], MAX_RSA_PRIME_LEN, dq); ! 116: reg2rsaref(rpk->primeExponent[1], MAX_RSA_PRIME_LEN, dp); ! 117: /* 1/q mod p */ ! 118: reg2rsaref(rpk->coefficient, MAX_RSA_PRIME_LEN, u); ! 119: return 0; ! 120: } /* make_RSA_PRIVATE_KEY */ ! 121: ! 122: #endif /* RSAREF */ ! 123: ! 124: /* These functions hide all the internal details of RSA-encrypted ! 125: * keys and digests. They owe a lot of their heritage to ! 126: * the preblock() and postunblock() routines in mpiio.c. ! 127: */ ! 128: ! 129: /* Abstract Syntax Notation One (ASN.1) Distinguished Encoding Rules (DER) ! 130: encoding for RSA/MD5, used in PKCS-format signatures. */ ! 131: static byte asn_array[] = { /* PKCS 01 block type 01 data */ ! 132: 0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, ! 133: 0x02,0x05,0x05,0x00,0x04,0x10 }; ! 134: /* This many bytes from the end, there's a zero byte */ ! 135: #define ASN_ZERO_END 3 ! 136: ! 137: int ! 138: rsa_public_encrypt(unitptr outbuf, byteptr inbuf, short bytes, ! 139: unitptr E, unitptr N) ! 140: /* Encrypt a DEK with a public key. Returns 0 on success. ! 141: * <0 means there was an error ! 142: */ ! 143: { ! 144: unit temp[MAX_UNIT_PRECISION]; ! 145: #ifdef RSAREF ! 146: R_RSA_PUBLIC_KEY PubKey; ! 147: R_RANDOM_STRUCT Random; ! 148: #endif /* RSAREF */ ! 149: unsigned int blocksize; ! 150: byte *p; ! 151: int i; /* Temporary, and holds error codes */ ! 152: ! 153: blocksize = countbytes(N) - 1; /* Bytes available for user data */ ! 154: ! 155: p = (byte *)temp; ! 156: ! 157: #ifdef RSAREF ! 158: /* Fill in the R_RSA_PUBLIC_KEY structure as needed later. */ ! 159: i = make_RSA_PUBLIC_KEY(&PubKey, E, N); ! 160: if (i < 0) ! 161: return -1; ! 162: #else /* !RSAREF */ ! 163: /* If !RSAREF, we are building the mpi in place, except for a ! 164: * possible byte-order swap to little-endian at the end. Thus, ! 165: * we need to fill the buffer with leading 0's in the unused ! 166: * most significant byte positions. ! 167: */ ! 168: for (i = units2bytes(global_precision) - blocksize; i > 0; --i) ! 169: *p++ = 0; ! 170: #endif /* !RSAREF */ ! 171: ! 172: /* Both the PKCS and PGP 2.0 key formats add a type byte, and a ! 173: * a framing byte of 0 to the user data. The remaining space ! 174: * is filled with random padding. (PKCS requires that there be ! 175: * at least 1 byte of padding.) ! 176: */ ! 177: i = blocksize - 2 - bytes; ! 178: ! 179: if (pkcs_compat) { ! 180: if (i < 1) /* Less than minimum padding? */ ! 181: return -1; ! 182: #ifndef RSAREF /* Build the packet ourselves */ ! 183: *p++ = CK_ENCRYPTED_BYTE; /* Type byte */ ! 184: while (i) /* Non-zero random padding */ ! 185: if ((*p = idearand())) ! 186: ++p, --i; ! 187: *p++ = 0; /* Framing byte */ ! 188: memcpy(p, inbuf, bytes); /* User data */ ! 189: #else /* RSAREF */ ! 190: /* The RSAREF routines have their own random number generator ! 191: * to generate random padding. The following code seeds it ! 192: * from PGP's random number generator. ! 193: */ ! 194: R_RandomInit(&Random); ! 195: for (;;) { ! 196: R_GetRandomBytesNeeded(&i, &Random); ! 197: if (i <= 0) ! 198: break; ! 199: blocksize = i > sizeof(temp) ? sizeof(temp) : i; ! 200: for (i = 0; i < blocksize; i++) ! 201: ((byte *)temp)[i] = idearand(); ! 202: R_RandomUpdate(&Random, (byte *)temp, blocksize); ! 203: } ! 204: /* Pad and encrypt */ ! 205: i = RSAPublicEncrypt((byte *)temp, &blocksize, ! 206: inbuf, bytes, &PubKey, &Random); ! 207: R_RandomFinal(&Random); /* Clean up RSAREF's RNG */ ! 208: burn(Random); /* Just to be sure */ ! 209: #endif /* RSAREF */ ! 210: } else { /* !pkcs_compat */ ! 211: if (i < 0) ! 212: return -1; ! 213: memcpy(p, inbuf, bytes); /* User data */ ! 214: p += bytes; ! 215: *p++ = 0; /* Framing byte */ ! 216: while (i) /* Non-zero random padding */ ! 217: if ((*p = idearand())) ! 218: ++p, --i; ! 219: *p = CK_ENCRYPTED_BYTE; /* Type byte */ ! 220: #ifdef RSAREF ! 221: /* Do the encryption */ ! 222: i = RSAPublicBlock((byte *)temp, &blocksize, ! 223: (byte *)temp, blocksize, &PubKey); ! 224: #endif ! 225: ! 226: } /* !pkcs_compat */ ! 227: ! 228: #ifndef RSAREF ! 229: mp_convert_order((byte *)temp); /* Convert buffer to MPI */ ! 230: i = mp_modexp(outbuf, temp, E, N); /* Do the encryption */ ! 231: #else /* RSAREF */ ! 232: rsaref2reg(outbuf, (byte *)temp, blocksize); ! 233: #endif /* RSAREF */ ! 234: ! 235: Cleanup: ! 236: mp_burn(temp); ! 237: #ifdef RSAREF ! 238: burn(PubKey); ! 239: #endif ! 240: return i < 0 ? i : 0; ! 241: } /* rsa_public_encrypt */ ! 242: ! 243: int ! 244: rsa_private_encrypt(unitptr outbuf, byteptr inbuf, short bytes, ! 245: unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N) ! 246: /* Encrypt a message digest with a private key. ! 247: * Returns <0 on error. ! 248: */ ! 249: { ! 250: unit temp[MAX_UNIT_PRECISION]; ! 251: unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION]; ! 252: #ifdef RSAREF ! 253: R_RSA_PRIVATE_KEY PrivKey; ! 254: #else ! 255: int byte_precision; ! 256: #endif ! 257: unsigned int blocksize; ! 258: byte *p; ! 259: int i; ! 260: ! 261: /* PGP doesn't store these coefficents, so we need to compute them. */ ! 262: mp_move(temp,P); ! 263: mp_dec(temp); ! 264: mp_mod(DP,D,temp); ! 265: mp_move(temp,Q); ! 266: mp_dec(temp); ! 267: mp_mod(DQ,D,temp); ! 268: ! 269: blocksize = countbytes(N) - 1; /* Space available for data */ ! 270: ! 271: p = (byte *)temp; ! 272: ! 273: #ifdef RSAREF ! 274: i = make_RSA_PRIVATE_KEY(&PrivKey, E, D, P, Q, DP, DQ, U, N); ! 275: if (i < 0) ! 276: goto Cleanup; ! 277: #else ! 278: /* If !RSAREF, we are building the mpi in place, except for a ! 279: * possible byte-order swap to little-endian at the end. Thus, ! 280: * we need to fill the buffer with leading 0's in the unused ! 281: * most significant byte positions. ! 282: */ ! 283: for (i = units2bytes(global_precision) - blocksize; i > 0; --i) ! 284: *p++ = 0; ! 285: #endif ! 286: i = blocksize - 2 - bytes; /* Padding needed */ ! 287: ! 288: if (pkcs_compat) { ! 289: #ifndef RSAREF /* Pad the packet ourselves */ ! 290: i -= sizeof(asn_array); /* Space for type encoding */ ! 291: if (i < 0) { ! 292: i = -1; /* Error code */ ! 293: goto Cleanup; ! 294: } ! 295: *p++ = MD_ENCRYPTED_BYTE; /* Type byte */ ! 296: memset(p, ~0, i); /* All 1's padding */ ! 297: p += i; ! 298: *p++ = 0; /* Zero framing byte */ ! 299: #endif /* !RSAREF */ ! 300: memcpy(p, asn_array, sizeof(asn_array)); /* ASN data */ ! 301: p += sizeof(asn_array); ! 302: memcpy(p, inbuf, bytes); /* User data */ ! 303: #ifdef RSAREF ! 304: /* Pad and encrypt */ ! 305: RSAPrivateEncrypt((byte *)temp, &blocksize, ! 306: (byte *)temp, bytes+sizeof(asn_array), ! 307: &PrivKey); ! 308: #endif ! 309: } else { /* Not pkcs_compat */ ! 310: --i; /* Space for type byte */ ! 311: if (i < 0) { ! 312: i = -1; /* Error code */ ! 313: goto Cleanup; ! 314: } ! 315: *p++ = MD5_ALGORITHM_BYTE; /* Algorithm type byte */ ! 316: memcpy(p, inbuf, bytes); /* User data */ ! 317: p += bytes; ! 318: *p++ = 0; /* Framing byte of 0 */ ! 319: memset(p, ~0, i); /* All 1's padding */ ! 320: p += i; ! 321: *p = MD_ENCRYPTED_BYTE; /* Type byte */ ! 322: ! 323: #ifdef RSAREF ! 324: /* Do the encryption */ ! 325: i = RSAPrivateBlock((byte *)temp, &blocksize, ! 326: (byte *)temp, blocksize, &PrivKey); ! 327: #endif /* RSAREF */ ! 328: ! 329: } /* !pkcs_compat */ ! 330: ! 331: #ifndef RSAREF ! 332: mp_convert_order((byte *)temp); ! 333: i = mp_modexp_crt(outbuf, temp, P, Q, DP, DQ, U); /* Encrypt */ ! 334: #else /* RSAREF */ ! 335: rsaref2reg(outbuf, (byte *)temp, blocksize); ! 336: #endif /* RSAREF */ ! 337: ! 338: Cleanup: ! 339: mp_burn(temp); ! 340: #ifdef RSAREF ! 341: memset(&PrivKey, 0, sizeof(PrivKey)); ! 342: #endif ! 343: return i < 0 ? i : 0; ! 344: } /* rsa_private_encrypt */ ! 345: ! 346: /* Remove a signature packet from an MPI */ ! 347: /* Thus, we expect constant padding and the MIC ASN sequence */ ! 348: int ! 349: rsa_public_decrypt(byteptr outbuf, unitptr inbuf, ! 350: unitptr E, unitptr N) ! 351: /* Decrypt a message digest using a public key. Returns the number of bytes ! 352: * extracted, or <0 on error. ! 353: * -1: Corrupted packet. ! 354: * -2: Unrecognized message digest algorithm. ! 355: */ ! 356: { ! 357: #ifdef RSAREF ! 358: R_RSA_PUBLIC_KEY PubKey; ! 359: #endif ! 360: unit temp[MAX_UNIT_PRECISION]; ! 361: unsigned int blocksize; ! 362: int i; ! 363: byte *front, *back; ! 364: ! 365: #ifdef RSAREF ! 366: make_RSA_PUBLIC_KEY(&PubKey, E, N); ! 367: blocksize = countbytes(inbuf); ! 368: reg2rsaref((byte *)temp, blocksize, inbuf); ! 369: RSAPublicBlock((byte *)temp, &blocksize, ! 370: (byte *)temp, blocksize, &PubKey); ! 371: ! 372: front = (byte *)temp; /* The start of the block */ ! 373: back = front + blocksize; /* The end */ ! 374: i = blocksize - countbytes(N) + 1; /* Expected leading 0's */ ! 375: #else ! 376: i = mp_modexp(temp, inbuf, E, N); ! 377: if (i < 0) { ! 378: mp_burn(temp); ! 379: return i; ! 380: } ! 381: mp_convert_order((byte *)temp); ! 382: blocksize = countbytes(N) - 1; ! 383: front = (byte *)temp; /* Points to start of block */ ! 384: i = units2bytes(global_precision); ! 385: back = front + i; /* Points to end of block */ ! 386: i -= countbytes(N) - 1; /* Expected leading 0's */ ! 387: #endif ! 388: ! 389: /* This could be stricter, but the length returned by the RSAREF code ! 390: is not documented too well. */ ! 391: if (i < 0) ! 392: goto ErrorReturn; ! 393: while (i--) /* Any excess should be 0 */ ! 394: if (*front++) ! 395: goto ErrorReturn; ! 396: /* front now points to the data */ ! 397: ! 398: /* How to distinguish old PGP from PKCS formats. ! 399: * The old PGP format ends in a trailing type byte, with ! 400: * all 1's padding before that. The PKCS format ends in ! 401: * 16 bytes of message digest, preceded by an ASN string ! 402: * which is not all 1's. ! 403: */ ! 404: if (back[-1] == MD_ENCRYPTED_BYTE && ! 405: back[-17] == 0xff && back[-18] == 0xff) { ! 406: /* Old PGP format: Padding is at the end */ ! 407: if (*--back != MD_ENCRYPTED_BYTE) ! 408: goto ErrorReturn; ! 409: if (*front++ != MD5_ALGORITHM_BYTE) { ! 410: mp_burn(temp); ! 411: return -2; ! 412: } ! 413: while (*--back == 0xff) /* Skip constant padding */ ! 414: ; ! 415: if (*back) /* It should end with a zero */ ! 416: goto ErrorReturn; ! 417: } else { ! 418: /* PKCS format: padding at the beginning */ ! 419: if (*front++ != MD_ENCRYPTED_BYTE) ! 420: goto ErrorReturn; ! 421: while (*front++ == 0xff) /* Skip constant padding */ ! 422: ; ! 423: if (front[-1]) /* First non-FF byte should be 0 */ ! 424: goto ErrorReturn; ! 425: /* Then comes the ASN header */ ! 426: if (memcmp(front, asn_array, sizeof(asn_array))) { ! 427: mp_burn(temp); ! 428: return -2; ! 429: } ! 430: front += sizeof(asn_array); ! 431: /* This is temporary - to be removed on release */ ! 432: if (back-front == 17 && *front == MD5_ALGORITHM_BYTE) { ! 433: front++; ! 434: fprintf(stderr, "PGP 2.2b signature bug!\n"); ! 435: } ! 436: } ! 437: /* We're done - copy user data to outbuf */ ! 438: if (back < front) ! 439: goto ErrorReturn; ! 440: memcpy(outbuf, front, back-front); ! 441: mp_burn(temp); ! 442: return back-front; ! 443: ErrorReturn: ! 444: mp_burn(temp); ! 445: return -1; ! 446: } /* rsa_public_decrypt */ ! 447: ! 448: /* We expect to find random padding and an encryption key */ ! 449: int ! 450: rsa_private_decrypt(byteptr outbuf, unitptr inbuf, ! 451: unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N) ! 452: /* Decrypt an encryption key using a private key. Returns the number of bytes ! 453: * extracted, or <0 on error. ! 454: * -1: Corrupted packet. ! 455: */ ! 456: { ! 457: #ifdef RSAREF ! 458: R_RSA_PRIVATE_KEY PrivKey; ! 459: #endif ! 460: unsigned int blocksize; ! 461: unit temp[MAX_UNIT_PRECISION]; ! 462: unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION]; ! 463: byte *front, *back; ! 464: int i; ! 465: ! 466: mp_move(temp,P); ! 467: mp_dec(temp); ! 468: mp_mod(DP,D,temp); ! 469: mp_move(temp,Q); ! 470: mp_dec(temp); ! 471: mp_mod(DQ,D,temp); ! 472: ! 473: #ifdef RSAREF ! 474: make_RSA_PRIVATE_KEY(&PrivKey, E, D, P, Q, DP, DQ, U, N); ! 475: blocksize = countbytes(inbuf); ! 476: reg2rsaref((byte *)temp, blocksize, inbuf); ! 477: i = RSAPrivateBlock((byte *)temp, &blocksize, ! 478: (byte *)temp, blocksize, &PrivKey); ! 479: if (i < 0) ! 480: goto ErrorReturn; ! 481: front = (byte *)temp; /* Start of block */ ! 482: back = front + blocksize; /* End of block */ ! 483: i = blocksize - countbytes(N) + 1; /* Expected # of leading 0's */ ! 484: #else ! 485: i = mp_modexp_crt(temp, inbuf, P, Q, DP, DQ, U); ! 486: if (i < 0) ! 487: goto ErrorReturn; ! 488: mp_convert_order((byte *)temp); ! 489: front = (byte *)temp; /* Start of block */ ! 490: i = units2bytes(global_precision); ! 491: back = (byte *)front + i; /* End of block */ ! 492: blocksize = countbytes(N) - 1; ! 493: i -= blocksize; /* Expected # of leading 0's */ ! 494: #endif ! 495: if (i < 0) /* This shouldn't happen */ ! 496: goto ErrorReturn; ! 497: while (i--) /* Extra bytes should be 0 */ ! 498: if (*front++) ! 499: goto ErrorReturn; ! 500: ! 501: /* How to distinguish old PGP from PKCS formats. ! 502: * PGP packets have a trailing type byte (CK_ENCRYPTED_BYTE), ! 503: * while PKCS formats have it leading. ! 504: */ ! 505: if (front[0] != CK_ENCRYPTED_BYTE && back[-1] == CK_ENCRYPTED_BYTE) { ! 506: /* PGP 2.0 format - padding at the end */ ! 507: if (back[-1] != CK_ENCRYPTED_BYTE) ! 508: goto ErrorReturn; ! 509: while (*--back) /* Skip non-zero random padding */ ! 510: ; ! 511: } else { ! 512: /* PKCS format - padding at the beginning */ ! 513: if (*front++ != CK_ENCRYPTED_BYTE) ! 514: goto ErrorReturn; ! 515: while (*front++) /* Skip non-zero random padding */ ! 516: ; ! 517: } ! 518: if (back < front) ! 519: goto ErrorReturn; ! 520: memcpy(outbuf, front, back-front); ! 521: mp_burn(temp); ! 522: mp_burn(DP); ! 523: mp_burn(DQ); ! 524: return back-front; ! 525: ! 526: ErrorReturn: ! 527: mp_burn(temp); ! 528: mp_burn(DP); ! 529: mp_burn(DQ); ! 530: return -1; ! 531: } /* rsa_private_decrypt */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.