Add SLH_DSA key validation.

The pairwise test requires that the computed PK_ROOT key matches the
keys PK_ROOT value. The public and private key tests just require the
key elements to exist.

Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25882)
This commit is contained in:
slontis 2024-11-21 16:09:18 +11:00 committed by Tomas Mraz
parent b8b67b1907
commit eba0e11c39
14 changed files with 331 additions and 243 deletions

View File

@ -15,8 +15,10 @@
#include <openssl/rand.h>
#include "slh_dsa_local.h"
#include "slh_dsa_key.h"
#include "internal/encoder.h"
static int slh_dsa_compute_pk_root(SLH_DSA_CTX *ctx, SLH_DSA_KEY *out);
static int slh_dsa_compute_pk_root(SLH_DSA_CTX *ctx, SLH_DSA_KEY *out,
int verify);
/**
* @brief Create a new SLH_DSA_KEY object
@ -142,6 +144,22 @@ int ossl_slh_dsa_key_has(const SLH_DSA_KEY *key, int selection)
return 0;
}
int ossl_slh_dsa_key_pairwise_check(const SLH_DSA_KEY *key)
{
int ret;
SLH_DSA_CTX *ctx = NULL;
if (key->pub == NULL || key->has_priv == 0)
return 0;
ctx = ossl_slh_dsa_ctx_new(key->params->alg, key->libctx, key->propq);
if (ctx == NULL)
return 0;
ret = slh_dsa_compute_pk_root(ctx, (SLH_DSA_KEY *)key, 1);
ossl_slh_dsa_ctx_free(ctx);
return ret;
}
/**
* @brief Load a SLH_DSA key from raw data.
*
@ -213,20 +231,28 @@ int ossl_slh_dsa_key_fromdata(SLH_DSA_KEY *key, const OSSL_PARAM params[],
* @param ctx Contains SLH_DSA algorithm functions and constants.
* @param out A SLH_DSA key containing the private key (seed and prf) and public key seed.
* The public root key is written to this key.
* @returns 1 if the root key is generated, or 0 on error.
* @param validate If set to 1 the computed public key is not written to the key,
* but will be compared to the existing value.
* @returns 1 if the root key is generated or compared successfully, or 0 on error.
*/
static int slh_dsa_compute_pk_root(SLH_DSA_CTX *ctx, SLH_DSA_KEY *out)
static int slh_dsa_compute_pk_root(SLH_DSA_CTX *ctx, SLH_DSA_KEY *out,
int validate)
{
SLH_ADRS_FUNC_DECLARE(ctx, adrsf);
SLH_ADRS_DECLARE(adrs);
const SLH_DSA_PARAMS *params = out->params;
size_t n = params->n;
uint8_t pk_root[SLH_DSA_MAX_N], *dst;
adrsf->zero(adrs);
adrsf->set_layer_address(adrs, params->d - 1);
dst = validate ? pk_root : SLH_DSA_PK_ROOT(out);
/* Generate the ROOT public key */
return ossl_slh_xmss_node(ctx, SLH_DSA_SK_SEED(out), 0, params->hm,
SLH_DSA_PK_SEED(out), adrs,
SLH_DSA_PK_ROOT(out), params->n);
SLH_DSA_PK_SEED(out), adrs, dst, n)
&& (validate == 0 || memcmp(dst, SLH_DSA_PK_ROOT(out), n) == 0);
}
/**
@ -265,7 +291,7 @@ int ossl_slh_dsa_generate_key(SLH_DSA_CTX *ctx, OSSL_LIB_CTX *lib_ctx,
|| RAND_bytes_ex(lib_ctx, pub, pk_seed_len, 0) <= 0)
goto err;
}
if (!slh_dsa_compute_pk_root(ctx, out))
if (!slh_dsa_compute_pk_root(ctx, out, 0))
goto err;
out->pub = pub;
out->has_priv = 1;
@ -358,3 +384,40 @@ int ossl_slh_dsa_set_pub(SLH_DSA_KEY *key, const uint8_t *pub, size_t pub_len)
key->has_priv = 0;
return 1;
}
int ossl_slh_dsa_key_to_text(BIO *out, const SLH_DSA_KEY *key, int selection)
{
const char *name;
if (out == NULL || key == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (ossl_slh_dsa_key_get_pub(key) == NULL) {
/* Regardless of the |selection|, there must be a public key */
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
return 0;
}
name = ossl_slh_dsa_key_get_name(key);
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
if (ossl_slh_dsa_key_get_priv(key) == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
return 0;
}
if (BIO_printf(out, "%s Private-Key:\n", name) <= 0)
return 0;
if (!ossl_bio_print_labeled_buf(out, "priv:", ossl_slh_dsa_key_get_priv(key),
ossl_slh_dsa_key_get_priv_len(key)))
return 0;
} else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
if (BIO_printf(out, "%s Public-Key:\n", name) <= 0)
return 0;
}
if (!ossl_bio_print_labeled_buf(out, "pub:", ossl_slh_dsa_key_get_pub(key),
ossl_slh_dsa_key_get_pub_len(key)))
return 0;
return 1;
}

