Add support for AES-XTS and RSA-PSS with auto salt-len (#68)

This commit is contained in:
Samuel Lee 2023-12-12 14:06:59 -08:00 коммит произвёл GitHub
Родитель 7abafd80a9
Коммит 0ecad51d38
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 72 добавлений и 86 удалений

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

@ -32,8 +32,6 @@ typedef struct
} SCOSSL_RSA_EXPORT_PARAMS;
SCOSSL_RSA_KEY_CTX *scossl_rsa_new_key_ctx();
// Enable SymCryptRsakeyCopy in SymCrypt
// SCOSSL_RSA_KEY_CTX *scossl_rsa_dup_key_ctx(_In_ const SCOSSL_RSA_KEY_CTX *keyCtx);
void scossl_rsa_free_key_ctx(_In_ SCOSSL_RSA_KEY_CTX *keyCtx);
SCOSSL_STATUS scossl_rsa_pkcs1_sign(_In_ SCOSSL_RSA_KEY_CTX *keyCtx, int mdnid,

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

@ -92,45 +92,6 @@ SCOSSL_RSA_KEY_CTX *scossl_rsa_new_key_ctx()
return OPENSSL_zalloc(sizeof(SCOSSL_RSA_KEY_CTX));
}
// _Use_decl_annotations_
// SCOSSL_RSA_KEY_CTX *scossl_rsa_dup_key_ctx(const SCOSSL_RSA_KEY_CTX *keyCtx)
// {
// SCOSSL_RSA_KEY_CTX *copyCtx = OPENSSL_malloc(sizeof(SCOSSL_RSA_KEY_CTX));
// if (copyCtx == NULL)
// {
// return NULL;
// }
// if (keyCtx->initialized)
// {
// SYMCRYPT_RSA_PARAMS SymcryptRsaParam;
// UINT32 cbModulus = SymCryptRsakeyModulusBits(keyCtx->key);
// UINT32 nPrimes = SymCryptRsakeyGetNumberOfPrimes(keyCtx->key);
// SymcryptRsaParam.version = 1;
// SymcryptRsaParam.nBitsOfModulus = cbModulus * 8;
// SymcryptRsaParam.nPrimes = nPrimes;
// SymcryptRsaParam.nPubExp = 1;
// copyCtx->key = SymCryptRsakeyAllocate(&SymcryptRsaParam, 0);
// if (copyCtx->key == NULL)
// {
// scossl_rsa_free_key_ctx(copyCtx);
// return NULL;
// }
// // TODO: Enable in SymCrypt
// SymCryptRsakeyCopy((PCSYMCRYPT_RSAKEY)keyCtx->key, copyCtx->key);
// copyCtx->initialized = 1;
// }
// else
// {
// copyCtx->initialized = 0;
// copyCtx->key = NULL;
// }
// return copyCtx;
// }
_Use_decl_annotations_
void scossl_rsa_free_key_ctx(SCOSSL_RSA_KEY_CTX *keyCtx)
{
@ -386,6 +347,7 @@ SCOSSL_STATUS scossl_rsapss_verify(SCOSSL_RSA_KEY_CTX *keyCtx, int mdnid, int cb
int cbSaltMax;
PCSYMCRYPT_HASH scosslHashAlgo = scossl_get_symcrypt_hash_algorithm(mdnid);
SIZE_T expectedHashLength = scossl_get_expected_hash_length(mdnid);
UINT32 scFlags = 0;
if (scosslHashAlgo == NULL || expectedHashLength == (SIZE_T)-1)
{
@ -410,12 +372,11 @@ SCOSSL_STATUS scossl_rsapss_verify(SCOSSL_RSA_KEY_CTX *keyCtx, int mdnid, int cb
break;
case RSA_PSS_SALTLEN_AUTO:
#ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX
// Added in 3.1, unsupported auto salt len for verify
// Added in 3.1; auto salt len for verify
case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX:
#endif
SCOSSL_LOG_ERROR(SCOSSL_ERR_F_RSAPSS_VERIFY, SCOSSL_ERR_R_NOT_IMPLEMENTED,
"SymCrypt for OpenSSL does not support RSA_PSS_SALTLEN_AUTO saltlen");
return SCOSSL_UNSUPPORTED;
scFlags = SYMCRYPT_FLAG_RSA_PSS_VERIFY_WITH_MINIMUM_SALT;
cbSalt = 0;
}
if (cbSalt < 0 || cbSalt > cbSaltMax)
@ -451,7 +412,7 @@ SCOSSL_STATUS scossl_rsapss_verify(SCOSSL_RSA_KEY_CTX *keyCtx, int mdnid, int cb
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
scosslHashAlgo,
cbSalt,
0);
scFlags);
if (scError == SYMCRYPT_NO_ERROR)
{

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

@ -20,7 +20,7 @@ set(SCOSSL_SOURCES
./src/asymcipher/p_scossl_rsa_cipher.c
./src/ciphers/p_scossl_aes.c
./src/ciphers/p_scossl_aes_aead.c
# ./src/ciphers/p_scossl_aes_xts.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

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

@ -334,6 +334,7 @@ SCOSSL_STATUS p_scossl_rsa_cipher_set_ctx_params(_Inout_ SCOSSL_RSA_CIPHER_CTX *
}
ctx->mgf1MdInfo = mgf1MdInfo;
ctx->oaepMdInfo = mgf1MdInfo;
}

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

@ -7,21 +7,22 @@
#include <openssl/proverr.h>
#include "scossl_helpers.h"
#include "p_scossl_aes.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SCOSSL_XTS_IV_LENGTH 8
#define SCOSSL_XTS_TWEAK_LENGTH 16
typedef struct
{
SYMCRYPT_XTS_AES_EXPANDED_KEY key;
SIZE_T keylen;
BYTE iv[SYMCRYPT_AES_BLOCK_SIZE];
BYTE tweak[SCOSSL_XTS_TWEAK_LENGTH];
INT32 encrypt;
BOOL encrypt;
} SCOSSL_AES_XTS_CTX;
static const OSSL_PARAM p_scossl_aes_xts_gettable_ctx_param_types[] = {
@ -32,6 +33,7 @@ static const OSSL_PARAM p_scossl_aes_xts_gettable_ctx_param_types[] = {
OSSL_PARAM_END};
static const OSSL_PARAM p_scossl_aes_xts_settable_ctx_param_types[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_END};
static SCOSSL_STATUS p_scossl_aes_xts_set_ctx_params(_Inout_ SCOSSL_AES_XTS_CTX *ctx, _In_ const OSSL_PARAM params[]);
@ -52,7 +54,10 @@ static SCOSSL_AES_XTS_CTX *p_scossl_aes_xts_dupctx(SCOSSL_AES_XTS_CTX *ctx)
if (copy_ctx != NULL)
{
memcpy(copy_ctx, ctx, sizeof(SCOSSL_AES_XTS_CTX));
SymCryptXtsAesKeyCopy(&ctx->key, &copy_ctx->key);
}
return copy_ctx;
}
@ -75,7 +80,7 @@ static SCOSSL_STATUS p_scossl_aes_xts_init_internal(_Inout_ SCOSSL_AES_XTS_CTX *
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return SCOSSL_FAILURE;
}
SYMCRYPT_ERROR scError = SymCryptXtsAesExpandKey(&ctx->key, key, keylen);
SYMCRYPT_ERROR scError = SymCryptXtsAesExpandKeyEx(&ctx->key, key, keylen, 0);
if (scError != SYMCRYPT_NO_ERROR)
{
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
@ -85,13 +90,13 @@ static SCOSSL_STATUS p_scossl_aes_xts_init_internal(_Inout_ SCOSSL_AES_XTS_CTX *
if (iv != NULL)
{
if (ivlen != SCOSSL_XTS_IV_LENGTH)
if (ivlen != SCOSSL_XTS_TWEAK_LENGTH)
{
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return SCOSSL_FAILURE;
}
memcpy(ctx->iv, iv, SCOSSL_XTS_IV_LENGTH);
memcpy(ctx->tweak, iv, SCOSSL_XTS_TWEAK_LENGTH);
}
return p_scossl_aes_xts_set_ctx_params(ctx, params);
@ -118,7 +123,7 @@ 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,
_In_reads_bytes_(inl) const unsigned char *in, size_t inl)
{
if( (inl % SYMCRYPT_AES_BLOCK_SIZE) != 0 )
if( inl < SYMCRYPT_AES_BLOCK_SIZE )
{
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
return SCOSSL_FAILURE;
@ -130,26 +135,25 @@ static SCOSSL_STATUS p_scossl_aes_xts_cipher(SCOSSL_AES_XTS_CTX *ctx,
return SCOSSL_FAILURE;
}
// It appears that the EVP API for exposing AES-XTS does not allow definition of the size of
// a data unit. My understanding is that callers are expected to make a single call through
// the EVP interface per data unit - so we pass inl to both cbDataUnit and cbData.
// The EVP API for exposing AES-XTS expects one call per data unit - so we pass inl
// to both cbDataUnit and cbData.
if(ctx->encrypt)
{
SymCryptXtsAesEncrypt(
SymCryptXtsAesEncryptWith128bTweak(
&ctx->key,
inl,
*(UINT64 *) ctx->iv,
&ctx->tweak[0],
in,
out,
inl);
}
else
{
SymCryptXtsAesDecrypt(
SymCryptXtsAesDecryptWith128bTweak(
&ctx->key,
inl,
*(UINT64 *) ctx->iv,
&ctx->tweak[0],
in,
out,
inl);
@ -180,6 +184,11 @@ static const OSSL_PARAM *p_scossl_aes_xts_gettable_ctx_params(ossl_unused void *
return p_scossl_aes_xts_gettable_ctx_param_types;
}
static const OSSL_PARAM *p_scossl_aes_xts_settable_ctx_params(ossl_unused void *cctx, ossl_unused void *provctx)
{
return p_scossl_aes_xts_settable_ctx_param_types;
}
static SCOSSL_STATUS p_scossl_aes_xts_get_ctx_params(_In_ SCOSSL_AES_XTS_CTX *ctx, _Inout_ OSSL_PARAM params[])
{
OSSL_PARAM *p = NULL;
@ -191,23 +200,23 @@ static SCOSSL_STATUS p_scossl_aes_xts_get_ctx_params(_In_ SCOSSL_AES_XTS_CTX *ct
return SCOSSL_FAILURE;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, SCOSSL_XTS_IV_LENGTH))
if (p != NULL && !OSSL_PARAM_set_size_t(p, SCOSSL_XTS_TWEAK_LENGTH))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
if (p != NULL &&
!OSSL_PARAM_set_octet_ptr(p, &ctx->iv, SCOSSL_XTS_IV_LENGTH) &&
!OSSL_PARAM_set_octet_string(p, &ctx->iv, SCOSSL_XTS_IV_LENGTH))
!OSSL_PARAM_set_octet_ptr(p, &ctx->tweak, SCOSSL_XTS_TWEAK_LENGTH) &&
!OSSL_PARAM_set_octet_string(p, &ctx->tweak, SCOSSL_XTS_TWEAK_LENGTH))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV);
if (p != NULL &&
!OSSL_PARAM_set_octet_ptr(p, &ctx->iv, SCOSSL_XTS_IV_LENGTH) &&
!OSSL_PARAM_set_octet_string(p, &ctx->iv, SCOSSL_XTS_IV_LENGTH))
!OSSL_PARAM_set_octet_ptr(p, &ctx->tweak, SCOSSL_XTS_TWEAK_LENGTH) &&
!OSSL_PARAM_set_octet_string(p, &ctx->tweak, SCOSSL_XTS_TWEAK_LENGTH))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return SCOSSL_FAILURE;
@ -215,15 +224,37 @@ static SCOSSL_STATUS p_scossl_aes_xts_get_ctx_params(_In_ SCOSSL_AES_XTS_CTX *ct
return SCOSSL_SUCCESS;
}
static SCOSSL_STATUS p_scossl_aes_xts_set_ctx_params(_Inout_ SCOSSL_AES_XTS_CTX *ctx, _In_ const OSSL_PARAM params[])
{
const OSSL_PARAM *p = NULL;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL)
{
size_t keylen;
if (!OSSL_PARAM_get_size_t(p, &keylen))
{
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return SCOSSL_FAILURE;
}
if (keylen != ctx->keylen)
{
return SCOSSL_FAILURE;
}
}
return SCOSSL_SUCCESS;
}
#define IMPLEMENT_SCOSSL_AES_XTS_CIPHER(kbits) \
SCOSSL_AES_XTS_CTX *p_scossl_aes_##kbits##_xts_newctx() \
{ \
return p_scossl_aes_xts_newctx_internal(kbits >> 3); \
return p_scossl_aes_xts_newctx_internal(2 * (kbits >> 3)); \
} \
SCOSSL_STATUS p_scossl_aes_##kbits##_xts_get_params(_Inout_ OSSL_PARAM params[]) \
{ \
return p_scossl_aes_generic_get_params(params, EVP_CIPH_XTS_MODE, kbits >> 3, \
SCOSSL_XTS_IV_LENGTH, 1, SCOSSL_FLAG_CUSTOM_IV); \
SCOSSL_XTS_TWEAK_LENGTH, 1, SCOSSL_FLAG_CUSTOM_IV); \
} \
\
const OSSL_DISPATCH p_scossl_aes##kbits##xts_functions[] = { \
@ -235,10 +266,12 @@ static SCOSSL_STATUS p_scossl_aes_xts_get_ctx_params(_In_ SCOSSL_AES_XTS_CTX *ct
{OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))p_scossl_aes_xts_update}, \
{OSSL_FUNC_CIPHER_FINAL, (void (*)(void))p_scossl_aes_xts_final}, \
{OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))p_scossl_aes_xts_cipher}, \
{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_GET_PARAMS, (void (*)(void))p_scossl_aes_##kbits##_xts_get_params}, \
{OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))p_scossl_aes_xts_get_ctx_params}, \
{OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))p_scossl_aes_xts_set_ctx_params}, \
{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}, \
{0, NULL}};
IMPLEMENT_SCOSSL_AES_XTS_CIPHER(128)

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

