Latest update.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
SUBDIRS=digests ciphers
|
||||
SUBDIRS=digests ciphers macs kdfs exchange keymgmt signature
|
||||
$COMMON=provider_util.c
|
||||
|
||||
SOURCE[../../libcrypto]=\
|
||||
provider_err.c provlib.c
|
||||
SOURCE[../../libcrypto]=$COMMON provider_err.c provlib.c
|
||||
SOURCE[../fips]=$COMMON
|
||||
@@ -1,485 +0,0 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/params.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/provider_algs.h"
|
||||
#include "ciphers_locl.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
static OSSL_OP_cipher_encrypt_init_fn aes_einit;
|
||||
static OSSL_OP_cipher_decrypt_init_fn aes_dinit;
|
||||
static OSSL_OP_cipher_update_fn aes_block_update;
|
||||
static OSSL_OP_cipher_final_fn aes_block_final;
|
||||
static OSSL_OP_cipher_update_fn aes_stream_update;
|
||||
static OSSL_OP_cipher_final_fn aes_stream_final;
|
||||
static OSSL_OP_cipher_cipher_fn aes_cipher;
|
||||
static OSSL_OP_cipher_freectx_fn aes_freectx;
|
||||
static OSSL_OP_cipher_dupctx_fn aes_dupctx;
|
||||
static OSSL_OP_cipher_ctx_get_params_fn aes_ctx_get_params;
|
||||
static OSSL_OP_cipher_ctx_set_params_fn aes_ctx_set_params;
|
||||
|
||||
static int PROV_AES_KEY_generic_init(PROV_AES_KEY *ctx,
|
||||
const unsigned char *iv,
|
||||
size_t ivlen,
|
||||
int enc)
|
||||
{
|
||||
if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) {
|
||||
if (ivlen != AES_BLOCK_SIZE) {
|
||||
PROVerr(PROV_F_PROV_AES_KEY_GENERIC_INIT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
|
||||
}
|
||||
ctx->enc = enc;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_einit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
|
||||
if (!PROV_AES_KEY_generic_init(ctx, iv, ivlen, 1)) {
|
||||
/* PROVerr already called */
|
||||
return 0;
|
||||
}
|
||||
if (key != NULL) {
|
||||
if (keylen != ctx->keylen) {
|
||||
PROVerr(PROV_F_AES_EINIT, PROV_R_INVALID_KEYLEN);
|
||||
return 0;
|
||||
}
|
||||
return ctx->ciph->init(ctx, key, ctx->keylen);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_dinit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
|
||||
if (!PROV_AES_KEY_generic_init(ctx, iv, ivlen, 0)) {
|
||||
/* PROVerr already called */
|
||||
return 0;
|
||||
}
|
||||
if (key != NULL) {
|
||||
if (keylen != ctx->keylen) {
|
||||
PROVerr(PROV_F_AES_DINIT, PROV_R_INVALID_KEYLEN);
|
||||
return 0;
|
||||
}
|
||||
return ctx->ciph->init(ctx, key, ctx->keylen);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_block_update(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize, const unsigned char *in, size_t inl)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE, &in,
|
||||
&inl);
|
||||
size_t outlint = 0;
|
||||
|
||||
/*
|
||||
* If we're decrypting and we end an update on a block boundary we hold
|
||||
* the last block back in case this is the last update call and the last
|
||||
* block is padded.
|
||||
*/
|
||||
if (ctx->bufsz == AES_BLOCK_SIZE
|
||||
&& (ctx->enc || inl > 0 || !ctx->pad)) {
|
||||
if (outsize < AES_BLOCK_SIZE) {
|
||||
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (!ctx->ciph->cipher(ctx, out, ctx->buf, AES_BLOCK_SIZE)) {
|
||||
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
ctx->bufsz = 0;
|
||||
outlint = AES_BLOCK_SIZE;
|
||||
out += AES_BLOCK_SIZE;
|
||||
}
|
||||
if (nextblocks > 0) {
|
||||
if (!ctx->enc && ctx->pad && nextblocks == inl) {
|
||||
if (!ossl_assert(inl >= AES_BLOCK_SIZE)) {
|
||||
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
nextblocks -= AES_BLOCK_SIZE;
|
||||
}
|
||||
outlint += nextblocks;
|
||||
if (outsize < outlint) {
|
||||
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (!ctx->ciph->cipher(ctx, out, in, nextblocks)) {
|
||||
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
in += nextblocks;
|
||||
inl -= nextblocks;
|
||||
}
|
||||
if (!trailingdata(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE, &in, &inl)) {
|
||||
/* PROVerr already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
*outl = outlint;
|
||||
return inl == 0;
|
||||
}
|
||||
|
||||
static int aes_block_final(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
|
||||
if (ctx->enc) {
|
||||
if (ctx->pad) {
|
||||
padblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE);
|
||||
} else if (ctx->bufsz == 0) {
|
||||
*outl = 0;
|
||||
return 1;
|
||||
} else if (ctx->bufsz != AES_BLOCK_SIZE) {
|
||||
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (outsize < AES_BLOCK_SIZE) {
|
||||
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (!ctx->ciph->cipher(ctx, out, ctx->buf, AES_BLOCK_SIZE)) {
|
||||
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
ctx->bufsz = 0;
|
||||
*outl = AES_BLOCK_SIZE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decrypting */
|
||||
if (ctx->bufsz != AES_BLOCK_SIZE) {
|
||||
if (ctx->bufsz == 0 && !ctx->pad) {
|
||||
*outl = 0;
|
||||
return 1;
|
||||
}
|
||||
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ctx->ciph->cipher(ctx, ctx->buf, ctx->buf, AES_BLOCK_SIZE)) {
|
||||
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->pad && !unpadblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE)) {
|
||||
/* PROVerr already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (outsize < ctx->bufsz) {
|
||||
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
memcpy(out, ctx->buf, ctx->bufsz);
|
||||
*outl = ctx->bufsz;
|
||||
ctx->bufsz = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_stream_update(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize, const unsigned char *in,
|
||||
size_t inl)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
|
||||
if (outsize < inl) {
|
||||
PROVerr(PROV_F_AES_STREAM_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ctx->ciph->cipher(ctx, out, in, inl)) {
|
||||
PROVerr(PROV_F_AES_STREAM_UPDATE, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*outl = inl;
|
||||
return 1;
|
||||
}
|
||||
static int aes_stream_final(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
*outl = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_cipher(void *vctx,
|
||||
unsigned char *out, size_t *outl, size_t outsize,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
|
||||
if (outsize < inl) {
|
||||
PROVerr(PROV_F_AES_CIPHER, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ctx->ciph->cipher(ctx, out, in, inl)) {
|
||||
PROVerr(PROV_F_AES_CIPHER, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*outl = inl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IMPLEMENT_cipher(lcmode, UCMODE, flags, kbits, blkbits, ivbits) \
|
||||
static OSSL_OP_cipher_get_params_fn aes_##kbits##_##lcmode##_get_params; \
|
||||
static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
|
||||
{ \
|
||||
OSSL_PARAM *p; \
|
||||
\
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE); \
|
||||
if (p != NULL) { \
|
||||
if (!OSSL_PARAM_set_int(p, EVP_CIPH_##UCMODE##_MODE)) \
|
||||
return 0; \
|
||||
} \
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_FLAGS); \
|
||||
if (p != NULL) { \
|
||||
if (!OSSL_PARAM_set_ulong(p, (flags))) \
|
||||
return 0; \
|
||||
} \
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); \
|
||||
if (p != NULL) { \
|
||||
if (!OSSL_PARAM_set_int(p, (kbits) / 8)) \
|
||||
return 0; \
|
||||
} \
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE); \
|
||||
if (p != NULL) { \
|
||||
if (!OSSL_PARAM_set_int(p, (blkbits) / 8)) \
|
||||
return 0; \
|
||||
} \
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); \
|
||||
if (p != NULL) { \
|
||||
if (!OSSL_PARAM_set_int(p, (ivbits) / 8)) \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
return 1; \
|
||||
} \
|
||||
static OSSL_OP_cipher_newctx_fn aes_##kbits##_##lcmode##_newctx; \
|
||||
static void *aes_##kbits##_##lcmode##_newctx(void *provctx) \
|
||||
{ \
|
||||
PROV_AES_KEY *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
|
||||
\
|
||||
ctx->pad = 1; \
|
||||
ctx->keylen = ((kbits) / 8); \
|
||||
ctx->ciph = PROV_AES_CIPHER_##lcmode(ctx->keylen); \
|
||||
ctx->mode = EVP_CIPH_##UCMODE##_MODE; \
|
||||
return ctx; \
|
||||
}
|
||||
|
||||
/* ECB */
|
||||
IMPLEMENT_cipher(ecb, ECB, 0, 256, 128, 0)
|
||||
IMPLEMENT_cipher(ecb, ECB, 0, 192, 128, 0)
|
||||
IMPLEMENT_cipher(ecb, ECB, 0, 128, 128, 0)
|
||||
|
||||
/* CBC */
|
||||
IMPLEMENT_cipher(cbc, CBC, 0, 256, 128, 128)
|
||||
IMPLEMENT_cipher(cbc, CBC, 0, 192, 128, 128)
|
||||
IMPLEMENT_cipher(cbc, CBC, 0, 128, 128, 128)
|
||||
|
||||
/* OFB */
|
||||
IMPLEMENT_cipher(ofb, OFB, 0, 256, 8, 128)
|
||||
IMPLEMENT_cipher(ofb, OFB, 0, 192, 8, 128)
|
||||
IMPLEMENT_cipher(ofb, OFB, 0, 128, 8, 128)
|
||||
|
||||
/* CFB */
|
||||
IMPLEMENT_cipher(cfb, CFB, 0, 256, 8, 128)
|
||||
IMPLEMENT_cipher(cfb, CFB, 0, 192, 8, 128)
|
||||
IMPLEMENT_cipher(cfb, CFB, 0, 128, 8, 128)
|
||||
IMPLEMENT_cipher(cfb1, CFB, 0, 256, 8, 128)
|
||||
IMPLEMENT_cipher(cfb1, CFB, 0, 192, 8, 128)
|
||||
IMPLEMENT_cipher(cfb1, CFB, 0, 128, 8, 128)
|
||||
IMPLEMENT_cipher(cfb8, CFB, 0, 256, 8, 128)
|
||||
IMPLEMENT_cipher(cfb8, CFB, 0, 192, 8, 128)
|
||||
IMPLEMENT_cipher(cfb8, CFB, 0, 128, 8, 128)
|
||||
|
||||
/* CTR */
|
||||
IMPLEMENT_cipher(ctr, CTR, 0, 256, 8, 128)
|
||||
IMPLEMENT_cipher(ctr, CTR, 0, 192, 8, 128)
|
||||
IMPLEMENT_cipher(ctr, CTR, 0, 128, 8, 128)
|
||||
|
||||
static void aes_freectx(void *vctx)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void *aes_dupctx(void *ctx)
|
||||
{
|
||||
PROV_AES_KEY *in = (PROV_AES_KEY *)ctx;
|
||||
PROV_AES_KEY *ret = OPENSSL_malloc(sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
PROVerr(PROV_F_AES_DUPCTX, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
*ret = *in;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aes_ctx_get_params(void *vctx, OSSL_PARAM params[])
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING);
|
||||
if (p != NULL && !OSSL_PARAM_set_int(p, ctx->pad)) {
|
||||
PROVerr(PROV_F_AES_CTX_GET_PARAMS, PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
|
||||
if (p != NULL
|
||||
&& !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, AES_BLOCK_SIZE)
|
||||
&& !OSSL_PARAM_set_octet_string(p, &ctx->iv, AES_BLOCK_SIZE)) {
|
||||
PROVerr(PROV_F_AES_CTX_GET_PARAMS,
|
||||
PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_NUM);
|
||||
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->num)) {
|
||||
PROVerr(PROV_F_AES_CTX_GET_PARAMS,
|
||||
PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
|
||||
if (p != NULL && !OSSL_PARAM_set_int(p, ctx->keylen)) {
|
||||
PROVerr(PROV_F_AES_CTX_GET_PARAMS,
|
||||
PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_ctx_set_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_PADDING);
|
||||
if (p != NULL) {
|
||||
int pad;
|
||||
|
||||
if (!OSSL_PARAM_get_int(p, &pad)) {
|
||||
PROVerr(PROV_F_AES_CTX_SET_PARAMS,
|
||||
PROV_R_FAILED_TO_GET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
ctx->pad = pad ? 1 : 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_NUM);
|
||||
if (p != NULL) {
|
||||
int num;
|
||||
|
||||
if (!OSSL_PARAM_get_int(p, &num)) {
|
||||
PROVerr(PROV_F_AES_CTX_SET_PARAMS,
|
||||
PROV_R_FAILED_TO_GET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
ctx->num = num;
|
||||
}
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
|
||||
if (p != NULL) {
|
||||
int keylen;
|
||||
|
||||
if (!OSSL_PARAM_get_int(p, &keylen)) {
|
||||
PROVerr(PROV_F_AES_CTX_SET_PARAMS,
|
||||
PROV_R_FAILED_TO_GET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
ctx->keylen = keylen;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IMPLEMENT_block_funcs(mode, kbits) \
|
||||
const OSSL_DISPATCH aes##kbits##mode##_functions[] = { \
|
||||
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##kbits##_##mode##_newctx }, \
|
||||
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_einit }, \
|
||||
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_dinit }, \
|
||||
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_block_update }, \
|
||||
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_block_final }, \
|
||||
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_cipher }, \
|
||||
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_freectx }, \
|
||||
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_dupctx }, \
|
||||
{ OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))aes_##kbits##_##mode##_get_params }, \
|
||||
{ OSSL_FUNC_CIPHER_CTX_GET_PARAMS, (void (*)(void))aes_ctx_get_params }, \
|
||||
{ OSSL_FUNC_CIPHER_CTX_SET_PARAMS, (void (*)(void))aes_ctx_set_params }, \
|
||||
{ 0, NULL } \
|
||||
};
|
||||
|
||||
#define IMPLEMENT_stream_funcs(mode, kbits) \
|
||||
const OSSL_DISPATCH aes##kbits##mode##_functions[] = { \
|
||||
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##kbits##_##mode##_newctx }, \
|
||||
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_einit }, \
|
||||
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_dinit }, \
|
||||
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_stream_update }, \
|
||||
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_stream_final }, \
|
||||
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_cipher }, \
|
||||
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_freectx }, \
|
||||
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_dupctx }, \
|
||||
{ OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))aes_##kbits##_##mode##_get_params }, \
|
||||
{ OSSL_FUNC_CIPHER_CTX_GET_PARAMS, (void (*)(void))aes_ctx_get_params }, \
|
||||
{ OSSL_FUNC_CIPHER_CTX_SET_PARAMS, (void (*)(void))aes_ctx_set_params }, \
|
||||
{ 0, NULL } \
|
||||
};
|
||||
|
||||
/* ECB */
|
||||
IMPLEMENT_block_funcs(ecb, 256)
|
||||
IMPLEMENT_block_funcs(ecb, 192)
|
||||
IMPLEMENT_block_funcs(ecb, 128)
|
||||
|
||||
/* CBC */
|
||||
IMPLEMENT_block_funcs(cbc, 256)
|
||||
IMPLEMENT_block_funcs(cbc, 192)
|
||||
IMPLEMENT_block_funcs(cbc, 128)
|
||||
|
||||
/* OFB */
|
||||
IMPLEMENT_stream_funcs(ofb, 256)
|
||||
IMPLEMENT_stream_funcs(ofb, 192)
|
||||
IMPLEMENT_stream_funcs(ofb, 128)
|
||||
|
||||
/* CFB */
|
||||
IMPLEMENT_stream_funcs(cfb, 256)
|
||||
IMPLEMENT_stream_funcs(cfb, 192)
|
||||
IMPLEMENT_stream_funcs(cfb, 128)
|
||||
IMPLEMENT_stream_funcs(cfb1, 256)
|
||||
IMPLEMENT_stream_funcs(cfb1, 192)
|
||||
IMPLEMENT_stream_funcs(cfb1, 128)
|
||||
IMPLEMENT_stream_funcs(cfb8, 256)
|
||||
IMPLEMENT_stream_funcs(cfb8, 192)
|
||||
IMPLEMENT_stream_funcs(cfb8, 128)
|
||||
|
||||
/* CTR */
|
||||
IMPLEMENT_stream_funcs(ctr, 256)
|
||||
IMPLEMENT_stream_funcs(ctr, 192)
|
||||
IMPLEMENT_stream_funcs(ctr, 128)
|
||||
@@ -1,866 +0,0 @@
|
||||
/*
|
||||
* Copyright 2001-2018 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/opensslconf.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <openssl/aes.h>
|
||||
#include "internal/evp_int.h"
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/cmac.h>
|
||||
#include "ciphers_locl.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
#define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4))
|
||||
|
||||
#ifdef VPAES_ASM
|
||||
int vpaes_set_encrypt_key(const unsigned char *userKey, int bits,
|
||||
AES_KEY *key);
|
||||
int vpaes_set_decrypt_key(const unsigned char *userKey, int bits,
|
||||
AES_KEY *key);
|
||||
|
||||
void vpaes_encrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
void vpaes_decrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
|
||||
void vpaes_cbc_encrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
size_t length,
|
||||
const AES_KEY *key, unsigned char *ivec, int enc);
|
||||
#endif
|
||||
#ifdef BSAES_ASM
|
||||
void bsaes_cbc_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t length, const AES_KEY *key,
|
||||
unsigned char ivec[16], int enc);
|
||||
void bsaes_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
const unsigned char ivec[16]);
|
||||
#endif
|
||||
#ifdef AES_CTR_ASM
|
||||
void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t blocks, const AES_KEY *key,
|
||||
const unsigned char ivec[AES_BLOCK_SIZE]);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC))
|
||||
# include "ppc_arch.h"
|
||||
# ifdef VPAES_ASM
|
||||
# define VPAES_CAPABLE (OPENSSL_ppccap_P & PPC_ALTIVEC)
|
||||
# endif
|
||||
# define HWAES_CAPABLE (OPENSSL_ppccap_P & PPC_CRYPTO207)
|
||||
# define HWAES_set_encrypt_key aes_p8_set_encrypt_key
|
||||
# define HWAES_set_decrypt_key aes_p8_set_decrypt_key
|
||||
# define HWAES_encrypt aes_p8_encrypt
|
||||
# define HWAES_decrypt aes_p8_decrypt
|
||||
# define HWAES_cbc_encrypt aes_p8_cbc_encrypt
|
||||
# define HWAES_ctr32_encrypt_blocks aes_p8_ctr32_encrypt_blocks
|
||||
# define HWAES_xts_encrypt aes_p8_xts_encrypt
|
||||
# define HWAES_xts_decrypt aes_p8_xts_decrypt
|
||||
#endif
|
||||
|
||||
#if defined(AES_ASM) && !defined(I386_ONLY) && ( \
|
||||
((defined(__i386) || defined(__i386__) || \
|
||||
defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \
|
||||
defined(__x86_64) || defined(__x86_64__) || \
|
||||
defined(_M_AMD64) || defined(_M_X64) )
|
||||
|
||||
extern unsigned int OPENSSL_ia32cap_P[];
|
||||
|
||||
# ifdef VPAES_ASM
|
||||
# define VPAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
|
||||
# endif
|
||||
# ifdef BSAES_ASM
|
||||
# define BSAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
|
||||
# endif
|
||||
/*
|
||||
* AES-NI section
|
||||
*/
|
||||
# define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
|
||||
|
||||
int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
|
||||
AES_KEY *key);
|
||||
int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
|
||||
AES_KEY *key);
|
||||
|
||||
void aesni_encrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
void aesni_decrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
|
||||
void aesni_ecb_encrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
size_t length, const AES_KEY *key, int enc);
|
||||
void aesni_cbc_encrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
size_t length,
|
||||
const AES_KEY *key, unsigned char *ivec, int enc);
|
||||
|
||||
void aesni_ctr32_encrypt_blocks(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
size_t blocks,
|
||||
const void *key, const unsigned char *ivec);
|
||||
|
||||
static int aesni_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
|
||||
&& !dat->enc) {
|
||||
ret = aesni_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f) aesni_decrypt;
|
||||
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f) aesni_cbc_encrypt : NULL;
|
||||
} else {
|
||||
ret = aesni_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f) aesni_encrypt;
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt;
|
||||
else if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
PROVerr(PROV_F_AESNI_INIT_KEY, PROV_R_AES_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aesni_cbc_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
aesni_cbc_encrypt(in, out, len, &ctx->ks.ks, ctx->iv, ctx->enc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aesni_ecb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
if (len < AES_BLOCK_SIZE)
|
||||
return 1;
|
||||
|
||||
aesni_ecb_encrypt(in, out, len, &ctx->ks.ks, ctx->enc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define aesni_ofb_cipher aes_ofb_cipher
|
||||
static int aesni_ofb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aesni_cfb_cipher aes_cfb_cipher
|
||||
static int aesni_cfb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aesni_cfb8_cipher aes_cfb8_cipher
|
||||
static int aesni_cfb8_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aesni_cfb1_cipher aes_cfb1_cipher
|
||||
static int aesni_cfb1_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aesni_ctr_cipher aes_ctr_cipher
|
||||
static int aesni_ctr_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define BLOCK_CIPHER_generic_prov(mode) \
|
||||
static const PROV_AES_CIPHER aesni_##mode = { \
|
||||
aesni_init_key, \
|
||||
aesni_##mode##_cipher}; \
|
||||
static const PROV_AES_CIPHER aes_##mode = { \
|
||||
aes_init_key, \
|
||||
aes_##mode##_cipher}; \
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
|
||||
{ return AESNI_CAPABLE?&aesni_##mode:&aes_##mode; }
|
||||
|
||||
|
||||
#elif defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
|
||||
|
||||
# include "sparc_arch.h"
|
||||
|
||||
extern unsigned int OPENSSL_sparcv9cap_P[];
|
||||
|
||||
/*
|
||||
* Fujitsu SPARC64 X support
|
||||
*/
|
||||
# define HWAES_CAPABLE (OPENSSL_sparcv9cap_P[0] & SPARCV9_FJAESX)
|
||||
# define HWAES_set_encrypt_key aes_fx_set_encrypt_key
|
||||
# define HWAES_set_decrypt_key aes_fx_set_decrypt_key
|
||||
# define HWAES_encrypt aes_fx_encrypt
|
||||
# define HWAES_decrypt aes_fx_decrypt
|
||||
# define HWAES_cbc_encrypt aes_fx_cbc_encrypt
|
||||
# define HWAES_ctr32_encrypt_blocks aes_fx_ctr32_encrypt_blocks
|
||||
|
||||
# define SPARC_AES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_AES)
|
||||
|
||||
void aes_t4_set_encrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
|
||||
void aes_t4_set_decrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
|
||||
void aes_t4_encrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
void aes_t4_decrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
/*
|
||||
* Key-length specific subroutines were chosen for following reason.
|
||||
* Each SPARC T4 core can execute up to 8 threads which share core's
|
||||
* resources. Loading as much key material to registers allows to
|
||||
* minimize references to shared memory interface, as well as amount
|
||||
* of instructions in inner loops [much needed on T4]. But then having
|
||||
* non-key-length specific routines would require conditional branches
|
||||
* either in inner loops or on subroutines' entries. Former is hardly
|
||||
* acceptable, while latter means code size increase to size occupied
|
||||
* by multiple key-length specific subroutines, so why fight?
|
||||
*/
|
||||
void aes128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes192_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes192_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t blocks, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes192_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t blocks, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t blocks, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
|
||||
static int aes_t4_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
int ret, bits;
|
||||
|
||||
bits = keylen * 8;
|
||||
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
|
||||
&& !dat->enc) {
|
||||
ret = 0;
|
||||
aes_t4_set_decrypt_key(key, bits, &dat->ks.ks);
|
||||
dat->block = (block128_f) aes_t4_decrypt;
|
||||
switch (bits) {
|
||||
case 128:
|
||||
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f) aes128_t4_cbc_decrypt : NULL;
|
||||
break;
|
||||
case 192:
|
||||
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f) aes192_t4_cbc_decrypt : NULL;
|
||||
break;
|
||||
case 256:
|
||||
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f) aes256_t4_cbc_decrypt : NULL;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
aes_t4_set_encrypt_key(key, bits, &dat->ks.ks);
|
||||
dat->block = (block128_f)aes_t4_encrypt;
|
||||
switch (bits) {
|
||||
case 128:
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)aes128_t4_cbc_encrypt;
|
||||
else if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)aes128_t4_ctr32_encrypt;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
break;
|
||||
case 192:
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)aes192_t4_cbc_encrypt;
|
||||
else if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)aes192_t4_ctr32_encrypt;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
break;
|
||||
case 256:
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)aes256_t4_cbc_encrypt;
|
||||
else if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)aes256_t4_ctr32_encrypt;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
PROVerr(PROV_F_AES_T4_INIT_KEY, PROV_R_AES_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define aes_t4_cbc_cipher aes_cbc_cipher
|
||||
static int aes_t4_cbc_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aes_t4_ecb_cipher aes_ecb_cipher
|
||||
static int aes_t4_ecb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aes_t4_ofb_cipher aes_ofb_cipher
|
||||
static int aes_t4_ofb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aes_t4_cfb_cipher aes_cfb_cipher
|
||||
static int aes_t4_cfb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aes_t4_cfb8_cipher aes_cfb8_cipher
|
||||
static int aes_t4_cfb8_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aes_t4_cfb1_cipher aes_cfb1_cipher
|
||||
static int aes_t4_cfb1_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aes_t4_ctr_cipher aes_ctr_cipher
|
||||
static int aes_t4_ctr_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define BLOCK_CIPHER_generic_prov(mode) \
|
||||
static const PROV_AES_CIPHER aes_t4_##mode = { \
|
||||
aes_t4_init_key, \
|
||||
aes_t4_##mode##_cipher}; \
|
||||
static const PROV_AES_CIPHER aes_##mode = { \
|
||||
aes_init_key, \
|
||||
aes_##mode##_cipher}; \
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
|
||||
{ return SPARC_AES_CAPABLE?&aes_t4_##mode:&aes_##mode; }
|
||||
|
||||
|
||||
#elif defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
|
||||
/*
|
||||
* IBM S390X support
|
||||
*/
|
||||
# include "s390x_arch.h"
|
||||
|
||||
/* Convert key size to function code: [16,24,32] -> [18,19,20]. */
|
||||
# define S390X_AES_FC(keylen) (S390X_AES_128 + ((((keylen) << 3) - 128) >> 6))
|
||||
|
||||
/* Most modes of operation need km for partial block processing. */
|
||||
# define S390X_aes_128_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
|
||||
S390X_CAPBIT(S390X_AES_128))
|
||||
# define S390X_aes_192_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
|
||||
S390X_CAPBIT(S390X_AES_192))
|
||||
# define S390X_aes_256_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
|
||||
S390X_CAPBIT(S390X_AES_256))
|
||||
|
||||
# define s390x_aes_init_key aes_init_key
|
||||
static int s390x_aes_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen);
|
||||
|
||||
# define S390X_aes_128_cbc_CAPABLE 1 /* checked by callee */
|
||||
# define S390X_aes_192_cbc_CAPABLE 1
|
||||
# define S390X_aes_256_cbc_CAPABLE 1
|
||||
# define S390X_AES_CBC_CTX PROV_AES_KEY
|
||||
|
||||
# define s390x_aes_cbc_init_key aes_init_key
|
||||
|
||||
# define s390x_aes_cbc_cipher aes_cbc_cipher
|
||||
static int s390x_aes_cbc_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define S390X_aes_128_ecb_CAPABLE S390X_aes_128_CAPABLE
|
||||
# define S390X_aes_192_ecb_CAPABLE S390X_aes_192_CAPABLE
|
||||
# define S390X_aes_256_ecb_CAPABLE S390X_aes_256_CAPABLE
|
||||
|
||||
static int s390x_aes_ecb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
dat->plat.s390x.fc = S390X_AES_FC(keylen);
|
||||
if (!dat->enc)
|
||||
dat->plat.s390x.fc |= S390X_DECRYPT;
|
||||
|
||||
memcpy(dat->plat.s390x.param.km.k, key, keylen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_ecb_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
s390x_km(in, len, out, dat->plat.s390x.fc,
|
||||
&dat->plat.s390x.param.km);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define S390X_aes_128_ofb_CAPABLE (S390X_aes_128_CAPABLE && \
|
||||
(OPENSSL_s390xcap_P.kmo[0] & \
|
||||
S390X_CAPBIT(S390X_AES_128)))
|
||||
# define S390X_aes_192_ofb_CAPABLE (S390X_aes_192_CAPABLE && \
|
||||
(OPENSSL_s390xcap_P.kmo[0] & \
|
||||
S390X_CAPBIT(S390X_AES_192)))
|
||||
# define S390X_aes_256_ofb_CAPABLE (S390X_aes_256_CAPABLE && \
|
||||
(OPENSSL_s390xcap_P.kmo[0] & \
|
||||
S390X_CAPBIT(S390X_AES_256)))
|
||||
|
||||
static int s390x_aes_ofb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
|
||||
memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
|
||||
dat->plat.s390x.fc = S390X_AES_FC(keylen);
|
||||
dat->plat.s390x.res = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_ofb_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int n = dat->plat.s390x.res;
|
||||
int rem;
|
||||
|
||||
while (n && len) {
|
||||
*out = *in ^ dat->plat.s390x.param.kmo_kmf.cv[n];
|
||||
n = (n + 1) & 0xf;
|
||||
--len;
|
||||
++in;
|
||||
++out;
|
||||
}
|
||||
|
||||
rem = len & 0xf;
|
||||
|
||||
len &= ~(size_t)0xf;
|
||||
if (len) {
|
||||
s390x_kmo(in, len, out, dat->plat.s390x.fc,
|
||||
&dat->plat.s390x.param.kmo_kmf);
|
||||
|
||||
out += len;
|
||||
in += len;
|
||||
}
|
||||
|
||||
if (rem) {
|
||||
s390x_km(dat->plat.s390x.param.kmo_kmf.cv, 16,
|
||||
dat->plat.s390x.param.kmo_kmf.cv, dat->plat.s390x.fc,
|
||||
dat->plat.s390x.param.kmo_kmf.k);
|
||||
|
||||
while (rem--) {
|
||||
out[n] = in[n] ^ dat->plat.s390x.param.kmo_kmf.cv[n];
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
dat->plat.s390x.res = n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define S390X_aes_128_cfb_CAPABLE (S390X_aes_128_CAPABLE && \
|
||||
(OPENSSL_s390xcap_P.kmf[0] & \
|
||||
S390X_CAPBIT(S390X_AES_128)))
|
||||
# define S390X_aes_192_cfb_CAPABLE (S390X_aes_192_CAPABLE && \
|
||||
(OPENSSL_s390xcap_P.kmf[0] & \
|
||||
S390X_CAPBIT(S390X_AES_192)))
|
||||
# define S390X_aes_256_cfb_CAPABLE (S390X_aes_256_CAPABLE && \
|
||||
(OPENSSL_s390xcap_P.kmf[0] & \
|
||||
S390X_CAPBIT(S390X_AES_256)))
|
||||
|
||||
static int s390x_aes_cfb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
dat->plat.s390x.fc = S390X_AES_FC(keylen);
|
||||
dat->plat.s390x.fc |= 16 << 24; /* 16 bytes cipher feedback */
|
||||
if (!dat->enc)
|
||||
dat->plat.s390x.fc |= S390X_DECRYPT;
|
||||
|
||||
dat->plat.s390x.res = 0;
|
||||
memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
|
||||
memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_cfb_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int n = dat->plat.s390x.res;
|
||||
int rem;
|
||||
unsigned char tmp;
|
||||
|
||||
while (n && len) {
|
||||
tmp = *in;
|
||||
*out = dat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
|
||||
dat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp;
|
||||
n = (n + 1) & 0xf;
|
||||
--len;
|
||||
++in;
|
||||
++out;
|
||||
}
|
||||
|
||||
rem = len & 0xf;
|
||||
|
||||
len &= ~(size_t)0xf;
|
||||
if (len) {
|
||||
s390x_kmf(in, len, out, dat->plat.s390x.fc,
|
||||
&dat->plat.s390x.param.kmo_kmf);
|
||||
|
||||
out += len;
|
||||
in += len;
|
||||
}
|
||||
|
||||
if (rem) {
|
||||
s390x_km(dat->plat.s390x.param.kmo_kmf.cv, 16,
|
||||
dat->plat.s390x.param.kmo_kmf.cv,
|
||||
S390X_AES_FC(dat->keylen), dat->plat.s390x.param.kmo_kmf.k);
|
||||
|
||||
while (rem--) {
|
||||
tmp = in[n];
|
||||
out[n] = dat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
|
||||
dat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp;
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
dat->plat.s390x.res = n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define S390X_aes_128_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
|
||||
S390X_CAPBIT(S390X_AES_128))
|
||||
# define S390X_aes_192_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
|
||||
S390X_CAPBIT(S390X_AES_192))
|
||||
# define S390X_aes_256_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
|
||||
S390X_CAPBIT(S390X_AES_256))
|
||||
|
||||
static int s390x_aes_cfb8_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
dat->plat.s390x.fc = S390X_AES_FC(keylen);
|
||||
dat->plat.s390x.fc |= 1 << 24; /* 1 byte cipher feedback */
|
||||
if (!dat->enc)
|
||||
dat->plat.s390x.fc |= S390X_DECRYPT;
|
||||
|
||||
memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
|
||||
memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_cfb8_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
s390x_kmf(in, len, out, dat->plat.s390x.fc,
|
||||
&dat->plat.s390x.param.kmo_kmf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define S390X_aes_128_cfb1_CAPABLE 0
|
||||
# define S390X_aes_192_cfb1_CAPABLE 0
|
||||
# define S390X_aes_256_cfb1_CAPABLE 0
|
||||
|
||||
# define s390x_aes_cfb1_init_key aes_init_key
|
||||
|
||||
# define s390x_aes_cfb1_cipher aes_cfb1_cipher
|
||||
static int s390x_aes_cfb1_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define S390X_aes_128_ctr_CAPABLE 1 /* checked by callee */
|
||||
# define S390X_aes_192_ctr_CAPABLE 1
|
||||
# define S390X_aes_256_ctr_CAPABLE 1
|
||||
# define S390X_AES_CTR_CTX PROV_AES_KEY
|
||||
|
||||
# define s390x_aes_ctr_init_key aes_init_key
|
||||
|
||||
# define s390x_aes_ctr_cipher aes_ctr_cipher
|
||||
static int s390x_aes_ctr_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define BLOCK_CIPHER_generic_prov(mode) \
|
||||
static const PROV_AES_CIPHER s390x_aes_##mode = { \
|
||||
s390x_aes_##mode##_init_key, \
|
||||
s390x_aes_##mode##_cipher \
|
||||
}; \
|
||||
static const PROV_AES_CIPHER aes_##mode = { \
|
||||
aes_init_key, \
|
||||
aes_##mode##_cipher \
|
||||
}; \
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
|
||||
{ \
|
||||
if ((keylen == 16 && S390X_aes_128_##mode##_CAPABLE) \
|
||||
|| (keylen == 24 && S390X_aes_192_##mode##_CAPABLE) \
|
||||
|| (keylen == 32 && S390X_aes_256_##mode##_CAPABLE)) \
|
||||
return &s390x_aes_##mode; \
|
||||
\
|
||||
return &aes_##mode; \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# define BLOCK_CIPHER_generic_prov(mode) \
|
||||
static const PROV_AES_CIPHER aes_##mode = { \
|
||||
aes_init_key, \
|
||||
aes_##mode##_cipher}; \
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
|
||||
{ return &aes_##mode; }
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(OPENSSL_CPUID_OBJ) && (defined(__arm__) || defined(__arm) || defined(__aarch64__))
|
||||
# include "arm_arch.h"
|
||||
# if __ARM_MAX_ARCH__>=7
|
||||
# if defined(BSAES_ASM)
|
||||
# define BSAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
|
||||
# endif
|
||||
# if defined(VPAES_ASM)
|
||||
# define VPAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
|
||||
# endif
|
||||
# define HWAES_CAPABLE (OPENSSL_armcap_P & ARMV8_AES)
|
||||
# define HWAES_set_encrypt_key aes_v8_set_encrypt_key
|
||||
# define HWAES_set_decrypt_key aes_v8_set_decrypt_key
|
||||
# define HWAES_encrypt aes_v8_encrypt
|
||||
# define HWAES_decrypt aes_v8_decrypt
|
||||
# define HWAES_cbc_encrypt aes_v8_cbc_encrypt
|
||||
# define HWAES_ctr32_encrypt_blocks aes_v8_ctr32_encrypt_blocks
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(HWAES_CAPABLE)
|
||||
int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits,
|
||||
AES_KEY *key);
|
||||
int HWAES_set_decrypt_key(const unsigned char *userKey, const int bits,
|
||||
AES_KEY *key);
|
||||
void HWAES_encrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
void HWAES_decrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
void HWAES_cbc_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t length, const AES_KEY *key,
|
||||
unsigned char *ivec, const int enc);
|
||||
void HWAES_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
const unsigned char ivec[16]);
|
||||
#endif
|
||||
|
||||
static int aes_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
|
||||
&& !dat->enc) {
|
||||
#ifdef HWAES_CAPABLE
|
||||
if (HWAES_CAPABLE) {
|
||||
ret = HWAES_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)HWAES_decrypt;
|
||||
dat->stream.cbc = NULL;
|
||||
# ifdef HWAES_cbc_encrypt
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
|
||||
# endif
|
||||
} else
|
||||
#endif
|
||||
#ifdef BSAES_CAPABLE
|
||||
if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CBC_MODE) {
|
||||
ret = AES_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)AES_decrypt;
|
||||
dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt;
|
||||
} else
|
||||
#endif
|
||||
#ifdef VPAES_CAPABLE
|
||||
if (VPAES_CAPABLE) {
|
||||
ret = vpaes_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)vpaes_decrypt;
|
||||
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
?(cbc128_f)vpaes_cbc_encrypt : NULL;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = AES_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)AES_decrypt;
|
||||
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
? (cbc128_f)AES_cbc_encrypt : NULL;
|
||||
}
|
||||
} else
|
||||
#ifdef HWAES_CAPABLE
|
||||
if (HWAES_CAPABLE) {
|
||||
ret = HWAES_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)HWAES_encrypt;
|
||||
dat->stream.cbc = NULL;
|
||||
# ifdef HWAES_cbc_encrypt
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
|
||||
else
|
||||
# endif
|
||||
# ifdef HWAES_ctr32_encrypt_blocks
|
||||
if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks;
|
||||
else
|
||||
# endif
|
||||
(void)0; /* terminate potentially open 'else' */
|
||||
} else
|
||||
#endif
|
||||
#ifdef BSAES_CAPABLE
|
||||
if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CTR_MODE) {
|
||||
ret = AES_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)AES_encrypt;
|
||||
dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks;
|
||||
} else
|
||||
#endif
|
||||
#ifdef VPAES_CAPABLE
|
||||
if (VPAES_CAPABLE) {
|
||||
ret = vpaes_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)vpaes_encrypt;
|
||||
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
? (cbc128_f)vpaes_cbc_encrypt : NULL;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = AES_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)AES_encrypt;
|
||||
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
? (cbc128_f)AES_cbc_encrypt : NULL;
|
||||
#ifdef AES_CTR_ASM
|
||||
if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)AES_ctr32_encrypt;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
PROVerr(PROV_F_AES_INIT_KEY, PROV_R_AES_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_cbc_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
if (dat->stream.cbc)
|
||||
(*dat->stream.cbc) (in, out, len, &dat->ks, dat->iv, dat->enc);
|
||||
else if (dat->enc)
|
||||
CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, dat->iv, dat->block);
|
||||
else
|
||||
CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, dat->iv, dat->block);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_ecb_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (len < AES_BLOCK_SIZE)
|
||||
return 1;
|
||||
|
||||
for (i = 0, len -= AES_BLOCK_SIZE; i <= len; i += AES_BLOCK_SIZE)
|
||||
(*dat->block) (in + i, out + i, &dat->ks);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_ofb_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int num = dat->num;
|
||||
CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, dat->iv, &num, dat->block);
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_cfb_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int num = dat->num;
|
||||
CRYPTO_cfb128_encrypt(in, out, len, &dat->ks, dat->iv, &num, dat->enc,
|
||||
dat->block);
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_cfb8_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int num = dat->num;
|
||||
CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks, dat->iv, &num, dat->enc,
|
||||
dat->block);
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_cfb1_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int num = dat->num;
|
||||
|
||||
if ((dat->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) {
|
||||
CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks, dat->iv, &num,
|
||||
dat->enc, dat->block);
|
||||
dat->num = num;
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (len >= MAXBITCHUNK) {
|
||||
CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks,
|
||||
dat->iv, &num, dat->enc, dat->block);
|
||||
len -= MAXBITCHUNK;
|
||||
out += MAXBITCHUNK;
|
||||
in += MAXBITCHUNK;
|
||||
}
|
||||
if (len)
|
||||
CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks, dat->iv, &num,
|
||||
dat->enc, dat->block);
|
||||
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_ctr_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
unsigned int num = dat->num;
|
||||
|
||||
if (dat->stream.ctr)
|
||||
CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, dat->iv, dat->buf,
|
||||
&num, dat->stream.ctr);
|
||||
else
|
||||
CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, dat->iv, dat->buf,
|
||||
&num, dat->block);
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BLOCK_CIPHER_generic_prov(cbc)
|
||||
BLOCK_CIPHER_generic_prov(ecb)
|
||||
BLOCK_CIPHER_generic_prov(ofb)
|
||||
BLOCK_CIPHER_generic_prov(cfb)
|
||||
BLOCK_CIPHER_generic_prov(cfb1)
|
||||
BLOCK_CIPHER_generic_prov(cfb8)
|
||||
BLOCK_CIPHER_generic_prov(ctr)
|
||||
|
||||
@@ -7,11 +7,8 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include "ciphers_locl.h"
|
||||
#include <assert.h>
|
||||
#include "cipher_locl.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
/*
|
||||
@@ -67,7 +64,7 @@ int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize,
|
||||
return 1;
|
||||
|
||||
if (*buflen + *inlen > blocksize) {
|
||||
PROVerr(PROV_F_TRAILINGDATA, ERR_R_INTERNAL_ERROR);
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -94,7 +91,7 @@ int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize)
|
||||
size_t len = *buflen;
|
||||
|
||||
if(len != blocksize) {
|
||||
PROVerr(PROV_F_UNPADBLOCK, ERR_R_INTERNAL_ERROR);
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -104,12 +101,12 @@ int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize)
|
||||
*/
|
||||
pad = buf[blocksize - 1];
|
||||
if (pad == 0 || pad > blocksize) {
|
||||
PROVerr(PROV_F_UNPADBLOCK, PROV_R_BAD_DECRYPT);
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < pad; i++) {
|
||||
if (buf[--len] != pad) {
|
||||
PROVerr(PROV_F_UNPADBLOCK, PROV_R_BAD_DECRYPT);
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
LIBS=../../../libcrypto
|
||||
SOURCE[../../../libcrypto]=\
|
||||
block.c aes.c aes_basic.c
|
||||
|
||||
IF[{- !$disabled{des} -}]
|
||||
$COMMON_DES=cipher_tdes.c cipher_tdes_hw.c
|
||||
ENDIF
|
||||
|
||||
$COMMON=cipher_common.c cipher_common_hw.c block.c \
|
||||
cipher_aes.c cipher_aes_hw.c \
|
||||
cipher_aes_xts.c cipher_aes_xts_hw.c \
|
||||
cipher_gcm.c cipher_gcm_hw.c \
|
||||
cipher_aes_gcm.c cipher_aes_gcm_hw.c \
|
||||
cipher_ccm.c cipher_ccm_hw.c \
|
||||
cipher_aes_ccm.c cipher_aes_ccm_hw.c \
|
||||
cipher_aes_wrp.c \
|
||||
$COMMON_DES
|
||||
|
||||
SOURCE[../../../libcrypto]=$COMMON
|
||||
INCLUDE[../../../libcrypto]=. ../../../crypto
|
||||
|
||||
SOURCE[../../fips]=\
|
||||
block.c aes.c aes_basic.c
|
||||
SOURCE[../../fips]=$COMMON
|
||||
INCLUDE[../../fips]=. ../../../crypto
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 cipher modes ecb, cbc, ofb, cfb, ctr */
|
||||
|
||||
#include "cipher_aes.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static OSSL_OP_cipher_freectx_fn aes_freectx;
|
||||
static OSSL_OP_cipher_dupctx_fn aes_dupctx;
|
||||
|
||||
static void aes_freectx(void *vctx)
|
||||
{
|
||||
PROV_AES_CTX *ctx = (PROV_AES_CTX *)vctx;
|
||||
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void *aes_dupctx(void *ctx)
|
||||
{
|
||||
PROV_AES_CTX *in = (PROV_AES_CTX *)ctx;
|
||||
PROV_AES_CTX *ret = OPENSSL_malloc(sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
*ret = *in;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* aes256ecb_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 256, 128, 0, block)
|
||||
/* aes192ecb_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 192, 128, 0, block)
|
||||
/* aes128ecb_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 128, 128, 0, block)
|
||||
/* aes256cbc_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 256, 128, 128, block)
|
||||
/* aes192cbc_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 192, 128, 128, block)
|
||||
/* aes128cbc_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 128, 128, 128, block)
|
||||
/* aes256ofb_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 256, 8, 128, stream)
|
||||
/* aes192ofb_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 192, 8, 128, stream)
|
||||
/* aes128ofb_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 128, 8, 128, stream)
|
||||
/* aes256cfb_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 256, 8, 128, stream)
|
||||
/* aes192cfb_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 192, 8, 128, stream)
|
||||
/* aes128cfb_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 128, 8, 128, stream)
|
||||
/* aes256cfb1_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 256, 8, 128, stream)
|
||||
/* aes192cfb1_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 192, 8, 128, stream)
|
||||
/* aes128cfb1_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 128, 8, 128, stream)
|
||||
/* aes256cfb8_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 256, 8, 128, stream)
|
||||
/* aes192cfb8_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 192, 8, 128, stream)
|
||||
/* aes128cfb8_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 128, 8, 128, stream)
|
||||
/* aes256ctr_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 256, 8, 128, stream)
|
||||
/* aes192ctr_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 192, 8, 128, stream)
|
||||
/* aes128ctr_functions */
|
||||
IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 128, 8, 128, stream)
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 "internal/ciphers/ciphercommon.h"
|
||||
|
||||
typedef struct prov_aes_ctx_st {
|
||||
PROV_CIPHER_CTX base; /* Must be first */
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
AES_KEY ks;
|
||||
} ks;
|
||||
|
||||
/* Platform specific data */
|
||||
union {
|
||||
int dummy;
|
||||
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
|
||||
struct {
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
/*-
|
||||
* KM-AES parameter block - begin
|
||||
* (see z/Architecture Principles of Operation >= SA22-7832-06)
|
||||
*/
|
||||
struct {
|
||||
unsigned char k[32];
|
||||
} km;
|
||||
/* KM-AES parameter block - end */
|
||||
/*-
|
||||
* KMO-AES/KMF-AES parameter block - begin
|
||||
* (see z/Architecture Principles of Operation >= SA22-7832-08)
|
||||
*/
|
||||
struct {
|
||||
unsigned char cv[16];
|
||||
unsigned char k[32];
|
||||
} kmo_kmf;
|
||||
/* KMO-AES/KMF-AES parameter block - end */
|
||||
} param;
|
||||
unsigned int fc;
|
||||
int res;
|
||||
} s390x;
|
||||
#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
|
||||
} plat;
|
||||
|
||||
} PROV_AES_CTX;
|
||||
|
||||
#define PROV_CIPHER_HW_aes_ofb PROV_CIPHER_HW_aes_ofb128
|
||||
#define PROV_CIPHER_HW_aes_cfb PROV_CIPHER_HW_aes_cfb128
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_ecb(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_cbc(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_ofb128(size_t keybits);
|
||||
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,39 @@
|
||||
/*
|
||||
* 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 CCM mode */
|
||||
|
||||
#include "cipher_locl.h"
|
||||
#include "internal/ciphers/cipher_ccm.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static void *aes_ccm_newctx(void *provctx, size_t keybits)
|
||||
{
|
||||
PROV_AES_CCM_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx != NULL)
|
||||
ccm_initctx(&ctx->base, keybits, PROV_AES_HW_ccm(keybits));
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static OSSL_OP_cipher_freectx_fn aes_ccm_freectx;
|
||||
static void aes_ccm_freectx(void *vctx)
|
||||
{
|
||||
PROV_AES_CCM_CTX *ctx = (PROV_AES_CCM_CTX *)vctx;
|
||||
|
||||
ccm_finalctx((PROV_CCM_CTX *)ctx);
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
/* aes128ccm_functions */
|
||||
IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 128, 8, 96);
|
||||
/* aes192ccm_functions */
|
||||
IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 192, 8, 96);
|
||||
/* aes256ccm_functions */
|
||||
IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 256, 8, 96);
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 CCM mode */
|
||||
|
||||
#include "cipher_locl.h"
|
||||
#include "internal/ciphers/cipher_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); \
|
||||
CRYPTO_ccm128_init(&ctx->ccm_ctx, ctx->m, ctx->l, &actx->ccm.ks.ks, \
|
||||
(block128_f)fn_blk); \
|
||||
ctx->str = ctx->enc ? (ccm128_f)fn_ccm_enc : (ccm128_f)fn_ccm_dec; \
|
||||
ctx->key_set = 1;
|
||||
|
||||
static int ccm_generic_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx;
|
||||
|
||||
#ifdef HWAES_CAPABLE
|
||||
if (HWAES_CAPABLE) {
|
||||
AES_HW_CCM_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_encrypt, NULL, NULL);
|
||||
} else
|
||||
#endif /* HWAES_CAPABLE */
|
||||
|
||||
#ifdef VPAES_CAPABLE
|
||||
if (VPAES_CAPABLE) {
|
||||
AES_HW_CCM_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_encrypt, NULL, NULL);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
AES_HW_CCM_SET_KEY_FN(AES_set_encrypt_key, AES_encrypt, NULL, NULL)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const PROV_CCM_HW aes_ccm = {
|
||||
ccm_generic_aes_initkey,
|
||||
ccm_generic_setiv,
|
||||
ccm_generic_setaad,
|
||||
ccm_generic_auth_encrypt,
|
||||
ccm_generic_auth_decrypt,
|
||||
ccm_generic_gettag
|
||||
};
|
||||
|
||||
#if defined(S390X_aes_128_CAPABLE)
|
||||
# include "cipher_aes_ccm_hw_s390x.inc"
|
||||
#elif defined(AESNI_CAPABLE)
|
||||
# include "cipher_aes_ccm_hw_aesni.inc"
|
||||
#elif defined(SPARC_AES_CAPABLE)
|
||||
# include "cipher_aes_ccm_hw_t4.inc"
|
||||
#else
|
||||
const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits)
|
||||
{
|
||||
return &aes_ccm;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*-
|
||||
* AES-NI support for AES CCM.
|
||||
* This file is included by cipher_ccm_hw.c
|
||||
*/
|
||||
|
||||
static int ccm_aesni_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx;
|
||||
|
||||
AES_HW_CCM_SET_KEY_FN(aesni_set_encrypt_key, aesni_encrypt,
|
||||
aesni_ccm64_encrypt_blocks,
|
||||
aesni_ccm64_decrypt_blocks);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const PROV_CCM_HW aesni_ccm = {
|
||||
ccm_aesni_initkey,
|
||||
ccm_generic_setiv,
|
||||
ccm_generic_setaad,
|
||||
ccm_generic_auth_encrypt,
|
||||
ccm_generic_auth_decrypt,
|
||||
ccm_generic_gettag
|
||||
};
|
||||
|
||||
const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits)
|
||||
{
|
||||
return AESNI_CAPABLE ? &aesni_ccm : &aes_ccm;
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*-
|
||||
* S390X support for AES CCM.
|
||||
* This file is included by cipher_ccm_hw.c
|
||||
*/
|
||||
|
||||
#define S390X_CCM_AAD_FLAG 0x40
|
||||
|
||||
static int s390x_aes_ccm_initkey(PROV_CCM_CTX *ctx,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
|
||||
|
||||
sctx->ccm.s390x.fc = S390X_AES_FC(keylen);
|
||||
memcpy(&sctx->ccm.s390x.kmac.k, key, keylen);
|
||||
/* Store encoded m and l. */
|
||||
sctx->ccm.s390x.nonce.b[0] = ((ctx->l - 1) & 0x7)
|
||||
| (((ctx->m - 2) >> 1) & 0x7) << 3;
|
||||
memset(sctx->ccm.s390x.nonce.b + 1, 0, sizeof(sctx->ccm.s390x.nonce.b));
|
||||
sctx->ccm.s390x.blocks = 0;
|
||||
ctx->key_set = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_ccm_setiv(PROV_CCM_CTX *ctx,
|
||||
const unsigned char *nonce, size_t noncelen,
|
||||
size_t mlen)
|
||||
{
|
||||
PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
|
||||
|
||||
sctx->ccm.s390x.nonce.b[0] &= ~S390X_CCM_AAD_FLAG;
|
||||
sctx->ccm.s390x.nonce.g[1] = mlen;
|
||||
memcpy(sctx->ccm.s390x.nonce.b + 1, nonce, 15 - ctx->l);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Process additional authenticated data. Code is big-endian.
|
||||
*/
|
||||
static int s390x_aes_ccm_setaad(PROV_CCM_CTX *ctx,
|
||||
const unsigned char *aad, size_t alen)
|
||||
{
|
||||
PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
|
||||
unsigned char *ptr;
|
||||
int i, rem;
|
||||
|
||||
if (!alen)
|
||||
return 1;
|
||||
|
||||
sctx->ccm.s390x.nonce.b[0] |= S390X_CCM_AAD_FLAG;
|
||||
|
||||
/* Suppress 'type-punned pointer dereference' warning. */
|
||||
ptr = sctx->ccm.s390x.buf.b;
|
||||
|
||||
if (alen < ((1 << 16) - (1 << 8))) {
|
||||
*(uint16_t *)ptr = alen;
|
||||
i = 2;
|
||||
} else if (sizeof(alen) == 8
|
||||
&& alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) {
|
||||
*(uint16_t *)ptr = 0xffff;
|
||||
*(uint64_t *)(ptr + 2) = alen;
|
||||
i = 10;
|
||||
} else {
|
||||
*(uint16_t *)ptr = 0xfffe;
|
||||
*(uint32_t *)(ptr + 2) = alen;
|
||||
i = 6;
|
||||
}
|
||||
|
||||
while (i < 16 && alen) {
|
||||
sctx->ccm.s390x.buf.b[i] = *aad;
|
||||
++aad;
|
||||
--alen;
|
||||
++i;
|
||||
}
|
||||
while (i < 16) {
|
||||
sctx->ccm.s390x.buf.b[i] = 0;
|
||||
++i;
|
||||
}
|
||||
|
||||
sctx->ccm.s390x.kmac.icv.g[0] = 0;
|
||||
sctx->ccm.s390x.kmac.icv.g[1] = 0;
|
||||
s390x_kmac(sctx->ccm.s390x.nonce.b, 32, sctx->ccm.s390x.fc,
|
||||
&sctx->ccm.s390x.kmac);
|
||||
sctx->ccm.s390x.blocks += 2;
|
||||
|
||||
rem = alen & 0xf;
|
||||
alen &= ~(size_t)0xf;
|
||||
if (alen) {
|
||||
s390x_kmac(aad, alen, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac);
|
||||
sctx->ccm.s390x.blocks += alen >> 4;
|
||||
aad += alen;
|
||||
}
|
||||
if (rem) {
|
||||
for (i = 0; i < rem; i++)
|
||||
sctx->ccm.s390x.kmac.icv.b[i] ^= aad[i];
|
||||
|
||||
s390x_km(sctx->ccm.s390x.kmac.icv.b, 16,
|
||||
sctx->ccm.s390x.kmac.icv.b, sctx->ccm.s390x.fc,
|
||||
sctx->ccm.s390x.kmac.k);
|
||||
sctx->ccm.s390x.blocks++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* En/de-crypt plain/cipher-text. Compute tag from plaintext. Returns 1 for
|
||||
* success.
|
||||
*/
|
||||
static int s390x_aes_ccm_auth_encdec(PROV_CCM_CTX *ctx,
|
||||
const unsigned char *in,
|
||||
unsigned char *out, size_t len, int enc)
|
||||
{
|
||||
PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
|
||||
size_t n, rem;
|
||||
unsigned int i, l, num;
|
||||
unsigned char flags;
|
||||
|
||||
flags = sctx->ccm.s390x.nonce.b[0];
|
||||
if (!(flags & S390X_CCM_AAD_FLAG)) {
|
||||
s390x_km(sctx->ccm.s390x.nonce.b, 16, sctx->ccm.s390x.kmac.icv.b,
|
||||
sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k);
|
||||
sctx->ccm.s390x.blocks++;
|
||||
}
|
||||
l = flags & 0x7;
|
||||
sctx->ccm.s390x.nonce.b[0] = l;
|
||||
|
||||
/*-
|
||||
* Reconstruct length from encoded length field
|
||||
* and initialize it with counter value.
|
||||
*/
|
||||
n = 0;
|
||||
for (i = 15 - l; i < 15; i++) {
|
||||
n |= sctx->ccm.s390x.nonce.b[i];
|
||||
sctx->ccm.s390x.nonce.b[i] = 0;
|
||||
n <<= 8;
|
||||
}
|
||||
n |= sctx->ccm.s390x.nonce.b[15];
|
||||
sctx->ccm.s390x.nonce.b[15] = 1;
|
||||
|
||||
if (n != len)
|
||||
return 0; /* length mismatch */
|
||||
|
||||
if (enc) {
|
||||
/* Two operations per block plus one for tag encryption */
|
||||
sctx->ccm.s390x.blocks += (((len + 15) >> 4) << 1) + 1;
|
||||
if (sctx->ccm.s390x.blocks > (1ULL << 61))
|
||||
return 0; /* too much data */
|
||||
}
|
||||
|
||||
num = 0;
|
||||
rem = len & 0xf;
|
||||
len &= ~(size_t)0xf;
|
||||
|
||||
if (enc) {
|
||||
/* mac-then-encrypt */
|
||||
if (len)
|
||||
s390x_kmac(in, len, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac);
|
||||
if (rem) {
|
||||
for (i = 0; i < rem; i++)
|
||||
sctx->ccm.s390x.kmac.icv.b[i] ^= in[len + i];
|
||||
|
||||
s390x_km(sctx->ccm.s390x.kmac.icv.b, 16,
|
||||
sctx->ccm.s390x.kmac.icv.b,
|
||||
sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k);
|
||||
}
|
||||
|
||||
CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &sctx->ccm.ks.ks,
|
||||
sctx->ccm.s390x.nonce.b, sctx->ccm.s390x.buf.b,
|
||||
&num, (ctr128_f)AES_ctr32_encrypt);
|
||||
} else {
|
||||
/* decrypt-then-mac */
|
||||
CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &sctx->ccm.ks.ks,
|
||||
sctx->ccm.s390x.nonce.b, sctx->ccm.s390x.buf.b,
|
||||
&num, (ctr128_f)AES_ctr32_encrypt);
|
||||
|
||||
if (len)
|
||||
s390x_kmac(out, len, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac);
|
||||
if (rem) {
|
||||
for (i = 0; i < rem; i++)
|
||||
sctx->ccm.s390x.kmac.icv.b[i] ^= out[len + i];
|
||||
|
||||
s390x_km(sctx->ccm.s390x.kmac.icv.b, 16,
|
||||
sctx->ccm.s390x.kmac.icv.b,
|
||||
sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k);
|
||||
}
|
||||
}
|
||||
/* encrypt tag */
|
||||
for (i = 15 - l; i < 16; i++)
|
||||
sctx->ccm.s390x.nonce.b[i] = 0;
|
||||
|
||||
s390x_km(sctx->ccm.s390x.nonce.b, 16, sctx->ccm.s390x.buf.b,
|
||||
sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k);
|
||||
sctx->ccm.s390x.kmac.icv.g[0] ^= sctx->ccm.s390x.buf.g[0];
|
||||
sctx->ccm.s390x.kmac.icv.g[1] ^= sctx->ccm.s390x.buf.g[1];
|
||||
|
||||
sctx->ccm.s390x.nonce.b[0] = flags; /* restore flags field */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int s390x_aes_ccm_gettag(PROV_CCM_CTX *ctx,
|
||||
unsigned char *tag, size_t tlen)
|
||||
{
|
||||
PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
|
||||
|
||||
if (tlen > ctx->m)
|
||||
return 0;
|
||||
memcpy(tag, sctx->ccm.s390x.kmac.icv.b, tlen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_ccm_auth_encrypt(PROV_CCM_CTX *ctx,
|
||||
const unsigned char *in,
|
||||
unsigned char *out, size_t len,
|
||||
unsigned char *tag, size_t taglen)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = s390x_aes_ccm_auth_encdec(ctx, in, out, len, 1);
|
||||
if (rv && tag != NULL)
|
||||
rv = s390x_aes_ccm_gettag(ctx, tag, taglen);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int s390x_aes_ccm_auth_decrypt(PROV_CCM_CTX *ctx,
|
||||
const unsigned char *in,
|
||||
unsigned char *out, size_t len,
|
||||
unsigned char *expected_tag,
|
||||
size_t taglen)
|
||||
{
|
||||
int rv = 0;
|
||||
PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
|
||||
|
||||
rv = s390x_aes_ccm_auth_encdec(ctx, in, out, len, 0);
|
||||
if (rv) {
|
||||
if (CRYPTO_memcmp(sctx->ccm.s390x.kmac.icv.b, expected_tag, ctx->m) != 0)
|
||||
rv = 0;
|
||||
}
|
||||
if (rv == 0)
|
||||
OPENSSL_cleanse(out, len);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static const PROV_CCM_HW s390x_aes_ccm = {
|
||||
s390x_aes_ccm_initkey,
|
||||
s390x_aes_ccm_setiv,
|
||||
s390x_aes_ccm_setaad,
|
||||
s390x_aes_ccm_auth_encrypt,
|
||||
s390x_aes_ccm_auth_decrypt,
|
||||
s390x_aes_ccm_gettag
|
||||
};
|
||||
|
||||
const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits)
|
||||
{
|
||||
if ((keybits == 128 && S390X_aes_128_ccm_CAPABLE)
|
||||
|| (keybits == 192 && S390X_aes_192_ccm_CAPABLE)
|
||||
|| (keybits == 256 && S390X_aes_256_ccm_CAPABLE))
|
||||
return &s390x_aes_ccm;
|
||||
return &aes_ccm;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Fujitsu SPARC64 X support for AES CCM.
|
||||
* This file is included by cipher_ccm_hw.c
|
||||
*/
|
||||
|
||||
static int ccm_t4_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx;
|
||||
|
||||
AES_HW_CCM_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_encrypt, NULL, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const PROV_CCM_HW t4_aes_ccm = {
|
||||
ccm_t4_aes_initkey,
|
||||
ccm_generic_setiv,
|
||||
ccm_generic_setaad,
|
||||
ccm_generic_auth_encrypt,
|
||||
ccm_generic_auth_decrypt,
|
||||
ccm_generic_gettag
|
||||
};
|
||||
|
||||
const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits)
|
||||
{
|
||||
return SPARC_AES_CAPABLE ? &t4_aes_ccm : &aes_ccm;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 GCM mode */
|
||||
|
||||
#include "cipher_locl.h"
|
||||
#include "internal/ciphers/cipher_gcm.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static void *aes_gcm_newctx(void *provctx, size_t keybits)
|
||||
{
|
||||
PROV_AES_GCM_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx != NULL)
|
||||
gcm_initctx(provctx, &ctx->base, keybits, PROV_AES_HW_gcm(keybits), 8);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static OSSL_OP_cipher_freectx_fn aes_gcm_freectx;
|
||||
static void aes_gcm_freectx(void *vctx)
|
||||
{
|
||||
PROV_AES_GCM_CTX *ctx = (PROV_AES_GCM_CTX *)vctx;
|
||||
|
||||
gcm_deinitctx((PROV_GCM_CTX *)ctx);
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
/* aes128gcm_functions */
|
||||
IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 128, 8, 96);
|
||||
/* aes192gcm_functions */
|
||||
IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 192, 8, 96);
|
||||
/* aes256gcm_functions */
|
||||
IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 256, 8, 96);
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 GCM mode */
|
||||
|
||||
#include "cipher_locl.h"
|
||||
#include "internal/ciphers/cipher_gcm.h"
|
||||
|
||||
static int generic_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;
|
||||
|
||||
# ifdef HWAES_CAPABLE
|
||||
if (HWAES_CAPABLE) {
|
||||
# ifdef HWAES_ctr32_encrypt_blocks
|
||||
GCM_HW_SET_KEY_CTR_FN(ks, HWAES_set_encrypt_key, HWAES_encrypt,
|
||||
HWAES_ctr32_encrypt_blocks);
|
||||
# else
|
||||
GCM_HW_SET_KEY_CTR_FN(ks, HWAES_set_encrypt_key, HWAES_encrypt, NULL);
|
||||
# endif /* HWAES_ctr32_encrypt_blocks */
|
||||
} else
|
||||
# endif /* HWAES_CAPABLE */
|
||||
|
||||
# ifdef BSAES_CAPABLE
|
||||
if (BSAES_CAPABLE) {
|
||||
GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt,
|
||||
bsaes_ctr32_encrypt_blocks);
|
||||
} else
|
||||
# endif /* BSAES_CAPABLE */
|
||||
|
||||
# ifdef VPAES_CAPABLE
|
||||
if (VPAES_CAPABLE) {
|
||||
GCM_HW_SET_KEY_CTR_FN(ks, vpaes_set_encrypt_key, vpaes_encrypt, NULL);
|
||||
} else
|
||||
# endif /* VPAES_CAPABLE */
|
||||
|
||||
{
|
||||
# ifdef AES_CTR_ASM
|
||||
GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt,
|
||||
AES_ctr32_encrypt);
|
||||
# else
|
||||
GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt, NULL);
|
||||
# endif /* AES_CTR_ASM */
|
||||
}
|
||||
ctx->key_set = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const PROV_GCM_HW aes_gcm = {
|
||||
generic_aes_gcm_initkey,
|
||||
gcm_setiv,
|
||||
gcm_aad_update,
|
||||
gcm_cipher_update,
|
||||
gcm_cipher_final,
|
||||
gcm_one_shot
|
||||
};
|
||||
|
||||
#if defined(S390X_aes_128_CAPABLE)
|
||||
# include "cipher_aes_gcm_hw_s390x.inc"
|
||||
#elif defined(AESNI_CAPABLE)
|
||||
# include "cipher_aes_gcm_hw_aesni.inc"
|
||||
#elif defined(SPARC_AES_CAPABLE)
|
||||
# include "cipher_aes_gcm_hw_t4.inc"
|
||||
#else
|
||||
const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits)
|
||||
{
|
||||
return &aes_gcm;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*-
|
||||
* AES-NI support for AES GCM.
|
||||
* This file is included by cipher_gcm_hw.c
|
||||
*/
|
||||
|
||||
static int aesni_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, aesni_set_encrypt_key, aesni_encrypt,
|
||||
aesni_ctr32_encrypt_blocks);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const PROV_GCM_HW aesni_gcm = {
|
||||
aesni_gcm_initkey,
|
||||
gcm_setiv,
|
||||
gcm_aad_update,
|
||||
gcm_cipher_update,
|
||||
gcm_cipher_final,
|
||||
gcm_one_shot
|
||||
};
|
||||
|
||||
const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits)
|
||||
{
|
||||
return AESNI_CAPABLE ? &aesni_gcm : &aes_gcm;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*-
|
||||
* IBM S390X support for AES GCM.
|
||||
* This file is included by cipher_gcm_hw.c
|
||||
*/
|
||||
|
||||
/* iv + padding length for iv lengths != 12 */
|
||||
#define S390X_gcm_ivpadlen(i) ((((i) + 15) >> 4 << 4) + 16)
|
||||
|
||||
static int s390x_aes_gcm_initkey(PROV_GCM_CTX *ctx,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
|
||||
|
||||
ctx->key_set = 1;
|
||||
memcpy(&actx->plat.s390x.param.kma.k, key, keylen);
|
||||
actx->plat.s390x.fc = S390X_AES_FC(keylen);
|
||||
if (!ctx->enc)
|
||||
actx->plat.s390x.fc |= S390X_DECRYPT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv,
|
||||
size_t ivlen)
|
||||
{
|
||||
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
|
||||
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
|
||||
|
||||
kma->t.g[0] = 0;
|
||||
kma->t.g[1] = 0;
|
||||
kma->tpcl = 0;
|
||||
kma->taadl = 0;
|
||||
actx->plat.s390x.mreslen = 0;
|
||||
actx->plat.s390x.areslen = 0;
|
||||
actx->plat.s390x.kreslen = 0;
|
||||
|
||||
if (ivlen == GCM_IV_DEFAULT_SIZE) {
|
||||
memcpy(&kma->j0, iv, ivlen);
|
||||
kma->j0.w[3] = 1;
|
||||
kma->cv.w = 1;
|
||||
} else {
|
||||
unsigned long long ivbits = ivlen << 3;
|
||||
size_t len = S390X_gcm_ivpadlen(ivlen);
|
||||
unsigned char iv_zero_pad[S390X_gcm_ivpadlen(GCM_IV_MAX_SIZE)];
|
||||
/*
|
||||
* The IV length needs to be zero padded to be a multiple of 16 bytes
|
||||
* followed by 8 bytes of zeros and 8 bytes for the IV length.
|
||||
* The GHASH of this value can then be calculated.
|
||||
*/
|
||||
memcpy(iv_zero_pad, iv, ivlen);
|
||||
memset(iv_zero_pad + ivlen, 0, len - ivlen);
|
||||
memcpy(iv_zero_pad + len - sizeof(ivbits), &ivbits, sizeof(ivbits));
|
||||
/*
|
||||
* Calculate the ghash of the iv - the result is stored into the tag
|
||||
* param.
|
||||
*/
|
||||
s390x_kma(iv_zero_pad, len, NULL, 0, NULL, actx->plat.s390x.fc, kma);
|
||||
actx->plat.s390x.fc |= S390X_KMA_HS; /* The hash subkey is set */
|
||||
|
||||
/* Copy the 128 bit GHASH result into J0 and clear the tag */
|
||||
kma->j0.g[0] = kma->t.g[0];
|
||||
kma->j0.g[1] = kma->t.g[1];
|
||||
kma->t.g[0] = 0;
|
||||
kma->t.g[1] = 0;
|
||||
/* Set the 32 bit counter */
|
||||
kma->cv.w = kma->j0.w[3];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag)
|
||||
{
|
||||
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
|
||||
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
|
||||
unsigned char out[AES_BLOCK_SIZE];
|
||||
int rc;
|
||||
|
||||
kma->taadl <<= 3;
|
||||
kma->tpcl <<= 3;
|
||||
s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen,
|
||||
actx->plat.s390x.mres, actx->plat.s390x.mreslen, out,
|
||||
actx->plat.s390x.fc | S390X_KMA_LAAD | S390X_KMA_LPC, kma);
|
||||
|
||||
/* gctx->mres already returned to the caller */
|
||||
OPENSSL_cleanse(out, actx->plat.s390x.mreslen);
|
||||
|
||||
if (ctx->enc) {
|
||||
ctx->taglen = GCM_TAG_MAX_SIZE;
|
||||
memcpy(tag, kma->t.b, ctx->taglen);
|
||||
rc = 1;
|
||||
} else {
|
||||
rc = (CRYPTO_memcmp(tag, kma->t.b, ctx->taglen) == 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int s390x_aes_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 taglen)
|
||||
{
|
||||
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
|
||||
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
|
||||
int rc;
|
||||
|
||||
kma->taadl = aad_len << 3;
|
||||
kma->tpcl = in_len << 3;
|
||||
s390x_kma(aad, aad_len, in, in_len, out,
|
||||
actx->plat.s390x.fc | S390X_KMA_LAAD | S390X_KMA_LPC, kma);
|
||||
|
||||
if (ctx->enc) {
|
||||
memcpy(tag, kma->t.b, taglen);
|
||||
rc = 1;
|
||||
} else {
|
||||
rc = (CRYPTO_memcmp(tag, kma->t.b, taglen) == 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process additional authenticated data. Returns 1 on success. Code is
|
||||
* big-endian.
|
||||
*/
|
||||
static int s390x_aes_gcm_aad_update(PROV_GCM_CTX *ctx,
|
||||
const unsigned char *aad, size_t len)
|
||||
{
|
||||
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
|
||||
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
|
||||
unsigned long long alen;
|
||||
int n, rem;
|
||||
|
||||
/* If already processed pt/ct then error */
|
||||
if (kma->tpcl != 0)
|
||||
return 0;
|
||||
|
||||
/* update the total aad length */
|
||||
alen = kma->taadl + len;
|
||||
if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len))
|
||||
return 0;
|
||||
kma->taadl = alen;
|
||||
|
||||
/* check if there is any existing aad data from a previous add */
|
||||
n = actx->plat.s390x.areslen;
|
||||
if (n) {
|
||||
/* add additional data to a buffer until it has 16 bytes */
|
||||
while (n && len) {
|
||||
actx->plat.s390x.ares[n] = *aad;
|
||||
++aad;
|
||||
--len;
|
||||
n = (n + 1) & 0xf;
|
||||
}
|
||||
/* ctx->ares contains a complete block if offset has wrapped around */
|
||||
if (!n) {
|
||||
s390x_kma(actx->plat.s390x.ares, 16, NULL, 0, NULL,
|
||||
actx->plat.s390x.fc, kma);
|
||||
actx->plat.s390x.fc |= S390X_KMA_HS;
|
||||
}
|
||||
actx->plat.s390x.areslen = n;
|
||||
}
|
||||
|
||||
/* If there are leftover bytes (< 128 bits) save them for next time */
|
||||
rem = len & 0xf;
|
||||
/* Add any remaining 16 byte blocks (128 bit each) */
|
||||
len &= ~(size_t)0xf;
|
||||
if (len) {
|
||||
s390x_kma(aad, len, NULL, 0, NULL, actx->plat.s390x.fc, kma);
|
||||
actx->plat.s390x.fc |= S390X_KMA_HS;
|
||||
aad += len;
|
||||
}
|
||||
|
||||
if (rem) {
|
||||
actx->plat.s390x.areslen = rem;
|
||||
|
||||
do {
|
||||
--rem;
|
||||
actx->plat.s390x.ares[rem] = aad[rem];
|
||||
} while (rem);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* En/de-crypt plain/cipher-text and authenticate ciphertext. Returns 1 for
|
||||
* success. Code is big-endian.
|
||||
*/
|
||||
static int s390x_aes_gcm_cipher_update(PROV_GCM_CTX *ctx,
|
||||
const unsigned char *in, size_t len,
|
||||
unsigned char *out)
|
||||
{
|
||||
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
|
||||
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
|
||||
const unsigned char *inptr;
|
||||
unsigned long long mlen;
|
||||
union {
|
||||
unsigned int w[4];
|
||||
unsigned char b[16];
|
||||
} buf;
|
||||
size_t inlen;
|
||||
int n, rem, i;
|
||||
|
||||
mlen = kma->tpcl + len;
|
||||
if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
|
||||
return 0;
|
||||
kma->tpcl = mlen;
|
||||
|
||||
n = actx->plat.s390x.mreslen;
|
||||
if (n) {
|
||||
inptr = in;
|
||||
inlen = len;
|
||||
while (n && inlen) {
|
||||
actx->plat.s390x.mres[n] = *inptr;
|
||||
n = (n + 1) & 0xf;
|
||||
++inptr;
|
||||
--inlen;
|
||||
}
|
||||
/* ctx->mres contains a complete block if offset has wrapped around */
|
||||
if (!n) {
|
||||
s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen,
|
||||
actx->plat.s390x.mres, 16, buf.b,
|
||||
actx->plat.s390x.fc | S390X_KMA_LAAD, kma);
|
||||
actx->plat.s390x.fc |= S390X_KMA_HS;
|
||||
actx->plat.s390x.areslen = 0;
|
||||
|
||||
/* previous call already encrypted/decrypted its remainder,
|
||||
* see comment below */
|
||||
n = actx->plat.s390x.mreslen;
|
||||
while (n) {
|
||||
*out = buf.b[n];
|
||||
n = (n + 1) & 0xf;
|
||||
++out;
|
||||
++in;
|
||||
--len;
|
||||
}
|
||||
actx->plat.s390x.mreslen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
rem = len & 0xf;
|
||||
|
||||
len &= ~(size_t)0xf;
|
||||
if (len) {
|
||||
s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen, in, len, out,
|
||||
actx->plat.s390x.fc | S390X_KMA_LAAD, kma);
|
||||
in += len;
|
||||
out += len;
|
||||
actx->plat.s390x.fc |= S390X_KMA_HS;
|
||||
actx->plat.s390x.areslen = 0;
|
||||
}
|
||||
|
||||
/*-
|
||||
* If there is a remainder, it has to be saved such that it can be
|
||||
* processed by kma later. However, we also have to do the for-now
|
||||
* unauthenticated encryption/decryption part here and now...
|
||||
*/
|
||||
if (rem) {
|
||||
if (!actx->plat.s390x.mreslen) {
|
||||
buf.w[0] = kma->j0.w[0];
|
||||
buf.w[1] = kma->j0.w[1];
|
||||
buf.w[2] = kma->j0.w[2];
|
||||
buf.w[3] = kma->cv.w + 1;
|
||||
s390x_km(buf.b, 16, actx->plat.s390x.kres,
|
||||
actx->plat.s390x.fc & 0x1f, &kma->k);
|
||||
}
|
||||
|
||||
n = actx->plat.s390x.mreslen;
|
||||
for (i = 0; i < rem; i++) {
|
||||
actx->plat.s390x.mres[n + i] = in[i];
|
||||
out[i] = in[i] ^ actx->plat.s390x.kres[n + i];
|
||||
}
|
||||
actx->plat.s390x.mreslen += rem;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const PROV_GCM_HW s390x_aes_gcm = {
|
||||
s390x_aes_gcm_initkey,
|
||||
s390x_aes_gcm_setiv,
|
||||
s390x_aes_gcm_aad_update,
|
||||
s390x_aes_gcm_cipher_update,
|
||||
s390x_aes_gcm_cipher_final,
|
||||
s390x_aes_gcm_one_shot
|
||||
};
|
||||
|
||||
const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits)
|
||||
{
|
||||
if ((keybits == 128 && S390X_aes_128_gcm_CAPABLE)
|
||||
|| (keybits == 192 && S390X_aes_192_gcm_CAPABLE)
|
||||
|| (keybits == 256 && S390X_aes_256_gcm_CAPABLE))
|
||||
return &s390x_aes_gcm;
|
||||
return &aes_gcm;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Fujitsu SPARC64 X support for AES GCM.
|
||||
* This file is included by cipher_gcm_hw.c
|
||||
*/
|
||||
|
||||
static int t4_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
ctr128_f ctr;
|
||||
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
|
||||
AES_KEY *ks = &actx->ks.ks;
|
||||
|
||||
|
||||
switch (keylen) {
|
||||
case 16:
|
||||
ctr = (ctr128_f)aes128_t4_ctr32_encrypt;
|
||||
break;
|
||||
case 24:
|
||||
ctr = (ctr128_f)aes192_t4_ctr32_encrypt;
|
||||
break;
|
||||
case 32:
|
||||
ctr = (ctr128_f)aes256_t4_ctr32_encrypt;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
GCM_HW_SET_KEY_CTR_FN(ks, aes_t4_set_encrypt_key, aes_t4_encrypt, ctr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const PROV_GCM_HW t4_aes_gcm = {
|
||||
t4_aes_gcm_initkey,
|
||||
gcm_setiv,
|
||||
gcm_aad_update,
|
||||
gcm_cipher_update,
|
||||
gcm_cipher_final,
|
||||
gcm_one_shot
|
||||
};
|
||||
const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits)
|
||||
{
|
||||
return SPARC_AES_CAPABLE ? &t4_aes_gcm : &aes_gcm;
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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 "cipher_aes.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
static int cipher_hw_aes_initkey(PROV_CIPHER_CTX *dat,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
int ret;
|
||||
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
||||
AES_KEY *ks = &adat->ks.ks;
|
||||
|
||||
dat->ks = ks;
|
||||
|
||||
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
|
||||
&& !dat->enc) {
|
||||
#ifdef HWAES_CAPABLE
|
||||
if (HWAES_CAPABLE) {
|
||||
ret = HWAES_set_decrypt_key(key, keylen * 8, ks);
|
||||
dat->block = (block128_f)HWAES_decrypt;
|
||||
dat->stream.cbc = NULL;
|
||||
# ifdef HWAES_cbc_encrypt
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
|
||||
# endif
|
||||
} else
|
||||
#endif
|
||||
#ifdef BSAES_CAPABLE
|
||||
if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CBC_MODE) {
|
||||
ret = AES_set_decrypt_key(key, keylen * 8, ks);
|
||||
dat->block = (block128_f)AES_decrypt;
|
||||
dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt;
|
||||
} else
|
||||
#endif
|
||||
#ifdef VPAES_CAPABLE
|
||||
if (VPAES_CAPABLE) {
|
||||
ret = vpaes_set_decrypt_key(key, keylen * 8, ks);
|
||||
dat->block = (block128_f)vpaes_decrypt;
|
||||
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
?(cbc128_f)vpaes_cbc_encrypt : NULL;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = AES_set_decrypt_key(key, keylen * 8, ks);
|
||||
dat->block = (block128_f)AES_decrypt;
|
||||
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
? (cbc128_f)AES_cbc_encrypt : NULL;
|
||||
}
|
||||
} else
|
||||
#ifdef HWAES_CAPABLE
|
||||
if (HWAES_CAPABLE) {
|
||||
ret = HWAES_set_encrypt_key(key, keylen * 8, ks);
|
||||
dat->block = (block128_f)HWAES_encrypt;
|
||||
dat->stream.cbc = NULL;
|
||||
# ifdef HWAES_cbc_encrypt
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
|
||||
else
|
||||
# endif
|
||||
# ifdef HWAES_ctr32_encrypt_blocks
|
||||
if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks;
|
||||
else
|
||||
# endif
|
||||
(void)0; /* terminate potentially open 'else' */
|
||||
} else
|
||||
#endif
|
||||
#ifdef BSAES_CAPABLE
|
||||
if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CTR_MODE) {
|
||||
ret = AES_set_encrypt_key(key, keylen * 8, ks);
|
||||
dat->block = (block128_f)AES_encrypt;
|
||||
dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks;
|
||||
} else
|
||||
#endif
|
||||
#ifdef VPAES_CAPABLE
|
||||
if (VPAES_CAPABLE) {
|
||||
ret = vpaes_set_encrypt_key(key, keylen * 8, ks);
|
||||
dat->block = (block128_f)vpaes_encrypt;
|
||||
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
? (cbc128_f)vpaes_cbc_encrypt : NULL;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = AES_set_encrypt_key(key, keylen * 8, ks);
|
||||
dat->block = (block128_f)AES_encrypt;
|
||||
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
? (cbc128_f)AES_cbc_encrypt : NULL;
|
||||
#ifdef AES_CTR_ASM
|
||||
if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)AES_ctr32_encrypt;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_AES_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define PROV_CIPHER_HW_aes_mode(mode) \
|
||||
static const PROV_CIPHER_HW aes_##mode = { \
|
||||
cipher_hw_aes_initkey, \
|
||||
cipher_hw_generic_##mode \
|
||||
}; \
|
||||
PROV_CIPHER_HW_declare(mode) \
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_##mode(size_t keybits) \
|
||||
{ \
|
||||
PROV_CIPHER_HW_select(mode) \
|
||||
return &aes_##mode; \
|
||||
}
|
||||
|
||||
#if defined(AESNI_CAPABLE)
|
||||
# include "cipher_aes_hw_aesni.inc"
|
||||
#elif defined(SPARC_AES_CAPABLE)
|
||||
# include "cipher_aes_hw_t4.inc"
|
||||
#elif defined(S390X_aes_128_CAPABLE)
|
||||
# include "cipher_aes_hw_s390x.inc"
|
||||
#else
|
||||
/* The generic case */
|
||||
# define PROV_CIPHER_HW_declare(mode)
|
||||
# define PROV_CIPHER_HW_select(mode)
|
||||
#endif
|
||||
|
||||
PROV_CIPHER_HW_aes_mode(cbc)
|
||||
PROV_CIPHER_HW_aes_mode(ecb)
|
||||
PROV_CIPHER_HW_aes_mode(ofb128)
|
||||
PROV_CIPHER_HW_aes_mode(cfb128)
|
||||
PROV_CIPHER_HW_aes_mode(cfb1)
|
||||
PROV_CIPHER_HW_aes_mode(cfb8)
|
||||
PROV_CIPHER_HW_aes_mode(ctr)
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*-
|
||||
* AES-NI support for AES modes ecb, cbc, ofb, cfb, ctr.
|
||||
* This file is included by cipher_aes_hw.c
|
||||
*/
|
||||
|
||||
#define cipher_hw_aesni_ofb128 cipher_hw_generic_ofb128
|
||||
#define cipher_hw_aesni_cfb128 cipher_hw_generic_cfb128
|
||||
#define cipher_hw_aesni_cfb8 cipher_hw_generic_cfb8
|
||||
#define cipher_hw_aesni_cfb1 cipher_hw_generic_cfb1
|
||||
#define cipher_hw_aesni_ctr cipher_hw_generic_ctr
|
||||
|
||||
static int cipher_hw_aesni_initkey(PROV_CIPHER_CTX *dat,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
int ret;
|
||||
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
||||
AES_KEY *ks = &adat->ks.ks;
|
||||
|
||||
dat->ks = ks;
|
||||
|
||||
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
|
||||
&& !dat->enc) {
|
||||
ret = aesni_set_decrypt_key(key, keylen * 8, ks);
|
||||
dat->block = (block128_f) aesni_decrypt;
|
||||
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f) aesni_cbc_encrypt : NULL;
|
||||
} else {
|
||||
ret = aesni_set_encrypt_key(key, keylen * 8, ks);
|
||||
dat->block = (block128_f) aesni_encrypt;
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt;
|
||||
else if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_AES_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cipher_hw_aesni_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
const AES_KEY *ks = ctx->ks;
|
||||
|
||||
aesni_cbc_encrypt(in, out, len, ks, ctx->iv, ctx->enc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cipher_hw_aesni_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
if (len < ctx->blocksize)
|
||||
return 1;
|
||||
|
||||
aesni_ecb_encrypt(in, out, len, ctx->ks, ctx->enc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define PROV_CIPHER_HW_declare(mode) \
|
||||
static const PROV_CIPHER_HW aesni_##mode = { \
|
||||
cipher_hw_aesni_initkey, \
|
||||
cipher_hw_aesni_##mode \
|
||||
};
|
||||
#define PROV_CIPHER_HW_select(mode) \
|
||||
if (AESNI_CAPABLE) \
|
||||
return &aesni_##mode;
|
||||
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* IBM S390X support for AES modes ecb, cbc, ofb, cfb, ctr.
|
||||
* This file is included by cipher_aes_hw.c
|
||||
*/
|
||||
|
||||
#include "s390x_arch.h"
|
||||
|
||||
#define s390x_aes_cbc_initkey cipher_hw_aes_initkey
|
||||
#define s390x_aes_cfb1_initkey cipher_hw_aes_initkey
|
||||
#define s390x_aes_ctr_initkey cipher_hw_aes_initkey
|
||||
#define s390x_aes_cbc_cipher_hw cipher_hw_generic_cbc
|
||||
#define s390x_aes_cfb1_cipher_hw cipher_hw_generic_cfb1
|
||||
#define s390x_aes_ctr_cipher_hw cipher_hw_generic_ctr
|
||||
|
||||
#define S390X_aes_128_ofb128_CAPABLE S390X_aes_128_ofb_CAPABLE
|
||||
#define S390X_aes_192_ofb128_CAPABLE S390X_aes_192_ofb_CAPABLE
|
||||
#define S390X_aes_256_ofb128_CAPABLE S390X_aes_256_ofb_CAPABLE
|
||||
#define S390X_aes_128_cfb128_CAPABLE S390X_aes_128_cfb_CAPABLE
|
||||
#define S390X_aes_192_cfb128_CAPABLE S390X_aes_192_cfb_CAPABLE
|
||||
#define S390X_aes_256_cfb128_CAPABLE S390X_aes_256_cfb_CAPABLE
|
||||
|
||||
static int s390x_aes_ecb_initkey(PROV_CIPHER_CTX *dat,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
||||
|
||||
adat->plat.s390x.fc = S390X_AES_FC(keylen);
|
||||
if (!dat->enc)
|
||||
adat->plat.s390x.fc |= S390X_DECRYPT;
|
||||
|
||||
memcpy(adat->plat.s390x.param.km.k, key, keylen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_ecb_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
||||
|
||||
s390x_km(in, len, out, adat->plat.s390x.fc, &adat->plat.s390x.param.km);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_ofb128_initkey(PROV_CIPHER_CTX *dat,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
||||
|
||||
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
|
||||
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
|
||||
adat->plat.s390x.fc = S390X_AES_FC(keylen);
|
||||
adat->plat.s390x.res = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_ofb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
||||
int n = adat->plat.s390x.res;
|
||||
int rem;
|
||||
|
||||
while (n && len) {
|
||||
*out = *in ^ adat->plat.s390x.param.kmo_kmf.cv[n];
|
||||
n = (n + 1) & 0xf;
|
||||
--len;
|
||||
++in;
|
||||
++out;
|
||||
}
|
||||
|
||||
rem = len & 0xf;
|
||||
|
||||
len &= ~(size_t)0xf;
|
||||
if (len) {
|
||||
s390x_kmo(in, len, out, adat->plat.s390x.fc,
|
||||
&adat->plat.s390x.param.kmo_kmf);
|
||||
|
||||
out += len;
|
||||
in += len;
|
||||
}
|
||||
|
||||
if (rem) {
|
||||
s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16,
|
||||
adat->plat.s390x.param.kmo_kmf.cv, adat->plat.s390x.fc,
|
||||
adat->plat.s390x.param.kmo_kmf.k);
|
||||
|
||||
while (rem--) {
|
||||
out[n] = in[n] ^ adat->plat.s390x.param.kmo_kmf.cv[n];
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
adat->plat.s390x.res = n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_cfb128_initkey(PROV_CIPHER_CTX *dat,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
||||
|
||||
adat->plat.s390x.fc = S390X_AES_FC(keylen);
|
||||
adat->plat.s390x.fc |= 16 << 24; /* 16 bytes cipher feedback */
|
||||
if (!dat->enc)
|
||||
adat->plat.s390x.fc |= S390X_DECRYPT;
|
||||
|
||||
adat->plat.s390x.res = 0;
|
||||
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
|
||||
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_cfb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
||||
int n = adat->plat.s390x.res;
|
||||
int rem;
|
||||
unsigned char tmp;
|
||||
|
||||
while (n && len) {
|
||||
tmp = *in;
|
||||
*out = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
|
||||
adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp;
|
||||
n = (n + 1) & 0xf;
|
||||
--len;
|
||||
++in;
|
||||
++out;
|
||||
}
|
||||
|
||||
rem = len & 0xf;
|
||||
|
||||
len &= ~(size_t)0xf;
|
||||
if (len) {
|
||||
s390x_kmf(in, len, out, adat->plat.s390x.fc,
|
||||
&adat->plat.s390x.param.kmo_kmf);
|
||||
|
||||
out += len;
|
||||
in += len;
|
||||
}
|
||||
|
||||
if (rem) {
|
||||
s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16,
|
||||
adat->plat.s390x.param.kmo_kmf.cv,
|
||||
S390X_AES_FC(dat->keylen), adat->plat.s390x.param.kmo_kmf.k);
|
||||
|
||||
while (rem--) {
|
||||
tmp = in[n];
|
||||
out[n] = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
|
||||
adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp;
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
adat->plat.s390x.res = n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_cfb8_initkey(PROV_CIPHER_CTX *dat,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
||||
|
||||
adat->plat.s390x.fc = S390X_AES_FC(keylen);
|
||||
adat->plat.s390x.fc |= 1 << 24; /* 1 byte cipher feedback */
|
||||
if (!dat->enc)
|
||||
adat->plat.s390x.fc |= S390X_DECRYPT;
|
||||
|
||||
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
|
||||
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_cfb8_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
||||
|
||||
s390x_kmf(in, len, out, adat->plat.s390x.fc,
|
||||
&adat->plat.s390x.param.kmo_kmf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define PROV_CIPHER_HW_declare(mode) \
|
||||
static const PROV_CIPHER_HW s390x_aes_##mode = { \
|
||||
s390x_aes_##mode##_initkey, \
|
||||
s390x_aes_##mode##_cipher_hw \
|
||||
};
|
||||
#define PROV_CIPHER_HW_select(mode) \
|
||||
if ((keybits == 128 && S390X_aes_128_##mode##_CAPABLE) \
|
||||
|| (keybits == 192 && S390X_aes_192_##mode##_CAPABLE) \
|
||||
|| (keybits == 256 && S390X_aes_256_##mode##_CAPABLE)) \
|
||||
return &s390x_aes_##mode;
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Sparc t4 support for AES modes ecb, cbc, ofb, cfb, ctr.
|
||||
* This file is included by cipher_aes_hw.c
|
||||
*/
|
||||
|
||||
static int cipher_hw_aes_t4_initkey(PROV_CIPHER_CTX *dat,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
int ret, bits;
|
||||
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
||||
AES_KEY *ks = &adat->ks.ks;
|
||||
|
||||
dat->ks = (const void *)ks; /* used by cipher_hw_generic_XXX */
|
||||
|
||||
bits = keylen * 8;
|
||||
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
|
||||
&& !dat->enc) {
|
||||
ret = 0;
|
||||
aes_t4_set_decrypt_key(key, bits, ks);
|
||||
dat->block = (block128_f)aes_t4_decrypt;
|
||||
switch (bits) {
|
||||
case 128:
|
||||
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f)aes128_t4_cbc_decrypt : NULL;
|
||||
break;
|
||||
case 192:
|
||||
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f)aes192_t4_cbc_decrypt : NULL;
|
||||
break;
|
||||
case 256:
|
||||
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f)aes256_t4_cbc_decrypt : NULL;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
aes_t4_set_encrypt_key(key, bits, ks);
|
||||
dat->block = (block128_f)aes_t4_encrypt;
|
||||
switch (bits) {
|
||||
case 128:
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)aes128_t4_cbc_encrypt;
|
||||
else if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)aes128_t4_ctr32_encrypt;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
break;
|
||||
case 192:
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)aes192_t4_cbc_encrypt;
|
||||
else if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)aes192_t4_ctr32_encrypt;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
break;
|
||||
case 256:
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)aes256_t4_cbc_encrypt;
|
||||
else if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)aes256_t4_ctr32_encrypt;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_AES_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define PROV_CIPHER_HW_declare(mode) \
|
||||
static const PROV_CIPHER_HW aes_t4_##mode = { \
|
||||
cipher_hw_aes_t4_initkey, \
|
||||
cipher_hw_generic_##mode \
|
||||
};
|
||||
#define PROV_CIPHER_HW_select(mode) \
|
||||
if (SPARC_AES_CAPABLE) \
|
||||
return &aes_t4_##mode;
|
||||
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* 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 "cipher_aes.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
/* AES wrap with padding has IV length of 4, without padding 8 */
|
||||
#define AES_WRAP_PAD_IVLEN 4
|
||||
#define AES_WRAP_NOPAD_IVLEN 8
|
||||
|
||||
/* TODO(3.0) Figure out what flags need to be passed */
|
||||
#define WRAP_FLAGS (EVP_CIPH_WRAP_MODE \
|
||||
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
|
||||
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_FLAG_DEFAULT_ASN1)
|
||||
|
||||
typedef size_t (*aeswrap_fn)(void *key, const unsigned char *iv,
|
||||
unsigned char *out, const unsigned char *in,
|
||||
size_t inlen, block128_f block);
|
||||
|
||||
static OSSL_OP_cipher_encrypt_init_fn aes_wrap_einit;
|
||||
static OSSL_OP_cipher_decrypt_init_fn aes_wrap_dinit;
|
||||
static OSSL_OP_cipher_update_fn aes_wrap_cipher;
|
||||
static OSSL_OP_cipher_final_fn aes_wrap_final;
|
||||
static OSSL_OP_cipher_freectx_fn aes_wrap_freectx;
|
||||
|
||||
typedef struct prov_aes_wrap_ctx_st {
|
||||
PROV_CIPHER_CTX base;
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
AES_KEY ks;
|
||||
} ks;
|
||||
unsigned int iv_set : 1;
|
||||
aeswrap_fn wrapfn;
|
||||
|
||||
} PROV_AES_WRAP_CTX;
|
||||
|
||||
|
||||
static void *aes_wrap_newctx(size_t kbits, size_t blkbits,
|
||||
size_t ivbits, unsigned int mode, uint64_t flags)
|
||||
{
|
||||
PROV_AES_WRAP_CTX *wctx = OPENSSL_zalloc(sizeof(*wctx));
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)wctx;
|
||||
|
||||
if (ctx != NULL) {
|
||||
cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
|
||||
NULL, NULL);
|
||||
ctx->pad = (ctx->ivlen == AES_WRAP_PAD_IVLEN);
|
||||
}
|
||||
return wctx;
|
||||
}
|
||||
|
||||
static void aes_wrap_freectx(void *vctx)
|
||||
{
|
||||
PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
|
||||
OPENSSL_cleanse(ctx->iv, sizeof(ctx->iv));
|
||||
OPENSSL_clear_free(wctx, sizeof(*wctx));
|
||||
}
|
||||
|
||||
static int aes_wrap_init(void *vctx, const unsigned char *key,
|
||||
size_t keylen, const unsigned char *iv,
|
||||
size_t ivlen, int enc)
|
||||
{
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
|
||||
|
||||
ctx->enc = enc;
|
||||
ctx->block = enc ? (block128_f)AES_encrypt : (block128_f)AES_decrypt;
|
||||
if (ctx->pad)
|
||||
wctx->wrapfn = enc ? CRYPTO_128_wrap_pad : CRYPTO_128_unwrap_pad;
|
||||
else
|
||||
wctx->wrapfn = enc ? CRYPTO_128_wrap : CRYPTO_128_unwrap;
|
||||
|
||||
if (iv != NULL) {
|
||||
ctx->ivlen = ivlen;
|
||||
memcpy(ctx->iv, iv, ivlen);
|
||||
wctx->iv_set = 1;
|
||||
}
|
||||
if (key != NULL) {
|
||||
if (keylen != ctx->keylen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if (ctx->enc)
|
||||
AES_set_encrypt_key(key, keylen * 8, &wctx->ks.ks);
|
||||
else
|
||||
AES_set_decrypt_key(key, keylen * 8, &wctx->ks.ks);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_wrap_einit(void *ctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return aes_wrap_init(ctx, key, keylen, iv, ivlen, 1);
|
||||
}
|
||||
|
||||
static int aes_wrap_dinit(void *ctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return aes_wrap_init(ctx, key, keylen, iv, ivlen, 0);
|
||||
}
|
||||
|
||||
static int aes_wrap_cipher_internal(void *vctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inlen)
|
||||
{
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
|
||||
size_t rv;
|
||||
int pad = ctx->pad;
|
||||
|
||||
/* No final operation so always return zero length */
|
||||
if (in == NULL)
|
||||
return 0;
|
||||
|
||||
/* Input length must always be non-zero */
|
||||
if (inlen == 0)
|
||||
return -1;
|
||||
|
||||
/* If decrypting need at least 16 bytes and multiple of 8 */
|
||||
if (!ctx->enc && (inlen < 16 || inlen & 0x7))
|
||||
return -1;
|
||||
|
||||
/* If not padding input must be multiple of 8 */
|
||||
if (!pad && inlen & 0x7)
|
||||
return -1;
|
||||
|
||||
if (out == NULL) {
|
||||
if (ctx->enc) {
|
||||
/* If padding round up to multiple of 8 */
|
||||
if (pad)
|
||||
inlen = (inlen + 7) / 8 * 8;
|
||||
/* 8 byte prefix */
|
||||
return inlen + 8;
|
||||
} else {
|
||||
/*
|
||||
* If not padding output will be exactly 8 bytes smaller than
|
||||
* input. If padding it will be at least 8 bytes smaller but we
|
||||
* don't know how much.
|
||||
*/
|
||||
return inlen - 8;
|
||||
}
|
||||
}
|
||||
|
||||
rv = wctx->wrapfn(&wctx->ks.ks, wctx->iv_set ? ctx->iv : NULL, out, in,
|
||||
inlen, ctx->block);
|
||||
return rv ? (int)rv : -1;
|
||||
}
|
||||
|
||||
static int aes_wrap_final(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
*outl = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_wrap_cipher(void *vctx,
|
||||
unsigned char *out, size_t *outl, size_t outsize,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
PROV_AES_WRAP_CTX *ctx = (PROV_AES_WRAP_CTX *)vctx;
|
||||
size_t len;
|
||||
|
||||
if (outsize < inl) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = aes_wrap_cipher_internal(ctx, out, in, inl);
|
||||
if (len == 0)
|
||||
return -1;
|
||||
|
||||
*outl = len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_wrap_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
const OSSL_PARAM *p;
|
||||
size_t keylen = 0;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
|
||||
if (p != NULL) {
|
||||
if (!OSSL_PARAM_get_size_t(p, &keylen)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
if (ctx->keylen != keylen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IMPLEMENT_cipher(mode, fname, UCMODE, flags, kbits, blkbits, ivbits) \
|
||||
static OSSL_OP_cipher_get_params_fn aes_##kbits##_##fname##_get_params; \
|
||||
static int aes_##kbits##_##fname##_get_params(OSSL_PARAM params[]) \
|
||||
{ \
|
||||
return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
|
||||
flags, kbits, blkbits, ivbits); \
|
||||
} \
|
||||
static OSSL_OP_cipher_newctx_fn aes_##kbits##fname##_newctx; \
|
||||
static void *aes_##kbits##fname##_newctx(void *provctx) \
|
||||
{ \
|
||||
return aes_##mode##_newctx(kbits, blkbits, ivbits, \
|
||||
EVP_CIPH_##UCMODE##_MODE, flags); \
|
||||
} \
|
||||
const OSSL_DISPATCH aes##kbits##fname##_functions[] = { \
|
||||
{ OSSL_FUNC_CIPHER_NEWCTX, \
|
||||
(void (*)(void))aes_##kbits##fname##_newctx }, \
|
||||
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit }, \
|
||||
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_##mode##_dinit }, \
|
||||
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_cipher }, \
|
||||
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_final }, \
|
||||
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx }, \
|
||||
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
|
||||
(void (*)(void))aes_##kbits##_##fname##_get_params }, \
|
||||
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
|
||||
(void (*)(void))cipher_generic_gettable_params }, \
|
||||
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
|
||||
(void (*)(void))cipher_generic_get_ctx_params }, \
|
||||
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
|
||||
(void (*)(void))aes_wrap_set_ctx_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 }, \
|
||||
{ 0, NULL } \
|
||||
}
|
||||
|
||||
IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
|
||||
IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
|
||||
IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
|
||||
IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_PAD_IVLEN * 8);
|
||||
IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_PAD_IVLEN * 8);
|
||||
IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_PAD_IVLEN * 8);
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* 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 "cipher_aes_xts.h"
|
||||
#include "internal/provider_algs.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
/* TODO (3.0) Figure out what flags need to be set */
|
||||
#define AES_XTS_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV \
|
||||
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
|
||||
| EVP_CIPH_CUSTOM_COPY)
|
||||
|
||||
#define AES_XTS_IV_BITS 128
|
||||
#define AES_XTS_BLOCK_BITS 8
|
||||
|
||||
#ifdef FIPS_MODE
|
||||
static const int allow_insecure_decrypt = 0;
|
||||
#else
|
||||
static const int allow_insecure_decrypt = 1;
|
||||
#endif /* FIPS_MODE */
|
||||
|
||||
/* forward declarations */
|
||||
static OSSL_OP_cipher_encrypt_init_fn aes_xts_einit;
|
||||
static OSSL_OP_cipher_decrypt_init_fn aes_xts_dinit;
|
||||
static OSSL_OP_cipher_update_fn aes_xts_stream_update;
|
||||
static OSSL_OP_cipher_final_fn aes_xts_stream_final;
|
||||
static OSSL_OP_cipher_cipher_fn aes_xts_cipher;
|
||||
static OSSL_OP_cipher_freectx_fn aes_xts_freectx;
|
||||
static OSSL_OP_cipher_dupctx_fn aes_xts_dupctx;
|
||||
static OSSL_OP_cipher_set_ctx_params_fn aes_xts_set_ctx_params;
|
||||
static OSSL_OP_cipher_settable_ctx_params_fn aes_xts_settable_ctx_params;
|
||||
|
||||
/*
|
||||
* Verify that the two keys are different.
|
||||
*
|
||||
* This addresses the vulnerability described in Rogaway's
|
||||
* September 2004 paper:
|
||||
*
|
||||
* "Efficient Instantiations of Tweakable Blockciphers and
|
||||
* Refinements to Modes OCB and PMAC".
|
||||
* (http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf)
|
||||
*
|
||||
* FIPS 140-2 IG A.9 XTS-AES Key Generation Requirements states
|
||||
* that:
|
||||
* "The check for Key_1 != Key_2 shall be done at any place
|
||||
* BEFORE using the keys in the XTS-AES algorithm to process
|
||||
* data with them."
|
||||
*/
|
||||
static int aes_xts_check_keys_differ(const unsigned char *key, size_t bytes,
|
||||
int enc)
|
||||
{
|
||||
if ((!allow_insecure_decrypt || enc)
|
||||
&& CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DUPLICATED_KEYS);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Provider dispatch functions
|
||||
*/
|
||||
static int aes_xts_init(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen, int enc)
|
||||
{
|
||||
PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)vctx;
|
||||
PROV_CIPHER_CTX *ctx = &xctx->base;
|
||||
|
||||
ctx->enc = enc;
|
||||
|
||||
if (iv != NULL) {
|
||||
if (ivlen != ctx->ivlen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
memcpy(ctx->iv, iv, ivlen);
|
||||
xctx->iv_set = 1;
|
||||
}
|
||||
if (key != NULL) {
|
||||
if (keylen != ctx->keylen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if (!aes_xts_check_keys_differ(key, keylen / 2, enc))
|
||||
return 0;
|
||||
return ctx->hw->init(ctx, key, keylen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_xts_einit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return aes_xts_init(vctx, key, keylen, iv, ivlen, 1);
|
||||
}
|
||||
|
||||
static int aes_xts_dinit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return aes_xts_init(vctx, key, keylen, iv, ivlen, 0);
|
||||
}
|
||||
|
||||
static void *aes_xts_newctx(void *provctx, unsigned int mode, uint64_t flags,
|
||||
size_t kbits, size_t blkbits, size_t ivbits)
|
||||
{
|
||||
PROV_AES_XTS_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx != NULL) {
|
||||
cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits, mode, flags,
|
||||
PROV_CIPHER_HW_aes_xts(kbits), NULL);
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void aes_xts_freectx(void *vctx)
|
||||
{
|
||||
PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
|
||||
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void *aes_xts_dupctx(void *vctx)
|
||||
{
|
||||
PROV_AES_XTS_CTX *in = (PROV_AES_XTS_CTX *)vctx;
|
||||
PROV_AES_XTS_CTX *ret = NULL;
|
||||
|
||||
if (in->xts.key1 != NULL) {
|
||||
if (in->xts.key1 != &in->ks1)
|
||||
return NULL;
|
||||
}
|
||||
if (in->xts.key2 != NULL) {
|
||||
if (in->xts.key2 != &in->ks2)
|
||||
return NULL;
|
||||
}
|
||||
ret = OPENSSL_malloc(sizeof(*ret));
|
||||
if (ret == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
*ret = *in;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize, const unsigned char *in, size_t inl)
|
||||
{
|
||||
PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
|
||||
|
||||
if (ctx->xts.key1 == NULL
|
||||
|| ctx->xts.key2 == NULL
|
||||
|| !ctx->iv_set
|
||||
|| out == NULL
|
||||
|| in == NULL
|
||||
|| inl < AES_BLOCK_SIZE)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Impose a limit of 2^20 blocks per data unit as specifed 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.
|
||||
*/
|
||||
if (inl > XTS_MAX_BLOCKS_PER_DATA_UNIT * AES_BLOCK_SIZE) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->stream != NULL)
|
||||
(*ctx->stream)(in, out, inl, ctx->xts.key1, ctx->xts.key2, ctx->base.iv);
|
||||
else if (CRYPTO_xts128_encrypt(&ctx->xts, ctx->base.iv, in, out, inl,
|
||||
ctx->base.enc))
|
||||
return 0;
|
||||
|
||||
*outl = inl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_xts_stream_update(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize, const unsigned char *in,
|
||||
size_t inl)
|
||||
{
|
||||
PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
|
||||
|
||||
if (outsize < inl) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!aes_xts_cipher(ctx, out, outl, outsize, in, inl)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_xts_stream_final(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
*outl = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM aes_xts_known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static const OSSL_PARAM *aes_xts_settable_ctx_params(void)
|
||||
{
|
||||
return aes_xts_known_settable_ctx_params;
|
||||
}
|
||||
|
||||
static int aes_xts_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
/*
|
||||
* TODO(3.0) 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);
|
||||
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 xts mode */
|
||||
if (keylen != ctx->keylen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IMPLEMENT_cipher(lcmode, UCMODE, kbits, flags) \
|
||||
static OSSL_OP_cipher_get_params_fn aes_##kbits##_##lcmode##_get_params; \
|
||||
static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
|
||||
{ \
|
||||
return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
|
||||
flags, 2 * kbits, AES_XTS_BLOCK_BITS, \
|
||||
AES_XTS_IV_BITS); \
|
||||
} \
|
||||
static OSSL_OP_cipher_newctx_fn aes_##kbits##_xts_newctx; \
|
||||
static void *aes_##kbits##_xts_newctx(void *provctx) \
|
||||
{ \
|
||||
return aes_xts_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, flags, 2 * kbits, \
|
||||
AES_XTS_BLOCK_BITS, AES_XTS_IV_BITS); \
|
||||
} \
|
||||
const OSSL_DISPATCH aes##kbits##xts_functions[] = { \
|
||||
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##kbits##_xts_newctx }, \
|
||||
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_xts_einit }, \
|
||||
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_xts_dinit }, \
|
||||
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_xts_stream_update }, \
|
||||
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_xts_stream_final }, \
|
||||
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_xts_cipher }, \
|
||||
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_xts_freectx }, \
|
||||
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_xts_dupctx }, \
|
||||
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
|
||||
(void (*)(void))aes_##kbits##_##lcmode##_get_params }, \
|
||||
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
|
||||
(void (*)(void))cipher_generic_gettable_params }, \
|
||||
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
|
||||
(void (*)(void))cipher_generic_get_ctx_params }, \
|
||||
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
|
||||
(void (*)(void))cipher_generic_gettable_ctx_params }, \
|
||||
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
|
||||
(void (*)(void))aes_xts_set_ctx_params }, \
|
||||
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
|
||||
(void (*)(void))aes_xts_settable_ctx_params }, \
|
||||
{ 0, NULL } \
|
||||
}
|
||||
|
||||
IMPLEMENT_cipher(xts, XTS, 256, AES_XTS_FLAGS);
|
||||
IMPLEMENT_cipher(xts, XTS, 128, AES_XTS_FLAGS);
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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 "internal/ciphers/ciphercommon.h"
|
||||
|
||||
PROV_CIPHER_FUNC(void, xts_stream,
|
||||
(const unsigned char *in, unsigned char *out, size_t len,
|
||||
const AES_KEY *key1, const AES_KEY *key2,
|
||||
const unsigned char iv[16]));
|
||||
|
||||
typedef struct prov_aes_xts_ctx_st {
|
||||
PROV_CIPHER_CTX base; /* Must be first */
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
AES_KEY ks;
|
||||
} ks1, ks2; /* AES key schedules to use */
|
||||
XTS128_CONTEXT xts;
|
||||
OSSL_xts_stream_fn stream;
|
||||
unsigned int iv_set : 1; /* Set if an iv is set */
|
||||
} PROV_AES_XTS_CTX;
|
||||
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_xts(size_t keybits);
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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 "cipher_aes_xts.h"
|
||||
|
||||
#define XTS_SET_KEY_FN(fn_set_enc_key, fn_set_dec_key, \
|
||||
fn_block_enc, fn_block_dec, \
|
||||
fn_stream_enc, fn_stream_dec) { \
|
||||
size_t bytes = keylen / 2; \
|
||||
size_t bits = bytes * 8; \
|
||||
\
|
||||
if (ctx->enc) { \
|
||||
fn_set_enc_key(key, bits, &xctx->ks1.ks); \
|
||||
xctx->xts.block1 = (block128_f)fn_block_enc; \
|
||||
} else { \
|
||||
fn_set_dec_key(key, bits, &xctx->ks1.ks); \
|
||||
xctx->xts.block1 = (block128_f)fn_block_dec; \
|
||||
} \
|
||||
fn_set_enc_key(key + bytes, bits, &xctx->ks2.ks); \
|
||||
xctx->xts.block2 = (block128_f)fn_block_enc; \
|
||||
xctx->xts.key1 = &xctx->ks1; \
|
||||
xctx->xts.key2 = &xctx->ks2; \
|
||||
xctx->stream = ctx->enc ? fn_stream_enc : fn_stream_dec; \
|
||||
}
|
||||
|
||||
static int cipher_hw_aes_xts_generic_initkey(PROV_CIPHER_CTX *ctx,
|
||||
const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx;
|
||||
OSSL_xts_stream_fn stream_enc = NULL;
|
||||
OSSL_xts_stream_fn stream_dec = NULL;
|
||||
|
||||
#ifdef AES_XTS_ASM
|
||||
stream_enc = AES_xts_encrypt;
|
||||
stream_dec = AES_xts_decrypt;
|
||||
#endif /* AES_XTS_ASM */
|
||||
|
||||
#ifdef HWAES_CAPABLE
|
||||
if (HWAES_CAPABLE) {
|
||||
# ifdef HWAES_xts_encrypt
|
||||
stream_enc = HWAES_xts_encrypt;
|
||||
# endif /* HWAES_xts_encrypt */
|
||||
# ifdef HWAES_xts_decrypt
|
||||
stream_dec = HWAES_xts_decrypt;
|
||||
# endif /* HWAES_xts_decrypt */
|
||||
XTS_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_set_decrypt_key,
|
||||
HWAES_encrypt, HWAES_decrypt,
|
||||
stream_enc, stream_dec);
|
||||
} else
|
||||
#endif /* HWAES_CAPABLE */
|
||||
|
||||
#ifdef BSAES_CAPABLE
|
||||
if (BSAES_CAPABLE) {
|
||||
stream_enc = bsaes_xts_encrypt;
|
||||
stream_dec = bsaes_xts_decrypt;
|
||||
}
|
||||
#endif /* BSAES_CAPABLE */
|
||||
|
||||
#ifdef VPAES_CAPABLE
|
||||
if (VPAES_CAPABLE) {
|
||||
XTS_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_set_decrypt_key,
|
||||
vpaes_encrypt, vpaes_decrypt, stream_enc, stream_dec);
|
||||
} else
|
||||
#endif /* VPAES_CAPABLE */
|
||||
{
|
||||
XTS_SET_KEY_FN(AES_set_encrypt_key, AES_set_decrypt_key,
|
||||
AES_encrypt, AES_decrypt, stream_enc, stream_dec);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(AESNI_CAPABLE)
|
||||
|
||||
static int cipher_hw_aesni_xts_initkey(PROV_CIPHER_CTX *ctx,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx;
|
||||
|
||||
XTS_SET_KEY_FN(aesni_set_encrypt_key, aesni_set_decrypt_key,
|
||||
aesni_encrypt, aesni_decrypt,
|
||||
aesni_xts_encrypt, aesni_xts_decrypt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define PROV_CIPHER_HW_declare_xts() \
|
||||
static const PROV_CIPHER_HW aesni_xts = { \
|
||||
cipher_hw_aesni_xts_initkey, \
|
||||
NULL \
|
||||
};
|
||||
# define PROV_CIPHER_HW_select_xts() \
|
||||
if (AESNI_CAPABLE) \
|
||||
return &aesni_xts;
|
||||
|
||||
# elif defined(SPARC_AES_CAPABLE)
|
||||
|
||||
static int cipher_hw_aes_xts_t4_initkey(PROV_CIPHER_CTX *ctx,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx;
|
||||
OSSL_xts_stream_fn stream_enc = NULL;
|
||||
OSSL_xts_stream_fn stream_dec = NULL;
|
||||
|
||||
/* Note: keylen is the size of 2 keys */
|
||||
switch (keylen) {
|
||||
case 32:
|
||||
stream_enc = aes128_t4_xts_encrypt;
|
||||
stream_dec = aes128_t4_xts_decrypt;
|
||||
break;
|
||||
case 64:
|
||||
stream_enc = aes256_t4_xts_encrypt;
|
||||
stream_dec = aes256_t4_xts_decrypt;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
XTS_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_set_decrypt_key,
|
||||
aes_t4_encrypt, aes_t4_decrypt,
|
||||
stream_enc, stream_dec);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define PROV_CIPHER_HW_declare_xts() \
|
||||
static const PROV_CIPHER_HW aes_xts_t4 = { \
|
||||
cipher_hw_aes_xts_t4_initkey, \
|
||||
NULL \
|
||||
};
|
||||
# define PROV_CIPHER_HW_select_xts() \
|
||||
if (SPARC_AES_CAPABLE) \
|
||||
return &aes_xts_t4;
|
||||
# else
|
||||
/* The generic case */
|
||||
# define PROV_CIPHER_HW_declare_xts()
|
||||
# define PROV_CIPHER_HW_select_xts()
|
||||
#endif
|
||||
|
||||
static const PROV_CIPHER_HW aes_generic_xts = {
|
||||
cipher_hw_aes_xts_generic_initkey,
|
||||
NULL
|
||||
};
|
||||
PROV_CIPHER_HW_declare_xts()
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_xts(size_t keybits)
|
||||
{
|
||||
PROV_CIPHER_HW_select_xts()
|
||||
return &aes_generic_xts;
|
||||
}
|
||||
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* 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 ccm mode */
|
||||
|
||||
#include "cipher_locl.h"
|
||||
#include "internal/ciphers/cipher_ccm.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out,
|
||||
size_t *padlen, const unsigned char *in,
|
||||
size_t len);
|
||||
|
||||
static int ccm_tls_init(PROV_CCM_CTX *ctx, unsigned char *aad, size_t alen)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (alen != EVP_AEAD_TLS1_AAD_LEN)
|
||||
return 0;
|
||||
|
||||
/* Save the aad for later use. */
|
||||
memcpy(ctx->buf, aad, alen);
|
||||
ctx->tls_aad_len = alen;
|
||||
|
||||
len = ctx->buf[alen - 2] << 8 | ctx->buf[alen - 1];
|
||||
if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
|
||||
return 0;
|
||||
|
||||
/* Correct length for explicit iv. */
|
||||
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
|
||||
|
||||
if (!ctx->enc) {
|
||||
if (len < ctx->m)
|
||||
return 0;
|
||||
/* Correct length for tag. */
|
||||
len -= ctx->m;
|
||||
}
|
||||
ctx->buf[alen - 2] = (unsigned char)(len >> 8);
|
||||
ctx->buf[alen - 1] = (unsigned char)(len & 0xff);
|
||||
|
||||
/* Extra padding: tag appended to record. */
|
||||
return ctx->m;
|
||||
}
|
||||
|
||||
static int ccm_tls_iv_set_fixed(PROV_CCM_CTX *ctx, unsigned char *fixed,
|
||||
size_t flen)
|
||||
{
|
||||
if (flen != EVP_CCM_TLS_FIXED_IV_LEN)
|
||||
return 0;
|
||||
|
||||
/* Copy to first part of the iv. */
|
||||
memcpy(ctx->iv, fixed, flen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t ccm_get_ivlen(PROV_CCM_CTX *ctx)
|
||||
{
|
||||
return 15 - ctx->l;
|
||||
}
|
||||
|
||||
int ccm_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
|
||||
const OSSL_PARAM *p;
|
||||
size_t sz;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
|
||||
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 ((p->data_size & 1) || (p->data_size < 4) || p->data_size > 16) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAGLEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (p->data != NULL) {
|
||||
if (ctx->enc) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED);
|
||||
return 0;
|
||||
}
|
||||
memcpy(ctx->buf, p->data, p->data_size);
|
||||
ctx->tag_set = 1;
|
||||
}
|
||||
ctx->m = p->data_size;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN);
|
||||
if (p != NULL) {
|
||||
size_t ivlen;
|
||||
|
||||
if (!OSSL_PARAM_get_size_t(p, &sz)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
ivlen = 15 - sz;
|
||||
if (ivlen < 2 || ivlen > 8) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
|
||||
return 0;
|
||||
}
|
||||
ctx->l = ivlen;
|
||||
}
|
||||
|
||||
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 = ccm_tls_init(ctx, 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_IV_FIXED);
|
||||
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 (ccm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ccm_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
||||
{
|
||||
PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
|
||||
if (p != NULL && !OSSL_PARAM_set_size_t(p, ccm_get_ivlen(ctx))) {
|
||||
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) {
|
||||
size_t m = ctx->m;
|
||||
|
||||
if (!OSSL_PARAM_set_size_t(p, m)) {
|
||||
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) {
|
||||
if (ccm_get_ivlen(ctx) != p->data_size) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
|
||||
return 0;
|
||||
}
|
||||
if (!OSSL_PARAM_set_octet_string(p, ctx->iv, p->data_size)) {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
|
||||
if (p != NULL) {
|
||||
if (!ctx->enc || !ctx->tag_set) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOTSET);
|
||||
return 0;
|
||||
}
|
||||
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
if (!ctx->hw->gettag(ctx, p->data, p->data_size))
|
||||
return 0;
|
||||
ctx->tag_set = 0;
|
||||
ctx->iv_set = 0;
|
||||
ctx->len_set = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ccm_init(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen, int enc)
|
||||
{
|
||||
PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
|
||||
|
||||
ctx->enc = enc;
|
||||
|
||||
if (iv != NULL) {
|
||||
if (ivlen != ccm_get_ivlen(ctx)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(ctx->iv, iv, ivlen);
|
||||
ctx->iv_set = 1;
|
||||
}
|
||||
if (key != NULL) {
|
||||
if (keylen != ctx->keylen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN);
|
||||
return 0;
|
||||
}
|
||||
return ctx->hw->setkey(ctx, key, keylen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ccm_einit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return ccm_init(vctx, key, keylen, iv, ivlen, 1);
|
||||
}
|
||||
|
||||
int ccm_dinit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return ccm_init(vctx, key, keylen, iv, ivlen, 0);
|
||||
}
|
||||
|
||||
int ccm_stream_update(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize, const unsigned char *in,
|
||||
size_t inl)
|
||||
{
|
||||
PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
|
||||
|
||||
if (outsize < inl) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ccm_cipher_internal(ctx, out, outl, in, inl)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ccm_stream_final(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
|
||||
int i;
|
||||
|
||||
i = ccm_cipher_internal(ctx, out, outl, NULL, 0);
|
||||
if (i <= 0)
|
||||
return 0;
|
||||
|
||||
*outl = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ccm_cipher(void *vctx,
|
||||
unsigned char *out, size_t *outl, size_t outsize,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
|
||||
|
||||
if (outsize < inl) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ccm_cipher_internal(ctx, out, outl, in, inl) <= 0)
|
||||
return -1;
|
||||
|
||||
*outl = inl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy the buffered iv */
|
||||
static int ccm_set_iv(PROV_CCM_CTX *ctx, size_t mlen)
|
||||
{
|
||||
const PROV_CCM_HW *hw = ctx->hw;
|
||||
|
||||
if (!hw->setiv(ctx, ctx->iv, ccm_get_ivlen(ctx), mlen))
|
||||
return 0;
|
||||
ctx->len_set = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ccm_tls_cipher(PROV_CCM_CTX *ctx,
|
||||
unsigned char *out, size_t *padlen,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int rv = 0;
|
||||
size_t olen = 0;
|
||||
|
||||
/* Encrypt/decrypt must be performed in place */
|
||||
if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)ctx->m))
|
||||
goto err;
|
||||
|
||||
/* If encrypting set explicit IV from sequence number (start of AAD) */
|
||||
if (ctx->enc)
|
||||
memcpy(out, ctx->buf, EVP_CCM_TLS_EXPLICIT_IV_LEN);
|
||||
/* Get rest of IV from explicit IV */
|
||||
memcpy(ctx->iv + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN);
|
||||
/* Correct length value */
|
||||
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m;
|
||||
if (!ccm_set_iv(ctx, len))
|
||||
goto err;
|
||||
|
||||
/* Use saved AAD */
|
||||
if (!ctx->hw->setaad(ctx, ctx->buf, ctx->tls_aad_len))
|
||||
goto err;
|
||||
|
||||
/* Fix buffer to point to payload */
|
||||
in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
|
||||
out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
|
||||
if (ctx->enc) {
|
||||
if (!ctx->hw->auth_encrypt(ctx, in, out, len, out + len, ctx->m))
|
||||
goto err;
|
||||
olen = len + EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m;
|
||||
} else {
|
||||
if (!ctx->hw->auth_decrypt(ctx, in, out, len,
|
||||
(unsigned char *)in + len, ctx->m))
|
||||
goto err;
|
||||
olen = len;
|
||||
}
|
||||
rv = 1;
|
||||
err:
|
||||
*padlen = olen;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out,
|
||||
size_t *padlen, const unsigned char *in,
|
||||
size_t len)
|
||||
{
|
||||
int rv = 0;
|
||||
size_t olen = 0;
|
||||
const PROV_CCM_HW *hw = ctx->hw;
|
||||
|
||||
/* If no key set, return error */
|
||||
if (!ctx->key_set)
|
||||
return 0;
|
||||
|
||||
if (ctx->tls_aad_len != UNINITIALISED_SIZET)
|
||||
return ccm_tls_cipher(ctx, out, padlen, in, len);
|
||||
|
||||
/* EVP_*Final() doesn't return any data */
|
||||
if (in == NULL && out != NULL)
|
||||
goto finish;
|
||||
|
||||
if (!ctx->iv_set)
|
||||
goto err;
|
||||
|
||||
if (out == NULL) {
|
||||
if (in == NULL) {
|
||||
if (!ccm_set_iv(ctx, len))
|
||||
goto err;
|
||||
} else {
|
||||
/* If we have AAD, we need a message length */
|
||||
if (!ctx->len_set && len)
|
||||
goto err;
|
||||
if (!hw->setaad(ctx, in, len))
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
/* If not set length yet do it */
|
||||
if (!ctx->len_set && !ccm_set_iv(ctx, len))
|
||||
goto err;
|
||||
|
||||
if (ctx->enc) {
|
||||
if (!hw->auth_encrypt(ctx, in, out, len, NULL, 0))
|
||||
goto err;
|
||||
ctx->tag_set = 1;
|
||||
} else {
|
||||
/* The tag must be set before actually decrypting data */
|
||||
if (!ctx->tag_set)
|
||||
goto err;
|
||||
|
||||
if (!hw->auth_decrypt(ctx, in, out, len, ctx->buf, ctx->m))
|
||||
goto err;
|
||||
/* Finished - reset flags so calling this method again will fail */
|
||||
ctx->iv_set = 0;
|
||||
ctx->tag_set = 0;
|
||||
ctx->len_set = 0;
|
||||
}
|
||||
}
|
||||
olen = len;
|
||||
finish:
|
||||
rv = 1;
|
||||
err:
|
||||
*padlen = olen;
|
||||
return rv;
|
||||
}
|
||||
|
||||
void ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw)
|
||||
{
|
||||
ctx->keylen = keybits / 8;
|
||||
ctx->key_set = 0;
|
||||
ctx->iv_set = 0;
|
||||
ctx->tag_set = 0;
|
||||
ctx->len_set = 0;
|
||||
ctx->l = 8;
|
||||
ctx->m = 12;
|
||||
ctx->tls_aad_len = UNINITIALISED_SIZET;
|
||||
ctx->hw = hw;
|
||||
}
|
||||
|
||||
void ccm_finalctx(PROV_CCM_CTX *ctx)
|
||||
{
|
||||
OPENSSL_cleanse(ctx->iv, sizeof(ctx->iv));
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 "internal/ciphers/ciphercommon.h"
|
||||
#include "internal/ciphers/cipher_ccm.h"
|
||||
|
||||
int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce,
|
||||
size_t nlen, size_t mlen)
|
||||
{
|
||||
return CRYPTO_ccm128_setiv(&ctx->ccm_ctx, nonce, nlen, mlen) == 0;
|
||||
}
|
||||
|
||||
int ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad, size_t alen)
|
||||
{
|
||||
CRYPTO_ccm128_aad(&ctx->ccm_ctx, aad, alen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag, size_t tlen)
|
||||
{
|
||||
return CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, tlen) > 0;
|
||||
}
|
||||
|
||||
int ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
|
||||
unsigned char *out, size_t len,
|
||||
unsigned char *tag, size_t taglen)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (ctx->str != NULL)
|
||||
rv = CRYPTO_ccm128_encrypt_ccm64(&ctx->ccm_ctx, in,
|
||||
out, len, ctx->str) == 0;
|
||||
else
|
||||
rv = CRYPTO_ccm128_encrypt(&ctx->ccm_ctx, in, out, len) == 0;
|
||||
|
||||
if (rv == 1 && tag != NULL)
|
||||
rv = (CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen) > 0);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
|
||||
unsigned char *out, size_t len,
|
||||
unsigned char *expected_tag, size_t taglen)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
if (ctx->str != NULL)
|
||||
rv = CRYPTO_ccm128_decrypt_ccm64(&ctx->ccm_ctx, in, out, len,
|
||||
ctx->str) == 0;
|
||||
else
|
||||
rv = CRYPTO_ccm128_decrypt(&ctx->ccm_ctx, in, out, len) == 0;
|
||||
if (rv) {
|
||||
unsigned char tag[16];
|
||||
|
||||
if (!CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen)
|
||||
|| CRYPTO_memcmp(tag, expected_tag, taglen) != 0)
|
||||
rv = 0;
|
||||
}
|
||||
if (rv == 0)
|
||||
OPENSSL_cleanse(out, len);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generic dispatch table functions for ciphers.
|
||||
*/
|
||||
|
||||
#include "cipher_locl.h"
|
||||
#include "internal/provider_ctx.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
/*-
|
||||
* Generic cipher functions for OSSL_PARAM gettables and settables
|
||||
*/
|
||||
static const OSSL_PARAM cipher_known_gettable_params[] = {
|
||||
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_MODE, NULL),
|
||||
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_BLOCK_SIZE, NULL),
|
||||
OSSL_PARAM_ulong(OSSL_CIPHER_PARAM_FLAGS, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
const OSSL_PARAM *cipher_generic_gettable_params(void)
|
||||
{
|
||||
return cipher_known_gettable_params;
|
||||
}
|
||||
|
||||
int cipher_generic_get_params(OSSL_PARAM params[], unsigned int md,
|
||||
unsigned long flags,
|
||||
size_t kbits, size_t blkbits, size_t ivbits)
|
||||
{
|
||||
OSSL_PARAM *p;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE);
|
||||
if (p != NULL && !OSSL_PARAM_set_uint(p, md)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_FLAGS);
|
||||
if (p != NULL && !OSSL_PARAM_set_ulong(p, flags)) {
|
||||
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, kbits / 8)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE);
|
||||
if (p != NULL && !OSSL_PARAM_set_size_t(p, blkbits / 8)) {
|
||||
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, ivbits / 8)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(cipher_generic)
|
||||
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(cipher_generic)
|
||||
|
||||
static const OSSL_PARAM cipher_known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
|
||||
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL),
|
||||
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
const OSSL_PARAM *cipher_generic_settable_ctx_params(void)
|
||||
{
|
||||
return cipher_known_settable_ctx_params;
|
||||
}
|
||||
|
||||
/*-
|
||||
* AEAD cipher functions for OSSL_PARAM gettables and settables
|
||||
*/
|
||||
static const OSSL_PARAM cipher_aead_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_TAGLEN, NULL),
|
||||
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_END
|
||||
};
|
||||
const OSSL_PARAM *cipher_aead_gettable_ctx_params(void)
|
||||
{
|
||||
return cipher_aead_known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
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_END
|
||||
};
|
||||
const OSSL_PARAM *cipher_aead_settable_ctx_params(void)
|
||||
{
|
||||
return cipher_aead_known_settable_ctx_params;
|
||||
}
|
||||
|
||||
static int cipher_generic_init_internal(PROV_CIPHER_CTX *ctx,
|
||||
const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen,
|
||||
int enc)
|
||||
{
|
||||
ctx->enc = enc ? 1 : 0;
|
||||
|
||||
if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) {
|
||||
if (ivlen != ctx->ivlen) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
memcpy(ctx->iv, iv, ctx->ivlen);
|
||||
}
|
||||
if (key != NULL) {
|
||||
if ((ctx->flags & EVP_CIPH_VARIABLE_LENGTH) == 0) {
|
||||
if (keylen != ctx->keylen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ctx->keylen = keylen;
|
||||
}
|
||||
return ctx->hw->init(ctx, key, ctx->keylen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_generic_einit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen,
|
||||
iv, ivlen, 1);
|
||||
}
|
||||
|
||||
int cipher_generic_dinit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen,
|
||||
iv, ivlen, 0);
|
||||
}
|
||||
|
||||
int cipher_generic_block_update(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize, const unsigned char *in,
|
||||
size_t inl)
|
||||
{
|
||||
size_t outlint = 0;
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
size_t blksz = ctx->blocksize;
|
||||
size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, blksz, &in, &inl);
|
||||
|
||||
/*
|
||||
* If we're decrypting and we end an update on a block boundary we hold
|
||||
* the last block back in case this is the last update call and the last
|
||||
* block is padded.
|
||||
*/
|
||||
if (ctx->bufsz == blksz && (ctx->enc || inl > 0 || !ctx->pad)) {
|
||||
if (outsize < blksz) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
ctx->bufsz = 0;
|
||||
outlint = blksz;
|
||||
out += blksz;
|
||||
}
|
||||
if (nextblocks > 0) {
|
||||
if (!ctx->enc && ctx->pad && nextblocks == inl) {
|
||||
if (!ossl_assert(inl >= blksz)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
nextblocks -= blksz;
|
||||
}
|
||||
outlint += nextblocks;
|
||||
if (outsize < outlint) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (!ctx->hw->cipher(ctx, out, in, nextblocks)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
in += nextblocks;
|
||||
inl -= nextblocks;
|
||||
}
|
||||
if (!trailingdata(ctx->buf, &ctx->bufsz, blksz, &in, &inl)) {
|
||||
/* ERR_raise already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
*outl = outlint;
|
||||
return inl == 0;
|
||||
}
|
||||
|
||||
int cipher_generic_block_final(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
size_t blksz = ctx->blocksize;
|
||||
|
||||
if (ctx->enc) {
|
||||
if (ctx->pad) {
|
||||
padblock(ctx->buf, &ctx->bufsz, blksz);
|
||||
} else if (ctx->bufsz == 0) {
|
||||
*outl = 0;
|
||||
return 1;
|
||||
} else if (ctx->bufsz != blksz) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (outsize < blksz) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
ctx->bufsz = 0;
|
||||
*outl = blksz;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decrypting */
|
||||
if (ctx->bufsz != blksz) {
|
||||
if (ctx->bufsz == 0 && !ctx->pad) {
|
||||
*outl = 0;
|
||||
return 1;
|
||||
}
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ctx->hw->cipher(ctx, ctx->buf, ctx->buf, blksz)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->pad && !unpadblock(ctx->buf, &ctx->bufsz, blksz)) {
|
||||
/* ERR_raise already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (outsize < ctx->bufsz) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
memcpy(out, ctx->buf, ctx->bufsz);
|
||||
*outl = ctx->bufsz;
|
||||
ctx->bufsz = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_generic_stream_update(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize, const unsigned char *in,
|
||||
size_t inl)
|
||||
{
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
|
||||
if (outsize < inl) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ctx->hw->cipher(ctx, out, in, inl)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*outl = inl;
|
||||
return 1;
|
||||
}
|
||||
int cipher_generic_stream_final(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
*outl = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_generic_cipher(void *vctx,
|
||||
unsigned char *out, size_t *outl, size_t outsize,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
|
||||
if (outsize < inl) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ctx->hw->cipher(ctx, out, in, inl)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*outl = inl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_generic_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
||||
{
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
|
||||
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING);
|
||||
if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->pad)) {
|
||||
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_ptr(p, &ctx->iv, ctx->ivlen)
|
||||
&& !OSSL_PARAM_set_octet_string(p, &ctx->iv, ctx->ivlen)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_NUM);
|
||||
if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->num)) {
|
||||
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;
|
||||
}
|
||||
|
||||
int cipher_generic_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_PADDING);
|
||||
if (p != NULL) {
|
||||
unsigned int pad;
|
||||
|
||||
if (!OSSL_PARAM_get_uint(p, &pad)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
ctx->pad = pad ? 1 : 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_NUM);
|
||||
if (p != NULL) {
|
||||
unsigned int num;
|
||||
|
||||
if (!OSSL_PARAM_get_uint(p, &num)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
void cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits,
|
||||
size_t ivbits, unsigned int mode, uint64_t flags,
|
||||
const PROV_CIPHER_HW *hw, void *provctx)
|
||||
{
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
|
||||
ctx->flags = flags;
|
||||
ctx->pad = 1;
|
||||
ctx->keylen = ((kbits) / 8);
|
||||
ctx->ivlen = ((ivbits) / 8);
|
||||
ctx->hw = hw;
|
||||
ctx->mode = mode;
|
||||
ctx->blocksize = blkbits / 8;
|
||||
if (provctx != NULL)
|
||||
ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); /* used for rand */
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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 "cipher_locl.h"
|
||||
|
||||
/*-
|
||||
* The generic cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
|
||||
* Used if there is no special hardware implementations.
|
||||
*/
|
||||
int cipher_hw_generic_cbc(PROV_CIPHER_CTX *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
if (dat->stream.cbc)
|
||||
(*dat->stream.cbc) (in, out, len, dat->ks, dat->iv, dat->enc);
|
||||
else if (dat->enc)
|
||||
CRYPTO_cbc128_encrypt(in, out, len, dat->ks, dat->iv, dat->block);
|
||||
else
|
||||
CRYPTO_cbc128_decrypt(in, out, len, dat->ks, dat->iv, dat->block);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_hw_generic_ecb(PROV_CIPHER_CTX *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
size_t i, bl = dat->blocksize;
|
||||
|
||||
if (len < bl)
|
||||
return 1;
|
||||
|
||||
for (i = 0, len -= bl; i <= len; i += bl)
|
||||
(*dat->block) (in + i, out + i, dat->ks);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_hw_generic_ofb128(PROV_CIPHER_CTX *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int num = dat->num;
|
||||
|
||||
CRYPTO_ofb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->block);
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_hw_generic_cfb128(PROV_CIPHER_CTX *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int num = dat->num;
|
||||
|
||||
CRYPTO_cfb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
|
||||
dat->block);
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_hw_generic_cfb8(PROV_CIPHER_CTX *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int num = dat->num;
|
||||
|
||||
CRYPTO_cfb128_8_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
|
||||
dat->block);
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_hw_generic_cfb1(PROV_CIPHER_CTX *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int num = dat->num;
|
||||
|
||||
if ((dat->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) {
|
||||
CRYPTO_cfb128_1_encrypt(in, out, len, dat->ks, dat->iv, &num,
|
||||
dat->enc, dat->block);
|
||||
dat->num = num;
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (len >= MAXBITCHUNK) {
|
||||
CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, dat->ks,
|
||||
dat->iv, &num, dat->enc, dat->block);
|
||||
len -= MAXBITCHUNK;
|
||||
out += MAXBITCHUNK;
|
||||
in += MAXBITCHUNK;
|
||||
}
|
||||
if (len)
|
||||
CRYPTO_cfb128_1_encrypt(in, out, len * 8, dat->ks, dat->iv, &num,
|
||||
dat->enc, dat->block);
|
||||
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_hw_generic_ctr(PROV_CIPHER_CTX *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
unsigned int num = dat->num;
|
||||
|
||||
if (dat->stream.ctr)
|
||||
CRYPTO_ctr128_encrypt_ctr32(in, out, len, dat->ks, dat->iv, dat->buf,
|
||||
&num, dat->stream.ctr);
|
||||
else
|
||||
CRYPTO_ctr128_encrypt(in, out, len, dat->ks, dat->iv, dat->buf,
|
||||
&num, dat->block);
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* The chunked cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
|
||||
* Used if there is no special hardware implementations.
|
||||
*/
|
||||
|
||||
int cipher_hw_chunked_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
while (inl >= MAXCHUNK) {
|
||||
cipher_hw_generic_cbc(ctx, out, in, MAXCHUNK);
|
||||
inl -= MAXCHUNK;
|
||||
in += MAXCHUNK;
|
||||
out += MAXCHUNK;
|
||||
}
|
||||
if (inl > 0)
|
||||
cipher_hw_generic_cbc(ctx, out, in, inl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_hw_chunked_cfb8(PROV_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
size_t chunk = MAXCHUNK;
|
||||
|
||||
if (inl < chunk)
|
||||
chunk = inl;
|
||||
while (inl > 0 && inl >= chunk) {
|
||||
cipher_hw_generic_cfb8(ctx, out, in, inl);
|
||||
inl -= chunk;
|
||||
in += chunk;
|
||||
out += chunk;
|
||||
if (inl < chunk)
|
||||
chunk = inl;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_hw_chunked_cfb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
size_t chunk = MAXCHUNK;
|
||||
|
||||
if (inl < chunk)
|
||||
chunk = inl;
|
||||
while (inl > 0 && inl >= chunk) {
|
||||
cipher_hw_generic_cfb128(ctx, out, in, inl);
|
||||
inl -= chunk;
|
||||
in += chunk;
|
||||
out += chunk;
|
||||
if (inl < chunk)
|
||||
chunk = inl;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_hw_chunked_ofb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
while (inl >= MAXCHUNK) {
|
||||
cipher_hw_generic_ofb128(ctx, out, in, MAXCHUNK);
|
||||
inl -= MAXCHUNK;
|
||||
in += MAXCHUNK;
|
||||
out += MAXCHUNK;
|
||||
}
|
||||
if (inl > 0)
|
||||
cipher_hw_generic_ofb128(ctx, out, in, inl);
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
* 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 gcm mode */
|
||||
|
||||
#include "cipher_locl.h"
|
||||
#include "internal/ciphers/cipher_gcm.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
#include "internal/rand_int.h"
|
||||
#include "internal/provider_ctx.h"
|
||||
|
||||
static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len);
|
||||
static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv,
|
||||
size_t len);
|
||||
static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen,
|
||||
const unsigned char *in, size_t len);
|
||||
static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out,
|
||||
size_t *padlen, const unsigned char *in,
|
||||
size_t len);
|
||||
|
||||
void gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits,
|
||||
const PROV_GCM_HW *hw, size_t ivlen_min)
|
||||
{
|
||||
ctx->pad = 1;
|
||||
ctx->mode = EVP_CIPH_GCM_MODE;
|
||||
ctx->taglen = UNINITIALISED_SIZET;
|
||||
ctx->tls_aad_len = UNINITIALISED_SIZET;
|
||||
ctx->ivlen_min = ivlen_min;
|
||||
ctx->ivlen = (EVP_GCM_TLS_FIXED_IV_LEN + EVP_GCM_TLS_EXPLICIT_IV_LEN);
|
||||
ctx->keylen = keybits / 8;
|
||||
ctx->hw = hw;
|
||||
ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
|
||||
}
|
||||
|
||||
void gcm_deinitctx(PROV_GCM_CTX *ctx)
|
||||
{
|
||||
OPENSSL_cleanse(ctx->iv, sizeof(ctx->iv));
|
||||
}
|
||||
|
||||
static int gcm_init(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen, int enc)
|
||||
{
|
||||
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
|
||||
|
||||
ctx->enc = enc;
|
||||
|
||||
if (iv != NULL) {
|
||||
if (ivlen < ctx->ivlen_min || ivlen > sizeof(ctx->iv)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
ctx->ivlen = ivlen;
|
||||
memcpy(ctx->iv, iv, ctx->ivlen);
|
||||
ctx->iv_state = IV_STATE_BUFFERED;
|
||||
}
|
||||
|
||||
if (key != NULL) {
|
||||
if (keylen != ctx->keylen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
return ctx->hw->setkey(ctx, key, ctx->keylen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int gcm_einit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return gcm_init(vctx, key, keylen, iv, ivlen, 1);
|
||||
}
|
||||
|
||||
int gcm_dinit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return gcm_init(vctx, key, keylen, iv, ivlen, 0);
|
||||
}
|
||||
|
||||
int gcm_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
||||
{
|
||||
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
|
||||
OSSL_PARAM *p;
|
||||
size_t sz;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
|
||||
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) {
|
||||
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;
|
||||
}
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
|
||||
if (p != NULL) {
|
||||
size_t taglen = (ctx->taglen != UNINITIALISED_SIZET) ? ctx->taglen :
|
||||
GCM_TAG_MAX_SIZE;
|
||||
|
||||
if (!OSSL_PARAM_set_size_t(p, taglen)) {
|
||||
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) {
|
||||
if (ctx->iv_gen != 1 && ctx->iv_gen_rand != 1)
|
||||
return 0;
|
||||
if (ctx->ivlen != p->data_size) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if (!OSSL_PARAM_set_octet_string(p, ctx->iv, ctx->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;
|
||||
}
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
|
||||
if (p != NULL) {
|
||||
sz = p->data_size;
|
||||
if (sz == 0
|
||||
|| sz > EVP_GCM_TLS_TAG_LEN
|
||||
|| !ctx->enc
|
||||
|| ctx->taglen == UNINITIALISED_SIZET) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG);
|
||||
return 0;
|
||||
}
|
||||
if (!OSSL_PARAM_set_octet_string(p, ctx->buf, sz)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int gcm_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
|
||||
const OSSL_PARAM *p;
|
||||
size_t sz;
|
||||
void *vp;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
|
||||
if (p != NULL) {
|
||||
vp = ctx->buf;
|
||||
if (!OSSL_PARAM_get_octet_string(p, &vp, EVP_GCM_TLS_TAG_LEN, &sz)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
if (sz == 0 || ctx->enc) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG);
|
||||
return 0;
|
||||
}
|
||||
ctx->taglen = sz;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_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 (sz == 0 || sz > sizeof(ctx->iv)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
ctx->ivlen = 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;
|
||||
}
|
||||
sz = gcm_tls_init(ctx, p->data, p->data_size);
|
||||
if (sz == 0) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_AAD);
|
||||
return 0;
|
||||
}
|
||||
ctx->tls_aad_pad_sz = sz;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED);
|
||||
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 (gcm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
|
||||
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);
|
||||
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)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int gcm_stream_update(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize, const unsigned char *in, size_t inl)
|
||||
{
|
||||
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
|
||||
|
||||
if (outsize < inl) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int gcm_stream_final(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
|
||||
int i;
|
||||
|
||||
i = gcm_cipher_internal(ctx, out, outl, NULL, 0);
|
||||
if (i <= 0)
|
||||
return 0;
|
||||
|
||||
*outl = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int gcm_cipher(void *vctx,
|
||||
unsigned char *out, size_t *outl, size_t outsize,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
|
||||
|
||||
if (outsize < inl) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0)
|
||||
return -1;
|
||||
|
||||
*outl = inl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* See SP800-38D (GCM) Section 8 "Uniqueness requirement on IVS and keys"
|
||||
*
|
||||
* See also 8.2.2 RBG-based construction.
|
||||
* Random construction consists of a free field (which can be NULL) and a
|
||||
* random field which will use a DRBG that can return at least 96 bits of
|
||||
* entropy strength. (The DRBG must be seeded by the FIPS module).
|
||||
*/
|
||||
static int gcm_iv_generate(PROV_GCM_CTX *ctx, int offset)
|
||||
{
|
||||
int sz = ctx->ivlen - offset;
|
||||
|
||||
/* Must be at least 96 bits */
|
||||
if (sz <= 0 || ctx->ivlen < GCM_IV_DEFAULT_SIZE)
|
||||
return 0;
|
||||
|
||||
/* Use DRBG to generate random iv */
|
||||
if (rand_bytes_ex(ctx->libctx, ctx->iv + offset, sz) <= 0)
|
||||
return 0;
|
||||
ctx->iv_state = IV_STATE_BUFFERED;
|
||||
ctx->iv_gen_rand = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out,
|
||||
size_t *padlen, const unsigned char *in,
|
||||
size_t len)
|
||||
{
|
||||
size_t olen = 0;
|
||||
int rv = 0;
|
||||
const PROV_GCM_HW *hw = ctx->hw;
|
||||
|
||||
if (ctx->tls_aad_len != UNINITIALISED_SIZET)
|
||||
return gcm_tls_cipher(ctx, out, padlen, in, len);
|
||||
|
||||
if (!ctx->key_set || ctx->iv_state == IV_STATE_FINISHED)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* FIPS requires generation of AES-GCM IV's inside the FIPS module.
|
||||
* The IV can still be set externally (the security policy will state that
|
||||
* this is not FIPS compliant). There are some applications
|
||||
* where setting the IV externally is the only option available.
|
||||
*/
|
||||
if (ctx->iv_state == IV_STATE_UNINITIALISED) {
|
||||
if (!ctx->enc || !gcm_iv_generate(ctx, 0))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ctx->iv_state == IV_STATE_BUFFERED) {
|
||||
if (!hw->setiv(ctx, ctx->iv, ctx->ivlen))
|
||||
goto err;
|
||||
ctx->iv_state = IV_STATE_COPIED;
|
||||
}
|
||||
|
||||
if (in != NULL) {
|
||||
/* The input is AAD if out is NULL */
|
||||
if (out == NULL) {
|
||||
if (!hw->aadupdate(ctx, in, len))
|
||||
goto err;
|
||||
} else {
|
||||
/* The input is ciphertext OR plaintext */
|
||||
if (!hw->cipherupdate(ctx, in, len, out))
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
/* The tag must be set before actually decrypting data */
|
||||
if (!ctx->enc && ctx->taglen == UNINITIALISED_SIZET)
|
||||
goto err;
|
||||
if (!hw->cipherfinal(ctx, ctx->buf))
|
||||
goto err;
|
||||
ctx->iv_state = IV_STATE_FINISHED; /* Don't reuse the IV */
|
||||
goto finish;
|
||||
}
|
||||
olen = len;
|
||||
finish:
|
||||
rv = 1;
|
||||
err:
|
||||
*padlen = olen;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len)
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t len;
|
||||
|
||||
if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
|
||||
return 0;
|
||||
|
||||
/* Save the aad for later use. */
|
||||
buf = dat->buf;
|
||||
memcpy(buf, aad, aad_len);
|
||||
dat->tls_aad_len = aad_len;
|
||||
dat->tls_enc_records = 0;
|
||||
|
||||
len = buf[aad_len - 2] << 8 | buf[aad_len - 1];
|
||||
/* Correct length for explicit iv. */
|
||||
if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
|
||||
return 0;
|
||||
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
||||
|
||||
/* If decrypting correct for tag too. */
|
||||
if (!dat->enc) {
|
||||
if (len < EVP_GCM_TLS_TAG_LEN)
|
||||
return 0;
|
||||
len -= EVP_GCM_TLS_TAG_LEN;
|
||||
}
|
||||
buf[aad_len - 2] = (unsigned char)(len >> 8);
|
||||
buf[aad_len - 1] = (unsigned char)(len & 0xff);
|
||||
/* Extra padding: tag appended to record. */
|
||||
return EVP_GCM_TLS_TAG_LEN;
|
||||
}
|
||||
|
||||
static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv,
|
||||
size_t len)
|
||||
{
|
||||
/* Special case: -1 length restores whole IV */
|
||||
if (len == (size_t)-1) {
|
||||
memcpy(ctx->iv, iv, ctx->ivlen);
|
||||
ctx->iv_gen = 1;
|
||||
ctx->iv_state = IV_STATE_BUFFERED;
|
||||
return 1;
|
||||
}
|
||||
/* Fixed field must be at least 4 bytes and invocation field at least 8 */
|
||||
if ((len < EVP_GCM_TLS_FIXED_IV_LEN)
|
||||
|| (ctx->ivlen - (int)len) < EVP_GCM_TLS_EXPLICIT_IV_LEN)
|
||||
return 0;
|
||||
if (len > 0)
|
||||
memcpy(ctx->iv, iv, len);
|
||||
if (ctx->enc
|
||||
&& rand_bytes_ex(ctx->libctx, ctx->iv + len, ctx->ivlen - len) <= 0)
|
||||
return 0;
|
||||
ctx->iv_gen = 1;
|
||||
ctx->iv_state = IV_STATE_BUFFERED;
|
||||
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,
|
||||
* encrypt payload and write the tag. On verify retrieve IV, decrypt payload
|
||||
* and verify tag.
|
||||
*/
|
||||
static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int rv = 0;
|
||||
size_t arg = EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
||||
size_t plen = 0;
|
||||
unsigned char *tag = NULL;
|
||||
|
||||
if (!ctx->key_set)
|
||||
goto err;
|
||||
|
||||
/* Encrypt/decrypt must be performed in place */
|
||||
if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness
|
||||
* Requirements from SP 800-38D". The requirements is for one party to the
|
||||
* communication to fail after 2^64 - 1 keys. We do this on the encrypting
|
||||
* side only.
|
||||
*/
|
||||
if (ctx->enc && ++ctx->tls_enc_records == 0) {
|
||||
ERR_raise(ERR_LIB_PROV, EVP_R_TOO_MANY_RECORDS);
|
||||
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))
|
||||
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))
|
||||
goto err;
|
||||
}
|
||||
ctx->iv_state = IV_STATE_COPIED;
|
||||
|
||||
/* Fix buffer and length to point to payload */
|
||||
in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
||||
out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
||||
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
|
||||
|
||||
tag = ctx->enc ? out + len : (unsigned char *)in + len;
|
||||
if (!ctx->hw->oneshot(ctx, ctx->buf, ctx->tls_aad_len, in, len, out, tag,
|
||||
EVP_GCM_TLS_TAG_LEN)) {
|
||||
if (!ctx->enc)
|
||||
OPENSSL_cleanse(out, len);
|
||||
goto err;
|
||||
}
|
||||
if (ctx->enc)
|
||||
plen = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
|
||||
else
|
||||
plen = len;
|
||||
|
||||
rv = 1;
|
||||
err:
|
||||
ctx->iv_state = IV_STATE_FINISHED;
|
||||
ctx->tls_aad_len = UNINITIALISED_SIZET;
|
||||
*padlen = plen;
|
||||
return rv;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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 "cipher_locl.h"
|
||||
#include "internal/ciphers/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;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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 "internal/ciphers/ciphercommon.h"
|
||||
|
||||
#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(name) \
|
||||
static const OSSL_PARAM name##_known_gettable_ctx_params[] = { \
|
||||
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), \
|
||||
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), \
|
||||
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL), \
|
||||
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL), \
|
||||
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
|
||||
|
||||
#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(name) \
|
||||
OSSL_PARAM_END \
|
||||
}; \
|
||||
const OSSL_PARAM * name##_gettable_ctx_params(void) \
|
||||
{ \
|
||||
return name##_known_gettable_ctx_params; \
|
||||
}
|
||||
|
||||
void padblock(unsigned char *buf, size_t *buflen, size_t blocksize);
|
||||
int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize);
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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 "cipher_locl.h"
|
||||
#include "internal/ciphers/cipher_tdes.h"
|
||||
#include "internal/rand_int.h"
|
||||
#include "internal/provider_algs.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
void *tdes_newctx(void *provctx, int mode, size_t kbits, size_t blkbits,
|
||||
size_t ivbits, uint64_t flags, const PROV_CIPHER_HW *hw)
|
||||
{
|
||||
PROV_TDES_CTX *tctx = OPENSSL_zalloc(sizeof(*tctx));
|
||||
|
||||
if (tctx != NULL)
|
||||
cipher_generic_initkey(tctx, kbits, blkbits, ivbits, mode, flags, hw,
|
||||
provctx);
|
||||
return tctx;
|
||||
}
|
||||
|
||||
void tdes_freectx(void *vctx)
|
||||
{
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static int tdes_init(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen, int enc)
|
||||
{
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
|
||||
ctx->enc = enc;
|
||||
|
||||
if (iv != NULL) {
|
||||
if (ivlen != TDES_IVLEN) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
|
||||
return 0;
|
||||
}
|
||||
memcpy(ctx->iv, iv, TDES_IVLEN);
|
||||
}
|
||||
|
||||
if (key != NULL) {
|
||||
if (keylen != ctx->keylen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN);
|
||||
return 0;
|
||||
}
|
||||
return ctx->hw->init(ctx, key, ctx->keylen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tdes_einit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return tdes_init(vctx, key, keylen, iv, ivlen, 1);
|
||||
}
|
||||
|
||||
int tdes_dinit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return tdes_init(vctx, key, keylen, iv, ivlen, 0);
|
||||
}
|
||||
|
||||
static int tdes_generatekey(PROV_CIPHER_CTX *ctx, void *ptr)
|
||||
{
|
||||
|
||||
DES_cblock *deskey = ptr;
|
||||
size_t kl = ctx->keylen;
|
||||
|
||||
if (kl == 0 || rand_priv_bytes_ex(ctx->libctx, ptr, kl) <= 0)
|
||||
return 0;
|
||||
DES_set_odd_parity(deskey);
|
||||
if (kl >= 16)
|
||||
DES_set_odd_parity(deskey + 1);
|
||||
if (kl >= 24) {
|
||||
DES_set_odd_parity(deskey + 2);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(tdes)
|
||||
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_RANDOM_KEY, NULL, 0),
|
||||
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(tdes)
|
||||
|
||||
int tdes_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
||||
{
|
||||
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if (!cipher_generic_get_ctx_params(vctx, params))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_RANDOM_KEY);
|
||||
if (p != NULL && !tdes_generatekey(ctx, p->data)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(3.0) - ECB mode does not use an IV - but existing test code is setting
|
||||
* an IV. Fixing this could potentially make applications break.
|
||||
*/
|
||||
|
||||
/* tdes_ede3_ecb_functions */
|
||||
IMPLEMENT_tdes_cipher(ede3, EDE3, ecb, ECB, TDES_FLAGS, 64*3, 64, 64, block);
|
||||
/* tdes_ede3_cbc_functions */
|
||||
IMPLEMENT_tdes_cipher(ede3, EDE3, cbc, CBC, TDES_FLAGS, 64*3, 64, 64, block);
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 1995-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 "cipher_locl.h"
|
||||
#include "internal/ciphers/cipher_tdes.h"
|
||||
|
||||
#define ks1 tks.ks[0]
|
||||
#define ks2 tks.ks[1]
|
||||
#define ks3 tks.ks[2]
|
||||
|
||||
int cipher_hw_tdes_ede3_initkey(PROV_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
|
||||
DES_cblock *deskey = (DES_cblock *)key;
|
||||
|
||||
tctx->tstream.cbc = NULL;
|
||||
# if defined(SPARC_DES_CAPABLE)
|
||||
if (SPARC_DES_CAPABLE) {
|
||||
if (ctx->mode == EVP_CIPH_CBC_MODE) {
|
||||
des_t4_key_expand(&deskey[0], &tctx->ks1);
|
||||
des_t4_key_expand(&deskey[1], &tctx->ks2);
|
||||
des_t4_key_expand(&deskey[2], &tctx->ks3);
|
||||
tctx->tstream.cbc = ctx->enc ? des_t4_ede3_cbc_encrypt :
|
||||
des_t4_ede3_cbc_decrypt;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
DES_set_key_unchecked(&deskey[0], &tctx->ks1);
|
||||
DES_set_key_unchecked(&deskey[1], &tctx->ks2);
|
||||
DES_set_key_unchecked(&deskey[2], &tctx->ks3);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_hw_tdes_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
|
||||
|
||||
if (tctx->tstream.cbc != NULL) {
|
||||
(*tctx->tstream.cbc) (in, out, inl, tctx->tks.ks, ctx->iv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (inl >= MAXCHUNK) {
|
||||
DES_ede3_cbc_encrypt(in, out, (long)MAXCHUNK, &tctx->ks1, &tctx->ks2,
|
||||
&tctx->ks3, (DES_cblock *)ctx->iv, ctx->enc);
|
||||
inl -= MAXCHUNK;
|
||||
in += MAXCHUNK;
|
||||
out += MAXCHUNK;
|
||||
}
|
||||
if (inl > 0)
|
||||
DES_ede3_cbc_encrypt(in, out, (long)inl, &tctx->ks1, &tctx->ks2,
|
||||
&tctx->ks3, (DES_cblock *)ctx->iv, ctx->enc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cipher_hw_tdes_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
|
||||
|
||||
if (len < DES_BLOCK_SIZE)
|
||||
return 1;
|
||||
|
||||
for (i = 0, len -= DES_BLOCK_SIZE; i <= len; i += DES_BLOCK_SIZE) {
|
||||
DES_ecb3_encrypt((const_DES_cblock *)(in + i), (DES_cblock *)(out + i),
|
||||
&tctx->ks1, &tctx->ks2, &tctx->ks3, ctx->enc);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
PROV_CIPHER_HW_tdes_mode(ede3, ecb)
|
||||
PROV_CIPHER_HW_tdes_mode(ede3, cbc)
|
||||
@@ -1,109 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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 <openssl/modes.h>
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
typedef struct prov_aes_cipher_st PROV_AES_CIPHER;
|
||||
|
||||
typedef struct prov_aes_key_st {
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
AES_KEY ks;
|
||||
} ks;
|
||||
block128_f block;
|
||||
union {
|
||||
cbc128_f cbc;
|
||||
ctr128_f ctr;
|
||||
} stream;
|
||||
|
||||
/* Platform specific data */
|
||||
union {
|
||||
int dummy;
|
||||
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
|
||||
struct {
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
/*-
|
||||
* KM-AES parameter block - begin
|
||||
* (see z/Architecture Principles of Operation >= SA22-7832-06)
|
||||
*/
|
||||
struct {
|
||||
unsigned char k[32];
|
||||
} km;
|
||||
/* KM-AES parameter block - end */
|
||||
/*-
|
||||
* KMO-AES/KMF-AES parameter block - begin
|
||||
* (see z/Architecture Principles of Operation >= SA22-7832-08)
|
||||
*/
|
||||
struct {
|
||||
unsigned char cv[16];
|
||||
unsigned char k[32];
|
||||
} kmo_kmf;
|
||||
/* KMO-AES/KMF-AES parameter block - end */
|
||||
} param;
|
||||
unsigned int fc;
|
||||
int res;
|
||||
} s390x;
|
||||
#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
|
||||
} plat;
|
||||
|
||||
/* The cipher functions we are going to use */
|
||||
const PROV_AES_CIPHER *ciph;
|
||||
|
||||
/* The mode that we are using */
|
||||
int mode;
|
||||
|
||||
/* Set to 1 if we are encrypting or 0 otherwise */
|
||||
int enc;
|
||||
|
||||
unsigned char iv[AES_BLOCK_SIZE];
|
||||
|
||||
/*
|
||||
* num contains the number of bytes of |iv| which are valid for modes that
|
||||
* manage partial blocks themselves.
|
||||
*/
|
||||
size_t num;
|
||||
|
||||
/* Buffer of partial blocks processed via update calls */
|
||||
unsigned char buf[AES_BLOCK_SIZE];
|
||||
|
||||
/* Number of bytes in buf */
|
||||
size_t bufsz;
|
||||
|
||||
uint64_t flags;
|
||||
|
||||
size_t keylen;
|
||||
|
||||
/* Whether padding should be used or not */
|
||||
unsigned int pad : 1;
|
||||
} PROV_AES_KEY;
|
||||
|
||||
struct prov_aes_cipher_st {
|
||||
int (*init)(PROV_AES_KEY *dat, const uint8_t *key, size_t keylen);
|
||||
int (*cipher)(PROV_AES_KEY *dat, uint8_t *out, const uint8_t *in,
|
||||
size_t inl);
|
||||
};
|
||||
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_ecb(size_t keylen);
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_cbc(size_t keylen);
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_ofb(size_t keylen);
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb(size_t keylen);
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb1(size_t keylen);
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb8(size_t keylen);
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_ctr(size_t keylen);
|
||||
|
||||
size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize,
|
||||
const unsigned char **in, size_t *inlen);
|
||||
int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize,
|
||||
const unsigned char **in, size_t *inlen);
|
||||
void padblock(unsigned char *buf, size_t *buflen, size_t blocksize);
|
||||
int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize);
|
||||
@@ -1,5 +1,5 @@
|
||||
SOURCE[../../../libcrypto]=\
|
||||
sha2_prov.c sha3_prov.c
|
||||
$COMMON=sha2_prov.c sha3_prov.c digest_common.c
|
||||
|
||||
SOURCE[../../fips]=\
|
||||
sha2_prov.c sha3_prov.c
|
||||
SOURCE[../../../libcrypto]=$COMMON
|
||||
SOURCE[../../fips]=$COMMON
|
||||
SOURCE[../../legacy]= digest_common.c
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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/err.h"
|
||||
#include "internal/digestcommon.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
int digest_default_get_params(OSSL_PARAM params[], size_t blksz, size_t paramsz,
|
||||
unsigned long flags)
|
||||
{
|
||||
OSSL_PARAM *p = NULL;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_BLOCK_SIZE);
|
||||
if (p != NULL && !OSSL_PARAM_set_size_t(p, blksz)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_SIZE);
|
||||
if (p != NULL && !OSSL_PARAM_set_size_t(p, paramsz)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_FLAGS);
|
||||
if (p != NULL && !OSSL_PARAM_set_ulong(p, flags)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM digest_default_known_gettable_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_BLOCK_SIZE, NULL),
|
||||
OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_SIZE, NULL),
|
||||
OSSL_PARAM_ulong(OSSL_DIGEST_PARAM_FLAGS, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
const OSSL_PARAM *digest_default_gettable_params(void)
|
||||
{
|
||||
return digest_default_known_gettable_params;
|
||||
}
|
||||
@@ -9,18 +9,29 @@
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include "internal/core_mkdigest.h"
|
||||
#include "internal/digestcommon.h"
|
||||
#include "internal/provider_algs.h"
|
||||
#include "internal/sha.h"
|
||||
|
||||
static OSSL_OP_digest_set_params_fn sha1_set_params;
|
||||
static OSSL_OP_digest_set_ctx_params_fn sha1_set_ctx_params;
|
||||
static OSSL_OP_digest_settable_ctx_params_fn sha1_settable_ctx_params;
|
||||
|
||||
static const OSSL_PARAM known_sha1_settable_ctx_params[] = {
|
||||
{OSSL_DIGEST_PARAM_SSL3_MS, OSSL_PARAM_OCTET_STRING, NULL, 0, 0},
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM *sha1_settable_ctx_params(void)
|
||||
{
|
||||
return known_sha1_settable_ctx_params;
|
||||
}
|
||||
|
||||
/* Special set_params method for SSL3 */
|
||||
static int sha1_set_params(void *vctx, const OSSL_PARAM params[])
|
||||
static int sha1_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
SHA_CTX *ctx = (SHA_CTX *)vctx;
|
||||
@@ -34,32 +45,45 @@ static int sha1_set_params(void *vctx, const OSSL_PARAM params[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
OSSL_FUNC_DIGEST_CONSTRUCT_PARAMS(sha1, SHA_CTX,
|
||||
SHA_CBLOCK, SHA_DIGEST_LENGTH,
|
||||
SHA1_Init, SHA1_Update, SHA1_Final,
|
||||
sha1_set_params)
|
||||
/* sha1_functions */
|
||||
IMPLEMENT_digest_functions_with_settable_ctx(
|
||||
sha1, SHA_CTX, SHA_CBLOCK, SHA_DIGEST_LENGTH, EVP_MD_FLAG_DIGALGID_ABSENT,
|
||||
SHA1_Init, SHA1_Update, SHA1_Final,
|
||||
sha1_settable_ctx_params, sha1_set_ctx_params)
|
||||
|
||||
OSSL_FUNC_DIGEST_CONSTRUCT(sha224, SHA256_CTX,
|
||||
/* sha224_functions */
|
||||
IMPLEMENT_digest_functions(sha224, SHA256_CTX,
|
||||
SHA256_CBLOCK, SHA224_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_DIGALGID_ABSENT,
|
||||
SHA224_Init, SHA224_Update, SHA224_Final)
|
||||
|
||||
OSSL_FUNC_DIGEST_CONSTRUCT(sha256, SHA256_CTX,
|
||||
/* sha256_functions */
|
||||
IMPLEMENT_digest_functions(sha256, SHA256_CTX,
|
||||
SHA256_CBLOCK, SHA256_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_DIGALGID_ABSENT,
|
||||
SHA256_Init, SHA256_Update, SHA256_Final)
|
||||
|
||||
OSSL_FUNC_DIGEST_CONSTRUCT(sha384, SHA512_CTX,
|
||||
/* sha384_functions */
|
||||
IMPLEMENT_digest_functions(sha384, SHA512_CTX,
|
||||
SHA512_CBLOCK, SHA384_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_DIGALGID_ABSENT,
|
||||
SHA384_Init, SHA384_Update, SHA384_Final)
|
||||
|
||||
OSSL_FUNC_DIGEST_CONSTRUCT(sha512, SHA512_CTX,
|
||||
/* sha512_functions */
|
||||
IMPLEMENT_digest_functions(sha512, SHA512_CTX,
|
||||
SHA512_CBLOCK, SHA512_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_DIGALGID_ABSENT,
|
||||
SHA512_Init, SHA512_Update, SHA512_Final)
|
||||
|
||||
OSSL_FUNC_DIGEST_CONSTRUCT(sha512_224, SHA512_CTX,
|
||||
/* sha512_224_functions */
|
||||
IMPLEMENT_digest_functions(sha512_224, SHA512_CTX,
|
||||
SHA512_CBLOCK, SHA224_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_DIGALGID_ABSENT,
|
||||
sha512_224_init, SHA512_Update, SHA512_Final)
|
||||
|
||||
OSSL_FUNC_DIGEST_CONSTRUCT(sha512_256, SHA512_CTX,
|
||||
/* sha512_256_functions */
|
||||
IMPLEMENT_digest_functions(sha512_256, SHA512_CTX,
|
||||
SHA512_CBLOCK, SHA256_DIGEST_LENGTH,
|
||||
EVP_MD_FLAG_DIGALGID_ABSENT,
|
||||
sha512_256_init, SHA512_Update, SHA512_Final)
|
||||
|
||||
@@ -7,14 +7,16 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/core_names.h>
|
||||
#include <string.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/err.h>
|
||||
#include "internal/sha3.h"
|
||||
#include "internal/core_mkdigest.h"
|
||||
#include "internal/digestcommon.h"
|
||||
#include "internal/provider_algs.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
/*
|
||||
* Forward declaration of any unique methods implemented here. This is not strictly
|
||||
@@ -26,7 +28,8 @@ static OSSL_OP_digest_update_fn keccak_update;
|
||||
static OSSL_OP_digest_final_fn keccak_final;
|
||||
static OSSL_OP_digest_freectx_fn keccak_freectx;
|
||||
static OSSL_OP_digest_dupctx_fn keccak_dupctx;
|
||||
static OSSL_OP_digest_set_params_fn shake_set_params;
|
||||
static OSSL_OP_digest_set_ctx_params_fn shake_set_ctx_params;
|
||||
static OSSL_OP_digest_settable_ctx_params_fn shake_settable_ctx_params;
|
||||
static sha3_absorb_fn generic_sha3_absorb;
|
||||
static sha3_final_fn generic_sha3_final;
|
||||
|
||||
@@ -89,10 +92,12 @@ static int keccak_update(void *vctx, const unsigned char *inp, size_t len)
|
||||
static int keccak_final(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsz)
|
||||
{
|
||||
int ret;
|
||||
int ret = 1;
|
||||
KECCAK1600_CTX *ctx = vctx;
|
||||
|
||||
ret = ctx->meth.final(out, ctx);
|
||||
if (outsz > 0)
|
||||
ret = ctx->meth.final(out, ctx);
|
||||
|
||||
*outl = ctx->md_size;
|
||||
return ret;
|
||||
}
|
||||
@@ -165,65 +170,64 @@ static PROV_SHA3_METHOD shake_s390x_md =
|
||||
s390x_shake_final
|
||||
};
|
||||
|
||||
# define SHA3_SET_MD(uname, typ) \
|
||||
if (S390_SHA3_CAPABLE(uname)) { \
|
||||
ctx->pad = S390X_##uname; \
|
||||
ctx->meth = typ##_s390x_md; \
|
||||
} else { \
|
||||
ctx->meth = sha3_generic_md; \
|
||||
# define SHA3_SET_MD(uname, typ) \
|
||||
if (S390_SHA3_CAPABLE(uname)) { \
|
||||
ctx->pad = S390X_##uname; \
|
||||
ctx->meth = typ##_s390x_md; \
|
||||
} else { \
|
||||
ctx->meth = sha3_generic_md; \
|
||||
}
|
||||
#else
|
||||
# define SHA3_SET_MD(uname, typ) ctx->meth = sha3_generic_md;
|
||||
#endif /* S390_SHA3 */
|
||||
|
||||
#define SHA3_newctx(typ, uname, name, bitlen, pad) \
|
||||
static OSSL_OP_digest_newctx_fn name##_newctx; \
|
||||
static void *name##_newctx(void *provctx) \
|
||||
{ \
|
||||
KECCAK1600_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
|
||||
\
|
||||
if (ctx == NULL) \
|
||||
return NULL; \
|
||||
sha3_init(ctx, pad, bitlen); \
|
||||
SHA3_SET_MD(uname, typ) \
|
||||
return ctx; \
|
||||
#define SHA3_newctx(typ, uname, name, bitlen, pad) \
|
||||
static OSSL_OP_digest_newctx_fn name##_newctx; \
|
||||
static void *name##_newctx(void *provctx) \
|
||||
{ \
|
||||
KECCAK1600_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
|
||||
\
|
||||
if (ctx == NULL) \
|
||||
return NULL; \
|
||||
sha3_init(ctx, pad, bitlen); \
|
||||
SHA3_SET_MD(uname, typ) \
|
||||
return ctx; \
|
||||
}
|
||||
|
||||
#define KMAC_newctx(uname, bitlen, pad) \
|
||||
static OSSL_OP_digest_newctx_fn uname##_newctx; \
|
||||
static void *uname##_newctx(void *provctx) \
|
||||
{ \
|
||||
KECCAK1600_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
|
||||
\
|
||||
if (ctx == NULL) \
|
||||
return NULL; \
|
||||
keccak_kmac_init(ctx, pad, bitlen); \
|
||||
ctx->meth = sha3_generic_md; \
|
||||
return ctx; \
|
||||
#define KMAC_newctx(uname, bitlen, pad) \
|
||||
static OSSL_OP_digest_newctx_fn uname##_newctx; \
|
||||
static void *uname##_newctx(void *provctx) \
|
||||
{ \
|
||||
KECCAK1600_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
|
||||
\
|
||||
if (ctx == NULL) \
|
||||
return NULL; \
|
||||
keccak_kmac_init(ctx, pad, bitlen); \
|
||||
ctx->meth = sha3_generic_md; \
|
||||
return ctx; \
|
||||
}
|
||||
|
||||
#define OSSL_FUNC_SHA3_DIGEST(name, bitlen, dgstsize, stparams) \
|
||||
static OSSL_OP_digest_size_fn name##_size; \
|
||||
static OSSL_OP_digest_block_size_fn name##_block_size; \
|
||||
static size_t name##_block_size(void) \
|
||||
{ \
|
||||
return SHA3_BLOCKSIZE(bitlen); \
|
||||
} \
|
||||
static size_t name##_size(void) \
|
||||
{ \
|
||||
return dgstsize; \
|
||||
} \
|
||||
const OSSL_DISPATCH name##_functions[] = { \
|
||||
{ OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx }, \
|
||||
{ OSSL_FUNC_DIGEST_INIT, (void (*)(void))keccak_init }, \
|
||||
{ OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))keccak_update }, \
|
||||
{ OSSL_FUNC_DIGEST_FINAL, (void (*)(void))keccak_final }, \
|
||||
{ OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))keccak_freectx }, \
|
||||
{ OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))keccak_dupctx }, \
|
||||
{ OSSL_FUNC_DIGEST_SIZE, (void (*)(void))name##_size }, \
|
||||
{ OSSL_FUNC_DIGEST_BLOCK_SIZE, (void (*)(void))name##_block_size }, \
|
||||
{ OSSL_FUNC_DIGEST_SET_PARAMS, (void (*)(void))stparams },\
|
||||
OSSL_FUNC_DIGEST_CONSTRUCT_END
|
||||
#define PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags) \
|
||||
PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \
|
||||
const OSSL_DISPATCH name##_functions[] = { \
|
||||
{ OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx }, \
|
||||
{ OSSL_FUNC_DIGEST_INIT, (void (*)(void))keccak_init }, \
|
||||
{ OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))keccak_update }, \
|
||||
{ OSSL_FUNC_DIGEST_FINAL, (void (*)(void))keccak_final }, \
|
||||
{ OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))keccak_freectx }, \
|
||||
{ OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))keccak_dupctx }, \
|
||||
PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name)
|
||||
|
||||
#define PROV_FUNC_SHA3_DIGEST(name, bitlen, blksize, dgstsize, flags) \
|
||||
PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags), \
|
||||
PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END
|
||||
|
||||
#define PROV_FUNC_SHAKE_DIGEST(name, bitlen, blksize, dgstsize, flags) \
|
||||
PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags), \
|
||||
{ OSSL_FUNC_DIGEST_SET_CTX_PARAMS, (void (*)(void))shake_set_ctx_params }, \
|
||||
{ OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS, \
|
||||
(void (*)(void))shake_settable_ctx_params }, \
|
||||
PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END
|
||||
|
||||
static void keccak_freectx(void *vctx)
|
||||
{
|
||||
@@ -241,38 +245,61 @@ static void *keccak_dupctx(void *ctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int shake_set_params(void *vctx, const OSSL_PARAM params[])
|
||||
static const OSSL_PARAM known_shake_settable_ctx_params[] = {
|
||||
{OSSL_DIGEST_PARAM_SSL3_MS, OSSL_PARAM_OCTET_STRING, NULL, 0, 0},
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM *shake_settable_ctx_params(void)
|
||||
{
|
||||
return known_shake_settable_ctx_params;
|
||||
}
|
||||
|
||||
static int shake_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
KECCAK1600_CTX *ctx = (KECCAK1600_CTX *)vctx;
|
||||
|
||||
if (ctx != NULL && params != NULL) {
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_XOFLEN);
|
||||
if (p != NULL && !OSSL_PARAM_get_size_t(p, &ctx->md_size))
|
||||
if (p != NULL && !OSSL_PARAM_get_size_t(p, &ctx->md_size)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0; /* Null Parameter */
|
||||
}
|
||||
|
||||
#define SHA3(bitlen) \
|
||||
SHA3_newctx(sha3, SHA3_##bitlen, sha3_##bitlen, bitlen, '\x06') \
|
||||
OSSL_FUNC_SHA3_DIGEST(sha3_##bitlen, bitlen, SHA3_MDSIZE(bitlen), NULL)
|
||||
#define IMPLEMENT_SHA3_functions(bitlen) \
|
||||
SHA3_newctx(sha3, SHA3_##bitlen, sha3_##bitlen, bitlen, '\x06') \
|
||||
PROV_FUNC_SHA3_DIGEST(sha3_##bitlen, bitlen, \
|
||||
SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen), \
|
||||
EVP_MD_FLAG_DIGALGID_ABSENT)
|
||||
|
||||
#define SHAKE(bitlen) \
|
||||
SHA3_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen, '\x1f') \
|
||||
OSSL_FUNC_SHA3_DIGEST(shake_##bitlen, bitlen, SHA3_MDSIZE(bitlen), \
|
||||
shake_set_params)
|
||||
#define KMAC(bitlen) \
|
||||
KMAC_newctx(keccak_kmac_##bitlen, bitlen, '\x04') \
|
||||
OSSL_FUNC_SHA3_DIGEST(keccak_kmac_##bitlen, bitlen, KMAC_MDSIZE(bitlen), \
|
||||
shake_set_params)
|
||||
#define IMPLEMENT_SHAKE_functions(bitlen) \
|
||||
SHA3_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen, '\x1f') \
|
||||
PROV_FUNC_SHAKE_DIGEST(shake_##bitlen, bitlen, \
|
||||
SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen), \
|
||||
EVP_MD_FLAG_XOF)
|
||||
#define IMPLEMENT_KMAC_functions(bitlen) \
|
||||
KMAC_newctx(keccak_kmac_##bitlen, bitlen, '\x04') \
|
||||
PROV_FUNC_SHAKE_DIGEST(keccak_kmac_##bitlen, bitlen, \
|
||||
SHA3_BLOCKSIZE(bitlen), KMAC_MDSIZE(bitlen), \
|
||||
EVP_MD_FLAG_XOF)
|
||||
|
||||
SHA3(224)
|
||||
SHA3(256)
|
||||
SHA3(384)
|
||||
SHA3(512)
|
||||
SHAKE(128)
|
||||
SHAKE(256)
|
||||
KMAC(128)
|
||||
KMAC(256)
|
||||
/* sha3_224_functions */
|
||||
IMPLEMENT_SHA3_functions(224)
|
||||
/* sha3_256_functions */
|
||||
IMPLEMENT_SHA3_functions(256)
|
||||
/* sha3_384_functions */
|
||||
IMPLEMENT_SHA3_functions(384)
|
||||
/* sha3_512_functions */
|
||||
IMPLEMENT_SHA3_functions(512)
|
||||
/* shake_128_functions */
|
||||
IMPLEMENT_SHAKE_functions(128)
|
||||
/* shake_256_functions */
|
||||
IMPLEMENT_SHAKE_functions(256)
|
||||
/* keccak_kmac_128_functions */
|
||||
IMPLEMENT_KMAC_functions(128)
|
||||
/* keccak_kmac_256_functions */
|
||||
IMPLEMENT_KMAC_functions(256)
|
||||
@@ -0,0 +1,7 @@
|
||||
LIBS=../../../libcrypto
|
||||
IF[{- !$disabled{dh} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
dh_exch.c
|
||||
ENDIF
|
||||
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/params.h>
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static OSSL_OP_keyexch_newctx_fn dh_newctx;
|
||||
static OSSL_OP_keyexch_init_fn dh_init;
|
||||
static OSSL_OP_keyexch_set_peer_fn dh_set_peer;
|
||||
static OSSL_OP_keyexch_derive_fn dh_derive;
|
||||
static OSSL_OP_keyexch_freectx_fn dh_freectx;
|
||||
static OSSL_OP_keyexch_dupctx_fn dh_dupctx;
|
||||
static OSSL_OP_keyexch_set_ctx_params_fn dh_set_ctx_params;
|
||||
static OSSL_OP_keyexch_settable_ctx_params_fn dh_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 DH structures, so
|
||||
* we use that here too.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
DH *dh;
|
||||
DH *dhpeer;
|
||||
unsigned int pad : 1;
|
||||
} PROV_DH_CTX;
|
||||
|
||||
static void *dh_newctx(void *provctx)
|
||||
{
|
||||
return OPENSSL_zalloc(sizeof(PROV_DH_CTX));
|
||||
}
|
||||
|
||||
static int dh_init(void *vpdhctx, void *vdh)
|
||||
{
|
||||
PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
|
||||
|
||||
if (pdhctx == NULL || vdh == NULL || !DH_up_ref(vdh))
|
||||
return 0;
|
||||
DH_free(pdhctx->dh);
|
||||
pdhctx->dh = vdh;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dh_set_peer(void *vpdhctx, void *vdh)
|
||||
{
|
||||
PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
|
||||
|
||||
if (pdhctx == NULL || vdh == NULL || !DH_up_ref(vdh))
|
||||
return 0;
|
||||
DH_free(pdhctx->dhpeer);
|
||||
pdhctx->dhpeer = vdh;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dh_derive(void *vpdhctx, unsigned char *secret, size_t *secretlen,
|
||||
size_t outlen)
|
||||
{
|
||||
PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
|
||||
int ret;
|
||||
size_t dhsize;
|
||||
const BIGNUM *pub_key = NULL;
|
||||
|
||||
/* TODO(3.0): Add errors to stack */
|
||||
if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL)
|
||||
return 0;
|
||||
|
||||
dhsize = (size_t)DH_size(pdhctx->dh);
|
||||
if (secret == NULL) {
|
||||
*secretlen = dhsize;
|
||||
return 1;
|
||||
}
|
||||
if (outlen < dhsize)
|
||||
return 0;
|
||||
|
||||
DH_get0_key(pdhctx->dhpeer, &pub_key, NULL);
|
||||
ret = (pdhctx->pad) ? DH_compute_key_padded(secret, pub_key, pdhctx->dh)
|
||||
: DH_compute_key(secret, pub_key, pdhctx->dh);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
|
||||
*secretlen = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void dh_freectx(void *vpdhctx)
|
||||
{
|
||||
PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
|
||||
|
||||
DH_free(pdhctx->dh);
|
||||
DH_free(pdhctx->dhpeer);
|
||||
|
||||
OPENSSL_free(pdhctx);
|
||||
}
|
||||
|
||||
static void *dh_dupctx(void *vpdhctx)
|
||||
{
|
||||
PROV_DH_CTX *srcctx = (PROV_DH_CTX *)vpdhctx;
|
||||
PROV_DH_CTX *dstctx;
|
||||
|
||||
dstctx = OPENSSL_zalloc(sizeof(*srcctx));
|
||||
if (dstctx == NULL)
|
||||
return NULL;
|
||||
|
||||
*dstctx = *srcctx;
|
||||
if (dstctx->dh != NULL && !DH_up_ref(dstctx->dh)) {
|
||||
OPENSSL_free(dstctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dstctx->dhpeer != NULL && !DH_up_ref(dstctx->dhpeer)) {
|
||||
DH_free(dstctx->dh);
|
||||
OPENSSL_free(dstctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dstctx;
|
||||
}
|
||||
|
||||
static int dh_set_ctx_params(void *vpdhctx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
|
||||
const OSSL_PARAM *p;
|
||||
unsigned int pad;
|
||||
|
||||
if (pdhctx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_PAD);
|
||||
if (p == NULL || !OSSL_PARAM_get_uint(p, &pad))
|
||||
return 0;
|
||||
pdhctx->pad = pad ? 1 : 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_PAD, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static const OSSL_PARAM *dh_settable_ctx_params(void)
|
||||
{
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH dh_keyexch_functions[] = {
|
||||
{ OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))dh_newctx },
|
||||
{ OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))dh_init },
|
||||
{ OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))dh_derive },
|
||||
{ OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer },
|
||||
{ OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx },
|
||||
{ OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx },
|
||||
{ OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))dh_set_ctx_params },
|
||||
{ OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))dh_settable_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define UNINITIALISED_SIZET ((size_t)-1)
|
||||
|
||||
/* TODO(3.0) Figure out what flags are really needed */
|
||||
#define AEAD_FLAGS (EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_DEFAULT_ASN1 \
|
||||
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
|
||||
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
|
||||
| EVP_CIPH_CUSTOM_COPY)
|
||||
|
||||
#define IMPLEMENT_aead_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, 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, kbits); \
|
||||
} \
|
||||
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_GET_CTX_PARAMS, \
|
||||
(void (*)(void)) lc##_get_ctx_params }, \
|
||||
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
|
||||
(void (*)(void)) lc##_set_ctx_params }, \
|
||||
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
|
||||
(void (*)(void))cipher_generic_gettable_params }, \
|
||||
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
|
||||
(void (*)(void))cipher_aead_gettable_ctx_params }, \
|
||||
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
|
||||
(void (*)(void))cipher_aead_settable_ctx_params }, \
|
||||
{ 0, NULL } \
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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 "cipher_aead.h"
|
||||
|
||||
typedef struct prov_ccm_hw_st PROV_CCM_HW;
|
||||
|
||||
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
|
||||
/*-
|
||||
* KMAC-AES parameter block - begin
|
||||
* (see z/Architecture Principles of Operation >= SA22-7832-08)
|
||||
*/
|
||||
typedef struct S390X_kmac_params_st {
|
||||
union {
|
||||
unsigned long long g[2];
|
||||
unsigned char b[16];
|
||||
} icv;
|
||||
unsigned char k[32];
|
||||
} S390X_KMAC_PARAMS;
|
||||
/* KMAC-AES parameter block - end */
|
||||
#endif
|
||||
|
||||
/* Base structure that is shared by AES & ARIA for CCM MODE */
|
||||
typedef struct prov_ccm_st {
|
||||
unsigned int enc : 1;
|
||||
unsigned int key_set : 1; /* Set if key initialised */
|
||||
unsigned int iv_set : 1; /* Set if an iv is set */
|
||||
unsigned int tag_set : 1; /* Set if tag is valid */
|
||||
unsigned int len_set : 1; /* Set if message length set */
|
||||
size_t l, m; /* L and M parameters from RFC3610 */
|
||||
size_t keylen;
|
||||
size_t tls_aad_len; /* TLS AAD length */
|
||||
size_t tls_aad_pad_sz;
|
||||
unsigned char iv[AES_BLOCK_SIZE];
|
||||
unsigned char buf[AES_BLOCK_SIZE];
|
||||
CCM128_CONTEXT ccm_ctx;
|
||||
ccm128_f str;
|
||||
const PROV_CCM_HW *hw; /* hardware specific methods */
|
||||
} PROV_CCM_CTX;
|
||||
|
||||
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;
|
||||
|
||||
PROV_CIPHER_FUNC(int, CCM_cipher, (PROV_CCM_CTX *ctx, unsigned char *out, \
|
||||
size_t *padlen, const unsigned char *in, \
|
||||
size_t len));
|
||||
PROV_CIPHER_FUNC(int, CCM_setkey, (PROV_CCM_CTX *ctx, \
|
||||
const unsigned char *key, size_t keylen));
|
||||
PROV_CIPHER_FUNC(int, CCM_setiv, (PROV_CCM_CTX *dat, \
|
||||
const unsigned char *iv, size_t ivlen, \
|
||||
size_t mlen));
|
||||
PROV_CIPHER_FUNC(int, CCM_setaad, (PROV_CCM_CTX *ctx, \
|
||||
const unsigned char *aad, size_t aadlen));
|
||||
PROV_CIPHER_FUNC(int, CCM_auth_encrypt, (PROV_CCM_CTX *ctx, \
|
||||
const unsigned char *in, \
|
||||
unsigned char *out, size_t len, \
|
||||
unsigned char *tag, size_t taglen));
|
||||
PROV_CIPHER_FUNC(int, CCM_auth_decrypt, (PROV_CCM_CTX *ctx, \
|
||||
const unsigned char *in, \
|
||||
unsigned char *out, size_t len, \
|
||||
unsigned char *tag, size_t taglen));
|
||||
PROV_CIPHER_FUNC(int, CCM_gettag, (PROV_CCM_CTX *ctx, \
|
||||
unsigned char *tag, size_t taglen));
|
||||
|
||||
/*
|
||||
* CCM Mode internal method table used to handle hardware specific differences,
|
||||
* (and different algorithms).
|
||||
*/
|
||||
struct prov_ccm_hw_st {
|
||||
OSSL_CCM_setkey_fn setkey;
|
||||
OSSL_CCM_setiv_fn setiv;
|
||||
OSSL_CCM_setaad_fn setaad;
|
||||
OSSL_CCM_auth_encrypt_fn auth_encrypt;
|
||||
OSSL_CCM_auth_decrypt_fn auth_decrypt;
|
||||
OSSL_CCM_gettag_fn gettag;
|
||||
};
|
||||
|
||||
const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keylen);
|
||||
|
||||
OSSL_OP_cipher_encrypt_init_fn ccm_einit;
|
||||
OSSL_OP_cipher_decrypt_init_fn ccm_dinit;
|
||||
OSSL_OP_cipher_get_ctx_params_fn ccm_get_ctx_params;
|
||||
OSSL_OP_cipher_set_ctx_params_fn ccm_set_ctx_params;
|
||||
OSSL_OP_cipher_update_fn ccm_stream_update;
|
||||
OSSL_OP_cipher_final_fn ccm_stream_final;
|
||||
OSSL_OP_cipher_cipher_fn ccm_cipher;
|
||||
void ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw);
|
||||
void ccm_finalctx(PROV_CCM_CTX *ctx);
|
||||
|
||||
int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce,
|
||||
size_t nlen, size_t mlen);
|
||||
int ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad, size_t alen);
|
||||
int ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag, size_t tlen);
|
||||
int ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
|
||||
unsigned char *out, size_t len,
|
||||
unsigned char *tag, size_t taglen);
|
||||
int ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
|
||||
unsigned char *out, size_t len,
|
||||
unsigned char *expected_tag, size_t taglen);
|
||||
@@ -0,0 +1,161 @@
|
||||
|
||||
/*
|
||||
* 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 "cipher_aead.h"
|
||||
|
||||
typedef struct prov_gcm_hw_st PROV_GCM_HW;
|
||||
|
||||
#define GCM_IV_DEFAULT_SIZE 12 /* IV's for AES_GCM should normally be 12 bytes */
|
||||
#define GCM_IV_MAX_SIZE 64
|
||||
#define GCM_TAG_MAX_SIZE 16
|
||||
|
||||
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
|
||||
/*-
|
||||
* KMA-GCM-AES parameter block - begin
|
||||
* (see z/Architecture Principles of Operation >= SA22-7832-11)
|
||||
*/
|
||||
typedef struct S390X_kma_params_st {
|
||||
unsigned char reserved[12];
|
||||
union {
|
||||
unsigned int w;
|
||||
unsigned char b[4];
|
||||
} cv; /* 32 bit counter value */
|
||||
union {
|
||||
unsigned long long g[2];
|
||||
unsigned char b[16];
|
||||
} t; /* tag */
|
||||
unsigned char h[16]; /* hash subkey */
|
||||
unsigned long long taadl; /* total AAD length */
|
||||
unsigned long long tpcl; /* total plaintxt/ciphertxt len */
|
||||
union {
|
||||
unsigned long long g[2];
|
||||
unsigned int w[4];
|
||||
} j0; /* initial counter value */
|
||||
unsigned char k[32]; /* key */
|
||||
} S390X_KMA_PARAMS;
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct prov_gcm_ctx_st {
|
||||
unsigned int mode; /* The mode that we are using */
|
||||
size_t keylen;
|
||||
size_t ivlen;
|
||||
size_t ivlen_min;
|
||||
size_t taglen;
|
||||
size_t tls_aad_pad_sz;
|
||||
size_t tls_aad_len; /* TLS AAD length */
|
||||
uint64_t tls_enc_records; /* Number of TLS records encrypted */
|
||||
|
||||
/*
|
||||
* num contains the number of bytes of |iv| which are valid for modes that
|
||||
* manage partial blocks themselves.
|
||||
*/
|
||||
size_t num;
|
||||
size_t bufsz; /* Number of bytes in buf */
|
||||
uint64_t flags;
|
||||
|
||||
unsigned int iv_state; /* set to one of IV_STATE_XXX */
|
||||
unsigned int enc:1; /* Set to 1 if we are encrypting or 0 otherwise */
|
||||
unsigned int pad:1; /* Whether padding should be used or not */
|
||||
unsigned int key_set:1; /* Set if key initialised */
|
||||
unsigned int iv_gen_rand:1; /* No IV was specified, so generate a rand IV */
|
||||
unsigned int iv_gen:1; /* It is OK to generate IVs */
|
||||
|
||||
unsigned char iv[GCM_IV_MAX_SIZE]; /* Buffer to use for IV's */
|
||||
unsigned char buf[AES_BLOCK_SIZE]; /* Buffer of partial blocks processed via update calls */
|
||||
|
||||
OPENSSL_CTX *libctx; /* needed for rand calls */
|
||||
const PROV_GCM_HW *hw; /* hardware specific methods */
|
||||
GCM128_CONTEXT gcm;
|
||||
ctr128_f ctr;
|
||||
const void *ks;
|
||||
} PROV_GCM_CTX;
|
||||
|
||||
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;
|
||||
|
||||
PROV_CIPHER_FUNC(int, GCM_setkey, (PROV_GCM_CTX *ctx, const unsigned char *key,
|
||||
size_t keylen));
|
||||
PROV_CIPHER_FUNC(int, GCM_setiv, (PROV_GCM_CTX *dat, const unsigned char *iv,
|
||||
size_t ivlen));
|
||||
PROV_CIPHER_FUNC(int, GCM_aadupdate, (PROV_GCM_CTX *ctx,
|
||||
const unsigned char *aad, size_t aadlen));
|
||||
PROV_CIPHER_FUNC(int, GCM_cipherupdate, (PROV_GCM_CTX *ctx,
|
||||
const unsigned char *in, size_t len,
|
||||
unsigned char *out));
|
||||
PROV_CIPHER_FUNC(int, GCM_cipherfinal, (PROV_GCM_CTX *ctx, unsigned char *tag));
|
||||
PROV_CIPHER_FUNC(int, GCM_oneshot, (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 taglen));
|
||||
struct prov_gcm_hw_st {
|
||||
OSSL_GCM_setkey_fn setkey;
|
||||
OSSL_GCM_setiv_fn setiv;
|
||||
OSSL_GCM_aadupdate_fn aadupdate;
|
||||
OSSL_GCM_cipherupdate_fn cipherupdate;
|
||||
OSSL_GCM_cipherfinal_fn cipherfinal;
|
||||
OSSL_GCM_oneshot_fn oneshot;
|
||||
};
|
||||
const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits);
|
||||
|
||||
OSSL_OP_cipher_encrypt_init_fn gcm_einit;
|
||||
OSSL_OP_cipher_decrypt_init_fn gcm_dinit;
|
||||
OSSL_OP_cipher_get_ctx_params_fn gcm_get_ctx_params;
|
||||
OSSL_OP_cipher_set_ctx_params_fn gcm_set_ctx_params;
|
||||
OSSL_OP_cipher_cipher_fn gcm_cipher;
|
||||
OSSL_OP_cipher_update_fn gcm_stream_update;
|
||||
OSSL_OP_cipher_final_fn gcm_stream_final;
|
||||
void gcm_deinitctx(PROV_GCM_CTX *ctx);
|
||||
void gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits,
|
||||
const PROV_GCM_HW *hw, size_t ivlen_min);
|
||||
|
||||
int gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen);
|
||||
int gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad,
|
||||
size_t aad_len);
|
||||
int gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag);
|
||||
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 gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
|
||||
size_t len, unsigned char *out);
|
||||
|
||||
#define GCM_HW_SET_KEY_CTR_FN(ks, fn_set_enc_key, fn_block, fn_ctr) \
|
||||
ctx->ks = ks; \
|
||||
fn_set_enc_key(key, keylen * 8, ks); \
|
||||
CRYPTO_gcm128_init(&ctx->gcm, ks, (block128_f)fn_block); \
|
||||
ctx->ctr = (ctr128_f)fn_ctr; \
|
||||
ctx->key_set = 1;
|
||||
@@ -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/des.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
|
||||
#define DES_BLOCK_SIZE 8
|
||||
#define TDES_IVLEN 8
|
||||
|
||||
/* TODO(3.0) Figure out what flags need to be here */
|
||||
#define TDES_FLAGS (EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1)
|
||||
|
||||
typedef struct prov_tdes_ctx_st {
|
||||
PROV_CIPHER_CTX base; /* Must be first */
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
DES_key_schedule ks[3];
|
||||
} tks;
|
||||
union {
|
||||
void (*cbc) (const void *, void *, size_t,
|
||||
const DES_key_schedule *, unsigned char *);
|
||||
} tstream;
|
||||
|
||||
} PROV_TDES_CTX;
|
||||
|
||||
#define IMPLEMENT_tdes_cipher(type, UCTYPE, lcmode, UCMODE, flags, \
|
||||
kbits, blkbits, ivbits, block) \
|
||||
static OSSL_OP_cipher_newctx_fn tdes_##type##_##lcmode##_newctx; \
|
||||
static void *tdes_##type##_##lcmode##_newctx(void *provctx) \
|
||||
{ \
|
||||
return tdes_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, kbits, blkbits, \
|
||||
ivbits, flags, PROV_CIPHER_HW_tdes_##type##_##lcmode());\
|
||||
} \
|
||||
static OSSL_OP_cipher_get_params_fn tdes_##type##_##lcmode##_get_params; \
|
||||
static int tdes_##type##_##lcmode##_get_params(OSSL_PARAM params[]) \
|
||||
{ \
|
||||
return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, flags, \
|
||||
kbits, blkbits, ivbits); \
|
||||
} \
|
||||
const OSSL_DISPATCH tdes_##type##_##lcmode##_functions[] = { \
|
||||
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))tdes_einit }, \
|
||||
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))tdes_dinit }, \
|
||||
{ OSSL_FUNC_CIPHER_UPDATE, \
|
||||
(void (*)(void))cipher_generic_##block##_update }, \
|
||||
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##block##_final },\
|
||||
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \
|
||||
{ OSSL_FUNC_CIPHER_NEWCTX, \
|
||||
(void (*)(void))tdes_##type##_##lcmode##_newctx }, \
|
||||
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))tdes_freectx }, \
|
||||
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
|
||||
(void (*)(void))tdes_##type##_##lcmode##_get_params }, \
|
||||
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
|
||||
(void (*)(void))cipher_generic_gettable_params }, \
|
||||
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))tdes_get_ctx_params }, \
|
||||
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
|
||||
(void (*)(void))tdes_gettable_ctx_params }, \
|
||||
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
|
||||
(void (*)(void))cipher_generic_set_ctx_params }, \
|
||||
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
|
||||
(void (*)(void))cipher_generic_settable_ctx_params }, \
|
||||
{ 0, NULL } \
|
||||
}
|
||||
|
||||
void *tdes_newctx(void *provctx, int mode, size_t kbits, size_t blkbits,
|
||||
size_t ivbits, uint64_t flags, const PROV_CIPHER_HW *hw);
|
||||
OSSL_OP_cipher_freectx_fn tdes_freectx;
|
||||
OSSL_OP_cipher_encrypt_init_fn tdes_einit;
|
||||
OSSL_OP_cipher_decrypt_init_fn tdes_dinit;
|
||||
OSSL_OP_cipher_get_ctx_params_fn tdes_get_ctx_params;
|
||||
OSSL_OP_cipher_gettable_ctx_params_fn tdes_gettable_ctx_params;
|
||||
|
||||
#define PROV_CIPHER_HW_tdes_mode(type, mode) \
|
||||
static const PROV_CIPHER_HW type##_##mode = { \
|
||||
cipher_hw_tdes_##type##_initkey, \
|
||||
cipher_hw_tdes_##mode \
|
||||
}; \
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_##type##_##mode(void) \
|
||||
{ \
|
||||
return &type##_##mode; \
|
||||
}
|
||||
|
||||
int cipher_hw_tdes_ede3_initkey(PROV_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
size_t keylen);
|
||||
int cipher_hw_tdes_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl);
|
||||
int cipher_hw_tdes_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_ede3_cbc(void);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_ede3_ecb(void);
|
||||
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* 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/params.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/modes_int.h"
|
||||
#include "internal/ciphermode_platform.h"
|
||||
|
||||
#define MAXCHUNK ((size_t)1 << (sizeof(long) * 8 - 2))
|
||||
#define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4))
|
||||
|
||||
#define GENERIC_BLOCK_SIZE 16
|
||||
#define IV_STATE_UNINITIALISED 0 /* initial state is not initialized */
|
||||
#define IV_STATE_BUFFERED 1 /* iv has been copied to the iv buffer */
|
||||
#define IV_STATE_COPIED 2 /* iv has been copied from the iv buffer */
|
||||
#define IV_STATE_FINISHED 3 /* the iv has been used - so don't reuse it */
|
||||
|
||||
#define PROV_CIPHER_FUNC(type, name, args) typedef type (* OSSL_##name##_fn)args
|
||||
|
||||
typedef struct prov_cipher_hw_st PROV_CIPHER_HW;
|
||||
typedef struct prov_cipher_ctx_st PROV_CIPHER_CTX;
|
||||
|
||||
typedef int (PROV_CIPHER_HW_FN)(PROV_CIPHER_CTX *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
struct prov_cipher_ctx_st {
|
||||
block128_f block;
|
||||
union {
|
||||
cbc128_f cbc;
|
||||
ctr128_f ctr;
|
||||
} stream;
|
||||
|
||||
unsigned int mode;
|
||||
size_t keylen; /* key size (in bytes) */
|
||||
size_t ivlen;
|
||||
size_t blocksize;
|
||||
size_t bufsz; /* Number of bytes in buf */
|
||||
unsigned int pad : 1; /* Whether padding should be used or not */
|
||||
unsigned int enc : 1; /* Set to 1 for encrypt, or 0 otherwise */
|
||||
|
||||
/*
|
||||
* num contains the number of bytes of |iv| which are valid for modes that
|
||||
* manage partial blocks themselves.
|
||||
*/
|
||||
unsigned int num;
|
||||
uint64_t flags;
|
||||
|
||||
/* Buffer of partial blocks processed via update calls */
|
||||
unsigned char buf[GENERIC_BLOCK_SIZE];
|
||||
unsigned char iv[GENERIC_BLOCK_SIZE];
|
||||
const PROV_CIPHER_HW *hw; /* hardware specific functions */
|
||||
const void *ks; /* Pointer to algorithm specific key data */
|
||||
OPENSSL_CTX *libctx;
|
||||
};
|
||||
|
||||
struct prov_cipher_hw_st {
|
||||
int (*init)(PROV_CIPHER_CTX *dat, const uint8_t *key, size_t keylen);
|
||||
PROV_CIPHER_HW_FN *cipher;
|
||||
};
|
||||
|
||||
OSSL_OP_cipher_encrypt_init_fn cipher_generic_einit;
|
||||
OSSL_OP_cipher_decrypt_init_fn cipher_generic_dinit;
|
||||
OSSL_OP_cipher_update_fn cipher_generic_block_update;
|
||||
OSSL_OP_cipher_final_fn cipher_generic_block_final;
|
||||
OSSL_OP_cipher_update_fn cipher_generic_stream_update;
|
||||
OSSL_OP_cipher_final_fn cipher_generic_stream_final;
|
||||
OSSL_OP_cipher_cipher_fn cipher_generic_cipher;
|
||||
OSSL_OP_cipher_get_ctx_params_fn cipher_generic_get_ctx_params;
|
||||
OSSL_OP_cipher_set_ctx_params_fn cipher_generic_set_ctx_params;
|
||||
OSSL_OP_cipher_gettable_params_fn cipher_generic_gettable_params;
|
||||
OSSL_OP_cipher_gettable_ctx_params_fn cipher_generic_gettable_ctx_params;
|
||||
OSSL_OP_cipher_settable_ctx_params_fn cipher_generic_settable_ctx_params;
|
||||
OSSL_OP_cipher_gettable_ctx_params_fn cipher_aead_gettable_ctx_params;
|
||||
OSSL_OP_cipher_settable_ctx_params_fn cipher_aead_settable_ctx_params;
|
||||
int cipher_generic_get_params(OSSL_PARAM params[], unsigned int md,
|
||||
unsigned long flags,
|
||||
size_t kbits, size_t blkbits, size_t ivbits);
|
||||
void cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits,
|
||||
size_t ivbits, unsigned int mode, uint64_t flags,
|
||||
const PROV_CIPHER_HW *hw, void *provctx);
|
||||
|
||||
#define IMPLEMENT_generic_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \
|
||||
blkbits, ivbits, typ) \
|
||||
static OSSL_OP_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \
|
||||
static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
|
||||
{ \
|
||||
return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, flags, \
|
||||
kbits, blkbits, ivbits); \
|
||||
} \
|
||||
static OSSL_OP_cipher_newctx_fn alg##_##kbits##_##lcmode##_newctx; \
|
||||
static void * alg##_##kbits##_##lcmode##_newctx(void *provctx) \
|
||||
{ \
|
||||
PROV_##UCALG##_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
|
||||
if (ctx != NULL) { \
|
||||
cipher_generic_initkey(ctx, kbits, blkbits, ivbits, \
|
||||
EVP_CIPH_##UCMODE##_MODE, flags, \
|
||||
PROV_CIPHER_HW_##alg##_##lcmode(kbits), NULL); \
|
||||
} \
|
||||
return ctx; \
|
||||
} \
|
||||
const OSSL_DISPATCH alg##kbits##lcmode##_functions[] = { \
|
||||
{ OSSL_FUNC_CIPHER_NEWCTX, \
|
||||
(void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \
|
||||
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \
|
||||
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \
|
||||
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))cipher_generic_einit }, \
|
||||
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))cipher_generic_dinit }, \
|
||||
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))cipher_generic_##typ##_update },\
|
||||
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##typ##_final }, \
|
||||
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \
|
||||
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
|
||||
(void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \
|
||||
{ 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 }, \
|
||||
{ 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 }, \
|
||||
{ 0, NULL } \
|
||||
};
|
||||
|
||||
PROV_CIPHER_HW_FN cipher_hw_generic_cbc;
|
||||
PROV_CIPHER_HW_FN cipher_hw_generic_ecb;
|
||||
PROV_CIPHER_HW_FN cipher_hw_generic_ofb128;
|
||||
PROV_CIPHER_HW_FN cipher_hw_generic_cfb128;
|
||||
PROV_CIPHER_HW_FN cipher_hw_generic_cfb8;
|
||||
PROV_CIPHER_HW_FN cipher_hw_generic_cfb1;
|
||||
PROV_CIPHER_HW_FN cipher_hw_generic_ctr;
|
||||
PROV_CIPHER_HW_FN cipher_hw_chunked_cbc;
|
||||
PROV_CIPHER_HW_FN cipher_hw_chunked_cfb8;
|
||||
PROV_CIPHER_HW_FN cipher_hw_chunked_cfb128;
|
||||
PROV_CIPHER_HW_FN cipher_hw_chunked_ofb128;
|
||||
#define cipher_hw_chunked_ecb cipher_hw_generic_ecb
|
||||
#define cipher_hw_chunked_ctr cipher_hw_generic_ctr
|
||||
#define cipher_hw_chunked_cfb1 cipher_hw_generic_cfb1
|
||||
|
||||
#define IMPLEMENT_CIPHER_HW_OFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \
|
||||
static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \
|
||||
unsigned char *out, \
|
||||
const unsigned char *in, size_t len) \
|
||||
{ \
|
||||
int num = ctx->num; \
|
||||
KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \
|
||||
\
|
||||
while (len >= MAXCHUNK) { \
|
||||
FUNC_PREFIX##_encrypt(in, out, MAXCHUNK, key, ctx->iv, &num); \
|
||||
len -= MAXCHUNK; \
|
||||
in += MAXCHUNK; \
|
||||
out += MAXCHUNK; \
|
||||
} \
|
||||
if (len > 0) { \
|
||||
FUNC_PREFIX##_encrypt(in, out, (long)len, key, ctx->iv, &num); \
|
||||
} \
|
||||
ctx->num = num; \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define IMPLEMENT_CIPHER_HW_ECB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \
|
||||
static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \
|
||||
unsigned char *out, \
|
||||
const unsigned char *in, size_t len) \
|
||||
{ \
|
||||
size_t i, bl = ctx->blocksize; \
|
||||
KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \
|
||||
\
|
||||
if (len < bl) \
|
||||
return 1; \
|
||||
for (i = 0, len -= bl; i <= len; i += bl) \
|
||||
FUNC_PREFIX##_encrypt(in + i, out + i, key, ctx->enc); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define IMPLEMENT_CIPHER_HW_CBC(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \
|
||||
static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \
|
||||
unsigned char *out, \
|
||||
const unsigned char *in, size_t len) \
|
||||
{ \
|
||||
KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \
|
||||
\
|
||||
while (len >= MAXCHUNK) { \
|
||||
FUNC_PREFIX##_encrypt(in, out, MAXCHUNK, key, ctx->iv, ctx->enc); \
|
||||
len -= MAXCHUNK; \
|
||||
in += MAXCHUNK; \
|
||||
out += MAXCHUNK; \
|
||||
} \
|
||||
if (len > 0) \
|
||||
FUNC_PREFIX##_encrypt(in, out, (long)len, key, ctx->iv, ctx->enc); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define IMPLEMENT_CIPHER_HW_CFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \
|
||||
static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \
|
||||
unsigned char *out, \
|
||||
const unsigned char *in, size_t len) \
|
||||
{ \
|
||||
size_t chunk = MAXCHUNK; \
|
||||
KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \
|
||||
int num = ctx->num; \
|
||||
\
|
||||
if (len < chunk) \
|
||||
chunk = len; \
|
||||
while (len > 0 && len >= chunk) { \
|
||||
FUNC_PREFIX##_encrypt(in, out, (long)chunk, key, ctx->iv, &num, \
|
||||
ctx->enc); \
|
||||
len -= chunk; \
|
||||
in += chunk; \
|
||||
out += chunk; \
|
||||
if (len < chunk) \
|
||||
chunk = len; \
|
||||
} \
|
||||
ctx->num = num; \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize,
|
||||
const unsigned char **in, size_t *inlen);
|
||||
int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize,
|
||||
const unsigned char **in, size_t *inlen);
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef OSSL_CORE_MKDIGEST_H
|
||||
# define OSSL_CORE_MKDIGEST_H
|
||||
|
||||
# include <openssl/core_numbers.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
# define OSSL_FUNC_DIGEST_ALLOC_METHODS(name, CTX_NAME) \
|
||||
static OSSL_OP_digest_newctx_fn name##_newctx; \
|
||||
static OSSL_OP_digest_freectx_fn name##_freectx; \
|
||||
static OSSL_OP_digest_dupctx_fn name##_dupctx; \
|
||||
static void *name##_newctx(void *prov_ctx) \
|
||||
{ \
|
||||
CTX_NAME *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
|
||||
return ctx; \
|
||||
} \
|
||||
static void name##_freectx(void *vctx) \
|
||||
{ \
|
||||
CTX_NAME *ctx = (CTX_NAME *)vctx; \
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx)); \
|
||||
} \
|
||||
static void *name##_dupctx(void *ctx) \
|
||||
{ \
|
||||
CTX_NAME *in = (CTX_NAME *)ctx; \
|
||||
CTX_NAME *ret = OPENSSL_malloc(sizeof(*ret)); \
|
||||
*ret = *in; \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
# define OSSL_FUNC_DIGEST_SET_FINAL(name, dgstsize, fin) \
|
||||
static OSSL_OP_digest_final_fn name##_wrapfinal; \
|
||||
static int name##_wrapfinal(void *ctx, unsigned char *out, size_t *outl, size_t outsz) \
|
||||
{ \
|
||||
if (outsz >= dgstsize && fin(out, ctx)) { \
|
||||
*outl = dgstsize; \
|
||||
return 1; \
|
||||
} \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
# define OSSL_FUNC_DIGEST_COMMON(name, blksize, dgstsize, init, upd) \
|
||||
static OSSL_OP_digest_block_size_fn name##_block_size; \
|
||||
static OSSL_OP_digest_size_fn name##_size; \
|
||||
static size_t name##_block_size(void) \
|
||||
{ \
|
||||
return blksize; \
|
||||
} \
|
||||
static size_t name##_size(void) \
|
||||
{ \
|
||||
return dgstsize; \
|
||||
} \
|
||||
const OSSL_DISPATCH name##_functions[] = { \
|
||||
{ OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx }, \
|
||||
{ OSSL_FUNC_DIGEST_INIT, (void (*)(void))init }, \
|
||||
{ OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))upd }, \
|
||||
{ OSSL_FUNC_DIGEST_FINAL, (void (*)(void))name##_wrapfinal }, \
|
||||
{ OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))name##_freectx }, \
|
||||
{ OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))name##_dupctx }, \
|
||||
{ OSSL_FUNC_DIGEST_SIZE, (void (*)(void))name##_size }, \
|
||||
{ OSSL_FUNC_DIGEST_BLOCK_SIZE, (void (*)(void))name##_block_size },
|
||||
|
||||
# define OSSL_FUNC_DIGEST_CONSTRUCT_START(name, CTX, blksize, dgstsize, init, upd, fin) \
|
||||
OSSL_FUNC_DIGEST_ALLOC_METHODS(name, CTX) \
|
||||
OSSL_FUNC_DIGEST_SET_FINAL(name, dgstsize, fin) \
|
||||
OSSL_FUNC_DIGEST_COMMON(name, blksize, dgstsize, init, upd)
|
||||
|
||||
# define OSSL_FUNC_DIGEST_CONSTRUCT_END \
|
||||
{ 0, NULL } \
|
||||
};
|
||||
|
||||
# define OSSL_FUNC_DIGEST_CONSTRUCT(name, CTX, blksize, dgstsize, init, upd, fin) \
|
||||
OSSL_FUNC_DIGEST_CONSTRUCT_START(name, CTX, blksize, dgstsize, init, upd, fin) \
|
||||
OSSL_FUNC_DIGEST_CONSTRUCT_END
|
||||
|
||||
# define OSSL_FUNC_DIGEST_CONSTRUCT_PARAMS(name, CTX, blksize, dgstsize, init, upd, fin, setparams) \
|
||||
OSSL_FUNC_DIGEST_CONSTRUCT_START(name, CTX, blksize, dgstsize, init, upd, fin) \
|
||||
{ OSSL_FUNC_DIGEST_SET_PARAMS, (void (*)(void))setparams }, \
|
||||
OSSL_FUNC_DIGEST_CONSTRUCT_END
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif /* OSSL_CORE_MKDIGEST_H */
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef OSSL_DIGESTCOMMON_H
|
||||
# define OSSL_DIGESTCOMMON_H
|
||||
|
||||
# include <openssl/core_numbers.h>
|
||||
# include <openssl/core_names.h>
|
||||
# include <openssl/params.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
#define PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \
|
||||
static OSSL_OP_digest_get_params_fn name##_get_params; \
|
||||
static int name##_get_params(OSSL_PARAM params[]) \
|
||||
{ \
|
||||
return digest_default_get_params(params, blksize, dgstsize, flags); \
|
||||
}
|
||||
|
||||
#define PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name) \
|
||||
{ OSSL_FUNC_DIGEST_GET_PARAMS, (void (*)(void))name##_get_params }, \
|
||||
{ OSSL_FUNC_DIGEST_GETTABLE_PARAMS, \
|
||||
(void (*)(void))digest_default_gettable_params }
|
||||
|
||||
# define PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_START( \
|
||||
name, CTX, blksize, dgstsize, flags, init, upd, fin) \
|
||||
static OSSL_OP_digest_newctx_fn name##_newctx; \
|
||||
static OSSL_OP_digest_freectx_fn name##_freectx; \
|
||||
static OSSL_OP_digest_dupctx_fn name##_dupctx; \
|
||||
static void *name##_newctx(void *prov_ctx) \
|
||||
{ \
|
||||
CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
|
||||
return ctx; \
|
||||
} \
|
||||
static void name##_freectx(void *vctx) \
|
||||
{ \
|
||||
CTX *ctx = (CTX *)vctx; \
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx)); \
|
||||
} \
|
||||
static void *name##_dupctx(void *ctx) \
|
||||
{ \
|
||||
CTX *in = (CTX *)ctx; \
|
||||
CTX *ret = OPENSSL_malloc(sizeof(*ret)); \
|
||||
*ret = *in; \
|
||||
return ret; \
|
||||
} \
|
||||
static OSSL_OP_digest_final_fn name##_internal_final; \
|
||||
static int name##_internal_final(void *ctx, unsigned char *out, size_t *outl, \
|
||||
size_t outsz) \
|
||||
{ \
|
||||
if (outsz >= dgstsize && fin(out, ctx)) { \
|
||||
*outl = dgstsize; \
|
||||
return 1; \
|
||||
} \
|
||||
return 0; \
|
||||
} \
|
||||
PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \
|
||||
const OSSL_DISPATCH name##_functions[] = { \
|
||||
{ OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx }, \
|
||||
{ OSSL_FUNC_DIGEST_INIT, (void (*)(void))init }, \
|
||||
{ OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))upd }, \
|
||||
{ OSSL_FUNC_DIGEST_FINAL, (void (*)(void))name##_internal_final }, \
|
||||
{ OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))name##_freectx }, \
|
||||
{ OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))name##_dupctx }, \
|
||||
PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name)
|
||||
|
||||
# define PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END \
|
||||
{ 0, NULL } \
|
||||
};
|
||||
|
||||
# define IMPLEMENT_digest_functions( \
|
||||
name, CTX, blksize, dgstsize, flags, init, upd, fin) \
|
||||
PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_START(name, CTX, blksize, dgstsize, flags, \
|
||||
init, upd, fin), \
|
||||
PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END
|
||||
|
||||
# define IMPLEMENT_digest_functions_with_settable_ctx( \
|
||||
name, CTX, blksize, dgstsize, flags, init, upd, fin, \
|
||||
settable_ctx_params, set_ctx_params) \
|
||||
PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_START(name, CTX, blksize, dgstsize, flags, \
|
||||
init, upd, fin), \
|
||||
{ OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS, (void (*)(void))settable_ctx_params }, \
|
||||
{ OSSL_FUNC_DIGEST_SET_CTX_PARAMS, (void (*)(void))set_ctx_params }, \
|
||||
PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END
|
||||
|
||||
|
||||
const OSSL_PARAM *digest_default_gettable_params(void);
|
||||
int digest_default_get_params(OSSL_PARAM params[], size_t blksz, size_t paramsz,
|
||||
unsigned long flags);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif /* OSSL_DIGESTCOMMON_H */
|
||||
@@ -28,7 +28,6 @@ extern const OSSL_DISPATCH blake2b512_functions[];
|
||||
extern const OSSL_DISPATCH md5_functions[];
|
||||
extern const OSSL_DISPATCH md5_sha1_functions[];
|
||||
extern const OSSL_DISPATCH sm3_functions[];
|
||||
extern const OSSL_DISPATCH nullmd_functions[];
|
||||
extern const OSSL_DISPATCH md2_functions[];
|
||||
extern const OSSL_DISPATCH md4_functions[];
|
||||
extern const OSSL_DISPATCH mdc2_functions[];
|
||||
@@ -57,3 +56,160 @@ extern const OSSL_DISPATCH aes128cfb8_functions[];
|
||||
extern const OSSL_DISPATCH aes256ctr_functions[];
|
||||
extern const OSSL_DISPATCH aes192ctr_functions[];
|
||||
extern const OSSL_DISPATCH aes128ctr_functions[];
|
||||
extern const OSSL_DISPATCH aes256xts_functions[];
|
||||
extern const OSSL_DISPATCH aes128xts_functions[];
|
||||
#ifndef OPENSSL_NO_OCB
|
||||
extern const OSSL_DISPATCH aes256ocb_functions[];
|
||||
extern const OSSL_DISPATCH aes192ocb_functions[];
|
||||
extern const OSSL_DISPATCH aes128ocb_functions[];
|
||||
#endif /* OPENSSL_NO_OCB */
|
||||
extern const OSSL_DISPATCH aes256gcm_functions[];
|
||||
extern const OSSL_DISPATCH aes192gcm_functions[];
|
||||
extern const OSSL_DISPATCH aes128gcm_functions[];
|
||||
extern const OSSL_DISPATCH aes256ccm_functions[];
|
||||
extern const OSSL_DISPATCH aes192ccm_functions[];
|
||||
extern const OSSL_DISPATCH aes128ccm_functions[];
|
||||
extern const OSSL_DISPATCH aes256wrap_functions[];
|
||||
extern const OSSL_DISPATCH aes192wrap_functions[];
|
||||
extern const OSSL_DISPATCH aes128wrap_functions[];
|
||||
extern const OSSL_DISPATCH aes256wrappad_functions[];
|
||||
extern const OSSL_DISPATCH aes192wrappad_functions[];
|
||||
extern const OSSL_DISPATCH aes128wrappad_functions[];
|
||||
|
||||
#ifndef OPENSSL_NO_ARIA
|
||||
extern const OSSL_DISPATCH aria256gcm_functions[];
|
||||
extern const OSSL_DISPATCH aria192gcm_functions[];
|
||||
extern const OSSL_DISPATCH aria128gcm_functions[];
|
||||
extern const OSSL_DISPATCH aria256ccm_functions[];
|
||||
extern const OSSL_DISPATCH aria192ccm_functions[];
|
||||
extern const OSSL_DISPATCH aria128ccm_functions[];
|
||||
extern const OSSL_DISPATCH aria256ecb_functions[];
|
||||
extern const OSSL_DISPATCH aria192ecb_functions[];
|
||||
extern const OSSL_DISPATCH aria128ecb_functions[];
|
||||
extern const OSSL_DISPATCH aria256cbc_functions[];
|
||||
extern const OSSL_DISPATCH aria192cbc_functions[];
|
||||
extern const OSSL_DISPATCH aria128cbc_functions[];
|
||||
extern const OSSL_DISPATCH aria256ofb_functions[];
|
||||
extern const OSSL_DISPATCH aria192ofb_functions[];
|
||||
extern const OSSL_DISPATCH aria128ofb_functions[];
|
||||
extern const OSSL_DISPATCH aria256cfb_functions[];
|
||||
extern const OSSL_DISPATCH aria192cfb_functions[];
|
||||
extern const OSSL_DISPATCH aria128cfb_functions[];
|
||||
extern const OSSL_DISPATCH aria256cfb1_functions[];
|
||||
extern const OSSL_DISPATCH aria192cfb1_functions[];
|
||||
extern const OSSL_DISPATCH aria128cfb1_functions[];
|
||||
extern const OSSL_DISPATCH aria256cfb8_functions[];
|
||||
extern const OSSL_DISPATCH aria192cfb8_functions[];
|
||||
extern const OSSL_DISPATCH aria128cfb8_functions[];
|
||||
extern const OSSL_DISPATCH aria256ctr_functions[];
|
||||
extern const OSSL_DISPATCH aria192ctr_functions[];
|
||||
extern const OSSL_DISPATCH aria128ctr_functions[];
|
||||
#endif /* OPENSSL_NO_ARIA */
|
||||
#ifndef OPENSSL_NO_CAMELLIA
|
||||
extern const OSSL_DISPATCH camellia256ecb_functions[];
|
||||
extern const OSSL_DISPATCH camellia192ecb_functions[];
|
||||
extern const OSSL_DISPATCH camellia128ecb_functions[];
|
||||
extern const OSSL_DISPATCH camellia256cbc_functions[];
|
||||
extern const OSSL_DISPATCH camellia192cbc_functions[];
|
||||
extern const OSSL_DISPATCH camellia128cbc_functions[];
|
||||
extern const OSSL_DISPATCH camellia256ofb_functions[];
|
||||
extern const OSSL_DISPATCH camellia192ofb_functions[];
|
||||
extern const OSSL_DISPATCH camellia128ofb_functions[];
|
||||
extern const OSSL_DISPATCH camellia256cfb_functions[];
|
||||
extern const OSSL_DISPATCH camellia192cfb_functions[];
|
||||
extern const OSSL_DISPATCH camellia128cfb_functions[];
|
||||
extern const OSSL_DISPATCH camellia256cfb1_functions[];
|
||||
extern const OSSL_DISPATCH camellia192cfb1_functions[];
|
||||
extern const OSSL_DISPATCH camellia128cfb1_functions[];
|
||||
extern const OSSL_DISPATCH camellia256cfb8_functions[];
|
||||
extern const OSSL_DISPATCH camellia192cfb8_functions[];
|
||||
extern const OSSL_DISPATCH camellia128cfb8_functions[];
|
||||
extern const OSSL_DISPATCH camellia256ctr_functions[];
|
||||
extern const OSSL_DISPATCH camellia192ctr_functions[];
|
||||
extern const OSSL_DISPATCH camellia128ctr_functions[];
|
||||
#endif /* OPENSSL_NO_CAMELLIA */
|
||||
#ifndef OPENSSL_NO_BF
|
||||
extern const OSSL_DISPATCH blowfish128ecb_functions[];
|
||||
extern const OSSL_DISPATCH blowfish128cbc_functions[];
|
||||
extern const OSSL_DISPATCH blowfish64ofb64_functions[];
|
||||
extern const OSSL_DISPATCH blowfish64cfb64_functions[];
|
||||
#endif /* OPENSSL_NO_BF */
|
||||
#ifndef OPENSSL_NO_IDEA
|
||||
extern const OSSL_DISPATCH idea128ecb_functions[];
|
||||
extern const OSSL_DISPATCH idea128cbc_functions[];
|
||||
extern const OSSL_DISPATCH idea128ofb64_functions[];
|
||||
extern const OSSL_DISPATCH idea128cfb64_functions[];
|
||||
#endif /* OPENSSL_NO_IDEA */
|
||||
#ifndef OPENSSL_NO_CAST
|
||||
extern const OSSL_DISPATCH cast5128ecb_functions[];
|
||||
extern const OSSL_DISPATCH cast5128cbc_functions[];
|
||||
extern const OSSL_DISPATCH cast564ofb64_functions[];
|
||||
extern const OSSL_DISPATCH cast564cfb64_functions[];
|
||||
#endif /* OPENSSL_NO_CAST */
|
||||
#ifndef OPENSSL_NO_SEED
|
||||
extern const OSSL_DISPATCH seed128ecb_functions[];
|
||||
extern const OSSL_DISPATCH seed128cbc_functions[];
|
||||
extern const OSSL_DISPATCH seed128ofb128_functions[];
|
||||
extern const OSSL_DISPATCH seed128cfb128_functions[];
|
||||
#endif /* OPENSSL_NO_SEED */
|
||||
#ifndef OPENSSL_NO_SM4
|
||||
extern const OSSL_DISPATCH sm4128ecb_functions[];
|
||||
extern const OSSL_DISPATCH sm4128cbc_functions[];
|
||||
extern const OSSL_DISPATCH sm4128ctr_functions[];
|
||||
extern const OSSL_DISPATCH sm4128ofb128_functions[];
|
||||
extern const OSSL_DISPATCH sm4128cfb128_functions[];
|
||||
#endif /* OPENSSL_NO_SM4 */
|
||||
|
||||
extern const OSSL_DISPATCH tdes_ede3_ecb_functions[];
|
||||
extern const OSSL_DISPATCH tdes_ede3_cbc_functions[];
|
||||
|
||||
#ifndef FIPS_MODE
|
||||
extern const OSSL_DISPATCH tdes_ede3_ofb_functions[];
|
||||
extern const OSSL_DISPATCH tdes_ede3_cfb_functions[];
|
||||
extern const OSSL_DISPATCH tdes_ede3_cfb8_functions[];
|
||||
extern const OSSL_DISPATCH tdes_ede3_cfb1_functions[];
|
||||
|
||||
extern const OSSL_DISPATCH tdes_ede2_ecb_functions[];
|
||||
extern const OSSL_DISPATCH tdes_ede2_cbc_functions[];
|
||||
extern const OSSL_DISPATCH tdes_ede2_ofb_functions[];
|
||||
extern const OSSL_DISPATCH tdes_ede2_cfb_functions[];
|
||||
|
||||
extern const OSSL_DISPATCH tdes_desx_cbc_functions[];
|
||||
extern const OSSL_DISPATCH tdes_wrap_cbc_functions[];
|
||||
#endif /* FIPS_MODE */
|
||||
|
||||
/* MACs */
|
||||
extern const OSSL_DISPATCH blake2bmac_functions[];
|
||||
extern const OSSL_DISPATCH blake2smac_functions[];
|
||||
extern const OSSL_DISPATCH cmac_functions[];
|
||||
extern const OSSL_DISPATCH gmac_functions[];
|
||||
extern const OSSL_DISPATCH hmac_functions[];
|
||||
extern const OSSL_DISPATCH kmac128_functions[];
|
||||
extern const OSSL_DISPATCH kmac256_functions[];
|
||||
extern const OSSL_DISPATCH siphash_functions[];
|
||||
extern const OSSL_DISPATCH poly1305_functions[];
|
||||
|
||||
/* KDFs / PRFs */
|
||||
extern const OSSL_DISPATCH kdf_pbkdf2_functions[];
|
||||
#ifndef OPENSSL_NO_SCRYPT
|
||||
extern const OSSL_DISPATCH kdf_scrypt_functions[];
|
||||
#endif
|
||||
extern const OSSL_DISPATCH kdf_tls1_prf_functions[];
|
||||
extern const OSSL_DISPATCH kdf_hkdf_functions[];
|
||||
extern const OSSL_DISPATCH kdf_sshkdf_functions[];
|
||||
extern const OSSL_DISPATCH kdf_sskdf_functions[];
|
||||
extern const OSSL_DISPATCH kdf_x963_kdf_functions[];
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
extern const OSSL_DISPATCH kdf_x942_kdf_functions[];
|
||||
#endif
|
||||
|
||||
|
||||
/* Key management */
|
||||
extern const OSSL_DISPATCH dh_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH dsa_keymgmt_functions[];
|
||||
|
||||
/* Key Exchange */
|
||||
extern const OSSL_DISPATCH dh_keyexch_functions[];
|
||||
|
||||
/* Signature */
|
||||
extern const OSSL_DISPATCH dsa_signature_functions[];
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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/provider.h>
|
||||
#include <openssl/engine.h>
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
* References to the underlying cipher implementation. |cipher| caches
|
||||
* the cipher, always. |alloc_cipher| only holds a reference to an
|
||||
* explicitly fetched cipher.
|
||||
*/
|
||||
const EVP_CIPHER *cipher; /* cipher */
|
||||
EVP_CIPHER *alloc_cipher; /* fetched cipher */
|
||||
|
||||
/* Conditions for legacy EVP_CIPHER uses */
|
||||
ENGINE *engine; /* cipher engine */
|
||||
} PROV_CIPHER;
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
* References to the underlying digest implementation. |md| caches
|
||||
* the digest, always. |alloc_md| only holds a reference to an explicitly
|
||||
* fetched digest.
|
||||
*/
|
||||
const EVP_MD *md; /* digest */
|
||||
EVP_MD *alloc_md; /* fetched digest */
|
||||
|
||||
/* Conditions for legacy EVP_MD uses */
|
||||
ENGINE *engine; /* digest engine */
|
||||
} PROV_DIGEST;
|
||||
|
||||
/* Cipher functions */
|
||||
/*
|
||||
* Load a cipher from the specified parameters with the specified context.
|
||||
* The params "properties", "engine" and "cipher" are used to determine the
|
||||
* implementation used. If a provider cannot be found, it falls back to trying
|
||||
* non-provider based implementations.
|
||||
*/
|
||||
int ossl_prov_cipher_load_from_params(PROV_CIPHER *pc,
|
||||
const OSSL_PARAM params[],
|
||||
OPENSSL_CTX *ctx);
|
||||
|
||||
/* Reset the PROV_CIPHER fields and free any allocated cipher reference */
|
||||
void ossl_prov_cipher_reset(PROV_CIPHER *pc);
|
||||
|
||||
/* Clone a PROV_CIPHER structure into a second */
|
||||
int ossl_prov_cipher_copy(PROV_CIPHER *dst, const PROV_CIPHER *src);
|
||||
|
||||
/* Query the cipher and associated engine (if any) */
|
||||
const EVP_CIPHER *ossl_prov_cipher_cipher(const PROV_CIPHER *pc);
|
||||
ENGINE *ossl_prov_cipher_engine(const PROV_CIPHER *pc);
|
||||
|
||||
/* Digest functions */
|
||||
/*
|
||||
* Load a digest from the specified parameters with the specified context.
|
||||
* The params "properties", "engine" and "digest" are used to determine the
|
||||
* implementation used. If a provider cannot be found, it falls back to trying
|
||||
* non-provider based implementations.
|
||||
*/
|
||||
int ossl_prov_digest_load_from_params(PROV_DIGEST *pd,
|
||||
const OSSL_PARAM params[],
|
||||
OPENSSL_CTX *ctx);
|
||||
|
||||
/* Reset the PROV_DIGEST fields and free any allocated digest reference */
|
||||
void ossl_prov_digest_reset(PROV_DIGEST *pd);
|
||||
|
||||
/* Clone a PROV_DIGEST structure into a second */
|
||||
int ossl_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src);
|
||||
|
||||
/* Query the digest and associated engine (if any) */
|
||||
const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd);
|
||||
ENGINE *ossl_prov_digest_engine(const PROV_DIGEST *pd);
|
||||
|
||||
/* MAC functions */
|
||||
/*
|
||||
* Load an EVP_MAC_CTX* from the specified parameters with the specified
|
||||
* library context.
|
||||
* The params "mac" and "properties" are used to determine the implementation
|
||||
* used, and the parameters "digest", "cipher", "engine" and "properties" are
|
||||
* passed to the MAC via the created MAC context if they are given.
|
||||
* If there is already a created MAC context, it will be replaced if the "mac"
|
||||
* parameter is found, otherwise it will simply be used as is, and passed the
|
||||
* parameters to pilfer as it sees fit.
|
||||
*
|
||||
* As an option, a MAC name may be explicitly given, and if it is, the "mac"
|
||||
* parameter will be ignored.
|
||||
* Similarly, as an option, a cipher name or a digest name may be explicitly
|
||||
* given, and if any of them is, the "digest" and "cipher" parameters are
|
||||
* ignored.
|
||||
*/
|
||||
int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx,
|
||||
const OSSL_PARAM params[],
|
||||
const char *macname,
|
||||
const char *ciphername,
|
||||
const char *mdname,
|
||||
OPENSSL_CTX *ctx);
|
||||
@@ -12,3 +12,4 @@
|
||||
const OSSL_PROVIDER *FIPS_get_provider(OPENSSL_CTX *ctx);
|
||||
|
||||
const char *ossl_prov_util_nid_to_name(int nid);
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
#ifndef HEADER_PROVERR_H
|
||||
# define HEADER_PROVERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
# include <openssl/opensslconf.h>
|
||||
# include <openssl/symhacks.h>
|
||||
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
@@ -23,32 +23,81 @@ int ERR_load_PROV_strings(void);
|
||||
/*
|
||||
* PROV function codes.
|
||||
*/
|
||||
# define PROV_F_AESNI_INIT_KEY 101
|
||||
# define PROV_F_AES_BLOCK_FINAL 102
|
||||
# define PROV_F_AES_BLOCK_UPDATE 103
|
||||
# define PROV_F_AES_CIPHER 104
|
||||
# define PROV_F_AES_CTX_GET_PARAMS 105
|
||||
# define PROV_F_AES_CTX_SET_PARAMS 106
|
||||
# define PROV_F_AES_DINIT 107
|
||||
# define PROV_F_AES_DUPCTX 108
|
||||
# define PROV_F_AES_EINIT 109
|
||||
# define PROV_F_AES_INIT_KEY 110
|
||||
# define PROV_F_AES_STREAM_UPDATE 111
|
||||
# define PROV_F_AES_T4_INIT_KEY 112
|
||||
# define PROV_F_PROV_AES_KEY_GENERIC_INIT 113
|
||||
# define PROV_F_TRAILINGDATA 114
|
||||
# define PROV_F_UNPADBLOCK 100
|
||||
# if !OPENSSL_API_3
|
||||
# define PROV_F_AESNI_INIT_KEY 0
|
||||
# define PROV_F_AES_BLOCK_FINAL 0
|
||||
# define PROV_F_AES_BLOCK_UPDATE 0
|
||||
# define PROV_F_AES_CIPHER 0
|
||||
# define PROV_F_AES_DINIT 0
|
||||
# define PROV_F_AES_DUPCTX 0
|
||||
# define PROV_F_AES_EINIT 0
|
||||
# define PROV_F_AES_GET_CTX_PARAMS 0
|
||||
# define PROV_F_AES_INIT_KEY 0
|
||||
# define PROV_F_AES_SET_CTX_PARAMS 0
|
||||
# define PROV_F_AES_STREAM_UPDATE 0
|
||||
# define PROV_F_AES_T4_INIT_KEY 0
|
||||
# define PROV_F_BLAKE2_MAC_INIT 0
|
||||
# define PROV_F_BLAKE2_MAC_SET_PARAMS 0
|
||||
# define PROV_F_GMAC_SET_PARAMS 0
|
||||
# define PROV_F_KMAC_SET_PARAMS 0
|
||||
# define PROV_F_POLY1305_SET_PARAMS 0
|
||||
# define PROV_F_PROV_AES_KEY_GENERIC_INIT 0
|
||||
# define PROV_F_TRAILINGDATA 0
|
||||
# define PROV_F_UNPADBLOCK 0
|
||||
# endif
|
||||
|
||||
/*
|
||||
* PROV reason codes.
|
||||
*/
|
||||
# define PROV_R_AES_KEY_SETUP_FAILED 101
|
||||
# define PROV_R_BAD_DECRYPT 100
|
||||
# define PROV_R_BAD_ENCODING 141
|
||||
# define PROV_R_BAD_LENGTH 142
|
||||
# define PROV_R_BOTH_MODE_AND_MODE_INT 127
|
||||
# define PROV_R_CIPHER_OPERATION_FAILED 102
|
||||
# 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_INVALID_KEYLEN 105
|
||||
# define PROV_R_INAVLID_UKM_LENGTH 146
|
||||
# define PROV_R_INVALID_AAD 108
|
||||
# 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_KEYLEN 117
|
||||
# define PROV_R_INVALID_KEY_LEN 124
|
||||
# define PROV_R_INVALID_KEY_LENGTH 105
|
||||
# define PROV_R_INVALID_MODE 125
|
||||
# define PROV_R_INVALID_MODE_INT 126
|
||||
# define PROV_R_INVALID_SALT_LENGTH 112
|
||||
# define PROV_R_INVALID_TAG 110
|
||||
# define PROV_R_INVALID_TAGLEN 118
|
||||
# define PROV_R_MISSING_CEK_ALG 144
|
||||
# define PROV_R_MISSING_KEY 128
|
||||
# define PROV_R_MISSING_MESSAGE_DIGEST 129
|
||||
# define PROV_R_MISSING_PASS 130
|
||||
# define PROV_R_MISSING_SALT 131
|
||||
# define PROV_R_MISSING_SECRET 132
|
||||
# define PROV_R_MISSING_SEED 140
|
||||
# define PROV_R_MISSING_SESSION_ID 133
|
||||
# define PROV_R_MISSING_TYPE 134
|
||||
# define PROV_R_MISSING_XCGHASH 135
|
||||
# define PROV_R_NOT_SUPPORTED 136
|
||||
# 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_TAG_NOTSET 119
|
||||
# define PROV_R_TAG_NOT_NEEDED 120
|
||||
# define PROV_R_UNABLE_TO_LOAD_SHA1 143
|
||||
# define PROV_R_UNABLE_TO_LOAD_SHA256 147
|
||||
# define PROV_R_UNSUPPORTED_CEK_ALG 145
|
||||
# define PROV_R_UNSUPPORTED_MAC_TYPE 137
|
||||
# define PROV_R_VALUE_ERROR 138
|
||||
# define PROV_R_WRONG_FINAL_BLOCK_LENGTH 107
|
||||
# define PROV_R_WRONG_OUTPUT_BUFFER_SIZE 139
|
||||
# define PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE 148
|
||||
# define PROV_R_XTS_DUPLICATED_KEYS 149
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
$COMMON=tls1_prf.c hkdf.c pbkdf2.c sskdf.c
|
||||
|
||||
LIBS=../../../libcrypto
|
||||
SOURCE[../../../libcrypto]=$COMMON
|
||||
INCLUDE[../../../libcrypto]=. ../../../crypto
|
||||
|
||||
IF[{- !$disabled{fips} -}]
|
||||
MODULES=../../fips
|
||||
SOURCE[../../fips]=$COMMON
|
||||
INCLUDE[../../fips]=. ../../../crypto
|
||||
ENDIF
|
||||
|
||||
|
||||
@@ -0,0 +1,463 @@
|
||||
/*
|
||||
* Copyright 2016-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 <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/kdf.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/numbers.h"
|
||||
#include "internal/evp_int.h"
|
||||
#include "internal/provider_ctx.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
#include "internal/provider_algs.h"
|
||||
#include "internal/provider_util.h"
|
||||
#include "e_os.h"
|
||||
|
||||
#define HKDF_MAXBUF 1024
|
||||
|
||||
static OSSL_OP_kdf_newctx_fn kdf_hkdf_new;
|
||||
static OSSL_OP_kdf_freectx_fn kdf_hkdf_free;
|
||||
static OSSL_OP_kdf_reset_fn kdf_hkdf_reset;
|
||||
static OSSL_OP_kdf_derive_fn kdf_hkdf_derive;
|
||||
static OSSL_OP_kdf_settable_ctx_params_fn kdf_hkdf_settable_ctx_params;
|
||||
static OSSL_OP_kdf_set_ctx_params_fn kdf_hkdf_set_ctx_params;
|
||||
static OSSL_OP_kdf_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params;
|
||||
static OSSL_OP_kdf_get_ctx_params_fn kdf_hkdf_get_ctx_params;
|
||||
|
||||
static int HKDF(const EVP_MD *evp_md,
|
||||
const unsigned char *salt, size_t salt_len,
|
||||
const unsigned char *key, size_t key_len,
|
||||
const unsigned char *info, size_t info_len,
|
||||
unsigned char *okm, size_t okm_len);
|
||||
static int HKDF_Extract(const EVP_MD *evp_md,
|
||||
const unsigned char *salt, size_t salt_len,
|
||||
const unsigned char *ikm, size_t ikm_len,
|
||||
unsigned char *prk, size_t prk_len);
|
||||
static int HKDF_Expand(const EVP_MD *evp_md,
|
||||
const unsigned char *prk, size_t prk_len,
|
||||
const unsigned char *info, size_t info_len,
|
||||
unsigned char *okm, size_t okm_len);
|
||||
|
||||
typedef struct {
|
||||
void *provctx;
|
||||
int mode;
|
||||
PROV_DIGEST digest;
|
||||
unsigned char *salt;
|
||||
size_t salt_len;
|
||||
unsigned char *key;
|
||||
size_t key_len;
|
||||
unsigned char info[HKDF_MAXBUF];
|
||||
size_t info_len;
|
||||
} KDF_HKDF;
|
||||
|
||||
static void *kdf_hkdf_new(void *provctx)
|
||||
{
|
||||
KDF_HKDF *ctx;
|
||||
|
||||
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
else
|
||||
ctx->provctx = provctx;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void kdf_hkdf_free(void *vctx)
|
||||
{
|
||||
KDF_HKDF *ctx = (KDF_HKDF *)vctx;
|
||||
|
||||
kdf_hkdf_reset(ctx);
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
static void kdf_hkdf_reset(void *vctx)
|
||||
{
|
||||
KDF_HKDF *ctx = (KDF_HKDF *)vctx;
|
||||
|
||||
ossl_prov_digest_reset(&ctx->digest);
|
||||
OPENSSL_free(ctx->salt);
|
||||
OPENSSL_clear_free(ctx->key, ctx->key_len);
|
||||
OPENSSL_cleanse(ctx->info, ctx->info_len);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static size_t kdf_hkdf_size(KDF_HKDF *ctx)
|
||||
{
|
||||
int sz;
|
||||
const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
|
||||
|
||||
if (ctx->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY)
|
||||
return SIZE_MAX;
|
||||
|
||||
if (md == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
sz = EVP_MD_size(md);
|
||||
if (sz < 0)
|
||||
return 0;
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
static int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen)
|
||||
{
|
||||
KDF_HKDF *ctx = (KDF_HKDF *)vctx;
|
||||
const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
|
||||
|
||||
if (md == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
if (ctx->key == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (ctx->mode) {
|
||||
case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
|
||||
return HKDF(md, ctx->salt, ctx->salt_len, ctx->key,
|
||||
ctx->key_len, ctx->info, ctx->info_len, key,
|
||||
keylen);
|
||||
|
||||
case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
|
||||
return HKDF_Extract(md, ctx->salt, ctx->salt_len, ctx->key,
|
||||
ctx->key_len, key, keylen);
|
||||
|
||||
case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
|
||||
return HKDF_Expand(md, ctx->key, ctx->key_len, ctx->info,
|
||||
ctx->info_len, key, keylen);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
KDF_HKDF *ctx = vctx;
|
||||
OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
|
||||
int n;
|
||||
|
||||
if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE)) != NULL) {
|
||||
if (p->data_type == OSSL_PARAM_UTF8_STRING) {
|
||||
if (strcasecmp(p->data, "EXTRACT_AND_EXPAND") == 0) {
|
||||
ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND;
|
||||
} else if (strcasecmp(p->data, "EXTRACT_ONLY") == 0) {
|
||||
ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY;
|
||||
} else if (strcasecmp(p->data, "EXPAND_ONLY") == 0) {
|
||||
ctx->mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY;
|
||||
} else {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
|
||||
return 0;
|
||||
}
|
||||
} else if (OSSL_PARAM_get_int(p, &n)) {
|
||||
if (n != EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND
|
||||
&& n != EVP_KDF_HKDF_MODE_EXTRACT_ONLY
|
||||
&& n != EVP_KDF_HKDF_MODE_EXPAND_ONLY) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
|
||||
return 0;
|
||||
}
|
||||
ctx->mode = n;
|
||||
} else {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) {
|
||||
OPENSSL_clear_free(ctx->key, ctx->key_len);
|
||||
ctx->key = NULL;
|
||||
if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->key, 0,
|
||||
&ctx->key_len))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) {
|
||||
if (p->data_size != 0 && p->data != NULL) {
|
||||
OPENSSL_free(ctx->salt);
|
||||
ctx->salt = NULL;
|
||||
if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->salt, 0,
|
||||
&ctx->salt_len))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* The info fields concatenate, so process them all */
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) {
|
||||
ctx->info_len = 0;
|
||||
for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1,
|
||||
OSSL_KDF_PARAM_INFO)) {
|
||||
const void *q = ctx->info + ctx->info_len;
|
||||
size_t sz = 0;
|
||||
|
||||
if (p->data_size != 0
|
||||
&& p->data != NULL
|
||||
&& !OSSL_PARAM_get_octet_string(p, (void **)&q,
|
||||
HKDF_MAXBUF - ctx->info_len,
|
||||
&sz))
|
||||
return 0;
|
||||
ctx->info_len += sz;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *kdf_hkdf_settable_ctx_params(void)
|
||||
{
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0),
|
||||
OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL),
|
||||
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
static int kdf_hkdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
||||
{
|
||||
KDF_HKDF *ctx = (KDF_HKDF *)vctx;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
|
||||
return OSSL_PARAM_set_size_t(p, kdf_hkdf_size(ctx));
|
||||
return -2;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(void)
|
||||
{
|
||||
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
return known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH kdf_hkdf_functions[] = {
|
||||
{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new },
|
||||
{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free },
|
||||
{ OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset },
|
||||
{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_hkdf_derive },
|
||||
{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
|
||||
(void(*)(void))kdf_hkdf_settable_ctx_params },
|
||||
{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_hkdf_set_ctx_params },
|
||||
{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
|
||||
(void(*)(void))kdf_hkdf_gettable_ctx_params },
|
||||
{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
|
||||
* Section 2 (https://tools.ietf.org/html/rfc5869#section-2) and
|
||||
* "Cryptographic Extraction and Key Derivation: The HKDF Scheme"
|
||||
* Section 4.2 (https://eprint.iacr.org/2010/264.pdf).
|
||||
*
|
||||
* From the paper:
|
||||
* The scheme HKDF is specified as:
|
||||
* HKDF(XTS, SKM, CTXinfo, L) = K(1) | K(2) | ... | K(t)
|
||||
*
|
||||
* where:
|
||||
* SKM is source key material
|
||||
* XTS is extractor salt (which may be null or constant)
|
||||
* CTXinfo is context information (may be null)
|
||||
* L is the number of key bits to be produced by KDF
|
||||
* k is the output length in bits of the hash function used with HMAC
|
||||
* t = ceil(L/k)
|
||||
* the value K(t) is truncated to its first d = L mod k bits.
|
||||
*
|
||||
* From RFC 5869:
|
||||
* 2.2. Step 1: Extract
|
||||
* HKDF-Extract(salt, IKM) -> PRK
|
||||
* 2.3. Step 2: Expand
|
||||
* HKDF-Expand(PRK, info, L) -> OKM
|
||||
*/
|
||||
static int HKDF(const EVP_MD *evp_md,
|
||||
const unsigned char *salt, size_t salt_len,
|
||||
const unsigned char *ikm, size_t ikm_len,
|
||||
const unsigned char *info, size_t info_len,
|
||||
unsigned char *okm, size_t okm_len)
|
||||
{
|
||||
unsigned char prk[EVP_MAX_MD_SIZE];
|
||||
int ret, sz;
|
||||
size_t prk_len;
|
||||
|
||||
sz = EVP_MD_size(evp_md);
|
||||
if (sz < 0)
|
||||
return 0;
|
||||
prk_len = (size_t)sz;
|
||||
|
||||
/* Step 1: HKDF-Extract(salt, IKM) -> PRK */
|
||||
if (!HKDF_Extract(evp_md, salt, salt_len, ikm, ikm_len, prk, prk_len))
|
||||
return 0;
|
||||
|
||||
/* Step 2: HKDF-Expand(PRK, info, L) -> OKM */
|
||||
ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
|
||||
OPENSSL_cleanse(prk, sizeof(prk));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
|
||||
* Section 2.2 (https://tools.ietf.org/html/rfc5869#section-2.2).
|
||||
*
|
||||
* 2.2. Step 1: Extract
|
||||
*
|
||||
* HKDF-Extract(salt, IKM) -> PRK
|
||||
*
|
||||
* Options:
|
||||
* Hash a hash function; HashLen denotes the length of the
|
||||
* hash function output in octets
|
||||
*
|
||||
* Inputs:
|
||||
* salt optional salt value (a non-secret random value);
|
||||
* if not provided, it is set to a string of HashLen zeros.
|
||||
* IKM input keying material
|
||||
*
|
||||
* Output:
|
||||
* PRK a pseudorandom key (of HashLen octets)
|
||||
*
|
||||
* The output PRK is calculated as follows:
|
||||
*
|
||||
* PRK = HMAC-Hash(salt, IKM)
|
||||
*/
|
||||
static int HKDF_Extract(const EVP_MD *evp_md,
|
||||
const unsigned char *salt, size_t salt_len,
|
||||
const unsigned char *ikm, size_t ikm_len,
|
||||
unsigned char *prk, size_t prk_len)
|
||||
{
|
||||
int sz = EVP_MD_size(evp_md);
|
||||
|
||||
if (sz < 0)
|
||||
return 0;
|
||||
if (prk_len != (size_t)sz) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE);
|
||||
return 0;
|
||||
}
|
||||
/* calc: PRK = HMAC-Hash(salt, IKM) */
|
||||
return HMAC(evp_md, salt, salt_len, ikm, ikm_len, prk, NULL) != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
|
||||
* Section 2.3 (https://tools.ietf.org/html/rfc5869#section-2.3).
|
||||
*
|
||||
* 2.3. Step 2: Expand
|
||||
*
|
||||
* HKDF-Expand(PRK, info, L) -> OKM
|
||||
*
|
||||
* Options:
|
||||
* Hash a hash function; HashLen denotes the length of the
|
||||
* hash function output in octets
|
||||
*
|
||||
* Inputs:
|
||||
* PRK a pseudorandom key of at least HashLen octets
|
||||
* (usually, the output from the extract step)
|
||||
* info optional context and application specific information
|
||||
* (can be a zero-length string)
|
||||
* L length of output keying material in octets
|
||||
* (<= 255*HashLen)
|
||||
*
|
||||
* Output:
|
||||
* OKM output keying material (of L octets)
|
||||
*
|
||||
* The output OKM is calculated as follows:
|
||||
*
|
||||
* N = ceil(L/HashLen)
|
||||
* T = T(1) | T(2) | T(3) | ... | T(N)
|
||||
* OKM = first L octets of T
|
||||
*
|
||||
* where:
|
||||
* T(0) = empty string (zero length)
|
||||
* T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
|
||||
* T(2) = HMAC-Hash(PRK, T(1) | info | 0x02)
|
||||
* T(3) = HMAC-Hash(PRK, T(2) | info | 0x03)
|
||||
* ...
|
||||
*
|
||||
* (where the constant concatenated to the end of each T(n) is a
|
||||
* single octet.)
|
||||
*/
|
||||
static int HKDF_Expand(const EVP_MD *evp_md,
|
||||
const unsigned char *prk, size_t prk_len,
|
||||
const unsigned char *info, size_t info_len,
|
||||
unsigned char *okm, size_t okm_len)
|
||||
{
|
||||
HMAC_CTX *hmac;
|
||||
int ret = 0, sz;
|
||||
unsigned int i;
|
||||
unsigned char prev[EVP_MAX_MD_SIZE];
|
||||
size_t done_len = 0, dig_len, n;
|
||||
|
||||
sz = EVP_MD_size(evp_md);
|
||||
if (sz <= 0)
|
||||
return 0;
|
||||
dig_len = (size_t)sz;
|
||||
|
||||
/* calc: N = ceil(L/HashLen) */
|
||||
n = okm_len / dig_len;
|
||||
if (okm_len % dig_len)
|
||||
n++;
|
||||
|
||||
if (n > 255 || okm == NULL)
|
||||
return 0;
|
||||
|
||||
if ((hmac = HMAC_CTX_new()) == NULL)
|
||||
return 0;
|
||||
|
||||
if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
|
||||
goto err;
|
||||
|
||||
for (i = 1; i <= n; i++) {
|
||||
size_t copy_len;
|
||||
const unsigned char ctr = i;
|
||||
|
||||
/* calc: T(i) = HMAC-Hash(PRK, T(i - 1) | info | i) */
|
||||
if (i > 1) {
|
||||
if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
|
||||
goto err;
|
||||
|
||||
if (!HMAC_Update(hmac, prev, dig_len))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!HMAC_Update(hmac, info, info_len))
|
||||
goto err;
|
||||
|
||||
if (!HMAC_Update(hmac, &ctr, 1))
|
||||
goto err;
|
||||
|
||||
if (!HMAC_Final(hmac, prev, NULL))
|
||||
goto err;
|
||||
|
||||
copy_len = (done_len + dig_len > okm_len) ?
|
||||
okm_len - done_len :
|
||||
dig_len;
|
||||
|
||||
memcpy(okm + done_len, prev, copy_len);
|
||||
|
||||
done_len += copy_len;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_cleanse(prev, sizeof(prev));
|
||||
HMAC_CTX_free(hmac);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* Copyright 2018-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 <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/kdf.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/numbers.h"
|
||||
#include "internal/evp_int.h"
|
||||
#include "internal/provider_ctx.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
#include "internal/provider_algs.h"
|
||||
#include "internal/provider_util.h"
|
||||
|
||||
/* Constants specified in SP800-132 */
|
||||
#define KDF_PBKDF2_MIN_KEY_LEN_BITS 112
|
||||
#define KDF_PBKDF2_MAX_KEY_LEN_DIGEST_RATIO 0xFFFFFFFF
|
||||
#define KDF_PBKDF2_MIN_ITERATIONS 1000
|
||||
#define KDF_PBKDF2_MIN_SALT_LEN (128 / 8)
|
||||
/*
|
||||
* For backwards compatibility reasons,
|
||||
* Extra checks are done by default in fips mode only.
|
||||
*/
|
||||
#ifdef FIPS_MODE
|
||||
# define KDF_PBKDF2_DEFAULT_CHECKS 1
|
||||
#else
|
||||
# define KDF_PBKDF2_DEFAULT_CHECKS 0
|
||||
#endif /* FIPS_MODE */
|
||||
|
||||
static OSSL_OP_kdf_newctx_fn kdf_pbkdf2_new;
|
||||
static OSSL_OP_kdf_freectx_fn kdf_pbkdf2_free;
|
||||
static OSSL_OP_kdf_reset_fn kdf_pbkdf2_reset;
|
||||
static OSSL_OP_kdf_derive_fn kdf_pbkdf2_derive;
|
||||
static OSSL_OP_kdf_settable_ctx_params_fn kdf_pbkdf2_settable_ctx_params;
|
||||
static OSSL_OP_kdf_set_ctx_params_fn kdf_pbkdf2_set_ctx_params;
|
||||
|
||||
static int pbkdf2_derive(const char *pass, size_t passlen,
|
||||
const unsigned char *salt, int saltlen, uint64_t iter,
|
||||
const EVP_MD *digest, unsigned char *key,
|
||||
size_t keylen, int extra_checks);
|
||||
|
||||
typedef struct {
|
||||
void *provctx;
|
||||
unsigned char *pass;
|
||||
size_t pass_len;
|
||||
unsigned char *salt;
|
||||
size_t salt_len;
|
||||
uint64_t iter;
|
||||
PROV_DIGEST digest;
|
||||
int lower_bound_checks;
|
||||
} KDF_PBKDF2;
|
||||
|
||||
static void kdf_pbkdf2_init(KDF_PBKDF2 *ctx);
|
||||
|
||||
static void *kdf_pbkdf2_new(void *provctx)
|
||||
{
|
||||
KDF_PBKDF2 *ctx;
|
||||
|
||||
ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
if (ctx == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
ctx->provctx = provctx;
|
||||
kdf_pbkdf2_init(ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void kdf_pbkdf2_cleanup(KDF_PBKDF2 *ctx)
|
||||
{
|
||||
ossl_prov_digest_reset(&ctx->digest);
|
||||
OPENSSL_free(ctx->salt);
|
||||
OPENSSL_clear_free(ctx->pass, ctx->pass_len);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void kdf_pbkdf2_free(void *vctx)
|
||||
{
|
||||
KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx;
|
||||
|
||||
kdf_pbkdf2_cleanup(ctx);
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
static void kdf_pbkdf2_reset(void *vctx)
|
||||
{
|
||||
KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx;
|
||||
|
||||
kdf_pbkdf2_cleanup(ctx);
|
||||
kdf_pbkdf2_init(ctx);
|
||||
}
|
||||
|
||||
static void kdf_pbkdf2_init(KDF_PBKDF2 *ctx)
|
||||
{
|
||||
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
||||
OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
|
||||
|
||||
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
|
||||
SN_sha1, 0);
|
||||
if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
|
||||
/* This is an error, but there is no way to indicate such directly */
|
||||
ossl_prov_digest_reset(&ctx->digest);
|
||||
ctx->iter = PKCS5_DEFAULT_ITER;
|
||||
ctx->lower_bound_checks = KDF_PBKDF2_DEFAULT_CHECKS;
|
||||
}
|
||||
|
||||
static int pbkdf2_set_membuf(unsigned char **buffer, size_t *buflen,
|
||||
const OSSL_PARAM *p)
|
||||
{
|
||||
OPENSSL_clear_free(*buffer, *buflen);
|
||||
if (p->data_size == 0) {
|
||||
if ((*buffer = OPENSSL_malloc(1)) == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else if (p->data != NULL) {
|
||||
*buffer = NULL;
|
||||
if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int kdf_pbkdf2_derive(void *vctx, unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx;
|
||||
const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
|
||||
|
||||
if (ctx->pass == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->salt == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pbkdf2_derive((char *)ctx->pass, ctx->pass_len,
|
||||
ctx->salt, ctx->salt_len, ctx->iter,
|
||||
md, key, keylen, ctx->lower_bound_checks);
|
||||
}
|
||||
|
||||
static int kdf_pbkdf2_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
KDF_PBKDF2 *ctx = vctx;
|
||||
OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
|
||||
int pkcs5;
|
||||
uint64_t iter, min_iter;
|
||||
|
||||
if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PKCS5)) != NULL) {
|
||||
if (!OSSL_PARAM_get_int(p, &pkcs5))
|
||||
return 0;
|
||||
ctx->lower_bound_checks = pkcs5 == 0;
|
||||
}
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
|
||||
if (!pbkdf2_set_membuf(&ctx->pass, &ctx->pass_len, p))
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) {
|
||||
if (ctx->lower_bound_checks != 0
|
||||
&& p->data_size < KDF_PBKDF2_MIN_SALT_LEN) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if (!pbkdf2_set_membuf(&ctx->salt, &ctx->salt_len,p))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL) {
|
||||
if (!OSSL_PARAM_get_uint64(p, &iter))
|
||||
return 0;
|
||||
min_iter = ctx->lower_bound_checks != 0 ? KDF_PBKDF2_MIN_ITERATIONS : 1;
|
||||
if (iter < min_iter) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT);
|
||||
return 0;
|
||||
}
|
||||
ctx->iter = iter;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *kdf_pbkdf2_settable_ctx_params(void)
|
||||
{
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
|
||||
OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL),
|
||||
OSSL_PARAM_int(OSSL_KDF_PARAM_PKCS5, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
static int kdf_pbkdf2_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
||||
{
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
|
||||
return OSSL_PARAM_set_size_t(p, SIZE_MAX);
|
||||
return -2;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *kdf_pbkdf2_gettable_ctx_params(void)
|
||||
{
|
||||
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
return known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH kdf_pbkdf2_functions[] = {
|
||||
{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf2_new },
|
||||
{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf2_free },
|
||||
{ OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pbkdf2_reset },
|
||||
{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pbkdf2_derive },
|
||||
{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
|
||||
(void(*)(void))kdf_pbkdf2_settable_ctx_params },
|
||||
{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pbkdf2_set_ctx_params },
|
||||
{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
|
||||
(void(*)(void))kdf_pbkdf2_gettable_ctx_params },
|
||||
{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pbkdf2_get_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* This is an implementation of PKCS#5 v2.0 password based encryption key
|
||||
* derivation function PBKDF2. SHA1 version verified against test vectors
|
||||
* posted by Peter Gutmann to the PKCS-TNG mailing list.
|
||||
*
|
||||
* The constraints specified by SP800-132 have been added i.e.
|
||||
* - Check the range of the key length.
|
||||
* - Minimum iteration count of 1000.
|
||||
* - Randomly-generated portion of the salt shall be at least 128 bits.
|
||||
*/
|
||||
static int pbkdf2_derive(const char *pass, size_t passlen,
|
||||
const unsigned char *salt, int saltlen, uint64_t iter,
|
||||
const EVP_MD *digest, unsigned char *key,
|
||||
size_t keylen, int lower_bound_checks)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
|
||||
int cplen, k, tkeylen, mdlen;
|
||||
uint64_t j;
|
||||
unsigned long i = 1;
|
||||
HMAC_CTX *hctx_tpl = NULL, *hctx = NULL;
|
||||
|
||||
mdlen = EVP_MD_size(digest);
|
||||
if (mdlen <= 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* This check should always be done because keylen / mdlen >= (2^32 - 1)
|
||||
* results in an overflow of the loop counter 'i'.
|
||||
*/
|
||||
if ((keylen / mdlen) >= KDF_PBKDF2_MAX_KEY_LEN_DIGEST_RATIO) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lower_bound_checks) {
|
||||
if ((keylen * 8) < KDF_PBKDF2_MIN_KEY_LEN_BITS) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LEN);
|
||||
return 0;
|
||||
}
|
||||
if (saltlen < KDF_PBKDF2_MIN_SALT_LEN) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if (iter < KDF_PBKDF2_MIN_ITERATIONS) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
hctx_tpl = HMAC_CTX_new();
|
||||
if (hctx_tpl == NULL)
|
||||
return 0;
|
||||
p = key;
|
||||
tkeylen = keylen;
|
||||
if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL))
|
||||
goto err;
|
||||
hctx = HMAC_CTX_new();
|
||||
if (hctx == NULL)
|
||||
goto err;
|
||||
while (tkeylen) {
|
||||
if (tkeylen > mdlen)
|
||||
cplen = mdlen;
|
||||
else
|
||||
cplen = tkeylen;
|
||||
/*
|
||||
* We are unlikely to ever use more than 256 blocks (5120 bits!) but
|
||||
* just in case...
|
||||
*/
|
||||
itmp[0] = (unsigned char)((i >> 24) & 0xff);
|
||||
itmp[1] = (unsigned char)((i >> 16) & 0xff);
|
||||
itmp[2] = (unsigned char)((i >> 8) & 0xff);
|
||||
itmp[3] = (unsigned char)(i & 0xff);
|
||||
if (!HMAC_CTX_copy(hctx, hctx_tpl))
|
||||
goto err;
|
||||
if (!HMAC_Update(hctx, salt, saltlen)
|
||||
|| !HMAC_Update(hctx, itmp, 4)
|
||||
|| !HMAC_Final(hctx, digtmp, NULL))
|
||||
goto err;
|
||||
memcpy(p, digtmp, cplen);
|
||||
for (j = 1; j < iter; j++) {
|
||||
if (!HMAC_CTX_copy(hctx, hctx_tpl))
|
||||
goto err;
|
||||
if (!HMAC_Update(hctx, digtmp, mdlen)
|
||||
|| !HMAC_Final(hctx, digtmp, NULL))
|
||||
goto err;
|
||||
for (k = 0; k < cplen; k++)
|
||||
p[k] ^= digtmp[k];
|
||||
}
|
||||
tkeylen -= cplen;
|
||||
i++;
|
||||
p += cplen;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
HMAC_CTX_free(hctx);
|
||||
HMAC_CTX_free(hctx_tpl);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,538 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
|
||||
* Section 4.1.
|
||||
*
|
||||
* The Single Step KDF algorithm is given by:
|
||||
*
|
||||
* Result(0) = empty bit string (i.e., the null string).
|
||||
* For i = 1 to reps, do the following:
|
||||
* Increment counter by 1.
|
||||
* Result(i) = Result(i - 1) || H(counter || Z || FixedInfo).
|
||||
* DKM = LeftmostBits(Result(reps), L))
|
||||
*
|
||||
* NOTES:
|
||||
* Z is a shared secret required to produce the derived key material.
|
||||
* counter is a 4 byte buffer.
|
||||
* FixedInfo is a bit string containing context specific data.
|
||||
* DKM is the output derived key material.
|
||||
* L is the required size of the DKM.
|
||||
* reps = [L / H_outputBits]
|
||||
* H(x) is the auxiliary function that can be either a hash, HMAC or KMAC.
|
||||
* H_outputBits is the length of the output of the auxiliary function H(x).
|
||||
*
|
||||
* Currently there is not a comprehensive list of test vectors for this
|
||||
* algorithm, especially for H(x) = HMAC and H(x) = KMAC.
|
||||
* Test vectors for H(x) = Hash are indirectly used by CAVS KAS tests.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/kdf.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/params.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/numbers.h"
|
||||
#include "internal/evp_int.h"
|
||||
#include "internal/provider_ctx.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
#include "internal/provider_algs.h"
|
||||
#include "internal/provider_util.h"
|
||||
|
||||
typedef struct {
|
||||
void *provctx;
|
||||
EVP_MAC_CTX *macctx; /* H(x) = HMAC_hash OR H(x) = KMAC */
|
||||
PROV_DIGEST digest; /* H(x) = hash(x) */
|
||||
unsigned char *secret;
|
||||
size_t secret_len;
|
||||
unsigned char *info;
|
||||
size_t info_len;
|
||||
unsigned char *salt;
|
||||
size_t salt_len;
|
||||
size_t out_len; /* optional KMAC parameter */
|
||||
} KDF_SSKDF;
|
||||
|
||||
#define SSKDF_MAX_INLEN (1<<30)
|
||||
#define SSKDF_KMAC128_DEFAULT_SALT_SIZE (168 - 4)
|
||||
#define SSKDF_KMAC256_DEFAULT_SALT_SIZE (136 - 4)
|
||||
|
||||
/* KMAC uses a Customisation string of 'KDF' */
|
||||
static const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 };
|
||||
|
||||
static OSSL_OP_kdf_newctx_fn sskdf_new;
|
||||
static OSSL_OP_kdf_freectx_fn sskdf_free;
|
||||
static OSSL_OP_kdf_reset_fn sskdf_reset;
|
||||
static OSSL_OP_kdf_derive_fn sskdf_derive;
|
||||
static OSSL_OP_kdf_derive_fn x963kdf_derive;
|
||||
static OSSL_OP_kdf_settable_ctx_params_fn sskdf_settable_ctx_params;
|
||||
static OSSL_OP_kdf_set_ctx_params_fn sskdf_set_ctx_params;
|
||||
static OSSL_OP_kdf_gettable_ctx_params_fn sskdf_gettable_ctx_params;
|
||||
static OSSL_OP_kdf_get_ctx_params_fn sskdf_get_ctx_params;
|
||||
|
||||
/*
|
||||
* Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
|
||||
* Section 4. One-Step Key Derivation using H(x) = hash(x)
|
||||
* Note: X9.63 also uses this code with the only difference being that the
|
||||
* counter is appended to the secret 'z'.
|
||||
* i.e.
|
||||
* result[i] = Hash(counter || z || info) for One Step OR
|
||||
* result[i] = Hash(z || counter || info) for X9.63.
|
||||
*/
|
||||
static int SSKDF_hash_kdm(const EVP_MD *kdf_md,
|
||||
const unsigned char *z, size_t z_len,
|
||||
const unsigned char *info, size_t info_len,
|
||||
unsigned int append_ctr,
|
||||
unsigned char *derived_key, size_t derived_key_len)
|
||||
{
|
||||
int ret = 0, hlen;
|
||||
size_t counter, out_len, len = derived_key_len;
|
||||
unsigned char c[4];
|
||||
unsigned char mac[EVP_MAX_MD_SIZE];
|
||||
unsigned char *out = derived_key;
|
||||
EVP_MD_CTX *ctx = NULL, *ctx_init = NULL;
|
||||
|
||||
if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN
|
||||
|| derived_key_len > SSKDF_MAX_INLEN
|
||||
|| derived_key_len == 0)
|
||||
return 0;
|
||||
|
||||
hlen = EVP_MD_size(kdf_md);
|
||||
if (hlen <= 0)
|
||||
return 0;
|
||||
out_len = (size_t)hlen;
|
||||
|
||||
ctx = EVP_MD_CTX_create();
|
||||
ctx_init = EVP_MD_CTX_create();
|
||||
if (ctx == NULL || ctx_init == NULL)
|
||||
goto end;
|
||||
|
||||
if (!EVP_DigestInit(ctx_init, kdf_md))
|
||||
goto end;
|
||||
|
||||
for (counter = 1;; counter++) {
|
||||
c[0] = (unsigned char)((counter >> 24) & 0xff);
|
||||
c[1] = (unsigned char)((counter >> 16) & 0xff);
|
||||
c[2] = (unsigned char)((counter >> 8) & 0xff);
|
||||
c[3] = (unsigned char)(counter & 0xff);
|
||||
|
||||
if (!(EVP_MD_CTX_copy_ex(ctx, ctx_init)
|
||||
&& (append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c)))
|
||||
&& EVP_DigestUpdate(ctx, z, z_len)
|
||||
&& (!append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c)))
|
||||
&& EVP_DigestUpdate(ctx, info, info_len)))
|
||||
goto end;
|
||||
if (len >= out_len) {
|
||||
if (!EVP_DigestFinal_ex(ctx, out, NULL))
|
||||
goto end;
|
||||
out += out_len;
|
||||
len -= out_len;
|
||||
if (len == 0)
|
||||
break;
|
||||
} else {
|
||||
if (!EVP_DigestFinal_ex(ctx, mac, NULL))
|
||||
goto end;
|
||||
memcpy(out, mac, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
EVP_MD_CTX_destroy(ctx_init);
|
||||
OPENSSL_cleanse(mac, sizeof(mac));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom,
|
||||
size_t custom_len, size_t kmac_out_len,
|
||||
size_t derived_key_len, unsigned char **out)
|
||||
{
|
||||
OSSL_PARAM params[2];
|
||||
|
||||
/* Only KMAC has custom data - so return if not KMAC */
|
||||
if (custom == NULL)
|
||||
return 1;
|
||||
|
||||
params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_CUSTOM,
|
||||
(void *)custom, custom_len);
|
||||
params[1] = OSSL_PARAM_construct_end();
|
||||
|
||||
if (!EVP_MAC_CTX_set_params(ctx, params))
|
||||
return 0;
|
||||
|
||||
/* By default only do one iteration if kmac_out_len is not specified */
|
||||
if (kmac_out_len == 0)
|
||||
kmac_out_len = derived_key_len;
|
||||
/* otherwise check the size is valid */
|
||||
else if (!(kmac_out_len == derived_key_len
|
||||
|| kmac_out_len == 20
|
||||
|| kmac_out_len == 28
|
||||
|| kmac_out_len == 32
|
||||
|| kmac_out_len == 48
|
||||
|| kmac_out_len == 64))
|
||||
return 0;
|
||||
|
||||
params[0] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE,
|
||||
&kmac_out_len);
|
||||
|
||||
if (EVP_MAC_CTX_set_params(ctx, params) <= 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* For kmac the output buffer can be larger than EVP_MAX_MD_SIZE: so
|
||||
* alloc a buffer for this case.
|
||||
*/
|
||||
if (kmac_out_len > EVP_MAX_MD_SIZE) {
|
||||
*out = OPENSSL_zalloc(kmac_out_len);
|
||||
if (*out == NULL)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
|
||||
* Section 4. One-Step Key Derivation using MAC: i.e either
|
||||
* H(x) = HMAC-hash(salt, x) OR
|
||||
* H(x) = KMAC#(salt, x, outbits, CustomString='KDF')
|
||||
*/
|
||||
static int SSKDF_mac_kdm(EVP_MAC_CTX *ctx_init,
|
||||
const unsigned char *kmac_custom,
|
||||
size_t kmac_custom_len, size_t kmac_out_len,
|
||||
const unsigned char *salt, size_t salt_len,
|
||||
const unsigned char *z, size_t z_len,
|
||||
const unsigned char *info, size_t info_len,
|
||||
unsigned char *derived_key, size_t derived_key_len)
|
||||
{
|
||||
int ret = 0;
|
||||
size_t counter, out_len, len;
|
||||
unsigned char c[4];
|
||||
unsigned char mac_buf[EVP_MAX_MD_SIZE];
|
||||
unsigned char *out = derived_key;
|
||||
EVP_MAC_CTX *ctx = NULL;
|
||||
unsigned char *mac = mac_buf, *kmac_buffer = NULL;
|
||||
OSSL_PARAM params[2], *p = params;
|
||||
|
||||
if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN
|
||||
|| derived_key_len > SSKDF_MAX_INLEN
|
||||
|| derived_key_len == 0)
|
||||
return 0;
|
||||
|
||||
*p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
|
||||
(void *)salt, salt_len);
|
||||
*p = OSSL_PARAM_construct_end();
|
||||
|
||||
if (!EVP_MAC_CTX_set_params(ctx_init, params))
|
||||
goto end;
|
||||
|
||||
if (!kmac_init(ctx_init, kmac_custom, kmac_custom_len, kmac_out_len,
|
||||
derived_key_len, &kmac_buffer))
|
||||
goto end;
|
||||
if (kmac_buffer != NULL)
|
||||
mac = kmac_buffer;
|
||||
|
||||
if (!EVP_MAC_init(ctx_init))
|
||||
goto end;
|
||||
|
||||
out_len = EVP_MAC_size(ctx_init); /* output size */
|
||||
if (out_len <= 0)
|
||||
goto end;
|
||||
len = derived_key_len;
|
||||
|
||||
for (counter = 1;; counter++) {
|
||||
c[0] = (unsigned char)((counter >> 24) & 0xff);
|
||||
c[1] = (unsigned char)((counter >> 16) & 0xff);
|
||||
c[2] = (unsigned char)((counter >> 8) & 0xff);
|
||||
c[3] = (unsigned char)(counter & 0xff);
|
||||
|
||||
ctx = EVP_MAC_CTX_dup(ctx_init);
|
||||
if (!(ctx != NULL
|
||||
&& EVP_MAC_update(ctx, c, sizeof(c))
|
||||
&& EVP_MAC_update(ctx, z, z_len)
|
||||
&& EVP_MAC_update(ctx, info, info_len)))
|
||||
goto end;
|
||||
if (len >= out_len) {
|
||||
if (!EVP_MAC_final(ctx, out, NULL, len))
|
||||
goto end;
|
||||
out += out_len;
|
||||
len -= out_len;
|
||||
if (len == 0)
|
||||
break;
|
||||
} else {
|
||||
if (!EVP_MAC_final(ctx, mac, NULL, len))
|
||||
goto end;
|
||||
memcpy(out, mac, len);
|
||||
break;
|
||||
}
|
||||
EVP_MAC_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
if (kmac_buffer != NULL)
|
||||
OPENSSL_clear_free(kmac_buffer, kmac_out_len);
|
||||
else
|
||||
OPENSSL_cleanse(mac_buf, sizeof(mac_buf));
|
||||
|
||||
EVP_MAC_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *sskdf_new(void *provctx)
|
||||
{
|
||||
KDF_SSKDF *ctx;
|
||||
|
||||
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
ctx->provctx = provctx;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void sskdf_reset(void *vctx)
|
||||
{
|
||||
KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
|
||||
|
||||
EVP_MAC_CTX_free(ctx->macctx);
|
||||
ossl_prov_digest_reset(&ctx->digest);
|
||||
OPENSSL_clear_free(ctx->secret, ctx->secret_len);
|
||||
OPENSSL_clear_free(ctx->info, ctx->info_len);
|
||||
OPENSSL_clear_free(ctx->salt, ctx->salt_len);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void sskdf_free(void *vctx)
|
||||
{
|
||||
KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
|
||||
|
||||
sskdf_reset(ctx);
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
static int sskdf_set_buffer(unsigned char **out, size_t *out_len,
|
||||
const OSSL_PARAM *p)
|
||||
{
|
||||
if (p->data == NULL || p->data_size == 0)
|
||||
return 1;
|
||||
OPENSSL_free(*out);
|
||||
*out = NULL;
|
||||
return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len);
|
||||
}
|
||||
|
||||
static size_t sskdf_size(KDF_SSKDF *ctx)
|
||||
{
|
||||
int len;
|
||||
const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
|
||||
|
||||
if (md == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
len = EVP_MD_size(md);
|
||||
return (len <= 0) ? 0 : (size_t)len;
|
||||
}
|
||||
|
||||
static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen)
|
||||
{
|
||||
KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
|
||||
const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
|
||||
|
||||
if (ctx->secret == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->macctx != NULL) {
|
||||
/* H(x) = KMAC or H(x) = HMAC */
|
||||
int ret;
|
||||
const unsigned char *custom = NULL;
|
||||
size_t custom_len = 0;
|
||||
int default_salt_len;
|
||||
EVP_MAC *mac = EVP_MAC_CTX_mac(ctx->macctx);
|
||||
|
||||
/*
|
||||
* TODO(3.0) investigate the necessity to have all these controls.
|
||||
* Why does KMAC require a salt length that's shorter than the MD
|
||||
* block size?
|
||||
*/
|
||||
if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_HMAC)) {
|
||||
/* H(x) = HMAC(x, salt, hash) */
|
||||
if (md == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
default_salt_len = EVP_MD_size(md);
|
||||
if (default_salt_len <= 0)
|
||||
return 0;
|
||||
} else if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC128)
|
||||
|| EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC256)) {
|
||||
/* H(x) = KMACzzz(x, salt, custom) */
|
||||
custom = kmac_custom_str;
|
||||
custom_len = sizeof(kmac_custom_str);
|
||||
if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC128))
|
||||
default_salt_len = SSKDF_KMAC128_DEFAULT_SALT_SIZE;
|
||||
else
|
||||
default_salt_len = SSKDF_KMAC256_DEFAULT_SALT_SIZE;
|
||||
} else {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_MAC_TYPE);
|
||||
return 0;
|
||||
}
|
||||
/* If no salt is set then use a default_salt of zeros */
|
||||
if (ctx->salt == NULL || ctx->salt_len <= 0) {
|
||||
ctx->salt = OPENSSL_zalloc(default_salt_len);
|
||||
if (ctx->salt == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
ctx->salt_len = default_salt_len;
|
||||
}
|
||||
ret = SSKDF_mac_kdm(ctx->macctx,
|
||||
custom, custom_len, ctx->out_len,
|
||||
ctx->salt, ctx->salt_len,
|
||||
ctx->secret, ctx->secret_len,
|
||||
ctx->info, ctx->info_len, key, keylen);
|
||||
return ret;
|
||||
} else {
|
||||
/* H(x) = hash */
|
||||
if (md == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len,
|
||||
ctx->info, ctx->info_len, 0, key, keylen);
|
||||
}
|
||||
}
|
||||
|
||||
static int x963kdf_derive(void *vctx, unsigned char *key, size_t keylen)
|
||||
{
|
||||
KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
|
||||
const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
|
||||
|
||||
if (ctx->secret == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->macctx != NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* H(x) = hash */
|
||||
if (md == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len,
|
||||
ctx->info, ctx->info_len, 1, key, keylen);
|
||||
}
|
||||
|
||||
static int sskdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
KDF_SSKDF *ctx = vctx;
|
||||
OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
|
||||
size_t sz;
|
||||
|
||||
if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
|
||||
return 0;
|
||||
|
||||
if (!ossl_prov_macctx_load_from_params(&ctx->macctx, params,
|
||||
NULL, NULL, NULL, libctx))
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL
|
||||
|| (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL)
|
||||
if (!sskdf_set_buffer(&ctx->secret, &ctx->secret_len, p))
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL)
|
||||
if (!sskdf_set_buffer(&ctx->info, &ctx->info_len, p))
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
|
||||
if (!sskdf_set_buffer(&ctx->salt, &ctx->salt_len, p))
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MAC_SIZE))
|
||||
!= NULL) {
|
||||
if (!OSSL_PARAM_get_size_t(p, &sz) || sz == 0)
|
||||
return 0;
|
||||
ctx->out_len = sz;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *sskdf_settable_ctx_params(void)
|
||||
{
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
|
||||
OSSL_PARAM_size_t(OSSL_KDF_PARAM_MAC_SIZE, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
static int sskdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
||||
{
|
||||
KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
|
||||
return OSSL_PARAM_set_size_t(p, sskdf_size(ctx));
|
||||
return -2;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *sskdf_gettable_ctx_params(void)
|
||||
{
|
||||
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
return known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH kdf_sskdf_functions[] = {
|
||||
{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new },
|
||||
{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free },
|
||||
{ OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset },
|
||||
{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))sskdf_derive },
|
||||
{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
|
||||
(void(*)(void))sskdf_settable_ctx_params },
|
||||
{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))sskdf_set_ctx_params },
|
||||
{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
|
||||
(void(*)(void))sskdf_gettable_ctx_params },
|
||||
{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
const OSSL_DISPATCH kdf_x963_kdf_functions[] = {
|
||||
{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new },
|
||||
{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free },
|
||||
{ OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset },
|
||||
{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))x963kdf_derive },
|
||||
{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
|
||||
(void(*)(void))sskdf_settable_ctx_params },
|
||||
{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))sskdf_set_ctx_params },
|
||||
{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
|
||||
(void(*)(void))sskdf_gettable_ctx_params },
|
||||
{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* Copyright 2016-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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Refer to "The TLS Protocol Version 1.0" Section 5
|
||||
* (https://tools.ietf.org/html/rfc2246#section-5) and
|
||||
* "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5
|
||||
* (https://tools.ietf.org/html/rfc5246#section-5).
|
||||
*
|
||||
* For TLS v1.0 and TLS v1.1 the TLS PRF algorithm is given by:
|
||||
*
|
||||
* PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
|
||||
* P_SHA-1(S2, label + seed)
|
||||
*
|
||||
* where P_MD5 and P_SHA-1 are defined by P_<hash>, below, and S1 and S2 are
|
||||
* two halves of the secret (with the possibility of one shared byte, in the
|
||||
* case where the length of the original secret is odd). S1 is taken from the
|
||||
* first half of the secret, S2 from the second half.
|
||||
*
|
||||
* For TLS v1.2 the TLS PRF algorithm is given by:
|
||||
*
|
||||
* PRF(secret, label, seed) = P_<hash>(secret, label + seed)
|
||||
*
|
||||
* where hash is SHA-256 for all cipher suites defined in RFC 5246 as well as
|
||||
* those published prior to TLS v1.2 while the TLS v1.2 protocol is in effect,
|
||||
* unless defined otherwise by the cipher suite.
|
||||
*
|
||||
* P_<hash> is an expansion function that uses a single hash function to expand
|
||||
* a secret and seed into an arbitrary quantity of output:
|
||||
*
|
||||
* P_<hash>(secret, seed) = HMAC_<hash>(secret, A(1) + seed) +
|
||||
* HMAC_<hash>(secret, A(2) + seed) +
|
||||
* HMAC_<hash>(secret, A(3) + seed) + ...
|
||||
*
|
||||
* where + indicates concatenation. P_<hash> can be iterated as many times as
|
||||
* is necessary to produce the required quantity of data.
|
||||
*
|
||||
* A(i) is defined as:
|
||||
* A(0) = seed
|
||||
* A(i) = HMAC_<hash>(secret, A(i-1))
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/kdf.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/params.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/numbers.h"
|
||||
#include "internal/evp_int.h"
|
||||
#include "internal/provider_ctx.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
#include "internal/provider_algs.h"
|
||||
#include "internal/provider_util.h"
|
||||
#include "e_os.h"
|
||||
|
||||
static OSSL_OP_kdf_newctx_fn kdf_tls1_prf_new;
|
||||
static OSSL_OP_kdf_freectx_fn kdf_tls1_prf_free;
|
||||
static OSSL_OP_kdf_reset_fn kdf_tls1_prf_reset;
|
||||
static OSSL_OP_kdf_derive_fn kdf_tls1_prf_derive;
|
||||
static OSSL_OP_kdf_settable_ctx_params_fn kdf_tls1_prf_settable_ctx_params;
|
||||
static OSSL_OP_kdf_set_ctx_params_fn kdf_tls1_prf_set_ctx_params;
|
||||
|
||||
static int tls1_prf_alg(EVP_MAC_CTX *mdctx, EVP_MAC_CTX *sha1ctx,
|
||||
const unsigned char *sec, size_t slen,
|
||||
const unsigned char *seed, size_t seed_len,
|
||||
unsigned char *out, size_t olen);
|
||||
|
||||
#define TLS1_PRF_MAXBUF 1024
|
||||
|
||||
/* TLS KDF kdf context structure */
|
||||
typedef struct {
|
||||
void *provctx;
|
||||
|
||||
/* MAC context for the main digest */
|
||||
EVP_MAC_CTX *P_hash;
|
||||
/* MAC context for SHA1 for the MD5/SHA-1 combined PRF */
|
||||
EVP_MAC_CTX *P_sha1;
|
||||
|
||||
/* Secret value to use for PRF */
|
||||
unsigned char *sec;
|
||||
size_t seclen;
|
||||
/* Buffer of concatenated seed data */
|
||||
unsigned char seed[TLS1_PRF_MAXBUF];
|
||||
size_t seedlen;
|
||||
} TLS1_PRF;
|
||||
|
||||
static void *kdf_tls1_prf_new(void *provctx)
|
||||
{
|
||||
TLS1_PRF *ctx;
|
||||
|
||||
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
ctx->provctx = provctx;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void kdf_tls1_prf_free(void *vctx)
|
||||
{
|
||||
TLS1_PRF *ctx = (TLS1_PRF *)vctx;
|
||||
|
||||
kdf_tls1_prf_reset(ctx);
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
static void kdf_tls1_prf_reset(void *vctx)
|
||||
{
|
||||
TLS1_PRF *ctx = (TLS1_PRF *)vctx;
|
||||
|
||||
EVP_MAC_CTX_free(ctx->P_hash);
|
||||
EVP_MAC_CTX_free(ctx->P_sha1);
|
||||
OPENSSL_clear_free(ctx->sec, ctx->seclen);
|
||||
OPENSSL_cleanse(ctx->seed, ctx->seedlen);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static int kdf_tls1_prf_derive(void *vctx, unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
TLS1_PRF *ctx = (TLS1_PRF *)vctx;
|
||||
|
||||
if (ctx->P_hash == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
if (ctx->sec == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
|
||||
return 0;
|
||||
}
|
||||
if (ctx->seedlen == 0) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SEED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tls1_prf_alg(ctx->P_hash, ctx->P_sha1,
|
||||
ctx->sec, ctx->seclen,
|
||||
ctx->seed, ctx->seedlen,
|
||||
key, keylen);
|
||||
}
|
||||
|
||||
static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
TLS1_PRF *ctx = vctx;
|
||||
OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) {
|
||||
if (strcasecmp(p->data, SN_md5_sha1) == 0) {
|
||||
if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params,
|
||||
OSSL_MAC_NAME_HMAC,
|
||||
NULL, SN_md5, libctx)
|
||||
|| !ossl_prov_macctx_load_from_params(&ctx->P_sha1, params,
|
||||
OSSL_MAC_NAME_HMAC,
|
||||
NULL, SN_sha1, libctx))
|
||||
return 0;
|
||||
} else {
|
||||
EVP_MAC_CTX_free(ctx->P_sha1);
|
||||
if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params,
|
||||
OSSL_MAC_NAME_HMAC,
|
||||
NULL, NULL, libctx))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL) {
|
||||
OPENSSL_clear_free(ctx->sec, ctx->seclen);
|
||||
ctx->sec = NULL;
|
||||
if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->sec, 0, &ctx->seclen))
|
||||
return 0;
|
||||
}
|
||||
/* The seed fields concatenate, so process them all */
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SEED)) != NULL) {
|
||||
OPENSSL_cleanse(ctx->seed, ctx->seedlen);
|
||||
ctx->seedlen = 0;
|
||||
|
||||
for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1,
|
||||
OSSL_KDF_PARAM_SEED)) {
|
||||
const void *q = ctx->seed + ctx->seedlen;
|
||||
size_t sz = 0;
|
||||
|
||||
if (p->data_size != 0
|
||||
&& p->data != NULL
|
||||
&& !OSSL_PARAM_get_octet_string(p, (void **)&q,
|
||||
TLS1_PRF_MAXBUF - ctx->seedlen,
|
||||
&sz))
|
||||
return 0;
|
||||
ctx->seedlen += sz;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *kdf_tls1_prf_settable_ctx_params(void)
|
||||
{
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SEED, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
static int kdf_tls1_prf_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
||||
{
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
|
||||
return OSSL_PARAM_set_size_t(p, SIZE_MAX);
|
||||
return -2;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *kdf_tls1_prf_gettable_ctx_params(void)
|
||||
{
|
||||
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
return known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH kdf_tls1_prf_functions[] = {
|
||||
{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_tls1_prf_new },
|
||||
{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_tls1_prf_free },
|
||||
{ OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_tls1_prf_reset },
|
||||
{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_prf_derive },
|
||||
{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
|
||||
(void(*)(void))kdf_tls1_prf_settable_ctx_params },
|
||||
{ OSSL_FUNC_KDF_SET_CTX_PARAMS,
|
||||
(void(*)(void))kdf_tls1_prf_set_ctx_params },
|
||||
{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
|
||||
(void(*)(void))kdf_tls1_prf_gettable_ctx_params },
|
||||
{ OSSL_FUNC_KDF_GET_CTX_PARAMS,
|
||||
(void(*)(void))kdf_tls1_prf_get_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* Refer to "The TLS Protocol Version 1.0" Section 5
|
||||
* (https://tools.ietf.org/html/rfc2246#section-5) and
|
||||
* "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5
|
||||
* (https://tools.ietf.org/html/rfc5246#section-5).
|
||||
*
|
||||
* P_<hash> is an expansion function that uses a single hash function to expand
|
||||
* a secret and seed into an arbitrary quantity of output:
|
||||
*
|
||||
* P_<hash>(secret, seed) = HMAC_<hash>(secret, A(1) + seed) +
|
||||
* HMAC_<hash>(secret, A(2) + seed) +
|
||||
* HMAC_<hash>(secret, A(3) + seed) + ...
|
||||
*
|
||||
* where + indicates concatenation. P_<hash> can be iterated as many times as
|
||||
* is necessary to produce the required quantity of data.
|
||||
*
|
||||
* A(i) is defined as:
|
||||
* A(0) = seed
|
||||
* A(i) = HMAC_<hash>(secret, A(i-1))
|
||||
*/
|
||||
static int tls1_prf_P_hash(EVP_MAC_CTX *ctx_init,
|
||||
const unsigned char *sec, size_t sec_len,
|
||||
const unsigned char *seed, size_t seed_len,
|
||||
unsigned char *out, size_t olen)
|
||||
{
|
||||
size_t chunk;
|
||||
EVP_MAC_CTX *ctx = NULL, *ctx_Ai = NULL;
|
||||
unsigned char Ai[EVP_MAX_MD_SIZE];
|
||||
size_t Ai_len;
|
||||
int ret = 0;
|
||||
OSSL_PARAM params[2], *p = params;
|
||||
|
||||
*p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
|
||||
(void *)sec, sec_len);
|
||||
*p = OSSL_PARAM_construct_end();
|
||||
if (!EVP_MAC_CTX_set_params(ctx_init, params))
|
||||
goto err;
|
||||
if (!EVP_MAC_init(ctx_init))
|
||||
goto err;
|
||||
chunk = EVP_MAC_size(ctx_init);
|
||||
if (chunk == 0)
|
||||
goto err;
|
||||
/* A(0) = seed */
|
||||
ctx_Ai = EVP_MAC_CTX_dup(ctx_init);
|
||||
if (ctx_Ai == NULL)
|
||||
goto err;
|
||||
if (seed != NULL && !EVP_MAC_update(ctx_Ai, seed, seed_len))
|
||||
goto err;
|
||||
|
||||
for (;;) {
|
||||
/* calc: A(i) = HMAC_<hash>(secret, A(i-1)) */
|
||||
if (!EVP_MAC_final(ctx_Ai, Ai, &Ai_len, sizeof(Ai)))
|
||||
goto err;
|
||||
EVP_MAC_CTX_free(ctx_Ai);
|
||||
ctx_Ai = NULL;
|
||||
|
||||
/* calc next chunk: HMAC_<hash>(secret, A(i) + seed) */
|
||||
ctx = EVP_MAC_CTX_dup(ctx_init);
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
if (!EVP_MAC_update(ctx, Ai, Ai_len))
|
||||
goto err;
|
||||
/* save state for calculating next A(i) value */
|
||||
if (olen > chunk) {
|
||||
ctx_Ai = EVP_MAC_CTX_dup(ctx);
|
||||
if (ctx_Ai == NULL)
|
||||
goto err;
|
||||
}
|
||||
if (seed != NULL && !EVP_MAC_update(ctx, seed, seed_len))
|
||||
goto err;
|
||||
if (olen <= chunk) {
|
||||
/* last chunk - use Ai as temp bounce buffer */
|
||||
if (!EVP_MAC_final(ctx, Ai, &Ai_len, sizeof(Ai)))
|
||||
goto err;
|
||||
memcpy(out, Ai, olen);
|
||||
break;
|
||||
}
|
||||
if (!EVP_MAC_final(ctx, out, NULL, olen))
|
||||
goto err;
|
||||
EVP_MAC_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
out += chunk;
|
||||
olen -= chunk;
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
EVP_MAC_CTX_free(ctx);
|
||||
EVP_MAC_CTX_free(ctx_Ai);
|
||||
OPENSSL_cleanse(Ai, sizeof(Ai));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Refer to "The TLS Protocol Version 1.0" Section 5
|
||||
* (https://tools.ietf.org/html/rfc2246#section-5) and
|
||||
* "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5
|
||||
* (https://tools.ietf.org/html/rfc5246#section-5).
|
||||
*
|
||||
* For TLS v1.0 and TLS v1.1:
|
||||
*
|
||||
* PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
|
||||
* P_SHA-1(S2, label + seed)
|
||||
*
|
||||
* S1 is taken from the first half of the secret, S2 from the second half.
|
||||
*
|
||||
* L_S = length in bytes of secret;
|
||||
* L_S1 = L_S2 = ceil(L_S / 2);
|
||||
*
|
||||
* For TLS v1.2:
|
||||
*
|
||||
* PRF(secret, label, seed) = P_<hash>(secret, label + seed)
|
||||
*/
|
||||
static int tls1_prf_alg(EVP_MAC_CTX *mdctx, EVP_MAC_CTX *sha1ctx,
|
||||
const unsigned char *sec, size_t slen,
|
||||
const unsigned char *seed, size_t seed_len,
|
||||
unsigned char *out, size_t olen)
|
||||
{
|
||||
if (sha1ctx != NULL) {
|
||||
/* TLS v1.0 and TLS v1.1 */
|
||||
size_t i;
|
||||
unsigned char *tmp;
|
||||
/* calc: L_S1 = L_S2 = ceil(L_S / 2) */
|
||||
size_t L_S1 = (slen + 1) / 2;
|
||||
size_t L_S2 = L_S1;
|
||||
|
||||
if (!tls1_prf_P_hash(mdctx, sec, L_S1,
|
||||
seed, seed_len, out, olen))
|
||||
return 0;
|
||||
|
||||
if ((tmp = OPENSSL_malloc(olen)) == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!tls1_prf_P_hash(sha1ctx, sec + slen - L_S2, L_S2,
|
||||
seed, seed_len, tmp, olen)) {
|
||||
OPENSSL_clear_free(tmp, olen);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < olen; i++)
|
||||
out[i] ^= tmp[i];
|
||||
OPENSSL_clear_free(tmp, olen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* TLS v1.2 */
|
||||
if (!tls1_prf_P_hash(mdctx, sec, slen, seed, seed_len, out, olen))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
LIBS=../../../libcrypto
|
||||
IF[{- !$disabled{dh} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
dh_kmgmt.c
|
||||
ENDIF
|
||||
IF[{- !$disabled{dsa} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
dsa_kmgmt.c
|
||||
ENDIF
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 <openssl/core_names.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/params.h>
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static OSSL_OP_keymgmt_importkey_fn dh_importkey;
|
||||
|
||||
static int params_to_key(DH *dh, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *param_p, *param_g, *param_priv_key, *param_pub_key;
|
||||
BIGNUM *p = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL;
|
||||
|
||||
if (dh == NULL)
|
||||
return 0;
|
||||
|
||||
param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P);
|
||||
param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G);
|
||||
param_priv_key =
|
||||
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_KEY);
|
||||
param_pub_key =
|
||||
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PUB_KEY);
|
||||
|
||||
/*
|
||||
* DH documentation says that a public key must be present if a
|
||||
* private key is present.
|
||||
* We want to have at least a public key either way, so we end up
|
||||
* requiring it unconditionally.
|
||||
*/
|
||||
if (param_pub_key == NULL)
|
||||
return 0;
|
||||
|
||||
if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
|
||||
|| (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g))
|
||||
|| (param_priv_key != NULL
|
||||
&& !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
|
||||
|| !OSSL_PARAM_get_BN(param_pub_key, &pub_key))
|
||||
goto err;
|
||||
|
||||
if (!DH_set0_pqg(dh, p, NULL, g))
|
||||
goto err;
|
||||
p = g = NULL;
|
||||
|
||||
if (!DH_set0_key(dh, pub_key, priv_key))
|
||||
goto err;
|
||||
priv_key = pub_key = NULL;
|
||||
|
||||
return 1;
|
||||
|
||||
err:
|
||||
BN_free(p);
|
||||
BN_free(g);
|
||||
BN_free(priv_key);
|
||||
BN_free(pub_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *dh_importkey(void *provctx, const OSSL_PARAM params[])
|
||||
{
|
||||
DH *dh;
|
||||
|
||||
if ((dh = DH_new()) == NULL
|
||||
|| !params_to_key(dh, params)) {
|
||||
DH_free(dh);
|
||||
dh = NULL;
|
||||
}
|
||||
return dh;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH dh_keymgmt_functions[] = {
|
||||
/*
|
||||
* TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also
|
||||
* implement OSSL_FUNC_KEYMGMT_EXPORTKEY.
|
||||
*/
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dh_importkey },
|
||||
{ OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DH_free },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 <openssl/core_names.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/params.h>
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static OSSL_OP_keymgmt_importkey_fn dsa_importkey;
|
||||
|
||||
static int params_to_key(DSA *dsa, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *param_p, *param_q, *param_g, *param_priv_key;
|
||||
const OSSL_PARAM *param_pub_key;
|
||||
BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL;
|
||||
|
||||
if (dsa == NULL)
|
||||
return 0;
|
||||
|
||||
param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P);
|
||||
param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q);
|
||||
param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G);
|
||||
param_priv_key =
|
||||
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PRIV_KEY);
|
||||
param_pub_key =
|
||||
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PUB_KEY);
|
||||
|
||||
/*
|
||||
* DSA documentation says that a public key must be present if a private key
|
||||
* is.
|
||||
*/
|
||||
if (param_priv_key != NULL && param_pub_key == NULL)
|
||||
return 0;
|
||||
|
||||
if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
|
||||
|| (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q))
|
||||
|| (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g))
|
||||
|| (param_priv_key != NULL
|
||||
&& !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
|
||||
|| (param_pub_key != NULL
|
||||
&& !OSSL_PARAM_get_BN(param_pub_key, &pub_key)))
|
||||
goto err;
|
||||
|
||||
if (!DSA_set0_pqg(dsa, p, q, g))
|
||||
goto err;
|
||||
p = q = g = NULL;
|
||||
|
||||
if (pub_key != NULL && !DSA_set0_key(dsa, pub_key, priv_key))
|
||||
goto err;
|
||||
priv_key = pub_key = NULL;
|
||||
|
||||
return 1;
|
||||
|
||||
err:
|
||||
BN_free(p);
|
||||
BN_free(q);
|
||||
BN_free(g);
|
||||
BN_free(priv_key);
|
||||
BN_free(pub_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *dsa_importkey(void *provctx, const OSSL_PARAM params[])
|
||||
{
|
||||
DSA *dsa;
|
||||
|
||||
if ((dsa = DSA_new()) == NULL
|
||||
|| !params_to_key(dsa, params)) {
|
||||
DSA_free(dsa);
|
||||
dsa = NULL;
|
||||
}
|
||||
return dsa;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH dsa_keymgmt_functions[] = {
|
||||
/*
|
||||
* TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also
|
||||
* implement OSSL_FUNC_KEYMGMT_EXPORTKEY.
|
||||
*/
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dsa_importkey },
|
||||
{ OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DSA_free },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
$COMMON=gmac_prov.c hmac_prov.c kmac_prov.c
|
||||
|
||||
IF[{- !$disabled{cmac} -}]
|
||||
$COMMON=$COMMON cmac_prov.c
|
||||
ENDIF
|
||||
|
||||
LIBS=../../../libcrypto
|
||||
SOURCE[../../../libcrypto]=$COMMON
|
||||
INCLUDE[../../../libcrypto]=. ../../../crypto
|
||||
|
||||
IF[{- !$disabled{fips} -}]
|
||||
MODULES=../../fips
|
||||
SOURCE[../../fips]=$COMMON
|
||||
INCLUDE[../../fips]=. ../../../crypto
|
||||
ENDIF
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright 2018 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 <openssl/core_names.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/cmac.h>
|
||||
|
||||
#include "internal/provider_algs.h"
|
||||
#include "internal/provider_ctx.h"
|
||||
#include "internal/provider_util.h"
|
||||
|
||||
/*
|
||||
* Forward declaration of everything implemented here. This is not strictly
|
||||
* necessary for the compiler, but provides an assurance that the signatures
|
||||
* of the functions in the dispatch table are correct.
|
||||
*/
|
||||
static OSSL_OP_mac_newctx_fn cmac_new;
|
||||
static OSSL_OP_mac_dupctx_fn cmac_dup;
|
||||
static OSSL_OP_mac_freectx_fn cmac_free;
|
||||
static OSSL_OP_mac_gettable_ctx_params_fn cmac_gettable_ctx_params;
|
||||
static OSSL_OP_mac_get_ctx_params_fn cmac_get_ctx_params;
|
||||
static OSSL_OP_mac_settable_ctx_params_fn cmac_settable_ctx_params;
|
||||
static OSSL_OP_mac_set_ctx_params_fn cmac_set_ctx_params;
|
||||
static OSSL_OP_mac_init_fn cmac_init;
|
||||
static OSSL_OP_mac_update_fn cmac_update;
|
||||
static OSSL_OP_mac_final_fn cmac_final;
|
||||
|
||||
/* local CMAC data */
|
||||
|
||||
struct cmac_data_st {
|
||||
void *provctx;
|
||||
CMAC_CTX *ctx;
|
||||
PROV_CIPHER cipher;
|
||||
};
|
||||
|
||||
static void *cmac_new(void *provctx)
|
||||
{
|
||||
struct cmac_data_st *macctx;
|
||||
|
||||
if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL
|
||||
|| (macctx->ctx = CMAC_CTX_new()) == NULL) {
|
||||
OPENSSL_free(macctx);
|
||||
macctx = NULL;
|
||||
} else {
|
||||
macctx->provctx = provctx;
|
||||
}
|
||||
|
||||
return macctx;
|
||||
}
|
||||
|
||||
static void cmac_free(void *vmacctx)
|
||||
{
|
||||
struct cmac_data_st *macctx = vmacctx;
|
||||
|
||||
if (macctx != NULL) {
|
||||
CMAC_CTX_free(macctx->ctx);
|
||||
ossl_prov_cipher_reset(&macctx->cipher);
|
||||
OPENSSL_free(macctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void *cmac_dup(void *vsrc)
|
||||
{
|
||||
struct cmac_data_st *src = vsrc;
|
||||
struct cmac_data_st *dst = cmac_new(src->provctx);
|
||||
|
||||
if (!CMAC_CTX_copy(dst->ctx, src->ctx)
|
||||
|| !ossl_prov_cipher_copy(&dst->cipher, &src->cipher)) {
|
||||
cmac_free(dst);
|
||||
return NULL;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
static size_t cmac_size(void *vmacctx)
|
||||
{
|
||||
struct cmac_data_st *macctx = vmacctx;
|
||||
|
||||
return EVP_CIPHER_CTX_block_size(CMAC_CTX_get0_cipher_ctx(macctx->ctx));
|
||||
}
|
||||
|
||||
static int cmac_init(void *vmacctx)
|
||||
{
|
||||
struct cmac_data_st *macctx = vmacctx;
|
||||
int rv = CMAC_Init(macctx->ctx, NULL, 0,
|
||||
ossl_prov_cipher_cipher(&macctx->cipher),
|
||||
ossl_prov_cipher_engine(&macctx->cipher));
|
||||
|
||||
ossl_prov_cipher_reset(&macctx->cipher);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int cmac_update(void *vmacctx, const unsigned char *data,
|
||||
size_t datalen)
|
||||
{
|
||||
struct cmac_data_st *macctx = vmacctx;
|
||||
|
||||
return CMAC_Update(macctx->ctx, data, datalen);
|
||||
}
|
||||
|
||||
static int cmac_final(void *vmacctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
struct cmac_data_st *macctx = vmacctx;
|
||||
|
||||
return CMAC_Final(macctx->ctx, out, outl);
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM *cmac_gettable_ctx_params(void)
|
||||
{
|
||||
return known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
static int cmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[])
|
||||
{
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL)
|
||||
return OSSL_PARAM_set_size_t(p, cmac_size(vmacctx));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_CIPHER, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_ENGINE, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM *cmac_settable_ctx_params(void)
|
||||
{
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
/*
|
||||
* ALL parameters should be set before init().
|
||||
*/
|
||||
static int cmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
|
||||
{
|
||||
struct cmac_data_st *macctx = vmacctx;
|
||||
OPENSSL_CTX *ctx = PROV_LIBRARY_CONTEXT_OF(macctx->provctx);
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
if (!ossl_prov_cipher_load_from_params(&macctx->cipher, params, ctx))
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) {
|
||||
if (p->data_type != OSSL_PARAM_OCTET_STRING)
|
||||
return 0;
|
||||
|
||||
if (!CMAC_Init(macctx->ctx, p->data, p->data_size,
|
||||
ossl_prov_cipher_cipher(&macctx->cipher),
|
||||
ossl_prov_cipher_engine(&macctx->cipher)))
|
||||
return 0;
|
||||
|
||||
ossl_prov_cipher_reset(&macctx->cipher);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH cmac_functions[] = {
|
||||
{ OSSL_FUNC_MAC_NEWCTX, (void (*)(void))cmac_new },
|
||||
{ OSSL_FUNC_MAC_DUPCTX, (void (*)(void))cmac_dup },
|
||||
{ OSSL_FUNC_MAC_FREECTX, (void (*)(void))cmac_free },
|
||||
{ OSSL_FUNC_MAC_INIT, (void (*)(void))cmac_init },
|
||||
{ OSSL_FUNC_MAC_UPDATE, (void (*)(void))cmac_update },
|
||||
{ OSSL_FUNC_MAC_FINAL, (void (*)(void))cmac_final },
|
||||
{ OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))cmac_gettable_ctx_params },
|
||||
{ OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))cmac_get_ctx_params },
|
||||
{ OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))cmac_settable_ctx_params },
|
||||
{ OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))cmac_set_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright 2018 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 <stdlib.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "internal/providercommonerr.h"
|
||||
#include "internal/provider_algs.h"
|
||||
#include "internal/provider_ctx.h"
|
||||
#include "internal/provider_util.h"
|
||||
|
||||
/*
|
||||
* Forward declaration of everything implemented here. This is not strictly
|
||||
* necessary for the compiler, but provides an assurance that the signatures
|
||||
* of the functions in the dispatch table are correct.
|
||||
*/
|
||||
static OSSL_OP_mac_newctx_fn gmac_new;
|
||||
static OSSL_OP_mac_dupctx_fn gmac_dup;
|
||||
static OSSL_OP_mac_freectx_fn gmac_free;
|
||||
static OSSL_OP_mac_gettable_params_fn gmac_gettable_params;
|
||||
static OSSL_OP_mac_get_params_fn gmac_get_params;
|
||||
static OSSL_OP_mac_settable_ctx_params_fn gmac_settable_ctx_params;
|
||||
static OSSL_OP_mac_set_ctx_params_fn gmac_set_ctx_params;
|
||||
static OSSL_OP_mac_init_fn gmac_init;
|
||||
static OSSL_OP_mac_update_fn gmac_update;
|
||||
static OSSL_OP_mac_final_fn gmac_final;
|
||||
|
||||
/* local GMAC pkey structure */
|
||||
|
||||
struct gmac_data_st {
|
||||
void *provctx;
|
||||
EVP_CIPHER_CTX *ctx; /* Cipher context */
|
||||
PROV_CIPHER cipher;
|
||||
};
|
||||
|
||||
static size_t gmac_size(void);
|
||||
|
||||
static void gmac_free(void *vmacctx)
|
||||
{
|
||||
struct gmac_data_st *macctx = vmacctx;
|
||||
|
||||
if (macctx != NULL) {
|
||||
EVP_CIPHER_CTX_free(macctx->ctx);
|
||||
ossl_prov_cipher_reset(&macctx->cipher);
|
||||
OPENSSL_free(macctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void *gmac_new(void *provctx)
|
||||
{
|
||||
struct gmac_data_st *macctx;
|
||||
|
||||
if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL
|
||||
|| (macctx->ctx = EVP_CIPHER_CTX_new()) == NULL) {
|
||||
gmac_free(macctx);
|
||||
return NULL;
|
||||
}
|
||||
macctx->provctx = provctx;
|
||||
|
||||
return macctx;
|
||||
}
|
||||
|
||||
static void *gmac_dup(void *vsrc)
|
||||
{
|
||||
struct gmac_data_st *src = vsrc;
|
||||
struct gmac_data_st *dst = gmac_new(src->provctx);
|
||||
|
||||
if (dst == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!EVP_CIPHER_CTX_copy(dst->ctx, src->ctx)
|
||||
|| !ossl_prov_cipher_copy(&dst->cipher, &src->cipher)) {
|
||||
gmac_free(dst);
|
||||
return NULL;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
static int gmac_init(void *vmacctx)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gmac_update(void *vmacctx, const unsigned char *data,
|
||||
size_t datalen)
|
||||
{
|
||||
struct gmac_data_st *macctx = vmacctx;
|
||||
EVP_CIPHER_CTX *ctx = macctx->ctx;
|
||||
int outlen;
|
||||
|
||||
while (datalen > INT_MAX) {
|
||||
if (!EVP_EncryptUpdate(ctx, NULL, &outlen, data, INT_MAX))
|
||||
return 0;
|
||||
data += INT_MAX;
|
||||
datalen -= INT_MAX;
|
||||
}
|
||||
return EVP_EncryptUpdate(ctx, NULL, &outlen, data, datalen);
|
||||
}
|
||||
|
||||
static int gmac_final(void *vmacctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
struct gmac_data_st *macctx = vmacctx;
|
||||
int hlen = 0;
|
||||
|
||||
if (!EVP_EncryptFinal_ex(macctx->ctx, out, &hlen))
|
||||
return 0;
|
||||
|
||||
/* TODO(3.0) Use params */
|
||||
hlen = gmac_size();
|
||||
if (!EVP_CIPHER_CTX_ctrl(macctx->ctx, EVP_CTRL_AEAD_GET_TAG,
|
||||
hlen, out))
|
||||
return 0;
|
||||
|
||||
*outl = hlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t gmac_size(void)
|
||||
{
|
||||
return EVP_GCM_TLS_TAG_LEN;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_gettable_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM *gmac_gettable_params(void)
|
||||
{
|
||||
return known_gettable_params;
|
||||
}
|
||||
|
||||
static int gmac_get_params(OSSL_PARAM params[])
|
||||
{
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL)
|
||||
return OSSL_PARAM_set_size_t(p, gmac_size());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_CIPHER, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_ENGINE, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_MAC_PARAM_IV, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM *gmac_settable_ctx_params(void)
|
||||
{
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
/*
|
||||
* ALL parameters should be set before init().
|
||||
*/
|
||||
static int gmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
|
||||
{
|
||||
struct gmac_data_st *macctx = vmacctx;
|
||||
EVP_CIPHER_CTX *ctx = macctx->ctx;
|
||||
OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(macctx->provctx);
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
if (ctx == NULL
|
||||
|| !ossl_prov_cipher_load_from_params(&macctx->cipher, params, provctx))
|
||||
return 0;
|
||||
|
||||
if (EVP_CIPHER_mode(ossl_prov_cipher_cipher(&macctx->cipher))
|
||||
!= EVP_CIPH_GCM_MODE) {
|
||||
ERR_raise(ERR_LIB_PROV, EVP_R_CIPHER_NOT_GCM_MODE);
|
||||
return 0;
|
||||
}
|
||||
if (!EVP_EncryptInit_ex(ctx, ossl_prov_cipher_cipher(&macctx->cipher),
|
||||
ossl_prov_cipher_engine(&macctx->cipher), NULL,
|
||||
NULL))
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) {
|
||||
if (p->data_type != OSSL_PARAM_OCTET_STRING)
|
||||
return 0;
|
||||
|
||||
if (p->data_size != (size_t)EVP_CIPHER_CTX_key_length(ctx)) {
|
||||
ERR_raise(ERR_LIB_PROV, EVP_R_INVALID_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if (!EVP_EncryptInit_ex(ctx, NULL, NULL, p->data, NULL))
|
||||
return 0;
|
||||
}
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_IV)) != NULL) {
|
||||
if (p->data_type != OSSL_PARAM_OCTET_STRING)
|
||||
return 0;
|
||||
|
||||
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN,
|
||||
p->data_size, NULL)
|
||||
|| !EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, p->data))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH gmac_functions[] = {
|
||||
{ OSSL_FUNC_MAC_NEWCTX, (void (*)(void))gmac_new },
|
||||
{ OSSL_FUNC_MAC_DUPCTX, (void (*)(void))gmac_dup },
|
||||
{ OSSL_FUNC_MAC_FREECTX, (void (*)(void))gmac_free },
|
||||
{ OSSL_FUNC_MAC_INIT, (void (*)(void))gmac_init },
|
||||
{ OSSL_FUNC_MAC_UPDATE, (void (*)(void))gmac_update },
|
||||
{ OSSL_FUNC_MAC_FINAL, (void (*)(void))gmac_final },
|
||||
{ OSSL_FUNC_MAC_GETTABLE_PARAMS, (void (*)(void))gmac_gettable_params },
|
||||
{ OSSL_FUNC_MAC_GET_PARAMS, (void (*)(void))gmac_get_params },
|
||||
{ OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))gmac_settable_ctx_params },
|
||||
{ OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))gmac_set_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright 2018 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 <openssl/core_names.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
|
||||
#include "internal/provider_algs.h"
|
||||
#include "internal/provider_ctx.h"
|
||||
#include "internal/provider_util.h"
|
||||
|
||||
/*
|
||||
* Forward declaration of everything implemented here. This is not strictly
|
||||
* necessary for the compiler, but provides an assurance that the signatures
|
||||
* of the functions in the dispatch table are correct.
|
||||
*/
|
||||
static OSSL_OP_mac_newctx_fn hmac_new;
|
||||
static OSSL_OP_mac_dupctx_fn hmac_dup;
|
||||
static OSSL_OP_mac_freectx_fn hmac_free;
|
||||
static OSSL_OP_mac_gettable_ctx_params_fn hmac_gettable_ctx_params;
|
||||
static OSSL_OP_mac_get_ctx_params_fn hmac_get_ctx_params;
|
||||
static OSSL_OP_mac_settable_ctx_params_fn hmac_settable_ctx_params;
|
||||
static OSSL_OP_mac_set_ctx_params_fn hmac_set_ctx_params;
|
||||
static OSSL_OP_mac_init_fn hmac_init;
|
||||
static OSSL_OP_mac_update_fn hmac_update;
|
||||
static OSSL_OP_mac_final_fn hmac_final;
|
||||
|
||||
/* local HMAC context structure */
|
||||
|
||||
/* typedef EVP_MAC_IMPL */
|
||||
struct hmac_data_st {
|
||||
void *provctx;
|
||||
HMAC_CTX *ctx; /* HMAC context */
|
||||
PROV_DIGEST digest;
|
||||
};
|
||||
|
||||
static size_t hmac_size(void *vmacctx);
|
||||
|
||||
static void *hmac_new(void *provctx)
|
||||
{
|
||||
struct hmac_data_st *macctx;
|
||||
|
||||
if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL
|
||||
|| (macctx->ctx = HMAC_CTX_new()) == NULL) {
|
||||
OPENSSL_free(macctx);
|
||||
return NULL;
|
||||
}
|
||||
/* TODO(3.0) Should we do something more with that context? */
|
||||
macctx->provctx = provctx;
|
||||
|
||||
return macctx;
|
||||
}
|
||||
|
||||
static void hmac_free(void *vmacctx)
|
||||
{
|
||||
struct hmac_data_st *macctx = vmacctx;
|
||||
|
||||
if (macctx != NULL) {
|
||||
HMAC_CTX_free(macctx->ctx);
|
||||
ossl_prov_digest_reset(&macctx->digest);
|
||||
OPENSSL_free(macctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void *hmac_dup(void *vsrc)
|
||||
{
|
||||
struct hmac_data_st *src = vsrc;
|
||||
struct hmac_data_st *dst = hmac_new(src->provctx);
|
||||
|
||||
if (dst == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!HMAC_CTX_copy(dst->ctx, src->ctx)
|
||||
|| !ossl_prov_digest_copy(&dst->digest, &src->digest)) {
|
||||
hmac_free(dst);
|
||||
return NULL;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
static size_t hmac_size(void *vmacctx)
|
||||
{
|
||||
struct hmac_data_st *macctx = vmacctx;
|
||||
|
||||
return HMAC_size(macctx->ctx);
|
||||
}
|
||||
|
||||
static int hmac_init(void *vmacctx)
|
||||
{
|
||||
struct hmac_data_st *macctx = vmacctx;
|
||||
const EVP_MD *digest = ossl_prov_digest_md(&macctx->digest);
|
||||
int rv = 1;
|
||||
|
||||
/* HMAC_Init_ex doesn't tolerate all zero params, so we must be careful */
|
||||
if (digest != NULL)
|
||||
rv = HMAC_Init_ex(macctx->ctx, NULL, 0, digest,
|
||||
ossl_prov_digest_engine(&macctx->digest));
|
||||
ossl_prov_digest_reset(&macctx->digest);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int hmac_update(void *vmacctx, const unsigned char *data,
|
||||
size_t datalen)
|
||||
{
|
||||
struct hmac_data_st *macctx = vmacctx;
|
||||
|
||||
return HMAC_Update(macctx->ctx, data, datalen);
|
||||
}
|
||||
|
||||
static int hmac_final(void *vmacctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
unsigned int hlen;
|
||||
struct hmac_data_st *macctx = vmacctx;
|
||||
|
||||
if (!HMAC_Final(macctx->ctx, out, &hlen))
|
||||
return 0;
|
||||
if (outl != NULL)
|
||||
*outl = hlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM *hmac_gettable_ctx_params(void)
|
||||
{
|
||||
return known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
static int hmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[])
|
||||
{
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL)
|
||||
return OSSL_PARAM_set_size_t(p, hmac_size(vmacctx));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_ENGINE, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
|
||||
OSSL_PARAM_int(OSSL_MAC_PARAM_FLAGS, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM *hmac_settable_ctx_params(void)
|
||||
{
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
/*
|
||||
* ALL parameters should be set before init().
|
||||
*/
|
||||
static int hmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
|
||||
{
|
||||
struct hmac_data_st *macctx = vmacctx;
|
||||
OPENSSL_CTX *ctx = PROV_LIBRARY_CONTEXT_OF(macctx->provctx);
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
if (!ossl_prov_digest_load_from_params(&macctx->digest, params, ctx))
|
||||
return 0;
|
||||
|
||||
/* TODO(3.0) formalize the meaning of "flags", perhaps as other params */
|
||||
if ((p = OSSL_PARAM_locate_const(params,
|
||||
OSSL_MAC_PARAM_FLAGS)) != NULL) {
|
||||
int flags = 0;
|
||||
|
||||
if (!OSSL_PARAM_get_int(p, &flags))
|
||||
return 0;
|
||||
HMAC_CTX_set_flags(macctx->ctx, flags);
|
||||
}
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) {
|
||||
if (p->data_type != OSSL_PARAM_OCTET_STRING)
|
||||
return 0;
|
||||
|
||||
if (!HMAC_Init_ex(macctx->ctx, p->data, p->data_size,
|
||||
ossl_prov_digest_md(&macctx->digest),
|
||||
NULL /* ENGINE */))
|
||||
return 0;
|
||||
|
||||
ossl_prov_digest_reset(&macctx->digest);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH hmac_functions[] = {
|
||||
{ OSSL_FUNC_MAC_NEWCTX, (void (*)(void))hmac_new },
|
||||
{ OSSL_FUNC_MAC_DUPCTX, (void (*)(void))hmac_dup },
|
||||
{ OSSL_FUNC_MAC_FREECTX, (void (*)(void))hmac_free },
|
||||
{ OSSL_FUNC_MAC_INIT, (void (*)(void))hmac_init },
|
||||
{ OSSL_FUNC_MAC_UPDATE, (void (*)(void))hmac_update },
|
||||
{ OSSL_FUNC_MAC_FINAL, (void (*)(void))hmac_final },
|
||||
{ OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))hmac_gettable_ctx_params },
|
||||
{ OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))hmac_get_ctx_params },
|
||||
{ OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))hmac_settable_ctx_params },
|
||||
{ OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))hmac_set_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -0,0 +1,543 @@
|
||||
/*
|
||||
* Copyright 2018 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* See SP800-185 "Appendix A - KMAC, .... in Terms of Keccak[c]"
|
||||
*
|
||||
* Inputs are:
|
||||
* K = Key (len(K) < 2^2040 bits)
|
||||
* X = Input
|
||||
* L = Output length (0 <= L < 2^2040 bits)
|
||||
* S = Customization String Default="" (len(S) < 2^2040 bits)
|
||||
*
|
||||
* KMAC128(K, X, L, S)
|
||||
* {
|
||||
* newX = bytepad(encode_string(K), 168) || X || right_encode(L).
|
||||
* T = bytepad(encode_string("KMAC") || encode_string(S), 168).
|
||||
* return KECCAK[256](T || newX || 00, L).
|
||||
* }
|
||||
*
|
||||
* KMAC256(K, X, L, S)
|
||||
* {
|
||||
* newX = bytepad(encode_string(K), 136) || X || right_encode(L).
|
||||
* T = bytepad(encode_string("KMAC") || encode_string(S), 136).
|
||||
* return KECCAK[512](T || newX || 00, L).
|
||||
* }
|
||||
*
|
||||
* KMAC128XOF(K, X, L, S)
|
||||
* {
|
||||
* newX = bytepad(encode_string(K), 168) || X || right_encode(0).
|
||||
* T = bytepad(encode_string("KMAC") || encode_string(S), 168).
|
||||
* return KECCAK[256](T || newX || 00, L).
|
||||
* }
|
||||
*
|
||||
* KMAC256XOF(K, X, L, S)
|
||||
* {
|
||||
* newX = bytepad(encode_string(K), 136) || X || right_encode(0).
|
||||
* T = bytepad(encode_string("KMAC") || encode_string(S), 136).
|
||||
* return KECCAK[512](T || newX || 00, L).
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "internal/providercommonerr.h"
|
||||
#include "internal/provider_algs.h"
|
||||
#include "internal/provider_ctx.h"
|
||||
#include "internal/provider_util.h"
|
||||
|
||||
/*
|
||||
* Forward declaration of everything implemented here. This is not strictly
|
||||
* necessary for the compiler, but provides an assurance that the signatures
|
||||
* of the functions in the dispatch table are correct.
|
||||
*/
|
||||
static OSSL_OP_mac_newctx_fn kmac128_new;
|
||||
static OSSL_OP_mac_newctx_fn kmac256_new;
|
||||
static OSSL_OP_mac_dupctx_fn kmac_dup;
|
||||
static OSSL_OP_mac_freectx_fn kmac_free;
|
||||
static OSSL_OP_mac_gettable_ctx_params_fn kmac_gettable_ctx_params;
|
||||
static OSSL_OP_mac_get_ctx_params_fn kmac_get_ctx_params;
|
||||
static OSSL_OP_mac_settable_ctx_params_fn kmac_settable_ctx_params;
|
||||
static OSSL_OP_mac_set_ctx_params_fn kmac_set_ctx_params;
|
||||
static OSSL_OP_mac_size_fn kmac_size;
|
||||
static OSSL_OP_mac_init_fn kmac_init;
|
||||
static OSSL_OP_mac_update_fn kmac_update;
|
||||
static OSSL_OP_mac_final_fn kmac_final;
|
||||
|
||||
#define KMAC_MAX_BLOCKSIZE ((1600 - 128*2) / 8) /* 168 */
|
||||
#define KMAC_MIN_BLOCKSIZE ((1600 - 256*2) / 8) /* 136 */
|
||||
|
||||
/* Length encoding will be a 1 byte size + length in bits (2 bytes max) */
|
||||
#define KMAC_MAX_ENCODED_HEADER_LEN 3
|
||||
|
||||
/*
|
||||
* Custom string max size is chosen such that:
|
||||
* len(encoded_string(custom) + len(kmac_encoded_string) <= KMAC_MIN_BLOCKSIZE
|
||||
* i.e: (KMAC_MAX_CUSTOM + KMAC_MAX_ENCODED_LEN) + 6 <= 136
|
||||
*/
|
||||
#define KMAC_MAX_CUSTOM 127
|
||||
|
||||
/* Maximum size of encoded custom string */
|
||||
#define KMAC_MAX_CUSTOM_ENCODED (KMAC_MAX_CUSTOM + KMAC_MAX_ENCODED_HEADER_LEN)
|
||||
|
||||
/* Maximum key size in bytes = 2040 / 8 */
|
||||
#define KMAC_MAX_KEY 255
|
||||
|
||||
/*
|
||||
* Maximum Encoded Key size will be padded to a multiple of the blocksize
|
||||
* i.e KMAC_MAX_KEY + KMAC_MAX_ENCODED_LEN = 258
|
||||
* Padded to a multiple of KMAC_MAX_BLOCKSIZE
|
||||
*/
|
||||
#define KMAC_MAX_KEY_ENCODED (KMAC_MAX_BLOCKSIZE * 2)
|
||||
|
||||
/* Fixed value of encode_string("KMAC") */
|
||||
static const unsigned char kmac_string[] = {
|
||||
0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43
|
||||
};
|
||||
|
||||
|
||||
#define KMAC_FLAG_XOF_MODE 1
|
||||
|
||||
struct kmac_data_st {
|
||||
void *provctx;
|
||||
EVP_MD_CTX *ctx;
|
||||
PROV_DIGEST digest;
|
||||
size_t out_len;
|
||||
int key_len;
|
||||
int custom_len;
|
||||
/* If xof_mode = 1 then we use right_encode(0) */
|
||||
int xof_mode;
|
||||
/* key and custom are stored in encoded form */
|
||||
unsigned char key[KMAC_MAX_KEY_ENCODED];
|
||||
unsigned char custom[KMAC_MAX_CUSTOM_ENCODED];
|
||||
};
|
||||
|
||||
static int encode_string(unsigned char *out, int *out_len,
|
||||
const unsigned char *in, int in_len);
|
||||
static int right_encode(unsigned char *out, int *out_len, size_t bits);
|
||||
static int bytepad(unsigned char *out, int *out_len,
|
||||
const unsigned char *in1, int in1_len,
|
||||
const unsigned char *in2, int in2_len,
|
||||
int w);
|
||||
static int kmac_bytepad_encode_key(unsigned char *out, int *out_len,
|
||||
const unsigned char *in, int in_len,
|
||||
int w);
|
||||
|
||||
static void kmac_free(void *vmacctx)
|
||||
{
|
||||
struct kmac_data_st *kctx = vmacctx;
|
||||
|
||||
if (kctx != NULL) {
|
||||
EVP_MD_CTX_free(kctx->ctx);
|
||||
ossl_prov_digest_reset(&kctx->digest);
|
||||
OPENSSL_cleanse(kctx->key, kctx->key_len);
|
||||
OPENSSL_cleanse(kctx->custom, kctx->custom_len);
|
||||
OPENSSL_free(kctx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We have KMAC implemented as a hash, which we can use instead of
|
||||
* reimplementing the EVP functionality with direct use of
|
||||
* keccak_mac_init() and friends.
|
||||
*/
|
||||
static struct kmac_data_st *kmac_new(void *provctx)
|
||||
{
|
||||
struct kmac_data_st *kctx;
|
||||
|
||||
if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL
|
||||
|| (kctx->ctx = EVP_MD_CTX_new()) == NULL) {
|
||||
kmac_free(kctx);
|
||||
return NULL;
|
||||
}
|
||||
kctx->provctx = provctx;
|
||||
return kctx;
|
||||
}
|
||||
|
||||
static void *kmac_fetch_new(void *provctx, const OSSL_PARAM *params)
|
||||
{
|
||||
struct kmac_data_st *kctx = kmac_new(provctx);
|
||||
|
||||
if (kctx == NULL)
|
||||
return 0;
|
||||
if (!ossl_prov_digest_load_from_params(&kctx->digest, params,
|
||||
PROV_LIBRARY_CONTEXT_OF(provctx))) {
|
||||
kmac_free(kctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kctx->out_len = EVP_MD_size(ossl_prov_digest_md(&kctx->digest));
|
||||
return kctx;
|
||||
}
|
||||
|
||||
static void *kmac128_new(void *provctx)
|
||||
{
|
||||
static const OSSL_PARAM kmac128_params[] = {
|
||||
OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC128,
|
||||
sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC128)),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
return kmac_fetch_new(provctx, kmac128_params);
|
||||
}
|
||||
|
||||
static void *kmac256_new(void *provctx)
|
||||
{
|
||||
static const OSSL_PARAM kmac256_params[] = {
|
||||
OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC256,
|
||||
sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC256)),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
return kmac_fetch_new(provctx, kmac256_params);
|
||||
}
|
||||
|
||||
static void *kmac_dup(void *vsrc)
|
||||
{
|
||||
struct kmac_data_st *src = vsrc;
|
||||
struct kmac_data_st *dst = kmac_new(src->provctx);
|
||||
|
||||
if (dst == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!EVP_MD_CTX_copy(dst->ctx, src->ctx)
|
||||
|| !ossl_prov_digest_copy(&dst->digest, &src->digest)) {
|
||||
kmac_free(dst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dst->out_len = src->out_len;
|
||||
dst->key_len = src->key_len;
|
||||
dst->custom_len = src->custom_len;
|
||||
dst->xof_mode = src->xof_mode;
|
||||
memcpy(dst->key, src->key, src->key_len);
|
||||
memcpy(dst->custom, src->custom, dst->custom_len);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* The init() assumes that any ctrl methods are set beforehand for
|
||||
* md, key and custom. Setting the fields afterwards will have no
|
||||
* effect on the output mac.
|
||||
*/
|
||||
static int kmac_init(void *vmacctx)
|
||||
{
|
||||
struct kmac_data_st *kctx = vmacctx;
|
||||
EVP_MD_CTX *ctx = kctx->ctx;
|
||||
unsigned char out[KMAC_MAX_BLOCKSIZE];
|
||||
int out_len, block_len;
|
||||
|
||||
|
||||
/* Check key has been set */
|
||||
if (kctx->key_len == 0) {
|
||||
EVPerr(EVP_F_KMAC_INIT, EVP_R_NO_KEY_SET);
|
||||
return 0;
|
||||
}
|
||||
if (!EVP_DigestInit_ex(kctx->ctx, ossl_prov_digest_md(&kctx->digest),
|
||||
NULL))
|
||||
return 0;
|
||||
|
||||
block_len = EVP_MD_block_size(ossl_prov_digest_md(&kctx->digest));
|
||||
|
||||
/* Set default custom string if it is not already set */
|
||||
if (kctx->custom_len == 0) {
|
||||
const OSSL_PARAM params[] = {
|
||||
OSSL_PARAM_octet_string(OSSL_MAC_PARAM_CUSTOM, "", 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
(void)kmac_set_ctx_params(kctx, params);
|
||||
}
|
||||
|
||||
return bytepad(out, &out_len, kmac_string, sizeof(kmac_string),
|
||||
kctx->custom, kctx->custom_len, block_len)
|
||||
&& EVP_DigestUpdate(ctx, out, out_len)
|
||||
&& EVP_DigestUpdate(ctx, kctx->key, kctx->key_len);
|
||||
}
|
||||
|
||||
static size_t kmac_size(void *vmacctx)
|
||||
{
|
||||
struct kmac_data_st *kctx = vmacctx;
|
||||
|
||||
return kctx->out_len;
|
||||
}
|
||||
|
||||
static int kmac_update(void *vmacctx, const unsigned char *data,
|
||||
size_t datalen)
|
||||
{
|
||||
struct kmac_data_st *kctx = vmacctx;
|
||||
|
||||
return EVP_DigestUpdate(kctx->ctx, data, datalen);
|
||||
}
|
||||
|
||||
static int kmac_final(void *vmacctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
struct kmac_data_st *kctx = vmacctx;
|
||||
EVP_MD_CTX *ctx = kctx->ctx;
|
||||
int lbits, len;
|
||||
unsigned char encoded_outlen[KMAC_MAX_ENCODED_HEADER_LEN];
|
||||
int ok;
|
||||
|
||||
/* KMAC XOF mode sets the encoded length to 0 */
|
||||
lbits = (kctx->xof_mode ? 0 : (kctx->out_len * 8));
|
||||
|
||||
ok = right_encode(encoded_outlen, &len, lbits)
|
||||
&& EVP_DigestUpdate(ctx, encoded_outlen, len)
|
||||
&& EVP_DigestFinalXOF(ctx, out, kctx->out_len);
|
||||
if (ok && outl != NULL)
|
||||
*outl = kctx->out_len;
|
||||
return ok;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM *kmac_gettable_ctx_params(void)
|
||||
{
|
||||
return known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
static int kmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[])
|
||||
{
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL)
|
||||
return OSSL_PARAM_set_size_t(p, kmac_size(vmacctx));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_int(OSSL_MAC_PARAM_XOF, NULL),
|
||||
OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
|
||||
OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_MAC_PARAM_CUSTOM, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM *kmac_settable_ctx_params(void)
|
||||
{
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following params can be set any time before final():
|
||||
* - "outlen" or "size": The requested output length.
|
||||
* - "xof": If set, this indicates that right_encoded(0)
|
||||
* is part of the digested data, otherwise it
|
||||
* uses right_encoded(requested output length).
|
||||
*
|
||||
* All other params should be set before init().
|
||||
*/
|
||||
static int kmac_set_ctx_params(void *vmacctx, const OSSL_PARAM *params)
|
||||
{
|
||||
struct kmac_data_st *kctx = vmacctx;
|
||||
const OSSL_PARAM *p;
|
||||
const EVP_MD *digest = ossl_prov_digest_md(&kctx->digest);
|
||||
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_XOF)) != NULL
|
||||
&& !OSSL_PARAM_get_int(p, &kctx->xof_mode))
|
||||
return 0;
|
||||
if (((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SIZE)) != NULL)
|
||||
&& !OSSL_PARAM_get_size_t(p, &kctx->out_len))
|
||||
return 0;
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) {
|
||||
if (p->data_size < 4 || p->data_size > KMAC_MAX_KEY) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if (!kmac_bytepad_encode_key(kctx->key, &kctx->key_len,
|
||||
p->data, p->data_size,
|
||||
EVP_MD_block_size(digest)))
|
||||
return 0;
|
||||
}
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CUSTOM))
|
||||
!= NULL) {
|
||||
if (p->data_size > KMAC_MAX_CUSTOM) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CUSTOM_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if (!encode_string(kctx->custom, &kctx->custom_len,
|
||||
p->data, p->data_size))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encoding/Padding Methods.
|
||||
*/
|
||||
|
||||
/* Returns the number of bytes required to store 'bits' into a byte array */
|
||||
static unsigned int get_encode_size(size_t bits)
|
||||
{
|
||||
unsigned int cnt = 0, sz = sizeof(size_t);
|
||||
|
||||
while (bits && (cnt < sz)) {
|
||||
++cnt;
|
||||
bits >>= 8;
|
||||
}
|
||||
/* If bits is zero 1 byte is required */
|
||||
if (cnt == 0)
|
||||
cnt = 1;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an integer into bytes . The number of bytes is appended
|
||||
* to the end of the buffer. Returns an array of bytes 'out' of size
|
||||
* *out_len.
|
||||
*
|
||||
* e.g if bits = 32, out[2] = { 0x20, 0x01 }
|
||||
*
|
||||
*/
|
||||
static int right_encode(unsigned char *out, int *out_len, size_t bits)
|
||||
{
|
||||
unsigned int len = get_encode_size(bits);
|
||||
int i;
|
||||
|
||||
/* The length is constrained to a single byte: 2040/8 = 255 */
|
||||
if (len > 0xFF)
|
||||
return 0;
|
||||
|
||||
/* MSB's are at the start of the bytes array */
|
||||
for (i = len - 1; i >= 0; --i) {
|
||||
out[i] = (unsigned char)(bits & 0xFF);
|
||||
bits >>= 8;
|
||||
}
|
||||
/* Tack the length onto the end */
|
||||
out[len] = (unsigned char)len;
|
||||
|
||||
/* The Returned length includes the tacked on byte */
|
||||
*out_len = len + 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encodes a string with a left encoded length added. Note that the
|
||||
* in_len is converted to bits (*8).
|
||||
*
|
||||
* e.g- in="KMAC" gives out[6] = { 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43 }
|
||||
* len bits K M A C
|
||||
*/
|
||||
static int encode_string(unsigned char *out, int *out_len,
|
||||
const unsigned char *in, int in_len)
|
||||
{
|
||||
if (in == NULL) {
|
||||
*out_len = 0;
|
||||
} else {
|
||||
int i, bits, len;
|
||||
|
||||
bits = 8 * in_len;
|
||||
len = get_encode_size(bits);
|
||||
if (len > 0xFF)
|
||||
return 0;
|
||||
|
||||
out[0] = len;
|
||||
for (i = len; i > 0; --i) {
|
||||
out[i] = (bits & 0xFF);
|
||||
bits >>= 8;
|
||||
}
|
||||
memcpy(out + len + 1, in, in_len);
|
||||
*out_len = (1 + len + in_len);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a zero padded encoding of the inputs in1 and an optional
|
||||
* in2 (can be NULL). The padded output must be a multiple of the blocksize 'w'.
|
||||
* The value of w is in bytes (< 256).
|
||||
*
|
||||
* The returned output is:
|
||||
* zero_padded(multiple of w, (left_encode(w) || in1 [|| in2])
|
||||
*/
|
||||
static int bytepad(unsigned char *out, int *out_len,
|
||||
const unsigned char *in1, int in1_len,
|
||||
const unsigned char *in2, int in2_len, int w)
|
||||
{
|
||||
int len;
|
||||
unsigned char *p = out;
|
||||
int sz = w;
|
||||
|
||||
/* Left encoded w */
|
||||
*p++ = 1;
|
||||
*p++ = w;
|
||||
/* || in1 */
|
||||
memcpy(p, in1, in1_len);
|
||||
p += in1_len;
|
||||
/* [ || in2 ] */
|
||||
if (in2 != NULL && in2_len > 0) {
|
||||
memcpy(p, in2, in2_len);
|
||||
p += in2_len;
|
||||
}
|
||||
/* Figure out the pad size (divisible by w) */
|
||||
len = p - out;
|
||||
while (len > sz) {
|
||||
sz += w;
|
||||
}
|
||||
/* zero pad the end of the buffer */
|
||||
memset(p, 0, sz - len);
|
||||
*out_len = sz;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns out = bytepad(encode_string(in), w)
|
||||
*/
|
||||
static int kmac_bytepad_encode_key(unsigned char *out, int *out_len,
|
||||
const unsigned char *in, int in_len,
|
||||
int w)
|
||||
{
|
||||
unsigned char tmp[KMAC_MAX_KEY + KMAC_MAX_ENCODED_HEADER_LEN];
|
||||
int tmp_len;
|
||||
|
||||
if (!encode_string(tmp, &tmp_len, in, in_len))
|
||||
return 0;
|
||||
|
||||
return bytepad(out, out_len, tmp, tmp_len, NULL, 0, w);
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH kmac128_functions[] = {
|
||||
{ OSSL_FUNC_MAC_NEWCTX, (void (*)(void))kmac128_new },
|
||||
{ OSSL_FUNC_MAC_DUPCTX, (void (*)(void))kmac_dup },
|
||||
{ OSSL_FUNC_MAC_FREECTX, (void (*)(void))kmac_free },
|
||||
{ OSSL_FUNC_MAC_INIT, (void (*)(void))kmac_init },
|
||||
{ OSSL_FUNC_MAC_UPDATE, (void (*)(void))kmac_update },
|
||||
{ OSSL_FUNC_MAC_FINAL, (void (*)(void))kmac_final },
|
||||
{ OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))kmac_gettable_ctx_params },
|
||||
{ OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))kmac_get_ctx_params },
|
||||
{ OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))kmac_settable_ctx_params },
|
||||
{ OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))kmac_set_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
const OSSL_DISPATCH kmac256_functions[] = {
|
||||
{ OSSL_FUNC_MAC_NEWCTX, (void (*)(void))kmac256_new },
|
||||
{ OSSL_FUNC_MAC_DUPCTX, (void (*)(void))kmac_dup },
|
||||
{ OSSL_FUNC_MAC_FREECTX, (void (*)(void))kmac_free },
|
||||
{ OSSL_FUNC_MAC_INIT, (void (*)(void))kmac_init },
|
||||
{ OSSL_FUNC_MAC_UPDATE, (void (*)(void))kmac_update },
|
||||
{ OSSL_FUNC_MAC_FINAL, (void (*)(void))kmac_final },
|
||||
{ OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))kmac_gettable_ctx_params },
|
||||
{ OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))kmac_get_ctx_params },
|
||||
{ OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))kmac_settable_ctx_params },
|
||||
{ OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))kmac_set_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -13,43 +13,80 @@
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static const ERR_STRING_DATA PROV_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AESNI_INIT_KEY, 0), "aesni_init_key"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_BLOCK_FINAL, 0), "aes_block_final"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_BLOCK_UPDATE, 0), "aes_block_update"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_CIPHER, 0), "aes_cipher"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_CTX_GET_PARAMS, 0),
|
||||
"aes_ctx_get_params"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_CTX_SET_PARAMS, 0),
|
||||
"aes_ctx_set_params"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_DINIT, 0), "aes_dinit"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_DUPCTX, 0), "aes_dupctx"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_EINIT, 0), "aes_einit"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_INIT_KEY, 0), "aes_init_key"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_STREAM_UPDATE, 0), "aes_stream_update"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_T4_INIT_KEY, 0), "aes_t4_init_key"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_PROV_AES_KEY_GENERIC_INIT, 0),
|
||||
"PROV_AES_KEY_generic_init"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_TRAILINGDATA, 0), "trailingdata"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_UNPADBLOCK, 0), "unpadblock"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static const ERR_STRING_DATA PROV_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_AES_KEY_SETUP_FAILED),
|
||||
"aes key setup failed"},
|
||||
{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_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_GENERATE_KEY),
|
||||
"failed to generate key"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_GET_PARAMETER),
|
||||
"failed to get parameter"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SET_PARAMETER),
|
||||
"failed to set parameter"},
|
||||
{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_CUSTOM_LENGTH),
|
||||
"invalid custom length"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DATA), "invalid data"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST), "invalid digest"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_ITERATION_COUNT),
|
||||
"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_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),
|
||||
"invalid key length"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MODE), "invalid mode"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MODE_INT), "invalid mode int"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_SALT_LENGTH),
|
||||
"invalid salt length"},
|
||||
{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_KEY), "missing key"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_MESSAGE_DIGEST),
|
||||
"missing message digest"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_PASS), "missing pass"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_SALT), "missing salt"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_SECRET), "missing secret"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_SEED), "missing seed"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_SESSION_ID),
|
||||
"missing session id"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_TYPE), "missing type"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_XCGHASH), "missing xcghash"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_SUPPORTED), "not supported"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_XOF_OR_INVALID_LENGTH),
|
||||
"not xof or invalid length"},
|
||||
{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_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),
|
||||
"unable to load sha1"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_LOAD_SHA256),
|
||||
"unable to load sha256"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNSUPPORTED_CEK_ALG),
|
||||
"unsupported cek alg"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNSUPPORTED_MAC_TYPE),
|
||||
"unsupported mac type"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_VALUE_ERROR), "value error"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_WRONG_FINAL_BLOCK_LENGTH),
|
||||
"wrong final block length"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_WRONG_OUTPUT_BUFFER_SIZE),
|
||||
"wrong output buffer size"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE),
|
||||
"xts data unit is too large"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_XTS_DUPLICATED_KEYS),
|
||||
"xts duplicated keys"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
@@ -58,10 +95,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
|
||||
int ERR_load_PROV_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
if (ERR_func_error_string(PROV_str_functs[0].error) == NULL) {
|
||||
ERR_load_strings_const(PROV_str_functs);
|
||||
if (ERR_reason_error_string(PROV_str_reasons[0].error) == NULL)
|
||||
ERR_load_strings_const(PROV_str_reasons);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* 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/evp.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include "internal/provider_util.h"
|
||||
|
||||
void ossl_prov_cipher_reset(PROV_CIPHER *pc)
|
||||
{
|
||||
EVP_CIPHER_free(pc->alloc_cipher);
|
||||
pc->alloc_cipher = NULL;
|
||||
pc->cipher = NULL;
|
||||
pc->engine = NULL;
|
||||
}
|
||||
|
||||
int ossl_prov_cipher_copy(PROV_CIPHER *dst, const PROV_CIPHER *src)
|
||||
{
|
||||
if (src->alloc_cipher != NULL && !EVP_CIPHER_up_ref(src->alloc_cipher))
|
||||
return 0;
|
||||
dst->engine = src->engine;
|
||||
dst->cipher = src->cipher;
|
||||
dst->alloc_cipher = src->alloc_cipher;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int load_common(const OSSL_PARAM params[], const char **propquery,
|
||||
ENGINE **engine)
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
*propquery = NULL;
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_PROPERTIES);
|
||||
if (p != NULL) {
|
||||
if (p->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
*propquery = p->data;
|
||||
}
|
||||
|
||||
*engine = NULL;
|
||||
/* TODO legacy stuff, to be removed */
|
||||
/* Inside the FIPS module, we don't support legacy ciphers */
|
||||
#if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE)
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE);
|
||||
if (p != NULL) {
|
||||
if (p->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
ENGINE_finish(*engine);
|
||||
*engine = ENGINE_by_id(p->data);
|
||||
if (*engine == NULL)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_prov_cipher_load_from_params(PROV_CIPHER *pc,
|
||||
const OSSL_PARAM params[],
|
||||
OPENSSL_CTX *ctx)
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
const char *propquery;
|
||||
|
||||
if (!load_common(params, &propquery, &pc->engine))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_CIPHER);
|
||||
if (p == NULL)
|
||||
return 1;
|
||||
if (p->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
|
||||
EVP_CIPHER_free(pc->alloc_cipher);
|
||||
pc->cipher = pc->alloc_cipher = EVP_CIPHER_fetch(ctx, p->data, propquery);
|
||||
/* TODO legacy stuff, to be removed */
|
||||
#ifndef FIPS_MODE /* Inside the FIPS module, we don't support legacy ciphers */
|
||||
if (pc->cipher == NULL)
|
||||
pc->cipher = EVP_get_cipherbyname(p->data);
|
||||
#endif
|
||||
return pc->cipher != NULL;
|
||||
}
|
||||
|
||||
const EVP_CIPHER *ossl_prov_cipher_cipher(const PROV_CIPHER *pc)
|
||||
{
|
||||
return pc->cipher;
|
||||
}
|
||||
|
||||
ENGINE *ossl_prov_cipher_engine(const PROV_CIPHER *pc)
|
||||
{
|
||||
return pc->engine;
|
||||
}
|
||||
|
||||
void ossl_prov_digest_reset(PROV_DIGEST *pd)
|
||||
{
|
||||
EVP_MD_free(pd->alloc_md);
|
||||
pd->alloc_md = NULL;
|
||||
pd->md = NULL;
|
||||
pd->engine = NULL;
|
||||
}
|
||||
|
||||
int ossl_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src)
|
||||
{
|
||||
if (src->alloc_md != NULL && !EVP_MD_up_ref(src->alloc_md))
|
||||
return 0;
|
||||
dst->engine = src->engine;
|
||||
dst->md = src->md;
|
||||
dst->alloc_md = src->alloc_md;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_prov_digest_load_from_params(PROV_DIGEST *pd,
|
||||
const OSSL_PARAM params[],
|
||||
OPENSSL_CTX *ctx)
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
const char *propquery;
|
||||
|
||||
if (!load_common(params, &propquery, &pd->engine))
|
||||
return 0;
|
||||
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST);
|
||||
if (p == NULL)
|
||||
return 1;
|
||||
if (p->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
|
||||
EVP_MD_free(pd->alloc_md);
|
||||
pd->md = pd->alloc_md = EVP_MD_fetch(ctx, p->data, propquery);
|
||||
/* TODO legacy stuff, to be removed */
|
||||
#ifndef FIPS_MODE /* Inside the FIPS module, we don't support legacy digests */
|
||||
if (pd->md == NULL)
|
||||
pd->md = EVP_get_digestbyname(p->data);
|
||||
#endif
|
||||
return pd->md != NULL;
|
||||
}
|
||||
|
||||
const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd)
|
||||
{
|
||||
return pd->md;
|
||||
}
|
||||
|
||||
ENGINE *ossl_prov_digest_engine(const PROV_DIGEST *pd)
|
||||
{
|
||||
return pd->engine;
|
||||
}
|
||||
|
||||
int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx,
|
||||
const OSSL_PARAM params[],
|
||||
const char *macname,
|
||||
const char *ciphername,
|
||||
const char *mdname,
|
||||
OPENSSL_CTX *libctx)
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
OSSL_PARAM mac_params[5], *mp = mac_params;
|
||||
const char *properties = NULL;
|
||||
|
||||
if (macname == NULL
|
||||
&& (p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_MAC)) != NULL) {
|
||||
if (p->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
macname = p->data;
|
||||
}
|
||||
if ((p = OSSL_PARAM_locate_const(params,
|
||||
OSSL_ALG_PARAM_PROPERTIES)) != NULL) {
|
||||
if (p->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
properties = p->data;
|
||||
}
|
||||
|
||||
/* If we got a new mac name, we make a new EVP_MAC_CTX */
|
||||
if (macname != NULL) {
|
||||
EVP_MAC *mac = EVP_MAC_fetch(libctx, macname, properties);
|
||||
|
||||
EVP_MAC_CTX_free(*macctx);
|
||||
*macctx = mac == NULL ? NULL : EVP_MAC_CTX_new(mac);
|
||||
/* The context holds on to the MAC */
|
||||
EVP_MAC_free(mac);
|
||||
if (*macctx == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no MAC yet (and therefore, no MAC context), we ignore
|
||||
* all other parameters.
|
||||
*/
|
||||
if (*macctx == NULL)
|
||||
return 1;
|
||||
|
||||
if (mdname == NULL) {
|
||||
if ((p = OSSL_PARAM_locate_const(params,
|
||||
OSSL_ALG_PARAM_DIGEST)) != NULL) {
|
||||
if (p->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
mdname = p->data;
|
||||
}
|
||||
}
|
||||
if (ciphername == NULL) {
|
||||
if ((p = OSSL_PARAM_locate_const(params,
|
||||
OSSL_ALG_PARAM_CIPHER)) != NULL) {
|
||||
if (p->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
ciphername = p->data;
|
||||
}
|
||||
}
|
||||
|
||||
if (mdname != NULL)
|
||||
*mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
|
||||
(char *)mdname, 0);
|
||||
if (ciphername != NULL)
|
||||
*mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
|
||||
(char *)ciphername, 0);
|
||||
if (properties != NULL)
|
||||
*mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES,
|
||||
(char *)properties, 0);
|
||||
|
||||
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE)) != NULL) {
|
||||
if (p->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
*mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE,
|
||||
p->data, p->data_size);
|
||||
}
|
||||
#endif
|
||||
*mp = OSSL_PARAM_construct_end();
|
||||
|
||||
if (EVP_MAC_CTX_set_params(*macctx, mac_params))
|
||||
return 1;
|
||||
|
||||
EVP_MAC_CTX_free(*macctx);
|
||||
*macctx = NULL;
|
||||
return 0;
|
||||
}
|
||||
@@ -16,6 +16,6 @@
|
||||
*/
|
||||
const char *ossl_prov_util_nid_to_name(int nid)
|
||||
{
|
||||
return OBJ_nid2sn(nid);
|
||||
return OBJ_nid2sn(nid);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
LIBS=../../../libcrypto
|
||||
IF[{- !$disabled{dsa} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
dsa.c
|
||||
ENDIF
|
||||
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* 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/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/params.h>
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static OSSL_OP_signature_newctx_fn dsa_newctx;
|
||||
static OSSL_OP_signature_sign_init_fn dsa_signature_init;
|
||||
static OSSL_OP_signature_verify_init_fn dsa_signature_init;
|
||||
static OSSL_OP_signature_sign_fn dsa_sign;
|
||||
static OSSL_OP_signature_freectx_fn dsa_freectx;
|
||||
static OSSL_OP_signature_dupctx_fn dsa_dupctx;
|
||||
static OSSL_OP_signature_get_ctx_params_fn dsa_get_ctx_params;
|
||||
static OSSL_OP_signature_gettable_ctx_params_fn dsa_gettable_ctx_params;
|
||||
static OSSL_OP_signature_set_ctx_params_fn dsa_set_ctx_params;
|
||||
static OSSL_OP_signature_settable_ctx_params_fn dsa_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 DSA structures, so
|
||||
* we use that here too.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
DSA *dsa;
|
||||
size_t mdsize;
|
||||
/* Should be big enough */
|
||||
char mdname[80];
|
||||
} PROV_DSA_CTX;
|
||||
|
||||
static void *dsa_newctx(void *provctx)
|
||||
{
|
||||
return OPENSSL_zalloc(sizeof(PROV_DSA_CTX));
|
||||
}
|
||||
|
||||
static int dsa_signature_init(void *vpdsactx, void *vdsa)
|
||||
{
|
||||
PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
|
||||
|
||||
if (pdsactx == NULL || vdsa == NULL || !DSA_up_ref(vdsa))
|
||||
return 0;
|
||||
DSA_free(pdsactx->dsa);
|
||||
pdsactx->dsa = vdsa;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen,
|
||||
size_t sigsize, const unsigned char *tbs, size_t tbslen)
|
||||
{
|
||||
PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
|
||||
int ret;
|
||||
unsigned int sltmp;
|
||||
size_t dsasize = DSA_size(pdsactx->dsa);
|
||||
|
||||
if (sig == NULL) {
|
||||
*siglen = dsasize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sigsize < (size_t)dsasize)
|
||||
return 0;
|
||||
|
||||
if (pdsactx->mdsize != 0 && tbslen != pdsactx->mdsize)
|
||||
return 0;
|
||||
|
||||
ret = DSA_sign(0, tbs, tbslen, sig, &sltmp, pdsactx->dsa);
|
||||
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
|
||||
*siglen = sltmp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dsa_verify(void *vpdsactx, const unsigned char *sig, size_t siglen,
|
||||
const unsigned char *tbs, size_t tbslen)
|
||||
{
|
||||
PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
|
||||
|
||||
if (pdsactx->mdsize != 0 && tbslen != pdsactx->mdsize)
|
||||
return 0;
|
||||
|
||||
return DSA_verify(0, tbs, tbslen, sig, siglen, pdsactx->dsa);
|
||||
}
|
||||
|
||||
|
||||
static void dsa_freectx(void *vpdsactx)
|
||||
{
|
||||
PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
|
||||
|
||||
DSA_free(pdsactx->dsa);
|
||||
|
||||
OPENSSL_free(pdsactx);
|
||||
}
|
||||
|
||||
static void *dsa_dupctx(void *vpdsactx)
|
||||
{
|
||||
PROV_DSA_CTX *srcctx = (PROV_DSA_CTX *)vpdsactx;
|
||||
PROV_DSA_CTX *dstctx;
|
||||
|
||||
dstctx = OPENSSL_zalloc(sizeof(*srcctx));
|
||||
if (dstctx == NULL)
|
||||
return NULL;
|
||||
|
||||
*dstctx = *srcctx;
|
||||
if (dstctx->dsa != NULL && !DSA_up_ref(dstctx->dsa)) {
|
||||
OPENSSL_free(dstctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dstctx;
|
||||
}
|
||||
|
||||
static int dsa_get_ctx_params(void *vpdsactx, OSSL_PARAM *params)
|
||||
{
|
||||
PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if (pdsactx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
|
||||
if (p != NULL && !OSSL_PARAM_set_size_t(p, pdsactx->mdsize))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
|
||||
if (p != NULL && !OSSL_PARAM_set_utf8_string(p, pdsactx->mdname))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static const OSSL_PARAM *dsa_gettable_ctx_params(void)
|
||||
{
|
||||
return known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
static int dsa_set_ctx_params(void *vpdsactx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
|
||||
const OSSL_PARAM *p;
|
||||
char *mdname;
|
||||
|
||||
if (pdsactx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
|
||||
if (p != NULL && !OSSL_PARAM_get_size_t(p, &pdsactx->mdsize))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We never actually use the mdname, but we do support getting it later.
|
||||
* This can be useful for applications that want to know the MD that they
|
||||
* previously set.
|
||||
*/
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
|
||||
mdname = pdsactx->mdname;
|
||||
if (p != NULL
|
||||
&& !OSSL_PARAM_get_utf8_string(p, &mdname, sizeof(pdsactx->mdname)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static const OSSL_PARAM *dsa_settable_ctx_params(void)
|
||||
{
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH dsa_signature_functions[] = {
|
||||
{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))dsa_newctx },
|
||||
{ OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))dsa_signature_init },
|
||||
{ OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))dsa_sign },
|
||||
{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))dsa_signature_init },
|
||||
{ OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))dsa_verify },
|
||||
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))dsa_freectx },
|
||||
{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))dsa_dupctx },
|
||||
{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))dsa_get_ctx_params },
|
||||
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))dsa_gettable_ctx_params },
|
||||
{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))dsa_set_ctx_params },
|
||||
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))dsa_settable_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -1,4 +1,6 @@
|
||||
SUBDIRS=digests
|
||||
SUBDIRS=digests macs ciphers
|
||||
SUBDIRS=digests kdfs macs ciphers
|
||||
LIBS=../../libcrypto
|
||||
SOURCE[../../libcrypto]=\
|
||||
defltprov.c
|
||||
INCLUDE[../../libcrypto]=include
|
||||
@@ -0,0 +1,52 @@
|
||||
LIBS=../../../libcrypto
|
||||
|
||||
IF[{- !$disabled{des} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
cipher_tdes_default.c cipher_tdes_default_hw.c \
|
||||
cipher_tdes_wrap.c cipher_tdes_wrap_hw.c \
|
||||
cipher_desx.c cipher_desx_hw.c
|
||||
ENDIF
|
||||
|
||||
IF[{- !$disabled{aria} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
cipher_aria.c cipher_aria_hw.c \
|
||||
cipher_aria_gcm.c cipher_aria_gcm_hw.c \
|
||||
cipher_aria_ccm.c cipher_aria_ccm_hw.c
|
||||
ENDIF
|
||||
|
||||
IF[{- !$disabled{camellia} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
cipher_camellia.c cipher_camellia_hw.c
|
||||
ENDIF
|
||||
|
||||
IF[{- !$disabled{bf} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
cipher_blowfish.c cipher_blowfish_hw.c
|
||||
ENDIF
|
||||
|
||||
IF[{- !$disabled{idea} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
cipher_idea.c cipher_idea_hw.c
|
||||
ENDIF
|
||||
|
||||
IF[{- !$disabled{cast} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
cipher_cast5.c cipher_cast5_hw.c
|
||||
ENDIF
|
||||
|
||||
IF[{- !$disabled{seed} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
cipher_seed.c cipher_seed_hw.c
|
||||
ENDIF
|
||||
|
||||
IF[{- !$disabled{sm4} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
cipher_sm4.c cipher_sm4_hw.c
|
||||
ENDIF
|
||||
|
||||
IF[{- !$disabled{ocb} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
cipher_aes_ocb.c cipher_aes_ocb_hw.c
|
||||
ENDIF
|
||||
|
||||
INCLUDE[../../../libcrypto]=. ../../../crypto
|
||||
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
* 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 "cipher_aes_ocb.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
#include "internal/ciphers/cipher_aead.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
#define AES_OCB_FLAGS AEAD_FLAGS
|
||||
|
||||
#define OCB_DEFAULT_TAG_LEN 16
|
||||
#define OCB_DEFAULT_IV_LEN 12
|
||||
#define OCB_MIN_IV_LEN 1
|
||||
#define OCB_MAX_IV_LEN 15
|
||||
|
||||
PROV_CIPHER_FUNC(int, ocb_cipher, (PROV_AES_OCB_CTX *ctx,
|
||||
const unsigned char *in, unsigned char *out,
|
||||
size_t nextblock));
|
||||
/* forward declarations */
|
||||
static OSSL_OP_cipher_encrypt_init_fn aes_ocb_einit;
|
||||
static OSSL_OP_cipher_decrypt_init_fn aes_ocb_dinit;
|
||||
static OSSL_OP_cipher_update_fn aes_ocb_block_update;
|
||||
static OSSL_OP_cipher_final_fn aes_ocb_block_final;
|
||||
static OSSL_OP_cipher_cipher_fn aes_ocb_cipher;
|
||||
static OSSL_OP_cipher_freectx_fn aes_ocb_freectx;
|
||||
static OSSL_OP_cipher_dupctx_fn aes_ocb_dupctx;
|
||||
static OSSL_OP_cipher_get_ctx_params_fn aes_ocb_get_ctx_params;
|
||||
static OSSL_OP_cipher_set_ctx_params_fn aes_ocb_set_ctx_params;
|
||||
|
||||
/*
|
||||
* The following methods could be moved into PROV_AES_OCB_HW if
|
||||
* multiple hardware implementations are ever needed.
|
||||
*/
|
||||
static ossl_inline int aes_generic_ocb_setiv(PROV_AES_OCB_CTX *ctx,
|
||||
const unsigned char *iv,
|
||||
size_t ivlen, size_t taglen)
|
||||
{
|
||||
return (CRYPTO_ocb128_setiv(&ctx->ocb, iv, ivlen, taglen) == 1);
|
||||
}
|
||||
|
||||
static ossl_inline int aes_generic_ocb_setaad(PROV_AES_OCB_CTX *ctx,
|
||||
const unsigned char *aad,
|
||||
size_t alen)
|
||||
{
|
||||
return CRYPTO_ocb128_aad(&ctx->ocb, aad, alen) == 1;
|
||||
}
|
||||
|
||||
static ossl_inline int aes_generic_ocb_gettag(PROV_AES_OCB_CTX *ctx,
|
||||
unsigned char *tag, size_t tlen)
|
||||
{
|
||||
return CRYPTO_ocb128_tag(&ctx->ocb, tag, tlen) > 0;
|
||||
}
|
||||
|
||||
static ossl_inline int aes_generic_ocb_final(PROV_AES_OCB_CTX *ctx)
|
||||
{
|
||||
return (CRYPTO_ocb128_finish(&ctx->ocb, ctx->tag, ctx->taglen) == 0);
|
||||
}
|
||||
|
||||
static ossl_inline void aes_generic_ocb_cleanup(PROV_AES_OCB_CTX *ctx)
|
||||
{
|
||||
CRYPTO_ocb128_cleanup(&ctx->ocb);
|
||||
}
|
||||
|
||||
static ossl_inline int aes_generic_ocb_cipher(PROV_AES_OCB_CTX *ctx,
|
||||
const unsigned char *in,
|
||||
unsigned char *out, size_t len)
|
||||
{
|
||||
if (ctx->base.enc) {
|
||||
if (!CRYPTO_ocb128_encrypt(&ctx->ocb, in, out, len))
|
||||
return 0;
|
||||
} else {
|
||||
if (!CRYPTO_ocb128_decrypt(&ctx->ocb, in, out, len))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/*-
|
||||
* Provider dispatch functions
|
||||
*/
|
||||
static int aes_ocb_init(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen, int enc)
|
||||
{
|
||||
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
|
||||
|
||||
ctx->base.enc = enc;
|
||||
|
||||
if (iv != NULL) {
|
||||
if (ivlen != ctx->base.ivlen) {
|
||||
/* IV len must be 1 to 15 */
|
||||
if (ivlen < OCB_MIN_IV_LEN || ivlen > OCB_MAX_IV_LEN) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
ctx->base.ivlen = ivlen;
|
||||
}
|
||||
memcpy(ctx->base.iv, iv, ivlen);
|
||||
ctx->iv_state = IV_STATE_BUFFERED;
|
||||
}
|
||||
if (key != NULL) {
|
||||
if (keylen != ctx->base.keylen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
return ctx->base.hw->init(&ctx->base, key, keylen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_ocb_einit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return aes_ocb_init(vctx, key, keylen, iv, ivlen, 1);
|
||||
}
|
||||
|
||||
static int aes_ocb_dinit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
return aes_ocb_init(vctx, key, keylen, iv, ivlen, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Because of the way OCB works, both the AAD and data are buffered in the
|
||||
* same way. Only the last block can be a partial block.
|
||||
*/
|
||||
static int aes_ocb_block_update_internal(PROV_AES_OCB_CTX *ctx,
|
||||
unsigned char *buf, size_t *bufsz,
|
||||
unsigned char *out, size_t *outl,
|
||||
size_t outsize, const unsigned char *in,
|
||||
size_t inl, OSSL_ocb_cipher_fn ciph)
|
||||
{
|
||||
size_t nextblocks = fillblock(buf, bufsz, AES_BLOCK_SIZE, &in, &inl);
|
||||
size_t outlint = 0;
|
||||
|
||||
if (*bufsz == AES_BLOCK_SIZE) {
|
||||
if (outsize < AES_BLOCK_SIZE) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (!ciph(ctx, buf, out, AES_BLOCK_SIZE)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
*bufsz = 0;
|
||||
outlint = AES_BLOCK_SIZE;
|
||||
out += AES_BLOCK_SIZE;
|
||||
}
|
||||
if (nextblocks > 0) {
|
||||
outlint += nextblocks;
|
||||
if (outsize < outlint) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (!ciph(ctx, in, out, nextblocks)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
in += nextblocks;
|
||||
inl -= nextblocks;
|
||||
}
|
||||
if (!trailingdata(buf, bufsz, AES_BLOCK_SIZE, &in, &inl)) {
|
||||
/* PROVerr already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
*outl = outlint;
|
||||
return inl == 0;
|
||||
}
|
||||
|
||||
/* A wrapper function that has the same signature as cipher */
|
||||
static int cipher_updateaad(PROV_AES_OCB_CTX *ctx, const unsigned char *in,
|
||||
unsigned char *out, size_t len)
|
||||
{
|
||||
return aes_generic_ocb_setaad(ctx, in, len);
|
||||
}
|
||||
|
||||
static int update_iv(PROV_AES_OCB_CTX *ctx)
|
||||
{
|
||||
if (ctx->iv_state == IV_STATE_FINISHED
|
||||
|| ctx->iv_state == IV_STATE_UNINITIALISED)
|
||||
return 0;
|
||||
if (ctx->iv_state == IV_STATE_BUFFERED) {
|
||||
if (!aes_generic_ocb_setiv(ctx, ctx->base.iv, ctx->base.ivlen,
|
||||
ctx->taglen))
|
||||
return 0;
|
||||
ctx->iv_state = IV_STATE_COPIED;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_ocb_block_update(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize, const unsigned char *in,
|
||||
size_t inl)
|
||||
{
|
||||
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
|
||||
unsigned char *buf;
|
||||
size_t *buflen;
|
||||
OSSL_ocb_cipher_fn fn;
|
||||
|
||||
if (!ctx->key_set || !update_iv(ctx))
|
||||
return 0;
|
||||
|
||||
/* Are we dealing with AAD or normal data here? */
|
||||
if (out == NULL) {
|
||||
buf = ctx->aad_buf;
|
||||
buflen = &ctx->aad_buf_len;
|
||||
fn = cipher_updateaad;
|
||||
} else {
|
||||
buf = ctx->data_buf;
|
||||
buflen = &ctx->data_buf_len;
|
||||
fn = aes_generic_ocb_cipher;
|
||||
}
|
||||
return aes_ocb_block_update_internal(ctx, buf, buflen, out, outl, outsize,
|
||||
in, inl, fn);
|
||||
}
|
||||
|
||||
static int aes_ocb_block_final(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
|
||||
|
||||
/* If no block_update has run then the iv still needs to be set */
|
||||
if (!ctx->key_set || !update_iv(ctx))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Empty the buffer of any partial block that we might have been provided,
|
||||
* both for data and AAD
|
||||
*/
|
||||
*outl = 0;
|
||||
if (ctx->data_buf_len > 0) {
|
||||
if (!aes_generic_ocb_cipher(ctx, ctx->data_buf, out, ctx->data_buf_len))
|
||||
return 0;
|
||||
*outl = ctx->data_buf_len;
|
||||
ctx->data_buf_len = 0;
|
||||
}
|
||||
if (ctx->aad_buf_len > 0) {
|
||||
if (!aes_generic_ocb_setaad(ctx, ctx->aad_buf, ctx->aad_buf_len))
|
||||
return 0;
|
||||
ctx->aad_buf_len = 0;
|
||||
}
|
||||
if (ctx->base.enc) {
|
||||
/* If encrypting then just get the tag */
|
||||
if (!aes_generic_ocb_gettag(ctx, ctx->tag, ctx->taglen))
|
||||
return 0;
|
||||
} else {
|
||||
/* If decrypting then verify */
|
||||
if (ctx->taglen == 0)
|
||||
return 0;
|
||||
if (!aes_generic_ocb_final(ctx))
|
||||
return 0;
|
||||
}
|
||||
/* Don't reuse the IV */
|
||||
ctx->iv_state = IV_STATE_FINISHED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *aes_ocb_newctx(void *provctx, size_t kbits, size_t blkbits,
|
||||
size_t ivbits, unsigned int mode, uint64_t flags)
|
||||
{
|
||||
PROV_AES_OCB_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx != NULL) {
|
||||
cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
|
||||
PROV_CIPHER_HW_aes_ocb(kbits), NULL);
|
||||
ctx->taglen = OCB_DEFAULT_TAG_LEN;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void aes_ocb_freectx(void *vctx)
|
||||
{
|
||||
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
|
||||
|
||||
aes_generic_ocb_cleanup(ctx);
|
||||
OPENSSL_cleanse(ctx->base.iv, sizeof(ctx->base.iv));
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void *aes_ocb_dupctx(void *vctx)
|
||||
{
|
||||
PROV_AES_OCB_CTX *in = (PROV_AES_OCB_CTX *)vctx;
|
||||
PROV_AES_OCB_CTX *ret = OPENSSL_malloc(sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
*ret = *in;
|
||||
if (!aes_generic_ocb_copy_ctx(ret, in))
|
||||
OPENSSL_free(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aes_ocb_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
|
||||
const OSSL_PARAM *p;
|
||||
size_t sz;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
|
||||
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 (p->data == NULL) {
|
||||
/* Tag len must be 0 to 16 */
|
||||
if (p->data_size > OCB_MAX_TAG_LEN)
|
||||
return 0;
|
||||
ctx->taglen = p->data_size;
|
||||
} else {
|
||||
if (p->data_size != ctx->taglen || ctx->base.enc)
|
||||
return 0;
|
||||
memcpy(ctx->tag, p->data, p->data_size);
|
||||
}
|
||||
}
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_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;
|
||||
}
|
||||
/* IV len must be 1 to 15 */
|
||||
if (sz < OCB_MIN_IV_LEN || sz > OCB_MAX_IV_LEN)
|
||||
return 0;
|
||||
ctx->base.ivlen = sz;
|
||||
}
|
||||
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 1;
|
||||
}
|
||||
|
||||
static int aes_ocb_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
||||
{
|
||||
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
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_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_AEAD_TAGLEN);
|
||||
if (p != NULL) {
|
||||
if (!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_IV);
|
||||
if (p != NULL) {
|
||||
if (ctx->base.ivlen != p->data_size) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if (!OSSL_PARAM_set_octet_string(p, ctx->base.iv, 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_TAG);
|
||||
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 (!ctx->base.enc || p->data_size != ctx->taglen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAGLEN);
|
||||
return 0;
|
||||
}
|
||||
memcpy(p->data, ctx->tag, ctx->taglen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM cipher_ocb_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_TAGLEN, NULL),
|
||||
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM *cipher_ocb_gettable_ctx_params(void)
|
||||
{
|
||||
return cipher_ocb_known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM cipher_ocb_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_END
|
||||
};
|
||||
static const OSSL_PARAM *cipher_ocb_settable_ctx_params(void)
|
||||
{
|
||||
return cipher_ocb_known_settable_ctx_params;
|
||||
}
|
||||
|
||||
static int aes_ocb_cipher(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize, const unsigned char *in, size_t inl)
|
||||
{
|
||||
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
|
||||
|
||||
if (outsize < inl) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!aes_generic_ocb_cipher(ctx, in, out, inl)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*outl = inl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IMPLEMENT_cipher(mode, UCMODE, flags, kbits, blkbits, ivbits) \
|
||||
static OSSL_OP_cipher_get_params_fn aes_##kbits##_##mode##_get_params; \
|
||||
static int aes_##kbits##_##mode##_get_params(OSSL_PARAM params[]) \
|
||||
{ \
|
||||
return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
|
||||
flags, kbits, blkbits, ivbits); \
|
||||
} \
|
||||
static OSSL_OP_cipher_newctx_fn aes_##kbits##_##mode##_newctx; \
|
||||
static void *aes_##kbits##_##mode##_newctx(void *provctx) \
|
||||
{ \
|
||||
return aes_##mode##_newctx(provctx, kbits, blkbits, ivbits, \
|
||||
EVP_CIPH_##UCMODE##_MODE, flags); \
|
||||
} \
|
||||
const OSSL_DISPATCH aes##kbits##mode##_functions[] = { \
|
||||
{ OSSL_FUNC_CIPHER_NEWCTX, \
|
||||
(void (*)(void))aes_##kbits##_##mode##_newctx }, \
|
||||
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit }, \
|
||||
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_##mode##_dinit }, \
|
||||
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_block_update }, \
|
||||
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_block_final }, \
|
||||
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_ocb_cipher }, \
|
||||
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx }, \
|
||||
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_##mode##_dupctx }, \
|
||||
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
|
||||
(void (*)(void))aes_##kbits##_##mode##_get_params }, \
|
||||
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
|
||||
(void (*)(void))aes_##mode##_get_ctx_params }, \
|
||||
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
|
||||
(void (*)(void))aes_##mode##_set_ctx_params }, \
|
||||
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
|
||||
(void (*)(void))cipher_generic_gettable_params }, \
|
||||
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
|
||||
(void (*)(void))cipher_ocb_gettable_ctx_params }, \
|
||||
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
|
||||
(void (*)(void))cipher_ocb_settable_ctx_params }, \
|
||||
{ 0, NULL } \
|
||||
}
|
||||
|
||||
IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 256, 128, OCB_DEFAULT_IV_LEN * 8);
|
||||
IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 192, 128, OCB_DEFAULT_IV_LEN * 8);
|
||||
IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 128, 128, OCB_DEFAULT_IV_LEN * 8);
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 "internal/ciphers/ciphercommon.h"
|
||||
|
||||
#define OCB_MAX_TAG_LEN AES_BLOCK_SIZE
|
||||
#define OCB_MAX_DATA_LEN AES_BLOCK_SIZE
|
||||
#define OCB_MAX_AAD_LEN AES_BLOCK_SIZE
|
||||
|
||||
typedef struct prov_aes_ocb_ctx_st {
|
||||
PROV_CIPHER_CTX base; /* Must be first */
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
AES_KEY ks;
|
||||
} ksenc; /* AES key schedule to use for encryption/aad */
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
AES_KEY ks;
|
||||
} ksdec; /* AES key schedule to use for decryption */
|
||||
OCB128_CONTEXT ocb;
|
||||
unsigned int iv_state; /* set to one of IV_STATE_XXX */
|
||||
unsigned int key_set : 1;
|
||||
size_t taglen;
|
||||
size_t data_buf_len;
|
||||
size_t aad_buf_len;
|
||||
unsigned char tag[OCB_MAX_TAG_LEN];
|
||||
unsigned char data_buf[OCB_MAX_DATA_LEN]; /* Store partial data blocks */
|
||||
unsigned char aad_buf[OCB_MAX_AAD_LEN]; /* Store partial AAD blocks */
|
||||
} PROV_AES_OCB_CTX;
|
||||
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_ocb(size_t keybits);
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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 "cipher_aes_ocb.h"
|
||||
|
||||
#define OCB_SET_KEY_FN(fn_set_enc_key, fn_set_dec_key, \
|
||||
fn_block_enc, fn_block_dec, \
|
||||
fn_stream_enc, fn_stream_dec) \
|
||||
fn_set_enc_key(key, keylen * 8, &ctx->ksenc.ks); \
|
||||
fn_set_dec_key(key, keylen * 8, &ctx->ksdec.ks); \
|
||||
if (!CRYPTO_ocb128_init(&ctx->ocb, &ctx->ksenc.ks, &ctx->ksdec.ks, \
|
||||
(block128_f)fn_block_enc, (block128_f)fn_block_dec, \
|
||||
ctx->base.enc ? (ocb128_f)fn_stream_enc : \
|
||||
(ocb128_f)fn_stream_dec)) \
|
||||
return 0; \
|
||||
ctx->key_set = 1
|
||||
|
||||
|
||||
static int cipher_hw_aes_ocb_generic_initkey(PROV_CIPHER_CTX *vctx,
|
||||
const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
|
||||
|
||||
/*
|
||||
* We set both the encrypt and decrypt key here because decrypt
|
||||
* needs both. (i.e- AAD uses encrypt).
|
||||
*/
|
||||
# ifdef HWAES_CAPABLE
|
||||
if (HWAES_CAPABLE) {
|
||||
OCB_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_set_decrypt_key,
|
||||
HWAES_encrypt, HWAES_decrypt,
|
||||
HWAES_ocb_encrypt, HWAES_ocb_decrypt);
|
||||
}
|
||||
# endif
|
||||
# ifdef VPAES_CAPABLE
|
||||
if (VPAES_CAPABLE) {
|
||||
OCB_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_set_decrypt_key,
|
||||
vpaes_encrypt, vpaes_decrypt, NULL, NULL);
|
||||
} else
|
||||
# endif
|
||||
{
|
||||
OCB_SET_KEY_FN(AES_set_encrypt_key, AES_set_decrypt_key,
|
||||
AES_encrypt, AES_decrypt, NULL, NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
# if defined(AESNI_CAPABLE)
|
||||
|
||||
static int cipher_hw_aes_ocb_aesni_initkey(PROV_CIPHER_CTX *vctx,
|
||||
const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
|
||||
|
||||
OCB_SET_KEY_FN(aesni_set_encrypt_key, aesni_set_decrypt_key,
|
||||
aesni_encrypt, aesni_decrypt,
|
||||
aesni_ocb_encrypt, aesni_ocb_decrypt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define PROV_CIPHER_HW_declare() \
|
||||
static const PROV_CIPHER_HW aesni_ocb = { \
|
||||
cipher_hw_aes_ocb_aesni_initkey, \
|
||||
NULL \
|
||||
};
|
||||
# define PROV_CIPHER_HW_select() \
|
||||
if (AESNI_CAPABLE) \
|
||||
return &aesni_ocb;
|
||||
|
||||
#elif defined(SPARC_AES_CAPABLE)
|
||||
|
||||
static int cipher_hw_aes_ocb_t4_initkey(PROV_CIPHER_CTX *vctx,
|
||||
const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
|
||||
|
||||
OCB_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_set_decrypt_key,
|
||||
aes_t4_encrypt, aes_t4_decrypt, NULL, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define PROV_CIPHER_HW_declare() \
|
||||
static const PROV_CIPHER_HW aes_t4_ocb = { \
|
||||
cipher_hw_aes_ocb_t4_initkey, \
|
||||
NULL \
|
||||
};
|
||||
# define PROV_CIPHER_HW_select() \
|
||||
if (SPARC_AES_CAPABLE) \
|
||||
return &aes_t4_ocb;
|
||||
#else
|
||||
# define PROV_CIPHER_HW_declare()
|
||||
# define PROV_CIPHER_HW_select()
|
||||
# endif
|
||||
|
||||
static const PROV_CIPHER_HW aes_generic_ocb = {
|
||||
cipher_hw_aes_ocb_generic_initkey,
|
||||
NULL
|
||||
};
|
||||
PROV_CIPHER_HW_declare()
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_ocb(size_t keybits)
|
||||
{
|
||||
PROV_CIPHER_HW_select()
|
||||
return &aes_generic_ocb;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 ARIA cipher modes ecb, cbc, ofb, cfb, ctr */
|
||||
|
||||
#include "cipher_aria.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static OSSL_OP_cipher_freectx_fn aria_freectx;
|
||||
static OSSL_OP_cipher_dupctx_fn aria_dupctx;
|
||||
|
||||
static void aria_freectx(void *vctx)
|
||||
{
|
||||
PROV_ARIA_CTX *ctx = (PROV_ARIA_CTX *)vctx;
|
||||
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void *aria_dupctx(void *ctx)
|
||||
{
|
||||
PROV_ARIA_CTX *in = (PROV_ARIA_CTX *)ctx;
|
||||
PROV_ARIA_CTX *ret = OPENSSL_malloc(sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
*ret = *in;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* aria256ecb_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, ecb, ECB, 0, 256, 128, 0, block)
|
||||
/* aria192ecb_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, ecb, ECB, 0, 192, 128, 0, block)
|
||||
/* aria128ecb_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, ecb, ECB, 0, 128, 128, 0, block)
|
||||
/* aria256cbc_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, cbc, CBC, 0, 256, 128, 128, block)
|
||||
/* aria192cbc_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, cbc, CBC, 0, 192, 128, 128, block)
|
||||
/* aria128cbc_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, cbc, CBC, 0, 128, 128, 128, block)
|
||||
/* aria256ofb_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, ofb, OFB, 0, 256, 8, 128, stream)
|
||||
/* aria192ofb_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, ofb, OFB, 0, 192, 8, 128, stream)
|
||||
/* aria128ofb_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, ofb, OFB, 0, 128, 8, 128, stream)
|
||||
/* aria256cfb_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, cfb, CFB, 0, 256, 8, 128, stream)
|
||||
/* aria192cfb_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, cfb, CFB, 0, 192, 8, 128, stream)
|
||||
/* aria128cfb_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, cfb, CFB, 0, 128, 8, 128, stream)
|
||||
/* aria256cfb1_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, cfb1, CFB, 0, 256, 8, 128, stream)
|
||||
/* aria192cfb1_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, cfb1, CFB, 0, 192, 8, 128, stream)
|
||||
/* aria128cfb1_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, cfb1, CFB, 0, 128, 8, 128, stream)
|
||||
/* aria256cfb8_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, cfb8, CFB, 0, 256, 8, 128, stream)
|
||||
/* aria192cfb8_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, cfb8, CFB, 0, 192, 8, 128, stream)
|
||||
/* aria128cfb8_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, cfb8, CFB, 0, 128, 8, 128, stream)
|
||||
/* aria256ctr_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, ctr, CTR, 0, 256, 8, 128, stream)
|
||||
/* aria192ctr_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, ctr, CTR, 0, 192, 8, 128, stream)
|
||||
/* aria128ctr_functions */
|
||||
IMPLEMENT_generic_cipher(aria, ARIA, ctr, CTR, 0, 128, 8, 128, stream)
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 "internal/aria.h"
|
||||
#include "internal/ciphers/ciphercommon.h"
|
||||
|
||||
typedef struct prov_aria_ctx_st {
|
||||
PROV_CIPHER_CTX base; /* Must be first */
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
ARIA_KEY ks;
|
||||
} ks;
|
||||
} PROV_ARIA_CTX;
|
||||
|
||||
|
||||
# define PROV_CIPHER_HW_aria_ofb PROV_CIPHER_HW_aria_ofb128
|
||||
# define PROV_CIPHER_HW_aria_cfb PROV_CIPHER_HW_aria_cfb128
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_ecb(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_cbc(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_ofb128(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_cfb128(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_cfb1(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_cfb8(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_ctr(size_t keybits);
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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 ARIA CCM mode */
|
||||
|
||||
#include "cipher_aria_ccm.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static OSSL_OP_cipher_freectx_fn aria_ccm_freectx;
|
||||
|
||||
static void *aria_ccm_newctx(void *provctx, size_t keybits)
|
||||
{
|
||||
PROV_ARIA_CCM_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx != NULL)
|
||||
ccm_initctx(&ctx->base, keybits, PROV_ARIA_HW_ccm(keybits));
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void aria_ccm_freectx(void *vctx)
|
||||
{
|
||||
PROV_ARIA_CCM_CTX *ctx = (PROV_ARIA_CCM_CTX *)vctx;
|
||||
|
||||
ccm_finalctx((PROV_CCM_CTX *)ctx);
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
/* aria128ccm functions */
|
||||
IMPLEMENT_aead_cipher(aria, ccm, CCM, AEAD_FLAGS, 128, 8, 96);
|
||||
/* aria192ccm functions */
|
||||
IMPLEMENT_aead_cipher(aria, ccm, CCM, AEAD_FLAGS, 192, 8, 96);
|
||||
/* aria256ccm functions */
|
||||
IMPLEMENT_aead_cipher(aria, ccm, CCM, AEAD_FLAGS, 256, 8, 96);
|
||||
|
||||
@@ -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 "internal/aria.h"
|
||||
#include "internal/ciphers/ciphercommon.h"
|
||||
#include "internal/ciphers/cipher_ccm.h"
|
||||
|
||||
typedef struct prov_aria_ccm_ctx_st {
|
||||
PROV_CCM_CTX base; /* Must be first */
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
ARIA_KEY ks;
|
||||
} ks; /* ARIA key schedule to use */
|
||||
} PROV_ARIA_CCM_CTX;
|
||||
|
||||
const PROV_CCM_HW *PROV_ARIA_HW_ccm(size_t keylen);
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Generic support for ARIA CCM.
|
||||
*/
|
||||
|
||||
#include "cipher_aria_ccm.h"
|
||||
|
||||
static int ccm_aria_initkey(PROV_CCM_CTX *ctx,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
PROV_ARIA_CCM_CTX *actx = (PROV_ARIA_CCM_CTX *)ctx;
|
||||
|
||||
aria_set_encrypt_key(key, keylen * 8, &actx->ks.ks);
|
||||
CRYPTO_ccm128_init(&ctx->ccm_ctx, ctx->m, ctx->l, &actx->ks.ks,
|
||||
(block128_f)aria_encrypt);
|
||||
ctx->str = NULL;
|
||||
ctx->key_set = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const PROV_CCM_HW ccm_aria = {
|
||||
ccm_aria_initkey,
|
||||
ccm_generic_setiv,
|
||||
ccm_generic_setaad,
|
||||
ccm_generic_auth_encrypt,
|
||||
ccm_generic_auth_decrypt,
|
||||
ccm_generic_gettag
|
||||
};
|
||||
const PROV_CCM_HW *PROV_ARIA_HW_ccm(size_t keybits)
|
||||
{
|
||||
return &ccm_aria;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 ARIA GCM mode */
|
||||
|
||||
#include "cipher_aria_gcm.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static void *aria_gcm_newctx(void *provctx, size_t keybits)
|
||||
{
|
||||
PROV_ARIA_GCM_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx != NULL)
|
||||
gcm_initctx(provctx, &ctx->base, keybits, PROV_ARIA_HW_gcm(keybits), 4);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static OSSL_OP_cipher_freectx_fn aria_gcm_freectx;
|
||||
static void aria_gcm_freectx(void *vctx)
|
||||
{
|
||||
PROV_ARIA_GCM_CTX *ctx = (PROV_ARIA_GCM_CTX *)vctx;
|
||||
|
||||
gcm_deinitctx((PROV_GCM_CTX *)ctx);
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
/* aria128gcm_functions */
|
||||
IMPLEMENT_aead_cipher(aria, gcm, GCM, AEAD_FLAGS, 128, 8, 96);
|
||||
/* aria192gcm_functions */
|
||||
IMPLEMENT_aead_cipher(aria, gcm, GCM, AEAD_FLAGS, 192, 8, 96);
|
||||
/* aria256gcm_functions */
|
||||
IMPLEMENT_aead_cipher(aria, gcm, GCM, AEAD_FLAGS, 256, 8, 96);
|
||||
|
||||
@@ -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 "internal/aria.h"
|
||||
#include "internal/ciphers/ciphercommon.h"
|
||||
#include "internal/ciphers/cipher_gcm.h"
|
||||
|
||||
typedef struct prov_aria_gcm_ctx_st {
|
||||
PROV_GCM_CTX base; /* must be first entry in struct */
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
ARIA_KEY ks;
|
||||
} ks;
|
||||
} PROV_ARIA_GCM_CTX;
|
||||
|
||||
const PROV_GCM_HW *PROV_ARIA_HW_gcm(size_t keybits);
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Generic support for ARIA GCM.
|
||||
*/
|
||||
|
||||
#include "cipher_aria_gcm.h"
|
||||
|
||||
static int aria_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
PROV_ARIA_GCM_CTX *actx = (PROV_ARIA_GCM_CTX *)ctx;
|
||||
ARIA_KEY *ks = &actx->ks.ks;
|
||||
|
||||
GCM_HW_SET_KEY_CTR_FN(ks, aria_set_encrypt_key, aria_encrypt, NULL);
|
||||
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_final,
|
||||
gcm_one_shot
|
||||
};
|
||||
const PROV_GCM_HW *PROV_ARIA_HW_gcm(size_t keybits)
|
||||
{
|
||||
return &aria_gcm;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 "cipher_aria.h"
|
||||
|
||||
static int cipher_hw_aria_initkey(PROV_CIPHER_CTX *dat,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
int ret, mode = dat->mode;
|
||||
PROV_ARIA_CTX *adat = (PROV_ARIA_CTX *)dat;
|
||||
ARIA_KEY *ks = &adat->ks.ks;
|
||||
|
||||
if (dat->enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE))
|
||||
ret = aria_set_encrypt_key(key, keylen * 8, ks);
|
||||
else
|
||||
ret = aria_set_decrypt_key(key, keylen * 8, ks);
|
||||
if (ret < 0) {
|
||||
ERR_raise(ERR_LIB_PROV, EVP_R_ARIA_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
dat->ks = ks;
|
||||
dat->block = (block128_f)aria_encrypt;
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define PROV_CIPHER_HW_aria_mode(mode) \
|
||||
static const PROV_CIPHER_HW aria_##mode = { \
|
||||
cipher_hw_aria_initkey, \
|
||||
cipher_hw_chunked_##mode \
|
||||
}; \
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_##mode(size_t keybits) \
|
||||
{ \
|
||||
return &aria_##mode; \
|
||||
}
|
||||
|
||||
PROV_CIPHER_HW_aria_mode(cbc)
|
||||
PROV_CIPHER_HW_aria_mode(ecb)
|
||||
PROV_CIPHER_HW_aria_mode(ofb128)
|
||||
PROV_CIPHER_HW_aria_mode(cfb128)
|
||||
PROV_CIPHER_HW_aria_mode(cfb1)
|
||||
PROV_CIPHER_HW_aria_mode(cfb8)
|
||||
PROV_CIPHER_HW_aria_mode(ctr)
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 Blowfish cipher modes ecb, cbc, ofb, cfb */
|
||||
|
||||
#include "cipher_blowfish.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static OSSL_OP_cipher_freectx_fn blowfish_freectx;
|
||||
static OSSL_OP_cipher_dupctx_fn blowfish_dupctx;
|
||||
|
||||
static void blowfish_freectx(void *vctx)
|
||||
{
|
||||
PROV_BLOWFISH_CTX *ctx = (PROV_BLOWFISH_CTX *)vctx;
|
||||
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void *blowfish_dupctx(void *ctx)
|
||||
{
|
||||
PROV_BLOWFISH_CTX *in = (PROV_BLOWFISH_CTX *)ctx;
|
||||
PROV_BLOWFISH_CTX *ret = OPENSSL_malloc(sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
*ret = *in;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* bf_ecb_functions */
|
||||
IMPLEMENT_generic_cipher(blowfish, BLOWFISH, ecb, ECB, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 0, block)
|
||||
/* bf_cbc_functions */
|
||||
IMPLEMENT_generic_cipher(blowfish, BLOWFISH, cbc, CBC, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 64, block)
|
||||
/* bf_ofb_functions */
|
||||
IMPLEMENT_generic_cipher(blowfish, BLOWFISH, ofb64, OFB, EVP_CIPH_VARIABLE_LENGTH, 64, 8, 64, stream)
|
||||
/* bf_cfb_functions */
|
||||
IMPLEMENT_generic_cipher(blowfish, BLOWFISH, cfb64, CFB, EVP_CIPH_VARIABLE_LENGTH, 64, 8, 64, stream)
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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/blowfish.h>
|
||||
#include "internal/ciphers/ciphercommon.h"
|
||||
|
||||
typedef struct prov_blowfish_ctx_st {
|
||||
PROV_CIPHER_CTX base; /* Must be first */
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
BF_KEY ks;
|
||||
} ks;
|
||||
} PROV_BLOWFISH_CTX;
|
||||
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_cbc(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_ecb(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_ofb64(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_cfb64(size_t keybits);
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 "cipher_blowfish.h"
|
||||
|
||||
static int cipher_hw_blowfish_initkey(PROV_CIPHER_CTX *ctx,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
PROV_BLOWFISH_CTX *bctx = (PROV_BLOWFISH_CTX *)ctx;
|
||||
|
||||
BF_set_key(&bctx->ks.ks, keylen, key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define PROV_CIPHER_HW_blowfish_mode(mode, UCMODE) \
|
||||
IMPLEMENT_CIPHER_HW_##UCMODE(mode, blowfish, PROV_BLOWFISH_CTX, BF_KEY, \
|
||||
BF_##mode) \
|
||||
static const PROV_CIPHER_HW bf_##mode = { \
|
||||
cipher_hw_blowfish_initkey, \
|
||||
cipher_hw_blowfish_##mode##_cipher \
|
||||
}; \
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_##mode(size_t keybits) \
|
||||
{ \
|
||||
return &bf_##mode; \
|
||||
}
|
||||
|
||||
PROV_CIPHER_HW_blowfish_mode(cbc, CBC)
|
||||
PROV_CIPHER_HW_blowfish_mode(ecb, ECB)
|
||||
PROV_CIPHER_HW_blowfish_mode(ofb64, OFB)
|
||||
PROV_CIPHER_HW_blowfish_mode(cfb64, CFB)
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 CAMELLIA cipher modes ecb, cbc, ofb, cfb, ctr */
|
||||
|
||||
#include "cipher_camellia.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static OSSL_OP_cipher_freectx_fn camellia_freectx;
|
||||
static OSSL_OP_cipher_dupctx_fn camellia_dupctx;
|
||||
|
||||
static void camellia_freectx(void *vctx)
|
||||
{
|
||||
PROV_CAMELLIA_CTX *ctx = (PROV_CAMELLIA_CTX *)vctx;
|
||||
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void *camellia_dupctx(void *ctx)
|
||||
{
|
||||
PROV_CAMELLIA_CTX *in = (PROV_CAMELLIA_CTX *)ctx;
|
||||
PROV_CAMELLIA_CTX *ret = OPENSSL_malloc(sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
*ret = *in;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* camellia256ecb_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ecb, ECB, 0, 256, 128, 0, block)
|
||||
/* camellia192ecb_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ecb, ECB, 0, 192, 128, 0, block)
|
||||
/* camellia128ecb_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ecb, ECB, 0, 128, 128, 0, block)
|
||||
/* camellia256cbc_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cbc, CBC, 0, 256, 128, 128, block)
|
||||
/* camellia192cbc_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cbc, CBC, 0, 192, 128, 128, block)
|
||||
/* camellia128cbc_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cbc, CBC, 0, 128, 128, 128, block)
|
||||
/* camellia256ofb_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ofb, OFB, 0, 256, 8, 128, stream)
|
||||
/* camellia192ofb_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ofb, OFB, 0, 192, 8, 128, stream)
|
||||
/* camellia128ofb_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ofb, OFB, 0, 128, 8, 128, stream)
|
||||
/* camellia256cfb_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb, CFB, 0, 256, 8, 128, stream)
|
||||
/* camellia192cfb_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb, CFB, 0, 192, 8, 128, stream)
|
||||
/* camellia128cfb_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb, CFB, 0, 128, 8, 128, stream)
|
||||
/* camellia256cfb1_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb1, CFB, 0, 256, 8, 128, stream)
|
||||
/* camellia192cfb1_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb1, CFB, 0, 192, 8, 128, stream)
|
||||
/* camellia128cfb1_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb1, CFB, 0, 128, 8, 128, stream)
|
||||
/* camellia256cfb8_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb8, CFB, 0, 256, 8, 128, stream)
|
||||
/* camellia192cfb8_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb8, CFB, 0, 192, 8, 128, stream)
|
||||
/* camellia128cfb8_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb8, CFB, 0, 128, 8, 128, stream)
|
||||
/* camellia256ctr_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ctr, CTR, 0, 256, 8, 128, stream)
|
||||
/* camellia192ctr_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ctr, CTR, 0, 192, 8, 128, stream)
|
||||
/* camellia128ctr_functions */
|
||||
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ctr, CTR, 0, 128, 8, 128, stream)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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/camellia.h"
|
||||
#include "internal/ciphers/ciphercommon.h"
|
||||
|
||||
typedef struct prov_camellia_ctx_st {
|
||||
PROV_CIPHER_CTX base; /* Must be first */
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
CAMELLIA_KEY ks;
|
||||
} ks;
|
||||
} PROV_CAMELLIA_CTX;
|
||||
|
||||
#define PROV_CIPHER_HW_camellia_ofb PROV_CIPHER_HW_camellia_ofb128
|
||||
#define PROV_CIPHER_HW_camellia_cfb PROV_CIPHER_HW_camellia_cfb128
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_ecb(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_cbc(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_ofb128(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_cfb128(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_cfb1(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_cfb8(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_ctr(size_t keybits);
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 "cipher_camellia.h"
|
||||
#include <openssl/camellia.h>
|
||||
|
||||
static int cipher_hw_camellia_initkey(PROV_CIPHER_CTX *dat,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
int ret, mode = dat->mode;
|
||||
PROV_CAMELLIA_CTX *adat = (PROV_CAMELLIA_CTX *)dat;
|
||||
CAMELLIA_KEY *ks = &adat->ks.ks;
|
||||
|
||||
dat->ks = ks;
|
||||
ret = Camellia_set_key(key, keylen * 8, ks);
|
||||
if (ret < 0) {
|
||||
ERR_raise(ERR_LIB_PROV, EVP_R_ARIA_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
if (dat->enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE)) {
|
||||
dat->block = (block128_f) Camellia_encrypt;
|
||||
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f) Camellia_cbc_encrypt : NULL;
|
||||
} else {
|
||||
dat->block = (block128_f) Camellia_decrypt;
|
||||
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f) Camellia_cbc_encrypt : NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
# if defined(SPARC_CMLL_CAPABLE)
|
||||
# include "cipher_camellia_hw_t4.inc"
|
||||
# else
|
||||
/* The generic case */
|
||||
# define PROV_CIPHER_HW_declare(mode)
|
||||
# define PROV_CIPHER_HW_select(mode)
|
||||
# endif /* SPARC_CMLL_CAPABLE */
|
||||
|
||||
#define PROV_CIPHER_HW_camellia_mode(mode) \
|
||||
static const PROV_CIPHER_HW camellia_##mode = { \
|
||||
cipher_hw_camellia_initkey, \
|
||||
cipher_hw_generic_##mode \
|
||||
}; \
|
||||
PROV_CIPHER_HW_declare(mode) \
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_##mode(size_t keybits) \
|
||||
{ \
|
||||
PROV_CIPHER_HW_select(mode) \
|
||||
return &camellia_##mode; \
|
||||
}
|
||||
|
||||
PROV_CIPHER_HW_camellia_mode(cbc)
|
||||
PROV_CIPHER_HW_camellia_mode(ecb)
|
||||
PROV_CIPHER_HW_camellia_mode(ofb128)
|
||||
PROV_CIPHER_HW_camellia_mode(cfb128)
|
||||
PROV_CIPHER_HW_camellia_mode(cfb1)
|
||||
PROV_CIPHER_HW_camellia_mode(cfb8)
|
||||
PROV_CIPHER_HW_camellia_mode(ctr)
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Fujitsu SPARC64 X support for camellia modes.
|
||||
* This file is included by cipher_camellia_hw.c
|
||||
*/
|
||||
|
||||
static int cipher_hw_camellia_t4_initkey(PROV_CIPHER_CTX *dat,
|
||||
const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
int ret = 0, bits, mode = dat->mode;
|
||||
PROV_CAMELLIA_CTX *adat = (PROV_CAMELLIA_CTX *)dat;
|
||||
CAMELLIA_KEY *ks = &adat->ks.ks;
|
||||
|
||||
dat->ks = ks;
|
||||
bits = keylen * 8;
|
||||
|
||||
cmll_t4_set_key(key, bits, ks);
|
||||
|
||||
if (dat->enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE)) {
|
||||
dat->block = (block128_f) cmll_t4_encrypt;
|
||||
switch (bits) {
|
||||
case 128:
|
||||
if (mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f) cmll128_t4_cbc_encrypt;
|
||||
else if (mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f) cmll128_t4_ctr32_encrypt;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
break;
|
||||
case 192:
|
||||
case 256:
|
||||
if (mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f) cmll256_t4_cbc_encrypt;
|
||||
else if (mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f) cmll256_t4_ctr32_encrypt;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
dat->block = (block128_f) cmll_t4_decrypt;
|
||||
switch (bits) {
|
||||
case 128:
|
||||
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f) cmll128_t4_cbc_decrypt : NULL;
|
||||
break;
|
||||
case 192:
|
||||
case 256:
|
||||
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f) cmll256_t4_cbc_decrypt : NULL;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret < 0) {
|
||||
ERR_raise(ERR_LIB_PROV, EVP_R_CAMELLIA_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define PROV_CIPHER_HW_declare(mode) \
|
||||
static const PROV_CIPHER_HW t4_camellia_##mode = { \
|
||||
cipher_hw_camellia_t4_initkey, \
|
||||
cipher_hw_generic_##mode \
|
||||
};
|
||||
#define PROV_CIPHER_HW_select(mode) \
|
||||
if (SPARC_CMLL_CAPABLE) \
|
||||
return &t4_camellia_##mode;
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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/cast.h>
|
||||
#include "internal/ciphers/ciphercommon.h"
|
||||
|
||||
typedef struct prov_cast_ctx_st {
|
||||
PROV_CIPHER_CTX base; /* Must be first */
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
CAST_KEY ks;
|
||||
} ks;
|
||||
} PROV_CAST_CTX;
|
||||
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_cast5_cbc(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_cast5_ecb(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_cast5_ofb64(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_cast5_cfb64(size_t keybits);
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 cast cipher modes ecb, cbc, ofb, cfb */
|
||||
|
||||
#include "cipher_cast.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static OSSL_OP_cipher_freectx_fn cast5_freectx;
|
||||
static OSSL_OP_cipher_dupctx_fn cast5_dupctx;
|
||||
|
||||
static void cast5_freectx(void *vctx)
|
||||
{
|
||||
PROV_CAST_CTX *ctx = (PROV_CAST_CTX *)vctx;
|
||||
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void *cast5_dupctx(void *ctx)
|
||||
{
|
||||
PROV_CAST_CTX *in = (PROV_CAST_CTX *)ctx;
|
||||
PROV_CAST_CTX *ret = OPENSSL_malloc(sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
*ret = *in;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* cast5128ecb_functions */
|
||||
IMPLEMENT_generic_cipher(cast5, CAST, ecb, ECB, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 0, block)
|
||||
/* cast5128cbc_functions */
|
||||
IMPLEMENT_generic_cipher(cast5, CAST, cbc, CBC, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 64, block)
|
||||
/* cast564ofb64_functions */
|
||||
IMPLEMENT_generic_cipher(cast5, CAST, ofb64, OFB, EVP_CIPH_VARIABLE_LENGTH, 64, 8, 64, stream)
|
||||
/* cast564cfb64_functions */
|
||||
IMPLEMENT_generic_cipher(cast5, CAST, cfb64, CFB, EVP_CIPH_VARIABLE_LENGTH, 64, 8, 64, stream)
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 "cipher_cast.h"
|
||||
|
||||
static int cipher_hw_cast5_initkey(PROV_CIPHER_CTX *ctx,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
PROV_CAST_CTX *bctx = (PROV_CAST_CTX *)ctx;
|
||||
|
||||
CAST_set_key(&(bctx->ks.ks), keylen, key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define PROV_CIPHER_HW_cast_mode(mode, UCMODE) \
|
||||
IMPLEMENT_CIPHER_HW_##UCMODE(mode, cast5, PROV_CAST_CTX, CAST_KEY, \
|
||||
CAST_##mode) \
|
||||
static const PROV_CIPHER_HW cast5_##mode = { \
|
||||
cipher_hw_cast5_initkey, \
|
||||
cipher_hw_cast5_##mode##_cipher \
|
||||
}; \
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_cast5_##mode(size_t keybits) \
|
||||
{ \
|
||||
return &cast5_##mode; \
|
||||
}
|
||||
|
||||
PROV_CIPHER_HW_cast_mode(cbc, CBC)
|
||||
PROV_CIPHER_HW_cast_mode(ecb, ECB)
|
||||
PROV_CIPHER_HW_cast_mode(ofb64, OFB)
|
||||
PROV_CIPHER_HW_cast_mode(cfb64, CFB)
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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 "cipher_tdes_default.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
/* desx_cbc_functions */
|
||||
IMPLEMENT_tdes_cipher(desx, DESX, cbc, CBC, TDES_FLAGS, 64*3, 64, 64, block);
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 1995-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/des.h>
|
||||
#include "cipher_tdes_default.h"
|
||||
|
||||
/*
|
||||
* Note the PROV_TDES_CTX has been used for the DESX cipher, just to reduce
|
||||
* code size.
|
||||
*/
|
||||
#define ks1 tks.ks[0]
|
||||
#define ks2 tks.ks[1].ks[0].cblock
|
||||
#define ks3 tks.ks[2].ks[0].cblock
|
||||
|
||||
static int cipher_hw_desx_cbc_initkey(PROV_CIPHER_CTX *ctx,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
|
||||
DES_cblock *deskey = (DES_cblock *)key;
|
||||
|
||||
DES_set_key_unchecked(deskey, &tctx->ks1);
|
||||
memcpy(&tctx->ks2, &key[8], 8);
|
||||
memcpy(&tctx->ks3, &key[16], 8);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cipher_hw_desx_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl)
|
||||
{
|
||||
PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
|
||||
|
||||
while (inl >= MAXCHUNK) {
|
||||
DES_xcbc_encrypt(in, out, (long)MAXCHUNK, &tctx->ks1,
|
||||
(DES_cblock *)ctx->iv, &tctx->ks2, &tctx->ks3,
|
||||
ctx->enc);
|
||||
inl -= MAXCHUNK;
|
||||
in += MAXCHUNK;
|
||||
out += MAXCHUNK;
|
||||
}
|
||||
if (inl > 0)
|
||||
DES_xcbc_encrypt(in, out, (long)inl, &tctx->ks1,
|
||||
(DES_cblock *)ctx->iv, &tctx->ks2, &tctx->ks3,
|
||||
ctx->enc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const PROV_CIPHER_HW desx_cbc =
|
||||
{
|
||||
cipher_hw_desx_cbc_initkey,
|
||||
cipher_hw_desx_cbc
|
||||
};
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_desx_cbc(void)
|
||||
{
|
||||
return &desx_cbc;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 Idea cipher modes ecb, cbc, ofb, cfb */
|
||||
|
||||
#include "cipher_idea.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static OSSL_OP_cipher_freectx_fn idea_freectx;
|
||||
static OSSL_OP_cipher_dupctx_fn idea_dupctx;
|
||||
|
||||
static void idea_freectx(void *vctx)
|
||||
{
|
||||
PROV_IDEA_CTX *ctx = (PROV_IDEA_CTX *)vctx;
|
||||
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void *idea_dupctx(void *ctx)
|
||||
{
|
||||
PROV_IDEA_CTX *in = (PROV_IDEA_CTX *)ctx;
|
||||
PROV_IDEA_CTX *ret = OPENSSL_malloc(sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
*ret = *in;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* idea128ecb_functions */
|
||||
IMPLEMENT_generic_cipher(idea, IDEA, ecb, ECB, 0, 128, 64, 0, block)
|
||||
/* idea128cbc_functions */
|
||||
IMPLEMENT_generic_cipher(idea, IDEA, cbc, CBC, 0, 128, 64, 64, block)
|
||||
/* idea128ofb64_functions */
|
||||
IMPLEMENT_generic_cipher(idea, IDEA, ofb64, OFB, 0, 128, 8, 64, stream)
|
||||
/* idea128cfb64_functions */
|
||||
IMPLEMENT_generic_cipher(idea, IDEA, cfb64, CFB, 0, 128, 8, 64, stream)
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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/idea.h>
|
||||
#include "internal/ciphers/ciphercommon.h"
|
||||
|
||||
typedef struct prov_idea_ctx_st {
|
||||
PROV_CIPHER_CTX base; /* Must be first */
|
||||
union {
|
||||
OSSL_UNION_ALIGN;
|
||||
IDEA_KEY_SCHEDULE ks;
|
||||
} ks;
|
||||
} PROV_IDEA_CTX;
|
||||
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_idea_cbc(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_idea_ecb(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_idea_ofb64(size_t keybits);
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_idea_cfb64(size_t keybits);
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 "cipher_idea.h"
|
||||
|
||||
static int cipher_hw_idea_initkey(PROV_CIPHER_CTX *ctx,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
PROV_IDEA_CTX *ictx = (PROV_IDEA_CTX *)ctx;
|
||||
IDEA_KEY_SCHEDULE *ks = &(ictx->ks.ks);
|
||||
|
||||
if (ctx->enc
|
||||
|| ctx->mode == EVP_CIPH_OFB_MODE
|
||||
|| ctx->mode == EVP_CIPH_CFB_MODE) {
|
||||
IDEA_set_encrypt_key(key, ks);
|
||||
} else {
|
||||
IDEA_KEY_SCHEDULE tmp;
|
||||
|
||||
IDEA_set_encrypt_key(key, &tmp);
|
||||
IDEA_set_decrypt_key(&tmp, ks);
|
||||
OPENSSL_cleanse((unsigned char *)&tmp, sizeof(IDEA_KEY_SCHEDULE));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define PROV_CIPHER_HW_idea_mode_ex(mode, UCMODE, fname) \
|
||||
IMPLEMENT_CIPHER_HW_##UCMODE(mode, idea, PROV_IDEA_CTX, IDEA_KEY_SCHEDULE, \
|
||||
fname) \
|
||||
static const PROV_CIPHER_HW idea_##mode = { \
|
||||
cipher_hw_idea_initkey, \
|
||||
cipher_hw_idea_##mode##_cipher \
|
||||
}; \
|
||||
const PROV_CIPHER_HW *PROV_CIPHER_HW_idea_##mode(size_t keybits) \
|
||||
{ \
|
||||
return &idea_##mode; \
|
||||
}
|
||||
|
||||
# define PROV_CIPHER_HW_idea_mode(mode, UCMODE) \
|
||||
PROV_CIPHER_HW_idea_mode_ex(mode, UCMODE, IDEA_##mode)
|
||||
|
||||
PROV_CIPHER_HW_idea_mode(cbc, CBC)
|
||||
PROV_CIPHER_HW_idea_mode(ofb64, OFB)
|
||||
PROV_CIPHER_HW_idea_mode(cfb64, CFB)
|
||||
/*
|
||||
* IDEA_ecb_encrypt() does not have a enc parameter - so we create a macro
|
||||
* that ignores this parameter when IMPLEMENT_CIPHER_HW_ecb() is called.
|
||||
*/
|
||||
#define IDEA2_ecb_encrypt(in, out, ks, enc) IDEA_ecb_encrypt(in, out, ks)
|
||||
|
||||
PROV_CIPHER_HW_idea_mode_ex(ecb, ECB, IDEA2_ecb)
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 Seed cipher modes ecb, cbc, ofb, cfb */
|
||||
|
||||
#include "cipher_seed.h"
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
/* TODO (3.0) Figure out what flags are required */
|
||||
#define SEED_FLAGS EVP_CIPH_FLAG_DEFAULT_ASN1
|
||||
|
||||
static OSSL_OP_cipher_freectx_fn seed_freectx;
|
||||
static OSSL_OP_cipher_dupctx_fn seed_dupctx;
|
||||
|
||||
static void seed_freectx(void *vctx)
|
||||
{
|
||||
PROV_SEED_CTX *ctx = (PROV_SEED_CTX *)vctx;
|
||||
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void *seed_dupctx(void *ctx)
|
||||
{
|
||||
PROV_SEED_CTX *in = (PROV_SEED_CTX *)ctx;
|
||||
PROV_SEED_CTX *ret = OPENSSL_malloc(sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
*ret = *in;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* seed128ecb_functions */
|
||||
IMPLEMENT_generic_cipher(seed, SEED, ecb, ECB, SEED_FLAGS, 128, 128, 0, block)
|
||||
/* seed128cbc_functions */
|
||||
IMPLEMENT_generic_cipher(seed, SEED, cbc, CBC, SEED_FLAGS, 128, 128, 128, block)
|
||||
/* seed128ofb128_functions */
|
||||
IMPLEMENT_generic_cipher(seed, SEED, ofb128, OFB, SEED_FLAGS, 128, 8, 128, stream)
|
||||
/* seed128cfb128_functions */
|
||||
IMPLEMENT_generic_cipher(seed, SEED, cfb128, CFB, SEED_FLAGS, 128, 8, 128, stream)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user