mirror of https://github.com/openssl/openssl.git
LMS code review fixups
Reviewed-by: Viktor Dukhovni <viktor@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Paul Dale <ppzgs1@gmail.com> (Merged from https://github.com/openssl/openssl/pull/27885)
This commit is contained in:
parent
e6c8110483
commit
6b5fd48ee4
|
@ -44,7 +44,7 @@ const LM_OTS_PARAMS *ossl_lm_ots_params_get(uint32_t ots_type)
|
||||||
{
|
{
|
||||||
const LM_OTS_PARAMS *p;
|
const LM_OTS_PARAMS *p;
|
||||||
|
|
||||||
for (p = lm_ots_params; p->lm_ots_type != 0; ++p)
|
for (p = lm_ots_params; p->digestname != NULL; ++p)
|
||||||
if (p->lm_ots_type == ots_type)
|
if (p->lm_ots_type == ots_type)
|
||||||
return p;
|
return p;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -61,6 +61,6 @@ uint16_t ossl_lm_ots_params_checksum(const LM_OTS_PARAMS *params,
|
||||||
uint16_t end = (1 << params->w) - 1;
|
uint16_t end = (1 << params->w) - 1;
|
||||||
|
|
||||||
for (i = 0; i < bytes; ++i)
|
for (i = 0; i < bytes; ++i)
|
||||||
sum += end - coef(S, i, params->w);
|
sum += end - lms_ots_coef(S, i, params->w);
|
||||||
return (sum << params->ls);
|
return (sum << params->ls);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/byteorder.h>
|
||||||
#include "crypto/lms_sig.h"
|
#include "crypto/lms_sig.h"
|
||||||
#include "crypto/lms_util.h"
|
#include "crypto/lms_util.h"
|
||||||
|
|
||||||
|
@ -39,38 +40,33 @@ int ossl_lm_ots_compute_pubkey(EVP_MD_CTX *ctx, EVP_MD_CTX *ctxIq,
|
||||||
const unsigned char *msg, size_t msglen,
|
const unsigned char *msg, size_t msglen,
|
||||||
unsigned char *Kc)
|
unsigned char *Kc)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
|
||||||
unsigned char qbuf[LMS_SIZE_q];
|
unsigned char qbuf[LMS_SIZE_q];
|
||||||
unsigned char d_mesg[sizeof(uint16_t)];
|
unsigned char d_mesg[sizeof(uint16_t)];
|
||||||
|
|
||||||
if (sig->params != pub)
|
if (sig->params != pub)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
U32STR(qbuf, q);
|
OPENSSL_store_u32_be(qbuf, q);
|
||||||
U16STR(d_mesg, OSSL_LMS_D_MESG);
|
OPENSSL_store_u16_be(d_mesg, OSSL_LMS_D_MESG);
|
||||||
|
|
||||||
if (!EVP_DigestUpdate(ctxIq, Id, LMS_SIZE_I)
|
return (EVP_DigestUpdate(ctxIq, Id, LMS_SIZE_I)
|
||||||
|| !EVP_DigestUpdate(ctxIq, qbuf, sizeof(qbuf))
|
&& EVP_DigestUpdate(ctxIq, qbuf, sizeof(qbuf))
|
||||||
|| !EVP_MD_CTX_copy_ex(ctx, ctxIq)
|
&& EVP_MD_CTX_copy_ex(ctx, ctxIq)
|
||||||
/* Q = H(I || u32str(q) || u16str(D_MESG) || C || msg) */
|
/* Q = H(I || u32str(q) || u16str(D_MESG) || C || msg) */
|
||||||
|| !EVP_DigestUpdate(ctx, d_mesg, sizeof(d_mesg))
|
&& EVP_DigestUpdate(ctx, d_mesg, sizeof(d_mesg))
|
||||||
|| !EVP_DigestUpdate(ctx, sig->C, sig->params->n)
|
&& EVP_DigestUpdate(ctx, sig->C, sig->params->n)
|
||||||
|| !EVP_DigestUpdate(ctx, msg, msglen)
|
&& EVP_DigestUpdate(ctx, msg, msglen)
|
||||||
|| !lm_ots_compute_pubkey_final(ctx, ctxIq, sig, Kc))
|
&& 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.
|
* @brief simple function to increment a big-endian 16 bit counter by 1.
|
||||||
* It assumes checking for overflow is not required.
|
* It assumes checking for overflow is not required.
|
||||||
*/
|
*/
|
||||||
static ossl_inline void INC16(unsigned char *tag)
|
static ossl_inline void INC16(unsigned char *tag)
|
||||||
{
|
{
|
||||||
if (++(tag[1]) == 0)
|
if (++(tag[1]) == 0)
|
||||||
++*tag;
|
++tag[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -83,7 +79,7 @@ static ossl_inline void INC16(unsigned char *tag)
|
||||||
* Q = H(I || u32str(q) || u16str(D_MESG) || C || msg)
|
* Q = H(I || u32str(q) || u16str(D_MESG) || C || msg)
|
||||||
* This ctx is reused for other calculations.
|
* 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 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 sig An object containing LM_OTS signature data.
|
||||||
* @param Kc The computed public key. It is assumed the size is n.
|
* @param Kc The computed public key. It is assumed the size is n.
|
||||||
* @returns 1 on success, or 0 otherwise.
|
* @returns 1 on success, or 0 otherwise.
|
||||||
*/
|
*/
|
||||||
|
@ -104,17 +100,15 @@ static int lm_ots_compute_pubkey_final(EVP_MD_CTX *ctx, EVP_MD_CTX *ctxIq,
|
||||||
int a;
|
int a;
|
||||||
unsigned char *y;
|
unsigned char *y;
|
||||||
|
|
||||||
if (!EVP_DigestFinal_ex(ctx, Q, NULL))
|
if (!EVP_DigestFinal_ex(ctx, Q, NULL)
|
||||||
goto err;
|
|| (ctxKc = EVP_MD_CTX_create()) == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
ctxKc = EVP_MD_CTX_create();
|
|
||||||
if (ctxKc == NULL)
|
|
||||||
goto err;
|
|
||||||
sum = ossl_lm_ots_params_checksum(params, Q);
|
sum = ossl_lm_ots_params_checksum(params, Q);
|
||||||
Qsum = Q + n;
|
Qsum = Q + n;
|
||||||
/* Q || Cksm(Q) */
|
/* Q || Cksm(Q) */
|
||||||
U16STR(Qsum, sum);
|
OPENSSL_store_u16_be(Qsum, sum);
|
||||||
U16STR(d_pblc, OSSL_LMS_D_PBLC);
|
OPENSSL_store_u16_be(d_pblc, OSSL_LMS_D_PBLC);
|
||||||
|
|
||||||
if (!(EVP_MD_CTX_copy_ex(ctxKc, ctxIq))
|
if (!(EVP_MD_CTX_copy_ex(ctxKc, ctxIq))
|
||||||
|| !EVP_DigestUpdate(ctxKc, d_pblc, sizeof(d_pblc)))
|
|| !EVP_DigestUpdate(ctxKc, d_pblc, sizeof(d_pblc)))
|
||||||
|
@ -130,7 +124,7 @@ static int lm_ots_compute_pubkey_final(EVP_MD_CTX *ctx, EVP_MD_CTX *ctxIq,
|
||||||
* the inner loop |end| is in the range 0...(2^w)-1
|
* the inner loop |end| is in the range 0...(2^w)-1
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < p; ++i) {
|
for (i = 0; i < p; ++i) {
|
||||||
a = coef(Q, i, w);
|
a = lms_ots_coef(Q, i, w);
|
||||||
memcpy(z, y, n);
|
memcpy(z, y, n);
|
||||||
y += n;
|
y += n;
|
||||||
for (j = a; j < end; ++j) {
|
for (j = a; j < end; ++j) {
|
||||||
|
|
|
@ -21,13 +21,8 @@ LMS_KEY *ossl_lms_key_new(OSSL_LIB_CTX *libctx)
|
||||||
{
|
{
|
||||||
LMS_KEY *ret = OPENSSL_zalloc(sizeof(LMS_KEY));
|
LMS_KEY *ret = OPENSSL_zalloc(sizeof(LMS_KEY));
|
||||||
|
|
||||||
if (ret != NULL) {
|
if (ret != NULL)
|
||||||
if (!CRYPTO_NEW_REF(&ret->references, 1)) {
|
|
||||||
OPENSSL_free(ret);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ret->libctx = libctx;
|
ret->libctx = libctx;
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,39 +32,15 @@ LMS_KEY *ossl_lms_key_new(OSSL_LIB_CTX *libctx)
|
||||||
void ossl_lms_key_free(LMS_KEY *lmskey)
|
void ossl_lms_key_free(LMS_KEY *lmskey)
|
||||||
{
|
{
|
||||||
LMS_PUB_KEY *pub;
|
LMS_PUB_KEY *pub;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (lmskey == NULL)
|
if (lmskey == NULL)
|
||||||
return;
|
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;
|
pub = &lmskey->pub;
|
||||||
OPENSSL_free(pub->encoded);
|
OPENSSL_free(pub->encoded);
|
||||||
CRYPTO_FREE_REF(&lmskey->references);
|
|
||||||
OPENSSL_free(lmskey);
|
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?
|
* @brief Are 2 LMS public keys equal?
|
||||||
*
|
*
|
||||||
|
|
|
@ -47,7 +47,7 @@ const LMS_PARAMS *ossl_lms_params_get(uint32_t lms_type)
|
||||||
{
|
{
|
||||||
const LMS_PARAMS *p;
|
const LMS_PARAMS *p;
|
||||||
|
|
||||||
for (p = lms_params; p->lms_type != 0; ++p)
|
for (p = lms_params; p->digestname != NULL; ++p)
|
||||||
if (p->lms_type == lms_type)
|
if (p->lms_type == lms_type)
|
||||||
return p;
|
return p;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -26,7 +26,7 @@ size_t ossl_lms_pubkey_length(const unsigned char *data, size_t datalen)
|
||||||
const LMS_PARAMS *params;
|
const LMS_PARAMS *params;
|
||||||
|
|
||||||
if (!PACKET_buf_init(&pkt, data, datalen)
|
if (!PACKET_buf_init(&pkt, data, datalen)
|
||||||
|| !PACKET_get_4_len(&pkt, &lms_type)
|
|| !PACKET_get_net_4_len_u32(&pkt, &lms_type)
|
||||||
|| (params = ossl_lms_params_get(lms_type)) == NULL)
|
|| (params = ossl_lms_params_get(lms_type)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
return LMS_SIZE_LMS_TYPE + LMS_SIZE_OTS_TYPE + LMS_SIZE_I + params->n;
|
return LMS_SIZE_LMS_TYPE + LMS_SIZE_OTS_TYPE + LMS_SIZE_I + params->n;
|
||||||
|
@ -56,12 +56,12 @@ int lms_pubkey_from_pkt(LMS_KEY *lmskey, const unsigned char *pubkeydata,
|
||||||
|
|
||||||
if (!PACKET_buf_init(&pkt, pubkeydata, publen))
|
if (!PACKET_buf_init(&pkt, pubkeydata, publen))
|
||||||
goto err;
|
goto err;
|
||||||
key->encoded = (unsigned char *)pkt.curr;
|
key->encoded = (unsigned char *)PACKET_data(&pkt);
|
||||||
if (!PACKET_get_4_len(&pkt, &lms_type))
|
if (!PACKET_get_net_4_len_u32(&pkt, &lms_type))
|
||||||
goto err;
|
goto err;
|
||||||
lmskey->lms_params = ossl_lms_params_get(lms_type);
|
lmskey->lms_params = ossl_lms_params_get(lms_type);
|
||||||
if (lmskey->lms_params == NULL
|
if (lmskey->lms_params == NULL
|
||||||
|| !PACKET_get_4_len(&pkt, &ots_type))
|
|| !PACKET_get_net_4_len_u32(&pkt, &ots_type))
|
||||||
goto err;
|
goto err;
|
||||||
lmskey->ots_params = ossl_lm_ots_params_get(ots_type);
|
lmskey->ots_params = ossl_lm_ots_params_get(ots_type);
|
||||||
if (lmskey->ots_params == NULL)
|
if (lmskey->ots_params == NULL)
|
||||||
|
@ -74,7 +74,7 @@ int lms_pubkey_from_pkt(LMS_KEY *lmskey, const unsigned char *pubkeydata,
|
||||||
|| !PACKET_get_bytes(&pkt, (const unsigned char **)&key->K,
|
|| !PACKET_get_bytes(&pkt, (const unsigned char **)&key->K,
|
||||||
lmskey->lms_params->n))
|
lmskey->lms_params->n))
|
||||||
goto err;
|
goto err;
|
||||||
key->encodedlen = pkt.curr - key->encoded;
|
key->encodedlen = (unsigned char *)PACKET_data(&pkt) - key->encoded;
|
||||||
return PACKET_remaining(&pkt) == 0;
|
return PACKET_remaining(&pkt) == 0;
|
||||||
err:
|
err:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
*
|
*
|
||||||
* @param pkt Contains the signature data to decode. There may still be data
|
* @param pkt Contains the signature data to decode. There may still be data
|
||||||
* remaining in pkt after decoding.
|
* remaining in pkt after decoding.
|
||||||
* @param pub A public key that contains LMS_PARAMS and LM_OTS_PARAMS associated
|
* @param pub A public key that contains LMS_PARAMS and LM_OTS_PARAMS associated
|
||||||
* with the signature.
|
* with the signature.
|
||||||
* @returns The created LMS_SIG object is successful, or NULL on failure. A
|
* @returns The created LMS_SIG object if successful, or NULL on failure. A
|
||||||
* failure may occur if the passed in LMS public key |pub| is not
|
* failure may occur if the passed in LMS public key |pub| is not
|
||||||
* compatible with the decoded LMS_SIG object,
|
* compatible with the decoded LMS_SIG object,
|
||||||
*/
|
*/
|
||||||
|
@ -38,8 +38,8 @@ LMS_SIG *ossl_lms_sig_from_pkt(PACKET *pkt, const LMS_KEY *pub)
|
||||||
if (lsig == NULL)
|
if (lsig == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!PACKET_get_4_len(pkt, &lsig->q) /* q = Leaf Index */
|
if (!PACKET_get_net_4_len_u32(pkt, &lsig->q) /* q = Leaf Index */
|
||||||
|| !PACKET_get_4_len(pkt, &sig_ots_type)
|
|| !PACKET_get_net_4_len_u32(pkt, &sig_ots_type)
|
||||||
|| pub_ots_params->lm_ots_type != sig_ots_type)
|
|| pub_ots_params->lm_ots_type != sig_ots_type)
|
||||||
goto err;
|
goto err;
|
||||||
sig_params = pub_ots_params;
|
sig_params = pub_ots_params;
|
||||||
|
@ -50,7 +50,7 @@ LMS_SIG *ossl_lms_sig_from_pkt(PACKET *pkt, const LMS_KEY *pub)
|
||||||
sig_params->n)
|
sig_params->n)
|
||||||
|| !PACKET_get_bytes(pkt, (const unsigned char **)&lsig->sig.y,
|
|| !PACKET_get_bytes(pkt, (const unsigned char **)&lsig->sig.y,
|
||||||
sig_params->p * sig_params->n)
|
sig_params->p * sig_params->n)
|
||||||
|| !PACKET_get_4_len(pkt, &sig_lms_type)
|
|| !PACKET_get_net_4_len_u32(pkt, &sig_lms_type)
|
||||||
|| (lparams->lms_type != sig_lms_type)
|
|| (lparams->lms_type != sig_lms_type)
|
||||||
|| HASH_NOT_MATCHED(lparams, sig_params)
|
|| HASH_NOT_MATCHED(lparams, sig_params)
|
||||||
|| lsig->q >= (uint32_t)(1 << lparams->h)
|
|| lsig->q >= (uint32_t)(1 << lparams->h)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* https://www.openssl.org/source/license.html
|
* https://www.openssl.org/source/license.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <openssl/byteorder.h>
|
||||||
#include "crypto/lms_sig.h"
|
#include "crypto/lms_sig.h"
|
||||||
#include "crypto/lms_util.h"
|
#include "crypto/lms_util.h"
|
||||||
#include "internal/common.h"
|
#include "internal/common.h"
|
||||||
|
@ -46,7 +47,7 @@ int lms_sig_compute_tc_from_path(const unsigned char *paths, uint32_t n,
|
||||||
unsigned char d_intr[sizeof(uint16_t)];
|
unsigned char d_intr[sizeof(uint16_t)];
|
||||||
const unsigned char *path = paths;
|
const unsigned char *path = paths;
|
||||||
|
|
||||||
U16STR(d_intr, OSSL_LMS_D_INTR);
|
OPENSSL_store_u16_be(d_intr, OSSL_LMS_D_INTR);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate the public key Tc using the path
|
* Calculate the public key Tc using the path
|
||||||
|
@ -60,7 +61,7 @@ int lms_sig_compute_tc_from_path(const unsigned char *paths, uint32_t n,
|
||||||
int odd = node_num & 1;
|
int odd = node_num & 1;
|
||||||
|
|
||||||
node_num = node_num >> 1; /* get the parent node_num */
|
node_num = node_num >> 1; /* get the parent node_num */
|
||||||
U32STR(qbuf, node_num);
|
OPENSSL_store_u32_be(qbuf, node_num);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate Tc as either
|
* Calculate Tc as either
|
||||||
|
@ -125,7 +126,7 @@ int ossl_lms_sig_verify(const LMS_SIG *lms_sig, const LMS_KEY *pub,
|
||||||
if (ctx == NULL || ctxIq == NULL)
|
if (ctx == NULL || ctxIq == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (!evp_md_ctx_init(ctxIq, md, lms_sig->params))
|
if (!lms_evp_md_ctx_init(ctxIq, md, lms_sig->params))
|
||||||
goto err;
|
goto err;
|
||||||
/*
|
/*
|
||||||
* Algorithm 6a: Step 3.
|
* Algorithm 6a: Step 3.
|
||||||
|
@ -145,8 +146,8 @@ int ossl_lms_sig_verify(const LMS_SIG *lms_sig, const LMS_KEY *pub,
|
||||||
return 0;
|
return 0;
|
||||||
node_num = (1 << lms_params->h) + lms_sig->q;
|
node_num = (1 << lms_params->h) + lms_sig->q;
|
||||||
|
|
||||||
U32STR(qbuf, node_num);
|
OPENSSL_store_u32_be(qbuf, node_num);
|
||||||
U16STR(d_leaf, OSSL_LMS_D_LEAF);
|
OPENSSL_store_u16_be(d_leaf, OSSL_LMS_D_LEAF);
|
||||||
ctxI = ctxIq;
|
ctxI = ctxIq;
|
||||||
/*
|
/*
|
||||||
* Tc = H(I || u32str(node_num) || u16str(D_LEAF) || Kc)
|
* Tc = H(I || u32str(node_num) || u16str(D_LEAF) || Kc)
|
||||||
|
|
|
@ -10,7 +10,7 @@ EVP_PKEY-LMS, EVP_KEYMGMT-LMS, LMS
|
||||||
The B<LMS> keytype is implemented in OpenSSL's default and FIPS providers.
|
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
|
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
|
[SP 800-208](https://csrc.nist.gov/pubs/sp/800/208/final) requirement for
|
||||||
software modules.
|
FIPS software modules.
|
||||||
|
|
||||||
=head2 Common LMS parameters
|
=head2 Common LMS parameters
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ Leighton-Micali Hash-Based Signatures
|
||||||
|
|
||||||
Recommendation for Stateful Hash-Based Signature Schemes
|
Recommendation for Stateful Hash-Based Signature Schemes
|
||||||
|
|
||||||
=item CSNA 2.0
|
=item CNSA 2.0
|
||||||
|
|
||||||
Commercial National Security Algorithm Suite
|
Commercial National Security Algorithm Suite
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,9 @@ EVP_SIGNATURE-LMS
|
||||||
The B<LMS> EVP_PKEY implementation supports Leighton-Micali Signatures (LMS)
|
The B<LMS> EVP_PKEY implementation supports Leighton-Micali Signatures (LMS)
|
||||||
described in [RFC 8554](https://datatracker.ietf.org/doc/html/rfc8854)
|
described in [RFC 8554](https://datatracker.ietf.org/doc/html/rfc8854)
|
||||||
and [SP 800-208](https://csrc.nist.gov/pubs/sp/800/208/final).
|
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
|
The OpenSSL providers only support LMS signature verification, as this is a
|
||||||
SP 800-208 requirement for software modules.
|
[SP 800-208](https://csrc.nist.gov/pubs/sp/800/208/final) requirement for
|
||||||
|
FIPS software modules.
|
||||||
|
|
||||||
EVP_PKEY_verify_message_init() and EVP_PKEY_verify() are the only supported
|
EVP_PKEY_verify_message_init() and EVP_PKEY_verify() are the only supported
|
||||||
functions used for LMS signatures. Streaming is not currently supported,
|
functions used for LMS signatures. Streaming is not currently supported,
|
||||||
|
@ -24,6 +24,10 @@ that specify the digest name are not necessary.
|
||||||
LMS support is disabled by default at compile-time.
|
LMS support is disabled by default at compile-time.
|
||||||
To enable, specify the B<enable-lms> build configuration option.
|
To enable, specify the B<enable-lms> build configuration option.
|
||||||
|
|
||||||
|
LMS should only be used for older deployments.
|
||||||
|
New deployments should use either L<EVP_SIGNATURE-ML-DSA(7)>
|
||||||
|
or <L/EVP_SIGNATURE-SLH-DSA(7)>.
|
||||||
|
|
||||||
=head1 EXAMPLES
|
=head1 EXAMPLES
|
||||||
|
|
||||||
Error checking has been omitted from the following examples
|
Error checking has been omitted from the following examples
|
||||||
|
|
|
@ -67,12 +67,8 @@ The OpenSSL FIPS provider supports these operations and algorithms:
|
||||||
|
|
||||||
=item SHA3, see L<EVP_MD-SHA3(7)>
|
=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 KECCAK-KMAC, see L<EVP_MD-KECCAK-KMAC(7)>
|
||||||
|
|
||||||
KECCAK-KMAC is only used internally as a sub algorithm of KMAC.
|
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head2 Symmetric Ciphers
|
=head2 Symmetric Ciphers
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
# ifndef OPENSSL_NO_LMS
|
# ifndef OPENSSL_NO_LMS
|
||||||
# include "types.h"
|
# include "types.h"
|
||||||
# include <openssl/params.h>
|
# include <openssl/params.h>
|
||||||
# include "internal/refcount.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Numeric identifiers associated with Leighton-Micali Signatures (LMS)
|
* Numeric identifiers associated with Leighton-Micali Signatures (LMS)
|
||||||
|
@ -135,20 +134,18 @@ typedef struct lms_pub_key_st {
|
||||||
unsigned char *K;
|
unsigned char *K;
|
||||||
} LMS_PUB_KEY;
|
} LMS_PUB_KEY;
|
||||||
|
|
||||||
struct lms_key_st {
|
typedef struct lms_key_st {
|
||||||
const LMS_PARAMS *lms_params;
|
const LMS_PARAMS *lms_params;
|
||||||
const LM_OTS_PARAMS *ots_params;
|
const LM_OTS_PARAMS *ots_params;
|
||||||
OSSL_LIB_CTX *libctx;
|
OSSL_LIB_CTX *libctx;
|
||||||
unsigned char *Id; /* A pointer to 16 bytes (I[16]) */
|
unsigned char *Id; /* A pointer to 16 bytes (I[16]) */
|
||||||
LMS_PUB_KEY pub;
|
LMS_PUB_KEY pub;
|
||||||
CRYPTO_REF_COUNT references;
|
} LMS_KEY;
|
||||||
};
|
|
||||||
|
|
||||||
const LMS_PARAMS *ossl_lms_params_get(uint32_t lms_type);
|
const LMS_PARAMS *ossl_lms_params_get(uint32_t lms_type);
|
||||||
const LM_OTS_PARAMS *ossl_lm_ots_params_get(uint32_t ots_type);
|
const LM_OTS_PARAMS *ossl_lm_ots_params_get(uint32_t ots_type);
|
||||||
|
|
||||||
LMS_KEY *ossl_lms_key_new(OSSL_LIB_CTX *libctx);
|
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);
|
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_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_valid(const LMS_KEY *key, int selection);
|
||||||
|
|
|
@ -23,24 +23,12 @@
|
||||||
#define HASH_NOT_MATCHED(a, b) \
|
#define HASH_NOT_MATCHED(a, b) \
|
||||||
(a)->n != (b)->n || (strcmp((a)->digestname, (b)->digestname) != 0)
|
(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)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See RFC 8554 Section 3.1.3: Strings of w-bit Elements
|
* See RFC 8554 Section 3.1.3: Strings of w-bit Elements
|
||||||
* w: Is one of {1,2,4,8}
|
* w: Is one of {1,2,4,8}
|
||||||
*/
|
*/
|
||||||
static ossl_unused ossl_inline
|
static ossl_unused ossl_inline
|
||||||
uint8_t coef(const unsigned char *S, uint16_t i, uint8_t w)
|
uint8_t lms_ots_coef(const unsigned char *S, uint16_t i, uint8_t w)
|
||||||
{
|
{
|
||||||
uint8_t bitmask = (1 << w) - 1;
|
uint8_t bitmask = (1 << w) - 1;
|
||||||
uint8_t shift = 8 - (w * (i % (8 / w)) + w);
|
uint8_t shift = 8 - (w * (i % (8 / w)) + w);
|
||||||
|
@ -50,8 +38,8 @@ uint8_t coef(const unsigned char *S, uint16_t i, uint8_t w)
|
||||||
}
|
}
|
||||||
|
|
||||||
static ossl_unused ossl_inline
|
static ossl_unused ossl_inline
|
||||||
int evp_md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *md,
|
int lms_evp_md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *md,
|
||||||
const LMS_PARAMS *lms_params)
|
const LMS_PARAMS *lms_params)
|
||||||
{
|
{
|
||||||
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
||||||
OSSL_PARAM *p = NULL;
|
OSSL_PARAM *p = NULL;
|
||||||
|
|
|
@ -31,8 +31,4 @@ typedef struct ecx_key_st ECX_KEY;
|
||||||
|
|
||||||
typedef struct prov_skey_st PROV_SKEY;
|
typedef struct prov_skey_st PROV_SKEY;
|
||||||
|
|
||||||
# ifndef OPENSSL_NO_LMS
|
|
||||||
typedef struct lms_key_st LMS_KEY;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -103,7 +103,7 @@ static const OSSL_ALGORITHM deflt_digests[] = {
|
||||||
{ PROV_NAMES_SHA1, "provider=default", ossl_sha1_functions },
|
{ PROV_NAMES_SHA1, "provider=default", ossl_sha1_functions },
|
||||||
{ PROV_NAMES_SHA2_224, "provider=default", ossl_sha224_functions },
|
{ PROV_NAMES_SHA2_224, "provider=default", ossl_sha224_functions },
|
||||||
{ PROV_NAMES_SHA2_256, "provider=default", ossl_sha256_functions },
|
{ PROV_NAMES_SHA2_256, "provider=default", ossl_sha256_functions },
|
||||||
{ PROV_NAMES_SHA2_256_192, "provider=default", ossl_sha256_192_functions },
|
{ PROV_NAMES_SHA2_256_192, "provider=default", ossl_sha256_192_internal_functions },
|
||||||
{ PROV_NAMES_SHA2_384, "provider=default", ossl_sha384_functions },
|
{ PROV_NAMES_SHA2_384, "provider=default", ossl_sha384_functions },
|
||||||
{ PROV_NAMES_SHA2_512, "provider=default", ossl_sha512_functions },
|
{ PROV_NAMES_SHA2_512, "provider=default", ossl_sha512_functions },
|
||||||
{ PROV_NAMES_SHA2_512_224, "provider=default", ossl_sha512_224_functions },
|
{ PROV_NAMES_SHA2_512_224, "provider=default", ossl_sha512_224_functions },
|
||||||
|
|
|
@ -295,7 +295,7 @@ static const OSSL_ALGORITHM fips_digests_internal[] = {
|
||||||
FIPS_DIGESTS_COMMON(),
|
FIPS_DIGESTS_COMMON(),
|
||||||
/* Used by LMS/HSS */
|
/* Used by LMS/HSS */
|
||||||
{ PROV_NAMES_SHA2_256_192, FIPS_DEFAULT_PROPERTIES,
|
{ PROV_NAMES_SHA2_256_192, FIPS_DEFAULT_PROPERTIES,
|
||||||
ossl_sha256_192_functions },
|
ossl_sha256_192_internal_functions },
|
||||||
/*
|
/*
|
||||||
* KECCAK-KMAC-128 and KECCAK-KMAC-256 as hashes are mostly useful for
|
* KECCAK-KMAC-128 and KECCAK-KMAC-256 as hashes are mostly useful for
|
||||||
* KMAC128 and KMAC256.
|
* KMAC128 and KMAC256.
|
||||||
|
|
|
@ -71,8 +71,8 @@ IMPLEMENT_digest_functions(sha224, SHA256_CTX,
|
||||||
IMPLEMENT_digest_functions(sha256, SHA256_CTX,
|
IMPLEMENT_digest_functions(sha256, SHA256_CTX,
|
||||||
SHA256_CBLOCK, SHA256_DIGEST_LENGTH, SHA2_FLAGS,
|
SHA256_CBLOCK, SHA256_DIGEST_LENGTH, SHA2_FLAGS,
|
||||||
SHA256_Init, SHA256_Update, SHA256_Final)
|
SHA256_Init, SHA256_Update, SHA256_Final)
|
||||||
/* ossl_sha256_192_functions */
|
/* ossl_sha256_192_internal_functions */
|
||||||
IMPLEMENT_digest_functions(sha256_192, SHA256_CTX,
|
IMPLEMENT_digest_functions(sha256_192_internal, SHA256_CTX,
|
||||||
SHA256_CBLOCK, SHA256_192_DIGEST_LENGTH, SHA2_FLAGS,
|
SHA256_CBLOCK, SHA256_192_DIGEST_LENGTH, SHA2_FLAGS,
|
||||||
ossl_sha256_192_init, SHA256_Update, SHA256_Final)
|
ossl_sha256_192_init, SHA256_Update, SHA256_Final)
|
||||||
/* ossl_sha384_functions */
|
/* ossl_sha384_functions */
|
||||||
|
|
|
@ -63,24 +63,33 @@ static int lmsxdr2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
|
||||||
LMS_KEY *key = NULL;
|
LMS_KEY *key = NULL;
|
||||||
unsigned char buf[LMS_MAX_PUBKEY];
|
unsigned char buf[LMS_MAX_PUBKEY];
|
||||||
size_t length;
|
size_t length;
|
||||||
int ok = 0;
|
int ok = 0, inlen, readlen;
|
||||||
BIO *in;
|
BIO *in;
|
||||||
|
|
||||||
in = ossl_bio_new_from_core_bio(ctx->provctx, cin);
|
in = ossl_bio_new_from_core_bio(ctx->provctx, cin);
|
||||||
if (in == NULL)
|
if (in == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ERR_set_mark();
|
|
||||||
ctx->selection = selection;
|
ctx->selection = selection;
|
||||||
|
|
||||||
/* Read the header to determine the size */
|
/* Read the header to determine the size */
|
||||||
if (BIO_read(in, buf, 4) != 4)
|
ERR_set_mark();
|
||||||
|
readlen = BIO_read(in, buf, 4);
|
||||||
|
ERR_pop_to_mark();
|
||||||
|
if (readlen != 4)
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
length = ossl_lms_pubkey_length(buf, 4);
|
length = ossl_lms_pubkey_length(buf, 4);
|
||||||
if (length == 0)
|
if (length <= 4)
|
||||||
goto next;
|
goto next;
|
||||||
if (BIO_read(in, buf + 4, length - 4) != (int)(length - 4))
|
inlen = (int)length - 4;
|
||||||
|
|
||||||
|
ERR_set_mark();
|
||||||
|
readlen = BIO_read(in, buf + 4, inlen);
|
||||||
|
ERR_pop_to_mark();
|
||||||
|
if (readlen != inlen)
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
if (selection == 0 || (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
|
if (selection == 0 || (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
|
||||||
key = ossl_lms_key_new(PROV_LIBCTX_OF(ctx->provctx));
|
key = ossl_lms_key_new(PROV_LIBCTX_OF(ctx->provctx));
|
||||||
if (key == NULL || !ossl_lms_pubkey_decode(buf, length, key)) {
|
if (key == NULL || !ossl_lms_pubkey_decode(buf, length, key)) {
|
||||||
|
@ -89,7 +98,6 @@ static int lmsxdr2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
next:
|
next:
|
||||||
ERR_clear_last_mark();
|
|
||||||
/*
|
/*
|
||||||
* Indicated that we successfully decoded something, or not at all.
|
* Indicated that we successfully decoded something, or not at all.
|
||||||
* Ending up "empty handed" is not an error.
|
* Ending up "empty handed" is not an error.
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
extern const OSSL_DISPATCH ossl_sha1_functions[];
|
extern const OSSL_DISPATCH ossl_sha1_functions[];
|
||||||
extern const OSSL_DISPATCH ossl_sha224_functions[];
|
extern const OSSL_DISPATCH ossl_sha224_functions[];
|
||||||
extern const OSSL_DISPATCH ossl_sha256_functions[];
|
extern const OSSL_DISPATCH ossl_sha256_functions[];
|
||||||
extern const OSSL_DISPATCH ossl_sha256_192_functions[];
|
extern const OSSL_DISPATCH ossl_sha256_192_internal_functions[];
|
||||||
extern const OSSL_DISPATCH ossl_sha384_functions[];
|
extern const OSSL_DISPATCH ossl_sha384_functions[];
|
||||||
extern const OSSL_DISPATCH ossl_sha512_functions[];
|
extern const OSSL_DISPATCH ossl_sha512_functions[];
|
||||||
extern const OSSL_DISPATCH ossl_sha512_224_functions[];
|
extern const OSSL_DISPATCH ossl_sha512_224_functions[];
|
||||||
|
|
|
@ -60,8 +60,6 @@ static int lms_match(const void *keydata1, const void *keydata2, int selection)
|
||||||
|
|
||||||
if (!ossl_prov_is_running())
|
if (!ossl_prov_is_running())
|
||||||
return 0;
|
return 0;
|
||||||
if (key1 == NULL || key2 == NULL)
|
|
||||||
return 0;
|
|
||||||
return ossl_lms_key_equal(key1, key2, selection);
|
return ossl_lms_key_equal(key1, key2, selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <openssl/proverr.h>
|
#include <openssl/proverr.h>
|
||||||
#include <openssl/params.h>
|
#include <openssl/params.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
#include "prov/providercommon.h"
|
#include "prov/providercommon.h"
|
||||||
#include "prov/provider_ctx.h"
|
#include "prov/provider_ctx.h"
|
||||||
#include "prov/implementations.h"
|
#include "prov/implementations.h"
|
||||||
|
@ -56,7 +57,6 @@ static void lms_freectx(void *vctx)
|
||||||
|
|
||||||
if (ctx == NULL)
|
if (ctx == NULL)
|
||||||
return;
|
return;
|
||||||
ossl_lms_key_free(ctx->key);
|
|
||||||
OPENSSL_free(ctx->propq);
|
OPENSSL_free(ctx->propq);
|
||||||
EVP_MD_free(ctx->md);
|
EVP_MD_free(ctx->md);
|
||||||
OPENSSL_free(ctx);
|
OPENSSL_free(ctx);
|
||||||
|
@ -97,14 +97,8 @@ static int lms_verify_msg_init(void *vctx, void *vkey, const OSSL_PARAM params[]
|
||||||
ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
|
ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ossl_lms_key_up_ref(key))
|
|
||||||
return 0;
|
|
||||||
ossl_lms_key_free(ctx->key);
|
|
||||||
ctx->key = key;
|
ctx->key = key;
|
||||||
if (!setdigest(ctx, NULL))
|
return setdigest(ctx, NULL);
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lms_verify(void *vctx, const unsigned char *sigbuf, size_t sigbuf_len,
|
static int lms_verify(void *vctx, const unsigned char *sigbuf, size_t sigbuf_len,
|
||||||
|
|
|
@ -151,7 +151,7 @@ static EVP_PKEY *key_decode_from_data(const unsigned char *data, size_t datalen,
|
||||||
BIO *bio;
|
BIO *bio;
|
||||||
EVP_PKEY *key = NULL;
|
EVP_PKEY *key = NULL;
|
||||||
|
|
||||||
if (!TEST_ptr(bio = BIO_new_mem_buf(data, datalen)))
|
if (!TEST_ptr(bio = BIO_new_mem_buf(data, (int)datalen)))
|
||||||
return NULL;
|
return NULL;
|
||||||
key = key_decode_from_bio(bio, keytype);
|
key = key_decode_from_bio(bio, keytype);
|
||||||
BIO_free(bio);
|
BIO_free(bio);
|
||||||
|
|
Loading…
Reference in New Issue