Latest update - GitHub fd0848b (1.29.3)
This commit is contained in:
+410
-10
@@ -9,6 +9,10 @@
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
|
||||
#if (NGX_ZLIB && defined TLSEXT_cert_compression_zlib)
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define NGX_SSL_PASSWORD_BUFFER_SIZE 4096
|
||||
|
||||
@@ -19,6 +23,13 @@ typedef struct {
|
||||
|
||||
|
||||
static ngx_inline ngx_int_t ngx_ssl_cert_already_in_hash(void);
|
||||
#if (NGX_ZLIB && defined TLSEXT_cert_compression_zlib)
|
||||
static int ngx_ssl_cert_compression_callback(ngx_ssl_conn_t *ssl_conn,
|
||||
CBB *out, const uint8_t *in, size_t in_len);
|
||||
static void *ngx_ssl_cert_compression_alloc(void *opaque, u_int items,
|
||||
u_int size);
|
||||
static void ngx_ssl_cert_compression_free(void *opaque, void *address);
|
||||
#endif
|
||||
static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
|
||||
static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
|
||||
int ret);
|
||||
@@ -128,6 +139,8 @@ int ngx_ssl_ticket_keys_index;
|
||||
int ngx_ssl_ocsp_index;
|
||||
int ngx_ssl_index;
|
||||
int ngx_ssl_certificate_name_index;
|
||||
int ngx_ssl_certificate_comp_index;
|
||||
int ngx_ssl_client_hello_arg_index;
|
||||
|
||||
|
||||
u_char ngx_ssl_session_buffer[NGX_SSL_MAX_SESSION_SIZE];
|
||||
@@ -270,6 +283,21 @@ ngx_ssl_init(ngx_log_t *log)
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_ssl_certificate_comp_index = X509_get_ex_new_index(0, NULL, NULL, NULL,
|
||||
NULL);
|
||||
if (ngx_ssl_certificate_comp_index == -1) {
|
||||
ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_ssl_client_hello_arg_index = SSL_CTX_get_ex_new_index(0, NULL, NULL,
|
||||
NULL, NULL);
|
||||
if (ngx_ssl_client_hello_arg_index == -1) {
|
||||
ngx_ssl_error(NGX_LOG_ALERT, log, 0,
|
||||
"SSL_CTX_get_ex_new_index() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
@@ -449,10 +477,18 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
|
||||
{
|
||||
char *err;
|
||||
X509 *x509, **elm;
|
||||
u_long n;
|
||||
EVP_PKEY *pkey;
|
||||
ngx_uint_t mask;
|
||||
STACK_OF(X509) *chain;
|
||||
|
||||
chain = ngx_ssl_cache_fetch(cf, NGX_SSL_CACHE_CERT, &err, cert, NULL);
|
||||
mask = 0;
|
||||
elm = NULL;
|
||||
|
||||
retry:
|
||||
|
||||
chain = ngx_ssl_cache_fetch(cf, NGX_SSL_CACHE_CERT | mask,
|
||||
&err, cert, NULL);
|
||||
if (chain == NULL) {
|
||||
if (err != NULL) {
|
||||
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
|
||||
@@ -492,11 +528,16 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
|
||||
}
|
||||
}
|
||||
|
||||
elm = ngx_array_push(&ssl->certs);
|
||||
if (elm == NULL) {
|
||||
X509_free(x509);
|
||||
sk_X509_pop_free(chain, X509_free);
|
||||
return NGX_ERROR;
|
||||
elm = ngx_array_push(&ssl->certs);
|
||||
if (elm == NULL) {
|
||||
X509_free(x509);
|
||||
sk_X509_pop_free(chain, X509_free);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
} else {
|
||||
X509_free(*elm);
|
||||
}
|
||||
|
||||
*elm = x509;
|
||||
@@ -519,11 +560,21 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
|
||||
}
|
||||
|
||||
#else
|
||||
{
|
||||
int n;
|
||||
|
||||
/* SSL_CTX_set0_chain() is only available in OpenSSL 1.0.2+ */
|
||||
|
||||
#ifdef SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS
|
||||
/* OpenSSL 1.0.1+ */
|
||||
SSL_CTX_clear_extra_chain_certs(ssl->ctx);
|
||||
#else
|
||||
|
||||
if (ssl->ctx->extra_certs) {
|
||||
sk_X509_pop_free(ssl->ctx->extra_certs, X509_free);
|
||||
ssl->ctx->extra_certs = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
n = sk_X509_num(chain);
|
||||
|
||||
while (n--) {
|
||||
@@ -539,10 +590,11 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
|
||||
}
|
||||
|
||||
sk_X509_free(chain);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
pkey = ngx_ssl_cache_fetch(cf, NGX_SSL_CACHE_PKEY, &err, key, passwords);
|
||||
pkey = ngx_ssl_cache_fetch(cf, NGX_SSL_CACHE_PKEY | mask,
|
||||
&err, key, passwords);
|
||||
if (pkey == NULL) {
|
||||
if (err != NULL) {
|
||||
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
|
||||
@@ -554,9 +606,23 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) {
|
||||
EVP_PKEY_free(pkey);
|
||||
|
||||
/* there can be mismatched pairs on uneven cache update */
|
||||
|
||||
n = ERR_peek_last_error();
|
||||
|
||||
if (ERR_GET_LIB(n) == ERR_LIB_X509
|
||||
&& ERR_GET_REASON(n) == X509_R_KEY_VALUES_MISMATCH
|
||||
&& mask == 0)
|
||||
{
|
||||
ERR_clear_error();
|
||||
mask = NGX_SSL_CACHE_INVALIDATE;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
|
||||
"SSL_CTX_use_PrivateKey(\"%s\") failed", key->data);
|
||||
EVP_PKEY_free(pkey);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
@@ -682,6 +748,18 @@ ngx_ssl_certificate_compression(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||
|
||||
SSL_CTX_clear_options(ssl->ctx, SSL_OP_NO_TX_CERTIFICATE_COMPRESSION);
|
||||
|
||||
#elif (NGX_ZLIB && defined TLSEXT_cert_compression_zlib)
|
||||
|
||||
if (SSL_CTX_add_cert_compression_alg(ssl->ctx, TLSEXT_cert_compression_zlib,
|
||||
ngx_ssl_cert_compression_callback,
|
||||
NULL)
|
||||
== 0)
|
||||
{
|
||||
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
|
||||
"SSL_CTX_add_cert_compression_alg() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
|
||||
@@ -694,6 +772,155 @@ ngx_ssl_certificate_compression(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_ZLIB && defined TLSEXT_cert_compression_zlib)
|
||||
|
||||
static int
|
||||
ngx_ssl_cert_compression_callback(ngx_ssl_conn_t *ssl_conn, CBB *out,
|
||||
const uint8_t *in, size_t in_len)
|
||||
{
|
||||
int rc;
|
||||
X509 *cert;
|
||||
u_char *p;
|
||||
z_stream zstream;
|
||||
ngx_str_t *comp, tmp;
|
||||
ngx_pool_t *pool;
|
||||
ngx_connection_t *c;
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
{
|
||||
SSL_CTX *ssl_ctx;
|
||||
ngx_ssl_t *ssl;
|
||||
|
||||
/* BoringSSL doesn't have certificate slots, we take the last set */
|
||||
|
||||
ssl_ctx = SSL_get_SSL_CTX(ssl_conn);
|
||||
ssl = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_index);
|
||||
cert = ((X509 **) ssl->certs.elts)[ssl->certs.nelts - 1];
|
||||
}
|
||||
#else
|
||||
|
||||
/*
|
||||
* AWS-LC saves leaf certificate in SSL to associate with SSL_CTX,
|
||||
* see https://github.com/aws/aws-lc/commit/e1ba2b3e5
|
||||
*/
|
||||
|
||||
cert = SSL_get_certificate(ssl_conn);
|
||||
|
||||
#endif
|
||||
|
||||
comp = X509_get_ex_data(cert, ngx_ssl_certificate_comp_index);
|
||||
|
||||
if (comp != NULL) {
|
||||
return CBB_add_bytes(out, comp->data, comp->len);
|
||||
}
|
||||
|
||||
c = ngx_ssl_get_connection(ssl_conn);
|
||||
|
||||
pool = ngx_create_pool(256, c->log);
|
||||
if (pool == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pool->log = c->log;
|
||||
|
||||
ngx_memzero(&zstream, sizeof(z_stream));
|
||||
|
||||
zstream.zalloc = ngx_ssl_cert_compression_alloc;
|
||||
zstream.zfree = ngx_ssl_cert_compression_free;
|
||||
zstream.opaque = pool;
|
||||
|
||||
rc = deflateInit(&zstream, Z_DEFAULT_COMPRESSION);
|
||||
|
||||
if (rc != Z_OK) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, 0, "deflateInit() failed: %d", rc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
tmp.len = deflateBound(&zstream, in_len);
|
||||
tmp.data = ngx_palloc(pool, tmp.len);
|
||||
if (tmp.data == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
zstream.next_in = (u_char *) in;
|
||||
zstream.avail_in = in_len;
|
||||
zstream.next_out = tmp.data;
|
||||
zstream.avail_out = tmp.len;
|
||||
|
||||
rc = deflate(&zstream, Z_FINISH);
|
||||
|
||||
if (rc != Z_STREAM_END) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
|
||||
"deflate(Z_FINISH) failed: %d", rc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
tmp.len -= zstream.avail_out;
|
||||
|
||||
rc = deflateEnd(&zstream);
|
||||
|
||||
if (rc != Z_OK) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, 0, "deflateEnd() failed: %d", rc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
p = ngx_alloc(sizeof(ngx_str_t) + tmp.len, c->log);
|
||||
if (p == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
comp = (ngx_str_t *) p;
|
||||
|
||||
comp->len = tmp.len;
|
||||
comp->data = p + sizeof(ngx_str_t);
|
||||
|
||||
ngx_memcpy(comp->data, tmp.data, tmp.len);
|
||||
|
||||
if (X509_set_ex_data(cert, ngx_ssl_certificate_comp_index, p) == 0) {
|
||||
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_set_ex_data() failed");
|
||||
ngx_free(p);
|
||||
}
|
||||
|
||||
rc = CBB_add_bytes(out, tmp.data, tmp.len);
|
||||
|
||||
ngx_destroy_pool(pool);
|
||||
|
||||
return rc;
|
||||
|
||||
error:
|
||||
|
||||
ngx_destroy_pool(pool);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
ngx_ssl_cert_compression_alloc(void *opaque, u_int items, u_int size)
|
||||
{
|
||||
ngx_pool_t *pool = opaque;
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pool->log, 0,
|
||||
"cert compression alloc: n:%ud s:%ud", items, size);
|
||||
|
||||
return ngx_palloc(pool, items * size);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_ssl_cert_compression_free(void *opaque, void *address)
|
||||
{
|
||||
#if 0
|
||||
ngx_pool_t *pool = opaque;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pool->log, 0,
|
||||
"cert compression free: %p", address);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
|
||||
ngx_uint_t prefer_server_ciphers)
|
||||
@@ -1645,6 +1872,118 @@ ngx_ssl_new_client_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_ssl_set_client_hello_callback(SSL_CTX *ssl_ctx,
|
||||
ngx_ssl_client_hello_arg *cb)
|
||||
{
|
||||
#ifdef SSL_CLIENT_HELLO_SUCCESS
|
||||
|
||||
SSL_CTX_set_client_hello_cb(ssl_ctx, ngx_ssl_client_hello_callback, NULL);
|
||||
SSL_CTX_set_ex_data(ssl_ctx, ngx_ssl_client_hello_arg_index, cb);
|
||||
|
||||
#elif defined OPENSSL_IS_BORINGSSL
|
||||
|
||||
SSL_CTX_set_select_certificate_cb(ssl_ctx, ngx_ssl_select_certificate);
|
||||
SSL_CTX_set_ex_data(ssl_ctx, ngx_ssl_client_hello_arg_index, cb);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef SSL_CLIENT_HELLO_SUCCESS
|
||||
|
||||
int
|
||||
ngx_ssl_client_hello_callback(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
|
||||
{
|
||||
u_char *p;
|
||||
size_t len;
|
||||
ngx_int_t rc;
|
||||
ngx_str_t host;
|
||||
ngx_connection_t *c;
|
||||
ngx_ssl_client_hello_arg *cb;
|
||||
|
||||
c = ngx_ssl_get_connection(ssl_conn);
|
||||
cb = SSL_CTX_get_ex_data(c->ssl->session_ctx,
|
||||
ngx_ssl_client_hello_arg_index);
|
||||
|
||||
if (SSL_client_hello_get0_ext(ssl_conn, TLSEXT_TYPE_server_name,
|
||||
(const unsigned char **) &p, &len)
|
||||
== 0)
|
||||
{
|
||||
ngx_str_null(&host);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 6066 mandates non-zero HostName length, we follow OpenSSL.
|
||||
* No more than one ServerName is expected.
|
||||
*/
|
||||
|
||||
if (len < 5
|
||||
|| (size_t) (p[0] << 8) + p[1] + 2 != len
|
||||
|| p[2] != TLSEXT_NAMETYPE_host_name
|
||||
|| (size_t) (p[3] << 8) + p[4] + 2 + 3 != len)
|
||||
{
|
||||
*ad = SSL_AD_DECODE_ERROR;
|
||||
return SSL_CLIENT_HELLO_ERROR;
|
||||
}
|
||||
|
||||
len -= 5;
|
||||
p += 5;
|
||||
|
||||
if (len > TLSEXT_MAXLEN_host_name || ngx_strlchr(p, p + len, '\0')) {
|
||||
*ad = SSL_AD_UNRECOGNIZED_NAME;
|
||||
return SSL_CLIENT_HELLO_ERROR;
|
||||
}
|
||||
|
||||
host.len = len;
|
||||
host.data = p;
|
||||
|
||||
done:
|
||||
|
||||
rc = cb->servername(ssl_conn, ad, &host);
|
||||
|
||||
if (rc == SSL_TLSEXT_ERR_ALERT_FATAL) {
|
||||
return SSL_CLIENT_HELLO_ERROR;
|
||||
}
|
||||
|
||||
return SSL_CLIENT_HELLO_SUCCESS;
|
||||
}
|
||||
|
||||
#elif defined OPENSSL_IS_BORINGSSL
|
||||
|
||||
enum ssl_select_cert_result_t ngx_ssl_select_certificate(
|
||||
const SSL_CLIENT_HELLO *client_hello)
|
||||
{
|
||||
int ad;
|
||||
ngx_int_t rc;
|
||||
ngx_ssl_conn_t *ssl_conn;
|
||||
ngx_connection_t *c;
|
||||
ngx_ssl_client_hello_arg *cb;
|
||||
|
||||
ssl_conn = client_hello->ssl;
|
||||
c = ngx_ssl_get_connection(ssl_conn);
|
||||
cb = SSL_CTX_get_ex_data(c->ssl->session_ctx,
|
||||
ngx_ssl_client_hello_arg_index);
|
||||
|
||||
/*
|
||||
* BoringSSL sends a hardcoded "handshake_failure" alert on errors,
|
||||
* we use it to map SSL_AD_INTERNAL_ERROR. To preserve other alert
|
||||
* values, error handling is postponed to the servername callback.
|
||||
*/
|
||||
|
||||
rc = cb->servername(ssl_conn, &ad, NULL);
|
||||
|
||||
if (rc == SSL_TLSEXT_ERR_ALERT_FATAL && ad == SSL_AD_INTERNAL_ERROR) {
|
||||
return ssl_select_cert_error;
|
||||
}
|
||||
|
||||
return ssl_select_cert_success;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
|
||||
{
|
||||
@@ -4831,10 +5170,19 @@ ngx_ssl_cleanup_ctx(void *data)
|
||||
ngx_ssl_t *ssl = data;
|
||||
|
||||
X509 *cert;
|
||||
u_char *p;
|
||||
ngx_uint_t i;
|
||||
|
||||
for (i = 0; i < ssl->certs.nelts; i++) {
|
||||
cert = ((X509 **) ssl->certs.elts)[i];
|
||||
|
||||
p = X509_get_ex_data(cert, ngx_ssl_certificate_comp_index);
|
||||
|
||||
if (p) {
|
||||
ngx_free(p);
|
||||
X509_set_ex_data(cert, ngx_ssl_certificate_comp_index, NULL);
|
||||
}
|
||||
|
||||
X509_free(cert);
|
||||
}
|
||||
|
||||
@@ -5231,6 +5579,32 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_ssl_get_sigalg(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
||||
{
|
||||
#ifdef SSL_get0_signature_name
|
||||
|
||||
const char *name;
|
||||
|
||||
if (SSL_get0_signature_name(c->ssl->connection, &name)) {
|
||||
s->len = ngx_strlen(name);
|
||||
s->data = ngx_pnalloc(pool, s->len);
|
||||
if (s->data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_memcpy(s->data, name, s->len);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
s->len = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
||||
{
|
||||
@@ -5976,6 +6350,32 @@ ngx_ssl_parse_time(
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_ssl_get_client_sigalg(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
||||
{
|
||||
#ifdef SSL_get0_peer_signature_name
|
||||
|
||||
const char *name;
|
||||
|
||||
if (SSL_get0_peer_signature_name(c->ssl->connection, &name)) {
|
||||
s->len = ngx_strlen(name);
|
||||
s->data = ngx_pnalloc(pool, s->len);
|
||||
if (s->data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_memcpy(s->data, name, s->len);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
s->len = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
ngx_openssl_create_conf(ngx_cycle_t *cycle)
|
||||
{
|
||||
|
||||
@@ -26,14 +26,6 @@
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
#include <openssl/evp.h>
|
||||
#if (NGX_QUIC)
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#include <openssl/hkdf.h>
|
||||
#include <openssl/chacha.h>
|
||||
#else
|
||||
#include <openssl/kdf.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <openssl/hmac.h>
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
#include <openssl/ocsp.h>
|
||||
@@ -161,6 +153,7 @@ struct ngx_ssl_connection_s {
|
||||
unsigned in_ocsp:1;
|
||||
unsigned early_preread:1;
|
||||
unsigned write_blocked:1;
|
||||
unsigned sni_accepted:1;
|
||||
|
||||
ngx_ssl_dyn_rec_t dyn_rec;
|
||||
ngx_msec_t dyn_rec_last_write;
|
||||
@@ -211,6 +204,13 @@ typedef struct {
|
||||
} ngx_ssl_session_cache_t;
|
||||
|
||||
|
||||
typedef int (*ngx_ssl_servername_pt)(ngx_ssl_conn_t *, int *, void *);
|
||||
|
||||
typedef struct {
|
||||
ngx_ssl_servername_pt servername;
|
||||
} ngx_ssl_client_hello_arg;
|
||||
|
||||
|
||||
#define NGX_SSL_SSLv2 0x0002
|
||||
#define NGX_SSL_SSLv3 0x0004
|
||||
#define NGX_SSL_TLSv1 0x0008
|
||||
@@ -300,6 +300,15 @@ ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||
ngx_array_t *paths);
|
||||
ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data);
|
||||
|
||||
void ngx_ssl_set_client_hello_callback(SSL_CTX *ssl_ctx,
|
||||
ngx_ssl_client_hello_arg *cb);
|
||||
#ifdef SSL_CLIENT_HELLO_SUCCESS
|
||||
int ngx_ssl_client_hello_callback(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg);
|
||||
#elif defined OPENSSL_IS_BORINGSSL
|
||||
enum ssl_select_cert_result_t ngx_ssl_select_certificate(
|
||||
const SSL_CLIENT_HELLO *client_hello);
|
||||
#endif
|
||||
|
||||
ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c,
|
||||
ngx_uint_t flags);
|
||||
|
||||
@@ -333,6 +342,8 @@ ngx_int_t ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_sigalg(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
@@ -369,6 +380,8 @@ ngx_int_t ngx_ssl_get_client_v_end(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_client_sigalg(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
ngx_str_t *s);
|
||||
|
||||
|
||||
ngx_int_t ngx_ssl_handshake(ngx_connection_t *c);
|
||||
@@ -396,6 +409,8 @@ extern int ngx_ssl_ticket_keys_index;
|
||||
extern int ngx_ssl_ocsp_index;
|
||||
extern int ngx_ssl_index;
|
||||
extern int ngx_ssl_certificate_name_index;
|
||||
extern int ngx_ssl_certificate_comp_index;
|
||||
extern int ngx_ssl_client_hello_arg_index;
|
||||
|
||||
|
||||
extern u_char ngx_ssl_session_buffer[NGX_SSL_MAX_SESSION_SIZE];
|
||||
|
||||
@@ -193,6 +193,7 @@ ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
|
||||
time_t mtime;
|
||||
uint32_t hash;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t invalidate;
|
||||
ngx_file_uniq_t uniq;
|
||||
ngx_file_info_t fi;
|
||||
ngx_ssl_cache_t *cache, *old_cache;
|
||||
@@ -202,10 +203,17 @@ ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
|
||||
|
||||
*err = NULL;
|
||||
|
||||
invalidate = index & NGX_SSL_CACHE_INVALIDATE;
|
||||
index &= ~NGX_SSL_CACHE_INVALIDATE;
|
||||
|
||||
if (ngx_ssl_cache_init_key(cf->pool, index, path, &id) != NGX_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (id.type == NGX_SSL_CACHE_DATA) {
|
||||
invalidate = 0;
|
||||
}
|
||||
|
||||
cache = (ngx_ssl_cache_t *) ngx_get_conf(cf->cycle->conf_ctx,
|
||||
ngx_openssl_cache_module);
|
||||
|
||||
@@ -215,7 +223,12 @@ ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
|
||||
cn = ngx_ssl_cache_lookup(cache, type, &id, hash);
|
||||
|
||||
if (cn != NULL) {
|
||||
return type->ref(err, cn->value);
|
||||
if (!invalidate) {
|
||||
return type->ref(err, cn->value);
|
||||
}
|
||||
|
||||
type->free(cn->value);
|
||||
ngx_rbtree_delete(&cache->rbtree, &cn->node);
|
||||
}
|
||||
|
||||
value = NULL;
|
||||
@@ -236,7 +249,7 @@ ngx_ssl_cache_fetch(ngx_conf_t *cf, ngx_uint_t index, char **err,
|
||||
|
||||
old_cache = ngx_ssl_cache_get_old_conf(cf->cycle);
|
||||
|
||||
if (old_cache && old_cache->inheritable) {
|
||||
if (old_cache && old_cache->inheritable && !invalidate) {
|
||||
cn = ngx_ssl_cache_lookup(old_cache, type, &id, hash);
|
||||
|
||||
if (cn != NULL) {
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
#elif (defined SSL_R_MISSING_QUIC_TRANSPORT_PARAMETERS_EXTENSION)
|
||||
#define NGX_QUIC_QUICTLS_API 1
|
||||
|
||||
#elif (defined OPENSSL_IS_BORINGSSL || defined LIBRESSL_VERSION_NUMBER)
|
||||
#elif (defined OPENSSL_IS_BORINGSSL || defined OPENSSL_IS_AWSLC \
|
||||
|| defined LIBRESSL_VERSION_NUMBER)
|
||||
#define NGX_QUIC_BORINGSSL_API 1
|
||||
|
||||
#else
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
#include <ngx_event_quic_connection.h>
|
||||
#if (NGX_QUIC_BORINGSSL_EVP_API)
|
||||
#include <openssl/hkdf.h>
|
||||
#include <openssl/chacha.h>
|
||||
#else
|
||||
#include <openssl/kdf.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* RFC 9001, 5.4.1. Header Protection Application: 5-byte mask */
|
||||
@@ -33,7 +39,7 @@ static uint64_t ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask,
|
||||
|
||||
static ngx_int_t ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out,
|
||||
const u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log);
|
||||
#ifndef OPENSSL_IS_BORINGSSL
|
||||
#if !(NGX_QUIC_BORINGSSL_EVP_API)
|
||||
static ngx_int_t ngx_quic_crypto_common(ngx_quic_secret_t *s, ngx_str_t *out,
|
||||
const u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log);
|
||||
#endif
|
||||
@@ -58,7 +64,7 @@ ngx_quic_ciphers(ngx_uint_t id, ngx_quic_ciphers_t *ciphers)
|
||||
switch (id) {
|
||||
|
||||
case TLS1_3_CK_AES_128_GCM_SHA256:
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (NGX_QUIC_BORINGSSL_EVP_API)
|
||||
ciphers->c = EVP_aead_aes_128_gcm();
|
||||
#else
|
||||
ciphers->c = EVP_aes_128_gcm();
|
||||
@@ -69,7 +75,7 @@ ngx_quic_ciphers(ngx_uint_t id, ngx_quic_ciphers_t *ciphers)
|
||||
break;
|
||||
|
||||
case TLS1_3_CK_AES_256_GCM_SHA384:
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (NGX_QUIC_BORINGSSL_EVP_API)
|
||||
ciphers->c = EVP_aead_aes_256_gcm();
|
||||
#else
|
||||
ciphers->c = EVP_aes_256_gcm();
|
||||
@@ -80,12 +86,12 @@ ngx_quic_ciphers(ngx_uint_t id, ngx_quic_ciphers_t *ciphers)
|
||||
break;
|
||||
|
||||
case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (NGX_QUIC_BORINGSSL_EVP_API)
|
||||
ciphers->c = EVP_aead_chacha20_poly1305();
|
||||
#else
|
||||
ciphers->c = EVP_chacha20_poly1305();
|
||||
#endif
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (NGX_QUIC_BORINGSSL_EVP_API)
|
||||
ciphers->hp = (const EVP_CIPHER *) EVP_aead_chacha20_poly1305();
|
||||
#else
|
||||
ciphers->hp = EVP_chacha20();
|
||||
@@ -94,7 +100,7 @@ ngx_quic_ciphers(ngx_uint_t id, ngx_quic_ciphers_t *ciphers)
|
||||
len = 32;
|
||||
break;
|
||||
|
||||
#ifndef OPENSSL_IS_BORINGSSL
|
||||
#if !(NGX_QUIC_BORINGSSL_EVP_API)
|
||||
case TLS1_3_CK_AES_128_CCM_SHA256:
|
||||
ciphers->c = EVP_aes_128_ccm();
|
||||
ciphers->hp = EVP_aes_128_ctr();
|
||||
@@ -263,7 +269,7 @@ static ngx_int_t
|
||||
ngx_hkdf_expand(u_char *out_key, size_t out_len, const EVP_MD *digest,
|
||||
const uint8_t *prk, size_t prk_len, const u_char *info, size_t info_len)
|
||||
{
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (NGX_QUIC_BORINGSSL_EVP_API)
|
||||
|
||||
if (HKDF_expand(out_key, out_len, digest, prk, prk_len, info, info_len)
|
||||
== 0)
|
||||
@@ -325,7 +331,7 @@ ngx_hkdf_extract(u_char *out_key, size_t *out_len, const EVP_MD *digest,
|
||||
const u_char *secret, size_t secret_len, const u_char *salt,
|
||||
size_t salt_len)
|
||||
{
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (NGX_QUIC_BORINGSSL_EVP_API)
|
||||
|
||||
if (HKDF_extract(out_key, out_len, digest, secret, secret_len, salt,
|
||||
salt_len)
|
||||
@@ -388,7 +394,7 @@ ngx_quic_crypto_init(const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s,
|
||||
ngx_quic_md_t *key, ngx_int_t enc, ngx_log_t *log)
|
||||
{
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (NGX_QUIC_BORINGSSL_EVP_API)
|
||||
EVP_AEAD_CTX *ctx;
|
||||
|
||||
ctx = EVP_AEAD_CTX_new(cipher, key->data, key->len,
|
||||
@@ -448,7 +454,7 @@ static ngx_int_t
|
||||
ngx_quic_crypto_open(ngx_quic_secret_t *s, ngx_str_t *out, const u_char *nonce,
|
||||
ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log)
|
||||
{
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (NGX_QUIC_BORINGSSL_EVP_API)
|
||||
if (EVP_AEAD_CTX_open(s->ctx, out->data, &out->len, out->len, nonce,
|
||||
s->iv.len, in->data, in->len, ad->data, ad->len)
|
||||
!= 1)
|
||||
@@ -468,7 +474,7 @@ ngx_int_t
|
||||
ngx_quic_crypto_seal(ngx_quic_secret_t *s, ngx_str_t *out, const u_char *nonce,
|
||||
ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log)
|
||||
{
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (NGX_QUIC_BORINGSSL_EVP_API)
|
||||
if (EVP_AEAD_CTX_seal(s->ctx, out->data, &out->len, out->len, nonce,
|
||||
s->iv.len, in->data, in->len, ad->data, ad->len)
|
||||
!= 1)
|
||||
@@ -484,7 +490,7 @@ ngx_quic_crypto_seal(ngx_quic_secret_t *s, ngx_str_t *out, const u_char *nonce,
|
||||
}
|
||||
|
||||
|
||||
#ifndef OPENSSL_IS_BORINGSSL
|
||||
#if !(NGX_QUIC_BORINGSSL_EVP_API)
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_crypto_common(ngx_quic_secret_t *s, ngx_str_t *out,
|
||||
@@ -563,7 +569,7 @@ void
|
||||
ngx_quic_crypto_cleanup(ngx_quic_secret_t *s)
|
||||
{
|
||||
if (s->ctx) {
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (NGX_QUIC_BORINGSSL_EVP_API)
|
||||
EVP_AEAD_CTX_free(s->ctx);
|
||||
#else
|
||||
EVP_CIPHER_CTX_free(s->ctx);
|
||||
@@ -579,7 +585,7 @@ ngx_quic_crypto_hp_init(const EVP_CIPHER *cipher, ngx_quic_secret_t *s,
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (NGX_QUIC_BORINGSSL_EVP_API)
|
||||
if (cipher == (EVP_CIPHER *) EVP_aead_chacha20_poly1305()) {
|
||||
/* no EVP interface */
|
||||
s->hp_ctx = NULL;
|
||||
@@ -615,7 +621,7 @@ ngx_quic_crypto_hp(ngx_quic_secret_t *s, u_char *out, u_char *in,
|
||||
|
||||
ctx = s->hp_ctx;
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (NGX_QUIC_BORINGSSL_EVP_API)
|
||||
uint32_t cnt;
|
||||
|
||||
if (ctx == NULL) {
|
||||
|
||||
@@ -22,10 +22,12 @@
|
||||
#define NGX_QUIC_MAX_MD_SIZE 48
|
||||
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (defined OPENSSL_IS_BORINGSSL || defined OPENSSL_IS_AWSLC)
|
||||
#define NGX_QUIC_BORINGSSL_EVP_API 1
|
||||
#define ngx_quic_cipher_t EVP_AEAD
|
||||
#define ngx_quic_crypto_ctx_t EVP_AEAD_CTX
|
||||
#else
|
||||
#define NGX_QUIC_BORINGSSL_EVP_API 0
|
||||
#define ngx_quic_cipher_t EVP_CIPHER
|
||||
#define ngx_quic_crypto_ctx_t EVP_CIPHER_CTX
|
||||
#endif
|
||||
|
||||
@@ -695,30 +695,35 @@ ngx_quic_handshake(ngx_connection_t *c)
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
|
||||
|
||||
if (qc->error) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (n <= 0) {
|
||||
sslerr = SSL_get_error(ssl_conn, n);
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d",
|
||||
sslerr);
|
||||
|
||||
if (c->ssl->handshake_rejected) {
|
||||
ngx_connection_error(c, 0, "handshake rejected");
|
||||
ERR_clear_error();
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (qc->error) {
|
||||
ngx_connection_error(c, 0, "SSL_do_handshake() failed");
|
||||
ERR_clear_error();
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (sslerr != SSL_ERROR_WANT_READ) {
|
||||
|
||||
if (c->ssl->handshake_rejected) {
|
||||
ngx_connection_error(c, 0, "handshake rejected");
|
||||
ERR_clear_error();
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_ssl_connection_error(c, sslerr, 0, "SSL_do_handshake() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (qc->error) {
|
||||
ngx_connection_error(c, 0, "SSL_do_handshake() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (!SSL_is_init_finished(ssl_conn)) {
|
||||
if (ngx_quic_keys_available(qc->keys, NGX_QUIC_ENCRYPTION_EARLY_DATA, 0)
|
||||
&& qc->client_tp_done)
|
||||
@@ -968,7 +973,7 @@ ngx_quic_init_connection(ngx_connection_t *c)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if (defined OPENSSL_IS_BORINGSSL || defined OPENSSL_IS_AWSLC)
|
||||
if (SSL_set_quic_early_data_context(ssl_conn, p, clen) == 0) {
|
||||
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
|
||||
"quic SSL_set_quic_early_data_context() failed");
|
||||
|
||||
Reference in New Issue
Block a user