comparison src/event/ngx_event_quic_protection.c @ 8285:f85749b60e58 quic

Removed memory allocations from encryption code. + ngx_quic_encrypt(): - no longer accepts pool as argument - pkt is 1st arg - payload is passed as pkt->payload - performs encryption to the specified static buffer + ngx_quic_create_long/short_packet() functions: - single buffer for everything, allocated by caller - buffer layout is: [ ad | payload | TAG ] the result is in the beginning of buffer with proper length - nonce is calculated on stack - log is passed explicitly, pkt is 1st arg - no more allocations inside + ngx_quic_create_long_header(): - args changed: no need to pass str_t + added ngx_quic_create_short_header()
author Vladimir Homutov <vl@nginx.com>
date Thu, 26 Mar 2020 12:11:50 +0300
parents d45325e90221
children ccb9cc95ad5e
comparison
equal deleted inserted replaced
8284:2935a11c55b6 8285:f85749b60e58
41 ngx_quic_ciphers_t *ciphers, enum ssl_encryption_level_t level); 41 ngx_quic_ciphers_t *ciphers, enum ssl_encryption_level_t level);
42 42
43 static ngx_int_t ngx_quic_tls_open(ngx_pool_t *pool, const ngx_quic_cipher_t *cipher, 43 static ngx_int_t ngx_quic_tls_open(ngx_pool_t *pool, const ngx_quic_cipher_t *cipher,
44 ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_str_t *in, 44 ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_str_t *in,
45 ngx_str_t *ad); 45 ngx_str_t *ad);
46 static ngx_int_t ngx_quic_tls_seal(ngx_pool_t *pool, 46 static ngx_int_t ngx_quic_tls_seal(const ngx_quic_cipher_t *cipher,
47 const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s, ngx_str_t *out, 47 ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_str_t *in,
48 u_char *nonce, ngx_str_t *in, ngx_str_t *ad); 48 ngx_str_t *ad, ngx_log_t *log);
49 static ngx_int_t ngx_quic_tls_hp(ngx_log_t *log, const EVP_CIPHER *cipher, 49 static ngx_int_t ngx_quic_tls_hp(ngx_log_t *log, const EVP_CIPHER *cipher,
50 ngx_quic_secret_t *s, u_char *out, u_char *in); 50 ngx_quic_secret_t *s, u_char *out, u_char *in);
51 static ngx_int_t ngx_quic_hkdf_expand(ngx_pool_t *pool, const EVP_MD *digest, 51 static ngx_int_t ngx_quic_hkdf_expand(ngx_pool_t *pool, const EVP_MD *digest,
52 ngx_str_t *out, ngx_str_t *label, const uint8_t *prk, size_t prk_len); 52 ngx_str_t *out, ngx_str_t *label, const uint8_t *prk, size_t prk_len);
53 53
54 static ngx_int_t ngx_quic_create_long_packet(ngx_pool_t *pool, 54 static ssize_t ngx_quic_create_long_packet(ngx_quic_header_t *pkt,
55 ngx_ssl_conn_t *ssl_conn, ngx_quic_header_t *pkt, ngx_str_t *in, 55 ngx_ssl_conn_t *ssl_conn, ngx_str_t *res);
56 ngx_str_t *res); 56
57 57 static ssize_t ngx_quic_create_short_packet(ngx_quic_header_t *pkt,
58 static ngx_int_t ngx_quic_create_short_packet(ngx_pool_t *pool, 58 ngx_ssl_conn_t *ssl_conn, ngx_str_t *res);
59 ngx_ssl_conn_t *ssl_conn, ngx_quic_header_t *pkt, ngx_str_t *in,
60 ngx_str_t *res);
61 59
62 60
63 static ngx_int_t 61 static ngx_int_t
64 ngx_quic_ciphers(ngx_ssl_conn_t *ssl_conn, ngx_quic_ciphers_t *ciphers, 62 ngx_quic_ciphers(ngx_ssl_conn_t *ssl_conn, ngx_quic_ciphers_t *ciphers,
65 enum ssl_encryption_level_t level) 63 enum ssl_encryption_level_t level)
465 return NGX_OK; 463 return NGX_OK;
466 } 464 }
467 465
468 466
469 static ngx_int_t 467 static ngx_int_t
470 ngx_quic_tls_seal(ngx_pool_t *pool, const ngx_quic_cipher_t *cipher, 468 ngx_quic_tls_seal(const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s,
471 ngx_quic_secret_t *s, ngx_str_t *out, u_char *nonce, ngx_str_t *in, 469 ngx_str_t *out, u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log)
472 ngx_str_t *ad) 470 {
473 {
474 ngx_log_t *log;
475
476 log = pool->log; // TODO: pass log ?
477
478 out->len = in->len + EVP_GCM_TLS_TAG_LEN;
479 out->data = ngx_pnalloc(pool, out->len);
480 if (out->data == NULL) {
481 return NGX_ERROR;
482 }
483 471
484 #ifdef OPENSSL_IS_BORINGSSL 472 #ifdef OPENSSL_IS_BORINGSSL
485 EVP_AEAD_CTX *ctx; 473 EVP_AEAD_CTX *ctx;
486 474
487 ctx = EVP_AEAD_CTX_new(cipher, s->key.data, s->key.len, 475 ctx = EVP_AEAD_CTX_new(cipher, s->key.data, s->key.len,
680 668
681 return 1; 669 return 1;
682 } 670 }
683 671
684 672
685 static ngx_int_t 673 static ssize_t
686 ngx_quic_create_long_packet(ngx_pool_t *pool, ngx_ssl_conn_t *ssl_conn, 674 ngx_quic_create_long_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn,
687 ngx_quic_header_t *pkt, ngx_str_t *payload, ngx_str_t *res) 675 ngx_str_t *res)
688 { 676 {
689 u_char *p, *pnp, *nonce, *sample, *packet; 677 u_char *pnp, *sample;
690 uint64_t pn; 678 uint64_t pn;
691 ngx_log_t *log;
692 ngx_str_t ad, out; 679 ngx_str_t ad, out;
693 ngx_quic_ciphers_t ciphers; 680 ngx_quic_ciphers_t ciphers;
694 u_char mask[16]; 681 u_char nonce[12], mask[16];
695 682
696 log = pool->log; 683 out.len = pkt->payload.len + EVP_GCM_TLS_TAG_LEN;
697 684
698 out.len = payload->len + EVP_GCM_TLS_TAG_LEN; 685 ad.data = res->data;
699 686 ad.len = ngx_quic_create_long_header(pkt, ad.data, out.len, &pnp);
700 ad.data = ngx_alloc(NGX_QUIC_MAX_LONG_HEADER, log); 687
701 if (ad.data == 0) { 688 out.data = res->data + ad.len;
702 return NGX_ERROR; 689
703 } 690 ngx_quic_hexdump0(pkt->log, "ad", ad.data, ad.len);
704
705 ad.len = ngx_quic_create_long_header(pkt, &ad, out.len, &pnp);
706
707 ngx_quic_hexdump0(log, "ad", ad.data, ad.len);
708 691
709 if (ngx_quic_ciphers(ssl_conn, &ciphers, pkt->level) == NGX_ERROR) { 692 if (ngx_quic_ciphers(ssl_conn, &ciphers, pkt->level) == NGX_ERROR) {
710 return NGX_ERROR; 693 return NGX_ERROR;
711 } 694 }
712 695
713 nonce = ngx_pstrdup(pool, &pkt->secret->iv); 696 ngx_memcpy(nonce, pkt->secret->iv.data, pkt->secret->iv.len);
714 pn = *pkt->number; 697 pn = *pkt->number;
715 nonce[11] ^= pn; 698 nonce[11] ^= pn;
716 699
717 ngx_quic_hexdump0(log, "server_iv", pkt->secret->iv.data, 12); 700 ngx_quic_hexdump0(pkt->log, "server_iv", pkt->secret->iv.data, 12);
718 ngx_quic_hexdump0(log, "nonce", nonce, 12); 701 ngx_quic_hexdump0(pkt->log, "nonce", nonce, 12);
719 702
720 if (ngx_quic_tls_seal(pool, ciphers.c, pkt->secret, &out, 703 if (ngx_quic_tls_seal(ciphers.c, pkt->secret, &out,
721 nonce, payload, &ad) 704 nonce, &pkt->payload, &ad, pkt->log)
722 != NGX_OK) 705 != NGX_OK)
723 { 706 {
724 return NGX_ERROR; 707 return NGX_ERROR;
725 } 708 }
726 709
727 sample = &out.data[3]; // pnl=0 710 sample = &out.data[3]; // pnl=0
728 if (ngx_quic_tls_hp(log, ciphers.hp, pkt->secret, mask, sample) != NGX_OK) { 711 if (ngx_quic_tls_hp(pkt->log, ciphers.hp, pkt->secret, mask, sample)
729 return NGX_ERROR; 712 != NGX_OK)
730 } 713 {
731 714 return NGX_ERROR;
732 ngx_quic_hexdump0(log, "sample", sample, 16); 715 }
733 ngx_quic_hexdump0(log, "mask", mask, 16); 716
734 ngx_quic_hexdump0(log, "hp_key", pkt->secret->hp.data, 16); 717 ngx_quic_hexdump0(pkt->log, "sample", sample, 16);
718 ngx_quic_hexdump0(pkt->log, "mask", mask, 16);
719 ngx_quic_hexdump0(pkt->log, "hp_key", pkt->secret->hp.data, 16);
735 720
736 // header protection, pnl = 0 721 // header protection, pnl = 0
737 ad.data[0] ^= mask[0] & 0x0f; 722 ad.data[0] ^= mask[0] & 0x0f;
738 *pnp ^= mask[1]; 723 *pnp ^= mask[1];
739 724
740 packet = ngx_alloc(ad.len + out.len, log); 725 res->len = ad.len + out.len;
741 if (packet == 0) {
742 return NGX_ERROR;
743 }
744
745 p = ngx_cpymem(packet, ad.data, ad.len);
746 p = ngx_cpymem(p, out.data, out.len);
747
748 res->data = packet;
749 res->len = p - packet;
750 726
751 return NGX_OK; 727 return NGX_OK;
752 } 728 }
753 729
754 730
755 static ngx_int_t 731 static ssize_t
756 ngx_quic_create_short_packet(ngx_pool_t *pool, ngx_ssl_conn_t *ssl_conn, 732 ngx_quic_create_short_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn,
757 ngx_quic_header_t *pkt, ngx_str_t *payload, ngx_str_t *res) 733 ngx_str_t *res)
758 { 734 {
759 u_char *p, *pnp, *nonce, *sample, *packet; 735 u_char *pnp, *sample;
760 ngx_log_t *log;
761 ngx_str_t ad, out; 736 ngx_str_t ad, out;
762 ngx_quic_ciphers_t ciphers; 737 ngx_quic_ciphers_t ciphers;
763 u_char mask[16]; 738 u_char nonce[12], mask[16];
764 739
765 log = pool->log; 740 out.len = pkt->payload.len + EVP_GCM_TLS_TAG_LEN;
766 741
767 out.len = payload->len + EVP_GCM_TLS_TAG_LEN; 742 ad.data = res->data;
768 743 ad.len = ngx_quic_create_short_header(pkt, ad.data, out.len, &pnp);
769 ad.data = ngx_alloc(NGX_QUIC_MAX_SHORT_HEADER, log); 744
770 if (ad.data == 0) { 745 ngx_quic_hexdump0(pkt->log, "ad", ad.data, ad.len);
771 return NGX_ERROR;
772 }
773
774 p = ad.data;
775
776 *p++ = 0x40;
777
778 p = ngx_cpymem(p, pkt->scid.data, pkt->scid.len);
779
780 pnp = p;
781
782 *p++ = (*pkt->number);
783
784 ad.len = p - ad.data;
785
786 ngx_quic_hexdump0(log, "ad", ad.data, ad.len);
787 746
788 if (ngx_quic_ciphers(ssl_conn, &ciphers, pkt->level) == NGX_ERROR) { 747 if (ngx_quic_ciphers(ssl_conn, &ciphers, pkt->level) == NGX_ERROR) {
789 return NGX_ERROR; 748 return NGX_ERROR;
790 } 749 }
791 750
792 nonce = ngx_pstrdup(pool, &pkt->secret->iv); 751 ngx_memcpy(nonce, pkt->secret->iv.data, pkt->secret->iv.len);
793 if (pkt->level == ssl_encryption_handshake 752 if (pkt->level == ssl_encryption_handshake
794 || pkt->level == ssl_encryption_application) 753 || pkt->level == ssl_encryption_application)
795 { 754 {
796 nonce[11] ^= *pkt->number; 755 nonce[11] ^= *pkt->number;
797 } 756 }
798 757
799 ngx_quic_hexdump0(log, "server_iv", pkt->secret->iv.data, 12); 758 ngx_quic_hexdump0(pkt->log, "server_iv", pkt->secret->iv.data, 12);
800 ngx_quic_hexdump0(log, "nonce", nonce, 12); 759 ngx_quic_hexdump0(pkt->log, "nonce", nonce, 12);
801 760
802 if (ngx_quic_tls_seal(pool, ciphers.c, pkt->secret, &out, 761 out.data = res->data + ad.len;
803 nonce, payload, &ad) 762
763 if (ngx_quic_tls_seal(ciphers.c, pkt->secret, &out, nonce, &pkt->payload,
764 &ad, pkt->log)
804 != NGX_OK) 765 != NGX_OK)
805 { 766 {
806 return NGX_ERROR; 767 return NGX_ERROR;
807 } 768 }
808 769
809 ngx_quic_hexdump0(log, "out", out.data, out.len); 770 ngx_quic_hexdump0(pkt->log, "out", out.data, out.len);
810 771
811 sample = &out.data[3]; // pnl=0 772 sample = &out.data[3]; // pnl=0
812 if (ngx_quic_tls_hp(log, ciphers.hp, pkt->secret, mask, sample) != NGX_OK) { 773 if (ngx_quic_tls_hp(pkt->log, ciphers.hp, pkt->secret, mask, sample)
813 return NGX_ERROR; 774 != NGX_OK)
814 } 775 {
815 776 return NGX_ERROR;
816 ngx_quic_hexdump0(log, "sample", sample, 16); 777 }
817 ngx_quic_hexdump0(log, "mask", mask, 16); 778
818 ngx_quic_hexdump0(log, "hp_key", pkt->secret->hp.data, 16); 779 ngx_quic_hexdump0(pkt->log, "sample", sample, 16);
780 ngx_quic_hexdump0(pkt->log, "mask", mask, 16);
781 ngx_quic_hexdump0(pkt->log, "hp_key", pkt->secret->hp.data, 16);
819 782
820 // header protection, pnl = 0 783 // header protection, pnl = 0
821 ad.data[0] ^= mask[0] & 0x1f; 784 ad.data[0] ^= mask[0] & 0x1f;
822 *pnp ^= mask[1]; 785 *pnp ^= mask[1];
823 786
824 packet = ngx_alloc(ad.len + out.len, log); 787 res->len = ad.len + out.len;
825 if (packet == 0) { 788
826 return NGX_ERROR; 789 ngx_quic_hexdump0(pkt->log, "packet", res->data, res->len);
827 }
828
829 p = ngx_cpymem(packet, ad.data, ad.len);
830 p = ngx_cpymem(p, out.data, out.len);
831
832 ngx_quic_hexdump0(log, "packet", packet, p - packet);
833
834 res->data = packet;
835 res->len = p - packet;
836 790
837 return NGX_OK; 791 return NGX_OK;
838 } 792 }
793
839 794
840 static uint64_t 795 static uint64_t
841 ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask) 796 ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask)
842 { 797 {
843 u_char *p; 798 u_char *p;
853 *pos = p; 808 *pos = p;
854 return value; 809 return value;
855 } 810 }
856 811
857 812
858 ngx_int_t 813 ssize_t
859 ngx_quic_encrypt(ngx_pool_t *pool, ngx_ssl_conn_t *ssl_conn, 814 ngx_quic_encrypt(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn,
860 ngx_quic_header_t *pkt, ngx_str_t *payload, ngx_str_t *res) 815 ngx_str_t *res)
861 { 816 {
862 if (pkt->level == ssl_encryption_application) { 817 if (pkt->level == ssl_encryption_application) {
863 return ngx_quic_create_short_packet(pool, ssl_conn, pkt, payload, res); 818 return ngx_quic_create_short_packet(pkt, ssl_conn, res);
864 } 819 }
865 820
866 return ngx_quic_create_long_packet(pool, ssl_conn, pkt, payload, res); 821 return ngx_quic_create_long_packet(pkt, ssl_conn, res);
867 } 822 }
868 823
869 824
870 ngx_int_t 825 ngx_int_t
871 ngx_quic_decrypt(ngx_pool_t *pool, ngx_ssl_conn_t *ssl_conn, 826 ngx_quic_decrypt(ngx_pool_t *pool, ngx_ssl_conn_t *ssl_conn,