Annotation of pgp/src/rsaglue2.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.