This required the LMS keymanager to have an export function. The self test will be provided by HSS, which covers the LMS case. 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)
138 lines
3.8 KiB
C
138 lines
3.8 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 <openssl/core.h>
|
|
#include <openssl/core_dispatch.h>
|
|
#include <openssl/core_names.h>
|
|
#include <openssl/proverr.h>
|
|
#include <openssl/params.h>
|
|
#include <openssl/evp.h>
|
|
#include "prov/providercommon.h"
|
|
#include "prov/provider_ctx.h"
|
|
#include "prov/implementations.h"
|
|
#include "crypto/lms_sig.h"
|
|
|
|
static OSSL_FUNC_signature_newctx_fn lms_newctx;
|
|
static OSSL_FUNC_signature_freectx_fn lms_freectx;
|
|
static OSSL_FUNC_signature_verify_message_init_fn lms_verify_msg_init;
|
|
static OSSL_FUNC_signature_verify_fn lms_verify;
|
|
|
|
typedef struct {
|
|
OSSL_LIB_CTX *libctx;
|
|
char *propq;
|
|
LMS_KEY *key;
|
|
EVP_MD *md;
|
|
} PROV_LMS_CTX;
|
|
|
|
static void *lms_newctx(void *provctx, const char *propq)
|
|
{
|
|
PROV_LMS_CTX *ctx;
|
|
|
|
if (!ossl_prov_is_running())
|
|
return NULL;
|
|
|
|
ctx = OPENSSL_zalloc(sizeof(PROV_LMS_CTX));
|
|
if (ctx == NULL)
|
|
return NULL;
|
|
|
|
if (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL)
|
|
goto err;
|
|
ctx->libctx = PROV_LIBCTX_OF(provctx);
|
|
return ctx;
|
|
err:
|
|
OPENSSL_free(ctx);
|
|
return NULL;
|
|
}
|
|
|
|
static void lms_freectx(void *vctx)
|
|
{
|
|
PROV_LMS_CTX *ctx = (PROV_LMS_CTX *)vctx;
|
|
|
|
if (ctx == NULL)
|
|
return;
|
|
ossl_lms_key_free(ctx->key);
|
|
OPENSSL_free(ctx->propq);
|
|
EVP_MD_free(ctx->md);
|
|
OPENSSL_free(ctx);
|
|
}
|
|
|
|
static int setdigest(PROV_LMS_CTX *ctx, const char *digestname)
|
|
{
|
|
/*
|
|
* Assume that only one digest can be used by LMS.
|
|
* Set the digest to the one contained in the public key.
|
|
* If the optional digestname passed in by the user is different
|
|
* then return an error.
|
|
*/
|
|
LMS_KEY *key = ctx->key;
|
|
const char *pub_digestname = key->ots_params->digestname;
|
|
|
|
if (ctx->md != NULL) {
|
|
if (EVP_MD_is_a(ctx->md, pub_digestname))
|
|
goto end;
|
|
EVP_MD_free(ctx->md);
|
|
}
|
|
ctx->md = EVP_MD_fetch(ctx->libctx, pub_digestname, ctx->propq);
|
|
if (ctx->md == NULL)
|
|
return 0;
|
|
end:
|
|
return digestname == NULL || EVP_MD_is_a(ctx->md, digestname);
|
|
}
|
|
|
|
static int lms_verify_msg_init(void *vctx, void *vkey, const OSSL_PARAM params[])
|
|
{
|
|
PROV_LMS_CTX *ctx = (PROV_LMS_CTX *)vctx;
|
|
LMS_KEY *key = (LMS_KEY *)vkey;
|
|
|
|
if (!ossl_prov_is_running() || ctx == NULL)
|
|
return 0;
|
|
|
|
if (key == NULL && ctx->key == NULL) {
|
|
ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
|
|
return 0;
|
|
}
|
|
|
|
if (!ossl_lms_key_up_ref(key))
|
|
return 0;
|
|
ossl_lms_key_free(ctx->key);
|
|
ctx->key = key;
|
|
if (!setdigest(ctx, NULL))
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
static int lms_verify(void *vctx, const unsigned char *sigbuf, size_t sigbuf_len,
|
|
const unsigned char *msg, size_t msglen)
|
|
{
|
|
int ret = 0;
|
|
PROV_LMS_CTX *ctx = (PROV_LMS_CTX *)vctx;
|
|
LMS_KEY *pub = ctx->key;
|
|
LMS_SIG *sig = NULL;
|
|
|
|
/* A root public key is required to perform a verify operation */
|
|
if (pub == NULL)
|
|
return 0;
|
|
|
|
/* Decode the LMS signature data into a LMS_SIG object */
|
|
if (!ossl_lms_sig_decode(&sig, pub, sigbuf, sigbuf_len))
|
|
return 0;
|
|
|
|
ret = ossl_lms_sig_verify(sig, pub, ctx->md, msg, msglen);
|
|
ossl_lms_sig_free(sig);
|
|
return ret;
|
|
}
|
|
|
|
const OSSL_DISPATCH ossl_lms_signature_functions[] = {
|
|
{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))lms_newctx },
|
|
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))lms_freectx },
|
|
{ OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT,
|
|
(void (*)(void))lms_verify_msg_init },
|
|
{ OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))lms_verify },
|
|
OSSL_DISPATCH_END
|
|
};
|