Mercurial > hg > nginx
comparison src/event/quic/ngx_event_quic_openssl_compat.c @ 9080:7da4791e0264 quic
QUIC: OpenSSL compatibility layer.
The change allows to compile QUIC with OpenSSL which lacks BoringSSL QUIC API.
This implementation does not support 0-RTT.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 22 Feb 2023 19:16:53 +0400 |
parents | |
children | b4a57278bf24 |
comparison
equal
deleted
inserted
replaced
9079:639fa6723700 | 9080:7da4791e0264 |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Nginx, Inc. | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_event.h> | |
10 #include <ngx_event_quic_connection.h> | |
11 | |
12 | |
13 #if (NGX_QUIC_OPENSSL_COMPAT) | |
14 | |
15 #define NGX_QUIC_COMPAT_RECORD_SIZE 1024 | |
16 | |
17 #define NGX_QUIC_COMPAT_SSL_TP_EXT 0x39 | |
18 | |
19 #define NGX_QUIC_COMPAT_CLIENT_HANDSHAKE "CLIENT_HANDSHAKE_TRAFFIC_SECRET" | |
20 #define NGX_QUIC_COMPAT_SERVER_HANDSHAKE "SERVER_HANDSHAKE_TRAFFIC_SECRET" | |
21 #define NGX_QUIC_COMPAT_CLIENT_APPLICATION "CLIENT_TRAFFIC_SECRET_0" | |
22 #define NGX_QUIC_COMPAT_SERVER_APPLICATION "SERVER_TRAFFIC_SECRET_0" | |
23 | |
24 | |
25 typedef struct { | |
26 ngx_quic_secret_t secret; | |
27 ngx_uint_t cipher; | |
28 } ngx_quic_compat_keys_t; | |
29 | |
30 | |
31 typedef struct { | |
32 ngx_log_t *log; | |
33 | |
34 u_char type; | |
35 ngx_str_t payload; | |
36 uint64_t number; | |
37 ngx_quic_compat_keys_t *keys; | |
38 | |
39 enum ssl_encryption_level_t level; | |
40 } ngx_quic_compat_record_t; | |
41 | |
42 | |
43 struct ngx_quic_compat_s { | |
44 const SSL_QUIC_METHOD *method; | |
45 | |
46 enum ssl_encryption_level_t write_level; | |
47 enum ssl_encryption_level_t read_level; | |
48 | |
49 uint64_t read_record; | |
50 ngx_quic_compat_keys_t keys; | |
51 | |
52 ngx_str_t tp; | |
53 ngx_str_t ctp; | |
54 }; | |
55 | |
56 | |
57 static void ngx_quic_compat_keylog_callback(const SSL *ssl, const char *line); | |
58 static ngx_int_t ngx_quic_compat_set_encryption_secret(ngx_log_t *log, | |
59 ngx_quic_compat_keys_t *keys, enum ssl_encryption_level_t level, | |
60 const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len); | |
61 static int ngx_quic_compat_add_transport_params_callback(SSL *ssl, | |
62 unsigned int ext_type, unsigned int context, const unsigned char **out, | |
63 size_t *outlen, X509 *x, size_t chainidx, int *al, void *add_arg); | |
64 static int ngx_quic_compat_parse_transport_params_callback(SSL *ssl, | |
65 unsigned int ext_type, unsigned int context, const unsigned char *in, | |
66 size_t inlen, X509 *x, size_t chainidx, int *al, void *parse_arg); | |
67 static void ngx_quic_compat_message_callback(int write_p, int version, | |
68 int content_type, const void *buf, size_t len, SSL *ssl, void *arg); | |
69 static size_t ngx_quic_compat_create_header(ngx_quic_compat_record_t *rec, | |
70 u_char *out, ngx_uint_t plain); | |
71 static ngx_int_t ngx_quic_compat_create_record(ngx_quic_compat_record_t *rec, | |
72 ngx_str_t *res); | |
73 | |
74 | |
75 ngx_int_t | |
76 ngx_quic_compat_init(ngx_conf_t *cf, SSL_CTX *ctx) | |
77 { | |
78 SSL_CTX_set_keylog_callback(ctx, ngx_quic_compat_keylog_callback); | |
79 | |
80 if (SSL_CTX_has_client_custom_ext(ctx, NGX_QUIC_COMPAT_SSL_TP_EXT)) { | |
81 return NGX_OK; | |
82 } | |
83 | |
84 if (SSL_CTX_add_custom_ext(ctx, NGX_QUIC_COMPAT_SSL_TP_EXT, | |
85 SSL_EXT_CLIENT_HELLO | |
86 |SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, | |
87 ngx_quic_compat_add_transport_params_callback, | |
88 NULL, | |
89 NULL, | |
90 ngx_quic_compat_parse_transport_params_callback, | |
91 NULL) | |
92 == 0) | |
93 { | |
94 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
95 "SSL_CTX_add_custom_ext() failed"); | |
96 return NGX_ERROR; | |
97 } | |
98 | |
99 return NGX_OK; | |
100 } | |
101 | |
102 | |
103 static void | |
104 ngx_quic_compat_keylog_callback(const SSL *ssl, const char *line) | |
105 { | |
106 u_char ch, *p, *start, value; | |
107 size_t n; | |
108 ngx_uint_t write; | |
109 const SSL_CIPHER *cipher; | |
110 ngx_quic_compat_t *com; | |
111 ngx_connection_t *c; | |
112 ngx_quic_connection_t *qc; | |
113 enum ssl_encryption_level_t level; | |
114 u_char secret[EVP_MAX_MD_SIZE]; | |
115 | |
116 c = ngx_ssl_get_connection(ssl); | |
117 if (c->type != SOCK_DGRAM) { | |
118 return; | |
119 } | |
120 | |
121 p = (u_char *) line; | |
122 | |
123 for (start = p; *p && *p != ' '; p++); | |
124 | |
125 n = p - start; | |
126 | |
127 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
128 "quic compat secret %*s", n, start); | |
129 | |
130 if (n == sizeof(NGX_QUIC_COMPAT_CLIENT_HANDSHAKE) - 1 | |
131 && ngx_strncmp(start, NGX_QUIC_COMPAT_CLIENT_HANDSHAKE, n) == 0) | |
132 { | |
133 level = ssl_encryption_handshake; | |
134 write = 0; | |
135 | |
136 } else if (n == sizeof(NGX_QUIC_COMPAT_SERVER_HANDSHAKE) - 1 | |
137 && ngx_strncmp(start, NGX_QUIC_COMPAT_SERVER_HANDSHAKE, n) == 0) | |
138 { | |
139 level = ssl_encryption_handshake; | |
140 write = 1; | |
141 | |
142 } else if (n == sizeof(NGX_QUIC_COMPAT_CLIENT_APPLICATION) - 1 | |
143 && ngx_strncmp(start, NGX_QUIC_COMPAT_CLIENT_APPLICATION, n) | |
144 == 0) | |
145 { | |
146 level = ssl_encryption_application; | |
147 write = 0; | |
148 | |
149 } else if (n == sizeof(NGX_QUIC_COMPAT_SERVER_APPLICATION) - 1 | |
150 && ngx_strncmp(start, NGX_QUIC_COMPAT_SERVER_APPLICATION, n) | |
151 == 0) | |
152 { | |
153 level = ssl_encryption_application; | |
154 write = 1; | |
155 | |
156 } else { | |
157 return; | |
158 } | |
159 | |
160 if (*p++ == '\0') { | |
161 return; | |
162 } | |
163 | |
164 for ( /* void */ ; *p && *p != ' '; p++); | |
165 | |
166 if (*p++ == '\0') { | |
167 return; | |
168 } | |
169 | |
170 for (n = 0, start = p; *p; p++) { | |
171 ch = *p; | |
172 | |
173 if (ch >= '0' && ch <= '9') { | |
174 value = ch - '0'; | |
175 goto next; | |
176 } | |
177 | |
178 ch = (u_char) (ch | 0x20); | |
179 | |
180 if (ch >= 'a' && ch <= 'f') { | |
181 value = ch - 'a' + 10; | |
182 goto next; | |
183 } | |
184 | |
185 ngx_log_error(NGX_LOG_EMERG, c->log, 0, | |
186 "invalid OpenSSL QUIC secret format"); | |
187 | |
188 return; | |
189 | |
190 next: | |
191 | |
192 if ((p - start) % 2) { | |
193 secret[n++] += value; | |
194 | |
195 } else { | |
196 if (n >= EVP_MAX_MD_SIZE) { | |
197 ngx_log_error(NGX_LOG_EMERG, c->log, 0, | |
198 "too big OpenSSL QUIC secret"); | |
199 return; | |
200 } | |
201 | |
202 secret[n] = (value << 4); | |
203 } | |
204 } | |
205 | |
206 qc = ngx_quic_get_connection(c); | |
207 com = qc->compat; | |
208 cipher = SSL_get_current_cipher(ssl); | |
209 | |
210 if (write) { | |
211 com->method->set_write_secret((SSL *) ssl, level, cipher, secret, n); | |
212 com->write_level = level; | |
213 | |
214 } else { | |
215 com->method->set_read_secret((SSL *) ssl, level, cipher, secret, n); | |
216 com->read_level = level; | |
217 com->read_record = 0; | |
218 | |
219 (void) ngx_quic_compat_set_encryption_secret(c->log, &com->keys, level, | |
220 cipher, secret, n); | |
221 } | |
222 } | |
223 | |
224 | |
225 static ngx_int_t | |
226 ngx_quic_compat_set_encryption_secret(ngx_log_t *log, | |
227 ngx_quic_compat_keys_t *keys, enum ssl_encryption_level_t level, | |
228 const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len) | |
229 { | |
230 ngx_int_t key_len; | |
231 ngx_str_t secret_str; | |
232 ngx_uint_t i; | |
233 ngx_quic_hkdf_t seq[2]; | |
234 ngx_quic_secret_t *peer_secret; | |
235 ngx_quic_ciphers_t ciphers; | |
236 | |
237 peer_secret = &keys->secret; | |
238 | |
239 keys->cipher = SSL_CIPHER_get_id(cipher); | |
240 | |
241 key_len = ngx_quic_ciphers(keys->cipher, &ciphers, level); | |
242 | |
243 if (key_len == NGX_ERROR) { | |
244 ngx_ssl_error(NGX_LOG_INFO, log, 0, "unexpected cipher"); | |
245 return NGX_ERROR; | |
246 } | |
247 | |
248 if (sizeof(peer_secret->secret.data) < secret_len) { | |
249 ngx_log_error(NGX_LOG_ALERT, log, 0, | |
250 "unexpected secret len: %uz", secret_len); | |
251 return NGX_ERROR; | |
252 } | |
253 | |
254 peer_secret->secret.len = secret_len; | |
255 ngx_memcpy(peer_secret->secret.data, secret, secret_len); | |
256 | |
257 peer_secret->key.len = key_len; | |
258 peer_secret->iv.len = NGX_QUIC_IV_LEN; | |
259 | |
260 secret_str.len = secret_len; | |
261 secret_str.data = (u_char *) secret; | |
262 | |
263 ngx_quic_hkdf_set(&seq[0], "tls13 key", &peer_secret->key, &secret_str); | |
264 ngx_quic_hkdf_set(&seq[1], "tls13 iv", &peer_secret->iv, &secret_str); | |
265 | |
266 for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) { | |
267 if (ngx_quic_hkdf_expand(&seq[i], ciphers.d, log) != NGX_OK) { | |
268 return NGX_ERROR; | |
269 } | |
270 } | |
271 | |
272 return NGX_OK; | |
273 } | |
274 | |
275 | |
276 static int | |
277 ngx_quic_compat_add_transport_params_callback(SSL *ssl, unsigned int ext_type, | |
278 unsigned int context, const unsigned char **out, size_t *outlen, X509 *x, | |
279 size_t chainidx, int *al, void *add_arg) | |
280 { | |
281 ngx_connection_t *c; | |
282 ngx_quic_compat_t *com; | |
283 ngx_quic_connection_t *qc; | |
284 | |
285 c = ngx_ssl_get_connection(ssl); | |
286 if (c->type != SOCK_DGRAM) { | |
287 return 0; | |
288 } | |
289 | |
290 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
291 "quic compat add transport params"); | |
292 | |
293 qc = ngx_quic_get_connection(c); | |
294 com = qc->compat; | |
295 | |
296 *out = com->tp.data; | |
297 *outlen = com->tp.len; | |
298 | |
299 return 1; | |
300 } | |
301 | |
302 | |
303 static int | |
304 ngx_quic_compat_parse_transport_params_callback(SSL *ssl, unsigned int ext_type, | |
305 unsigned int context, const unsigned char *in, size_t inlen, X509 *x, | |
306 size_t chainidx, int *al, void *parse_arg) | |
307 { | |
308 u_char *p; | |
309 ngx_connection_t *c; | |
310 ngx_quic_compat_t *com; | |
311 ngx_quic_connection_t *qc; | |
312 | |
313 c = ngx_ssl_get_connection(ssl); | |
314 if (c->type != SOCK_DGRAM) { | |
315 return 0; | |
316 } | |
317 | |
318 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
319 "quic compat parse transport params"); | |
320 | |
321 qc = ngx_quic_get_connection(c); | |
322 com = qc->compat; | |
323 | |
324 p = ngx_pnalloc(c->pool, inlen); | |
325 if (p == NULL) { | |
326 return 0; | |
327 } | |
328 | |
329 ngx_memcpy(p, in, inlen); | |
330 | |
331 com->ctp.data = p; | |
332 com->ctp.len = inlen; | |
333 | |
334 return 1; | |
335 } | |
336 | |
337 | |
338 int | |
339 SSL_set_quic_method(SSL *ssl, const SSL_QUIC_METHOD *quic_method) | |
340 { | |
341 BIO *rbio, *wbio; | |
342 ngx_connection_t *c; | |
343 ngx_quic_compat_t *com; | |
344 ngx_quic_connection_t *qc; | |
345 | |
346 c = ngx_ssl_get_connection(ssl); | |
347 | |
348 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic compat set method"); | |
349 | |
350 qc = ngx_quic_get_connection(c); | |
351 | |
352 qc->compat = ngx_pcalloc(c->pool, sizeof(ngx_quic_compat_t)); | |
353 if (qc->compat == NULL) { | |
354 return 0; | |
355 } | |
356 | |
357 com = qc->compat; | |
358 com->method = quic_method; | |
359 | |
360 rbio = BIO_new(BIO_s_mem()); | |
361 if (rbio == NULL) { | |
362 return 0; | |
363 } | |
364 | |
365 wbio = BIO_new(BIO_s_null()); | |
366 if (wbio == NULL) { | |
367 return 0; | |
368 } | |
369 | |
370 SSL_set_bio(ssl, rbio, wbio); | |
371 | |
372 SSL_set_msg_callback(ssl, ngx_quic_compat_message_callback); | |
373 | |
374 /* early data is not supported */ | |
375 SSL_set_max_early_data(ssl, 0); | |
376 | |
377 return 1; | |
378 } | |
379 | |
380 | |
381 static void | |
382 ngx_quic_compat_message_callback(int write_p, int version, int content_type, | |
383 const void *buf, size_t len, SSL *ssl, void *arg) | |
384 { | |
385 ngx_uint_t alert; | |
386 ngx_connection_t *c; | |
387 ngx_quic_compat_t *com; | |
388 ngx_quic_connection_t *qc; | |
389 enum ssl_encryption_level_t level; | |
390 | |
391 if (!write_p) { | |
392 return; | |
393 } | |
394 | |
395 c = ngx_ssl_get_connection(ssl); | |
396 qc = ngx_quic_get_connection(c); | |
397 | |
398 if (qc == NULL) { | |
399 /* closing */ | |
400 return; | |
401 } | |
402 | |
403 com = qc->compat; | |
404 level = com->write_level; | |
405 | |
406 switch (content_type) { | |
407 | |
408 case SSL3_RT_HANDSHAKE: | |
409 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
410 "quic compat tx %s len:%uz ", | |
411 ngx_quic_level_name(level), len); | |
412 | |
413 (void) com->method->add_handshake_data(ssl, level, buf, len); | |
414 | |
415 break; | |
416 | |
417 case SSL3_RT_ALERT: | |
418 if (len >= 2) { | |
419 alert = ((u_char *) buf)[1]; | |
420 | |
421 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
422 "quic compat %s alert:%ui len:%uz ", | |
423 ngx_quic_level_name(level), alert, len); | |
424 | |
425 (void) com->method->send_alert(ssl, level, alert); | |
426 } | |
427 | |
428 break; | |
429 } | |
430 } | |
431 | |
432 | |
433 int | |
434 SSL_provide_quic_data(SSL *ssl, enum ssl_encryption_level_t level, | |
435 const uint8_t *data, size_t len) | |
436 { | |
437 BIO *rbio; | |
438 size_t n; | |
439 u_char *p; | |
440 ngx_str_t res; | |
441 ngx_connection_t *c; | |
442 ngx_quic_compat_t *com; | |
443 ngx_quic_connection_t *qc; | |
444 ngx_quic_compat_record_t rec; | |
445 u_char in[NGX_QUIC_COMPAT_RECORD_SIZE + 1]; | |
446 u_char out[NGX_QUIC_COMPAT_RECORD_SIZE + 1 | |
447 + SSL3_RT_HEADER_LENGTH | |
448 + EVP_GCM_TLS_TAG_LEN]; | |
449 | |
450 c = ngx_ssl_get_connection(ssl); | |
451 | |
452 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic compat rx %s len:%uz", | |
453 ngx_quic_level_name(level), len); | |
454 | |
455 qc = ngx_quic_get_connection(c); | |
456 com = qc->compat; | |
457 rbio = SSL_get_rbio(ssl); | |
458 | |
459 while (len) { | |
460 ngx_memzero(&rec, sizeof(ngx_quic_compat_record_t)); | |
461 | |
462 rec.type = SSL3_RT_HANDSHAKE; | |
463 rec.log = c->log; | |
464 rec.number = com->read_record++; | |
465 rec.keys = &com->keys; | |
466 | |
467 if (level == ssl_encryption_initial) { | |
468 n = ngx_min(len, 65535); | |
469 | |
470 rec.payload.len = n; | |
471 rec.payload.data = (u_char *) data; | |
472 | |
473 ngx_quic_compat_create_header(&rec, out, 1); | |
474 | |
475 BIO_write(rbio, out, SSL3_RT_HEADER_LENGTH); | |
476 BIO_write(rbio, data, n); | |
477 | |
478 #if defined(NGX_QUIC_DEBUG_CRYPTO) && defined(NGX_QUIC_DEBUG_PACKETS) | |
479 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
480 "quic compat record len:%uz %*xs%*xs", | |
481 n + SSL3_RT_HEADER_LENGTH, | |
482 (size_t) SSL3_RT_HEADER_LENGTH, out, n, data); | |
483 #endif | |
484 | |
485 } else { | |
486 n = ngx_min(len, NGX_QUIC_COMPAT_RECORD_SIZE); | |
487 | |
488 p = ngx_cpymem(in, data, n); | |
489 *p++ = SSL3_RT_HANDSHAKE; | |
490 | |
491 rec.payload.len = p - in; | |
492 rec.payload.data = in; | |
493 | |
494 res.data = out; | |
495 | |
496 if (ngx_quic_compat_create_record(&rec, &res) != NGX_OK) { | |
497 return 0; | |
498 } | |
499 | |
500 #if defined(NGX_QUIC_DEBUG_CRYPTO) && defined(NGX_QUIC_DEBUG_PACKETS) | |
501 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
502 "quic compat record len:%uz %xV", res.len, &res); | |
503 #endif | |
504 | |
505 BIO_write(rbio, res.data, res.len); | |
506 } | |
507 | |
508 data += n; | |
509 len -= n; | |
510 } | |
511 | |
512 return 1; | |
513 } | |
514 | |
515 | |
516 static size_t | |
517 ngx_quic_compat_create_header(ngx_quic_compat_record_t *rec, u_char *out, | |
518 ngx_uint_t plain) | |
519 { | |
520 u_char type; | |
521 size_t len; | |
522 | |
523 len = rec->payload.len; | |
524 | |
525 if (plain) { | |
526 type = rec->type; | |
527 | |
528 } else { | |
529 type = SSL3_RT_APPLICATION_DATA; | |
530 len += EVP_GCM_TLS_TAG_LEN; | |
531 } | |
532 | |
533 out[0] = type; | |
534 out[1] = 0x03; | |
535 out[2] = 0x03; | |
536 out[3] = (len >> 8); | |
537 out[4] = len; | |
538 | |
539 return 5; | |
540 } | |
541 | |
542 | |
543 static ngx_int_t | |
544 ngx_quic_compat_create_record(ngx_quic_compat_record_t *rec, ngx_str_t *res) | |
545 { | |
546 ngx_str_t ad, out; | |
547 ngx_quic_secret_t *secret; | |
548 ngx_quic_ciphers_t ciphers; | |
549 u_char nonce[NGX_QUIC_IV_LEN]; | |
550 | |
551 ad.data = res->data; | |
552 ad.len = ngx_quic_compat_create_header(rec, ad.data, 0); | |
553 | |
554 out.len = rec->payload.len + EVP_GCM_TLS_TAG_LEN; | |
555 out.data = res->data + ad.len; | |
556 | |
557 #ifdef NGX_QUIC_DEBUG_CRYPTO | |
558 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, rec->log, 0, | |
559 "quic compat ad len:%uz %xV", ad.len, &ad); | |
560 #endif | |
561 | |
562 if (ngx_quic_ciphers(rec->keys->cipher, &ciphers, rec->level) == NGX_ERROR) | |
563 { | |
564 return NGX_ERROR; | |
565 } | |
566 | |
567 secret = &rec->keys->secret; | |
568 | |
569 ngx_memcpy(nonce, secret->iv.data, secret->iv.len); | |
570 ngx_quic_compute_nonce(nonce, sizeof(nonce), rec->number); | |
571 | |
572 if (ngx_quic_tls_seal(ciphers.c, secret, &out, | |
573 nonce, &rec->payload, &ad, rec->log) | |
574 != NGX_OK) | |
575 { | |
576 return NGX_ERROR; | |
577 } | |
578 | |
579 res->len = ad.len + out.len; | |
580 | |
581 return NGX_OK; | |
582 } | |
583 | |
584 | |
585 enum ssl_encryption_level_t | |
586 SSL_quic_read_level(const SSL *ssl) | |
587 { | |
588 ngx_connection_t *c; | |
589 ngx_quic_connection_t *qc; | |
590 | |
591 c = ngx_ssl_get_connection(ssl); | |
592 qc = ngx_quic_get_connection(c); | |
593 | |
594 return qc->compat->read_level; | |
595 } | |
596 | |
597 | |
598 enum ssl_encryption_level_t | |
599 SSL_quic_write_level(const SSL *ssl) | |
600 { | |
601 ngx_connection_t *c; | |
602 ngx_quic_connection_t *qc; | |
603 | |
604 c = ngx_ssl_get_connection(ssl); | |
605 qc = ngx_quic_get_connection(c); | |
606 | |
607 return qc->compat->write_level; | |
608 } | |
609 | |
610 | |
611 int | |
612 SSL_set_quic_transport_params(SSL *ssl, const uint8_t *params, | |
613 size_t params_len) | |
614 { | |
615 ngx_connection_t *c; | |
616 ngx_quic_compat_t *com; | |
617 ngx_quic_connection_t *qc; | |
618 | |
619 c = ngx_ssl_get_connection(ssl); | |
620 qc = ngx_quic_get_connection(c); | |
621 com = qc->compat; | |
622 | |
623 com->tp.len = params_len; | |
624 com->tp.data = (u_char *) params; | |
625 | |
626 return 1; | |
627 } | |
628 | |
629 | |
630 void | |
631 SSL_get_peer_quic_transport_params(const SSL *ssl, const uint8_t **out_params, | |
632 size_t *out_params_len) | |
633 { | |
634 ngx_connection_t *c; | |
635 ngx_quic_compat_t *com; | |
636 ngx_quic_connection_t *qc; | |
637 | |
638 c = ngx_ssl_get_connection(ssl); | |
639 qc = ngx_quic_get_connection(c); | |
640 com = qc->compat; | |
641 | |
642 *out_params = com->ctp.data; | |
643 *out_params_len = com->ctp.len; | |
644 } | |
645 | |
646 #endif /* NGX_QUIC_OPENSSL_COMPAT */ |