|
|
1.1 ! root 1: /* ! 2: * rsaglue2.c - These functions wrap and unwrap message digests (MDs) and ! 3: * data encryption keys (DEKs) in padding and RSA-encrypt them into ! 4: * multi-precision integers. This layer was introduced to allow the ! 5: * transparent use of RSAREF for the encryption (where required by ! 6: * patent law) or Philip Zimmermann's mpi library (where permitted, such ! 7: * as Canada). ! 8: * ! 9: * This file uses RSAREF to perform the actual encryption and decryption. ! 10: * It must be linked with the RSAREF 2.0 library (rsaref.a, rsaref.lib, ! 11: * or whatever it's called on your system) to function. ! 12: * ! 13: * This code only accepts PKCS-style padding. Sorry, folks, but the ! 14: * RSAREF routines won't do it any other way. This will cause some ! 15: * older messages and signatures trouble. ! 16: * See pgformat.doc for a detailed description of the formats. ! 17: * ! 18: * (c) Copyright 1990-1994 by Philip Zimmermann. All rights reserved. ! 19: * The author assumes no liability for damages resulting from the use ! 20: * of this software, even if the damage results from defects in this ! 21: * software. No warranty is expressed or implied. ! 22: * ! 23: * Note that while most PGP source modules bear Philip Zimmermann's ! 24: * copyright notice, many of them have been revised or entirely written ! 25: * by contributors who frequently failed to put their names in their ! 26: * code. Code that has been incorporated into PGP from other authors ! 27: * was either originally published in the public domain or is used with ! 28: * permission from the various authors. ! 29: * ! 30: * PGP is available for free to the public under certain restrictions. ! 31: * See the PGP User's Guide (included in the release package) for ! 32: * important information about licensing, patent restrictions on ! 33: * certain algorithms, trademarks, copyrights, and export controls. ! 34: */ ! 35: ! 36: #include <string.h> /* for mem*() */ ! 37: #include <assert.h> ! 38: #include "mpilib.h" ! 39: #include "mpiio.h" ! 40: #include "pgp.h" ! 41: #include "rsaglue.h" ! 42: #include "random.h" /* for cryptRandByte() */ ! 43: #include "language.h" /* for _LANG() */ ! 44: ! 45: char signon_legalese[] = _LANG("Distributed by the Massachusetts Institute of Technology. Uses RSAREF 2.0.\n"); ! 46: ! 47: #include <global.h> ! 48: #include <rsaref.h> ! 49: #include <rsa.h> ! 50: /* ! 51: * The functions we call in rsa.h are: ! 52: * ! 53: * int RSAPublicEncrypt PROTO_LIST ! 54: * ((unsigned char *, unsigned int *, unsigned char *, unsigned int, ! 55: * R_RSA_PUBLIC_KEY *, R_RANDOM_STRUCT *)); ! 56: * int RSAPrivateEncrypt PROTO_LIST ! 57: * ((unsigned char *, unsigned int *, unsigned char *, unsigned int, ! 58: * R_RSA_PRIVATE_KEY *)); ! 59: * int RSAPublicDecrypt PROTO_LIST ! 60: * ((unsigned char *, unsigned int *, unsigned char *, unsigned int, ! 61: * R_RSA_PUBLIC_KEY *)); ! 62: * int RSAPrivateDecrypt PROTO_LIST ! 63: * ((unsigned char *, unsigned int *, unsigned char *, unsigned int, ! 64: * R_RSA_PRIVATE_KEY *)); ! 65: */ ! 66: ! 67: /* Functions to convert to and from RSAREF's bignum formats */ ! 68: ! 69: void ! 70: rsaref2reg (unitptr to, byte *from, int frombytes) ! 71: /* Convert an RSAREF-style MSB-first array of bytes to an mpi-style ! 72: * native-byte-order integer. (global_precision units long.) ! 73: */ ! 74: { ! 75: int tobytes; ! 76: ! 77: tobytes = units2bytes (global_precision); ! 78: if (tobytes > frombytes) { ! 79: memset(to, 0, tobytes - frombytes); ! 80: memcpy((byte *)to + tobytes - frombytes, from, frombytes); ! 81: } else { ! 82: memcpy((byte *)to, from + frombytes - tobytes, tobytes); ! 83: } ! 84: #ifndef HIGHFIRST ! 85: hiloswap((byte *)to, tobytes); ! 86: #endif ! 87: } /* rsaref2reg */ ! 88: ! 89: void ! 90: reg2rsaref (byte *to, int tobytes, unitptr from) ! 91: /* Convert the other way, mpi format to an array of bytes. */ ! 92: { ! 93: int frombytes; ! 94: ! 95: frombytes = units2bytes(global_precision); ! 96: ! 97: #ifdef HIGHFIRST ! 98: if (tobytes > frombytes) { ! 99: memset(to, 0, tobytes-frombytes); ! 100: memcpy(to + tobytes - frombytes, (byte *)from, frombytes); ! 101: } else { ! 102: memcpy(to, (byte *)from + frombytes - tobytes, tobytes); ! 103: } ! 104: #else ! 105: if (tobytes > frombytes) { ! 106: memcpy(to, (byte *)from, frombytes); ! 107: memset(to + frombytes, 0, tobytes-frombytes); ! 108: } else { ! 109: memcpy(to, (byte *)from, tobytes); ! 110: } ! 111: hiloswap(to, tobytes); ! 112: #endif ! 113: } /* reg2rsaref */ ! 114: ! 115: int ! 116: make_RSA_PUBLIC_KEY(R_RSA_PUBLIC_KEY *rpk, unitptr e, unitptr n) ! 117: /* Given mpi's e and n, fill in an R_RSA_PUBLIC_KEY structure. ! 118: * Returns -3 on error (key too big), 0 on success ! 119: */ ! 120: { ! 121: rpk->bits = countbits(n); ! 122: ! 123: if (rpk->bits > MAX_RSA_MODULUS_BITS) ! 124: return -3; ! 125: ! 126: reg2rsaref(rpk->modulus, MAX_RSA_MODULUS_LEN, n); ! 127: reg2rsaref(rpk->exponent, MAX_RSA_MODULUS_LEN, e); ! 128: return 0; ! 129: } /* make_RSA_PUBLIC_KEY */ ! 130: ! 131: /* Returns -1 on error, 0 on success */ ! 132: int ! 133: make_RSA_PRIVATE_KEY(R_RSA_PRIVATE_KEY *rpk, unitptr e, unitptr d, unitptr p, ! 134: unitptr q, unitptr dp, unitptr dq, unitptr u, unitptr n) ! 135: /* Given a number of necessary mpi's, fill in an R_RSA_PRIVATE_KEY structure. ! 136: * Returns -3 on error (key too big), 0 on success ! 137: */ ! 138: { ! 139: rpk->bits = countbits(n); ! 140: ! 141: if (rpk->bits > MAX_RSA_MODULUS_BITS || ! 142: countbits(p) > MAX_RSA_PRIME_BITS || ! 143: countbits(q) > MAX_RSA_PRIME_BITS) ! 144: return -3; ! 145: ! 146: reg2rsaref(rpk->modulus, MAX_RSA_MODULUS_LEN, n); ! 147: reg2rsaref(rpk->publicExponent, MAX_RSA_MODULUS_LEN, e); ! 148: reg2rsaref(rpk->exponent, MAX_RSA_MODULUS_LEN, d); ! 149: /* The larger prime (p) first */ ! 150: reg2rsaref(rpk->prime[0], MAX_RSA_PRIME_LEN, q); ! 151: reg2rsaref(rpk->prime[1], MAX_RSA_PRIME_LEN, p); ! 152: /* d mod (p-1) and d mod (q-1) */ ! 153: reg2rsaref(rpk->primeExponent[0], MAX_RSA_PRIME_LEN, dq); ! 154: reg2rsaref(rpk->primeExponent[1], MAX_RSA_PRIME_LEN, dp); ! 155: /* 1/q mod p */ ! 156: reg2rsaref(rpk->coefficient, MAX_RSA_PRIME_LEN, u); ! 157: return 0; ! 158: } /* make_RSA_PRIVATE_KEY */ ! 159: ! 160: /* ! 161: * These functions hide all the internal details of RSA-encrypted ! 162: * keys and digests. ! 163: */ ! 164: ! 165: /* Abstract Syntax Notation One (ASN.1) Distinguished Encoding Rules (DER) ! 166: encoding for RSA/MD5, used in PKCS-format signatures. */ ! 167: static byte asn_array[] = { /* PKCS 01 block type 01 data */ ! 168: 0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, ! 169: 0x02,0x05,0x05,0x00,0x04,0x10 }; ! 170: /* This many bytes from the end, there's a zero byte */ ! 171: #define ASN_ZERO_END 3 ! 172: ! 173: int ! 174: rsa_public_encrypt(unitptr outbuf, byteptr inbuf, short bytes, ! 175: unitptr E, unitptr N) ! 176: /* Encrypt a DEK with a public key. Returns 0 on success. ! 177: * <0 means there was an error. ! 178: * -1: Generic error ! 179: * -3: Key too big ! 180: * -4: Key too small ! 181: */ ! 182: { ! 183: unit temp[MAX_UNIT_PRECISION]; ! 184: unsigned int blocksize; ! 185: int i; /* Temporary, and holds error codes */ ! 186: R_RSA_PUBLIC_KEY PubKey; ! 187: R_RANDOM_STRUCT Random; ! 188: ! 189: /* Fill in the R_RSA_PUBLIC_KEY structure as needed later. */ ! 190: i = make_RSA_PUBLIC_KEY(&PubKey, E, N); ! 191: if (i < 0) ! 192: return i; ! 193: ! 194: /* The RSAREF routines have their own random number generator ! 195: * to generate random padding. The following code seeds it ! 196: * from PGP's random number generator. ! 197: */ ! 198: R_RandomInit(&Random); ! 199: for (;;) { ! 200: /* Bytes needed is an unsigned int */ ! 201: R_GetRandomBytesNeeded(&blocksize, &Random); ! 202: if (!blocksize) ! 203: break; ! 204: if (blocksize > sizeof(temp)) ! 205: blocksize = sizeof(temp); ! 206: for (i = 0; i < blocksize; i++) ! 207: ((byte *)temp)[i] = cryptRandByte(); ! 208: R_RandomUpdate(&Random, (byte *)temp, blocksize); ! 209: ! 210: } ! 211: /* Pad and encrypt */ ! 212: i = RSAPublicEncrypt((byte *)temp, &blocksize, ! 213: inbuf, bytes, &PubKey, &Random); ! 214: R_RandomFinal(&Random); /* Clean up RSAREF's RNG */ ! 215: burn(Random); /* Just to be sure */ ! 216: ! 217: if (i) ! 218: i = (i == RE_LEN) ? -4 : -1; ! 219: ! 220: rsaref2reg(outbuf, (byte *)temp, blocksize); ! 221: ! 222: Cleanup: ! 223: mp_burn(temp); ! 224: burn(PubKey); ! 225: return i < 0 ? i : 0; ! 226: } /* rsa_public_encrypt */ ! 227: ! 228: int ! 229: rsa_private_encrypt(unitptr outbuf, byteptr inbuf, short bytes, ! 230: unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N) ! 231: /* Encrypt a message digest with a private key. ! 232: * Returns <0 on error: ! 233: * -1: generic error ! 234: * -3: Key too big ! 235: * -4: Key too small ! 236: */ ! 237: { ! 238: unit temp[MAX_UNIT_PRECISION]; ! 239: unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION]; ! 240: R_RSA_PRIVATE_KEY PrivKey; ! 241: byte *p; ! 242: int i; ! 243: unsigned int blocksize; ! 244: ! 245: /* PGP doesn't store these coefficents, so we need to compute them. */ ! 246: mp_move(temp,P); ! 247: mp_dec(temp); ! 248: mp_mod(DP,D,temp); ! 249: mp_move(temp,Q); ! 250: mp_dec(temp); ! 251: mp_mod(DQ,D,temp); ! 252: ! 253: p = (byte *)temp; ! 254: ! 255: i = make_RSA_PRIVATE_KEY(&PrivKey, E, D, P, Q, DP, DQ, U, N); ! 256: if (i < 0) ! 257: goto Cleanup; ! 258: memcpy(p, asn_array, sizeof(asn_array)); /* ASN data */ ! 259: p += sizeof(asn_array); ! 260: memcpy(p, inbuf, bytes); /* User data */ ! 261: /* Pad and encrypt */ ! 262: i = RSAPrivateEncrypt((byte *)temp, &blocksize, ! 263: (byte *)temp, bytes+sizeof(asn_array), &PrivKey); ! 264: burn(PrivKey); ! 265: if (i) ! 266: i = (i == RE_LEN) ? -4 : -1; ! 267: ! 268: rsaref2reg(outbuf, (byte *)temp, blocksize); ! 269: ! 270: Cleanup: ! 271: burn(temp); ! 272: ! 273: return i; ! 274: } /* rsa_private_encrypt */ ! 275: ! 276: /* Remove a signature packet from an MPI */ ! 277: /* Thus, we expect constant padding and the MIC ASN sequence */ ! 278: int ! 279: rsa_public_decrypt(byteptr outbuf, unitptr inbuf, ! 280: unitptr E, unitptr N) ! 281: /* Decrypt a message digest using a public key. Returns the number of bytes ! 282: * extracted, or <0 on error. ! 283: * -1: Corrupted packet. ! 284: * -3: Key too big ! 285: * -4: Key too small ! 286: * -5: Maybe malformed RSA packet ! 287: * -7: Unknown conventional algorithm ! 288: * -9: Malformed RSA packet ! 289: */ ! 290: { ! 291: R_RSA_PUBLIC_KEY PubKey; ! 292: unit temp[MAX_UNIT_PRECISION]; ! 293: unsigned int blocksize; ! 294: int i; ! 295: byte *front, *back; ! 296: ! 297: i = make_RSA_PUBLIC_KEY(&PubKey, E, N); ! 298: if (i < 0) ! 299: return i; ! 300: blocksize = countbytes(inbuf); ! 301: reg2rsaref((byte *)temp, blocksize, inbuf); ! 302: ! 303: i = RSAPublicDecrypt((byte *)temp, &blocksize, ! 304: (byte *)temp, blocksize, &PubKey); ! 305: burn(PubKey); ! 306: if (i) { ! 307: mp_burn(temp); ! 308: if (i == RE_LEN) ! 309: return -4; ! 310: if (i == RE_DATA) ! 311: return -5; ! 312: return -1; ! 313: } ! 314: front = (byte *)temp; ! 315: back = front+blocksize; ! 316: ! 317: if (memcmp(front, asn_array, sizeof(asn_array))) { ! 318: mp_burn(temp); ! 319: return -7; ! 320: } ! 321: front += sizeof(asn_array); ! 322: ! 323: /* We're done - copy user data to outbuf */ ! 324: if (back < front) ! 325: goto ErrorReturn; ! 326: blocksize = back-front; ! 327: memcpy(outbuf, front, blocksize); ! 328: mp_burn(temp); ! 329: return blocksize; ! 330: ErrorReturn: ! 331: mp_burn(temp); ! 332: return -9; ! 333: } /* rsa_public_decrypt */ ! 334: ! 335: /* We expect to find random padding and an encryption key */ ! 336: int ! 337: rsa_private_decrypt(byteptr outbuf, unitptr inbuf, ! 338: unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N) ! 339: /* Decrypt an encryption key using a private key. Returns the number of bytes ! 340: * extracted, or <0 on error. ! 341: * -1: Generic error ! 342: * -3: Key too big ! 343: * -4: Key too small ! 344: * -5: Maybe malformed RSA ! 345: * -7: Unknown conventional algorithm ! 346: * -9: Malformed RSA packet ! 347: */ ! 348: { ! 349: R_RSA_PRIVATE_KEY PrivKey; ! 350: byte *front; ! 351: unsigned int blocksize; ! 352: unit temp[MAX_UNIT_PRECISION]; ! 353: unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION]; ! 354: int i; ! 355: ! 356: /* PGP doesn't store (d mod p-1) and (d mod q-1), so compute 'em */ ! 357: mp_move(temp,P); ! 358: mp_dec(temp); ! 359: mp_mod(DP,D,temp); ! 360: mp_move(temp,Q); ! 361: mp_dec(temp); ! 362: mp_mod(DQ,D,temp); ! 363: ! 364: i = make_RSA_PRIVATE_KEY(&PrivKey, E, D, P, Q, DP, DQ, U, N); ! 365: mp_burn(DP); ! 366: mp_burn(DQ); ! 367: mp_burn(temp); ! 368: ! 369: if (i < 0) ! 370: return i; ! 371: ! 372: blocksize = countbytes(inbuf); ! 373: reg2rsaref((byte *)temp, blocksize, inbuf); ! 374: i = RSAPrivateDecrypt((byte *)temp, &blocksize, ! 375: (byte *)temp, blocksize, &PrivKey); ! 376: burn(PrivKey); ! 377: if (i) { ! 378: if (i == RE_LEN) ! 379: return -4; ! 380: if (i == RE_DATA) ! 381: return -5; ! 382: return -1; ! 383: } ! 384: front = (byte *)temp; /* Start of block */ ! 385: ! 386: memcpy(outbuf, front, blocksize); ! 387: mp_burn(temp); ! 388: return blocksize; ! 389: ! 390: Corrupted: ! 391: mp_burn(temp); ! 392: return -9; ! 393: } /* rsa_private_decrypt */ ! 394: ! 395: /* ! 396: * Stub to replace RSAREF's NN_ModExp with a call to the mpilib's ! 397: * faster mp_modexp. (A bit over 3x faster on an IBM PC.) ! 398: * It's too bad that RSAREF's NN routines are pretty clean, while the ! 399: * mpilib is attractive only to the sort of people who like dead baby ! 400: * jokes. But the mpilib is pretty fast, especially on 16-bit machines, ! 401: * so this Bride of Frankenstein creation has reason for existence. ! 402: * ! 403: * If you comment out the following block of code, you get a (much slower) ! 404: * pure RSAREF version. ! 405: */ ! 406: #ifdef USEMPILIB ! 407: ! 408: /* ! 409: * The mpilib keeps numbers in native byte order, in arrays global_precision ! 410: * "units" long. RSAREF keeps numbers in little-endian arrays of 32-bit ! 411: * "digits". ! 412: */ ! 413: static void ! 414: nn2mpi(unit *mpi, word32 *nn, unsigned nndigits) ! 415: { ! 416: /* nndigits must be <= global_precision */ ! 417: unsigned i; ! 418: word32 *p; ! 419: ! 420: assert((units2bytes(global_precision) & 3) == 0); ! 421: i = units2bytes(global_precision) >> 2; ! 422: if (nndigits > i) ! 423: nndigits = i; ! 424: i -= nndigits; ! 425: ! 426: #ifdef HIGHFIRST ! 427: p = (word32 *)(mpi+global_precision); ! 428: while (nndigits--) ! 429: *--p = *nn++; ! 430: while (i--) ! 431: *--p = 0; ! 432: #else ! 433: p = (word32 *)mpi; ! 434: while (nndigits--) ! 435: *p++ = *nn++; ! 436: while (i--) ! 437: *p++ = 0; ! 438: #endif ! 439: } ! 440: ! 441: static void ! 442: mpi2nn(word32 *nn, unsigned nndigits, unit *mpi) ! 443: { ! 444: /* nndigits must be >= global_precision */ ! 445: unsigned i; ! 446: word32 *p; ! 447: ! 448: assert((units2bytes(global_precision) & 3) == 0); ! 449: i = units2bytes(global_precision) >> 2; ! 450: if (i > nndigits) ! 451: i = nndigits; ! 452: nndigits -= i; ! 453: ! 454: #ifdef HIGHFIRST ! 455: p = (word32 *)(mpi+global_precision); ! 456: while (i--) ! 457: *nn++ = *--p; ! 458: #else ! 459: p = (word32 *)mpi; ! 460: while (i--) ! 461: *nn++ = *p++; ! 462: #endif ! 463: while (nndigits--) ! 464: *nn++ = 0; ! 465: } ! 466: ! 467: void ! 468: NN_ModExp(word32 *result, word32 *base, word32 *exponent, unsigned expdigits, ! 469: word32 *modulus, unsigned moddigits) ! 470: { ! 471: unit a[MAX_UNIT_PRECISION], b[MAX_UNIT_PRECISION]; ! 472: unit c[MAX_UNIT_PRECISION], d[MAX_UNIT_PRECISION]; ! 473: int i; ! 474: unsigned oldprecision; ! 475: ! 476: oldprecision = global_precision; ! 477: set_precision(MAX_UNIT_PRECISION); ! 478: ! 479: nn2mpi(b, base, moddigits); ! 480: nn2mpi(c, exponent, expdigits); ! 481: nn2mpi(d, modulus, moddigits); ! 482: ! 483: i = mp_modexp(a, b, c, d); ! 484: assert(i == 0); ! 485: mpi2nn(result, moddigits, a); ! 486: set_precision(oldprecision); ! 487: } ! 488: ! 489: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.