[nginx] SSL: support AES256 encryption of tickets.
Maxim Dounin
mdounin at mdounin.ru
Fri Dec 23 14:51:40 UTC 2016
details: http://hg.nginx.org/nginx/rev/75e7d55214bd
branches:
changeset: 6854:75e7d55214bd
user: Maxim Dounin <mdounin at mdounin.ru>
date: Fri Dec 23 17:28:20 2016 +0300
description:
SSL: support AES256 encryption of tickets.
This implies ticket key size of 80 bytes instead of previously used 48,
as both HMAC and AES keys are 32 bytes now. When an old 48-byte ticket key
is provided, we fall back to using backward-compatible AES128 encryption.
OpenSSL switched to using AES256 in 1.1.0, and we are providing equivalent
security. While here, order of HMAC and AES keys was reverted to make
the implementation compatible with keys used by OpenSSL with
SSL_CTX_set_tlsext_ticket_keys().
Prodded by Christian Klinger.
diffstat:
src/event/ngx_event_openssl.c | 58 ++++++++++++++++++++++++++++++++----------
src/event/ngx_event_openssl.h | 5 ++-
2 files changed, 47 insertions(+), 16 deletions(-)
diffs (155 lines):
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -2856,7 +2856,8 @@ ngx_ssl_session_rbtree_insert_value(ngx_
ngx_int_t
ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
{
- u_char buf[48];
+ u_char buf[80];
+ size_t size;
ssize_t n;
ngx_str_t *path;
ngx_file_t file;
@@ -2899,13 +2900,15 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *
goto failed;
}
- if (ngx_file_size(&fi) != 48) {
+ size = ngx_file_size(&fi);
+
+ if (size != 48 && size != 80) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"%V\" must be 48 bytes", &file.name);
+ "\"%V\" must be 48 or 80 bytes", &file.name);
goto failed;
}
- n = ngx_read_file(&file, buf, 48, 0);
+ n = ngx_read_file(&file, buf, size, 0);
if (n == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
@@ -2913,10 +2916,10 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *
goto failed;
}
- if (n != 48) {
+ if ((size_t) n != size) {
ngx_conf_log_error(NGX_LOG_CRIT, cf, 0,
ngx_read_file_n " \"%V\" returned only "
- "%z bytes instead of 48", &file.name, n);
+ "%z bytes instead of %uz", &file.name, n, size);
goto failed;
}
@@ -2925,9 +2928,18 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *
goto failed;
}
- ngx_memcpy(key->name, buf, 16);
- ngx_memcpy(key->aes_key, buf + 16, 16);
- ngx_memcpy(key->hmac_key, buf + 32, 16);
+ if (size == 48) {
+ key->size = 48;
+ ngx_memcpy(key->name, buf, 16);
+ ngx_memcpy(key->aes_key, buf + 16, 16);
+ ngx_memcpy(key->hmac_key, buf + 32, 16);
+
+ } else {
+ key->size = 80;
+ ngx_memcpy(key->name, buf, 16);
+ ngx_memcpy(key->hmac_key, buf + 16, 32);
+ ngx_memcpy(key->aes_key, buf + 48, 32);
+ }
if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
@@ -2972,6 +2984,7 @@ ngx_ssl_session_ticket_key_callback(ngx_
unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
HMAC_CTX *hctx, int enc)
{
+ size_t size;
SSL_CTX *ssl_ctx;
ngx_uint_t i;
ngx_array_t *keys;
@@ -2986,7 +2999,6 @@ ngx_ssl_session_ticket_key_callback(ngx_
c = ngx_ssl_get_connection(ssl_conn);
ssl_ctx = c->ssl->session_ctx;
- cipher = EVP_aes_128_cbc();
#ifdef OPENSSL_NO_SHA256
digest = EVP_sha1();
#else
@@ -3008,6 +3020,15 @@ ngx_ssl_session_ticket_key_callback(ngx_
ngx_hex_dump(buf, key[0].name, 16) - buf, buf,
SSL_session_reused(ssl_conn) ? "reused" : "new");
+ if (key[0].size == 48) {
+ cipher = EVP_aes_128_cbc();
+ size = 16;
+
+ } else {
+ cipher = EVP_aes_256_cbc();
+ size = 32;
+ }
+
if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) != 1) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "RAND_bytes() failed");
return -1;
@@ -3020,12 +3041,12 @@ ngx_ssl_session_ticket_key_callback(ngx_
}
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- if (HMAC_Init_ex(hctx, key[0].hmac_key, 16, digest, NULL) != 1) {
+ if (HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL) != 1) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "HMAC_Init_ex() failed");
return -1;
}
#else
- HMAC_Init_ex(hctx, key[0].hmac_key, 16, digest, NULL);
+ HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL);
#endif
ngx_memcpy(name, key[0].name, 16);
@@ -3054,13 +3075,22 @@ ngx_ssl_session_ticket_key_callback(ngx_
ngx_hex_dump(buf, key[i].name, 16) - buf, buf,
(i == 0) ? " (default)" : "");
+ if (key[i].size == 48) {
+ cipher = EVP_aes_128_cbc();
+ size = 16;
+
+ } else {
+ cipher = EVP_aes_256_cbc();
+ size = 32;
+ }
+
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- if (HMAC_Init_ex(hctx, key[i].hmac_key, 16, digest, NULL) != 1) {
+ if (HMAC_Init_ex(hctx, key[i].hmac_key, size, digest, NULL) != 1) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "HMAC_Init_ex() failed");
return -1;
}
#else
- HMAC_Init_ex(hctx, key[i].hmac_key, 16, digest, NULL);
+ HMAC_Init_ex(hctx, key[i].hmac_key, size, digest, NULL);
#endif
if (EVP_DecryptInit_ex(ectx, cipher, NULL, key[i].aes_key, iv) != 1) {
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -117,9 +117,10 @@ typedef struct {
#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
typedef struct {
+ size_t size;
u_char name[16];
- u_char aes_key[16];
- u_char hmac_key[16];
+ u_char hmac_key[32];
+ u_char aes_key[32];
} ngx_ssl_session_ticket_key_t;
#endif
More information about the nginx-devel
mailing list