comparison src/event/ngx_event_openssl.c @ 8170:53a5cdbe500c quic

QUIC add_handshake_data callback, varint routines.
author Sergey Kandaurov <pluknet@nginx.com>
date Fri, 28 Feb 2020 13:09:51 +0300
parents bd006bd520a9
children 4daf03d2bd0a
comparison
equal deleted inserted replaced
8169:bd006bd520a9 8170:53a5cdbe500c
360 360
361 static int 361 static int
362 quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn, 362 quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
363 enum ssl_encryption_level_t level, const uint8_t *data, size_t len) 363 enum ssl_encryption_level_t level, const uint8_t *data, size_t len)
364 { 364 {
365 u_char buf[512]; 365 u_char buf[512], *p, *cipher, *clear, *ad;
366 ngx_int_t m; 366 size_t ad_len, clear_len;
367 ngx_connection_t *c; 367 ngx_int_t m;
368 ngx_str_t *server_key, *server_iv, *server_hp;
369 ngx_connection_t *c;
370 ngx_quic_connection_t *qc;
368 371
369 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); 372 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
373 qc = c->quic;
374
375 switch (level) {
376
377 case ssl_encryption_initial:
378 server_key = &qc->server_in_key;
379 server_iv = &qc->server_in_iv;
380 server_hp = &qc->server_in_hp;
381 break;
382
383 case ssl_encryption_handshake:
384 server_key = &qc->server_hs_key;
385 server_iv = &qc->server_hs_iv;
386 server_hp = &qc->server_hs_hp;
387 break;
388
389 default:
390 return 0;
391 }
370 392
371 m = ngx_hex_dump(buf, (u_char *) data, ngx_min(len, 256)) - buf; 393 m = ngx_hex_dump(buf, (u_char *) data, ngx_min(len, 256)) - buf;
372 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0, 394 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
373 "quic_add_handshake_data: %*s%s, len: %uz, level:%d", 395 "quic_add_handshake_data: %*s%s, len: %uz, level:%d",
374 m, buf, len < 512 ? "" : "...", len, (int) level); 396 m, buf, len < 512 ? "" : "...", len, (int) level);
375 397
376 if (!(SSL_provide_quic_data(ssl_conn, level, data, len))) { 398 clear = ngx_alloc(4 + len + 5 /*minimal ACK*/, c->log);
377 ERR_print_errors_fp(stderr); 399 if (clear == 0) {
378 return 0; 400 return 0;
379 } 401 }
402
403 p = clear;
404 ngx_quic_build_int(&p, 6); // crypto frame
405 ngx_quic_build_int(&p, 0);
406 ngx_quic_build_int(&p, len);
407 p = ngx_cpymem(p, data, len);
408
409 ngx_quic_build_int(&p, 2); // ack frame
410 ngx_quic_build_int(&p, 0);
411 ngx_quic_build_int(&p, 0);
412 ngx_quic_build_int(&p, 0);
413 ngx_quic_build_int(&p, 0);
414
415 clear_len = p - clear;
416 size_t cipher_len = clear_len + 16 /*expansion*/;
417
418 ad = ngx_alloc(346 /*max header*/, c->log);
419 if (ad == 0) {
420 return 0;
421 }
422
423 p = ad;
424 if (level == ssl_encryption_initial) {
425 *p++ = 0xc0; // initial, packet number len
426 } else if (level == ssl_encryption_handshake) {
427 *p++ = 0xe0; // handshake, packet number len
428 }
429 *p++ = 0xff;
430 *p++ = 0x00;
431 *p++ = 0x00;
432 *p++ = 0x17;
433 *p++ = qc->scid.len;
434 p = ngx_cpymem(p, qc->scid.data, qc->scid.len);
435 *p++ = qc->dcid.len;
436 p = ngx_cpymem(p, qc->dcid.data, qc->dcid.len);
437 ngx_quic_build_int(&p, 0); // token length
438 ngx_quic_build_int(&p, cipher_len); // length
439 u_char *pnp = p;
440 *p++ = 0; // packet number 0
441
442 ad_len = p - ad;
443
444 m = ngx_hex_dump(buf, (u_char *) ad, ad_len) - buf;
445 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
446 "quic_add_handshake_data ad: %*s, len: %uz",
447 m, buf, ad_len);
448
449 EVP_AEAD_CTX *aead = EVP_AEAD_CTX_new(EVP_aead_aes_128_gcm(),
450 server_key->data,
451 server_key->len,
452 EVP_AEAD_DEFAULT_TAG_LENGTH);
453
454 cipher = ngx_alloc(cipher_len, c->log);
455 if (cipher == 0) {
456 return 0;
457 }
458
459 size_t out_len;
460
461 if (EVP_AEAD_CTX_seal(aead, cipher, &out_len, cipher_len,
462 server_iv->data, server_iv->len,
463 clear, clear_len, ad, ad_len)
464 != 1)
465 {
466 EVP_AEAD_CTX_free(aead);
467 ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
468 "EVP_AEAD_CTX_seal() failed");
469 return 0;
470 }
471
472 EVP_AEAD_CTX_free(aead);
473
474 EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
475 u_char *sample = cipher + 3; // pnl=0
476 uint8_t mask[16];
477 int outlen;
478
479 if (EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, server_hp->data, NULL)
480 != 1)
481 {
482 EVP_CIPHER_CTX_free(ctx);
483 ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
484 "EVP_EncryptInit_ex() failed");
485 return 0;
486 }
487
488 if (!EVP_EncryptUpdate(ctx, mask, &outlen, sample, 16)) {
489 EVP_CIPHER_CTX_free(ctx);
490 ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
491 "EVP_EncryptUpdate() failed");
492 return 0;
493 }
494
495 EVP_CIPHER_CTX_free(ctx);
496
497 // header protection, pnl = 0
498 ad[0] ^= mask[0] & 0x0f;
499 *pnp ^= mask[1];
500
501 printf("cipher_len %ld out_len %ld ad_len %ld\n", cipher_len, out_len, ad_len);
502
503 u_char *packet = ngx_alloc(ad_len + out_len, c->log);
504 if (packet == 0) {
505 return 0;
506 }
507
508 p = ngx_cpymem(packet, ad, ad_len);
509 p = ngx_cpymem(p, cipher, out_len);
510
511 m = ngx_hex_dump(buf, (u_char *) packet, p - packet) - buf;
512 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
513 "quic_add_handshake_data packet: %*s, len: %uz",
514 m, buf, p - packet);
515
516 c->send(c, packet, p - packet);
380 517
381 return 1; 518 return 1;
382 } 519 }
383 520
384 521