diff --git a/SymCryptProvider/CMakeLists.txt b/SymCryptProvider/CMakeLists.txt index a529c165..18f7bb2c 100644 --- a/SymCryptProvider/CMakeLists.txt +++ b/SymCryptProvider/CMakeLists.txt @@ -11,7 +11,7 @@ configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/inc/p_scossl_base.h.in ${CMAKE_CURRENT_SOURCE_DIR}/inc/p_scossl_base.h) -find_package(OpenSSL REQUIRED) +find_package(OpenSSL 3.5 REQUIRED) include_directories(${OPENSSL_INCLUDE_DIR}) find_library(SYMCRYPT_LIBRARY symcrypt PATHS ${CMAKE_SOURCE_DIR}) @@ -52,6 +52,8 @@ set(SCOSSL_SOURCES ./src/mac/p_scossl_kmac.c ./src/signature/p_scossl_ecdsa_signature.c ./src/signature/p_scossl_rsa_signature.c + ./src/skeymgmt/p_scossl_aes_skeymgmt.c + ./src/skeymgmt/p_scossl_generic_skeymgmt.c ./src/p_scossl_bio.c ./src/p_scossl_ecc.c ./src/p_scossl_rand.c diff --git a/SymCryptProvider/src/ciphers/p_scossl_aes.c b/SymCryptProvider/src/ciphers/p_scossl_aes.c index c864a588..e56908c3 100644 --- a/SymCryptProvider/src/ciphers/p_scossl_aes.c +++ b/SymCryptProvider/src/ciphers/p_scossl_aes.c @@ -10,6 +10,7 @@ #include "scossl_helpers.h" #include "p_scossl_base.h" #include "p_scossl_aes.h" +#include "p_scossl_skey.h" #ifdef __cplusplus extern "C" { @@ -148,12 +149,26 @@ static SCOSSL_STATUS p_scossl_aes_generic_decrypt_init(_Inout_ SCOSSL_AES_CTX *c return p_scossl_aes_generic_init_internal(ctx, FALSE, key, keylen, iv, ivlen, params); } +static SCOSSL_STATUS p_scossl_aes_generic_skey_encrypt_init(_Inout_ SCOSSL_AES_CTX *ctx, _In_ SCOSSL_SKEY *skey, + _In_reads_bytes_opt_(ivlen) const unsigned char *iv, size_t ivlen, + _In_ const OSSL_PARAM params[]) +{ + return p_scossl_aes_generic_init_internal(ctx, TRUE, skey->pbKey, skey->cbKey, iv, ivlen, params); +} + +static SCOSSL_STATUS p_scossl_aes_generic_skey_decrypt_init(_Inout_ SCOSSL_AES_CTX *ctx, _In_ SCOSSL_SKEY *skey, + _In_reads_bytes_opt_(ivlen) const unsigned char *iv, size_t ivlen, + _In_ const OSSL_PARAM params[]) +{ + return p_scossl_aes_generic_init_internal(ctx, FALSE, skey->pbKey, skey->cbKey, iv, ivlen, params); +} + #define SYMCRYPT_OPENSSL_MASK8_SELECT( _mask, _a, _b ) (SYMCRYPT_FORCE_READ8(&_mask) & _a) | (~(SYMCRYPT_FORCE_READ8(&_mask)) & _b) // Verifies the TLS padding from the end of record, extracts the MAC from the end of -// the unpadded record, and saves the result to ctx->tlsMac. -// -// If ctx->tlsMacSize is 0 (in the case of encrypt-then-mac), no MAC is extracted, +// the unpadded record, and saves the result to ctx->tlsMac. +// +// If ctx->tlsMacSize is 0 (in the case of encrypt-then-mac), no MAC is extracted, // but the padding is still verified and removed. // // The MAC will later be fetched through p_scossl_aes_generic_get_ctx_params @@ -1028,6 +1043,8 @@ static SCOSSL_STATUS scossl_aes_cfb8_cipher(_Inout_ SCOSSL_AES_CTX *ctx, {OSSL_FUNC_CIPHER_GETTABLE_PARAMS, (void (*)(void))p_scossl_aes_generic_gettable_params}, \ {OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_aes_generic_gettable_ctx_params}, \ {OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_aes_generic_settable_ctx_params}, \ + {OSSL_FUNC_CIPHER_ENCRYPT_SKEY_INIT, (void (*)(void))p_scossl_aes_generic_skey_encrypt_init}, \ + {OSSL_FUNC_CIPHER_DECRYPT_SKEY_INIT, (void (*)(void))p_scossl_aes_generic_skey_decrypt_init}, \ {0, NULL}}; IMPLEMENT_SCOSSL_AES_GENERIC_CIPHER(128, SYMCRYPT_AES_BLOCK_SIZE, cbc, CBC, block, SYMCRYPT_AES_BLOCK_SIZE) diff --git a/SymCryptProvider/src/ciphers/p_scossl_aes_aead.c b/SymCryptProvider/src/ciphers/p_scossl_aes_aead.c index 531ba344..821f11ec 100644 --- a/SymCryptProvider/src/ciphers/p_scossl_aes_aead.c +++ b/SymCryptProvider/src/ciphers/p_scossl_aes_aead.c @@ -8,6 +8,7 @@ #include "scossl_aes_aead.h" #include "p_scossl_aes.h" +#include "p_scossl_skey.h" #ifdef __cplusplus extern "C" { @@ -115,6 +116,20 @@ static SCOSSL_STATUS p_scossl_aes_gcm_decrypt_init(_Inout_ SCOSSL_CIPHER_GCM_CTX return p_scossl_aes_gcm_init_internal(ctx, 0, key, keylen, iv, ivlen, params); } +static SCOSSL_STATUS p_scossl_aes_gcm_skey_encrypt_init(_Inout_ void *ctx, _In_ SCOSSL_SKEY *skey, + _In_reads_bytes_opt_(ivlen) const unsigned char *iv, size_t ivlen, + _In_ const OSSL_PARAM params[]) +{ + return p_scossl_aes_gcm_init_internal(ctx, 1, skey->pbKey, skey->cbKey, iv, ivlen, params); +} + +static SCOSSL_STATUS p_scossl_aes_gcm_skey_decrypt_init(_Inout_ void *ctx, _In_ SCOSSL_SKEY *skey, + _In_reads_bytes_opt_(ivlen) const unsigned char *iv, size_t ivlen, + _In_ const OSSL_PARAM params[]) +{ + return p_scossl_aes_gcm_init_internal(ctx, 0, skey->pbKey, skey->cbKey, iv, ivlen, params); +} + static SCOSSL_STATUS p_scossl_aes_gcm_final(_Inout_ SCOSSL_CIPHER_GCM_CTX *ctx, _Out_writes_bytes_(*outl) unsigned char *out, _Out_ size_t *outl, ossl_unused size_t outsize) { @@ -372,6 +387,20 @@ static SCOSSL_STATUS p_scossl_aes_ccm_decrypt_init(_Inout_ SCOSSL_CIPHER_CCM_CTX return p_scossl_aes_ccm_init_internal(ctx, 0, key, keylen, iv, ivlen, params); } +static SCOSSL_STATUS p_scossl_aes_ccm_skey_encrypt_init(_Inout_ void *ctx, _In_ SCOSSL_SKEY *skey, + _In_reads_bytes_opt_(ivlen) const unsigned char *iv, size_t ivlen, + _In_ const OSSL_PARAM params[]) +{ + return p_scossl_aes_ccm_init_internal(ctx, 1, skey->pbKey, skey->cbKey, iv, ivlen, params); +} + +static SCOSSL_STATUS p_scossl_aes_ccm_skey_decrypt_init(_Inout_ void *ctx, _In_ SCOSSL_SKEY *skey, + _In_reads_bytes_opt_(ivlen) const unsigned char *iv, size_t ivlen, + _In_ const OSSL_PARAM params[]) +{ + return p_scossl_aes_ccm_init_internal(ctx, 0, skey->pbKey, skey->cbKey, iv, ivlen, params); +} + static SCOSSL_STATUS p_scossl_aes_ccm_final(_Inout_ SCOSSL_CIPHER_CCM_CTX *ctx, _Out_writes_bytes_(*outl) unsigned char *out, _Out_ size_t *outl, ossl_unused size_t outsize) { @@ -579,6 +608,8 @@ static SCOSSL_STATUS p_scossl_aes_ccm_set_ctx_params(_Inout_ SCOSSL_CIPHER_CCM_C {OSSL_FUNC_CIPHER_GETTABLE_PARAMS, (void (*)(void))p_scossl_aes_generic_gettable_params}, \ {OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_aes_##lcmode##_gettable_ctx_params}, \ {OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_aes_##lcmode##_settable_ctx_params}, \ + {OSSL_FUNC_CIPHER_ENCRYPT_SKEY_INIT, (void (*)(void))p_scossl_aes_##lcmode##_skey_encrypt_init}, \ + {OSSL_FUNC_CIPHER_DECRYPT_SKEY_INIT, (void (*)(void))p_scossl_aes_##lcmode##_skey_decrypt_init}, \ {0, NULL}}; IMPLEMENT_SCOSSL_AES_AEAD_CIPHER(128, SCOSSL_GCM_DEFAULT_IV_LENGTH, gcm, GCM) diff --git a/SymCryptProvider/src/ciphers/p_scossl_aes_xts.c b/SymCryptProvider/src/ciphers/p_scossl_aes_xts.c index 1d38e3a3..4d44f485 100644 --- a/SymCryptProvider/src/ciphers/p_scossl_aes_xts.c +++ b/SymCryptProvider/src/ciphers/p_scossl_aes_xts.c @@ -8,6 +8,7 @@ #include "scossl_helpers.h" #include "p_scossl_aes.h" +#include "p_scossl_skey.h" #ifdef __cplusplus extern "C" { @@ -120,6 +121,19 @@ static SCOSSL_STATUS p_scossl_aes_xts_decrypt_init(_Inout_ SCOSSL_AES_XTS_CTX *c return p_scossl_aes_xts_init_internal(ctx, 0, key, keylen, iv, ivlen, params); } +static SCOSSL_STATUS p_scossl_aes_xts_skey_encrypt_init(_Inout_ SCOSSL_AES_XTS_CTX *ctx, _In_ SCOSSL_SKEY *skey, + _In_reads_bytes_opt_(ivlen) const unsigned char *iv, size_t ivlen, + _In_ const OSSL_PARAM params[]) +{ + return p_scossl_aes_xts_init_internal(ctx, 1, skey->pbKey, skey->cbKey, iv, ivlen, params); +} + +static SCOSSL_STATUS p_scossl_aes_xts_skey_decrypt_init(_Inout_ SCOSSL_AES_XTS_CTX *ctx, _In_ SCOSSL_SKEY *skey, + _In_reads_bytes_opt_(ivlen) const unsigned char *iv, size_t ivlen, + _In_ const OSSL_PARAM params[]) +{ + return p_scossl_aes_xts_init_internal(ctx, 0, skey->pbKey, skey->cbKey, iv, ivlen, params); +} static SCOSSL_STATUS p_scossl_aes_xts_cipher(SCOSSL_AES_XTS_CTX *ctx, _Out_writes_bytes_(*outl) unsigned char *out, _Out_ size_t *outl, size_t outsize, @@ -274,6 +288,8 @@ static SCOSSL_STATUS p_scossl_aes_xts_set_ctx_params(_Inout_ SCOSSL_AES_XTS_CTX {OSSL_FUNC_CIPHER_GETTABLE_PARAMS, (void (*)(void))p_scossl_aes_generic_gettable_params}, \ {OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_aes_xts_gettable_ctx_params}, \ {OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_aes_xts_settable_ctx_params}, \ + {OSSL_FUNC_CIPHER_ENCRYPT_SKEY_INIT, (void (*)(void))p_scossl_aes_xts_skey_encrypt_init}, \ + {OSSL_FUNC_CIPHER_DECRYPT_SKEY_INIT, (void (*)(void))p_scossl_aes_xts_skey_decrypt_init}, \ {0, NULL}}; IMPLEMENT_SCOSSL_AES_XTS_CIPHER(128) diff --git a/SymCryptProvider/src/mac/p_scossl_cmac.c b/SymCryptProvider/src/mac/p_scossl_cmac.c index 730724e2..0024c125 100644 --- a/SymCryptProvider/src/mac/p_scossl_cmac.c +++ b/SymCryptProvider/src/mac/p_scossl_cmac.c @@ -4,6 +4,7 @@ #include "scossl_mac.h" #include "p_scossl_base.h" +#include "p_scossl_skey.h" #include @@ -44,6 +45,14 @@ static SCOSSL_STATUS p_scossl_cmac_init(_Inout_ SCOSSL_MAC_CTX *ctx, } +static SCOSSL_STATUS p_scossl_cmac_init_skey(_Inout_ void *ctx, + _In_ SCOSSL_SKEY *skey, + _In_ const OSSL_PARAM params[]) +{ + return p_scossl_cmac_set_ctx_params(ctx, params) && + scossl_mac_init(ctx, skey->pbKey, skey->cbKey); +} + static const OSSL_PARAM *p_scossl_cmac_gettable_ctx_params(ossl_unused void *ctx, ossl_unused void *provctx) { return p_scossl_cmac_ctx_gettable_param_types; @@ -130,6 +139,7 @@ const OSSL_DISPATCH p_scossl_cmac_functions[] = { {OSSL_FUNC_MAC_FREECTX, (void (*)(void))scossl_mac_freectx}, {OSSL_FUNC_MAC_DUPCTX, (void (*)(void))scossl_mac_dupctx}, {OSSL_FUNC_MAC_INIT, (void (*)(void))p_scossl_cmac_init}, + {OSSL_FUNC_MAC_INIT_SKEY, (void (*)(void))p_scossl_cmac_init_skey}, {OSSL_FUNC_MAC_UPDATE, (void (*)(void))scossl_mac_update}, {OSSL_FUNC_MAC_FINAL, (void (*)(void))scossl_mac_final}, {OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_cmac_gettable_ctx_params}, diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index 1e59b9f0..e092410a 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -518,6 +518,15 @@ static const OSSL_ALGORITHM p_scossl_encoder[] = { ENCODER_ENTRIES_ALL(SCOSSL_LN_MLKEM1024, mlkem1024) ALG_TABLE_END}; +// Symmetric key management +extern const OSSL_DISPATCH p_scossl_aes_skeymgmt_functions[]; +extern const OSSL_DISPATCH p_scossl_generic_skeymgmt_functions[]; + +static const OSSL_ALGORITHM p_scossl_skeymgmt[] = { + ALG("AES", p_scossl_aes_skeymgmt_functions), + ALG("GENERIC-SECRET", p_scossl_generic_skeymgmt_functions), + ALG_TABLE_END}; + static SCOSSL_STATUS p_scossl_register_extended_algorithms() { return p_scossl_mlkem_register_algorithms(); @@ -609,6 +618,8 @@ static const OSSL_ALGORITHM *p_scossl_query_operation(ossl_unused void *provctx, return p_scossl_decoder; case OSSL_OP_ENCODER: return p_scossl_encoder; + case OSSL_OP_SKEYMGMT: + return p_scossl_skeymgmt; } return NULL; diff --git a/SymCryptProvider/src/p_scossl_skey.h b/SymCryptProvider/src/p_scossl_skey.h new file mode 100644 index 00000000..7e18ac0c --- /dev/null +++ b/SymCryptProvider/src/p_scossl_skey.h @@ -0,0 +1,28 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#pragma once + +#include "scossl_helpers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SCOSSL_SKEY_TYPE_GENERIC 1 +#define SCOSSL_SKEY_TYPE_AES 2 + +typedef struct +{ + int type; + + OSSL_LIB_CTX *libctx; + + PBYTE pbKey; + SIZE_T cbKey; +} SCOSSL_SKEY; + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/skeymgmt/p_scossl_aes_skeymgmt.c b/SymCryptProvider/src/skeymgmt/p_scossl_aes_skeymgmt.c new file mode 100644 index 00000000..5d015f4f --- /dev/null +++ b/SymCryptProvider/src/skeymgmt/p_scossl_aes_skeymgmt.c @@ -0,0 +1,171 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include + +#include "p_scossl_generic_skeymgmt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static const OSSL_PARAM p_scossl_aes_skeymgmt_settable_param_types[] = { + OSSL_PARAM_octet_string(OSSL_SKEY_PARAM_RAW_BYTES, NULL, 0), + OSSL_PARAM_END}; + +static const OSSL_PARAM p_scossl_aes_skeygen_settable_param_types[] = { + OSSL_PARAM_size_t(OSSL_SKEY_PARAM_KEY_LENGTH, NULL), + OSSL_PARAM_END}; + +static SCOSSL_SKEY *p_scossl_aes_skeymgmt_import(_In_ SCOSSL_PROVCTX *provctx, int selection, _In_ const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + PCBYTE pcbKey = NULL; + SIZE_T cbKey = 0; + SCOSSL_SKEY *skey = NULL; + SCOSSL_STATUS status = SCOSSL_FAILURE; + + if ((selection & OSSL_SKEYMGMT_SELECT_SECRET_KEY) == 0) + { + goto cleanup; + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_SKEY_PARAM_RAW_BYTES)) == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + goto cleanup; + } + + if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pcbKey, &cbKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + goto cleanup; + } + + if (pcbKey == NULL || cbKey == 0 || + (cbKey != 16 && cbKey != 24 && cbKey != 32)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + goto cleanup; + } + + skey = p_scossl_generic_skeymgmt_new(provctx->libctx); + if (skey == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + skey->pbKey = OPENSSL_secure_malloc(cbKey); + if (skey->pbKey == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + skey->type = SCOSSL_SKEY_TYPE_AES; + skey->cbKey = cbKey; + memcpy(skey->pbKey, pcbKey, cbKey); + + status = SCOSSL_SUCCESS; + +cleanup: + if (status != SCOSSL_SUCCESS) + { + p_scossl_generic_skeymgmt_free(skey); + skey = NULL; + } + + return skey; +} + +static SCOSSL_STATUS p_scossl_aes_skeymgmt_export(_In_ SCOSSL_SKEY *skey, int selection, + _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg) +{ + if (skey->type != SCOSSL_SKEY_TYPE_AES) + { + return SCOSSL_FAILURE; + } + + return p_scossl_generic_skeymgmt_export(skey, selection, param_cb, cbarg); +} + +static SCOSSL_SKEY *p_scossl_aes_skeygen_generate(_In_ SCOSSL_PROVCTX *provctx, _In_ const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + SIZE_T cbKey = 0; + SCOSSL_SKEY *skey = NULL; + SCOSSL_STATUS status = SCOSSL_FAILURE; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_SKEY_PARAM_KEY_LENGTH)) == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + goto cleanup; + } + + if (!OSSL_PARAM_get_size_t(p, &cbKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + goto cleanup; + } + + if (cbKey == 0 || + (cbKey != 16 && cbKey != 24 && cbKey != 32)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + goto cleanup; + } + + skey = p_scossl_generic_skeymgmt_new(provctx->libctx); + if (skey == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + skey->pbKey = OPENSSL_secure_malloc(cbKey); + if (skey->pbKey == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + skey->type = SCOSSL_SKEY_TYPE_AES; + skey->cbKey = cbKey; + SymCryptRandom(skey->pbKey, cbKey); + + status = SCOSSL_SUCCESS; + +cleanup: + if (status != SCOSSL_SUCCESS) + { + p_scossl_generic_skeymgmt_free(skey); + skey = NULL; + } + + return skey; +} + +static const OSSL_PARAM *p_scossl_aes_skeymgmt_imp_settable_params(ossl_unused void *provctx) +{ + return p_scossl_aes_skeymgmt_settable_param_types; +} + +static const OSSL_PARAM *p_scossl_aes_skeygen_settable_params(ossl_unused void *provctx) +{ + return p_scossl_aes_skeygen_settable_param_types; +} + +const OSSL_DISPATCH p_scossl_aes_skeymgmt_functions[] = { + {OSSL_FUNC_SKEYMGMT_FREE, (void (*)(void))p_scossl_generic_skeymgmt_free}, + {OSSL_FUNC_SKEYMGMT_IMPORT, (void (*)(void))p_scossl_aes_skeymgmt_import}, + {OSSL_FUNC_SKEYMGMT_EXPORT, (void (*)(void))p_scossl_aes_skeymgmt_export}, + {OSSL_FUNC_SKEYMGMT_GENERATE, (void (*)(void))p_scossl_aes_skeygen_generate}, + {OSSL_FUNC_SKEYMGMT_IMP_SETTABLE_PARAMS, (void (*)(void))p_scossl_aes_skeymgmt_imp_settable_params}, + {OSSL_FUNC_SKEYMGMT_GEN_SETTABLE_PARAMS, (void (*)(void))p_scossl_aes_skeygen_settable_params}, + {0, NULL}}; + +#ifdef __cplusplus +} +#endif diff --git a/SymCryptProvider/src/skeymgmt/p_scossl_generic_skeymgmt.c b/SymCryptProvider/src/skeymgmt/p_scossl_generic_skeymgmt.c new file mode 100644 index 00000000..6f7345a8 --- /dev/null +++ b/SymCryptProvider/src/skeymgmt/p_scossl_generic_skeymgmt.c @@ -0,0 +1,196 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include + +#include "p_scossl_generic_skeymgmt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static const OSSL_PARAM p_scossl_generic_skeymgmt_settable_param_types[] = { + OSSL_PARAM_octet_string(OSSL_SKEY_PARAM_RAW_BYTES, NULL, 0), + OSSL_PARAM_END}; + +static const OSSL_PARAM p_scossl_generic_skeygen_settable_param_types[] = { + OSSL_PARAM_size_t(OSSL_SKEY_PARAM_KEY_LENGTH, NULL), + OSSL_PARAM_END}; + +_Use_decl_annotations_ +SCOSSL_SKEY *p_scossl_generic_skeymgmt_new(OSSL_LIB_CTX *libctx) +{ + SCOSSL_SKEY *skey = OPENSSL_zalloc(sizeof(SCOSSL_SKEY)); + if (skey != NULL) + { + skey->libctx = libctx; + skey->type = SCOSSL_SKEY_TYPE_GENERIC; + } + + return skey; +} + +_Use_decl_annotations_ +void p_scossl_generic_skeymgmt_free(SCOSSL_SKEY *skey) +{ + if (skey == NULL) + return; + + OPENSSL_secure_clear_free(skey->pbKey, skey->cbKey); + OPENSSL_free(skey); +} + +SCOSSL_SKEY *p_scossl_generic_skeymgmt_import(_In_ SCOSSL_PROVCTX *provctx, int selection, _In_ const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + PCBYTE pcbKey = NULL; + SIZE_T cbKey = 0; + SCOSSL_SKEY *skey = NULL; + SCOSSL_STATUS status = SCOSSL_FAILURE; + + if ((selection & OSSL_SKEYMGMT_SELECT_SECRET_KEY) == 0) + { + goto cleanup; + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_SKEY_PARAM_RAW_BYTES)) == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + goto cleanup; + } + + if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pcbKey, &cbKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + goto cleanup; + } + + skey = p_scossl_generic_skeymgmt_new(provctx->libctx); + if (skey == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + if (cbKey > 0) + { + skey->pbKey = OPENSSL_secure_malloc(cbKey); + if (skey->pbKey == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + memcpy(skey->pbKey, pcbKey, cbKey); + } + + skey->cbKey = cbKey; + + status = SCOSSL_SUCCESS; + +cleanup: + if (status != SCOSSL_SUCCESS) + { + p_scossl_generic_skeymgmt_free(skey); + skey = NULL; + } + + return skey; +} + +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_generic_skeymgmt_export(SCOSSL_SKEY *skey, int selection, + OSSL_CALLBACK *param_cb, void *cbarg) +{ + OSSL_PARAM params[2]; + + if (skey == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if ((selection & OSSL_SKEYMGMT_SELECT_SECRET_KEY) == 0) + { + return SCOSSL_FAILURE; + } + + params[0] = OSSL_PARAM_construct_octet_string(OSSL_SKEY_PARAM_RAW_BYTES, skey->cbKey > 0 ? skey->pbKey : "", skey->cbKey); + params[1] = OSSL_PARAM_construct_end(); + + return param_cb(params, cbarg); +} + +SCOSSL_SKEY *p_scossl_generic_skeygen_generate(_In_ SCOSSL_PROVCTX *provctx, _In_ const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + SIZE_T cbKey = 0; + SCOSSL_SKEY *skey = NULL; + SCOSSL_STATUS status = SCOSSL_FAILURE; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_SKEY_PARAM_KEY_LENGTH)) == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + goto cleanup; + } + + if (!OSSL_PARAM_get_size_t(p, &cbKey)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + goto cleanup; + } + + skey = p_scossl_generic_skeymgmt_new(provctx->libctx); + if (skey == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + + if (cbKey > 0) + { + skey->pbKey = OPENSSL_secure_malloc(cbKey); + if (skey->pbKey == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + SymCryptRandom(skey->pbKey, cbKey); + } + + skey->cbKey = cbKey; + + status = SCOSSL_SUCCESS; + +cleanup: + if (status != SCOSSL_SUCCESS) + { + p_scossl_generic_skeymgmt_free(skey); + skey = NULL; + } + + return skey; +} + +static const OSSL_PARAM *p_scossl_generic_skeymgmt_settable_params(ossl_unused void *provctx) +{ + return p_scossl_generic_skeymgmt_settable_param_types; +} + +static const OSSL_PARAM *p_scossl_generic_skeygen_settable_params(ossl_unused void *provctx) +{ + return p_scossl_generic_skeygen_settable_param_types; +} + +const OSSL_DISPATCH p_scossl_generic_skeymgmt_functions[] = { + {OSSL_FUNC_SKEYMGMT_FREE, (void (*)(void))p_scossl_generic_skeymgmt_free}, + {OSSL_FUNC_SKEYMGMT_IMPORT, (void (*)(void))p_scossl_generic_skeymgmt_import}, + {OSSL_FUNC_SKEYMGMT_EXPORT, (void (*)(void))p_scossl_generic_skeymgmt_export}, + {OSSL_FUNC_SKEYMGMT_GENERATE, (void (*)(void))p_scossl_generic_skeygen_generate}, + {OSSL_FUNC_SKEYMGMT_IMP_SETTABLE_PARAMS, (void (*)(void))p_scossl_generic_skeymgmt_settable_params}, + {OSSL_FUNC_SKEYMGMT_GEN_SETTABLE_PARAMS, (void (*)(void))p_scossl_generic_skeygen_settable_params}, + {0, NULL}}; + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/SymCryptProvider/src/skeymgmt/p_scossl_generic_skeymgmt.h b/SymCryptProvider/src/skeymgmt/p_scossl_generic_skeymgmt.h new file mode 100644 index 00000000..cdb5c882 --- /dev/null +++ b/SymCryptProvider/src/skeymgmt/p_scossl_generic_skeymgmt.h @@ -0,0 +1,22 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#pragma once + +#include "p_scossl_base.h" +#include "p_scossl_skey.h" + +#ifdef __cplusplus +extern "C" { +#endif + +SCOSSL_SKEY *p_scossl_generic_skeymgmt_new(_In_ OSSL_LIB_CTX *libctx); +void p_scossl_generic_skeymgmt_free(_Inout_ SCOSSL_SKEY *skey); + +SCOSSL_STATUS p_scossl_generic_skeymgmt_export(_In_ SCOSSL_SKEY *skey, int selection, + _In_ OSSL_CALLBACK *param_cb, _In_ void *cbarg); + +#ifdef __cplusplus +} +#endif \ No newline at end of file