Mercurial > hg > nginx-quic
comparison src/http/ngx_http_request.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 | 4ae9ac69ab93 |
comparison
equal
deleted
inserted
replaced
7647:3cb4f16426a5 | 7648:b28ea685a56e |
---|---|
659 #if (NGX_HTTP_SSL) | 659 #if (NGX_HTTP_SSL) |
660 | 660 |
661 static void | 661 static void |
662 ngx_http_quic_handshake(ngx_event_t *rev) | 662 ngx_http_quic_handshake(ngx_event_t *rev) |
663 { | 663 { |
664 int n, sslerr; | |
665 #if (NGX_DEBUG) | |
666 u_char buf[512]; | |
667 size_t m; | |
668 #endif | |
669 ngx_buf_t *b; | |
670 ngx_connection_t *c; | 664 ngx_connection_t *c; |
671 ngx_http_connection_t *hc; | 665 ngx_http_connection_t *hc; |
672 ngx_quic_connection_t *qc; | |
673 ngx_http_ssl_srv_conf_t *sscf; | 666 ngx_http_ssl_srv_conf_t *sscf; |
674 | 667 |
675 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "quic handshake"); | 668 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "quic handshake"); |
676 | 669 |
677 c = rev->data; | 670 c = rev->data; |
678 hc = c->data; | 671 hc = c->data; |
679 b = c->buffer; | 672 |
680 | 673 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); |
681 if ((b->pos[0] & 0xf0) != 0xc0) { | 674 |
682 ngx_log_error(NGX_LOG_INFO, rev->log, 0, "invalid initial packet"); | 675 if (ngx_quic_input(c, &sscf->ssl, c->buffer) != NGX_OK) { |
683 ngx_http_close_connection(c); | 676 ngx_http_close_connection(c); |
684 return; | 677 return; |
685 } | 678 } |
686 | |
687 if (ngx_buf_size(b) < 1200) { | |
688 ngx_log_error(NGX_LOG_INFO, rev->log, 0, "too small UDP datagram"); | |
689 ngx_http_close_connection(c); | |
690 return; | |
691 } | |
692 | |
693 ngx_int_t flags = *b->pos++; | |
694 uint32_t version = ngx_quic_parse_uint32(b->pos); | |
695 b->pos += sizeof(uint32_t); | |
696 | |
697 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
698 "quic flags:%xi version:%xD", flags, version); | |
699 | |
700 if (version != quic_version) { | |
701 ngx_log_error(NGX_LOG_INFO, rev->log, 0, "unsupported quic version"); | |
702 ngx_http_close_connection(c); | |
703 return; | |
704 } | |
705 | |
706 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t)); | |
707 if (qc == NULL) { | |
708 ngx_http_close_connection(c); | |
709 return; | |
710 } | |
711 | |
712 c->quic = qc; | |
713 | |
714 qc->dcid.len = *b->pos++; | |
715 qc->dcid.data = ngx_pnalloc(c->pool, qc->dcid.len); | |
716 if (qc->dcid.data == NULL) { | |
717 ngx_http_close_connection(c); | |
718 return; | |
719 } | |
720 | |
721 ngx_memcpy(qc->dcid.data, b->pos, qc->dcid.len); | |
722 b->pos += qc->dcid.len; | |
723 | |
724 qc->scid.len = *b->pos++; | |
725 qc->scid.data = ngx_pnalloc(c->pool, qc->scid.len); | |
726 if (qc->scid.data == NULL) { | |
727 ngx_http_close_connection(c); | |
728 return; | |
729 } | |
730 | |
731 ngx_memcpy(qc->scid.data, b->pos, qc->scid.len); | |
732 b->pos += qc->scid.len; | |
733 | |
734 qc->token.len = ngx_quic_parse_int(&b->pos); | |
735 qc->token.data = ngx_pnalloc(c->pool, qc->token.len); | |
736 if (qc->token.data == NULL) { | |
737 ngx_http_close_connection(c); | |
738 return; | |
739 } | |
740 | |
741 ngx_memcpy(qc->token.data, b->pos, qc->token.len); | |
742 b->pos += qc->token.len; | |
743 | |
744 ngx_int_t plen = ngx_quic_parse_int(&b->pos); | |
745 | |
746 if (plen > b->last - b->pos) { | |
747 ngx_log_error(NGX_LOG_INFO, rev->log, 0, "truncated initial packet"); | |
748 ngx_http_close_connection(c); | |
749 return; | |
750 } | |
751 | |
752 /* draft-ietf-quic-tls-23#section-5.4.2: | |
753 * the Packet Number field is assumed to be 4 bytes long | |
754 * draft-ietf-quic-tls-23#section-5.4.[34]: | |
755 * AES-Based and ChaCha20-Based header protections sample 16 bytes | |
756 */ | |
757 u_char *sample = b->pos + 4; | |
758 | |
759 #if (NGX_DEBUG) | |
760 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { | |
761 m = ngx_hex_dump(buf, qc->dcid.data, qc->dcid.len) - buf; | |
762 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
763 "quic DCID: %*s, len: %uz", m, buf, qc->dcid.len); | |
764 | |
765 m = ngx_hex_dump(buf, qc->scid.data, qc->scid.len) - buf; | |
766 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
767 "quic SCID: %*s, len: %uz", m, buf, qc->scid.len); | |
768 | |
769 m = ngx_hex_dump(buf, qc->token.data, qc->token.len) - buf; | |
770 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
771 "quic token: %*s, len: %uz", m, buf, qc->token.len); | |
772 | |
773 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
774 "quic packet length: %d", plen); | |
775 | |
776 m = ngx_hex_dump(buf, sample, 16) - buf; | |
777 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
778 "quic sample: %*s", m, buf); | |
779 } | |
780 #endif | |
781 | |
782 // initial secret | |
783 | |
784 size_t is_len; | |
785 uint8_t is[SHA256_DIGEST_LENGTH]; | |
786 ngx_uint_t i; | |
787 const EVP_MD *digest; | |
788 const EVP_CIPHER *cipher; | |
789 static const uint8_t salt[20] = | |
790 "\xc3\xee\xf7\x12\xc7\x2e\xbb\x5a\x11\xa7" | |
791 "\xd2\x43\x2b\xb4\x63\x65\xbe\xf9\xf5\x02"; | |
792 | |
793 /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.3 */ | |
794 | |
795 cipher = EVP_aes_128_gcm(); | |
796 digest = EVP_sha256(); | |
797 | |
798 if (ngx_hkdf_extract(is, &is_len, digest, qc->dcid.data, qc->dcid.len, | |
799 salt, sizeof(salt)) | |
800 != NGX_OK) | |
801 { | |
802 ngx_http_close_connection(c); | |
803 return; | |
804 } | |
805 | |
806 ngx_str_t iss = { | |
807 .data = is, | |
808 .len = is_len | |
809 }; | |
810 | |
811 #if (NGX_DEBUG) | |
812 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { | |
813 m = ngx_hex_dump(buf, (uint8_t *) salt, sizeof(salt)) - buf; | |
814 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
815 "quic salt: %*s, len: %uz", m, buf, sizeof(salt)); | |
816 | |
817 m = ngx_hex_dump(buf, is, is_len) - buf; | |
818 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
819 "quic initial secret: %*s, len: %uz", m, buf, is_len); | |
820 } | |
821 #endif | |
822 | |
823 /* draft-ietf-quic-tls-23#section-5.2 */ | |
824 qc->client_in.secret.len = SHA256_DIGEST_LENGTH; | |
825 qc->server_in.secret.len = SHA256_DIGEST_LENGTH; | |
826 | |
827 qc->client_in.key.len = EVP_CIPHER_key_length(cipher); | |
828 qc->server_in.key.len = EVP_CIPHER_key_length(cipher); | |
829 | |
830 qc->client_in.hp.len = EVP_CIPHER_key_length(cipher); | |
831 qc->server_in.hp.len = EVP_CIPHER_key_length(cipher); | |
832 | |
833 qc->client_in.iv.len = EVP_CIPHER_iv_length(cipher); | |
834 qc->server_in.iv.len = EVP_CIPHER_iv_length(cipher); | |
835 | |
836 struct { | |
837 ngx_str_t label; | |
838 ngx_str_t *key; | |
839 ngx_str_t *prk; | |
840 } seq[] = { | |
841 | |
842 /* draft-ietf-quic-tls-23#section-5.2 */ | |
843 { ngx_string("tls13 client in"), &qc->client_in.secret, &iss }, | |
844 { | |
845 ngx_string("tls13 quic key"), | |
846 &qc->client_in.key, | |
847 &qc->client_in.secret, | |
848 }, | |
849 { | |
850 ngx_string("tls13 quic iv"), | |
851 &qc->client_in.iv, | |
852 &qc->client_in.secret, | |
853 }, | |
854 { | |
855 /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.4.1 */ | |
856 ngx_string("tls13 quic hp"), | |
857 &qc->client_in.hp, | |
858 &qc->client_in.secret, | |
859 }, | |
860 { ngx_string("tls13 server in"), &qc->server_in.secret, &iss }, | |
861 { | |
862 /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.3 */ | |
863 ngx_string("tls13 quic key"), | |
864 &qc->server_in.key, | |
865 &qc->server_in.secret, | |
866 }, | |
867 { | |
868 ngx_string("tls13 quic iv"), | |
869 &qc->server_in.iv, | |
870 &qc->server_in.secret, | |
871 }, | |
872 { | |
873 /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.4.1 */ | |
874 ngx_string("tls13 quic hp"), | |
875 &qc->server_in.hp, | |
876 &qc->server_in.secret, | |
877 }, | |
878 | |
879 }; | |
880 | |
881 for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) { | |
882 | |
883 if (ngx_quic_hkdf_expand(c, digest, seq[i].key, &seq[i].label, | |
884 seq[i].prk->data, seq[i].prk->len) | |
885 != NGX_OK) | |
886 { | |
887 ngx_http_close_connection(c); | |
888 return; | |
889 } | |
890 } | |
891 | |
892 // header protection | |
893 | |
894 uint8_t mask[16]; | |
895 if (ngx_quic_tls_hp(c, EVP_aes_128_ecb(), &qc->client_in, mask, sample) | |
896 != NGX_OK) | |
897 { | |
898 ngx_http_close_connection(c); | |
899 return; | |
900 } | |
901 | |
902 u_char clearflags = flags ^ (mask[0] & 0x0f); | |
903 ngx_int_t pnl = (clearflags & 0x03) + 1; | |
904 uint64_t pn = ngx_quic_parse_pn(&b->pos, pnl, &mask[1]); | |
905 | |
906 #if (NGX_DEBUG) | |
907 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { | |
908 m = ngx_hex_dump(buf, sample, 16) - buf; | |
909 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
910 "quic sample: %*s", m, buf); | |
911 | |
912 m = ngx_hex_dump(buf, mask, 5) - buf; | |
913 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
914 "quic mask: %*s", m, buf); | |
915 | |
916 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
917 "quic packet number: %uL, len: %xi", pn, pnl); | |
918 } | |
919 #endif | |
920 | |
921 // packet protection | |
922 | |
923 ngx_str_t in; | |
924 in.data = b->pos; | |
925 in.len = plen - pnl; | |
926 | |
927 ngx_str_t ad; | |
928 ad.len = b->pos - b->start; | |
929 ad.data = ngx_pnalloc(c->pool, ad.len); | |
930 if (ad.data == NULL) { | |
931 ngx_http_close_connection(c); | |
932 return; | |
933 } | |
934 | |
935 ngx_memcpy(ad.data, b->start, ad.len); | |
936 ad.data[0] = clearflags; | |
937 ad.data[ad.len - pnl] = (u_char)pn; | |
938 | |
939 uint8_t *nonce = ngx_pstrdup(c->pool, &qc->client_in.iv); | |
940 nonce[11] ^= pn; | |
941 | |
942 #if (NGX_DEBUG) | |
943 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { | |
944 m = ngx_hex_dump(buf, nonce, 12) - buf; | |
945 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
946 "quic nonce: %*s, len: %uz", m, buf, 12); | |
947 | |
948 m = ngx_hex_dump(buf, ad.data, ad.len) - buf; | |
949 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
950 "quic ad: %*s, len: %uz", m, buf, ad.len); | |
951 } | |
952 #endif | |
953 | |
954 ngx_str_t out; | |
955 | |
956 if (ngx_quic_tls_open(c, EVP_aes_128_gcm(), &qc->client_in, &out, nonce, | |
957 &in, &ad) | |
958 != NGX_OK) | |
959 { | |
960 ngx_http_close_connection(c); | |
961 return; | |
962 } | |
963 | |
964 #if (NGX_DEBUG) | |
965 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { | |
966 m = ngx_hex_dump(buf, out.data, ngx_min(out.len, 256)) - buf; | |
967 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
968 "quic packet payload: %*s%s, len: %uz", | |
969 m, buf, m < 512 ? "" : "...", out.len); | |
970 } | |
971 #endif | |
972 | |
973 if (out.data[0] != 0x06) { | |
974 ngx_log_error(NGX_LOG_INFO, rev->log, 0, | |
975 "unexpected frame in initial packet"); | |
976 ngx_http_close_connection(c); | |
977 return; | |
978 } | |
979 | |
980 if (out.data[1] != 0x00) { | |
981 ngx_log_error(NGX_LOG_INFO, rev->log, 0, | |
982 "unexpected CRYPTO offset in initial packet"); | |
983 ngx_http_close_connection(c); | |
984 return; | |
985 } | |
986 | |
987 uint8_t *crypto = &out.data[2]; | |
988 uint64_t crypto_len = ngx_quic_parse_int(&crypto); | |
989 | |
990 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
991 "quic initial packet CRYPTO length: %uL pp:%p:%p", | |
992 crypto_len, out.data, crypto); | |
993 | |
994 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); | |
995 | |
996 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER) | |
997 != NGX_OK) | |
998 { | |
999 ngx_http_close_connection(c); | |
1000 return; | |
1001 } | |
1002 | |
1003 static const uint8_t params[12] = "\x00\x0a\x00\x3a\x00\x01\x00\x00\x09\x00\x01\x03"; | |
1004 | |
1005 if (SSL_set_quic_transport_params(c->ssl->connection, params, | |
1006 sizeof(params)) == 0) | |
1007 { | |
1008 ngx_log_error(NGX_LOG_INFO, rev->log, 0, | |
1009 "SSL_set_quic_transport_params() failed"); | |
1010 ngx_http_close_connection(c); | |
1011 return; | |
1012 } | |
1013 | |
1014 n = SSL_do_handshake(c->ssl->connection); | |
1015 | |
1016 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); | |
1017 | |
1018 if (n == -1) { | |
1019 sslerr = SSL_get_error(c->ssl->connection, n); | |
1020 | |
1021 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", | |
1022 sslerr); | |
1023 } | |
1024 | |
1025 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1026 "SSL_quic_read_level: %d, SSL_quic_write_level: %d", | |
1027 (int) SSL_quic_read_level(c->ssl->connection), | |
1028 (int) SSL_quic_write_level(c->ssl->connection)); | |
1029 | |
1030 if (!SSL_provide_quic_data(c->ssl->connection, | |
1031 SSL_quic_read_level(c->ssl->connection), | |
1032 crypto, crypto_len)) | |
1033 { | |
1034 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, | |
1035 "SSL_provide_quic_data() failed"); | |
1036 ngx_http_close_connection(c); | |
1037 return; | |
1038 } | |
1039 | |
1040 n = SSL_do_handshake(c->ssl->connection); | |
1041 | |
1042 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); | |
1043 | |
1044 if (n == -1) { | |
1045 sslerr = SSL_get_error(c->ssl->connection, n); | |
1046 | |
1047 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", | |
1048 sslerr); | |
1049 | |
1050 if (sslerr == SSL_ERROR_SSL) { | |
1051 ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "SSL_do_handshake() failed"); | |
1052 } | |
1053 } | |
1054 | |
1055 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1056 "SSL_quic_read_level: %d, SSL_quic_write_level: %d", | |
1057 (int) SSL_quic_read_level(c->ssl->connection), | |
1058 (int) SSL_quic_write_level(c->ssl->connection)); | |
1059 | 679 |
1060 if (!rev->timer_set) { | 680 if (!rev->timer_set) { |
1061 ngx_add_timer(rev, c->listening->post_accept_timeout); | 681 ngx_add_timer(rev, c->listening->post_accept_timeout); |
1062 } | 682 } |
1063 | 683 |
1067 | 687 |
1068 | 688 |
1069 static void | 689 static void |
1070 ngx_http_quic_handshake_handler(ngx_event_t *rev) | 690 ngx_http_quic_handshake_handler(ngx_event_t *rev) |
1071 { | 691 { |
1072 size_t m; | |
1073 ssize_t n; | 692 ssize_t n; |
1074 ngx_str_t out; | |
1075 ngx_connection_t *c; | 693 ngx_connection_t *c; |
1076 const EVP_CIPHER *cipher; | 694 u_char buf[512]; |
1077 ngx_quic_connection_t *qc; | 695 ngx_buf_t b; |
1078 u_char buf[4096], b[512], *p; | 696 |
697 b.start = buf; | |
698 b.end = buf + 512; | |
699 b.pos = b.last = b.start; | |
1079 | 700 |
1080 c = rev->data; | 701 c = rev->data; |
1081 qc = c->quic; | |
1082 p = b; | |
1083 | 702 |
1084 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "quic handshake handler"); | 703 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "quic handshake handler"); |
1085 | 704 |
1086 if (rev->timedout) { | 705 if (rev->timedout) { |
1087 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); | 706 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); |
1092 if (c->close) { | 711 if (c->close) { |
1093 ngx_http_close_connection(c); | 712 ngx_http_close_connection(c); |
1094 return; | 713 return; |
1095 } | 714 } |
1096 | 715 |
1097 n = c->recv(c, b, sizeof(b)); | 716 n = c->recv(c, b.start, b.end - b.start); |
1098 | 717 |
1099 if (n == NGX_AGAIN) { | 718 if (n == NGX_AGAIN) { |
1100 return; | 719 return; |
1101 } | 720 } |
1102 | 721 |
1104 c->read->eof = 1; | 723 c->read->eof = 1; |
1105 ngx_http_close_connection(c); | 724 ngx_http_close_connection(c); |
1106 return; | 725 return; |
1107 } | 726 } |
1108 | 727 |
1109 m = ngx_hex_dump(buf, b, n) - buf; | 728 b.last += n; |
1110 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | 729 |
1111 "quic handshake handler: %*s, len: %uz", m, buf, n); | 730 if (ngx_quic_input(c, NULL, &b) != NGX_OK) { |
1112 | |
1113 if ((p[0] & 0xf0) != 0xe0) { | |
1114 ngx_log_error(NGX_LOG_INFO, rev->log, 0, "invalid packet type"); | |
1115 ngx_http_close_connection(c); | 731 ngx_http_close_connection(c); |
1116 return; | 732 return; |
1117 } | 733 } |
1118 | |
1119 ngx_int_t flags = *p++; | |
1120 uint32_t version = ngx_quic_parse_uint32(p); | |
1121 p += sizeof(uint32_t); | |
1122 | |
1123 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
1124 "quic flags:%xi version:%xD", flags, version); | |
1125 | |
1126 if (version != quic_version) { | |
1127 ngx_log_error(NGX_LOG_INFO, rev->log, 0, "unsupported quic version"); | |
1128 ngx_http_close_connection(c); | |
1129 return; | |
1130 } | |
1131 | |
1132 if (*p++ != qc->dcid.len) { | |
1133 ngx_log_error(NGX_LOG_INFO, rev->log, 0, "unexpected quic dcidl"); | |
1134 ngx_http_close_connection(c); | |
1135 return; | |
1136 } | |
1137 | |
1138 if (ngx_memcmp(p, qc->dcid.data, qc->dcid.len) != 0) { | |
1139 ngx_log_error(NGX_LOG_INFO, rev->log, 0, "unexpected quic dcid"); | |
1140 ngx_http_close_connection(c); | |
1141 return; | |
1142 } | |
1143 | |
1144 p += qc->dcid.len; | |
1145 | |
1146 if (*p++ != qc->scid.len) { | |
1147 ngx_log_error(NGX_LOG_INFO, rev->log, 0, "unexpected quic scidl"); | |
1148 ngx_http_close_connection(c); | |
1149 return; | |
1150 } | |
1151 | |
1152 if (ngx_memcmp(p, qc->scid.data, qc->scid.len) != 0) { | |
1153 ngx_log_error(NGX_LOG_INFO, rev->log, 0, "unexpected quic scid"); | |
1154 ngx_http_close_connection(c); | |
1155 return; | |
1156 } | |
1157 | |
1158 p += qc->scid.len; | |
1159 | |
1160 ngx_int_t plen = ngx_quic_parse_int(&p); | |
1161 | |
1162 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
1163 "quic packet length: %d", plen); | |
1164 | |
1165 if (plen > b + n - p) { | |
1166 ngx_log_error(NGX_LOG_INFO, rev->log, 0, "truncated handshake packet"); | |
1167 ngx_http_close_connection(c); | |
1168 return; | |
1169 } | |
1170 | |
1171 u_char *sample = p + 4; | |
1172 | |
1173 m = ngx_hex_dump(buf, sample, 16) - buf; | |
1174 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, rev->log, 0, "quic sample: %*s", m, buf); | |
1175 | |
1176 // header protection | |
1177 | |
1178 uint8_t mask[16]; | |
1179 if (ngx_quic_tls_hp(c, EVP_aes_128_ecb(), &qc->client_hs, mask, sample) | |
1180 != NGX_OK) | |
1181 { | |
1182 ngx_http_close_connection(c); | |
1183 return; | |
1184 } | |
1185 | |
1186 u_char clearflags = flags ^ (mask[0] & 0x0f); | |
1187 ngx_int_t pnl = (clearflags & 0x03) + 1; | |
1188 uint64_t pn = ngx_quic_parse_pn(&p, pnl, &mask[1]); | |
1189 | |
1190 #if (NGX_DEBUG) | |
1191 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { | |
1192 m = ngx_hex_dump(buf, mask, 5) - buf; | |
1193 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
1194 "quic mask: %*s", m, buf); | |
1195 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
1196 "quic clear flags: %xi", clearflags); | |
1197 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
1198 "quic packet number: %uL, len: %xi", pn, pnl); | |
1199 } | |
1200 #endif | |
1201 | |
1202 // packet protection | |
1203 | |
1204 ngx_str_t in; | |
1205 in.data = p; | |
1206 in.len = plen - pnl; | |
1207 | |
1208 ngx_str_t ad; | |
1209 ad.len = p - b; | |
1210 ad.data = ngx_pnalloc(c->pool, ad.len); | |
1211 if (ad.data == NULL) { | |
1212 ngx_http_close_connection(c); | |
1213 return; | |
1214 } | |
1215 | |
1216 ngx_memcpy(ad.data, b, ad.len); | |
1217 ad.data[0] = clearflags; | |
1218 ad.data[ad.len - pnl] = (u_char)pn; | |
1219 | |
1220 uint8_t *nonce = ngx_pstrdup(c->pool, &qc->client_hs.iv); | |
1221 nonce[11] ^= pn; | |
1222 | |
1223 #if (NGX_DEBUG) | |
1224 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { | |
1225 m = ngx_hex_dump(buf, nonce, 12) - buf; | |
1226 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
1227 "quic nonce: %*s, len: %uz", m, buf, 12); | |
1228 | |
1229 m = ngx_hex_dump(buf, ad.data, ad.len) - buf; | |
1230 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
1231 "quic ad: %*s, len: %uz", m, buf, ad.len); | |
1232 } | |
1233 #endif | |
1234 | |
1235 u_char *name = (u_char *) SSL_get_cipher(c->ssl->connection); | |
1236 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
1237 "quic ssl cipher: %s", name); | |
1238 | |
1239 if (ngx_strcasecmp(name, (u_char *) "TLS_AES_128_GCM_SHA256") == 0 | |
1240 || ngx_strcasecmp(name, (u_char *) "(NONE)") == 0) | |
1241 { | |
1242 cipher = EVP_aes_128_gcm(); | |
1243 | |
1244 } else if (ngx_strcasecmp(name, (u_char *) "TLS_AES_256_GCM_SHA384") == 0) { | |
1245 cipher = EVP_aes_256_gcm(); | |
1246 | |
1247 } else { | |
1248 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "unexpected cipher"); | |
1249 ngx_http_close_connection(c); | |
1250 return; | |
1251 } | |
1252 | |
1253 if (ngx_quic_tls_open(c, cipher, &qc->client_hs, &out, nonce, &in, &ad) | |
1254 != NGX_OK) | |
1255 { | |
1256 ngx_http_close_connection(c); | |
1257 return; | |
1258 } | |
1259 | |
1260 #if (NGX_DEBUG) | |
1261 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { | |
1262 m = ngx_hex_dump(buf, out.data, ngx_min(out.len, 256)) - buf; | |
1263 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, rev->log, 0, | |
1264 "quic packet payload: %*s%s, len: %uz", | |
1265 m, buf, m < 512 ? "" : "...", out.len); | |
1266 } | |
1267 #endif | |
1268 | |
1269 } | 734 } |
1270 | 735 |
1271 | 736 |
1272 static void | 737 static void |
1273 ngx_http_ssl_handshake(ngx_event_t *rev) | 738 ngx_http_ssl_handshake(ngx_event_t *rev) |