Delete unused files of thirparty libs (zlib, mbedtls)
Signed-off-by: Yevhen Babiichuk (DustDFG) <dfgdust@gmail.com>
This commit is contained in:
394
thirdparty/mbedtls/library/bignum_mod.c
vendored
394
thirdparty/mbedtls/library/bignum_mod.c
vendored
@ -1,394 +0,0 @@
|
||||
/**
|
||||
* Modular bignum functions
|
||||
*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/bignum.h"
|
||||
|
||||
#include "mbedtls/platform.h"
|
||||
|
||||
#include "bignum_core.h"
|
||||
#include "bignum_mod.h"
|
||||
#include "bignum_mod_raw.h"
|
||||
#include "constant_time_internal.h"
|
||||
|
||||
int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r,
|
||||
const mbedtls_mpi_mod_modulus *N,
|
||||
mbedtls_mpi_uint *p,
|
||||
size_t p_limbs)
|
||||
{
|
||||
if (p_limbs != N->limbs || !mbedtls_mpi_core_lt_ct(p, N->p, N->limbs)) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
r->limbs = N->limbs;
|
||||
r->p = p;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r)
|
||||
{
|
||||
if (r == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
r->limbs = 0;
|
||||
r->p = NULL;
|
||||
}
|
||||
|
||||
void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N)
|
||||
{
|
||||
if (N == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
N->p = NULL;
|
||||
N->limbs = 0;
|
||||
N->bits = 0;
|
||||
N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
|
||||
}
|
||||
|
||||
void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N)
|
||||
{
|
||||
if (N == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (N->int_rep) {
|
||||
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
|
||||
if (N->rep.mont.rr != NULL) {
|
||||
mbedtls_zeroize_and_free((mbedtls_mpi_uint *) N->rep.mont.rr,
|
||||
N->limbs * sizeof(mbedtls_mpi_uint));
|
||||
N->rep.mont.rr = NULL;
|
||||
}
|
||||
N->rep.mont.mm = 0;
|
||||
break;
|
||||
case MBEDTLS_MPI_MOD_REP_OPT_RED:
|
||||
N->rep.ored.modp = NULL;
|
||||
break;
|
||||
case MBEDTLS_MPI_MOD_REP_INVALID:
|
||||
break;
|
||||
}
|
||||
|
||||
N->p = NULL;
|
||||
N->limbs = 0;
|
||||
N->bits = 0;
|
||||
N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
|
||||
}
|
||||
|
||||
static int set_mont_const_square(const mbedtls_mpi_uint **X,
|
||||
const mbedtls_mpi_uint *A,
|
||||
size_t limbs)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
mbedtls_mpi N;
|
||||
mbedtls_mpi RR;
|
||||
*X = NULL;
|
||||
|
||||
mbedtls_mpi_init(&N);
|
||||
mbedtls_mpi_init(&RR);
|
||||
|
||||
if (A == NULL || limbs == 0 || limbs >= (MBEDTLS_MPI_MAX_LIMBS / 2) - 2) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (mbedtls_mpi_grow(&N, limbs)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
memcpy(N.p, A, sizeof(mbedtls_mpi_uint) * limbs);
|
||||
|
||||
ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N);
|
||||
|
||||
if (ret == 0) {
|
||||
*X = RR.p;
|
||||
RR.p = NULL;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&N);
|
||||
mbedtls_mpi_free(&RR);
|
||||
ret = (ret != 0) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void standard_modulus_setup(mbedtls_mpi_mod_modulus *N,
|
||||
const mbedtls_mpi_uint *p,
|
||||
size_t p_limbs,
|
||||
mbedtls_mpi_mod_rep_selector int_rep)
|
||||
{
|
||||
N->p = p;
|
||||
N->limbs = p_limbs;
|
||||
N->bits = mbedtls_mpi_core_bitlen(p, p_limbs);
|
||||
N->int_rep = int_rep;
|
||||
}
|
||||
|
||||
int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
|
||||
const mbedtls_mpi_uint *p,
|
||||
size_t p_limbs)
|
||||
{
|
||||
int ret = 0;
|
||||
standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_MONTGOMERY);
|
||||
N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p);
|
||||
ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs);
|
||||
|
||||
if (ret != 0) {
|
||||
mbedtls_mpi_mod_modulus_free(N);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N,
|
||||
const mbedtls_mpi_uint *p,
|
||||
size_t p_limbs,
|
||||
mbedtls_mpi_modp_fn modp)
|
||||
{
|
||||
standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_OPT_RED);
|
||||
N->rep.ored.modp = modp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,
|
||||
const mbedtls_mpi_mod_residue *A,
|
||||
const mbedtls_mpi_mod_residue *B,
|
||||
const mbedtls_mpi_mod_modulus *N)
|
||||
{
|
||||
if (N->limbs == 0) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
mbedtls_mpi_uint *T = mbedtls_calloc(N->limbs * 2 + 1, ciL);
|
||||
if (T == NULL) {
|
||||
return MBEDTLS_ERR_MPI_ALLOC_FAILED;
|
||||
}
|
||||
|
||||
mbedtls_mpi_mod_raw_mul(X->p, A->p, B->p, N, T);
|
||||
|
||||
mbedtls_free(T);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X,
|
||||
const mbedtls_mpi_mod_residue *A,
|
||||
const mbedtls_mpi_mod_residue *B,
|
||||
const mbedtls_mpi_mod_modulus *N)
|
||||
{
|
||||
if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
mbedtls_mpi_mod_raw_sub(X->p, A->p, B->p, N);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mbedtls_mpi_mod_inv_mont(mbedtls_mpi_mod_residue *X,
|
||||
const mbedtls_mpi_mod_residue *A,
|
||||
const mbedtls_mpi_mod_modulus *N,
|
||||
mbedtls_mpi_uint *working_memory)
|
||||
{
|
||||
/* Input already in Montgomery form, so there's little to do */
|
||||
mbedtls_mpi_mod_raw_inv_prime(X->p, A->p,
|
||||
N->p, N->limbs,
|
||||
N->rep.mont.rr,
|
||||
working_memory);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue *X,
|
||||
const mbedtls_mpi_mod_residue *A,
|
||||
const mbedtls_mpi_mod_modulus *N,
|
||||
mbedtls_mpi_uint *working_memory)
|
||||
{
|
||||
/* Need to convert input into Montgomery form */
|
||||
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
mbedtls_mpi_mod_modulus Nmont;
|
||||
mbedtls_mpi_mod_modulus_init(&Nmont);
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs));
|
||||
|
||||
/* We'll use X->p to hold the Montgomery form of the input A->p */
|
||||
mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs,
|
||||
Nmont.rep.mont.mm, Nmont.rep.mont.rr,
|
||||
working_memory);
|
||||
|
||||
mbedtls_mpi_mod_raw_inv_prime(X->p, X->p,
|
||||
Nmont.p, Nmont.limbs,
|
||||
Nmont.rep.mont.rr,
|
||||
working_memory);
|
||||
|
||||
/* And convert back from Montgomery form */
|
||||
|
||||
mbedtls_mpi_core_from_mont_rep(X->p, X->p, Nmont.p, Nmont.limbs,
|
||||
Nmont.rep.mont.mm, working_memory);
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_mod_modulus_free(&Nmont);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,
|
||||
const mbedtls_mpi_mod_residue *A,
|
||||
const mbedtls_mpi_mod_modulus *N)
|
||||
{
|
||||
if (X->limbs != N->limbs || A->limbs != N->limbs) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* Zero has the same value regardless of Montgomery form or not */
|
||||
if (mbedtls_mpi_core_check_zero_ct(A->p, A->limbs) == 0) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
size_t working_limbs =
|
||||
mbedtls_mpi_mod_raw_inv_prime_working_limbs(N->limbs);
|
||||
|
||||
mbedtls_mpi_uint *working_memory = mbedtls_calloc(working_limbs,
|
||||
sizeof(mbedtls_mpi_uint));
|
||||
if (working_memory == NULL) {
|
||||
return MBEDTLS_ERR_MPI_ALLOC_FAILED;
|
||||
}
|
||||
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
switch (N->int_rep) {
|
||||
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
|
||||
ret = mbedtls_mpi_mod_inv_mont(X, A, N, working_memory);
|
||||
break;
|
||||
case MBEDTLS_MPI_MOD_REP_OPT_RED:
|
||||
ret = mbedtls_mpi_mod_inv_non_mont(X, A, N, working_memory);
|
||||
break;
|
||||
default:
|
||||
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
mbedtls_zeroize_and_free(working_memory,
|
||||
working_limbs * sizeof(mbedtls_mpi_uint));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,
|
||||
const mbedtls_mpi_mod_residue *A,
|
||||
const mbedtls_mpi_mod_residue *B,
|
||||
const mbedtls_mpi_mod_modulus *N)
|
||||
{
|
||||
if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,
|
||||
mbedtls_mpi_uint min,
|
||||
const mbedtls_mpi_mod_modulus *N,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng)
|
||||
{
|
||||
if (X->limbs != N->limbs) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
return mbedtls_mpi_mod_raw_random(X->p, min, N, f_rng, p_rng);
|
||||
}
|
||||
|
||||
int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r,
|
||||
const mbedtls_mpi_mod_modulus *N,
|
||||
const unsigned char *buf,
|
||||
size_t buflen,
|
||||
mbedtls_mpi_mod_ext_rep ext_rep)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
|
||||
/* Do our best to check if r and m have been set up */
|
||||
if (r->limbs == 0 || N->limbs == 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (r->limbs != N->limbs) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = mbedtls_mpi_mod_raw_read(r->p, N, buf, buflen, ext_rep);
|
||||
if (ret != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
r->limbs = N->limbs;
|
||||
|
||||
ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep(r->p, N);
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r,
|
||||
const mbedtls_mpi_mod_modulus *N,
|
||||
unsigned char *buf,
|
||||
size_t buflen,
|
||||
mbedtls_mpi_mod_ext_rep ext_rep)
|
||||
{
|
||||
/* Do our best to check if r and m have been set up */
|
||||
if (r->limbs == 0 || N->limbs == 0) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
if (r->limbs != N->limbs) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
mbedtls_mpi_uint *working_memory = r->p;
|
||||
size_t working_memory_len = sizeof(mbedtls_mpi_uint) * r->limbs;
|
||||
|
||||
if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
|
||||
|
||||
working_memory = mbedtls_calloc(r->limbs, sizeof(mbedtls_mpi_uint));
|
||||
|
||||
if (working_memory == NULL) {
|
||||
ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
memcpy(working_memory, r->p, working_memory_len);
|
||||
|
||||
ret = mbedtls_mpi_mod_raw_from_mont_rep(working_memory, N);
|
||||
if (ret != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mbedtls_mpi_mod_raw_write(working_memory, N, buf, buflen, ext_rep);
|
||||
|
||||
cleanup:
|
||||
|
||||
if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY &&
|
||||
working_memory != NULL) {
|
||||
|
||||
mbedtls_zeroize_and_free(working_memory, working_memory_len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */
|
||||
207
thirdparty/mbedtls/library/block_cipher.c
vendored
207
thirdparty/mbedtls/library/block_cipher.c
vendored
@ -1,207 +0,0 @@
|
||||
/**
|
||||
* \file block_cipher.c
|
||||
*
|
||||
* \brief Lightweight abstraction layer for block ciphers with 128 bit blocks,
|
||||
* for use by the GCM and CCM modules.
|
||||
*/
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_core.h"
|
||||
#include "psa_util_internal.h"
|
||||
#endif
|
||||
|
||||
#include "block_cipher_internal.h"
|
||||
|
||||
#if defined(MBEDTLS_BLOCK_CIPHER_C)
|
||||
|
||||
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
|
||||
static psa_key_type_t psa_key_type_from_block_cipher_id(mbedtls_block_cipher_id_t cipher_id)
|
||||
{
|
||||
switch (cipher_id) {
|
||||
#if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_AES:
|
||||
return PSA_KEY_TYPE_AES;
|
||||
#endif
|
||||
#if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
|
||||
return PSA_KEY_TYPE_ARIA;
|
||||
#endif
|
||||
#if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
|
||||
return PSA_KEY_TYPE_CAMELLIA;
|
||||
#endif
|
||||
default:
|
||||
return PSA_KEY_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static int mbedtls_cipher_error_from_psa(psa_status_t status)
|
||||
{
|
||||
return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_cipher_errors,
|
||||
psa_generic_status_to_mbedtls);
|
||||
}
|
||||
#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */
|
||||
|
||||
void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
|
||||
if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {
|
||||
psa_destroy_key(ctx->psa_key_id);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
switch (ctx->id) {
|
||||
#if defined(MBEDTLS_AES_C)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_AES:
|
||||
mbedtls_aes_free(&ctx->ctx.aes);
|
||||
break;
|
||||
#endif
|
||||
#if defined(MBEDTLS_ARIA_C)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
|
||||
mbedtls_aria_free(&ctx->ctx.aria);
|
||||
break;
|
||||
#endif
|
||||
#if defined(MBEDTLS_CAMELLIA_C)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
|
||||
mbedtls_camellia_free(&ctx->ctx.camellia);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE;
|
||||
}
|
||||
|
||||
int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx,
|
||||
mbedtls_cipher_id_t cipher_id)
|
||||
{
|
||||
ctx->id = (cipher_id == MBEDTLS_CIPHER_ID_AES) ? MBEDTLS_BLOCK_CIPHER_ID_AES :
|
||||
(cipher_id == MBEDTLS_CIPHER_ID_ARIA) ? MBEDTLS_BLOCK_CIPHER_ID_ARIA :
|
||||
(cipher_id == MBEDTLS_CIPHER_ID_CAMELLIA) ? MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA :
|
||||
MBEDTLS_BLOCK_CIPHER_ID_NONE;
|
||||
|
||||
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
|
||||
psa_key_type_t psa_key_type = psa_key_type_from_block_cipher_id(ctx->id);
|
||||
if (psa_key_type != PSA_KEY_TYPE_NONE &&
|
||||
psa_can_do_cipher(psa_key_type, PSA_ALG_ECB_NO_PADDING)) {
|
||||
ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_PSA;
|
||||
return 0;
|
||||
}
|
||||
ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY;
|
||||
#endif
|
||||
|
||||
switch (ctx->id) {
|
||||
#if defined(MBEDTLS_AES_C)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_AES:
|
||||
mbedtls_aes_init(&ctx->ctx.aes);
|
||||
return 0;
|
||||
#endif
|
||||
#if defined(MBEDTLS_ARIA_C)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
|
||||
mbedtls_aria_init(&ctx->ctx.aria);
|
||||
return 0;
|
||||
#endif
|
||||
#if defined(MBEDTLS_CAMELLIA_C)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
|
||||
mbedtls_camellia_init(&ctx->ctx.camellia);
|
||||
return 0;
|
||||
#endif
|
||||
default:
|
||||
ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE;
|
||||
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx,
|
||||
const unsigned char *key,
|
||||
unsigned key_bitlen)
|
||||
{
|
||||
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
|
||||
if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {
|
||||
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_status_t status;
|
||||
|
||||
psa_set_key_type(&key_attr, psa_key_type_from_block_cipher_id(ctx->id));
|
||||
psa_set_key_bits(&key_attr, key_bitlen);
|
||||
psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);
|
||||
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT);
|
||||
|
||||
status = psa_import_key(&key_attr, key, PSA_BITS_TO_BYTES(key_bitlen), &ctx->psa_key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return mbedtls_cipher_error_from_psa(status);
|
||||
}
|
||||
psa_reset_key_attributes(&key_attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */
|
||||
|
||||
switch (ctx->id) {
|
||||
#if defined(MBEDTLS_AES_C)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_AES:
|
||||
return mbedtls_aes_setkey_enc(&ctx->ctx.aes, key, key_bitlen);
|
||||
#endif
|
||||
#if defined(MBEDTLS_ARIA_C)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
|
||||
return mbedtls_aria_setkey_enc(&ctx->ctx.aria, key, key_bitlen);
|
||||
#endif
|
||||
#if defined(MBEDTLS_CAMELLIA_C)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
|
||||
return mbedtls_camellia_setkey_enc(&ctx->ctx.camellia, key, key_bitlen);
|
||||
#endif
|
||||
default:
|
||||
return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16])
|
||||
{
|
||||
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
|
||||
if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {
|
||||
psa_status_t status;
|
||||
size_t olen;
|
||||
|
||||
status = psa_cipher_encrypt(ctx->psa_key_id, PSA_ALG_ECB_NO_PADDING,
|
||||
input, 16, output, 16, &olen);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return mbedtls_cipher_error_from_psa(status);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */
|
||||
|
||||
switch (ctx->id) {
|
||||
#if defined(MBEDTLS_AES_C)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_AES:
|
||||
return mbedtls_aes_crypt_ecb(&ctx->ctx.aes, MBEDTLS_AES_ENCRYPT,
|
||||
input, output);
|
||||
#endif
|
||||
#if defined(MBEDTLS_ARIA_C)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
|
||||
return mbedtls_aria_crypt_ecb(&ctx->ctx.aria, input, output);
|
||||
#endif
|
||||
#if defined(MBEDTLS_CAMELLIA_C)
|
||||
case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
|
||||
return mbedtls_camellia_crypt_ecb(&ctx->ctx.camellia,
|
||||
MBEDTLS_CAMELLIA_ENCRYPT,
|
||||
input, output);
|
||||
#endif
|
||||
default:
|
||||
return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_BLOCK_CIPHER_C */
|
||||
6036
thirdparty/mbedtls/library/ecp_curves_new.c
vendored
6036
thirdparty/mbedtls/library/ecp_curves_new.c
vendored
File diff suppressed because it is too large
Load Diff
786
thirdparty/mbedtls/library/lmots.c
vendored
786
thirdparty/mbedtls/library/lmots.c
vendored
@ -1,786 +0,0 @@
|
||||
/*
|
||||
* The LM-OTS one-time public-key signature scheme
|
||||
*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following sources were referenced in the design of this implementation
|
||||
* of the LM-OTS algorithm:
|
||||
*
|
||||
* [1] IETF RFC8554
|
||||
* D. McGrew, M. Curcio, S.Fluhrer
|
||||
* https://datatracker.ietf.org/doc/html/rfc8554
|
||||
*
|
||||
* [2] NIST Special Publication 800-208
|
||||
* David A. Cooper et. al.
|
||||
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(MBEDTLS_LMS_C)
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lmots.h"
|
||||
|
||||
#include "mbedtls/lms.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "psa_util_internal.h"
|
||||
|
||||
#include "psa/crypto.h"
|
||||
|
||||
/* Define a local translating function to save code size by not using too many
|
||||
* arguments in each translating place. */
|
||||
static int local_err_translation(psa_status_t status)
|
||||
{
|
||||
return psa_status_to_mbedtls(status, psa_to_lms_errors,
|
||||
ARRAY_LENGTH(psa_to_lms_errors),
|
||||
psa_generic_status_to_mbedtls);
|
||||
}
|
||||
#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
|
||||
|
||||
#define PUBLIC_KEY_TYPE_OFFSET (0)
|
||||
#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \
|
||||
MBEDTLS_LMOTS_TYPE_LEN)
|
||||
#define PUBLIC_KEY_Q_LEAF_ID_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \
|
||||
MBEDTLS_LMOTS_I_KEY_ID_LEN)
|
||||
#define PUBLIC_KEY_KEY_HASH_OFFSET (PUBLIC_KEY_Q_LEAF_ID_OFFSET + \
|
||||
MBEDTLS_LMOTS_Q_LEAF_ID_LEN)
|
||||
|
||||
/* We only support parameter sets that use 8-bit digits, as it does not require
|
||||
* translation logic between digits and bytes */
|
||||
#define W_WINTERNITZ_PARAMETER (8u)
|
||||
#define CHECKSUM_LEN (2)
|
||||
#define I_DIGIT_IDX_LEN (2)
|
||||
#define J_HASH_IDX_LEN (1)
|
||||
#define D_CONST_LEN (2)
|
||||
|
||||
#define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u)
|
||||
|
||||
#define D_CONST_LEN (2)
|
||||
static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = { 0x80, 0x80 };
|
||||
static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = { 0x81, 0x81 };
|
||||
|
||||
#if defined(MBEDTLS_TEST_HOOKS)
|
||||
int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *) = NULL;
|
||||
#endif /* defined(MBEDTLS_TEST_HOOKS) */
|
||||
|
||||
/* Calculate the checksum digits that are appended to the end of the LMOTS digit
|
||||
* string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of
|
||||
* the checksum algorithm.
|
||||
*
|
||||
* params The LMOTS parameter set, I and q values which
|
||||
* describe the key being used.
|
||||
*
|
||||
* digest The digit string to create the digest from. As
|
||||
* this does not contain a checksum, it is the same
|
||||
* size as a hash output.
|
||||
*/
|
||||
static unsigned short lmots_checksum_calculate(const mbedtls_lmots_parameters_t *params,
|
||||
const unsigned char *digest)
|
||||
{
|
||||
size_t idx;
|
||||
unsigned sum = 0;
|
||||
|
||||
for (idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN(params->type); idx++) {
|
||||
sum += DIGIT_MAX_VALUE - digest[idx];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* Create the string of digest digits (in the base determined by the Winternitz
|
||||
* parameter with the checksum appended to the end (Q || cksm(Q)). See NIST
|
||||
* SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm
|
||||
* 4b step 3) for details.
|
||||
*
|
||||
* params The LMOTS parameter set, I and q values which
|
||||
* describe the key being used.
|
||||
*
|
||||
* msg The message that will be hashed to create the
|
||||
* digest.
|
||||
*
|
||||
* msg_size The size of the message.
|
||||
*
|
||||
* C_random_value The random value that will be combined with the
|
||||
* message digest. This is always the same size as a
|
||||
* hash output for whichever hash algorithm is
|
||||
* determined by the parameter set.
|
||||
*
|
||||
* output An output containing the digit string (+
|
||||
* checksum) of length P digits (in the case of
|
||||
* MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of
|
||||
* size P bytes).
|
||||
*/
|
||||
static int create_digit_array_with_checksum(const mbedtls_lmots_parameters_t *params,
|
||||
const unsigned char *msg,
|
||||
size_t msg_len,
|
||||
const unsigned char *C_random_value,
|
||||
unsigned char *out)
|
||||
{
|
||||
psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
size_t output_hash_len;
|
||||
unsigned short checksum;
|
||||
|
||||
status = psa_hash_setup(&op, PSA_ALG_SHA_256);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, params->I_key_identifier,
|
||||
MBEDTLS_LMOTS_I_KEY_ID_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, params->q_leaf_identifier,
|
||||
MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, C_random_value,
|
||||
MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type));
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, msg, msg_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_finish(&op, out,
|
||||
MBEDTLS_LMOTS_N_HASH_LEN(params->type),
|
||||
&output_hash_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
checksum = lmots_checksum_calculate(params, out);
|
||||
MBEDTLS_PUT_UINT16_BE(checksum, out, MBEDTLS_LMOTS_N_HASH_LEN(params->type));
|
||||
|
||||
exit:
|
||||
psa_hash_abort(&op);
|
||||
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
|
||||
/* Hash each element of the string of digits (+ checksum), producing a hash
|
||||
* output for each element. This is used in several places (by varying the
|
||||
* hash_idx_min/max_values) in order to calculate a public key from a private
|
||||
* key (RFC8554 Algorithm 1 step 4), in order to sign a message (RFC8554
|
||||
* Algorithm 3 step 5), and to calculate a public key candidate from a
|
||||
* signature and message (RFC8554 Algorithm 4b step 3).
|
||||
*
|
||||
* params The LMOTS parameter set, I and q values which
|
||||
* describe the key being used.
|
||||
*
|
||||
* x_digit_array The array of digits (of size P, 34 in the case of
|
||||
* MBEDTLS_LMOTS_SHA256_N32_W8).
|
||||
*
|
||||
* hash_idx_min_values An array of the starting values of the j iterator
|
||||
* for each of the members of the digit array. If
|
||||
* this value in NULL, then all iterators will start
|
||||
* at 0.
|
||||
*
|
||||
* hash_idx_max_values An array of the upper bound values of the j
|
||||
* iterator for each of the members of the digit
|
||||
* array. If this value in NULL, then iterator is
|
||||
* bounded to be less than 2^w - 1 (255 in the case
|
||||
* of MBEDTLS_LMOTS_SHA256_N32_W8)
|
||||
*
|
||||
* output An array containing a hash output for each member
|
||||
* of the digit string P. In the case of
|
||||
* MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 *
|
||||
* 34.
|
||||
*/
|
||||
static int hash_digit_array(const mbedtls_lmots_parameters_t *params,
|
||||
const unsigned char *x_digit_array,
|
||||
const unsigned char *hash_idx_min_values,
|
||||
const unsigned char *hash_idx_max_values,
|
||||
unsigned char *output)
|
||||
{
|
||||
unsigned int i_digit_idx;
|
||||
unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN];
|
||||
unsigned int j_hash_idx;
|
||||
unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN];
|
||||
unsigned int j_hash_idx_min;
|
||||
unsigned int j_hash_idx_max;
|
||||
psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
size_t output_hash_len;
|
||||
unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
|
||||
|
||||
for (i_digit_idx = 0;
|
||||
i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type);
|
||||
i_digit_idx++) {
|
||||
|
||||
memcpy(tmp_hash,
|
||||
&x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)],
|
||||
MBEDTLS_LMOTS_N_HASH_LEN(params->type));
|
||||
|
||||
j_hash_idx_min = hash_idx_min_values != NULL ?
|
||||
hash_idx_min_values[i_digit_idx] : 0;
|
||||
j_hash_idx_max = hash_idx_max_values != NULL ?
|
||||
hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE;
|
||||
|
||||
for (j_hash_idx = j_hash_idx_min;
|
||||
j_hash_idx < j_hash_idx_max;
|
||||
j_hash_idx++) {
|
||||
status = psa_hash_setup(&op, PSA_ALG_SHA_256);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op,
|
||||
params->I_key_identifier,
|
||||
MBEDTLS_LMOTS_I_KEY_ID_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op,
|
||||
params->q_leaf_identifier,
|
||||
MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0);
|
||||
status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
j_hash_idx_bytes[0] = (uint8_t) j_hash_idx;
|
||||
status = psa_hash_update(&op, j_hash_idx_bytes, J_HASH_IDX_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, tmp_hash,
|
||||
MBEDTLS_LMOTS_N_HASH_LEN(params->type));
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_finish(&op, tmp_hash, sizeof(tmp_hash),
|
||||
&output_hash_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
psa_hash_abort(&op);
|
||||
}
|
||||
|
||||
memcpy(&output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)],
|
||||
tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type));
|
||||
}
|
||||
|
||||
exit:
|
||||
psa_hash_abort(&op);
|
||||
mbedtls_platform_zeroize(tmp_hash, sizeof(tmp_hash));
|
||||
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
|
||||
/* Combine the hashes of the digit array into a public key. This is used in
|
||||
* in order to calculate a public key from a private key (RFC8554 Algorithm 1
|
||||
* step 4), and to calculate a public key candidate from a signature and message
|
||||
* (RFC8554 Algorithm 4b step 3).
|
||||
*
|
||||
* params The LMOTS parameter set, I and q values which describe
|
||||
* the key being used.
|
||||
* y_hashed_digits The array of hashes, one hash for each digit of the
|
||||
* symbol array (which is of size P, 34 in the case of
|
||||
* MBEDTLS_LMOTS_SHA256_N32_W8)
|
||||
*
|
||||
* pub_key The output public key (or candidate public key in
|
||||
* case this is being run as part of signature
|
||||
* verification), in the form of a hash output.
|
||||
*/
|
||||
static int public_key_from_hashed_digit_array(const mbedtls_lmots_parameters_t *params,
|
||||
const unsigned char *y_hashed_digits,
|
||||
unsigned char *pub_key)
|
||||
{
|
||||
psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
size_t output_hash_len;
|
||||
|
||||
status = psa_hash_setup(&op, PSA_ALG_SHA_256);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op,
|
||||
params->I_key_identifier,
|
||||
MBEDTLS_LMOTS_I_KEY_ID_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, params->q_leaf_identifier,
|
||||
MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, y_hashed_digits,
|
||||
MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) *
|
||||
MBEDTLS_LMOTS_N_HASH_LEN(params->type));
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_finish(&op, pub_key,
|
||||
MBEDTLS_LMOTS_N_HASH_LEN(params->type),
|
||||
&output_hash_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
|
||||
exit:
|
||||
psa_hash_abort(&op);
|
||||
}
|
||||
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
int mbedtls_lms_error_from_psa(psa_status_t status)
|
||||
{
|
||||
switch (status) {
|
||||
case PSA_SUCCESS:
|
||||
return 0;
|
||||
case PSA_ERROR_HARDWARE_FAILURE:
|
||||
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
|
||||
case PSA_ERROR_NOT_SUPPORTED:
|
||||
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
|
||||
case PSA_ERROR_BUFFER_TOO_SMALL:
|
||||
return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
|
||||
case PSA_ERROR_INVALID_ARGUMENT:
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
default:
|
||||
return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
|
||||
}
|
||||
}
|
||||
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
|
||||
|
||||
void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
mbedtls_platform_zeroize(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx,
|
||||
const unsigned char *key, size_t key_len)
|
||||
{
|
||||
if (key_len < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
ctx->params.type = (mbedtls_lmots_algorithm_type_t)
|
||||
MBEDTLS_GET_UINT32_BE(key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
|
||||
|
||||
if (key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
memcpy(ctx->params.I_key_identifier,
|
||||
key + PUBLIC_KEY_I_KEY_ID_OFFSET,
|
||||
MBEDTLS_LMOTS_I_KEY_ID_LEN);
|
||||
|
||||
memcpy(ctx->params.q_leaf_identifier,
|
||||
key + PUBLIC_KEY_Q_LEAF_ID_OFFSET,
|
||||
MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
|
||||
|
||||
memcpy(ctx->public_key,
|
||||
key + PUBLIC_KEY_KEY_HASH_OFFSET,
|
||||
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
|
||||
|
||||
ctx->have_public_key = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx,
|
||||
unsigned char *key, size_t key_size,
|
||||
size_t *key_len)
|
||||
{
|
||||
if (key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) {
|
||||
return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (!ctx->have_public_key) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
|
||||
|
||||
memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET,
|
||||
ctx->params.I_key_identifier,
|
||||
MBEDTLS_LMOTS_I_KEY_ID_LEN);
|
||||
|
||||
memcpy(key + PUBLIC_KEY_Q_LEAF_ID_OFFSET,
|
||||
ctx->params.q_leaf_identifier,
|
||||
MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
|
||||
|
||||
memcpy(key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key,
|
||||
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
|
||||
|
||||
if (key_len != NULL) {
|
||||
*key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params,
|
||||
const unsigned char *msg,
|
||||
size_t msg_size,
|
||||
const unsigned char *sig,
|
||||
size_t sig_size,
|
||||
unsigned char *out,
|
||||
size_t out_size,
|
||||
size_t *out_len)
|
||||
{
|
||||
unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX];
|
||||
unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (msg == NULL && msg_size != 0) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) ||
|
||||
out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type)) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
ret = create_digit_array_with_checksum(params, msg, msg_size,
|
||||
sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET,
|
||||
tmp_digit_array);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hash_digit_array(params,
|
||||
sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type),
|
||||
tmp_digit_array, NULL, (unsigned char *) y_hashed_digits);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = public_key_from_hashed_digit_array(params,
|
||||
(unsigned char *) y_hashed_digits,
|
||||
out);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (out_len != NULL) {
|
||||
*out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx,
|
||||
const unsigned char *msg, size_t msg_size,
|
||||
const unsigned char *sig, size_t sig_size)
|
||||
{
|
||||
unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (msg == NULL && msg_size != 0) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (!ctx->have_public_key) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (ctx->params.type != MBEDTLS_LMOTS_SHA256_N32_W8) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (sig_size < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {
|
||||
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
if (MBEDTLS_GET_UINT32_BE(sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != MBEDTLS_LMOTS_SHA256_N32_W8) {
|
||||
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
ret = mbedtls_lmots_calculate_public_key_candidate(&ctx->params,
|
||||
msg, msg_size, sig, sig_size,
|
||||
Kc_public_key_candidate,
|
||||
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type),
|
||||
NULL);
|
||||
if (ret) {
|
||||
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
if (memcmp(&Kc_public_key_candidate, ctx->public_key,
|
||||
sizeof(ctx->public_key))) {
|
||||
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_LMS_PRIVATE)
|
||||
|
||||
void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
mbedtls_platform_zeroize(ctx,
|
||||
sizeof(*ctx));
|
||||
}
|
||||
|
||||
int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx,
|
||||
mbedtls_lmots_algorithm_type_t type,
|
||||
const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN],
|
||||
uint32_t q_leaf_identifier,
|
||||
const unsigned char *seed,
|
||||
size_t seed_size)
|
||||
{
|
||||
psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
size_t output_hash_len;
|
||||
unsigned int i_digit_idx;
|
||||
unsigned char i_digit_idx_bytes[2];
|
||||
unsigned char const_bytes[1] = { 0xFF };
|
||||
|
||||
if (ctx->have_private_key) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (type != MBEDTLS_LMOTS_SHA256_N32_W8) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
ctx->params.type = type;
|
||||
|
||||
memcpy(ctx->params.I_key_identifier,
|
||||
I_key_identifier,
|
||||
sizeof(ctx->params.I_key_identifier));
|
||||
|
||||
MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ctx->params.q_leaf_identifier, 0);
|
||||
|
||||
for (i_digit_idx = 0;
|
||||
i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type);
|
||||
i_digit_idx++) {
|
||||
status = psa_hash_setup(&op, PSA_ALG_SHA_256);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op,
|
||||
ctx->params.I_key_identifier,
|
||||
sizeof(ctx->params.I_key_identifier));
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op,
|
||||
ctx->params.q_leaf_identifier,
|
||||
MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0);
|
||||
status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, const_bytes, sizeof(const_bytes));
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, seed, seed_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_finish(&op,
|
||||
ctx->private_key[i_digit_idx],
|
||||
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type),
|
||||
&output_hash_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
psa_hash_abort(&op);
|
||||
}
|
||||
|
||||
ctx->have_private_key = 1;
|
||||
|
||||
exit:
|
||||
psa_hash_abort(&op);
|
||||
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
|
||||
int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx,
|
||||
const mbedtls_lmots_private_t *priv_ctx)
|
||||
{
|
||||
unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
/* Check that a private key is loaded */
|
||||
if (!priv_ctx->have_private_key) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
ret = hash_digit_array(&priv_ctx->params,
|
||||
(unsigned char *) priv_ctx->private_key, NULL,
|
||||
NULL, (unsigned char *) y_hashed_digits);
|
||||
if (ret) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = public_key_from_hashed_digit_array(&priv_ctx->params,
|
||||
(unsigned char *) y_hashed_digits,
|
||||
ctx->public_key);
|
||||
if (ret) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(&ctx->params, &priv_ctx->params,
|
||||
sizeof(ctx->params));
|
||||
|
||||
ctx->have_public_key = 1;
|
||||
|
||||
exit:
|
||||
mbedtls_platform_zeroize(y_hashed_digits, sizeof(y_hashed_digits));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng, const unsigned char *msg, size_t msg_size,
|
||||
unsigned char *sig, size_t sig_size, size_t *sig_len)
|
||||
{
|
||||
unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX];
|
||||
/* Create a temporary buffer to prepare the signature in. This allows us to
|
||||
* finish creating a signature (ensuring the process doesn't fail), and then
|
||||
* erase the private key **before** writing any data into the sig parameter
|
||||
* buffer. If data were directly written into the sig buffer, it might leak
|
||||
* a partial signature on failure, which effectively compromises the private
|
||||
* key.
|
||||
*/
|
||||
unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
|
||||
unsigned char tmp_c_random[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (msg == NULL && msg_size != 0) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (sig_size < MBEDTLS_LMOTS_SIG_LEN(ctx->params.type)) {
|
||||
return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* Check that a private key is loaded */
|
||||
if (!ctx->have_private_key) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
ret = f_rng(p_rng, tmp_c_random,
|
||||
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = create_digit_array_with_checksum(&ctx->params,
|
||||
msg, msg_size,
|
||||
tmp_c_random,
|
||||
tmp_digit_array);
|
||||
if (ret) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = hash_digit_array(&ctx->params, (unsigned char *) ctx->private_key,
|
||||
NULL, tmp_digit_array, (unsigned char *) tmp_sig);
|
||||
if (ret) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
|
||||
|
||||
/* Test hook to check if sig is being written to before we invalidate the
|
||||
* private key.
|
||||
*/
|
||||
#if defined(MBEDTLS_TEST_HOOKS)
|
||||
if (mbedtls_lmots_sign_private_key_invalidated_hook != NULL) {
|
||||
ret = (*mbedtls_lmots_sign_private_key_invalidated_hook)(sig);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif /* defined(MBEDTLS_TEST_HOOKS) */
|
||||
|
||||
/* We've got a valid signature now, so it's time to make sure the private
|
||||
* key can't be reused.
|
||||
*/
|
||||
ctx->have_private_key = 0;
|
||||
mbedtls_platform_zeroize(ctx->private_key,
|
||||
sizeof(ctx->private_key));
|
||||
|
||||
memcpy(sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random,
|
||||
MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type));
|
||||
|
||||
memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(ctx->params.type), tmp_sig,
|
||||
MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type)
|
||||
* MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
|
||||
|
||||
if (sig_len != NULL) {
|
||||
*sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
exit:
|
||||
mbedtls_platform_zeroize(tmp_digit_array, sizeof(tmp_digit_array));
|
||||
mbedtls_platform_zeroize(tmp_sig, sizeof(tmp_sig));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
|
||||
#endif /* defined(MBEDTLS_LMS_C) */
|
||||
769
thirdparty/mbedtls/library/lms.c
vendored
769
thirdparty/mbedtls/library/lms.c
vendored
@ -1,769 +0,0 @@
|
||||
/*
|
||||
* The LMS stateful-hash public-key signature scheme
|
||||
*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following sources were referenced in the design of this implementation
|
||||
* of the LMS algorithm:
|
||||
*
|
||||
* [1] IETF RFC8554
|
||||
* D. McGrew, M. Curcio, S.Fluhrer
|
||||
* https://datatracker.ietf.org/doc/html/rfc8554
|
||||
*
|
||||
* [2] NIST Special Publication 800-208
|
||||
* David A. Cooper et. al.
|
||||
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(MBEDTLS_LMS_C)
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lmots.h"
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_util_internal.h"
|
||||
#include "mbedtls/lms.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
|
||||
#include "mbedtls/platform.h"
|
||||
|
||||
/* Define a local translating function to save code size by not using too many
|
||||
* arguments in each translating place. */
|
||||
static int local_err_translation(psa_status_t status)
|
||||
{
|
||||
return psa_status_to_mbedtls(status, psa_to_lms_errors,
|
||||
ARRAY_LENGTH(psa_to_lms_errors),
|
||||
psa_generic_status_to_mbedtls);
|
||||
}
|
||||
#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
|
||||
|
||||
#define SIG_Q_LEAF_ID_OFFSET (0)
|
||||
#define SIG_OTS_SIG_OFFSET (SIG_Q_LEAF_ID_OFFSET + \
|
||||
MBEDTLS_LMOTS_Q_LEAF_ID_LEN)
|
||||
#define SIG_TYPE_OFFSET(otstype) (SIG_OTS_SIG_OFFSET + \
|
||||
MBEDTLS_LMOTS_SIG_LEN(otstype))
|
||||
#define SIG_PATH_OFFSET(otstype) (SIG_TYPE_OFFSET(otstype) + \
|
||||
MBEDTLS_LMS_TYPE_LEN)
|
||||
|
||||
#define PUBLIC_KEY_TYPE_OFFSET (0)
|
||||
#define PUBLIC_KEY_OTSTYPE_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \
|
||||
MBEDTLS_LMS_TYPE_LEN)
|
||||
#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_OTSTYPE_OFFSET + \
|
||||
MBEDTLS_LMOTS_TYPE_LEN)
|
||||
#define PUBLIC_KEY_ROOT_NODE_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \
|
||||
MBEDTLS_LMOTS_I_KEY_ID_LEN)
|
||||
|
||||
|
||||
/* Currently only support H=10 */
|
||||
#define H_TREE_HEIGHT_MAX 10
|
||||
#define MERKLE_TREE_NODE_AM(type) ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))
|
||||
#define MERKLE_TREE_LEAF_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
|
||||
#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((unsigned int) \
|
||||
(1u << MBEDTLS_LMS_H_TREE_HEIGHT(type)))
|
||||
|
||||
#define D_CONST_LEN (2)
|
||||
static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 };
|
||||
static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = { 0x83, 0x83 };
|
||||
|
||||
|
||||
/* Calculate the value of a leaf node of the Merkle tree (which is a hash of a
|
||||
* public key and some other parameters like the leaf index). This function
|
||||
* implements RFC8554 section 5.3, in the case where r >= 2^h.
|
||||
*
|
||||
* params The LMS parameter set, the underlying LMOTS
|
||||
* parameter set, and I value which describe the key
|
||||
* being used.
|
||||
*
|
||||
* pub_key The public key of the private whose index
|
||||
* corresponds to the index of this leaf node. This
|
||||
* is a hash output.
|
||||
*
|
||||
* r_node_idx The index of this node in the Merkle tree. Note
|
||||
* that the root node of the Merkle tree is
|
||||
* 1-indexed.
|
||||
*
|
||||
* out The output node value, which is a hash output.
|
||||
*/
|
||||
static int create_merkle_leaf_value(const mbedtls_lms_parameters_t *params,
|
||||
unsigned char *pub_key,
|
||||
unsigned int r_node_idx,
|
||||
unsigned char *out)
|
||||
{
|
||||
psa_hash_operation_t op;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
size_t output_hash_len;
|
||||
unsigned char r_node_idx_bytes[4];
|
||||
|
||||
op = psa_hash_operation_init();
|
||||
status = psa_hash_setup(&op, PSA_ALG_SHA_256);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, params->I_key_identifier,
|
||||
MBEDTLS_LMOTS_I_KEY_ID_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0);
|
||||
status = psa_hash_update(&op, r_node_idx_bytes, 4);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, pub_key,
|
||||
MBEDTLS_LMOTS_N_HASH_LEN(params->otstype));
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),
|
||||
&output_hash_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
psa_hash_abort(&op);
|
||||
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
|
||||
/* Calculate the value of an internal node of the Merkle tree (which is a hash
|
||||
* of a public key and some other parameters like the node index). This function
|
||||
* implements RFC8554 section 5.3, in the case where r < 2^h.
|
||||
*
|
||||
* params The LMS parameter set, the underlying LMOTS
|
||||
* parameter set, and I value which describe the key
|
||||
* being used.
|
||||
*
|
||||
* left_node The value of the child of this node which is on
|
||||
* the left-hand side. As with all nodes on the
|
||||
* Merkle tree, this is a hash output.
|
||||
*
|
||||
* right_node The value of the child of this node which is on
|
||||
* the right-hand side. As with all nodes on the
|
||||
* Merkle tree, this is a hash output.
|
||||
*
|
||||
* r_node_idx The index of this node in the Merkle tree. Note
|
||||
* that the root node of the Merkle tree is
|
||||
* 1-indexed.
|
||||
*
|
||||
* out The output node value, which is a hash output.
|
||||
*/
|
||||
static int create_merkle_internal_value(const mbedtls_lms_parameters_t *params,
|
||||
const unsigned char *left_node,
|
||||
const unsigned char *right_node,
|
||||
unsigned int r_node_idx,
|
||||
unsigned char *out)
|
||||
{
|
||||
psa_hash_operation_t op;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
size_t output_hash_len;
|
||||
unsigned char r_node_idx_bytes[4];
|
||||
|
||||
op = psa_hash_operation_init();
|
||||
status = psa_hash_setup(&op, PSA_ALG_SHA_256);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, params->I_key_identifier,
|
||||
MBEDTLS_LMOTS_I_KEY_ID_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0);
|
||||
status = psa_hash_update(&op, r_node_idx_bytes, 4);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, D_INTR_CONSTANT_BYTES, D_CONST_LEN);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, left_node,
|
||||
MBEDTLS_LMS_M_NODE_BYTES(params->type));
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_update(&op, right_node,
|
||||
MBEDTLS_LMS_M_NODE_BYTES(params->type));
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),
|
||||
&output_hash_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
psa_hash_abort(&op);
|
||||
|
||||
return PSA_TO_MBEDTLS_ERR(status);
|
||||
}
|
||||
|
||||
void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
mbedtls_platform_zeroize(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx,
|
||||
const unsigned char *key, size_t key_size)
|
||||
{
|
||||
mbedtls_lms_algorithm_type_t type;
|
||||
mbedtls_lmots_algorithm_type_t otstype;
|
||||
|
||||
type = (mbedtls_lms_algorithm_type_t) MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_TYPE_OFFSET);
|
||||
if (type != MBEDTLS_LMS_SHA256_M32_H10) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
ctx->params.type = type;
|
||||
|
||||
if (key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
otstype = (mbedtls_lmots_algorithm_type_t)
|
||||
MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_OTSTYPE_OFFSET);
|
||||
if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
ctx->params.otstype = otstype;
|
||||
|
||||
memcpy(ctx->params.I_key_identifier,
|
||||
key + PUBLIC_KEY_I_KEY_ID_OFFSET,
|
||||
MBEDTLS_LMOTS_I_KEY_ID_LEN);
|
||||
memcpy(ctx->T_1_pub_key, key + PUBLIC_KEY_ROOT_NODE_OFFSET,
|
||||
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type));
|
||||
|
||||
ctx->have_public_key = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx,
|
||||
unsigned char *key,
|
||||
size_t key_size, size_t *key_len)
|
||||
{
|
||||
if (key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) {
|
||||
return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (!ctx->have_public_key) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, PUBLIC_KEY_TYPE_OFFSET);
|
||||
MBEDTLS_PUT_UINT32_BE(ctx->params.otstype, key, PUBLIC_KEY_OTSTYPE_OFFSET);
|
||||
memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET,
|
||||
ctx->params.I_key_identifier,
|
||||
MBEDTLS_LMOTS_I_KEY_ID_LEN);
|
||||
memcpy(key +PUBLIC_KEY_ROOT_NODE_OFFSET,
|
||||
ctx->T_1_pub_key,
|
||||
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type));
|
||||
|
||||
if (key_len != NULL) {
|
||||
*key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx,
|
||||
const unsigned char *msg, size_t msg_size,
|
||||
const unsigned char *sig, size_t sig_size)
|
||||
{
|
||||
unsigned int q_leaf_identifier;
|
||||
unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
|
||||
unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES_MAX];
|
||||
unsigned int height;
|
||||
unsigned int curr_node_id;
|
||||
unsigned int parent_node_id;
|
||||
const unsigned char *left_node;
|
||||
const unsigned char *right_node;
|
||||
mbedtls_lmots_parameters_t ots_params;
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (!ctx->have_public_key) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (ctx->params.type
|
||||
!= MBEDTLS_LMS_SHA256_M32_H10) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (ctx->params.otstype
|
||||
!= MBEDTLS_LMOTS_SHA256_N32_W8) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) {
|
||||
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
if (sig_size < SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {
|
||||
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
if (MBEDTLS_GET_UINT32_BE(sig, SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET)
|
||||
!= MBEDTLS_LMOTS_SHA256_N32_W8) {
|
||||
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
if (sig_size < SIG_TYPE_OFFSET(ctx->params.otstype) + MBEDTLS_LMS_TYPE_LEN) {
|
||||
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
if (MBEDTLS_GET_UINT32_BE(sig, SIG_TYPE_OFFSET(ctx->params.otstype))
|
||||
!= MBEDTLS_LMS_SHA256_M32_H10) {
|
||||
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
|
||||
q_leaf_identifier = MBEDTLS_GET_UINT32_BE(sig, SIG_Q_LEAF_ID_OFFSET);
|
||||
|
||||
if (q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) {
|
||||
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
memcpy(ots_params.I_key_identifier,
|
||||
ctx->params.I_key_identifier,
|
||||
MBEDTLS_LMOTS_I_KEY_ID_LEN);
|
||||
MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ots_params.q_leaf_identifier, 0);
|
||||
ots_params.type = ctx->params.otstype;
|
||||
|
||||
ret = mbedtls_lmots_calculate_public_key_candidate(&ots_params,
|
||||
msg,
|
||||
msg_size,
|
||||
sig + SIG_OTS_SIG_OFFSET,
|
||||
MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype),
|
||||
Kc_candidate_ots_pub_key,
|
||||
sizeof(Kc_candidate_ots_pub_key),
|
||||
NULL);
|
||||
if (ret != 0) {
|
||||
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
create_merkle_leaf_value(
|
||||
&ctx->params,
|
||||
Kc_candidate_ots_pub_key,
|
||||
MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,
|
||||
Tc_candidate_root_node);
|
||||
|
||||
curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) +
|
||||
q_leaf_identifier;
|
||||
|
||||
for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);
|
||||
height++) {
|
||||
parent_node_id = curr_node_id / 2;
|
||||
|
||||
/* Left/right node ordering matters for the hash */
|
||||
if (curr_node_id & 1) {
|
||||
left_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +
|
||||
height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
|
||||
right_node = Tc_candidate_root_node;
|
||||
} else {
|
||||
left_node = Tc_candidate_root_node;
|
||||
right_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +
|
||||
height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
|
||||
}
|
||||
|
||||
create_merkle_internal_value(&ctx->params, left_node, right_node,
|
||||
parent_node_id, Tc_candidate_root_node);
|
||||
|
||||
curr_node_id /= 2;
|
||||
}
|
||||
|
||||
if (memcmp(Tc_candidate_root_node, ctx->T_1_pub_key,
|
||||
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type))) {
|
||||
return MBEDTLS_ERR_LMS_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_LMS_PRIVATE)
|
||||
|
||||
/* Calculate a full Merkle tree based on a private key. This function
|
||||
* implements RFC8554 section 5.3, and is used to generate a public key (as the
|
||||
* public key is the root node of the Merkle tree).
|
||||
*
|
||||
* ctx The LMS private context, containing a parameter
|
||||
* set and private key material consisting of both
|
||||
* public and private OTS.
|
||||
*
|
||||
* tree The output tree, which is 2^(H + 1) hash outputs.
|
||||
* In the case of H=10 we have 2048 tree nodes (of
|
||||
* which 1024 of them are leaf nodes). Note that
|
||||
* because the Merkle tree root is 1-indexed, the 0
|
||||
* index tree node is never used.
|
||||
*/
|
||||
static int calculate_merkle_tree(const mbedtls_lms_private_t *ctx,
|
||||
unsigned char *tree)
|
||||
{
|
||||
unsigned int priv_key_idx;
|
||||
unsigned int r_node_idx;
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
/* First create the leaf nodes, in ascending order */
|
||||
for (priv_key_idx = 0;
|
||||
priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type);
|
||||
priv_key_idx++) {
|
||||
r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + priv_key_idx;
|
||||
|
||||
ret = create_merkle_leaf_value(&ctx->params,
|
||||
ctx->ots_public_keys[priv_key_idx].public_key,
|
||||
r_node_idx,
|
||||
&tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(
|
||||
ctx->params.type)]);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then the internal nodes, in reverse order so that we can guarantee the
|
||||
* parent has been created */
|
||||
for (r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) - 1;
|
||||
r_node_idx > 0;
|
||||
r_node_idx--) {
|
||||
ret = create_merkle_internal_value(&ctx->params,
|
||||
&tree[(r_node_idx * 2) *
|
||||
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
|
||||
&tree[(r_node_idx * 2 + 1) *
|
||||
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
|
||||
r_node_idx,
|
||||
&tree[r_node_idx *
|
||||
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)]);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate a path from a leaf node of the Merkle tree to the root of the tree,
|
||||
* and return the full path. This function implements RFC8554 section 5.4.1, as
|
||||
* the Merkle path is the main component of an LMS signature.
|
||||
*
|
||||
* ctx The LMS private context, containing a parameter
|
||||
* set and private key material consisting of both
|
||||
* public and private OTS.
|
||||
*
|
||||
* leaf_node_id Which leaf node to calculate the path from.
|
||||
*
|
||||
* path The output path, which is H hash outputs.
|
||||
*/
|
||||
static int get_merkle_path(mbedtls_lms_private_t *ctx,
|
||||
unsigned int leaf_node_id,
|
||||
unsigned char *path)
|
||||
{
|
||||
const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
|
||||
unsigned int curr_node_id = leaf_node_id;
|
||||
unsigned int adjacent_node_id;
|
||||
unsigned char *tree = NULL;
|
||||
unsigned int height;
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(ctx->params.type),
|
||||
node_bytes);
|
||||
if (tree == NULL) {
|
||||
return MBEDTLS_ERR_LMS_ALLOC_FAILED;
|
||||
}
|
||||
|
||||
ret = calculate_merkle_tree(ctx, tree);
|
||||
if (ret != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);
|
||||
height++) {
|
||||
adjacent_node_id = curr_node_id ^ 1;
|
||||
|
||||
memcpy(&path[height * node_bytes],
|
||||
&tree[adjacent_node_id * node_bytes], node_bytes);
|
||||
|
||||
curr_node_id >>= 1;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
exit:
|
||||
mbedtls_zeroize_and_free(tree, node_bytes *
|
||||
(size_t) MERKLE_TREE_NODE_AM(ctx->params.type));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int idx;
|
||||
|
||||
if (ctx->have_private_key) {
|
||||
if (ctx->ots_private_keys != NULL) {
|
||||
for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
|
||||
mbedtls_lmots_private_free(&ctx->ots_private_keys[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->ots_public_keys != NULL) {
|
||||
for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
|
||||
mbedtls_lmots_public_free(&ctx->ots_public_keys[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_free(ctx->ots_private_keys);
|
||||
mbedtls_free(ctx->ots_public_keys);
|
||||
}
|
||||
|
||||
mbedtls_platform_zeroize(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
|
||||
int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx,
|
||||
mbedtls_lms_algorithm_type_t type,
|
||||
mbedtls_lmots_algorithm_type_t otstype,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng, const unsigned char *seed,
|
||||
size_t seed_size)
|
||||
{
|
||||
unsigned int idx = 0;
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (type != MBEDTLS_LMS_SHA256_M32_H10) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (ctx->have_private_key) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
ctx->params.type = type;
|
||||
ctx->params.otstype = otstype;
|
||||
ctx->have_private_key = 1;
|
||||
|
||||
ret = f_rng(p_rng,
|
||||
ctx->params.I_key_identifier,
|
||||
MBEDTLS_LMOTS_I_KEY_ID_LEN);
|
||||
if (ret != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Requires a cast to size_t to avoid an implicit cast warning on certain
|
||||
* platforms (particularly Windows) */
|
||||
ctx->ots_private_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),
|
||||
sizeof(*ctx->ots_private_keys));
|
||||
if (ctx->ots_private_keys == NULL) {
|
||||
ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Requires a cast to size_t to avoid an implicit cast warning on certain
|
||||
* platforms (particularly Windows) */
|
||||
ctx->ots_public_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),
|
||||
sizeof(*ctx->ots_public_keys));
|
||||
if (ctx->ots_public_keys == NULL) {
|
||||
ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
|
||||
mbedtls_lmots_private_init(&ctx->ots_private_keys[idx]);
|
||||
mbedtls_lmots_public_init(&ctx->ots_public_keys[idx]);
|
||||
}
|
||||
|
||||
|
||||
for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
|
||||
ret = mbedtls_lmots_generate_private_key(&ctx->ots_private_keys[idx],
|
||||
otstype,
|
||||
ctx->params.I_key_identifier,
|
||||
idx, seed, seed_size);
|
||||
if (ret != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = mbedtls_lmots_calculate_public_key(&ctx->ots_public_keys[idx],
|
||||
&ctx->ots_private_keys[idx]);
|
||||
if (ret != 0) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->q_next_usable_key = 0;
|
||||
|
||||
exit:
|
||||
if (ret != 0) {
|
||||
mbedtls_lms_private_free(ctx);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx,
|
||||
const mbedtls_lms_private_t *priv_ctx)
|
||||
{
|
||||
const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(priv_ctx->params.type);
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
unsigned char *tree = NULL;
|
||||
|
||||
if (!priv_ctx->have_private_key) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (priv_ctx->params.type
|
||||
!= MBEDTLS_LMS_SHA256_M32_H10) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (priv_ctx->params.otstype
|
||||
!= MBEDTLS_LMOTS_SHA256_N32_W8) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type),
|
||||
node_bytes);
|
||||
if (tree == NULL) {
|
||||
return MBEDTLS_ERR_LMS_ALLOC_FAILED;
|
||||
}
|
||||
|
||||
memcpy(&ctx->params, &priv_ctx->params,
|
||||
sizeof(mbedtls_lmots_parameters_t));
|
||||
|
||||
ret = calculate_merkle_tree(priv_ctx, tree);
|
||||
if (ret != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Root node is always at position 1, due to 1-based indexing */
|
||||
memcpy(ctx->T_1_pub_key, &tree[node_bytes], node_bytes);
|
||||
|
||||
ctx->have_public_key = 1;
|
||||
|
||||
ret = 0;
|
||||
|
||||
exit:
|
||||
mbedtls_zeroize_and_free(tree, node_bytes *
|
||||
(size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int mbedtls_lms_sign(mbedtls_lms_private_t *ctx,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng, const unsigned char *msg,
|
||||
unsigned int msg_size, unsigned char *sig, size_t sig_size,
|
||||
size_t *sig_len)
|
||||
{
|
||||
uint32_t q_leaf_identifier;
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (!ctx->have_private_key) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (sig_size < MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) {
|
||||
return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (ctx->params.otstype
|
||||
!= MBEDTLS_LMOTS_SHA256_N32_W8) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) {
|
||||
return MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS;
|
||||
}
|
||||
|
||||
|
||||
q_leaf_identifier = ctx->q_next_usable_key;
|
||||
/* This new value must _always_ be written back to the disk before the
|
||||
* signature is returned.
|
||||
*/
|
||||
ctx->q_next_usable_key += 1;
|
||||
|
||||
if (MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)
|
||||
< SIG_OTS_SIG_OFFSET) {
|
||||
return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
ret = mbedtls_lmots_sign(&ctx->ots_private_keys[q_leaf_identifier],
|
||||
f_rng,
|
||||
p_rng,
|
||||
msg,
|
||||
msg_size,
|
||||
sig + SIG_OTS_SIG_OFFSET,
|
||||
MBEDTLS_LMS_SIG_LEN(ctx->params.type,
|
||||
ctx->params.otstype) - SIG_OTS_SIG_OFFSET,
|
||||
NULL);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, SIG_TYPE_OFFSET(ctx->params.otstype));
|
||||
MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, sig, SIG_Q_LEAF_ID_OFFSET);
|
||||
|
||||
ret = get_merkle_path(ctx,
|
||||
MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,
|
||||
sig + SIG_PATH_OFFSET(ctx->params.otstype));
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sig_len != NULL) {
|
||||
*sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
|
||||
#endif /* defined(MBEDTLS_LMS_C) */
|
||||
Reference in New Issue
Block a user