2016-05-17 18:51:04 +00:00
|
|
|
/*
|
2019-02-26 14:05:09 +00:00
|
|
|
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
1998-12-21 10:52:47 +00:00
|
|
|
*
|
2016-05-17 18:51:04 +00:00
|
|
|
* Licensed under the OpenSSL license (the "License"). You may not use
|
|
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
|
|
* in the file LICENSE in the source distribution or at
|
|
|
|
* https://www.openssl.org/source/license.html
|
1998-12-21 10:52:47 +00:00
|
|
|
*/
|
|
|
|
|
2000-09-04 15:34:43 +00:00
|
|
|
#include <assert.h>
|
2000-12-03 09:55:08 +00:00
|
|
|
#include <limits.h>
|
2015-05-14 14:56:48 +00:00
|
|
|
#include "internal/cryptlib.h"
|
1998-12-21 10:52:47 +00:00
|
|
|
#include "bn_lcl.h"
|
2016-01-05 04:00:33 +00:00
|
|
|
#include <openssl/opensslconf.h>
|
2018-02-04 14:20:29 +00:00
|
|
|
#include "internal/constant_time_locl.h"
|
1998-12-21 10:52:47 +00:00
|
|
|
|
2004-06-17 23:50:25 +00:00
|
|
|
/* This stuff appears to be completely unused, so is deprecated */
|
2016-01-05 04:00:33 +00:00
|
|
|
#if OPENSSL_API_COMPAT < 0x00908000L
|
2014-12-28 02:48:40 +00:00
|
|
|
/*-
|
|
|
|
* For a 32 bit machine
|
1998-12-21 11:00:56 +00:00
|
|
|
* 2 - 4 == 128
|
|
|
|
* 3 - 8 == 256
|
|
|
|
* 4 - 16 == 512
|
|
|
|
* 5 - 32 == 1024
|
|
|
|
* 6 - 64 == 2048
|
|
|
|
* 7 - 128 == 4096
|
|
|
|
* 8 - 256 == 8192
|
|
|
|
*/
|
2015-01-22 03:40:55 +00:00
|
|
|
static int bn_limit_bits = 0;
|
|
|
|
static int bn_limit_num = 8; /* (1<<bn_limit_bits) */
|
|
|
|
static int bn_limit_bits_low = 0;
|
|
|
|
static int bn_limit_num_low = 8; /* (1<<bn_limit_bits_low) */
|
|
|
|
static int bn_limit_bits_high = 0;
|
|
|
|
static int bn_limit_num_high = 8; /* (1<<bn_limit_bits_high) */
|
|
|
|
static int bn_limit_bits_mont = 0;
|
|
|
|
static int bn_limit_num_mont = 8; /* (1<<bn_limit_bits_mont) */
|
1998-12-21 11:00:56 +00:00
|
|
|
|
1999-04-19 21:31:43 +00:00
|
|
|
void BN_set_params(int mult, int high, int low, int mont)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
if (mult >= 0) {
|
|
|
|
if (mult > (int)(sizeof(int) * 8) - 1)
|
|
|
|
mult = sizeof(int) * 8 - 1;
|
|
|
|
bn_limit_bits = mult;
|
|
|
|
bn_limit_num = 1 << mult;
|
|
|
|
}
|
|
|
|
if (high >= 0) {
|
|
|
|
if (high > (int)(sizeof(int) * 8) - 1)
|
|
|
|
high = sizeof(int) * 8 - 1;
|
|
|
|
bn_limit_bits_high = high;
|
|
|
|
bn_limit_num_high = 1 << high;
|
|
|
|
}
|
|
|
|
if (low >= 0) {
|
|
|
|
if (low > (int)(sizeof(int) * 8) - 1)
|
|
|
|
low = sizeof(int) * 8 - 1;
|
|
|
|
bn_limit_bits_low = low;
|
|
|
|
bn_limit_num_low = 1 << low;
|
|
|
|
}
|
|
|
|
if (mont >= 0) {
|
|
|
|
if (mont > (int)(sizeof(int) * 8) - 1)
|
|
|
|
mont = sizeof(int) * 8 - 1;
|
|
|
|
bn_limit_bits_mont = mont;
|
|
|
|
bn_limit_num_mont = 1 << mont;
|
|
|
|
}
|
|
|
|
}
|
1998-12-21 11:00:56 +00:00
|
|
|
|
1999-04-19 21:31:43 +00:00
|
|
|
int BN_get_params(int which)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
if (which == 0)
|
2017-10-17 14:04:09 +00:00
|
|
|
return bn_limit_bits;
|
2015-01-22 03:40:55 +00:00
|
|
|
else if (which == 1)
|
2017-10-17 14:04:09 +00:00
|
|
|
return bn_limit_bits_high;
|
2015-01-22 03:40:55 +00:00
|
|
|
else if (which == 2)
|
2017-10-17 14:04:09 +00:00
|
|
|
return bn_limit_bits_low;
|
2015-01-22 03:40:55 +00:00
|
|
|
else if (which == 3)
|
2017-10-17 14:04:09 +00:00
|
|
|
return bn_limit_bits_mont;
|
2015-01-22 03:40:55 +00:00
|
|
|
else
|
2017-10-17 14:04:09 +00:00
|
|
|
return 0;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
2004-06-17 23:50:25 +00:00
|
|
|
#endif
|
1998-12-21 10:52:47 +00:00
|
|
|
|
2001-03-08 13:58:09 +00:00
|
|
|
const BIGNUM *BN_value_one(void)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
static const BN_ULONG data_one = 1L;
|
|
|
|
static const BIGNUM const_one =
|
|
|
|
{ (BN_ULONG *)&data_one, 1, 1, 0, BN_FLG_STATIC_DATA };
|
1998-12-21 10:52:47 +00:00
|
|
|
|
2017-10-17 14:04:09 +00:00
|
|
|
return &const_one;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
1999-04-19 21:31:43 +00:00
|
|
|
int BN_num_bits_word(BN_ULONG l)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
Make BN_num_bits_word constant-time.
(This patch was written by Andy Polyakov. I only wrote the commit
message. Mistakes in the analysis are my fault.)
BN_num_bits, by way of BN_num_bits_word, currently leaks the
most-significant word of its argument via branching and memory access
pattern.
BN_num_bits is called on RSA prime factors in various places. These have
public bit lengths, but all bits beyond the high bit are secret. This
fully resolves those cases.
There are a few places where BN_num_bits is called on an input where the
bit length is also secret. This does *not* fully resolve those cases as
we still only look at the top word. Today, that is guaranteed to be
non-zero, but only because of the long-standing bn_correct_top timing
leak. Once that is fixed, a constant-time BN_num_bits on such inputs
must count bits on each word.
Instead, those cases should not call BN_num_bits at all. In particular,
BN_mod_exp_mont_consttime uses the exponent bit width to pick windows,
but it should be using the maximum bit width. The next patch will fix
this.
Thanks to Dinghao Wu, Danfeng Zhang, Shuai Wang, Pei Wang, and Xiao Liu
for reporting this issue.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5154)
2018-01-23 18:46:53 +00:00
|
|
|
BN_ULONG x, mask;
|
|
|
|
int bits = (l != 0);
|
|
|
|
|
|
|
|
#if BN_BITS2 > 32
|
|
|
|
x = l >> 32;
|
|
|
|
mask = (0 - x) & BN_MASK2;
|
|
|
|
mask = (0 - (mask >> (BN_BITS2 - 1)));
|
|
|
|
bits += 32 & mask;
|
|
|
|
l ^= (x ^ l) & mask;
|
1998-12-21 10:52:47 +00:00
|
|
|
#endif
|
Make BN_num_bits_word constant-time.
(This patch was written by Andy Polyakov. I only wrote the commit
message. Mistakes in the analysis are my fault.)
BN_num_bits, by way of BN_num_bits_word, currently leaks the
most-significant word of its argument via branching and memory access
pattern.
BN_num_bits is called on RSA prime factors in various places. These have
public bit lengths, but all bits beyond the high bit are secret. This
fully resolves those cases.
There are a few places where BN_num_bits is called on an input where the
bit length is also secret. This does *not* fully resolve those cases as
we still only look at the top word. Today, that is guaranteed to be
non-zero, but only because of the long-standing bn_correct_top timing
leak. Once that is fixed, a constant-time BN_num_bits on such inputs
must count bits on each word.
Instead, those cases should not call BN_num_bits at all. In particular,
BN_mod_exp_mont_consttime uses the exponent bit width to pick windows,
but it should be using the maximum bit width. The next patch will fix
this.
Thanks to Dinghao Wu, Danfeng Zhang, Shuai Wang, Pei Wang, and Xiao Liu
for reporting this issue.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5154)
2018-01-23 18:46:53 +00:00
|
|
|
|
|
|
|
x = l >> 16;
|
|
|
|
mask = (0 - x) & BN_MASK2;
|
|
|
|
mask = (0 - (mask >> (BN_BITS2 - 1)));
|
|
|
|
bits += 16 & mask;
|
|
|
|
l ^= (x ^ l) & mask;
|
|
|
|
|
|
|
|
x = l >> 8;
|
|
|
|
mask = (0 - x) & BN_MASK2;
|
|
|
|
mask = (0 - (mask >> (BN_BITS2 - 1)));
|
|
|
|
bits += 8 & mask;
|
|
|
|
l ^= (x ^ l) & mask;
|
|
|
|
|
|
|
|
x = l >> 4;
|
|
|
|
mask = (0 - x) & BN_MASK2;
|
|
|
|
mask = (0 - (mask >> (BN_BITS2 - 1)));
|
|
|
|
bits += 4 & mask;
|
|
|
|
l ^= (x ^ l) & mask;
|
|
|
|
|
|
|
|
x = l >> 2;
|
|
|
|
mask = (0 - x) & BN_MASK2;
|
|
|
|
mask = (0 - (mask >> (BN_BITS2 - 1)));
|
|
|
|
bits += 2 & mask;
|
|
|
|
l ^= (x ^ l) & mask;
|
|
|
|
|
|
|
|
x = l >> 1;
|
|
|
|
mask = (0 - x) & BN_MASK2;
|
|
|
|
mask = (0 - (mask >> (BN_BITS2 - 1)));
|
|
|
|
bits += 1 & mask;
|
|
|
|
|
|
|
|
return bits;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
Make BN_num_bits() consttime upon BN_FLG_CONSTTIME
This issue was partially addressed by commit
972c87dfc7e765bd28a4964519c362f0d3a58ca4, which hardened its callee
BN_num_bits_word() to avoid leaking the most-significant word of its
argument via branching and memory access pattern.
The commit message also reported:
> There are a few places where BN_num_bits is called on an input where
> the bit length is also secret. This does *not* fully resolve those
> cases as we still only look at the top word.
BN_num_bits() is called directly or indirectly (e.g., through
BN_num_bytes() or BN_bn2binpad() ) in various parts of the `crypto/ec`
code, notably in all the currently supported implementations of scalar
multiplication (in the generic path through ec_scalar_mul_ladder() as
well as in dedicated methods like ecp_nistp{224,256,521}.c and
ecp_nistz256.c).
Under the right conditions, a motivated SCA attacker could retrieve the
secret bitlength of a secret nonce through this vulnerability,
potentially leading, ultimately, to recover a long-term secret key.
With this commit, exclusively for BIGNUMs that are flagged with
BN_FLG_CONSTTIME, instead of accessing only bn->top, all the limbs of
the BIGNUM are accessed up to bn->dmax and bitwise masking is used to
avoid branching.
Memory access pattern still leaks bn->dmax, the size of the lazily
allocated buffer for representing the BIGNUM, which is inevitable with
the current BIGNUM architecture: reading past bn->dmax would be an
out-of-bound read.
As such, it's the caller responsibility to ensure that bn->dmax does not
leak secret information, by explicitly expanding the internal BIGNUM
buffer to a public value sufficient to avoid any lazy reallocation
while manipulating it: this should be already done at the top level
alongside setting the BN_FLG_CONSTTIME.
Thanks to David Schrammel and Samuel Weiser for reporting this issue
through responsible disclosure.
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de>
(Merged from https://github.com/openssl/openssl/pull/9511)
(cherry picked from commit 8b44198b916015f77bef1befa26edb48ad8a0238)
2019-08-01 23:08:34 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
1999-06-04 22:23:10 +00:00
|
|
|
int BN_num_bits(const BIGNUM *a)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
int i = a->top - 1;
|
|
|
|
bn_check_top(a);
|
1998-12-21 11:00:56 +00:00
|
|
|
|
Make BN_num_bits() consttime upon BN_FLG_CONSTTIME
This issue was partially addressed by commit
972c87dfc7e765bd28a4964519c362f0d3a58ca4, which hardened its callee
BN_num_bits_word() to avoid leaking the most-significant word of its
argument via branching and memory access pattern.
The commit message also reported:
> There are a few places where BN_num_bits is called on an input where
> the bit length is also secret. This does *not* fully resolve those
> cases as we still only look at the top word.
BN_num_bits() is called directly or indirectly (e.g., through
BN_num_bytes() or BN_bn2binpad() ) in various parts of the `crypto/ec`
code, notably in all the currently supported implementations of scalar
multiplication (in the generic path through ec_scalar_mul_ladder() as
well as in dedicated methods like ecp_nistp{224,256,521}.c and
ecp_nistz256.c).
Under the right conditions, a motivated SCA attacker could retrieve the
secret bitlength of a secret nonce through this vulnerability,
potentially leading, ultimately, to recover a long-term secret key.
With this commit, exclusively for BIGNUMs that are flagged with
BN_FLG_CONSTTIME, instead of accessing only bn->top, all the limbs of
the BIGNUM are accessed up to bn->dmax and bitwise masking is used to
avoid branching.
Memory access pattern still leaks bn->dmax, the size of the lazily
allocated buffer for representing the BIGNUM, which is inevitable with
the current BIGNUM architecture: reading past bn->dmax would be an
out-of-bound read.
As such, it's the caller responsibility to ensure that bn->dmax does not
leak secret information, by explicitly expanding the internal BIGNUM
buffer to a public value sufficient to avoid any lazy reallocation
while manipulating it: this should be already done at the top level
alongside setting the BN_FLG_CONSTTIME.
Thanks to David Schrammel and Samuel Weiser for reporting this issue
through responsible disclosure.
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de>
(Merged from https://github.com/openssl/openssl/pull/9511)
(cherry picked from commit 8b44198b916015f77bef1befa26edb48ad8a0238)
2019-08-01 23:08:34 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2015-01-22 03:40:55 +00:00
|
|
|
if (BN_is_zero(a))
|
|
|
|
return 0;
|
Make BN_num_bits() consttime upon BN_FLG_CONSTTIME
This issue was partially addressed by commit
972c87dfc7e765bd28a4964519c362f0d3a58ca4, which hardened its callee
BN_num_bits_word() to avoid leaking the most-significant word of its
argument via branching and memory access pattern.
The commit message also reported:
> There are a few places where BN_num_bits is called on an input where
> the bit length is also secret. This does *not* fully resolve those
> cases as we still only look at the top word.
BN_num_bits() is called directly or indirectly (e.g., through
BN_num_bytes() or BN_bn2binpad() ) in various parts of the `crypto/ec`
code, notably in all the currently supported implementations of scalar
multiplication (in the generic path through ec_scalar_mul_ladder() as
well as in dedicated methods like ecp_nistp{224,256,521}.c and
ecp_nistz256.c).
Under the right conditions, a motivated SCA attacker could retrieve the
secret bitlength of a secret nonce through this vulnerability,
potentially leading, ultimately, to recover a long-term secret key.
With this commit, exclusively for BIGNUMs that are flagged with
BN_FLG_CONSTTIME, instead of accessing only bn->top, all the limbs of
the BIGNUM are accessed up to bn->dmax and bitwise masking is used to
avoid branching.
Memory access pattern still leaks bn->dmax, the size of the lazily
allocated buffer for representing the BIGNUM, which is inevitable with
the current BIGNUM architecture: reading past bn->dmax would be an
out-of-bound read.
As such, it's the caller responsibility to ensure that bn->dmax does not
leak secret information, by explicitly expanding the internal BIGNUM
buffer to a public value sufficient to avoid any lazy reallocation
while manipulating it: this should be already done at the top level
alongside setting the BN_FLG_CONSTTIME.
Thanks to David Schrammel and Samuel Weiser for reporting this issue
through responsible disclosure.
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de>
(Merged from https://github.com/openssl/openssl/pull/9511)
(cherry picked from commit 8b44198b916015f77bef1befa26edb48ad8a0238)
2019-08-01 23:08:34 +00:00
|
|
|
|
2015-01-22 03:40:55 +00:00
|
|
|
return ((i * BN_BITS2) + BN_num_bits_word(a->d[i]));
|
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
2019-07-23 06:54:52 +00:00
|
|
|
static void bn_free_d(BIGNUM *a, int clear)
|
2015-07-22 10:44:50 +00:00
|
|
|
{
|
2016-07-28 19:15:52 +00:00
|
|
|
if (BN_get_flags(a, BN_FLG_SECURE))
|
2019-07-23 06:54:52 +00:00
|
|
|
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]));
|
2015-07-22 10:44:50 +00:00
|
|
|
else
|
|
|
|
OPENSSL_free(a->d);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-04-19 21:31:43 +00:00
|
|
|
void BN_clear_free(BIGNUM *a)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
if (a == NULL)
|
|
|
|
return;
|
2019-07-23 06:54:52 +00:00
|
|
|
if (a->d != NULL && !BN_get_flags(a, BN_FLG_STATIC_DATA))
|
|
|
|
bn_free_d(a, 1);
|
2017-10-08 20:04:05 +00:00
|
|
|
if (BN_get_flags(a, BN_FLG_MALLOCED)) {
|
|
|
|
OPENSSL_cleanse(a, sizeof(*a));
|
2015-01-22 03:40:55 +00:00
|
|
|
OPENSSL_free(a);
|
2017-10-08 20:04:05 +00:00
|
|
|
}
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
1999-04-19 21:31:43 +00:00
|
|
|
void BN_free(BIGNUM *a)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
if (a == NULL)
|
|
|
|
return;
|
2015-05-01 14:02:07 +00:00
|
|
|
if (!BN_get_flags(a, BN_FLG_STATIC_DATA))
|
2019-07-23 06:54:52 +00:00
|
|
|
bn_free_d(a, 0);
|
2015-01-22 03:40:55 +00:00
|
|
|
if (a->flags & BN_FLG_MALLOCED)
|
|
|
|
OPENSSL_free(a);
|
|
|
|
}
|
1998-12-21 11:00:56 +00:00
|
|
|
|
2015-11-21 13:27:46 +00:00
|
|
|
void bn_init(BIGNUM *a)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
2015-11-21 13:27:46 +00:00
|
|
|
static BIGNUM nilbn;
|
|
|
|
|
|
|
|
*a = nilbn;
|
2015-01-22 03:40:55 +00:00
|
|
|
bn_check_top(a);
|
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
1999-04-19 21:31:43 +00:00
|
|
|
BIGNUM *BN_new(void)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
BIGNUM *ret;
|
|
|
|
|
2015-09-03 13:15:26 +00:00
|
|
|
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
|
2015-01-22 03:40:55 +00:00
|
|
|
BNerr(BN_F_BN_NEW, ERR_R_MALLOC_FAILURE);
|
2017-10-17 14:04:09 +00:00
|
|
|
return NULL;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
|
|
|
ret->flags = BN_FLG_MALLOCED;
|
|
|
|
bn_check_top(ret);
|
2017-10-17 14:04:09 +00:00
|
|
|
return ret;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
2015-04-24 20:39:40 +00:00
|
|
|
BIGNUM *BN_secure_new(void)
|
|
|
|
{
|
|
|
|
BIGNUM *ret = BN_new();
|
2015-10-30 11:12:26 +00:00
|
|
|
if (ret != NULL)
|
2015-04-24 20:39:40 +00:00
|
|
|
ret->flags |= BN_FLG_SECURE;
|
2017-10-17 14:04:09 +00:00
|
|
|
return ret;
|
2015-04-24 20:39:40 +00:00
|
|
|
}
|
|
|
|
|
2016-01-08 04:56:43 +00:00
|
|
|
/* This is used by bn_expand2() */
|
2000-11-06 21:15:54 +00:00
|
|
|
/* The caller MUST check that words > b->dmax before calling this */
|
2008-11-12 03:58:08 +00:00
|
|
|
static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
2017-02-28 17:12:25 +00:00
|
|
|
BN_ULONG *a = NULL;
|
2015-01-22 03:40:55 +00:00
|
|
|
|
|
|
|
if (words > (INT_MAX / (4 * BN_BITS2))) {
|
|
|
|
BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_BIGNUM_TOO_LONG);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (BN_get_flags(b, BN_FLG_STATIC_DATA)) {
|
|
|
|
BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
|
2017-10-17 14:04:09 +00:00
|
|
|
return NULL;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
2016-07-28 19:15:52 +00:00
|
|
|
if (BN_get_flags(b, BN_FLG_SECURE))
|
2017-02-28 17:12:25 +00:00
|
|
|
a = OPENSSL_secure_zalloc(words * sizeof(*a));
|
2015-04-24 20:39:40 +00:00
|
|
|
else
|
2017-02-28 17:12:25 +00:00
|
|
|
a = OPENSSL_zalloc(words * sizeof(*a));
|
|
|
|
if (a == NULL) {
|
2015-01-22 03:40:55 +00:00
|
|
|
BNerr(BN_F_BN_EXPAND_INTERNAL, ERR_R_MALLOC_FAILURE);
|
2017-10-17 14:04:09 +00:00
|
|
|
return NULL;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
2014-07-10 22:47:31 +00:00
|
|
|
|
2017-02-28 17:12:25 +00:00
|
|
|
assert(b->top <= words);
|
2017-03-03 08:56:25 +00:00
|
|
|
if (b->top > 0)
|
|
|
|
memcpy(a, b->d, sizeof(*a) * b->top);
|
1998-12-21 11:00:56 +00:00
|
|
|
|
2017-02-28 17:12:25 +00:00
|
|
|
return a;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is an internal function that should not be used in applications. It
|
|
|
|
* ensures that 'b' has enough room for a 'words' word number and initialises
|
|
|
|
* any unused part of b->d with leading zeros. It is mostly used by the
|
|
|
|
* various BIGNUM routines. If there is an error, NULL is returned. If not,
|
|
|
|
* 'b' is returned.
|
|
|
|
*/
|
2000-11-06 21:15:54 +00:00
|
|
|
|
2008-11-12 03:58:08 +00:00
|
|
|
BIGNUM *bn_expand2(BIGNUM *b, int words)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
if (words > b->dmax) {
|
|
|
|
BN_ULONG *a = bn_expand_internal(b, words);
|
|
|
|
if (!a)
|
|
|
|
return NULL;
|
2019-07-23 06:54:52 +00:00
|
|
|
if (b->d != NULL)
|
|
|
|
bn_free_d(b, 1);
|
2015-01-22 03:40:55 +00:00
|
|
|
b->d = a;
|
|
|
|
b->dmax = words;
|
|
|
|
}
|
2003-12-02 20:01:30 +00:00
|
|
|
|
2015-01-22 03:40:55 +00:00
|
|
|
return b;
|
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
1999-06-04 22:23:10 +00:00
|
|
|
BIGNUM *BN_dup(const BIGNUM *a)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
BIGNUM *t;
|
|
|
|
|
|
|
|
if (a == NULL)
|
|
|
|
return NULL;
|
|
|
|
bn_check_top(a);
|
|
|
|
|
2015-04-24 20:39:40 +00:00
|
|
|
t = BN_get_flags(a, BN_FLG_SECURE) ? BN_secure_new() : BN_new();
|
2015-01-22 03:40:55 +00:00
|
|
|
if (t == NULL)
|
|
|
|
return NULL;
|
|
|
|
if (!BN_copy(t, a)) {
|
|
|
|
BN_free(t);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
bn_check_top(t);
|
|
|
|
return t;
|
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
1999-06-04 22:23:10 +00:00
|
|
|
BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
bn_check_top(b);
|
1998-12-21 11:00:56 +00:00
|
|
|
|
2015-01-22 03:40:55 +00:00
|
|
|
if (a == b)
|
2017-02-28 17:12:25 +00:00
|
|
|
return a;
|
2015-01-22 03:40:55 +00:00
|
|
|
if (bn_wexpand(a, b->top) == NULL)
|
2017-02-28 17:12:25 +00:00
|
|
|
return NULL;
|
1998-12-21 10:56:39 +00:00
|
|
|
|
2017-03-03 08:56:25 +00:00
|
|
|
if (b->top > 0)
|
|
|
|
memcpy(a->d, b->d, sizeof(b->d[0]) * b->top);
|
1998-12-21 10:56:39 +00:00
|
|
|
|
2015-01-22 03:40:55 +00:00
|
|
|
a->neg = b->neg;
|
2018-07-06 13:02:29 +00:00
|
|
|
a->top = b->top;
|
|
|
|
a->flags |= b->flags & BN_FLG_FIXED_TOP;
|
2015-01-22 03:40:55 +00:00
|
|
|
bn_check_top(a);
|
2017-02-28 17:12:25 +00:00
|
|
|
return a;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
2018-04-26 15:08:36 +00:00
|
|
|
#define FLAGS_DATA(flags) ((flags) & (BN_FLG_STATIC_DATA \
|
|
|
|
| BN_FLG_CONSTTIME \
|
2018-07-06 13:02:29 +00:00
|
|
|
| BN_FLG_SECURE \
|
|
|
|
| BN_FLG_FIXED_TOP))
|
2018-04-26 15:08:36 +00:00
|
|
|
#define FLAGS_STRUCT(flags) ((flags) & (BN_FLG_MALLOCED))
|
|
|
|
|
2000-11-26 16:42:38 +00:00
|
|
|
void BN_swap(BIGNUM *a, BIGNUM *b)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
int flags_old_a, flags_old_b;
|
|
|
|
BN_ULONG *tmp_d;
|
|
|
|
int tmp_top, tmp_dmax, tmp_neg;
|
|
|
|
|
|
|
|
bn_check_top(a);
|
|
|
|
bn_check_top(b);
|
|
|
|
|
|
|
|
flags_old_a = a->flags;
|
|
|
|
flags_old_b = b->flags;
|
|
|
|
|
|
|
|
tmp_d = a->d;
|
|
|
|
tmp_top = a->top;
|
|
|
|
tmp_dmax = a->dmax;
|
|
|
|
tmp_neg = a->neg;
|
|
|
|
|
|
|
|
a->d = b->d;
|
|
|
|
a->top = b->top;
|
|
|
|
a->dmax = b->dmax;
|
|
|
|
a->neg = b->neg;
|
|
|
|
|
|
|
|
b->d = tmp_d;
|
|
|
|
b->top = tmp_top;
|
|
|
|
b->dmax = tmp_dmax;
|
|
|
|
b->neg = tmp_neg;
|
|
|
|
|
2018-04-26 15:08:36 +00:00
|
|
|
a->flags = FLAGS_STRUCT(flags_old_a) | FLAGS_DATA(flags_old_b);
|
|
|
|
b->flags = FLAGS_STRUCT(flags_old_b) | FLAGS_DATA(flags_old_a);
|
2015-01-22 03:40:55 +00:00
|
|
|
bn_check_top(a);
|
|
|
|
bn_check_top(b);
|
|
|
|
}
|
2000-11-26 16:42:38 +00:00
|
|
|
|
1999-04-19 21:31:43 +00:00
|
|
|
void BN_clear(BIGNUM *a)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
2019-03-18 23:58:09 +00:00
|
|
|
if (a == NULL)
|
|
|
|
return;
|
2015-01-22 03:40:55 +00:00
|
|
|
bn_check_top(a);
|
|
|
|
if (a->d != NULL)
|
2016-06-24 22:37:27 +00:00
|
|
|
OPENSSL_cleanse(a->d, sizeof(*a->d) * a->dmax);
|
2015-01-22 03:40:55 +00:00
|
|
|
a->neg = 0;
|
2018-07-06 13:02:29 +00:00
|
|
|
a->top = 0;
|
|
|
|
a->flags &= ~BN_FLG_FIXED_TOP;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
2000-11-06 21:15:54 +00:00
|
|
|
BN_ULONG BN_get_word(const BIGNUM *a)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
if (a->top > 1)
|
|
|
|
return BN_MASK2;
|
|
|
|
else if (a->top == 1)
|
|
|
|
return a->d[0];
|
|
|
|
/* a->top == 0 */
|
|
|
|
return 0;
|
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
2004-03-17 17:36:54 +00:00
|
|
|
int BN_set_word(BIGNUM *a, BN_ULONG w)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
bn_check_top(a);
|
|
|
|
if (bn_expand(a, (int)sizeof(BN_ULONG) * 8) == NULL)
|
2017-10-17 14:04:09 +00:00
|
|
|
return 0;
|
2015-01-22 03:40:55 +00:00
|
|
|
a->neg = 0;
|
|
|
|
a->d[0] = w;
|
|
|
|
a->top = (w ? 1 : 0);
|
2018-07-06 13:02:29 +00:00
|
|
|
a->flags &= ~BN_FLG_FIXED_TOP;
|
2015-01-22 03:40:55 +00:00
|
|
|
bn_check_top(a);
|
2017-10-09 11:05:58 +00:00
|
|
|
return 1;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
2008-11-12 03:58:08 +00:00
|
|
|
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
unsigned int i, m;
|
|
|
|
unsigned int n;
|
|
|
|
BN_ULONG l;
|
|
|
|
BIGNUM *bn = NULL;
|
|
|
|
|
|
|
|
if (ret == NULL)
|
|
|
|
ret = bn = BN_new();
|
|
|
|
if (ret == NULL)
|
2017-10-17 14:04:09 +00:00
|
|
|
return NULL;
|
2015-01-22 03:40:55 +00:00
|
|
|
bn_check_top(ret);
|
2015-08-10 16:45:25 +00:00
|
|
|
/* Skip leading zero's. */
|
2015-08-27 21:17:26 +00:00
|
|
|
for ( ; len > 0 && *s == 0; s++, len--)
|
2015-08-10 16:45:25 +00:00
|
|
|
continue;
|
2015-01-22 03:40:55 +00:00
|
|
|
n = len;
|
|
|
|
if (n == 0) {
|
|
|
|
ret->top = 0;
|
2017-10-17 14:04:09 +00:00
|
|
|
return ret;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
|
|
|
i = ((n - 1) / BN_BYTES) + 1;
|
|
|
|
m = ((n - 1) % (BN_BYTES));
|
|
|
|
if (bn_wexpand(ret, (int)i) == NULL) {
|
2015-05-01 01:37:06 +00:00
|
|
|
BN_free(bn);
|
2015-01-22 03:40:55 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ret->top = i;
|
|
|
|
ret->neg = 0;
|
2015-08-10 16:45:25 +00:00
|
|
|
l = 0;
|
2015-01-22 03:40:55 +00:00
|
|
|
while (n--) {
|
|
|
|
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);
|
2017-10-17 14:04:09 +00:00
|
|
|
return ret;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
2019-09-05 21:18:36 +00:00
|
|
|
typedef enum {big, little} endianess_t;
|
|
|
|
|
1998-12-21 10:52:47 +00:00
|
|
|
/* ignore negative */
|
2019-09-05 21:18:36 +00:00
|
|
|
static
|
|
|
|
int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianess_t endianess)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
2018-07-16 16:17:44 +00:00
|
|
|
int n;
|
2018-08-15 13:46:35 +00:00
|
|
|
size_t i, lasti, j, atop, mask;
|
2015-01-22 03:40:55 +00:00
|
|
|
BN_ULONG l;
|
|
|
|
|
2018-08-15 13:46:35 +00:00
|
|
|
/*
|
|
|
|
* 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...
|
|
|
|
*/
|
2018-07-16 16:17:44 +00:00
|
|
|
n = BN_num_bytes(a);
|
2018-08-15 13:46:35 +00:00
|
|
|
if (tolen == -1) {
|
2018-07-16 16:17:44 +00:00
|
|
|
tolen = n;
|
2018-08-15 13:46:35 +00:00
|
|
|
} else if (tolen < n) { /* uncommon/unlike case */
|
|
|
|
BIGNUM temp = *a;
|
2018-02-04 14:20:29 +00:00
|
|
|
|
2018-08-15 13:46:35 +00:00
|
|
|
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) {
|
2018-02-04 14:20:29 +00:00
|
|
|
OPENSSL_cleanse(to, tolen);
|
|
|
|
return tolen;
|
2016-02-01 00:02:05 +00:00
|
|
|
}
|
2018-02-04 14:20:29 +00:00
|
|
|
|
2018-08-15 13:46:35 +00:00
|
|
|
lasti = atop - 1;
|
|
|
|
atop = a->top * BN_BYTES;
|
2019-09-05 21:18:36 +00:00
|
|
|
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;
|
2015-01-22 03:40:55 +00:00
|
|
|
l = a->d[i / BN_BYTES];
|
2018-08-15 13:46:35 +00:00
|
|
|
mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1));
|
2019-09-05 21:18:36 +00:00
|
|
|
val = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask);
|
|
|
|
if (endianess == big)
|
|
|
|
*--to = val;
|
|
|
|
else
|
|
|
|
*to++ = val;
|
2018-08-15 13:46:35 +00:00
|
|
|
i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
2018-02-04 14:20:29 +00:00
|
|
|
|
2016-02-01 00:02:05 +00:00
|
|
|
return tolen;
|
|
|
|
}
|
|
|
|
|
|
|
|
int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
|
|
|
|
{
|
|
|
|
if (tolen < 0)
|
|
|
|
return -1;
|
2019-09-05 21:18:36 +00:00
|
|
|
return bn2binpad(a, to, tolen, big);
|
2016-02-01 00:02:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int BN_bn2bin(const BIGNUM *a, unsigned char *to)
|
|
|
|
{
|
2019-09-05 21:18:36 +00:00
|
|
|
return bn2binpad(a, to, -1, big);
|
2016-02-01 00:02:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret)
|
|
|
|
{
|
|
|
|
unsigned int i, m;
|
|
|
|
unsigned int n;
|
|
|
|
BN_ULONG l;
|
|
|
|
BIGNUM *bn = NULL;
|
|
|
|
|
|
|
|
if (ret == NULL)
|
|
|
|
ret = bn = BN_new();
|
|
|
|
if (ret == NULL)
|
2017-10-17 14:04:09 +00:00
|
|
|
return NULL;
|
2016-02-01 00:02:05 +00:00
|
|
|
bn_check_top(ret);
|
2016-06-06 20:50:25 +00:00
|
|
|
s += len;
|
2016-02-01 00:02:05 +00:00
|
|
|
/* Skip trailing zeroes. */
|
2016-06-06 20:50:25 +00:00
|
|
|
for ( ; len > 0 && s[-1] == 0; s--, len--)
|
2016-02-01 00:02:05 +00:00
|
|
|
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) == NULL) {
|
|
|
|
BN_free(bn);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ret->top = i;
|
|
|
|
ret->neg = 0;
|
|
|
|
l = 0;
|
|
|
|
while (n--) {
|
2016-06-06 20:50:25 +00:00
|
|
|
s--;
|
|
|
|
l = (l << 8L) | *s;
|
2016-02-01 00:02:05 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen)
|
|
|
|
{
|
2019-09-05 21:18:36 +00:00
|
|
|
if (tolen < 0)
|
2016-02-01 00:02:05 +00:00
|
|
|
return -1;
|
2019-09-05 21:18:36 +00:00
|
|
|
return bn2binpad(a, to, tolen, little);
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
1999-06-04 22:23:10 +00:00
|
|
|
int BN_ucmp(const BIGNUM *a, const BIGNUM *b)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
BN_ULONG t1, t2, *ap, *bp;
|
|
|
|
|
|
|
|
bn_check_top(a);
|
|
|
|
bn_check_top(b);
|
|
|
|
|
|
|
|
i = a->top - b->top;
|
|
|
|
if (i != 0)
|
2017-10-17 14:04:09 +00:00
|
|
|
return i;
|
2015-01-22 03:40:55 +00:00
|
|
|
ap = a->d;
|
|
|
|
bp = b->d;
|
|
|
|
for (i = a->top - 1; i >= 0; i--) {
|
|
|
|
t1 = ap[i];
|
|
|
|
t2 = bp[i];
|
|
|
|
if (t1 != t2)
|
|
|
|
return ((t1 > t2) ? 1 : -1);
|
|
|
|
}
|
2017-10-17 14:04:09 +00:00
|
|
|
return 0;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
1999-06-04 22:23:10 +00:00
|
|
|
int BN_cmp(const BIGNUM *a, const BIGNUM *b)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int gt, lt;
|
|
|
|
BN_ULONG t1, t2;
|
|
|
|
|
|
|
|
if ((a == NULL) || (b == NULL)) {
|
|
|
|
if (a != NULL)
|
2017-10-17 14:04:09 +00:00
|
|
|
return -1;
|
2015-01-22 03:40:55 +00:00
|
|
|
else if (b != NULL)
|
2017-10-09 11:05:58 +00:00
|
|
|
return 1;
|
2015-01-22 03:40:55 +00:00
|
|
|
else
|
2017-10-17 14:04:09 +00:00
|
|
|
return 0;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bn_check_top(a);
|
|
|
|
bn_check_top(b);
|
|
|
|
|
|
|
|
if (a->neg != b->neg) {
|
|
|
|
if (a->neg)
|
2017-10-17 14:04:09 +00:00
|
|
|
return -1;
|
2015-01-22 03:40:55 +00:00
|
|
|
else
|
2017-10-09 11:05:58 +00:00
|
|
|
return 1;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
|
|
|
if (a->neg == 0) {
|
|
|
|
gt = 1;
|
|
|
|
lt = -1;
|
|
|
|
} else {
|
|
|
|
gt = -1;
|
|
|
|
lt = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->top > b->top)
|
2017-10-17 14:04:09 +00:00
|
|
|
return gt;
|
2015-01-22 03:40:55 +00:00
|
|
|
if (a->top < b->top)
|
2017-10-17 14:04:09 +00:00
|
|
|
return lt;
|
2015-01-22 03:40:55 +00:00
|
|
|
for (i = a->top - 1; i >= 0; i--) {
|
|
|
|
t1 = a->d[i];
|
|
|
|
t2 = b->d[i];
|
|
|
|
if (t1 > t2)
|
2017-10-17 14:04:09 +00:00
|
|
|
return gt;
|
2015-01-22 03:40:55 +00:00
|
|
|
if (t1 < t2)
|
2017-10-17 14:04:09 +00:00
|
|
|
return lt;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
2017-10-17 14:04:09 +00:00
|
|
|
return 0;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
1999-04-19 21:31:43 +00:00
|
|
|
int BN_set_bit(BIGNUM *a, int n)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
int i, j, k;
|
|
|
|
|
|
|
|
if (n < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
i = n / BN_BITS2;
|
|
|
|
j = n % BN_BITS2;
|
|
|
|
if (a->top <= i) {
|
|
|
|
if (bn_wexpand(a, i + 1) == NULL)
|
2017-10-17 14:04:09 +00:00
|
|
|
return 0;
|
2015-01-22 03:40:55 +00:00
|
|
|
for (k = a->top; k < i + 1; k++)
|
|
|
|
a->d[k] = 0;
|
|
|
|
a->top = i + 1;
|
2018-07-06 13:02:29 +00:00
|
|
|
a->flags &= ~BN_FLG_FIXED_TOP;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
a->d[i] |= (((BN_ULONG)1) << j);
|
|
|
|
bn_check_top(a);
|
2017-10-09 11:05:58 +00:00
|
|
|
return 1;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
1999-04-19 21:31:43 +00:00
|
|
|
int BN_clear_bit(BIGNUM *a, int n)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
1998-12-21 10:52:47 +00:00
|
|
|
|
2015-01-22 03:40:55 +00:00
|
|
|
bn_check_top(a);
|
|
|
|
if (n < 0)
|
|
|
|
return 0;
|
2003-11-15 08:37:50 +00:00
|
|
|
|
2015-01-22 03:40:55 +00:00
|
|
|
i = n / BN_BITS2;
|
|
|
|
j = n % BN_BITS2;
|
|
|
|
if (a->top <= i)
|
2017-10-17 14:04:09 +00:00
|
|
|
return 0;
|
1998-12-21 10:52:47 +00:00
|
|
|
|
2015-01-22 03:40:55 +00:00
|
|
|
a->d[i] &= (~(((BN_ULONG)1) << j));
|
|
|
|
bn_correct_top(a);
|
2017-10-09 11:05:58 +00:00
|
|
|
return 1;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
1999-06-04 22:23:10 +00:00
|
|
|
int BN_is_bit_set(const BIGNUM *a, int n)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
bn_check_top(a);
|
|
|
|
if (n < 0)
|
|
|
|
return 0;
|
|
|
|
i = n / BN_BITS2;
|
|
|
|
j = n % BN_BITS2;
|
|
|
|
if (a->top <= i)
|
|
|
|
return 0;
|
|
|
|
return (int)(((a->d[i]) >> j) & ((BN_ULONG)1));
|
|
|
|
}
|
1998-12-21 10:52:47 +00:00
|
|
|
|
1999-04-19 21:31:43 +00:00
|
|
|
int BN_mask_bits(BIGNUM *a, int n)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
int b, w;
|
|
|
|
|
|
|
|
bn_check_top(a);
|
|
|
|
if (n < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
w = n / BN_BITS2;
|
|
|
|
b = n % BN_BITS2;
|
|
|
|
if (w >= a->top)
|
|
|
|
return 0;
|
|
|
|
if (b == 0)
|
|
|
|
a->top = w;
|
|
|
|
else {
|
|
|
|
a->top = w + 1;
|
|
|
|
a->d[w] &= ~(BN_MASK2 << b);
|
|
|
|
}
|
|
|
|
bn_correct_top(a);
|
2017-10-09 11:05:58 +00:00
|
|
|
return 1;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
1998-12-21 11:00:56 +00:00
|
|
|
|
2005-04-22 20:02:44 +00:00
|
|
|
void BN_set_negative(BIGNUM *a, int b)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
if (b && !BN_is_zero(a))
|
|
|
|
a->neg = 1;
|
|
|
|
else
|
|
|
|
a->neg = 0;
|
|
|
|
}
|
2005-04-22 20:02:44 +00:00
|
|
|
|
2000-11-16 22:43:32 +00:00
|
|
|
int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
BN_ULONG aa, bb;
|
|
|
|
|
2019-02-25 11:28:32 +00:00
|
|
|
if (n == 0)
|
|
|
|
return 0;
|
|
|
|
|
2015-01-22 03:40:55 +00:00
|
|
|
aa = a[n - 1];
|
|
|
|
bb = b[n - 1];
|
|
|
|
if (aa != bb)
|
|
|
|
return ((aa > bb) ? 1 : -1);
|
|
|
|
for (i = n - 2; i >= 0; i--) {
|
|
|
|
aa = a[i];
|
|
|
|
bb = b[i];
|
|
|
|
if (aa != bb)
|
|
|
|
return ((aa > bb) ? 1 : -1);
|
|
|
|
}
|
2017-10-17 14:04:09 +00:00
|
|
|
return 0;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Here follows a specialised variants of bn_cmp_words(). It has the
|
2016-03-14 11:39:32 +00:00
|
|
|
* capability of performing the operation on arrays of different sizes. The
|
2015-01-22 03:40:55 +00:00
|
|
|
* sizes of those arrays is expressed through cl, which is the common length
|
2016-03-14 11:39:32 +00:00
|
|
|
* ( basically, min(len(a),len(b)) ), and dl, which is the delta between the
|
2015-01-22 03:40:55 +00:00
|
|
|
* two lengths, calculated as len(a)-len(b). All lengths are the number of
|
|
|
|
* BN_ULONGs...
|
|
|
|
*/
|
|
|
|
|
|
|
|
int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl)
|
|
|
|
{
|
|
|
|
int n, i;
|
|
|
|
n = cl - 1;
|
|
|
|
|
|
|
|
if (dl < 0) {
|
|
|
|
for (i = dl; i < 0; i++) {
|
|
|
|
if (b[n - i] != 0)
|
|
|
|
return -1; /* a < b */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dl > 0) {
|
|
|
|
for (i = dl; i > 0; i--) {
|
|
|
|
if (a[n + i] != 0)
|
|
|
|
return 1; /* a > b */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bn_cmp_words(a, b, cl);
|
|
|
|
}
|
|
|
|
|
2018-11-12 13:47:54 +00:00
|
|
|
/*-
|
2015-01-22 03:40:55 +00:00
|
|
|
* Constant-time conditional swap of a and b.
|
2018-11-12 13:47:54 +00:00
|
|
|
* 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.
|
2014-03-12 14:16:19 +00:00
|
|
|
*/
|
|
|
|
void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
BN_ULONG t;
|
|
|
|
int i;
|
2014-03-12 14:16:19 +00:00
|
|
|
|
2018-11-12 13:47:54 +00:00
|
|
|
if (a == b)
|
|
|
|
return;
|
|
|
|
|
2015-01-22 03:40:55 +00:00
|
|
|
bn_wcheck_size(a, nwords);
|
|
|
|
bn_wcheck_size(b, nwords);
|
2014-03-12 14:16:19 +00:00
|
|
|
|
2018-11-12 13:47:54 +00:00
|
|
|
condition = ((~condition & ((condition - 1))) >> (BN_BITS2 - 1)) - 1;
|
2014-03-12 14:16:19 +00:00
|
|
|
|
2015-01-22 03:40:55 +00:00
|
|
|
t = (a->top ^ b->top) & condition;
|
|
|
|
a->top ^= t;
|
|
|
|
b->top ^= t;
|
2014-03-12 14:16:19 +00:00
|
|
|
|
2018-04-19 09:21:51 +00:00
|
|
|
t = (a->neg ^ b->neg) & condition;
|
|
|
|
a->neg ^= t;
|
|
|
|
b->neg ^= t;
|
|
|
|
|
2018-04-23 11:34:11 +00:00
|
|
|
/*-
|
2018-11-09 07:25:43 +00:00
|
|
|
* 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
|
2018-04-19 09:21:51 +00:00
|
|
|
*/
|
2018-11-09 07:25:43 +00:00
|
|
|
|
|
|
|
#define BN_CONSTTIME_SWAP_FLAGS (BN_FLG_CONSTTIME | BN_FLG_FIXED_TOP)
|
|
|
|
|
|
|
|
t = ((a->flags ^ b->flags) & BN_CONSTTIME_SWAP_FLAGS) & condition;
|
2018-04-19 09:21:51 +00:00
|
|
|
a->flags ^= t;
|
|
|
|
b->flags ^= t;
|
|
|
|
|
2018-11-12 13:47:54 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2014-03-12 14:16:19 +00:00
|
|
|
}
|
2014-01-18 14:51:40 +00:00
|
|
|
|
2018-11-12 13:47:54 +00:00
|
|
|
#undef BN_CONSTTIME_SWAP_FLAGS
|
|
|
|
|
2014-01-18 14:51:40 +00:00
|
|
|
/* Bits of security, see SP800-57 */
|
|
|
|
|
|
|
|
int BN_security_bits(int L, int N)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
int secbits, bits;
|
|
|
|
if (L >= 15360)
|
|
|
|
secbits = 256;
|
2017-10-18 09:23:33 +00:00
|
|
|
else if (L >= 7680)
|
2015-01-22 03:40:55 +00:00
|
|
|
secbits = 192;
|
|
|
|
else if (L >= 3072)
|
|
|
|
secbits = 128;
|
|
|
|
else if (L >= 2048)
|
|
|
|
secbits = 112;
|
|
|
|
else if (L >= 1024)
|
|
|
|
secbits = 80;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
if (N == -1)
|
|
|
|
return secbits;
|
|
|
|
bits = N / 2;
|
|
|
|
if (bits < 80)
|
|
|
|
return 0;
|
|
|
|
return bits >= secbits ? secbits : bits;
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
void BN_zero_ex(BIGNUM *a)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
a->neg = 0;
|
2018-07-06 13:02:29 +00:00
|
|
|
a->top = 0;
|
|
|
|
a->flags &= ~BN_FLG_FIXED_TOP;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
return ((a->top == 1) && (a->d[0] == w)) || ((w == 0) && (a->top == 0));
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
int BN_is_zero(const BIGNUM *a)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
return a->top == 0;
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
int BN_is_one(const BIGNUM *a)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
return BN_abs_is_word(a, 1) && !a->neg;
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
int BN_is_word(const BIGNUM *a, const BN_ULONG w)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
return BN_abs_is_word(a, w) && (!w || !a->neg);
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
int BN_is_odd(const BIGNUM *a)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
return (a->top > 0) && (a->d[0] & 1);
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
int BN_is_negative(const BIGNUM *a)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
return (a->neg != 0);
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
2015-01-22 03:40:55 +00:00
|
|
|
int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
|
|
|
|
BN_CTX *ctx)
|
|
|
|
{
|
|
|
|
return BN_mod_mul_montgomery(r, a, &(mont->RR), mont, ctx);
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
2015-11-24 11:09:00 +00:00
|
|
|
void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
dest->d = b->d;
|
|
|
|
dest->top = b->top;
|
|
|
|
dest->dmax = b->dmax;
|
|
|
|
dest->neg = b->neg;
|
|
|
|
dest->flags = ((dest->flags & BN_FLG_MALLOCED)
|
|
|
|
| (b->flags & ~BN_FLG_MALLOCED)
|
2015-11-24 11:09:00 +00:00
|
|
|
| BN_FLG_STATIC_DATA | flags);
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
BN_GENCB *BN_GENCB_new(void)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
BN_GENCB *ret;
|
2014-11-24 10:06:20 +00:00
|
|
|
|
2015-05-02 03:10:31 +00:00
|
|
|
if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) {
|
2015-01-22 03:40:55 +00:00
|
|
|
BNerr(BN_F_BN_GENCB_NEW, ERR_R_MALLOC_FAILURE);
|
2017-10-17 14:04:09 +00:00
|
|
|
return NULL;
|
2015-01-22 03:40:55 +00:00
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
2015-01-22 03:40:55 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
void BN_GENCB_free(BN_GENCB *cb)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
if (cb == NULL)
|
|
|
|
return;
|
|
|
|
OPENSSL_free(cb);
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
void BN_set_flags(BIGNUM *b, int n)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
b->flags |= n;
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
int BN_get_flags(const BIGNUM *b, int n)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
return b->flags & n;
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
/* Populate a BN_GENCB structure with an "old"-style callback */
|
2015-01-22 03:40:55 +00:00
|
|
|
void BN_GENCB_set_old(BN_GENCB *gencb, void (*callback) (int, int, void *),
|
|
|
|
void *cb_arg)
|
|
|
|
{
|
|
|
|
BN_GENCB *tmp_gencb = gencb;
|
|
|
|
tmp_gencb->ver = 1;
|
|
|
|
tmp_gencb->arg = cb_arg;
|
|
|
|
tmp_gencb->cb.cb_1 = callback;
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
/* Populate a BN_GENCB structure with a "new"-style callback */
|
2015-01-22 03:40:55 +00:00
|
|
|
void BN_GENCB_set(BN_GENCB *gencb, int (*callback) (int, int, BN_GENCB *),
|
|
|
|
void *cb_arg)
|
|
|
|
{
|
|
|
|
BN_GENCB *tmp_gencb = gencb;
|
|
|
|
tmp_gencb->ver = 2;
|
|
|
|
tmp_gencb->arg = cb_arg;
|
|
|
|
tmp_gencb->cb.cb_2 = callback;
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
void *BN_GENCB_get_arg(BN_GENCB *cb)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
return cb->arg;
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
BIGNUM *bn_wexpand(BIGNUM *a, int words)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
return (words <= a->dmax) ? a : bn_expand2(a, words);
|
|
|
|
}
|
2014-11-24 10:06:20 +00:00
|
|
|
|
|
|
|
void bn_correct_top(BIGNUM *a)
|
2015-01-22 03:40:55 +00:00
|
|
|
{
|
|
|
|
BN_ULONG *ftl;
|
|
|
|
int tmp_top = a->top;
|
|
|
|
|
|
|
|
if (tmp_top > 0) {
|
2016-05-21 14:53:14 +00:00
|
|
|
for (ftl = &(a->d[tmp_top]); tmp_top > 0; tmp_top--) {
|
|
|
|
ftl--;
|
|
|
|
if (*ftl != 0)
|
2015-01-22 03:40:55 +00:00
|
|
|
break;
|
2016-05-21 14:53:14 +00:00
|
|
|
}
|
2015-01-22 03:40:55 +00:00
|
|
|
a->top = tmp_top;
|
|
|
|
}
|
2016-09-05 22:08:43 +00:00
|
|
|
if (a->top == 0)
|
|
|
|
a->neg = 0;
|
2018-07-06 13:02:29 +00:00
|
|
|
a->flags &= ~BN_FLG_FIXED_TOP;
|
2015-01-22 03:40:55 +00:00
|
|
|
bn_pollute(a);
|
|
|
|
}
|