Latest update.
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
# This source is common for all digests in all our providers.
|
||||
SOURCE[../../libcommon.a]=digest_common.c
|
||||
@@ -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
|
||||
@@ -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),
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -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)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(¶ms[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;
|
||||
}
|
||||
@@ -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 }
|
||||
};
|
||||
@@ -1 +1,2 @@
|
||||
SUBDIRS=digests ciphers macs kdfs exchange keymgmt signature
|
||||
SUBDIRS=digests ciphers macs kdfs exchange keymgmt signature asymciphers \
|
||||
serializers
|
||||
@@ -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;
|
||||
|
||||
+38
-12
@@ -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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "cipher_local.h"
|
||||
#include "ciphercommon_local.h"
|
||||
#include "prov/providercommonerr.h"
|
||||
|
||||
/*
|
||||
+1
-1
@@ -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,
|
||||
+1
-1
@@ -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)
|
||||
+69
-48
@@ -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;
|
||||
}
|
||||
+7
-2
@@ -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
Reference in New Issue
Block a user