home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / varia / pgp / pgpamiga / source / rsaglue.c < prev    next >
C/C++ Source or Header  |  1996-11-08  |  20KB  |  533 lines

  1. /* rsaglue.c - These functions wrap and unwrap message digests (MDs) and
  2.  * data encryption keys (DEKs) in padding and RSA-encrypt them into
  3.  * multi-precision integers.  This layer was introduced to allow the
  4.  * transparent use of RSAREF for the encryption (in regions where it is
  5.  * legally available - the U.S. and treaty partners), or Philip Zimmermann's
  6.  * mpi library (where permitted by patent law - outside the U.S.).
  7.  *
  8.  * These functions also hide the details of using either PKCS or PGP 2.0
  9.  * style padding and encodings within the integers.  See pgformat.doc
  10.  * for a detailed description of the formats.
  11.  */
  12.  
  13. #include <string.h>     /* for mem*() */
  14. #include "mpilib.h"
  15. #include "mpiio.h"
  16. #include "pgp.h"
  17. #include "rsaglue.h"
  18. #include "idea.h"
  19.  
  20. #ifdef RSAREF           /* defined (or not) in rsaglue.h */
  21. #include "rsaref/test/global.h"
  22. #include "rsaref/source/rsa.h"
  23. #include "rsaref/source/rsaref.h"
  24.  
  25. int RSAPublicBlock(byte *dest, unsigned *destbytesptr,
  26.                    byte *src, unsigned srcbytes,
  27.                    R_RSA_PUBLIC_KEY *PubKey);
  28. int RSAPrivateBlock(byte *dest, unsigned *destbytesptr,
  29.                     byte *src, unsigned srcbytes,
  30.                     R_RSA_PRIVATE_KEY *PrivKey);
  31.  
  32. /* Functions to convert to and from RSAREF's bignum formats */
  33.  
  34. void
  35. rsaref2reg (unitptr to, byte *from, int frombytes)
  36. /* Convert an RSAREF-style MSB-first array of bytes to an mpi-style
  37.  * native-byte-order integer.  (global_precision units long.)
  38.  */
  39. {
  40.         int tobytes;
  41.  
  42.         tobytes = units2bytes (global_precision);
  43.         if (tobytes > frombytes) {
  44.                 memset(to, 0, tobytes - frombytes);
  45.                 memcpy((byte *)to + tobytes - frombytes, from, frombytes);
  46.         } else {
  47.                 memcpy((byte *)to, from + frombytes - tobytes, tobytes);
  48.         }
  49. #ifndef HIGHFIRST
  50.         hiloswap((byte *)to, tobytes);
  51. #endif
  52. } /* rsaref2reg */
  53.  
  54. void
  55. reg2rsaref (byte *to, int tobytes, unitptr from)
  56. /* Convert the other way, mpi format to an array of bytes. */
  57. {
  58.         int frombytes;
  59.  
  60.         frombytes = units2bytes(global_precision);
  61.  
  62. #ifdef HIGHFIRST
  63.         if (tobytes > frombytes) {
  64.                 memset(to, 0, tobytes-frombytes);
  65.                 memcpy(to + tobytes - frombytes, (byte *)from, frombytes);
  66.         } else {
  67.                 memcpy(to, (byte *)from + frombytes - tobytes, tobytes);
  68.         }
  69. #else
  70.         if (tobytes > frombytes) {
  71.                 memcpy(to, (byte *)from, frombytes);
  72.                 memset(to + frombytes, 0, tobytes-frombytes);
  73.         } else {
  74.                 memcpy(to, (byte *)from, tobytes);
  75.         }
  76.         hiloswap(to, tobytes);
  77. #endif
  78. } /* reg2rsaref */
  79.  
  80. int
  81. make_RSA_PUBLIC_KEY(R_RSA_PUBLIC_KEY *rpk, unitptr e, unitptr n)
  82. /* Given mpi's e and n, fill in an R_RSA_PUBLIC_KEY structure.
  83.  * Returns -1 on error, 0 on success
  84.  */
  85. {
  86.         rpk->bits = countbits(n);
  87.         if (rpk->bits > MAX_RSA_MODULUS_BITS)
  88.                 return -1;
  89.  
  90.         reg2rsaref(rpk->modulus, MAX_RSA_MODULUS_LEN, n);
  91.         reg2rsaref(rpk->exponent, MAX_RSA_MODULUS_LEN, e);
  92.         return 0;
  93. } /* make_RSA_PUBLIC_KEY */
  94.  
  95. /* Returns -1 on error, 0 on success */
  96. int
  97. make_RSA_PRIVATE_KEY(R_RSA_PRIVATE_KEY *rpk, unitptr e, unitptr d, unitptr p,
  98.                      unitptr q, unitptr dp, unitptr dq, unitptr u, unitptr n)
  99. /* Given a number of necessary mpi's, fill in an R_RSA_PRIVATE_KEY structure.
  100.  * Returns -1 on error, 0 on success
  101.  */
  102. {
  103.         rpk->bits = countbits(n);
  104.         if (rpk->bits > MAX_RSA_MODULUS_BITS ||
  105.             countbits(p) > MAX_RSA_PRIME_BITS ||
  106.             countbits(q) > MAX_RSA_PRIME_BITS)
  107.                 return -1;
  108.  
  109.         reg2rsaref(rpk->modulus, MAX_RSA_MODULUS_LEN, n);
  110.         reg2rsaref(rpk->publicExponent, MAX_RSA_MODULUS_LEN, e);
  111.         reg2rsaref(rpk->exponent, MAX_RSA_MODULUS_LEN, d);
  112.         /* The larger prime (p) first */
  113.         reg2rsaref(rpk->prime[0], MAX_RSA_PRIME_LEN, q);
  114.         reg2rsaref(rpk->prime[1], MAX_RSA_PRIME_LEN, p);
  115.         /* d mod (p-1) and d mod (q-1) */
  116.         reg2rsaref(rpk->primeExponent[0], MAX_RSA_PRIME_LEN, dq);
  117.         reg2rsaref(rpk->primeExponent[1], MAX_RSA_PRIME_LEN, dp);
  118.         /* 1/q mod p */
  119.         reg2rsaref(rpk->coefficient, MAX_RSA_PRIME_LEN, u);
  120.         return 0;
  121. } /* make_RSA_PRIVATE_KEY */
  122.  
  123. #endif /* RSAREF */
  124.  
  125. /* These functions hide all the internal details of RSA-encrypted
  126.  * keys and digests.  They owe a lot of their heritage to
  127.  * the preblock() and postunblock() routines in mpiio.c.
  128.  */
  129.  
  130. /* Abstract Syntax Notation One (ASN.1) Distinguished Encoding Rules (DER)
  131.    encoding for RSA/MD5, used in PKCS-format signatures. */
  132. static byte asn_array[] = {     /* PKCS 01 block type 01 data */
  133.         0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
  134.         0x02,0x05,0x05,0x00,0x04,0x10 };
  135. /* This many bytes from the end, there's a zero byte */
  136. #define ASN_ZERO_END 3
  137.  
  138. int
  139. rsa_public_encrypt(unitptr outbuf, byteptr inbuf, short bytes,
  140.          unitptr E, unitptr N)
  141. /* Encrypt a DEK with a public key.  Returns 0 on success.
  142.  * <0 means there was an error
  143.  */
  144. {
  145.         unit temp[MAX_UNIT_PRECISION];
  146. #ifdef RSAREF
  147.         R_RSA_PUBLIC_KEY PubKey;
  148.         R_RANDOM_STRUCT Random;
  149. #endif /* RSAREF */
  150.         unsigned int blocksize;
  151.         byte *p;
  152.         int i;  /* Temporary, and holds error codes */
  153.  
  154.         blocksize = countbytes(N) - 1;  /* Bytes available for user data */
  155.  
  156.         p = (byte *)temp;
  157.  
  158. #ifdef RSAREF
  159.         /* Fill in the R_RSA_PUBLIC_KEY structure as needed later. */
  160.         i = make_RSA_PUBLIC_KEY(&PubKey, E, N);
  161.         if (i < 0)
  162.                 return -1;
  163. #else /* !RSAREF */
  164.         /* If !RSAREF, we are building the mpi in place, except for a
  165.          * possible byte-order swap to little-endian at the end.  Thus,
  166.          * we need to fill the buffer with leading 0's in the unused
  167.          * most significant byte positions.
  168.          */
  169.         for (i = units2bytes(global_precision) - blocksize; i > 0; --i)
  170.                 *p++ = 0;
  171. #endif /* !RSAREF */
  172.  
  173.         /* Both the PKCS and PGP 2.0 key formats add a type byte, and a
  174.          * a framing byte of 0 to the user data.  The remaining space
  175.          * is filled with random padding.  (PKCS requires that there be
  176.          * at least 1 byte of padding.)
  177.          */
  178.         i = blocksize - 2 - bytes;
  179.  
  180.         if (pkcs_compat) {
  181.                 if (i < 1)              /* Less than minimum padding? */
  182.                         return -1;
  183. #ifndef RSAREF  /* Build the packet ourselves */
  184.                 *p++ = CK_ENCRYPTED_BYTE;       /* Type byte */
  185.                 while (i)                       /* Non-zero random padding */
  186.                         if ((*p = idearand()))
  187.                                 ++p, --i;
  188.                 *p++ = 0;                       /* Framing byte */
  189.                 memcpy(p, inbuf, bytes);        /* User data */
  190. #else /* RSAREF */
  191.                 /* The RSAREF routines have their own random number generator
  192.                  * to generate random padding.  The following code seeds it
  193.                  * from PGP's random number generator.
  194.                  */
  195.                 R_RandomInit(&Random);
  196.                 for (;;) {
  197.                         R_GetRandomBytesNeeded(&i, &Random);
  198.                         if (i <= 0)
  199.                                 break;
  200.                         blocksize = i > sizeof(temp) ? sizeof(temp) : i;
  201.                         for (i = 0; i < blocksize; i++)
  202.                                 ((byte *)temp)[i] = idearand();
  203.                         R_RandomUpdate(&Random, (byte *)temp, blocksize);
  204.                 }
  205.                 /* Pad and encrypt */
  206.                 i = RSAPublicEncrypt((byte *)temp, &blocksize,
  207.                                      inbuf, bytes, &PubKey, &Random);
  208.                 R_RandomFinal(&Random); /* Clean up RSAREF's RNG */
  209.                 burn(Random);           /* Just to be sure */
  210. #endif /* RSAREF */
  211.         } else {        /* !pkcs_compat */
  212.                 if (i < 0)
  213.                         return -1;
  214.                 memcpy(p, inbuf, bytes);        /* User data */
  215.                 p += bytes;
  216.                 *p++ = 0;                       /* Framing byte */
  217.                 while (i)                       /* Non-zero random padding */
  218.                         if ((*p = idearand()))
  219.                                 ++p, --i;
  220.                 *p = CK_ENCRYPTED_BYTE;         /* Type byte */
  221. #ifdef RSAREF
  222.         /* Do the encryption */
  223.         i = RSAPublicBlock((byte *)temp, &blocksize,
  224.                            (byte *)temp, blocksize, &PubKey);
  225. #endif
  226.  
  227.         } /* !pkcs_compat */
  228.  
  229. #ifndef RSAREF
  230.         mp_convert_order((byte *)temp);         /* Convert buffer to MPI */
  231.         i = mp_modexp(outbuf, temp, E, N);      /* Do the encryption */
  232. #else /* RSAREF */
  233.         rsaref2reg(outbuf, (byte *)temp, blocksize);
  234. #endif /* RSAREF */
  235.  
  236. Cleanup:
  237.         mp_burn(temp);
  238. #ifdef RSAREF
  239.         burn(PubKey);
  240. #endif
  241.         return i < 0 ? i : 0;
  242. } /* rsa_public_encrypt */
  243.  
  244. int
  245. rsa_private_encrypt(unitptr outbuf, byteptr inbuf, short bytes,
  246.          unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N)
  247. /* Encrypt a message digest with a private key.
  248.  * Returns <0 on error.
  249.  */
  250. {
  251.         unit temp[MAX_UNIT_PRECISION];
  252.         unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION];
  253. #ifdef RSAREF
  254.         R_RSA_PRIVATE_KEY PrivKey;
  255. #else
  256. /*        int byte_precision;   */
  257. #endif
  258.         unsigned int blocksize;
  259.         byte *p;
  260.         int i;
  261.  
  262.         /* PGP doesn't store these coefficents, so we need to compute them. */
  263.         mp_move(temp,P);
  264.         mp_dec(temp);
  265.         mp_mod(DP,D,temp);
  266.         mp_move(temp,Q);
  267.         mp_dec(temp);
  268.         mp_mod(DQ,D,temp);
  269.  
  270.         blocksize = countbytes(N) - 1;  /* Space available for data */
  271.  
  272.         p = (byte *)temp;
  273.  
  274. #ifdef RSAREF
  275.         i = make_RSA_PRIVATE_KEY(&PrivKey, E, D, P, Q, DP, DQ, U, N);
  276.         if (i < 0)
  277.                 goto Cleanup;
  278. #else
  279.         /* If !RSAREF, we are building the mpi in place, except for a
  280.          * possible byte-order swap to little-endian at the end.  Thus,
  281.          * we need to fill the buffer with leading 0's in the unused
  282.          * most significant byte positions.
  283.          */
  284.         for (i = units2bytes(global_precision) - blocksize; i > 0; --i)
  285.                 *p++ = 0;
  286. #endif
  287.         i = blocksize - 2 - bytes;              /* Padding needed */
  288.  
  289.         if (pkcs_compat) {
  290. #ifndef RSAREF  /* Pad the packet ourselves */
  291.                 i -= sizeof(asn_array);         /* Space for type encoding */
  292.                 if (i < 0) {
  293.                         i = -1;                 /* Error code */
  294.                         goto Cleanup;
  295.                 }
  296.                 *p++ = MD_ENCRYPTED_BYTE;       /* Type byte */
  297.                 memset(p, ~0, i);               /* All 1's padding */
  298.                 p += i;
  299.                 *p++ = 0;                       /* Zero framing byte */
  300. #endif /* !RSAREF */
  301.                 memcpy(p, asn_array, sizeof(asn_array)); /* ASN data */
  302.                 p += sizeof(asn_array);
  303.                 memcpy(p, inbuf, bytes);        /* User data */
  304. #ifdef RSAREF
  305.                 /* Pad and encrypt */
  306.                 RSAPrivateEncrypt((byte *)temp, &blocksize,
  307.                                   (byte *)temp, bytes+sizeof(asn_array),
  308.                                   &PrivKey);
  309. #endif
  310.         } else {        /* Not pkcs_compat */
  311.                 --i;                            /* Space for type byte */
  312.                 if (i < 0) {
  313.                         i = -1;                 /* Error code */
  314.                         goto Cleanup;
  315.                 }
  316.                 *p++ = MD5_ALGORITHM_BYTE;      /* Algorithm type byte */
  317.                 memcpy(p, inbuf, bytes);        /* User data */
  318.                 p += bytes;
  319.                 *p++ = 0;                       /* Framing byte of 0 */
  320.                 memset(p, ~0, i);               /* All 1's padding */
  321.                 p += i;
  322.                 *p = MD_ENCRYPTED_BYTE;         /* Type byte */
  323.  
  324. #ifdef RSAREF
  325.         /* Do the encryption */
  326.         i = RSAPrivateBlock((byte *)temp, &blocksize,
  327.                             (byte *)temp, blocksize, &PrivKey);
  328. #endif /* RSAREF */
  329.  
  330.         } /* !pkcs_compat */
  331.  
  332. #ifndef RSAREF
  333.         mp_convert_order((byte *)temp);
  334.         i = mp_modexp_crt(outbuf, temp, P, Q, DP, DQ, U);       /* Encrypt */
  335. #else /* RSAREF */
  336.         rsaref2reg(outbuf, (byte *)temp, blocksize);
  337. #endif /* RSAREF */
  338.  
  339. Cleanup:
  340.         mp_burn(temp);
  341. #ifdef RSAREF
  342.         memset(&PrivKey, 0, sizeof(PrivKey));
  343. #endif
  344.         return i < 0 ? i : 0;
  345. } /* rsa_private_encrypt */
  346.  
  347. /* Remove a signature packet from an MPI */
  348. /* Thus, we expect constant padding and the MIC ASN sequence */
  349. int
  350. rsa_public_decrypt(byteptr outbuf, unitptr inbuf,
  351.         unitptr E, unitptr N)
  352. /* Decrypt a message digest using a public key.  Returns the number of bytes
  353.  * extracted, or <0 on error.
  354.  * -1: Corrupted packet.
  355.  * -2: Unrecognized message digest algorithm.
  356.  */
  357. {
  358. #ifdef RSAREF
  359.         R_RSA_PUBLIC_KEY PubKey;
  360. #endif
  361.         unit temp[MAX_UNIT_PRECISION];
  362.         unsigned int blocksize;
  363.         int i;
  364.         byte *front, *back;
  365.  
  366. #ifdef RSAREF
  367.         make_RSA_PUBLIC_KEY(&PubKey, E, N);
  368.         blocksize = countbytes(inbuf);
  369.         reg2rsaref((byte *)temp, blocksize, inbuf);
  370.         RSAPublicBlock((byte *)temp, &blocksize,
  371.                            (byte *)temp, blocksize, &PubKey);
  372.  
  373.         front = (byte *)temp;                   /* The start of the block */
  374.         back = front + blocksize;               /* The end */
  375.         i = blocksize - countbytes(N) + 1;      /* Expected leading 0's */
  376. #else
  377.         i = mp_modexp(temp, inbuf, E, N);
  378.         if (i < 0) {
  379.                 mp_burn(temp);
  380.                 return i;
  381.         }
  382.         mp_convert_order((byte *)temp);
  383.         blocksize = countbytes(N) - 1;
  384.         front = (byte *)temp;                   /* Points to start of block */
  385.         i = units2bytes(global_precision);
  386.         back = front + i;                       /* Points to end of block */
  387.         i -= countbytes(N) - 1;                 /* Expected leading 0's */
  388. #endif
  389.  
  390.         /* This could be stricter, but the length returned by the RSAREF code
  391.            is not documented too well. */
  392.         if (i < 0)
  393.                 goto ErrorReturn;
  394.         while (i--)             /* Any excess should be 0 */
  395.                 if (*front++)
  396.                         goto ErrorReturn;
  397.         /* front now points to the data */
  398.  
  399.         /* How to distinguish old PGP from PKCS formats.
  400.          * The old PGP format ends in a trailing type byte, with
  401.          * all 1's padding before that.  The PKCS format ends in
  402.          * 16 bytes of message digest, preceded by an ASN string
  403.          * which is not all 1's.
  404.          */
  405.         if (back[-1] == MD_ENCRYPTED_BYTE &&
  406.             back[-17] == 0xff && back[-18] == 0xff) {
  407.                 /* Old PGP format: Padding is at the end */
  408.                 if (*--back != MD_ENCRYPTED_BYTE)
  409.                         goto ErrorReturn;
  410.                 if (*front++ != MD5_ALGORITHM_BYTE) {
  411.                         mp_burn(temp);
  412.                         return -2;
  413.                 }
  414.                 while (*--back == 0xff) /* Skip constant padding */
  415.                         ;
  416.                 if (*back)              /* It should end with a zero */
  417.                         goto ErrorReturn;
  418.         } else {
  419.                 /* PKCS format: padding at the beginning */
  420.                 if (*front++ != MD_ENCRYPTED_BYTE)
  421.                         goto ErrorReturn;
  422.                 while (*front++ == 0xff) /* Skip constant padding */
  423.                         ;
  424.                 if (front[-1])  /* First non-FF byte should be 0 */
  425.                         goto ErrorReturn;
  426.                 /* Then comes the ASN header */
  427.                 if (memcmp(front, asn_array, sizeof(asn_array))) {
  428.                         mp_burn(temp);
  429.                         return -2;
  430.                 }
  431.                 front += sizeof(asn_array);
  432. /* This is temporary - to be removed on release */
  433.                 if (back-front == 17 && *front == MD5_ALGORITHM_BYTE) {
  434.                         front++;
  435.                         fprintf(stderr, "PGP 2.2b signature bug!\n");
  436.                 }
  437.         }
  438. /* We're done - copy user data to outbuf */
  439.         if (back < front)
  440.                 goto ErrorReturn;
  441.         memcpy(outbuf, front, back-front);
  442.         mp_burn(temp);
  443.         return back-front;
  444. ErrorReturn:
  445.         mp_burn(temp);
  446.         return -1;
  447. } /* rsa_public_decrypt */
  448.  
  449. /* We expect to find random padding and an encryption key */
  450. int
  451. rsa_private_decrypt(byteptr outbuf, unitptr inbuf,
  452.          unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N)
  453. /* Decrypt an encryption key using a private key.  Returns the number of bytes
  454.  * extracted, or <0 on error.
  455.  * -1: Corrupted packet.
  456.  */
  457. {
  458. #ifdef RSAREF
  459.         R_RSA_PRIVATE_KEY PrivKey;
  460. #endif
  461.         unsigned int blocksize;
  462.         unit temp[MAX_UNIT_PRECISION];
  463.         unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION];
  464.         byte *front, *back;
  465.         int i;
  466.  
  467.         mp_move(temp,P);
  468.         mp_dec(temp);
  469.         mp_mod(DP,D,temp);
  470.         mp_move(temp,Q);
  471.         mp_dec(temp);
  472.         mp_mod(DQ,D,temp);
  473.  
  474. #ifdef RSAREF
  475.         make_RSA_PRIVATE_KEY(&PrivKey, E, D, P, Q, DP, DQ, U, N);
  476.         blocksize = countbytes(inbuf);
  477.         reg2rsaref((byte *)temp, blocksize, inbuf);
  478.         i = RSAPrivateBlock((byte *)temp, &blocksize,
  479.                             (byte *)temp, blocksize, &PrivKey);
  480.         if (i < 0)
  481.                 goto ErrorReturn;
  482.         front = (byte *)temp;                   /* Start of block */
  483.         back = front + blocksize;               /* End of block */
  484.         i = blocksize - countbytes(N) + 1;      /* Expected # of leading 0's */
  485. #else
  486.         i = mp_modexp_crt(temp, inbuf, P, Q, DP, DQ, U);
  487.         if (i < 0)
  488.                 goto ErrorReturn;
  489.         mp_convert_order((byte *)temp);
  490.         front = (byte *)temp;                   /* Start of block */
  491.         i = units2bytes(global_precision);
  492.         back = (byte *)front + i;               /* End of block */
  493.         blocksize = countbytes(N) - 1;
  494.         i -= blocksize;                         /* Expected # of leading 0's */
  495. #endif
  496.         if (i < 0)                              /* This shouldn't happen */
  497.                 goto ErrorReturn;
  498.         while (i--)                             /* Extra bytes should be 0 */
  499.                 if (*front++)
  500.                         goto ErrorReturn;
  501.  
  502.         /* How to distinguish old PGP from PKCS formats.
  503.          * PGP packets have a trailing type byte (CK_ENCRYPTED_BYTE),
  504.          * while PKCS formats have it leading.
  505.          */
  506.         if (front[0] != CK_ENCRYPTED_BYTE && back[-1] == CK_ENCRYPTED_BYTE) {
  507.                 /* PGP 2.0 format  - padding at the end */
  508.                 if (back[-1] != CK_ENCRYPTED_BYTE)
  509.                         goto ErrorReturn;
  510.                 while (*--back) /* Skip non-zero random padding */
  511.                         ;
  512.         } else {
  513.                 /* PKCS format - padding at the beginning */
  514.                 if (*front++ != CK_ENCRYPTED_BYTE)
  515.                         goto ErrorReturn;
  516.                 while (*front++)        /* Skip non-zero random padding */
  517.                         ;
  518.         }
  519.         if (back < front)
  520.                 goto ErrorReturn;
  521.         memcpy(outbuf, front, back-front);
  522.         mp_burn(temp);
  523.         mp_burn(DP);
  524.         mp_burn(DQ);
  525.         return back-front;
  526.  
  527. ErrorReturn:
  528.         mp_burn(temp);
  529.         mp_burn(DP);
  530.         mp_burn(DQ);
  531.         return -1;
  532. } /* rsa_private_decrypt */
  533.