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

  1. /*
  2.  * rsaglue1.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, Philip Zimmermann's mpi library for the
  8.  * RSA calculations.  The rsaglue.c module from PGP version 2.3a performs
  9.  * the same functions as this module, but can be compiled to select the
  10.  * use of mpilib functions instead of RSAREF as the underlying math engine.
  11.  * That version of rsaglue.c would be suitable where the RSA patent does
  12.  * not apply, such as Canada.
  13.  *
  14.  * This file uses MPILIB to perform the actual encryption and decryption.
  15.  * It uses the same PKCS format as RSAREF, although it also accepts an older
  16.  * format used in PGP 2.1.
  17.  *
  18.  * (c) Copyright 1990-1996 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 "mpilib.h"
  38. #include "mpiio.h"
  39. #include "pgp.h"
  40. #include "rsaglue.h"
  41. #include "random.h"    /* for cryptRandByte() */
  42.  
  43. /* No RSADSI credit for MPI version */
  44. char signon_legalese[] = "";
  45.  
  46. /* These functions hide all the internal details of RSA-encrypted
  47.  * keys and digests.  They owe a lot of their heritage to
  48.  * the preblock() and postunblock() routines in mpiio.c.
  49.  */
  50.  
  51. /* Abstract Syntax Notation One (ASN.1) Distinguished Encoding Rules (DER)
  52.    encoding for RSA/MD5, used in PKCS-format signatures. */
  53. static byte asn_array[] = {    /* PKCS 01 block type 01 data */
  54.     0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
  55.     0x02,0x05,0x05,0x00,0x04,0x10 };
  56. /* This many bytes from the end, there's a zero byte */
  57. #define ASN_ZERO_END 3
  58.  
  59. int
  60. rsa_public_encrypt(unitptr outbuf, byteptr inbuf, short bytes,
  61.      unitptr E, unitptr N)
  62. /* Encrypt a DEK with a public key.  Returns 0 on success.
  63.  * <0 means there was an error.
  64.  * -1: Generic error
  65.  * -3: Key too big
  66.  * -4: Key too small
  67.  */
  68. {
  69.     unit temp[MAX_UNIT_PRECISION];
  70.     unsigned int blocksize;
  71.     int i;    /* Temporary, and holds error codes */
  72.     byte *p = (byte *)temp;
  73.  
  74.     /*
  75.      * We are building the mpi in place, except for a possible
  76.      * byte-order swap to little-endian at the end.  Thus, we
  77.      * need to fill the buffer with leading 0's in the unused
  78.      * most significant byte positions.
  79.      */
  80.     blocksize = countbytes(N) - 1;    /* Bytes available for user data */
  81.     for (i = units2bytes(global_precision) - blocksize; i > 0; --i)
  82.         *p++ = 0;
  83.     /*
  84.      * Both the PKCS and PGP 2.0 key formats add a type byte, and a
  85.      * a framing byte of 0 to the user data.  The remaining space
  86.      * is filled with random padding.  (PKCS requires that there be
  87.      * at least 1 byte of padding.)
  88.      */
  89.     i = blocksize - 2 - bytes;
  90.  
  91.     if (i < 1)        /* Less than minimum padding? */
  92.         return -4;
  93.     *p++ = CK_ENCRYPTED_BYTE;    /* Type byte */
  94.     while (i)            /* Non-zero random padding */
  95.         if ((*p = cryptRandByte()))
  96.             ++p, --i;
  97.     *p++ = 0;            /* Framing byte */
  98.     memcpy(p, inbuf, bytes);    /* User data */
  99.  
  100.     mp_convert_order((byte *)temp);        /* Convert buffer to MPI */
  101.     i = mp_modexp(outbuf, temp, E, N);    /* Do the encryption */
  102.     if (i < 0)
  103.         i = -1;
  104.  
  105. Cleanup:
  106.     mp_burn(temp);
  107.     return i < 0 ? i : 0;
  108. } /* rsa_public_encrypt */
  109.  
  110. int
  111. rsa_private_encrypt(unitptr outbuf, byteptr inbuf, short bytes,
  112.      unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N)
  113. /* Encrypt a message digest with a private key.
  114.  * Returns <0 on error:
  115.  * -1: generic error
  116.  * -4: Key too big
  117.  * -5: Key too small
  118.  */
  119. {
  120.     unit temp[MAX_UNIT_PRECISION];
  121.     unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION];
  122.     byte *p;
  123.     int i;
  124.     unsigned int blocksize;
  125.  
  126.     /* PGP doesn't store these coefficents, so we need to compute them. */
  127.     mp_move(temp,P);
  128.     mp_dec(temp);
  129.     mp_mod(DP,D,temp);
  130.     mp_move(temp,Q);
  131.     mp_dec(temp);
  132.     mp_mod(DQ,D,temp);
  133.  
  134.     p = (byte *)temp;
  135.  
  136.  
  137.     /* We are building the mpi in place, except for a possible
  138.      * byte-order swap to little-endian at the end.  Thus, we
  139.      * need to fill the buffer with leading 0's in the unused
  140.      * most significant byte positions.
  141.      */
  142.     blocksize = countbytes(N) - 1;    /* Space available for data */
  143.     for (i = units2bytes(global_precision) - blocksize; i > 0; --i)
  144.         *p++ = 0;
  145.  
  146.     i = blocksize - 2 - bytes;        /* Padding needed */
  147.     i -= sizeof(asn_array);        /* Space for type encoding */
  148.     if (i < 0) {
  149.         i = -4;            /* Error code */
  150.         goto Cleanup;
  151.     }
  152.     *p++ = MD_ENCRYPTED_BYTE;    /* Type byte */
  153.     memset(p, ~0, i);        /* All 1's padding */
  154.     p += i;
  155.     *p++ = 0;            /* Zero framing byte */
  156.     memcpy(p, asn_array, sizeof(asn_array)); /* ASN data */
  157.     p += sizeof(asn_array);
  158.     memcpy(p, inbuf, bytes);    /* User data */
  159.  
  160.     mp_convert_order((byte *)temp);
  161.     i = mp_modexp_crt(outbuf, temp, P, Q, DP, DQ, U);    /* Encrypt */
  162.     if (i < 0)
  163.         i = -1;
  164.  
  165. Cleanup:
  166.     burn(temp);
  167.  
  168.     return i;
  169. } /* rsa_private_encrypt */
  170.  
  171. /* Remove a signature packet from an MPI */
  172. /* Thus, we expect constant padding and the MIC ASN sequence */
  173. int
  174. rsa_public_decrypt(byteptr outbuf, unitptr inbuf,
  175.     unitptr E, unitptr N)
  176. /* Decrypt a message digest using a public key.  Returns the number of bytes
  177.  * extracted, or <0 on error.
  178.  * -1: Corrupted packet.
  179.  * -3: Key too big
  180.  * -4: Key too small
  181.  * -5: Maybe malformed RSA packet
  182.  * -7: Unknown conventional algorithm
  183.  * -9: Malformed RSA packet
  184.  */
  185. {
  186.     unit temp[MAX_UNIT_PRECISION];
  187.     unsigned int blocksize;
  188.     int i;
  189.     byte *front, *back;
  190.  
  191.     i = mp_modexp(temp, inbuf, E, N);
  192.     if (i < 0) {
  193.         mp_burn(temp);
  194.         return -1;
  195.     }
  196.     mp_convert_order((byte *)temp);
  197.     blocksize = countbytes(N) - 1;
  198.     front = (byte *)temp;            /* Points to start of block */
  199.     i = units2bytes(global_precision);
  200.     back = front + i;            /* Points to end of block */
  201.     i -= countbytes(N) - 1;            /* Expected leading 0's */
  202.  
  203.     /*
  204.      * Strip off the padding.  This handles both PKCS and PGP 2.0
  205.      * formats.  If we're using RSAREF2, we use the padding-removal
  206.      * code in RSAPublicDecrypt, which accepts only PKCS style.
  207.      * Oh, well.
  208.      */
  209.  
  210.     if (i < 0)                /* This shouldn't happen */
  211.         goto ErrorReturn;
  212.     while (i--)                /* Extra bytes should be 0 */
  213.         if (*front++)
  214.             goto ErrorReturn;
  215.  
  216.     /* How to distinguish old PGP from PKCS formats.
  217.      * The old PGP format ends in a trailing type byte, with
  218.      * all 1's padding before that.  The PKCS format ends in
  219.      * 16 bytes of message digest, preceded by an ASN string
  220.      * which is not all 1's.
  221.      */
  222.     if (back[-1] == MD_ENCRYPTED_BYTE &&
  223.         back[-17] == 0xff && back[-18] == 0xff) {
  224.         /* Old PGP format: Padding is at the end */
  225.         if (*--back != MD_ENCRYPTED_BYTE)
  226.             goto ErrorReturn;
  227.         if (*front++ != MD5_ALGORITHM_BYTE) {
  228.             mp_burn(temp);
  229.             return -7;
  230.         }
  231.         while (*--back == 0xff)    /* Skip constant padding */
  232.             ;
  233.         if (*back)        /* It should end with a zero */
  234.             goto ErrorReturn;
  235.     } else {
  236.         /* PKCS format: padding at the beginning */
  237.         if (*front++ != MD_ENCRYPTED_BYTE)
  238.             goto ErrorReturn;
  239.         while (*front++ == 0xff) /* Skip constant padding */
  240.             ;
  241.         if (front[-1])    /* First non-FF byte should be 0 */
  242.             goto ErrorReturn;
  243.         /* Then comes the ASN header */
  244.         if (memcmp(front, asn_array, sizeof(asn_array))) {
  245.             mp_burn(temp);
  246.             return -7;
  247.         }
  248.         front += sizeof(asn_array);
  249.     }
  250.  
  251. /* We're done - copy user data to outbuf */
  252.     if (back < front)
  253.         goto ErrorReturn;
  254.     blocksize = back-front;
  255.     memcpy(outbuf, front, blocksize);
  256.     mp_burn(temp);
  257.     return blocksize;
  258. ErrorReturn:
  259.     mp_burn(temp);
  260.     return -9;
  261. } /* rsa_public_decrypt */
  262.  
  263. /* We expect to find random padding and an encryption key */
  264. int
  265. rsa_private_decrypt(byteptr outbuf, unitptr inbuf,
  266.      unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N)
  267. /* Decrypt an encryption key using a private key.  Returns the number of bytes
  268.  * extracted, or <0 on error.
  269.  * -1: Generic error
  270.  * -3: Key too big
  271.  * -4: Key too small
  272.  * -5: Maybe malformed RSA
  273.  * -7: Unknown conventional algorithm
  274.  * -9: Malformed RSA packet
  275.  */
  276. {
  277.     byte *back;
  278.     byte *front;
  279.     unsigned int blocksize;
  280.     unit temp[MAX_UNIT_PRECISION];
  281.     unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION];
  282.     int i;
  283.  
  284.     /* PGP doesn't store (d mod p-1) and (d mod q-1), so compute 'em */
  285.     mp_move(temp,P);
  286.     mp_dec(temp);
  287.     mp_mod(DP,D,temp);
  288.     mp_move(temp,Q);
  289.     mp_dec(temp);
  290.     mp_mod(DQ,D,temp);
  291.  
  292.     i = mp_modexp_crt(temp, inbuf, P, Q, DP, DQ, U);
  293.     mp_burn(DP);
  294.     mp_burn(DQ);
  295.     if (i < 0) {
  296.         mp_burn(temp);
  297.         return -1;
  298.     }
  299.     mp_convert_order((byte *)temp);
  300.     front = (byte *)temp;            /* Start of block */
  301.     i = units2bytes(global_precision);
  302.     back = (byte *)front + i;        /* End of block */
  303.     blocksize = countbytes(N) - 1;
  304.     i -= blocksize;                /* Expected # of leading 0's */
  305.  
  306.     if (i < 0)                /* This shouldn't happen */
  307.         goto Corrupted;
  308.     while (i--)                /* Extra bytes should be 0 */
  309.         if (*front++)
  310.             goto Corrupted;
  311.  
  312.     /* How to distinguish old PGP from PKCS formats.
  313.      * PGP packets have a trailing type byte (CK_ENCRYPTED_BYTE),
  314.      * while PKCS formats have it leading.
  315.      */
  316.     if (front[0] != CK_ENCRYPTED_BYTE && back[-1] == CK_ENCRYPTED_BYTE) {
  317.         /* PGP 2.0 format  - padding at the end */
  318.         if (back[-1] != CK_ENCRYPTED_BYTE)
  319.             goto Corrupted;
  320.         while (*--back)    /* Skip non-zero random padding */
  321.             ;
  322.     } else {
  323.         /* PKCS format - padding at the beginning */
  324.         if (*front++ != CK_ENCRYPTED_BYTE)
  325.             goto Corrupted;
  326.         while (*front++)    /* Skip non-zero random padding */
  327.             ;
  328.     }
  329.     if (back <= front)
  330.         goto Corrupted;
  331.     blocksize = back-front;
  332.  
  333.     memcpy(outbuf, front, blocksize);
  334.     mp_burn(temp);
  335.     return blocksize;
  336.  
  337. Corrupted:
  338.     mp_burn(temp);
  339.     return -9;
  340. } /* rsa_private_decrypt */
  341.