* Stub KDF functions

* HKDF implementation

* Provider SSH KDF

* Fix engine publiuc header property

* Provider TLS1-PRF

* Cleanup

* OpenSSL 1.1.1 engine build compatability

* Use common hash fetching for RSA

* Address PR comments

* Correct MAC related error logging

* PR comments

* PR comments

* Minor cleanup
This commit is contained in:
Maxwell McKee 2023-11-29 16:04:38 -08:00 коммит произвёл GitHub
Родитель 8ee9ee42c9
Коммит 7abafd80a9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
23 изменённых файлов: 1709 добавлений и 380 удалений

Просмотреть файл

@ -12,7 +12,10 @@ set(SCOSSL_SOURCES
./src/scossl_helpers.c
./src/scossl_aes_aead.c
./src/scossl_ecc.c
./src/scossl_hkdf.c
./src/scossl_rsa.c
./src/scossl_sshkdf.c
./src/scossl_tls1prf.c
)
add_library(scossl_common STATIC ${SCOSSL_SOURCES})

Просмотреть файл

@ -239,6 +239,15 @@ void _scossl_log_SYMCRYPT_ERROR(
#define SCOSSL_LOG_SYMCRYPT_ERROR(func_code, reason_code, description, scError) \
_scossl_log_SYMCRYPT_ERROR(SCOSSL_LOG_LEVEL_ERROR, func_code, reason_code, __FILE__, __LINE__, description, scError)
//
// Common helper functions
//
// Functions for converting OpenSSL types to their SymCrypt equivalent
BOOL scossl_is_md_supported(int mdnid);
PCSYMCRYPT_MAC scossl_get_symcrypt_hmac_algorithm(int mdnid);
PCSYMCRYPT_HASH scossl_get_symcrypt_hash_algorithm(int mdnid);
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -0,0 +1,56 @@
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "scossl_helpers.h"
#include <openssl/kdf.h>
#ifdef __cplusplus
extern "C" {
#endif
#define HKDF_MAXBUF 1024
// These macros were renamed in OpenSSL 3. Common implementation
// uses the new names. This mapping from new to old names is
// needed until OpenSSL 1.1.1 builds are no longer needed.
#ifndef EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND
#define EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND
#endif
#ifndef EVP_KDF_HKDF_MODE_EXTRACT_ONLY
#define EVP_KDF_HKDF_MODE_EXTRACT_ONLY EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY
#endif
#ifndef EVP_KDF_HKDF_MODE_EXPAND_ONLY
#define EVP_KDF_HKDF_MODE_EXPAND_ONLY EVP_PKEY_HKDEF_MODE_EXPAND_ONLY
#endif
typedef struct
{
int mode;
EVP_MD *md;
PBYTE pbSalt;
SIZE_T cbSalt;
PBYTE pbKey;
SIZE_T cbKey;
BYTE info[HKDF_MAXBUF];
SIZE_T cbInfo;
} SCOSSL_HKDF_CTX;
SCOSSL_HKDF_CTX *scossl_hkdf_newctx();
SCOSSL_HKDF_CTX *scossl_hkdf_dupctx(_In_ SCOSSL_HKDF_CTX *ctx);
void scossl_hkdf_freectx(_Inout_ SCOSSL_HKDF_CTX *ctx);
SCOSSL_STATUS scossl_hkdf_reset(_Inout_ SCOSSL_HKDF_CTX *ctx);
SCOSSL_STATUS scossl_hkdf_append_info(_Inout_ SCOSSL_HKDF_CTX *ctx,
_In_reads_bytes_(cbInfo) PCBYTE pbInfo, SIZE_T cbInfo);
SCOSSL_STATUS scossl_hkdf_derive(_In_ SCOSSL_HKDF_CTX *ctx,
_Out_writes_bytes_(keylen) PBYTE key, SIZE_T keylen);
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -0,0 +1,36 @@
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "scossl_helpers.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SSH_KDF_MAX_DIGEST_SIZE (512 / 8)
typedef struct
{
PCSYMCRYPT_HASH pHash;
PBYTE pbKey;
SIZE_T cbKey;
BYTE hashValue[SSH_KDF_MAX_DIGEST_SIZE];
SIZE_T cbHashValue;
BYTE sessionId[SSH_KDF_MAX_DIGEST_SIZE];
SIZE_T cbSessionId;
BYTE label;
} SCOSSL_SSHKDF_CTX;
SCOSSL_SSHKDF_CTX *scossl_sshkdf_newctx();
SCOSSL_SSHKDF_CTX *scossl_sshkdf_dupctx(_In_ SCOSSL_SSHKDF_CTX *ctx);
void scossl_sshkdf_freectx(_Inout_ SCOSSL_SSHKDF_CTX *ctx);
SCOSSL_STATUS scossl_sshkdf_reset(_Inout_ SCOSSL_SSHKDF_CTX *ctx);
SCOSSL_STATUS scossl_sshkdf_derive(_In_ SCOSSL_SSHKDF_CTX *ctx,
_Out_writes_bytes_(keylen) PBYTE key, SIZE_T keylen);
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -0,0 +1,36 @@
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "scossl_helpers.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TLS1_PRF_MAXBUF 1024
typedef struct
{
BOOL isTlsPrf1_1;
PCSYMCRYPT_MAC pHmac;
PBYTE pbSecret;
SIZE_T cbSecret;
BYTE seed[TLS1_PRF_MAXBUF];
SIZE_T cbSeed;
} SCOSSL_TLS1_PRF_CTX;
SCOSSL_TLS1_PRF_CTX *scossl_tls1prf_newctx();
SCOSSL_TLS1_PRF_CTX *scossl_tls1prf_dupctx(_In_ SCOSSL_TLS1_PRF_CTX *ctx);
void scossl_tls1prf_freectx(_Inout_ SCOSSL_TLS1_PRF_CTX *ctx);
SCOSSL_STATUS scossl_tls1prf_reset(_Inout_ SCOSSL_TLS1_PRF_CTX *ctx);
SCOSSL_STATUS scossl_tls1prf_append_seed(_Inout_ SCOSSL_TLS1_PRF_CTX *ctx,
_In_reads_bytes_(cbSeed) PCBYTE pbSeed, SIZE_T cbSeed);
SCOSSL_STATUS scossl_tls1prf_derive(_In_ SCOSSL_TLS1_PRF_CTX *ctx,
_Out_writes_bytes_(keylen) PBYTE key, SIZE_T keylen);
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -67,7 +67,7 @@ static ERR_STRING_DATA SCOSSL_ERR_function_strings[] = {
{ERR_PACK(0, SCOSSL_ERR_F_GET_DH_CONTEXT_EX, 0), "scossl_get_dh_context_ex"},
{ERR_PACK(0, SCOSSL_ERR_F_GET_ECC_CONTEXT_EX, 0), "scossl_get_ecc_context_ex"},
{ERR_PACK(0, SCOSSL_ERR_F_GET_SYMCRYPT_HASH_ALGORITHM, 0), "scossl_get_symcrypt_hash_algorithm"},
{ERR_PACK(0, SCOSSL_ERR_F_GET_SYMCRYPT_MAC_ALGORITHM, 0), "scossl_get_symcrypt_mac_algorithm"},
{ERR_PACK(0, SCOSSL_ERR_F_GET_SYMCRYPT_MAC_ALGORITHM, 0), "scossl_get_symcrypt_hmac_algorithm"},
{ERR_PACK(0, SCOSSL_ERR_F_HKDF_CTRL, 0), "scossl_hkdf_ctrl"},
{ERR_PACK(0, SCOSSL_ERR_F_HKDF_DERIVE, 0), "scossl_hkdf_derive"},
{ERR_PACK(0, SCOSSL_ERR_F_HKDF_INIT, 0), "scossl_hkdf_init"},
@ -394,6 +394,74 @@ void _scossl_log_SYMCRYPT_ERROR(
_scossl_log(trace_level, func_code, reason_code, file, line, "%s - %s (0x%x)", description, scErrorString, scError);
}
_Use_decl_annotations_
BOOL scossl_is_md_supported(int mdnid)
{
switch (mdnid)
{
case NID_sha1:
case NID_sha256:
case NID_sha384:
case NID_sha512:
case NID_sha3_256:
case NID_sha3_384:
case NID_sha3_512:
return TRUE;
}
return FALSE;
}
_Use_decl_annotations_
PCSYMCRYPT_MAC scossl_get_symcrypt_hmac_algorithm(int mdnid)
{
switch(mdnid)
{
case NID_sha1:
return SymCryptHmacSha1Algorithm;
case NID_sha256:
return SymCryptHmacSha256Algorithm;
case NID_sha384:
return SymCryptHmacSha384Algorithm;
case NID_sha512:
return SymCryptHmacSha512Algorithm;
case NID_sha3_256:
return SymCryptHmacSha3_256Algorithm;
case NID_sha3_384:
return SymCryptHmacSha3_384Algorithm;
case NID_sha3_512:
return SymCryptHmacSha3_512Algorithm;
}
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_GET_SYMCRYPT_MAC_ALGORITHM, SCOSSL_ERR_R_NOT_IMPLEMENTED,
"SymCrypt-OpenSSL does not support hmac algorithm %d", mdnid);
return NULL;
}
_Use_decl_annotations_
PCSYMCRYPT_HASH scossl_get_symcrypt_hash_algorithm(int mdnid)
{
switch (mdnid)
{
case NID_sha1:
return SymCryptSha1Algorithm;
case NID_sha256:
return SymCryptSha256Algorithm;
case NID_sha384:
return SymCryptSha384Algorithm;
case NID_sha512:
return SymCryptSha512Algorithm;
case NID_sha3_256:
return SymCryptSha3_256Algorithm;
case NID_sha3_384:
return SymCryptSha3_384Algorithm;
case NID_sha3_512:
return SymCryptSha3_512Algorithm;
}
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_GET_SYMCRYPT_HASH_ALGORITHM, SCOSSL_ERR_R_NOT_IMPLEMENTED,
"SymCrypt-OpenSSL does not support hash algorithm %d", mdnid);
return NULL;
}
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -0,0 +1,172 @@
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "scossl_hkdf.h"
#ifdef __cplusplus
extern "C" {
#endif
SCOSSL_HKDF_CTX *scossl_hkdf_newctx()
{
return OPENSSL_zalloc(sizeof(SCOSSL_HKDF_CTX));
}
_Use_decl_annotations_
SCOSSL_HKDF_CTX *scossl_hkdf_dupctx(SCOSSL_HKDF_CTX *ctx)
{
SCOSSL_HKDF_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_HKDF_CTX));
if (copyCtx != NULL)
{
if (ctx->pbSalt == NULL)
{
copyCtx->pbSalt = NULL;
}
else if ((copyCtx->pbSalt = OPENSSL_memdup(ctx->pbSalt, ctx->cbSalt)) == NULL)
{
scossl_hkdf_freectx(copyCtx);
return NULL;
}
copyCtx->cbSalt = ctx->cbSalt;
if (ctx->pbKey == NULL)
{
copyCtx->pbKey = NULL;
}
else if ((copyCtx->pbKey = OPENSSL_memdup(ctx->pbKey, ctx->cbKey)) == NULL)
{
scossl_hkdf_freectx(copyCtx);
return NULL;
}
copyCtx->cbKey = ctx->cbKey;
copyCtx->md = ctx->md;
copyCtx->mode = ctx->mode;
copyCtx->cbInfo = ctx->cbInfo;
memcpy(copyCtx->info, ctx->info, ctx->cbInfo);
}
return copyCtx;
}
_Use_decl_annotations_
void scossl_hkdf_freectx(SCOSSL_HKDF_CTX *ctx)
{
if (ctx == NULL)
return;
OPENSSL_clear_free(ctx->pbSalt, ctx->cbSalt);
OPENSSL_clear_free(ctx->pbKey, ctx->cbKey);
OPENSSL_cleanse(ctx->info, ctx->cbInfo);
OPENSSL_free(ctx);
}
_Use_decl_annotations_
SCOSSL_STATUS scossl_hkdf_reset(SCOSSL_HKDF_CTX *ctx)
{
OPENSSL_clear_free(ctx->pbSalt, ctx->cbSalt);
OPENSSL_clear_free(ctx->pbKey, ctx->cbKey);
OPENSSL_cleanse(ctx, sizeof(*ctx));
return SCOSSL_SUCCESS;
}
_Use_decl_annotations_
SCOSSL_STATUS scossl_hkdf_append_info(SCOSSL_HKDF_CTX *ctx,
PCBYTE pbInfo, SIZE_T cbInfo)
{
if (cbInfo > HKDF_MAXBUF - ctx->cbInfo)
{
return SCOSSL_FAILURE;
}
memcpy(ctx->info + ctx->cbInfo, pbInfo, cbInfo);
ctx->cbInfo += cbInfo;
return SCOSSL_SUCCESS;
}
_Use_decl_annotations_
SCOSSL_STATUS scossl_hkdf_derive(SCOSSL_HKDF_CTX *ctx,
PBYTE key, SIZE_T keylen)
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
PCSYMCRYPT_MAC symcryptHmacAlg = NULL;
SYMCRYPT_HKDF_EXPANDED_KEY scExpandedKey;
if (ctx->md == NULL)
{
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_HKDF_DERIVE, ERR_R_INTERNAL_ERROR,
"Missing Digest");
return SCOSSL_FAILURE;
}
if (ctx->pbKey == NULL)
{
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_HKDF_DERIVE, ERR_R_INTERNAL_ERROR,
"Missing Key");
return SCOSSL_FAILURE;
}
symcryptHmacAlg = scossl_get_symcrypt_hmac_algorithm(EVP_MD_type(ctx->md));
if (symcryptHmacAlg == NULL)
{
return SCOSSL_FAILURE;
}
switch (ctx->mode)
{
case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
scError = SymCryptHkdf(
symcryptHmacAlg,
ctx->pbKey, ctx->cbKey,
ctx->pbSalt, ctx->cbSalt,
ctx->info, ctx->cbInfo,
key, keylen);
if (scError != SYMCRYPT_NO_ERROR)
{
return SCOSSL_FAILURE;
}
break;
case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
scError = SymCryptHkdfExtractPrk(
symcryptHmacAlg,
ctx->pbKey, ctx->cbKey,
ctx->pbSalt, ctx->cbSalt,
key, keylen);
if (scError != SYMCRYPT_NO_ERROR)
{
return SCOSSL_FAILURE;
}
break;
case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
scError = SymCryptHkdfPrkExpandKey(
&scExpandedKey,
symcryptHmacAlg,
ctx->pbKey, ctx->cbKey);
if (scError != SYMCRYPT_NO_ERROR)
{
return SCOSSL_FAILURE;
}
scError = SymCryptHkdfDerive(
&scExpandedKey,
ctx->info, ctx->cbInfo,
key, keylen);
if (scError != SYMCRYPT_NO_ERROR)
{
return SCOSSL_FAILURE;
}
break;
default:
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_HKDF_DERIVE, ERR_R_INTERNAL_ERROR,
"Invalid Mode: %d", ctx->mode);
return SCOSSL_FAILURE;
}
return SCOSSL_SUCCESS;
}
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -64,30 +64,6 @@ static const SCOSSL_RSA_PKCS1_PARAMS *scossl_get_rsa_pkcs1_params(int mdnid)
return NULL;
}
static PCSYMCRYPT_HASH scossl_get_symcrypt_hash_algorithm(int mdnid)
{
switch (mdnid)
{
case NID_md5:
return SymCryptMd5Algorithm;
case NID_sha1:
return SymCryptSha1Algorithm;
case NID_sha256:
return SymCryptSha256Algorithm;
case NID_sha384:
return SymCryptSha384Algorithm;
case NID_sha512:
return SymCryptSha512Algorithm;
case NID_sha3_256:
return SymCryptSha3_256Algorithm;
case NID_sha3_384:
return SymCryptSha3_384Algorithm;
case NID_sha3_512:
return SymCryptSha3_512Algorithm;
}
return NULL;
}
static SIZE_T scossl_get_expected_hash_length(int mdnid)
{
switch (mdnid)
@ -196,15 +172,15 @@ SCOSSL_STATUS scossl_rsa_pkcs1_sign(SCOSSL_RSA_KEY_CTX *keyCtx, int mdnid,
{
case NID_md5_sha1:
SCOSSL_LOG_INFO(SCOSSL_ERR_F_RSA_SIGN, SCOSSL_ERR_R_NOT_FIPS_ALGORITHM,
"Using Mac algorithm MD5+SHA1 which is not FIPS compliant");
"Using Hmac algorithm MD5+SHA1 which is not FIPS compliant");
break;
case NID_md5:
SCOSSL_LOG_INFO(SCOSSL_ERR_F_RSA_SIGN, SCOSSL_ERR_R_NOT_FIPS_ALGORITHM,
"Using Mac algorithm MD5 which is not FIPS compliant");
"Using Hmac algorithm MD5 which is not FIPS compliant");
break;
case NID_sha1:
SCOSSL_LOG_INFO(SCOSSL_ERR_F_RSA_SIGN, SCOSSL_ERR_R_NOT_FIPS_ALGORITHM,
"Using Mac algorithm SHA1 which is not FIPS compliant");
"Using Hmac algorithm SHA1 which is not FIPS compliant");
break;
}
@ -258,15 +234,15 @@ SCOSSL_STATUS scossl_rsa_pkcs1_verify(SCOSSL_RSA_KEY_CTX *keyCtx, int mdnid,
{
case NID_md5_sha1:
SCOSSL_LOG_INFO(SCOSSL_ERR_F_RSA_VERIFY, SCOSSL_ERR_R_NOT_FIPS_ALGORITHM,
"Using Mac algorithm MD5+SHA1 which is not FIPS compliant");
"Using Hmac algorithm MD5+SHA1 which is not FIPS compliant");
break;
case NID_md5:
SCOSSL_LOG_INFO(SCOSSL_ERR_F_RSA_VERIFY, SCOSSL_ERR_R_NOT_FIPS_ALGORITHM,
"Using Mac algorithm MD5 which is not FIPS compliant");
"Using Hmac algorithm MD5 which is not FIPS compliant");
break;
case NID_sha1:
SCOSSL_LOG_INFO(SCOSSL_ERR_F_RSA_VERIFY, SCOSSL_ERR_R_NOT_FIPS_ALGORITHM,
"Using Mac algorithm SHA1 which is not FIPS compliant");
"Using Hmac algorithm SHA1 which is not FIPS compliant");
break;
}
@ -363,12 +339,12 @@ SCOSSL_STATUS scossl_rsapss_sign(SCOSSL_RSA_KEY_CTX *keyCtx, int mdnid, int cbSa
if (mdnid == NID_md5)
{
SCOSSL_LOG_INFO(SCOSSL_ERR_F_RSAPSS_SIGN, SCOSSL_ERR_R_NOT_FIPS_ALGORITHM,
"Using Mac algorithm MD5 which is not FIPS compliant");
"Using Hmac algorithm MD5 which is not FIPS compliant");
}
else if (mdnid == NID_sha1)
{
SCOSSL_LOG_INFO(SCOSSL_ERR_F_RSAPSS_SIGN, SCOSSL_ERR_R_NOT_FIPS_ALGORITHM,
"Using Mac algorithm SHA1 which is not FIPS compliant");
"Using Hmac algorithm SHA1 which is not FIPS compliant");
}
if (cbHashValue != expectedHashLength)
@ -458,12 +434,12 @@ SCOSSL_STATUS scossl_rsapss_verify(SCOSSL_RSA_KEY_CTX *keyCtx, int mdnid, int cb
if (mdnid == NID_md5)
{
SCOSSL_LOG_INFO(SCOSSL_ERR_F_RSAPSS_VERIFY, SCOSSL_ERR_R_NOT_FIPS_ALGORITHM,
"Using Mac algorithm MD5 which is not FIPS compliant");
"Using Hmac algorithm MD5 which is not FIPS compliant");
}
else if (mdnid == NID_sha1)
{
SCOSSL_LOG_INFO(SCOSSL_ERR_F_RSAPSS_VERIFY, SCOSSL_ERR_R_NOT_FIPS_ALGORITHM,
"Using Mac algorithm SHA1 which is not FIPS compliant");
"Using Hmac algorithm SHA1 which is not FIPS compliant");
}
scError = SymCryptRsaPssVerify(

Просмотреть файл

@ -0,0 +1,111 @@
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "scossl_sshkdf.h"
#ifdef __cplusplus
extern "C" {
#endif
_Use_decl_annotations_
SCOSSL_SSHKDF_CTX *scossl_sshkdf_newctx()
{
return OPENSSL_zalloc(sizeof(SCOSSL_SSHKDF_CTX));
}
_Use_decl_annotations_
SCOSSL_SSHKDF_CTX *scossl_sshkdf_dupctx(SCOSSL_SSHKDF_CTX *ctx)
{
SCOSSL_SSHKDF_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_SSHKDF_CTX));
if (copyCtx != NULL)
{
*copyCtx = *ctx;
copyCtx->pbKey = NULL;
if (ctx->pbKey != NULL &&
(copyCtx->pbKey = OPENSSL_memdup(ctx->pbKey, ctx->cbKey)) == NULL)
{
scossl_sshkdf_freectx(copyCtx);
copyCtx = NULL;
}
}
return copyCtx;
}
_Use_decl_annotations_
void scossl_sshkdf_freectx(SCOSSL_SSHKDF_CTX *ctx)
{
if (ctx == NULL)
return;
OPENSSL_clear_free(ctx->pbKey, ctx->cbKey);
OPENSSL_cleanse(ctx->hashValue, sizeof(ctx->hashValue));
OPENSSL_cleanse(ctx->sessionId, sizeof(ctx->sessionId));
OPENSSL_free(ctx);
}
_Use_decl_annotations_
SCOSSL_STATUS scossl_sshkdf_reset(SCOSSL_SSHKDF_CTX *ctx)
{
OPENSSL_clear_free(ctx->pbKey, ctx->cbKey);
OPENSSL_cleanse(ctx, sizeof(*ctx));
return SCOSSL_SUCCESS;
}
_Use_decl_annotations_
SCOSSL_STATUS scossl_sshkdf_derive(SCOSSL_SSHKDF_CTX *ctx,
PBYTE key, SIZE_T keylen)
{
SYMCRYPT_ERROR scError;
if (!ctx->pHash ||
ctx->cbHashValue == 0)
{
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_SSHKDF_DERIVE, ERR_R_INTERNAL_ERROR,
"Missing Digest");
return SCOSSL_FAILURE;
}
if (!ctx->pbKey)
{
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_SSHKDF_DERIVE, ERR_R_INTERNAL_ERROR,
"Missing Key");
return SCOSSL_FAILURE;
}
if (ctx->cbSessionId == 0)
{
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_SSHKDF_DERIVE, ERR_R_INTERNAL_ERROR,
"Missing Session ID");
return SCOSSL_FAILURE;
}
if (ctx->label == 0)
{
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_SSHKDF_DERIVE, ERR_R_INTERNAL_ERROR,
"Missing Label");
return SCOSSL_FAILURE;
}
scError = SymCryptSshKdf(
ctx->pHash,
ctx->pbKey, ctx->cbKey,
ctx->hashValue, ctx->cbHashValue,
ctx->label,
ctx->sessionId, ctx->cbSessionId,
key, keylen);
if (scError != SYMCRYPT_NO_ERROR)
{
return SCOSSL_FAILURE;
}
return SCOSSL_SUCCESS;
}
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -0,0 +1,130 @@
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "scossl_tls1prf.h"
#ifdef __cplusplus
extern "C" {
#endif
SCOSSL_TLS1_PRF_CTX *scossl_tls1prf_newctx()
{
return OPENSSL_zalloc(sizeof(SCOSSL_TLS1_PRF_CTX));
}
_Use_decl_annotations_
SCOSSL_TLS1_PRF_CTX *scossl_tls1prf_dupctx(SCOSSL_TLS1_PRF_CTX *ctx)
{
SCOSSL_TLS1_PRF_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_TLS1_PRF_CTX));
if (copyCtx != NULL)
{
if (ctx->pbSecret == NULL)
{
copyCtx->pbSecret = NULL;
}
else if ((copyCtx->pbSecret = OPENSSL_memdup(ctx->pbSecret, ctx->cbSecret)) == NULL)
{
scossl_tls1prf_freectx(copyCtx);
return NULL;
}
copyCtx->isTlsPrf1_1 = ctx->isTlsPrf1_1;
copyCtx->pHmac = ctx->pHmac;
copyCtx->cbSecret = ctx->cbSecret;
copyCtx->cbSeed = ctx->cbSeed;
memcpy(copyCtx->seed, ctx->seed, ctx->cbSeed);
}
return copyCtx;
}
_Use_decl_annotations_
void scossl_tls1prf_freectx(SCOSSL_TLS1_PRF_CTX *ctx)
{
if (ctx == NULL)
return;
OPENSSL_clear_free(ctx->pbSecret, ctx->cbSecret);
OPENSSL_cleanse(ctx->seed, ctx->cbSeed);
OPENSSL_free(ctx);
}
_Use_decl_annotations_
SCOSSL_STATUS scossl_tls1prf_reset(SCOSSL_TLS1_PRF_CTX *ctx)
{
OPENSSL_clear_free(ctx->pbSecret, ctx->cbSecret);
OPENSSL_cleanse(ctx, sizeof(*ctx));
return SCOSSL_SUCCESS;
}
_Use_decl_annotations_
SCOSSL_STATUS scossl_tls1prf_append_seed(SCOSSL_TLS1_PRF_CTX *ctx,
PCBYTE pbSeed, SIZE_T cbSeed)
{
if (cbSeed > TLS1_PRF_MAXBUF - ctx->cbSeed )
{
return SCOSSL_FAILURE;
}
memcpy(ctx->seed + ctx->cbSeed, pbSeed, cbSeed);
ctx->cbSeed += cbSeed;
return SCOSSL_SUCCESS;
}
_Use_decl_annotations_
SCOSSL_STATUS scossl_tls1prf_derive(SCOSSL_TLS1_PRF_CTX *ctx,
PBYTE key, SIZE_T keylen)
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
if (ctx->pbSecret == NULL)
{
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_TLS1PRF_DERIVE, ERR_R_INTERNAL_ERROR,
"Missing Secret");
return SCOSSL_FAILURE;
}
if (ctx->isTlsPrf1_1)
{
// Special case to use TlsPrf1_1 to handle md5_sha1
SCOSSL_LOG_INFO(SCOSSL_ERR_F_TLS1PRF_DERIVE, SCOSSL_ERR_R_NOT_FIPS_ALGORITHM,
"Using Hmac algorithm MD5+SHA1 which is not FIPS compliant");
scError = SymCryptTlsPrf1_1(
ctx->pbSecret, ctx->cbSecret,
NULL, 0,
ctx->seed, ctx->cbSeed,
key, keylen);
}
else
{
if (ctx->pHmac == NULL)
{
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_TLS1PRF_DERIVE, ERR_R_INTERNAL_ERROR,
"Missing Digest");
return SCOSSL_FAILURE;
}
scError = SymCryptTlsPrf1_2(
ctx->pHmac,
ctx->pbSecret, ctx->cbSecret,
NULL, 0,
ctx->seed, ctx->cbSeed,
key, keylen);
}
if (scError != SYMCRYPT_NO_ERROR)
{
SCOSSL_LOG_SYMCRYPT_ERROR(SCOSSL_ERR_F_TLS1PRF_DERIVE, SCOSSL_ERR_R_SYMCRYPT_FAILURE,
"SymCryptTlsPrf1_x failed", scError);
return SCOSSL_FAILURE;
}
return SCOSSL_SUCCESS;
}
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -39,7 +39,7 @@ endif()
add_library(scossl_dynamic SHARED ${SCOSSL_SOURCES})
add_dependencies(scossl_dynamic scossl_common)
set_target_properties(scossl_dynamic PROPERTIES PUBLIC_HEADER ../inc/scossl.h)
set_target_properties(scossl_dynamic PROPERTIES PUBLIC_HEADER ../inc/e_scossl.h)
# target_link_libraries(scossl_dynamic ${OPENSSL_CRYPTO_LIBRARY})
target_include_directories(scossl_dynamic PUBLIC ../inc)
target_include_directories(scossl_dynamic PRIVATE ../src)