View File

@ -15,6 +15,22 @@
#include "crypto/x509.h"
#include "crypto/slh_dsa.h"
/* Minimal ASN1 method table to support PUB_KEY decoding */
#define IMPLEMENT_PKEY_ASN1_METHOD(alg, name, PKEY_NAME) \
const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_##name##_asn1_meth = \
{ \
EVP_PKEY_SLH_DSA_##PKEY_NAME, EVP_PKEY_SLH_DSA_##PKEY_NAME, \
0, \
alg, \
"OpenSSL " alg " algorithm", \
slh_dsa_pub_decode, NULL, NULL, NULL, \
NULL, NULL, NULL, \
NULL, NULL, NULL, \
NULL, NULL, NULL, NULL, NULL, NULL, \
NULL, \
slh_dsa_free, \
}
static SLH_DSA_KEY *ossl_slh_dsa_key_create(const X509_ALGOR *palg,
const unsigned char *p, int p_len,
int id, int public,
@ -83,21 +99,6 @@ static void slh_dsa_free(EVP_PKEY *pkey)
ossl_slh_dsa_key_free(pkey->pkey.slh_dsa);
}
/* Minimal ASN1 method table to support PUB_KEY decoding */
#define IMPLEMENT_PKEY_ASN1_METHOD(alg, name, PKEY_NAME) \
const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_##name##_asn1_meth = { \
EVP_PKEY_SLH_DSA_##PKEY_NAME, EVP_PKEY_SLH_DSA_##PKEY_NAME, \
0, \
alg, \
"OpenSSL " alg " algorithm", \
slh_dsa_pub_decode, NULL, NULL, NULL, \
NULL, NULL, NULL, \
NULL, NULL, NULL, \
NULL, NULL, NULL, NULL, NULL, NULL, \
NULL, \
slh_dsa_free, \
}
IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-128s", sha2_128s, SHA2_128S);
IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-128f", sha2_128f, SHA2_128F);
IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-192s", sha2_192s, SHA2_192S);

View File

@ -1054,17 +1054,17 @@ static int i2d_SLH_DSA_PUBKEY(const SLH_DSA_KEY *a, unsigned char **pp,
return ret;
}
#define IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(alg) \
int ossl_i2d_SLH_DSA_##alg##_PUBKEY(const SLH_DSA_KEY *a, unsigned char **pp) \
{ \
# define IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(alg) \
int ossl_i2d_SLH_DSA_##alg##_PUBKEY(const SLH_DSA_KEY *a, unsigned char **pp)\
{ \
return i2d_SLH_DSA_PUBKEY(a, pp, EVP_PKEY_SLH_DSA_##alg); \
} \
SLH_DSA_KEY *ossl_d2i_SLH_DSA_##alg##_PUBKEY(SLH_DSA_KEY **a, \
} \
SLH_DSA_KEY *ossl_d2i_SLH_DSA_##alg##_PUBKEY(SLH_DSA_KEY **a, \
const unsigned char **pp, \
long length) \
{ \
{ \
return d2i_SLH_DSA_PUBKEY(a, pp, length, EVP_PKEY_SLH_DSA_##alg); \
}
}
IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHA2_128S)
IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHA2_128F)

View File

@ -60,7 +60,7 @@ The fields 'key_len' and 'has_priv' are used to determine if a key has loaded
the public and private key elements.
The 'params' field is the parameter set which is resolved via the algorithm name.
The FIPS 205 the SLH_DSA private key contains the public key.
In FIPS 205 the SLH_DSA private key contains the public key.
In OpenSSL these components are stored separately, so there must always be a
public key in order for the key to be valid.

