mirror of https://github.com/openssl/openssl.git
134 lines
4.4 KiB
C
134 lines
4.4 KiB
C
/*
|
|
* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
|
|
*
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
* in the file LICENSE in the source distribution or at
|
|
* https://www.openssl.org/source/license.html
|
|
*/
|
|
|
|
#include <openssl/core_names.h>
|
|
#include "crypto/lms.h"
|
|
#include "crypto/lms_util.h"
|
|
|
|
/**
|
|
* @brief 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_net_4_len_u32(&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(LMS_KEY *lmskey, const unsigned char *pubkeydata,
|
|
size_t publen)
|
|
{
|
|
uint32_t lms_type;
|
|
uint32_t ots_type;
|
|
LMS_PUB_KEY *key = &lmskey->pub;
|
|
PACKET pkt;
|
|
|
|
if (!PACKET_buf_init(&pkt, pubkeydata, publen))
|
|
goto err;
|
|
key->encoded = (unsigned char *)PACKET_data(&pkt);
|
|
if (!PACKET_get_net_4_len_u32(&pkt, &lms_type))
|
|
goto err;
|
|
lmskey->lms_params = ossl_lms_params_get(lms_type);
|
|
if (lmskey->lms_params == NULL
|
|
|| !PACKET_get_net_4_len_u32(&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(&pkt, (const unsigned char **)&lmskey->Id,
|
|
LMS_SIZE_I)
|
|
|| !PACKET_get_bytes(&pkt, (const unsigned char **)&key->K,
|
|
lmskey->lms_params->n))
|
|
goto err;
|
|
key->encodedlen = (unsigned char *)PACKET_data(&pkt) - key->encoded;
|
|
return PACKET_remaining(&pkt) == 0;
|
|
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)
|
|
{
|
|
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 (!lms_pubkey_from_pkt(lmskey, pkey->encoded, publen))
|
|
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 *pub, LMS_KEY *lmskey)
|
|
{
|
|
if (pub != NULL) {
|
|
if (pub->data == NULL
|
|
|| pub->data_type != OSSL_PARAM_OCTET_STRING
|
|
|| !ossl_lms_pubkey_decode(pub->data, pub->data_size, lmskey))
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|