comparison src/event/ngx_event_quic_protection.c @ 8339:aba84d9ab256 quic

Parsing of truncated packet numbers. For sample decoding algorithm, see quic-transport-27#appendix-A.
author Sergey Kandaurov <pluknet@nginx.com>
date Thu, 16 Apr 2020 12:46:48 +0300
parents 7cca3624f9c4
children 2f900ae486bc
comparison
equal deleted inserted replaced
8338:0f9e9786b90d 8339:aba84d9ab256
34 const u_char *info, size_t info_len); 34 const u_char *info, size_t info_len);
35 static ngx_int_t ngx_hkdf_extract(u_char *out_key, size_t *out_len, 35 static ngx_int_t ngx_hkdf_extract(u_char *out_key, size_t *out_len,
36 const EVP_MD *digest, const u_char *secret, size_t secret_len, 36 const EVP_MD *digest, const u_char *secret, size_t secret_len,
37 const u_char *salt, size_t salt_len); 37 const u_char *salt, size_t salt_len);
38 38
39 static uint64_t ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask); 39 static uint64_t ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask,
40 uint64_t *largest_pn);
40 static void ngx_quic_compute_nonce(u_char *nonce, size_t len, uint64_t pn); 41 static void ngx_quic_compute_nonce(u_char *nonce, size_t len, uint64_t pn);
41 static ngx_int_t ngx_quic_ciphers(ngx_ssl_conn_t *ssl_conn, 42 static ngx_int_t ngx_quic_ciphers(ngx_ssl_conn_t *ssl_conn,
42 ngx_quic_ciphers_t *ciphers, enum ssl_encryption_level_t level); 43 ngx_quic_ciphers_t *ciphers, enum ssl_encryption_level_t level);
43 44
44 static ngx_int_t ngx_quic_tls_open(const ngx_quic_cipher_t *cipher, 45 static ngx_int_t ngx_quic_tls_open(const ngx_quic_cipher_t *cipher,
868 return NGX_OK; 869 return NGX_OK;
869 } 870 }
870 871
871 872
872 static uint64_t 873 static uint64_t
873 ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask) 874 ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask,
875 uint64_t *largest_pn)
874 { 876 {
875 u_char *p; 877 u_char *p;
876 uint64_t value; 878 uint64_t truncated_pn, expected_pn, candidate_pn;
879 uint64_t pn_nbits, pn_win, pn_hwin, pn_mask;
880
881 pn_nbits = ngx_min(len * 8, 62);
877 882
878 p = *pos; 883 p = *pos;
879 value = *p++ ^ *mask++; 884 truncated_pn = *p++ ^ *mask++;
880 885
881 while (--len) { 886 while (--len) {
882 value = (value << 8) + (*p++ ^ *mask++); 887 truncated_pn = (truncated_pn << 8) + (*p++ ^ *mask++);
883 } 888 }
884 889
885 *pos = p; 890 *pos = p;
886 return value; 891
892 expected_pn = *largest_pn + 1;
893 pn_win = 1 << pn_nbits;
894 pn_hwin = pn_win / 2;
895 pn_mask = pn_win - 1;
896
897 candidate_pn = (expected_pn & ~pn_mask) | truncated_pn;
898
899 if ((int64_t) candidate_pn <= (int64_t) (expected_pn - pn_hwin)
900 && candidate_pn < (1ULL << 62) - pn_win)
901 {
902 candidate_pn += pn_win;
903
904 } else if (candidate_pn > expected_pn + pn_hwin
905 && candidate_pn >= pn_win)
906 {
907 candidate_pn -= pn_win;
908 }
909
910 *largest_pn = ngx_max((int64_t) *largest_pn, (int64_t) candidate_pn);
911
912 return candidate_pn;
887 } 913 }
888 914
889 915
890 static void 916 static void
891 ngx_quic_compute_nonce(u_char *nonce, size_t len, uint64_t pn) 917 ngx_quic_compute_nonce(u_char *nonce, size_t len, uint64_t pn)
908 return ngx_quic_create_long_packet(pkt, ssl_conn, res); 934 return ngx_quic_create_long_packet(pkt, ssl_conn, res);
909 } 935 }
910 936
911 937
912 ngx_int_t 938 ngx_int_t
913 ngx_quic_decrypt(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn) 939 ngx_quic_decrypt(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn,
940 uint64_t *largest_pn)
914 { 941 {
915 u_char clearflags, *p, *sample; 942 u_char clearflags, *p, *sample;
916 uint64_t pn; 943 uint64_t pn;
917 ngx_int_t pnl, rc, key_phase; 944 ngx_int_t pnl, rc, key_phase;
918 ngx_str_t in, ad; 945 ngx_str_t in, ad;
958 pkt->key_update = 1; 985 pkt->key_update = 1;
959 } 986 }
960 } 987 }
961 988
962 pnl = (clearflags & 0x03) + 1; 989 pnl = (clearflags & 0x03) + 1;
963 pn = ngx_quic_parse_pn(&p, pnl, &mask[1]); 990 pn = ngx_quic_parse_pn(&p, pnl, &mask[1], largest_pn);
964 991
965 pkt->pn = pn; 992 pkt->pn = pn;
966 993
967 ngx_quic_hexdump0(pkt->log, "mask", mask, 5); 994 ngx_quic_hexdump0(pkt->log, "mask", mask, 5);
968 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0, 995 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,