View File

@ -663,10 +663,10 @@ union legacy_pkey_st {
# ifndef OPENSSL_NO_ECX
ECX_KEY *ecx; /* X25519, X448, Ed25519, Ed448 */
# endif
# endif
# ifndef OPENSSL_NO_SLH_DSA
SLH_DSA_KEY *slh_dsa; /* SLH_DSA_* */
# endif
# endif
};
struct evp_pkey_st {

View File

@ -27,11 +27,13 @@ __owur int ossl_slh_dsa_key_up_ref(SLH_DSA_KEY *key);
__owur int ossl_slh_dsa_key_equal(const SLH_DSA_KEY *key1, const SLH_DSA_KEY *key2,
int selection);
__owur int ossl_slh_dsa_key_has(const SLH_DSA_KEY *key, int selection);
__owur int ossl_slh_dsa_key_pairwise_check(const SLH_DSA_KEY *key);
__owur int ossl_slh_dsa_key_fromdata(SLH_DSA_KEY *key, const OSSL_PARAM *params,
int include_private);
__owur int ossl_slh_dsa_generate_key(SLH_DSA_CTX *ctx, OSSL_LIB_CTX *libctx,
const uint8_t *entropy, size_t entropy_len,
SLH_DSA_KEY *out);
__owur int ossl_slh_dsa_key_to_text(BIO *out, const SLH_DSA_KEY *key, int selection);
__owur const uint8_t *ossl_slh_dsa_key_get_pub(const SLH_DSA_KEY *key);
__owur const uint8_t *ossl_slh_dsa_key_get_priv(const SLH_DSA_KEY *key);
__owur size_t ossl_slh_dsa_key_get_pub_len(const SLH_DSA_KEY *key);

View File

@ -622,7 +622,7 @@ ml_kem_d2i_PUBKEY(const uint8_t **der, long der_len,
#endif
# ifndef OPENSSL_NO_SLH_DSA
#ifndef OPENSSL_NO_SLH_DSA
/* SLH_DSA only implements PKCS#8 and SubjectPublicKeyInfo */
@ -757,9 +757,7 @@ static void slh_dsa_key_adjust(void *key, struct der2key_ctx_st *ctx)
# define slh_dsa_shake_256f_free (free_key_fn *)ossl_slh_dsa_key_free
# define slh_dsa_shake_256f_check NULL
# define slh_dsa_shake_256f_adjust slh_dsa_key_adjust
# endif /* OPENSSL_NO_SLH_DSA */
#endif /* OPENSSL_NO_SLH_DSA */
/* ---------------------------------------------------------------------- */

View File

@ -1628,8 +1628,6 @@ MAKE_ENCODER(slh_dsa_shake_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192S, Encrypted
MAKE_ENCODER(slh_dsa_shake_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192F, EncryptedPrivateKeyInfo, pem);
MAKE_ENCODER(slh_dsa_shake_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256S, EncryptedPrivateKeyInfo, pem);
MAKE_ENCODER(slh_dsa_shake_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256F, EncryptedPrivateKeyInfo, pem);
MAKE_ENCODER(slh_dsa_sha2_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128S, PrivateKeyInfo, der);
MAKE_ENCODER(slh_dsa_sha2_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128F, PrivateKeyInfo, der);
MAKE_ENCODER(slh_dsa_sha2_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192S, PrivateKeyInfo, der);
@ -1654,7 +1652,6 @@ MAKE_ENCODER(slh_dsa_shake_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192S, PrivateKe
MAKE_ENCODER(slh_dsa_shake_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192F, PrivateKeyInfo, pem);
MAKE_ENCODER(slh_dsa_shake_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256S, PrivateKeyInfo, pem);
MAKE_ENCODER(slh_dsa_shake_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256F, PrivateKeyInfo, pem);
MAKE_ENCODER(slh_dsa_sha2_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128S, SubjectPublicKeyInfo, der);
MAKE_ENCODER(slh_dsa_sha2_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128F, SubjectPublicKeyInfo, der);
MAKE_ENCODER(slh_dsa_sha2_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192S, SubjectPublicKeyInfo, der);

View File

@ -449,41 +449,8 @@ static int ml_kem_to_text(BIO *out, const void *vkey, int selection)
#ifndef OPENSSL_NO_SLH_DSA
static int slh_dsa_to_text(BIO *out, const void *key, int selection)
{
const char *name;
if (out == NULL || key == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (ossl_slh_dsa_key_get_pub(key) == NULL) {
/* Regardless of the |selection|, there must be a public key */
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
return 0;
}
name = ossl_slh_dsa_key_get_name(key);
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
if (ossl_slh_dsa_key_get_priv(key) == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
return 0;
}
if (BIO_printf(out, "%s Private-Key:\n", name) <= 0)
return 0;
if (!print_labeled_buf(out, "priv:", ossl_slh_dsa_key_get_priv(key),
ossl_slh_dsa_key_get_priv_len(key)))
return 0;
} else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
if (BIO_printf(out, "%s Public-Key:\n", name) <= 0)
return 0;
}
if (!print_labeled_buf(out, "pub:", ossl_slh_dsa_key_get_pub(key),
ossl_slh_dsa_key_get_pub_len(key)))
return 0;
return 1;
return ossl_slh_dsa_key_to_text(out, (SLH_DSA_KEY *)key, selection);
}
#endif /* OPENSSL_NO_SLH_DSA */
static int rsa_to_text(BIO *out, const void *key, int selection)

View File

@ -27,6 +27,7 @@ static OSSL_FUNC_keymgmt_export_types_fn slh_dsa_imexport_types;
static OSSL_FUNC_keymgmt_load_fn slh_dsa_load;
static OSSL_FUNC_keymgmt_get_params_fn slh_dsa_get_params;
static OSSL_FUNC_keymgmt_gettable_params_fn slh_dsa_gettable_params;
static OSSL_FUNC_keymgmt_validate_fn slh_dsa_validate;
static OSSL_FUNC_keymgmt_gen_init_fn slh_dsa_gen_init;
static OSSL_FUNC_keymgmt_gen_cleanup_fn slh_dsa_gen_cleanup;
static OSSL_FUNC_keymgmt_gen_set_params_fn slh_dsa_gen_set_params;
@ -79,6 +80,18 @@ static int slh_dsa_match(const void *keydata1, const void *keydata2, int selecti
return ossl_slh_dsa_key_equal(key1, key2, selection);
}
static int slh_dsa_validate(const void *key_data, int selection, int check_type)
{
const SLH_DSA_KEY *key = key_data;
if (!slh_dsa_has(key, selection))
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
return ossl_slh_dsa_key_pairwise_check(key);
return 1;
}
static int slh_dsa_import(void *keydata, int selection, const OSSL_PARAM params[])
{
SLH_DSA_KEY *key = keydata;
@ -400,6 +413,7 @@ static void slh_dsa_gen_cleanup(void *genctx)
{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))slh_dsa_load }, \
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))slh_dsa_get_params }, \
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))slh_dsa_gettable_params },\
{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))slh_dsa_validate }, \
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))slh_dsa_gen_init }, \
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))slh_dsa_##fn##_gen }, \
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))slh_dsa_gen_cleanup },\

