fix error found by coverity: check if ctx is != NULL before calling BN_CTX_end()
[openssl.git] / crypto / dh / dh_key.c
index 62d05a4facf3e7cd2949b09e0810a37bdafac6a7..79984e13bc927111d08b81ddb2b98a389f78356b 100644 (file)
@@ -104,7 +104,7 @@ static int generate_key(DH *dh)
        int generate_new_key=0;
        unsigned l;
        BN_CTX *ctx;
-       BN_MONT_CTX *mont;
+       BN_MONT_CTX *mont=NULL;
        BIGNUM *pub_key=NULL,*priv_key=NULL;
 
        ctx = BN_CTX_new();
@@ -141,8 +141,22 @@ static int generate_key(DH *dh)
                l = dh->length ? dh->length : BN_num_bits(dh->p)-1; /* secret exponent length */
                if (!BN_rand(priv_key, l, 0, 0)) goto err;
                }
-       if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, priv_key,dh->p,ctx,mont))
-               goto err;
+
+       {
+               BIGNUM local_prk;
+               BIGNUM *prk;
+
+               if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0)
+                       {
+                       BN_init(&local_prk);
+                       prk = &local_prk;
+                       BN_with_flags(prk, priv_key, BN_FLG_EXP_CONSTTIME);
+                       }
+               else
+                       prk = priv_key;
+
+               if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) goto err;
+       }
                
        dh->pub_key=pub_key;
        dh->priv_key=priv_key;
@@ -160,9 +174,10 @@ err:
 static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
        {
        BN_CTX *ctx;
-       BN_MONT_CTX *mont;
+       BN_MONT_CTX *mont=NULL;
        BIGNUM *tmp;
        int ret= -1;
+        int check_result;
 
        ctx = BN_CTX_new();
        if (ctx == NULL) goto err;
@@ -179,10 +194,21 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
                {
                mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
                                CRYPTO_LOCK_DH, dh->p, ctx);
+               if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0)
+                       {
+                       /* XXX */
+                       BN_set_flags(dh->priv_key, BN_FLG_EXP_CONSTTIME);
+                       }
                if (!mont)
                        goto err;
                }
 
+        if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result)
+               {
+               DHerr(DH_F_COMPUTE_KEY,DH_R_INVALID_PUBKEY);
+               goto err;
+               }
+
        if (!dh->meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key,dh->p,ctx,mont))
                {
                DHerr(DH_F_COMPUTE_KEY,ERR_R_BN_LIB);
@@ -191,8 +217,11 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
 
        ret=BN_bn2bin(tmp,key);
 err:
-       BN_CTX_end(ctx);
-       BN_CTX_free(ctx);
+       if (ctx != NULL)
+               {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+               }
        return(ret);
        }
 
@@ -201,7 +230,10 @@ static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
                        const BIGNUM *m, BN_CTX *ctx,
                        BN_MONT_CTX *m_ctx)
        {
-       if (a->top == 1)
+       /* If a is only one word long and constant time is false, use the faster
+        * exponenentiation function.
+        */
+       if (a->top == 1 && ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) != 0))
                {
                BN_ULONG A = a->d[0];
                return BN_mod_exp_mont_word(r,A,p,m,ctx,m_ctx);