mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-22 06:11:32 +02:00
MINOR: quic: Make QUIC-TLS support at least two initial salts
These salts are used to derive initial secrets to decrypt the first Initial packet. We support draft-29 and v1 QUIC version initial salts. Add parameters to our QUIC-TLS API functions used to derive these secret for these salts. Make our xprt_quic use the correct initial salt upon QUIC version field found in the first paquet. Useful to support connections with curl which use draft-29 QUIC version.
This commit is contained in:
parent
2766e78f3b
commit
2fc76cffaf
@ -27,12 +27,28 @@
|
|||||||
#include <haproxy/trace.h>
|
#include <haproxy/trace.h>
|
||||||
#include <haproxy/xprt_quic.h>
|
#include <haproxy/xprt_quic.h>
|
||||||
|
|
||||||
|
/* Initial salt depending on QUIC version to derive client/server initial secrets.
|
||||||
|
* This one is for draft-29 QUIC version.
|
||||||
|
*/
|
||||||
|
unsigned char initial_salt_draft_29[20] = {
|
||||||
|
0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c,
|
||||||
|
0x9e, 0x97, 0x86, 0xf1, 0x9c, 0x61, 0x11, 0xe0,
|
||||||
|
0x43, 0x90, 0xa8, 0x99
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char initial_salt_v1[20] = {
|
||||||
|
0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3,
|
||||||
|
0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad,
|
||||||
|
0xcc, 0xbb, 0x7f, 0x0a
|
||||||
|
};
|
||||||
|
|
||||||
void quic_tls_keys_hexdump(struct buffer *buf, struct quic_tls_secrets *secs);
|
void quic_tls_keys_hexdump(struct buffer *buf, struct quic_tls_secrets *secs);
|
||||||
|
|
||||||
void quic_tls_secret_hexdump(struct buffer *buf,
|
void quic_tls_secret_hexdump(struct buffer *buf,
|
||||||
const unsigned char *secret, size_t secret_len);
|
const unsigned char *secret, size_t secret_len);
|
||||||
|
|
||||||
int quic_derive_initial_secret(const EVP_MD *md,
|
int quic_derive_initial_secret(const EVP_MD *md,
|
||||||
|
const unsigned char *initial_salt, size_t initial_salt_sz,
|
||||||
unsigned char *initial_secret, size_t initial_secret_sz,
|
unsigned char *initial_secret, size_t initial_secret_sz,
|
||||||
const unsigned char *secret, size_t secret_sz);
|
const unsigned char *secret, size_t secret_sz);
|
||||||
|
|
||||||
@ -390,6 +406,7 @@ static inline void quic_tls_discard_keys(struct quic_enc_level *qel)
|
|||||||
* Return 1 if succeeded or 0 if not.
|
* Return 1 if succeeded or 0 if not.
|
||||||
*/
|
*/
|
||||||
static inline int qc_new_isecs(struct quic_conn *qc,
|
static inline int qc_new_isecs(struct quic_conn *qc,
|
||||||
|
const unsigned char *salt, size_t salt_len,
|
||||||
const unsigned char *cid, size_t cidlen, int server)
|
const unsigned char *cid, size_t cidlen, int server)
|
||||||
{
|
{
|
||||||
unsigned char initial_secret[32];
|
unsigned char initial_secret[32];
|
||||||
@ -404,6 +421,7 @@ static inline int qc_new_isecs(struct quic_conn *qc,
|
|||||||
ctx = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].tls_ctx;
|
ctx = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].tls_ctx;
|
||||||
quic_initial_tls_ctx_init(ctx);
|
quic_initial_tls_ctx_init(ctx);
|
||||||
if (!quic_derive_initial_secret(ctx->rx.md,
|
if (!quic_derive_initial_secret(ctx->rx.md,
|
||||||
|
salt, salt_len,
|
||||||
initial_secret, sizeof initial_secret,
|
initial_secret, sizeof initial_secret,
|
||||||
cid, cidlen))
|
cid, cidlen))
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -42,6 +42,8 @@
|
|||||||
#include <import/ebmbtree.h>
|
#include <import/ebmbtree.h>
|
||||||
|
|
||||||
#define QUIC_PROTOCOL_VERSION_DRAFT_28 0xff00001c /* draft-28 */
|
#define QUIC_PROTOCOL_VERSION_DRAFT_28 0xff00001c /* draft-28 */
|
||||||
|
#define QUIC_PROTOCOL_VERSION_DRAFT_29 0xff00001d /* draft-29 */
|
||||||
|
#define QUIC_PROTOCOL_VERSION_1 0x00000001 /* V1 */
|
||||||
|
|
||||||
#define QUIC_INITIAL_IPV4_MTU 1252 /* (bytes) */
|
#define QUIC_INITIAL_IPV4_MTU 1252 /* (bytes) */
|
||||||
#define QUIC_INITIAL_IPV6_MTU 1232
|
#define QUIC_INITIAL_IPV6_MTU 1232
|
||||||
|
@ -18,21 +18,6 @@
|
|||||||
__attribute__((format (printf, 3, 4)))
|
__attribute__((format (printf, 3, 4)))
|
||||||
void hexdump(const void *buf, size_t buflen, const char *title_fmt, ...);
|
void hexdump(const void *buf, size_t buflen, const char *title_fmt, ...);
|
||||||
|
|
||||||
/* Initial salt depending on QUIC version to derive client/server initial secrets.
|
|
||||||
* This one is for draft-29 QUIC version.
|
|
||||||
*/
|
|
||||||
unsigned char initial_salt[20] = {
|
|
||||||
0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c,
|
|
||||||
0x9e, 0x97, 0x86, 0xf1, 0x9c, 0x61, 0x11, 0xe0,
|
|
||||||
0x43, 0x90, 0xa8, 0x99
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned char initial_salt_v1[20] = {
|
|
||||||
0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3,
|
|
||||||
0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad,
|
|
||||||
0xcc, 0xbb, 0x7f, 0x0a
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Dump the RX/TX secrets of <secs> QUIC TLS secrets. */
|
/* Dump the RX/TX secrets of <secs> QUIC TLS secrets. */
|
||||||
void quic_tls_keys_hexdump(struct buffer *buf, struct quic_tls_secrets *secs)
|
void quic_tls_keys_hexdump(struct buffer *buf, struct quic_tls_secrets *secs)
|
||||||
{
|
{
|
||||||
@ -67,7 +52,7 @@ void quic_tls_secret_hexdump(struct buffer *buf,
|
|||||||
int quic_hkdf_extract(const EVP_MD *md,
|
int quic_hkdf_extract(const EVP_MD *md,
|
||||||
unsigned char *buf, size_t *buflen,
|
unsigned char *buf, size_t *buflen,
|
||||||
const unsigned char *key, size_t keylen,
|
const unsigned char *key, size_t keylen,
|
||||||
unsigned char *salt, size_t saltlen)
|
const unsigned char *salt, size_t saltlen)
|
||||||
{
|
{
|
||||||
return HKDF_extract(buf, buflen, md, key, keylen, salt, saltlen);
|
return HKDF_extract(buf, buflen, md, key, keylen, salt, saltlen);
|
||||||
}
|
}
|
||||||
@ -83,7 +68,7 @@ int quic_hkdf_expand(const EVP_MD *md,
|
|||||||
int quic_hkdf_extract(const EVP_MD *md,
|
int quic_hkdf_extract(const EVP_MD *md,
|
||||||
unsigned char *buf, size_t *buflen,
|
unsigned char *buf, size_t *buflen,
|
||||||
const unsigned char *key, size_t keylen,
|
const unsigned char *key, size_t keylen,
|
||||||
unsigned char *salt, size_t saltlen)
|
const unsigned char *salt, size_t saltlen)
|
||||||
{
|
{
|
||||||
EVP_PKEY_CTX *ctx;
|
EVP_PKEY_CTX *ctx;
|
||||||
|
|
||||||
@ -224,11 +209,12 @@ int quic_tls_derive_keys(const EVP_CIPHER *aead, const EVP_CIPHER *hp,
|
|||||||
* Returns the size of the derived secret if succeeded, 0 if not.
|
* Returns the size of the derived secret if succeeded, 0 if not.
|
||||||
*/
|
*/
|
||||||
int quic_derive_initial_secret(const EVP_MD *md,
|
int quic_derive_initial_secret(const EVP_MD *md,
|
||||||
|
const unsigned char *initial_salt, size_t initial_salt_sz,
|
||||||
unsigned char *initial_secret, size_t initial_secret_sz,
|
unsigned char *initial_secret, size_t initial_secret_sz,
|
||||||
const unsigned char *secret, size_t secret_sz)
|
const unsigned char *secret, size_t secret_sz)
|
||||||
{
|
{
|
||||||
if (!quic_hkdf_extract(md, initial_secret, &initial_secret_sz, secret, secret_sz,
|
if (!quic_hkdf_extract(md, initial_secret, &initial_secret_sz, secret, secret_sz,
|
||||||
initial_salt_v1, sizeof initial_salt_v1))
|
initial_salt, initial_salt_sz))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -3371,6 +3371,8 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
|
|||||||
int ipv4;
|
int ipv4;
|
||||||
struct quic_cid *odcid;
|
struct quic_cid *odcid;
|
||||||
struct ebmb_node *n = NULL;
|
struct ebmb_node *n = NULL;
|
||||||
|
const unsigned char *salt = initial_salt_v1;
|
||||||
|
size_t salt_len = sizeof initial_salt_v1;
|
||||||
|
|
||||||
if (pkt->type != QUIC_PACKET_TYPE_INITIAL) {
|
if (pkt->type != QUIC_PACKET_TYPE_INITIAL) {
|
||||||
TRACE_PROTO("Non Initiial packet", QUIC_EV_CONN_LPKT);
|
TRACE_PROTO("Non Initiial packet", QUIC_EV_CONN_LPKT);
|
||||||
@ -3406,7 +3408,12 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char **buf, const unsigned char *end,
|
|||||||
/* NOTE: the socket address has been concatenated to the destination ID
|
/* NOTE: the socket address has been concatenated to the destination ID
|
||||||
* chosen by the client for Initial packets.
|
* chosen by the client for Initial packets.
|
||||||
*/
|
*/
|
||||||
if (!qc_new_isecs(qc, pkt->dcid.data, pkt->odcid_len, 1)) {
|
if (pkt->version == QUIC_PROTOCOL_VERSION_DRAFT_29) {
|
||||||
|
salt = initial_salt_draft_29;
|
||||||
|
salt_len = sizeof initial_salt_draft_29;
|
||||||
|
}
|
||||||
|
if (!qc_new_isecs(qc, salt, salt_len,
|
||||||
|
pkt->dcid.data, pkt->odcid_len, 1)) {
|
||||||
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc->conn);
|
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc->conn);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -4360,7 +4367,8 @@ static int qc_conn_init(struct connection *conn, void **xprt_ctx)
|
|||||||
|
|
||||||
conn->qc = qc;
|
conn->qc = qc;
|
||||||
qc->conn = conn;
|
qc->conn = conn;
|
||||||
if (!qc_new_isecs(qc, dcid, sizeof dcid, 0))
|
if (!qc_new_isecs(qc, initial_salt_v1, sizeof initial_salt_v1,
|
||||||
|
dcid, sizeof dcid, 0))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (ssl_bio_and_sess_init(conn, srv->ssl_ctx.ctx,
|
if (ssl_bio_and_sess_init(conn, srv->ssl_ctx.ctx,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user