View File

@ -110,7 +110,8 @@ static EVP_PKEY *make_template(const char *type, OSSL_PARAM *genparams)
!defined(OPENSSL_NO_DSA) || \
!defined(OPENSSL_NO_EC) || \
!defined(OPENSSL_NO_ML_DSA) || \
!defined(OPENSSL_NO_ML_KEM)
!defined(OPENSSL_NO_ML_KEM) || \
!defined(OPENSSL_NO_SLH_DSA)
static EVP_PKEY *make_key(const char *type, EVP_PKEY *template,
OSSL_PARAM *genparams)
{
@ -1396,7 +1397,7 @@ int setup_tests(void)
/* FIPS(3.0.0): provider imports explicit params but they won't work #17998 */
is_fips_3_0_0 = is_fips && fips_provider_version_eq(testctx, 3, 0, 0);
/* FIPS(3.5.0) is the first to support ML-KEM and ML-DSA */
/* FIPS(3.5.0) is the first to support ML-DSA, ML-KEM and SLH-DSA */
is_fips_lt_3_5 = is_fips && fips_provider_version_lt(testctx, 3, 5, 0);
#ifdef STATIC_LEGACY
@ -1480,6 +1481,7 @@ int setup_tests(void)
}
#endif
#ifndef OPENSSL_NO_SLH_DSA
if (!is_fips_lt_3_5) {
MAKE_KEYS(SLH_DSA_SHA2_128s, "SLH-DSA-SHA2-128s", NULL);
MAKE_KEYS(SLH_DSA_SHA2_128f, "SLH-DSA-SHA2-128f", NULL);
MAKE_KEYS(SLH_DSA_SHA2_192s, "SLH-DSA-SHA2-192s", NULL);
@ -1492,6 +1494,7 @@ int setup_tests(void)
MAKE_KEYS(SLH_DSA_SHAKE_192f, "SLH-DSA-SHAKE-192f", NULL);
MAKE_KEYS(SLH_DSA_SHAKE_256s, "SLH-DSA-SHAKE-256s", NULL);
MAKE_KEYS(SLH_DSA_SHAKE_256f, "SLH-DSA-SHAKE-256f", NULL);
}
#endif /* OPENSSL_NO_SLH_DSA */
TEST_info("Loading RSA key...");
@ -1581,6 +1584,7 @@ int setup_tests(void)
#endif /* OPENSSL_NO_ML_DSA */
#ifndef OPENSSL_NO_SLH_DSA
if (!is_fips_lt_3_5) {
ADD_TEST_SUITE(SLH_DSA_SHA2_128s);
ADD_TEST_SUITE(SLH_DSA_SHA2_128f);
ADD_TEST_SUITE(SLH_DSA_SHA2_192s);
@ -1593,6 +1597,7 @@ int setup_tests(void)
ADD_TEST_SUITE(SLH_DSA_SHAKE_192f);
ADD_TEST_SUITE(SLH_DSA_SHAKE_256s);
ADD_TEST_SUITE(SLH_DSA_SHAKE_256f);
}
#endif /* OPENSSL_NO_SLH_DSA */
}
@ -1659,6 +1664,7 @@ void cleanup_tests(void)
#endif /* OPENSSL_NO_ML_DSA */
#ifndef OPENSSL_NO_SLH_DSA
if (!is_fips_lt_3_5) {
FREE_KEYS(SLH_DSA_SHA2_128s);
FREE_KEYS(SLH_DSA_SHA2_128f);
FREE_KEYS(SLH_DSA_SHA2_192s);
@ -1671,6 +1677,7 @@ void cleanup_tests(void)
FREE_KEYS(SLH_DSA_SHAKE_192f);
FREE_KEYS(SLH_DSA_SHAKE_256s);
FREE_KEYS(SLH_DSA_SHAKE_256f);
}
#endif /* OPENSSL_NO_SLH_DSA */
OSSL_PROVIDER_unload(nullprov);

