Commit fe2f91a1b892af0d97c9ff0ff60702b4955b959f

Daniel Mendler 2019-10-09T20:22:11

to_sbin/to_ubin/pack: don't write anything in case of buffer overflow

diff --git a/bn_mp_pack.c b/bn_mp_pack.c
index 48da1b2..6e00b6f 100644
--- a/bn_mp_pack.c
+++ b/bn_mp_pack.c
@@ -6,16 +6,18 @@
 /* based on gmp's mpz_export.
  * see http://gmplib.org/manual/Integer-Import-and-Export.html
  */
-mp_err mp_pack(void *rop, size_t maxcount, size_t *writtencount, mp_order order, size_t size,
+mp_err mp_pack(void *rop, size_t maxcount, size_t *written, mp_order order, size_t size,
                mp_endian endian, size_t nails, const mp_int *op)
 {
    mp_err err;
-   size_t odd_nails, nail_bytes, i, j, count, written = 0;
+   size_t odd_nails, nail_bytes, i, j, count;
    unsigned char odd_nail_mask;
 
    mp_int t;
 
-   if (maxcount == 0u) {
+   count = mp_pack_count(op, nails, size);
+
+   if (count > maxcount) {
       return MP_BUF;
    }
 
@@ -34,13 +36,7 @@ mp_err mp_pack(void *rop, size_t maxcount, size_t *writtencount, mp_order order,
    }
    nail_bytes = nails / 8u;
 
-   count = mp_pack_count(&t, nails, size);
-
    for (i = 0u; i < count; ++i) {
-      if (i >= maxcount) {
-         err = MP_BUF;
-         break;
-      }
       for (j = 0u; j < size; ++j) {
          unsigned char *byte = (unsigned char *)rop +
                                (((order == MP_LSB_FIRST) ? i : ((count - 1u) - i)) * size) +
@@ -58,11 +54,10 @@ mp_err mp_pack(void *rop, size_t maxcount, size_t *writtencount, mp_order order,
          }
 
       }
-      written++;
    }
 
-   if (writtencount != NULL) {
-      *writtencount = written;
+   if (written != NULL) {
+      *written = count;
    }
    err = MP_OKAY;
 
diff --git a/bn_mp_pack_count.c b/bn_mp_pack_count.c
index 0199d04..dfecdf9 100644
--- a/bn_mp_pack_count.c
+++ b/bn_mp_pack_count.c
@@ -3,7 +3,7 @@
 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
 /* SPDX-License-Identifier: Unlicense */
 
-size_t mp_pack_count(mp_int *a, size_t nails, size_t size)
+size_t mp_pack_count(const mp_int *a, size_t nails, size_t size)
 {
    size_t bits = (size_t)mp_count_bits(a);
    return ((bits / ((size * 8u) - nails)) + (((bits % ((size * 8u) - nails)) != 0u) ? 1u : 0u));
diff --git a/bn_mp_to_radix.c b/bn_mp_to_radix.c
index e0613b4..7fa86ca 100644
--- a/bn_mp_to_radix.c
+++ b/bn_mp_to_radix.c
@@ -55,7 +55,7 @@ mp_err mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, i
       if (--maxlen < 1u) {
          /* no more room */
          err = MP_BUF;
-         break;
+         goto LBL_ERR;
       }
       if ((err = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) {
          goto LBL_ERR;
@@ -71,6 +71,7 @@ mp_err mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, i
    /* append a NULL so the string is properly terminated */
    *str = '\0';
    digs++;
+
    if (written != NULL) {
       *written = (a->sign == MP_NEG) ? (digs + 1u): digs;
    }
diff --git a/bn_mp_to_sbin.c b/bn_mp_to_sbin.c
index 3e194ca..dbaf53e 100644
--- a/bn_mp_to_sbin.c
+++ b/bn_mp_to_sbin.c
@@ -10,7 +10,6 @@ mp_err mp_to_sbin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *wr
    if (maxlen == 0u) {
       return MP_BUF;
    }
-
    if ((err = mp_to_ubin(a, buf + 1, maxlen - 1u, written)) != MP_OKAY) {
       return err;
    }
diff --git a/bn_mp_to_ubin.c b/bn_mp_to_ubin.c
index cfa391a..5e4a5da 100644
--- a/bn_mp_to_ubin.c
+++ b/bn_mp_to_ubin.c
@@ -6,11 +6,12 @@
 /* store in unsigned [big endian] format */
 mp_err mp_to_ubin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written)
 {
-   size_t    x;
+   size_t  x, count;
    mp_err  err;
    mp_int  t;
 
-   if (maxlen == 0u) {
+   count = mp_ubin_size(a);
+   if (count > maxlen) {
       return MP_BUF;
    }
 
@@ -18,27 +19,21 @@ mp_err mp_to_ubin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *wr
       return err;
    }
 
-   x = 0u;
-   while (!MP_IS_ZERO(&t)) {
-      if (maxlen == 0u) {
-         err = MP_BUF;
-         goto LBL_ERR;
-      }
-      maxlen--;
+   for (x = count; x --> 0;) {
 #ifndef MP_8BIT
-      buf[x++] = (unsigned char)(t.dp[0] & 255u);
+      buf[x] = (unsigned char)(t.dp[0] & 255u);
 #else
-      buf[x++] = (unsigned char)(t.dp[0] | ((t.dp[1] & 1u) << 7));
+      buf[x] = (unsigned char)(t.dp[0] | ((t.dp[1] & 1u) << 7));
 #endif
       if ((err = mp_div_2d(&t, 8, &t, NULL)) != MP_OKAY) {
          goto LBL_ERR;
       }
    }
-   s_mp_reverse(buf, x);
 
    if (written != NULL) {
-      *written = x;
+      *written = count;
    }
+
 LBL_ERR:
    mp_clear(&t);
    return err;
diff --git a/tommath.h b/tommath.h
index deb042a..1e0192b 100644
--- a/tommath.h
+++ b/tommath.h
@@ -384,7 +384,7 @@ mp_err mp_unpack(mp_int *rop, size_t count, mp_order order, size_t size, mp_endi
                  size_t nails, const void *op) MP_WUR;
 
 /* pack binary data */
-size_t mp_pack_count(mp_int *a, size_t nails, size_t size) MP_WUR;
+size_t mp_pack_count(const mp_int *a, size_t nails, size_t size) MP_WUR;
 mp_err mp_pack(void *rop, size_t maxcount, size_t *writtencount, mp_order order, size_t size, mp_endian endian,
                size_t nails, const mp_int *op) MP_WUR;
 
diff --git a/tommath_class.h b/tommath_class.h
index ee30b29..3abb55a 100644
--- a/tommath_class.h
+++ b/tommath_class.h
@@ -1080,7 +1080,7 @@
 #   define BN_MP_CLEAR_C
 #   define BN_MP_DIV_2D_C
 #   define BN_MP_INIT_COPY_C
-#   define BN_S_MP_REVERSE_C
+#   define BN_MP_UBIN_SIZE_C
 #endif
 
 #if defined(BN_MP_UBIN_SIZE_C)