[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Thu Nov 26 10:23:32 UTC 2015


The branch master has been updated
       via  e113c9c59dcb419dd00525cec431edb854a6c897 (commit)
       via  fd7d252060c427b2e567295845a61d824539443b (commit)
      from  6938c954b072c1ddddeb0ec9f6a151df0d2cd925 (commit)


- Log -----------------------------------------------------------------
commit e113c9c59dcb419dd00525cec431edb854a6c897
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Nov 24 16:08:34 2015 +0000

    Add documentation for BN_with_flags
    
    Following on from the previous commit this adds some documentation for the
    BN_with_flags function which is easy to misuse.
    
    Reviewed-by: Emilia Käsper <emilia at openssl.org>

commit fd7d252060c427b2e567295845a61d824539443b
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Nov 24 11:09:00 2015 +0000

    Tighten up BN_with_flags usage and avoid a reachable assert
    
    The function rsa_ossl_mod_exp uses the function BN_with_flags to create a
    temporary copy (local_r1) of a BIGNUM (r1) with modified flags. This
    temporary copy shares some state with the original r1. If the state of r1
    gets updated then local_r1's state will be stale. This was occurring in the
    function so that when local_r1 was freed a call to bn_check_top was made
    which failed an assert due to the stale state. To resolve this we must free
    local_r1 immediately after we have finished using it and not wait until the
    end of the function.
    
    This problem prompted a review of all BN_with_flag usage within the
    codebase. All other usage appears to be correct, although often not
    obviously so. This commit refactors things to make it much clearer for
    these other uses.
    
    Reviewed-by: Emilia Käsper <emilia at openssl.org>

-----------------------------------------------------------------------

Summary of changes:
 crypto/bn/bn_gcd.c     |  30 +++++-----
 crypto/bn/bn_lib.c     |   4 +-
 crypto/dh/dh_key.c     |   4 +-
 crypto/dsa/dsa_key.c   |   4 +-
 crypto/rsa/rsa_crpt.c  |  32 ++++++-----
 crypto/rsa/rsa_gen.c   |  98 +++++++++++++++++++-------------
 crypto/rsa/rsa_ossl.c  | 151 ++++++++++++++++++++++++++++++-------------------
 doc/crypto/BN_copy.pod |  32 ++++++++++-
 include/openssl/bn.h   |   6 +-
 9 files changed, 229 insertions(+), 132 deletions(-)

diff --git a/crypto/bn/bn_gcd.c b/crypto/bn/bn_gcd.c
index 0264319..d243606 100644
--- a/crypto/bn/bn_gcd.c
+++ b/crypto/bn/bn_gcd.c
@@ -559,8 +559,6 @@ static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in,
                                         BN_CTX *ctx)
 {
     BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
-    BIGNUM local_A, local_B;
-    BIGNUM *pA, *pB;
     BIGNUM *ret = NULL;
     int sign;
 
@@ -598,11 +596,14 @@ static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in,
          * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
          * BN_div_no_branch will be called eventually.
          */
-        pB = &local_B;
-        local_B.flags = 0;
-        BN_with_flags(pB, B, BN_FLG_CONSTTIME);
-        if (!BN_nnmod(B, pB, A, ctx))
-            goto err;
+         {
+            BIGNUM local_B;
+            BN_init(&local_B);
+            BN_with_flags(&local_B, B, BN_FLG_CONSTTIME);
+            if (!BN_nnmod(B, &local_B, A, ctx))
+                goto err;
+            /* Ensure local_B goes out of scope before any further use of B */
+        }
     }
     sign = -1;
     /*-
@@ -626,13 +627,16 @@ static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in,
          * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
          * BN_div_no_branch will be called eventually.
          */
