]> granicus.if.org Git - postgresql/commitdiff
Cherry-pick security-relevant fixes from upstream imath library.
authorNoah Misch <noah@leadboat.com>
Mon, 2 Feb 2015 15:00:45 +0000 (10:00 -0500)
committerNoah Misch <noah@leadboat.com>
Mon, 2 Feb 2015 15:00:45 +0000 (10:00 -0500)
This covers alterations to buffer sizing and zeroing made between imath
1.3 and imath 1.20.  Valgrind Memcheck identified the buffer overruns
and reliance on uninitialized data; their exploit potential is unknown.
Builds specifying --with-openssl are unaffected, because they use the
OpenSSL BIGNUM facility instead of imath.  Back-patch to 9.0 (all
supported versions).

Security: CVE-2015-0243

contrib/pgcrypto/imath.c

index 5c6ebebfe2108c138c224545935f67db123e794a..61a01e2b71002e16fb0a27bc6201dd041f6a55cd 100644 (file)
@@ -818,7 +818,8 @@ mp_int_mul(mp_int a, mp_int b, mp_int c)
         */
        ua = MP_USED(a);
        ub = MP_USED(b);
-       osize = ua + ub;
+       osize = MAX(ua, ub);
+       osize = 4 * ((osize + 1) / 2);
 
        if (c == a || c == b)
        {
@@ -907,7 +908,7 @@ mp_int_sqr(mp_int a, mp_int c)
        CHECK(a != NULL && c != NULL);
 
        /* Get a temporary buffer big enough to hold the result */
-       osize = (mp_size) 2 *MP_USED(a);
+       osize = (mp_size) 4 *((MP_USED(a) + 1) / 2);
 
        if (a == c)
        {
@@ -2605,8 +2606,8 @@ s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
                 * Now we'll get t1 = a0b0 and t2 = a1b1, and subtract them out so
                 * that we're left with only the pieces we want:  t3 = a1b0 + a0b1
                 */
-               ZERO(t1, bot_size + 1);
-               ZERO(t2, bot_size + 1);
+               ZERO(t1, buf_size);
+               ZERO(t2, buf_size);
                (void) s_kmul(da, db, t1, bot_size, bot_size);  /* t1 = a0 * b0 */
                (void) s_kmul(a_top, b_top, t2, at_size, bt_size);              /* t2 = a1 * b1 */
 
@@ -2616,11 +2617,13 @@ s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
 
                /* Assemble the output value */
                COPY(t1, dc, buf_size);
-               (void) s_uadd(t3, dc + bot_size, dc + bot_size,
-                                         buf_size + 1, buf_size + 1);
+               carry = s_uadd(t3, dc + bot_size, dc + bot_size,
+                                          buf_size + 1, buf_size);
+               assert(carry == 0);
 
-               (void) s_uadd(t2, dc + 2 * bot_size, dc + 2 * bot_size,
-                                         buf_size, buf_size);
+               carry = s_uadd(t2, dc + 2 * bot_size, dc + 2 * bot_size,
+                                          buf_size, buf_size);
+               assert(carry == 0);
 
                s_free(t1);                             /* note t2 and t3 are just internal pointers
                                                                 * to t1 */
@@ -3307,7 +3310,10 @@ s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
        dbt = db + MP_USED(b) - 1;
 
        while (last < 3)
-               SETUP(mp_int_init_size(TEMP(last), 2 * umu), last);
+       {
+               SETUP(mp_int_init_size(TEMP(last), 4 * umu), last);
+               ZERO(MP_DIGITS(TEMP(last - 1)), MP_ALLOC(TEMP(last - 1)));
+       }
 
        (void) mp_int_set_value(c, 1);