Home | History | Annotate | Download | only in rsa
      1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
      2  *
      3  * LibTomCrypt is a library that provides various cryptographic
      4  * algorithms in a highly modular and flexible manner.
      5  *
      6  * The library is free for all purposes without any express
      7  * guarantee it works.
      8  *
      9  * Tom St Denis, tomstdenis (at) gmail.com, http://libtomcrypt.com
     10  */
     11 #include "tomcrypt.h"
     12 
     13 /**
     14   @file rsa_exptmod.c
     15   RSA PKCS exptmod, Tom St Denis
     16 */
     17 
     18 #ifdef MRSA
     19 
     20 /**
     21    Compute an RSA modular exponentiation
     22    @param in         The input data to send into RSA
     23    @param inlen      The length of the input (octets)
     24    @param out        [out] The destination
     25    @param outlen     [in/out] The max size and resulting size of the output
     26    @param which      Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC
     27    @param key        The RSA key to use
     28    @return CRYPT_OK if successful
     29 */
     30 int rsa_exptmod(const unsigned char *in,   unsigned long inlen,
     31                       unsigned char *out,  unsigned long *outlen, int which,
     32                       rsa_key *key)
     33 {
     34    void         *tmp, *tmpa, *tmpb;
     35    unsigned long x;
     36    int           err;
     37 
     38    LTC_ARGCHK(in     != NULL);
     39    LTC_ARGCHK(out    != NULL);
     40    LTC_ARGCHK(outlen != NULL);
     41    LTC_ARGCHK(key    != NULL);
     42 
     43    /* is the key of the right type for the operation? */
     44    if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {
     45       return CRYPT_PK_NOT_PRIVATE;
     46    }
     47 
     48    /* must be a private or public operation */
     49    if (which != PK_PRIVATE && which != PK_PUBLIC) {
     50       return CRYPT_PK_INVALID_TYPE;
     51    }
     52 
     53    /* init and copy into tmp */
     54    if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != CRYPT_OK)                                    { return err; }
     55    if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK)                 { goto error; }
     56 
     57    /* sanity check on the input */
     58    if (mp_cmp(key->N, tmp) == LTC_MP_LT) {
     59       err = CRYPT_PK_INVALID_SIZE;
     60       goto error;
     61    }
     62 
     63    /* are we using the private exponent and is the key optimized? */
     64    if (which == PK_PRIVATE) {
     65       /* tmpa = tmp^dP mod p */
     66       if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK)                               { goto error; }
     67 
     68       /* tmpb = tmp^dQ mod q */
     69       if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK)                               { goto error; }
     70 
     71       /* tmp = (tmpa - tmpb) * qInv (mod p) */
     72       if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK)                                              { goto error; }
     73       if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK)                                { goto error; }
     74 
     75       /* tmp = tmpb + q * tmp */
     76       if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK)                                             { goto error; }
     77       if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK)                                               { goto error; }
     78    } else {
     79       /* exptmod it */
     80       if ((err = mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK)                                { goto error; }
     81    }
     82 
     83    /* read it back */
     84    x = (unsigned long)mp_unsigned_bin_size(key->N);
     85    if (x > *outlen) {
     86       *outlen = x;
     87       err = CRYPT_BUFFER_OVERFLOW;
     88       goto error;
     89    }
     90 
     91    /* this should never happen ... */
     92    if (mp_unsigned_bin_size(tmp) > mp_unsigned_bin_size(key->N)) {
     93       err = CRYPT_ERROR;
     94       goto error;
     95    }
     96    *outlen = x;
     97 
     98    /* convert it */
     99    zeromem(out, x);
    100    if ((err = mp_to_unsigned_bin(tmp, out+(x-mp_unsigned_bin_size(tmp)))) != CRYPT_OK)               { goto error; }
    101 
    102    /* clean up and return */
    103    err = CRYPT_OK;
    104 error:
    105    mp_clear_multi(tmp, tmpa, tmpb, NULL);
    106    return err;
    107 }
    108 
    109 #endif
    110 
    111 /* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_exptmod.c,v $ */
    112 /* $Revision: 1.16 $ */
    113 /* $Date: 2006/12/04 03:09:28 $ */
    114