diff options
Diffstat (limited to 'deps/openssl/openssl/crypto/bn/bn_lib.c')
-rw-r--r-- | deps/openssl/openssl/crypto/bn/bn_lib.c | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/deps/openssl/openssl/crypto/bn/bn_lib.c b/deps/openssl/openssl/crypto/bn/bn_lib.c index 25eac396e0..3f3c7bbb2f 100644 --- a/deps/openssl/openssl/crypto/bn/bn_lib.c +++ b/deps/openssl/openssl/crypto/bn/bn_lib.c @@ -503,26 +503,40 @@ BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) { int n; - size_t i, inc, lasti, j; + size_t i, lasti, j, atop, mask; BN_ULONG l; + /* + * In case |a| is fixed-top, BN_num_bytes can return bogus length, + * but it's assumed that fixed-top inputs ought to be "nominated" + * even for padded output, so it works out... + */ n = BN_num_bytes(a); - if (tolen == -1) + if (tolen == -1) { tolen = n; - else if (tolen < n) - return -1; + } else if (tolen < n) { /* uncommon/unlike case */ + BIGNUM temp = *a; - if (n == 0) { + bn_correct_top(&temp); + n = BN_num_bytes(&temp); + if (tolen < n) + return -1; + } + + /* Swipe through whole available data and don't give away padded zero. */ + atop = a->dmax * BN_BYTES; + if (atop == 0) { OPENSSL_cleanse(to, tolen); return tolen; } - lasti = n - 1; - for (i = 0, inc = 1, j = tolen; j > 0;) { + lasti = atop - 1; + atop = a->top * BN_BYTES; + for (i = 0, j = 0, to += tolen; j < (size_t)tolen; j++) { l = a->d[i / BN_BYTES]; - to[--j] = (unsigned char)(l >> (8 * (i % BN_BYTES)) & (0 - inc)); - inc = (i - lasti) >> (8 * sizeof(i) - 1); - i += inc; /* stay on top limb */ + mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1)); + *--to = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask); + i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */ } return tolen; @@ -838,26 +852,30 @@ void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) b->neg ^= t; /*- - * Idea behind BN_FLG_STATIC_DATA is actually to - * indicate that data may not be written to. - * Intention is actually to treat it as it's - * read-only data, and some (if not most) of it does - * reside in read-only segment. In other words - * observation of BN_FLG_STATIC_DATA in - * BN_consttime_swap should be treated as fatal - * condition. It would either cause SEGV or - * effectively cause data corruption. - * BN_FLG_MALLOCED refers to BN structure itself, - * and hence must be preserved. Remaining flags are - * BN_FLG_CONSTIME and BN_FLG_SECURE. Latter must be - * preserved, because it determines how x->d was - * allocated and hence how to free it. This leaves - * BN_FLG_CONSTTIME that one can do something about. - * To summarize it's sufficient to mask and swap - * BN_FLG_CONSTTIME alone. BN_FLG_STATIC_DATA should - * be treated as fatal. + * BN_FLG_STATIC_DATA: indicates that data may not be written to. Intention + * is actually to treat it as it's read-only data, and some (if not most) + * of it does reside in read-only segment. In other words observation of + * BN_FLG_STATIC_DATA in BN_consttime_swap should be treated as fatal + * condition. It would either cause SEGV or effectively cause data + * corruption. + * + * BN_FLG_MALLOCED: refers to BN structure itself, and hence must be + * preserved. + * + * BN_FLG_SECURE: must be preserved, because it determines how x->d was + * allocated and hence how to free it. + * + * BN_FLG_CONSTTIME: sufficient to mask and swap + * + * BN_FLG_FIXED_TOP: indicates that we haven't called bn_correct_top() on + * the data, so the d array may be padded with additional 0 values (i.e. + * top could be greater than the minimal value that it could be). We should + * be swapping it */ - t = ((a->flags ^ b->flags) & BN_FLG_CONSTTIME) & condition; + +#define BN_CONSTTIME_SWAP_FLAGS (BN_FLG_CONSTTIME | BN_FLG_FIXED_TOP) + + t = ((a->flags ^ b->flags) & BN_CONSTTIME_SWAP_FLAGS) & condition; a->flags ^= t; b->flags ^= t; |