From 2305e453bf9138cf6f5eefbec00bb96d6876c901 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Tue, 13 Aug 2024 23:38:05 +0000 Subject: [PATCH 01/21] Boilerplate mlkem kem and keymgmt interfaces --- EvpTestRecipes/3.0/evpkem_mlkem.txt | 0 SymCryptProvider/CMakeLists.txt | 7 + SymCryptProvider/src/kem/p_scossl_mlkem.c | 157 +++++++++++++ SymCryptProvider/src/kem/p_scossl_mlkem.h | 17 ++ .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 209 ++++++++++++++++++ SymCryptProvider/src/p_scossl_base.c | 17 ++ 6 files changed, 407 insertions(+) create mode 100644 EvpTestRecipes/3.0/evpkem_mlkem.txt create mode 100644 SymCryptProvider/src/kem/p_scossl_mlkem.c create mode 100644 SymCryptProvider/src/kem/p_scossl_mlkem.h create mode 100644 SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c diff --git a/EvpTestRecipes/3.0/evpkem_mlkem.txt b/EvpTestRecipes/3.0/evpkem_mlkem.txt new file mode 100644 index 00000000..e69de29b diff --git a/SymCryptProvider/CMakeLists.txt b/SymCryptProvider/CMakeLists.txt index 2a9f598d..2c99b489 100644 --- a/SymCryptProvider/CMakeLists.txt +++ b/SymCryptProvider/CMakeLists.txt @@ -55,6 +55,13 @@ if (KEYSINUSE_ENABLED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DKEYSINUSE_ENABLED") endif() +if (MLKEM_ENABLED) + list(APPEND SCOSSL_SOURCES ./src/kem/p_scossl_mlkem.c) + list(APPEND SCOSSL_SOURCES ./src/keymgmt/p_scossl_mlkem_keymgmt.c) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMLKEM_ENABLED") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMLKEM_ENABLED") +endif() + add_library(scossl_provider SHARED ${SCOSSL_SOURCES}) add_dependencies(scossl_provider scossl_common) diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.c b/SymCryptProvider/src/kem/p_scossl_mlkem.c new file mode 100644 index 00000000..ad7beddd --- /dev/null +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.c @@ -0,0 +1,157 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "kem/p_scossl_mlkem.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + SCOSSL_MLKEM_KEY_CTX *keyCtx; +} SCOSSL_MLKEM_CTX; + +static const OSSL_PARAM p_scossl_mlkem_settable_param_types[] = { + OSSL_PARAM_END}; + +static const OSSL_PARAM p_scossl_mlkem_gettable_param_types[] = { + OSSL_PARAM_END}; + +/* Context management */ +SCOSSL_MLKEM_CTX *p_scossl_mlkem_newctx(ossl_unused void *provctx) +{ + SCOSSL_MLKEM_CTX *ctx = OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_CTX)); + + if (ctx != NULL) + { + + } + + return ctx; +} + +void p_scossl_mlkem_freectx(SCOSSL_MLKEM_CTX *ctx) +{ + if (ctx == NULL) + return; + + OPENSSL_free(ctx); +} + +SCOSSL_MLKEM_CTX *p_scossl_mlkem_dupctx(SCOSSL_MLKEM_CTX *ctx) +{ + SCOSSL_MLKEM_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_CTX)); + + if (copyCtx != NULL) + { + copyCtx->keyCtx = ctx->keyCtx; + } + + return copyCtx; +} + +// +// Encapsulation +// +SCOSSL_STATUS p_scossl_mlkem_encapsulate_init(SCOSSL_MLKEM_CTX *ctx, SCOSSL_MLKEM_KEY_CTX *keyCtx, const char *name, + const OSSL_PARAM params[]) +{ + if (ctx == NULL || keyCtx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (keyCtx == NULL || !keyCtx->initialized) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY); + return SCOSSL_FAILURE; + } + + ctx->keyCtx = keyCtx; + + return SCOSSL_FAILURE; +} + +SCOSSL_STATUS p_scossl_mlkem_encapsulate(SCOSSL_MLKEM_CTX *ctx, unsigned char *out, size_t *outlen, + unsigned char *secret, size_t *secretlen) +{ + return SCOSSL_FAILURE; +} + +// +// Decapsulation +// +SCOSSL_STATUS p_scossl_mlkem_decapsulate_init(SCOSSL_MLKEM_CTX *ctx, SCOSSL_MLKEM_KEY_CTX *keyCtx, const char *name) +{ + if (ctx == NULL || keyCtx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (keyCtx == NULL || !keyCtx->initialized) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY); + return SCOSSL_FAILURE; + } + + ctx->keyCtx = keyCtx; + + return SCOSSL_FAILURE; +} + +SCOSSL_STATUS p_scossl_mlkem_decapsulate(SCOSSL_MLKEM_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + return SCOSSL_FAILURE; +} + +// +// Parameters +// +SCOSSL_STATUS p_scossl_mlkem_set_ctx_params(SCOSSL_MLKEM_CTX *ctx, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + return SCOSSL_SUCCESS; +} + +const OSSL_PARAM *p_scossl_mlkem_settable_ctx_params(ossl_unused void *ctx, ossl_unused void *provctx) +{ + return p_scossl_mlkem_settable_param_types; +} + +SCOSSL_STATUS p_scossl_mlkem_get_ctx_params(SCOSSL_MLKEM_CTX *ctx, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + return SCOSSL_SUCCESS; +} + +const OSSL_PARAM *p_scossl_mlkem_gettable_ctx_params(ossl_unused void *ctx, ossl_unused void *provctx) +{ + return p_scossl_mlkem_gettable_param_types; +} + +const OSSL_DISPATCH p_scossl_mlkem_functions[] = { + {OSSL_FUNC_KEM_NEWCTX, (void (*)(void))p_scossl_mlkem_newctx}, + {OSSL_FUNC_KEM_FREECTX, (void (*)(void))p_scossl_mlkem_freectx}, + {OSSL_FUNC_KEM_DUPCTX, (void (*)(void))p_scossl_mlkem_dupctx}, + {OSSL_FUNC_KEM_ENCAPSULATE_INIT, (void (*)(void))p_scossl_mlkem_encapsulate_init}, + {OSSL_FUNC_KEM_ENCAPSULATE, (void (*)(void))p_scossl_mlkem_encapsulate}, + {OSSL_FUNC_KEM_DECAPSULATE_INIT, (void (*)(void))p_scossl_mlkem_decapsulate_init}, + {OSSL_FUNC_KEM_DECAPSULATE, (void (*)(void))p_scossl_mlkem_decapsulate}, + {OSSL_FUNC_KEM_SET_CTX_PARAMS, (void (*)(void))p_scossl_mlkem_set_ctx_params}, + {OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_mlkem_settable_ctx_params}, + {OSSL_FUNC_KEM_GET_CTX_PARAMS, (void (*)(void))p_scossl_mlkem_get_ctx_params}, + {OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_mlkem_gettable_ctx_params}, + {0, NULL}}; + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.h b/SymCryptProvider/src/kem/p_scossl_mlkem.h new file mode 100644 index 00000000..5aa250e5 --- /dev/null +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.h @@ -0,0 +1,17 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "scossl_helpers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + BOOL initialized; +} SCOSSL_MLKEM_KEY_CTX; + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c new file mode 100644 index 00000000..11cd3949 --- /dev/null +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -0,0 +1,209 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "kem/p_scossl_mlkem.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + +} SCOSSL_MLKEM_KEYGEN_CTX; + +static const OSSL_PARAM p_scossl_mlkem_keymgmt_settable_param_types[] = { + OSSL_PARAM_END}; + +static const OSSL_PARAM p_scossl_mlkem_keymgmt_gettable_param_types[] = { + OSSL_PARAM_END}; + +static const OSSL_PARAM p_scossl_mlkem_keygen_settable_param_types[] = { + OSSL_PARAM_END}; + +static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(ossl_unused void *provCtx) +{ + SCOSSL_MLKEM_KEY_CTX *ctx = OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_KEY_CTX)); + if (ctx != NULL) + { + + } + + return ctx; +} + +static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSSL_MLKEM_KEY_CTX *ctx, ossl_unused int selection) +{ + SCOSSL_MLKEM_KEY_CTX *copyCtx = OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_KEY_CTX)); + + if (copyCtx != NULL) + { + + } + + return copyCtx; +} + +static void p_scossl_mlkem_keymgmt_free_key_ctx(_In_ SCOSSL_MLKEM_KEY_CTX *ctx) +{ + if (ctx == NULL) + return; + + OPENSSL_free(ctx); +} + +// +// Key Generation +// +static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ const OSSL_PARAM params[]) +{ + return SCOSSL_FAILURE; +} + +static const OSSL_PARAM *p_scossl_mlkem_keygen_settable_params(ossl_unused void *genCtx, ossl_unused void *provCtx) +{ + return p_scossl_mlkem_keygen_settable_param_types; +} + +static void p_scossl_mlkem_keygen_cleanup(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx) +{ + if (genCtx == NULL) + return; + + OPENSSL_free(genCtx); +} + +static SCOSSL_MLKEM_KEYGEN_CTX *p_scossl_mlkem_keygen_init(ossl_unused void *provCtx, int selection, + _In_ const OSSL_PARAM params[]) +{ + SCOSSL_MLKEM_KEYGEN_CTX *genCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEYGEN_CTX)); + + if (genCtx != NULL) + { + + } + + return genCtx; +} + +static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ SCOSSL_MLKEM_KEY_CTX *tmplCtx) +{ + if (genCtx == NULL || + tmplCtx == NULL) + { + return SCOSSL_FAILURE; + } + + return SCOSSL_FAILURE; +} + +static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, ossl_unused OSSL_CALLBACK *cb, ossl_unused void *cbarg) +{ + SCOSSL_MLKEM_KEY_CTX *ctx; + + if ((ctx = p_scossl_mlkem_keymgmt_new_ctx(NULL)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + + return ctx; +} + +static const OSSL_PARAM *p_scossl_mlkem_keymgmt_settable_params(ossl_unused void *provCtx) +{ + return p_scossl_mlkem_keymgmt_settable_param_types; +} + +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_params(_In_ SCOSSL_MLKEM_KEY_CTX *ctx, _In_ const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + return SCOSSL_SUCCESS; +} + +static const OSSL_PARAM *p_scossl_mlkem_keymgmt_gettable_params(ossl_unused void *provCtx) +{ + return p_scossl_mlkem_keymgmt_gettable_param_types; +} + +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX *ctx, _Inout_ OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + return SCOSSL_SUCCESS; +} + + +static BOOL p_scossl_mlkem_keymgmt_has(_In_ SCOSSL_MLKEM_KEY_CTX *ctx, int selection) +{ + BOOL ret = TRUE; + + if (ctx == NULL) + { + return FALSE; + } + + return ret; +} + +static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *ctx1, _In_ SCOSSL_MLKEM_KEY_CTX *ctx2, + int selection) +{ + BOOL ret = FALSE; + + return ret; +} + +// +// Key import/export +// +static const OSSL_PARAM *p_scossl_mlkem_keymgmt_impexp_types(int selection) +{ + return NULL; +} + +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *ctx, int selection, _In_ const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + SCOSSL_STATUS ret = SCOSSL_FAILURE; + + return ret; +} + +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *ctx, int selection, + _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg) +{ + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + + SCOSSL_STATUS ret = SCOSSL_FAILURE; + + return ret; +} + +const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[] = { + {OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))p_scossl_mlkem_keymgmt_new_ctx}, + {OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))p_scossl_mlkem_keymgmt_dup_key_ctx}, + {OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))p_scossl_mlkem_keymgmt_free_key_ctx}, + {OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))p_scossl_mlkem_keygen_set_params}, + {OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (void (*)(void))p_scossl_mlkem_keygen_settable_params}, + {OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))p_scossl_mlkem_keygen_cleanup}, + {OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))p_scossl_mlkem_keygen_init}, + {OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))p_scossl_mlkem_keygen_set_template}, + {OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))p_scossl_mlkem_keygen}, + {OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))p_scossl_mlkem_keymgmt_settable_params}, + {OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*)(void))p_scossl_mlkem_keymgmt_set_params}, + {OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))p_scossl_mlkem_keymgmt_gettable_params}, + {OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))p_scossl_mlkem_keymgmt_get_params}, + {OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))p_scossl_mlkem_keymgmt_has}, + {OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))p_scossl_mlkem_keymgmt_match}, + {OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))p_scossl_mlkem_keymgmt_impexp_types}, + {OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))p_scossl_mlkem_keymgmt_impexp_types}, + {OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))p_scossl_mlkem_keymgmt_import}, + {OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))p_scossl_mlkem_keymgmt_export}, + {0, NULL}}; + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index 10ad4e96..51324260 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -256,6 +256,7 @@ extern const OSSL_DISPATCH p_scossl_kdf_keymgmt_functions[]; extern const OSSL_DISPATCH p_scossl_rsa_keymgmt_functions[]; extern const OSSL_DISPATCH p_scossl_rsapss_keymgmt_functions[]; extern const OSSL_DISPATCH p_scossl_x25519_keymgmt_functions[]; +extern const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[]; static const OSSL_ALGORITHM p_scossl_keymgmt[] = { ALG("DH:dhKeyAgreement:1.2.840.113549.1.3.1", p_scossl_dh_keymgmt_functions), @@ -265,6 +266,9 @@ static const OSSL_ALGORITHM p_scossl_keymgmt[] = { ALG("RSA-PSS:RSASSA-PSS:1.2.840.113549.1.1.10", p_scossl_rsapss_keymgmt_functions), ALG("TLS1-PRF", p_scossl_kdf_keymgmt_functions), ALG("X25519:1.3.101.110", p_scossl_x25519_keymgmt_functions), +#ifdef MLKEM_ENABLED + ALG("MLKEM", p_scossl_mlkem_keymgmt_functions), +#endif ALG_TABLE_END}; // Key exchange @@ -298,6 +302,17 @@ static const OSSL_ALGORITHM p_scossl_asym_cipher[] = { ALG("RSA:rsaEncryption:1.2.840.113549.1.1.1", p_scossl_rsa_cipher_functions), ALG_TABLE_END}; +// Key encapsulation + +extern const OSSL_DISPATCH p_scossl_mlkem_functions[]; + +static const OSSL_ALGORITHM p_scossl_kem[] = { +#ifdef MLKEM_ENABLED + ALG("MLKEM", p_scossl_mlkem_functions), +#endif + ALG_TABLE_END}; + + static int p_scossl_get_status() { return scossl_prov_initialized; @@ -375,6 +390,8 @@ static const OSSL_ALGORITHM *p_scossl_query_operation(ossl_unused void *provctx, return p_scossl_signature; case OSSL_OP_ASYM_CIPHER: return p_scossl_asym_cipher; + case OSSL_OP_KEM: + return p_scossl_kem; } return NULL; From 09dfe6fdc1fdcd73df0a59eaca5cfa98dd7fb55d Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Mon, 19 Aug 2024 22:06:07 +0000 Subject: [PATCH 02/21] ML-KEM key management --- .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 848 +++++++++++++++++- 1 file changed, 807 insertions(+), 41 deletions(-) diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index 11cd3949..0021aafa 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -4,52 +4,175 @@ #include "kem/p_scossl_mlkem.h" +#include +#include +#include + #ifdef __cplusplus extern "C" { #endif -typedef struct { +#define SCOSSL_MLKEM_PARAM_NAME_512 "MK-KEM-512" +#define SCOSSL_MLKEM_PARAM_NAME_768 "ML-KEM-768" +#define SCOSSL_MLKEM_PARAM_NAME_1024 "ML-KEM-1024" +typedef struct { + PCSYMCRYPT_MLKEM_PARAMS params; } SCOSSL_MLKEM_KEYGEN_CTX; +#define SCOSSL_MLKEM_PKEY_PARAMETER_TYPES \ + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), \ + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \ + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), + +static const OSSL_PARAM p_scossl_mlkem_keygen_settable_param_types[] = { + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), + OSSL_PARAM_END}; + static const OSSL_PARAM p_scossl_mlkem_keymgmt_settable_param_types[] = { + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), OSSL_PARAM_END}; static const OSSL_PARAM p_scossl_mlkem_keymgmt_gettable_param_types[] = { + OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), + OSSL_PARAM_size_t(OSSL_PKEY_PARAM_MAX_SIZE, NULL), + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), + SCOSSL_MLKEM_PKEY_PARAMETER_TYPES OSSL_PARAM_END}; -static const OSSL_PARAM p_scossl_mlkem_keygen_settable_param_types[] = { +// Import/export types +static const OSSL_PARAM p_scossl_mlkem_param_types[] = { + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), + OSSL_PARAM_END}; + +static const OSSL_PARAM p_scossl_mlkem_pkey_types[] = { + SCOSSL_MLKEM_PKEY_PARAMETER_TYPES OSSL_PARAM_END}; +static const OSSL_PARAM p_scossl_mlkem_all_types[] = { + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), + SCOSSL_MLKEM_PKEY_PARAMETER_TYPES + OSSL_PARAM_END}; + +static const OSSL_PARAM *p_scossl_mlkem_impexp_types[] = { + NULL, + p_scossl_mlkem_param_types, + p_scossl_mlkem_pkey_types, + p_scossl_mlkem_all_types}; + +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_bytes(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, + SYMCRYPT_MLKEMKEY_FORMAT format, + _Out_writes_bytes_(*cbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); + +static PCSYMCRYPT_MLKEM_PARAMS p_scossl_mlkem_keymgmt_params_from_name(_In_ const char *name); +static const char * p_scossl_mlkem_keymgmt_params_to_name(_In_ const PCSYMCRYPT_MLKEM_PARAMS name); +static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx); + static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(ossl_unused void *provCtx) { - SCOSSL_MLKEM_KEY_CTX *ctx = OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_KEY_CTX)); - if (ctx != NULL) - { + return OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_KEY_CTX));; +} +static void p_scossl_mlkem_keymgmt_free_key_ctx(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx) +{ + if (keyCtx == NULL) + return; + + if (keyCtx->key != NULL) + { + SymCryptMlKemkeyFree(keyCtx->key); } - return ctx; + OPENSSL_free(keyCtx); } -static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSSL_MLKEM_KEY_CTX *ctx, ossl_unused int selection) +static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection) { - SCOSSL_MLKEM_KEY_CTX *copyCtx = OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_KEY_CTX)); + PBYTE pbKey = NULL; + SIZE_T cbKey = 0; + SYMCRYPT_MLKEMKEY_FORMAT format; + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + SCOSSL_STATUS ret = SCOSSL_FAILURE; + SCOSSL_MLKEM_KEY_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEY_CTX)); if (copyCtx != NULL) { - + if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) + { + copyCtx->params = keyCtx->params; + } + else + { + copyCtx->params = NULL; + } + + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 && keyCtx->key != NULL) + { + if (copyCtx->params == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); + goto cleanup; + } + + if ((copyCtx->key = SymCryptMlKemkeyAllocate(copyCtx->params)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + { + format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; + } + else + { + format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; + } + + ret = p_scossl_mlkem_keymgmt_get_key_bytes( + keyCtx, + format, + &pbKey, &cbKey); + + if (ret != SCOSSL_SUCCESS) + { + goto cleanup; + } + + scError = SymCryptMlKemkeySetValue( + pbKey, cbKey, + format, + 0, + copyCtx->key); + + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + copyCtx->format = format; + } + else + { + copyCtx->key = NULL; + copyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_NULL; + } } - return copyCtx; -} + ret = SCOSSL_SUCCESS; -static void p_scossl_mlkem_keymgmt_free_key_ctx(_In_ SCOSSL_MLKEM_KEY_CTX *ctx) -{ - if (ctx == NULL) - return; +cleanup: - OPENSSL_free(ctx); + if (ret != SCOSSL_SUCCESS) + { + p_scossl_mlkem_keymgmt_free_key_ctx(copyCtx); + copyCtx = NULL; + } + + OPENSSL_secure_clear_free(pbKey, cbKey); + + return copyCtx; } // @@ -57,7 +180,25 @@ static void p_scossl_mlkem_keymgmt_free_key_ctx(_In_ SCOSSL_MLKEM_KEY_CTX *ctx) // static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ const OSSL_PARAM params[]) { - return SCOSSL_FAILURE; + const OSSL_PARAM *p; + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL) + { + const char *name; + + if (!OSSL_PARAM_get_utf8_ptr(p, &name)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return SCOSSL_FAILURE; + } + + if ((genCtx->params = p_scossl_mlkem_keymgmt_params_from_name(name)) == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); + return SCOSSL_FAILURE; + } + } + + return SCOSSL_SUCCESS;; } static const OSSL_PARAM *p_scossl_mlkem_keygen_settable_params(ossl_unused void *genCtx, ossl_unused void *provCtx) @@ -67,20 +208,23 @@ static const OSSL_PARAM *p_scossl_mlkem_keygen_settable_params(ossl_unused void static void p_scossl_mlkem_keygen_cleanup(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx) { - if (genCtx == NULL) - return; - OPENSSL_free(genCtx); } -static SCOSSL_MLKEM_KEYGEN_CTX *p_scossl_mlkem_keygen_init(ossl_unused void *provCtx, int selection, +static SCOSSL_MLKEM_KEYGEN_CTX *p_scossl_mlkem_keygen_init(ossl_unused void *provCtx, ossl_unused int selection, _In_ const OSSL_PARAM params[]) { SCOSSL_MLKEM_KEYGEN_CTX *genCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEYGEN_CTX)); if (genCtx != NULL) { + genCtx->params = SymCryptMlKemParamsDraft203MlKem768; + if (p_scossl_mlkem_keygen_set_params(genCtx, params) != SCOSSL_SUCCESS) + { + OPENSSL_free(genCtx); + return NULL; + } } return genCtx; @@ -91,23 +235,54 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEY if (genCtx == NULL || tmplCtx == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (tmplCtx->params == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); return SCOSSL_FAILURE; } - return SCOSSL_FAILURE; + genCtx->params = tmplCtx->params; + + return SCOSSL_SUCCESS; } static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, ossl_unused OSSL_CALLBACK *cb, ossl_unused void *cbarg) { - SCOSSL_MLKEM_KEY_CTX *ctx; + BOOL success = FALSE; + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + SCOSSL_MLKEM_KEY_CTX *keyCtx; - if ((ctx = p_scossl_mlkem_keymgmt_new_ctx(NULL)) == NULL) + if ((keyCtx = p_scossl_mlkem_keymgmt_new_ctx(NULL)) == NULL || + (keyCtx->key = SymCryptMlKemkeyAllocate(genCtx->params)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return NULL; + goto cleanup; + } + + scError = SymCryptMlKemkeyGenerate(keyCtx->key, 0); + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; } - return ctx; + keyCtx->params = genCtx->params; + keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; + + success = TRUE; + +cleanup: + if (!success) + { + p_scossl_mlkem_keymgmt_free_key_ctx(keyCtx); + keyCtx = NULL; + } + + return keyCtx; } static const OSSL_PARAM *p_scossl_mlkem_keymgmt_settable_params(ossl_unused void *provCtx) @@ -115,10 +290,50 @@ static const OSSL_PARAM *p_scossl_mlkem_keymgmt_settable_params(ossl_unused void return p_scossl_mlkem_keymgmt_settable_param_types; } -static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_params(_In_ SCOSSL_MLKEM_KEY_CTX *ctx, _In_ const OSSL_PARAM params[]) +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_params(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, _In_ const OSSL_PARAM params[]) { + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; const OSSL_PARAM *p; + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) + { + PCBYTE pbKey; + SIZE_T cbKey; + + if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbKey, &cbKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return SCOSSL_FAILURE; + } + + if (keyCtx->key != NULL) + { + SymCryptMlKemkeyFree(keyCtx->key); + } + + if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return SCOSSL_FAILURE; + } + + scError = SymCryptMlKemkeySetValue( + pbKey, cbKey, + SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, + 0, + keyCtx->key); + + if (scError != SYMCRYPT_NO_ERROR) + { + SymCryptMlKemkeyFree(keyCtx->key); + keyCtx->key = NULL; + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; + } + + keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; + } + return SCOSSL_SUCCESS; } @@ -127,30 +342,284 @@ static const OSSL_PARAM *p_scossl_mlkem_keymgmt_gettable_params(ossl_unused void return p_scossl_mlkem_keymgmt_gettable_param_types; } -static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX *ctx, _Inout_ OSSL_PARAM params[]) +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, _Inout_ OSSL_PARAM params[]) +{ + PBYTE pbKey = NULL; + SIZE_T cbKey = 0; + OSSL_PARAM *paramEncodedKey; + OSSL_PARAM *paramPubKey; + OSSL_PARAM *paramPrivKey; + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + SCOSSL_STATUS ret = SCOSSL_FAILURE; + + paramEncodedKey = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); + paramPubKey = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY); + paramPrivKey = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PRIV_KEY); + + if (keyCtx->key == NULL && + (paramEncodedKey != NULL || + paramPubKey != NULL || + paramPrivKey != NULL)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return SCOSSL_FAILURE; + } + + if (paramEncodedKey != NULL || paramPubKey != NULL) + { + scError = p_scossl_mlkem_keymgmt_get_key_bytes( + keyCtx, + SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, + &pbKey, &cbKey); + + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + if (paramEncodedKey != NULL && + !OSSL_PARAM_set_octet_string(paramEncodedKey, pbKey, cbKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + goto cleanup; + } + + if (paramPubKey != NULL && + !OSSL_PARAM_set_octet_string(paramPubKey, pbKey, cbKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + goto cleanup; + } + } + + if (paramPrivKey != NULL) + { + // Reset pbKey in case it was used for encapsulation key + OPENSSL_secure_clear_free(pbKey, cbKey); + + if (keyCtx->format != SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY); + goto cleanup; + } + + scError = p_scossl_mlkem_keymgmt_get_key_bytes( + keyCtx, + SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, + &pbKey, &cbKey); + + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + if (!OSSL_PARAM_set_octet_string(paramPrivKey, pbKey, cbKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + goto cleanup; + } + } + + ret = SCOSSL_SUCCESS; + +cleanup: + OPENSSL_secure_clear_free(pbKey, cbKey); + + return ret; +} + +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, _Inout_ OSSL_PARAM params[]) { + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; OSSL_PARAM *p; - return SCOSSL_SUCCESS; + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) + { + if (keyCtx->params == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); + return SCOSSL_FAILURE; + } + + if (!OSSL_PARAM_set_int(p, p_scossl_mlkem_keymgmt_get_security_bits(keyCtx))) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; + } + } + + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL) + { + SIZE_T cbSize; + SYMCRYPT_MLKEMKEY_FORMAT format = keyCtx->format; + + if (keyCtx->params == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); + return SCOSSL_FAILURE; + } + + // Default to larger size if key data is not set (and therefore format is unknown) + if (format == SYMCRYPT_MLKEMKEY_FORMAT_NULL) + { + format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; + } + + scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->params, format, &cbSize); + + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; + } + + if (!OSSL_PARAM_set_size_t(p, cbSize)) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; + } + } + + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL) + { + if (keyCtx->params == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); + return SCOSSL_FAILURE; + } + + if (!OSSL_PARAM_set_utf8_string(p, p_scossl_mlkem_keymgmt_params_to_name(keyCtx->params))) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; + } + } + + return p_scossl_mlkem_keymgmt_get_key_params(keyCtx, params); } -static BOOL p_scossl_mlkem_keymgmt_has(_In_ SCOSSL_MLKEM_KEY_CTX *ctx, int selection) +static BOOL p_scossl_mlkem_keymgmt_has(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection) { - BOOL ret = TRUE; + if (keyCtx == NULL) + { + return FALSE; + } - if (ctx == NULL) + if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0 && + keyCtx->params != NULL) { return FALSE; } - return ret; + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0 && + keyCtx->key != NULL) + { + return FALSE; + } + + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && + keyCtx->format == SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY) + { + return FALSE; + } + + return TRUE; } -static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *ctx1, _In_ SCOSSL_MLKEM_KEY_CTX *ctx2, +static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx1, _In_ SCOSSL_MLKEM_KEY_CTX *keyCtx2, int selection) { + PBYTE pbKey1 = NULL; + PBYTE pbKey2 = NULL; + SIZE_T cbKey1 = 0; + SIZE_T cbKey2 = 0; BOOL ret = FALSE; + SCOSSL_STATUS success; + + if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0 && + keyCtx1->params != keyCtx2->params) + { + goto cleanup; + } + + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)) + { + if (keyCtx1->key != NULL || keyCtx2->key != NULL) + { + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + { + // Both keys must be decapsulation keys to compare + if (keyCtx1->format != keyCtx2->format) + { + goto cleanup; + } + + // Reset pbKeys in case they was used for encapsulation key compare + OPENSSL_secure_clear_free(pbKey1, cbKey1); + OPENSSL_secure_clear_free(pbKey2, cbKey2); + + success = p_scossl_mlkem_keymgmt_get_key_bytes( + keyCtx1, + SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, + &pbKey1, &cbKey1); + if (!success) + { + goto cleanup; + } + + success = p_scossl_mlkem_keymgmt_get_key_bytes( + keyCtx2, + SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, + &pbKey2, &cbKey2); + if (!success) + { + goto cleanup; + } + + if (cbKey1 != cbKey2 || + memcmp(pbKey1, pbKey2, cbKey1) != 0) + { + goto cleanup; + } + } + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + { + success = p_scossl_mlkem_keymgmt_get_key_bytes( + keyCtx1, + SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, + &pbKey1, &cbKey1); + if (!success) + { + goto cleanup; + } + + success = p_scossl_mlkem_keymgmt_get_key_bytes( + keyCtx2, + SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, + &pbKey2, &cbKey2); + if (!success) + { + goto cleanup; + } + + if (cbKey1 != cbKey2 || + memcmp(pbKey1, pbKey2, cbKey1) != 0) + { + goto cleanup; + } + } + } + } + + ret = TRUE; + +cleanup: + OPENSSL_secure_clear_free(pbKey1, cbKey1); + OPENSSL_secure_clear_free(pbKey2, cbKey2); return ret; } @@ -160,25 +629,206 @@ static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *ctx1, _In_ S // static const OSSL_PARAM *p_scossl_mlkem_keymgmt_impexp_types(int selection) { - return NULL; + int idx = 0; + if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) + { + idx += 1; + } + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) + { + idx += 2; + } + + return p_scossl_mlkem_impexp_types[idx]; } -static SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *ctx, int selection, _In_ const OSSL_PARAM params[]) +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]) { const OSSL_PARAM *p; - SCOSSL_STATUS ret = SCOSSL_FAILURE; + PCBYTE pbKey; + SIZE_T cbKey; + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; - return ret; + // Domain parameters are required for import + if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0) + { + return SCOSSL_FAILURE; + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL) + { + const char *name; + + if (!OSSL_PARAM_get_utf8_ptr(p, &name)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return SCOSSL_FAILURE; + } + + if ((keyCtx->params = p_scossl_mlkem_keymgmt_params_from_name(name)) == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); + return SCOSSL_FAILURE; + } + } + + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) + { + if (keyCtx->key != NULL) + { + SymCryptMlKemkeyFree(keyCtx->key); + keyCtx->key = NULL; + } + + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && + (p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY)) != NULL) + { + if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbKey, &cbKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return SCOSSL_FAILURE; + } + + keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; + } + else + { + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) == NULL && + (p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY)) == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return SCOSSL_FAILURE; + } + + if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbKey, &cbKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return SCOSSL_FAILURE; + } + + keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; + } + + if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return SCOSSL_FAILURE; + } + + scError = SymCryptMlKemkeySetValue( + pbKey, cbKey, + keyCtx->format, + 0, + keyCtx->key); + + if (scError != SYMCRYPT_NO_ERROR) + { + SymCryptMlKemkeyFree(keyCtx->key); + keyCtx->key = NULL; + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; + } + } + + return SCOSSL_SUCCESS; } -static SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *ctx, int selection, - _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg) +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, + _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg) { + const char *mlkemParamsName; + PBYTE pbKey = NULL; + SIZE_T cbKey = 0; OSSL_PARAM_BLD *bld = NULL; OSSL_PARAM *params = NULL; - SCOSSL_STATUS ret = SCOSSL_FAILURE; + // Domain parameters are required for export + if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0) + { + goto cleanup; + } + + if (keyCtx->params == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); + goto cleanup; + } + + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 && + keyCtx->key == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + goto cleanup; + } + + if ((bld = OSSL_PARAM_BLD_new()) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + mlkemParamsName = p_scossl_mlkem_keymgmt_params_to_name(keyCtx->params); + if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, mlkemParamsName, sizeof(mlkemParamsName))) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + goto cleanup; + } + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + { + ret = p_scossl_mlkem_keymgmt_get_key_bytes( + keyCtx, + SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, + &pbKey, &cbKey); + + if (ret != SCOSSL_SUCCESS) + { + goto cleanup; + } + + if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PRIV_KEY, pbKey, cbKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + goto cleanup; + } + } + + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + { + if (keyCtx->format != SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY); + goto cleanup; + } + + // Reset pbKey in case it was used for encapsulation key export + OPENSSL_secure_clear_free(pbKey, cbKey); + + ret = p_scossl_mlkem_keymgmt_get_key_bytes( + keyCtx, + SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, + &pbKey, &cbKey); + + if (ret != SCOSSL_SUCCESS) + { + goto cleanup; + } + + if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PRIV_KEY, pbKey, cbKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + goto cleanup; + } + } + + ret = param_cb(params, cbarg); + +cleanup: + OSSL_PARAM_BLD_free(bld); + OSSL_PARAM_free(params); + OPENSSL_secure_clear_free(pbKey, cbKey); + return ret; } @@ -204,6 +854,122 @@ const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[] = { {OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))p_scossl_mlkem_keymgmt_export}, {0, NULL}}; +// +// Helper functions +// + +_Use_decl_annotations_ +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_bytes(const SCOSSL_MLKEM_KEY_CTX *keyCtx, + SYMCRYPT_MLKEMKEY_FORMAT format, + PBYTE *ppbKey, SIZE_T *pcbKey) +{ + PBYTE pbKey = NULL; + SIZE_T cbKey = 0; + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + SCOSSL_STATUS ret = SCOSSL_FAILURE; + + if (keyCtx->key == NULL || keyCtx->params == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return SCOSSL_FAILURE; + } + + scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->params, format, &cbKey); + + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + // Always using OPENSSL_secure_malloc so caller doesn't have to worry about + // calling separate free functions for encapsulation and decapsulation keys + if ((pbKey = OPENSSL_secure_malloc(cbKey)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + scError = SymCryptMlKemkeyGetValue(keyCtx->key, pbKey, cbKey, format, 0); + + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + ret = SCOSSL_SUCCESS; + + *ppbKey = pbKey; + *pcbKey = cbKey; + +cleanup: + if (ret != SCOSSL_SUCCESS) + { + OPENSSL_secure_clear_free(pbKey, cbKey); + } + + return SCOSSL_SUCCESS; +} + +_Use_decl_annotations_ +static PCSYMCRYPT_MLKEM_PARAMS p_scossl_mlkem_keymgmt_params_from_name(const char *name) +{ + if (OPENSSL_strcasecmp(name, SCOSSL_MLKEM_PARAM_NAME_512) == 0) + { + return SymCryptMlKemParamsDraft203MlKem512; + } + else if (OPENSSL_strcasecmp(name, SCOSSL_MLKEM_PARAM_NAME_768) == 0) + { + return SymCryptMlKemParamsDraft203MlKem768; + } + else if (OPENSSL_strcasecmp(name, SCOSSL_MLKEM_PARAM_NAME_1024) == 0) + { + return SymCryptMlKemParamsDraft203MlKem1024; + } + + return NULL; +} + +_Use_decl_annotations_ +static const char *p_scossl_mlkem_keymgmt_params_to_name(const PCSYMCRYPT_MLKEM_PARAMS params) +{ + if (params == SymCryptMlKemParamsDraft203MlKem512) + { + return SCOSSL_MLKEM_PARAM_NAME_512; + } + else if (params == SymCryptMlKemParamsDraft203MlKem768) + { + return SCOSSL_MLKEM_PARAM_NAME_768; + } + else if (params == SymCryptMlKemParamsDraft203MlKem1024) + { + return SCOSSL_MLKEM_PARAM_NAME_1024; + } + + return ""; +} + +_Use_decl_annotations_ +static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx) +{ + if (keyCtx->params == SymCryptMlKemParamsDraft203MlKem512) + { + return 128; + } + else if (keyCtx->params == SymCryptMlKemParamsDraft203MlKem768) + { + return 192; + } + else if (keyCtx->params == SymCryptMlKemParamsDraft203MlKem1024) + { + return 256; + } + + return 0; +} + + #ifdef __cplusplus } #endif \ No newline at end of file From 5bc0a0dd1a67bee9a1c243bbf2a36c4d0345c1d5 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Tue, 20 Aug 2024 00:09:52 +0000 Subject: [PATCH 03/21] ML-KEM KEM interface --- SymCryptProvider/src/kem/p_scossl_mlkem.c | 186 ++++++++++++++++------ SymCryptProvider/src/kem/p_scossl_mlkem.h | 4 +- 2 files changed, 136 insertions(+), 54 deletions(-) diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.c b/SymCryptProvider/src/kem/p_scossl_mlkem.c index ad7beddd..ba9306a5 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.c +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.c @@ -10,31 +10,24 @@ extern "C" { #endif +#define SYMCRYPT_MLKEM_SECRET_LENGTH 32 + typedef struct { SCOSSL_MLKEM_KEY_CTX *keyCtx; + int operation; } SCOSSL_MLKEM_CTX; -static const OSSL_PARAM p_scossl_mlkem_settable_param_types[] = { - OSSL_PARAM_END}; - -static const OSSL_PARAM p_scossl_mlkem_gettable_param_types[] = { +static const OSSL_PARAM p_scossl_mlkem_param_types[] = { OSSL_PARAM_END}; /* Context management */ -SCOSSL_MLKEM_CTX *p_scossl_mlkem_newctx(ossl_unused void *provctx) +static SCOSSL_MLKEM_CTX *p_scossl_mlkem_newctx(ossl_unused void *provctx) { - SCOSSL_MLKEM_CTX *ctx = OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_CTX)); - - if (ctx != NULL) - { - - } - - return ctx; + return OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_CTX)); } -void p_scossl_mlkem_freectx(SCOSSL_MLKEM_CTX *ctx) +static void p_scossl_mlkem_freectx(_Inout_ SCOSSL_MLKEM_CTX *ctx) { if (ctx == NULL) return; @@ -42,23 +35,21 @@ void p_scossl_mlkem_freectx(SCOSSL_MLKEM_CTX *ctx) OPENSSL_free(ctx); } -SCOSSL_MLKEM_CTX *p_scossl_mlkem_dupctx(SCOSSL_MLKEM_CTX *ctx) +static SCOSSL_MLKEM_CTX *p_scossl_mlkem_dupctx(_In_ SCOSSL_MLKEM_CTX *ctx) { SCOSSL_MLKEM_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_CTX)); if (copyCtx != NULL) { copyCtx->keyCtx = ctx->keyCtx; + copyCtx->operation = ctx->operation; } return copyCtx; } -// -// Encapsulation -// -SCOSSL_STATUS p_scossl_mlkem_encapsulate_init(SCOSSL_MLKEM_CTX *ctx, SCOSSL_MLKEM_KEY_CTX *keyCtx, const char *name, - const OSSL_PARAM params[]) +static SCOSSL_STATUS p_scossl_mlkem_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, _In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, + int operation) { if (ctx == NULL || keyCtx == NULL) { @@ -66,79 +57,168 @@ SCOSSL_STATUS p_scossl_mlkem_encapsulate_init(SCOSSL_MLKEM_CTX *ctx, SCOSSL_MLKE return SCOSSL_FAILURE; } - if (keyCtx == NULL || !keyCtx->initialized) + if (keyCtx == NULL || keyCtx->key == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY); return SCOSSL_FAILURE; } ctx->keyCtx = keyCtx; + ctx->operation = operation; - return SCOSSL_FAILURE; + return SCOSSL_SUCCESS; } -SCOSSL_STATUS p_scossl_mlkem_encapsulate(SCOSSL_MLKEM_CTX *ctx, unsigned char *out, size_t *outlen, - unsigned char *secret, size_t *secretlen) +// +// Encapsulation +// +static SCOSSL_STATUS p_scossl_mlkem_encapsulate_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, _In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, + ossl_unused const OSSL_PARAM params[]) { - return SCOSSL_FAILURE; + return p_scossl_mlkem_init(ctx, keyCtx, EVP_PKEY_OP_ENCAPSULATE); } -// -// Decapsulation -// -SCOSSL_STATUS p_scossl_mlkem_decapsulate_init(SCOSSL_MLKEM_CTX *ctx, SCOSSL_MLKEM_KEY_CTX *keyCtx, const char *name) +static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, + _Out_writes_bytes_opt_(*outlen) unsigned char *out, _Out_ size_t *outlen, + _Out_writes_bytes_(*secretlen) unsigned char *secret, _Out_ size_t *secretlen) { - if (ctx == NULL || keyCtx == NULL) + SIZE_T cbCipherText; + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + + if (ctx->keyCtx == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); return SCOSSL_FAILURE; } - if (keyCtx == NULL || !keyCtx->initialized) + if (ctx->operation != EVP_PKEY_OP_ENCAPSULATE) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY); + ERR_raise(ERR_LIB_PROV, ERR_R_OPERATION_FAIL); return SCOSSL_FAILURE; } - ctx->keyCtx = keyCtx; + scError = SymCryptMlKemSizeofCiphertextFromParams(ctx->keyCtx->params, &cbCipherText); - return SCOSSL_FAILURE; -} + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; + } -SCOSSL_STATUS p_scossl_mlkem_decapsulate(SCOSSL_MLKEM_CTX *ctx, unsigned char *out, size_t *outlen, - const unsigned char *in, size_t inlen) -{ - return SCOSSL_FAILURE; + if (out != NULL) + { + scError = SymCryptMlKemEncapsulate(ctx->keyCtx->key, secret, SYMCRYPT_MLKEM_SECRET_LENGTH, out, cbCipherText); + + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; + } + } + else if (outlen == NULL && secretlen != NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); + return SCOSSL_FAILURE; + } + + if (outlen != NULL) + { + *outlen = cbCipherText; + } + + if (secretlen != NULL) + { + *secretlen = SYMCRYPT_MLKEM_SECRET_LENGTH; + } + + return SCOSSL_SUCCESS; } // -// Parameters +// Decapsulation // -SCOSSL_STATUS p_scossl_mlkem_set_ctx_params(SCOSSL_MLKEM_CTX *ctx, const OSSL_PARAM params[]) +static SCOSSL_STATUS p_scossl_mlkem_decapsulate_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, _In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, + ossl_unused const OSSL_PARAM params[]) +{ + return p_scossl_mlkem_init(ctx, keyCtx, EVP_PKEY_OP_DECAPSULATE); +} + +static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, + _Out_writes_bytes_opt_(*outlen) unsigned char *out, _Out_ size_t *outlen, + _In_reads_bytes_(inlen) const unsigned char *in, size_t inlen) { - const OSSL_PARAM *p; + SIZE_T cbCipherText; + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + + if (ctx->keyCtx == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + return SCOSSL_FAILURE; + } + + if (ctx->operation != EVP_PKEY_OP_DECAPSULATE) + { + ERR_raise(ERR_LIB_PROV, ERR_R_OPERATION_FAIL); + return SCOSSL_FAILURE; + } + + scError = SymCryptMlKemSizeofCiphertextFromParams(ctx->keyCtx->params, &cbCipherText); + + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; + } + + if (inlen != cbCipherText) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH); + return SCOSSL_FAILURE; + } + + if (out != NULL) + { + scError = SymCryptMlKemDecapsulate(ctx->keyCtx->key, in, inlen, out, SYMCRYPT_MLKEM_SECRET_LENGTH); + + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; + } + } + else if (outlen == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); + return SCOSSL_FAILURE; + } + + if (outlen != NULL) + { + *outlen = SYMCRYPT_MLKEM_SECRET_LENGTH; + } return SCOSSL_SUCCESS; } -const OSSL_PARAM *p_scossl_mlkem_settable_ctx_params(ossl_unused void *ctx, ossl_unused void *provctx) +// +// Parameters +// +static const OSSL_PARAM *p_scossl_mlkem_ctx_param_types(ossl_unused void *ctx, ossl_unused void *provctx) { - return p_scossl_mlkem_settable_param_types; + return p_scossl_mlkem_param_types; } -SCOSSL_STATUS p_scossl_mlkem_get_ctx_params(SCOSSL_MLKEM_CTX *ctx, OSSL_PARAM params[]) +static SCOSSL_STATUS p_scossl_mlkem_set_ctx_params(ossl_unused void *ctx, ossl_unused const OSSL_PARAM params[]) { - OSSL_PARAM *p; - return SCOSSL_SUCCESS; } -const OSSL_PARAM *p_scossl_mlkem_gettable_ctx_params(ossl_unused void *ctx, ossl_unused void *provctx) +static SCOSSL_STATUS p_scossl_mlkem_get_ctx_params(ossl_unused void *ctx, ossl_unused OSSL_PARAM params[]) { - return p_scossl_mlkem_gettable_param_types; + return SCOSSL_SUCCESS; } -const OSSL_DISPATCH p_scossl_mlkem_functions[] = { +static const OSSL_DISPATCH p_scossl_mlkem_functions[] = { {OSSL_FUNC_KEM_NEWCTX, (void (*)(void))p_scossl_mlkem_newctx}, {OSSL_FUNC_KEM_FREECTX, (void (*)(void))p_scossl_mlkem_freectx}, {OSSL_FUNC_KEM_DUPCTX, (void (*)(void))p_scossl_mlkem_dupctx}, @@ -147,9 +227,9 @@ const OSSL_DISPATCH p_scossl_mlkem_functions[] = { {OSSL_FUNC_KEM_DECAPSULATE_INIT, (void (*)(void))p_scossl_mlkem_decapsulate_init}, {OSSL_FUNC_KEM_DECAPSULATE, (void (*)(void))p_scossl_mlkem_decapsulate}, {OSSL_FUNC_KEM_SET_CTX_PARAMS, (void (*)(void))p_scossl_mlkem_set_ctx_params}, - {OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_mlkem_settable_ctx_params}, + {OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_mlkem_ctx_param_types}, {OSSL_FUNC_KEM_GET_CTX_PARAMS, (void (*)(void))p_scossl_mlkem_get_ctx_params}, - {OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_mlkem_gettable_ctx_params}, + {OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_mlkem_ctx_param_types}, {0, NULL}}; #ifdef __cplusplus diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.h b/SymCryptProvider/src/kem/p_scossl_mlkem.h index 5aa250e5..0e2605ad 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.h +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.h @@ -9,7 +9,9 @@ extern "C" { #endif typedef struct { - BOOL initialized; + PSYMCRYPT_MLKEMKEY key; + PCSYMCRYPT_MLKEM_PARAMS params; + SYMCRYPT_MLKEMKEY_FORMAT format; } SCOSSL_MLKEM_KEY_CTX; #ifdef __cplusplus From b42de0672ccca4ac1b6ce228056bb2bdc196978b Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Thu, 26 Sep 2024 23:44:51 +0000 Subject: [PATCH 04/21] Update to latest APIs --- SymCryptProvider/src/kem/p_scossl_mlkem.c | 2 +- SymCryptProvider/src/kem/p_scossl_mlkem.h | 2 +- .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 126 ++++++++---------- SymCryptProvider/src/p_scossl_base.c | 6 - 4 files changed, 60 insertions(+), 76 deletions(-) diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.c b/SymCryptProvider/src/kem/p_scossl_mlkem.c index ba9306a5..f8db80eb 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.c +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.c @@ -218,7 +218,7 @@ static SCOSSL_STATUS p_scossl_mlkem_get_ctx_params(ossl_unused void *ctx, ossl_u return SCOSSL_SUCCESS; } -static const OSSL_DISPATCH p_scossl_mlkem_functions[] = { +const OSSL_DISPATCH p_scossl_mlkem_functions[] = { {OSSL_FUNC_KEM_NEWCTX, (void (*)(void))p_scossl_mlkem_newctx}, {OSSL_FUNC_KEM_FREECTX, (void (*)(void))p_scossl_mlkem_freectx}, {OSSL_FUNC_KEM_DUPCTX, (void (*)(void))p_scossl_mlkem_dupctx}, diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.h b/SymCryptProvider/src/kem/p_scossl_mlkem.h index 0e2605ad..2f01bd4c 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.h +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.h @@ -10,7 +10,7 @@ extern "C" { typedef struct { PSYMCRYPT_MLKEMKEY key; - PCSYMCRYPT_MLKEM_PARAMS params; + SYMCRYPT_MLKEM_PARAMS params; SYMCRYPT_MLKEMKEY_FORMAT format; } SCOSSL_MLKEM_KEY_CTX; diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index 0021aafa..d12a9b5e 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -12,12 +12,12 @@ extern "C" { #endif -#define SCOSSL_MLKEM_PARAM_NAME_512 "MK-KEM-512" -#define SCOSSL_MLKEM_PARAM_NAME_768 "ML-KEM-768" -#define SCOSSL_MLKEM_PARAM_NAME_1024 "ML-KEM-1024" +#define SCOSSL_MLKEM_PARAM_NAME_512 "mlkem512" +#define SCOSSL_MLKEM_PARAM_NAME_768 "mlkem768" +#define SCOSSL_MLKEM_PARAM_NAME_1024 "mlkem1024" typedef struct { - PCSYMCRYPT_MLKEM_PARAMS params; + SYMCRYPT_MLKEM_PARAMS params; } SCOSSL_MLKEM_KEYGEN_CTX; #define SCOSSL_MLKEM_PKEY_PARAMETER_TYPES \ @@ -64,8 +64,8 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_bytes(_In_ const SCOSSL_MLKE SYMCRYPT_MLKEMKEY_FORMAT format, _Out_writes_bytes_(*cbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); -static PCSYMCRYPT_MLKEM_PARAMS p_scossl_mlkem_keymgmt_params_from_name(_In_ const char *name); -static const char * p_scossl_mlkem_keymgmt_params_to_name(_In_ const PCSYMCRYPT_MLKEM_PARAMS name); +static SYMCRYPT_MLKEM_PARAMS p_scossl_mlkem_keymgmt_params_from_name(_In_ const char *name); +static const char * p_scossl_mlkem_keymgmt_params_to_name(_In_ const SYMCRYPT_MLKEM_PARAMS name); static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx); static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(ossl_unused void *provCtx) @@ -103,12 +103,12 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS } else { - copyCtx->params = NULL; + copyCtx->params = SYMCRYPT_MLKEM_PARAMS_NULL; } if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 && keyCtx->key != NULL) { - if (copyCtx->params == NULL) + if (copyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); goto cleanup; @@ -185,13 +185,13 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEYGE { const char *name; - if (!OSSL_PARAM_get_utf8_ptr(p, &name)) + if (!OSSL_PARAM_get_utf8_string_ptr(p, &name)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return SCOSSL_FAILURE; } - if ((genCtx->params = p_scossl_mlkem_keymgmt_params_from_name(name)) == NULL) + if ((genCtx->params = p_scossl_mlkem_keymgmt_params_from_name(name)) == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); return SCOSSL_FAILURE; @@ -218,7 +218,7 @@ static SCOSSL_MLKEM_KEYGEN_CTX *p_scossl_mlkem_keygen_init(ossl_unused void *pro if (genCtx != NULL) { - genCtx->params = SymCryptMlKemParamsDraft203MlKem768; + genCtx->params = SYMCRYPT_MLKEM_PARAMS_MLKEM768; if (p_scossl_mlkem_keygen_set_params(genCtx, params) != SCOSSL_SUCCESS) { @@ -239,7 +239,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEY return SCOSSL_FAILURE; } - if (tmplCtx->params == NULL) + if (tmplCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); return SCOSSL_FAILURE; @@ -300,6 +300,12 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_params(_In_ SCOSSL_MLKEM_KEY_CTX PCBYTE pbKey; SIZE_T cbKey; + if (keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); + return SCOSSL_FAILURE; + } + if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbKey, &cbKey)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); @@ -435,19 +441,17 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; OSSL_PARAM *p; - if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) + if (keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) { - if (keyCtx->params == NULL) - { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); - return SCOSSL_FAILURE; - } + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); + return SCOSSL_FAILURE; + } - if (!OSSL_PARAM_set_int(p, p_scossl_mlkem_keymgmt_get_security_bits(keyCtx))) - { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - return SCOSSL_FAILURE; - } + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL && + !OSSL_PARAM_set_int(p, p_scossl_mlkem_keymgmt_get_security_bits(keyCtx))) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; } if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL) @@ -455,12 +459,6 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX SIZE_T cbSize; SYMCRYPT_MLKEMKEY_FORMAT format = keyCtx->format; - if (keyCtx->params == NULL) - { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); - return SCOSSL_FAILURE; - } - // Default to larger size if key data is not set (and therefore format is unknown) if (format == SYMCRYPT_MLKEMKEY_FORMAT_NULL) { @@ -482,19 +480,11 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX } } - if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL) + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL && + !OSSL_PARAM_set_utf8_string(p, p_scossl_mlkem_keymgmt_params_to_name(keyCtx->params))) { - if (keyCtx->params == NULL) - { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); - return SCOSSL_FAILURE; - } - - if (!OSSL_PARAM_set_utf8_string(p, p_scossl_mlkem_keymgmt_params_to_name(keyCtx->params))) - { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - return SCOSSL_FAILURE; - } + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; } return p_scossl_mlkem_keymgmt_get_key_params(keyCtx, params); @@ -509,13 +499,13 @@ static BOOL p_scossl_mlkem_keymgmt_has(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int se } if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0 && - keyCtx->params != NULL) + keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) { return FALSE; } if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0 && - keyCtx->key != NULL) + keyCtx->key == NULL) { return FALSE; } @@ -659,13 +649,13 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX { const char *name; - if (!OSSL_PARAM_get_utf8_ptr(p, &name)) + if (!OSSL_PARAM_get_utf8_string_ptr(p, &name)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return SCOSSL_FAILURE; } - if ((keyCtx->params = p_scossl_mlkem_keymgmt_params_from_name(name)) == NULL) + if ((keyCtx->params = p_scossl_mlkem_keymgmt_params_from_name(name)) == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); return SCOSSL_FAILURE; @@ -749,7 +739,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *ke goto cleanup; } - if (keyCtx->params == NULL) + if (keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); goto cleanup; @@ -868,7 +858,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_bytes(const SCOSSL_MLKEM_KEY SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; - if (keyCtx->key == NULL || keyCtx->params == NULL) + if (keyCtx->key == NULL || keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); return SCOSSL_FAILURE; @@ -913,38 +903,38 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_bytes(const SCOSSL_MLKEM_KEY } _Use_decl_annotations_ -static PCSYMCRYPT_MLKEM_PARAMS p_scossl_mlkem_keymgmt_params_from_name(const char *name) +static SYMCRYPT_MLKEM_PARAMS p_scossl_mlkem_keymgmt_params_from_name(const char *name) { if (OPENSSL_strcasecmp(name, SCOSSL_MLKEM_PARAM_NAME_512) == 0) { - return SymCryptMlKemParamsDraft203MlKem512; + return SYMCRYPT_MLKEM_PARAMS_MLKEM512; } else if (OPENSSL_strcasecmp(name, SCOSSL_MLKEM_PARAM_NAME_768) == 0) { - return SymCryptMlKemParamsDraft203MlKem768; + return SYMCRYPT_MLKEM_PARAMS_MLKEM512; } else if (OPENSSL_strcasecmp(name, SCOSSL_MLKEM_PARAM_NAME_1024) == 0) { - return SymCryptMlKemParamsDraft203MlKem1024; + return SYMCRYPT_MLKEM_PARAMS_MLKEM512; } - return NULL; + return SYMCRYPT_MLKEM_PARAMS_NULL; } _Use_decl_annotations_ -static const char *p_scossl_mlkem_keymgmt_params_to_name(const PCSYMCRYPT_MLKEM_PARAMS params) +static const char *p_scossl_mlkem_keymgmt_params_to_name(const SYMCRYPT_MLKEM_PARAMS params) { - if (params == SymCryptMlKemParamsDraft203MlKem512) + switch (params) { + case SYMCRYPT_MLKEM_PARAMS_MLKEM512: return SCOSSL_MLKEM_PARAM_NAME_512; - } - else if (params == SymCryptMlKemParamsDraft203MlKem768) - { + case SYMCRYPT_MLKEM_PARAMS_MLKEM768: return SCOSSL_MLKEM_PARAM_NAME_768; - } - else if (params == SymCryptMlKemParamsDraft203MlKem1024) - { - return SCOSSL_MLKEM_PARAM_NAME_1024; + case SYMCRYPT_MLKEM_PARAMS_MLKEM1024: + return SCOSSL_MLKEM_PARAM_NAME_1024;\ + default: + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); + break; } return ""; @@ -953,17 +943,17 @@ static const char *p_scossl_mlkem_keymgmt_params_to_name(const PCSYMCRYPT_MLKEM_ _Use_decl_annotations_ static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx) { - if (keyCtx->params == SymCryptMlKemParamsDraft203MlKem512) + switch(keyCtx->params) { + case SYMCRYPT_MLKEM_PARAMS_MLKEM512: return 128; - } - else if (keyCtx->params == SymCryptMlKemParamsDraft203MlKem768) - { + case SYMCRYPT_MLKEM_PARAMS_MLKEM768: return 192; - } - else if (keyCtx->params == SymCryptMlKemParamsDraft203MlKem1024) - { + case SYMCRYPT_MLKEM_PARAMS_MLKEM1024: return 256; + default: + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); + break; } return 0; diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index 51324260..ef153ea6 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -266,9 +266,7 @@ static const OSSL_ALGORITHM p_scossl_keymgmt[] = { ALG("RSA-PSS:RSASSA-PSS:1.2.840.113549.1.1.10", p_scossl_rsapss_keymgmt_functions), ALG("TLS1-PRF", p_scossl_kdf_keymgmt_functions), ALG("X25519:1.3.101.110", p_scossl_x25519_keymgmt_functions), -#ifdef MLKEM_ENABLED ALG("MLKEM", p_scossl_mlkem_keymgmt_functions), -#endif ALG_TABLE_END}; // Key exchange @@ -303,16 +301,12 @@ static const OSSL_ALGORITHM p_scossl_asym_cipher[] = { ALG_TABLE_END}; // Key encapsulation - extern const OSSL_DISPATCH p_scossl_mlkem_functions[]; static const OSSL_ALGORITHM p_scossl_kem[] = { -#ifdef MLKEM_ENABLED ALG("MLKEM", p_scossl_mlkem_functions), -#endif ALG_TABLE_END}; - static int p_scossl_get_status() { return scossl_prov_initialized; From abe8cf7ae3e75118531edb3f35ac808bfe9cacc2 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Mon, 7 Oct 2024 22:38:59 +0000 Subject: [PATCH 05/21] ML-KEM decoder --- SymCryptProvider/CMakeLists.txt | 11 +- SymCryptProvider/inc/p_scossl_base.h.in | 3 + .../src/decoder/p_scossl_der_to_key.c | 372 ++++++++++++++++++ .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 16 +- SymCryptProvider/src/p_scossl_base.c | 45 ++- SymCryptProvider/src/p_scossl_bio.c | 157 ++++++++ SymCryptProvider/src/p_scossl_bio.h | 17 + 7 files changed, 608 insertions(+), 13 deletions(-) create mode 100644 SymCryptProvider/src/decoder/p_scossl_der_to_key.c create mode 100644 SymCryptProvider/src/p_scossl_bio.c create mode 100644 SymCryptProvider/src/p_scossl_bio.h diff --git a/SymCryptProvider/CMakeLists.txt b/SymCryptProvider/CMakeLists.txt index 2c99b489..5b9b1deb 100644 --- a/SymCryptProvider/CMakeLists.txt +++ b/SymCryptProvider/CMakeLists.txt @@ -18,6 +18,7 @@ find_library(SYMCRYPT_LIBRARY symcrypt PATHS ${CMAKE_SOURCE_DIR}) set(SCOSSL_SOURCES ./src/asymcipher/p_scossl_rsa_cipher.c + ./src/decoder/p_scossl_der_to_key.c ./src/ciphers/p_scossl_aes.c ./src/ciphers/p_scossl_aes_aead.c ./src/ciphers/p_scossl_aes_xts.c @@ -25,6 +26,7 @@ set(SCOSSL_SOURCES ./src/digests/p_scossl_digest_generic.c ./src/digests/p_scossl_shake.c ./src/digests/p_scossl_cshake.c + ./src/kem/p_scossl_mlkem.c ./src/kdf/p_scossl_hkdf.c ./src/kdf/p_scossl_kbkdf.c ./src/kdf/p_scossl_srtpkdf.c @@ -37,12 +39,14 @@ set(SCOSSL_SOURCES ./src/keymgmt/p_scossl_dh_keymgmt.c ./src/keymgmt/p_scossl_ecc_keymgmt.c ./src/keymgmt/p_scossl_kdf_keymgmt.c + ./src/keymgmt/p_scossl_mlkem_keymgmt.c ./src/keymgmt/p_scossl_rsa_keymgmt.c ./src/mac/p_scossl_cmac.c ./src/mac/p_scossl_hmac.c ./src/mac/p_scossl_kmac.c ./src/signature/p_scossl_ecdsa_signature.c ./src/signature/p_scossl_rsa_signature.c + ./src/p_scossl_bio.c ./src/p_scossl_ecc.c ./src/p_scossl_rand.c ./src/p_scossl_rsa.c @@ -55,13 +59,6 @@ if (KEYSINUSE_ENABLED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DKEYSINUSE_ENABLED") endif() -if (MLKEM_ENABLED) - list(APPEND SCOSSL_SOURCES ./src/kem/p_scossl_mlkem.c) - list(APPEND SCOSSL_SOURCES ./src/keymgmt/p_scossl_mlkem_keymgmt.c) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMLKEM_ENABLED") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMLKEM_ENABLED") -endif() - add_library(scossl_provider SHARED ${SCOSSL_SOURCES}) add_dependencies(scossl_provider scossl_common) diff --git a/SymCryptProvider/inc/p_scossl_base.h.in b/SymCryptProvider/inc/p_scossl_base.h.in index 4ddf3948..b07bebda 100644 --- a/SymCryptProvider/inc/p_scossl_base.h.in +++ b/SymCryptProvider/inc/p_scossl_base.h.in @@ -4,8 +4,10 @@ #pragma once +#include #include #include + #include "scossl_helpers.h" #ifdef __cplusplus @@ -20,6 +22,7 @@ typedef struct { OSSL_LIB_CTX *libctx; const OSSL_CORE_HANDLE *handle; + BIO_METHOD *coreBioMeth; } SCOSSL_PROVCTX; static const OSSL_PARAM p_scossl_param_types[] = { diff --git a/SymCryptProvider/src/decoder/p_scossl_der_to_key.c b/SymCryptProvider/src/decoder/p_scossl_der_to_key.c new file mode 100644 index 00000000..3a33ece4 --- /dev/null +++ b/SymCryptProvider/src/decoder/p_scossl_der_to_key.c @@ -0,0 +1,372 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "p_scossl_bio.h" +#include "kem/p_scossl_mlkem.h" + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + X509_ALGOR algorithm; + ASN1_BIT_STRING *subjectPublicKey; +} SUBJECT_PUBKEY_INFO; + +typedef struct +{ + const char *dataType; + const OSSL_DISPATCH *keymgmtFns; + int selection; + + SYMCRYPT_MLKEM_PARAMS mlkemParams; +} SCOSSL_KEYTYPE_DESC; + +typedef struct +{ + SCOSSL_PROVCTX *provctx; + + const SCOSSL_KEYTYPE_DESC *desc; + + OSSL_FUNC_keymgmt_free_fn *keymgmt_free; + OSSL_FUNC_keymgmt_export_fn *keymgmt_export; +} SCOSSL_DER_TO_KEY_CTX; + +ASN1_NDEF_SEQUENCE(SUBJECT_PUBKEY_INFO) = { + ASN1_SIMPLE(SUBJECT_PUBKEY_INFO, algorithm, X509_ALGOR), + ASN1_SIMPLE(SUBJECT_PUBKEY_INFO, subjectPublicKey, ASN1_BIT_STRING), +} ASN1_SEQUENCE_END(SUBJECT_PUBKEY_INFO) + +IMPLEMENT_ASN1_FUNCTIONS(SUBJECT_PUBKEY_INFO) + +static const OSSL_PARAM p_scossl_der_to_key_settable_param_types[] = { + OSSL_PARAM_END}; + +static SCOSSL_DER_TO_KEY_CTX *p_scossl_der_to_key_newctx(SCOSSL_PROVCTX *provctx, const SCOSSL_KEYTYPE_DESC *desc) +{ + SCOSSL_DER_TO_KEY_CTX *ctx = OPENSSL_zalloc(sizeof(SCOSSL_DER_TO_KEY_CTX)); + + if (ctx != NULL) + { + ctx->desc = desc; + ctx->provctx = provctx; + + for (const OSSL_DISPATCH *fn = desc->keymgmtFns; fn->function_id != 0; fn++) + { + switch (fn->function_id) + { + case OSSL_FUNC_KEYMGMT_FREE: + ctx->keymgmt_free = (OSSL_FUNC_keymgmt_free_fn *)fn->function; + break; + case OSSL_FUNC_KEYMGMT_EXPORT: + ctx->keymgmt_export = (OSSL_FUNC_keymgmt_export_fn *)fn->function; + break; + } + } + } + + return ctx; +} + +static void p_scossl_der_to_key_freectx(_Inout_ SCOSSL_DER_TO_KEY_CTX *ctx) +{ + if (ctx == NULL) + return; + + OPENSSL_free(ctx); +} + +static const OSSL_PARAM *p_scossl_der_to_key_settable_ctx_params(ossl_unused void *ctx) +{ + return p_scossl_der_to_key_settable_param_types; +} + +static SCOSSL_STATUS p_scossl_der_to_key_set_ctx_params(ossl_unused void *ctx, ossl_unused const OSSL_PARAM params[]) +{ + return SCOSSL_SUCCESS; +} + +static BOOL p_scossl_der_to_key_does_selection(_In_ SCOSSL_KEYTYPE_DESC *desc, int selection) +{ + if (selection == 0) + { + return TRUE; + } + + // Supporting private key implies supporting public key. + // Both imply supporting key parameters + + return ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) || + ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) || + ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0); +} + + +static SCOSSL_MLKEM_KEY_CTX *p_scossl_d2i_mlkem_PKCS8(_In_ const SCOSSL_KEYTYPE_DESC *desc, _In_ BIO *bio) +{ + PKCS8_PRIV_KEY_INFO *p8Info = NULL; + const unsigned char *pbKey = NULL; + int cbKey; + ASN1_OCTET_STRING *p8Data = NULL; + SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; + SYMCRYPT_MLKEMKEY_FORMAT decodeFormat = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; + SYMCRYPT_ERROR scError; + SCOSSL_STATUS status = SCOSSL_FAILURE; + + if (d2i_PKCS8_PRIV_KEY_INFO_bio(bio, &p8Info) == NULL || + !PKCS8_pkey_get0(NULL, &pbKey, &cbKey, NULL, p8Info) || + (p8Data = d2i_ASN1_OCTET_STRING(NULL, &pbKey, cbKey)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ASN1_R_DECODE_ERROR); + goto cleanup; + } + + pbKey = ASN1_STRING_get0_data(p8Data); + cbKey = ASN1_STRING_length(p8Data); + + if (cbKey == 64) + { + decodeFormat = SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED; + } + + if ((keyCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEY_CTX))) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + keyCtx->params = desc->mlkemParams; + keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; + + if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + scError = SymCryptMlKemkeySetValue( + pbKey, cbKey, + decodeFormat, + 0, + keyCtx->key); + + if (scError != SYMCRYPT_NO_ERROR) + { + SymCryptMlKemkeyFree(keyCtx->key); + keyCtx->key = NULL; + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + status = SCOSSL_SUCCESS; + +cleanup: + if (status != SCOSSL_SUCCESS) + { + OPENSSL_free(keyCtx); + keyCtx = NULL; + } + + ASN1_OCTET_STRING_free(p8Data); + PKCS8_PRIV_KEY_INFO_free(p8Info); + + return keyCtx; +} + +static SCOSSL_MLKEM_KEY_CTX *p_scossl_d2i_mlkem_PUBKEY(_In_ const SCOSSL_KEYTYPE_DESC *desc, _In_ BIO *bio) +{ + SUBJECT_PUBKEY_INFO *subjPubKeyInfo; + SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; + SYMCRYPT_ERROR scError; + SCOSSL_STATUS status = SCOSSL_FAILURE; + + if ((subjPubKeyInfo = OPENSSL_zalloc(sizeof(SUBJECT_PUBKEY_INFO))) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + if (ASN1_item_d2i_bio(ASN1_ITEM_rptr(SUBJECT_PUBKEY_INFO), bio, (ASN1_VALUE **)&subjPubKeyInfo) == NULL) + { + ERR_raise(ERR_LIB_PROV, ASN1_R_DECODE_ERROR); + goto cleanup; + } + + if ((keyCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEY_CTX))) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + keyCtx->params = desc->mlkemParams; + keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; + + if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + scError = SymCryptMlKemkeySetValue( + subjPubKeyInfo->subjectPublicKey->data, + subjPubKeyInfo->subjectPublicKey->length, + keyCtx->format, + 0, + keyCtx->key); + + if (scError != SYMCRYPT_NO_ERROR) + { + SymCryptMlKemkeyFree(keyCtx->key); + keyCtx->key = NULL; + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + status = SCOSSL_SUCCESS; + +cleanup: + if (status != SCOSSL_SUCCESS) + { + OPENSSL_free(keyCtx); + keyCtx = NULL; + } + + OPENSSL_free(subjPubKeyInfo); + + return keyCtx; +} + +// This function should return SCOSSL_SUCCESS if it successfully decodes something, +// or decodes nothing at all. Another decoder may be able to decode the data into something. +// This function should only return SCOSSL_FAILURE if the data could be decoded, but further +// validation of the data failed in a way that another decoder could not handle. +static SCOSSL_STATUS p_scossl_der_to_key_decode(_In_ SCOSSL_DER_TO_KEY_CTX *ctx, _In_ OSSL_CORE_BIO *in, + int selection, + _In_ OSSL_CALLBACK *dataCb, _In_ void *dataCbArg, + ossl_unused OSSL_PASSPHRASE_CALLBACK *passphraseCb, ossl_unused void *passphraseCbArg) +{ + BIO *bio = NULL; + SCOSSL_MLKEM_KEY_CTX *pKey = NULL; + OSSL_PARAM cbParams[4]; + SCOSSL_STATUS ret = SCOSSL_SUCCESS; + + if (selection == 0) + { + selection = ctx->desc->selection; + } + else if ((selection & ctx->desc->selection) == 0) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); + } + + if ((bio = p_scossl_bio_new_from_core_bio(ctx->provctx, in)) == NULL) + { + goto callback; + } + + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + { + pKey = p_scossl_d2i_mlkem_PKCS8(ctx->desc, bio); + if (!BIO_reset(bio)) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto callback; + } + } + + if (pKey == NULL && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + { + pKey = p_scossl_d2i_mlkem_PUBKEY(ctx->desc, bio); + } + +callback: + + if (pKey != NULL) + { + int objectType = OSSL_OBJECT_PKEY; + + cbParams[0] = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objectType); + cbParams[1] = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE, (char *)ctx->desc->dataType, 0); + cbParams[2] = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE, &pKey, sizeof(pKey)); + cbParams[3] = OSSL_PARAM_construct_end(); + + ret = dataCb(cbParams, dataCbArg); + } + + BIO_free(bio); + ctx->keymgmt_free(pKey); + + return ret; +} + +static SCOSSL_STATUS p_scossl_der_to_key_export_object(_In_ SCOSSL_DER_TO_KEY_CTX *ctx, + _In_reads_bytes_(cbObjRef) const void *pbObjRef, _In_ size_t cbObjRef, + _In_ OSSL_CALLBACK *exportCb, _In_ void *exportCbArg) +{ + SCOSSL_MLKEM_KEY_CTX *keyCtx = *(SCOSSL_MLKEM_KEY_CTX **)pbObjRef; + + if (cbObjRef != sizeof(SCOSSL_MLKEM_KEY_CTX *) || keyCtx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); + return SCOSSL_FAILURE; + } + + return ctx->keymgmt_export(keyCtx, ctx->desc->selection, exportCb, exportCbArg); +} + +#define SCOSSL_MAKE_MLKEM_DECODER(paramSet, decoderType, selectionType) \ + static SCOSSL_KEYTYPE_DESC p_scossl_mlkem##paramSet##_##decoderType##_desc = { \ + "MLKEM", \ + p_scossl_mlkem_keymgmt_functions, \ + selectionType, \ + SYMCRYPT_MLKEM_PARAMS_MLKEM##paramSet}; \ + \ + static SCOSSL_DER_TO_KEY_CTX * \ + p_scossl_der_to_mlkem##paramSet##_##decoderType##_newctx(_In_ SCOSSL_PROVCTX *provctx) \ + { \ + return p_scossl_der_to_key_newctx( \ + provctx, \ + &p_scossl_mlkem##paramSet##_##decoderType##_desc); \ + } \ + \ + static BOOL \ + p_scossl_der_to_mlkem##paramSet##_##decoderType##_does_selection( \ + ossl_unused void *provctx, \ + int selection) \ + { \ + return p_scossl_der_to_key_does_selection( \ + &p_scossl_mlkem##paramSet##_##decoderType##_desc, \ + selection); \ + } \ + \ + const OSSL_DISPATCH p_scossl_der_to_mlkem##paramSet##_##decoderType##_functions[] = { \ + {OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))p_scossl_der_to_mlkem##paramSet##_##decoderType##_newctx}, \ + {OSSL_FUNC_DECODER_FREECTX, (void (*)(void))p_scossl_der_to_key_freectx}, \ + {OSSL_FUNC_DECODER_SET_CTX_PARAMS, (void (*)(void))p_scossl_der_to_key_set_ctx_params}, \ + {OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_der_to_key_settable_ctx_params}, \ + {OSSL_FUNC_DECODER_DOES_SELECTION, (void (*)(void)) \ + p_scossl_der_to_mlkem##paramSet##_##decoderType##_does_selection}, \ + {OSSL_FUNC_DECODER_DECODE, (void (*)(void))p_scossl_der_to_key_decode}, \ + {OSSL_FUNC_DECODER_EXPORT_OBJECT, (void (*)(void))p_scossl_der_to_key_export_object}, \ + {0, NULL}}; + + +extern const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[]; + +SCOSSL_MAKE_MLKEM_DECODER(512, PrivateKeyInfo, OSSL_KEYMGMT_SELECT_PRIVATE_KEY); +SCOSSL_MAKE_MLKEM_DECODER(512, SubjectPublicKeyInfo, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); +SCOSSL_MAKE_MLKEM_DECODER(768, PrivateKeyInfo, OSSL_KEYMGMT_SELECT_PRIVATE_KEY); +SCOSSL_MAKE_MLKEM_DECODER(768, SubjectPublicKeyInfo, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); +SCOSSL_MAKE_MLKEM_DECODER(1024, PrivateKeyInfo, OSSL_KEYMGMT_SELECT_PRIVATE_KEY); +SCOSSL_MAKE_MLKEM_DECODER(1024, SubjectPublicKeyInfo, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index d12a9b5e..f97a6ae7 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -285,6 +285,19 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX return keyCtx; } +static const SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_load(const void *reference, size_t reference_size) +{ + SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; + + if (reference_size == sizeof(keyCtx)) + { + keyCtx = *(SCOSSL_MLKEM_KEY_CTX **)reference; + *(SCOSSL_MLKEM_KEY_CTX **)reference = NULL; + } + + return keyCtx; +} + static const OSSL_PARAM *p_scossl_mlkem_keymgmt_settable_params(ossl_unused void *provCtx) { return p_scossl_mlkem_keymgmt_settable_param_types; @@ -511,7 +524,7 @@ static BOOL p_scossl_mlkem_keymgmt_has(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int se } if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && - keyCtx->format == SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY) + keyCtx->format != SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY) { return FALSE; } @@ -832,6 +845,7 @@ const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[] = { {OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))p_scossl_mlkem_keygen_init}, {OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))p_scossl_mlkem_keygen_set_template}, {OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))p_scossl_mlkem_keygen}, + {OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))p_scossl_mlkem_keymgmt_load}, {OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))p_scossl_mlkem_keymgmt_settable_params}, {OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*)(void))p_scossl_mlkem_keymgmt_set_params}, {OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))p_scossl_mlkem_keymgmt_gettable_params}, diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index ef153ea6..e827d501 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -9,7 +9,7 @@ #include "scossl_dh.h" #include "scossl_ecc.h" #include "p_scossl_keysinuse.h" -#include "p_scossl_base.h" +#include "p_scossl_bio.h" #ifdef __cplusplus extern "C" { @@ -40,6 +40,15 @@ extern "C" { #define OSSL_TLS_GROUP_ID_ffdhe4096 0x0102 #define ALG(names, funcs) {names, "provider="P_SCOSSL_NAME",fips=yes", funcs, NULL} +#define ALG_DECODER(algNames, name, decoderType) { \ + algNames, \ + "provider="P_SCOSSL_NAME \ + ",fips=yes" \ + ",input=der" \ + ",structure="#decoderType, \ + p_scossl_der_to_##name##_##decoderType##_functions, \ + NULL} + #define ALG_TABLE_END {NULL, NULL, NULL, NULL} typedef struct { @@ -266,7 +275,7 @@ static const OSSL_ALGORITHM p_scossl_keymgmt[] = { ALG("RSA-PSS:RSASSA-PSS:1.2.840.113549.1.1.10", p_scossl_rsapss_keymgmt_functions), ALG("TLS1-PRF", p_scossl_kdf_keymgmt_functions), ALG("X25519:1.3.101.110", p_scossl_x25519_keymgmt_functions), - ALG("MLKEM", p_scossl_mlkem_keymgmt_functions), + ALG("MLKEM:mlkem512:mlkem768:mlkem1024", p_scossl_mlkem_keymgmt_functions), ALG_TABLE_END}; // Key exchange @@ -307,6 +316,23 @@ static const OSSL_ALGORITHM p_scossl_kem[] = { ALG("MLKEM", p_scossl_mlkem_functions), ALG_TABLE_END}; +// Decoders +extern const OSSL_DISPATCH p_scossl_der_to_mlkem512_PrivateKeyInfo_functions[]; +extern const OSSL_DISPATCH p_scossl_der_to_mlkem512_SubjectPublicKeyInfo_functions[]; +extern const OSSL_DISPATCH p_scossl_der_to_mlkem768_PrivateKeyInfo_functions[]; +extern const OSSL_DISPATCH p_scossl_der_to_mlkem768_SubjectPublicKeyInfo_functions[]; +extern const OSSL_DISPATCH p_scossl_der_to_mlkem1024_PrivateKeyInfo_functions[]; +extern const OSSL_DISPATCH p_scossl_der_to_mlkem1024_SubjectPublicKeyInfo_functions[]; + +static const OSSL_ALGORITHM p_scossl_decoder[] = { + ALG_DECODER("mlkem512:1.3.6.1.4.1.22554.5.6.1", mlkem512, PrivateKeyInfo), + ALG_DECODER("mlkem512:1.3.6.1.4.1.22554.5.6.1", mlkem512, SubjectPublicKeyInfo), + ALG_DECODER("mlkem768", mlkem768, PrivateKeyInfo), + ALG_DECODER("mlkem768", mlkem768, SubjectPublicKeyInfo), + ALG_DECODER("mlkem1024", mlkem1024, PrivateKeyInfo), + ALG_DECODER("mlkem1024", mlkem1024, SubjectPublicKeyInfo), + ALG_TABLE_END}; + static int p_scossl_get_status() { return scossl_prov_initialized; @@ -386,6 +412,8 @@ static const OSSL_ALGORITHM *p_scossl_query_operation(ossl_unused void *provctx, return p_scossl_asym_cipher; case OSSL_OP_KEM: return p_scossl_kem; + case OSSL_OP_DECODER: + return p_scossl_decoder; } return NULL; @@ -581,12 +609,12 @@ SCOSSL_STATUS OSSL_provider_init(_In_ const OSSL_CORE_HANDLE *handle, { SCOSSL_PROVCTX *p_ctx = NULL; - for (; in->function_id != 0; in++) + for (const OSSL_DISPATCH *coreFns = in; coreFns->function_id != 0; coreFns++) { - switch(in->function_id) + switch(coreFns->function_id) { case OSSL_FUNC_CORE_GET_PARAMS: - core_get_params = OSSL_FUNC_core_get_params(in); + core_get_params = OSSL_FUNC_core_get_params(coreFns); break; } } @@ -612,6 +640,13 @@ SCOSSL_STATUS OSSL_provider_init(_In_ const OSSL_CORE_HANDLE *handle, return SCOSSL_FAILURE; } + p_scossl_set_core_bio(in); + if ((p_ctx->coreBioMeth = p_scossl_bio_init()) == NULL) + { + OPENSSL_free(p_ctx); + return SCOSSL_FAILURE; + } + p_ctx->handle = handle; p_ctx->libctx = OSSL_LIB_CTX_new_child(handle, in); *provctx = p_ctx; diff --git a/SymCryptProvider/src/p_scossl_bio.c b/SymCryptProvider/src/p_scossl_bio.c new file mode 100644 index 00000000..6ef99ec4 --- /dev/null +++ b/SymCryptProvider/src/p_scossl_bio.c @@ -0,0 +1,157 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "p_scossl_bio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +OSSL_FUNC_BIO_read_ex_fn *core_bio_read_ex = NULL; +OSSL_FUNC_BIO_write_ex_fn *core_bio_write_ex = NULL; +OSSL_FUNC_BIO_up_ref_fn *core_bio_up_ref = NULL; +OSSL_FUNC_BIO_free_fn *core_bio_free = NULL; +OSSL_FUNC_BIO_gets_fn *core_bio_gets = NULL; +OSSL_FUNC_BIO_puts_fn *core_bio_puts = NULL; +OSSL_FUNC_BIO_ctrl_fn *core_bio_ctrl = NULL; + +static int p_scossl_bio_core_read_ex(BIO *bio, char *data, size_t data_len, + size_t *bytes_read) +{ + if (core_bio_read_ex == NULL) + return 0; + + return core_bio_read_ex(BIO_get_data(bio), data, data_len, bytes_read); +} + +static int p_scossl_bio_core_write_ex(BIO *bio, const char *data, size_t data_len, + size_t *written) +{ + if (core_bio_write_ex == NULL) + return 0; + + return core_bio_write_ex(BIO_get_data(bio), data, data_len, written); +} + +static int p_scossl_bio_core_create(BIO *bio) +{ + BIO_set_init(bio, 1); + + return 1; +} + +static int p_scossl_bio_core_destroy(BIO *bio) +{ + BIO_set_init(bio, 0); + + if (core_bio_free != NULL) + core_bio_free(BIO_get_data(bio)); + + return 1; +} + +static long p_scossl_bio_core_ctrl(BIO *bio, int cmd, long num, void *ptr) +{ + if (core_bio_ctrl == NULL) + return 0; + + return core_bio_ctrl(BIO_get_data(bio), cmd, num, ptr); +} + +static int p_scossl_bio_core_gets(BIO *bio, char *buf, int size) +{ + if (core_bio_gets == NULL) + return 0; + + return core_bio_gets(BIO_get_data(bio), buf, size); +} + +static int p_scossl_bio_core_puts(BIO *bio, const char *str) +{ + if (core_bio_puts == NULL) + return 0; + + return core_bio_puts(BIO_get_data(bio), str); +} + +_Use_decl_annotations_ +void p_scossl_set_core_bio(const OSSL_DISPATCH *dispatch) +{ + for (const OSSL_DISPATCH *coreFns = dispatch; coreFns->function_id != 0; coreFns++) + { + switch (coreFns->function_id) + { + case OSSL_FUNC_BIO_READ_EX: + core_bio_read_ex = (OSSL_FUNC_BIO_read_ex_fn *)coreFns->function; + break; + case OSSL_FUNC_BIO_WRITE_EX: + core_bio_write_ex = (OSSL_FUNC_BIO_write_ex_fn *)coreFns->function; + break; + case OSSL_FUNC_BIO_UP_REF: + core_bio_up_ref = (OSSL_FUNC_BIO_up_ref_fn *)coreFns->function; + break; + case OSSL_FUNC_BIO_FREE: + core_bio_free = (OSSL_FUNC_BIO_free_fn *)coreFns->function; + break; + case OSSL_FUNC_BIO_PUTS: + core_bio_puts = (OSSL_FUNC_BIO_puts_fn *)coreFns->function; + break; + case OSSL_FUNC_BIO_GETS: + core_bio_gets = (OSSL_FUNC_BIO_gets_fn *)coreFns->function; + break; + case OSSL_FUNC_BIO_CTRL: + core_bio_ctrl = (OSSL_FUNC_BIO_ctrl_fn *)coreFns->function; + break; + } + } +} + +BIO_METHOD *p_scossl_bio_init() +{ + BIO_METHOD *coreBioMeth = BIO_meth_new(BIO_TYPE_CORE_TO_PROV, "SCOSSL BIO to core filter"); + + if (coreBioMeth != NULL && + (!BIO_meth_set_read_ex(coreBioMeth, p_scossl_bio_core_read_ex) || + !BIO_meth_set_write_ex(coreBioMeth, p_scossl_bio_core_write_ex) || + !BIO_meth_set_create(coreBioMeth, p_scossl_bio_core_create) || + !BIO_meth_set_destroy(coreBioMeth, p_scossl_bio_core_destroy) || + !BIO_meth_set_gets(coreBioMeth, p_scossl_bio_core_gets) || + !BIO_meth_set_puts(coreBioMeth, p_scossl_bio_core_puts) || + !BIO_meth_set_ctrl(coreBioMeth, p_scossl_bio_core_ctrl))) + { + BIO_meth_free(coreBioMeth); + coreBioMeth = NULL; + } + + return coreBioMeth; +} + +_Use_decl_annotations_ +BIO *p_scossl_bio_new_from_core_bio(SCOSSL_PROVCTX *provctx, OSSL_CORE_BIO *coreBio) +{ + BIO *bio; + + if (provctx->coreBioMeth == NULL) + { + return NULL; + } + + if ((bio = BIO_new(provctx->coreBioMeth)) != NULL) + { + if (core_bio_up_ref == NULL || + !core_bio_up_ref(coreBio)) + { + BIO_free(bio); + return NULL; + } + + BIO_set_data(bio, coreBio); + } + + return bio; +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/p_scossl_bio.h b/SymCryptProvider/src/p_scossl_bio.h new file mode 100644 index 00000000..769b8ca6 --- /dev/null +++ b/SymCryptProvider/src/p_scossl_bio.h @@ -0,0 +1,17 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "p_scossl_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void p_scossl_set_core_bio(_In_ const OSSL_DISPATCH *dispatch); +BIO_METHOD *p_scossl_bio_init(); +BIO *p_scossl_bio_new_from_core_bio(_In_ SCOSSL_PROVCTX *provctx, _In_ OSSL_CORE_BIO *coreBio); + +#ifdef __cplusplus +} +#endif \ No newline at end of file From f4ba041b3d43f4896623beec7445b62a3a4ae90a Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Fri, 18 Oct 2024 00:22:36 +0000 Subject: [PATCH 06/21] MLKEM PEM and DER encoder. Refactor decoder --- SymCryptProvider/CMakeLists.txt | 5 +- .../src/decoder/p_scossl_decode_common.c | 127 ++++++ .../src/decoder/p_scossl_decode_common.h | 59 +++ .../src/decoder/p_scossl_decode_mlkem.c | 213 ++++++++++ .../src/decoder/p_scossl_der_to_key.c | 372 ----------------- .../src/encoder/p_scossl_encode_common.c | 149 +++++++ .../src/encoder/p_scossl_encode_common.h | 61 +++ .../src/encoder/p_scossl_encode_mlkem.c | 377 ++++++++++++++++++ .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 22 +- .../src/keymgmt/p_scossl_mlkem_keymgmt.h | 24 ++ SymCryptProvider/src/p_scossl_base.c | 157 +++++--- SymCryptProvider/src/p_scossl_names.h | 90 +++++ 12 files changed, 1213 insertions(+), 443 deletions(-) create mode 100644 SymCryptProvider/src/decoder/p_scossl_decode_common.c create mode 100644 SymCryptProvider/src/decoder/p_scossl_decode_common.h create mode 100644 SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c delete mode 100644 SymCryptProvider/src/decoder/p_scossl_der_to_key.c create mode 100644 SymCryptProvider/src/encoder/p_scossl_encode_common.c create mode 100644 SymCryptProvider/src/encoder/p_scossl_encode_common.h create mode 100644 SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c create mode 100644 SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h create mode 100644 SymCryptProvider/src/p_scossl_names.h diff --git a/SymCryptProvider/CMakeLists.txt b/SymCryptProvider/CMakeLists.txt index 5b9b1deb..c76caf2f 100644 --- a/SymCryptProvider/CMakeLists.txt +++ b/SymCryptProvider/CMakeLists.txt @@ -18,7 +18,6 @@ find_library(SYMCRYPT_LIBRARY symcrypt PATHS ${CMAKE_SOURCE_DIR}) set(SCOSSL_SOURCES ./src/asymcipher/p_scossl_rsa_cipher.c - ./src/decoder/p_scossl_der_to_key.c ./src/ciphers/p_scossl_aes.c ./src/ciphers/p_scossl_aes_aead.c ./src/ciphers/p_scossl_aes_xts.c @@ -26,6 +25,10 @@ set(SCOSSL_SOURCES ./src/digests/p_scossl_digest_generic.c ./src/digests/p_scossl_shake.c ./src/digests/p_scossl_cshake.c + ./src/decoder/p_scossl_decode_common.c + ./src/decoder/p_scossl_decode_mlkem.c + ./src/encoder/p_scossl_encode_common.c + ./src/encoder/p_scossl_encode_mlkem.c ./src/kem/p_scossl_mlkem.c ./src/kdf/p_scossl_hkdf.c ./src/kdf/p_scossl_kbkdf.c diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_common.c b/SymCryptProvider/src/decoder/p_scossl_decode_common.c new file mode 100644 index 00000000..dd84a865 --- /dev/null +++ b/SymCryptProvider/src/decoder/p_scossl_decode_common.c @@ -0,0 +1,127 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "p_scossl_bio.h" +#include "decoder/p_scossl_decode_common.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +ASN1_NDEF_SEQUENCE(SUBJECT_PUBKEY_INFO) = { + ASN1_SIMPLE(SUBJECT_PUBKEY_INFO, algorithm, X509_ALGOR), + ASN1_SIMPLE(SUBJECT_PUBKEY_INFO, subjectPublicKey, ASN1_BIT_STRING), +} ASN1_SEQUENCE_END(SUBJECT_PUBKEY_INFO) + +IMPLEMENT_ASN1_FUNCTIONS(SUBJECT_PUBKEY_INFO) + +const OSSL_PARAM p_scossl_der_to_key_settable_param_types[] = { + OSSL_PARAM_END}; + +_Use_decl_annotations_ +SCOSSL_DECODE_CTX *p_scossl_decode_newctx(SCOSSL_PROVCTX *provctx, const SCOSSL_DECODE_KEYTYPE_DESC *desc) +{ + SCOSSL_DECODE_CTX *ctx = OPENSSL_zalloc(sizeof(SCOSSL_DECODE_CTX)); + + if (ctx != NULL) + { + ctx->provctx = provctx; + ctx->desc = desc; + } + + return ctx; +} + +_Use_decl_annotations_ +void p_scossl_decode_freectx(SCOSSL_DECODE_CTX *ctx) +{ + if (ctx == NULL) + return; + + OPENSSL_free(ctx); +} + +const OSSL_PARAM *p_scossl_decode_settable_ctx_params(ossl_unused void *ctx) +{ + return p_scossl_der_to_key_settable_param_types; +} + +SCOSSL_STATUS p_scossl_decode_set_ctx_params(ossl_unused void *ctx, ossl_unused const OSSL_PARAM params[]) +{ + return SCOSSL_SUCCESS; +} + +_Use_decl_annotations_ +BOOL p_scossl_decode_does_selection(SCOSSL_DECODE_KEYTYPE_DESC *desc, int selection) +{ + if (selection == 0) + { + return TRUE; + } + + // Supporting private key implies supporting public key. + // Both imply supporting key parameters + + return ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) || + ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) || + ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0); +} + +// This function should return SCOSSL_SUCCESS if it successfully decodes something, +// or decodes nothing at all. Another decoder may be able to decode the data into something. +// This function should only return SCOSSL_FAILURE if the data could be decoded, but further +// validation of the data failed in a way that another decoder could not handle. +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_decode(SCOSSL_DECODE_CTX *ctx, OSSL_CORE_BIO *in, int selection, + OSSL_CALLBACK *dataCb, void *dataCbArg, + ossl_unused OSSL_PASSPHRASE_CALLBACK *passphraseCb, ossl_unused void *passphraseCbArg) +{ + BIO *bio = NULL; + PVOID *keyCtx = NULL; + OSSL_PARAM cbParams[4]; + SCOSSL_STATUS ret = SCOSSL_SUCCESS; + + if (selection == 0) + { + selection = ctx->desc->selection; + } + else if ((selection & ctx->desc->selection) == 0) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); + } + + if ((bio = p_scossl_bio_new_from_core_bio(ctx->provctx, in)) != NULL) + { + keyCtx = ctx->desc->decodeInternal(ctx->desc, bio); + } + + if (keyCtx != NULL) + { + int objectType = OSSL_OBJECT_PKEY; + + cbParams[0] = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objectType); + cbParams[1] = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE, (char *)ctx->desc->dataType, 0); + cbParams[2] = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE, &keyCtx, sizeof(keyCtx)); + cbParams[3] = OSSL_PARAM_construct_end(); + + ret = dataCb(cbParams, dataCbArg); + } + + BIO_free(bio); + ctx->desc->freeKeyCtx(keyCtx); + + return ret; +} + +const ASN1_ITEM *p_scossl_decode_get_pubkey_asn1_item() +{ + return ASN1_ITEM_rptr(SUBJECT_PUBKEY_INFO); +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_common.h b/SymCryptProvider/src/decoder/p_scossl_decode_common.h new file mode 100644 index 00000000..20b1f3ce --- /dev/null +++ b/SymCryptProvider/src/decoder/p_scossl_decode_common.h @@ -0,0 +1,59 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "p_scossl_base.h" +#include "kem/p_scossl_mlkem.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define select_PrivateKeyInfo OSSL_KEYMGMT_SELECT_PRIVATE_KEY +#define select_SubjectPublicKeyInfo OSSL_KEYMGMT_SELECT_PUBLIC_KEY + +typedef PVOID (*PSCOSSL_DECODE_INTERNAL_FN) (_In_ PCVOID desc, _In_ BIO *bio); + +typedef struct +{ + const char *dataType; + int selection; + + PSCOSSL_DECODE_INTERNAL_FN decodeInternal; + OSSL_FUNC_keymgmt_free_fn *freeKeyCtx; + + // Contains type-specific key parameters (e.g. ML-KEM params, EC curve, etc.) + UINT64 keyParams; +} SCOSSL_DECODE_KEYTYPE_DESC; + +typedef struct +{ + SCOSSL_PROVCTX *provctx; + + const SCOSSL_DECODE_KEYTYPE_DESC *desc; +} SCOSSL_DECODE_CTX; + +typedef struct +{ + X509_ALGOR algorithm; + ASN1_BIT_STRING *subjectPublicKey; +} SUBJECT_PUBKEY_INFO; + +SCOSSL_DECODE_CTX *p_scossl_decode_newctx(_In_ SCOSSL_PROVCTX *provctx, _In_ const SCOSSL_DECODE_KEYTYPE_DESC *desc); +void p_scossl_decode_freectx(_Inout_ SCOSSL_DECODE_CTX *ctx); + +const OSSL_PARAM *p_scossl_decode_settable_ctx_params(ossl_unused void *ctx); +SCOSSL_STATUS p_scossl_decode_set_ctx_params(ossl_unused void *ctx, ossl_unused const OSSL_PARAM params[]); + +BOOL p_scossl_decode_does_selection(_In_ SCOSSL_DECODE_KEYTYPE_DESC *desc, int selection); + +SCOSSL_STATUS p_scossl_decode(_In_ SCOSSL_DECODE_CTX *ctx, _In_ OSSL_CORE_BIO *in, + int selection, + _In_ OSSL_CALLBACK *dataCb, _In_ void *dataCbArg, + ossl_unused OSSL_PASSPHRASE_CALLBACK *passphraseCb, ossl_unused void *passphraseCbArg); + +const ASN1_ITEM *p_scossl_decode_get_pubkey_asn1_item(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c new file mode 100644 index 00000000..6d7c8944 --- /dev/null +++ b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c @@ -0,0 +1,213 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "decoder/p_scossl_decode_common.h" +#include "keymgmt/p_scossl_mlkem_keymgmt.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static SCOSSL_MLKEM_KEY_CTX *p_scossl_PrivateKeyInfo_to_mlkem(_In_ const SCOSSL_DECODE_KEYTYPE_DESC *desc, _In_ BIO *bio) +{ + PKCS8_PRIV_KEY_INFO *p8Info = NULL; + const unsigned char *pbKey = NULL; + int cbKey; + ASN1_OCTET_STRING *p8Data = NULL; + SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; + SYMCRYPT_MLKEMKEY_FORMAT decodeFormat = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; + SYMCRYPT_ERROR scError; + SCOSSL_STATUS status = SCOSSL_FAILURE; + + if (d2i_PKCS8_PRIV_KEY_INFO_bio(bio, &p8Info) == NULL || + !PKCS8_pkey_get0(NULL, &pbKey, &cbKey, NULL, p8Info) || + (p8Data = d2i_ASN1_OCTET_STRING(NULL, &pbKey, cbKey)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ASN1_R_DECODE_ERROR); + goto cleanup; + } + + pbKey = ASN1_STRING_get0_data(p8Data); + cbKey = ASN1_STRING_length(p8Data); + + if (cbKey == 64) + { + decodeFormat = SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED; + } + + if ((keyCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEY_CTX))) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + keyCtx->params = (SYMCRYPT_MLKEM_PARAMS)desc->keyParams;; + keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; + + if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + scError = SymCryptMlKemkeySetValue( + pbKey, cbKey, + decodeFormat, + 0, + keyCtx->key); + + if (scError != SYMCRYPT_NO_ERROR) + { + SymCryptMlKemkeyFree(keyCtx->key); + keyCtx->key = NULL; + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + status = SCOSSL_SUCCESS; + +cleanup: + if (status != SCOSSL_SUCCESS) + { + OPENSSL_free(keyCtx); + keyCtx = NULL; + } + + ASN1_OCTET_STRING_free(p8Data); + PKCS8_PRIV_KEY_INFO_free(p8Info); + + return keyCtx; +} + +static SCOSSL_MLKEM_KEY_CTX *p_scossl_SubjectPublicKeyInfo_to_mlkem(_In_ const SCOSSL_DECODE_KEYTYPE_DESC *desc, _In_ BIO *bio) +{ + SUBJECT_PUBKEY_INFO *subjPubKeyInfo; + SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; + SYMCRYPT_ERROR scError; + SCOSSL_STATUS status = SCOSSL_FAILURE; + + if ((subjPubKeyInfo = OPENSSL_zalloc(sizeof(SUBJECT_PUBKEY_INFO))) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + if (ASN1_item_d2i_bio(p_scossl_decode_get_pubkey_asn1_item(), bio, (ASN1_VALUE **)&subjPubKeyInfo) == NULL) + { + ERR_raise(ERR_LIB_PROV, ASN1_R_DECODE_ERROR); + goto cleanup; + } + + if ((keyCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEY_CTX))) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + keyCtx->params = (SYMCRYPT_MLKEM_PARAMS)desc->keyParams; + keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; + + if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + scError = SymCryptMlKemkeySetValue( + subjPubKeyInfo->subjectPublicKey->data, + subjPubKeyInfo->subjectPublicKey->length, + keyCtx->format, + 0, + keyCtx->key); + + if (scError != SYMCRYPT_NO_ERROR) + { + SymCryptMlKemkeyFree(keyCtx->key); + keyCtx->key = NULL; + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + status = SCOSSL_SUCCESS; + +cleanup: + if (status != SCOSSL_SUCCESS) + { + OPENSSL_free(keyCtx); + keyCtx = NULL; + } + + OPENSSL_free(subjPubKeyInfo); + + return keyCtx; +} + +static SCOSSL_STATUS p_scossl_der_to_mlkem_export_object(_In_ SCOSSL_DECODE_CTX *ctx, + _In_reads_bytes_(cbObjRef) const void *pbObjRef, _In_ size_t cbObjRef, + _In_ OSSL_CALLBACK *exportCb, _In_ void *exportCbArg) +{ + SCOSSL_MLKEM_KEY_CTX *keyCtx = *(SCOSSL_MLKEM_KEY_CTX **)pbObjRef; + + if (cbObjRef != sizeof(SCOSSL_MLKEM_KEY_CTX *) || keyCtx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); + return SCOSSL_FAILURE; + } + + return p_scossl_mlkem_keymgmt_export(keyCtx, ctx->desc->selection, exportCb, exportCbArg); +} + +#define SCOSSL_MAKE_MLKEM_DECODER(paramSet, decoderType) \ + static SCOSSL_DECODE_KEYTYPE_DESC p_scossl_mlkem##paramSet##_##decoderType##_desc = { \ + "MLKEM", \ + select_##decoderType, \ + (PSCOSSL_DECODE_INTERNAL_FN)p_scossl_##decoderType##_to_mlkem, \ + (OSSL_FUNC_keymgmt_free_fn *)p_scossl_mlkem_keymgmt_free_key_ctx, \ + SYMCRYPT_MLKEM_PARAMS_MLKEM##paramSet}; \ + \ + static SCOSSL_DECODE_CTX * \ + p_scossl_der_to_mlkem##paramSet##_##decoderType##_newctx(_In_ SCOSSL_PROVCTX *provctx) \ + { \ + return p_scossl_decode_newctx( \ + provctx, \ + &p_scossl_mlkem##paramSet##_##decoderType##_desc); \ + } \ + \ + static BOOL \ + p_scossl_der_to_mlkem##paramSet##_##decoderType##_does_selection( \ + ossl_unused void *provctx, \ + int selection) \ + { \ + return p_scossl_decode_does_selection( \ + &p_scossl_mlkem##paramSet##_##decoderType##_desc, \ + selection); \ + } \ + \ + const OSSL_DISPATCH p_scossl_der_to_mlkem##paramSet##_##decoderType##_functions[] = { \ + {OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))p_scossl_der_to_mlkem##paramSet##_##decoderType##_newctx}, \ + {OSSL_FUNC_DECODER_FREECTX, (void (*)(void))p_scossl_decode_freectx}, \ + {OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_decode_settable_ctx_params}, \ + {OSSL_FUNC_DECODER_SET_CTX_PARAMS, (void (*)(void))p_scossl_decode_set_ctx_params}, \ + {OSSL_FUNC_DECODER_DOES_SELECTION, (void (*)(void)) \ + p_scossl_der_to_mlkem##paramSet##_##decoderType##_does_selection}, \ + {OSSL_FUNC_DECODER_DECODE, (void (*)(void))p_scossl_decode}, \ + {OSSL_FUNC_DECODER_EXPORT_OBJECT, (void (*)(void))p_scossl_der_to_mlkem_export_object}, \ + {0, NULL}}; + + +extern const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[]; + +SCOSSL_MAKE_MLKEM_DECODER(512, PrivateKeyInfo); +SCOSSL_MAKE_MLKEM_DECODER(512, SubjectPublicKeyInfo); +SCOSSL_MAKE_MLKEM_DECODER(768, PrivateKeyInfo); +SCOSSL_MAKE_MLKEM_DECODER(768, SubjectPublicKeyInfo); +SCOSSL_MAKE_MLKEM_DECODER(1024, PrivateKeyInfo); +SCOSSL_MAKE_MLKEM_DECODER(1024, SubjectPublicKeyInfo); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/decoder/p_scossl_der_to_key.c b/SymCryptProvider/src/decoder/p_scossl_der_to_key.c deleted file mode 100644 index 3a33ece4..00000000 --- a/SymCryptProvider/src/decoder/p_scossl_der_to_key.c +++ /dev/null @@ -1,372 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. Licensed under the MIT license. -// - -#include "p_scossl_bio.h" -#include "kem/p_scossl_mlkem.h" - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct -{ - X509_ALGOR algorithm; - ASN1_BIT_STRING *subjectPublicKey; -} SUBJECT_PUBKEY_INFO; - -typedef struct -{ - const char *dataType; - const OSSL_DISPATCH *keymgmtFns; - int selection; - - SYMCRYPT_MLKEM_PARAMS mlkemParams; -} SCOSSL_KEYTYPE_DESC; - -typedef struct -{ - SCOSSL_PROVCTX *provctx; - - const SCOSSL_KEYTYPE_DESC *desc; - - OSSL_FUNC_keymgmt_free_fn *keymgmt_free; - OSSL_FUNC_keymgmt_export_fn *keymgmt_export; -} SCOSSL_DER_TO_KEY_CTX; - -ASN1_NDEF_SEQUENCE(SUBJECT_PUBKEY_INFO) = { - ASN1_SIMPLE(SUBJECT_PUBKEY_INFO, algorithm, X509_ALGOR), - ASN1_SIMPLE(SUBJECT_PUBKEY_INFO, subjectPublicKey, ASN1_BIT_STRING), -} ASN1_SEQUENCE_END(SUBJECT_PUBKEY_INFO) - -IMPLEMENT_ASN1_FUNCTIONS(SUBJECT_PUBKEY_INFO) - -static const OSSL_PARAM p_scossl_der_to_key_settable_param_types[] = { - OSSL_PARAM_END}; - -static SCOSSL_DER_TO_KEY_CTX *p_scossl_der_to_key_newctx(SCOSSL_PROVCTX *provctx, const SCOSSL_KEYTYPE_DESC *desc) -{ - SCOSSL_DER_TO_KEY_CTX *ctx = OPENSSL_zalloc(sizeof(SCOSSL_DER_TO_KEY_CTX)); - - if (ctx != NULL) - { - ctx->desc = desc; - ctx->provctx = provctx; - - for (const OSSL_DISPATCH *fn = desc->keymgmtFns; fn->function_id != 0; fn++) - { - switch (fn->function_id) - { - case OSSL_FUNC_KEYMGMT_FREE: - ctx->keymgmt_free = (OSSL_FUNC_keymgmt_free_fn *)fn->function; - break; - case OSSL_FUNC_KEYMGMT_EXPORT: - ctx->keymgmt_export = (OSSL_FUNC_keymgmt_export_fn *)fn->function; - break; - } - } - } - - return ctx; -} - -static void p_scossl_der_to_key_freectx(_Inout_ SCOSSL_DER_TO_KEY_CTX *ctx) -{ - if (ctx == NULL) - return; - - OPENSSL_free(ctx); -} - -static const OSSL_PARAM *p_scossl_der_to_key_settable_ctx_params(ossl_unused void *ctx) -{ - return p_scossl_der_to_key_settable_param_types; -} - -static SCOSSL_STATUS p_scossl_der_to_key_set_ctx_params(ossl_unused void *ctx, ossl_unused const OSSL_PARAM params[]) -{ - return SCOSSL_SUCCESS; -} - -static BOOL p_scossl_der_to_key_does_selection(_In_ SCOSSL_KEYTYPE_DESC *desc, int selection) -{ - if (selection == 0) - { - return TRUE; - } - - // Supporting private key implies supporting public key. - // Both imply supporting key parameters - - return ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) || - ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) || - ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0); -} - - -static SCOSSL_MLKEM_KEY_CTX *p_scossl_d2i_mlkem_PKCS8(_In_ const SCOSSL_KEYTYPE_DESC *desc, _In_ BIO *bio) -{ - PKCS8_PRIV_KEY_INFO *p8Info = NULL; - const unsigned char *pbKey = NULL; - int cbKey; - ASN1_OCTET_STRING *p8Data = NULL; - SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; - SYMCRYPT_MLKEMKEY_FORMAT decodeFormat = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; - SYMCRYPT_ERROR scError; - SCOSSL_STATUS status = SCOSSL_FAILURE; - - if (d2i_PKCS8_PRIV_KEY_INFO_bio(bio, &p8Info) == NULL || - !PKCS8_pkey_get0(NULL, &pbKey, &cbKey, NULL, p8Info) || - (p8Data = d2i_ASN1_OCTET_STRING(NULL, &pbKey, cbKey)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ASN1_R_DECODE_ERROR); - goto cleanup; - } - - pbKey = ASN1_STRING_get0_data(p8Data); - cbKey = ASN1_STRING_length(p8Data); - - if (cbKey == 64) - { - decodeFormat = SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED; - } - - if ((keyCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEY_CTX))) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - keyCtx->params = desc->mlkemParams; - keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; - - if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - scError = SymCryptMlKemkeySetValue( - pbKey, cbKey, - decodeFormat, - 0, - keyCtx->key); - - if (scError != SYMCRYPT_NO_ERROR) - { - SymCryptMlKemkeyFree(keyCtx->key); - keyCtx->key = NULL; - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - goto cleanup; - } - - status = SCOSSL_SUCCESS; - -cleanup: - if (status != SCOSSL_SUCCESS) - { - OPENSSL_free(keyCtx); - keyCtx = NULL; - } - - ASN1_OCTET_STRING_free(p8Data); - PKCS8_PRIV_KEY_INFO_free(p8Info); - - return keyCtx; -} - -static SCOSSL_MLKEM_KEY_CTX *p_scossl_d2i_mlkem_PUBKEY(_In_ const SCOSSL_KEYTYPE_DESC *desc, _In_ BIO *bio) -{ - SUBJECT_PUBKEY_INFO *subjPubKeyInfo; - SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; - SYMCRYPT_ERROR scError; - SCOSSL_STATUS status = SCOSSL_FAILURE; - - if ((subjPubKeyInfo = OPENSSL_zalloc(sizeof(SUBJECT_PUBKEY_INFO))) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - if (ASN1_item_d2i_bio(ASN1_ITEM_rptr(SUBJECT_PUBKEY_INFO), bio, (ASN1_VALUE **)&subjPubKeyInfo) == NULL) - { - ERR_raise(ERR_LIB_PROV, ASN1_R_DECODE_ERROR); - goto cleanup; - } - - if ((keyCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEY_CTX))) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - keyCtx->params = desc->mlkemParams; - keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; - - if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - scError = SymCryptMlKemkeySetValue( - subjPubKeyInfo->subjectPublicKey->data, - subjPubKeyInfo->subjectPublicKey->length, - keyCtx->format, - 0, - keyCtx->key); - - if (scError != SYMCRYPT_NO_ERROR) - { - SymCryptMlKemkeyFree(keyCtx->key); - keyCtx->key = NULL; - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - goto cleanup; - } - - status = SCOSSL_SUCCESS; - -cleanup: - if (status != SCOSSL_SUCCESS) - { - OPENSSL_free(keyCtx); - keyCtx = NULL; - } - - OPENSSL_free(subjPubKeyInfo); - - return keyCtx; -} - -// This function should return SCOSSL_SUCCESS if it successfully decodes something, -// or decodes nothing at all. Another decoder may be able to decode the data into something. -// This function should only return SCOSSL_FAILURE if the data could be decoded, but further -// validation of the data failed in a way that another decoder could not handle. -static SCOSSL_STATUS p_scossl_der_to_key_decode(_In_ SCOSSL_DER_TO_KEY_CTX *ctx, _In_ OSSL_CORE_BIO *in, - int selection, - _In_ OSSL_CALLBACK *dataCb, _In_ void *dataCbArg, - ossl_unused OSSL_PASSPHRASE_CALLBACK *passphraseCb, ossl_unused void *passphraseCbArg) -{ - BIO *bio = NULL; - SCOSSL_MLKEM_KEY_CTX *pKey = NULL; - OSSL_PARAM cbParams[4]; - SCOSSL_STATUS ret = SCOSSL_SUCCESS; - - if (selection == 0) - { - selection = ctx->desc->selection; - } - else if ((selection & ctx->desc->selection) == 0) - { - ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); - } - - if ((bio = p_scossl_bio_new_from_core_bio(ctx->provctx, in)) == NULL) - { - goto callback; - } - - if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) - { - pKey = p_scossl_d2i_mlkem_PKCS8(ctx->desc, bio); - if (!BIO_reset(bio)) - { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - goto callback; - } - } - - if (pKey == NULL && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) - { - pKey = p_scossl_d2i_mlkem_PUBKEY(ctx->desc, bio); - } - -callback: - - if (pKey != NULL) - { - int objectType = OSSL_OBJECT_PKEY; - - cbParams[0] = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objectType); - cbParams[1] = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE, (char *)ctx->desc->dataType, 0); - cbParams[2] = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE, &pKey, sizeof(pKey)); - cbParams[3] = OSSL_PARAM_construct_end(); - - ret = dataCb(cbParams, dataCbArg); - } - - BIO_free(bio); - ctx->keymgmt_free(pKey); - - return ret; -} - -static SCOSSL_STATUS p_scossl_der_to_key_export_object(_In_ SCOSSL_DER_TO_KEY_CTX *ctx, - _In_reads_bytes_(cbObjRef) const void *pbObjRef, _In_ size_t cbObjRef, - _In_ OSSL_CALLBACK *exportCb, _In_ void *exportCbArg) -{ - SCOSSL_MLKEM_KEY_CTX *keyCtx = *(SCOSSL_MLKEM_KEY_CTX **)pbObjRef; - - if (cbObjRef != sizeof(SCOSSL_MLKEM_KEY_CTX *) || keyCtx == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); - return SCOSSL_FAILURE; - } - - return ctx->keymgmt_export(keyCtx, ctx->desc->selection, exportCb, exportCbArg); -} - -#define SCOSSL_MAKE_MLKEM_DECODER(paramSet, decoderType, selectionType) \ - static SCOSSL_KEYTYPE_DESC p_scossl_mlkem##paramSet##_##decoderType##_desc = { \ - "MLKEM", \ - p_scossl_mlkem_keymgmt_functions, \ - selectionType, \ - SYMCRYPT_MLKEM_PARAMS_MLKEM##paramSet}; \ - \ - static SCOSSL_DER_TO_KEY_CTX * \ - p_scossl_der_to_mlkem##paramSet##_##decoderType##_newctx(_In_ SCOSSL_PROVCTX *provctx) \ - { \ - return p_scossl_der_to_key_newctx( \ - provctx, \ - &p_scossl_mlkem##paramSet##_##decoderType##_desc); \ - } \ - \ - static BOOL \ - p_scossl_der_to_mlkem##paramSet##_##decoderType##_does_selection( \ - ossl_unused void *provctx, \ - int selection) \ - { \ - return p_scossl_der_to_key_does_selection( \ - &p_scossl_mlkem##paramSet##_##decoderType##_desc, \ - selection); \ - } \ - \ - const OSSL_DISPATCH p_scossl_der_to_mlkem##paramSet##_##decoderType##_functions[] = { \ - {OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))p_scossl_der_to_mlkem##paramSet##_##decoderType##_newctx}, \ - {OSSL_FUNC_DECODER_FREECTX, (void (*)(void))p_scossl_der_to_key_freectx}, \ - {OSSL_FUNC_DECODER_SET_CTX_PARAMS, (void (*)(void))p_scossl_der_to_key_set_ctx_params}, \ - {OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_der_to_key_settable_ctx_params}, \ - {OSSL_FUNC_DECODER_DOES_SELECTION, (void (*)(void)) \ - p_scossl_der_to_mlkem##paramSet##_##decoderType##_does_selection}, \ - {OSSL_FUNC_DECODER_DECODE, (void (*)(void))p_scossl_der_to_key_decode}, \ - {OSSL_FUNC_DECODER_EXPORT_OBJECT, (void (*)(void))p_scossl_der_to_key_export_object}, \ - {0, NULL}}; - - -extern const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[]; - -SCOSSL_MAKE_MLKEM_DECODER(512, PrivateKeyInfo, OSSL_KEYMGMT_SELECT_PRIVATE_KEY); -SCOSSL_MAKE_MLKEM_DECODER(512, SubjectPublicKeyInfo, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); -SCOSSL_MAKE_MLKEM_DECODER(768, PrivateKeyInfo, OSSL_KEYMGMT_SELECT_PRIVATE_KEY); -SCOSSL_MAKE_MLKEM_DECODER(768, SubjectPublicKeyInfo, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); -SCOSSL_MAKE_MLKEM_DECODER(1024, PrivateKeyInfo, OSSL_KEYMGMT_SELECT_PRIVATE_KEY); -SCOSSL_MAKE_MLKEM_DECODER(1024, SubjectPublicKeyInfo, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_common.c b/SymCryptProvider/src/encoder/p_scossl_encode_common.c new file mode 100644 index 00000000..58762151 --- /dev/null +++ b/SymCryptProvider/src/encoder/p_scossl_encode_common.c @@ -0,0 +1,149 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "p_scossl_bio.h" +#include "encoder/p_scossl_encode_common.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static const OSSL_PARAM p_scossl_encode_settable_param_types[] = { + OSSL_PARAM_utf8_string(OSSL_ENCODER_PARAM_CIPHER, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_ENCODER_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_END}; + +_Use_decl_annotations_ +SCOSSL_ENCODE_CTX *p_scossl_encode_newctx(SCOSSL_PROVCTX *provctx, + int selection, + SCOSSL_ENCODE_OUT_FORMAT outFormat, + PSCOSSL_ENCODE_INTERNAL_FN encodeInternal) +{ + SCOSSL_ENCODE_CTX *ctx = OPENSSL_zalloc(sizeof(SCOSSL_ENCODE_CTX)); + + if (ctx != NULL) + { + ctx->provctx = provctx; + ctx->selection = selection; + ctx->outFormat = outFormat; + ctx->encodeInternal = encodeInternal; + } + + return ctx; +} + +_Use_decl_annotations_ +void p_scossl_encode_freectx(SCOSSL_ENCODE_CTX *ctx) +{ + if (ctx == NULL) + return; + + OPENSSL_free(ctx); +} + +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_encode_set_ctx_params(SCOSSL_ENCODE_CTX *ctx, const OSSL_PARAM params[]) +{ + OSSL_LIB_CTX *libctx = ctx->provctx != NULL ? ctx->provctx->libctx : NULL; + const char *cipherName = NULL; + const char *propQ = NULL; + const OSSL_PARAM *paramCipher = OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_CIPHER); + const OSSL_PARAM *paramProperties = OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_PROPERTIES); + + if (paramCipher != NULL) + { + if (!OSSL_PARAM_get_utf8_string_ptr(paramCipher, &cipherName) || + (paramProperties != NULL && !OSSL_PARAM_get_utf8_string_ptr(paramProperties, &propQ))) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return SCOSSL_FAILURE; + } + + EVP_CIPHER_free(ctx->cipher); + + if (cipherName != NULL) + { + if ((ctx->cipher = EVP_CIPHER_fetch(libctx, cipherName, propQ)) == NULL) + { + ctx->cipherIntent = FALSE; + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return SCOSSL_FAILURE; + } + ctx->cipherIntent = TRUE; + + } + else + { + ctx->cipher = NULL; + } + + ctx->cipherIntent = ctx->cipher != NULL; + } + + return SCOSSL_SUCCESS; +} + +const OSSL_PARAM *p_scossl_encode_settable_ctx_params(ossl_unused void *provctx) +{ + return p_scossl_encode_settable_param_types; +} + +BOOL p_scossl_encode_does_selection(int supportedSelection, int selection) +{ + if (selection == 0) + { + return TRUE; + } + + // Supporting private key implies supporting public key. + // Both imply supporting key parameters + + return ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && (supportedSelection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) || + ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0 && (supportedSelection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) || + ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0 && (supportedSelection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0); +} + +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_encode(SCOSSL_ENCODE_CTX *ctx, OSSL_CORE_BIO *out, + const SCOSSL_MLKEM_KEY_CTX *keyCtx, + const OSSL_PARAM keyAbstract[], + int selection, + OSSL_PASSPHRASE_CALLBACK *passphraseCb, void *passphraseCbArgs) +{ + BIO *bio = NULL; + SCOSSL_STATUS ret; + + if (keyCtx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (ctx->encodeInternal == NULL || + keyAbstract != NULL || + (selection & ctx->selection) == 0) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); + return SCOSSL_FAILURE; + } + + if ((bio = p_scossl_bio_new_from_core_bio(ctx->provctx, out)) != NULL) + { + ret = ctx->encodeInternal( + ctx, keyCtx, + passphraseCb, passphraseCbArgs, + bio, + ctx->outFormat == SCOSSL_ENCODE_PEM); + } + + BIO_free(bio); + + return ret; +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_common.h b/SymCryptProvider/src/encoder/p_scossl_encode_common.h new file mode 100644 index 00000000..05f5bf0e --- /dev/null +++ b/SymCryptProvider/src/encoder/p_scossl_encode_common.h @@ -0,0 +1,61 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "p_scossl_base.h" +#include "kem/p_scossl_mlkem.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define select_PrivateKeyInfo OSSL_KEYMGMT_SELECT_PRIVATE_KEY +#define select_EncryptedPrivateKeyInfo OSSL_KEYMGMT_SELECT_PRIVATE_KEY +#define select_SubjectPublicKeyInfo OSSL_KEYMGMT_SELECT_PUBLIC_KEY + +typedef enum { + SCOSSL_ENCODE_PEM = 1, + SCOSSL_ENCODE_DER, + SCOSSL_ENCODE_TEXT +} SCOSSL_ENCODE_OUT_FORMAT; + +typedef SCOSSL_STATUS (*PSCOSSL_ENCODE_INTERNAL_FN) (_In_ PVOID ctx, + _In_ PCVOID keyCtx, + _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs, + _Inout_ BIO *out, BOOL encodeToPem); + +typedef struct +{ + SCOSSL_PROVCTX *provctx; + + int selection; + + BOOL cipherIntent; + EVP_CIPHER *cipher; + + SCOSSL_ENCODE_OUT_FORMAT outFormat; + PSCOSSL_ENCODE_INTERNAL_FN encodeInternal; +} SCOSSL_ENCODE_CTX; + +SCOSSL_ENCODE_CTX *p_scossl_encode_newctx(_In_ SCOSSL_PROVCTX *provctx, + int selection, + SCOSSL_ENCODE_OUT_FORMAT outFormat, + _In_ PSCOSSL_ENCODE_INTERNAL_FN encodeInternal); +void p_scossl_encode_freectx(_Inout_ SCOSSL_ENCODE_CTX *ctx); + +SCOSSL_STATUS p_scossl_encode_set_ctx_params(_In_ SCOSSL_ENCODE_CTX *ctx, _In_ const OSSL_PARAM params[]); +const OSSL_PARAM *p_scossl_encode_settable_ctx_params(ossl_unused void *provctx); + +BOOL p_scossl_encode_does_selection(int supportedSelection, int selection); + +SCOSSL_STATUS p_scossl_encode(_In_ SCOSSL_ENCODE_CTX *ctx, _Out_ OSSL_CORE_BIO *coreOut, + _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, + _In_ const OSSL_PARAM keyAbstract[], + int selection, + _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs); + + + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c new file mode 100644 index 00000000..993454b7 --- /dev/null +++ b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c @@ -0,0 +1,377 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "p_scossl_names.h" +#include "encoder/p_scossl_encode_common.h" +#include "keymgmt/p_scossl_mlkem_keymgmt.h" + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[]; + +static ASN1_OBJECT *p_scossl_encode_get_mlkem_oid(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx) +{ + int nid = NID_undef; + + switch (keyCtx->params) + { + case SYMCRYPT_MLKEM_PARAMS_MLKEM512: + nid = OBJ_sn2nid(SCOSSL_SN_MLKEM512); + break; + case SYMCRYPT_MLKEM_PARAMS_MLKEM768: + nid = OBJ_sn2nid(SCOSSL_SN_MLKEM768); + break; + case SYMCRYPT_MLKEM_PARAMS_MLKEM1024: + nid = OBJ_sn2nid(SCOSSL_SN_MLKEM1024); + break; + default: + break; + } + + if (nid != NID_undef) + { + return OBJ_nid2obj(nid); + } + + return NULL; +} + +static PKCS8_PRIV_KEY_INFO *p_scossl_mlkem_key_to_p8info(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx) +{ + PBYTE pbKey = NULL; + SIZE_T cbKey; + unsigned char *pbDer = NULL; + int cbDer; + ASN1_OCTET_STRING *p8Data = NULL; + PKCS8_PRIV_KEY_INFO *p8Info = NULL; + ASN1_OBJECT *p8Obj = NULL; + SCOSSL_STATUS status = SCOSSL_FAILURE; + + if (keyCtx->key == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + goto cleanup; + } + + if ((p8Data = ASN1_OCTET_STRING_new()) == NULL || + (p8Info = PKCS8_PRIV_KEY_INFO_new()) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + if (p_scossl_mlkem_keymgmt_get_key_bytes(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED, &pbKey, &cbKey) != SCOSSL_SUCCESS) + { + goto cleanup; + } + + if (!ASN1_OCTET_STRING_set(p8Data, pbKey, cbKey) || + (cbDer = i2d_ASN1_OCTET_STRING(p8Data, &pbDer)) == 0) + { + ERR_raise(ERR_LIB_PROV, ASN1_R_ENCODE_ERROR); + goto cleanup; + } + + if ((p8Obj = p_scossl_encode_get_mlkem_oid(keyCtx)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + if (!PKCS8_pkey_set0(p8Info, p8Obj, 0, V_ASN1_UNDEF, NULL, pbDer, cbKey)) // TODO params? + { + ERR_raise(ERR_LIB_PROV, ASN1_R_ENCODE_ERROR); + goto cleanup; + } + + status = SCOSSL_SUCCESS; + +cleanup: + if (status != SCOSSL_SUCCESS) + { + PKCS8_PRIV_KEY_INFO_free(p8Info); + p8Info = NULL; + } + + ASN1_OCTET_STRING_free(p8Data); + ASN1_OBJECT_free(p8Obj); + OPENSSL_secure_clear_free(pbKey, cbKey); + OPENSSL_free(pbDer); + + return p8Info; +} + +static X509_PUBKEY *p_scossl_mlkem_key_to_pubkey(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx) +{ + PBYTE pbKey = NULL; + SIZE_T cbKey; + unsigned char *pbDer = NULL; + int cbDer; + ASN1_BIT_STRING *subjectPublicKey = NULL; + X509_PUBKEY *pubKey = NULL; + ASN1_OBJECT *p8Obj = NULL; + SCOSSL_STATUS status = SCOSSL_FAILURE; + + if (keyCtx->key == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + goto cleanup; + } + + if ((subjectPublicKey = ASN1_BIT_STRING_new()) == NULL || + (pubKey = X509_PUBKEY_new()) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + if (p_scossl_mlkem_keymgmt_get_key_bytes(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, &pbKey, &cbKey) != SCOSSL_SUCCESS) + { + goto cleanup; + } + + if (!ASN1_BIT_STRING_set(subjectPublicKey, pbKey, cbKey) || + (cbDer = i2d_ASN1_BIT_STRING(subjectPublicKey, &pbDer)) == 0) + { + ERR_raise(ERR_LIB_PROV, ASN1_R_ENCODE_ERROR); + goto cleanup; + } + + if ((p8Obj = p_scossl_encode_get_mlkem_oid(keyCtx)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + if (!X509_PUBKEY_set0_param(pubKey, p8Obj, V_ASN1_NULL, NULL, pbDer, cbDer)) // TODO params? + { + ERR_raise(ERR_LIB_PROV, ASN1_R_ENCODE_ERROR); + goto cleanup; + } + + status = SCOSSL_SUCCESS; + +cleanup: + if (status != SCOSSL_SUCCESS) + { + X509_PUBKEY_free(pubKey); + pubKey = NULL; + } + + ASN1_BIT_STRING_free(subjectPublicKey); + ASN1_OBJECT_free(p8Obj); + OPENSSL_secure_free(pbKey); + OPENSSL_free(pbDer); + + return pubKey; +} + + +static SCOSSL_STATUS p_scossl_mlkem_to_EncryptedPrivateKeyInfo(_In_ SCOSSL_ENCODE_CTX *ctx, + _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, + _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs, + _Inout_ BIO *out, BOOL encodeToPem) +{ + int encodeSuccess; + PKCS8_PRIV_KEY_INFO *p8Info = NULL; + X509_SIG *p8 = NULL; + char pbPass[PEM_BUFSIZE]; + SIZE_T cbPass = 0; + SCOSSL_STATUS ret = SCOSSL_FAILURE; + + if (ctx->cipher == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CIPHER); + goto cleanup; + } + + if ((p8Info = p_scossl_mlkem_key_to_p8info(keyCtx)) == NULL) + { + goto cleanup; + } + + if (!passphraseCb(pbPass, sizeof(pbPass), &cbPass, NULL, passphraseCbArgs)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PASSPHRASE); + goto cleanup; + } + + if ((p8 = PKCS8_encrypt_ex(-1, ctx->cipher, pbPass, cbPass, NULL, 0, 0, p8Info, ctx->provctx->libctx, NULL)) == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); + goto cleanup; + } + + if (encodeToPem) + { + encodeSuccess = PEM_write_bio_PKCS8(out, p8); + } + else + { + encodeSuccess = i2d_PKCS8_bio(out, p8); + } + + if (!encodeSuccess) + { + ERR_raise(ERR_LIB_PROV, ASN1_R_ENCODE_ERROR); + goto cleanup; + } + + ret = SCOSSL_SUCCESS; + +cleanup: + OPENSSL_cleanse(pbPass, sizeof(pbPass)); + PKCS8_PRIV_KEY_INFO_free(p8Info); + X509_SIG_free(p8); + + return ret; +} + +static SCOSSL_STATUS p_scossl_mlkem_to_PrivateKeyInfo(_In_ SCOSSL_ENCODE_CTX *ctx, + _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, + _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs, + _Inout_ BIO *out, BOOL encodeToPem) +{ + int encodeSuccess; + PKCS8_PRIV_KEY_INFO *p8Info = NULL; + SCOSSL_STATUS ret = SCOSSL_FAILURE; + + if (ctx->cipherIntent) + { + return p_scossl_mlkem_to_EncryptedPrivateKeyInfo(ctx, keyCtx, passphraseCb, passphraseCbArgs, out, encodeToPem); + } + + if ((p8Info = p_scossl_mlkem_key_to_p8info(keyCtx)) == NULL) + { + goto cleanup; + } + + if (encodeToPem) + { + encodeSuccess = PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8Info); + } + else + { + encodeSuccess = i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8Info); + } + + if (!encodeSuccess) + { + ERR_raise(ERR_LIB_PROV, ASN1_R_ENCODE_ERROR); + goto cleanup; + } + + ret = SCOSSL_SUCCESS; + +cleanup: + PKCS8_PRIV_KEY_INFO_free(p8Info); + + return ret; +} + +static SCOSSL_STATUS p_scossl_mlkem_to_SubjectPublicKeyInfo(ossl_unused SCOSSL_ENCODE_CTX *ctx, + _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, + ossl_unused OSSL_PASSPHRASE_CALLBACK *passphraseCb, ossl_unused void *passphraseCbArgs, + _Inout_ BIO *out, BOOL encodeToPem) +{ + int encodeSuccess; + X509_PUBKEY *pubKey = NULL; + SCOSSL_STATUS ret = SCOSSL_FAILURE; + + if ((pubKey = p_scossl_mlkem_key_to_pubkey(keyCtx)) == NULL) + { + goto cleanup; + } + + if (encodeToPem) + { + encodeSuccess = PEM_write_bio_X509_PUBKEY(out, pubKey); + } + else + { + encodeSuccess = i2d_X509_PUBKEY_bio(out, pubKey); + } + + if (!encodeSuccess) + { + ERR_raise(ERR_LIB_PROV, ASN1_R_ENCODE_ERROR); + goto cleanup; + } + + ret = SCOSSL_SUCCESS; + +cleanup: + X509_PUBKEY_free(pubKey); + + return ret; +} + +static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_encoder_import_object(_In_ SCOSSL_ENCODE_CTX *ctx, + int selection, _In_ const OSSL_PARAM params[]) +{ + SCOSSL_MLKEM_KEY_CTX *keyCtx = p_scossl_mlkem_keymgmt_new_ctx(ctx->provctx); + + if (keyCtx != NULL) + { + p_scossl_mlkem_keymgmt_import(keyCtx, selection, params); + } + + return keyCtx; +} + +#define MAKE_MLKEM_ENCODER(decoderType) \ + static SCOSSL_ENCODE_CTX *p_scossl_mlkem_to_##decoderType##_der_newctx(_In_ SCOSSL_PROVCTX *provctx) \ + { \ + return p_scossl_encode_newctx(provctx, select_##decoderType, \ + SCOSSL_ENCODE_DER, \ + (PSCOSSL_ENCODE_INTERNAL_FN)p_scossl_mlkem_to_##decoderType); \ + } \ + \ + static SCOSSL_ENCODE_CTX *p_scossl_mlkem_to_##decoderType##_pem_newctx(_In_ SCOSSL_PROVCTX *provctx) \ + { \ + return p_scossl_encode_newctx(provctx, select_##decoderType, \ + SCOSSL_ENCODE_PEM, \ + (PSCOSSL_ENCODE_INTERNAL_FN)p_scossl_mlkem_to_##decoderType); \ + } \ + \ + static BOOL p_scossl_der_to_mlkem_##decoderType##_does_selection(ossl_unused void *provctx, int selection) \ + { \ + return p_scossl_encode_does_selection(select_##decoderType, selection); \ + } \ + \ + const OSSL_DISPATCH p_scossl_mlkem_to_##decoderType##_der_functions[] = { \ + {OSSL_FUNC_ENCODER_NEWCTX, (void (*)(void))p_scossl_mlkem_to_##decoderType##_der_newctx}, \ + {OSSL_FUNC_ENCODER_FREECTX, (void (*)(void))p_scossl_encode_freectx}, \ + {OSSL_FUNC_ENCODER_SET_CTX_PARAMS, (void (*)(void))p_scossl_encode_set_ctx_params}, \ + {OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_encode_settable_ctx_params}, \ + {OSSL_FUNC_ENCODER_DOES_SELECTION, (void (*)(void))p_scossl_der_to_mlkem_##decoderType##_does_selection}, \ + {OSSL_FUNC_ENCODER_ENCODE, (void (*)(void))p_scossl_encode}, \ + {OSSL_FUNC_ENCODER_IMPORT_OBJECT, (void (*)(void))p_scossl_mlkem_encoder_import_object}, \ + {OSSL_FUNC_ENCODER_FREE_OBJECT, (void (*)(void))p_scossl_mlkem_keymgmt_free_key_ctx}, \ + {0, NULL}}; \ + \ + const OSSL_DISPATCH p_scossl_mlkem_to_##decoderType##_pem_functions[] = { \ + {OSSL_FUNC_ENCODER_NEWCTX, (void (*)(void))p_scossl_mlkem_to_##decoderType##_pem_newctx}, \ + {OSSL_FUNC_ENCODER_FREECTX, (void (*)(void))p_scossl_encode_freectx}, \ + {OSSL_FUNC_ENCODER_SET_CTX_PARAMS, (void (*)(void))p_scossl_encode_set_ctx_params}, \ + {OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_encode_settable_ctx_params}, \ + {OSSL_FUNC_ENCODER_DOES_SELECTION, (void (*)(void))p_scossl_der_to_mlkem_##decoderType##_does_selection}, \ + {OSSL_FUNC_ENCODER_ENCODE, (void (*)(void))p_scossl_encode}, \ + {OSSL_FUNC_ENCODER_IMPORT_OBJECT, (void (*)(void))p_scossl_mlkem_encoder_import_object}, \ + {OSSL_FUNC_ENCODER_FREE_OBJECT, (void (*)(void))p_scossl_mlkem_keymgmt_free_key_ctx}, \ + {0, NULL}}; + +MAKE_MLKEM_ENCODER(PrivateKeyInfo) +MAKE_MLKEM_ENCODER(EncryptedPrivateKeyInfo) +MAKE_MLKEM_ENCODER(SubjectPublicKeyInfo) + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index f97a6ae7..32e497a2 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -3,6 +3,7 @@ // #include "kem/p_scossl_mlkem.h" +#include "keymgmt/p_scossl_mlkem_keymgmt.h" #include #include @@ -60,20 +61,16 @@ static const OSSL_PARAM *p_scossl_mlkem_impexp_types[] = { p_scossl_mlkem_pkey_types, p_scossl_mlkem_all_types}; -static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_bytes(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, - SYMCRYPT_MLKEMKEY_FORMAT format, - _Out_writes_bytes_(*cbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); - static SYMCRYPT_MLKEM_PARAMS p_scossl_mlkem_keymgmt_params_from_name(_In_ const char *name); static const char * p_scossl_mlkem_keymgmt_params_to_name(_In_ const SYMCRYPT_MLKEM_PARAMS name); static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx); -static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(ossl_unused void *provCtx) +SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(ossl_unused void *provCtx) { return OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_KEY_CTX));; } -static void p_scossl_mlkem_keymgmt_free_key_ctx(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx) +void p_scossl_mlkem_keymgmt_free_key_ctx(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx) { if (keyCtx == NULL) return; @@ -645,7 +642,7 @@ static const OSSL_PARAM *p_scossl_mlkem_keymgmt_impexp_types(int selection) return p_scossl_mlkem_impexp_types[idx]; } -static SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]) +SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]) { const OSSL_PARAM *p; PCBYTE pbKey; @@ -736,8 +733,8 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX return SCOSSL_SUCCESS; } -static SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, - _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg) +SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, + _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg) { const char *mlkemParamsName; PBYTE pbKey = NULL; @@ -863,9 +860,9 @@ const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[] = { // _Use_decl_annotations_ -static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_bytes(const SCOSSL_MLKEM_KEY_CTX *keyCtx, - SYMCRYPT_MLKEMKEY_FORMAT format, - PBYTE *ppbKey, SIZE_T *pcbKey) +SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_bytes(const SCOSSL_MLKEM_KEY_CTX *keyCtx, + SYMCRYPT_MLKEMKEY_FORMAT format, + PBYTE *ppbKey, SIZE_T *pcbKey) { PBYTE pbKey = NULL; SIZE_T cbKey = 0; @@ -973,7 +970,6 @@ static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_ return 0; } - #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h new file mode 100644 index 00000000..ff79cdaf --- /dev/null +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h @@ -0,0 +1,24 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "scossl_helpers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(ossl_unused void *provCtx); +void p_scossl_mlkem_keymgmt_free_key_ctx(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx); + +SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]); +SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, + _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg); + +SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_bytes(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, + SYMCRYPT_MLKEMKEY_FORMAT format, + _Out_writes_bytes_(*cbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index e827d501..d93ed8bf 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -8,8 +8,9 @@ #include "scossl_dh.h" #include "scossl_ecc.h" -#include "p_scossl_keysinuse.h" #include "p_scossl_bio.h" +#include "p_scossl_keysinuse.h" +#include "p_scossl_names.h" #ifdef __cplusplus extern "C" { @@ -49,6 +50,15 @@ extern "C" { p_scossl_der_to_##name##_##decoderType##_functions, \ NULL} +#define ALG_ENCODER(algNames, name, encoderType, format) { \ + algNames, \ + "provider="P_SCOSSL_NAME \ + ",fips=yes" \ + ",output="#format \ + ",structure="#encoderType, \ + p_scossl_##name##_to_##encoderType##_##format##_functions, \ + NULL} + #define ALG_TABLE_END {NULL, NULL, NULL, NULL} typedef struct { @@ -197,26 +207,26 @@ extern const OSSL_DISPATCH p_scossl_aes128xts_functions[]; extern const OSSL_DISPATCH p_scossl_aes256xts_functions[]; static const OSSL_ALGORITHM p_scossl_cipher[] = { - ALG("AES-128-CBC:AES128:2.16.840.1.101.3.4.1.2", p_scossl_aes128cbc_functions), - ALG("AES-192-CBC:AES192:2.16.840.1.101.3.4.1.22", p_scossl_aes192cbc_functions), - ALG("AES-256-CBC:AES256:2.16.840.1.101.3.4.1.42", p_scossl_aes256cbc_functions), - ALG("AES-128-ECB:2.16.840.1.101.3.4.1.1", p_scossl_aes128ecb_functions), - ALG("AES-192-ECB:2.16.840.1.101.3.4.1.21", p_scossl_aes192ecb_functions), - ALG("AES-256-ECB:2.16.840.1.101.3.4.1.41", p_scossl_aes256ecb_functions), - ALG("AES-128-CFB:2.16.840.1.101.3.4.1.4", p_scossl_aes128cfb_functions), - ALG("AES-192-CFB:2.16.840.1.101.3.4.1.24", p_scossl_aes192cfb_functions), - ALG("AES-256-CFB:2.16.840.1.101.3.4.1.44", p_scossl_aes256cfb_functions), - ALG("AES-128-CFB8", p_scossl_aes128cfb8_functions), - ALG("AES-192-CFB8", p_scossl_aes192cfb8_functions), - ALG("AES-256-CFB8", p_scossl_aes256cfb8_functions), - ALG("AES-128-GCM:id-aes128-GCM:2.16.840.1.101.3.4.1.6", p_scossl_aes128gcm_functions), - ALG("AES-192-GCM:id-aes192-GCM:2.16.840.1.101.3.4.1.26", p_scossl_aes192gcm_functions), - ALG("AES-256-GCM:id-aes256-GCM:2.16.840.1.101.3.4.1.46", p_scossl_aes256gcm_functions), - ALG("AES-128-CCM:id-aes128-CCM:2.16.840.1.101.3.4.1.7", p_scossl_aes128ccm_functions), - ALG("AES-192-CCM:id-aes192-CCM:2.16.840.1.101.3.4.1.27", p_scossl_aes192ccm_functions), - ALG("AES-256-CCM:id-aes256-CCM:2.16.840.1.101.3.4.1.47", p_scossl_aes256ccm_functions), - ALG("AES-128-XTS:1.3.111.2.1619.0.1.1", p_scossl_aes128xts_functions), - ALG("AES-256-XTS:1.3.111.2.1619.0.1.2", p_scossl_aes256xts_functions), + ALG(SCOSSL_ALG_NAME_AES_128_CBC, p_scossl_aes128cbc_functions), + ALG(SCOSSL_ALG_NAME_AES_192_CBC, p_scossl_aes192cbc_functions), + ALG(SCOSSL_ALG_NAME_AES_256_CBC, p_scossl_aes256cbc_functions), + ALG(SCOSSL_ALG_NAME_AES_128_ECB, p_scossl_aes128ecb_functions), + ALG(SCOSSL_ALG_NAME_AES_192_ECB, p_scossl_aes192ecb_functions), + ALG(SCOSSL_ALG_NAME_AES_256_ECB, p_scossl_aes256ecb_functions), + ALG(SCOSSL_ALG_NAME_AES_128_CFB, p_scossl_aes128cfb_functions), + ALG(SCOSSL_ALG_NAME_AES_192_CFB, p_scossl_aes192cfb_functions), + ALG(SCOSSL_ALG_NAME_AES_256_CFB, p_scossl_aes256cfb_functions), + ALG(SCOSSL_ALG_NAME_AES_128_CFB8, p_scossl_aes128cfb8_functions), + ALG(SCOSSL_ALG_NAME_AES_192_CFB8, p_scossl_aes192cfb8_functions), + ALG(SCOSSL_ALG_NAME_AES_256_CFB8, p_scossl_aes256cfb8_functions), + ALG(SCOSSL_ALG_NAME_AES_128_GCM, p_scossl_aes128gcm_functions), + ALG(SCOSSL_ALG_NAME_AES_192_GCM, p_scossl_aes192gcm_functions), + ALG(SCOSSL_ALG_NAME_AES_256_GCM, p_scossl_aes256gcm_functions), + ALG(SCOSSL_ALG_NAME_AES_128_CCM, p_scossl_aes128ccm_functions), + ALG(SCOSSL_ALG_NAME_AES_192_CCM, p_scossl_aes192ccm_functions), + ALG(SCOSSL_ALG_NAME_AES_256_CCM, p_scossl_aes256ccm_functions), + ALG(SCOSSL_ALG_NAME_AES_128_XTS, p_scossl_aes128xts_functions), + ALG(SCOSSL_ALG_NAME_AES_256_XTS, p_scossl_aes256xts_functions), ALG_TABLE_END}; // MAC @@ -226,10 +236,10 @@ extern const OSSL_DISPATCH p_scossl_kmac128_functions[]; extern const OSSL_DISPATCH p_scossl_kmac256_functions[]; static const OSSL_ALGORITHM p_scossl_mac[] = { - ALG("CMAC", p_scossl_cmac_functions), - ALG("HMAC", p_scossl_hmac_functions), - ALG("KMAC-128:KMAC128:2.16.840.1.101.3.4.2.19", p_scossl_kmac128_functions), - ALG("KMAC-256:KMAC256:2.16.840.1.101.3.4.2.20", p_scossl_kmac256_functions), + ALG(SCOSSL_ALG_NAME_CMAC, p_scossl_cmac_functions), + ALG(SCOSSL_ALG_NAME_HMAC, p_scossl_hmac_functions), + ALG(SCOSSL_ALG_NAME_KMAC128, p_scossl_kmac128_functions), + ALG(SCOSSL_ALG_NAME_KMAC256, p_scossl_kmac256_functions), ALG_TABLE_END}; // KDF @@ -242,20 +252,20 @@ extern const OSSL_DISPATCH p_scossl_sskdf_kdf_functions[]; extern const OSSL_DISPATCH p_scossl_tls1prf_kdf_functions[]; static const OSSL_ALGORITHM p_scossl_kdf[] = { - ALG("HKDF", p_scossl_hkdf_kdf_functions), - ALG("KBKDF", p_scossl_kbkdf_kdf_functions), - ALG("SRTPKDF", p_scossl_srtpkdf_kdf_functions), - ALG("SRTCPKDF", p_scossl_srtcpkdf_kdf_functions), - ALG("SSHKDF", p_scossl_sshkdf_kdf_functions), - ALG("SSKDF", p_scossl_sskdf_kdf_functions), - ALG("TLS1-PRF", p_scossl_tls1prf_kdf_functions), + ALG(SCOSSL_ALG_NAME_HKDF, p_scossl_hkdf_kdf_functions), + ALG(SCOSSL_ALG_NAME_KBKKDF, p_scossl_kbkdf_kdf_functions), + ALG(SCOSSL_ALG_NAME_SRTPKDF, p_scossl_srtpkdf_kdf_functions), + ALG(SCOSSL_ALG_NAME_SRTCPKDF, p_scossl_srtcpkdf_kdf_functions), + ALG(SCOSSL_ALG_NAME_SSHKDF, p_scossl_sshkdf_kdf_functions), + ALG(SCOSSL_ALG_NAME_SSKDF, p_scossl_sskdf_kdf_functions), + ALG(SCOSSL_ALG_NAME_TLS1_PRF, p_scossl_tls1prf_kdf_functions), ALG_TABLE_END}; // Rand extern const OSSL_DISPATCH p_scossl_rand_functions[]; static const OSSL_ALGORITHM p_scossl_rand[] = { - ALG("CTR-DRBG", p_scossl_rand_functions), + ALG(SCOSSL_ALG_NAME_CTR_DBG, p_scossl_rand_functions), ALG_TABLE_END}; // Key management @@ -268,14 +278,14 @@ extern const OSSL_DISPATCH p_scossl_x25519_keymgmt_functions[]; extern const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[]; static const OSSL_ALGORITHM p_scossl_keymgmt[] = { - ALG("DH:dhKeyAgreement:1.2.840.113549.1.3.1", p_scossl_dh_keymgmt_functions), - ALG("EC:id-ecPublicKey:1.2.840.10045.2.1", p_scossl_ecc_keymgmt_functions), - ALG("HKDF", p_scossl_kdf_keymgmt_functions), - ALG("RSA:rsaEncryption:1.2.840.113549.1.1.1:", p_scossl_rsa_keymgmt_functions), - ALG("RSA-PSS:RSASSA-PSS:1.2.840.113549.1.1.10", p_scossl_rsapss_keymgmt_functions), - ALG("TLS1-PRF", p_scossl_kdf_keymgmt_functions), - ALG("X25519:1.3.101.110", p_scossl_x25519_keymgmt_functions), - ALG("MLKEM:mlkem512:mlkem768:mlkem1024", p_scossl_mlkem_keymgmt_functions), + ALG(SCOSSL_ALG_NAME_DH, p_scossl_dh_keymgmt_functions), + ALG(SCOSSL_ALG_NAME_EC, p_scossl_ecc_keymgmt_functions), + ALG(SCOSSL_ALG_NAME_HKDF, p_scossl_kdf_keymgmt_functions), + ALG(SCOSSL_ALG_NAME_MLKEM, p_scossl_mlkem_keymgmt_functions), + ALG(SCOSSL_ALG_NAME_RSA, p_scossl_rsa_keymgmt_functions), + ALG(SCOSSL_ALG_NAME_RSA_PSS, p_scossl_rsapss_keymgmt_functions), + ALG(SCOSSL_ALG_NAME_TLS1_PRF, p_scossl_kdf_keymgmt_functions), + ALG(SCOSSL_ALG_NAME_X25519, p_scossl_x25519_keymgmt_functions), ALG_TABLE_END}; // Key exchange @@ -286,11 +296,11 @@ extern const OSSL_DISPATCH p_scossl_tls1prf_keyexch_functions[]; extern const OSSL_DISPATCH p_scossl_x25519_functions[]; static const OSSL_ALGORITHM p_scossl_keyexch[] = { - ALG("DH:dhKeyAgreement:1.2.840.113549.1.3.1", p_scossl_dh_functions), - ALG("ECDH", p_scossl_ecdh_functions), - ALG("HKDF", p_scossl_hkdf_keyexch_functions), - ALG("TLS1-PRF", p_scossl_tls1prf_keyexch_functions), - ALG("X25519:1.3.101.110", p_scossl_ecdh_functions), + ALG(SCOSSL_ALG_NAME_DH, p_scossl_dh_functions), + ALG(SCOSSL_ALG_NAME_ECDH, p_scossl_ecdh_functions), + ALG(SCOSSL_ALG_NAME_HKDF, p_scossl_hkdf_keyexch_functions), + ALG(SCOSSL_ALG_NAME_TLS1_PRF, p_scossl_tls1prf_keyexch_functions), + ALG(SCOSSL_ALG_NAME_X25519, p_scossl_ecdh_functions), ALG_TABLE_END}; // Signature @@ -298,22 +308,22 @@ extern const OSSL_DISPATCH p_scossl_rsa_signature_functions[]; extern const OSSL_DISPATCH p_scossl_ecdsa_signature_functions[]; static const OSSL_ALGORITHM p_scossl_signature[] = { - ALG("RSA:rsaEncryption:1.2.840.113549.1.1.1", p_scossl_rsa_signature_functions), - ALG("ECDSA", p_scossl_ecdsa_signature_functions), + ALG(SCOSSL_ALG_NAME_RSA, p_scossl_rsa_signature_functions), + ALG(SCOSSL_ALG_NAME_ECDSA, p_scossl_ecdsa_signature_functions), ALG_TABLE_END}; // Asymmetric Cipher extern const OSSL_DISPATCH p_scossl_rsa_cipher_functions[]; static const OSSL_ALGORITHM p_scossl_asym_cipher[] = { - ALG("RSA:rsaEncryption:1.2.840.113549.1.1.1", p_scossl_rsa_cipher_functions), + ALG(SCOSSL_ALG_NAME_RSA, p_scossl_rsa_cipher_functions), ALG_TABLE_END}; // Key encapsulation extern const OSSL_DISPATCH p_scossl_mlkem_functions[]; static const OSSL_ALGORITHM p_scossl_kem[] = { - ALG("MLKEM", p_scossl_mlkem_functions), + ALG(SCOSSL_ALG_NAME_MLKEM, p_scossl_mlkem_functions), ALG_TABLE_END}; // Decoders @@ -325,14 +335,43 @@ extern const OSSL_DISPATCH p_scossl_der_to_mlkem1024_PrivateKeyInfo_functions[]; extern const OSSL_DISPATCH p_scossl_der_to_mlkem1024_SubjectPublicKeyInfo_functions[]; static const OSSL_ALGORITHM p_scossl_decoder[] = { - ALG_DECODER("mlkem512:1.3.6.1.4.1.22554.5.6.1", mlkem512, PrivateKeyInfo), - ALG_DECODER("mlkem512:1.3.6.1.4.1.22554.5.6.1", mlkem512, SubjectPublicKeyInfo), - ALG_DECODER("mlkem768", mlkem768, PrivateKeyInfo), - ALG_DECODER("mlkem768", mlkem768, SubjectPublicKeyInfo), - ALG_DECODER("mlkem1024", mlkem1024, PrivateKeyInfo), - ALG_DECODER("mlkem1024", mlkem1024, SubjectPublicKeyInfo), + ALG_DECODER(SCOSSL_ALG_NAME_MLKEM512, mlkem512, PrivateKeyInfo), + ALG_DECODER(SCOSSL_ALG_NAME_MLKEM512, mlkem512, SubjectPublicKeyInfo), + ALG_DECODER(SCOSSL_ALG_NAME_MLKEM768, mlkem768, PrivateKeyInfo), + ALG_DECODER(SCOSSL_ALG_NAME_MLKEM768, mlkem768, SubjectPublicKeyInfo), + ALG_DECODER(SCOSSL_ALG_NAME_MLKEM1024, mlkem1024, PrivateKeyInfo), + ALG_DECODER(SCOSSL_ALG_NAME_MLKEM1024, mlkem1024, SubjectPublicKeyInfo), ALG_TABLE_END}; +// Encoders +extern const OSSL_DISPATCH p_scossl_mlkem_to_PrivateKeyInfo_der_functions[]; +extern const OSSL_DISPATCH p_scossl_mlkem_to_PrivateKeyInfo_pem_functions[]; +extern const OSSL_DISPATCH p_scossl_mlkem_to_EncryptedPrivateKeyInfo_der_functions[]; +extern const OSSL_DISPATCH p_scossl_mlkem_to_EncryptedPrivateKeyInfo_pem_functions[]; +extern const OSSL_DISPATCH p_scossl_mlkem_to_SubjectPublicKeyInfo_der_functions[]; +extern const OSSL_DISPATCH p_scossl_mlkem_to_SubjectPublicKeyInfo_pem_functions[]; + +static const OSSL_ALGORITHM p_scossl_encoder[] = { + ALG_ENCODER(SCOSSL_ALG_NAME_MLKEM, mlkem, PrivateKeyInfo, der), + ALG_ENCODER(SCOSSL_ALG_NAME_MLKEM, mlkem, PrivateKeyInfo, pem), + ALG_ENCODER(SCOSSL_ALG_NAME_MLKEM, mlkem, EncryptedPrivateKeyInfo, der), + ALG_ENCODER(SCOSSL_ALG_NAME_MLKEM, mlkem, EncryptedPrivateKeyInfo, pem), + ALG_ENCODER(SCOSSL_ALG_NAME_MLKEM, mlkem, SubjectPublicKeyInfo, der), + ALG_ENCODER(SCOSSL_ALG_NAME_MLKEM, mlkem, SubjectPublicKeyInfo, pem), + ALG_TABLE_END}; + +static SCOSSL_STATUS p_scossl_register_extended_algorithms() +{ + if (OBJ_create(SCOSSL_OID_MLKEM512, SCOSSL_SN_MLKEM512, SCOSSL_SN_MLKEM512) == NID_undef || + OBJ_create(SCOSSL_OID_MLKEM768, SCOSSL_SN_MLKEM768, SCOSSL_SN_MLKEM768) == NID_undef || + OBJ_create(SCOSSL_OID_MLKEM1024, SCOSSL_SN_MLKEM1024, SCOSSL_SN_MLKEM1024) == NID_undef) + { + return SCOSSL_FAILURE; + } + + return SCOSSL_SUCCESS; +} + static int p_scossl_get_status() { return scossl_prov_initialized; @@ -414,6 +453,8 @@ static const OSSL_ALGORITHM *p_scossl_query_operation(ossl_unused void *provctx, return p_scossl_kem; case OSSL_OP_DECODER: return p_scossl_decoder; + case OSSL_OP_ENCODER: + return p_scossl_encoder; } return NULL; @@ -625,11 +666,13 @@ SCOSSL_STATUS OSSL_provider_init(_In_ const OSSL_CORE_HANDLE *handle, { SYMCRYPT_MODULE_INIT(); if (!scossl_dh_init_static() || - !scossl_ecc_init_static()) + !scossl_ecc_init_static() || + !p_scossl_register_extended_algorithms()) { ERR_raise(ERR_LIB_PROV, ERR_R_INIT_FAIL); return SCOSSL_FAILURE; } + scossl_prov_initialized = 1; } diff --git a/SymCryptProvider/src/p_scossl_names.h b/SymCryptProvider/src/p_scossl_names.h new file mode 100644 index 00000000..9209164a --- /dev/null +++ b/SymCryptProvider/src/p_scossl_names.h @@ -0,0 +1,90 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +// +// Extended algorithms not found in default OpenSSL implementation +// + +#define SCOSSL_SN_MLKEM512 "mlkem512" +#define SCOSSL_OID_MLKEM512 "2.16.840.1.101.3.4.4.1" + +#define SCOSSL_SN_MLKEM768 "mlkem768" +#define SCOSSL_OID_MLKEM768 "2.16.840.1.101.3.4.4.2" + +#define SCOSSL_SN_MLKEM1024 "mlkem1024" +#define SCOSSL_OID_MLKEM1024 "2.16.840.1.101.3.4.4.3" + +// +// Provider algorithm names +// + +// Ciphers +#define SCOSSL_ALG_NAME_AES_128_CBC SN_aes_128_cbc":AES128:2.16.840.1.101.3.4.1.2" +#define SCOSSL_ALG_NAME_AES_192_CBC SN_aes_192_cbc":AES192:2.16.840.1.101.3.4.1.22" +#define SCOSSL_ALG_NAME_AES_256_CBC SN_aes_256_cbc":AES256:2.16.840.1.101.3.4.1.42" +#define SCOSSL_ALG_NAME_AES_128_ECB SN_aes_128_ecb":2.16.840.1.101.3.4.1.1" +#define SCOSSL_ALG_NAME_AES_192_ECB SN_aes_192_ecb":2.16.840.1.101.3.4.1.21" +#define SCOSSL_ALG_NAME_AES_256_ECB SN_aes_256_ecb":2.16.840.1.101.3.4.1.41" +#define SCOSSL_ALG_NAME_AES_128_CFB SN_aes_128_cfb128":2.16.840.1.101.3.4.1.4" +#define SCOSSL_ALG_NAME_AES_192_CFB SN_aes_192_cfb128":2.16.840.1.101.3.4.1.24" +#define SCOSSL_ALG_NAME_AES_256_CFB SN_aes_256_cfb128":2.16.840.1.101.3.4.1.44" +#define SCOSSL_ALG_NAME_AES_128_CFB8 SN_aes_128_cfb8 +#define SCOSSL_ALG_NAME_AES_192_CFB8 SN_aes_192_cfb8 +#define SCOSSL_ALG_NAME_AES_256_CFB8 SN_aes_256_cfb8 +#define SCOSSL_ALG_NAME_AES_128_GCM SN_aes_128_gcm":AES-128-GCM:2.16.840.1.101.3.4.1.6" +#define SCOSSL_ALG_NAME_AES_192_GCM SN_aes_192_gcm":AES-192-GCM:2.16.840.1.101.3.4.1.26" +#define SCOSSL_ALG_NAME_AES_256_GCM SN_aes_256_gcm":AES-256-GCM:2.16.840.1.101.3.4.1.46" +#define SCOSSL_ALG_NAME_AES_128_CCM SN_aes_128_ccm":AES-128-CCM:2.16.840.1.101.3.4.1.7" +#define SCOSSL_ALG_NAME_AES_192_CCM SN_aes_192_ccm":AES-192-CCM:2.16.840.1.101.3.4.1.27" +#define SCOSSL_ALG_NAME_AES_256_CCM SN_aes_256_ccm":AES-256-CCM:2.16.840.1.101.3.4.1.47" +#define SCOSSL_ALG_NAME_AES_128_XTS SN_aes_128_xts":1.3.111.2.1619.0.1.1" +#define SCOSSL_ALG_NAME_AES_256_XTS SN_aes_256_xts":1.3.111.2.1619.0.1.2" + +// MAC +#define SCOSSL_ALG_NAME_CMAC SN_cmac +#define SCOSSL_ALG_NAME_HMAC SN_hmac +#define SCOSSL_ALG_NAME_KMAC128 SN_kmac128":KMAC-128:KMAC128:2.16.840.1.101.3.4.2.19" +#define SCOSSL_ALG_NAME_KMAC256 SN_kmac256":KMAC-256:KMAC256:2.16.840.1.101.3.4.2.20" + +// KDF +#define SCOSSL_ALG_NAME_HKDF SN_hkdf +#define SCOSSL_ALG_NAME_KBKKDF "KBKDF" +#define SCOSSL_ALG_NAME_SRTPKDF "SRTPKDF" +#define SCOSSL_ALG_NAME_SRTCPKDF "SRTCPKDF" +#define SCOSSL_ALG_NAME_SSHKDF SN_sshkdf +#define SCOSSL_ALG_NAME_SSKDF SN_sskdf +#define SCOSSL_ALG_NAME_TLS1_PRF SN_tls1_prf + +// Rand +#define SCOSSL_ALG_NAME_CTR_DBG "CTR-DRBG" + +// Key management +#define SCOSSL_ALG_NAME_EC SN_X9_62_id_ecPublicKey":EC:1.2.840.10045.2.1" +#define SCOSSL_ALG_NAME_RSA_PSS SN_rsassaPss":RSA-PSS:1.2.840.113549.1.1.10" + +// Key exchange +#define SCOSSL_ALG_NAME_DH LN_dhKeyAgreement":DH:1.2.840.113549.1.3.1" +#define SCOSSL_ALG_NAME_ECDH "ECDH" +#define SCOSSL_ALG_NAME_X25519 SN_X25519":1.3.101.110" + +// Signature +#define SCOSSL_ALG_NAME_RSA SN_rsa":"LN_rsaEncryption":1.2.840.113549.1.1.1" +#define SCOSSL_ALG_NAME_ECDSA "ECDSA" + +// Key encapsulation +#define SCOSSL_ALG_NAME_MLKEM512 SCOSSL_SN_MLKEM512":"SCOSSL_OID_MLKEM512 +#define SCOSSL_ALG_NAME_MLKEM768 SCOSSL_SN_MLKEM768":"SCOSSL_OID_MLKEM768 +#define SCOSSL_ALG_NAME_MLKEM1024 SCOSSL_SN_MLKEM1024":"SCOSSL_OID_MLKEM1024 +#define SCOSSL_ALG_NAME_MLKEM "MLKEM:"SCOSSL_ALG_NAME_MLKEM512":"SCOSSL_ALG_NAME_MLKEM768":"SCOSSL_ALG_NAME_MLKEM1024 + + +#ifdef __cplusplus +} +#endif \ No newline at end of file From 8bd3af6edc05b1a28a03419b0af1ec87e6a846fb Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Fri, 18 Oct 2024 21:24:03 +0000 Subject: [PATCH 07/21] Consolidate ML-KEM decoder --- .../src/decoder/p_scossl_decode_common.c | 2 +- .../src/decoder/p_scossl_decode_common.h | 7 +- .../src/decoder/p_scossl_decode_mlkem.c | 129 +++++++++++------- .../src/encoder/p_scossl_encode_mlkem.c | 4 +- SymCryptProvider/src/p_scossl_base.c | 17 +-- SymCryptProvider/src/p_scossl_names.h | 7 +- 6 files changed, 95 insertions(+), 71 deletions(-) diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_common.c b/SymCryptProvider/src/decoder/p_scossl_decode_common.c index dd84a865..c53b555e 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_common.c +++ b/SymCryptProvider/src/decoder/p_scossl_decode_common.c @@ -96,7 +96,7 @@ SCOSSL_STATUS p_scossl_decode(SCOSSL_DECODE_CTX *ctx, OSSL_CORE_BIO *in, int sel if ((bio = p_scossl_bio_new_from_core_bio(ctx->provctx, in)) != NULL) { - keyCtx = ctx->desc->decodeInternal(ctx->desc, bio); + keyCtx = ctx->desc->decodeInternal(bio); } if (keyCtx != NULL) diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_common.h b/SymCryptProvider/src/decoder/p_scossl_decode_common.h index 20b1f3ce..5256f796 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_common.h +++ b/SymCryptProvider/src/decoder/p_scossl_decode_common.h @@ -12,7 +12,7 @@ extern "C" { #define select_PrivateKeyInfo OSSL_KEYMGMT_SELECT_PRIVATE_KEY #define select_SubjectPublicKeyInfo OSSL_KEYMGMT_SELECT_PUBLIC_KEY -typedef PVOID (*PSCOSSL_DECODE_INTERNAL_FN) (_In_ PCVOID desc, _In_ BIO *bio); +typedef PVOID (*PSCOSSL_DECODE_INTERNAL_FN) (_In_ BIO *bio); typedef struct { @@ -21,9 +21,6 @@ typedef struct PSCOSSL_DECODE_INTERNAL_FN decodeInternal; OSSL_FUNC_keymgmt_free_fn *freeKeyCtx; - - // Contains type-specific key parameters (e.g. ML-KEM params, EC curve, etc.) - UINT64 keyParams; } SCOSSL_DECODE_KEYTYPE_DESC; typedef struct @@ -35,7 +32,7 @@ typedef struct typedef struct { - X509_ALGOR algorithm; + X509_ALGOR *algorithm; ASN1_BIT_STRING *subjectPublicKey; } SUBJECT_PUBKEY_INFO; diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c index 6d7c8944..42084295 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c +++ b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c @@ -2,6 +2,7 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // +#include "p_scossl_names.h" #include "decoder/p_scossl_decode_common.h" #include "keymgmt/p_scossl_mlkem_keymgmt.h" @@ -12,9 +13,39 @@ extern "C" { #endif -static SCOSSL_MLKEM_KEY_CTX *p_scossl_PrivateKeyInfo_to_mlkem(_In_ const SCOSSL_DECODE_KEYTYPE_DESC *desc, _In_ BIO *bio) +typedef struct { + int nid; + const char *name; + SYMCRYPT_MLKEM_PARAMS keyParams; +} SCOSSL_DECODE_MLKEM_PARAM_MAP; + +static SCOSSL_DECODE_MLKEM_PARAM_MAP p_scossl_decode_mlkem_param_maps[] = { + {-1, SCOSSL_SN_MLKEM512, SYMCRYPT_MLKEM_PARAMS_MLKEM512}, + {-1, SCOSSL_SN_MLKEM768, SYMCRYPT_MLKEM_PARAMS_MLKEM768}, + {-1, SCOSSL_SN_MLKEM1024, SYMCRYPT_MLKEM_PARAMS_MLKEM1024}}; + +static SYMCRYPT_MLKEM_PARAMS p_scossl_decode_mlkem_get_params(int nid) +{ + for (size_t i = 0; i < sizeof(p_scossl_decode_mlkem_param_maps) / sizeof(SCOSSL_DECODE_MLKEM_PARAM_MAP); i++) + { + if (p_scossl_decode_mlkem_param_maps[i].nid == -1) + { + p_scossl_decode_mlkem_param_maps[i].nid = OBJ_sn2nid(p_scossl_decode_mlkem_param_maps[i].name); + } + + if (p_scossl_decode_mlkem_param_maps[i].nid == nid) + { + return p_scossl_decode_mlkem_param_maps[i].keyParams; + } + } + + return SYMCRYPT_MLKEM_PARAMS_NULL; +} + +static SCOSSL_MLKEM_KEY_CTX *p_scossl_PrivateKeyInfo_to_mlkem(_In_ BIO *bio) { PKCS8_PRIV_KEY_INFO *p8Info = NULL; + const X509_ALGOR *alg = NULL; const unsigned char *pbKey = NULL; int cbKey; ASN1_OCTET_STRING *p8Data = NULL; @@ -24,7 +55,7 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_PrivateKeyInfo_to_mlkem(_In_ const SCOSSL_ SCOSSL_STATUS status = SCOSSL_FAILURE; if (d2i_PKCS8_PRIV_KEY_INFO_bio(bio, &p8Info) == NULL || - !PKCS8_pkey_get0(NULL, &pbKey, &cbKey, NULL, p8Info) || + !PKCS8_pkey_get0(NULL, &pbKey, &cbKey, &alg, p8Info) || (p8Data = d2i_ASN1_OCTET_STRING(NULL, &pbKey, cbKey)) == NULL) { ERR_raise(ERR_LIB_PROV, ASN1_R_DECODE_ERROR); @@ -45,9 +76,15 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_PrivateKeyInfo_to_mlkem(_In_ const SCOSSL_ goto cleanup; } - keyCtx->params = (SYMCRYPT_MLKEM_PARAMS)desc->keyParams;; + keyCtx->params = p_scossl_decode_mlkem_get_params(OBJ_obj2nid(alg->algorithm)); keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; + if (keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); + goto cleanup; + } + if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); @@ -83,7 +120,7 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_PrivateKeyInfo_to_mlkem(_In_ const SCOSSL_ return keyCtx; } -static SCOSSL_MLKEM_KEY_CTX *p_scossl_SubjectPublicKeyInfo_to_mlkem(_In_ const SCOSSL_DECODE_KEYTYPE_DESC *desc, _In_ BIO *bio) +static SCOSSL_MLKEM_KEY_CTX *p_scossl_SubjectPublicKeyInfo_to_mlkem(_In_ BIO *bio) { SUBJECT_PUBKEY_INFO *subjPubKeyInfo; SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; @@ -108,9 +145,15 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_SubjectPublicKeyInfo_to_mlkem(_In_ const S goto cleanup; } - keyCtx->params = (SYMCRYPT_MLKEM_PARAMS)desc->keyParams; + keyCtx->params = p_scossl_decode_mlkem_get_params(OBJ_obj2nid(subjPubKeyInfo->algorithm->algorithm)); keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; + if (keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); + goto cleanup; + } + if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); @@ -161,52 +204,46 @@ static SCOSSL_STATUS p_scossl_der_to_mlkem_export_object(_In_ SCOSSL_DECODE_CTX return p_scossl_mlkem_keymgmt_export(keyCtx, ctx->desc->selection, exportCb, exportCbArg); } -#define SCOSSL_MAKE_MLKEM_DECODER(paramSet, decoderType) \ - static SCOSSL_DECODE_KEYTYPE_DESC p_scossl_mlkem##paramSet##_##decoderType##_desc = { \ - "MLKEM", \ - select_##decoderType, \ - (PSCOSSL_DECODE_INTERNAL_FN)p_scossl_##decoderType##_to_mlkem, \ - (OSSL_FUNC_keymgmt_free_fn *)p_scossl_mlkem_keymgmt_free_key_ctx, \ - SYMCRYPT_MLKEM_PARAMS_MLKEM##paramSet}; \ - \ - static SCOSSL_DECODE_CTX * \ - p_scossl_der_to_mlkem##paramSet##_##decoderType##_newctx(_In_ SCOSSL_PROVCTX *provctx) \ - { \ - return p_scossl_decode_newctx( \ - provctx, \ - &p_scossl_mlkem##paramSet##_##decoderType##_desc); \ - } \ - \ - static BOOL \ - p_scossl_der_to_mlkem##paramSet##_##decoderType##_does_selection( \ - ossl_unused void *provctx, \ - int selection) \ - { \ - return p_scossl_decode_does_selection( \ - &p_scossl_mlkem##paramSet##_##decoderType##_desc, \ - selection); \ - } \ - \ - const OSSL_DISPATCH p_scossl_der_to_mlkem##paramSet##_##decoderType##_functions[] = { \ - {OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))p_scossl_der_to_mlkem##paramSet##_##decoderType##_newctx}, \ - {OSSL_FUNC_DECODER_FREECTX, (void (*)(void))p_scossl_decode_freectx}, \ - {OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_decode_settable_ctx_params}, \ - {OSSL_FUNC_DECODER_SET_CTX_PARAMS, (void (*)(void))p_scossl_decode_set_ctx_params}, \ - {OSSL_FUNC_DECODER_DOES_SELECTION, (void (*)(void)) \ - p_scossl_der_to_mlkem##paramSet##_##decoderType##_does_selection}, \ - {OSSL_FUNC_DECODER_DECODE, (void (*)(void))p_scossl_decode}, \ - {OSSL_FUNC_DECODER_EXPORT_OBJECT, (void (*)(void))p_scossl_der_to_mlkem_export_object}, \ +#define SCOSSL_MAKE_MLKEM_DECODER(decoderType) \ + static SCOSSL_DECODE_KEYTYPE_DESC p_scossl_mlkem_##decoderType##_desc = { \ + "MLKEM", \ + select_##decoderType, \ + (PSCOSSL_DECODE_INTERNAL_FN)p_scossl_##decoderType##_to_mlkem, \ + (OSSL_FUNC_keymgmt_free_fn *)p_scossl_mlkem_keymgmt_free_key_ctx}; \ + \ + static SCOSSL_DECODE_CTX * \ + p_scossl_der_to_mlkem_##decoderType##_newctx(_In_ SCOSSL_PROVCTX *provctx) \ + { \ + return p_scossl_decode_newctx( \ + provctx, \ + &p_scossl_mlkem_##decoderType##_desc); \ + } \ + \ + static BOOL \ + p_scossl_der_to_mlkem_##decoderType##_does_selection( \ + ossl_unused void *provctx, \ + int selection) \ + { \ + return p_scossl_decode_does_selection( \ + &p_scossl_mlkem_##decoderType##_desc, \ + selection); \ + } \ + \ + const OSSL_DISPATCH p_scossl_der_to_mlkem_##decoderType##_functions[] = { \ + {OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))p_scossl_der_to_mlkem_##decoderType##_newctx}, \ + {OSSL_FUNC_DECODER_FREECTX, (void (*)(void))p_scossl_decode_freectx}, \ + {OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_decode_settable_ctx_params}, \ + {OSSL_FUNC_DECODER_SET_CTX_PARAMS, (void (*)(void))p_scossl_decode_set_ctx_params}, \ + {OSSL_FUNC_DECODER_DOES_SELECTION, (void (*)(void)) p_scossl_der_to_mlkem_##decoderType##_does_selection}, \ + {OSSL_FUNC_DECODER_DECODE, (void (*)(void))p_scossl_decode}, \ + {OSSL_FUNC_DECODER_EXPORT_OBJECT, (void (*)(void))p_scossl_der_to_mlkem_export_object}, \ {0, NULL}}; extern const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[]; -SCOSSL_MAKE_MLKEM_DECODER(512, PrivateKeyInfo); -SCOSSL_MAKE_MLKEM_DECODER(512, SubjectPublicKeyInfo); -SCOSSL_MAKE_MLKEM_DECODER(768, PrivateKeyInfo); -SCOSSL_MAKE_MLKEM_DECODER(768, SubjectPublicKeyInfo); -SCOSSL_MAKE_MLKEM_DECODER(1024, PrivateKeyInfo); -SCOSSL_MAKE_MLKEM_DECODER(1024, SubjectPublicKeyInfo); +SCOSSL_MAKE_MLKEM_DECODER(PrivateKeyInfo); +SCOSSL_MAKE_MLKEM_DECODER(SubjectPublicKeyInfo); #ifdef __cplusplus } diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c index 993454b7..a68dbd22 100644 --- a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c +++ b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c @@ -85,7 +85,7 @@ static PKCS8_PRIV_KEY_INFO *p_scossl_mlkem_key_to_p8info(_In_ const SCOSSL_MLKEM goto cleanup; } - if (!PKCS8_pkey_set0(p8Info, p8Obj, 0, V_ASN1_UNDEF, NULL, pbDer, cbKey)) // TODO params? + if (!PKCS8_pkey_set0(p8Info, p8Obj, 0, V_ASN1_UNDEF, NULL, pbDer, cbDer)) { ERR_raise(ERR_LIB_PROV, ASN1_R_ENCODE_ERROR); goto cleanup; @@ -97,13 +97,13 @@ static PKCS8_PRIV_KEY_INFO *p_scossl_mlkem_key_to_p8info(_In_ const SCOSSL_MLKEM if (status != SCOSSL_SUCCESS) { PKCS8_PRIV_KEY_INFO_free(p8Info); + OPENSSL_free(pbDer); p8Info = NULL; } ASN1_OCTET_STRING_free(p8Data); ASN1_OBJECT_free(p8Obj); OPENSSL_secure_clear_free(pbKey, cbKey); - OPENSSL_free(pbDer); return p8Info; } diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index d93ed8bf..0f9dc0c3 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -327,20 +327,12 @@ static const OSSL_ALGORITHM p_scossl_kem[] = { ALG_TABLE_END}; // Decoders -extern const OSSL_DISPATCH p_scossl_der_to_mlkem512_PrivateKeyInfo_functions[]; -extern const OSSL_DISPATCH p_scossl_der_to_mlkem512_SubjectPublicKeyInfo_functions[]; -extern const OSSL_DISPATCH p_scossl_der_to_mlkem768_PrivateKeyInfo_functions[]; -extern const OSSL_DISPATCH p_scossl_der_to_mlkem768_SubjectPublicKeyInfo_functions[]; -extern const OSSL_DISPATCH p_scossl_der_to_mlkem1024_PrivateKeyInfo_functions[]; -extern const OSSL_DISPATCH p_scossl_der_to_mlkem1024_SubjectPublicKeyInfo_functions[]; +extern const OSSL_DISPATCH p_scossl_der_to_mlkem_PrivateKeyInfo_functions[]; +extern const OSSL_DISPATCH p_scossl_der_to_mlkem_SubjectPublicKeyInfo_functions[]; static const OSSL_ALGORITHM p_scossl_decoder[] = { - ALG_DECODER(SCOSSL_ALG_NAME_MLKEM512, mlkem512, PrivateKeyInfo), - ALG_DECODER(SCOSSL_ALG_NAME_MLKEM512, mlkem512, SubjectPublicKeyInfo), - ALG_DECODER(SCOSSL_ALG_NAME_MLKEM768, mlkem768, PrivateKeyInfo), - ALG_DECODER(SCOSSL_ALG_NAME_MLKEM768, mlkem768, SubjectPublicKeyInfo), - ALG_DECODER(SCOSSL_ALG_NAME_MLKEM1024, mlkem1024, PrivateKeyInfo), - ALG_DECODER(SCOSSL_ALG_NAME_MLKEM1024, mlkem1024, SubjectPublicKeyInfo), + ALG_DECODER(SCOSSL_ALG_NAME_MLKEM_DECODER, mlkem, PrivateKeyInfo), + ALG_DECODER(SCOSSL_ALG_NAME_MLKEM_DECODER, mlkem, SubjectPublicKeyInfo), ALG_TABLE_END}; // Encoders @@ -382,6 +374,7 @@ static void p_scossl_teardown(_Inout_ SCOSSL_PROVCTX *provctx) scossl_destroy_logging(); scossl_destroy_safeprime_dlgroups(); scossl_ecc_destroy_ecc_curves(); + BIO_meth_free(provctx->coreBioMeth); #ifdef KEYSINUSE_ENABLED p_scossl_keysinuse_teardown(); #endif diff --git a/SymCryptProvider/src/p_scossl_names.h b/SymCryptProvider/src/p_scossl_names.h index 9209164a..9dec333b 100644 --- a/SymCryptProvider/src/p_scossl_names.h +++ b/SymCryptProvider/src/p_scossl_names.h @@ -79,11 +79,8 @@ extern "C" { #define SCOSSL_ALG_NAME_ECDSA "ECDSA" // Key encapsulation -#define SCOSSL_ALG_NAME_MLKEM512 SCOSSL_SN_MLKEM512":"SCOSSL_OID_MLKEM512 -#define SCOSSL_ALG_NAME_MLKEM768 SCOSSL_SN_MLKEM768":"SCOSSL_OID_MLKEM768 -#define SCOSSL_ALG_NAME_MLKEM1024 SCOSSL_SN_MLKEM1024":"SCOSSL_OID_MLKEM1024 -#define SCOSSL_ALG_NAME_MLKEM "MLKEM:"SCOSSL_ALG_NAME_MLKEM512":"SCOSSL_ALG_NAME_MLKEM768":"SCOSSL_ALG_NAME_MLKEM1024 - +#define SCOSSL_ALG_NAME_MLKEM "MLKEM" +#define SCOSSL_ALG_NAME_MLKEM_DECODER SCOSSL_ALG_NAME_MLKEM":"SCOSSL_SN_MLKEM512":"SCOSSL_OID_MLKEM512":"SCOSSL_SN_MLKEM768":"SCOSSL_OID_MLKEM768":"SCOSSL_SN_MLKEM1024":"SCOSSL_OID_MLKEM1024 #ifdef __cplusplus } From 495b85217e46d6705fa6543590c7937b9e37858f Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Mon, 21 Oct 2024 18:04:36 +0000 Subject: [PATCH 08/21] MLKEM text encoder and bugfixes --- .../src/decoder/p_scossl_decode_common.c | 7 +- .../src/encoder/p_scossl_encode_common.c | 37 +++- .../src/encoder/p_scossl_encode_common.h | 9 +- .../src/encoder/p_scossl_encode_mlkem.c | 191 +++++++++++++++--- .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 4 +- SymCryptProvider/src/p_scossl_base.c | 9 + 6 files changed, 214 insertions(+), 43 deletions(-) diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_common.c b/SymCryptProvider/src/decoder/p_scossl_decode_common.c index c53b555e..6dfb266b 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_common.c +++ b/SymCryptProvider/src/decoder/p_scossl_decode_common.c @@ -89,12 +89,9 @@ SCOSSL_STATUS p_scossl_decode(SCOSSL_DECODE_CTX *ctx, OSSL_CORE_BIO *in, int sel { selection = ctx->desc->selection; } - else if ((selection & ctx->desc->selection) == 0) - { - ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); - } - if ((bio = p_scossl_bio_new_from_core_bio(ctx->provctx, in)) != NULL) + if ((selection & ctx->desc->selection) != 0 && + (bio = p_scossl_bio_new_from_core_bio(ctx->provctx, in)) != NULL) { keyCtx = ctx->desc->decodeInternal(bio); } diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_common.c b/SymCryptProvider/src/encoder/p_scossl_encode_common.c index 58762151..7809cf9f 100644 --- a/SymCryptProvider/src/encoder/p_scossl_encode_common.c +++ b/SymCryptProvider/src/encoder/p_scossl_encode_common.c @@ -11,6 +11,8 @@ extern "C" { #endif +#define KEY_TO_TEXT_PRINT_WIDTH 15 + static const OSSL_PARAM p_scossl_encode_settable_param_types[] = { OSSL_PARAM_utf8_string(OSSL_ENCODER_PARAM_CIPHER, NULL, 0), OSSL_PARAM_utf8_string(OSSL_ENCODER_PARAM_PROPERTIES, NULL, 0), @@ -124,7 +126,7 @@ SCOSSL_STATUS p_scossl_encode(SCOSSL_ENCODE_CTX *ctx, OSSL_CORE_BIO *out, if (ctx->encodeInternal == NULL || keyAbstract != NULL || - (selection & ctx->selection) == 0) + (ctx->outFormat != SCOSSL_ENCODE_TEXT && ((selection & ctx->selection) == 0))) { ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); return SCOSSL_FAILURE; @@ -133,9 +135,10 @@ SCOSSL_STATUS p_scossl_encode(SCOSSL_ENCODE_CTX *ctx, OSSL_CORE_BIO *out, if ((bio = p_scossl_bio_new_from_core_bio(ctx->provctx, out)) != NULL) { ret = ctx->encodeInternal( - ctx, keyCtx, + ctx, bio, + keyCtx, + selection, passphraseCb, passphraseCbArgs, - bio, ctx->outFormat == SCOSSL_ENCODE_PEM); } @@ -144,6 +147,34 @@ SCOSSL_STATUS p_scossl_encode(SCOSSL_ENCODE_CTX *ctx, OSSL_CORE_BIO *out, return ret; } +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_encode_write_key_bytes(PCBYTE pbKey, SIZE_T cbKey, BIO *out) +{ + for(SIZE_T i = 0; i < cbKey; i++) + { + if (i % KEY_TO_TEXT_PRINT_WIDTH == 0) + { + if (BIO_printf(out, "\n ") <= 0) + { + return SCOSSL_FAILURE; + } + } + + if (BIO_printf(out, "%02x%s", pbKey[i], (i < cbKey - 1) ? ":" : "") <= 0) + { + return SCOSSL_FAILURE; + } + } + + if (BIO_printf(out, "\n") <= 0) + { + return SCOSSL_FAILURE; + } + + return SCOSSL_SUCCESS; +} + + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_common.h b/SymCryptProvider/src/encoder/p_scossl_encode_common.h index 05f5bf0e..e921a2e4 100644 --- a/SymCryptProvider/src/encoder/p_scossl_encode_common.h +++ b/SymCryptProvider/src/encoder/p_scossl_encode_common.h @@ -19,10 +19,11 @@ typedef enum { SCOSSL_ENCODE_TEXT } SCOSSL_ENCODE_OUT_FORMAT; -typedef SCOSSL_STATUS (*PSCOSSL_ENCODE_INTERNAL_FN) (_In_ PVOID ctx, +typedef SCOSSL_STATUS (*PSCOSSL_ENCODE_INTERNAL_FN) (_In_ PVOID ctx, _Inout_ BIO *out, _In_ PCVOID keyCtx, + int selection, _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs, - _Inout_ BIO *out, BOOL encodeToPem); + BOOL encodeToPem); typedef struct { @@ -48,13 +49,13 @@ const OSSL_PARAM *p_scossl_encode_settable_ctx_params(ossl_unused void *provctx) BOOL p_scossl_encode_does_selection(int supportedSelection, int selection); -SCOSSL_STATUS p_scossl_encode(_In_ SCOSSL_ENCODE_CTX *ctx, _Out_ OSSL_CORE_BIO *coreOut, +SCOSSL_STATUS p_scossl_encode(_In_ SCOSSL_ENCODE_CTX *ctx, _In_ OSSL_CORE_BIO *coreOut, _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, _In_ const OSSL_PARAM keyAbstract[], int selection, _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs); - +SCOSSL_STATUS p_scossl_encode_write_key_bytes(_In_reads_bytes_(cbKey) PCBYTE pbKey, SIZE_T cbKey, _Inout_ BIO *out); #ifdef __cplusplus } diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c index a68dbd22..44bafbc7 100644 --- a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c +++ b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c @@ -16,6 +16,23 @@ extern "C" { extern const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[]; +static const char *p_scossl_encode_mlkem_params_to_name(SYMCRYPT_MLKEM_PARAMS params) +{ + switch (params) + { + case SYMCRYPT_MLKEM_PARAMS_MLKEM512: + return SCOSSL_SN_MLKEM512; + case SYMCRYPT_MLKEM_PARAMS_MLKEM768: + return SCOSSL_SN_MLKEM768; + case SYMCRYPT_MLKEM_PARAMS_MLKEM1024: + return SCOSSL_SN_MLKEM1024; + default: + break; + } + + return NULL; +} + static ASN1_OBJECT *p_scossl_encode_get_mlkem_oid(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx) { int nid = NID_undef; @@ -112,9 +129,6 @@ static X509_PUBKEY *p_scossl_mlkem_key_to_pubkey(_In_ const SCOSSL_MLKEM_KEY_CTX { PBYTE pbKey = NULL; SIZE_T cbKey; - unsigned char *pbDer = NULL; - int cbDer; - ASN1_BIT_STRING *subjectPublicKey = NULL; X509_PUBKEY *pubKey = NULL; ASN1_OBJECT *p8Obj = NULL; SCOSSL_STATUS status = SCOSSL_FAILURE; @@ -125,8 +139,7 @@ static X509_PUBKEY *p_scossl_mlkem_key_to_pubkey(_In_ const SCOSSL_MLKEM_KEY_CTX goto cleanup; } - if ((subjectPublicKey = ASN1_BIT_STRING_new()) == NULL || - (pubKey = X509_PUBKEY_new()) == NULL) + if ((pubKey = X509_PUBKEY_new()) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; @@ -137,20 +150,13 @@ static X509_PUBKEY *p_scossl_mlkem_key_to_pubkey(_In_ const SCOSSL_MLKEM_KEY_CTX goto cleanup; } - if (!ASN1_BIT_STRING_set(subjectPublicKey, pbKey, cbKey) || - (cbDer = i2d_ASN1_BIT_STRING(subjectPublicKey, &pbDer)) == 0) - { - ERR_raise(ERR_LIB_PROV, ASN1_R_ENCODE_ERROR); - goto cleanup; - } - if ((p8Obj = p_scossl_encode_get_mlkem_oid(keyCtx)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); goto cleanup; } - if (!X509_PUBKEY_set0_param(pubKey, p8Obj, V_ASN1_NULL, NULL, pbDer, cbDer)) // TODO params? + if (!X509_PUBKEY_set0_param(pubKey, p8Obj, V_ASN1_NULL, NULL, pbKey, cbKey)) { ERR_raise(ERR_LIB_PROV, ASN1_R_ENCODE_ERROR); goto cleanup; @@ -161,23 +167,24 @@ static X509_PUBKEY *p_scossl_mlkem_key_to_pubkey(_In_ const SCOSSL_MLKEM_KEY_CTX cleanup: if (status != SCOSSL_SUCCESS) { + if (pubKey == NULL) + { + OPENSSL_secure_free(pbKey); + ASN1_OBJECT_free(p8Obj); + } X509_PUBKEY_free(pubKey); pubKey = NULL; } - ASN1_BIT_STRING_free(subjectPublicKey); - ASN1_OBJECT_free(p8Obj); - OPENSSL_secure_free(pbKey); - OPENSSL_free(pbDer); - return pubKey; } -static SCOSSL_STATUS p_scossl_mlkem_to_EncryptedPrivateKeyInfo(_In_ SCOSSL_ENCODE_CTX *ctx, +static SCOSSL_STATUS p_scossl_mlkem_to_EncryptedPrivateKeyInfo(_In_ SCOSSL_ENCODE_CTX *ctx, _Inout_ BIO *out, _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, + ossl_unused int selection, _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs, - _Inout_ BIO *out, BOOL encodeToPem) + BOOL encodeToPem) { int encodeSuccess; PKCS8_PRIV_KEY_INFO *p8Info = NULL; @@ -234,10 +241,11 @@ static SCOSSL_STATUS p_scossl_mlkem_to_EncryptedPrivateKeyInfo(_In_ SCOSSL_ENCOD return ret; } -static SCOSSL_STATUS p_scossl_mlkem_to_PrivateKeyInfo(_In_ SCOSSL_ENCODE_CTX *ctx, +static SCOSSL_STATUS p_scossl_mlkem_to_PrivateKeyInfo(_In_ SCOSSL_ENCODE_CTX *ctx, _Inout_ BIO *out, _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, + ossl_unused int selection, _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs, - _Inout_ BIO *out, BOOL encodeToPem) + BOOL encodeToPem) { int encodeSuccess; PKCS8_PRIV_KEY_INFO *p8Info = NULL; @@ -245,7 +253,7 @@ static SCOSSL_STATUS p_scossl_mlkem_to_PrivateKeyInfo(_In_ SCOSSL_ENCODE_CTX *ct if (ctx->cipherIntent) { - return p_scossl_mlkem_to_EncryptedPrivateKeyInfo(ctx, keyCtx, passphraseCb, passphraseCbArgs, out, encodeToPem); + return p_scossl_mlkem_to_EncryptedPrivateKeyInfo(ctx, out, keyCtx, selection, passphraseCb, passphraseCbArgs, encodeToPem); } if ((p8Info = p_scossl_mlkem_key_to_p8info(keyCtx)) == NULL) @@ -276,10 +284,11 @@ static SCOSSL_STATUS p_scossl_mlkem_to_PrivateKeyInfo(_In_ SCOSSL_ENCODE_CTX *ct return ret; } -static SCOSSL_STATUS p_scossl_mlkem_to_SubjectPublicKeyInfo(ossl_unused SCOSSL_ENCODE_CTX *ctx, +static SCOSSL_STATUS p_scossl_mlkem_to_SubjectPublicKeyInfo(ossl_unused SCOSSL_ENCODE_CTX *ctx, _Inout_ BIO *out, _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, + ossl_unused int selection, ossl_unused OSSL_PASSPHRASE_CALLBACK *passphraseCb, ossl_unused void *passphraseCbArgs, - _Inout_ BIO *out, BOOL encodeToPem) + BOOL encodeToPem) { int encodeSuccess; X509_PUBKEY *pubKey = NULL; @@ -313,6 +322,115 @@ static SCOSSL_STATUS p_scossl_mlkem_to_SubjectPublicKeyInfo(ossl_unused SCOSSL_E return ret; } +static SCOSSL_STATUS p_scossl_mlkem_to_text(ossl_unused SCOSSL_ENCODE_CTX *ctx, _Inout_ BIO *out, + _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, + int selection, + ossl_unused OSSL_PASSPHRASE_CALLBACK *passphraseCb, ossl_unused void *passphraseCbArgs, + ossl_unused BOOL encodeToPem) +{ + BOOL printPrivateSeed = FALSE; + BOOL printDecapsulationKey = FALSE; + BOOL printEncapsulationKey = FALSE; + const char *paramName = p_scossl_encode_mlkem_params_to_name(keyCtx->params); + PBYTE pbKey = NULL; + SIZE_T cbKey; + SCOSSL_STATUS ret = SCOSSL_FAILURE; + + if (keyCtx->key == NULL || + paramName == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + goto cleanup; + } + + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + { + if (keyCtx->format == SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY); + goto cleanup; + } + + printDecapsulationKey = TRUE; + printEncapsulationKey = TRUE; + } + else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + { + printEncapsulationKey = TRUE; + } + + if (printDecapsulationKey) + { + // Try to get the private seed. Otherwise this key was encoded using the whole decapsulation key. + if (p_scossl_mlkem_keymgmt_get_key_bytes(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED, &pbKey, &cbKey)) + { + if (BIO_printf(out, "MLKEM Decapsulation-Key (512 bit private seed encoding):\n") <= 0) + { + goto cleanup; + } + + if (BIO_printf(out, "private-seed") <= 0 || + p_scossl_encode_write_key_bytes(pbKey, cbKey, out) != SCOSSL_SUCCESS) + { + goto cleanup; + } + + printPrivateSeed = TRUE; + } + + OPENSSL_secure_clear_free(pbKey, cbKey); + if (!p_scossl_mlkem_keymgmt_get_key_bytes(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, &pbKey, &cbKey)) + { + goto cleanup; + } + + if (!printPrivateSeed && + BIO_printf(out, "MLKEM Decapsulation-Key (%ld bit decapsulation key encoding):", cbKey * 8) <= 0) + { + goto cleanup; + } + + if (BIO_printf(out, "decapsulation-key") <= 0 || + p_scossl_encode_write_key_bytes(pbKey, cbKey, out) != SCOSSL_SUCCESS) + { + goto cleanup; + } + } + + if (printEncapsulationKey) + { + OPENSSL_secure_clear_free(pbKey, cbKey); + if (!p_scossl_mlkem_keymgmt_get_key_bytes(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, &pbKey, &cbKey)) + { + goto cleanup; + } + + if (!printDecapsulationKey && // Implies no private seed + BIO_printf(out, "MLKEM Encapsulation-Key (%ld bit):", cbKey * 8) <= 0) + { + goto cleanup; + } + + if (BIO_printf(out, "encapsulation-key") <= 0 || + p_scossl_encode_write_key_bytes(pbKey, cbKey, out) != SCOSSL_SUCCESS) + { + goto cleanup; + } + } + + if (BIO_printf(out, "PARAMETER SET: %s\n", paramName) <= 0) + { + goto cleanup; + } + + ret = SCOSSL_SUCCESS; + +cleanup: + OPENSSL_secure_clear_free(pbKey, cbKey); + + return ret; +} + static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_encoder_import_object(_In_ SCOSSL_ENCODE_CTX *ctx, int selection, _In_ const OSSL_PARAM params[]) { @@ -330,15 +448,15 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_encoder_import_object(_In_ SCOSSL_EN static SCOSSL_ENCODE_CTX *p_scossl_mlkem_to_##decoderType##_der_newctx(_In_ SCOSSL_PROVCTX *provctx) \ { \ return p_scossl_encode_newctx(provctx, select_##decoderType, \ - SCOSSL_ENCODE_DER, \ - (PSCOSSL_ENCODE_INTERNAL_FN)p_scossl_mlkem_to_##decoderType); \ + SCOSSL_ENCODE_DER, \ + (PSCOSSL_ENCODE_INTERNAL_FN)p_scossl_mlkem_to_##decoderType); \ } \ \ static SCOSSL_ENCODE_CTX *p_scossl_mlkem_to_##decoderType##_pem_newctx(_In_ SCOSSL_PROVCTX *provctx) \ { \ return p_scossl_encode_newctx(provctx, select_##decoderType, \ - SCOSSL_ENCODE_PEM, \ - (PSCOSSL_ENCODE_INTERNAL_FN)p_scossl_mlkem_to_##decoderType); \ + SCOSSL_ENCODE_PEM, \ + (PSCOSSL_ENCODE_INTERNAL_FN)p_scossl_mlkem_to_##decoderType); \ } \ \ static BOOL p_scossl_der_to_mlkem_##decoderType##_does_selection(ossl_unused void *provctx, int selection) \ @@ -372,6 +490,21 @@ MAKE_MLKEM_ENCODER(PrivateKeyInfo) MAKE_MLKEM_ENCODER(EncryptedPrivateKeyInfo) MAKE_MLKEM_ENCODER(SubjectPublicKeyInfo) +static SCOSSL_ENCODE_CTX *p_scossl_mlkem_to_text_newctx(_In_ SCOSSL_PROVCTX *provctx) +{ + return p_scossl_encode_newctx(provctx, 0, + SCOSSL_ENCODE_TEXT, + (PSCOSSL_ENCODE_INTERNAL_FN)p_scossl_mlkem_to_text); +} + +const OSSL_DISPATCH p_scossl_mlkem_to_text_functions[] = { + {OSSL_FUNC_ENCODER_NEWCTX, (void (*)(void))p_scossl_mlkem_to_text_newctx}, + {OSSL_FUNC_ENCODER_FREECTX, (void (*)(void))p_scossl_encode_freectx}, + {OSSL_FUNC_ENCODER_ENCODE, (void (*)(void))p_scossl_encode}, + {OSSL_FUNC_ENCODER_IMPORT_OBJECT, (void (*)(void))p_scossl_mlkem_encoder_import_object}, + {OSSL_FUNC_ENCODER_FREE_OBJECT, (void (*)(void))p_scossl_mlkem_keymgmt_free_key_ctx}, + {0, NULL}}; + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index 32e497a2..2d5160f4 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -922,11 +922,11 @@ static SYMCRYPT_MLKEM_PARAMS p_scossl_mlkem_keymgmt_params_from_name(const char } else if (OPENSSL_strcasecmp(name, SCOSSL_MLKEM_PARAM_NAME_768) == 0) { - return SYMCRYPT_MLKEM_PARAMS_MLKEM512; + return SYMCRYPT_MLKEM_PARAMS_MLKEM768; } else if (OPENSSL_strcasecmp(name, SCOSSL_MLKEM_PARAM_NAME_1024) == 0) { - return SYMCRYPT_MLKEM_PARAMS_MLKEM512; + return SYMCRYPT_MLKEM_PARAMS_MLKEM1024; } return SYMCRYPT_MLKEM_PARAMS_NULL; diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index 0f9dc0c3..9a0a0353 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -59,6 +59,13 @@ extern "C" { p_scossl_##name##_to_##encoderType##_##format##_functions, \ NULL} +#define ALG_TEXT_ENCODER(algNames, name) { \ + algNames, \ + "provider="P_SCOSSL_NAME \ + ",fips=yes,output=text", \ + p_scossl_##name##_to_text_functions, \ + NULL} + #define ALG_TABLE_END {NULL, NULL, NULL, NULL} typedef struct { @@ -342,6 +349,7 @@ extern const OSSL_DISPATCH p_scossl_mlkem_to_EncryptedPrivateKeyInfo_der_functio extern const OSSL_DISPATCH p_scossl_mlkem_to_EncryptedPrivateKeyInfo_pem_functions[]; extern const OSSL_DISPATCH p_scossl_mlkem_to_SubjectPublicKeyInfo_der_functions[]; extern const OSSL_DISPATCH p_scossl_mlkem_to_SubjectPublicKeyInfo_pem_functions[]; +extern const OSSL_DISPATCH p_scossl_mlkem_to_text_functions[]; static const OSSL_ALGORITHM p_scossl_encoder[] = { ALG_ENCODER(SCOSSL_ALG_NAME_MLKEM, mlkem, PrivateKeyInfo, der), @@ -350,6 +358,7 @@ static const OSSL_ALGORITHM p_scossl_encoder[] = { ALG_ENCODER(SCOSSL_ALG_NAME_MLKEM, mlkem, EncryptedPrivateKeyInfo, pem), ALG_ENCODER(SCOSSL_ALG_NAME_MLKEM, mlkem, SubjectPublicKeyInfo, der), ALG_ENCODER(SCOSSL_ALG_NAME_MLKEM, mlkem, SubjectPublicKeyInfo, pem), + ALG_TEXT_ENCODER(SCOSSL_ALG_NAME_MLKEM, mlkem), ALG_TABLE_END}; static SCOSSL_STATUS p_scossl_register_extended_algorithms() From 4ddd8ca5b57b94fca8960fa07f763ea8531c55ef Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Tue, 29 Oct 2024 18:45:26 +0000 Subject: [PATCH 09/21] Start of hybrid implementation --- SymCryptProvider/inc/scossl_provider.h | 33 +- .../src/encoder/p_scossl_encode_mlkem.c | 10 +- SymCryptProvider/src/kem/p_scossl_mlkem.h | 35 +- .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 341 ++++++++++++++---- .../src/keymgmt/p_scossl_mlkem_keymgmt.h | 6 +- SymCryptProvider/src/p_scossl_base.c | 5 +- SymCryptProvider/src/p_scossl_ecc.c | 48 ++- SymCryptProvider/src/p_scossl_ecc.h | 4 + SymCryptProvider/src/p_scossl_names.h | 13 - 9 files changed, 386 insertions(+), 109 deletions(-) diff --git a/SymCryptProvider/inc/scossl_provider.h b/SymCryptProvider/inc/scossl_provider.h index 2ad7a375..69ebd253 100644 --- a/SymCryptProvider/inc/scossl_provider.h +++ b/SymCryptProvider/inc/scossl_provider.h @@ -14,14 +14,12 @@ extern "C" { // // Digest parameters // - #define SCOSSL_DIGEST_PARAM_FUNCTION_NAME_STRING "function-name-string" #define SCOSSL_DIGEST_PARAM_CUSTOMIZATION_STRING "customization-string" // // KDF parameters // - #define SCOSSL_KDF_PARAM_SRTP_RATE "rate" #define SCOSSL_KDF_PARAM_SRTP_INDEX "index" #define SCOSSL_KDF_PARAM_SRTP_INDEX_WIDTH "index-width" @@ -29,11 +27,40 @@ extern "C" { // // SRTP labels // - #define SCOSSL_SRTP_LABEL_ENCRYPTION "encryption" #define SCOSSL_SRTP_LABEL_AUTHENTICATION "authentication" #define SCOSSL_SRTP_LABEL_SALTING "salting" +// +// Hybrid PQ parameters +// +#define SCOSSL_PKEY_PARAM_CLASSIC_PRIV_KEY "classic-priv" +#define SCOSSL_PKEY_PARAM_CLASSIC_PUB_KEY "classic-pub" +#define SCOSSL_PKEY_PARAM_CLASSIC_ENCODED_PUBLIC_KEY "classic-encoded-pub-key" + +// +// Extended algorithms not found in default OpenSSL implementation +// + +#define SCOSSL_SN_MLKEM512 "mlkem512" +#define SCOSSL_OID_MLKEM512 "2.16.840.1.101.3.4.4.1" + +#define SCOSSL_SN_MLKEM768 "mlkem768" +#define SCOSSL_OID_MLKEM768 "2.16.840.1.101.3.4.4.2" + +#define SCOSSL_SN_MLKEM1024 "mlkem1024" +#define SCOSSL_OID_MLKEM1024 "2.16.840.1.101.3.4.4.3" + +#define SCOSSL_SN_P256_MLKEM768 SN_X9_62_prime256v1 SCOSSL_SN_MLKEM768 +#define SCOSSL_OID_P256_MLKEM768 "2.16.840.1.101.3.4.4.4" + +#define SCOSSL_SN_X25519_MLKEM768 SN_X25519 SCOSSL_SN_MLKEM768 +#define SCOSSL_OID_X25519_MLKEM768 "2.16.840.1.101.3.4.4.3" + +// Hybrid PQ group names +#define SCOSSL_MLKEM_PARAM_NAME_P256_MLKEM768 SN_secp256r1 SCOSSL_MLKEM_PARAM_NAME_768 +#define SCOSSL_MLKEM_PARAM_NAME_X25519_MLKEM768 SN_X25519 SCOSSL_MLKEM_PARAM_NAME_768 + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c index 44bafbc7..b015b4ea 100644 --- a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c +++ b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c @@ -84,7 +84,7 @@ static PKCS8_PRIV_KEY_INFO *p_scossl_mlkem_key_to_p8info(_In_ const SCOSSL_MLKEM goto cleanup; } - if (p_scossl_mlkem_keymgmt_get_key_bytes(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED, &pbKey, &cbKey) != SCOSSL_SUCCESS) + if (p_scossl_mlkem_keymgmt_get_encoded_key(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED, &pbKey, &cbKey) != SCOSSL_SUCCESS) { goto cleanup; } @@ -145,7 +145,7 @@ static X509_PUBKEY *p_scossl_mlkem_key_to_pubkey(_In_ const SCOSSL_MLKEM_KEY_CTX goto cleanup; } - if (p_scossl_mlkem_keymgmt_get_key_bytes(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, &pbKey, &cbKey) != SCOSSL_SUCCESS) + if (p_scossl_mlkem_keymgmt_get_encoded_key(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, &pbKey, &cbKey) != SCOSSL_SUCCESS) { goto cleanup; } @@ -362,7 +362,7 @@ static SCOSSL_STATUS p_scossl_mlkem_to_text(ossl_unused SCOSSL_ENCODE_CTX *ctx, if (printDecapsulationKey) { // Try to get the private seed. Otherwise this key was encoded using the whole decapsulation key. - if (p_scossl_mlkem_keymgmt_get_key_bytes(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED, &pbKey, &cbKey)) + if (p_scossl_mlkem_keymgmt_get_encoded_key(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED, &pbKey, &cbKey)) { if (BIO_printf(out, "MLKEM Decapsulation-Key (512 bit private seed encoding):\n") <= 0) { @@ -379,7 +379,7 @@ static SCOSSL_STATUS p_scossl_mlkem_to_text(ossl_unused SCOSSL_ENCODE_CTX *ctx, } OPENSSL_secure_clear_free(pbKey, cbKey); - if (!p_scossl_mlkem_keymgmt_get_key_bytes(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, &pbKey, &cbKey)) + if (!p_scossl_mlkem_keymgmt_get_encoded_key(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, &pbKey, &cbKey)) { goto cleanup; } @@ -400,7 +400,7 @@ static SCOSSL_STATUS p_scossl_mlkem_to_text(ossl_unused SCOSSL_ENCODE_CTX *ctx, if (printEncapsulationKey) { OPENSSL_secure_clear_free(pbKey, cbKey); - if (!p_scossl_mlkem_keymgmt_get_key_bytes(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, &pbKey, &cbKey)) + if (!p_scossl_mlkem_keymgmt_get_encoded_key(keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, &pbKey, &cbKey)) { goto cleanup; } diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.h b/SymCryptProvider/src/kem/p_scossl_mlkem.h index 2f01bd4c..3154dff2 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.h +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.h @@ -3,15 +3,48 @@ // #include "scossl_helpers.h" +#include "p_scossl_ecc.h" #ifdef __cplusplus extern "C" { #endif typedef struct { + OSSL_FUNC_keymgmt_gen_set_params_fn *setParams; + OSSL_FUNC_keymgmt_gen_cleanup_fn *genCleanup; + OSSL_FUNC_keymgmt_gen_init_fn *genInit; + OSSL_FUNC_keymgmt_gen_set_template_fn *setTemplate; + OSSL_FUNC_keymgmt_gen_fn *gen; + OSSL_FUNC_keymgmt_new_fn *new; + OSSL_FUNC_keymgmt_free_fn *free; + OSSL_FUNC_keymgmt_dup_fn *dup; + OSSL_FUNC_keymgmt_get_params_fn *getParams; + OSSL_FUNC_keymgmt_set_params_fn *setParams; + OSSL_FUNC_keymgmt_has_fn *has; + OSSL_FUNC_keymgmt_match_fn *match; + OSSL_FUNC_keymgmt_import_fn *import; + OSSL_FUNC_keymgmt_export_fn *export; + OSSL_FUNC_keymgmt_validate_fn *validate; +} SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS; + +typedef struct { + OSSL_FUNC_keyexch_newctx_fn *newCtx; + OSSL_FUNC_keyexch_freectx_fn *freeCtx; + OSSL_FUNC_keyexch_dupctx_fn *dupCtx; + OSSL_FUNC_keyexch_init_fn *init; + OSSL_FUNC_keyexch_set_peer_fn *setPeer; + OSSL_FUNC_keyexch_derive_fn *derive; +} SCOSSL_MLKEM_CLASSIC_KEYEXCH_FNS; + + +typedef struct { + const char *groupName; PSYMCRYPT_MLKEMKEY key; - SYMCRYPT_MLKEM_PARAMS params; + SYMCRYPT_MLKEM_PARAMS mlkemParams; SYMCRYPT_MLKEMKEY_FORMAT format; + + SCOSSL_ECC_KEY_CTX *classicKeyCtx; + SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS *classicKeyMgmt; } SCOSSL_MLKEM_KEY_CTX; #ifdef __cplusplus diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index 2d5160f4..f4e20b0a 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -2,6 +2,8 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // +#include "scossl_provider.h" +#include "p_scossl_base.h" #include "kem/p_scossl_mlkem.h" #include "keymgmt/p_scossl_mlkem_keymgmt.h" @@ -13,18 +15,23 @@ extern "C" { #endif -#define SCOSSL_MLKEM_PARAM_NAME_512 "mlkem512" -#define SCOSSL_MLKEM_PARAM_NAME_768 "mlkem768" -#define SCOSSL_MLKEM_PARAM_NAME_1024 "mlkem1024" - typedef struct { - SYMCRYPT_MLKEM_PARAMS params; + SCOSSL_PROVCTX *provCtx; + const char *groupName; + SYMCRYPT_MLKEM_PARAMS mlkemParams; + + PVOID classicKeygenCtx; + const char *classicGroupName; + SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS *classicKeyMgmt; } SCOSSL_MLKEM_KEYGEN_CTX; -#define SCOSSL_MLKEM_PKEY_PARAMETER_TYPES \ - OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), \ - OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \ - OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), +#define SCOSSL_MLKEM_PKEY_PARAMETER_TYPES \ + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), \ + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \ + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), \ + OSSL_PARAM_octet_string(SCOSSL_PKEY_PARAM_CLASSIC_ENCODED_PUBLIC_KEY, NULL, 0), \ + OSSL_PARAM_octet_string(SCOSSL_PKEY_PARAM_CLASSIC_PUB_KEY, NULL, 0), \ + OSSL_PARAM_octet_string(SCOSSL_PKEY_PARAM_CLASSIC_PRIV_KEY, NULL, 0), \ static const OSSL_PARAM p_scossl_mlkem_keygen_settable_param_types[] = { OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), @@ -32,6 +39,7 @@ static const OSSL_PARAM p_scossl_mlkem_keygen_settable_param_types[] = { static const OSSL_PARAM p_scossl_mlkem_keymgmt_settable_param_types[] = { OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), + OSSL_PARAM_octet_string(SCOSSL_PKEY_PARAM_CLASSIC_ENCODED_PUBLIC_KEY, NULL, 0), OSSL_PARAM_END}; static const OSSL_PARAM p_scossl_mlkem_keymgmt_gettable_param_types[] = { @@ -61,8 +69,14 @@ static const OSSL_PARAM *p_scossl_mlkem_impexp_types[] = { p_scossl_mlkem_pkey_types, p_scossl_mlkem_all_types}; -static SYMCRYPT_MLKEM_PARAMS p_scossl_mlkem_keymgmt_params_from_name(_In_ const char *name); -static const char * p_scossl_mlkem_keymgmt_params_to_name(_In_ const SYMCRYPT_MLKEM_PARAMS name); +static SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS p_scossl_ecc_classic_keymgmt; +static SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS p_scossl_x25519_classic_keymgmt; + +static const char *p_scossl_mlkem_keymgmt_params_from_name(_In_ const char *groupName, + _Out_ SYMCRYPT_MLKEM_PARAMS *mlkemParams, + _Out_ const char **classicGroupName, + _Out_ SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS **classicKeymgmt); +static const char *p_scossl_mlkem_keymgmt_get_group_name(_In_ const SCOSSL_MLKEM_KEY_CTX keyCtx); static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx); SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(ossl_unused void *provCtx) @@ -80,6 +94,11 @@ void p_scossl_mlkem_keymgmt_free_key_ctx(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx) SymCryptMlKemkeyFree(keyCtx->key); } + if (keyCtx->classicKeyCtx != NULL) + { + keyCtx->classicKeyMgmt->free(keyCtx->classicKeyCtx); + } + OPENSSL_free(keyCtx); } @@ -96,22 +115,22 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS { if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { - copyCtx->params = keyCtx->params; + copyCtx->mlkemParams = keyCtx->mlkemParams; } else { - copyCtx->params = SYMCRYPT_MLKEM_PARAMS_NULL; + copyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_NULL; } if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 && keyCtx->key != NULL) { - if (copyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) + if (copyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); goto cleanup; } - if ((copyCtx->key = SymCryptMlKemkeyAllocate(copyCtx->params)) == NULL) + if ((copyCtx->key = SymCryptMlKemkeyAllocate(copyCtx->mlkemParams)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; @@ -126,7 +145,7 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; } - ret = p_scossl_mlkem_keymgmt_get_key_bytes( + ret = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx, format, &pbKey, &cbKey); @@ -155,6 +174,12 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS copyCtx->key = NULL; copyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_NULL; } + + if (keyCtx->classicKeyCtx != NULL) + { + copyCtx->classicKeyMgmt = keyCtx->classicKeyMgmt; + copyCtx->classicKeyCtx = keyCtx->classicKeyMgmt->dup(keyCtx->classicKeyCtx, selection); + } } ret = SCOSSL_SUCCESS; @@ -180,6 +205,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEYGE const OSSL_PARAM *p; if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL) { + int classicGroupNid; const char *name; if (!OSSL_PARAM_get_utf8_string_ptr(p, &name)) @@ -188,9 +214,11 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEYGE return SCOSSL_FAILURE; } - if ((genCtx->params = p_scossl_mlkem_keymgmt_params_from_name(name)) == SYMCRYPT_MLKEM_PARAMS_NULL) + genCtx->groupName = p_scossl_mlkem_keymgmt_params_from_name(name, &genCtx->mlkemParams, &genCtx->classicGroupName, &genCtx->classicKeyMgmt); + + if (genCtx->groupName == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); return SCOSSL_FAILURE; } } @@ -198,13 +226,21 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEYGE return SCOSSL_SUCCESS;; } -static const OSSL_PARAM *p_scossl_mlkem_keygen_settable_params(ossl_unused void *genCtx, ossl_unused void *provCtx) +static const OSSL_PARAM *p_scossl_mlkem_keygen_settable_params(_In_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, ossl_unused void *provCtx) { return p_scossl_mlkem_keygen_settable_param_types; } static void p_scossl_mlkem_keygen_cleanup(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx) { + if (genCtx == NULL) + return; + + if (genCtx->classicKeygenCtx != NULL) + { + genCtx->classicKeyMgmt->genCleanup(genCtx->classicKeygenCtx); + } + OPENSSL_free(genCtx); } @@ -215,7 +251,12 @@ static SCOSSL_MLKEM_KEYGEN_CTX *p_scossl_mlkem_keygen_init(ossl_unused void *pro if (genCtx != NULL) { - genCtx->params = SYMCRYPT_MLKEM_PARAMS_MLKEM768; + genCtx->provCtx = provCtx; + genCtx->groupName = SCOSSL_SN_MLKEM768; + genCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; + genCtx->classicGroupName = NULL; + genCtx->classicKeyMgmt = NULL; + genCtx->classicKeygenCtx = NULL; if (p_scossl_mlkem_keygen_set_params(genCtx, params) != SCOSSL_SUCCESS) { @@ -236,25 +277,32 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEY return SCOSSL_FAILURE; } - if (tmplCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) + if (tmplCtx->groupName == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); return SCOSSL_FAILURE; } - genCtx->params = tmplCtx->params; + genCtx->groupName = p_scossl_mlkem_keymgmt_params_from_name(tmplCtx->groupName, &genCtx->mlkemParams, &genCtx->classicGroupName, &genCtx->classicKeyMgmt); + if (genCtx->groupName == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); + return SCOSSL_FAILURE; + } return SCOSSL_SUCCESS; } -static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, ossl_unused OSSL_CALLBACK *cb, ossl_unused void *cbarg) +static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ OSSL_CALLBACK *cb, _In_ void *cbarg) { + EVP_PKEY_CTX *classicGenCtx; + int pkeyId; BOOL success = FALSE; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_MLKEM_KEY_CTX *keyCtx; if ((keyCtx = p_scossl_mlkem_keymgmt_new_ctx(NULL)) == NULL || - (keyCtx->key = SymCryptMlKemkeyAllocate(genCtx->params)) == NULL) + (keyCtx->key = SymCryptMlKemkeyAllocate(genCtx->mlkemParams)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; @@ -267,7 +315,26 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX goto cleanup; } - keyCtx->params = genCtx->params; + if (genCtx->classicGroupName != NULL) + { + OSSL_PARAM classicParams[2] = { + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, genCtx->classicGroupName, 0), + OSSL_PARAM_END}; + + genCtx->classicKeygenCtx = genCtx->classicKeyMgmt->genInit(genCtx->provCtx, 0, classicParams); + if (genCtx->classicKeygenCtx == NULL) + { + goto cleanup; + } + + keyCtx->classicKeyCtx = genCtx->classicKeyMgmt->gen(genCtx->classicKeygenCtx, cb, cbarg); + if (keyCtx->classicKeyCtx == NULL) + { + goto cleanup; + } + } + + keyCtx->mlkemParams = genCtx->mlkemParams; keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; success = TRUE; @@ -302,15 +369,19 @@ static const OSSL_PARAM *p_scossl_mlkem_keymgmt_settable_params(ossl_unused void static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_params(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, _In_ const OSSL_PARAM params[]) { - SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; const OSSL_PARAM *p; if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) { PCBYTE pbKey; SIZE_T cbKey; + PCBYTE pbMlKemKey; + SIZE_T cbMlKemKey; + PCBYTE pbClassicKey; + SIZE_T cbClassicKey; + SYMCRYPT_ERROR scError; - if (keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) + if (keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); return SCOSSL_FAILURE; @@ -322,19 +393,49 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_params(_In_ SCOSSL_MLKEM_KEY_CTX return SCOSSL_FAILURE; } + if (keyCtx->classicKeyCtx != NULL) + { + scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->mlkemParams, SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, &cbMlKemKey); + if (scError != SYMCRYPT_NO_ERROR || + cbKey < cbMlKemKey) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; + } + + cbClassicKey = cbKey - cbMlKemKey; + pbClassicKey = pbKey; + pbMlKemKey = pbClassicKey + cbClassicKey; + + OSSL_PARAM classicParams[2] = { + OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, pbClassicKey, cbClassicKey), + OSSL_PARAM_END}; + + if (keyCtx->classicKeyMgmt->setParams(keyCtx->classicKeyCtx, classicParams) != SCOSSL_SUCCESS) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; + } + } + else + { + pbMlKemKey = pbKey; + cbMlKemKey = cbKey; + } + if (keyCtx->key != NULL) { SymCryptMlKemkeyFree(keyCtx->key); } - if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) + if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->mlkemParams)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); return SCOSSL_FAILURE; } scError = SymCryptMlKemkeySetValue( - pbKey, cbKey, + pbMlKemKey, cbMlKemKey, SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, 0, keyCtx->key); @@ -360,17 +461,18 @@ static const OSSL_PARAM *p_scossl_mlkem_keymgmt_gettable_params(ossl_unused void static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, _Inout_ OSSL_PARAM params[]) { + PBYTE pbMlKemKey = NULL; + SIZE_T cbMlKemKey = 0; + PBYTE pbClassicKey = NULL; + SIZE_T cbClassicKey = 0; PBYTE pbKey = NULL; SIZE_T cbKey = 0; - OSSL_PARAM *paramEncodedKey; - OSSL_PARAM *paramPubKey; - OSSL_PARAM *paramPrivKey; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; - - paramEncodedKey = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); - paramPubKey = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY); - paramPrivKey = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PRIV_KEY); + OSSL_PARAM *paramEncodedKey = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); + OSSL_PARAM *paramPubKey = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY); + OSSL_PARAM *paramPrivKey = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PRIV_KEY); + OSSL_PARAM classic_params[2] = { OSSL_PARAM_END }; if (keyCtx->key == NULL && (paramEncodedKey != NULL || @@ -383,10 +485,10 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY if (paramEncodedKey != NULL || paramPubKey != NULL) { - scError = p_scossl_mlkem_keymgmt_get_key_bytes( + scError = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, - &pbKey, &cbKey); + &pbMlKemKey, &cbMlKemKey); if (scError != SYMCRYPT_NO_ERROR) { @@ -411,7 +513,8 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY if (paramPrivKey != NULL) { - // Reset pbKey in case it was used for encapsulation key + OPENSSL_secure_clear_free(pbMlKemKey, cbMlKemKey); + OPENSSL_secure_clear_free(pbClassicKey, cbClassicKey); OPENSSL_secure_clear_free(pbKey, cbKey); if (keyCtx->format != SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY) @@ -420,7 +523,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY goto cleanup; } - scError = p_scossl_mlkem_keymgmt_get_key_bytes( + scError = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, &pbKey, &cbKey); @@ -431,6 +534,33 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY goto cleanup; } + if (keyCtx->classicKeyCtx != NULL) + { + classic_params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, &pbClassicKey, &cbClassicKey); + if (keyCtx->classicKeyMgmt->getParams(keyCtx->classicKeyCtx, classic_params) != SCOSSL_SUCCESS) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + cbKey = cbMlKemKey + cbClassicKey; + if (pbKey = OPENSSL_malloc(cbKey) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + memcpy(pbKey, pbClassicKey, cbClassicKey); + memcpy(pbKey + cbClassicKey, pbMlKemKey, cbMlKemKey); + } + else + { + pbKey = pbMlKemKey; + cbKey = cbMlKemKey; + pbMlKemKey = NULL; + cbMlKemKey = 0; + } + if (!OSSL_PARAM_set_octet_string(paramPrivKey, pbKey, cbKey)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); @@ -441,6 +571,8 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY ret = SCOSSL_SUCCESS; cleanup: + OPENSSL_secure_clear_free(pbMlKemKey, cbMlKemKey); + OPENSSL_secure_clear_free(pbClassicKey, cbClassicKey); OPENSSL_secure_clear_free(pbKey, cbKey); return ret; @@ -450,8 +582,9 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX { SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; OSSL_PARAM *p; + OSSL_PARAM classicParams[2] = { OSSL_PARAM_END }; - if (keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) + if (keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); return SCOSSL_FAILURE; @@ -466,7 +599,8 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL) { - SIZE_T cbSize; + SIZE_T cbClassicMax; + SIZE_T cbMax; SYMCRYPT_MLKEMKEY_FORMAT format = keyCtx->format; // Default to larger size if key data is not set (and therefore format is unknown) @@ -475,15 +609,25 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; } - scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->params, format, &cbSize); - + scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->mlkemParams, format, &cbMax); if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); return SCOSSL_FAILURE; } - if (!OSSL_PARAM_set_size_t(p, cbSize)) + if (keyCtx->classicKeyCtx != NULL) + { + classicParams[0] = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_MAX_SIZE, &cbClassicMax); + if (keyCtx->classicKeyMgmt->getParams(keyCtx->classicKeyCtx, classicParams) != SCOSSL_SUCCESS) + { + return SCOSSL_FAILURE; + } + + cbMax += cbClassicMax; + } + + if (!OSSL_PARAM_set_size_t(p, cbMax)) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); return SCOSSL_FAILURE; @@ -491,7 +635,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX } if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL && - !OSSL_PARAM_set_utf8_string(p, p_scossl_mlkem_keymgmt_params_to_name(keyCtx->params))) + !OSSL_PARAM_set_utf8_string(p, p_scossl_mlkem_keymgmt_params_to_name(keyCtx->mlkemParams))) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); return SCOSSL_FAILURE; @@ -509,7 +653,7 @@ static BOOL p_scossl_mlkem_keymgmt_has(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int se } if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0 && - keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) + keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) { return FALSE; } @@ -540,7 +684,7 @@ static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx1, _In SCOSSL_STATUS success; if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0 && - keyCtx1->params != keyCtx2->params) + keyCtx1->mlkemParams != keyCtx2->mlkemParams) { goto cleanup; } @@ -561,7 +705,7 @@ static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx1, _In OPENSSL_secure_clear_free(pbKey1, cbKey1); OPENSSL_secure_clear_free(pbKey2, cbKey2); - success = p_scossl_mlkem_keymgmt_get_key_bytes( + success = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx1, SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, &pbKey1, &cbKey1); @@ -570,7 +714,7 @@ static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx1, _In goto cleanup; } - success = p_scossl_mlkem_keymgmt_get_key_bytes( + success = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx2, SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, &pbKey2, &cbKey2); @@ -588,7 +732,7 @@ static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx1, _In if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { - success = p_scossl_mlkem_keymgmt_get_key_bytes( + success = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx1, SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, &pbKey1, &cbKey1); @@ -597,7 +741,7 @@ static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx1, _In goto cleanup; } - success = p_scossl_mlkem_keymgmt_get_key_bytes( + success = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx2, SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, &pbKey2, &cbKey2); @@ -665,7 +809,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx return SCOSSL_FAILURE; } - if ((keyCtx->params = p_scossl_mlkem_keymgmt_params_from_name(name)) == SYMCRYPT_MLKEM_PARAMS_NULL) + if ((keyCtx->mlkemParams = p_scossl_mlkem_keymgmt_params_from_name(name)) == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); return SCOSSL_FAILURE; @@ -709,7 +853,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; } - if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) + if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->mlkemParams)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); return SCOSSL_FAILURE; @@ -749,7 +893,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, i goto cleanup; } - if (keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) + if (keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); goto cleanup; @@ -768,7 +912,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, i goto cleanup; } - mlkemParamsName = p_scossl_mlkem_keymgmt_params_to_name(keyCtx->params); + mlkemParamsName = p_scossl_mlkem_keymgmt_params_to_name(keyCtx->mlkemParams); if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, mlkemParamsName, sizeof(mlkemParamsName))) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); @@ -777,7 +921,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, i if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { - ret = p_scossl_mlkem_keymgmt_get_key_bytes( + ret = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, &pbKey, &cbKey); @@ -805,7 +949,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, i // Reset pbKey in case it was used for encapsulation key export OPENSSL_secure_clear_free(pbKey, cbKey); - ret = p_scossl_mlkem_keymgmt_get_key_bytes( + ret = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx, SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, &pbKey, &cbKey); @@ -860,23 +1004,28 @@ const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[] = { // _Use_decl_annotations_ -SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_bytes(const SCOSSL_MLKEM_KEY_CTX *keyCtx, - SYMCRYPT_MLKEMKEY_FORMAT format, - PBYTE *ppbKey, SIZE_T *pcbKey) +SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX *keyCtx, + SYMCRYPT_MLKEMKEY_FORMAT format, + PBYTE *ppbKey, SIZE_T *pcbKey) { PBYTE pbKey = NULL; SIZE_T cbKey = 0; + PBYTE pbMlKemKey = NULL; + SIZE_T cbMlKemKey = 0; + PBYTE pbClassicKey = NULL; + SIZE_T cbClassicKey = 0; + int classicSelection = (format == SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY ? + OSSL_KEYMGMT_SELECT_PRIVATE_KEY : OSSL_KEYMGMT_SELECT_PUBLIC_KEY); SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; - if (keyCtx->key == NULL || keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) + if (keyCtx->key == NULL || keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); return SCOSSL_FAILURE; } - scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->params, format, &cbKey); - + scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->mlkemParams, format, &cbKey); if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); @@ -891,6 +1040,13 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_bytes(const SCOSSL_MLKEM_KEY_CTX *k goto cleanup; } + // Copy the private key in first if it exists. + if (keyCtx->classicKeyCtx != NULL && + p_scossl_ecc_get_encoded_key(keyCtx->classicKeyCtx, classicSelection, &pbClassicKey, &cbClassicKey) != SCOSSL_SUCCESS) + { + goto cleanup; + } + scError = SymCryptMlKemkeyGetValue(keyCtx->key, pbKey, cbKey, format, 0); if (scError != SYMCRYPT_NO_ERROR) @@ -913,36 +1069,65 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_bytes(const SCOSSL_MLKEM_KEY_CTX *k return SCOSSL_SUCCESS; } +// This function checks if groupName matches a supported MLKEM or MLKEM hybrid group name. +// If a match is found, the appropriate MLKEM parameters and classic group NID are set, +// and the constant group name is returned. _Use_decl_annotations_ -static SYMCRYPT_MLKEM_PARAMS p_scossl_mlkem_keymgmt_params_from_name(const char *name) +static const char* p_scossl_mlkem_keymgmt_params_from_name(const char *groupName, + SYMCRYPT_MLKEM_PARAMS *mlkemParams, + const char **classicGroupName, + SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS **classicKeymgmt) { - if (OPENSSL_strcasecmp(name, SCOSSL_MLKEM_PARAM_NAME_512) == 0) + if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM512) == 0) + { + *mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM512; + *classicGroupName = NULL; + *classicKeymgmt = NULL; + return SCOSSL_SN_MLKEM512; + } + else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM768) == 0) + { + *mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; + *classicGroupName = NULL; + *classicKeymgmt = NULL; + return SCOSSL_SN_MLKEM768; + } + else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM1024) == 0) { - return SYMCRYPT_MLKEM_PARAMS_MLKEM512; + *mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM1024; + *classicGroupName = NULL; + *classicKeymgmt = NULL; + return SCOSSL_SN_MLKEM1024; } - else if (OPENSSL_strcasecmp(name, SCOSSL_MLKEM_PARAM_NAME_768) == 0) + else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_P256_MLKEM768) == 0) { - return SYMCRYPT_MLKEM_PARAMS_MLKEM768; + *mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; + *classicGroupName = SN_X9_62_prime256v1; + *classicKeymgmt = &p_scossl_ecc_classic_keymgmt; + return SCOSSL_SN_P256_MLKEM768; } - else if (OPENSSL_strcasecmp(name, SCOSSL_MLKEM_PARAM_NAME_1024) == 0) + else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_X25519_MLKEM768) == 0) { - return SYMCRYPT_MLKEM_PARAMS_MLKEM1024; + *mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; + *classicGroupName = SN_X25519; + *classicKeymgmt = &p_scossl_x25519_classic_keymgmt; + return SCOSSL_SN_X25519_MLKEM768; } - return SYMCRYPT_MLKEM_PARAMS_NULL; + return NULL; } _Use_decl_annotations_ -static const char *p_scossl_mlkem_keymgmt_params_to_name(const SYMCRYPT_MLKEM_PARAMS params) +static const char *p_scossl_mlkem_keymgmt_get_group_name(const SCOSSL_MLKEM_KEY_CTX keyCtx) { - switch (params) + switch (keyCtx->mlkemParams) { case SYMCRYPT_MLKEM_PARAMS_MLKEM512: - return SCOSSL_MLKEM_PARAM_NAME_512; + return SCOSSL_SN_MLKEM512; case SYMCRYPT_MLKEM_PARAMS_MLKEM768: - return SCOSSL_MLKEM_PARAM_NAME_768; + return SCOSSL_SN_MLKEM768; case SYMCRYPT_MLKEM_PARAMS_MLKEM1024: - return SCOSSL_MLKEM_PARAM_NAME_1024;\ + return SCOSSL_SN_MLKEM1024; default: ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); break; @@ -954,7 +1139,7 @@ static const char *p_scossl_mlkem_keymgmt_params_to_name(const SYMCRYPT_MLKEM_PA _Use_decl_annotations_ static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx) { - switch(keyCtx->params) + switch(keyCtx->mlkemParams) { case SYMCRYPT_MLKEM_PARAMS_MLKEM512: return 128; diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h index ff79cdaf..9b6b6404 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h @@ -15,9 +15,9 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg); -SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_bytes(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, - SYMCRYPT_MLKEMKEY_FORMAT format, - _Out_writes_bytes_(*cbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); +SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, + SYMCRYPT_MLKEMKEY_FORMAT format, + _Out_writes_bytes_(*cbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); #ifdef __cplusplus } diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index 9a0a0353..f6c4f0f5 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -8,6 +8,7 @@ #include "scossl_dh.h" #include "scossl_ecc.h" +#include "scossl_provider.h" #include "p_scossl_bio.h" #include "p_scossl_keysinuse.h" #include "p_scossl_names.h" @@ -365,7 +366,9 @@ static SCOSSL_STATUS p_scossl_register_extended_algorithms() { if (OBJ_create(SCOSSL_OID_MLKEM512, SCOSSL_SN_MLKEM512, SCOSSL_SN_MLKEM512) == NID_undef || OBJ_create(SCOSSL_OID_MLKEM768, SCOSSL_SN_MLKEM768, SCOSSL_SN_MLKEM768) == NID_undef || - OBJ_create(SCOSSL_OID_MLKEM1024, SCOSSL_SN_MLKEM1024, SCOSSL_SN_MLKEM1024) == NID_undef) + OBJ_create(SCOSSL_OID_MLKEM1024, SCOSSL_SN_MLKEM1024, SCOSSL_SN_MLKEM1024) == NID_undef || + OBJ_create(NULL, SCOSSL_SN_P256_MLKEM768, SCOSSL_SN_P256_MLKEM768) == NID_undef || + OBJ_create(NULL, SCOSSL_SN_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768) == NID_undef) { return SCOSSL_FAILURE; } diff --git a/SymCryptProvider/src/p_scossl_ecc.c b/SymCryptProvider/src/p_scossl_ecc.c index 7351c1f9..e0ca6a57 100644 --- a/SymCryptProvider/src/p_scossl_ecc.c +++ b/SymCryptProvider/src/p_scossl_ecc.c @@ -21,6 +21,7 @@ SCOSSL_STATUS p_scossl_ecc_get_encoded_public_key(const SCOSSL_ECC_KEY_CTX *keyC SYMCRYPT_ECPOINT_FORMAT pointFormat; PBYTE pbPublicKey, pbPublicKeyStart; SIZE_T cbPublicKey; + BOOL freePublicKey = FALSE; SYMCRYPT_ERROR scError; SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -45,10 +46,24 @@ SCOSSL_STATUS p_scossl_ecc_get_encoded_public_key(const SCOSSL_ECC_KEY_CTX *keyC cbPublicKey = SymCryptEckeySizeofPublicKey(keyCtx->key, pointFormat) + 1; } - if ((pbPublicKeyStart = OPENSSL_malloc(cbPublicKey)) == NULL) + if (ppbEncodedKey == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; + *pcbEncodedKey = cbPublicKey; + return SCOSSL_SUCCESS; + } + else if (*ppbEncodedKey == NULL) + { + if ((pbPublicKeyStart = OPENSSL_malloc(cbPublicKey)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + freePublicKey = TRUE; + } + else + { + pbPublicKeyStart = *ppbEncodedKey; } pbPublicKey = pbPublicKeyStart; @@ -99,7 +114,11 @@ SCOSSL_STATUS p_scossl_ecc_get_encoded_public_key(const SCOSSL_ECC_KEY_CTX *keyC ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; } - OPENSSL_free(pbPublicKeyStart); + + if (freePublicKey) + { + OPENSSL_free(pbPublicKeyStart); + } pbPublicKeyStart = pbPublicKey; } } @@ -112,7 +131,7 @@ SCOSSL_STATUS p_scossl_ecc_get_encoded_public_key(const SCOSSL_ECC_KEY_CTX *keyC ret = SCOSSL_SUCCESS; cleanup: - if (!ret) + if (!ret && freePublicKey) { OPENSSL_free(pbPublicKeyStart); } @@ -120,6 +139,25 @@ SCOSSL_STATUS p_scossl_ecc_get_encoded_public_key(const SCOSSL_ECC_KEY_CTX *keyC return ret; } +SCOSSL_STATUS p_scossl_ecc_get_private_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, + _Out_writes_bytes_(*pcbPrivateKey) PBYTE *ppbPrivateKey, _Out_ SIZE_T *pcbPrivateKey) +{ + return SCOSSL_FAILURE; +} + +SCOSSL_STATUS p_scossl_ecc_get_encoded_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, + _Out_writes_bytes_(*pcbPrivateKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey) +{ + if (selection == OSSL_KEYMGMT_SELECT_PUBLIC_KEY) + { + return p_scossl_ecc_get_encoded_public_key(keyCtx, ppbKey, pcbKey); + } + else + { + return p_scossl_ecc_get_private_key(keyCtx, ppbKey, pcbKey); + } +} + #ifdef KEYSINUSE_ENABLED _Use_decl_annotations_ void p_scossl_ecc_init_keysinuse(SCOSSL_ECC_KEY_CTX *keyCtx) diff --git a/SymCryptProvider/src/p_scossl_ecc.h b/SymCryptProvider/src/p_scossl_ecc.h index 681cc713..46c559b8 100644 --- a/SymCryptProvider/src/p_scossl_ecc.h +++ b/SymCryptProvider/src/p_scossl_ecc.h @@ -40,6 +40,10 @@ typedef struct { #endif } SCOSSL_ECC_KEY_CTX; +SIZE_T p_scossl_ecc_get_key_size(_In_ const SCOSSL_ECC_KEY_CTX *keyCtx, int selection); +SCOSSL_STATUS p_scossl_ecc_get_encoded_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, + _Out_writes_bytes_(*pcbPrivateKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); + // Helper function for retrieving the properly formatted encoded public key. // The format differs for x25519 keys. Caller is responsible for freeing *ppbEncodedKey. SCOSSL_STATUS p_scossl_ecc_get_encoded_public_key(_In_ const SCOSSL_ECC_KEY_CTX *keyCtx, diff --git a/SymCryptProvider/src/p_scossl_names.h b/SymCryptProvider/src/p_scossl_names.h index 9dec333b..73825553 100644 --- a/SymCryptProvider/src/p_scossl_names.h +++ b/SymCryptProvider/src/p_scossl_names.h @@ -8,19 +8,6 @@ extern "C" { #endif -// -// Extended algorithms not found in default OpenSSL implementation -// - -#define SCOSSL_SN_MLKEM512 "mlkem512" -#define SCOSSL_OID_MLKEM512 "2.16.840.1.101.3.4.4.1" - -#define SCOSSL_SN_MLKEM768 "mlkem768" -#define SCOSSL_OID_MLKEM768 "2.16.840.1.101.3.4.4.2" - -#define SCOSSL_SN_MLKEM1024 "mlkem1024" -#define SCOSSL_OID_MLKEM1024 "2.16.840.1.101.3.4.4.3" - // // Provider algorithm names // From 78edcf2f93a49a41615cb491666b05f00e082708 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Sun, 3 Nov 2024 12:22:44 -0700 Subject: [PATCH 10/21] ML-KEM hyrbid key management --- .../src/decoder/p_scossl_decode_mlkem.c | 14 +- .../src/encoder/p_scossl_encode_common.c | 7 +- .../src/encoder/p_scossl_encode_mlkem.c | 8 +- SymCryptProvider/src/kem/p_scossl_mlkem.c | 4 +- SymCryptProvider/src/kem/p_scossl_mlkem.h | 2 - .../src/keymgmt/p_scossl_ecc_keymgmt.c | 128 +------ .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 339 +++++++++--------- .../src/keymgmt/p_scossl_mlkem_keymgmt.h | 8 +- SymCryptProvider/src/p_scossl_ecc.c | 245 ++++++++++--- SymCryptProvider/src/p_scossl_ecc.h | 13 +- 10 files changed, 417 insertions(+), 351 deletions(-) diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c index 42084295..d1496a96 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c +++ b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c @@ -2,7 +2,7 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // -#include "p_scossl_names.h" +#include "scossl_provider.h" #include "decoder/p_scossl_decode_common.h" #include "keymgmt/p_scossl_mlkem_keymgmt.h" @@ -76,16 +76,16 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_PrivateKeyInfo_to_mlkem(_In_ BIO *bio) goto cleanup; } - keyCtx->params = p_scossl_decode_mlkem_get_params(OBJ_obj2nid(alg->algorithm)); + keyCtx->mlkemParams = p_scossl_decode_mlkem_get_params(OBJ_obj2nid(alg->algorithm)); keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; - if (keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) + if (keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); goto cleanup; } - if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) + if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->mlkemParams)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; @@ -145,16 +145,16 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_SubjectPublicKeyInfo_to_mlkem(_In_ BIO *bi goto cleanup; } - keyCtx->params = p_scossl_decode_mlkem_get_params(OBJ_obj2nid(subjPubKeyInfo->algorithm->algorithm)); + keyCtx->mlkemParams = p_scossl_decode_mlkem_get_params(OBJ_obj2nid(subjPubKeyInfo->algorithm->algorithm)); keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; - if (keyCtx->params == SYMCRYPT_MLKEM_PARAMS_NULL) + if (keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); goto cleanup; } - if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->params)) == NULL) + if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->mlkemParams)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_common.c b/SymCryptProvider/src/encoder/p_scossl_encode_common.c index 7809cf9f..79c57720 100644 --- a/SymCryptProvider/src/encoder/p_scossl_encode_common.c +++ b/SymCryptProvider/src/encoder/p_scossl_encode_common.c @@ -116,12 +116,12 @@ SCOSSL_STATUS p_scossl_encode(SCOSSL_ENCODE_CTX *ctx, OSSL_CORE_BIO *out, OSSL_PASSPHRASE_CALLBACK *passphraseCb, void *passphraseCbArgs) { BIO *bio = NULL; - SCOSSL_STATUS ret; + SCOSSL_STATUS ret = SCOSSL_FAILURE; if (keyCtx == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); - return SCOSSL_FAILURE; + goto cleanup; } if (ctx->encodeInternal == NULL || @@ -129,7 +129,7 @@ SCOSSL_STATUS p_scossl_encode(SCOSSL_ENCODE_CTX *ctx, OSSL_CORE_BIO *out, (ctx->outFormat != SCOSSL_ENCODE_TEXT && ((selection & ctx->selection) == 0))) { ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); - return SCOSSL_FAILURE; + goto cleanup; } if ((bio = p_scossl_bio_new_from_core_bio(ctx->provctx, out)) != NULL) @@ -142,6 +142,7 @@ SCOSSL_STATUS p_scossl_encode(SCOSSL_ENCODE_CTX *ctx, OSSL_CORE_BIO *out, ctx->outFormat == SCOSSL_ENCODE_PEM); } +cleanup: BIO_free(bio); return ret; diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c index b015b4ea..00bc51d7 100644 --- a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c +++ b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c @@ -2,7 +2,7 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // -#include "p_scossl_names.h" +#include "scossl_provider.h" #include "encoder/p_scossl_encode_common.h" #include "keymgmt/p_scossl_mlkem_keymgmt.h" @@ -37,7 +37,7 @@ static ASN1_OBJECT *p_scossl_encode_get_mlkem_oid(_In_ const SCOSSL_MLKEM_KEY_CT { int nid = NID_undef; - switch (keyCtx->params) + switch (keyCtx->mlkemParams) { case SYMCRYPT_MLKEM_PARAMS_MLKEM512: nid = OBJ_sn2nid(SCOSSL_SN_MLKEM512); @@ -331,9 +331,9 @@ static SCOSSL_STATUS p_scossl_mlkem_to_text(ossl_unused SCOSSL_ENCODE_CTX *ctx, BOOL printPrivateSeed = FALSE; BOOL printDecapsulationKey = FALSE; BOOL printEncapsulationKey = FALSE; - const char *paramName = p_scossl_encode_mlkem_params_to_name(keyCtx->params); + const char *paramName = p_scossl_encode_mlkem_params_to_name(keyCtx->mlkemParams); PBYTE pbKey = NULL; - SIZE_T cbKey; + SIZE_T cbKey = 0; SCOSSL_STATUS ret = SCOSSL_FAILURE; if (keyCtx->key == NULL || diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.c b/SymCryptProvider/src/kem/p_scossl_mlkem.c index f8db80eb..ebf822a0 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.c +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.c @@ -97,7 +97,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, return SCOSSL_FAILURE; } - scError = SymCryptMlKemSizeofCiphertextFromParams(ctx->keyCtx->params, &cbCipherText); + scError = SymCryptMlKemSizeofCiphertextFromParams(ctx->keyCtx->mlkemParams, &cbCipherText); if (scError != SYMCRYPT_NO_ERROR) { @@ -162,7 +162,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, return SCOSSL_FAILURE; } - scError = SymCryptMlKemSizeofCiphertextFromParams(ctx->keyCtx->params, &cbCipherText); + scError = SymCryptMlKemSizeofCiphertextFromParams(ctx->keyCtx->mlkemParams, &cbCipherText); if (scError != SYMCRYPT_NO_ERROR) { diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.h b/SymCryptProvider/src/kem/p_scossl_mlkem.h index 3154dff2..4a2f546e 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.h +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.h @@ -10,7 +10,6 @@ extern "C" { #endif typedef struct { - OSSL_FUNC_keymgmt_gen_set_params_fn *setParams; OSSL_FUNC_keymgmt_gen_cleanup_fn *genCleanup; OSSL_FUNC_keymgmt_gen_init_fn *genInit; OSSL_FUNC_keymgmt_gen_set_template_fn *setTemplate; @@ -36,7 +35,6 @@ typedef struct { OSSL_FUNC_keyexch_derive_fn *derive; } SCOSSL_MLKEM_CLASSIC_KEYEXCH_FNS; - typedef struct { const char *groupName; PSYMCRYPT_MLKEMKEY key; diff --git a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c index 938a197e..0ea5f31a 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c @@ -79,8 +79,6 @@ static const OSSL_ITEM p_scossl_ecc_keymgmt_conversion_formats[] = { {POINT_CONVERSION_UNCOMPRESSED, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED}, {POINT_CONVERSION_HYBRID, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID}}; -static SCOSSL_STATUS p_scossl_ecc_keymgmt_get_private_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, - _Out_writes_bytes_(*pcbPrivateKey) PBYTE *ppbPrivateKey, _Out_ SIZE_T *pcbPrivateKey); static SCOSSL_STATUS p_scossl_ecc_keymgmt_get_private_key_bn(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, _Out_ BIGNUM **pbnPrivateKey, _Out_opt_ SIZE_T *pcbPrivateKey); @@ -590,7 +588,7 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_get_params(_In_ SCOSSL_ECC_KEY_CTX *ke if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) { SIZE_T cbEncodedKey; - if (!p_scossl_ecc_get_encoded_public_key(keyCtx, &pbEncodedKey, &cbEncodedKey) || + if (!p_scossl_ecc_get_encoded_key(keyCtx, OSSL_KEYMGMT_SELECT_PRIVATE_KEY, &pbEncodedKey, &cbEncodedKey) || !OSSL_PARAM_set_octet_string(p, pbEncodedKey, cbEncodedKey)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); @@ -620,7 +618,7 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_get_params(_In_ SCOSSL_ECC_KEY_CTX *ke if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY)) != NULL) { SIZE_T cbEncodedKey; - if (!p_scossl_ecc_get_encoded_public_key(keyCtx, &pbEncodedKey, &cbEncodedKey) || + if (!p_scossl_ecc_get_encoded_key(keyCtx, OSSL_KEYMGMT_SELECT_PRIVATE_KEY, &pbEncodedKey, &cbEncodedKey) || !OSSL_PARAM_set_octet_string(p, pbEncodedKey, cbEncodedKey)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); @@ -634,7 +632,7 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_get_params(_In_ SCOSSL_ECC_KEY_CTX *ke { if (keyCtx->isX25519) { - if (!p_scossl_ecc_keymgmt_get_private_key(keyCtx, &pbPrivateKey, &cbPrivateKey) || + if (!p_scossl_ecc_get_encoded_key(keyCtx, OSSL_KEYMGMT_SELECT_KEYPAIR, &pbPrivateKey, &cbPrivateKey) || !OSSL_PARAM_set_octet_string(p, pbPrivateKey, cbPrivateKey)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); @@ -1032,15 +1030,14 @@ static const OSSL_PARAM *p_scossl_ecc_keymgmt_impexp_types(int selection) static SCOSSL_STATUS p_scossl_ecc_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]) { - SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; EC_GROUP *ecGroup = NULL; PCSYMCRYPT_ECURVE pCurve; + PCBYTE pbEncodedPublicKey = NULL; + SIZE_T cbEncodedPublicKey = 0; PBYTE pbPrivateKey = NULL; SIZE_T cbPrivateKey = 0; BIGNUM *bnPrivateKey = NULL; - PBYTE pbPublicKey = NULL; - SIZE_T cbPublicKey = 0; BN_CTX *bnCtx = NULL; EC_POINT *ecPoint = NULL; const OSSL_PARAM *p; @@ -1109,49 +1106,13 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *key // Keypair if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { - if (keyCtx->key != NULL) - { - SymCryptEckeyFree(keyCtx->key); - } - -#ifdef KEYSINUSE_ENABLED - // Reset keysinuse in case new key material is overwriting existing - p_scossl_ecc_reset_keysinuse(keyCtx); -#endif - - if ((keyCtx->key = SymCryptEckeyAllocate(keyCtx->curve)) == NULL) + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY)) != NULL && + !OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbEncodedPublicKey, &cbEncodedPublicKey)) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); goto cleanup; } - if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY)) != NULL) - { - PCBYTE encodedPoint; - SIZE_T encodedLen; - if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&encodedPoint, &encodedLen)) - { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - goto cleanup; - } - - cbPublicKey = SymCryptEckeySizeofPublicKey(keyCtx->key, SYMCRYPT_ECPOINT_FORMAT_XY); - if (((ecPoint = EC_POINT_new(ecGroup)) == NULL) || - ((bnCtx = BN_CTX_new_ex(keyCtx->libctx)) == NULL) || - ((pbPublicKey = OPENSSL_malloc(cbPublicKey)) == NULL)) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - if (!EC_POINT_oct2point(ecGroup, ecPoint, encodedPoint, encodedLen, bnCtx) || - !scossl_ec_point_to_pubkey(ecPoint, ecGroup, bnCtx, pbPublicKey, cbPublicKey)) - { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - goto cleanup; - } - } - if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY)) != NULL) { if ((bnPrivateKey = BN_secure_new()) == NULL) @@ -1181,20 +1142,16 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *key } } - scError = SymCryptEckeySetValue( - pbPrivateKey, cbPrivateKey, - pbPublicKey, cbPublicKey, - SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, - SYMCRYPT_ECPOINT_FORMAT_XY, - SYMCRYPT_FLAG_ECKEY_ECDH, - keyCtx->key); - if (scError != SYMCRYPT_NO_ERROR) + ret = p_scossl_ecc_set_encoded_key(keyCtx, selection, + pbEncodedPublicKey, cbEncodedPublicKey, + pbPrivateKey, cbPrivateKey); + + if (ret != SCOSSL_SUCCESS) { SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeySetValue failed", scError); goto cleanup; } - - keyCtx->initialized = TRUE; + #ifdef KEYSINUSE_ENABLED keyCtx->isImported = TRUE; #endif @@ -1208,7 +1165,6 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *key } EC_GROUP_free(ecGroup); BN_clear_free(bnPrivateKey); - OPENSSL_free(pbPublicKey); EC_POINT_free(ecPoint); BN_CTX_free(bnCtx); @@ -1263,7 +1219,7 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_export(_In_ SCOSSL_ECC_KEY_CTX *keyCtx if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { - if (!p_scossl_ecc_get_encoded_public_key(keyCtx, &pbPublicKey, &cbPublicKey) || + if (!p_scossl_ecc_get_encoded_key(keyCtx, OSSL_KEYMGMT_SELECT_PRIVATE_KEY, &pbPublicKey, &cbPublicKey) || !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, pbPublicKey, cbPublicKey)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); @@ -1551,58 +1507,6 @@ const OSSL_DISPATCH p_scossl_x25519_keymgmt_functions[] = { // Helpers // -_Use_decl_annotations_ -static SCOSSL_STATUS p_scossl_ecc_keymgmt_get_private_key(SCOSSL_ECC_KEY_CTX *keyCtx, - PBYTE *ppbPrivateKey, SIZE_T *pcbPrivateKey) -{ - PBYTE pbPrivateKey = NULL; - SIZE_T cbPrivateKey = 0; - SYMCRYPT_NUMBER_FORMAT numFormat = keyCtx->isX25519 ? SYMCRYPT_NUMBER_FORMAT_LSB_FIRST : SYMCRYPT_NUMBER_FORMAT_MSB_FIRST; - SYMCRYPT_ECPOINT_FORMAT pointFormat = keyCtx->isX25519 ? SYMCRYPT_ECPOINT_FORMAT_X : SYMCRYPT_ECPOINT_FORMAT_XY; - SYMCRYPT_ERROR scError; - SCOSSL_STATUS ret = SCOSSL_FAILURE; - - cbPrivateKey = SymCryptEckeySizeofPrivateKey(keyCtx->key); - if ((pbPrivateKey = OPENSSL_secure_malloc(cbPrivateKey)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - scError = SymCryptEckeyGetValue( - keyCtx->key, - pbPrivateKey, cbPrivateKey, - NULL, 0, - numFormat, - pointFormat, - 0); - - if (scError != SYMCRYPT_NO_ERROR) - { - SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeyGetValue failed", scError); - goto cleanup; - } - - if (keyCtx->isX25519) - { - pbPrivateKey[0] = (keyCtx->modifiedPrivateBits & 0x07) | (pbPrivateKey[0] & 0xf8); - pbPrivateKey[cbPrivateKey-1] = (keyCtx->modifiedPrivateBits & 0xc0) | (pbPrivateKey[cbPrivateKey-1] & 0x3f); - } - - *ppbPrivateKey = pbPrivateKey; - *pcbPrivateKey = cbPrivateKey; - - ret = SCOSSL_SUCCESS; - -cleanup: - if (!ret) - { - OPENSSL_secure_clear_free(pbPrivateKey, cbPrivateKey); - } - - return ret; -} - // General ECC case exports private key as a BIGNUM, while x25519 exports as an octet string _Use_decl_annotations_ static SCOSSL_STATUS p_scossl_ecc_keymgmt_get_private_key_bn(SCOSSL_ECC_KEY_CTX *keyCtx, @@ -1613,7 +1517,7 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_get_private_key_bn(SCOSSL_ECC_KEY_CTX BIGNUM *bnPrivateKey = NULL; SCOSSL_STATUS ret = SCOSSL_FAILURE; - if (!p_scossl_ecc_keymgmt_get_private_key(keyCtx, &pbPrivateKey, &cbPrivateKey)) + if (!p_scossl_ecc_get_encoded_key(keyCtx, OSSL_KEYMGMT_SELECT_PRIVATE_KEY, &pbPrivateKey, &cbPrivateKey)) { goto cleanup; } diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index f4e20b0a..beeaa1d4 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -76,7 +76,6 @@ static const char *p_scossl_mlkem_keymgmt_params_from_name(_In_ const char *grou _Out_ SYMCRYPT_MLKEM_PARAMS *mlkemParams, _Out_ const char **classicGroupName, _Out_ SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS **classicKeymgmt); -static const char *p_scossl_mlkem_keymgmt_get_group_name(_In_ const SCOSSL_MLKEM_KEY_CTX keyCtx); static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx); SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(ossl_unused void *provCtx) @@ -106,21 +105,17 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS { PBYTE pbKey = NULL; SIZE_T cbKey = 0; - SYMCRYPT_MLKEMKEY_FORMAT format; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; - SCOSSL_MLKEM_KEY_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEY_CTX)); + SCOSSL_MLKEM_KEY_CTX *copyCtx = OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_KEY_CTX)); if (copyCtx != NULL) { if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { + copyCtx->groupName = keyCtx->groupName; copyCtx->mlkemParams = keyCtx->mlkemParams; } - else - { - copyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_NULL; - } if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 && keyCtx->key != NULL) { @@ -130,49 +125,35 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS goto cleanup; } - if ((copyCtx->key = SymCryptMlKemkeyAllocate(copyCtx->mlkemParams)) == NULL) + scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->mlkemParams, keyCtx->format, &cbKey); + if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); goto cleanup; } - if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) - { - format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; - } - else + if ((copyCtx->key = SymCryptMlKemkeyAllocate(copyCtx->mlkemParams)) == NULL || + (pbKey = OPENSSL_secure_malloc(cbKey)) == NULL) { - format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; } - ret = p_scossl_mlkem_keymgmt_get_encoded_key( - keyCtx, - format, - &pbKey, &cbKey); - - if (ret != SCOSSL_SUCCESS) + scError = SymCryptMlKemkeyGetValue(keyCtx->key, pbKey, cbKey, keyCtx->format, 0); + if (scError != SYMCRYPT_NO_ERROR) { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); goto cleanup; } - scError = SymCryptMlKemkeySetValue( - pbKey, cbKey, - format, - 0, - copyCtx->key); - + scError = SymCryptMlKemkeySetValue(pbKey, cbKey, keyCtx->format, 0, copyCtx->key); if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); goto cleanup; } - copyCtx->format = format; - } - else - { - copyCtx->key = NULL; - copyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_NULL; + copyCtx->format = keyCtx->format; } if (keyCtx->classicKeyCtx != NULL) @@ -205,7 +186,6 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEYGE const OSSL_PARAM *p; if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL) { - int classicGroupNid; const char *name; if (!OSSL_PARAM_get_utf8_string_ptr(p, &name)) @@ -215,7 +195,6 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEYGE } genCtx->groupName = p_scossl_mlkem_keymgmt_params_from_name(name, &genCtx->mlkemParams, &genCtx->classicGroupName, &genCtx->classicKeyMgmt); - if (genCtx->groupName == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); @@ -226,7 +205,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEYGE return SCOSSL_SUCCESS;; } -static const OSSL_PARAM *p_scossl_mlkem_keygen_settable_params(_In_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, ossl_unused void *provCtx) +static const OSSL_PARAM *p_scossl_mlkem_keygen_settable_params(ossl_unused void *genCtx, ossl_unused void *provCtx) { return p_scossl_mlkem_keygen_settable_param_types; } @@ -295,8 +274,6 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEY static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ OSSL_CALLBACK *cb, _In_ void *cbarg) { - EVP_PKEY_CTX *classicGenCtx; - int pkeyId; BOOL success = FALSE; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_MLKEM_KEY_CTX *keyCtx; @@ -318,7 +295,7 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX if (genCtx->classicGroupName != NULL) { OSSL_PARAM classicParams[2] = { - OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, genCtx->classicGroupName, 0), + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, (char *)genCtx->classicGroupName, strlen(genCtx->classicGroupName)), OSSL_PARAM_END}; genCtx->classicKeygenCtx = genCtx->classicKeyMgmt->genInit(genCtx->provCtx, 0, classicParams); @@ -375,17 +352,6 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_params(_In_ SCOSSL_MLKEM_KEY_CTX { PCBYTE pbKey; SIZE_T cbKey; - PCBYTE pbMlKemKey; - SIZE_T cbMlKemKey; - PCBYTE pbClassicKey; - SIZE_T cbClassicKey; - SYMCRYPT_ERROR scError; - - if (keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) - { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); - return SCOSSL_FAILURE; - } if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbKey, &cbKey)) { @@ -393,62 +359,10 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_params(_In_ SCOSSL_MLKEM_KEY_CTX return SCOSSL_FAILURE; } - if (keyCtx->classicKeyCtx != NULL) - { - scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->mlkemParams, SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, &cbMlKemKey); - if (scError != SYMCRYPT_NO_ERROR || - cbKey < cbMlKemKey) - { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - return SCOSSL_FAILURE; - } - - cbClassicKey = cbKey - cbMlKemKey; - pbClassicKey = pbKey; - pbMlKemKey = pbClassicKey + cbClassicKey; - - OSSL_PARAM classicParams[2] = { - OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, pbClassicKey, cbClassicKey), - OSSL_PARAM_END}; - - if (keyCtx->classicKeyMgmt->setParams(keyCtx->classicKeyCtx, classicParams) != SCOSSL_SUCCESS) - { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - return SCOSSL_FAILURE; - } - } - else - { - pbMlKemKey = pbKey; - cbMlKemKey = cbKey; - } - - if (keyCtx->key != NULL) - { - SymCryptMlKemkeyFree(keyCtx->key); - } - - if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->mlkemParams)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return SCOSSL_FAILURE; - } - - scError = SymCryptMlKemkeySetValue( - pbMlKemKey, cbMlKemKey, - SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, - 0, - keyCtx->key); - - if (scError != SYMCRYPT_NO_ERROR) + if (p_scossl_mlkem_keymgmt_set_encoded_key(keyCtx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, pbKey, cbKey) != SCOSSL_SUCCESS) { - SymCryptMlKemkeyFree(keyCtx->key); - keyCtx->key = NULL; - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); return SCOSSL_FAILURE; } - - keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; } return SCOSSL_SUCCESS; @@ -487,7 +401,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY { scError = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx, - SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, + OSSL_KEYMGMT_SELECT_PUBLIC_KEY, &pbMlKemKey, &cbMlKemKey); if (scError != SYMCRYPT_NO_ERROR) @@ -525,7 +439,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY scError = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx, - SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, + OSSL_KEYMGMT_SELECT_PRIVATE_KEY, &pbKey, &cbKey); if (scError != SYMCRYPT_NO_ERROR) @@ -536,7 +450,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY if (keyCtx->classicKeyCtx != NULL) { - classic_params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, &pbClassicKey, &cbClassicKey); + classic_params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, &pbClassicKey, cbClassicKey); if (keyCtx->classicKeyMgmt->getParams(keyCtx->classicKeyCtx, classic_params) != SCOSSL_SUCCESS) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); @@ -544,7 +458,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY } cbKey = cbMlKemKey + cbClassicKey; - if (pbKey = OPENSSL_malloc(cbKey) == NULL) + if ((pbKey = OPENSSL_malloc(cbKey)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; @@ -635,7 +549,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX } if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL && - !OSSL_PARAM_set_utf8_string(p, p_scossl_mlkem_keymgmt_params_to_name(keyCtx->mlkemParams))) + !OSSL_PARAM_set_utf8_string(p, keyCtx->groupName != NULL ? keyCtx->groupName : "")) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); return SCOSSL_FAILURE; @@ -644,7 +558,6 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX return p_scossl_mlkem_keymgmt_get_key_params(keyCtx, params); } - static BOOL p_scossl_mlkem_keymgmt_has(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection) { if (keyCtx == NULL) @@ -707,7 +620,7 @@ static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx1, _In success = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx1, - SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, + OSSL_KEYMGMT_SELECT_PRIVATE_KEY, &pbKey1, &cbKey1); if (!success) { @@ -716,7 +629,7 @@ static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx1, _In success = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx2, - SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, + OSSL_KEYMGMT_SELECT_PRIVATE_KEY, &pbKey2, &cbKey2); if (!success) { @@ -734,7 +647,7 @@ static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx1, _In { success = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx1, - SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, + OSSL_KEYMGMT_SELECT_PUBLIC_KEY, &pbKey1, &cbKey1); if (!success) { @@ -743,7 +656,7 @@ static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx1, _In success = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx2, - SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, + OSSL_KEYMGMT_SELECT_PUBLIC_KEY, &pbKey2, &cbKey2); if (!success) { @@ -791,7 +704,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx const OSSL_PARAM *p; PCBYTE pbKey; SIZE_T cbKey; - SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + const char *classicGroupName = NULL; // Domain parameters are required for import if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0) @@ -801,19 +714,33 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL) { - const char *name; + const char *groupName; - if (!OSSL_PARAM_get_utf8_string_ptr(p, &name)) + if (!OSSL_PARAM_get_utf8_string_ptr(p, &groupName)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return SCOSSL_FAILURE; } - if ((keyCtx->mlkemParams = p_scossl_mlkem_keymgmt_params_from_name(name)) == SYMCRYPT_MLKEM_PARAMS_NULL) + keyCtx->groupName = p_scossl_mlkem_keymgmt_params_from_name(groupName, &keyCtx->mlkemParams, &classicGroupName, &keyCtx->classicKeyMgmt); + + if (keyCtx->groupName == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); return SCOSSL_FAILURE; } + + if (classicGroupName != NULL) + { + OSSL_PARAM classicParams[2] = { + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, (char *)classicGroupName, strlen(classicGroupName)), + OSSL_PARAM_END}; + + if (keyCtx->classicKeyMgmt->import(keyCtx->classicKeyCtx, selection, classicParams) != SCOSSL_SUCCESS) + { + return SCOSSL_FAILURE; + } + } } if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) @@ -832,8 +759,6 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return SCOSSL_FAILURE; } - - keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; } else { @@ -849,27 +774,10 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return SCOSSL_FAILURE; } - - keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; - } - - if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->mlkemParams)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return SCOSSL_FAILURE; } - scError = SymCryptMlKemkeySetValue( - pbKey, cbKey, - keyCtx->format, - 0, - keyCtx->key); - - if (scError != SYMCRYPT_NO_ERROR) + if (p_scossl_mlkem_keymgmt_set_encoded_key(keyCtx, selection, pbKey, cbKey) != SCOSSL_SUCCESS) { - SymCryptMlKemkeyFree(keyCtx->key); - keyCtx->key = NULL; - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); return SCOSSL_FAILURE; } } @@ -912,8 +820,8 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, i goto cleanup; } - mlkemParamsName = p_scossl_mlkem_keymgmt_params_to_name(keyCtx->mlkemParams); - if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, mlkemParamsName, sizeof(mlkemParamsName))) + mlkemParamsName = keyCtx->groupName != NULL ? keyCtx->groupName : ""; + if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, mlkemParamsName, strlen(mlkemParamsName))) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); goto cleanup; @@ -923,7 +831,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, i { ret = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx, - SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY, + OSSL_KEYMGMT_SELECT_PUBLIC_KEY, &pbKey, &cbKey); if (ret != SCOSSL_SUCCESS) @@ -931,7 +839,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, i goto cleanup; } - if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PRIV_KEY, pbKey, cbKey)) + if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, pbKey, cbKey)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); goto cleanup; @@ -951,7 +859,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, i ret = p_scossl_mlkem_keymgmt_get_encoded_key( keyCtx, - SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY, + OSSL_KEYMGMT_SELECT_PRIVATE_KEY, &pbKey, &cbKey); if (ret != SCOSSL_SUCCESS) @@ -1002,10 +910,8 @@ const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[] = { // // Helper functions // - _Use_decl_annotations_ -SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX *keyCtx, - SYMCRYPT_MLKEMKEY_FORMAT format, +SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, PBYTE *ppbKey, SIZE_T *pcbKey) { PBYTE pbKey = NULL; @@ -1014,8 +920,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX SIZE_T cbMlKemKey = 0; PBYTE pbClassicKey = NULL; SIZE_T cbClassicKey = 0; - int classicSelection = (format == SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY ? - OSSL_KEYMGMT_SELECT_PRIVATE_KEY : OSSL_KEYMGMT_SELECT_PUBLIC_KEY); + SYMCRYPT_MLKEMKEY_FORMAT format; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -1025,13 +930,37 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX return SCOSSL_FAILURE; } - scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->mlkemParams, format, &cbKey); + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + { + if (keyCtx->format == SYMCRYPT_MLKEMKEY_FORMAT_NULL || + keyCtx->format == SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY); + return SCOSSL_FAILURE; + } + + format = keyCtx->format; + } + else + { + format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; + } + + scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->mlkemParams, format, &cbMlKemKey); if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); goto cleanup; } + if (keyCtx->classicKeyCtx != NULL && + (cbClassicKey = p_scossl_ecc_get_encoded_key_size(keyCtx->classicKeyCtx, selection)) == 0) + { + goto cleanup; + } + + cbKey = cbMlKemKey + cbClassicKey; + // Always using OPENSSL_secure_malloc so caller doesn't have to worry about // calling separate free functions for encapsulation and decapsulation keys if ((pbKey = OPENSSL_secure_malloc(cbKey)) == NULL) @@ -1040,15 +969,16 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX goto cleanup; } - // Copy the private key in first if it exists. + pbClassicKey = pbKey; + pbMlKemKey = pbKey + cbClassicKey; + if (keyCtx->classicKeyCtx != NULL && - p_scossl_ecc_get_encoded_key(keyCtx->classicKeyCtx, classicSelection, &pbClassicKey, &cbClassicKey) != SCOSSL_SUCCESS) + p_scossl_ecc_get_encoded_key(keyCtx->classicKeyCtx, selection, &pbClassicKey, &cbClassicKey) != SCOSSL_SUCCESS) { goto cleanup; } - scError = SymCryptMlKemkeyGetValue(keyCtx->key, pbKey, cbKey, format, 0); - + scError = SymCryptMlKemkeyGetValue(keyCtx->key, pbMlKemKey, cbMlKemKey, format, 0); if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); @@ -1069,6 +999,92 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX return SCOSSL_SUCCESS; } +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, + PCBYTE pbKey, SIZE_T cbKey) +{ + PCBYTE pbMlKemKey = NULL; + SIZE_T cbMlKemKey = 0; + PCBYTE pbClassicKey = NULL; + SIZE_T cbClassicKey = 0; + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + SCOSSL_STATUS ret = SCOSSL_FAILURE; + + if (keyCtx->key == NULL || keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + goto cleanup; + } + + if (keyCtx->classicKeyCtx != NULL && + (cbClassicKey = p_scossl_ecc_get_encoded_key_size(keyCtx->classicKeyCtx, selection)) == 0) + { + goto cleanup; + } + + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + { + keyCtx->format = cbKey - cbClassicKey == 64 ? SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED : SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; + } + else + { + keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; + } + + scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->mlkemParams, keyCtx->format, &cbMlKemKey); + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + if (cbKey != cbClassicKey + cbMlKemKey) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + goto cleanup; + } + + pbClassicKey = pbKey; + pbMlKemKey = pbKey + cbClassicKey; + + if (keyCtx->classicKeyCtx != NULL) + { + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + { + ret = p_scossl_ecc_set_encoded_key(keyCtx->classicKeyCtx, selection, NULL, 0, pbClassicKey, cbClassicKey); + } + else + { + ret = p_scossl_ecc_set_encoded_key(keyCtx->classicKeyCtx, selection, pbClassicKey, cbClassicKey, NULL, 0); + } + + if (ret != SCOSSL_SUCCESS) + { + goto cleanup; + } + } + + scError = SymCryptMlKemkeySetValue(pbMlKemKey, cbMlKemKey, keyCtx->format, 0, keyCtx->key); + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + ret = SCOSSL_SUCCESS; + +cleanup: + + if (ret != SCOSSL_SUCCESS) + { + SymCryptMlKemkeyFree(keyCtx->key); + keyCtx->key = NULL; + keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_NULL; + } + + return ret; +} + // This function checks if groupName matches a supported MLKEM or MLKEM hybrid group name. // If a match is found, the appropriate MLKEM parameters and classic group NID are set, // and the constant group name is returned. @@ -1117,25 +1133,6 @@ static const char* p_scossl_mlkem_keymgmt_params_from_name(const char *groupName return NULL; } -_Use_decl_annotations_ -static const char *p_scossl_mlkem_keymgmt_get_group_name(const SCOSSL_MLKEM_KEY_CTX keyCtx) -{ - switch (keyCtx->mlkemParams) - { - case SYMCRYPT_MLKEM_PARAMS_MLKEM512: - return SCOSSL_SN_MLKEM512; - case SYMCRYPT_MLKEM_PARAMS_MLKEM768: - return SCOSSL_SN_MLKEM768; - case SYMCRYPT_MLKEM_PARAMS_MLKEM1024: - return SCOSSL_SN_MLKEM1024; - default: - ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); - break; - } - - return ""; -} - _Use_decl_annotations_ static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx) { diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h index 9b6b6404..67d6f771 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h @@ -15,9 +15,11 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg); -SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, - SYMCRYPT_MLKEMKEY_FORMAT format, - _Out_writes_bytes_(*cbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); +SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, + _Out_writes_bytes_(*pcbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); +SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, + _In_reads_bytes_(cbKey) PCBYTE pbKey, SIZE_T cbKey); + #ifdef __cplusplus } diff --git a/SymCryptProvider/src/p_scossl_ecc.c b/SymCryptProvider/src/p_scossl_ecc.c index e0ca6a57..d46bb318 100644 --- a/SymCryptProvider/src/p_scossl_ecc.c +++ b/SymCryptProvider/src/p_scossl_ecc.c @@ -4,24 +4,50 @@ #include +#include "scossl_ecc.h" #include "p_scossl_ecc.h" #ifdef __cplusplus extern "C" { #endif +_Use_decl_annotations_ +SIZE_T p_scossl_ecc_get_encoded_key_size(SCOSSL_ECC_KEY_CTX *keyCtx, int selection) +{ + SYMCRYPT_ECPOINT_FORMAT pointFormat; + + if (!keyCtx->initialized) + { + return 0; + } + + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + { + return SymCryptEckeySizeofPrivateKey(keyCtx->key); + } + else if (keyCtx->isX25519) + { + return SymCryptEckeySizeofPublicKey(keyCtx->key, SYMCRYPT_ECPOINT_FORMAT_X); + } + + pointFormat = keyCtx->conversionFormat == POINT_CONVERSION_COMPRESSED ? SYMCRYPT_ECPOINT_FORMAT_X : SYMCRYPT_ECPOINT_FORMAT_XY; + + return SymCryptEckeySizeofPublicKey(keyCtx->key, pointFormat) + 1; +} + // Gets the public key as an encoded octet string // For x25519, the encoding rules defined in RFC 7748 are used // Otherwise, the encoding rules defined in SECG SEC 1 are used, according to the conversion format of keyCtx _Use_decl_annotations_ SCOSSL_STATUS p_scossl_ecc_get_encoded_public_key(const SCOSSL_ECC_KEY_CTX *keyCtx, - PBYTE *ppbEncodedKey, SIZE_T *pcbEncodedKey) + PBYTE *ppbPublicKey, SIZE_T *pcbPublicKey) { SYMCRYPT_NUMBER_FORMAT numFormat; SYMCRYPT_ECPOINT_FORMAT pointFormat; - PBYTE pbPublicKey, pbPublicKeyStart; + PBYTE pbPublicKeyStart = NULL; + PBYTE pbPublicKey = NULL; SIZE_T cbPublicKey; - BOOL freePublicKey = FALSE; + BOOL allocatedKey = FALSE; SYMCRYPT_ERROR scError; SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -40,18 +66,13 @@ SCOSSL_STATUS p_scossl_ecc_get_encoded_public_key(const SCOSSL_ECC_KEY_CTX *keyC else { numFormat = SYMCRYPT_NUMBER_FORMAT_MSB_FIRST; - pointFormat = SYMCRYPT_ECPOINT_FORMAT_XY; + pointFormat = keyCtx->conversionFormat == POINT_CONVERSION_COMPRESSED ? SYMCRYPT_ECPOINT_FORMAT_X : SYMCRYPT_ECPOINT_FORMAT_XY; // Allocate one extra byte for point compression type cbPublicKey = SymCryptEckeySizeofPublicKey(keyCtx->key, pointFormat) + 1; } - if (ppbEncodedKey == NULL) - { - *pcbEncodedKey = cbPublicKey; - return SCOSSL_SUCCESS; - } - else if (*ppbEncodedKey == NULL) + if (*ppbPublicKey == NULL) { if ((pbPublicKeyStart = OPENSSL_malloc(cbPublicKey)) == NULL) { @@ -59,11 +80,16 @@ SCOSSL_STATUS p_scossl_ecc_get_encoded_public_key(const SCOSSL_ECC_KEY_CTX *keyC goto cleanup; } - freePublicKey = TRUE; + allocatedKey = TRUE; + } + else if (*pcbPublicKey >= cbPublicKey) + { + pbPublicKeyStart = *ppbPublicKey; } else { - pbPublicKeyStart = *ppbEncodedKey; + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + goto cleanup; } pbPublicKey = pbPublicKeyStart; @@ -84,7 +110,7 @@ SCOSSL_STATUS p_scossl_ecc_get_encoded_public_key(const SCOSSL_ECC_KEY_CTX *keyC if (scError != SYMCRYPT_NO_ERROR) { - SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeyGetValue failed", scError); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeyGetValue failed", scError); goto cleanup; } @@ -104,34 +130,21 @@ SCOSSL_STATUS p_scossl_ecc_get_encoded_public_key(const SCOSSL_ECC_KEY_CTX *keyC { pbPublicKeyStart[0]++; } - - if (keyCtx->conversionFormat == POINT_CONVERSION_COMPRESSED) - { - // We only need the X coordinate, so copy that and the format byte for return. - // Copy to pbPublicKey in case OPENSSL_memdup fails so we still free the original buffer - if ((pbPublicKey = OPENSSL_memdup(pbPublicKeyStart, (cbPublicKey/2) + 1)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - if (freePublicKey) - { - OPENSSL_free(pbPublicKeyStart); - } - pbPublicKeyStart = pbPublicKey; - } } cbPublicKey++; } - *ppbEncodedKey = pbPublicKeyStart; - *pcbEncodedKey = cbPublicKey; + if (allocatedKey) + { + *ppbPublicKey = pbPublicKeyStart; + } + *pcbPublicKey = cbPublicKey; + ret = SCOSSL_SUCCESS; cleanup: - if (!ret && freePublicKey) + if (!ret && allocatedKey) { OPENSSL_free(pbPublicKeyStart); } @@ -142,20 +155,172 @@ SCOSSL_STATUS p_scossl_ecc_get_encoded_public_key(const SCOSSL_ECC_KEY_CTX *keyC SCOSSL_STATUS p_scossl_ecc_get_private_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, _Out_writes_bytes_(*pcbPrivateKey) PBYTE *ppbPrivateKey, _Out_ SIZE_T *pcbPrivateKey) { - return SCOSSL_FAILURE; -} + PBYTE pbPrivateKey = NULL; + SIZE_T cbPrivateKey; + SYMCRYPT_NUMBER_FORMAT numFormat = keyCtx->isX25519 ? SYMCRYPT_NUMBER_FORMAT_LSB_FIRST : SYMCRYPT_NUMBER_FORMAT_MSB_FIRST; + SYMCRYPT_ECPOINT_FORMAT pointFormat = keyCtx->isX25519 ? SYMCRYPT_ECPOINT_FORMAT_X : SYMCRYPT_ECPOINT_FORMAT_XY; + BOOL allocatedKey = FALSE; + SYMCRYPT_ERROR scError; + SCOSSL_STATUS ret = SCOSSL_FAILURE; + + if (!keyCtx->initialized) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return SCOSSL_FAILURE; + } -SCOSSL_STATUS p_scossl_ecc_get_encoded_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, - _Out_writes_bytes_(*pcbPrivateKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey) -{ - if (selection == OSSL_KEYMGMT_SELECT_PUBLIC_KEY) + cbPrivateKey = SymCryptEckeySizeofPrivateKey(keyCtx->key); + + if (*ppbPrivateKey == NULL) + { + if ((pbPrivateKey = OPENSSL_malloc(cbPrivateKey)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + allocatedKey = TRUE; + } + else if (*pcbPrivateKey >= cbPrivateKey) { - return p_scossl_ecc_get_encoded_public_key(keyCtx, ppbKey, pcbKey); + pbPrivateKey = *ppbPrivateKey; + } else + { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + goto cleanup; + } + + scError = SymCryptEckeyGetValue( + keyCtx->key, + pbPrivateKey, cbPrivateKey, + NULL, 0, + numFormat, + pointFormat, + 0); + if (scError != SYMCRYPT_NO_ERROR) + { + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeyGetValue failed", scError); + goto cleanup; + } + + if (keyCtx->isX25519) + { + pbPrivateKey[0] = (keyCtx->modifiedPrivateBits & 0x07) | (pbPrivateKey[0] & 0xf8); + pbPrivateKey[cbPrivateKey-1] = (keyCtx->modifiedPrivateBits & 0xc0) | (pbPrivateKey[cbPrivateKey-1] & 0x3f); + } + + if (allocatedKey) + { + *ppbPrivateKey = pbPrivateKey; + } + *pcbPrivateKey = cbPrivateKey; + + ret = SCOSSL_SUCCESS; + +cleanup: + if (ret != SCOSSL_SUCCESS && allocatedKey) + { + OPENSSL_secure_clear_free(pbPrivateKey, cbPrivateKey); + } + + return ret; +} + +// Gets the ECC Key following the proper encoding rules. If *ppbKey is non-NULL, then the key material +// is written directly to the supplied buffer. Otherwise, a new buffer is allocated to contain the key. +// The caller is responsible for freeing *ppbKey. +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecc_get_encoded_key(SCOSSL_ECC_KEY_CTX *keyCtx, int selection, + PBYTE *ppbKey, SIZE_T *pcbKey) +{ + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { return p_scossl_ecc_get_private_key(keyCtx, ppbKey, pcbKey); } + + return p_scossl_ecc_get_encoded_public_key(keyCtx, ppbKey, pcbKey); +} + +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecc_set_encoded_key(SCOSSL_ECC_KEY_CTX *keyCtx, int selection, + PCBYTE pbEncodedPublicKey, SIZE_T cbEncodedPublicKey, + PCBYTE pbPrivateKey, SIZE_T cbPrivateKey) +{ + EC_GROUP *ecGroup = NULL; + EC_POINT *ecPoint = NULL; + BN_CTX *bnCtx = NULL; + + PBYTE pbPublicKey = NULL; + SIZE_T cbPublicKey = 0; + SYMCRYPT_ERROR scError; + SCOSSL_STATUS ret = SCOSSL_FAILURE; + + if (keyCtx->key != NULL) + { + SymCryptEckeyFree(keyCtx->key); + } + +#ifdef KEYSINUSE_ENABLED + // Reset keysinuse in case new key material is overwriting existing + p_scossl_ecc_reset_keysinuse(keyCtx); +#endif + + if ((keyCtx->key = SymCryptEckeyAllocate(keyCtx->curve)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + { + cbPublicKey = SymCryptEckeySizeofPublicKey(keyCtx->key, SYMCRYPT_ECPOINT_FORMAT_XY); + if (((ecPoint = EC_POINT_new(ecGroup)) == NULL) || + ((bnCtx = BN_CTX_new_ex(keyCtx->libctx)) == NULL) || + ((pbPublicKey = OPENSSL_malloc(cbPublicKey)) == NULL)) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + if (!EC_POINT_oct2point(ecGroup, ecPoint, pbEncodedPublicKey, cbEncodedPublicKey, bnCtx) || + !scossl_ec_point_to_pubkey(ecPoint, ecGroup, bnCtx, pbPublicKey, cbPublicKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + goto cleanup; + } + } + + scError = SymCryptEckeySetValue( + pbPrivateKey, cbPrivateKey, + pbPublicKey, cbPublicKey, + SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, + SYMCRYPT_ECPOINT_FORMAT_XY, + SYMCRYPT_FLAG_ECKEY_ECDH, + keyCtx->key); + if (scError != SYMCRYPT_NO_ERROR) + { + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeySetValue failed", scError); + goto cleanup; + } + + keyCtx->initialized = TRUE; + ret = SCOSSL_SUCCESS; + +cleanup: + if (ret != SCOSSL_SUCCESS && + keyCtx->key != NULL) + { + SymCryptEckeyFree(keyCtx->key); + } + + EC_GROUP_free(ecGroup); + OPENSSL_free(pbPublicKey); + EC_POINT_free(ecPoint); + BN_CTX_free(bnCtx); + + return ret; } #ifdef KEYSINUSE_ENABLED diff --git a/SymCryptProvider/src/p_scossl_ecc.h b/SymCryptProvider/src/p_scossl_ecc.h index 46c559b8..25aba800 100644 --- a/SymCryptProvider/src/p_scossl_ecc.h +++ b/SymCryptProvider/src/p_scossl_ecc.h @@ -40,14 +40,13 @@ typedef struct { #endif } SCOSSL_ECC_KEY_CTX; -SIZE_T p_scossl_ecc_get_key_size(_In_ const SCOSSL_ECC_KEY_CTX *keyCtx, int selection); +SIZE_T p_scossl_ecc_get_encoded_key_size(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection); SCOSSL_STATUS p_scossl_ecc_get_encoded_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, - _Out_writes_bytes_(*pcbPrivateKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); - -// Helper function for retrieving the properly formatted encoded public key. -// The format differs for x25519 keys. Caller is responsible for freeing *ppbEncodedKey. -SCOSSL_STATUS p_scossl_ecc_get_encoded_public_key(_In_ const SCOSSL_ECC_KEY_CTX *keyCtx, - _Inout_ PBYTE *ppbEncodedKey, _Inout_ SIZE_T *pcbEncodedKey); + _Out_writes_bytes_(*pcbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); + +SCOSSL_STATUS p_scossl_ecc_set_encoded_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, + _In_reads_bytes_opt_(cbEncodedPublicKey) PCBYTE pbEncodedPublicKey, SIZE_T cbEncodedPublicKey, + _In_reads_bytes_opt_(cbPrivateKey) PCBYTE pbPrivateKey, SIZE_T cbPrivateKey); #ifdef KEYSINUSE_ENABLED void p_scossl_ecc_init_keysinuse(_In_ SCOSSL_ECC_KEY_CTX *keyCtx); From b6c3c2d055c3d637112b2ef40f94d77e8a05b315 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Tue, 10 Dec 2024 01:26:57 +0000 Subject: [PATCH 11/21] Expose classic ECDH functions for ML-KEM hybrid --- SymCryptProvider/src/kem/p_scossl_mlkem.c | 7 +- SymCryptProvider/src/kem/p_scossl_mlkem.h | 7 +- SymCryptProvider/src/keyexch/p_scossl_ecdh.c | 33 ++- SymCryptProvider/src/keyexch/p_scossl_ecdh.h | 33 +++ .../src/keymgmt/p_scossl_ecc_impexp_types.h | 167 +++++++++++++++ .../src/keymgmt/p_scossl_ecc_keymgmt.c | 75 ++++--- .../src/keymgmt/p_scossl_ecc_keymgmt.h | 191 ++++------------- .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 202 ++++++++++++------ 8 files changed, 444 insertions(+), 271 deletions(-) create mode 100644 SymCryptProvider/src/keyexch/p_scossl_ecdh.h create mode 100644 SymCryptProvider/src/keymgmt/p_scossl_ecc_impexp_types.h diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.c b/SymCryptProvider/src/kem/p_scossl_mlkem.c index ebf822a0..0647bbf2 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.c +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.c @@ -82,6 +82,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, _Out_writes_bytes_opt_(*outlen) unsigned char *out, _Out_ size_t *outlen, _Out_writes_bytes_(*secretlen) unsigned char *secret, _Out_ size_t *secretlen) { + SIZE_T cbSecret; SIZE_T cbCipherText; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; @@ -98,13 +99,17 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, } scError = SymCryptMlKemSizeofCiphertextFromParams(ctx->keyCtx->mlkemParams, &cbCipherText); - if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); return SCOSSL_FAILURE; } + if (ctx->keyCtx->classicKeyCtx != NULL) + { + + } + if (out != NULL) { scError = SymCryptMlKemEncapsulate(ctx->keyCtx->key, secret, SYMCRYPT_MLKEM_SECRET_LENGTH, out, cbCipherText); diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.h b/SymCryptProvider/src/kem/p_scossl_mlkem.h index 4a2f546e..3990a077 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.h +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.h @@ -10,10 +10,6 @@ extern "C" { #endif typedef struct { - OSSL_FUNC_keymgmt_gen_cleanup_fn *genCleanup; - OSSL_FUNC_keymgmt_gen_init_fn *genInit; - OSSL_FUNC_keymgmt_gen_set_template_fn *setTemplate; - OSSL_FUNC_keymgmt_gen_fn *gen; OSSL_FUNC_keymgmt_new_fn *new; OSSL_FUNC_keymgmt_free_fn *free; OSSL_FUNC_keymgmt_dup_fn *dup; @@ -42,7 +38,8 @@ typedef struct { SYMCRYPT_MLKEMKEY_FORMAT format; SCOSSL_ECC_KEY_CTX *classicKeyCtx; - SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS *classicKeyMgmt; + const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS *classicKeymgmt; + const SCOSSL_MLKEM_CLASSIC_KEYEXCH_FNS *classicKeyexch; } SCOSSL_MLKEM_KEY_CTX; #ifdef __cplusplus diff --git a/SymCryptProvider/src/keyexch/p_scossl_ecdh.c b/SymCryptProvider/src/keyexch/p_scossl_ecdh.c index 14015cf6..8020d23c 100644 --- a/SymCryptProvider/src/keyexch/p_scossl_ecdh.c +++ b/SymCryptProvider/src/keyexch/p_scossl_ecdh.c @@ -2,9 +2,9 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // -#include "scossl_ecc.h" #include "p_scossl_ecc.h" #include "p_scossl_base.h" +#include "keyexch/p_scossl_ecdh.h" #include @@ -12,19 +12,13 @@ extern "C" { #endif -typedef struct -{ - OSSL_LIB_CTX *libctx; - SCOSSL_ECC_KEY_CTX *keyCtx; - SCOSSL_ECC_KEY_CTX *peerKeyCtx; -} SCOSSL_ECDH_CTX; - static const OSSL_PARAM p_scossl_ecdh_ctx_param_types[] = { OSSL_PARAM_END}; static SCOSSL_STATUS p_scossl_ecdh_set_ctx_params(_Inout_ SCOSSL_ECDH_CTX *ctx, _In_ const OSSL_PARAM params[]); -static SCOSSL_ECDH_CTX *p_scossl_ecdh_newctx(_In_ SCOSSL_PROVCTX *provctx) +_Use_decl_annotations_ +SCOSSL_ECDH_CTX *p_scossl_ecdh_newctx(SCOSSL_PROVCTX *provctx) { SCOSSL_ECDH_CTX *ctx = OPENSSL_malloc(sizeof(SCOSSL_ECDH_CTX)); if (ctx != NULL) @@ -37,12 +31,14 @@ static SCOSSL_ECDH_CTX *p_scossl_ecdh_newctx(_In_ SCOSSL_PROVCTX *provctx) return ctx; } -static void p_scossl_ecdh_freectx(_In_ SCOSSL_ECDH_CTX *ctx) +_Use_decl_annotations_ +void p_scossl_ecdh_freectx(SCOSSL_ECDH_CTX *ctx) { OPENSSL_free(ctx); } -static SCOSSL_ECDH_CTX *p_scossl_ecdh_dupctx(_In_ SCOSSL_ECDH_CTX *ctx) +_Use_decl_annotations_ +SCOSSL_ECDH_CTX *p_scossl_ecdh_dupctx(SCOSSL_ECDH_CTX *ctx) { SCOSSL_ECDH_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_ECDH_CTX)); if (copyCtx != NULL) @@ -55,8 +51,9 @@ static SCOSSL_ECDH_CTX *p_scossl_ecdh_dupctx(_In_ SCOSSL_ECDH_CTX *ctx) return copyCtx; } -static SCOSSL_STATUS p_scossl_ecdh_init(_In_ SCOSSL_ECDH_CTX *ctx, _In_ SCOSSL_ECC_KEY_CTX *keyCtx, - ossl_unused const OSSL_PARAM params[]) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecdh_init(SCOSSL_ECDH_CTX *ctx, SCOSSL_ECC_KEY_CTX *keyCtx, + ossl_unused const OSSL_PARAM params[]) { if (ctx == NULL || keyCtx == NULL) { @@ -69,7 +66,8 @@ static SCOSSL_STATUS p_scossl_ecdh_init(_In_ SCOSSL_ECDH_CTX *ctx, _In_ SCOSSL_E return SCOSSL_SUCCESS; } -static SCOSSL_STATUS p_scossl_ecdh_set_peer(_Inout_ SCOSSL_ECDH_CTX *ctx, _In_ SCOSSL_ECC_KEY_CTX *peerKeyCtx) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecdh_set_peer(SCOSSL_ECDH_CTX *ctx, SCOSSL_ECC_KEY_CTX *peerKeyCtx) { SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -93,9 +91,10 @@ static SCOSSL_STATUS p_scossl_ecdh_set_peer(_Inout_ SCOSSL_ECDH_CTX *ctx, _In_ S return ret; } -static SCOSSL_STATUS p_scossl_ecdh_derive(_In_ SCOSSL_ECDH_CTX *ctx, - _Out_writes_bytes_opt_(*secretlen) unsigned char *secret, _Out_ size_t *secretlen, - size_t outlen) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecdh_derive(SCOSSL_ECDH_CTX *ctx, + unsigned char *secret, size_t *secretlen, + size_t outlen) { PBYTE pbSecret = secret; PBYTE pbSecretBuf = NULL; diff --git a/SymCryptProvider/src/keyexch/p_scossl_ecdh.h b/SymCryptProvider/src/keyexch/p_scossl_ecdh.h new file mode 100644 index 00000000..72c874ed --- /dev/null +++ b/SymCryptProvider/src/keyexch/p_scossl_ecdh.h @@ -0,0 +1,33 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include "scossl_ecc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + OSSL_LIB_CTX *libctx; + SCOSSL_ECC_KEY_CTX *keyCtx; + SCOSSL_ECC_KEY_CTX *peerKeyCtx; +} SCOSSL_ECDH_CTX; + +// ECDH functions are exposed here for use in hybrid key exchange +SCOSSL_ECDH_CTX *p_scossl_ecdh_newctx(_In_ SCOSSL_PROVCTX *provctx); +void p_scossl_ecdh_freectx(_In_ SCOSSL_ECDH_CTX *ctx); +SCOSSL_ECDH_CTX *p_scossl_ecdh_dupctx(_In_ SCOSSL_ECDH_CTX *ctx); + +SCOSSL_STATUS p_scossl_ecdh_init(_In_ SCOSSL_ECDH_CTX *ctx, _In_ SCOSSL_ECC_KEY_CTX *keyCtx, + ossl_unused const OSSL_PARAM params[]); +SCOSSL_STATUS p_scossl_ecdh_set_peer(_Inout_ SCOSSL_ECDH_CTX *ctx, _In_ SCOSSL_ECC_KEY_CTX *peerKeyCtx); +SCOSSL_STATUS p_scossl_ecdh_derive(_In_ SCOSSL_ECDH_CTX *ctx, + _Out_writes_bytes_opt_(*secretlen) unsigned char *secret, _Out_ size_t *secretlen, + size_t outlen); + + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/keymgmt/p_scossl_ecc_impexp_types.h b/SymCryptProvider/src/keymgmt/p_scossl_ecc_impexp_types.h new file mode 100644 index 00000000..3e6ccd16 --- /dev/null +++ b/SymCryptProvider/src/keymgmt/p_scossl_ecc_impexp_types.h @@ -0,0 +1,167 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Parameter types for import/export depend on the selection +// passed by the caller. These can be any combination of: +// OSSL_KEYMGMT_SELECT_PRIVATE_KEY +// OSSL_KEYMGMT_SELECT_PUBLIC_KEY +// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS +// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS +// Rather than constructing the parameter array each time +// a caller queries supported parameters, these values +// are hardcoded here. This follows the same pattern as +// the default provider. + +#define SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS \ + OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), + +#define SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS \ + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), + +#define SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS \ + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), \ + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), + +#define SCOSSL_ECC_IMPEXP_OTHER_PARAMS \ + OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), \ + OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL), \ + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), + +// OSSL_KEYMGMT_SELECT_PRIVATE_KEY +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x01[] = { + SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_PUBLIC_KEY +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x02[] = { + SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_PRIVATE_KEY +// OSSL_KEYMGMT_SELECT_PUBLIC_KEY +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x03[] = { + SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS + SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x04[] = { + SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_PRIVATE_KEY +// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x05[] = { + SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS + SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_PUBLIC_KEY +// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x06[] = { + SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS + SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_PRIVATE_KEY +// OSSL_KEYMGMT_SELECT_PUBLIC_KEY +// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x07[] = { + SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS + SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS + SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x08[] = { + SCOSSL_ECC_IMPEXP_OTHER_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_PRIVATE_KEY +// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x09[] = { + SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS + SCOSSL_ECC_IMPEXP_OTHER_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_PUBLIC_KEY +// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x0a[] = { + SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS + SCOSSL_ECC_IMPEXP_OTHER_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_PRIVATE_KEY +// OSSL_KEYMGMT_SELECT_PUBLIC_KEY +// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x0b[] = { + SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS + SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS + SCOSSL_ECC_IMPEXP_OTHER_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS +// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x0c[] = { + SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS + SCOSSL_ECC_IMPEXP_OTHER_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_PRIVATE_KEY +// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS +// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x0d[] = { + SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS + SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS + SCOSSL_ECC_IMPEXP_OTHER_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_PUBLIC_KEY +// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS +// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x0e[] = { + SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS + SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS + SCOSSL_ECC_IMPEXP_OTHER_PARAMS + OSSL_PARAM_END}; + +// OSSL_KEYMGMT_SELECT_PRIVATE_KEY +// OSSL_KEYMGMT_SELECT_PUBLIC_KEY +// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS +// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS +static const OSSL_PARAM p_scossl_ecc_impexp_types_0x0f[] = { + SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS + SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS + SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS + SCOSSL_ECC_IMPEXP_OTHER_PARAMS + OSSL_PARAM_END}; + +const OSSL_PARAM *p_scossl_ecc_keymgmt_impexp_param_types[] = { + NULL, + p_scossl_ecc_impexp_types_0x01, + p_scossl_ecc_impexp_types_0x02, + p_scossl_ecc_impexp_types_0x03, + p_scossl_ecc_impexp_types_0x04, + p_scossl_ecc_impexp_types_0x05, + p_scossl_ecc_impexp_types_0x06, + p_scossl_ecc_impexp_types_0x07, + p_scossl_ecc_impexp_types_0x08, + p_scossl_ecc_impexp_types_0x09, + p_scossl_ecc_impexp_types_0x0a, + p_scossl_ecc_impexp_types_0x0b, + p_scossl_ecc_impexp_types_0x0c, + p_scossl_ecc_impexp_types_0x0d, + p_scossl_ecc_impexp_types_0x0e, + p_scossl_ecc_impexp_types_0x0f}; + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c index 0ea5f31a..73f71a73 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c @@ -5,7 +5,8 @@ #include "scossl_ecc.h" #include "p_scossl_ecc.h" #include "p_scossl_base.h" -#include "p_scossl_ecc_keymgmt.h" +#include "keymgmt/p_scossl_ecc_impexp_types.h" +#include "keymgmt/p_scossl_ecc_keymgmt.h" #include #include @@ -18,14 +19,6 @@ extern "C" { #define SCOSSL_ECC_DEFAULT_DIGEST SN_sha256 #define SCOSSL_ECC_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_PUBLIC_KEY | OSSL_KEYMGMT_SELECT_PRIVATE_KEY | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) -typedef struct -{ - OSSL_LIB_CTX *libctx; - PCSYMCRYPT_ECURVE curve; - BOOL isX25519; - point_conversion_form_t conversionFormat; -} SCOSSL_ECC_KEYGEN_CTX; - // ScOSSL only supports named curves static const OSSL_PARAM p_scossl_ecc_keygen_settable_param_types[] = { OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), @@ -92,7 +85,8 @@ static point_conversion_form_t p_scossl_ecc_keymgmt_conversion_name_to_id(_In_ c // the size of the SYMCRYPT_ECKEY depends on parameters that aren't // known until import, no key is actually allocated here. -static SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_new_ctx(_In_ SCOSSL_PROVCTX *provctx) +_Use_decl_annotations_ +SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_new_ctx(SCOSSL_PROVCTX *provctx) { SCOSSL_ECC_KEY_CTX *keyCtx = OPENSSL_zalloc(sizeof(SCOSSL_ECC_KEY_CTX)); if (keyCtx != NULL) @@ -108,7 +102,8 @@ static SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_new_ctx(_In_ SCOSSL_PROVCTX *pro return keyCtx; } -static SCOSSL_ECC_KEY_CTX *p_scossl_x25519_keymgmt_new_ctx(_In_ SCOSSL_PROVCTX *provctx) +_Use_decl_annotations_ +SCOSSL_ECC_KEY_CTX *p_scossl_x25519_keymgmt_new_ctx(SCOSSL_PROVCTX *provctx) { SCOSSL_ECC_KEY_CTX *keyCtx = p_scossl_ecc_keymgmt_new_ctx(provctx); if (keyCtx != NULL) @@ -123,7 +118,8 @@ static SCOSSL_ECC_KEY_CTX *p_scossl_x25519_keymgmt_new_ctx(_In_ SCOSSL_PROVCTX * return keyCtx; } -void p_scossl_ecc_keymgmt_free_ctx(_In_ SCOSSL_ECC_KEY_CTX *keyCtx) +_Use_decl_annotations_ +void p_scossl_ecc_keymgmt_free_ctx(SCOSSL_ECC_KEY_CTX *keyCtx) { if (keyCtx == NULL) return; @@ -139,7 +135,8 @@ void p_scossl_ecc_keymgmt_free_ctx(_In_ SCOSSL_ECC_KEY_CTX *keyCtx) OPENSSL_free(keyCtx); } -static SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_dup_ctx(_In_ const SCOSSL_ECC_KEY_CTX *keyCtx, int selection) +_Use_decl_annotations_ +SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_dup_ctx(_In_ const SCOSSL_ECC_KEY_CTX *keyCtx, int selection) { PBYTE pbData = NULL; PBYTE pbPrivateKey = NULL; @@ -355,7 +352,8 @@ static const OSSL_PARAM *p_scossl_ecc_keygen_settable_params(ossl_unused void *g return p_scossl_ecc_keygen_settable_param_types; } -static void p_scossl_ecc_keygen_cleanup(_Inout_ SCOSSL_ECC_KEYGEN_CTX *genCtx) +_Use_decl_annotations_ +void p_scossl_ecc_keygen_cleanup(SCOSSL_ECC_KEYGEN_CTX *genCtx) { OPENSSL_free(genCtx); } @@ -383,14 +381,16 @@ static SCOSSL_ECC_KEYGEN_CTX *p_scossl_ecc_common_keygen_init(_In_ SCOSSL_PROVCT return genCtx; } -static SCOSSL_ECC_KEYGEN_CTX *p_scossl_ecc_keygen_init(_In_ SCOSSL_PROVCTX *provctx, ossl_unused int selection, - _In_ const OSSL_PARAM params[]) +_Use_decl_annotations_ +SCOSSL_ECC_KEYGEN_CTX *p_scossl_ecc_keygen_init(SCOSSL_PROVCTX *provctx, ossl_unused int selection, + const OSSL_PARAM params[]) { return p_scossl_ecc_common_keygen_init(provctx, selection, params, FALSE); } -static SCOSSL_ECC_KEYGEN_CTX *p_scossl_x25519_keygen_init(_In_ SCOSSL_PROVCTX *provctx, ossl_unused int selection, - _In_ const OSSL_PARAM params[]) +_Use_decl_annotations_ +SCOSSL_ECC_KEYGEN_CTX *p_scossl_x25519_keygen_init(SCOSSL_PROVCTX *provctx, ossl_unused int selection, + const OSSL_PARAM params[]) { SCOSSL_ECC_KEYGEN_CTX *genCtx = p_scossl_ecc_common_keygen_init(provctx, selection, params, TRUE); // Always set curve to X25519 @@ -402,7 +402,8 @@ static SCOSSL_ECC_KEYGEN_CTX *p_scossl_x25519_keygen_init(_In_ SCOSSL_PROVCTX *p return genCtx; } -static SCOSSL_STATUS p_scossl_ecc_keygen_set_template(_Inout_ SCOSSL_ECC_KEYGEN_CTX *genCtx, SCOSSL_ECC_KEY_CTX *tmplCtx) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecc_keygen_set_template(SCOSSL_ECC_KEYGEN_CTX *genCtx, SCOSSL_ECC_KEY_CTX *tmplCtx) { if (tmplCtx == NULL || tmplCtx->curve == NULL) { @@ -413,7 +414,8 @@ static SCOSSL_STATUS p_scossl_ecc_keygen_set_template(_Inout_ SCOSSL_ECC_KEYGEN_ return SCOSSL_SUCCESS; } -static SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keygen(_In_ SCOSSL_ECC_KEYGEN_CTX *genCtx, ossl_unused OSSL_CALLBACK *cb, ossl_unused void *cbarg) +_Use_decl_annotations_ +SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keygen(SCOSSL_ECC_KEYGEN_CTX *genCtx, ossl_unused OSSL_CALLBACK *cb, ossl_unused void *cbarg) { SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; @@ -540,7 +542,8 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_get_pubkey_point(_In_ SCOSSL_ECC_KEY_C return ret; } -static SCOSSL_STATUS p_scossl_ecc_keymgmt_get_params(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, _Inout_ OSSL_PARAM params[]) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecc_keymgmt_get_params(SCOSSL_ECC_KEY_CTX *keyCtx, OSSL_PARAM params[]) { PBYTE pbEncodedKey = NULL; PBYTE pbPrivateKey = NULL; @@ -714,7 +717,8 @@ static const OSSL_PARAM *p_scossl_x25519_keymgmt_gettable_params(ossl_unused voi return p_scossl_x25519_keymgmt_gettable_param_types; } -static SCOSSL_STATUS p_scossl_ecc_keymgmt_set_params(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, _In_ const OSSL_PARAM params[]) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecc_keymgmt_set_params(SCOSSL_ECC_KEY_CTX *keyCtx, const OSSL_PARAM params[]) { EC_GROUP *ecGroup = NULL; PBYTE encodedPoint = NULL; @@ -845,7 +849,8 @@ static const OSSL_PARAM *p_scossl_ecc_keymgmt_settable_params(ossl_unused void * return p_scossl_ecc_keymgmt_settable_param_types; } -static BOOL p_scossl_ecc_keymgmt_has(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection) +_Use_decl_annotations_ +BOOL p_scossl_ecc_keymgmt_has(SCOSSL_ECC_KEY_CTX *keyCtx, int selection) { BOOL hasSelection = TRUE; @@ -876,7 +881,8 @@ static BOOL p_scossl_ecc_keymgmt_has(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int select // Key checking is handled by SymCrypt, and the curves are valid named curves. This function // just needs to check whether the data indicated by selection has been set. -static SCOSSL_STATUS p_scossl_ecc_keymgmt_validate(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, ossl_unused int checktype) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecc_keymgmt_validate(SCOSSL_ECC_KEY_CTX *keyCtx, int selection, ossl_unused int checktype) { SCOSSL_STATUS success = SCOSSL_SUCCESS; @@ -888,8 +894,9 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_validate(_In_ SCOSSL_ECC_KEY_CTX *keyC return success; } -static BOOL p_scossl_ecc_keymgmt_match(_In_ SCOSSL_ECC_KEY_CTX *keyCtx1, _In_ SCOSSL_ECC_KEY_CTX *keyCtx2, - int selection) +_Use_decl_annotations_ +BOOL p_scossl_ecc_keymgmt_match(SCOSSL_ECC_KEY_CTX *keyCtx1, SCOSSL_ECC_KEY_CTX *keyCtx2, + int selection) { BOOL ret = FALSE; PBYTE pbPrivateKey1 = NULL; @@ -1028,7 +1035,8 @@ static const OSSL_PARAM *p_scossl_ecc_keymgmt_impexp_types(int selection) return p_scossl_ecc_keymgmt_impexp_param_types[idx]; } -static SCOSSL_STATUS p_scossl_ecc_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecc_keymgmt_import(SCOSSL_ECC_KEY_CTX *keyCtx, int selection, const OSSL_PARAM params[]) { SCOSSL_STATUS ret = SCOSSL_FAILURE; EC_GROUP *ecGroup = NULL; @@ -1171,8 +1179,9 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *key return ret; } -static SCOSSL_STATUS p_scossl_ecc_keymgmt_export(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, - _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecc_keymgmt_export(SCOSSL_ECC_KEY_CTX *keyCtx, int selection, + OSSL_CALLBACK *param_cb, void *cbarg) { SCOSSL_STATUS ret = SCOSSL_FAILURE; OSSL_PARAM_BLD *bld = NULL; @@ -1269,7 +1278,8 @@ static const OSSL_PARAM *p_scossl_x25519_keymgmt_impexp_types(int selection) return (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0 ? NULL : p_scossl_x25519_keymgmt_impexp_param_types; } -static SCOSSL_STATUS p_scossl_x25519_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_x25519_keymgmt_import(SCOSSL_ECC_KEY_CTX *keyCtx, int selection, const OSSL_PARAM params[]) { SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -1350,8 +1360,9 @@ static SCOSSL_STATUS p_scossl_x25519_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX * return ret; } -static SCOSSL_STATUS p_scossl_x25519_keymgmt_export(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, - _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_x25519_keymgmt_export(SCOSSL_ECC_KEY_CTX *keyCtx, int selection, + OSSL_CALLBACK *param_cb, void *cbarg) { SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; diff --git a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.h b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.h index 508281db..65b402eb 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.h +++ b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.h @@ -2,165 +2,48 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // -#include -#include +#include "scossl_helpers.h" #ifdef __cplusplus extern "C" { #endif -// Parameter types for import/export depend on the selection -// passed by the caller. These can be any combination of: -// OSSL_KEYMGMT_SELECT_PRIVATE_KEY -// OSSL_KEYMGMT_SELECT_PUBLIC_KEY -// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS -// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS -// Rather than constructing the parameter array each time -// a caller queries supported parameters, these values -// are hardcoded here. This follows the same pattern as -// the default provider. - -#define SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS \ - OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), - -#define SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS \ - OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), - -#define SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS \ - OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), \ - OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), - -#define SCOSSL_ECC_IMPEXP_OTHER_PARAMS \ - OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), \ - OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL), \ - OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0), - -// OSSL_KEYMGMT_SELECT_PRIVATE_KEY -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x01[] = { - SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_PUBLIC_KEY -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x02[] = { - SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_PRIVATE_KEY -// OSSL_KEYMGMT_SELECT_PUBLIC_KEY -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x03[] = { - SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS - SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x04[] = { - SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_PRIVATE_KEY -// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x05[] = { - SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS - SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_PUBLIC_KEY -// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x06[] = { - SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS - SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_PRIVATE_KEY -// OSSL_KEYMGMT_SELECT_PUBLIC_KEY -// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x07[] = { - SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS - SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS - SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x08[] = { - SCOSSL_ECC_IMPEXP_OTHER_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_PRIVATE_KEY -// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x09[] = { - SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS - SCOSSL_ECC_IMPEXP_OTHER_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_PUBLIC_KEY -// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x0a[] = { - SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS - SCOSSL_ECC_IMPEXP_OTHER_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_PRIVATE_KEY -// OSSL_KEYMGMT_SELECT_PUBLIC_KEY -// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x0b[] = { - SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS - SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS - SCOSSL_ECC_IMPEXP_OTHER_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS -// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x0c[] = { - SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS - SCOSSL_ECC_IMPEXP_OTHER_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_PRIVATE_KEY -// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS -// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x0d[] = { - SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS - SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS - SCOSSL_ECC_IMPEXP_OTHER_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_PUBLIC_KEY -// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS -// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x0e[] = { - SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS - SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS - SCOSSL_ECC_IMPEXP_OTHER_PARAMS - OSSL_PARAM_END}; - -// OSSL_KEYMGMT_SELECT_PRIVATE_KEY -// OSSL_KEYMGMT_SELECT_PUBLIC_KEY -// OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS -// OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS -static const OSSL_PARAM p_scossl_ecc_impexp_types_0x0f[] = { - SCOSSL_ECC_IMPEXP_PRIV_KEY_PARAMS - SCOSSL_ECC_IMPEXP_PUB_KEY_PARAMS - SCOSSL_ECC_IMPEXP_DOMAIN_PARAMS - SCOSSL_ECC_IMPEXP_OTHER_PARAMS - OSSL_PARAM_END}; - -static const OSSL_PARAM *p_scossl_ecc_keymgmt_impexp_param_types[] = { - NULL, - p_scossl_ecc_impexp_types_0x01, - p_scossl_ecc_impexp_types_0x02, - p_scossl_ecc_impexp_types_0x03, - p_scossl_ecc_impexp_types_0x04, - p_scossl_ecc_impexp_types_0x05, - p_scossl_ecc_impexp_types_0x06, - p_scossl_ecc_impexp_types_0x07, - p_scossl_ecc_impexp_types_0x08, - p_scossl_ecc_impexp_types_0x09, - p_scossl_ecc_impexp_types_0x0a, - p_scossl_ecc_impexp_types_0x0b, - p_scossl_ecc_impexp_types_0x0c, - p_scossl_ecc_impexp_types_0x0d, - p_scossl_ecc_impexp_types_0x0e, - p_scossl_ecc_impexp_types_0x0f}; +typedef struct +{ + OSSL_LIB_CTX *libctx; + PCSYMCRYPT_ECURVE curve; + BOOL isX25519; + point_conversion_form_t conversionFormat; +} SCOSSL_ECC_KEYGEN_CTX; + +// ECC Key management functions are exposed here for use in hybrid key exchange +SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_new_ctx(_In_ SCOSSL_PROVCTX *provctx); +SCOSSL_ECC_KEY_CTX *p_scossl_x25519_keymgmt_new_ctx(_In_ SCOSSL_PROVCTX *provctx); +void p_scossl_ecc_keymgmt_free_ctx(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx); +SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_dup_ctx(_In_ const SCOSSL_ECC_KEY_CTX *keyCtx, int selection); + +SCOSSL_ECC_KEYGEN_CTX *p_scossl_ecc_keygen_init(_In_ SCOSSL_PROVCTX *provctx, ossl_unused int selection, + _In_ const OSSL_PARAM params[]); +SCOSSL_ECC_KEYGEN_CTX *p_scossl_x25519_keygen_init(_In_ SCOSSL_PROVCTX *provctx, ossl_unused int selection, + _In_ const OSSL_PARAM params[]); +void p_scossl_ecc_keygen_cleanup(_Inout_ SCOSSL_ECC_KEYGEN_CTX *genCtx); +SCOSSL_STATUS p_scossl_ecc_keygen_set_template(_Inout_ SCOSSL_ECC_KEYGEN_CTX *genCtx, _In_ SCOSSL_ECC_KEY_CTX *tmplCtx); +SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keygen(_In_ SCOSSL_ECC_KEYGEN_CTX *genCtx, ossl_unused OSSL_CALLBACK *cb, ossl_unused void *cbarg); + +SCOSSL_STATUS p_scossl_ecc_keymgmt_get_params(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, _Inout_ OSSL_PARAM params[]); +SCOSSL_STATUS p_scossl_ecc_keymgmt_set_params(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, _In_ const OSSL_PARAM params[]); + +BOOL p_scossl_ecc_keymgmt_has(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection); +SCOSSL_STATUS p_scossl_ecc_keymgmt_validate(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, ossl_unused int checktype); +BOOL p_scossl_ecc_keymgmt_match(_In_ SCOSSL_ECC_KEY_CTX *keyCtx1, _In_ SCOSSL_ECC_KEY_CTX *keyCtx2, + int selection); + +SCOSSL_STATUS p_scossl_ecc_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]); +SCOSSL_STATUS p_scossl_ecc_keymgmt_export(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, + _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg); +SCOSSL_STATUS p_scossl_x25519_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]); +SCOSSL_STATUS p_scossl_x25519_keymgmt_export(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, + _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg); #ifdef __cplusplus } diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index beeaa1d4..2580c515 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -6,6 +6,8 @@ #include "p_scossl_base.h" #include "kem/p_scossl_mlkem.h" #include "keymgmt/p_scossl_mlkem_keymgmt.h" +#include "keyexch/p_scossl_ecdh.h" +#include "keymgmt/p_scossl_ecc_keymgmt.h" #include #include @@ -15,14 +17,19 @@ extern "C" { #endif +typedef struct { + OSSL_FUNC_keymgmt_gen_cleanup_fn *genCleanup; + OSSL_FUNC_keymgmt_gen_init_fn *genInit; + OSSL_FUNC_keymgmt_gen_set_template_fn *setTemplate; + OSSL_FUNC_keymgmt_gen_fn *gen; +} SCOSSL_MLKEM_CLASSIC_KEYGEN_FNS; + typedef struct { SCOSSL_PROVCTX *provCtx; const char *groupName; - SYMCRYPT_MLKEM_PARAMS mlkemParams; PVOID classicKeygenCtx; - const char *classicGroupName; - SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS *classicKeyMgmt; + const SCOSSL_MLKEM_CLASSIC_KEYGEN_FNS *classicKeygen; } SCOSSL_MLKEM_KEYGEN_CTX; #define SCOSSL_MLKEM_PKEY_PARAMETER_TYPES \ @@ -69,13 +76,52 @@ static const OSSL_PARAM *p_scossl_mlkem_impexp_types[] = { p_scossl_mlkem_pkey_types, p_scossl_mlkem_all_types}; -static SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS p_scossl_ecc_classic_keymgmt; -static SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS p_scossl_x25519_classic_keymgmt; - -static const char *p_scossl_mlkem_keymgmt_params_from_name(_In_ const char *groupName, - _Out_ SYMCRYPT_MLKEM_PARAMS *mlkemParams, - _Out_ const char **classicGroupName, - _Out_ SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS **classicKeymgmt); +static const SCOSSL_MLKEM_CLASSIC_KEYGEN_FNS p_scossl_ecc_classic_keygen = { + (OSSL_FUNC_keymgmt_gen_cleanup_fn *) p_scossl_ecc_keygen_cleanup, + (OSSL_FUNC_keymgmt_gen_init_fn *) p_scossl_ecc_keygen_init, + (OSSL_FUNC_keymgmt_gen_set_template_fn *) p_scossl_ecc_keygen_set_template, + (OSSL_FUNC_keymgmt_gen_fn *) p_scossl_ecc_keygen}; + +static const SCOSSL_MLKEM_CLASSIC_KEYGEN_FNS p_scossl_x25519_classic_keygen = { + (OSSL_FUNC_keymgmt_gen_cleanup_fn *) p_scossl_ecc_keygen_cleanup, + (OSSL_FUNC_keymgmt_gen_init_fn *) p_scossl_x25519_keygen_init, + (OSSL_FUNC_keymgmt_gen_set_template_fn *) p_scossl_ecc_keygen_set_template, + (OSSL_FUNC_keymgmt_gen_fn *) p_scossl_ecc_keygen}; + +static const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS p_scossl_ecc_classic_keymgmt = { + (OSSL_FUNC_keymgmt_new_fn *) p_scossl_ecc_keymgmt_new_ctx, + (OSSL_FUNC_keymgmt_free_fn *) p_scossl_ecc_keymgmt_free_ctx, + (OSSL_FUNC_keymgmt_dup_fn *) p_scossl_ecc_keymgmt_dup_ctx, + (OSSL_FUNC_keymgmt_get_params_fn *) p_scossl_ecc_keymgmt_get_params, + (OSSL_FUNC_keymgmt_set_params_fn *) p_scossl_ecc_keymgmt_set_params, + (OSSL_FUNC_keymgmt_has_fn *) p_scossl_ecc_keymgmt_has, + (OSSL_FUNC_keymgmt_match_fn *) p_scossl_ecc_keymgmt_match, + (OSSL_FUNC_keymgmt_import_fn *) p_scossl_ecc_keymgmt_import, + (OSSL_FUNC_keymgmt_export_fn *) p_scossl_ecc_keymgmt_export, + (OSSL_FUNC_keymgmt_validate_fn *) p_scossl_ecc_keymgmt_validate}; + +static const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS p_scossl_x25519_classic_keymgmt = { + (OSSL_FUNC_keymgmt_new_fn *) p_scossl_x25519_keymgmt_new_ctx, + (OSSL_FUNC_keymgmt_free_fn *) p_scossl_ecc_keymgmt_free_ctx, + (OSSL_FUNC_keymgmt_dup_fn *) p_scossl_ecc_keymgmt_dup_ctx, + (OSSL_FUNC_keymgmt_get_params_fn *) p_scossl_ecc_keymgmt_get_params, + (OSSL_FUNC_keymgmt_set_params_fn *) p_scossl_ecc_keymgmt_set_params, + (OSSL_FUNC_keymgmt_has_fn *) p_scossl_ecc_keymgmt_has, + (OSSL_FUNC_keymgmt_match_fn *) p_scossl_ecc_keymgmt_match, + (OSSL_FUNC_keymgmt_import_fn *) p_scossl_x25519_keymgmt_import, + (OSSL_FUNC_keymgmt_export_fn *) p_scossl_x25519_keymgmt_export, + (OSSL_FUNC_keymgmt_validate_fn *) p_scossl_ecc_keymgmt_validate}; + +static const SCOSSL_MLKEM_CLASSIC_KEYEXCH_FNS p_scossl_ecdh_classic_keyexch = { + (OSSL_FUNC_keyexch_newctx_fn *) p_scossl_ecdh_newctx, + (OSSL_FUNC_keyexch_freectx_fn *) p_scossl_ecdh_freectx, + (OSSL_FUNC_keyexch_dupctx_fn *) p_scossl_ecdh_dupctx, + (OSSL_FUNC_keyexch_init_fn *) p_scossl_ecdh_init, + (OSSL_FUNC_keyexch_set_peer_fn *) p_scossl_ecdh_set_peer, + (OSSL_FUNC_keyexch_derive_fn *) p_scossl_ecdh_derive}; + +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_group(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, _In_ const char *groupName, + _Out_ const char **classicGroupName); static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx); SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(ossl_unused void *provCtx) @@ -95,7 +141,7 @@ void p_scossl_mlkem_keymgmt_free_key_ctx(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx) if (keyCtx->classicKeyCtx != NULL) { - keyCtx->classicKeyMgmt->free(keyCtx->classicKeyCtx); + keyCtx->classicKeymgmt->free(keyCtx->classicKeyCtx); } OPENSSL_free(keyCtx); @@ -158,8 +204,8 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS if (keyCtx->classicKeyCtx != NULL) { - copyCtx->classicKeyMgmt = keyCtx->classicKeyMgmt; - copyCtx->classicKeyCtx = keyCtx->classicKeyMgmt->dup(keyCtx->classicKeyCtx, selection); + copyCtx->classicKeymgmt = keyCtx->classicKeymgmt; + copyCtx->classicKeyCtx = keyCtx->classicKeymgmt->dup(keyCtx->classicKeyCtx, selection); } } @@ -181,21 +227,56 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS // // Key Generation // +static SCOSSL_STATUS p_scossl_mlkem_keygen_set_group(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ const char *groupName) +{ + if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM512) == 0) + { + genCtx->groupName = SCOSSL_SN_MLKEM512; + genCtx->classicKeygen = NULL; + } + else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM768) == 0) + { + genCtx->groupName = SCOSSL_SN_MLKEM768; + genCtx->classicKeygen = NULL; + } + else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM1024) == 0) + { + genCtx->groupName = SCOSSL_SN_MLKEM1024; + genCtx->classicKeygen = NULL; + } + else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_P256_MLKEM768) == 0) + { + genCtx->groupName = SCOSSL_SN_P256_MLKEM768; + genCtx->classicKeygen = &p_scossl_ecc_classic_keygen; + } + else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_X25519_MLKEM768) == 0) + { + genCtx->groupName = SCOSSL_SN_X25519_MLKEM768; + genCtx->classicKeygen = &p_scossl_x25519_classic_keygen; + } + else + { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); + return SCOSSL_FAILURE; + } + + return SCOSSL_SUCCESS; +} + static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ const OSSL_PARAM params[]) { const OSSL_PARAM *p; if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL) { - const char *name; + const char *groupName; - if (!OSSL_PARAM_get_utf8_string_ptr(p, &name)) + if (!OSSL_PARAM_get_utf8_string_ptr(p, &groupName)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return SCOSSL_FAILURE; } - genCtx->groupName = p_scossl_mlkem_keymgmt_params_from_name(name, &genCtx->mlkemParams, &genCtx->classicGroupName, &genCtx->classicKeyMgmt); - if (genCtx->groupName == NULL) + if (p_scossl_mlkem_keygen_set_group(genCtx, groupName) != SCOSSL_SUCCESS) { ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); return SCOSSL_FAILURE; @@ -217,7 +298,7 @@ static void p_scossl_mlkem_keygen_cleanup(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCt if (genCtx->classicKeygenCtx != NULL) { - genCtx->classicKeyMgmt->genCleanup(genCtx->classicKeygenCtx); + genCtx->classicKeygen->genCleanup(genCtx->classicKeygenCtx); } OPENSSL_free(genCtx); @@ -232,10 +313,8 @@ static SCOSSL_MLKEM_KEYGEN_CTX *p_scossl_mlkem_keygen_init(ossl_unused void *pro { genCtx->provCtx = provCtx; genCtx->groupName = SCOSSL_SN_MLKEM768; - genCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; - genCtx->classicGroupName = NULL; - genCtx->classicKeyMgmt = NULL; genCtx->classicKeygenCtx = NULL; + genCtx->classicKeygen = NULL; if (p_scossl_mlkem_keygen_set_params(genCtx, params) != SCOSSL_SUCCESS) { @@ -262,8 +341,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEY return SCOSSL_FAILURE; } - genCtx->groupName = p_scossl_mlkem_keymgmt_params_from_name(tmplCtx->groupName, &genCtx->mlkemParams, &genCtx->classicGroupName, &genCtx->classicKeyMgmt); - if (genCtx->groupName == NULL) + if (p_scossl_mlkem_keygen_set_group(genCtx, tmplCtx->groupName) != SCOSSL_SUCCESS) { ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); return SCOSSL_FAILURE; @@ -274,12 +352,14 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEY static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ OSSL_CALLBACK *cb, _In_ void *cbarg) { - BOOL success = FALSE; - SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + const char *classicGroupName; SCOSSL_MLKEM_KEY_CTX *keyCtx; + SCOSSL_STATUS status = SCOSSL_FAILURE; + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; if ((keyCtx = p_scossl_mlkem_keymgmt_new_ctx(NULL)) == NULL || - (keyCtx->key = SymCryptMlKemkeyAllocate(genCtx->mlkemParams)) == NULL) + p_scossl_mlkem_keymgmt_set_group(keyCtx, genCtx->groupName, &classicGroupName) != SCOSSL_SUCCESS || + (keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->mlkemParams)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; @@ -292,32 +372,31 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX goto cleanup; } - if (genCtx->classicGroupName != NULL) + if (genCtx->classicKeygen != NULL) { OSSL_PARAM classicParams[2] = { - OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, (char *)genCtx->classicGroupName, strlen(genCtx->classicGroupName)), + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, (char *)classicGroupName, strlen(classicGroupName)), OSSL_PARAM_END}; - genCtx->classicKeygenCtx = genCtx->classicKeyMgmt->genInit(genCtx->provCtx, 0, classicParams); + genCtx->classicKeygenCtx = genCtx->classicKeygen->genInit(genCtx->provCtx, 0, classicParams); if (genCtx->classicKeygenCtx == NULL) { goto cleanup; } - keyCtx->classicKeyCtx = genCtx->classicKeyMgmt->gen(genCtx->classicKeygenCtx, cb, cbarg); + keyCtx->classicKeyCtx = genCtx->classicKeygen->gen(genCtx->classicKeygenCtx, cb, cbarg); if (keyCtx->classicKeyCtx == NULL) { goto cleanup; } } - keyCtx->mlkemParams = genCtx->mlkemParams; keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; - success = TRUE; + status = SCOSSL_SUCCESS; cleanup: - if (!success) + if (status != SCOSSL_SUCCESS) { p_scossl_mlkem_keymgmt_free_key_ctx(keyCtx); keyCtx = NULL; @@ -451,7 +530,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY if (keyCtx->classicKeyCtx != NULL) { classic_params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, &pbClassicKey, cbClassicKey); - if (keyCtx->classicKeyMgmt->getParams(keyCtx->classicKeyCtx, classic_params) != SCOSSL_SUCCESS) + if (keyCtx->classicKeymgmt->getParams(keyCtx->classicKeyCtx, classic_params) != SCOSSL_SUCCESS) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); goto cleanup; @@ -533,7 +612,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX if (keyCtx->classicKeyCtx != NULL) { classicParams[0] = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_MAX_SIZE, &cbClassicMax); - if (keyCtx->classicKeyMgmt->getParams(keyCtx->classicKeyCtx, classicParams) != SCOSSL_SUCCESS) + if (keyCtx->classicKeymgmt->getParams(keyCtx->classicKeyCtx, classicParams) != SCOSSL_SUCCESS) { return SCOSSL_FAILURE; } @@ -722,9 +801,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx return SCOSSL_FAILURE; } - keyCtx->groupName = p_scossl_mlkem_keymgmt_params_from_name(groupName, &keyCtx->mlkemParams, &classicGroupName, &keyCtx->classicKeyMgmt); - - if (keyCtx->groupName == NULL) + if (p_scossl_mlkem_keymgmt_set_group(keyCtx, keyCtx->groupName, &classicGroupName) != SCOSSL_SUCCESS) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); return SCOSSL_FAILURE; @@ -736,7 +813,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, (char *)classicGroupName, strlen(classicGroupName)), OSSL_PARAM_END}; - if (keyCtx->classicKeyMgmt->import(keyCtx->classicKeyCtx, selection, classicParams) != SCOSSL_SUCCESS) + if (keyCtx->classicKeymgmt->import(keyCtx->classicKeyCtx, selection, classicParams) != SCOSSL_SUCCESS) { return SCOSSL_FAILURE; } @@ -1085,52 +1162,53 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt return ret; } -// This function checks if groupName matches a supported MLKEM or MLKEM hybrid group name. -// If a match is found, the appropriate MLKEM parameters and classic group NID are set, -// and the constant group name is returned. + _Use_decl_annotations_ -static const char* p_scossl_mlkem_keymgmt_params_from_name(const char *groupName, - SYMCRYPT_MLKEM_PARAMS *mlkemParams, - const char **classicGroupName, - SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS **classicKeymgmt) +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_group(SCOSSL_MLKEM_KEY_CTX *keyCtx, const char *groupName, + const char **classicGroupName) { if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM512) == 0) { - *mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM512; + keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM512; + keyCtx->classicKeymgmt = NULL; + keyCtx->classicKeyexch = NULL; *classicGroupName = NULL; - *classicKeymgmt = NULL; - return SCOSSL_SN_MLKEM512; } else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM768) == 0) { - *mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; + keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; + keyCtx->classicKeymgmt = NULL; + keyCtx->classicKeyexch = NULL; *classicGroupName = NULL; - *classicKeymgmt = NULL; - return SCOSSL_SN_MLKEM768; } else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM1024) == 0) { - *mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM1024; + keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM1024; + keyCtx->classicKeymgmt = NULL; + keyCtx->classicKeyexch = NULL; *classicGroupName = NULL; - *classicKeymgmt = NULL; - return SCOSSL_SN_MLKEM1024; } else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_P256_MLKEM768) == 0) { - *mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; + keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; + keyCtx->classicKeymgmt = &p_scossl_ecc_classic_keymgmt; + keyCtx->classicKeyexch = &p_scossl_ecdh_classic_keyexch; *classicGroupName = SN_X9_62_prime256v1; - *classicKeymgmt = &p_scossl_ecc_classic_keymgmt; - return SCOSSL_SN_P256_MLKEM768; } else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_X25519_MLKEM768) == 0) { - *mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; + keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; + keyCtx->classicKeymgmt = &p_scossl_x25519_classic_keymgmt; + keyCtx->classicKeyexch = &p_scossl_ecdh_classic_keyexch; *classicGroupName = SN_X25519; - *classicKeymgmt = &p_scossl_x25519_classic_keymgmt; - return SCOSSL_SN_X25519_MLKEM768; + } + else + { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); + return SCOSSL_FAILURE; } - return NULL; + return SCOSSL_SUCCESS; } _Use_decl_annotations_ From 600c0d6b278aa8a5e5330bcf25f884773499e02f Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Wed, 11 Dec 2024 22:24:19 +0000 Subject: [PATCH 12/21] ML-KEM hybrid --- SymCryptProvider/src/kem/p_scossl_mlkem.c | 267 ++++++++++++++++-- SymCryptProvider/src/kem/p_scossl_mlkem.h | 17 +- SymCryptProvider/src/keyexch/p_scossl_ecdh.c | 10 +- .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 225 +++++---------- .../src/keymgmt/p_scossl_mlkem_keymgmt.h | 4 +- SymCryptProvider/src/p_scossl_ecc.h | 1 - 6 files changed, 329 insertions(+), 195 deletions(-) diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.c b/SymCryptProvider/src/kem/p_scossl_mlkem.c index 0647bbf2..459a13b6 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.c +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.c @@ -2,7 +2,9 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // +#include "p_scossl_base.h" #include "kem/p_scossl_mlkem.h" +#include "keyexch/p_scossl_ecdh.h" #include @@ -12,19 +14,49 @@ extern "C" { #define SYMCRYPT_MLKEM_SECRET_LENGTH 32 +typedef struct { + OSSL_FUNC_keyexch_newctx_fn *newCtx; + OSSL_FUNC_keyexch_freectx_fn *freeCtx; + OSSL_FUNC_keyexch_dupctx_fn *dupCtx; + OSSL_FUNC_keyexch_init_fn *init; + OSSL_FUNC_keyexch_set_peer_fn *setPeer; + OSSL_FUNC_keyexch_derive_fn *derive; +} SCOSSL_MLKEM_CLASSIC_KEYEXCH_FNS; + typedef struct { + // Unused by MLKEM, but forwarded to the classic key exchange + SCOSSL_PROVCTX *provCtx; + SCOSSL_MLKEM_KEY_CTX *keyCtx; int operation; + + PVOID classicKeyexchCtx; + const SCOSSL_MLKEM_CLASSIC_KEYEXCH_FNS *classicKeyexch; } SCOSSL_MLKEM_CTX; static const OSSL_PARAM p_scossl_mlkem_param_types[] = { OSSL_PARAM_END}; +static const SCOSSL_MLKEM_CLASSIC_KEYEXCH_FNS p_scossl_ecdh_classic_keyexch = { + (OSSL_FUNC_keyexch_newctx_fn *) p_scossl_ecdh_newctx, + (OSSL_FUNC_keyexch_freectx_fn *) p_scossl_ecdh_freectx, + (OSSL_FUNC_keyexch_dupctx_fn *) p_scossl_ecdh_dupctx, + (OSSL_FUNC_keyexch_init_fn *) p_scossl_ecdh_init, + (OSSL_FUNC_keyexch_set_peer_fn *) p_scossl_ecdh_set_peer, + (OSSL_FUNC_keyexch_derive_fn *) p_scossl_ecdh_derive}; + /* Context management */ static SCOSSL_MLKEM_CTX *p_scossl_mlkem_newctx(ossl_unused void *provctx) { - return OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_CTX)); + SCOSSL_MLKEM_CTX *ctx = OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_CTX)); + + if (ctx != NULL) + { + ctx->provCtx = provctx; + } + + return ctx; } static void p_scossl_mlkem_freectx(_Inout_ SCOSSL_MLKEM_CTX *ctx) @@ -32,6 +64,11 @@ static void p_scossl_mlkem_freectx(_Inout_ SCOSSL_MLKEM_CTX *ctx) if (ctx == NULL) return; + if (ctx->classicKeyexch != NULL) + { + ctx->classicKeyexch->freeCtx(ctx->classicKeyexchCtx); + } + OPENSSL_free(ctx); } @@ -43,11 +80,45 @@ static SCOSSL_MLKEM_CTX *p_scossl_mlkem_dupctx(_In_ SCOSSL_MLKEM_CTX *ctx) { copyCtx->keyCtx = ctx->keyCtx; copyCtx->operation = ctx->operation; + copyCtx->provCtx = ctx->provCtx; + copyCtx->classicKeyexch = ctx->classicKeyexch; + + if (ctx->classicKeyexchCtx != NULL) + { + if (copyCtx->classicKeyexch != NULL && + (copyCtx->classicKeyexchCtx = copyCtx->classicKeyexch->dupCtx(ctx->classicKeyexchCtx)) == NULL) + { + OPENSSL_free(copyCtx); + copyCtx = NULL; + } + } + else + { + copyCtx->classicKeyexchCtx = NULL; + } } return copyCtx; } +static SCOSSL_STATUS p_scossl_mlkem_classic_keyexch_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, PVOID classicKeyCtx) +{ + ctx->classicKeyexch = &p_scossl_ecdh_classic_keyexch; + + if ((ctx->classicKeyexchCtx = ctx->classicKeyexch->newCtx(ctx->provCtx)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return SCOSSL_FAILURE; + } + + if (ctx->classicKeyexch->init(ctx->classicKeyexchCtx, classicKeyCtx, NULL) != SCOSSL_SUCCESS) + { + return SCOSSL_FAILURE; + } + + return SCOSSL_SUCCESS; +} + static SCOSSL_STATUS p_scossl_mlkem_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, _In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int operation) { @@ -78,65 +149,137 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate_init(_Inout_ SCOSSL_MLKEM_CTX *c return p_scossl_mlkem_init(ctx, keyCtx, EVP_PKEY_OP_ENCAPSULATE); } +// Export secret = PEER || MLKEM secret, out = ECDH secret || MLKEM CT +// Generate ECDH private key static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, _Out_writes_bytes_opt_(*outlen) unsigned char *out, _Out_ size_t *outlen, _Out_writes_bytes_(*secretlen) unsigned char *secret, _Out_ size_t *secretlen) { - SIZE_T cbSecret; - SIZE_T cbCipherText; + SIZE_T cbClassicKeyPublic = 0; + SIZE_T cbMlkemCiphertext = 0; + SIZE_T cbClassicSecret = 0; + PVOID classicKeygenCtx = NULL; + PVOID classicKeyCtxPrivate = NULL; + const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS *classicKeymgmt = ctx->keyCtx->classicKeymgmt; + OSSL_PARAM classicKeyexchParams[2]; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + SCOSSL_STATUS ret = SCOSSL_FAILURE; if (ctx->keyCtx == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); - return SCOSSL_FAILURE; + goto cleanup; } if (ctx->operation != EVP_PKEY_OP_ENCAPSULATE) { ERR_raise(ERR_LIB_PROV, ERR_R_OPERATION_FAIL); - return SCOSSL_FAILURE; + goto cleanup; } - scError = SymCryptMlKemSizeofCiphertextFromParams(ctx->keyCtx->mlkemParams, &cbCipherText); - if (scError != SYMCRYPT_NO_ERROR) + if (ctx->classicKeyexch != NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - return SCOSSL_FAILURE; + if (ctx->keyCtx->classicKeyCtx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + // Get key size + cbClassicKeyPublic = p_scossl_ecc_get_encoded_key_size(ctx->keyCtx->classicKeyCtx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); + + // Get secret size + if (ctx->classicKeyexch->derive(ctx->keyCtx->classicKeyCtx, NULL, &cbClassicSecret, 0) != SCOSSL_SUCCESS) + { + goto cleanup; + } } - if (ctx->keyCtx->classicKeyCtx != NULL) + scError = SymCryptMlKemSizeofCiphertextFromParams(ctx->keyCtx->mlkemParams, &cbMlkemCiphertext); + if (scError != SYMCRYPT_NO_ERROR) { - + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; } if (out != NULL) { - scError = SymCryptMlKemEncapsulate(ctx->keyCtx->key, secret, SYMCRYPT_MLKEM_SECRET_LENGTH, out, cbCipherText); + if ((outlen != NULL && *outlen < cbClassicKeyPublic + cbMlkemCiphertext) || + (secretlen != NULL && *secretlen < cbClassicSecret + SYMCRYPT_MLKEM_SECRET_LENGTH)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + goto cleanup; + } + if (ctx->keyCtx->classicKeyCtx != NULL) + { + classicKeyexchParams[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, out, cbClassicKeyPublic); + classicKeyexchParams[1] = OSSL_PARAM_construct_end(); + + if (classicKeymgmt == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + // Generate ephemeral ECDH key + if ((classicKeygenCtx = classicKeymgmt->genInit(ctx->provCtx, OSSL_KEYMGMT_SELECT_ALL, NULL)) == NULL || + classicKeymgmt->setTemplate(classicKeygenCtx, ctx->keyCtx->classicKeyCtx) != SCOSSL_SUCCESS || + (classicKeyCtxPrivate = classicKeymgmt->gen(classicKeygenCtx, NULL, NULL)) == NULL) + { + goto cleanup; + } + + // Write encoded public key bytes + if ((classicKeymgmt->getParams(classicKeyCtxPrivate, classicKeyexchParams)) != SCOSSL_SUCCESS) + { + goto cleanup; + } + out += cbClassicKeyPublic; + + // Derive ECDH secret + if (p_scossl_mlkem_classic_keyexch_init(ctx, classicKeyCtxPrivate) != SCOSSL_SUCCESS || + ctx->classicKeyexch->setPeer(ctx->classicKeyexchCtx, ctx->keyCtx->classicKeyCtx) != SCOSSL_SUCCESS || + ctx->classicKeyexch->derive(ctx->classicKeyexchCtx, secret, &cbClassicSecret, 0) != SCOSSL_SUCCESS) + { + goto cleanup; + } + secret += cbClassicSecret; + } + + scError = SymCryptMlKemEncapsulate(ctx->keyCtx->key, secret, SYMCRYPT_MLKEM_SECRET_LENGTH, out, cbMlkemCiphertext); if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - return SCOSSL_FAILURE; + goto cleanup; } } - else if (outlen == NULL && secretlen != NULL) + else if (outlen == NULL && secretlen == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); - return SCOSSL_FAILURE; + goto cleanup; } if (outlen != NULL) { - *outlen = cbCipherText; + *outlen = cbClassicKeyPublic + cbMlkemCiphertext; } if (secretlen != NULL) { - *secretlen = SYMCRYPT_MLKEM_SECRET_LENGTH; + *secretlen = cbClassicSecret + SYMCRYPT_MLKEM_SECRET_LENGTH; } - return SCOSSL_SUCCESS; + ret = SCOSSL_SUCCESS; + +cleanup: + if (classicKeymgmt != NULL) + { + classicKeymgmt->free(classicKeyCtxPrivate); + classicKeymgmt->genCleanup(classicKeygenCtx); + } + + return ret; } // @@ -145,56 +288,114 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, static SCOSSL_STATUS p_scossl_mlkem_decapsulate_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, _In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, ossl_unused const OSSL_PARAM params[]) { - return p_scossl_mlkem_init(ctx, keyCtx, EVP_PKEY_OP_DECAPSULATE); + return p_scossl_mlkem_init(ctx, keyCtx, EVP_PKEY_OP_DECAPSULATE) && + (ctx->keyCtx->classicKeyCtx != NULL || p_scossl_mlkem_classic_keyexch_init(ctx, ctx->keyCtx->classicKeyCtx)); } +// Set peer, derive ECDH || MLKEM CT static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, _Out_writes_bytes_opt_(*outlen) unsigned char *out, _Out_ size_t *outlen, _In_reads_bytes_(inlen) const unsigned char *in, size_t inlen) { - SIZE_T cbCipherText; + SIZE_T cbClassicKeyPublic = 0; + SIZE_T cbMlkemCiphertext = 0; + SIZE_T cbClassicSecret = 0; + PVOID classicKeyCtxPublic = NULL; + const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS *classicKeymgmt = ctx->keyCtx->classicKeymgmt; + OSSL_PARAM classicKeyexchParams[2]; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + SCOSSL_STATUS ret = SCOSSL_FAILURE; if (ctx->keyCtx == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); - return SCOSSL_FAILURE; + goto cleanup; } if (ctx->operation != EVP_PKEY_OP_DECAPSULATE) { ERR_raise(ERR_LIB_PROV, ERR_R_OPERATION_FAIL); - return SCOSSL_FAILURE; + goto cleanup; } - scError = SymCryptMlKemSizeofCiphertextFromParams(ctx->keyCtx->mlkemParams, &cbCipherText); + if (ctx->classicKeyexch != NULL) + { + if (ctx->keyCtx->classicKeyCtx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + // Get key size + cbClassicKeyPublic = p_scossl_ecc_get_encoded_key_size(ctx->keyCtx->classicKeyCtx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); + + // Get secret size + if (ctx->classicKeyexch->derive(ctx->keyCtx->classicKeyCtx, NULL, &cbClassicSecret, 0) != SCOSSL_SUCCESS) + { + goto cleanup; + } + } + scError = SymCryptMlKemSizeofCiphertextFromParams(ctx->keyCtx->mlkemParams, &cbMlkemCiphertext); if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - return SCOSSL_FAILURE; + goto cleanup; } - if (inlen != cbCipherText) + if (inlen != cbClassicKeyPublic + cbMlkemCiphertext) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH); - return SCOSSL_FAILURE; + goto cleanup; } if (out != NULL) { + if (outlen != NULL && *outlen < SYMCRYPT_MLKEM_SECRET_LENGTH) + { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + goto cleanup; + } + + if (ctx->classicKeyexch != NULL) + { + // Extract ECDH public key from in + classicKeyexchParams[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, (void *)in, cbClassicKeyPublic); + classicKeyexchParams[1] = OSSL_PARAM_construct_end(); + + if ((classicKeyCtxPublic = classicKeymgmt->new(ctx->provCtx)) == NULL || + classicKeymgmt->setParams(classicKeyCtxPublic, classicKeyexchParams) != SCOSSL_SUCCESS) + { + goto cleanup; + } + in += cbClassicKeyPublic; + + // Set ECDH peer + if (ctx->classicKeyexch->setPeer(ctx->classicKeyexchCtx, classicKeyCtxPublic) != SCOSSL_SUCCESS) + { + goto cleanup; + } + // Derive shared ECDH secret + if (ctx->classicKeyexch->setPeer(ctx->classicKeyexchCtx, classicKeyCtxPublic) != SCOSSL_SUCCESS || + ctx->classicKeyexch->derive(ctx->classicKeyexchCtx, out, &cbClassicSecret, 0) != SCOSSL_SUCCESS) + { + goto cleanup; + } + out += cbClassicSecret; + } + scError = SymCryptMlKemDecapsulate(ctx->keyCtx->key, in, inlen, out, SYMCRYPT_MLKEM_SECRET_LENGTH); if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - return SCOSSL_FAILURE; + goto cleanup; } } else if (outlen == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); - return SCOSSL_FAILURE; + goto cleanup; } if (outlen != NULL) @@ -202,7 +403,15 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, *outlen = SYMCRYPT_MLKEM_SECRET_LENGTH; } - return SCOSSL_SUCCESS; + ret = SCOSSL_SUCCESS; + +cleanup: + if (classicKeymgmt != NULL) + { + classicKeymgmt->free(classicKeyCtxPublic); + } + + return ret; } // diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.h b/SymCryptProvider/src/kem/p_scossl_mlkem.h index 3990a077..ed3b310f 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.h +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.h @@ -2,7 +2,7 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // -#include "scossl_helpers.h" +#include "p_scossl_base.h" #include "p_scossl_ecc.h" #ifdef __cplusplus @@ -10,6 +10,10 @@ extern "C" { #endif typedef struct { + OSSL_FUNC_keymgmt_gen_cleanup_fn *genCleanup; + OSSL_FUNC_keymgmt_gen_init_fn *genInit; + OSSL_FUNC_keymgmt_gen_set_template_fn *setTemplate; + OSSL_FUNC_keymgmt_gen_fn *gen; OSSL_FUNC_keymgmt_new_fn *new; OSSL_FUNC_keymgmt_free_fn *free; OSSL_FUNC_keymgmt_dup_fn *dup; @@ -23,23 +27,16 @@ typedef struct { } SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS; typedef struct { - OSSL_FUNC_keyexch_newctx_fn *newCtx; - OSSL_FUNC_keyexch_freectx_fn *freeCtx; - OSSL_FUNC_keyexch_dupctx_fn *dupCtx; - OSSL_FUNC_keyexch_init_fn *init; - OSSL_FUNC_keyexch_set_peer_fn *setPeer; - OSSL_FUNC_keyexch_derive_fn *derive; -} SCOSSL_MLKEM_CLASSIC_KEYEXCH_FNS; + SCOSSL_PROVCTX *provCtx; -typedef struct { const char *groupName; PSYMCRYPT_MLKEMKEY key; SYMCRYPT_MLKEM_PARAMS mlkemParams; SYMCRYPT_MLKEMKEY_FORMAT format; + const char *classicGroupName; SCOSSL_ECC_KEY_CTX *classicKeyCtx; const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS *classicKeymgmt; - const SCOSSL_MLKEM_CLASSIC_KEYEXCH_FNS *classicKeyexch; } SCOSSL_MLKEM_KEY_CTX; #ifdef __cplusplus diff --git a/SymCryptProvider/src/keyexch/p_scossl_ecdh.c b/SymCryptProvider/src/keyexch/p_scossl_ecdh.c index 8020d23c..65f5f128 100644 --- a/SymCryptProvider/src/keyexch/p_scossl_ecdh.c +++ b/SymCryptProvider/src/keyexch/p_scossl_ecdh.c @@ -109,11 +109,6 @@ SCOSSL_STATUS p_scossl_ecdh_derive(SCOSSL_ECDH_CTX *ctx, return SCOSSL_FAILURE; } - if (ctx->keyCtx == NULL || ctx->peerKeyCtx == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); - return SCOSSL_FAILURE; - } - cbSecretBuf = SymCryptEckeySizeofPublicKey(ctx->keyCtx->key, SYMCRYPT_ECPOINT_FORMAT_X); if (secret == NULL) { @@ -121,6 +116,11 @@ SCOSSL_STATUS p_scossl_ecdh_derive(SCOSSL_ECDH_CTX *ctx, return SCOSSL_SUCCESS; } + if (ctx->keyCtx == NULL || ctx->peerKeyCtx == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + return SCOSSL_FAILURE; + } + if (outlen < cbSecretBuf) { if ((pbSecretBuf = OPENSSL_secure_malloc(cbSecretBuf)) == NULL) diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index 2580c515..6c93347d 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -3,10 +3,8 @@ // #include "scossl_provider.h" -#include "p_scossl_base.h" #include "kem/p_scossl_mlkem.h" #include "keymgmt/p_scossl_mlkem_keymgmt.h" -#include "keyexch/p_scossl_ecdh.h" #include "keymgmt/p_scossl_ecc_keymgmt.h" #include @@ -17,21 +15,6 @@ extern "C" { #endif -typedef struct { - OSSL_FUNC_keymgmt_gen_cleanup_fn *genCleanup; - OSSL_FUNC_keymgmt_gen_init_fn *genInit; - OSSL_FUNC_keymgmt_gen_set_template_fn *setTemplate; - OSSL_FUNC_keymgmt_gen_fn *gen; -} SCOSSL_MLKEM_CLASSIC_KEYGEN_FNS; - -typedef struct { - SCOSSL_PROVCTX *provCtx; - const char *groupName; - - PVOID classicKeygenCtx; - const SCOSSL_MLKEM_CLASSIC_KEYGEN_FNS *classicKeygen; -} SCOSSL_MLKEM_KEYGEN_CTX; - #define SCOSSL_MLKEM_PKEY_PARAMETER_TYPES \ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), \ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \ @@ -76,57 +59,51 @@ static const OSSL_PARAM *p_scossl_mlkem_impexp_types[] = { p_scossl_mlkem_pkey_types, p_scossl_mlkem_all_types}; -static const SCOSSL_MLKEM_CLASSIC_KEYGEN_FNS p_scossl_ecc_classic_keygen = { +static const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS p_scossl_ecc_classic_keymgmt = { (OSSL_FUNC_keymgmt_gen_cleanup_fn *) p_scossl_ecc_keygen_cleanup, (OSSL_FUNC_keymgmt_gen_init_fn *) p_scossl_ecc_keygen_init, (OSSL_FUNC_keymgmt_gen_set_template_fn *) p_scossl_ecc_keygen_set_template, - (OSSL_FUNC_keymgmt_gen_fn *) p_scossl_ecc_keygen}; + (OSSL_FUNC_keymgmt_gen_fn *) p_scossl_ecc_keygen, + (OSSL_FUNC_keymgmt_new_fn *) p_scossl_ecc_keymgmt_new_ctx, + (OSSL_FUNC_keymgmt_free_fn *) p_scossl_ecc_keymgmt_free_ctx, + (OSSL_FUNC_keymgmt_dup_fn *) p_scossl_ecc_keymgmt_dup_ctx, + (OSSL_FUNC_keymgmt_get_params_fn *) p_scossl_ecc_keymgmt_get_params, + (OSSL_FUNC_keymgmt_set_params_fn *) p_scossl_ecc_keymgmt_set_params, + (OSSL_FUNC_keymgmt_has_fn *) p_scossl_ecc_keymgmt_has, + (OSSL_FUNC_keymgmt_match_fn *) p_scossl_ecc_keymgmt_match, + (OSSL_FUNC_keymgmt_import_fn *) p_scossl_ecc_keymgmt_import, + (OSSL_FUNC_keymgmt_export_fn *) p_scossl_ecc_keymgmt_export, + (OSSL_FUNC_keymgmt_validate_fn *) p_scossl_ecc_keymgmt_validate}; -static const SCOSSL_MLKEM_CLASSIC_KEYGEN_FNS p_scossl_x25519_classic_keygen = { +static const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS p_scossl_x25519_classic_keymgmt = { (OSSL_FUNC_keymgmt_gen_cleanup_fn *) p_scossl_ecc_keygen_cleanup, (OSSL_FUNC_keymgmt_gen_init_fn *) p_scossl_x25519_keygen_init, (OSSL_FUNC_keymgmt_gen_set_template_fn *) p_scossl_ecc_keygen_set_template, - (OSSL_FUNC_keymgmt_gen_fn *) p_scossl_ecc_keygen}; - -static const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS p_scossl_ecc_classic_keymgmt = { - (OSSL_FUNC_keymgmt_new_fn *) p_scossl_ecc_keymgmt_new_ctx, - (OSSL_FUNC_keymgmt_free_fn *) p_scossl_ecc_keymgmt_free_ctx, - (OSSL_FUNC_keymgmt_dup_fn *) p_scossl_ecc_keymgmt_dup_ctx, - (OSSL_FUNC_keymgmt_get_params_fn *) p_scossl_ecc_keymgmt_get_params, - (OSSL_FUNC_keymgmt_set_params_fn *) p_scossl_ecc_keymgmt_set_params, - (OSSL_FUNC_keymgmt_has_fn *) p_scossl_ecc_keymgmt_has, - (OSSL_FUNC_keymgmt_match_fn *) p_scossl_ecc_keymgmt_match, - (OSSL_FUNC_keymgmt_import_fn *) p_scossl_ecc_keymgmt_import, - (OSSL_FUNC_keymgmt_export_fn *) p_scossl_ecc_keymgmt_export, - (OSSL_FUNC_keymgmt_validate_fn *) p_scossl_ecc_keymgmt_validate}; - -static const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS p_scossl_x25519_classic_keymgmt = { - (OSSL_FUNC_keymgmt_new_fn *) p_scossl_x25519_keymgmt_new_ctx, - (OSSL_FUNC_keymgmt_free_fn *) p_scossl_ecc_keymgmt_free_ctx, - (OSSL_FUNC_keymgmt_dup_fn *) p_scossl_ecc_keymgmt_dup_ctx, - (OSSL_FUNC_keymgmt_get_params_fn *) p_scossl_ecc_keymgmt_get_params, - (OSSL_FUNC_keymgmt_set_params_fn *) p_scossl_ecc_keymgmt_set_params, - (OSSL_FUNC_keymgmt_has_fn *) p_scossl_ecc_keymgmt_has, - (OSSL_FUNC_keymgmt_match_fn *) p_scossl_ecc_keymgmt_match, - (OSSL_FUNC_keymgmt_import_fn *) p_scossl_x25519_keymgmt_import, - (OSSL_FUNC_keymgmt_export_fn *) p_scossl_x25519_keymgmt_export, - (OSSL_FUNC_keymgmt_validate_fn *) p_scossl_ecc_keymgmt_validate}; - -static const SCOSSL_MLKEM_CLASSIC_KEYEXCH_FNS p_scossl_ecdh_classic_keyexch = { - (OSSL_FUNC_keyexch_newctx_fn *) p_scossl_ecdh_newctx, - (OSSL_FUNC_keyexch_freectx_fn *) p_scossl_ecdh_freectx, - (OSSL_FUNC_keyexch_dupctx_fn *) p_scossl_ecdh_dupctx, - (OSSL_FUNC_keyexch_init_fn *) p_scossl_ecdh_init, - (OSSL_FUNC_keyexch_set_peer_fn *) p_scossl_ecdh_set_peer, - (OSSL_FUNC_keyexch_derive_fn *) p_scossl_ecdh_derive}; - -static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_group(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, _In_ const char *groupName, - _Out_ const char **classicGroupName); + (OSSL_FUNC_keymgmt_gen_fn *) p_scossl_ecc_keygen, + (OSSL_FUNC_keymgmt_new_fn *) p_scossl_x25519_keymgmt_new_ctx, + (OSSL_FUNC_keymgmt_free_fn *) p_scossl_ecc_keymgmt_free_ctx, + (OSSL_FUNC_keymgmt_dup_fn *) p_scossl_ecc_keymgmt_dup_ctx, + (OSSL_FUNC_keymgmt_get_params_fn *) p_scossl_ecc_keymgmt_get_params, + (OSSL_FUNC_keymgmt_set_params_fn *) p_scossl_ecc_keymgmt_set_params, + (OSSL_FUNC_keymgmt_has_fn *) p_scossl_ecc_keymgmt_has, + (OSSL_FUNC_keymgmt_match_fn *) p_scossl_ecc_keymgmt_match, + (OSSL_FUNC_keymgmt_import_fn *) p_scossl_x25519_keymgmt_import, + (OSSL_FUNC_keymgmt_export_fn *) p_scossl_x25519_keymgmt_export, + (OSSL_FUNC_keymgmt_validate_fn *) p_scossl_ecc_keymgmt_validate}; + +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_group(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, _In_ const char *groupName); static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx); -SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(ossl_unused void *provCtx) +SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(_In_ SCOSSL_PROVCTX *provCtx) { - return OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_KEY_CTX));; + SCOSSL_MLKEM_KEY_CTX *keyCtx = OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_KEY_CTX)); + + if (keyCtx != NULL) + { + keyCtx->provCtx = provCtx; + } + + return keyCtx; } void p_scossl_mlkem_keymgmt_free_key_ctx(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx) @@ -157,10 +134,14 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS if (copyCtx != NULL) { + copyCtx->provCtx = keyCtx->provCtx; + copyCtx->classicKeymgmt = keyCtx->classicKeymgmt; + if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { copyCtx->groupName = keyCtx->groupName; copyCtx->mlkemParams = keyCtx->mlkemParams; + copyCtx->classicGroupName = keyCtx->classicGroupName; } if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 && keyCtx->key != NULL) @@ -204,7 +185,6 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS if (keyCtx->classicKeyCtx != NULL) { - copyCtx->classicKeymgmt = keyCtx->classicKeymgmt; copyCtx->classicKeyCtx = keyCtx->classicKeymgmt->dup(keyCtx->classicKeyCtx, selection); } } @@ -224,46 +204,7 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS return copyCtx; } -// -// Key Generation -// -static SCOSSL_STATUS p_scossl_mlkem_keygen_set_group(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ const char *groupName) -{ - if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM512) == 0) - { - genCtx->groupName = SCOSSL_SN_MLKEM512; - genCtx->classicKeygen = NULL; - } - else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM768) == 0) - { - genCtx->groupName = SCOSSL_SN_MLKEM768; - genCtx->classicKeygen = NULL; - } - else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM1024) == 0) - { - genCtx->groupName = SCOSSL_SN_MLKEM1024; - genCtx->classicKeygen = NULL; - } - else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_P256_MLKEM768) == 0) - { - genCtx->groupName = SCOSSL_SN_P256_MLKEM768; - genCtx->classicKeygen = &p_scossl_ecc_classic_keygen; - } - else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_X25519_MLKEM768) == 0) - { - genCtx->groupName = SCOSSL_SN_X25519_MLKEM768; - genCtx->classicKeygen = &p_scossl_x25519_classic_keygen; - } - else - { - ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); - return SCOSSL_FAILURE; - } - - return SCOSSL_SUCCESS; -} - -static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ const OSSL_PARAM params[]) +static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEY_CTX *genCtx, _In_ const OSSL_PARAM params[]) { const OSSL_PARAM *p; if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL) @@ -276,7 +217,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEYGE return SCOSSL_FAILURE; } - if (p_scossl_mlkem_keygen_set_group(genCtx, groupName) != SCOSSL_SUCCESS) + if (p_scossl_mlkem_keymgmt_set_group(genCtx, groupName) != SCOSSL_SUCCESS) { ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); return SCOSSL_FAILURE; @@ -291,42 +232,32 @@ static const OSSL_PARAM *p_scossl_mlkem_keygen_settable_params(ossl_unused void return p_scossl_mlkem_keygen_settable_param_types; } -static void p_scossl_mlkem_keygen_cleanup(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx) +static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen_init(_In_ SCOSSL_PROVCTX *provCtx, ossl_unused int selection, + _In_ const OSSL_PARAM params[]) { - if (genCtx == NULL) - return; - - if (genCtx->classicKeygenCtx != NULL) - { - genCtx->classicKeygen->genCleanup(genCtx->classicKeygenCtx); - } - - OPENSSL_free(genCtx); -} - -static SCOSSL_MLKEM_KEYGEN_CTX *p_scossl_mlkem_keygen_init(ossl_unused void *provCtx, ossl_unused int selection, - _In_ const OSSL_PARAM params[]) -{ - SCOSSL_MLKEM_KEYGEN_CTX *genCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEYGEN_CTX)); + SCOSSL_STATUS status = SCOSSL_FAILURE; + SCOSSL_MLKEM_KEY_CTX *genCtx = p_scossl_mlkem_keymgmt_new_ctx(provCtx); if (genCtx != NULL) { - genCtx->provCtx = provCtx; - genCtx->groupName = SCOSSL_SN_MLKEM768; - genCtx->classicKeygenCtx = NULL; - genCtx->classicKeygen = NULL; + status = p_scossl_mlkem_keygen_set_params(genCtx, params); - if (p_scossl_mlkem_keygen_set_params(genCtx, params) != SCOSSL_SUCCESS) + if (status == SCOSSL_SUCCESS && genCtx->groupName == NULL) { - OPENSSL_free(genCtx); - return NULL; + status = p_scossl_mlkem_keymgmt_set_group(genCtx, SCOSSL_SN_MLKEM768); } } + if (status != SCOSSL_SUCCESS) + { + p_scossl_mlkem_keymgmt_free_key_ctx(genCtx); + genCtx = NULL; + } + return genCtx; } -static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ SCOSSL_MLKEM_KEY_CTX *tmplCtx) +static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEY_CTX *genCtx, _In_ SCOSSL_MLKEM_KEY_CTX *tmplCtx) { if (genCtx == NULL || tmplCtx == NULL) @@ -341,7 +272,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEY return SCOSSL_FAILURE; } - if (p_scossl_mlkem_keygen_set_group(genCtx, tmplCtx->groupName) != SCOSSL_SUCCESS) + if (p_scossl_mlkem_keymgmt_set_group(genCtx, tmplCtx->groupName) != SCOSSL_SUCCESS) { ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); return SCOSSL_FAILURE; @@ -350,15 +281,14 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEY return SCOSSL_SUCCESS; } -static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ OSSL_CALLBACK *cb, _In_ void *cbarg) +static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEY_CTX *genCtx, _In_ OSSL_CALLBACK *cb, _In_ void *cbarg) { - const char *classicGroupName; + PVOID classicKeygenCtx = NULL; SCOSSL_MLKEM_KEY_CTX *keyCtx; SCOSSL_STATUS status = SCOSSL_FAILURE; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; - if ((keyCtx = p_scossl_mlkem_keymgmt_new_ctx(NULL)) == NULL || - p_scossl_mlkem_keymgmt_set_group(keyCtx, genCtx->groupName, &classicGroupName) != SCOSSL_SUCCESS || + if ((keyCtx = p_scossl_mlkem_keymgmt_dup_key_ctx(genCtx, OSSL_KEYMGMT_SELECT_ALL)) == NULL || (keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->mlkemParams)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); @@ -372,19 +302,19 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX goto cleanup; } - if (genCtx->classicKeygen != NULL) + if (keyCtx->classicGroupName != NULL) { OSSL_PARAM classicParams[2] = { - OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, (char *)classicGroupName, strlen(classicGroupName)), + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, (char *)keyCtx->classicGroupName, strlen(keyCtx->classicGroupName)), OSSL_PARAM_END}; - genCtx->classicKeygenCtx = genCtx->classicKeygen->genInit(genCtx->provCtx, 0, classicParams); - if (genCtx->classicKeygenCtx == NULL) + classicKeygenCtx = keyCtx->classicKeymgmt->genInit(keyCtx->provCtx, 0, classicParams); + if (classicKeygenCtx == NULL) { goto cleanup; } - keyCtx->classicKeyCtx = genCtx->classicKeygen->gen(genCtx->classicKeygenCtx, cb, cbarg); + keyCtx->classicKeyCtx = keyCtx->classicKeymgmt->gen(classicKeygenCtx, cb, cbarg); if (keyCtx->classicKeyCtx == NULL) { goto cleanup; @@ -402,6 +332,11 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX keyCtx = NULL; } + if (classicKeygenCtx != NULL) + { + genCtx->classicKeymgmt->genCleanup(classicKeygenCtx); + } + return keyCtx; } @@ -801,7 +736,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx return SCOSSL_FAILURE; } - if (p_scossl_mlkem_keymgmt_set_group(keyCtx, keyCtx->groupName, &classicGroupName) != SCOSSL_SUCCESS) + if (p_scossl_mlkem_keymgmt_set_group(keyCtx, keyCtx->groupName) != SCOSSL_SUCCESS) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); return SCOSSL_FAILURE; @@ -967,7 +902,7 @@ const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[] = { {OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))p_scossl_mlkem_keymgmt_free_key_ctx}, {OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))p_scossl_mlkem_keygen_set_params}, {OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (void (*)(void))p_scossl_mlkem_keygen_settable_params}, - {OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))p_scossl_mlkem_keygen_cleanup}, + {OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))p_scossl_mlkem_keymgmt_free_key_ctx}, {OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))p_scossl_mlkem_keygen_init}, {OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))p_scossl_mlkem_keygen_set_template}, {OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))p_scossl_mlkem_keygen}, @@ -1164,43 +1099,37 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt _Use_decl_annotations_ -static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_group(SCOSSL_MLKEM_KEY_CTX *keyCtx, const char *groupName, - const char **classicGroupName) +static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_group(SCOSSL_MLKEM_KEY_CTX *keyCtx, const char *groupName) { if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM512) == 0) { keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM512; keyCtx->classicKeymgmt = NULL; - keyCtx->classicKeyexch = NULL; - *classicGroupName = NULL; + keyCtx->classicGroupName = NULL; } else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM768) == 0) { keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; keyCtx->classicKeymgmt = NULL; - keyCtx->classicKeyexch = NULL; - *classicGroupName = NULL; + keyCtx->classicGroupName = NULL; } else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM1024) == 0) { keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM1024; keyCtx->classicKeymgmt = NULL; - keyCtx->classicKeyexch = NULL; - *classicGroupName = NULL; + keyCtx->classicGroupName = NULL; } else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_P256_MLKEM768) == 0) { keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; keyCtx->classicKeymgmt = &p_scossl_ecc_classic_keymgmt; - keyCtx->classicKeyexch = &p_scossl_ecdh_classic_keyexch; - *classicGroupName = SN_X9_62_prime256v1; + keyCtx->classicGroupName = SN_X9_62_prime256v1; } else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_X25519_MLKEM768) == 0) { keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; keyCtx->classicKeymgmt = &p_scossl_x25519_classic_keymgmt; - keyCtx->classicKeyexch = &p_scossl_ecdh_classic_keyexch; - *classicGroupName = SN_X25519; + keyCtx->classicGroupName = SN_X25519; } else { diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h index 67d6f771..bb51dc70 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h @@ -2,13 +2,13 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // -#include "scossl_helpers.h" +#include "p_scossl_base.h" #ifdef __cplusplus extern "C" { #endif -SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(ossl_unused void *provCtx); +SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(_In_ SCOSSL_PROVCTX *provCtx); void p_scossl_mlkem_keymgmt_free_key_ctx(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx); SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]); diff --git a/SymCryptProvider/src/p_scossl_ecc.h b/SymCryptProvider/src/p_scossl_ecc.h index 25aba800..81e572e3 100644 --- a/SymCryptProvider/src/p_scossl_ecc.h +++ b/SymCryptProvider/src/p_scossl_ecc.h @@ -43,7 +43,6 @@ typedef struct { SIZE_T p_scossl_ecc_get_encoded_key_size(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection); SCOSSL_STATUS p_scossl_ecc_get_encoded_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, _Out_writes_bytes_(*pcbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); - SCOSSL_STATUS p_scossl_ecc_set_encoded_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, _In_reads_bytes_opt_(cbEncodedPublicKey) PCBYTE pbEncodedPublicKey, SIZE_T cbEncodedPublicKey, _In_reads_bytes_opt_(cbPrivateKey) PCBYTE pbPrivateKey, SIZE_T cbPrivateKey); From 62ae32d779a579a7efabfe9905ac9fc2c6e2ef9f Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Fri, 20 Dec 2024 19:16:05 +0000 Subject: [PATCH 13/21] Cleanup ecc usage from mlkem keymgmt --- ScosslCommon/inc/scossl_ecc.h | 1 + ScosslCommon/src/scossl_ecc.c | 22 +- SymCryptProvider/inc/scossl_provider.h | 6 +- .../src/decoder/p_scossl_decode_common.c | 2 +- .../src/decoder/p_scossl_decode_common.h | 6 +- .../src/decoder/p_scossl_decode_mlkem.c | 162 ++++------- .../src/encoder/p_scossl_encode_mlkem.c | 46 +-- SymCryptProvider/src/kem/p_scossl_mlkem.c | 69 ++--- SymCryptProvider/src/kem/p_scossl_mlkem.h | 18 -- .../src/keymgmt/p_scossl_ecc_keymgmt.c | 222 ++------------ .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 179 ++++-------- .../src/keymgmt/p_scossl_mlkem_keymgmt.h | 2 + SymCryptProvider/src/p_scossl_base.c | 4 +- SymCryptProvider/src/p_scossl_ecc.c | 270 +++++++++++++++++- SymCryptProvider/src/p_scossl_ecc.h | 12 +- 15 files changed, 450 insertions(+), 571 deletions(-) diff --git a/ScosslCommon/inc/scossl_ecc.h b/ScosslCommon/inc/scossl_ecc.h index 711738ac..21826351 100644 --- a/ScosslCommon/inc/scossl_ecc.h +++ b/ScosslCommon/inc/scossl_ecc.h @@ -16,6 +16,7 @@ void scossl_ecc_destroy_ecc_curves(); // x25519 is a separate interface in the provider and not supported in the // engine, so there's no need to fetch the hidden group from an EC_GROUP. +PCSYMCRYPT_ECURVE scossl_ecc_nid_to_symcrypt_curve(int groupNid); PCSYMCRYPT_ECURVE scossl_ecc_group_to_symcrypt_curve(_In_ const EC_GROUP *group); PCSYMCRYPT_ECURVE scossl_ecc_get_x25519_curve(); EC_GROUP *scossl_ecc_symcrypt_curve_to_ecc_group(_In_ PCSYMCRYPT_ECURVE pCurve); diff --git a/ScosslCommon/src/scossl_ecc.c b/ScosslCommon/src/scossl_ecc.c index a2d745ab..9c5f1a9a 100644 --- a/ScosslCommon/src/scossl_ecc.c +++ b/ScosslCommon/src/scossl_ecc.c @@ -78,14 +78,8 @@ void scossl_ecc_destroy_ecc_curves() } } -_Use_decl_annotations_ -PCSYMCRYPT_ECURVE scossl_ecc_group_to_symcrypt_curve(const EC_GROUP *group) +PCSYMCRYPT_ECURVE scossl_ecc_nid_to_symcrypt_curve(int groupNid) { - if (group == NULL) - return NULL; - - int groupNid = EC_GROUP_get_curve_name(group); - // Only reroute NIST Prime curves to SymCrypt for now switch (groupNid) { @@ -107,6 +101,15 @@ PCSYMCRYPT_ECURVE scossl_ecc_group_to_symcrypt_curve(const EC_GROUP *group) return NULL; } +_Use_decl_annotations_ +PCSYMCRYPT_ECURVE scossl_ecc_group_to_symcrypt_curve(const EC_GROUP *group) +{ + if (group == NULL) + return NULL; + + return scossl_ecc_nid_to_symcrypt_curve(EC_GROUP_get_curve_name(group)); +} + PCSYMCRYPT_ECURVE scossl_ecc_get_x25519_curve() { return _hidden_curve_X25519; @@ -535,6 +538,11 @@ static SCOSSL_STATUS scossl_ecdsa_apply_der(_In_reads_bytes_(cbSymCryptSignature _Use_decl_annotations_ SIZE_T scossl_ecdsa_size(PCSYMCRYPT_ECURVE curve) { + if (curve == NULL) + { + return 0; + } + return 2*SymCryptEcurveSizeofScalarMultiplier(curve) + 8; } diff --git a/SymCryptProvider/inc/scossl_provider.h b/SymCryptProvider/inc/scossl_provider.h index 69ebd253..6f3ef0f5 100644 --- a/SymCryptProvider/inc/scossl_provider.h +++ b/SymCryptProvider/inc/scossl_provider.h @@ -55,11 +55,7 @@ extern "C" { #define SCOSSL_OID_P256_MLKEM768 "2.16.840.1.101.3.4.4.4" #define SCOSSL_SN_X25519_MLKEM768 SN_X25519 SCOSSL_SN_MLKEM768 -#define SCOSSL_OID_X25519_MLKEM768 "2.16.840.1.101.3.4.4.3" - -// Hybrid PQ group names -#define SCOSSL_MLKEM_PARAM_NAME_P256_MLKEM768 SN_secp256r1 SCOSSL_MLKEM_PARAM_NAME_768 -#define SCOSSL_MLKEM_PARAM_NAME_X25519_MLKEM768 SN_X25519 SCOSSL_MLKEM_PARAM_NAME_768 +#define SCOSSL_OID_X25519_MLKEM768 "2.16.840.1.101.3.4.4.5" #ifdef __cplusplus } diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_common.c b/SymCryptProvider/src/decoder/p_scossl_decode_common.c index 6dfb266b..dff777fd 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_common.c +++ b/SymCryptProvider/src/decoder/p_scossl_decode_common.c @@ -93,7 +93,7 @@ SCOSSL_STATUS p_scossl_decode(SCOSSL_DECODE_CTX *ctx, OSSL_CORE_BIO *in, int sel if ((selection & ctx->desc->selection) != 0 && (bio = p_scossl_bio_new_from_core_bio(ctx->provctx, in)) != NULL) { - keyCtx = ctx->desc->decodeInternal(bio); + keyCtx = ctx->desc->decodeInternal(ctx, bio); } if (keyCtx != NULL) diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_common.h b/SymCryptProvider/src/decoder/p_scossl_decode_common.h index 5256f796..bcea0dbc 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_common.h +++ b/SymCryptProvider/src/decoder/p_scossl_decode_common.h @@ -12,7 +12,9 @@ extern "C" { #define select_PrivateKeyInfo OSSL_KEYMGMT_SELECT_PRIVATE_KEY #define select_SubjectPublicKeyInfo OSSL_KEYMGMT_SELECT_PUBLIC_KEY -typedef PVOID (*PSCOSSL_DECODE_INTERNAL_FN) (_In_ BIO *bio); +struct scossl_decode_ctx_st; + +typedef PVOID (*PSCOSSL_DECODE_INTERNAL_FN) (_In_ struct scossl_decode_ctx_st *ctx, _In_ BIO *bio); typedef struct { @@ -23,7 +25,7 @@ typedef struct OSSL_FUNC_keymgmt_free_fn *freeKeyCtx; } SCOSSL_DECODE_KEYTYPE_DESC; -typedef struct +typedef struct scossl_decode_ctx_st { SCOSSL_PROVCTX *provctx; diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c index d1496a96..c5a26105 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c +++ b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c @@ -13,119 +13,108 @@ extern "C" { #endif + typedef struct { int nid; - const char *name; - SYMCRYPT_MLKEM_PARAMS keyParams; + const char *groupName; } SCOSSL_DECODE_MLKEM_PARAM_MAP; static SCOSSL_DECODE_MLKEM_PARAM_MAP p_scossl_decode_mlkem_param_maps[] = { - {-1, SCOSSL_SN_MLKEM512, SYMCRYPT_MLKEM_PARAMS_MLKEM512}, - {-1, SCOSSL_SN_MLKEM768, SYMCRYPT_MLKEM_PARAMS_MLKEM768}, - {-1, SCOSSL_SN_MLKEM1024, SYMCRYPT_MLKEM_PARAMS_MLKEM1024}}; + {-1, SCOSSL_SN_MLKEM512}, + {-1, SCOSSL_SN_MLKEM768}, + {-1, SCOSSL_SN_MLKEM1024}, + {-1, SCOSSL_SN_P256_MLKEM768}, + {-1, SCOSSL_SN_X25519_MLKEM768}}; -static SYMCRYPT_MLKEM_PARAMS p_scossl_decode_mlkem_get_params(int nid) +static const char *p_scossl_decode_mlkem_obj_to_groupname(const ASN1_OBJECT *obj) { - for (size_t i = 0; i < sizeof(p_scossl_decode_mlkem_param_maps) / sizeof(SCOSSL_DECODE_MLKEM_PARAM_MAP); i++) - { - if (p_scossl_decode_mlkem_param_maps[i].nid == -1) - { - p_scossl_decode_mlkem_param_maps[i].nid = OBJ_sn2nid(p_scossl_decode_mlkem_param_maps[i].name); - } + int nid = OBJ_obj2nid(obj); - if (p_scossl_decode_mlkem_param_maps[i].nid == nid) + if (nid != -1) + { + for (size_t i = 0; i < sizeof(p_scossl_decode_mlkem_param_maps) / sizeof(OSSL_ITEM); i++) { - return p_scossl_decode_mlkem_param_maps[i].keyParams; + if (p_scossl_decode_mlkem_param_maps[i].nid == -1) + { + p_scossl_decode_mlkem_param_maps[i].nid = OBJ_sn2nid(p_scossl_decode_mlkem_param_maps[i].groupName); + } + + if (p_scossl_decode_mlkem_param_maps[i].nid == nid) + { + return p_scossl_decode_mlkem_param_maps[i].groupName; + } } } - return SYMCRYPT_MLKEM_PARAMS_NULL; + return NULL; } -static SCOSSL_MLKEM_KEY_CTX *p_scossl_PrivateKeyInfo_to_mlkem(_In_ BIO *bio) +static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_decode_key(_In_ SCOSSL_DECODE_CTX *ctx, _In_ const ASN1_OBJECT *algorithm, int selection, + _In_reads_bytes_(cbKey) PCBYTE pbKey, SIZE_T cbKey) { - PKCS8_PRIV_KEY_INFO *p8Info = NULL; - const X509_ALGOR *alg = NULL; - const unsigned char *pbKey = NULL; - int cbKey; - ASN1_OCTET_STRING *p8Data = NULL; + const char *groupName; SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; - SYMCRYPT_MLKEMKEY_FORMAT decodeFormat = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; - SYMCRYPT_ERROR scError; SCOSSL_STATUS status = SCOSSL_FAILURE; - if (d2i_PKCS8_PRIV_KEY_INFO_bio(bio, &p8Info) == NULL || - !PKCS8_pkey_get0(NULL, &pbKey, &cbKey, &alg, p8Info) || - (p8Data = d2i_ASN1_OCTET_STRING(NULL, &pbKey, cbKey)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ASN1_R_DECODE_ERROR); - goto cleanup; - } - - pbKey = ASN1_STRING_get0_data(p8Data); - cbKey = ASN1_STRING_length(p8Data); - - if (cbKey == 64) - { - decodeFormat = SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED; - } - if ((keyCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEY_CTX))) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; } - keyCtx->mlkemParams = p_scossl_decode_mlkem_get_params(OBJ_obj2nid(alg->algorithm)); - keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; + keyCtx->provCtx = ctx->provctx; - if (keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) + groupName = p_scossl_decode_mlkem_obj_to_groupname(algorithm); + if (groupName == NULL || + p_scossl_mlkem_keymgmt_set_group(keyCtx, groupName) != SCOSSL_SUCCESS) { ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); goto cleanup; } - if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->mlkemParams)) == NULL) + status = p_scossl_mlkem_keymgmt_set_encoded_key(keyCtx, selection, pbKey, cbKey); + +cleanup: + if (status != SCOSSL_SUCCESS) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; + OPENSSL_free(keyCtx); + keyCtx = NULL; } - scError = SymCryptMlKemkeySetValue( - pbKey, cbKey, - decodeFormat, - 0, - keyCtx->key); + return keyCtx; +} + +static SCOSSL_MLKEM_KEY_CTX *p_scossl_PrivateKeyInfo_to_mlkem(_In_ SCOSSL_DECODE_CTX *ctx, _In_ BIO *bio) +{ + PKCS8_PRIV_KEY_INFO *p8Info = NULL; + const X509_ALGOR *alg = NULL; + const unsigned char *pbKey = NULL; + int cbKey; + ASN1_OCTET_STRING *p8Data = NULL; + SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; - if (scError != SYMCRYPT_NO_ERROR) + if (d2i_PKCS8_PRIV_KEY_INFO_bio(bio, &p8Info) == NULL || + !PKCS8_pkey_get0(NULL, &pbKey, &cbKey, &alg, p8Info) || + (p8Data = d2i_ASN1_OCTET_STRING(NULL, &pbKey, cbKey)) == NULL) { - SymCryptMlKemkeyFree(keyCtx->key); - keyCtx->key = NULL; - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_PROV, ASN1_R_DECODE_ERROR); goto cleanup; } - status = SCOSSL_SUCCESS; + keyCtx = p_scossl_mlkem_decode_key(ctx, alg->algorithm, OSSL_KEYMGMT_SELECT_PRIVATE_KEY, + ASN1_STRING_get0_data(p8Data), ASN1_STRING_length(p8Data)); cleanup: - if (status != SCOSSL_SUCCESS) - { - OPENSSL_free(keyCtx); - keyCtx = NULL; - } - ASN1_OCTET_STRING_free(p8Data); PKCS8_PRIV_KEY_INFO_free(p8Info); return keyCtx; } -static SCOSSL_MLKEM_KEY_CTX *p_scossl_SubjectPublicKeyInfo_to_mlkem(_In_ BIO *bio) +static SCOSSL_MLKEM_KEY_CTX *p_scossl_SubjectPublicKeyInfo_to_mlkem(_In_ SCOSSL_DECODE_CTX *ctx, _In_ BIO *bio) { SUBJECT_PUBKEY_INFO *subjPubKeyInfo; SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; - SYMCRYPT_ERROR scError; - SCOSSL_STATUS status = SCOSSL_FAILURE; if ((subjPubKeyInfo = OPENSSL_zalloc(sizeof(SUBJECT_PUBKEY_INFO))) == NULL) { @@ -139,51 +128,10 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_SubjectPublicKeyInfo_to_mlkem(_In_ BIO *bi goto cleanup; } - if ((keyCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEY_CTX))) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - keyCtx->mlkemParams = p_scossl_decode_mlkem_get_params(OBJ_obj2nid(subjPubKeyInfo->algorithm->algorithm)); - keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; - - if (keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) - { - ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); - goto cleanup; - } - - if ((keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->mlkemParams)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - scError = SymCryptMlKemkeySetValue( - subjPubKeyInfo->subjectPublicKey->data, - subjPubKeyInfo->subjectPublicKey->length, - keyCtx->format, - 0, - keyCtx->key); - - if (scError != SYMCRYPT_NO_ERROR) - { - SymCryptMlKemkeyFree(keyCtx->key); - keyCtx->key = NULL; - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - goto cleanup; - } - - status = SCOSSL_SUCCESS; + keyCtx = p_scossl_mlkem_decode_key(ctx, subjPubKeyInfo->algorithm->algorithm, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, + subjPubKeyInfo->subjectPublicKey->data, subjPubKeyInfo->subjectPublicKey->length); cleanup: - if (status != SCOSSL_SUCCESS) - { - OPENSSL_free(keyCtx); - keyCtx = NULL; - } - OPENSSL_free(subjPubKeyInfo); return keyCtx; diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c index 00bc51d7..7dc45d58 100644 --- a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c +++ b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c @@ -16,41 +16,9 @@ extern "C" { extern const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[]; -static const char *p_scossl_encode_mlkem_params_to_name(SYMCRYPT_MLKEM_PARAMS params) +static ASN1_OBJECT *p_scossl_encode_mlkem_get_oid(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx) { - switch (params) - { - case SYMCRYPT_MLKEM_PARAMS_MLKEM512: - return SCOSSL_SN_MLKEM512; - case SYMCRYPT_MLKEM_PARAMS_MLKEM768: - return SCOSSL_SN_MLKEM768; - case SYMCRYPT_MLKEM_PARAMS_MLKEM1024: - return SCOSSL_SN_MLKEM1024; - default: - break; - } - - return NULL; -} - -static ASN1_OBJECT *p_scossl_encode_get_mlkem_oid(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx) -{ - int nid = NID_undef; - - switch (keyCtx->mlkemParams) - { - case SYMCRYPT_MLKEM_PARAMS_MLKEM512: - nid = OBJ_sn2nid(SCOSSL_SN_MLKEM512); - break; - case SYMCRYPT_MLKEM_PARAMS_MLKEM768: - nid = OBJ_sn2nid(SCOSSL_SN_MLKEM768); - break; - case SYMCRYPT_MLKEM_PARAMS_MLKEM1024: - nid = OBJ_sn2nid(SCOSSL_SN_MLKEM1024); - break; - default: - break; - } + int nid = OBJ_sn2nid(keyCtx->groupName); if (nid != NID_undef) { @@ -96,7 +64,7 @@ static PKCS8_PRIV_KEY_INFO *p_scossl_mlkem_key_to_p8info(_In_ const SCOSSL_MLKEM goto cleanup; } - if ((p8Obj = p_scossl_encode_get_mlkem_oid(keyCtx)) == NULL) + if ((p8Obj = p_scossl_encode_mlkem_get_oid(keyCtx)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); goto cleanup; @@ -150,7 +118,7 @@ static X509_PUBKEY *p_scossl_mlkem_key_to_pubkey(_In_ const SCOSSL_MLKEM_KEY_CTX goto cleanup; } - if ((p8Obj = p_scossl_encode_get_mlkem_oid(keyCtx)) == NULL) + if ((p8Obj = p_scossl_encode_mlkem_get_oid(keyCtx)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); goto cleanup; @@ -331,13 +299,11 @@ static SCOSSL_STATUS p_scossl_mlkem_to_text(ossl_unused SCOSSL_ENCODE_CTX *ctx, BOOL printPrivateSeed = FALSE; BOOL printDecapsulationKey = FALSE; BOOL printEncapsulationKey = FALSE; - const char *paramName = p_scossl_encode_mlkem_params_to_name(keyCtx->mlkemParams); PBYTE pbKey = NULL; SIZE_T cbKey = 0; SCOSSL_STATUS ret = SCOSSL_FAILURE; - if (keyCtx->key == NULL || - paramName == NULL) + if (keyCtx->key == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); goto cleanup; @@ -418,7 +384,7 @@ static SCOSSL_STATUS p_scossl_mlkem_to_text(ossl_unused SCOSSL_ENCODE_CTX *ctx, } } - if (BIO_printf(out, "PARAMETER SET: %s\n", paramName) <= 0) + if (BIO_printf(out, "PARAMETER SET: %s\n", keyCtx->groupName) <= 0) { goto cleanup; } diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.c b/SymCryptProvider/src/kem/p_scossl_mlkem.c index 459a13b6..fb3c5a64 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.c +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.c @@ -155,13 +155,11 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, _Out_writes_bytes_opt_(*outlen) unsigned char *out, _Out_ size_t *outlen, _Out_writes_bytes_(*secretlen) unsigned char *secret, _Out_ size_t *secretlen) { - SIZE_T cbClassicKeyPublic = 0; + SIZE_T cbClassicKey = 0; SIZE_T cbMlkemCiphertext = 0; SIZE_T cbClassicSecret = 0; - PVOID classicKeygenCtx = NULL; - PVOID classicKeyCtxPrivate = NULL; - const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS *classicKeymgmt = ctx->keyCtx->classicKeymgmt; - OSSL_PARAM classicKeyexchParams[2]; + SCOSSL_ECC_KEY_CTX *classicKeyCtxPeer = NULL; + SCOSSL_ECC_KEY_CTX *classicKeyCtxPrivate = NULL; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -177,6 +175,8 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, goto cleanup; } + classicKeyCtxPeer = ctx->keyCtx->classicKeyCtx; + if (ctx->classicKeyexch != NULL) { if (ctx->keyCtx->classicKeyCtx == NULL) @@ -186,7 +186,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, } // Get key size - cbClassicKeyPublic = p_scossl_ecc_get_encoded_key_size(ctx->keyCtx->classicKeyCtx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); + cbClassicKey = p_scossl_ecc_get_encoded_key_size(ctx->keyCtx->classicKeyCtx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); // Get secret size if (ctx->classicKeyexch->derive(ctx->keyCtx->classicKeyCtx, NULL, &cbClassicSecret, 0) != SCOSSL_SUCCESS) @@ -204,38 +204,34 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, if (out != NULL) { - if ((outlen != NULL && *outlen < cbClassicKeyPublic + cbMlkemCiphertext) || + if ((outlen != NULL && *outlen < cbClassicKey + cbMlkemCiphertext) || (secretlen != NULL && *secretlen < cbClassicSecret + SYMCRYPT_MLKEM_SECRET_LENGTH)) { ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); goto cleanup; } - if (ctx->keyCtx->classicKeyCtx != NULL) + if (classicKeyCtxPeer != NULL) { - classicKeyexchParams[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, out, cbClassicKeyPublic); - classicKeyexchParams[1] = OSSL_PARAM_construct_end(); - - if (classicKeymgmt == NULL) + // Generate ephemeral ECDH key + if ((classicKeyCtxPrivate = p_scossl_ecc_new_ctx(ctx->provCtx)) == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; } - // Generate ephemeral ECDH key - if ((classicKeygenCtx = classicKeymgmt->genInit(ctx->provCtx, OSSL_KEYMGMT_SELECT_ALL, NULL)) == NULL || - classicKeymgmt->setTemplate(classicKeygenCtx, ctx->keyCtx->classicKeyCtx) != SCOSSL_SUCCESS || - (classicKeyCtxPrivate = classicKeymgmt->gen(classicKeygenCtx, NULL, NULL)) == NULL) + if (p_scossl_ecc_set_group(classicKeyCtxPrivate, ctx->keyCtx->classicGroupName) != SCOSSL_SUCCESS || + p_scossl_ecc_gen(classicKeyCtxPrivate) != SCOSSL_SUCCESS) { goto cleanup; } // Write encoded public key bytes - if ((classicKeymgmt->getParams(classicKeyCtxPrivate, classicKeyexchParams)) != SCOSSL_SUCCESS) + if (p_scossl_ecc_get_encoded_key(classicKeyCtxPrivate, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, &out, &cbClassicKey) != SCOSSL_SUCCESS) { goto cleanup; } - out += cbClassicKeyPublic; + out += cbClassicKey; // Derive ECDH secret if (p_scossl_mlkem_classic_keyexch_init(ctx, classicKeyCtxPrivate) != SCOSSL_SUCCESS || @@ -262,7 +258,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, if (outlen != NULL) { - *outlen = cbClassicKeyPublic + cbMlkemCiphertext; + *outlen = cbClassicKey + cbMlkemCiphertext; } if (secretlen != NULL) @@ -273,11 +269,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, ret = SCOSSL_SUCCESS; cleanup: - if (classicKeymgmt != NULL) - { - classicKeymgmt->free(classicKeyCtxPrivate); - classicKeymgmt->genCleanup(classicKeygenCtx); - } + p_scossl_ecc_free_ctx(classicKeyCtxPrivate); return ret; } @@ -297,12 +289,10 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, _Out_writes_bytes_opt_(*outlen) unsigned char *out, _Out_ size_t *outlen, _In_reads_bytes_(inlen) const unsigned char *in, size_t inlen) { - SIZE_T cbClassicKeyPublic = 0; + SIZE_T cbClassicKey = 0; SIZE_T cbMlkemCiphertext = 0; SIZE_T cbClassicSecret = 0; - PVOID classicKeyCtxPublic = NULL; - const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS *classicKeymgmt = ctx->keyCtx->classicKeymgmt; - OSSL_PARAM classicKeyexchParams[2]; + SCOSSL_ECC_KEY_CTX *classicKeyCtxPublic = NULL; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -327,7 +317,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, } // Get key size - cbClassicKeyPublic = p_scossl_ecc_get_encoded_key_size(ctx->keyCtx->classicKeyCtx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); + cbClassicKey = p_scossl_ecc_get_encoded_key_size(ctx->keyCtx->classicKeyCtx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); // Get secret size if (ctx->classicKeyexch->derive(ctx->keyCtx->classicKeyCtx, NULL, &cbClassicSecret, 0) != SCOSSL_SUCCESS) @@ -343,7 +333,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, goto cleanup; } - if (inlen != cbClassicKeyPublic + cbMlkemCiphertext) + if (inlen != cbClassicKey + cbMlkemCiphertext) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH); goto cleanup; @@ -360,15 +350,17 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, if (ctx->classicKeyexch != NULL) { // Extract ECDH public key from in - classicKeyexchParams[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, (void *)in, cbClassicKeyPublic); - classicKeyexchParams[1] = OSSL_PARAM_construct_end(); + if ((classicKeyCtxPublic = p_scossl_ecc_new_ctx(ctx->provCtx)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } - if ((classicKeyCtxPublic = classicKeymgmt->new(ctx->provCtx)) == NULL || - classicKeymgmt->setParams(classicKeyCtxPublic, classicKeyexchParams) != SCOSSL_SUCCESS) + if (p_scossl_ecc_set_group(classicKeyCtxPublic, ctx->keyCtx->classicGroupName) != SCOSSL_SUCCESS || + p_scossl_ecc_get_encoded_key(classicKeyCtxPublic, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, &out, &cbClassicKey) != SCOSSL_SUCCESS) { goto cleanup; } - in += cbClassicKeyPublic; // Set ECDH peer if (ctx->classicKeyexch->setPeer(ctx->classicKeyexchCtx, classicKeyCtxPublic) != SCOSSL_SUCCESS) @@ -406,10 +398,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, ret = SCOSSL_SUCCESS; cleanup: - if (classicKeymgmt != NULL) - { - classicKeymgmt->free(classicKeyCtxPublic); - } + p_scossl_ecc_free_ctx(classicKeyCtxPublic); return ret; } diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.h b/SymCryptProvider/src/kem/p_scossl_mlkem.h index ed3b310f..ca6594f1 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.h +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.h @@ -9,23 +9,6 @@ extern "C" { #endif -typedef struct { - OSSL_FUNC_keymgmt_gen_cleanup_fn *genCleanup; - OSSL_FUNC_keymgmt_gen_init_fn *genInit; - OSSL_FUNC_keymgmt_gen_set_template_fn *setTemplate; - OSSL_FUNC_keymgmt_gen_fn *gen; - OSSL_FUNC_keymgmt_new_fn *new; - OSSL_FUNC_keymgmt_free_fn *free; - OSSL_FUNC_keymgmt_dup_fn *dup; - OSSL_FUNC_keymgmt_get_params_fn *getParams; - OSSL_FUNC_keymgmt_set_params_fn *setParams; - OSSL_FUNC_keymgmt_has_fn *has; - OSSL_FUNC_keymgmt_match_fn *match; - OSSL_FUNC_keymgmt_import_fn *import; - OSSL_FUNC_keymgmt_export_fn *export; - OSSL_FUNC_keymgmt_validate_fn *validate; -} SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS; - typedef struct { SCOSSL_PROVCTX *provCtx; @@ -36,7 +19,6 @@ typedef struct { const char *classicGroupName; SCOSSL_ECC_KEY_CTX *classicKeyCtx; - const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS *classicKeymgmt; } SCOSSL_MLKEM_KEY_CTX; #ifdef __cplusplus diff --git a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c index 73f71a73..525801b2 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c @@ -4,7 +4,6 @@ #include "scossl_ecc.h" #include "p_scossl_ecc.h" -#include "p_scossl_base.h" #include "keymgmt/p_scossl_ecc_impexp_types.h" #include "keymgmt/p_scossl_ecc_keymgmt.h" @@ -88,12 +87,9 @@ static point_conversion_form_t p_scossl_ecc_keymgmt_conversion_name_to_id(_In_ c _Use_decl_annotations_ SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_new_ctx(SCOSSL_PROVCTX *provctx) { - SCOSSL_ECC_KEY_CTX *keyCtx = OPENSSL_zalloc(sizeof(SCOSSL_ECC_KEY_CTX)); + SCOSSL_ECC_KEY_CTX *keyCtx = p_scossl_ecc_new_ctx(provctx); if (keyCtx != NULL) { - keyCtx->libctx = provctx->libctx; - keyCtx->includePublic = 1; - keyCtx->conversionFormat = POINT_CONVERSION_UNCOMPRESSED; #ifdef KEYSINUSE_ENABLED keyCtx->keysinuseLock = CRYPTO_THREAD_lock_new(); #endif @@ -105,7 +101,7 @@ SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_new_ctx(SCOSSL_PROVCTX *provctx) _Use_decl_annotations_ SCOSSL_ECC_KEY_CTX *p_scossl_x25519_keymgmt_new_ctx(SCOSSL_PROVCTX *provctx) { - SCOSSL_ECC_KEY_CTX *keyCtx = p_scossl_ecc_keymgmt_new_ctx(provctx); + SCOSSL_ECC_KEY_CTX *keyCtx = p_scossl_ecc_new_ctx(provctx); if (keyCtx != NULL) { keyCtx->curve = scossl_ecc_get_x25519_curve(); @@ -118,154 +114,6 @@ SCOSSL_ECC_KEY_CTX *p_scossl_x25519_keymgmt_new_ctx(SCOSSL_PROVCTX *provctx) return keyCtx; } -_Use_decl_annotations_ -void p_scossl_ecc_keymgmt_free_ctx(SCOSSL_ECC_KEY_CTX *keyCtx) -{ - if (keyCtx == NULL) - return; - if (keyCtx->key != NULL) - { - SymCryptEckeyFree(keyCtx->key); - } -#ifdef KEYSINUSE_ENABLED - p_scossl_ecc_reset_keysinuse(keyCtx); - CRYPTO_THREAD_lock_free(keyCtx->keysinuseLock); -#endif - - OPENSSL_free(keyCtx); -} - -_Use_decl_annotations_ -SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_dup_ctx(_In_ const SCOSSL_ECC_KEY_CTX *keyCtx, int selection) -{ - PBYTE pbData = NULL; - PBYTE pbPrivateKey = NULL; - PBYTE pbPublicKey = NULL; - SIZE_T cbData = 0; - SIZE_T cbPublicKey = 0; - SIZE_T cbPrivateKey = 0; - SCOSSL_STATUS success = SCOSSL_FAILURE; - SYMCRYPT_ECPOINT_FORMAT pointFormat = keyCtx->isX25519 ? SYMCRYPT_ECPOINT_FORMAT_X : SYMCRYPT_ECPOINT_FORMAT_XY; - SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; - - SCOSSL_ECC_KEY_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_ECC_KEY_CTX)); - - if (copyCtx != NULL) - { -#ifdef KEYSINUSE_ENABLED - copyCtx->keysinuseLock = CRYPTO_THREAD_lock_new(); - - if (keyCtx->keysinuseInfo == NULL || - p_scossl_keysinuse_upref(keyCtx->keysinuseInfo, NULL)) - { - copyCtx->keysinuseInfo = keyCtx->keysinuseInfo; - } -#endif - - copyCtx->isX25519 = keyCtx->isX25519; - copyCtx->libctx = keyCtx->libctx; - copyCtx->modifiedPrivateBits = keyCtx->modifiedPrivateBits; - copyCtx->conversionFormat = keyCtx->conversionFormat; - - if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) - { - copyCtx->curve = keyCtx->curve; - } - else - { - copyCtx->curve = NULL; - } - - if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 && keyCtx->initialized) - { - if (copyCtx->curve == NULL) - { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); - goto cleanup; - } - - if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && - SymCryptEckeyHasPrivateKey(keyCtx->key)) - { - cbPrivateKey = SymCryptEckeySizeofPrivateKey(keyCtx->key); - } - - if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) - { - cbPublicKey = SymCryptEckeySizeofPublicKey(keyCtx->key, pointFormat); - } - - cbData = cbPrivateKey + cbPublicKey; - if ((pbData = OPENSSL_secure_malloc(cbData)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - pbPrivateKey = cbPrivateKey != 0 ? pbData : NULL; - pbPublicKey = cbPublicKey != 0 ? pbData + cbPrivateKey : NULL; - - scError = SymCryptEckeyGetValue( - keyCtx->key, - pbPrivateKey, cbPrivateKey, - pbPublicKey, cbPublicKey, - SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, - pointFormat, - 0); - if (scError != SYMCRYPT_NO_ERROR) - { - SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeyGetValue failed", scError); - goto cleanup; - } - - if ((copyCtx->key = SymCryptEckeyAllocate(keyCtx->curve)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - // Default ECDH only. If the key is used for ECDSA then we call SymCryptEckeyExtendKeyUsage - scError = SymCryptEckeySetValue( - pbPrivateKey, cbPrivateKey, - pbPublicKey, cbPublicKey, - SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, - pointFormat, - SYMCRYPT_FLAG_ECKEY_ECDH, - copyCtx->key); - if (scError != SYMCRYPT_NO_ERROR) - { - SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeySetValue failed", scError); - goto cleanup; - } - - copyCtx->initialized = 1; - copyCtx->includePublic = keyCtx->includePublic; - } - else - { - copyCtx->key = NULL; - copyCtx->initialized = 0; - copyCtx->includePublic = 1; - } - } - - success = SCOSSL_SUCCESS; - -cleanup: - if (pbData != NULL) - { - OPENSSL_secure_clear_free(pbData, cbData); - } - - if (!success) - { - p_scossl_ecc_keymgmt_free_ctx(copyCtx); - copyCtx = NULL; - } - - return copyCtx; -} - // // Key Generation // @@ -417,8 +265,6 @@ SCOSSL_STATUS p_scossl_ecc_keygen_set_template(SCOSSL_ECC_KEYGEN_CTX *genCtx, SC _Use_decl_annotations_ SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keygen(SCOSSL_ECC_KEYGEN_CTX *genCtx, ossl_unused OSSL_CALLBACK *cb, ossl_unused void *cbarg) { - SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; - SCOSSL_ECC_KEY_CTX *keyCtx = OPENSSL_malloc(sizeof(SCOSSL_ECC_KEY_CTX)); if (keyCtx == NULL) { @@ -429,35 +275,12 @@ SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keygen(SCOSSL_ECC_KEYGEN_CTX *genCtx, ossl_unus keyCtx->libctx = genCtx->libctx; keyCtx->curve = genCtx->curve; keyCtx->isX25519 = genCtx->isX25519; -#ifdef KEYSINUSE_ENABLED - keyCtx->isImported = FALSE; - keyCtx->keysinuseLock = CRYPTO_THREAD_lock_new(); - keyCtx->keysinuseInfo = NULL; -#endif keyCtx->conversionFormat = genCtx->conversionFormat; - keyCtx->key = SymCryptEckeyAllocate(keyCtx->curve); - if (keyCtx->key == NULL) + if (p_scossl_ecc_gen(keyCtx) != SCOSSL_SUCCESS) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - // Default ECDH only. If the key is used for ECDSA then we call SymCryptEckeyExtendKeyUsage - scError = SymCryptEckeySetRandom(SYMCRYPT_FLAG_ECKEY_ECDH, keyCtx->key); - if (scError != SYMCRYPT_NO_ERROR) - { - SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeySetRandom failed", scError); - goto cleanup; - } - - keyCtx->initialized = TRUE; - -cleanup: - if (!keyCtx->initialized) - { - p_scossl_ecc_keymgmt_free_ctx(keyCtx); - keyCtx = NULL; + p_scossl_ecc_free_ctx(keyCtx); + return NULL; } return keyCtx; @@ -552,24 +375,11 @@ SCOSSL_STATUS p_scossl_ecc_keymgmt_get_params(SCOSSL_ECC_KEY_CTX *keyCtx, OSSL_P SCOSSL_STATUS ret = SCOSSL_FAILURE; OSSL_PARAM *p; - if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL) + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL && + !OSSL_PARAM_set_uint32(p, p_scossl_ecc_get_max_size(keyCtx, FALSE))) { - if (keyCtx->isX25519) - { - if (!OSSL_PARAM_set_uint32(p, SCOSSL_X25519_MAX_SIZE)) - { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - goto cleanup; - } - } - // We don't know if the key will be used for ECDSA or ECDH so return - // the larger size - else if (keyCtx->curve == NULL || - !OSSL_PARAM_set_uint32(p, scossl_ecdsa_size(keyCtx->curve))) - { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - goto cleanup; - } + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + goto cleanup; } if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL && @@ -1041,7 +851,7 @@ SCOSSL_STATUS p_scossl_ecc_keymgmt_import(SCOSSL_ECC_KEY_CTX *keyCtx, int select SCOSSL_STATUS ret = SCOSSL_FAILURE; EC_GROUP *ecGroup = NULL; PCSYMCRYPT_ECURVE pCurve; - PCBYTE pbEncodedPublicKey = NULL; + PCBYTE pbEncodedPublicKey = NULL; SIZE_T cbEncodedPublicKey = 0; PBYTE pbPrivateKey = NULL; SIZE_T cbPrivateKey = 0; @@ -1153,13 +963,13 @@ SCOSSL_STATUS p_scossl_ecc_keymgmt_import(SCOSSL_ECC_KEY_CTX *keyCtx, int select ret = p_scossl_ecc_set_encoded_key(keyCtx, selection, pbEncodedPublicKey, cbEncodedPublicKey, pbPrivateKey, cbPrivateKey); - + if (ret != SCOSSL_SUCCESS) { SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeySetValue failed", scError); goto cleanup; } - + #ifdef KEYSINUSE_ENABLED keyCtx->isImported = TRUE; #endif @@ -1470,8 +1280,8 @@ static const char *p_scossl_ecc_keymgmt_query_operation_name(int operation_id) const OSSL_DISPATCH p_scossl_ecc_keymgmt_functions[] = { {OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))p_scossl_ecc_keymgmt_new_ctx}, - {OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))p_scossl_ecc_keymgmt_free_ctx}, - {OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))p_scossl_ecc_keymgmt_dup_ctx}, + {OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))p_scossl_ecc_free_ctx}, + {OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))p_scossl_ecc_dup_ctx}, {OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))p_scossl_ecc_keygen_set_params}, {OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (void (*)(void))p_scossl_ecc_keygen_settable_params}, {OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))p_scossl_ecc_keygen_cleanup}, @@ -1494,8 +1304,8 @@ const OSSL_DISPATCH p_scossl_ecc_keymgmt_functions[] = { const OSSL_DISPATCH p_scossl_x25519_keymgmt_functions[] = { {OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))p_scossl_x25519_keymgmt_new_ctx}, - {OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))p_scossl_ecc_keymgmt_free_ctx}, - {OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))p_scossl_ecc_keymgmt_dup_ctx}, + {OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))p_scossl_ecc_free_ctx}, + {OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))p_scossl_ecc_dup_ctx}, {OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))p_scossl_x25519_keygen_set_params}, {OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (void (*)(void))p_scossl_ecc_keygen_settable_params}, {OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))p_scossl_ecc_keygen_cleanup}, diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index 6c93347d..a04c4c2a 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -59,39 +59,6 @@ static const OSSL_PARAM *p_scossl_mlkem_impexp_types[] = { p_scossl_mlkem_pkey_types, p_scossl_mlkem_all_types}; -static const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS p_scossl_ecc_classic_keymgmt = { - (OSSL_FUNC_keymgmt_gen_cleanup_fn *) p_scossl_ecc_keygen_cleanup, - (OSSL_FUNC_keymgmt_gen_init_fn *) p_scossl_ecc_keygen_init, - (OSSL_FUNC_keymgmt_gen_set_template_fn *) p_scossl_ecc_keygen_set_template, - (OSSL_FUNC_keymgmt_gen_fn *) p_scossl_ecc_keygen, - (OSSL_FUNC_keymgmt_new_fn *) p_scossl_ecc_keymgmt_new_ctx, - (OSSL_FUNC_keymgmt_free_fn *) p_scossl_ecc_keymgmt_free_ctx, - (OSSL_FUNC_keymgmt_dup_fn *) p_scossl_ecc_keymgmt_dup_ctx, - (OSSL_FUNC_keymgmt_get_params_fn *) p_scossl_ecc_keymgmt_get_params, - (OSSL_FUNC_keymgmt_set_params_fn *) p_scossl_ecc_keymgmt_set_params, - (OSSL_FUNC_keymgmt_has_fn *) p_scossl_ecc_keymgmt_has, - (OSSL_FUNC_keymgmt_match_fn *) p_scossl_ecc_keymgmt_match, - (OSSL_FUNC_keymgmt_import_fn *) p_scossl_ecc_keymgmt_import, - (OSSL_FUNC_keymgmt_export_fn *) p_scossl_ecc_keymgmt_export, - (OSSL_FUNC_keymgmt_validate_fn *) p_scossl_ecc_keymgmt_validate}; - -static const SCOSSL_MLKEM_CLASSIC_KEYMGMT_FNS p_scossl_x25519_classic_keymgmt = { - (OSSL_FUNC_keymgmt_gen_cleanup_fn *) p_scossl_ecc_keygen_cleanup, - (OSSL_FUNC_keymgmt_gen_init_fn *) p_scossl_x25519_keygen_init, - (OSSL_FUNC_keymgmt_gen_set_template_fn *) p_scossl_ecc_keygen_set_template, - (OSSL_FUNC_keymgmt_gen_fn *) p_scossl_ecc_keygen, - (OSSL_FUNC_keymgmt_new_fn *) p_scossl_x25519_keymgmt_new_ctx, - (OSSL_FUNC_keymgmt_free_fn *) p_scossl_ecc_keymgmt_free_ctx, - (OSSL_FUNC_keymgmt_dup_fn *) p_scossl_ecc_keymgmt_dup_ctx, - (OSSL_FUNC_keymgmt_get_params_fn *) p_scossl_ecc_keymgmt_get_params, - (OSSL_FUNC_keymgmt_set_params_fn *) p_scossl_ecc_keymgmt_set_params, - (OSSL_FUNC_keymgmt_has_fn *) p_scossl_ecc_keymgmt_has, - (OSSL_FUNC_keymgmt_match_fn *) p_scossl_ecc_keymgmt_match, - (OSSL_FUNC_keymgmt_import_fn *) p_scossl_x25519_keymgmt_import, - (OSSL_FUNC_keymgmt_export_fn *) p_scossl_x25519_keymgmt_export, - (OSSL_FUNC_keymgmt_validate_fn *) p_scossl_ecc_keymgmt_validate}; - -static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_group(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, _In_ const char *groupName); static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx); SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_new_ctx(_In_ SCOSSL_PROVCTX *provCtx) @@ -116,10 +83,7 @@ void p_scossl_mlkem_keymgmt_free_key_ctx(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx) SymCryptMlKemkeyFree(keyCtx->key); } - if (keyCtx->classicKeyCtx != NULL) - { - keyCtx->classicKeymgmt->free(keyCtx->classicKeyCtx); - } + p_scossl_ecc_free_ctx(keyCtx->classicKeyCtx); OPENSSL_free(keyCtx); } @@ -135,7 +99,6 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS if (copyCtx != NULL) { copyCtx->provCtx = keyCtx->provCtx; - copyCtx->classicKeymgmt = keyCtx->classicKeymgmt; if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { @@ -185,7 +148,7 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS if (keyCtx->classicKeyCtx != NULL) { - copyCtx->classicKeyCtx = keyCtx->classicKeymgmt->dup(keyCtx->classicKeyCtx, selection); + copyCtx->classicKeyCtx = p_scossl_ecc_dup_ctx(keyCtx->classicKeyCtx, selection); } } @@ -281,9 +244,8 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEY return SCOSSL_SUCCESS; } -static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEY_CTX *genCtx, _In_ OSSL_CALLBACK *cb, _In_ void *cbarg) +static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEY_CTX *genCtx, ossl_unused OSSL_CALLBACK *cb, ossl_unused void *cbarg) { - PVOID classicKeygenCtx = NULL; SCOSSL_MLKEM_KEY_CTX *keyCtx; SCOSSL_STATUS status = SCOSSL_FAILURE; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; @@ -304,18 +266,14 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEY_CTX *ge if (keyCtx->classicGroupName != NULL) { - OSSL_PARAM classicParams[2] = { - OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, (char *)keyCtx->classicGroupName, strlen(keyCtx->classicGroupName)), - OSSL_PARAM_END}; - - classicKeygenCtx = keyCtx->classicKeymgmt->genInit(keyCtx->provCtx, 0, classicParams); - if (classicKeygenCtx == NULL) + if ((keyCtx->classicKeyCtx = p_scossl_ecc_new_ctx(keyCtx->provCtx)) == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; } - keyCtx->classicKeyCtx = keyCtx->classicKeymgmt->gen(classicKeygenCtx, cb, cbarg); - if (keyCtx->classicKeyCtx == NULL) + if (p_scossl_ecc_set_group(keyCtx->classicKeyCtx, keyCtx->classicGroupName) != SCOSSL_SUCCESS || + p_scossl_ecc_gen(keyCtx->classicKeyCtx) != SCOSSL_SUCCESS) { goto cleanup; } @@ -328,15 +286,15 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEY_CTX *ge cleanup: if (status != SCOSSL_SUCCESS) { + if (keyCtx != NULL) + { + p_scossl_ecc_free_ctx(keyCtx->classicKeyCtx); + } + p_scossl_mlkem_keymgmt_free_key_ctx(keyCtx); keyCtx = NULL; } - if (classicKeygenCtx != NULL) - { - genCtx->classicKeymgmt->genCleanup(classicKeygenCtx); - } - return keyCtx; } @@ -389,18 +347,13 @@ static const OSSL_PARAM *p_scossl_mlkem_keymgmt_gettable_params(ossl_unused void static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, _Inout_ OSSL_PARAM params[]) { - PBYTE pbMlKemKey = NULL; - SIZE_T cbMlKemKey = 0; - PBYTE pbClassicKey = NULL; - SIZE_T cbClassicKey = 0; PBYTE pbKey = NULL; SIZE_T cbKey = 0; - SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + SCOSSL_STATUS status; SCOSSL_STATUS ret = SCOSSL_FAILURE; OSSL_PARAM *paramEncodedKey = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); OSSL_PARAM *paramPubKey = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY); OSSL_PARAM *paramPrivKey = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PRIV_KEY); - OSSL_PARAM classic_params[2] = { OSSL_PARAM_END }; if (keyCtx->key == NULL && (paramEncodedKey != NULL || @@ -413,12 +366,10 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY if (paramEncodedKey != NULL || paramPubKey != NULL) { - scError = p_scossl_mlkem_keymgmt_get_encoded_key( - keyCtx, - OSSL_KEYMGMT_SELECT_PUBLIC_KEY, - &pbMlKemKey, &cbMlKemKey); - - if (scError != SYMCRYPT_NO_ERROR) + status = p_scossl_mlkem_keymgmt_get_encoded_key( + keyCtx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, + &pbKey, &cbKey); + if (status != SCOSSL_SUCCESS) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); goto cleanup; @@ -441,8 +392,6 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY if (paramPrivKey != NULL) { - OPENSSL_secure_clear_free(pbMlKemKey, cbMlKemKey); - OPENSSL_secure_clear_free(pbClassicKey, cbClassicKey); OPENSSL_secure_clear_free(pbKey, cbKey); if (keyCtx->format != SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY) @@ -451,44 +400,15 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY goto cleanup; } - scError = p_scossl_mlkem_keymgmt_get_encoded_key( - keyCtx, - OSSL_KEYMGMT_SELECT_PRIVATE_KEY, + status = p_scossl_mlkem_keymgmt_get_encoded_key( + keyCtx, OSSL_KEYMGMT_SELECT_PRIVATE_KEY, &pbKey, &cbKey); - - if (scError != SYMCRYPT_NO_ERROR) + if (status != SCOSSL_SUCCESS) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); goto cleanup; } - if (keyCtx->classicKeyCtx != NULL) - { - classic_params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, &pbClassicKey, cbClassicKey); - if (keyCtx->classicKeymgmt->getParams(keyCtx->classicKeyCtx, classic_params) != SCOSSL_SUCCESS) - { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - goto cleanup; - } - - cbKey = cbMlKemKey + cbClassicKey; - if ((pbKey = OPENSSL_malloc(cbKey)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - - memcpy(pbKey, pbClassicKey, cbClassicKey); - memcpy(pbKey + cbClassicKey, pbMlKemKey, cbMlKemKey); - } - else - { - pbKey = pbMlKemKey; - cbKey = cbMlKemKey; - pbMlKemKey = NULL; - cbMlKemKey = 0; - } - if (!OSSL_PARAM_set_octet_string(paramPrivKey, pbKey, cbKey)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); @@ -499,8 +419,6 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY ret = SCOSSL_SUCCESS; cleanup: - OPENSSL_secure_clear_free(pbMlKemKey, cbMlKemKey); - OPENSSL_secure_clear_free(pbClassicKey, cbClassicKey); OPENSSL_secure_clear_free(pbKey, cbKey); return ret; @@ -510,7 +428,6 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX { SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; OSSL_PARAM *p; - OSSL_PARAM classicParams[2] = { OSSL_PARAM_END }; if (keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) { @@ -527,7 +444,6 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL) { - SIZE_T cbClassicMax; SIZE_T cbMax; SYMCRYPT_MLKEMKEY_FORMAT format = keyCtx->format; @@ -546,13 +462,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX if (keyCtx->classicKeyCtx != NULL) { - classicParams[0] = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_MAX_SIZE, &cbClassicMax); - if (keyCtx->classicKeymgmt->getParams(keyCtx->classicKeyCtx, classicParams) != SCOSSL_SUCCESS) - { - return SCOSSL_FAILURE; - } - - cbMax += cbClassicMax; + cbMax += p_scossl_ecc_get_max_size(keyCtx->classicKeyCtx, TRUE); } if (!OSSL_PARAM_set_size_t(p, cbMax)) @@ -742,16 +652,10 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx return SCOSSL_FAILURE; } - if (classicGroupName != NULL) + if (classicGroupName != NULL && + p_scossl_ecc_set_group(keyCtx->classicKeyCtx, classicGroupName) != SCOSSL_SUCCESS) { - OSSL_PARAM classicParams[2] = { - OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, (char *)classicGroupName, strlen(classicGroupName)), - OSSL_PARAM_END}; - - if (keyCtx->classicKeymgmt->import(keyCtx->classicKeyCtx, selection, classicParams) != SCOSSL_SUCCESS) - { - return SCOSSL_FAILURE; - } + return SCOSSL_FAILURE; } } @@ -1022,18 +926,34 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; - if (keyCtx->key == NULL || keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) + if (keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); goto cleanup; } - if (keyCtx->classicKeyCtx != NULL && - (cbClassicKey = p_scossl_ecc_get_encoded_key_size(keyCtx->classicKeyCtx, selection)) == 0) + if (keyCtx->key == NULL && + (keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->mlkemParams)) == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; } + if (keyCtx->classicGroupName != NULL) + { + if (keyCtx->classicKeyCtx == NULL && + (keyCtx->classicKeyCtx = p_scossl_ecc_new_ctx(keyCtx->provCtx)) == NULL) + { + goto cleanup; + } + + if (p_scossl_ecc_set_group(keyCtx->classicKeyCtx, keyCtx->classicGroupName) != SCOSSL_SUCCESS || + (cbClassicKey = p_scossl_ecc_get_encoded_key_size(keyCtx->classicKeyCtx, selection)) == 0) + { + goto cleanup; + } + } + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { keyCtx->format = cbKey - cbClassicKey == 64 ? SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED : SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; @@ -1086,7 +1006,6 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt ret = SCOSSL_SUCCESS; cleanup: - if (ret != SCOSSL_SUCCESS) { SymCryptMlKemkeyFree(keyCtx->key); @@ -1099,36 +1018,36 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt _Use_decl_annotations_ -static SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_group(SCOSSL_MLKEM_KEY_CTX *keyCtx, const char *groupName) +SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_group(SCOSSL_MLKEM_KEY_CTX *keyCtx, const char *groupName) { if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM512) == 0) { + keyCtx->groupName = SCOSSL_SN_MLKEM512; keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM512; - keyCtx->classicKeymgmt = NULL; keyCtx->classicGroupName = NULL; } else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM768) == 0) { + keyCtx->groupName = SCOSSL_SN_MLKEM768; keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; - keyCtx->classicKeymgmt = NULL; keyCtx->classicGroupName = NULL; } else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM1024) == 0) { + keyCtx->groupName = SCOSSL_SN_MLKEM1024; keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM1024; - keyCtx->classicKeymgmt = NULL; keyCtx->classicGroupName = NULL; } else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_P256_MLKEM768) == 0) { + keyCtx->groupName = SCOSSL_SN_P256_MLKEM768; keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; - keyCtx->classicKeymgmt = &p_scossl_ecc_classic_keymgmt; keyCtx->classicGroupName = SN_X9_62_prime256v1; } else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_X25519_MLKEM768) == 0) { + keyCtx->groupName = SCOSSL_SN_X25519_MLKEM768; keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; - keyCtx->classicKeymgmt = &p_scossl_x25519_classic_keymgmt; keyCtx->classicGroupName = SN_X25519; } else diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h index bb51dc70..bd88f7d5 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h @@ -15,6 +15,8 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg); +SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_group(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, _In_ const char *groupName); + SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, _Out_writes_bytes_(*pcbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index f6c4f0f5..16330c55 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -367,8 +367,8 @@ static SCOSSL_STATUS p_scossl_register_extended_algorithms() if (OBJ_create(SCOSSL_OID_MLKEM512, SCOSSL_SN_MLKEM512, SCOSSL_SN_MLKEM512) == NID_undef || OBJ_create(SCOSSL_OID_MLKEM768, SCOSSL_SN_MLKEM768, SCOSSL_SN_MLKEM768) == NID_undef || OBJ_create(SCOSSL_OID_MLKEM1024, SCOSSL_SN_MLKEM1024, SCOSSL_SN_MLKEM1024) == NID_undef || - OBJ_create(NULL, SCOSSL_SN_P256_MLKEM768, SCOSSL_SN_P256_MLKEM768) == NID_undef || - OBJ_create(NULL, SCOSSL_SN_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768) == NID_undef) + OBJ_create(SCOSSL_OID_P256_MLKEM768, SCOSSL_SN_P256_MLKEM768, SCOSSL_SN_P256_MLKEM768) == NID_undef || + OBJ_create(SCOSSL_OID_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768) == NID_undef) { return SCOSSL_FAILURE; } diff --git a/SymCryptProvider/src/p_scossl_ecc.c b/SymCryptProvider/src/p_scossl_ecc.c index d46bb318..deaa83ed 100644 --- a/SymCryptProvider/src/p_scossl_ecc.c +++ b/SymCryptProvider/src/p_scossl_ecc.c @@ -11,28 +11,277 @@ extern "C" { #endif +#define SCOSSL_X25519_MAX_SIZE (32) + +_Use_decl_annotations_ +SCOSSL_ECC_KEY_CTX *p_scossl_ecc_new_ctx(SCOSSL_PROVCTX *provctx) +{ + SCOSSL_ECC_KEY_CTX *keyCtx = OPENSSL_zalloc(sizeof(SCOSSL_ECC_KEY_CTX)); + if (keyCtx != NULL) + { + keyCtx->libctx = provctx->libctx; + keyCtx->includePublic = 1; + keyCtx->conversionFormat = POINT_CONVERSION_UNCOMPRESSED; + } + return keyCtx; +} + +_Use_decl_annotations_ +void p_scossl_ecc_free_ctx(SCOSSL_ECC_KEY_CTX *keyCtx) +{ + if (keyCtx == NULL) + return; + if (keyCtx->key != NULL) + { + SymCryptEckeyFree(keyCtx->key); + } +#ifdef KEYSINUSE_ENABLED + p_scossl_ecc_reset_keysinuse(keyCtx); + CRYPTO_THREAD_lock_free(keyCtx->keysinuseLock); +#endif + + OPENSSL_free(keyCtx); +} + +_Use_decl_annotations_ +SCOSSL_ECC_KEY_CTX *p_scossl_ecc_dup_ctx(SCOSSL_ECC_KEY_CTX *keyCtx, int selection) +{ + PBYTE pbData = NULL; + PBYTE pbPrivateKey = NULL; + PBYTE pbPublicKey = NULL; + SIZE_T cbData = 0; + SIZE_T cbPublicKey = 0; + SIZE_T cbPrivateKey = 0; + SCOSSL_STATUS success = SCOSSL_FAILURE; + SYMCRYPT_ECPOINT_FORMAT pointFormat = keyCtx->isX25519 ? SYMCRYPT_ECPOINT_FORMAT_X : SYMCRYPT_ECPOINT_FORMAT_XY; + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + + SCOSSL_ECC_KEY_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_ECC_KEY_CTX)); + + if (copyCtx != NULL) + { +#ifdef KEYSINUSE_ENABLED + copyCtx->keysinuseLock = CRYPTO_THREAD_lock_new(); + + if (keyCtx->keysinuseInfo == NULL || + p_scossl_keysinuse_upref(keyCtx->keysinuseInfo, NULL)) + { + copyCtx->keysinuseInfo = keyCtx->keysinuseInfo; + } +#endif + + copyCtx->isX25519 = keyCtx->isX25519; + copyCtx->libctx = keyCtx->libctx; + copyCtx->modifiedPrivateBits = keyCtx->modifiedPrivateBits; + copyCtx->conversionFormat = keyCtx->conversionFormat; + + if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) + { + copyCtx->curve = keyCtx->curve; + } + else + { + copyCtx->curve = NULL; + } + + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 && keyCtx->initialized) + { + if (copyCtx->curve == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); + goto cleanup; + } + + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && + SymCryptEckeyHasPrivateKey(keyCtx->key)) + { + cbPrivateKey = SymCryptEckeySizeofPrivateKey(keyCtx->key); + } + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + { + cbPublicKey = SymCryptEckeySizeofPublicKey(keyCtx->key, pointFormat); + } + + cbData = cbPrivateKey + cbPublicKey; + if ((pbData = OPENSSL_secure_malloc(cbData)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + pbPrivateKey = cbPrivateKey != 0 ? pbData : NULL; + pbPublicKey = cbPublicKey != 0 ? pbData + cbPrivateKey : NULL; + + scError = SymCryptEckeyGetValue( + keyCtx->key, + pbPrivateKey, cbPrivateKey, + pbPublicKey, cbPublicKey, + SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, + pointFormat, + 0); + if (scError != SYMCRYPT_NO_ERROR) + { + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeyGetValue failed", scError); + goto cleanup; + } + + if ((copyCtx->key = SymCryptEckeyAllocate(keyCtx->curve)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + // Default ECDH only. If the key is used for ECDSA then we call SymCryptEckeyExtendKeyUsage + scError = SymCryptEckeySetValue( + pbPrivateKey, cbPrivateKey, + pbPublicKey, cbPublicKey, + SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, + pointFormat, + SYMCRYPT_FLAG_ECKEY_ECDH, + copyCtx->key); + if (scError != SYMCRYPT_NO_ERROR) + { + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeySetValue failed", scError); + goto cleanup; + } + + copyCtx->initialized = 1; + copyCtx->includePublic = keyCtx->includePublic; + } + else + { + copyCtx->key = NULL; + copyCtx->initialized = 0; + copyCtx->includePublic = 1; + } + } + + success = SCOSSL_SUCCESS; + +cleanup: + if (pbData != NULL) + { + OPENSSL_secure_clear_free(pbData, cbData); + } + + if (!success) + { + p_scossl_ecc_free_ctx(copyCtx); + copyCtx = NULL; + } + + return copyCtx; +} + +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecc_set_group(SCOSSL_ECC_KEY_CTX *keyCtx, const char *groupName) +{ + PCSYMCRYPT_ECURVE curve; + int nid = OBJ_sn2nid(groupName); + + if (nid == NID_X25519) + { + keyCtx->isX25519 = TRUE; + curve = scossl_ecc_get_x25519_curve(); + } + else + { + keyCtx->isX25519 = FALSE; + curve = scossl_ecc_nid_to_symcrypt_curve(nid); + + if (curve == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); + return SCOSSL_FAILURE; + } + } + + keyCtx->curve = curve; + + return SCOSSL_SUCCESS; +} + +SCOSSL_STATUS p_scossl_ecc_gen(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx) +{ + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + +#ifdef KEYSINUSE_ENABLED + keyCtx->isImported = FALSE; + keyCtx->keysinuseLock = CRYPTO_THREAD_lock_new(); + keyCtx->keysinuseInfo = NULL; +#endif + + if (keyCtx->key != NULL) + { + SymCryptEckeyFree(keyCtx->key); + } + + keyCtx->key = SymCryptEckeyAllocate(keyCtx->curve); + if (keyCtx->key == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return SCOSSL_FAILURE; + } + + // Default ECDH only. If the key is used for ECDSA then we call SymCryptEckeyExtendKeyUsage + scError = SymCryptEckeySetRandom(SYMCRYPT_FLAG_ECKEY_ECDH, keyCtx->key); + if (scError != SYMCRYPT_NO_ERROR) + { + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeySetRandom failed", scError); + return SCOSSL_FAILURE; + } + + keyCtx->initialized = TRUE; + + return SCOSSL_SUCCESS; +} + +SIZE_T p_scossl_ecc_get_max_size(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, BOOL isEcdh) +{ + if (keyCtx->isX25519) + { + return SCOSSL_X25519_MAX_SIZE; + } + else if (isEcdh) + { + return keyCtx->key == NULL ? 0 : SymCryptEckeySizeofPublicKey(keyCtx->key, SYMCRYPT_ECPOINT_FORMAT_X); + } + + return scossl_ecdsa_size(keyCtx->curve); +} + _Use_decl_annotations_ SIZE_T p_scossl_ecc_get_encoded_key_size(SCOSSL_ECC_KEY_CTX *keyCtx, int selection) { - SYMCRYPT_ECPOINT_FORMAT pointFormat; + SIZE_T cbKey; - if (!keyCtx->initialized) + if (keyCtx->curve == NULL) { return 0; } - + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { - return SymCryptEckeySizeofPrivateKey(keyCtx->key); + return SymCryptEcurveSizeofScalarMultiplier(keyCtx->curve); } else if (keyCtx->isX25519) { return SymCryptEckeySizeofPublicKey(keyCtx->key, SYMCRYPT_ECPOINT_FORMAT_X); } - pointFormat = keyCtx->conversionFormat == POINT_CONVERSION_COMPRESSED ? SYMCRYPT_ECPOINT_FORMAT_X : SYMCRYPT_ECPOINT_FORMAT_XY; + cbKey = SymCryptEcurveSizeofFieldElement(keyCtx->curve); + if (!keyCtx->isX25519) + { + if (keyCtx->conversionFormat != POINT_CONVERSION_COMPRESSED) + { + cbKey *= 2; + } - return SymCryptEckeySizeofPublicKey(keyCtx->key, pointFormat) + 1; + cbKey++; + } + + return cbKey; } // Gets the public key as an encoded octet string @@ -162,7 +411,7 @@ SCOSSL_STATUS p_scossl_ecc_get_private_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, BOOL allocatedKey = FALSE; SYMCRYPT_ERROR scError; SCOSSL_STATUS ret = SCOSSL_FAILURE; - + if (!keyCtx->initialized) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); @@ -184,14 +433,13 @@ SCOSSL_STATUS p_scossl_ecc_get_private_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, else if (*pcbPrivateKey >= cbPrivateKey) { pbPrivateKey = *ppbPrivateKey; - } else { ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); goto cleanup; } - + scError = SymCryptEckeyGetValue( keyCtx->key, pbPrivateKey, cbPrivateKey, @@ -248,10 +496,10 @@ SCOSSL_STATUS p_scossl_ecc_set_encoded_key(SCOSSL_ECC_KEY_CTX *keyCtx, int selec PCBYTE pbEncodedPublicKey, SIZE_T cbEncodedPublicKey, PCBYTE pbPrivateKey, SIZE_T cbPrivateKey) { + SYMCRYPT_ECPOINT_FORMAT pointFormat = keyCtx->isX25519 ? SYMCRYPT_ECPOINT_FORMAT_X : SYMCRYPT_ECPOINT_FORMAT_XY; EC_GROUP *ecGroup = NULL; EC_POINT *ecPoint = NULL; BN_CTX *bnCtx = NULL; - PBYTE pbPublicKey = NULL; SIZE_T cbPublicKey = 0; SYMCRYPT_ERROR scError; @@ -296,7 +544,7 @@ SCOSSL_STATUS p_scossl_ecc_set_encoded_key(SCOSSL_ECC_KEY_CTX *keyCtx, int selec pbPrivateKey, cbPrivateKey, pbPublicKey, cbPublicKey, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, - SYMCRYPT_ECPOINT_FORMAT_XY, + pointFormat, SYMCRYPT_FLAG_ECKEY_ECDH, keyCtx->key); if (scError != SYMCRYPT_NO_ERROR) diff --git a/SymCryptProvider/src/p_scossl_ecc.h b/SymCryptProvider/src/p_scossl_ecc.h index 81e572e3..0f68bb0c 100644 --- a/SymCryptProvider/src/p_scossl_ecc.h +++ b/SymCryptProvider/src/p_scossl_ecc.h @@ -1,8 +1,7 @@ // // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // - -#include "scossl_helpers.h" +#include "p_scossl_base.h" #ifdef KEYSINUSE_ENABLED #include "p_scossl_keysinuse.h" #endif @@ -40,6 +39,15 @@ typedef struct { #endif } SCOSSL_ECC_KEY_CTX; +SCOSSL_ECC_KEY_CTX *p_scossl_ecc_new_ctx(_In_ SCOSSL_PROVCTX *provctx); +void p_scossl_ecc_free_ctx(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx); +SCOSSL_ECC_KEY_CTX *p_scossl_ecc_dup_ctx(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection); + +SCOSSL_STATUS p_scossl_ecc_set_group(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, _In_ const char *groupName); + +SCOSSL_STATUS p_scossl_ecc_gen(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx); + +SIZE_T p_scossl_ecc_get_max_size(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, BOOL isEcdh); SIZE_T p_scossl_ecc_get_encoded_key_size(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection); SCOSSL_STATUS p_scossl_ecc_get_encoded_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, _Out_writes_bytes_(*pcbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); From 739ce6b603c21e699980866e6f7a352c3b6ea837 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Fri, 20 Dec 2024 22:13:07 +0000 Subject: [PATCH 14/21] Cleanup ML-KEM hybrid and register algorithms --- SymCryptProvider/src/kem/p_scossl_mlkem.c | 114 ++++++++++------------ SymCryptProvider/src/p_scossl_base.c | 73 ++++++++++---- 2 files changed, 105 insertions(+), 82 deletions(-) diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.c b/SymCryptProvider/src/kem/p_scossl_mlkem.c index fb3c5a64..bfafb4c0 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.c +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.c @@ -14,15 +14,6 @@ extern "C" { #define SYMCRYPT_MLKEM_SECRET_LENGTH 32 -typedef struct { - OSSL_FUNC_keyexch_newctx_fn *newCtx; - OSSL_FUNC_keyexch_freectx_fn *freeCtx; - OSSL_FUNC_keyexch_dupctx_fn *dupCtx; - OSSL_FUNC_keyexch_init_fn *init; - OSSL_FUNC_keyexch_set_peer_fn *setPeer; - OSSL_FUNC_keyexch_derive_fn *derive; -} SCOSSL_MLKEM_CLASSIC_KEYEXCH_FNS; - typedef struct { // Unused by MLKEM, but forwarded to the classic key exchange @@ -31,21 +22,12 @@ typedef struct SCOSSL_MLKEM_KEY_CTX *keyCtx; int operation; - PVOID classicKeyexchCtx; - const SCOSSL_MLKEM_CLASSIC_KEYEXCH_FNS *classicKeyexch; + SCOSSL_ECDH_CTX *classicKeyexchCtx; } SCOSSL_MLKEM_CTX; static const OSSL_PARAM p_scossl_mlkem_param_types[] = { OSSL_PARAM_END}; -static const SCOSSL_MLKEM_CLASSIC_KEYEXCH_FNS p_scossl_ecdh_classic_keyexch = { - (OSSL_FUNC_keyexch_newctx_fn *) p_scossl_ecdh_newctx, - (OSSL_FUNC_keyexch_freectx_fn *) p_scossl_ecdh_freectx, - (OSSL_FUNC_keyexch_dupctx_fn *) p_scossl_ecdh_dupctx, - (OSSL_FUNC_keyexch_init_fn *) p_scossl_ecdh_init, - (OSSL_FUNC_keyexch_set_peer_fn *) p_scossl_ecdh_set_peer, - (OSSL_FUNC_keyexch_derive_fn *) p_scossl_ecdh_derive}; - /* Context management */ static SCOSSL_MLKEM_CTX *p_scossl_mlkem_newctx(ossl_unused void *provctx) { @@ -64,9 +46,9 @@ static void p_scossl_mlkem_freectx(_Inout_ SCOSSL_MLKEM_CTX *ctx) if (ctx == NULL) return; - if (ctx->classicKeyexch != NULL) + if (ctx->classicKeyexchCtx != NULL) { - ctx->classicKeyexch->freeCtx(ctx->classicKeyexchCtx); + p_scossl_ecdh_freectx(ctx->classicKeyexchCtx); } OPENSSL_free(ctx); @@ -81,20 +63,15 @@ static SCOSSL_MLKEM_CTX *p_scossl_mlkem_dupctx(_In_ SCOSSL_MLKEM_CTX *ctx) copyCtx->keyCtx = ctx->keyCtx; copyCtx->operation = ctx->operation; copyCtx->provCtx = ctx->provCtx; - copyCtx->classicKeyexch = ctx->classicKeyexch; if (ctx->classicKeyexchCtx != NULL) { - if (copyCtx->classicKeyexch != NULL && - (copyCtx->classicKeyexchCtx = copyCtx->classicKeyexch->dupCtx(ctx->classicKeyexchCtx)) == NULL) - { - OPENSSL_free(copyCtx); - copyCtx = NULL; - } + copyCtx->classicKeyexchCtx = NULL; } - else + else if ((copyCtx->classicKeyexchCtx = p_scossl_ecdh_dupctx(ctx->classicKeyexchCtx)) == NULL) { - copyCtx->classicKeyexchCtx = NULL; + OPENSSL_free(copyCtx); + copyCtx = NULL; } } @@ -103,15 +80,13 @@ static SCOSSL_MLKEM_CTX *p_scossl_mlkem_dupctx(_In_ SCOSSL_MLKEM_CTX *ctx) static SCOSSL_STATUS p_scossl_mlkem_classic_keyexch_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, PVOID classicKeyCtx) { - ctx->classicKeyexch = &p_scossl_ecdh_classic_keyexch; - - if ((ctx->classicKeyexchCtx = ctx->classicKeyexch->newCtx(ctx->provCtx)) == NULL) + if ((ctx->classicKeyexchCtx = p_scossl_ecdh_newctx(ctx->provCtx)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); return SCOSSL_FAILURE; } - if (ctx->classicKeyexch->init(ctx->classicKeyexchCtx, classicKeyCtx, NULL) != SCOSSL_SUCCESS) + if (p_scossl_ecdh_init(ctx->classicKeyexchCtx, classicKeyCtx, NULL) != SCOSSL_SUCCESS) { return SCOSSL_FAILURE; } @@ -143,14 +118,23 @@ static SCOSSL_STATUS p_scossl_mlkem_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, _In_ SCO // // Encapsulation // + +// We don't initialize the classic key context for hybrid here, since +// ctx->keyCtx->classicKeyCtx contains the peer key, and 'our' key is generated +// during encapsulation. static SCOSSL_STATUS p_scossl_mlkem_encapsulate_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, _In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, ossl_unused const OSSL_PARAM params[]) { return p_scossl_mlkem_init(ctx, keyCtx, EVP_PKEY_OP_ENCAPSULATE); } -// Export secret = PEER || MLKEM secret, out = ECDH secret || MLKEM CT -// Generate ECDH private key +// Performs ML-KEM encapsulation using the previously initialized context. If +// this is a hybrid group, then hybrid encapsulation is performed. +// ctx->keyCtx->classicKeyCtx is used as the peer key, and an ephemeral +// ECDH key is generated as 'our' key to derive the shared ECDH secret. +// +// secret == ECDH shared secret | MLKEM secret +// out == Ephemeral ECDH public key | MLKEM ciphertext static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, _Out_writes_bytes_opt_(*outlen) unsigned char *out, _Out_ size_t *outlen, _Out_writes_bytes_(*secretlen) unsigned char *secret, _Out_ size_t *secretlen) @@ -177,19 +161,19 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, classicKeyCtxPeer = ctx->keyCtx->classicKeyCtx; - if (ctx->classicKeyexch != NULL) + if (ctx->keyCtx->classicGroupName != NULL) { - if (ctx->keyCtx->classicKeyCtx == NULL) + if (classicKeyCtxPeer == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); goto cleanup; } // Get key size - cbClassicKey = p_scossl_ecc_get_encoded_key_size(ctx->keyCtx->classicKeyCtx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); + cbClassicKey = p_scossl_ecc_get_encoded_key_size(classicKeyCtxPeer, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); // Get secret size - if (ctx->classicKeyexch->derive(ctx->keyCtx->classicKeyCtx, NULL, &cbClassicSecret, 0) != SCOSSL_SUCCESS) + if (p_scossl_ecdh_derive(ctx->classicKeyexchCtx, NULL, &cbClassicSecret, 0) != SCOSSL_SUCCESS) { goto cleanup; } @@ -211,7 +195,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, goto cleanup; } - if (classicKeyCtxPeer != NULL) + if (ctx->keyCtx->classicGroupName != NULL) { // Generate ephemeral ECDH key if ((classicKeyCtxPrivate = p_scossl_ecc_new_ctx(ctx->provCtx)) == NULL) @@ -235,8 +219,8 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, // Derive ECDH secret if (p_scossl_mlkem_classic_keyexch_init(ctx, classicKeyCtxPrivate) != SCOSSL_SUCCESS || - ctx->classicKeyexch->setPeer(ctx->classicKeyexchCtx, ctx->keyCtx->classicKeyCtx) != SCOSSL_SUCCESS || - ctx->classicKeyexch->derive(ctx->classicKeyexchCtx, secret, &cbClassicSecret, 0) != SCOSSL_SUCCESS) + p_scossl_ecdh_set_peer(ctx->classicKeyexchCtx, classicKeyCtxPeer) != SCOSSL_SUCCESS || + p_scossl_ecdh_derive(ctx->classicKeyexchCtx, secret, &cbClassicSecret, 0) != SCOSSL_SUCCESS) { goto cleanup; } @@ -284,7 +268,13 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate_init(_Inout_ SCOSSL_MLKEM_CTX *c (ctx->keyCtx->classicKeyCtx != NULL || p_scossl_mlkem_classic_keyexch_init(ctx, ctx->keyCtx->classicKeyCtx)); } -// Set peer, derive ECDH || MLKEM CT +// Performs ML-KEM decapsulation using the previously initialized context. If +// this is a hybrid group, then hybrid decapsulation is performed. +// ctx->keyCtx->classicKeyCtx is used as 'our' key, and the peer key is +// extracted from the beginning of 'in' +// +// in == Ephemeral ECDH public key | MLKEM ciphertext +// out == ECDH shared secret | MLKEM secret static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, _Out_writes_bytes_opt_(*outlen) unsigned char *out, _Out_ size_t *outlen, _In_reads_bytes_(inlen) const unsigned char *in, size_t inlen) @@ -292,7 +282,8 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, SIZE_T cbClassicKey = 0; SIZE_T cbMlkemCiphertext = 0; SIZE_T cbClassicSecret = 0; - SCOSSL_ECC_KEY_CTX *classicKeyCtxPublic = NULL; + SCOSSL_ECC_KEY_CTX *classicKeyCtxPeer = NULL; + SCOSSL_ECC_KEY_CTX *classicKeyCtxPrivate = NULL; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -308,19 +299,21 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, goto cleanup; } - if (ctx->classicKeyexch != NULL) + classicKeyCtxPrivate = ctx->keyCtx->classicKeyCtx; + + if (ctx->keyCtx->classicGroupName != NULL) { - if (ctx->keyCtx->classicKeyCtx == NULL) + if (classicKeyCtxPrivate == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); goto cleanup; } // Get key size - cbClassicKey = p_scossl_ecc_get_encoded_key_size(ctx->keyCtx->classicKeyCtx, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); + cbClassicKey = p_scossl_ecc_get_encoded_key_size(classicKeyCtxPrivate, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); // Get secret size - if (ctx->classicKeyexch->derive(ctx->keyCtx->classicKeyCtx, NULL, &cbClassicSecret, 0) != SCOSSL_SUCCESS) + if (p_scossl_ecdh_derive(ctx->classicKeyexchCtx, NULL, &cbClassicSecret, 0) != SCOSSL_SUCCESS) { goto cleanup; } @@ -347,29 +340,24 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, goto cleanup; } - if (ctx->classicKeyexch != NULL) + if (ctx->keyCtx->classicGroupName != NULL) { // Extract ECDH public key from in - if ((classicKeyCtxPublic = p_scossl_ecc_new_ctx(ctx->provCtx)) == NULL) + if ((classicKeyCtxPeer = p_scossl_ecc_new_ctx(ctx->provCtx)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; } - if (p_scossl_ecc_set_group(classicKeyCtxPublic, ctx->keyCtx->classicGroupName) != SCOSSL_SUCCESS || - p_scossl_ecc_get_encoded_key(classicKeyCtxPublic, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, &out, &cbClassicKey) != SCOSSL_SUCCESS) + if (p_scossl_ecc_set_group(classicKeyCtxPeer, ctx->keyCtx->classicGroupName) != SCOSSL_SUCCESS || + p_scossl_ecc_get_encoded_key(classicKeyCtxPeer, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, &out, &cbClassicKey) != SCOSSL_SUCCESS) { goto cleanup; } - // Set ECDH peer - if (ctx->classicKeyexch->setPeer(ctx->classicKeyexchCtx, classicKeyCtxPublic) != SCOSSL_SUCCESS) - { - goto cleanup; - } // Derive shared ECDH secret - if (ctx->classicKeyexch->setPeer(ctx->classicKeyexchCtx, classicKeyCtxPublic) != SCOSSL_SUCCESS || - ctx->classicKeyexch->derive(ctx->classicKeyexchCtx, out, &cbClassicSecret, 0) != SCOSSL_SUCCESS) + if (p_scossl_ecdh_set_peer(ctx->classicKeyexchCtx, classicKeyCtxPeer) != SCOSSL_SUCCESS || + p_scossl_ecdh_derive(ctx->classicKeyexchCtx, out, &cbClassicSecret, 0) != SCOSSL_SUCCESS) { goto cleanup; } @@ -398,7 +386,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, ret = SCOSSL_SUCCESS; cleanup: - p_scossl_ecc_free_ctx(classicKeyCtxPublic); + p_scossl_ecc_free_ctx(classicKeyCtxPeer); return ret; } diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index 16330c55..eba09996 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -31,15 +31,20 @@ extern "C" { #define SCOSSL_MAX_CONFIGURABLE_FILE_SIZE (2 << 30) #endif -#define OSSL_TLS_GROUP_ID_secp192r1 0x0013 -#define OSSL_TLS_GROUP_ID_secp224r1 0x0015 -#define OSSL_TLS_GROUP_ID_secp256r1 0x0017 -#define OSSL_TLS_GROUP_ID_secp384r1 0x0018 -#define OSSL_TLS_GROUP_ID_secp521r1 0x0019 -#define OSSL_TLS_GROUP_ID_x25519 0x001D -#define OSSL_TLS_GROUP_ID_ffdhe2048 0x0100 -#define OSSL_TLS_GROUP_ID_ffdhe3072 0x0101 -#define OSSL_TLS_GROUP_ID_ffdhe4096 0x0102 +#define SCOSSL_TLS_GROUP_ID_secp192r1 0x0013 +#define SCOSSL_TLS_GROUP_ID_secp224r1 0x0015 +#define SCOSSL_TLS_GROUP_ID_secp256r1 0x0017 +#define SCOSSL_TLS_GROUP_ID_secp384r1 0x0018 +#define SCOSSL_TLS_GROUP_ID_secp521r1 0x0019 +#define SCOSSL_TLS_GROUP_ID_x25519 0x001d +#define SCOSSL_TLS_GROUP_ID_ffdhe2048 0x0100 +#define SCOSSL_TLS_GROUP_ID_ffdhe3072 0x0101 +#define SCOSSL_TLS_GROUP_ID_ffdhe4096 0x0102 +#define SCOSSL_TLS_GROUP_ID_mlkem512 0x0200 +#define SCOSSL_TLS_GROUP_ID_mlkem768 0x0201 +#define SCOSSL_TLS_GROUP_ID_mlkem1024 0x0202 +#define SCOSSL_TLS_GROUP_ID_secp256r1mlkem768 0x11eb +#define SCOSSL_TLS_GROUP_ID_x25519mlkem768 0x11ec #define ALG(names, funcs) {names, "provider="P_SCOSSL_NAME",fips=yes", funcs, NULL} #define ALG_DECODER(algNames, name, decoderType) { \ @@ -79,47 +84,72 @@ typedef struct { } SCOSSL_TLS_GROUP_INFO; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_p192 = { - OSSL_TLS_GROUP_ID_secp192r1, 80, + SCOSSL_TLS_GROUP_ID_secp192r1, 80, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_p224 = { - OSSL_TLS_GROUP_ID_secp224r1, 112, + SCOSSL_TLS_GROUP_ID_secp224r1, 112, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_p256 = { - OSSL_TLS_GROUP_ID_secp256r1, 128, + SCOSSL_TLS_GROUP_ID_secp256r1, 128, TLS1_VERSION, 0, DTLS1_VERSION, 0}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_p384 = { - OSSL_TLS_GROUP_ID_secp384r1, 192, + SCOSSL_TLS_GROUP_ID_secp384r1, 192, TLS1_VERSION, 0, DTLS1_VERSION, 0}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_p521 = { - OSSL_TLS_GROUP_ID_secp521r1, 256, + SCOSSL_TLS_GROUP_ID_secp521r1, 256, TLS1_VERSION, 0, DTLS1_VERSION, 0}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_x25519 = { - OSSL_TLS_GROUP_ID_x25519, 128, + SCOSSL_TLS_GROUP_ID_x25519, 128, TLS1_VERSION, 0, DTLS1_VERSION, 0}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_ffdhe2048 = { - OSSL_TLS_GROUP_ID_ffdhe2048, 112, + SCOSSL_TLS_GROUP_ID_ffdhe2048, 112, TLS1_3_VERSION, 0, -1, -1}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_ffdhe3072 = { - OSSL_TLS_GROUP_ID_ffdhe3072, 128, + SCOSSL_TLS_GROUP_ID_ffdhe3072, 128, TLS1_3_VERSION, 0, -1, -1}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_ffdhe4096 = { - OSSL_TLS_GROUP_ID_ffdhe4096, 128, + SCOSSL_TLS_GROUP_ID_ffdhe4096, 128, + TLS1_3_VERSION, 0, + -1, -1}; + +const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_mlkem512 = { + SCOSSL_TLS_GROUP_ID_mlkem512, 128, + TLS1_3_VERSION, 0, + -1, -1}; + +const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_mlkem768 = { + SCOSSL_TLS_GROUP_ID_mlkem768, 192, + TLS1_3_VERSION, 0, + -1, -1}; + +const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_mlkem1024 = { + SCOSSL_TLS_GROUP_ID_mlkem1024, 215, + TLS1_3_VERSION, 0, + -1, -1}; + +const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_secp256r1mlkem768 = { + SCOSSL_TLS_GROUP_ID_secp256r1mlkem768, 192, + TLS1_3_VERSION, 0, + -1, -1}; + +const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_x25519mlkem768 = { + SCOSSL_TLS_GROUP_ID_x25519mlkem768, 192, TLS1_3_VERSION, 0, -1, -1}; @@ -153,7 +183,12 @@ static const OSSL_PARAM p_scossl_supported_group_list[][11] = { TLS_GROUP_ENTRY("x25519", SN_X25519, "X25519", scossl_tls_group_info_x25519), TLS_GROUP_ENTRY("ffdhe2048", SN_ffdhe2048, "DH", scossl_tls_group_info_ffdhe2048), TLS_GROUP_ENTRY("ffdhe3072", SN_ffdhe3072, "DH", scossl_tls_group_info_ffdhe3072), - TLS_GROUP_ENTRY("ffdhe4096", SN_ffdhe4096, "DH", scossl_tls_group_info_ffdhe4096)}; + TLS_GROUP_ENTRY("ffdhe4096", SN_ffdhe4096, "DH", scossl_tls_group_info_ffdhe4096), + TLS_GROUP_ENTRY("mlkem512", SCOSSL_SN_MLKEM512, "MLKEM", scossl_tls_group_info_mlkem512), + TLS_GROUP_ENTRY("mlkem768", SCOSSL_SN_MLKEM768, "MLKEM", scossl_tls_group_info_mlkem768), + TLS_GROUP_ENTRY("mlkem1024", SCOSSL_SN_MLKEM1024, "MLKEM", scossl_tls_group_info_mlkem1024), + TLS_GROUP_ENTRY("secp256r1mlkem768", SCOSSL_SN_P256_MLKEM768, "MLKEM", scossl_tls_group_info_secp256r1mlkem768), + TLS_GROUP_ENTRY("x25519mlkem768", SCOSSL_SN_X25519_MLKEM768, "MLKEM", scossl_tls_group_info_x25519mlkem768)}; // Digest extern const OSSL_DISPATCH p_scossl_md5_functions[]; From 6c5ff94601aa0ad8e55c36783ca69aadf23e1892 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Thu, 26 Dec 2024 22:01:41 +0000 Subject: [PATCH 15/21] Bugfixes for compatibility with public PQ endpoints --- SymCryptProvider/src/kem/p_scossl_mlkem.c | 59 ++++++------ SymCryptProvider/src/keyexch/p_scossl_ecdh.c | 4 +- .../src/keymgmt/p_scossl_ecc_keymgmt.c | 5 +- .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 26 +++--- SymCryptProvider/src/p_scossl_base.c | 30 +++--- SymCryptProvider/src/p_scossl_ecc.c | 93 +++++++++++++++---- SymCryptProvider/src/p_scossl_ecc.h | 2 +- 7 files changed, 144 insertions(+), 75 deletions(-) diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.c b/SymCryptProvider/src/kem/p_scossl_mlkem.c index bfafb4c0..92298306 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.c +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.c @@ -80,7 +80,8 @@ static SCOSSL_MLKEM_CTX *p_scossl_mlkem_dupctx(_In_ SCOSSL_MLKEM_CTX *ctx) static SCOSSL_STATUS p_scossl_mlkem_classic_keyexch_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, PVOID classicKeyCtx) { - if ((ctx->classicKeyexchCtx = p_scossl_ecdh_newctx(ctx->provCtx)) == NULL) + if (ctx->classicKeyexchCtx == NULL && + (ctx->classicKeyexchCtx = p_scossl_ecdh_newctx(ctx->provCtx)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); return SCOSSL_FAILURE; @@ -173,7 +174,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, cbClassicKey = p_scossl_ecc_get_encoded_key_size(classicKeyCtxPeer, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); // Get secret size - if (p_scossl_ecdh_derive(ctx->classicKeyexchCtx, NULL, &cbClassicSecret, 0) != SCOSSL_SUCCESS) + if ((cbClassicSecret = p_scossl_ecc_get_max_size(classicKeyCtxPeer, TRUE)) == 0) { goto cleanup; } @@ -195,6 +196,16 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, goto cleanup; } + scError = SymCryptMlKemEncapsulate(ctx->keyCtx->key, secret, SYMCRYPT_MLKEM_SECRET_LENGTH, out, cbMlkemCiphertext); + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + out += cbMlkemCiphertext; + secret += SYMCRYPT_MLKEM_SECRET_LENGTH; + if (ctx->keyCtx->classicGroupName != NULL) { // Generate ephemeral ECDH key @@ -215,23 +226,14 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, { goto cleanup; } - out += cbClassicKey; // Derive ECDH secret if (p_scossl_mlkem_classic_keyexch_init(ctx, classicKeyCtxPrivate) != SCOSSL_SUCCESS || p_scossl_ecdh_set_peer(ctx->classicKeyexchCtx, classicKeyCtxPeer) != SCOSSL_SUCCESS || - p_scossl_ecdh_derive(ctx->classicKeyexchCtx, secret, &cbClassicSecret, 0) != SCOSSL_SUCCESS) + p_scossl_ecdh_derive(ctx->classicKeyexchCtx, secret, &cbClassicSecret, *secretlen) != SCOSSL_SUCCESS) { goto cleanup; } - secret += cbClassicSecret; - } - - scError = SymCryptMlKemEncapsulate(ctx->keyCtx->key, secret, SYMCRYPT_MLKEM_SECRET_LENGTH, out, cbMlkemCiphertext); - if (scError != SYMCRYPT_NO_ERROR) - { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - goto cleanup; } } else if (outlen == NULL && secretlen == NULL) @@ -265,7 +267,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate_init(_Inout_ SCOSSL_MLKEM_CTX *c ossl_unused const OSSL_PARAM params[]) { return p_scossl_mlkem_init(ctx, keyCtx, EVP_PKEY_OP_DECAPSULATE) && - (ctx->keyCtx->classicKeyCtx != NULL || p_scossl_mlkem_classic_keyexch_init(ctx, ctx->keyCtx->classicKeyCtx)); + p_scossl_mlkem_classic_keyexch_init(ctx, ctx->keyCtx->classicKeyCtx); } // Performs ML-KEM decapsulation using the previously initialized context. If @@ -313,7 +315,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, cbClassicKey = p_scossl_ecc_get_encoded_key_size(classicKeyCtxPrivate, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); // Get secret size - if (p_scossl_ecdh_derive(ctx->classicKeyexchCtx, NULL, &cbClassicSecret, 0) != SCOSSL_SUCCESS) + if ((cbClassicSecret = p_scossl_ecc_get_max_size(classicKeyCtxPrivate, TRUE)) == 0) { goto cleanup; } @@ -326,7 +328,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, goto cleanup; } - if (inlen != cbClassicKey + cbMlkemCiphertext) + if (inlen != cbMlkemCiphertext + cbClassicKey) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH); goto cleanup; @@ -334,12 +336,22 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, if (out != NULL) { - if (outlen != NULL && *outlen < SYMCRYPT_MLKEM_SECRET_LENGTH) + if (outlen != NULL && *outlen < SYMCRYPT_MLKEM_SECRET_LENGTH + cbClassicSecret) { ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); goto cleanup; } + scError = SymCryptMlKemDecapsulate(ctx->keyCtx->key, in, cbMlkemCiphertext, out, SYMCRYPT_MLKEM_SECRET_LENGTH); + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + in += cbMlkemCiphertext; + out += SYMCRYPT_MLKEM_SECRET_LENGTH; + if (ctx->keyCtx->classicGroupName != NULL) { // Extract ECDH public key from in @@ -350,26 +362,17 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, } if (p_scossl_ecc_set_group(classicKeyCtxPeer, ctx->keyCtx->classicGroupName) != SCOSSL_SUCCESS || - p_scossl_ecc_get_encoded_key(classicKeyCtxPeer, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, &out, &cbClassicKey) != SCOSSL_SUCCESS) + p_scossl_ecc_set_encoded_key(classicKeyCtxPeer, in, cbClassicKey, NULL, 0) != SCOSSL_SUCCESS) { goto cleanup; } // Derive shared ECDH secret if (p_scossl_ecdh_set_peer(ctx->classicKeyexchCtx, classicKeyCtxPeer) != SCOSSL_SUCCESS || - p_scossl_ecdh_derive(ctx->classicKeyexchCtx, out, &cbClassicSecret, 0) != SCOSSL_SUCCESS) + p_scossl_ecdh_derive(ctx->classicKeyexchCtx, out, &cbClassicSecret, *outlen - SYMCRYPT_MLKEM_SECRET_LENGTH) != SCOSSL_SUCCESS) { goto cleanup; } - out += cbClassicSecret; - } - - scError = SymCryptMlKemDecapsulate(ctx->keyCtx->key, in, inlen, out, SYMCRYPT_MLKEM_SECRET_LENGTH); - - if (scError != SYMCRYPT_NO_ERROR) - { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - goto cleanup; } } else if (outlen == NULL) @@ -380,7 +383,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, if (outlen != NULL) { - *outlen = SYMCRYPT_MLKEM_SECRET_LENGTH; + *outlen = SYMCRYPT_MLKEM_SECRET_LENGTH + cbClassicSecret; } ret = SCOSSL_SUCCESS; diff --git a/SymCryptProvider/src/keyexch/p_scossl_ecdh.c b/SymCryptProvider/src/keyexch/p_scossl_ecdh.c index 65f5f128..1b0f0e18 100644 --- a/SymCryptProvider/src/keyexch/p_scossl_ecdh.c +++ b/SymCryptProvider/src/keyexch/p_scossl_ecdh.c @@ -101,7 +101,7 @@ SCOSSL_STATUS p_scossl_ecdh_derive(SCOSSL_ECDH_CTX *ctx, SIZE_T cbSecretBuf = 0; SCOSSL_STATUS ret = SCOSSL_FAILURE; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; - SYMCRYPT_NUMBER_FORMAT numberFormat = ctx->keyCtx->isX25519 ? SYMCRYPT_NUMBER_FORMAT_LSB_FIRST : SYMCRYPT_NUMBER_FORMAT_MSB_FIRST; + SYMCRYPT_NUMBER_FORMAT numberFormat; if (ctx == NULL || secretlen == NULL) { @@ -121,6 +121,8 @@ SCOSSL_STATUS p_scossl_ecdh_derive(SCOSSL_ECDH_CTX *ctx, return SCOSSL_FAILURE; } + numberFormat = ctx->keyCtx->isX25519 ? SYMCRYPT_NUMBER_FORMAT_LSB_FIRST : SYMCRYPT_NUMBER_FORMAT_MSB_FIRST; + if (outlen < cbSecretBuf) { if ((pbSecretBuf = OPENSSL_secure_malloc(cbSecretBuf)) == NULL) diff --git a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c index 525801b2..a576ab07 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c @@ -276,6 +276,7 @@ SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keygen(SCOSSL_ECC_KEYGEN_CTX *genCtx, ossl_unus keyCtx->curve = genCtx->curve; keyCtx->isX25519 = genCtx->isX25519; keyCtx->conversionFormat = genCtx->conversionFormat; + keyCtx->key = NULL; if (p_scossl_ecc_gen(keyCtx) != SCOSSL_SUCCESS) { @@ -946,7 +947,7 @@ SCOSSL_STATUS p_scossl_ecc_keymgmt_import(SCOSSL_ECC_KEY_CTX *keyCtx, int select goto cleanup; } - cbPrivateKey = SymCryptEckeySizeofPrivateKey(keyCtx->key); + cbPrivateKey = p_scossl_ecc_get_encoded_key_size(keyCtx, OSSL_KEYMGMT_SELECT_PRIVATE_KEY); if ((pbPrivateKey = OPENSSL_secure_malloc(cbPrivateKey)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); @@ -960,7 +961,7 @@ SCOSSL_STATUS p_scossl_ecc_keymgmt_import(SCOSSL_ECC_KEY_CTX *keyCtx, int select } } - ret = p_scossl_ecc_set_encoded_key(keyCtx, selection, + ret = p_scossl_ecc_set_encoded_key(keyCtx, pbEncodedPublicKey, cbEncodedPublicKey, pbPrivateKey, cbPrivateKey); diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index a04c4c2a..e59726d2 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -885,8 +885,8 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX goto cleanup; } - pbClassicKey = pbKey; - pbMlKemKey = pbKey + cbClassicKey; + pbMlKemKey = pbKey; + pbClassicKey = pbKey + cbMlKemKey; if (keyCtx->classicKeyCtx != NULL && p_scossl_ecc_get_encoded_key(keyCtx->classicKeyCtx, selection, &pbClassicKey, &cbClassicKey) != SCOSSL_SUCCESS) @@ -976,18 +976,25 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt goto cleanup; } - pbClassicKey = pbKey; - pbMlKemKey = pbKey + cbClassicKey; + pbMlKemKey = pbKey; + pbClassicKey = pbKey + cbMlKemKey; + + scError = SymCryptMlKemkeySetValue(pbMlKemKey, cbMlKemKey, keyCtx->format, 0, keyCtx->key); + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } if (keyCtx->classicKeyCtx != NULL) { if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { - ret = p_scossl_ecc_set_encoded_key(keyCtx->classicKeyCtx, selection, NULL, 0, pbClassicKey, cbClassicKey); + ret = p_scossl_ecc_set_encoded_key(keyCtx->classicKeyCtx, NULL, 0, pbClassicKey, cbClassicKey); } else { - ret = p_scossl_ecc_set_encoded_key(keyCtx->classicKeyCtx, selection, pbClassicKey, cbClassicKey, NULL, 0); + ret = p_scossl_ecc_set_encoded_key(keyCtx->classicKeyCtx, pbClassicKey, cbClassicKey, NULL, 0); } if (ret != SCOSSL_SUCCESS) @@ -996,13 +1003,6 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt } } - scError = SymCryptMlKemkeySetValue(pbMlKemKey, cbMlKemKey, keyCtx->format, 0, keyCtx->key); - if (scError != SYMCRYPT_NO_ERROR) - { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - goto cleanup; - } - ret = SCOSSL_SUCCESS; cleanup: diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index eba09996..2409cca4 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -77,6 +77,7 @@ extern "C" { typedef struct { unsigned int groupId; unsigned int securityBits; + int is_kem; int minTls; int maxTls; int minDtls; @@ -84,72 +85,72 @@ typedef struct { } SCOSSL_TLS_GROUP_INFO; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_p192 = { - SCOSSL_TLS_GROUP_ID_secp192r1, 80, + SCOSSL_TLS_GROUP_ID_secp192r1, 80, 0, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_p224 = { - SCOSSL_TLS_GROUP_ID_secp224r1, 112, + SCOSSL_TLS_GROUP_ID_secp224r1, 112, 0, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_p256 = { - SCOSSL_TLS_GROUP_ID_secp256r1, 128, + SCOSSL_TLS_GROUP_ID_secp256r1, 128, 0, TLS1_VERSION, 0, DTLS1_VERSION, 0}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_p384 = { - SCOSSL_TLS_GROUP_ID_secp384r1, 192, + SCOSSL_TLS_GROUP_ID_secp384r1, 192, 0, TLS1_VERSION, 0, DTLS1_VERSION, 0}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_p521 = { - SCOSSL_TLS_GROUP_ID_secp521r1, 256, + SCOSSL_TLS_GROUP_ID_secp521r1, 256, 0, TLS1_VERSION, 0, DTLS1_VERSION, 0}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_x25519 = { - SCOSSL_TLS_GROUP_ID_x25519, 128, + SCOSSL_TLS_GROUP_ID_x25519, 128, 0, TLS1_VERSION, 0, DTLS1_VERSION, 0}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_ffdhe2048 = { - SCOSSL_TLS_GROUP_ID_ffdhe2048, 112, + SCOSSL_TLS_GROUP_ID_ffdhe2048, 112, 0, TLS1_3_VERSION, 0, -1, -1}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_ffdhe3072 = { - SCOSSL_TLS_GROUP_ID_ffdhe3072, 128, + SCOSSL_TLS_GROUP_ID_ffdhe3072, 128, 0, TLS1_3_VERSION, 0, -1, -1}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_ffdhe4096 = { - SCOSSL_TLS_GROUP_ID_ffdhe4096, 128, + SCOSSL_TLS_GROUP_ID_ffdhe4096, 128, 0, TLS1_3_VERSION, 0, -1, -1}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_mlkem512 = { - SCOSSL_TLS_GROUP_ID_mlkem512, 128, + SCOSSL_TLS_GROUP_ID_mlkem512, 128, 1, TLS1_3_VERSION, 0, -1, -1}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_mlkem768 = { - SCOSSL_TLS_GROUP_ID_mlkem768, 192, + SCOSSL_TLS_GROUP_ID_mlkem768, 192, 1, TLS1_3_VERSION, 0, -1, -1}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_mlkem1024 = { - SCOSSL_TLS_GROUP_ID_mlkem1024, 215, + SCOSSL_TLS_GROUP_ID_mlkem1024, 256, 1, TLS1_3_VERSION, 0, -1, -1}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_secp256r1mlkem768 = { - SCOSSL_TLS_GROUP_ID_secp256r1mlkem768, 192, + SCOSSL_TLS_GROUP_ID_secp256r1mlkem768, 192, 1, TLS1_3_VERSION, 0, -1, -1}; const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_x25519mlkem768 = { - SCOSSL_TLS_GROUP_ID_x25519mlkem768, 192, + SCOSSL_TLS_GROUP_ID_x25519mlkem768, 192, 1, TLS1_3_VERSION, 0, -1, -1}; @@ -163,6 +164,7 @@ const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_x25519mlkem768 = { OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_TLS, (int *)&group_info.maxTls), \ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS, (int *)&group_info.minTls), \ OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS, (int *)&group_info.maxTls), \ + OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_IS_KEM, (int *)&group_info.is_kem), \ OSSL_PARAM_END} static int scossl_prov_initialized = 0; diff --git a/SymCryptProvider/src/p_scossl_ecc.c b/SymCryptProvider/src/p_scossl_ecc.c index deaa83ed..c80150b3 100644 --- a/SymCryptProvider/src/p_scossl_ecc.c +++ b/SymCryptProvider/src/p_scossl_ecc.c @@ -492,16 +492,19 @@ SCOSSL_STATUS p_scossl_ecc_get_encoded_key(SCOSSL_ECC_KEY_CTX *keyCtx, int selec } _Use_decl_annotations_ -SCOSSL_STATUS p_scossl_ecc_set_encoded_key(SCOSSL_ECC_KEY_CTX *keyCtx, int selection, +SCOSSL_STATUS p_scossl_ecc_set_encoded_key(SCOSSL_ECC_KEY_CTX *keyCtx, PCBYTE pbEncodedPublicKey, SIZE_T cbEncodedPublicKey, - PCBYTE pbPrivateKey, SIZE_T cbPrivateKey) + PCBYTE pbEncodedPrivateKey, SIZE_T cbEncodedPrivateKey) { - SYMCRYPT_ECPOINT_FORMAT pointFormat = keyCtx->isX25519 ? SYMCRYPT_ECPOINT_FORMAT_X : SYMCRYPT_ECPOINT_FORMAT_XY; + SYMCRYPT_NUMBER_FORMAT numFormat; + SYMCRYPT_ECPOINT_FORMAT pointFormat; EC_GROUP *ecGroup = NULL; EC_POINT *ecPoint = NULL; BN_CTX *bnCtx = NULL; PBYTE pbPublicKey = NULL; SIZE_T cbPublicKey = 0; + PBYTE pbPrivateKey = NULL; + SIZE_T cbPrivateKey = 0; SYMCRYPT_ERROR scError; SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -515,35 +518,82 @@ SCOSSL_STATUS p_scossl_ecc_set_encoded_key(SCOSSL_ECC_KEY_CTX *keyCtx, int selec p_scossl_ecc_reset_keysinuse(keyCtx); #endif + if (keyCtx->isX25519) + { + numFormat = SYMCRYPT_NUMBER_FORMAT_LSB_FIRST; + pointFormat = SYMCRYPT_ECPOINT_FORMAT_X; + } + else + { + numFormat = SYMCRYPT_NUMBER_FORMAT_MSB_FIRST; + pointFormat = SYMCRYPT_ECPOINT_FORMAT_XY; + } + if ((keyCtx->key = SymCryptEckeyAllocate(keyCtx->curve)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; } - if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + if (pbEncodedPublicKey != NULL) { - cbPublicKey = SymCryptEckeySizeofPublicKey(keyCtx->key, SYMCRYPT_ECPOINT_FORMAT_XY); - if (((ecPoint = EC_POINT_new(ecGroup)) == NULL) || - ((bnCtx = BN_CTX_new_ex(keyCtx->libctx)) == NULL) || - ((pbPublicKey = OPENSSL_malloc(cbPublicKey)) == NULL)) + if (keyCtx->isX25519) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; + pbPublicKey = (PBYTE) pbEncodedPublicKey; + cbPublicKey = cbEncodedPublicKey; + } + else + { + cbPublicKey = SymCryptEckeySizeofPublicKey(keyCtx->key, SYMCRYPT_ECPOINT_FORMAT_XY); + if (((ecGroup = scossl_ecc_symcrypt_curve_to_ecc_group(keyCtx->curve)) == NULL) || + ((ecPoint = EC_POINT_new(ecGroup)) == NULL) || + ((bnCtx = BN_CTX_new_ex(keyCtx->libctx)) == NULL) || + ((pbPublicKey = OPENSSL_malloc(cbPublicKey)) == NULL)) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + if (!EC_POINT_oct2point(ecGroup, ecPoint, pbEncodedPublicKey, cbEncodedPublicKey, bnCtx) || + !scossl_ec_point_to_pubkey(ecPoint, ecGroup, bnCtx, pbPublicKey, cbPublicKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + goto cleanup; + } } + } - if (!EC_POINT_oct2point(ecGroup, ecPoint, pbEncodedPublicKey, cbEncodedPublicKey, bnCtx) || - !scossl_ec_point_to_pubkey(ecPoint, ecGroup, bnCtx, pbPublicKey, cbPublicKey)) + if (pbEncodedPrivateKey != NULL) + { + if (keyCtx->isX25519) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - goto cleanup; + if ((pbPrivateKey = OPENSSL_secure_malloc(cbEncodedPrivateKey)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + memcpy(pbPrivateKey, pbEncodedPrivateKey, cbEncodedPrivateKey); + + // Preserve original bits for export + keyCtx->modifiedPrivateBits = pbPrivateKey[0] & 0x07; + keyCtx->modifiedPrivateBits |= pbPrivateKey[cbPrivateKey-1] & 0xc0; + + pbPrivateKey[0] &= 0xf8; + pbPrivateKey[cbPrivateKey-1] &= 0x7f; + pbPrivateKey[cbPrivateKey-1] |= 0x40; + } + else + { + pbPrivateKey = (PBYTE) pbEncodedPrivateKey; + cbPrivateKey = cbEncodedPrivateKey; } } scError = SymCryptEckeySetValue( pbPrivateKey, cbPrivateKey, pbPublicKey, cbPublicKey, - SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, + numFormat, pointFormat, SYMCRYPT_FLAG_ECKEY_ECDH, keyCtx->key); @@ -561,10 +611,21 @@ SCOSSL_STATUS p_scossl_ecc_set_encoded_key(SCOSSL_ECC_KEY_CTX *keyCtx, int selec keyCtx->key != NULL) { SymCryptEckeyFree(keyCtx->key); + keyCtx->key = NULL; + } + + // X25519 needs to copy and decode the private key, other ECC needs + // to copy and decode the public key. + if (keyCtx->isX25519) + { + OPENSSL_secure_clear_free(pbPrivateKey, cbPrivateKey); + } + else + { + OPENSSL_free(pbPublicKey); } EC_GROUP_free(ecGroup); - OPENSSL_free(pbPublicKey); EC_POINT_free(ecPoint); BN_CTX_free(bnCtx); diff --git a/SymCryptProvider/src/p_scossl_ecc.h b/SymCryptProvider/src/p_scossl_ecc.h index 0f68bb0c..67fe7464 100644 --- a/SymCryptProvider/src/p_scossl_ecc.h +++ b/SymCryptProvider/src/p_scossl_ecc.h @@ -51,7 +51,7 @@ SIZE_T p_scossl_ecc_get_max_size(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, BOOL isEcdh); SIZE_T p_scossl_ecc_get_encoded_key_size(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection); SCOSSL_STATUS p_scossl_ecc_get_encoded_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, _Out_writes_bytes_(*pcbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); -SCOSSL_STATUS p_scossl_ecc_set_encoded_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, +SCOSSL_STATUS p_scossl_ecc_set_encoded_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, _In_reads_bytes_opt_(cbEncodedPublicKey) PCBYTE pbEncodedPublicKey, SIZE_T cbEncodedPublicKey, _In_reads_bytes_opt_(cbPrivateKey) PCBYTE pbPrivateKey, SIZE_T cbPrivateKey); From 05f1c24a20c6fc9bfcae210ac9d6965671749c89 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Fri, 27 Dec 2024 00:28:41 +0000 Subject: [PATCH 16/21] Fix ordering for non-x25519 hybrid and add P384MLKEM1024 --- SymCryptProvider/inc/scossl_provider.h | 3 + .../src/decoder/p_scossl_decode_mlkem.c | 3 +- SymCryptProvider/src/kem/p_scossl_mlkem.c | 99 +++++++++++++------ .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 38 +++++-- SymCryptProvider/src/p_scossl_base.c | 12 ++- 5 files changed, 114 insertions(+), 41 deletions(-) diff --git a/SymCryptProvider/inc/scossl_provider.h b/SymCryptProvider/inc/scossl_provider.h index 6f3ef0f5..eacedbe9 100644 --- a/SymCryptProvider/inc/scossl_provider.h +++ b/SymCryptProvider/inc/scossl_provider.h @@ -57,6 +57,9 @@ extern "C" { #define SCOSSL_SN_X25519_MLKEM768 SN_X25519 SCOSSL_SN_MLKEM768 #define SCOSSL_OID_X25519_MLKEM768 "2.16.840.1.101.3.4.4.5" +#define SCOSSL_SN_P384_MLKEM1024 SN_secp384r1 SCOSSL_SN_MLKEM1024 +#define SCOSSL_OID_P384_MLKEM1024 "2.16.840.1.101.3.4.4.6" + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c index c5a26105..d499a1f5 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c +++ b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c @@ -24,7 +24,8 @@ static SCOSSL_DECODE_MLKEM_PARAM_MAP p_scossl_decode_mlkem_param_maps[] = { {-1, SCOSSL_SN_MLKEM768}, {-1, SCOSSL_SN_MLKEM1024}, {-1, SCOSSL_SN_P256_MLKEM768}, - {-1, SCOSSL_SN_X25519_MLKEM768}}; + {-1, SCOSSL_SN_X25519_MLKEM768}, + {-1, SCOSSL_SN_P384_MLKEM1024}}; static const char *p_scossl_decode_mlkem_obj_to_groupname(const ASN1_OBJECT *obj) { diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.c b/SymCryptProvider/src/kem/p_scossl_mlkem.c index 92298306..0dc3ade0 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.c +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.c @@ -140,6 +140,10 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, _Out_writes_bytes_opt_(*outlen) unsigned char *out, _Out_ size_t *outlen, _Out_writes_bytes_(*secretlen) unsigned char *secret, _Out_ size_t *secretlen) { + PBYTE pbMlkemCipherText = NULL; + PBYTE pbClassicKey = NULL; + PBYTE pbMlkemSecret = NULL; + PBYTE pbClassicSecret = NULL; SIZE_T cbClassicKey = 0; SIZE_T cbMlkemCiphertext = 0; SIZE_T cbClassicSecret = 0; @@ -189,25 +193,23 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, if (out != NULL) { - if ((outlen != NULL && *outlen < cbClassicKey + cbMlkemCiphertext) || - (secretlen != NULL && *secretlen < cbClassicSecret + SYMCRYPT_MLKEM_SECRET_LENGTH)) - { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - goto cleanup; - } - - scError = SymCryptMlKemEncapsulate(ctx->keyCtx->key, secret, SYMCRYPT_MLKEM_SECRET_LENGTH, out, cbMlkemCiphertext); - if (scError != SYMCRYPT_NO_ERROR) - { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - goto cleanup; - } - - out += cbMlkemCiphertext; - secret += SYMCRYPT_MLKEM_SECRET_LENGTH; - if (ctx->keyCtx->classicGroupName != NULL) { + if (classicKeyCtxPeer->isX25519) + { + pbMlkemCipherText = out; + pbClassicKey = out + cbMlkemCiphertext; + pbMlkemSecret = secret; + pbClassicSecret = secret + SYMCRYPT_MLKEM_SECRET_LENGTH; + } + else + { + pbClassicKey = out; + pbMlkemCipherText = out + cbClassicKey; + pbClassicSecret = secret ; + pbMlkemSecret = secret + cbClassicSecret; + } + // Generate ephemeral ECDH key if ((classicKeyCtxPrivate = p_scossl_ecc_new_ctx(ctx->provCtx)) == NULL) { @@ -222,7 +224,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, } // Write encoded public key bytes - if (p_scossl_ecc_get_encoded_key(classicKeyCtxPrivate, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, &out, &cbClassicKey) != SCOSSL_SUCCESS) + if (p_scossl_ecc_get_encoded_key(classicKeyCtxPrivate, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, &pbClassicKey, &cbClassicKey) != SCOSSL_SUCCESS) { goto cleanup; } @@ -230,11 +232,30 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, // Derive ECDH secret if (p_scossl_mlkem_classic_keyexch_init(ctx, classicKeyCtxPrivate) != SCOSSL_SUCCESS || p_scossl_ecdh_set_peer(ctx->classicKeyexchCtx, classicKeyCtxPeer) != SCOSSL_SUCCESS || - p_scossl_ecdh_derive(ctx->classicKeyexchCtx, secret, &cbClassicSecret, *secretlen) != SCOSSL_SUCCESS) + p_scossl_ecdh_derive(ctx->classicKeyexchCtx, pbClassicSecret, &cbClassicSecret, *secretlen - SYMCRYPT_MLKEM_SECRET_LENGTH) != SCOSSL_SUCCESS) { goto cleanup; } } + else + { + pbMlkemCipherText = out; + pbMlkemSecret = secret; + } + + if ((outlen != NULL && *outlen < cbClassicKey + cbMlkemCiphertext) || + (secretlen != NULL && *secretlen < cbClassicSecret + SYMCRYPT_MLKEM_SECRET_LENGTH)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + goto cleanup; + } + + scError = SymCryptMlKemEncapsulate(ctx->keyCtx->key, pbMlkemSecret, SYMCRYPT_MLKEM_SECRET_LENGTH, pbMlkemCipherText, cbMlkemCiphertext); + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } } else if (outlen == NULL && secretlen == NULL) { @@ -281,6 +302,10 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, _Out_writes_bytes_opt_(*outlen) unsigned char *out, _Out_ size_t *outlen, _In_reads_bytes_(inlen) const unsigned char *in, size_t inlen) { + PCBYTE pbMlkemCipherText = NULL; + PCBYTE pbClassicKey = NULL; + PBYTE pbMlkemSecret = NULL; + PBYTE pbClassicSecret = NULL; SIZE_T cbClassicKey = 0; SIZE_T cbMlkemCiphertext = 0; SIZE_T cbClassicSecret = 0; @@ -342,18 +367,23 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, goto cleanup; } - scError = SymCryptMlKemDecapsulate(ctx->keyCtx->key, in, cbMlkemCiphertext, out, SYMCRYPT_MLKEM_SECRET_LENGTH); - if (scError != SYMCRYPT_NO_ERROR) - { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - goto cleanup; - } - - in += cbMlkemCiphertext; - out += SYMCRYPT_MLKEM_SECRET_LENGTH; - if (ctx->keyCtx->classicGroupName != NULL) { + if (classicKeyCtxPrivate->isX25519) + { + pbMlkemCipherText = in; + pbClassicKey = in + cbMlkemCiphertext; + pbMlkemSecret = out; + pbClassicSecret = out + SYMCRYPT_MLKEM_SECRET_LENGTH; + } + else + { + pbClassicKey = in; + pbMlkemCipherText = in + cbClassicKey; + pbClassicSecret = out; + pbMlkemSecret = out + cbClassicSecret; + } + // Extract ECDH public key from in if ((classicKeyCtxPeer = p_scossl_ecc_new_ctx(ctx->provCtx)) == NULL) { @@ -362,18 +392,25 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, } if (p_scossl_ecc_set_group(classicKeyCtxPeer, ctx->keyCtx->classicGroupName) != SCOSSL_SUCCESS || - p_scossl_ecc_set_encoded_key(classicKeyCtxPeer, in, cbClassicKey, NULL, 0) != SCOSSL_SUCCESS) + p_scossl_ecc_set_encoded_key(classicKeyCtxPeer, pbClassicKey, cbClassicKey, NULL, 0) != SCOSSL_SUCCESS) { goto cleanup; } // Derive shared ECDH secret if (p_scossl_ecdh_set_peer(ctx->classicKeyexchCtx, classicKeyCtxPeer) != SCOSSL_SUCCESS || - p_scossl_ecdh_derive(ctx->classicKeyexchCtx, out, &cbClassicSecret, *outlen - SYMCRYPT_MLKEM_SECRET_LENGTH) != SCOSSL_SUCCESS) + p_scossl_ecdh_derive(ctx->classicKeyexchCtx, pbClassicSecret, &cbClassicSecret, *outlen - SYMCRYPT_MLKEM_SECRET_LENGTH) != SCOSSL_SUCCESS) { goto cleanup; } } + + scError = SymCryptMlKemDecapsulate(ctx->keyCtx->key, pbMlkemCipherText, cbMlkemCiphertext, pbMlkemSecret, SYMCRYPT_MLKEM_SECRET_LENGTH); + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } } else if (outlen == NULL) { diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index e59726d2..97f64664 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -885,13 +885,16 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX goto cleanup; } - pbMlKemKey = pbKey; - pbClassicKey = pbKey + cbMlKemKey; - if (keyCtx->classicKeyCtx != NULL && - p_scossl_ecc_get_encoded_key(keyCtx->classicKeyCtx, selection, &pbClassicKey, &cbClassicKey) != SCOSSL_SUCCESS) + keyCtx->classicKeyCtx->isX25519) { - goto cleanup; + pbMlKemKey = pbKey; + pbClassicKey = pbKey + cbMlKemKey; + } + else + { + pbClassicKey = pbKey; + pbMlKemKey = pbKey + cbClassicKey; } scError = SymCryptMlKemkeyGetValue(keyCtx->key, pbMlKemKey, cbMlKemKey, format, 0); @@ -901,6 +904,12 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX goto cleanup; } + if (keyCtx->classicKeyCtx != NULL && + p_scossl_ecc_get_encoded_key(keyCtx->classicKeyCtx, selection, &pbClassicKey, &cbClassicKey) != SCOSSL_SUCCESS) + { + goto cleanup; + } + ret = SCOSSL_SUCCESS; *ppbKey = pbKey; @@ -976,8 +985,17 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt goto cleanup; } - pbMlKemKey = pbKey; - pbClassicKey = pbKey + cbMlKemKey; + if (keyCtx->classicKeyCtx != NULL && + keyCtx->classicKeyCtx->isX25519) + { + pbMlKemKey = pbKey; + pbClassicKey = pbKey + cbMlKemKey; + } + else + { + pbClassicKey = pbKey; + pbMlKemKey = pbKey + cbClassicKey; + } scError = SymCryptMlKemkeySetValue(pbMlKemKey, cbMlKemKey, keyCtx->format, 0, keyCtx->key); if (scError != SYMCRYPT_NO_ERROR) @@ -1050,6 +1068,12 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_group(SCOSSL_MLKEM_KEY_CTX *keyCtx, con keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; keyCtx->classicGroupName = SN_X25519; } + else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_P384_MLKEM1024) == 0) + { + keyCtx->groupName = SCOSSL_SN_P384_MLKEM1024; + keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM1024; + keyCtx->classicGroupName = SN_secp384r1; + } else { ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index 2409cca4..f84efe81 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -45,6 +45,7 @@ extern "C" { #define SCOSSL_TLS_GROUP_ID_mlkem1024 0x0202 #define SCOSSL_TLS_GROUP_ID_secp256r1mlkem768 0x11eb #define SCOSSL_TLS_GROUP_ID_x25519mlkem768 0x11ec +#define SCOSSL_TLS_GROUP_ID_secp384r1mlkem1024 0x11ed #define ALG(names, funcs) {names, "provider="P_SCOSSL_NAME",fips=yes", funcs, NULL} #define ALG_DECODER(algNames, name, decoderType) { \ @@ -154,6 +155,11 @@ const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_x25519mlkem768 = { TLS1_3_VERSION, 0, -1, -1}; +const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_secp384r1mlkem1024 = { + SCOSSL_TLS_GROUP_ID_secp384r1mlkem1024, 256, 1, + TLS1_3_VERSION, 0, + -1, -1}; + #define TLS_GROUP_ENTRY(tlsname, realname, algorithm, group_info) { \ OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME, tlsname, sizeof(tlsname)), \ OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL, realname, sizeof(realname)), \ @@ -190,7 +196,8 @@ static const OSSL_PARAM p_scossl_supported_group_list[][11] = { TLS_GROUP_ENTRY("mlkem768", SCOSSL_SN_MLKEM768, "MLKEM", scossl_tls_group_info_mlkem768), TLS_GROUP_ENTRY("mlkem1024", SCOSSL_SN_MLKEM1024, "MLKEM", scossl_tls_group_info_mlkem1024), TLS_GROUP_ENTRY("secp256r1mlkem768", SCOSSL_SN_P256_MLKEM768, "MLKEM", scossl_tls_group_info_secp256r1mlkem768), - TLS_GROUP_ENTRY("x25519mlkem768", SCOSSL_SN_X25519_MLKEM768, "MLKEM", scossl_tls_group_info_x25519mlkem768)}; + TLS_GROUP_ENTRY("x25519mlkem768", SCOSSL_SN_X25519_MLKEM768, "MLKEM", scossl_tls_group_info_x25519mlkem768), + TLS_GROUP_ENTRY("secp384r1mlkem1024", SCOSSL_SN_P384_MLKEM1024, "MLKEM", scossl_tls_group_info_secp384r1mlkem1024)}; // Digest extern const OSSL_DISPATCH p_scossl_md5_functions[]; @@ -405,7 +412,8 @@ static SCOSSL_STATUS p_scossl_register_extended_algorithms() OBJ_create(SCOSSL_OID_MLKEM768, SCOSSL_SN_MLKEM768, SCOSSL_SN_MLKEM768) == NID_undef || OBJ_create(SCOSSL_OID_MLKEM1024, SCOSSL_SN_MLKEM1024, SCOSSL_SN_MLKEM1024) == NID_undef || OBJ_create(SCOSSL_OID_P256_MLKEM768, SCOSSL_SN_P256_MLKEM768, SCOSSL_SN_P256_MLKEM768) == NID_undef || - OBJ_create(SCOSSL_OID_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768) == NID_undef) + OBJ_create(SCOSSL_OID_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768) == NID_undef || + OBJ_create(SCOSSL_OID_P384_MLKEM1024, SCOSSL_SN_P384_MLKEM1024, SCOSSL_SN_P384_MLKEM1024) == NID_undef) { return SCOSSL_FAILURE; } From 7054d72aa2d6bb454cf037debd40d25c235fa566 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Fri, 27 Dec 2024 09:28:14 -0800 Subject: [PATCH 17/21] Rebase cleanup --- SymCryptProvider/src/p_scossl_base.c | 36 ++++++++++++++------------- SymCryptProvider/src/p_scossl_names.h | 19 ++++++++++++++ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index f84efe81..d8c57df8 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -196,8 +196,10 @@ static const OSSL_PARAM p_scossl_supported_group_list[][11] = { TLS_GROUP_ENTRY("mlkem768", SCOSSL_SN_MLKEM768, "MLKEM", scossl_tls_group_info_mlkem768), TLS_GROUP_ENTRY("mlkem1024", SCOSSL_SN_MLKEM1024, "MLKEM", scossl_tls_group_info_mlkem1024), TLS_GROUP_ENTRY("secp256r1mlkem768", SCOSSL_SN_P256_MLKEM768, "MLKEM", scossl_tls_group_info_secp256r1mlkem768), + TLS_GROUP_ENTRY("P256mlkem768", SCOSSL_SN_P256_MLKEM768, "MLKEM", scossl_tls_group_info_secp256r1mlkem768), TLS_GROUP_ENTRY("x25519mlkem768", SCOSSL_SN_X25519_MLKEM768, "MLKEM", scossl_tls_group_info_x25519mlkem768), - TLS_GROUP_ENTRY("secp384r1mlkem1024", SCOSSL_SN_P384_MLKEM1024, "MLKEM", scossl_tls_group_info_secp384r1mlkem1024)}; + TLS_GROUP_ENTRY("secp384r1mlkem1024", SCOSSL_SN_P384_MLKEM1024, "MLKEM", scossl_tls_group_info_secp384r1mlkem1024), + TLS_GROUP_ENTRY("P384mlkem1024", SCOSSL_SN_P384_MLKEM1024, "MLKEM", scossl_tls_group_info_secp384r1mlkem1024)}; // Digest extern const OSSL_DISPATCH p_scossl_md5_functions[]; @@ -218,22 +220,22 @@ extern const OSSL_DISPATCH p_scossl_cshake_128_functions[]; extern const OSSL_DISPATCH p_scossl_cshake_256_functions[]; static const OSSL_ALGORITHM p_scossl_digest[] = { - ALG("MD5:SSL3-MD5:1.2.840.113549.2.5", p_scossl_md5_functions), - ALG("SHA1:SHA-1:SSL3-SHA1:1.3.14.3.2.26", p_scossl_sha1_functions), - ALG("SHA2-224:SHA-224:SHA224:2.16.840.1.101.3.4.2.4", p_scossl_sha224_functions), - ALG("SHA2-256:SHA-256:SHA256:2.16.840.1.101.3.4.2.1", p_scossl_sha256_functions), - ALG("SHA2-384:SHA-384:SHA384:2.16.840.1.101.3.4.2.2", p_scossl_sha384_functions), - ALG("SHA2-512:SHA-512:SHA512:2.16.840.1.101.3.4.2.3", p_scossl_sha512_functions), - ALG("SHA2-512/224:SHA-512/224:SHA512-224:2.16.840.1.101.3.4.2.5", p_scossl_sha512_224_functions), - ALG("SHA2-512/256:SHA-512/256:SHA512-256:2.16.840.1.101.3.4.2.6", p_scossl_sha512_256_functions), - ALG("SHA3-224:2.16.840.1.101.3.4.2.7", p_scossl_sha3_224_functions), - ALG("SHA3-256:2.16.840.1.101.3.4.2.8", p_scossl_sha3_256_functions), - ALG("SHA3-384:2.16.840.1.101.3.4.2.9", p_scossl_sha3_384_functions), - ALG("SHA3-512:2.16.840.1.101.3.4.2.10", p_scossl_sha3_512_functions), - ALG("SHAKE-128:SHAKE128:2.16.840.1.101.3.4.2.11", p_scossl_shake_128_functions), - ALG("SHAKE-256:SHAKE256:2.16.840.1.101.3.4.2.12", p_scossl_shake_256_functions), - ALG("CSHAKE-128:CSHAKE128", p_scossl_cshake_128_functions), - ALG("CSHAKE-256:CSHAKE256", p_scossl_cshake_256_functions), + ALG(SCOSSL_ALG_NAME_MD5, p_scossl_md5_functions), + ALG(SCOSSL_ALG_NAME_SHA1, p_scossl_sha1_functions), + ALG(SCOSSL_ALG_NAME_SHA224, p_scossl_sha224_functions), + ALG(SCOSSL_ALG_NAME_SHA256, p_scossl_sha256_functions), + ALG(SCOSSL_ALG_NAME_SHA384, p_scossl_sha384_functions), + ALG(SCOSSL_ALG_NAME_SHA512, p_scossl_sha512_functions), + ALG(SCOSSL_ALG_NAME_SHA512_224, p_scossl_sha512_224_functions), + ALG(SCOSSL_ALG_NAME_SHA512_256, p_scossl_sha512_256_functions), + ALG(SCOSSL_ALG_NAME_SHA3_224, p_scossl_sha3_224_functions), + ALG(SCOSSL_ALG_NAME_SHA3_256, p_scossl_sha3_256_functions), + ALG(SCOSSL_ALG_NAME_SHA3_384, p_scossl_sha3_384_functions), + ALG(SCOSSL_ALG_NAME_SHA3_512, p_scossl_sha3_512_functions), + ALG(SCOSSL_ALG_NAME_SHAKE128, p_scossl_shake_128_functions), + ALG(SCOSSL_ALG_NAME_SHAKE256, p_scossl_shake_256_functions), + ALG(SCOSSL_ALG_NAME_CSHAKE128, p_scossl_cshake_128_functions), + ALG(SCOSSL_ALG_NAME_CSHAKE256, p_scossl_cshake_256_functions), ALG_TABLE_END}; // Cipher diff --git a/SymCryptProvider/src/p_scossl_names.h b/SymCryptProvider/src/p_scossl_names.h index 73825553..25dbd963 100644 --- a/SymCryptProvider/src/p_scossl_names.h +++ b/SymCryptProvider/src/p_scossl_names.h @@ -12,6 +12,25 @@ extern "C" { // Provider algorithm names // +// Digests + +#define SCOSSL_ALG_NAME_MD5 SN_md5"SSL3-MD5:1.2.840.113549.2.5" +#define SCOSSL_ALG_NAME_SHA1 SN_sha1"SHA-1:SSL3-SHA1:1.3.14.3.2.26" +#define SCOSSL_ALG_NAME_SHA224 SN_sha224"SHA2-224:SHA-224:2.16.840.1.101.3.4.2.4" +#define SCOSSL_ALG_NAME_SHA256 SN_sha256"SHA2-256:SHA-256:2.16.840.1.101.3.4.2.1" +#define SCOSSL_ALG_NAME_SHA384 SN_sha384"SHA2-384:SHA-384:2.16.840.1.101.3.4.2.2" +#define SCOSSL_ALG_NAME_SHA512 SN_sha512"SHA2-512:SHA-512:2.16.840.1.101.3.4.2.3" +#define SCOSSL_ALG_NAME_SHA512_224 SN_sha512_224"SHA2-512/224:SHA-512/224:2.16.840.1.101.3.4.2.5" +#define SCOSSL_ALG_NAME_SHA512_256 SN_sha512_256"SHA2-512/256:SHA-512/256:2.16.840.1.101.3.4.2.6" +#define SCOSSL_ALG_NAME_SHA3_224 SN_sha3_224"2.16.840.1.101.3.4.2.7" +#define SCOSSL_ALG_NAME_SHA3_256 SN_sha3_256"2.16.840.1.101.3.4.2.8" +#define SCOSSL_ALG_NAME_SHA3_384 SN_sha3_384"2.16.840.1.101.3.4.2.9" +#define SCOSSL_ALG_NAME_SHA3_512 SN_sha3_512"2.16.840.1.101.3.4.2.10" +#define SCOSSL_ALG_NAME_SHAKE128 SN_shake128"SHAKE-128:2.16.840.1.101.3.4.2.11" +#define SCOSSL_ALG_NAME_SHAKE256 SN_shake256"SHAKE-256:2.16.840.1.101.3.4.2.12" +#define SCOSSL_ALG_NAME_CSHAKE128 "CSHAKE-128:CSHAKE128" +#define SCOSSL_ALG_NAME_CSHAKE256 "CSHAKE-256:CSHAKE256" + // Ciphers #define SCOSSL_ALG_NAME_AES_128_CBC SN_aes_128_cbc":AES128:2.16.840.1.101.3.4.1.2" #define SCOSSL_ALG_NAME_AES_192_CBC SN_aes_192_cbc":AES192:2.16.840.1.101.3.4.1.22" From e89449fa55845b0999402dbddfc01440355b262e Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Fri, 27 Dec 2024 15:31:53 -0800 Subject: [PATCH 18/21] Cleanup --- EvpTestRecipes/3.0/evpkem_mlkem.txt | 0 SymCryptProvider/CMakeLists.txt | 6 +- SymCryptProvider/inc/scossl_provider.h | 8 -- .../src/decoder/p_scossl_decode_common.c | 16 +--- .../src/decoder/p_scossl_decode_common.h | 2 - .../src/decoder/p_scossl_decode_mlkem.c | 44 +-------- SymCryptProvider/src/kem/p_scossl_mlkem.c | 16 ++++ SymCryptProvider/src/kem/p_scossl_mlkem.h | 2 + SymCryptProvider/src/keyexch/p_scossl_ecdh.c | 11 ++- .../src/keymgmt/p_scossl_ecc_keymgmt.c | 85 ++++++++--------- .../src/keymgmt/p_scossl_ecc_keymgmt.h | 50 ---------- .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 5 - SymCryptProvider/src/p_scossl_base.c | 94 +++++++++---------- SymCryptProvider/src/p_scossl_bio.c | 18 ++-- SymCryptProvider/src/p_scossl_ecc.h | 2 +- 15 files changed, 128 insertions(+), 231 deletions(-) delete mode 100644 EvpTestRecipes/3.0/evpkem_mlkem.txt delete mode 100644 SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.h diff --git a/EvpTestRecipes/3.0/evpkem_mlkem.txt b/EvpTestRecipes/3.0/evpkem_mlkem.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/SymCryptProvider/CMakeLists.txt b/SymCryptProvider/CMakeLists.txt index c76caf2f..78b2054a 100644 --- a/SymCryptProvider/CMakeLists.txt +++ b/SymCryptProvider/CMakeLists.txt @@ -21,21 +21,21 @@ set(SCOSSL_SOURCES ./src/ciphers/p_scossl_aes.c ./src/ciphers/p_scossl_aes_aead.c ./src/ciphers/p_scossl_aes_xts.c + ./src/decoder/p_scossl_decode_common.c + ./src/decoder/p_scossl_decode_mlkem.c ./src/digests/p_scossl_digest_common.c ./src/digests/p_scossl_digest_generic.c ./src/digests/p_scossl_shake.c ./src/digests/p_scossl_cshake.c - ./src/decoder/p_scossl_decode_common.c - ./src/decoder/p_scossl_decode_mlkem.c ./src/encoder/p_scossl_encode_common.c ./src/encoder/p_scossl_encode_mlkem.c - ./src/kem/p_scossl_mlkem.c ./src/kdf/p_scossl_hkdf.c ./src/kdf/p_scossl_kbkdf.c ./src/kdf/p_scossl_srtpkdf.c ./src/kdf/p_scossl_sshkdf.c ./src/kdf/p_scossl_sskdf.c ./src/kdf/p_scossl_tls1prf.c + ./src/kem/p_scossl_mlkem.c ./src/keyexch/p_scossl_dh.c ./src/keyexch/p_scossl_ecdh.c ./src/keyexch/p_scossl_kdf_keyexch.c diff --git a/SymCryptProvider/inc/scossl_provider.h b/SymCryptProvider/inc/scossl_provider.h index eacedbe9..594f786a 100644 --- a/SymCryptProvider/inc/scossl_provider.h +++ b/SymCryptProvider/inc/scossl_provider.h @@ -31,17 +31,9 @@ extern "C" { #define SCOSSL_SRTP_LABEL_AUTHENTICATION "authentication" #define SCOSSL_SRTP_LABEL_SALTING "salting" -// -// Hybrid PQ parameters -// -#define SCOSSL_PKEY_PARAM_CLASSIC_PRIV_KEY "classic-priv" -#define SCOSSL_PKEY_PARAM_CLASSIC_PUB_KEY "classic-pub" -#define SCOSSL_PKEY_PARAM_CLASSIC_ENCODED_PUBLIC_KEY "classic-encoded-pub-key" - // // Extended algorithms not found in default OpenSSL implementation // - #define SCOSSL_SN_MLKEM512 "mlkem512" #define SCOSSL_OID_MLKEM512 "2.16.840.1.101.3.4.4.1" diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_common.c b/SymCryptProvider/src/decoder/p_scossl_decode_common.c index dff777fd..3f09a1e5 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_common.c +++ b/SymCryptProvider/src/decoder/p_scossl_decode_common.c @@ -2,19 +2,19 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // -#include "p_scossl_bio.h" -#include "decoder/p_scossl_decode_common.h" - #include #include +#include "p_scossl_bio.h" +#include "decoder/p_scossl_decode_common.h" + #ifdef __cplusplus extern "C" { #endif ASN1_NDEF_SEQUENCE(SUBJECT_PUBKEY_INFO) = { - ASN1_SIMPLE(SUBJECT_PUBKEY_INFO, algorithm, X509_ALGOR), - ASN1_SIMPLE(SUBJECT_PUBKEY_INFO, subjectPublicKey, ASN1_BIT_STRING), + ASN1_SIMPLE(SUBJECT_PUBKEY_INFO, algorithm, X509_ALGOR), + ASN1_SIMPLE(SUBJECT_PUBKEY_INFO, subjectPublicKey, ASN1_BIT_STRING), } ASN1_SEQUENCE_END(SUBJECT_PUBKEY_INFO) IMPLEMENT_ASN1_FUNCTIONS(SUBJECT_PUBKEY_INFO) @@ -65,7 +65,6 @@ BOOL p_scossl_decode_does_selection(SCOSSL_DECODE_KEYTYPE_DESC *desc, int select // Supporting private key implies supporting public key. // Both imply supporting key parameters - return ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) || ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) || ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0); @@ -114,11 +113,6 @@ SCOSSL_STATUS p_scossl_decode(SCOSSL_DECODE_CTX *ctx, OSSL_CORE_BIO *in, int sel return ret; } -const ASN1_ITEM *p_scossl_decode_get_pubkey_asn1_item() -{ - return ASN1_ITEM_rptr(SUBJECT_PUBKEY_INFO); -} - #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_common.h b/SymCryptProvider/src/decoder/p_scossl_decode_common.h index bcea0dbc..e90f0a05 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_common.h +++ b/SymCryptProvider/src/decoder/p_scossl_decode_common.h @@ -51,8 +51,6 @@ SCOSSL_STATUS p_scossl_decode(_In_ SCOSSL_DECODE_CTX *ctx, _In_ OSSL_CORE_BIO *i _In_ OSSL_CALLBACK *dataCb, _In_ void *dataCbArg, ossl_unused OSSL_PASSPHRASE_CALLBACK *passphraseCb, ossl_unused void *passphraseCbArg); -const ASN1_ITEM *p_scossl_decode_get_pubkey_asn1_item(); - #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c index d499a1f5..5931bdc9 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c +++ b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c @@ -13,47 +13,11 @@ extern "C" { #endif - -typedef struct { - int nid; - const char *groupName; -} SCOSSL_DECODE_MLKEM_PARAM_MAP; - -static SCOSSL_DECODE_MLKEM_PARAM_MAP p_scossl_decode_mlkem_param_maps[] = { - {-1, SCOSSL_SN_MLKEM512}, - {-1, SCOSSL_SN_MLKEM768}, - {-1, SCOSSL_SN_MLKEM1024}, - {-1, SCOSSL_SN_P256_MLKEM768}, - {-1, SCOSSL_SN_X25519_MLKEM768}, - {-1, SCOSSL_SN_P384_MLKEM1024}}; - -static const char *p_scossl_decode_mlkem_obj_to_groupname(const ASN1_OBJECT *obj) -{ - int nid = OBJ_obj2nid(obj); - - if (nid != -1) - { - for (size_t i = 0; i < sizeof(p_scossl_decode_mlkem_param_maps) / sizeof(OSSL_ITEM); i++) - { - if (p_scossl_decode_mlkem_param_maps[i].nid == -1) - { - p_scossl_decode_mlkem_param_maps[i].nid = OBJ_sn2nid(p_scossl_decode_mlkem_param_maps[i].groupName); - } - - if (p_scossl_decode_mlkem_param_maps[i].nid == nid) - { - return p_scossl_decode_mlkem_param_maps[i].groupName; - } - } - } - - return NULL; -} - static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_decode_key(_In_ SCOSSL_DECODE_CTX *ctx, _In_ const ASN1_OBJECT *algorithm, int selection, _In_reads_bytes_(cbKey) PCBYTE pbKey, SIZE_T cbKey) { const char *groupName; + int nid; SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; SCOSSL_STATUS status = SCOSSL_FAILURE; @@ -65,8 +29,8 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_decode_key(_In_ SCOSSL_DECODE_CTX *c keyCtx->provCtx = ctx->provctx; - groupName = p_scossl_decode_mlkem_obj_to_groupname(algorithm); - if (groupName == NULL || + if ((nid = OBJ_obj2nid(algorithm)) < 0 || + (groupName = OBJ_nid2sn(nid)) == NULL || p_scossl_mlkem_keymgmt_set_group(keyCtx, groupName) != SCOSSL_SUCCESS) { ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); @@ -123,7 +87,7 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_SubjectPublicKeyInfo_to_mlkem(_In_ SCOSSL_ goto cleanup; } - if (ASN1_item_d2i_bio(p_scossl_decode_get_pubkey_asn1_item(), bio, (ASN1_VALUE **)&subjPubKeyInfo) == NULL) + if (ASN1_item_d2i_bio(ASN1_ITEM_rptr(SUBJECT_PUBKEY_INFO), bio, (ASN1_VALUE **)&subjPubKeyInfo) == NULL) { ERR_raise(ERR_LIB_PROV, ASN1_R_DECODE_ERROR); goto cleanup; diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.c b/SymCryptProvider/src/kem/p_scossl_mlkem.c index 0dc3ade0..4ffc9c44 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.c +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.c @@ -2,6 +2,7 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // +#include "scossl_provider.h" #include "p_scossl_base.h" #include "kem/p_scossl_mlkem.h" #include "keyexch/p_scossl_ecdh.h" @@ -463,6 +464,21 @@ const OSSL_DISPATCH p_scossl_mlkem_functions[] = { {OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_mlkem_ctx_param_types}, {0, NULL}}; +SCOSSL_STATUS p_scossl_mlkem_register_algorithms() +{ + if (OBJ_create(SCOSSL_OID_MLKEM512, SCOSSL_SN_MLKEM512, SCOSSL_SN_MLKEM512) == NID_undef || + OBJ_create(SCOSSL_OID_MLKEM768, SCOSSL_SN_MLKEM768, SCOSSL_SN_MLKEM768) == NID_undef || + OBJ_create(SCOSSL_OID_MLKEM1024, SCOSSL_SN_MLKEM1024, SCOSSL_SN_MLKEM1024) == NID_undef || + OBJ_create(SCOSSL_OID_P256_MLKEM768, SCOSSL_SN_P256_MLKEM768, SCOSSL_SN_P256_MLKEM768) == NID_undef || + OBJ_create(SCOSSL_OID_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768) == NID_undef || + OBJ_create(SCOSSL_OID_P384_MLKEM1024, SCOSSL_SN_P384_MLKEM1024, SCOSSL_SN_P384_MLKEM1024) == NID_undef) + { + return SCOSSL_FAILURE; + } + + return SCOSSL_SUCCESS; +} + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.h b/SymCryptProvider/src/kem/p_scossl_mlkem.h index ca6594f1..c6a227f0 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.h +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.h @@ -21,6 +21,8 @@ typedef struct { SCOSSL_ECC_KEY_CTX *classicKeyCtx; } SCOSSL_MLKEM_KEY_CTX; +SCOSSL_STATUS p_scossl_mlkem_register_algorithms(); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/keyexch/p_scossl_ecdh.c b/SymCryptProvider/src/keyexch/p_scossl_ecdh.c index 1b0f0e18..f539b467 100644 --- a/SymCryptProvider/src/keyexch/p_scossl_ecdh.c +++ b/SymCryptProvider/src/keyexch/p_scossl_ecdh.c @@ -109,6 +109,12 @@ SCOSSL_STATUS p_scossl_ecdh_derive(SCOSSL_ECDH_CTX *ctx, return SCOSSL_FAILURE; } + if (ctx->keyCtx == NULL || + (secret != NULL && ctx->peerKeyCtx == NULL)) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + return SCOSSL_FAILURE; + } + cbSecretBuf = SymCryptEckeySizeofPublicKey(ctx->keyCtx->key, SYMCRYPT_ECPOINT_FORMAT_X); if (secret == NULL) { @@ -116,11 +122,6 @@ SCOSSL_STATUS p_scossl_ecdh_derive(SCOSSL_ECDH_CTX *ctx, return SCOSSL_SUCCESS; } - if (ctx->keyCtx == NULL || ctx->peerKeyCtx == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); - return SCOSSL_FAILURE; - } - numberFormat = ctx->keyCtx->isX25519 ? SYMCRYPT_NUMBER_FORMAT_LSB_FIRST : SYMCRYPT_NUMBER_FORMAT_MSB_FIRST; if (outlen < cbSecretBuf) diff --git a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c index a576ab07..158165b7 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c @@ -5,7 +5,6 @@ #include "scossl_ecc.h" #include "p_scossl_ecc.h" #include "keymgmt/p_scossl_ecc_impexp_types.h" -#include "keymgmt/p_scossl_ecc_keymgmt.h" #include #include @@ -18,6 +17,14 @@ extern "C" { #define SCOSSL_ECC_DEFAULT_DIGEST SN_sha256 #define SCOSSL_ECC_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_PUBLIC_KEY | OSSL_KEYMGMT_SELECT_PRIVATE_KEY | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) +typedef struct +{ + OSSL_LIB_CTX *libctx; + PCSYMCRYPT_ECURVE curve; + BOOL isX25519; + point_conversion_form_t conversionFormat; +} SCOSSL_ECC_KEYGEN_CTX; + // ScOSSL only supports named curves static const OSSL_PARAM p_scossl_ecc_keygen_settable_param_types[] = { OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), @@ -84,8 +91,7 @@ static point_conversion_form_t p_scossl_ecc_keymgmt_conversion_name_to_id(_In_ c // the size of the SYMCRYPT_ECKEY depends on parameters that aren't // known until import, no key is actually allocated here. -_Use_decl_annotations_ -SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_new_ctx(SCOSSL_PROVCTX *provctx) +static SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_new_ctx(_In_ SCOSSL_PROVCTX *provctx) { SCOSSL_ECC_KEY_CTX *keyCtx = p_scossl_ecc_new_ctx(provctx); if (keyCtx != NULL) @@ -98,8 +104,7 @@ SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_new_ctx(SCOSSL_PROVCTX *provctx) return keyCtx; } -_Use_decl_annotations_ -SCOSSL_ECC_KEY_CTX *p_scossl_x25519_keymgmt_new_ctx(SCOSSL_PROVCTX *provctx) +static SCOSSL_ECC_KEY_CTX *p_scossl_x25519_keymgmt_new_ctx(_In_ SCOSSL_PROVCTX *provctx) { SCOSSL_ECC_KEY_CTX *keyCtx = p_scossl_ecc_new_ctx(provctx); if (keyCtx != NULL) @@ -200,8 +205,7 @@ static const OSSL_PARAM *p_scossl_ecc_keygen_settable_params(ossl_unused void *g return p_scossl_ecc_keygen_settable_param_types; } -_Use_decl_annotations_ -void p_scossl_ecc_keygen_cleanup(SCOSSL_ECC_KEYGEN_CTX *genCtx) +static void p_scossl_ecc_keygen_cleanup(_Inout_ SCOSSL_ECC_KEYGEN_CTX *genCtx) { OPENSSL_free(genCtx); } @@ -229,16 +233,14 @@ static SCOSSL_ECC_KEYGEN_CTX *p_scossl_ecc_common_keygen_init(_In_ SCOSSL_PROVCT return genCtx; } -_Use_decl_annotations_ -SCOSSL_ECC_KEYGEN_CTX *p_scossl_ecc_keygen_init(SCOSSL_PROVCTX *provctx, ossl_unused int selection, - const OSSL_PARAM params[]) +static SCOSSL_ECC_KEYGEN_CTX *p_scossl_ecc_keygen_init(_In_ SCOSSL_PROVCTX *provctx, ossl_unused int selection, + _In_ const OSSL_PARAM params[]) { return p_scossl_ecc_common_keygen_init(provctx, selection, params, FALSE); } -_Use_decl_annotations_ -SCOSSL_ECC_KEYGEN_CTX *p_scossl_x25519_keygen_init(SCOSSL_PROVCTX *provctx, ossl_unused int selection, - const OSSL_PARAM params[]) +static SCOSSL_ECC_KEYGEN_CTX *p_scossl_x25519_keygen_init(_In_ SCOSSL_PROVCTX *provctx, ossl_unused int selection, + _In_ const OSSL_PARAM params[]) { SCOSSL_ECC_KEYGEN_CTX *genCtx = p_scossl_ecc_common_keygen_init(provctx, selection, params, TRUE); // Always set curve to X25519 @@ -250,8 +252,7 @@ SCOSSL_ECC_KEYGEN_CTX *p_scossl_x25519_keygen_init(SCOSSL_PROVCTX *provctx, ossl return genCtx; } -_Use_decl_annotations_ -SCOSSL_STATUS p_scossl_ecc_keygen_set_template(SCOSSL_ECC_KEYGEN_CTX *genCtx, SCOSSL_ECC_KEY_CTX *tmplCtx) +static SCOSSL_STATUS p_scossl_ecc_keygen_set_template(_Inout_ SCOSSL_ECC_KEYGEN_CTX *genCtx, SCOSSL_ECC_KEY_CTX *tmplCtx) { if (tmplCtx == NULL || tmplCtx->curve == NULL) { @@ -262,8 +263,7 @@ SCOSSL_STATUS p_scossl_ecc_keygen_set_template(SCOSSL_ECC_KEYGEN_CTX *genCtx, SC return SCOSSL_SUCCESS; } -_Use_decl_annotations_ -SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keygen(SCOSSL_ECC_KEYGEN_CTX *genCtx, ossl_unused OSSL_CALLBACK *cb, ossl_unused void *cbarg) +static SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keygen(_In_ SCOSSL_ECC_KEYGEN_CTX *genCtx, ossl_unused OSSL_CALLBACK *cb, ossl_unused void *cbarg) { SCOSSL_ECC_KEY_CTX *keyCtx = OPENSSL_malloc(sizeof(SCOSSL_ECC_KEY_CTX)); if (keyCtx == NULL) @@ -366,8 +366,7 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_get_pubkey_point(_In_ SCOSSL_ECC_KEY_C return ret; } -_Use_decl_annotations_ -SCOSSL_STATUS p_scossl_ecc_keymgmt_get_params(SCOSSL_ECC_KEY_CTX *keyCtx, OSSL_PARAM params[]) +static SCOSSL_STATUS p_scossl_ecc_keymgmt_get_params(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, _Inout_ OSSL_PARAM params[]) { PBYTE pbEncodedKey = NULL; PBYTE pbPrivateKey = NULL; @@ -528,8 +527,7 @@ static const OSSL_PARAM *p_scossl_x25519_keymgmt_gettable_params(ossl_unused voi return p_scossl_x25519_keymgmt_gettable_param_types; } -_Use_decl_annotations_ -SCOSSL_STATUS p_scossl_ecc_keymgmt_set_params(SCOSSL_ECC_KEY_CTX *keyCtx, const OSSL_PARAM params[]) +static SCOSSL_STATUS p_scossl_ecc_keymgmt_set_params(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, _In_ const OSSL_PARAM params[]) { EC_GROUP *ecGroup = NULL; PBYTE encodedPoint = NULL; @@ -660,8 +658,7 @@ static const OSSL_PARAM *p_scossl_ecc_keymgmt_settable_params(ossl_unused void * return p_scossl_ecc_keymgmt_settable_param_types; } -_Use_decl_annotations_ -BOOL p_scossl_ecc_keymgmt_has(SCOSSL_ECC_KEY_CTX *keyCtx, int selection) +static BOOL p_scossl_ecc_keymgmt_has(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection) { BOOL hasSelection = TRUE; @@ -692,8 +689,7 @@ BOOL p_scossl_ecc_keymgmt_has(SCOSSL_ECC_KEY_CTX *keyCtx, int selection) // Key checking is handled by SymCrypt, and the curves are valid named curves. This function // just needs to check whether the data indicated by selection has been set. -_Use_decl_annotations_ -SCOSSL_STATUS p_scossl_ecc_keymgmt_validate(SCOSSL_ECC_KEY_CTX *keyCtx, int selection, ossl_unused int checktype) +static SCOSSL_STATUS p_scossl_ecc_keymgmt_validate(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, ossl_unused int checktype) { SCOSSL_STATUS success = SCOSSL_SUCCESS; @@ -705,9 +701,8 @@ SCOSSL_STATUS p_scossl_ecc_keymgmt_validate(SCOSSL_ECC_KEY_CTX *keyCtx, int sele return success; } -_Use_decl_annotations_ -BOOL p_scossl_ecc_keymgmt_match(SCOSSL_ECC_KEY_CTX *keyCtx1, SCOSSL_ECC_KEY_CTX *keyCtx2, - int selection) +static BOOL p_scossl_ecc_keymgmt_match(_In_ SCOSSL_ECC_KEY_CTX *keyCtx1, _In_ SCOSSL_ECC_KEY_CTX *keyCtx2, + int selection) { BOOL ret = FALSE; PBYTE pbPrivateKey1 = NULL; @@ -846,14 +841,13 @@ static const OSSL_PARAM *p_scossl_ecc_keymgmt_impexp_types(int selection) return p_scossl_ecc_keymgmt_impexp_param_types[idx]; } -_Use_decl_annotations_ -SCOSSL_STATUS p_scossl_ecc_keymgmt_import(SCOSSL_ECC_KEY_CTX *keyCtx, int selection, const OSSL_PARAM params[]) +static SCOSSL_STATUS p_scossl_ecc_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]) { SCOSSL_STATUS ret = SCOSSL_FAILURE; EC_GROUP *ecGroup = NULL; PCSYMCRYPT_ECURVE pCurve; - PCBYTE pbEncodedPublicKey = NULL; - SIZE_T cbEncodedPublicKey = 0; + PCBYTE pbPublicKey = NULL; + SIZE_T cbPublicKey = 0; PBYTE pbPrivateKey = NULL; SIZE_T cbPrivateKey = 0; BIGNUM *bnPrivateKey = NULL; @@ -926,7 +920,7 @@ SCOSSL_STATUS p_scossl_ecc_keymgmt_import(SCOSSL_ECC_KEY_CTX *keyCtx, int select if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY)) != NULL && - !OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbEncodedPublicKey, &cbEncodedPublicKey)) + !OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbPublicKey, &cbPublicKey)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); goto cleanup; @@ -961,8 +955,9 @@ SCOSSL_STATUS p_scossl_ecc_keymgmt_import(SCOSSL_ECC_KEY_CTX *keyCtx, int select } } - ret = p_scossl_ecc_set_encoded_key(keyCtx, - pbEncodedPublicKey, cbEncodedPublicKey, + ret = p_scossl_ecc_set_encoded_key( + keyCtx, + pbPublicKey, cbPublicKey, pbPrivateKey, cbPrivateKey); if (ret != SCOSSL_SUCCESS) @@ -978,21 +973,17 @@ SCOSSL_STATUS p_scossl_ecc_keymgmt_import(SCOSSL_ECC_KEY_CTX *keyCtx, int select ret = SCOSSL_SUCCESS; cleanup: - if (pbPrivateKey != NULL) - { - OPENSSL_secure_clear_free(pbPrivateKey, cbPrivateKey); - } - EC_GROUP_free(ecGroup); + OPENSSL_secure_clear_free(pbPrivateKey, cbPrivateKey); BN_clear_free(bnPrivateKey); + EC_GROUP_free(ecGroup); EC_POINT_free(ecPoint); BN_CTX_free(bnCtx); return ret; } -_Use_decl_annotations_ -SCOSSL_STATUS p_scossl_ecc_keymgmt_export(SCOSSL_ECC_KEY_CTX *keyCtx, int selection, - OSSL_CALLBACK *param_cb, void *cbarg) +static SCOSSL_STATUS p_scossl_ecc_keymgmt_export(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, + _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg) { SCOSSL_STATUS ret = SCOSSL_FAILURE; OSSL_PARAM_BLD *bld = NULL; @@ -1089,8 +1080,7 @@ static const OSSL_PARAM *p_scossl_x25519_keymgmt_impexp_types(int selection) return (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0 ? NULL : p_scossl_x25519_keymgmt_impexp_param_types; } -_Use_decl_annotations_ -SCOSSL_STATUS p_scossl_x25519_keymgmt_import(SCOSSL_ECC_KEY_CTX *keyCtx, int selection, const OSSL_PARAM params[]) +static SCOSSL_STATUS p_scossl_x25519_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]) { SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -1171,9 +1161,8 @@ SCOSSL_STATUS p_scossl_x25519_keymgmt_import(SCOSSL_ECC_KEY_CTX *keyCtx, int sel return ret; } -_Use_decl_annotations_ -SCOSSL_STATUS p_scossl_x25519_keymgmt_export(SCOSSL_ECC_KEY_CTX *keyCtx, int selection, - OSSL_CALLBACK *param_cb, void *cbarg) +static SCOSSL_STATUS p_scossl_x25519_keymgmt_export(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, + _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg) { SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; diff --git a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.h b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.h deleted file mode 100644 index 65b402eb..00000000 --- a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. Licensed under the MIT license. -// - -#include "scossl_helpers.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct -{ - OSSL_LIB_CTX *libctx; - PCSYMCRYPT_ECURVE curve; - BOOL isX25519; - point_conversion_form_t conversionFormat; -} SCOSSL_ECC_KEYGEN_CTX; - -// ECC Key management functions are exposed here for use in hybrid key exchange -SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_new_ctx(_In_ SCOSSL_PROVCTX *provctx); -SCOSSL_ECC_KEY_CTX *p_scossl_x25519_keymgmt_new_ctx(_In_ SCOSSL_PROVCTX *provctx); -void p_scossl_ecc_keymgmt_free_ctx(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx); -SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keymgmt_dup_ctx(_In_ const SCOSSL_ECC_KEY_CTX *keyCtx, int selection); - -SCOSSL_ECC_KEYGEN_CTX *p_scossl_ecc_keygen_init(_In_ SCOSSL_PROVCTX *provctx, ossl_unused int selection, - _In_ const OSSL_PARAM params[]); -SCOSSL_ECC_KEYGEN_CTX *p_scossl_x25519_keygen_init(_In_ SCOSSL_PROVCTX *provctx, ossl_unused int selection, - _In_ const OSSL_PARAM params[]); -void p_scossl_ecc_keygen_cleanup(_Inout_ SCOSSL_ECC_KEYGEN_CTX *genCtx); -SCOSSL_STATUS p_scossl_ecc_keygen_set_template(_Inout_ SCOSSL_ECC_KEYGEN_CTX *genCtx, _In_ SCOSSL_ECC_KEY_CTX *tmplCtx); -SCOSSL_ECC_KEY_CTX *p_scossl_ecc_keygen(_In_ SCOSSL_ECC_KEYGEN_CTX *genCtx, ossl_unused OSSL_CALLBACK *cb, ossl_unused void *cbarg); - -SCOSSL_STATUS p_scossl_ecc_keymgmt_get_params(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, _Inout_ OSSL_PARAM params[]); -SCOSSL_STATUS p_scossl_ecc_keymgmt_set_params(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, _In_ const OSSL_PARAM params[]); - -BOOL p_scossl_ecc_keymgmt_has(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection); -SCOSSL_STATUS p_scossl_ecc_keymgmt_validate(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, ossl_unused int checktype); -BOOL p_scossl_ecc_keymgmt_match(_In_ SCOSSL_ECC_KEY_CTX *keyCtx1, _In_ SCOSSL_ECC_KEY_CTX *keyCtx2, - int selection); - -SCOSSL_STATUS p_scossl_ecc_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]); -SCOSSL_STATUS p_scossl_ecc_keymgmt_export(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, - _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg); -SCOSSL_STATUS p_scossl_x25519_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, _In_ const OSSL_PARAM params[]); -SCOSSL_STATUS p_scossl_x25519_keymgmt_export(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int selection, - _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index 97f64664..6da4c0b3 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -5,7 +5,6 @@ #include "scossl_provider.h" #include "kem/p_scossl_mlkem.h" #include "keymgmt/p_scossl_mlkem_keymgmt.h" -#include "keymgmt/p_scossl_ecc_keymgmt.h" #include #include @@ -19,9 +18,6 @@ extern "C" { OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), \ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), \ - OSSL_PARAM_octet_string(SCOSSL_PKEY_PARAM_CLASSIC_ENCODED_PUBLIC_KEY, NULL, 0), \ - OSSL_PARAM_octet_string(SCOSSL_PKEY_PARAM_CLASSIC_PUB_KEY, NULL, 0), \ - OSSL_PARAM_octet_string(SCOSSL_PKEY_PARAM_CLASSIC_PRIV_KEY, NULL, 0), \ static const OSSL_PARAM p_scossl_mlkem_keygen_settable_param_types[] = { OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), @@ -29,7 +25,6 @@ static const OSSL_PARAM p_scossl_mlkem_keygen_settable_param_types[] = { static const OSSL_PARAM p_scossl_mlkem_keymgmt_settable_param_types[] = { OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), - OSSL_PARAM_octet_string(SCOSSL_PKEY_PARAM_CLASSIC_ENCODED_PUBLIC_KEY, NULL, 0), OSSL_PARAM_END}; static const OSSL_PARAM p_scossl_mlkem_keymgmt_gettable_param_types[] = { diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index d8c57df8..ab4f2c6b 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -12,6 +12,7 @@ #include "p_scossl_bio.h" #include "p_scossl_keysinuse.h" #include "p_scossl_names.h" +#include "kem/p_scossl_mlkem.h" #ifdef __cplusplus extern "C" { @@ -47,23 +48,29 @@ extern "C" { #define SCOSSL_TLS_GROUP_ID_x25519mlkem768 0x11ec #define SCOSSL_TLS_GROUP_ID_secp384r1mlkem1024 0x11ed -#define ALG(names, funcs) {names, "provider="P_SCOSSL_NAME",fips=yes", funcs, NULL} -#define ALG_DECODER(algNames, name, decoderType) { \ - algNames, \ - "provider="P_SCOSSL_NAME \ - ",fips=yes" \ - ",input=der" \ - ",structure="#decoderType, \ - p_scossl_der_to_##name##_##decoderType##_functions, \ +#define ALG(names, funcs) { \ + names, \ + "provider="P_SCOSSL_NAME \ + ",fips=yes", \ + funcs, \ NULL} -#define ALG_ENCODER(algNames, name, encoderType, format) { \ - algNames, \ - "provider="P_SCOSSL_NAME \ - ",fips=yes" \ - ",output="#format \ - ",structure="#encoderType, \ - p_scossl_##name##_to_##encoderType##_##format##_functions, \ +#define ALG_DECODER(algNames, name, decoderType) { \ + algNames, \ + "provider="P_SCOSSL_NAME \ + ",fips=yes" \ + ",input=der" \ + ",structure="#decoderType, \ + p_scossl_der_to_##name##_##decoderType##_functions, \ + NULL} + +#define ALG_ENCODER(algNames, name, encoderType, format) { \ + algNames, \ + "provider="P_SCOSSL_NAME \ + ",fips=yes" \ + ",output="#format \ + ",structure="#encoderType, \ + p_scossl_##name##_to_##encoderType##_##format##_functions, \ NULL} #define ALG_TEXT_ENCODER(algNames, name) { \ @@ -160,17 +167,17 @@ const SCOSSL_TLS_GROUP_INFO scossl_tls_group_info_secp384r1mlkem1024 = { TLS1_3_VERSION, 0, -1, -1}; -#define TLS_GROUP_ENTRY(tlsname, realname, algorithm, group_info) { \ - OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME, tlsname, sizeof(tlsname)), \ - OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL, realname, sizeof(realname)), \ - OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_ALG, algorithm, sizeof(algorithm)), \ - OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_ID, (unsigned int *)&group_info.groupId), \ +#define TLS_GROUP_ENTRY(tlsname, realname, algorithm, group_info) { \ + OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME, tlsname, sizeof(tlsname)), \ + OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL, realname, sizeof(realname)), \ + OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_ALG, algorithm, sizeof(algorithm)), \ + OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_ID, (unsigned int *)&group_info.groupId), \ OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS, (unsigned int *)&group_info.securityBits), \ - OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_TLS, (int *)&group_info.minTls), \ - OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_TLS, (int *)&group_info.maxTls), \ - OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS, (int *)&group_info.minTls), \ - OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS, (int *)&group_info.maxTls), \ - OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_IS_KEM, (int *)&group_info.is_kem), \ + OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_TLS, (int *)&group_info.minTls), \ + OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_TLS, (int *)&group_info.maxTls), \ + OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS, (int *)&group_info.minTls), \ + OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS, (int *)&group_info.maxTls), \ + OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_IS_KEM, (int *)&group_info.is_kem), \ OSSL_PARAM_END} static int scossl_prov_initialized = 0; @@ -358,12 +365,12 @@ static const OSSL_ALGORITHM p_scossl_keyexch[] = { ALG_TABLE_END}; // Signature -extern const OSSL_DISPATCH p_scossl_rsa_signature_functions[]; extern const OSSL_DISPATCH p_scossl_ecdsa_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_rsa_signature_functions[]; static const OSSL_ALGORITHM p_scossl_signature[] = { - ALG(SCOSSL_ALG_NAME_RSA, p_scossl_rsa_signature_functions), ALG(SCOSSL_ALG_NAME_ECDSA, p_scossl_ecdsa_signature_functions), + ALG(SCOSSL_ALG_NAME_RSA, p_scossl_rsa_signature_functions), ALG_TABLE_END}; // Asymmetric Cipher @@ -410,17 +417,7 @@ static const OSSL_ALGORITHM p_scossl_encoder[] = { static SCOSSL_STATUS p_scossl_register_extended_algorithms() { - if (OBJ_create(SCOSSL_OID_MLKEM512, SCOSSL_SN_MLKEM512, SCOSSL_SN_MLKEM512) == NID_undef || - OBJ_create(SCOSSL_OID_MLKEM768, SCOSSL_SN_MLKEM768, SCOSSL_SN_MLKEM768) == NID_undef || - OBJ_create(SCOSSL_OID_MLKEM1024, SCOSSL_SN_MLKEM1024, SCOSSL_SN_MLKEM1024) == NID_undef || - OBJ_create(SCOSSL_OID_P256_MLKEM768, SCOSSL_SN_P256_MLKEM768, SCOSSL_SN_P256_MLKEM768) == NID_undef || - OBJ_create(SCOSSL_OID_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768) == NID_undef || - OBJ_create(SCOSSL_OID_P384_MLKEM1024, SCOSSL_SN_P384_MLKEM1024, SCOSSL_SN_P384_MLKEM1024) == NID_undef) - { - return SCOSSL_FAILURE; - } - - return SCOSSL_SUCCESS; + return p_scossl_mlkem_register_algorithms(); } static int p_scossl_get_status() @@ -702,12 +699,19 @@ SCOSSL_STATUS OSSL_provider_init(_In_ const OSSL_CORE_HANDLE *handle, { SCOSSL_PROVCTX *p_ctx = NULL; - for (const OSSL_DISPATCH *coreFns = in; coreFns->function_id != 0; coreFns++) + p_scossl_set_core_bio(in); + if ((p_ctx->coreBioMeth = p_scossl_bio_init()) == NULL) + { + OPENSSL_free(p_ctx); + return SCOSSL_FAILURE; + } + + for (; in->function_id != 0; in++) { - switch(coreFns->function_id) + switch(in->function_id) { case OSSL_FUNC_CORE_GET_PARAMS: - core_get_params = OSSL_FUNC_core_get_params(coreFns); + core_get_params = OSSL_FUNC_core_get_params(in); break; } } @@ -724,7 +728,6 @@ SCOSSL_STATUS OSSL_provider_init(_In_ const OSSL_CORE_HANDLE *handle, ERR_raise(ERR_LIB_PROV, ERR_R_INIT_FAIL); return SCOSSL_FAILURE; } - scossl_prov_initialized = 1; } @@ -735,13 +738,6 @@ SCOSSL_STATUS OSSL_provider_init(_In_ const OSSL_CORE_HANDLE *handle, return SCOSSL_FAILURE; } - p_scossl_set_core_bio(in); - if ((p_ctx->coreBioMeth = p_scossl_bio_init()) == NULL) - { - OPENSSL_free(p_ctx); - return SCOSSL_FAILURE; - } - p_ctx->handle = handle; p_ctx->libctx = OSSL_LIB_CTX_new_child(handle, in); *provctx = p_ctx; diff --git a/SymCryptProvider/src/p_scossl_bio.c b/SymCryptProvider/src/p_scossl_bio.c index 6ef99ec4..ea00ca67 100644 --- a/SymCryptProvider/src/p_scossl_bio.c +++ b/SymCryptProvider/src/p_scossl_bio.c @@ -78,30 +78,30 @@ static int p_scossl_bio_core_puts(BIO *bio, const char *str) _Use_decl_annotations_ void p_scossl_set_core_bio(const OSSL_DISPATCH *dispatch) { - for (const OSSL_DISPATCH *coreFns = dispatch; coreFns->function_id != 0; coreFns++) + for (; dispatch->function_id != 0; dispatch++) { - switch (coreFns->function_id) + switch (dispatch->function_id) { case OSSL_FUNC_BIO_READ_EX: - core_bio_read_ex = (OSSL_FUNC_BIO_read_ex_fn *)coreFns->function; + core_bio_read_ex = (OSSL_FUNC_BIO_read_ex_fn *)dispatch->function; break; case OSSL_FUNC_BIO_WRITE_EX: - core_bio_write_ex = (OSSL_FUNC_BIO_write_ex_fn *)coreFns->function; + core_bio_write_ex = (OSSL_FUNC_BIO_write_ex_fn *)dispatch->function; break; case OSSL_FUNC_BIO_UP_REF: - core_bio_up_ref = (OSSL_FUNC_BIO_up_ref_fn *)coreFns->function; + core_bio_up_ref = (OSSL_FUNC_BIO_up_ref_fn *)dispatch->function; break; case OSSL_FUNC_BIO_FREE: - core_bio_free = (OSSL_FUNC_BIO_free_fn *)coreFns->function; + core_bio_free = (OSSL_FUNC_BIO_free_fn *)dispatch->function; break; case OSSL_FUNC_BIO_PUTS: - core_bio_puts = (OSSL_FUNC_BIO_puts_fn *)coreFns->function; + core_bio_puts = (OSSL_FUNC_BIO_puts_fn *)dispatch->function; break; case OSSL_FUNC_BIO_GETS: - core_bio_gets = (OSSL_FUNC_BIO_gets_fn *)coreFns->function; + core_bio_gets = (OSSL_FUNC_BIO_gets_fn *)dispatch->function; break; case OSSL_FUNC_BIO_CTRL: - core_bio_ctrl = (OSSL_FUNC_BIO_ctrl_fn *)coreFns->function; + core_bio_ctrl = (OSSL_FUNC_BIO_ctrl_fn *)dispatch->function; break; } } diff --git a/SymCryptProvider/src/p_scossl_ecc.h b/SymCryptProvider/src/p_scossl_ecc.h index 67fe7464..33f4972f 100644 --- a/SymCryptProvider/src/p_scossl_ecc.h +++ b/SymCryptProvider/src/p_scossl_ecc.h @@ -53,7 +53,7 @@ SCOSSL_STATUS p_scossl_ecc_get_encoded_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, int _Out_writes_bytes_(*pcbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); SCOSSL_STATUS p_scossl_ecc_set_encoded_key(_In_ SCOSSL_ECC_KEY_CTX *keyCtx, _In_reads_bytes_opt_(cbEncodedPublicKey) PCBYTE pbEncodedPublicKey, SIZE_T cbEncodedPublicKey, - _In_reads_bytes_opt_(cbPrivateKey) PCBYTE pbPrivateKey, SIZE_T cbPrivateKey); + _In_reads_bytes_opt_(cbEncodedPrivateKey) PCBYTE pbEncodedPrivateKey, SIZE_T cbEncodedPrivateKey); #ifdef KEYSINUSE_ENABLED void p_scossl_ecc_init_keysinuse(_In_ SCOSSL_ECC_KEY_CTX *keyCtx); From 0a98fd59e163f20a535bd8d2bb4a165a93bea9ae Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Mon, 30 Dec 2024 22:09:06 +0000 Subject: [PATCH 19/21] Cleanup and refactoring --- SymCryptProvider/inc/p_scossl_base.h.in | 4 +- .../src/decoder/p_scossl_decode_common.c | 23 +- .../src/decoder/p_scossl_decode_common.h | 13 +- .../src/decoder/p_scossl_decode_mlkem.c | 56 ++-- .../src/encoder/p_scossl_encode_common.c | 61 ++--- .../src/encoder/p_scossl_encode_common.h | 33 ++- .../src/encoder/p_scossl_encode_mlkem.c | 90 +++--- SymCryptProvider/src/kem/p_scossl_mlkem.c | 146 ++++++---- SymCryptProvider/src/kem/p_scossl_mlkem.h | 14 +- SymCryptProvider/src/keyexch/p_scossl_ecdh.c | 2 +- .../src/keymgmt/p_scossl_ecc_keymgmt.c | 2 +- ..._impexp_types.h => p_scossl_ecc_keymgmt.h} | 2 +- .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 259 ++++++++---------- .../src/keymgmt/p_scossl_mlkem_keymgmt.h | 6 +- SymCryptProvider/src/p_scossl_base.c | 20 +- SymCryptProvider/src/p_scossl_names.h | 9 +- 16 files changed, 376 insertions(+), 364 deletions(-) rename SymCryptProvider/src/keymgmt/{p_scossl_ecc_impexp_types.h => p_scossl_ecc_keymgmt.h} (98%) diff --git a/SymCryptProvider/inc/p_scossl_base.h.in b/SymCryptProvider/inc/p_scossl_base.h.in index b07bebda..fbdcb50b 100644 --- a/SymCryptProvider/inc/p_scossl_base.h.in +++ b/SymCryptProvider/inc/p_scossl_base.h.in @@ -4,12 +4,12 @@ #pragma once +#include "scossl_helpers.h" + #include #include #include -#include "scossl_helpers.h" - #ifdef __cplusplus extern "C" { #endif diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_common.c b/SymCryptProvider/src/decoder/p_scossl_decode_common.c index 3f09a1e5..af548444 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_common.c +++ b/SymCryptProvider/src/decoder/p_scossl_decode_common.c @@ -2,18 +2,18 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // +#include "p_scossl_bio.h" +#include "p_scossl_decode_common.h" + #include #include -#include "p_scossl_bio.h" -#include "decoder/p_scossl_decode_common.h" - #ifdef __cplusplus extern "C" { #endif ASN1_NDEF_SEQUENCE(SUBJECT_PUBKEY_INFO) = { - ASN1_SIMPLE(SUBJECT_PUBKEY_INFO, algorithm, X509_ALGOR), + ASN1_SIMPLE(SUBJECT_PUBKEY_INFO, x509Alg, X509_ALGOR), ASN1_SIMPLE(SUBJECT_PUBKEY_INFO, subjectPublicKey, ASN1_BIT_STRING), } ASN1_SEQUENCE_END(SUBJECT_PUBKEY_INFO) @@ -45,18 +45,18 @@ void p_scossl_decode_freectx(SCOSSL_DECODE_CTX *ctx) OPENSSL_free(ctx); } -const OSSL_PARAM *p_scossl_decode_settable_ctx_params(ossl_unused void *ctx) +SCOSSL_STATUS p_scossl_decode_set_ctx_params(ossl_unused void *ctx, ossl_unused const OSSL_PARAM params[]) { - return p_scossl_der_to_key_settable_param_types; + return SCOSSL_SUCCESS; } -SCOSSL_STATUS p_scossl_decode_set_ctx_params(ossl_unused void *ctx, ossl_unused const OSSL_PARAM params[]) +const OSSL_PARAM *p_scossl_decode_settable_ctx_params(ossl_unused void *ctx) { - return SCOSSL_SUCCESS; + return p_scossl_der_to_key_settable_param_types; } _Use_decl_annotations_ -BOOL p_scossl_decode_does_selection(SCOSSL_DECODE_KEYTYPE_DESC *desc, int selection) +BOOL p_scossl_decode_does_selection(const SCOSSL_DECODE_KEYTYPE_DESC *desc, int selection) { if (selection == 0) { @@ -113,6 +113,11 @@ SCOSSL_STATUS p_scossl_decode(SCOSSL_DECODE_CTX *ctx, OSSL_CORE_BIO *in, int sel return ret; } +const ASN1_ITEM *p_scossl_decode_subject_pubkey_asn1_item() +{ + return ASN1_ITEM_rptr(SUBJECT_PUBKEY_INFO); +} + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_common.h b/SymCryptProvider/src/decoder/p_scossl_decode_common.h index e90f0a05..5fde32dd 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_common.h +++ b/SymCryptProvider/src/decoder/p_scossl_decode_common.h @@ -3,7 +3,6 @@ // #include "p_scossl_base.h" -#include "kem/p_scossl_mlkem.h" #ifdef __cplusplus extern "C" { @@ -12,9 +11,7 @@ extern "C" { #define select_PrivateKeyInfo OSSL_KEYMGMT_SELECT_PRIVATE_KEY #define select_SubjectPublicKeyInfo OSSL_KEYMGMT_SELECT_PUBLIC_KEY -struct scossl_decode_ctx_st; - -typedef PVOID (*PSCOSSL_DECODE_INTERNAL_FN) (_In_ struct scossl_decode_ctx_st *ctx, _In_ BIO *bio); +typedef PVOID (*PSCOSSL_DECODE_INTERNAL_FN) (_In_ PVOID decodeCtx, _In_ BIO *bio); typedef struct { @@ -34,23 +31,25 @@ typedef struct scossl_decode_ctx_st typedef struct { - X509_ALGOR *algorithm; + X509_ALGOR *x509Alg; ASN1_BIT_STRING *subjectPublicKey; } SUBJECT_PUBKEY_INFO; SCOSSL_DECODE_CTX *p_scossl_decode_newctx(_In_ SCOSSL_PROVCTX *provctx, _In_ const SCOSSL_DECODE_KEYTYPE_DESC *desc); void p_scossl_decode_freectx(_Inout_ SCOSSL_DECODE_CTX *ctx); -const OSSL_PARAM *p_scossl_decode_settable_ctx_params(ossl_unused void *ctx); SCOSSL_STATUS p_scossl_decode_set_ctx_params(ossl_unused void *ctx, ossl_unused const OSSL_PARAM params[]); +const OSSL_PARAM *p_scossl_decode_settable_ctx_params(ossl_unused void *ctx); -BOOL p_scossl_decode_does_selection(_In_ SCOSSL_DECODE_KEYTYPE_DESC *desc, int selection); +BOOL p_scossl_decode_does_selection(_In_ const SCOSSL_DECODE_KEYTYPE_DESC *desc, int selection); SCOSSL_STATUS p_scossl_decode(_In_ SCOSSL_DECODE_CTX *ctx, _In_ OSSL_CORE_BIO *in, int selection, _In_ OSSL_CALLBACK *dataCb, _In_ void *dataCbArg, ossl_unused OSSL_PASSPHRASE_CALLBACK *passphraseCb, ossl_unused void *passphraseCbArg); +const ASN1_ITEM *p_scossl_decode_subject_pubkey_asn1_item(); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c index 5931bdc9..1d893a80 100644 --- a/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c +++ b/SymCryptProvider/src/decoder/p_scossl_decode_mlkem.c @@ -3,7 +3,7 @@ // #include "scossl_provider.h" -#include "decoder/p_scossl_decode_common.h" +#include "p_scossl_decode_common.h" #include "keymgmt/p_scossl_mlkem_keymgmt.h" #include @@ -13,25 +13,25 @@ extern "C" { #endif -static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_decode_key(_In_ SCOSSL_DECODE_CTX *ctx, _In_ const ASN1_OBJECT *algorithm, int selection, - _In_reads_bytes_(cbKey) PCBYTE pbKey, SIZE_T cbKey) +static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_decode_key_bytes(_In_ SCOSSL_DECODE_CTX *ctx, _In_ const ASN1_OBJECT *algorithm, int selection, + _In_reads_bytes_(cbKey) PCBYTE pbKey, SIZE_T cbKey) { - const char *groupName; - int nid; SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; SCOSSL_STATUS status = SCOSSL_FAILURE; - if ((keyCtx = OPENSSL_malloc(sizeof(SCOSSL_MLKEM_KEY_CTX))) == NULL) + if (pbKey == NULL || cbKey == 0) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); goto cleanup; } - keyCtx->provCtx = ctx->provctx; + if ((keyCtx = p_scossl_mlkem_keymgmt_new_ctx(ctx->provctx)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } - if ((nid = OBJ_obj2nid(algorithm)) < 0 || - (groupName = OBJ_nid2sn(nid)) == NULL || - p_scossl_mlkem_keymgmt_set_group(keyCtx, groupName) != SCOSSL_SUCCESS) + if ((keyCtx->groupInfo = p_scossl_mlkem_get_group_info_by_nid(OBJ_obj2nid(algorithm))) == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); goto cleanup; @@ -52,22 +52,22 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_decode_key(_In_ SCOSSL_DECODE_CTX *c static SCOSSL_MLKEM_KEY_CTX *p_scossl_PrivateKeyInfo_to_mlkem(_In_ SCOSSL_DECODE_CTX *ctx, _In_ BIO *bio) { PKCS8_PRIV_KEY_INFO *p8Info = NULL; - const X509_ALGOR *alg = NULL; - const unsigned char *pbKey = NULL; + const ASN1_OBJECT *algorithm; + const unsigned char *pbKey; int cbKey; ASN1_OCTET_STRING *p8Data = NULL; SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; if (d2i_PKCS8_PRIV_KEY_INFO_bio(bio, &p8Info) == NULL || - !PKCS8_pkey_get0(NULL, &pbKey, &cbKey, &alg, p8Info) || - (p8Data = d2i_ASN1_OCTET_STRING(NULL, &pbKey, cbKey)) == NULL) + !PKCS8_pkey_get0(&algorithm, &pbKey, &cbKey, NULL, p8Info) || + d2i_ASN1_OCTET_STRING(&p8Data, &pbKey, cbKey) == NULL) { - ERR_raise(ERR_LIB_PROV, ASN1_R_DECODE_ERROR); + ERR_raise(ERR_LIB_PROV, PROV_R_BAD_ENCODING); goto cleanup; } - keyCtx = p_scossl_mlkem_decode_key(ctx, alg->algorithm, OSSL_KEYMGMT_SELECT_PRIVATE_KEY, - ASN1_STRING_get0_data(p8Data), ASN1_STRING_length(p8Data)); + keyCtx = p_scossl_mlkem_decode_key_bytes(ctx, algorithm, OSSL_KEYMGMT_SELECT_PRIVATE_KEY, + ASN1_STRING_get0_data(p8Data), ASN1_STRING_length(p8Data)); cleanup: ASN1_OCTET_STRING_free(p8Data); @@ -78,7 +78,8 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_PrivateKeyInfo_to_mlkem(_In_ SCOSSL_DECODE static SCOSSL_MLKEM_KEY_CTX *p_scossl_SubjectPublicKeyInfo_to_mlkem(_In_ SCOSSL_DECODE_CTX *ctx, _In_ BIO *bio) { - SUBJECT_PUBKEY_INFO *subjPubKeyInfo; + SUBJECT_PUBKEY_INFO *subjPubKeyInfo = NULL; + const ASN1_OBJECT *algorithm; SCOSSL_MLKEM_KEY_CTX *keyCtx = NULL; if ((subjPubKeyInfo = OPENSSL_zalloc(sizeof(SUBJECT_PUBKEY_INFO))) == NULL) @@ -87,14 +88,16 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_SubjectPublicKeyInfo_to_mlkem(_In_ SCOSSL_ goto cleanup; } - if (ASN1_item_d2i_bio(ASN1_ITEM_rptr(SUBJECT_PUBKEY_INFO), bio, (ASN1_VALUE **)&subjPubKeyInfo) == NULL) + if (ASN1_item_d2i_bio(p_scossl_decode_subject_pubkey_asn1_item(), bio, (ASN1_VALUE **)&subjPubKeyInfo) == NULL) { - ERR_raise(ERR_LIB_PROV, ASN1_R_DECODE_ERROR); + ERR_raise(ERR_LIB_PROV, PROV_R_BAD_ENCODING); goto cleanup; } - keyCtx = p_scossl_mlkem_decode_key(ctx, subjPubKeyInfo->algorithm->algorithm, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, - subjPubKeyInfo->subjectPublicKey->data, subjPubKeyInfo->subjectPublicKey->length); + X509_ALGOR_get0(&algorithm, NULL, NULL, subjPubKeyInfo->x509Alg); + + keyCtx = p_scossl_mlkem_decode_key_bytes(ctx, algorithm, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, + ASN1_STRING_get0_data(subjPubKeyInfo->subjectPublicKey), ASN1_STRING_length(subjPubKeyInfo->subjectPublicKey)); cleanup: OPENSSL_free(subjPubKeyInfo); @@ -118,7 +121,7 @@ static SCOSSL_STATUS p_scossl_der_to_mlkem_export_object(_In_ SCOSSL_DECODE_CTX } #define SCOSSL_MAKE_MLKEM_DECODER(decoderType) \ - static SCOSSL_DECODE_KEYTYPE_DESC p_scossl_mlkem_##decoderType##_desc = { \ + static const SCOSSL_DECODE_KEYTYPE_DESC p_scossl_mlkem_##decoderType##_desc = { \ "MLKEM", \ select_##decoderType, \ (PSCOSSL_DECODE_INTERNAL_FN)p_scossl_##decoderType##_to_mlkem, \ @@ -145,16 +148,13 @@ static SCOSSL_STATUS p_scossl_der_to_mlkem_export_object(_In_ SCOSSL_DECODE_CTX const OSSL_DISPATCH p_scossl_der_to_mlkem_##decoderType##_functions[] = { \ {OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))p_scossl_der_to_mlkem_##decoderType##_newctx}, \ {OSSL_FUNC_DECODER_FREECTX, (void (*)(void))p_scossl_decode_freectx}, \ - {OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_decode_settable_ctx_params}, \ {OSSL_FUNC_DECODER_SET_CTX_PARAMS, (void (*)(void))p_scossl_decode_set_ctx_params}, \ + {OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_decode_settable_ctx_params}, \ {OSSL_FUNC_DECODER_DOES_SELECTION, (void (*)(void)) p_scossl_der_to_mlkem_##decoderType##_does_selection}, \ {OSSL_FUNC_DECODER_DECODE, (void (*)(void))p_scossl_decode}, \ {OSSL_FUNC_DECODER_EXPORT_OBJECT, (void (*)(void))p_scossl_der_to_mlkem_export_object}, \ {0, NULL}}; - -extern const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[]; - SCOSSL_MAKE_MLKEM_DECODER(PrivateKeyInfo); SCOSSL_MAKE_MLKEM_DECODER(SubjectPublicKeyInfo); diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_common.c b/SymCryptProvider/src/encoder/p_scossl_encode_common.c index 79c57720..f1ecb5bd 100644 --- a/SymCryptProvider/src/encoder/p_scossl_encode_common.c +++ b/SymCryptProvider/src/encoder/p_scossl_encode_common.c @@ -3,7 +3,7 @@ // #include "p_scossl_bio.h" -#include "encoder/p_scossl_encode_common.h" +#include "p_scossl_encode_common.h" #include @@ -19,20 +19,15 @@ static const OSSL_PARAM p_scossl_encode_settable_param_types[] = { OSSL_PARAM_END}; _Use_decl_annotations_ -SCOSSL_ENCODE_CTX *p_scossl_encode_newctx(SCOSSL_PROVCTX *provctx, - int selection, - SCOSSL_ENCODE_OUT_FORMAT outFormat, - PSCOSSL_ENCODE_INTERNAL_FN encodeInternal) +SCOSSL_ENCODE_CTX *p_scossl_encode_newctx(SCOSSL_PROVCTX *provctx, const SCOSSL_ENCODE_KEYTYPE_DESC *desc) { SCOSSL_ENCODE_CTX *ctx = OPENSSL_zalloc(sizeof(SCOSSL_ENCODE_CTX)); if (ctx != NULL) { ctx->provctx = provctx; - ctx->selection = selection; - ctx->outFormat = outFormat; - ctx->encodeInternal = encodeInternal; - } + ctx->desc = desc; + } return ctx; } @@ -49,16 +44,22 @@ void p_scossl_encode_freectx(SCOSSL_ENCODE_CTX *ctx) _Use_decl_annotations_ SCOSSL_STATUS p_scossl_encode_set_ctx_params(SCOSSL_ENCODE_CTX *ctx, const OSSL_PARAM params[]) { - OSSL_LIB_CTX *libctx = ctx->provctx != NULL ? ctx->provctx->libctx : NULL; - const char *cipherName = NULL; - const char *propQ = NULL; - const OSSL_PARAM *paramCipher = OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_CIPHER); - const OSSL_PARAM *paramProperties = OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_PROPERTIES); + const OSSL_PARAM *p; - if (paramCipher != NULL) + if ((p = OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_CIPHER)) != NULL) { - if (!OSSL_PARAM_get_utf8_string_ptr(paramCipher, &cipherName) || - (paramProperties != NULL && !OSSL_PARAM_get_utf8_string_ptr(paramProperties, &propQ))) + OSSL_LIB_CTX *libctx = ctx->provctx != NULL ? ctx->provctx->libctx : NULL; + const char *cipherName = NULL; + const char *propQ = NULL; + + if (!OSSL_PARAM_get_utf8_string_ptr(p, &cipherName)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return SCOSSL_FAILURE; + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_PROPERTIES)) != NULL && + !OSSL_PARAM_get_utf8_string_ptr(p, &propQ)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return SCOSSL_FAILURE; @@ -70,19 +71,14 @@ SCOSSL_STATUS p_scossl_encode_set_ctx_params(SCOSSL_ENCODE_CTX *ctx, const OSSL_ { if ((ctx->cipher = EVP_CIPHER_fetch(libctx, cipherName, propQ)) == NULL) { - ctx->cipherIntent = FALSE; ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return SCOSSL_FAILURE; } - ctx->cipherIntent = TRUE; - } else { ctx->cipher = NULL; } - - ctx->cipherIntent = ctx->cipher != NULL; } return SCOSSL_SUCCESS; @@ -93,7 +89,7 @@ const OSSL_PARAM *p_scossl_encode_settable_ctx_params(ossl_unused void *provctx) return p_scossl_encode_settable_param_types; } -BOOL p_scossl_encode_does_selection(int supportedSelection, int selection) +BOOL p_scossl_encode_does_selection(const SCOSSL_ENCODE_KEYTYPE_DESC *desc, int selection) { if (selection == 0) { @@ -102,15 +98,14 @@ BOOL p_scossl_encode_does_selection(int supportedSelection, int selection) // Supporting private key implies supporting public key. // Both imply supporting key parameters - - return ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && (supportedSelection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) || - ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0 && (supportedSelection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) || - ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0 && (supportedSelection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0); + return ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) || + ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) || + ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0 && (desc->selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0); } _Use_decl_annotations_ SCOSSL_STATUS p_scossl_encode(SCOSSL_ENCODE_CTX *ctx, OSSL_CORE_BIO *out, - const SCOSSL_MLKEM_KEY_CTX *keyCtx, + const void *keyCtx, const OSSL_PARAM keyAbstract[], int selection, OSSL_PASSPHRASE_CALLBACK *passphraseCb, void *passphraseCbArgs) @@ -124,9 +119,9 @@ SCOSSL_STATUS p_scossl_encode(SCOSSL_ENCODE_CTX *ctx, OSSL_CORE_BIO *out, goto cleanup; } - if (ctx->encodeInternal == NULL || + if (ctx->desc->encodeInternal == NULL || keyAbstract != NULL || - (ctx->outFormat != SCOSSL_ENCODE_TEXT && ((selection & ctx->selection) == 0))) + (ctx->desc->outFormat != SCOSSL_ENCODE_TEXT && ((selection & ctx->desc->selection) == 0))) { ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); goto cleanup; @@ -134,12 +129,11 @@ SCOSSL_STATUS p_scossl_encode(SCOSSL_ENCODE_CTX *ctx, OSSL_CORE_BIO *out, if ((bio = p_scossl_bio_new_from_core_bio(ctx->provctx, out)) != NULL) { - ret = ctx->encodeInternal( + ret = ctx->desc->encodeInternal( ctx, bio, keyCtx, selection, - passphraseCb, passphraseCbArgs, - ctx->outFormat == SCOSSL_ENCODE_PEM); + passphraseCb, passphraseCbArgs); } cleanup: @@ -175,7 +169,6 @@ SCOSSL_STATUS p_scossl_encode_write_key_bytes(PCBYTE pbKey, SIZE_T cbKey, BIO *o return SCOSSL_SUCCESS; } - #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_common.h b/SymCryptProvider/src/encoder/p_scossl_encode_common.h index e921a2e4..f791f612 100644 --- a/SymCryptProvider/src/encoder/p_scossl_encode_common.h +++ b/SymCryptProvider/src/encoder/p_scossl_encode_common.h @@ -3,7 +3,6 @@ // #include "p_scossl_base.h" -#include "kem/p_scossl_mlkem.h" #ifdef __cplusplus extern "C" { @@ -14,43 +13,43 @@ extern "C" { #define select_SubjectPublicKeyInfo OSSL_KEYMGMT_SELECT_PUBLIC_KEY typedef enum { - SCOSSL_ENCODE_PEM = 1, - SCOSSL_ENCODE_DER, + SCOSSL_ENCODE_DER = 1, + SCOSSL_ENCODE_PEM, SCOSSL_ENCODE_TEXT } SCOSSL_ENCODE_OUT_FORMAT; -typedef SCOSSL_STATUS (*PSCOSSL_ENCODE_INTERNAL_FN) (_In_ PVOID ctx, _Inout_ BIO *out, +typedef SCOSSL_STATUS (*PSCOSSL_ENCODE_INTERNAL_FN) (_In_ PVOID encodeCtx, _Inout_ BIO *out, _In_ PCVOID keyCtx, int selection, - _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs, - BOOL encodeToPem); + _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs); typedef struct { - SCOSSL_PROVCTX *provctx; - int selection; + SCOSSL_ENCODE_OUT_FORMAT outFormat; + + PSCOSSL_ENCODE_INTERNAL_FN encodeInternal; +} SCOSSL_ENCODE_KEYTYPE_DESC; + +typedef struct +{ + SCOSSL_PROVCTX *provctx; - BOOL cipherIntent; EVP_CIPHER *cipher; - SCOSSL_ENCODE_OUT_FORMAT outFormat; - PSCOSSL_ENCODE_INTERNAL_FN encodeInternal; + const SCOSSL_ENCODE_KEYTYPE_DESC *desc; } SCOSSL_ENCODE_CTX; -SCOSSL_ENCODE_CTX *p_scossl_encode_newctx(_In_ SCOSSL_PROVCTX *provctx, - int selection, - SCOSSL_ENCODE_OUT_FORMAT outFormat, - _In_ PSCOSSL_ENCODE_INTERNAL_FN encodeInternal); +SCOSSL_ENCODE_CTX *p_scossl_encode_newctx(_In_ SCOSSL_PROVCTX *provctx, const SCOSSL_ENCODE_KEYTYPE_DESC *desc); void p_scossl_encode_freectx(_Inout_ SCOSSL_ENCODE_CTX *ctx); SCOSSL_STATUS p_scossl_encode_set_ctx_params(_In_ SCOSSL_ENCODE_CTX *ctx, _In_ const OSSL_PARAM params[]); const OSSL_PARAM *p_scossl_encode_settable_ctx_params(ossl_unused void *provctx); -BOOL p_scossl_encode_does_selection(int supportedSelection, int selection); +BOOL p_scossl_encode_does_selection(_In_ const SCOSSL_ENCODE_KEYTYPE_DESC *desc, int selection); SCOSSL_STATUS p_scossl_encode(_In_ SCOSSL_ENCODE_CTX *ctx, _In_ OSSL_CORE_BIO *coreOut, - _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, + _In_ const void *keyCtx, _In_ const OSSL_PARAM keyAbstract[], int selection, _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs); diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c index 7dc45d58..da7ab981 100644 --- a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c +++ b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c @@ -3,7 +3,7 @@ // #include "scossl_provider.h" -#include "encoder/p_scossl_encode_common.h" +#include "p_scossl_encode_common.h" #include "keymgmt/p_scossl_mlkem_keymgmt.h" #include @@ -18,14 +18,7 @@ extern const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[]; static ASN1_OBJECT *p_scossl_encode_mlkem_get_oid(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx) { - int nid = OBJ_sn2nid(keyCtx->groupName); - - if (nid != NID_undef) - { - return OBJ_nid2obj(nid); - } - - return NULL; + return keyCtx->groupInfo != NULL ? OBJ_nid2obj(keyCtx->groupInfo->nid) : NULL; } static PKCS8_PRIV_KEY_INFO *p_scossl_mlkem_key_to_p8info(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx) @@ -151,8 +144,7 @@ static X509_PUBKEY *p_scossl_mlkem_key_to_pubkey(_In_ const SCOSSL_MLKEM_KEY_CTX static SCOSSL_STATUS p_scossl_mlkem_to_EncryptedPrivateKeyInfo(_In_ SCOSSL_ENCODE_CTX *ctx, _Inout_ BIO *out, _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, ossl_unused int selection, - _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs, - BOOL encodeToPem) + _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs) { int encodeSuccess; PKCS8_PRIV_KEY_INFO *p8Info = NULL; @@ -184,7 +176,7 @@ static SCOSSL_STATUS p_scossl_mlkem_to_EncryptedPrivateKeyInfo(_In_ SCOSSL_ENCOD goto cleanup; } - if (encodeToPem) + if (ctx->desc->outFormat == SCOSSL_ENCODE_PEM) { encodeSuccess = PEM_write_bio_PKCS8(out, p8); } @@ -212,16 +204,15 @@ static SCOSSL_STATUS p_scossl_mlkem_to_EncryptedPrivateKeyInfo(_In_ SCOSSL_ENCOD static SCOSSL_STATUS p_scossl_mlkem_to_PrivateKeyInfo(_In_ SCOSSL_ENCODE_CTX *ctx, _Inout_ BIO *out, _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, ossl_unused int selection, - _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs, - BOOL encodeToPem) + _In_ OSSL_PASSPHRASE_CALLBACK *passphraseCb, _In_ void *passphraseCbArgs) { int encodeSuccess; PKCS8_PRIV_KEY_INFO *p8Info = NULL; SCOSSL_STATUS ret = SCOSSL_FAILURE; - if (ctx->cipherIntent) + if (ctx->cipher != NULL) { - return p_scossl_mlkem_to_EncryptedPrivateKeyInfo(ctx, out, keyCtx, selection, passphraseCb, passphraseCbArgs, encodeToPem); + return p_scossl_mlkem_to_EncryptedPrivateKeyInfo(ctx, out, keyCtx, selection, passphraseCb, passphraseCbArgs); } if ((p8Info = p_scossl_mlkem_key_to_p8info(keyCtx)) == NULL) @@ -229,7 +220,7 @@ static SCOSSL_STATUS p_scossl_mlkem_to_PrivateKeyInfo(_In_ SCOSSL_ENCODE_CTX *ct goto cleanup; } - if (encodeToPem) + if (ctx->desc->outFormat == SCOSSL_ENCODE_PEM) { encodeSuccess = PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8Info); } @@ -255,8 +246,7 @@ static SCOSSL_STATUS p_scossl_mlkem_to_PrivateKeyInfo(_In_ SCOSSL_ENCODE_CTX *ct static SCOSSL_STATUS p_scossl_mlkem_to_SubjectPublicKeyInfo(ossl_unused SCOSSL_ENCODE_CTX *ctx, _Inout_ BIO *out, _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, ossl_unused int selection, - ossl_unused OSSL_PASSPHRASE_CALLBACK *passphraseCb, ossl_unused void *passphraseCbArgs, - BOOL encodeToPem) + ossl_unused OSSL_PASSPHRASE_CALLBACK *passphraseCb, ossl_unused void *passphraseCbArgs) { int encodeSuccess; X509_PUBKEY *pubKey = NULL; @@ -267,7 +257,7 @@ static SCOSSL_STATUS p_scossl_mlkem_to_SubjectPublicKeyInfo(ossl_unused SCOSSL_E goto cleanup; } - if (encodeToPem) + if (ctx->desc->outFormat == SCOSSL_ENCODE_PEM) { encodeSuccess = PEM_write_bio_X509_PUBKEY(out, pubKey); } @@ -293,8 +283,7 @@ static SCOSSL_STATUS p_scossl_mlkem_to_SubjectPublicKeyInfo(ossl_unused SCOSSL_E static SCOSSL_STATUS p_scossl_mlkem_to_text(ossl_unused SCOSSL_ENCODE_CTX *ctx, _Inout_ BIO *out, _In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, - ossl_unused OSSL_PASSPHRASE_CALLBACK *passphraseCb, ossl_unused void *passphraseCbArgs, - ossl_unused BOOL encodeToPem) + ossl_unused OSSL_PASSPHRASE_CALLBACK *passphraseCb, ossl_unused void *passphraseCbArgs) { BOOL printPrivateSeed = FALSE; BOOL printDecapsulationKey = FALSE; @@ -384,7 +373,7 @@ static SCOSSL_STATUS p_scossl_mlkem_to_text(ossl_unused SCOSSL_ENCODE_CTX *ctx, } } - if (BIO_printf(out, "PARAMETER SET: %s\n", keyCtx->groupName) <= 0) + if (BIO_printf(out, "PARAMETER SET: %s\n", keyCtx->groupInfo->groupName) <= 0) { goto cleanup; } @@ -410,57 +399,66 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_encoder_import_object(_In_ SCOSSL_EN return keyCtx; } -#define MAKE_MLKEM_ENCODER(decoderType) \ - static SCOSSL_ENCODE_CTX *p_scossl_mlkem_to_##decoderType##_der_newctx(_In_ SCOSSL_PROVCTX *provctx) \ +#define MAKE_MLKEM_ASN1_ENCODER(encoderType) \ + static SCOSSL_ENCODE_KEYTYPE_DESC p_scossl_mlkem_##encoderType##_der_desc = { \ + select_##encoderType, \ + SCOSSL_ENCODE_DER, \ + (PSCOSSL_ENCODE_INTERNAL_FN)p_scossl_mlkem_to_##encoderType}; \ + \ + static SCOSSL_ENCODE_KEYTYPE_DESC p_scossl_mlkem_##encoderType##_pem_desc = { \ + select_##encoderType, \ + SCOSSL_ENCODE_PEM, \ + (PSCOSSL_ENCODE_INTERNAL_FN)p_scossl_mlkem_to_##encoderType}; \ + \ + static SCOSSL_ENCODE_CTX *p_scossl_mlkem_to_##encoderType##_der_newctx(_In_ SCOSSL_PROVCTX *provctx) \ { \ - return p_scossl_encode_newctx(provctx, select_##decoderType, \ - SCOSSL_ENCODE_DER, \ - (PSCOSSL_ENCODE_INTERNAL_FN)p_scossl_mlkem_to_##decoderType); \ + return p_scossl_encode_newctx(provctx, &p_scossl_mlkem_##encoderType##_der_desc); \ } \ \ - static SCOSSL_ENCODE_CTX *p_scossl_mlkem_to_##decoderType##_pem_newctx(_In_ SCOSSL_PROVCTX *provctx) \ + static SCOSSL_ENCODE_CTX *p_scossl_mlkem_to_##encoderType##_pem_newctx(_In_ SCOSSL_PROVCTX *provctx) \ { \ - return p_scossl_encode_newctx(provctx, select_##decoderType, \ - SCOSSL_ENCODE_PEM, \ - (PSCOSSL_ENCODE_INTERNAL_FN)p_scossl_mlkem_to_##decoderType); \ + return p_scossl_encode_newctx(provctx, &p_scossl_mlkem_##encoderType##_pem_desc); \ } \ \ - static BOOL p_scossl_der_to_mlkem_##decoderType##_does_selection(ossl_unused void *provctx, int selection) \ + static BOOL p_scossl_der_to_mlkem_##encoderType##_does_selection(ossl_unused void *provctx, int selection) \ { \ - return p_scossl_encode_does_selection(select_##decoderType, selection); \ + return p_scossl_encode_does_selection(&p_scossl_mlkem_##encoderType##_der_desc, selection); \ } \ \ - const OSSL_DISPATCH p_scossl_mlkem_to_##decoderType##_der_functions[] = { \ - {OSSL_FUNC_ENCODER_NEWCTX, (void (*)(void))p_scossl_mlkem_to_##decoderType##_der_newctx}, \ + const OSSL_DISPATCH p_scossl_mlkem_to_##encoderType##_der_functions[] = { \ + {OSSL_FUNC_ENCODER_NEWCTX, (void (*)(void))p_scossl_mlkem_to_##encoderType##_der_newctx}, \ {OSSL_FUNC_ENCODER_FREECTX, (void (*)(void))p_scossl_encode_freectx}, \ {OSSL_FUNC_ENCODER_SET_CTX_PARAMS, (void (*)(void))p_scossl_encode_set_ctx_params}, \ {OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_encode_settable_ctx_params}, \ - {OSSL_FUNC_ENCODER_DOES_SELECTION, (void (*)(void))p_scossl_der_to_mlkem_##decoderType##_does_selection}, \ + {OSSL_FUNC_ENCODER_DOES_SELECTION, (void (*)(void))p_scossl_der_to_mlkem_##encoderType##_does_selection}, \ {OSSL_FUNC_ENCODER_ENCODE, (void (*)(void))p_scossl_encode}, \ {OSSL_FUNC_ENCODER_IMPORT_OBJECT, (void (*)(void))p_scossl_mlkem_encoder_import_object}, \ {OSSL_FUNC_ENCODER_FREE_OBJECT, (void (*)(void))p_scossl_mlkem_keymgmt_free_key_ctx}, \ {0, NULL}}; \ \ - const OSSL_DISPATCH p_scossl_mlkem_to_##decoderType##_pem_functions[] = { \ - {OSSL_FUNC_ENCODER_NEWCTX, (void (*)(void))p_scossl_mlkem_to_##decoderType##_pem_newctx}, \ + const OSSL_DISPATCH p_scossl_mlkem_to_##encoderType##_pem_functions[] = { \ + {OSSL_FUNC_ENCODER_NEWCTX, (void (*)(void))p_scossl_mlkem_to_##encoderType##_pem_newctx}, \ {OSSL_FUNC_ENCODER_FREECTX, (void (*)(void))p_scossl_encode_freectx}, \ {OSSL_FUNC_ENCODER_SET_CTX_PARAMS, (void (*)(void))p_scossl_encode_set_ctx_params}, \ {OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_encode_settable_ctx_params}, \ - {OSSL_FUNC_ENCODER_DOES_SELECTION, (void (*)(void))p_scossl_der_to_mlkem_##decoderType##_does_selection}, \ + {OSSL_FUNC_ENCODER_DOES_SELECTION, (void (*)(void))p_scossl_der_to_mlkem_##encoderType##_does_selection}, \ {OSSL_FUNC_ENCODER_ENCODE, (void (*)(void))p_scossl_encode}, \ {OSSL_FUNC_ENCODER_IMPORT_OBJECT, (void (*)(void))p_scossl_mlkem_encoder_import_object}, \ {OSSL_FUNC_ENCODER_FREE_OBJECT, (void (*)(void))p_scossl_mlkem_keymgmt_free_key_ctx}, \ {0, NULL}}; -MAKE_MLKEM_ENCODER(PrivateKeyInfo) -MAKE_MLKEM_ENCODER(EncryptedPrivateKeyInfo) -MAKE_MLKEM_ENCODER(SubjectPublicKeyInfo) +MAKE_MLKEM_ASN1_ENCODER(PrivateKeyInfo) +MAKE_MLKEM_ASN1_ENCODER(EncryptedPrivateKeyInfo) +MAKE_MLKEM_ASN1_ENCODER(SubjectPublicKeyInfo) + +static SCOSSL_ENCODE_KEYTYPE_DESC p_scossl_mlkem_text_desc = { + 0, + SCOSSL_ENCODE_TEXT, + (PSCOSSL_ENCODE_INTERNAL_FN)p_scossl_mlkem_to_text}; static SCOSSL_ENCODE_CTX *p_scossl_mlkem_to_text_newctx(_In_ SCOSSL_PROVCTX *provctx) { - return p_scossl_encode_newctx(provctx, 0, - SCOSSL_ENCODE_TEXT, - (PSCOSSL_ENCODE_INTERNAL_FN)p_scossl_mlkem_to_text); + return p_scossl_encode_newctx(provctx, &p_scossl_mlkem_text_desc); } const OSSL_DISPATCH p_scossl_mlkem_to_text_functions[] = { diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.c b/SymCryptProvider/src/kem/p_scossl_mlkem.c index 4ffc9c44..616bf303 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.c +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.c @@ -4,7 +4,7 @@ #include "scossl_provider.h" #include "p_scossl_base.h" -#include "kem/p_scossl_mlkem.h" +#include "p_scossl_mlkem.h" #include "keyexch/p_scossl_ecdh.h" #include @@ -15,13 +15,21 @@ extern "C" { #define SYMCRYPT_MLKEM_SECRET_LENGTH 32 +static SCOSSL_MLKEM_GROUP_INFO p_scossl_mlkem_groups[] = { + {NID_undef, SCOSSL_OID_MLKEM512, SCOSSL_SN_MLKEM512, NULL, SYMCRYPT_MLKEM_PARAMS_MLKEM512}, + {NID_undef, SCOSSL_OID_MLKEM768, SCOSSL_SN_MLKEM768, NULL, SYMCRYPT_MLKEM_PARAMS_MLKEM768}, + {NID_undef, SCOSSL_OID_MLKEM1024, SCOSSL_SN_MLKEM1024, NULL, SYMCRYPT_MLKEM_PARAMS_MLKEM1024}, + {NID_undef, SCOSSL_OID_P256_MLKEM768, SCOSSL_SN_P256_MLKEM768, SN_X9_62_prime256v1, SYMCRYPT_MLKEM_PARAMS_MLKEM768}, + {NID_undef, SCOSSL_OID_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768, SN_X25519, SYMCRYPT_MLKEM_PARAMS_MLKEM768}, + {NID_undef, SCOSSL_OID_P384_MLKEM1024, SCOSSL_SN_P384_MLKEM1024, SN_secp384r1, SYMCRYPT_MLKEM_PARAMS_MLKEM1024}}; + typedef struct { // Unused by MLKEM, but forwarded to the classic key exchange SCOSSL_PROVCTX *provCtx; - SCOSSL_MLKEM_KEY_CTX *keyCtx; int operation; + SCOSSL_MLKEM_KEY_CTX *keyCtx; SCOSSL_ECDH_CTX *classicKeyexchCtx; } SCOSSL_MLKEM_CTX; @@ -30,7 +38,7 @@ static const OSSL_PARAM p_scossl_mlkem_param_types[] = { OSSL_PARAM_END}; /* Context management */ -static SCOSSL_MLKEM_CTX *p_scossl_mlkem_newctx(ossl_unused void *provctx) +static SCOSSL_MLKEM_CTX *p_scossl_mlkem_newctx(_In_ SCOSSL_PROVCTX *provctx) { SCOSSL_MLKEM_CTX *ctx = OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_CTX)); @@ -47,11 +55,7 @@ static void p_scossl_mlkem_freectx(_Inout_ SCOSSL_MLKEM_CTX *ctx) if (ctx == NULL) return; - if (ctx->classicKeyexchCtx != NULL) - { - p_scossl_ecdh_freectx(ctx->classicKeyexchCtx); - } - + p_scossl_ecdh_freectx(ctx->classicKeyexchCtx); OPENSSL_free(ctx); } @@ -79,7 +83,7 @@ static SCOSSL_MLKEM_CTX *p_scossl_mlkem_dupctx(_In_ SCOSSL_MLKEM_CTX *ctx) return copyCtx; } -static SCOSSL_STATUS p_scossl_mlkem_classic_keyexch_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, PVOID classicKeyCtx) +static SCOSSL_STATUS p_scossl_mlkem_classic_keyexch_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, _In_ SCOSSL_ECC_KEY_CTX *classicKeyCtx) { if (ctx->classicKeyexchCtx == NULL && (ctx->classicKeyexchCtx = p_scossl_ecdh_newctx(ctx->provCtx)) == NULL) @@ -105,7 +109,8 @@ static SCOSSL_STATUS p_scossl_mlkem_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, _In_ SCO return SCOSSL_FAILURE; } - if (keyCtx == NULL || keyCtx->key == NULL) + if (keyCtx->key == NULL || + keyCtx->groupInfo == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY); return SCOSSL_FAILURE; @@ -121,9 +126,9 @@ static SCOSSL_STATUS p_scossl_mlkem_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, _In_ SCO // Encapsulation // -// We don't initialize the classic key context for hybrid here, since -// ctx->keyCtx->classicKeyCtx contains the peer key, and 'our' key is generated -// during encapsulation. +// We don't initialize the classic key context for hybrid here. +// ctx->keyCtx->classicKeyCtx contains the peer key. Our ephemeral key +// is generated during encapsulation. static SCOSSL_STATUS p_scossl_mlkem_encapsulate_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, _In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, ossl_unused const OSSL_PARAM params[]) { @@ -132,11 +137,16 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate_init(_Inout_ SCOSSL_MLKEM_CTX *c // Performs ML-KEM encapsulation using the previously initialized context. If // this is a hybrid group, then hybrid encapsulation is performed. -// ctx->keyCtx->classicKeyCtx is used as the peer key, and an ephemeral -// ECDH key is generated as 'our' key to derive the shared ECDH secret. +// ctx->keyCtx->classicKeyCtx is used as the peer key, and our ephemeral +// ECDH key is generated as to derive the shared ECDH secret. The concatenated +// order of classic and ML-KEM data depends on the classic group. // -// secret == ECDH shared secret | MLKEM secret -// out == Ephemeral ECDH public key | MLKEM ciphertext +// - secret +// X25519: MLKEM shared secret || ECDH shared secret +// P-256/P-384: ECDH shared secret || MLKEM shared secret +// - out +// X25519: MLKEM ciphertext || Ephemeral ECDH public key +// P-256/P-384: Ephemeral ECDH public key || MLKEM ciphertext static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, _Out_writes_bytes_opt_(*outlen) unsigned char *out, _Out_ size_t *outlen, _Out_writes_bytes_(*secretlen) unsigned char *secret, _Out_ size_t *secretlen) @@ -150,6 +160,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, SIZE_T cbClassicSecret = 0; SCOSSL_ECC_KEY_CTX *classicKeyCtxPeer = NULL; SCOSSL_ECC_KEY_CTX *classicKeyCtxPrivate = NULL; + const SCOSSL_MLKEM_GROUP_INFO *groupInfo; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -165,27 +176,25 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, goto cleanup; } - classicKeyCtxPeer = ctx->keyCtx->classicKeyCtx; + groupInfo = ctx->keyCtx->groupInfo; - if (ctx->keyCtx->classicGroupName != NULL) + if (groupInfo->classicGroupName != NULL) { - if (classicKeyCtxPeer == NULL) + if ((classicKeyCtxPeer = ctx->keyCtx->classicKeyCtx) == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); goto cleanup; } - // Get key size cbClassicKey = p_scossl_ecc_get_encoded_key_size(classicKeyCtxPeer, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); - // Get secret size if ((cbClassicSecret = p_scossl_ecc_get_max_size(classicKeyCtxPeer, TRUE)) == 0) { goto cleanup; } } - scError = SymCryptMlKemSizeofCiphertextFromParams(ctx->keyCtx->mlkemParams, &cbMlkemCiphertext); + scError = SymCryptMlKemSizeofCiphertextFromParams(groupInfo->mlkemParams, &cbMlkemCiphertext); if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); @@ -194,7 +203,14 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, if (out != NULL) { - if (ctx->keyCtx->classicGroupName != NULL) + if ((outlen != NULL && *outlen < cbClassicKey + cbMlkemCiphertext) || + (secretlen != NULL && *secretlen < cbClassicSecret + SYMCRYPT_MLKEM_SECRET_LENGTH)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + goto cleanup; + } + + if (groupInfo->classicGroupName != NULL) { if (classicKeyCtxPeer->isX25519) { @@ -207,7 +223,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, { pbClassicKey = out; pbMlkemCipherText = out + cbClassicKey; - pbClassicSecret = secret ; + pbClassicSecret = secret; pbMlkemSecret = secret + cbClassicSecret; } @@ -218,7 +234,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, goto cleanup; } - if (p_scossl_ecc_set_group(classicKeyCtxPrivate, ctx->keyCtx->classicGroupName) != SCOSSL_SUCCESS || + if (p_scossl_ecc_set_group(classicKeyCtxPrivate, groupInfo->classicGroupName) != SCOSSL_SUCCESS || p_scossl_ecc_gen(classicKeyCtxPrivate) != SCOSSL_SUCCESS) { goto cleanup; @@ -233,7 +249,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, // Derive ECDH secret if (p_scossl_mlkem_classic_keyexch_init(ctx, classicKeyCtxPrivate) != SCOSSL_SUCCESS || p_scossl_ecdh_set_peer(ctx->classicKeyexchCtx, classicKeyCtxPeer) != SCOSSL_SUCCESS || - p_scossl_ecdh_derive(ctx->classicKeyexchCtx, pbClassicSecret, &cbClassicSecret, *secretlen - SYMCRYPT_MLKEM_SECRET_LENGTH) != SCOSSL_SUCCESS) + p_scossl_ecdh_derive(ctx->classicKeyexchCtx, pbClassicSecret, &cbClassicSecret, cbClassicSecret) != SCOSSL_SUCCESS) { goto cleanup; } @@ -244,13 +260,6 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, pbMlkemSecret = secret; } - if ((outlen != NULL && *outlen < cbClassicKey + cbMlkemCiphertext) || - (secretlen != NULL && *secretlen < cbClassicSecret + SYMCRYPT_MLKEM_SECRET_LENGTH)) - { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - goto cleanup; - } - scError = SymCryptMlKemEncapsulate(ctx->keyCtx->key, pbMlkemSecret, SYMCRYPT_MLKEM_SECRET_LENGTH, pbMlkemCipherText, cbMlkemCiphertext); if (scError != SYMCRYPT_NO_ERROR) { @@ -285,20 +294,26 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, // // Decapsulation // + +// Unlike encapsulation, we initialize the classic key context for hybrid here, +// since ctx->keyCtx->classicKeyCtx contains our private key. The peer key is +// extracted from the public data passed to decapsulate. static SCOSSL_STATUS p_scossl_mlkem_decapsulate_init(_Inout_ SCOSSL_MLKEM_CTX *ctx, _In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, ossl_unused const OSSL_PARAM params[]) { return p_scossl_mlkem_init(ctx, keyCtx, EVP_PKEY_OP_DECAPSULATE) && - p_scossl_mlkem_classic_keyexch_init(ctx, ctx->keyCtx->classicKeyCtx); + (keyCtx->classicKeyCtx == NULL || p_scossl_mlkem_classic_keyexch_init(ctx, ctx->keyCtx->classicKeyCtx)); } // Performs ML-KEM decapsulation using the previously initialized context. If // this is a hybrid group, then hybrid decapsulation is performed. -// ctx->keyCtx->classicKeyCtx is used as 'our' key, and the peer key is -// extracted from the beginning of 'in' +// ctx->keyCtx->classicKeyCtx is used as our key, and the peer key is +// extracted from the beginning of 'in'. The concatenated +// order of classic and ML-KEM data depends on the classic group. // -// in == Ephemeral ECDH public key | MLKEM ciphertext -// out == ECDH shared secret | MLKEM secret +// - out +// X25519: MLKEM shared secret || ECDH shared secret +// P-256/P-384: ECDH shared secret || MLKEM shared secret static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, _Out_writes_bytes_opt_(*outlen) unsigned char *out, _Out_ size_t *outlen, _In_reads_bytes_(inlen) const unsigned char *in, size_t inlen) @@ -312,6 +327,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, SIZE_T cbClassicSecret = 0; SCOSSL_ECC_KEY_CTX *classicKeyCtxPeer = NULL; SCOSSL_ECC_KEY_CTX *classicKeyCtxPrivate = NULL; + const SCOSSL_MLKEM_GROUP_INFO *groupInfo; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -327,11 +343,11 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, goto cleanup; } - classicKeyCtxPrivate = ctx->keyCtx->classicKeyCtx; + groupInfo = ctx->keyCtx->groupInfo; - if (ctx->keyCtx->classicGroupName != NULL) + if (groupInfo->classicGroupName != NULL) { - if (classicKeyCtxPrivate == NULL) + if ((classicKeyCtxPrivate = ctx->keyCtx->classicKeyCtx) == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); goto cleanup; @@ -347,7 +363,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, } } - scError = SymCryptMlKemSizeofCiphertextFromParams(ctx->keyCtx->mlkemParams, &cbMlkemCiphertext); + scError = SymCryptMlKemSizeofCiphertextFromParams(groupInfo->mlkemParams, &cbMlkemCiphertext); if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); @@ -368,7 +384,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, goto cleanup; } - if (ctx->keyCtx->classicGroupName != NULL) + if (groupInfo->classicGroupName != NULL) { if (classicKeyCtxPrivate->isX25519) { @@ -392,7 +408,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, goto cleanup; } - if (p_scossl_ecc_set_group(classicKeyCtxPeer, ctx->keyCtx->classicGroupName) != SCOSSL_SUCCESS || + if (p_scossl_ecc_set_group(classicKeyCtxPeer, groupInfo->classicGroupName) != SCOSSL_SUCCESS || p_scossl_ecc_set_encoded_key(classicKeyCtxPeer, pbClassicKey, cbClassicKey, NULL, 0) != SCOSSL_SUCCESS) { goto cleanup; @@ -400,11 +416,16 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, // Derive shared ECDH secret if (p_scossl_ecdh_set_peer(ctx->classicKeyexchCtx, classicKeyCtxPeer) != SCOSSL_SUCCESS || - p_scossl_ecdh_derive(ctx->classicKeyexchCtx, pbClassicSecret, &cbClassicSecret, *outlen - SYMCRYPT_MLKEM_SECRET_LENGTH) != SCOSSL_SUCCESS) + p_scossl_ecdh_derive(ctx->classicKeyexchCtx, pbClassicSecret, &cbClassicSecret, cbClassicSecret) != SCOSSL_SUCCESS) { goto cleanup; } } + else + { + pbMlkemCipherText = in; + pbMlkemSecret = out; + } scError = SymCryptMlKemDecapsulate(ctx->keyCtx->key, pbMlkemCipherText, cbMlkemCiphertext, pbMlkemSecret, SYMCRYPT_MLKEM_SECRET_LENGTH); if (scError != SYMCRYPT_NO_ERROR) @@ -464,16 +485,35 @@ const OSSL_DISPATCH p_scossl_mlkem_functions[] = { {OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_mlkem_ctx_param_types}, {0, NULL}}; +_Use_decl_annotations_ +SCOSSL_MLKEM_GROUP_INFO *p_scossl_mlkem_get_group_info_by_nid(int nid) +{ + for (SIZE_T i = 0; i < sizeof(p_scossl_mlkem_groups) / sizeof(SCOSSL_MLKEM_GROUP_INFO); i++) + { + if (p_scossl_mlkem_groups[i].nid == nid) + { + return &p_scossl_mlkem_groups[i]; + } + } + + return NULL; +} + +_Use_decl_annotations_ +SCOSSL_MLKEM_GROUP_INFO *p_scossl_mlkem_get_group_info(_In_ const char *groupName) +{ + return p_scossl_mlkem_get_group_info_by_nid(OBJ_sn2nid(groupName)); +} + SCOSSL_STATUS p_scossl_mlkem_register_algorithms() { - if (OBJ_create(SCOSSL_OID_MLKEM512, SCOSSL_SN_MLKEM512, SCOSSL_SN_MLKEM512) == NID_undef || - OBJ_create(SCOSSL_OID_MLKEM768, SCOSSL_SN_MLKEM768, SCOSSL_SN_MLKEM768) == NID_undef || - OBJ_create(SCOSSL_OID_MLKEM1024, SCOSSL_SN_MLKEM1024, SCOSSL_SN_MLKEM1024) == NID_undef || - OBJ_create(SCOSSL_OID_P256_MLKEM768, SCOSSL_SN_P256_MLKEM768, SCOSSL_SN_P256_MLKEM768) == NID_undef || - OBJ_create(SCOSSL_OID_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768, SCOSSL_SN_X25519_MLKEM768) == NID_undef || - OBJ_create(SCOSSL_OID_P384_MLKEM1024, SCOSSL_SN_P384_MLKEM1024, SCOSSL_SN_P384_MLKEM1024) == NID_undef) + for (SIZE_T i = 0; i < sizeof(p_scossl_mlkem_groups) / sizeof(SCOSSL_MLKEM_GROUP_INFO); i++) { - return SCOSSL_FAILURE; + p_scossl_mlkem_groups[i].nid = OBJ_create(p_scossl_mlkem_groups[i].oid, p_scossl_mlkem_groups[i].groupName, p_scossl_mlkem_groups[i].groupName); + if (p_scossl_mlkem_groups[i].nid == NID_undef) + { + return SCOSSL_FAILURE; + } } return SCOSSL_SUCCESS; diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.h b/SymCryptProvider/src/kem/p_scossl_mlkem.h index c6a227f0..3b6dcbb2 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.h +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.h @@ -9,19 +9,27 @@ extern "C" { #endif +typedef struct { + int nid; + const char *oid; + const char *groupName; + const char *classicGroupName; + SYMCRYPT_MLKEM_PARAMS mlkemParams; +} SCOSSL_MLKEM_GROUP_INFO; + typedef struct { SCOSSL_PROVCTX *provCtx; - const char *groupName; + const SCOSSL_MLKEM_GROUP_INFO *groupInfo; PSYMCRYPT_MLKEMKEY key; - SYMCRYPT_MLKEM_PARAMS mlkemParams; SYMCRYPT_MLKEMKEY_FORMAT format; - const char *classicGroupName; SCOSSL_ECC_KEY_CTX *classicKeyCtx; } SCOSSL_MLKEM_KEY_CTX; SCOSSL_STATUS p_scossl_mlkem_register_algorithms(); +SCOSSL_MLKEM_GROUP_INFO *p_scossl_mlkem_get_group_info_by_nid(int nid); +SCOSSL_MLKEM_GROUP_INFO *p_scossl_mlkem_get_group_info(_In_ const char *groupName); #ifdef __cplusplus } diff --git a/SymCryptProvider/src/keyexch/p_scossl_ecdh.c b/SymCryptProvider/src/keyexch/p_scossl_ecdh.c index f539b467..1139eebb 100644 --- a/SymCryptProvider/src/keyexch/p_scossl_ecdh.c +++ b/SymCryptProvider/src/keyexch/p_scossl_ecdh.c @@ -4,7 +4,7 @@ #include "p_scossl_ecc.h" #include "p_scossl_base.h" -#include "keyexch/p_scossl_ecdh.h" +#include "p_scossl_ecdh.h" #include diff --git a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c index 158165b7..ee9398ff 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c @@ -4,7 +4,7 @@ #include "scossl_ecc.h" #include "p_scossl_ecc.h" -#include "keymgmt/p_scossl_ecc_impexp_types.h" +#include "p_scossl_ecc_keymgmt.h" #include #include diff --git a/SymCryptProvider/src/keymgmt/p_scossl_ecc_impexp_types.h b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.h similarity index 98% rename from SymCryptProvider/src/keymgmt/p_scossl_ecc_impexp_types.h rename to SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.h index 3e6ccd16..508281db 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_ecc_impexp_types.h +++ b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.h @@ -144,7 +144,7 @@ static const OSSL_PARAM p_scossl_ecc_impexp_types_0x0f[] = { SCOSSL_ECC_IMPEXP_OTHER_PARAMS OSSL_PARAM_END}; -const OSSL_PARAM *p_scossl_ecc_keymgmt_impexp_param_types[] = { +static const OSSL_PARAM *p_scossl_ecc_keymgmt_impexp_param_types[] = { NULL, p_scossl_ecc_impexp_types_0x01, p_scossl_ecc_impexp_types_0x02, diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index 6da4c0b3..ebdb012a 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -3,8 +3,7 @@ // #include "scossl_provider.h" -#include "kem/p_scossl_mlkem.h" -#include "keymgmt/p_scossl_mlkem_keymgmt.h" +#include "p_scossl_mlkem_keymgmt.h" #include #include @@ -14,6 +13,12 @@ extern "C" { #endif +typedef struct { + SCOSSL_PROVCTX *provCtx; + + const SCOSSL_MLKEM_GROUP_INFO *groupInfo; +} SCOSSL_MLKEM_KEYGEN_CTX; + #define SCOSSL_MLKEM_PKEY_PARAMETER_TYPES \ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), \ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \ @@ -34,7 +39,6 @@ static const OSSL_PARAM p_scossl_mlkem_keymgmt_gettable_param_types[] = { SCOSSL_MLKEM_PKEY_PARAMETER_TYPES OSSL_PARAM_END}; -// Import/export types static const OSSL_PARAM p_scossl_mlkem_param_types[] = { OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), OSSL_PARAM_END}; @@ -79,7 +83,6 @@ void p_scossl_mlkem_keymgmt_free_key_ctx(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx) } p_scossl_ecc_free_ctx(keyCtx->classicKeyCtx); - OPENSSL_free(keyCtx); } @@ -88,7 +91,7 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS PBYTE pbKey = NULL; SIZE_T cbKey = 0; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; - SCOSSL_STATUS ret = SCOSSL_FAILURE; + SCOSSL_STATUS status = SCOSSL_FAILURE; SCOSSL_MLKEM_KEY_CTX *copyCtx = OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_KEY_CTX)); if (copyCtx != NULL) @@ -97,61 +100,61 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { - copyCtx->groupName = keyCtx->groupName; - copyCtx->mlkemParams = keyCtx->mlkemParams; - copyCtx->classicGroupName = keyCtx->classicGroupName; + copyCtx->groupInfo = keyCtx->groupInfo; } - if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 && keyCtx->key != NULL) + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { - if (copyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) + if (keyCtx->key != NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); - goto cleanup; - } + if (copyCtx->groupInfo == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); + goto cleanup; + } - scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->mlkemParams, keyCtx->format, &cbKey); - if (scError != SYMCRYPT_NO_ERROR) - { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - goto cleanup; - } + scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->groupInfo->mlkemParams, keyCtx->format, &cbKey); + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } - if ((copyCtx->key = SymCryptMlKemkeyAllocate(copyCtx->mlkemParams)) == NULL || - (pbKey = OPENSSL_secure_malloc(cbKey)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } + if ((copyCtx->key = SymCryptMlKemkeyAllocate(copyCtx->groupInfo->mlkemParams)) == NULL || + (pbKey = OPENSSL_secure_malloc(cbKey)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } - scError = SymCryptMlKemkeyGetValue(keyCtx->key, pbKey, cbKey, keyCtx->format, 0); - if (scError != SYMCRYPT_NO_ERROR) - { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - goto cleanup; + scError = SymCryptMlKemkeyGetValue(keyCtx->key, pbKey, cbKey, keyCtx->format, 0); + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + scError = SymCryptMlKemkeySetValue(pbKey, cbKey, keyCtx->format, 0, copyCtx->key); + if (scError != SYMCRYPT_NO_ERROR) + { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + goto cleanup; + } + + copyCtx->format = keyCtx->format; } - scError = SymCryptMlKemkeySetValue(pbKey, cbKey, keyCtx->format, 0, copyCtx->key); - if (scError != SYMCRYPT_NO_ERROR) + if (keyCtx->classicKeyCtx != NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - goto cleanup; + copyCtx->classicKeyCtx = p_scossl_ecc_dup_ctx(keyCtx->classicKeyCtx, selection); } - - copyCtx->format = keyCtx->format; - } - - if (keyCtx->classicKeyCtx != NULL) - { - copyCtx->classicKeyCtx = p_scossl_ecc_dup_ctx(keyCtx->classicKeyCtx, selection); } } - ret = SCOSSL_SUCCESS; + status = SCOSSL_SUCCESS; cleanup: - - if (ret != SCOSSL_SUCCESS) + if (status != SCOSSL_SUCCESS) { p_scossl_mlkem_keymgmt_free_key_ctx(copyCtx); copyCtx = NULL; @@ -162,7 +165,7 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS return copyCtx; } -static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEY_CTX *genCtx, _In_ const OSSL_PARAM params[]) +static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ const OSSL_PARAM params[]) { const OSSL_PARAM *p; if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL) @@ -175,7 +178,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keygen_set_params(_Inout_ SCOSSL_MLKEM_KEY_C return SCOSSL_FAILURE; } - if (p_scossl_mlkem_keymgmt_set_group(genCtx, groupName) != SCOSSL_SUCCESS) + if ((genCtx->groupInfo = p_scossl_mlkem_get_group_info(groupName)) == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); return SCOSSL_FAILURE; @@ -190,63 +193,70 @@ static const OSSL_PARAM *p_scossl_mlkem_keygen_settable_params(ossl_unused void return p_scossl_mlkem_keygen_settable_param_types; } -static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen_init(_In_ SCOSSL_PROVCTX *provCtx, ossl_unused int selection, +static void p_scossl_mlkem_keygen_cleanup(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx) +{ + OPENSSL_free(genCtx); +} + +static SCOSSL_MLKEM_KEYGEN_CTX *p_scossl_mlkem_keygen_init(_In_ SCOSSL_PROVCTX *provCtx, ossl_unused int selection, _In_ const OSSL_PARAM params[]) { SCOSSL_STATUS status = SCOSSL_FAILURE; - SCOSSL_MLKEM_KEY_CTX *genCtx = p_scossl_mlkem_keymgmt_new_ctx(provCtx); + SCOSSL_MLKEM_KEYGEN_CTX *genCtx = OPENSSL_zalloc(sizeof(SCOSSL_MLKEM_KEYGEN_CTX)); if (genCtx != NULL) { + genCtx->provCtx = provCtx; status = p_scossl_mlkem_keygen_set_params(genCtx, params); - if (status == SCOSSL_SUCCESS && genCtx->groupName == NULL) + if (status == SCOSSL_SUCCESS && genCtx->groupInfo == NULL) { - status = p_scossl_mlkem_keymgmt_set_group(genCtx, SCOSSL_SN_MLKEM768); + genCtx->groupInfo = p_scossl_mlkem_get_group_info(SCOSSL_SN_MLKEM768); } } if (status != SCOSSL_SUCCESS) { - p_scossl_mlkem_keymgmt_free_key_ctx(genCtx); + p_scossl_mlkem_keygen_cleanup(genCtx); genCtx = NULL; } return genCtx; } -static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEY_CTX *genCtx, _In_ SCOSSL_MLKEM_KEY_CTX *tmplCtx) +static SCOSSL_STATUS p_scossl_mlkem_keygen_set_template(_Inout_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, _In_ SCOSSL_MLKEM_KEY_CTX *tmplCtx) { - if (genCtx == NULL || - tmplCtx == NULL) + if (genCtx == NULL || tmplCtx == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); return SCOSSL_FAILURE; } - if (tmplCtx->groupName == NULL) + if (tmplCtx->groupInfo == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); return SCOSSL_FAILURE; } - if (p_scossl_mlkem_keymgmt_set_group(genCtx, tmplCtx->groupName) != SCOSSL_SUCCESS) - { - ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); - return SCOSSL_FAILURE; - } + genCtx->groupInfo = tmplCtx->groupInfo; return SCOSSL_SUCCESS; } -static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEY_CTX *genCtx, ossl_unused OSSL_CALLBACK *cb, ossl_unused void *cbarg) +static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX *genCtx, ossl_unused OSSL_CALLBACK *cb, ossl_unused void *cbarg) { SCOSSL_MLKEM_KEY_CTX *keyCtx; SCOSSL_STATUS status = SCOSSL_FAILURE; SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; - if ((keyCtx = p_scossl_mlkem_keymgmt_dup_key_ctx(genCtx, OSSL_KEYMGMT_SELECT_ALL)) == NULL || - (keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->mlkemParams)) == NULL) + if (genCtx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if ((keyCtx = p_scossl_mlkem_keymgmt_new_ctx(genCtx->provCtx)) == NULL || + (keyCtx->key = SymCryptMlKemkeyAllocate(genCtx->groupInfo->mlkemParams)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; @@ -259,7 +269,7 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEY_CTX *ge goto cleanup; } - if (keyCtx->classicGroupName != NULL) + if (genCtx->groupInfo->classicGroupName != NULL) { if ((keyCtx->classicKeyCtx = p_scossl_ecc_new_ctx(keyCtx->provCtx)) == NULL) { @@ -267,14 +277,16 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEY_CTX *ge goto cleanup; } - if (p_scossl_ecc_set_group(keyCtx->classicKeyCtx, keyCtx->classicGroupName) != SCOSSL_SUCCESS || + if (p_scossl_ecc_set_group(keyCtx->classicKeyCtx, genCtx->groupInfo->classicGroupName) != SCOSSL_SUCCESS || p_scossl_ecc_gen(keyCtx->classicKeyCtx) != SCOSSL_SUCCESS) { goto cleanup; } } - keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; + keyCtx->provCtx = genCtx->provCtx; + keyCtx->groupInfo = genCtx->groupInfo; + keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED; status = SCOSSL_SUCCESS; @@ -424,7 +436,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; OSSL_PARAM *p; - if (keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) + if (keyCtx->groupInfo == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); return SCOSSL_FAILURE; @@ -448,7 +460,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX format = SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY; } - scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->mlkemParams, format, &cbMax); + scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->groupInfo->mlkemParams, format, &cbMax); if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); @@ -468,7 +480,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX } if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL && - !OSSL_PARAM_set_utf8_string(p, keyCtx->groupName != NULL ? keyCtx->groupName : "")) + !OSSL_PARAM_set_utf8_string(p, keyCtx->groupInfo->groupName != NULL ? keyCtx->groupInfo->groupName : "")) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); return SCOSSL_FAILURE; @@ -485,7 +497,7 @@ static BOOL p_scossl_mlkem_keymgmt_has(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int se } if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0 && - keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) + keyCtx->groupInfo == NULL) { return FALSE; } @@ -497,6 +509,7 @@ static BOOL p_scossl_mlkem_keymgmt_has(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int se } if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && + keyCtx->format != SYMCRYPT_MLKEMKEY_FORMAT_PRIVATE_SEED && keyCtx->format != SYMCRYPT_MLKEMKEY_FORMAT_DECAPSULATION_KEY) { return FALSE; @@ -516,7 +529,7 @@ static BOOL p_scossl_mlkem_keymgmt_match(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx1, _In SCOSSL_STATUS success; if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0 && - keyCtx1->mlkemParams != keyCtx2->mlkemParams) + keyCtx1->groupInfo != keyCtx2->groupInfo) { goto cleanup; } @@ -623,7 +636,6 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx const OSSL_PARAM *p; PCBYTE pbKey; SIZE_T cbKey; - const char *classicGroupName = NULL; // Domain parameters are required for import if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0) @@ -641,14 +653,15 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx return SCOSSL_FAILURE; } - if (p_scossl_mlkem_keymgmt_set_group(keyCtx, keyCtx->groupName) != SCOSSL_SUCCESS) + if ((keyCtx->groupInfo = p_scossl_mlkem_get_group_info(groupName)) == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); return SCOSSL_FAILURE; } - if (classicGroupName != NULL && - p_scossl_ecc_set_group(keyCtx->classicKeyCtx, classicGroupName) != SCOSSL_SUCCESS) + if (keyCtx->classicKeyCtx != NULL && + keyCtx->groupInfo->classicGroupName != NULL && + p_scossl_ecc_set_group(keyCtx->classicKeyCtx, keyCtx->groupInfo->classicGroupName) != SCOSSL_SUCCESS) { return SCOSSL_FAILURE; } @@ -712,7 +725,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, i goto cleanup; } - if (keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) + if (keyCtx->groupInfo == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); goto cleanup; @@ -731,7 +744,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, i goto cleanup; } - mlkemParamsName = keyCtx->groupName != NULL ? keyCtx->groupName : ""; + mlkemParamsName = keyCtx->groupInfo->groupName != NULL ? keyCtx->groupInfo->groupName : ""; if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, mlkemParamsName, strlen(mlkemParamsName))) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); @@ -801,7 +814,7 @@ const OSSL_DISPATCH p_scossl_mlkem_keymgmt_functions[] = { {OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))p_scossl_mlkem_keymgmt_free_key_ctx}, {OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))p_scossl_mlkem_keygen_set_params}, {OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (void (*)(void))p_scossl_mlkem_keygen_settable_params}, - {OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))p_scossl_mlkem_keymgmt_free_key_ctx}, + {OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))p_scossl_mlkem_keygen_cleanup}, {OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))p_scossl_mlkem_keygen_init}, {OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))p_scossl_mlkem_keygen_set_template}, {OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))p_scossl_mlkem_keygen}, @@ -835,7 +848,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; - if (keyCtx->key == NULL || keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) + if (keyCtx->key == NULL || keyCtx->groupInfo == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); return SCOSSL_FAILURE; @@ -857,7 +870,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; } - scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->mlkemParams, format, &cbMlKemKey); + scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->groupInfo->mlkemParams, format, &cbMlKemKey); if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); @@ -930,20 +943,20 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; - if (keyCtx->mlkemParams == SYMCRYPT_MLKEM_PARAMS_NULL) + if (keyCtx->groupInfo == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); goto cleanup; } if (keyCtx->key == NULL && - (keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->mlkemParams)) == NULL) + (keyCtx->key = SymCryptMlKemkeyAllocate(keyCtx->groupInfo->mlkemParams)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto cleanup; } - if (keyCtx->classicGroupName != NULL) + if (keyCtx->groupInfo->classicGroupName != NULL) { if (keyCtx->classicKeyCtx == NULL && (keyCtx->classicKeyCtx = p_scossl_ecc_new_ctx(keyCtx->provCtx)) == NULL) @@ -951,7 +964,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt goto cleanup; } - if (p_scossl_ecc_set_group(keyCtx->classicKeyCtx, keyCtx->classicGroupName) != SCOSSL_SUCCESS || + if (p_scossl_ecc_set_group(keyCtx->classicKeyCtx, keyCtx->groupInfo->classicGroupName) != SCOSSL_SUCCESS || (cbClassicKey = p_scossl_ecc_get_encoded_key_size(keyCtx->classicKeyCtx, selection)) == 0) { goto cleanup; @@ -967,7 +980,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt keyCtx->format = SYMCRYPT_MLKEMKEY_FORMAT_ENCAPSULATION_KEY; } - scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->mlkemParams, keyCtx->format, &cbMlKemKey); + scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->groupInfo->mlkemParams, keyCtx->format, &cbMlKemKey); if (scError != SYMCRYPT_NO_ERROR) { ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); @@ -1029,71 +1042,25 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt return ret; } - -_Use_decl_annotations_ -SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_group(SCOSSL_MLKEM_KEY_CTX *keyCtx, const char *groupName) -{ - if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM512) == 0) - { - keyCtx->groupName = SCOSSL_SN_MLKEM512; - keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM512; - keyCtx->classicGroupName = NULL; - } - else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM768) == 0) - { - keyCtx->groupName = SCOSSL_SN_MLKEM768; - keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; - keyCtx->classicGroupName = NULL; - } - else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_MLKEM1024) == 0) - { - keyCtx->groupName = SCOSSL_SN_MLKEM1024; - keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM1024; - keyCtx->classicGroupName = NULL; - } - else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_P256_MLKEM768) == 0) - { - keyCtx->groupName = SCOSSL_SN_P256_MLKEM768; - keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; - keyCtx->classicGroupName = SN_X9_62_prime256v1; - } - else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_X25519_MLKEM768) == 0) - { - keyCtx->groupName = SCOSSL_SN_X25519_MLKEM768; - keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM768; - keyCtx->classicGroupName = SN_X25519; - } - else if (OPENSSL_strcasecmp(groupName, SCOSSL_SN_P384_MLKEM1024) == 0) - { - keyCtx->groupName = SCOSSL_SN_P384_MLKEM1024; - keyCtx->mlkemParams = SYMCRYPT_MLKEM_PARAMS_MLKEM1024; - keyCtx->classicGroupName = SN_secp384r1; - } - else - { - ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); - return SCOSSL_FAILURE; - } - - return SCOSSL_SUCCESS; -} - _Use_decl_annotations_ static int p_scossl_mlkem_keymgmt_get_security_bits(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx) { - switch(keyCtx->mlkemParams) - { - case SYMCRYPT_MLKEM_PARAMS_MLKEM512: - return 128; - case SYMCRYPT_MLKEM_PARAMS_MLKEM768: - return 192; - case SYMCRYPT_MLKEM_PARAMS_MLKEM1024: - return 256; - default: - ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); - break; + if (keyCtx->groupInfo != NULL) + { + switch(keyCtx->groupInfo->mlkemParams) + { + case SYMCRYPT_MLKEM_PARAMS_MLKEM512: + return 128; + case SYMCRYPT_MLKEM_PARAMS_MLKEM768: + return 192; + case SYMCRYPT_MLKEM_PARAMS_MLKEM1024: + return 256; + default: + break; + } } + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); return 0; } diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h index bd88f7d5..ce453da3 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.h @@ -2,7 +2,10 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // +#pragma once + #include "p_scossl_base.h" +#include "kem/p_scossl_mlkem.h" #ifdef __cplusplus extern "C" { @@ -15,14 +18,11 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_import(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx SCOSSL_STATUS p_scossl_mlkem_keymgmt_export(_In_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg); -SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_group(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, _In_ const char *groupName); - SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(_In_ const SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, _Out_writes_bytes_(*pcbKey) PBYTE *ppbKey, _Out_ SIZE_T *pcbKey); SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(_Inout_ SCOSSL_MLKEM_KEY_CTX *keyCtx, int selection, _In_reads_bytes_(cbKey) PCBYTE pbKey, SIZE_T cbKey); - #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index ab4f2c6b..ec648d6b 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -10,7 +10,6 @@ #include "scossl_ecc.h" #include "scossl_provider.h" #include "p_scossl_bio.h" -#include "p_scossl_keysinuse.h" #include "p_scossl_names.h" #include "kem/p_scossl_mlkem.h" @@ -697,7 +696,15 @@ SCOSSL_STATUS OSSL_provider_init(_In_ const OSSL_CORE_HANDLE *handle, _Out_ const OSSL_DISPATCH **out, _Out_ void **provctx) { - SCOSSL_PROVCTX *p_ctx = NULL; + SCOSSL_PROVCTX *p_ctx = OPENSSL_malloc(sizeof(SCOSSL_PROVCTX)); + if (p_ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return SCOSSL_FAILURE; + } + + p_ctx->handle = handle; + p_ctx->libctx = OSSL_LIB_CTX_new_child(handle, in); p_scossl_set_core_bio(in); if ((p_ctx->coreBioMeth = p_scossl_bio_init()) == NULL) @@ -731,15 +738,6 @@ SCOSSL_STATUS OSSL_provider_init(_In_ const OSSL_CORE_HANDLE *handle, scossl_prov_initialized = 1; } - p_ctx = OPENSSL_malloc(sizeof(SCOSSL_PROVCTX)); - if (p_ctx == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return SCOSSL_FAILURE; - } - - p_ctx->handle = handle; - p_ctx->libctx = OSSL_LIB_CTX_new_child(handle, in); *provctx = p_ctx; *out = p_scossl_base_dispatch; diff --git a/SymCryptProvider/src/p_scossl_names.h b/SymCryptProvider/src/p_scossl_names.h index 25dbd963..777967da 100644 --- a/SymCryptProvider/src/p_scossl_names.h +++ b/SymCryptProvider/src/p_scossl_names.h @@ -13,7 +13,6 @@ extern "C" { // // Digests - #define SCOSSL_ALG_NAME_MD5 SN_md5"SSL3-MD5:1.2.840.113549.2.5" #define SCOSSL_ALG_NAME_SHA1 SN_sha1"SHA-1:SSL3-SHA1:1.3.14.3.2.26" #define SCOSSL_ALG_NAME_SHA224 SN_sha224"SHA2-224:SHA-224:2.16.840.1.101.3.4.2.4" @@ -86,7 +85,13 @@ extern "C" { // Key encapsulation #define SCOSSL_ALG_NAME_MLKEM "MLKEM" -#define SCOSSL_ALG_NAME_MLKEM_DECODER SCOSSL_ALG_NAME_MLKEM":"SCOSSL_SN_MLKEM512":"SCOSSL_OID_MLKEM512":"SCOSSL_SN_MLKEM768":"SCOSSL_OID_MLKEM768":"SCOSSL_SN_MLKEM1024":"SCOSSL_OID_MLKEM1024 +#define SCOSSL_ALG_NAME_MLKEM_DECODER SCOSSL_ALG_NAME_MLKEM":" \ + SCOSSL_SN_MLKEM512":" \ + SCOSSL_OID_MLKEM512":" \ + SCOSSL_SN_MLKEM768":" \ + SCOSSL_OID_MLKEM768":" \ + SCOSSL_SN_MLKEM1024":" \ + SCOSSL_OID_MLKEM1024 #ifdef __cplusplus } From bb3e09b9f7af3d32bcfc1108ab170cf5fa44381f Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Mon, 30 Dec 2024 22:56:28 +0000 Subject: [PATCH 20/21] Fix TLS names --- SymCryptProvider/inc/scossl_provider.h | 2 +- SymCryptProvider/src/p_scossl_base.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SymCryptProvider/inc/scossl_provider.h b/SymCryptProvider/inc/scossl_provider.h index 594f786a..79ec559b 100644 --- a/SymCryptProvider/inc/scossl_provider.h +++ b/SymCryptProvider/inc/scossl_provider.h @@ -43,7 +43,7 @@ extern "C" { #define SCOSSL_SN_MLKEM1024 "mlkem1024" #define SCOSSL_OID_MLKEM1024 "2.16.840.1.101.3.4.4.3" -#define SCOSSL_SN_P256_MLKEM768 SN_X9_62_prime256v1 SCOSSL_SN_MLKEM768 +#define SCOSSL_SN_P256_MLKEM768 "secp256r1"SCOSSL_SN_MLKEM768 #define SCOSSL_OID_P256_MLKEM768 "2.16.840.1.101.3.4.4.4" #define SCOSSL_SN_X25519_MLKEM768 SN_X25519 SCOSSL_SN_MLKEM768 diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index ec648d6b..ac5d2686 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -203,7 +203,7 @@ static const OSSL_PARAM p_scossl_supported_group_list[][11] = { TLS_GROUP_ENTRY("mlkem1024", SCOSSL_SN_MLKEM1024, "MLKEM", scossl_tls_group_info_mlkem1024), TLS_GROUP_ENTRY("secp256r1mlkem768", SCOSSL_SN_P256_MLKEM768, "MLKEM", scossl_tls_group_info_secp256r1mlkem768), TLS_GROUP_ENTRY("P256mlkem768", SCOSSL_SN_P256_MLKEM768, "MLKEM", scossl_tls_group_info_secp256r1mlkem768), - TLS_GROUP_ENTRY("x25519mlkem768", SCOSSL_SN_X25519_MLKEM768, "MLKEM", scossl_tls_group_info_x25519mlkem768), + TLS_GROUP_ENTRY("X25519mlkem768", SCOSSL_SN_X25519_MLKEM768, "MLKEM", scossl_tls_group_info_x25519mlkem768), TLS_GROUP_ENTRY("secp384r1mlkem1024", SCOSSL_SN_P384_MLKEM1024, "MLKEM", scossl_tls_group_info_secp384r1mlkem1024), TLS_GROUP_ENTRY("P384mlkem1024", SCOSSL_SN_P384_MLKEM1024, "MLKEM", scossl_tls_group_info_secp384r1mlkem1024)}; From 3b662e7f6b3b2ab6fbbf98aeff9b6e0ad43d2bef Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Fri, 17 Jan 2025 20:28:20 +0000 Subject: [PATCH 21/21] Use new debug logging for symcrypt errors --- .../src/encoder/p_scossl_encode_mlkem.c | 4 +-- SymCryptProvider/src/kem/p_scossl_mlkem.c | 8 +++--- .../src/keymgmt/p_scossl_ecc_keymgmt.c | 2 -- .../src/keymgmt/p_scossl_mlkem_keymgmt.c | 28 +++++++++---------- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c index da7ab981..8c9f7e9f 100644 --- a/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c +++ b/SymCryptProvider/src/encoder/p_scossl_encode_mlkem.c @@ -59,7 +59,7 @@ static PKCS8_PRIV_KEY_INFO *p_scossl_mlkem_key_to_p8info(_In_ const SCOSSL_MLKEM if ((p8Obj = p_scossl_encode_mlkem_get_oid(keyCtx)) == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_ERROR(ERR_R_INTERNAL_ERROR, "p_scossl_encode_mlkem_get_oid returned NULL"); goto cleanup; } @@ -113,7 +113,7 @@ static X509_PUBKEY *p_scossl_mlkem_key_to_pubkey(_In_ const SCOSSL_MLKEM_KEY_CTX if ((p8Obj = p_scossl_encode_mlkem_get_oid(keyCtx)) == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_ERROR(ERR_R_INTERNAL_ERROR, "p_scossl_encode_mlkem_get_oid returned NULL"); goto cleanup; } diff --git a/SymCryptProvider/src/kem/p_scossl_mlkem.c b/SymCryptProvider/src/kem/p_scossl_mlkem.c index 616bf303..efb2642c 100644 --- a/SymCryptProvider/src/kem/p_scossl_mlkem.c +++ b/SymCryptProvider/src/kem/p_scossl_mlkem.c @@ -197,7 +197,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, scError = SymCryptMlKemSizeofCiphertextFromParams(groupInfo->mlkemParams, &cbMlkemCiphertext); if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptMlKemSizeofCiphertextFromParams failed", scError); goto cleanup; } @@ -263,7 +263,7 @@ static SCOSSL_STATUS p_scossl_mlkem_encapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, scError = SymCryptMlKemEncapsulate(ctx->keyCtx->key, pbMlkemSecret, SYMCRYPT_MLKEM_SECRET_LENGTH, pbMlkemCipherText, cbMlkemCiphertext); if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptMlKemEncapsulate failed", scError); goto cleanup; } } @@ -366,7 +366,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, scError = SymCryptMlKemSizeofCiphertextFromParams(groupInfo->mlkemParams, &cbMlkemCiphertext); if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptMlKemSizeofCiphertextFromParams failed", scError); goto cleanup; } @@ -430,7 +430,7 @@ static SCOSSL_STATUS p_scossl_mlkem_decapsulate(_In_ SCOSSL_MLKEM_CTX *ctx, scError = SymCryptMlKemDecapsulate(ctx->keyCtx->key, pbMlkemCipherText, cbMlkemCiphertext, pbMlkemSecret, SYMCRYPT_MLKEM_SECRET_LENGTH); if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptMlKemDecapsulate failed", scError); goto cleanup; } } diff --git a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c index ee9398ff..743dd932 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c @@ -959,10 +959,8 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *key keyCtx, pbPublicKey, cbPublicKey, pbPrivateKey, cbPrivateKey); - if (ret != SCOSSL_SUCCESS) { - SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeySetValue failed", scError); goto cleanup; } diff --git a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c index ebdb012a..b12a78aa 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_mlkem_keymgmt.c @@ -116,7 +116,7 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->groupInfo->mlkemParams, keyCtx->format, &cbKey); if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptMlKemSizeofKeyFormatFromParams failed", scError); goto cleanup; } @@ -130,14 +130,14 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keymgmt_dup_key_ctx(_In_ const SCOSS scError = SymCryptMlKemkeyGetValue(keyCtx->key, pbKey, cbKey, keyCtx->format, 0); if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptMlKemkeyGetValue failed", scError); goto cleanup; } scError = SymCryptMlKemkeySetValue(pbKey, cbKey, keyCtx->format, 0, copyCtx->key); if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptMlKemkeySetValue failed", scError); goto cleanup; } @@ -265,7 +265,7 @@ static SCOSSL_MLKEM_KEY_CTX *p_scossl_mlkem_keygen(_In_ SCOSSL_MLKEM_KEYGEN_CTX scError = SymCryptMlKemkeyGenerate(keyCtx->key, 0); if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptMlKemkeyGenerate failed", scError); goto cleanup; } @@ -378,7 +378,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY &pbKey, &cbKey); if (status != SCOSSL_SUCCESS) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_ERROR(ERR_R_INTERNAL_ERROR, "Failed to get encoded public key"); goto cleanup; } @@ -412,7 +412,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_key_params(_In_ SCOSSL_MLKEM_KEY &pbKey, &cbKey); if (status != SCOSSL_SUCCESS) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_ERROR(ERR_R_INTERNAL_ERROR, "Failed to get encoded private key"); goto cleanup; } @@ -445,7 +445,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL && !OSSL_PARAM_set_int(p, p_scossl_mlkem_keymgmt_get_security_bits(keyCtx))) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); return SCOSSL_FAILURE; } @@ -463,7 +463,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->groupInfo->mlkemParams, format, &cbMax); if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptMlKemSizeofKeyFormatFromParams failed", scError); return SCOSSL_FAILURE; } @@ -474,7 +474,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX if (!OSSL_PARAM_set_size_t(p, cbMax)) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); return SCOSSL_FAILURE; } } @@ -482,7 +482,7 @@ static SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_params(_In_ SCOSSL_MLKEM_KEY_CTX if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL && !OSSL_PARAM_set_utf8_string(p, keyCtx->groupInfo->groupName != NULL ? keyCtx->groupInfo->groupName : "")) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); return SCOSSL_FAILURE; } @@ -873,7 +873,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->groupInfo->mlkemParams, format, &cbMlKemKey); if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptMlKemSizeofKeyFormatFromParams failed", scError); goto cleanup; } @@ -908,7 +908,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_get_encoded_key(const SCOSSL_MLKEM_KEY_CTX scError = SymCryptMlKemkeyGetValue(keyCtx->key, pbMlKemKey, cbMlKemKey, format, 0); if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptMlKemkeyGetValue failed", scError); goto cleanup; } @@ -983,7 +983,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt scError = SymCryptMlKemSizeofKeyFormatFromParams(keyCtx->groupInfo->mlkemParams, keyCtx->format, &cbMlKemKey); if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptMlKemSizeofKeyFormatFromParams failed", scError); goto cleanup; } @@ -1008,7 +1008,7 @@ SCOSSL_STATUS p_scossl_mlkem_keymgmt_set_encoded_key(SCOSSL_MLKEM_KEY_CTX *keyCt scError = SymCryptMlKemkeySetValue(pbMlKemKey, cbMlKemKey, keyCtx->format, 0, keyCtx->key); if (scError != SYMCRYPT_NO_ERROR) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptMlKemkeySetValue failed", scError); goto cleanup; }