home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1998 February / PCOnline_02_1998.iso / filesbbs / os2 / pgp263.arj / PGP263I.SRC / PGP263II.ZIP / src / rsaglue2.c < prev    next >
C/C++ Source or Header  |  1996-01-02  |  14KB  |  498 lines

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