openssl/test/evp_pkey_provided_test.c
Nicola Tuveri a16e86683e Honor OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT as set and default to UNCOMPRESSED
Originally the code to im/export the EC pubkey was meant to be consumed
only by the im/export functions when crossing the provider boundary.
Having our providers exporting to a COMPRESSED format octet string made
sense to avoid memory waste, as it wasn't exposed outside the provider
API, and providers had all tools available to convert across the three
formats.

Later on, with #13139 deprecating the `EC_KEY_*` functions, more state
was added among the params imported/exported on an EC provider-native
key (including `OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT`, although it
did not affect the format used to export `OSSL_PKEY_PARAM_PUB_KEY`).

Finally, in #14800, `EVP_PKEY_todata()` was introduced and prominently
exposed directly to users outside the provider API, and the choice of
COMPRESSED over UNCOMPRESSED as the default became less sensible in
light of usability, given the latter is more often needed by
applications and protocols.

This commit fixes it, by using `EC_KEY_get_conv_form()` to get the
point format from the internal state (an `EC_KEY` under the hood) of the
provider-side object, and using it on
`EVP_PKEY_export()`/`EVP_PKEY_todata()` to format
`OSSL_PKEY_PARAM_PUB_KEY`.
The default for an `EC_KEY` was already UNCOMPRESSED, and it is altered
if the user sets `OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT` via
`EVP_PKEY_fromdata()`, `EVP_PKEY_set_params()`, or one of the
more specialized methods.

For symmetry, this commit also alters `ec_pkey_export_to()` in
`crypto/ec/ec_ameth.c`, part of the `EVP_PKEY_ASN1_METHOD` for legacy EC
keys: it exclusively used COMPRESSED format, and now it honors the
conversion format specified in the EC_KEY object being exported to a
provider when this function is called.

Expand documentation about `OSSL_PKEY_PARAM_PUB_KEY` and mention the
3.1 change in behavior for our providers.

Fixes #16595

Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19681)

(cherry picked from commit 926db476bc)
2022-11-29 16:03:04 +01:00

1782 lines
69 KiB
C

