[openssl-commits] [openssl] OpenSSL_1_0_2-stable update

Matt Caswell matt at openssl.org
Tue Jun 7 21:03:21 UTC 2016


The branch OpenSSL_1_0_2-stable has been updated
       via  e4c4b2766bb97b34ea3479252276ab7c66311809 (commit)
       via  e82fd1b4574c8908b2c3bb68e1237f057a981820 (commit)
      from  b7d0f2834e139a20560d64c73e2565e93715ce2b (commit)


- Log -----------------------------------------------------------------
commit e4c4b2766bb97b34ea3479252276ab7c66311809
Author: Matt Caswell <matt at openssl.org>
Date:   Tue May 31 11:38:52 2016 +0100

    Add a BN_mod_word test()
    
    The previous commit fixed a bug with BN_mod_word() which would have been
    caught if we had a test for it. This commit adds one.
    
    Reviewed-by: Andy Polyakov <appro at openssl.org>

commit e82fd1b4574c8908b2c3bb68e1237f057a981820
Author: Matt Caswell <matt at openssl.org>
Date:   Tue May 31 11:28:14 2016 +0100

    Fix BN_mod_word bug
    
    On systems where we do not have BN_ULLONG (e.g. typically 64 bit systems)
    then BN_mod_word() can return incorrect results if the supplied modulus is
    too big.
    
    RT#4501
    
    Reviewed-by: Andy Polyakov <appro at openssl.org>
    (cherry picked from commit 37258dadaa9e36db4b96a3aa54aa6c67136160cc)

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

Summary of changes:
 crypto/bn/bn_word.c | 22 ++++++++++++++++++++++
 crypto/bn/bntest.c  |  8 +++++++-
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/crypto/bn/bn_word.c b/crypto/bn/bn_word.c
index b031a60..9b5f9cb 100644
--- a/crypto/bn/bn_word.c
+++ b/crypto/bn/bn_word.c
@@ -72,10 +72,32 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w)
     if (w == 0)
         return (BN_ULONG)-1;
 
+#ifndef BN_LLONG
+    /*
+     * If |w| is too long and we don't have BN_ULLONG then we need to fall
+     * back to using BN_div_word
+     */
+    if (w > ((BN_ULONG)1 << BN_BITS4)) {
+        BIGNUM *tmp = BN_dup(a);
+        if (tmp == NULL)
+            return (BN_ULONG)-1;
+
+        ret = BN_div_word(tmp, w);
+        BN_free(tmp);
+
+        return ret;
+    }
+#endif
+
     bn_check_top(a);
     w &= BN_MASK2;
     for (i = a->top - 1; i >= 0; i--) {
 #ifndef BN_LLONG
+        /*
+         * We can assume here that | w <= ((BN_ULONG)1 << BN_BITS4) | and so
+         * | ret < ((BN_ULONG)1 << BN_BITS4) | and therefore the shifts here are
+         * safe and will not overflow
+         */
         ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) & BN_MASK2l)) % w;
         ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w;
 #else
diff --git a/crypto/bn/bntest.c b/crypto/bn/bntest.c
index 1e35988..a327b1a 100644
--- a/crypto/bn/bntest.c
+++ b/crypto/bn/bntest.c
@@ -514,7 +514,7 @@ static void print_word(BIO *bp, BN_ULONG w)
 int test_div_word(BIO *bp)
 {
     BIGNUM a, b;
-    BN_ULONG r, s;
+    BN_ULONG r, rmod, s;
     int i;
 
     BN_init(&a);
@@ -528,8 +528,14 @@ int test_div_word(BIO *bp)
 
         s = b.d[0];
         BN_copy(&b, &a);
+        rmod = BN_mod_word(&b, s);
         r = BN_div_word(&b, s);
 
+        if (rmod != r) {
+            fprintf(stderr, "Mod (word) test failed!\n");
+            return 0;
+        }
+
         if (bp != NULL) {
             if (!results) {
                 BN_print(bp, &a);


More information about the openssl-commits mailing list