ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rsa.c
Go to the documentation of this file.
00001 /*
00002  * dlls/rsaenh/rsa.c
00003  * RSA public key cryptographic functions
00004  *
00005  * Copyright 2004 Michael Jung
00006  * Based on public domain code by Tom St Denis (tomstdenis@iahu.ca)
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00021  */
00022 
00023 /*
00024  * This file contains code from the LibTomCrypt cryptographic 
00025  * library written by Tom St Denis (tomstdenis@iahu.ca). LibTomCrypt
00026  * is in the public domain. The code in this file is tailored to
00027  * special requirements. Take a look at http://libtomcrypt.org for the
00028  * original version. 
00029  */
00030 
00031 #include "tomcrypt.h"
00032 
00033 static const struct {
00034     int mpi_code, ltc_code;
00035 } mpi_to_ltc_codes[] = {
00036    { MP_OKAY ,  CRYPT_OK},
00037    { MP_MEM  ,  CRYPT_MEM},
00038    { MP_VAL  ,  CRYPT_INVALID_ARG},
00039 };
00040 
00041 /* convert a MPI error to a LTC error (Possibly the most powerful function ever!  Oh wait... no) */
00042 static int mpi_to_ltc_error(int err)
00043 {
00044    int x;
00045 
00046    for (x = 0; x < (int)(sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0])); x++) {
00047        if (err == mpi_to_ltc_codes[x].mpi_code) { 
00048           return mpi_to_ltc_codes[x].ltc_code;
00049        }
00050    }
00051    return CRYPT_ERROR;
00052 }
00053 
00054 extern int gen_rand_impl(unsigned char *dst, unsigned int len);
00055 
00056 static int rand_prime_helper(unsigned char *dst, int len, void *dat)
00057 {
00058     return gen_rand_impl(dst, len) ? len : 0;
00059 }
00060 
00061 static int rand_prime(mp_int *N, long len)
00062 {
00063    int type;
00064 
00065    /* get type */
00066    if (len < 0) {
00067       type = LTM_PRIME_BBS;
00068       len = -len;
00069    } else {
00070       /* This seems to be what MS CSP's do: */
00071       type = LTM_PRIME_2MSB_ON;
00072       /* Original LibTomCrypt: type = 0; */
00073    }
00074 
00075    /* allow sizes between 2 and 256 bytes for a prime size */
00076    if (len < 16 || len > 8192) {
00077       printf("Invalid prime size!\n");
00078       return CRYPT_INVALID_PRIME_SIZE;
00079    }
00080    
00081    /* New prime generation makes the code even more cryptoish-insane.  Do you know what this means!!!
00082       -- Gir:  Yeah, oh wait, er, no.
00083     */
00084    return mpi_to_ltc_error(mp_prime_random_ex(N, mp_prime_rabin_miller_trials(len), len, type, rand_prime_helper, NULL));
00085 }
00086       
00087 int rsa_make_key(int size, long e, rsa_key *key)
00088 {
00089    mp_int p, q, tmp1, tmp2, tmp3;
00090    int    err;
00091 
00092    if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) {
00093       return CRYPT_INVALID_KEYSIZE;
00094    }
00095 
00096    if ((e < 3) || ((e & 1) == 0)) {
00097       return CRYPT_INVALID_ARG;
00098    }
00099 
00100    if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY) {
00101       return mpi_to_ltc_error(err);
00102    }
00103 
00104     /* make primes p and q (optimization provided by Wayne Scott) */
00105    if ((err = mp_set_int(&tmp3, e)) != MP_OKAY) { goto error; }            /* tmp3 = e */
00106 
00107     /* make prime "p" */
00108    do {
00109        if ((err = rand_prime(&p, size*4)) != CRYPT_OK) { goto done; }
00110        if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY)               { goto error; }  /* tmp1 = p-1 */
00111        if ((err = mp_gcd(&tmp1, &tmp3, &tmp2)) != MP_OKAY)          { goto error; }  /* tmp2 = gcd(p-1, e) */
00112    } while (mp_cmp_d(&tmp2, 1) != 0);                                                /* while e divides p-1 */
00113 
00114    /* make prime "q" */
00115    do {
00116        if ((err = rand_prime(&q, size*4)) != CRYPT_OK) { goto done; }
00117        if ((err = mp_sub_d(&q, 1, &tmp1)) != MP_OKAY)               { goto error; } /* tmp1 = q-1 */
00118        if ((err = mp_gcd(&tmp1, &tmp3, &tmp2)) != MP_OKAY)          { goto error; } /* tmp2 = gcd(q-1, e) */
00119    } while (mp_cmp_d(&tmp2, 1) != 0);                                               /* while e divides q-1 */
00120 
00121    /* tmp1 = lcm(p-1, q-1) */
00122    if ((err = mp_sub_d(&p, 1, &tmp2)) != MP_OKAY)                  { goto error; } /* tmp2 = p-1 */
00123                                                                    /* tmp1 = q-1 (previous do/while loop) */
00124    if ((err = mp_lcm(&tmp1, &tmp2, &tmp1)) != MP_OKAY)             { goto error; } /* tmp1 = lcm(p-1, q-1) */
00125 
00126    /* make key */
00127    if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP,
00128                      &key->qP, &key->p, &key->q, NULL)) != MP_OKAY) {
00129       goto error;
00130    }
00131 
00132    if ((err = mp_set_int(&key->e, e)) != MP_OKAY)                     { goto error2; } /* key->e =  e */
00133    if ((err = mp_invmod(&key->e, &tmp1, &key->d)) != MP_OKAY)         { goto error2; } /* key->d = 1/e mod lcm(p-1,q-1) */
00134    if ((err = mp_mul(&p, &q, &key->N)) != MP_OKAY)                    { goto error2; } /* key->N = pq */
00135 
00136    /* optimize for CRT now */
00137    /* find d mod q-1 and d mod p-1 */
00138    if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY)                     { goto error2; } /* tmp1 = q-1 */
00139    if ((err = mp_sub_d(&q, 1, &tmp2)) != MP_OKAY)                     { goto error2; } /* tmp2 = p-1 */
00140    if ((err = mp_mod(&key->d, &tmp1, &key->dP)) != MP_OKAY)           { goto error2; } /* dP = d mod p-1 */
00141    if ((err = mp_mod(&key->d, &tmp2, &key->dQ)) != MP_OKAY)           { goto error2; } /* dQ = d mod q-1 */
00142    if ((err = mp_invmod(&q, &p, &key->qP)) != MP_OKAY)                { goto error2; } /* qP = 1/q mod p */
00143 
00144    if ((err = mp_copy(&p, &key->p)) != MP_OKAY)                       { goto error2; }
00145    if ((err = mp_copy(&q, &key->q)) != MP_OKAY)                       { goto error2; }
00146 
00147    /* shrink ram required  */
00148    if ((err = mp_shrink(&key->e)) != MP_OKAY)                         { goto error2; }
00149    if ((err = mp_shrink(&key->d)) != MP_OKAY)                         { goto error2; }
00150    if ((err = mp_shrink(&key->N)) != MP_OKAY)                         { goto error2; }
00151    if ((err = mp_shrink(&key->dQ)) != MP_OKAY)                        { goto error2; }
00152    if ((err = mp_shrink(&key->dP)) != MP_OKAY)                        { goto error2; }
00153    if ((err = mp_shrink(&key->qP)) != MP_OKAY)                        { goto error2; }
00154    if ((err = mp_shrink(&key->p)) != MP_OKAY)                         { goto error2; }
00155    if ((err = mp_shrink(&key->q)) != MP_OKAY)                         { goto error2; }
00156 
00157    /* set key type (in this case it's CRT optimized) */
00158    key->type = PK_PRIVATE;
00159 
00160    /* return ok and free temps */
00161    err       = CRYPT_OK;
00162    goto done;
00163 error2:
00164    mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,
00165                   &key->qP, &key->p, &key->q, NULL);
00166 error:
00167    err = mpi_to_ltc_error(err);
00168 done:
00169    mp_clear_multi(&tmp3, &tmp2, &tmp1, &p, &q, NULL);
00170    return err;
00171 }
00172 
00173 void rsa_free(rsa_key *key)
00174 {
00175    mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP,
00176                   &key->qP, &key->p, &key->q, NULL);
00177 }
00178 
00179 /* compute an RSA modular exponentiation */
00180 int rsa_exptmod(const unsigned char *in,   unsigned long inlen,
00181                       unsigned char *out,  unsigned long *outlen, int which,
00182                       rsa_key *key)
00183 {
00184    mp_int        tmp, tmpa, tmpb;
00185    unsigned long x;
00186    int           err;
00187 
00188    /* is the key of the right type for the operation? */
00189    if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {
00190       return CRYPT_PK_NOT_PRIVATE;
00191    }
00192 
00193    /* must be a private or public operation */
00194    if (which != PK_PRIVATE && which != PK_PUBLIC) {
00195       return CRYPT_PK_INVALID_TYPE;
00196    }
00197 
00198    /* init and copy into tmp */
00199    if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != MP_OKAY)    { return mpi_to_ltc_error(err); }
00200    if ((err = mp_read_unsigned_bin(&tmp, in, (int)inlen)) != MP_OKAY) { goto error; }
00201 
00202    /* sanity check on the input */
00203    if (mp_cmp(&key->N, &tmp) == MP_LT) {
00204       err = CRYPT_PK_INVALID_SIZE;
00205       goto done;
00206    }
00207 
00208    /* are we using the private exponent and is the key optimized? */
00209    if (which == PK_PRIVATE) {
00210       /* tmpa = tmp^dP mod p */
00211       if ((err = mpi_to_ltc_error(mp_exptmod(&tmp, &key->dP, &key->p, &tmpa))) != MP_OKAY)    { goto error; }
00212       
00213       /* tmpb = tmp^dQ mod q */
00214       if ((err = mpi_to_ltc_error(mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb))) != MP_OKAY)    { goto error; }
00215 
00216       /* tmp = (tmpa - tmpb) * qInv (mod p) */
00217       if ((err = mp_sub(&tmpa, &tmpb, &tmp)) != MP_OKAY)                    { goto error; }
00218       if ((err = mp_mulmod(&tmp, &key->qP, &key->p, &tmp)) != MP_OKAY)      { goto error; }
00219 
00220       /* tmp = tmpb + q * tmp */
00221       if ((err = mp_mul(&tmp, &key->q, &tmp)) != MP_OKAY)                   { goto error; }
00222       if ((err = mp_add(&tmp, &tmpb, &tmp)) != MP_OKAY)                     { goto error; }
00223    } else {
00224       /* exptmod it */
00225       if ((err = mp_exptmod(&tmp, &key->e, &key->N, &tmp)) != MP_OKAY) { goto error; }
00226    }
00227 
00228    /* read it back */
00229    x = (unsigned long)mp_unsigned_bin_size(&key->N);
00230    if (x > *outlen) {
00231       err = CRYPT_BUFFER_OVERFLOW;
00232       goto done;
00233    }
00234    *outlen = x;
00235 
00236    /* convert it */
00237    memset(out, 0, x);
00238    if ((err = mp_to_unsigned_bin(&tmp, out+(x-mp_unsigned_bin_size(&tmp)))) != MP_OKAY) { goto error; }
00239 
00240    /* clean up and return */
00241    err = CRYPT_OK;
00242    goto done;
00243 error:
00244    err = mpi_to_ltc_error(err);
00245 done:
00246    mp_clear_multi(&tmp, &tmpa, &tmpb, NULL);
00247    return err;
00248 }

Generated on Fri May 25 2012 04:24:17 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.