-        pA = &local_A;
-        local_A.flags = 0;
-        BN_with_flags(pA, A, BN_FLG_CONSTTIME);
+        {
+            BIGNUM local_A;
+            BN_init(&local_A);
+            BN_with_flags(&local_A, A, BN_FLG_CONSTTIME);
 
-        /* (D, M) := (A/B, A%B) ... */
-        if (!BN_div(D, M, pA, B, ctx))
-            goto err;
+            /* (D, M) := (A/B, A%B) ... */
+            if (!BN_div(D, M, &local_A, B, ctx))
+                goto err;
+            /* Ensure local_A goes out of scope before any further use of A */
+        }
 
         /*-
          * Now
diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c
index 2042920..4a6480b 100644
--- a/crypto/bn/bn_lib.c
+++ b/crypto/bn/bn_lib.c
@@ -924,7 +924,7 @@ int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
     return BN_mod_mul_montgomery(r, a, &(mont->RR), mont, ctx);
 }
 
-void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int n)
+void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags)
 {
     dest->d = b->d;
     dest->top = b->top;
@@ -932,7 +932,7 @@ void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int n)
     dest->neg = b->neg;
     dest->flags = ((dest->flags & BN_FLG_MALLOCED)
                    | (b->flags & ~BN_FLG_MALLOCED)
-                   | BN_FLG_STATIC_DATA | n);
+                   | BN_FLG_STATIC_DATA | flags);
 }
 
 BN_GENCB *BN_GENCB_new(void)
diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c
index a5cac06..271c6f4 100644
--- a/crypto/dh/dh_key.c
+++ b/crypto/dh/dh_key.c
@@ -170,13 +170,15 @@ static int generate_key(DH *dh)
             if (local_prk == NULL)
                 goto err;
             BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
-        } else
+        } else {
             prk = priv_key;
+        }
 
         if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) {
             BN_free(local_prk);
             goto err;
         }
+        /* We MUST free local_prk before any further use of priv_key */
         BN_free(local_prk);
     }
 
diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c
index d27d47a..0cde6d1 100644
--- a/crypto/dsa/dsa_key.c
+++ b/crypto/dsa/dsa_key.c
@@ -107,13 +107,15 @@ static int dsa_builtin_keygen(DSA *dsa)
             if (local_prk == NULL)
                 goto err;
             BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
-        } else
+        } else {
             prk = priv_key;
+        }
 
         if (!BN_mod_exp(pub_key, dsa->g, prk, dsa->p, ctx)) {
             BN_free(local_prk);
             goto err;
         }
+        /* We MUST free local_prk before any further use of priv_key */
         BN_free(local_prk);
     }
 
diff --git a/crypto/rsa/rsa_crpt.c b/crypto/rsa/rsa_crpt.c
index 4df1662..d08258e 100644
--- a/crypto/rsa/rsa_crpt.c
+++ b/crypto/rsa/rsa_crpt.c
@@ -159,8 +159,7 @@ static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p,
 
 BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
 {
-    BIGNUM *local_n = NULL;
-    BIGNUM *e, *n;
+    BIGNUM *e;
     BN_CTX *ctx;
     BN_BLINDING *ret = NULL;
 
@@ -196,19 +195,25 @@ BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
                  0.0);
     }
 
-    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
-        /* Set BN_FLG_CONSTTIME flag */
-        local_n = n = BN_new();
-        if (local_n == NULL) {
-            RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE);
-            goto err;
+    {
+        BIGNUM *local_n = NULL, *n;
+        if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
+            /* Set BN_FLG_CONSTTIME flag */
+            local_n = n = BN_new();
+            if (local_n == NULL) {
+                RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE);
+                goto err;
+            }
+            BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME);
+        } else {
+            n = rsa->n;
         }
-        BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME);
-    } else
-        n = rsa->n;
 
-    ret = BN_BLINDING_create_param(NULL, e, n, ctx,
-                                   rsa->meth->bn_mod_exp, rsa->_method_mod_n);
+        ret = BN_BLINDING_create_param(NULL, e, n, ctx, rsa->meth->bn_mod_exp,
+                                       rsa->_method_mod_n);
+        /* We MUST free local_n before any further use of rsa->n */
+        BN_free(local_n);
+    }
     if (ret == NULL) {
         RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_BN_LIB);
         goto err;
@@ -220,7 +225,6 @@ BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
         BN_CTX_free(ctx);
     if (e != rsa->e)
         BN_free(e);
-    BN_free(local_n);
 
     return ret;
 }
diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c
index dc3e5d3..d23d47d 100644
--- a/crypto/rsa/rsa_gen.c
+++ b/crypto/rsa/rsa_gen.c
@@ -89,17 +89,9 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
                               BN_GENCB *cb)
 {
     BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
-    BIGNUM *local_r0, *local_d, *local_p;
-    BIGNUM *pr0, *d, *p;
     int bitsp, bitsq, ok = -1, n = 0;
     BN_CTX *ctx = NULL;
 
-    local_r0 = BN_new();
-    local_d = BN_new();
-    local_p = BN_new();
-    if (local_r0 == NULL || local_d == NULL || local_p == NULL)
-        goto err;
-
     ctx = BN_CTX_new();
     if (ctx == NULL)
         goto err;
@@ -193,43 +185,69 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
         goto err;               /* q-1 */
     if (!BN_mul(r0, r1, r2, ctx))
         goto err;               /* (p-1)(q-1) */
-    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
-        pr0 = local_r0;
-        BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
-    } else
-        pr0 = r0;
-    if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx))
-        goto err;               /* d */
-
-    /* set up d for correct BN_FLG_CONSTTIME flag */
-    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
-        d = local_d;
-        BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
-    } else
-        d = rsa->d;
-
-    /* calculate d mod (p-1) */
-    if (!BN_mod(rsa->dmp1, d, r1, ctx))
-        goto err;
+    {
+        BIGNUM *local_r0 = NULL, *pr0;
+        if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
+            pr0 = local_r0 = BN_new();
+            if (local_r0 == NULL)
+                goto err;
+            BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
+        } else {
+            pr0 = r0;
+        }
+        if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx)) {
+            BN_free(local_r0);
+            goto err;               /* d */
+        }
+        /* We MUST free local_r0 before any further use of r0 */
+        BN_free(local_r0);
+    }
 
-    /* calculate d mod (q-1) */
-    if (!BN_mod(rsa->dmq1, d, r2, ctx))
-        goto err;
+    {
+        BIGNUM *local_d = NULL, *d;
+        /* set up d for correct BN_FLG_CONSTTIME flag */
+        if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
+            d = local_d = BN_new();
+            if (local_d == NULL)
+                goto err;
+            BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
+        } else {
+            d = rsa->d;
+        }
 
-    /* calculate inverse of q mod p */
-    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
-        p = local_p;
-        BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
-    } else
-        p = rsa->p;
-    if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx))
-        goto err;
+        if (   /* calculate d mod (p-1) */
+               !BN_mod(rsa->dmp1, d, r1, ctx)
+               /* calculate d mod (q-1) */
+            || !BN_mod(rsa->dmq1, d, r2, ctx)) {
+            BN_free(local_d);
+            goto err;
+        }
+        /* We MUST free local_d before any further use of rsa->d */
+        BN_free(local_d);
+    }
+
+    {
+        BIGNUM *local_p = NULL, *p;
+
+        /* calculate inverse of q mod p */
+        if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
+            p = local_p = BN_new();
+            if (local_p == NULL)
+                goto err;
+            BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
+        } else {
+            p = rsa->p;
+        }
+        if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx)) {
+            BN_free(local_p);
+            goto err;
+        }
+        /* We MUST free local_p before any further use of rsa->p */
+        BN_free(local_p);
+    }
 
     ok = 1;
  err:
-    BN_free(local_r0);
-    BN_free(local_d);
-    BN_free(local_p);
     if (ok == -1) {
         RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, ERR_LIB_BN);
         ok = 0;
diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c
index 09a65b8..0752f5f 100644
--- a/crypto/rsa/rsa_ossl.c
+++ b/crypto/rsa/rsa_ossl.c
@@ -426,8 +426,9 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
                 goto err;
             }
             BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
-        } else
+        } else {
             d = rsa->d;
+        }
 
         if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
             if (!BN_MONT_CTX_set_locked
@@ -441,6 +442,7 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
             BN_free(local_d);
             goto err;
         }
+        /* We MUST free local_d before any further use of rsa->d */
         BN_free(local_d);
     }
 
@@ -558,8 +560,9 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
                 goto err;
             }
             BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
-        } else
+        } else {
             d = rsa->d;
+        }
 
         if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
             if (!BN_MONT_CTX_set_locked
@@ -572,6 +575,7 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
             BN_free(local_d);
             goto err;
         }
+        /* We MUST free local_d before any further use of rsa->d */
         BN_free(local_d);
     }
 
