Fix error codes.
[openssl.git] / crypto / rsa / rsa_eay.c
index a1ecd6d478732e446695dae95f27ad54601c66de..865fb6a26924e2bc617df541e5f62c9d0a23366b 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 */
@@ -150,16 +155,6 @@ const RSA_METHOD *RSA_PKCS1_SSLeay(void)
        return(&rsa_pkcs1_eay_meth);
        }
 
-/* Usage example;
- *    MONT_HELPER(rsa->_method_mod_p, bn_ctx, rsa->p, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
- */
-#define MONT_HELPER(method_mod, ctx, m, pre_cond, err_instr) \
-       if ((pre_cond) && ((method_mod) == NULL) && \
-                       !BN_MONT_CTX_set_locked(&(method_mod), \
-                               CRYPTO_LOCK_RSA, \
-                               (m), (ctx))) \
-               err_instr
-
 static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
             unsigned char *to, RSA *rsa, int padding)
        {
@@ -168,6 +163,20 @@ 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_mode() && (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);
@@ -233,7 +242,9 @@ static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
                goto err;
                }
 
-       MONT_HELPER(rsa->_method_mod_n, ctx, rsa->n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
+       if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
+               if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
+                       goto err;
 
        if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx,
                rsa->_method_mod_n)) goto err;
@@ -264,6 +275,7 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
 {
        BN_BLINDING *ret;
        int got_write_lock = 0;
+       CRYPTO_THREADID cur;
 
        CRYPTO_r_lock(CRYPTO_LOCK_RSA);
 
@@ -281,7 +293,8 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
        if (ret == NULL)
                goto err;
 
-       if ((BN_BLINDING_get_thread_id(ret) == CRYPTO_thread_id()) && (BN_BLINDING_get_thread_idptr(ret) == CRYPTO_thread_idptr()))
+       CRYPTO_THREADID_current(&cur);
+       if (!CRYPTO_THREADID_cmp(&cur, BN_BLINDING_thread_id(ret)))
                {
                /* rsa->blinding is ours! */
 
@@ -361,6 +374,20 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
        int local_blinding = 0;
        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_mode() && (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);
@@ -438,7 +465,9 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
                else
                        d= rsa->d;
 
-               MONT_HELPER(rsa->_method_mod_n, ctx, rsa->n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
+               if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
+                       if(!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
+                               goto err;
 
                if (!rsa->meth->bn_mod_exp(ret,f,d,rsa->n,ctx,
                                rsa->_method_mod_n)) goto err;
@@ -492,6 +521,20 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
        int local_blinding = 0;
        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_mode() && (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);
@@ -559,7 +602,9 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
                else
                        d = rsa->d;
 
-               MONT_HELPER(rsa->_method_mod_n, ctx, rsa->n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
+               if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
+                       if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
+                               goto err;
                if (!rsa->meth->bn_mod_exp(ret,f,d,rsa->n,ctx,
                                rsa->_method_mod_n))
                  goto err;
@@ -578,9 +623,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);
@@ -619,6 +664,20 @@ 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_mode() && (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);
@@ -669,13 +728,15 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from,
                goto err;
                }
 
-       MONT_HELPER(rsa->_method_mod_n, ctx, rsa->n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
+       if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
+               if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
+                       goto err;
 
        if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx,
                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);
@@ -747,11 +808,18 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
                        q = rsa->q;
                        }
 
-               MONT_HELPER(rsa->_method_mod_p, ctx, p, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
-               MONT_HELPER(rsa->_method_mod_q, ctx, q, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
+               if (rsa->flags & RSA_FLAG_CACHE_PRIVATE)
+                       {
+                       if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_p, CRYPTO_LOCK_RSA, p, ctx))
+                               goto err;
+                       if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_q, CRYPTO_LOCK_RSA, q, ctx))
+                               goto err;
+                       }
        }
 
-       MONT_HELPER(rsa->_method_mod_n, ctx, rsa->n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
+       if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
+               if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
+                       goto err;
 
        /* compute I mod q */
        if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
@@ -818,12 +886,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;
@@ -868,6 +936,9 @@ err:
 
 static int RSA_eay_init(RSA *rsa)
        {
+#ifdef OPENSSL_FIPS
+       FIPS_selftest_check();
+#endif
        rsa->flags|=RSA_FLAG_CACHE_PUBLIC|RSA_FLAG_CACHE_PRIVATE;
        return(1);
        }