runtests: generate certs dynamically, bump to EC-256, tidy up

Before this patch the curl repository and source tarball distribution
contained test certificates as binary blobs. Used by runtests.

Drop these certificates in favor of generating them dynamically as
part of the build process. Both via autotools and CMake.

As part of this, improve certificates, the generator script and process,
file layout, and fix any issue to make it work fast and smooth both in
CI and local builds.

Note, cert generator scripts require OpenSSL >=1.0.2
(or LibreSSL >=3.1.0). Generation requires POSIX shell, also with CMake.
Without a POSIX shell tests relying on TLS (and stunnel) will fail.

Details:

- build: generate certs as part of the test run process.
- build, tests: generate certs in the build directory.
- binarycheck: drop concept of known binary files with hashes.
- binarycheck: move binary check logic into spacecheck and drop this
  separate checker tool.
- build: fix to clean all cert files.
- autotools: fix to not run leaf cert generators in parallel. To avoid
  confusion when updating the revocation database and counter.
- scripts: drop `scripts` subdir, merge two scripts into one,
  auto-generate root cert, allow generating multiple leafs at once.
- scripts: switch to EC-256 keys (was: RSA-2048). For key size and perf.
- scripts: drop `-x` echo, text dumps, most other output. To avoid log
  noise and make it quicker in CI.
- scripts: make it non-RSA-specific.
- scripts: delete unused code.
- scripts: use POSIX shell shebang. Some envs don't have bash (Alpine).
- scripts: pass test pseudo-secrets via the command-line. To avoid:
  ```
  + openssl genrsa -out test-ca.key -passout fd:0 2048
  Invalid password argument, starting with "fd:"
  ```
- cmake: fix to launch generator scripts via the detected POSIX shell.
- cmake: fix `build-certs` rule to not depend on `SRPFILES`
  (`srp-verifier-*`).
- cmake: drop `EXCLUDE_FROM_ALL` for the cert subdir. It makes
  the Visual Studio generator miss to create the `clean-certs`,
  `build-certs` targets. No target depend on them, so they don't execute
  implicitly anyway. Fixes:
  ```
  MSBUILD : error MSB1009: Project file does not exist.
  Switch: clean-certs.vcxproj
  ```
- cmake: add `VERBATIM USES_TERMINAL` to `build-certs` target.
- GHA/linux: install openssl on Alpine, for the cert generator scripts.

Follow-up to 556f722fe3 #16593
Follow-up to fa461b4eff #14486

Closes #16824
This commit is contained in:
Viktor Szakats 2025-03-24 22:13:29 +01:00
parent 1821ea8b14
commit 44341e736a
No known key found for this signature in database
GPG key ID: B5ABD165E2AEF201
80 changed files with 207 additions and 2425 deletions

View file

@ -1,115 +0,0 @@
#!/usr/bin/env perl
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# This scripts scans the entire git repository for binary files.
#
# All files in the git repo that contain signs of being binary are then
# collected and a sha256sum is generated for all of them. That summary is then
# compared to the list of pre-vetted files so that only the exact copies of
# already scrutinized files are deemed okay to "appear binary".
#
use strict;
use warnings;
my $root = ".";
my $sumsfile = ".github/scripts/binarycheck.sums";
if($ARGV[0]) {
$root = $ARGV[0];
}
my @bin;
my %known;
my $error = 0;
sub knownbins {
open(my $mh, "<", "$sumsfile") ||
die "can't read known binaries";
while(<$mh>) {
my $l = $_;
chomp $l;
if($l =~ /^([a-f0-9]+) (.*)/) {
my ($sum, $file) = ($1, $2);
$known{$file} = 1;
}
elsif($l =~ /^#/) {
# skip comments
}
else {
print STDERR "suspicious line in $sumsfile\n";
$error++;
}
}
close($mh);
}
sub checkfile {
my ($file) = @_;
open(my $mh, "<", "$file") || die "can't read $file";
my $line = 0;
while(<$mh>) {
my $l = $_;
$line++;
if($l =~ /([\x00-\x08\x0b\x0c\x0e-\x1f\x7f])/) {
push @bin, $file;
if(!$known{$file}) {
printf STDERR "$file:$line has unknown binary contents\n";
$error++;
}
last;
}
}
close($mh);
}
my @files = `git ls-files -- $root`;
if(scalar(@files) < 3000) {
# this means this is not the git source code repository or that git does
# not work, error out!
print STDERR "too few files in the git repository!\n";
exit 1;
}
knownbins();
if(scalar(keys %known) < 4) {
print STDERR "too few known binaries in $sumsfile\n";
exit 2;
}
for my $f (@files) {
chomp $f;
checkfile("$root/$f");
}
my $check=system("sha256sum -c $sumsfile");
if($check) {
print STDERR "sha256sum detected a problem\n";
$error++;
}
exit $error;

View file

@ -1,7 +0,0 @@
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
# SPDX-License-Identifier: curl
c68161dba1c0166e4ab8d8ce00f57326db25d29fdd52c33d9974d0972ec60990 ./tests/certs/test-localhost-san-first.pub.der
82430be03ec1783e2f9fad6e07a6f42cce62f8a23d87ea81a95977b47110c200 ./tests/certs/test-localhost-san-last.pub.der
47233a0092db614f53e96a4df83ddeaa7e5242899ede1c1a90c53423a0b13bba ./tests/certs/test-localhost.nn.pub.der
63898448aa199675a30fb6722046a665a7c1a5c24453e63d8c37397482a7dc52 ./tests/certs/test-localhost.pub.der
f78c61bb06a71d1bf9b034ecfcb7fe35ae85b6a3b87bf3a73c085dc062747dc1 ./tests/certs/test-localhost0h.pub.der

View file

@ -28,16 +28,13 @@ use warnings;
my @tabs = (
"^m4/zz40-xc-ovr.m4",
"Makefile\\.[a-z]+\$",
"Makefile\\.(am|example)\$",
"/mkfile",
"\\.(bat|sln|vc)\$",
"^tests/certs/.+\\.der\$",
"^tests/data/test",
);
my @mixed_eol = (
"^tests/certs/.+\\.(crt|der)\$",
"^tests/certs/Server-localhost0h-sv.pem",
"^tests/data/test",
);
@ -47,14 +44,9 @@ my @need_crlf = (
);
my @space_at_eol = (
"^tests/.+\\.(cacert|crt|pem)\$",
"^tests/data/test",
);
my @eol_at_eof = (
"^tests/certs/.+\\.der\$",
);
sub fn_match {
my ($filename, @masklist) = @_;
@ -129,7 +121,6 @@ while (my $filename = <$git_ls_files>) {
}
if ($content ne "" &&
!fn_match($filename, @eol_at_eof) &&
$content !~ /\n\z/) {
push @err, "content: has no EOL at EOF";
}
@ -139,6 +130,10 @@ while (my $filename = <$git_ls_files>) {
push @err, "content: has multiple EOL at EOF";
}
if($content =~ /([\x00-\x08\x0b\x0c\x0e-\x1f\x7f])/) {
push @err, "content: has binary contents";
}
if (@err) {
$issues++;
foreach my $err (@err) {