Rewrite BN_lebin2bn() using CBS.
authorjsing <jsing@openbsd.org>
Wed, 17 Apr 2024 14:45:46 +0000 (14:45 +0000)
committerjsing <jsing@openbsd.org>
Wed, 17 Apr 2024 14:45:46 +0000 (14:45 +0000)
We get an implementation of this for free by having bn_bin2bn_cbs() use
CBS_get_u8() instead of CBS_get_last_u8().

ok tb@

lib/libcrypto/bn/bn_convert.c

index 5c3c98b..0bfb00e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_convert.c,v 1.18 2024/04/16 13:14:46 jsing Exp $ */
+/* $OpenBSD: bn_convert.c,v 1.19 2024/04/17 14:45:46 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -154,7 +154,7 @@ BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
 LCRYPTO_ALIAS(BN_bn2binpad);
 
 static int
-bn_bin2bn_cbs(BIGNUM **bnp, CBS *cbs)
+bn_bin2bn_cbs(BIGNUM **bnp, CBS *cbs, int lebin)
 {
        BIGNUM *bn = NULL;
        BN_ULONG w;
@@ -173,8 +173,13 @@ bn_bin2bn_cbs(BIGNUM **bnp, CBS *cbs)
        w = 0;
 
        while (CBS_len(cbs) > 0) {
-               if (!CBS_get_last_u8(cbs, &v))
-                       goto err;
+               if (lebin) {
+                       if (!CBS_get_u8(cbs, &v))
+                               goto err;
+               } else {
+                       if (!CBS_get_last_u8(cbs, &v))
+                               goto err;
+               }
 
                w |= (BN_ULONG)v << b;
                b += 8;
@@ -212,7 +217,7 @@ BN_bin2bn(const unsigned char *d, int len, BIGNUM *bn)
 
        CBS_init(&cbs, d, len);
 
-       if (!bn_bin2bn_cbs(&bn, &cbs))
+       if (!bn_bin2bn_cbs(&bn, &cbs, 0))
                return NULL;
 
        return bn;
@@ -230,56 +235,19 @@ BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen)
 LCRYPTO_ALIAS(BN_bn2lebinpad);
 
 BIGNUM *
-BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret)
+BN_lebin2bn(const unsigned char *d, int len, BIGNUM *bn)
 {
-       unsigned int i, m, n;
-       BN_ULONG l;
-       BIGNUM *bn = NULL;
+       CBS cbs;
 
-       if (ret == NULL)
-               ret = bn = BN_new();
-       if (ret == NULL)
+       if (len < 0)
                return NULL;
 
+       CBS_init(&cbs, d, len);
 
-       s += len;
-       /* Skip trailing zeroes. */
-       for (; len > 0 && s[-1] == 0; s--, len--)
-               continue;
-
-       n = len;
-       if (n == 0) {
-               ret->top = 0;
-               return ret;
-       }
-
-       i = ((n - 1) / BN_BYTES) + 1;
-       m = (n - 1) % BN_BYTES;
-       if (!bn_wexpand(ret, (int)i)) {
-               BN_free(bn);
+       if (!bn_bin2bn_cbs(&bn, &cbs, 1))
                return NULL;
-       }
-
-       ret->top = i;
-       ret->neg = 0;
-       l = 0;
-       while (n-- > 0) {
-               s--;
-               l = (l << 8L) | *s;
-               if (m-- == 0) {
-                       ret->d[--i] = l;
-                       l = 0;
-                       m = BN_BYTES - 1;
-               }
-       }
 
-       /*
-        * need to call this due to clear byte at top if avoiding having the
-        * top bit set (-ve number)
-        */
-       bn_correct_top(ret);
-
-       return ret;
+       return bn;
 }
 LCRYPTO_ALIAS(BN_lebin2bn);