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