Add support for signed BIGNUMs in the OSSL_PARAM API
authorRichard Levitte <levitte@openssl.org>
Thu, 25 Nov 2021 17:45:50 +0000 (18:45 +0100)
committerRichard Levitte <levitte@openssl.org>
Wed, 26 Jan 2022 20:35:39 +0000 (21:35 +0100)
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17162)

crypto/params.c
doc/man3/OSSL_PARAM_int.pod

index cf86eea3c76bc237edd67f7276c07b5de0709659..a1a04a6b4d2f53cc86a2e1a5bdb9685c0d8a1969 100644 (file)
@@ -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)
@@ -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;
index 9e03ec4ddccab1c8bae5028a333302c55d91ace1..290855e676a488e21817f07582c1e1bdc4754663 100644 (file)
@@ -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