Mercurial > hg > nginx
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, |