Просмотреть файл

@ -2,31 +2,20 @@
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "scossl_hkdf.h"
#include "e_scossl_hkdf.h"
#include <openssl/hmac.h>
#include <openssl/kdf.h>
#ifdef __cplusplus
extern "C" {
#endif
#define HKDF_MAXBUF 1024
typedef struct {
int mode;
const EVP_MD *md;
unsigned char *salt;
size_t salt_len;
unsigned char *key;
size_t key_len;
unsigned char info[HKDF_MAXBUF];
size_t info_len;
} SCOSSL_HKDF_PKEY_CTX;
SCOSSL_STATUS e_scossl_hkdf_init(_Inout_ EVP_PKEY_CTX *ctx)
_Use_decl_annotations_
SCOSSL_STATUS e_scossl_hkdf_init(EVP_PKEY_CTX *ctx)
{
SCOSSL_HKDF_PKEY_CTX *e_scossl_hkdf_context;
if ((e_scossl_hkdf_context = OPENSSL_zalloc(sizeof(*e_scossl_hkdf_context))) == NULL) {
SCOSSL_HKDF_CTX *e_scossl_hkdf_context;
if ((e_scossl_hkdf_context = scossl_hkdf_newctx()) == NULL) {
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_HKDF_INIT, ERR_R_MALLOC_FAILURE,
"OPENSSL_zalloc returned NULL");
return SCOSSL_FAILURE;
@ -35,24 +24,23 @@ SCOSSL_STATUS e_scossl_hkdf_init(_Inout_ EVP_PKEY_CTX *ctx)
return SCOSSL_SUCCESS;
}
void e_scossl_hkdf_cleanup(_Inout_ EVP_PKEY_CTX *ctx)
_Use_decl_annotations_
void e_scossl_hkdf_cleanup(EVP_PKEY_CTX *ctx)
{
SCOSSL_HKDF_PKEY_CTX *e_scossl_hkdf_context = NULL;
SCOSSL_HKDF_CTX *e_scossl_hkdf_context = NULL;
e_scossl_hkdf_context = (SCOSSL_HKDF_PKEY_CTX *)EVP_PKEY_CTX_get_data(ctx);
if (e_scossl_hkdf_context == NULL) {
e_scossl_hkdf_context = (SCOSSL_HKDF_CTX *)EVP_PKEY_CTX_get_data(ctx);
if (e_scossl_hkdf_context == NULL)
return;
}
OPENSSL_clear_free(e_scossl_hkdf_context->salt, e_scossl_hkdf_context->salt_len);
OPENSSL_clear_free(e_scossl_hkdf_context->key, e_scossl_hkdf_context->key_len);
OPENSSL_cleanse(e_scossl_hkdf_context->info, e_scossl_hkdf_context->info_len);
OPENSSL_free(e_scossl_hkdf_context);
scossl_hkdf_freectx(e_scossl_hkdf_context);
EVP_PKEY_CTX_set_data(ctx, NULL);
}
_Use_decl_annotations_
SCOSSL_STATUS e_scossl_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
SCOSSL_HKDF_PKEY_CTX *e_scossl_hkdf_context = (SCOSSL_HKDF_PKEY_CTX *)EVP_PKEY_CTX_get_data(ctx);
SCOSSL_HKDF_CTX *e_scossl_hkdf_context = (SCOSSL_HKDF_CTX *)EVP_PKEY_CTX_get_data(ctx);
switch (type) {
case EVP_PKEY_CTRL_HKDF_MD:
if (p2 == NULL)
@ -67,31 +55,27 @@ SCOSSL_STATUS e_scossl_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return SCOSSL_SUCCESS;
if (p1 < 0)
return SCOSSL_FAILURE;
if (e_scossl_hkdf_context->salt != NULL)
OPENSSL_clear_free(e_scossl_hkdf_context->salt, e_scossl_hkdf_context->salt_len);
e_scossl_hkdf_context->salt = OPENSSL_memdup(p2, p1);
if (e_scossl_hkdf_context->salt == NULL)
if (e_scossl_hkdf_context->pbSalt != NULL)
OPENSSL_clear_free(e_scossl_hkdf_context->pbSalt, e_scossl_hkdf_context->cbSalt);
e_scossl_hkdf_context->pbSalt = OPENSSL_memdup(p2, p1);
if (e_scossl_hkdf_context->pbSalt == NULL)
return SCOSSL_FAILURE;
e_scossl_hkdf_context->salt_len = p1;
e_scossl_hkdf_context->cbSalt = p1;
return SCOSSL_SUCCESS;
case EVP_PKEY_CTRL_HKDF_KEY:
if (p1 < 0)
return SCOSSL_FAILURE;
if (e_scossl_hkdf_context->key != NULL)
OPENSSL_clear_free(e_scossl_hkdf_context->key, e_scossl_hkdf_context->key_len);
e_scossl_hkdf_context->key = OPENSSL_memdup(p2, p1);
if (e_scossl_hkdf_context->key == NULL)
if (e_scossl_hkdf_context->pbKey != NULL)
OPENSSL_clear_free(e_scossl_hkdf_context->pbKey, e_scossl_hkdf_context->cbKey);
e_scossl_hkdf_context->pbKey = OPENSSL_memdup(p2, p1);
if (e_scossl_hkdf_context->pbKey == NULL)
return SCOSSL_FAILURE;
e_scossl_hkdf_context->key_len = p1;
e_scossl_hkdf_context->cbKey = p1;
return SCOSSL_SUCCESS;
case EVP_PKEY_CTRL_HKDF_INFO:
if (p1 == 0 || p2 == NULL)
return SCOSSL_SUCCESS;
if (p1 < 0 || p1 > (int)(HKDF_MAXBUF - e_scossl_hkdf_context->info_len))
return SCOSSL_FAILURE;
memcpy(e_scossl_hkdf_context->info + e_scossl_hkdf_context->info_len, p2, p1);
e_scossl_hkdf_context->info_len += p1;
return SCOSSL_SUCCESS;
return scossl_hkdf_append_info(e_scossl_hkdf_context, p2, p1);
default:
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_HKDF_CTRL, SCOSSL_ERR_R_NOT_IMPLEMENTED,
"SymCrypt Engine does not support ctrl type (%d)", type);
@ -99,16 +83,16 @@ SCOSSL_STATUS e_scossl_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
}
}
SCOSSL_STATUS e_scossl_hkdf_derive_init(_Inout_ EVP_PKEY_CTX *ctx)
_Use_decl_annotations_
SCOSSL_STATUS e_scossl_hkdf_derive_init(EVP_PKEY_CTX *ctx)
{
SCOSSL_HKDF_PKEY_CTX *e_scossl_hkdf_context = (SCOSSL_HKDF_PKEY_CTX *)EVP_PKEY_CTX_get_data(ctx);
OPENSSL_clear_free(e_scossl_hkdf_context->key, e_scossl_hkdf_context->key_len);
OPENSSL_clear_free(e_scossl_hkdf_context->salt, e_scossl_hkdf_context->salt_len);
OPENSSL_cleanse(e_scossl_hkdf_context->info, e_scossl_hkdf_context->info_len);
memset(e_scossl_hkdf_context, 0, sizeof(*e_scossl_hkdf_context));
return SCOSSL_SUCCESS;
SCOSSL_HKDF_CTX *e_scossl_hkdf_context = (SCOSSL_HKDF_CTX *)EVP_PKEY_CTX_get_data(ctx);
return scossl_hkdf_reset(e_scossl_hkdf_context);
}
//
// Default OpenSSL fallback functions
//
static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
@ -206,140 +190,64 @@ static unsigned char *HKDF(const EVP_MD *evp_md,
return ret;
}
static PCSYMCRYPT_MAC e_scossl_get_symcrypt_mac_algorithm( _In_ const EVP_MD *evp_md )
_Use_decl_annotations_
SCOSSL_STATUS e_scossl_hkdf_derive(EVP_PKEY_CTX *ctx,
unsigned char *key, size_t *keylen)
{
int type = EVP_MD_type(evp_md);
SCOSSL_HKDF_CTX *e_scossl_hkdf_context = (SCOSSL_HKDF_CTX *)EVP_PKEY_CTX_get_data(ctx);
if (type == NID_sha1)
return SymCryptHmacSha1Algorithm;
if (type == NID_sha256)
return SymCryptHmacSha256Algorithm;
if (type == NID_sha384)
return SymCryptHmacSha384Algorithm;
if (type == NID_sha512)
return SymCryptHmacSha512Algorithm;
// if (type == NID_AES_CMC)
// return SymCryptAesCmacAlgorithm;
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_GET_SYMCRYPT_MAC_ALGORITHM, SCOSSL_ERR_R_NOT_IMPLEMENTED,
"SymCrypt engine does not support Mac algorithm %d", type);
return NULL;
}
SCOSSL_STATUS e_scossl_hkdf_derive(_Inout_ EVP_PKEY_CTX *ctx, _Out_writes_opt_(*keylen) unsigned char *key,
_Inout_ size_t *keylen)
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
SCOSSL_HKDF_PKEY_CTX *e_scossl_hkdf_context = (SCOSSL_HKDF_PKEY_CTX *)EVP_PKEY_CTX_get_data(ctx);
PCSYMCRYPT_MAC e_scossl_mac_algo = NULL;
SYMCRYPT_HKDF_EXPANDED_KEY scExpandedKey;
if (e_scossl_hkdf_context->md == NULL) {
if (e_scossl_hkdf_context->md == NULL)
{
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_HKDF_DERIVE, ERR_R_INTERNAL_ERROR,
"Missing Digest");
return SCOSSL_FAILURE;
}
e_scossl_mac_algo = e_scossl_get_symcrypt_mac_algorithm(e_scossl_hkdf_context->md);
if (e_scossl_hkdf_context->key == NULL) {
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_HKDF_DERIVE, ERR_R_INTERNAL_ERROR,
"Missing Key");
"Missing Digest");
return SCOSSL_FAILURE;
}
switch (e_scossl_hkdf_context->mode) {
case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
if( e_scossl_mac_algo != NULL )
{
scError = SymCryptHkdf(
e_scossl_mac_algo,
e_scossl_hkdf_context->key, e_scossl_hkdf_context->key_len,
e_scossl_hkdf_context->salt, e_scossl_hkdf_context->salt_len,
e_scossl_hkdf_context->info, e_scossl_hkdf_context->info_len,
key, *keylen);
if (scError != SYMCRYPT_NO_ERROR)
{
return SCOSSL_FAILURE;
}
}
else
{
SCOSSL_LOG_INFO(SCOSSL_ERR_F_HKDF_DERIVE, SCOSSL_ERR_R_OPENSSL_FALLBACK,
"SymCrypt engine does not support Mac algorithm %d - falling back to OpenSSL", EVP_MD_type(e_scossl_hkdf_context->md));
if (e_scossl_hkdf_context->pbKey == NULL)
{
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_HKDF_DERIVE, ERR_R_INTERNAL_ERROR,
"Missing Key");
return SCOSSL_FAILURE;
}
return HKDF(
e_scossl_hkdf_context->md,
e_scossl_hkdf_context->salt, e_scossl_hkdf_context->salt_len,
e_scossl_hkdf_context->key, e_scossl_hkdf_context->key_len,
e_scossl_hkdf_context->info, e_scossl_hkdf_context->info_len,
key, *keylen) != NULL;
}
return SCOSSL_SUCCESS;
case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
if (key == NULL) {
if (scossl_is_md_supported(EVP_MD_type(e_scossl_hkdf_context->md)))
{
if (e_scossl_hkdf_context->mode == EVP_KDF_HKDF_MODE_EXTRACT_ONLY && key == NULL)
{
*keylen = EVP_MD_size(e_scossl_hkdf_context->md);
return SCOSSL_SUCCESS;
}
if( e_scossl_mac_algo != NULL )
{
scError = SymCryptHkdfExtractPrk(
e_scossl_mac_algo,
e_scossl_hkdf_context->key, e_scossl_hkdf_context->key_len,
e_scossl_hkdf_context->salt, e_scossl_hkdf_context->salt_len,
key, *keylen );
if (scError != SYMCRYPT_NO_ERROR)
{
return SCOSSL_FAILURE;
}
}
else
{
SCOSSL_LOG_INFO(SCOSSL_ERR_F_HKDF_DERIVE, SCOSSL_ERR_R_OPENSSL_FALLBACK,
"SymCrypt engine does not support Mac algorithm %d - falling back to OpenSSL", EVP_MD_type(e_scossl_hkdf_context->md));
return HKDF_Extract(
e_scossl_hkdf_context->md,
e_scossl_hkdf_context->salt, e_scossl_hkdf_context->salt_len,
e_scossl_hkdf_context->key, e_scossl_hkdf_context->key_len,
key, keylen) != NULL;
}
return SCOSSL_SUCCESS;
case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
if( e_scossl_mac_algo != NULL )
{
scError = SymCryptHkdfPrkExpandKey(
&scExpandedKey,
e_scossl_mac_algo,
e_scossl_hkdf_context->key, e_scossl_hkdf_context->key_len );
if (scError != SYMCRYPT_NO_ERROR)
{
return SCOSSL_FAILURE;
}
scError = SymCryptHkdfDerive(
&scExpandedKey,
e_scossl_hkdf_context->info, e_scossl_hkdf_context->info_len,
key,
*keylen);
if (scError != SYMCRYPT_NO_ERROR)
{
return SCOSSL_FAILURE;
}
}
else
{
SCOSSL_LOG_INFO(SCOSSL_ERR_F_HKDF_DERIVE, SCOSSL_ERR_R_OPENSSL_FALLBACK,
"SymCrypt engine does not support Mac algorithm %d - falling back to OpenSSL", EVP_MD_type(e_scossl_hkdf_context->md));
return HKDF_Expand(
e_scossl_hkdf_context->md,
e_scossl_hkdf_context->key, e_scossl_hkdf_context->key_len,
e_scossl_hkdf_context->info, e_scossl_hkdf_context->info_len,
key, *keylen) != NULL;
}
return SCOSSL_SUCCESS;
default:
return SCOSSL_FAILURE;
return scossl_hkdf_derive(e_scossl_hkdf_context, key, *keylen);
}
SCOSSL_LOG_INFO(SCOSSL_ERR_F_HKDF_DERIVE, SCOSSL_ERR_R_OPENSSL_FALLBACK,
"SymCrypt engine does not support Hmac algorithm %d - falling back to OpenSSL", EVP_MD_type(e_scossl_hkdf_context->md));
switch (e_scossl_hkdf_context->mode)
{
case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
return HKDF(
e_scossl_hkdf_context->md,
e_scossl_hkdf_context->pbSalt, e_scossl_hkdf_context->cbSalt,
e_scossl_hkdf_context->pbKey, e_scossl_hkdf_context->cbKey,
e_scossl_hkdf_context->info, e_scossl_hkdf_context->cbInfo,
key, *keylen) != NULL;
case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
return HKDF_Extract(
e_scossl_hkdf_context->md,
e_scossl_hkdf_context->pbSalt, e_scossl_hkdf_context->cbSalt,
e_scossl_hkdf_context->pbKey, e_scossl_hkdf_context->cbKey,
key, keylen) != NULL;
case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
return HKDF_Expand(
e_scossl_hkdf_context->md,
e_scossl_hkdf_context->pbKey, e_scossl_hkdf_context->cbKey,
e_scossl_hkdf_context->info, e_scossl_hkdf_context->cbInfo,
key, *keylen) != NULL;
}
return SCOSSL_FAILURE;
}
#ifdef __cplusplus

