From fb0b540c39c782c9152081c2021f54363e04307c Mon Sep 17 00:00:00 2001 From: tb <> Date: Sun, 17 Mar 2019 18:07:41 +0000 Subject: Provide EVP_aes_{128,192,256}_wrap(). This is a compatible implementation based on the one in OpenSSL 1.0.2r which is still freely licensed. The functions are undocumented in OpenSSL. To use them, one needs to set the undocumented EVP_CIPHER_CTX_FLAG_WRAP_ALLOW flag on the EVP_CIPHER_CTX. resolves #505 ok jsing --- src/lib/libcrypto/Symbols.list | 3 + src/lib/libcrypto/evp/c_all.c | 5 +- src/lib/libcrypto/evp/e_aes.c | 146 +++++++++++++++++++++++++++++++++++++++- src/lib/libcrypto/evp/evp.h | 13 +++- src/lib/libcrypto/evp/evp_enc.c | 10 ++- src/lib/libcrypto/evp/evp_err.c | 3 +- 6 files changed, 174 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/lib/libcrypto/Symbols.list b/src/lib/libcrypto/Symbols.list index 63e3ee45ac..9fdf723f87 100644 --- a/src/lib/libcrypto/Symbols.list +++ b/src/lib/libcrypto/Symbols.list @@ -1515,6 +1515,7 @@ EVP_aes_128_ctr EVP_aes_128_ecb EVP_aes_128_gcm EVP_aes_128_ofb +EVP_aes_128_wrap EVP_aes_128_xts EVP_aes_192_cbc EVP_aes_192_ccm @@ -1526,6 +1527,7 @@ EVP_aes_192_ctr EVP_aes_192_ecb EVP_aes_192_gcm EVP_aes_192_ofb +EVP_aes_192_wrap EVP_aes_256_cbc EVP_aes_256_cbc_hmac_sha1 EVP_aes_256_ccm @@ -1537,6 +1539,7 @@ EVP_aes_256_ctr EVP_aes_256_ecb EVP_aes_256_gcm EVP_aes_256_ofb +EVP_aes_256_wrap EVP_aes_256_xts EVP_bf_cbc EVP_bf_cfb diff --git a/src/lib/libcrypto/evp/c_all.c b/src/lib/libcrypto/evp/c_all.c index cce3640866..9e9d39d5ab 100644 --- a/src/lib/libcrypto/evp/c_all.c +++ b/src/lib/libcrypto/evp/c_all.c @@ -1,4 +1,4 @@ -/* $OpenBSD: c_all.c,v 1.25 2019/03/17 17:42:37 tb Exp $ */ +/* $OpenBSD: c_all.c,v 1.26 2019/03/17 18:07:41 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -159,6 +159,7 @@ OpenSSL_add_all_ciphers_internal(void) EVP_add_cipher(EVP_aes_128_ofb()); EVP_add_cipher(EVP_aes_128_ctr()); EVP_add_cipher(EVP_aes_128_gcm()); + EVP_add_cipher(EVP_aes_128_wrap()); EVP_add_cipher(EVP_aes_128_xts()); EVP_add_cipher_alias(SN_aes_128_cbc, "AES128"); EVP_add_cipher_alias(SN_aes_128_cbc, "aes128"); @@ -171,6 +172,7 @@ OpenSSL_add_all_ciphers_internal(void) EVP_add_cipher(EVP_aes_192_ofb()); EVP_add_cipher(EVP_aes_192_ctr()); EVP_add_cipher(EVP_aes_192_gcm()); + EVP_add_cipher(EVP_aes_192_wrap()); EVP_add_cipher_alias(SN_aes_192_cbc, "AES192"); EVP_add_cipher_alias(SN_aes_192_cbc, "aes192"); EVP_add_cipher(EVP_aes_256_ecb()); @@ -182,6 +184,7 @@ OpenSSL_add_all_ciphers_internal(void) EVP_add_cipher(EVP_aes_256_ofb()); EVP_add_cipher(EVP_aes_256_ctr()); EVP_add_cipher(EVP_aes_256_gcm()); + EVP_add_cipher(EVP_aes_256_wrap()); EVP_add_cipher(EVP_aes_256_xts()); EVP_add_cipher_alias(SN_aes_256_cbc, "AES256"); EVP_add_cipher_alias(SN_aes_256_cbc, "aes256"); diff --git a/src/lib/libcrypto/evp/e_aes.c b/src/lib/libcrypto/evp/e_aes.c index 7c713db026..6b455dc503 100644 --- a/src/lib/libcrypto/evp/e_aes.c +++ b/src/lib/libcrypto/evp/e_aes.c @@ -1,4 +1,4 @@ -/* $OpenBSD: e_aes.c,v 1.34 2017/05/02 03:59:44 deraadt Exp $ */ +/* $OpenBSD: e_aes.c,v 1.35 2019/03/17 18:07:41 tb Exp $ */ /* ==================================================================== * Copyright (c) 2001-2011 The OpenSSL Project. All rights reserved. * @@ -49,6 +49,7 @@ * */ +#include #include #include @@ -1549,4 +1550,147 @@ EVP_aead_aes_256_gcm(void) return &aead_aes_256_gcm; } +typedef struct { + union { + double align; + AES_KEY ks; + } ks; + unsigned char *iv; +} EVP_AES_WRAP_CTX; + +static int +aes_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_AES_WRAP_CTX *wctx = (EVP_AES_WRAP_CTX *)ctx->cipher_data; + + if (iv == NULL && key == NULL) + return 1; + + if (key != NULL) { + if (ctx->encrypt) + AES_set_encrypt_key(key, 8 * ctx->key_len, + &wctx->ks.ks); + else + AES_set_decrypt_key(key, 8 * ctx->key_len, + &wctx->ks.ks); + + if (iv == NULL) + wctx->iv = NULL; + } + + if (iv != NULL) { + memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx)); + wctx->iv = ctx->iv; + } + + return 1; +} + +static int +aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inlen) +{ + EVP_AES_WRAP_CTX *wctx = ctx->cipher_data; + int ret; + + if (in == NULL) + return 0; + + if (inlen % 8 != 0) + return -1; + if (ctx->encrypt && inlen < 8) + return -1; + if (!ctx->encrypt && inlen < 16) + return -1; + if (inlen > INT_MAX) + return -1; + + if (out == NULL) { + if (ctx->encrypt) + return inlen + 8; + else + return inlen - 8; + } + + if (ctx->encrypt) + ret = AES_wrap_key(&wctx->ks.ks, wctx->iv, out, in, + (unsigned int)inlen); + else + ret = AES_unwrap_key(&wctx->ks.ks, wctx->iv, out, in, + (unsigned int)inlen); + + return ret != 0 ? ret : -1; +} + +#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 ) + +static const EVP_CIPHER aes_128_wrap = { + .nid = NID_id_aes128_wrap, + .block_size = 8, + .key_len = 16, + .iv_len = 8, + .flags = WRAP_FLAGS, + .init = aes_wrap_init_key, + .do_cipher = aes_wrap_cipher, + .cleanup = NULL, + .ctx_size = sizeof(EVP_AES_WRAP_CTX), + .set_asn1_parameters = NULL, + .get_asn1_parameters = NULL, + .ctrl = NULL, + .app_data = NULL, +}; + +const EVP_CIPHER * +EVP_aes_128_wrap(void) +{ + return &aes_128_wrap; +} + +static const EVP_CIPHER aes_192_wrap = { + .nid = NID_id_aes192_wrap, + .block_size = 8, + .key_len = 24, + .iv_len = 8, + .flags = WRAP_FLAGS, + .init = aes_wrap_init_key, + .do_cipher = aes_wrap_cipher, + .cleanup = NULL, + .ctx_size = sizeof(EVP_AES_WRAP_CTX), + .set_asn1_parameters = NULL, + .get_asn1_parameters = NULL, + .ctrl = NULL, + .app_data = NULL, +}; + +const EVP_CIPHER * +EVP_aes_192_wrap(void) +{ + return &aes_192_wrap; +} + +static const EVP_CIPHER aes_256_wrap = { + .nid = NID_id_aes256_wrap, + .block_size = 8, + .key_len = 32, + .iv_len = 8, + .flags = WRAP_FLAGS, + .init = aes_wrap_init_key, + .do_cipher = aes_wrap_cipher, + .cleanup = NULL, + .ctx_size = sizeof(EVP_AES_WRAP_CTX), + .set_asn1_parameters = NULL, + .get_asn1_parameters = NULL, + .ctrl = NULL, + .app_data = NULL, +}; + +const EVP_CIPHER * +EVP_aes_256_wrap(void) +{ + return &aes_256_wrap; +} + #endif diff --git a/src/lib/libcrypto/evp/evp.h b/src/lib/libcrypto/evp/evp.h index cd9b33c9b8..22876f9fe9 100644 --- a/src/lib/libcrypto/evp/evp.h +++ b/src/lib/libcrypto/evp/evp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: evp.h,v 1.73 2019/03/17 17:42:37 tb Exp $ */ +/* $OpenBSD: evp.h,v 1.74 2019/03/17 18:07:41 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -325,6 +325,7 @@ struct evp_cipher_st { #define EVP_CIPH_GCM_MODE 0x6 #define EVP_CIPH_CCM_MODE 0x7 #define EVP_CIPH_XTS_MODE 0x10001 +#define EVP_CIPH_WRAP_MODE 0x10002 #define EVP_CIPH_MODE 0xF0007 /* Set if variable length cipher */ #define EVP_CIPH_VARIABLE_LENGTH 0x8 @@ -356,6 +357,12 @@ struct evp_cipher_st { #define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x100000 #define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000 +/* + * Cipher context flag to indicate that we can handle wrap mode: if allowed in + * older applications, it could overflow buffers. + */ +#define EVP_CIPHER_CTX_FLAG_WRAP_ALLOW 0x1 + /* ctrl() values */ #define EVP_CTRL_INIT 0x0 @@ -776,6 +783,7 @@ const EVP_CIPHER *EVP_aes_128_ofb(void); const EVP_CIPHER *EVP_aes_128_ctr(void); const EVP_CIPHER *EVP_aes_128_ccm(void); const EVP_CIPHER *EVP_aes_128_gcm(void); +const EVP_CIPHER *EVP_aes_128_wrap(void); const EVP_CIPHER *EVP_aes_128_xts(void); const EVP_CIPHER *EVP_aes_192_ecb(void); const EVP_CIPHER *EVP_aes_192_cbc(void); @@ -787,6 +795,7 @@ const EVP_CIPHER *EVP_aes_192_ofb(void); const EVP_CIPHER *EVP_aes_192_ctr(void); const EVP_CIPHER *EVP_aes_192_ccm(void); const EVP_CIPHER *EVP_aes_192_gcm(void); +const EVP_CIPHER *EVP_aes_192_wrap(void); const EVP_CIPHER *EVP_aes_256_ecb(void); const EVP_CIPHER *EVP_aes_256_cbc(void); const EVP_CIPHER *EVP_aes_256_cfb1(void); @@ -797,6 +806,7 @@ const EVP_CIPHER *EVP_aes_256_ofb(void); const EVP_CIPHER *EVP_aes_256_ctr(void); const EVP_CIPHER *EVP_aes_256_ccm(void); const EVP_CIPHER *EVP_aes_256_gcm(void); +const EVP_CIPHER *EVP_aes_256_wrap(void); const EVP_CIPHER *EVP_aes_256_xts(void); #if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1) const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void); @@ -1523,6 +1533,7 @@ void ERR_load_EVP_strings(void); #define EVP_R_UNSUPPORTED_KEY_SIZE 108 #define EVP_R_UNSUPPORTED_PRF 125 #define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 118 +#define EVP_R_WRAP_MODE_NOT_ALLOWED 170 #define EVP_R_UNSUPPORTED_SALT_TYPE 126 #define EVP_R_WRONG_FINAL_BLOCK_LENGTH 109 #define EVP_R_WRONG_PUBLIC_KEY_TYPE 110 diff --git a/src/lib/libcrypto/evp/evp_enc.c b/src/lib/libcrypto/evp/evp_enc.c index db2deb6905..a229901956 100644 --- a/src/lib/libcrypto/evp/evp_enc.c +++ b/src/lib/libcrypto/evp/evp_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: evp_enc.c,v 1.39 2018/04/14 07:09:21 tb Exp $ */ +/* $OpenBSD: evp_enc.c,v 1.40 2019/03/17 18:07:41 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -153,7 +153,7 @@ EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, ctx->cipher_data = NULL; } ctx->key_len = cipher->key_len; - ctx->flags = 0; + ctx->flags &= EVP_CIPHER_CTX_FLAG_WRAP_ALLOW; if (ctx->cipher->flags & EVP_CIPH_CTRL_INIT) { if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) { EVPerror(EVP_R_INITIALIZATION_ERROR); @@ -175,6 +175,12 @@ skip_to_init: return 0; } + if (!(ctx->flags & EVP_CIPHER_CTX_FLAG_WRAP_ALLOW) && + EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_WRAP_MODE) { + EVPerror(EVP_R_WRAP_MODE_NOT_ALLOWED); + return 0; + } + if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) { switch (EVP_CIPHER_CTX_mode(ctx)) { diff --git a/src/lib/libcrypto/evp/evp_err.c b/src/lib/libcrypto/evp/evp_err.c index 1e1cc8350b..814637c739 100644 --- a/src/lib/libcrypto/evp/evp_err.c +++ b/src/lib/libcrypto/evp/evp_err.c @@ -1,4 +1,4 @@ -/* $OpenBSD: evp_err.c,v 1.22 2017/01/29 17:49:23 beck Exp $ */ +/* $OpenBSD: evp_err.c,v 1.23 2019/03/17 18:07:41 tb Exp $ */ /* ==================================================================== * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. * @@ -147,6 +147,7 @@ static ERR_STRING_DATA EVP_str_reasons[] = { {ERR_REASON(EVP_R_UNSUPPORTED_PRF) , "unsupported prf"}, {ERR_REASON(EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM), "unsupported private key algorithm"}, {ERR_REASON(EVP_R_UNSUPPORTED_SALT_TYPE) , "unsupported salt type"}, + {ERR_REASON(EVP_R_WRAP_MODE_NOT_ALLOWED), "wrap mode not allowed"}, {ERR_REASON(EVP_R_WRONG_FINAL_BLOCK_LENGTH), "wrong final block length"}, {ERR_REASON(EVP_R_WRONG_PUBLIC_KEY_TYPE) , "wrong public key type"}, {0, NULL} -- cgit v1.2.3-55-g6feb