Mercurial > hg > nginx
comparison src/event/quic/ngx_event_quic.c @ 8694:cef042935003 quic
QUIC: the "quic_host_key" directive.
The token generation in QUIC is reworked. Single host key is used to generate
all required keys of needed sizes using HKDF.
The "quic_stateless_reset_token_key" directive is removed. Instead, the
"quic_host_key" directive is used, which reads key from file, or sets it
to random bytes if not specified.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Mon, 08 Feb 2021 16:49:33 +0300 |
parents | 3956bbf91002 |
children | 0b3d70fbba99 |
comparison
equal
deleted
inserted
replaced
8693:3956bbf91002 | 8694:cef042935003 |
---|---|
223 | 223 |
224 static ngx_quic_connection_t *ngx_quic_new_connection(ngx_connection_t *c, | 224 static ngx_quic_connection_t *ngx_quic_new_connection(ngx_connection_t *c, |
225 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); | 225 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); |
226 static ngx_int_t ngx_quic_send_stateless_reset(ngx_connection_t *c, | 226 static ngx_int_t ngx_quic_send_stateless_reset(ngx_connection_t *c, |
227 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); | 227 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); |
228 static ngx_int_t ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, | |
229 u_char *secret, u_char *token); | |
228 static ngx_int_t ngx_quic_process_stateless_reset(ngx_connection_t *c, | 230 static ngx_int_t ngx_quic_process_stateless_reset(ngx_connection_t *c, |
229 ngx_quic_header_t *pkt); | 231 ngx_quic_header_t *pkt); |
230 static ngx_int_t ngx_quic_negotiate_version(ngx_connection_t *c, | 232 static ngx_int_t ngx_quic_negotiate_version(ngx_connection_t *c, |
231 ngx_quic_header_t *inpkt); | 233 ngx_quic_header_t *inpkt); |
232 static ngx_int_t ngx_quic_create_server_id(ngx_connection_t *c, u_char *id); | 234 static ngx_int_t ngx_quic_create_server_id(ngx_connection_t *c, u_char *id); |
1243 buf[0] &= ~NGX_QUIC_PKT_LONG; | 1245 buf[0] &= ~NGX_QUIC_PKT_LONG; |
1244 buf[0] |= NGX_QUIC_PKT_FIXED_BIT; | 1246 buf[0] |= NGX_QUIC_PKT_FIXED_BIT; |
1245 | 1247 |
1246 token = &buf[len - NGX_QUIC_SR_TOKEN_LEN]; | 1248 token = &buf[len - NGX_QUIC_SR_TOKEN_LEN]; |
1247 | 1249 |
1248 if (ngx_quic_new_sr_token(c, &pkt->dcid, &conf->sr_token_key, token) | 1250 if (ngx_quic_new_sr_token(c, &pkt->dcid, conf->sr_token_key, token) |
1249 != NGX_OK) | 1251 != NGX_OK) |
1250 { | 1252 { |
1251 return NGX_ERROR; | 1253 return NGX_ERROR; |
1252 } | 1254 } |
1253 | 1255 |
1254 (void) ngx_quic_send(c, buf, len); | 1256 (void) ngx_quic_send(c, buf, len); |
1255 | 1257 |
1256 return NGX_DECLINED; | 1258 return NGX_DECLINED; |
1259 } | |
1260 | |
1261 | |
1262 static ngx_int_t | |
1263 ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, u_char *secret, | |
1264 u_char *token) | |
1265 { | |
1266 ngx_str_t tmp; | |
1267 | |
1268 tmp.data = secret; | |
1269 tmp.len = NGX_QUIC_SR_KEY_LEN; | |
1270 | |
1271 if (ngx_quic_derive_key(c->log, "sr_token_key", &tmp, cid, token, | |
1272 NGX_QUIC_SR_TOKEN_LEN) | |
1273 != NGX_OK) | |
1274 { | |
1275 return NGX_ERROR; | |
1276 } | |
1277 | |
1278 #if (NGX_DEBUG) | |
1279 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1280 "quic stateless reset token %*xs", | |
1281 (size_t) NGX_QUIC_SR_TOKEN_LEN, token); | |
1282 #endif | |
1283 | |
1284 return NGX_OK; | |
1257 } | 1285 } |
1258 | 1286 |
1259 | 1287 |
1260 static ngx_int_t | 1288 static ngx_int_t |
1261 ngx_quic_process_stateless_reset(ngx_connection_t *c, ngx_quic_header_t *pkt) | 1289 ngx_quic_process_stateless_reset(ngx_connection_t *c, ngx_quic_header_t *pkt) |
1389 ngx_quic_header_t pkt; | 1417 ngx_quic_header_t pkt; |
1390 | 1418 |
1391 u_char buf[NGX_QUIC_RETRY_BUFFER_SIZE]; | 1419 u_char buf[NGX_QUIC_RETRY_BUFFER_SIZE]; |
1392 u_char dcid[NGX_QUIC_SERVER_CID_LEN]; | 1420 u_char dcid[NGX_QUIC_SERVER_CID_LEN]; |
1393 | 1421 |
1394 expires = ngx_time() + NGX_QUIC_RETRY_LIFETIME; | 1422 expires = ngx_time() + NGX_QUIC_RETRY_TOKEN_LIFETIME; |
1395 | 1423 |
1396 if (ngx_quic_new_token(c, conf->token_key, &token, &inpkt->dcid, expires, 1) | 1424 if (ngx_quic_new_token(c, conf->av_token_key, &token, &inpkt->dcid, |
1425 expires, 1) | |
1397 != NGX_OK) | 1426 != NGX_OK) |
1398 { | 1427 { |
1399 return NGX_ERROR; | 1428 return NGX_ERROR; |
1400 } | 1429 } |
1401 | 1430 |
1721 if (SSL_CTX_get_max_early_data(qc->conf->ssl->ctx)) { | 1750 if (SSL_CTX_get_max_early_data(qc->conf->ssl->ctx)) { |
1722 SSL_set_quic_early_data_enabled(ssl_conn, 1); | 1751 SSL_set_quic_early_data_enabled(ssl_conn, 1); |
1723 } | 1752 } |
1724 #endif | 1753 #endif |
1725 | 1754 |
1726 if (ngx_quic_new_sr_token(c, &qc->dcid, &qc->conf->sr_token_key, | 1755 if (ngx_quic_new_sr_token(c, &qc->dcid, qc->conf->sr_token_key, |
1727 qc->tp.sr_token) | 1756 qc->tp.sr_token) |
1728 != NGX_OK) | 1757 != NGX_OK) |
1729 { | 1758 { |
1730 return NGX_ERROR; | 1759 return NGX_ERROR; |
1731 } | 1760 } |
2233 pkt->scid.len, &pkt->scid); | 2262 pkt->scid.len, &pkt->scid); |
2234 } | 2263 } |
2235 | 2264 |
2236 if (pkt->level == ssl_encryption_initial) { | 2265 if (pkt->level == ssl_encryption_initial) { |
2237 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | 2266 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, |
2238 "quic token len:%uz %xV", | 2267 "quic address validation token len:%uz %xV", |
2239 pkt->token.len, &pkt->token); | 2268 pkt->token.len, &pkt->token); |
2240 } | 2269 } |
2241 #endif | 2270 #endif |
2242 | 2271 |
2243 qc = ngx_quic_get_connection(c); | 2272 qc = ngx_quic_get_connection(c); |
2304 | 2333 |
2305 /* process retry and initialize connection IDs */ | 2334 /* process retry and initialize connection IDs */ |
2306 | 2335 |
2307 if (pkt->token.len) { | 2336 if (pkt->token.len) { |
2308 | 2337 |
2309 rc = ngx_quic_validate_token(c, conf->token_key, pkt); | 2338 rc = ngx_quic_validate_token(c, conf->av_token_key, pkt); |
2310 | 2339 |
2311 if (rc == NGX_ERROR) { | 2340 if (rc == NGX_ERROR) { |
2312 /* internal error */ | 2341 /* internal error */ |
2313 return NGX_ERROR; | 2342 return NGX_ERROR; |
2314 | 2343 |
2319 "cannot decrypt token"); | 2348 "cannot decrypt token"); |
2320 } else if (rc == NGX_DECLINED) { | 2349 } else if (rc == NGX_DECLINED) { |
2321 /* token is invalid */ | 2350 /* token is invalid */ |
2322 | 2351 |
2323 if (pkt->retried) { | 2352 if (pkt->retried) { |
2324 /* invalid Retry token */ | 2353 /* invalid address validation token */ |
2325 return ngx_quic_send_early_cc(c, pkt, | 2354 return ngx_quic_send_early_cc(c, pkt, |
2326 NGX_QUIC_ERR_INVALID_TOKEN, | 2355 NGX_QUIC_ERR_INVALID_TOKEN, |
2327 "invalid token"); | 2356 "invalid address validation token"); |
2328 } else if (conf->retry) { | 2357 } else if (conf->retry) { |
2329 /* invalid NEW_TOKEN */ | 2358 /* invalid NEW_TOKEN */ |
2330 return ngx_quic_send_retry(c, conf, pkt); | 2359 return ngx_quic_send_retry(c, conf, pkt); |
2331 } | 2360 } |
2332 } | 2361 } |
3284 return NGX_OK; | 3313 return NGX_OK; |
3285 } | 3314 } |
3286 | 3315 |
3287 expires = ngx_time() + NGX_QUIC_NEW_TOKEN_LIFETIME; | 3316 expires = ngx_time() + NGX_QUIC_NEW_TOKEN_LIFETIME; |
3288 | 3317 |
3289 if (ngx_quic_new_token(c, qc->conf->token_key, &token, NULL, expires, 0) | 3318 if (ngx_quic_new_token(c, qc->conf->av_token_key, &token, NULL, expires, 0) |
3290 != NGX_OK) | 3319 != NGX_OK) |
3291 { | 3320 { |
3292 return NGX_ERROR; | 3321 return NGX_ERROR; |
3293 } | 3322 } |
3294 | 3323 |
4665 frame->u.ncid.seqnum = sid->seqnum; | 4694 frame->u.ncid.seqnum = sid->seqnum; |
4666 frame->u.ncid.retire = 0; | 4695 frame->u.ncid.retire = 0; |
4667 frame->u.ncid.len = NGX_QUIC_SERVER_CID_LEN; | 4696 frame->u.ncid.len = NGX_QUIC_SERVER_CID_LEN; |
4668 ngx_memcpy(frame->u.ncid.cid, id, NGX_QUIC_SERVER_CID_LEN); | 4697 ngx_memcpy(frame->u.ncid.cid, id, NGX_QUIC_SERVER_CID_LEN); |
4669 | 4698 |
4670 if (ngx_quic_new_sr_token(c, &dcid, &qc->conf->sr_token_key, | 4699 if (ngx_quic_new_sr_token(c, &dcid, qc->conf->sr_token_key, |
4671 frame->u.ncid.srt) | 4700 frame->u.ncid.srt) |
4672 != NGX_OK) | 4701 != NGX_OK) |
4673 { | 4702 { |
4674 return NGX_ERROR; | 4703 return NGX_ERROR; |
4675 } | 4704 } |