Просмотреть файл

@ -28,8 +28,8 @@ SCOSSL_STATUS e_scossl_hkdf_derive_init(_Inout_ EVP_PKEY_CTX *ctx);
// is written to the keylen parameter. If key is not NULL, then keylen should contain the length of
// the key buffer, the shared secret is written to key and the amount of data written to keylen.
// Returns SCOSSL_SUCCESS on success, or SCOSSL_FAILURE or a negative value for failure.
SCOSSL_STATUS e_scossl_hkdf_derive(_Inout_ EVP_PKEY_CTX *ctx, _Out_writes_opt_(*keylen) unsigned char *key,
_Inout_ size_t *keylen);
SCOSSL_STATUS e_scossl_hkdf_derive(_Inout_ EVP_PKEY_CTX *ctx,
_Out_writes_opt_(*keylen) unsigned char *key, _Inout_ size_t *keylen);
#ifdef __cplusplus
}

Просмотреть файл

@ -89,7 +89,7 @@ SCOSSL_STATUS e_scossl_sshkdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
case EVP_KDF_CTRL_SET_MD:
md = va_arg(args, EVP_MD*);
impl->pHash = e_scossl_get_symcrypt_hash_algorithm(md);
impl->pHash = e_scossl_get_symcrypt_hash_algorithm(EVP_MD_type(md));
if(!impl->pHash) {
ret = SCOSSL_FAILURE;

Просмотреть файл

@ -2,168 +2,97 @@
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "scossl_tls1prf.h"
#include "e_scossl_tls1prf.h"
#include <openssl/kdf.h>
#ifdef __cplusplus
extern "C" {
#endif
#define TLS1_PRF_MAXBUF 1024
/* TLS KDF pkey context structure */
typedef struct {
/* Digest to use for PRF */
const EVP_MD *md;
/* Secret value to use for PRF */
unsigned char *secret;
size_t secret_length;
/* Buffer of concatenated seed data */
unsigned char seed[TLS1_PRF_MAXBUF];
size_t seed_length;
} SCOSSL_TLS1_PRF_PKEY_CTX;
SCOSSL_STATUS e_scossl_tls1prf_init(_Inout_ EVP_PKEY_CTX *ctx)
_Use_decl_annotations_
SCOSSL_STATUS e_scossl_tls1prf_init(EVP_PKEY_CTX *ctx)
{
SCOSSL_TLS1_PRF_PKEY_CTX *key_context = NULL;
if ((key_context = OPENSSL_zalloc(sizeof(*key_context))) == NULL) {
SCOSSL_TLS1_PRF_CTX *key_context = NULL;
if ((key_context = scossl_tls1prf_newctx()) == NULL)
{
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_TLS1PRF_INIT, ERR_R_MALLOC_FAILURE,
"OPENSSL_zalloc return NULL");
"OPENSSL_zalloc return NULL");
return SCOSSL_FAILURE;
}
EVP_PKEY_CTX_set_data(ctx, key_context);
return SCOSSL_SUCCESS;
}
void e_scossl_tls1prf_cleanup(_Inout_ EVP_PKEY_CTX *ctx)
_Use_decl_annotations_
void e_scossl_tls1prf_cleanup(EVP_PKEY_CTX *ctx)
{
SCOSSL_TLS1_PRF_PKEY_CTX *key_context = (SCOSSL_TLS1_PRF_PKEY_CTX *)EVP_PKEY_CTX_get_data(ctx);
if (key_context == NULL) {
SCOSSL_TLS1_PRF_CTX *key_context = (SCOSSL_TLS1_PRF_CTX *)EVP_PKEY_CTX_get_data(ctx);
if (key_context == NULL)
return;
}
OPENSSL_clear_free(key_context->secret, key_context->secret_length);
OPENSSL_cleanse(key_context->seed, key_context->seed_length);
OPENSSL_free(key_context);
scossl_tls1prf_freectx(key_context);
EVP_PKEY_CTX_set_data(ctx, NULL);
}
SCOSSL_STATUS e_scossl_tls1prf_ctrl(_Inout_ EVP_PKEY_CTX *ctx, int type, int p1, _In_ void *p2)
_Use_decl_annotations_
SCOSSL_STATUS e_scossl_tls1prf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
SCOSSL_TLS1_PRF_PKEY_CTX *key_context = (SCOSSL_TLS1_PRF_PKEY_CTX *)EVP_PKEY_CTX_get_data(ctx);
SCOSSL_TLS1_PRF_CTX *key_context = (SCOSSL_TLS1_PRF_CTX *)EVP_PKEY_CTX_get_data(ctx);
PCSYMCRYPT_MAC symcryptHmacAlg = NULL;
BOOL isTlsPrf1_1 = TRUE;
switch (type) {
switch (type)
{
case EVP_PKEY_CTRL_TLS_MD:
key_context->md = p2;
// Special case to always allow md5_sha1 for tls1.1 PRF compat
if (EVP_MD_type(p2) != NID_md5_sha1)
{
if ((symcryptHmacAlg = scossl_get_symcrypt_hmac_algorithm(EVP_MD_type(p2))) == NULL)
return SCOSSL_FAILURE;
isTlsPrf1_1 = FALSE;
}
key_context->pHmac = symcryptHmacAlg;
key_context->isTlsPrf1_1 = isTlsPrf1_1;
return SCOSSL_SUCCESS;
case EVP_PKEY_CTRL_TLS_SECRET:
if (p1 < 0)
return SCOSSL_FAILURE;
if (key_context->secret != NULL)
OPENSSL_clear_free(key_context->secret, key_context->secret_length);
OPENSSL_cleanse(key_context->seed, key_context->seed_length);
key_context->seed_length = 0;
key_context->secret = OPENSSL_memdup(p2, p1);
if (key_context->secret == NULL)
if (key_context->pbSecret != NULL)
OPENSSL_clear_free(key_context->pbSecret, key_context->cbSecret);
OPENSSL_cleanse(key_context->seed, key_context->cbSeed);
key_context->cbSeed = 0;
key_context->pbSecret = OPENSSL_memdup(p2, p1);
if (key_context->pbSecret == NULL)
return SCOSSL_FAILURE;
key_context->secret_length = p1;
key_context->cbSecret = p1;
return SCOSSL_SUCCESS;
case EVP_PKEY_CTRL_TLS_SEED:
if (p1 == 0 || p2 == NULL)
return SCOSSL_SUCCESS;
if (p1 < 0 || p1 > (int)(TLS1_PRF_MAXBUF - key_context->seed_length))
return SCOSSL_FAILURE;
memcpy(key_context->seed + key_context->seed_length, p2, p1);
key_context->seed_length += p1;
return SCOSSL_SUCCESS;
return scossl_tls1prf_append_seed(key_context, p2, p1);
default:
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_TLS1PRF_CTRL, SCOSSL_ERR_R_NOT_IMPLEMENTED,
"SymCrypt Engine does not support ctrl type (%d)", type);
"SymCrypt Engine does not support ctrl type (%d)", type);
return SCOSSL_UNSUPPORTED;
}
}
SCOSSL_STATUS e_scossl_tls1prf_derive_init(_Inout_ EVP_PKEY_CTX *ctx)
_Use_decl_annotations_
SCOSSL_STATUS e_scossl_tls1prf_derive_init(EVP_PKEY_CTX *ctx)
{
SCOSSL_TLS1_PRF_PKEY_CTX *key_context = (SCOSSL_TLS1_PRF_PKEY_CTX *)EVP_PKEY_CTX_get_data(ctx);
OPENSSL_clear_free(key_context->secret, key_context->secret_length);
OPENSSL_cleanse(key_context->seed, key_context->seed_length);
memset(key_context, 0, sizeof(*key_context));
return SCOSSL_SUCCESS;
SCOSSL_TLS1_PRF_CTX *key_context = (SCOSSL_TLS1_PRF_CTX *)EVP_PKEY_CTX_get_data(ctx);
return scossl_tls1prf_reset(key_context);
}
static PCSYMCRYPT_MAC e_scossl_get_symcrypt_mac_algorithm(const EVP_MD *evp_md)
_Use_decl_annotations_
SCOSSL_STATUS e_scossl_tls1prf_derive(EVP_PKEY_CTX *ctx,
unsigned char *key, size_t *keylen)
{
int type = EVP_MD_type(evp_md);
if (type == NID_sha1)
return SymCryptHmacSha1Algorithm;
if (type == NID_sha256)
return SymCryptHmacSha256Algorithm;
if (type == NID_sha384)
return SymCryptHmacSha384Algorithm;
if (type == NID_sha512)
return SymCryptHmacSha512Algorithm;
// if (type == NID_AES_CMC)
// return SymCryptAesCmacAlgorithm;
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_GET_SYMCRYPT_MAC_ALGORITHM, SCOSSL_ERR_R_NOT_IMPLEMENTED,
"SymCrypt engine does not support Mac algorithm %d", type);
return NULL;
}
SCOSSL_STATUS e_scossl_tls1prf_derive(_Inout_ EVP_PKEY_CTX *ctx, _Out_writes_opt_(*keylen) unsigned char *key,
_Inout_ size_t *keylen)
{
SCOSSL_TLS1_PRF_PKEY_CTX *key_context = (SCOSSL_TLS1_PRF_PKEY_CTX *)EVP_PKEY_CTX_get_data(ctx);
PCSYMCRYPT_MAC e_scossl_mac_algo = NULL;
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
if (key_context->md == NULL) {
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_TLS1PRF_DERIVE, ERR_R_INTERNAL_ERROR,
"Missing Digest");
return SCOSSL_FAILURE;
}
if (key_context->secret == NULL) {
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_TLS1PRF_DERIVE, ERR_R_INTERNAL_ERROR,
"Missing Secret");
return SCOSSL_FAILURE;
}
if( EVP_MD_type(key_context->md) == NID_md5_sha1 )
{
// Special case to use TlsPrf1_1 to handle md5_sha1
SCOSSL_LOG_INFO(SCOSSL_ERR_F_TLS1PRF_DERIVE, SCOSSL_ERR_R_NOT_FIPS_ALGORITHM,
"Using Mac algorithm MD5+SHA1 which is not FIPS compliant");
scError = SymCryptTlsPrf1_1(
key_context->secret, key_context->secret_length,
NULL, 0,
key_context->seed, key_context->seed_length,
key, *keylen);
}
else
{
e_scossl_mac_algo = e_scossl_get_symcrypt_mac_algorithm(key_context->md);
if( e_scossl_mac_algo == NULL )
{
return SCOSSL_FAILURE;
}
scError = SymCryptTlsPrf1_2(
e_scossl_mac_algo,
key_context->secret, key_context->secret_length,
NULL, 0,
key_context->seed, key_context->seed_length,
key, *keylen);
}
if (scError != SYMCRYPT_NO_ERROR)
{
SCOSSL_LOG_SYMCRYPT_ERROR(SCOSSL_ERR_F_TLS1PRF_DERIVE, SCOSSL_ERR_R_SYMCRYPT_FAILURE,
"SymCryptTlsPrf1_x failed", scError);
return SCOSSL_FAILURE;
}
return SCOSSL_SUCCESS;
SCOSSL_TLS1_PRF_CTX *key_context = (SCOSSL_TLS1_PRF_CTX *)EVP_PKEY_CTX_get_data(ctx);
return scossl_tls1prf_derive(key_context, key, *keylen);
}
#ifdef __cplusplus

