include the list of supported algorithms in CH.signature_algorithms, while preserving the existing list when no verifier is registered
diff --git a/include/picotls.h b/include/picotls.h
index 1e450eb..6134467 100644
--- a/include/picotls.h
+++ b/include/picotls.h
@@ -575,9 +575,15 @@
* The implementor of the callback should use that as the opportunity to free any temporary data allocated for the verify_sign
* callback.
*/
-PTLS_CALLBACK_TYPE(int, verify_certificate, ptls_t *tls,
- int (**verify_sign)(void *verify_ctx, uint16_t algo, ptls_iovec_t data, ptls_iovec_t sign), void **verify_data,
- ptls_iovec_t *certs, size_t num_certs);
+typedef struct st_ptls_verify_certificate_t {
+ int (*cb)(struct st_ptls_verify_certificate_t *self, ptls_t *tls,
+ int (**verify_sign)(void *verify_ctx, uint16_t algo, ptls_iovec_t data, ptls_iovec_t sign), void **verify_data,
+ ptls_iovec_t *certs, size_t num_certs);
+ /**
+ * list of signature algorithms being supported, terminated by UINT16_MAX
+ */
+ const uint16_t *algos;
+} ptls_verify_certificate_t;
/**
* Encrypt-and-signs (or verify-and-decrypts) a ticket (server-only).
* When used for encryption (i.e., is_encrypt being set), the function should return 0 if successful, or else a non-zero value.
diff --git a/lib/openssl.c b/lib/openssl.c
index e95a4ed..75148ef 100644
--- a/lib/openssl.c
+++ b/lib/openssl.c
@@ -103,6 +103,19 @@
{PTLS_SIGNATURE_ECDSA_SECP521R1_SHA512, EVP_sha512}, {UINT16_MAX, NULL}};
#endif
+/**
+ * The default list sent in ClientHello.signature_algorithms. ECDSA certificates are preferred.
+ */
+static const uint16_t default_signature_schemes[] = {PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256,
+#if PTLS_OPENSSL_HAVE_SECP384R1
+ PTLS_SIGNATURE_ECDSA_SECP384R1_SHA384,
+#endif
+#if PTLS_OPENSSL_HAVE_SECP521R1
+ PTLS_SIGNATURE_ECDSA_SECP521R1_SHA512,
+#endif
+ PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512, PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384,
+ PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256, UINT16_MAX};
+
static const struct st_ptls_openssl_signature_scheme_t *lookup_signature_schemes(EVP_PKEY *key)
{
static const struct st_ptls_openssl_signature_scheme_t *schemes = NULL;
@@ -1270,7 +1283,7 @@
int ptls_openssl_init_verify_certificate(ptls_openssl_verify_certificate_t *self, X509_STORE *store)
{
- *self = (ptls_openssl_verify_certificate_t){{verify_cert}};
+ *self = (ptls_openssl_verify_certificate_t){{verify_cert, default_signature_schemes}};
if (store != NULL) {
X509_STORE_up_ref(store);
@@ -1348,7 +1361,7 @@
int ptls_openssl_raw_pubkey_init_verify_certificate(ptls_openssl_raw_pubkey_verify_certificate_t *self, EVP_PKEY *expected_pubkey)
{
EVP_PKEY_up_ref(expected_pubkey);
- *self = (ptls_openssl_raw_pubkey_verify_certificate_t){{verify_raw_cert}, expected_pubkey};
+ *self = (ptls_openssl_raw_pubkey_verify_certificate_t){{verify_raw_cert, default_signature_schemes}, expected_pubkey};
return 0;
}
void ptls_openssl_raw_pubkey_dispose_verify_certificate(ptls_openssl_raw_pubkey_verify_certificate_t *self)
diff --git a/lib/picotls.c b/lib/picotls.c
index 1ebbf70..874e5d1 100644
--- a/lib/picotls.c
+++ b/lib/picotls.c
@@ -1519,15 +1519,16 @@
return ret;
}
-static int push_signature_algorithms(ptls_buffer_t *sendbuf)
+static int push_signature_algorithms(ptls_verify_certificate_t *vc, ptls_buffer_t *sendbuf)
{
+ /* The list sent when verify callback is not registered */
+ static const uint16_t default_algos[] = {PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256, PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256,
+ PTLS_SIGNATURE_RSA_PKCS1_SHA256, PTLS_SIGNATURE_RSA_PKCS1_SHA1, UINT16_MAX};
int ret;
ptls_buffer_push_block(sendbuf, 2, {
- ptls_buffer_push16(sendbuf, PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256);
- ptls_buffer_push16(sendbuf, PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256);
- ptls_buffer_push16(sendbuf, PTLS_SIGNATURE_RSA_PKCS1_SHA256);
- ptls_buffer_push16(sendbuf, PTLS_SIGNATURE_RSA_PKCS1_SHA1);
+ for (const uint16_t *p = vc != NULL ? vc->algos : default_algos; *p != UINT16_MAX; ++p)
+ ptls_buffer_push16(sendbuf, *p);
});
ret = 0;
@@ -2059,7 +2060,7 @@
});
});
buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_SIGNATURE_ALGORITHMS, {
- if ((ret = push_signature_algorithms(sendbuf)) != 0)
+ if ((ret = push_signature_algorithms(tls->ctx->verify_certificate, sendbuf)) != 0)
goto Exit;
});
buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_SUPPORTED_GROUPS, {
@@ -4095,7 +4096,7 @@
/* extensions */
ptls_buffer_push_block(sendbuf, 2, {
buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_SIGNATURE_ALGORITHMS, {
- if ((ret = push_signature_algorithms(sendbuf)) != 0)
+ if ((ret = push_signature_algorithms(tls->ctx->verify_certificate, sendbuf)) != 0)
goto Exit;
});
});