Path: blob/master/libs/tomcrypt/src/pk/rsa/rsa_exptmod.c
4396 views
/* LibTomCrypt, modular cryptographic library -- Tom St Denis1*2* LibTomCrypt is a library that provides various cryptographic3* algorithms in a highly modular and flexible manner.4*5* The library is free for all purposes without any express6* guarantee it works.7*/8#include "tomcrypt.h"910/**11@file rsa_exptmod.c12RSA PKCS exptmod, Tom St Denis13Added RSA blinding --nmav14*/1516#ifdef LTC_MRSA1718/**19Compute an RSA modular exponentiation20@param in The input data to send into RSA21@param inlen The length of the input (octets)22@param out [out] The destination23@param outlen [in/out] The max size and resulting size of the output24@param which Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC25@param key The RSA key to use26@return CRYPT_OK if successful27*/28int rsa_exptmod(const unsigned char *in, unsigned long inlen,29unsigned char *out, unsigned long *outlen, int which,30rsa_key *key)31{32void *tmp, *tmpa, *tmpb;33#ifdef LTC_RSA_BLINDING34void *rnd, *rndi /* inverse of rnd */;35#endif36unsigned long x;37int err, has_crt_parameters;3839LTC_ARGCHK(in != NULL);40LTC_ARGCHK(out != NULL);41LTC_ARGCHK(outlen != NULL);42LTC_ARGCHK(key != NULL);4344/* is the key of the right type for the operation? */45if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {46return CRYPT_PK_NOT_PRIVATE;47}4849/* must be a private or public operation */50if (which != PK_PRIVATE && which != PK_PUBLIC) {51return CRYPT_PK_INVALID_TYPE;52}5354/* init and copy into tmp */55if ((err = mp_init_multi(&tmp, &tmpa, &tmpb,56#ifdef LTC_RSA_BLINDING57&rnd, &rndi,58#endif /* LTC_RSA_BLINDING */59NULL)) != CRYPT_OK)60{ return err; }61if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK)62{ goto error; }636465/* sanity check on the input */66if (mp_cmp(key->N, tmp) == LTC_MP_LT) {67err = CRYPT_PK_INVALID_SIZE;68goto error;69}7071/* are we using the private exponent and is the key optimized? */72if (which == PK_PRIVATE) {73#ifdef LTC_RSA_BLINDING74/* do blinding */75err = mp_rand(rnd, mp_get_digit_count(key->N));76if (err != CRYPT_OK) {77goto error;78}7980/* rndi = 1/rnd mod N */81err = mp_invmod(rnd, key->N, rndi);82if (err != CRYPT_OK) {83goto error;84}8586/* rnd = rnd^e */87err = mp_exptmod( rnd, key->e, key->N, rnd);88if (err != CRYPT_OK) {89goto error;90}9192/* tmp = tmp*rnd mod N */93err = mp_mulmod( tmp, rnd, key->N, tmp);94if (err != CRYPT_OK) {95goto error;96}97#endif /* LTC_RSA_BLINDING */9899has_crt_parameters = (key->p != NULL) && (mp_get_digit_count(key->p) != 0) &&100(key->q != NULL) && (mp_get_digit_count(key->q) != 0) &&101(key->dP != NULL) && (mp_get_digit_count(key->dP) != 0) &&102(key->dQ != NULL) && (mp_get_digit_count(key->dQ) != 0) &&103(key->qP != NULL) && (mp_get_digit_count(key->qP) != 0);104105if (!has_crt_parameters) {106/*107* In case CRT optimization parameters are not provided,108* the private key is directly used to exptmod it109*/110if ((err = mp_exptmod(tmp, key->d, key->N, tmp)) != CRYPT_OK) { goto error; }111} else {112/* tmpa = tmp^dP mod p */113if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK) { goto error; }114115/* tmpb = tmp^dQ mod q */116if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK) { goto error; }117118/* tmp = (tmpa - tmpb) * qInv (mod p) */119if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK) { goto error; }120if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK) { goto error; }121122/* tmp = tmpb + q * tmp */123if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK) { goto error; }124if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK) { goto error; }125}126127#ifdef LTC_RSA_BLINDING128/* unblind */129err = mp_mulmod( tmp, rndi, key->N, tmp);130if (err != CRYPT_OK) {131goto error;132}133#endif134135#ifdef LTC_RSA_CRT_HARDENING136if (has_crt_parameters) {137if ((err = mp_exptmod(tmp, key->e, key->N, tmpa)) != CRYPT_OK) { goto error; }138if ((err = mp_read_unsigned_bin(tmpb, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto error; }139if (mp_cmp(tmpa, tmpb) != LTC_MP_EQ) { err = CRYPT_ERROR; goto error; }140}141#endif142} else {143/* exptmod it */144if ((err = mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK) { goto error; }145}146147/* read it back */148x = (unsigned long)mp_unsigned_bin_size(key->N);149if (x > *outlen) {150*outlen = x;151err = CRYPT_BUFFER_OVERFLOW;152goto error;153}154155/* this should never happen ... */156if (mp_unsigned_bin_size(tmp) > mp_unsigned_bin_size(key->N)) {157err = CRYPT_ERROR;158goto error;159}160*outlen = x;161162/* convert it */163zeromem(out, x);164if ((err = mp_to_unsigned_bin(tmp, out+(x-mp_unsigned_bin_size(tmp)))) != CRYPT_OK) { goto error; }165166/* clean up and return */167err = CRYPT_OK;168error:169mp_clear_multi(170#ifdef LTC_RSA_BLINDING171rndi, rnd,172#endif /* LTC_RSA_BLINDING */173tmpb, tmpa, tmp, NULL);174return err;175}176177#endif178179180