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: 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)
This commit is contained in:
slontis 2024-10-03 11:16:15 +10:00 committed by Pauli
parent 495f5fa0ba
commit 2a6a2adc8d
21 changed files with 1193 additions and 1 deletions

View File

@ -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 ml_dsa slh_dsa
ffc hpke thread lms ml_dsa slh_dsa
LIBS=../libcrypto

7
crypto/lms/build.info Normal file
View File

@ -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

View File

@ -0,0 +1,49 @@
/*
* 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
* 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;
}

108
crypto/lms/lms_key.c Normal file
View File

@ -0,0 +1,108 @@
/*
* 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core_dispatch.h>
#include "crypto/lms.h"
#include <string.h>
/**
* @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;
}

54
crypto/lms/lms_params.c Normal file
View File

@ -0,0 +1,54 @@
/*
* 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
* 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;
}

View File

@ -0,0 +1,116 @@
/*
* 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core_names.h>
#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;
}

View File

@ -4807,6 +4807,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-ML-DSA.html]=man7/EVP_PKEY-ML-DSA.pod
GENERATE[html/man7/EVP_PKEY-ML-DSA.html]=man7/EVP_PKEY-ML-DSA.pod
DEPEND[man/man7/EVP_PKEY-ML-DSA.7]=man7/EVP_PKEY-ML-DSA.pod
@ -5239,6 +5243,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-ML-DSA.html \
html/man7/EVP_PKEY-ML-KEM.html \
html/man7/EVP_PKEY-RSA.html \
@ -5396,6 +5401,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-ML-DSA.7 \
man/man7/EVP_PKEY-ML-KEM.7 \
man/man7/EVP_PKEY-RSA.7 \

83
doc/man7/EVP_PKEY-LMS.pod Normal file
View File

@ -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<LMS> 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<OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY>) <octet string>
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<EVP_PKEY> 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<EVP_KEYMGMT(3)>,
L<EVP_PKEY(3)>,
L<provider-keymgmt(7)>
=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<https://www.openssl.org/source/license.html>.
=cut

146
include/crypto/lms.h Normal file
View File

@ -0,0 +1,146 @@
/*
* 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
* 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 <openssl/params.h>
/*
* 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 */

63
include/crypto/lms_util.h Normal file
View File

@ -0,0 +1,63 @@
/*
* 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
* 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;
}

View File

@ -31,4 +31,8 @@ typedef struct ecx_key_st ECX_KEY;
typedef struct prov_skey_st PROV_SKEY;
# ifndef OPENSSL_NO_LMS
typedef struct lms_key_st LMS_KEY;
# endif
#endif

View File

@ -604,6 +604,10 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = {
{ 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
#ifndef OPENSSL_NO_ML_KEM
{ PROV_NAMES_ML_KEM_512, "provider=default", ossl_ml_kem_512_keymgmt_functions,
PROV_DESCS_ML_KEM_512 },

View File

@ -335,6 +335,9 @@ extern const OSSL_DISPATCH ossl_ed448_keymgmt_functions[];
extern const OSSL_DISPATCH ossl_sm2_keymgmt_functions[];
# endif
#endif
#ifndef OPENSSL_NO_LMS
extern const OSSL_DISPATCH ossl_lms_keymgmt_functions[];
#endif
extern const OSSL_DISPATCH ossl_ml_dsa_44_keymgmt_functions[];
extern const OSSL_DISPATCH ossl_ml_dsa_65_keymgmt_functions[];
extern const OSSL_DISPATCH ossl_ml_dsa_87_keymgmt_functions[];

View File

@ -404,6 +404,8 @@
#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"
#define PROV_NAMES_ML_DSA_44 "ML-DSA-44:MLDSA44:2.16.840.1.101.3.4.3.17:id-ml-dsa-44"
#define PROV_DESCS_ML_DSA_44 "OpenSSL ML-DSA-44 implementation"
#define PROV_NAMES_ML_DSA_65 "ML-DSA-65:MLDSA65:2.16.840.1.101.3.4.3.18:id-ml-dsa-65"

View File

@ -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
$ML_DSA_GOAL=../../libdefault.a ../../libfips.a
$ML_KEM_GOAL=../../libdefault.a ../../libfips.a
@ -54,6 +55,10 @@ 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
IF[{- !$disabled{'ml-dsa'} -}]

View File

@ -0,0 +1,111 @@
/*
* 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#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
};

View File

@ -221,6 +221,13 @@ IF[{- !$disabled{tests} -}]
INCLUDE[hpke_test]=../include ../apps/include
DEPEND[hpke_test]=../libcrypto 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

38
test/lms.inc Normal file
View File

@ -0,0 +1,38 @@
/*
* 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
* 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)
};

233
test/lms_common.inc Normal file
View File

@ -0,0 +1,233 @@
/*
* 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
* 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,
};

127
test/lms_test.c Normal file
View File

@ -0,0 +1,127 @@
/*
* 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core_names.h>
#include <openssl/evp.h>
#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;
}

View File

@ -0,0 +1,26 @@
#! /usr/bin/env perl
# 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
# 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");