comparison src/event/quic/ngx_event_quic_protection.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 3443ee341cc1
children d4e02b3b734f
comparison
equal deleted inserted replaced
8693:3956bbf91002 8694:cef042935003
940 return NGX_OK; 940 return NGX_OK;
941 } 941 }
942 942
943 943
944 ngx_int_t 944 ngx_int_t
945 ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, ngx_str_t *secret, 945 ngx_quic_derive_key(ngx_log_t *log, const char *label, ngx_str_t *secret,
946 u_char *token) 946 ngx_str_t *salt, u_char *out, size_t len)
947 { 947 {
948 size_t is_len, info_len;
948 uint8_t *p; 949 uint8_t *p;
949 size_t is_len, key_len, info_len;
950 ngx_str_t label;
951 const EVP_MD *digest; 950 const EVP_MD *digest;
952 uint8_t info[20]; 951
953 uint8_t is[SHA256_DIGEST_LENGTH]; 952 uint8_t is[SHA256_DIGEST_LENGTH];
954 uint8_t key[SHA256_DIGEST_LENGTH]; 953 uint8_t info[20];
955
956 /* 10.4.2. Calculating a Stateless Reset Token */
957 954
958 digest = EVP_sha256(); 955 digest = EVP_sha256();
959 ngx_str_set(&label, "sr_token_key");
960 956
961 if (ngx_hkdf_extract(is, &is_len, digest, secret->data, secret->len, 957 if (ngx_hkdf_extract(is, &is_len, digest, secret->data, secret->len,
962 cid->data, cid->len) 958 salt->data, salt->len)
963 != NGX_OK) 959 != NGX_OK)
964 { 960 {
965 ngx_ssl_error(NGX_LOG_INFO, c->log, 0, 961 ngx_ssl_error(NGX_LOG_INFO, log, 0,
966 "ngx_hkdf_extract(%V) failed", &label); 962 "ngx_hkdf_extract(%s) failed", label);
967 return NGX_ERROR; 963 return NGX_ERROR;
968 } 964 }
969
970 key_len = SHA256_DIGEST_LENGTH;
971
972 info_len = 2 + 1 + label.len + 1;
973 965
974 info[0] = 0; 966 info[0] = 0;
975 info[1] = key_len; 967 info[1] = len;
976 info[2] = label.len; 968 info[2] = ngx_strlen(label);
977 969
978 p = ngx_cpymem(&info[3], label.data, label.len); 970 info_len = 2 + 1 + info[2] + 1;
971
972 if (info_len >= 20) {
973 ngx_log_error(NGX_LOG_INFO, log, 0,
974 "ngx_quic_create_key label \"%s\" too long", label);
975 return NGX_ERROR;
976 }
977
978 p = ngx_cpymem(&info[3], label, info[2]);
979 *p = '\0'; 979 *p = '\0';
980 980
981 if (ngx_hkdf_expand(key, key_len, digest, is, is_len, info, info_len) 981 if (ngx_hkdf_expand(out, len, digest, is, is_len, info, info_len) != NGX_OK)
982 != NGX_OK) 982 {
983 { 983 ngx_ssl_error(NGX_LOG_INFO, log, 0,
984 ngx_ssl_error(NGX_LOG_INFO, c->log, 0, 984 "ngx_hkdf_expand(%s) failed", label);
985 "ngx_hkdf_expand(%V) failed", &label); 985 return NGX_ERROR;
986 return NGX_ERROR; 986 }
987 }
988
989 ngx_memcpy(token, key, NGX_QUIC_SR_TOKEN_LEN);
990
991 #if (NGX_DEBUG)
992 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
993 "quic stateless reset token %*xs",
994 (size_t) NGX_QUIC_SR_TOKEN_LEN, token);
995 #endif
996 987
997 return NGX_OK; 988 return NGX_OK;
998 } 989 }
999 990
1000 991