Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for signed BIGNUMs in the OSSL_PARAM APIs #17162

Closed
wants to merge 9 commits into from
52 changes: 39 additions & 13 deletions crypto/param_build.c
Expand Up @@ -192,23 +192,20 @@ int OSSL_PARAM_BLD_push_double(OSSL_PARAM_BLD *bld, const char *key,
return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_REAL);
}

int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key,
const BIGNUM *bn)
{
return OSSL_PARAM_BLD_push_BN_pad(bld, key, bn,
bn == NULL ? 0 : BN_num_bytes(bn));
}

int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
const BIGNUM *bn, size_t sz)
static int push_BN(OSSL_PARAM_BLD *bld, const char *key,
const BIGNUM *bn, size_t sz, int type)
{
int n, secure = 0;
OSSL_PARAM_BLD_DEF *pd;

if (!ossl_assert(type == OSSL_PARAM_UNSIGNED_INTEGER
|| type == OSSL_PARAM_INTEGER))
return 0;

if (bn != NULL) {
if (BN_is_negative(bn)) {
if (type == OSSL_PARAM_UNSIGNED_INTEGER && BN_is_negative(bn)) {
ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_UNSUPPORTED,
"Negative big numbers are unsupported for OSSL_PARAM");
"Negative big numbers are unsupported for OSSL_PARAM_UNSIGNED_INTEGER");
return 0;
}

Expand All @@ -224,13 +221,39 @@ int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
if (BN_get_flags(bn, BN_FLG_SECURE) == BN_FLG_SECURE)
secure = 1;
}
pd = param_push(bld, key, sz, sz, OSSL_PARAM_UNSIGNED_INTEGER, secure);
pd = param_push(bld, key, sz, sz, type, secure);
if (pd == NULL)
return 0;
pd->bn = bn;
return 1;
}

int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key,
const BIGNUM *bn)
{
return push_BN(bld, key, bn, bn == NULL ? 0 : BN_num_bytes(bn),
OSSL_PARAM_UNSIGNED_INTEGER);
}

int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
const BIGNUM *bn, size_t sz)
{
return push_BN(bld, key, bn, sz, OSSL_PARAM_UNSIGNED_INTEGER);
}

int OSSL_PARAM_BLD_push_signed_BN(OSSL_PARAM_BLD *bld, const char *key,
levitte marked this conversation as resolved.
Show resolved Hide resolved
const BIGNUM *bn)
{
return push_BN(bld, key, bn, bn == NULL ? 0 : BN_num_bytes(bn) + 1,
OSSL_PARAM_INTEGER);
}

int OSSL_PARAM_BLD_push_signed_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
const BIGNUM *bn, size_t sz)
{
return push_BN(bld, key, bn, sz, OSSL_PARAM_INTEGER);
}

int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
const char *buf, size_t bsize)
{
Expand Down Expand Up @@ -328,7 +351,10 @@ static OSSL_PARAM *param_bld_convert(OSSL_PARAM_BLD *bld, OSSL_PARAM *param,
param[i].data = p;
if (pd->bn != NULL) {
/* BIGNUM */
BN_bn2nativepad(pd->bn, (unsigned char *)p, pd->size);
if (pd->type == OSSL_PARAM_UNSIGNED_INTEGER)
BN_bn2nativepad(pd->bn, (unsigned char *)p, pd->size);
else
BN_signed_bn2native(pd->bn, (unsigned char *)p, pd->size);
} else if (pd->type == OSSL_PARAM_OCTET_PTR
|| pd->type == OSSL_PARAM_UTF8_PTR) {
/* PTR */
Expand Down
28 changes: 28 additions & 0 deletions crypto/param_build_set.c
Expand Up @@ -83,6 +83,22 @@ int ossl_param_build_set_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
return 1;
}

int ossl_param_build_set_signed_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *key, const BIGNUM *bn,
size_t sz)
{
if (bld != NULL)
return OSSL_PARAM_BLD_push_signed_BN(bld, key, bn);
p = OSSL_PARAM_locate(p, key);
if (p != NULL) {
if (sz > p->data_size)
return 0;
p->data_size = sz;
return OSSL_PARAM_set_BN(p, bn);
}
return 1;
}

int ossl_param_build_set_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *key, const BIGNUM *bn)
{
Expand All @@ -95,6 +111,18 @@ int ossl_param_build_set_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
return 1;
}

