Commit f1a27c8432 for strongswan.org

commit f1a27c8432a367c6bc31ebd165bf19be2aed08da
Author: Tobias Brunner <tobias@strongswan.org>
Date:   Tue Sep 22 19:35:21 2026 +0200

    testing: Reduce RSA key size in ikev2/rw-eap-tls-fragments scenario

    Generating certificates with 16k-bit RSA keys takes quite a long time.
    This change reduces the key size and instead pads the intermediate CA
    certificates with a certificatePolicy extension that contains a large
    userNotice to compensate for the reduced size of the public keys and
    signatures in these certificates (~3072 bytes per IM CA certificate) and
    the end entity certificate (~2048 bytes).

    Also added a short description of the actual goal of the test scenario
    and a check for it.  We want to see a full 16k TLS fragment and a
    smaller one (the exact size is unspecified as it also depends on the DH
    group and cert reqs etc., but it should be between 100 and 9999 bytes).

    Fixes: fb9355759087 ("testing: ikev2/rw-eap-tls-fragments certificates")

diff --git a/testing/scripts/build-certs-chroot b/testing/scripts/build-certs-chroot
index 5bde8ba06b..4012a7e73e 100755
--- a/testing/scripts/build-certs-chroot
+++ b/testing/scripts/build-certs-chroot
@@ -93,16 +93,13 @@ MONSTER_CA_RSA_SIZE="8192"
 MONSTER_EE_RSA_SIZE="4096"
 #
 TLS_FRAG_DIR="${CA_DIR}/tls_frag"
-TLS_FRAG_KEY_A="${TLS_FRAG_DIR}/ca_A_key.der"
-TLS_FRAG_KEY_B="${TLS_FRAG_DIR}/ca_B_key.der"
-TLS_FRAG_KEY_C="${TLS_FRAG_DIR}/ca_C_key.der"
-TLS_FRAG_KEY_D="${TLS_FRAG_DIR}/ca_D_key.der"
-TLS_FRAG_CERT_A="${TLS_FRAG_DIR}/ca_A_cert.der"
-TLS_FRAG_CERT_B="${TLS_FRAG_DIR}/ca_B_cert.der"
-TLS_FRAG_CERT_C="${TLS_FRAG_DIR}/ca_C_cert.der"
-TLS_FRAG_CERT_D="${TLS_FRAG_DIR}/ca_D_cert.der"
-TLS_FRAG_CA_RSA_SIZE="16384"
-TLS_FRAG_EE_RSA_SIZE="8192"
+TLS_FRAG_CAS="A B C D"
+TLS_FRAG_CA_RSA_SIZE="4096"
+TLS_FRAG_EE_RSA_SIZE="4096"
+# use the strongSwan OID as policy to pad the certificates
+TLS_FRAG_POLICY="1.3.6.1.4.1.36906.1"
+# ~3.7 KiB deterministic and cheap padding for each intermediate CA certificate
+TLS_FRAG_NOTICE=$(head -c 3750 /dev/zero | tr '\0' '0')
 #
 RSA_SIZE="3072"
 IPSEC_DIR="etc/ipsec.d"
@@ -1638,50 +1635,42 @@ cp ${TEST_CERT} ${MONSTER_DIR}/certs/${SERIAL}.pem
 # strongSwan TLS Frag Root CA                                                  #
 ################################################################################

-# Generate strongSwan TLS Frag Root CA A
-pki --gen  --type rsa --size ${TLS_FRAG_CA_RSA_SIZE} > ${TLS_FRAG_KEY_A}
-pki --self --type rsa --in ${TLS_FRAG_KEY_A} \
-    --not-before "${START}" --not-after "${CA_END}" --ca \
-    --dn "C=CH, O=${PROJECT}, CN=strongSwan A Root CA" \
-    --san ca.a.strongswan.org --san admin@a.strongswan.org \
-    --outform der > ${TLS_FRAG_CERT_A}
-
-# Put a copy in the ikev2/rw-eap-tls-fragments scenario
+# Put a copy of the certificates in the ikev2/rw-eap-tls-fragments scenario
 TEST="${TEST_DIR}/ikev2/rw-eap-tls-fragments"
 mkdir -p ${TEST}/hosts/moon/${SWANCTL_DIR}/x509ca
 mkdir -p ${TEST}/hosts/carol/${SWANCTL_DIR}/x509ca
