]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: ssl: support SCTL with AWS-LC
authorWilliam Lallemand <wlallemand@haproxy.com>
Thu, 22 Oct 2026 15:12:18 +0000 (15:12 +0000)
committerWilliam Lallemand <wlallemand@haproxy.com>
Wed, 28 Oct 2026 13:55:51 +0000 (14:55 +0100)
AWS-LC owns extension 18 and rejects server custom extension registration.
The previous commit skips that registration, leaving .sctl files ignored.

Use SSL_CTX_set_signed_cert_timestamp_list(), available in all AWS-LC
releases, to set the serialized SCT list. AWS-LC copies the list and handles
context switches. Enable HAVE_SSL_SCTL for AWS-LC despite its missing
SN_ct_cert_scts OID.

AWS-LC also validates the list. Report a rejected list as a warning and omit
the extension, allowing the certificate to remain usable.

Tested with AWS-LC 4.2.0 and 3.0.0: TLS 1.2 sends the exact SCT payload for
the selected certificate with a sidecar and omits it for another certificate
on the same bind.

This must be backported to 3.0, the first version supporting AWS-LC.

include/haproxy/openssl-compat.h
src/ssl_sock.c

index 5c37d6584b3064f7803dd0eb489bc6a56aca72a2..4918024f59d7e673219dccd91c8d1fc470ea00cd 100644 (file)
@@ -127,6 +127,11 @@ enum ssl_encryption_level_t {
 #define HAVE_SSL_CTX_ADD_SERVER_CUSTOM_EXT
 #endif
 
+#if (defined(OPENSSL_IS_AWSLC))
+/* AWS-LC owns extension 18; its native SCT API is available in all releases. */
+#define HAVE_SSL_CTX_SET_SIGNED_CERT_TIMESTAMP_LIST
+#endif
+
 #if ((OPENSSL_VERSION_NUMBER >= 0x10002000L) && !defined(LIBRESSL_VERSION_NUMBER))
 #define HAVE_SSL_CTX_get0_privatekey
 #endif
@@ -141,7 +146,8 @@ enum ssl_encryption_level_t {
 #define HAVE_VANILLA_OPENSSL
 #endif
 
-#if (defined(SN_ct_cert_scts) && !defined(OPENSSL_NO_TLSEXT))
+#if ((defined(SN_ct_cert_scts) && !defined(OPENSSL_NO_TLSEXT)) || defined(OPENSSL_IS_AWSLC))
+/* AWS-LC supports SCT lists without defining the CT OID SN_ct_cert_scts. */
 #define HAVE_SSL_SCTL
 #endif
 
index 4a70975d975836095b4998a700871bed32359770..f3bd0f5fd1d2a474e5ea2649806bf61cb94e42c4 100644 (file)
@@ -1673,6 +1673,8 @@ static int ssl_sock_load_ocsp(const char *path, SSL_CTX *ctx, struct ckch_data *
 #endif
 
 
+#if defined(HAVE_SSL_CTX_ADD_SERVER_CUSTOM_EXT) || defined(HAVE_SSL_CTX_SET_SIGNED_CERT_TIMESTAMP_LIST)
+
 #ifdef HAVE_SSL_CTX_ADD_SERVER_CUSTOM_EXT
 
 #define CT_EXTENSION_TYPE 18
@@ -1703,12 +1705,21 @@ static __maybe_unused int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type,
        return 1;
 }
 
+#endif /* HAVE_SSL_CTX_ADD_SERVER_CUSTOM_EXT */
+
 /* Attaches <sctl> to <ctx>. Returns 0 on success or -1 on failure. */
 static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
 {
+#ifdef HAVE_SSL_CTX_SET_SIGNED_CERT_TIMESTAMP_LIST
+       /* AWS-LC validates and copies the list, including on context switches. */
+       if (!SSL_CTX_set_signed_cert_timestamp_list(ctx, (const uint8_t *)sctl->area, sctl->data))
+               return -1;
+       return 0;
+#else
        if (!SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl))
                return -1;
        return 0;
+#endif
 }
 
 #endif
@@ -3247,14 +3258,23 @@ static int ssl_sock_put_ckch_into_ctx(const char *path, struct ckch_store *store
        }
 #endif
 
-#ifdef HAVE_SSL_CTX_ADD_SERVER_CUSTOM_EXT
-       if (sctl_ex_index >= 0 && data->sctl) {
+#if defined(HAVE_SSL_CTX_ADD_SERVER_CUSTOM_EXT) || defined(HAVE_SSL_CTX_SET_SIGNED_CERT_TIMESTAMP_LIST)
+       if (data->sctl) {
+#ifdef HAVE_SSL_CTX_SET_SIGNED_CERT_TIMESTAMP_LIST
+               /* A list rejected by AWS-LC only disables SCT delivery; warn and continue. */
                if (ssl_sock_load_sctl(ctx, data->sctl) < 0) {
+                       memprintf(err, "%s '%s.sctl' is present but cannot be parsed by SSL_CTX_set_signed_cert_timestamp_list, the SCTL extension will not be sent.\n",
+                                 err && *err ? *err : "", path);
+                       errcode |= ERR_WARN;
+               }
+#else
+               if (sctl_ex_index >= 0 && ssl_sock_load_sctl(ctx, data->sctl) < 0) {
                        memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
                                  err && *err ? *err : "", path);
                        errcode |= ERR_ALERT | ERR_FATAL;
                        goto end;
                }
+#endif
        }
 #endif