View File

@ -28,20 +28,22 @@ static OSSL_LIB_CTX *lib_ctx = NULL;
static OSSL_PROVIDER *null_prov = NULL;
static OSSL_PROVIDER *lib_prov = NULL;
static EVP_PKEY *slh_dsa_pubkey_from_data(const char *alg,
const unsigned char *data, size_t datalen)
static EVP_PKEY *slh_dsa_key_from_data(const char *alg,
const unsigned char *data, size_t datalen,
int public)
{
int ret;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *key = NULL;
OSSL_PARAM params[2];
const char *keytype = public ? OSSL_PKEY_PARAM_PUB_KEY : OSSL_PKEY_PARAM_PRIV_KEY;
int selection = public ? EVP_PKEY_PUBLIC_KEY : EVP_PKEY_KEYPAIR;
params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
(unsigned char *)data, datalen);
params[0] = OSSL_PARAM_construct_octet_string(keytype, (uint8_t *)data, datalen);
params[1] = OSSL_PARAM_construct_end();
ret = TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(lib_ctx, alg, NULL))
&& TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1)
&& (EVP_PKEY_fromdata(ctx, &key, EVP_PKEY_PUBLIC_KEY, params) == 1);
&& (EVP_PKEY_fromdata(ctx, &key, selection, params) == 1);
if (ret == 0) {
EVP_PKEY_free(key);
key = NULL;
@ -96,10 +98,10 @@ static int slh_dsa_bad_pub_len_test(void)
OPENSSL_cleanse(pubdata, sizeof(pubdata));
memcpy(pubdata, td->pub, td->pub_len);
if (!TEST_ptr_null(pkey = slh_dsa_pubkey_from_data(td->alg, pubdata,
td->pub_len - 1))
|| !TEST_ptr_null(pkey = slh_dsa_pubkey_from_data(td->alg, pubdata,
td->pub_len + 1)))
if (!TEST_ptr_null(pkey = slh_dsa_key_from_data(td->alg, pubdata,
td->pub_len - 1, 1))
|| !TEST_ptr_null(pkey = slh_dsa_key_from_data(td->alg, pubdata,
td->pub_len + 1, 1)))
goto end;
ret = 1;
@ -121,9 +123,9 @@ static int slh_dsa_key_eq_test(void)
EVP_PKEY *eckey = NULL;
#endif
if (!TEST_ptr(key[0] = slh_dsa_pubkey_from_data(td1->alg, td1->pub, td1->pub_len))
|| !TEST_ptr(key[1] = slh_dsa_pubkey_from_data(td1->alg, td1->pub, td1->pub_len))
|| !TEST_ptr(key[2] = slh_dsa_pubkey_from_data(td2->alg, td2->pub, td2->pub_len)))
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)))
goto end;
if (!TEST_int_eq(EVP_PKEY_eq(key[0], key[1]), 1)
@ -152,13 +154,44 @@ static int slh_dsa_key_validate_test(void)
EVP_PKEY_CTX *vctx = NULL;
EVP_PKEY *key = NULL;
if (!TEST_ptr(key = slh_dsa_pubkey_from_data(td->alg, td->pub, td->pub_len)))
if (!TEST_ptr(key = slh_dsa_key_from_data(td->alg, td->pub, td->pub_len, 1)))
return 0;
if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL)))
goto end;
ret = TEST_int_eq(EVP_PKEY_check(vctx), 1);
EVP_PKEY_CTX_free(vctx);
if (!TEST_int_eq(EVP_PKEY_public_check(vctx), 1))
goto end;
if (!TEST_int_eq(EVP_PKEY_private_check(vctx), 0))
goto end;
if (!TEST_int_eq(EVP_PKEY_pairwise_check(vctx), 0))
goto end;
ret = 1;
end:
EVP_PKEY_CTX_free(vctx);
EVP_PKEY_free(key);
return ret;
}
static int slh_dsa_key_validate_failure_test(void)
{
int ret = 0;
EVP_PKEY_CTX *vctx = NULL;
EVP_PKEY *key = NULL;
/*
* Loading 128s private key data into a 128f algorithm will have an incorrect
* public key.
*/
if (!TEST_ptr(key = slh_dsa_key_from_data("SLH-DSA-SHA2-128f",
slh_dsa_sha2_128s_0_keygen_priv,
sizeof(slh_dsa_sha2_128s_0_keygen_priv), 0)))
return 0;
if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL)))
goto end;
if (!TEST_int_eq(EVP_PKEY_pairwise_check(vctx), 0))
goto end;
ret = 1;
end:
EVP_PKEY_CTX_free(vctx);
EVP_PKEY_free(key);
return ret;
}
@ -182,7 +215,7 @@ static int do_slh_dsa_verify(const SLH_DSA_SIG_TEST_DATA *td,
*p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, &encode);
*p = OSSL_PARAM_construct_end();
if (!TEST_ptr(key = slh_dsa_pubkey_from_data(td->alg, td->pub, td->pub_len)))
if (!TEST_ptr(key = slh_dsa_key_from_data(td->alg, td->pub, td->pub_len, 1)))
return 0;
if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL)))
goto err;
@ -365,6 +398,10 @@ static int slh_dsa_usage_test(void)
|| !TEST_ptr(sig = OPENSSL_malloc(sig_len))
|| !TEST_int_eq(EVP_PKEY_sign(sctx, sig, &sig_len, msg, msg_len), 1))
goto err;
if (!TEST_true(EVP_PKEY_pairwise_check(sctx))
|| !TEST_true(EVP_PKEY_public_check(sctx))
|| !TEST_true(EVP_PKEY_private_check(sctx)))
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)))
@ -373,6 +410,7 @@ static int slh_dsa_usage_test(void)
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))
goto err;
ret = 1;
err:
EVP_CIPHER_free(cipher);
@ -495,6 +533,7 @@ int setup_tests(void)
ADD_TEST(slh_dsa_bad_pub_len_test);
ADD_TEST(slh_dsa_key_validate_test);
ADD_TEST(slh_dsa_key_validate_failure_test);
ADD_TEST(slh_dsa_key_eq_test);
ADD_TEST(slh_dsa_usage_test);
ADD_TEST(slh_dsa_deterministic_usage_test);