-cp ${TLS_FRAG_CERT_A} ${TEST}/hosts/moon/${SWANCTL_DIR}/x509ca
-cp ${TLS_FRAG_CERT_A} ${TEST}/hosts/carol/${SWANCTL_DIR}/x509ca

-# Generate strongSwan TLS Frag Intermediate CA B
-pki --gen  --type rsa --size ${TLS_FRAG_CA_RSA_SIZE} > ${TLS_FRAG_KEY_B}
-pki --issue --cakey ${TLS_FRAG_KEY_A} --cacert ${TLS_FRAG_CERT_A} --type rsa \
-    --in ${TLS_FRAG_KEY_B}  \
-    --not-before "${START}" --not-after "${CA_END}" --ca \
-    --dn "C=CH, O=${PROJECT}, CN=strongSwan B Intermediate CA" \
-    --san ca.b.strongswan.org --san admin@b.strongswan.org \
-    --outform der > ${TLS_FRAG_CERT_B}
-cp ${TLS_FRAG_CERT_B} ${TEST}/hosts/moon/${SWANCTL_DIR}/x509ca
-
-# Generate strongSwan TLS Frag Intermediate CA C
-pki --gen  --type rsa --size ${TLS_FRAG_CA_RSA_SIZE} > ${TLS_FRAG_KEY_C}
-pki --issue --cakey ${TLS_FRAG_KEY_B} --cacert ${TLS_FRAG_CERT_B} --type rsa \
-    --in ${TLS_FRAG_KEY_C}  \
-    --not-before "${START}" --not-after "${CA_END}" --ca \
-    --dn "C=CH, O=${PROJECT}, CN=strongSwan C Intermediate CA" \
-    --san ca.c.strongswan.org --san admin@c.strongswan.org \
-    --outform der > ${TLS_FRAG_CERT_C}
-cp ${TLS_FRAG_CERT_C} ${TEST}/hosts/moon/${SWANCTL_DIR}/x509ca
-
-# Generate strongSwan TLS Frag Intermediate CA D
-pki --gen  --type rsa --size ${TLS_FRAG_CA_RSA_SIZE} > ${TLS_FRAG_KEY_D}
-pki --issue --cakey ${TLS_FRAG_KEY_C} --cacert ${TLS_FRAG_CERT_C} --type rsa \
-    --in ${TLS_FRAG_KEY_D}  \
-    --not-before "${START}" --not-after "${CA_END}" --ca \
-    --dn "C=CH, O=${PROJECT}, CN=strongSwan D Intermediate CA" \
-    --san ca.d.strongswan.org --san admin@d.strongswan.org \
-    --outform der > ${TLS_FRAG_CERT_D}
-cp ${TLS_FRAG_CERT_D} ${TEST}/hosts/moon/${SWANCTL_DIR}/x509ca
+PREV_KEY=""
+PREV_CERT=""
+for ca in ${TLS_FRAG_CAS}
+do
+  KEY="${TLS_FRAG_DIR}/ca_${ca}_key.der"
+  CERT="${TLS_FRAG_DIR}/ca_${ca}_cert.der"
+  LC_CA=${ca,,}
+  pki --gen  --type rsa --size ${TLS_FRAG_CA_RSA_SIZE} > ${KEY}
+  if [ -z "${PREV_KEY}" ]
+  then
+    pki --self --type rsa --in ${KEY} \
+        --not-before "${START}" --not-after "${CA_END}" --ca \
+        --dn "C=CH, O=${PROJECT}, CN=strongSwan ${ca} Root CA" \
+        --san ca.${LC_CA}.strongswan.org --san admin@${LC_CA}.strongswan.org \
+        --outform der > ${CERT}
+    # copy only the root CA certificate to carol
+    cp ${CERT} ${TEST}/hosts/carol/${SWANCTL_DIR}/x509ca
+  else
+    pki --issue --cakey ${PREV_KEY} --cacert ${PREV_CERT} --type rsa \
+        --in ${KEY}  \
+        --not-before "${START}" --not-after "${CA_END}" --ca \
+        --dn "C=CH, O=${PROJECT}, CN=strongSwan ${ca} Intermediate CA" \
+        --san ca.${LC_CA}.strongswan.org --san admin@${LC_CA}.strongswan.org \
+        --cert-policy "${TLS_FRAG_POLICY}" --user-notice "${TLS_FRAG_NOTICE}" \
+        --outform der > ${CERT}
+  fi
+  # copy all CA certificates to moon
+  cp ${CERT} ${TEST}/hosts/moon/${SWANCTL_DIR}/x509ca
+  PREV_KEY=${KEY}
+  PREV_CERT=${CERT}
+done

 # Generate a moon TLS FRAG certificate
 TEST_KEY="${TEST}/hosts/moon/${SWANCTL_DIR}/rsa/moon_key.der"
