diff --git a/CMakeLists.txt b/CMakeLists.txt index c09a03b6..a75e7e0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.13.0) project(SymCrypt-OpenSSL - VERSION 1.9.5 + VERSION 1.9.6 DESCRIPTION "The SymCrypt engine and provider for OpenSSL (SCOSSL)" HOMEPAGE_URL "https://github.com/microsoft/SymCrypt-OpenSSL") diff --git a/ScosslCommon/inc/scossl_helpers.h b/ScosslCommon/inc/scossl_helpers.h index a7122a06..7b7c6703 100644 --- a/ScosslCommon/inc/scossl_helpers.h +++ b/ScosslCommon/inc/scossl_helpers.h @@ -119,8 +119,10 @@ typedef enum { SCOSSL_ERR_F_GET_SYMCRYPT_MAC_ALGORITHM, SCOSSL_ERR_F_HKDF_DERIVE, SCOSSL_ERR_F_MAC_DUPCTX, + SCOSSL_ERR_F_MAC_FINAL, SCOSSL_ERR_F_MAC_INIT, SCOSSL_ERR_F_MAC_SET_HMAC_MD, + SCOSSL_ERR_F_MAC_UPDATE, SCOSSL_ERR_F_RSA_DECRYPT, SCOSSL_ERR_F_RSA_ENCRYPT, SCOSSL_ERR_F_RSA_EXPORT_KEY, diff --git a/ScosslCommon/inc/scossl_mac.h b/ScosslCommon/inc/scossl_mac.h index 8477ff2f..86adba12 100644 --- a/ScosslCommon/inc/scossl_mac.h +++ b/ScosslCommon/inc/scossl_mac.h @@ -32,6 +32,7 @@ typedef struct PCSCOSSL_MAC_EX pMacEx; PBYTE pbKey; SIZE_T cbKey; + BOOL initialized; // Provider specific fields PVOID libctx; diff --git a/ScosslCommon/src/scossl_dh.c b/ScosslCommon/src/scossl_dh.c index bf2e4f5e..178e7678 100644 --- a/ScosslCommon/src/scossl_dh.c +++ b/ScosslCommon/src/scossl_dh.c @@ -73,7 +73,7 @@ SCOSSL_DH_KEY_CTX *scossl_dh_dup_key_ctx(SCOSSL_DH_KEY_CTX *ctx, BOOL copyGroup) NULL, NULL); - if ((pDlgroupCopy = SymCryptDlgroupAllocate(pcbPrimeP, pcbPrimeQ)) == NULL) + if ((pDlgroupCopy = SymCryptDlgroupAllocate(pcbPrimeP * 8, pcbPrimeQ * 8)) == NULL) { goto cleanup; } diff --git a/ScosslCommon/src/scossl_helpers.c b/ScosslCommon/src/scossl_helpers.c index ce3f6ff1..8b4a06c1 100644 --- a/ScosslCommon/src/scossl_helpers.c +++ b/ScosslCommon/src/scossl_helpers.c @@ -79,8 +79,10 @@ static ERR_STRING_DATA SCOSSL_ERR_function_strings[] = { {ERR_PACK(0, SCOSSL_ERR_F_GET_SYMCRYPT_MAC_ALGORITHM, 0), "scossl_get_symcrypt_hmac_algorithm"}, {ERR_PACK(0, SCOSSL_ERR_F_HKDF_DERIVE, 0), "scossl_hkdf_derive"}, {ERR_PACK(0, SCOSSL_ERR_F_MAC_DUPCTX, 0), "scossl_mac_dupctx"}, + {ERR_PACK(0, SCOSSL_ERR_F_MAC_FINAL, 0), "scossl_mac_final"}, {ERR_PACK(0, SCOSSL_ERR_F_MAC_INIT, 0), "scossl_mac_init"}, {ERR_PACK(0, SCOSSL_ERR_F_MAC_SET_HMAC_MD, 0), "scossl_mac_set_hmac_md"}, + {ERR_PACK(0, SCOSSL_ERR_F_MAC_UPDATE, 0), "scossl_mac_update"}, {ERR_PACK(0, SCOSSL_ERR_F_RSA_DECRYPT, 0), "scossl_rsa_decrypt"}, {ERR_PACK(0, SCOSSL_ERR_F_RSA_ENCRYPT, 0), "scossl_rsa_encrypt"}, {ERR_PACK(0, SCOSSL_ERR_F_RSA_EXPORT_KEY, 0), "scossl_rsa_export_key"}, diff --git a/ScosslCommon/src/scossl_mac.c b/ScosslCommon/src/scossl_mac.c index 66b5814f..4ba3c2e5 100644 --- a/ScosslCommon/src/scossl_mac.c +++ b/ScosslCommon/src/scossl_mac.c @@ -149,6 +149,8 @@ SCOSSL_MAC_CTX *scossl_mac_dupctx(SCOSSL_MAC_CTX *ctx) } } + copyCtx->initialized = ctx->initialized; + if (ctx->mdName != NULL && (copyCtx->mdName = OPENSSL_strdup(ctx->mdName)) == NULL) { @@ -208,6 +210,8 @@ SCOSSL_STATUS scossl_mac_set_hmac_md(SCOSSL_MAC_CTX *ctx, int mdNid) ctx->expandedKey = NULL; } + ctx->initialized = FALSE; + switch (mdNid) { case NID_sha1: @@ -282,6 +286,8 @@ SCOSSL_STATUS scossl_mac_set_cmac_cipher(SCOSSL_MAC_CTX *ctx, const EVP_CIPHER * ctx->expandedKey = NULL; } + ctx->initialized = FALSE; + switch (EVP_CIPHER_nid(cipher)) { case NID_aes_128_cbc: @@ -336,21 +342,21 @@ SCOSSL_STATUS scossl_mac_init(SCOSSL_MAC_CTX *ctx, return SCOSSL_FAILURE; } - if (ctx->expandedKey == NULL) + if (pbKey != NULL) { - SCOSSL_COMMON_ALIGNED_ALLOC_EX(expandedKey, OPENSSL_malloc, SCOSSL_MAC_EXPANDED_KEY, ctx->pMac->expandedKeySize); - if (expandedKey == NULL) + if (ctx->expandedKey == NULL) { - SCOSSL_LOG_ERROR(SCOSSL_ERR_F_MAC_INIT, ERR_R_MALLOC_FAILURE, - "Failed to aligned allocate expanded key"); - return SCOSSL_FAILURE; - } + SCOSSL_COMMON_ALIGNED_ALLOC_EX(expandedKey, OPENSSL_malloc, SCOSSL_MAC_EXPANDED_KEY, ctx->pMac->expandedKeySize); + if (expandedKey == NULL) + { + SCOSSL_LOG_ERROR(SCOSSL_ERR_F_MAC_INIT, ERR_R_MALLOC_FAILURE, + "Failed to aligned allocate expanded key"); + return SCOSSL_FAILURE; + } - ctx->expandedKey = expandedKey; - } + ctx->expandedKey = expandedKey; + } - if (pbKey != NULL) - { scError = ctx->pMac->expandKeyFunc(ctx->expandedKey, pbKey, cbKey); if (scError != SYMCRYPT_NO_ERROR) @@ -359,6 +365,13 @@ SCOSSL_STATUS scossl_mac_init(SCOSSL_MAC_CTX *ctx, "SymCryptMacExpandKey failed", scError); return SCOSSL_FAILURE; } + + ctx->initialized = TRUE; + } + + if (!ctx->initialized) + { + return SCOSSL_FAILURE; } ctx->pMac->initFunc(ctx->macState, ctx->expandedKey); @@ -370,6 +383,13 @@ _Use_decl_annotations_ SCOSSL_STATUS scossl_mac_update(SCOSSL_MAC_CTX *ctx, PCBYTE pbData, SIZE_T cbData) { + if (!ctx->initialized) + { + SCOSSL_LOG_ERROR(SCOSSL_ERR_F_MAC_UPDATE, SCOSSL_ERR_R_MISSING_CTX_DATA, + "MAC key has not been initialized"); + return SCOSSL_FAILURE; + } + ctx->pMac->appendFunc(ctx->macState, pbData, cbData); return SCOSSL_SUCCESS; @@ -379,6 +399,13 @@ _Use_decl_annotations_ SCOSSL_STATUS scossl_mac_final(SCOSSL_MAC_CTX *ctx, PBYTE pbResult, SIZE_T *cbResult, SIZE_T outsize) { + if (!ctx->initialized) + { + SCOSSL_LOG_ERROR(SCOSSL_ERR_F_MAC_FINAL, SCOSSL_ERR_R_MISSING_CTX_DATA, + "MAC key has not been initialized"); + return SCOSSL_FAILURE; + } + if (pbResult != NULL) { if (outsize < ctx->pMac->resultSize) diff --git a/SymCryptProvider/src/asymcipher/p_scossl_rsa_cipher.c b/SymCryptProvider/src/asymcipher/p_scossl_rsa_cipher.c index b5bae5fa..444ac7ad 100644 --- a/SymCryptProvider/src/asymcipher/p_scossl_rsa_cipher.c +++ b/SymCryptProvider/src/asymcipher/p_scossl_rsa_cipher.c @@ -8,6 +8,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -141,11 +142,12 @@ static SCOSSL_STATUS p_scossl_rsa_decrypt_init(_Inout_ SCOSSL_RSA_CIPHER_CTX *ct } static SCOSSL_STATUS p_scossl_rsa_cipher_encrypt(_In_ SCOSSL_RSA_CIPHER_CTX *ctx, - _Out_writes_bytes_(*outlen) unsigned char *out, _Out_ size_t *outlen, size_t outsize, - _In_reads_bytes_(inlen) const unsigned char *in, size_t inlen) + _Out_writes_bytes_(*outlen) unsigned char *out, _Out_ size_t *outlen, size_t outsize, + _In_reads_bytes_(inlen) const unsigned char *in, size_t inlen) { int mdnid = 0; INT32 cbResult; + UINT32 cbModulus; SCOSSL_STATUS ret; if (ctx->keyCtx == NULL) @@ -160,6 +162,25 @@ static SCOSSL_STATUS p_scossl_rsa_cipher_encrypt(_In_ SCOSSL_RSA_CIPHER_CTX *ctx return SCOSSL_FAILURE; } + cbModulus = SymCryptRsakeySizeofModulus(ctx->keyCtx->key); + if (cbModulus == 0) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY); + return SCOSSL_FAILURE; + } + + if (out == NULL) + { + *outlen = cbModulus; + return SCOSSL_SUCCESS; + } + + if (outsize < cbModulus) + { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return SCOSSL_FAILURE; + } + // Default to SHA1 for OAEP. Update md in context so this is // reflected in getparam if (ctx->padding == RSA_PKCS1_OAEP_PADDING) @@ -187,11 +208,12 @@ static SCOSSL_STATUS p_scossl_rsa_cipher_encrypt(_In_ SCOSSL_RSA_CIPHER_CTX *ctx } static SCOSSL_STATUS p_scossl_rsa_cipher_decrypt(_In_ SCOSSL_RSA_CIPHER_CTX *ctx, - _Out_writes_bytes_(*outlen) unsigned char *out, _Out_ size_t *outlen, size_t outsize, - _In_reads_bytes_(inlen) const unsigned char *in, size_t inlen) + _Out_writes_bytes_(*outlen) unsigned char *out, _Out_ size_t *outlen, size_t outsize, + _In_reads_bytes_(inlen) const unsigned char *in, size_t inlen) { int mdnid = 0; INT32 cbResult; + UINT32 cbModulus; SCOSSL_STATUS ret; if (ctx->keyCtx == NULL) @@ -206,6 +228,41 @@ static SCOSSL_STATUS p_scossl_rsa_cipher_decrypt(_In_ SCOSSL_RSA_CIPHER_CTX *ctx return SCOSSL_FAILURE; } + if (ctx->padding == RSA_PKCS1_WITH_TLS_PADDING) + { + if (out == NULL) + { + *outlen = SSL_MAX_MASTER_KEY_LENGTH; + return SCOSSL_SUCCESS; + } + if (outsize < SSL_MAX_MASTER_KEY_LENGTH) + { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return SCOSSL_FAILURE; + } + } + else + { + cbModulus = SymCryptRsakeySizeofModulus(ctx->keyCtx->key); + if (cbModulus == 0) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY); + return SCOSSL_FAILURE; + } + + if (out == NULL) + { + *outlen = cbModulus; + return SCOSSL_SUCCESS; + } + + if (outsize < cbModulus) + { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return SCOSSL_FAILURE; + } + } + // Default to SHA1 for OAEP. Update md in context so this is // reflected in getparam if (ctx->padding == RSA_PKCS1_OAEP_PADDING) diff --git a/SymCryptProvider/src/ciphers/p_scossl_aes.c b/SymCryptProvider/src/ciphers/p_scossl_aes.c index 7fbe7d85..41002e6a 100644 --- a/SymCryptProvider/src/ciphers/p_scossl_aes.c +++ b/SymCryptProvider/src/ciphers/p_scossl_aes.c @@ -774,7 +774,7 @@ static SCOSSL_STATUS p_scossl_aes_generic_set_ctx_params(_Inout_ SCOSSL_AES_CTX return SCOSSL_FAILURE; } - if (ctx->tlsMacSize > EVP_MAX_MD_SIZE) + if (tlsMacSize > EVP_MAX_MD_SIZE) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MAC); return SCOSSL_FAILURE; diff --git a/SymCryptProvider/src/keymgmt/p_scossl_dh_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_dh_keymgmt.c index 99210ac2..dcb21a7a 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_dh_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_dh_keymgmt.c @@ -155,7 +155,7 @@ static SCOSSL_PROV_DH_KEY_CTX *p_scossl_dh_keymgmt_dup_key_ctx(_In_ const SCOSSL NULL, NULL); - if ((copyCtx->pDlGroup = SymCryptDlgroupAllocate(pcbPrimeP, pcbPrimeQ)) == NULL) + if ((copyCtx->pDlGroup = SymCryptDlgroupAllocate(pcbPrimeP * 8, pcbPrimeQ * 8)) == NULL) { OPENSSL_free(copyCtx); return NULL; diff --git a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c index 67c11b92..0e6bfcb6 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c @@ -14,7 +14,7 @@ extern "C" { #endif -#define SCOSSL_X25519_MAX_SIZE (32) +#define SCOSSL_X25519_KEY_SIZE (32) #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) @@ -568,7 +568,7 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_get_params(_In_ SCOSSL_ECC_KEY_CTX *ke { if (keyCtx->isX25519) { - if (!OSSL_PARAM_set_uint32(p, SCOSSL_X25519_MAX_SIZE)) + if (!OSSL_PARAM_set_uint32(p, SCOSSL_X25519_KEY_SIZE)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); goto cleanup; @@ -1332,10 +1332,13 @@ static SCOSSL_STATUS p_scossl_x25519_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX * { SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; SCOSSL_STATUS ret = SCOSSL_FAILURE; + PSYMCRYPT_ECKEY ecKey = NULL; PBYTE pbPrivateKey = NULL; + PCBYTE pcbPrivateKey = NULL; SIZE_T cbPrivateKey = 0; PBYTE pbPublicKey = NULL; SIZE_T cbPublicKey = 0; + BYTE modifiedPrivateBits = 0; const OSSL_PARAM *p; // Other parameters @@ -1352,12 +1355,6 @@ static SCOSSL_STATUS p_scossl_x25519_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX * // Keypair if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { - if ((keyCtx->key = SymCryptEckeyAllocate(keyCtx->curve))== NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - goto cleanup; - } - if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY)) != NULL) { if (!OSSL_PARAM_get_octet_string(p, (void **)&pbPublicKey, 0, &cbPublicKey)) @@ -1365,43 +1362,91 @@ static SCOSSL_STATUS p_scossl_x25519_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX * ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); goto cleanup; } + + if (cbPublicKey != SCOSSL_X25519_KEY_SIZE) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + goto cleanup; + } } if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY)) != NULL) { - if (!OSSL_PARAM_get_octet_string(p, (void **)&pbPrivateKey, 0, &cbPrivateKey)) + if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pcbPrivateKey, &cbPrivateKey)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); goto cleanup; } + if (cbPrivateKey != SCOSSL_X25519_KEY_SIZE) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + goto cleanup; + } + + if ((pbPrivateKey = OPENSSL_secure_malloc(cbPrivateKey)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + memcpy(pbPrivateKey, pcbPrivateKey, cbPrivateKey); + // Preserve original bits for export - keyCtx->modifiedPrivateBits = pbPrivateKey[0] & 0x07; - keyCtx->modifiedPrivateBits |= pbPrivateKey[cbPrivateKey-1] & 0xc0; + modifiedPrivateBits = pbPrivateKey[0] & 0x07; + modifiedPrivateBits |= pbPrivateKey[cbPrivateKey-1] & 0xc0; pbPrivateKey[0] &= 0xf8; pbPrivateKey[cbPrivateKey-1] &= 0x7f; pbPrivateKey[cbPrivateKey-1] |= 0x40; } + if (pbPrivateKey == NULL && pbPublicKey == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + goto cleanup; + } + + if ((ecKey = SymCryptEckeyAllocate(keyCtx->curve)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + goto cleanup; + } + scError = SymCryptEckeySetValue( pbPrivateKey, cbPrivateKey, pbPublicKey, cbPublicKey, SYMCRYPT_NUMBER_FORMAT_LSB_FIRST, SYMCRYPT_ECPOINT_FORMAT_X, SYMCRYPT_FLAG_ECKEY_ECDH, - keyCtx->key); + ecKey); if (scError != SYMCRYPT_NO_ERROR) { SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptEckeySetValue failed", scError); goto cleanup; } + 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 + + keyCtx->key = ecKey; + ecKey = NULL; + keyCtx->modifiedPrivateBits = modifiedPrivateBits; keyCtx->initialized = TRUE; } ret = SCOSSL_SUCCESS; cleanup: + if (ret != SCOSSL_SUCCESS && ecKey != NULL) + { + SymCryptEckeyFree(ecKey); + } OPENSSL_secure_clear_free(pbPrivateKey, cbPrivateKey); OPENSSL_free(pbPublicKey); diff --git a/SymCryptProvider/src/keymgmt/p_scossl_rsa_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_rsa_keymgmt.c index 46342746..07774f41 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_rsa_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_rsa_keymgmt.c @@ -1056,7 +1056,7 @@ static BOOL p_scossl_rsa_keymgmt_match(_In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx1, _I SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, 0); if (scError != SYMCRYPT_NO_ERROR) - { + { SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptRsakeyGetCrtValue failed", scError); goto cleanup; } @@ -1074,7 +1074,7 @@ static BOOL p_scossl_rsa_keymgmt_match(_In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx1, _I goto cleanup; } - if (memcmp(pbPrivateExponent1, pbPrivateExponent1, cbModulus) != 0) + if (memcmp(pbPrivateExponent1, pbPrivateExponent2, cbModulus) != 0) { goto cleanup; }