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: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/27885)
IF[{- !$disabled{'lms'} -}]
SOURCE[../../libcrypto]=$COMMON
+SOURCE[../../providers/libfips.a]=$COMMON
ENDIF
*/
#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(),
{ 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
#ifndef OPENSSL_NO_SLH_DSA
{ PROV_NAMES_SLH_DSA_SHA2_128S, FIPS_DEFAULT_PROPERTIES,
ossl_slh_dsa_sha2_128s_signature_functions, PROV_DESCS_SLH_DSA_SHA2_128S },
{ 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
#ifndef OPENSSL_NO_ML_KEM
{ PROV_NAMES_ML_KEM_512, FIPS_DEFAULT_PROPERTIES, ossl_ml_kem_512_keymgmt_functions,
PROV_DESCS_ML_KEM_512 },
$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
$ML_DSA_GOAL=../../libdefault.a ../../libfips.a
$ML_KEM_GOAL=../../libdefault.a ../../libfips.a
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#include "crypto/lms.h"
+#include "internal/param_build_set.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#include "prov/provider_ctx.h"
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)
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;
{ 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
};
$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
$ML_DSA_GOAL=../../libdefault.a ../../libfips.a
$SLH_DSA_GOAL=../../libdefault.a ../../libfips.a
SOURCE[$MAC_GOAL]=mac_legacy_sig.c
IF[{- !$disabled{lms} -}]
- SOURCE[$LMS_GOAL]=lms_sig.c
+ SOURCE[$LMS_GOAL]=lms_signature.c
ENDIF
IF[{- !$disabled{'ml-dsa'} -}]
/*
- * Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2025 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
#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)
{
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) {
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))
return ret;
}
+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);
return 1;
}
+
+void cleanup_tests(void)
+{
+ OSSL_PROVIDER_unload(nullprov);
+ OSSL_PROVIDER_unload(libprov);
+ OSSL_LIB_CTX_free(libctx);
+}
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");
+}