int ossl_param_build_set_signed_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *key, const BIGNUM *bn)
{
if (bld != NULL)
return OSSL_PARAM_BLD_push_signed_BN(bld, key, bn);

p = OSSL_PARAM_locate(p, key);
if (p != NULL)
return OSSL_PARAM_set_BN(p, bn) > 0;
return 1;
}

int ossl_param_build_set_multi_key_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *params,
const char *names[],
STACK_OF(BIGNUM_const) *stk)
Expand Down
57 changes: 38 additions & 19 deletions crypto/params.c
Expand Up @@ -1018,24 +1018,32 @@ OSSL_PARAM OSSL_PARAM_construct_time_t(const char *key, time_t *buf)

int OSSL_PARAM_get_BN(const OSSL_PARAM *p, BIGNUM **val)
{
BIGNUM *b;
BIGNUM *b = NULL;

if (val == NULL || p == NULL) {
err_null_argument;
return 0;
}
if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER) {

switch (p->data_type) {
case OSSL_PARAM_UNSIGNED_INTEGER:
b = BN_native2bn(p->data, (int)p->data_size, *val);
break;
case OSSL_PARAM_INTEGER:
b = BN_signed_native2bn(p->data, (int)p->data_size, *val);
break;
default:
err_bad_type;
return 0;
break;
}

b = BN_native2bn(p->data, (int)p->data_size, *val);
if (b != NULL) {
*val = b;
return 1;
if (b == NULL) {
ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;
}
ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;

*val = b;
return 1;
}

int OSSL_PARAM_set_BN(OSSL_PARAM *p, const BIGNUM *val)
Expand All @@ -1051,26 +1059,37 @@ int OSSL_PARAM_set_BN(OSSL_PARAM *p, const BIGNUM *val)
err_null_argument;
return 0;
}
if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER) {
if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && BN_is_negative(val)) {
err_bad_type;
return 0;
}

/* For the moment, only positive values are permitted */
if (BN_is_negative(val)) {
err_unsigned_negative;
return 0;
}

bytes = (size_t)BN_num_bytes(val);
/* We add 1 byte for signed numbers, to make space for a sign extension */
if (p->data_type == OSSL_PARAM_INTEGER)
bytes++;

p->return_size = bytes;
if (p->data == NULL)
return 1;
if (p->data_size >= bytes) {
p->return_size = p->data_size;
if (BN_bn2nativepad(val, p->data, p->data_size) >= 0)
return 1;
ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_INTEGER_OVERFLOW);

switch (p->data_type) {
case OSSL_PARAM_UNSIGNED_INTEGER:
if (BN_bn2nativepad(val, p->data, p->data_size) >= 0)
return 1;
ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_INTEGER_OVERFLOW);
break;
case OSSL_PARAM_INTEGER:
if (BN_signed_bn2native(val, p->data, p->data_size) >= 0)
return 1;
ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_INTEGER_OVERFLOW);
break;
default:
err_bad_type;
break;
}
return 0;
}
err_too_small;
Expand Down
27 changes: 25 additions & 2 deletions doc/man3/OSSL_PARAM_BLD.pod
Expand Up @@ -10,6 +10,7 @@ OSSL_PARAM_BLD_push_uint32, OSSL_PARAM_BLD_push_int64,
OSSL_PARAM_BLD_push_uint64, OSSL_PARAM_BLD_push_size_t,
OSSL_PARAM_BLD_push_time_t, OSSL_PARAM_BLD_push_double,
OSSL_PARAM_BLD_push_BN, OSSL_PARAM_BLD_push_BN_pad,
OSSL_PARAM_BLD_push_signed_BN, OSSL_PARAM_BLD_push_signed_BN_pad,
OSSL_PARAM_BLD_push_utf8_string, OSSL_PARAM_BLD_push_utf8_ptr,
OSSL_PARAM_BLD_push_octet_string, OSSL_PARAM_BLD_push_octet_ptr
- functions to assist in the creation of OSSL_PARAM arrays
Expand All @@ -32,6 +33,10 @@ OSSL_PARAM_BLD_push_octet_string, OSSL_PARAM_BLD_push_octet_ptr
const BIGNUM *bn);
int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
const BIGNUM *bn, size_t sz);
int OSSL_PARAM_BLD_push_signed_BN(OSSL_PARAM_BLD *bld, const char *key,
const BIGNUM *bn);
levitte marked this conversation as resolved.
Show resolved Hide resolved
int OSSL_PARAM_BLD_push_signed_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
const BIGNUM *bn, size_t sz);

