Reviewed-by: Hugo Landau <hlandau@devever.net> Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com> Reviewed-by: Paul Dale <ppzgs1@gmail.com> (Merged from https://github.com/openssl/openssl/pull/25598)
103 lines
3.3 KiB
C
103 lines
3.3 KiB
C
/*
|
|
* 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;
|
|
}
|