|
|
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.