Commit 6fb07d7062 for openssl.org

commit 6fb07d7062229923ee147ea48956c0fa5bfbb1d5
Author: sftcd <stephen.farrell@cs.tcd.ie>
Date:   Tue Feb 17 23:09:01 2026 +0000

    require manual build for external ECH tests

    Reviewed-by: Tomas Mraz <tomas@openssl.org>
    Reviewed-by: Matt Caswell <matt@openssl.org>
    MergeDate: Fri Feb 20 14:16:40 2026
    (Merged from https://github.com/openssl/openssl/pull/30059)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c915b6b217..866030de5f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -843,3 +843,50 @@ jobs:
         ./util/opensslwrap.sh version -c
     - name: test external pyca
       run: make test TESTS="test_external_pyca" VERBOSE=1
+
+  external-test-bssl:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v6
+      with:
+        persist-credentials: false
+    - name: Configure OpenSSL
+      run: ./config enable-external-tests
+    - name: Build OpenSSL
+      run: make -s -j4
+    - name: Clone BoringSSL 0.20260211.0
+      run: git clone --depth 1 --branch 0.20260211.0  https://boringssl.googlesource.com/boringssl
+    - name: Configure and Build BoringSSL
+      run: |
+        cd boringssl
+        mkdir build
+        cd build
+        cmake -DCMAKE_INSTALL_PREFIX=../../boringssl/.local ..
+        make -s -j4
+        make install
+        cd ../..
+    - name: Test ECH with BoringSSL
+      run: make test TESTS='test_external_ech_bssl' V=1
+
+  external-test-nss:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v6
+      with:
+        persist-credentials: false
+    - name: Configure OpenSSL
+      run: ./config enable-external-tests
+    - name: Build OpenSSL
+      run: make -s -j4
+    - name: Clone and Build NSS
+      run: |
+        mkdir nss
+        cd nss
+        git clone --depth 1 --branch NSS_3_112_3_RTM https://github.com/nss-dev/nss.git
+        hg clone https://hg.mozilla.org/projects/nspr -r NSPR_4_36_BRANCH
+        cd nss
+        USE_64=1 make nss_build_all
+        USE_64=1 make install
+        cd ../..
+    - name: Test ECH with NSS
+      run: make test TESTS='test_external_ech_nss' V=1
diff --git a/doc/designs/ech-api.md b/doc/designs/ech-api.md
index 18cd8199f4..079fc3d9a6 100644
--- a/doc/designs/ech-api.md
+++ b/doc/designs/ech-api.md
@@ -564,12 +564,14 @@ the output from those command may require changes to these tests as
 they use pattern matching on the outputs to detect expected successes
 or failures.

-The external tests check that the library correctly interoperates,
-as a client or server, with NSS or BoringSSL. These require a build
-configured with `enable-external-tests` and are quite time consuming
-when first run, as they need to download and build the relevant
-NSS or BoringSSL library. The client/server tests here are not very
-extensive and just check that a basic configuration interoperates.
+The external tests check that the library correctly interoperates, as a client
+or server, with NSS or BoringSSL. These require a build configured with
+`enable-external-tests`.  In order to avoid potential supply-chain issues, you
+need to download and build the relevant NSS or BoringSSL library manually in
+the correct location. When you first attempt to run these external tests, they
+will provide instructions for how to download and build NSS or BoringSSL in the
+correct manner. The client/server tests here are not very extensive and just
+check that a basic configuration interoperates.

 How to measure coverage of ECH tests
 ------------------------------------
diff --git a/test/README-external.md b/test/README-external.md
index 2d7e71d79b..dd831bff64 100644
--- a/test/README-external.md
+++ b/test/README-external.md
@@ -123,6 +123,12 @@ Test failures and suppressions
 There are tests for different software tokens - softhsm, nss-softokn and kryoptic.
 Kryoptic tests will not run at this point. Currently no test fails.

+Encrypted Client Hello (ECH) external tests
+===========================================
+
+ECH external tests versus BoringSSL and NSS exist and are described
+in `doc/designs/ech-api.md`.
+
 Updating test suites
 ====================

diff --git a/test/recipes/95-test_external_ech_bssl_data/ech_bssl_external.sh b/test/recipes/95-test_external_ech_bssl_data/ech_bssl_external.sh
index 343a2fce4b..10970b2232 100755
--- a/test/recipes/95-test_external_ech_bssl_data/ech_bssl_external.sh
+++ b/test/recipes/95-test_external_ech_bssl_data/ech_bssl_external.sh
@@ -1,7 +1,7 @@
 #!/bin/sh

 #
-# Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -49,20 +49,20 @@ echo "   PEM ECH Config file: $ECHCONFIGFILE"

 echo "------------------------------------------------------------------"

-if [ ! -d $SRCTOP/boringssl ]; then
-    mkdir -p $SRCTOP/boringssl
-fi
-if [ ! -d $SRCTOP/boringssl/.local ]; then
-(
-       cd $SRCTOP \
-           && git clone https://boringssl.googlesource.com/boringssl \
-           && cd boringssl \
-           && mkdir build \
-           && cd build \
-           && cmake -DOPENSSL_ROOT_DIR=$OPENSSL_ROOT_DIR -DCMAKE_INSTALL_PREFIX=$SRCTOP/boringssl/.local .. \
-           && make \
-           && make install
-   )
+if [ ! -f $BTOOL/bssl ]; then
+    echo "You need to have built boringssl before running this test."
+    echo "To do that, run the following commands:"
+    cat <<EOF
+        cd $SRCTOP
+        git clone https://boringssl.googlesource.com/boringssl
+        cd boringssl
+        mkdir build
+        cd build
+        cmake -DCMAKE_INSTALL_PREFIX=$SRCTOP/boringssl/.local ..
+        make
+        make install
+EOF
+    exit 1
 fi

 echo "   CWD:                $PWD"
diff --git a/test/recipes/95-test_external_ech_bssl_data/ech_bssl_server_external.sh b/test/recipes/95-test_external_ech_bssl_data/ech_bssl_server_external.sh
index 770ed27e98..863ad52973 100755
--- a/test/recipes/95-test_external_ech_bssl_data/ech_bssl_server_external.sh
+++ b/test/recipes/95-test_external_ech_bssl_data/ech_bssl_server_external.sh
@@ -1,7 +1,7 @@
 #!/bin/sh

 #
-# Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -49,20 +49,20 @@ echo "   PEM ECH Config file: $ECHCONFIGFILE"

 echo "------------------------------------------------------------------"

-if [ ! -d $SRCTOP/boringssl ]; then
-    mkdir -p $SRCTOP/boringssl
-fi
-if [ ! -d $SRCTOP/boringssl/.local ]; then
-(
-       cd $SRCTOP \
-           && git clone https://boringssl.googlesource.com/boringssl \
-           && cd boringssl \
-           && mkdir build \
-           && cd build \
-           && cmake -DOPENSSL_ROOT_DIR=$OPENSSL_ROOT_DIR -DCMAKE_INSTALL_PREFIX=$SRCTOP/boringssl/.local .. \
-           && make \
-           && make install
-   )
+if [ ! -f $BTOOL/bssl ]; then
+    echo "You need to have built boringssl before running this test."
+    echo "To do that, run the following commands:"
+    cat <<EOF
+        cd $SRCTOP
+        git clone https://boringssl.googlesource.com/boringssl
+        cd boringssl
+        mkdir build
+        cd build
+        cmake -DCMAKE_INSTALL_PREFIX=$SRCTOP/boringssl/.local ..
+        make
+        make install
+EOF
+    exit 1
 fi

 echo "   CWD:                $PWD"
diff --git a/test/recipes/95-test_external_ech_nss.t b/test/recipes/95-test_external_ech_nss.t
index ced0e72836..9ae78cb0c8 100644
--- a/test/recipes/95-test_external_ech_nss.t
+++ b/test/recipes/95-test_external_ech_nss.t
@@ -22,10 +22,27 @@ plan skip_all => "External ECH tests not available on Windows or VMS"
 plan skip_all => "External ECH tests not supported in out of tree builds"
     if bldtop_dir() ne srctop_dir();

-plan tests => 2;
+# There is an issue with running the NSS server test in the CI setup. The
+# NSS server test uses the NSS selfserv test server, which, when ECH is
+# enabled generates an ephemeral ECHConfig and private key and prints the
+# base64 encoded ECHConfigList to stdout, which we then collect and feed
+# into s_client for the ECH test. When run locally this requires setting
+# `stdbuf -o0` on the command line to avoid buffering, but that setting
+# seems not to work in the CI environment. For now, we therefore omit the
+# NSS server test when running in the CI environment, which is ok as we
+# have another test checking ECH between s_client and the BoringSSL test
+# server. As a result, we need to set `OSSL_RUN_CI_TESTS` in the CI
+# environment to signal that the NSS server test is not to be run.
+if (defined ($ENV{OSSL_RUN_CI_TESTS})) {
+    plan tests => 1;
+} else {
+    plan tests => 2;
+}

 ok(run(cmd(["sh", data_file("ech_nss_external.sh")])),
    "running ECH client external NSS tests");

-ok(run(cmd(["sh", data_file("ech_nss_server_external.sh")])),
-   "running ECH server external NSS tests");
+if (! defined ($ENV{OSSL_RUN_CI_TESTS})) {
+    ok(run(cmd(["sh", data_file("ech_nss_server_external.sh")])),
+    "running ECH server external NSS tests");
+}
diff --git a/test/recipes/95-test_external_ech_nss_data/ech_nss_external.sh b/test/recipes/95-test_external_ech_nss_data/ech_nss_external.sh
index 9dfc583079..f855b3125f 100755
--- a/test/recipes/95-test_external_ech_nss_data/ech_nss_external.sh
+++ b/test/recipes/95-test_external_ech_nss_data/ech_nss_external.sh
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash

 #
-# Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -36,8 +36,6 @@ OPENSSL_VERSION=`openssl version | cut -f 2 -d ' '`
 ECHCONFIGFILE=$SRCTOP/test/certs/echdir/ech-eg.pem
 httphost=server.example
 httpreq="GET /stats HTTP/1.1\\r\\nConnection: close\\r\\nHost: $httphost\\r\\n\\r\\n"
-LDIR=$SRCTOP/nss/dist/Debug/bin
-NLIB=$SRCTOP/nss/dist/Debug/lib

 echo "------------------------------------------------------------------"
 echo "Testing OpenSSL s_server using ECH-enabled nss client:"
@@ -50,46 +48,35 @@ echo "   PEM ECH Config file: $ECHCONFIGFILE"

 echo "------------------------------------------------------------------"

-if [ ! -d $SRCTOP/nss ]; then
-    mkdir -p $SRCTOP/nss
+LATEST='non-existent-directory'
+if [ -f $SRCTOP/nss/dist/latest ]; then
+    LATEST=`cat $SRCTOP/nss/dist/latest`
 fi
+LDIR=$SRCTOP/nss/dist/$LATEST/bin
+NLIB=$SRCTOP/nss/dist/$LATEST/lib

-# clone our NSS and NSPR
-if [ ! -d $SRCTOP/nss/nss ]; then
-   cd $SRCTOP/nss && git clone https://github.com/nss-dev/nss.git
-fi
-if [ ! -d $SRCTOP/nss/nspr ]; then
-   cd $SRCTOP/nss && hg clone https://hg.mozilla.org/projects/nspr
-fi
-
-# build - used to use build.sh but there's some problem with an
-# tmp awk script running within the make environment so we'll do
-# things in a more basic fashion
-TPATH=""
-if [ -d "$SRCTOP/nss/dist" ]
-then
-    TPATH="$(find $SRCTOP/nss/dist -name tstclnt)"
-fi
-if [ -z "$TPATH" ]
-then
-    ( cd $SRCTOP/nss/nss && USE_64=1 make nss_build_all )
-    ( cd $SRCTOP/nss/nss && USE_64=1 make install )
-fi
-TPATH="$(find $SRCTOP/nss/dist -name tstclnt)"
-if [ -z "$TPATH" ]
-then
-    echo "Build failed - exiting"
-    exit 99
-fi
-LDIR=$(dirname "$TPATH")
-NLIB="$LDIR/../lib"
+if [ ! -f $LDIR/tstclnt ]; then
+    # clone our NSS and NSPR
+    echo "You need to have built NSS before running this test."
+    echo "To do that, run the following commands:"
+    cat <<EOF
+        mkdir $SRCTOP/nss
+        cd $SRCTOP/nss
+        git clone https://github.com/nss-dev/nss.git
+        hg clone https://hg.mozilla.org/projects/nspr
+        cd $SRCTOP/nss/nss
+        USE_64=1 make nss_build_all
+        USE_64=1 make install
+EOF
+    exit 1
+fi

 if [ ! -f $LDIR/tstclnt ]; then
-    echo "Failed to build NSS - exiting"
+    echo "Bad NSS build - exiting"
     exit 99
 fi
 if [ ! -f $LDIR/certutil ]; then
-    echo "Failed to build NSS - exiting"
+    echo "Bad NSS build - exiting"
     exit 99
 fi

diff --git a/test/recipes/95-test_external_ech_nss_data/ech_nss_server_external.sh b/test/recipes/95-test_external_ech_nss_data/ech_nss_server_external.sh
index 2a9e499010..35147ed26b 100755
--- a/test/recipes/95-test_external_ech_nss_data/ech_nss_server_external.sh
+++ b/test/recipes/95-test_external_ech_nss_data/ech_nss_server_external.sh
@@ -1,7 +1,9 @@
-#!/bin/sh
+#!/usr/bin/env bash
+
+set -x

 #
-# Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -49,51 +51,35 @@ echo "   PEM ECH Config file: $ECHCONFIGFILE"

 echo "------------------------------------------------------------------"

-if [ ! -d $SRCTOP/nss ]; then
-    mkdir -p $SRCTOP/nss
-fi
-# clone our NSS and NSPR
-if [ ! -d $SRCTOP/nss/nss ]; then
-    (
-       cd $SRCTOP/nss \
-           && git clone https://github.com/nss-dev/nss.git
-    )
-fi
-if [ ! -d $SRCTOP/nss/nspr ]; then
-    (
-       cd $SRCTOP/nss \
-           && hg clone https://hg.mozilla.org/projects/nspr
-    )
+LATEST='non-existent-directory'
+if [ -f $SRCTOP/nss/dist/latest ]; then
+    LATEST=`cat $SRCTOP/nss/dist/latest`
 fi
+LDIR=$SRCTOP/nss/dist/$LATEST/bin
+NLIB=$SRCTOP/nss/dist/$LATEST/lib

-# build - used to use build.sh but there's some problem with an
-# tmp awk script running within the make environment so we'll do
-# things in a more basic fashion
-TPATH=""
-if [ -d "$SRCTOP/nss/dist" ]
-then
-    TPATH="$(find $SRCTOP/nss/dist -name tstclnt)"
-fi
-if [ -z "$TPATH" ]
-then
-    ( cd $SRCTOP/nss/nss && USE_64=1 make nss_build_all )
-    ( cd $SRCTOP/nss/nss && USE_64=1 make install )
-fi
-TPATH="$(find $SRCTOP/nss/dist -name tstclnt)"
-if [ -z "$TPATH" ]
-then
-    echo "Build failed - exiting"
-    exit 99
-fi
-LDIR=$(dirname "$TPATH")
-LLIB="$LDIR/../lib"
+if [ ! -f $LDIR/selfserv ]; then
+    # clone our NSS and NSPR
+    echo "You need to have built NSS before running this test."
+    echo "To do that, run the following commands:"
+    cat <<EOF
+        mkdir $SRCTOP/nss
+        cd $SRCTOP/nss
+        git clone https://github.com/nss-dev/nss.git
+        hg clone https://hg.mozilla.org/projects/nspr
+        cd $SRCTOP/nss/nss
+        USE_64=1 make nss_build_all
+        USE_64=1 make install
+EOF
+    exit 1
+fi

 if [ ! -f $LDIR/selfserv ]; then
-    echo "Failed to build NSS - exiting"
+    echo "Bad NSS build - exiting"
     exit 99
 fi
 if [ ! -f $LDIR/certutil ]; then
-    echo "Failed to build NSS - exiting"
+    echo "Bad NSS build - exiting"
     exit 99
 fi

@@ -102,7 +88,7 @@ fi
 if [ ! -d $SRCTOP/nss/server ]
 then
     mkdir -p $SRCTOP/nss/server
-    LD_LIBRARY_PATH=$LLIB $LDIR/certutil -A \
+    LD_LIBRARY_PATH=$NLIB $LDIR/certutil -A \
         -i $SRCTOP/test/certs/rootcert.pem \
         -n "oe" -t "CT,C,C" -d $SRCTOP/nss/server/
     sillypass="sillypass"
@@ -111,8 +97,8 @@ then
         -in $SRCTOP/test/certs/echserver.pem \
         -password "pass:$sillypass"
     echo -n $sillypass >sillypassfile
-    LD_LIBRARY_PATH=$LLIB $LDIR/pk12util \
-        -i tmp.p12 -d $SRCTOP/nss/server -w sillypassfile
+    LD_LIBRARY_PATH=$NLIB $LDIR/pk12util \
+        -i tmp.p12 -d $SRCTOP/nss/server -w sillypassfile
     cat sillypassfile
     # rm -f sillypassfile tmp.p12
 fi
@@ -125,13 +111,8 @@ echo "   CWD:                $PWD"

 # need to use ``stdbuf -o0`` so that we don't get buffering and
 # can grab echconfig immediately...
-LD_LIBRARY_PATH=$LLIB stdbuf -o0 $LDIR/selfserv -p 8443 -d $SRCTOP/nss/server \
+LD_LIBRARY_PATH=$NLIB stdbuf -o0 $LDIR/selfserv -p 8443 -d $SRCTOP/nss/server \
     -n server.example -X "publicname:example.com" >ss-echfile &
-if [ -s ss-echfile ]
-then
-    echo "Did you remember to patch NSS? See $0 for details"
-    exit 78
-fi

 # For the future, we'd like a provide our private-key/ECHConfig to
 # NSS - looks like there could be some work required to get that
@@ -145,10 +126,7 @@ then
     exit 88
 fi

-# to ensure we detect a fail, use the wrong ECHConfig ...
-# ECHCONFIGFILE=$SRCTOP/esnistuff/d13.pem
-# ECH=`cat $ECHCONFIGFILE | tail -2 | head -1`
-ECH=`cat ss-echfile | tail -2 | head -1`
+ECH=`cat ss-echfile`
 echo "Running openssl s_client against localhost"
 (echo -e $httpreq ; sleep 2) | \
     $SRCTOP/apps/openssl s_client -connect localhost:8443 \