2016-05-18 02:51:04 +08:00
|
|
|
/*
|
2022-05-03 18:52:38 +08:00
|
|
|
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
|
1998-12-21 18:52:47 +08:00
|
|
|
*
|
2018-12-06 20:22:12 +08:00
|
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
2016-05-18 02:51:04 +08:00
|
|
|
* 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 18:52:47 +08:00
|
|
|
*/
|
|
|
|
|
2000-09-04 23:34:43 +08:00
|
|
|
#include <assert.h>
|
2000-12-03 17:55:08 +08:00
|
|
|
#include <limits.h>
|
2015-05-14 22:56:48 +08:00
|
|
|
#include "internal/cryptlib.h"
|
2020-07-09 14:40:50 +08:00
|
|
|
#include "internal/endian.h"
|
2019-09-28 06:45:40 +08:00
|
|
|
#include "bn_local.h"
|
2016-01-05 12:00:33 +08:00
|
|
|
#include <openssl/opensslconf.h>
|
2019-09-28 06:45:40 +08:00
|
|
|
#include "internal/constant_time.h"
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2004-06-18 07:50:25 +08:00
|
|
|
/* This stuff appears to be completely unused, so is deprecated */
|
2019-11-06 00:34:09 +08:00
|
|
|
#ifndef OPENSSL_NO_DEPRECATED_0_9_8
|
2014-12-28 10:48:40 +08:00
|
|
|
/*-
|
|
|
|
* For a 32 bit machine
|
1998-12-21 19:00:56 +08: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 11:40:55 +08: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 19:00:56 +08:00
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
void BN_set_params(int mult, int high, int low, int mont)
|
2015-01-22 11:40:55 +08: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 19:00:56 +08:00
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
int BN_get_params(int which)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (which == 0)
|
2017-10-17 22:04:09 +08:00
|
|
|
return bn_limit_bits;
|
2015-01-22 11:40:55 +08:00
|
|
|
else if (which == 1)
|
2017-10-17 22:04:09 +08:00
|
|
|
return bn_limit_bits_high;
|
2015-01-22 11:40:55 +08:00
|
|
|
else if (which == 2)
|
2017-10-17 22:04:09 +08:00
|
|
|
return bn_limit_bits_low;
|
2015-01-22 11:40:55 +08:00
|
|
|
else if (which == 3)
|
2017-10-17 22:04:09 +08:00
|
|
|
return bn_limit_bits_mont;
|
2015-01-22 11:40:55 +08:00
|
|
|
else
|
2017-10-17 22:04:09 +08:00
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2004-06-18 07:50:25 +08:00
|
|
|
#endif
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2001-03-08 21:58:09 +08:00
|
|
|
const BIGNUM *BN_value_one(void)
|
2015-01-22 11:40:55 +08: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 18:52:47 +08:00
|
|
|
|
2017-10-17 22:04:09 +08:00
|
|
|
return &const_one;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2020-04-12 02:58:44 +08:00
|
|
|
/*
|
|
|
|
* Old Visual Studio ARM compiler miscompiles BN_num_bits_word()
|
|
|
|
* https://mta.openssl.org/pipermail/openssl-users/2018-August/008465.html
|
|
|
|
*/
|
|
|
|
#if defined(_MSC_VER) && defined(_ARM_) && defined(_WIN32_WCE) \
|
|
|
|
&& _MSC_VER>=1400 && _MSC_VER<1501
|
|
|
|
# define MS_BROKEN_BN_num_bits_word
|
|
|
|
# pragma optimize("", off)
|
|
|
|
#endif
|
1999-04-20 05:31:43 +08:00
|
|
|
int BN_num_bits_word(BN_ULONG l)
|
2015-01-22 11:40:55 +08: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-24 02:46:53 +08: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 18:52:47 +08: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-24 02:46:53 +08: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 11:40:55 +08:00
|
|
|
}
|
2020-04-12 02:58:44 +08:00
|
|
|
#ifdef MS_BROKEN_BN_num_bits_word
|
|
|
|
# pragma optimize("", on)
|
|
|
|
#endif
|
1998-12-21 18:52:47 +08: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)
2019-08-02 07:08:34 +08: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-05 06:23:10 +08:00
|
|
|
int BN_num_bits(const BIGNUM *a)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int i = a->top - 1;
|
|
|
|
bn_check_top(a);
|
1998-12-21 19:00:56 +08: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)
2019-08-02 07:08:34 +08: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 11:40:55 +08: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)
2019-08-02 07:08:34 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
return ((i * BN_BITS2) + BN_num_bits_word(a->d[i]));
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2019-07-23 14:54:52 +08:00
|
|
|
static void bn_free_d(BIGNUM *a, int clear)
|
2015-07-22 18:44:50 +08:00
|
|
|
{
|
2016-07-29 03:15:52 +08:00
|
|
|
if (BN_get_flags(a, BN_FLG_SECURE))
|
2019-07-23 14:54:52 +08: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 18:44:50 +08:00
|
|
|
else
|
|
|
|
OPENSSL_free(a->d);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
void BN_clear_free(BIGNUM *a)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (a == NULL)
|
|
|
|
return;
|
2019-07-23 14:54:52 +08:00
|
|
|
if (a->d != NULL && !BN_get_flags(a, BN_FLG_STATIC_DATA))
|
|
|
|
bn_free_d(a, 1);
|
2017-10-09 04:04:05 +08:00
|
|
|
if (BN_get_flags(a, BN_FLG_MALLOCED)) {
|
|
|
|
OPENSSL_cleanse(a, sizeof(*a));
|
2015-01-22 11:40:55 +08:00
|
|
|
OPENSSL_free(a);
|
2017-10-09 04:04:05 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
void BN_free(BIGNUM *a)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (a == NULL)
|
|
|
|
return;
|
2015-05-01 22:02:07 +08:00
|
|
|
if (!BN_get_flags(a, BN_FLG_STATIC_DATA))
|
2019-07-23 14:54:52 +08:00
|
|
|
bn_free_d(a, 0);
|
2015-01-22 11:40:55 +08:00
|
|
|
if (a->flags & BN_FLG_MALLOCED)
|
|
|
|
OPENSSL_free(a);
|
|
|
|
}
|
1998-12-21 19:00:56 +08:00
|
|
|
|
2015-11-21 21:27:46 +08:00
|
|
|
void bn_init(BIGNUM *a)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2015-11-21 21:27:46 +08:00
|
|
|
static BIGNUM nilbn;
|
|
|
|
|
|
|
|
*a = nilbn;
|
2015-01-22 11:40:55 +08:00
|
|
|
bn_check_top(a);
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
BIGNUM *BN_new(void)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
BIGNUM *ret;
|
|
|
|
|
2022-09-29 19:57:34 +08:00
|
|
|
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL)
|
2017-10-17 22:04:09 +08:00
|
|
|
return NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
ret->flags = BN_FLG_MALLOCED;
|
|
|
|
bn_check_top(ret);
|
2017-10-17 22:04:09 +08:00
|
|
|
return ret;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2015-04-25 04:39:40 +08:00
|
|
|
BIGNUM *BN_secure_new(void)
|
|
|
|
{
|
|
|
|
BIGNUM *ret = BN_new();
|
2015-10-30 19:12:26 +08:00
|
|
|
if (ret != NULL)
|
2015-04-25 04:39:40 +08:00
|
|
|
ret->flags |= BN_FLG_SECURE;
|
2017-10-17 22:04:09 +08:00
|
|
|
return ret;
|
2015-04-25 04:39:40 +08:00
|
|
|
}
|
|
|
|
|
2016-01-08 12:56:43 +08:00
|
|
|
/* This is used by bn_expand2() */
|
2000-11-07 05:15:54 +08:00
|
|
|
/* The caller MUST check that words > b->dmax before calling this */
|
2008-11-12 11:58:08 +08:00
|
|
|
static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2017-03-01 01:12:25 +08:00
|
|
|
BN_ULONG *a = NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
|
|
|
if (words > (INT_MAX / (4 * BN_BITS2))) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_BN, BN_R_BIGNUM_TOO_LONG);
|
2015-01-22 11:40:55 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (BN_get_flags(b, BN_FLG_STATIC_DATA)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_BN, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
|
2017-10-17 22:04:09 +08:00
|
|
|
return NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2016-07-29 03:15:52 +08:00
|
|
|
if (BN_get_flags(b, BN_FLG_SECURE))
|
2017-03-01 01:12:25 +08:00
|
|
|
a = OPENSSL_secure_zalloc(words * sizeof(*a));
|
2015-04-25 04:39:40 +08:00
|
|
|
else
|
2017-03-01 01:12:25 +08:00
|
|
|
a = OPENSSL_zalloc(words * sizeof(*a));
|
2022-09-29 19:57:34 +08:00
|
|
|
if (a == NULL)
|
2017-10-17 22:04:09 +08:00
|
|
|
return NULL;
|
2014-07-11 06:47:31 +08:00
|
|
|
|
2017-03-01 01:12:25 +08:00
|
|
|
assert(b->top <= words);
|
2017-03-03 16:56:25 +08:00
|
|
|
if (b->top > 0)
|
|
|
|
memcpy(a, b->d, sizeof(*a) * b->top);
|
1998-12-21 19:00:56 +08:00
|
|
|
|
2017-03-01 01:12:25 +08:00
|
|
|
return a;
|
2015-01-22 11:40:55 +08: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-07 05:15:54 +08:00
|
|
|
|
2008-11-12 11:58:08 +08:00
|
|
|
BIGNUM *bn_expand2(BIGNUM *b, int words)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (words > b->dmax) {
|
|
|
|
BN_ULONG *a = bn_expand_internal(b, words);
|
|
|
|
if (!a)
|
|
|
|
return NULL;
|
2019-07-23 14:54:52 +08:00
|
|
|
if (b->d != NULL)
|
|
|
|
bn_free_d(b, 1);
|
2015-01-22 11:40:55 +08:00
|
|
|
b->d = a;
|
|
|
|
b->dmax = words;
|
|
|
|
}
|
2003-12-03 04:01:30 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
return b;
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
1999-06-05 06:23:10 +08:00
|
|
|
BIGNUM *BN_dup(const BIGNUM *a)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
BIGNUM *t;
|
|
|
|
|
|
|
|
if (a == NULL)
|
|
|
|
return NULL;
|
|
|
|
bn_check_top(a);
|
|
|
|
|
2015-04-25 04:39:40 +08:00
|
|
|
t = BN_get_flags(a, BN_FLG_SECURE) ? BN_secure_new() : BN_new();
|
2015-01-22 11:40:55 +08: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 18:52:47 +08:00
|
|
|
|
1999-06-05 06:23:10 +08:00
|
|
|
BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2020-01-21 23:08:16 +08:00
|
|
|
int bn_words;
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
bn_check_top(b);
|
1998-12-21 19:00:56 +08:00
|
|
|
|
2020-01-21 23:08:16 +08:00
|
|
|
bn_words = BN_get_flags(b, BN_FLG_CONSTTIME) ? b->dmax : b->top;
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (a == b)
|
2017-03-01 01:12:25 +08:00
|
|
|
return a;
|
2020-01-21 23:08:16 +08:00
|
|
|
if (bn_wexpand(a, bn_words) == NULL)
|
2017-03-01 01:12:25 +08:00
|
|
|
return NULL;
|
1998-12-21 18:56:39 +08:00
|
|
|
|
2017-03-03 16:56:25 +08:00
|
|
|
if (b->top > 0)
|
2020-01-21 23:08:16 +08:00
|
|
|
memcpy(a->d, b->d, sizeof(b->d[0]) * bn_words);
|
1998-12-21 18:56:39 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
a->neg = b->neg;
|
2018-07-06 21:02:29 +08:00
|
|
|
a->top = b->top;
|
|
|
|
a->flags |= b->flags & BN_FLG_FIXED_TOP;
|
2015-01-22 11:40:55 +08:00
|
|
|
bn_check_top(a);
|
2017-03-01 01:12:25 +08:00
|
|
|
return a;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2018-04-26 23:08:36 +08:00
|
|
|
#define FLAGS_DATA(flags) ((flags) & (BN_FLG_STATIC_DATA \
|
|
|
|
| BN_FLG_CONSTTIME \
|
2018-07-06 21:02:29 +08:00
|
|
|
| BN_FLG_SECURE \
|
|
|
|
| BN_FLG_FIXED_TOP))
|
2018-04-26 23:08:36 +08:00
|
|
|
#define FLAGS_STRUCT(flags) ((flags) & (BN_FLG_MALLOCED))
|
|
|
|
|
2000-11-27 00:42:38 +08:00
|
|
|
void BN_swap(BIGNUM *a, BIGNUM *b)
|
2015-01-22 11:40:55 +08: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 23:08:36 +08: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 11:40:55 +08:00
|
|
|
bn_check_top(a);
|
|
|
|
bn_check_top(b);
|
|
|
|
}
|
2000-11-27 00:42:38 +08:00
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
void BN_clear(BIGNUM *a)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2019-03-19 07:58:09 +08:00
|
|
|
if (a == NULL)
|
|
|
|
return;
|
2015-01-22 11:40:55 +08:00
|
|
|
bn_check_top(a);
|
|
|
|
if (a->d != NULL)
|
2016-06-25 06:37:27 +08:00
|
|
|
OPENSSL_cleanse(a->d, sizeof(*a->d) * a->dmax);
|
2015-01-22 11:40:55 +08:00
|
|
|
a->neg = 0;
|
2018-07-06 21:02:29 +08:00
|
|
|
a->top = 0;
|
|
|
|
a->flags &= ~BN_FLG_FIXED_TOP;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2000-11-07 05:15:54 +08:00
|
|
|
BN_ULONG BN_get_word(const BIGNUM *a)
|
2015-01-22 11:40:55 +08: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 18:52:47 +08:00
|
|
|
|
2004-03-18 01:36:54 +08:00
|
|
|
int BN_set_word(BIGNUM *a, BN_ULONG w)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
bn_check_top(a);
|
|
|
|
if (bn_expand(a, (int)sizeof(BN_ULONG) * 8) == NULL)
|
2017-10-17 22:04:09 +08:00
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
a->neg = 0;
|
|
|
|
a->d[0] = w;
|
|
|
|
a->top = (w ? 1 : 0);
|
2018-07-06 21:02:29 +08:00
|
|
|
a->flags &= ~BN_FLG_FIXED_TOP;
|
2015-01-22 11:40:55 +08:00
|
|
|
bn_check_top(a);
|
2017-10-09 19:05:58 +08:00
|
|
|
return 1;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2021-11-24 14:10:13 +08:00
|
|
|
typedef enum {BIG, LITTLE} endianess_t;
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
typedef enum {SIGNED, UNSIGNED} signedness_t;
|
2021-11-24 14:10:13 +08:00
|
|
|
|
|
|
|
static BIGNUM *bin2bn(const unsigned char *s, int len, BIGNUM *ret,
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
endianess_t endianess, signedness_t signedness)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2021-11-24 14:10:13 +08:00
|
|
|
int inc;
|
2021-11-24 15:23:02 +08:00
|
|
|
const unsigned char *s2;
|
|
|
|
int inc2;
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
int neg = 0, xor = 0, carry = 0;
|
2021-11-24 15:23:02 +08:00
|
|
|
unsigned int i;
|
2015-01-22 11:40:55 +08:00
|
|
|
unsigned int n;
|
|
|
|
BIGNUM *bn = NULL;
|
|
|
|
|
|
|
|
if (ret == NULL)
|
|
|
|
ret = bn = BN_new();
|
|
|
|
if (ret == NULL)
|
2017-10-17 22:04:09 +08:00
|
|
|
return NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
bn_check_top(ret);
|
2021-11-24 14:10:13 +08:00
|
|
|
|
|
|
|
/*
|
2021-11-24 15:23:02 +08:00
|
|
|
* The loop that does the work iterates from least to most
|
2022-02-04 00:51:26 +08:00
|
|
|
* significant BIGNUM chunk, so we adapt parameters to transfer
|
2021-11-24 14:10:13 +08:00
|
|
|
* input bytes accordingly.
|
|
|
|
*/
|
2022-01-22 08:22:31 +08:00
|
|
|
if (endianess == LITTLE) {
|
2021-11-24 15:23:02 +08:00
|
|
|
s2 = s + len - 1;
|
|
|
|
inc2 = -1;
|
|
|
|
inc = 1;
|
2022-01-22 08:22:31 +08:00
|
|
|
} else {
|
2021-11-24 15:23:02 +08:00
|
|
|
s2 = s;
|
|
|
|
inc2 = 1;
|
|
|
|
inc = -1;
|
|
|
|
s += len - 1;
|
2021-11-24 14:10:13 +08:00
|
|
|
}
|
|
|
|
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
/* Take note of the signedness of the input bytes*/
|
|
|
|
if (signedness == SIGNED) {
|
|
|
|
neg = !!(*s2 & 0x80);
|
|
|
|
xor = neg ? 0xff : 0x00;
|
|
|
|
carry = neg;
|
|
|
|
}
|
|
|
|
|
2021-11-24 15:23:02 +08:00
|
|
|
/*
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
* Skip leading sign extensions (the value of |xor|).
|
2021-11-24 15:23:02 +08:00
|
|
|
* This is the only spot where |s2| and |inc2| are used.
|
|
|
|
*/
|
|
|
|
for ( ; len > 0 && *s2 == xor; s2 += inc2, len--)
|
2015-08-11 00:45:25 +08:00
|
|
|
continue;
|
2021-11-24 15:23:02 +08:00
|
|
|
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
/*
|
|
|
|
* If there was a set of 0xff, we backtrack one byte unless the next
|
|
|
|
* one has a sign bit, as the last 0xff is then part of the actual
|
|
|
|
* number, rather then a mere sign extension.
|
|
|
|
*/
|
|
|
|
if (xor == 0xff) {
|
|
|
|
if (len == 0 || !(*s2 & 0x80))
|
|
|
|
len++;
|
|
|
|
}
|
|
|
|
/* If it was all zeros, we're done */
|
2021-11-24 15:23:02 +08:00
|
|
|
if (len == 0) {
|
2015-01-22 11:40:55 +08:00
|
|
|
ret->top = 0;
|
2017-10-17 22:04:09 +08:00
|
|
|
return ret;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2021-11-24 15:23:02 +08:00
|
|
|
n = ((len - 1) / BN_BYTES) + 1; /* Number of resulting bignum chunks */
|
|
|
|
if (!ossl_assert(bn_wexpand(ret, (int)n) != NULL)) {
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_free(bn);
|
2015-01-22 11:40:55 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2021-11-24 15:23:02 +08:00
|
|
|
ret->top = n;
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
ret->neg = neg;
|
2021-11-24 15:23:02 +08:00
|
|
|
for (i = 0; n-- > 0; i++) {
|
|
|
|
BN_ULONG l = 0; /* Accumulator */
|
|
|
|
unsigned int m = 0; /* Offset in a bignum chunk, in bits */
|
|
|
|
|
|
|
|
for (; len > 0 && m < BN_BYTES * 8; len--, s += inc, m += 8) {
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
BN_ULONG byte_xored = *s ^ xor;
|
|
|
|
BN_ULONG byte = (byte_xored + carry) & 0xff;
|
2021-11-24 15:23:02 +08:00
|
|
|
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
carry = byte_xored > byte; /* Implicit 1 or 0 */
|
2021-11-24 15:23:02 +08:00
|
|
|
l |= (byte << m);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2021-11-24 15:23:02 +08:00
|
|
|
ret->d[i] = l;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* 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 22:04:09 +08:00
|
|
|
return ret;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2021-11-24 14:10:13 +08:00
|
|
|
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
|
|
|
|
{
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
return bin2bn(s, len, ret, BIG, UNSIGNED);
|
2021-11-24 14:10:13 +08:00
|
|
|
}
|
2019-09-06 05:18:36 +08:00
|
|
|
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
BIGNUM *BN_signed_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
|
|
|
|
{
|
|
|
|
return bin2bn(s, len, ret, BIG, SIGNED);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen,
|
|
|
|
endianess_t endianess, signedness_t signedness)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2021-11-24 14:16:09 +08:00
|
|
|
int inc;
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
int n, n8;
|
|
|
|
int xor = 0, carry = 0, ext = 0;
|
2018-08-15 21:46:35 +08:00
|
|
|
size_t i, lasti, j, atop, mask;
|
2015-01-22 11:40:55 +08:00
|
|
|
BN_ULONG l;
|
|
|
|
|
2018-08-15 21:46:35 +08:00
|
|
|
/*
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
* In case |a| is fixed-top, BN_num_bits can return bogus length,
|
2018-08-15 21:46:35 +08:00
|
|
|
* but it's assumed that fixed-top inputs ought to be "nominated"
|
|
|
|
* even for padded output, so it works out...
|
|
|
|
*/
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
n8 = BN_num_bits(a);
|
|
|
|
n = (n8 + 7) / 8; /* This is what BN_num_bytes() does */
|
|
|
|
|
|
|
|
/* Take note of the signedness of the bignum */
|
|
|
|
if (signedness == SIGNED) {
|
|
|
|
xor = a->neg ? 0xff : 0x00;
|
|
|
|
carry = a->neg;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if |n * 8 == n|, then the MSbit is set, otherwise unset.
|
|
|
|
* We must compensate with one extra byte if that doesn't
|
|
|
|
* correspond to the signedness of the bignum with regards
|
|
|
|
* to 2's complement.
|
|
|
|
*/
|
|
|
|
ext = (n * 8 == n8)
|
|
|
|
? !a->neg /* MSbit set on nonnegative bignum */
|
|
|
|
: a->neg; /* MSbit unset on negative bignum */
|
|
|
|
}
|
|
|
|
|
2018-08-15 21:46:35 +08:00
|
|
|
if (tolen == -1) {
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
tolen = n + ext;
|
|
|
|
} else if (tolen < n + ext) { /* uncommon/unlike case */
|
2018-08-15 21:46:35 +08:00
|
|
|
BIGNUM temp = *a;
|
2018-02-04 22:20:29 +08:00
|
|
|
|
2018-08-15 21:46:35 +08:00
|
|
|
bn_correct_top(&temp);
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
n8 = BN_num_bits(&temp);
|
|
|
|
n = (n8 + 7) / 8; /* This is what BN_num_bytes() does */
|
|
|
|
if (tolen < n + ext)
|
2018-08-15 21:46:35 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Swipe through whole available data and don't give away padded zero. */
|
|
|
|
atop = a->dmax * BN_BYTES;
|
|
|
|
if (atop == 0) {
|
2021-12-09 01:26:03 +08:00
|
|
|
if (tolen != 0)
|
|
|
|
memset(to, '\0', tolen);
|
2018-02-04 22:20:29 +08:00
|
|
|
return tolen;
|
2016-02-01 08:02:05 +08:00
|
|
|
}
|
2018-02-04 22:20:29 +08:00
|
|
|
|
2021-11-24 14:16:09 +08:00
|
|
|
/*
|
|
|
|
* The loop that does the work iterates from least significant
|
|
|
|
* to most significant BIGNUM limb, so we adapt parameters to
|
2022-02-04 00:51:26 +08:00
|
|
|
* transfer output bytes accordingly.
|
2021-11-24 14:16:09 +08:00
|
|
|
*/
|
2022-01-22 08:22:31 +08:00
|
|
|
if (endianess == LITTLE) {
|
2021-11-24 14:16:09 +08:00
|
|
|
inc = 1;
|
2022-01-22 08:22:31 +08:00
|
|
|
} else {
|
2021-11-24 14:16:09 +08:00
|
|
|
inc = -1;
|
|
|
|
to += tolen - 1; /* Move to the last byte, not beyond */
|
|
|
|
}
|
|
|
|
|
2018-08-15 21:46:35 +08:00
|
|
|
lasti = atop - 1;
|
|
|
|
atop = a->top * BN_BYTES;
|
2019-09-06 05:18:36 +08:00
|
|
|
for (i = 0, j = 0; j < (size_t)tolen; j++) {
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
unsigned char byte, byte_xored;
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
l = a->d[i / BN_BYTES];
|
2018-08-15 21:46:35 +08:00
|
|
|
mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1));
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
byte = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask);
|
|
|
|
byte_xored = byte ^ xor;
|
|
|
|
*to = (unsigned char)(byte_xored + carry);
|
|
|
|
carry = byte_xored > *to; /* Implicit 1 or 0 */
|
2021-11-24 14:16:09 +08:00
|
|
|
to += inc;
|
2018-08-15 21:46:35 +08:00
|
|
|
i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2018-02-04 22:20:29 +08:00
|
|
|
|
2016-02-01 08:02:05 +08:00
|
|
|
return tolen;
|
|
|
|
}
|
|
|
|
|
|
|
|
int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
|
|
|
|
{
|
|
|
|
if (tolen < 0)
|
|
|
|
return -1;
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
return bn2binpad(a, to, tolen, BIG, UNSIGNED);
|
|
|
|
}
|
|
|
|
|
|
|
|
int BN_signed_bn2bin(const BIGNUM *a, unsigned char *to, int tolen)
|
|
|
|
{
|
|
|
|
if (tolen < 0)
|
|
|
|
return -1;
|
|
|
|
return bn2binpad(a, to, tolen, BIG, SIGNED);
|
2016-02-01 08:02:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int BN_bn2bin(const BIGNUM *a, unsigned char *to)
|
|
|
|
{
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
return bn2binpad(a, to, -1, BIG, UNSIGNED);
|
2016-02-01 08:02:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret)
|
|
|
|
{
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
return bin2bn(s, len, ret, LITTLE, UNSIGNED);
|
|
|
|
}
|
|
|
|
|
|
|
|
BIGNUM *BN_signed_lebin2bn(const unsigned char *s, int len, BIGNUM *ret)
|
|
|
|
{
|
|
|
|
return bin2bn(s, len, ret, LITTLE, SIGNED);
|
2016-02-01 08:02:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen)
|
|
|
|
{
|
2019-09-06 05:18:36 +08:00
|
|
|
if (tolen < 0)
|
2016-02-01 08:02:05 +08:00
|
|
|
return -1;
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
return bn2binpad(a, to, tolen, LITTLE, UNSIGNED);
|
|
|
|
}
|
|
|
|
|
|
|
|
int BN_signed_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen)
|
|
|
|
{
|
|
|
|
if (tolen < 0)
|
|
|
|
return -1;
|
|
|
|
return bn2binpad(a, to, tolen, LITTLE, SIGNED);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2019-02-26 20:08:31 +08:00
|
|
|
BIGNUM *BN_native2bn(const unsigned char *s, int len, BIGNUM *ret)
|
|
|
|
{
|
2020-07-09 14:40:50 +08:00
|
|
|
DECLARE_IS_ENDIAN;
|
|
|
|
|
|
|
|
if (IS_LITTLE_ENDIAN)
|
|
|
|
return BN_lebin2bn(s, len, ret);
|
2019-02-26 20:08:31 +08:00
|
|
|
return BN_bin2bn(s, len, ret);
|
|
|
|
}
|
|
|
|
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
BIGNUM *BN_signed_native2bn(const unsigned char *s, int len, BIGNUM *ret)
|
|
|
|
{
|
|
|
|
DECLARE_IS_ENDIAN;
|
|
|
|
|
|
|
|
if (IS_LITTLE_ENDIAN)
|
|
|
|
return BN_signed_lebin2bn(s, len, ret);
|
|
|
|
return BN_signed_bin2bn(s, len, ret);
|
|
|
|
}
|
|
|
|
|
2019-02-26 20:08:31 +08:00
|
|
|
int BN_bn2nativepad(const BIGNUM *a, unsigned char *to, int tolen)
|
|
|
|
{
|
2020-07-09 14:40:50 +08:00
|
|
|
DECLARE_IS_ENDIAN;
|
|
|
|
|
|
|
|
if (IS_LITTLE_ENDIAN)
|
|
|
|
return BN_bn2lebinpad(a, to, tolen);
|
2019-02-26 20:08:31 +08:00
|
|
|
return BN_bn2binpad(a, to, tolen);
|
|
|
|
}
|
|
|
|
|
Add signed bn2bin and bin2bn functions
This adds the functions BN_signed_bin2bn(), BN_signed_bn2bin(),
BN_signed_lebin2bn(), BN_signed_bn2lebin(), BN_signed_native2bn(),
and BN_signed_bn2native(), all essentially doing the same job as
BN_bin2bn(), BN_bn2binpad(), BN_lebin2bn(), BN_bn2lebinpad(),
BN_native2bn(), and BN_bn2nativepad(), except that the 'signed'
ones operate on signed number bins in 2's complement form.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17139)
2021-11-26 00:55:41 +08:00
|
|
|
int BN_signed_bn2native(const BIGNUM *a, unsigned char *to, int tolen)
|
|
|
|
{
|
|
|
|
DECLARE_IS_ENDIAN;
|
|
|
|
|
|
|
|
if (IS_LITTLE_ENDIAN)
|
|
|
|
return BN_signed_bn2lebin(a, to, tolen);
|
|
|
|
return BN_signed_bn2bin(a, to, tolen);
|
|
|
|
}
|
|
|
|
|
1999-06-05 06:23:10 +08:00
|
|
|
int BN_ucmp(const BIGNUM *a, const BIGNUM *b)
|
2015-01-22 11:40:55 +08: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 22:04:09 +08:00
|
|
|
return i;
|
2015-01-22 11:40:55 +08: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 22:04:09 +08:00
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
1999-06-05 06:23:10 +08:00
|
|
|
int BN_cmp(const BIGNUM *a, const BIGNUM *b)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int gt, lt;
|
|
|
|
BN_ULONG t1, t2;
|
|
|
|
|
|
|
|
if ((a == NULL) || (b == NULL)) {
|
|
|
|
if (a != NULL)
|
2017-10-17 22:04:09 +08:00
|
|
|
return -1;
|
2015-01-22 11:40:55 +08:00
|
|
|
else if (b != NULL)
|
2017-10-09 19:05:58 +08:00
|
|
|
return 1;
|
2015-01-22 11:40:55 +08:00
|
|
|
else
|
2017-10-17 22:04:09 +08:00
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bn_check_top(a);
|
|
|
|
bn_check_top(b);
|
|
|
|
|
|
|
|
if (a->neg != b->neg) {
|
|
|
|
if (a->neg)
|
2017-10-17 22:04:09 +08:00
|
|
|
return -1;
|
2015-01-22 11:40:55 +08:00
|
|
|
else
|
2017-10-09 19:05:58 +08:00
|
|
|
return 1;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
if (a->neg == 0) {
|
|
|
|
gt = 1;
|
|
|
|
lt = -1;
|
|
|
|
} else {
|
|
|
|
gt = -1;
|
|
|
|
lt = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->top > b->top)
|
2017-10-17 22:04:09 +08:00
|
|
|
return gt;
|
2015-01-22 11:40:55 +08:00
|
|
|
if (a->top < b->top)
|
2017-10-17 22:04:09 +08:00
|
|
|
return lt;
|
2015-01-22 11:40:55 +08:00
|
|
|
for (i = a->top - 1; i >= 0; i--) {
|
|
|
|
t1 = a->d[i];
|
|
|
|
t2 = b->d[i];
|
|
|
|
if (t1 > t2)
|
2017-10-17 22:04:09 +08:00
|
|
|
return gt;
|
2015-01-22 11:40:55 +08:00
|
|
|
if (t1 < t2)
|
2017-10-17 22:04:09 +08:00
|
|
|
return lt;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2017-10-17 22:04:09 +08:00
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
int BN_set_bit(BIGNUM *a, int n)
|
2015-01-22 11:40:55 +08: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 22:04:09 +08:00
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
for (k = a->top; k < i + 1; k++)
|
|
|
|
a->d[k] = 0;
|
|
|
|
a->top = i + 1;
|
2018-07-06 21:02:29 +08:00
|
|
|
a->flags &= ~BN_FLG_FIXED_TOP;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
a->d[i] |= (((BN_ULONG)1) << j);
|
|
|
|
bn_check_top(a);
|
2017-10-09 19:05:58 +08:00
|
|
|
return 1;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
int BN_clear_bit(BIGNUM *a, int n)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int i, j;
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
bn_check_top(a);
|
|
|
|
if (n < 0)
|
|
|
|
return 0;
|
2003-11-15 16:37:50 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
i = n / BN_BITS2;
|
|
|
|
j = n % BN_BITS2;
|
|
|
|
if (a->top <= i)
|
2017-10-17 22:04:09 +08:00
|
|
|
return 0;
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
a->d[i] &= (~(((BN_ULONG)1) << j));
|
|
|
|
bn_correct_top(a);
|
2017-10-09 19:05:58 +08:00
|
|
|
return 1;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
1999-06-05 06:23:10 +08:00
|
|
|
int BN_is_bit_set(const BIGNUM *a, int n)
|
2015-01-22 11:40:55 +08: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 18:52:47 +08:00
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
int BN_mask_bits(BIGNUM *a, int n)
|
2015-01-22 11:40:55 +08: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 19:05:58 +08:00
|
|
|
return 1;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 19:00:56 +08:00
|
|
|
|
2005-04-23 04:02:44 +08:00
|
|
|
void BN_set_negative(BIGNUM *a, int b)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (b && !BN_is_zero(a))
|
|
|
|
a->neg = 1;
|
|
|
|
else
|
|
|
|
a->neg = 0;
|
|
|
|
}
|
2005-04-23 04:02:44 +08:00
|
|
|
|
2000-11-17 06:43:32 +08:00
|
|
|
int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
BN_ULONG aa, bb;
|
|
|
|
|
2019-02-25 19:28:32 +08:00
|
|
|
if (n == 0)
|
|
|
|
return 0;
|
|
|
|
|
2015-01-22 11:40:55 +08: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 22:04:09 +08:00
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Here follows a specialised variants of bn_cmp_words(). It has the
|
2016-03-14 19:39:32 +08:00
|
|
|
* capability of performing the operation on arrays of different sizes. The
|
2015-01-22 11:40:55 +08:00
|
|
|
* sizes of those arrays is expressed through cl, which is the common length
|
2016-03-14 19:39:32 +08:00
|
|
|
* ( basically, min(len(a),len(b)) ), and dl, which is the delta between the
|
2015-01-22 11:40:55 +08: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 21:47:54 +08:00
|
|
|
/*-
|
2015-01-22 11:40:55 +08:00
|
|
|
* Constant-time conditional swap of a and b.
|
2018-11-12 21:47:54 +08: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 22:16:19 +08:00
|
|
|
*/
|
|
|
|
void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
BN_ULONG t;
|
|
|
|
int i;
|
2014-03-12 22:16:19 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
bn_wcheck_size(a, nwords);
|
|
|
|
bn_wcheck_size(b, nwords);
|
2014-03-12 22:16:19 +08:00
|
|
|
|
2018-11-12 21:47:54 +08:00
|
|
|
condition = ((~condition & ((condition - 1))) >> (BN_BITS2 - 1)) - 1;
|
2014-03-12 22:16:19 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
t = (a->top ^ b->top) & condition;
|
|
|
|
a->top ^= t;
|
|
|
|
b->top ^= t;
|
2014-03-12 22:16:19 +08:00
|
|
|
|
2018-04-19 17:21:51 +08:00
|
|
|
t = (a->neg ^ b->neg) & condition;
|
|
|
|
a->neg ^= t;
|
|
|
|
b->neg ^= t;
|
|
|
|
|
2018-04-23 19:34:11 +08:00
|
|
|
/*-
|
2018-11-09 15:25:43 +08: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 17:21:51 +08:00
|
|
|
*/
|
2018-11-09 15:25:43 +08: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 17:21:51 +08:00
|
|
|
a->flags ^= t;
|
|
|
|
b->flags ^= t;
|
|
|
|
|
2018-11-12 21:47:54 +08: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 22:16:19 +08:00
|
|
|
}
|
2014-01-18 22:51:40 +08:00
|
|
|
|
2018-11-12 21:47:54 +08:00
|
|
|
#undef BN_CONSTTIME_SWAP_FLAGS
|
|
|
|
|
2014-01-18 22:51:40 +08:00
|
|
|
/* Bits of security, see SP800-57 */
|
|
|
|
|
|
|
|
int BN_security_bits(int L, int N)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int secbits, bits;
|
|
|
|
if (L >= 15360)
|
|
|
|
secbits = 256;
|
2017-10-18 17:23:33 +08:00
|
|
|
else if (L >= 7680)
|
2015-01-22 11:40:55 +08: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 18:06:20 +08:00
|
|
|
|
|
|
|
void BN_zero_ex(BIGNUM *a)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
a->neg = 0;
|
2018-07-06 21:02:29 +08:00
|
|
|
a->top = 0;
|
|
|
|
a->flags &= ~BN_FLG_FIXED_TOP;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
|
|
|
int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return ((a->top == 1) && (a->d[0] == w)) || ((w == 0) && (a->top == 0));
|
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
|
|
|
int BN_is_zero(const BIGNUM *a)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return a->top == 0;
|
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
|
|
|
int BN_is_one(const BIGNUM *a)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return BN_abs_is_word(a, 1) && !a->neg;
|
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
|
|
|
int BN_is_word(const BIGNUM *a, const BN_ULONG w)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return BN_abs_is_word(a, w) && (!w || !a->neg);
|
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
|
|
|
int BN_is_odd(const BIGNUM *a)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return (a->top > 0) && (a->d[0] & 1);
|
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
|
|
|
int BN_is_negative(const BIGNUM *a)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return (a->neg != 0);
|
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
2015-01-22 11:40:55 +08: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 18:06:20 +08:00
|
|
|
|
2015-11-24 19:09:00 +08:00
|
|
|
void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags)
|
2015-01-22 11:40:55 +08: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 19:09:00 +08:00
|
|
|
| BN_FLG_STATIC_DATA | flags);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
|
|
|
BN_GENCB *BN_GENCB_new(void)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
BN_GENCB *ret;
|
2014-11-24 18:06:20 +08:00
|
|
|
|
2022-09-29 19:57:34 +08:00
|
|
|
if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
|
2017-10-17 22:04:09 +08:00
|
|
|
return NULL;
|
2014-11-24 18:06:20 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
return ret;
|
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
|
|
|
void BN_GENCB_free(BN_GENCB *cb)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (cb == NULL)
|
|
|
|
return;
|
|
|
|
OPENSSL_free(cb);
|
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
|
|
|
void BN_set_flags(BIGNUM *b, int n)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
b->flags |= n;
|
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
|
|
|
int BN_get_flags(const BIGNUM *b, int n)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return b->flags & n;
|
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
|
|
|
/* Populate a BN_GENCB structure with an "old"-style callback */
|
2015-01-22 11:40:55 +08: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 18:06:20 +08:00
|
|
|
|
|
|
|
/* Populate a BN_GENCB structure with a "new"-style callback */
|
2015-01-22 11:40:55 +08: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 18:06:20 +08:00
|
|
|
|
|
|
|
void *BN_GENCB_get_arg(BN_GENCB *cb)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return cb->arg;
|
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
|
|
|
BIGNUM *bn_wexpand(BIGNUM *a, int words)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return (words <= a->dmax) ? a : bn_expand2(a, words);
|
|
|
|
}
|
2014-11-24 18:06:20 +08:00
|
|
|
|
|
|
|
void bn_correct_top(BIGNUM *a)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
BN_ULONG *ftl;
|
|
|
|
int tmp_top = a->top;
|
|
|
|
|
|
|
|
if (tmp_top > 0) {
|
2016-05-21 22:53:14 +08:00
|
|
|
for (ftl = &(a->d[tmp_top]); tmp_top > 0; tmp_top--) {
|
|
|
|
ftl--;
|
|
|
|
if (*ftl != 0)
|
2015-01-22 11:40:55 +08:00
|
|
|
break;
|
2016-05-21 22:53:14 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
a->top = tmp_top;
|
|
|
|
}
|
2016-09-06 06:08:43 +08:00
|
|
|
if (a->top == 0)
|
|
|
|
a->neg = 0;
|
2018-07-06 21:02:29 +08:00
|
|
|
a->flags &= ~BN_FLG_FIXED_TOP;
|
2015-01-22 11:40:55 +08:00
|
|
|
bn_pollute(a);
|
|
|
|
}
|