mirror of
https://github.com/openssl/openssl.git
synced 2026-01-14 21:20:29 +00:00
Compare commits
22 Commits
feature/os
...
feature/me
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d4f44f3e7 | ||
|
|
5844109177 | ||
|
|
8a17b8ee9e | ||
|
|
f174d994ef | ||
|
|
d65db7f0e1 | ||
|
|
ba4fce934a | ||
|
|
cb97cc61e0 | ||
|
|
8220d3664d | ||
|
|
cbb3db48ac | ||
|
|
f5877a9d04 | ||
|
|
ba4970afb5 | ||
|
|
52cd2a49c5 | ||
|
|
26d138af72 | ||
|
|
f247d36074 | ||
|
|
013e1174df | ||
|
|
0f22d74662 | ||
|
|
ba26e3f46b | ||
|
|
688e4f4a5f | ||
|
|
21d4585718 | ||
|
|
996d50da8f | ||
|
|
e7d5206e89 | ||
|
|
21722fe554 |
@@ -16,18 +16,6 @@ PointerAlignment: Right
|
||||
# of a comment block to protect comments as
|
||||
# per STYLE.md
|
||||
CommentPragmas: '(^ IWYU pragma:|^\*$|^-$)'
|
||||
# OpenSSL uses type names (usually typedefs) extensively. Tell clang-format about them.
|
||||
TypeNames:
|
||||
- "BIGNUM"
|
||||
- "BN_BLINDING"
|
||||
- "BN_CTX"
|
||||
- "BN_GENCB"
|
||||
- "BN_MONT_CTX"
|
||||
- "BN_RECP_CTX"
|
||||
- "BN_ULLONG"
|
||||
- "BN_ULONG"
|
||||
- "OSSL_FN_CTX"
|
||||
- "OSSL_FN_ULONG"
|
||||
# OpenSSL uses macros extensively. Tell clang-format about them.
|
||||
TypenameMacros: ['LHASH_OF', 'STACK_OF']
|
||||
StatementMacros:
|
||||
@@ -255,6 +243,7 @@ StatementMacros:
|
||||
- "ASN1_SEQUENCE_END_enc"
|
||||
- "ASN1_SEQUENCE_END_name"
|
||||
- "ASN1_SEQUENCE_END_ref"
|
||||
- "static_ASN1_SEQUENCE_END"
|
||||
# This isn't quite right, but it causes clang-format to do a slightly better
|
||||
# job formatting this macro.
|
||||
- "ASN1_EX_TEMPLATE_TYPE"
|
||||
|
||||
16
apps/cmp.c
16
apps/cmp.c
@@ -87,6 +87,7 @@ static char *opt_srvcert = NULL;
|
||||
static char *opt_expect_sender = NULL;
|
||||
static int opt_ignore_keyusage = 0;
|
||||
static int opt_unprotected_errors = 0;
|
||||
static int opt_ta_in_ip_extracerts = 0;
|
||||
static int opt_no_cache_extracerts = 0;
|
||||
static char *opt_srvcertout = NULL;
|
||||
static char *opt_extracertsout = NULL;
|
||||
@@ -281,6 +282,7 @@ typedef enum OPTION_choice {
|
||||
OPT_EXPECT_SENDER,
|
||||
OPT_IGNORE_KEYUSAGE,
|
||||
OPT_UNPROTECTED_ERRORS,
|
||||
OPT_TA_IN_IP_EXTRACERTS,
|
||||
OPT_NO_CACHE_EXTRACERTS,
|
||||
OPT_SRVCERTOUT,
|
||||
OPT_EXTRACERTSOUT,
|
||||
@@ -509,6 +511,12 @@ const OPTIONS cmp_options[] = {
|
||||
"certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf" },
|
||||
{ OPT_MORE_STR, 0, 0,
|
||||
"WARNING: This setting leads to behavior allowing violation of RFC 9810" },
|
||||
{ "ta_in_ip_extracerts", OPT_TA_IN_IP_EXTRACERTS, '-',
|
||||
"Permit using self-issued certificates from the extraCerts in an IP message" },
|
||||
{ OPT_MORE_STR, 0, 0,
|
||||
"as trust anchors under conditions defined by 3GPP TS 33.310" },
|
||||
{ OPT_MORE_STR, 0, 0,
|
||||
"WARNING: This setting leads to behavior allowing violation of RFC 9810" },
|
||||
{ "no_cache_extracerts", OPT_NO_CACHE_EXTRACERTS, '-',
|
||||
"Do not keep certificates received in the extraCerts CMP message field" },
|
||||
{ "srvcertout", OPT_SRVCERTOUT, 's',
|
||||
@@ -727,6 +735,7 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
|
||||
{ &opt_trusted }, { &opt_untrusted }, { &opt_srvcert },
|
||||
{ &opt_expect_sender },
|
||||
{ (char **)&opt_ignore_keyusage }, { (char **)&opt_unprotected_errors },
|
||||
{ (char **)&opt_ta_in_ip_extracerts },
|
||||
{ (char **)&opt_no_cache_extracerts },
|
||||
{ &opt_srvcertout }, { &opt_extracertsout }, { &opt_cacertsout },
|
||||
{ &opt_oldwithold }, { &opt_newwithnew }, { &opt_newwithold }, { &opt_oldwithnew },
|
||||
@@ -1391,6 +1400,10 @@ static int setup_verification_ctx(OSSL_CMP_CTX *ctx)
|
||||
|
||||
if (opt_unprotected_errors)
|
||||
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS, 1);
|
||||
if (opt_ta_in_ip_extracerts) {
|
||||
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR, 1);
|
||||
CMP_warn("permitting non-authenticated trust anchors in IP extracerts according to 3GPP TS 33.310");
|
||||
}
|
||||
|
||||
if (opt_out_trusted != NULL) { /* for use in OSSL_CMP_certConf_cb() */
|
||||
X509_VERIFY_PARAM *out_vpm = NULL;
|
||||
@@ -2963,6 +2976,9 @@ static int get_opts(int argc, char **argv)
|
||||
case OPT_UNPROTECTED_ERRORS:
|
||||
opt_unprotected_errors = 1;
|
||||
break;
|
||||
case OPT_TA_IN_IP_EXTRACERTS:
|
||||
opt_ta_in_ip_extracerts = 1;
|
||||
break;
|
||||
case OPT_NO_CACHE_EXTRACERTS:
|
||||
opt_no_cache_extracerts = 1;
|
||||
break;
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include "crypto/cryptlib.h"
|
||||
|
||||
#define COPY_SIZE(a, b) (sizeof(a) < sizeof(b) ? sizeof(a) : sizeof(b))
|
||||
|
||||
@@ -56,6 +56,31 @@ static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
memcpy(pval, &it->size, COPY_SIZE(*pval, it->size));
|
||||
}
|
||||
|
||||
/*
|
||||
* Originally BN_num_bits_word was called to perform this operation, but
|
||||
* trouble is that there is no guarantee that sizeof(long) equals to
|
||||
* sizeof(BN_ULONG). BN_ULONG is a configurable type that can be as wide
|
||||
* as long, but also double or half...
|
||||
*/
|
||||
static int num_bits_ulong(unsigned long value)
|
||||
{
|
||||
size_t i;
|
||||
unsigned long ret = 0;
|
||||
|
||||
/*
|
||||
* It is argued that *on average* constant counter loop performs
|
||||
* not worse [if not better] than one with conditional break or
|
||||
* mask-n-table-lookup-style, because of branch misprediction
|
||||
* penalties.
|
||||
*/
|
||||
for (i = 0; i < sizeof(value) * 8; i++) {
|
||||
ret += (value != 0);
|
||||
value >>= 1;
|
||||
}
|
||||
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
static int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
@@ -78,7 +103,7 @@ static int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
sign = 0;
|
||||
utmp = ltmp;
|
||||
}
|
||||
clen = (int)ossl_num_bits(utmp);
|
||||
clen = num_bits_ulong(utmp);
|
||||
/* If MSB of leading octet set we need to pad */
|
||||
if (!(clen & 0x7))
|
||||
pad = 1;
|
||||
|
||||
@@ -64,7 +64,12 @@
|
||||
#undef NO_RECVMSG
|
||||
#define NO_RECVMSG
|
||||
#endif
|
||||
#if (defined(__ANDROID_API__) && __ANDROID_API__ < 21) || defined(_AIX)
|
||||
#if (defined(__ANDROID_API__) && __ANDROID_API__ < 21)
|
||||
#undef NO_RECVMMSG
|
||||
#define NO_RECVMMSG
|
||||
#endif
|
||||
#if defined(_AIX) && !defined(_AIX72)
|
||||
/* AIX >= 7.2 provides sendmmsg() and recvmmsg(). */
|
||||
#undef NO_RECVMMSG
|
||||
#define NO_RECVMMSG
|
||||
#endif
|
||||
@@ -130,7 +135,14 @@
|
||||
BIO_MAX(BIO_CMSG_ALLOC_LEN_1, \
|
||||
BIO_MAX(BIO_CMSG_ALLOC_LEN_2, BIO_CMSG_ALLOC_LEN_3))
|
||||
#endif
|
||||
#if (defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)) && defined(IPV6_RECVPKTINFO)
|
||||
/*
|
||||
* Although AIX defines IP_RECVDSTADDR and IPV6_RECVPKTINFO, the
|
||||
* implementation requires IP_PKTINFO to be available for AF_INET.
|
||||
* For AF_INET6 there seem to be limitations how local addresses
|
||||
* are handled on AIX. So, disable the support for now.
|
||||
*/
|
||||
#if (defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)) && defined(IPV6_RECVPKTINFO) \
|
||||
&& !defined(_AIX)
|
||||
#define SUPPORT_LOCAL_ADDR
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -261,7 +261,7 @@ BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
#else
|
||||
/* Simics 1.4<7 has buggy sbbq:-( */
|
||||
#define BN_MASK2 0xffffffffffffffffL
|
||||
BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n)
|
||||
BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
|
||||
{
|
||||
BN_ULONG t1, t2;
|
||||
int c = 0;
|
||||
@@ -408,7 +408,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n)
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) \
|
||||
mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
|
||||
void bn_mul_comba8(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b)
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
|
||||
{
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
@@ -511,7 +511,7 @@ void bn_mul_comba8(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b)
|
||||
r[15] = c1;
|
||||
}
|
||||
|
||||
void bn_mul_comba4(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b)
|
||||
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
|
||||
{
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
|
||||
@@ -10,21 +10,6 @@
|
||||
#include "internal/cryptlib.h"
|
||||
#include "bn_local.h"
|
||||
|
||||
static size_t calculate_max_limbs(const BIGNUM *a, const BIGNUM *b)
|
||||
{
|
||||
OSSL_FN *af = a->data;
|
||||
OSSL_FN *bf = b->data;
|
||||
|
||||
return (af->dsize > bf->dsize) ? af->dsize : bf->dsize;
|
||||
}
|
||||
|
||||
static bool is_highest_bit_set(const BIGNUM *a)
|
||||
{
|
||||
OSSL_FN *af = a->data;
|
||||
|
||||
return (af->d[af->dsize - 1] & OSSL_FN_HIGH_BIT_MASK) != 0;
|
||||
}
|
||||
|
||||
/* signed add of b to a. */
|
||||
int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
{
|
||||
@@ -87,9 +72,8 @@ int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO(FIXNUM): TO BE REMOVED */
|
||||
/* pure BIGNUM unsigned add of b to a, r can be equal to a or b. */
|
||||
static int bn_uadd_legacy(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
/* unsigned add of b to a, r can be equal to a or b. */
|
||||
int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
{
|
||||
int max, min, dif;
|
||||
const BN_ULONG *ap, *bp;
|
||||
@@ -112,7 +96,7 @@ static int bn_uadd_legacy(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
if (bn_wexpand(r, max + 1) == NULL)
|
||||
return 0;
|
||||
|
||||
bn_set_top(r, max);
|
||||
r->top = max;
|
||||
|
||||
ap = a->d;
|
||||
bp = b->d;
|
||||
@@ -130,42 +114,15 @@ static int bn_uadd_legacy(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
carry &= (t2 == 0);
|
||||
}
|
||||
*rp = carry;
|
||||
bn_set_top(r, r->top + (int)carry);
|
||||
r->top += (int)carry;
|
||||
|
||||
r->neg = 0;
|
||||
bn_check_top(r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* unsigned add of b to a, r can be equal to a or b. */
|
||||
int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
{
|
||||
/* TODO(FIXNUM): TO BE REMOVED */
|
||||
if (r->data == NULL || a->data == NULL || b->data == NULL)
|
||||
return bn_uadd_legacy(r, a, b);
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
|
||||
size_t max = calculate_max_limbs(a, b);
|
||||
|
||||
/*
|
||||
* If either operands have the highest bit set the result may become
|
||||
* one limb larger.
|
||||
*/
|
||||
if (is_highest_bit_set(a) || is_highest_bit_set(b))
|
||||
max++;
|
||||
|
||||
OSSL_FN *rf = bn_acquire_ossl_fn(r, (int)max);
|
||||
int ret = OSSL_FN_add(rf, a->data, b->data);
|
||||
bn_release(r, (int)max);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO(FIXNUM): TO BE REMOVED */
|
||||
/* pure BIGNUM unsigned subtraction of b from a, a must be larger than b. */
|
||||
static int bn_usub_legacy(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
/* unsigned subtraction of b from a, a must be larger than b. */
|
||||
int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
{
|
||||
int max, min, dif;
|
||||
BN_ULONG t1, t2, borrow, *rp;
|
||||
@@ -205,32 +162,9 @@ static int bn_usub_legacy(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
while (max && *--rp == 0)
|
||||
max--;
|
||||
|
||||
bn_set_top(r, max);
|
||||
r->top = max;
|
||||
r->neg = 0;
|
||||
bn_pollute(r);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* unsigned subtraction of b from a, a must be larger than b. */
|
||||
int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
{
|
||||
/* TODO(FIXNUM): TO BE REMOVED */
|
||||
if (r->data == NULL || a->data == NULL || b->data == NULL)
|
||||
return bn_usub_legacy(r, a, b);
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
|
||||
if (a->top < b->top) { /* hmm... should not be happening */
|
||||
ERR_raise(ERR_LIB_BN, BN_R_ARG2_LT_ARG3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t max = calculate_max_limbs(a, b);
|
||||
|
||||
OSSL_FN *rf = bn_acquire_ossl_fn(r, (int)max);
|
||||
int ret = OSSL_FN_sub(rf, a->data, b->data);
|
||||
bn_release(r, (int)max);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -622,7 +622,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
#endif /* !BN_LLONG */
|
||||
|
||||
void bn_mul_comba8(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b)
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
|
||||
{
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
@@ -725,7 +725,7 @@ void bn_mul_comba8(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b)
|
||||
r[15] = c1;
|
||||
}
|
||||
|
||||
void bn_mul_comba4(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b)
|
||||
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
|
||||
{
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
@@ -1006,7 +1006,7 @@ void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
|
||||
bn_sqr_normal(r, a, 8, t);
|
||||
}
|
||||
|
||||
void bn_mul_comba4(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b)
|
||||
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
|
||||
{
|
||||
r[4] = bn_mul_words(&(r[0]), a, 4, b[0]);
|
||||
r[5] = bn_mul_add_words(&(r[1]), a, 4, b[1]);
|
||||
@@ -1014,7 +1014,7 @@ void bn_mul_comba4(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b)
|
||||
r[7] = bn_mul_add_words(&(r[3]), a, 4, b[3]);
|
||||
}
|
||||
|
||||
void bn_mul_comba8(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b)
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
|
||||
{
|
||||
r[8] = bn_mul_words(&(r[0]), a, 8, b[0]);
|
||||
r[9] = bn_mul_add_words(&(r[1]), a, 8, b[1]);
|
||||
|
||||
@@ -185,7 +185,7 @@ int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
|
||||
}
|
||||
mask = (BN_ULONG)0 - ((rtop - ntop) >> (8 * sizeof(ntop) - 1));
|
||||
/* always true, if (rtop >= ntop) n->top = r->top; */
|
||||
bn_set_top(n, (int)((rtop & ~mask) | (ntop & mask)));
|
||||
n->top = (int)((rtop & ~mask) | (ntop & mask));
|
||||
n->flags |= (BN_FLG_FIXED_TOP & ~mask);
|
||||
}
|
||||
ret = bn_mul_mont_fixed_top(n, n, r, b->m_ctx, ctx);
|
||||
|
||||
@@ -178,7 +178,7 @@ int BN_hex2bn(BIGNUM **bn, const char *a)
|
||||
}
|
||||
j -= BN_BYTES * 2;
|
||||
}
|
||||
bn_set_top(ret, h);
|
||||
ret->top = h;
|
||||
bn_correct_top(ret);
|
||||
|
||||
*bn = ret;
|
||||
|
||||
@@ -1374,53 +1374,50 @@ static const BN_ULONG ffdhe8192_q[] = {
|
||||
#define make_dh_bn(x) \
|
||||
extern const BIGNUM ossl_bignum_##x; \
|
||||
const BIGNUM ossl_bignum_##x = { \
|
||||
.d = (BN_ULONG *)x, \
|
||||
.top = OSSL_NELEM(x), \
|
||||
.dmax = OSSL_NELEM(x), \
|
||||
.flags = BN_FLG_STATIC_DATA, \
|
||||
}
|
||||
(BN_ULONG *)x, \
|
||||
OSSL_NELEM(x), \
|
||||
OSSL_NELEM(x), \
|
||||
0, BN_FLG_STATIC_DATA \
|
||||
};
|
||||
|
||||
static const BN_ULONG value_2 = 2;
|
||||
|
||||
const BIGNUM ossl_bignum_const_2 = {
|
||||
.d = (BN_ULONG *)&value_2,
|
||||
.top = 1,
|
||||
.dmax = 1,
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)&value_2, 1, 1, 0, BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
make_dh_bn(dh1024_160_p);
|
||||
make_dh_bn(dh1024_160_q);
|
||||
make_dh_bn(dh1024_160_g);
|
||||
make_dh_bn(dh2048_224_p);
|
||||
make_dh_bn(dh2048_224_q);
|
||||
make_dh_bn(dh2048_224_g);
|
||||
make_dh_bn(dh2048_256_p);
|
||||
make_dh_bn(dh2048_256_q);
|
||||
make_dh_bn(dh2048_256_g);
|
||||
make_dh_bn(dh1024_160_p)
|
||||
make_dh_bn(dh1024_160_q)
|
||||
make_dh_bn(dh1024_160_g)
|
||||
make_dh_bn(dh2048_224_p)
|
||||
make_dh_bn(dh2048_224_q)
|
||||
make_dh_bn(dh2048_224_g)
|
||||
make_dh_bn(dh2048_256_p)
|
||||
make_dh_bn(dh2048_256_q)
|
||||
make_dh_bn(dh2048_256_g)
|
||||
|
||||
make_dh_bn(ffdhe2048_p);
|
||||
make_dh_bn(ffdhe2048_q);
|
||||
make_dh_bn(ffdhe3072_p);
|
||||
make_dh_bn(ffdhe3072_q);
|
||||
make_dh_bn(ffdhe4096_p);
|
||||
make_dh_bn(ffdhe4096_q);
|
||||
make_dh_bn(ffdhe6144_p);
|
||||
make_dh_bn(ffdhe6144_q);
|
||||
make_dh_bn(ffdhe8192_p);
|
||||
make_dh_bn(ffdhe8192_q);
|
||||
make_dh_bn(ffdhe2048_p)
|
||||
make_dh_bn(ffdhe2048_q)
|
||||
make_dh_bn(ffdhe3072_p)
|
||||
make_dh_bn(ffdhe3072_q)
|
||||
make_dh_bn(ffdhe4096_p)
|
||||
make_dh_bn(ffdhe4096_q)
|
||||
make_dh_bn(ffdhe6144_p)
|
||||
make_dh_bn(ffdhe6144_q)
|
||||
make_dh_bn(ffdhe8192_p)
|
||||
make_dh_bn(ffdhe8192_q)
|
||||
|
||||
#ifndef FIPS_MODULE
|
||||
make_dh_bn(modp_1536_p);
|
||||
make_dh_bn(modp_1536_q);
|
||||
make_dh_bn(modp_1536_p)
|
||||
make_dh_bn(modp_1536_q)
|
||||
#endif
|
||||
make_dh_bn(modp_2048_p);
|
||||
make_dh_bn(modp_2048_q);
|
||||
make_dh_bn(modp_3072_p);
|
||||
make_dh_bn(modp_3072_q);
|
||||
make_dh_bn(modp_4096_p);
|
||||
make_dh_bn(modp_4096_q);
|
||||
make_dh_bn(modp_6144_p);
|
||||
make_dh_bn(modp_6144_q);
|
||||
make_dh_bn(modp_8192_p);
|
||||
make_dh_bn(modp_8192_q);
|
||||
make_dh_bn(modp_2048_p)
|
||||
make_dh_bn(modp_2048_q)
|
||||
make_dh_bn(modp_3072_p)
|
||||
make_dh_bn(modp_3072_q)
|
||||
make_dh_bn(modp_4096_p)
|
||||
make_dh_bn(modp_4096_q)
|
||||
make_dh_bn(modp_6144_p)
|
||||
make_dh_bn(modp_6144_q)
|
||||
make_dh_bn(modp_8192_p)
|
||||
make_dh_bn(modp_8192_q)
|
||||
|
||||
@@ -61,7 +61,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
|
||||
BN_zero(dv);
|
||||
if (bn_wexpand(dv, 1) == NULL)
|
||||
goto end;
|
||||
bn_set_top(dv, 1);
|
||||
dv->top = 1;
|
||||
|
||||
if (!BN_lshift(D, D, nm - nd))
|
||||
goto end;
|
||||
@@ -310,9 +310,7 @@ int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num,
|
||||
if (bn_wexpand(snum, div_n + 1) == NULL)
|
||||
goto err;
|
||||
memset(&(snum->d[num_n]), 0, (div_n - num_n + 1) * sizeof(BN_ULONG));
|
||||
num_n = div_n + 1;
|
||||
bn_set_top(snum, num_n);
|
||||
snum->flags |= BN_FLG_FIXED_TOP;
|
||||
snum->top = num_n = div_n + 1;
|
||||
}
|
||||
|
||||
loop = num_n - div_n;
|
||||
@@ -332,15 +330,13 @@ int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num,
|
||||
goto err;
|
||||
num_neg = num->neg;
|
||||
res->neg = (num_neg ^ divisor->neg);
|
||||
bn_set_top(res, loop);
|
||||
res->top = loop;
|
||||
res->flags |= BN_FLG_FIXED_TOP;
|
||||
resp = &(res->d[loop]);
|
||||
|
||||
/* space for temp */
|
||||
if (!bn_wexpand(tmp, (div_n + 1)))
|
||||
goto err;
|
||||
tmp->top = div_n + 1;
|
||||
tmp->flags |= BN_FLG_FIXED_TOP;
|
||||
|
||||
for (i = 0; i < loop; i++, wnumtop--) {
|
||||
BN_ULONG q, l0;
|
||||
@@ -450,7 +446,7 @@ int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num,
|
||||
}
|
||||
/* snum holds remainder, it's as wide as divisor */
|
||||
snum->neg = num_neg;
|
||||
bn_set_top(snum, div_n);
|
||||
snum->top = div_n;
|
||||
snum->flags |= BN_FLG_FIXED_TOP;
|
||||
|
||||
if (rm != NULL && bn_rshift_fixed_top(rm, snum, norm_shift) == 0)
|
||||
|
||||
@@ -402,7 +402,7 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
r->d[0] = (0 - m->d[0]) & BN_MASK2;
|
||||
for (i = 1; i < j; i++)
|
||||
r->d[i] = (~m->d[i]) & BN_MASK2;
|
||||
bn_set_top(r, j);
|
||||
r->top = j;
|
||||
r->flags |= BN_FLG_FIXED_TOP;
|
||||
} else
|
||||
#endif
|
||||
@@ -468,8 +468,7 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
val[0]->d[0] = 1; /* borrow val[0] */
|
||||
for (i = 1; i < j; i++)
|
||||
val[0]->d[i] = 0;
|
||||
bn_set_top(val[0], j);
|
||||
val[0]->flags |= BN_FLG_FIXED_TOP;
|
||||
val[0]->top = j;
|
||||
if (!BN_mod_mul_montgomery(rr, r, val[0], mont, ctx))
|
||||
goto err;
|
||||
} else
|
||||
@@ -582,7 +581,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top,
|
||||
}
|
||||
}
|
||||
|
||||
bn_set_top(b, top);
|
||||
b->top = top;
|
||||
b->flags |= BN_FLG_FIXED_TOP;
|
||||
return 1;
|
||||
}
|
||||
@@ -613,7 +612,7 @@ int bn_mod_exp_mont_fixed_top(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
unsigned char *powerbufFree = NULL;
|
||||
int powerbufLen = 0;
|
||||
unsigned char *powerbuf = NULL;
|
||||
BIGNUM tmp = { .data = NULL }, am = { .data = NULL };
|
||||
BIGNUM tmp, am;
|
||||
#if defined(SPARC_T4_MONT)
|
||||
unsigned int t4 = 0;
|
||||
#endif
|
||||
@@ -682,7 +681,7 @@ int bn_mod_exp_mont_fixed_top(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
goto err;
|
||||
RSAZ_1024_mod_exp_avx2(rr->d, a->d, p->d, m->d, mont->RR.d,
|
||||
mont->n0[0]);
|
||||
bn_set_top(rr, 16);
|
||||
rr->top = 16;
|
||||
rr->neg = 0;
|
||||
bn_correct_top(rr);
|
||||
ret = 1;
|
||||
@@ -691,7 +690,7 @@ int bn_mod_exp_mont_fixed_top(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
if (NULL == bn_wexpand(rr, 8))
|
||||
goto err;
|
||||
RSAZ_512_mod_exp(rr->d, a->d, p->d, m->d, mont->n0[0], mont->RR.d);
|
||||
bn_set_top(rr, 8);
|
||||
rr->top = 8;
|
||||
rr->neg = 0;
|
||||
bn_correct_top(rr);
|
||||
ret = 1;
|
||||
@@ -1489,12 +1488,12 @@ int BN_mod_exp_mont_consttime_x2(BIGNUM *rr1, const BIGNUM *a1, const BIGNUM *p1
|
||||
mont2->RR.d, mont2->n0[0],
|
||||
mod_bits);
|
||||
|
||||
bn_set_top(rr1, topn);
|
||||
rr1->top = topn;
|
||||
rr1->neg = 0;
|
||||
bn_correct_top(rr1);
|
||||
bn_check_top(rr1);
|
||||
|
||||
bn_set_top(rr2, topn);
|
||||
rr2->top = topn;
|
||||
rr2->neg = 0;
|
||||
bn_correct_top(rr2);
|
||||
bn_check_top(rr2);
|
||||
|
||||
@@ -267,7 +267,7 @@ int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
r->d[i] = at->d[i];
|
||||
}
|
||||
|
||||
bn_set_top(r, at->top);
|
||||
r->top = at->top;
|
||||
bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
@@ -305,7 +305,7 @@ int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[])
|
||||
for (j = 0; j < a->top; j++) {
|
||||
r->d[j] = a->d[j];
|
||||
}
|
||||
bn_set_top(r, a->top);
|
||||
r->top = a->top;
|
||||
}
|
||||
z = r->d;
|
||||
|
||||
@@ -419,7 +419,7 @@ int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
zlen = a->top + b->top + 4;
|
||||
if (!bn_wexpand(s, zlen))
|
||||
goto err;
|
||||
bn_set_top(s, zlen);
|
||||
s->top = zlen;
|
||||
|
||||
for (i = 0; i < zlen; i++)
|
||||
s->d[i] = 0;
|
||||
@@ -498,7 +498,7 @@ int BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[],
|
||||
s->d[2 * i] = SQR0(a->d[i]);
|
||||
}
|
||||
|
||||
bn_set_top(s, 2 * a->top);
|
||||
s->top = 2 * a->top;
|
||||
bn_correct_top(s);
|
||||
if (!BN_GF2m_mod_arr(r, s, p))
|
||||
goto err;
|
||||
@@ -618,20 +618,20 @@ static int BN_GF2m_mod_inv_vartime(BIGNUM *r, const BIGNUM *a,
|
||||
udp = u->d;
|
||||
for (i = u->top; i < top; i++)
|
||||
udp[i] = 0;
|
||||
bn_set_top(u, top);
|
||||
u->top = top;
|
||||
if (!bn_wexpand(b, top))
|
||||
goto err;
|
||||
bdp = b->d;
|
||||
bdp[0] = 1;
|
||||
for (i = 1; i < top; i++)
|
||||
bdp[i] = 0;
|
||||
bn_set_top(b, top);
|
||||
b->top = top;
|
||||
if (!bn_wexpand(c, top))
|
||||
goto err;
|
||||
cdp = c->d;
|
||||
for (i = 0; i < top; i++)
|
||||
cdp[i] = 0;
|
||||
bn_set_top(c, top);
|
||||
c->top = top;
|
||||
vdp = v->d; /* It pays off to "cache" *->d pointers,
|
||||
* because it allows optimizer to be more
|
||||
* aggressive. But we don't have to "cache"
|
||||
|
||||
@@ -174,9 +174,7 @@ void bn_set_static_words(BIGNUM *a, const BN_ULONG *words, int size)
|
||||
* |const| qualifier omission is compensated by BN_FLG_STATIC_DATA
|
||||
* flag, which effectively means "read-only data".
|
||||
*/
|
||||
a->data = NULL;
|
||||
a->d = (BN_ULONG *)words;
|
||||
/* No need to call bn_set_top() in this case */
|
||||
a->dmax = a->top = size;
|
||||
a->neg = 0;
|
||||
a->flags |= BN_FLG_STATIC_DATA;
|
||||
@@ -190,11 +188,8 @@ int bn_set_words(BIGNUM *a, const BN_ULONG *words, int num_words)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO(FIXNUM): In the future, we'll use an OSSL_FN function on a->data */
|
||||
memcpy(a->d, words, sizeof(BN_ULONG) * num_words);
|
||||
|
||||
/* TODO(FIXNUM): The following two lines are TO BE REMOVED */
|
||||
bn_set_top(a, num_words);
|
||||
a->top = num_words;
|
||||
bn_correct_top(a);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -9,14 +9,11 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/opensslconf.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/endian.h"
|
||||
#include "internal/constant_time.h"
|
||||
#include "crypto/fn.h"
|
||||
#include "bn_local.h"
|
||||
#include <openssl/opensslconf.h>
|
||||
#include "internal/constant_time.h"
|
||||
|
||||
/* This stuff appears to be completely unused, so is deprecated */
|
||||
#ifndef OPENSSL_NO_DEPRECATED_0_9_8
|
||||
@@ -86,10 +83,7 @@ const BIGNUM *BN_value_one(void)
|
||||
{
|
||||
static const BN_ULONG data_one = 1L;
|
||||
static const BIGNUM const_one = {
|
||||
.d = (BN_ULONG *)&data_one,
|
||||
.top = 1,
|
||||
.dmax = 1,
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)&data_one, 1, 1, 0, BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
return &const_one;
|
||||
@@ -205,7 +199,7 @@ int BN_num_bits(const BIGNUM *a)
|
||||
return ((i * BN_BITS2) + BN_num_bits_word(a->d[i]));
|
||||
}
|
||||
|
||||
static void bn_free_d(BIGNUM *a, bool clear)
|
||||
static void bn_free_d(BIGNUM *a, int clear)
|
||||
{
|
||||
if (BN_get_flags(a, BN_FLG_SECURE))
|
||||
OPENSSL_secure_clear_free(a->d, a->dmax * sizeof(a->d[0]));
|
||||
@@ -219,12 +213,8 @@ void BN_clear_free(BIGNUM *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
if (!BN_get_flags(a, BN_FLG_STATIC_DATA)) {
|
||||
if (a->data != NULL)
|
||||
OSSL_FN_clear_free(a->data);
|
||||
else
|
||||
bn_free_d(a, true);
|
||||
}
|
||||
if (a->d != NULL && !BN_get_flags(a, BN_FLG_STATIC_DATA))
|
||||
bn_free_d(a, 1);
|
||||
if (BN_get_flags(a, BN_FLG_MALLOCED)) {
|
||||
OPENSSL_cleanse(a, sizeof(*a));
|
||||
OPENSSL_free(a);
|
||||
@@ -235,12 +225,8 @@ void BN_free(BIGNUM *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
if (!BN_get_flags(a, BN_FLG_STATIC_DATA)) {
|
||||
if (a->data != NULL)
|
||||
OSSL_FN_free(a->data);
|
||||
else
|
||||
bn_free_d(a, false);
|
||||
}
|
||||
if (!BN_get_flags(a, BN_FLG_STATIC_DATA))
|
||||
bn_free_d(a, 0);
|
||||
if (a->flags & BN_FLG_MALLOCED)
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
@@ -275,11 +261,11 @@ BIGNUM *BN_secure_new(void)
|
||||
|
||||
/* This is used by bn_expand2() */
|
||||
/* The caller MUST check that words > b->dmax before calling this */
|
||||
static OSSL_FN *bn_expand_internal(const BIGNUM *b, int words)
|
||||
static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
|
||||
{
|
||||
OSSL_FN *a = NULL;
|
||||
BN_ULONG *a = NULL;
|
||||
|
||||
if (ossl_unlikely(words > BN_MAX_WORDS)) {
|
||||
if (ossl_unlikely(words > (INT_MAX / (4 * BN_BITS2)))) {
|
||||
ERR_raise(ERR_LIB_BN, BN_R_BIGNUM_TOO_LONG);
|
||||
return NULL;
|
||||
}
|
||||
@@ -288,19 +274,15 @@ static OSSL_FN *bn_expand_internal(const BIGNUM *b, int words)
|
||||
return NULL;
|
||||
}
|
||||
if (BN_get_flags(b, BN_FLG_SECURE))
|
||||
a = OSSL_FN_secure_new_limbs(words);
|
||||
a = OPENSSL_secure_calloc(words, sizeof(*a));
|
||||
else
|
||||
a = OSSL_FN_new_limbs(words);
|
||||
a = OPENSSL_calloc(words, sizeof(*a));
|
||||
if (ossl_unlikely(a == NULL))
|
||||
return NULL;
|
||||
|
||||
assert(b->top <= words);
|
||||
if (b->top > 0) {
|
||||
if (b->data != NULL)
|
||||
ossl_fn_copy_internal(a, b->data, -1);
|
||||
else if (b->d != NULL)
|
||||
ossl_fn_copy_internal_limbs(a, b->d, b->top);
|
||||
}
|
||||
if (b->top > 0)
|
||||
memcpy(a, b->d, sizeof(*a) * b->top);
|
||||
|
||||
return a;
|
||||
}
|
||||
@@ -316,18 +298,14 @@ static OSSL_FN *bn_expand_internal(const BIGNUM *b, int words)
|
||||
BIGNUM *bn_expand2(BIGNUM *b, int words)
|
||||
{
|
||||
if (ossl_likely(words > b->dmax)) {
|
||||
OSSL_FN *a = bn_expand_internal(b, words);
|
||||
BN_ULONG *a = bn_expand_internal(b, words);
|
||||
|
||||
if (ossl_unlikely(!a))
|
||||
return NULL;
|
||||
if (b->data != NULL)
|
||||
OSSL_FN_clear_free(b->data);
|
||||
else if (b->d != NULL)
|
||||
bn_free_d(b, true);
|
||||
b->data = a;
|
||||
/* TODO(FIXNUM) The following is TO BE REMOVED */
|
||||
b->d = b->data->d;
|
||||
b->dmax = b->data->dsize;
|
||||
if (b->d != NULL)
|
||||
bn_free_d(b, 1);
|
||||
b->d = a;
|
||||
b->dmax = words;
|
||||
}
|
||||
|
||||
return b;
|
||||
@@ -365,14 +343,11 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
|
||||
if (ossl_unlikely(bn_wexpand(a, bn_words) == NULL))
|
||||
return NULL;
|
||||
|
||||
if (ossl_likely(bn_words > 0)) {
|
||||
if (b->data != NULL)
|
||||
ossl_fn_copy_internal(a->data, b->data, bn_words);
|
||||
else if (b->d != NULL)
|
||||
ossl_fn_copy_internal_limbs(a->data, b->d, bn_words);
|
||||
}
|
||||
if (ossl_likely(b->top > 0))
|
||||
memcpy(a->d, b->d, sizeof(b->d[0]) * bn_words);
|
||||
|
||||
a->neg = b->neg;
|
||||
bn_set_top(a, b->top);
|
||||
a->top = b->top;
|
||||
a->flags |= b->flags & BN_FLG_FIXED_TOP;
|
||||
bn_check_top(a);
|
||||
return a;
|
||||
@@ -384,7 +359,6 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
|
||||
void BN_swap(BIGNUM *a, BIGNUM *b)
|
||||
{
|
||||
int flags_old_a, flags_old_b;
|
||||
OSSL_FN *tmp_data;
|
||||
BN_ULONG *tmp_d;
|
||||
int tmp_top, tmp_dmax, tmp_neg;
|
||||
|
||||
@@ -394,19 +368,16 @@ void BN_swap(BIGNUM *a, BIGNUM *b)
|
||||
flags_old_a = a->flags;
|
||||
flags_old_b = b->flags;
|
||||
|
||||
tmp_data = a->data;
|
||||
tmp_d = a->d;
|
||||
tmp_top = a->top;
|
||||
tmp_dmax = a->dmax;
|
||||
tmp_neg = a->neg;
|
||||
|
||||
a->data = b->data;
|
||||
a->d = b->d;
|
||||
a->top = b->top;
|
||||
a->dmax = b->dmax;
|
||||
a->neg = b->neg;
|
||||
|
||||
b->data = tmp_data;
|
||||
b->d = tmp_d;
|
||||
b->top = tmp_top;
|
||||
b->dmax = tmp_dmax;
|
||||
@@ -423,12 +394,10 @@ void BN_clear(BIGNUM *a)
|
||||
if (a == NULL)
|
||||
return;
|
||||
bn_check_top(a);
|
||||
if (a->data != NULL)
|
||||
OSSL_FN_clear(a->data);
|
||||
else if (a->d != NULL)
|
||||
if (a->d != NULL)
|
||||
OPENSSL_cleanse(a->d, sizeof(*a->d) * a->dmax);
|
||||
a->neg = 0;
|
||||
bn_set_top(a, 0);
|
||||
a->top = 0;
|
||||
a->flags &= ~BN_FLG_FIXED_TOP;
|
||||
}
|
||||
|
||||
@@ -445,11 +414,11 @@ BN_ULONG BN_get_word(const BIGNUM *a)
|
||||
int BN_set_word(BIGNUM *a, BN_ULONG w)
|
||||
{
|
||||
bn_check_top(a);
|
||||
if (bn_wexpand(a, 1) == NULL)
|
||||
if (bn_expand(a, (int)sizeof(BN_ULONG) * 8) == NULL)
|
||||
return 0;
|
||||
a->neg = 0;
|
||||
a->d[0] = w;
|
||||
bn_set_top(a, (w ? 1 : 0));
|
||||
a->top = (w ? 1 : 0);
|
||||
a->flags &= ~BN_FLG_FIXED_TOP;
|
||||
bn_check_top(a);
|
||||
return 1;
|
||||
@@ -531,7 +500,7 @@ static BIGNUM *bin2bn(const unsigned char *s, int len, BIGNUM *ret,
|
||||
}
|
||||
/* If it was all zeros, we're done */
|
||||
if (len == 0) {
|
||||
bn_set_top(ret, 0);
|
||||
ret->top = 0;
|
||||
return ret;
|
||||
}
|
||||
n = ((len - 1) / BN_BYTES) + 1; /* Number of resulting bignum chunks */
|
||||
@@ -539,7 +508,7 @@ static BIGNUM *bin2bn(const unsigned char *s, int len, BIGNUM *ret,
|
||||
BN_free(bn);
|
||||
return NULL;
|
||||
}
|
||||
bn_set_top(ret, n);
|
||||
ret->top = n;
|
||||
ret->neg = neg;
|
||||
for (i = 0; n-- > 0; i++) {
|
||||
BN_ULONG l = 0; /* Accumulator */
|
||||
@@ -820,7 +789,7 @@ int BN_cmp(const BIGNUM *a, const BIGNUM *b)
|
||||
|
||||
int BN_set_bit(BIGNUM *a, int n)
|
||||
{
|
||||
int i, j;
|
||||
int i, j, k;
|
||||
|
||||
if (n < 0)
|
||||
return 0;
|
||||
@@ -830,12 +799,9 @@ int BN_set_bit(BIGNUM *a, int n)
|
||||
if (a->top <= i) {
|
||||
if (bn_wexpand(a, i + 1) == NULL)
|
||||
return 0;
|
||||
/*
|
||||
* If 'a' is actually expanded, we know that the expanded
|
||||
* part of the 'd' array is zeroed during allocation, so
|
||||
* no need to zero it again here.
|
||||
*/
|
||||
bn_set_top(a, i + 1);
|
||||
for (k = a->top; k < i + 1; k++)
|
||||
a->d[k] = 0;
|
||||
a->top = i + 1;
|
||||
a->flags &= ~BN_FLG_FIXED_TOP;
|
||||
}
|
||||
|
||||
@@ -888,9 +854,9 @@ int ossl_bn_mask_bits_fixed_top(BIGNUM *a, int n)
|
||||
if (w >= a->top)
|
||||
return 0;
|
||||
if (b == 0)
|
||||
bn_set_top(a, w);
|
||||
a->top = w;
|
||||
else {
|
||||
bn_set_top(a, w + 1);
|
||||
a->top = w + 1;
|
||||
a->d[w] &= ~(BN_MASK2 << b);
|
||||
}
|
||||
a->flags |= BN_FLG_FIXED_TOP;
|
||||
@@ -1057,7 +1023,7 @@ int BN_security_bits(int L, int N)
|
||||
void BN_zero_ex(BIGNUM *a)
|
||||
{
|
||||
a->neg = 0;
|
||||
bn_set_top(a, 0);
|
||||
a->top = 0;
|
||||
a->flags &= ~BN_FLG_FIXED_TOP;
|
||||
}
|
||||
|
||||
@@ -1068,12 +1034,7 @@ int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w)
|
||||
|
||||
int BN_is_zero(const BIGNUM *a)
|
||||
{
|
||||
if ((a->flags & BN_FLG_FIXED_TOP) == 0)
|
||||
return a->top == 0;
|
||||
for (size_t i = a->top; i-- > 0;)
|
||||
if (a->d[i] != (BN_ULONG)0)
|
||||
return 0;
|
||||
return 1;
|
||||
return a->top == 0;
|
||||
}
|
||||
|
||||
int BN_is_one(const BIGNUM *a)
|
||||
@@ -1120,7 +1081,6 @@ int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
|
||||
|
||||
void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags)
|
||||
{
|
||||
dest->data = b->data;
|
||||
dest->d = b->d;
|
||||
dest->top = b->top;
|
||||
dest->dmax = b->dmax;
|
||||
@@ -1204,11 +1164,6 @@ void bn_correct_top_consttime(BIGNUM *a)
|
||||
}
|
||||
|
||||
mask = constant_time_eq_int(atop, 0);
|
||||
/*
|
||||
* We just went through the whole 'd' array to identify where
|
||||
* any leading set of zeros are located, so there's no need to
|
||||
* call bn_set_top() here.
|
||||
*/
|
||||
a->top = atop;
|
||||
a->neg = constant_time_select_int(mask, 0, a->neg);
|
||||
a->flags &= ~BN_FLG_FIXED_TOP;
|
||||
@@ -1225,14 +1180,10 @@ void bn_correct_top(BIGNUM *a)
|
||||
if (*ftl != 0)
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* We just verified that the BN_ULONGs between a->top and
|
||||
* tmp_top are all zero, so there's no need to call
|
||||
* bn_set_top() here.
|
||||
*/
|
||||
a->top = tmp_top;
|
||||
}
|
||||
if (a->top == 0)
|
||||
a->neg = 0;
|
||||
a->flags &= ~BN_FLG_FIXED_TOP;
|
||||
bn_pollute(a);
|
||||
}
|
||||
|
||||
@@ -10,24 +10,27 @@
|
||||
#ifndef OSSL_CRYPTO_BN_LOCAL_H
|
||||
#define OSSL_CRYPTO_BN_LOCAL_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/numbers.h"
|
||||
#include "crypto/bn.h"
|
||||
|
||||
#include "../fn/fn_local.h"
|
||||
|
||||
/*
|
||||
* BN_RAND_DEBUG was historically used to poison unused words in bignum data,
|
||||
* for integrity debugging purposes. This isn't done any more, but enabling
|
||||
* BN_RAND_DEBUG also defined BN_DEBUG, which we preserve for the moment.
|
||||
* These preprocessor symbols control various aspects of the bignum headers
|
||||
* and library code. They're not defined by any "normal" configuration, as
|
||||
* they are intended for development and testing purposes. NB: defining
|
||||
* them can be useful for debugging application code as well as openssl
|
||||
* itself. BN_DEBUG - turn on various debugging alterations to the bignum
|
||||
* code BN_RAND_DEBUG - uses random poisoning of unused words to trip up
|
||||
* mismanagement of bignum internals. Enable BN_RAND_DEBUG is known to
|
||||
* break some of the OpenSSL tests.
|
||||
*/
|
||||
#if defined(BN_RAND_DEBUG) && !defined(BN_DEBUG)
|
||||
#define BN_DEBUG
|
||||
#endif
|
||||
#if defined(BN_RAND_DEBUG)
|
||||
#include <openssl/rand.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This should limit the stack usage due to alloca to about 4K.
|
||||
@@ -123,72 +126,32 @@
|
||||
#define BN_DEC_FMT2 "%09u"
|
||||
#endif
|
||||
|
||||
#define BN_MAX_WORDS (INT_MAX / (4 * BN_BITS2))
|
||||
|
||||
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
|
||||
BN_ULONG w);
|
||||
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
|
||||
void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
|
||||
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
|
||||
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
int num);
|
||||
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
int num);
|
||||
|
||||
struct bignum_st {
|
||||
/* The number itself is a FIXNUM */
|
||||
OSSL_FN *data;
|
||||
|
||||
/* Some of these flags are replicated in OSSL_FN, some are not */
|
||||
int flags;
|
||||
|
||||
/*
|
||||
* TODO(FIXNUM) The fields that follow ARE TO BE REMOVED when all relevant
|
||||
* BN_ functions have transitioned to be wrappers around OSSL_FN_ functions.
|
||||
* All of this is maintained by bn_expand and BIGNUM allocators and
|
||||
* deallocators.
|
||||
*/
|
||||
|
||||
BN_ULONG *d; /* Pointer to |data->d| */
|
||||
int top; /* Index of last used d +1. */
|
||||
/* The next are internal book keeping for bn_expand. */
|
||||
int dmax; /* Copy of |data->dsize| */
|
||||
int neg; /* One if the number is negative */
|
||||
};
|
||||
|
||||
/*-
|
||||
* Bignum consistency macros
|
||||
*
|
||||
* There is one "API" macro, bn_fix_top(), for stripping leading zeroes from
|
||||
* bignum data after direct manipulations on the data. There is also an
|
||||
* "internal" macro, bn_check_top(), for verifying that there are no leading
|
||||
* zeroes, and in case the BIGNUM has an integrated OSSL_FN, check the
|
||||
* consistency of the integration, including that the unused part of the
|
||||
* data is all zeros.
|
||||
*
|
||||
* Unfortunately, some auditing is required due to the fact that bn_fix_top()
|
||||
* has become an overabused duck-tape because bignum data is occasionally
|
||||
* passed around in an inconsistent state. So the following changes have been
|
||||
* made to sort this out;
|
||||
*
|
||||
* zeroes. Unfortunately, some auditing is required due to the fact that
|
||||
* bn_fix_top() has become an overabused duct-tape because bignum data is
|
||||
* occasionally passed around in an inconsistent state. So the following
|
||||
* changes have been made to sort this out;
|
||||
* - bn_fix_top()s implementation has been moved to bn_correct_top()
|
||||
* - if BN_DEBUG isn't defined:
|
||||
* - bn_check_top() does nothing.
|
||||
* - bn_fix_top() maps to bn_correct_top()
|
||||
* - if BN_DEBUG is defined:
|
||||
* - bn_check_top() performs its consistency checks
|
||||
* - if BN_DEBUG isn't defined, bn_fix_top() maps to bn_correct_top(), and
|
||||
* bn_check_top() is as before.
|
||||
* - if BN_DEBUG *is* defined;
|
||||
* - bn_check_top() tries to pollute unused words even if the bignum 'top' is
|
||||
* consistent. (ed: only if BN_RAND_DEBUG is defined)
|
||||
* - bn_fix_top() maps to bn_check_top() rather than "fixing" anything.
|
||||
*
|
||||
* The idea is to have debug builds flag up inconsistent bignums when they
|
||||
* occur. If that occurs in a bn_fix_top(), we examine the code in question;
|
||||
* if the use of bn_fix_top() was appropriate (ie. it follows directly after
|
||||
* code that manipulates the bignum) it is converted to bn_correct_top(),
|
||||
* and if it was not appropriate, we convert it permanently to bn_check_top()
|
||||
* and track down the cause of the bug. Eventually, no internal code should be
|
||||
* using the bn_fix_top() macro. External applications and libraries should try
|
||||
* this with their own code too, both in terms of building against the openssl
|
||||
* headers with BN_DEBUG defined *and* linking with a version of OpenSSL built
|
||||
* with it defined. This not only improves external code, it provides more test
|
||||
* occur. If that occurs in a bn_fix_top(), we examine the code in question; if
|
||||
* the use of bn_fix_top() was appropriate (ie. it follows directly after code
|
||||
* that manipulates the bignum) it is converted to bn_correct_top(), and if it
|
||||
* was not appropriate, we convert it permanently to bn_check_top() and track
|
||||
* down the cause of the bug. Eventually, no internal code should be using the
|
||||
* bn_fix_top() macro. External applications and libraries should try this with
|
||||
* their own code too, both in terms of building against the openssl headers
|
||||
* with BN_DEBUG defined *and* linking with a version of OpenSSL built with it
|
||||
* defined. This not only improves external code, it provides more test
|
||||
* coverage for openssl's own code.
|
||||
*/
|
||||
|
||||
@@ -207,49 +170,54 @@ struct bignum_st {
|
||||
* all operations manipulating the bit in question in non-BN_DEBUG build.
|
||||
*/
|
||||
#define BN_FLG_FIXED_TOP 0x10000
|
||||
|
||||
static ossl_inline bool bn_check_zero(BN_ULONG *words, int num_words)
|
||||
{
|
||||
for (int i = 0; i < num_words; i++)
|
||||
if (words[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static ossl_inline void bn_check_top(const BIGNUM *bn)
|
||||
{
|
||||
if (bn != NULL) {
|
||||
/* BIGNUM <-> OSSL_FN compat checks */
|
||||
if (bn->data != NULL) {
|
||||
/* TODO(FIXNUM): Assertion for the future */
|
||||
/* assert(_bnum2->d == NULL); */
|
||||
assert(bn->d == bn->data->d);
|
||||
assert(bn->dmax == bn->data->dsize);
|
||||
assert(bn_check_zero(&bn->d[bn->top], bn->dmax - bn->top));
|
||||
}
|
||||
/* BIGNUM specific checks */
|
||||
if (bn->top == 0) {
|
||||
assert(!bn->neg);
|
||||
} else if ((bn->flags & BN_FLG_FIXED_TOP) == 0) {
|
||||
assert(bn->d[bn->top - 1] != 0);
|
||||
}
|
||||
assert(bn->dmax >= 0 && bn->dmax <= BN_MAX_WORDS);
|
||||
}
|
||||
}
|
||||
#ifdef BN_RAND_DEBUG
|
||||
#define bn_pollute(a) \
|
||||
do { \
|
||||
const BIGNUM *_bnum1 = (a); \
|
||||
if (_bnum1->top < _bnum1->dmax) { \
|
||||
unsigned char _tmp_char; \
|
||||
/* We cast away const without the compiler knowing, any \
|
||||
* *genuinely* constant variables that aren't mutable \
|
||||
* wouldn't be constructed with top!=dmax. */ \
|
||||
BN_ULONG *_not_const; \
|
||||
memcpy(&_not_const, &_bnum1->d, sizeof(_not_const)); \
|
||||
(void)RAND_bytes(&_tmp_char, 1); /* Debug only - safe to ignore error return */ \
|
||||
memset(_not_const + _bnum1->top, _tmp_char, \
|
||||
sizeof(*_not_const) * (_bnum1->dmax - _bnum1->top)); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define bn_pollute(a)
|
||||
#endif
|
||||
#define bn_check_top(a) \
|
||||
do { \
|
||||
const BIGNUM *_bnum2 = (a); \
|
||||
if (_bnum2 != NULL) { \
|
||||
int _top = _bnum2->top; \
|
||||
if (_top == 0) { \
|
||||
assert(!_bnum2->neg); \
|
||||
} else if ((_bnum2->flags & BN_FLG_FIXED_TOP) == 0) { \
|
||||
assert(_bnum2->d[_top - 1] != 0); \
|
||||
} \
|
||||
bn_pollute(_bnum2); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define bn_fix_top(a) bn_check_top(a)
|
||||
|
||||
static ossl_inline void bn_wcheck_size(const BIGNUM *bn, int words)
|
||||
{
|
||||
assert(words <= bn->dmax);
|
||||
assert(words >= bn->top);
|
||||
}
|
||||
|
||||
#define bn_check_size(bn, bits) bn_wcheck_size(bn, ((bits + BN_BITS2 - 1)) / BN_BITS2)
|
||||
#define bn_wcheck_size(bn, words) \
|
||||
do { \
|
||||
const BIGNUM *_bnum2 = (bn); \
|
||||
assert((words) <= (_bnum2)->dmax && (words) >= (_bnum2)->top); \
|
||||
/* avoid unused variable warning with NDEBUG */ \
|
||||
(void)(_bnum2); \
|
||||
} while (0)
|
||||
|
||||
#else /* !BN_DEBUG */
|
||||
|
||||
#define BN_FLG_FIXED_TOP 0
|
||||
#define bn_pollute(a)
|
||||
#define bn_check_top(a)
|
||||
#define bn_fix_top(a) bn_correct_top(a)
|
||||
#define bn_check_size(bn, bits)
|
||||
@@ -257,6 +225,29 @@ static ossl_inline void bn_wcheck_size(const BIGNUM *bn, int words)
|
||||
|
||||
#endif
|
||||
|
||||
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
|
||||
BN_ULONG w);
|
||||
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
|
||||
void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
|
||||
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
|
||||
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
int num);
|
||||
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
int num);
|
||||
|
||||
struct bignum_st {
|
||||
BN_ULONG *d; /*
|
||||
* Pointer to an array of 'BN_BITS2' bit
|
||||
* chunks. These chunks are organised in
|
||||
* a least significant chunk first order.
|
||||
*/
|
||||
int top; /* Index of last used d +1. */
|
||||
/* The next are internal book keeping for bn_expand. */
|
||||
int dmax; /* Size of the d array. */
|
||||
int neg; /* one if the number is negative */
|
||||
int flags;
|
||||
};
|
||||
|
||||
/* Used for montgomery multiplication */
|
||||
struct bn_mont_ctx_st {
|
||||
BIGNUM RR; /* used to convert to montgomery form,
|
||||
@@ -658,21 +649,21 @@ void BN_RECP_CTX_init(BN_RECP_CTX *recp);
|
||||
void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
|
||||
|
||||
void bn_init(BIGNUM *a);
|
||||
void bn_mul_normal(BN_ULONG *r, const BN_ULONG *a, int na, const BN_ULONG *b, int nb);
|
||||
void bn_mul_comba8(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b);
|
||||
void bn_mul_comba4(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b);
|
||||
void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb);
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
|
||||
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
|
||||
void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp);
|
||||
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a);
|
||||
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a);
|
||||
int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n);
|
||||
int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl);
|
||||
void bn_mul_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n2,
|
||||
void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
|
||||
int dna, int dnb, BN_ULONG *t);
|
||||
void bn_mul_part_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b,
|
||||
int n, int tna, int tnb, BN_ULONG *t);
|
||||
void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t);
|
||||
void bn_mul_low_normal(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n);
|
||||
void bn_mul_low_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n2,
|
||||
void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n);
|
||||
void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
|
||||
BN_ULONG *t);
|
||||
BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
int cl, int dl);
|
||||
@@ -682,7 +673,6 @@ void bn_correct_top_consttime(BIGNUM *a);
|
||||
BIGNUM *int_bn_mod_inverse(BIGNUM *in,
|
||||
const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx,
|
||||
int *noinv);
|
||||
void bn_mul_truncated(BN_ULONG *r, int nr, const BN_ULONG *a, int na, const BN_ULONG *b, int nb);
|
||||
|
||||
static ossl_inline BIGNUM *bn_expand(BIGNUM *a, int bits)
|
||||
{
|
||||
@@ -698,83 +688,4 @@ static ossl_inline BIGNUM *bn_expand(BIGNUM *a, int bits)
|
||||
int ossl_bn_check_prime(const BIGNUM *w, int checks, BN_CTX *ctx,
|
||||
int do_trial_division, BN_GENCB *cb);
|
||||
|
||||
/**
|
||||
* Set top on a given BIGNUM. If it has an associated OSSL_FN (the 'data'
|
||||
* field is non-NULL), and the new 'top' is less than the existing 'top',
|
||||
* zeroise the space between them.
|
||||
*
|
||||
* @param[in] b The BIGNUM instance to zeroise
|
||||
* @param[in] newtop The new 'top'
|
||||
* @returns the new 'top'
|
||||
* @pre b must not be NULL and newtop must be zero or positive
|
||||
*/
|
||||
static ossl_inline int bn_set_top(BIGNUM *b, int newtop)
|
||||
{
|
||||
assert(b != NULL && newtop >= 0);
|
||||
|
||||
if (b->data != NULL && newtop < b->top) {
|
||||
BN_ULONG *start = &(b->d[newtop]);
|
||||
size_t bytes = sizeof(BN_ULONG) * (b->top - newtop);
|
||||
|
||||
memset(start, 0, bytes);
|
||||
}
|
||||
|
||||
b->top = newtop;
|
||||
return b->top;
|
||||
}
|
||||
|
||||
/*
|
||||
* bn_acquire_ossl_fn() and bn_release() work in tandem, and are
|
||||
* most useful in OSSL_FN_ wrapper functions, specifically with the
|
||||
* BIGNUM in which an operation result is written.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Acquire the OSSL_FN from a BIGNUM. The BIGNUM should no longer be
|
||||
* used until bn_release() is called.
|
||||
*
|
||||
* @param[in] b The BIGNUM instance to get an OSSL_FN from
|
||||
* @param[in] limbs The minimum number of limbs 'b' should be expanded to.
|
||||
* Note that this doesn't set 'top', that's done by
|
||||
* bn_release().
|
||||
* @returns the OSSL_FN instance of the BIGNUM, if there is one
|
||||
* @pre b and b->data must not be NULL
|
||||
*/
|
||||
static ossl_inline OSSL_FN *bn_acquire_ossl_fn(BIGNUM *b, int limbs)
|
||||
{
|
||||
if (ossl_unlikely(b == NULL || b->data == NULL))
|
||||
return NULL;
|
||||
|
||||
if (bn_wexpand(b, limbs) == NULL)
|
||||
return NULL;
|
||||
/* TODO(FIXNUM): should we add a flag bit for this in b->flags ? */
|
||||
return b->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the BIGNUM from which the OSSL_FN was acquired. This will
|
||||
* adjust the BIGNUM to what was done with its OSSL_FN, and the BIGNUM
|
||||
* can again be used with BN_ functions.
|
||||
*
|
||||
* @param[in] b The BIGNUM instance to release
|
||||
* @param[in] limbs The maximum number of significant limbs. This sets
|
||||
* 'top'.
|
||||
* @pre b and b->data must not be NULL
|
||||
*/
|
||||
static ossl_inline void bn_release(BIGNUM *b, int limbs)
|
||||
{
|
||||
if (ossl_unlikely(b == NULL || b->data == NULL))
|
||||
return;
|
||||
|
||||
int fixed_top = (b->flags & BN_FLG_FIXED_TOP) != 0;
|
||||
|
||||
bn_set_top(b, limbs);
|
||||
|
||||
/* Don't correct top if BN_FLG_FIXED_TOP was set */
|
||||
if (fixed_top)
|
||||
return;
|
||||
|
||||
bn_correct_top(b);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -90,7 +90,7 @@ int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
rp[i] = (carry & tp[i]) | (~carry & rp[i]);
|
||||
((volatile BN_ULONG *)tp)[i] = 0;
|
||||
}
|
||||
bn_set_top(r, (int)mtop);
|
||||
r->top = (int)mtop;
|
||||
r->flags |= BN_FLG_FIXED_TOP;
|
||||
r->neg = 0;
|
||||
|
||||
@@ -176,7 +176,7 @@ int bn_mod_sub_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
carry += (rp[i] < ta);
|
||||
}
|
||||
|
||||
bn_set_top(r, (int)mtop);
|
||||
r->top = (int)mtop;
|
||||
r->flags |= BN_FLG_FIXED_TOP;
|
||||
r->neg = 0;
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
return 0;
|
||||
if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
|
||||
r->neg = a->neg ^ b->neg;
|
||||
bn_set_top(r, num);
|
||||
r->top = num;
|
||||
r->flags |= BN_FLG_FIXED_TOP;
|
||||
return 1;
|
||||
}
|
||||
@@ -95,7 +95,7 @@ static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
|
||||
n = &(mont->N);
|
||||
nl = n->top;
|
||||
if (nl == 0) {
|
||||
bn_set_top(ret, 0);
|
||||
ret->top = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
|
||||
rp[i] &= v;
|
||||
}
|
||||
|
||||
bn_set_top(r, max);
|
||||
r->top = max;
|
||||
r->flags |= BN_FLG_FIXED_TOP;
|
||||
n0 = mont->n0[0];
|
||||
|
||||
@@ -132,7 +132,7 @@ static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
|
||||
|
||||
if (bn_wexpand(ret, nl) == NULL)
|
||||
return 0;
|
||||
bn_set_top(ret, nl);
|
||||
ret->top = nl;
|
||||
ret->flags |= BN_FLG_FIXED_TOP;
|
||||
ret->neg = r->neg;
|
||||
|
||||
@@ -326,7 +326,7 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
|
||||
Ri->neg = 0;
|
||||
Ri->d[0] = BN_MASK2;
|
||||
Ri->d[1] = BN_MASK2;
|
||||
bn_set_top(Ri, 2);
|
||||
Ri->top = 2;
|
||||
}
|
||||
if (!BN_div(Ri, NULL, Ri, &tmod, ctx))
|
||||
goto err;
|
||||
|
||||
@@ -65,7 +65,7 @@ BIGNUM *BN_mpi2bn(const unsigned char *d, int n, BIGNUM *ain)
|
||||
|
||||
if (len == 0) {
|
||||
a->neg = 0;
|
||||
bn_set_top(a, 0);
|
||||
a->top = 0;
|
||||
return a;
|
||||
}
|
||||
d += 4;
|
||||
|
||||
@@ -11,39 +11,496 @@
|
||||
#include "internal/cryptlib.h"
|
||||
#include "bn_local.h"
|
||||
|
||||
int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
||||
#if defined(OPENSSL_NO_ASM) || !defined(OPENSSL_BN_ASM_PART_WORDS)
|
||||
/*
|
||||
* Here follows specialised variants of bn_add_words() and bn_sub_words().
|
||||
* They have the property performing operations on arrays of different sizes.
|
||||
* The sizes of those arrays is expressed through cl, which is the common
|
||||
* length ( basically, min(len(a),len(b)) ), and dl, which is the delta
|
||||
* between the two lengths, calculated as len(a)-len(b). All lengths are the
|
||||
* number of BN_ULONGs... For the operations that require a result array as
|
||||
* parameter, it must have the length cl+abs(dl). These functions should
|
||||
* probably end up in bn_asm.c as soon as there are assembler counterparts
|
||||
* for the systems that use assembler files.
|
||||
*/
|
||||
|
||||
BN_ULONG bn_sub_part_words(BN_ULONG *r,
|
||||
const BN_ULONG *a, const BN_ULONG *b,
|
||||
int cl, int dl)
|
||||
{
|
||||
/* TODO(FIXNUM): TO BE REMOVED */
|
||||
if (r->data == NULL || a->data == NULL || b->data == NULL) {
|
||||
int ret = bn_mul_fixed_top(r, a, b, ctx);
|
||||
BN_ULONG c, t;
|
||||
|
||||
bn_correct_top(r);
|
||||
bn_check_top(r);
|
||||
assert(cl >= 0);
|
||||
c = bn_sub_words(r, a, b, cl);
|
||||
|
||||
return ret;
|
||||
if (dl == 0)
|
||||
return c;
|
||||
|
||||
r += cl;
|
||||
a += cl;
|
||||
b += cl;
|
||||
|
||||
if (dl < 0) {
|
||||
for (;;) {
|
||||
t = b[0];
|
||||
r[0] = (0 - t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 1;
|
||||
if (++dl >= 0)
|
||||
break;
|
||||
|
||||
t = b[1];
|
||||
r[1] = (0 - t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 1;
|
||||
if (++dl >= 0)
|
||||
break;
|
||||
|
||||
t = b[2];
|
||||
r[2] = (0 - t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 1;
|
||||
if (++dl >= 0)
|
||||
break;
|
||||
|
||||
t = b[3];
|
||||
r[3] = (0 - t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 1;
|
||||
if (++dl >= 0)
|
||||
break;
|
||||
|
||||
b += 4;
|
||||
r += 4;
|
||||
}
|
||||
} else {
|
||||
int save_dl = dl;
|
||||
while (c) {
|
||||
t = a[0];
|
||||
r[0] = (t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 0;
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
|
||||
t = a[1];
|
||||
r[1] = (t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 0;
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
|
||||
t = a[2];
|
||||
r[2] = (t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 0;
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
|
||||
t = a[3];
|
||||
r[3] = (t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 0;
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
|
||||
save_dl = dl;
|
||||
a += 4;
|
||||
r += 4;
|
||||
}
|
||||
if (dl > 0) {
|
||||
if (save_dl > dl) {
|
||||
switch (save_dl - dl) {
|
||||
case 1:
|
||||
r[1] = a[1];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
/* fall through */
|
||||
case 2:
|
||||
r[2] = a[2];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
/* fall through */
|
||||
case 3:
|
||||
r[3] = a[3];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
}
|
||||
a += 4;
|
||||
r += 4;
|
||||
}
|
||||
}
|
||||
if (dl > 0) {
|
||||
for (;;) {
|
||||
r[0] = a[0];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
r[1] = a[1];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
r[2] = a[2];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
r[3] = a[3];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
|
||||
a += 4;
|
||||
r += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BN_RECURSION
|
||||
/*
|
||||
* Karatsuba recursive multiplication algorithm (cf. Knuth, The Art of
|
||||
* Computer Programming, Vol. 2)
|
||||
*/
|
||||
|
||||
/*-
|
||||
* r is 2*n2 words in size,
|
||||
* a and b are both n2 words in size.
|
||||
* n2 must be a power of 2.
|
||||
* We multiply and return the result.
|
||||
* t must be 2*n2 words in size
|
||||
* We calculate
|
||||
* a[0]*b[0]
|
||||
* a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
|
||||
* a[1]*b[1]
|
||||
*/
|
||||
/* dnX may not be positive, but n2/2+dnX has to be */
|
||||
void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
|
||||
int dna, int dnb, BN_ULONG *t)
|
||||
{
|
||||
int n = n2 / 2, c1, c2;
|
||||
int tna = n + dna, tnb = n + dnb;
|
||||
unsigned int neg, zero;
|
||||
BN_ULONG ln, lo, *p;
|
||||
|
||||
#ifdef BN_MUL_COMBA
|
||||
#if 0
|
||||
if (n2 == 4) {
|
||||
bn_mul_comba4(r, a, b);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Only call bn_mul_comba 8 if n2 == 8 and the two arrays are complete
|
||||
* [steve]
|
||||
*/
|
||||
if (n2 == 8 && dna == 0 && dnb == 0) {
|
||||
bn_mul_comba8(r, a, b);
|
||||
return;
|
||||
}
|
||||
#endif /* BN_MUL_COMBA */
|
||||
/* Else do normal multiply */
|
||||
if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) {
|
||||
bn_mul_normal(r, a, n2 + dna, b, n2 + dnb);
|
||||
if ((dna + dnb) < 0)
|
||||
memset(&r[2 * n2 + dna + dnb], 0,
|
||||
sizeof(BN_ULONG) * -(dna + dnb));
|
||||
return;
|
||||
}
|
||||
/* r=(a[0]-a[1])*(b[1]-b[0]) */
|
||||
c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);
|
||||
c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n);
|
||||
zero = neg = 0;
|
||||
switch (c1 * 3 + c2) {
|
||||
case -4:
|
||||
bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
|
||||
bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
|
||||
break;
|
||||
case -3:
|
||||
zero = 1;
|
||||
break;
|
||||
case -2:
|
||||
bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
|
||||
bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */
|
||||
neg = 1;
|
||||
break;
|
||||
case -1:
|
||||
case 0:
|
||||
case 1:
|
||||
zero = 1;
|
||||
break;
|
||||
case 2:
|
||||
bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */
|
||||
bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
|
||||
neg = 1;
|
||||
break;
|
||||
case 3:
|
||||
zero = 1;
|
||||
break;
|
||||
case 4:
|
||||
bn_sub_part_words(t, a, &(a[n]), tna, n - tna);
|
||||
bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n);
|
||||
break;
|
||||
}
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
#ifdef BN_MUL_COMBA
|
||||
if (n == 4 && dna == 0 && dnb == 0) { /* XXX: bn_mul_comba4 could take
|
||||
* extra args to do this well */
|
||||
if (!zero)
|
||||
bn_mul_comba4(&(t[n2]), t, &(t[n]));
|
||||
else
|
||||
memset(&t[n2], 0, sizeof(*t) * 8);
|
||||
|
||||
bn_mul_comba4(r, a, b);
|
||||
bn_mul_comba4(&(r[n2]), &(a[n]), &(b[n]));
|
||||
} else if (n == 8 && dna == 0 && dnb == 0) { /* XXX: bn_mul_comba8 could
|
||||
* take extra args to do
|
||||
* this well */
|
||||
if (!zero)
|
||||
bn_mul_comba8(&(t[n2]), t, &(t[n]));
|
||||
else
|
||||
memset(&t[n2], 0, sizeof(*t) * 16);
|
||||
|
||||
bn_mul_comba8(r, a, b);
|
||||
bn_mul_comba8(&(r[n2]), &(a[n]), &(b[n]));
|
||||
} else
|
||||
#endif /* BN_MUL_COMBA */
|
||||
{
|
||||
p = &(t[n2 * 2]);
|
||||
if (!zero)
|
||||
bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
|
||||
else
|
||||
memset(&t[n2], 0, sizeof(*t) * n2);
|
||||
bn_mul_recursive(r, a, b, n, 0, 0, p);
|
||||
bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p);
|
||||
}
|
||||
|
||||
/*-
|
||||
* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
|
||||
* r[10] holds (a[0]*b[0])
|
||||
* r[32] holds (b[1]*b[1])
|
||||
*/
|
||||
|
||||
c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));
|
||||
|
||||
if (neg) { /* if t[32] is negative */
|
||||
c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));
|
||||
} else {
|
||||
/* Might have a carry */
|
||||
c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2));
|
||||
}
|
||||
|
||||
/*-
|
||||
* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
|
||||
* r[10] holds (a[0]*b[0])
|
||||
* r[32] holds (b[1]*b[1])
|
||||
* c1 holds the carry bits
|
||||
*/
|
||||
c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));
|
||||
if (c1) {
|
||||
p = &(r[n + n2]);
|
||||
lo = *p;
|
||||
ln = (lo + c1) & BN_MASK2;
|
||||
*p = ln;
|
||||
|
||||
/*
|
||||
* The overflow will stop before we over write words we should not
|
||||
* overwrite
|
||||
*/
|
||||
if (ln < (BN_ULONG)c1) {
|
||||
do {
|
||||
p++;
|
||||
lo = *p;
|
||||
ln = (lo + 1) & BN_MASK2;
|
||||
*p = ln;
|
||||
} while (ln == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* n+tn is the word length t needs to be n*4 is size, as does r
|
||||
*/
|
||||
/* tnX may not be negative but less than n */
|
||||
void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n,
|
||||
int tna, int tnb, BN_ULONG *t)
|
||||
{
|
||||
int i, j, n2 = n * 2;
|
||||
int c1, c2, neg;
|
||||
BN_ULONG ln, lo, *p;
|
||||
|
||||
if (n < 8) {
|
||||
bn_mul_normal(r, a, n + tna, b, n + tnb);
|
||||
return;
|
||||
}
|
||||
|
||||
/* r=(a[0]-a[1])*(b[1]-b[0]) */
|
||||
c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);
|
||||
c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n);
|
||||
neg = 0;
|
||||
switch (c1 * 3 + c2) {
|
||||
case -4:
|
||||
bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
|
||||
bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
|
||||
break;
|
||||
case -3:
|
||||
case -2:
|
||||
bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
|
||||
bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */
|
||||
neg = 1;
|
||||
break;
|
||||
case -1:
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */
|
||||
bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
|
||||
neg = 1;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
bn_sub_part_words(t, a, &(a[n]), tna, n - tna);
|
||||
bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* The zero case isn't yet implemented here. The speedup would probably
|
||||
* be negligible.
|
||||
*/
|
||||
#if 0
|
||||
if (n == 4) {
|
||||
bn_mul_comba4(&(t[n2]), t, &(t[n]));
|
||||
bn_mul_comba4(r, a, b);
|
||||
bn_mul_normal(&(r[n2]), &(a[n]), tn, &(b[n]), tn);
|
||||
memset(&r[n2 + tn * 2], 0, sizeof(*r) * (n2 - tn * 2));
|
||||
} else
|
||||
#endif
|
||||
if (n == 8) {
|
||||
bn_mul_comba8(&(t[n2]), t, &(t[n]));
|
||||
bn_mul_comba8(r, a, b);
|
||||
bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);
|
||||
memset(&r[n2 + tna + tnb], 0, sizeof(*r) * (n2 - tna - tnb));
|
||||
} else {
|
||||
p = &(t[n2 * 2]);
|
||||
bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
|
||||
bn_mul_recursive(r, a, b, n, 0, 0, p);
|
||||
i = n / 2;
|
||||
/*
|
||||
* If there is only a bottom half to the number, just do it
|
||||
*/
|
||||
if (tna > tnb)
|
||||
j = tna - i;
|
||||
else
|
||||
j = tnb - i;
|
||||
if (j == 0) {
|
||||
bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]),
|
||||
i, tna - i, tnb - i, p);
|
||||
memset(&r[n2 + i * 2], 0, sizeof(*r) * (n2 - i * 2));
|
||||
} else if (j > 0) { /* eg, n == 16, i == 8 and tn == 11 */
|
||||
bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]),
|
||||
i, tna - i, tnb - i, p);
|
||||
memset(&(r[n2 + tna + tnb]), 0,
|
||||
sizeof(BN_ULONG) * (n2 - tna - tnb));
|
||||
} else { /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
|
||||
|
||||
memset(&r[n2], 0, sizeof(*r) * n2);
|
||||
if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL
|
||||
&& tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) {
|
||||
bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);
|
||||
} else {
|
||||
for (;;) {
|
||||
i /= 2;
|
||||
/*
|
||||
* these simplified conditions work exclusively because
|
||||
* difference between tna and tnb is 1 or 0
|
||||
*/
|
||||
if (i < tna || i < tnb) {
|
||||
bn_mul_part_recursive(&(r[n2]),
|
||||
&(a[n]), &(b[n]),
|
||||
i, tna - i, tnb - i, p);
|
||||
break;
|
||||
} else if (i == tna || i == tnb) {
|
||||
bn_mul_recursive(&(r[n2]),
|
||||
&(a[n]), &(b[n]),
|
||||
i, tna - i, tnb - i, p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
|
||||
* r[10] holds (a[0]*b[0])
|
||||
* r[32] holds (b[1]*b[1])
|
||||
*/
|
||||
|
||||
c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));
|
||||
|
||||
if (neg) { /* if t[32] is negative */
|
||||
c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));
|
||||
} else {
|
||||
/* Might have a carry */
|
||||
c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2));
|
||||
}
|
||||
|
||||
/*-
|
||||
* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
|
||||
* r[10] holds (a[0]*b[0])
|
||||
* r[32] holds (b[1]*b[1])
|
||||
* c1 holds the carry bits
|
||||
*/
|
||||
c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));
|
||||
if (c1) {
|
||||
p = &(r[n + n2]);
|
||||
lo = *p;
|
||||
ln = (lo + c1) & BN_MASK2;
|
||||
*p = ln;
|
||||
|
||||
/*
|
||||
* The overflow will stop before we over write words we should not
|
||||
* overwrite
|
||||
*/
|
||||
if (ln < (BN_ULONG)c1) {
|
||||
do {
|
||||
p++;
|
||||
lo = *p;
|
||||
ln = (lo + 1) & BN_MASK2;
|
||||
*p = ln;
|
||||
} while (ln == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
* a and b must be the same size, which is n2.
|
||||
* r needs to be n2 words and t needs to be n2*2
|
||||
*/
|
||||
void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
|
||||
BN_ULONG *t)
|
||||
{
|
||||
int n = n2 / 2;
|
||||
|
||||
bn_mul_recursive(r, a, b, n, 0, 0, &(t[0]));
|
||||
if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL) {
|
||||
bn_mul_low_recursive(&(t[0]), &(a[0]), &(b[n]), n, &(t[n2]));
|
||||
bn_add_words(&(r[n]), &(r[n]), &(t[0]), n);
|
||||
bn_mul_low_recursive(&(t[0]), &(a[n]), &(b[0]), n, &(t[n2]));
|
||||
bn_add_words(&(r[n]), &(r[n]), &(t[0]), n);
|
||||
} else {
|
||||
bn_mul_low_normal(&(t[0]), &(a[0]), &(b[n]), n);
|
||||
bn_mul_low_normal(&(t[n]), &(a[n]), &(b[0]), n);
|
||||
bn_add_words(&(r[n]), &(r[n]), &(t[0]), n);
|
||||
bn_add_words(&(r[n]), &(r[n]), &(t[n]), n);
|
||||
}
|
||||
}
|
||||
#endif /* BN_RECURSION */
|
||||
|
||||
int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
||||
{
|
||||
int ret = bn_mul_fixed_top(r, a, b, ctx);
|
||||
|
||||
bn_correct_top(r);
|
||||
bn_check_top(r);
|
||||
|
||||
size_t top = a->top + b->top;
|
||||
size_t max = a->dmax + b->dmax;
|
||||
|
||||
/*
|
||||
* Unfortunately, OSSL_FN_CTX and BN_CTX are too wildly different to
|
||||
* be interchangeable. We must therefore create an OSSL_FN_CTX here.
|
||||
* (OSSL_FN_CTX is only really useful within OSSL_FN functionality)
|
||||
*/
|
||||
OSSL_FN_CTX *fnctx = OSSL_FN_CTX_new(NULL, 1, 1, max);
|
||||
OSSL_FN *rf = bn_acquire_ossl_fn(r, (int)top);
|
||||
int ret = OSSL_FN_mul(rf, a->data, b->data, fnctx);
|
||||
bn_release(r, (int)top);
|
||||
|
||||
if (ret && !BN_is_zero(r))
|
||||
r->neg = a->neg ^ b->neg;
|
||||
|
||||
OSSL_FN_CTX_free(fnctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -55,6 +512,10 @@ int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
||||
#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
|
||||
int i;
|
||||
#endif
|
||||
#ifdef BN_RECURSION
|
||||
BIGNUM *t = NULL;
|
||||
int j = 0, k;
|
||||
#endif
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
@@ -85,8 +546,7 @@ int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
||||
if (al == 4) {
|
||||
if (bn_wexpand(rr, 8) == NULL)
|
||||
goto err;
|
||||
rr->flags |= BN_FLG_FIXED_TOP;
|
||||
bn_set_top(rr, 8);
|
||||
rr->top = 8;
|
||||
bn_mul_comba4(rr->d, a->d, b->d);
|
||||
goto end;
|
||||
}
|
||||
@@ -94,8 +554,7 @@ int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
||||
if (al == 8) {
|
||||
if (bn_wexpand(rr, 16) == NULL)
|
||||
goto err;
|
||||
rr->flags |= BN_FLG_FIXED_TOP;
|
||||
bn_set_top(rr, 16);
|
||||
rr->top = 16;
|
||||
bn_mul_comba8(rr->d, a->d, b->d);
|
||||
goto end;
|
||||
}
|
||||
@@ -104,9 +563,6 @@ int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
||||
#ifdef BN_RECURSION
|
||||
if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) {
|
||||
if (i >= -1 && i <= 1) {
|
||||
BIGNUM *t = NULL;
|
||||
int j = 0, k;
|
||||
|
||||
/*
|
||||
* Find out the power of two lower or equal to the longest of the
|
||||
* two numbers
|
||||
@@ -126,33 +582,26 @@ int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
||||
if (al > j || bl > j) {
|
||||
if (bn_wexpand(t, k * 4) == NULL)
|
||||
goto err;
|
||||
t->top = k * 4;
|
||||
t->flags |= BN_FLG_FIXED_TOP;
|
||||
if (bn_wexpand(rr, k * 4) == NULL)
|
||||
goto err;
|
||||
bn_set_top(rr, k * 4);
|
||||
rr->flags |= BN_FLG_FIXED_TOP;
|
||||
bn_mul_part_recursive(rr->d, a->d, b->d,
|
||||
j, al - j, bl - j, t->d);
|
||||
} else { /* al <= j || bl <= j */
|
||||
|
||||
if (bn_wexpand(t, k * 2) == NULL)
|
||||
goto err;
|
||||
t->top = k * 2;
|
||||
t->flags |= BN_FLG_FIXED_TOP;
|
||||
if (bn_wexpand(rr, k * 2) == NULL)
|
||||
goto err;
|
||||
bn_set_top(rr, k * 2);
|
||||
rr->flags |= BN_FLG_FIXED_TOP;
|
||||
bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d);
|
||||
}
|
||||
bn_set_top(rr, top);
|
||||
rr->top = top;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
#endif /* BN_RECURSION */
|
||||
if (bn_wexpand(rr, top) == NULL)
|
||||
goto err;
|
||||
bn_set_top(rr, top);
|
||||
rr->top = top;
|
||||
bn_mul_normal(rr->d, a->d, al, b->d, bl);
|
||||
|
||||
#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
|
||||
@@ -169,3 +618,66 @@ err:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb)
|
||||
{
|
||||
BN_ULONG *rr;
|
||||
|
||||
if (na < nb) {
|
||||
int itmp;
|
||||
BN_ULONG *ltmp;
|
||||
|
||||
itmp = na;
|
||||
na = nb;
|
||||
nb = itmp;
|
||||
ltmp = a;
|
||||
a = b;
|
||||
b = ltmp;
|
||||
}
|
||||
rr = &(r[na]);
|
||||
if (nb <= 0) {
|
||||
(void)bn_mul_words(r, a, na, 0);
|
||||
return;
|
||||
} else
|
||||
rr[0] = bn_mul_words(r, a, na, b[0]);
|
||||
|
||||
for (;;) {
|
||||
if (--nb <= 0)
|
||||
return;
|
||||
rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]);
|
||||
if (--nb <= 0)
|
||||
return;
|
||||
rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]);
|
||||
if (--nb <= 0)
|
||||
return;
|
||||
rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]);
|
||||
if (--nb <= 0)
|
||||
return;
|
||||
rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]);
|
||||
rr += 4;
|
||||
r += 4;
|
||||
b += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
|
||||
{
|
||||
bn_mul_words(r, a, n, b[0]);
|
||||
|
||||
for (;;) {
|
||||
if (--n <= 0)
|
||||
return;
|
||||
bn_mul_add_words(&(r[1]), a, n, b[1]);
|
||||
if (--n <= 0)
|
||||
return;
|
||||
bn_mul_add_words(&(r[2]), a, n, b[2]);
|
||||
if (--n <= 0)
|
||||
return;
|
||||
bn_mul_add_words(&(r[3]), a, n, b[3]);
|
||||
if (--n <= 0)
|
||||
return;
|
||||
bn_mul_add_words(&(r[4]), a, n, b[4]);
|
||||
r += 4;
|
||||
b += 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,38 +184,43 @@ static const BN_ULONG _nist_p_521_sqr[] = {
|
||||
#endif
|
||||
|
||||
static const BIGNUM ossl_bignum_nist_p_192 = {
|
||||
.d = (BN_ULONG *)_nist_p_192[0],
|
||||
.top = BN_NIST_192_TOP,
|
||||
.dmax = BN_NIST_192_TOP,
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)_nist_p_192[0],
|
||||
BN_NIST_192_TOP,
|
||||
BN_NIST_192_TOP,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BIGNUM ossl_bignum_nist_p_224 = {
|
||||
.d = (BN_ULONG *)_nist_p_224[0],
|
||||
.top = BN_NIST_224_TOP,
|
||||
.dmax = BN_NIST_224_TOP,
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)_nist_p_224[0],
|
||||
BN_NIST_224_TOP,
|
||||
BN_NIST_224_TOP,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BIGNUM ossl_bignum_nist_p_256 = {
|
||||
.d = (BN_ULONG *)_nist_p_256[0],
|
||||
.top = BN_NIST_256_TOP,
|
||||
.dmax = BN_NIST_256_TOP,
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)_nist_p_256[0],
|
||||
BN_NIST_256_TOP,
|
||||
BN_NIST_256_TOP,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BIGNUM ossl_bignum_nist_p_384 = {
|
||||
.d = (BN_ULONG *)_nist_p_384[0],
|
||||
.top = BN_NIST_384_TOP,
|
||||
.dmax = BN_NIST_384_TOP,
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)_nist_p_384[0],
|
||||
BN_NIST_384_TOP,
|
||||
BN_NIST_384_TOP,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BIGNUM ossl_bignum_nist_p_521 = {
|
||||
.d = (BN_ULONG *)_nist_p_521,
|
||||
.top = BN_NIST_521_TOP,
|
||||
.dmax = BN_NIST_521_TOP,
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)_nist_p_521,
|
||||
BN_NIST_521_TOP,
|
||||
BN_NIST_521_TOP,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
const BIGNUM *BN_get0_nist_prime_192(void)
|
||||
@@ -354,10 +359,10 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
} buf;
|
||||
BN_ULONG c_d[BN_NIST_192_TOP], *res;
|
||||
static const BIGNUM ossl_bignum_nist_p_192_sqr = {
|
||||
.d = (BN_ULONG *)_nist_p_192_sqr,
|
||||
.top = OSSL_NELEM(_nist_p_192_sqr),
|
||||
.dmax = OSSL_NELEM(_nist_p_192_sqr),
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)_nist_p_192_sqr,
|
||||
OSSL_NELEM(_nist_p_192_sqr),
|
||||
OSSL_NELEM(_nist_p_192_sqr),
|
||||
0, BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
field = &ossl_bignum_nist_p_192; /* just to make sure */
|
||||
@@ -457,7 +462,7 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
? r_d
|
||||
: c_d;
|
||||
nist_cp_bn(r_d, res, BN_NIST_192_TOP);
|
||||
bn_set_top(r, BN_NIST_192_TOP);
|
||||
r->top = BN_NIST_192_TOP;
|
||||
bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
@@ -490,10 +495,10 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
BN_ULONG c_d[BN_NIST_224_TOP], *res;
|
||||
bn_addsub_f adjust;
|
||||
static const BIGNUM ossl_bignum_nist_p_224_sqr = {
|
||||
.d = (BN_ULONG *)_nist_p_224_sqr,
|
||||
.top = OSSL_NELEM(_nist_p_224_sqr),
|
||||
.dmax = OSSL_NELEM(_nist_p_224_sqr),
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)_nist_p_224_sqr,
|
||||
OSSL_NELEM(_nist_p_224_sqr),
|
||||
OSSL_NELEM(_nist_p_224_sqr),
|
||||
0, BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
field = &ossl_bignum_nist_p_224; /* just to make sure */
|
||||
@@ -628,7 +633,7 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
? r_d
|
||||
: c_d;
|
||||
nist_cp_bn(r_d, res, BN_NIST_224_TOP);
|
||||
bn_set_top(r, BN_NIST_224_TOP);
|
||||
r->top = BN_NIST_224_TOP;
|
||||
bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
@@ -659,10 +664,10 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
BN_ULONG c_d[BN_NIST_256_TOP], *res;
|
||||
bn_addsub_f adjust;
|
||||
static const BIGNUM ossl_bignum_nist_p_256_sqr = {
|
||||
.d = (BN_ULONG *)_nist_p_256_sqr,
|
||||
.top = OSSL_NELEM(_nist_p_256_sqr),
|
||||
.dmax = OSSL_NELEM(_nist_p_256_sqr),
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)_nist_p_256_sqr,
|
||||
OSSL_NELEM(_nist_p_256_sqr),
|
||||
OSSL_NELEM(_nist_p_256_sqr),
|
||||
0, BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
field = &ossl_bignum_nist_p_256; /* just to make sure */
|
||||
@@ -857,7 +862,7 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
? r_d
|
||||
: c_d;
|
||||
nist_cp_bn(r_d, res, BN_NIST_256_TOP);
|
||||
bn_set_top(r, BN_NIST_256_TOP);
|
||||
r->top = BN_NIST_256_TOP;
|
||||
bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
@@ -892,10 +897,10 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
BN_ULONG c_d[BN_NIST_384_TOP], *res;
|
||||
bn_addsub_f adjust;
|
||||
static const BIGNUM ossl_bignum_nist_p_384_sqr = {
|
||||
.d = (BN_ULONG *)_nist_p_384_sqr,
|
||||
.top = OSSL_NELEM(_nist_p_384_sqr),
|
||||
.dmax = OSSL_NELEM(_nist_p_384_sqr),
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)_nist_p_384_sqr,
|
||||
OSSL_NELEM(_nist_p_384_sqr),
|
||||
OSSL_NELEM(_nist_p_384_sqr),
|
||||
0, BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
field = &ossl_bignum_nist_p_384; /* just to make sure */
|
||||
@@ -1124,7 +1129,7 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
? r_d
|
||||
: c_d;
|
||||
nist_cp_bn(r_d, res, BN_NIST_384_TOP);
|
||||
bn_set_top(r, BN_NIST_384_TOP);
|
||||
r->top = BN_NIST_384_TOP;
|
||||
bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
@@ -1140,10 +1145,10 @@ int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
int top = a->top, i;
|
||||
BN_ULONG *r_d, *a_d = a->d, t_d[BN_NIST_521_TOP], val, tmp, *res;
|
||||
static const BIGNUM ossl_bignum_nist_p_521_sqr = {
|
||||
.d = (BN_ULONG *)_nist_p_521_sqr,
|
||||
.top = OSSL_NELEM(_nist_p_521_sqr),
|
||||
.dmax = OSSL_NELEM(_nist_p_521_sqr),
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)_nist_p_521_sqr,
|
||||
OSSL_NELEM(_nist_p_521_sqr),
|
||||
OSSL_NELEM(_nist_p_521_sqr),
|
||||
0, BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
field = &ossl_bignum_nist_p_521; /* just to make sure */
|
||||
@@ -1195,7 +1200,7 @@ int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
? r_d
|
||||
: t_d;
|
||||
nist_cp_bn(r_d, res, BN_NIST_521_TOP);
|
||||
bn_set_top(r, BN_NIST_521_TOP);
|
||||
r->top = BN_NIST_521_TOP;
|
||||
bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -55,10 +55,11 @@ static const BN_ULONG small_prime_factors[] = {
|
||||
|
||||
#define BN_SMALL_PRIME_FACTORS_TOP OSSL_NELEM(small_prime_factors)
|
||||
static const BIGNUM _bignum_small_prime_factors = {
|
||||
.d = (BN_ULONG *)small_prime_factors,
|
||||
.top = BN_SMALL_PRIME_FACTORS_TOP,
|
||||
.dmax = BN_SMALL_PRIME_FACTORS_TOP,
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)small_prime_factors,
|
||||
BN_SMALL_PRIME_FACTORS_TOP,
|
||||
BN_SMALL_PRIME_FACTORS_TOP,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
const BIGNUM *ossl_bn_get0_small_factors(void)
|
||||
|
||||
@@ -41,10 +41,11 @@ static const BN_ULONG inv_sqrt_2_val[] = {
|
||||
};
|
||||
|
||||
const BIGNUM ossl_bn_inv_sqrt_2 = {
|
||||
.d = (BN_ULONG *)inv_sqrt_2_val,
|
||||
.top = OSSL_NELEM(inv_sqrt_2_val),
|
||||
.dmax = OSSL_NELEM(inv_sqrt_2_val),
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)inv_sqrt_2_val,
|
||||
OSSL_NELEM(inv_sqrt_2_val),
|
||||
OSSL_NELEM(inv_sqrt_2_val),
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -23,7 +23,7 @@ int BN_lshift1(BIGNUM *r, const BIGNUM *a)
|
||||
r->neg = a->neg;
|
||||
if (bn_wexpand(r, a->top + 1) == NULL)
|
||||
return 0;
|
||||
bn_set_top(r, a->top);
|
||||
r->top = a->top;
|
||||
} else {
|
||||
if (bn_wexpand(r, a->top + 1) == NULL)
|
||||
return 0;
|
||||
@@ -37,7 +37,7 @@ int BN_lshift1(BIGNUM *r, const BIGNUM *a)
|
||||
c = t >> (BN_BITS2 - 1);
|
||||
}
|
||||
*rp = c;
|
||||
bn_set_top(r, r->top + (int)c);
|
||||
r->top += (int)c;
|
||||
bn_check_top(r);
|
||||
return 1;
|
||||
}
|
||||
@@ -62,10 +62,11 @@ int BN_rshift1(BIGNUM *r, const BIGNUM *a)
|
||||
r->neg = a->neg;
|
||||
}
|
||||
rp = r->d;
|
||||
r->top = i;
|
||||
t = ap[--i];
|
||||
rp[i] = t >> 1;
|
||||
c = t << (BN_BITS2 - 1);
|
||||
bn_set_top(r, i + (t > 1));
|
||||
r->top -= (t == 1);
|
||||
while (i > 0) {
|
||||
t = ap[--i];
|
||||
rp[i] = ((t >> 1) & BN_MASK2) | c;
|
||||
@@ -140,7 +141,7 @@ int bn_lshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n)
|
||||
memset(r->d, 0, sizeof(*t) * nw);
|
||||
|
||||
r->neg = a->neg;
|
||||
bn_set_top(r, a->top + nw + 1);
|
||||
r->top = a->top + nw + 1;
|
||||
r->flags |= BN_FLG_FIXED_TOP;
|
||||
|
||||
return 1;
|
||||
@@ -208,7 +209,7 @@ int bn_rshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n)
|
||||
t[i] = l >> rb;
|
||||
|
||||
r->neg = a->neg;
|
||||
bn_set_top(r, top);
|
||||
r->top = top;
|
||||
r->flags |= BN_FLG_FIXED_TOP;
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -34,7 +34,7 @@ int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
|
||||
|
||||
al = a->top;
|
||||
if (al <= 0) {
|
||||
bn_set_top(r, 0);
|
||||
r->top = 0;
|
||||
r->neg = 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -91,12 +91,8 @@ int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Ensure that tmp won't cause any trouble */
|
||||
tmp->top = tmp->dmax;
|
||||
tmp->flags |= BN_FLG_FIXED_TOP;
|
||||
|
||||
rr->neg = 0;
|
||||
bn_set_top(rr, max);
|
||||
rr->top = max;
|
||||
rr->flags |= BN_FLG_FIXED_TOP;
|
||||
if (r != rr && BN_copy(r, rr) == NULL)
|
||||
goto err;
|
||||
@@ -104,6 +100,7 @@ int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
|
||||
ret = 1;
|
||||
err:
|
||||
bn_check_top(rr);
|
||||
bn_check_top(tmp);
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -49,10 +49,11 @@ static const BN_ULONG bn_group_1024_value[] = {
|
||||
};
|
||||
|
||||
const BIGNUM ossl_bn_group_1024 = {
|
||||
.d = (BN_ULONG *)bn_group_1024_value,
|
||||
.top = OSSL_NELEM(bn_group_1024_value),
|
||||
.dmax = OSSL_NELEM(bn_group_1024_value),
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)bn_group_1024_value,
|
||||
OSSL_NELEM(bn_group_1024_value),
|
||||
OSSL_NELEM(bn_group_1024_value),
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BN_ULONG bn_group_1536_value[] = {
|
||||
@@ -83,10 +84,11 @@ static const BN_ULONG bn_group_1536_value[] = {
|
||||
};
|
||||
|
||||
const BIGNUM ossl_bn_group_1536 = {
|
||||
.d = (BN_ULONG *)bn_group_1536_value,
|
||||
.top = OSSL_NELEM(bn_group_1536_value),
|
||||
.dmax = OSSL_NELEM(bn_group_1536_value),
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)bn_group_1536_value,
|
||||
OSSL_NELEM(bn_group_1536_value),
|
||||
OSSL_NELEM(bn_group_1536_value),
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BN_ULONG bn_group_2048_value[] = {
|
||||
@@ -125,10 +127,11 @@ static const BN_ULONG bn_group_2048_value[] = {
|
||||
};
|
||||
|
||||
const BIGNUM ossl_bn_group_2048 = {
|
||||
.d = (BN_ULONG *)bn_group_2048_value,
|
||||
.top = OSSL_NELEM(bn_group_2048_value),
|
||||
.dmax = OSSL_NELEM(bn_group_2048_value),
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)bn_group_2048_value,
|
||||
OSSL_NELEM(bn_group_2048_value),
|
||||
OSSL_NELEM(bn_group_2048_value),
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BN_ULONG bn_group_3072_value[] = {
|
||||
@@ -183,10 +186,11 @@ static const BN_ULONG bn_group_3072_value[] = {
|
||||
};
|
||||
|
||||
const BIGNUM ossl_bn_group_3072 = {
|
||||
.d = (BN_ULONG *)bn_group_3072_value,
|
||||
.top = OSSL_NELEM(bn_group_3072_value),
|
||||
.dmax = OSSL_NELEM(bn_group_3072_value),
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)bn_group_3072_value,
|
||||
OSSL_NELEM(bn_group_3072_value),
|
||||
OSSL_NELEM(bn_group_3072_value),
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BN_ULONG bn_group_4096_value[] = {
|
||||
@@ -257,10 +261,11 @@ static const BN_ULONG bn_group_4096_value[] = {
|
||||
};
|
||||
|
||||
const BIGNUM ossl_bn_group_4096 = {
|
||||
.d = (BN_ULONG *)bn_group_4096_value,
|
||||
.top = OSSL_NELEM(bn_group_4096_value),
|
||||
.dmax = OSSL_NELEM(bn_group_4096_value),
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)bn_group_4096_value,
|
||||
OSSL_NELEM(bn_group_4096_value),
|
||||
OSSL_NELEM(bn_group_4096_value),
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BN_ULONG bn_group_6144_value[] = {
|
||||
@@ -363,10 +368,11 @@ static const BN_ULONG bn_group_6144_value[] = {
|
||||
};
|
||||
|
||||
const BIGNUM ossl_bn_group_6144 = {
|
||||
.d = (BN_ULONG *)bn_group_6144_value,
|
||||
.top = OSSL_NELEM(bn_group_6144_value),
|
||||
.dmax = OSSL_NELEM(bn_group_6144_value),
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)bn_group_6144_value,
|
||||
OSSL_NELEM(bn_group_6144_value),
|
||||
OSSL_NELEM(bn_group_6144_value),
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BN_ULONG bn_group_8192_value[] = {
|
||||
@@ -501,35 +507,39 @@ static const BN_ULONG bn_group_8192_value[] = {
|
||||
};
|
||||
|
||||
const BIGNUM ossl_bn_group_8192 = {
|
||||
.d = (BN_ULONG *)bn_group_8192_value,
|
||||
.top = OSSL_NELEM(bn_group_8192_value),
|
||||
.dmax = OSSL_NELEM(bn_group_8192_value),
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)bn_group_8192_value,
|
||||
OSSL_NELEM(bn_group_8192_value),
|
||||
OSSL_NELEM(bn_group_8192_value),
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BN_ULONG bn_generator_19_value[] = { 19 };
|
||||
|
||||
const BIGNUM ossl_bn_generator_19 = {
|
||||
.d = (BN_ULONG *)bn_generator_19_value,
|
||||
.top = 1,
|
||||
.dmax = 1,
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)bn_generator_19_value,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
static const BN_ULONG bn_generator_5_value[] = { 5 };
|
||||
|
||||
const BIGNUM ossl_bn_generator_5 = {
|
||||
.d = (BN_ULONG *)bn_generator_5_value,
|
||||
.top = 1,
|
||||
.dmax = 1,
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)bn_generator_5_value,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
static const BN_ULONG bn_generator_2_value[] = { 2 };
|
||||
|
||||
const BIGNUM ossl_bn_generator_2 = {
|
||||
.d = (BN_ULONG *)bn_generator_2_value,
|
||||
.top = 1,
|
||||
.dmax = 1,
|
||||
.flags = BN_FLG_STATIC_DATA,
|
||||
(BN_ULONG *)bn_generator_2_value,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,413 +0,0 @@
|
||||
/*
|
||||
* Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "bn_local.h"
|
||||
|
||||
#ifdef BN_RECURSION
|
||||
/*
|
||||
* Karatsuba recursive multiplication algorithm (cf. Knuth, The Art of
|
||||
* Computer Programming, Vol. 2)
|
||||
*/
|
||||
|
||||
/*-
|
||||
* r is 2*n2 words in size,
|
||||
* a and b are both n2 words in size.
|
||||
* n2 must be a power of 2.
|
||||
* We multiply and return the result.
|
||||
* t must be 2*n2 words in size
|
||||
* We calculate
|
||||
* a[0]*b[0]
|
||||
* a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
|
||||
* a[1]*b[1]
|
||||
*/
|
||||
/* dnX may not be positive, but n2/2+dnX has to be */
|
||||
void bn_mul_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n2,
|
||||
int dna, int dnb, BN_ULONG *t)
|
||||
{
|
||||
int n = n2 / 2, c1, c2;
|
||||
int tna = n + dna, tnb = n + dnb;
|
||||
unsigned int neg, zero;
|
||||
BN_ULONG ln, lo, *p;
|
||||
|
||||
#ifdef BN_MUL_COMBA
|
||||
#if 0
|
||||
if (n2 == 4) {
|
||||
bn_mul_comba4(r, a, b);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Only call bn_mul_comba 8 if n2 == 8 and the two arrays are complete
|
||||
* [steve]
|
||||
*/
|
||||
if (n2 == 8 && dna == 0 && dnb == 0) {
|
||||
bn_mul_comba8(r, a, b);
|
||||
return;
|
||||
}
|
||||
#endif /* BN_MUL_COMBA */
|
||||
/* Else do normal multiply */
|
||||
if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) {
|
||||
bn_mul_normal(r, a, n2 + dna, b, n2 + dnb);
|
||||
if ((dna + dnb) < 0)
|
||||
memset(&r[2 * n2 + dna + dnb], 0,
|
||||
sizeof(BN_ULONG) * -(dna + dnb));
|
||||
return;
|
||||
}
|
||||
/* r=(a[0]-a[1])*(b[1]-b[0]) */
|
||||
c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);
|
||||
c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n);
|
||||
zero = neg = 0;
|
||||
switch (c1 * 3 + c2) {
|
||||
case -4:
|
||||
bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
|
||||
bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
|
||||
break;
|
||||
case -3:
|
||||
zero = 1;
|
||||
break;
|
||||
case -2:
|
||||
bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
|
||||
bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */
|
||||
neg = 1;
|
||||
break;
|
||||
case -1:
|
||||
case 0:
|
||||
case 1:
|
||||
zero = 1;
|
||||
break;
|
||||
case 2:
|
||||
bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */
|
||||
bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
|
||||
neg = 1;
|
||||
break;
|
||||
case 3:
|
||||
zero = 1;
|
||||
break;
|
||||
case 4:
|
||||
bn_sub_part_words(t, a, &(a[n]), tna, n - tna);
|
||||
bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef BN_MUL_COMBA
|
||||
if (n == 4 && dna == 0 && dnb == 0) { /* XXX: bn_mul_comba4 could take
|
||||
* extra args to do this well */
|
||||
if (!zero)
|
||||
bn_mul_comba4(&(t[n2]), t, &(t[n]));
|
||||
else
|
||||
memset(&t[n2], 0, sizeof(*t) * 8);
|
||||
|
||||
bn_mul_comba4(r, a, b);
|
||||
bn_mul_comba4(&(r[n2]), &(a[n]), &(b[n]));
|
||||
} else if (n == 8 && dna == 0 && dnb == 0) { /* XXX: bn_mul_comba8 could
|
||||
* take extra args to do
|
||||
* this well */
|
||||
if (!zero)
|
||||
bn_mul_comba8(&(t[n2]), t, &(t[n]));
|
||||
else
|
||||
memset(&t[n2], 0, sizeof(*t) * 16);
|
||||
|
||||
bn_mul_comba8(r, a, b);
|
||||
bn_mul_comba8(&(r[n2]), &(a[n]), &(b[n]));
|
||||
} else
|
||||
#endif /* BN_MUL_COMBA */
|
||||
{
|
||||
p = &(t[n2 * 2]);
|
||||
if (!zero)
|
||||
bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
|
||||
else
|
||||
memset(&t[n2], 0, sizeof(*t) * n2);
|
||||
bn_mul_recursive(r, a, b, n, 0, 0, p);
|
||||
bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p);
|
||||
}
|
||||
|
||||
/*-
|
||||
* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
|
||||
* r[10] holds (a[0]*b[0])
|
||||
* r[32] holds (b[1]*b[1])
|
||||
*/
|
||||
|
||||
c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));
|
||||
|
||||
if (neg) { /* if t[32] is negative */
|
||||
c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));
|
||||
} else {
|
||||
/* Might have a carry */
|
||||
c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2));
|
||||
}
|
||||
|
||||
/*-
|
||||
* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
|
||||
* r[10] holds (a[0]*b[0])
|
||||
* r[32] holds (b[1]*b[1])
|
||||
* c1 holds the carry bits
|
||||
*/
|
||||
c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));
|
||||
if (c1) {
|
||||
p = &(r[n + n2]);
|
||||
lo = *p;
|
||||
ln = (lo + c1) & BN_MASK2;
|
||||
*p = ln;
|
||||
|
||||
/*
|
||||
* The overflow will stop before we over write words we should not
|
||||
* overwrite
|
||||
*/
|
||||
if (ln < (BN_ULONG)c1) {
|
||||
do {
|
||||
p++;
|
||||
lo = *p;
|
||||
ln = (lo + 1) & BN_MASK2;
|
||||
*p = ln;
|
||||
} while (ln == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* n+tn is the word length t needs to be n*4 is size, as does r
|
||||
*/
|
||||
/* tnX may not be negative but less than n */
|
||||
void bn_mul_part_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
int n, int tna, int tnb, BN_ULONG *t)
|
||||
{
|
||||
int i, j, n2 = n * 2;
|
||||
int c1, c2, neg;
|
||||
BN_ULONG ln, lo, *p;
|
||||
|
||||
if (n < 8) {
|
||||
bn_mul_normal(r, a, n + tna, b, n + tnb);
|
||||
return;
|
||||
}
|
||||
|
||||
/* r=(a[0]-a[1])*(b[1]-b[0]) */
|
||||
c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);
|
||||
c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n);
|
||||
neg = 0;
|
||||
switch (c1 * 3 + c2) {
|
||||
case -4:
|
||||
bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
|
||||
bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
|
||||
break;
|
||||
case -3:
|
||||
case -2:
|
||||
bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
|
||||
bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */
|
||||
neg = 1;
|
||||
break;
|
||||
case -1:
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */
|
||||
bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
|
||||
neg = 1;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
bn_sub_part_words(t, a, &(a[n]), tna, n - tna);
|
||||
bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* The zero case isn't yet implemented here. The speedup would probably
|
||||
* be negligible.
|
||||
*/
|
||||
#if 0
|
||||
if (n == 4) {
|
||||
bn_mul_comba4(&(t[n2]), t, &(t[n]));
|
||||
bn_mul_comba4(r, a, b);
|
||||
bn_mul_normal(&(r[n2]), &(a[n]), tn, &(b[n]), tn);
|
||||
memset(&r[n2 + tn * 2], 0, sizeof(*r) * (n2 - tn * 2));
|
||||
} else
|
||||
#endif
|
||||
if (n == 8) {
|
||||
bn_mul_comba8(&(t[n2]), t, &(t[n]));
|
||||
bn_mul_comba8(r, a, b);
|
||||
bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);
|
||||
memset(&r[n2 + tna + tnb], 0, sizeof(*r) * (n2 - tna - tnb));
|
||||
} else {
|
||||
p = &(t[n2 * 2]);
|
||||
bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
|
||||
bn_mul_recursive(r, a, b, n, 0, 0, p);
|
||||
i = n / 2;
|
||||
/*
|
||||
* If there is only a bottom half to the number, just do it
|
||||
*/
|
||||
if (tna > tnb)
|
||||
j = tna - i;
|
||||
else
|
||||
j = tnb - i;
|
||||
if (j == 0) {
|
||||
bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]),
|
||||
i, tna - i, tnb - i, p);
|
||||
memset(&r[n2 + i * 2], 0, sizeof(*r) * (n2 - i * 2));
|
||||
} else if (j > 0) { /* eg, n == 16, i == 8 and tn == 11 */
|
||||
bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]),
|
||||
i, tna - i, tnb - i, p);
|
||||
memset(&(r[n2 + tna + tnb]), 0,
|
||||
sizeof(BN_ULONG) * (n2 - tna - tnb));
|
||||
} else { /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
|
||||
|
||||
memset(&r[n2], 0, sizeof(*r) * n2);
|
||||
if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL
|
||||
&& tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) {
|
||||
bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);
|
||||
} else {
|
||||
for (;;) {
|
||||
i /= 2;
|
||||
/*
|
||||
* these simplified conditions work exclusively because
|
||||
* difference between tna and tnb is 1 or 0
|
||||
*/
|
||||
if (i < tna || i < tnb) {
|
||||
bn_mul_part_recursive(&(r[n2]),
|
||||
&(a[n]), &(b[n]),
|
||||
i, tna - i, tnb - i, p);
|
||||
break;
|
||||
} else if (i == tna || i == tnb) {
|
||||
bn_mul_recursive(&(r[n2]),
|
||||
&(a[n]), &(b[n]),
|
||||
i, tna - i, tnb - i, p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
|
||||
* r[10] holds (a[0]*b[0])
|
||||
* r[32] holds (b[1]*b[1])
|
||||
*/
|
||||
|
||||
c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));
|
||||
|
||||
if (neg) { /* if t[32] is negative */
|
||||
c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));
|
||||
} else {
|
||||
/* Might have a carry */
|
||||
c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2));
|
||||
}
|
||||
|
||||
/*-
|
||||
* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
|
||||
* r[10] holds (a[0]*b[0])
|
||||
* r[32] holds (b[1]*b[1])
|
||||
* c1 holds the carry bits
|
||||
*/
|
||||
c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));
|
||||
if (c1) {
|
||||
p = &(r[n + n2]);
|
||||
lo = *p;
|
||||
ln = (lo + c1) & BN_MASK2;
|
||||
*p = ln;
|
||||
|
||||
/*
|
||||
* The overflow will stop before we over write words we should not
|
||||
* overwrite
|
||||
*/
|
||||
if (ln < (BN_ULONG)c1) {
|
||||
do {
|
||||
p++;
|
||||
lo = *p;
|
||||
ln = (lo + 1) & BN_MASK2;
|
||||
*p = ln;
|
||||
} while (ln == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
* a and b must be the same size, which is n2.
|
||||
* r needs to be n2 words and t needs to be n2*2
|
||||
*/
|
||||
void bn_mul_low_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
int n2, BN_ULONG *t)
|
||||
{
|
||||
int n = n2 / 2;
|
||||
|
||||
bn_mul_recursive(r, a, b, n, 0, 0, &(t[0]));
|
||||
if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL) {
|
||||
bn_mul_low_recursive(&(t[0]), &(a[0]), &(b[n]), n, &(t[n2]));
|
||||
bn_add_words(&(r[n]), &(r[n]), &(t[0]), n);
|
||||
bn_mul_low_recursive(&(t[0]), &(a[n]), &(b[0]), n, &(t[n2]));
|
||||
bn_add_words(&(r[n]), &(r[n]), &(t[0]), n);
|
||||
} else {
|
||||
bn_mul_low_normal(&(t[0]), &(a[0]), &(b[n]), n);
|
||||
bn_mul_low_normal(&(t[n]), &(a[n]), &(b[0]), n);
|
||||
bn_add_words(&(r[n]), &(r[n]), &(t[0]), n);
|
||||
bn_add_words(&(r[n]), &(r[n]), &(t[n]), n);
|
||||
}
|
||||
}
|
||||
#endif /* BN_RECURSION */
|
||||
|
||||
void bn_mul_truncated(BN_ULONG *r, int nr, const BN_ULONG *a, int na,
|
||||
const BN_ULONG *b, int nb)
|
||||
{
|
||||
BN_ULONG tmp, *carryp = NULL;
|
||||
int n; /* Number of words to use in the current iteration */
|
||||
|
||||
if (na < nb) {
|
||||
int itmp;
|
||||
const BN_ULONG *ltmp;
|
||||
|
||||
itmp = na;
|
||||
na = nb;
|
||||
nb = itmp;
|
||||
ltmp = a;
|
||||
a = b;
|
||||
b = ltmp;
|
||||
}
|
||||
n = (na < nr) ? na : nr;
|
||||
if (nb <= 0) {
|
||||
(void)bn_mul_words(r, a, n, 0);
|
||||
return;
|
||||
} else {
|
||||
carryp = (na < nr) ? &r[na] : &tmp;
|
||||
*carryp = bn_mul_words(r, a, n, b[0]);
|
||||
}
|
||||
|
||||
for (int i = 1; i < nb && i < nr; i++) {
|
||||
int rspace = nr - i;
|
||||
n = (na < rspace) ? na : rspace;
|
||||
carryp = (na < rspace) ? &r[i + na] : &tmp;
|
||||
*carryp = bn_mul_add_words(&(r[i]), a, n, b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void bn_mul_normal(BN_ULONG *r, const BN_ULONG *a, int na, const BN_ULONG *b,
|
||||
int nb)
|
||||
{
|
||||
bn_mul_truncated(r, na + nb, a, na, b, nb);
|
||||
}
|
||||
|
||||
void bn_mul_low_normal(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n)
|
||||
{
|
||||
bn_mul_words(r, a, n, b[0]);
|
||||
|
||||
for (;;) {
|
||||
if (--n <= 0)
|
||||
return;
|
||||
bn_mul_add_words(&(r[1]), a, n, b[1]);
|
||||
if (--n <= 0)
|
||||
return;
|
||||
bn_mul_add_words(&(r[2]), a, n, b[2]);
|
||||
if (--n <= 0)
|
||||
return;
|
||||
bn_mul_add_words(&(r[3]), a, n, b[3]);
|
||||
if (--n <= 0)
|
||||
return;
|
||||
bn_mul_add_words(&(r[4]), a, n, b[4]);
|
||||
r += 4;
|
||||
b += 4;
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "bn_local.h"
|
||||
|
||||
#if defined(OPENSSL_NO_ASM) || !defined(OPENSSL_BN_ASM_PART_WORDS)
|
||||
/*
|
||||
* Here follows specialised variants of bn_add_words() and bn_sub_words().
|
||||
* They have the property performing operations on arrays of different sizes.
|
||||
* The sizes of those arrays is expressed through cl, which is the common
|
||||
* length ( basically, min(len(a),len(b)) ), and dl, which is the delta
|
||||
* between the two lengths, calculated as len(a)-len(b). All lengths are the
|
||||
* number of BN_ULONGs... For the operations that require a result array as
|
||||
* parameter, it must have the length cl+abs(dl).
|
||||
*
|
||||
* These functions should probably end up in bn_asm.c as soon as there are
|
||||
* assembler counterparts for the systems that use assembler files.
|
||||
*/
|
||||
|
||||
BN_ULONG bn_sub_part_words(BN_ULONG *r,
|
||||
const BN_ULONG *a, const BN_ULONG *b,
|
||||
int cl, int dl)
|
||||
{
|
||||
BN_ULONG c, t;
|
||||
|
||||
assert(cl >= 0);
|
||||
c = bn_sub_words(r, a, b, cl);
|
||||
|
||||
if (dl == 0)
|
||||
return c;
|
||||
|
||||
r += cl;
|
||||
a += cl;
|
||||
b += cl;
|
||||
|
||||
if (dl < 0) {
|
||||
for (;;) {
|
||||
t = b[0];
|
||||
r[0] = (0 - t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 1;
|
||||
if (++dl >= 0)
|
||||
break;
|
||||
|
||||
t = b[1];
|
||||
r[1] = (0 - t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 1;
|
||||
if (++dl >= 0)
|
||||
break;
|
||||
|
||||
t = b[2];
|
||||
r[2] = (0 - t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 1;
|
||||
if (++dl >= 0)
|
||||
break;
|
||||
|
||||
t = b[3];
|
||||
r[3] = (0 - t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 1;
|
||||
if (++dl >= 0)
|
||||
break;
|
||||
|
||||
b += 4;
|
||||
r += 4;
|
||||
}
|
||||
} else {
|
||||
int save_dl = dl;
|
||||
while (c) {
|
||||
t = a[0];
|
||||
r[0] = (t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 0;
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
|
||||
t = a[1];
|
||||
r[1] = (t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 0;
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
|
||||
t = a[2];
|
||||
r[2] = (t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 0;
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
|
||||
t = a[3];
|
||||
r[3] = (t - c) & BN_MASK2;
|
||||
if (t != 0)
|
||||
c = 0;
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
|
||||
save_dl = dl;
|
||||
a += 4;
|
||||
r += 4;
|
||||
}
|
||||
if (dl > 0) {
|
||||
if (save_dl > dl) {
|
||||
switch (save_dl - dl) {
|
||||
case 1:
|
||||
r[1] = a[1];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
/* fall through */
|
||||
case 2:
|
||||
r[2] = a[2];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
/* fall through */
|
||||
case 3:
|
||||
r[3] = a[3];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
}
|
||||
a += 4;
|
||||
r += 4;
|
||||
}
|
||||
}
|
||||
if (dl > 0) {
|
||||
for (;;) {
|
||||
r[0] = a[0];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
r[1] = a[1];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
r[2] = a[2];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
r[3] = a[3];
|
||||
if (--dl <= 0)
|
||||
break;
|
||||
|
||||
a += 4;
|
||||
r += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
@@ -105,18 +105,11 @@ IF[{- !$disabled{asm} -}]
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
$COMMON_BN=bn_add.c bn_div.c bn_exp.c bn_lib.c bn_ctx.c bn_mul.c \
|
||||
$COMMON=bn_add.c bn_div.c bn_exp.c bn_lib.c bn_ctx.c bn_mul.c \
|
||||
bn_mod.c bn_conv.c bn_rand.c bn_shift.c bn_word.c bn_blind.c \
|
||||
bn_kron.c bn_sqrt.c bn_gcd.c bn_prime.c bn_sqr.c \
|
||||
bn_recp.c bn_mont.c bn_mpi.c bn_exp2.c bn_gf2m.c bn_nist.c \
|
||||
bn_intern.c bn_dh.c bn_rsa_fips186_5.c bn_const.c
|
||||
# bnw_*.c is a growing collection of files with routines that operate on
|
||||
# BN_ULONG only. They were helper routines dispersed in bn_*.c, and are
|
||||
# often routines that don't have an assembler implementation, and therefore
|
||||
# didn't fit into bn_asm.c.
|
||||
$COMMON_BNW=bnw_sub.c bnw_mul.c
|
||||
$COMMON=$COMMON_BN $COMMON_BNW
|
||||
|
||||
SOURCE[../../libcrypto]=$COMMON $BNASM bn_print.c bn_err.c bn_srp.c
|
||||
DEFINE[../../libcrypto]=$BNDEF
|
||||
IF[{- !$disabled{'deprecated-0.9.8'} -}]
|
||||
|
||||
@@ -4,7 +4,7 @@ SUBDIRS=objects buffer bio stack lhash hashtable rand evp asn1 pem x509 conf \
|
||||
txt_db pkcs7 pkcs12 ui kdf store property \
|
||||
md2 md4 md5 sha mdc2 ml_kem hmac ripemd whrlpool poly1305 \
|
||||
siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \
|
||||
seed sm4 chacha modes fn bn ec rsa dsa dh sm2 dso \
|
||||
seed sm4 chacha modes bn ec rsa dsa dh sm2 dso \
|
||||
err comp http ocsp cms ts srp cmac ct async ess crmf cmp encode_decode \
|
||||
ffc hpke thread lms ml_dsa slh_dsa
|
||||
|
||||
@@ -100,8 +100,7 @@ $UTIL_COMMON=\
|
||||
threads_pthread.c threads_win.c threads_none.c threads_common.c \
|
||||
initthread.c context.c sparse_array.c asn1_dsa.c packet.c \
|
||||
param_build.c param_build_set.c der_writer.c threads_lib.c \
|
||||
params_dup.c time.c array_alloc.c aligned_alloc.c deterministic_nonce.c \
|
||||
int.c
|
||||
params_dup.c time.c array_alloc.c aligned_alloc.c deterministic_nonce.c
|
||||
|
||||
SOURCE[../libcrypto]=$UTIL_COMMON \
|
||||
mem.c mem_sec.c \
|
||||
|
||||
@@ -327,21 +327,31 @@ static int check_cert_path(const OSSL_CMP_CTX *ctx, X509_STORE *store,
|
||||
/*
|
||||
* Exceptional handling for 3GPP TS 33.310 [3G/LTE Network Domain Security
|
||||
* (NDS); Authentication Framework (AF)], only to use for IP messages
|
||||
* and if the ctx option is explicitly set: use self-issued certificates
|
||||
* from extraCerts as trust anchor to validate sender cert -
|
||||
* provided it also can validate the newly enrolled certificate
|
||||
* and if the ctx option is explicitly set: use self-issued certificates from
|
||||
* extraCerts as trust anchors when validating the CMP message protection cert
|
||||
* in this and any subsequent responses from the server in the same transaction,
|
||||
* but only if these extraCerts can also be used as trust anchors for validating
|
||||
* the newly enrolled certificate received in the IP message.
|
||||
*/
|
||||
static int check_cert_path_3gpp(const OSSL_CMP_CTX *ctx,
|
||||
const OSSL_CMP_MSG *msg, X509 *scrt)
|
||||
{
|
||||
int valid = 0;
|
||||
X509_STORE *store;
|
||||
STACK_OF(X509) *extraCerts;
|
||||
|
||||
if (!ctx->permitTAInExtraCertsForIR)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Initially, use extraCerts from the IP message.
|
||||
* For subsequent msgs (pollRep or PKIConf) in the same transaction,
|
||||
* use extraCertsIn remembered from earlier message (typically, the IP message).
|
||||
* The extraCertsIn field will be cleared by OSSL_CMP_CTX_reinit().
|
||||
*/
|
||||
extraCerts = ctx->extraCertsIn == NULL ? msg->extraCerts : ctx->extraCertsIn;
|
||||
if ((store = X509_STORE_new()) == NULL
|
||||
|| !ossl_cmp_X509_STORE_add1_certs(store, msg->extraCerts,
|
||||
|| !ossl_cmp_X509_STORE_add1_certs(store, extraCerts,
|
||||
1 /* self-issued only */))
|
||||
goto err;
|
||||
|
||||
@@ -554,10 +564,11 @@ end:
|
||||
* (in this order) and is path is validated against ctx->trusted.
|
||||
* On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert().
|
||||
*
|
||||
* If ctx->permitTAInExtraCertsForIR is true and when validating a CMP IP msg,
|
||||
* the trust anchor for validating the IP msg may be taken from msg->extraCerts
|
||||
* if a self-issued certificate is found there that can be used to
|
||||
* validate the enrolled certificate returned in the IP.
|
||||
* If ctx->permitTAInExtraCertsForIR is true, when validating a CMP IP message,
|
||||
* trust anchors for validating the IP message (and any subsequent responses
|
||||
* by the server in the same transaction) may be taken from msg->extraCerts
|
||||
* if self-issued certificates are found there that can also be used
|
||||
* to validate the newly enrolled certificate returned in the IP msg.
|
||||
* This is according to the need given in 3GPP TS 33.310.
|
||||
*
|
||||
* Returns 1 on success, 0 on error or validation failed.
|
||||
|
||||
@@ -547,6 +547,13 @@ OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *libctx)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int OSSL_LIB_CTX_freeze(OSSL_LIB_CTX *ctx, const char *propq)
|
||||
{
|
||||
if ((ctx = ossl_lib_ctx_get_concrete(ctx)) == NULL)
|
||||
return 0;
|
||||
return ossl_method_store_freeze(ctx->evp_method_store, propq);
|
||||
}
|
||||
|
||||
void ossl_release_default_drbg_ctx(void)
|
||||
{
|
||||
/* early release of the DRBG in global default libctx */
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "crypto/cryptoerr.h"
|
||||
#include "crypto/asn1err.h"
|
||||
#include "crypto/bnerr.h"
|
||||
#include "crypto/fnerr.h"
|
||||
#include "crypto/ecerr.h"
|
||||
#include "crypto/buffererr.h"
|
||||
#include "crypto/bioerr.h"
|
||||
@@ -51,7 +50,6 @@ int ossl_err_load_crypto_strings(void)
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|| ossl_err_load_ERR_strings() == 0 /* include error strings for SYSerr */
|
||||
|| ossl_err_load_BN_strings() == 0
|
||||
|| ossl_err_load_OSSL_FN_strings() == 0
|
||||
|| ossl_err_load_RSA_strings() == 0
|
||||
#ifndef OPENSSL_NO_DH
|
||||
|| ossl_err_load_DH_strings() == 0
|
||||
|
||||
@@ -43,7 +43,6 @@ L PROV include/openssl/proverr.h providers/common/provider_err.c
|
||||
L OSSL_ENCODER include/openssl/encodererr.h crypto/encode_decode/encoder_err.c include/crypto/encodererr.h
|
||||
L OSSL_DECODER include/openssl/decodererr.h crypto/encode_decode/decoder_err.c include/crypto/decodererr.h
|
||||
L HTTP include/openssl/httperr.h crypto/http/http_err.c include/crypto/httperr.h
|
||||
L OSSL_FN NONE crypto/fn/fn_err.c include/crypto/fnerr.h
|
||||
|
||||
# SSL/TLS alerts
|
||||
R SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
|
||||
|
||||
@@ -884,7 +884,6 @@ OSSL_DECODER_R_MISSING_GET_PARAMS:100:missing get params
|
||||
OSSL_ENCODER_R_ENCODER_NOT_FOUND:101:encoder not found
|
||||
OSSL_ENCODER_R_INCORRECT_PROPERTY_QUERY:100:incorrect property query
|
||||
OSSL_ENCODER_R_MISSING_GET_PARAMS:102:missing get params
|
||||
OSSL_FN_R_RESULT_ARG_TOO_SMALL:100:result arg too small
|
||||
OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE:107:ambiguous content type
|
||||
OSSL_STORE_R_BAD_PASSWORD_READ:115:bad password read
|
||||
OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC:113:error verifying pkcs12 mac
|
||||
|
||||
@@ -1078,7 +1078,13 @@ static void evp_md_free(void *md)
|
||||
EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
|
||||
const char *properties)
|
||||
{
|
||||
EVP_MD *md = evp_generic_fetch(ctx, OSSL_OP_DIGEST, algorithm, properties,
|
||||
EVP_MD *md = NULL;
|
||||
|
||||
if (evp_generic_fetch_frozen(ctx, OSSL_OP_DIGEST, algorithm, properties,
|
||||
NULL, (void **)&md))
|
||||
return md;
|
||||
|
||||
md = evp_generic_fetch(ctx, OSSL_OP_DIGEST, algorithm, properties,
|
||||
evp_md_from_algorithm, evp_md_up_ref, evp_md_free);
|
||||
|
||||
return md;
|
||||
|
||||
@@ -388,6 +388,77 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata,
|
||||
return method;
|
||||
}
|
||||
|
||||
/* TODO: FREEZE: Replace with actual implementation */
|
||||
/*
|
||||
* Returns 1 if method store is frozen AND prop query is equal to frozen prop
|
||||
* query. Only sets METHOD if found.
|
||||
*/
|
||||
int evp_generic_fetch_frozen(OSSL_LIB_CTX *libctx, int operation_id,
|
||||
const char *name, const char *properties,
|
||||
OSSL_PROVIDER *prov, void **method)
|
||||
{
|
||||
OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
|
||||
const char *store_propq;
|
||||
OSSL_NAMEMAP *namemap;
|
||||
uint32_t meth_id;
|
||||
#ifdef FIPS_MODULE
|
||||
/*
|
||||
* The FIPS provider has its own internal library context where only it
|
||||
* is loaded. Consequently, property queries aren't relevant because
|
||||
* there is only one fetchable algorithm and it is assumed that the
|
||||
* FIPS-ness is handled by the using algorithm.
|
||||
*/
|
||||
const char *const propq = "";
|
||||
#else
|
||||
const char *const propq = properties != NULL ? properties : "";
|
||||
#endif /* FIPS_MODULE */
|
||||
|
||||
if (store == NULL) {
|
||||
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's ever an operation_id == 0 passed, we have an internal
|
||||
* programming error.
|
||||
*/
|
||||
if (!ossl_assert(operation_id > 0)) {
|
||||
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return 0 if not frozen or prop query is different than frozen prop query */
|
||||
if (!ossl_method_store_is_frozen(store))
|
||||
return 0;
|
||||
if (strlen(propq) != 0
|
||||
&& (store_propq = ossl_method_store_frozen_propq(store)) != NULL
|
||||
&& strcmp(propq, store_propq) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If we haven't received a name id yet, try to get one for the name */
|
||||
namemap = ossl_namemap_stored(libctx);
|
||||
if (namemap == NULL) {
|
||||
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
meth_id = name != NULL ? ossl_namemap_name2num(namemap, name) : 0;
|
||||
|
||||
/*
|
||||
* If we have a name id, calculate a method id with evp_method_id().
|
||||
*
|
||||
* evp_method_id returns 0 if we have too many operations (more than
|
||||
* about 2^8) or too many names (more than about 2^24).
|
||||
* For all intents and purposes, this is an internal error.
|
||||
*/
|
||||
if (meth_id != 0 && (meth_id = evp_method_id(meth_id, operation_id)) == 0) {
|
||||
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ossl_frozen_method_store_cache_get(store, prov, meth_id, propq, method);
|
||||
}
|
||||
|
||||
void *evp_generic_fetch(OSSL_LIB_CTX *libctx, int operation_id,
|
||||
const char *name, const char *properties,
|
||||
void *(*new_method)(int name_id,
|
||||
|
||||
@@ -302,6 +302,9 @@ void *evp_generic_fetch(OSSL_LIB_CTX *ctx, int operation_id,
|
||||
OSSL_PROVIDER *prov),
|
||||
int (*up_ref_method)(void *),
|
||||
void (*free_method)(void *));
|
||||
int evp_generic_fetch_frozen(OSSL_LIB_CTX *libctx, int operation_id,
|
||||
const char *name, const char *properties,
|
||||
OSSL_PROVIDER *prov, void **method);
|
||||
void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id,
|
||||
const char *name, const char *properties,
|
||||
void *(*new_method)(int name_id,
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
$LIBCRYPTO=../../libcrypto
|
||||
$LIBFIPS=../../providers/libfips.a
|
||||
LIBS=$LIBCRYPTO
|
||||
|
||||
$COMMON=fn_err.c fn_lib.c fn_ctx.c fn_intern.c fn_addsub.c fn_mul.c
|
||||
|
||||
SOURCE[$LIBCRYPTO]=$COMMON
|
||||
SOURCE[$LIBFIPS]=$COMMON
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
#include "crypto/fnerr.h"
|
||||
#include "../bn/bn_local.h" /* For using the low level bignum functions */
|
||||
#include "fn_local.h"
|
||||
|
||||
/* add of b to a. */
|
||||
/* unsigned add of b to a, r can be equal to a or b. */
|
||||
int OSSL_FN_add(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b)
|
||||
{
|
||||
/*
|
||||
* Addition is commutative, so we switch 'a' and 'b' around to
|
||||
* ensure that 'a' is physically the largest, so a maximum of
|
||||
* work is done with 'bn_add_words'
|
||||
*/
|
||||
if (a->dsize < b->dsize) {
|
||||
const OSSL_FN *tmp;
|
||||
|
||||
tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
/* At this point, we know that a->dsize >= b->dsize */
|
||||
size_t max = a->dsize;
|
||||
size_t min = b->dsize;
|
||||
size_t rs = r->dsize;
|
||||
const OSSL_FN_ULONG *ap = a->d;
|
||||
const OSSL_FN_ULONG *bp = b->d;
|
||||
OSSL_FN_ULONG *rp = r->d;
|
||||
|
||||
/*
|
||||
* Three stages, after which there's a possible return.
|
||||
* Each stage is limited by the number of remaining limbs
|
||||
* in |r|.
|
||||
*
|
||||
* For each stage, |stage_limbs| is used to hold the number
|
||||
* of limbs being treated in that stage, and |borrow| is
|
||||
* used to transport the borrow from one stage to the other.
|
||||
*/
|
||||
size_t stage_limbs;
|
||||
OSSL_FN_ULONG carry;
|
||||
|
||||
/* Stage 1 */
|
||||
|
||||
stage_limbs = (min > rs) ? rs : min;
|
||||
carry = bn_add_words(rp, ap, bp, (int)stage_limbs);
|
||||
if (stage_limbs == rs)
|
||||
return 1;
|
||||
|
||||
/* At this point, we know that |min| limbs have been used so far */
|
||||
rp += min;
|
||||
ap += min;
|
||||
|
||||
/* Stage 2 */
|
||||
|
||||
stage_limbs = ((max > rs) ? rs : max) - min;
|
||||
|
||||
for (size_t dif = stage_limbs; dif > 0; dif--, ap++, rp++) {
|
||||
OSSL_FN_ULONG t1 = *ap;
|
||||
OSSL_FN_ULONG t2 = (t1 + carry) & OSSL_FN_MASK;
|
||||
|
||||
*rp = t2;
|
||||
carry &= (t2 == 0);
|
||||
}
|
||||
if (stage_limbs == rs)
|
||||
return 1;
|
||||
|
||||
/* Stage 3 */
|
||||
|
||||
/* We know that |max| limbs have been used */
|
||||
stage_limbs = rs - max;
|
||||
|
||||
for (size_t dif = stage_limbs; dif > 0; dif--, rp++) {
|
||||
OSSL_FN_ULONG t1 = 0;
|
||||
OSSL_FN_ULONG t2 = (t1 + carry) & OSSL_FN_MASK;
|
||||
|
||||
*rp = carry;
|
||||
carry &= (t2 == 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* unsigned subtraction of b from a */
|
||||
int OSSL_FN_sub(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b)
|
||||
{
|
||||
size_t max = (a->dsize >= b->dsize) ? a->dsize : b->dsize;
|
||||
size_t min = (a->dsize <= b->dsize) ? a->dsize : b->dsize;
|
||||
size_t rs = r->dsize;
|
||||
const OSSL_FN_ULONG *ap = a->d;
|
||||
const OSSL_FN_ULONG *bp = b->d;
|
||||
OSSL_FN_ULONG *rp = r->d;
|
||||
|
||||
/*
|
||||
* Three stages, after which there's a possible return.
|
||||
* Each stage is limited by the number of remaining limbs
|
||||
* in |r|.
|
||||
*
|
||||
* For each stage, |stage_limbs| is used to hold the number
|
||||
* of limbs being treated in that stage, and |borrow| is
|
||||
* used to transport the borrow from one stage to the other.
|
||||
*/
|
||||
size_t stage_limbs;
|
||||
OSSL_FN_ULONG borrow;
|
||||
|
||||
/* Stage 1 */
|
||||
|
||||
stage_limbs = (min > rs) ? rs : min;
|
||||
borrow = bn_sub_words(rp, ap, bp, (int)stage_limbs);
|
||||
if (stage_limbs == rs)
|
||||
return 1;
|
||||
|
||||
/* At this point, we know that |min| limbs have been used so far */
|
||||
ap += min;
|
||||
bp += min;
|
||||
rp += min;
|
||||
|
||||
/* Stage 2 */
|
||||
|
||||
const OSSL_FN_ULONG *maxp = (a->dsize >= b->dsize) ? ap : bp;
|
||||
const OSSL_FN_ULONG s2_mask1 = (a->dsize >= b->dsize) ? OSSL_FN_MASK : 0;
|
||||
const OSSL_FN_ULONG s2_mask2 = ~s2_mask1;
|
||||
|
||||
stage_limbs = ((max > rs) ? rs : max) - min;
|
||||
|
||||
/* calculate the result of borrowing from more significant limbs */
|
||||
for (size_t dif = stage_limbs; dif > 0; dif--, maxp++, rp++) {
|
||||
OSSL_FN_ULONG t1 = (*maxp & s2_mask1);
|
||||
OSSL_FN_ULONG t2 = (*maxp & s2_mask2);
|
||||
OSSL_FN_ULONG t3 = (t1 - t2 - borrow) & OSSL_FN_MASK;
|
||||
|
||||
*rp = t3;
|
||||
borrow &= (t1 <= t2);
|
||||
}
|
||||
if (stage_limbs == rs)
|
||||
return 1;
|
||||
|
||||
/* Stage 3 */
|
||||
|
||||
/* We know that |max| limbs have been used */
|
||||
stage_limbs = rs - max;
|
||||
|
||||
/* Finally, fill in the rest of the result array by borrowing from zeros */
|
||||
for (size_t dif = stage_limbs; dif > 0; dif--, rp++) {
|
||||
OSSL_FN_ULONG t1 = 0;
|
||||
OSSL_FN_ULONG t2 = (t1 - borrow) & OSSL_FN_MASK;
|
||||
|
||||
*rp = t2;
|
||||
borrow &= (t1 == 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include "crypto/fn.h"
|
||||
#include "fn_local.h"
|
||||
|
||||
/*
|
||||
* An OSSL_FN_CTX is a large pre-allocated chunk of memory that can be used
|
||||
* to quickly allocate OSSL_FN instances. The organization of memory is as
|
||||
* a fairly typical arena, where OSSL_FN instances are "stacked" one after
|
||||
* the other.
|
||||
*
|
||||
* However, there is also the concept of frames, which are arenas within an
|
||||
* arena. This allows easily passing an OSSL_FN_CTX to a function, and for
|
||||
* that function to allocate such a frame for itself, and easily deallocate
|
||||
* it when it's done.
|
||||
*/
|
||||
|
||||
struct ossl_fn_ctx_st {
|
||||
/*
|
||||
* Pointer to the last OSSL_FN_CTX_start() location (a simple pointer into
|
||||
* the memory area). See the struct ossl_fn_ctx_frame_st definition below
|
||||
* for details.
|
||||
*/
|
||||
struct ossl_fn_ctx_frame_st *last_frame;
|
||||
|
||||
/*
|
||||
* Flags
|
||||
*/
|
||||
unsigned int is_securely_allocated : 1;
|
||||
|
||||
/*
|
||||
* The arena itself.
|
||||
*/
|
||||
size_t msize; /* Size of the arena, in bytes */
|
||||
unsigned char memory[];
|
||||
};
|
||||
|
||||
struct ossl_fn_ctx_frame_st {
|
||||
/*
|
||||
* Pointer back to the whole arena where the frame is located,
|
||||
* for |last_frame| bookkeeping.
|
||||
*/
|
||||
struct ossl_fn_ctx_st *arena;
|
||||
/*
|
||||
* Pointer to the previous frame in the arena, allowing OSSL_FN_CTX_end()
|
||||
* to do its job.
|
||||
*/
|
||||
struct ossl_fn_ctx_frame_st *previous_frame;
|
||||
/*
|
||||
* Every time OSSL_FN_CTX_get() is called, the current value of
|
||||
* |free_memory| is returned, and it's updated by incrementing it
|
||||
* by the number of bytes given by OSSL_FN_CTX_get().
|
||||
* The available number of bytes is limited by what's left in the arena.
|
||||
*/
|
||||
unsigned char *free_memory; /* Pointer to the free area of the frame */
|
||||
size_t msize; /* Size of the frame, in bytes */
|
||||
unsigned char memory[];
|
||||
};
|
||||
|
||||
static size_t calculate_arena_size(size_t max_n_frames, size_t max_n_numbers, size_t max_n_limbs)
|
||||
{
|
||||
return max_n_frames * sizeof(struct ossl_fn_ctx_frame_st)
|
||||
+ max_n_numbers * sizeof(OSSL_FN)
|
||||
+ max_n_limbs * OSSL_FN_BYTES;
|
||||
}
|
||||
|
||||
OSSL_FN_CTX *OSSL_FN_CTX_new(OSSL_LIB_CTX *libctx, size_t max_n_frames,
|
||||
size_t max_n_numbers, size_t max_n_limbs)
|
||||
{
|
||||
size_t arena_size = calculate_arena_size(max_n_frames, max_n_numbers, max_n_limbs);
|
||||
OSSL_FN_CTX *ctx = OPENSSL_zalloc(sizeof(OSSL_FN_CTX) + arena_size);
|
||||
|
||||
if (ctx != NULL)
|
||||
ctx->msize = arena_size;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
OSSL_FN_CTX *OSSL_FN_CTX_secure_new(OSSL_LIB_CTX *libctx, size_t max_n_frames,
|
||||
size_t max_n_numbers, size_t max_n_limbs)
|
||||
{
|
||||
size_t arena_size = calculate_arena_size(max_n_frames, max_n_numbers, max_n_limbs);
|
||||
OSSL_FN_CTX *ctx = OPENSSL_secure_zalloc(sizeof(OSSL_FN_CTX) + arena_size);
|
||||
|
||||
if (ctx != NULL) {
|
||||
ctx->msize = arena_size;
|
||||
ctx->is_securely_allocated = 1;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void OSSL_FN_CTX_free(OSSL_FN_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
|
||||
assert(ctx->last_frame == NULL);
|
||||
|
||||
if (ctx->is_securely_allocated)
|
||||
OPENSSL_secure_free(ctx);
|
||||
else
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
int OSSL_FN_CTX_start(OSSL_FN_CTX *ctx)
|
||||
{
|
||||
if (!ossl_assert(ctx != NULL))
|
||||
return 0;
|
||||
|
||||
struct ossl_fn_ctx_frame_st *last_frame = ctx->last_frame;
|
||||
size_t used = (last_frame == NULL) ? 0 : last_frame->free_memory - ctx->memory;
|
||||
|
||||
if (ctx->msize - used < sizeof(struct ossl_fn_ctx_frame_st))
|
||||
return 0;
|
||||
|
||||
if (ctx->last_frame == NULL)
|
||||
ctx->last_frame = (struct ossl_fn_ctx_frame_st *)ctx->memory;
|
||||
else
|
||||
ctx->last_frame = (struct ossl_fn_ctx_frame_st *)last_frame->free_memory;
|
||||
|
||||
struct ossl_fn_ctx_frame_st *frame = ctx->last_frame;
|
||||
frame->arena = ctx;
|
||||
frame->previous_frame = last_frame;
|
||||
frame->free_memory = frame->memory;
|
||||
frame->msize = ctx->msize - used - sizeof(*frame);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int OSSL_FN_CTX_end(OSSL_FN_CTX *ctx)
|
||||
{
|
||||
if (!ossl_assert(ctx != NULL))
|
||||
return 0;
|
||||
|
||||
struct ossl_fn_ctx_frame_st *last_frame = ctx->last_frame;
|
||||
|
||||
ctx->last_frame = last_frame->previous_frame;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
OSSL_FN *OSSL_FN_CTX_get_limbs(OSSL_FN_CTX *ctx, size_t limbs)
|
||||
{
|
||||
if (!ossl_assert(ctx != NULL))
|
||||
return NULL;
|
||||
|
||||
struct ossl_fn_ctx_frame_st *frame = ctx->last_frame;
|
||||
|
||||
if (!ossl_assert(frame != NULL))
|
||||
return NULL;
|
||||
|
||||
size_t totalsize = ossl_fn_totalsize(limbs);
|
||||
size_t used = frame->free_memory - frame->memory;
|
||||
if (totalsize == 0 || frame->msize - used < totalsize)
|
||||
return NULL;
|
||||
|
||||
OSSL_FN *fn = (OSSL_FN *)frame->free_memory;
|
||||
frame->free_memory += totalsize;
|
||||
|
||||
memset(fn, 0, totalsize);
|
||||
fn->dsize = (int)limbs;
|
||||
fn->is_securely_allocated = ctx->is_securely_allocated;
|
||||
fn->is_dynamically_allocated = 1;
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
OSSL_FN *OSSL_FN_CTX_get_bytes(OSSL_FN_CTX *ctx, size_t bytes)
|
||||
{
|
||||
return OSSL_FN_CTX_get_limbs(ctx, ossl_fn_bytes_to_limbs(bytes));
|
||||
}
|
||||
|
||||
OSSL_FN *OSSL_FN_CTX_get_bits(OSSL_FN_CTX *ctx, size_t bits)
|
||||
{
|
||||
return OSSL_FN_CTX_get_bytes(ctx, ossl_fn_bits_to_bytes(bits));
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include "crypto/fnerr.h"
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static const ERR_STRING_DATA OSSL_FN_str_reasons[] = {
|
||||
{ ERR_PACK(ERR_LIB_OSSL_FN, 0, OSSL_FN_R_RESULT_ARG_TOO_SMALL),
|
||||
"result arg too small" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
int ossl_err_load_OSSL_FN_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
if (ERR_reason_error_string(OSSL_FN_str_reasons[0].error) == NULL)
|
||||
ERR_load_strings_const(OSSL_FN_str_reasons);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
#include "crypto/fn_intern.h"
|
||||
#include "crypto/fnerr.h"
|
||||
#include "fn_local.h"
|
||||
#include <openssl/err.h>
|
||||
|
||||
int ossl_fn_set_words(OSSL_FN *f, const OSSL_FN_ULONG *words, size_t limbs)
|
||||
{
|
||||
if (ossl_unlikely(f == NULL)) {
|
||||
ERR_raise(ERR_LIB_OSSL_FN, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((size_t)f->dsize < limbs) {
|
||||
ERR_raise(ERR_LIB_OSSL_FN, OSSL_FN_R_RESULT_ARG_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(f->d, words, sizeof(OSSL_FN_ULONG) * limbs);
|
||||
memset(f->d + limbs, 0, sizeof(OSSL_FN_ULONG) * (f->dsize - limbs));
|
||||
return 1;
|
||||
}
|
||||
|
||||
const OSSL_FN_ULONG *ossl_fn_get_words(const OSSL_FN *f)
|
||||
{
|
||||
if (ossl_unlikely(f == NULL)) {
|
||||
ERR_raise(ERR_LIB_OSSL_FN, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return f->d;
|
||||
}
|
||||
|
||||
size_t ossl_fn_get_dsize(const OSSL_FN *f)
|
||||
{
|
||||
return f->dsize;
|
||||
}
|
||||
|
||||
bool ossl_fn_is_dynamically_allocated(const OSSL_FN *f)
|
||||
{
|
||||
return f->is_dynamically_allocated;
|
||||
}
|
||||
|
||||
bool ossl_fn_is_securely_allocated(const OSSL_FN *f)
|
||||
{
|
||||
return f->is_securely_allocated;
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <limits.h>
|
||||
#include <openssl/opensslconf.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include "internal/common.h"
|
||||
#include "crypto/fnerr.h"
|
||||
#include "fn_local.h"
|
||||
|
||||
static OSSL_FN *ossl_fn_new_internal(size_t limbs, bool securely)
|
||||
{
|
||||
/* Total size of the whole OSSL_FN, in bytes */
|
||||
size_t totalsize = ossl_fn_totalsize(limbs);
|
||||
if (totalsize == 0)
|
||||
return NULL;
|
||||
|
||||
OSSL_FN *ret = NULL;
|
||||
|
||||
if (securely)
|
||||
ret = OPENSSL_secure_zalloc(totalsize);
|
||||
else
|
||||
ret = OPENSSL_zalloc(totalsize);
|
||||
|
||||
if (ret != NULL) {
|
||||
ret->dsize = (int)limbs;
|
||||
ret->is_dynamically_allocated = 1;
|
||||
ret->is_securely_allocated = securely;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ossl_fn_free_internal(OSSL_FN *f, bool clear)
|
||||
{
|
||||
if (f == NULL)
|
||||
return;
|
||||
|
||||
size_t limbssize = f->dsize * sizeof(OSSL_FN_ULONG);
|
||||
size_t totalsize = limbssize + sizeof(OSSL_FN);
|
||||
|
||||
if (f->is_dynamically_allocated) {
|
||||
if (f->is_securely_allocated)
|
||||
OPENSSL_secure_clear_free(f, totalsize);
|
||||
else if (clear)
|
||||
OPENSSL_clear_free(f, totalsize);
|
||||
else
|
||||
OPENSSL_free(f);
|
||||
} else if (clear) {
|
||||
OPENSSL_cleanse(f->d, limbssize);
|
||||
}
|
||||
}
|
||||
|
||||
OSSL_FN *OSSL_FN_new_limbs(size_t size)
|
||||
{
|
||||
return ossl_fn_new_internal(size, false);
|
||||
}
|
||||
|
||||
OSSL_FN *OSSL_FN_secure_new_limbs(size_t size)
|
||||
{
|
||||
return ossl_fn_new_internal(size, true);
|
||||
}
|
||||
|
||||
OSSL_FN *OSSL_FN_new_bytes(size_t size)
|
||||
{
|
||||
return OSSL_FN_new_limbs(ossl_fn_bytes_to_limbs(size));
|
||||
}
|
||||
|
||||
OSSL_FN *OSSL_FN_secure_new_bytes(size_t size)
|
||||
{
|
||||
return OSSL_FN_secure_new_limbs(ossl_fn_bytes_to_limbs(size));
|
||||
}
|
||||
|
||||
OSSL_FN *OSSL_FN_new_bits(size_t size)
|
||||
{
|
||||
return OSSL_FN_new_bytes(ossl_fn_bits_to_bytes(size));
|
||||
}
|
||||
|
||||
OSSL_FN *OSSL_FN_secure_new_bits(size_t size)
|
||||
{
|
||||
return OSSL_FN_secure_new_bytes(ossl_fn_bits_to_bytes(size));
|
||||
}
|
||||
|
||||
void OSSL_FN_free(OSSL_FN *f)
|
||||
{
|
||||
ossl_fn_free_internal(f, false);
|
||||
}
|
||||
|
||||
void OSSL_FN_clear_free(OSSL_FN *f)
|
||||
{
|
||||
ossl_fn_free_internal(f, true);
|
||||
}
|
||||
|
||||
void OSSL_FN_clear(OSSL_FN *f)
|
||||
{
|
||||
size_t limbssize = f->dsize * sizeof(OSSL_FN_ULONG);
|
||||
|
||||
OPENSSL_cleanse(f->d, limbssize);
|
||||
}
|
||||
|
||||
OSSL_FN *OSSL_FN_copy(OSSL_FN *a, const OSSL_FN *b)
|
||||
{
|
||||
if (ossl_unlikely(a == b))
|
||||
return a;
|
||||
|
||||
size_t al = a->dsize;
|
||||
size_t bl = b->dsize;
|
||||
|
||||
if (al < bl) {
|
||||
ERR_raise_data(ERR_LIB_OSSL_FN, OSSL_FN_R_RESULT_ARG_TOO_SMALL,
|
||||
"Needs to be at least %d, but is only %d",
|
||||
bl, al);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t t = ossl_fn_totalsize(bl);
|
||||
|
||||
memcpy(a, b, t);
|
||||
a->dsize = (int)al; /* Restore to its original size */
|
||||
memset(&a->d[a->dsize], 0, sizeof(OSSL_FN_ULONG) * (a->dsize - b->dsize));
|
||||
return a;
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
#ifndef OSSL_CRYPTO_FN_LOCAL_H
|
||||
#define OSSL_CRYPTO_FN_LOCAL_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <openssl/opensslconf.h>
|
||||
#include <openssl/e_os2.h>
|
||||
#include "internal/common.h"
|
||||
#include "crypto/fn.h"
|
||||
#include "crypto/fn_intern.h"
|
||||
|
||||
#if OSSL_FN_BYTES == 4
|
||||
/* 32-bit systems */
|
||||
#define OSSL_FN_MASK UINT32_MAX
|
||||
#elif OSSL_FN_BYTES == 8
|
||||
/* 64-bit systems */
|
||||
#define OSSL_FN_MASK UINT64_MAX
|
||||
#else
|
||||
#error "OpenSSL doesn't support large numbers on this platform"
|
||||
#endif
|
||||
|
||||
#define OSSL_FN_HIGH_BIT_MASK (OSSL_FN_ULONG_C(1) << (OSSL_FN_BYTES * 8 - 1))
|
||||
|
||||
#if OSSL_FN_BYTES == 4
|
||||
/* 32-bit systems */
|
||||
#define OSSL_FN_ULONG_C(n) UINT32_C(n)
|
||||
#define OSSL_FN_MASK UINT32_MAX
|
||||
#elif OSSL_FN_BYTES == 8
|
||||
#define OSSL_FN_ULONG_C(n) UINT64_C(n)
|
||||
#define OSSL_FN_MASK UINT64_MAX
|
||||
#else
|
||||
#error "OpenSSL doesn't support large numbers on this platform"
|
||||
#endif
|
||||
|
||||
#define OSSL_FN_HIGH_BIT_MASK (OSSL_FN_ULONG_C(1) << (OSSL_FN_BYTES * 8 - 1))
|
||||
|
||||
struct ossl_fn_st {
|
||||
/* Flag: alloced with OSSL_FN_new() or OSSL_FN_secure_new() */
|
||||
unsigned int is_dynamically_allocated : 1;
|
||||
/* Flag: alloced with OSSL_FN_secure_new() */
|
||||
unsigned int is_securely_allocated : 1;
|
||||
|
||||
/*
|
||||
* The d array, with its size in number of OSSL_FN_ULONG.
|
||||
* This stores the number itself.
|
||||
*
|
||||
* Note: |dsize| is an int, because it turns out that some lower level
|
||||
* (possibly assembler) functions expect that type (especially, that
|
||||
* type size).
|
||||
* This deviates from the design in doc/designs/fixed-size-large-numbers.md
|
||||
*/
|
||||
int dsize;
|
||||
OSSL_FN_ULONG d[];
|
||||
};
|
||||
|
||||
static ossl_inline size_t ossl_fn_totalsize(size_t limbs)
|
||||
{
|
||||
/*
|
||||
* TODO(FIXNUM): Since the number of limbs is currently represented
|
||||
* as an 'int' in OSSL_FN, we must ensure that the desired size isn't
|
||||
* larger than can be represented.
|
||||
*/
|
||||
if (ossl_unlikely(limbs >= INT_MAX))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* sizeof(OSSL_FN) + limbs * sizeof(OSSL_FN_ULONG) > SIZE_MAX
|
||||
* => limbs * sizeof(OSSL_FN_ULONG) > SIZE_MAX - sizeof(OSSL_FN)
|
||||
* => limbs > (SIZE_MAX - sizeof(OSSL_FN)) / sizeof(OSSL_FN_ULONG)
|
||||
*/
|
||||
if (ossl_unlikely(limbs > (SIZE_MAX - sizeof(OSSL_FN)) / sizeof(OSSL_FN_ULONG)))
|
||||
return 0;
|
||||
return sizeof(OSSL_FN) + limbs * sizeof(OSSL_FN_ULONG);
|
||||
}
|
||||
|
||||
static ossl_inline size_t ossl_fn_bytes_to_limbs(size_t size)
|
||||
{
|
||||
return (size + sizeof(OSSL_FN_ULONG) - 1) / sizeof(OSSL_FN_ULONG);
|
||||
}
|
||||
|
||||
static ossl_inline size_t ossl_fn_bits_to_bytes(size_t size)
|
||||
{
|
||||
return (size + 7) / 8;
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal functions to support BIGNUM's bn_expand_internal, BN_copy, and
|
||||
* similar.
|
||||
* The caller must ensure that src and dest are not NULL.
|
||||
* With ossl_fn_copy_internal, bn_words may be given -1 to signify that the
|
||||
* number of BN_ULONG should be found in src.
|
||||
*/
|
||||
static ossl_inline OSSL_FN *ossl_fn_copy_internal_limbs(OSSL_FN *dest,
|
||||
const OSSL_FN_ULONG *src,
|
||||
int limbs)
|
||||
{
|
||||
if (ossl_unlikely(dest->dsize < limbs))
|
||||
return NULL;
|
||||
memcpy(dest->d, src, limbs * sizeof(dest->d[0]));
|
||||
memset(dest->d + limbs, 0, (dest->dsize - limbs) * sizeof(dest->d[0]));
|
||||
return dest;
|
||||
}
|
||||
|
||||
static ossl_inline OSSL_FN *ossl_fn_copy_internal(OSSL_FN *dest,
|
||||
const OSSL_FN *src,
|
||||
int bn_words)
|
||||
{
|
||||
int words = bn_words < 0 ? src->dsize : bn_words;
|
||||
|
||||
if (ossl_fn_copy_internal_limbs(dest, src->d, words) == NULL)
|
||||
return NULL;
|
||||
return dest;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <openssl/err.h>
|
||||
#include "crypto/cryptlib.h"
|
||||
#include "crypto/fnerr.h"
|
||||
#include "../bn/bn_local.h" /* For using the low level bignum functions */
|
||||
#include "fn_local.h"
|
||||
|
||||
int OSSL_FN_mul(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, OSSL_FN_CTX *ctx)
|
||||
{
|
||||
if (!OSSL_FN_CTX_start(ctx))
|
||||
return 0;
|
||||
|
||||
size_t al = (size_t)a->dsize;
|
||||
size_t bl = (size_t)b->dsize;
|
||||
size_t rl = (size_t)r->dsize;
|
||||
size_t max = (size_t)(al + bl);
|
||||
|
||||
int ret = 0;
|
||||
#ifdef BN_MUL_COMBA
|
||||
if (al == bl) {
|
||||
if (rl >= 16 && al == 8) {
|
||||
bn_mul_comba8(r->d, a->d, b->d);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
#endif /* BN_MUL_COMBA */
|
||||
|
||||
OSSL_FN *rr = r;
|
||||
if ((r == a) || (r == b))
|
||||
if ((rr = OSSL_FN_CTX_get_limbs(ctx, rl)) == NULL)
|
||||
goto err;
|
||||
|
||||
bn_mul_truncated(rr->d, (int)rl, a->d, (int)al, b->d, (int)bl);
|
||||
|
||||
if (rr != r)
|
||||
if (OSSL_FN_copy(r, rr) == NULL)
|
||||
goto err;
|
||||
|
||||
#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
|
||||
end:
|
||||
#endif
|
||||
|
||||
{
|
||||
size_t dif = (rl > max) ? rl - max : 0;
|
||||
OSSL_FN_ULONG *rp = &r->d[max];
|
||||
while (dif > 0) {
|
||||
*rp++ = 0;
|
||||
dif--;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
OSSL_FN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
29
crypto/int.c
29
crypto/int.c
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
#include "crypto/cryptlib.h"
|
||||
|
||||
size_t ossl_num_bits(size_t value)
|
||||
{
|
||||
size_t i;
|
||||
unsigned long ret = 0;
|
||||
|
||||
/*
|
||||
* It is argued that *on average* constant counter loop performs
|
||||
* not worse [if not better] than one with conditional break or
|
||||
* mask-n-table-lookup-style, because of branch misprediction
|
||||
* penalties.
|
||||
*/
|
||||
for (i = 0; i < sizeof(value) * 8; i++) {
|
||||
ret += (value != 0);
|
||||
value >>= 1;
|
||||
}
|
||||
|
||||
return (int)ret;
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "crypto/sparse_array.h"
|
||||
#include "property_local.h"
|
||||
#include "crypto/context.h"
|
||||
#include "crypto/evp.h"
|
||||
|
||||
/*
|
||||
* The number of elements in the query cache before we initiate a flush.
|
||||
@@ -86,6 +87,12 @@ struct ossl_method_store_st {
|
||||
|
||||
/* Flag: 1 if query cache entries for all algs need flushing */
|
||||
int cache_need_flush;
|
||||
|
||||
/* Flag: 1 if method store is frozen */
|
||||
int frozen;
|
||||
|
||||
/* Property query associated with frozen state */
|
||||
char *frozen_propq;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -265,6 +272,7 @@ void ossl_method_store_free(OSSL_METHOD_STORE *store)
|
||||
ossl_sa_ALGORITHM_free(store->algs);
|
||||
CRYPTO_THREAD_lock_free(store->lock);
|
||||
CRYPTO_THREAD_lock_free(store->biglock);
|
||||
OPENSSL_free(store->frozen_propq);
|
||||
OPENSSL_free(store);
|
||||
}
|
||||
}
|
||||
@@ -324,7 +332,7 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov,
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
if (nid <= 0 || method == NULL || store == NULL)
|
||||
if (nid <= 0 || method == NULL || store == NULL || store->frozen == 1)
|
||||
return 0;
|
||||
|
||||
if (properties == NULL)
|
||||
@@ -438,7 +446,7 @@ int ossl_method_store_remove(OSSL_METHOD_STORE *store, int nid,
|
||||
ALGORITHM *alg = NULL;
|
||||
int i;
|
||||
|
||||
if (nid <= 0 || method == NULL || store == NULL)
|
||||
if (nid <= 0 || method == NULL || store == NULL || store->frozen == 1)
|
||||
return 0;
|
||||
|
||||
if (!ossl_property_write_lock(store))
|
||||
@@ -540,7 +548,7 @@ int ossl_method_store_remove_all_provided(OSSL_METHOD_STORE *store,
|
||||
{
|
||||
struct alg_cleanup_by_provider_data_st data;
|
||||
|
||||
if (!ossl_property_write_lock(store))
|
||||
if (store == NULL || store->frozen == 1 || !ossl_property_write_lock(store))
|
||||
return 0;
|
||||
data.prov = prov;
|
||||
data.store = store;
|
||||
@@ -549,6 +557,34 @@ int ossl_method_store_remove_all_provided(OSSL_METHOD_STORE *store,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_method_store_freeze(OSSL_METHOD_STORE *store, const char *propq)
|
||||
{
|
||||
if (store == NULL || store->frozen == 1)
|
||||
return 0;
|
||||
|
||||
if (propq != NULL) {
|
||||
store->frozen_propq = OPENSSL_strdup(propq);
|
||||
if (store->frozen_propq == NULL)
|
||||
return 0;
|
||||
}
|
||||
/* TODO: FREEZE: Create frozen caches */
|
||||
store->frozen = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_method_store_is_frozen(OSSL_METHOD_STORE *store)
|
||||
{
|
||||
return store != NULL && store->frozen == 1;
|
||||
}
|
||||
|
||||
const char *ossl_method_store_frozen_propq(OSSL_METHOD_STORE *store)
|
||||
{
|
||||
if (store == NULL)
|
||||
return NULL;
|
||||
return store->frozen_propq;
|
||||
}
|
||||
|
||||
static void alg_do_one(ALGORITHM *alg, IMPLEMENTATION *impl,
|
||||
void (*fn)(int id, void *method, void *fnarg),
|
||||
void *fnarg)
|
||||
@@ -774,7 +810,7 @@ static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid)
|
||||
|
||||
int ossl_method_store_cache_flush_all(OSSL_METHOD_STORE *store)
|
||||
{
|
||||
if (!ossl_property_write_lock(store))
|
||||
if (store == NULL || store->frozen == 1 || !ossl_property_write_lock(store))
|
||||
return 0;
|
||||
ossl_sa_ALGORITHM_doall(store->algs, &impl_cache_flush_alg);
|
||||
store->cache_nelem = 0;
|
||||
@@ -856,6 +892,11 @@ static void ossl_method_cache_flush_some(OSSL_METHOD_STORE *store)
|
||||
tsan_add(&global_seed, state.seed);
|
||||
}
|
||||
|
||||
/* TODO: FREEZE: Remove these and replace with actual implementation */
|
||||
static EVP_MD andrew_md;
|
||||
static void *andrew_method = NULL;
|
||||
|
||||
/* TODO: FREEZE: Replace with actual implementation */
|
||||
int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
|
||||
int nid, const char *prop_query, void **method)
|
||||
{
|
||||
@@ -886,6 +927,39 @@ err:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* TODO: FREEZE: Replace with actual implementation */
|
||||
int ossl_frozen_method_store_cache_get(OSSL_METHOD_STORE *store,
|
||||
OSSL_PROVIDER *prov, int nid,
|
||||
const char *prop_query, void **method)
|
||||
{
|
||||
/*
|
||||
* Query triplet (nid, prov, prop_query) from frozen store with no fallback.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO: FREEZE: Replace with actual implementation
|
||||
* For now, just store & fetch from global variables
|
||||
*/
|
||||
EVP_MD *temp_method;
|
||||
|
||||
if (andrew_method == NULL) {
|
||||
if (!ossl_method_store_cache_get(store, prov, nid, prop_query, (void **)&temp_method))
|
||||
return 0;
|
||||
|
||||
memcpy(&andrew_md, temp_method, sizeof(andrew_md));
|
||||
andrew_md.origin = EVP_ORIG_FROZEN;
|
||||
andrew_method = &andrew_md;
|
||||
EVP_MD_free(temp_method);
|
||||
}
|
||||
|
||||
if (andrew_method != NULL) {
|
||||
*method = andrew_method;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
|
||||
int nid, const char *prop_query, void *method,
|
||||
int (*method_up_ref)(void *),
|
||||
@@ -896,7 +970,7 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
|
||||
size_t len;
|
||||
int res = 1;
|
||||
|
||||
if (nid <= 0 || store == NULL || prop_query == NULL)
|
||||
if (nid <= 0 || store == NULL || prop_query == NULL || store->frozen == 1)
|
||||
return 0;
|
||||
|
||||
if (!ossl_assert(prov != NULL))
|
||||
|
||||
@@ -693,12 +693,12 @@ static int rsa_keygen(OSSL_LIB_CTX *libctx, RSA *rsa, int bits, int primes,
|
||||
static int rsa_keygen_pairwise_test(RSA *rsa, OSSL_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int plaintxt_len;
|
||||
unsigned char *plaintxt = NULL;
|
||||
unsigned int ciphertxt_len;
|
||||
unsigned char *ciphertxt = NULL;
|
||||
unsigned char *decoded = NULL;
|
||||
unsigned int decoded_len;
|
||||
int plaintxt_len;
|
||||
int ciphertxt_len;
|
||||
int decoded_len;
|
||||
int padding = RSA_NO_PADDING;
|
||||
OSSL_SELF_TEST *st = NULL;
|
||||
|
||||
|
||||
@@ -193,8 +193,7 @@ static int verify_cb_crl(X509_STORE_CTX *ctx, int err)
|
||||
/*
|
||||
* Inform the verify callback of an error, OCSP-specific variant.
|
||||
* It is called also on OCSP response errors, if the
|
||||
* X509_V_FLAG_OCSP_RESP_CHECK or X509_V_FLAG_OCSP_RESP_CHECK_ALL flag
|
||||
* is set.
|
||||
* X509_V_FLAG_OCSP_RESP_CHECK flag is set.
|
||||
* Here, the error depth and certificate are already set, we just specify
|
||||
* the error number.
|
||||
*
|
||||
@@ -1134,10 +1133,10 @@ trusted:
|
||||
static int check_revocation(X509_STORE_CTX *ctx)
|
||||
{
|
||||
int i = 0, last = 0, ok = 0;
|
||||
int crl_check_enabled = (ctx->param->flags & (X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL)) != 0;
|
||||
int crl_check_all_enabled = (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) != 0;
|
||||
int ocsp_check_enabled = (ctx->param->flags & (X509_V_FLAG_OCSP_RESP_CHECK | X509_V_FLAG_OCSP_RESP_CHECK_ALL)) != 0;
|
||||
int ocsp_check_all_enabled = (ctx->param->flags & X509_V_FLAG_OCSP_RESP_CHECK_ALL) != 0;
|
||||
int crl_check_enabled = (ctx->param->flags & X509_V_FLAG_CRL_CHECK) != 0;
|
||||
int crl_check_all_enabled = crl_check_enabled && (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) != 0;
|
||||
int ocsp_check_enabled = (ctx->param->flags & X509_V_FLAG_OCSP_RESP_CHECK) != 0;
|
||||
int ocsp_check_all_enabled = ocsp_check_enabled && (ctx->param->flags & X509_V_FLAG_OCSP_RESP_CHECK_ALL) != 0;
|
||||
|
||||
if (!crl_check_enabled && !ocsp_check_enabled)
|
||||
return 1;
|
||||
|
||||
@@ -1607,6 +1607,10 @@ DEPEND[html/man3/OPENSSL_malloc.html]=man3/OPENSSL_malloc.pod
|
||||
GENERATE[html/man3/OPENSSL_malloc.html]=man3/OPENSSL_malloc.pod
|
||||
DEPEND[man/man3/OPENSSL_malloc.3]=man3/OPENSSL_malloc.pod
|
||||
GENERATE[man/man3/OPENSSL_malloc.3]=man3/OPENSSL_malloc.pod
|
||||
DEPEND[html/man3/OPENSSL_ppccap.html]=man3/OPENSSL_ppccap.pod
|
||||
GENERATE[html/man3/OPENSSL_ppccap.html]=man3/OPENSSL_ppccap.pod
|
||||
DEPEND[man/man3/OPENSSL_ppccap.3]=man3/OPENSSL_ppccap.pod
|
||||
GENERATE[man/man3/OPENSSL_ppccap.3]=man3/OPENSSL_ppccap.pod
|
||||
DEPEND[html/man3/OPENSSL_riscvcap.html]=man3/OPENSSL_riscvcap.pod
|
||||
GENERATE[html/man3/OPENSSL_riscvcap.html]=man3/OPENSSL_riscvcap.pod
|
||||
DEPEND[man/man3/OPENSSL_riscvcap.3]=man3/OPENSSL_riscvcap.pod
|
||||
@@ -3455,6 +3459,7 @@ html/man3/OPENSSL_instrument_bus.html \
|
||||
html/man3/OPENSSL_load_builtin_modules.html \
|
||||
html/man3/OPENSSL_load_u16_le.html \
|
||||
html/man3/OPENSSL_malloc.html \
|
||||
html/man3/OPENSSL_ppccap.html \
|
||||
html/man3/OPENSSL_riscvcap.html \
|
||||
html/man3/OPENSSL_s390xcap.html \
|
||||
html/man3/OPENSSL_secure_malloc.html \
|
||||
@@ -4129,6 +4134,7 @@ man/man3/OPENSSL_instrument_bus.3 \
|
||||
man/man3/OPENSSL_load_builtin_modules.3 \
|
||||
man/man3/OPENSSL_load_u16_le.3 \
|
||||
man/man3/OPENSSL_malloc.3 \
|
||||
man/man3/OPENSSL_ppccap.3 \
|
||||
man/man3/OPENSSL_riscvcap.3 \
|
||||
man/man3/OPENSSL_s390xcap.3 \
|
||||
man/man3/OPENSSL_secure_malloc.3 \
|
||||
|
||||
@@ -1,711 +0,0 @@
|
||||
Fixed size large numbers
|
||||
========================
|
||||
|
||||
*`BIGNUM` redesign for better constant time calculations*
|
||||
---------------------------------------------------------
|
||||
|
||||
<center>
|
||||
<p><h3>Abstract</h3></p>
|
||||
|
||||
<p>
|
||||
In this design, we explore and define how OpenSSL's `BIGNUM` library can
|
||||
be remodelled for constant-size calculations. Furthermore, we explore and
|
||||
define a fixed size large number library, which never changes the in-memory
|
||||
size of a number once it has been allocated. Finally, we define how `BIGNUM`
|
||||
functions with corresponding fixed size large number functions can be remade
|
||||
into wrappers around the latter.
|
||||
</p>
|
||||
|
||||
</center>
|
||||
|
||||
### Table of contents:
|
||||
|
||||
- [Background][]
|
||||
- [Goals][]
|
||||
- [Challenges][]
|
||||
- [Design][]
|
||||
- [The `OSSL_FN` type][]
|
||||
- [The `OSSL_FN_CTX` type][]
|
||||
- [The `OSSL_FN_CTX` type, with frames][]
|
||||
- [The `OSSL_FN_CTX` type, without frames][]
|
||||
- [The `BIGNUM` type][]
|
||||
- [Mutability][]
|
||||
- [Dropping `top` from `BIGNUM`][]
|
||||
- [Memory functionality for `OSSL_FN`][]
|
||||
- [Memory functionality for `OSSL_FN_CTX`][]
|
||||
- [Wrapping an `OSSL_FN` function with a `BIGNUM` function][]
|
||||
- [Failures][]
|
||||
- [Repurposing existing code][]
|
||||
- [How to apply `OSSL_FN`][]
|
||||
- [Where to apply `OSSL_FN`][]
|
||||
- [How to apply `OSSL_FN_CTX`][]
|
||||
- [The variant with frames][]
|
||||
- [The variant without frames][]
|
||||
- [Testing][]
|
||||
- [Appendix][]
|
||||
- [Using the C99 flexible array member feature][]
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
[Background]: #background
|
||||
|
||||
The current internal definition of OpenSSL's `BIGNUM` looks like this:
|
||||
|
||||
```c
|
||||
struct bignum_st {
|
||||
BN_ULONG *d; /*
|
||||
* Pointer to an array of 'BN_BITS2' bit
|
||||
* chunks. These chunks are organised in
|
||||
* a least significant chunk first order.
|
||||
*/
|
||||
int top; /* Index of last used d +1. */
|
||||
/* The next are internal book keeping for bn_expand. */
|
||||
int dmax; /* Size of the d array. */
|
||||
int neg; /* one if the number is negative */
|
||||
int flags;
|
||||
};
|
||||
```
|
||||
|
||||
The fields `d`, `top` and `dmax` allow the numbers to be quite dynamic in
|
||||
terms of its memory footprint, as it can both increase in size[^1] and
|
||||
decrease in size.[^2]
|
||||
|
||||
Furthermore, the result of any `BIGNUM` operation may be the same `BIGNUM`
|
||||
instance as any of the operands, which means that any `BIGNUM` may have its
|
||||
memory footprint adjusted at any time.
|
||||
|
||||
While this is very flexible, it leaves uncertainties about the time any
|
||||
calculation may take, following any earlier calculation, which is a security
|
||||
vulnerability.
|
||||
|
||||
[^1]: the array `d` is reallocated to a larger size and `dmax` as well as top
|
||||
are updated
|
||||
[^2]: `top` is diminished
|
||||
|
||||
Goals
|
||||
=====
|
||||
|
||||
[Goals]: #goals
|
||||
|
||||
Overall goal: Introduce a new type and API that are inherently constant size
|
||||
to replace the existing `BIGNUM` usage.
|
||||
|
||||
The intention is to enhance this one aspect of constant time calculations.
|
||||
Other aspects are considered out of scope for this design.
|
||||
|
||||
The included sub-goals are:
|
||||
|
||||
* To define a new large number type and accompanying API, that doesn't allow
|
||||
size adjustments of the large numbers once their individual size has been
|
||||
established
|
||||
* To define that large number type and API in such a way it's compatible
|
||||
with and can be used by the `BIGNUM` API through easy transition to the
|
||||
new type.
|
||||
* To ensure that the new large number API is constant-size
|
||||
* To repurpose as much as possible of our current `BIGNUM` code for the new
|
||||
large number API, especially our assembler code (with the assumption that
|
||||
everything that doesn't change the `BIGNUM` sizes can be repurposed as is)
|
||||
* To replace the public `BIGNUM` API that has been repurposed as wrappers
|
||||
around the new large number API
|
||||
* To replace all security critical large number calculations so that they
|
||||
are not just constant-size in themselves, but that the whole set of
|
||||
calculations remains constant-size, within OpenSSL code
|
||||
|
||||
Challenges
|
||||
==========
|
||||
|
||||
[Challenges]: #challenges
|
||||
|
||||
The challenges we have are:
|
||||
|
||||
- **`BIGNUM` usage**
|
||||
|
||||
Because `BIGNUM` is a public facing API, it's likely to be used by OpenSSL
|
||||
users. This existing API needs to be backward compatible, but performance
|
||||
isn't necessarily critical.
|
||||
|
||||
- **constant-time through constant-size**
|
||||
|
||||
To make calculation time predictable on a broader scale than on a
|
||||
per-operation basis, there's a need to ensure that each large number being
|
||||
used in the calculations involved has a fixed size, i.e. to avoid the sort
|
||||
of dynamic sizing that the `BIGNUM` functionality does.
|
||||
|
||||
Design
|
||||
======
|
||||
|
||||
[Design]: #design
|
||||
|
||||
The overall design defines a new type, `OSSL_FN` (where FN is short for
|
||||
"FIXNUM"), which can somehow be made compatible with `BIGNUM`, but yet be
|
||||
distinct. Early thoughts on this was to make them essentially the same type
|
||||
internally, and cast between them, but unfortunately, a compliant C compiler
|
||||
is very likely to auto-cast between them, making it difficult to keep them
|
||||
separate yet castable back and forth.
|
||||
|
||||
To allow a stricter or more explicit way to remedy the flexibility of the C
|
||||
language, this design therefore defines a `OSSL_FN` which is separate from
|
||||
the `BIGNUM`, yet compatible with BIGNUM insofar that the `BIGNUM` type
|
||||
wraps around the `OSSL_FN` type, and `BIGNUM` functions wrap around
|
||||
corresponding `OSSL_FN` functions when there are any.
|
||||
|
||||
The idea is that a `BIGNUM` (`BN_`) function may call an `OSSL_FN` function,
|
||||
but not the other way around, i.e. when an `OSSL_FN` function is called, an
|
||||
"`OSSL_FN` only" bubble is entered, and such a function must therefore only
|
||||
in turn call other `OSSL_FN` functions for large number operations, rather
|
||||
than `BIGNUM` functions.
|
||||
|
||||
The overall design also defines new associated types to replace their
|
||||
`BIGNUM` counterparts: `OSSL_FN_CTX`, `OSSL_FN_BLINDING`, `OSSL_FN_MONT_CTX`,
|
||||
and `OSSL_FN_RECP_CTX`. Notably, however, the callback type `BN_GENCB`
|
||||
isn't replaced, as it contains nothing `BIGNUM`, and can therefore be reused
|
||||
unchanged with an `OSSL_FN` API.
|
||||
|
||||
The `OSSL_FN` type and API will be designed in such a way to enable it to
|
||||
become public at some point in the future. *The initial version will not be
|
||||
public and will only be used internally within OpenSSL.*
|
||||
|
||||
Let's go over the details
|
||||
|
||||
The `OSSL_FN` type
|
||||
------------------
|
||||
|
||||
[The `OSSL_FN` type]: #the-ossl_fn-type
|
||||
|
||||
The `OSSL_FN` type would be a structure derived from the existing `BIGNUM`
|
||||
type, retaining a minimum amount of data. Just as was previously with
|
||||
`BIGNUM`, the absolute value of the number is stored in a `BN_ULONG` array,
|
||||
and a flag indicates if the number is positive or negative.
|
||||
|
||||
```c
|
||||
typedef struct ossl_fn_st OSSL_FN;
|
||||
|
||||
struct ossl_fn_st {
|
||||
/* Flag: alloced with OSSL_FN_new() or OSSL_FN_secure_new() */
|
||||
unsigned int is_dynamically_allocated : 1;
|
||||
/* Flag: alloced with OSSL_FN_secure_new() */
|
||||
unsigned int is_securely_allocated : 1;
|
||||
/* Flag: the caller holds a pointer to this OSSL_FN as well as the BIGNUM that wraps it */
|
||||
unsigned int is_acquired : 1;
|
||||
/* Flag: the number is negative */
|
||||
unsigned int is_negative : 1;
|
||||
|
||||
/*
|
||||
* The d array, with its size in number of BN_ULONG.
|
||||
* This stores the number itself
|
||||
*/
|
||||
size_t dsize;
|
||||
BN_ULONG d[];
|
||||
};
|
||||
```
|
||||
|
||||
To be noted is that current cryptosystems never use negative numbers, so
|
||||
it's possible that the `is_negative` flag will never be used. Therefore, it
|
||||
is possible that it will never exist in actual implementation. It is
|
||||
retained in this design, though, to keep that option open.
|
||||
|
||||
The `OSSL_FN_CTX` type
|
||||
----------------------
|
||||
|
||||
[The `OSSL_FN_CTX` type]: #the-ossl_fn_ctx-type
|
||||
|
||||
The `OSSL_FN_CTX` type is made to replace the `BN_CTX` type where `OSSL_FN`
|
||||
type is used instead of `BIGNUM`.
|
||||
|
||||
The `OSSL_FN_CTX` type is to be implemented as an arena (a large enough chunk
|
||||
of memory) in which `OSSL_FN` instances are allocated. More in detail, there
|
||||
are two possibilities.
|
||||
|
||||
### The `OSSL_FN_CTX` type, with frames
|
||||
|
||||
[The `OSSL_FN_CTX` type, with frames]: #the-ossl_fn_ctx-type-with-frames
|
||||
|
||||
This variant is intended to mimic all `BN_CTX` functionality. The idea is to
|
||||
create a large `OSSL_FN_CTX` at the top function of a complex calculation, and
|
||||
pass it around to all sub-function calls.
|
||||
|
||||
Each sub-function would begin with starting a frame (using `OSSL_FN_CTX_begin()`,
|
||||
similar in spirit to `BN_CTX_start()`) in the passed `OSSL_FN_CTX` arena,
|
||||
obtain what temporary `OSSL_FN`s it needs from it (using `OSSL_FN_CTX_get()`,
|
||||
similar in spirit to `BN_CTX_get()`), perform what calculations it needs, and
|
||||
finish with ending the frame (using `OSSL_FN_CTX_end()`, similar in spirit to
|
||||
`BN_CTX_end()`), which relinquishing that frame's space in the `OSSL_FN_CTX`
|
||||
arena, and thereby making that same space available for the next sub-function.
|
||||
|
||||
```c
|
||||
typedef struct ossl_fn_ctx_st OSSL_FN_CTX;
|
||||
|
||||
struct ossl_fn_ctx_frame_st; /* forwarding, see below */
|
||||
struct ossl_fn_ctx_st {
|
||||
/*
|
||||
* Pointer to the last OSSL_FN_CTX_start() location (a simple pointer into
|
||||
* the memory area). See the struct ossl_fn_ctx_frame_st definition below
|
||||
* for details.
|
||||
*/
|
||||
struct ossl_fn_ctx_frame_st *last_frame;
|
||||
/*
|
||||
* The arena itself.
|
||||
*/
|
||||
size_t msize; /* bytes */
|
||||
unsigned char memory[];
|
||||
};
|
||||
|
||||
struct ossl_fn_ctx_frame_st {
|
||||
/*
|
||||
* Pointer back to the whole arena where the frame is located, to access
|
||||
* |msize| and |memory| from it.
|
||||
*/
|
||||
struct ossl_fn_ctx_st *arena;
|
||||
/*
|
||||
* Pointer to the previous frame in the arena, allowing OSSL_FN_CTX_end()
|
||||
* to do its job.
|
||||
*/
|
||||
struct ossl_fn_ctx_frame_st *previous_frame;
|
||||
/*
|
||||
* Pointer to the free area of the frame. Every time OSSL_FN_CTX_get() is
|
||||
* called, the current value of this pointer is returned, and it's updated
|
||||
* by incrementing it by the number of bytes given by OSSL_FN_CTX_get().
|
||||
* The available number of bytes is limited by what's left in the arena.
|
||||
*/
|
||||
unsigned char *free_memory;
|
||||
unsigned char memory[];
|
||||
};
|
||||
```
|
||||
|
||||
The arena design requires that the total use of the arena can be predicted
|
||||
at the point of allocating the arena. There is an inherent uncertainty how
|
||||
large an arena should be to accommodate the needs of a large tree of
|
||||
function calls using it. A possible solution is to allocate a very large
|
||||
arena (could 32kB be considered enough?), but it may require some
|
||||
investigation to find out what's reasonable.
|
||||
|
||||
Looking at the current use of `BN_CTX_new`, it can be noted that they are
|
||||
allocated all over current OpenSSL code, so it's easy to assume that each is
|
||||
used in a fairly limited fashion. Furthermore, the `BN_CTX` internals allow
|
||||
for a maximum of 16 `BIGNUM`s. A corresponding arena could the reasonably
|
||||
have the size 16 \* *size of largest fixed number* plus a little extra for
|
||||
bookkeeping purposes.
|
||||
|
||||
### The `OSSL_FN_CTX` type, without frames
|
||||
|
||||
[The `OSSL_FN_CTX` type, without frames]: #the-ossl_fn_ctx-type-without-frames
|
||||
|
||||
Compared to the variant with frames, this `OSSL_FN_CTX` variant is much
|
||||
simpler, but also more heap allocation intense.
|
||||
|
||||
The idea with this one is that each function that needs to obtain temporary
|
||||
`OSSL_FN`s would also create their own `OSSL_FN_CTX`, independently from any
|
||||
other function.
|
||||
|
||||
```c
|
||||
typedef struct ossl_fn_ctx_st OSSL_FN_CTX;
|
||||
|
||||
struct ossl_fn_ctx_st {
|
||||
/*
|
||||
* Pointer to the free area of the arena. Every time OSSL_FN_CTX_get() is
|
||||
* called, the current value of this pointer is returned, and it's updated
|
||||
* by incrementing it by the number of bytes given by OSSL_FN_CTX_get().
|
||||
* The available number of bytes is limited by what's left in the arena.
|
||||
*/
|
||||
unsigned char *free_memory;
|
||||
/*
|
||||
* The arena itself.
|
||||
*/
|
||||
size_t msize; /* bytes */
|
||||
unsigned char memory[];
|
||||
};
|
||||
```
|
||||
|
||||
Other associated types
|
||||
----------------------
|
||||
|
||||
[Other associated types]: #other-associated-types
|
||||
|
||||
There are a few types that, like `BN_CTX` / `OSSL_FN_CTX`, are used to hold
|
||||
a context around some more complicated calculations. Just like `OSSL_FN_CTX`,
|
||||
The `OSSL_FN` variants of these types are made into strictly separate types,
|
||||
not compatible with their `BIGNUM` counterparts.
|
||||
|
||||
| `BIGNUM` types | `OSSL_FN` types |
|
||||
|----------------|--------------------|
|
||||
| `BN_BLINDING` | `OSSL_FN_BLINDING` |
|
||||
| `BN_MONT_CTX` | `OSSL_FN_MONT_CTX` |
|
||||
| `BN_RECP_CTX` | `OSSL_FN_RECP_CTX` |
|
||||
|
||||
Their `OSSL_FN` APIs for these types should be possible to create by
|
||||
repurposing the corresponding `BIGNUM` APIs, with adjustments for the
|
||||
constant-size requirements of all `OSSL_FN` functions.
|
||||
|
||||
The `BIGNUM` type
|
||||
-----------------
|
||||
|
||||
[The `BIGNUM` type]: #the-bignum-type
|
||||
|
||||
The `BIGNUM` type is changed to include a `OSSL_FN` for its data, and other
|
||||
fields that are only of interest for `BIGNUM`s:
|
||||
|
||||
```c
|
||||
struct bignum_st {
|
||||
OSSL_FN *data;
|
||||
/* Some of these flags are replicated in OSSL_FN, some are not */
|
||||
int flags;
|
||||
};
|
||||
```
|
||||
|
||||
When structured this way, it's easy to get an `OSSL_FN` out of a `BIGNUM`,
|
||||
as well as to wrap an `OSSL_FN` in a `BIGNUM`:
|
||||
|
||||
```c
|
||||
/*
|
||||
* BN_acquire_fn() and BN_release_fn() function together. It is done this
|
||||
* way as a safety measure, to make sure that a BIGNUM doesn't expand an OSSL_FN
|
||||
* that the caller currently has a handle on. However, it's possible to
|
||||
* adjust the size of the OSSL_FN while acquiring it.
|
||||
*/
|
||||
OSSL_FN *BN_acquire_fn(BIGNUM *a, size_t bits)
|
||||
{
|
||||
if (a->data->is_acquired)
|
||||
return NULL; /* only one acquisition at a time */
|
||||
if ((bn_expand(a, bits)) <= 0)
|
||||
return NULL;
|
||||
a->data->is_acquired = 1;
|
||||
return a->data;
|
||||
}
|
||||
void BN_release_fn(BIGNUM *a)
|
||||
{
|
||||
a->data->is_acquired = 0;
|
||||
}
|
||||
```
|
||||
|
||||
Note that these functions are not designed to be thread-safe, nor do they
|
||||
support multiple suímultaneous acquisitions. By design, holding pointers to
|
||||
a `BIGNUM` and its wrapped `OSSL_FN` at the same time should only happen in
|
||||
a very short term.
|
||||
|
||||
If there's a need, it would also be possible to wrap an `OSSL_FN` with a
|
||||
`BIGNUM`:
|
||||
|
||||
``` C
|
||||
/*
|
||||
* When wrapping an OSSL_FN in a BIGNUM, the OSSL_FN is considered acquired
|
||||
* until the caller decides to release it.
|
||||
*/
|
||||
BIGNUM *BN_wrap_fn(OSSL_FN *a)
|
||||
{
|
||||
BIGNUM *r = OPENSSL_zalloc(sizeof(BIGNUM));
|
||||
|
||||
if (r != NULL) {
|
||||
r->data = a;
|
||||
r->flags |= (a->is_dynamically_allocated ? BN_FLG_MALLOCED);
|
||||
r->flags |= (a->is_securely_allocated ? BN_FLG_SECURE);
|
||||
a->is_acquired = 1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
```
|
||||
|
||||
This should be avoided, but we retain this possibility just in case its use
|
||||
is unavoidable.
|
||||
|
||||
Mutability
|
||||
----------
|
||||
|
||||
[Mutability]: #mutability
|
||||
|
||||
The understanding is that within a `OSSL_FN` API, `dsize` is immutable as
|
||||
soon as a `OSSL_FN` has been allocated to its target size, except for when
|
||||
the `OSSL_FN` instance is freed. However, when accessed through the `BIGNUM`
|
||||
type (i.e. by the `BIGNUM` API), the `OSSL_FN` size may be reallocated to
|
||||
allow a larger size than initially allocated, and `dsize` may be modified
|
||||
accordingly.
|
||||
|
||||
The `OSSL_FN_CTX` API is much more strict. The size of an `OSSL_FN_CTX`
|
||||
instance is immutable after it has been allocated, except when it is freed.
|
||||
|
||||
In the case where an `OSSL_FN` is "acquired" (i.e. the calling code holds a
|
||||
pointer to a `OSSL_FN` and to a `BIGNUM` that wraps it), `BIGNUM` must
|
||||
consider the `OSSL_FN` size as immutable.
|
||||
|
||||
Dropping `top` from `BIGNUM`
|
||||
----------------------------
|
||||
|
||||
[Dropping `top` from `BIGNUM`]: #dropping-top-from-bignum
|
||||
|
||||
With this design, the `top` field is dropped, meaning that a `BIGNUM` will
|
||||
no longer be able to diminish its memory footprint. The reason is that the
|
||||
`OSSL_FN` functionality would need to update it, but that runs counter to
|
||||
the ideas behind the `OSSL_FN` functionality in terms of mutability.
|
||||
|
||||
This may come at a performance cost for users calling the `BIGNUM`
|
||||
API. However, it's our judgement that this is acceptable to get better
|
||||
overall safety.
|
||||
|
||||
Memory functionality for `OSSL_FN`
|
||||
----------------------------------
|
||||
|
||||
[Memory functionality for `OSSL_FN`]: #memory-functionality-for-ossl_fn
|
||||
|
||||
We anticipate that we will need the following functions to allocate and
|
||||
deallocate `OSSL_FN`s:
|
||||
|
||||
```c
|
||||
OSSL_FN *OSSL_FN_new(size_t size);
|
||||
void OSSL_FN_free(OSSL_FN *f);
|
||||
```
|
||||
|
||||
Memory functionality for `OSSL_FN_CTX`
|
||||
--------------------------------------
|
||||
|
||||
[Memory functionality for `OSSL_FN_CTX`]: #memory-functionality-for-ossl_fn_ctx
|
||||
|
||||
We anticipate that the `OSSL_FN_CTX` API will look very much like the
|
||||
`BN_CTX` API, except for the allocation functionality:
|
||||
|
||||
```c
|
||||
OSSL_FN_CTX *OSSL_FN_CTX_new(OSSL_LIB_CTX *libctx, size_t arena_size);
|
||||
OSSL_FN_CTX *OSSL_FN_CTX_secure_new(OSSL_LIB_CTX *libctx, size_t arena_size);
|
||||
void OSSL_FN_CTX_free(OSSL_FN_CTX *ctx);
|
||||
|
||||
OSSL_FN *OSSL_FN_CTX_get(OSSL_FN_CTX *ctx, size_t size);
|
||||
```
|
||||
|
||||
*Something to be noted is that `OSSL_FN_CTX_secure_new()` allocates the
|
||||
whole arena in secure memory. The impact compared to allocating individual
|
||||
`OSSL_FN` instances in secure memory is considered minimal.*
|
||||
|
||||
If the variant of `OSSL_FN_CTX` *with frames* is chosen, the following
|
||||
functions will also have to be defined:
|
||||
|
||||
```c
|
||||
int OSSL_FN_CTX_start(OSSL_FN_CTX *ctx);
|
||||
int OSSL_FN_CTX_end(OSSL_FN_CTX *ctx);
|
||||
```
|
||||
|
||||
Wrapping an `OSSL_FN` function with a `BIGNUM` function
|
||||
-------------------------------------------------------
|
||||
|
||||
[Wrapping an `OSSL_FN` function with a `BIGNUM` function]: #wrapping-an-ossl_fn-function-with-a-bignum-function
|
||||
|
||||
This is one example of what that would look like. This assumes that there is
|
||||
a function `OSSL_FN_add()`:
|
||||
|
||||
```c
|
||||
int OSSL_FN_add(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b)
|
||||
{
|
||||
/*
|
||||
* Code from the current BN_add() goes here, without the part that touches
|
||||
* top and dmax (top doesn't exist in this design, but it does exist in
|
||||
* current OpenSSL code)
|
||||
*/
|
||||
}
|
||||
|
||||
int BN_add(BIGNUM *r, BIGNUM *a, BIGNUM *b)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!r->data.is_acquired) {
|
||||
size_t max_size = a->data.dsize; /* number of sizeof(BN_ULONG) limbs */
|
||||
BN_ULONG n = a->data->d[max_size-1];
|
||||
|
||||
if (b->data.dsize > max_size) {
|
||||
max_size = b->data->dsize;
|
||||
n = b->data->d[max_size-1];
|
||||
}
|
||||
|
||||
/*
|
||||
* If the highest limb in the biggest number is non-zero and they are
|
||||
* both positive or both negative, it's assumed that the resulting
|
||||
* bignum may grow by one limb.
|
||||
*/
|
||||
if (n != 0 && a->data->is_negative == b->data->is_negative)
|
||||
max_size++;
|
||||
|
||||
if ((ret = bn_expand(r, max_size * BN_BITS2)) <= 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* It's not necessary to "acquire" the OSSL_FNs here, because it's
|
||||
* assumed that the call of OSSL_FN_add() enters a "OSSL_FN only" bubble.
|
||||
*/
|
||||
ret = OSSL_FN_add(r->data, a->data, b->data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
```
|
||||
|
||||
*(This is not perfect and tested code, it's just an example. Actual code
|
||||
should be more perfect, and of course, tested)*
|
||||
|
||||
Failures
|
||||
--------
|
||||
|
||||
[Failures]: #failures
|
||||
|
||||
A fixed size large number introduces new problems, which introduces new ways
|
||||
that the `OSSL_FN` API can fail:
|
||||
|
||||
* Overflow: this will happen when the caller has allocated an improperly
|
||||
sized `OSSL_FN` to store future calculation results in. *This is akin to
|
||||
memory allocation failures in so far that there isn't enough memory space*
|
||||
|
||||
Repurposing existing code
|
||||
=========================
|
||||
|
||||
[Repurposing existing code]: #repurposing-existing-code
|
||||
|
||||
A majority of existing internal `BIGNUM` code operates directly on the `d`
|
||||
array of the existing `BIGNUM` structure, with the size of that array given
|
||||
separately, and are already essentially operating on fixed size numbers.
|
||||
This design assumes that such functions can be repurposed for `OSSL_FN`
|
||||
functionality with zero change, apart from function name changes.
|
||||
|
||||
Furthermore, this design assumes that the remaining functions, which do
|
||||
manipulate the size of the `BIGNUM`, or are public facing `BIGNUM`
|
||||
functions, can be rewritten in the same way as [the `BN_add()` example
|
||||
above](#wrapping-an-ossl_fn-function-with-a-bignum-function), thereby
|
||||
functionally separating the dynamic properties of `BIGNUM`s from the less
|
||||
dynamic properties of `OSSL_FN`s.
|
||||
|
||||
How to apply `OSSL_FN`
|
||||
======================
|
||||
|
||||
[How to apply `OSSL_FN`]: #how-to-apply-ossl_fn
|
||||
|
||||
The purpose of `OSSL_FN` is to make the number constant size (implying
|
||||
enhanced constant time) for a crypto system. To guarantee this with high
|
||||
confidence, any function that performs some sort of numeric operation on a
|
||||
set of input `OSSL_FN`s must only use other functions that only affect the
|
||||
contents of their `d` array, but not its size. Those are typically other
|
||||
`OSSL_FN` functions, or reused bignum functions that receive the `d` array
|
||||
and its size directly.
|
||||
|
||||
Where to apply `OSSL_FN`
|
||||
========================
|
||||
|
||||
[Where to apply `OSSL_FN`]: #where-to-apply-ossl_fn
|
||||
|
||||
`OSSL_FN` should primarily be used instead of `BIGNUM` in internal
|
||||
calculations throughout OpenSSLs libraries. Exceptions can be made where
|
||||
calculations aren't security critical.
|
||||
|
||||
In this, "calculations" is meant in a mathematical sense, i.e. whatever what
|
||||
would be expressed as a mathematical formula is considered a "calculation".
|
||||
|
||||
However, `BIGNUM` has other uses than mere calculations. For example,
|
||||
`BIGNUM` is used as storage of numbers that were originally ASN.1 INTEGERs,
|
||||
and while individual ASN.1 INTEGERs always have a known size, they are
|
||||
usually just one number in a set, and it's often only known at a later time
|
||||
what are the size requirements of the cryptosystem that use them.
|
||||
For example, the size of an RSA key can only be determined when a known
|
||||
number in that key - usually *n* - has been seen by code, and this affects
|
||||
what size all numbers in an RSA key should be adjusted to before doing
|
||||
calculations on them.
|
||||
|
||||
How to apply `OSSL_FN_CTX`
|
||||
==========================
|
||||
|
||||
[How to apply `OSSL_FN_CTX`]: #how-to-apply-ossl_fn_ctx
|
||||
|
||||
The variant with frames
|
||||
-----------------------
|
||||
|
||||
[The variant with frames]: #the-variant-with-frames
|
||||
|
||||
All internal uses of `BN_CTX_new()` and `BN_CTX_new_ex()` are to be replaced
|
||||
with calls of `OSSL_FN_CTX_new()`.
|
||||
|
||||
All internal uses of `BN_CTX_secure_new()` and `BN_CTX_secure_new_ex()` are to
|
||||
be replaced with calls of `OSSL_FN_CTX_secure_new()`.
|
||||
|
||||
All internal uses of `BN_CTX_free()` are to be replaced with calls of
|
||||
`OSSL_FN_CTX_free()`.
|
||||
|
||||
All internal uses of `BN_CTX_start()` are to be replaced with calls of
|
||||
`OSSL_FN_CTX_start()`.
|
||||
|
||||
All internal uses of `BN_CTX_get()` are to be replaced with calls of
|
||||
`OSSL_FN_CTX_get()`.
|
||||
|
||||
All internal uses of `BN_CTX_end()` are to be replaced with calls of
|
||||
`OSSL_FN_CTX_end()`.
|
||||
|
||||
The variant without frames
|
||||
--------------------------
|
||||
|
||||
[The variant without frames]: #the-variant-without-frames
|
||||
|
||||
All internal uses of `BN_CTX_new()`, `BN_CTX_new_ex()`, `BN_CTX_secure_new()`,
|
||||
`BN_CTX_secure_new_ex()`, and `BN_CTX_free()` are to be dropped.
|
||||
|
||||
All internal uses of `BN_CTX_start()` are to be replaced with calls of
|
||||
`OSSL_FN_CTX_new()`.
|
||||
|
||||
All internal uses of `BN_CTX_get()` are to be replaced with calls of
|
||||
`OSSL_FN_CTX_get()`.
|
||||
|
||||
All internal uses of `BN_CTX_end()` are to be replaced with calls of
|
||||
`OSSL_FN_CTX_free()`.
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
[Testing]: #testing
|
||||
|
||||
Functional tests similar to `test/recipes/10-test_bn.t` must be added.
|
||||
|
||||
Timing tests to compare operations on a variety of inputs of different sizes
|
||||
must also be added. These tests should perform operations based on a given
|
||||
fixed number size.
|
||||
|
||||
It should also prove interesting to collect timing statistics for a set of
|
||||
operations using `BIGNUM` in previous OpenSSL versions and compare them with
|
||||
similar timing statistics using `BIGNUM` when reimplemented according to this
|
||||
design. It is *assumed* that the new statistics will show a higher degree
|
||||
of constant time, [due to `top` being dropped](#dropping-top-from-bignum),
|
||||
even though not as much as pure `OSSL_FN` operations.
|
||||
|
||||
Appendix
|
||||
========
|
||||
|
||||
[Appendix]: #appendix
|
||||
|
||||
Using the C99 flexible array member feature
|
||||
-------------------------------------------
|
||||
|
||||
[Using the C99 flexible array member feature]: #using-the-c99-flexible-array-member-feature
|
||||
|
||||
In this design, the C99 feature that's dubbed "flexible array member" is used
|
||||
extensively. This a `struct` member that's an array, that must come last in
|
||||
the struct, and that is incomplete in so far that no array size is given. It
|
||||
can look like this:
|
||||
|
||||
``` C
|
||||
struct t {
|
||||
size_t a;
|
||||
char b;
|
||||
char c[]; /**< flexible array member */
|
||||
};
|
||||
```
|
||||
|
||||
Some attention must be paid to how it's arranged in memory. It's debated
|
||||
whether the offset of a flexible array member's offset from the start of the
|
||||
`struct` is set to be before or after the `struct`'s end padding, i.e. whether
|
||||
`sizeof(struct t) == offsetof(struct t, c)` is true or not in all circumstances.
|
||||
|
||||
Here's how that would differ on a 64-bit system:
|
||||
|
||||
| location of `c` | `offsetof(struct t, a)` | `offsetof(struct t, b)` | `offsetof(struct t, c)` | `sizeof(struct t)` |
|
||||
|-----------------|:-----------------------:|:-----------------------:|:-----------------------:|:------------------:|
|
||||
| before padding | 0 | 8 | 9 | 16 |
|
||||
| after padding | 0 | 8 | 16 | 16 |
|
||||
|
||||
To be noted, `gcc` and `clang` favor "before padding".
|
||||
|
||||
For consistent placement of the flexible array member, one therefore needs to
|
||||
pay attention to possible `struct` padding. Among other methods, one chosen
|
||||
here is to precede the flexible array member with a member whose type is
|
||||
assumed to be large enough that no padding is needed after it, such as
|
||||
`size_t` or a pointer.
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
bn_mul_words, bn_mul_add_words, bn_sqr_words, bn_div_words,
|
||||
bn_add_words, bn_sub_words, bn_mul_comba4, bn_mul_comba8,
|
||||
bn_sqr_comba4, bn_sqr_comba8, bn_cmp_words, bn_mul_truncated, bn_mul_normal,
|
||||
bn_sqr_comba4, bn_sqr_comba8, bn_cmp_words, bn_mul_normal,
|
||||
bn_mul_low_normal, bn_mul_recursive, bn_mul_part_recursive,
|
||||
bn_mul_low_recursive, bn_sqr_normal, bn_sqr_recursive,
|
||||
bn_expand, bn_wexpand, bn_expand2, bn_fix_top, bn_check_top,
|
||||
@@ -32,8 +32,6 @@ library internal functions
|
||||
|
||||
int bn_cmp_words(BN_ULONG *a, BN_ULONG *b, int n);
|
||||
|
||||
void bn_mul_truncated(BN_ULONG *r, int rn, BN_ULONG *a, int na,
|
||||
BN_ULONG *b, int nb);
|
||||
void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b,
|
||||
int nb);
|
||||
void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n);
|
||||
@@ -153,11 +151,6 @@ bn_cmp_words(B<a>, B<b>, B<n>) operates on the B<n> word arrays B<a>
|
||||
and B<b>. It returns 1, 0 and -1 if B<a> is greater than, equal and
|
||||
less than B<b>.
|
||||
|
||||
bn_mul_truncated(B<r>, B<nr>, B<a>, B<na>, B<b>, B<nb>) operates on the
|
||||
B<na> word array B<a>, the B<nb> word array B<b> and the B<nr> word array
|
||||
B<r>. It computes B<a>*B<b> and places the result in B<r>, truncated to
|
||||
B<nr> words.
|
||||
|
||||
bn_mul_normal(B<r>, B<a>, B<na>, B<b>, B<nb>) operates on the B<na>
|
||||
word array B<a>, the B<nb> word array B<b> and the B<na>+B<nb> word
|
||||
array B<r>. It computes B<a>*B<b> and places the result in B<r>.
|
||||
|
||||
@@ -70,6 +70,7 @@ Server authentication options:
|
||||
[B<-expect_sender> I<name>]
|
||||
[B<-ignore_keyusage>]
|
||||
[B<-unprotected_errors>]
|
||||
[B<-ta_in_ip_extracerts>]
|
||||
[B<-no_cache_extracerts>]
|
||||
[B<-srvcertout> I<filename>]
|
||||
[B<-extracertsout> I<filename>]
|
||||
@@ -715,6 +716,22 @@ with a signature key."
|
||||
|
||||
=back
|
||||
|
||||
=item B<-ta_in_ip_extracerts>
|
||||
|
||||
This is a quirk option added to support 3GPP TS 33.310.
|
||||
B<WARNING:> This leads to behavior violating RFCs 4210 and 9810.
|
||||
|
||||
It allows using self-issued certificates from the extraCerts in an IP message
|
||||
as non-authenticated trust anchors when validating the CMP message protection certificate
|
||||
in this and any subsequent responses from the server in the same transaction,
|
||||
but only if these extraCerts can also be used as trust anchors for validating
|
||||
the newly enrolled certificate received in the IP message.
|
||||
|
||||
Note that using this option is dangerous as the to-be-trusted certificates
|
||||
obtained this way have not been authenticated (at least not at CMP level).
|
||||
Taking them over as initial trust anchors
|
||||
implements a form of trust-on-first-use (TOFU).
|
||||
|
||||
=item B<-no_cache_extracerts>
|
||||
|
||||
Do not cache certificates in the extraCerts field of CMP messages received.
|
||||
@@ -1513,6 +1530,8 @@ and B<-rsp_crl> options were added in OpenSSL 3.4.
|
||||
B<-centralkeygen>, B<-newkeyout>, B<-rsp_key> and
|
||||
B<-rsp_keypass> were added in OpenSSL 3.5.
|
||||
|
||||
The B<-ta_in_ip_extracerts> quirk option was added in OpenSSL 4.0.
|
||||
|
||||
The B<-engine> option was removed in OpenSSL 4.0.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
@@ -674,7 +674,8 @@ For information about specific commands, see L<openssl-rehash(1)>
|
||||
and L<tsget(1)>.
|
||||
|
||||
For information about querying or specifying CPU architecture flags, see
|
||||
L<OPENSSL_ia32cap(3)>, L<OPENSSL_s390xcap(3)> and L<OPENSSL_riscvcap(3)>.
|
||||
L<OPENSSL_ia32cap(3)>, L<OPENSSL_ppccap(3)>, L<OPENSSL_s390xcap(3)>,
|
||||
and L<OPENSSL_riscvcap(3)>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
|
||||
155
doc/man3/OPENSSL_ppccap.pod
Normal file
155
doc/man3/OPENSSL_ppccap.pod
Normal file
@@ -0,0 +1,155 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
OPENSSL_ppccap - the PowerPC processor capabilities vector
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
env OPENSSL_ppccap=... <application>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
libcrypto supports PowerPC instruction set extensions. These extensions are
|
||||
represented by bits in the PowerPC capabilities vector. When libcrypto
|
||||
initializes, it stores the results returned by PowerPC CPU capabilities detection
|
||||
logic in the PowerPC capabilities vector. The CPU capabilities detection methods
|
||||
are OS-dependent and use a combination of information gathered by the kernel
|
||||
during boot and probe functions that attempt to execute instructions and trap
|
||||
illegal instruction signals with a signal handler.
|
||||
|
||||
To override the set of extensions available to an application, you can set the
|
||||
B<OPENSSL_ppccap> environment variable before you start the application. The
|
||||
environment variable is assigned a numerical value that denotes the bits in
|
||||
the PowerPC capabilities vector. The ppc_arch.h header file states that, "Flags'
|
||||
usage can appear ambiguous, because they are set rather to reflect OpenSSL
|
||||
performance preferences than actual processor capabilities."
|
||||
|
||||
Multiple extensions are enabled by logically OR-ing the values that represent the
|
||||
desired extensions.
|
||||
|
||||
B<Notes>: Enabling an extension on a CPU that does not support the extension
|
||||
will result in a SIGILL crash. On AIX, all vector instructions can be disabled
|
||||
with the schedo -ro allow_vmx=0 command. DO NOT USE THIS COMMAND to disable
|
||||
vector instructions in the OS when it is running on a CPU level that supports the
|
||||
instructions without also disabling them in libcrpto via the OPENSSL_ppccap
|
||||
environment variable or the application will crash with a SIGILL.
|
||||
|
||||
Currently, the following extensions are defined:
|
||||
|
||||
=over 4
|
||||
|
||||
=item 0x01
|
||||
|
||||
Name: B<PPC_FPU64>
|
||||
|
||||
This flag is obsolete.
|
||||
|
||||
=item 0x02
|
||||
|
||||
Name: B<PPC_ALTIVEC>
|
||||
|
||||
Meaning: Use AltiVec (aka VMX) instructions. In some but not all cases, this
|
||||
capability gates the use of later ISA vector instructions. The associated probe
|
||||
instruction is vor (vector logical or).
|
||||
|
||||
Effect: Enables use of vector instructions but does not enable extensions added
|
||||
at specific ISA levels. However, disabling this capability disables a subset of
|
||||
vector extensions added at specific ISA levels even if they are otherwise
|
||||
enabled.
|
||||
|
||||
=item 0x04
|
||||
|
||||
Name: B<PPC_CRYPTO207>
|
||||
|
||||
Meaning: Use instructions added in ISA level 2.07. The associated probe
|
||||
instruction instruction is vcipher (vector AES cipher round).
|
||||
|
||||
Effect: Enables AES, SHA-2 sigma, and other ISA 2.07 instructions for AES, SHA-2,
|
||||
GHASH, and Poly1305.
|
||||
|
||||
=item 0x08
|
||||
|
||||
Name: B<PPC_FPU>
|
||||
|
||||
Meaning: Use FPU instructions. The associated probe instruction is fmr (floating
|
||||
move register).
|
||||
|
||||
Effect: Enables Poly1305 FPU implementation. The PPC_CRYPTO207 capability
|
||||
overrides this effect.
|
||||
|
||||
=item 0x10
|
||||
|
||||
Name: B<PPC_MADD300>
|
||||
|
||||
Meaning: Use instructions added in ISA level 3.00. The associated probe
|
||||
instruction is maddhdu (multiply-add high doubleword unsigned).
|
||||
|
||||
Effect: Enables use of the polynomial multiply and other ISA 3.00 instructions
|
||||
for AES-GCM, P-384, and P-521.
|
||||
|
||||
=item 0x20
|
||||
|
||||
Name: B<PPC_MFTB>
|
||||
|
||||
Meaning: Use the mftb (move from time base) instruction. The associated probe
|
||||
instruction is mftb.
|
||||
|
||||
Effect: Enables use of the mftb instruction to sample the lower 32 bits of the
|
||||
CPU time base register in order to acquire entropy. Considered obsolete. The
|
||||
PPC_MFSPR268 capability overrides this capability.
|
||||
|
||||
=item 0x40
|
||||
|
||||
Name: B<PPC_MFSPR268>
|
||||
|
||||
Meaning: Use the mfspr (move from special purpose register) instruction to
|
||||
read SPR 268. The associated probe instruction is mfspr 268.
|
||||
|
||||
Effect: Enables use of the mfspr instruction to sample the lower 32 bits of the
|
||||
CPU time base register from SPR 268, the TBL (time base lower) register, in order
|
||||
to acquire entropy.
|
||||
|
||||
=item 0x80
|
||||
|
||||
Name: B<PPC_BRD31>
|
||||
|
||||
Meaning: Use instructions added in ISA level 3.1. The associated probe instruction
|
||||
is brd (byte-reverse doubleword).
|
||||
|
||||
Effect: Enables use of ISA 3.1 instructions in ChaCha20.
|
||||
|
||||
=back
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
Not available.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
Check currently detected capabilities:
|
||||
|
||||
$ openssl info -cpusettings
|
||||
OPENSSL_ppccap=0x2E
|
||||
|
||||
The detected capabilities in the above example indicate that PPC_MFTB, PPC_FPU,
|
||||
PPC_CRYPTO207, PPC_MFSPR268, and PPC_ALTIVEC are enabled.
|
||||
|
||||
Disable all instruction set extensions:
|
||||
|
||||
OPENSSL_ppccap=0x00
|
||||
|
||||
Enable base AltiVec extensions:
|
||||
|
||||
OPENSSL_ppccap=0x02
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License 2.0 (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
|
||||
L<https://www.openssl.org/source/license.html>.
|
||||
|
||||
=cut
|
||||
@@ -343,13 +343,18 @@ Else, 'digitalSignature' must be allowed by CMP signer certificates.
|
||||
|
||||
=item B<OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR>
|
||||
|
||||
Allow retrieving a trust anchor from extraCerts and using that
|
||||
to validate the certificate chain of an IP message.
|
||||
This is a quirk option added to support 3GPP TS 33.310.
|
||||
It leads to behavior violating RFCs 4210 and 9810.
|
||||
It allows using self-issued certificates from the extraCerts in an IP message
|
||||
as trust anchors when validating the CMP message protection certificate
|
||||
in this and any subsequent responses from the server in the same transaction,
|
||||
but only if these extraCerts can also be used as trust anchors for validating
|
||||
the newly enrolled certificate received in the IP message.
|
||||
|
||||
Note that using this option is dangerous as the certificate obtained
|
||||
this way has not been authenticated (at least not at CMP level).
|
||||
Taking it over as a trust anchor implements trust-on-first-use (TOFU).
|
||||
Note that using this option is dangerous as the to-be-trusted certificates
|
||||
obtained this way have not been authenticated (at least not at CMP level).
|
||||
Taking them over as initial trust anchors
|
||||
implements a form of trust-on-first-use (TOFU).
|
||||
|
||||
=item B<OSSL_CMP_OPT_NO_CACHE_EXTRACERTS>
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
OSSL_LIB_CTX, OSSL_LIB_CTX_get_data, OSSL_LIB_CTX_new,
|
||||
OSSL_LIB_CTX_new_from_dispatch, OSSL_LIB_CTX_new_child,
|
||||
OSSL_LIB_CTX_free, OSSL_LIB_CTX_load_config,
|
||||
OSSL_LIB_CTX_get0_global_default, OSSL_LIB_CTX_set0_default
|
||||
OSSL_LIB_CTX_get0_global_default, OSSL_LIB_CTX_set0_default,
|
||||
OSSL_LIB_CTX_freeze
|
||||
- OpenSSL library context
|
||||
|
||||
=head1 SYNOPSIS
|
||||
@@ -24,6 +25,7 @@ OSSL_LIB_CTX_get0_global_default, OSSL_LIB_CTX_set0_default
|
||||
OSSL_LIB_CTX *OSSL_LIB_CTX_get0_global_default(void);
|
||||
OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *ctx);
|
||||
void *OSSL_LIB_CTX_get_data(OSSL_LIB_CTX *ctx, int index);
|
||||
void *OSSL_LIB_CTX_freeze(OSSL_LIB_CTX *ctx, const char* propq);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
@@ -121,6 +123,20 @@ If ctx is NULL then the function operates on the default library context.
|
||||
OSSL_LIB_CTX_get_data() returns a memory address whose interpretation
|
||||
depends on the index.
|
||||
|
||||
OSSL_LIB_CTX_freeze() freezes the method store associated with the library
|
||||
context. A frozen context will speed up ONLY isolated, uncached algorithm
|
||||
lookups. This is specifically designed to benefit legacy high-throughput
|
||||
applications with worker threads doing isolated computations, without requiring
|
||||
a code restructuring. Existing and new applications are generally recommended to
|
||||
not use this feature and instead structure the application to pre-initialize
|
||||
contexts where possible. This function should only be called from a non-threaded
|
||||
context, before any worker threads have been dispatched.
|
||||
|
||||
If propq is NULL, it will only speed up method store operations with a NULL
|
||||
property query. If propq is not NULL, it will also speed up method store
|
||||
operations when given that exact property query. Other property queries will go
|
||||
through the normal, slower lookup method.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
OSSL_LIB_CTX_new(), OSSL_LIB_CTX_get0_global_default() and
|
||||
@@ -134,15 +150,20 @@ OSSL_LIB_CTX_load_config() returns 1 on success, 0 on error.
|
||||
OSSL_LIB_CTX_get_data() returns a memory address whose interpretation
|
||||
depends on the index.
|
||||
|
||||
OSSL_LIB_CTX_freeze() returns 1 on success, 0 on error. A frozen library context
|
||||
cannot be frozen again.
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
All of the functions described on this page were added in OpenSSL 3.0.
|
||||
|
||||
OSSL_LIB_CTX_get_data() was introduced in OpenSSL 3.4.
|
||||
|
||||
OSSL_LIB_CTX_freeze() was introduced in OpenSSL 4.0.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
|
||||
Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
this file except in compliance with the License. You can obtain a copy
|
||||
|
||||
@@ -234,7 +234,8 @@ OpenSSL supports a number of different algorithm implementations for
|
||||
various machines and, by default, it determines which to use based on the
|
||||
processor capabilities and run time feature enquiry. These environment
|
||||
variables can be used to exert more control over this selection process.
|
||||
See L<OPENSSL_ia32cap(3)>, L<OPENSSL_riscvcap(3)>, and L<OPENSSL_s390xcap(3)>.
|
||||
See L<OPENSSL_ia32cap(3)>, L<OPENSSL_ppccap(3)>, L<OPENSSL_riscvcap(3)>,
|
||||
and L<OPENSSL_s390xcap(3)>.
|
||||
|
||||
These variables are not considered security-sensitive.
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <limits.h>
|
||||
#include "types.h"
|
||||
|
||||
BIGNUM *bn_wexpand(BIGNUM *a, int words);
|
||||
BIGNUM *bn_expand2(BIGNUM *a, int words);
|
||||
|
||||
@@ -36,6 +36,4 @@ void ossl_malloc_setup_failures(void);
|
||||
int ossl_crypto_alloc_ex_data_intern(int class_index, void *obj,
|
||||
CRYPTO_EX_DATA *ad, int idx);
|
||||
|
||||
size_t ossl_num_bits(size_t value);
|
||||
|
||||
#endif /* OSSL_CRYPTO_CRYPTLIB_H */
|
||||
|
||||
@@ -252,6 +252,7 @@ struct evp_kdf_st {
|
||||
#define EVP_ORIG_DYNAMIC 0
|
||||
#define EVP_ORIG_GLOBAL 1
|
||||
#define EVP_ORIG_METH 2
|
||||
#define EVP_ORIG_FROZEN 3
|
||||
|
||||
struct evp_md_st {
|
||||
/* nid */
|
||||
|
||||
@@ -1,285 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_FN_H
|
||||
#define OPENSSL_FN_H
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <openssl/opensslconf.h>
|
||||
#include <openssl/bn_limbs.h>
|
||||
#include <openssl/types.h>
|
||||
#include "crypto/types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* @type OSSL_FN_ULONG is the type for the OSSL_FN limb. It's made to be
|
||||
* compatible with BN_ULONG (quite literally).
|
||||
*
|
||||
* @def OSSL_FN_BYTES is defined with the size of OSSL_FN_ULONG, measured in
|
||||
* bytes. This is mainly useful where 'sizeof(OSSL_FN_ULONG)' isn't suitable,
|
||||
* such as the C pre-processor.
|
||||
*/
|
||||
|
||||
#ifdef BN_ULONG
|
||||
typedef BN_ULONG OSSL_FN_ULONG;
|
||||
#define OSSL_FN_BYTES BN_BYTES
|
||||
#endif
|
||||
|
||||
#ifndef OSSL_FN_BYTES
|
||||
#error "OpenSSL doesn't support large numbers on this platform"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For practical reasons, we allow allocating OSSL_FNs in terms of limbs (what
|
||||
* the BIGNUM library calls "words"), bytes and bits. The number of bytes and
|
||||
* bits are rounded up to the number of limbs that can fit them.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allocate an OSSL_FN in memory.
|
||||
*
|
||||
* @param[in] size The number of limbs for the number itself.
|
||||
* There's an additional few bytes allocated for bookkeeping.
|
||||
* @returns an OSSL_FN instance.
|
||||
* @retval NULL on error.
|
||||
*/
|
||||
OSSL_FN *OSSL_FN_new_limbs(size_t size);
|
||||
|
||||
/**
|
||||
* Allocate an OSSL_FN in secure memory.
|
||||
*
|
||||
* @param[in] size The number of limbs for the number itself.
|
||||
* There's an additional few bytes allocated for bookkeeping.
|
||||
* @returns an OSSL_FN instance.
|
||||
* @retval NULL on error.
|
||||
*/
|
||||
OSSL_FN *OSSL_FN_secure_new_limbs(size_t size);
|
||||
|
||||
/**
|
||||
* Allocate an OSSL_FN in memory.
|
||||
*
|
||||
* @param[in] size The number of bytes for the number itself.
|
||||
* There's an additional few bytes allocated for bookkeeping.
|
||||
* @returns an OSSL_FN instance.
|
||||
* @retval NULL on error.
|
||||
*/
|
||||
OSSL_FN *OSSL_FN_new_bytes(size_t size);
|
||||
|
||||
/**
|
||||
* Allocate an OSSL_FN in secure memory.
|
||||
*
|
||||
* @param[in] size The number of bytes for the number itself.
|
||||
* There's an additional few bytes allocated for bookkeeping.
|
||||
* @returns an OSSL_FN instance.
|
||||
* @retval NULL on error.
|
||||
*/
|
||||
OSSL_FN *OSSL_FN_secure_new_bytes(size_t size);
|
||||
|
||||
/**
|
||||
* Allocate an OSSL_FN in memory.
|
||||
*
|
||||
* @param[in] size The number of bits for the number itself.
|
||||
* There's an additional few bytes allocated for bookkeeping.
|
||||
* @returns an OSSL_FN instance.
|
||||
* @retval NULL on error.
|
||||
*/
|
||||
OSSL_FN *OSSL_FN_new_bits(size_t size);
|
||||
|
||||
/**
|
||||
* Allocate an OSSL_FN in secure memory.
|
||||
*
|
||||
* @param[in] size The number of bits for the number itself.
|
||||
* There's an additional few bytes allocated for bookkeeping.
|
||||
* @returns an OSSL_FN instance.
|
||||
* @retval NULL on error.
|
||||
*/
|
||||
OSSL_FN *OSSL_FN_secure_new_bits(size_t size);
|
||||
|
||||
/**
|
||||
* Free an OSSL_FN instance if it was dynamically allocated.
|
||||
* Free it securely if it was allocated securely.
|
||||
*
|
||||
* @param[in] f The OSSL_FN instance to be freed.
|
||||
*/
|
||||
void OSSL_FN_free(OSSL_FN *f);
|
||||
|
||||
/**
|
||||
* Cleanse and free an OSSL_FN instance if it was dynamically allocated.
|
||||
* Cleanse and free it securely if it was allocated securely.
|
||||
* Merely cleanse it if it was not dynamically allocated.
|
||||
*
|
||||
* @param[in] f The OSSL_FN instance to be freed.
|
||||
*/
|
||||
void OSSL_FN_clear_free(OSSL_FN *f);
|
||||
|
||||
/**
|
||||
* Cleanse the data of an OSSL_FN instance, effectively making it zero.
|
||||
*
|
||||
* @param[in] f The OSSL_FN instance to be cleared.
|
||||
*/
|
||||
void OSSL_FN_clear(OSSL_FN *f);
|
||||
|
||||
/**
|
||||
* Copy the contents of one OSSL_FN instance to another.
|
||||
*
|
||||
* @param[out] a The destination OSSL_FN
|
||||
* @param[in] b The source OSSL_FN
|
||||
* @returns 1 on success, 0 on error.
|
||||
*/
|
||||
OSSL_FN *OSSL_FN_copy(OSSL_FN *a, const OSSL_FN *b);
|
||||
|
||||
/**
|
||||
* Allocate a new OSSL_FN_CTX, given a set of input numbers.
|
||||
*
|
||||
* @param[in] libctx OpenSSL library context (currently unused)
|
||||
* @param[in] max_n_frames Maximum number of simultaneously active frames.
|
||||
* This indicates the expected depth of call stack
|
||||
* that the resulting OSSL_FN_CTX will be used in.
|
||||
* @param[in] max_n_numbers Maximum number of simultaneously active OSSL_FN.
|
||||
* @param[in] max_n_limbs Maximum number of simultaneously active OSSL_FN
|
||||
* limbs.
|
||||
* @returns An allocated OSSL_FN_CTX, or NULL on error.
|
||||
**/
|
||||
OSSL_FN_CTX *OSSL_FN_CTX_new(OSSL_LIB_CTX *libctx, size_t max_n_frames,
|
||||
size_t max_n_numbers, size_t max_n_limbs);
|
||||
/**
|
||||
* Allocate a new OSSL_FN_CTX in secure memory, given a set of input numbers.
|
||||
* Other than allocating in secure memory, this function does exactly the same
|
||||
* thing as OSSL_FN_CTX_new().
|
||||
**/
|
||||
OSSL_FN_CTX *OSSL_FN_CTX_secure_new(OSSL_LIB_CTX *libctx, size_t max_n_frames,
|
||||
size_t max_n_numbers, size_t max_n_limbs);
|
||||
/**
|
||||
* Free an OSSL_FN_CTX.
|
||||
*
|
||||
* @param[in] ctx The OSSL_FN_CTX to be freed. This may be NULL.
|
||||
*/
|
||||
void OSSL_FN_CTX_free(OSSL_FN_CTX *ctx);
|
||||
|
||||
/**
|
||||
* Start a new OSSL_FN_CTX frame. This *must* be called by any function
|
||||
* that wants to get a temporary OSSL_FN from the OSSL_FN_CTX. The function
|
||||
* call this must also clean up with a OSSL_FN_CTX_end() call.
|
||||
*
|
||||
* @param[in] ctx The OSSL_FN_CTX to start the frame in.
|
||||
* @returns 1 on success, 0 on error.
|
||||
*/
|
||||
int OSSL_FN_CTX_start(OSSL_FN_CTX *ctx);
|
||||
|
||||
/**
|
||||
* End the last OSSL_FN_CTX frame, resetting back to the previous
|
||||
* frame. If a function called OSSL_FN_CTX_start(), it *must* call
|
||||
* this function before returning.
|
||||
*
|
||||
* @param[in] ctx The OSSL_FN_CTX to start the frame in.
|
||||
* @returns 1 on success, 0 on error.
|
||||
*/
|
||||
int OSSL_FN_CTX_end(OSSL_FN_CTX *ctx);
|
||||
|
||||
/**
|
||||
* Get a suitably sized OSSL_FN from an OSSL_FN_CTX.
|
||||
*
|
||||
* @param[in] ctx The OSSL_FN_CTX
|
||||
* @param[in] limbs The desired size of the resulting OSSL_FN,
|
||||
* in number of limbs.
|
||||
* @returns an OSSL_FN pointer on success, NULL on error.
|
||||
*/
|
||||
OSSL_FN *OSSL_FN_CTX_get_limbs(OSSL_FN_CTX *ctx, size_t limbs);
|
||||
|
||||
/**
|
||||
* Get a suitably sized OSSL_FN from an OSSL_FN_CTX.
|
||||
*
|
||||
* @param[in] ctx The OSSL_FN_CTX
|
||||
* @param[in] limbs The desired size of the resulting OSSL_FN,
|
||||
* in number of bytes.
|
||||
* @returns an OSSL_FN pointer on success, NULL on error.
|
||||
*/
|
||||
OSSL_FN *OSSL_FN_CTX_get_bytes(OSSL_FN_CTX *ctx, size_t bytes);
|
||||
|
||||
/**
|
||||
* Get a suitably sized OSSL_FN from an OSSL_FN_CTX.
|
||||
*
|
||||
* @param[in] ctx The OSSL_FN_CTX
|
||||
* @param[in] limbs The desired size of the resulting OSSL_FN,
|
||||
* in number of bits.
|
||||
* @returns an OSSL_FN pointer on success, NULL on error.
|
||||
*/
|
||||
OSSL_FN *OSSL_FN_CTX_get_bits(OSSL_FN_CTX *ctx, size_t bits);
|
||||
|
||||
/*
|
||||
* Arithmetic functions treat the OSSL_FN 'd' array as a large 2's complement
|
||||
* unsigned integer, least significant limb first. All carrys or borrows are
|
||||
* extended in the result and otherwise ignored. This makes OSSL_FN functions
|
||||
* act just like operations on C unsigned integer types, but at a larger scale.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add two OSSL_FN numbers.
|
||||
*
|
||||
* @param[out] r The OSSL_FN for the result
|
||||
* @param[in] a The first operand
|
||||
* @param[in] b The second operand
|
||||
* @returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_FN_add(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b);
|
||||
|
||||
/**
|
||||
* Add an OSSL_FN_ULONG word to an OSSL_FN numbers.
|
||||
*
|
||||
* @param[in,out] a The OSSL_FN to add the word to
|
||||
* @param[in] w The OSSL_FN_ULONG word
|
||||
* @returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_FN_add_word(OSSL_FN *a, const OSSL_FN_ULONG *w);
|
||||
|
||||
/**
|
||||
* Subtract two OSSL_FN numbers.
|
||||
*
|
||||
* @param[out] r The OSSL_FN for the result
|
||||
* @param[in] a The first operand
|
||||
* @param[in] b The second operand
|
||||
* @returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_FN_sub(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b);
|
||||
|
||||
/**
|
||||
* Subtract an OSSL_FN_ULONG word from an OSSL_FN numbers.
|
||||
*
|
||||
* @param[in,out] a The OSSL_FN to subtract the word from
|
||||
* @param[in] w The OSSL_FN_ULONG word
|
||||
* @returns 1 on success, 0 on error
|
||||
*/
|
||||
int OSSL_FN_sub_word(OSSL_FN *a, const OSSL_FN_ULONG *w);
|
||||
|
||||
/**
|
||||
* Multiply two OSSL_FN numbers. Truncates the result to fit in r.
|
||||
*
|
||||
* @param[out] r The OSSL_FN for the result
|
||||
* @param[in] a The first operand
|
||||
* @param[in] b The second operand
|
||||
* @param[in] ctx A context to get temporary OSSL_FN
|
||||
* instances from.
|
||||
* @returns 1 on success, 0 on error
|
||||
*
|
||||
* @note This function currently requires that the OSSL_FN_CTX has free
|
||||
* space for one temporary OSSL_FN with res->dsize limbs, plus one frame
|
||||
* (currently 32 bytes).
|
||||
*/
|
||||
int OSSL_FN_mul(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b,
|
||||
OSSL_FN_CTX *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file A set of internal functions to manipulate the OSSL_FN d array, and
|
||||
* for introspection.
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_FN_INTERN_H
|
||||
#define OPENSSL_FN_INTERN_H
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "crypto/fn.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if OSSL_FN_BYTES == 4
|
||||
/* 32-bit systems */
|
||||
#define OSSL_FN_ULONG_C(n) UINT32_C(n)
|
||||
#define OSSL_FN_ULONG64_C(hi32, lo32) OSSL_FN_ULONG_C(lo32), OSSL_FN_ULONG_C(hi32)
|
||||
#elif OSSL_FN_BYTES == 8
|
||||
/* 64-bit systems */
|
||||
#define OSSL_FN_ULONG_C(n) UINT64_C(n)
|
||||
#define OSSL_FN_ULONG64_C(hi32, lo32) (OSSL_FN_ULONG_C(hi32) << 32 | OSSL_FN_ULONG_C(lo32))
|
||||
#else
|
||||
#error "OpenSSL doesn't support large numbers on this platform"
|
||||
#endif
|
||||
|
||||
int ossl_fn_set_words(OSSL_FN *f, const OSSL_FN_ULONG *words, size_t limbs);
|
||||
const OSSL_FN_ULONG *ossl_fn_get_words(const OSSL_FN *f);
|
||||
|
||||
size_t ossl_fn_get_dsize(const OSSL_FN *f);
|
||||
|
||||
void ossl_fn_set_negative(OSSL_FN *f, bool neg);
|
||||
|
||||
bool ossl_fn_is_negative(const OSSL_FN *f);
|
||||
bool ossl_fn_is_dynamically_allocated(const OSSL_FN *f);
|
||||
bool ossl_fn_is_securely_allocated(const OSSL_FN *f);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
#ifndef OSSL_CRYPTO_FNERR_H
|
||||
#define OSSL_CRYPTO_FNERR_H
|
||||
#pragma once
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
#include <openssl/symhacks.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int ossl_err_load_OSSL_FN_strings(void);
|
||||
|
||||
/*
|
||||
* OSSL_FN reason codes.
|
||||
*/
|
||||
#define OSSL_FN_R_RESULT_ARG_TOO_SMALL 100
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -13,10 +13,6 @@
|
||||
#define OSSL_CRYPTO_TYPES_H
|
||||
#pragma once
|
||||
|
||||
/* At some point in the future, this may move to include/openssl/types.h */
|
||||
typedef struct ossl_fn_st OSSL_FN;
|
||||
typedef struct ossl_fn_ctx_st OSSL_FN_CTX;
|
||||
|
||||
#ifdef OPENSSL_NO_DEPRECATED_3_0
|
||||
typedef struct rsa_st RSA;
|
||||
typedef struct rsa_meth_st RSA_METHOD;
|
||||
|
||||
@@ -407,7 +407,7 @@ static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
|
||||
unsigned char *p = data;
|
||||
const size_t prepend_length = SSL3_RT_HEADER_LENGTH;
|
||||
|
||||
if (length < prepend_length + EVP_GCM_TLS_TAG_LEN) {
|
||||
if (length < prepend_length) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@@ -417,17 +417,27 @@ static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
|
||||
msg.msg_controllen = sizeof(cmsgbuf.buf);
|
||||
|
||||
msg_iov.iov_base = p + prepend_length;
|
||||
msg_iov.iov_len = length - prepend_length - EVP_GCM_TLS_TAG_LEN;
|
||||
msg_iov.iov_len = length - prepend_length;
|
||||
msg.msg_iov = &msg_iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
memset(p, 0, prepend_length);
|
||||
|
||||
ret = recvmsg(fd, &msg, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ((msg.msg_flags & (MSG_EOR | MSG_CTRUNC)) != MSG_EOR) {
|
||||
errno = EMSGSIZE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (msg.msg_controllen > 0) {
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if (cmsg->cmsg_type == TLS_GET_RECORD_TYPE) {
|
||||
if (cmsg != NULL
|
||||
&& cmsg->cmsg_level == SOL_TLS
|
||||
&& cmsg->cmsg_type == TLS_GET_RECORD_TYPE
|
||||
&& cmsg->cmsg_len >= CMSG_LEN(sizeof(unsigned char))) {
|
||||
p[0] = *((unsigned char *)CMSG_DATA(cmsg));
|
||||
p[1] = TLS1_2_VERSION_MAJOR;
|
||||
p[2] = TLS1_2_VERSION_MINOR;
|
||||
|
||||
@@ -71,6 +71,11 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store,
|
||||
int ossl_method_store_remove_all_provided(OSSL_METHOD_STORE *store,
|
||||
const OSSL_PROVIDER *prov);
|
||||
|
||||
/* Frozen method store related functions */
|
||||
int ossl_method_store_freeze(OSSL_METHOD_STORE *store, const char *propq);
|
||||
int ossl_method_store_is_frozen(OSSL_METHOD_STORE *store);
|
||||
const char *ossl_method_store_frozen_propq(OSSL_METHOD_STORE *store);
|
||||
|
||||
/* Get the global properties associate with the specified library context */
|
||||
OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *ctx,
|
||||
int loadconfig);
|
||||
@@ -78,6 +83,9 @@ OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *ctx,
|
||||
/* property query cache functions */
|
||||
int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
|
||||
int nid, const char *prop_query, void **result);
|
||||
int ossl_frozen_method_store_cache_get(OSSL_METHOD_STORE *store,
|
||||
OSSL_PROVIDER *prov, int nid,
|
||||
const char *prop_query, void **result);
|
||||
int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
|
||||
int nid, const char *prop_query, void *result,
|
||||
int (*method_up_ref)(void *),
|
||||
|
||||
@@ -21,15 +21,36 @@
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <openssl/opensslconf.h>
|
||||
#include <openssl/types.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/bnerr.h>
|
||||
#include <openssl/bn_limbs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 64-bit processor with LP64 ABI
|
||||
*/
|
||||
#ifdef SIXTY_FOUR_BIT_LONG
|
||||
#define BN_ULONG unsigned long
|
||||
#define BN_BYTES 8
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 64-bit processor other than LP64 ABI
|
||||
*/
|
||||
#ifdef SIXTY_FOUR_BIT
|
||||
#define BN_ULONG unsigned long long
|
||||
#define BN_BYTES 8
|
||||
#endif
|
||||
|
||||
#ifdef THIRTY_TWO_BIT
|
||||
#define BN_ULONG unsigned int
|
||||
#define BN_BYTES 4
|
||||
#endif
|
||||
|
||||
#define BN_BITS2 (BN_BYTES * 8)
|
||||
#define BN_BITS (BN_BITS2 * 2)
|
||||
#define BN_TBIT ((BN_ULONG)1 << (BN_BITS2 - 1))
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Defines the type of large integer limbs.
|
||||
*
|
||||
* The large number is composed of words, the size of which is assumed to
|
||||
* be optimal for the platform it's built for. In many large number texts,
|
||||
* these words are called "limb". The BIGNUM library also calls this "word".
|
||||
*
|
||||
* In OpenSSL code, the BIGNUM "limb" is represented with the type macro
|
||||
* BN_ULONG.
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_BN_LIMBS_H
|
||||
#define OPENSSL_BN_LIMBS_H
|
||||
#pragma once
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
/*
|
||||
* 64-bit processor with LP64 ABI
|
||||
*/
|
||||
#ifdef SIXTY_FOUR_BIT_LONG
|
||||
#define BN_ULONG unsigned long
|
||||
#define BN_BYTES 8
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 64-bit processor other than LP64 ABI
|
||||
*/
|
||||
#ifdef SIXTY_FOUR_BIT
|
||||
#define BN_ULONG unsigned long long
|
||||
#define BN_BYTES 8
|
||||
#endif
|
||||
|
||||
#ifdef THIRTY_TWO_BIT
|
||||
#define BN_ULONG unsigned int
|
||||
#define BN_BYTES 4
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -586,6 +586,7 @@ OSSL_LIB_CTX *OSSL_LIB_CTX_get0_global_default(void);
|
||||
OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *libctx);
|
||||
int OSSL_LIB_CTX_get_conf_diagnostics(OSSL_LIB_CTX *ctx);
|
||||
void OSSL_LIB_CTX_set_conf_diagnostics(OSSL_LIB_CTX *ctx, int value);
|
||||
int OSSL_LIB_CTX_freeze(OSSL_LIB_CTX *ctx, const char *propq);
|
||||
|
||||
void OSSL_sleep(uint64_t millis);
|
||||
|
||||
|
||||
@@ -124,7 +124,6 @@ struct err_state_st {
|
||||
#define ERR_LIB_OSSL_ENCODER 59
|
||||
#define ERR_LIB_OSSL_DECODER 60
|
||||
#define ERR_LIB_HTTP 61
|
||||
#define ERR_LIB_OSSL_FN 62
|
||||
|
||||
#define ERR_LIB_USER 128
|
||||
|
||||
|
||||
@@ -60,11 +60,13 @@ ASN1_SEQUENCE(BARE_ALGOR) = {
|
||||
ASN1_SIMPLE(BARE_ALGOR, oid, ASN1_OBJECT),
|
||||
} static_ASN1_SEQUENCE_END(BARE_ALGOR)
|
||||
|
||||
ASN1_SEQUENCE(BARE_PUBKEY)
|
||||
= { ASN1_EMBED(BARE_PUBKEY, algor, BARE_ALGOR), ASN1_SIMPLE(BARE_PUBKEY, pubkey, ASN1_BIT_STRING) } static_ASN1_SEQUENCE_END(BARE_PUBKEY)
|
||||
ASN1_SEQUENCE(BARE_PUBKEY) = {
|
||||
ASN1_EMBED(BARE_PUBKEY, algor, BARE_ALGOR),
|
||||
ASN1_SIMPLE(BARE_PUBKEY, pubkey, ASN1_BIT_STRING)
|
||||
} static_ASN1_SEQUENCE_END(BARE_PUBKEY)
|
||||
#endif /* OPENSSL_NO_SLH_DSA */
|
||||
|
||||
struct der2key_ctx_st; /* Forward declaration */
|
||||
struct der2key_ctx_st; /* Forward declaration */
|
||||
typedef int check_key_fn(void *, struct der2key_ctx_st *ctx);
|
||||
typedef void adjust_key_fn(void *, struct der2key_ctx_st *ctx);
|
||||
typedef void free_key_fn(void *);
|
||||
|
||||
@@ -985,7 +985,7 @@ static void *ec_gen_init(void *provctx, int selection,
|
||||
gctx->ecdh_mode = 0;
|
||||
OSSL_FIPS_IND_INIT(gctx)
|
||||
if (!ec_gen_set_params(gctx, params)) {
|
||||
OPENSSL_free(gctx);
|
||||
ec_gen_cleanup(gctx);
|
||||
gctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,6 @@ use OpenSSL::paramnames qw(produce_param_decoder);
|
||||
)); -}
|
||||
|
||||
{- produce_param_decoder('ml_kem_gen_set_params',
|
||||
(['OSSL_PKEY_PARAM_ML_DSA_SEED', 'seed', 'octet_string'],
|
||||
(['OSSL_PKEY_PARAM_ML_KEM_SEED', 'seed', 'octet_string'],
|
||||
['OSSL_PKEY_PARAM_PROPERTIES', 'propq', 'utf8_string'],
|
||||
)); -}
|
||||
|
||||
@@ -722,6 +722,7 @@ static void *mlx_kem_dup(const void *vkey, int selection)
|
||||
if (ret->xkey == NULL)
|
||||
return ret;
|
||||
/* Fail if the source key is an inconsistent state */
|
||||
OPENSSL_free(ret->propq);
|
||||
OPENSSL_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
15
ssl/d1_lib.c
15
ssl/d1_lib.c
@@ -731,10 +731,17 @@ int DTLSv1_listen(SSL *ssl, BIO_ADDR *client)
|
||||
&wbuf[DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH - 3],
|
||||
3);
|
||||
|
||||
if (s->msg_callback)
|
||||
s->msg_callback(1, version, SSL3_RT_HEADER, wbuf,
|
||||
DTLS1_RT_HEADER_LENGTH, ssl,
|
||||
s->msg_callback_arg);
|
||||
if (s->msg_callback) {
|
||||
/* Report the outgoing DTLS record header */
|
||||
s->msg_callback(1, (int)version, SSL3_RT_HEADER,
|
||||
wbuf, DTLS1_RT_HEADER_LENGTH,
|
||||
ssl, s->msg_callback_arg);
|
||||
/* Report the HelloVerifyRequest handshake message */
|
||||
s->msg_callback(1, (int)version, SSL3_RT_HANDSHAKE,
|
||||
wbuf + DTLS1_RT_HEADER_LENGTH,
|
||||
wreclen - DTLS1_RT_HEADER_LENGTH,
|
||||
ssl, s->msg_callback_arg);
|
||||
}
|
||||
|
||||
if ((tmpclient = BIO_ADDR_new()) == NULL) {
|
||||
ERR_raise(ERR_LIB_SSL, ERR_R_BIO_LIB);
|
||||
|
||||
@@ -25,7 +25,7 @@ The number `{nn}` is (somewhat loosely) grouped as follows:
|
||||
|
||||
00-04 sanity, internal and essential API tests
|
||||
05-09 individual symmetric cipher algorithms
|
||||
10-14 math (bignum and ossl_fn)
|
||||
10-14 math (bignum)
|
||||
15-19 individual asymmetric cipher algorithms
|
||||
20-24 openssl commands (some otherwise not tested)
|
||||
25-29 certificate forms, generation and verification
|
||||
|
||||
@@ -1038,16 +1038,6 @@ IF[{- !$disabled{tests} -}]
|
||||
DEPEND[rsa_x931_test]=../libcrypto.a libtestutil.a
|
||||
ENDIF
|
||||
|
||||
PROGRAMS{noinst}=fn_internal_test
|
||||
SOURCE[fn_internal_test]=fn_internal_test.c
|
||||
INCLUDE[fn_internal_test]=.. ../include ../crypto/fn ../apps/include
|
||||
DEPEND[fn_internal_test]=../libcrypto.a libtestutil.a
|
||||
|
||||
PROGRAMS{noinst}=fn_api_test
|
||||
SOURCE[fn_api_test]=fn_api_test.c
|
||||
INCLUDE[fn_api_test]=.. ../include ../crypto/fn ../apps/include
|
||||
DEPEND[fn_api_test]=../libcrypto.a libtestutil.a
|
||||
|
||||
SOURCE[bn_internal_test]=bn_internal_test.c
|
||||
INCLUDE[bn_internal_test]=.. ../include ../crypto/bn ../apps/include
|
||||
DEPEND[bn_internal_test]=../libcrypto.a libtestutil.a
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <openssl/provider.h>
|
||||
#include "internal/sizes.h"
|
||||
#include "testutil.h"
|
||||
#include "crypto/evp.h"
|
||||
|
||||
static char *config_file = NULL;
|
||||
static char *alg = "digest";
|
||||
@@ -219,6 +220,46 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_EVP_MD_fetch_freeze(void)
|
||||
{
|
||||
EVP_MD *md = NULL;
|
||||
int ret = 0;
|
||||
OSSL_LIB_CTX *ctx = OSSL_LIB_CTX_new();
|
||||
|
||||
if (!TEST_ptr(ctx)
|
||||
|| !TEST_ptr(md = EVP_MD_fetch(ctx, "SHA256", NULL))
|
||||
|| !TEST_true(test_md(md))
|
||||
|| !TEST_int_ne(md->origin, EVP_ORIG_FROZEN))
|
||||
goto err;
|
||||
EVP_MD_free(md);
|
||||
md = NULL;
|
||||
|
||||
if (!TEST_int_eq(OSSL_LIB_CTX_freeze(ctx, "?fips=true"), 1)
|
||||
|| !TEST_ptr(md = EVP_MD_fetch(ctx, "SHA256", NULL))
|
||||
|| !TEST_true(test_md(md))
|
||||
|| !TEST_int_eq(md->origin, EVP_ORIG_FROZEN))
|
||||
goto err;
|
||||
/* Technically, frozen version doesn't need to be freed */
|
||||
EVP_MD_free(md);
|
||||
|
||||
if (!TEST_ptr(md = EVP_MD_fetch(ctx, "SHA256", "?fips=true"))
|
||||
|| !TEST_true(test_md(md))
|
||||
|| !TEST_int_eq(md->origin, EVP_ORIG_FROZEN))
|
||||
goto err;
|
||||
EVP_MD_free(md);
|
||||
|
||||
if (!TEST_ptr(md = EVP_MD_fetch(ctx, "SHA256", "?provider=default"))
|
||||
|| !TEST_true(test_md(md))
|
||||
|| !TEST_int_ne(md->origin, EVP_ORIG_FROZEN))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
OSSL_LIB_CTX_free(ctx);
|
||||
EVP_MD_free(md);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_explicit_EVP_MD_fetch_by_name(void)
|
||||
{
|
||||
return test_explicit_EVP_MD_fetch("SHA256");
|
||||
@@ -402,6 +443,7 @@ int setup_tests(void)
|
||||
}
|
||||
ADD_TEST(test_legacy_provider_unloaded);
|
||||
if (strcmp(alg, "digest") == 0) {
|
||||
ADD_TEST(test_EVP_MD_fetch_freeze);
|
||||
ADD_TEST(test_implicit_EVP_MD_fetch);
|
||||
ADD_TEST(test_explicit_EVP_MD_fetch_by_name);
|
||||
ADD_ALL_TESTS_NOSUBTEST(test_explicit_EVP_MD_fetch_by_X509_ALGOR, 2);
|
||||
|
||||
@@ -1,770 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file API tests of OSSL_FN
|
||||
*
|
||||
* This tests the OSSL_FN "public" API, i.e. anything that only requires
|
||||
* including crypto/fn.h. including crypto/fn_intern.h is included too,
|
||||
* for introspection.
|
||||
*/
|
||||
|
||||
#include <openssl/rand.h>
|
||||
#include "crypto/fn.h"
|
||||
#include "crypto/fn_intern.h"
|
||||
#include "testutil.h"
|
||||
|
||||
/*
|
||||
* Helper to pollute a number before writing to it.
|
||||
* This is a destructive function, use with care!
|
||||
*/
|
||||
static int pollute(OSSL_FN *f, size_t start, size_t end)
|
||||
{
|
||||
/* Constness deliberately violated here */
|
||||
OSSL_FN_ULONG *u = (OSSL_FN_ULONG *)ossl_fn_get_words(f);
|
||||
size_t l = ossl_fn_get_dsize(f);
|
||||
|
||||
if (end > l)
|
||||
end = l;
|
||||
if (start > end)
|
||||
start = end;
|
||||
|
||||
unsigned char tmp_char;
|
||||
(void)RAND_bytes(&tmp_char, 1);
|
||||
memset(u + start, tmp_char, sizeof(OSSL_FN_ULONG) * (end - start));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int check_limbs_value(const OSSL_FN *f, size_t start, size_t end,
|
||||
OSSL_FN_ULONG value)
|
||||
{
|
||||
const OSSL_FN_ULONG *u = ossl_fn_get_words(f);
|
||||
size_t l = ossl_fn_get_dsize(f);
|
||||
|
||||
if (end > l)
|
||||
end = l;
|
||||
if (start > end)
|
||||
start = end;
|
||||
|
||||
for (size_t i = start; i < end; i++)
|
||||
if (!TEST_size_t_eq(u[i], value)) {
|
||||
TEST_note("start = %zu, end = %zu, i = %zu\n", start, end, i);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* A set of numbers on OSSL_FN_ULONG array form */
|
||||
static const OSSL_FN_ULONG num0[] = { OSSL_FN_ULONG64_C(0x80000000, 0x00000001) };
|
||||
static const OSSL_FN_ULONG num1[] = { OSSL_FN_ULONG64_C(0x00000001, 0x80000000) };
|
||||
static const OSSL_FN_ULONG num2[] = { OSSL_FN_ULONG64_C(0x01234567, 0x89abcdef) };
|
||||
static const OSSL_FN_ULONG num3[] = { OSSL_FN_ULONG64_C(0xfedcba98, 0x76543210) };
|
||||
|
||||
/* Numbers for edge cases */
|
||||
static const OSSL_FN_ULONG num4[] = { OSSL_FN_ULONG64_C(0x00000000, 0x00000000) };
|
||||
static const OSSL_FN_ULONG num5[] = { OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff) };
|
||||
static const OSSL_FN_ULONG num6[] = {
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000000),
|
||||
OSSL_FN_ULONG64_C(0x10000000, 0x00000000),
|
||||
};
|
||||
|
||||
/*
|
||||
* For each test function using predefined numbers, set up an
|
||||
* arrays of test cases to simply run through, and call common
|
||||
* test function for the operation being tested.
|
||||
*
|
||||
* All sizes are in number of limbs, the LIMBSOF() macro is there to help
|
||||
*/
|
||||
#define LIMBSOF(num) ((sizeof(num) + OSSL_FN_BYTES - 1) / OSSL_FN_BYTES)
|
||||
struct test_case_st {
|
||||
/* Two operands and expected full result */
|
||||
const OSSL_FN_ULONG *op1;
|
||||
size_t op1_size;
|
||||
const OSSL_FN_ULONG *op2;
|
||||
size_t op2_size;
|
||||
const OSSL_FN_ULONG *ex;
|
||||
size_t ex_size;
|
||||
|
||||
/* Setup sizes for creating OSSL_FNs */
|
||||
size_t op1_live_size;
|
||||
size_t op2_live_size;
|
||||
size_t res_live_size;
|
||||
|
||||
/* Number of limbs to compare the result's OSSL_FN_ULONG array against ex */
|
||||
size_t check_size;
|
||||
|
||||
/* When the result is larger than check_size, the expected extended value */
|
||||
OSSL_FN_ULONG extended_limb_value;
|
||||
#define EXTENDED_LIMB_ZERO ((OSSL_FN_ULONG)0)
|
||||
#define EXTENDED_LIMB_MINUS_ONE ((OSSL_FN_ULONG)-1)
|
||||
};
|
||||
|
||||
static const OSSL_FN_ULONG ex_add_num0_num0[] = {
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000002),
|
||||
OSSL_FN_ULONG_C(0x1),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_add_num0_num1[] = {
|
||||
OSSL_FN_ULONG64_C(0x80000001, 0x80000001),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_add_num0_num2[] = {
|
||||
OSSL_FN_ULONG64_C(0x81234567, 0x89abcdf0),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_add_num0_num3[] = {
|
||||
OSSL_FN_ULONG64_C(0x7edcba98, 0x76543211),
|
||||
OSSL_FN_ULONG_C(0x1),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_add_num1_num1[] = {
|
||||
OSSL_FN_ULONG64_C(0x00000003, 0x00000000),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_add_num1_num2[] = {
|
||||
OSSL_FN_ULONG64_C(0x01234569, 0x09abcdef),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_add_num1_num3[] = {
|
||||
OSSL_FN_ULONG64_C(0xfedcba99, 0xf6543210),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_add_num2_num2[] = {
|
||||
OSSL_FN_ULONG64_C(0x02468acf, 0x13579bde),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_add_num2_num3[] = {
|
||||
OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_add_num3_num3[] = {
|
||||
OSSL_FN_ULONG64_C(0xfdb97530, 0xeca86420),
|
||||
OSSL_FN_ULONG_C(0x1),
|
||||
};
|
||||
|
||||
static int test_add_common(struct test_case_st test_case)
|
||||
{
|
||||
const OSSL_FN_ULONG *n1 = test_case.op1;
|
||||
size_t n1_limbs = test_case.op1_size;
|
||||
const OSSL_FN_ULONG *n2 = test_case.op2;
|
||||
size_t n2_limbs = test_case.op2_size;
|
||||
const OSSL_FN_ULONG *ex = test_case.ex;
|
||||
size_t n1_new_limbs = test_case.op1_live_size;
|
||||
size_t n2_new_limbs = test_case.op2_live_size;
|
||||
size_t res_limbs = test_case.res_live_size;
|
||||
size_t check_limbs = test_case.check_size;
|
||||
OSSL_FN_ULONG extended_value = test_case.extended_limb_value;
|
||||
int ret = 1;
|
||||
OSSL_FN *fn1 = NULL, *fn2 = NULL, *res = NULL;
|
||||
const OSSL_FN_ULONG *u = NULL;
|
||||
|
||||
/* To test that OSSL_FN_add() does a complete job, 'res' is pre-polluted */
|
||||
|
||||
if (!TEST_ptr(fn1 = OSSL_FN_new_limbs(n1_new_limbs))
|
||||
|| !TEST_ptr(fn2 = OSSL_FN_new_limbs(n2_new_limbs))
|
||||
|| !TEST_true(ossl_fn_set_words(fn1, n1, n1_limbs))
|
||||
|| !TEST_true(ossl_fn_set_words(fn2, n2, n2_limbs))
|
||||
|| !TEST_ptr(res = OSSL_FN_new_limbs(res_limbs))
|
||||
|| !TEST_true(pollute(res, 0, res_limbs))) {
|
||||
res = 0;
|
||||
/* There's no way to continue tests in this case */
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!TEST_true(OSSL_FN_add(res, fn1, fn2))
|
||||
|| !TEST_ptr(u = ossl_fn_get_words(res))
|
||||
|| !TEST_mem_eq(u, check_limbs * OSSL_FN_BYTES,
|
||||
ex, check_limbs * OSSL_FN_BYTES)
|
||||
|| !TEST_true(check_limbs_value(res, check_limbs, res_limbs,
|
||||
extended_value)))
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
OSSL_FN_free(fn1);
|
||||
OSSL_FN_free(fn2);
|
||||
OSSL_FN_free(res);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define ADD_CASE(i, op1, op2, ex) \
|
||||
{ \
|
||||
/* op1 */ op1, \
|
||||
/* op1_size */ LIMBSOF(op1), \
|
||||
/* op2 */ op2, \
|
||||
/* op2_size */ LIMBSOF(op2), \
|
||||
/* ex */ ex, \
|
||||
/* ex_size */ LIMBSOF(ex), \
|
||||
/* op1_live_size */ LIMBSOF(op1) + 1, \
|
||||
/* op2_live_size */ LIMBSOF(op2) + 2, \
|
||||
/* res_live_size */ LIMBSOF(ex) + 3, \
|
||||
/* check_size */ LIMBSOF(ex), \
|
||||
/* extended_limb_value */ EXTENDED_LIMB_ZERO, \
|
||||
}
|
||||
|
||||
static struct test_case_st test_add_cases[] = {
|
||||
ADD_CASE(1, num0, num0, ex_add_num0_num0),
|
||||
ADD_CASE(2, num0, num1, ex_add_num0_num1),
|
||||
ADD_CASE(3, num0, num2, ex_add_num0_num2),
|
||||
ADD_CASE(4, num0, num3, ex_add_num0_num3),
|
||||
ADD_CASE(5, num1, num0, ex_add_num0_num1), /* Commutativity check */
|
||||
ADD_CASE(6, num1, num1, ex_add_num1_num1),
|
||||
ADD_CASE(7, num1, num2, ex_add_num1_num2),
|
||||
ADD_CASE(8, num1, num3, ex_add_num1_num3),
|
||||
ADD_CASE(9, num2, num0, ex_add_num0_num2), /* Commutativity check */
|
||||
ADD_CASE(10, num2, num1, ex_add_num1_num2), /* Commutativity check */
|
||||
ADD_CASE(11, num2, num2, ex_add_num2_num2),
|
||||
ADD_CASE(12, num2, num3, ex_add_num2_num3),
|
||||
ADD_CASE(13, num3, num0, ex_add_num0_num3), /* Commutativity check */
|
||||
ADD_CASE(14, num3, num1, ex_add_num1_num3), /* Commutativity check */
|
||||
ADD_CASE(15, num3, num2, ex_add_num2_num3), /* Commutativity check */
|
||||
ADD_CASE(16, num3, num3, ex_add_num3_num3),
|
||||
};
|
||||
|
||||
static int test_add(int i)
|
||||
{
|
||||
return test_add_common(test_add_cases[i]);
|
||||
}
|
||||
|
||||
#define ADD_TRUNCATED_CASE(i, op1, op2, ex) \
|
||||
{ \
|
||||
/* op1 */ op1, \
|
||||
/* op1_size */ LIMBSOF(op1), \
|
||||
/* op2 */ op2, \
|
||||
/* op2_size */ LIMBSOF(op2), \
|
||||
/* ex */ ex, \
|
||||
/* ex_size */ LIMBSOF(ex), \
|
||||
/* op1_live_size */ LIMBSOF(op1) + 1, \
|
||||
/* op2_live_size */ LIMBSOF(op2) + 2, \
|
||||
/* res_live_size */ LIMBSOF(ex) - 1, \
|
||||
/* check_size */ LIMBSOF(ex) - 1, \
|
||||
/* extended_limb_value */ EXTENDED_LIMB_ZERO, \
|
||||
}
|
||||
|
||||
static struct test_case_st test_add_truncated_cases[] = {
|
||||
ADD_TRUNCATED_CASE(1, num0, num0, ex_add_num0_num0),
|
||||
ADD_TRUNCATED_CASE(2, num0, num1, ex_add_num0_num1),
|
||||
ADD_TRUNCATED_CASE(3, num0, num2, ex_add_num0_num2),
|
||||
ADD_TRUNCATED_CASE(4, num0, num3, ex_add_num0_num3),
|
||||
ADD_TRUNCATED_CASE(5, num1, num0, ex_add_num0_num1), /* Commutativity check */
|
||||
ADD_TRUNCATED_CASE(6, num1, num1, ex_add_num1_num1),
|
||||
ADD_TRUNCATED_CASE(7, num1, num2, ex_add_num1_num2),
|
||||
ADD_TRUNCATED_CASE(8, num1, num3, ex_add_num1_num3),
|
||||
ADD_TRUNCATED_CASE(9, num2, num0, ex_add_num0_num2), /* Commutativity check */
|
||||
ADD_TRUNCATED_CASE(10, num2, num1, ex_add_num1_num2), /* Commutativity check */
|
||||
ADD_TRUNCATED_CASE(11, num2, num2, ex_add_num2_num2),
|
||||
ADD_TRUNCATED_CASE(12, num2, num3, ex_add_num2_num3),
|
||||
ADD_TRUNCATED_CASE(13, num3, num0, ex_add_num0_num3), /* Commutativity check */
|
||||
ADD_TRUNCATED_CASE(14, num3, num1, ex_add_num1_num3), /* Commutativity check */
|
||||
ADD_TRUNCATED_CASE(15, num3, num2, ex_add_num2_num3), /* Commutativity check */
|
||||
ADD_TRUNCATED_CASE(16, num3, num3, ex_add_num3_num3),
|
||||
};
|
||||
|
||||
static int test_add_truncated(int i)
|
||||
{
|
||||
return test_add_common(test_add_truncated_cases[i]);
|
||||
}
|
||||
|
||||
static const OSSL_FN_ULONG ex_sub_num0_num0[] = {
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000000),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num0_num1[] = {
|
||||
OSSL_FN_ULONG64_C(0x7ffffffe, 0x80000001),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num0_num2[] = {
|
||||
OSSL_FN_ULONG64_C(0x7edcba98, 0x76543212),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num0_num3[] = {
|
||||
OSSL_FN_ULONG64_C(0x81234567, 0x89abcdf1),
|
||||
OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff)
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num1_num0[] = {
|
||||
OSSL_FN_ULONG64_C(0x80000001, 0x7fffffff),
|
||||
OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num1_num1[] = {
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000000),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num1_num2[] = {
|
||||
OSSL_FN_ULONG64_C(0xfedcba99, 0xf6543211),
|
||||
OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num1_num3[] = {
|
||||
OSSL_FN_ULONG64_C(0x01234569, 0x09abcdf0),
|
||||
OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num2_num0[] = {
|
||||
OSSL_FN_ULONG64_C(0x81234567, 0x89abcdee),
|
||||
OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num2_num1[] = {
|
||||
OSSL_FN_ULONG64_C(0x01234566, 0x09abcdef),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num2_num2[] = {
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000000),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num2_num3[] = {
|
||||
OSSL_FN_ULONG64_C(0x02468acf, 0x13579bdf),
|
||||
OSSL_FN_ULONG64_C(0xffffffff, 0xffffffff),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num3_num0[] = {
|
||||
OSSL_FN_ULONG64_C(0x7edcba98, 0x7654320f),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num3_num1[] = {
|
||||
OSSL_FN_ULONG64_C(0xfedcba96, 0xf6543210),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num3_num2[] = {
|
||||
OSSL_FN_ULONG64_C(0xfdb97530, 0xeca86421),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_sub_num3_num3[] = {
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000000),
|
||||
};
|
||||
|
||||
static int test_sub_common(struct test_case_st test_case)
|
||||
{
|
||||
const OSSL_FN_ULONG *n1 = test_case.op1;
|
||||
size_t n1_limbs = test_case.op1_size;
|
||||
const OSSL_FN_ULONG *n2 = test_case.op2;
|
||||
size_t n2_limbs = test_case.op2_size;
|
||||
const OSSL_FN_ULONG *ex = test_case.ex;
|
||||
size_t n1_new_limbs = test_case.op1_live_size;
|
||||
size_t n2_new_limbs = test_case.op2_live_size;
|
||||
size_t res_limbs = test_case.res_live_size;
|
||||
size_t check_limbs = test_case.check_size;
|
||||
OSSL_FN_ULONG extended_value = test_case.extended_limb_value;
|
||||
int ret = 1;
|
||||
OSSL_FN *fn1 = NULL, *fn2 = NULL, *res = NULL;
|
||||
const OSSL_FN_ULONG *u = NULL;
|
||||
|
||||
/* To test that OSSL_FN_sub() does a complete job, 'res' is pre-polluted */
|
||||
|
||||
if (!TEST_ptr(fn1 = OSSL_FN_new_limbs(n1_new_limbs))
|
||||
|| !TEST_ptr(fn2 = OSSL_FN_new_limbs(n2_new_limbs))
|
||||
|| !TEST_true(ossl_fn_set_words(fn1, n1, n1_limbs))
|
||||
|| !TEST_true(ossl_fn_set_words(fn2, n2, n2_limbs))
|
||||
|| !TEST_ptr(res = OSSL_FN_new_limbs(res_limbs))
|
||||
|| !TEST_true(pollute(res, 0, res_limbs))) {
|
||||
res = 0;
|
||||
/* There's no way to continue tests in this case */
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!TEST_true(OSSL_FN_sub(res, fn1, fn2))
|
||||
|| !TEST_ptr(u = ossl_fn_get_words(res))
|
||||
|| !TEST_mem_eq(u, check_limbs * OSSL_FN_BYTES,
|
||||
ex, check_limbs * OSSL_FN_BYTES)
|
||||
|| !TEST_true(check_limbs_value(res, check_limbs, res_limbs,
|
||||
extended_value)))
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
OSSL_FN_free(fn1);
|
||||
OSSL_FN_free(fn2);
|
||||
OSSL_FN_free(res);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define SUB_CASE(i, op1, op2, ex, ext) \
|
||||
{ \
|
||||
/* op1 */ op1, \
|
||||
/* op1_size */ LIMBSOF(op1), \
|
||||
/* op2 */ op2, \
|
||||
/* op2_size */ LIMBSOF(op2), \
|
||||
/* ex */ ex, \
|
||||
/* ex_size */ LIMBSOF(ex), \
|
||||
/* op1_live_size */ LIMBSOF(op1) + 1, \
|
||||
/* op2_live_size */ LIMBSOF(op2) + 2, \
|
||||
/* res_live_size */ LIMBSOF(ex) + 3, \
|
||||
/* check_size */ LIMBSOF(ex), \
|
||||
/* extended_limb_value */ (ext), \
|
||||
}
|
||||
|
||||
static struct test_case_st test_sub_cases[] = {
|
||||
SUB_CASE(1, num0, num0, ex_sub_num0_num0, EXTENDED_LIMB_ZERO),
|
||||
SUB_CASE(2, num0, num1, ex_sub_num0_num1, EXTENDED_LIMB_ZERO),
|
||||
SUB_CASE(3, num0, num2, ex_sub_num0_num2, EXTENDED_LIMB_ZERO),
|
||||
SUB_CASE(4, num0, num3, ex_sub_num0_num3, EXTENDED_LIMB_MINUS_ONE),
|
||||
SUB_CASE(5, num1, num0, ex_sub_num1_num0, EXTENDED_LIMB_MINUS_ONE),
|
||||
SUB_CASE(6, num1, num1, ex_sub_num1_num1, EXTENDED_LIMB_ZERO),
|
||||
SUB_CASE(7, num1, num2, ex_sub_num1_num2, EXTENDED_LIMB_MINUS_ONE),
|
||||
SUB_CASE(8, num1, num3, ex_sub_num1_num3, EXTENDED_LIMB_MINUS_ONE),
|
||||
SUB_CASE(9, num2, num0, ex_sub_num2_num0, EXTENDED_LIMB_MINUS_ONE),
|
||||
SUB_CASE(10, num2, num1, ex_sub_num2_num1, EXTENDED_LIMB_ZERO),
|
||||
SUB_CASE(11, num2, num2, ex_sub_num2_num2, EXTENDED_LIMB_ZERO),
|
||||
SUB_CASE(12, num2, num3, ex_sub_num2_num3, EXTENDED_LIMB_MINUS_ONE),
|
||||
SUB_CASE(13, num3, num0, ex_sub_num3_num0, EXTENDED_LIMB_ZERO),
|
||||
SUB_CASE(14, num3, num1, ex_sub_num3_num1, EXTENDED_LIMB_ZERO),
|
||||
SUB_CASE(15, num3, num2, ex_sub_num3_num2, EXTENDED_LIMB_ZERO),
|
||||
SUB_CASE(16, num3, num3, ex_sub_num3_num3, EXTENDED_LIMB_ZERO),
|
||||
};
|
||||
|
||||
static int test_sub(int i)
|
||||
{
|
||||
return test_sub_common(test_sub_cases[i]);
|
||||
}
|
||||
|
||||
#define SUB_TRUNCATED_CASE(i, op1, op2, ex) \
|
||||
{ \
|
||||
/* op1 */ op1, \
|
||||
/* op1_size */ LIMBSOF(op1), \
|
||||
/* op2 */ op2, \
|
||||
/* op2_size */ LIMBSOF(op2), \
|
||||
/* ex */ ex, \
|
||||
/* ex_size */ LIMBSOF(ex), \
|
||||
/* op1_live_size */ LIMBSOF(op1) + 1, \
|
||||
/* op2_live_size */ LIMBSOF(op2) + 2, \
|
||||
/* res_live_size */ LIMBSOF(ex) - 1, \
|
||||
/* check_size */ LIMBSOF(ex) - 1, \
|
||||
/* extended_limb_value */ EXTENDED_LIMB_ZERO, \
|
||||
}
|
||||
|
||||
static struct test_case_st test_sub_truncated_cases[] = {
|
||||
SUB_TRUNCATED_CASE(1, num0, num0, ex_sub_num0_num0),
|
||||
SUB_TRUNCATED_CASE(2, num0, num1, ex_sub_num0_num1),
|
||||
SUB_TRUNCATED_CASE(3, num0, num2, ex_sub_num0_num2),
|
||||
SUB_TRUNCATED_CASE(4, num0, num3, ex_sub_num0_num3),
|
||||
SUB_TRUNCATED_CASE(5, num1, num0, ex_sub_num1_num0),
|
||||
SUB_TRUNCATED_CASE(6, num1, num1, ex_sub_num1_num1),
|
||||
SUB_TRUNCATED_CASE(7, num1, num2, ex_sub_num1_num2),
|
||||
SUB_TRUNCATED_CASE(8, num1, num3, ex_sub_num1_num3),
|
||||
SUB_TRUNCATED_CASE(9, num2, num0, ex_sub_num2_num0),
|
||||
SUB_TRUNCATED_CASE(10, num2, num1, ex_sub_num2_num1),
|
||||
SUB_TRUNCATED_CASE(11, num2, num2, ex_sub_num2_num2),
|
||||
SUB_TRUNCATED_CASE(12, num2, num3, ex_sub_num2_num3),
|
||||
SUB_TRUNCATED_CASE(13, num3, num0, ex_sub_num3_num0),
|
||||
SUB_TRUNCATED_CASE(14, num3, num1, ex_sub_num3_num1),
|
||||
SUB_TRUNCATED_CASE(15, num3, num2, ex_sub_num3_num2),
|
||||
SUB_TRUNCATED_CASE(16, num3, num3, ex_sub_num3_num3),
|
||||
};
|
||||
|
||||
static int test_sub_truncated(int i)
|
||||
{
|
||||
return test_sub_common(test_sub_truncated_cases[i]);
|
||||
}
|
||||
|
||||
/* A set of expected results, also in OSSL_FN_ULONG array form */
|
||||
static const OSSL_FN_ULONG ex_mul_num0_num0[] = {
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000001),
|
||||
OSSL_FN_ULONG64_C(0x40000000, 0x00000001),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_mul_num0_num1[] = {
|
||||
OSSL_FN_ULONG64_C(0x00000001, 0x80000000),
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0xC0000000),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_mul_num0_num2[] = {
|
||||
OSSL_FN_ULONG64_C(0x81234567, 0x89ABCDEF),
|
||||
OSSL_FN_ULONG64_C(0x0091A2B3, 0xC4D5E6F7),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_mul_num0_num3[] = {
|
||||
OSSL_FN_ULONG64_C(0xFEDCBA98, 0x76543210),
|
||||
OSSL_FN_ULONG64_C(0x7F6E5D4C, 0x3B2A1908),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_mul_num1_num1[] = {
|
||||
OSSL_FN_ULONG64_C(0x40000000, 0x00000000),
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000002),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_mul_num1_num2[] = {
|
||||
OSSL_FN_ULONG64_C(0x4E81B4E6, 0x80000000),
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x01B4E81B),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_mul_num1_num3[] = {
|
||||
OSSL_FN_ULONG64_C(0xB17E4B18, 0x00000000),
|
||||
OSSL_FN_ULONG64_C(0x00000001, 0x7E4B17E4),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_mul_num2_num2[] = {
|
||||
OSSL_FN_ULONG64_C(0xDCA5E208, 0x90F2A521),
|
||||
OSSL_FN_ULONG64_C(0x00014B66, 0xDC33F6AC),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_mul_num2_num3[] = {
|
||||
OSSL_FN_ULONG64_C(0x2236D88F, 0xE5618CF0),
|
||||
OSSL_FN_ULONG64_C(0x0121FA00, 0xAD77D742),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_mul_num3_num3[] = {
|
||||
OSSL_FN_ULONG64_C(0xDEEC6CD7, 0xA44A4100),
|
||||
OSSL_FN_ULONG64_C(0xFDBAC097, 0xC8DC5ACC),
|
||||
};
|
||||
/* Expected results for edge cases */
|
||||
static const OSSL_FN_ULONG ex_mul_num4_num4[] = {
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000000),
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000000),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_mul_num5_num5[] = {
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000001),
|
||||
OSSL_FN_ULONG64_C(0xFFFFFFFF, 0xFFFFFFFE),
|
||||
};
|
||||
static const OSSL_FN_ULONG ex_mul_num6_num6[] = {
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000000),
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000000),
|
||||
OSSL_FN_ULONG64_C(0x00000000, 0x00000000),
|
||||
OSSL_FN_ULONG64_C(0x01000000, 0x00000000),
|
||||
};
|
||||
|
||||
static int test_mul_feature_r_is_operand(int i)
|
||||
{
|
||||
int ret = 1;
|
||||
const OSSL_FN_ULONG *a_data = num0;
|
||||
size_t a_limbs = sizeof(num0) / OSSL_FN_BYTES;
|
||||
const OSSL_FN_ULONG *b_data = num1;
|
||||
size_t b_limbs = sizeof(num1) / OSSL_FN_BYTES;
|
||||
OSSL_FN *a = NULL, *b = NULL, *res = NULL;
|
||||
|
||||
OSSL_FN_CTX *ctx = NULL;
|
||||
if (!TEST_ptr(ctx = OSSL_FN_CTX_new(NULL, 1, 1, a_limbs + b_limbs))
|
||||
|| !TEST_ptr(a = OSSL_FN_new_limbs(a_limbs))
|
||||
|| !TEST_ptr(b = OSSL_FN_new_limbs(b_limbs))
|
||||
|| !TEST_true(ossl_fn_set_words(a, a_data, a_limbs))
|
||||
|| !TEST_true(ossl_fn_set_words(b, b_data, b_limbs))) {
|
||||
ret = 0;
|
||||
/* There's no way to continue tests in this case */
|
||||
goto end;
|
||||
}
|
||||
|
||||
const OSSL_FN *op1 = NULL, *op2 = NULL;
|
||||
const OSSL_FN_ULONG *u = NULL;
|
||||
const OSSL_FN_ULONG *ex_data = NULL;
|
||||
size_t ex_limbs = 0;
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
/* a * b, result in separate OSSL_FN */
|
||||
if (!TEST_ptr(res = OSSL_FN_new_limbs(a_limbs + b_limbs))) {
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
op1 = a;
|
||||
op2 = b;
|
||||
ex_data = ex_mul_num0_num1;
|
||||
ex_limbs = ossl_fn_get_dsize(res);
|
||||
break;
|
||||
case 1:
|
||||
/* a * b, result in a */
|
||||
res = a;
|
||||
op1 = a;
|
||||
op2 = b;
|
||||
ex_data = ex_mul_num0_num1;
|
||||
ex_limbs = ossl_fn_get_dsize(res);
|
||||
break;
|
||||
case 2:
|
||||
/* a * b, result in b */
|
||||
res = b;
|
||||
op1 = a;
|
||||
op2 = b;
|
||||
ex_data = ex_mul_num0_num1;
|
||||
ex_limbs = ossl_fn_get_dsize(res);
|
||||
break;
|
||||
case 3:
|
||||
/* a * a, result in a */
|
||||
res = a;
|
||||
op1 = a;
|
||||
op2 = a;
|
||||
ex_data = ex_mul_num0_num0;
|
||||
ex_limbs = ossl_fn_get_dsize(res);
|
||||
break;
|
||||
default:
|
||||
/* Invalid call */
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!TEST_true(OSSL_FN_mul(res, op1, op2, ctx))
|
||||
|| !TEST_ptr(u = ossl_fn_get_words(res))
|
||||
|| !TEST_mem_eq(u, ex_limbs * OSSL_FN_BYTES,
|
||||
ex_data, ex_limbs * OSSL_FN_BYTES))
|
||||
ret = 0;
|
||||
|
||||
if (TEST_ptr(u = ossl_fn_get_words(a))) {
|
||||
if (res == a) {
|
||||
if (!TEST_mem_eq(u, ex_limbs * OSSL_FN_BYTES,
|
||||
ex_data, ex_limbs * OSSL_FN_BYTES))
|
||||
res = 0;
|
||||
} else {
|
||||
if (!TEST_mem_eq(u, a_limbs * OSSL_FN_BYTES,
|
||||
a_data, a_limbs * OSSL_FN_BYTES))
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (TEST_ptr(u = ossl_fn_get_words(b))) {
|
||||
if (res == b) {
|
||||
if (!TEST_mem_eq(u, ex_limbs * OSSL_FN_BYTES,
|
||||
ex_data, ex_limbs * OSSL_FN_BYTES))
|
||||
res = 0;
|
||||
} else {
|
||||
if (!TEST_mem_eq(u, b_limbs * OSSL_FN_BYTES,
|
||||
b_data, b_limbs * OSSL_FN_BYTES))
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
OSSL_FN_CTX_free(ctx);
|
||||
if (res != a && res != b)
|
||||
OSSL_FN_free(res);
|
||||
OSSL_FN_free(a);
|
||||
OSSL_FN_free(b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_mul_common(struct test_case_st test_case)
|
||||
{
|
||||
int ret = 1;
|
||||
const OSSL_FN_ULONG *n1 = test_case.op1;
|
||||
size_t n1_limbs = test_case.op1_size;
|
||||
const OSSL_FN_ULONG *n2 = test_case.op2;
|
||||
size_t n2_limbs = test_case.op2_size;
|
||||
const OSSL_FN_ULONG *ex = test_case.ex;
|
||||
size_t n1_new_limbs = test_case.op1_live_size;
|
||||
size_t n2_new_limbs = test_case.op2_live_size;
|
||||
size_t res_limbs = test_case.res_live_size;
|
||||
size_t check_limbs = test_case.check_size;
|
||||
OSSL_FN_ULONG extended_value = test_case.extended_limb_value;
|
||||
OSSL_FN *fn1 = NULL, *fn2 = NULL, *res = NULL;
|
||||
const OSSL_FN_ULONG *u = NULL;
|
||||
|
||||
OSSL_FN_CTX *ctx = NULL;
|
||||
if (!TEST_ptr(ctx = OSSL_FN_CTX_new(NULL, 1, 1, res_limbs))
|
||||
|| !TEST_ptr(fn1 = OSSL_FN_new_limbs(n1_new_limbs))
|
||||
|| !TEST_ptr(fn2 = OSSL_FN_new_limbs(n2_new_limbs))
|
||||
|| !TEST_true(ossl_fn_set_words(fn1, n1, n1_limbs))
|
||||
|| !TEST_true(ossl_fn_set_words(fn2, n2, n2_limbs))
|
||||
|| !TEST_ptr(res = OSSL_FN_new_limbs(res_limbs))) {
|
||||
res = 0;
|
||||
/* There's no way to continue tests in this case */
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* To test that OSSL_FN_mul() does a complete job, 'res' is pre-polluted */
|
||||
|
||||
if (!TEST_true(pollute(res, 0, res_limbs))
|
||||
|| !TEST_true(OSSL_FN_mul(res, fn1, fn2, ctx))
|
||||
|| !TEST_ptr(u = ossl_fn_get_words(res))
|
||||
|| !TEST_mem_eq(u, check_limbs * OSSL_FN_BYTES,
|
||||
ex, check_limbs * OSSL_FN_BYTES)
|
||||
|| !TEST_true(check_limbs_value(res, check_limbs, res_limbs,
|
||||
extended_value)))
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
OSSL_FN_CTX_free(ctx);
|
||||
OSSL_FN_free(fn1);
|
||||
OSSL_FN_free(fn2);
|
||||
OSSL_FN_free(res);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* i should be set to match the iteration number that's displayed when testing */
|
||||
#define MUL_CASE(i, op1, op2, ex) \
|
||||
{ \
|
||||
/* op1 */ op1, \
|
||||
/* op1_size */ LIMBSOF(op1), \
|
||||
/* op2 */ op2, \
|
||||
/* op2_size */ LIMBSOF(op2), \
|
||||
/* ex */ ex, \
|
||||
/* ex_size */ LIMBSOF(ex), \
|
||||
/* op1_live_size */ LIMBSOF(op1) + 1, \
|
||||
/* op2_live_size */ LIMBSOF(op2) + 2, \
|
||||
/* res_live_size */ LIMBSOF(op1) + LIMBSOF(op2) + ((i - 1) % 4), \
|
||||
/* check_size */ LIMBSOF(ex), \
|
||||
/* extended_limb_value */ EXTENDED_LIMB_ZERO, \
|
||||
}
|
||||
|
||||
static struct test_case_st test_mul_cases[] = {
|
||||
MUL_CASE(1, num0, num0, ex_mul_num0_num0),
|
||||
MUL_CASE(2, num0, num1, ex_mul_num0_num1),
|
||||
MUL_CASE(3, num0, num2, ex_mul_num0_num2),
|
||||
MUL_CASE(4, num0, num3, ex_mul_num0_num3),
|
||||
MUL_CASE(5, num1, num0, ex_mul_num0_num1), /* Commutativity check */
|
||||
MUL_CASE(6, num1, num1, ex_mul_num1_num1),
|
||||
MUL_CASE(7, num1, num2, ex_mul_num1_num2),
|
||||
MUL_CASE(8, num1, num3, ex_mul_num1_num3),
|
||||
MUL_CASE(9, num2, num0, ex_mul_num0_num2), /* Commutativity check */
|
||||
MUL_CASE(10, num2, num1, ex_mul_num1_num2), /* Commutativity check */
|
||||
MUL_CASE(11, num2, num2, ex_mul_num2_num2),
|
||||
MUL_CASE(12, num2, num3, ex_mul_num2_num3),
|
||||
MUL_CASE(13, num3, num0, ex_mul_num0_num3), /* Commutativity check */
|
||||
MUL_CASE(14, num3, num1, ex_mul_num1_num3), /* Commutativity check */
|
||||
MUL_CASE(15, num3, num2, ex_mul_num2_num3), /* Commutativity check */
|
||||
MUL_CASE(16, num3, num3, ex_mul_num3_num3),
|
||||
|
||||
/* Edge cases */
|
||||
MUL_CASE(17, num4, num4, ex_mul_num4_num4),
|
||||
MUL_CASE(18, num5, num5, ex_mul_num5_num5),
|
||||
MUL_CASE(19, num6, num6, ex_mul_num6_num6),
|
||||
};
|
||||
|
||||
static int test_mul(int i)
|
||||
{
|
||||
return test_mul_common(test_mul_cases[i]);
|
||||
}
|
||||
|
||||
/* i should be set to match the iteration number that's displayed when testing */
|
||||
#define MUL_TRUNCATED_CASE(i, op1, op2, ex) \
|
||||
{ \
|
||||
/* op1 */ op1, \
|
||||
/* op1_size */ LIMBSOF(op1), \
|
||||
/* op2 */ op2, \
|
||||
/* op2_size */ LIMBSOF(op2), \
|
||||
/* ex */ ex, \
|
||||
/* ex_size */ LIMBSOF(ex), \
|
||||
/* op1_live_size */ LIMBSOF(op1) + 1, \
|
||||
/* op2_live_size */ LIMBSOF(op2) + 2, \
|
||||
/* res_live_size */ LIMBSOF(ex) / 2, \
|
||||
/* check_size */ LIMBSOF(ex) / 2, \
|
||||
/* extended_limb_value */ EXTENDED_LIMB_ZERO, \
|
||||
}
|
||||
/* A special case, where the truncation is set to the size of ex minus 64 bits */
|
||||
#define MUL_TRUNCATED_SPECIAL_CASE1(i, op1, op2, ex) \
|
||||
{ \
|
||||
/* op1 */ op1, \
|
||||
/* op1_size */ LIMBSOF(op1), \
|
||||
/* op2 */ op2, \
|
||||
/* op2_size */ LIMBSOF(op2), \
|
||||
/* ex */ ex, \
|
||||
/* ex_size */ LIMBSOF(ex), \
|
||||
/* op1_live_size */ LIMBSOF(op1) + 1, \
|
||||
/* op2_live_size */ LIMBSOF(op2) + 2, \
|
||||
/* res_live_size */ LIMBSOF(ex) - 8 / OSSL_FN_BYTES, \
|
||||
/* check_size */ LIMBSOF(ex) - 8 / OSSL_FN_BYTES, \
|
||||
/* extended_limb_value */ EXTENDED_LIMB_ZERO, \
|
||||
}
|
||||
|
||||
static struct test_case_st test_mul_truncate_cases[] = {
|
||||
MUL_TRUNCATED_CASE(1, num0, num0, ex_mul_num0_num0),
|
||||
MUL_TRUNCATED_CASE(2, num0, num1, ex_mul_num0_num1),
|
||||
MUL_TRUNCATED_CASE(3, num0, num2, ex_mul_num0_num2),
|
||||
MUL_TRUNCATED_CASE(4, num0, num3, ex_mul_num0_num3),
|
||||
MUL_TRUNCATED_CASE(5, num1, num0, ex_mul_num0_num1), /* Commutativity check */
|
||||
MUL_TRUNCATED_CASE(6, num1, num1, ex_mul_num1_num1),
|
||||
MUL_TRUNCATED_CASE(7, num1, num2, ex_mul_num1_num2),
|
||||
MUL_TRUNCATED_CASE(8, num1, num3, ex_mul_num1_num3),
|
||||
MUL_TRUNCATED_CASE(9, num2, num0, ex_mul_num0_num2), /* Commutativity check */
|
||||
MUL_TRUNCATED_CASE(10, num2, num1, ex_mul_num1_num2), /* Commutativity check */
|
||||
MUL_TRUNCATED_CASE(11, num2, num2, ex_mul_num2_num2),
|
||||
MUL_TRUNCATED_CASE(12, num2, num3, ex_mul_num2_num3),
|
||||
MUL_TRUNCATED_CASE(13, num3, num0, ex_mul_num0_num3), /* Commutativity check */
|
||||
MUL_TRUNCATED_CASE(14, num3, num1, ex_mul_num1_num3), /* Commutativity check */
|
||||
MUL_TRUNCATED_CASE(15, num3, num2, ex_mul_num2_num3), /* Commutativity check */
|
||||
MUL_TRUNCATED_CASE(16, num3, num3, ex_mul_num3_num3),
|
||||
|
||||
/* Edge cases */
|
||||
MUL_TRUNCATED_CASE(17, num4, num4, ex_mul_num4_num4),
|
||||
MUL_TRUNCATED_CASE(18, num5, num5, ex_mul_num5_num5),
|
||||
MUL_TRUNCATED_SPECIAL_CASE1(19, num6, num6, ex_mul_num6_num6),
|
||||
};
|
||||
|
||||
static int test_mul_truncated(int i)
|
||||
{
|
||||
return test_mul_common(test_mul_truncate_cases[i]);
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
ADD_ALL_TESTS(test_add, 16);
|
||||
ADD_ALL_TESTS(test_add_truncated, 16);
|
||||
ADD_ALL_TESTS(test_sub, 16);
|
||||
ADD_ALL_TESTS(test_sub_truncated, 16);
|
||||
ADD_ALL_TESTS(test_mul_feature_r_is_operand, 4);
|
||||
ADD_ALL_TESTS(test_mul, OSSL_NELEM(test_mul_cases));
|
||||
ADD_ALL_TESTS(test_mul_truncated, OSSL_NELEM(test_mul_truncate_cases));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1,215 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Internal tests of OSSL_FN
|
||||
*
|
||||
* This tests OSSL_FN internals only, i.e. anything that requires including
|
||||
* ../crypto/fn/fn_local.h, such as introspection.
|
||||
*/
|
||||
|
||||
#include "crypto/fn.h"
|
||||
#include "crypto/fn_intern.h"
|
||||
#include "fn_local.h"
|
||||
#include "testutil.h"
|
||||
|
||||
static int test_struct(void)
|
||||
{
|
||||
TEST_note("OSSL_FN struct is %zu bytes\n", sizeof(OSSL_FN));
|
||||
TEST_note("OSSL_FN 'd' array starts at offset %zu\n", offsetof(OSSL_FN, d));
|
||||
|
||||
/*
|
||||
* Note: The working theory for the moment is that the 'd' array *must*
|
||||
* align with the end of the OSSL_FN struct.
|
||||
* If it turns out that this isn't the case, we can choose to run
|
||||
* TEST_size_t_eq() for display purposes, but ignore its result and
|
||||
* return 1.
|
||||
*/
|
||||
return TEST_size_t_eq(sizeof(OSSL_FN), offsetof(OSSL_FN, d));
|
||||
}
|
||||
|
||||
static int test_alloc(void)
|
||||
{
|
||||
int ret = 1;
|
||||
OSSL_FN *f = NULL;
|
||||
const OSSL_FN_ULONG *u = NULL;
|
||||
|
||||
/*
|
||||
* OSSL_FN_new_bits() calls OSSL_FN_new_bytes(), which calls
|
||||
* OSSL_FN_new_limbs(), so we're exercising all three in one go.
|
||||
*
|
||||
* The curious size formula is there to check that the number of bits that
|
||||
* is passed in gets properly rounded up to the number of limbs they fit
|
||||
* into.
|
||||
* This formula aims for two limbs (each of which is at least 32 bits),
|
||||
* shaving off 17 bits for demonstration purposes.
|
||||
*/
|
||||
if (!TEST_ptr(f = OSSL_FN_new_bits(sizeof(OSSL_FN_ULONG) * 16 - 17))
|
||||
|| !TEST_true(ossl_fn_is_dynamically_allocated(f))
|
||||
|| !TEST_false(ossl_fn_is_securely_allocated(f))
|
||||
|| !TEST_size_t_eq(ossl_fn_get_dsize(f), 2)
|
||||
|| !TEST_ptr(u = ossl_fn_get_words(f))
|
||||
|| !TEST_size_t_eq(u[0], 0)
|
||||
|| !TEST_size_t_eq(u[1], 0))
|
||||
ret = 0;
|
||||
OSSL_FN_free(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_secure_alloc(void)
|
||||
{
|
||||
int ret = 1;
|
||||
OSSL_FN *f = NULL;
|
||||
const OSSL_FN_ULONG *u = NULL;
|
||||
|
||||
/*
|
||||
* OSSL_FN_secure_new_bits() calls OSSL_FN_secure_new_bytes(), which calls
|
||||
* OSSL_FN_secure_new_limbs(), so we're exercising all three in one go.
|
||||
*
|
||||
* The curious size formula is there to check that the number of bits that
|
||||
* is passed in gets properly rounded up to the number of limbs they fit
|
||||
* into.
|
||||
* This formula aims for two limbs (each of which is at least 32 bits),
|
||||
* shaving off 17 bits for demonstration purposes.
|
||||
*/
|
||||
if (!TEST_ptr(f = OSSL_FN_secure_new_bits(sizeof(OSSL_FN_ULONG) * 16 - 17))
|
||||
|| !TEST_true(ossl_fn_is_dynamically_allocated(f))
|
||||
|| !TEST_true(ossl_fn_is_securely_allocated(f))
|
||||
|| !TEST_size_t_eq(ossl_fn_get_dsize(f), 2)
|
||||
|| !TEST_ptr(u = ossl_fn_get_words(f))
|
||||
|| !TEST_size_t_eq(u[0], 0)
|
||||
|| !TEST_size_t_eq(u[1], 0))
|
||||
ret = 0;
|
||||
OSSL_FN_free(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_ctx(void)
|
||||
{
|
||||
int ret = 1;
|
||||
OSSL_FN_CTX *ctx = NULL;
|
||||
OSSL_FN *f = NULL;
|
||||
|
||||
/*
|
||||
* Make a CTX that is likely to contain two 2048-bit or one 4096-bit OSSL_FN
|
||||
* and one frame (let's overestimate its size to 128 bytes).
|
||||
* Note that OSSL_FN_CTX_new() takes a size in bytes, so we must ensure that
|
||||
* we get that number right.
|
||||
*/
|
||||
if (!TEST_ptr(ctx = OSSL_FN_CTX_new(NULL, 1, 2, 4096 / 8 / OSSL_FN_BYTES))) {
|
||||
ret = 0;
|
||||
/* It's pointless to try more tests after this failure */
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Check that we can get 1 2048-bit OSSL_FN instance, and check its metadata */
|
||||
if (!TEST_true(OSSL_FN_CTX_start(ctx))) {
|
||||
ret = 0;
|
||||
/* It's pointless to try more tests after this failure */
|
||||
goto end;
|
||||
}
|
||||
if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048))
|
||||
|| !TEST_true(ossl_fn_is_dynamically_allocated(f))
|
||||
|| !TEST_false(ossl_fn_is_securely_allocated(f)))
|
||||
ret = 0;
|
||||
if (!TEST_true(OSSL_FN_CTX_end(ctx))) {
|
||||
ret = 0;
|
||||
/* It's pointless to try more tests after this failure */
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Check that we can get 2 2048-bit OSSL_FN instances, but not 3 */
|
||||
if (!TEST_true(OSSL_FN_CTX_start(ctx))) {
|
||||
ret = 0;
|
||||
/* It's pointless to try more tests after this failure */
|
||||
goto end;
|
||||
}
|
||||
if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048))
|
||||
|| !TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048))
|
||||
|| !TEST_ptr_null(f = OSSL_FN_CTX_get_bits(ctx, 2048)))
|
||||
ret = 0;
|
||||
if (!TEST_true(OSSL_FN_CTX_end(ctx))) {
|
||||
ret = 0;
|
||||
/* It's pointless to try more tests after this failure */
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Check that we can get 1 4096-bit OSSL_FN instance, but not 2 */
|
||||
if (!TEST_true(OSSL_FN_CTX_start(ctx))) {
|
||||
ret = 0;
|
||||
/* It's pointless to try more tests after this failure */
|
||||
goto end;
|
||||
}
|
||||
if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 4096))
|
||||
|| !TEST_ptr_null(f = OSSL_FN_CTX_get_bits(ctx, 2048)))
|
||||
ret = 0;
|
||||
if (!TEST_true(OSSL_FN_CTX_end(ctx))) {
|
||||
ret = 0;
|
||||
/* It's pointless to try more tests after this failure */
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
OSSL_FN_CTX_free(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_secure_ctx(void)
|
||||
{
|
||||
int ret = 1;
|
||||
OSSL_FN_CTX *ctx = NULL;
|
||||
OSSL_FN *f = NULL;
|
||||
|
||||
/*
|
||||
* Make a CTX that is likely to contain two 2048-bit OSSL_FN and one frame
|
||||
* (let's overestimate its size to 128 bytes).
|
||||
* Note that OSSL_FN_CTX_new() takes a size in bytes, so we must ensure that
|
||||
* we get that number right.
|
||||
*/
|
||||
if (!TEST_ptr(ctx = OSSL_FN_CTX_secure_new(NULL, 1, 2, 2048 / 8 / OSSL_FN_BYTES))) {
|
||||
ret = 0;
|
||||
/* It's pointless to try more tests after this failure */
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Check that we can get 1 2048-bit OSSL_FN instance, and check its metadata */
|
||||
if (!TEST_true(OSSL_FN_CTX_start(ctx))) {
|
||||
ret = 0;
|
||||
/* It's pointless to try more tests after this failure */
|
||||
goto end;
|
||||
}
|
||||
if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048))
|
||||
|| !TEST_true(ossl_fn_is_dynamically_allocated(f))
|
||||
|| !TEST_true(ossl_fn_is_securely_allocated(f)))
|
||||
ret = 0;
|
||||
if (!TEST_true(OSSL_FN_CTX_end(ctx))) {
|
||||
ret = 0;
|
||||
/* It's pointless to try more tests after this failure */
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
OSSL_FN_CTX_free(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
ADD_TEST(test_struct);
|
||||
ADD_TEST(test_alloc);
|
||||
ADD_TEST(test_secure_alloc);
|
||||
ADD_TEST(test_ctx);
|
||||
ADD_TEST(test_secure_ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -417,6 +417,41 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_freeze_flag(void)
|
||||
{
|
||||
int ret = 0, nid = 6;
|
||||
const char *prop = "position=1", *prop2 = "position=2";
|
||||
char *impl = "a", *impl2 = "b";
|
||||
OSSL_METHOD_STORE *store;
|
||||
OSSL_PROVIDER prov = { 1 };
|
||||
const OSSL_PROVIDER *fetched_prov = NULL;
|
||||
void *fetched_meth = NULL;
|
||||
|
||||
if (!TEST_ptr(store = ossl_method_store_new(NULL))
|
||||
|| !TEST_true(add_property_names("position", NULL))
|
||||
|| !TEST_true(ossl_method_store_add(store, &prov, nid, prop, impl, &up_ref, &down_ref))
|
||||
|| !TEST_true(ossl_method_store_fetch(store, nid, prop, &fetched_prov, &fetched_meth))
|
||||
|| !TEST_ptr_eq(&prov, fetched_prov)
|
||||
|| !TEST_str_eq((char *)fetched_meth, impl)
|
||||
|| !TEST_true(ossl_method_store_freeze(store, NULL))
|
||||
|| !TEST_false(ossl_method_store_remove(store, nid, impl))
|
||||
|| !TEST_true(ossl_method_store_fetch(store, nid, prop, &fetched_prov, &fetched_meth))
|
||||
|| !TEST_ptr_eq(&prov, fetched_prov)
|
||||
|| !TEST_str_eq((char *)fetched_meth, impl)
|
||||
|| !TEST_false(ossl_method_store_remove_all_provided(store, fetched_prov))
|
||||
|| !TEST_true(ossl_method_store_fetch(store, nid, prop, &fetched_prov, &fetched_meth))
|
||||
|| !TEST_ptr_eq(&prov, fetched_prov)
|
||||
|| !TEST_str_eq((char *)fetched_meth, impl)
|
||||
|| !TEST_false(ossl_method_store_add(store, &prov, nid, prop2, impl2, &up_ref, &down_ref))
|
||||
|| !TEST_false(ossl_method_store_freeze(store, NULL)))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
ossl_method_store_free(store);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_property(void)
|
||||
{
|
||||
static OSSL_PROVIDER fake_provider1 = { 1 };
|
||||
@@ -713,6 +748,7 @@ int setup_tests(void)
|
||||
ADD_TEST(test_property_defn_cache);
|
||||
ADD_ALL_TESTS(test_definition_compares, OSSL_NELEM(definition_tests));
|
||||
ADD_TEST(test_register_deregister);
|
||||
ADD_TEST(test_freeze_flag);
|
||||
ADD_TEST(test_property);
|
||||
ADD_TEST(test_query_cache_stochastic);
|
||||
ADD_TEST(test_fips_mode);
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License 2.0 (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
|
||||
|
||||
use strict;
|
||||
use OpenSSL::Test; # get 'plan'
|
||||
use OpenSSL::Test::Simple;
|
||||
use OpenSSL::Test::Utils;
|
||||
|
||||
setup("test_internal_fn");
|
||||
|
||||
plan skip_all => "This test is unsupported in a shared library build on Windows"
|
||||
if $^O eq 'MSWin32' && !disabled("shared");
|
||||
|
||||
simple_test("test_internal_fn", "fn_internal_test");
|
||||
@@ -1,19 +0,0 @@
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License 2.0 (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
|
||||
|
||||
use strict;
|
||||
use OpenSSL::Test; # get 'plan'
|
||||
use OpenSSL::Test::Simple;
|
||||
use OpenSSL::Test::Utils;
|
||||
|
||||
setup("test_fn_api");
|
||||
|
||||
plan skip_all => "This test is unsupported in a shared library build on Windows"
|
||||
if $^O eq 'MSWin32' && !disabled("shared");
|
||||
|
||||
simple_test("test_fn_api", "fn_api_test");
|
||||
@@ -5815,3 +5815,4 @@ OSSL_PARAM_clear_free ? 4_0_0 EXIST::FUNCTION:
|
||||
CMS_dataFinal_ex ? 4_0_0 EXIST::FUNCTION:CMS
|
||||
CMS_SignerInfo_verify_ex ? 4_0_0 EXIST::FUNCTION:CMS
|
||||
EVP_SIGNATURE_has_message_update ? 4_0_0 EXIST::FUNCTION:
|
||||
OSSL_LIB_CTX_freeze ? 4_0_0 EXIST::FUNCTION:
|
||||
|
||||
Reference in New Issue
Block a user