Просмотреть файл

@ -24,12 +24,12 @@ SCOSSL_STATUS e_scossl_tls1prf_ctrl(_Inout_ EVP_PKEY_CTX *ctx, int type, int p1,
// Returns SCOSSL_SUCCESS on success or SCOSSL_FAILURE on error.
SCOSSL_STATUS e_scossl_tls1prf_derive_init(_Inout_ EVP_PKEY_CTX *ctx);
// Derives a shared secret using ctx. If key is NULL then the maximum size of the output buffer
// is written to the keylen parameter. If key is not NULL, then keylen should contain the length of
// the key buffer, the shared secret is written to key and the amount of data written to keylen.
// Derives a shared secret using ctx.
// NOTE: The documentation states that if the key is NULL, then keylen will be set to the maximum size of
// the output buffer. This is not true for TLS1-PRF, and the keylen is always expected.
// Returns SCOSSL_SUCCESS on success, or SCOSSL_FAILURE on error.
SCOSSL_STATUS e_scossl_tls1prf_derive(_Inout_ EVP_PKEY_CTX *ctx, _Out_writes_opt_(*keylen) unsigned char *key,
_Inout_ size_t *keylen);
SCOSSL_STATUS e_scossl_tls1prf_derive(_Inout_ EVP_PKEY_CTX *ctx,
_Out_writes_bytes_(*keylen) unsigned char *key, _In_ size_t *keylen);
#ifdef __cplusplus
}