@@ -1690,7 +1679,7 @@ CN="moon.d.strongswan.org"
 mkdir -p ${TEST}/hosts/moon/${SWANCTL_DIR}/rsa
 mkdir -p ${TEST}/hosts/moon/${SWANCTL_DIR}/x509
 pki --gen --type rsa --size ${TLS_FRAG_EE_RSA_SIZE}  > ${TEST_KEY}
-pki --issue --cakey ${TLS_FRAG_KEY_D} --cacert ${TLS_FRAG_CERT_D} --type rsa \
+pki --issue --cakey ${PREV_KEY} --cacert ${PREV_CERT} --type rsa \
     --in ${TEST_KEY} --san ${CN} \
     --not-before "${START}" --not-after "${EE_END}" \
     --dn "C=CH, O=${PROJECT}, CN=${CN}" \
@@ -1703,7 +1692,7 @@ CN="carol@d.strongswan.org"
 mkdir -p ${TEST}/hosts/carol/${SWANCTL_DIR}/rsa
 mkdir -p ${TEST}/hosts/carol/${SWANCTL_DIR}/x509
 pki --gen --type rsa --size ${TLS_FRAG_EE_RSA_SIZE} > ${TEST_KEY}
-pki --issue --cakey ${TLS_FRAG_KEY_D} --cacert ${TLS_FRAG_CERT_D} --type rsa \
+pki --issue --cakey ${PREV_KEY} --cacert ${PREV_CERT} --type rsa \
     --in ${TEST_KEY} --san ${CN} \
     --not-before "${START}" --not-after "${EE_END}" \
     --dn "C=CH, O=${PROJECT}, CN=${CN}" \
diff --git a/testing/tests/ikev2/rw-eap-tls-fragments/description.txt b/testing/tests/ikev2/rw-eap-tls-fragments/description.txt
index b3e0450a41..08b08d4298 100644
--- a/testing/tests/ikev2/rw-eap-tls-fragments/description.txt
+++ b/testing/tests/ikev2/rw-eap-tls-fragments/description.txt
@@ -2,3 +2,7 @@ The roadwarrior <b>carol</b> sets up a connection to gateway <b>moon</b>.
 The strong mutual authentication of both peers is based on <b>EAP-TLS</b> only
 (without a separate IKEv2 authentication), using TLS client and server certificates,
 respectively.
+<p/>
+This scenario uses several intermediate CA certificates that all encode a
+nonsensical but large certificate policy in order to trigger TLS fragmentation
+by exceeding the TLS fragment size of 16k.
diff --git a/testing/tests/ikev2/rw-eap-tls-fragments/evaltest.dat b/testing/tests/ikev2/rw-eap-tls-fragments/evaltest.dat
index fb19cd7c25..77ef54a16a 100644
--- a/testing/tests/ikev2/rw-eap-tls-fragments/evaltest.dat
+++ b/testing/tests/ikev2/rw-eap-tls-fragments/evaltest.dat
@@ -3,6 +3,8 @@ moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw-eap.*version=2 state
 carol::cat /var/log/daemon.log::server requested EAP_TLS authentication::YES
 carol::cat /var/log/daemon.log::allow mutual EAP-only authentication::YES
 carol::cat /var/log/daemon.log::authentication of 'C=CH, O=strongSwan Project, CN=moon.d.strongswan.org' with EAP successful::YES
+moon:: cat /var/log/daemon.log::sending TLS Handshake record (16384 bytes)::YES
+moon:: cat /var/log/daemon.log::sending TLS Handshake record ([0-9]\{3,4\} bytes)::YES
 moon:: cat /var/log/daemon.log::authentication of 'C=CH, O=strongSwan Project, CN=carol@d.strongswan.org' with EAP successful::YES
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_.eq=1::YES
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES