Add functions returning security bits.
[openssl.git] / crypto / rsa / rsa_eay.c
index c5eaeeae6bdd3825a8aadf6e0bd9c422e7150e5a..16f000ff48af7261940c3bd89d5265539d6f5769 100644 (file)
  *
  */
 
+#define OPENSSL_FIPSAPI
+
 #include <stdio.h>
 #include "cryptlib.h"
 #include <openssl/bn.h>
 #include <openssl/rsa.h>
 #include <openssl/rand.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
 
 #ifndef RSA_NULL
 
@@ -138,7 +143,7 @@ static RSA_METHOD rsa_pkcs1_eay_meth={
        BN_mod_exp_mont, /* XXX probably we should not use Montgomery if  e == 3 */
        RSA_eay_init,
        RSA_eay_finish,
-       0, /* flags */
+       RSA_FLAG_FIPS_METHOD, /* flags */
        NULL,
        0, /* rsa_sign */
        0, /* rsa_verify */
@@ -158,6 +163,21 @@ static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
        unsigned char *buf=NULL;
        BN_CTX *ctx=NULL;
 
+#ifdef OPENSSL_FIPS
+       if(FIPS_selftest_failed())
+               {
+               FIPSerr(FIPS_F_RSA_EAY_PUBLIC_ENCRYPT,FIPS_R_FIPS_SELFTEST_FAILED);
+               goto err;
+               }
+
+       if (FIPS_module_mode() && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)
+               && (BN_num_bits(rsa->n) < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS))
+               {
+               RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_KEY_SIZE_TOO_SMALL);
+               return -1;
+               }
+#endif
+
        if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS)
                {
                RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_MODULUS_TOO_LARGE);
@@ -314,51 +334,71 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
        return ret;
 }
 
-static int rsa_blinding_convert(BN_BLINDING *b, int local, BIGNUM *f,
-       BIGNUM *r, BN_CTX *ctx)
-{
-       if (local)
+static int rsa_blinding_convert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
+       BN_CTX *ctx)
+       {
+       if (unblind == NULL)
+               /* Local blinding: store the unblinding factor
+                * in BN_BLINDING. */
                return BN_BLINDING_convert_ex(f, NULL, b, ctx);
        else
                {
-               int ret;
-               CRYPTO_r_lock(CRYPTO_LOCK_RSA_BLINDING);
-               ret = BN_BLINDING_convert_ex(f, r, b, ctx);
-               CRYPTO_r_unlock(CRYPTO_LOCK_RSA_BLINDING);
-               return ret;
-               }
-}
-
-static int rsa_blinding_invert(BN_BLINDING *b, int local, BIGNUM *f,
-       BIGNUM *r, BN_CTX *ctx)
-{
-       if (local)
-               return BN_BLINDING_invert_ex(f, NULL, b, ctx);
-       else
-               {
+               /* Shared blinding: store the unblinding factor
+                * outside BN_BLINDING. */
                int ret;
                CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
-               ret = BN_BLINDING_invert_ex(f, r, b, ctx);
+               ret = BN_BLINDING_convert_ex(f, unblind, b, ctx);
                CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
                return ret;
                }
-}
+       }
+
+static int rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
+       BN_CTX *ctx)
+       {
+       /* For local blinding, unblind is set to NULL, and BN_BLINDING_invert_ex
+        * will use the unblinding factor stored in BN_BLINDING.
+        * If BN_BLINDING is shared between threads, unblind must be non-null:
+        * BN_BLINDING_invert_ex will then use the local unblinding factor,
+        * and will only read the modulus from BN_BLINDING.
+        * In both cases it's safe to access the blinding without a lock.
+        */
+       return BN_BLINDING_invert_ex(f, unblind, b, ctx);
+       }
 
 /* signing */
 static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
             unsigned char *to, RSA *rsa, int padding)
        {
-       BIGNUM *f, *ret, *br, *res;
+       BIGNUM *f, *ret, *res;
        int i,j,k,num=0,r= -1;
        unsigned char *buf=NULL;
        BN_CTX *ctx=NULL;
        int local_blinding = 0;
+       /* Used only if the blinding structure is shared. A non-NULL unblind
+        * instructs rsa_blinding_convert() and rsa_blinding_invert() to store
+        * the unblinding factor outside the blinding structure. */
+       BIGNUM *unblind = NULL;
        BN_BLINDING *blinding = NULL;
 
+#ifdef OPENSSL_FIPS
+       if(FIPS_selftest_failed())
+               {
+               FIPSerr(FIPS_F_RSA_EAY_PRIVATE_ENCRYPT,FIPS_R_FIPS_SELFTEST_FAILED);
+               goto err;
+               }
+
+       if (FIPS_module_mode() && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)
+               && (BN_num_bits(rsa->n) < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS))
+               {
+               RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_KEY_SIZE_TOO_SMALL);
+               return -1;
+               }
+#endif
+
        if ((ctx=BN_CTX_new()) == NULL) goto err;
        BN_CTX_start(ctx);
        f   = BN_CTX_get(ctx);
-       br  = BN_CTX_get(ctx);
        ret = BN_CTX_get(ctx);
        num = BN_num_bytes(rsa->n);
        buf = OPENSSL_malloc(num);
@@ -406,8 +446,15 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
                }
        
        if (blinding != NULL)
-               if (!rsa_blinding_convert(blinding, local_blinding, f, br, ctx))
+               {
+               if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL))
+                       {
+                       RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,ERR_R_MALLOC_FAILURE);
+                       goto err;
+                       }
+               if (!rsa_blinding_convert(blinding, f, unblind, ctx))
                        goto err;
+               }
 
        if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
                ((rsa->p != NULL) &&
@@ -441,7 +488,7 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
                }
 
        if (blinding)
-               if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx))
+               if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
                        goto err;
 
        if (padding == RSA_X931_PADDING)
@@ -480,18 +527,36 @@ err:
 static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
             unsigned char *to, RSA *rsa, int padding)
        {
-       BIGNUM *f, *ret, *br;
+       BIGNUM *f, *ret;
        int j,num=0,r= -1;
        unsigned char *p;
        unsigned char *buf=NULL;
        BN_CTX *ctx=NULL;
        int local_blinding = 0;
+       /* Used only if the blinding structure is shared. A non-NULL unblind
+        * instructs rsa_blinding_convert() and rsa_blinding_invert() to store
+        * the unblinding factor outside the blinding structure. */
+       BIGNUM *unblind = NULL;
        BN_BLINDING *blinding = NULL;
 
+#ifdef OPENSSL_FIPS
+       if(FIPS_selftest_failed())
+               {
+               FIPSerr(FIPS_F_RSA_EAY_PRIVATE_DECRYPT,FIPS_R_FIPS_SELFTEST_FAILED);
+               goto err;
+               }
+
+       if (FIPS_module_mode() && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)
+               && (BN_num_bits(rsa->n) < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS))
+               {
+               RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, RSA_R_KEY_SIZE_TOO_SMALL);
+               return -1;
+               }
+#endif
+
        if((ctx = BN_CTX_new()) == NULL) goto err;
        BN_CTX_start(ctx);
        f   = BN_CTX_get(ctx);
-       br  = BN_CTX_get(ctx);
        ret = BN_CTX_get(ctx);
        num = BN_num_bytes(rsa->n);
        buf = OPENSSL_malloc(num);
@@ -529,8 +594,15 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
                }
        
        if (blinding != NULL)
-               if (!rsa_blinding_convert(blinding, local_blinding, f, br, ctx))
+               {
+               if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL))
+                       {
+                       RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,ERR_R_MALLOC_FAILURE);
                        goto err;
+                       }
+               if (!rsa_blinding_convert(blinding, f, unblind, ctx))
+                       goto err;
+               }
 
        /* do the decrypt */
        if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
@@ -564,7 +636,7 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
                }
 
        if (blinding)
-               if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx))
+               if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
                        goto err;
 
        p=buf;
@@ -576,9 +648,9 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
                r=RSA_padding_check_PKCS1_type_2(to,num,buf,j,num);
                break;
 #ifndef OPENSSL_NO_SHA
-        case RSA_PKCS1_OAEP_PADDING:
+       case RSA_PKCS1_OAEP_PADDING:
                r=RSA_padding_check_PKCS1_OAEP(to,num,buf,j,num,NULL,0);
-                break;
+               break;
 #endif
        case RSA_SSLV23_PADDING:
                r=RSA_padding_check_SSLv23(to,num,buf,j,num);
@@ -617,6 +689,21 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from,
        unsigned char *buf=NULL;
        BN_CTX *ctx=NULL;
 
+#ifdef OPENSSL_FIPS
+       if(FIPS_selftest_failed())
+               {
+               FIPSerr(FIPS_F_RSA_EAY_PUBLIC_DECRYPT,FIPS_R_FIPS_SELFTEST_FAILED);
+               goto err;
+               }
+
+       if (FIPS_module_mode() && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)
+               && (BN_num_bits(rsa->n) < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS))
+               {
+               RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_KEY_SIZE_TOO_SMALL);
+               return -1;
+               }
+#endif
+
        if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS)
                {
                RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_MODULUS_TOO_LARGE);
@@ -675,7 +762,7 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from,
                rsa->_method_mod_n)) goto err;
 
        if ((padding == RSA_X931_PADDING) && ((ret->d[0] & 0xf) != 12))
-               BN_sub(ret, rsa->n, ret);
+               if (!BN_sub(ret, rsa->n, ret)) goto err;
 
        p=buf;
        i=BN_bn2bin(ret,p);
@@ -825,12 +912,12 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
        if (!BN_mod(r0,pr1,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
+        * 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]
-         */
+        * they ensure p > q [steve]
+        */
        if (BN_is_negative(r0))
                if (!BN_add(r0,r0,rsa->p)) goto err;
        if (!BN_mul(r1,r0,rsa->q,ctx)) goto err;
@@ -875,6 +962,13 @@ err:
 
 static int RSA_eay_init(RSA *rsa)
        {
+#ifdef OPENSSL_FIPS
+       if(FIPS_selftest_failed())
+               {
+               FIPSerr(FIPS_F_RSA_EAY_INIT,FIPS_R_FIPS_SELFTEST_FAILED);
+               return 0;
+               }
+#endif
        rsa->flags|=RSA_FLAG_CACHE_PUBLIC|RSA_FLAG_CACHE_PRIVATE;
        return(1);
        }