Add EVP_PKEY_gettable_params support for accessing EVP_PKEY key data fields
[openssl.git] / test / evp_pkey_provided_test.c
index 6ba61c3cdaee271e6b3fe9bf603246202e38d9b0..9f8d0086f7b587644fa927895a3b85b974de1e2f 100644 (file)
@@ -7,6 +7,7 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include <string.h> /* memset */
 #include <openssl/evp.h>
 #include <openssl/pem.h>
 #include <openssl/serializer.h>
@@ -260,7 +261,7 @@ static int test_print_key_using_serializer(const char *alg, const EVP_PKEY *pk)
 
 static int test_fromdata_rsa(void)
 {
-    int ret = 0;
+    int ret = 0, i;
     EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL;
     EVP_PKEY *pk = NULL, *copy_pk = NULL;
     /*
@@ -283,13 +284,15 @@ static int test_fromdata_rsa(void)
         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_N, &key_numbers[N]),
         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_E, &key_numbers[E]),
         OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_D, &key_numbers[D]),
-        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR, &key_numbers[P]),
-        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR, &key_numbers[Q]),
-        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT, &key_numbers[DP]),
-        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT, &key_numbers[DQ]),
-        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_COEFFICIENT, &key_numbers[QINV]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR1, &key_numbers[P]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR2, &key_numbers[Q]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT1, &key_numbers[DP]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT2, &key_numbers[DQ]),
+        OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_COEFFICIENT1, &key_numbers[QINV]),
         OSSL_PARAM_END
     };
+    BIGNUM *bn = BN_new();
+    BIGNUM *bn_from = BN_new();
 
     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)))
         goto err;
@@ -315,10 +318,17 @@ static int test_fromdata_rsa(void)
         || !TEST_false(EVP_PKEY_copy_parameters(copy_pk, pk)))
         goto err;
 
+    for (i = 0; fromdata_params[i].key != NULL; ++i) {
+        if (!TEST_true(BN_set_word(bn_from, key_numbers[i]))
+            || !TEST_true(EVP_PKEY_get_bn_param(pk, fromdata_params[i].key, &bn))
+            || !TEST_BN_eq(bn, bn_from))
+            goto err;
+    }
     ret = test_print_key_using_pem("RSA", pk)
           && test_print_key_using_serializer("RSA", pk);
-
  err:
+    BN_free(bn_from);
+    BN_free(bn);
     EVP_PKEY_free(pk);
     EVP_PKEY_free(copy_pk);
     EVP_PKEY_CTX_free(key_ctx);
@@ -327,6 +337,59 @@ static int test_fromdata_rsa(void)
     return ret;
 }
 
+static int test_evp_pkey_get_bn_param_large(void)
+{
+    int ret = 0;
+    EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL;
+    EVP_PKEY *pk = NULL;
+    OSSL_PARAM_BLD *bld = NULL;
+    OSSL_PARAM *fromdata_params = NULL;
+    BIGNUM *n = NULL, *e = NULL, *d = NULL, *n_out = NULL;
+    /*
+     * The buffer size chosen here for n_data larger than the buffer used
+     * internally in EVP_PKEY_get_bn_param.
+     */
+    static unsigned char n_data[2050];
+    static const unsigned char e_data[] = {
+        0x1, 0x00, 0x01
+    };
+    static const unsigned char d_data[]= {
+       0x99, 0x33, 0x13, 0x7b
+    };
+
+    /* N is a large buffer */
+    memset(n_data, 0xCE, sizeof(n_data));
+
+    if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
+        || !TEST_ptr(n = BN_bin2bn(n_data, sizeof(n_data), NULL))
+        || !TEST_ptr(e = BN_bin2bn(e_data, sizeof(e_data), NULL))
+        || !TEST_ptr(d = BN_bin2bn(d_data, sizeof(d_data), NULL))
+        || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, n))
+        || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, e))
+        || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_D, d))
+        || !TEST_ptr(fromdata_params = OSSL_PARAM_BLD_to_param(bld))
+        || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL))
+        || !TEST_true(EVP_PKEY_key_fromdata_init(ctx))
+        || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
+        || !TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pk, ""))
+        || !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_RSA_N, &n_out))
+        || !TEST_BN_eq(n, n_out))
+        goto err;
+    ret = 1;
+ err:
+    BN_free(n_out);
+    BN_free(n);
+    BN_free(e);
+    BN_free(d);
+    EVP_PKEY_free(pk);
+    EVP_PKEY_CTX_free(key_ctx);
+    EVP_PKEY_CTX_free(ctx);
+    OSSL_PARAM_BLD_free_params(fromdata_params);
+    OSSL_PARAM_BLD_free(bld);
+    return ret;
+}
+
+
 #ifndef OPENSSL_NO_DH
 /* Array indexes used in test_fromdata_dh */
 #define PRIV_KEY        0
@@ -412,6 +475,9 @@ static int test_fromdata_ecx(int tst)
     EVP_PKEY_CTX *ctx = NULL;
     EVP_PKEY *pk = NULL, *copy_pk = NULL;
     const char *alg = NULL;