int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
const char *buf, size_t bsize);
Expand Down Expand Up @@ -89,6 +94,22 @@ will also be securely allocated.
The I<bn> argument is stored by reference and the underlying BIGNUM object
must exist until after OSSL_PARAM_BLD_to_param() has been called.

OSSL_PARAM_BLD_push_signed_BN() is a function that will create an OSSL_PARAM
object that holds the specified BIGNUM I<bn>.
If I<bn> is marked as being securely allocated, its OSSL_PARAM representation
will also be securely allocated.
The I<bn> argument is stored by reference and the underlying BIGNUM object
must exist until after OSSL_PARAM_BLD_to_param() has been called.

OSSL_PARAM_BLD_push_signed_BN_pad() is a function that will create an OSSL_PARAM
object that holds the specified BIGNUM I<bn>.
The object will be padded to occupy exactly I<sz> bytes, if insufficient space
is specified an error results.
If I<bn> is marked as being securely allocated, its OSSL_PARAM representation
will also be securely allocated.
The I<bn> argument is stored by reference and the underlying BIGNUM object
must exist until after OSSL_PARAM_BLD_to_param() has been called.

OSSL_PARAM_BLD_push_utf8_string() is a function that will create an OSSL_PARAM
object that references the UTF8 string specified by I<buf>.
The length of the string I<bsize> should not include the terminating NUL byte.
Expand Down Expand Up @@ -126,8 +147,10 @@ on error.

=head1 NOTES

OSSL_PARAM_BLD_push_BN() and OSSL_PARAM_BLD_push_BN_pad() currently only
support nonnegative B<BIGNUM>s. They return an error on negative B<BIGNUM>s.
OSSL_PARAM_BLD_push_BN() and OSSL_PARAM_BLD_push_BN_pad() only
support nonnegative B<BIGNUM>s. They return an error on negative
B<BIGNUM>s.
To pass signed B<BIGNUM>s, use OSSL_PARAM_BLD_push_signed_BN().

=head1 EXAMPLES

Expand Down
9 changes: 4 additions & 5 deletions doc/man3/OSSL_PARAM_int.pod
Expand Up @@ -331,11 +331,10 @@ representable by the target type or parameter.
Apart from that, the functions must be used appropriately for the
expected type of the parameter.

OSSL_PARAM_get_BN() and OSSL_PARAM_set_BN() currently only support
nonnegative B<BIGNUM>s, and by consequence, only
B<OSSL_PARAM_UNSIGNED_INTEGER>. OSSL_PARAM_construct_BN() currently
constructs an B<OSSL_PARAM> structure with the data type
B<OSSL_PARAM_UNSIGNED_INTEGER>.
OSSL_PARAM_get_BN() and OSSL_PARAM_set_BN() only support nonnegative
B<BIGNUM>s when the desired data type is B<OSSL_PARAM_UNSIGNED_INTEGER>.
OSSL_PARAM_construct_BN() currently constructs an B<OSSL_PARAM> structure
with the data type B<OSSL_PARAM_UNSIGNED_INTEGER>.

For OSSL_PARAM_construct_utf8_ptr() and OSSL_PARAM_consstruct_octet_ptr(),
I<bsize> is not relevant if the purpose is to send the B<OSSL_PARAM> array
Expand Down
5 changes: 5 additions & 0 deletions include/internal/param_build_set.h
Expand Up @@ -39,6 +39,11 @@ int ossl_param_build_set_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *key, const BIGNUM *bn);
int ossl_param_build_set_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *key, const BIGNUM *bn, size_t sz);
int ossl_param_build_set_signed_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *key, const BIGNUM *bn);
int ossl_param_build_set_signed_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *key, const BIGNUM *bn,
size_t sz);
int ossl_param_build_set_multi_key_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *names[],
STACK_OF(BIGNUM_const) *stk);
Expand Down
4 changes: 4 additions & 0 deletions include/openssl/param_build.h
Expand Up @@ -48,6 +48,10 @@ int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key,
const BIGNUM *bn);
int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
const BIGNUM *bn, size_t sz);
int OSSL_PARAM_BLD_push_signed_BN(OSSL_PARAM_BLD *bld, const char *key,
const BIGNUM *bn);
int OSSL_PARAM_BLD_push_signed_BN_pad(OSSL_PARAM_BLD *bld, const char *key,
const BIGNUM *bn, size_t sz);
int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
const char *buf, size_t bsize);
int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key,
Expand Down