1 /* 2 * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include "internal/quic_record_util.h" 11 #include "internal/quic_record_rx.h" 12 #include "internal/quic_record_tx.h" 13 #include "internal/quic_wire_pkt.h" 14 #include "../ssl_local.h" 15 #include <openssl/kdf.h> 16 #include <openssl/core_names.h> 17 18 /* 19 * QUIC Key Derivation Utilities 20 * ============================= 21 */ 22 int ossl_quic_hkdf_extract(OSSL_LIB_CTX *libctx, 23 const char *propq, 24 const EVP_MD *md, 25 const unsigned char *salt, size_t salt_len, 26 const unsigned char *ikm, size_t ikm_len, 27 unsigned char *out, size_t out_len) 28 { 29 int ret = 0; 30 EVP_KDF *kdf = NULL; 31 EVP_KDF_CTX *kctx = NULL; 32 OSSL_PARAM params[8], *p = params; 33 int key_check = 0; 34 int mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY; 35 const char *md_name; 36 37 if ((md_name = EVP_MD_get0_name(md)) == NULL 38 || (kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_HKDF, propq)) == NULL 39 || (kctx = EVP_KDF_CTX_new(kdf)) == NULL) 40 goto err; 41 42 /* 43 * According to RFC 9000, the length of destination connection ID must be 44 * at least 8 bytes. It means that the length of destination connection ID 45 * may be less than the minimum length for HKDF required by FIPS provider. 46 * 47 * Therefore, we need to set `key-check` to zero to allow using destination 48 * connection ID as IKM. 49 */ 50 *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_FIPS_KEY_CHECK, &key_check); 51 *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode); 52 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, 53 (char *)md_name, 0); 54 *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, 55 (unsigned char *)salt, salt_len); 56 *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, 57 (unsigned char *)ikm, ikm_len); 58 *p++ = OSSL_PARAM_construct_end(); 59 60 ret = EVP_KDF_derive(kctx, out, out_len, params); 61 62 err: 63 EVP_KDF_CTX_free(kctx); 64 EVP_KDF_free(kdf); 65 return ret; 66 } 67 68 /* Constants used for key derivation in QUIC v1. */ 69 static const unsigned char quic_client_in_label[] = { 70 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e /* "client in" */ 71 }; 72 static const unsigned char quic_server_in_label[] = { 73 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x69, 0x6e /* "server in" */ 74 }; 75 76 /* Salt used to derive Initial packet protection keys (RFC 9001 Section 5.2). */ 77 static const unsigned char quic_v1_initial_salt[] = { 78 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 79 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a 80 }; 81 82 int ossl_quic_provide_initial_secret(OSSL_LIB_CTX *libctx, 83 const char *propq, 84 const QUIC_CONN_ID *dst_conn_id, 85 int is_server, 86 struct ossl_qrx_st *qrx, 87 struct ossl_qtx_st *qtx) 88 { 89 unsigned char initial_secret[32]; 90 unsigned char client_initial_secret[32], server_initial_secret[32]; 91 unsigned char *rx_secret, *tx_secret; 92 EVP_MD *sha256; 93 94 if (qrx == NULL && qtx == NULL) 95 return 1; 96 97 /* Initial encryption always uses SHA-256. */ 98 if ((sha256 = EVP_MD_fetch(libctx, "SHA256", propq)) == NULL) 99 return 0; 100 101 if (is_server) { 102 rx_secret = client_initial_secret; 103 tx_secret = server_initial_secret; 104 } else { 105 rx_secret = server_initial_secret; 106 tx_secret = client_initial_secret; 107 } 108 109 /* Derive initial secret from destination connection ID. */ 110 if (!ossl_quic_hkdf_extract(libctx, propq, 111 sha256, 112 quic_v1_initial_salt, 113 sizeof(quic_v1_initial_salt), 114 dst_conn_id->id, 115 dst_conn_id->id_len, 116 initial_secret, 117 sizeof(initial_secret))) 118 goto err; 119 120 /* Derive "client in" secret. */ 121 if (((qtx != NULL && tx_secret == client_initial_secret) 122 || (qrx != NULL && rx_secret == client_initial_secret)) 123 && !tls13_hkdf_expand_ex(libctx, propq, 124 sha256, 125 initial_secret, 126 quic_client_in_label, 127 sizeof(quic_client_in_label), 128 NULL, 0, 129 client_initial_secret, 130 sizeof(client_initial_secret), 1)) 131 goto err; 132 133 /* Derive "server in" secret. */ 134 if (((qtx != NULL && tx_secret == server_initial_secret) 135 || (qrx != NULL && rx_secret == server_initial_secret)) 136 && !tls13_hkdf_expand_ex(libctx, propq, 137 sha256, 138 initial_secret, 139 quic_server_in_label, 140 sizeof(quic_server_in_label), 141 NULL, 0, 142 server_initial_secret, 143 sizeof(server_initial_secret), 1)) 144 goto err; 145 146 /* Setup RX EL. Initial encryption always uses AES-128-GCM. */ 147 if (qrx != NULL 148 && !ossl_qrx_provide_secret(qrx, QUIC_ENC_LEVEL_INITIAL, 149 QRL_SUITE_AES128GCM, 150 sha256, 151 rx_secret, 152 sizeof(server_initial_secret))) 153 goto err; 154 155 /* 156 * ossl_qrx_provide_secret takes ownership of our ref to SHA256, so if we 157 * are initialising both sides, get a new ref for the following call for the 158 * TX side. 159 */ 160 if (qrx != NULL && qtx != NULL && !EVP_MD_up_ref(sha256)) { 161 sha256 = NULL; 162 goto err; 163 } 164 165 /* Setup TX cipher. */ 166 if (qtx != NULL 167 && !ossl_qtx_provide_secret(qtx, QUIC_ENC_LEVEL_INITIAL, 168 QRL_SUITE_AES128GCM, 169 sha256, 170 tx_secret, 171 sizeof(server_initial_secret))) 172 goto err; 173 174 return 1; 175 176 err: 177 EVP_MD_free(sha256); 178 return 0; 179 } 180 181 /* 182 * QUIC Record Layer Ciphersuite Info 183 * ================================== 184 */ 185 186 struct suite_info { 187 const char *cipher_name, *md_name; 188 uint32_t secret_len, cipher_key_len, cipher_iv_len, cipher_tag_len; 189 uint32_t hdr_prot_key_len, hdr_prot_cipher_id; 190 uint64_t max_pkt, max_forged_pkt; 191 }; 192 193 static const struct suite_info suite_aes128gcm = { 194 "AES-128-GCM", 195 "SHA256", 196 32, 197 16, 198 12, 199 16, 200 16, 201 QUIC_HDR_PROT_CIPHER_AES_128, 202 ((uint64_t)1) << 23, /* Limits as prescribed by RFC 9001 */ 203 ((uint64_t)1) << 52, 204 }; 205 206 static const struct suite_info suite_aes256gcm = { 207 "AES-256-GCM", 208 "SHA384", 209 48, 210 32, 211 12, 212 16, 213 32, 214 QUIC_HDR_PROT_CIPHER_AES_256, 215 ((uint64_t)1) << 23, /* Limits as prescribed by RFC 9001 */ 216 ((uint64_t)1) << 52, 217 }; 218 219 static const struct suite_info suite_chacha20poly1305 = { 220 "ChaCha20-Poly1305", 221 "SHA256", 222 32, 223 32, 224 12, 225 16, 226 32, 227 QUIC_HDR_PROT_CIPHER_CHACHA, 228 /* Do not use UINT64_MAX here as this represents an invalid value */ 229 UINT64_MAX - 1, /* No applicable limit for this suite (RFC 9001) */ 230 ((uint64_t)1) << 36, /* Limit as prescribed by RFC 9001 */ 231 }; 232 233 static const struct suite_info *get_suite(uint32_t suite_id) 234 { 235 switch (suite_id) { 236 case QRL_SUITE_AES128GCM: 237 return &suite_aes128gcm; 238 case QRL_SUITE_AES256GCM: 239 return &suite_aes256gcm; 240 case QRL_SUITE_CHACHA20POLY1305: 241 return &suite_chacha20poly1305; 242 default: 243 return NULL; 244 } 245 } 246 247 const char *ossl_qrl_get_suite_cipher_name(uint32_t suite_id) 248 { 249 const struct suite_info *c = get_suite(suite_id); 250 return c != NULL ? c->cipher_name : NULL; 251 } 252 253 const char *ossl_qrl_get_suite_md_name(uint32_t suite_id) 254 { 255 const struct suite_info *c = get_suite(suite_id); 256 return c != NULL ? c->md_name : NULL; 257 } 258 259 uint32_t ossl_qrl_get_suite_secret_len(uint32_t suite_id) 260 { 261 const struct suite_info *c = get_suite(suite_id); 262 return c != NULL ? c->secret_len : 0; 263 } 264 265 uint32_t ossl_qrl_get_suite_cipher_key_len(uint32_t suite_id) 266 { 267 const struct suite_info *c = get_suite(suite_id); 268 return c != NULL ? c->cipher_key_len : 0; 269 } 270 271 uint32_t ossl_qrl_get_suite_cipher_iv_len(uint32_t suite_id) 272 { 273 const struct suite_info *c = get_suite(suite_id); 274 return c != NULL ? c->cipher_iv_len : 0; 275 } 276 277 uint32_t ossl_qrl_get_suite_cipher_tag_len(uint32_t suite_id) 278 { 279 const struct suite_info *c = get_suite(suite_id); 280 return c != NULL ? c->cipher_tag_len : 0; 281 } 282 283 uint32_t ossl_qrl_get_suite_hdr_prot_cipher_id(uint32_t suite_id) 284 { 285 const struct suite_info *c = get_suite(suite_id); 286 return c != NULL ? c->hdr_prot_cipher_id : 0; 287 } 288 289 uint32_t ossl_qrl_get_suite_hdr_prot_key_len(uint32_t suite_id) 290 { 291 const struct suite_info *c = get_suite(suite_id); 292 return c != NULL ? c->hdr_prot_key_len : 0; 293 } 294 295 uint64_t ossl_qrl_get_suite_max_pkt(uint32_t suite_id) 296 { 297 const struct suite_info *c = get_suite(suite_id); 298 return c != NULL ? c->max_pkt : UINT64_MAX; 299 } 300 301 uint64_t ossl_qrl_get_suite_max_forged_pkt(uint32_t suite_id) 302 { 303 const struct suite_info *c = get_suite(suite_id); 304 return c != NULL ? c->max_forged_pkt : UINT64_MAX; 305 } 306