Skip to content

Commit

Permalink
SSL: support AES256 encryption of tickets.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mdounin committed Dec 23, 2016
1 parent f021706 commit c2d3d82
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 16 deletions.
58 changes: 44 additions & 14 deletions src/event/ngx_event_openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2856,7 +2856,8 @@ ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
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;
Expand Down Expand Up @@ -2899,24 +2900,26 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
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,
ngx_read_file_n " \"%V\" failed", &file.name);
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;
}

Expand All @@ -2925,9 +2928,18 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
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,
Expand Down Expand Up @@ -2972,6 +2984,7 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
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;
Expand All @@ -2986,7 +2999,6 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
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
Expand All @@ -3008,6 +3020,15 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
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;
Expand All @@ -3020,12 +3041,12 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
}

#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);
Expand Down Expand Up @@ -3054,13 +3075,22 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
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) {
Expand Down
5 changes: 3 additions & 2 deletions src/event/ngx_event_openssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit c2d3d82

Please sign in to comment.