code reuse
diff --git a/lib/picotls.c b/lib/picotls.c
index b2aa2f6..2feba7e 100644
--- a/lib/picotls.c
+++ b/lib/picotls.c
@@ -5017,35 +5017,27 @@
     return tls;
 }
 
-static int export_tls13_params(ptls_buffer_t *output, int is_server, int session_reused, ptls_cipher_suite_t *cipher,
-                               const void *client_random, const char *server_name, ptls_iovec_t negotiated_protocol,
-                               const void *enc_key, uint64_t enc_seq, const void *dec_key, uint64_t dec_seq)
-{
-    int ret;
-
-    ptls_buffer_push_block(output, 2, {
-        ptls_buffer_push(output, is_server);
-        ptls_buffer_push(output, session_reused);
-        ptls_buffer_push16(output, PTLS_PROTOCOL_VERSION_TLS13);
-        ptls_buffer_push16(output, cipher->id);
-        ptls_buffer_pushv(output, client_random, PTLS_HELLO_RANDOM_SIZE);
-        ptls_buffer_push_block(output, 2, {
-            size_t len = server_name != NULL ? strlen(server_name) : 0;
-            ptls_buffer_pushv(output, server_name, len);
-        });
-        ptls_buffer_push_block(output, 2, { ptls_buffer_pushv(output, negotiated_protocol.base, negotiated_protocol.len); });
-        ptls_buffer_push_block(output, 2, {
-            ptls_buffer_pushv(output, enc_key, cipher->hash->digest_size);
-            ptls_buffer_push64(output, enc_seq);
-            ptls_buffer_pushv(output, dec_key, cipher->hash->digest_size);
-            ptls_buffer_push64(output, dec_seq);
-        });
-        ptls_buffer_push_block(output, 2, {}); /* for future extensions */
-    });
-
-Exit:
-    return ret;
-}
+#define export_tls_params(output, is_server, session_reused, protocol_version, cipher, client_random, server_name,                 \
+                          negotiated_protocol, ver_block)                                                                          \
+    do {                                                                                                                           \
+        const char *_server_name = (server_name);                                                                                  \
+        ptls_iovec_t _negotiated_protocol = (negotiated_protocol);                                                                 \
+        ptls_buffer_push_block((output), 2, {                                                                                      \
+            ptls_buffer_push((output), (is_server));                                                                               \
+            ptls_buffer_push((output), (session_reused));                                                                          \
+            ptls_buffer_push16((output), (protocol_version));                                                                      \
+            ptls_buffer_push16((output), (cipher)->id);                                                                            \
+            ptls_buffer_pushv((output), (client_random), PTLS_HELLO_RANDOM_SIZE);                                                  \
+            ptls_buffer_push_block((output), 2, {                                                                                  \
+                size_t len = _server_name != NULL ? strlen(_server_name) : 0;                                                      \
+                ptls_buffer_pushv((output), _server_name, len);                                                                    \
+            });                                                                                                                    \
+            ptls_buffer_push_block((output), 2,                                                                                    \
+                                   { ptls_buffer_pushv((output), _negotiated_protocol.base, _negotiated_protocol.len); });         \
+            ptls_buffer_push_block((output), 2, {ver_block}); /* version-specific block */                                         \
+            ptls_buffer_push_block((output), 2, {});          /* for future extensions */                                          \
+        });                                                                                                                        \
+    } while (0)
 
 static int export_tls12_params(ptls_buffer_t *output, int is_server, int session_reused, ptls_cipher_suite_t *cipher,
                                const void *client_random, const char *server_name, ptls_iovec_t negotiated_protocol,
@@ -5054,29 +5046,18 @@
 {
     int ret;
 
-    ptls_buffer_push_block(output, 2, {
-        ptls_buffer_push(output, is_server);
-        ptls_buffer_push(output, session_reused);
-        ptls_buffer_push16(output, PTLS_PROTOCOL_VERSION_TLS12);
-        ptls_buffer_push16(output, cipher->id);
-        ptls_buffer_pushv(output, client_random, PTLS_HELLO_RANDOM_SIZE);
-        ptls_buffer_push_block(output, 2, {
-            size_t len = server_name != NULL ? strlen(server_name) : 0;
-            ptls_buffer_pushv(output, server_name, len);
-        });
-        ptls_buffer_push_block(output, 2, { ptls_buffer_pushv(output, negotiated_protocol.base, negotiated_protocol.len); });
-        ptls_buffer_push_block(output, 2, {
-            ptls_buffer_pushv(output, enc_key, cipher->aead->key_size);
-            ptls_buffer_pushv(output, enc_iv, cipher->aead->tls12.fixed_iv_size);
-            ptls_buffer_push64(output, enc_seq);
-            if (cipher->aead->tls12.record_iv_size != 0)
-                ptls_buffer_push64(output, enc_record_iv);
-            ptls_buffer_pushv(output, dec_key, cipher->aead->key_size);
-            ptls_buffer_pushv(output, dec_iv, cipher->aead->tls12.fixed_iv_size);
-            ptls_buffer_push64(output, dec_seq);
-        });
-        ptls_buffer_push_block(output, 2, {}); /* for future extensions */
-    });
+    export_tls_params(output, is_server, session_reused, PTLS_PROTOCOL_VERSION_TLS12, cipher, client_random, server_name,
+                      negotiated_protocol, {
+                          ptls_buffer_pushv(output, enc_key, cipher->aead->key_size);
+                          ptls_buffer_pushv(output, enc_iv, cipher->aead->tls12.fixed_iv_size);
+                          ptls_buffer_push64(output, enc_seq);
+                          if (cipher->aead->tls12.record_iv_size != 0)
+                              ptls_buffer_push64(output, enc_record_iv);
+                          ptls_buffer_pushv(output, dec_key, cipher->aead->key_size);
+                          ptls_buffer_pushv(output, dec_iv, cipher->aead->tls12.fixed_iv_size);
+                          ptls_buffer_push64(output, dec_seq);
+                      });
+    ret = 0;
 
 Exit:
     return ret;
@@ -5126,20 +5107,34 @@
 {
     ptls_iovec_t negotiated_protocol =
         ptls_iovec_init(tls->negotiated_protocol, tls->negotiated_protocol != NULL ? strlen(tls->negotiated_protocol) : 0);
-    if (ptls_get_protocol_version(tls) == PTLS_PROTOCOL_VERSION_TLS13) {
-        if (tls->state != PTLS_STATE_SERVER_POST_HANDSHAKE)
-            return PTLS_ERROR_LIBRARY;
-        return export_tls13_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random,
-                                   tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret,
-                                   tls->traffic_protection.enc.seq, tls->traffic_protection.dec.secret,
-                                   tls->traffic_protection.dec.seq);
-    } else {
-        return export_tls12_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random,
-                                   tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret,
-                                   tls->traffic_protection.enc.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.enc.seq,
-                                   tls->traffic_protection.enc.tls12_enc_record_iv, tls->traffic_protection.dec.secret,
-                                   tls->traffic_protection.dec.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.dec.seq);
+    int ret;
+
+    if (tls->state != PTLS_STATE_SERVER_POST_HANDSHAKE) {
+        ret = PTLS_ERROR_LIBRARY;
+        goto Exit;
     }
+
+    if (ptls_get_protocol_version(tls) == PTLS_PROTOCOL_VERSION_TLS13) {
+        export_tls_params(output, tls->is_server, tls->is_psk_handshake, PTLS_PROTOCOL_VERSION_TLS13, tls->cipher_suite,
+                          tls->client_random, tls->server_name, negotiated_protocol, {
+                              ptls_buffer_pushv(output, tls->traffic_protection.enc.secret, tls->cipher_suite->hash->digest_size);
+                              ptls_buffer_push64(output, tls->traffic_protection.enc.seq);
+                              ptls_buffer_pushv(output, tls->traffic_protection.dec.secret, tls->cipher_suite->hash->digest_size);
+                              ptls_buffer_push64(output, tls->traffic_protection.dec.seq);
+                          });
+        ret = 0;
+    } else {
+        if ((ret = export_tls12_params(output, tls->is_server, tls->is_psk_handshake, tls->cipher_suite, tls->client_random,
+                                       tls->server_name, negotiated_protocol, tls->traffic_protection.enc.secret,
+                                       tls->traffic_protection.enc.secret + PTLS_MAX_SECRET_SIZE, tls->traffic_protection.enc.seq,
+                                       tls->traffic_protection.enc.tls12_enc_record_iv, tls->traffic_protection.dec.secret,
+                                       tls->traffic_protection.dec.secret + PTLS_MAX_SECRET_SIZE,
+                                       tls->traffic_protection.dec.seq)) != 0)
+            goto Exit;
+    }
+
+Exit:
+    return ret;
 }
 
 static int import_tls12_traffic_protection(ptls_t *tls, int is_enc, const uint8_t **src, const uint8_t *const end)