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