From 2f2c9caa727d7d2a5ce4bfb8266e019546ce77df Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 27 Nov 2015 12:02:25 +0000 Subject: [PATCH 1/1] Add dummy pipeline support for aes128_cbc_hmac_sha1 Add dummy pipline support to dasync for the aes128_cbc_hmac_sha1 cipher. This is treated as an AEAD cipher. Reviewed-by: Tim Hudson --- engines/e_dasync.c | 222 +++++++++++++++++++++++++++++++++++++++-- engines/e_dasync_err.c | 8 +- engines/e_dasync_err.h | 1 + 3 files changed, 221 insertions(+), 10 deletions(-) diff --git a/engines/e_dasync.c b/engines/e_dasync.c index 018175c9e4..1d9c278bd3 100644 --- a/engines/e_dasync.c +++ b/engines/e_dasync.c @@ -55,6 +55,7 @@ #include #include +#include #include #include #include @@ -182,15 +183,24 @@ static RSA_METHOD dasync_rsa_method = { static int dasync_aes128_cbc_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); - static int dasync_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc); - static int dasync_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl); - static int dasync_aes128_cbc_cleanup(EVP_CIPHER_CTX *ctx); +static int dasync_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, + int arg, void *ptr); +static int dasync_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, + int enc); +static int dasync_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl); +static int dasync_aes128_cbc_hmac_sha1_cleanup(EVP_CIPHER_CTX *ctx); + struct aes_128_cbc_pipeline_ctx { void *inner_cipher_data; unsigned char dummy[256]; @@ -198,6 +208,9 @@ struct aes_128_cbc_pipeline_ctx { unsigned char **inbufs; unsigned char **outbufs; size_t *lens; + int enc; + unsigned char tlsaad[SSL_MAX_PIPELINES][EVP_AEAD_TLS1_AAD_LEN]; + unsigned int aadctr; }; static EVP_CIPHER *_hidden_aes_128_cbc = NULL; @@ -229,18 +242,45 @@ static const EVP_CIPHER *dasync_aes_128_cbc(void) return _hidden_aes_128_cbc; } +static EVP_CIPHER *_hidden_aes_128_cbc_hmac_sha1 = NULL; +static const EVP_CIPHER *dasync_aes_128_cbc_hmac_sha1(void) +{ + if (_hidden_aes_128_cbc_hmac_sha1 == NULL) + _hidden_aes_128_cbc_hmac_sha1 = EVP_CIPHER_meth_new( + NID_aes_128_cbc_hmac_sha1, + 16 /* block size */, + 16 /* key len */); + if (_hidden_aes_128_cbc_hmac_sha1 == NULL + || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc_hmac_sha1,16) + || !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc_hmac_sha1, + EVP_CIPH_CBC_MODE + | EVP_CIPH_FLAG_DEFAULT_ASN1 + | EVP_CIPH_FLAG_AEAD_CIPHER + | EVP_CIPH_FLAG_PIPELINE) + || !EVP_CIPHER_meth_set_init(_hidden_aes_128_cbc_hmac_sha1, + dasync_aes128_cbc_hmac_sha1_init_key) + || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc_hmac_sha1, + dasync_aes128_cbc_hmac_sha1_cipher) + || !EVP_CIPHER_meth_set_cleanup(_hidden_aes_128_cbc_hmac_sha1, + dasync_aes128_cbc_hmac_sha1_cleanup) + || !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_cbc_hmac_sha1, + dasync_aes128_cbc_hmac_sha1_ctrl) + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc_hmac_sha1, + sizeof(struct aes_128_cbc_pipeline_ctx))) { + EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1); + _hidden_aes_128_cbc_hmac_sha1 = NULL; + } + return _hidden_aes_128_cbc_hmac_sha1; +} static int dasync_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid); -# ifdef NID_aes_128_cbc_hmac_sha256 static int dasync_cipher_nids[] = { NID_aes_128_cbc, + NID_aes_128_cbc_hmac_sha1, 0 }; -# else -static int dasync_cipher_nids[] = { 0 }; -#endif static int bind_dasync(ENGINE *e) { @@ -353,6 +393,9 @@ static int dasync_ciphers(ENGINE *e, const EVP_CIPHER **cipher, case NID_aes_128_cbc: *cipher = dasync_aes_128_cbc(); break; + case NID_aes_128_cbc_hmac_sha1: + *cipher = dasync_aes_128_cbc_hmac_sha1(); + break; default: ok = 0; *cipher = NULL; @@ -577,6 +620,7 @@ static int dasync_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, } pipe_ctx->numpipes = 0; + pipe_ctx->aadctr = 0; EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx->inner_cipher_data); ret = EVP_CIPHER_meth_get_init(EVP_aes_128_cbc())(ctx, key, iv, enc); @@ -621,3 +665,167 @@ static int dasync_aes128_cbc_cleanup(EVP_CIPHER_CTX *ctx) return 1; } + + +/* + * AES128 CBC HMAC SHA1 Implementation + */ + +static int dasync_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, + int arg, void *ptr) +{ + struct aes_128_cbc_pipeline_ctx *pipe_ctx = + (struct aes_128_cbc_pipeline_ctx *)EVP_CIPHER_CTX_cipher_data(ctx); + int ret; + + if (pipe_ctx == NULL) + return 0; + + switch (type) { + case EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS: + pipe_ctx->numpipes = arg; + pipe_ctx->outbufs = (unsigned char **)ptr; + break; + + case EVP_CTRL_SET_PIPELINE_INPUT_BUFS: + pipe_ctx->numpipes = arg; + pipe_ctx->inbufs = (unsigned char **)ptr; + break; + + case EVP_CTRL_SET_PIPELINE_INPUT_LENS: + pipe_ctx->numpipes = arg; + pipe_ctx->lens = (size_t *)ptr; + break; + + case EVP_CTRL_AEAD_SET_MAC_KEY: + EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx->inner_cipher_data); + ret = EVP_CIPHER_meth_get_ctrl(EVP_aes_128_cbc_hmac_sha1()) + (ctx, type, arg, ptr); + EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx); + return ret; + + case EVP_CTRL_AEAD_TLS1_AAD: + { + unsigned char *p = ptr; + unsigned int len; + + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return -1; + + if (pipe_ctx->aadctr >= SSL_MAX_PIPELINES) + return -1; + + memcpy(pipe_ctx->tlsaad[pipe_ctx->aadctr], ptr, + EVP_AEAD_TLS1_AAD_LEN); + pipe_ctx->aadctr++; + + len = p[arg - 2] << 8 | p[arg - 1]; + + if (pipe_ctx->enc) { + if ((p[arg - 4] << 8 | p[arg - 3]) >= TLS1_1_VERSION) { + len -= AES_BLOCK_SIZE; + } + + return ((len + SHA_DIGEST_LENGTH + AES_BLOCK_SIZE) + & -AES_BLOCK_SIZE) - len; + } else { + return SHA_DIGEST_LENGTH; + } + } + + + default: + return 0; + } + + return 1; +} + +static int dasync_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, + int enc) +{ + int ret; + struct aes_128_cbc_pipeline_ctx *pipe_ctx = + (struct aes_128_cbc_pipeline_ctx *)EVP_CIPHER_CTX_cipher_data(ctx); + + if (pipe_ctx->inner_cipher_data == NULL + && EVP_CIPHER_impl_ctx_size(EVP_aes_128_cbc_hmac_sha1()) + != 0) { + pipe_ctx->inner_cipher_data = + OPENSSL_zalloc(EVP_CIPHER_impl_ctx_size( + EVP_aes_128_cbc_hmac_sha1())); + if (pipe_ctx->inner_cipher_data == NULL) { + DASYNCerr(DASYNC_F_DASYNC_AES128_CBC_HMAC_SHA1_INIT_KEY, + ERR_R_MALLOC_FAILURE); + return 0; + } + } + + pipe_ctx->numpipes = 0; + pipe_ctx->enc = enc; + + EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx->inner_cipher_data); + ret = EVP_CIPHER_meth_get_init(EVP_aes_128_cbc_hmac_sha1()) + (ctx, key, iv, enc); + EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx); + + return ret; +} + +static int dasync_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl) +{ + int ret = 1; + unsigned int i, pipes; + struct aes_128_cbc_pipeline_ctx *pipe_ctx = + (struct aes_128_cbc_pipeline_ctx *)EVP_CIPHER_CTX_cipher_data(ctx); + + pipes = pipe_ctx->numpipes; + EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx->inner_cipher_data); + if (pipes == 0) { + if (pipe_ctx->aadctr != 0) { + if (pipe_ctx->aadctr != 1) + return -1; + EVP_CIPHER_meth_get_ctrl(EVP_aes_128_cbc_hmac_sha1()) + (ctx, EVP_CTRL_AEAD_TLS1_AAD, + EVP_AEAD_TLS1_AAD_LEN, + pipe_ctx->tlsaad[0]); + } + ret = EVP_CIPHER_meth_get_do_cipher(EVP_aes_128_cbc_hmac_sha1()) + (ctx, out, in, inl); + } else { + if (pipe_ctx->aadctr > 0 && pipe_ctx->aadctr != pipes) + return -1; + for (i = 0; i < pipes; i++) { + if (pipe_ctx->aadctr > 0) { + EVP_CIPHER_meth_get_ctrl(EVP_aes_128_cbc_hmac_sha1()) + (ctx, EVP_CTRL_AEAD_TLS1_AAD, + EVP_AEAD_TLS1_AAD_LEN, + pipe_ctx->tlsaad[i]); + } + ret = ret && EVP_CIPHER_meth_get_do_cipher( + EVP_aes_128_cbc_hmac_sha1()) + (ctx, pipe_ctx->outbufs[i], pipe_ctx->inbufs[i], + pipe_ctx->lens[i]); + } + pipe_ctx->numpipes = 0; + } + pipe_ctx->aadctr = 0; + EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx); + return ret; +} + +static int dasync_aes128_cbc_hmac_sha1_cleanup(EVP_CIPHER_CTX *ctx) +{ + struct aes_128_cbc_pipeline_ctx *pipe_ctx = + (struct aes_128_cbc_pipeline_ctx *)EVP_CIPHER_CTX_cipher_data(ctx); + + OPENSSL_clear_free(pipe_ctx->inner_cipher_data, + EVP_CIPHER_impl_ctx_size(EVP_aes_128_cbc_hmac_sha1())); + + return 1; +} diff --git a/engines/e_dasync_err.c b/engines/e_dasync_err.c index 570a54ed37..ed5e98ee3f 100644 --- a/engines/e_dasync_err.c +++ b/engines/e_dasync_err.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1999-2015 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2016 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -69,9 +69,11 @@ # define ERR_REASON(reason) ERR_PACK(0,0,reason) static ERR_STRING_DATA DASYNC_str_functs[] = { - {ERR_FUNC(DASYNC_F_BIND_DASYNC), "BIND_DASYNC"}, + {ERR_FUNC(DASYNC_F_BIND_DASYNC), "bind_dasync"}, {ERR_FUNC(DASYNC_F_CIPHER_AES_128_CBC_CODE), "CIPHER_AES_128_CBC_CODE"}, - {ERR_FUNC(DASYNC_F_DASYNC_AES128_INIT_KEY), "DASYNC_AES128_INIT_KEY"}, + {ERR_FUNC(DASYNC_F_DASYNC_AES128_CBC_HMAC_SHA1_INIT_KEY), + "dasync_aes128_cbc_hmac_sha1_init_key"}, + {ERR_FUNC(DASYNC_F_DASYNC_AES128_INIT_KEY), "dasync_aes128_init_key"}, {ERR_FUNC(DASYNC_F_DASYNC_BN_MOD_EXP), "DASYNC_BN_MOD_EXP"}, {ERR_FUNC(DASYNC_F_DASYNC_MOD_EXP), "DASYNC_MOD_EXP"}, {ERR_FUNC(DASYNC_F_DASYNC_PRIVATE_DECRYPT), "DASYNC_PRIVATE_DECRYPT"}, diff --git a/engines/e_dasync_err.h b/engines/e_dasync_err.h index af5241e572..560f163a6f 100644 --- a/engines/e_dasync_err.h +++ b/engines/e_dasync_err.h @@ -74,6 +74,7 @@ static void ERR_DASYNC_error(int function, int reason, char *file, int line); /* Function codes. */ # define DASYNC_F_BIND_DASYNC 107 # define DASYNC_F_CIPHER_AES_128_CBC_CODE 100 +# define DASYNC_F_DASYNC_AES128_CBC_HMAC_SHA1_INIT_KEY 109 # define DASYNC_F_DASYNC_AES128_INIT_KEY 108 # define DASYNC_F_DASYNC_BN_MOD_EXP 101 # define DASYNC_F_DASYNC_MOD_EXP 102 -- 2.34.1