comparison src/event/ngx_event_openssl.c @ 7648:b28ea685a56e quic

Moved all QUIC code into ngx_event_quic.c Introduced ngx_quic_input() and ngx_quic_output() as interface between nginx and protocol. They are the only functions that are exported. While there, added copyrights.
author Vladimir Homutov <vl@nginx.com>
date Fri, 28 Feb 2020 16:23:25 +0300
parents 3cb4f16426a5
children 253cf267f95a
comparison
equal deleted inserted replaced
7647:3cb4f16426a5 7648:b28ea685a56e
88 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); 88 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
89 static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 89 static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
90 static void ngx_openssl_exit(ngx_cycle_t *cycle); 90 static void ngx_openssl_exit(ngx_cycle_t *cycle);
91 91
92 92
93 #if NGX_OPENSSL_QUIC
94
95 static int
96 quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
97 enum ssl_encryption_level_t level, const uint8_t *read_secret,
98 const uint8_t *write_secret, size_t secret_len)
99 {
100 u_char *name;
101 ngx_uint_t i;
102 const EVP_MD *digest;
103 const EVP_CIPHER *cipher;
104 ngx_connection_t *c;
105 ngx_quic_secret_t *client, *server;
106
107 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
108
109 ngx_ssl_handshake_log(c);
110
111 #if (NGX_DEBUG)
112 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) {
113 u_char buf[64];
114 size_t m;
115
116 m = ngx_hex_dump(buf, (u_char *) read_secret, secret_len) - buf;
117 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
118 "set_encryption_secrets: read %*s, len: %uz, level:%d",
119 m, buf, secret_len, (int) level);
120
121 m = ngx_hex_dump(buf, (u_char *) write_secret, secret_len) - buf;
122 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
123 "set_encryption_secrets: write %*s, len: %uz, level:%d",
124 m, buf, secret_len, (int) level);
125 }
126 #endif
127
128 name = (u_char *) SSL_get_cipher(ssl_conn);
129
130 if (ngx_strcasecmp(name, (u_char *) "TLS_AES_128_GCM_SHA256") == 0
131 || ngx_strcasecmp(name, (u_char *) "(NONE)") == 0)
132 {
133 cipher = EVP_aes_128_gcm();
134 digest = EVP_sha256();
135
136 } else if (ngx_strcasecmp(name, (u_char *) "TLS_AES_256_GCM_SHA384") == 0) {
137 cipher = EVP_aes_256_gcm();
138 digest = EVP_sha384();
139
140 } else {
141 ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "unexpected cipher");
142 return 0;
143 }
144
145 switch (level) {
146
147 case ssl_encryption_handshake:
148 client = &c->quic->client_hs;
149 server = &c->quic->server_hs;
150
151 break;
152
153 case ssl_encryption_application:
154 client = &c->quic->client_ad;
155 server = &c->quic->server_ad;
156
157 break;
158
159 default:
160 return 0;
161 }
162
163 client->key.len = EVP_CIPHER_key_length(cipher);
164 server->key.len = EVP_CIPHER_key_length(cipher);
165
166 client->iv.len = EVP_CIPHER_iv_length(cipher);
167 server->iv.len = EVP_CIPHER_iv_length(cipher);
168
169 client->hp.len = EVP_CIPHER_key_length(cipher);
170 server->hp.len = EVP_CIPHER_key_length(cipher);
171
172 struct {
173 ngx_str_t label;
174 ngx_str_t *key;
175 const uint8_t *secret;
176 } seq[] = {
177 { ngx_string("tls13 quic key"), &client->key, read_secret },
178 { ngx_string("tls13 quic iv"), &client->iv, read_secret },
179 { ngx_string("tls13 quic hp"), &client->hp, read_secret },
180 { ngx_string("tls13 quic key"), &server->key, write_secret },
181 { ngx_string("tls13 quic iv"), &server->iv, write_secret },
182 { ngx_string("tls13 quic hp"), &server->hp, write_secret },
183 };
184
185 for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) {
186
187 if (ngx_quic_hkdf_expand(c, digest, seq[i].key, &seq[i].label,
188 seq[i].secret, secret_len)
189 != NGX_OK)
190 {
191 return 0;
192 }
193 }
194
195 return 1;
196 }
197
198
199 static int
200 quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
201 enum ssl_encryption_level_t level, const uint8_t *data, size_t len)
202 {
203 u_char *p, *pnp, *name, *nonce, *sample;
204 ngx_int_t m;
205 ngx_str_t in, out, ad;
206 static int pn;
207 const EVP_CIPHER *cipher;
208 ngx_connection_t *c;
209 ngx_quic_secret_t *secret;
210 ngx_quic_connection_t *qc;
211 u_char buf[2048], mask[16];
212
213 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
214 qc = c->quic;
215
216 ngx_ssl_handshake_log(c);
217
218 switch (level) {
219
220 case ssl_encryption_initial:
221 secret = &qc->server_in;
222 break;
223
224 case ssl_encryption_handshake:
225 secret = &qc->server_hs;
226 break;
227
228 default:
229 return 0;
230 }
231
232 m = ngx_hex_dump(buf, (u_char *) data, ngx_min(len, 1024)) - buf;
233 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
234 "quic_add_handshake_data: %*s%s, len: %uz, level:%d",
235 m, buf, len < 2048 ? "" : "...", len, (int) level);
236
237 in.data = ngx_alloc(4 + len + 5 /*minimal ACK*/, c->log);
238 if (in.data == 0) {
239 return 0;
240 }
241
242 p = in.data;
243 ngx_quic_build_int(&p, 6); // crypto frame
244 ngx_quic_build_int(&p, 0);
245 ngx_quic_build_int(&p, len);
246 p = ngx_cpymem(p, data, len);
247
248 if (level == ssl_encryption_initial) {
249 ngx_quic_build_int(&p, 2); // ack frame
250 ngx_quic_build_int(&p, 0);
251 ngx_quic_build_int(&p, 0);
252 ngx_quic_build_int(&p, 0);
253 ngx_quic_build_int(&p, 0);
254 }
255
256 in.len = p - in.data;
257 out.len = in.len + EVP_GCM_TLS_TAG_LEN;
258
259 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
260 "quic_add_handshake_data: clear_len:%uz, ciphertext_len:%uz",
261 in.len, out.len);
262
263 ad.data = ngx_alloc(346 /*max header*/, c->log);
264 if (ad.data == 0) {
265 return 0;
266 }
267
268 p = ad.data;
269 if (level == ssl_encryption_initial) {
270 *p++ = 0xc0; // initial, packet number len
271 } else if (level == ssl_encryption_handshake) {
272 *p++ = 0xe0; // handshake, packet number len
273 }
274 p = ngx_quic_write_uint32(p, quic_version);
275 *p++ = qc->scid.len;
276 p = ngx_cpymem(p, qc->scid.data, qc->scid.len);
277 *p++ = qc->dcid.len;
278 p = ngx_cpymem(p, qc->dcid.data, qc->dcid.len);
279 if (level == ssl_encryption_initial) {
280 ngx_quic_build_int(&p, 0); // token length
281 }
282 ngx_quic_build_int(&p, out.len + 1); // length (inc. pnl)
283 pnp = p;
284
285 if (level == ssl_encryption_initial) {
286 *p++ = 0; // packet number 0
287
288 } else if (level == ssl_encryption_handshake) {
289 *p++ = pn++;
290 }
291
292 ad.len = p - ad.data;
293
294 m = ngx_hex_dump(buf, ad.data, ad.len) - buf;
295 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
296 "quic_add_handshake_data ad: %*s, len: %uz",
297 m, buf, ad.len);
298
299
300 name = (u_char *) SSL_get_cipher(ssl_conn);
301
302 if (ngx_strcasecmp(name, (u_char *) "TLS_AES_128_GCM_SHA256") == 0
303 || ngx_strcasecmp(name, (u_char *) "(NONE)") == 0)
304 {
305 cipher = EVP_aes_128_gcm();
306
307 } else if (ngx_strcasecmp(name, (u_char *) "TLS_AES_256_GCM_SHA384") == 0) {
308 cipher = EVP_aes_256_gcm();
309
310 } else {
311 return 0;
312 }
313
314 nonce = ngx_pstrdup(c->pool, &secret->iv);
315 if (level == ssl_encryption_handshake) {
316 nonce[11] ^= (pn - 1);
317 }
318
319 m = ngx_hex_dump(buf, (u_char *) secret->iv.data, 12) - buf;
320 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
321 "quic_add_handshake_data sample: server_iv %*s",
322 m, buf);
323 m = ngx_hex_dump(buf, (u_char *) nonce, 12) - buf;
324 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
325 "quic_add_handshake_data sample: n=%d nonce %*s",
326 pn - 1, m, buf);
327
328 if (ngx_quic_tls_seal(c, cipher, secret, &out, nonce, &in, &ad) != NGX_OK)
329 {
330 return 0;
331 }
332
333 sample = &out.data[3]; // pnl=0
334 if (ngx_quic_tls_hp(c, EVP_aes_128_ecb(), secret, mask, sample) != NGX_OK) {
335 return 0;
336 }
337
338 m = ngx_hex_dump(buf, (u_char *) sample, 16) - buf;
339 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
340 "quic_add_handshake_data sample: %*s, len: %uz",
341 m, buf, 16);
342
343 m = ngx_hex_dump(buf, (u_char *) mask, 16) - buf;
344 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
345 "quic_add_handshake_data mask: %*s, len: %uz",
346 m, buf, 16);
347
348 m = ngx_hex_dump(buf, (u_char *) secret->hp.data, 16) - buf;
349 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
350 "quic_add_handshake_data hp_key: %*s, len: %uz",
351 m, buf, 16);
352
353 // header protection, pnl = 0
354 ad.data[0] ^= mask[0] & 0x0f;
355 *pnp ^= mask[1];
356
357 u_char *packet = ngx_alloc(ad.len + out.len, c->log);
358 if (packet == 0) {
359 return 0;
360 }
361
362 p = ngx_cpymem(packet, ad.data, ad.len);
363 p = ngx_cpymem(p, out.data, out.len);
364
365 m = ngx_hex_dump(buf, (u_char *) packet, ngx_min(1024, p - packet)) - buf;
366 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
367 "quic_add_handshake_data packet: %*s%s, len: %uz",
368 m, buf, len < 2048 ? "" : "...", p - packet);
369
370 c->send(c, packet, p - packet);
371
372 return 1;
373 }
374
375
376 static int
377 quic_flush_flight(ngx_ssl_conn_t *ssl_conn)
378 {
379 ngx_connection_t *c;
380
381 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
382
383 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic_flush_flight()");
384
385 return 1;
386 }
387
388
389 static int
390 quic_send_alert(ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level,
391 uint8_t alert)
392 {
393 ngx_connection_t *c;
394
395 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
396
397 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
398 "quic_send_alert(), lvl=%d, alert=%d",
399 (int) level, (int) alert);
400
401 return 1;
402 }
403
404
405 static SSL_QUIC_METHOD quic_method = {
406 quic_set_encryption_secrets,
407 quic_add_handshake_data,
408 quic_flush_flight,
409 quic_send_alert,
410 };
411
412 #endif
413
414
415 static ngx_command_t ngx_openssl_commands[] = { 93 static ngx_command_t ngx_openssl_commands[] = {
416 94
417 { ngx_string("ssl_engine"), 95 { ngx_string("ssl_engine"),
418 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, 96 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
419 ngx_openssl_engine, 97 ngx_openssl_engine,
1788 return NGX_OK; 1466 return NGX_OK;
1789 } 1467 }
1790 1468
1791 #if NGX_OPENSSL_QUIC 1469 #if NGX_OPENSSL_QUIC
1792 1470
1793 SSL_CTX_set_quic_method(ssl->ctx, &quic_method); 1471 ngx_quic_init_ssl_methods(ssl->ctx);
1794 return NGX_OK; 1472 return NGX_OK;
1795 1473
1796 #else 1474 #else
1797 1475
1798 ngx_log_error(NGX_LOG_WARN, ssl->log, 0, 1476 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,