Latest update.

This commit is contained in:
2020-01-17 19:45:12 +09:00
parent 016df9f433
commit 0f7abb4eb6
1100 changed files with 47785 additions and 16292 deletions
+6 -6
View File
@@ -16,7 +16,7 @@
# needed both by non-legacy and legacy code.
#
# libimplementations.a Contains all non-legacy implementations.
# liblegacy.a Contains all legacy implementaions.
# liblegacy.a Contains all legacy implementations.
#
# libfips.a Contains all things needed to support
# FIPS implementations, such as code from
@@ -40,14 +40,14 @@ $LIBNONFIPS=libnonfips.a
$LIBFIPS=libfips.a
# Enough of our implementations include prov/ciphercommon.h (present in
# providers/common/include), which includes crypto/ciphermode_platform.h
# providers/implementations/include), which includes crypto/*_platform.h
# (present in include), which in turn may include very internal header
# files in crypto/, so let's have a common include list for them all.
$COMMON_INCLUDES=../crypto ../include common/include
$COMMON_INCLUDES=../crypto ../include implementations/include common/include
INCLUDE[$LIBCOMMON]=$COMMON_INCLUDES
INCLUDE[$LIBIMPLEMENTATIONS]=.. $COMMON_INCLUDES implementations/include
INCLUDE[$LIBLEGACY]=$COMMON_INCLUDES implementations/include
INCLUDE[$LIBIMPLEMENTATIONS]=.. $COMMON_INCLUDES
INCLUDE[$LIBLEGACY]=$COMMON_INCLUDES
INCLUDE[$LIBNONFIPS]=$COMMON_INCLUDES
INCLUDE[$LIBFIPS]=.. $COMMON_INCLUDES
DEFINE[$LIBFIPS]=FIPS_MODE
@@ -84,7 +84,7 @@ $DEFAULTGOAL=../libcrypto
SOURCE[$DEFAULTGOAL]=$LIBIMPLEMENTATIONS $LIBNONFIPS
SOURCE[$DEFAULTGOAL]=defltprov.c
# Some legacy implementations depend on provider header files
INCLUDE[../libcrypto]=implementations/include
INCLUDE[$DEFAULTGOAL]=implementations/include
LIBS=$DEFAULTGOAL
+96
View File
@@ -0,0 +1,96 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core_numbers.h>
#include "prov/bio.h"
static OSSL_BIO_new_file_fn *c_bio_new_file = NULL;
static OSSL_BIO_new_membuf_fn *c_bio_new_membuf = NULL;
static OSSL_BIO_read_ex_fn *c_bio_read_ex = NULL;
static OSSL_BIO_free_fn *c_bio_free = NULL;
static OSSL_BIO_vprintf_fn *c_bio_vprintf = NULL;
int ossl_prov_bio_from_dispatch(const OSSL_DISPATCH *fns)
{
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
case OSSL_FUNC_BIO_NEW_FILE:
if (c_bio_new_file == NULL)
c_bio_new_file = OSSL_get_BIO_new_file(fns);
break;
case OSSL_FUNC_BIO_NEW_MEMBUF:
if (c_bio_new_membuf == NULL)
c_bio_new_membuf = OSSL_get_BIO_new_membuf(fns);
break;
case OSSL_FUNC_BIO_READ_EX:
if (c_bio_read_ex == NULL)
c_bio_read_ex = OSSL_get_BIO_read_ex(fns);
break;
case OSSL_FUNC_BIO_FREE:
if (c_bio_free == NULL)
c_bio_free = OSSL_get_BIO_free(fns);
break;
case OSSL_FUNC_BIO_VPRINTF:
if (c_bio_vprintf == NULL)
c_bio_vprintf = OSSL_get_BIO_vprintf(fns);
break;
}
}
return 1;
}
BIO *ossl_prov_bio_new_file(const char *filename, const char *mode)
{
if (c_bio_new_file == NULL)
return NULL;
return c_bio_new_file(filename, mode);
}
BIO *ossl_prov_bio_new_membuf(const char *filename, int len)
{
if (c_bio_new_membuf == NULL)
return NULL;
return c_bio_new_membuf(filename, len);
}
int ossl_prov_bio_read_ex(BIO *bio, void *data, size_t data_len,
size_t *bytes_read)
{
if (c_bio_read_ex == NULL)
return 0;
return c_bio_read_ex(bio, data, data_len, bytes_read);
}
int ossl_prov_bio_free(BIO *bio)
{
if (c_bio_free == NULL)
return 0;
return c_bio_free(bio);
}
int ossl_prov_bio_vprintf(BIO *bio, const char *format, va_list ap)
{
if (c_bio_vprintf == NULL)
return -1;
return c_bio_vprintf(bio, format, ap);
}
int ossl_prov_bio_printf(BIO *bio, const char *format, ...)
{
va_list ap;
int ret;
va_start(ap, format);
ret = ossl_prov_bio_vprintf(bio, format, ap);
va_end(ap);
return ret;
}
+2 -4
View File
@@ -1,6 +1,4 @@
SUBDIRS=digests ciphers
SOURCE[../libcommon.a]=provider_err.c provlib.c
SOURCE[../libcommon.a]=provider_err.c bio_prov.c
$FIPSCOMMON=provider_util.c
SOURCE[../libnonfips.a]=$FIPSCOMMON
SOURCE[../libnonfips.a]=$FIPSCOMMON nid_to_name.c
SOURCE[../libfips.a]=$FIPSCOMMON
-5
View File
@@ -1,5 +0,0 @@
# This source is common building blocks for all ciphers in all our providers.
SOURCE[../../libcommon.a]=\
cipher_common.c cipher_common_hw.c block.c \
cipher_gcm.c cipher_gcm_hw.c \
cipher_ccm.c cipher_ccm_hw.c
-117
View File
@@ -1,117 +0,0 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "prov/ciphercommon.h"
#include "prov/cipher_gcm.h"
int gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen)
{
CRYPTO_gcm128_setiv(&ctx->gcm, iv, ivlen);
return 1;
}
int gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad, size_t aad_len)
{
return CRYPTO_gcm128_aad(&ctx->gcm, aad, aad_len) == 0;
}
int gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
size_t len, unsigned char *out)
{
if (ctx->enc) {
if (ctx->ctr != NULL) {
#if defined(AES_GCM_ASM)
size_t bulk = 0;
if (len >= 32 && AES_GCM_ASM(ctx)) {
size_t res = (16 - ctx->gcm.mres) % 16;
if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res))
return 0;
bulk = aesni_gcm_encrypt(in + res, out + res, len - res,
ctx->gcm.key,
ctx->gcm.Yi.c, ctx->gcm.Xi.u);
ctx->gcm.len.u[1] += bulk;
bulk += res;
}
if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
len - bulk, ctx->ctr))
return 0;
#else
if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
return 0;
#endif /* AES_GCM_ASM */
} else {
if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len))
return 0;
}
} else {
if (ctx->ctr != NULL) {
#if defined(AES_GCM_ASM)
size_t bulk = 0;
if (len >= 16 && AES_GCM_ASM(ctx)) {
size_t res = (16 - ctx->gcm.mres) % 16;
if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res))
return -1;
bulk = aesni_gcm_decrypt(in + res, out + res, len - res,
ctx->gcm.key,
ctx->gcm.Yi.c, ctx->gcm.Xi.u);
ctx->gcm.len.u[1] += bulk;
bulk += res;
}
if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
len - bulk, ctx->ctr))
return 0;
#else
if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
return 0;
#endif /* AES_GCM_ASM */
} else {
if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len))
return 0;
}
}
return 1;
}
int gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag)
{
if (ctx->enc) {
CRYPTO_gcm128_tag(&ctx->gcm, tag, GCM_TAG_MAX_SIZE);
ctx->taglen = GCM_TAG_MAX_SIZE;
} else {
if (CRYPTO_gcm128_finish(&ctx->gcm, tag, ctx->taglen) != 0)
return 0;
}
return 1;
}
int gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len,
const unsigned char *in, size_t in_len,
unsigned char *out, unsigned char *tag, size_t tag_len)
{
int ret = 0;
/* Use saved AAD */
if (!ctx->hw->aadupdate(ctx, aad, aad_len))
goto err;
if (!ctx->hw->cipherupdate(ctx, in, in_len, out))
goto err;
ctx->taglen = GCM_TAG_MAX_SIZE;
if (!ctx->hw->cipherfinal(ctx, tag))
goto err;
ret = 1;
err:
return ret;
}
-2
View File
@@ -1,2 +0,0 @@
# This source is common for all digests in all our providers.
SOURCE[../../libcommon.a]=digest_common.c
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdarg.h>
#include <openssl/bio.h>
#include <openssl/core.h>
int ossl_prov_bio_from_dispatch(const OSSL_DISPATCH *fns);
BIO *ossl_prov_bio_new_file(const char *filename, const char *mode);
BIO *ossl_prov_bio_new_membuf(const char *filename, int len);
int ossl_prov_bio_read_ex(BIO *bio, void *data, size_t data_len,
size_t *bytes_read);
int ossl_prov_bio_free(BIO *bio);
int ossl_prov_bio_vprintf(BIO *bio, const char *format, va_list ap);
int ossl_prov_bio_printf(BIO *bio, const char *format, ...);
@@ -101,3 +101,15 @@ int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx,
const char *ciphername,
const char *mdname,
OPENSSL_CTX *ctx);
typedef struct ag_capable_st {
OSSL_ALGORITHM alg;
int (*capable)(void);
} OSSL_ALGORITHM_CAPABLE;
/*
* Dynamically select algorithms by calling a capable() method.
* If this method is NULL or the method returns 1 then the algorithm is added.
*/
void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in,
OSSL_ALGORITHM *out);
@@ -13,3 +13,5 @@ const OSSL_PROVIDER *FIPS_get_provider(OPENSSL_CTX *ctx);
const char *ossl_prov_util_nid_to_name(int nid);
int cipher_capable_aes_cbc_hmac_sha1(void);
int cipher_capable_aes_cbc_hmac_sha256(void);
@@ -23,7 +23,7 @@ int ERR_load_PROV_strings(void);
/*
* PROV function codes.
*/
# if !OPENSSL_API_3
# ifndef OPENSSL_NO_DEPRECATED_3_0
# define PROV_F_AESNI_INIT_KEY 0
# define PROV_F_AES_BLOCK_FINAL 0
# define PROV_F_AES_BLOCK_UPDATE 0
@@ -53,19 +53,24 @@ int ERR_load_PROV_strings(void);
# define PROV_R_BAD_DECRYPT 100
# define PROV_R_BAD_ENCODING 141
# define PROV_R_BAD_LENGTH 142
# define PROV_R_BAD_TLS_CLIENT_VERSION 161
# define PROV_R_BN_ERROR 160
# define PROV_R_BOTH_MODE_AND_MODE_INT 127
# define PROV_R_CIPHER_OPERATION_FAILED 102
# define PROV_R_FAILED_TO_DECRYPT 162
# define PROV_R_FAILED_TO_GENERATE_KEY 121
# define PROV_R_FAILED_TO_GET_PARAMETER 103
# define PROV_R_FAILED_TO_SET_PARAMETER 104
# define PROV_R_INAVLID_UKM_LENGTH 146
# define PROV_R_INVALID_AAD 108
# define PROV_R_INVALID_CONSTANT_LENGTH 157
# define PROV_R_INVALID_CUSTOM_LENGTH 111
# define PROV_R_INVALID_DATA 115
# define PROV_R_INVALID_DIGEST 122
# define PROV_R_INVALID_ITERATION_COUNT 123
# define PROV_R_INVALID_IVLEN 116
# define PROV_R_INVALID_IV_LENGTH 109
# define PROV_R_INVALID_KEY 158
# define PROV_R_INVALID_KEYLEN 117
# define PROV_R_INVALID_KEY_LEN 124
# define PROV_R_INVALID_KEY_LENGTH 105
@@ -77,6 +82,8 @@ int ERR_load_PROV_strings(void);
# define PROV_R_INVALID_TAG 110
# define PROV_R_INVALID_TAGLEN 118
# define PROV_R_MISSING_CEK_ALG 144
# define PROV_R_MISSING_CIPHER 155
# define PROV_R_MISSING_CONSTANT 156
# define PROV_R_MISSING_KEY 128
# define PROV_R_MISSING_MAC 150
# define PROV_R_MISSING_MESSAGE_DIGEST 129
@@ -91,6 +98,7 @@ int ERR_load_PROV_strings(void);
# define PROV_R_NOT_XOF_OR_INVALID_LENGTH 113
# define PROV_R_NO_KEY_SET 114
# define PROV_R_OUTPUT_BUFFER_TOO_SMALL 106
# define PROV_R_READ_KEY 159
# define PROV_R_TAG_NOTSET 119
# define PROV_R_TAG_NOT_NEEDED 120
# define PROV_R_UNABLE_TO_LOAD_SHA1 143
@@ -1,5 +1,5 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
+10
View File
@@ -19,10 +19,14 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_DECRYPT), "bad decrypt"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_ENCODING), "bad encoding"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_LENGTH), "bad length"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_TLS_CLIENT_VERSION),
"bad tls client version"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BN_ERROR), "bn error"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BOTH_MODE_AND_MODE_INT),
"both mode and mode int"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_CIPHER_OPERATION_FAILED),
"cipher operation failed"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_DECRYPT), "failed to decrypt"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_GENERATE_KEY),
"failed to generate key"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_GET_PARAMETER),
@@ -32,6 +36,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INAVLID_UKM_LENGTH),
"inavlid ukm length"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_AAD), "invalid aad"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CONSTANT_LENGTH),
"invalid constant length"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CUSTOM_LENGTH),
"invalid custom length"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DATA), "invalid data"},
@@ -40,6 +46,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
"invalid iteration count"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_IVLEN), "invalid ivlen"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_IV_LENGTH), "invalid iv length"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY), "invalid key"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEYLEN), "invalid keylen"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY_LEN), "invalid key len"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY_LENGTH),
@@ -54,6 +61,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAG), "invalid tag"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAGLEN), "invalid taglen"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CEK_ALG), "missing cek alg"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CIPHER), "missing cipher"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CONSTANT), "missing constant"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_KEY), "missing key"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_MAC), "missing mac"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_MESSAGE_DIGEST),
@@ -72,6 +81,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NO_KEY_SET), "no key set"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_OUTPUT_BUFFER_TOO_SMALL),
"output buffer too small"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_READ_KEY), "read key"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOTSET), "tag notset"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOT_NEEDED), "tag not needed"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_LOAD_SHA1),
+14
View File
@@ -237,3 +237,17 @@ int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx,
*macctx = NULL;
return 0;
}
void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in,
OSSL_ALGORITHM *out)
{
int i, j;
if (out[0].algorithm_names == NULL) {
for (i = j = 0; in[i].alg.algorithm_names != NULL; ++i) {
if (in[i].capable == NULL || in[i].capable())
out[j++] = in[i].alg;
}
out[j++] = in[i].alg;
}
}
+267 -171
View File
@@ -14,7 +14,14 @@
#include <openssl/core_numbers.h>
#include <openssl/core_names.h>
#include <openssl/params.h>
#include "prov/bio.h"
#include "prov/providercommon.h"
#include "prov/implementations.h"
#include "prov/provider_util.h"
#include "internal/nelem.h"
#define ALGC(NAMES, FUNC, CHECK) { { NAMES, "default=yes", FUNC }, CHECK }
#define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL)
/* Functions provided by the core */
static OSSL_core_gettable_params_fn *c_gettable_params = NULL;
@@ -73,6 +80,9 @@ static int deflt_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
* We add diverse other names where applicable, such as the names that
* NIST uses, or that are used for ASN.1 OBJECT IDENTIFIERs, or names
* we have used historically.
*
* Algorithm names are case insensitive, but we use all caps in our "canonical"
* names for consistency.
*/
static const OSSL_ALGORITHM deflt_digests[] = {
/* Our primary name:NIST name[:our older names] */
@@ -93,11 +103,11 @@ static const OSSL_ALGORITHM deflt_digests[] = {
{ "SHA3-512", "default=yes", sha3_512_functions },
/*
* KECCAK_KMAC128 and KECCAK_KMAC256 as hashes are mostly useful for
* the KMAC128 and KMAC256.
* KECCAK-KMAC-128 and KECCAK-KMAC-256 as hashes are mostly useful for
* the KMAC-128 and KMAC-256.
*/
{ "KECCAK_KMAC128", "default=yes", keccak_kmac_128_functions },
{ "KECCAK_KMAC256", "default=yes", keccak_kmac_256_functions },
{ "KECCAK-KMAC-128:KECCAK-KMAC128", "default=yes", keccak_kmac_128_functions },
{ "KECCAK-KMAC-256:KECCAK-KMAC256", "default=yes", keccak_kmac_256_functions },
/* Our primary name:NIST name */
{ "SHAKE-128:SHAKE128", "default=yes", shake_128_functions },
@@ -111,8 +121,8 @@ static const OSSL_ALGORITHM deflt_digests[] = {
* If we assume that "2b" and "2s" are versions, that pattern
* fits with ours. We also add our historical names.
*/
{ "BLAKE2s-256:BLAKE2s256", "default=yes", blake2s256_functions },
{ "BLAKE2b-512:BLAKE2b512", "default=yes", blake2b512_functions },
{ "BLAKE2S-256:BLAKE2s256", "default=yes", blake2s256_functions },
{ "BLAKE2B-512:BLAKE2b512", "default=yes", blake2b512_functions },
#endif /* OPENSSL_NO_BLAKE2 */
#ifndef OPENSSL_NO_SM3
@@ -127,219 +137,234 @@ static const OSSL_ALGORITHM deflt_digests[] = {
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM deflt_ciphers[] = {
{ "AES-256-ECB", "default=yes", aes256ecb_functions },
{ "AES-192-ECB", "default=yes", aes192ecb_functions },
{ "AES-128-ECB", "default=yes", aes128ecb_functions },
{ "AES-256-CBC", "default=yes", aes256cbc_functions },
{ "AES-192-CBC", "default=yes", aes192cbc_functions },
{ "AES-128-CBC", "default=yes", aes128cbc_functions },
{ "AES-256-OFB", "default=yes", aes256ofb_functions },
{ "AES-192-OFB", "default=yes", aes192ofb_functions },
{ "AES-128-OFB", "default=yes", aes128ofb_functions },
{ "AES-256-CFB", "default=yes", aes256cfb_functions },
{ "AES-192-CFB", "default=yes", aes192cfb_functions },
{ "AES-128-CFB", "default=yes", aes128cfb_functions },
{ "AES-256-CFB1", "default=yes", aes256cfb1_functions },
{ "AES-192-CFB1", "default=yes", aes192cfb1_functions },
{ "AES-128-CFB1", "default=yes", aes128cfb1_functions },
{ "AES-256-CFB8", "default=yes", aes256cfb8_functions },
{ "AES-192-CFB8", "default=yes", aes192cfb8_functions },
{ "AES-128-CFB8", "default=yes", aes128cfb8_functions },
{ "AES-256-CTR", "default=yes", aes256ctr_functions },
{ "AES-192-CTR", "default=yes", aes192ctr_functions },
{ "AES-128-CTR", "default=yes", aes128ctr_functions },
{ "AES-256-XTS", "default=yes", aes256xts_functions },
{ "AES-128-XTS", "default=yes", aes128xts_functions },
static const OSSL_ALGORITHM_CAPABLE deflt_ciphers[] = {
ALG("AES-256-ECB", aes256ecb_functions),
ALG("AES-192-ECB", aes192ecb_functions),
ALG("AES-128-ECB", aes128ecb_functions),
ALG("AES-256-CBC", aes256cbc_functions),
ALG("AES-192-CBC", aes192cbc_functions),
ALG("AES-128-CBC", aes128cbc_functions),
ALG("AES-256-OFB", aes256ofb_functions),
ALG("AES-192-OFB", aes192ofb_functions),
ALG("AES-128-OFB", aes128ofb_functions),
ALG("AES-256-CFB", aes256cfb_functions),
ALG("AES-192-CFB", aes192cfb_functions),
ALG("AES-128-CFB", aes128cfb_functions),
ALG("AES-256-CFB1", aes256cfb1_functions),
ALG("AES-192-CFB1", aes192cfb1_functions),
ALG("AES-128-CFB1", aes128cfb1_functions),
ALG("AES-256-CFB8", aes256cfb8_functions),
ALG("AES-192-CFB8", aes192cfb8_functions),
ALG("AES-128-CFB8", aes128cfb8_functions),
ALG("AES-256-CTR", aes256ctr_functions),
ALG("AES-192-CTR", aes192ctr_functions),
ALG("AES-128-CTR", aes128ctr_functions),
ALG("AES-256-XTS", aes256xts_functions),
ALG("AES-128-XTS", aes128xts_functions),
#ifndef OPENSSL_NO_OCB
{ "AES-256-OCB", "default=yes", aes256ocb_functions },
{ "AES-192-OCB", "default=yes", aes192ocb_functions },
{ "AES-128-OCB", "default=yes", aes128ocb_functions },
ALG("AES-256-OCB", aes256ocb_functions),
ALG("AES-192-OCB", aes192ocb_functions),
ALG("AES-128-OCB", aes128ocb_functions),
#endif /* OPENSSL_NO_OCB */
{ "AES-256-GCM:id-aes256-GCM", "default=yes", aes256gcm_functions },
{ "AES-192-GCM:id-aes192-GCM", "default=yes", aes192gcm_functions },
{ "AES-128-GCM:id-aes128-GCM", "default=yes", aes128gcm_functions },
{ "AES-256-CCM:id-aes256-CCM", "default=yes", aes256ccm_functions },
{ "AES-192-CCM:id-aes192-CCM", "default=yes", aes192ccm_functions },
{ "AES-128-CCM:id-aes128-CCM", "default=yes", aes128ccm_functions },
{ "AES-256-WRAP:id-aes256-wrap:AES256-WRAP", "default=yes",
aes256wrap_functions },
{ "AES-192-WRAP:id-aes192-wrap:AES192-WRAP", "default=yes",
aes192wrap_functions },
{ "AES-128-WRAP:id-aes128-wrap:AES128-WRAP", "default=yes",
aes128wrap_functions },
{ "AES-256-WRAP-PAD:id-aes256-wrap-pad:AES256-WRAP-PAD", "default=yes",
aes256wrappad_functions },
{ "AES-192-WRAP-PAD:id-aes192-wrap-pad:AES192-WRAP-PAD", "default=yes",
aes192wrappad_functions },
{ "AES-128-WRAP-PAD:id-aes128-wrap-pad:AES128-WRAP-PAD", "default=yes",
aes128wrappad_functions },
#ifndef OPENSSL_NO_SIV
ALG("AES-128-SIV", aes128siv_functions),
ALG("AES-192-SIV", aes192siv_functions),
ALG("AES-256-SIV", aes256siv_functions),
#endif /* OPENSSL_NO_SIV */
ALG("AES-256-GCM:id-aes256-GCM", aes256gcm_functions),
ALG("AES-192-GCM:id-aes192-GCM", aes192gcm_functions),
ALG("AES-128-GCM:id-aes128-GCM", aes128gcm_functions),
ALG("AES-256-CCM:id-aes256-CCM", aes256ccm_functions),
ALG("AES-192-CCM:id-aes192-CCM", aes192ccm_functions),
ALG("AES-128-CCM:id-aes128-CCM", aes128ccm_functions),
ALG("AES-256-WRAP:id-aes256-wrap:AES256-WRAP", aes256wrap_functions),
ALG("AES-192-WRAP:id-aes192-wrap:AES192-WRAP", aes192wrap_functions),
ALG("AES-128-WRAP:id-aes128-wrap:AES128-WRAP", aes128wrap_functions),
ALG("AES-256-WRAP-PAD:id-aes256-wrap-pad:AES256-WRAP-PAD",
aes256wrappad_functions),
ALG("AES-192-WRAP-PAD:id-aes192-wrap-pad:AES192-WRAP-PAD",
aes192wrappad_functions),
ALG("AES-128-WRAP-PAD:id-aes128-wrap-pad:AES128-WRAP-PAD",
aes128wrappad_functions),
ALGC("AES-128-CBC-HMAC-SHA1", aes128cbc_hmac_sha1_functions,
cipher_capable_aes_cbc_hmac_sha1),
ALGC("AES-256-CBC-HMAC-SHA1", aes256cbc_hmac_sha1_functions,
cipher_capable_aes_cbc_hmac_sha1),
ALGC("AES-128-CBC-HMAC-SHA256", aes128cbc_hmac_sha256_functions,
cipher_capable_aes_cbc_hmac_sha256),
ALGC("AES-256-CBC-HMAC-SHA256", aes256cbc_hmac_sha256_functions,
cipher_capable_aes_cbc_hmac_sha256),
#ifndef OPENSSL_NO_ARIA
{ "ARIA-256-GCM", "default=yes", aria256gcm_functions },
{ "ARIA-192-GCM", "default=yes", aria192gcm_functions },
{ "ARIA-128-GCM", "default=yes", aria128gcm_functions },
{ "ARIA-256-CCM", "default=yes", aria256ccm_functions },
{ "ARIA-192-CCM", "default=yes", aria192ccm_functions },
{ "ARIA-128-CCM", "default=yes", aria128ccm_functions },
{ "ARIA-256-ECB", "default=yes", aria256ecb_functions },
{ "ARIA-192-ECB", "default=yes", aria192ecb_functions },
{ "ARIA-128-ECB", "default=yes", aria128ecb_functions },
{ "ARIA-256-CBC:ARIA256", "default=yes", aria256cbc_functions },
{ "ARIA-192-CBC:ARIA192", "default=yes", aria192cbc_functions },
{ "ARIA-128-CBC:ARIA128", "default=yes", aria128cbc_functions },
{ "ARIA-256-OFB", "default=yes", aria256ofb_functions },
{ "ARIA-192-OFB", "default=yes", aria192ofb_functions },
{ "ARIA-128-OFB", "default=yes", aria128ofb_functions },
{ "ARIA-256-CFB", "default=yes", aria256cfb_functions },
{ "ARIA-192-CFB", "default=yes", aria192cfb_functions },
{ "ARIA-128-CFB", "default=yes", aria128cfb_functions },
{ "ARIA-256-CFB1", "default=yes", aria256cfb1_functions },
{ "ARIA-192-CFB1", "default=yes", aria192cfb1_functions },
{ "ARIA-128-CFB1", "default=yes", aria128cfb1_functions },
{ "ARIA-256-CFB8", "default=yes", aria256cfb8_functions },
{ "ARIA-192-CFB8", "default=yes", aria192cfb8_functions },
{ "ARIA-128-CFB8", "default=yes", aria128cfb8_functions },
{ "ARIA-256-CTR", "default=yes", aria256ctr_functions },
{ "ARIA-192-CTR", "default=yes", aria192ctr_functions },
{ "ARIA-128-CTR", "default=yes", aria128ctr_functions },
ALG("ARIA-256-GCM", aria256gcm_functions),
ALG("ARIA-192-GCM", aria192gcm_functions),
ALG("ARIA-128-GCM", aria128gcm_functions),
ALG("ARIA-256-CCM", aria256ccm_functions),
ALG("ARIA-192-CCM", aria192ccm_functions),
ALG("ARIA-128-CCM", aria128ccm_functions),
ALG("ARIA-256-ECB", aria256ecb_functions),
ALG("ARIA-192-ECB", aria192ecb_functions),
ALG("ARIA-128-ECB", aria128ecb_functions),
ALG("ARIA-256-CBC:ARIA256", aria256cbc_functions),
ALG("ARIA-192-CBC:ARIA192", aria192cbc_functions),
ALG("ARIA-128-CBC:ARIA128", aria128cbc_functions),
ALG("ARIA-256-OFB", aria256ofb_functions),
ALG("ARIA-192-OFB", aria192ofb_functions),
ALG("ARIA-128-OFB", aria128ofb_functions),
ALG("ARIA-256-CFB", aria256cfb_functions),
ALG("ARIA-192-CFB", aria192cfb_functions),
ALG("ARIA-128-CFB", aria128cfb_functions),
ALG("ARIA-256-CFB1", aria256cfb1_functions),
ALG("ARIA-192-CFB1", aria192cfb1_functions),
ALG("ARIA-128-CFB1", aria128cfb1_functions),
ALG("ARIA-256-CFB8", aria256cfb8_functions),
ALG("ARIA-192-CFB8", aria192cfb8_functions),
ALG("ARIA-128-CFB8", aria128cfb8_functions),
ALG("ARIA-256-CTR", aria256ctr_functions),
ALG("ARIA-192-CTR", aria192ctr_functions),
ALG("ARIA-128-CTR", aria128ctr_functions),
#endif /* OPENSSL_NO_ARIA */
#ifndef OPENSSL_NO_CAMELLIA
{ "CAMELLIA-256-ECB", "default=yes", camellia256ecb_functions },
{ "CAMELLIA-192-ECB", "default=yes", camellia192ecb_functions },
{ "CAMELLIA-128-ECB", "default=yes", camellia128ecb_functions },
{ "CAMELLIA-256-CBC:CAMELLIA256", "default=yes", camellia256cbc_functions },
{ "CAMELLIA-192-CBC:CAMELLIA192", "default=yes", camellia192cbc_functions },
{ "CAMELLIA-128-CBC:CAMELLIA128", "default=yes", camellia128cbc_functions },
{ "CAMELLIA-256-OFB", "default=yes", camellia256ofb_functions },
{ "CAMELLIA-192-OFB", "default=yes", camellia192ofb_functions },
{ "CAMELLIA-128-OFB", "default=yes", camellia128ofb_functions },
{ "CAMELLIA-256-CFB", "default=yes", camellia256cfb_functions },
{ "CAMELLIA-192-CFB", "default=yes", camellia192cfb_functions },
{ "CAMELLIA-128-CFB", "default=yes", camellia128cfb_functions },
{ "CAMELLIA-256-CFB1", "default=yes", camellia256cfb1_functions },
{ "CAMELLIA-192-CFB1", "default=yes", camellia192cfb1_functions },
{ "CAMELLIA-128-CFB1", "default=yes", camellia128cfb1_functions },
{ "CAMELLIA-256-CFB8", "default=yes", camellia256cfb8_functions },
{ "CAMELLIA-192-CFB8", "default=yes", camellia192cfb8_functions },
{ "CAMELLIA-128-CFB8", "default=yes", camellia128cfb8_functions },
{ "CAMELLIA-256-CTR", "default=yes", camellia256ctr_functions },
{ "CAMELLIA-192-CTR", "default=yes", camellia192ctr_functions },
{ "CAMELLIA-128-CTR", "default=yes", camellia128ctr_functions },
ALG("CAMELLIA-256-ECB", camellia256ecb_functions),
ALG("CAMELLIA-192-ECB", camellia192ecb_functions),
ALG("CAMELLIA-128-ECB", camellia128ecb_functions),
ALG("CAMELLIA-256-CBC:CAMELLIA256", camellia256cbc_functions),
ALG("CAMELLIA-192-CBC:CAMELLIA192", camellia192cbc_functions),
ALG("CAMELLIA-128-CBC:CAMELLIA128", camellia128cbc_functions),
ALG("CAMELLIA-256-OFB", camellia256ofb_functions),
ALG("CAMELLIA-192-OFB", camellia192ofb_functions),
ALG("CAMELLIA-128-OFB", camellia128ofb_functions),
ALG("CAMELLIA-256-CFB", camellia256cfb_functions),
ALG("CAMELLIA-192-CFB", camellia192cfb_functions),
ALG("CAMELLIA-128-CFB", camellia128cfb_functions),
ALG("CAMELLIA-256-CFB1", camellia256cfb1_functions),
ALG("CAMELLIA-192-CFB1", camellia192cfb1_functions),
ALG("CAMELLIA-128-CFB1", camellia128cfb1_functions),
ALG("CAMELLIA-256-CFB8", camellia256cfb8_functions),
ALG("CAMELLIA-192-CFB8", camellia192cfb8_functions),
ALG("CAMELLIA-128-CFB8", camellia128cfb8_functions),
ALG("CAMELLIA-256-CTR", camellia256ctr_functions),
ALG("CAMELLIA-192-CTR", camellia192ctr_functions),
ALG("CAMELLIA-128-CTR", camellia128ctr_functions),
#endif /* OPENSSL_NO_CAMELLIA */
#ifndef OPENSSL_NO_DES
{ "DES-EDE3-ECB:DES-EDE3", "default=yes", tdes_ede3_ecb_functions },
{ "DES-EDE3-CBC:DES3", "default=yes", tdes_ede3_cbc_functions },
{ "DES-EDE3-OFB", "default=yes", tdes_ede3_ofb_functions },
{ "DES-EDE3-CFB", "default=yes", tdes_ede3_cfb_functions },
{ "DES-EDE3-CFB8", "default=yes", tdes_ede3_cfb8_functions },
{ "DES-EDE3-CFB1", "default=yes", tdes_ede3_cfb1_functions },
{ "DES-EDE-ECB:DES-EDE", "default=yes", tdes_ede2_ecb_functions },
{ "DES-EDE-CBC", "default=yes", tdes_ede2_cbc_functions },
{ "DES-EDE-OFB", "default=yes", tdes_ede2_ofb_functions },
{ "DES-EDE-CFB", "default=yes", tdes_ede2_cfb_functions },
{ "DESX-CBC:DESX", "default=yes", tdes_desx_cbc_functions },
{ "DES3-WRAP:id-smime-alg-CMS3DESwrap", "default=yes", tdes_wrap_cbc_functions },
{ "DES-ECB", "default=yes", des_ecb_functions },
{ "DES-CBC:DES", "default=yes", des_cbc_functions },
{ "DES-OFB", "default=yes", des_ofb64_functions },
{ "DES-CFB", "default=yes", des_cfb64_functions },
{ "DES-CFB1", "default=yes", des_cfb1_functions },
{ "DES-CFB8", "default=yes", des_cfb8_functions },
ALG("DES-EDE3-ECB:DES-EDE3", tdes_ede3_ecb_functions),
ALG("DES-EDE3-CBC:DES3", tdes_ede3_cbc_functions),
ALG("DES-EDE3-OFB", tdes_ede3_ofb_functions),
ALG("DES-EDE3-CFB", tdes_ede3_cfb_functions),
ALG("DES-EDE3-CFB8", tdes_ede3_cfb8_functions),
ALG("DES-EDE3-CFB1", tdes_ede3_cfb1_functions),
ALG("DES-EDE-ECB:DES-EDE", tdes_ede2_ecb_functions),
ALG("DES-EDE-CBC", tdes_ede2_cbc_functions),
ALG("DES-EDE-OFB", tdes_ede2_ofb_functions),
ALG("DES-EDE-CFB", tdes_ede2_cfb_functions),
ALG("DESX-CBC:DESX", tdes_desx_cbc_functions),
ALG("DES3-WRAP:id-smime-alg-CMS3DESwrap", tdes_wrap_cbc_functions),
ALG("DES-ECB", des_ecb_functions),
ALG("DES-CBC:DES", des_cbc_functions),
ALG("DES-OFB", des_ofb64_functions),
ALG("DES-CFB", des_cfb64_functions),
ALG("DES-CFB1", des_cfb1_functions),
ALG("DES-CFB8", des_cfb8_functions),
#endif /* OPENSSL_NO_DES */
#ifndef OPENSSL_NO_BF
{ "BF-ECB", "default=yes", blowfish128ecb_functions },
{ "BF-CBC:BF:BLOWFISH", "default=yes", blowfish128cbc_functions },
{ "BF-OFB", "default=yes", blowfish64ofb64_functions },
{ "BF-CFB", "default=yes", blowfish64cfb64_functions },
ALG("BF-ECB", blowfish128ecb_functions),
ALG("BF-CBC:BF:BLOWFISH", blowfish128cbc_functions),
ALG("BF-OFB", blowfish64ofb64_functions),
ALG("BF-CFB", blowfish64cfb64_functions),
#endif /* OPENSSL_NO_BF */
#ifndef OPENSSL_NO_IDEA
{ "IDEA-ECB", "default=yes", idea128ecb_functions },
{ "IDEA-CBC:IDEA", "default=yes", idea128cbc_functions },
{ "IDEA-OFB:IDEA-OFB64", "default=yes", idea128ofb64_functions },
{ "IDEA-CFB:IDEA-CFB64", "default=yes", idea128cfb64_functions },
ALG("IDEA-ECB", idea128ecb_functions),
ALG("IDEA-CBC:IDEA", idea128cbc_functions),
ALG("IDEA-OFB:IDEA-OFB64", idea128ofb64_functions),
ALG("IDEA-CFB:IDEA-CFB64", idea128cfb64_functions),
#endif /* OPENSSL_NO_IDEA */
#ifndef OPENSSL_NO_CAST
{ "CAST5-ECB", "default=yes", cast5128ecb_functions },
{ "CAST5-CBC:CAST-CBC:CAST", "default=yes", cast5128cbc_functions },
{ "CAST5-OFB", "default=yes", cast564ofb64_functions },
{ "CAST5-CFB", "default=yes", cast564cfb64_functions },
ALG("CAST5-ECB", cast5128ecb_functions),
ALG("CAST5-CBC:CAST-CBC:CAST", cast5128cbc_functions),
ALG("CAST5-OFB", cast564ofb64_functions),
ALG("CAST5-CFB", cast564cfb64_functions),
#endif /* OPENSSL_NO_CAST */
#ifndef OPENSSL_NO_SEED
{ "SEED-ECB", "default=yes", seed128ecb_functions },
{ "SEED-CBC:SEED", "default=yes", seed128cbc_functions },
{ "SEED-OFB:SEED-OFB128", "default=yes", seed128ofb128_functions },
{ "SEED-CFB:SEED-CFB128", "default=yes", seed128cfb128_functions },
ALG("SEED-ECB", seed128ecb_functions),
ALG("SEED-CBC:SEED", seed128cbc_functions),
ALG("SEED-OFB:SEED-OFB128", seed128ofb128_functions),
ALG("SEED-CFB:SEED-CFB128", seed128cfb128_functions),
#endif /* OPENSSL_NO_SEED */
#ifndef OPENSSL_NO_SM4
{ "SM4-ECB", "default=yes", sm4128ecb_functions },
{ "SM4-CBC:SM4", "default=yes", sm4128cbc_functions },
{ "SM4-CTR", "default=yes", sm4128ctr_functions },
{ "SM4-OFB:SM4-OFB128", "default=yes", sm4128ofb128_functions },
{ "SM4-CFB:SM4-CFB128", "default=yes", sm4128cfb128_functions },
ALG("SM4-ECB", sm4128ecb_functions),
ALG("SM4-CBC:SM4", sm4128cbc_functions),
ALG("SM4-CTR", sm4128ctr_functions),
ALG("SM4-OFB:SM4-OFB128", sm4128ofb128_functions),
ALG("SM4-CFB:SM4-CFB128", sm4128cfb128_functions),
#endif /* OPENSSL_NO_SM4 */
#ifndef OPENSSL_NO_RC4
{ "RC4", "default=yes", rc4128_functions },
{ "RC4-40", "default=yes", rc440_functions },
ALG("RC4", rc4128_functions),
ALG("RC4-40", rc440_functions),
# ifndef OPENSSL_NO_MD5
ALG("RC4-HMAC-MD5", rc4_hmac_md5_functions),
# endif /* OPENSSL_NO_MD5 */
#endif /* OPENSSL_NO_RC4 */
#ifndef OPENSSL_NO_RC5
{ "RC5-ECB", "default=yes", rc5128ecb_functions },
{ "RC5-CBC", "default=yes", rc5128cbc_functions },
{ "RC5-OFB", "default=yes", rc5128ofb64_functions },
{ "RC5-CFB", "default=yes", rc5128cfb64_functions },
ALG("RC5-ECB", rc5128ecb_functions),
ALG("RC5-CBC", rc5128cbc_functions),
ALG("RC5-OFB", rc5128ofb64_functions),
ALG("RC5-CFB", rc5128cfb64_functions),
#endif /* OPENSSL_NO_RC5 */
#ifndef OPENSSL_NO_RC2
{ "RC2-ECB", "default=yes", rc2128ecb_functions },
{ "RC2-CBC", "default=yes", rc2128cbc_functions },
{ "RC2-40-CBC", "default=yes", rc240cbc_functions },
{ "RC2-64-CBC", "default=yes", rc264cbc_functions },
{ "RC2-CFB", "default=yes", rc2128cfb128_functions },
{ "RC2-OFB", "default=yes", rc2128ofb128_functions },
ALG("RC2-ECB", rc2128ecb_functions),
ALG("RC2-CBC", rc2128cbc_functions),
ALG("RC2-40-CBC", rc240cbc_functions),
ALG("RC2-64-CBC", rc264cbc_functions),
ALG("RC2-CFB", rc2128cfb128_functions),
ALG("RC2-OFB", rc2128ofb128_functions),
#endif /* OPENSSL_NO_RC2 */
#ifndef OPENSSL_NO_CHACHA
{ "ChaCha20", "default=yes", chacha20_functions },
ALG("ChaCha20", chacha20_functions),
# ifndef OPENSSL_NO_POLY1305
{ "ChaCha20-Poly1305", "default=yes", chacha20_poly1305_functions },
ALG("ChaCha20-Poly1305", chacha20_poly1305_functions),
# endif /* OPENSSL_NO_POLY1305 */
#endif /* OPENSSL_NO_CHACHA */
{ NULL, NULL, NULL }
{ { NULL, NULL, NULL }, NULL }
};
static OSSL_ALGORITHM exported_ciphers[OSSL_NELEM(deflt_ciphers)];
static const OSSL_ALGORITHM deflt_macs[] = {
#ifndef OPENSSL_NO_BLAKE2
{ "BLAKE2bMAC", "default=yes", blake2bmac_functions },
{ "BLAKE2sMAC", "default=yes", blake2smac_functions },
{ "BLAKE2BMAC", "default=yes", blake2bmac_functions },
{ "BLAKE2SMAC", "default=yes", blake2smac_functions },
#endif
#ifndef OPENSSL_NO_CMAC
{ "CMAC", "default=yes", cmac_functions },
#endif
{ "GMAC", "default=yes", gmac_functions },
{ "HMAC", "default=yes", hmac_functions },
{ "KMAC128", "default=yes", kmac128_functions },
{ "KMAC256", "default=yes", kmac256_functions },
{ "KMAC-128:KMAC128", "default=yes", kmac128_functions },
{ "KMAC-256:KMAC256", "default=yes", kmac256_functions },
#ifndef OPENSSL_NO_SIPHASH
{ "SipHash", "default=yes", siphash_functions },
{ "SIPHASH", "default=yes", siphash_functions },
#endif
#ifndef OPENSSL_NO_POLY1305
{ "Poly1305", "default=yes", poly1305_functions },
{ "POLY1305", "default=yes", poly1305_functions },
#endif
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM deflt_kdfs[] = {
{ OSSL_KDF_NAME_HKDF, "default=yes", kdf_hkdf_functions },
{ OSSL_KDF_NAME_SSKDF, "default=yes", kdf_sskdf_functions },
{ OSSL_KDF_NAME_PBKDF2, "default=yes", kdf_pbkdf2_functions },
{ OSSL_KDF_NAME_SSHKDF, "default=yes", kdf_sshkdf_functions },
{ OSSL_KDF_NAME_X963KDF, "default=yes", kdf_x963_kdf_functions },
{ OSSL_KDF_NAME_TLS1_PRF, "default=yes", kdf_tls1_prf_functions },
{ OSSL_KDF_NAME_KBKDF, "default=yes", kdf_kbkdf_functions },
{ "HKDF", "default=yes", kdf_hkdf_functions },
{ "SSKDF", "default=yes", kdf_sskdf_functions },
{ "PBKDF2", "default=yes", kdf_pbkdf2_functions },
{ "SSHKDF", "default=yes", kdf_sshkdf_functions },
{ "X963KDF", "default=yes", kdf_x963_kdf_functions },
{ "TLS1-PRF", "default=yes", kdf_tls1_prf_functions },
{ "KBKDF", "default=yes", kdf_kbkdf_functions },
#ifndef OPENSSL_NO_CMS
{ OSSL_KDF_NAME_X942KDF, "default=yes", kdf_x942_kdf_functions },
{ "X942KDF", "default=yes", kdf_x942_kdf_functions },
#endif
#ifndef OPENSSL_NO_SCRYPT
{ "SCRYPT:id-scrypt", "default=yes", kdf_scrypt_functions },
#endif
{ NULL, NULL, NULL }
{ "KRB5KDF", "default=yes", kdf_krb5kdf_functions },
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM deflt_keyexch[] = {
@@ -356,14 +381,78 @@ static const OSSL_ALGORITHM deflt_signature[] = {
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM deflt_asym_cipher[] = {
{ "RSA:rsaEncryption", "default=yes", rsa_asym_cipher_functions },
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM deflt_keymgmt[] = {
#ifndef OPENSSL_NO_DH
{ "DH", "default=yes", dh_keymgmt_functions },
{ "DH:dhKeyAgreement", "default=yes", dh_keymgmt_functions },
#endif
#ifndef OPENSSL_NO_DSA
{ "DSA", "default=yes", dsa_keymgmt_functions },
{ "DSA:dsaEncryption", "default=yes", dsa_keymgmt_functions },
#endif
{ "RSA:rsaEncryption", "default=yes", rsa_keymgmt_functions },
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM deflt_serializer[] = {
{ "RSA", "default=yes,format=text,type=private",
rsa_priv_text_serializer_functions },
{ "RSA", "default=yes,format=text,type=public",
rsa_pub_text_serializer_functions },
{ "RSA", "default=yes,format=der,type=private",
rsa_priv_der_serializer_functions },
{ "RSA", "default=yes,format=der,type=public",
rsa_pub_der_serializer_functions },
{ "RSA", "default=yes,format=pem,type=private",
rsa_priv_pem_serializer_functions },
{ "RSA", "default=yes,format=pem,type=public",
rsa_pub_pem_serializer_functions },
#ifndef OPENSSL_NO_DH
{ "DH", "default=yes,format=text,type=private",
dh_priv_text_serializer_functions },
{ "DH", "default=yes,format=text,type=public",
dh_pub_text_serializer_functions },
{ "DH", "default=yes,format=text,type=domainparams",
dh_param_text_serializer_functions },
{ "DH", "default=yes,format=der,type=private",
dh_priv_der_serializer_functions },
{ "DH", "default=yes,format=der,type=public",
dh_pub_der_serializer_functions },
{ "DH", "default=yes,format=der,type=domainparams",
dh_param_der_serializer_functions },
{ "DH", "default=yes,format=pem,type=private",
dh_priv_pem_serializer_functions },
{ "DH", "default=yes,format=pem,type=public",
dh_pub_pem_serializer_functions },
{ "DH", "default=yes,format=pem,type=domainparams",
dh_param_pem_serializer_functions },
#endif
#ifndef OPENSSL_NO_DSA
{ "DSA", "default=yes,format=text,type=private",
dsa_priv_text_serializer_functions },
{ "DSA", "default=yes,format=text,type=public",
dsa_pub_text_serializer_functions },
{ "DSA", "default=yes,format=text,type=domainparams",
dsa_param_text_serializer_functions },
{ "DSA", "default=yes,format=der,type=private",
dsa_priv_der_serializer_functions },
{ "DSA", "default=yes,format=der,type=public",
dsa_pub_der_serializer_functions },
{ "DSA", "default=yes,format=der,type=domainparams",
dsa_param_der_serializer_functions },
{ "DSA", "default=yes,format=pem,type=private",
dsa_priv_pem_serializer_functions },
{ "DSA", "default=yes,format=pem,type=public",
dsa_pub_pem_serializer_functions },
{ "DSA", "default=yes,format=pem,type=domainparams",
dsa_param_pem_serializer_functions },
#endif
{ NULL, NULL, NULL }
};
@@ -376,7 +465,8 @@ static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov,
case OSSL_OP_DIGEST:
return deflt_digests;
case OSSL_OP_CIPHER:
return deflt_ciphers;
ossl_prov_cache_exported_algorithms(deflt_ciphers, exported_ciphers);
return exported_ciphers;
case OSSL_OP_MAC:
return deflt_macs;
case OSSL_OP_KDF:
@@ -387,6 +477,10 @@ static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov,
return deflt_keyexch;
case OSSL_OP_SIGNATURE:
return deflt_signature;
case OSSL_OP_ASYM_CIPHER:
return deflt_asym_cipher;
case OSSL_OP_SERIALIZER:
return deflt_serializer;
}
return NULL;
}
@@ -408,6 +502,8 @@ int ossl_default_provider_init(const OSSL_PROVIDER *provider,
{
OSSL_core_get_library_context_fn *c_get_libctx = NULL;
if (!ossl_prov_bio_from_dispatch(in))
return 0;
for (; in->function_id != 0; in++) {
switch (in->function_id) {
case OSSL_FUNC_CORE_GETTABLE_PARAMS:
+2 -3
View File
@@ -1,3 +1,2 @@
SOURCE[../fips]=fipsprov.c selftest.c
INCLUDE[../fips]=../implementations/include ../common/include
SOURCE[../fips]=fipsprov.c self_test.c self_test_kats.c self_test_event.c
INCLUDE[../fips]=../implementations/include ../common/include ../..
+261 -56
View File
@@ -25,11 +25,16 @@
#include "internal/cryptlib.h"
#include "internal/property.h"
#include "internal/nelem.h"
#include "crypto/evp.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "prov/providercommon.h"
#include "selftest.h"
#include "prov/provider_util.h"
#include "self_test.h"
#define ALGC(NAMES, FUNC, CHECK) { { NAMES, "fips=yes", FUNC }, CHECK }
#define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL)
extern OSSL_core_thread_start_fn *c_thread_start;
@@ -116,6 +121,49 @@ static OSSL_PARAM core_params[] =
OSSL_PARAM_END
};
/*
* This routine is currently necessary as bn params are currently processed
* using BN_native2bn when raw data is received. This means we need to do
* magic to reverse the order of the bytes to match native format.
* The array of hexdata is to get around compilers that dont like
* strings longer than 509 bytes,
*/
static int rawnative_fromhex(const char *hex_data[],
unsigned char **native, size_t *nativelen)
{
int ret = 0;
unsigned char *data = NULL;
BIGNUM *bn = NULL;
int i, slen, datalen, sz;
char *str = NULL;
for (slen = 0, i = 0; hex_data[i] != NULL; ++i)
slen += strlen(hex_data[i]);
str = OPENSSL_zalloc(slen + 1);
if (str == NULL)
return 0;
for (i = 0; hex_data[i] != NULL; ++i)
strcat(str, hex_data[i]);
if (BN_hex2bn(&bn, str) <= 0)
return 0;
datalen = slen / 2;
data = (unsigned char *)str; /* reuse the str buffer */
sz = BN_bn2nativepad(bn, data, datalen);
if (sz <= 0)
goto err;
ret = 1;
*native = data;
*nativelen = datalen;
data = NULL; /* so it does not get freed */
err:
BN_free(bn);
OPENSSL_free(data);
return ret;
}
/* TODO(3.0): To be removed */
static int dummy_evp_call(void *provctx)
{
@@ -123,6 +171,58 @@ static int dummy_evp_call(void *provctx)
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
EVP_MD *sha256 = EVP_MD_fetch(libctx, "SHA256", NULL);
EVP_KDF *kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_PBKDF2, NULL);
EVP_PKEY_CTX *sctx = NULL, *kctx = NULL;
EVP_PKEY *pkey = NULL;
OSSL_PARAM *p;
OSSL_PARAM params[16];
unsigned char sig[64];
size_t siglen, sigdgstlen;
unsigned char *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
unsigned char *dsa_pub = NULL, *dsa_priv = NULL;
size_t dsa_p_len, dsa_q_len, dsa_g_len, dsa_pub_len, dsa_priv_len;
/* dsa 2048 */
static const char *dsa_p_hex[] = {
"a29b8872ce8b8423b7d5d21d4b02f57e03e9e6b8a258dc16611ba098ab543415"
"e415f156997a3ee236658fa093260de3ad422e05e046f9ec29161a375f0eb4ef"
"fcef58285c5d39ed425d7a62ca12896c4a92cb1946f2952a48133f07da364d1b"
"df6b0f7139983e693c80059b0eacd1479ba9f2857754ede75f112b07ebbf3534",
"8bbf3e01e02f2d473de39453f99dd2367541caca3ba01166343d7b5b58a37bd1"
"b7521db2f13b86707132fe09f4cd09dc1618fa3401ebf9cc7b19fa94aa472088"
"133d6cb2d35c1179c8c8ff368758d507d9f9a17d46c110fe3144ce9b022b42e4"
"19eb4f5388613bfc3e26241a432e8706bc58ef76117278deab6cf692618291b7",
NULL
};
static const char *dsa_q_hex[] = {
"a3bfd9ab7884794e383450d5891dc18b65157bdcfcdac51518902867",
NULL
};
static const char *dsa_g_hex[] = {
"6819278869c7fd3d2d7b77f77e8150d9ad433bea3ba85efc80415aa3545f78f7"
"2296f06cb19ceda06c94b0551cfe6e6f863e31d1de6eed7dab8b0c9df231e084"
"34d1184f91d033696bb382f8455e9888f5d31d4784ec40120246f4bea61794bb"
"a5866f09746463bdf8e9e108cd9529c3d0f6df80316e2e70aaeb1b26cdb8ad97",
"bc3d287e0b8d616c42e65b87db20deb7005bc416747a6470147a68a7820388eb"
"f44d52e0628af9cf1b7166d03465f35acc31b6110c43dabc7c5d591e671eaf7c"
"252c1c145336a1a4ddf13244d55e835680cab2533b82df2efe55ec18c1e6cd00"
"7bb089758bb17c2cbe14441bd093ae66e5976d53733f4fa3269701d31d23d467",
NULL
};
static const char *dsa_pub_hex[] = {
"a012b3b170b307227957b7ca2061a816ac7a2b3d9ae995a5119c385b603bf6f6"
"c5de4dc5ecb5dfa4a41c68662eb25b638b7e2620ba898d07da6c4991e76cc0ec"
"d1ad3421077067e47c18f58a92a72ad43199ecb7bd84e7d3afb9019f0e9dd0fb"
"aa487300b13081e33c902876436f7b03c345528481d362815e24fe59dac5ac34",
"660d4c8a76cb99a7c7de93eb956cd6bc88e58d901034944a094b01803a43c672"
"b9688c0e01d8f4fc91c62a3f88021f7bd6a651b1a88f43aa4ef27653d12bf8b7"
"099fdf6b461082f8e939107bfd2f7210087d326c375200f1f51e7e74a3413190"
"1bcd0863521ff8d676c48581868736c5e51b16a4e39215ea0b17c4735974c516",
NULL
};
static const char *dsa_priv_hex[] = {
"6ccaeef6d73b4e80f11c17b8e9627c036635bac39423505e407e5cb7",
NULL
};
char msg[] = "Hello World!";
const unsigned char exptd[] = {
0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81,
@@ -181,7 +281,54 @@ static int dummy_evp_call(void *provctx)
if (!EC_KEY_generate_key(key))
goto err;
#endif
if (!rawnative_fromhex(dsa_p_hex, &dsa_p, &dsa_p_len)
|| !rawnative_fromhex(dsa_q_hex, &dsa_q, &dsa_q_len)
|| !rawnative_fromhex(dsa_g_hex, &dsa_g, &dsa_g_len)
|| !rawnative_fromhex(dsa_pub_hex, &dsa_pub, &dsa_pub_len)
|| !rawnative_fromhex(dsa_priv_hex, &dsa_priv, &dsa_priv_len))
goto err;
p = params;
*p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_P, dsa_p, dsa_p_len);
*p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_Q, dsa_q, dsa_q_len);
*p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_G, dsa_g, dsa_g_len);
*p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_DSA_PUB_KEY,
dsa_pub, dsa_pub_len);
*p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_DSA_PRIV_KEY,
dsa_priv, dsa_priv_len);
*p = OSSL_PARAM_construct_end();
kctx = EVP_PKEY_CTX_new_from_name(libctx, SN_dsa, "");
if (kctx == NULL)
goto err;
if (EVP_PKEY_key_fromdata_init(kctx) <= 0
|| EVP_PKEY_fromdata(kctx, &pkey, params) <= 0)
goto err;
sctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey);
if (sctx == NULL)
goto err;;
if (EVP_PKEY_sign_init(sctx) <= 0)
goto err;
/* set signature parameters */
sigdgstlen = SHA256_DIGEST_LENGTH;
p = params;
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST,
SN_sha256,
strlen(SN_sha256) + 1);
*p++ = OSSL_PARAM_construct_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE,
&sigdgstlen);
*p = OSSL_PARAM_construct_end();
if (EVP_PKEY_CTX_set_params(sctx, params) <= 0)
goto err;
if (EVP_PKEY_sign(sctx, sig, &siglen, dgst, sizeof(dgst)) <= 0
|| EVP_PKEY_verify_init(sctx) <= 0
|| EVP_PKEY_verify(sctx, sig, siglen, dgst, sizeof(dgst)) <= 0)
goto err;
ret = 1;
err:
BN_CTX_end(bnctx);
@@ -194,6 +341,14 @@ static int dummy_evp_call(void *provctx)
#ifndef OPENSSL_NO_EC
EC_KEY_free(key);
#endif
OPENSSL_free(dsa_p);
OPENSSL_free(dsa_q);
OPENSSL_free(dsa_g);
OPENSSL_free(dsa_pub);
OPENSSL_free(dsa_priv);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(kctx);
EVP_PKEY_CTX_free(sctx);
return ret;
}
@@ -300,6 +455,14 @@ const char *ossl_prov_util_nid_to_name(int nid)
return "DES-EDE3";
case NID_des_ede3_cbc:
return "DES-EDE3-CBC";
case NID_aes_256_cbc_hmac_sha256:
return "AES-256-CBC-HMAC-SHA256";
case NID_aes_128_cbc_hmac_sha256:
return "AES-128-CBC-HMAC-SHA256";
case NID_aes_256_cbc_hmac_sha1:
return "AES-256-CBC-HMAC-SHA1";
case NID_aes_128_cbc_hmac_sha1:
return "AES-128-CBC-HMAC-SHA1";
default:
break;
}
@@ -349,52 +512,58 @@ static const OSSL_ALGORITHM fips_digests[] = {
{ "SHA3-384", "fips=yes", sha3_384_functions },
{ "SHA3-512", "fips=yes", sha3_512_functions },
/*
* KECCAK_KMAC128 and KECCAK_KMAC256 as hashes are mostly useful for
* KECCAK-KMAC-128 and KECCAK-KMAC-256 as hashes are mostly useful for
* KMAC128 and KMAC256.
*/
{ "KECCAK_KMAC128", "fips=yes", keccak_kmac_128_functions },
{ "KECCAK_KMAC256", "fips=yes", keccak_kmac_256_functions },
{ "KECCAK-KMAC-128:KECCAK-KMAC128", "fips=yes", keccak_kmac_128_functions },
{ "KECCAK-KMAC-256:KECCAK-KMAC256", "fips=yes", keccak_kmac_256_functions },
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM fips_ciphers[] = {
static const OSSL_ALGORITHM_CAPABLE fips_ciphers[] = {
/* Our primary name[:ASN.1 OID name][:our older names] */
{ "AES-256-ECB", "fips=yes", aes256ecb_functions },
{ "AES-192-ECB", "fips=yes", aes192ecb_functions },
{ "AES-128-ECB", "fips=yes", aes128ecb_functions },
{ "AES-256-CBC", "fips=yes", aes256cbc_functions },
{ "AES-192-CBC", "fips=yes", aes192cbc_functions },
{ "AES-128-CBC", "fips=yes", aes128cbc_functions },
{ "AES-256-CTR", "fips=yes", aes256ctr_functions },
{ "AES-192-CTR", "fips=yes", aes192ctr_functions },
{ "AES-128-CTR", "fips=yes", aes128ctr_functions },
{ "AES-256-XTS", "fips=yes", aes256xts_functions },
{ "AES-128-XTS", "fips=yes", aes128xts_functions },
{ "AES-256-GCM:id-aes256-GCM", "fips=yes", aes256gcm_functions },
{ "AES-192-GCM:id-aes192-GCM", "fips=yes", aes192gcm_functions },
{ "AES-128-GCM:id-aes128-GCM", "fips=yes", aes128gcm_functions },
{ "AES-256-CCM:id-aes256-CCM", "fips=yes", aes256ccm_functions },
{ "AES-192-CCM:id-aes192-CCM", "fips=yes", aes192ccm_functions },
{ "AES-128-CCM:id-aes128-CCM", "fips=yes", aes128ccm_functions },
{ "AES-256-WRAP:id-aes256-wrap:AES256-WRAP", "fips=yes",
aes256wrap_functions },
{ "AES-192-WRAP:id-aes192-wrap:AES192-WRAP", "fips=yes",
aes192wrap_functions },
{ "AES-128-WRAP:id-aes128-wrap:AES128-WRAP", "fips=yes",
aes128wrap_functions },
{ "AES-256-WRAP-PAD:id-aes256-wrap-pad:AES256-WRAP-PAD", "fips=yes",
aes256wrappad_functions },
{ "AES-192-WRAP-PAD:id-aes192-wrap-pad:AES192-WRAP-PAD", "fips=yes",
aes192wrappad_functions },
{ "AES-128-WRAP-PAD:id-aes128-wrap-pad:AES128-WRAP-PAD", "fips=yes",
aes128wrappad_functions },
ALG("AES-256-ECB", aes256ecb_functions),
ALG("AES-192-ECB", aes192ecb_functions),
ALG("AES-128-ECB", aes128ecb_functions),
ALG("AES-256-CBC", aes256cbc_functions),
ALG("AES-192-CBC", aes192cbc_functions),
ALG("AES-128-CBC", aes128cbc_functions),
ALG("AES-256-CTR", aes256ctr_functions),
ALG("AES-192-CTR", aes192ctr_functions),
ALG("AES-128-CTR", aes128ctr_functions),
ALG("AES-256-XTS", aes256xts_functions),
ALG("AES-128-XTS", aes128xts_functions),
ALG("AES-256-GCM:id-aes256-GCM", aes256gcm_functions),
ALG("AES-192-GCM:id-aes192-GCM", aes192gcm_functions),
ALG("AES-128-GCM:id-aes128-GCM", aes128gcm_functions),
ALG("AES-256-CCM:id-aes256-CCM", aes256ccm_functions),
ALG("AES-192-CCM:id-aes192-CCM", aes192ccm_functions),
ALG("AES-128-CCM:id-aes128-CCM", aes128ccm_functions),
ALG("AES-256-WRAP:id-aes256-wrap:AES256-WRAP", aes256wrap_functions),
ALG("AES-192-WRAP:id-aes192-wrap:AES192-WRAP", aes192wrap_functions),
ALG("AES-128-WRAP:id-aes128-wrap:AES128-WRAP", aes128wrap_functions),
ALG("AES-256-WRAP-PAD:id-aes256-wrap-pad:AES256-WRAP-PAD",
aes256wrappad_functions),
ALG("AES-192-WRAP-PAD:id-aes192-wrap-pad:AES192-WRAP-PAD",
aes192wrappad_functions),
ALG("AES-128-WRAP-PAD:id-aes128-wrap-pad:AES128-WRAP-PAD",
aes128wrappad_functions),
ALGC("AES-128-CBC-HMAC-SHA1", aes128cbc_hmac_sha1_functions,
cipher_capable_aes_cbc_hmac_sha1),
ALGC("AES-256-CBC-HMAC-SHA1", aes256cbc_hmac_sha1_functions,
cipher_capable_aes_cbc_hmac_sha1),
ALGC("AES-128-CBC-HMAC-SHA256", aes128cbc_hmac_sha256_functions,
cipher_capable_aes_cbc_hmac_sha256),
ALGC("AES-256-CBC-HMAC-SHA256", aes256cbc_hmac_sha256_functions,
cipher_capable_aes_cbc_hmac_sha256),
#ifndef OPENSSL_NO_DES
{ "DES-EDE3-ECB:DES-EDE3", "fips=yes", tdes_ede3_ecb_functions },
{ "DES-EDE3-CBC:DES3", "fips=yes", tdes_ede3_cbc_functions },
ALG("DES-EDE3-ECB:DES-EDE3", tdes_ede3_ecb_functions),
ALG("DES-EDE3-CBC:DES3", tdes_ede3_cbc_functions),
#endif /* OPENSSL_NO_DES */
{ NULL, NULL, NULL }
{ { NULL, NULL, NULL }, NULL }
};
static OSSL_ALGORITHM exported_fips_ciphers[OSSL_NELEM(fips_ciphers)];
static const OSSL_ALGORITHM fips_macs[] = {
#ifndef OPENSSL_NO_CMAC
@@ -402,17 +571,31 @@ static const OSSL_ALGORITHM fips_macs[] = {
#endif
{ "GMAC", "fips=yes", gmac_functions },
{ "HMAC", "fips=yes", hmac_functions },
{ "KMAC128", "fips=yes", kmac128_functions },
{ "KMAC256", "fips=yes", kmac256_functions },
{ "KMAC-128:KMAC128", "fips=yes", kmac128_functions },
{ "KMAC-256:KMAC256", "fips=yes", kmac256_functions },
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM fips_kdfs[] = {
{ OSSL_KDF_NAME_HKDF, "fips=yes", kdf_hkdf_functions },
{ OSSL_KDF_NAME_SSKDF, "fips=yes", kdf_sskdf_functions },
{ OSSL_KDF_NAME_PBKDF2, "fips=yes", kdf_pbkdf2_functions },
{ OSSL_KDF_NAME_TLS1_PRF, "fips=yes", kdf_tls1_prf_functions },
{ OSSL_KDF_NAME_KBKDF, "fips=yes", kdf_kbkdf_functions },
{ "HKDF", "fips=yes", kdf_hkdf_functions },
{ "SSKDF", "fips=yes", kdf_sskdf_functions },
{ "PBKDF2", "fips=yes", kdf_pbkdf2_functions },
{ "TLS1-PRF", "fips=yes", kdf_tls1_prf_functions },
{ "KBKDF", "fips=yes", kdf_kbkdf_functions },
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM fips_signature[] = {
#ifndef OPENSSL_NO_DSA
{ "DSA:dsaEncryption", "fips=yes", dsa_signature_functions },
#endif
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM fips_keymgmt[] = {
#ifndef OPENSSL_NO_DSA
{ "DSA", "fips=yes", dsa_keymgmt_functions },
#endif
{ NULL, NULL, NULL }
};
@@ -425,11 +608,16 @@ static const OSSL_ALGORITHM *fips_query(OSSL_PROVIDER *prov,
case OSSL_OP_DIGEST:
return fips_digests;
case OSSL_OP_CIPHER:
return fips_ciphers;
ossl_prov_cache_exported_algorithms(fips_ciphers, exported_fips_ciphers);
return exported_fips_ciphers;
case OSSL_OP_MAC:
return fips_macs;
case OSSL_OP_KDF:
return fips_kdfs;
case OSSL_OP_KEYMGMT:
return fips_keymgmt;
case OSSL_OP_SIGNATURE:
return fips_signature;
}
return NULL;
}
@@ -461,9 +649,14 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
{
FIPS_GLOBAL *fgbl;
OPENSSL_CTX *ctx;
OSSL_self_test_cb_fn *stcbfn = NULL;
OSSL_core_get_library_context_fn *c_get_libctx = NULL;
for (; in->function_id != 0; in++) {
switch (in->function_id) {
case OSSL_FUNC_CORE_GET_LIBRARY_CONTEXT:
c_get_libctx = OSSL_get_core_get_library_context(in);
break;
case OSSL_FUNC_CORE_GETTABLE_PARAMS:
c_gettable_params = OSSL_get_core_gettable_params(in);
break;
@@ -527,12 +720,25 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
case OSSL_FUNC_BIO_FREE:
selftest_params.bio_free_cb = OSSL_get_BIO_free(in);
break;
case OSSL_FUNC_SELF_TEST_CB: {
stcbfn = OSSL_get_self_test_cb(in);
break;
}
default:
/* Just ignore anything we don't understand */
break;
}
}
if (stcbfn != NULL && c_get_libctx != NULL) {
stcbfn(c_get_libctx(provider), &selftest_params.event_cb,
&selftest_params.event_cb_arg);
}
else {
selftest_params.event_cb = NULL;
selftest_params.event_cb_arg = NULL;
}
if (!c_get_params(provider, core_params))
return 0;
@@ -548,7 +754,16 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
fgbl->prov = provider;
selftest_params.libctx = PROV_LIBRARY_CONTEXT_OF(ctx);
if (!SELF_TEST_post(&selftest_params)) {
if (!SELF_TEST_post(&selftest_params, 0)) {
OPENSSL_CTX_free(ctx);
return 0;
}
/*
* TODO(3.0): Remove me. This is just a dummy call to demonstrate making
* EVP calls from within the FIPS module.
*/
if (!dummy_evp_call(ctx)) {
OPENSSL_CTX_free(ctx);
return 0;
}
@@ -556,16 +771,6 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
*out = fips_dispatch_table;
*provctx = ctx;
/*
* TODO(3.0): Remove me. This is just a dummy call to demonstrate making
* EVP calls from within the FIPS module.
*/
if (!dummy_evp_call(*provctx)) {
OPENSSL_CTX_free(*provctx);
*provctx = NULL;
return 0;
}
return 1;
}
+285
View File
@@ -0,0 +1,285 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/evp.h>
#include <openssl/params.h>
#include <openssl/crypto.h>
#include "e_os.h"
/*
* We're cheating here. Normally we don't allow RUN_ONCE usage inside the FIPS
* module because all such initialisation should be associated with an
* individual OPENSSL_CTX. That doesn't work with the self test though because
* it should be run once regardless of the number of OPENSSL_CTXs we have.
*/
#define ALLOW_RUN_ONCE_IN_FIPS
#include <internal/thread_once.h>
#include "self_test.h"
#define FIPS_STATE_INIT 0
#define FIPS_STATE_SELFTEST 1
#define FIPS_STATE_RUNNING 2
#define FIPS_STATE_ERROR 3
/* The size of a temp buffer used to read in data */
#define INTEGRITY_BUF_SIZE (4096)
#define MAX_MD_SIZE 64
#define MAC_NAME "HMAC"
#define DIGEST_NAME "SHA256"
static int FIPS_state = FIPS_STATE_INIT;
static CRYPTO_RWLOCK *self_test_lock = NULL;
static unsigned char fixed_key[32] = { 0 };
static CRYPTO_ONCE fips_self_test_init = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(do_fips_self_test_init)
{
/*
* This lock gets freed in platform specific ways that may occur after we
* do mem leak checking. If we don't know how to free it for a particular
* platform then we just leak it deliberately. So we temporarily disable the
* mem leak checking while we allocate this.
*/
self_test_lock = CRYPTO_THREAD_lock_new();
return self_test_lock != NULL;
}
#define DEP_DECLARE() \
void init(void); \
void cleanup(void);
/*
* This is the Default Entry Point (DEP) code. Every platform must have a DEP.
* See FIPS 140-2 IG 9.10
*
* If we're run on a platform where we don't know how to define the DEP then
* the self-tests will never get triggered (FIPS_state never moves to
* FIPS_STATE_SELFTEST). This will be detected as an error when SELF_TEST_post()
* is called from OSSL_provider_init(), and so the fips module will be unusable
* on those platforms.
*/
#if defined(_WIN32) || defined(__CYGWIN__)
# ifdef __CYGWIN__
/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
# include <windows.h>
/*
* this has side-effect of _WIN32 getting defined, which otherwise is
* mutually exclusive with __CYGWIN__...
*/
# endif
DEP_DECLARE()
# define DEP_INIT_ATTRIBUTE
# define DEP_FINI_ATTRIBUTE
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
init();
break;
case DLL_PROCESS_DETACH:
cleanup();
break;
default:
break;
}
return TRUE;
}
#elif defined(__sun)
DEP_DECLARE() /* must be declared before pragma */
# define DEP_INIT_ATTRIBUTE
# define DEP_FINI_ATTRIBUTE
# pragma init(init)
# pragma fini(cleanup)
#elif defined(__hpux)
DEP_DECLARE()
# define DEP_INIT_ATTRIBUTE
# define DEP_FINI_ATTRIBUTE
# pragma init "init"
# pragma fini "cleanup"
#elif defined(__GNUC__)
# define DEP_INIT_ATTRIBUTE static __attribute__((constructor))
# define DEP_FINI_ATTRIBUTE static __attribute__((destructor))
#endif
#if defined(DEP_INIT_ATTRIBUTE) && defined(DEP_FINI_ATTRIBUTE)
DEP_INIT_ATTRIBUTE void init(void)
{
FIPS_state = FIPS_STATE_SELFTEST;
}
DEP_FINI_ATTRIBUTE void cleanup(void)
{
CRYPTO_THREAD_lock_free(self_test_lock);
}
#endif
/*
* Calculate the HMAC SHA256 of data read using a BIO and read_cb, and verify
* the result matches the expected value.
* Return 1 if verified, or 0 if it fails.
*/
static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
unsigned char *expected, size_t expected_len,
OPENSSL_CTX *libctx, OSSL_ST_EVENT *ev,
const char *event_type)
{
int ret = 0, status;
unsigned char out[MAX_MD_SIZE];
unsigned char buf[INTEGRITY_BUF_SIZE];
size_t bytes_read = 0, out_len = 0;
EVP_MAC *mac = NULL;
EVP_MAC_CTX *ctx = NULL;
OSSL_PARAM params[3], *p = params;
SELF_TEST_EVENT_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
ctx = EVP_MAC_CTX_new(mac);
if (mac == NULL || ctx == NULL)
goto err;
*p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME,
strlen(DIGEST_NAME) + 1);
*p++ = OSSL_PARAM_construct_octet_string("key", fixed_key,
sizeof(fixed_key));
*p = OSSL_PARAM_construct_end();
if (EVP_MAC_CTX_set_params(ctx, params) <= 0
|| !EVP_MAC_init(ctx))
goto err;
while (1) {
status = read_ex_cb(bio, buf, sizeof(buf), &bytes_read);
if (status != 1)
break;
if (!EVP_MAC_update(ctx, buf, bytes_read))
goto err;
}
if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out)))
goto err;
SELF_TEST_EVENT_oncorrupt_byte(ev, out);
if (expected_len != out_len
|| memcmp(expected, out, out_len) != 0)
goto err;
ret = 1;
err:
SELF_TEST_EVENT_onend(ev, ret);
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
return ret;
}
/* This API is triggered either on loading of the FIPS module or on demand */
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
{
int ok = 0;
int kats_already_passed = 0;
long checksum_len;
BIO *bio_module = NULL, *bio_indicator = NULL;
unsigned char *module_checksum = NULL;
unsigned char *indicator_checksum = NULL;
int loclstate;
OSSL_ST_EVENT ev;
if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init))
return 0;
CRYPTO_THREAD_read_lock(self_test_lock);
loclstate = FIPS_state;
CRYPTO_THREAD_unlock(self_test_lock);
if (loclstate == FIPS_STATE_RUNNING) {
if (!on_demand_test)
return 1;
} else if (loclstate != FIPS_STATE_SELFTEST) {
return 0;
}
CRYPTO_THREAD_write_lock(self_test_lock);
if (FIPS_state == FIPS_STATE_RUNNING) {
if (!on_demand_test) {
CRYPTO_THREAD_unlock(self_test_lock);
return 1;
}
FIPS_state = FIPS_STATE_SELFTEST;
} else if (FIPS_state != FIPS_STATE_SELFTEST) {
CRYPTO_THREAD_unlock(self_test_lock);
return 0;
}
if (st == NULL
|| st->module_checksum_data == NULL)
goto end;
SELF_TEST_EVENT_init(&ev, st->event_cb, st->event_cb_arg);
module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data,
&checksum_len);
if (module_checksum == NULL)
goto end;
bio_module = (*st->bio_new_file_cb)(st->module_filename, "rb");
/* Always check the integrity of the fips module */
if (bio_module == NULL
|| !verify_integrity(bio_module, st->bio_read_ex_cb,
module_checksum, checksum_len, st->libctx,
&ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY))
goto end;
/* This will be NULL during installation - so the self test KATS will run */
if (st->indicator_data != NULL) {
/*
* If the kats have already passed indicator is set - then check the
* integrity of the indicator.
*/
if (st->indicator_checksum_data == NULL)
goto end;
indicator_checksum = OPENSSL_hexstr2buf(st->indicator_checksum_data,
&checksum_len);
if (indicator_checksum == NULL)
goto end;
bio_indicator =
(*st->bio_new_buffer_cb)(st->indicator_data,
strlen(st->indicator_data));
if (bio_indicator == NULL
|| !verify_integrity(bio_indicator, st->bio_read_ex_cb,
indicator_checksum, checksum_len,
st->libctx, &ev,
OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY))
goto end;
else
kats_already_passed = 1;
}
/* Only runs the KAT's during installation OR on_demand() */
if (on_demand_test || kats_already_passed == 0) {
if (!SELF_TEST_kats(&ev, st->libctx))
goto end;
}
ok = 1;
end:
OPENSSL_free(module_checksum);
OPENSSL_free(indicator_checksum);
if (st != NULL) {
(*st->bio_free_cb)(bio_indicator);
(*st->bio_free_cb)(bio_module);
}
FIPS_state = ok ? FIPS_STATE_RUNNING : FIPS_STATE_ERROR;
CRYPTO_THREAD_unlock(self_test_lock);
return ok;
}
@@ -9,6 +9,7 @@
#include <openssl/core_numbers.h>
#include <openssl/types.h>
#include <openssl/self_test.h>
typedef struct self_test_post_params_st {
/* FIPS module integrity check parameters */
@@ -25,8 +26,31 @@ typedef struct self_test_post_params_st {
OSSL_BIO_new_membuf_fn *bio_new_buffer_cb;
OSSL_BIO_read_ex_fn *bio_read_ex_cb;
OSSL_BIO_free_fn *bio_free_cb;
OSSL_CALLBACK *event_cb;
void *event_cb_arg;
OPENSSL_CTX *libctx;
} SELF_TEST_POST_PARAMS;
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st);
typedef struct st_event_st
{
/* local state variables */
const char *phase;
const char *type;
const char *desc;
OSSL_CALLBACK *cb;
/* callback related variables used to pass the state back to the user */
OSSL_PARAM params[4];
void *cb_arg;
} OSSL_ST_EVENT;
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test);
int SELF_TEST_kats(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx);
void SELF_TEST_EVENT_init(OSSL_ST_EVENT *ev, OSSL_CALLBACK *cb, void *cbarg);
void SELF_TEST_EVENT_onbegin(OSSL_ST_EVENT *ev, const char *type,
const char *desc);
void SELF_TEST_EVENT_onend(OSSL_ST_EVENT *ev, int ret);
void SELF_TEST_EVENT_oncorrupt_byte(OSSL_ST_EVENT *ev, unsigned char *bytes);
+191
View File
@@ -0,0 +1,191 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
typedef struct st_kat_st {
const char *desc;
const char *algorithm;
const unsigned char *pt;
size_t pt_len;
const unsigned char *expected;
size_t expected_len;
} ST_KAT;
typedef ST_KAT ST_KAT_DIGEST;
typedef struct st_kat_cipher_st {
ST_KAT base;
const unsigned char *key;
size_t key_len;
const unsigned char *iv;
size_t iv_len;
const unsigned char *aad;
size_t aad_len;
const unsigned char *tag;
size_t tag_len;
} ST_KAT_CIPHER;
typedef struct st_kat_nvp_st {
const char *name;
const char *value;
} ST_KAT_NVP;
typedef struct st_kat_kdf_st {
const char *desc;
const char *algorithm;
const ST_KAT_NVP *ctrls;
const unsigned char *expected;
size_t expected_len;
} ST_KAT_KDF;
/* Macros to build Self test data */
#define ITM(x) x, sizeof(x)
#define ITM_STR(x) x, sizeof(x) - 1
/*- DIGEST TEST DATA */
static const unsigned char sha1_pt[] = "abc";
static const unsigned char sha1_digest[] = {
0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, 0x25, 0x71,
0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D
};
static const unsigned char sha512_pt[] = "abc";
static const unsigned char sha512_digest[] = {
0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, 0xCC, 0x41, 0x73, 0x49,
0xAE, 0x20, 0x41, 0x31, 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, 0x21, 0x92, 0x99, 0x2A,
0x27, 0x4F, 0xC1, 0xA8, 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, 0x2A, 0x9A, 0xC9, 0x4F,
0xA5, 0x4C, 0xA4, 0x9F
};
static const unsigned char sha3_256_pt[] = { 0xe7, 0x37, 0x21, 0x05 };
static const unsigned char sha3_256_digest[] = {
0x3a, 0x42, 0xb6, 0x8a, 0xb0, 0x79, 0xf2, 0x8c, 0x4c, 0xa3, 0xc7, 0x52,
0x29, 0x6f, 0x27, 0x90, 0x06, 0xc4, 0xfe, 0x78, 0xb1, 0xeb, 0x79, 0xd9,
0x89, 0x77, 0x7f, 0x05, 0x1e, 0x40, 0x46, 0xae
};
static const ST_KAT_DIGEST st_kat_digest_tests[] =
{
{
OSSL_SELF_TEST_DESC_MD_SHA1,
"SHA1",
ITM_STR(sha1_pt),
ITM(sha1_digest),
},
{
OSSL_SELF_TEST_DESC_MD_SHA2,
"SHA512",
ITM_STR(sha512_pt),
ITM(sha512_digest),
},
{
OSSL_SELF_TEST_DESC_MD_SHA3,
"SHA3-256",
ITM(sha3_256_pt),
ITM(sha3_256_digest),
},
};
/*- CIPHER TEST DATA */
/* DES3 test data */
static const unsigned char des_ede3_cbc_pt[] = {
0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11,
0x73, 0x93, 0x17, 0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51
};
static const unsigned char des_ede3_cbc_key[] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
};
static const unsigned char des_ede3_cbc_iv[] = {
0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17
};
static const unsigned char des_ede3_cbc_ct[] = {
0x20, 0x79, 0xC3, 0xD5, 0x3A, 0xA7, 0x63, 0xE1, 0x93, 0xB7, 0x9E, 0x25,
0x69, 0xAB, 0x52, 0x62, 0x51, 0x65, 0x70, 0x48, 0x1F, 0x25, 0xB5, 0x0F,
0x73, 0xC0, 0xBD, 0xA8, 0x5C, 0x8E, 0x0D, 0xA7
};
static const unsigned char aes_256_gcm_key[] = {
0x92,0xe1,0x1d,0xcd,0xaa,0x86,0x6f,0x5c,0xe7,0x90,0xfd,0x24,
0x50,0x1f,0x92,0x50,0x9a,0xac,0xf4,0xcb,0x8b,0x13,0x39,0xd5,
0x0c,0x9c,0x12,0x40,0x93,0x5d,0xd0,0x8b
};
static const unsigned char aes_256_gcm_iv[] = {
0xac,0x93,0xa1,0xa6,0x14,0x52,0x99,0xbd,0xe9,0x02,0xf2,0x1a
};
static const unsigned char aes_256_gcm_pt[] = {
0x2d,0x71,0xbc,0xfa,0x91,0x4e,0x4a,0xc0,0x45,0xb2,0xaa,0x60,
0x95,0x5f,0xad,0x24
};
static const unsigned char aes_256_gcm_aad[] = {
0x1e,0x08,0x89,0x01,0x6f,0x67,0x60,0x1c,0x8e,0xbe,0xa4,0x94,
0x3b,0xc2,0x3a,0xd6
};
static const unsigned char aes_256_gcm_ct[] = {
0x89,0x95,0xae,0x2e,0x6d,0xf3,0xdb,0xf9,0x6f,0xac,0x7b,0x71,
0x37,0xba,0xe6,0x7f
};
static const unsigned char aes_256_gcm_tag[] = {
0xec,0xa5,0xaa,0x77,0xd5,0x1d,0x4a,0x0a,0x14,0xd9,0xc5,0x1e,
0x1d,0xa4,0x74,0xab
};
static const ST_KAT_CIPHER st_kat_cipher_tests[] = {
{
{
OSSL_SELF_TEST_DESC_CIPHER_TDES,
"DES-EDE3-CBC",
ITM(des_ede3_cbc_pt),
ITM(des_ede3_cbc_ct)
},
ITM(des_ede3_cbc_key),
ITM(des_ede3_cbc_iv),
},
{
{
OSSL_SELF_TEST_DESC_CIPHER_AES_GCM,
"AES-256-GCM",
ITM(aes_256_gcm_pt),
ITM(aes_256_gcm_ct),
},
ITM(aes_256_gcm_key),
ITM(aes_256_gcm_iv),
ITM(aes_256_gcm_aad),
ITM(aes_256_gcm_tag)
}
};
/*- KDF TEST DATA */
static const ST_KAT_NVP hkdf_ctrl[] =
{
{ "digest", "SHA256" },
{ "key", "secret" },
{ "salt", "salt" },
{ "info", "label" },
{ NULL, NULL }
};
static const unsigned char hkdf_expected[] = {
0x2a, 0xc4, 0x36, 0x9f, 0x52, 0x59, 0x96, 0xf8, 0xde, 0x13
};
static const ST_KAT_KDF st_kat_kdf_tests[] =
{
{
OSSL_SELF_TEST_DESC_KDF_HKDF,
"HKDF",
hkdf_ctrl,
ITM(hkdf_expected)
}
};
+93
View File
@@ -0,0 +1,93 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core_names.h>
#include <openssl/params.h>
#include "self_test.h"
static void self_test_event_setparams(OSSL_ST_EVENT *ev)
{
size_t n = 0;
if (ev->cb != NULL) {
ev->params[n++] =
OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_PHASE,
(char *)ev->phase, 0);
ev->params[n++] =
OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_TYPE,
(char *)ev->type, 0);
ev->params[n++] =
OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_DESC,
(char *)ev->desc, 0);
}
ev->params[n++] = OSSL_PARAM_construct_end();
}
void SELF_TEST_EVENT_init(OSSL_ST_EVENT *ev, OSSL_CALLBACK *cb, void *cbarg)
{
if (ev == NULL)
return;
ev->cb = cb;
ev->cb_arg = cbarg;
ev->phase = "";
ev->type = "";
ev->desc = "";
self_test_event_setparams(ev);
}
/* Can be used during application testing to log that a test has started. */
void SELF_TEST_EVENT_onbegin(OSSL_ST_EVENT *ev, const char *type,
const char *desc)
{
if (ev != NULL && ev->cb != NULL) {
ev->phase = OSSL_SELF_TEST_PHASE_START;
ev->type = type;
ev->desc = desc;
self_test_event_setparams(ev);
(void)ev->cb(ev->params, ev->cb_arg);
}
}
/*
* Can be used during application testing to log that a test has either
* passed or failed.
*/
void SELF_TEST_EVENT_onend(OSSL_ST_EVENT *ev, int ret)
{
if (ev != NULL && ev->cb != NULL) {
ev->phase =
(ret == 1 ? OSSL_SELF_TEST_PHASE_PASS : OSSL_SELF_TEST_PHASE_FAIL);
self_test_event_setparams(ev);
(void)ev->cb(ev->params, ev->cb_arg);
ev->phase = OSSL_SELF_TEST_PHASE_NONE;
ev->type = OSSL_SELF_TEST_TYPE_NONE;
ev->desc = OSSL_SELF_TEST_DESC_NONE;
}
}
/*
* Used for failure testing.
*
* Call the applications SELF_TEST_cb() if it exists.
* If the application callback decides to return 0 then the first byte of 'bytes'
* is modified (corrupted). This is used to modify output signatures or
* ciphertext before they are verified or decrypted.
*/
void SELF_TEST_EVENT_oncorrupt_byte(OSSL_ST_EVENT *ev, unsigned char *bytes)
{
if (ev != NULL && ev->cb != NULL) {
ev->phase = OSSL_SELF_TEST_PHASE_CORRUPT;
self_test_event_setparams(ev);
if (!ev->cb(ev->params, ev->cb_arg))
bytes[0] ^= 1;
}
}
+246
View File
@@ -0,0 +1,246 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include "internal/nelem.h"
#include "self_test.h"
#include "self_test_data.inc"
static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_ST_EVENT *event,
OPENSSL_CTX *libctx)
{
int ok = 0;
unsigned char out[EVP_MAX_MD_SIZE];
unsigned int out_len = 0;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
EVP_MD *md = EVP_MD_fetch(libctx, t->algorithm, NULL);
SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_DIGEST, t->desc);
if (ctx == NULL
|| md == NULL
|| !EVP_DigestInit_ex(ctx, md, NULL)
|| !EVP_DigestUpdate(ctx, t->pt, t->pt_len)
|| !EVP_DigestFinal(ctx, out, &out_len))
goto err;
/* Optional corruption */
SELF_TEST_EVENT_oncorrupt_byte(event, out);
if (out_len != t->expected_len
|| memcmp(out, t->expected, out_len) != 0)
goto err;
ok = 1;
err:
SELF_TEST_EVENT_onend(event, ok);
EVP_MD_free(md);
EVP_MD_CTX_free(ctx);
return ok;
}
/*
* Helper function to setup a EVP_CipherInit
* Used to hide the complexity of Authenticated ciphers.
*/
static int cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const ST_KAT_CIPHER *t, int enc)
{
unsigned char *in_tag = NULL;
int pad = 0, tmp;
/* Flag required for Key wrapping */
EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
if (t->tag == NULL) {
/* Use a normal cipher init */
return EVP_CipherInit_ex(ctx, cipher, NULL, t->key, t->iv, enc)
&& EVP_CIPHER_CTX_set_padding(ctx, pad);
}
/* The authenticated cipher init */
if (!enc)
in_tag = (unsigned char *)t->tag;
return EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)
&& EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, t->iv_len, NULL)
&& (in_tag == NULL
|| EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, t->tag_len,
in_tag))
&& EVP_CipherInit_ex(ctx, NULL, NULL, t->key, t->iv, enc)
&& EVP_CIPHER_CTX_set_padding(ctx, pad)
&& EVP_CipherUpdate(ctx, NULL, &tmp, t->aad, t->aad_len);
}
/* Test a single KAT for encrypt/decrypt */
static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_ST_EVENT *event,
OPENSSL_CTX *libctx)
{
int ret = 0, encrypt = 1, len, ct_len = 0, pt_len = 0;
EVP_CIPHER_CTX *ctx = NULL;
EVP_CIPHER *cipher = NULL;
unsigned char ct_buf[256] = { 0 };
unsigned char pt_buf[256] = { 0 };
SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_CIPHER, t->base.desc);
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
goto end;
cipher = EVP_CIPHER_fetch(libctx, t->base.algorithm, "");
if (cipher == NULL)
goto end;
/* Encrypt plain text message */
if (!cipher_init(ctx, cipher, t, encrypt)
|| !EVP_CipherUpdate(ctx, ct_buf, &len, t->base.pt, t->base.pt_len)
|| !EVP_CipherFinal_ex(ctx, ct_buf + len, &ct_len))
goto end;
SELF_TEST_EVENT_oncorrupt_byte(event, ct_buf);
ct_len += len;
if (ct_len != (int)t->base.expected_len
|| memcmp(t->base.expected, ct_buf, ct_len) != 0)
goto end;
if (t->tag != NULL) {
unsigned char tag[16] = { 0 };
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, t->tag_len, tag)
|| memcmp(tag, t->tag, t->tag_len) != 0)
goto end;
}
if (!(cipher_init(ctx, cipher, t, !encrypt)
&& EVP_CipherUpdate(ctx, pt_buf, &len, ct_buf, ct_len)
&& EVP_CipherFinal_ex(ctx, pt_buf + len, &pt_len)))
goto end;
pt_len += len;
if (pt_len != (int)t->base.pt_len
|| memcmp(pt_buf, t->base.pt, pt_len) != 0)
goto end;
ret = 1;
end:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
SELF_TEST_EVENT_onend(event, ret);
return ret;
}
static int self_test_kdf(const ST_KAT_KDF *t, OSSL_ST_EVENT *event,
OPENSSL_CTX *libctx)
{
int ret = 0;
int i;
unsigned char out[64];
EVP_KDF *kdf = NULL;
EVP_KDF_CTX *ctx = NULL;
OSSL_PARAM params[16];
const OSSL_PARAM *settables = NULL;
SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_KDF, t->desc);
kdf = EVP_KDF_fetch(libctx, t->algorithm, "");
ctx = EVP_KDF_CTX_new(kdf);
if (ctx == NULL)
goto end;
settables = EVP_KDF_settable_ctx_params(kdf);
for (i = 0; t->ctrls[i].name != NULL; ++i) {
if (!OSSL_PARAM_allocate_from_text(&params[i], settables,
t->ctrls[i].name,
t->ctrls[i].value,
strlen(t->ctrls[i].value)))
goto end;
}
params[i] = OSSL_PARAM_construct_end();
if (!EVP_KDF_CTX_set_params(ctx, params))
goto end;
if (t->expected_len > sizeof(out))
goto end;
if (EVP_KDF_derive(ctx, out, t->expected_len) <= 0)
goto end;
SELF_TEST_EVENT_oncorrupt_byte(event, out);
if (memcmp(out, t->expected, t->expected_len) != 0)
goto end;
ret = 1;
end:
for (i = 0; params[i].key != NULL; ++i)
OPENSSL_free(params[i].data);
EVP_KDF_free(kdf);
EVP_KDF_CTX_free(ctx);
SELF_TEST_EVENT_onend(event, ret);
return ret;
}
/*
* Test a data driven list of KAT's for digest algorithms.
* All tests are run regardless of if they fail or not.
* Return 0 if any test fails.
*/
static int self_test_digests(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
{
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_digest_tests); ++i) {
if (!self_test_digest(&st_kat_digest_tests[i], event, libctx))
ret = 0;
}
return ret;
}
static int self_test_ciphers(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
{
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_cipher_tests); ++i) {
if (!self_test_cipher(&st_kat_cipher_tests[i], event, libctx))
ret = 0;
}
return ret;
}
static int self_test_kdfs(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
{
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_kdf_tests); ++i) {
if (!self_test_kdf(&st_kat_kdf_tests[i], event, libctx))
ret = 0;
}
return ret;
}
/*
* Run the algorithm KAT's.
* Return 1 is successful, otherwise return 0.
* This runs all the tests regardless of if any fail.
*
* TODO(3.0) Add self tests for KA, DRBG, Sign/Verify when they become available
*/
int SELF_TEST_kats(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
{
int ret = 1;
if (!self_test_digests(event, libctx))
ret = 0;
if (!self_test_ciphers(event, libctx))
ret = 0;
if (!self_test_kdfs(event, libctx))
ret = 0;
return ret;
}
-151
View File
@@ -1,151 +0,0 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/evp.h>
#include <openssl/params.h>
#include "selftest.h"
#define FIPS_STATE_INIT 0
#define FIPS_STATE_RUNNING 1
#define FIPS_STATE_SELFTEST 2
#define FIPS_STATE_ERROR 3
/* The size of a temp buffer used to read in data */
#define INTEGRITY_BUF_SIZE (4096)
#define MAX_MD_SIZE 64
#define MAC_NAME "HMAC"
#define DIGEST_NAME "SHA256"
static int FIPS_state = FIPS_STATE_INIT;
static unsigned char fixed_key[32] = { 0 };
/*
* Calculate the HMAC SHA256 of data read using a BIO and read_cb, and verify
* the result matches the expected value.
* Return 1 if verified, or 0 if it fails.
*/
static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
unsigned char *expected, size_t expected_len,
OPENSSL_CTX *libctx)
{
int ret = 0, status;
unsigned char out[MAX_MD_SIZE];
unsigned char buf[INTEGRITY_BUF_SIZE];
size_t bytes_read = 0, out_len = 0;
EVP_MAC *mac = NULL;
EVP_MAC_CTX *ctx = NULL;
OSSL_PARAM params[3], *p = params;
mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
ctx = EVP_MAC_CTX_new(mac);
if (mac == NULL || ctx == NULL)
goto err;
*p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME,
strlen(DIGEST_NAME) + 1);
*p++ = OSSL_PARAM_construct_octet_string("key", fixed_key,
sizeof(fixed_key));
*p = OSSL_PARAM_construct_end();
if (EVP_MAC_CTX_set_params(ctx, params) <= 0
|| !EVP_MAC_init(ctx))
goto err;
while (1) {
status = read_ex_cb(bio, buf, sizeof(buf), &bytes_read);
if (status != 1)
break;
if (!EVP_MAC_update(ctx, buf, bytes_read))
goto err;
}
if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out)))
goto err;
if (expected_len != out_len
|| memcmp(expected, out, out_len) != 0)
goto err;
ret = 1;
err:
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
return ret;
}
/* This API is triggered either on loading of the FIPS module or on demand */
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st)
{
int ok = 0;
int kats_already_passed = 0;
int on_demand_test = (FIPS_state != FIPS_STATE_INIT);
long checksum_len;
BIO *bio_module = NULL, *bio_indicator = NULL;
unsigned char *module_checksum = NULL;
unsigned char *indicator_checksum = NULL;
if (st == NULL
|| FIPS_state == FIPS_STATE_ERROR
|| FIPS_state == FIPS_STATE_SELFTEST
|| st->module_checksum_data == NULL)
goto end;
module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data,
&checksum_len);
if (module_checksum == NULL)
goto end;
bio_module = (*st->bio_new_file_cb)(st->module_filename, "rb");
/* Always check the integrity of the fips module */
if (bio_module == NULL
|| !verify_integrity(bio_module, st->bio_read_ex_cb,
module_checksum, checksum_len, st->libctx))
goto end;
/* This will be NULL during installation - so the self test KATS will run */
if (st->indicator_data != NULL) {
/*
* If the kats have already passed indicator is set - then check the
* integrity of the indicator.
*/
if (st->indicator_checksum_data == NULL)
goto end;
indicator_checksum = OPENSSL_hexstr2buf(st->indicator_checksum_data,
&checksum_len);
if (indicator_checksum == NULL)
goto end;
bio_indicator =
(*st->bio_new_buffer_cb)(st->indicator_data,
strlen(st->indicator_data));
if (bio_indicator == NULL
|| !verify_integrity(bio_indicator, st->bio_read_ex_cb,
indicator_checksum, checksum_len,
st->libctx))
goto end;
else
kats_already_passed = 1;
}
/* Only runs the KAT's during installation OR on_demand() */
if (on_demand_test || kats_already_passed == 0) {
/*TODO (3.0) Add self test KATS */
}
ok = 1;
end:
OPENSSL_free(module_checksum);
OPENSSL_free(indicator_checksum);
if (st != NULL) {
(*st->bio_free_cb)(bio_indicator);
(*st->bio_free_cb)(bio_module);
}
FIPS_state = ok ? FIPS_STATE_RUNNING : FIPS_STATE_ERROR;
return ok;
}
@@ -0,0 +1,4 @@
LIBS=../../../libcrypto
SOURCE[../../../libcrypto]=rsa_enc.c
@@ -0,0 +1,459 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/core_numbers.h>
#include <openssl/core_names.h>
#include <openssl/rsa.h>
#include <openssl/params.h>
#include <openssl/err.h>
/* Just for SSL_MAX_MASTER_KEY_LENGTH */
#include <openssl/ssl.h>
#include "internal/constant_time.h"
#include "crypto/rsa.h"
#include "prov/providercommonerr.h"
#include "prov/provider_ctx.h"
#include "prov/implementations.h"
#include <stdlib.h>
static OSSL_OP_asym_cipher_newctx_fn rsa_newctx;
static OSSL_OP_asym_cipher_encrypt_init_fn rsa_init;
static OSSL_OP_asym_cipher_encrypt_fn rsa_encrypt;
static OSSL_OP_asym_cipher_decrypt_init_fn rsa_init;
static OSSL_OP_asym_cipher_decrypt_fn rsa_decrypt;
static OSSL_OP_asym_cipher_freectx_fn rsa_freectx;
static OSSL_OP_asym_cipher_dupctx_fn rsa_dupctx;
static OSSL_OP_asym_cipher_get_ctx_params_fn rsa_get_ctx_params;
static OSSL_OP_asym_cipher_gettable_ctx_params_fn rsa_gettable_ctx_params;
static OSSL_OP_asym_cipher_set_ctx_params_fn rsa_set_ctx_params;
static OSSL_OP_asym_cipher_settable_ctx_params_fn rsa_settable_ctx_params;
/*
* What's passed as an actual key is defined by the KEYMGMT interface.
* We happen to know that our KEYMGMT simply passes RSA structures, so
* we use that here too.
*/
typedef struct {
OPENSSL_CTX *libctx;
RSA *rsa;
int pad_mode;
/* OAEP message digest */
EVP_MD *oaep_md;
/* message digest for MGF1 */
EVP_MD *mgf1_md;
/* OAEP label */
unsigned char *oaep_label;
size_t oaep_labellen;
/* TLS padding */
unsigned int client_version;
unsigned int alt_version;
} PROV_RSA_CTX;
static void *rsa_newctx(void *provctx)
{
PROV_RSA_CTX *prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX));
if (prsactx == NULL)
return NULL;
prsactx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
return prsactx;
}
static int rsa_init(void *vprsactx, void *vrsa)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
if (prsactx == NULL || vrsa == NULL || !RSA_up_ref(vrsa))
return 0;
RSA_free(prsactx->rsa);
prsactx->rsa = vrsa;
prsactx->pad_mode = RSA_PKCS1_PADDING;
return 1;
}
static int rsa_encrypt(void *vprsactx, unsigned char *out, size_t *outlen,
size_t outsize, const unsigned char *in, size_t inlen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
int ret;
if (out == NULL) {
size_t len = RSA_size(prsactx->rsa);
if (len == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
return 0;
}
*outlen = len;
return 1;
}
if (prsactx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
int rsasize = RSA_size(prsactx->rsa);
unsigned char *tbuf;
if ((tbuf = OPENSSL_malloc(rsasize)) == NULL) {
PROVerr(0, ERR_R_MALLOC_FAILURE);
return 0;
}
ret = RSA_padding_add_PKCS1_OAEP_mgf1(tbuf, rsasize, in, inlen,
prsactx->oaep_label,
prsactx->oaep_labellen,
prsactx->oaep_md,
prsactx->mgf1_md);
if (!ret) {
OPENSSL_free(tbuf);
return 0;
}
ret = RSA_public_encrypt(rsasize, tbuf, out, prsactx->rsa,
RSA_NO_PADDING);
OPENSSL_free(tbuf);
} else {
ret = RSA_public_encrypt(inlen, in, out, prsactx->rsa,
prsactx->pad_mode);
}
/* A ret value of 0 is not an error */
if (ret < 0)
return ret;
*outlen = ret;
return 1;
}
static int rsa_decrypt(void *vprsactx, unsigned char *out, size_t *outlen,
size_t outsize, const unsigned char *in, size_t inlen)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
int ret;
size_t len = RSA_size(prsactx->rsa);
if (prsactx->pad_mode == RSA_PKCS1_WITH_TLS_PADDING) {
if (out == NULL) {
*outlen = SSL_MAX_MASTER_KEY_LENGTH;
return 1;
}
if (outsize < SSL_MAX_MASTER_KEY_LENGTH) {
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH);
return 0;
}
} else {
if (out == NULL) {
if (len == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
return 0;
}
*outlen = len;
return 1;
}
if (outsize < len) {
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH);
return 0;
}
}
if (prsactx->pad_mode == RSA_PKCS1_OAEP_PADDING
|| prsactx->pad_mode == RSA_PKCS1_WITH_TLS_PADDING) {
unsigned char *tbuf;
if ((tbuf = OPENSSL_malloc(len)) == NULL) {
PROVerr(0, ERR_R_MALLOC_FAILURE);
return 0;
}
ret = RSA_private_decrypt(inlen, in, tbuf, prsactx->rsa,
RSA_NO_PADDING);
/*
* With no padding then, on success ret should be len, otherwise an
* error occurred (non-constant time)
*/
if (ret != (int)len) {
OPENSSL_free(tbuf);
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_DECRYPT);
return 0;
}
if (prsactx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, outsize, tbuf,
len, len,
prsactx->oaep_label,
prsactx->oaep_labellen,
prsactx->oaep_md,
prsactx->mgf1_md);
} else {
/* RSA_PKCS1_WITH_TLS_PADDING */
if (prsactx->client_version <= 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_TLS_CLIENT_VERSION);
return 0;
}
ret = rsa_padding_check_PKCS1_type_2_TLS(out, outsize,
tbuf, len,
prsactx->client_version,
prsactx->alt_version);
}
OPENSSL_free(tbuf);
} else {
ret = RSA_private_decrypt(inlen, in, out, prsactx->rsa,
prsactx->pad_mode);
}
*outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret);
ret = constant_time_select_int(constant_time_msb(ret), 0, 1);
return ret;
}
static void rsa_freectx(void *vprsactx)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
RSA_free(prsactx->rsa);
EVP_MD_free(prsactx->oaep_md);
EVP_MD_free(prsactx->mgf1_md);
OPENSSL_free(prsactx);
}
static void *rsa_dupctx(void *vprsactx)
{
PROV_RSA_CTX *srcctx = (PROV_RSA_CTX *)vprsactx;
PROV_RSA_CTX *dstctx;
dstctx = OPENSSL_zalloc(sizeof(*srcctx));
if (dstctx == NULL)
return NULL;
*dstctx = *srcctx;
if (dstctx->rsa != NULL && !RSA_up_ref(dstctx->rsa)) {
OPENSSL_free(dstctx);
return NULL;
}
if (dstctx->oaep_md != NULL && !EVP_MD_up_ref(dstctx->oaep_md)) {
RSA_free(dstctx->rsa);
OPENSSL_free(dstctx);
return NULL;
}
if (dstctx->mgf1_md != NULL && !EVP_MD_up_ref(dstctx->mgf1_md)) {
RSA_free(dstctx->rsa);
EVP_MD_free(dstctx->oaep_md);
OPENSSL_free(dstctx);
return NULL;
}
return dstctx;
}
static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
OSSL_PARAM *p;
if (prsactx == NULL || params == NULL)
return 0;
p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE);
if (p != NULL && !OSSL_PARAM_set_int(p, prsactx->pad_mode))
return 0;
p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST);
if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->oaep_md == NULL
? ""
: EVP_MD_name(prsactx->oaep_md)))
return 0;
p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST);
if (p != NULL) {
EVP_MD *mgf1_md = prsactx->mgf1_md == NULL ? prsactx->oaep_md
: prsactx->mgf1_md;
if (!OSSL_PARAM_set_utf8_string(p, mgf1_md == NULL
? ""
: EVP_MD_name(mgf1_md)))
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL);
if (p != NULL && !OSSL_PARAM_set_octet_ptr(p, prsactx->oaep_label, 0))
return 0;
p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL_LEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, prsactx->oaep_labellen))
return 0;
p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION);
if (p != NULL && !OSSL_PARAM_set_uint(p, prsactx->client_version))
return 0;
p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION);
if (p != NULL && !OSSL_PARAM_set_uint(p, prsactx->alt_version))
return 0;
return 1;
}
static const OSSL_PARAM known_gettable_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, NULL, 0),
OSSL_PARAM_int(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL),
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, NULL, 0),
OSSL_PARAM_DEFN(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, OSSL_PARAM_OCTET_PTR,
NULL, 0),
OSSL_PARAM_size_t(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL_LEN, NULL),
OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL),
OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL),
OSSL_PARAM_END
};
static const OSSL_PARAM *rsa_gettable_ctx_params(void)
{
return known_gettable_ctx_params;
}
static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
const OSSL_PARAM *p;
/* Should be big enough */
char mdname[80], mdprops[80] = { '\0' };
char *str = mdname;
int pad_mode;
if (prsactx == NULL || params == NULL)
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST);
if (p != NULL) {
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdname)))
return 0;
str = mdprops;
p = OSSL_PARAM_locate_const(params,
OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS);
if (p != NULL) {
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
return 0;
}
EVP_MD_free(prsactx->oaep_md);
prsactx->oaep_md = EVP_MD_fetch(prsactx->libctx, mdname, mdprops);
if (prsactx->oaep_md == NULL)
return 0;
}
p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE);
if (p != NULL) {
if (!OSSL_PARAM_get_int(p, &pad_mode))
return 0;
/*
* PSS padding is for signatures only so is not compatible with
* asymmetric cipher use.
*/
if (pad_mode == RSA_PKCS1_PSS_PADDING)
return 0;
if (pad_mode == RSA_PKCS1_OAEP_PADDING && prsactx->oaep_md == NULL) {
prsactx->oaep_md = EVP_MD_fetch(prsactx->libctx, "SHA1", mdprops);
if (prsactx->oaep_md == NULL)
return 0;
}
prsactx->pad_mode = pad_mode;
}
p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST);
if (p != NULL) {
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdname)))
return 0;
str = mdprops;
p = OSSL_PARAM_locate_const(params,
OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS);
if (p != NULL) {
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
return 0;
} else {
str = NULL;
}
EVP_MD_free(prsactx->mgf1_md);
prsactx->mgf1_md = EVP_MD_fetch(prsactx->libctx, mdname, str);
if (prsactx->mgf1_md == NULL)
return 0;
}
p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL);
if (p != NULL) {
void *tmp_label = NULL;
size_t tmp_labellen;
if (!OSSL_PARAM_get_octet_string(p, &tmp_label, 0, &tmp_labellen))
return 0;
OPENSSL_free(prsactx->oaep_label);
prsactx->oaep_label = (unsigned char *)tmp_label;
prsactx->oaep_labellen = tmp_labellen;
}
p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION);
if (p != NULL) {
unsigned int client_version;
if (!OSSL_PARAM_get_uint(p, &client_version))
return 0;
prsactx->client_version = client_version;
}
p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION);
if (p != NULL) {
unsigned int alt_version;
if (!OSSL_PARAM_get_uint(p, &alt_version))
return 0;
prsactx->alt_version = alt_version;
}
return 1;
}
static const OSSL_PARAM known_settable_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, NULL, 0),
OSSL_PARAM_int(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL),
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS, NULL, 0),
OSSL_PARAM_octet_string(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, NULL, 0),
OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL),
OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL),
OSSL_PARAM_END
};
static const OSSL_PARAM *rsa_settable_ctx_params(void)
{
return known_settable_ctx_params;
}
const OSSL_DISPATCH rsa_asym_cipher_functions[] = {
{ OSSL_FUNC_ASYM_CIPHER_NEWCTX, (void (*)(void))rsa_newctx },
{ OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT, (void (*)(void))rsa_init },
{ OSSL_FUNC_ASYM_CIPHER_ENCRYPT, (void (*)(void))rsa_encrypt },
{ OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT, (void (*)(void))rsa_init },
{ OSSL_FUNC_ASYM_CIPHER_DECRYPT, (void (*)(void))rsa_decrypt },
{ OSSL_FUNC_ASYM_CIPHER_FREECTX, (void (*)(void))rsa_freectx },
{ OSSL_FUNC_ASYM_CIPHER_DUPCTX, (void (*)(void))rsa_dupctx },
{ OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS,
(void (*)(void))rsa_get_ctx_params },
{ OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS,
(void (*)(void))rsa_gettable_ctx_params },
{ OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS,
(void (*)(void))rsa_set_ctx_params },
{ OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS,
(void (*)(void))rsa_settable_ctx_params },
{ 0, NULL }
};
+2 -1
View File
@@ -1 +1,2 @@
SUBDIRS=digests ciphers macs kdfs exchange keymgmt signature
SUBDIRS=digests ciphers macs kdfs exchange keymgmt signature asymciphers \
serializers
+22 -2
View File
@@ -5,6 +5,8 @@
# The latter may become legacy sooner, so it's comfortable to have two
# variables already now, to switch the non-FIPSable TDES to legacy if needed.
$COMMON_GOAL=../../libcommon.a
$AES_GOAL=../../libimplementations.a
$TDES_1_GOAL=../../libimplementations.a
$TDES_2_GOAL=../../libimplementations.a
@@ -21,6 +23,13 @@ $RC5_GOAL=../../libimplementations.a
$RC2_GOAL=../../libimplementations.a
$CHACHA_GOAL=../../libimplementations.a
$CHACHAPOLY_GOAL=../../libimplementations.a
$SIV_GOAL=../../libimplementations.a
# This source is common building blocks for all ciphers in all our providers.
SOURCE[$COMMON_GOAL]=\
ciphercommon.c ciphercommon_hw.c ciphercommon_block.c \
ciphercommon_gcm.c ciphercommon_gcm_hw.c \
ciphercommon_ccm.c ciphercommon_ccm_hw.c
IF[{- !$disabled{des} -}]
SOURCE[$TDES_1_GOAL]=cipher_tdes.c cipher_tdes_hw.c
@@ -31,12 +40,20 @@ SOURCE[$AES_GOAL]=\
cipher_aes_xts.c cipher_aes_xts_hw.c \
cipher_aes_gcm.c cipher_aes_gcm_hw.c \
cipher_aes_ccm.c cipher_aes_ccm_hw.c \
cipher_aes_wrp.c
cipher_aes_wrp.c \
cipher_aes_cbc_hmac_sha.c \
cipher_aes_cbc_hmac_sha256_hw.c cipher_aes_cbc_hmac_sha1_hw.c
# Extra code to satisfy the FIPS and non-FIPS separation.
# When the AES-xxx-XTS moves to legacy, this can be removed.
SOURCE[../../libfips.a]=cipher_aes_xts_fips.c
SOURCE[../../libnonfips.a]=cipher_aes_xts_fips.c
IF[{- !$disabled{siv} -}]
SOURCE[$SIV_GOAL]=\
cipher_aes_siv.c cipher_aes_siv_hw.c
ENDIF
IF[{- !$disabled{des} -}]
SOURCE[$TDES_2_GOAL]=\
cipher_tdes_default.c cipher_tdes_default_hw.c \
@@ -91,6 +108,10 @@ ENDIF
IF[{- !$disabled{rc4} -}]
SOURCE[$RC4_GOAL]=\
cipher_rc4.c cipher_rc4_hw.c
IF[{- !$disabled{md5} -}]
SOURCE[$RC4_GOAL]=\
cipher_rc4_hmac_md5.c cipher_rc4_hmac_md5_hw.c
ENDIF
ENDIF
IF[{- !$disabled{rc5} -}]
@@ -111,4 +132,3 @@ IF[{- !$disabled{chacha} -}]
cipher_chacha20_poly1305.c cipher_chacha20_poly1305_hw.c
ENDIF
ENDIF
@@ -7,6 +7,13 @@
* https://www.openssl.org/source/license.html
*/
/*
* AES low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
/* Dispatch functions for AES cipher modes ecb, cbc, ofb, cfb, ctr */
#include "cipher_aes.h"
@@ -31,7 +38,7 @@ static void *aes_dupctx(void *ctx)
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
*ret = *in;
in->base.hw->copyctx(&ret->base, &in->base);
return ret;
}
@@ -9,6 +9,7 @@
#include <openssl/aes.h>
#include "prov/ciphercommon.h"
#include "crypto/aes_platform.h"
typedef struct prov_aes_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
@@ -59,4 +60,3 @@ const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_cfb128(size_t keybits);
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_cfb1(size_t keybits);
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_cfb8(size_t keybits);
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_ctr(size_t keybits);
@@ -0,0 +1,351 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* AES low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
/* Dispatch functions for AES_CBC_HMAC_SHA ciphers */
#include "cipher_aes_cbc_hmac_sha.h"
#include "prov/implementations.h"
#ifndef AES_CBC_HMAC_SHA_CAPABLE
# define IMPLEMENT_CIPHER(nm, sub, kbits, blkbits, ivbits, flags) \
const OSSL_DISPATCH nm##kbits##sub##_functions[] = { \
{ 0, NULL } \
};
#else
# include "prov/providercommonerr.h"
/* TODO(3.0) Figure out what flags are required */
# define AES_CBC_HMAC_SHA_FLAGS (EVP_CIPH_CBC_MODE \
| EVP_CIPH_FLAG_DEFAULT_ASN1 \
| EVP_CIPH_FLAG_AEAD_CIPHER \
| EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)
static OSSL_OP_cipher_freectx_fn aes_cbc_hmac_sha1_freectx;
static OSSL_OP_cipher_freectx_fn aes_cbc_hmac_sha256_freectx;
static OSSL_OP_cipher_get_ctx_params_fn aes_get_ctx_params;
static OSSL_OP_cipher_gettable_ctx_params_fn aes_gettable_ctx_params;
static OSSL_OP_cipher_set_ctx_params_fn aes_set_ctx_params;
static OSSL_OP_cipher_settable_ctx_params_fn aes_settable_ctx_params;
# define aes_gettable_params cipher_generic_gettable_params
# define aes_einit cipher_generic_einit
# define aes_dinit cipher_generic_dinit
# define aes_update cipher_generic_stream_update
# define aes_final cipher_generic_stream_final
# define aes_cipher cipher_generic_cipher
static const OSSL_PARAM cipher_aes_known_settable_ctx_params[] = {
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_MAC_KEY, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0),
# if !defined(OPENSSL_NO_MULTIBLOCK)
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN, NULL, 0),
# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_END
};
const OSSL_PARAM *aes_settable_ctx_params(void)
{
return cipher_aes_known_settable_ctx_params;
}
static int aes_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_CIPHER_HW_AES_HMAC_SHA *hw =
(PROV_CIPHER_HW_AES_HMAC_SHA *)ctx->hw;
EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
const OSSL_PARAM *p, *p1, *pin;
int ret = 1;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_MAC_KEY);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
hw->init_mac_key(ctx, p->data, p->data_size);
}
# if !defined(OPENSSL_NO_MULTIBLOCK)
p = OSSL_PARAM_locate_const(params,
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT);
if (p != NULL
&& !OSSL_PARAM_get_size_t(p, &ctx->multiblock_max_send_fragment)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
/*
* The inputs to tls1_multiblock_aad are:
* mb_param->inp
* mb_param->len
* mb_param->interleave
* The outputs of tls1_multiblock_aad are written to:
* ctx->multiblock_interleave
* ctx->multiblock_aad_packlen
*/
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD);
if (p != NULL) {
p1 = OSSL_PARAM_locate_const(params,
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE);
if (p->data_type != OSSL_PARAM_OCTET_STRING
|| p1 == NULL
|| !OSSL_PARAM_get_uint(p1, &mb_param.interleave)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
mb_param.inp = p->data;
mb_param.len = p->data_size;
if (hw->tls1_multiblock_aad(vctx, &mb_param) <= 0)
return 0;
}
/*
* The inputs to tls1_multiblock_encrypt are:
* mb_param->inp
* mb_param->len
* mb_param->interleave
* mb_param->out
* The outputs of tls1_multiblock_encrypt are:
* ctx->multiblock_encrypt_len
*/
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC);
if (p != NULL) {
p1 = OSSL_PARAM_locate_const(params,
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE);
pin = OSSL_PARAM_locate_const(params,
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN);
if (p->data_type != OSSL_PARAM_OCTET_STRING
|| pin == NULL
|| pin->data_type != OSSL_PARAM_OCTET_STRING
|| p1 == NULL
|| !OSSL_PARAM_get_uint(p1, &mb_param.interleave)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
mb_param.out = p->data;
mb_param.inp = pin->data;
mb_param.len = pin->data_size;
if (hw->tls1_multiblock_encrypt(vctx, &mb_param) <= 0)
return 0;
}
# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (hw->set_tls1_aad(ctx, p->data, p->data_size) <= 0)
return 0;
}
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 0;
}
if (ctx->base.keylen != keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
}
return ret;
}
static int aes_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_CIPHER_HW_AES_HMAC_SHA *hw =
(PROV_CIPHER_HW_AES_HMAC_SHA *)ctx->hw;
OSSL_PARAM *p;
# if !defined(OPENSSL_NO_MULTIBLOCK)
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE);
if (p != NULL) {
size_t len = hw->tls1_multiblock_max_bufsize(ctx);
if (!OSSL_PARAM_set_size_t(p, len)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE);
if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->multiblock_interleave)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN);
if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->multiblock_aad_packlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->multiblock_encrypt_len)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.keylen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.ivlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
if (p != NULL
&& !OSSL_PARAM_set_octet_string(p, ctx->base.oiv, ctx->base.ivlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
return 1;
}
static const OSSL_PARAM cipher_aes_known_gettable_ctx_params[] = {
# if !defined(OPENSSL_NO_MULTIBLOCK)
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN, NULL),
# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
OSSL_PARAM_END
};
const OSSL_PARAM *aes_gettable_ctx_params(void)
{
return cipher_aes_known_gettable_ctx_params;
}
static void base_init(void *provctx, PROV_AES_HMAC_SHA_CTX *ctx,
const PROV_CIPHER_HW_AES_HMAC_SHA *meths,
size_t kbits, size_t blkbits, size_t ivbits,
uint64_t flags)
{
cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits,
EVP_CIPH_CBC_MODE, flags,
&meths->base, provctx);
ctx->hw = (PROV_CIPHER_HW_AES_HMAC_SHA *)ctx->base.hw;
}
static void *aes_cbc_hmac_sha1_newctx(void *provctx, size_t kbits,
size_t blkbits, size_t ivbits,
uint64_t flags)
{
PROV_AES_HMAC_SHA1_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
base_init(provctx, &ctx->base_ctx,
PROV_CIPHER_HW_aes_cbc_hmac_sha1(), kbits, blkbits,
ivbits, flags);
return ctx;
}
static void aes_cbc_hmac_sha1_freectx(void *vctx)
{
PROV_AES_HMAC_SHA1_CTX *ctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
if (ctx != NULL)
OPENSSL_clear_free(ctx, sizeof(ctx));
}
static void *aes_cbc_hmac_sha256_newctx(void *provctx, size_t kbits,
size_t blkbits, size_t ivbits,
uint64_t flags)
{
PROV_AES_HMAC_SHA256_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
base_init(provctx, &ctx->base_ctx,
PROV_CIPHER_HW_aes_cbc_hmac_sha256(), kbits, blkbits,
ivbits, flags);
return ctx;
}
static void aes_cbc_hmac_sha256_freectx(void *vctx)
{
PROV_AES_HMAC_SHA256_CTX *ctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
if (ctx != NULL)
OPENSSL_clear_free(ctx, sizeof(ctx));
}
# define IMPLEMENT_CIPHER(nm, sub, kbits, blkbits, ivbits, flags) \
static OSSL_OP_cipher_newctx_fn nm##_##kbits##_##sub##_newctx; \
static void *nm##_##kbits##_##sub##_newctx(void *provctx) \
{ \
return nm##_##sub##_newctx(provctx, kbits, blkbits, ivbits, flags); \
} \
static OSSL_OP_cipher_get_params_fn nm##_##kbits##_##sub##_get_params; \
static int nm##_##kbits##_##sub##_get_params(OSSL_PARAM params[]) \
{ \
return cipher_generic_get_params(params, EVP_CIPH_CBC_MODE, \
flags, kbits, blkbits, ivbits); \
} \
const OSSL_DISPATCH nm##kbits##sub##_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))nm##_##kbits##_##sub##_newctx },\
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))nm##_##sub##_freectx }, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))nm##_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))nm##_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))nm##_update }, \
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))nm##_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))nm##_cipher }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void))nm##_##kbits##_##sub##_get_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))nm##_gettable_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void))nm##_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void))nm##_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void))nm##_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void))nm##_settable_ctx_params }, \
{ 0, NULL } \
};
#endif /* AES_CBC_HMAC_SHA_CAPABLE */
/* aes128cbc_hmac_sha1_functions */
IMPLEMENT_CIPHER(aes, cbc_hmac_sha1, 128, 128, 128, AES_CBC_HMAC_SHA_FLAGS)
/* aes256cbc_hmac_sha1_functions */
IMPLEMENT_CIPHER(aes, cbc_hmac_sha1, 256, 128, 128, AES_CBC_HMAC_SHA_FLAGS)
/* aes128cbc_hmac_sha256_functions */
IMPLEMENT_CIPHER(aes, cbc_hmac_sha256, 128, 128, 128, AES_CBC_HMAC_SHA_FLAGS)
/* aes256cbc_hmac_sha256_functions */
IMPLEMENT_CIPHER(aes, cbc_hmac_sha256, 256, 128, 128, AES_CBC_HMAC_SHA_FLAGS)
@@ -0,0 +1,65 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "prov/ciphercommon.h"
#include "crypto/aes_platform.h"
int cipher_capable_aes_cbc_hmac_sha1(void);
int cipher_capable_aes_cbc_hmac_sha256(void);
#ifdef AES_CBC_HMAC_SHA_CAPABLE
# include <openssl/aes.h>
# include <openssl/sha.h>
typedef struct prov_cipher_hw_aes_hmac_sha_ctx_st {
PROV_CIPHER_HW base; /* must be first */
void (*init_mac_key)(void *ctx, const unsigned char *inkey, size_t inlen);
int (*set_tls1_aad)(void *ctx, unsigned char *aad_rec, int aad_len);
# if !defined(OPENSSL_NO_MULTIBLOCK)
int (*tls1_multiblock_max_bufsize)(void *ctx);
int (*tls1_multiblock_aad)(
void *vctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param);
int (*tls1_multiblock_encrypt)(
void *ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param);
# endif /* OPENSSL_NO_MULTIBLOCK) */
} PROV_CIPHER_HW_AES_HMAC_SHA;
typedef struct prov_aes_hmac_sha_ctx_st {
PROV_CIPHER_CTX base;
AES_KEY ks;
size_t payload_length; /* AAD length in decrypt case */
union {
unsigned int tls_ver;
unsigned char tls_aad[16]; /* 13 used */
} aux;
const PROV_CIPHER_HW_AES_HMAC_SHA *hw;
/* some value that are setup by set methods - that can be retrieved */
unsigned int multiblock_interleave;
unsigned int multiblock_aad_packlen;
size_t multiblock_max_send_fragment;
size_t multiblock_encrypt_len;
size_t tls_aad_pad;
} PROV_AES_HMAC_SHA_CTX;
typedef struct prov_aes_hmac_sha1_ctx_st {
PROV_AES_HMAC_SHA_CTX base_ctx;
SHA_CTX head, tail, md;
} PROV_AES_HMAC_SHA1_CTX;
typedef struct prov_aes_hmac_sha256_ctx_st {
PROV_AES_HMAC_SHA_CTX base_ctx;
SHA256_CTX head, tail, md;
} PROV_AES_HMAC_SHA256_CTX;
# define NO_PAYLOAD_LENGTH ((size_t)-1)
const PROV_CIPHER_HW_AES_HMAC_SHA *PROV_CIPHER_HW_aes_cbc_hmac_sha1(void);
const PROV_CIPHER_HW_AES_HMAC_SHA *PROV_CIPHER_HW_aes_cbc_hmac_sha256(void);
#endif /* AES_CBC_HMAC_SHA_CAPABLE */
@@ -0,0 +1,789 @@
/*
* Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* AES low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include "cipher_aes_cbc_hmac_sha.h"
#ifndef AES_CBC_HMAC_SHA_CAPABLE
int cipher_capable_aes_cbc_hmac_sha1(void)
{
return 0;
}
#else
# include "crypto/rand.h"
# include "crypto/evp.h"
# include "internal/constant_time.h"
void sha1_block_data_order(void *c, const void *p, size_t len);
void aesni_cbc_sha1_enc(const void *inp, void *out, size_t blocks,
const AES_KEY *key, unsigned char iv[16],
SHA_CTX *ctx, const void *in0);
int cipher_capable_aes_cbc_hmac_sha1(void)
{
return AESNI_CBC_HMAC_SHA_CAPABLE;
}
static int aesni_cbc_hmac_sha1_init_key(PROV_CIPHER_CTX *vctx,
const unsigned char *key, size_t keylen)
{
int ret;
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
if (ctx->base.enc)
ret = aesni_set_encrypt_key(key, keylen * 8, &ctx->ks);
else
ret = aesni_set_decrypt_key(key, keylen * 8, &ctx->ks);
SHA1_Init(&sctx->head); /* handy when benchmarking */
sctx->tail = sctx->head;
sctx->md = sctx->head;
ctx->payload_length = NO_PAYLOAD_LENGTH;
return ret < 0 ? 0 : 1;
}
static void sha1_update(SHA_CTX *c, const void *data, size_t len)
{
const unsigned char *ptr = data;
size_t res;
if ((res = c->num)) {
res = SHA_CBLOCK - res;
if (len < res)
res = len;
SHA1_Update(c, ptr, res);
ptr += res;
len -= res;
}
res = len % SHA_CBLOCK;
len -= res;
if (len) {
sha1_block_data_order(c, ptr, len / SHA_CBLOCK);
ptr += len;
c->Nh += len >> 29;
c->Nl += len <<= 3;
if (c->Nl < (unsigned int)len)
c->Nh++;
}
if (res)
SHA1_Update(c, ptr, res);
}
# if !defined(OPENSSL_NO_MULTIBLOCK)
typedef struct {
unsigned int A[8], B[8], C[8], D[8], E[8];
} SHA1_MB_CTX;
typedef struct {
const unsigned char *ptr;
int blocks;
} HASH_DESC;
typedef struct {
const unsigned char *inp;
unsigned char *out;
int blocks;
u64 iv[2];
} CIPH_DESC;
void sha1_multi_block(SHA1_MB_CTX *, const HASH_DESC *, int);
void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int);
static size_t tls1_multi_block_encrypt(void *vctx,
unsigned char *out,
const unsigned char *inp,
size_t inp_len, int n4x)
{ /* n4x is 1 or 2 */
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
HASH_DESC hash_d[8], edges[8];
CIPH_DESC ciph_d[8];
unsigned char storage[sizeof(SHA1_MB_CTX) + 32];
union {
u64 q[16];
u32 d[32];
u8 c[128];
} blocks[8];
SHA1_MB_CTX *mctx;
unsigned int frag, last, packlen, i;
unsigned int x4 = 4 * n4x, minblocks, processed = 0;
size_t ret = 0;
u8 *IVs;
# if defined(BSWAP8)
u64 seqnum;
# endif
/* ask for IVs in bulk */
if (rand_bytes_ex(ctx->base.libctx, (IVs = blocks[0].c), 16 * x4) <= 0)
return 0;
mctx = (SHA1_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); /* align */
frag = (unsigned int)inp_len >> (1 + n4x);
last = (unsigned int)inp_len + frag - (frag << (1 + n4x));
if (last > frag && ((last + 13 + 9) % 64) < (x4 - 1)) {
frag++;
last -= x4 - 1;
}
packlen = 5 + 16 + ((frag + 20 + 16) & -16);
/* populate descriptors with pointers and IVs */
hash_d[0].ptr = inp;
ciph_d[0].inp = inp;
/* 5+16 is place for header and explicit IV */
ciph_d[0].out = out + 5 + 16;
memcpy(ciph_d[0].out - 16, IVs, 16);
memcpy(ciph_d[0].iv, IVs, 16);
IVs += 16;
for (i = 1; i < x4; i++) {
ciph_d[i].inp = hash_d[i].ptr = hash_d[i - 1].ptr + frag;
ciph_d[i].out = ciph_d[i - 1].out + packlen;
memcpy(ciph_d[i].out - 16, IVs, 16);
memcpy(ciph_d[i].iv, IVs, 16);
IVs += 16;
}
# if defined(BSWAP8)
memcpy(blocks[0].c, sctx->md.data, 8);
seqnum = BSWAP8(blocks[0].q[0]);
# endif
for (i = 0; i < x4; i++) {
unsigned int len = (i == (x4 - 1) ? last : frag);
# if !defined(BSWAP8)
unsigned int carry, j;
# endif
mctx->A[i] = sctx->md.h0;
mctx->B[i] = sctx->md.h1;
mctx->C[i] = sctx->md.h2;
mctx->D[i] = sctx->md.h3;
mctx->E[i] = sctx->md.h4;
/* fix seqnum */
# if defined(BSWAP8)
blocks[i].q[0] = BSWAP8(seqnum + i);
# else
for (carry = i, j = 8; j--;) {
blocks[i].c[j] = ((u8 *)sctx->md.data)[j] + carry;
carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1);
}
# endif
blocks[i].c[8] = ((u8 *)sctx->md.data)[8];
blocks[i].c[9] = ((u8 *)sctx->md.data)[9];
blocks[i].c[10] = ((u8 *)sctx->md.data)[10];
/* fix length */
blocks[i].c[11] = (u8)(len >> 8);
blocks[i].c[12] = (u8)(len);
memcpy(blocks[i].c + 13, hash_d[i].ptr, 64 - 13);
hash_d[i].ptr += 64 - 13;
hash_d[i].blocks = (len - (64 - 13)) / 64;
edges[i].ptr = blocks[i].c;
edges[i].blocks = 1;
}
/* hash 13-byte headers and first 64-13 bytes of inputs */
sha1_multi_block(mctx, edges, n4x);
/* hash bulk inputs */
# define MAXCHUNKSIZE 2048
# if MAXCHUNKSIZE%64
# error "MAXCHUNKSIZE is not divisible by 64"
# elif MAXCHUNKSIZE
/*
* goal is to minimize pressure on L1 cache by moving in shorter steps,
* so that hashed data is still in the cache by the time we encrypt it
*/
minblocks = ((frag <= last ? frag : last) - (64 - 13)) / 64;
if (minblocks > MAXCHUNKSIZE / 64) {
for (i = 0; i < x4; i++) {
edges[i].ptr = hash_d[i].ptr;
edges[i].blocks = MAXCHUNKSIZE / 64;
ciph_d[i].blocks = MAXCHUNKSIZE / 16;
}
do {
sha1_multi_block(mctx, edges, n4x);
aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x);
for (i = 0; i < x4; i++) {
edges[i].ptr = hash_d[i].ptr += MAXCHUNKSIZE;
hash_d[i].blocks -= MAXCHUNKSIZE / 64;
edges[i].blocks = MAXCHUNKSIZE / 64;
ciph_d[i].inp += MAXCHUNKSIZE;
ciph_d[i].out += MAXCHUNKSIZE;
ciph_d[i].blocks = MAXCHUNKSIZE / 16;
memcpy(ciph_d[i].iv, ciph_d[i].out - 16, 16);
}
processed += MAXCHUNKSIZE;
minblocks -= MAXCHUNKSIZE / 64;
} while (minblocks > MAXCHUNKSIZE / 64);
}
# endif
# undef MAXCHUNKSIZE
sha1_multi_block(mctx, hash_d, n4x);
memset(blocks, 0, sizeof(blocks));
for (i = 0; i < x4; i++) {
unsigned int len = (i == (x4 - 1) ? last : frag),
off = hash_d[i].blocks * 64;
const unsigned char *ptr = hash_d[i].ptr + off;
off = (len - processed) - (64 - 13) - off; /* remainder actually */
memcpy(blocks[i].c, ptr, off);
blocks[i].c[off] = 0x80;
len += 64 + 13; /* 64 is HMAC header */
len *= 8; /* convert to bits */
if (off < (64 - 8)) {
# ifdef BSWAP4
blocks[i].d[15] = BSWAP4(len);
# else
PUTU32(blocks[i].c + 60, len);
# endif
edges[i].blocks = 1;
} else {
# ifdef BSWAP4
blocks[i].d[31] = BSWAP4(len);
# else
PUTU32(blocks[i].c + 124, len);
# endif
edges[i].blocks = 2;
}
edges[i].ptr = blocks[i].c;
}
/* hash input tails and finalize */
sha1_multi_block(mctx, edges, n4x);
memset(blocks, 0, sizeof(blocks));
for (i = 0; i < x4; i++) {
# ifdef BSWAP4
blocks[i].d[0] = BSWAP4(mctx->A[i]);
mctx->A[i] = sctx->tail.h0;
blocks[i].d[1] = BSWAP4(mctx->B[i]);
mctx->B[i] = sctx->tail.h1;
blocks[i].d[2] = BSWAP4(mctx->C[i]);
mctx->C[i] = sctx->tail.h2;
blocks[i].d[3] = BSWAP4(mctx->D[i]);
mctx->D[i] = sctx->tail.h3;
blocks[i].d[4] = BSWAP4(mctx->E[i]);
mctx->E[i] = sctx->tail.h4;
blocks[i].c[20] = 0x80;
blocks[i].d[15] = BSWAP4((64 + 20) * 8);
# else
PUTU32(blocks[i].c + 0, mctx->A[i]);
mctx->A[i] = sctx->tail.h0;
PUTU32(blocks[i].c + 4, mctx->B[i]);
mctx->B[i] = sctx->tail.h1;
PUTU32(blocks[i].c + 8, mctx->C[i]);
mctx->C[i] = sctx->tail.h2;
PUTU32(blocks[i].c + 12, mctx->D[i]);
mctx->D[i] = sctx->tail.h3;
PUTU32(blocks[i].c + 16, mctx->E[i]);
mctx->E[i] = sctx->tail.h4;
blocks[i].c[20] = 0x80;
PUTU32(blocks[i].c + 60, (64 + 20) * 8);
# endif /* BSWAP */
edges[i].ptr = blocks[i].c;
edges[i].blocks = 1;
}
/* finalize MACs */
sha1_multi_block(mctx, edges, n4x);
for (i = 0; i < x4; i++) {
unsigned int len = (i == (x4 - 1) ? last : frag), pad, j;
unsigned char *out0 = out;
memcpy(ciph_d[i].out, ciph_d[i].inp, len - processed);
ciph_d[i].inp = ciph_d[i].out;
out += 5 + 16 + len;
/* write MAC */
PUTU32(out + 0, mctx->A[i]);
PUTU32(out + 4, mctx->B[i]);
PUTU32(out + 8, mctx->C[i]);
PUTU32(out + 12, mctx->D[i]);
PUTU32(out + 16, mctx->E[i]);
out += 20;
len += 20;
/* pad */
pad = 15 - len % 16;
for (j = 0; j <= pad; j++)
*(out++) = pad;
len += pad + 1;
ciph_d[i].blocks = (len - processed) / 16;
len += 16; /* account for explicit iv */
/* arrange header */
out0[0] = ((u8 *)sctx->md.data)[8];
out0[1] = ((u8 *)sctx->md.data)[9];
out0[2] = ((u8 *)sctx->md.data)[10];
out0[3] = (u8)(len >> 8);
out0[4] = (u8)(len);
ret += len + 5;
inp += frag;
}
aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x);
OPENSSL_cleanse(blocks, sizeof(blocks));
OPENSSL_cleanse(mctx, sizeof(*mctx));
ctx->multiblock_encrypt_len = ret;
return ret;
}
# endif /* OPENSSL_NO_MULTIBLOCK */
static int aesni_cbc_hmac_sha1_cipher(PROV_CIPHER_CTX *vctx,
unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
unsigned int l;
size_t plen = ctx->payload_length;
size_t iv = 0; /* explicit IV in TLS 1.1 and later */
size_t aes_off = 0, blocks;
size_t sha_off = SHA_CBLOCK - sctx->md.num;
ctx->payload_length = NO_PAYLOAD_LENGTH;
if (len % AES_BLOCK_SIZE)
return 0;
if (ctx->base.enc) {
if (plen == NO_PAYLOAD_LENGTH)
plen = len;
else if (len !=
((plen + SHA_DIGEST_LENGTH +
AES_BLOCK_SIZE) & -AES_BLOCK_SIZE))
return 0;
else if (ctx->aux.tls_ver >= TLS1_1_VERSION)
iv = AES_BLOCK_SIZE;
if (plen > (sha_off + iv)
&& (blocks = (plen - (sha_off + iv)) / SHA_CBLOCK)) {
sha1_update(&sctx->md, in + iv, sha_off);
aesni_cbc_sha1_enc(in, out, blocks, &ctx->ks, ctx->base.iv,
&sctx->md, in + iv + sha_off);
blocks *= SHA_CBLOCK;
aes_off += blocks;
sha_off += blocks;
sctx->md.Nh += blocks >> 29;
sctx->md.Nl += blocks <<= 3;
if (sctx->md.Nl < (unsigned int)blocks)
sctx->md.Nh++;
} else {
sha_off = 0;
}
sha_off += iv;
sha1_update(&sctx->md, in + sha_off, plen - sha_off);
if (plen != len) { /* "TLS" mode of operation */
if (in != out)
memcpy(out + aes_off, in + aes_off, plen - aes_off);
/* calculate HMAC and append it to payload */
SHA1_Final(out + plen, &sctx->md);
sctx->md = sctx->tail;
sha1_update(&sctx->md, out + plen, SHA_DIGEST_LENGTH);
SHA1_Final(out + plen, &sctx->md);
/* pad the payload|hmac */
plen += SHA_DIGEST_LENGTH;
for (l = len - plen - 1; plen < len; plen++)
out[plen] = l;
/* encrypt HMAC|padding at once */
aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off,
&ctx->ks, ctx->base.iv, 1);
} else {
aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off,
&ctx->ks, ctx->base.iv, 1);
}
} else {
union {
unsigned int u[SHA_DIGEST_LENGTH / sizeof(unsigned int)];
unsigned char c[32 + SHA_DIGEST_LENGTH];
} mac, *pmac;
/* arrange cache line alignment */
pmac = (void *)(((size_t)mac.c + 31) & ((size_t)0 - 32));
if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */
size_t inp_len, mask, j, i;
unsigned int res, maxpad, pad, bitlen;
int ret = 1;
union {
unsigned int u[SHA_LBLOCK];
unsigned char c[SHA_CBLOCK];
} *data = (void *)sctx->md.data;
if ((ctx->aux.tls_aad[plen - 4] << 8 | ctx->aux.tls_aad[plen - 3])
>= TLS1_1_VERSION) {
if (len < (AES_BLOCK_SIZE + SHA_DIGEST_LENGTH + 1))
return 0;
/* omit explicit iv */
memcpy(ctx->base.iv, in, AES_BLOCK_SIZE);
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
len -= AES_BLOCK_SIZE;
} else if (len < (SHA_DIGEST_LENGTH + 1))
return 0;
/* decrypt HMAC|padding at once */
aesni_cbc_encrypt(in, out, len, &ctx->ks, ctx->base.iv, 0);
/* figure out payload length */
pad = out[len - 1];
maxpad = len - (SHA_DIGEST_LENGTH + 1);
maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8);
maxpad &= 255;
mask = constant_time_ge(maxpad, pad);
ret &= mask;
/*
* If pad is invalid then we will fail the above test but we must
* continue anyway because we are in constant time code. However,
* we'll use the maxpad value instead of the supplied pad to make
* sure we perform well defined pointer arithmetic.
*/
pad = constant_time_select(mask, pad, maxpad);
inp_len = len - (SHA_DIGEST_LENGTH + pad + 1);
ctx->aux.tls_aad[plen - 2] = inp_len >> 8;
ctx->aux.tls_aad[plen - 1] = inp_len;
/* calculate HMAC */
sctx->md = sctx->head;
sha1_update(&sctx->md, ctx->aux.tls_aad, plen);
/* code containing lucky-13 fix */
len -= SHA_DIGEST_LENGTH; /* amend mac */
if (len >= (256 + SHA_CBLOCK)) {
j = (len - (256 + SHA_CBLOCK)) & (0 - SHA_CBLOCK);
j += SHA_CBLOCK - sctx->md.num;
sha1_update(&sctx->md, out, j);
out += j;
len -= j;
inp_len -= j;
}
/* but pretend as if we hashed padded payload */
bitlen = sctx->md.Nl + (inp_len << 3); /* at most 18 bits */
# ifdef BSWAP4
bitlen = BSWAP4(bitlen);
# else
mac.c[0] = 0;
mac.c[1] = (unsigned char)(bitlen >> 16);
mac.c[2] = (unsigned char)(bitlen >> 8);
mac.c[3] = (unsigned char)bitlen;
bitlen = mac.u[0];
# endif /* BSWAP */
pmac->u[0] = 0;
pmac->u[1] = 0;
pmac->u[2] = 0;
pmac->u[3] = 0;
pmac->u[4] = 0;
for (res = sctx->md.num, j = 0; j < len; j++) {
size_t c = out[j];
mask = (j - inp_len) >> (sizeof(j) * 8 - 8);
c &= mask;
c |= 0x80 & ~mask & ~((inp_len - j) >> (sizeof(j) * 8 - 8));
data->c[res++] = (unsigned char)c;
if (res != SHA_CBLOCK)
continue;
/* j is not incremented yet */
mask = 0 - ((inp_len + 7 - j) >> (sizeof(j) * 8 - 1));
data->u[SHA_LBLOCK - 1] |= bitlen & mask;
sha1_block_data_order(&sctx->md, data, 1);
mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1));
pmac->u[0] |= sctx->md.h0 & mask;
pmac->u[1] |= sctx->md.h1 & mask;
pmac->u[2] |= sctx->md.h2 & mask;
pmac->u[3] |= sctx->md.h3 & mask;
pmac->u[4] |= sctx->md.h4 & mask;
res = 0;
}
for (i = res; i < SHA_CBLOCK; i++, j++)
data->c[i] = 0;
if (res > SHA_CBLOCK - 8) {
mask = 0 - ((inp_len + 8 - j) >> (sizeof(j) * 8 - 1));
data->u[SHA_LBLOCK - 1] |= bitlen & mask;
sha1_block_data_order(&sctx->md, data, 1);
mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
pmac->u[0] |= sctx->md.h0 & mask;
pmac->u[1] |= sctx->md.h1 & mask;
pmac->u[2] |= sctx->md.h2 & mask;
pmac->u[3] |= sctx->md.h3 & mask;
pmac->u[4] |= sctx->md.h4 & mask;
memset(data, 0, SHA_CBLOCK);
j += 64;
}
data->u[SHA_LBLOCK - 1] = bitlen;
sha1_block_data_order(&sctx->md, data, 1);
mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
pmac->u[0] |= sctx->md.h0 & mask;
pmac->u[1] |= sctx->md.h1 & mask;
pmac->u[2] |= sctx->md.h2 & mask;
pmac->u[3] |= sctx->md.h3 & mask;
pmac->u[4] |= sctx->md.h4 & mask;
# ifdef BSWAP4
pmac->u[0] = BSWAP4(pmac->u[0]);
pmac->u[1] = BSWAP4(pmac->u[1]);
pmac->u[2] = BSWAP4(pmac->u[2]);
pmac->u[3] = BSWAP4(pmac->u[3]);
pmac->u[4] = BSWAP4(pmac->u[4]);
# else
for (i = 0; i < 5; i++) {
res = pmac->u[i];
pmac->c[4 * i + 0] = (unsigned char)(res >> 24);
pmac->c[4 * i + 1] = (unsigned char)(res >> 16);
pmac->c[4 * i + 2] = (unsigned char)(res >> 8);
pmac->c[4 * i + 3] = (unsigned char)res;
}
# endif /* BSWAP4 */
len += SHA_DIGEST_LENGTH;
sctx->md = sctx->tail;
sha1_update(&sctx->md, pmac->c, SHA_DIGEST_LENGTH);
SHA1_Final(pmac->c, &sctx->md);
/* verify HMAC */
out += inp_len;
len -= inp_len;
/* version of code with lucky-13 fix */
{
unsigned char *p = out + len - 1 - maxpad - SHA_DIGEST_LENGTH;
size_t off = out - p;
unsigned int c, cmask;
maxpad += SHA_DIGEST_LENGTH;
for (res = 0, i = 0, j = 0; j < maxpad; j++) {
c = p[j];
cmask =
((int)(j - off - SHA_DIGEST_LENGTH)) >> (sizeof(int) *
8 - 1);
res |= (c ^ pad) & ~cmask; /* ... and padding */
cmask &= ((int)(off - 1 - j)) >> (sizeof(int) * 8 - 1);
res |= (c ^ pmac->c[i]) & cmask;
i += 1 & cmask;
}
maxpad -= SHA_DIGEST_LENGTH;
res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
ret &= (int)~res;
}
return ret;
} else {
/* decrypt HMAC|padding at once */
aesni_cbc_encrypt(in, out, len, &ctx->ks, ctx->base.iv, 0);
sha1_update(&sctx->md, out, len);
}
}
return 1;
}
/* EVP_CTRL_AEAD_SET_MAC_KEY */
static void aesni_cbc_hmac_sha1_set_mac_key(void *vctx,
const unsigned char *mac, size_t len)
{
PROV_AES_HMAC_SHA1_CTX *ctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
unsigned int i;
unsigned char hmac_key[64];
memset(hmac_key, 0, sizeof(hmac_key));
if (len > (int)sizeof(hmac_key)) {
SHA1_Init(&ctx->head);
sha1_update(&ctx->head, mac, len);
SHA1_Final(hmac_key, &ctx->head);
} else {
memcpy(hmac_key, mac, len);
}
for (i = 0; i < sizeof(hmac_key); i++)
hmac_key[i] ^= 0x36; /* ipad */
SHA1_Init(&ctx->head);
sha1_update(&ctx->head, hmac_key, sizeof(hmac_key));
for (i = 0; i < sizeof(hmac_key); i++)
hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */
SHA1_Init(&ctx->tail);
sha1_update(&ctx->tail, hmac_key, sizeof(hmac_key));
OPENSSL_cleanse(hmac_key, sizeof(hmac_key));
}
/* EVP_CTRL_AEAD_TLS1_AAD */
static int aesni_cbc_hmac_sha1_set_tls1_aad(void *vctx,
unsigned char *aad_rec, int aad_len)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
unsigned char *p = aad_rec;
unsigned int len;
if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
return -1;
len = p[aad_len - 2] << 8 | p[aad_len - 1];
if (ctx->base.enc) {
ctx->payload_length = len;
if ((ctx->aux.tls_ver =
p[aad_len - 4] << 8 | p[aad_len - 3]) >= TLS1_1_VERSION) {
if (len < AES_BLOCK_SIZE)
return 0;
len -= AES_BLOCK_SIZE;
p[aad_len - 2] = len >> 8;
p[aad_len - 1] = len;
}
sctx->md = sctx->head;
sha1_update(&sctx->md, p, aad_len);
ctx->tls_aad_pad = (int)(((len + SHA_DIGEST_LENGTH +
AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)
- len);
return 1;
} else {
memcpy(ctx->aux.tls_aad, aad_rec, aad_len);
ctx->payload_length = aad_len;
ctx->tls_aad_pad = SHA_DIGEST_LENGTH;
return 1;
}
}
# if !defined(OPENSSL_NO_MULTIBLOCK)
/* EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE */
static int aesni_cbc_hmac_sha1_tls1_multiblock_max_bufsize(void *vctx)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
OPENSSL_assert(ctx->multiblock_max_send_fragment != 0);
return (int)(5 + 16
+ (((int)ctx->multiblock_max_send_fragment + 20 + 16) & -16));
}
/* EVP_CTRL_TLS1_1_MULTIBLOCK_AAD */
static int aesni_cbc_hmac_sha1_tls1_multiblock_aad(
void *vctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
unsigned int n4x = 1, x4;
unsigned int frag, last, packlen, inp_len;
inp_len = param->inp[11] << 8 | param->inp[12];
ctx->multiblock_interleave = param->interleave;
if (ctx->base.enc) {
if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION)
return -1;
if (inp_len) {
if (inp_len < 4096)
return 0; /* too short */
if (inp_len >= 8192 && OPENSSL_ia32cap_P[2] & (1 << 5))
n4x = 2; /* AVX2 */
} else if ((n4x = param->interleave / 4) && n4x <= 2)
inp_len = param->len;
else
return -1;
sctx->md = sctx->head;
sha1_update(&sctx->md, param->inp, 13);
x4 = 4 * n4x;
n4x += 1;
frag = inp_len >> n4x;
last = inp_len + frag - (frag << n4x);
if (last > frag && ((last + 13 + 9) % 64 < (x4 - 1))) {
frag++;
last -= x4 - 1;
}
packlen = 5 + 16 + ((frag + 20 + 16) & -16);
packlen = (packlen << n4x) - packlen;
packlen += 5 + 16 + ((last + 20 + 16) & -16);
param->interleave = x4;
/* The returned values used by get need to be stored */
ctx->multiblock_interleave = x4;
ctx->multiblock_aad_packlen = packlen;
return 1;
}
return -1; /* not yet */
}
/* EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT */
static int aesni_cbc_hmac_sha1_tls1_multiblock_encrypt(
void *ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param)
{
return (int)tls1_multi_block_encrypt(ctx, param->out,
param->inp, param->len,
param->interleave / 4);
}
#endif /* OPENSSL_NO_MULTIBLOCK */
static const PROV_CIPHER_HW_AES_HMAC_SHA cipher_hw_aes_hmac_sha1 = {
{
aesni_cbc_hmac_sha1_init_key,
aesni_cbc_hmac_sha1_cipher
},
aesni_cbc_hmac_sha1_set_mac_key,
aesni_cbc_hmac_sha1_set_tls1_aad,
# if !defined(OPENSSL_NO_MULTIBLOCK)
aesni_cbc_hmac_sha1_tls1_multiblock_max_bufsize,
aesni_cbc_hmac_sha1_tls1_multiblock_aad,
aesni_cbc_hmac_sha1_tls1_multiblock_encrypt
# endif
};
const PROV_CIPHER_HW_AES_HMAC_SHA *PROV_CIPHER_HW_aes_cbc_hmac_sha1(void)
{
return &cipher_hw_aes_hmac_sha1;
}
#endif /* AES_CBC_HMAC_SHA_CAPABLE */
@@ -0,0 +1,838 @@
/*
* Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* AES low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include "cipher_aes_cbc_hmac_sha.h"
#ifndef AES_CBC_HMAC_SHA_CAPABLE
int cipher_capable_aes_cbc_hmac_sha256(void)
{
return 0;
}
#else
# include "crypto/rand.h"
# include "crypto/evp.h"
# include "internal/constant_time.h"
void sha256_block_data_order(void *c, const void *p, size_t len);
int aesni_cbc_sha256_enc(const void *inp, void *out, size_t blocks,
const AES_KEY *key, unsigned char iv[16],
SHA256_CTX *ctx, const void *in0);
int cipher_capable_aes_cbc_hmac_sha256(void)
{
return AESNI_CBC_HMAC_SHA_CAPABLE
&& aesni_cbc_sha256_enc(NULL, NULL, 0, NULL, NULL, NULL, NULL);
}
static int aesni_cbc_hmac_sha256_init_key(PROV_CIPHER_CTX *vctx,
const unsigned char *key,
size_t keylen)
{
int ret;
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
if (ctx->base.enc)
ret = aesni_set_encrypt_key(key, ctx->base.keylen * 8, &ctx->ks);
else
ret = aesni_set_decrypt_key(key, ctx->base.keylen * 8, &ctx->ks);
SHA256_Init(&sctx->head); /* handy when benchmarking */
sctx->tail = sctx->head;
sctx->md = sctx->head;
ctx->payload_length = NO_PAYLOAD_LENGTH;
return ret < 0 ? 0 : 1;
}
void sha256_block_data_order(void *c, const void *p, size_t len);
static void sha256_update(SHA256_CTX *c, const void *data, size_t len)
{
const unsigned char *ptr = data;
size_t res;
if ((res = c->num)) {
res = SHA256_CBLOCK - res;
if (len < res)
res = len;
SHA256_Update(c, ptr, res);
ptr += res;
len -= res;
}
res = len % SHA256_CBLOCK;
len -= res;
if (len) {
sha256_block_data_order(c, ptr, len / SHA256_CBLOCK);
ptr += len;
c->Nh += len >> 29;
c->Nl += len <<= 3;
if (c->Nl < (unsigned int)len)
c->Nh++;
}
if (res)
SHA256_Update(c, ptr, res);
}
# if !defined(OPENSSL_NO_MULTIBLOCK)
typedef struct {
unsigned int A[8], B[8], C[8], D[8], E[8], F[8], G[8], H[8];
} SHA256_MB_CTX;
typedef struct {
const unsigned char *ptr;
int blocks;
} HASH_DESC;
typedef struct {
const unsigned char *inp;
unsigned char *out;
int blocks;
u64 iv[2];
} CIPH_DESC;
void sha256_multi_block(SHA256_MB_CTX *, const HASH_DESC *, int);
void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int);
static size_t tls1_multi_block_encrypt(void *vctx,
unsigned char *out,
const unsigned char *inp,
size_t inp_len, int n4x)
{ /* n4x is 1 or 2 */
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
HASH_DESC hash_d[8], edges[8];
CIPH_DESC ciph_d[8];
unsigned char storage[sizeof(SHA256_MB_CTX) + 32];
union {
u64 q[16];
u32 d[32];
u8 c[128];
} blocks[8];
SHA256_MB_CTX *mctx;
unsigned int frag, last, packlen, i;
unsigned int x4 = 4 * n4x, minblocks, processed = 0;
size_t ret = 0;
u8 *IVs;
# if defined(BSWAP8)
u64 seqnum;
# endif
/* ask for IVs in bulk */
if (rand_bytes_ex(ctx->base.libctx, (IVs = blocks[0].c), 16 * x4) <= 0)
return 0;
mctx = (SHA256_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); /* align */
frag = (unsigned int)inp_len >> (1 + n4x);
last = (unsigned int)inp_len + frag - (frag << (1 + n4x));
if (last > frag && ((last + 13 + 9) % 64) < (x4 - 1)) {
frag++;
last -= x4 - 1;
}
packlen = 5 + 16 + ((frag + 32 + 16) & -16);
/* populate descriptors with pointers and IVs */
hash_d[0].ptr = inp;
ciph_d[0].inp = inp;
/* 5+16 is place for header and explicit IV */
ciph_d[0].out = out + 5 + 16;
memcpy(ciph_d[0].out - 16, IVs, 16);
memcpy(ciph_d[0].iv, IVs, 16);
IVs += 16;
for (i = 1; i < x4; i++) {
ciph_d[i].inp = hash_d[i].ptr = hash_d[i - 1].ptr + frag;
ciph_d[i].out = ciph_d[i - 1].out + packlen;
memcpy(ciph_d[i].out - 16, IVs, 16);
memcpy(ciph_d[i].iv, IVs, 16);
IVs += 16;
}
# if defined(BSWAP8)
memcpy(blocks[0].c, sctx->md.data, 8);
seqnum = BSWAP8(blocks[0].q[0]);
# endif
for (i = 0; i < x4; i++) {
unsigned int len = (i == (x4 - 1) ? last : frag);
# if !defined(BSWAP8)
unsigned int carry, j;
# endif
mctx->A[i] = sctx->md.h[0];
mctx->B[i] = sctx->md.h[1];
mctx->C[i] = sctx->md.h[2];
mctx->D[i] = sctx->md.h[3];
mctx->E[i] = sctx->md.h[4];
mctx->F[i] = sctx->md.h[5];
mctx->G[i] = sctx->md.h[6];
mctx->H[i] = sctx->md.h[7];
/* fix seqnum */
# if defined(BSWAP8)
blocks[i].q[0] = BSWAP8(seqnum + i);
# else
for (carry = i, j = 8; j--;) {
blocks[i].c[j] = ((u8 *)sctx->md.data)[j] + carry;
carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1);
}
# endif
blocks[i].c[8] = ((u8 *)sctx->md.data)[8];
blocks[i].c[9] = ((u8 *)sctx->md.data)[9];
blocks[i].c[10] = ((u8 *)sctx->md.data)[10];
/* fix length */
blocks[i].c[11] = (u8)(len >> 8);
blocks[i].c[12] = (u8)(len);
memcpy(blocks[i].c + 13, hash_d[i].ptr, 64 - 13);
hash_d[i].ptr += 64 - 13;
hash_d[i].blocks = (len - (64 - 13)) / 64;
edges[i].ptr = blocks[i].c;
edges[i].blocks = 1;
}
/* hash 13-byte headers and first 64-13 bytes of inputs */
sha256_multi_block(mctx, edges, n4x);
/* hash bulk inputs */
# define MAXCHUNKSIZE 2048
# if MAXCHUNKSIZE%64
# error "MAXCHUNKSIZE is not divisible by 64"
# elif MAXCHUNKSIZE
/*
* goal is to minimize pressure on L1 cache by moving in shorter steps,
* so that hashed data is still in the cache by the time we encrypt it
*/
minblocks = ((frag <= last ? frag : last) - (64 - 13)) / 64;
if (minblocks > MAXCHUNKSIZE / 64) {
for (i = 0; i < x4; i++) {
edges[i].ptr = hash_d[i].ptr;
edges[i].blocks = MAXCHUNKSIZE / 64;
ciph_d[i].blocks = MAXCHUNKSIZE / 16;
}
do {
sha256_multi_block(mctx, edges, n4x);
aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x);
for (i = 0; i < x4; i++) {
edges[i].ptr = hash_d[i].ptr += MAXCHUNKSIZE;
hash_d[i].blocks -= MAXCHUNKSIZE / 64;
edges[i].blocks = MAXCHUNKSIZE / 64;
ciph_d[i].inp += MAXCHUNKSIZE;
ciph_d[i].out += MAXCHUNKSIZE;
ciph_d[i].blocks = MAXCHUNKSIZE / 16;
memcpy(ciph_d[i].iv, ciph_d[i].out - 16, 16);
}
processed += MAXCHUNKSIZE;
minblocks -= MAXCHUNKSIZE / 64;
} while (minblocks > MAXCHUNKSIZE / 64);
}
# endif
# undef MAXCHUNKSIZE
sha256_multi_block(mctx, hash_d, n4x);
memset(blocks, 0, sizeof(blocks));
for (i = 0; i < x4; i++) {
unsigned int len = (i == (x4 - 1) ? last : frag),
off = hash_d[i].blocks * 64;
const unsigned char *ptr = hash_d[i].ptr + off;
off = (len - processed) - (64 - 13) - off; /* remainder actually */
memcpy(blocks[i].c, ptr, off);
blocks[i].c[off] = 0x80;
len += 64 + 13; /* 64 is HMAC header */
len *= 8; /* convert to bits */
if (off < (64 - 8)) {
# ifdef BSWAP4
blocks[i].d[15] = BSWAP4(len);
# else
PUTU32(blocks[i].c + 60, len);
# endif
edges[i].blocks = 1;
} else {
# ifdef BSWAP4
blocks[i].d[31] = BSWAP4(len);
# else
PUTU32(blocks[i].c + 124, len);
# endif
edges[i].blocks = 2;
}
edges[i].ptr = blocks[i].c;
}
/* hash input tails and finalize */
sha256_multi_block(mctx, edges, n4x);
memset(blocks, 0, sizeof(blocks));
for (i = 0; i < x4; i++) {
# ifdef BSWAP4
blocks[i].d[0] = BSWAP4(mctx->A[i]);
mctx->A[i] = sctx->tail.h[0];
blocks[i].d[1] = BSWAP4(mctx->B[i]);
mctx->B[i] = sctx->tail.h[1];
blocks[i].d[2] = BSWAP4(mctx->C[i]);
mctx->C[i] = sctx->tail.h[2];
blocks[i].d[3] = BSWAP4(mctx->D[i]);
mctx->D[i] = sctx->tail.h[3];
blocks[i].d[4] = BSWAP4(mctx->E[i]);
mctx->E[i] = sctx->tail.h[4];
blocks[i].d[5] = BSWAP4(mctx->F[i]);
mctx->F[i] = sctx->tail.h[5];
blocks[i].d[6] = BSWAP4(mctx->G[i]);
mctx->G[i] = sctx->tail.h[6];
blocks[i].d[7] = BSWAP4(mctx->H[i]);
mctx->H[i] = sctx->tail.h[7];
blocks[i].c[32] = 0x80;
blocks[i].d[15] = BSWAP4((64 + 32) * 8);
# else
PUTU32(blocks[i].c + 0, mctx->A[i]);
mctx->A[i] = sctx->tail.h[0];
PUTU32(blocks[i].c + 4, mctx->B[i]);
mctx->B[i] = sctx->tail.h[1];
PUTU32(blocks[i].c + 8, mctx->C[i]);
mctx->C[i] = sctx->tail.h[2];
PUTU32(blocks[i].c + 12, mctx->D[i]);
mctx->D[i] = sctx->tail.h[3];
PUTU32(blocks[i].c + 16, mctx->E[i]);
mctx->E[i] = sctx->tail.h[4];
PUTU32(blocks[i].c + 20, mctx->F[i]);
mctx->F[i] = sctx->tail.h[5];
PUTU32(blocks[i].c + 24, mctx->G[i]);
mctx->G[i] = sctx->tail.h[6];
PUTU32(blocks[i].c + 28, mctx->H[i]);
mctx->H[i] = sctx->tail.h[7];
blocks[i].c[32] = 0x80;
PUTU32(blocks[i].c + 60, (64 + 32) * 8);
# endif /* BSWAP */
edges[i].ptr = blocks[i].c;
edges[i].blocks = 1;
}
/* finalize MACs */
sha256_multi_block(mctx, edges, n4x);
for (i = 0; i < x4; i++) {
unsigned int len = (i == (x4 - 1) ? last : frag), pad, j;
unsigned char *out0 = out;
memcpy(ciph_d[i].out, ciph_d[i].inp, len - processed);
ciph_d[i].inp = ciph_d[i].out;
out += 5 + 16 + len;
/* write MAC */
PUTU32(out + 0, mctx->A[i]);
PUTU32(out + 4, mctx->B[i]);
PUTU32(out + 8, mctx->C[i]);
PUTU32(out + 12, mctx->D[i]);
PUTU32(out + 16, mctx->E[i]);
PUTU32(out + 20, mctx->F[i]);
PUTU32(out + 24, mctx->G[i]);
PUTU32(out + 28, mctx->H[i]);
out += 32;
len += 32;
/* pad */
pad = 15 - len % 16;
for (j = 0; j <= pad; j++)
*(out++) = pad;
len += pad + 1;
ciph_d[i].blocks = (len - processed) / 16;
len += 16; /* account for explicit iv */
/* arrange header */
out0[0] = ((u8 *)sctx->md.data)[8];
out0[1] = ((u8 *)sctx->md.data)[9];
out0[2] = ((u8 *)sctx->md.data)[10];
out0[3] = (u8)(len >> 8);
out0[4] = (u8)(len);
ret += len + 5;
inp += frag;
}
aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x);
OPENSSL_cleanse(blocks, sizeof(blocks));
OPENSSL_cleanse(mctx, sizeof(*mctx));
ctx->multiblock_encrypt_len = ret;
return ret;
}
# endif /* !OPENSSL_NO_MULTIBLOCK */
static int aesni_cbc_hmac_sha256_cipher(PROV_CIPHER_CTX *vctx,
unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
unsigned int l;
size_t plen = ctx->payload_length;
size_t iv = 0; /* explicit IV in TLS 1.1 and * later */
size_t aes_off = 0, blocks;
size_t sha_off = SHA256_CBLOCK - sctx->md.num;
ctx->payload_length = NO_PAYLOAD_LENGTH;
if (len % AES_BLOCK_SIZE)
return 0;
if (ctx->base.enc) {
if (plen == NO_PAYLOAD_LENGTH)
plen = len;
else if (len !=
((plen + SHA256_DIGEST_LENGTH +
AES_BLOCK_SIZE) & -AES_BLOCK_SIZE))
return 0;
else if (ctx->aux.tls_ver >= TLS1_1_VERSION)
iv = AES_BLOCK_SIZE;
/*
* Assembly stitch handles AVX-capable processors, but its
* performance is not optimal on AMD Jaguar, ~40% worse, for
* unknown reasons. Incidentally processor in question supports
* AVX, but not AMD-specific XOP extension, which can be used
* to identify it and avoid stitch invocation. So that after we
* establish that current CPU supports AVX, we even see if it's
* either even XOP-capable Bulldozer-based or GenuineIntel one.
* But SHAEXT-capable go ahead...
*/
if (((OPENSSL_ia32cap_P[2] & (1 << 29)) || /* SHAEXT? */
((OPENSSL_ia32cap_P[1] & (1 << (60 - 32))) && /* AVX? */
((OPENSSL_ia32cap_P[1] & (1 << (43 - 32))) /* XOP? */
| (OPENSSL_ia32cap_P[0] & (1 << 30))))) && /* "Intel CPU"? */
plen > (sha_off + iv) &&
(blocks = (plen - (sha_off + iv)) / SHA256_CBLOCK)) {
sha256_update(&sctx->md, in + iv, sha_off);
(void)aesni_cbc_sha256_enc(in, out, blocks, &ctx->ks,
ctx->base.iv,
&sctx->md, in + iv + sha_off);
blocks *= SHA256_CBLOCK;
aes_off += blocks;
sha_off += blocks;
sctx->md.Nh += blocks >> 29;
sctx->md.Nl += blocks <<= 3;
if (sctx->md.Nl < (unsigned int)blocks)
sctx->md.Nh++;
} else {
sha_off = 0;
}
sha_off += iv;
sha256_update(&sctx->md, in + sha_off, plen - sha_off);
if (plen != len) { /* "TLS" mode of operation */
if (in != out)
memcpy(out + aes_off, in + aes_off, plen - aes_off);
/* calculate HMAC and append it to payload */
SHA256_Final(out + plen, &sctx->md);
sctx->md = sctx->tail;
sha256_update(&sctx->md, out + plen, SHA256_DIGEST_LENGTH);
SHA256_Final(out + plen, &sctx->md);
/* pad the payload|hmac */
plen += SHA256_DIGEST_LENGTH;
for (l = len - plen - 1; plen < len; plen++)
out[plen] = l;
/* encrypt HMAC|padding at once */
aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off,
&ctx->ks, ctx->base.iv, 1);
} else {
aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off,
&ctx->ks, ctx->base.iv, 1);
}
} else {
union {
unsigned int u[SHA256_DIGEST_LENGTH / sizeof(unsigned int)];
unsigned char c[64 + SHA256_DIGEST_LENGTH];
} mac, *pmac;
/* arrange cache line alignment */
pmac = (void *)(((size_t)mac.c + 63) & ((size_t)0 - 64));
/* decrypt HMAC|padding at once */
aesni_cbc_encrypt(in, out, len, &ctx->ks,
ctx->base.iv, 0);
if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */
size_t inp_len, mask, j, i;
unsigned int res, maxpad, pad, bitlen;
int ret = 1;
union {
unsigned int u[SHA_LBLOCK];
unsigned char c[SHA256_CBLOCK];
} *data = (void *)sctx->md.data;
if ((ctx->aux.tls_aad[plen - 4] << 8 | ctx->aux.tls_aad[plen - 3])
>= TLS1_1_VERSION)
iv = AES_BLOCK_SIZE;
if (len < (iv + SHA256_DIGEST_LENGTH + 1))
return 0;
/* omit explicit iv */
out += iv;
len -= iv;
/* figure out payload length */
pad = out[len - 1];
maxpad = len - (SHA256_DIGEST_LENGTH + 1);
maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8);
maxpad &= 255;
mask = constant_time_ge(maxpad, pad);
ret &= mask;
/*
* If pad is invalid then we will fail the above test but we must
* continue anyway because we are in constant time code. However,
* we'll use the maxpad value instead of the supplied pad to make
* sure we perform well defined pointer arithmetic.
*/
pad = constant_time_select(mask, pad, maxpad);
inp_len = len - (SHA256_DIGEST_LENGTH + pad + 1);
ctx->aux.tls_aad[plen - 2] = inp_len >> 8;
ctx->aux.tls_aad[plen - 1] = inp_len;
/* calculate HMAC */
sctx->md = sctx->head;
sha256_update(&sctx->md, ctx->aux.tls_aad, plen);
/* code with lucky-13 fix */
len -= SHA256_DIGEST_LENGTH; /* amend mac */
if (len >= (256 + SHA256_CBLOCK)) {
j = (len - (256 + SHA256_CBLOCK)) & (0 - SHA256_CBLOCK);
j += SHA256_CBLOCK - sctx->md.num;
sha256_update(&sctx->md, out, j);
out += j;
len -= j;
inp_len -= j;
}
/* but pretend as if we hashed padded payload */
bitlen = sctx->md.Nl + (inp_len << 3); /* at most 18 bits */
# ifdef BSWAP4
bitlen = BSWAP4(bitlen);
# else
mac.c[0] = 0;
mac.c[1] = (unsigned char)(bitlen >> 16);
mac.c[2] = (unsigned char)(bitlen >> 8);
mac.c[3] = (unsigned char)bitlen;
bitlen = mac.u[0];
# endif /* BSWAP */
pmac->u[0] = 0;
pmac->u[1] = 0;
pmac->u[2] = 0;
pmac->u[3] = 0;
pmac->u[4] = 0;
pmac->u[5] = 0;
pmac->u[6] = 0;
pmac->u[7] = 0;
for (res = sctx->md.num, j = 0; j < len; j++) {
size_t c = out[j];
mask = (j - inp_len) >> (sizeof(j) * 8 - 8);
c &= mask;
c |= 0x80 & ~mask & ~((inp_len - j) >> (sizeof(j) * 8 - 8));
data->c[res++] = (unsigned char)c;
if (res != SHA256_CBLOCK)
continue;
/* j is not incremented yet */
mask = 0 - ((inp_len + 7 - j) >> (sizeof(j) * 8 - 1));
data->u[SHA_LBLOCK - 1] |= bitlen & mask;
sha256_block_data_order(&sctx->md, data, 1);
mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1));
pmac->u[0] |= sctx->md.h[0] & mask;
pmac->u[1] |= sctx->md.h[1] & mask;
pmac->u[2] |= sctx->md.h[2] & mask;
pmac->u[3] |= sctx->md.h[3] & mask;
pmac->u[4] |= sctx->md.h[4] & mask;
pmac->u[5] |= sctx->md.h[5] & mask;
pmac->u[6] |= sctx->md.h[6] & mask;
pmac->u[7] |= sctx->md.h[7] & mask;
res = 0;
}
for (i = res; i < SHA256_CBLOCK; i++, j++)
data->c[i] = 0;
if (res > SHA256_CBLOCK - 8) {
mask = 0 - ((inp_len + 8 - j) >> (sizeof(j) * 8 - 1));
data->u[SHA_LBLOCK - 1] |= bitlen & mask;
sha256_block_data_order(&sctx->md, data, 1);
mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
pmac->u[0] |= sctx->md.h[0] & mask;
pmac->u[1] |= sctx->md.h[1] & mask;
pmac->u[2] |= sctx->md.h[2] & mask;
pmac->u[3] |= sctx->md.h[3] & mask;
pmac->u[4] |= sctx->md.h[4] & mask;
pmac->u[5] |= sctx->md.h[5] & mask;
pmac->u[6] |= sctx->md.h[6] & mask;
pmac->u[7] |= sctx->md.h[7] & mask;
memset(data, 0, SHA256_CBLOCK);
j += 64;
}
data->u[SHA_LBLOCK - 1] = bitlen;
sha256_block_data_order(&sctx->md, data, 1);
mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
pmac->u[0] |= sctx->md.h[0] & mask;
pmac->u[1] |= sctx->md.h[1] & mask;
pmac->u[2] |= sctx->md.h[2] & mask;
pmac->u[3] |= sctx->md.h[3] & mask;
pmac->u[4] |= sctx->md.h[4] & mask;
pmac->u[5] |= sctx->md.h[5] & mask;
pmac->u[6] |= sctx->md.h[6] & mask;
pmac->u[7] |= sctx->md.h[7] & mask;
# ifdef BSWAP4
pmac->u[0] = BSWAP4(pmac->u[0]);
pmac->u[1] = BSWAP4(pmac->u[1]);
pmac->u[2] = BSWAP4(pmac->u[2]);
pmac->u[3] = BSWAP4(pmac->u[3]);
pmac->u[4] = BSWAP4(pmac->u[4]);
pmac->u[5] = BSWAP4(pmac->u[5]);
pmac->u[6] = BSWAP4(pmac->u[6]);
pmac->u[7] = BSWAP4(pmac->u[7]);
# else
for (i = 0; i < 8; i++) {
res = pmac->u[i];
pmac->c[4 * i + 0] = (unsigned char)(res >> 24);
pmac->c[4 * i + 1] = (unsigned char)(res >> 16);
pmac->c[4 * i + 2] = (unsigned char)(res >> 8);
pmac->c[4 * i + 3] = (unsigned char)res;
}
# endif /* BSWAP */
len += SHA256_DIGEST_LENGTH;
sctx->md = sctx->tail;
sha256_update(&sctx->md, pmac->c, SHA256_DIGEST_LENGTH);
SHA256_Final(pmac->c, &sctx->md);
/* verify HMAC */
out += inp_len;
len -= inp_len;
/* code containing lucky-13 fix */
{
unsigned char *p =
out + len - 1 - maxpad - SHA256_DIGEST_LENGTH;
size_t off = out - p;
unsigned int c, cmask;
maxpad += SHA256_DIGEST_LENGTH;
for (res = 0, i = 0, j = 0; j < maxpad; j++) {
c = p[j];
cmask =
((int)(j - off - SHA256_DIGEST_LENGTH)) >>
(sizeof(int) * 8 - 1);
res |= (c ^ pad) & ~cmask; /* ... and padding */
cmask &= ((int)(off - 1 - j)) >> (sizeof(int) * 8 - 1);
res |= (c ^ pmac->c[i]) & cmask;
i += 1 & cmask;
}
maxpad -= SHA256_DIGEST_LENGTH;
res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
ret &= (int)~res;
}
return ret;
} else {
sha256_update(&sctx->md, out, len);
}
}
return 1;
}
/* EVP_CTRL_AEAD_SET_MAC_KEY */
static void aesni_cbc_hmac_sha256_set_mac_key(void *vctx,
const unsigned char *mackey,
size_t len)
{
PROV_AES_HMAC_SHA256_CTX *ctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
unsigned int i;
unsigned char hmac_key[64];
memset(hmac_key, 0, sizeof(hmac_key));
if (len > sizeof(hmac_key)) {
SHA256_Init(&ctx->head);
sha256_update(&ctx->head, mackey, len);
SHA256_Final(hmac_key, &ctx->head);
} else {
memcpy(hmac_key, mackey, len);
}
for (i = 0; i < sizeof(hmac_key); i++)
hmac_key[i] ^= 0x36; /* ipad */
SHA256_Init(&ctx->head);
sha256_update(&ctx->head, hmac_key, sizeof(hmac_key));
for (i = 0; i < sizeof(hmac_key); i++)
hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */
SHA256_Init(&ctx->tail);
sha256_update(&ctx->tail, hmac_key, sizeof(hmac_key));
OPENSSL_cleanse(hmac_key, sizeof(hmac_key));
}
/* EVP_CTRL_AEAD_TLS1_AAD */
static int aesni_cbc_hmac_sha256_set_tls1_aad(void *vctx,
unsigned char *aad_rec, int aad_len)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
unsigned char *p = aad_rec;
unsigned int len;
if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
return -1;
len = p[aad_len - 2] << 8 | p[aad_len - 1];
if (ctx->base.enc) {
ctx->payload_length = len;
if ((ctx->aux.tls_ver =
p[aad_len - 4] << 8 | p[aad_len - 3]) >= TLS1_1_VERSION) {
if (len < AES_BLOCK_SIZE)
return 0;
len -= AES_BLOCK_SIZE;
p[aad_len] = len >> 8;
p[aad_len - 1] = len;
}
sctx->md = sctx->head;
sha256_update(&sctx->md, p, aad_len);
ctx->tls_aad_pad = (int)(((len + SHA256_DIGEST_LENGTH +
AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)
- len);
return 1;
} else {
memcpy(ctx->aux.tls_aad, p, aad_len);
ctx->payload_length = aad_len;
ctx->tls_aad_pad = SHA256_DIGEST_LENGTH;
return 1;
}
}
# if !defined(OPENSSL_NO_MULTIBLOCK)
/* EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE */
static int aesni_cbc_hmac_sha256_tls1_multiblock_max_bufsize(
void *vctx)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
OPENSSL_assert(ctx->multiblock_max_send_fragment != 0);
return (int)(5 + 16
+ (((int)ctx->multiblock_max_send_fragment + 32 + 16) & -16));
}
/* EVP_CTRL_TLS1_1_MULTIBLOCK_AAD */
static int aesni_cbc_hmac_sha256_tls1_multiblock_aad(
void *vctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
unsigned int n4x = 1, x4;
unsigned int frag, last, packlen, inp_len;
inp_len = param->inp[11] << 8 | param->inp[12];
if (ctx->base.enc) {
if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION)
return -1;
if (inp_len) {
if (inp_len < 4096)
return 0; /* too short */
if (inp_len >= 8192 && OPENSSL_ia32cap_P[2] & (1 << 5))
n4x = 2; /* AVX2 */
} else if ((n4x = param->interleave / 4) && n4x <= 2)
inp_len = param->len;
else
return -1;
sctx->md = sctx->head;
sha256_update(&sctx->md, param->inp, 13);
x4 = 4 * n4x;
n4x += 1;
frag = inp_len >> n4x;
last = inp_len + frag - (frag << n4x);
if (last > frag && ((last + 13 + 9) % 64 < (x4 - 1))) {
frag++;
last -= x4 - 1;
}
packlen = 5 + 16 + ((frag + 32 + 16) & -16);
packlen = (packlen << n4x) - packlen;
packlen += 5 + 16 + ((last + 32 + 16) & -16);
param->interleave = x4;
/* The returned values used by get need to be stored */
ctx->multiblock_interleave = x4;
ctx->multiblock_aad_packlen = packlen;
return 1;
}
return -1; /* not yet */
}
/* EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT */
static int aesni_cbc_hmac_sha256_tls1_multiblock_encrypt(
void *ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param)
{
return (int)tls1_multi_block_encrypt(ctx, param->out,
param->inp, param->len,
param->interleave / 4);
}
#endif
static const PROV_CIPHER_HW_AES_HMAC_SHA cipher_hw_aes_hmac_sha256 = {
{
aesni_cbc_hmac_sha256_init_key,
aesni_cbc_hmac_sha256_cipher
},
aesni_cbc_hmac_sha256_set_mac_key,
aesni_cbc_hmac_sha256_set_tls1_aad,
# if !defined(OPENSSL_NO_MULTIBLOCK)
aesni_cbc_hmac_sha256_tls1_multiblock_max_bufsize,
aesni_cbc_hmac_sha256_tls1_multiblock_aad,
aesni_cbc_hmac_sha256_tls1_multiblock_encrypt
# endif
};
const PROV_CIPHER_HW_AES_HMAC_SHA *PROV_CIPHER_HW_aes_cbc_hmac_sha256(void)
{
return &cipher_hw_aes_hmac_sha256;
}
#endif /* AES_CBC_HMAC_SHA_CAPABLE */
@@ -7,10 +7,16 @@
* https://www.openssl.org/source/license.html
*/
/*
* AES low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
/* Dispatch functions for AES CCM mode */
#include "prov/ciphercommon.h"
#include "prov/cipher_ccm.h"
#include "cipher_aes_ccm.h"
#include "prov/implementations.h"
static void *aes_ccm_newctx(void *provctx, size_t keybits)
@@ -0,0 +1,48 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/aes.h>
#include "prov/ciphercommon.h"
#include "prov/ciphercommon_ccm.h"
#include "crypto/aes_platform.h"
typedef struct prov_aes_ccm_ctx_st {
PROV_CCM_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
/*-
* Padding is chosen so that s390x.kmac.k overlaps with ks.ks and
* fc with ks.ks.rounds. Remember that on s390x, an AES_KEY's
* rounds field is used to store the function code and that the key
* schedule is not stored (if aes hardware support is detected).
*/
struct {
unsigned char pad[16];
AES_KEY ks;
} ks;
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
struct {
S390X_KMAC_PARAMS kmac;
unsigned long long blocks;
union {
unsigned long long g[2];
unsigned char b[AES_BLOCK_SIZE];
} nonce;
union {
unsigned long long g[2];
unsigned char b[AES_BLOCK_SIZE];
} buf;
unsigned char dummy_pad[168];
unsigned int fc; /* fc has same offset as ks.ks.rounds */
} s390x;
#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
} ccm;
} PROV_AES_CCM_CTX;
const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keylen);
@@ -9,8 +9,13 @@
/* AES CCM mode */
#include "prov/ciphercommon.h"
#include "prov/cipher_ccm.h"
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include "cipher_aes_ccm.h"
#define AES_HW_CCM_SET_KEY_FN(fn_set_enc_key, fn_blk, fn_ccm_enc, fn_ccm_dec) \
fn_set_enc_key(key, keylen * 8, &actx->ccm.ks.ks); \
@@ -9,7 +9,7 @@
/*-
* AES-NI support for AES CCM.
* This file is included by cipher_ccm_hw.c
* This file is included by cipher_aes_ccm_hw.c
*/
static int ccm_aesni_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
@@ -9,7 +9,7 @@
/*-
* S390X support for AES CCM.
* This file is included by cipher_ccm_hw.c
* This file is included by cipher_aes_ccm_hw.c
*/
#define S390X_CCM_AAD_FLAG 0x40
@@ -9,7 +9,7 @@
/*-
* Fujitsu SPARC64 X support for AES CCM.
* This file is included by cipher_ccm_hw.c
* This file is included by cipher_aes_ccm_hw.c
*/
static int ccm_t4_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
@@ -7,10 +7,16 @@
* https://www.openssl.org/source/license.html
*/
/*
* AES low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
/* Dispatch functions for AES GCM mode */
#include "prov/ciphercommon.h"
#include "prov/cipher_gcm.h"
#include "cipher_aes_gcm.h"
#include "prov/implementations.h"
static void *aes_gcm_newctx(void *provctx, size_t keybits)
@@ -0,0 +1,44 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/aes.h>
#include "prov/ciphercommon.h"
#include "prov/ciphercommon_gcm.h"
#include "crypto/aes_platform.h"
typedef struct prov_aes_gcm_ctx_st {
PROV_GCM_CTX base; /* must be first entry in struct */
union {
OSSL_UNION_ALIGN;
AES_KEY ks;
} ks; /* AES key schedule to use */
/* Platform specific data */
union {
int dummy;
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
struct {
union {
OSSL_UNION_ALIGN;
S390X_KMA_PARAMS kma;
} param;
unsigned int fc;
unsigned char ares[16];
unsigned char mres[16];
unsigned char kres[16];
int areslen;
int mreslen;
int kreslen;
int res;
} s390x;
#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
} plat;
} PROV_AES_GCM_CTX;
const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits);
@@ -9,10 +9,15 @@
/* Dispatch functions for AES GCM mode */
#include "prov/ciphercommon.h"
#include "prov/cipher_gcm.h"
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
static int generic_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
#include "cipher_aes_gcm.h"
static int aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
size_t keylen)
{
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
@@ -54,11 +59,76 @@ static int generic_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
return 1;
}
static int generic_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
size_t len, unsigned char *out)
{
if (ctx->enc) {
if (ctx->ctr != NULL) {
#if defined(AES_GCM_ASM)
size_t bulk = 0;
if (len >= AES_GCM_ENC_BYTES && AES_GCM_ASM(ctx)) {
size_t res = (16 - ctx->gcm.mres) % 16;
if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res))
return 0;
bulk = AES_gcm_encrypt(in + res, out + res, len - res,
ctx->gcm.key,
ctx->gcm.Yi.c, ctx->gcm.Xi.u);
ctx->gcm.len.u[1] += bulk;
bulk += res;
}
if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
len - bulk, ctx->ctr))
return 0;
#else
if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
return 0;
#endif /* AES_GCM_ASM */
} else {
if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len))
return 0;
}
} else {
if (ctx->ctr != NULL) {
#if defined(AES_GCM_ASM)
size_t bulk = 0;
if (len >= AES_GCM_DEC_BYTES && AES_GCM_ASM(ctx)) {
size_t res = (16 - ctx->gcm.mres) % 16;
if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res))
return -1;
bulk = AES_gcm_decrypt(in + res, out + res, len - res,
ctx->gcm.key,
ctx->gcm.Yi.c, ctx->gcm.Xi.u);
ctx->gcm.len.u[1] += bulk;
bulk += res;
}
if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
len - bulk, ctx->ctr))
return 0;
#else
if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
return 0;
#endif /* AES_GCM_ASM */
} else {
if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len))
return 0;
}
}
return 1;
}
static const PROV_GCM_HW aes_gcm = {
generic_aes_gcm_initkey,
aes_gcm_initkey,
gcm_setiv,
gcm_aad_update,
gcm_cipher_update,
generic_aes_gcm_cipher_update,
gcm_cipher_final,
gcm_one_shot
};
@@ -69,6 +139,8 @@ static const PROV_GCM_HW aes_gcm = {
# include "cipher_aes_gcm_hw_aesni.inc"
#elif defined(SPARC_AES_CAPABLE)
# include "cipher_aes_gcm_hw_t4.inc"
#elif defined(AES_PMULL_CAPABLE) && defined(AES_GCM_ASM)
# include "cipher_aes_gcm_hw_armv8.inc"
#else
const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits)
{
@@ -9,7 +9,7 @@
/*-
* AES-NI support for AES GCM.
* This file is included by cipher_gcm_hw.c
* This file is included by cipher_aes_gcm_hw.c
*/
static int aesni_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
@@ -26,7 +26,7 @@ static const PROV_GCM_HW aesni_gcm = {
aesni_gcm_initkey,
gcm_setiv,
gcm_aad_update,
gcm_cipher_update,
generic_aes_gcm_cipher_update,
gcm_cipher_final,
gcm_one_shot
};
@@ -0,0 +1,83 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* Crypto extention support for AES GCM.
* This file is included by cipher_aes_gcm_hw.c
*/
size_t armv8_aes_gcm_encrypt(const unsigned char *in, unsigned char *out, size_t len,
const void *key, unsigned char ivec[16], u64 *Xi)
{
size_t align_bytes = 0;
align_bytes = len - len % 16;
AES_KEY *aes_key = (AES_KEY *)key;
switch(aes_key->rounds) {
case 10:
aes_gcm_enc_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
break;
case 12:
aes_gcm_enc_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
break;
case 14:
aes_gcm_enc_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
break;
}
return align_bytes;
}
size_t armv8_aes_gcm_decrypt(const unsigned char *in, unsigned char *out, size_t len,
const void *key, unsigned char ivec[16], u64 *Xi)
{
size_t align_bytes = 0;
align_bytes = len - len % 16;
AES_KEY *aes_key = (AES_KEY *)key;
switch(aes_key->rounds) {
case 10:
aes_gcm_dec_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
break;
case 12:
aes_gcm_dec_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
break;
case 14:
aes_gcm_dec_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
break;
}
return align_bytes;
}
static int armv8_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
size_t keylen)
{
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
AES_KEY *ks = &actx->ks.ks;
GCM_HW_SET_KEY_CTR_FN(ks, aes_v8_set_encrypt_key, aes_v8_encrypt,
aes_v8_ctr32_encrypt_blocks);
return 1;
}
static const PROV_GCM_HW armv8_aes_gcm = {
armv8_aes_gcm_initkey,
gcm_setiv,
gcm_aad_update,
generic_aes_gcm_cipher_update,
gcm_cipher_final,
gcm_one_shot
};
const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits)
{
return AES_PMULL_CAPABLE ? &armv8_aes_gcm : &aes_gcm;
}
@@ -9,7 +9,7 @@
/*-
* IBM S390X support for AES GCM.
* This file is included by cipher_gcm_hw.c
* This file is included by cipher_aes_gcm_hw.c
*/
/* iv + padding length for iv lengths != 12 */
@@ -9,7 +9,7 @@
/*-
* Fujitsu SPARC64 X support for AES GCM.
* This file is included by cipher_gcm_hw.c
* This file is included by cipher_aes_gcm_hw.c
*/
static int t4_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
@@ -42,7 +42,7 @@ static const PROV_GCM_HW t4_aes_gcm = {
t4_aes_gcm_initkey,
gcm_setiv,
gcm_aad_update,
gcm_cipher_update,
generic_aes_gcm_cipher_update,
gcm_cipher_final,
gcm_one_shot
};
@@ -7,6 +7,12 @@
* https://www.openssl.org/source/license.html
*/
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include "cipher_aes.h"
#include "prov/providercommonerr.h"
@@ -29,6 +35,10 @@ static int cipher_hw_aes_initkey(PROV_CIPHER_CTX *dat,
# ifdef HWAES_cbc_encrypt
if (dat->mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
# endif
# ifdef HWAES_ecb_encrypt
if (dat->mode == EVP_CIPH_ECB_MODE)
dat->stream.ecb = (ecb128_f)HWAES_ecb_encrypt;
# endif
} else
#endif
@@ -64,6 +74,11 @@ static int cipher_hw_aes_initkey(PROV_CIPHER_CTX *dat,
dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
else
# endif
# ifdef HWAES_ecb_encrypt
if (dat->mode == EVP_CIPH_ECB_MODE)
dat->stream.ecb = (ecb128_f)HWAES_ecb_encrypt;
else
# endif
# ifdef HWAES_ctr32_encrypt_blocks
if (dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks;
@@ -106,10 +121,13 @@ static int cipher_hw_aes_initkey(PROV_CIPHER_CTX *dat,
return 1;
}
IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_aes_copyctx, PROV_AES_CTX)
#define PROV_CIPHER_HW_aes_mode(mode) \
static const PROV_CIPHER_HW aes_##mode = { \
cipher_hw_aes_initkey, \
cipher_hw_generic_##mode \
cipher_hw_generic_##mode, \
cipher_hw_aes_copyctx \
}; \
PROV_CIPHER_HW_declare(mode) \
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_##mode(size_t keybits) \
@@ -76,7 +76,8 @@ static int cipher_hw_aesni_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out,
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW aesni_##mode = { \
cipher_hw_aesni_initkey, \
cipher_hw_aesni_##mode \
cipher_hw_aesni_##mode, \
cipher_hw_aes_copyctx \
};
#define PROV_CIPHER_HW_select(mode) \
if (AESNI_CAPABLE) \
@@ -193,7 +193,8 @@ static int s390x_aes_cfb8_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW s390x_aes_##mode = { \
s390x_aes_##mode##_initkey, \
s390x_aes_##mode##_cipher_hw \
s390x_aes_##mode##_cipher_hw, \
cipher_hw_aes_copyctx \
};
#define PROV_CIPHER_HW_select(mode) \
if ((keybits == 128 && S390X_aes_128_##mode##_CAPABLE) \
@@ -88,7 +88,8 @@ static int cipher_hw_aes_t4_initkey(PROV_CIPHER_CTX *dat,
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW aes_t4_##mode = { \
cipher_hw_aes_t4_initkey, \
cipher_hw_generic_##mode \
cipher_hw_generic_##mode, \
cipher_hw_aes_copyctx \
};
#define PROV_CIPHER_HW_select(mode) \
if (SPARC_AES_CAPABLE) \
@@ -7,9 +7,16 @@
* https://www.openssl.org/source/license.html
*/
/*
* AES low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include "cipher_aes_ocb.h"
#include "prov/providercommonerr.h"
#include "prov/cipher_aead.h"
#include "prov/ciphercommon_aead.h"
#include "prov/implementations.h"
#define AES_OCB_FLAGS AEAD_FLAGS
@@ -84,8 +91,8 @@ static ossl_inline int aes_generic_ocb_cipher(PROV_AES_OCB_CTX *ctx,
static ossl_inline int aes_generic_ocb_copy_ctx(PROV_AES_OCB_CTX *dst,
PROV_AES_OCB_CTX *src)
{
return (!CRYPTO_ocb128_copy_ctx(&dst->ocb, &src->ocb,
&src->ksenc.ks, &src->ksdec.ks));
return CRYPTO_ocb128_copy_ctx(&dst->ocb, &src->ocb,
&dst->ksenc.ks, &dst->ksdec.ks);
}
/*-
@@ -214,6 +221,11 @@ static int aes_ocb_block_update(void *vctx, unsigned char *out, size_t *outl,
if (!ctx->key_set || !update_iv(ctx))
return 0;
if (inl == 0) {
*outl = 0;
return 1;
}
/* Are we dealing with AAD or normal data here? */
if (out == NULL) {
buf = ctx->aad_buf;
@@ -9,6 +9,7 @@
#include <openssl/aes.h>
#include "prov/ciphercommon.h"
#include "crypto/aes_platform.h"
#define OCB_MAX_TAG_LEN AES_BLOCK_SIZE
#define OCB_MAX_DATA_LEN AES_BLOCK_SIZE
@@ -7,6 +7,12 @@
* https://www.openssl.org/source/license.html
*/
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include "cipher_aes_ocb.h"
#define OCB_SET_KEY_FN(fn_set_enc_key, fn_set_dec_key, \
@@ -0,0 +1,244 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Dispatch functions for AES SIV mode */
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include "cipher_aes_siv.h"
#include "prov/implementations.h"
#include "prov/providercommonerr.h"
#include "prov/ciphercommon_aead.h"
#define siv_stream_update siv_cipher
#define SIV_FLAGS AEAD_FLAGS
static void *aes_siv_newctx(void *provctx, size_t keybits, unsigned int mode,
uint64_t flags)
{
PROV_AES_SIV_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL) {
ctx->taglen = SIV_LEN;
ctx->mode = mode;
ctx->flags = flags;
ctx->keylen = keybits / 8;
ctx->hw = PROV_CIPHER_HW_aes_siv(keybits);
}
return ctx;
}
static void aes_siv_freectx(void *vctx)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
if (ctx != NULL) {
ctx->hw->cleanup(ctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
}
static int siv_init(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen, int enc)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
ctx->enc = enc;
if (key != NULL) {
if (keylen != ctx->keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
return ctx->hw->initkey(ctx, key, ctx->keylen);
}
return 1;
}
static int siv_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return siv_init(vctx, key, keylen, iv, ivlen, 1);
}
static int siv_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return siv_init(vctx, key, keylen, iv, ivlen, 0);
}
static int siv_cipher(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in, size_t inl)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
if (inl == 0) {
*outl = 0;
return 1;
}
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (ctx->hw->cipher(ctx, out, in, inl) <= 0)
return 0;
if (outl != NULL)
*outl = inl;
return 1;
}
static int siv_stream_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
if (!ctx->hw->cipher(vctx, out, NULL, 0))
return 0;
if (outl != NULL)
*outl = 0;
return 1;
}
static int aes_siv_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
SIV128_CONTEXT *sctx = &ctx->siv;
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
if (p != NULL && p->data_type == OSSL_PARAM_OCTET_STRING) {
if (!ctx->enc
|| p->data_size != ctx->taglen
|| !OSSL_PARAM_set_octet_string(p, &sctx->tag.byte, ctx->taglen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->taglen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
return 1;
}
static const OSSL_PARAM aes_siv_known_gettable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_SPEED, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *aes_siv_gettable_ctx_params(void)
{
return aes_siv_known_gettable_ctx_params;
}
static int aes_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
const OSSL_PARAM *p;
unsigned int speed = 0;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
if (p != NULL) {
if (ctx->enc)
return 1;
if (p->data_type != OSSL_PARAM_OCTET_STRING
|| !ctx->hw->settag(ctx, p->data, p->data_size)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_SPEED);
if (p != NULL) {
if (!OSSL_PARAM_get_uint(p, &speed)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
ctx->hw->setspeed(ctx, (int)speed);
}
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 0;
}
/* The key length can not be modified */
if (keylen != ctx->keylen)
return 0;
}
return 1;
}
static const OSSL_PARAM aes_siv_known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_SPEED, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *aes_siv_settable_ctx_params(void)
{
return aes_siv_known_settable_ctx_params;
}
#define IMPLEMENT_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \
static OSSL_OP_cipher_get_params_fn alg##_##kbits##_##lc##_get_params; \
static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \
{ \
return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
flags, 2*kbits, blkbits, ivbits); \
} \
static OSSL_OP_cipher_newctx_fn alg##kbits##lc##_newctx; \
static void * alg##kbits##lc##_newctx(void *provctx) \
{ \
return alg##_##lc##_newctx(provctx, 2*kbits, EVP_CIPH_##UCMODE##_MODE, \
flags); \
} \
const OSSL_DISPATCH alg##kbits##lc##_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))alg##kbits##lc##_newctx }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))alg##_##lc##_freectx }, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) lc##_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) lc##_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void)) lc##_stream_update }, \
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void)) lc##_stream_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void)) lc##_cipher }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void)) alg##_##kbits##_##lc##_get_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void)) alg##_##lc##_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void)) alg##_##lc##_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void)) alg##_##lc##_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void)) alg##_##lc##_settable_ctx_params }, \
{ 0, NULL } \
};
IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 128, 8, 0)
IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 192, 8, 0)
IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 256, 8, 0)
@@ -0,0 +1,35 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "prov/ciphercommon.h"
#include "crypto/aes_platform.h"
#include "crypto/siv.h"
typedef struct prov_cipher_hw_aes_siv_st {
int (*initkey)(void *ctx, const uint8_t *key, size_t keylen);
int (*cipher)(void *ctx, unsigned char *out, const unsigned char *in,
size_t len);
void (*setspeed)(void *ctx, int speed);
int (*settag)(void *ctx, const unsigned char *tag, size_t tagl);
void (*cleanup)(void *ctx);
} PROV_CIPHER_HW_AES_SIV;
typedef struct prov_siv_ctx_st {
unsigned int mode; /* The mode that we are using */
unsigned int enc : 1; /* Set to 1 if we are encrypting or 0 otherwise */
uint64_t flags;
size_t keylen; /* The input keylength (twice the alg key length) */
size_t taglen; /* the taglen is the same as the sivlen */
SIV128_CONTEXT siv;
EVP_CIPHER *ctr; /* These are fetched - so we need to free them */
EVP_CIPHER *cbc;
const PROV_CIPHER_HW_AES_SIV *hw;
} PROV_AES_SIV_CTX;
const PROV_CIPHER_HW_AES_SIV *PROV_CIPHER_HW_aes_siv(size_t keybits);
@@ -0,0 +1,105 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include "cipher_aes_siv.h"
static int aes_siv_initkey(void *vctx, const unsigned char *key, size_t keylen)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
SIV128_CONTEXT *sctx = &ctx->siv;
size_t klen = keylen / 2;
switch (klen) {
case 16:
ctx->cbc = EVP_CIPHER_fetch(NULL, "AES-128-CBC", "");
ctx->ctr = EVP_CIPHER_fetch(NULL, "AES-128-CTR", "");
break;
case 24:
ctx->cbc = EVP_CIPHER_fetch(NULL, "AES-192-CBC", "");
ctx->ctr = EVP_CIPHER_fetch(NULL, "AES-192-CTR", "");
break;
case 32:
ctx->cbc = EVP_CIPHER_fetch(NULL, "AES-256-CBC", "");
ctx->ctr = EVP_CIPHER_fetch(NULL, "AES-256-CTR", "");
break;
default:
return 0;
}
/*
* klen is the length of the underlying cipher, not the input key,
* which should be twice as long
*/
return CRYPTO_siv128_init(sctx, key, klen, ctx->cbc, ctx->ctr);
}
static int aes_siv_settag(void *vctx, const unsigned char *tag, size_t tagl)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
SIV128_CONTEXT *sctx = &ctx->siv;
return CRYPTO_siv128_set_tag(sctx, tag, tagl);
}
static void aes_siv_setspeed(void *vctx, int speed)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
SIV128_CONTEXT *sctx = &ctx->siv;
CRYPTO_siv128_speed(sctx, (int)speed);
}
static void aes_siv_cleanup(void *vctx)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
SIV128_CONTEXT *sctx = &ctx->siv;
CRYPTO_siv128_cleanup(sctx);
EVP_CIPHER_free(ctx->cbc);
EVP_CIPHER_free(ctx->ctr);
}
static int aes_siv_cipher(void *vctx, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
SIV128_CONTEXT *sctx = &ctx->siv;
/* EncryptFinal or DecryptFinal */
if (in == NULL)
return CRYPTO_siv128_finish(sctx) == 0;
/* Deal with associated data */
if (out == NULL)
return (CRYPTO_siv128_aad(sctx, in, len) == 1);
if (ctx->enc)
return CRYPTO_siv128_encrypt(sctx, in, out, len) > 0;
return CRYPTO_siv128_decrypt(sctx, in, out, len) > 0;
}
static const PROV_CIPHER_HW_AES_SIV aes_siv_hw =
{
aes_siv_initkey,
aes_siv_cipher,
aes_siv_setspeed,
aes_siv_settag,
aes_siv_cleanup
};
const PROV_CIPHER_HW_AES_SIV *PROV_CIPHER_HW_aes_siv(size_t keybits)
{
return &aes_siv_hw;
}
@@ -7,6 +7,12 @@
* https://www.openssl.org/source/license.html
*/
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include "cipher_aes.h"
#include "prov/providercommonerr.h"
#include "prov/implementations.h"
@@ -164,6 +170,11 @@ static int aes_wrap_cipher(void *vctx,
PROV_AES_WRAP_CTX *ctx = (PROV_AES_WRAP_CTX *)vctx;
size_t len;
if (inl == 0) {
*outl = 0;
return 1;
}
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return -1;
@@ -7,6 +7,13 @@
* https://www.openssl.org/source/license.html
*/
/*
* AES low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include "cipher_aes_xts.h"
#include "prov/implementations.h"
#include "prov/providercommonerr.h"
@@ -134,7 +141,7 @@ static void *aes_xts_dupctx(void *vctx)
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
*ret = *in;
in->base.hw->copyctx(&ret->base, &in->base);
return ret;
}
@@ -152,7 +159,7 @@ static int aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl,
return 0;
/*
* Impose a limit of 2^20 blocks per data unit as specifed by
* Impose a limit of 2^20 blocks per data unit as specified by
* IEEE Std 1619-2018. The earlier and obsolete IEEE Std 1619-2007
* indicated that this was a SHOULD NOT rather than a MUST NOT.
* NIST SP 800-38E mandates the same limit.
@@ -9,6 +9,7 @@
#include <openssl/aes.h>
#include "prov/ciphercommon.h"
#include "crypto/aes_platform.h"
/*
* Available in cipher_fips.c, and compiled with different values depending
@@ -7,6 +7,13 @@
* https://www.openssl.org/source/license.html
*/
/*
* AES low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include "cipher_aes_xts.h"
#ifdef FIPS_MODE
@@ -7,6 +7,12 @@
* https://www.openssl.org/source/license.html
*/
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include "cipher_aes_xts.h"
#define XTS_SET_KEY_FN(fn_set_enc_key, fn_set_dec_key, \
@@ -76,6 +82,17 @@ static int cipher_hw_aes_xts_generic_initkey(PROV_CIPHER_CTX *ctx,
return 1;
}
static void cipher_hw_aes_xts_copyctx(PROV_CIPHER_CTX *dst,
const PROV_CIPHER_CTX *src)
{
PROV_AES_XTS_CTX *sctx = (PROV_AES_XTS_CTX *)src;
PROV_AES_XTS_CTX *dctx = (PROV_AES_XTS_CTX *)dst;
*dctx = *sctx;
dctx->xts.key1 = &dctx->ks1.ks;
dctx->xts.key2 = &dctx->ks2.ks;
}
#if defined(AESNI_CAPABLE)
static int cipher_hw_aesni_xts_initkey(PROV_CIPHER_CTX *ctx,
@@ -92,7 +109,8 @@ static int cipher_hw_aesni_xts_initkey(PROV_CIPHER_CTX *ctx,
# define PROV_CIPHER_HW_declare_xts() \
static const PROV_CIPHER_HW aesni_xts = { \
cipher_hw_aesni_xts_initkey, \
NULL \
NULL, \
cipher_hw_aes_xts_copyctx \
};
# define PROV_CIPHER_HW_select_xts() \
if (AESNI_CAPABLE) \
@@ -130,7 +148,8 @@ static int cipher_hw_aes_xts_t4_initkey(PROV_CIPHER_CTX *ctx,
# define PROV_CIPHER_HW_declare_xts() \
static const PROV_CIPHER_HW aes_xts_t4 = { \
cipher_hw_aes_xts_t4_initkey, \
NULL \
NULL, \
cipher_hw_aes_xts_copyctx \
};
# define PROV_CIPHER_HW_select_xts() \
if (SPARC_AES_CAPABLE) \
@@ -143,7 +162,8 @@ if (SPARC_AES_CAPABLE) \
static const PROV_CIPHER_HW aes_generic_xts = {
cipher_hw_aes_xts_generic_initkey,
NULL
NULL,
cipher_hw_aes_xts_copyctx
};
PROV_CIPHER_HW_declare_xts()
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_xts(size_t keybits)
@@ -31,7 +31,7 @@ static void *aria_dupctx(void *ctx)
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
*ret = *in;
in->base.hw->copyctx(&ret->base, &in->base);
return ret;
}
@@ -9,7 +9,7 @@
#include "crypto/aria.h"
#include "prov/ciphercommon.h"
#include "prov/cipher_ccm.h"
#include "prov/ciphercommon_ccm.h"
typedef struct prov_aria_ccm_ctx_st {
PROV_CCM_CTX base; /* Must be first */
@@ -9,7 +9,7 @@
#include "crypto/aria.h"
#include "prov/ciphercommon.h"
#include "prov/cipher_gcm.h"
#include "prov/ciphercommon_gcm.h"
typedef struct prov_aria_gcm_ctx_st {
PROV_GCM_CTX base; /* must be first entry in struct */
@@ -23,24 +23,11 @@ static int aria_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
return 1;
}
static int aria_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
size_t len, unsigned char *out)
{
if (ctx->enc) {
if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len))
return 0;
} else {
if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len))
return 0;
}
return 1;
}
static const PROV_GCM_HW aria_gcm = {
aria_gcm_initkey,
gcm_setiv,
gcm_aad_update,
aria_cipher_update,
gcm_cipher_update,
gcm_cipher_final,
gcm_one_shot
};
@@ -29,10 +29,13 @@ static int cipher_hw_aria_initkey(PROV_CIPHER_CTX *dat,
return 1;
}
IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_aria_copyctx, PROV_ARIA_CTX)
# define PROV_CIPHER_HW_aria_mode(mode) \
static const PROV_CIPHER_HW aria_##mode = { \
cipher_hw_aria_initkey, \
cipher_hw_chunked_##mode \
cipher_hw_chunked_##mode, \
cipher_hw_aria_copyctx \
}; \
const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_##mode(size_t keybits) \
{ \
@@ -9,6 +9,12 @@
/* Dispatch functions for Blowfish cipher modes ecb, cbc, ofb, cfb */
/*
* BF low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_blowfish.h"
#include "prov/implementations.h"
@@ -39,10 +45,10 @@ static void *blowfish_dupctx(void *ctx)
}
/* bf_ecb_functions */
IMPLEMENT_generic_cipher(blowfish, BLOWFISH, ecb, ECB, BF_FLAGS, 128, 64, 0, block)
IMPLEMENT_var_keylen_cipher(blowfish, BLOWFISH, ecb, ECB, BF_FLAGS, 128, 64, 0, block)
/* bf_cbc_functions */
IMPLEMENT_generic_cipher(blowfish, BLOWFISH, cbc, CBC, BF_FLAGS, 128, 64, 64, block)
IMPLEMENT_var_keylen_cipher(blowfish, BLOWFISH, cbc, CBC, BF_FLAGS, 128, 64, 64, block)
/* bf_ofb_functions */
IMPLEMENT_generic_cipher(blowfish, BLOWFISH, ofb64, OFB, BF_FLAGS, 64, 8, 64, stream)
IMPLEMENT_var_keylen_cipher(blowfish, BLOWFISH, ofb64, OFB, BF_FLAGS, 64, 8, 64, stream)
/* bf_cfb_functions */
IMPLEMENT_generic_cipher(blowfish, BLOWFISH, cfb64, CFB, BF_FLAGS, 64, 8, 64, stream)
IMPLEMENT_var_keylen_cipher(blowfish, BLOWFISH, cfb64, CFB, BF_FLAGS, 64, 8, 64, stream)
@@ -7,6 +7,12 @@
* https://www.openssl.org/source/license.html
*/
/*
* BF low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_blowfish.h"
static int cipher_hw_blowfish_initkey(PROV_CIPHER_CTX *ctx,
@@ -7,6 +7,12 @@
* https://www.openssl.org/source/license.html
*/
/*
* Camellia low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
/* Dispatch functions for CAMELLIA cipher modes ecb, cbc, ofb, cfb, ctr */
#include "cipher_camellia.h"
@@ -31,7 +37,7 @@ static void *camellia_dupctx(void *ctx)
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
*ret = *in;
in->base.hw->copyctx(&ret->base, &in->base);
return ret;
}
@@ -9,6 +9,7 @@
#include "openssl/camellia.h"
#include "prov/ciphercommon.h"
#include "crypto/cmll_platform.h"
typedef struct prov_camellia_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
@@ -7,6 +7,12 @@
* https://www.openssl.org/source/license.html
*/
/*
* Camellia low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include "cipher_camellia.h"
#include <openssl/camellia.h>
@@ -35,6 +41,8 @@ static int cipher_hw_camellia_initkey(PROV_CIPHER_CTX *dat,
return 1;
}
IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_camellia_copyctx, PROV_CAMELLIA_CTX)
# if defined(SPARC_CMLL_CAPABLE)
# include "cipher_camellia_hw_t4.inc"
# else
@@ -46,7 +54,8 @@ static int cipher_hw_camellia_initkey(PROV_CIPHER_CTX *dat,
#define PROV_CIPHER_HW_camellia_mode(mode) \
static const PROV_CIPHER_HW camellia_##mode = { \
cipher_hw_camellia_initkey, \
cipher_hw_generic_##mode \
cipher_hw_generic_##mode, \
cipher_hw_camellia_copyctx \
}; \
PROV_CIPHER_HW_declare(mode) \
const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_##mode(size_t keybits) \
@@ -76,7 +76,8 @@ static int cipher_hw_camellia_t4_initkey(PROV_CIPHER_CTX *dat,
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW t4_camellia_##mode = { \
cipher_hw_camellia_t4_initkey, \
cipher_hw_generic_##mode \
cipher_hw_generic_##mode, \
cipher_hw_camellia_copyctx \
};
#define PROV_CIPHER_HW_select(mode) \
if (SPARC_CMLL_CAPABLE) \
@@ -7,10 +7,17 @@
* https://www.openssl.org/source/license.html
*/
/*
* CAST low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
/* Dispatch functions for cast cipher modes ecb, cbc, ofb, cfb */
#include "cipher_cast.h"
#include "prov/implementations.h"
#include "prov/providercommonerr.h"
#define CAST5_FLAGS (EVP_CIPH_VARIABLE_LENGTH)
@@ -39,10 +46,10 @@ static void *cast5_dupctx(void *ctx)
}
/* cast5128ecb_functions */
IMPLEMENT_generic_cipher(cast5, CAST, ecb, ECB, CAST5_FLAGS, 128, 64, 0, block)
IMPLEMENT_var_keylen_cipher(cast5, CAST, ecb, ECB, CAST5_FLAGS, 128, 64, 0, block)
/* cast5128cbc_functions */
IMPLEMENT_generic_cipher(cast5, CAST, cbc, CBC, CAST5_FLAGS, 128, 64, 64, block)
IMPLEMENT_var_keylen_cipher(cast5, CAST, cbc, CBC, CAST5_FLAGS, 128, 64, 64, block)
/* cast564ofb64_functions */
IMPLEMENT_generic_cipher(cast5, CAST, ofb64, OFB, CAST5_FLAGS, 64, 8, 64, stream)
IMPLEMENT_var_keylen_cipher(cast5, CAST, ofb64, OFB, CAST5_FLAGS, 64, 8, 64, stream)
/* cast564cfb64_functions */
IMPLEMENT_generic_cipher(cast5, CAST, cfb64, CFB, CAST5_FLAGS, 64, 8, 64, stream)
IMPLEMENT_var_keylen_cipher(cast5, CAST, cfb64, CFB, CAST5_FLAGS, 64, 8, 64, stream)
@@ -7,6 +7,12 @@
* https://www.openssl.org/source/license.html
*/
/*
* CAST low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include "cipher_cast.h"
static int cipher_hw_cast5_initkey(PROV_CIPHER_CTX *ctx,
@@ -55,7 +55,7 @@ static void chacha20_freectx(void *vctx)
PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)vctx;
if (ctx != NULL) {
OPENSSL_clear_free(ctx, sizeof(ctx));
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
}
@@ -66,7 +66,7 @@ static void chacha20_poly1305_freectx(void *vctx)
PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)vctx;
if (ctx != NULL)
OPENSSL_clear_free(ctx, sizeof(ctx));
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static int chacha20_poly1305_get_params(OSSL_PARAM params[])
@@ -262,6 +262,11 @@ static int chacha20_poly1305_cipher(void *vctx, unsigned char *out,
PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
(PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->hw;
if (inl == 0) {
*outl = 0;
return 1;
}
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
@@ -142,7 +142,7 @@ static int chacha20_poly1305_tls_cipher(PROV_CIPHER_CTX *bctx,
ctx->len.text = plen;
if (plen) {
if (ctx->enc)
if (bctx->enc)
ctr = xor128_encrypt_n_pad(out, in, ctr, plen);
else
ctr = xor128_decrypt_n_pad(out, in, ctr, plen);
@@ -8,6 +8,7 @@
*/
#include <openssl/des.h>
#include "crypto/des_platform.h"
/* TODO(3.0) Figure out what flags need to be here */
#define TDES_FLAGS (EVP_CIPH_RAND_KEY)
@@ -9,6 +9,12 @@
/* Dispatch functions for RC2 cipher modes ecb, cbc, ofb, cfb */
/*
* RC2 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_rc2.h"
#include "prov/implementations.h"
#include "prov/providercommonerr.h"
@@ -130,7 +136,7 @@ static int rc2_set_ctx_params(void *vctx, OSSL_PARAM params[])
PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx;
const OSSL_PARAM *p;
if (!cipher_generic_set_ctx_params(vctx, params))
if (!cipher_var_keylen_set_ctx_params(vctx, params))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_RC2_KEYBITS);
if (p != NULL) {
@@ -176,6 +182,7 @@ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_RC2_KEYBITS, NULL),
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(rc2)
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(rc2)
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_RC2_KEYBITS, NULL),
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(rc2)
@@ -7,6 +7,12 @@
* https://www.openssl.org/source/license.html
*/
/*
* RC2 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_rc2.h"
static int cipher_hw_rc2_initkey(PROV_CIPHER_CTX *ctx,
@@ -9,6 +9,12 @@
/* Dispatch functions for RC4 ciphers */
/*
* RC4 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_rc4.h"
#include "prov/implementations.h"
@@ -71,13 +77,13 @@ const OSSL_DISPATCH alg##kbits##_functions[] = { \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void))cipher_generic_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void))cipher_generic_set_ctx_params }, \
(void (*)(void))cipher_var_keylen_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void))cipher_generic_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void))cipher_generic_settable_ctx_params }, \
(void (*)(void))cipher_var_keylen_settable_ctx_params }, \
{ 0, NULL } \
};
@@ -0,0 +1,197 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Dispatch functions for RC4_HMAC_MD5 cipher */
/*
* RC4 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_rc4_hmac_md5.h"
#include "prov/implementations.h"
#include "prov/providercommonerr.h"
/* TODO(3.0) Figure out what flags are required */
#define RC4_HMAC_MD5_FLAGS (EVP_CIPH_STREAM_CIPHER | EVP_CIPH_VARIABLE_LENGTH \
| EVP_CIPH_FLAG_AEAD_CIPHER)
#define RC4_HMAC_MD5_KEY_BITS (16 * 8)
#define RC4_HMAC_MD5_BLOCK_BITS (1 * 8)
#define RC4_HMAC_MD5_IV_BITS 0
#define RC4_HMAC_MD5_MODE 0
#define GET_HW(ctx) ((PROV_CIPHER_HW_RC4_HMAC_MD5 *)ctx->base.hw)
static OSSL_OP_cipher_newctx_fn rc4_hmac_md5_newctx;
static OSSL_OP_cipher_freectx_fn rc4_hmac_md5_freectx;
static OSSL_OP_cipher_get_ctx_params_fn rc4_hmac_md5_get_ctx_params;
static OSSL_OP_cipher_gettable_ctx_params_fn rc4_hmac_md5_gettable_ctx_params;
static OSSL_OP_cipher_set_ctx_params_fn rc4_hmac_md5_set_ctx_params;
static OSSL_OP_cipher_settable_ctx_params_fn rc4_hmac_md5_settable_ctx_params;
static OSSL_OP_cipher_get_params_fn rc4_hmac_md5_get_params;
#define rc4_hmac_md5_gettable_params cipher_generic_gettable_params
#define rc4_hmac_md5_einit cipher_generic_einit
#define rc4_hmac_md5_dinit cipher_generic_dinit
#define rc4_hmac_md5_update cipher_generic_stream_update
#define rc4_hmac_md5_final cipher_generic_stream_final
#define rc4_hmac_md5_cipher cipher_generic_cipher
static void *rc4_hmac_md5_newctx(void *provctx)
{
PROV_RC4_HMAC_MD5_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
cipher_generic_initkey(ctx, RC4_HMAC_MD5_KEY_BITS,
RC4_HMAC_MD5_BLOCK_BITS,
RC4_HMAC_MD5_IV_BITS,
RC4_HMAC_MD5_MODE, RC4_HMAC_MD5_FLAGS,
PROV_CIPHER_HW_rc4_hmac_md5(RC4_HMAC_MD5_KEY_BITS),
NULL);
return ctx;
}
static void rc4_hmac_md5_freectx(void *vctx)
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)vctx;
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static const OSSL_PARAM rc4_hmac_md5_known_gettable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
OSSL_PARAM_END
};
const OSSL_PARAM *rc4_hmac_md5_gettable_ctx_params(void)
{
return rc4_hmac_md5_known_gettable_ctx_params;
}
static int rc4_hmac_md5_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)vctx;
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.keylen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.ivlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
return 1;
}
static const OSSL_PARAM rc4_hmac_md5_known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0),
OSSL_PARAM_END
};
const OSSL_PARAM *rc4_hmac_md5_settable_ctx_params(void)
{
return rc4_hmac_md5_known_settable_ctx_params;
}
static int rc4_hmac_md5_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)vctx;
const OSSL_PARAM *p;
size_t sz;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL) {
if (!OSSL_PARAM_get_size_t(p, &sz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (ctx->base.keylen != sz) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL) {
if (!OSSL_PARAM_get_size_t(p, &sz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (ctx->base.ivlen != sz) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
sz = GET_HW(ctx)->tls_init(&ctx->base, p->data, p->data_size);
if (sz == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA);
return 0;
}
ctx->tls_aad_pad_sz = sz;
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
GET_HW(ctx)->init_mackey(&ctx->base, p->data, p->data_size);
}
return 1;
}
static int rc4_hmac_md5_get_params(OSSL_PARAM params[])
{
return cipher_generic_get_params(params, RC4_HMAC_MD5_MODE,
RC4_HMAC_MD5_FLAGS,
RC4_HMAC_MD5_KEY_BITS,
RC4_HMAC_MD5_BLOCK_BITS,
RC4_HMAC_MD5_IV_BITS);
}
const OSSL_DISPATCH rc4_hmac_md5_functions[] = {
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))rc4_hmac_md5_newctx },
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))rc4_hmac_md5_freectx },
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))rc4_hmac_md5_einit },
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))rc4_hmac_md5_dinit },
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))rc4_hmac_md5_update },
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))rc4_hmac_md5_final },
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))rc4_hmac_md5_cipher },
{ OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))rc4_hmac_md5_get_params },
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS,
(void (*)(void))rc4_hmac_md5_gettable_params },
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS,
(void (*)(void))rc4_hmac_md5_get_ctx_params },
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
(void (*)(void))rc4_hmac_md5_gettable_ctx_params },
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS,
(void (*)(void))rc4_hmac_md5_set_ctx_params },
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
(void (*)(void))rc4_hmac_md5_settable_ctx_params },
{ 0, NULL }
};
@@ -0,0 +1,33 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/rc4.h>
#include <openssl/md5.h>
#include "prov/ciphercommon.h"
typedef struct prov_rc4_hmac_md5_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
RC4_KEY ks;
} ks;
MD5_CTX head, tail, md;
size_t payload_length;
size_t tls_aad_pad_sz;
} PROV_RC4_HMAC_MD5_CTX;
typedef struct prov_cipher_hw_rc4_hmac_md5_st {
PROV_CIPHER_HW base; /* Must be first */
int (*tls_init)(PROV_CIPHER_CTX *ctx, unsigned char *aad, size_t aad_len);
void (*init_mackey)(PROV_CIPHER_CTX *ctx, const unsigned char *key,
size_t len);
} PROV_CIPHER_HW_RC4_HMAC_MD5;
const PROV_CIPHER_HW *PROV_CIPHER_HW_rc4_hmac_md5(size_t keybits);
@@ -0,0 +1,231 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* RC4_HMAC_MD5 cipher implementation */
/*
* RC4 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_rc4_hmac_md5.h"
#define NO_PAYLOAD_LENGTH ((size_t)-1)
#if defined(RC4_ASM) \
&& defined(MD5_ASM) \
&& (defined(__x86_64) \
|| defined(__x86_64__) \
|| defined(_M_AMD64) \
|| defined(_M_X64))
# define STITCHED_CALL
# define MOD 32 /* 32 is $MOD from rc4_md5-x86_64.pl */
#else
# define rc4_off 0
# define md5_off 0
#endif
static int cipher_hw_rc4_hmac_md5_initkey(PROV_CIPHER_CTX *bctx,
const uint8_t *key, size_t keylen)
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)bctx;
RC4_set_key(&ctx->ks.ks, keylen, key);
MD5_Init(&ctx->head); /* handy when benchmarking */
ctx->tail = ctx->head;
ctx->md = ctx->head;
ctx->payload_length = NO_PAYLOAD_LENGTH;
return 1;
}
static int cipher_hw_rc4_hmac_md5_cipher(PROV_CIPHER_CTX *bctx,
unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)bctx;
RC4_KEY *ks = &ctx->ks.ks;
#if defined(STITCHED_CALL)
size_t rc4_off = MOD - 1 - (ks->x & (MOD - 1));
size_t md5_off = MD5_CBLOCK - ctx->md.num, blocks;
unsigned int l;
#endif
size_t plen = ctx->payload_length;
if (plen != NO_PAYLOAD_LENGTH && len != (plen + MD5_DIGEST_LENGTH))
return 0;
if (ctx->base.enc) {
if (plen == NO_PAYLOAD_LENGTH)
plen = len;
#if defined(STITCHED_CALL)
/* cipher has to "fall behind" */
if (rc4_off > md5_off)
md5_off += MD5_CBLOCK;
if (plen > md5_off
&& (blocks = (plen - md5_off) / MD5_CBLOCK)
&& (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
MD5_Update(&ctx->md, in, md5_off);
RC4(ks, rc4_off, in, out);
rc4_md5_enc(ks, in + rc4_off, out + rc4_off,
&ctx->md, in + md5_off, blocks);
blocks *= MD5_CBLOCK;
rc4_off += blocks;
md5_off += blocks;
ctx->md.Nh += blocks >> 29;
ctx->md.Nl += blocks <<= 3;
if (ctx->md.Nl < (unsigned int)blocks)
ctx->md.Nh++;
} else {
rc4_off = 0;
md5_off = 0;
}
#endif
MD5_Update(&ctx->md, in + md5_off, plen - md5_off);
if (plen != len) { /* "TLS" mode of operation */
if (in != out)
memcpy(out + rc4_off, in + rc4_off, plen - rc4_off);
/* calculate HMAC and append it to payload */
MD5_Final(out + plen, &ctx->md);
ctx->md = ctx->tail;
MD5_Update(&ctx->md, out + plen, MD5_DIGEST_LENGTH);
MD5_Final(out + plen, &ctx->md);
/* encrypt HMAC at once */
RC4(ks, len - rc4_off, out + rc4_off, out + rc4_off);
} else {
RC4(ks, len - rc4_off, in + rc4_off, out + rc4_off);
}
} else {
unsigned char mac[MD5_DIGEST_LENGTH];
#if defined(STITCHED_CALL)
/* digest has to "fall behind" */
if (md5_off > rc4_off)
rc4_off += 2 * MD5_CBLOCK;
else
rc4_off += MD5_CBLOCK;
if (len > rc4_off
&& (blocks = (len - rc4_off) / MD5_CBLOCK)
&& (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
RC4(ks, rc4_off, in, out);
MD5_Update(&ctx->md, out, md5_off);
rc4_md5_enc(ks, in + rc4_off, out + rc4_off,
&ctx->md, out + md5_off, blocks);
blocks *= MD5_CBLOCK;
rc4_off += blocks;
md5_off += blocks;
l = (ctx->md.Nl + (blocks << 3)) & 0xffffffffU;
if (l < ctx->md.Nl)
ctx->md.Nh++;
ctx->md.Nl = l;
ctx->md.Nh += blocks >> 29;
} else {
md5_off = 0;
rc4_off = 0;
}
#endif
/* decrypt HMAC at once */
RC4(ks, len - rc4_off, in + rc4_off, out + rc4_off);
if (plen != NO_PAYLOAD_LENGTH) {
/* "TLS" mode of operation */
MD5_Update(&ctx->md, out + md5_off, plen - md5_off);
/* calculate HMAC and verify it */
MD5_Final(mac, &ctx->md);
ctx->md = ctx->tail;
MD5_Update(&ctx->md, mac, MD5_DIGEST_LENGTH);
MD5_Final(mac, &ctx->md);
if (CRYPTO_memcmp(out + plen, mac, MD5_DIGEST_LENGTH))
return 0;
} else {
MD5_Update(&ctx->md, out + md5_off, len - md5_off);
}
}
ctx->payload_length = NO_PAYLOAD_LENGTH;
return 1;
}
static int cipher_hw_rc4_hmac_md5_tls_init(PROV_CIPHER_CTX *bctx,
unsigned char *aad, size_t aad_len)
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)bctx;
unsigned int len;
if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
return 0;
len = aad[aad_len - 2] << 8 | aad[aad_len - 1];
if (!bctx->enc) {
if (len < MD5_DIGEST_LENGTH)
return 0;
len -= MD5_DIGEST_LENGTH;
aad[aad_len - 2] = len >> 8;
aad[aad_len - 1] = len;
}
ctx->payload_length = len;
ctx->md = ctx->head;
MD5_Update(&ctx->md, aad, aad_len);
return MD5_DIGEST_LENGTH;
}
static void cipher_hw_rc4_hmac_md5_init_mackey(PROV_CIPHER_CTX *bctx,
const unsigned char *key,
size_t len)
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)bctx;
unsigned int i;
unsigned char hmac_key[64];
memset(hmac_key, 0, sizeof(hmac_key));
if (len > (int)sizeof(hmac_key)) {
MD5_Init(&ctx->head);
MD5_Update(&ctx->head, key, len);
MD5_Final(hmac_key, &ctx->head);
} else {
memcpy(hmac_key, key, len);
}
for (i = 0; i < sizeof(hmac_key); i++)
hmac_key[i] ^= 0x36; /* ipad */
MD5_Init(&ctx->head);
MD5_Update(&ctx->head, hmac_key, sizeof(hmac_key));
for (i = 0; i < sizeof(hmac_key); i++)
hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */
MD5_Init(&ctx->tail);
MD5_Update(&ctx->tail, hmac_key, sizeof(hmac_key));
OPENSSL_cleanse(hmac_key, sizeof(hmac_key));
}
static const PROV_CIPHER_HW_RC4_HMAC_MD5 rc4_hmac_md5_hw = {
{
cipher_hw_rc4_hmac_md5_initkey,
cipher_hw_rc4_hmac_md5_cipher
},
cipher_hw_rc4_hmac_md5_tls_init,
cipher_hw_rc4_hmac_md5_init_mackey
};
const PROV_CIPHER_HW *PROV_CIPHER_HW_rc4_hmac_md5(size_t keybits)
{
return (PROV_CIPHER_HW *)&rc4_hmac_md5_hw;
}
@@ -7,6 +7,12 @@
* https://www.openssl.org/source/license.html
*/
/*
* RC4 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_rc4.h"
static int cipher_hw_rc4_initkey(PROV_CIPHER_CTX *ctx,
@@ -9,6 +9,12 @@
/* Dispatch functions for RC5 cipher modes ecb, cbc, ofb, cfb */
/*
* RC5 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_rc5.h"
#include "prov/implementations.h"
#include "prov/providercommonerr.h"
@@ -44,7 +50,7 @@ static int rc5_set_ctx_params(void *vctx, const OSSL_PARAM params[])
PROV_RC5_CTX *ctx = (PROV_RC5_CTX *)vctx;
const OSSL_PARAM *p;
if (!cipher_generic_set_ctx_params(vctx, params))
if (!cipher_var_keylen_set_ctx_params(vctx, params))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_ROUNDS);
@@ -71,6 +77,7 @@ CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(rc5)
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(rc5)
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(rc5)
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_ROUNDS, NULL),
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(rc5)
@@ -7,6 +7,12 @@
* https://www.openssl.org/source/license.html
*/
/*
* RC5 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_rc5.h"
static int cipher_hw_rc5_initkey(PROV_CIPHER_CTX *ctx,
@@ -9,6 +9,12 @@
/* Dispatch functions for Seed cipher modes ecb, cbc, ofb, cfb */
/*
* SEED low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include "cipher_seed.h"
#include "prov/implementations.h"
@@ -7,6 +7,12 @@
* https://www.openssl.org/source/license.html
*/
/*
* SEED low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include "cipher_seed.h"
static int cipher_hw_seed_initkey(PROV_CIPHER_CTX *ctx,
@@ -31,7 +31,7 @@ static void *sm4_dupctx(void *ctx)
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
*ret = *in;
in->base.hw->copyctx(&ret->base, &in->base);
return ret;
}
@@ -26,10 +26,13 @@ static int cipher_hw_sm4_initkey(PROV_CIPHER_CTX *ctx,
return 1;
}
IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_sm4_copyctx, PROV_SM4_CTX)
# define PROV_CIPHER_HW_sm4_mode(mode) \
static const PROV_CIPHER_HW sm4_##mode = { \
cipher_hw_sm4_initkey, \
cipher_hw_chunked_##mode \
cipher_hw_chunked_##mode, \
cipher_hw_sm4_copyctx \
}; \
const PROV_CIPHER_HW *PROV_CIPHER_HW_sm4_##mode(size_t keybits) \
{ \
@@ -9,6 +9,7 @@
#include <openssl/des.h>
#include <openssl/core_numbers.h>
#include "crypto/des_platform.h"
#define DES_BLOCK_SIZE 8
#define TDES_IVLEN 8
@@ -14,7 +14,7 @@
#include "prov/implementations.h"
#include "prov/providercommonerr.h"
/* TODO (3.0) Figure out what flags are requred */
/* TODO (3.0) Figure out what flags are required */
#define TDES_WRAP_FLAGS (EVP_CIPH_WRAP_MODE | EVP_CIPH_CUSTOM_IV)
@@ -145,6 +145,8 @@ static int tdes_wrap_update(void *vctx, unsigned char *out, size_t *outl,
size_t inl)
{
*outl = 0;
if (inl == 0)
return 1;
if (outsize < inl) {
PROVerr(0, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
@@ -11,7 +11,7 @@
* Generic dispatch table functions for ciphers.
*/
#include "cipher_local.h"
#include "ciphercommon_local.h"
#include "prov/provider_ctx.h"
#include "prov/providercommonerr.h"
@@ -71,6 +71,34 @@ CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(cipher_generic)
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_generic)
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_generic)
/*
* Variable key length cipher functions for OSSL_PARAM settables
*/
int cipher_var_keylen_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
const OSSL_PARAM *p;
if (!cipher_generic_set_ctx_params(vctx, params))
return 0;
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 0;
}
ctx->keylen = keylen;
}
return 1;
}
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_var_keylen)
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_var_keylen)
/*-
* AEAD cipher functions for OSSL_PARAM gettables and settables
*/
@@ -81,6 +109,7 @@ static const OSSL_PARAM cipher_aead_known_gettable_ctx_params[] = {
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN, NULL, 0),
OSSL_PARAM_END
};
const OSSL_PARAM *cipher_aead_gettable_ctx_params(void)
@@ -89,11 +118,11 @@ const OSSL_PARAM *cipher_aead_gettable_ctx_params(void)
}
static const OSSL_PARAM cipher_aead_known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV, NULL, 0),
OSSL_PARAM_END
};
const OSSL_PARAM *cipher_aead_settable_ctx_params(void)
@@ -180,6 +209,8 @@ int cipher_generic_block_update(void *vctx, unsigned char *out, size_t *outl,
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
}
if (nextblocks > 0) {
if (!ctx->hw->cipher(ctx, out, in, nextblocks)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
@@ -262,6 +293,11 @@ int cipher_generic_stream_update(void *vctx, unsigned char *out, size_t *outl,
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
if (inl == 0) {
*outl = 0;
return 1;
}
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
@@ -362,16 +398,6 @@ int cipher_generic_set_ctx_params(void *vctx, const OSSL_PARAM params[])
}
ctx->num = num;
}
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 0;
}
ctx->keylen = keylen;
}
return 1;
}
@@ -8,7 +8,7 @@
*/
#include <assert.h>
#include "cipher_local.h"
#include "ciphercommon_local.h"
#include "prov/providercommonerr.h"
/*
@@ -10,7 +10,7 @@
/* Dispatch functions for ccm mode */
#include "prov/ciphercommon.h"
#include "prov/cipher_ccm.h"
#include "prov/ciphercommon_ccm.h"
#include "prov/providercommonerr.h"
static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out,
@@ -8,7 +8,7 @@
*/
#include "prov/ciphercommon.h"
#include "prov/cipher_ccm.h"
#include "prov/ciphercommon_ccm.h"
int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce,
size_t nlen, size_t mlen)
@@ -10,7 +10,7 @@
/* Dispatch functions for gcm mode */
#include "prov/ciphercommon.h"
#include "prov/cipher_gcm.h"
#include "prov/ciphercommon_gcm.h"
#include "prov/providercommonerr.h"
#include "crypto/rand.h"
#include "prov/provider_ctx.h"
@@ -77,6 +77,54 @@ int gcm_dinit(void *vctx, const unsigned char *key, size_t keylen,
return gcm_init(vctx, key, keylen, iv, ivlen, 0);
}
/* increment counter (64-bit int) by 1 */
static void ctr64_inc(unsigned char *counter)
{
int n = 8;
unsigned char c;
do {
--n;
c = counter[n];
++c;
counter[n] = c;
if (c > 0)
return;
} while (n > 0);
}
static int getivgen(PROV_GCM_CTX *ctx, unsigned char *out, size_t olen)
{
if (!ctx->iv_gen
|| !ctx->key_set
|| !ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
return 0;
if (olen == 0 || olen > ctx->ivlen)
olen = ctx->ivlen;
memcpy(out, ctx->iv + ctx->ivlen - olen, olen);
/*
* Invocation field will be at least 8 bytes in size and so no need
* to check wrap around or increment more than last 8 bytes.
*/
ctr64_inc(ctx->iv + ctx->ivlen - 8);
ctx->iv_state = IV_STATE_COPIED;
return 1;
}
static int setivinv(PROV_GCM_CTX *ctx, unsigned char *in, size_t inl)
{
if (!ctx->iv_gen
|| !ctx->key_set
|| ctx->enc)
return 0;
memcpy(ctx->iv + ctx->ivlen - inl, in, inl);
if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
return 0;
ctx->iv_state = IV_STATE_COPIED;
return 1;
}
int gcm_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
@@ -138,7 +186,13 @@ int gcm_get_ctx_params(void *vctx, OSSL_PARAM params[])
return 0;
}
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN);
if (p != NULL) {
if (p->data == NULL
|| p->data_type != OSSL_PARAM_OCTET_STRING
|| !getivgen(ctx, p->data, p->data_size))
return 0;
}
return 1;
}
@@ -201,26 +255,15 @@ int gcm_set_ctx_params(void *vctx, const OSSL_PARAM params[])
return 0;
}
}
/*
* TODO(3.0) Temporary solution to address fuzz test crash, which will be
* reworked once the discussion in PR #9510 is resolved. i.e- We need a
* general solution for handling missing parameters inside set_params and
* get_params methods.
*/
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV);
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 0;
}
/* The key length can not be modified for gcm mode */
if (keylen != ctx->keylen)
if (p->data == NULL
|| p->data_type != OSSL_PARAM_OCTET_STRING
|| !setivinv(ctx, p->data, p->data_size))
return 0;
}
return 1;
}
@@ -229,6 +272,11 @@ int gcm_stream_update(void *vctx, unsigned char *out, size_t *outl,
{
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
if (inl == 0) {
*outl = 0;
return 1;
}
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return -1;
@@ -411,22 +459,6 @@ static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv,
return 1;
}
/* increment counter (64-bit int) by 1 */
static void ctr64_inc(unsigned char *counter)
{
int n = 8;
unsigned char c;
do {
--n;
c = counter[n];
++c;
counter[n] = c;
if (c > 0)
return;
} while (n > 0);
}
/*
* Handle TLS GCM packet format. This consists of the last portion of the IV
* followed by the payload and finally the tag. On encrypt generate IV,
@@ -459,29 +491,17 @@ static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen,
goto err;
}
if (ctx->iv_gen == 0)
goto err;
/*
* Set IV from start of buffer or generate IV and write to start of
* buffer.
*/
if (ctx->enc) {
if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
if (!getivgen(ctx, out, arg))
goto err;
if (arg > ctx->ivlen)
arg = ctx->ivlen;
memcpy(out, ctx->iv + ctx->ivlen - arg, arg);
/*
* Invocation field will be at least 8 bytes in size and so no need
* to check wrap around or increment more than last 8 bytes.
*/
ctr64_inc(ctx->iv + ctx->ivlen - 8);
} else {
memcpy(ctx->iv + ctx->ivlen - arg, out, arg);
if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
if (!setivinv(ctx, out, arg))
goto err;
}
ctx->iv_state = IV_STATE_COPIED;
/* Fix buffer and length to point to payload */
in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
@@ -507,3 +527,4 @@ err:
*padlen = plen;
return rv;
}
@@ -0,0 +1,68 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "prov/ciphercommon.h"
#include "prov/ciphercommon_gcm.h"
int gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen)
{
CRYPTO_gcm128_setiv(&ctx->gcm, iv, ivlen);
return 1;
}
int gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad, size_t aad_len)
{
return CRYPTO_gcm128_aad(&ctx->gcm, aad, aad_len) == 0;
}
int gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
size_t len, unsigned char *out)
{
if (ctx->enc) {
if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len))
return 0;
} else {
if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len))
return 0;
}
return 1;
}
int gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag)
{
if (ctx->enc) {
CRYPTO_gcm128_tag(&ctx->gcm, tag, GCM_TAG_MAX_SIZE);
ctx->taglen = GCM_TAG_MAX_SIZE;
} else {
if (CRYPTO_gcm128_finish(&ctx->gcm, tag, ctx->taglen) != 0)
return 0;
}
return 1;
}
int gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len,
const unsigned char *in, size_t in_len,
unsigned char *out, unsigned char *tag, size_t tag_len)
{
int ret = 0;
/* Use saved AAD */
if (!ctx->hw->aadupdate(ctx, aad, aad_len))
goto err;
if (!ctx->hw->cipherupdate(ctx, in, in_len, out))
goto err;
ctx->taglen = GCM_TAG_MAX_SIZE;
if (!ctx->hw->cipherfinal(ctx, tag))
goto err;
ret = 1;
err:
return ret;
}
@@ -34,8 +34,13 @@ int cipher_hw_generic_ecb(PROV_CIPHER_CTX *dat, unsigned char *out,
if (len < bl)
return 1;
for (i = 0, len -= bl; i <= len; i += bl)
(*dat->block) (in + i, out + i, dat->ks);
if (dat->stream.ecb) {
(*dat->stream.ecb) (in, out, len, dat->ks, dat->enc);
}
else {
for (i = 0, len -= bl; i <= len; i += bl)
(*dat->block) (in + i, out + i, dat->ks);
}
return 1;
}

Some files were not shown because too many files have changed in this diff Show More