Compare commits
13 commits
master
...
feature/hs
Author | SHA1 | Date | |
---|---|---|---|
|
a167e8efc2 | ||
|
b201fc96c8 | ||
|
8339b3d753 | ||
|
5edaaac5fa | ||
|
ce680a3de0 | ||
|
6d55700499 | ||
|
fc875389ee | ||
|
06937de11d | ||
|
c6f68a4213 | ||
|
2ae5fd035a | ||
|
e9eb032e15 | ||
|
11551fb38c | ||
|
bfffa8bc02 |
46 changed files with 2991 additions and 32 deletions
|
@ -37,6 +37,11 @@ OpenSSL 3.5
|
|||
|
||||
*Viktor Dukhovni*
|
||||
|
||||
* Added LMS signature verification support as per [SP 800-208].
|
||||
This support is present in both the FIPS and default providers.
|
||||
|
||||
*Shane Lontis and Paul Dale*
|
||||
|
||||
* All the BIO_meth_get_*() functions allowing reuse of the internal OpenSSL
|
||||
BIO method implementations were deprecated. The reuse is unsafe due to
|
||||
dependency on the code of the internal methods not changing.
|
||||
|
@ -21202,3 +21207,4 @@ ndif
|
|||
[CVE-2002-0655]: https://www.openssl.org/news/vulnerabilities.html#CVE-2002-0655
|
||||
[CMVP]: https://csrc.nist.gov/projects/cryptographic-module-validation-program
|
||||
[ESV]: https://csrc.nist.gov/Projects/cryptographic-module-validation-program/entropy-validations
|
||||
[SP 800-208]: https://csrc.nist.gov/pubs/sp/800/208/final
|
||||
|
|
|
@ -481,6 +481,7 @@ my @disablables = (
|
|||
"jitter",
|
||||
"ktls",
|
||||
"legacy",
|
||||
"lms",
|
||||
"loadereng",
|
||||
"makedepend",
|
||||
"md2",
|
||||
|
@ -621,7 +622,7 @@ my @disable_cascades = (
|
|||
"des", "dgram", "dh", "dsa",
|
||||
"ec", "engine",
|
||||
"filenames",
|
||||
"idea", "ktls",
|
||||
"idea", "ktls", "lms",
|
||||
"md4", "multiblock", "nextprotoneg",
|
||||
"ocsp", "ocb", "poly1305", "psk",
|
||||
"rc2", "rc4", "rmd160",
|
||||
|
|
|
@ -881,6 +881,12 @@ Don't build the legacy provider.
|
|||
|
||||
Disabling this also disables the legacy algorithms: MD2 (already disabled by default).
|
||||
|
||||
### no-lms
|
||||
|
||||
Disable Leighton-Micali Signatures (LMS) support.
|
||||
Support is currently limited to verification only as per
|
||||
[SP 800-208](https://csrc.nist.gov/pubs/sp/800/208/final).
|
||||
|
||||
### no-makedepend
|
||||
|
||||
Don't generate dependencies.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
9
crypto/lms/build.info
Normal file
9
crypto/lms/build.info
Normal file
|
@ -0,0 +1,9 @@
|
|||
LIBS=../../libcrypto
|
||||
|
||||
$COMMON=lms_params.c lms_pubkey_decode.c lms_key.c lm_ots_params.c \
|
||||
lm_ots_verify.c lms_sig.c lms_sig_decoder.c lms_verify.c
|
||||
|
||||
IF[{- !$disabled{'lms'} -}]
|
||||
SOURCE[../../libcrypto]=$COMMON
|
||||
SOURCE[../../providers/libfips.a]=$COMMON
|
||||
ENDIF
|
66
crypto/lms/lm_ots_params.c
Normal file
66
crypto/lms/lm_ots_params.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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"
|
||||
#include "crypto/lms_sig.h"
|
||||
#include "crypto/lms_util.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;
|
||||
}
|
||||
|
||||
/* See RFC 8554 Section 4.4 Checksum */
|
||||
uint16_t ossl_lm_ots_params_checksum(const LM_OTS_PARAMS *params,
|
||||
const unsigned char *S)
|
||||
{
|
||||
uint16_t sum = 0;
|
||||
uint16_t i;
|
||||
/* Largest size is 8 * 32 / 1 = 256 (which doesnt quite fit into 8 bits) */
|
||||
uint16_t bytes = (8 * params->n / params->w);
|
||||
uint16_t end = (1 << params->w) - 1;
|
||||
|
||||
for (i = 0; i < bytes; ++i)
|
||||
sum += end - coef(S, i, params->w);
|
||||
return (sum << (8 - params->w));
|
||||
}
|
156
crypto/lms/lm_ots_verify.c
Normal file
156
crypto/lms/lm_ots_verify.c
Normal file
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* 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 <openssl/evp.h>
|
||||
#include "crypto/lms_sig.h"
|
||||
#include "crypto/lms_util.h"
|
||||
|
||||
static int lm_ots_compute_pubkey_final(EVP_MD_CTX *ctx, EVP_MD_CTX *ctxIq,
|
||||
const LM_OTS_SIG *sig, unsigned char *Kc);
|
||||
|
||||
/**
|
||||
* @brief OTS Signature verification.
|
||||
*
|
||||
* See RFC 8554 Section 4.6 Signature Verification
|
||||
* Algorithm 4b: Compute a Public Key Candidate |Kc| from a signature, message
|
||||
* and public key parameters.
|
||||
*
|
||||
* @param ctx A temporary working EVP_MD_CTX object.
|
||||
* @param ctxIq A EVP_MD_CTX object that has been initialised with a digest,
|
||||
* that returns a non finalized value of H(I || q)
|
||||
* @param sig An LM_OTS_SIG object that contains C and y
|
||||
* @param pub The public key LM_OTS_PARAMS
|
||||
* @param Id A 16 byte indentifier (I) associated with a LMS tree
|
||||
* @param q The leaf index of the LMS tree.
|
||||
* @param msg A message to verify
|
||||
* @param msglen The size of |msg|
|
||||
* @param Kc The computed public key candidate. It is assumed the size is n.
|
||||
* @returns 1 on success, or 0 otherwise.
|
||||
*/
|
||||
int ossl_lm_ots_compute_pubkey(EVP_MD_CTX *ctx, EVP_MD_CTX *ctxIq,
|
||||
const LM_OTS_SIG *sig, const LM_OTS_PARAMS *pub,
|
||||
const unsigned char *Id, uint32_t q,
|
||||
const unsigned char *msg, size_t msglen,
|
||||
unsigned char *Kc)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char qbuf[LMS_SIZE_q];
|
||||
unsigned char d_mesg[sizeof(uint16_t)];
|
||||
|
||||
if (sig->params != pub)
|
||||
return 0;
|
||||
|
||||
U32STR(qbuf, q);
|
||||
U16STR(d_mesg, OSSL_LMS_D_MESG);
|
||||
|
||||
if (!EVP_DigestUpdate(ctxIq, Id, LMS_SIZE_I)
|
||||
|| !EVP_DigestUpdate(ctxIq, qbuf, sizeof(qbuf))
|
||||
|| !EVP_MD_CTX_copy_ex(ctx, ctxIq)
|
||||
/* Q = H(I || u32str(q) || u16str(D_MESG) || C || msg) */
|
||||
|| !EVP_DigestUpdate(ctx, d_mesg, sizeof(d_mesg))
|
||||
|| !EVP_DigestUpdate(ctx, sig->C, sig->params->n)
|
||||
|| !EVP_DigestUpdate(ctx, msg, msglen)
|
||||
|| !lm_ots_compute_pubkey_final(ctx, ctxIq, sig, Kc))
|
||||
goto err;
|
||||
ret = 1;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief simple function to increment a 16 bit counter by 1.
|
||||
* It assumes checking for overflow is not required.
|
||||
*/
|
||||
static ossl_inline void INC16(unsigned char *tag)
|
||||
{
|
||||
if (++(tag[1]) == 0)
|
||||
++*tag;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief OTS signature verification final phase
|
||||
* See RFC 8554 Section 4.3 Signature Verification
|
||||
* Algorithm 4b - Part 3
|
||||
* Step 3 (Finalizes Q) and 4
|
||||
*
|
||||
* @param ctx A EVP_MD_CTX object that contains a non finalized value of
|
||||
* Q = H(I || u32str(q) || u16str(D_MESG) || C || msg)
|
||||
* This ctx is reused for other calculations.
|
||||
* @param ctxIq A EVP_MD_CTX object that contains a non finalized value of H(I || q).
|
||||
* @param sig An object that containing LM_OTS signature data.
|
||||
* @param Kc The computed public key. It is assumed the size is n.
|
||||
* @returns 1 on success, or 0 otherwise.
|
||||
*/
|
||||
static int lm_ots_compute_pubkey_final(EVP_MD_CTX *ctx, EVP_MD_CTX *ctxIq,
|
||||
const LM_OTS_SIG *sig, unsigned char *Kc)
|
||||
{
|
||||
int ret = 0, i;
|
||||
EVP_MD_CTX *ctxKc = NULL;
|
||||
unsigned char tag[2 + 1], *tag2 = &tag[2];
|
||||
unsigned char Q[LMS_MAX_DIGEST_SIZE + LMS_SIZE_QSUM], *Qsum;
|
||||
unsigned char z[LMS_MAX_DIGEST_SIZE];
|
||||
unsigned char d_pblc[sizeof(uint16_t)];
|
||||
uint16_t sum;
|
||||
const LM_OTS_PARAMS *params = sig->params;
|
||||
int n = params->n;
|
||||
int p = params->p;
|
||||
uint8_t j, w = params->w, end = (1 << w) - 1;
|
||||
int a;
|
||||
unsigned char *y;
|
||||
|
||||
if (!EVP_DigestFinal_ex(ctx, Q, NULL))
|
||||
goto err;
|
||||
|
||||
ctxKc = EVP_MD_CTX_create();
|
||||
if (ctxKc == NULL)
|
||||
goto err;
|
||||
sum = ossl_lm_ots_params_checksum(params, Q);
|
||||
Qsum = Q + n;
|
||||
/* Q || Cksm(Q) */
|
||||
U16STR(Qsum, sum);
|
||||
U16STR(d_pblc, OSSL_LMS_D_PBLC);
|
||||
|
||||
if (!(EVP_MD_CTX_copy_ex(ctxKc, ctxIq))
|
||||
|| !EVP_DigestUpdate(ctxKc, d_pblc, sizeof(d_pblc)))
|
||||
goto err;
|
||||
|
||||
y = sig->y;
|
||||
tag[0] = 0;
|
||||
tag[1] = 0;
|
||||
|
||||
/*
|
||||
* Depending on the lm_ots_type (see lm_ots_params[])
|
||||
* The outer loop |p| ranges from 26...265 iterations and
|
||||
* the inner loop |end| is in the range 0...(2^w)-1
|
||||
*/
|
||||
for (i = 0; i < p; ++i) {
|
||||
a = coef(Q, i, w);
|
||||
memcpy(z, y, n);
|
||||
y += n;
|
||||
for (j = a; j < end; ++j) {
|
||||
*tag2 = (j & 0xFF);
|
||||
if (!(EVP_MD_CTX_copy_ex(ctx, ctxIq))
|
||||
|| !EVP_DigestUpdate(ctx, tag, sizeof(tag))
|
||||
|| !EVP_DigestUpdate(ctx, z, n)
|
||||
|| !EVP_DigestFinal_ex(ctx, z, NULL))
|
||||
goto err;
|
||||
}
|
||||
INC16(tag);
|
||||
if (!EVP_DigestUpdate(ctxKc, z, n))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Kc = H(I || u32str(q) || u16str(D_PBLC) || z[0] || ... || z[p-1]) */
|
||||
if (!EVP_DigestFinal(ctxKc, Kc, NULL))
|
||||
goto err;
|
||||
ret = 1;
|
||||
err:
|
||||
EVP_MD_CTX_free(ctxKc);
|
||||
return ret;
|
||||
}
|
136
crypto/lms/lms_key.c
Normal file
136
crypto/lms/lms_key.c
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* 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 <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) {
|
||||
if (!CRYPTO_NEW_REF(&ret->references, 1)) {
|
||||
OPENSSL_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
ret->libctx = libctx;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy a LMS_KEY object
|
||||
*/
|
||||
void ossl_lms_key_free(LMS_KEY *lmskey)
|
||||
{
|
||||
LMS_PUB_KEY *pub;
|
||||
int i;
|
||||
|
||||
if (lmskey == NULL)
|
||||
return;
|
||||
|
||||
CRYPTO_DOWN_REF(&lmskey->references, &i);
|
||||
REF_PRINT_COUNT("LMS_KEY", i, lmskey);
|
||||
if (i > 0)
|
||||
return;
|
||||
REF_ASSERT_ISNT(i < 0);
|
||||
|
||||
pub = &lmskey->pub;
|
||||
OPENSSL_free(pub->encoded);
|
||||
CRYPTO_FREE_REF(&lmskey->references);
|
||||
OPENSSL_free(lmskey);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Increase the reference count for a LMS_KEY object.
|
||||
* @returns 1 on success or 0 otherwise.
|
||||
*/
|
||||
int ossl_lms_key_up_ref(LMS_KEY *key)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (CRYPTO_UP_REF(&key->references, &i) <= 0)
|
||||
return 0;
|
||||
|
||||
REF_PRINT_COUNT("LMS_KEY", i, key);
|
||||
REF_ASSERT_ISNT(i < 2);
|
||||
return ((i > 1) ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
54
crypto/lms/lms_params.c
Normal file
|
@ -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;
|
||||
}
|
133
crypto/lms/lms_pubkey_decode.c
Normal file
133
crypto/lms/lms_pubkey_decode.c
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* 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 <openssl/core_names.h>
|
||||
#include "crypto/lms.h"
|
||||
#include "crypto/lms_util.h"
|
||||
|
||||
/**
|
||||
* @brief Calculate the size of a public key in XDR format.
|
||||
*
|
||||
* @param data A byte array of XDR data for a LMS public key.
|
||||
* The first 4 bytes are looked at.
|
||||
* @param datalen The size of |data|.
|
||||
* @returns The calculated size, or 0 on error.
|
||||
*/
|
||||
size_t ossl_lms_pubkey_length(const unsigned char *data, size_t datalen)
|
||||
{
|
||||
PACKET pkt;
|
||||
uint32_t lms_type;
|
||||
const LMS_PARAMS *params;
|
||||
|
||||
if (!PACKET_buf_init(&pkt, data, datalen)
|
||||
|| !PACKET_get_4_len(&pkt, &lms_type)
|
||||
|| (params = ossl_lms_params_get(lms_type)) == NULL)
|
||||
return 0;
|
||||
return LMS_SIZE_LMS_TYPE + LMS_SIZE_OTS_TYPE + LMS_SIZE_I + params->n;
|
||||
}
|
||||
|
||||
/*
|
||||
* @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)
|
||||
*/
|
||||
int ossl_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) {
|
||||
OPENSSL_free(pkey->encoded);
|
||||
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;
|
||||
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
|
||||
|| !ossl_lms_pubkey_decode(p->data, p->data_size, lmskey))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
26
crypto/lms/lms_sig.c
Normal file
26
crypto/lms/lms_sig.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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_sig.h"
|
||||
|
||||
/**
|
||||
* @brief Create a new LMS_SIG object
|
||||
*/
|
||||
LMS_SIG *ossl_lms_sig_new(void)
|
||||
{
|
||||
return OPENSSL_zalloc(sizeof(LMS_SIG));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy an existing LMS_SIG object
|
||||
*/
|
||||
void ossl_lms_sig_free(LMS_SIG *sig)
|
||||
{
|
||||
OPENSSL_free(sig);
|
||||
}
|
103
crypto/lms/lms_sig_decoder.c
Normal file
103
crypto/lms/lms_sig_decoder.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* 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_sig.h"
|
||||
#include "crypto/lms_util.h"
|
||||
|
||||
/**
|
||||
* @brief Decode a byte array containing XDR signature data into a LMS_SIG object.
|
||||
*
|
||||
* This is used for LMS Signature Verification.
|
||||
* This function may be called multiple times.
|
||||
* See RFC 8554 Algorithm 6a: Steps 1 and 2.
|
||||
* It uses shallow copies for C, y and path.
|
||||
*
|
||||
* @param pkt Contains the signature data to decode. There may still be data
|
||||
* remaining in pkt after decoding.
|
||||
* @param pub A public key that contains LMS_PARAMS and LM_OTS_PARAMS associated
|
||||
* with the signature.
|
||||
* @returns The created LMS_SIG object is successful, or NULL on failure. A
|
||||
* failure may occur if the passed in LMS public key |pub| is not
|
||||
* compatible with the decoded LMS_SIG object,
|
||||
*/
|
||||
LMS_SIG *ossl_lms_sig_from_pkt(PACKET *pkt, const LMS_KEY *pub)
|
||||
{
|
||||
uint32_t sig_ots_type = 0, sig_lms_type = 0;
|
||||
const LMS_PARAMS *lparams = pub->lms_params;
|
||||
const LM_OTS_PARAMS *pub_ots_params = pub->ots_params;
|
||||
const LM_OTS_PARAMS *sig_params;
|
||||
LMS_SIG *lsig = NULL;
|
||||
|
||||
lsig = ossl_lms_sig_new();
|
||||
if (lsig == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!PACKET_get_4_len(pkt, &lsig->q) /* q = Leaf Index */
|
||||
|| !PACKET_get_4_len(pkt, &sig_ots_type)
|
||||
|| pub_ots_params->lm_ots_type != sig_ots_type)
|
||||
goto err;
|
||||
sig_params = pub_ots_params;
|
||||
lsig->sig.params = sig_params;
|
||||
lsig->params = lparams;
|
||||
|
||||
if (!PACKET_get_bytes_shallow(pkt, &lsig->sig.C, sig_params->n)
|
||||
|| !PACKET_get_bytes_shallow(pkt, &lsig->sig.y,
|
||||
sig_params->p * sig_params->n)
|
||||
|| !PACKET_get_4_len(pkt, &sig_lms_type)
|
||||
|| (lparams->lms_type != sig_lms_type)
|
||||
|| HASH_NOT_MATCHED(lparams, sig_params)
|
||||
|| lsig->q >= (uint32_t)(1 << lparams->h)
|
||||
|| !PACKET_get_bytes_shallow(pkt, &lsig->paths,
|
||||
lparams->h * lparams->n))
|
||||
goto err;
|
||||
return lsig;
|
||||
err:
|
||||
ossl_lms_sig_free(lsig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode a byte array of LMS signature data.
|
||||
*
|
||||
* This function does not duplicate any of the byte data contained within
|
||||
* |sig|. So it is expected that |sig| will exist for the duration of the
|
||||
* returned signature |out|.
|
||||
*
|
||||
* @param out Used to return the LMS_SIG object.
|
||||
* @param pub The root public LMS key
|
||||
* @param sig A input byte array of signature data.
|
||||
* @param siglen The size of sig.
|
||||
* @returns 1 if the signature is successfully decoded,
|
||||
* otherwise it returns 0.
|
||||
*/
|
||||
int ossl_lms_sig_decode(LMS_SIG **out, LMS_KEY *pub,
|
||||
const unsigned char *sig, size_t siglen)
|
||||
{
|
||||
PACKET pkt;
|
||||
LMS_SIG *s = NULL;
|
||||
|
||||
if (pub == NULL)
|
||||
return 0;
|
||||
|
||||
if (!PACKET_buf_init(&pkt, sig, siglen))
|
||||
return 0;
|
||||
|
||||
s = ossl_lms_sig_from_pkt(&pkt, pub);
|
||||
if (s == NULL)
|
||||
return 0;
|
||||
|
||||
/* Fail if there are trailing bytes */
|
||||
if (PACKET_remaining(&pkt) > 0)
|
||||
goto err;
|
||||
*out = s;
|
||||
return 1;
|
||||
err:
|
||||
ossl_lms_sig_free(s);
|
||||
return 0;
|
||||
}
|
168
crypto/lms/lms_verify.c
Normal file
168
crypto/lms/lms_verify.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* 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_sig.h"
|
||||
#include "crypto/lms_util.h"
|
||||
#include "internal/common.h"
|
||||
|
||||
/*
|
||||
* Constants used for obtaining unique inputs for different hashing operations
|
||||
* e.g H(I || q || OSSL_LMS_D_LEAF || ... )
|
||||
*/
|
||||
const uint16_t OSSL_LMS_D_PBLC = 0x8080;
|
||||
const uint16_t OSSL_LMS_D_MESG = 0x8181;
|
||||
const uint16_t OSSL_LMS_D_LEAF = 0x8282;
|
||||
const uint16_t OSSL_LMS_D_INTR = 0x8383;
|
||||
|
||||
/*
|
||||
* @brief Compute the candidate LMS root value Tc
|
||||
*
|
||||
* @param paths An array of bytes representing the hash values associated with
|
||||
* the path through the tree from the leaf associated with the
|
||||
* LM-OTS signature to the root public key node.
|
||||
* @param n The hash output size (The size of each path in |paths|)
|
||||
* @param nodenum The leaf index node number. The root node had a value of 1
|
||||
* Each subsequent level has nodes in the range 2^h...2^(h+1)-1
|
||||
* @param ctx A EVP_MD_CTX object used for calculations
|
||||
* @param ctxI A EVP_MD_CTX object containing an unfinalised H(I)
|
||||
* @param Tc Contains H(I || u32str(node_num) || u16str(D_LEAF) || Kc) on input,
|
||||
* and on output returns the calculated candidate public key.
|
||||
* @returns 1 on success, or 0 otherwise.
|
||||
*/
|
||||
static
|
||||
int lms_sig_compute_tc_from_path(const unsigned char *paths, uint32_t n,
|
||||
uint32_t node_num,
|
||||
EVP_MD_CTX *ctx, EVP_MD_CTX *ctxI,
|
||||
unsigned char *Tc)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char qbuf[4];
|
||||
unsigned char d_intr[sizeof(uint16_t)];
|
||||
const unsigned char *path = paths;
|
||||
|
||||
U16STR(d_intr, OSSL_LMS_D_INTR);
|
||||
|
||||
/*
|
||||
* Calculate the public key Tc using the path
|
||||
* The root hash is the hash of its 2 childrens Hash values.
|
||||
* A child hash for each level is passed in by paths, and we have
|
||||
* a leaf value that can be used with the path to calculate the parent
|
||||
* hash.
|
||||
*/
|
||||
while (node_num > 1) {
|
||||
/* At each level the path contains either the left or right child */
|
||||
int odd = node_num & 1;
|
||||
|
||||
node_num = node_num >> 1; /* get the parent node_num */
|
||||
U32STR(qbuf, node_num);
|
||||
|
||||
/*
|
||||
* Calculate Tc as either
|
||||
* Tc(parent) = H(I || node_q || 0x8383 || paths[i][n] || Tc(right) OR
|
||||
* Tc(parent) = H(I || node_q || 0x8383 || Tc(left) || paths[i][n])
|
||||
*/
|
||||
if (!EVP_MD_CTX_copy_ex(ctx, ctxI)
|
||||
|| !EVP_DigestUpdate(ctx, qbuf, sizeof(qbuf))
|
||||
|| !EVP_DigestUpdate(ctx, d_intr, sizeof(d_intr)))
|
||||
goto err;
|
||||
|
||||
if (odd) {
|
||||
if (!EVP_DigestUpdate(ctx, path, n)
|
||||
|| !EVP_DigestUpdate(ctx, Tc, n))
|
||||
goto err;
|
||||
} else {
|
||||
if (!EVP_DigestUpdate(ctx, Tc, n)
|
||||
|| !EVP_DigestUpdate(ctx, path, n))
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* Tc = parent Hash, which is either the left or right child for the next
|
||||
* level up (node_num determines if it is left or right).
|
||||
*/
|
||||
if (!EVP_DigestFinal_ex(ctx, Tc, NULL))
|
||||
goto err;
|
||||
path += n;
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief LMS signature verification.
|
||||
* See RFC 8554 Section 5.4.2. Algorithm 6: Steps 3 & 4
|
||||
*
|
||||
* @param lms_sig Is a valid decoded LMS_SIG signature object.
|
||||
* @param pub Is a valid LMS public key object.
|
||||
* @param md Contains the fetched digest to be used for Hash operations
|
||||
* @param msg A message to verify
|
||||
* @param msglen The size of |msg|
|
||||
* @returns 1 if the verification succeeded, or 0 otherwise.
|
||||
*/
|
||||
int ossl_lms_sig_verify(const LMS_SIG *lms_sig, const LMS_KEY *pub,
|
||||
const EVP_MD *md,
|
||||
const unsigned char *msg, size_t msglen)
|
||||
{
|
||||
int ret = 0;
|
||||
EVP_MD_CTX *ctx = NULL, *ctxIq = NULL;
|
||||
EVP_MD_CTX *ctxI;
|
||||
unsigned char Kc[LMS_MAX_DIGEST_SIZE];
|
||||
unsigned char Tc[LMS_MAX_DIGEST_SIZE];
|
||||
unsigned char qbuf[4];
|
||||
unsigned char d_leaf[sizeof(uint16_t)];
|
||||
const LMS_PARAMS *lms_params = pub->lms_params;
|
||||
uint32_t n = lms_params->n;
|
||||
uint32_t node_num;
|
||||
|
||||
ctx = EVP_MD_CTX_create();
|
||||
ctxIq = EVP_MD_CTX_create();
|
||||
if (ctx == NULL || ctxIq == NULL)
|
||||
goto err;
|
||||
|
||||
if (!evp_md_ctx_init(ctxIq, md, lms_sig->params))
|
||||
goto err;
|
||||
/*
|
||||
* Algorithm 6a: Step 3.
|
||||
* Calculate a candidate public key |Kc| using the lmots_signature, message,
|
||||
* and the identifiers I, q
|
||||
*/
|
||||
if (!ossl_lm_ots_compute_pubkey(ctx, ctxIq, &lms_sig->sig,
|
||||
pub->ots_params, pub->Id,
|
||||
lms_sig->q, msg, msglen, Kc))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Algorithm 6a: Step 4
|
||||
* Compute the candidate LMS root value Tc
|
||||
*/
|
||||
if (!ossl_assert(lms_sig->q < (uint32_t)(1 << lms_params->h)))
|
||||
return 0;
|
||||
node_num = (1 << lms_params->h) + lms_sig->q;
|
||||
|
||||
U32STR(qbuf, node_num);
|
||||
U16STR(d_leaf, OSSL_LMS_D_LEAF);
|
||||
ctxI = ctxIq;
|
||||
/* Tc = H(I || u32str(node_num) || u16str(D_LEAF) || Kc) */
|
||||
if (!EVP_DigestInit_ex2(ctx, NULL, NULL)
|
||||
|| !EVP_DigestUpdate(ctx, pub->Id, LMS_SIZE_I)
|
||||
|| !EVP_MD_CTX_copy_ex(ctxI, ctx)
|
||||
|| !EVP_DigestUpdate(ctx, qbuf, sizeof(qbuf))
|
||||
|| !EVP_DigestUpdate(ctx, d_leaf, sizeof(d_leaf))
|
||||
|| !EVP_DigestUpdate(ctx, Kc, n)
|
||||
|| !EVP_DigestFinal_ex(ctx, Tc, NULL)
|
||||
|| !lms_sig_compute_tc_from_path(lms_sig->paths, n, node_num,
|
||||
ctx, ctxI, Tc))
|
||||
goto err;
|
||||
/* Algorithm 6: Step 4 */
|
||||
ret = (memcmp(pub->pub.K, Tc, n) == 0);
|
||||
err:
|
||||
EVP_MD_CTX_free(ctxIq);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
|
@ -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
|
||||
|
@ -4805,6 +4809,10 @@ DEPEND[html/man7/EVP_SIGNATURE-HMAC.html]=man7/EVP_SIGNATURE-HMAC.pod
|
|||
GENERATE[html/man7/EVP_SIGNATURE-HMAC.html]=man7/EVP_SIGNATURE-HMAC.pod
|
||||
DEPEND[man/man7/EVP_SIGNATURE-HMAC.7]=man7/EVP_SIGNATURE-HMAC.pod
|
||||
GENERATE[man/man7/EVP_SIGNATURE-HMAC.7]=man7/EVP_SIGNATURE-HMAC.pod
|
||||
DEPEND[html/man7/EVP_SIGNATURE-LMS.html]=man7/EVP_SIGNATURE-LMS.pod
|
||||
GENERATE[html/man7/EVP_SIGNATURE-LMS.html]=man7/EVP_SIGNATURE-LMS.pod
|
||||
DEPEND[man/man7/EVP_SIGNATURE-LMS.7]=man7/EVP_SIGNATURE-LMS.pod
|
||||
GENERATE[man/man7/EVP_SIGNATURE-LMS.7]=man7/EVP_SIGNATURE-LMS.pod
|
||||
DEPEND[html/man7/EVP_SIGNATURE-RSA.html]=man7/EVP_SIGNATURE-RSA.pod
|
||||
GENERATE[html/man7/EVP_SIGNATURE-RSA.html]=man7/EVP_SIGNATURE-RSA.pod
|
||||
DEPEND[man/man7/EVP_SIGNATURE-RSA.7]=man7/EVP_SIGNATURE-RSA.pod
|
||||
|
@ -5140,6 +5148,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 \
|
||||
|
@ -5155,6 +5164,7 @@ html/man7/EVP_SIGNATURE-DSA.html \
|
|||
html/man7/EVP_SIGNATURE-ECDSA.html \
|
||||
html/man7/EVP_SIGNATURE-ED25519.html \
|
||||
html/man7/EVP_SIGNATURE-HMAC.html \
|
||||
html/man7/EVP_SIGNATURE-LMS.html \
|
||||
html/man7/EVP_SIGNATURE-RSA.html \
|
||||
html/man7/OSSL_PROVIDER-FIPS.html \
|
||||
html/man7/OSSL_PROVIDER-base.html \
|
||||
|
@ -5287,6 +5297,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 \
|
||||
|
@ -5302,6 +5313,7 @@ man/man7/EVP_SIGNATURE-DSA.7 \
|
|||
man/man7/EVP_SIGNATURE-ECDSA.7 \
|
||||
man/man7/EVP_SIGNATURE-ED25519.7 \
|
||||
man/man7/EVP_SIGNATURE-HMAC.7 \
|
||||
man/man7/EVP_SIGNATURE-LMS.7 \
|
||||
man/man7/EVP_SIGNATURE-RSA.7 \
|
||||
man/man7/OSSL_PROVIDER-FIPS.7 \
|
||||
man/man7/OSSL_PROVIDER-base.7 \
|
||||
|
|
|
@ -57,6 +57,7 @@ L<EVP_PKEY-DH(7)/DH parameters>
|
|||
L<EVP_PKEY-DH(7)/DH key generation parameters>
|
||||
L<EVP_PKEY-EC(7)/Common EC parameters>
|
||||
L<EVP_PKEY-X25519(7)/Common X25519, X448, ED25519 and ED448 parameters>
|
||||
L<EVP_PKEY-LMS(7)/Common LMS parameters>
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
|
|
|
@ -261,7 +261,7 @@ L<EVP_PKEY_CTX_new(3)>, L<provider(7)>, L<EVP_PKEY_gettable_params(3)>,
|
|||
L<OSSL_PARAM(3)>, L<EVP_PKEY_todata(3)>,
|
||||
L<EVP_PKEY-RSA(7)>, L<EVP_PKEY-DSA(7)>, L<EVP_PKEY-DH(7)>, L<EVP_PKEY-EC(7)>,
|
||||
L<EVP_PKEY-ED448(7)>, L<EVP_PKEY-X25519(7)>, L<EVP_PKEY-X448(7)>,
|
||||
L<EVP_PKEY-ED25519(7)>
|
||||
L<EVP_PKEY-ED25519(7)>, L<EVP_PKEY-LMS(7)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ L<OSSL_PARAM(3)>, L<openssl-core.h(7)>,
|
|||
L<EVP_PKEY_fromdata(3)>,
|
||||
L<EVP_PKEY-RSA(7)>, L<EVP_PKEY-DSA(7)>, L<EVP_PKEY-DH(7)>, L<EVP_PKEY-EC(7)>,
|
||||
L<EVP_PKEY-ED448(7)>, L<EVP_PKEY-X25519(7)>, L<EVP_PKEY-X448(7)>,
|
||||
L<EVP_PKEY-ED25519(7)>
|
||||
L<EVP_PKEY-ED25519(7)>, L<EVP_PKEY-LMS(7)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
|
|
99
doc/man7/EVP_PKEY-LMS.pod
Normal file
99
doc/man7/EVP_PKEY-LMS.pod
Normal file
|
@ -0,0 +1,99 @@
|
|||
=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 and FIPS providers.
|
||||
The OpenSSL providers only support LMS signature verification, as this is a
|
||||
[SP 800-208](https://csrc.nist.gov/pubs/sp/800/208/final) requirement for
|
||||
software modules.
|
||||
|
||||
=head2 Common LMS parameters
|
||||
|
||||
LMS public keys are encoded in XDR format (i.e. not ASN1 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 SP800-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(libctx, "LMS", propq);
|
||||
|
||||
An B<LMS> public key can be loaded simply like this:
|
||||
|
||||
EVP_PKEY *pkey = NULL;
|
||||
OSSL_DECODER_CTX *dctx = NULL;
|
||||
int selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
|
||||
|
||||
dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "XDR", NULL,
|
||||
"LMS", selection, libctx, propq);
|
||||
ret = OSSL_DECODER_from_bio(dctx, bio);
|
||||
OSSL_DECODER_CTX_free(dctx);
|
||||
|
||||
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<EVP_SIGNATURE-LMS(7)>,
|
||||
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
|
60
doc/man7/EVP_SIGNATURE-LMS.pod
Normal file
60
doc/man7/EVP_SIGNATURE-LMS.pod
Normal file
|
@ -0,0 +1,60 @@
|
|||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
EVP_SIGNATURE-LMS
|
||||
- The EVP_PKEY Leighton-Micali Signature (LMS) implementation
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<LMS> EVP_PKEY implementation supports Leighton-Micali Signatures (LMS)
|
||||
described in [RFC 8554](https://datatracker.ietf.org/doc/html/rfc8854)
|
||||
and [SP 800-208](https://csrc.nist.gov/pubs/sp/800/208/final).
|
||||
|
||||
The OpenSSL providers only support LMS signature verification, as this is a
|
||||
SP 800-208 requirement for software modules.
|
||||
|
||||
EVP_PKEY_verify_message_init() and EVP_PKEY_verify() are the only supported
|
||||
functions used for LMS signatures. Streaming is not currently supported,
|
||||
and since the signature data contains data related to the digest used, functions
|
||||
that specify the digest name are not necessary.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
Error checking has been omitted from the following examples
|
||||
|
||||
=head2 LMS signature verification
|
||||
|
||||
/* See L<EVP_PKEY-LMS(7)/EXAMPLES for an example of loading a LMS |pub| key */
|
||||
ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pub, propq);
|
||||
sig = EVP_SIGNATURE_fetch(libctx, "LMS", propq);
|
||||
EVP_PKEY_verify_message_init(ctx, sig, NULL);
|
||||
/*
|
||||
* EVP_PKEY_verify_message_update() and EVP_PKEY_verify_message_final()
|
||||
* are not supported
|
||||
*/
|
||||
ret = EVP_PKEY_verify(ctx, sigdata, sigdata_len, msg, msglen);
|
||||
/*
|
||||
* ret == 1 indicates success, 0 verify failure and < 0 for some
|
||||
* other error.
|
||||
*/
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<EVP_PKEY-LMS(7)>,
|
||||
L<provider-signature(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
|
|
@ -70,9 +70,11 @@ The OpenSSL FIPS provider supports these operations and algorithms:
|
|||
|
||||
=item SHA3, see L<EVP_MD-SHA3(7)>
|
||||
|
||||
=item SHAKE, see L<EVP_MD-SHAKE(7)>
|
||||
|
||||
=item KECCAK-KMAC, see L<EVP_MD-KECCAK-KMAC(7)>
|
||||
|
||||
=item SHAKE, see L<EVP_MD-SHAKE(7)>
|
||||
KECCAK-KMAC is only used internally as a sub algorithm of KMAC.
|
||||
|
||||
=back
|
||||
|
||||
|
@ -168,6 +170,8 @@ for signature generation, but may be used for verification for legacy use cases.
|
|||
|
||||
=item CMAC, see L<EVP_SIGNATURE-CMAC(7)>
|
||||
|
||||
=item LMS, see L<EVP_SIGNATURE-LMS(7)>
|
||||
|
||||
=back
|
||||
|
||||
=head2 Asymmetric Cipher
|
||||
|
@ -381,6 +385,8 @@ Digest tests used with the "KAT_Digest" type.
|
|||
|
||||
=item "EDDSA" (B<OSSL_SELF_TEST_DESC_SIGN_EDDSA>)
|
||||
|
||||
=item "LMS" (B<OSSL_SELF_TEST_DESC_SIGN_LMS>)
|
||||
|
||||
Signature tests used with the "KAT_Signature" type.
|
||||
|
||||
=item "ECDH" (B<OSSL_SELF_TEST_DESC_KA_ECDH>)
|
||||
|
|
|
@ -199,6 +199,8 @@ The OpenSSL default provider supports these operations and algorithms:
|
|||
|
||||
=item CMAC, see L<EVP_SIGNATURE-CMAC(7)>
|
||||
|
||||
=item LMS, see L<EVP_SIGNATURE-LMS(7)>
|
||||
|
||||
=back
|
||||
|
||||
=head2 Asymmetric Cipher
|
||||
|
|
|
@ -502,7 +502,8 @@ L<EVP_PKEY_get_security_bits(3)>,
|
|||
L<provider(7)>,
|
||||
L<EVP_PKEY-X25519(7)>, L<EVP_PKEY-X448(7)>, L<EVP_PKEY-ED25519(7)>,
|
||||
L<EVP_PKEY-ED448(7)>, L<EVP_PKEY-EC(7)>, L<EVP_PKEY-RSA(7)>,
|
||||
L<EVP_PKEY-DSA(7)>, L<EVP_PKEY-DH(7)>
|
||||
L<EVP_PKEY-DSA(7)>, L<EVP_PKEY-DH(7)>,
|
||||
L<EVP_PKEY-LMS(7)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
|
|
157
include/crypto/lms.h
Normal file
157
include/crypto/lms.h
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* 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 <openssl/params.h>
|
||||
# include "internal/refcount.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
|
||||
|
||||
/* Constants used for verifying */
|
||||
# define LMS_SIZE_q 4
|
||||
|
||||
/* XDR sizes when encoding and decoding */
|
||||
# define LMS_SIZE_I 16
|
||||
# define LMS_SIZE_LMS_TYPE 4
|
||||
# define LMS_SIZE_OTS_TYPE 4
|
||||
# define LMS_MAX_DIGEST_SIZE 32
|
||||
# define LMS_MAX_PUBKEY \
|
||||
(LMS_SIZE_LMS_TYPE + LMS_SIZE_OTS_TYPE + LMS_SIZE_I + LMS_MAX_DIGEST_SIZE)
|
||||
|
||||
/*
|
||||
* 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;
|
||||
} 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;
|
||||
CRYPTO_REF_COUNT references;
|
||||
};
|
||||
|
||||
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);
|
||||
int ossl_lms_key_up_ref(LMS_KEY *key);
|
||||
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);
|
||||
int ossl_lms_pubkey_decode(const unsigned char *pub, size_t publen,
|
||||
LMS_KEY *lmskey);
|
||||
size_t ossl_lms_pubkey_length(const unsigned char *data, size_t datalen);
|
||||
|
||||
# endif /* OPENSSL_NO_LMS */
|
||||
#endif /* OSSL_CRYPTO_LMS_H */
|
75
include/crypto/lms_sig.h
Normal file
75
include/crypto/lms_sig.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* Refer to RFC 8554 Sections 5.4 & 4.5 for information related to
|
||||
* LMS Signatures & LM_OTS Signature Generation respectively.
|
||||
*/
|
||||
|
||||
#ifndef OSSL_CRYPTO_LMS_SIG_H
|
||||
# define OSSL_CRYPTO_LMS_SIG_H
|
||||
# pragma once
|
||||
# ifndef OPENSSL_NO_LMS
|
||||
# include "lms.h"
|
||||
# include "internal/packet.h"
|
||||
|
||||
/* The values defined for 8 byte TAGS */
|
||||
extern const uint16_t OSSL_LMS_D_PBLC; /* 8080 */
|
||||
extern const uint16_t OSSL_LMS_D_MESG; /* 8181 */
|
||||
extern const uint16_t OSSL_LMS_D_LEAF; /* 8282 */
|
||||
extern const uint16_t OSSL_LMS_D_INTR; /* 8383 */
|
||||
|
||||
/* Used by OTS signature when calculating Q || Cksm(Q) */
|
||||
# define LMS_SIZE_CHECKSUM 2
|
||||
# define LMS_SIZE_QSUM 2
|
||||
|
||||
/*
|
||||
* An object for storing a One-Time Signature
|
||||
* See RFC 8554 Section 4.5
|
||||
*/
|
||||
typedef struct lm_ots_sig_st {
|
||||
const LM_OTS_PARAMS *params;
|
||||
/* For verify operations the following pointers are not allocated */
|
||||
unsigned char *C; /* A salt value of size n */
|
||||
unsigned char *y; /* The trailing part of a signature of size p * n */
|
||||
} LM_OTS_SIG;
|
||||
|
||||
/*
|
||||
* An object for storing a LMS signature
|
||||
* See RFC 8554 Section 5.4
|
||||
*/
|
||||
typedef struct lms_signature_st {
|
||||
uint32_t q;
|
||||
LM_OTS_SIG sig;
|
||||
const LMS_PARAMS *params; /* contains the LMS type */
|
||||
unsigned char *paths; /* size is h * m */
|
||||
} LMS_SIG;
|
||||
|
||||
LMS_SIG *ossl_lms_sig_new(void);
|
||||
void ossl_lms_sig_free(LMS_SIG *sig);
|
||||
LMS_SIG *ossl_lms_sig_from_pkt(PACKET *pkt, const LMS_KEY *pub);
|
||||
int ossl_lms_sig_decode(LMS_SIG **out, LMS_KEY *pub,
|
||||
const unsigned char *sig, size_t siglen);
|
||||
int ossl_lms_sig_verify(const LMS_SIG *lms_sig, const LMS_KEY *pub,
|
||||
const EVP_MD *md,
|
||||
const unsigned char *msg, size_t msglen);
|
||||
|
||||
int ossl_lm_ots_compute_pubkey(EVP_MD_CTX *ctx, EVP_MD_CTX *ctxIq,
|
||||
const LM_OTS_SIG *sig, const LM_OTS_PARAMS *pub,
|
||||
const unsigned char *Id, uint32_t q,
|
||||
const unsigned char *msg, size_t msglen,
|
||||
unsigned char *Kc);
|
||||
uint16_t ossl_lm_ots_params_checksum(const LM_OTS_PARAMS *params,
|
||||
const unsigned char *S);
|
||||
|
||||
# endif /* OPENSSL_NO_LMS */
|
||||
#endif /* OSSL_CRYPTO_LMS_SIG_H */
|
108
include/crypto/lms_util.h
Normal file
108
include/crypto/lms_util.h
Normal file
|
@ -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
|
||||
*/
|
||||
|
||||
/* @brief Internal LMS internal helper functions */
|
||||
|
||||
#include "internal/packet.h"
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/evp.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)
|
||||
|
||||
/* Convert a 32 bit value |in| to 4 bytes |out| */
|
||||
#define U32STR(out, in) \
|
||||
(out)[0] = (unsigned char)(((in) >> 24) & 0xff); \
|
||||
(out)[1] = (unsigned char)(((in) >> 16) & 0xff); \
|
||||
(out)[2] = (unsigned char)(((in) >> 8) & 0xff); \
|
||||
(out)[3] = (unsigned char)((in) & 0xff)
|
||||
|
||||
/* Convert a 16 bit value |in| to 2 bytes |out| */
|
||||
#define U16STR(out, in) \
|
||||
(out)[0] = (unsigned char)(((in) >> 8) & 0xff); \
|
||||
(out)[1] = (unsigned char)((in) & 0xff)
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
||||
/*
|
||||
* See RFC 8554 Section 3.1.3: Strings of w-bit Elements
|
||||
* w: Is one of {1,2,4,8}
|
||||
*/
|
||||
static ossl_unused ossl_inline
|
||||
uint8_t coef(const unsigned char *S, uint16_t i, uint8_t w)
|
||||
{
|
||||
uint8_t bitmask = (1 << w) - 1;
|
||||
uint8_t shift = 8 - (w * (i % (8 / w)) + w);
|
||||
int id = (i * w) / 8;
|
||||
|
||||
return (S[id] >> shift) & bitmask;
|
||||
}
|
||||
|
||||
static ossl_unused ossl_inline
|
||||
int evp_md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *md,
|
||||
const LMS_PARAMS *lms_params)
|
||||
{
|
||||
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
||||
OSSL_PARAM *p = NULL;
|
||||
|
||||
/* The OpenSSL SHAKE implementation requires the xoflen to be set */
|
||||
if (strncmp(lms_params->digestname, "SHAKE", 5) == 0) {
|
||||
params[0] = OSSL_PARAM_construct_uint32(OSSL_DIGEST_PARAM_XOFLEN,
|
||||
(uint32_t *)&lms_params->n);
|
||||
p = params;
|
||||
}
|
||||
return EVP_DigestInit_ex2(ctx, md, p);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -61,6 +61,7 @@ extern "C" {
|
|||
# define OSSL_SELF_TEST_DESC_SIGN_RSA "RSA"
|
||||
# define OSSL_SELF_TEST_DESC_SIGN_ECDSA "ECDSA"
|
||||
# define OSSL_SELF_TEST_DESC_SIGN_EDDSA "EDDSA"
|
||||
# define OSSL_SELF_TEST_DESC_SIGN_LMS "LMS"
|
||||
# define OSSL_SELF_TEST_DESC_DRBG_CTR "CTR"
|
||||
# define OSSL_SELF_TEST_DESC_DRBG_HASH "HASH"
|
||||
# define OSSL_SELF_TEST_DESC_DRBG_HMAC "HMAC"
|
||||
|
|
|
@ -95,3 +95,7 @@ DECODER("DER", pem, der, yes),
|
|||
* form to the next decoder.
|
||||
*/
|
||||
DECODER_w_structure("DER", der, EncryptedPrivateKeyInfo, der, yes),
|
||||
|
||||
#ifndef OPENSSL_NO_LMS
|
||||
DECODER("LMS", xdr, lms, yes),
|
||||
#endif
|
||||
|
|
|
@ -456,6 +456,9 @@ static const OSSL_ALGORITHM deflt_signature[] = {
|
|||
#endif
|
||||
#ifndef OPENSSL_NO_CMAC
|
||||
{ PROV_NAMES_CMAC, "provider=default", ossl_mac_legacy_cmac_signature_functions },
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_LMS
|
||||
{ PROV_NAMES_LMS, "provider=default", ossl_lms_signature_functions },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
@ -530,6 +533,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 }
|
||||
};
|
||||
|
|
|
@ -253,27 +253,33 @@ static int fips_self_test(void *provctx)
|
|||
* NIST uses, or that are used for ASN.1 OBJECT IDENTIFIERs, or names
|
||||
* we have used historically.
|
||||
*/
|
||||
|
||||
#define FIPS_DIGESTS_COMMON() \
|
||||
{ PROV_NAMES_SHA1, FIPS_DEFAULT_PROPERTIES, ossl_sha1_functions }, \
|
||||
{ PROV_NAMES_SHA2_224, FIPS_DEFAULT_PROPERTIES, ossl_sha224_functions }, \
|
||||
{ PROV_NAMES_SHA2_256, FIPS_DEFAULT_PROPERTIES, ossl_sha256_functions }, \
|
||||
{ PROV_NAMES_SHA2_384, FIPS_DEFAULT_PROPERTIES, ossl_sha384_functions }, \
|
||||
{ PROV_NAMES_SHA2_512, FIPS_DEFAULT_PROPERTIES, ossl_sha512_functions }, \
|
||||
{ PROV_NAMES_SHA2_512_224, FIPS_DEFAULT_PROPERTIES, \
|
||||
ossl_sha512_224_functions }, \
|
||||
{ PROV_NAMES_SHA2_512_256, FIPS_DEFAULT_PROPERTIES, \
|
||||
ossl_sha512_256_functions }, \
|
||||
{ PROV_NAMES_SHA3_224, FIPS_DEFAULT_PROPERTIES, ossl_sha3_224_functions }, \
|
||||
{ PROV_NAMES_SHA3_256, FIPS_DEFAULT_PROPERTIES, ossl_sha3_256_functions }, \
|
||||
{ PROV_NAMES_SHA3_384, FIPS_DEFAULT_PROPERTIES, ossl_sha3_384_functions }, \
|
||||
{ PROV_NAMES_SHA3_512, FIPS_DEFAULT_PROPERTIES, ossl_sha3_512_functions }, \
|
||||
{ PROV_NAMES_SHAKE_128, FIPS_DEFAULT_PROPERTIES, ossl_shake_128_functions }, \
|
||||
{ PROV_NAMES_SHAKE_256, FIPS_DEFAULT_PROPERTIES, ossl_shake_256_functions }
|
||||
|
||||
static const OSSL_ALGORITHM fips_digests[] = {
|
||||
/* Our primary name:NiST name[:our older names] */
|
||||
{ PROV_NAMES_SHA1, FIPS_DEFAULT_PROPERTIES, ossl_sha1_functions },
|
||||
{ PROV_NAMES_SHA2_224, FIPS_DEFAULT_PROPERTIES, ossl_sha224_functions },
|
||||
{ PROV_NAMES_SHA2_256, FIPS_DEFAULT_PROPERTIES, ossl_sha256_functions },
|
||||
{ PROV_NAMES_SHA2_384, FIPS_DEFAULT_PROPERTIES, ossl_sha384_functions },
|
||||
{ PROV_NAMES_SHA2_512, FIPS_DEFAULT_PROPERTIES, ossl_sha512_functions },
|
||||
{ PROV_NAMES_SHA2_512_224, FIPS_DEFAULT_PROPERTIES,
|
||||
ossl_sha512_224_functions },
|
||||
{ PROV_NAMES_SHA2_512_256, FIPS_DEFAULT_PROPERTIES,
|
||||
ossl_sha512_256_functions },
|
||||
|
||||
/* We agree with NIST here, so one name only */
|
||||
{ PROV_NAMES_SHA3_224, FIPS_DEFAULT_PROPERTIES, ossl_sha3_224_functions },
|
||||
{ PROV_NAMES_SHA3_256, FIPS_DEFAULT_PROPERTIES, ossl_sha3_256_functions },
|
||||
{ PROV_NAMES_SHA3_384, FIPS_DEFAULT_PROPERTIES, ossl_sha3_384_functions },
|
||||
{ PROV_NAMES_SHA3_512, FIPS_DEFAULT_PROPERTIES, ossl_sha3_512_functions },
|
||||
|
||||
{ PROV_NAMES_SHAKE_128, FIPS_DEFAULT_PROPERTIES, ossl_shake_128_functions },
|
||||
{ PROV_NAMES_SHAKE_256, FIPS_DEFAULT_PROPERTIES, ossl_shake_256_functions },
|
||||
|
||||
FIPS_DIGESTS_COMMON(),
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
static const OSSL_ALGORITHM fips_digests_internal[] = {
|
||||
FIPS_DIGESTS_COMMON(),
|
||||
/* Used by LMS/HSS */
|
||||
{ PROV_NAMES_SHA2_256_192, FIPS_DEFAULT_PROPERTIES,
|
||||
ossl_sha256_192_functions },
|
||||
/*
|
||||
* KECCAK-KMAC-128 and KECCAK-KMAC-256 as hashes are mostly useful for
|
||||
* KMAC128 and KMAC256.
|
||||
|
@ -479,6 +485,9 @@ static const OSSL_ALGORITHM fips_signature[] = {
|
|||
#ifndef OPENSSL_NO_CMAC
|
||||
{ PROV_NAMES_CMAC, FIPS_DEFAULT_PROPERTIES,
|
||||
ossl_mac_legacy_cmac_signature_functions },
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_LMS
|
||||
{ PROV_NAMES_LMS, FIPS_DEFAULT_PROPERTIES, ossl_lms_signature_functions },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
@ -531,6 +540,10 @@ static const OSSL_ALGORITHM fips_keymgmt[] = {
|
|||
#ifndef OPENSSL_NO_CMAC
|
||||
{ PROV_NAMES_CMAC, FIPS_DEFAULT_PROPERTIES,
|
||||
ossl_cmac_legacy_keymgmt_functions, PROV_DESCS_CMAC_SIGN },
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_LMS
|
||||
{ PROV_NAMES_LMS, FIPS_DEFAULT_PROPERTIES, ossl_lms_keymgmt_functions,
|
||||
PROV_DESCS_LMS },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
@ -571,11 +584,14 @@ static const OSSL_ALGORITHM *fips_query(void *provctx, int operation_id,
|
|||
static const OSSL_ALGORITHM *fips_query_internal(void *provctx, int operation_id,
|
||||
int *no_cache)
|
||||
{
|
||||
if (operation_id == OSSL_OP_MAC) {
|
||||
int is_digest_op = (operation_id == OSSL_OP_DIGEST);
|
||||
|
||||
if (is_digest_op
|
||||
|| operation_id == OSSL_OP_MAC) {
|
||||
*no_cache = 0;
|
||||
if (!ossl_prov_is_running())
|
||||
return NULL;
|
||||
return fips_macs_internal;
|
||||
return is_digest_op ? fips_digests_internal : fips_macs_internal;
|
||||
}
|
||||
return fips_query(provctx, operation_id, no_cache);
|
||||
}
|
||||
|
|
|
@ -307,6 +307,148 @@ static const ST_KAT_CIPHER st_kat_cipher_tests[] = {
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifndef OPENSSL_NO_LMS
|
||||
typedef struct st_kat_lms_s {
|
||||
const unsigned char *pub;
|
||||
size_t publen;
|
||||
const unsigned char *msg;
|
||||
size_t msglen;
|
||||
const unsigned char *sig;
|
||||
size_t siglen;
|
||||
} ST_KAT_LMS;
|
||||
|
||||
/*
|
||||
* Test vector 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, 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_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, 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 ST_KAT_LMS st_kat_lms_test = {
|
||||
ITM(sha256_192_pub),
|
||||
ITM(sha256_192_msg),
|
||||
ITM(sha256_192_sig)
|
||||
};
|
||||
#endif /* OPENSSL_NO_LMS */
|
||||
|
||||
static const char hkdf_digest[] = "SHA256";
|
||||
/*
|
||||
* Input parameters and expected result are from RFC 5869 test case 1, which is
|
||||
|
|
|
@ -446,6 +446,52 @@ err:
|
|||
}
|
||||
#endif /* !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC) */
|
||||
|
||||
#ifndef OPENSSL_NO_LMS
|
||||
static int self_test_LMS(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
|
||||
{
|
||||
int ret = 0;
|
||||
OSSL_PARAM pm[2];
|
||||
const ST_KAT_LMS *t = &st_kat_lms_test;
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EVP_SIGNATURE *sig = NULL;
|
||||
|
||||
OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_SIGNATURE,
|
||||
OSSL_SELF_TEST_DESC_SIGN_LMS);
|
||||
|
||||
pm[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
|
||||
(unsigned char *)t->pub,
|
||||
t->publen);
|
||||
pm[1] = OSSL_PARAM_construct_end();
|
||||
|
||||
ctx = EVP_PKEY_CTX_new_from_name(libctx, "LMS", "");
|
||||
if (ctx == NULL
|
||||
|| EVP_PKEY_fromdata_init(ctx) <= 0
|
||||
|| EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, pm) <= 0)
|
||||
goto err;
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, "");
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
|
||||
sig = EVP_SIGNATURE_fetch(libctx, "LMS", NULL);
|
||||
if (sig == NULL
|
||||
|| EVP_PKEY_verify_message_init(ctx, sig, NULL) <= 0
|
||||
|| EVP_PKEY_verify(ctx, t->sig, t->siglen,
|
||||
t->msg, t->msglen) <= 0)
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_SIGNATURE_free(sig);
|
||||
|
||||
OSSL_SELF_TEST_onend(st, ret);
|
||||
return ret;
|
||||
}
|
||||
#endif /* OPENSSL_NO_LMS */
|
||||
|
||||
static int self_test_digest_sign(const ST_KAT_SIGN *t,
|
||||
OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
|
||||
{
|
||||
|
@ -799,6 +845,19 @@ int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
|
|||
ret = 0;
|
||||
if (!self_test_ciphers(st, libctx))
|
||||
ret = 0;
|
||||
#ifndef OPENSSL_NO_LMS
|
||||
/*
|
||||
* FIPS 140-3 IG 10.3.A Note 5 mandates a CAST for LMS.
|
||||
*
|
||||
* It permits this to be omitted if HSS is also implemented and has
|
||||
* the relevant self tests. One HSS is implemented, this test can be
|
||||
* removed. This IG permits the digest's CAST to be subsumed into this
|
||||
* test, however, because this will be removed, the underlying digest
|
||||
* test has been retained elsewhere lest it is accidentally omitted.
|
||||
*/
|
||||
if (!self_test_LMS(st, libctx))
|
||||
ret = 0;
|
||||
#endif /* OPENSSL_NO_LMS */
|
||||
if (!self_test_signatures(st, libctx))
|
||||
ret = 0;
|
||||
if (!self_test_kdfs(st, libctx))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2019-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
|
||||
|
@ -71,12 +71,10 @@ IMPLEMENT_digest_functions(sha224, SHA256_CTX,
|
|||
IMPLEMENT_digest_functions(sha256, SHA256_CTX,
|
||||
SHA256_CBLOCK, SHA256_DIGEST_LENGTH, SHA2_FLAGS,
|
||||
SHA256_Init, SHA256_Update, SHA256_Final)
|
||||
#ifndef FIPS_MODULE
|
||||
/* ossl_sha256_192_functions */
|
||||
IMPLEMENT_digest_functions(sha256_192, SHA256_CTX,
|
||||
SHA256_CBLOCK, SHA256_192_DIGEST_LENGTH, SHA2_FLAGS,
|
||||
ossl_sha256_192_init, SHA256_Update, SHA256_Final)
|
||||
#endif
|
||||
/* ossl_sha384_functions */
|
||||
IMPLEMENT_digest_functions(sha384, SHA512_CTX,
|
||||
SHA512_CBLOCK, SHA384_DIGEST_LENGTH, SHA2_FLAGS,
|
||||
|
|
|
@ -18,3 +18,7 @@ IF[{- !$disabled{ec} -}]
|
|||
SOURCE[$ENCODER_GOAL]=encode_key2blob.c
|
||||
ENDIF
|
||||
DEPEND[encode_key2any.o]=../../common/include/prov/der_rsa.h
|
||||
|
||||
IF[{- !$disabled{lms} -}]
|
||||
SOURCE[$DECODER_GOAL]=decode_lmsxdr2key.c
|
||||
ENDIF
|
||||
|
|
162
providers/implementations/encode_decode/decode_lmsxdr2key.c
Normal file
162
providers/implementations/encode_decode/decode_lmsxdr2key.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* 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 <openssl/core_object.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/params.h>
|
||||
#include "endecoder_local.h"
|
||||
#include "crypto/lms.h"
|
||||
#include "prov/bio.h"
|
||||
#include "prov/implementations.h"
|
||||
|
||||
static OSSL_FUNC_decoder_newctx_fn lmsxdr2key_newctx;
|
||||
static OSSL_FUNC_decoder_freectx_fn lmsxdr2key_freectx;
|
||||
static OSSL_FUNC_decoder_decode_fn lmsxdr2key_decode;
|
||||
static OSSL_FUNC_decoder_export_object_fn lmsxdr2key_export_object;
|
||||
|
||||
/* Context used for xdr to key decoding. */
|
||||
struct lmsxdr2key_ctx_st {
|
||||
PROV_CTX *provctx;
|
||||
int selection; /* The selection that is passed to lmsxdr2key_decode() */
|
||||
};
|
||||
|
||||
static void *lmsxdr2key_newctx(void *provctx)
|
||||
{
|
||||
struct lmsxdr2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx != NULL)
|
||||
ctx->provctx = provctx;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void lmsxdr2key_freectx(void *vctx)
|
||||
{
|
||||
struct lmsxdr2key_ctx_st *ctx = vctx;
|
||||
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
static int lmsxdr2key_does_selection(void *provctx, int selection)
|
||||
{
|
||||
if (selection == 0)
|
||||
return 1;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lmsxdr2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
|
||||
OSSL_CALLBACK *data_cb, void *data_cbarg,
|
||||
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
|
||||
{
|
||||
struct lmsxdr2key_ctx_st *ctx = vctx;
|
||||
LMS_KEY *key = NULL;
|
||||
unsigned char buf[LMS_MAX_PUBKEY];
|
||||
size_t length;
|
||||
int ok = 0;
|
||||
BIO *in;
|
||||
|
||||
in = ossl_bio_new_from_core_bio(ctx->provctx, cin);
|
||||
if (in == NULL)
|
||||
return 0;
|
||||
|
||||
ERR_set_mark();
|
||||
ctx->selection = selection;
|
||||
/* Read the header to determine the size */
|
||||
if (BIO_read(in, buf, 4) != 4)
|
||||
goto next;
|
||||
|
||||
length = ossl_lms_pubkey_length(buf, 4);
|
||||
if (length == 0)
|
||||
goto next;
|
||||
if (BIO_read(in, buf + 4, length - 4) != (int)(length - 4))
|
||||
goto next;
|
||||
if (selection == 0 || (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
|
||||
key = ossl_lms_key_new(PROV_LIBCTX_OF(ctx->provctx));
|
||||
if (key == NULL || !ossl_lms_pubkey_decode(buf, length, key)) {
|
||||
ossl_lms_key_free(key);
|
||||
key = NULL;
|
||||
}
|
||||
}
|
||||
next:
|
||||
ERR_clear_last_mark();
|
||||
/*
|
||||
* Indicated that we successfully decoded something, or not at all.
|
||||
* Ending up "empty handed" is not an error.
|
||||
*/
|
||||
ok = 1;
|
||||
|
||||
/*
|
||||
* We free resources here so it's not held up during the callback, because
|
||||
* we know the process is recursive and the allocated chunks of memory
|
||||
* add up.
|
||||
*/
|
||||
BIO_free(in);
|
||||
in = NULL;
|
||||
|
||||
if (key != NULL) {
|
||||
OSSL_PARAM params[4];
|
||||
int object_type = OSSL_OBJECT_PKEY;
|
||||
|
||||
params[0] =
|
||||
OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &object_type);
|
||||
params[1] =
|
||||
OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
|
||||
(char *)"lms", 0);
|
||||
/* The address of the key becomes the octet string */
|
||||
params[2] =
|
||||
OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE,
|
||||
&key, sizeof(key));
|
||||
params[3] = OSSL_PARAM_construct_end();
|
||||
|
||||
ok = data_cb(params, data_cbarg);
|
||||
}
|
||||
|
||||
BIO_free(in);
|
||||
ossl_lms_key_free(key);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int lmsxdr2key_export_object(void *vctx,
|
||||
const void *reference, size_t reference_sz,
|
||||
OSSL_CALLBACK *export_cb,
|
||||
void *export_cbarg)
|
||||
{
|
||||
struct lmsxdr2key_ctx_st *ctx = vctx;
|
||||
OSSL_FUNC_keymgmt_export_fn *export =
|
||||
ossl_prov_get_keymgmt_export(ossl_lms_keymgmt_functions);
|
||||
void *keydata;
|
||||
|
||||
if (reference_sz == sizeof(keydata) && export != NULL) {
|
||||
int selection = ctx->selection;
|
||||
|
||||
if (selection == 0)
|
||||
selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
|
||||
/* The contents of the reference is the address to our object */
|
||||
keydata = *(void **)reference;
|
||||
|
||||
return export(keydata, selection, export_cb, export_cbarg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH ossl_xdr_to_lms_decoder_functions[] = {
|
||||
{ OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))lmsxdr2key_newctx },
|
||||
{ OSSL_FUNC_DECODER_FREECTX, (void (*)(void))lmsxdr2key_freectx },
|
||||
{ OSSL_FUNC_DECODER_DOES_SELECTION,
|
||||
(void (*)(void))lmsxdr2key_does_selection },
|
||||
{ OSSL_FUNC_DECODER_DECODE, (void (*)(void))lmsxdr2key_decode },
|
||||
{ OSSL_FUNC_DECODER_EXPORT_OBJECT,
|
||||
(void (*)(void))lmsxdr2key_export_object },
|
||||
OSSL_DISPATCH_END
|
||||
};
|
|
@ -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[];
|
||||
|
@ -383,6 +386,7 @@ extern const OSSL_DISPATCH ossl_mac_legacy_siphash_signature_functions[];
|
|||
extern const OSSL_DISPATCH ossl_mac_legacy_poly1305_signature_functions[];
|
||||
extern const OSSL_DISPATCH ossl_mac_legacy_cmac_signature_functions[];
|
||||
extern const OSSL_DISPATCH ossl_sm2_signature_functions[];
|
||||
extern const OSSL_DISPATCH ossl_lms_signature_functions[];
|
||||
|
||||
/* Asym Cipher */
|
||||
extern const OSSL_DISPATCH ossl_rsa_asym_cipher_functions[];
|
||||
|
@ -587,3 +591,5 @@ extern const OSSL_DISPATCH ossl_pem_to_der_decoder_functions[];
|
|||
|
||||
extern const OSSL_DISPATCH ossl_file_store_functions[];
|
||||
extern const OSSL_DISPATCH ossl_winstore_store_functions[];
|
||||
|
||||
extern const OSSL_DISPATCH ossl_xdr_to_lms_decoder_functions[];
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 ../../libfips.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
|
||||
|
|
167
providers/implementations/keymgmt/lms_kmgmt.c
Normal file
167
providers/implementations/keymgmt/lms_kmgmt.c
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* 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 <openssl/core_dispatch.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/param_build.h>
|
||||
#include "crypto/lms.h"
|
||||
#include "internal/param_build_set.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "prov/providercommon.h"
|
||||
#include "prov/provider_ctx.h"
|
||||
|
||||
static OSSL_FUNC_keymgmt_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_export_fn lms_export;
|
||||
static OSSL_FUNC_keymgmt_import_types_fn lms_imexport_types;
|
||||
static OSSL_FUNC_keymgmt_export_types_fn lms_imexport_types;
|
||||
static OSSL_FUNC_keymgmt_load_fn lms_load;
|
||||
|
||||
#define LMS_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_PUBLIC_KEY)
|
||||
|
||||
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_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
|
||||
void *cbarg)
|
||||
{
|
||||
LMS_KEY *lmskey = keydata;
|
||||
OSSL_PARAM_BLD *tmpl;
|
||||
OSSL_PARAM *params = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!ossl_prov_is_running() || lmskey == NULL)
|
||||
return 0;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
|
||||
return 0;
|
||||
|
||||
tmpl = OSSL_PARAM_BLD_new();
|
||||
if (tmpl == NULL)
|
||||
return 0;
|
||||
|
||||
if (!ossl_param_build_set_octet_string(tmpl, params,
|
||||
OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
|
||||
lmskey->pub.encoded,
|
||||
lmskey->pub.encodedlen))
|
||||
goto err;
|
||||
|
||||
params = OSSL_PARAM_BLD_to_param(tmpl);
|
||||
if (params == NULL)
|
||||
goto err;
|
||||
|
||||
ret = param_cb(params, cbarg);
|
||||
OSSL_PARAM_free(params);
|
||||
err:
|
||||
OSSL_PARAM_BLD_free(tmpl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lms_validate(const void *keydata, int selection, int checktype)
|
||||
{
|
||||
const LMS_KEY *lmskey = keydata;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void *lms_load(const void *reference, size_t reference_sz)
|
||||
{
|
||||
LMS_KEY *key = NULL;
|
||||
|
||||
if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
|
||||
/* The contents of the reference is the address to our object */
|
||||
key = *(LMS_KEY **)reference;
|
||||
/* We grabbed, so we detach it */
|
||||
*(LMS_KEY **)reference = NULL;
|
||||
return key;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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_FUNC_KEYMGMT_EXPORT, (void (*)(void))lms_export },
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))lms_imexport_types },
|
||||
{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))lms_load },
|
||||
OSSL_DISPATCH_END
|
||||
};
|
|
@ -6,6 +6,7 @@ $EC_GOAL=../../libdefault.a ../../libfips.a
|
|||
$MAC_GOAL=../../libdefault.a ../../libfips.a
|
||||
$RSA_GOAL=../../libdefault.a ../../libfips.a
|
||||
$SM2_GOAL=../../libdefault.a
|
||||
$LMS_GOAL=../../libdefault.a ../../libfips.a
|
||||
|
||||
IF[{- !$disabled{dsa} -}]
|
||||
SOURCE[$DSA_GOAL]=dsa_sig.c
|
||||
|
@ -31,3 +32,7 @@ DEPEND[eddsa_sig.o]=../../common/include/prov/der_ecx.h
|
|||
DEPEND[sm2_sig.o]=../../common/include/prov/der_sm2.h
|
||||
|
||||
SOURCE[$MAC_GOAL]=mac_legacy_sig.c
|
||||
|
||||
IF[{- !$disabled{lms} -}]
|
||||
SOURCE[$LMS_GOAL]=lms_signature.c
|
||||
ENDIF
|
||||
|
|
138
providers/implementations/signature/lms_signature.c
Normal file
138
providers/implementations/signature/lms_signature.c
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* 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 <openssl/core.h>
|
||||
#include <openssl/core_dispatch.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/proverr.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "prov/providercommon.h"
|
||||
#include "prov/provider_ctx.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "crypto/lms_sig.h"
|
||||
|
||||
static OSSL_FUNC_signature_newctx_fn lms_newctx;
|
||||
static OSSL_FUNC_signature_freectx_fn lms_freectx;
|
||||
static OSSL_FUNC_signature_verify_message_init_fn lms_verify_msg_init;
|
||||
static OSSL_FUNC_signature_verify_fn lms_verify;
|
||||
|
||||
typedef struct {
|
||||
OSSL_LIB_CTX *libctx;
|
||||
char *propq;
|
||||
LMS_KEY *key;
|
||||
EVP_MD *md;
|
||||
} PROV_LMS_CTX;
|
||||
|
||||
static void *lms_newctx(void *provctx, const char *propq)
|
||||
{
|
||||
PROV_LMS_CTX *ctx;
|
||||
|
||||
if (!ossl_prov_is_running())
|
||||
return NULL;
|
||||
|
||||
ctx = OPENSSL_zalloc(sizeof(PROV_LMS_CTX));
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
if (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL)
|
||||
goto err;
|
||||
ctx->libctx = PROV_LIBCTX_OF(provctx);
|
||||
return ctx;
|
||||
err:
|
||||
OPENSSL_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void lms_freectx(void *vctx)
|
||||
{
|
||||
PROV_LMS_CTX *ctx = (PROV_LMS_CTX *)vctx;
|
||||
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
ossl_lms_key_free(ctx->key);
|
||||
OPENSSL_free(ctx->propq);
|
||||
EVP_MD_free(ctx->md);
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
static int setdigest(PROV_LMS_CTX *ctx, const char *digestname)
|
||||
{
|
||||
/*
|
||||
* Assume that only one digest can be used by LMS.
|
||||
* Set the digest to the one contained in the public key.
|
||||
* If the optional digestname passed in by the user is different
|
||||
* then return an error.
|
||||
*/
|
||||
LMS_KEY *key = ctx->key;
|
||||
const char *pub_digestname = key->ots_params->digestname;
|
||||
|
||||
if (ctx->md != NULL) {
|
||||
if (EVP_MD_is_a(ctx->md, pub_digestname))
|
||||
goto end;
|
||||
EVP_MD_free(ctx->md);
|
||||
}
|
||||
ctx->md = EVP_MD_fetch(ctx->libctx, pub_digestname, ctx->propq);
|
||||
if (ctx->md == NULL)
|
||||
return 0;
|
||||
end:
|
||||
return digestname == NULL || EVP_MD_is_a(ctx->md, digestname);
|
||||
}
|
||||
|
||||
static int lms_verify_msg_init(void *vctx, void *vkey, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_LMS_CTX *ctx = (PROV_LMS_CTX *)vctx;
|
||||
LMS_KEY *key = (LMS_KEY *)vkey;
|
||||
|
||||
if (!ossl_prov_is_running() || ctx == NULL)
|
||||
return 0;
|
||||
|
||||
if (key == NULL && ctx->key == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ossl_lms_key_up_ref(key))
|
||||
return 0;
|
||||
ossl_lms_key_free(ctx->key);
|
||||
ctx->key = key;
|
||||
if (!setdigest(ctx, NULL))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lms_verify(void *vctx, const unsigned char *sigbuf, size_t sigbuf_len,
|
||||
const unsigned char *msg, size_t msglen)
|
||||
{
|
||||
int ret = 0;
|
||||
PROV_LMS_CTX *ctx = (PROV_LMS_CTX *)vctx;
|
||||
LMS_KEY *pub = ctx->key;
|
||||
LMS_SIG *sig = NULL;
|
||||
|
||||
/* A root public key is required to perform a verify operation */
|
||||
if (pub == NULL)
|
||||
return 0;
|
||||
|
||||
/* Decode the LMS signature data into a LMS_SIG object */
|
||||
if (!ossl_lms_sig_decode(&sig, pub, sigbuf, sigbuf_len))
|
||||
return 0;
|
||||
|
||||
ret = ossl_lms_sig_verify(sig, pub, ctx->md, msg, msglen);
|
||||
ossl_lms_sig_free(sig);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH ossl_lms_signature_functions[] = {
|
||||
{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))lms_newctx },
|
||||
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))lms_freectx },
|
||||
{ OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT,
|
||||
(void (*)(void))lms_verify_msg_init },
|
||||
{ OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))lms_verify },
|
||||
OSSL_DISPATCH_END
|
||||
};
|
|
@ -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
|
||||
|
|
38
test/lms.inc
Normal file
38
test/lms.inc
Normal file
|
@ -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)
|
||||
};
|
233
test/lms_common.inc
Normal file
233
test/lms_common.inc
Normal file
|
@ -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,
|
||||
};
|
538
test/lms_test.c
Normal file
538
test/lms_test.c
Normal file
|
@ -0,0 +1,538 @@
|
|||
/*
|
||||
* 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 <openssl/core_names.h>
|
||||
#include <openssl/decoder.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "crypto/lms.h"
|
||||
#include "internal/nelem.h"
|
||||
#include "testutil.h"
|
||||
#include "lms.inc"
|
||||
|
||||
typedef enum OPTION_choice {
|
||||
OPT_ERR = -1,
|
||||
OPT_EOF = 0,
|
||||
OPT_CONFIG_FILE,
|
||||
OPT_TEST_ENUM
|
||||
} OPTION_CHOICE;
|
||||
|
||||
static OSSL_LIB_CTX *libctx = NULL;
|
||||
static char *propq = NULL;
|
||||
static OSSL_PROVIDER *nullprov = NULL;
|
||||
static OSSL_PROVIDER *libprov = NULL;
|
||||
|
||||
static EVP_PKEY *lms_pubkey_from_data(const unsigned char *data, size_t datalen)
|
||||
{
|
||||
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", propq))
|
||||
&& 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_pubkey_decoder_fail_test(void)
|
||||
{
|
||||
int ret = 0;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
OSSL_DECODER_CTX *dctx = NULL;
|
||||
int selection = 0;
|
||||
LMS_ACVP_TEST_DATA *td = &lms_testdata[0];
|
||||
const unsigned char *pdata;
|
||||
size_t pdatalen;
|
||||
static const unsigned char pub_bad_LMSType[] = {
|
||||
0x00, 0x00, 0x00, 0xAA
|
||||
};
|
||||
static const unsigned char pub_bad_OTSType[] = {
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xAA
|
||||
};
|
||||
|
||||
if (!TEST_ptr(dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, NULL, NULL, "LMS",
|
||||
selection,
|
||||
libctx, NULL)))
|
||||
return 0;
|
||||
|
||||
pdata = td->pub;
|
||||
pdatalen = 3;
|
||||
if (!TEST_false(OSSL_DECODER_from_data(dctx, &pdata, &pdatalen)))
|
||||
goto end;
|
||||
|
||||
pdatalen = SIZE_MAX;
|
||||
if (!TEST_false(OSSL_DECODER_from_data(dctx, &pdata, &pdatalen)))
|
||||
goto end;
|
||||
|
||||
pdata = pub_bad_LMSType;
|
||||
pdatalen = sizeof(pub_bad_LMSType);
|
||||
if (!TEST_false(OSSL_DECODER_from_data(dctx, &pdata, &pdatalen)))
|
||||
goto end;
|
||||
|
||||
pdata = pub_bad_OTSType;
|
||||
pdatalen = sizeof(pub_bad_OTSType);
|
||||
if (!TEST_false(OSSL_DECODER_from_data(dctx, &pdata, &pdatalen)))
|
||||
goto end;
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
EVP_PKEY_free(pkey);
|
||||
OSSL_DECODER_CTX_free(dctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static EVP_PKEY *key_decode_from_bio(BIO *bio, const char *keytype)
|
||||
{
|
||||
EVP_PKEY *pkey = NULL;
|
||||
OSSL_DECODER_CTX *dctx = NULL;
|
||||
int selection = 0;
|
||||
|
||||
if (!TEST_ptr(dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, NULL, NULL,
|
||||
keytype,
|
||||
selection,
|
||||
libctx, NULL)))
|
||||
return NULL;
|
||||
|
||||
if (!TEST_true(OSSL_DECODER_from_bio(dctx, bio))) {
|
||||
EVP_PKEY_free(pkey);
|
||||
pkey = NULL;
|
||||
}
|
||||
OSSL_DECODER_CTX_free(dctx);
|
||||
return pkey;
|
||||
}
|
||||
|
||||
static EVP_PKEY *key_decode_from_data(const unsigned char *data, size_t datalen,
|
||||
const char *keytype)
|
||||
{
|
||||
BIO *bio;
|
||||
EVP_PKEY *key = NULL;
|
||||
|
||||
if (!TEST_ptr(bio = BIO_new_mem_buf(data, datalen)))
|
||||
return NULL;
|
||||
key = key_decode_from_bio(bio, keytype);
|
||||
BIO_free(bio);
|
||||
return key;
|
||||
}
|
||||
|
||||
static int lms_key_decode_test(void)
|
||||
{
|
||||
int ret = 0;
|
||||
LMS_ACVP_TEST_DATA *td1 = &lms_testdata[0];
|
||||
EVP_PKEY *key = NULL;
|
||||
|
||||
ret = TEST_ptr(key = key_decode_from_data(td1->pub, td1->publen, NULL));
|
||||
EVP_PKEY_free(key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lms_pubkey_decoder_test(void)
|
||||
{
|
||||
int ret = 0;
|
||||
LMS_ACVP_TEST_DATA *td = &lms_testdata[0];
|
||||
EVP_PKEY *pub = NULL;
|
||||
OSSL_DECODER_CTX *dctx = NULL;
|
||||
const unsigned char *data;
|
||||
size_t data_len;
|
||||
|
||||
if (!TEST_ptr(dctx = OSSL_DECODER_CTX_new_for_pkey(&pub, "xdr", NULL,
|
||||
"LMS",
|
||||
OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
|
||||
libctx, NULL)))
|
||||
goto err;
|
||||
data = td->pub;
|
||||
data_len = td->publen;
|
||||
if (!TEST_true(OSSL_DECODER_from_data(dctx, &data, &data_len)))
|
||||
goto err;
|
||||
ret = 1;
|
||||
err:
|
||||
EVP_PKEY_free(pub);
|
||||
OSSL_DECODER_CTX_free(dctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lms_key_eq_test(void)
|
||||
{
|
||||
int ret = 0;
|
||||
EVP_PKEY *key[4];
|
||||
LMS_ACVP_TEST_DATA *td1 = &lms_testdata[0];
|
||||
LMS_ACVP_TEST_DATA *td2 = &lms_testdata[1];
|
||||
size_t i;
|
||||
#ifndef OPENSSL_NO_EC
|
||||
EVP_PKEY *eckey = NULL;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < OSSL_NELEM(key); i++)
|
||||
key[i] = NULL;
|
||||
|
||||
if (!TEST_ptr(key[0] = lms_pubkey_from_data(td1->pub, td1->publen))
|
||||
|| !TEST_ptr(key[1] = lms_pubkey_from_data(td1->pub, td1->publen))
|
||||
|| !TEST_ptr(key[2] = lms_pubkey_from_data(td2->pub, td2->publen))
|
||||
|| !TEST_ptr(key[3] = key_decode_from_data(td1->pub, td1->publen,
|
||||
NULL)))
|
||||
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)
|
||||
&& TEST_int_eq(EVP_PKEY_eq(key[0], key[3]), 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[3]);
|
||||
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;
|
||||
}
|
||||
|
||||
static int lms_verify_test(int tst)
|
||||
{
|
||||
int ret = 0;
|
||||
LMS_ACVP_TEST_DATA *td = &lms_testdata[tst];
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EVP_SIGNATURE *sig = NULL;
|
||||
|
||||
ret = TEST_ptr(pkey = lms_pubkey_from_data(td->pub, td->publen))
|
||||
&& TEST_ptr(sig = EVP_SIGNATURE_fetch(libctx, "LMS", NULL))
|
||||
&& TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL))
|
||||
&& TEST_int_eq(EVP_PKEY_verify_message_init(ctx, sig, NULL), 1)
|
||||
&& TEST_int_eq(EVP_PKEY_verify(ctx, td->sig, td->siglen,
|
||||
td->msg, td->msglen), 1);
|
||||
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_SIGNATURE_free(sig);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lms_digest_verify_fail_test(void)
|
||||
{
|
||||
int ret = 0;
|
||||
LMS_ACVP_TEST_DATA *td = &lms_testdata[0];
|
||||
EVP_PKEY *pub = NULL;
|
||||
EVP_MD_CTX *vctx = NULL;
|
||||
|
||||
if (!TEST_ptr(pub = lms_pubkey_from_data(td->pub, td->publen)))
|
||||
return 0;
|
||||
if (!TEST_ptr(vctx = EVP_MD_CTX_new()))
|
||||
goto err;
|
||||
if (!TEST_int_eq(EVP_DigestVerifyInit_ex(vctx, NULL, NULL, libctx, NULL,
|
||||
pub, NULL), 0))
|
||||
goto err;
|
||||
ret = 1;
|
||||
err:
|
||||
EVP_PKEY_free(pub);
|
||||
EVP_MD_CTX_free(vctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lms_verify_fail_test(void)
|
||||
{
|
||||
int ret = 0;
|
||||
LMS_ACVP_TEST_DATA *td = &lms_testdata[0];
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
|
||||
if (!TEST_ptr(pkey = lms_pubkey_from_data(td->pub, td->publen))
|
||||
|| !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL)))
|
||||
goto end;
|
||||
if (!TEST_int_eq(EVP_PKEY_verify_init(ctx), -2))
|
||||
goto end;
|
||||
ret = 1;
|
||||
end:
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lms_verify_bad_sig_test(void)
|
||||
{
|
||||
int ret = 0, i = 0;
|
||||
LMS_ACVP_TEST_DATA *td = &lms_testdata[1];
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EVP_SIGNATURE *sig = NULL;
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
unsigned char *sig_data = NULL, corrupt_mask = 0x01;
|
||||
/*
|
||||
* Corrupt every 3rd byte to run less tests. The smallest element of an XDR
|
||||
* encoding is 4 bytes, so this will corrupt every element.
|
||||
* Memory sanitisation is slow, so a larger step size is used for this.
|
||||
*/
|
||||
#if defined(OSSL_SANITIZE_MEMORY)
|
||||
const int step = (int)(td->siglen >> 1);
|
||||
#else
|
||||
const int step = 3;
|
||||
#endif
|
||||
|
||||
/* Copy the signature so that we can corrupt it */
|
||||
sig_data = OPENSSL_memdup(td->sig, td->siglen);
|
||||
if (sig_data == NULL)
|
||||
return 0;
|
||||
|
||||
if (!TEST_ptr(pkey = lms_pubkey_from_data(td->pub, td->publen))
|
||||
|| !TEST_ptr(sig = EVP_SIGNATURE_fetch(libctx, "LMS", NULL))
|
||||
|| !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL)))
|
||||
goto end;
|
||||
|
||||
if (!TEST_int_eq(EVP_PKEY_verify_message_init(ctx, sig, NULL), 1))
|
||||
goto end;
|
||||
|
||||
for (i = 0; i < (int)td->siglen; i += step) {
|
||||
sig_data[i] ^= corrupt_mask; /* corrupt a byte */
|
||||
if (i > 0)
|
||||
sig_data[i - step] ^= corrupt_mask; /* Reset the previously corrupt byte */
|
||||
|
||||
if (!TEST_int_eq(EVP_PKEY_verify(ctx, sig_data, td->siglen,
|
||||
td->msg, td->msglen), 0)) {
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
if (ret == -1)
|
||||
TEST_note("Incorrectly passed when %dth byte of signature"
|
||||
" was corrupted", i);
|
||||
EVP_SIGNATURE_free(sig);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
OPENSSL_free(sig_data);
|
||||
|
||||
return ret == 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that using the incorrect signature lengths (both shorter and longer)
|
||||
* fail.
|
||||
* NOTE: It does not get an out of bounds read due to the signature
|
||||
* knowing how large it should be
|
||||
*/
|
||||
static int lms_verify_bad_sig_len_test(void)
|
||||
{
|
||||
int ret = 0;
|
||||
LMS_ACVP_TEST_DATA *td = &lms_testdata[1];
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EVP_SIGNATURE *sig = NULL;
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
size_t siglen = 0;
|
||||
const int step = 3;
|
||||
unsigned char sigdata[4096];
|
||||
|
||||
if (!TEST_ptr(pkey = lms_pubkey_from_data(td->pub, td->publen))
|
||||
|| !TEST_ptr(sig = EVP_SIGNATURE_fetch(libctx, "LMS", NULL))
|
||||
|| !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL)))
|
||||
goto end;
|
||||
|
||||
if (!TEST_size_t_le(td->siglen + 16, sizeof(sigdata)))
|
||||
goto end;
|
||||
|
||||
OPENSSL_cleanse(sigdata, sizeof(sigdata));
|
||||
memcpy(sigdata, td->sig, td->siglen);
|
||||
|
||||
ret = 0;
|
||||
for (siglen = 0; siglen < td->siglen + 16; siglen += step) {
|
||||
if (siglen == td->siglen) /* ignore the size that should pass */
|
||||
continue;
|
||||
if (!TEST_int_eq(EVP_PKEY_verify_message_init(ctx, sig, NULL), 1))
|
||||
goto end;
|
||||
if (!TEST_int_eq(EVP_PKEY_verify(ctx, sigdata, siglen,
|
||||
td->msg, td->msglen), 0)) {
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
if (ret == -1)
|
||||
TEST_note("Incorrectly accepted signature key of length"
|
||||
" %u (expected %u)", (unsigned)siglen, (unsigned)td->siglen);
|
||||
EVP_SIGNATURE_free(sig);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
|
||||
return ret == 1;
|
||||
}
|
||||
|
||||
static int lms_verify_bad_pub_sig_test(void)
|
||||
{
|
||||
LMS_ACVP_TEST_DATA *td = &lms_testdata[1];
|
||||
int ret = 0, i = 0;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EVP_SIGNATURE *sig = NULL;
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
unsigned char *pub = NULL;
|
||||
const int step = 1;
|
||||
|
||||
/* Copy the public key data so that we can corrupt it */
|
||||
if (!TEST_ptr(pub = OPENSSL_memdup(td->pub, td->publen)))
|
||||
return 0;
|
||||
|
||||
if (!TEST_ptr(sig = EVP_SIGNATURE_fetch(libctx, "LMS", NULL)))
|
||||
goto end;
|
||||
|
||||
for (i = 0; i < (int)td->publen; i += step) {
|
||||
if (i > 0) {
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
pkey = NULL;
|
||||
ctx = NULL;
|
||||
pub[i - step] ^= 1;
|
||||
}
|
||||
pub[3] ^= 1;
|
||||
/* Corrupting the public key may cause the key load to fail */
|
||||
pkey = lms_pubkey_from_data(pub, td->publen);
|
||||
if (pkey == NULL)
|
||||
continue;
|
||||
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL)))
|
||||
continue;
|
||||
if (!TEST_int_eq(EVP_PKEY_verify_message_init(ctx, sig, NULL), 1))
|
||||
continue;
|
||||
/* We expect the verify to fail */
|
||||
if (!TEST_int_eq(EVP_PKEY_verify(ctx, td->sig, td->siglen,
|
||||
td->msg, td->msglen), 0)) {
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
if (ret == -1)
|
||||
TEST_note("Incorrectly passed when byte %d of the public key"
|
||||
" was corrupted", i);
|
||||
EVP_SIGNATURE_free(sig);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
OPENSSL_free(pub);
|
||||
|
||||
return ret == 1;
|
||||
}
|
||||
|
||||
const OPTIONS *test_get_options(void)
|
||||
{
|
||||
static const OPTIONS options[] = {
|
||||
OPT_TEST_OPTIONS_DEFAULT_USAGE,
|
||||
{ "config", OPT_CONFIG_FILE, '<',
|
||||
"The configuration file to use for the libctx" },
|
||||
{ NULL }
|
||||
};
|
||||
return options;
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
OPTION_CHOICE o;
|
||||
char *config_file = NULL;
|
||||
|
||||
/* Swap the libctx to test non-default context only */
|
||||
propq = "provider=default";
|
||||
|
||||
while ((o = opt_next()) != OPT_EOF) {
|
||||
switch (o) {
|
||||
case OPT_CONFIG_FILE:
|
||||
config_file = opt_arg();
|
||||
propq = "";
|
||||
break;
|
||||
case OPT_TEST_CASES:
|
||||
break;
|
||||
default:
|
||||
case OPT_ERR:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!test_get_libctx(&libctx, &nullprov, config_file, &libprov, NULL))
|
||||
return 0;
|
||||
|
||||
ADD_TEST(lms_bad_pub_len_test);
|
||||
ADD_TEST(lms_key_validate_test);
|
||||
ADD_TEST(lms_key_eq_test);
|
||||
ADD_TEST(lms_key_decode_test);
|
||||
ADD_TEST(lms_pubkey_decoder_test);
|
||||
ADD_TEST(lms_pubkey_decoder_fail_test);
|
||||
ADD_ALL_TESTS(lms_verify_test, OSSL_NELEM(lms_testdata));
|
||||
ADD_TEST(lms_verify_fail_test);
|
||||
ADD_TEST(lms_digest_verify_fail_test);
|
||||
ADD_TEST(lms_verify_bad_sig_test);
|
||||
ADD_TEST(lms_verify_bad_sig_len_test);
|
||||
ADD_TEST(lms_verify_bad_pub_sig_test);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cleanup_tests(void)
|
||||
{
|
||||
OSSL_PROVIDER_unload(nullprov);
|
||||
OSSL_PROVIDER_unload(libprov);
|
||||
OSSL_LIB_CTX_free(libctx);
|
||||
}
|
38
test/recipes/30-test_lms.t
Normal file
38
test/recipes/30-test_lms.t
Normal file
|
@ -0,0 +1,38 @@
|
|||
#! /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_file srctop_dir bldtop_dir);
|
||||
use OpenSSL::Test::Utils;
|
||||
|
||||
BEGIN {
|
||||
setup("test_lms");
|
||||
}
|
||||
|
||||
my $provconf = srctop_file("test", "fips-and-base.cnf");
|
||||
my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
|
||||
|
||||
run(test(["fips_version_test", "-config", $provconf, ">=3.5.0"]),
|
||||
capture => 1, statusvar => \my $exit);
|
||||
|
||||
plan skip_all => "FIPS provider does not support LMS" if !$exit;
|
||||
|
||||
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 + + ($no_fips ? 0 : 1);
|
||||
|
||||
ok(run(test(["lms_test"])), "running lms_test");
|
||||
|
||||
unless ($no_fips) {
|
||||
ok(run(test(["lms_test", "-config", $provconf])),
|
||||
"running lms_test with fips");
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue