From: slontis Date: Thu, 3 Oct 2024 01:16:15 +0000 (+1000) Subject: Add base code to load a LMS public key. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=11551fb38c55c156f2fb07a7898129042fa4730e;p=thirdparty%2Fopenssl.git Add base code to load a LMS public key. This loads a XDR encoded LMS public key. It adds a simple LMS keymanager to import this key. Reviewed-by: Hugo Landau Reviewed-by: Dmitry Belyavskiy Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/25598) --- diff --git a/crypto/build.info b/crypto/build.info index 2642d30754b..cb43cbfe345 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -6,7 +6,7 @@ SUBDIRS=objects buffer bio stack lhash hashtable rand evp asn1 pem x509 conf \ siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \ seed sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \ err comp http ocsp cms ts srp cmac ct async ess crmf cmp encode_decode \ - ffc hpke thread + ffc hpke thread lms LIBS=../libcrypto diff --git a/crypto/lms/build.info b/crypto/lms/build.info new file mode 100644 index 00000000000..e6bf504e19c --- /dev/null +++ b/crypto/lms/build.info @@ -0,0 +1,7 @@ +LIBS=../../libcrypto + +$COMMON=lms_params.c lms_pubkey_decode.c lms_key.c lm_ots_params.c + +IF[{- !$disabled{'lms'} -}] +SOURCE[../../libcrypto]=$COMMON +ENDIF diff --git a/crypto/lms/lm_ots_params.c b/crypto/lms/lm_ots_params.c new file mode 100644 index 00000000000..9777d0e65bf --- /dev/null +++ b/crypto/lms/lm_ots_params.c @@ -0,0 +1,49 @@ +/* + * Copyright 2024 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 "crypto/lms.h" + +/* Refer to SP800-208 Section 4 LM-OTS parameter sets */ +static const LM_OTS_PARAMS lm_ots_params[] = { + { OSSL_LM_OTS_TYPE_SHA256_N32_W1, 32, 1, 265, "SHA256"}, + { OSSL_LM_OTS_TYPE_SHA256_N32_W2, 32, 2, 133, "SHA256"}, + { OSSL_LM_OTS_TYPE_SHA256_N32_W4, 32, 4, 67, "SHA256"}, + { OSSL_LM_OTS_TYPE_SHA256_N32_W8, 32, 8, 34, "SHA256"}, + { OSSL_LM_OTS_TYPE_SHA256_N24_W1, 24, 1, 200, "SHA256-192"}, + { OSSL_LM_OTS_TYPE_SHA256_N24_W2, 24, 2, 101, "SHA256-192"}, + { OSSL_LM_OTS_TYPE_SHA256_N24_W4, 24, 4, 51, "SHA256-192"}, + { OSSL_LM_OTS_TYPE_SHA256_N24_W8, 24, 8, 26, "SHA256-192"}, + { OSSL_LM_OTS_TYPE_SHAKE_N32_W1, 32, 1, 265, "SHAKE-256"}, + { OSSL_LM_OTS_TYPE_SHAKE_N32_W2, 32, 2, 133, "SHAKE-256"}, + { OSSL_LM_OTS_TYPE_SHAKE_N32_W4, 32, 4, 67, "SHAKE-256"}, + { OSSL_LM_OTS_TYPE_SHAKE_N32_W8, 32, 8, 34, "SHAKE-256"}, + /* SHAKE-256/192 - OpenSSL does not support this as a name */ + { OSSL_LM_OTS_TYPE_SHAKE_N24_W1, 24, 1, 200, "SHAKE-256"}, + { OSSL_LM_OTS_TYPE_SHAKE_N24_W2, 24, 2, 101, "SHAKE-256"}, + { OSSL_LM_OTS_TYPE_SHAKE_N24_W4, 24, 4, 51, "SHAKE-256"}, + { OSSL_LM_OTS_TYPE_SHAKE_N24_W8, 24, 8, 26, "SHAKE-256"}, + { 0, 0, 0, 0, NULL }, +}; + +/** + * @brief A getter to convert an |ots_type| into a LM_OTS_PARAMS object. + * + * @param ots_type The type such as OSSL_LM_OTS_TYPE_SHA256_N32_W1 + * @returns The LM_OTS_PARAMS object associated with the |ots_type|, or + * NULL if |ots_type| is undefined. + */ +const LM_OTS_PARAMS *ossl_lm_ots_params_get(uint32_t ots_type) +{ + const LM_OTS_PARAMS *p; + + for (p = lm_ots_params; p->lm_ots_type != 0; ++p) + if (p->lm_ots_type == ots_type) + return p; + return NULL; +} diff --git a/crypto/lms/lms_key.c b/crypto/lms/lms_key.c new file mode 100644 index 00000000000..6f35a5ad39c --- /dev/null +++ b/crypto/lms/lms_key.c @@ -0,0 +1,108 @@ +/* + * Copyright 2024 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 +#include "crypto/lms.h" +#include + +/** + * @brief Create a new LMS_KEY object + * + * @param libctx A OSSL_LIB_CTX object used for fetching algorithms. + * @returns The new LMS_KEY object on success, or NULL on malloc failure + */ +LMS_KEY *ossl_lms_key_new(OSSL_LIB_CTX *libctx) +{ + LMS_KEY *ret = OPENSSL_zalloc(sizeof(LMS_KEY)); + + if (ret != NULL) + ret->libctx = libctx; + return ret; +} + +/** + * @brief Destroy a LMS_KEY object + */ +void ossl_lms_key_free(LMS_KEY *lmskey) +{ + LMS_PUB_KEY *pub; + + if (lmskey == NULL) + return; + + pub = &lmskey->pub; + if (pub->allocated) + OPENSSL_free(pub->encoded); + OPENSSL_free(lmskey); +} + +/** + * @brief Are 2 LMS public keys equal? + * + * To be equal the keys must have the same LMS_PARAMS, LM_OTS_PARAMS and + * encoded public keys. + * + * @param key1 A LMS_KEY object + * @param key2 A LMS_KEY object + * @param selection Only OSSL_KEYMGMT_SELECT_PUBLIC_KEY is supported + * @returns 1 if the keys are equal otherwise it returns 0. + */ +int ossl_lms_key_equal(const LMS_KEY *key1, const LMS_KEY *key2, int selection) +{ + int ok = 1; + + if (key1->lms_params != key2->lms_params + || key1->ots_params != key2->ots_params) + return 0; + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { + if (key1->pub.encodedlen != key2->pub.encodedlen) + return 0; + ok = (key1->pub.encodedlen == 0) + || (memcmp(key1->pub.encoded, key2->pub.encoded, + key1->pub.encodedlen) == 0); + } + return ok; +} + +/** + * @brief Is a LMS_KEY valid. + * + * @param key A LMS_KEY object + * @param selection Currently only supports |OSSL_KEYMGMT_SELECT_PUBLIC_KEY| + * @returns 1 if a LMS_KEY contains valid key data. + */ +int ossl_lms_key_valid(const LMS_KEY *key, int selection) +{ + if (key == NULL) + return 0; + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + if (key->pub.encoded == NULL || key->pub.encodedlen == 0) + return 0; + /* There is no private key currently */ + return 1; +} + +/** + * @brief Does a LMS_KEY object contain a public key. + * + * @param key A LMS_KEY object + * @param selection Currently only supports |OSSL_KEYMGMT_SELECT_PUBLIC_KEY| + * @returns 1 if a LMS_KEY contains public key data, or 0 otherwise. + */ +int ossl_lms_key_has(const LMS_KEY *key, int selection) +{ + int ok = 1; + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + ok = (key != NULL && key->pub.K != NULL); + /* There is no private key currently */ + return ok; +} diff --git a/crypto/lms/lms_params.c b/crypto/lms/lms_params.c new file mode 100644 index 00000000000..b8c34701807 --- /dev/null +++ b/crypto/lms/lms_params.c @@ -0,0 +1,54 @@ +/* + * Copyright 2024 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 "crypto/lms.h" + +/* Refer to SP800-208 Section 4 LMS Parameter Sets */ +static const LMS_PARAMS lms_params[] = { + {OSSL_LMS_TYPE_SHA256_N32_H5, "SHA256", 32, 5}, + {OSSL_LMS_TYPE_SHA256_N32_H10, "SHA256", 32, 10}, + {OSSL_LMS_TYPE_SHA256_N32_H15, "SHA256", 32, 15}, + {OSSL_LMS_TYPE_SHA256_N32_H20, "SHA256", 32, 20}, + {OSSL_LMS_TYPE_SHA256_N32_H25, "SHA256", 32, 25}, + {OSSL_LMS_TYPE_SHA256_N24_H5, "SHA256-192", 24, 5}, + {OSSL_LMS_TYPE_SHA256_N24_H10, "SHA256-192", 24, 10}, + {OSSL_LMS_TYPE_SHA256_N24_H15, "SHA256-192", 24, 15}, + {OSSL_LMS_TYPE_SHA256_N24_H20, "SHA256-192", 24, 20}, + {OSSL_LMS_TYPE_SHA256_N24_H25, "SHA256-192", 24, 25}, + {OSSL_LMS_TYPE_SHAKE_N32_H5, "SHAKE-256", 32, 5}, + {OSSL_LMS_TYPE_SHAKE_N32_H10, "SHAKE-256", 32, 10}, + {OSSL_LMS_TYPE_SHAKE_N32_H15, "SHAKE-256", 32, 15}, + {OSSL_LMS_TYPE_SHAKE_N32_H20, "SHAKE-256", 32, 20}, + {OSSL_LMS_TYPE_SHAKE_N32_H25, "SHAKE-256", 32, 25}, + /* SHAKE-256/192 */ + {OSSL_LMS_TYPE_SHAKE_N24_H5, "SHAKE-256", 24, 5}, + {OSSL_LMS_TYPE_SHAKE_N24_H10, "SHAKE-256", 24, 10}, + {OSSL_LMS_TYPE_SHAKE_N24_H15, "SHAKE-256", 24, 15}, + {OSSL_LMS_TYPE_SHAKE_N24_H20, "SHAKE-256", 24, 20}, + {OSSL_LMS_TYPE_SHAKE_N24_H25, "SHAKE-256", 24, 25}, + + {0, NULL, 0, 0} +}; + +/** + * @brief A getter to convert a |lms_type| into a LMS_PARAMS object. + * + * @param lms_type The type such as OSSL_LMS_TYPE_SHA256_N32_H5. + * @returns The LMS_PARAMS object associated with the |lms_type|, or + * NULL if |lms_type| is undefined. + */ +const LMS_PARAMS *ossl_lms_params_get(uint32_t lms_type) +{ + const LMS_PARAMS *p; + + for (p = lms_params; p->lms_type != 0; ++p) + if (p->lms_type == lms_type) + return p; + return NULL; +} diff --git a/crypto/lms/lms_pubkey_decode.c b/crypto/lms/lms_pubkey_decode.c new file mode 100644 index 00000000000..59e4e929967 --- /dev/null +++ b/crypto/lms/lms_pubkey_decode.c @@ -0,0 +1,116 @@ +/* + * Copyright 2024 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 +#include "crypto/lms.h" +#include "crypto/lms_util.h" + +/* + * @brief Decode LMS public key data in XDR format into a LMS_KEY object. + * + * See RFC 8554 Algorithm 6: Steps 1 & 2. + * The XDR format is lms_type[4] || ots_type[4] || I[16] || K[n] + * Steps that involve checking the size of the public key data are + * done indirectly by checking the return result of PACKET_get API's. + * This function may be called multiple times. + * + * @param pkt The packet to read public key data in XDR format from. + * @param lmskey The object to store the public key into + * @return 1 on success or 0 otherwise. + */ +static +int lms_pubkey_from_pkt(PACKET *pkt, LMS_KEY *lmskey) +{ + uint32_t lms_type; + uint32_t ots_type; + LMS_PUB_KEY *key = &lmskey->pub; + + key->encoded = (unsigned char *)pkt->curr; + if (!PACKET_get_4_len(pkt, &lms_type)) + goto err; + lmskey->lms_params = ossl_lms_params_get(lms_type); + if (lmskey->lms_params == NULL + || !PACKET_get_4_len(pkt, &ots_type)) + goto err; + lmskey->ots_params = ossl_lm_ots_params_get(ots_type); + if (lmskey->ots_params == NULL) + goto err; + + /* The digest used must be the same */ + if (HASH_NOT_MATCHED(lmskey->ots_params, lmskey->lms_params) + || !PACKET_get_bytes_shallow(pkt, &lmskey->Id, LMS_SIZE_I) + || !PACKET_get_bytes_shallow(pkt, &key->K, lmskey->lms_params->n)) + goto err; + key->encodedlen = pkt->curr - key->encoded; + return 1; +err: + return 0; +} + +/* + * @brief Decode LMS public key data in XDR format into a LMS_KEY object. + * Used by the LMS public key decoder. + * The XDR format is lms_type[4] || ots_type[4] || I[16] || K[n] + * + * @param pub byte array of public key data in XDR format. + * @param publen is the size of |pub|. + * @param lmskey The LMS_KEY object to store the public key into. + * @returns 1 on success, or 0 otherwise. 0 is returned if either |pub| is + * invalid or |publen| is not the correct size (i.e. trailing data is not allowed) + */ +static +int lms_pubkey_decode(const unsigned char *pub, size_t publen, LMS_KEY *lmskey) +{ + PACKET pkt; + LMS_PUB_KEY *pkey = &lmskey->pub; + + if (pkey->encoded != NULL && pkey->encodedlen != publen) { + if (pkey->allocated) { + OPENSSL_free(pkey->encoded); + pkey->allocated = 0; + } + pkey->encodedlen = 0; + } + pkey->encoded = OPENSSL_memdup(pub, publen); + if (pkey->encoded == NULL) + return 0; + + if (!PACKET_buf_init(&pkt, pkey->encoded, publen) + || !lms_pubkey_from_pkt(&pkt, lmskey) + || (PACKET_remaining(&pkt) > 0)) + goto err; + pkey->encodedlen = publen; + pkey->allocated = 1; + return 1; +err: + OPENSSL_free(pkey->encoded); + pkey->encoded = NULL; + return 0; +} + +/** + * @brief Load a LMS public key from OSSL_PARAM data. + * + * @param params An array of OSSL_PARAM + * @param lmskey The LMS_KEY to load the public key data into. + * @returns 1 on success, or 0 otherwise. + */ +int ossl_lms_pubkey_from_params(const OSSL_PARAM params[], LMS_KEY *lmskey) +{ + const OSSL_PARAM *p = NULL; + + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); + if (p != NULL) { + if (p->data == NULL || p->data_type != OSSL_PARAM_OCTET_STRING) + return 0; + if (!lms_pubkey_decode(p->data, p->data_size, lmskey)) + return 0; + } + return 1; +} diff --git a/doc/build.info b/doc/build.info index 9003540be42..44e6ca27c07 100644 --- a/doc/build.info +++ b/doc/build.info @@ -4745,6 +4745,10 @@ DEPEND[html/man7/EVP_PKEY-HMAC.html]=man7/EVP_PKEY-HMAC.pod GENERATE[html/man7/EVP_PKEY-HMAC.html]=man7/EVP_PKEY-HMAC.pod DEPEND[man/man7/EVP_PKEY-HMAC.7]=man7/EVP_PKEY-HMAC.pod GENERATE[man/man7/EVP_PKEY-HMAC.7]=man7/EVP_PKEY-HMAC.pod +DEPEND[html/man7/EVP_PKEY-LMS.html]=man7/EVP_PKEY-LMS.pod +GENERATE[html/man7/EVP_PKEY-LMS.html]=man7/EVP_PKEY-LMS.pod +DEPEND[man/man7/EVP_PKEY-LMS.7]=man7/EVP_PKEY-LMS.pod +GENERATE[man/man7/EVP_PKEY-LMS.7]=man7/EVP_PKEY-LMS.pod DEPEND[html/man7/EVP_PKEY-RSA.html]=man7/EVP_PKEY-RSA.pod GENERATE[html/man7/EVP_PKEY-RSA.html]=man7/EVP_PKEY-RSA.pod DEPEND[man/man7/EVP_PKEY-RSA.7]=man7/EVP_PKEY-RSA.pod @@ -5140,6 +5144,7 @@ html/man7/EVP_PKEY-DSA.html \ html/man7/EVP_PKEY-EC.html \ html/man7/EVP_PKEY-FFC.html \ html/man7/EVP_PKEY-HMAC.html \ +html/man7/EVP_PKEY-LMS.html \ html/man7/EVP_PKEY-RSA.html \ html/man7/EVP_PKEY-SM2.html \ html/man7/EVP_PKEY-X25519.html \ @@ -5287,6 +5292,7 @@ man/man7/EVP_PKEY-DSA.7 \ man/man7/EVP_PKEY-EC.7 \ man/man7/EVP_PKEY-FFC.7 \ man/man7/EVP_PKEY-HMAC.7 \ +man/man7/EVP_PKEY-LMS.7 \ man/man7/EVP_PKEY-RSA.7 \ man/man7/EVP_PKEY-SM2.7 \ man/man7/EVP_PKEY-X25519.7 \ diff --git a/doc/man7/EVP_PKEY-LMS.pod b/doc/man7/EVP_PKEY-LMS.pod new file mode 100644 index 00000000000..9f16d15289d --- /dev/null +++ b/doc/man7/EVP_PKEY-LMS.pod @@ -0,0 +1,83 @@ +=pod + +=head1 NAME + +EVP_PKEY-LMS, EVP_KEYMGMT-LMS, LMS +- EVP_PKEY Leighton-Micali Signature (LMS) keytype and algorithm support + +=head1 DESCRIPTION + +The B keytype is implemented in OpenSSL's default provider. + +=head2 Common LMS parameters + +LMS public keys are encoded in XDR format (i.e. not ANS1 format), +The following parameters are used by EVP_PKEY_fromdata() and by the +LMS keymanager for import and export. + +=over 4 + +=item "encoded-pub-key" (B) + +Used for getting and setting the encoding of an LMS public key. The public key +is expected to be in XDR format. + +=back + +=head1 CONFORMING TO + +=over 4 + +=item RFC 8554 + +Leighton-Micali Hash-Based Signatures + +=item NIST SP 800-208 + +Recommendation for Stateful Hash-Based Signature Schemes + +=item CSNA 2.0 + +Commercial National Security Algorithm Suite + +=back + +=head1 EXAMPLES + +NOTE error checking has been omitted in these examples + +An B context can be obtained by calling: + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "LMS", NULL); + +To load a LMS key from XDR encoded "data" of size "datalen": + + EVP_PKEY *key = NULL; + OSSL_PARAM params[2]; + + params[0] = + OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, + (unsigned char *)data, datalen); + params[1] = OSSL_PARAM_construct_end(); + ret = EVP_PKEY_fromdata_init(ctx) + ret = EVP_PKEY_fromdata(ctx, &key, EVP_PKEY_PUBLIC_KEY, params); + +=head1 SEE ALSO + +L, +L, +L + +=head1 HISTORY + +This functionality was added in OpenSSL 3.5.0 + +=head1 COPYRIGHT + +Copyright 2024 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 +L. + +=cut diff --git a/include/crypto/lms.h b/include/crypto/lms.h new file mode 100644 index 00000000000..bea0909f36f --- /dev/null +++ b/include/crypto/lms.h @@ -0,0 +1,146 @@ +/* + * Copyright 2024 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 + */ + +/* + * Internal LMS/LM_OTS functions for other submodules, + * not for application use + */ + +#ifndef OSSL_CRYPTO_LMS_H +# define OSSL_CRYPTO_LMS_H +# pragma once +# ifndef OPENSSL_NO_LMS +# include "types.h" +# include + +/* + * Numeric identifiers associated with Leighton-Micali Signatures (LMS) + * parameter sets are defined in + * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml + * which is referenced from SP800-208. + */ +# define OSSL_LMS_TYPE_SHA256_N32_H5 0x00000005 +# define OSSL_LMS_TYPE_SHA256_N32_H10 0x00000006 +# define OSSL_LMS_TYPE_SHA256_N32_H15 0x00000007 +# define OSSL_LMS_TYPE_SHA256_N32_H20 0x00000008 +# define OSSL_LMS_TYPE_SHA256_N32_H25 0x00000009 +# define OSSL_LMS_TYPE_SHA256_N24_H5 0x0000000A +# define OSSL_LMS_TYPE_SHA256_N24_H10 0x0000000B +# define OSSL_LMS_TYPE_SHA256_N24_H15 0x0000000C +# define OSSL_LMS_TYPE_SHA256_N24_H20 0x0000000D +# define OSSL_LMS_TYPE_SHA256_N24_H25 0x0000000E +# define OSSL_LMS_TYPE_SHAKE_N32_H5 0x0000000F +# define OSSL_LMS_TYPE_SHAKE_N32_H10 0x00000010 +# define OSSL_LMS_TYPE_SHAKE_N32_H15 0x00000011 +# define OSSL_LMS_TYPE_SHAKE_N32_H20 0x00000012 +# define OSSL_LMS_TYPE_SHAKE_N32_H25 0x00000013 +# define OSSL_LMS_TYPE_SHAKE_N24_H5 0x00000014 +# define OSSL_LMS_TYPE_SHAKE_N24_H10 0x00000015 +# define OSSL_LMS_TYPE_SHAKE_N24_H15 0x00000016 +# define OSSL_LMS_TYPE_SHAKE_N24_H20 0x00000017 +# define OSSL_LMS_TYPE_SHAKE_N24_H25 0x00000018 + +# define OSSL_LM_OTS_TYPE_SHA256_N32_W1 0x00000001 +# define OSSL_LM_OTS_TYPE_SHA256_N32_W2 0x00000002 +# define OSSL_LM_OTS_TYPE_SHA256_N32_W4 0x00000003 +# define OSSL_LM_OTS_TYPE_SHA256_N32_W8 0x00000004 +# define OSSL_LM_OTS_TYPE_SHA256_N24_W1 0x00000005 +# define OSSL_LM_OTS_TYPE_SHA256_N24_W2 0x00000006 +# define OSSL_LM_OTS_TYPE_SHA256_N24_W4 0x00000007 +# define OSSL_LM_OTS_TYPE_SHA256_N24_W8 0x00000008 +# define OSSL_LM_OTS_TYPE_SHAKE_N32_W1 0x00000009 +# define OSSL_LM_OTS_TYPE_SHAKE_N32_W2 0x0000000A +# define OSSL_LM_OTS_TYPE_SHAKE_N32_W4 0x0000000B +# define OSSL_LM_OTS_TYPE_SHAKE_N32_W8 0x0000000C +# define OSSL_LM_OTS_TYPE_SHAKE_N24_W1 0x0000000D +# define OSSL_LM_OTS_TYPE_SHAKE_N24_W2 0x0000000E +# define OSSL_LM_OTS_TYPE_SHAKE_N24_W4 0x0000000F +# define OSSL_LM_OTS_TYPE_SHAKE_N24_W8 0x00000010 + +/* XDR sizes when encoding and decoding */ +# define LMS_SIZE_I 16 +# define LMS_SIZE_LMS_TYPE 4 +# define LMS_SIZE_OTS_TYPE 4 + +/* + * Refer to RFC 8554 Section 4.1. + * See also lm_ots_params[] + */ +typedef struct lm_ots_params_st { + /* + * The OTS type associates an id with a set of OTS parameters + * e.g. OSSL_LM_OTS_TYPE_SHAKE_N32_W1 + */ + uint32_t lm_ots_type; + uint32_t n; /* Hash output size in bytes (32 or 24) */ + /* + * The width of the Winternitz coefficients in bits. One of (1, 2, 4, 8) + * Higher values of w are slower (~2^w computations) but have smaller + * signatures. + */ + uint32_t w; + /* + * The number of n-byte elements used for an LMOTS signature. + * One of (265, 133, 67, 34) for n = 32, for w=1,2,4,8 + * One of (200, 101, 51, 26) for n = 24, for w=1,2,4,8 + */ + uint32_t p; + const char *digestname; /* Hash Name */ +} LM_OTS_PARAMS; + +/* See lms_params[] */ +typedef struct lms_params_st { + /* + * The lms type associates an id with a set of parameters to define the + * Digest and Height of a LMS tree. + * e.g, OSSL_LMS_TYPE_SHA256_N24_H25 + */ + uint32_t lms_type; + const char *digestname; /* One of SHA256, SHA256-192, or SHAKE256 */ + uint32_t n; /* The Digest size (either 24 or 32), Useful for setting up SHAKE */ + uint32_t h; /* The height of a LMS tree which is one of 5, 10, 15, 20, 25) */ +} LMS_PARAMS; + +typedef struct lms_pub_key_st { + /* + * A buffer containing an encoded public key of the form + * u32str(lmstype) || u32str(otstype) || I[16] || K[n] + */ + unsigned char *encoded; /* encoded public key data */ + size_t encodedlen; + /* + * K is the LMS tree's root public key (Called T(1)) + * It is n bytes long (the hash size). + * It is a pointer into the encoded buffer + */ + unsigned char *K; + uint32_t allocated; /* If 1 then encoded needs to be freed */ +} LMS_PUB_KEY; + +struct lms_key_st { + const LMS_PARAMS *lms_params; + const LM_OTS_PARAMS *ots_params; + OSSL_LIB_CTX *libctx; + unsigned char *Id; /* A pointer to 16 bytes (I[16]) */ + LMS_PUB_KEY pub; +}; + +const LMS_PARAMS *ossl_lms_params_get(uint32_t lms_type); +const LM_OTS_PARAMS *ossl_lm_ots_params_get(uint32_t ots_type); + +LMS_KEY *ossl_lms_key_new(OSSL_LIB_CTX *libctx); +void ossl_lms_key_free(LMS_KEY *lmskey); +int ossl_lms_key_equal(const LMS_KEY *key1, const LMS_KEY *key2, int selection); +int ossl_lms_key_valid(const LMS_KEY *key, int selection); +int ossl_lms_key_has(const LMS_KEY *key, int selection); + +int ossl_lms_pubkey_from_params(const OSSL_PARAM params[], LMS_KEY *lmskey); + +# endif /* OPENSSL_NO_LMS */ +#endif /* OSSL_CRYPTO_LMS_H */ diff --git a/include/crypto/lms_util.h b/include/crypto/lms_util.h new file mode 100644 index 00000000000..690a0ebfae4 --- /dev/null +++ b/include/crypto/lms_util.h @@ -0,0 +1,63 @@ +/* + * Copyright 2024 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 + */ + +/* @brief Internal LMS internal helper functions */ + +#include "internal/packet.h" + +/* + * This LMS implementation assumes that the hash algorithm must be the same for + * LMS params and OTS params. Since OpenSSL does not have a "SHAKE256-192" + * algorithm, we have to check the digest size as well as the name. + * This macro can be used to compare 2 LMS_PARAMS, LMS_PARAMS and LM_OTS_PARAMS. + */ +#define HASH_NOT_MATCHED(a, b) \ + (a)->n != (b)->n || (strcmp((a)->digestname, (b)->digestname) != 0) + +/** + * @brief Helper function to return a ptr to a pkt buffer and move forward. + * Used when decoding byte array XDR data. + * + * @param pkt A PACKET object that needs to have at least len bytes remaining. + * @param out The returned ptr to the current position in the pkt buffer. + * @param len The amount that we will move forward in the pkt buffer. + * @returns 1 if there is enough bytes remaining to be able to skip forward, + * or 0 otherwise. + */ +static ossl_unused ossl_inline +int PACKET_get_bytes_shallow(PACKET *pkt, unsigned char **out, size_t len) +{ + const unsigned char **data = (const unsigned char **)out; + + if (!PACKET_peek_bytes(pkt, data, len)) + return 0; + + packet_forward(pkt, len); + + return 1; +} + +/** + * @brief Get 4 bytes in network order from |pkt| and store the value in |*data| + * Similar to PACKET_get_net_4() except the data is uint32_t + * + * @param pkt Contains a buffer to read from + * @param data The object to write the data to. + * @returns 1 on success, or 0 otherwise. + */ +static ossl_unused ossl_inline +int PACKET_get_4_len(PACKET *pkt, uint32_t *data) +{ + size_t i = 0; + int ret = PACKET_get_net_4_len(pkt, &i); + + if (ret) + *data = (uint32_t)i; + return ret; +} diff --git a/include/crypto/types.h b/include/crypto/types.h index ad17f052e45..b79d9b7e4a1 100644 --- a/include/crypto/types.h +++ b/include/crypto/types.h @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2024 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 @@ -29,4 +29,8 @@ typedef struct dsa_st DSA; typedef struct ecx_key_st ECX_KEY; # endif +# ifndef OPENSSL_NO_LMS +typedef struct lms_key_st LMS_KEY; +# endif + #endif diff --git a/providers/defltprov.c b/providers/defltprov.c index e30256cbaa4..e869110b351 100644 --- a/providers/defltprov.c +++ b/providers/defltprov.c @@ -530,6 +530,10 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = { #ifndef OPENSSL_NO_SM2 { PROV_NAMES_SM2, "provider=default", ossl_sm2_keymgmt_functions, PROV_DESCS_SM2 }, +#endif +#ifndef OPENSSL_NO_LMS + { PROV_NAMES_LMS, "provider=default", ossl_lms_keymgmt_functions, + PROV_DESCS_LMS }, #endif { NULL, NULL, NULL } }; diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index 5b919056577..0555ddee8c3 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -321,6 +321,9 @@ extern const OSSL_DISPATCH ossl_cmac_legacy_keymgmt_functions[]; #ifndef OPENSSL_NO_SM2 extern const OSSL_DISPATCH ossl_sm2_keymgmt_functions[]; #endif +#ifndef OPENSSL_NO_LMS +extern const OSSL_DISPATCH ossl_lms_keymgmt_functions[]; +#endif /* Key Exchange */ extern const OSSL_DISPATCH ossl_dh_keyexch_functions[]; diff --git a/providers/implementations/include/prov/names.h b/providers/implementations/include/prov/names.h index d422dbac296..3010b04bdfd 100644 --- a/providers/implementations/include/prov/names.h +++ b/providers/implementations/include/prov/names.h @@ -384,3 +384,5 @@ #define PROV_DESCS_RSA_PSS "OpenSSL RSA-PSS implementation" #define PROV_NAMES_SM2 "SM2:1.2.156.10197.1.301" #define PROV_DESCS_SM2 "OpenSSL SM2 implementation" +#define PROV_NAMES_LMS "LMS" +#define PROV_DESCS_LMS "OpenSSL LMS implementation" diff --git a/providers/implementations/keymgmt/build.info b/providers/implementations/keymgmt/build.info index f2cbb3dfe8d..a4e03b4f6a1 100644 --- a/providers/implementations/keymgmt/build.info +++ b/providers/implementations/keymgmt/build.info @@ -8,6 +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 $TEMPLATE_GOAL=../../libtemplate.a IF[{- !$disabled{dh} -}] @@ -43,4 +44,8 @@ SOURCE[$KDF_GOAL]=kdf_legacy_kmgmt.c SOURCE[$MAC_GOAL]=mac_legacy_kmgmt.c +IF[{- !$disabled{lms} -}] + SOURCE[$LMS_GOAL]=lms_kmgmt.c +ENDIF + SOURCE[$TEMPLATE_GOAL]=template_kmgmt.c diff --git a/providers/implementations/keymgmt/lms_kmgmt.c b/providers/implementations/keymgmt/lms_kmgmt.c new file mode 100644 index 00000000000..ac9764672e9 --- /dev/null +++ b/providers/implementations/keymgmt/lms_kmgmt.c @@ -0,0 +1,111 @@ +/* + * Copyright 2024 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 +#include +#include +#include "crypto/lms.h" +#include "prov/implementations.h" +#include "prov/providercommon.h" +#include "prov/provider_ctx.h" + +static OSSL_FUNC_keymgmt_new_fn lms_new_key; +static OSSL_FUNC_keymgmt_free_fn lms_free_key; +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_import_types_fn lms_imexport_types; + +#define LMS_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_PUBLIC_KEY) + +static void *lms_new_key(void *provctx) +{ + if (!ossl_prov_is_running()) + return 0; + return ossl_lms_key_new(PROV_LIBCTX_OF(provctx)); +} + +static void lms_free_key(void *keydata) +{ + ossl_lms_key_free((LMS_KEY *)keydata); +} + +static int lms_has(const void *keydata, int selection) +{ + const LMS_KEY *key = keydata; + + if (!ossl_prov_is_running() || key == NULL) + return 0; + if ((selection & LMS_POSSIBLE_SELECTIONS) == 0) + return 1; /* the selection is not missing */ + + return ossl_lms_key_has(key, selection); +} + +static int lms_match(const void *keydata1, const void *keydata2, int selection) +{ + const LMS_KEY *key1 = keydata1; + const LMS_KEY *key2 = keydata2; + + if (!ossl_prov_is_running()) + return 0; + if (key1 == NULL || key2 == NULL) + return 0; + return ossl_lms_key_equal(key1, key2, selection); +} + +static int lms_import(void *keydata, int selection, const OSSL_PARAM params[]) +{ + LMS_KEY *key = keydata; + + if (!ossl_prov_is_running() || key == NULL) + return 0; + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0) + return 0; + + return ossl_lms_pubkey_from_params(params, key); +} + +static const OSSL_PARAM lms_key_types[] = { + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_END +}; +static const OSSL_PARAM *lms_imexport_types(int selection) +{ + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + return lms_key_types; + return NULL; +} + +static int lms_validate(const void *keydata, int selection, int checktype) +{ + const LMS_KEY *lmskey = keydata; + + if (!ossl_prov_is_running()) + return 0; + + if ((selection & LMS_POSSIBLE_SELECTIONS) == 0) + return 1; /* nothing to validate */ + + return ossl_lms_key_valid(lmskey, selection); +} + +const OSSL_DISPATCH ossl_lms_keymgmt_functions[] = { + { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))lms_new_key }, + { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))lms_free_key }, + { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))lms_has }, + { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))lms_match }, + { 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_DISPATCH_END +}; diff --git a/test/build.info b/test/build.info index 71ae915253f..2d38724393e 100644 --- a/test/build.info +++ b/test/build.info @@ -209,6 +209,13 @@ IF[{- !$disabled{tests} -}] INCLUDE[hpke_test]=../include ../apps/include DEPEND[hpke_test]=../libcrypto.a libtestutil.a + IF[{- !$disabled{'lms'} -}] + PROGRAMS{noinst}=lms_test + SOURCE[lms_test]=lms_test.c + INCLUDE[lms_test]=../include ../apps/include + DEPEND[lms_test]=../libcrypto.a libtestutil.a + ENDIF + SOURCE[evp_extra_test2]=evp_extra_test2.c $INITSRC tls-provider.c INCLUDE[evp_extra_test2]=../include ../apps/include DEPEND[evp_extra_test2]=../libcrypto libtestutil.a diff --git a/test/lms.inc b/test/lms.inc new file mode 100644 index 00000000000..6507eec38e9 --- /dev/null +++ b/test/lms.inc @@ -0,0 +1,38 @@ +/* + * Copyright 2024 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 "lms_common.inc" + +typedef struct LMS_ACVP_TEST_DATA_st { + const unsigned char *pub; + size_t publen; + const unsigned char *priv; + size_t privlen; + const unsigned char *msg; + size_t msglen; + const unsigned char *sig; + size_t siglen; +} LMS_ACVP_TEST_DATA; + +/* + * The data for HSS with a single level is almost identical + * to LMS data, except the public key & signature have extra 4 byte headers. + */ +#define LMS_ACVP_ITEM(name) { \ + name##_pub + 4, sizeof(name##_pub) - 4, \ + name##_priv, sizeof(name##_priv), \ + name##_msg, sizeof(name##_msg), \ + name##_sig + 4, sizeof(name##_sig) - 4 } + +/* We can only use the hss tests that have a single level here */ +static LMS_ACVP_TEST_DATA lms_testdata[] = { + LMS_ACVP_ITEM(sha256_192), + LMS_ACVP_ITEM(shake256_192), + LMS_ACVP_ITEM(shake256_256) +}; diff --git a/test/lms_common.inc b/test/lms_common.inc new file mode 100644 index 00000000000..829ef12a839 --- /dev/null +++ b/test/lms_common.inc @@ -0,0 +1,233 @@ +/* + * Copyright 2024 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 + */ + +/* + * Test vectors from + * https://datatracker.ietf.org/doc/html/draft-fluhrer-lms-more-parm-sets-15#name-test-cases + */ +static const unsigned char sha256_192_pub[] = { +0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x0A, +0x00,0x00,0x00,0x08, +0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, +0x2c,0x57,0x14,0x50,0xae,0xd9,0x9c,0xfb,0x4f,0x4a,0xc2,0x85,0xda,0x14,0x88,0x27, +0x96,0x61,0x83,0x14,0x50,0x8b,0x12,0xd2 +}; +static const unsigned char sha256_192_priv[] = { +0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, +0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, +0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f +}; +static const unsigned char sha256_192_msg[] = { +0x54,0x65,0x73,0x74,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x20,0x66,0x6f,0x72, +0x20,0x53,0x48,0x41,0x32,0x35,0x36,0x2d,0x31,0x39,0x32,0x0a +}; +static const unsigned char sha256_192_sig[] = { +/* L = 1, q = 5 */ +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x05, +0x00,0x00,0x00,0x08, +0x0b,0x50,0x40,0xa1,0x8c,0x1b,0x5c,0xab,0xcb,0xc8,0x5b,0x04,0x74,0x02,0xec,0x62,0x94,0xa3,0x0d,0xd8,0xda,0x8f,0xc3,0xda, +0xe1,0x3b,0x9f,0x08,0x75,0xf0,0x93,0x61,0xdc,0x77,0xfc,0xc4,0x48,0x1e,0xa4,0x63,0xc0,0x73,0x71,0x62,0x49,0x71,0x91,0x93, +0x61,0x4b,0x83,0x5b,0x46,0x94,0xc0,0x59,0xf1,0x2d,0x3a,0xed,0xd3,0x4f,0x3d,0xb9,0x3f,0x35,0x80,0xfb,0x88,0x74,0x3b,0x8b, +0x3d,0x06,0x48,0xc0,0x53,0x7b,0x7a,0x50,0xe4,0x33,0xd7,0xea,0x9d,0x66,0x72,0xff,0xfc,0x5f,0x42,0x77,0x0f,0xea,0xb4,0xf9, +0x8e,0xb3,0xf3,0xb2,0x3f,0xd2,0x06,0x1e,0x4d,0x0b,0x38,0xf8,0x32,0x86,0x0a,0xe7,0x66,0x73,0xad,0x1a,0x1a,0x52,0xa9,0x00, +0x5d,0xcf,0x1b,0xfb,0x56,0xfe,0x16,0xff,0x72,0x36,0x27,0x61,0x2f,0x9a,0x48,0xf7,0x90,0xf3,0xc4,0x7a,0x67,0xf8,0x70,0xb8, +0x1e,0x91,0x9d,0x99,0x91,0x9c,0x8d,0xb4,0x81,0x68,0x83,0x8c,0xec,0xe0,0xab,0xfb,0x68,0x3d,0xa4,0x8b,0x92,0x09,0x86,0x8b, +0xe8,0xec,0x10,0xc6,0x3d,0x8b,0xf8,0x0d,0x36,0x49,0x8d,0xfc,0x20,0x5d,0xc4,0x5d,0x0d,0xd8,0x70,0x57,0x2d,0x6d,0x8f,0x1d, +0x90,0x17,0x7c,0xf5,0x13,0x7b,0x8b,0xbf,0x7b,0xcb,0x67,0xa4,0x6f,0x86,0xf2,0x6c,0xfa,0x5a,0x44,0xcb,0xca,0xa4,0xe1,0x8d, +0xa0,0x99,0xa9,0x8b,0x0b,0x3f,0x96,0xd5,0xac,0x8a,0xc3,0x75,0xd8,0xda,0x2a,0x7c,0x24,0x80,0x04,0xba,0x11,0xd7,0xac,0x77, +0x5b,0x92,0x18,0x35,0x9c,0xdd,0xab,0x4c,0xf8,0xcc,0xc6,0xd5,0x4c,0xb7,0xe1,0xb3,0x5a,0x36,0xdd,0xc9,0x26,0x5c,0x08,0x70, +0x63,0xd2,0xfc,0x67,0x42,0xa7,0x17,0x78,0x76,0x47,0x6a,0x32,0x4b,0x03,0x29,0x5b,0xfe,0xd9,0x9f,0x2e,0xaf,0x1f,0x38,0x97, +0x05,0x83,0xc1,0xb2,0xb6,0x16,0xaa,0xd0,0xf3,0x1c,0xd7,0xa4,0xb1,0xbb,0x0a,0x51,0xe4,0x77,0xe9,0x4a,0x01,0xbb,0xb4,0xd6, +0xf8,0x86,0x6e,0x25,0x28,0xa1,0x59,0xdf,0x3d,0x6c,0xe2,0x44,0xd2,0xb6,0x51,0x8d,0x1f,0x02,0x12,0x28,0x5a,0x3c,0x2d,0x4a, +0x92,0x70,0x54,0xa1,0xe1,0x62,0x0b,0x5b,0x02,0xaa,0xb0,0xc8,0xc1,0x0e,0xd4,0x8a,0xe5,0x18,0xea,0x73,0xcb,0xa8,0x1f,0xcf, +0xff,0x88,0xbf,0xf4,0x61,0xda,0xc5,0x1e,0x7a,0xb4,0xca,0x75,0xf4,0x7a,0x62,0x59,0xd2,0x48,0x20,0xb9,0x99,0x57,0x92,0xd1, +0x39,0xf6,0x1a,0xe2,0xa8,0x18,0x6a,0xe4,0xe3,0xc9,0xbf,0xe0,0xaf,0x2c,0xc7,0x17,0xf4,0x24,0xf4,0x1a,0xa6,0x7f,0x03,0xfa, +0xed,0xb0,0x66,0x51,0x15,0xf2,0x06,0x7a,0x46,0x84,0x3a,0x4c,0xbb,0xd2,0x97,0xd5,0xe8,0x3b,0xc1,0xaa,0xfc,0x18,0xd1,0xd0, +0x3b,0x3d,0x89,0x4e,0x85,0x95,0xa6,0x52,0x60,0x73,0xf0,0x2a,0xb0,0xf0,0x8b,0x99,0xfd,0x9e,0xb2,0x08,0xb5,0x9f,0xf6,0x31, +0x7e,0x55,0x45,0xe6,0xf9,0xad,0x5f,0x9c,0x18,0x3a,0xbd,0x04,0x3d,0x5a,0xcd,0x6e,0xb2,0xdd,0x4d,0xa3,0xf0,0x2d,0xbc,0x31, +0x67,0xb4,0x68,0x72,0x0a,0x4b,0x8b,0x92,0xdd,0xfe,0x79,0x60,0x99,0x8b,0xb7,0xa0,0xec,0xf2,0xa2,0x6a,0x37,0x59,0x82,0x99, +0x41,0x3f,0x7b,0x2a,0xec,0xd3,0x9a,0x30,0xce,0xc5,0x27,0xb4,0xd9,0x71,0x0c,0x44,0x73,0x63,0x90,0x22,0x45,0x1f,0x50,0xd0, +0x1c,0x04,0x57,0x12,0x5d,0xa0,0xfa,0x44,0x29,0xc0,0x7d,0xad,0x85,0x9c,0x84,0x6c,0xbb,0xd9,0x3a,0xb5,0xb9,0x1b,0x01,0xbc, +0x77,0x0b,0x08,0x9c,0xfe,0xde,0x6f,0x65,0x1e,0x86,0xdd,0x7c,0x15,0x98,0x9c,0x8b,0x53,0x21,0xde,0xa9,0xca,0x60,0x8c,0x71, +0xfd,0x86,0x23,0x23,0x07,0x2b,0x82,0x7c,0xee,0x7a,0x7e,0x28,0xe4,0xe2,0xb9,0x99,0x64,0x72,0x33,0xc3,0x45,0x69,0x44,0xbb, +0x7a,0xef,0x91,0x87,0xc9,0x6b,0x3f,0x5b,0x79,0xfb,0x98,0xbc,0x76,0xc3,0x57,0x4d,0xd0,0x6f,0x0e,0x95,0x68,0x5e,0x5b,0x3a, +0xef,0x3a,0x54,0xc4,0x15,0x5f,0xe3,0xad,0x81,0x77,0x49,0x62,0x9c,0x30,0xad,0xbe,0x89,0x7c,0x4f,0x44,0x54,0xc8,0x6c,0x49, +0x00,0x00,0x00,0x0a, +0xe9,0xca,0x10,0xea,0xa8,0x11,0xb2,0x2a,0xe0,0x7f,0xb1,0x95,0xe3,0x59,0x0a,0x33,0x4e,0xa6,0x42,0x09,0x94,0x2f,0xba,0xe3, +0x38,0xd1,0x9f,0x15,0x21,0x82,0xc8,0x07,0xd3,0xc4,0x0b,0x18,0x9d,0x3f,0xcb,0xea,0x94,0x2f,0x44,0x68,0x24,0x39,0xb1,0x91, +0x33,0x2d,0x33,0xae,0x0b,0x76,0x1a,0x2a,0x8f,0x98,0x4b,0x56,0xb2,0xac,0x2f,0xd4,0xab,0x08,0x22,0x3a,0x69,0xed,0x1f,0x77, +0x19,0xc7,0xaa,0x7e,0x9e,0xee,0x96,0x50,0x4b,0x0e,0x60,0xc6,0xbb,0x5c,0x94,0x2d,0x69,0x5f,0x04,0x93,0xeb,0x25,0xf8,0x0a, +0x58,0x71,0xcf,0xfd,0x13,0x1d,0x0e,0x04,0xff,0xe5,0x06,0x5b,0xc7,0x87,0x5e,0x82,0xd3,0x4b,0x40,0xb6,0x9d,0xd9,0xf3,0xc1 +}; + +static const unsigned char shake256_192_pub[] = { +0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x14, +0x00,0x00,0x00,0x10, +0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, +0xdb,0x54,0xa4,0x50,0x99,0x01,0x05,0x1c,0x01,0xe2,0x6d,0x99,0x90,0xe5,0x50,0x34, +0x79,0x86,0xda,0x87,0x92,0x4f,0xf0,0xb1 +}; +static const unsigned char shake256_192_priv[] = { +/* SEED */ +0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, +0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, +/* I */ +0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f +}; +static const unsigned char shake256_192_msg[] = { +0x54,0x65,0x73,0x74,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x20,0x66,0x6f,0x72, +0x20,0x53,0x48,0x41,0x4b,0x45,0x32,0x35,0x36,0x2d,0x31,0x39,0x32,0x0a +}; +static const unsigned char shake256_192_sig[] = { +/* L = 1, q = 6 */ +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x06, +0x00,0x00,0x00,0x10, +0x84,0x21,0x9d,0xa9,0xce,0x9f,0xff,0xb1,0x6e,0xdb,0x94,0x52,0x7c,0x6d,0x10,0x56,0x55,0x87,0xdb,0x28,0x06,0x2d,0xea,0xc4, +0x20,0x8e,0x62,0xfc,0x4f,0xbe,0x9d,0x85,0xde,0xb3,0xc6,0xbd,0x2c,0x01,0x64,0x0a,0xcc,0xb3,0x87,0xd8,0xa6,0x09,0x3d,0x68, +0x51,0x12,0x34,0xa6,0xa1,0xa5,0x01,0x08,0x09,0x1c,0x03,0x4c,0xb1,0x77,0x7e,0x02,0xb5,0xdf,0x46,0x61,0x49,0xa6,0x69,0x69, +0xa4,0x98,0xe4,0x20,0x0c,0x0a,0x0c,0x1b,0xf5,0xd1,0x00,0xcd,0xb9,0x7d,0x2d,0xd4,0x0e,0xfd,0x3c,0xad,0xa2,0x78,0xac,0xc5, +0xa5,0x70,0x07,0x1a,0x04,0x39,0x56,0x11,0x2c,0x6d,0xee,0xbd,0x1e,0xb3,0xa7,0xb5,0x6f,0x5f,0x67,0x91,0x51,0x5a,0x7b,0x5f, +0xfd,0xdb,0x0e,0xc2,0xd9,0x09,0x4b,0xfb,0xc8,0x89,0xea,0x15,0xc3,0xc7,0xb9,0xbe,0xa9,0x53,0xef,0xb7,0x5e,0xd6,0x48,0xf5, +0x35,0xb9,0xac,0xab,0x66,0xa2,0xe9,0x63,0x1e,0x42,0x6e,0x4e,0x99,0xb7,0x33,0xca,0xa6,0xc5,0x59,0x63,0x92,0x9b,0x77,0xfe, +0xc5,0x4a,0x7e,0x70,0x3d,0x81,0x62,0xe7,0x36,0x87,0x5c,0xb6,0xa4,0x55,0xd4,0xa9,0x01,0x5c,0x7a,0x6d,0x8f,0xd5,0xfe,0x75, +0xe4,0x02,0xb4,0x70,0x36,0xdc,0x37,0x70,0xf4,0xa1,0xdd,0x0a,0x55,0x9c,0xb4,0x78,0xc7,0xfb,0x17,0x26,0x00,0x53,0x21,0xbe, +0x9d,0x1a,0xc2,0xde,0x94,0xd7,0x31,0xee,0x4c,0xa7,0x9c,0xff,0x45,0x4c,0x81,0x1f,0x46,0xd1,0x19,0x80,0x90,0x9f,0x04,0x7b, +0x20,0x05,0xe8,0x4b,0x6e,0x15,0x37,0x84,0x46,0xb1,0xca,0x69,0x1e,0xfe,0x49,0x1e,0xa9,0x8a,0xcc,0x9d,0x3c,0x0f,0x78,0x5c, +0xab,0xa5,0xe2,0xeb,0x3c,0x30,0x68,0x11,0xc2,0x40,0xba,0x22,0x80,0x29,0x23,0x82,0x7d,0x58,0x26,0x39,0x30,0x4a,0x1e,0x97, +0x83,0xba,0x5b,0xc9,0xd6,0x9d,0x99,0x9a,0x7d,0xb8,0xf7,0x49,0x77,0x0c,0x3c,0x04,0xa1,0x52,0x85,0x6d,0xc7,0x26,0xd8,0x06, +0x79,0x21,0x46,0x5b,0x61,0xb3,0xf8,0x47,0xb1,0x3b,0x26,0x35,0xa4,0x53,0x79,0xe5,0xad,0xc6,0xff,0x58,0xa9,0x9b,0x00,0xe6, +0x0a,0xc7,0x67,0xf7,0xf3,0x01,0x75,0xf9,0xf7,0xa1,0x40,0x25,0x7e,0x21,0x8b,0xe3,0x07,0x95,0x4b,0x12,0x50,0xc9,0xb4,0x19, +0x02,0xc4,0xfa,0x7c,0x90,0xd8,0xa5,0x92,0x94,0x5c,0x66,0xe8,0x6a,0x76,0xde,0xfc,0xb8,0x45,0x00,0xb5,0x55,0x98,0xa1,0x99, +0x0f,0xaa,0xa1,0x00,0x77,0xc7,0x4c,0x94,0x89,0x57,0x31,0x58,0x5c,0x8f,0x90,0x0d,0xe1,0xa1,0xc6,0x75,0xbd,0x8b,0x0c,0x18, +0x0e,0xbe,0x2b,0x5e,0xb3,0xef,0x80,0x19,0xec,0xe3,0xe1,0xea,0x72,0x23,0xeb,0x79,0x06,0xa2,0x04,0x2b,0x62,0x62,0xb4,0xaa, +0x25,0xc4,0xb8,0xa0,0x5f,0x20,0x5c,0x8b,0xef,0xee,0xf1,0x1c,0xef,0xf1,0x28,0x25,0x08,0xd7,0x1b,0xc2,0xa8,0xcf,0xa0,0xa9, +0x9f,0x73,0xf3,0xe3,0xa7,0x4b,0xb4,0xb3,0xc0,0xd8,0xca,0x2a,0xbd,0x0e,0x1c,0x2c,0x17,0xda,0xfe,0x18,0xb4,0xee,0x22,0x98, +0xe8,0x7b,0xcf,0xb1,0x30,0x5b,0x3c,0x06,0x9e,0x6d,0x38,0x55,0x69,0xa4,0x06,0x7e,0xd5,0x47,0x48,0x6d,0xd1,0xa5,0x0d,0x6f, +0x4a,0x58,0xaa,0xb9,0x6e,0x2f,0xa8,0x83,0xa9,0xa3,0x9e,0x1b,0xd4,0x55,0x41,0xee,0xe9,0x4e,0xfc,0x32,0xfa,0xa9,0xa9,0x4b, +0xe6,0x6d,0xc8,0x53,0x8b,0x2d,0xab,0x05,0xae,0xe5,0xef,0xa6,0xb3,0xb2,0xef,0xb3,0xfd,0x02,0x0f,0xe7,0x89,0x47,0x7a,0x93, +0xaf,0xff,0x9a,0x3e,0x63,0x6d,0xbb,0xa8,0x64,0xa5,0xbf,0xfa,0x3e,0x28,0xd1,0x3d,0x49,0xbb,0x59,0x7d,0x94,0x86,0x5b,0xde, +0x88,0xc4,0x62,0x7f,0x20,0x6a,0xb2,0xb4,0x65,0x08,0x4d,0x6b,0x78,0x06,0x66,0xe9,0x52,0xf8,0x71,0x0e,0xfd,0x74,0x8b,0xd0, +0xf1,0xae,0x8f,0x10,0x35,0x08,0x7f,0x50,0x28,0xf1,0x4a,0xff,0xcc,0x5f,0xff,0xe3,0x32,0x12,0x1a,0xe4,0xf8,0x7a,0xc5,0xf1, +0xea,0xc9,0x06,0x26,0x08,0xc7,0xd8,0x77,0x08,0xf1,0x72,0x3f,0x38,0xb2,0x32,0x37,0xa4,0xed,0xf4,0xb4,0x9a,0x5c,0xd3,0xd7, +0x00,0x00,0x00,0x14, +0xdd,0x4b,0xdc,0x8f,0x92,0x8f,0xb5,0x26,0xf6,0xfb,0x7c,0xdb,0x94,0x4a,0x7e,0xba,0xa7,0xfb,0x05,0xd9,0x95,0xb5,0x72,0x1a, +0x27,0x09,0x6a,0x50,0x07,0xd8,0x2f,0x79,0xd0,0x63,0xac,0xd4,0x34,0xa0,0x4e,0x97,0xf6,0x15,0x52,0xf7,0xf8,0x1a,0x93,0x17, +0xb4,0xec,0x7c,0x87,0xa5,0xed,0x10,0xc8,0x81,0x92,0x8f,0xc6,0xeb,0xce,0x6d,0xfc,0xe9,0xda,0xae,0x9c,0xc9,0xdb,0xa6,0x90, +0x7c,0xa9,0xa9,0xdd,0x5f,0x9f,0x57,0x37,0x04,0xd5,0xe6,0xcf,0x22,0xa4,0x3b,0x04,0xe6,0x4c,0x1f,0xfc,0x7e,0x1c,0x44,0x2e, +0xcb,0x49,0x5b,0xa2,0x65,0xf4,0x65,0xc5,0x62,0x91,0xa9,0x02,0xe6,0x2a,0x46,0x1f,0x6d,0xfd,0xa2,0x32,0x45,0x7f,0xad,0x14 +}; + +static const unsigned char shake256_256_pub[] = { +0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x0C, +0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, +0x9b,0xb7,0xfa,0xee,0x41,0x1c,0xae,0x80,0x6c,0x16,0xa4,0x66,0xc3,0x19,0x1a,0x8b, +0x65,0xd0,0xac,0x31,0x93,0x2b,0xbf,0x0c,0x2d,0x07,0xc7,0xa4,0xa3,0x63,0x79,0xfe +}; +static const unsigned char shake256_256_priv[] = { +/* SEED */ +0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, +0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, +/* I */ +0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f +}; +static const unsigned char shake256_256_msg[] = { +0x54,0x65,0x73,0x74,0x20,0x6d,0x65,0x73,0x61,0x67,0x65,0x20,0x66,0x6f,0x72,0x20, +0x53,0x48,0x41,0x4b,0x45,0x32,0x35,0x36,0x2d,0x32,0x35,0x36,0x0a +}; +static const unsigned char shake256_256_sig[] = { +/* L = 1, q = 7 */ +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07, +0x00,0x00,0x00,0x0c, +0xb8,0x27,0x09,0xf0,0xf0,0x0e,0x83,0x75,0x91,0x90,0x99,0x62,0x33,0xd1,0xee,0x4f, +0x4e,0xc5,0x05,0x34,0x47,0x3c,0x02,0xff,0xa1,0x45,0xe8,0xca,0x28,0x74,0xe3,0x2b, +0x16,0xb2,0x28,0x11,0x8c,0x62,0xb9,0x6c,0x9c,0x77,0x67,0x8b,0x33,0x18,0x37,0x30, +0xde,0xba,0xad,0xe8,0xfe,0x60,0x7f,0x05,0xc6,0x69,0x7b,0xc9,0x71,0x51,0x9a,0x34, +0x1d,0x69,0xc0,0x01,0x29,0x68,0x0b,0x67,0xe7,0x5b,0x3b,0xd7,0xd8,0xaa,0x5c,0x8b, +0x71,0xf0,0x26,0x69,0xd1,0x77,0xa2,0xa0,0xee,0xa8,0x96,0xdc,0xd1,0x66,0x0f,0x16, +0x86,0x4b,0x30,0x2f,0xf3,0x21,0xf9,0xc4,0xb8,0x35,0x44,0x08,0xd0,0x67,0x60,0x50, +0x4f,0x76,0x8e,0xbd,0x4e,0x54,0x5a,0x9b,0x0a,0xc0,0x58,0xc5,0x75,0x07,0x8e,0x6c, +0x14,0x03,0x16,0x0f,0xb4,0x54,0x50,0xd6,0x1a,0x9c,0x8c,0x81,0xf6,0xbd,0x69,0xbd, +0xfa,0x26,0xa1,0x6e,0x12,0xa2,0x65,0xba,0xf7,0x9e,0x9e,0x23,0x3e,0xb7,0x1a,0xf6, +0x34,0xec,0xc6,0x6d,0xc8,0x8e,0x10,0xc6,0xe0,0x14,0x29,0x42,0xd4,0x84,0x3f,0x70, +0xa0,0x24,0x27,0x27,0xbc,0x5a,0x2a,0xab,0xf7,0xb0,0xec,0x12,0xa9,0x90,0x90,0xd8, +0xca,0xee,0xf2,0x13,0x03,0xf8,0xac,0x58,0xb9,0xf2,0x00,0x37,0x1d,0xc9,0xe4,0x1a, +0xb9,0x56,0xe1,0xa3,0xef,0xed,0x9d,0x4b,0xbb,0x38,0x97,0x5b,0x46,0xc2,0x8d,0x5f, +0x5b,0x3e,0xd1,0x9d,0x84,0x7b,0xd0,0xa7,0x37,0x17,0x72,0x63,0xcb,0xc1,0xa2,0x26, +0x2d,0x40,0xe8,0x08,0x15,0xee,0x14,0x9b,0x6c,0xce,0x27,0x14,0x38,0x4c,0x9b,0x7f, +0xce,0xb3,0xbb,0xcb,0xd2,0x52,0x28,0xdd,0xa8,0x30,0x65,0x36,0x37,0x6f,0x87,0x93, +0xec,0xad,0xd6,0x02,0x02,0x65,0xda,0xb9,0x07,0x5f,0x64,0xc7,0x73,0xef,0x97,0xd0, +0x73,0x52,0x91,0x99,0x95,0xb7,0x44,0x04,0xcc,0x69,0xa6,0xf3,0xb4,0x69,0x44,0x5c, +0x92,0x86,0xa6,0xb2,0xc9,0xf6,0xdc,0x83,0x9b,0xe7,0x66,0x18,0xf0,0x53,0xde,0x76, +0x3d,0xa3,0x57,0x1e,0xf7,0x0f,0x80,0x5c,0x9c,0xc5,0x4b,0x8e,0x50,0x1a,0x98,0xb9, +0x8c,0x70,0x78,0x5e,0xeb,0x61,0x73,0x7e,0xce,0xd7,0x8b,0x0e,0x38,0x0d,0xed,0x4f, +0x76,0x9a,0x9d,0x42,0x27,0x86,0xde,0xf5,0x97,0x00,0xee,0xf3,0x27,0x80,0x17,0xba, +0xbb,0xe5,0xf9,0x06,0x3b,0x46,0x8a,0xe0,0xdd,0x61,0xd9,0x4f,0x9f,0x99,0xd5,0xcc, +0x36,0xfb,0xec,0x41,0x78,0xd2,0xbd,0xa3,0xad,0x31,0xe1,0x64,0x4a,0x2b,0xcc,0xe2, +0x08,0xd7,0x2d,0x50,0xa7,0x63,0x78,0x51,0xaa,0x90,0x8b,0x94,0xdc,0x43,0x76,0x12, +0x0d,0x5b,0xea,0xb0,0xfb,0x80,0x5e,0x19,0x45,0xc4,0x18,0x34,0xdd,0x60,0x85,0xe6, +0xdb,0x1a,0x3a,0xa7,0x8f,0xcb,0x59,0xf6,0x2b,0xde,0x68,0x23,0x6a,0x10,0x61,0x8c, +0xff,0x12,0x3a,0xbe,0x64,0xda,0xe8,0xda,0xbb,0x2e,0x84,0xca,0x70,0x53,0x09,0xc2, +0xab,0x98,0x6d,0x4f,0x83,0x26,0xba,0x06,0x42,0x27,0x2c,0xb3,0x90,0x4e,0xb9,0x6f, +0x6f,0x5e,0x3b,0xb8,0x81,0x39,0x97,0x88,0x1b,0x6a,0x33,0xca,0xc0,0x71,0x4e,0x4b, +0x5e,0x7a,0x88,0x2a,0xd8,0x7e,0x14,0x19,0x31,0xf9,0x7d,0x61,0x2b,0x84,0xe9,0x03, +0xe7,0x73,0x13,0x9a,0xe3,0x77,0xf5,0xba,0x19,0xac,0x86,0x19,0x8d,0x48,0x5f,0xca, +0x97,0x74,0x25,0x68,0xf6,0xff,0x75,0x81,0x20,0xa8,0x9b,0xf1,0x90,0x59,0xb8,0xa6, +0xbf,0xe2,0xd8,0x6b,0x12,0x77,0x81,0x64,0x43,0x6a,0xb2,0x65,0x9b,0xa8,0x66,0x76, +0x7f,0xcc,0x43,0x55,0x84,0x12,0x5f,0xb7,0x92,0x42,0x01,0xee,0x67,0xb5,0x35,0xda, +0xf7,0x2c,0x5c,0xb3,0x1f,0x5a,0x0b,0x1d,0x92,0x63,0x24,0xc2,0x6e,0x67,0xd4,0xc3, +0x83,0x6e,0x30,0x1a,0xa0,0x9b,0xae,0x8f,0xb3,0xf9,0x1f,0x16,0x22,0xb1,0x81,0x8c, +0xcf,0x44,0x0f,0x52,0xca,0x9b,0x5b,0x9b,0x99,0xab,0xa8,0xa6,0x75,0x4a,0xae,0x2b, +0x96,0x7c,0x49,0x54,0xfa,0x85,0x29,0x8a,0xd9,0xb1,0xe7,0x4f,0x27,0xa4,0x61,0x27, +0xc3,0x61,0x31,0xc8,0x99,0x1f,0x0c,0xc2,0xba,0x57,0xa1,0x5d,0x35,0xc9,0x1c,0xf8, +0xbc,0x48,0xe8,0xe2,0x0d,0x62,0x5a,0xf4,0xe8,0x5d,0x8f,0x94,0x02,0xec,0x44,0xaf, +0xbd,0x47,0x92,0xb9,0x24,0xb8,0x39,0x33,0x2a,0x64,0x78,0x8a,0x77,0x01,0xa3,0x00, +0x94,0xb9,0xec,0x4b,0x9f,0x4b,0x64,0x8f,0x16,0x8b,0xf4,0x57,0xfb,0xb3,0xc9,0x59, +0x4f,0xa8,0x79,0x20,0xb6,0x45,0xe4,0x2a,0xa2,0xfe,0xcc,0x9e,0x21,0xe0,0x00,0xca, +0x7d,0x3f,0xf9,0x14,0xe1,0x5c,0x40,0xa8,0xbc,0x53,0x31,0x29,0xa7,0xfd,0x39,0x52, +0x93,0x76,0x43,0x0f,0x35,0x5a,0xaf,0x96,0xa0,0xa1,0x3d,0x13,0xf2,0x41,0x91,0x41, +0xb3,0xcc,0x25,0x84,0x3e,0x8c,0x90,0xd0,0xe5,0x51,0xa3,0x55,0xdd,0x90,0xad,0x77, +0x0e,0xa7,0x25,0x52,0x14,0xce,0x11,0x23,0x86,0x05,0xde,0x2f,0x00,0x0d,0x20,0x01, +0x04,0xd0,0xc3,0xa3,0xe3,0x5a,0xe6,0x4e,0xa1,0x0a,0x3e,0xff,0x37,0xac,0x7e,0x95, +0x49,0x21,0x7c,0xdf,0x52,0xf3,0x07,0x17,0x2e,0x2f,0x6c,0x7a,0x2a,0x45,0x43,0xe1, +0x43,0x14,0x03,0x65,0x25,0xb1,0xad,0x53,0xee,0xad,0xdf,0x0e,0x24,0xb1,0xf3,0x69, +0x14,0xed,0x22,0x48,0x3f,0x28,0x89,0xf6,0x1e,0x62,0xb6,0xfb,0x78,0xf5,0x64,0x5b, +0xdb,0xb0,0x2c,0x9e,0x5b,0xf9,0x7d,0xb7,0xa0,0x00,0x4e,0x87,0xc2,0xa5,0x53,0x99, +0xb6,0x19,0x58,0x78,0x6c,0x97,0xbd,0x52,0xfa,0x19,0x9c,0x27,0xf6,0xbb,0x4d,0x68, +0xc4,0x90,0x79,0x33,0x56,0x27,0x55,0xbf,0xec,0x5d,0x4f,0xb5,0x2f,0x06,0xc2,0x89, +0xd6,0xe8,0x52,0xcf,0x6b,0xc7,0x73,0xff,0xd4,0xc0,0x7e,0xe2,0xd6,0xcc,0x55,0xf5, +0x7e,0xdc,0xfb,0xc8,0xe8,0x69,0x2a,0x49,0xad,0x47,0xa1,0x21,0xfe,0x3c,0x1b,0x16, +0xca,0xb1,0xcc,0x28,0x5f,0xaf,0x67,0x93,0xff,0xad,0x7a,0x8c,0x34,0x1a,0x49,0xc5, +0xd2,0xdc,0xe7,0x06,0x9e,0x46,0x4c,0xb9,0x0a,0x00,0xb2,0x90,0x36,0x48,0xb2,0x3c, +0x81,0xa6,0x8e,0x21,0xd7,0x48,0xa7,0xe7,0xb1,0xdf,0x8a,0x59,0x3f,0x38,0x94,0xb2, +0x47,0x7e,0x83,0x16,0x94,0x7c,0xa7,0x25,0xd1,0x41,0x13,0x52,0x02,0xa9,0x44,0x2e, +0x1d,0xb3,0x3b,0xbd,0x39,0x0d,0x2c,0x04,0x40,0x1c,0x39,0xb2,0x53,0xb7,0x8c,0xe2, +0x97,0xb0,0xe1,0x47,0x55,0xe4,0x6e,0xc0,0x8a,0x14,0x6d,0x27,0x9c,0x67,0xaf,0x70, +0xde,0x25,0x68,0x90,0x80,0x4d,0x83,0xd6,0xec,0x5c,0xa3,0x28,0x6f,0x1f,0xca,0x9c, +0x72,0xab,0xf6,0xef,0x86,0x8e,0x7f,0x6e,0xb0,0xfd,0xdd,0xa1,0xb0,0x40,0xec,0xec, +0x9b,0xbc,0x69,0xe2,0xfd,0x86,0x18,0xe9,0xdb,0x3b,0xdb,0x0a,0xf1,0x3d,0xda,0x06, +0xc6,0x61,0x7e,0x95,0xaf,0xa5,0x22,0xd6,0xa2,0x55,0x2d,0xe1,0x53,0x24,0xd9,0x91, +0x19,0xf5,0x5e,0x9a,0xf1,0x1a,0xe3,0xd5,0x61,0x4b,0x56,0x4c,0x64,0x2d,0xbf,0xec, +0x6c,0x64,0x41,0x98,0xce,0x80,0xd2,0x43,0x3a,0xc8,0xee,0x73,0x8f,0x9d,0x82,0x5e, +0x00,0x00,0x00,0x0f, +0x71,0xd5,0x85,0xa3,0x5c,0x3a,0x90,0x83,0x79,0xf4,0x07,0x2d,0x07,0x03,0x11,0xdb, +0x5d,0x65,0xb2,0x42,0xb7,0x14,0xbc,0x5a,0x75,0x6b,0xa5,0xe2,0x28,0xab,0xfa,0x0d, +0x13,0x29,0x97,0x8a,0x05,0xd5,0xe8,0x15,0xcf,0x4d,0x74,0xc1,0xe5,0x47,0xec,0x4a, +0xa3,0xca,0x95,0x6a,0xe9,0x27,0xdf,0x8b,0x29,0xfb,0x9f,0xab,0x39,0x17,0xa7,0xa4, +0xae,0x61,0xba,0x57,0xe5,0x34,0x2e,0x9d,0xb1,0x2c,0xaf,0x6f,0x6d,0xbc,0x52,0x53, +0xde,0x52,0x68,0xd4,0xb0,0xc4,0xce,0x4e,0xbe,0x68,0x52,0xf0,0x12,0xb1,0x62,0xfc, +0x1c,0x12,0xb9,0xff,0xc3,0xbc,0xb1,0xd3,0xac,0x85,0x89,0x77,0x76,0x55,0xe2,0x2c, +0xd9,0xb9,0x9f,0xf1,0xe4,0x34,0x6f,0xd0,0xef,0xea,0xa1,0xda,0x04,0x46,0x92,0xe7, +0xad,0x6b,0xfc,0x33,0x7d,0xb6,0x98,0x49,0xe5,0x44,0x11,0xdf,0x89,0x20,0xc2,0x28, +0xa2,0xb7,0x76,0x2c,0x11,0xe4,0xb1,0xc4,0x9e,0xfb,0x74,0x48,0x6d,0x39,0x31,0xea, +}; diff --git a/test/lms_test.c b/test/lms_test.c new file mode 100644 index 00000000000..6c90b6f7ee1 --- /dev/null +++ b/test/lms_test.c @@ -0,0 +1,127 @@ +/* + * Copyright 2024 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 +#include +#include "crypto/lms.h" +#include "internal/nelem.h" +#include "testutil.h" +#include "lms.inc" + +static OSSL_LIB_CTX *libctx = NULL; + +static EVP_PKEY *lms_pubkey_from_data(const unsigned char *data, size_t datalen) +{ + int ret; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *key = NULL; + OSSL_PARAM params[2]; + + 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)) + && TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1) + && (EVP_PKEY_fromdata(ctx, &key, EVP_PKEY_PUBLIC_KEY, params) == 1); + if (ret == 0) { + EVP_PKEY_free(key); + key = NULL; + } + EVP_PKEY_CTX_free(ctx); + return key; +} + +static int lms_bad_pub_len_test(void) +{ + int ret = 0; + LMS_ACVP_TEST_DATA *td = &lms_testdata[1]; + EVP_PKEY *pkey = NULL; + size_t publen = 0; + unsigned char pubdata[128]; + + if (!TEST_size_t_le(td->publen + 16, sizeof(pubdata))) + goto end; + + OPENSSL_cleanse(pubdata, sizeof(pubdata)); + memcpy(pubdata, td->pub, td->publen); + + for (publen = 0; publen <= td->publen + 16; publen += 3) { + if (publen == td->publen) + continue; + if (!TEST_ptr_null(pkey = lms_pubkey_from_data(pubdata, publen))) + goto end; + } + ret = 1; +end: + if (ret == 0) + TEST_note("Incorrectly accepted public key of length %u (expected %u)", + (unsigned)publen, (unsigned)td->publen); + EVP_PKEY_free(pkey); + + return ret == 1; +} + +static int lms_key_eq_test(void) +{ + int ret = 0; + EVP_PKEY *key[3] = { NULL, NULL, NULL }; + LMS_ACVP_TEST_DATA *td1 = &lms_testdata[0]; + LMS_ACVP_TEST_DATA *td2 = &lms_testdata[1]; +#ifndef OPENSSL_NO_EC + EVP_PKEY *eckey = NULL; +#endif + + 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))) + goto end; + + ret = TEST_int_eq(EVP_PKEY_eq(key[0], key[1]), 1) + && TEST_int_ne(EVP_PKEY_eq(key[0], key[2]), 1); + if (ret == 0) + goto end; + +#ifndef OPENSSL_NO_EC + if (!TEST_ptr(eckey = EVP_PKEY_Q_keygen(libctx, NULL, "EC", "P-256"))) + goto end; + ret = TEST_int_ne(EVP_PKEY_eq(key[0], eckey), 1); + EVP_PKEY_free(eckey); +#endif +end: + EVP_PKEY_free(key[2]); + EVP_PKEY_free(key[1]); + EVP_PKEY_free(key[0]); + return ret; +} + +static int lms_key_validate_test(void) +{ + int ret = 0; + LMS_ACVP_TEST_DATA *td = &lms_testdata[0]; + EVP_PKEY_CTX *vctx = NULL; + EVP_PKEY *key = NULL; + + if (!TEST_ptr(key = lms_pubkey_from_data(td->pub, td->publen))) + return 0; + if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL))) + goto end; + ret = TEST_int_eq(EVP_PKEY_check(vctx), 1); + EVP_PKEY_CTX_free(vctx); +end: + EVP_PKEY_free(key); + return ret; +} + +int setup_tests(void) +{ + ADD_TEST(lms_bad_pub_len_test); + ADD_TEST(lms_key_validate_test); + ADD_TEST(lms_key_eq_test); + return 1; +} diff --git a/test/recipes/30-test_lms.t b/test/recipes/30-test_lms.t new file mode 100644 index 00000000000..ada1ab01661 --- /dev/null +++ b/test/recipes/30-test_lms.t @@ -0,0 +1,26 @@ +#! /usr/bin/env perl +# Copyright 2024 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 + +use strict; +use warnings; + +use OpenSSL::Test qw(:DEFAULT srctop_dir bldtop_dir); +use OpenSSL::Test::Utils; + +BEGIN { + setup("test_lms"); +} + +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; + +ok(run(test(["lms_test"])), "running lms_test"); +