11#if (PC_ENABLE_HTTP3 || PC_ENABLE_DTLS)
22 static constexpr uint16_t TLS_EXT_SERVER_NAME = 0x0000;
23 static constexpr uint16_t TLS_EXT_SUPPORTED_GROUPS = 0x000a;
24 static constexpr uint16_t TLS_EXT_SIGNATURE_ALGORITHMS = 0x000d;
25 static constexpr uint16_t TLS_EXT_ALPN = 0x0010;
26 static constexpr uint16_t TLS_EXT_CLIENT_CERTIFICATE_TYPE = 0x0013;
27 static constexpr uint16_t TLS_EXT_SERVER_CERTIFICATE_TYPE = 0x0014;
28 static constexpr uint16_t TLS_EXT_SUPPORTED_VERSIONS = 0x002b;
29 static constexpr uint16_t TLS_EXT_COOKIE = 0x002c;
30 static constexpr uint16_t TLS_EXT_KEY_SHARE = 0x0033;
31 static constexpr uint16_t TLS_EXT_CONNECTION_ID = 0x0036;
47void w_u8(Writer *w, uint8_t v)
58void w_u16(Writer *w, uint16_t v)
60 w_u8(w, (uint8_t)(v >> 8));
63void w_u24(Writer *w, uint32_t v)
65 w_u8(w, (uint8_t)(v >> 16));
66 w_u8(w, (uint8_t)(v >> 8));
69void w_bytes(Writer *w,
const uint8_t *b,
size_t n)
78 if (w->pos > w->cap || n > w->cap - w->pos)
83 memcpy(w->buf + w->pos, b, n);
87size_t w_mark(Writer *w,
size_t nbytes)
90 for (
size_t i = 0; i < nbytes; i++)
96void w_patch16(Writer *w,
size_t at)
102 uint16_t len = (uint16_t)(w->pos - at - 2);
103 w->buf[at] = (uint8_t)(len >> 8);
104 w->buf[at + 1] = (uint8_t)len;
106void w_patch24(Writer *w,
size_t at)
112 uint32_t len = (uint32_t)(w->pos - at - 3);
113 w->buf[at] = (uint8_t)(len >> 16);
114 w->buf[at + 1] = (uint8_t)(len >> 8);
115 w->buf[at + 2] = (uint8_t)len;
125bool r_u8(Reader *r, uint8_t *v)
127 if (r->pos + 1 > r->len)
131 *v = r->buf[r->pos++];
134bool r_u16(Reader *r, uint16_t *v)
136 if (r->pos + 2 > r->len)
140 *v = (uint16_t)((r->buf[r->pos] << 8) | r->buf[r->pos + 1]);
144bool r_u24(Reader *r, uint32_t *v)
146 if (r->pos + 3 > r->len)
150 *v = (uint32_t)((r->buf[r->pos] << 16) | (r->buf[r->pos + 1] << 8) | r->buf[r->pos + 2]);
155bool r_take(Reader *r,
size_t n,
const uint8_t **out)
157 if (r->pos + n > r->len)
161 *out = r->buf + r->pos;
173bool list16_contains(
const uint8_t *body,
size_t body_len,
size_t list_len, uint16_t target)
175 if (list_len > body_len || (list_len % 2) != 0)
179 for (
size_t i = 0; i + 1 < list_len; i += 2)
181 if (((body[i] << 8) | body[i + 1]) == target)
190void parse_key_share(
const uint8_t *body,
size_t blen, Tls13ClientHello *out)
196 size_t ll = (body[0] << 8) | body[1];
205 uint16_t group = (uint16_t)((body[i] << 8) | body[i + 1]);
206 uint16_t klen = (uint16_t)((body[i + 2] << 8) | body[i + 3]);
212 if (group == TLS_GROUP_X25519 && klen == 32)
214 memcpy(out->client_x25519, body + i, 32);
215 out->has_key_share =
true;
218 else if (group == TLS_GROUP_X25519MLKEM768 && klen == MLKEM768_EK_BYTES + 32)
220 out->client_mlkem_ek = body + i;
221 memcpy(out->client_x25519, body + i + MLKEM768_EK_BYTES, 32);
222 out->has_hybrid_share =
true;
230void parse_alpn(
const uint8_t *body,
size_t blen, Tls13ClientHello *out)
236 size_t ll = (body[0] << 8) | body[1];
245 size_t nl = body[i++];
250 if (nl == 2 && body[i] ==
'h' && body[i + 1] ==
'3')
252 out->offers_h3_alpn =
true;
259void parse_server_name(
const uint8_t *body,
size_t blen, Tls13ClientHello *out)
265 size_t ll = (body[0] << 8) | body[1];
276 uint8_t nt = body[i++];
277 size_t nl = (body[i] << 8) | body[i + 1];
279 if (nt == 0 && i + nl <= end)
286void parse_extension(uint16_t type,
const uint8_t *body,
size_t blen, Tls13ClientHello *out,
bool dtls)
290 case TlsExt::TLS_EXT_SUPPORTED_VERSIONS: {
297 out->offers_tls13 = list16_contains(body + 1, blen - 1, ll, dtls ? PC_TLS_VERSION_DTLS_1_3 : TLS_VERSION_1_3);
300 case TlsExt::TLS_EXT_SUPPORTED_GROUPS: {
305 size_t ll = (body[0] << 8) | body[1];
306 out->offers_x25519 = list16_contains(body + 2, blen - 2, ll, TLS_GROUP_X25519);
308 out->offers_x25519mlkem768 = list16_contains(body + 2, blen - 2, ll, TLS_GROUP_X25519MLKEM768);
312 case TlsExt::TLS_EXT_SIGNATURE_ALGORITHMS: {
317 size_t ll = (body[0] << 8) | body[1];
318 out->offers_ed25519 = list16_contains(body + 2, blen - 2, ll, TLS_SIG_ED25519);
321 case TlsExt::TLS_EXT_KEY_SHARE:
322 parse_key_share(body, blen, out);
324 case TlsExt::TLS_EXT_ALPN:
325 parse_alpn(body, blen, out);
328 case TlsExt::TLS_EXT_SERVER_CERTIFICATE_TYPE: {
340 for (
size_t i = 0; i < ll; i++)
342 if (body[1 + i] == TLS_CERT_TYPE_RAW_PUBLIC_KEY)
344 out->offers_rpk_server_cert =
true;
350 case TLS_EXT_QUIC_TRANSPORT_PARAMS:
351 out->pc_quic_tp = body;
352 out->pc_quic_tp_len = blen;
354 case TlsExt::TLS_EXT_COOKIE: {
360 size_t cl = (size_t)((body[0] << 8) | body[1]);
365 out->cookie = body + 2;
366 out->cookie_len = cl;
369 case TlsExt::TLS_EXT_CONNECTION_ID: {
381 out->has_conn_id =
true;
382 out->conn_id = body + 1;
383 out->conn_id_len = cl;
386 case TlsExt::TLS_EXT_SERVER_NAME:
387 parse_server_name(body, blen, out);
395bool pc_tls13_parse_client_hello(
const uint8_t *msg,
size_t len, Tls13ClientHello *out,
bool dtls)
397 memset(out, 0,
sizeof(*out));
399 Reader r = {msg, len, 0};
401 uint32_t body_len = 0;
402 if (!r_u8(&r, &type) || type != TlsHs::TLS_HS_CLIENT_HELLO || !r_u24(&r, &body_len))
407 if (r.pos + body_len > len)
411 r.len = r.pos + body_len;
413 uint16_t legacy_version = 0;
414 const uint8_t *random =
nullptr;
415 if (!r_u16(&r, &legacy_version) || !r_take(&r, 32, &random))
421 if (!r_u8(&r, &sid_len) || sid_len > 32)
425 if (!r_take(&r, sid_len, &out->session_id))
429 out->session_id_len = sid_len;
435 uint8_t cookie_len = 0;
436 const uint8_t *cookie =
nullptr;
437 if (!r_u8(&r, &cookie_len) || !r_take(&r, cookie_len, &cookie))
444 const uint8_t *cs =
nullptr;
445 if (!r_u16(&r, &cs_len) || (cs_len % 2) != 0 || !r_take(&r, cs_len, &cs))
450 uint8_t comp_len = 0;
451 const uint8_t *comp =
nullptr;
452 if (!r_u8(&r, &comp_len) || !r_take(&r, comp_len, &comp))
458 uint16_t ext_total = 0;
459 if (!r_u16(&r, &ext_total))
463 size_t ext_end = r.pos + ext_total;
468 while (r.pos < ext_end)
472 const uint8_t *ebody =
nullptr;
473 if (!r_u16(&r, &etype) || !r_u16(&r, &elen) || !r_take(&r, elen, &ebody))
477 parse_extension(etype, ebody, elen, out, dtls);
485size_t pc_tls13_build_server_hello(uint8_t *out,
size_t cap,
const uint8_t random[32],
const uint8_t *session_id,
486 uint8_t session_id_len,
const uint8_t *share,
size_t share_len, uint16_t group,
487 bool dtls,
const uint8_t *conn_id,
size_t conn_id_len)
489 Writer w = {out, cap, 0,
true};
490 w_u8(&w, TlsHs::TLS_HS_SERVER_HELLO);
491 size_t hs_len = w_mark(&w, 3);
494 w_u16(&w, dtls ? PC_TLS_LEGACY_VERSION_DTLS : (uint16_t)0x0303);
495 w_bytes(&w, random, 32);
496 w_u8(&w, session_id_len);
497 w_bytes(&w, session_id, session_id_len);
498 w_u16(&w, TLS_CIPHER_AES_128_GCM_SHA256);
501 size_t ext_len = w_mark(&w, 2);
504 w_u16(&w, TlsExt::TLS_EXT_KEY_SHARE);
505 w_u16(&w, (uint16_t)(4 + share_len));
507 w_u16(&w, (uint16_t)share_len);
508 w_bytes(&w, share, share_len);
510 w_u16(&w, TlsExt::TLS_EXT_SUPPORTED_VERSIONS);
512 w_u16(&w, dtls ? PC_TLS_VERSION_DTLS_1_3 : TLS_VERSION_1_3);
517 w_u16(&w, TlsExt::TLS_EXT_CONNECTION_ID);
518 w_u16(&w, (uint16_t)(1 + conn_id_len));
519 w_u8(&w, (uint8_t)conn_id_len);
520 w_bytes(&w, conn_id, conn_id_len);
522 w_patch16(&w, ext_len);
524 w_patch24(&w, hs_len);
525 return w.ok ? w.pos : 0;
529const uint8_t pc_tls13_hrr_random[32] = {0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C,
530 0x02, 0x1E, 0x65, 0xB8, 0x91, 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB,
531 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C};
533size_t pc_tls13_build_hello_retry_request(uint8_t *out,
size_t cap,
const uint8_t *session_id, uint8_t session_id_len,
534 uint16_t selected_group,
const uint8_t *cookie,
size_t cookie_len,
bool dtls)
536 if (cookie_len > 0xFFFD)
540 Writer w = {out, cap, 0,
true};
541 w_u8(&w, TlsHs::TLS_HS_SERVER_HELLO);
542 size_t hs_len = w_mark(&w, 3);
547 w_u16(&w, dtls ? PC_TLS_LEGACY_VERSION_DTLS : (uint16_t)0x0303);
548 w_bytes(&w, pc_tls13_hrr_random, 32);
549 w_u8(&w, session_id_len);
550 w_bytes(&w, session_id, session_id_len);
551 w_u16(&w, TLS_CIPHER_AES_128_GCM_SHA256);
554 size_t ext_len = w_mark(&w, 2);
556 w_u16(&w, TlsExt::TLS_EXT_SUPPORTED_VERSIONS);
558 w_u16(&w, dtls ? PC_TLS_VERSION_DTLS_1_3 : TLS_VERSION_1_3);
560 w_u16(&w, TlsExt::TLS_EXT_KEY_SHARE);
562 w_u16(&w, selected_group);
566 w_u16(&w, TlsExt::TLS_EXT_COOKIE);
567 w_u16(&w, (uint16_t)(cookie_len + 2));
568 w_u16(&w, (uint16_t)cookie_len);
569 w_bytes(&w, cookie, cookie_len);
571 w_patch16(&w, ext_len);
573 w_patch24(&w, hs_len);
574 return w.ok ? w.pos : 0;
579static void w_server_cert_type_rpk(Writer *w)
581 w_u16(w, TlsExt::TLS_EXT_SERVER_CERTIFICATE_TYPE);
583 w_u8(w, TLS_CERT_TYPE_RAW_PUBLIC_KEY);
587size_t pc_tls13_build_encrypted_extensions_empty(uint8_t *out,
size_t cap,
bool rpk_server_cert)
589 Writer w = {out, cap, 0,
true};
590 w_u8(&w, TlsHs::TLS_HS_ENCRYPTED_EXTENSIONS);
591 size_t hs_len = w_mark(&w, 3);
594 size_t ext_len = w_mark(&w, 2);
598 w_server_cert_type_rpk(&w);
601 (void)rpk_server_cert;
603 w_patch16(&w, ext_len);
604 w_patch24(&w, hs_len);
605 return w.ok ? w.pos : 0;
608size_t pc_tls13_build_message_hash(uint8_t *out,
size_t cap,
const uint8_t ch1_hash[32])
610 Writer w = {out, cap, 0,
true};
613 w_bytes(&w, ch1_hash, 32);
614 return w.ok ? w.pos : 0;
617size_t pc_tls13_build_encrypted_extensions(uint8_t *out,
size_t cap,
const uint8_t *pc_quic_tp,
size_t pc_quic_tp_len,
618 bool rpk_server_cert)
620 Writer w = {out, cap, 0,
true};
621 w_u8(&w, TlsHs::TLS_HS_ENCRYPTED_EXTENSIONS);
622 size_t hs_len = w_mark(&w, 3);
624 size_t ext_len = w_mark(&w, 2);
626 w_u16(&w, TlsExt::TLS_EXT_ALPN);
630 w_bytes(&w, (
const uint8_t *)
"h3", 2);
632 w_u16(&w, TLS_EXT_QUIC_TRANSPORT_PARAMS);
633 w_u16(&w, (uint16_t)pc_quic_tp_len);
634 w_bytes(&w, pc_quic_tp, pc_quic_tp_len);
639 w_server_cert_type_rpk(&w);
642 (void)rpk_server_cert;
644 w_patch16(&w, ext_len);
646 w_patch24(&w, hs_len);
647 return w.ok ? w.pos : 0;
650size_t pc_tls13_build_certificate(uint8_t *out,
size_t cap,
const uint8_t *cert_der,
size_t cert_len)
652 Writer w = {out, cap, 0,
true};
653 w_u8(&w, TlsHs::TLS_HS_CERTIFICATE);
654 size_t hs_len = w_mark(&w, 3);
657 size_t list_len = w_mark(&w, 3);
658 w_u24(&w, (uint32_t)cert_len);
659 w_bytes(&w, cert_der, cert_len);
661 w_patch24(&w, list_len);
663 w_patch24(&w, hs_len);
664 return w.ok ? w.pos : 0;
668size_t pc_tls13_ed25519_spki(uint8_t *out,
size_t cap,
const uint8_t pub[32])
672 static const uint8_t PREFIX[12] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00};
673 if (cap < PC_TLS13_ED25519_SPKI_LEN)
677 memcpy(out, PREFIX,
sizeof(PREFIX));
678 memcpy(out +
sizeof(PREFIX), pub, 32);
679 return PC_TLS13_ED25519_SPKI_LEN;
682size_t pc_tls13_build_certificate_rpk(uint8_t *out,
size_t cap,
const uint8_t ed25519_pub[32])
684 uint8_t spki[PC_TLS13_ED25519_SPKI_LEN];
686 if (!pc_tls13_ed25519_spki(spki,
sizeof(spki), ed25519_pub))
691 return pc_tls13_build_certificate(out, cap, spki,
sizeof(spki));
695size_t pc_tls13_cert_verify_content(uint8_t *out,
size_t cap,
const uint8_t transcript_hash[32],
bool is_server)
698 static const char SRV[] =
"TLS 1.3, server CertificateVerify";
699 static const char CLI[] =
"TLS 1.3, client CertificateVerify";
700 const char *ctx = is_server ? SRV : CLI;
701 size_t ctx_len = is_server ?
sizeof(SRV) - 1 : sizeof(CLI) - 1;
702 size_t total = 64 + ctx_len + 1 + 32;
707 memset(out, 0x20, 64);
708 memcpy(out + 64, ctx, ctx_len);
709 out[64 + ctx_len] = 0x00;
710 memcpy(out + 64 + ctx_len + 1, transcript_hash, 32);
714size_t pc_tls13_build_cert_verify(uint8_t *out,
size_t cap,
const uint8_t transcript_hash[32],
const uint8_t seed[32])
716 uint8_t content[64 + 33 + 1 + 32];
717 size_t clen = pc_tls13_cert_verify_content(content,
sizeof(content), transcript_hash,
true);
728 Writer w = {out, cap, 0,
true};
729 w_u8(&w, TlsHs::TLS_HS_CERTIFICATE_VERIFY);
730 size_t hs_len = w_mark(&w, 3);
731 w_u16(&w, TLS_SIG_ED25519);
734 w_patch24(&w, hs_len);
735 return w.ok ? w.pos : 0;
738size_t pc_tls13_build_finished(uint8_t *out,
size_t cap,
const uint8_t verify_data[32])
740 Writer w = {out, cap, 0,
true};
741 w_u8(&w, TlsHs::TLS_HS_FINISHED);
742 size_t hs_len = w_mark(&w, 3);
743 w_bytes(&w, verify_data, 32);
744 w_patch24(&w, hs_len);
745 return w.ok ? w.pos : 0;
void pc_ed25519_sign(uint8_t sig[64], const uint8_t *msg, size_t mlen, const uint8_t seed[32])
Ed25519 signatures (RFC 8032) for ssh-ed25519 host keys + client auth.
#define PC_ED25519_SIG_LEN
Ed25519 signature length (R || S).
ML-KEM-768 (FIPS 203): Encaps (responder) + KeyGen and Decaps (initiator).