@@ -712,20 +716,10 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
 static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
 {
     BIGNUM *r1, *m1, *vrfy;
-    BIGNUM *local_dmp1, *local_dmq1, *local_c, *local_r1;
-    BIGNUM *dmp1, *dmq1, *c, *pr1;
     int ret = 0;
 
     BN_CTX_start(ctx);
 
-    local_dmp1 = BN_new();
-    local_dmq1 = BN_new();
-    local_c = BN_new();
-    local_r1 = BN_new();
-    if (local_dmp1 == NULL
-            || local_dmq1 == NULL || local_c == NULL || local_r1 == NULL)
-        goto err;
-
     r1 = BN_CTX_get(ctx);
     m1 = BN_CTX_get(ctx);
     vrfy = BN_CTX_get(ctx);
@@ -765,6 +759,10 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
                 goto err;
             }
         }
+        /*
+         * We MUST free local_p and local_q before any further use of rsa->p and
+         * rsa->q
+         */
         BN_free(local_p);
         BN_free(local_q);
     }
@@ -775,44 +773,74 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
             goto err;
 
     /* compute I mod q */
-    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
-        c = local_c;
-        BN_with_flags(c, I, BN_FLG_CONSTTIME);
-        if (!BN_mod(r1, c, rsa->q, ctx))
-            goto err;
-    } else {
-        if (!BN_mod(r1, I, rsa->q, ctx))
+    {
+        BIGNUM *local_c = NULL;
+        const BIGNUM *c;
+        if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
+            local_c = BN_new();
+            if (local_c == NULL)
+                goto err;
+            BN_with_flags(local_c, I, BN_FLG_CONSTTIME);
+            c = local_c;
+        } else {
+            c = I;
+        }
+        if (!BN_mod(r1, c, rsa->q, ctx)) {
+            BN_free(local_c);
             goto err;
-    }
+        }
 
-    /* compute r1^dmq1 mod q */
-    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
-        dmq1 = local_dmq1;
-        BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
-    } else
-        dmq1 = rsa->dmq1;
-    if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx, rsa->_method_mod_q))
-        goto err;
+        {
+            BIGNUM *local_dmq1 = NULL, *dmq1;
+            /* compute r1^dmq1 mod q */
+            if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
+                dmq1 = local_dmq1 = BN_new();
+                if (local_dmq1 == NULL) {
+                    BN_free(local_c);
+                    goto err;
+                }
+                BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
+            } else {
+                dmq1 = rsa->dmq1;
+            }
+            if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx,
+                rsa->_method_mod_q)) {
+                BN_free(local_c);
+                BN_free(local_dmq1);
+                goto err;
+            }
+            /* We MUST free local_dmq1 before any further use of rsa->dmq1 */
+            BN_free(local_dmq1);
+        }
 
-    /* compute I mod p */
-    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
-        c = local_c;
-        BN_with_flags(c, I, BN_FLG_CONSTTIME);
-        if (!BN_mod(r1, c, rsa->p, ctx))
-            goto err;
-    } else {
-        if (!BN_mod(r1, I, rsa->p, ctx))
+        /* compute I mod p */
+        if (!BN_mod(r1, c, rsa->p, ctx)) {
+            BN_free(local_c);
             goto err;
+        }
+        /* We MUST free local_c before any further use of I */
+        BN_free(local_c);
     }
 
-    /* compute r1^dmp1 mod p */
-    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
-        dmp1 = local_dmp1;
-        BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
-    } else
-        dmp1 = rsa->dmp1;
-    if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx, rsa->_method_mod_p))
-        goto err;
+    {
+        BIGNUM *local_dmp1 = NULL, *dmp1;
+        /* compute r1^dmp1 mod p */
+        if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
+            dmp1 = local_dmp1 = BN_new();
+            if (local_dmp1 == NULL)
+                goto err;
+            BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
+        } else {
+            dmp1 = rsa->dmp1;
+        }
+        if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx,
+                                   rsa->_method_mod_p)) {
+            BN_free(local_dmp1);
+            goto err;
+        }
+        /* We MUST free local_dmp1 before any further use of rsa->dmp1 */
+        BN_free(local_dmp1);
+    }
 
     if (!BN_sub(r0, r0, m1))
         goto err;
@@ -827,14 +855,24 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
     if (!BN_mul(r1, r0, rsa->iqmp, ctx))
         goto err;
 
