changeset 8288:ebd5c71b9f02 quic

Got rid of memory allocation in decryption. Static buffers are used instead in functions where decryption takes place. The pkt->plaintext points to the beginning of a static buffer. The pkt->payload.data points to decrypted data actual start.
author Vladimir Homutov <vl@nginx.com>
date Thu, 26 Mar 2020 16:54:46 +0300
parents ccb9cc95ad5e
children 949b95e4d504
files src/event/ngx_event_quic.c src/event/ngx_event_quic_protection.c src/event/ngx_event_quic_protection.h src/event/ngx_event_quic_transport.h
diffstat 4 files changed, 34 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/ngx_event_quic.c
+++ b/src/event/ngx_event_quic.c
@@ -377,6 +377,7 @@ ngx_quic_new_connection(ngx_connection_t
 {
     ngx_quic_tp_t          *ctp;
     ngx_quic_connection_t  *qc;
+    static u_char           buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE];
 
     if (ngx_buf_size(pkt->raw) < 1200) {
         ngx_log_error(NGX_LOG_INFO, c->log, 0, "too small UDP datagram");
@@ -448,8 +449,9 @@ ngx_quic_new_connection(ngx_connection_t
 
     pkt->secret = &qc->secrets.client.in;
     pkt->level = ssl_encryption_initial;
+    pkt->plaintext = buf;
 
-    if (ngx_quic_decrypt(c->pool, NULL, pkt) != NGX_OK) {
+    if (ngx_quic_decrypt(pkt, NULL) != NGX_OK) {
         return NGX_ERROR;
     }
 
@@ -532,8 +534,7 @@ ngx_quic_input_handler(ngx_event_t *rev)
     ngx_buf_t               b;
     ngx_connection_t       *c;
     ngx_quic_connection_t  *qc;
-
-    static u_char      buf[65535];
+    static u_char           buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE];
 
     b.start = buf;
     b.end = buf + sizeof(buf);
@@ -719,6 +720,7 @@ ngx_quic_initial_input(ngx_connection_t 
 {
     ngx_ssl_conn_t         *ssl_conn;
     ngx_quic_connection_t  *qc;
+    static u_char           buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE];
 
     c->log->action = "processing initial quic packet";
 
@@ -735,8 +737,9 @@ ngx_quic_initial_input(ngx_connection_t 
 
     pkt->secret = &qc->secrets.client.in;
     pkt->level = ssl_encryption_initial;
+    pkt->plaintext = buf;
 
-    if (ngx_quic_decrypt(c->pool, ssl_conn, pkt) != NGX_OK) {
+    if (ngx_quic_decrypt(pkt, ssl_conn) != NGX_OK) {
         return NGX_ERROR;
     }
 
@@ -748,6 +751,7 @@ static ngx_int_t
 ngx_quic_handshake_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
 {
     ngx_quic_connection_t  *qc;
+    static u_char           buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE];
 
     c->log->action = "processing handshake quic packet";
 
@@ -790,8 +794,9 @@ ngx_quic_handshake_input(ngx_connection_
 
     pkt->secret = &qc->secrets.client.hs;
     pkt->level = ssl_encryption_handshake;
+    pkt->plaintext = buf;
 
-    if (ngx_quic_decrypt(c->pool, c->ssl->connection, pkt) != NGX_OK) {
+    if (ngx_quic_decrypt(pkt, c->ssl->connection) != NGX_OK) {
         return NGX_ERROR;
     }
 
@@ -803,6 +808,7 @@ static ngx_int_t
 ngx_quic_app_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
 {
     ngx_quic_connection_t  *qc;
+    static u_char           buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE];
 
     c->log->action = "processing application data quic packet";
 
@@ -820,8 +826,9 @@ ngx_quic_app_input(ngx_connection_t *c, 
 
     pkt->secret = &qc->secrets.client.ad;
     pkt->level = ssl_encryption_application;
+    pkt->plaintext = buf;
 
-    if (ngx_quic_decrypt(c->pool, c->ssl->connection, pkt) != NGX_OK) {
+    if (ngx_quic_decrypt(pkt, c->ssl->connection) != NGX_OK) {
         return NGX_ERROR;
     }
 
@@ -1374,7 +1381,7 @@ ngx_quic_send_packet(ngx_connection_t *c
 {
     ngx_str_t          res;
     ngx_quic_header_t  pkt;
-    static u_char      buf[65535];
+    static u_char      buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE];
 
     static ngx_str_t  initial_token = ngx_null_string;
 
--- a/src/event/ngx_event_quic_protection.c
+++ b/src/event/ngx_event_quic_protection.c
@@ -40,7 +40,7 @@ static uint64_t ngx_quic_parse_pn(u_char
 static ngx_int_t ngx_quic_ciphers(ngx_ssl_conn_t *ssl_conn,
     ngx_quic_ciphers_t *ciphers, enum ssl_encryption_level_t level);
 
-static ngx_int_t ngx_quic_tls_open(ngx_pool_t *pool, const ngx_quic_cipher_t *cipher,
+static ngx_int_t ngx_quic_tls_open(const ngx_quic_cipher_t *cipher,
     ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_str_t *in,
     ngx_str_t *ad, ngx_log_t *log);
 static ngx_int_t ngx_quic_tls_seal(const ngx_quic_cipher_t *cipher,
@@ -356,15 +356,10 @@ ngx_hkdf_extract(u_char *out_key, size_t
 
 
 static ngx_int_t
-ngx_quic_tls_open(ngx_pool_t *pool, const ngx_quic_cipher_t *cipher,
-    ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_str_t *in,
-    ngx_str_t *ad, ngx_log_t *log)
+ngx_quic_tls_open(const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s,
+    ngx_str_t *out, u_char *nonce, ngx_str_t *in, ngx_str_t *ad,
+    ngx_log_t *log)
 {
-    out->len = in->len - EVP_GCM_TLS_TAG_LEN;
-    out->data = ngx_pnalloc(pool, out->len);
-    if (out->data == NULL) {
-        return NGX_ERROR;
-    }
 
 #ifdef OPENSSL_IS_BORINGSSL
     EVP_AEAD_CTX  *ctx;
@@ -819,16 +814,14 @@ ngx_quic_encrypt(ngx_quic_header_t *pkt,
 
 
 ngx_int_t
-ngx_quic_decrypt(ngx_pool_t *pool, ngx_ssl_conn_t *ssl_conn,
-    ngx_quic_header_t *pkt)
+ngx_quic_decrypt(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn)
 {
     u_char               clearflags, *p, *sample;
-    uint8_t             *nonce;
     uint64_t             pn;
     ngx_int_t            pnl, rc;
     ngx_str_t            in, ad;
     ngx_quic_ciphers_t   ciphers;
-    uint8_t              mask[16];
+    uint8_t              mask[16], nonce[12];
 
     if (ngx_quic_ciphers(ssl_conn, &ciphers, pkt->level) == NGX_ERROR) {
         return NGX_ERROR;
@@ -884,10 +877,7 @@ ngx_quic_decrypt(ngx_pool_t *pool, ngx_s
     }
 
     ad.len = p - pkt->data;
-    ad.data = ngx_pnalloc(pool, ad.len);
-    if (ad.data == NULL) {
-        return NGX_ERROR;
-    }
+    ad.data = pkt->plaintext;
 
     ngx_memcpy(ad.data, pkt->data, ad.len);
     ad.data[0] = clearflags;
@@ -896,13 +886,21 @@ ngx_quic_decrypt(ngx_pool_t *pool, ngx_s
         ad.data[ad.len - pnl] = pn >> (8 * (pnl - 1)) % 256;
     } while (--pnl);
 
-    nonce = ngx_pstrdup(pool, &pkt->secret->iv);
+    ngx_memcpy(nonce, pkt->secret->iv.data, pkt->secret->iv.len);
     nonce[11] ^= pn;
 
     ngx_quic_hexdump0(pkt->log, "nonce", nonce, 12);
     ngx_quic_hexdump0(pkt->log, "ad", ad.data, ad.len);
 
-    rc = ngx_quic_tls_open(pool, ciphers.c, pkt->secret, &pkt->payload,
+    pkt->payload.len = in.len - EVP_GCM_TLS_TAG_LEN;
+
+    if (NGX_QUIC_DEFAULT_MAX_PACKET_SIZE - ad.len < pkt->payload.len) {
+        return NGX_ERROR;
+    }
+
+    pkt->payload.data = pkt->plaintext + ad.len;
+
+    rc = ngx_quic_tls_open(ciphers.c, pkt->secret, &pkt->payload,
                            nonce, &in, &ad, pkt->log);
 
     ngx_quic_hexdump0(pkt->log, "packet payload",
--- a/src/event/ngx_event_quic_protection.h
+++ b/src/event/ngx_event_quic_protection.h
@@ -39,8 +39,7 @@ int ngx_quic_set_encryption_secret(ngx_p
 ssize_t ngx_quic_encrypt(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn,
      ngx_str_t *res);
 
-ngx_int_t ngx_quic_decrypt(ngx_pool_t *pool, ngx_ssl_conn_t *ssl_conn,
-    ngx_quic_header_t *pkt);
+ngx_int_t ngx_quic_decrypt(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn);
 
 
 #endif /* _NGX_EVENT_QUIC_PROTECTION_H_INCLUDED_ */
--- a/src/event/ngx_event_quic_transport.h
+++ b/src/event/ngx_event_quic_transport.h
@@ -249,7 +249,8 @@ typedef struct {
     ngx_str_t                                   dcid;
     ngx_str_t                                   scid;
     uint64_t                                    pn;
-    ngx_str_t                                   payload;  /* decrypted */
+    u_char                                     *plaintext;
+    ngx_str_t                                   payload; /* decrypted data */
 } ngx_quic_header_t;