return NULL;
}
+/**
+ * @brief Duplicate a SLH_DSA_HASH_CTX
+ *
+ * @param ctx The SLH_DSA_HASH_CTX object to duplicate.
+ */
+SLH_DSA_HASH_CTX *ossl_slh_dsa_hash_ctx_dup(const SLH_DSA_HASH_CTX *src)
+{
+ SLH_DSA_HASH_CTX *ret = OPENSSL_zalloc(sizeof(*ret));
+
+ if (ret == NULL)
+ return NULL;
+
+ ret->hmac_digest_used = src->hmac_digest_used;
+ /* Note that the key is not ref counted, since it does not own the key */
+ ret->key = src->key;
+
+ if (src->md_ctx != NULL
+ && (ret->md_ctx = EVP_MD_CTX_dup(src->md_ctx)) == NULL)
+ goto err;
+ if (src->md_big_ctx != NULL) {
+ if (src->md_big_ctx != src->md_ctx) {
+ if ((ret->md_big_ctx = EVP_MD_CTX_dup(src->md_big_ctx)) == NULL)
+ goto err;
+ } else {
+ ret->md_big_ctx = ret->md_ctx;
+ }
+ }
+ if (src->hmac_ctx != NULL
+ && (ret->hmac_ctx = EVP_MAC_CTX_dup(src->hmac_ctx)) == NULL)
+ goto err;
+ return ret;
+ err:
+ ossl_slh_dsa_hash_ctx_free(ret);
+ return NULL;
+}
+
/**
* @brief Destroy a SLH_DSA_HASH_CTX
*
static OSSL_FUNC_keymgmt_gen_cleanup_fn slh_dsa_gen_cleanup;
static OSSL_FUNC_keymgmt_gen_set_params_fn slh_dsa_gen_set_params;
static OSSL_FUNC_keymgmt_gen_settable_params_fn slh_dsa_gen_settable_params;
+static OSSL_FUNC_keymgmt_dup_fn slh_dsa_dup_key;
#define SLH_DSA_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
ossl_slh_dsa_key_free((SLH_DSA_KEY *)keydata);
}
+static void *slh_dsa_dup_key(const void *keydata_from, int selection)
+{
+ if (ossl_prov_is_running())
+ return ossl_slh_dsa_key_dup(keydata_from, selection);
+ return NULL;
+}
+
static int slh_dsa_has(const void *keydata, int selection)
{
const SLH_DSA_KEY *key = keydata;
const OSSL_DISPATCH ossl_slh_dsa_##fn##_keymgmt_functions[] = { \
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))slh_dsa_##fn##_new_key }, \
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))slh_dsa_free_key }, \
+ { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))slh_dsa_dup_key }, \
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))slh_dsa_has }, \
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))slh_dsa_match }, \
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))slh_dsa_import }, \
static OSSL_FUNC_signature_digest_sign_fn slh_dsa_digest_sign;
static OSSL_FUNC_signature_digest_verify_fn slh_dsa_digest_verify;
static OSSL_FUNC_signature_freectx_fn slh_dsa_freectx;
+static OSSL_FUNC_signature_dupctx_fn slh_dsa_dupctx;
static OSSL_FUNC_signature_set_ctx_params_fn slh_dsa_set_ctx_params;
static OSSL_FUNC_signature_settable_ctx_params_fn slh_dsa_settable_ctx_params;
+/*
+ * NOTE: Any changes to this structure may require updating slh_dsa_dupctx().
+ */
typedef struct {
SLH_DSA_KEY *key; /* Note that the key is not owned by this object */
SLH_DSA_HASH_CTX *hash_ctx;
return NULL;
}
+static void *slh_dsa_dupctx(void *vctx)
+{
+ PROV_SLH_DSA_CTX *src = (PROV_SLH_DSA_CTX *)vctx;
+ PROV_SLH_DSA_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ /*
+ * Note that the SLH_DSA_KEY is ref counted via EVP_PKEY so we can just copy
+ * the key here.
+ */
+ ret = OPENSSL_memdup(src, sizeof(*src));
+ if (ret == NULL)
+ return NULL;
+ ret->propq = NULL;
+ ret->hash_ctx = NULL;
+ if (src->propq != NULL && (ret->propq = OPENSSL_strdup(src->propq)) == NULL)
+ goto err;
+ ret->hash_ctx = ossl_slh_dsa_hash_ctx_dup(src->hash_ctx);
+ if (ret->hash_ctx == NULL)
+ goto err;
+
+ return ret;
+ err:
+ slh_dsa_freectx(ret);
+ return NULL;
+}
+
static int slh_dsa_set_alg_id_buffer(PROV_SLH_DSA_CTX *ctx)
{
int ret;
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY, \
(void (*)(void))slh_dsa_digest_verify }, \
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))slh_dsa_freectx }, \
+ { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))slh_dsa_dupctx }, \
{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))slh_dsa_set_ctx_params },\
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, \
(void (*)(void))slh_dsa_settable_ctx_params }, \
static int slh_dsa_key_eq_test(void)
{
int ret = 0;
- EVP_PKEY *key[3] = { NULL, NULL, NULL };
+ size_t i;
+ EVP_PKEY *key[4] = { NULL, NULL, NULL, NULL };
SLH_DSA_SIG_TEST_DATA *td1 = &slh_dsa_sig_testdata[0];
SLH_DSA_SIG_TEST_DATA *td2 = &slh_dsa_sig_testdata[1];
#ifndef OPENSSL_NO_EC
if (!TEST_ptr(key[0] = slh_dsa_key_from_data(td1->alg, td1->pub, td1->pub_len, 1))
|| !TEST_ptr(key[1] = slh_dsa_key_from_data(td1->alg, td1->pub, td1->pub_len, 1))
- || !TEST_ptr(key[2] = slh_dsa_key_from_data(td2->alg, td2->pub, td2->pub_len, 1)))
+ || !TEST_ptr(key[2] = slh_dsa_key_from_data(td2->alg, td2->pub, td2->pub_len, 1))
+ || !TEST_ptr(key[3] = EVP_PKEY_dup(key[0])))
goto end;
if (!TEST_int_eq(EVP_PKEY_eq(key[0], key[1]), 1)
- || !TEST_int_ne(EVP_PKEY_eq(key[0], key[2]), 1))
+ || !TEST_int_ne(EVP_PKEY_eq(key[0], key[2]), 1)
+ || !TEST_int_eq(EVP_PKEY_eq(key[0], key[3]), 1))
goto end;
#ifndef OPENSSL_NO_EC
#else
ret = 1;
#endif
-end:
- EVP_PKEY_free(key[2]);
- EVP_PKEY_free(key[1]);
- EVP_PKEY_free(key[0]);
+ end:
+ for (i = 0; i < OSSL_NELEM(key); ++i)
+ EVP_PKEY_free(key[i]);
return ret;
}
EVP_CIPHER *cipher = NULL; /* Used to encrypt the private key */
char *pass = "Password";
BIO *pub_bio = NULL, *priv_bio = NULL;
- EVP_PKEY_CTX *gctx = NULL, *sctx = NULL, *vctx = NULL;
+ EVP_PKEY_CTX *gctx = NULL, *sctx = NULL, *vctx = NULL, *dupctx = NULL;
EVP_PKEY *gkey = NULL, *pub = NULL, *priv = NULL;
EVP_SIGNATURE *sig_alg = NULL;
uint8_t *sig = NULL;
- size_t sig_len = 0;
+ size_t sig_len = 0, len = 0;
uint8_t msg[] = { 0x01, 0x02, 0x03, 0x04 };
size_t msg_len = sizeof(msg);
const SLH_DSA_KEYGEN_TEST_DATA *tst = &slh_dsa_keygen_testdata[0];
|| !TEST_int_eq(EVP_PKEY_sign_message_init(sctx, sig_alg, params), 1))
goto err;
+ if (!TEST_ptr(dupctx = EVP_PKEY_CTX_dup(sctx)))
+ goto err;
+
/* Determine the size of the signature & allocate space */
- if (!TEST_int_eq(EVP_PKEY_sign(sctx, NULL, &sig_len, msg, msg_len), 1)
- || !TEST_ptr(sig = OPENSSL_malloc(sig_len))
- || !TEST_int_eq(EVP_PKEY_sign(sctx, sig, &sig_len, msg, msg_len), 1))
+ if (!TEST_int_eq(EVP_PKEY_sign(sctx, NULL, &sig_len, msg, msg_len), 1))
+ goto err;
+ len = sig_len;
+ if (!TEST_ptr(sig = OPENSSL_zalloc(sig_len * 2))
+ || !TEST_int_eq(EVP_PKEY_sign(sctx, sig, &len, msg, msg_len), 1)
+ || !TEST_size_t_eq(sig_len, len)
+ || !TEST_int_eq(EVP_PKEY_sign(dupctx, sig + sig_len, &len,
+ msg, msg_len), 1)
+ || !TEST_size_t_eq(sig_len, len))
goto err;
/* Read the public key and add to a verify ctx */
if (!TEST_ptr(PEM_read_bio_PUBKEY_ex(pub_bio, &pub, NULL, NULL, lib_ctx, NULL))
|| !TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, pub, NULL)))
goto err;
+ EVP_PKEY_CTX_free(dupctx);
+
/* verify the signature */
if (!TEST_int_eq(EVP_PKEY_verify_message_init(vctx, sig_alg, NULL), 1)
- || !TEST_int_eq(EVP_PKEY_verify(vctx, sig, sig_len, msg, msg_len), 1))
+ || !TEST_ptr(dupctx = EVP_PKEY_CTX_dup(vctx))
+ || !TEST_int_eq(EVP_PKEY_verify(vctx, sig, sig_len, msg, msg_len), 1)
+ || !TEST_int_eq(EVP_PKEY_verify(dupctx, sig + sig_len, sig_len,
+ msg, msg_len), 1))
goto err;
ret = 1;
err:
EVP_PKEY_CTX_free(gctx);
EVP_PKEY_CTX_free(sctx);
EVP_PKEY_CTX_free(vctx);
+ EVP_PKEY_CTX_free(dupctx);
BIO_free(pub_bio);
BIO_free(priv_bio);
OPENSSL_free(sig);