From 06937de11d302de72f3f88f4620592bceb32bec2 Mon Sep 17 00:00:00 2001 From: slontis Date: Tue, 1 Oct 2024 16:17:05 +1000 Subject: [PATCH] Add LMS to the fips provider. This required the LMS keymanager to have an export function. The self test will be provided by HSS, which covers the LMS case. Reviewed-by: Hugo Landau Reviewed-by: Dmitry Belyavskiy Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/25598) --- crypto/lms/build.info | 1 + providers/fips/fipsprov.c | 37 +++++++----- providers/implementations/keymgmt/build.info | 2 +- providers/implementations/keymgmt/lms_kmgmt.c | 40 +++++++++++++ .../implementations/signature/build.info | 4 +- .../signature/{lms_sig.c => lms_signature.c} | 0 test/lms_test.c | 58 ++++++++++++++++++- test/recipes/30-test_lms.t | 11 +++- 8 files changed, 131 insertions(+), 22 deletions(-) rename providers/implementations/signature/{lms_sig.c => lms_signature.c} (100%) diff --git a/crypto/lms/build.info b/crypto/lms/build.info index 068f3d7d85a..f34366a6311 100644 --- a/crypto/lms/build.info +++ b/crypto/lms/build.info @@ -5,4 +5,5 @@ $COMMON=lms_params.c lms_pubkey_decode.c lms_key.c lm_ots_params.c \ IF[{- !$disabled{'lms'} -}] SOURCE[../../libcrypto]=$COMMON +SOURCE[../../providers/libfips.a]=$COMMON ENDIF diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 825eb329e16..268b15e249c 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -255,21 +255,21 @@ static int fips_self_test(void *provctx) */ #define FIPS_DIGESTS_COMMON() \ -{ PROV_NAMES_SHA1, FIPS_DEFAULT_PROPERTIES, ossl_sha1_functions }, \ -{ PROV_NAMES_SHA2_224, FIPS_DEFAULT_PROPERTIES, ossl_sha224_functions }, \ -{ PROV_NAMES_SHA2_256, FIPS_DEFAULT_PROPERTIES, ossl_sha256_functions }, \ -{ PROV_NAMES_SHA2_384, FIPS_DEFAULT_PROPERTIES, ossl_sha384_functions }, \ -{ PROV_NAMES_SHA2_512, FIPS_DEFAULT_PROPERTIES, ossl_sha512_functions }, \ -{ PROV_NAMES_SHA2_512_224, FIPS_DEFAULT_PROPERTIES, \ - ossl_sha512_224_functions }, \ -{ PROV_NAMES_SHA2_512_256, FIPS_DEFAULT_PROPERTIES, \ - ossl_sha512_256_functions }, \ -{ PROV_NAMES_SHA3_224, FIPS_DEFAULT_PROPERTIES, ossl_sha3_224_functions }, \ -{ PROV_NAMES_SHA3_256, FIPS_DEFAULT_PROPERTIES, ossl_sha3_256_functions }, \ -{ PROV_NAMES_SHA3_384, FIPS_DEFAULT_PROPERTIES, ossl_sha3_384_functions }, \ -{ PROV_NAMES_SHA3_512, FIPS_DEFAULT_PROPERTIES, ossl_sha3_512_functions }, \ -{ PROV_NAMES_SHAKE_128, FIPS_DEFAULT_PROPERTIES, ossl_shake_128_functions }, \ -{ PROV_NAMES_SHAKE_256, FIPS_DEFAULT_PROPERTIES, ossl_shake_256_functions } + { PROV_NAMES_SHA1, FIPS_DEFAULT_PROPERTIES, ossl_sha1_functions }, \ + { PROV_NAMES_SHA2_224, FIPS_DEFAULT_PROPERTIES, ossl_sha224_functions }, \ + { PROV_NAMES_SHA2_256, FIPS_DEFAULT_PROPERTIES, ossl_sha256_functions }, \ + { PROV_NAMES_SHA2_384, FIPS_DEFAULT_PROPERTIES, ossl_sha384_functions }, \ + { PROV_NAMES_SHA2_512, FIPS_DEFAULT_PROPERTIES, ossl_sha512_functions }, \ + { PROV_NAMES_SHA2_512_224, FIPS_DEFAULT_PROPERTIES, \ + ossl_sha512_224_functions }, \ + { PROV_NAMES_SHA2_512_256, FIPS_DEFAULT_PROPERTIES, \ + ossl_sha512_256_functions }, \ + { PROV_NAMES_SHA3_224, FIPS_DEFAULT_PROPERTIES, ossl_sha3_224_functions }, \ + { PROV_NAMES_SHA3_256, FIPS_DEFAULT_PROPERTIES, ossl_sha3_256_functions }, \ + { PROV_NAMES_SHA3_384, FIPS_DEFAULT_PROPERTIES, ossl_sha3_384_functions }, \ + { PROV_NAMES_SHA3_512, FIPS_DEFAULT_PROPERTIES, ossl_sha3_512_functions }, \ + { PROV_NAMES_SHAKE_128, FIPS_DEFAULT_PROPERTIES, ossl_shake_128_functions }, \ + { PROV_NAMES_SHAKE_256, FIPS_DEFAULT_PROPERTIES, ossl_shake_256_functions } static const OSSL_ALGORITHM fips_digests[] = { FIPS_DIGESTS_COMMON(), @@ -485,6 +485,9 @@ static const OSSL_ALGORITHM fips_signature[] = { #ifndef OPENSSL_NO_CMAC { PROV_NAMES_CMAC, FIPS_DEFAULT_PROPERTIES, ossl_mac_legacy_cmac_signature_functions }, +#endif +#ifndef OPENSSL_NO_LMS + { PROV_NAMES_LMS, FIPS_DEFAULT_PROPERTIES, ossl_lms_signature_functions }, #endif { NULL, NULL, NULL } }; @@ -537,6 +540,10 @@ static const OSSL_ALGORITHM fips_keymgmt[] = { #ifndef OPENSSL_NO_CMAC { PROV_NAMES_CMAC, FIPS_DEFAULT_PROPERTIES, ossl_cmac_legacy_keymgmt_functions, PROV_DESCS_CMAC_SIGN }, +#endif +#ifndef OPENSSL_NO_LMS + { PROV_NAMES_LMS, FIPS_DEFAULT_PROPERTIES, ossl_lms_keymgmt_functions, + PROV_DESCS_LMS }, #endif { NULL, NULL, NULL } }; diff --git a/providers/implementations/keymgmt/build.info b/providers/implementations/keymgmt/build.info index a4e03b4f6a1..0650e9391b7 100644 --- a/providers/implementations/keymgmt/build.info +++ b/providers/implementations/keymgmt/build.info @@ -8,7 +8,7 @@ $ECX_GOAL=../../libdefault.a ../../libfips.a $KDF_GOAL=../../libdefault.a ../../libfips.a $MAC_GOAL=../../libdefault.a ../../libfips.a $RSA_GOAL=../../libdefault.a ../../libfips.a -$LMS_GOAL=../../libdefault.a +$LMS_GOAL=../../libdefault.a ../../libfips.a $TEMPLATE_GOAL=../../libtemplate.a IF[{- !$disabled{dh} -}] diff --git a/providers/implementations/keymgmt/lms_kmgmt.c b/providers/implementations/keymgmt/lms_kmgmt.c index 330528f91af..d8998d572cc 100644 --- a/providers/implementations/keymgmt/lms_kmgmt.c +++ b/providers/implementations/keymgmt/lms_kmgmt.c @@ -11,6 +11,7 @@ #include #include #include "crypto/lms.h" +#include "internal/param_build_set.h" #include "prov/implementations.h" #include "prov/providercommon.h" #include "prov/provider_ctx.h" @@ -21,7 +22,9 @@ static OSSL_FUNC_keymgmt_has_fn lms_has; static OSSL_FUNC_keymgmt_match_fn lms_match; static OSSL_FUNC_keymgmt_validate_fn lms_validate; static OSSL_FUNC_keymgmt_import_fn lms_import; +static OSSL_FUNC_keymgmt_export_fn lms_export; static OSSL_FUNC_keymgmt_import_types_fn lms_imexport_types; +static OSSL_FUNC_keymgmt_export_types_fn lms_imexport_types; static OSSL_FUNC_keymgmt_load_fn lms_load; #define LMS_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_PUBLIC_KEY) @@ -87,6 +90,41 @@ static const OSSL_PARAM *lms_imexport_types(int selection) return NULL; } +static int lms_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, + void *cbarg) +{ + LMS_KEY *lmskey = keydata; + OSSL_PARAM_BLD *tmpl; + OSSL_PARAM *params = NULL; + int ret = 0; + + if (!ossl_prov_is_running() || lmskey == NULL) + return 0; + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0) + return 0; + + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) + return 0; + + if (!ossl_param_build_set_octet_string(tmpl, params, + OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, + lmskey->pub.encoded, + lmskey->pub.encodedlen)) + goto err; + + params = OSSL_PARAM_BLD_to_param(tmpl); + if (params == NULL) + goto err; + + ret = param_cb(params, cbarg); + OSSL_PARAM_free(params); +err: + OSSL_PARAM_BLD_free(tmpl); + return ret; +} + static int lms_validate(const void *keydata, int selection, int checktype) { const LMS_KEY *lmskey = keydata; @@ -122,6 +160,8 @@ const OSSL_DISPATCH ossl_lms_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))lms_validate }, { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))lms_import }, { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))lms_imexport_types }, + { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))lms_export }, + { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))lms_imexport_types }, { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))lms_load }, OSSL_DISPATCH_END }; diff --git a/providers/implementations/signature/build.info b/providers/implementations/signature/build.info index 9903076f457..56a19412861 100644 --- a/providers/implementations/signature/build.info +++ b/providers/implementations/signature/build.info @@ -6,7 +6,7 @@ $EC_GOAL=../../libdefault.a ../../libfips.a $MAC_GOAL=../../libdefault.a ../../libfips.a $RSA_GOAL=../../libdefault.a ../../libfips.a $SM2_GOAL=../../libdefault.a -$LMS_GOAL=../../libdefault.a +$LMS_GOAL=../../libdefault.a ../../libfips.a IF[{- !$disabled{dsa} -}] SOURCE[$DSA_GOAL]=dsa_sig.c @@ -34,5 +34,5 @@ DEPEND[sm2_sig.o]=../../common/include/prov/der_sm2.h SOURCE[$MAC_GOAL]=mac_legacy_sig.c IF[{- !$disabled{lms} -}] - SOURCE[$LMS_GOAL]=lms_sig.c + SOURCE[$LMS_GOAL]=lms_signature.c ENDIF diff --git a/providers/implementations/signature/lms_sig.c b/providers/implementations/signature/lms_signature.c similarity index 100% rename from providers/implementations/signature/lms_sig.c rename to providers/implementations/signature/lms_signature.c diff --git a/test/lms_test.c b/test/lms_test.c index 346b1b9fb0f..4150aeae33a 100644 --- a/test/lms_test.c +++ b/test/lms_test.c @@ -15,7 +15,17 @@ #include "testutil.h" #include "lms.inc" +typedef enum OPTION_choice { + OPT_ERR = -1, + OPT_EOF = 0, + OPT_CONFIG_FILE, + OPT_TEST_ENUM +} OPTION_CHOICE; + static OSSL_LIB_CTX *libctx = NULL; +static char *propq = NULL; +static OSSL_PROVIDER *nullprov = NULL; +static OSSL_PROVIDER *libprov = NULL; static EVP_PKEY *lms_pubkey_from_data(const unsigned char *data, size_t datalen) { @@ -27,7 +37,7 @@ static EVP_PKEY *lms_pubkey_from_data(const unsigned char *data, size_t datalen) params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, (unsigned char *)data, datalen); params[1] = OSSL_PARAM_construct_end(); - ret = TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "LMS", NULL)) + ret = TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "LMS", propq)) && TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1) && (EVP_PKEY_fromdata(ctx, &key, EVP_PKEY_PUBLIC_KEY, params) == 1); if (ret == 0) { @@ -187,13 +197,17 @@ err: static int lms_key_eq_test(void) { int ret = 0; - EVP_PKEY *key[4] = { NULL, NULL, NULL }; + EVP_PKEY *key[4]; LMS_ACVP_TEST_DATA *td1 = &lms_testdata[0]; LMS_ACVP_TEST_DATA *td2 = &lms_testdata[1]; + size_t i; #ifndef OPENSSL_NO_EC EVP_PKEY *eckey = NULL; #endif + for (i = 0; i < OSSL_NELEM(key); i++) + key[i] = NULL; + if (!TEST_ptr(key[0] = lms_pubkey_from_data(td1->pub, td1->publen)) || !TEST_ptr(key[1] = lms_pubkey_from_data(td1->pub, td1->publen)) || !TEST_ptr(key[2] = lms_pubkey_from_data(td2->pub, td2->publen)) @@ -465,8 +479,41 @@ end: return ret == 1; } +const OPTIONS *test_get_options(void) +{ + static const OPTIONS options[] = { + OPT_TEST_OPTIONS_DEFAULT_USAGE, + { "config", OPT_CONFIG_FILE, '<', + "The configuration file to use for the libctx" }, + { NULL } + }; + return options; +} + int setup_tests(void) { + OPTION_CHOICE o; + char *config_file = NULL; + + /* Swap the libctx to test non-default context only */ + propq = "provider=default"; + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_CONFIG_FILE: + config_file = opt_arg(); + propq = ""; + break; + case OPT_TEST_CASES: + break; + default: + case OPT_ERR: + return 0; + } + } + if (!test_get_libctx(&libctx, &nullprov, config_file, &libprov, NULL)) + return 0; + ADD_TEST(lms_bad_pub_len_test); ADD_TEST(lms_key_validate_test); ADD_TEST(lms_key_eq_test); @@ -482,3 +529,10 @@ int setup_tests(void) return 1; } + +void cleanup_tests(void) +{ + OSSL_PROVIDER_unload(nullprov); + OSSL_PROVIDER_unload(libprov); + OSSL_LIB_CTX_free(libctx); +} diff --git a/test/recipes/30-test_lms.t b/test/recipes/30-test_lms.t index ada1ab01661..1f7b6803331 100644 --- a/test/recipes/30-test_lms.t +++ b/test/recipes/30-test_lms.t @@ -9,18 +9,25 @@ use strict; use warnings; -use OpenSSL::Test qw(:DEFAULT srctop_dir bldtop_dir); +use OpenSSL::Test qw(:DEFAULT srctop_file srctop_dir bldtop_dir); use OpenSSL::Test::Utils; BEGIN { setup("test_lms"); } +my $provconf = srctop_file("test", "fips-and-base.cnf"); +my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0); + use lib srctop_dir('Configurations'); use lib bldtop_dir('.'); plan skip_all => 'LMS is not supported in this build' if disabled('lms'); -plan tests => 1; +plan tests => 1 + + ($no_fips ? 0 : 1); ok(run(test(["lms_test"])), "running lms_test"); +unless ($no_fips) { + ok(run(test(["lms_test", "-config", $provconf])), + "running lms_test with fips"); +} -- 2.47.2