X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2Frsa%2Frsa_eay.c;h=cafdc419e26556bff814c2f48e6dacab0e74ea72;hb=27f3a1bd9ced7c72046755b227a5b35d66ef3606;hp=7623189e41a3afbe52699085df5fe44153f853e0;hpb=31b8d8684441e6cd5138832bb1b2ddb10acd6ba6;p=oweals%2Fopenssl.git diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c index 7623189e41..cafdc419e2 100644 --- a/crypto/rsa/rsa_eay.c +++ b/crypto/rsa/rsa_eay.c @@ -58,11 +58,12 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "rsa.h" -#include "rand.h" +#include +#include +#include + +#ifndef RSA_NULL -#ifndef NOPROTO static int RSA_eay_public_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa,int padding); static int RSA_eay_private_encrypt(int flen, unsigned char *from, @@ -74,21 +75,11 @@ static int RSA_eay_private_decrypt(int flen, unsigned char *from, static int RSA_eay_mod_exp(BIGNUM *r0, BIGNUM *i, RSA *rsa); static int RSA_eay_init(RSA *rsa); static int RSA_eay_finish(RSA *rsa); -#else -static int RSA_eay_public_encrypt(); -static int RSA_eay_private_encrypt(); -static int RSA_eay_public_decrypt(); -static int RSA_eay_private_decrypt(); -static int RSA_eay_mod_exp(); -static int RSA_eay_init(); -static int RSA_eay_finish(); -#endif - static RSA_METHOD rsa_pkcs1_eay_meth={ "Eric Young's PKCS#1 RSA", RSA_eay_public_encrypt, - RSA_eay_public_decrypt, - RSA_eay_private_encrypt, + RSA_eay_public_decrypt, /* signature verification */ + RSA_eay_private_encrypt, /* signing */ RSA_eay_private_decrypt, RSA_eay_mod_exp, BN_mod_exp_mont, @@ -98,17 +89,13 @@ static RSA_METHOD rsa_pkcs1_eay_meth={ NULL, }; -RSA_METHOD *RSA_PKCS1_SSLeay() +RSA_METHOD *RSA_PKCS1_SSLeay(void) { return(&rsa_pkcs1_eay_meth); } -static int RSA_eay_public_encrypt(flen, from, to, rsa, padding) -int flen; -unsigned char *from; -unsigned char *to; -RSA *rsa; -int padding; +static int RSA_eay_public_encrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding) { BIGNUM f,ret; int i,j,k,num=0,r= -1; @@ -119,7 +106,7 @@ int padding; BN_init(&ret); if ((ctx=BN_CTX_new()) == NULL) goto err; num=BN_num_bytes(rsa->n); - if ((buf=(unsigned char *)Malloc(num)) == NULL) + if ((buf=(unsigned char *)OPENSSL_malloc(num)) == NULL) { RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,ERR_R_MALLOC_FAILURE); goto err; @@ -130,6 +117,11 @@ int padding; case RSA_PKCS1_PADDING: i=RSA_padding_add_PKCS1_type_2(buf,num,from,flen); break; +#ifndef NO_SHA + case RSA_PKCS1_OAEP_PADDING: + i=RSA_padding_add_PKCS1_OAEP(buf,num,from,flen,NULL,0); + break; +#endif case RSA_SSLV23_PADDING: i=RSA_padding_add_SSLv23(buf,num,from,flen); break; @@ -144,15 +136,39 @@ int padding; if (BN_bin2bn(buf,num,&f) == NULL) goto err; - if ((rsa->method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC)) - { - if ((rsa->method_mod_n=(char *)BN_MONT_CTX_new()) != NULL) - if (!BN_MONT_CTX_set((BN_MONT_CTX *)rsa->method_mod_n, - rsa->n,ctx)) goto err; + if (BN_ucmp(&f, rsa->n) >= 0) + { + /* usually the padding functions would catch this */ + RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; } + if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC)) + { + BN_MONT_CTX* bn_mont_ctx; + if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx)) + { + BN_MONT_CTX_free(bn_mont_ctx); + goto err; + } + if (rsa->_method_mod_n == NULL) /* other thread may have finished first */ + { + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + if (rsa->_method_mod_n == NULL) + { + rsa->_method_mod_n = bn_mont_ctx; + bn_mont_ctx = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_RSA); + } + if (bn_mont_ctx) + BN_MONT_CTX_free(bn_mont_ctx); + } + if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx, - rsa->method_mod_n)) goto err; + rsa->_method_mod_n)) goto err; /* put in leading 0 bytes if the number is less than the * length of the modulus */ @@ -169,17 +185,14 @@ err: if (buf != NULL) { memset(buf,0,num); - Free(buf); + OPENSSL_free(buf); } return(r); } -static int RSA_eay_private_encrypt(flen, from, to, rsa, padding) -int flen; -unsigned char *from; -unsigned char *to; -RSA *rsa; -int padding; +/* signing */ +static int RSA_eay_private_encrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding) { BIGNUM f,ret; int i,j,k,num=0,r= -1; @@ -191,7 +204,7 @@ int padding; if ((ctx=BN_CTX_new()) == NULL) goto err; num=BN_num_bytes(rsa->n); - if ((buf=(unsigned char *)Malloc(num)) == NULL) + if ((buf=(unsigned char *)OPENSSL_malloc(num)) == NULL) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,ERR_R_MALLOC_FAILURE); goto err; @@ -213,17 +226,25 @@ int padding; if (i <= 0) goto err; if (BN_bin2bn(buf,num,&f) == NULL) goto err; + + if (BN_ucmp(&f, rsa->n) >= 0) + { + /* usually the padding functions would catch this */ + RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } if ((rsa->flags & RSA_FLAG_BLINDING) && (rsa->blinding == NULL)) RSA_blinding_on(rsa,ctx); if (rsa->flags & RSA_FLAG_BLINDING) if (!BN_BLINDING_convert(&f,rsa->blinding,ctx)) goto err; - if ( (rsa->p != NULL) && + if ( (rsa->flags & RSA_FLAG_EXT_PKEY) || + ((rsa->p != NULL) && (rsa->q != NULL) && (rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && - (rsa->iqmp != NULL)) + (rsa->iqmp != NULL)) ) { if (!rsa->meth->rsa_mod_exp(&ret,&f,rsa)) goto err; } else { @@ -248,17 +269,13 @@ err: if (buf != NULL) { memset(buf,0,num); - Free(buf); + OPENSSL_free(buf); } return(r); } -static int RSA_eay_private_decrypt(flen, from, to, rsa,padding) -int flen; -unsigned char *from; -unsigned char *to; -RSA *rsa; -int padding; +static int RSA_eay_private_decrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding) { BIGNUM f,ret; int j,num=0,r= -1; @@ -273,13 +290,13 @@ int padding; num=BN_num_bytes(rsa->n); - if ((buf=(unsigned char *)Malloc(num)) == NULL) + if ((buf=(unsigned char *)OPENSSL_malloc(num)) == NULL) { RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,ERR_R_MALLOC_FAILURE); goto err; } - /* This check was for equallity but PGP does evil things + /* This check was for equality but PGP does evil things * and chops off the top '0' bytes */ if (flen > num) { @@ -290,17 +307,24 @@ int padding; /* make data into a big number */ if (BN_bin2bn(from,(int)flen,&f) == NULL) goto err; + if (BN_ucmp(&f, rsa->n) >= 0) + { + RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + if ((rsa->flags & RSA_FLAG_BLINDING) && (rsa->blinding == NULL)) RSA_blinding_on(rsa,ctx); if (rsa->flags & RSA_FLAG_BLINDING) if (!BN_BLINDING_convert(&f,rsa->blinding,ctx)) goto err; /* do the decrypt */ - if ( (rsa->p != NULL) && + if ( (rsa->flags & RSA_FLAG_EXT_PKEY) || + ((rsa->p != NULL) && (rsa->q != NULL) && (rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && - (rsa->iqmp != NULL)) + (rsa->iqmp != NULL)) ) { if (!rsa->meth->rsa_mod_exp(&ret,&f,rsa)) goto err; } else { @@ -319,7 +343,12 @@ int padding; case RSA_PKCS1_PADDING: r=RSA_padding_check_PKCS1_type_2(to,num,buf,j,num); break; - case RSA_SSLV23_PADDING: +#ifndef NO_SHA + case RSA_PKCS1_OAEP_PADDING: + r=RSA_padding_check_PKCS1_OAEP(to,num,buf,j,num,NULL,0); + break; +#endif + case RSA_SSLV23_PADDING: r=RSA_padding_check_SSLv23(to,num,buf,j,num); break; case RSA_NO_PADDING: @@ -339,17 +368,14 @@ err: if (buf != NULL) { memset(buf,0,num); - Free(buf); + OPENSSL_free(buf); } return(r); } -static int RSA_eay_public_decrypt(flen, from, to, rsa, padding) -int flen; -unsigned char *from; -unsigned char *to; -RSA *rsa; -int padding; +/* signature verification */ +static int RSA_eay_public_decrypt(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding) { BIGNUM f,ret; int i,num=0,r= -1; @@ -363,14 +389,14 @@ int padding; if (ctx == NULL) goto err; num=BN_num_bytes(rsa->n); - buf=(unsigned char *)Malloc(num); + buf=(unsigned char *)OPENSSL_malloc(num); if (buf == NULL) { RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,ERR_R_MALLOC_FAILURE); goto err; } - /* This check was for equallity but PGP does evil things + /* This check was for equality but PGP does evil things * and chops off the top '0' bytes */ if (flen > num) { @@ -379,16 +405,40 @@ int padding; } if (BN_bin2bn(from,flen,&f) == NULL) goto err; - /* do the decrypt */ - if ((rsa->method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC)) + + if (BN_ucmp(&f, rsa->n) >= 0) { - if ((rsa->method_mod_n=(char *)BN_MONT_CTX_new()) != NULL) - if (!BN_MONT_CTX_set((BN_MONT_CTX *)rsa->method_mod_n, - rsa->n,ctx)) goto err; + RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; } + /* do the decrypt */ + if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC)) + { + BN_MONT_CTX* bn_mont_ctx; + if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx)) + { + BN_MONT_CTX_free(bn_mont_ctx); + goto err; + } + if (rsa->_method_mod_n == NULL) /* other thread may have finished first */ + { + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + if (rsa->_method_mod_n == NULL) + { + rsa->_method_mod_n = bn_mont_ctx; + bn_mont_ctx = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_RSA); + } + if (bn_mont_ctx) + BN_MONT_CTX_free(bn_mont_ctx); + } + if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx, - rsa->method_mod_n)) goto err; + rsa->_method_mod_n)) goto err; p=buf; i=BN_bn2bin(&ret,p); @@ -415,51 +465,80 @@ err: if (buf != NULL) { memset(buf,0,num); - Free(buf); + OPENSSL_free(buf); } return(r); } -static int RSA_eay_mod_exp(r0, I, rsa) -BIGNUM *r0; -BIGNUM *I; -RSA *rsa; +static int RSA_eay_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa) { - BIGNUM r1,m1; + BIGNUM r1,m1,vrfy; int ret=0; BN_CTX *ctx; if ((ctx=BN_CTX_new()) == NULL) goto err; BN_init(&m1); BN_init(&r1); + BN_init(&vrfy); if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) { - if (rsa->method_mod_p == NULL) + if (rsa->_method_mod_p == NULL) { - if ((rsa->method_mod_p=(char *) - BN_MONT_CTX_new()) != NULL) - if (!BN_MONT_CTX_set((BN_MONT_CTX *) - rsa->method_mod_p,rsa->p,ctx)) - goto err; + BN_MONT_CTX* bn_mont_ctx; + if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->p,ctx)) + { + BN_MONT_CTX_free(bn_mont_ctx); + goto err; + } + if (rsa->_method_mod_p == NULL) /* other thread may have finished first */ + { + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + if (rsa->_method_mod_p == NULL) + { + rsa->_method_mod_p = bn_mont_ctx; + bn_mont_ctx = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_RSA); + } + if (bn_mont_ctx) + BN_MONT_CTX_free(bn_mont_ctx); } - if (rsa->method_mod_q == NULL) + + if (rsa->_method_mod_q == NULL) { - if ((rsa->method_mod_q=(char *) - BN_MONT_CTX_new()) != NULL) - if (!BN_MONT_CTX_set((BN_MONT_CTX *) - rsa->method_mod_q,rsa->q,ctx)) - goto err; + BN_MONT_CTX* bn_mont_ctx; + if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->q,ctx)) + { + BN_MONT_CTX_free(bn_mont_ctx); + goto err; + } + if (rsa->_method_mod_q == NULL) /* other thread may have finished first */ + { + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + if (rsa->_method_mod_q == NULL) + { + rsa->_method_mod_q = bn_mont_ctx; + bn_mont_ctx = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_RSA); + } + if (bn_mont_ctx) + BN_MONT_CTX_free(bn_mont_ctx); } } - + if (!BN_mod(&r1,I,rsa->q,ctx)) goto err; if (!rsa->meth->bn_mod_exp(&m1,&r1,rsa->dmq1,rsa->q,ctx, - rsa->method_mod_q)) goto err; + rsa->_method_mod_q)) goto err; if (!BN_mod(&r1,I,rsa->p,ctx)) goto err; if (!rsa->meth->bn_mod_exp(r0,&r1,rsa->dmp1,rsa->p,ctx, - rsa->method_mod_p)) goto err; + rsa->_method_mod_p)) goto err; if (!BN_sub(r0,r0,&m1)) goto err; /* This will help stop the size of r0 increasing, which does @@ -469,34 +548,50 @@ RSA *rsa; if (!BN_mul(&r1,r0,rsa->iqmp,ctx)) goto err; if (!BN_mod(r0,&r1,rsa->p,ctx)) goto err; + /* If p < q it is occasionally possible for the correction of + * adding 'p' if r0 is negative above to leave the result still + * negative. This can break the private key operations: the following + * second correction should *always* correct this rare occurrence. + * This will *never* happen with OpenSSL generated keys because + * they ensure p > q [steve] + */ + if (r0->neg) + if (!BN_add(r0,r0,rsa->p)) goto err; if (!BN_mul(&r1,r0,rsa->q,ctx)) goto err; if (!BN_add(r0,&r1,&m1)) goto err; + if (rsa->e && rsa->n) + { + if (!rsa->meth->bn_mod_exp(&vrfy,r0,rsa->e,rsa->n,ctx,NULL)) goto err; + if (BN_cmp(I, &vrfy) != 0) + { + if (!rsa->meth->bn_mod_exp(r0,I,rsa->d,rsa->n,ctx,NULL)) goto err; + } + } ret=1; err: BN_clear_free(&m1); BN_clear_free(&r1); + BN_clear_free(&vrfy); BN_CTX_free(ctx); return(ret); } -static int RSA_eay_init(rsa) -RSA *rsa; +static int RSA_eay_init(RSA *rsa) { rsa->flags|=RSA_FLAG_CACHE_PUBLIC|RSA_FLAG_CACHE_PRIVATE; return(1); } -static int RSA_eay_finish(rsa) -RSA *rsa; +static int RSA_eay_finish(RSA *rsa) { - if (rsa->method_mod_n != NULL) - BN_MONT_CTX_free((BN_MONT_CTX *)rsa->method_mod_n); - if (rsa->method_mod_p != NULL) - BN_MONT_CTX_free((BN_MONT_CTX *)rsa->method_mod_p); - if (rsa->method_mod_q != NULL) - BN_MONT_CTX_free((BN_MONT_CTX *)rsa->method_mod_q); + if (rsa->_method_mod_n != NULL) + BN_MONT_CTX_free(rsa->_method_mod_n); + if (rsa->_method_mod_p != NULL) + BN_MONT_CTX_free(rsa->_method_mod_p); + if (rsa->_method_mod_q != NULL) + BN_MONT_CTX_free(rsa->_method_mod_q); return(1); } - +#endif