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];