+    size_t len;
+    unsigned char out_pub[ED448_KEYLEN];
+    unsigned char out_priv[ED448_KEYLEN];
 
     /* ED448_KEYLEN > X448_KEYLEN > X25519_KEYLEN == ED25519_KEYLEN */
     static unsigned char key_numbers[4][2][ED448_KEYLEN] = {
@@ -580,6 +646,20 @@ static int test_fromdata_ecx(int tst)
         || !TEST_false(EVP_PKEY_copy_parameters(copy_pk, pk)))
         goto err;
 
+    if (!TEST_true(EVP_PKEY_get_octet_string_param(
+                       pk, fromdata_params[PRIV_KEY].key,
+                       out_priv, sizeof(out_priv), &len))
+        || !TEST_mem_eq(out_priv, len,
+                        fromdata_params[PRIV_KEY].data,
+                        fromdata_params[PRIV_KEY].data_size)
+        || !TEST_true(EVP_PKEY_get_octet_string_param(
+                          pk, fromdata_params[PUB_KEY].key,
+                          out_pub, sizeof(out_pub), &len))
+        || !TEST_mem_eq(out_pub, len,
+                        fromdata_params[PUB_KEY].data,
+                        fromdata_params[PUB_KEY].data_size))
+        goto err;
+
     ret = test_print_key_using_pem(alg, pk)
           && test_print_key_using_serializer(alg, pk);
 
@@ -591,6 +671,8 @@ err:
     return ret;
 }
 
+#define CURVE_NAME 2
+
 static int test_fromdata_ec(void)
 {
     int ret = 0;
@@ -598,10 +680,13 @@ static int test_fromdata_ec(void)
     EVP_PKEY *pk = NULL, *copy_pk = NULL;
     OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
     BIGNUM *ec_priv_bn = NULL;
+    BIGNUM *bn_priv = NULL;
     OSSL_PARAM *fromdata_params = NULL;
     const char *alg = "EC";
+    const char *curve = "prime256v1";
+    /* UNCOMPRESSED FORMAT */
     static const unsigned char ec_pub_keydata[] = {
-       0x04,
+       POINT_CONVERSION_UNCOMPRESSED,
        0x1b, 0x93, 0x67, 0x55, 0x1c, 0x55, 0x9f, 0x63,
        0xd1, 0x22, 0xa4, 0xd8, 0xd1, 0x0a, 0x60, 0x6d,
        0x02, 0xa5, 0x77, 0x57, 0xc8, 0xa3, 0x47, 0x73,
@@ -617,6 +702,12 @@ static int test_fromdata_ec(void)
         0xcc, 0x0d, 0x9a, 0x24, 0x6c, 0x86, 0x1b, 0x2e,
         0xdc, 0x4b, 0x4d, 0x35, 0x43, 0xe1, 0x1b, 0xad
     };
+    const int compressed_sz = 1 + (sizeof(ec_pub_keydata) - 1) / 2;
+    unsigned char out_pub[sizeof(ec_pub_keydata)];
+    char out_curve_name[80];
+    const OSSL_PARAM *gettable = NULL;
+    size_t len;
+
 
     if (!TEST_ptr(bld))
         goto err;
@@ -625,7 +716,7 @@ static int test_fromdata_ec(void)
         goto err;
 
     if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_NAME,
-                                        "prime256v1", 0) <= 0)
+                                        curve, 0) <= 0)
         goto err;
     if (OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY,
                                          ec_pub_keydata,
@@ -650,9 +741,30 @@ static int test_fromdata_ec(void)
         || !TEST_true(EVP_PKEY_copy_parameters(copy_pk, pk)))
         goto err;
 
+    if (!TEST_ptr(gettable = EVP_PKEY_gettable_params(pk))
+        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_EC_NAME))
+        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_PUB_KEY))
+        || !TEST_ptr(OSSL_PARAM_locate_const(gettable, OSSL_PKEY_PARAM_PRIV_KEY)))
+        goto err;
+
+    if (!EVP_PKEY_get_utf8_string_param(pk, OSSL_PKEY_PARAM_EC_NAME,
+                                        out_curve_name, sizeof(out_curve_name),
+                                        &len)
+        || !TEST_str_eq(out_curve_name, curve)
+        || !EVP_PKEY_get_octet_string_param(pk, OSSL_PKEY_PARAM_PUB_KEY,
+                                            out_pub, sizeof(out_pub), &len)
+        || !TEST_true(out_pub[0] == (POINT_CONVERSION_COMPRESSED + 1))
+        || !TEST_mem_eq(out_pub + 1, len - 1,
+                        ec_pub_keydata + 1, compressed_sz - 1)
+        || !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_PRIV_KEY,
+                                            &bn_priv))
+        || !TEST_BN_eq(ec_priv_bn, bn_priv))
+        goto err;
+
     ret = test_print_key_using_pem(alg, pk)
           && test_print_key_using_serializer(alg, pk);
 err:
+    BN_free(bn_priv);
     BN_free(ec_priv_bn);
     OSSL_PARAM_BLD_free_params(fromdata_params);
     OSSL_PARAM_BLD_free(bld);
@@ -674,6 +786,7 @@ int setup_tests(void)
     if (!TEST_ptr(datadir = test_get_argument(0)))
         return 0;
 
+    ADD_TEST(test_evp_pkey_get_bn_param_large);
     ADD_TEST(test_fromdata_rsa);
 #ifndef OPENSSL_NO_DH
     ADD_TEST(test_fromdata_dh);