/*
* Copyright 2019-2022 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 <string.h> /* memset */
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/encoder.h>
#include <openssl/provider.h>
#include <openssl/param_build.h>
#include <openssl/core_names.h>
#include <openssl/sha.h>
#include "crypto/ecx.h"
#include "crypto/evp.h" /* For the internal API */
#include "crypto/bn_dh.h" /* _bignum_ffdhe2048_p */
#include "internal/nelem.h"
#include "testutil.h"
static char *datadir = NULL;
/*
* Do not change the order of the following defines unless you also
* update the for loop bounds used inside test_print_key_using_encoder() and
* test_print_key_using_encoder_public().
*/
#define PRIV_TEXT 0
#define PRIV_PEM 1
#define PRIV_DER 2
#define PUB_TEXT 3
#define PUB_PEM 4
#define PUB_DER 5
static void stripcr(char *buf, size_t *len)
{
size_t i;
char *curr, *writ;
for (i = *len, curr = buf, writ = buf; i > 0; i--, curr++) {
if (*curr == '\r') {
(*len)--;
continue;
}
if (curr != writ)
*writ = *curr;
writ++;
}
}
static int compare_with_file(const char *alg, int type, BIO *membio)
{
char filename[80];
BIO *file = NULL;
char buf[4096];
char *memdata, *fullfile = NULL;
const char *suffix;
size_t readbytes;
int ret = 0;
int len;
size_t slen;
switch (type) {
case PRIV_TEXT:
suffix = "priv.txt";
break;
case PRIV_PEM:
suffix = "priv.pem";
break;
case PRIV_DER:
suffix = "priv.der";
break;
case PUB_TEXT:
suffix = "pub.txt";
break;
case PUB_PEM:
suffix = "pub.pem";
break;
case PUB_DER:
suffix = "pub.der";
break;
default:
TEST_error("Invalid file type");
goto err;
}
BIO_snprintf(filename, sizeof(filename), "%s.%s", alg, suffix);
fullfile = test_mk_file_path(datadir, filename);
if (!TEST_ptr(fullfile))
goto err;
file = BIO_new_file(fullfile, "rb");
if (!TEST_ptr(file))
goto err;
if (!TEST_true(BIO_read_ex(file, buf, sizeof(buf), &readbytes))
|| !TEST_true(BIO_eof(file))
|| !TEST_size_t_lt(readbytes, sizeof(buf)))
goto err;
len = BIO_get_mem_data(membio, &memdata);
if (!TEST_int_gt(len, 0))
goto err;
slen = len;
if (type != PRIV_DER && type != PUB_DER) {
stripcr(memdata, &slen);
stripcr(buf, &readbytes);
}
if (!TEST_mem_eq(memdata, slen, buf, readbytes))
goto err;
ret = 1;
err:
OPENSSL_free(fullfile);
(void)BIO_reset(membio);
BIO_free(file);
return ret;
}
static int pass_cb(char *buf, int size, int rwflag, void *u)
{
return 0;
}
static int pass_cb_error(char *buf, int size, int rwflag, void *u)
{
return -1;
}
static int test_print_key_using_pem(const char *alg, const EVP_PKEY *pk)
{
BIO *membio = BIO_new(BIO_s_mem());
int ret = 0;
if (!TEST_ptr(membio))
goto err;
if (/* Output Encrypted private key in PEM form */
!TEST_true(PEM_write_bio_PrivateKey(bio_out, pk, EVP_aes_256_cbc(),
(unsigned char *)"pass", 4,
NULL, NULL))
/* Output zero-length passphrase encrypted private key in PEM form */
|| !TEST_true(PEM_write_bio_PKCS8PrivateKey(bio_out, pk,
EVP_aes_256_cbc(),
(const char *)~0, 0,
NULL, NULL))
|| !TEST_true(PEM_write_bio_PKCS8PrivateKey(bio_out, pk,
EVP_aes_256_cbc(),
NULL, 0, NULL, ""))
|| !TEST_true(PEM_write_bio_PKCS8PrivateKey(bio_out, pk,
EVP_aes_256_cbc(),
NULL, 0, pass_cb, NULL))
|| !TEST_false(PEM_write_bio_PKCS8PrivateKey(bio_out, pk,
EVP_aes_256_cbc(),
NULL, 0, pass_cb_error,
NULL))
#ifndef OPENSSL_NO_DES
|| !TEST_true(PEM_write_bio_PKCS8PrivateKey_nid(
bio_out, pk, NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
(const char *)~0, 0, NULL, NULL))
|| !TEST_true(PEM_write_bio_PKCS8PrivateKey_nid(
bio_out, pk, NID_pbe_WithSHA1And3_Key_TripleDES_CBC, NULL, 0,
NULL, ""))
|| !TEST_true(PEM_write_bio_PKCS8PrivateKey_nid(
bio_out, pk, NID_pbe_WithSHA1And3_Key_TripleDES_CBC, NULL, 0,
pass_cb, NULL))
|| !TEST_false(PEM_write_bio_PKCS8PrivateKey_nid(
bio_out, pk, NID_pbe_WithSHA1And3_Key_TripleDES_CBC, NULL, 0,
pass_cb_error, NULL))
#endif
/* Private key in text form */
|| !TEST_int_gt(EVP_PKEY_print_private(membio, pk, 0, NULL), 0)
|| !TEST_true(compare_with_file(alg, PRIV_TEXT, membio))
/* Public key in PEM form */
|| !TEST_true(PEM_write_bio_PUBKEY(membio, pk))
|| !TEST_true(compare_with_file(alg, PUB_PEM, membio))
/* Unencrypted private key in PEM form */
|| !TEST_true(PEM_write_bio_PrivateKey(membio, pk,
NULL, NULL, 0, NULL, NULL))
|| !TEST_true(compare_with_file(alg, PRIV_PEM, membio))
/* NULL key */
|| !TEST_false(PEM_write_bio_PrivateKey(membio, NULL,
NULL, NULL, 0, NULL, NULL))
|| !TEST_false(PEM_write_bio_PrivateKey_traditional(membio, NULL,
NULL, NULL, 0, NULL, NULL)))
goto err;
ret = 1;
err:
BIO_free(membio);
return ret;
}
static int test_print_key_type_using_encoder(const char *alg, int type,
const EVP_PKEY *pk)
{
const char *output_type, *output_structure;
int selection;
OSSL_ENCODER_CTX *ctx = NULL;
BIO *membio = BIO_new(BIO_s_mem());
int ret = 0;
switch (type) {
case PRIV_TEXT:
output_type = "TEXT";
output_structure = NULL;
selection = OSSL_KEYMGMT_SELECT_KEYPAIR
| OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
break;
case PRIV_PEM:
output_type = "PEM";
output_structure = "PrivateKeyInfo";
selection = OSSL_KEYMGMT_SELECT_KEYPAIR
| OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
break;
case PRIV_DER:
output_type = "DER";
output_structure = "PrivateKeyInfo";
selection = OSSL_KEYMGMT_SELECT_KEYPAIR
| OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
break;
case PUB_TEXT:
output_type = "TEXT";
output_structure = NULL;
selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY
| OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
break;
case PUB_PEM:
output_type = "PEM";
output_structure = "SubjectPublicKeyInfo";
selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY
| OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
break;
case PUB_DER:
output_type = "DER";
output_structure = "SubjectPublicKeyInfo";
selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY
| OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
break;
default:
TEST_error("Invalid encoding type");
goto err;
}
if (!TEST_ptr(membio))
goto err;
/* Make a context, it's valid for several prints */
TEST_note("Setting up a OSSL_ENCODER context with passphrase");
if (!TEST_ptr(ctx = OSSL_ENCODER_CTX_new_for_pkey(pk, selection,
output_type,
output_structure,
NULL))
/* Check that this operation is supported */
|| !TEST_int_ne(OSSL_ENCODER_CTX_get_num_encoders(ctx), 0))
goto err;
/* Use no cipher. This should give us an unencrypted PEM */
TEST_note("Testing with no encryption");
if (!TEST_true(OSSL_ENCODER_to_bio(ctx, membio))
|| !TEST_true(compare_with_file(alg, type, membio)))
goto err;
if (type == PRIV_PEM) {
/* Set a passphrase to be used later */
if (!TEST_true(OSSL_ENCODER_CTX_set_passphrase(ctx,
(unsigned char *)"pass",
4)))
goto err;
/* Use a valid cipher name */
TEST_note("Displaying PEM encrypted with AES-256-CBC");
if (!TEST_true(OSSL_ENCODER_CTX_set_cipher(ctx, "AES-256-CBC", NULL))
|| !TEST_true(OSSL_ENCODER_to_bio(ctx, bio_out)))
goto err;
/* Use an invalid cipher name, which should generate no output */
TEST_note("NOT Displaying PEM encrypted with (invalid) FOO");
if (!TEST_false(OSSL_ENCODER_CTX_set_cipher(ctx, "FOO", NULL))
|| !TEST_false(OSSL_ENCODER_to_bio(ctx, bio_out)))
goto err;
/* Clear the cipher. This should give us an unencrypted PEM again */
TEST_note("Testing with encryption cleared (no encryption)");
if (!TEST_true(OSSL_ENCODER_CTX_set_cipher(ctx, NULL, NULL))
|| !TEST_true(OSSL_ENCODER_to_bio(ctx, membio))
|| !TEST_true(compare_with_file(alg, type, membio)))
goto err;
}
ret = 1;
err:
BIO_free(membio);
OSSL_ENCODER_CTX_free(ctx);
return ret;
}
static int test_print_key_using_encoder(const char *alg, const EVP_PKEY *pk)
{
int i;
int ret = 1;
for (i = PRIV_TEXT; i <= PUB_DER; i++)
ret = ret && test_print_key_type_using_encoder(alg, i, pk);
return ret;
}
#ifndef OPENSSL_NO_EC
static int test_print_key_using_encoder_public(const char *alg,
const EVP_PKEY *pk)
{
int i;
int ret = 1;
for (i = PUB_TEXT; i <= PUB_DER; i++)
ret = ret && test_print_key_type_using_encoder(alg, i, pk);
return ret;
}
#endif
/* Array indexes used in test_fromdata_rsa */
#define N 0
#define E 1
#define D 2
#define P 3
#define Q 4
#define DP 5
#define DQ 6
#define QINV 7
static int test_fromdata_rsa(void)
{
int ret = 0, i;
EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL;
EVP_PKEY *pk = NULL, *copy_pk = NULL, *dup_pk = NULL;
/*
* 32-bit RSA key, extracted from this command,
* executed with OpenSSL 1.0.2:
*
* openssl genrsa 32 | openssl rsa -text
*/
static unsigned long key_numbers[] = {
0xbc747fc5, /* N */
0x10001, /* E */
0x7b133399, /* D */
0xe963, /* P */
0xceb7, /* Q */
0x8599, /* DP */
0xbd87, /* DQ */
0xcc3b, /* QINV */
};
OSSL_PARAM fromdata_params[] = {
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_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;
if (!TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
|| !TEST_int_eq(EVP_PKEY_fromdata(ctx, &pk, EVP_PKEY_KEYPAIR,
fromdata_params), 1))
goto err;
while (dup_pk == NULL) {
ret = 0;
if (!TEST_int_eq(EVP_PKEY_get_bits(pk), 32)
|| !TEST_int_eq(EVP_PKEY_get_security_bits(pk), 8)
|| !TEST_int_eq(EVP_PKEY_get_size(pk), 4)
|| !TEST_false(EVP_PKEY_missing_parameters(pk)))
goto err;
EVP_PKEY_CTX_free(key_ctx);
if (!TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pk, "")))
goto err;
if (!TEST_int_gt(EVP_PKEY_check(key_ctx), 0)
|| !TEST_int_gt(EVP_PKEY_public_check(key_ctx), 0)
|| !TEST_int_gt(EVP_PKEY_private_check(key_ctx), 0)
|| !TEST_int_gt(EVP_PKEY_pairwise_check(key_ctx), 0))
goto err;
/* EVP_PKEY_copy_parameters() should fail for RSA */
if (!TEST_ptr(copy_pk = EVP_PKEY_new())
|| !TEST_false(EVP_PKEY_copy_parameters(copy_pk, pk)))
goto err;
EVP_PKEY_free(copy_pk);
copy_pk = NULL;
ret = test_print_key_using_pem("RSA", pk)
&& test_print_key_using_encoder("RSA", pk);
if (!ret || !TEST_ptr(dup_pk = EVP_PKEY_dup(pk)))
goto err;
ret = ret && TEST_int_eq(EVP_PKEY_eq(pk, dup_pk), 1);
EVP_PKEY_free(pk);
pk = dup_pk;
if (!ret)
goto err;
}
err:
/* for better diagnostics always compare key params */
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))
ret = 0;
}
BN_free(bn_from);
BN_free(bn);
EVP_PKEY_free(pk);
EVP_PKEY_free(copy_pk);
EVP_PKEY_CTX_free(key_ctx);
EVP_PKEY_CTX_free(ctx);
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_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
|| !TEST_int_eq(EVP_PKEY_fromdata(ctx, &pk, EVP_PKEY_KEYPAIR,
fromdata_params), 1)
|| !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_free(fromdata_params);
OSSL_PARAM_BLD_free(bld);
return ret;
}
#ifndef OPENSSL_NO_DH
static int test_fromdata_dh_named_group(void)
{
int ret = 0;
int gindex = 0, pcounter = 0, hindex = 0;
EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL;
EVP_PKEY *pk = NULL, *copy_pk = NULL, *dup_pk = NULL;
size_t len;
BIGNUM *pub = NULL, *priv = NULL;
BIGNUM *pub_out = NULL, *priv_out = NULL;
BIGNUM *p = NULL, *q = NULL, *g = NULL, *j = NULL;
OSSL_PARAM *fromdata_params = NULL;
OSSL_PARAM_BLD *bld = NULL;
char name_out[80];
unsigned char seed_out[32];
/*
* DH key data was generated using the following:
* openssl genpkey -algorithm DH -pkeyopt group:ffdhe2048
* -pkeyopt priv_len:224 -text
*/
static const unsigned char priv_data[] = {
0x88, 0x85, 0xe7, 0x9f, 0xee, 0x6d, 0xc5, 0x7c, 0x78, 0xaf, 0x63, 0x5d,
0x38, 0x2a, 0xd0, 0xed, 0x56, 0x4b, 0x47, 0x21, 0x2b, 0xfa, 0x55, 0xfa,
0x87, 0xe8, 0xa9, 0x7b,
};
static const unsigned char pub_data[] = {
0x00, 0xd6, 0x2d, 0x77, 0xe0, 0xd3, 0x7d, 0xf8, 0xeb, 0x98, 0x50, 0xa1,
0x82, 0x22, 0x65, 0xd5, 0xd9, 0xfe, 0xc9, 0x3f, 0xbe, 0x16, 0x83, 0xbd,
0x33, 0xe9, 0xc6, 0x93, 0xcf, 0x08, 0xaf, 0x83, 0xfa, 0x80, 0x8a, 0x6c,
0x64, 0xdf, 0x70, 0x64, 0xd5, 0x0a, 0x7c, 0x5a, 0x72, 0xda, 0x66, 0xe6,
0xf9, 0xf5, 0x31, 0x21, 0x92, 0xb0, 0x60, 0x1a, 0xb5, 0xd3, 0xf0, 0xa5,
0xfa, 0x48, 0x95, 0x2e, 0x38, 0xd9, 0xc5, 0xe6, 0xda, 0xfb, 0x6c, 0x03,
0x9d, 0x4b, 0x69, 0xb7, 0x95, 0xe4, 0x5c, 0xc0, 0x93, 0x4f, 0x48, 0xd9,
0x7e, 0x06, 0x22, 0xb2, 0xde, 0xf3, 0x79, 0x24, 0xed, 0xe1, 0xd1, 0x4a,
0x57, 0xf1, 0x40, 0x86, 0x70, 0x42, 0x25, 0xc5, 0x27, 0x68, 0xc9, 0xfa,
0xe5, 0x8e, 0x62, 0x7e, 0xff, 0x49, 0x6c, 0x5b, 0xb5, 0xba, 0xf9, 0xef,
0x9a, 0x1a, 0x10, 0xd4, 0x81, 0x53, 0xcf, 0x83, 0x04, 0x18, 0x1c, 0xe1,
0xdb, 0xe1, 0x65, 0xa9, 0x7f, 0xe1, 0x33, 0xeb, 0xc3, 0x4f, 0xe3, 0xb7,
0x22, 0xf7, 0x1c, 0x09, 0x4f, 0xed, 0xc6, 0x07, 0x8e, 0x78, 0x05, 0x8f,
0x7c, 0x96, 0xd9, 0x12, 0xe0, 0x81, 0x74, 0x1a, 0xe9, 0x13, 0xc0, 0x20,
0x82, 0x65, 0xbb, 0x42, 0x3b, 0xed, 0x08, 0x6a, 0x84, 0x4f, 0xea, 0x77,
0x14, 0x32, 0xf9, 0xed, 0xc2, 0x12, 0xd6, 0xc5, 0xc6, 0xb3, 0xe5, 0xf2,
0x6e, 0xf6, 0x16, 0x7f, 0x37, 0xde, 0xbc, 0x09, 0xc7, 0x06, 0x6b, 0x12,
0xbc, 0xad, 0x2d, 0x49, 0x25, 0xd5, 0xdc, 0xf4, 0x18, 0x14, 0xd2, 0xf0,
0xf1, 0x1d, 0x1f, 0x3a, 0xaa, 0x15, 0x55, 0xbb, 0x0d, 0x7f, 0xbe, 0x67,
0xa1, 0xa7, 0xf0, 0xaa, 0xb3, 0xfb, 0x41, 0x82, 0x39, 0x49, 0x93, 0xbc,
0xa8, 0xee, 0x72, 0x13, 0x45, 0x65, 0x15, 0x42, 0x17, 0xaa, 0xd8, 0xab,
0xcf, 0x33, 0x42, 0x83, 0x42
};
static const char group_name[] = "ffdhe2048";
static const long priv_len = 224;
if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
|| !TEST_ptr(pub = BN_bin2bn(pub_data, sizeof(pub_data), NULL))
|| !TEST_ptr(priv = BN_bin2bn(priv_data, sizeof(priv_data), NULL))
|| !TEST_true(OSSL_PARAM_BLD_push_utf8_string(bld,
OSSL_PKEY_PARAM_GROUP_NAME,
group_name, 0))
|| !TEST_true(OSSL_PARAM_BLD_push_long(bld, OSSL_PKEY_PARAM_DH_PRIV_LEN,
priv_len))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, priv))
|| !TEST_ptr(fromdata_params = OSSL_PARAM_BLD_to_param(bld)))
goto err;
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)))
goto err;
if (!TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
|| !TEST_int_eq(EVP_PKEY_fromdata(ctx, &pk, EVP_PKEY_KEYPAIR,
fromdata_params), 1))
goto err;
/*
* A few extra checks of EVP_PKEY_get_utf8_string_param() to see that
* it behaves as expected with regards to string length and terminating
* NUL byte.
*/
if (!TEST_true(EVP_PKEY_get_utf8_string_param(pk,
OSSL_PKEY_PARAM_GROUP_NAME,
NULL, sizeof(name_out),
&len))
|| !TEST_size_t_eq(len, sizeof(group_name) - 1)
/* Just enough space to hold the group name and a terminating NUL */
|| !TEST_true(EVP_PKEY_get_utf8_string_param(pk,
OSSL_PKEY_PARAM_GROUP_NAME,
name_out,
sizeof(group_name),
&len))
|| !TEST_size_t_eq(len, sizeof(group_name) - 1)
/* Too small buffer to hold the terminating NUL byte */
|| !TEST_false(EVP_PKEY_get_utf8_string_param(pk,
OSSL_PKEY_PARAM_GROUP_NAME,
name_out,
sizeof(group_name) - 1,
&len))
/* Too small buffer to hold the whole group name, even! */
|| !TEST_false(EVP_PKEY_get_utf8_string_param(pk,
OSSL_PKEY_PARAM_GROUP_NAME,
name_out,
sizeof(group_name) - 2,
&len)))
goto err;
while (dup_pk == NULL) {
ret = 0;
if (!TEST_int_eq(EVP_PKEY_get_bits(pk), 2048)
|| !TEST_int_eq(EVP_PKEY_get_security_bits(pk), 112)
|| !TEST_int_eq(EVP_PKEY_get_size(pk), 256)
|| !TEST_false(EVP_PKEY_missing_parameters(pk)))
goto err;
if (!TEST_true(EVP_PKEY_get_utf8_string_param(pk,
OSSL_PKEY_PARAM_GROUP_NAME,
name_out,
sizeof(name_out),
&len))
|| !TEST_str_eq(name_out, group_name)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_PUB_KEY,
&pub_out))
|| !TEST_BN_eq(pub, pub_out)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_PRIV_KEY,
&priv_out))
|| !TEST_BN_eq(priv, priv_out)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_FFC_P, &p))
|| !TEST_BN_eq(&ossl_bignum_ffdhe2048_p, p)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_FFC_Q, &q))
|| !TEST_ptr(q)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_FFC_G, &g))
|| !TEST_BN_eq(&ossl_bignum_const_2, g)
|| !TEST_false(EVP_PKEY_get_bn_param(pk,
OSSL_PKEY_PARAM_FFC_COFACTOR,
&j))
|| !TEST_ptr_null(j)
|| !TEST_false(EVP_PKEY_get_octet_string_param(pk,
OSSL_PKEY_PARAM_FFC_SEED,
seed_out,
sizeof(seed_out),
&len))
|| !TEST_true(EVP_PKEY_get_int_param(pk, OSSL_PKEY_PARAM_FFC_GINDEX,
&gindex))
|| !TEST_int_eq(gindex, -1)
|| !TEST_true(EVP_PKEY_get_int_param(pk, OSSL_PKEY_PARAM_FFC_H,
&hindex))
|| !TEST_int_eq(hindex, 0)
|| !TEST_true(EVP_PKEY_get_int_param(pk,
OSSL_PKEY_PARAM_FFC_PCOUNTER,
&pcounter))
|| !TEST_int_eq(pcounter, -1))
goto err;
BN_free(p);
p = NULL;
BN_free(q);
q = NULL;
BN_free(g);
g = NULL;
BN_free(j);
j = NULL;
BN_free(pub_out);
pub_out = NULL;
BN_free(priv_out);
priv_out = NULL;
if (!TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pk, "")))
goto err;
if (!TEST_int_gt(EVP_PKEY_check(key_ctx), 0)
|| !TEST_int_gt(EVP_PKEY_public_check(key_ctx), 0)
|| !TEST_int_gt(EVP_PKEY_private_check(key_ctx), 0)
|| !TEST_int_gt(EVP_PKEY_pairwise_check(key_ctx), 0))
goto err;
EVP_PKEY_CTX_free(key_ctx);
key_ctx = NULL;
if (!TEST_ptr(copy_pk = EVP_PKEY_new())
|| !TEST_true(EVP_PKEY_copy_parameters(copy_pk, pk)))
goto err;
EVP_PKEY_free(copy_pk);
copy_pk = NULL;
ret = test_print_key_using_pem("DH", pk)
&& test_print_key_using_encoder("DH", pk);
if (!ret || !TEST_ptr(dup_pk = EVP_PKEY_dup(pk)))
goto err;
ret = ret && TEST_int_eq(EVP_PKEY_eq(pk, dup_pk), 1);
EVP_PKEY_free(pk);
pk = dup_pk;
if (!ret)
goto err;
}
err:
BN_free(p);
BN_free(q);
BN_free(g);
BN_free(j);
BN_free(pub);
BN_free(priv);
BN_free(pub_out);
BN_free(priv_out);
EVP_PKEY_free(copy_pk);
EVP_PKEY_free(pk);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_CTX_free(key_ctx);
OSSL_PARAM_free(fromdata_params);
OSSL_PARAM_BLD_free(bld);
return ret;
}
static int test_fromdata_dh_fips186_4(void)
{
int ret = 0;
int gindex = 0, pcounter = 0, hindex = 0;
EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL;
EVP_PKEY *pk = NULL, *dup_pk = NULL;
size_t len;
BIGNUM *pub = NULL, *priv = NULL;
BIGNUM *pub_out = NULL, *priv_out = NULL;
BIGNUM *p = NULL, *q = NULL, *g = NULL, *j = NULL;
OSSL_PARAM_BLD *bld = NULL;
OSSL_PARAM *fromdata_params = NULL;
char name_out[80];
unsigned char seed_out[32];
/*
* DH key data was generated using the following:
* openssl genpkey -algorithm DH
* -pkeyopt group:ffdhe2048 -pkeyopt priv_len:224 -text
*/
static const unsigned char priv_data[] = {
0x88, 0x85, 0xe7, 0x9f, 0xee, 0x6d, 0xc5, 0x7c, 0x78, 0xaf, 0x63, 0x5d,
0x38, 0x2a, 0xd0, 0xed, 0x56, 0x4b, 0x47, 0x21, 0x2b, 0xfa, 0x55, 0xfa,
0x87, 0xe8, 0xa9, 0x7b,
};
static const unsigned char pub_data[] = {
0xd6, 0x2d, 0x77, 0xe0, 0xd3, 0x7d, 0xf8, 0xeb, 0x98, 0x50, 0xa1, 0x82,
0x22, 0x65, 0xd5, 0xd9, 0xfe, 0xc9, 0x3f, 0xbe, 0x16, 0x83, 0xbd, 0x33,
0xe9, 0xc6, 0x93, 0xcf, 0x08, 0xaf, 0x83, 0xfa, 0x80, 0x8a, 0x6c, 0x64,
0xdf, 0x70, 0x64, 0xd5, 0x0a, 0x7c, 0x5a, 0x72, 0xda, 0x66, 0xe6, 0xf9,
0xf5, 0x31, 0x21, 0x92, 0xb0, 0x60, 0x1a, 0xb5, 0xd3, 0xf0, 0xa5, 0xfa,
0x48, 0x95, 0x2e, 0x38, 0xd9, 0xc5, 0xe6, 0xda, 0xfb, 0x6c, 0x03, 0x9d,
0x4b, 0x69, 0xb7, 0x95, 0xe4, 0x5c, 0xc0, 0x93, 0x4f, 0x48, 0xd9, 0x7e,
0x06, 0x22, 0xb2, 0xde, 0xf3, 0x79, 0x24, 0xed, 0xe1, 0xd1, 0x4a, 0x57,
0xf1, 0x40, 0x86, 0x70, 0x42, 0x25, 0xc5, 0x27, 0x68, 0xc9, 0xfa, 0xe5,
0x8e, 0x62, 0x7e, 0xff, 0x49, 0x6c, 0x5b, 0xb5, 0xba, 0xf9, 0xef, 0x9a,
0x1a, 0x10, 0xd4, 0x81, 0x53, 0xcf, 0x83, 0x04, 0x18, 0x1c, 0xe1, 0xdb,
0xe1, 0x65, 0xa9, 0x7f, 0xe1, 0x33, 0xeb, 0xc3, 0x4f, 0xe3, 0xb7, 0x22,
0xf7, 0x1c, 0x09, 0x4f, 0xed, 0xc6, 0x07, 0x8e, 0x78, 0x05, 0x8f, 0x7c,
0x96, 0xd9, 0x12, 0xe0, 0x81, 0x74, 0x1a, 0xe9, 0x13, 0xc0, 0x20, 0x82,
0x65, 0xbb, 0x42, 0x3b, 0xed, 0x08, 0x6a, 0x84, 0x4f, 0xea, 0x77, 0x14,
0x32, 0xf9, 0xed, 0xc2, 0x12, 0xd6, 0xc5, 0xc6, 0xb3, 0xe5, 0xf2, 0x6e,
0xf6, 0x16, 0x7f, 0x37, 0xde, 0xbc, 0x09, 0xc7, 0x06, 0x6b, 0x12, 0xbc,
0xad, 0x2d, 0x49, 0x25, 0xd5, 0xdc, 0xf4, 0x18, 0x14, 0xd2, 0xf0, 0xf1,
0x1d, 0x1f, 0x3a, 0xaa, 0x15, 0x55, 0xbb, 0x0d, 0x7f, 0xbe, 0x67, 0xa1,
0xa7, 0xf0, 0xaa, 0xb3, 0xfb, 0x41, 0x82, 0x39, 0x49, 0x93, 0xbc, 0xa8,
0xee, 0x72, 0x13, 0x45, 0x65, 0x15, 0x42, 0x17, 0xaa, 0xd8, 0xab, 0xcf,
0x33, 0x42, 0x83, 0x42
};
static const char group_name[] = "ffdhe2048";
static const long priv_len = 224;
if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
|| !TEST_ptr(pub = BN_bin2bn(pub_data, sizeof(pub_data), NULL))
|| !TEST_ptr(priv = BN_bin2bn(priv_data, sizeof(priv_data), NULL))
|| !TEST_true(OSSL_PARAM_BLD_push_utf8_string(bld,
OSSL_PKEY_PARAM_GROUP_NAME,
group_name, 0))
|| !TEST_true(OSSL_PARAM_BLD_push_long(bld, OSSL_PKEY_PARAM_DH_PRIV_LEN,
priv_len))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, priv))
|| !TEST_ptr(fromdata_params = OSSL_PARAM_BLD_to_param(bld)))
goto err;
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)))
goto err;
if (!TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
|| !TEST_int_eq(EVP_PKEY_fromdata(ctx, &pk, EVP_PKEY_KEYPAIR,
fromdata_params), 1))
goto err;
while (dup_pk == NULL) {
ret = 0;
if (!TEST_int_eq(EVP_PKEY_get_bits(pk), 2048)
|| !TEST_int_eq(EVP_PKEY_get_security_bits(pk), 112)
|| !TEST_int_eq(EVP_PKEY_get_size(pk), 256)
|| !TEST_false(EVP_PKEY_missing_parameters(pk)))
goto err;
if (!TEST_true(EVP_PKEY_get_utf8_string_param(pk,
OSSL_PKEY_PARAM_GROUP_NAME,
name_out,
sizeof(name_out),
&len))
|| !TEST_str_eq(name_out, group_name)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_PUB_KEY,
&pub_out))
|| !TEST_BN_eq(pub, pub_out)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_PRIV_KEY,
&priv_out))
|| !TEST_BN_eq(priv, priv_out)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_FFC_P, &p))
|| !TEST_BN_eq(&ossl_bignum_ffdhe2048_p, p)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_FFC_Q, &q))
|| !TEST_ptr(q)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_FFC_G, &g))
|| !TEST_BN_eq(&ossl_bignum_const_2, g)
|| !TEST_false(EVP_PKEY_get_bn_param(pk,
OSSL_PKEY_PARAM_FFC_COFACTOR,
&j))
|| !TEST_ptr_null(j)
|| !TEST_false(EVP_PKEY_get_octet_string_param(pk,
OSSL_PKEY_PARAM_FFC_SEED,
seed_out,
sizeof(seed_out),
&len))
|| !TEST_true(EVP_PKEY_get_int_param(pk,
OSSL_PKEY_PARAM_FFC_GINDEX,
&gindex))
|| !TEST_int_eq(gindex, -1)
|| !TEST_true(EVP_PKEY_get_int_param(pk, OSSL_PKEY_PARAM_FFC_H,
&hindex))
|| !TEST_int_eq(hindex, 0)
|| !TEST_true(EVP_PKEY_get_int_param(pk,
OSSL_PKEY_PARAM_FFC_PCOUNTER,
&pcounter))
|| !TEST_int_eq(pcounter, -1))
goto err;
BN_free(p);
p = NULL;
BN_free(q);
q = NULL;
BN_free(g);
g = NULL;
BN_free(j);
j = NULL;
BN_free(pub_out);
pub_out = NULL;
BN_free(priv_out);
priv_out = NULL;
if (!TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pk, "")))
goto err;
if (!TEST_int_gt(EVP_PKEY_check(key_ctx), 0)
|| !TEST_int_gt(EVP_PKEY_public_check(key_ctx), 0)
|| !TEST_int_gt(EVP_PKEY_private_check(key_ctx), 0)
|| !TEST_int_gt(EVP_PKEY_pairwise_check(key_ctx), 0))
goto err;
EVP_PKEY_CTX_free(key_ctx);
key_ctx = NULL;
ret = test_print_key_using_pem("DH", pk)
&& test_print_key_using_encoder("DH", pk);
if (!ret || !TEST_ptr(dup_pk = EVP_PKEY_dup(pk)))
goto err;
ret = ret && TEST_int_eq(EVP_PKEY_eq(pk, dup_pk), 1);
EVP_PKEY_free(pk);
pk = dup_pk;
if (!ret)
goto err;
}
err:
BN_free(p);
BN_free(q);
BN_free(g);
BN_free(j);
BN_free(pub);
BN_free(priv);
BN_free(pub_out);
BN_free(priv_out);
EVP_PKEY_free(pk);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_CTX_free(key_ctx);
OSSL_PARAM_free(fromdata_params);
OSSL_PARAM_BLD_free(bld);
return ret;
}
#endif
#ifndef OPENSSL_NO_EC
/* Array indexes used in test_fromdata_ecx */
# define PRIV_KEY 0
# define PUB_KEY 1
# define X25519_IDX 0
# define X448_IDX 1
# define ED25519_IDX 2
# define ED448_IDX 3
/*
* tst uses indexes 0 ... (3 * 4 - 1)
* For the 4 ECX key types (X25519_IDX..ED448_IDX)
* 0..3 = public + private key.
* 4..7 = private key (This will generate the public key from the private key)
* 8..11 = public key
*/
static int test_fromdata_ecx(int tst)
{
int ret = 0;
EVP_PKEY_CTX *ctx = NULL, *ctx2 = NULL;
EVP_PKEY *pk = NULL, *copy_pk = NULL, *dup_pk = NULL;
const char *alg = NULL;
size_t len;
unsigned char out_pub[ED448_KEYLEN];
unsigned char out_priv[ED448_KEYLEN];
OSSL_PARAM params[3] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
/* ED448_KEYLEN > X448_KEYLEN > X25519_KEYLEN == ED25519_KEYLEN */
static unsigned char key_numbers[4][2][ED448_KEYLEN] = {
/* X25519: Keys from RFC 7748 6.1 */
{
/* Private Key */
{
0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16,
0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87,
0xeb, 0xc0, 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9,
0x2c, 0x2a
},
/* Public Key */
{
0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b,
0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d,
0x26, 0x38, 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b,
0x4e, 0x6a
}
},
/* X448: Keys from RFC 7748 6.2 */
{
/* Private Key */
{
0x9a, 0x8f, 0x49, 0x25, 0xd1, 0x51, 0x9f, 0x57, 0x75, 0xcf,
0x46, 0xb0, 0x4b, 0x58, 0x00, 0xd4, 0xee, 0x9e, 0xe8, 0xba,
0xe8, 0xbc, 0x55, 0x65, 0xd4, 0x98, 0xc2, 0x8d, 0xd9, 0xc9,
0xba, 0xf5, 0x74, 0xa9, 0x41, 0x97, 0x44, 0x89, 0x73, 0x91,
0x00, 0x63, 0x82, 0xa6, 0xf1, 0x27, 0xab, 0x1d, 0x9a, 0xc2,
0xd8, 0xc0, 0xa5, 0x98, 0x72, 0x6b
},
/* Public Key */
{
0x9b, 0x08, 0xf7, 0xcc, 0x31, 0xb7, 0xe3, 0xe6, 0x7d, 0x22,
0xd5, 0xae, 0xa1, 0x21, 0x07, 0x4a, 0x27, 0x3b, 0xd2, 0xb8,
0x3d, 0xe0, 0x9c, 0x63, 0xfa, 0xa7, 0x3d, 0x2c, 0x22, 0xc5,
0xd9, 0xbb, 0xc8, 0x36, 0x64, 0x72, 0x41, 0xd9, 0x53, 0xd4,
0x0c, 0x5b, 0x12, 0xda, 0x88, 0x12, 0x0d, 0x53, 0x17, 0x7f,
0x80, 0xe5, 0x32, 0xc4, 0x1f, 0xa0
}
},
/* ED25519: Keys from RFC 8032 */
{
/* Private Key */
{
0x9d, 0x61, 0xb1, 0x9d, 0xef, 0xfd, 0x5a, 0x60, 0xba, 0x84,
0x4a, 0xf4, 0x92, 0xec, 0x2c, 0xc4, 0x44, 0x49, 0xc5, 0x69,
0x7b, 0x32, 0x69, 0x19, 0x70, 0x3b, 0xac, 0x03, 0x1c, 0xae,
0x7f, 0x60
},
/* Public Key */
{
0xd7, 0x5a, 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, 0xd5, 0x4b,
0xfe, 0xd3, 0xc9, 0x64, 0x07, 0x3a, 0x0e, 0xe1, 0x72, 0xf3,
0xda, 0xa6, 0x23, 0x25, 0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07,
0x51, 0x1a
}
},
/* ED448: Keys from RFC 8032 */
{
/* Private Key */
{
0x6c, 0x82, 0xa5, 0x62, 0xcb, 0x80, 0x8d, 0x10, 0xd6, 0x32,
0xbe, 0x89, 0xc8, 0x51, 0x3e, 0xbf, 0x6c, 0x92, 0x9f, 0x34,
0xdd, 0xfa, 0x8c, 0x9f, 0x63, 0xc9, 0x96, 0x0e, 0xf6, 0xe3,
0x48, 0xa3, 0x52, 0x8c, 0x8a, 0x3f, 0xcc, 0x2f, 0x04, 0x4e,
0x39, 0xa3, 0xfc, 0x5b, 0x94, 0x49, 0x2f, 0x8f, 0x03, 0x2e,
0x75, 0x49, 0xa2, 0x00, 0x98, 0xf9, 0x5b
},
/* Public Key */
{
0x5f, 0xd7, 0x44, 0x9b, 0x59, 0xb4, 0x61, 0xfd, 0x2c, 0xe7,
0x87, 0xec, 0x61, 0x6a, 0xd4, 0x6a, 0x1d, 0xa1, 0x34, 0x24,
0x85, 0xa7, 0x0e, 0x1f, 0x8a, 0x0e, 0xa7, 0x5d, 0x80, 0xe9,
0x67, 0x78, 0xed, 0xf1, 0x24, 0x76, 0x9b, 0x46, 0xc7, 0x06,
0x1b, 0xd6, 0x78, 0x3d, 0xf1, 0xe5, 0x0f, 0x6c, 0xd1, 0xfa,
0x1a, 0xbe, 0xaf, 0xe8, 0x25, 0x61, 0x80
}
}
};
OSSL_PARAM x25519_fromdata_params[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
key_numbers[X25519_IDX][PRIV_KEY],
X25519_KEYLEN),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
key_numbers[X25519_IDX][PUB_KEY],
X25519_KEYLEN),
OSSL_PARAM_END
};
OSSL_PARAM x448_fromdata_params[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
key_numbers[X448_IDX][PRIV_KEY],
X448_KEYLEN),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
key_numbers[X448_IDX][PUB_KEY],
X448_KEYLEN),
OSSL_PARAM_END
};
OSSL_PARAM ed25519_fromdata_params[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
key_numbers[ED25519_IDX][PRIV_KEY],
ED25519_KEYLEN),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
key_numbers[ED25519_IDX][PUB_KEY],
ED25519_KEYLEN),
OSSL_PARAM_END
};
OSSL_PARAM ed448_fromdata_params[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
key_numbers[ED448_IDX][PRIV_KEY],
ED448_KEYLEN),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
key_numbers[ED448_IDX][PUB_KEY],
ED448_KEYLEN),
OSSL_PARAM_END
};
OSSL_PARAM *fromdata_params = NULL;
int bits = 0, security_bits = 0, size = 0;
OSSL_PARAM *orig_fromdata_params = NULL;
switch (tst & 3) {
case X25519_IDX:
fromdata_params = x25519_fromdata_params;
bits = X25519_BITS;
security_bits = X25519_SECURITY_BITS;
size = X25519_KEYLEN;
alg = "X25519";
break;
case X448_IDX:
fromdata_params = x448_fromdata_params;
bits = X448_BITS;
security_bits = X448_SECURITY_BITS;
size = X448_KEYLEN;
alg = "X448";
break;
case ED25519_IDX:
fromdata_params = ed25519_fromdata_params;
bits = ED25519_BITS;
security_bits = ED25519_SECURITY_BITS;
size = ED25519_SIGSIZE;
alg = "ED25519";
break;
case ED448_IDX:
fromdata_params = ed448_fromdata_params;
bits = ED448_BITS;
security_bits = ED448_SECURITY_BITS;
size = ED448_SIGSIZE;
alg = "ED448";
break;
default:
goto err;
}
ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
if (!TEST_ptr(ctx))
goto err;
orig_fromdata_params = fromdata_params;
if (tst > 7) {
/* public key only */
fromdata_params++;
} else if (tst > 3) {
/* private key only */
params[0] = fromdata_params[0];
params[1] = fromdata_params[2];
fromdata_params = params;
}
if (!TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
|| !TEST_int_eq(EVP_PKEY_fromdata(ctx, &pk, EVP_PKEY_KEYPAIR,
fromdata_params), 1))
goto err;
while (dup_pk == NULL) {
ret = 0;
if (!TEST_int_eq(EVP_PKEY_get_bits(pk), bits)
|| !TEST_int_eq(EVP_PKEY_get_security_bits(pk), security_bits)
|| !TEST_int_eq(EVP_PKEY_get_size(pk), size)
|| !TEST_false(EVP_PKEY_missing_parameters(pk)))
goto err;
if (!TEST_ptr(ctx2 = EVP_PKEY_CTX_new_from_pkey(NULL, pk, NULL)))
goto err;
if (tst <= 7) {
if (!TEST_int_gt(EVP_PKEY_check(ctx2), 0))
goto err;
if (!TEST_true(EVP_PKEY_get_octet_string_param(
pk, orig_fromdata_params[PRIV_KEY].key,
out_priv, sizeof(out_priv), &len))
|| !TEST_mem_eq(out_priv, len,
orig_fromdata_params[PRIV_KEY].data,
orig_fromdata_params[PRIV_KEY].data_size)
|| !TEST_true(EVP_PKEY_get_octet_string_param(
pk, orig_fromdata_params[PUB_KEY].key,
out_pub, sizeof(out_pub), &len))
|| !TEST_mem_eq(out_pub, len,
orig_fromdata_params[PUB_KEY].data,
orig_fromdata_params[PUB_KEY].data_size))
goto err;
} else {
/* The private key check should fail if there is only a public key */
if (!TEST_int_gt(EVP_PKEY_public_check(ctx2), 0)
|| !TEST_int_le(EVP_PKEY_private_check(ctx2), 0)
|| !TEST_int_le(EVP_PKEY_check(ctx2), 0))
goto err;
}
EVP_PKEY_CTX_free(ctx2);
ctx2 = NULL;
if (!TEST_ptr(copy_pk = EVP_PKEY_new())
/* This should succeed because there are no parameters to copy */
|| !TEST_true(EVP_PKEY_copy_parameters(copy_pk, pk)))
goto err;
EVP_PKEY_free(copy_pk);
copy_pk = NULL;
if (tst > 7)
ret = test_print_key_using_encoder_public(alg, pk);
else
ret = test_print_key_using_pem(alg, pk)
&& test_print_key_using_encoder(alg, pk);
if (!ret || !TEST_ptr(dup_pk = EVP_PKEY_dup(pk)))
goto err;
ret = ret && TEST_int_eq(EVP_PKEY_eq(pk, dup_pk), 1);
EVP_PKEY_free(pk);
pk = dup_pk;
if (!ret)
goto err;
}
err:
EVP_PKEY_free(pk);
EVP_PKEY_free(copy_pk);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_CTX_free(ctx2);
return ret;
}
static int test_fromdata_ec(void)
{
int ret = 0;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pk = NULL, *copy_pk = NULL, *dup_pk = NULL;
OSSL_PARAM_BLD *bld = NULL;
BIGNUM *ec_priv_bn = NULL;
BIGNUM *bn_priv = NULL;
OSSL_PARAM *fromdata_params = NULL;
const char *alg = "EC";
const char *curve = "prime256v1";
const char bad_curve[] = "nonexistent-curve";
OSSL_PARAM nokey_params[2] = {
OSSL_PARAM_END,
OSSL_PARAM_END
};
/* UNCOMPRESSED FORMAT */
static const unsigned char ec_pub_keydata[] = {
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,
0x3a, 0x6a, 0x08, 0x28, 0x39, 0xbd, 0xc9, 0xd2,
0x80, 0xec, 0xe9, 0xa7, 0x08, 0x29, 0x71, 0x2f,
0xc9, 0x56, 0x82, 0xee, 0x9a, 0x85, 0x0f, 0x6d,
0x7f, 0x59, 0x5f, 0x8c, 0xd1, 0x96, 0x0b, 0xdf,
0x29, 0x3e, 0x49, 0x07, 0x88, 0x3f, 0x9a, 0x29
};
/* SAME BUT COMPRESSED FORMAT */
static const unsigned char ec_pub_keydata_compressed[] = {
POINT_CONVERSION_COMPRESSED+1,
0x1b, 0x93, 0x67, 0x55, 0x1c, 0x55, 0x9f, 0x63,
0xd1, 0x22, 0xa4, 0xd8, 0xd1, 0x0a, 0x60, 0x6d,
0x02, 0xa5, 0x77, 0x57, 0xc8, 0xa3, 0x47, 0x73,
0x3a, 0x6a, 0x08, 0x28, 0x39, 0xbd, 0xc9, 0xd2
};
static const unsigned char ec_priv_keydata[] = {
0x33, 0xd0, 0x43, 0x83, 0xa9, 0x89, 0x56, 0x03,
0xd2, 0xd7, 0xfe, 0x6b, 0x01, 0x6f, 0xe4, 0x59,
0xcc, 0x0d, 0x9a, 0x24, 0x6c, 0x86, 0x1b, 0x2e,
0xdc, 0x4b, 0x4d, 0x35, 0x43, 0xe1, 0x1b, 0xad
};
unsigned char out_pub[sizeof(ec_pub_keydata)];
char out_curve_name[80];
const OSSL_PARAM *gettable = NULL;
size_t len;
EC_GROUP *group = NULL;
BIGNUM *group_a = NULL;
BIGNUM *group_b = NULL;
BIGNUM *group_p = NULL;
BIGNUM *a = NULL;
BIGNUM *b = NULL;
BIGNUM *p = NULL;
if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()))
goto err;
if (!TEST_ptr(ec_priv_bn = BN_bin2bn(ec_priv_keydata,
sizeof(ec_priv_keydata), NULL)))
goto err;
if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME,
curve, 0) <= 0)
goto err;
/*
* We intentionally provide the input point in compressed format,
* and avoid setting `OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT`.
*
* Later on we check what format is used when exporting the
* `OSSL_PKEY_PARAM_PUB_KEY` and expect to default to uncompressed
* format.
*/
if (OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY,
ec_pub_keydata_compressed,
sizeof(ec_pub_keydata_compressed)) <= 0)
goto err;
if (OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, ec_priv_bn) <= 0)
goto err;
if (!TEST_ptr(fromdata_params = OSSL_PARAM_BLD_to_param(bld)))
goto err;
ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
if (!TEST_ptr(ctx))
goto err;
/* try importing parameters with bad curve first */
nokey_params[0] =
OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
(char *)bad_curve, sizeof(bad_curve));
if (!TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
|| !TEST_int_eq(EVP_PKEY_fromdata(ctx, &pk, EVP_PKEY_KEY_PARAMETERS,
nokey_params), 0)
|| !TEST_ptr_null(pk))
goto err;
if (!TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
|| !TEST_int_eq(EVP_PKEY_fromdata(ctx, &pk, EVP_PKEY_KEYPAIR,
fromdata_params), 1))
goto err;
while (dup_pk == NULL) {
ret = 0;
if (!TEST_int_eq(EVP_PKEY_get_bits(pk), 256)
|| !TEST_int_eq(EVP_PKEY_get_security_bits(pk), 128)
|| !TEST_int_eq(EVP_PKEY_get_size(pk), 2 + 35 * 2)
|| !TEST_false(EVP_PKEY_missing_parameters(pk)))
goto err;
if (!TEST_ptr(copy_pk = EVP_PKEY_new())
|| !TEST_true(EVP_PKEY_copy_parameters(copy_pk, pk)))
goto err;
EVP_PKEY_free(copy_pk);
copy_pk = NULL;
if (!TEST_ptr(gettable = EVP_PKEY_gettable_params(pk))
|| !TEST_ptr(OSSL_PARAM_locate_const(gettable,
OSSL_PKEY_PARAM_GROUP_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 (!TEST_ptr(group = EC_GROUP_new_by_curve_name(OBJ_sn2nid(curve)))
|| !TEST_ptr(group_p = BN_new())
|| !TEST_ptr(group_a = BN_new())
|| !TEST_ptr(group_b = BN_new())
|| !TEST_true(EC_GROUP_get_curve(group, group_p, group_a, group_b, NULL)))
goto err;
if (!TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_EC_A, &a))
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_EC_B, &b))
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_EC_P, &p)))
goto err;
if (!TEST_BN_eq(group_p, p) || !TEST_BN_eq(group_a, a)
|| !TEST_BN_eq(group_b, b))
goto err;
if (!EVP_PKEY_get_utf8_string_param(pk, OSSL_PKEY_PARAM_GROUP_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)
/*
* Our providers use uncompressed format by default if
* `OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT` was not
* explicitly set, irrespective of the format used for the
* input point given as a param to create this key.
*/
|| !TEST_true(out_pub[0] == POINT_CONVERSION_UNCOMPRESSED)
|| !TEST_mem_eq(out_pub + 1, len - 1,
ec_pub_keydata + 1, sizeof(ec_pub_keydata) - 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;
BN_free(bn_priv);
bn_priv = NULL;
ret = test_print_key_using_pem(alg, pk)
&& test_print_key_using_encoder(alg, pk);
if (!ret || !TEST_ptr(dup_pk = EVP_PKEY_dup(pk)))
goto err;
ret = ret && TEST_int_eq(EVP_PKEY_eq(pk, dup_pk), 1);
EVP_PKEY_free(pk);
pk = dup_pk;
if (!ret)
goto err;
}
err:
EC_GROUP_free(group);
BN_free(group_a);
BN_free(group_b);
BN_free(group_p);
BN_free(a);
BN_free(b);
BN_free(p);
BN_free(bn_priv);
BN_free(ec_priv_bn);
OSSL_PARAM_free(fromdata_params);
OSSL_PARAM_BLD_free(bld);
EVP_PKEY_free(pk);
EVP_PKEY_free(copy_pk);
EVP_PKEY_CTX_free(ctx);
return ret;
}
static int test_ec_dup_no_operation(void)
{
int ret = 0;
EVP_PKEY_CTX *pctx = NULL, *ctx = NULL, *kctx = NULL;
EVP_PKEY *param = NULL, *pkey = NULL;
if (!TEST_ptr(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))
|| !TEST_int_gt(EVP_PKEY_paramgen_init(pctx), 0)
|| !TEST_int_gt(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
NID_X9_62_prime256v1), 0)
|| !TEST_int_gt(EVP_PKEY_paramgen(pctx, &param), 0)
|| !TEST_ptr(param))
goto err;
EVP_PKEY_CTX_free(pctx);
pctx = NULL;
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(NULL, param, NULL))
|| !TEST_ptr(kctx = EVP_PKEY_CTX_dup(ctx))
|| !TEST_int_gt(EVP_PKEY_keygen_init(kctx), 0)
|| !TEST_int_gt(EVP_PKEY_keygen(kctx, &pkey), 0))
goto err;
ret = 1;
err:
EVP_PKEY_free(pkey);
EVP_PKEY_free(param);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_CTX_free(kctx);
EVP_PKEY_CTX_free(pctx);
return ret;
}
/* Test that keygen doesn't support EVP_PKEY_CTX_dup */
static int test_ec_dup_keygen_operation(void)
{
int ret = 0;
EVP_PKEY_CTX *pctx = NULL, *ctx = NULL, *kctx = NULL;
EVP_PKEY *param = NULL, *pkey = NULL;
if (!TEST_ptr(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))
|| !TEST_int_gt(EVP_PKEY_paramgen_init(pctx), 0)
|| !TEST_int_gt(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
NID_X9_62_prime256v1), 0)
|| !TEST_int_gt(EVP_PKEY_paramgen(pctx, &param), 0)
|| !TEST_ptr(param))
goto err;
EVP_PKEY_CTX_free(pctx);
pctx = NULL;
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(NULL, param, NULL))
|| !TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0)
|| !TEST_ptr_null(kctx = EVP_PKEY_CTX_dup(ctx)))
goto err;
ret = 1;
err:
EVP_PKEY_free(pkey);
EVP_PKEY_free(param);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_CTX_free(kctx);
EVP_PKEY_CTX_free(pctx);
return ret;
}
#endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_DSA
static int test_fromdata_dsa_fips186_4(void)
{
int ret = 0;
EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL;
EVP_PKEY *pk = NULL, *copy_pk = NULL, *dup_pk = NULL;
BIGNUM *pub = NULL, *priv = NULL;
BIGNUM *p = NULL, *q = NULL, *g = NULL;
BIGNUM *pub_out = NULL, *priv_out = NULL;
BIGNUM *p_out = NULL, *q_out = NULL, *g_out = NULL, *j_out = NULL;
int gindex_out = 0, pcounter_out = 0, hindex_out = 0;
char name_out[80];
unsigned char seed_out[32];
size_t len;
OSSL_PARAM_BLD *bld = NULL;
OSSL_PARAM *fromdata_params = NULL;
/*
* DSA parameter data was generated using the following:
* openssl genpkey -genparam -algorithm DSA -pkeyopt pbits:2048 \
* -pkeyopt qbits:256 -pkeyopt type:0 \
* -pkeyopt gindex:1 -out dsa_params.pem -text
*/
static const unsigned char p_data[] = {
0x00, 0xa0, 0xb7, 0x02, 0xc4, 0xac, 0xa6, 0x42, 0xab, 0xf2, 0x34, 0x0b,
0x22, 0x47, 0x1f, 0x33, 0xcf, 0xd5, 0x04, 0xe4, 0x3e, 0xec, 0xa1, 0x21,
0xc8, 0x41, 0x2b, 0xef, 0xb8, 0x1f, 0x0b, 0x5b, 0x88, 0x8b, 0x67, 0xf8,
0x68, 0x6d, 0x7c, 0x4d, 0x96, 0x5f, 0x3c, 0x66, 0xef, 0x58, 0x34, 0xd7,
0xf6, 0xa2, 0x1b, 0xad, 0xc8, 0x12, 0x52, 0xb8, 0xe8, 0x2a, 0x63, 0xcc,
0xea, 0xe7, 0x4e, 0xc8, 0x34, 0x4c, 0x58, 0x59, 0x0a, 0xc2, 0x4a, 0xe4,
0xb4, 0x64, 0x20, 0xf4, 0xf6, 0x0a, 0xcf, 0x86, 0x01, 0x6c, 0x7f, 0x23,
0x4a, 0x51, 0x07, 0x99, 0x42, 0x28, 0x7a, 0xff, 0x18, 0x67, 0x52, 0x64,
0xf2, 0x9a, 0x62, 0x30, 0xc3, 0x00, 0xde, 0x23, 0xe9, 0x11, 0x95, 0x7e,
0xd1, 0x3d, 0x8d, 0xb4, 0x0e, 0x9f, 0x9e, 0xb1, 0x30, 0x03, 0xf0, 0x73,
0xa8, 0x40, 0x48, 0x42, 0x7b, 0x60, 0xa0, 0xc4, 0xf2, 0x3b, 0x2d, 0x0a,
0x0c, 0xb8, 0x19, 0xfb, 0xb4, 0xf8, 0xe0, 0x2a, 0xc7, 0xf1, 0xc0, 0xc6,
0x86, 0x14, 0x60, 0x12, 0x0f, 0xc0, 0xde, 0x4a, 0x67, 0xec, 0xc7, 0xde,
0x76, 0x21, 0x1a, 0x55, 0x7f, 0x86, 0xc3, 0x97, 0x98, 0xce, 0xf5, 0xcd,
0xf0, 0xe7, 0x12, 0xd6, 0x93, 0xee, 0x1b, 0x9b, 0x61, 0xef, 0x05, 0x8c,
0x45, 0x46, 0xd9, 0x64, 0x6f, 0xbe, 0x27, 0xaa, 0x67, 0x01, 0xcc, 0x71,
0xb1, 0x60, 0xce, 0x21, 0xd8, 0x51, 0x17, 0x27, 0x0d, 0x90, 0x3d, 0x18,
0x7c, 0x87, 0x15, 0x8e, 0x48, 0x4c, 0x6c, 0xc5, 0x72, 0xeb, 0xb7, 0x56,
0xf5, 0x6b, 0x60, 0x8f, 0xc2, 0xfd, 0x3f, 0x46, 0x5c, 0x00, 0x91, 0x85,
0x79, 0x45, 0x5b, 0x1c, 0x82, 0xc4, 0x87, 0x50, 0x79, 0xba, 0xcc, 0x1c,
0x32, 0x7e, 0x2e, 0xb8, 0x2e, 0xc5, 0x4e, 0xd1, 0x9b, 0xdb, 0x66, 0x79,
0x7c, 0xfe, 0xaf, 0x6a, 0x05
};
static const unsigned char q_data[] = {
0xa8, 0xcd, 0xf4, 0x33, 0x7b, 0x13, 0x0a, 0x24, 0xc1, 0xde, 0x4a, 0x04,
0x7b, 0x4b, 0x71, 0x51, 0x32, 0xe9, 0x47, 0x74, 0xbd, 0x0c, 0x21, 0x40,
0x84, 0x12, 0x0a, 0x17, 0x73, 0xdb, 0x29, 0xc7
};
static const unsigned char g_data[] = {
0x6c, 0xc6, 0xa4, 0x3e, 0x61, 0x84, 0xc1, 0xff, 0x6f, 0x4a, 0x1a, 0x6b,
0xb0, 0x24, 0x4b, 0xd2, 0x92, 0x5b, 0x29, 0x5c, 0x61, 0xb8, 0xc9, 0x2b,
0xd6, 0xf7, 0x59, 0xfd, 0xd8, 0x70, 0x66, 0x77, 0xfc, 0xc1, 0xa4, 0xd4,
0xb0, 0x1e, 0xd5, 0xbf, 0x59, 0x98, 0xb3, 0x66, 0x8b, 0xf4, 0x2e, 0xe6,
0x12, 0x3e, 0xcc, 0xf8, 0x02, 0xb8, 0xc6, 0xc3, 0x47, 0xd2, 0xf5, 0xaa,
0x0c, 0x5f, 0x51, 0xf5, 0xd0, 0x4c, 0x55, 0x3d, 0x07, 0x73, 0xa6, 0x57,
0xce, 0x5a, 0xad, 0x42, 0x0c, 0x13, 0x0f, 0xe2, 0x31, 0x25, 0x8e, 0x72,
0x12, 0x73, 0x10, 0xdb, 0x7f, 0x79, 0xeb, 0x59, 0xfc, 0xfe, 0xf7, 0x0c,
0x1a, 0x81, 0x53, 0x96, 0x22, 0xb8, 0xe7, 0x58, 0xd8, 0x67, 0x80, 0x60,
0xad, 0x8b, 0x55, 0x1c, 0x91, 0xf0, 0x72, 0x9a, 0x7e, 0xad, 0x37, 0xf1,
0x77, 0x18, 0x96, 0x8a, 0x68, 0x70, 0xfc, 0x71, 0xa9, 0xa2, 0xe8, 0x35,
0x27, 0x78, 0xf2, 0xef, 0x59, 0x36, 0x6d, 0x7c, 0xb6, 0x98, 0xd8, 0x1e,
0xfa, 0x25, 0x73, 0x97, 0x45, 0x58, 0xe3, 0xae, 0xbd, 0x52, 0x54, 0x05,
0xd8, 0x26, 0x26, 0xba, 0xba, 0x05, 0xb5, 0xe9, 0xe5, 0x76, 0xae, 0x25,
0xdd, 0xfc, 0x10, 0x89, 0x5a, 0xa9, 0xee, 0x59, 0xc5, 0x79, 0x8b, 0xeb,
0x1e, 0x2c, 0x61, 0xab, 0x0d, 0xd1, 0x10, 0x04, 0x91, 0x32, 0x77, 0x4a,
0xa6, 0x64, 0x53, 0xda, 0x4c, 0xd7, 0x3a, 0x29, 0xd4, 0xf3, 0x82, 0x25,
0x1d, 0x6f, 0x4a, 0x7f, 0xd3, 0x08, 0x3b, 0x42, 0x30, 0x10, 0xd8, 0xd0,
0x97, 0x3a, 0xeb, 0x92, 0x63, 0xec, 0x93, 0x2b, 0x6f, 0x32, 0xd8, 0xcd,
0x80, 0xd3, 0xc0, 0x4c, 0x03, 0xd5, 0xca, 0xbc, 0x8f, 0xc7, 0x43, 0x53,
0x64, 0x66, 0x1c, 0x82, 0x2d, 0xfb, 0xff, 0x39, 0xba, 0xd6, 0x42, 0x62,
0x02, 0x6f, 0x96, 0x36
};
static const unsigned char seed_data[] = {
0x64, 0x46, 0x07, 0x32, 0x8d, 0x70, 0x9c, 0xb3, 0x8a, 0x35, 0xde, 0x62,
0x00, 0xf2, 0x6d, 0x52, 0x37, 0x4d, 0xb3, 0x84, 0xe1, 0x9d, 0x41, 0x04,
0xda, 0x7b, 0xdc, 0x0d, 0x8b, 0x5e, 0xe0, 0x84
};
const int gindex = 1;
const int pcounter = 53;
/*
* The keypair was generated using
* openssl genpkey -paramfile dsa_params.pem --pkeyopt pcounter:53 \
* -pkeyopt gindex:1 \
* -pkeyopt hexseed:644607328d709cb38a35de6200f26d -text
*/
static const unsigned char priv_data[] = {
0x00, 0x8f, 0xc5, 0x9e, 0xd0, 0xf7, 0x2a, 0x0b, 0x66, 0xf1, 0x32, 0x73,
0xae, 0xf6, 0xd9, 0xd4, 0xdb, 0x2d, 0x96, 0x55, 0x89, 0xff, 0xef, 0xa8,
0x5f, 0x47, 0x8f, 0xca, 0x02, 0x8a, 0xe1, 0x35, 0x90
};
static const unsigned char pub_data[] = {
0x44, 0x19, 0xc9, 0x46, 0x45, 0x57, 0xc1, 0xa9, 0xd8, 0x30, 0x99, 0x29,
0x6a, 0x4b, 0x63, 0x71, 0x69, 0x96, 0x35, 0x17, 0xb2, 0x62, 0x9b, 0x80,
0x0a, 0x95, 0x9d, 0x6a, 0xc0, 0x32, 0x0d, 0x07, 0x5f, 0x19, 0x44, 0x02,
0xf1, 0xbd, 0xce, 0xdf, 0x10, 0xf8, 0x02, 0x5d, 0x7d, 0x98, 0x8a, 0x73,
0x89, 0x00, 0xb6, 0x24, 0xd6, 0x33, 0xe7, 0xcf, 0x8b, 0x49, 0x2a, 0xaf,
0x13, 0x1c, 0xb2, 0x52, 0x15, 0xfd, 0x9b, 0xd5, 0x40, 0x4a, 0x1a, 0xda,
0x29, 0x4c, 0x92, 0x7e, 0x66, 0x06, 0xdb, 0x61, 0x86, 0xac, 0xb5, 0xda,
0x3c, 0x7d, 0x73, 0x7e, 0x54, 0x32, 0x68, 0xa5, 0x02, 0xbc, 0x59, 0x47,
0x84, 0xd3, 0x87, 0x71, 0x5f, 0xeb, 0x43, 0x45, 0x24, 0xd3, 0xec, 0x08,
0x52, 0xc2, 0x89, 0x2d, 0x9c, 0x1a, 0xcc, 0x91, 0x65, 0x5d, 0xa3, 0xa1,
0x35, 0x31, 0x10, 0x1c, 0x3a, 0xa8, 0x4d, 0x18, 0xd5, 0x06, 0xaf, 0xb2,
0xec, 0x5c, 0x89, 0x9e, 0x90, 0x86, 0x10, 0x01, 0xeb, 0x51, 0xd5, 0x1b,
0x9c, 0xcb, 0x66, 0x07, 0x3f, 0xc4, 0x6e, 0x0a, 0x1b, 0x73, 0xa0, 0x4b,
0x5f, 0x4d, 0xab, 0x35, 0x28, 0xfa, 0xda, 0x3a, 0x0c, 0x08, 0xe8, 0xf3,
0xef, 0x42, 0x67, 0xbc, 0x21, 0xf2, 0xc2, 0xb8, 0xff, 0x1a, 0x81, 0x05,
0x68, 0x73, 0x62, 0xdf, 0xd7, 0xab, 0x0f, 0x22, 0x89, 0x57, 0x96, 0xd4,
0x93, 0xaf, 0xa1, 0x21, 0xa3, 0x48, 0xe9, 0xf0, 0x97, 0x47, 0xa0, 0x27,
0xba, 0x87, 0xb8, 0x15, 0x5f, 0xff, 0x2c, 0x50, 0x41, 0xf1, 0x7e, 0xc6,
0x81, 0xc4, 0x51, 0xf1, 0xfd, 0xd6, 0x86, 0xf7, 0x69, 0x97, 0xf1, 0x49,
0xc9, 0xf9, 0xf4, 0x9b, 0xf4, 0xe8, 0x85, 0xa7, 0xbd, 0x36, 0x55, 0x4a,
0x3d, 0xe8, 0x65, 0x09, 0x7b, 0xb7, 0x12, 0x64, 0xd2, 0x0a, 0x53, 0x60,
0x48, 0xd1, 0x8a, 0xbd
};
if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
|| !TEST_ptr(pub = BN_bin2bn(pub_data, sizeof(pub_data), NULL))
|| !TEST_ptr(priv = BN_bin2bn(priv_data, sizeof(priv_data), NULL))
|| !TEST_ptr(p = BN_bin2bn(p_data, sizeof(p_data), NULL))
|| !TEST_ptr(q = BN_bin2bn(q_data, sizeof(q_data), NULL))
|| !TEST_ptr(g = BN_bin2bn(g_data, sizeof(g_data), NULL))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g))
|| !TEST_true(OSSL_PARAM_BLD_push_octet_string(bld,
OSSL_PKEY_PARAM_FFC_SEED,
seed_data,
sizeof(seed_data)))
|| !TEST_true(OSSL_PARAM_BLD_push_int(bld, OSSL_PKEY_PARAM_FFC_GINDEX,
gindex))
|| !TEST_true(OSSL_PARAM_BLD_push_int(bld,
OSSL_PKEY_PARAM_FFC_PCOUNTER,
pcounter))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY,
pub))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY,
priv))
|| !TEST_ptr(fromdata_params = OSSL_PARAM_BLD_to_param(bld)))
goto err;
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL)))
goto err;
if (!TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
|| !TEST_int_eq(EVP_PKEY_fromdata(ctx, &pk, EVP_PKEY_KEYPAIR,
fromdata_params), 1))
goto err;
while (dup_pk == NULL) {
ret = 0;
if (!TEST_int_eq(EVP_PKEY_get_bits(pk), 2048)
|| !TEST_int_eq(EVP_PKEY_get_security_bits(pk), 112)
|| !TEST_int_eq(EVP_PKEY_get_size(pk), 2 + 2 * (3 + sizeof(q_data)))
|| !TEST_false(EVP_PKEY_missing_parameters(pk)))
goto err;
if (!TEST_false(EVP_PKEY_get_utf8_string_param(pk,
OSSL_PKEY_PARAM_GROUP_NAME,
name_out,
sizeof(name_out),
&len))
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_PUB_KEY,
&pub_out))
|| !TEST_BN_eq(pub, pub_out)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_PRIV_KEY,
&priv_out))
|| !TEST_BN_eq(priv, priv_out)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_FFC_P,
&p_out))
|| !TEST_BN_eq(p, p_out)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_FFC_Q,
&q_out))
|| !TEST_BN_eq(q, q_out)
|| !TEST_true(EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_FFC_G,
&g_out))
|| !TEST_BN_eq(g, g_out)
|| !TEST_false(EVP_PKEY_get_bn_param(pk,
OSSL_PKEY_PARAM_FFC_COFACTOR,
&j_out))
|| !TEST_ptr_null(j_out)
|| !TEST_true(EVP_PKEY_get_octet_string_param(pk,
OSSL_PKEY_PARAM_FFC_SEED,
seed_out,
sizeof(seed_out),
&len))
|| !TEST_true(EVP_PKEY_get_int_param(pk,
OSSL_PKEY_PARAM_FFC_GINDEX,
&gindex_out))
|| !TEST_int_eq(gindex, gindex_out)
|| !TEST_true(EVP_PKEY_get_int_param(pk, OSSL_PKEY_PARAM_FFC_H,
&hindex_out))
|| !TEST_int_eq(hindex_out, 0)
|| !TEST_true(EVP_PKEY_get_int_param(pk,
OSSL_PKEY_PARAM_FFC_PCOUNTER,
&pcounter_out))
|| !TEST_int_eq(pcounter, pcounter_out))
goto err;
BN_free(p);
p = NULL;
BN_free(q);
q = NULL;
BN_free(g);
g = NULL;
BN_free(j_out);
j_out = NULL;
BN_free(pub_out);
pub_out = NULL;
BN_free(priv_out);
priv_out = NULL;
if (!TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pk, "")))
goto err;
if (!TEST_int_gt(EVP_PKEY_check(key_ctx), 0)
|| !TEST_int_gt(EVP_PKEY_public_check(key_ctx), 0)
|| !TEST_int_gt(EVP_PKEY_private_check(key_ctx), 0)
|| !TEST_int_gt(EVP_PKEY_pairwise_check(key_ctx), 0))
goto err;
EVP_PKEY_CTX_free(key_ctx);
key_ctx = NULL;
if (!TEST_ptr(copy_pk = EVP_PKEY_new())
|| !TEST_true(EVP_PKEY_copy_parameters(copy_pk, pk)))
goto err;
EVP_PKEY_free(copy_pk);
copy_pk = NULL;
ret = test_print_key_using_pem("DSA", pk)
&& test_print_key_using_encoder("DSA", pk);
if (!ret || !TEST_ptr(dup_pk = EVP_PKEY_dup(pk)))
goto err;
ret = ret && TEST_int_eq(EVP_PKEY_eq(pk, dup_pk), 1);
EVP_PKEY_free(pk);
pk = dup_pk;
if (!ret)
goto err;
}
err:
OSSL_PARAM_free(fromdata_params);
OSSL_PARAM_BLD_free(bld);
BN_free(p);
BN_free(q);
BN_free(g);
BN_free(pub);
BN_free(priv);
BN_free(p_out);
BN_free(q_out);
BN_free(g_out);
BN_free(pub_out);
BN_free(priv_out);
BN_free(j_out);
EVP_PKEY_free(pk);
EVP_PKEY_free(copy_pk);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_CTX_free(key_ctx);
return ret;
}
static int test_check_dsa(void)
{
int ret = 0;
EVP_PKEY_CTX *ctx = NULL;
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL))
|| !TEST_int_le(EVP_PKEY_check(ctx), 0)
|| !TEST_int_le(EVP_PKEY_public_check(ctx), 0)
|| !TEST_int_le(EVP_PKEY_private_check(ctx), 0)
|| !TEST_int_le(EVP_PKEY_pairwise_check(ctx), 0))
goto err;
ret = 1;
err:
EVP_PKEY_CTX_free(ctx);
return ret;
}
#endif /* OPENSSL_NO_DSA */
static OSSL_PARAM *do_construct_hkdf_params(char *digest, char *key,
size_t keylen, char *salt)
{
OSSL_PARAM *params = OPENSSL_malloc(sizeof(OSSL_PARAM) * 5);
OSSL_PARAM *p = params;
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, digest, 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
salt, strlen(salt));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
(unsigned char *)key, keylen);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE,
"EXTRACT_ONLY", 0);
*p = OSSL_PARAM_construct_end();
return params;
}
static int test_evp_pkey_ctx_dup_kdf(void)
{
int ret = 0;
size_t len = 0, dlen = 0;
EVP_PKEY_CTX *pctx = NULL, *dctx = NULL;
OSSL_PARAM *params = NULL;
if (!TEST_ptr(params = do_construct_hkdf_params("sha256", "secret", 6,
"salt")))
goto err;
if (!TEST_ptr(pctx = EVP_PKEY_CTX_new_from_name(NULL, "HKDF", NULL)))
goto err;
if (!TEST_int_eq(EVP_PKEY_derive_init_ex(pctx, params), 1))
goto err;
if (!TEST_ptr(dctx = EVP_PKEY_CTX_dup(pctx)))
goto err;
if (!TEST_int_eq(EVP_PKEY_derive(pctx, NULL, &len), 1)
|| !TEST_size_t_eq(len, SHA256_DIGEST_LENGTH)
|| !TEST_int_eq(EVP_PKEY_derive(dctx, NULL, &dlen), 1)
|| !TEST_size_t_eq(dlen, SHA256_DIGEST_LENGTH))
goto err;
ret = 1;
err:
OPENSSL_free(params);
EVP_PKEY_CTX_free(dctx);
EVP_PKEY_CTX_free(pctx);
return ret;
}
int setup_tests(void)
{
if (!test_skip_common_options()) {
TEST_error("Error parsing test options\n");
return 0;
}
if (!TEST_ptr(datadir = test_get_argument(0)))
return 0;
ADD_TEST(test_evp_pkey_ctx_dup_kdf);
ADD_TEST(test_evp_pkey_get_bn_param_large);
ADD_TEST(test_fromdata_rsa);
#ifndef OPENSSL_NO_DH
ADD_TEST(test_fromdata_dh_fips186_4);
ADD_TEST(test_fromdata_dh_named_group);
#endif
#ifndef OPENSSL_NO_DSA
ADD_TEST(test_check_dsa);
ADD_TEST(test_fromdata_dsa_fips186_4);
#endif
#ifndef OPENSSL_NO_EC
ADD_ALL_TESTS(test_fromdata_ecx, 4 * 3);
ADD_TEST(test_fromdata_ec);
ADD_TEST(test_ec_dup_no_operation);
ADD_TEST(test_ec_dup_keygen_operation);
#endif
return 1;
}