Просмотреть файл

@ -38,7 +38,7 @@ endif()
add_library(scossl_static STATIC ${SCOSSL_SOURCES})
add_dependencies(scossl_static scossl_common)
set_target_properties(scossl_static PROPERTIES PUBLIC_HEADER ../inc/scossl.h)
set_target_properties(scossl_static PROPERTIES PUBLIC_HEADER ../inc/e_scossl.h)
# target_link_libraries(scossl_static ${OPENSSL_CRYPTO_LIBRARY})
target_include_directories(scossl_static PUBLIC ../inc)
target_include_directories(scossl_static PRIVATE ../src)

Просмотреть файл

@ -21,6 +21,9 @@ set(SCOSSL_SOURCES
./src/ciphers/p_scossl_aes.c
./src/ciphers/p_scossl_aes_aead.c
# ./src/ciphers/p_scossl_aes_xts.c
./src/kdf/p_scossl_hkdf.c
./src/kdf/p_scossl_sshkdf.c
./src/kdf/p_scossl_tls1prf.c
./src/keyexch/p_scossl_ecdh.c
./src/keymgmt/p_scossl_ecc_keymgmt.c
./src/keymgmt/p_scossl_rsa_keymgmt.c

Просмотреть файл

@ -0,0 +1,354 @@
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "scossl_hkdf.h"
#include "p_scossl_base.h"
#include <openssl/proverr.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
// Needed for fetching md
OSSL_LIB_CTX *libctx;
SCOSSL_HKDF_CTX *hkdfCtx;
} SCOSSL_PROV_HKDF_CTX;
#define HKDF_MODE_EXTRACT_AND_EXPAND "EXTRACT_AND_EXPAND"
#define HKDF_MODE_EXTRACT_ONLY "EXTRACT_ONLY"
#define HKDF_MODE_EXPAND_ONLY "EXPAND_ONLY"
static const OSSL_PARAM p_scossl_hkdf_gettable_ctx_param_types[] = {
OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0),
OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0),
OSSL_PARAM_END};
static const OSSL_PARAM p_scossl_hkdf_settable_ctx_param_types[] = {
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0),
OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0),
OSSL_PARAM_END};
static SCOSSL_STATUS p_scossl_hkdf_set_ctx_params(_Inout_ SCOSSL_PROV_HKDF_CTX *ctx, const _In_ OSSL_PARAM params[]);
static SCOSSL_PROV_HKDF_CTX *p_scossl_hkdf_newctx(_In_ SCOSSL_PROVCTX *provctx)
{
SCOSSL_PROV_HKDF_CTX *ctx = OPENSSL_malloc(sizeof(SCOSSL_PROV_HKDF_CTX));
if (ctx != NULL)
{
if ((ctx->hkdfCtx = scossl_hkdf_newctx()) == NULL)
{
OPENSSL_free(ctx);
return NULL;
}
ctx->libctx = provctx->libctx;
}
return ctx;
}
static void p_scossl_hkdf_freectx(_Inout_ SCOSSL_PROV_HKDF_CTX *ctx)
{
if (ctx != NULL)
{
EVP_MD_free(ctx->hkdfCtx->md);
scossl_hkdf_freectx(ctx->hkdfCtx);
}
OPENSSL_free(ctx);
}
static SCOSSL_PROV_HKDF_CTX *p_scossl_hkdf_dupctx(_In_ SCOSSL_PROV_HKDF_CTX *ctx)
{
SCOSSL_PROV_HKDF_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_PROV_HKDF_CTX));
if (copyCtx != NULL)
{
if ((copyCtx->hkdfCtx = scossl_hkdf_dupctx(ctx->hkdfCtx)) == NULL ||
(ctx->hkdfCtx->md != NULL && !EVP_MD_up_ref(ctx->hkdfCtx->md)))
{
scossl_hkdf_freectx(copyCtx->hkdfCtx);
OPENSSL_free(copyCtx);
return NULL;
}
copyCtx->libctx = ctx->libctx;
}
return copyCtx;
}
static SCOSSL_STATUS p_scossl_hkdf_reset(_Inout_ SCOSSL_PROV_HKDF_CTX *ctx)
{
EVP_MD_free(ctx->hkdfCtx->md);
return scossl_hkdf_reset(ctx->hkdfCtx);
}
static SCOSSL_STATUS p_scossl_hkdf_derive(_In_ SCOSSL_PROV_HKDF_CTX *ctx,
_Out_writes_bytes_(keylen) unsigned char *key, size_t keylen,
_In_ const OSSL_PARAM params[])
{
return p_scossl_hkdf_set_ctx_params(ctx, params) &&
scossl_hkdf_derive(ctx->hkdfCtx, key, keylen);
}
static const OSSL_PARAM *p_scossl_hkdf_gettable_ctx_params(ossl_unused void *ctx, ossl_unused void *provctx)
{
return p_scossl_hkdf_gettable_ctx_param_types;
}
static const OSSL_PARAM *p_scossl_hkdf_settable_ctx_params(ossl_unused void *ctx, ossl_unused void *provctx)
{
return p_scossl_hkdf_settable_ctx_param_types;
}
static SCOSSL_STATUS p_scossl_hkdf_get_ctx_params(_In_ SCOSSL_PROV_HKDF_CTX *ctx, _Inout_ OSSL_PARAM params[])
{
OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
{
SIZE_T cbResult;
if (ctx->hkdfCtx->mode == EVP_KDF_HKDF_MODE_EXTRACT_ONLY)
{
if (ctx->hkdfCtx->md == NULL)
{
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
return SCOSSL_FAILURE;
}
cbResult = EVP_MD_get_size(ctx->hkdfCtx->md);
}
else
{
cbResult = SIZE_MAX;
}
if (!OSSL_PARAM_set_size_t(p, cbResult))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_MODE)) != NULL)
{
if (p->data_type == OSSL_PARAM_UTF8_STRING)
{
const char *mode = NULL;
switch (ctx->hkdfCtx->mode)
{
case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
mode = HKDF_MODE_EXTRACT_AND_EXPAND;
break;
case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
mode = HKDF_MODE_EXTRACT_ONLY;
break;
case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
mode = HKDF_MODE_EXPAND_ONLY;
break;
}
if (mode == NULL ||
!OSSL_PARAM_set_utf8_string(p, mode))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
}
else if (!OSSL_PARAM_set_int(p, ctx->hkdfCtx->mode))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_DIGEST)) != NULL &&
!OSSL_PARAM_set_utf8_string(p, ctx->hkdfCtx->md == NULL ? "" : EVP_MD_get0_name(ctx->hkdfCtx->md)))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SALT)) != NULL &&
!OSSL_PARAM_set_octet_string(p, ctx->hkdfCtx->pbSalt, ctx->hkdfCtx->cbSalt))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_KEY)) != NULL &&
!OSSL_PARAM_set_octet_string(p, ctx->hkdfCtx->pbKey, ctx->hkdfCtx->cbKey))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_INFO)) != NULL &&
!OSSL_PARAM_set_octet_string(p, ctx->hkdfCtx->info, ctx->hkdfCtx->cbInfo))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
return SCOSSL_SUCCESS;
}
static SCOSSL_STATUS p_scossl_hkdf_set_ctx_params(_Inout_ SCOSSL_PROV_HKDF_CTX *ctx, const _In_ OSSL_PARAM params[])
{
PCBYTE pbInfo;
SIZE_T cbInfo;
const OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE)) != NULL)
{
int mode = -1;
if (p->data_type == OSSL_PARAM_UTF8_STRING)
{
if (OPENSSL_strcasecmp(p->data, HKDF_MODE_EXTRACT_AND_EXPAND) == 0)
{
mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND;
}
else if (OPENSSL_strcasecmp(p->data, HKDF_MODE_EXTRACT_ONLY) == 0)
{
mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY;
}
else if (OPENSSL_strcasecmp(p->data, HKDF_MODE_EXPAND_ONLY) == 0)
{
mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY;
}
}
else if (!OSSL_PARAM_get_int(p, &mode))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
if (mode < EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND || mode > EVP_KDF_HKDF_MODE_EXPAND_ONLY)
{
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
return SCOSSL_FAILURE;
}
ctx->hkdfCtx->mode = mode;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL)
{
const OSSL_PARAM *param_propq;
const char *mdName, *mdProps;
EVP_MD *md;
if (!OSSL_PARAM_get_utf8_string_ptr(p, &mdName))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
mdProps = NULL;
param_propq = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
if (param_propq != NULL &&
!OSSL_PARAM_get_utf8_string_ptr(p, &mdProps))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
md = EVP_MD_fetch(ctx->libctx, mdName, mdProps);
if (md == NULL ||
!scossl_is_md_supported(EVP_MD_type(md)))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
EVP_MD_free(ctx->hkdfCtx->md);
ctx->hkdfCtx->md = md;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
{
PBYTE pbSalt = NULL;
SIZE_T cbSalt = 0;
if (p->data_size > 0 &&
!OSSL_PARAM_get_octet_string(p, (void **)&pbSalt, 0, &cbSalt))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
OPENSSL_clear_free(ctx->hkdfCtx->pbSalt, ctx->hkdfCtx->cbSalt);
ctx->hkdfCtx->pbSalt = pbSalt;
ctx->hkdfCtx->cbSalt = cbSalt;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL)
{
PBYTE pbKey = NULL;
SIZE_T cbKey = 0;
if (p->data_size > 0 &&
!OSSL_PARAM_get_octet_string(p, (void **)&pbKey, 0, &cbKey))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
OPENSSL_clear_free(ctx->hkdfCtx->pbKey, ctx->hkdfCtx->cbKey);
ctx->hkdfCtx->pbKey = pbKey;
ctx->hkdfCtx->cbKey = cbKey;
}
// Parameters may contain multiple info params that must all be processed
for (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO);
p != NULL;
p = OSSL_PARAM_locate_const(p + 1, OSSL_KDF_PARAM_INFO))
{
if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbInfo, &cbInfo))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
if (!scossl_hkdf_append_info(ctx->hkdfCtx, pbInfo, cbInfo))
{
ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE);
return SCOSSL_FAILURE;
}
}
return SCOSSL_SUCCESS;
}
const OSSL_DISPATCH p_scossl_hkdf_kdf_functions[] = {
{OSSL_FUNC_KDF_NEWCTX, (void (*)(void))p_scossl_hkdf_newctx},
{OSSL_FUNC_KDF_FREECTX, (void (*)(void))p_scossl_hkdf_freectx},
{OSSL_FUNC_KDF_DUPCTX, (void (*)(void))p_scossl_hkdf_dupctx},
{OSSL_FUNC_KDF_RESET, (void (*)(void))p_scossl_hkdf_reset},
{OSSL_FUNC_KDF_DERIVE, (void (*)(void))p_scossl_hkdf_derive},
{OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_hkdf_gettable_ctx_params},
{OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_hkdf_settable_ctx_params},
{OSSL_FUNC_KDF_GET_CTX_PARAMS, (void (*)(void))p_scossl_hkdf_get_ctx_params},
{OSSL_FUNC_KDF_SET_CTX_PARAMS, (void (*)(void))p_scossl_hkdf_set_ctx_params},
{0, NULL}};
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -0,0 +1,320 @@
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include "scossl_sshkdf.h"
#include "p_scossl_base.h"
#include <openssl/kdf.h>
#include <openssl/proverr.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
// Needed for fetching md
OSSL_LIB_CTX *libctx;
// Purely informational
char* mdName;
SCOSSL_SSHKDF_CTX *sshkdfCtx;
} SCOSSL_PROV_SSHKDF_CTX;
static const OSSL_PARAM p_scossl_sshkdf_gettable_ctx_param_types[] = {
OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_XCGHASH, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_SESSION_ID, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_SSHKDF_TYPE, NULL, 0),
OSSL_PARAM_END};
static const OSSL_PARAM p_scossl_sshkdf_settable_ctx_param_types[] = {
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_XCGHASH, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_SESSION_ID, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_SSHKDF_TYPE, NULL, 0),
OSSL_PARAM_END};
SCOSSL_STATUS p_scossl_sshkdf_set_ctx_params(_Inout_ SCOSSL_PROV_SSHKDF_CTX *ctx, _In_ const OSSL_PARAM params[]);
SCOSSL_PROV_SSHKDF_CTX *p_scossl_sshkdf_newctx(_In_ SCOSSL_PROVCTX *provctx)
{
SCOSSL_PROV_SSHKDF_CTX *ctx = OPENSSL_malloc(sizeof(SCOSSL_PROV_SSHKDF_CTX));
if (ctx != NULL)
{
if ((ctx->sshkdfCtx = scossl_sshkdf_newctx()) == NULL)
{
OPENSSL_free(ctx);
return NULL;
}
ctx->mdName = NULL;
ctx->libctx = provctx->libctx;
}
return ctx;
}
void p_scossl_sshkdf_freectx(_Inout_ SCOSSL_PROV_SSHKDF_CTX *ctx)
{
if (ctx != NULL)
{
OPENSSL_free(ctx->mdName);
scossl_sshkdf_freectx(ctx->sshkdfCtx);
}
OPENSSL_free(ctx);
}
SCOSSL_PROV_SSHKDF_CTX *p_scossl_sshkdf_dupctx(_In_ SCOSSL_PROV_SSHKDF_CTX *ctx)
{
SCOSSL_PROV_SSHKDF_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_PROV_SSHKDF_CTX));
if (copyCtx != NULL)
{
if ((copyCtx->sshkdfCtx = scossl_sshkdf_dupctx(ctx->sshkdfCtx)) == NULL)
{
OPENSSL_free(copyCtx);
return NULL;
}
copyCtx->libctx = ctx->libctx;
copyCtx->mdName = OPENSSL_strdup(ctx->mdName);
}
return copyCtx;
}
SCOSSL_STATUS p_scossl_sshkdf_reset(_Inout_ SCOSSL_PROV_SSHKDF_CTX *ctx)
{
OPENSSL_free(ctx->mdName);
ctx->mdName = NULL;
return scossl_sshkdf_reset(ctx->sshkdfCtx);
}
SCOSSL_STATUS p_scossl_sshkdf_derive(_In_ SCOSSL_PROV_SSHKDF_CTX *ctx,
_Out_writes_bytes_(keylen) unsigned char *key, size_t keylen,
_In_ const OSSL_PARAM params[])
{
return p_scossl_sshkdf_set_ctx_params(ctx, params) &&
scossl_sshkdf_derive(ctx->sshkdfCtx, key, keylen);
}
const OSSL_PARAM *p_scossl_sshkdf_gettable_ctx_params(ossl_unused void *ctx, ossl_unused void *provctx)
{
return p_scossl_sshkdf_gettable_ctx_param_types;
}
const OSSL_PARAM *p_scossl_sshkdf_settable_ctx_params(ossl_unused void *ctx, ossl_unused void *provctx)
{
return p_scossl_sshkdf_settable_ctx_param_types;
}
SCOSSL_STATUS p_scossl_sshkdf_get_ctx_params(_In_ SCOSSL_PROV_SSHKDF_CTX *ctx, _Inout_ OSSL_PARAM params[])
{
OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL &&
!OSSL_PARAM_set_size_t(p, SIZE_MAX))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_DIGEST)) != NULL &&
!OSSL_PARAM_set_utf8_string(p, ctx->mdName == NULL ? "" : ctx->mdName))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_KEY)) != NULL &&
!OSSL_PARAM_set_octet_string(p, ctx->sshkdfCtx->pbKey, ctx->sshkdfCtx->cbKey))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SSHKDF_XCGHASH)) != NULL &&
!OSSL_PARAM_set_octet_string(p, ctx->sshkdfCtx->hashValue, ctx->sshkdfCtx->cbHashValue))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SSHKDF_SESSION_ID)) != NULL &&
!OSSL_PARAM_set_octet_string(p, ctx->sshkdfCtx->sessionId, ctx->sshkdfCtx->cbSessionId))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SSHKDF_TYPE)) != NULL)
{
char *pData = p->data;
if (p->data_type != OSSL_PARAM_UTF8_STRING ||
p->data_size < 1)
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
pData[0] = ctx->sshkdfCtx->label;
p->return_size = 1;
}
return SCOSSL_SUCCESS;
}
SCOSSL_STATUS p_scossl_sshkdf_set_ctx_params(_Inout_ SCOSSL_PROV_SSHKDF_CTX *ctx, _In_ const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL)
{
PCSYMCRYPT_HASH symcryptHashAlg = NULL;
const char *paramMdName, *mdProps;
char *mdName;
EVP_MD *md;
if (!OSSL_PARAM_get_utf8_string_ptr(p, &paramMdName))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
mdProps = NULL;
p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
if (p != NULL &&
!OSSL_PARAM_get_utf8_string_ptr(p, &mdProps))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
if ((md = EVP_MD_fetch(ctx->libctx, paramMdName, mdProps)) == NULL)
{
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
return SCOSSL_FAILURE;
}
mdName = OPENSSL_strdup(EVP_MD_get0_name(md));
symcryptHashAlg = scossl_get_symcrypt_hash_algorithm(EVP_MD_type(md));
EVP_MD_free(md);
if (symcryptHashAlg == NULL)
{
OPENSSL_free(mdName);
return SCOSSL_FAILURE;
}
OPENSSL_free(ctx->mdName);
ctx->mdName = mdName;
ctx->sshkdfCtx->pHash = symcryptHashAlg;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL)
{
PBYTE pbKey = NULL;
SIZE_T cbKey = 0;
if (p->data_size > 0 &&
!OSSL_PARAM_get_octet_string(p, (void **)&pbKey, 0, &cbKey))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
OPENSSL_clear_free(ctx->sshkdfCtx->pbKey, ctx->sshkdfCtx->cbKey);
ctx->sshkdfCtx->pbKey = pbKey;
ctx->sshkdfCtx->cbKey = cbKey;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SSHKDF_XCGHASH)) != NULL)
{
PCBYTE pbHashValue;
SIZE_T cbHashValue;
if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbHashValue, &cbHashValue))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
if (cbHashValue > SSH_KDF_MAX_DIGEST_SIZE)
{
ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE);
return SCOSSL_FAILURE;
}
memcpy(ctx->sshkdfCtx->hashValue, pbHashValue, cbHashValue);
ctx->sshkdfCtx->cbHashValue = cbHashValue;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SSHKDF_SESSION_ID)) != NULL)
{
PCBYTE pbSessionId;
SIZE_T cbSessionId;
if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbSessionId, &cbSessionId))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
if (cbSessionId > SSH_KDF_MAX_DIGEST_SIZE)
{
ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE);
return SCOSSL_FAILURE;
}
memcpy(ctx->sshkdfCtx->sessionId, pbSessionId, cbSessionId);
ctx->sshkdfCtx->cbSessionId = cbSessionId;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SSHKDF_TYPE)) != NULL)
{
const char *type;
if (p->data_size != 1)
{
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH);
return SCOSSL_FAILURE;
}
if (!OSSL_PARAM_get_utf8_string_ptr(p, &type))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
if (type[0] < EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV ||
type[0] > EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_SRV_TO_CLI)
{
ERR_raise(ERR_LIB_PROV, PROV_R_VALUE_ERROR);
return 0;
}
ctx->sshkdfCtx->label = type[0];
}
return SCOSSL_SUCCESS;
}
const OSSL_DISPATCH p_scossl_sshkdf_kdf_functions[] = {
{OSSL_FUNC_KDF_NEWCTX, (void (*)(void))p_scossl_sshkdf_newctx},
{OSSL_FUNC_KDF_FREECTX, (void (*)(void))p_scossl_sshkdf_freectx},
{OSSL_FUNC_KDF_DUPCTX, (void (*)(void))p_scossl_sshkdf_dupctx},
{OSSL_FUNC_KDF_RESET, (void (*)(void))p_scossl_sshkdf_reset},
{OSSL_FUNC_KDF_DERIVE, (void (*)(void))p_scossl_sshkdf_derive},
{OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_sshkdf_gettable_ctx_params},
{OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_sshkdf_settable_ctx_params},
{OSSL_FUNC_KDF_GET_CTX_PARAMS, (void (*)(void))p_scossl_sshkdf_get_ctx_params},
{OSSL_FUNC_KDF_SET_CTX_PARAMS, (void (*)(void))p_scossl_sshkdf_set_ctx_params},
{0, NULL}};
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -0,0 +1,257 @@
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include <openssl/proverr.h>
#include "scossl_tls1prf.h"
#include "p_scossl_base.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
// Needed for fetching md
OSSL_LIB_CTX *libctx;
// Purely informational
char *mdName;
SCOSSL_TLS1_PRF_CTX *tls1prfCtx;
} SCOSSL_PROV_TLS1_PRF_CTX;
static const OSSL_PARAM p_scossl_tls1prf_gettable_ctx_param_types[] = {
OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SEED, NULL, 0),
OSSL_PARAM_END};
static const OSSL_PARAM p_scossl_tls1prf_settable_ctx_param_types[] = {
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SEED, NULL, 0),
OSSL_PARAM_END};
SCOSSL_STATUS p_scossl_tls1prf_set_ctx_params(_Inout_ SCOSSL_PROV_TLS1_PRF_CTX *ctx, _In_ const OSSL_PARAM params[]);
SCOSSL_PROV_TLS1_PRF_CTX *p_scossl_tls1prf_newctx(_In_ SCOSSL_PROVCTX *provctx)
{
SCOSSL_PROV_TLS1_PRF_CTX *ctx = OPENSSL_malloc(sizeof(SCOSSL_PROV_TLS1_PRF_CTX));
if (ctx != NULL)
{
if ((ctx->tls1prfCtx = scossl_tls1prf_newctx()) == NULL)
{
OPENSSL_free(ctx);
return NULL;
}
ctx->mdName = NULL;
ctx->libctx = provctx->libctx;
}
return ctx;
}
void p_scossl_tls1prf_freectx(_Inout_ SCOSSL_PROV_TLS1_PRF_CTX *ctx)
{
if (ctx != NULL)
{
scossl_tls1prf_freectx(ctx->tls1prfCtx);
}
OPENSSL_free(ctx);
}
SCOSSL_PROV_TLS1_PRF_CTX *p_scossl_tls1prf_dupctx(_In_ SCOSSL_PROV_TLS1_PRF_CTX *ctx)
{
SCOSSL_PROV_TLS1_PRF_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_PROV_TLS1_PRF_CTX));
if (copyCtx != NULL)
{
if ((copyCtx->tls1prfCtx = scossl_tls1prf_dupctx(ctx->tls1prfCtx)) == NULL)
{
OPENSSL_free(copyCtx);
return NULL;
}
copyCtx->mdName = OPENSSL_strdup(ctx->mdName);
copyCtx->libctx = ctx->libctx;
}
return copyCtx;
}
SCOSSL_STATUS p_scossl_tls1prf_reset(_Inout_ SCOSSL_PROV_TLS1_PRF_CTX *ctx)
{
OPENSSL_free(ctx->mdName);
ctx->mdName = NULL;
return scossl_tls1prf_reset(ctx->tls1prfCtx);
}
SCOSSL_STATUS p_scossl_tls1prf_derive(_In_ SCOSSL_PROV_TLS1_PRF_CTX *ctx,
_Out_writes_bytes_(keylen) unsigned char *key, size_t keylen,
_In_ const OSSL_PARAM params[])
{
return p_scossl_tls1prf_set_ctx_params(ctx, params) &&
scossl_tls1prf_derive(ctx->tls1prfCtx, key, keylen);
}
const OSSL_PARAM *p_scossl_tls1prf_gettable_ctx_params(ossl_unused void *ctx, ossl_unused void *provctx)
{
return p_scossl_tls1prf_gettable_ctx_param_types;
}
const OSSL_PARAM *p_scossl_tls1prf_settable_ctx_params(ossl_unused void *ctx, ossl_unused void *provctx)
{
return p_scossl_tls1prf_settable_ctx_param_types;
}
SCOSSL_STATUS p_scossl_tls1prf_get_ctx_params(_In_ SCOSSL_PROV_TLS1_PRF_CTX *ctx, _Inout_ OSSL_PARAM params[])
{
OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL &&
!OSSL_PARAM_set_size_t(p, SIZE_MAX))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_DIGEST)) != NULL &&
!OSSL_PARAM_set_utf8_string(p, ctx->mdName == NULL ? "" : ctx->mdName))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SECRET)) != NULL &&
!OSSL_PARAM_set_octet_string(p, ctx->tls1prfCtx->pbSecret, ctx->tls1prfCtx->cbSecret))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SEED)) != NULL &&
!OSSL_PARAM_set_octet_string(p, ctx->tls1prfCtx->seed, ctx->tls1prfCtx->cbSeed))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
return SCOSSL_SUCCESS;
}
SCOSSL_STATUS p_scossl_tls1prf_set_ctx_params(_Inout_ SCOSSL_PROV_TLS1_PRF_CTX *ctx, _In_ const OSSL_PARAM params[])
{
PCBYTE pbSeed;
SIZE_T cbSeed;
const OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL)
{
PCSYMCRYPT_MAC symcryptHmacAlg = NULL;
BOOL isTlsPrf1_1 = FALSE;
const char *paramMdName, *mdProps;
char *mdName;
EVP_MD *md;
if (!OSSL_PARAM_get_utf8_string_ptr(p, &paramMdName))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
// Special case to always allow md5_sha1 for tls1.1 PRF compat
if (OPENSSL_strcasecmp(paramMdName, SN_md5_sha1) != 0)
{
mdProps = NULL;
p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
if ((p != NULL &&
!OSSL_PARAM_get_utf8_string_ptr(p, &mdProps)))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
if ((md = EVP_MD_fetch(ctx->libctx, paramMdName, mdProps)) == NULL)
{
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
return SCOSSL_FAILURE;
}
mdName = OPENSSL_strdup(EVP_MD_get0_name(md));
symcryptHmacAlg = scossl_get_symcrypt_hmac_algorithm(EVP_MD_type(md));
EVP_MD_free(md);
if (symcryptHmacAlg == NULL)
{
return SCOSSL_FAILURE;
}
}
else
{
mdName = OPENSSL_strdup(SN_md5_sha1);
isTlsPrf1_1 = TRUE;
}
OPENSSL_free(ctx->mdName);
ctx->mdName = mdName;
ctx->tls1prfCtx->pHmac = symcryptHmacAlg;
ctx->tls1prfCtx->isTlsPrf1_1 = isTlsPrf1_1;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL)
{
PBYTE pbSecret = NULL;
SIZE_T cbSecret = 0;
if (p->data_size > 0 &&
!OSSL_PARAM_get_octet_string(p, (void **)&pbSecret, 0, &cbSecret))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
OPENSSL_clear_free(ctx->tls1prfCtx->pbSecret, ctx->tls1prfCtx->cbSecret);
ctx->tls1prfCtx->pbSecret = pbSecret;
ctx->tls1prfCtx->cbSecret = cbSecret;
}
// Parameters may contain multiple seed params that must all be processed
for (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SEED);
p != NULL;
p = OSSL_PARAM_locate_const(p + 1, OSSL_KDF_PARAM_SEED))
{
if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbSeed, &cbSeed))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
if (!scossl_tls1prf_append_seed(ctx->tls1prfCtx, pbSeed, cbSeed))
{
ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE);
return SCOSSL_FAILURE;
}
}
return SCOSSL_SUCCESS;
}
const OSSL_DISPATCH p_scossl_tls1prf_kdf_functions[] = {
{OSSL_FUNC_KDF_NEWCTX, (void (*)(void))p_scossl_tls1prf_newctx},
{OSSL_FUNC_KDF_FREECTX, (void (*)(void))p_scossl_tls1prf_freectx},
{OSSL_FUNC_KDF_DUPCTX, (void (*)(void))p_scossl_tls1prf_dupctx},
{OSSL_FUNC_KDF_RESET, (void (*)(void))p_scossl_tls1prf_reset},
{OSSL_FUNC_KDF_DERIVE, (void (*)(void))p_scossl_tls1prf_derive},
{OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_tls1prf_gettable_ctx_params},
{OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_tls1prf_settable_ctx_params},
{OSSL_FUNC_KDF_GET_CTX_PARAMS, (void (*)(void))p_scossl_tls1prf_get_ctx_params},
{OSSL_FUNC_KDF_SET_CTX_PARAMS, (void (*)(void))p_scossl_tls1prf_set_ctx_params},
{0, NULL}};
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -106,9 +106,9 @@ extern const OSSL_DISPATCH p_scossl_hkdf_kdf_functions[];
extern const OSSL_DISPATCH p_scossl_tls1prf_kdf_functions[];
static const OSSL_ALGORITHM p_scossl_kdf[] = {
// ALG("SSHKDF", p_scossl_sshkdf_kdf_functions),
// ALG("HKDF", p_scossl_hkdf_kdf_functions),
// ALG("TLS1-PRF", p_scossl_tls1prf_kdf_functions),
ALG("SSHKDF", p_scossl_sshkdf_kdf_functions),
ALG("HKDF", p_scossl_hkdf_kdf_functions),
ALG("TLS1-PRF", p_scossl_tls1prf_kdf_functions),
ALG_TABLE_END};
// Rand
@ -252,8 +252,6 @@ SCOSSL_STATUS OSSL_provider_init(_In_ const OSSL_CORE_HANDLE *handle,
SCOSSL_PROVCTX *p_ctx = NULL;
OSSL_FUNC_core_get_libctx_fn *core_get_libctx = NULL;
*out = p_scossl_base_dispatch;
if (!scossl_prov_initialized)
{
SYMCRYPT_MODULE_INIT();
@ -289,23 +287,12 @@ SCOSSL_STATUS OSSL_provider_init(_In_ const OSSL_CORE_HANDLE *handle,
}
}
p_ctx = OPENSSL_malloc(sizeof(SCOSSL_PROVCTX));
if (p_ctx != NULL)
{
p_ctx->handle = handle;
*provctx = p_ctx;
}
*out = p_scossl_base_dispatch;
if (!scossl_prov_initialized)
{
SYMCRYPT_MODULE_INIT();
scossl_prov_initialized = 1;
}
scossl_setup_logging();
if (core_get_libctx == NULL)
{
return SCOSSL_FAILURE;
@ -322,6 +309,8 @@ SCOSSL_STATUS OSSL_provider_init(_In_ const OSSL_CORE_HANDLE *handle,
p_ctx->libctx = (OSSL_LIB_CTX *)core_get_libctx(handle);
*provctx = p_ctx;
*out = p_scossl_base_dispatch;
return SCOSSL_SUCCESS;
}

Просмотреть файл

@ -1,28 +0,0 @@
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
//
#include <openssl/core_dispatch.h>
#include "scossl_helpers.h"
#ifdef __cplusplus
extern "C" {
#endif
// Prototype definition, subject to change
#define IMPLEMENT_SCOSSL_KDF_FUNCTIONS(alg) \
const OSSL_DISPATCH p_scossl_##alg##_kdf_functions = { \
{OSSL_FUNC_KDF_NEWCTX, (void (*)(void))p_scossl_##alg##_kdf_new}, \
{OSSL_FUNC_KDF_DUPCTX, (void (*)(void))p_scossl_##alg##_kdf_dup}, \
{OSSL_FUNC_KDF_FREECTX, (void (*)(void))p_scossl_##alg##_kdf_free}, \
{OSSL_FUNC_KDF_RESET, (void (*)(void))p_scossl_##alg##_kdf_reset}, \
{OSSL_FUNC_KDF_DERIVE, (void (*)(void))p_scossl_##alg##_kdf_derive}, \
{OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_##alg##_kdf_settable_ctx_params}, \
{OSSL_FUNC_KDF_SET_CTX_PARAMS, (void (*)(void))p_scossl_##alg##_kdf_set_ctx_params}, \
{OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_##alg##_kdf_gettable_ctx_params}, \
{OSSL_FUNC_KDF_GET_CTX_PARAMS, (void (*)(void))p_scossl_##alg##_kdf_get_ctx_params}, \
{0, NULL}};
#ifdef __cplusplus
}
#endif