From 64da15c40d15aac58e211fd25d00e9ae84d0379b Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Sun, 24 May 2020 16:14:02 +0200 Subject: [PATCH] Replace the AES-128-CBC-HMAC-SHA1 cipher in e_ossltest.c This replaces the AES-128-CBC-HMAC-SHA1 cipher with a non-encrypting version for use the test suite. [extended tests] Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/16693) --- engines/e_ossltest.c | 216 +++++++++++++++++++++++++++++++++++---- ssl/record/ssl3_record.c | 23 ++--- ssl/record/tls_pad.c | 2 - ssl/tls_depr.c | 10 +- 4 files changed, 210 insertions(+), 41 deletions(-) diff --git a/engines/e_ossltest.c b/engines/e_ossltest.c index 8479414f01..0506faa628 100644 --- a/engines/e_ossltest.c +++ b/engines/e_ossltest.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "e_ossltest_err.c" @@ -247,21 +248,39 @@ static int ossltest_ciphers(ENGINE *, const EVP_CIPHER **, const int **, int); static int ossltest_cipher_nids[] = { - NID_aes_128_cbc, NID_aes_128_gcm, 0 + NID_aes_128_cbc, NID_aes_128_gcm, + NID_aes_128_cbc_hmac_sha1, 0 }; /* AES128 */ -int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc); -int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t inl); -int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc); -int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t inl); +static int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, int enc); +static int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +static int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, int enc); +static int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); static int ossltest_aes128_gcm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); +static int ossltest_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, + int enc); +static int ossltest_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl); +static int ossltest_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, + int arg, void *ptr); + +typedef struct { + size_t payload_length; /* AAD length in decrypt case */ + unsigned int tls_ver; +} EVP_AES_HMAC_SHA1; static EVP_CIPHER *_hidden_aes_128_cbc = NULL; static const EVP_CIPHER *ossltest_aes_128_cbc(void) @@ -285,6 +304,7 @@ static const EVP_CIPHER *ossltest_aes_128_cbc(void) } return _hidden_aes_128_cbc; } + static EVP_CIPHER *_hidden_aes_128_gcm = NULL; #define AES_GCM_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \ @@ -315,11 +335,45 @@ static const EVP_CIPHER *ossltest_aes_128_gcm(void) return _hidden_aes_128_gcm; } +static EVP_CIPHER *_hidden_aes_128_cbc_hmac_sha1 = NULL; + +static const EVP_CIPHER *ossltest_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 */)) == 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_CIPHER_meth_set_init(_hidden_aes_128_cbc_hmac_sha1, + ossltest_aes128_cbc_hmac_sha1_init_key) + || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc_hmac_sha1, + ossltest_aes128_cbc_hmac_sha1_cipher) + || !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_cbc_hmac_sha1, + ossltest_aes128_cbc_hmac_sha1_ctrl) + || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_aes_128_cbc_hmac_sha1, + EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv) + || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_aes_128_cbc_hmac_sha1, + EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv) + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc_hmac_sha1, + sizeof(EVP_AES_HMAC_SHA1)))) { + 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 void destroy_ciphers(void) { EVP_CIPHER_meth_free(_hidden_aes_128_cbc); EVP_CIPHER_meth_free(_hidden_aes_128_gcm); + EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1); _hidden_aes_128_cbc = NULL; + _hidden_aes_128_gcm = NULL; + _hidden_aes_128_cbc_hmac_sha1 = NULL; } /* Key loading */ @@ -490,6 +544,9 @@ static int ossltest_ciphers(ENGINE *e, const EVP_CIPHER **cipher, case NID_aes_128_gcm: *cipher = ossltest_aes_128_gcm(); break; + case NID_aes_128_cbc_hmac_sha1: + *cipher = ossltest_aes_128_cbc_hmac_sha1(); + break; default: ok = 0; *cipher = NULL; @@ -634,14 +691,15 @@ static int digest_sha512_final(EVP_MD_CTX *ctx, unsigned char *md) * AES128 Implementation */ -int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc) +static int ossltest_aes128_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, int enc) { return EVP_CIPHER_meth_get_init(EVP_aes_128_cbc()) (ctx, key, iv, enc); } -int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t inl) +static int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) { unsigned char *tmpbuf; int ret; @@ -667,15 +725,15 @@ int ossltest_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, return ret; } -int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc) +static int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, int enc) { return EVP_CIPHER_meth_get_init(EVP_aes_128_gcm()) (ctx, key, iv, enc); } - -int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t inl) +static int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) { unsigned char *tmpbuf = OPENSSL_malloc(inl); @@ -720,6 +778,128 @@ static int ossltest_aes128_gcm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, return 1; } +#define NO_PAYLOAD_LENGTH ((size_t)-1) +# define data(ctx) ((EVP_AES_HMAC_SHA1 *)EVP_CIPHER_CTX_get_cipher_data(ctx)) + +static int ossltest_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *inkey, + const unsigned char *iv, + int enc) +{ + EVP_AES_HMAC_SHA1 *key = data(ctx); + key->payload_length = NO_PAYLOAD_LENGTH; + return 1; +} + +static int ossltest_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t len) +{ + EVP_AES_HMAC_SHA1 *key = data(ctx); + unsigned int l; + size_t plen = key->payload_length; + + key->payload_length = NO_PAYLOAD_LENGTH; + + if (len % AES_BLOCK_SIZE) + return 0; + + if (EVP_CIPHER_CTX_is_encrypting(ctx)) { + if (plen == NO_PAYLOAD_LENGTH) + plen = len; + else if (len != + ((plen + SHA_DIGEST_LENGTH + + AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)) + return 0; + + memmove(out, in, plen); + + if (plen != len) { /* "TLS" mode of operation */ + /* calculate HMAC and append it to payload */ + fill_known_data(out + plen, SHA_DIGEST_LENGTH); + + /* pad the payload|hmac */ + plen += SHA_DIGEST_LENGTH; + for (l = len - plen - 1; plen < len; plen++) + out[plen] = l; + } + } else { + /* decrypt HMAC|padding at once */ + memmove(out, in, len); + + if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */ + unsigned int maxpad, pad; + + if (key->tls_ver >= TLS1_1_VERSION) { + if (len < (AES_BLOCK_SIZE + SHA_DIGEST_LENGTH + 1)) + return 0; + + /* omit explicit iv */ + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + len -= AES_BLOCK_SIZE; + } else if (len < (SHA_DIGEST_LENGTH + 1)) + return 0; + + /* figure out payload length */ + pad = out[len - 1]; + maxpad = len - (SHA_DIGEST_LENGTH + 1); + if (pad > maxpad) + return 0; + for (plen = len - pad - 1; plen < len; plen++) + if (out[plen] != pad) + return 0; + } + } + + return 1; +} + +static int ossltest_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, + int arg, void *ptr) +{ + EVP_AES_HMAC_SHA1 *key = data(ctx); + + switch (type) { + case EVP_CTRL_AEAD_SET_MAC_KEY: + return 1; + + case EVP_CTRL_AEAD_TLS1_AAD: + { + unsigned char *p = ptr; + unsigned int len; + + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return -1; + + len = p[arg - 2] << 8 | p[arg - 1]; + key->tls_ver = p[arg - 4] << 8 | p[arg - 3]; + + if (EVP_CIPHER_CTX_is_encrypting(ctx)) { + key->payload_length = len; + if (key->tls_ver >= TLS1_1_VERSION) { + if (len < AES_BLOCK_SIZE) + return 0; + len -= AES_BLOCK_SIZE; + p[arg - 2] = len >> 8; + p[arg - 1] = len; + } + + return (int)(((len + SHA_DIGEST_LENGTH + + AES_BLOCK_SIZE) & -AES_BLOCK_SIZE) + - len); + } else { + key->payload_length = arg; + + return SHA_DIGEST_LENGTH; + } + } + default: + return -1; + } +} + static int ossltest_rand_bytes(unsigned char *buf, int num) { unsigned char val = 1; diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c index b6ac61e0e8..c713f231ca 100644 --- a/ssl/record/ssl3_record.c +++ b/ssl/record/ssl3_record.c @@ -1218,23 +1218,17 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending, } if (!sending) { - /* Adjust the record to remove the explicit IV/MAC/Tag */ - if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_GCM_MODE) { - for (ctr = 0; ctr < n_recs; ctr++) { + for (ctr = 0; ctr < n_recs; ctr++) { + /* Adjust the record to remove the explicit IV/MAC/Tag */ + if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_GCM_MODE) { recs[ctr].data += EVP_GCM_TLS_EXPLICIT_IV_LEN; recs[ctr].input += EVP_GCM_TLS_EXPLICIT_IV_LEN; recs[ctr].length -= EVP_GCM_TLS_EXPLICIT_IV_LEN; - } - } else if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_CCM_MODE) { - for (ctr = 0; ctr < n_recs; ctr++) { + } else if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_CCM_MODE) { recs[ctr].data += EVP_CCM_TLS_EXPLICIT_IV_LEN; recs[ctr].input += EVP_CCM_TLS_EXPLICIT_IV_LEN; recs[ctr].length -= EVP_CCM_TLS_EXPLICIT_IV_LEN; - } - } - - for (ctr = 0; ctr < n_recs; ctr++) { - if (bs != 1 && SSL_USE_EXPLICIT_IV(s)) { + } else if (bs != 1 && SSL_USE_EXPLICIT_IV(s)) { if (recs[ctr].length < bs) return 0; recs[ctr].data += bs; @@ -1254,17 +1248,12 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending, (macs != NULL) ? &macs[ctr].alloced : NULL, bs, - macsize, + pad ? (size_t)pad : macsize, (EVP_CIPHER_get_flags(enc) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0, s->ctx->libctx)) return 0; } - if (pad) { - for (ctr = 0; ctr < n_recs; ctr++) { - recs[ctr].length -= pad; - } - } } } } diff --git a/ssl/record/tls_pad.c b/ssl/record/tls_pad.c index 46614e143b..528c605554 100644 --- a/ssl/record/tls_pad.c +++ b/ssl/record/tls_pad.c @@ -138,8 +138,6 @@ int tls1_cbc_remove_padding_and_mac(size_t *reclen, if (aead) { /* padding is already verified and we don't need to check the MAC */ *reclen -= padding_length + 1 + mac_size; - *mac = NULL; - *alloced = 0; return 1; } diff --git a/ssl/tls_depr.c b/ssl/tls_depr.c index 0b21ff7669..1761ba1d8e 100644 --- a/ssl/tls_depr.c +++ b/ssl/tls_depr.c @@ -27,6 +27,7 @@ void tls_engine_finish(ENGINE *e) const EVP_CIPHER *tls_get_cipher_from_engine(int nid) { + const EVP_CIPHER *ret = NULL; #ifndef OPENSSL_NO_ENGINE ENGINE *eng; @@ -36,15 +37,16 @@ const EVP_CIPHER *tls_get_cipher_from_engine(int nid) */ eng = ENGINE_get_cipher_engine(nid); if (eng != NULL) { + ret = ENGINE_get_cipher(eng, nid); ENGINE_finish(eng); - return EVP_get_cipherbynid(nid); } #endif - return NULL; + return ret; } const EVP_MD *tls_get_digest_from_engine(int nid) { + const EVP_MD *ret = NULL; #ifndef OPENSSL_NO_ENGINE ENGINE *eng; @@ -54,11 +56,11 @@ const EVP_MD *tls_get_digest_from_engine(int nid) */ eng = ENGINE_get_digest_engine(nid); if (eng != NULL) { + ret = ENGINE_get_digest(eng, nid); ENGINE_finish(eng); - return EVP_get_digestbynid(nid); } #endif - return NULL; + return ret; } #ifndef OPENSSL_NO_ENGINE -- 2.34.1