comparison src/event/ngx_event_quic.c @ 7659:4355efde26d8 quic

Added functions to decrypt long packets.
author Vladimir Homutov <vl@nginx.com>
date Thu, 05 Mar 2020 17:18:33 +0300
parents fb0879c65650
children 817c82af127f
comparison
equal deleted inserted replaced
7658:fb0879c65650 7659:4355efde26d8
183 typedef struct { 183 typedef struct {
184 ngx_quic_secret_t *secret; 184 ngx_quic_secret_t *secret;
185 ngx_uint_t type; 185 ngx_uint_t type;
186 ngx_uint_t *number; 186 ngx_uint_t *number;
187 ngx_uint_t flags; 187 ngx_uint_t flags;
188 ngx_uint_t version; 188 uint32_t version;
189 ngx_str_t *token; 189 ngx_str_t token;
190 ngx_quic_level_t level; 190 ngx_quic_level_t level;
191
192 /* filled in by parser */
193 ngx_str_t buf; /* quic packet from wire */
194 u_char *pos; /* current parser position */
195
196 /* cleartext fields */
197 ngx_str_t dcid;
198 ngx_str_t scid;
199
200 uint64_t pn;
201
202 ngx_str_t payload; /* decrypted payload */
203
191 } ngx_quic_header_t; 204 } ngx_quic_header_t;
192 205
193 206
194 static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, 207 static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl,
195 ngx_buf_t *b); 208 ngx_buf_t *b);
208 ngx_str_t *res); 221 ngx_str_t *res);
209 static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn); 222 static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn);
210 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, 223 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
211 enum ssl_encryption_level_t level, uint8_t alert); 224 enum ssl_encryption_level_t level, uint8_t alert);
212 225
226 static ngx_int_t ngx_quic_process_long_header(ngx_connection_t *c,
227 ngx_quic_header_t *pkt);
228 static ngx_int_t ngx_quic_process_initial_header(ngx_connection_t *c,
229 ngx_quic_header_t *pkt);
230 static ngx_int_t ngx_quic_process_handshake_header(ngx_connection_t *c,
231 ngx_quic_header_t *pkt);
232 static ngx_int_t ngx_quic_initial_secret(ngx_connection_t *c);
233 static ngx_int_t ngx_quic_decrypt(ngx_connection_t *c, ngx_quic_header_t *pkt);
234
213 static uint64_t ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask); 235 static uint64_t ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask);
214 static uint64_t ngx_quic_parse_int(u_char **pos); 236 static uint64_t ngx_quic_parse_int(u_char **pos);
215 static void ngx_quic_build_int(u_char **pos, uint64_t value); 237 static void ngx_quic_build_int(u_char **pos, uint64_t value);
216 238
217 static ngx_int_t ngx_hkdf_extract(u_char *out_key, size_t *out_len, 239 static ngx_int_t ngx_hkdf_extract(u_char *out_key, size_t *out_len,
285 307
286 if (level == ssl_encryption_initial) { 308 if (level == ssl_encryption_initial) {
287 pkt.number = &qc->initial_pn; 309 pkt.number = &qc->initial_pn;
288 pkt.flags = NGX_QUIC_PKT_INITIAL; 310 pkt.flags = NGX_QUIC_PKT_INITIAL;
289 pkt.secret = &qc->server_in; 311 pkt.secret = &qc->server_in;
290 pkt.token = &initial_token; 312 pkt.token = initial_token;
291 313
292 if (ngx_quic_create_long_packet(c, c->ssl->connection, 314 if (ngx_quic_create_long_packet(c, c->ssl->connection,
293 &pkt, payload, &res) 315 &pkt, payload, &res)
294 != NGX_OK) 316 != NGX_OK)
295 { 317 {
597 p = ngx_cpymem(p, qc->scid.data, qc->scid.len); 619 p = ngx_cpymem(p, qc->scid.data, qc->scid.len);
598 620
599 *p++ = qc->dcid.len; 621 *p++ = qc->dcid.len;
600 p = ngx_cpymem(p, qc->dcid.data, qc->dcid.len); 622 p = ngx_cpymem(p, qc->dcid.data, qc->dcid.len);
601 623
602 if (pkt->token) { // if pkt->flags & initial ? 624 if (pkt->level == ssl_encryption_initial) {
603 ngx_quic_build_int(&p, pkt->token->len); 625 ngx_quic_build_int(&p, pkt->token.len);
604 } 626 }
605 627
606 ngx_quic_build_int(&p, out.len + 1); // length (inc. pnl) 628 ngx_quic_build_int(&p, out.len + 1); // length (inc. pnl)
607 pnp = p; 629 pnp = p;
608 630
863 return 1; 885 return 1;
864 } 886 }
865 887
866 888
867 static ngx_int_t 889 static ngx_int_t
868 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_buf_t *b) 890 ngx_quic_process_long_header(ngx_connection_t *c, ngx_quic_header_t *pkt)
869 { 891 {
870 int n, sslerr; 892 u_char *p;
871 ngx_quic_connection_t *qc; 893
872 894 p = pkt->buf.data;
873 if ((b->pos[0] & 0xf0) != NGX_QUIC_PKT_INITIAL) { 895
874 ngx_log_error(NGX_LOG_INFO, c->log, 0, "invalid initial packet"); 896 ngx_quic_hexdump0(c->log, "input", pkt->buf.data, pkt->buf.len);
875 return NGX_ERROR; 897
876 } 898 if (!(p[0] & NGX_QUIC_PKT_LONG)) {
877 899 ngx_log_error(NGX_LOG_INFO, c->log, 0, "not a long packet");
878 if (ngx_buf_size(b) < 1200) { 900 return NGX_ERROR;
879 ngx_log_error(NGX_LOG_INFO, c->log, 0, "too small UDP datagram"); 901 }
880 return NGX_ERROR; 902
881 } 903 pkt->flags = *p++;
882 904
883 ngx_int_t flags = *b->pos++; 905 pkt->version = ngx_quic_parse_uint32(p);
884 uint32_t version = ngx_quic_parse_uint32(b->pos); 906 p += sizeof(uint32_t);
885 b->pos += sizeof(uint32_t);
886 907
887 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 908 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
888 "quic flags:%xi version:%xD", flags, version); 909 "quic flags:%xi version:%xD", pkt->flags, pkt->version);
889 910
890 if (version != quic_version) { 911 if (pkt->version != quic_version) {
891 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unsupported quic version"); 912 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unsupported quic version");
892 return NGX_ERROR; 913 return NGX_ERROR;
893 } 914 }
894 915
895 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t)); 916 pkt->dcid.len = *p++;
896 if (qc == NULL) { 917 pkt->dcid.data = p;
897 return NGX_ERROR; 918 p += pkt->dcid.len;
898 } 919
899 920 pkt->scid.len = *p++;
900 c->quic = qc; 921 pkt->scid.data = p;
901 922 p += pkt->scid.len;
902 qc->dcid.len = *b->pos++; 923
903 qc->dcid.data = ngx_pnalloc(c->pool, qc->dcid.len); 924 pkt->pos = p;
904 if (qc->dcid.data == NULL) { 925
905 return NGX_ERROR; 926 return NGX_OK;
906 } 927 }
907 928
908 ngx_memcpy(qc->dcid.data, b->pos, qc->dcid.len); 929
909 b->pos += qc->dcid.len; 930 static ngx_int_t
910 931 ngx_quic_process_initial_header(ngx_connection_t *c, ngx_quic_header_t *pkt)
911 qc->scid.len = *b->pos++; 932 {
912 qc->scid.data = ngx_pnalloc(c->pool, qc->scid.len); 933 u_char *p;
913 if (qc->scid.data == NULL) { 934 ngx_int_t plen;
914 return NGX_ERROR; 935
915 } 936 p = pkt->pos;
916 937
917 ngx_memcpy(qc->scid.data, b->pos, qc->scid.len); 938 pkt->token.len = ngx_quic_parse_int(&p);
918 b->pos += qc->scid.len; 939 pkt->token.data = p;
919 940
920 qc->token.len = ngx_quic_parse_int(&b->pos); 941 p += pkt->token.len;
921 qc->token.data = ngx_pnalloc(c->pool, qc->token.len); 942
922 if (qc->token.data == NULL) { 943 plen = ngx_quic_parse_int(&p);
923 return NGX_ERROR; 944
924 }
925
926 ngx_memcpy(qc->token.data, b->pos, qc->token.len);
927 b->pos += qc->token.len;
928
929 ngx_int_t plen = ngx_quic_parse_int(&b->pos);
930
931 if (plen > b->last - b->pos) {
932 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated initial packet");
933 return NGX_ERROR;
934 }
935
936 /* draft-ietf-quic-tls-23#section-5.4.2:
937 * the Packet Number field is assumed to be 4 bytes long
938 * draft-ietf-quic-tls-23#section-5.4.[34]:
939 * AES-Based and ChaCha20-Based header protections sample 16 bytes
940 */
941 u_char *sample = b->pos + 4;
942
943 ngx_quic_hexdump0(c->log, "DCID", qc->dcid.data, qc->dcid.len);
944 ngx_quic_hexdump0(c->log, "SCID", qc->scid.data, qc->scid.len);
945 ngx_quic_hexdump0(c->log, "token", qc->token.data, qc->token.len);
946 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 945 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
947 "quic packet length: %d", plen); 946 "quic packet length: %d", plen);
948 ngx_quic_hexdump0(c->log, "sample", sample, 16); 947
949 948 if (plen > pkt->buf.data + pkt->buf.len - p) {
950 949 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated initial packet");
951 // initial secret 950 return NGX_ERROR;
951 }
952
953 pkt->pos = p;
954 pkt->buf.len = plen;
955
956 ngx_quic_hexdump0(c->log, "DCID", pkt->dcid.data, pkt->dcid.len);
957 ngx_quic_hexdump0(c->log, "SCID", pkt->scid.data, pkt->scid.len);
958 ngx_quic_hexdump0(c->log, "token", pkt->token.data, pkt->token.len);
959
960 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
961 "quic packet length: %d", plen);
962
963 return NGX_OK;
964 }
965
966 static ngx_int_t
967 ngx_quic_process_handshake_header(ngx_connection_t *c, ngx_quic_header_t *pkt)
968 {
969 u_char *p;
970 ngx_int_t plen;
971
972 p = pkt->pos;
973
974 plen = ngx_quic_parse_int(&p);
975
976 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
977 "quic packet length: %d", plen);
978
979 if (plen > pkt->buf.data + pkt->buf.len - p) {
980 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated handshake packet");
981 return NGX_ERROR;
982 }
983
984 pkt->pos = p;
985 pkt->buf.len = plen;
986
987 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
988 "quic packet length: %d", plen);
989
990 return NGX_OK;
991 }
992
993
994 static ngx_int_t
995 ngx_quic_initial_secret(ngx_connection_t *c)
996 {
997 ngx_quic_connection_t *qc = c->quic;
952 998
953 size_t is_len; 999 size_t is_len;
954 uint8_t is[SHA256_DIGEST_LENGTH]; 1000 uint8_t is[SHA256_DIGEST_LENGTH];
955 ngx_uint_t i; 1001 ngx_uint_t i;
956 const EVP_MD *digest; 1002 const EVP_MD *digest;
1045 { 1091 {
1046 return NGX_ERROR; 1092 return NGX_ERROR;
1047 } 1093 }
1048 } 1094 }
1049 1095
1050 // header protection 1096 return NGX_OK;
1051 1097 }
1052 uint8_t mask[16]; 1098
1053 if (ngx_quic_tls_hp(c, EVP_aes_128_ecb(), &qc->client_in, mask, sample) 1099
1100 static ngx_int_t
1101 ngx_quic_decrypt(ngx_connection_t *c, ngx_quic_header_t *pkt)
1102 {
1103 u_char clearflags, *p, *sample;
1104 uint8_t *nonce;
1105 uint64_t pn;
1106 ngx_int_t pnl, rc;
1107 ngx_str_t in, ad;
1108
1109 const EVP_CIPHER *cipher;
1110
1111 uint8_t mask[16];
1112
1113 p = pkt->pos;
1114
1115 /* draft-ietf-quic-tls-23#section-5.4.2:
1116 * the Packet Number field is assumed to be 4 bytes long
1117 * draft-ietf-quic-tls-23#section-5.4.[34]:
1118 * AES-Based and ChaCha20-Based header protections sample 16 bytes
1119 */
1120
1121 sample = p + 4;
1122
1123 ngx_quic_hexdump0(c->log, "sample", sample, 16);
1124
1125 /* header protection */
1126
1127 if (ngx_quic_tls_hp(c, EVP_aes_128_ecb(), pkt->secret, mask, sample)
1054 != NGX_OK) 1128 != NGX_OK)
1055 { 1129 {
1056 return NGX_ERROR; 1130 return NGX_ERROR;
1057 } 1131 }
1058 1132
1059 u_char clearflags = flags ^ (mask[0] & 0x0f); 1133 clearflags = pkt->flags ^ (mask[0] & 0x0f);
1060 ngx_int_t pnl = (clearflags & 0x03) + 1; 1134 pnl = (clearflags & 0x03) + 1;
1061 uint64_t pn = ngx_quic_parse_pn(&b->pos, pnl, &mask[1]); 1135 pn = ngx_quic_parse_pn(&p, pnl, &mask[1]);
1062 1136
1063 ngx_quic_hexdump0(c->log, "sample", sample, 16); 1137 pkt->pn = pn;
1138
1064 ngx_quic_hexdump0(c->log, "mask", mask, 5); 1139 ngx_quic_hexdump0(c->log, "mask", mask, 5);
1140 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1141 "quic clear flags: %xi", clearflags);
1065 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 1142 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1066 "quic packet number: %uL, len: %xi", pn, pnl); 1143 "quic packet number: %uL, len: %xi", pn, pnl);
1067 1144
1068 // packet protection 1145 /* packet protection */
1069 1146
1070 ngx_str_t in; 1147 in.data = p;
1071 in.data = b->pos; 1148 in.len = pkt->buf.len - pnl;
1072 in.len = plen - pnl; 1149
1073 1150 ad.len = p - pkt->buf.data;;
1074 ngx_str_t ad;
1075 ad.len = b->pos - b->start;
1076 ad.data = ngx_pnalloc(c->pool, ad.len); 1151 ad.data = ngx_pnalloc(c->pool, ad.len);
1077 if (ad.data == NULL) { 1152 if (ad.data == NULL) {
1078 return NGX_ERROR; 1153 return NGX_ERROR;
1079 } 1154 }
1080 1155
1081 ngx_memcpy(ad.data, b->start, ad.len); 1156 ngx_memcpy(ad.data, pkt->buf.data, ad.len);
1082 ad.data[0] = clearflags; 1157 ad.data[0] = clearflags;
1083 ad.data[ad.len - pnl] = (u_char)pn; 1158 ad.data[ad.len - pnl] = (u_char) pn;
1084 1159
1085 uint8_t *nonce = ngx_pstrdup(c->pool, &qc->client_in.iv); 1160 nonce = ngx_pstrdup(c->pool, &pkt->secret->iv);
1086 nonce[11] ^= pn; 1161 nonce[11] ^= pn;
1087 1162
1088 ngx_quic_hexdump0(c->log, "nonce", nonce, 12); 1163 ngx_quic_hexdump0(c->log, "nonce", nonce, 12);
1089 ngx_quic_hexdump0(c->log, "ad", ad.data, ad.len); 1164 ngx_quic_hexdump0(c->log, "ad", ad.data, ad.len);
1090 1165
1091 ngx_str_t out; 1166 if (c->ssl) {
1092 1167 switch (SSL_CIPHER_get_id(SSL_get_current_cipher(c->ssl->connection)) & 0xffff) {
1093 if (ngx_quic_tls_open(c, EVP_aes_128_gcm(), &qc->client_in, &out, nonce, 1168
1094 &in, &ad) 1169 case NGX_AES_128_GCM_SHA256:
1095 != NGX_OK) 1170 cipher = EVP_aes_128_gcm();
1096 { 1171 break;
1097 return NGX_ERROR; 1172 case NGX_AES_256_GCM_SHA384:
1098 } 1173 cipher = EVP_aes_256_gcm();
1099 1174 break;
1100 ngx_quic_hexdump0(c->log, "packet payload", out.data, out.len); 1175 default:
1176 ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "unexpected cipher");
1177 return NGX_ERROR;
1178 }
1179
1180 } else {
1181 /* initial packets */
1182 cipher = EVP_aes_128_gcm();
1183 }
1184
1185 rc = ngx_quic_tls_open(c, cipher, pkt->secret, &pkt->payload,
1186 nonce, &in, &ad);
1187
1188 ngx_quic_hexdump0(c->log, "packet payload",
1189 pkt->payload.data, pkt->payload.len);
1190
1191 return rc;
1192 }
1193
1194
1195 static ngx_int_t
1196 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_buf_t *b)
1197 {
1198 int n, sslerr;
1199 ngx_str_t out;
1200 ngx_quic_connection_t *qc;
1201
1202 ngx_quic_header_t pkt = { 0 };
1203
1204 pkt.buf.data = b->start;
1205 pkt.buf.len = b->last - b->pos;
1206
1207 if (ngx_buf_size(b) < 1200) {
1208 ngx_log_error(NGX_LOG_INFO, c->log, 0, "too small UDP datagram");
1209 return NGX_ERROR;
1210 }
1211
1212 if (ngx_quic_process_long_header(c, &pkt) != NGX_OK) {
1213 return NGX_ERROR;
1214 }
1215
1216 if ((pkt.flags & 0xf0) != NGX_QUIC_PKT_INITIAL) {
1217 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1218 "invalid initial packet: 0x%x", pkt.flags);
1219 return NGX_ERROR;
1220 }
1221
1222 if (ngx_quic_process_initial_header(c, &pkt) != NGX_OK) {
1223 return NGX_ERROR;
1224 }
1225
1226 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t));
1227 if (qc == NULL) {
1228 return NGX_ERROR;
1229 }
1230
1231 c->quic = qc;
1232
1233 qc->dcid.len = pkt.dcid.len;
1234 qc->dcid.data = ngx_pnalloc(c->pool, pkt.dcid.len);
1235 if (qc->dcid.data == NULL) {
1236 return NGX_ERROR;
1237 }
1238 ngx_memcpy(qc->dcid.data, pkt.dcid.data, qc->dcid.len);
1239
1240 qc->scid.len = pkt.scid.len;
1241 qc->scid.data = ngx_pnalloc(c->pool, qc->scid.len);
1242 if (qc->scid.data == NULL) {
1243 return NGX_ERROR;
1244 }
1245 ngx_memcpy(qc->scid.data, pkt.scid.data, qc->scid.len);
1246
1247 qc->token.len = pkt.token.len;
1248 qc->token.data = ngx_pnalloc(c->pool, qc->token.len);
1249 if (qc->token.data == NULL) {
1250 return NGX_ERROR;
1251 }
1252 ngx_memcpy(qc->token.data, pkt.token.data, qc->token.len);
1253
1254
1255 if (ngx_quic_initial_secret(c) != NGX_OK) {
1256 return NGX_ERROR;
1257 }
1258
1259 pkt.secret = &qc->client_in;
1260
1261 if (ngx_quic_decrypt(c, &pkt) != NGX_OK) {
1262 return NGX_ERROR;
1263 }
1264
1265 out = pkt.payload;
1101 1266
1102 if (out.data[0] != 0x06) { 1267 if (out.data[0] != 0x06) {
1103 ngx_log_error(NGX_LOG_INFO, c->log, 0, 1268 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1104 "unexpected frame in initial packet"); 1269 "unexpected frame in initial packet");
1105 return NGX_ERROR; 1270 return NGX_ERROR;
1181 return NGX_OK; 1346 return NGX_OK;
1182 } 1347 }
1183 1348
1184 1349
1185 static ngx_int_t 1350 static ngx_int_t
1186 ngx_quic_handshake_input(ngx_connection_t *c, ngx_buf_t *bb) 1351 ngx_quic_handshake_input(ngx_connection_t *c, ngx_buf_t *b)
1187 { 1352 {
1188 int sslerr; 1353 int sslerr;
1189 u_char *p, *b;
1190 ssize_t n; 1354 ssize_t n;
1191 ngx_str_t out; 1355 ngx_str_t out;
1192 ngx_ssl_conn_t *ssl_conn; 1356 ngx_ssl_conn_t *ssl_conn;
1193 const EVP_CIPHER *cipher;
1194 ngx_quic_connection_t *qc; 1357 ngx_quic_connection_t *qc;
1358
1359 ngx_quic_header_t pkt = { 0 };
1195 1360
1196 qc = c->quic; 1361 qc = c->quic;
1197 ssl_conn = c->ssl->connection; 1362 ssl_conn = c->ssl->connection;
1198 1363
1199 n = bb->last - bb->pos; 1364 pkt.buf.data = b->start;
1200 p = bb->pos; 1365 pkt.buf.len = b->last - b->pos;
1201 b = bb->start; 1366
1202 1367 /* extract cleartext data into pkt */
1203 ngx_quic_hexdump0(c->log, "input", p, n); 1368 if (ngx_quic_process_long_header(c, &pkt) != NGX_OK) {
1204 1369 return NGX_ERROR;
1205 if ((p[0] & 0xf0) != NGX_QUIC_PKT_HANDSHAKE) { 1370 }
1206 ngx_log_error(NGX_LOG_INFO, c->log, 0, "invalid packet type"); 1371
1207 return NGX_ERROR; 1372 if (pkt.dcid.len != qc->dcid.len) {
1208 }
1209
1210 ngx_int_t flags = *p++;
1211 uint32_t version = ngx_quic_parse_uint32(p);
1212 p += sizeof(uint32_t);
1213
1214 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1215 "quic flags:%xi version:%xD", flags, version);
1216
1217 if (version != quic_version) {
1218 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unsupported quic version");
1219 return NGX_ERROR;
1220 }
1221
1222 if (*p++ != qc->dcid.len) {
1223 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcidl"); 1373 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcidl");
1224 return NGX_ERROR; 1374 return NGX_ERROR;
1225 } 1375 }
1226 1376
1227 if (ngx_memcmp(p, qc->dcid.data, qc->dcid.len) != 0) { 1377 if (ngx_memcmp(pkt.dcid.data, qc->dcid.data, qc->dcid.len) != 0) {
1228 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid"); 1378 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid");
1229 return NGX_ERROR; 1379 return NGX_ERROR;
1230 } 1380 }
1231 1381
1232 p += qc->dcid.len; 1382 if (pkt.scid.len != qc->scid.len) {
1233
1234 if (*p++ != qc->scid.len) {
1235 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scidl"); 1383 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scidl");
1236 return NGX_ERROR; 1384 return NGX_ERROR;
1237 } 1385 }
1238 1386
1239 if (ngx_memcmp(p, qc->scid.data, qc->scid.len) != 0) { 1387 if (ngx_memcmp(pkt.scid.data, qc->scid.data, qc->scid.len) != 0) {
1240 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scid"); 1388 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scid");
1241 return NGX_ERROR; 1389 return NGX_ERROR;
1242 } 1390 }
1243 1391
1244 p += qc->scid.len; 1392 if ((pkt.flags & 0xf0) != NGX_QUIC_PKT_HANDSHAKE) {
1245 1393 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1246 ngx_int_t plen = ngx_quic_parse_int(&p); 1394 "invalid packet type: 0x%x", pkt.flags);
1247 1395 return NGX_ERROR;
1248 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 1396 }
1249 "quic packet length: %d", plen); 1397
1250 1398 if (ngx_quic_process_handshake_header(c, &pkt) != NGX_OK) {
1251 if (plen > b + n - p) { 1399 return NGX_ERROR;
1252 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated handshake packet"); 1400 }
1253 return NGX_ERROR; 1401
1254 } 1402 pkt.secret = &qc->client_hs;
1255 1403
1256 u_char *sample = p + 4; 1404 if (ngx_quic_decrypt(c, &pkt) != NGX_OK) {
1257 1405 return NGX_ERROR;
1258 ngx_quic_hexdump0(c->log, "sample", sample, 16); 1406 }
1259 1407
1260 // header protection 1408 out = pkt.payload;
1261
1262 uint8_t mask[16];
1263 if (ngx_quic_tls_hp(c, EVP_aes_128_ecb(), &qc->client_hs, mask, sample)
1264 != NGX_OK)
1265 {
1266 return NGX_ERROR;
1267 }
1268
1269 u_char clearflags = flags ^ (mask[0] & 0x0f);
1270 ngx_int_t pnl = (clearflags & 0x03) + 1;
1271 uint64_t pn = ngx_quic_parse_pn(&p, pnl, &mask[1]);
1272
1273 ngx_quic_hexdump0(c->log, "mask", mask, 5);
1274 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1275 "quic clear flags: %xi", clearflags);
1276 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1277 "quic packet number: %uL, len: %xi", pn, pnl);
1278
1279 // packet protection
1280
1281 ngx_str_t in;
1282 in.data = p;
1283 in.len = plen - pnl;
1284
1285 ngx_str_t ad;
1286 ad.len = p - b;
1287 ad.data = ngx_pnalloc(c->pool, ad.len);
1288 if (ad.data == NULL) {
1289 return NGX_ERROR;
1290 }
1291
1292 ngx_memcpy(ad.data, b, ad.len);
1293 ad.data[0] = clearflags;
1294 ad.data[ad.len - pnl] = (u_char)pn;
1295
1296 uint8_t *nonce = ngx_pstrdup(c->pool, &qc->client_hs.iv);
1297 nonce[11] ^= pn;
1298
1299 ngx_quic_hexdump0(c->log, "nonce", nonce, 12);
1300 ngx_quic_hexdump0(c->log, "ad", ad.data, ad.len);
1301
1302 switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl_conn)) & 0xffff) {
1303
1304 case NGX_AES_128_GCM_SHA256:
1305 cipher = EVP_aes_128_gcm();
1306 break;
1307
1308 case NGX_AES_256_GCM_SHA384:
1309 cipher = EVP_aes_256_gcm();
1310 break;
1311
1312 default:
1313 ngx_ssl_error(NGX_LOG_INFO, c->log, 0, "unexpected cipher");
1314 return NGX_ERROR;
1315 }
1316
1317 if (ngx_quic_tls_open(c, cipher, &qc->client_hs, &out, nonce, &in, &ad)
1318 != NGX_OK)
1319 {
1320 return NGX_ERROR;
1321 }
1322
1323 ngx_quic_hexdump0(c->log, "packet payload", out.data, out.len);
1324 1409
1325 if (out.data[0] != 0x06) { 1410 if (out.data[0] != 0x06) {
1326 ngx_log_error(NGX_LOG_INFO, c->log, 0, 1411 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1327 "non-CRYPTO frame in HS packet, skipping"); 1412 "non-CRYPTO frame in HS packet, skipping");
1328 return NGX_OK; 1413 return NGX_OK;
1386 return 0; 1471 return 0;
1387 } 1472 }
1388 1473
1389 frame->level = ssl_encryption_handshake; 1474 frame->level = ssl_encryption_handshake;
1390 frame->type = NGX_QUIC_FT_ACK; 1475 frame->type = NGX_QUIC_FT_ACK;
1391 frame->u.ack.pn = pn; 1476 frame->u.ack.pn = pkt.pn;
1392 1477
1393 ngx_sprintf(frame->info, "ACK for PN=%d at handshake level, in respond to client finished", pn); 1478 ngx_sprintf(frame->info, "ACK for PN=%d at handshake level, in respond to client finished", pkt.pn);
1394 ngx_quic_queue_frame(qc, frame); 1479 ngx_quic_queue_frame(qc, frame);
1395 1480
1396 if (ngx_quic_output(c) != NGX_OK) { 1481 if (ngx_quic_output(c) != NGX_OK) {
1397 return 0; 1482 return 0;
1398 } 1483 }