summaryrefslogtreecommitdiffstats
path: root/freebsd/crypto/openssl/crypto/bn/bn_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/crypto/openssl/crypto/bn/bn_lib.c')
-rw-r--r--freebsd/crypto/openssl/crypto/bn/bn_lib.c169
1 files changed, 93 insertions, 76 deletions
diff --git a/freebsd/crypto/openssl/crypto/bn/bn_lib.c b/freebsd/crypto/openssl/crypto/bn/bn_lib.c
index 55215433..611db290 100644
--- a/freebsd/crypto/openssl/crypto/bn/bn_lib.c
+++ b/freebsd/crypto/openssl/crypto/bn/bn_lib.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-user-space.h>
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -134,20 +134,66 @@ int BN_num_bits_word(BN_ULONG l)
return bits;
}
+/*
+ * This function still leaks `a->dmax`: it's caller's responsibility to
+ * expand the input `a` in advance to a public length.
+ */
+static ossl_inline
+int bn_num_bits_consttime(const BIGNUM *a)
+{
+ int j, ret;
+ unsigned int mask, past_i;
+ int i = a->top - 1;
+ bn_check_top(a);
+
+ for (j = 0, past_i = 0, ret = 0; j < a->dmax; j++) {
+ mask = constant_time_eq_int(i, j); /* 0xff..ff if i==j, 0x0 otherwise */
+
+ ret += BN_BITS2 & (~mask & ~past_i);
+ ret += BN_num_bits_word(a->d[j]) & mask;
+
+ past_i |= mask; /* past_i will become 0xff..ff after i==j */
+ }
+
+ /*
+ * if BN_is_zero(a) => i is -1 and ret contains garbage, so we mask the
+ * final result.
+ */
+ mask = ~(constant_time_eq_int(i, ((int)-1)));
+
+ return ret & mask;
+}
+
int BN_num_bits(const BIGNUM *a)
{
int i = a->top - 1;
bn_check_top(a);
+ if (a->flags & BN_FLG_CONSTTIME) {
+ /*
+ * We assume that BIGNUMs flagged as CONSTTIME have also been expanded
+ * so that a->dmax is not leaking secret information.
+ *
+ * In other words, it's the caller's responsibility to ensure `a` has
+ * been preallocated in advance to a public length if we hit this
+ * branch.
+ *
+ */
+ return bn_num_bits_consttime(a);
+ }
+
if (BN_is_zero(a))
return 0;
+
return ((i * BN_BITS2) + BN_num_bits_word(a->d[i]));
}
-static void bn_free_d(BIGNUM *a)
+static void bn_free_d(BIGNUM *a, int clear)
{
if (BN_get_flags(a, BN_FLG_SECURE))
- OPENSSL_secure_free(a->d);
+ OPENSSL_secure_clear_free(a->d, a->dmax * sizeof(a->d[0]));
+ else if (clear != 0)
+ OPENSSL_clear_free(a->d, a->dmax * sizeof(a->d[0]));
else
OPENSSL_free(a->d);
}
@@ -157,10 +203,8 @@ void BN_clear_free(BIGNUM *a)
{
if (a == NULL)
return;
- if (a->d != NULL && !BN_get_flags(a, BN_FLG_STATIC_DATA)) {
- OPENSSL_cleanse(a->d, a->dmax * sizeof(a->d[0]));
- bn_free_d(a);
- }
+ if (a->d != NULL && !BN_get_flags(a, BN_FLG_STATIC_DATA))
+ bn_free_d(a, 1);
if (BN_get_flags(a, BN_FLG_MALLOCED)) {
OPENSSL_cleanse(a, sizeof(*a));
OPENSSL_free(a);
@@ -172,7 +216,7 @@ void BN_free(BIGNUM *a)
if (a == NULL)
return;
if (!BN_get_flags(a, BN_FLG_STATIC_DATA))
- bn_free_d(a);
+ bn_free_d(a, 0);
if (a->flags & BN_FLG_MALLOCED)
OPENSSL_free(a);
}
@@ -250,10 +294,8 @@ BIGNUM *bn_expand2(BIGNUM *b, int words)
BN_ULONG *a = bn_expand_internal(b, words);
if (!a)
return NULL;
- if (b->d) {
- OPENSSL_cleanse(b->d, b->dmax * sizeof(b->d[0]));
- bn_free_d(b);
- }
+ if (b->d != NULL)
+ bn_free_d(b, 1);
b->d = a;
b->dmax = words;
}
@@ -340,6 +382,8 @@ void BN_swap(BIGNUM *a, BIGNUM *b)
void BN_clear(BIGNUM *a)
{
+ if (a == NULL)
+ return;
bn_check_top(a);
if (a->d != NULL)
OPENSSL_cleanse(a->d, sizeof(*a->d) * a->dmax);
@@ -416,8 +460,11 @@ BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
return ret;
}
+typedef enum {big, little} endianess_t;
+
/* ignore negative */
-static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
+static
+int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianess_t endianess)
{
int n;
size_t i, lasti, j, atop, mask;
@@ -449,10 +496,17 @@ static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
lasti = atop - 1;
atop = a->top * BN_BYTES;
- for (i = 0, j = 0, to += tolen; j < (size_t)tolen; j++) {
+ if (endianess == big)
+ to += tolen; /* start from the end of the buffer */
+ for (i = 0, j = 0; j < (size_t)tolen; j++) {
+ unsigned char val;
l = a->d[i / BN_BYTES];
mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1));
- *--to = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask);
+ val = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask);
+ if (endianess == big)
+ *--to = val;
+ else
+ *to++ = val;
i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */
}
@@ -463,12 +517,12 @@ int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
{
if (tolen < 0)
return -1;
- return bn2binpad(a, to, tolen);
+ return bn2binpad(a, to, tolen, big);
}
int BN_bn2bin(const BIGNUM *a, unsigned char *to)
{
- return bn2binpad(a, to, -1);
+ return bn2binpad(a, to, -1, big);
}
BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret)
@@ -520,22 +574,9 @@ BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret)
int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen)
{
- int i;
- BN_ULONG l;
- bn_check_top(a);
- i = BN_num_bytes(a);
- if (tolen < i)
+ if (tolen < 0)
return -1;
- /* Add trailing zeroes if necessary */
- if (tolen > i)
- memset(to + i, 0, tolen - i);
- to += i;
- while (i--) {
- l = a->d[i / BN_BYTES];
- to--;
- *to = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff;
- }
- return tolen;
+ return bn2binpad(a, to, tolen, little);
}
int BN_ucmp(const BIGNUM *a, const BIGNUM *b)
@@ -697,6 +738,9 @@ int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
int i;
BN_ULONG aa, bb;
+ if (n == 0)
+ return 0;
+
aa = a[n - 1];
bb = b[n - 1];
if (aa != bb)
@@ -739,26 +783,25 @@ int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl)
return bn_cmp_words(a, b, cl);
}
-/*
+/*-
* Constant-time conditional swap of a and b.
- * a and b are swapped if condition is not 0. The code assumes that at most one bit of condition is set.
- * nwords is the number of words to swap. The code assumes that at least nwords are allocated in both a and b,
- * and that no more than nwords are used by either a or b.
- * a and b cannot be the same number
+ * a and b are swapped if condition is not 0.
+ * nwords is the number of words to swap.
+ * Assumes that at least nwords are allocated in both a and b.
+ * Assumes that no more than nwords are used by either a or b.
*/
void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords)
{
BN_ULONG t;
int i;
+ if (a == b)
+ return;
+
bn_wcheck_size(a, nwords);
bn_wcheck_size(b, nwords);
- assert(a != b);
- assert((condition & (condition - 1)) == 0);
- assert(sizeof(BN_ULONG) >= sizeof(int));
-
- condition = ((condition - 1) >> (BN_BITS2 - 1)) - 1;
+ condition = ((~condition & ((condition - 1))) >> (BN_BITS2 - 1)) - 1;
t = (a->top ^ b->top) & condition;
a->top ^= t;
@@ -796,42 +839,16 @@ void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords)
a->flags ^= t;
b->flags ^= t;
-#define BN_CONSTTIME_SWAP(ind) \
- do { \
- t = (a->d[ind] ^ b->d[ind]) & condition; \
- a->d[ind] ^= t; \
- b->d[ind] ^= t; \
- } while (0)
-
- switch (nwords) {
- default:
- for (i = 10; i < nwords; i++)
- BN_CONSTTIME_SWAP(i);
- /* Fallthrough */
- case 10:
- BN_CONSTTIME_SWAP(9); /* Fallthrough */
- case 9:
- BN_CONSTTIME_SWAP(8); /* Fallthrough */
- case 8:
- BN_CONSTTIME_SWAP(7); /* Fallthrough */
- case 7:
- BN_CONSTTIME_SWAP(6); /* Fallthrough */
- case 6:
- BN_CONSTTIME_SWAP(5); /* Fallthrough */
- case 5:
- BN_CONSTTIME_SWAP(4); /* Fallthrough */
- case 4:
- BN_CONSTTIME_SWAP(3); /* Fallthrough */
- case 3:
- BN_CONSTTIME_SWAP(2); /* Fallthrough */
- case 2:
- BN_CONSTTIME_SWAP(1); /* Fallthrough */
- case 1:
- BN_CONSTTIME_SWAP(0);
- }
-#undef BN_CONSTTIME_SWAP
+ /* conditionally swap the data */
+ for (i = 0; i < nwords; i++) {
+ t = (a->d[i] ^ b->d[i]) & condition;
+ a->d[i] ^= t;
+ b->d[i] ^= t;
+ }
}
+#undef BN_CONSTTIME_SWAP_FLAGS
+
/* Bits of security, see SP800-57 */
int BN_security_bits(int L, int N)