add API for encoding ECHConfig
diff --git a/include/picotls.h b/include/picotls.h
index ecd4620..972bc9d 100644
--- a/include/picotls.h
+++ b/include/picotls.h
@@ -1687,6 +1687,11 @@
*/
int ptls_server_name_is_ipaddr(const char *name);
/**
+ * encodes one ECH Config
+ */
+int ptls_ech_encode_config(ptls_buffer_t *buf, uint8_t config_id, ptls_hpke_kem_t *kem, ptls_iovec_t public_key,
+ ptls_hpke_cipher_suite_t **ciphers, uint8_t max_name_length, const char *public_name);
+/**
* loads a certificate chain to ptls_context_t::certificates. `certificate.list` and each element of the list is allocated by
* malloc. It is the responsibility of the user to free them when discarding the TLS context.
*/
diff --git a/lib/picotls.c b/lib/picotls.c
index 9a0d983..187c862 100644
--- a/lib/picotls.c
+++ b/lib/picotls.c
@@ -6324,6 +6324,31 @@
return 0;
}
+int ptls_ech_encode_config(ptls_buffer_t *buf, uint8_t config_id, ptls_hpke_kem_t *kem, ptls_iovec_t public_key,
+ ptls_hpke_cipher_suite_t **ciphers, uint8_t max_name_length, const char *public_name)
+{
+ int ret;
+
+ ptls_buffer_push16(buf, PTLS_ECH_CONFIG_VERSION);
+ ptls_buffer_push_block(buf, 2, {
+ ptls_buffer_push(buf, config_id);
+ ptls_buffer_push16(buf, kem->id);
+ ptls_buffer_push_block(buf, 2, { ptls_buffer_pushv(buf, public_key.base, public_key.len); });
+ ptls_buffer_push_block(buf, 2, {
+ for (size_t i = 0; ciphers[i] != NULL; ++i) {
+ ptls_buffer_push16(buf, ciphers[i]->id.kdf);
+ ptls_buffer_push16(buf, ciphers[i]->id.aead);
+ }
+ });
+ ptls_buffer_push(buf, max_name_length);
+ ptls_buffer_push_block(buf, 2, { ptls_buffer_pushv(buf, public_name, strlen(public_name)); });
+ ptls_buffer_push_block(buf, 2, {/* extensions */});
+ });
+
+Exit:
+ return ret;
+}
+
static char *byte_to_hex(char *dst, uint8_t v)
{
*dst++ = "0123456789abcdef"[v >> 4];