@ -65,7 +65,7 @@ static SCOSSL_RSA_KEY_CTX *p_scossl_rsa_keymgmt_new_ctx(ossl_unused void *provct
return scossl_rsa_new_key_ctx();
}
// Temporary solution until SymCryptRsakeyCopy is enabled. For now we need to export, then import the key to copy.
// We need to export, then import the key to copy with optional private key.
static SCOSSL_STATUS p_scossl_rsa_keymgmt_dup_keydata(_In_ PCSYMCRYPT_RSAKEY fromKey, _Out_ PSYMCRYPT_RSAKEY *toKey, BOOL includePrivate)
{
UINT64 pubExp64;

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

@ -62,13 +62,8 @@ extern const OSSL_DISPATCH p_scossl_aes256gcm_functions[];
extern const OSSL_DISPATCH p_scossl_aes128ccm_functions[];
extern const OSSL_DISPATCH p_scossl_aes192ccm_functions[];
extern const OSSL_DISPATCH p_scossl_aes256ccm_functions[];
// Disabling XTS for now, also disabled in engine pending
// the same dependencies.
// Need to push the FIPS mode XTS flag into the SymCrypt API,
// and expose an XTS key copy method.
// extern const OSSL_DISPATCH p_scossl_aes256xts_functions[];
// extern const OSSL_DISPATCH p_scossl_aes128xts_functions[];
extern const OSSL_DISPATCH p_scossl_aes128xts_functions[];
extern const OSSL_DISPATCH p_scossl_aes256xts_functions[];
static const OSSL_ALGORITHM p_scossl_cipher[] = {
ALG("AES-128-CBC:AES128:2.16.840.1.101.3.4.1.2", p_scossl_aes128cbc_functions),
@ -89,8 +84,8 @@ static const OSSL_ALGORITHM p_scossl_cipher[] = {
ALG("AES-128-CCM:id-aes128-CCM:2.16.840.1.101.3.4.1.7", p_scossl_aes128ccm_functions),
ALG("AES-192-CCM:id-aes192-CCM:2.16.840.1.101.3.4.1.27", p_scossl_aes192ccm_functions),
ALG("AES-256-CCM:id-aes256-CCM:2.16.840.1.101.3.4.1.47", p_scossl_aes256ccm_functions),
// ALG("AES-128-XTS:1.3.111.2.1619.0.1.1", p_scossl_aes256xts_functions),
// ALG("AES-256-XTS:1.3.111.2.1619.0.1.2", p_scossl_aes128xts_functions),
ALG("AES-128-XTS:1.3.111.2.1619.0.1.1", p_scossl_aes128xts_functions),
ALG("AES-256-XTS:1.3.111.2.1619.0.1.2", p_scossl_aes256xts_functions),
ALG_TABLE_END};
// MAC

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

@ -449,7 +449,7 @@ static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ct
else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO) == 0)
{
// Sign: Maximized salt length
// Verify: Autorecovered salt length (not supported)
// Verify: Autorecovered salt length
saltlen = RSA_PSS_SALTLEN_AUTO;
}
else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_MAX) == 0)
@ -459,7 +459,7 @@ static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ct
else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX) == 0)
{
// Sign: Smaller of digest length or maximized salt length
// Verify: Autorecovered salt length (not supported)
// Verify: Autorecovered salt length
saltlen = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX;
}
else
@ -472,10 +472,7 @@ static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ct
return SCOSSL_FAILURE;
}
if (saltlen < RSA_PSS_SALTLEN_AUTO_DIGEST_MAX ||
(ctx->operation == EVP_PKEY_OP_VERIFY &&
(saltlen == RSA_PSS_SALTLEN_AUTO ||
saltlen == RSA_PSS_SALTLEN_AUTO_DIGEST_MAX)))
if (saltlen < RSA_PSS_SALTLEN_AUTO_DIGEST_MAX)
{
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
return SCOSSL_FAILURE;
@ -516,6 +513,7 @@ static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ct
EVP_MD_free(ctx->md);
ctx->md = md;
ctx->mgf1MdInfo = mgf1MdInfo;
ctx->mdInfo = mgf1MdInfo;
}
return SCOSSL_SUCCESS;