-    /* Turn BN_FLG_CONSTTIME flag on before division operation */
-    if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
-        pr1 = local_r1;
-        BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);
-    } else
-        pr1 = r1;
-    if (!BN_mod(r0, pr1, rsa->p, ctx))
-        goto err;
+    {
+        BIGNUM *local_r1 = NULL, *pr1;
+        /* Turn BN_FLG_CONSTTIME flag on before division operation */
+        if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
+            pr1 = local_r1 = BN_new();
+            if (local_r1 == NULL)
+                goto err;
+            BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);
+        } else {
+            pr1 = r1;
+        }
+        if (!BN_mod(r0, pr1, rsa->p, ctx)) {
+            BN_free(local_r1);
+            goto err;
+        }
+        /* We MUST free local_r1 before any further use of r1 */
+        BN_free(local_r1);
+    }
 
     /*
      * If p < q it is occasionally possible for the correction of adding 'p'
@@ -883,23 +921,20 @@ static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
                 if (d == NULL)
                     goto err;
                 BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
-            } else
+            } else {
                 d = rsa->d;
+            }
             if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx,
                                        rsa->_method_mod_n)) {
                 BN_free(local_d);
                 goto err;
             }
-
+            /* We MUST free local_d before any further use of rsa->d */
             BN_free(local_d);
         }
     }
     ret = 1;
  err:
-    BN_free(local_dmp1);
-    BN_free(local_dmq1);
-    BN_free(local_c);
-    BN_free(local_r1);
     BN_CTX_end(ctx);
     return (ret);
 }
diff --git a/doc/crypto/BN_copy.pod b/doc/crypto/BN_copy.pod
index 4de9c1a..0a00884 100644
--- a/doc/crypto/BN_copy.pod
+++ b/doc/crypto/BN_copy.pod
@@ -2,7 +2,7 @@
 
 =head1 NAME
 
-BN_copy, BN_dup - copy BIGNUMs
+BN_copy, BN_dup, BN_with_flags - copy BIGNUMs
 
 =head1 SYNOPSIS
 
@@ -12,11 +12,41 @@ BN_copy, BN_dup - copy BIGNUMs
 
  BIGNUM *BN_dup(const BIGNUM *from);
 
+ void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags);
+
 =head1 DESCRIPTION
 
 BN_copy() copies B<from> to B<to>. BN_dup() creates a new B<BIGNUM>
 containing the value B<from>.
 
+BN_with_flags creates a B<temporary> shallow copy of B<b> in B<dest>. It places
+significant restrictions on the copied data. Applications that do no adhere to
+these restrictions may encounter unexpected side effects or crashes. For that
+reason use of this function is discouraged. Any flags provided in B<flags> will
+be set in B<dest> in addition to any flags already set in B<b>. For example this
+might commonly be used to create a temporary copy of a BIGNUM with the
+B<BN_FLG_CONSTTIME> flag set for constant time operations. The temporary copy in
+B<dest> will share some internal state with B<b>. For this reason the following
+restrictions apply to the use of B<dest>:
+
+=over 4
+
+=item *
+
+B<dest> should be a newly allocated BIGNUM obtained via a call to BN_new(). It
+should not have been used for other purposes or initialised in any way.
+
+=item *
+
+B<dest> must only be used in "read-only" operations, i.e. typically those
+functions where the relevant parameter is declared "const".
+
+=item *
+
+B<dest> must be used and freed before any further subsequent use of B<b>
+
+=back
+
 =head1 RETURN VALUES
 
 BN_copy() returns B<to> on success, NULL on error. BN_dup() returns
diff --git a/include/openssl/bn.h b/include/openssl/bn.h
index 0fcf843..b052c41 100644
--- a/include/openssl/bn.h
+++ b/include/openssl/bn.h
@@ -285,9 +285,11 @@ int BN_get_flags(const BIGNUM *b, int n);
 
 /*
  * get a clone of a BIGNUM with changed flags, for *temporary* use only (the
- * two BIGNUMs cannot not be used in parallel!)
+ * two BIGNUMs cannot be used in parallel!). Also only for *read only* use. The
+ * value |dest| should be a newly allocated BIGNUM obtained via BN_new() that
+ * has not been otherwise initialised or used.
  */
-void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int n);
+void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags);
 
 /* Wrapper function to make using BN_GENCB easier,  */
 int BN_GENCB_call(BN_GENCB *cb, int a, int b);


More information about the openssl-commits mailing list