From fe0356fb06fe4bef53751d3294cd13eee99a1f1f Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Thu, 23 Oct 2025 10:52:52 -0400 Subject: [PATCH] Release SSCG 4.0.0 - Support for ML-DSA keys for post-quantum cryptography (PQC) when built against OpenSSL 3.5 or later - Support for EC-DSA keys for elliptic curves - RSA certificate authority is now created with a minimum key strength of 4096 bits - Improved --help output - Deprecated support for generating custom DH parameters - Stopped producing the DH parameter file by default (it may be requested explicitly with the --dhparams-file argument) - Minimum OpenSSL version is now 3.0 - Drop upstreamed patches Resolves: RHEL-123675 Signed-off-by: Stephen Gallagher --- .gitignore | 8 + 0001-Drop-usage-of-ERR_GET_FUNC.patch | 30 - ...ect-certificate-lifetime-calculation.patch | 42 - 0003-Truncate-IP-address-in-SAN.patch | 56 - ...ail-if-default-file-can-t-be-created.patch | 139 -- ...x-the-FIPS_mode-call-for-OpenSSL-3.0.patch | 32 - 0006-x509-Use-proper-version-for-CSR.patch | 31 - ...critical-basicConstraint-for-CA-cert.patch | 29 - ...andling-in-CA-certificate-SAN-constr.patch | 1115 ----------------- changelog | 264 ++++ sources | 2 +- sscg.spec | 287 +---- 12 files changed, 280 insertions(+), 1755 deletions(-) delete mode 100644 0001-Drop-usage-of-ERR_GET_FUNC.patch delete mode 100644 0002-Correct-certificate-lifetime-calculation.patch delete mode 100644 0003-Truncate-IP-address-in-SAN.patch delete mode 100644 0004-dhparams-don-t-fail-if-default-file-can-t-be-created.patch delete mode 100644 0005-dhparams-Fix-the-FIPS_mode-call-for-OpenSSL-3.0.patch delete mode 100644 0006-x509-Use-proper-version-for-CSR.patch delete mode 100644 0007-Ensure-critical-basicConstraint-for-CA-cert.patch delete mode 100644 0008-Fix-IP-address-handling-in-CA-certificate-SAN-constr.patch create mode 100644 changelog diff --git a/.gitignore b/.gitignore index c9f8a2e..b68ee09 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,11 @@ /sscg-2.6.1.tar.xz /sscg-2.6.2.tar.xz /sscg-3.0.0.tar.xz +/sscg-3.0.1.tar.gz +/sscg-3.0.2.tar.gz +/sscg-3.0.3.tar.gz +/sscg-3.0.5.tar.gz +/sscg-3.0.6.tar.gz +/sscg-3.0.7.tar.gz +/sscg-3.0.8.tar.gz +/sscg-4.0.0.tar.gz diff --git a/0001-Drop-usage-of-ERR_GET_FUNC.patch b/0001-Drop-usage-of-ERR_GET_FUNC.patch deleted file mode 100644 index 1d61a2e..0000000 --- a/0001-Drop-usage-of-ERR_GET_FUNC.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 67ef8f036f7324fe37bc7a7e31a38e7088d21df2 Mon Sep 17 00:00:00 2001 -From: Stephen Gallagher -Date: Sat, 7 Aug 2021 11:48:04 -0400 -Subject: [PATCH 1/6] Drop usage of ERR_GET_FUNC() - -This macro was dropped in OpenSSL 3.0 and has actually not been -providing a valid return code for some time. - -Related: rhbz#1964837 - -Signed-off-by: Stephen Gallagher ---- - include/sscg.h | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/include/sscg.h b/include/sscg.h -index faf86ba4f68e186bd35c7bc3ec77b98b8e37d253..851dc93175607e5223a70ef40a5feb24b7b69215 100644 ---- a/include/sscg.h -+++ b/include/sscg.h -@@ -96,7 +96,6 @@ - /* Get information about error from OpenSSL */ \ - unsigned long _ssl_error = ERR_get_error (); \ - if ((ERR_GET_LIB (_ssl_error) == ERR_LIB_UI) && \ -- (ERR_GET_FUNC (_ssl_error) == UI_F_UI_SET_RESULT_EX) && \ - ((ERR_GET_REASON (_ssl_error) == UI_R_RESULT_TOO_LARGE) || \ - (ERR_GET_REASON (_ssl_error) == UI_R_RESULT_TOO_SMALL))) \ - { \ --- -2.49.0 - diff --git a/0002-Correct-certificate-lifetime-calculation.patch b/0002-Correct-certificate-lifetime-calculation.patch deleted file mode 100644 index 37a73ea..0000000 --- a/0002-Correct-certificate-lifetime-calculation.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 5852d74f338bb6de3f303275aa73024f082b47bf Mon Sep 17 00:00:00 2001 -From: Allison Karlitskaya -Date: Tue, 26 Oct 2021 12:32:13 +0200 -Subject: [PATCH 2/6] Correct certificate lifetime calculation - -sscg allows passing the certificate lifetime, as a number of days, as a -commandline argument. It converts this value to seconds using the -formula - - days * 24 * 3650 - -which is incorrect. The correct value is 3600. - -This effectively adds an extra 20 minutes to the lifetime of the -certificate for each day as given on the commandline, and was enough to -cause some new integration tests in cockpit to fail. - -Interestingly, 3650 is the old default value for the number of days of -certificate validity (~10 years) so this probably slipped in as a sort -of muscle-memory-assisted typo. - -Let's just write `24 * 60 * 60` to make things clear. ---- - src/x509.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/x509.c b/src/x509.c -index dc1594a4bdcb9d81607f0fe5ad2d4562e5edb533..7c7e4dfe56d5756862f3e0f851941e846ce96f31 100644 ---- a/src/x509.c -+++ b/src/x509.c -@@ -418,7 +418,7 @@ sscg_sign_x509_csr (TALLOC_CTX *mem_ctx, - - /* set time */ - X509_gmtime_adj (X509_get_notBefore (cert), 0); -- X509_gmtime_adj (X509_get_notAfter (cert), days * 24 * 3650); -+ X509_gmtime_adj (X509_get_notAfter (cert), days * 24 * 60 * 60); - - /* set subject */ - subject = X509_NAME_dup (X509_REQ_get_subject_name (csr)); --- -2.49.0 - diff --git a/0003-Truncate-IP-address-in-SAN.patch b/0003-Truncate-IP-address-in-SAN.patch deleted file mode 100644 index ce2f302..0000000 --- a/0003-Truncate-IP-address-in-SAN.patch +++ /dev/null @@ -1,56 +0,0 @@ -From c633de3d77987cef5b652c861aa646774c6f1167 Mon Sep 17 00:00:00 2001 -From: Stephen Gallagher -Date: Tue, 8 Mar 2022 16:33:35 -0500 -Subject: [PATCH 3/6] Truncate IP address in SAN - -In OpenSSL 1.1, this was done automatically when addind a SAN extension, -but in OpenSSL 3.0 it is rejected as an invalid input. - -Signed-off-by: Stephen Gallagher ---- - src/x509.c | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - -diff --git a/src/x509.c b/src/x509.c -index 7c7e4dfe56d5756862f3e0f851941e846ce96f31..e828ec725b23d7ea79393151e7bb436e2f61bdb8 100644 ---- a/src/x509.c -+++ b/src/x509.c -@@ -133,6 +133,7 @@ sscg_x509v3_csr_new (TALLOC_CTX *mem_ctx, - char *alt_name = NULL; - char *tmp = NULL; - char *san = NULL; -+ char *slash = NULL; - TALLOC_CTX *tmp_ctx; - X509_EXTENSION *ex = NULL; - struct sscg_x509_req *csr; -@@ -267,6 +268,12 @@ sscg_x509v3_csr_new (TALLOC_CTX *mem_ctx, - else - { - san = talloc_strdup (tmp_ctx, certinfo->subject_alt_names[i]); -+ /* SAN IP addresses cannot include the subnet mask */ -+ if ((slash = strchr (san, '/'))) -+ { -+ /* Truncate at the slash */ -+ *slash = '\0'; -+ } - } - CHECK_MEM (san); - -@@ -289,7 +296,13 @@ sscg_x509v3_csr_new (TALLOC_CTX *mem_ctx, - } - - ex = X509V3_EXT_conf_nid (NULL, NULL, NID_subject_alt_name, alt_name); -- CHECK_MEM (ex); -+ if (!ex) -+ { -+ ret = EINVAL; -+ fprintf (stderr, "Invalid subjectAlternativeName: %s\n", alt_name); -+ goto done; -+ } -+ - sk_X509_EXTENSION_push (certinfo->extensions, ex); - - /* Set the public key for the certificate */ --- -2.49.0 - diff --git a/0004-dhparams-don-t-fail-if-default-file-can-t-be-created.patch b/0004-dhparams-don-t-fail-if-default-file-can-t-be-created.patch deleted file mode 100644 index 46f658b..0000000 --- a/0004-dhparams-don-t-fail-if-default-file-can-t-be-created.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 259c4c83307273551fd267585ec8854896a168bd Mon Sep 17 00:00:00 2001 -From: Stephen Gallagher -Date: Wed, 16 Nov 2022 15:27:58 -0500 -Subject: [PATCH 4/6] dhparams: don't fail if default file can't be created - -Resolves: rhbz#2143206 - -Signed-off-by: Stephen Gallagher ---- - src/arguments.c | 1 - - src/io_utils.c | 12 +++++++++++ - src/sscg.c | 55 +++++++++++++++++++++++++++++++++---------------- - 3 files changed, 49 insertions(+), 19 deletions(-) - -diff --git a/src/arguments.c b/src/arguments.c -index 7b9da14a732875b0f33a12e22a97d51a78216839..770d834aacc05d6d92cc0c855852eadb88f8c9bc 100644 ---- a/src/arguments.c -+++ b/src/arguments.c -@@ -69,7 +69,6 @@ set_default_options (struct sscg_options *opts) - - opts->lifetime = 398; - -- opts->dhparams_file = talloc_strdup (opts, "dhparams.pem"); - opts->dhparams_group = talloc_strdup (opts, "ffdhe4096"); - opts->dhparams_generator = 2; - -diff --git a/src/io_utils.c b/src/io_utils.c -index 1b8bc41c3849acbe4657ae14dfe55e3010957129..5d34327bdbe450add5326ac20c337c9399b471dc 100644 ---- a/src/io_utils.c -+++ b/src/io_utils.c -@@ -544,6 +544,18 @@ sscg_io_utils_open_output_files (struct sscg_stream **streams, bool overwrite) - { - SSCG_LOG (SSCG_DEBUG, "Opening %s\n", stream->path); - stream->bio = BIO_new_file (stream->path, create_mode); -+ if (!stream->bio) -+ { -+ fprintf (stderr, -+ "Could not write to %s. Check directory permissions.\n", -+ stream->path); -+ -+ /* The dhparams file is special, it will be handled later */ -+ if (i != SSCG_FILE_TYPE_DHPARAMS) -+ { -+ continue; -+ } -+ } - CHECK_BIO (stream->bio, stream->path); - } - -diff --git a/src/sscg.c b/src/sscg.c -index 1bf8019c2dda136abe56acd101dfe8ad0b3d725d..dcff4cd2b8dfd2e11c8612d36ecc94b175e9dc26 100644 ---- a/src/sscg.c -+++ b/src/sscg.c -@@ -93,6 +93,7 @@ main (int argc, const char **argv) - int ret, sret; - struct sscg_options *options; - bool build_client_cert = false; -+ char *dhparams_file = NULL; - - struct sscg_x509_cert *cacert; - struct sscg_evp_pkey *cakey; -@@ -182,9 +183,19 @@ main (int argc, const char **argv) - options->crl_mode); - CHECK_OK (ret); - -+ if (options->dhparams_file) -+ { -+ dhparams_file = talloc_strdup (main_ctx, options->dhparams_file); -+ } -+ else -+ { -+ dhparams_file = talloc_strdup (main_ctx, "./dhparams.pem"); -+ } -+ CHECK_MEM (dhparams_file); -+ - ret = sscg_io_utils_add_output_file (options->streams, - SSCG_FILE_TYPE_DHPARAMS, -- options->dhparams_file, -+ dhparams_file, - options->dhparams_mode); - CHECK_OK (ret); - -@@ -281,28 +292,36 @@ main (int argc, const char **argv) - - - /* Create DH parameters file */ -- bp = GET_BIO (SSCG_FILE_TYPE_DHPARAMS); -- if (options->dhparams_prime_len > 0) -+ if ((bp = GET_BIO (SSCG_FILE_TYPE_DHPARAMS))) - { -- ret = create_dhparams (options->verbosity, -- options->dhparams_prime_len, -- options->dhparams_generator, -- &dhparams); -- CHECK_OK (ret); -+ if (options->dhparams_prime_len > 0) -+ { -+ ret = create_dhparams (options->verbosity, -+ options->dhparams_prime_len, -+ options->dhparams_generator, -+ &dhparams); -+ CHECK_OK (ret); -+ } -+ else -+ { -+ ret = get_params_by_named_group (options->dhparams_group, &dhparams); -+ CHECK_OK (ret); -+ } -+ -+ /* Export the DH parameters to the file */ -+ sret = PEM_write_bio_Parameters (bp, dhparams); -+ CHECK_SSL (sret, PEM_write_bio_Parameters ()); -+ ANNOUNCE_WRITE (SSCG_FILE_TYPE_DHPARAMS); -+ EVP_PKEY_free (dhparams); - } -- else -+ else if (options->dhparams_file) - { -- ret = get_params_by_named_group (options->dhparams_group, &dhparams); -- CHECK_OK (ret); -+ /* A filename was explicitly passed, but it couldn't be created */ -+ ret = EPERM; -+ fprintf (stderr, "Could not write to %s: ", options->dhparams_file); -+ goto done; - } - -- /* Export the DH parameters to the file */ -- sret = PEM_write_bio_Parameters (bp, dhparams); -- CHECK_SSL (sret, PEM_write_bio_Parameters ()); -- ANNOUNCE_WRITE (SSCG_FILE_TYPE_DHPARAMS); -- EVP_PKEY_free (dhparams); -- -- - /* Set the final file permissions */ - sscg_io_utils_finalize_output_files (options->streams); - --- -2.49.0 - diff --git a/0005-dhparams-Fix-the-FIPS_mode-call-for-OpenSSL-3.0.patch b/0005-dhparams-Fix-the-FIPS_mode-call-for-OpenSSL-3.0.patch deleted file mode 100644 index 3e86c2c..0000000 --- a/0005-dhparams-Fix-the-FIPS_mode-call-for-OpenSSL-3.0.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 7abb9f7f929eb85fa3ab66a150978bbc5e198e5c Mon Sep 17 00:00:00 2001 -From: Simon Chopin -Date: Mon, 13 Dec 2021 15:20:55 +0100 -Subject: [PATCH 5/6] dhparams: Fix the FIPS_mode() call for OpenSSL 3.0 - -This function has been removed from OpenSSL 3.0, replaced by -EVP_default_properties_is_fips_enabled(). - -Closes #50 ---- - src/dhparams.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/dhparams.c b/src/dhparams.c -index 5c50128970d48790df910b9f9531e61e1d4c5758..61fd57aeedca47fba49f75d356cd5f42b9586696 100644 ---- a/src/dhparams.c -+++ b/src/dhparams.c -@@ -231,7 +231,11 @@ is_valid_named_group (const char *group_name) - } - - /* Check non-FIPS groups */ -+#if OPENSSL_VERSION_NUMBER < 0x30000000L - if (!FIPS_mode ()) -+#else -+ if (!EVP_default_properties_is_fips_enabled(NULL)) -+#endif - { - i = 0; - while (dh_nonfips_groups[i]) --- -2.49.0 - diff --git a/0006-x509-Use-proper-version-for-CSR.patch b/0006-x509-Use-proper-version-for-CSR.patch deleted file mode 100644 index 73066f8..0000000 --- a/0006-x509-Use-proper-version-for-CSR.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 6b48b480d57f75fc93ea646fbe6a457c4afd319f Mon Sep 17 00:00:00 2001 -From: Sebastian Andrzej Siewior -Date: Sat, 19 Oct 2024 15:43:20 +0200 -Subject: [PATCH 6/6] x509: Use proper version for CSR. - -RFC 2986 only defines a single version for CSRs: X509_VERSION_1 (0). -OpenSSL starting with 3.4 rejects everything else. - -Use X509_VERSION_1 as version for X509_REQ_set_version. - -Signed-off-by: Sebastian Andrzej Siewior ---- - src/x509.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/x509.c b/src/x509.c -index e828ec725b23d7ea79393151e7bb436e2f61bdb8..22f8163ec5a6b20bcb16177edf8088cf148a8661 100644 ---- a/src/x509.c -+++ b/src/x509.c -@@ -156,7 +156,7 @@ sscg_x509v3_csr_new (TALLOC_CTX *mem_ctx, - talloc_set_destructor ((TALLOC_CTX *)csr, _sscg_csr_destructor); - - /* We will generate only x509v3 certificates */ -- sslret = X509_REQ_set_version (csr->x509_req, 2); -+ sslret = X509_REQ_set_version (csr->x509_req, X509_VERSION_1); - CHECK_SSL (sslret, X509_REQ_set_version); - - subject = X509_REQ_get_subject_name (csr->x509_req); --- -2.49.0 - diff --git a/0007-Ensure-critical-basicConstraint-for-CA-cert.patch b/0007-Ensure-critical-basicConstraint-for-CA-cert.patch deleted file mode 100644 index 30d0b6f..0000000 --- a/0007-Ensure-critical-basicConstraint-for-CA-cert.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 499ce83c85d14dd8cbc52f6431e775f1d00578d6 Mon Sep 17 00:00:00 2001 -From: Stephen Gallagher -Date: Tue, 22 Apr 2025 13:09:32 -0400 -Subject: [PATCH 7/7] Ensure 'critical' basicConstraint for CA cert - -Fixes: https://github.com/sgallagher/sscg/issues/74 - -Signed-off-by: Stephen Gallagher ---- - src/authority.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/authority.c b/src/authority.c -index af60e1a93023c32e3fdf6da920fba4464256ed81..044c62f5192e75a9f7d3f49616f852a97da7505a 100644 ---- a/src/authority.c -+++ b/src/authority.c -@@ -89,7 +89,8 @@ create_private_CA (TALLOC_CTX *mem_ctx, - sk_X509_EXTENSION_push (ca_certinfo->extensions, ex); - - /* Mark it as a CA */ -- ex = X509V3_EXT_conf_nid (NULL, NULL, NID_basic_constraints, "CA:TRUE"); -+ ex = X509V3_EXT_conf_nid ( -+ NULL, NULL, NID_basic_constraints, "critical,CA:TRUE"); - CHECK_MEM (ex); - sk_X509_EXTENSION_push (ca_certinfo->extensions, ex); - --- -2.49.0 - diff --git a/0008-Fix-IP-address-handling-in-CA-certificate-SAN-constr.patch b/0008-Fix-IP-address-handling-in-CA-certificate-SAN-constr.patch deleted file mode 100644 index 770641a..0000000 --- a/0008-Fix-IP-address-handling-in-CA-certificate-SAN-constr.patch +++ /dev/null @@ -1,1115 +0,0 @@ -From aac0351de2fade86572eac4f24e22bd667177f7e Mon Sep 17 00:00:00 2001 -From: Stephen Gallagher -Date: Mon, 21 Jul 2025 15:13:31 -0400 -Subject: [PATCH 8/8] Fix IP address handling in CA certificate SAN constraints - -- Add automatic single-IP subnet mask to IP addresses in CA name constraints -- Update help text to show simplified IP format without subnet mask -- Add comprehensive test for basicConstraints - -Signed-off-by: Stephen Gallagher ---- - src/arguments.c | 2 +- - src/authority.c | 84 ++++ - test/create_ca_test.c | 960 +++++++++++++++++++++++++++++++++++++++++- - 3 files changed, 1044 insertions(+), 2 deletions(-) - -diff --git a/src/arguments.c b/src/arguments.c -index 770d834aacc05d6d92cc0c855852eadb88f8c9bc..96e3bbb1bcb2efc4e155b646104ffc8f2500079e 100644 ---- a/src/arguments.c -+++ b/src/arguments.c -@@ -309,7 +309,7 @@ sscg_handle_arguments (TALLOC_CTX *mem_ctx, - _ ("Optional additional valid hostnames for the certificate. " - "In addition to hostnames, this option also accepts explicit values " - "supported by RFC 5280 such as " -- "IP:xxx.xxx.xxx.xxx/yyy.yyy.yyy.yyy " -+ "IP:xxx.xxx.xxx.xxx " - "May be specified multiple times."), - _ ("alt.example.com") - }, -diff --git a/src/authority.c b/src/authority.c -index 044c62f5192e75a9f7d3f49616f852a97da7505a..8590e844bee3cc2888476135dc44711d7ba6fc28 100644 ---- a/src/authority.c -+++ b/src/authority.c -@@ -109,6 +109,90 @@ create_private_CA (TALLOC_CTX *mem_ctx, - san = talloc_asprintf ( - tmp_ctx, "DNS:%s", options->subject_alt_names[i]); - } -+ else if (strncmp (options->subject_alt_names[i], "IP:", 3) == 0) -+ { -+ char *ip_addr = options->subject_alt_names[i] + 3; -+ char *slash = strchr (ip_addr, '/'); -+ char *clean_ip = ip_addr; -+ const char *netmask_str = NULL; -+ -+ if (slash) -+ { -+ /* Extract IP and netmask parts */ -+ clean_ip = -+ talloc_strndup (tmp_ctx, ip_addr, slash - ip_addr); -+ char *cidr_str = slash + 1; -+ int cidr_bits = atoi (cidr_str); -+ -+ /* Convert CIDR to appropriate netmask format */ -+ if (strchr (clean_ip, ':')) -+ { -+ /* IPv6 - convert CIDR to hex netmask */ -+ if (cidr_bits == 128) -+ { -+ netmask_str = -+ "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"; -+ } -+ else if (cidr_bits == 64) -+ { -+ netmask_str = "FFFF:FFFF:FFFF:FFFF:0:0:0:0"; -+ } -+ else -+ { -+ /* For other values, default to /128 */ -+ netmask_str = -+ "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"; -+ } -+ } -+ else -+ { -+ /* IPv4 - convert CIDR to dotted decimal */ -+ if (cidr_bits == 32) -+ { -+ netmask_str = "255.255.255.255"; -+ } -+ else if (cidr_bits == 24) -+ { -+ netmask_str = "255.255.255.0"; -+ } -+ else if (cidr_bits == 16) -+ { -+ netmask_str = "255.255.0.0"; -+ } -+ else if (cidr_bits == 8) -+ { -+ netmask_str = "255.0.0.0"; -+ } -+ else -+ { -+ /* For other values, default to /32 */ -+ netmask_str = "255.255.255.255"; -+ } -+ } -+ } -+ else -+ { -+ /* No netmask provided - add single host netmask */ -+ if (strchr (clean_ip, ':')) -+ { -+ /* IPv6 - use /128 netmask */ -+ netmask_str = "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"; -+ } -+ else -+ { -+ /* IPv4 - use /32 netmask */ -+ netmask_str = "255.255.255.255"; -+ } -+ } -+ -+ san = -+ talloc_asprintf (tmp_ctx, "IP:%s/%s", clean_ip, netmask_str); -+ -+ if (slash && clean_ip != ip_addr) -+ { -+ talloc_free (clean_ip); -+ } -+ } - else - { - san = talloc_strdup (tmp_ctx, options->subject_alt_names[i]); -diff --git a/test/create_ca_test.c b/test/create_ca_test.c -index 270cfa3dc189540bb807a3d3140ca45335e727b0..eaf2e77052569fd63c09200636004bcd5afcd97c 100644 ---- a/test/create_ca_test.c -+++ b/test/create_ca_test.c -@@ -21,9 +21,861 @@ - #include - #include - #include -+#include -+#include - - #include "include/sscg.h" - #include "include/x509.h" -+#include "include/authority.h" -+ -+static int -+verify_subject_alt_names (struct sscg_x509_cert *cert) -+{ -+ X509 *x509 = cert->certificate; -+ STACK_OF (GENERAL_NAME) *san_names = NULL; -+ GENERAL_NAME *name = NULL; -+ ASN1_STRING *san_str = NULL; -+ int san_count = 0; -+ int found_primary_cn = 0; -+ int found_alt1 = 0; -+ int found_alt2 = 0; -+ int found_ip4_1 = 0; -+ int found_ip4_2 = 0; -+ int found_ip6 = 0; -+ int found_ip4_netmask = 0; -+ int found_ip6_netmask = 0; -+ int found_email = 0; -+ int found_uri = 0; -+ int found_wildcard = 0; -+ int found_subdomain = 0; -+ int found_international = 0; -+ char *name_str = NULL; -+ -+ /* Get the Subject Alternative Name extension */ -+ san_names = X509_get_ext_d2i (x509, NID_subject_alt_name, NULL, NULL); -+ if (!san_names) -+ { -+ printf ("Certificate missing Subject Alternative Name extension.\n"); -+ return EINVAL; -+ } -+ -+ san_count = sk_GENERAL_NAME_num (san_names); -+ printf ("\n Processing %d Subject Alternative Names:\n", san_count); -+ -+ /* Check each SAN entry */ -+ for (int i = 0; i < san_count; i++) -+ { -+ name = sk_GENERAL_NAME_value (san_names, i); -+ -+ switch (name->type) -+ { -+ case GEN_DNS: -+ san_str = name->d.dNSName; -+ name_str = (char *)ASN1_STRING_get0_data (san_str); -+ printf (" DNS: %s\n", name_str); -+ -+ if (strcmp (name_str, "server.example.com") == 0) -+ found_primary_cn = 1; -+ else if (strcmp (name_str, "alt1.example.com") == 0) -+ found_alt1 = 1; -+ else if (strcmp (name_str, "alt2.example.com") == 0) -+ found_alt2 = 1; -+ else if (strcmp (name_str, "*.wildcard.example.com") == 0) -+ found_wildcard = 1; -+ else if (strcmp (name_str, "subdomain.alt1.example.com") == 0) -+ found_subdomain = 1; -+ else if (strcmp (name_str, "xn--nxasmq6b.example.com") == 0) -+ found_international = 1; -+ break; -+ -+ case GEN_IPADD: -+ san_str = name->d.iPAddress; -+ /* IP addresses are stored as binary data */ -+ if (ASN1_STRING_length (san_str) == 4) /* IPv4 */ -+ { -+ const unsigned char *ip_data = ASN1_STRING_get0_data (san_str); -+ printf (" IP (IPv4): %d.%d.%d.%d\n", -+ ip_data[0], -+ ip_data[1], -+ ip_data[2], -+ ip_data[3]); -+ -+ if (ip_data[0] == 192 && ip_data[1] == 168 && ip_data[2] == 1 && -+ ip_data[3] == 100) -+ found_ip4_1 = 1; -+ else if (ip_data[0] == 10 && ip_data[1] == 0 && -+ ip_data[2] == 0 && ip_data[3] == 1) -+ found_ip4_2 = 1; -+ else if (ip_data[0] == 203 && ip_data[1] == 0 && -+ ip_data[2] == 113 && ip_data[3] == 0) -+ found_ip4_netmask = 1; -+ } -+ else if (ASN1_STRING_length (san_str) == 16) /* IPv6 */ -+ { -+ const unsigned char *ip_data = ASN1_STRING_get0_data (san_str); -+ printf (" IP (IPv6): "); -+ for (int j = 0; j < 16; j += 2) -+ { -+ printf ("%02x%02x", ip_data[j], ip_data[j + 1]); -+ if (j < 14) -+ printf (":"); -+ } -+ printf ("\n"); -+ -+ /* Check for 2001:db8::1 */ -+ if (ip_data[0] == 0x20 && ip_data[1] == 0x01 && -+ ip_data[2] == 0x0d && ip_data[3] == 0xb8 && -+ ip_data[4] == 0x00 && ip_data[5] == 0x00 && -+ ip_data[6] == 0x00 && ip_data[7] == 0x00 && -+ ip_data[8] == 0x00 && ip_data[9] == 0x00 && -+ ip_data[10] == 0x00 && ip_data[11] == 0x00 && -+ ip_data[12] == 0x00 && ip_data[13] == 0x00 && -+ ip_data[14] == 0x00 && ip_data[15] == 0x01) -+ found_ip6 = 1; -+ /* Check for 2001:db8:85a3:: (netmask stripped) */ -+ else if (ip_data[0] == 0x20 && ip_data[1] == 0x01 && -+ ip_data[2] == 0x0d && ip_data[3] == 0xb8 && -+ ip_data[4] == 0x85 && ip_data[5] == 0xa3 && -+ ip_data[6] == 0x00 && ip_data[7] == 0x00 && -+ ip_data[8] == 0x00 && ip_data[9] == 0x00 && -+ ip_data[10] == 0x00 && ip_data[11] == 0x00 && -+ ip_data[12] == 0x00 && ip_data[13] == 0x00 && -+ ip_data[14] == 0x00 && ip_data[15] == 0x00) -+ found_ip6_netmask = 1; -+ } -+ break; -+ -+ case GEN_EMAIL: -+ san_str = name->d.rfc822Name; -+ name_str = (char *)ASN1_STRING_get0_data (san_str); -+ printf (" Email: %s\n", name_str); -+ -+ if (strcmp (name_str, "admin@example.com") == 0) -+ found_email = 1; -+ break; -+ -+ case GEN_URI: -+ san_str = name->d.uniformResourceIdentifier; -+ name_str = (char *)ASN1_STRING_get0_data (san_str); -+ printf (" URI: %s\n", name_str); -+ -+ if (strcmp (name_str, "https://www.example.com/service") == 0) -+ found_uri = 1; -+ break; -+ -+ default: printf (" Other type: %d\n", name->type); break; -+ } -+ } -+ -+ GENERAL_NAMES_free (san_names); -+ -+ /* Verify all expected SANs were found */ -+ int missing_count = 0; -+ -+ if (!found_primary_cn) -+ { -+ printf ( -+ " MISSING: Primary CN not found in Subject Alternative Names.\n"); -+ missing_count++; -+ } -+ -+ if (!found_alt1) -+ { -+ printf ( -+ " MISSING: alt1.example.com not found in Subject Alternative " -+ "Names.\n"); -+ missing_count++; -+ } -+ -+ if (!found_alt2) -+ { -+ printf ( -+ " MISSING: alt2.example.com not found in Subject Alternative " -+ "Names.\n"); -+ missing_count++; -+ } -+ -+ if (!found_ip4_1) -+ { -+ printf ( -+ " MISSING: IPv4 192.168.1.100 not found in Subject Alternative " -+ "Names.\n"); -+ missing_count++; -+ } -+ -+ if (!found_ip4_2) -+ { -+ printf ( -+ " MISSING: IPv4 10.0.0.1 not found in Subject Alternative " -+ "Names.\n"); -+ missing_count++; -+ } -+ -+ if (!found_ip6) -+ { -+ printf ( -+ " MISSING: IPv6 2001:db8::1 not found in Subject Alternative " -+ "Names.\n"); -+ missing_count++; -+ } -+ -+ if (!found_ip4_netmask) -+ { -+ printf ( -+ " MISSING: IPv4 203.0.113.0 (from 203.0.113.0/24, netmask " -+ "stripped) not found in Subject Alternative Names.\n"); -+ missing_count++; -+ } -+ -+ if (!found_ip6_netmask) -+ { -+ printf ( -+ " MISSING: IPv6 2001:db8:85a3:: (from 2001:db8:85a3::/64, netmask " -+ "stripped) not found in Subject Alternative Names.\n"); -+ missing_count++; -+ } -+ -+ if (!found_email) -+ { -+ printf ( -+ " MISSING: Email admin@example.com not found in Subject " -+ "Alternative Names.\n"); -+ missing_count++; -+ } -+ -+ if (!found_uri) -+ { -+ printf ( -+ " MISSING: URI https://www.example.com/service not found in " -+ "Subject Alternative Names.\n"); -+ missing_count++; -+ } -+ -+ if (!found_wildcard) -+ { -+ printf ( -+ " MISSING: Wildcard *.wildcard.example.com not found in Subject " -+ "Alternative Names.\n"); -+ missing_count++; -+ } -+ -+ if (!found_subdomain) -+ { -+ printf ( -+ " MISSING: Subdomain subdomain.alt1.example.com not found in " -+ "Subject Alternative Names.\n"); -+ missing_count++; -+ } -+ -+ if (!found_international) -+ { -+ printf ( -+ " MISSING: International domain xn--nxasmq6b.example.com not found " -+ "in Subject Alternative Names.\n"); -+ missing_count++; -+ } -+ -+ if (missing_count > 0) -+ { -+ printf (" %d expected SAN entries were missing.\n", missing_count); -+ return EINVAL; -+ } -+ -+ printf (" All expected SAN entries found successfully.\n"); -+ return EOK; -+} -+ -+static int -+test_san_edge_cases (struct sscg_x509_cert *cert) -+{ -+ X509 *x509 = cert->certificate; -+ STACK_OF (GENERAL_NAME) *san_names = NULL; -+ GENERAL_NAME *name = NULL; -+ ASN1_STRING *san_str = NULL; -+ int san_count = 0; -+ int dns_count = 0; -+ int ip_count = 0; -+ int email_count = 0; -+ int uri_count = 0; -+ char *name_str = NULL; -+ -+ /* Get the Subject Alternative Name extension */ -+ san_names = X509_get_ext_d2i (x509, NID_subject_alt_name, NULL, NULL); -+ if (!san_names) -+ { -+ printf ("Certificate missing Subject Alternative Name extension.\n"); -+ return EINVAL; -+ } -+ -+ san_count = sk_GENERAL_NAME_num (san_names); -+ -+ printf ("\n Performing comprehensive SAN validation:\n"); -+ -+ /* Count and validate all SAN types */ -+ for (int i = 0; i < san_count; i++) -+ { -+ name = sk_GENERAL_NAME_value (san_names, i); -+ -+ switch (name->type) -+ { -+ case GEN_DNS: -+ dns_count++; -+ san_str = name->d.dNSName; -+ name_str = (char *)ASN1_STRING_get0_data (san_str); -+ -+ /* Validate DNS name format */ -+ if (strlen (name_str) == 0) -+ { -+ printf (" ERROR: Empty DNS name found in SANs.\n"); -+ GENERAL_NAMES_free (san_names); -+ return EINVAL; -+ } -+ -+ /* Allow wildcards and validate domain format */ -+ if (name_str[0] != '*' && !strchr (name_str, '.')) -+ { -+ printf (" ERROR: DNS name '%s' missing domain part.\n", -+ name_str); -+ GENERAL_NAMES_free (san_names); -+ return EINVAL; -+ } -+ -+ /* Validate wildcard format */ -+ if (name_str[0] == '*' && name_str[1] != '.') -+ { -+ printf (" ERROR: Invalid wildcard DNS name '%s'.\n", -+ name_str); -+ GENERAL_NAMES_free (san_names); -+ return EINVAL; -+ } -+ break; -+ -+ case GEN_IPADD: -+ ip_count++; -+ san_str = name->d.iPAddress; -+ -+ /* Validate IP address length */ -+ int ip_len = ASN1_STRING_length (san_str); -+ if (ip_len != 4 && ip_len != 16) /* IPv4 or IPv6 */ -+ { -+ printf (" ERROR: Invalid IP address length: %d bytes.\n", -+ ip_len); -+ GENERAL_NAMES_free (san_names); -+ return EINVAL; -+ } -+ break; -+ -+ case GEN_EMAIL: -+ email_count++; -+ san_str = name->d.rfc822Name; -+ name_str = (char *)ASN1_STRING_get0_data (san_str); -+ -+ /* Validate email format */ -+ if (!strchr (name_str, '@')) -+ { -+ printf (" ERROR: Invalid email address '%s' - missing @.\n", -+ name_str); -+ GENERAL_NAMES_free (san_names); -+ return EINVAL; -+ } -+ break; -+ -+ case GEN_URI: -+ uri_count++; -+ san_str = name->d.uniformResourceIdentifier; -+ name_str = (char *)ASN1_STRING_get0_data (san_str); -+ -+ /* Validate URI format - must have scheme */ -+ if (!strstr (name_str, "://")) -+ { -+ printf (" ERROR: Invalid URI '%s' - missing scheme.\n", -+ name_str); -+ GENERAL_NAMES_free (san_names); -+ return EINVAL; -+ } -+ break; -+ -+ default: -+ /* Other SAN types are acceptable but not validated here */ -+ break; -+ } -+ } -+ -+ printf (" Found %d total SANs: %d DNS, %d IP, %d Email, %d URI.\n", -+ san_count, -+ dns_count, -+ ip_count, -+ email_count, -+ uri_count); -+ -+ /* Validate expected counts for comprehensive test */ -+ int expected_dns = -+ 6; /* CN + alt1 + alt2 + wildcard + subdomain + international */ -+ int expected_ip = 5; /* IPv4 x2 + IPv6 x1 + IPv4 netmask + IPv6 netmask */ -+ int expected_email = 1; -+ int expected_uri = 1; -+ -+ if (dns_count < expected_dns) -+ { -+ printf (" ERROR: Expected at least %d DNS names, found %d.\n", -+ expected_dns, -+ dns_count); -+ GENERAL_NAMES_free (san_names); -+ return EINVAL; -+ } -+ -+ if (ip_count < expected_ip) -+ { -+ printf (" ERROR: Expected at least %d IP addresses, found %d.\n", -+ expected_ip, -+ ip_count); -+ GENERAL_NAMES_free (san_names); -+ return EINVAL; -+ } -+ -+ if (email_count < expected_email) -+ { -+ printf (" ERROR: Expected at least %d email addresses, found %d.\n", -+ expected_email, -+ email_count); -+ GENERAL_NAMES_free (san_names); -+ return EINVAL; -+ } -+ -+ if (uri_count < expected_uri) -+ { -+ printf (" ERROR: Expected at least %d URIs, found %d.\n", -+ expected_uri, -+ uri_count); -+ GENERAL_NAMES_free (san_names); -+ return EINVAL; -+ } -+ -+ printf (" All SAN format validations passed successfully.\n"); -+ -+ GENERAL_NAMES_free (san_names); -+ return EOK; -+} -+ -+static int -+test_ip_netmask_handling (struct sscg_x509_cert *cert) -+{ -+ X509 *x509 = cert->certificate; -+ STACK_OF (GENERAL_NAME) *san_names = NULL; -+ GENERAL_NAME *name = NULL; -+ ASN1_STRING *san_str = NULL; -+ int san_count = 0; -+ int found_netmask_ipv4 = 0; -+ int found_netmask_ipv6 = 0; -+ -+ /* Get the Subject Alternative Name extension */ -+ san_names = X509_get_ext_d2i (x509, NID_subject_alt_name, NULL, NULL); -+ if (!san_names) -+ { -+ printf ("Certificate missing Subject Alternative Name extension.\n"); -+ return EINVAL; -+ } -+ -+ san_count = sk_GENERAL_NAME_num (san_names); -+ -+ printf ("\n Testing IP address netmask stripping:\n"); -+ -+ /* Look specifically for IP addresses that had netmasks stripped */ -+ for (int i = 0; i < san_count; i++) -+ { -+ name = sk_GENERAL_NAME_value (san_names, i); -+ -+ if (name->type == GEN_IPADD) -+ { -+ san_str = name->d.iPAddress; -+ -+ if (ASN1_STRING_length (san_str) == 4) /* IPv4 */ -+ { -+ const unsigned char *ip_data = ASN1_STRING_get0_data (san_str); -+ -+ /* Check for 203.0.113.0 (from original 203.0.113.0/24) */ -+ if (ip_data[0] == 203 && ip_data[1] == 0 && ip_data[2] == 113 && -+ ip_data[3] == 0) -+ { -+ printf ( -+ " ✓ IPv4 netmask stripped: 203.0.113.0/24 → " -+ "203.0.113.0\n"); -+ found_netmask_ipv4 = 1; -+ } -+ } -+ else if (ASN1_STRING_length (san_str) == 16) /* IPv6 */ -+ { -+ const unsigned char *ip_data = ASN1_STRING_get0_data (san_str); -+ -+ /* Check for 2001:db8:85a3:: (from original 2001:db8:85a3::/64) */ -+ if (ip_data[0] == 0x20 && ip_data[1] == 0x01 && -+ ip_data[2] == 0x0d && ip_data[3] == 0xb8 && -+ ip_data[4] == 0x85 && ip_data[5] == 0xa3 && -+ ip_data[6] == 0x00 && ip_data[7] == 0x00 && -+ ip_data[8] == 0x00 && ip_data[9] == 0x00 && -+ ip_data[10] == 0x00 && ip_data[11] == 0x00 && -+ ip_data[12] == 0x00 && ip_data[13] == 0x00 && -+ ip_data[14] == 0x00 && ip_data[15] == 0x00) -+ { -+ printf ( -+ " ✓ IPv6 netmask stripped: 2001:db8:85a3::/64 → " -+ "2001:db8:85a3::\n"); -+ found_netmask_ipv6 = 1; -+ } -+ } -+ } -+ } -+ -+ GENERAL_NAMES_free (san_names); -+ -+ /* Verify that netmask stripping worked correctly */ -+ if (!found_netmask_ipv4) -+ { -+ printf (" ERROR: IPv4 netmask stripping test failed.\n"); -+ return EINVAL; -+ } -+ -+ if (!found_netmask_ipv6) -+ { -+ printf (" ERROR: IPv6 netmask stripping test failed.\n"); -+ return EINVAL; -+ } -+ -+ printf (" All IP address netmask tests passed successfully.\n"); -+ return EOK; -+} -+ -+static int -+verify_name_constraints (struct sscg_x509_cert *ca_cert, -+ char **expected_san_list) -+{ -+ X509 *x509 = ca_cert->certificate; -+ X509_EXTENSION *name_constraints_ext = NULL; -+ ASN1_OCTET_STRING *ext_data = NULL; -+ BIO *bio = NULL; -+ char *ext_str = NULL; -+ char *line = NULL; -+ char *saveptr = NULL; -+ size_t ext_str_len = 0; -+ int found_constraints[20] = { -+ 0 -+ }; /* Track which expected constraints we found */ -+ int missing_count = 0; -+ int j; -+ -+ printf ("\n Verifying name constraints in CA certificate:\n"); -+ -+ /* Find the name constraints extension */ -+ int ext_idx = X509_get_ext_by_NID (x509, NID_name_constraints, -1); -+ if (ext_idx < 0) -+ { -+ printf ( -+ " ERROR: CA certificate missing Name Constraints extension.\n"); -+ return EINVAL; -+ } -+ -+ name_constraints_ext = X509_get_ext (x509, ext_idx); -+ if (!name_constraints_ext) -+ { -+ printf (" ERROR: Failed to get Name Constraints extension.\n"); -+ return EINVAL; -+ } -+ -+ /* Get the extension data */ -+ ext_data = X509_EXTENSION_get_data (name_constraints_ext); -+ if (!ext_data) -+ { -+ printf (" ERROR: Failed to get Name Constraints extension data.\n"); -+ return EINVAL; -+ } -+ -+ /* Convert the extension to a readable string using BIO */ -+ bio = BIO_new (BIO_s_mem ()); -+ if (!bio) -+ { -+ printf (" ERROR: Failed to create BIO for extension parsing.\n"); -+ return EINVAL; -+ } -+ -+ /* Print the extension to the BIO */ -+ if (!X509V3_EXT_print (bio, name_constraints_ext, 0, 0)) -+ { -+ printf (" ERROR: Failed to print Name Constraints extension.\n"); -+ BIO_free (bio); -+ return EINVAL; -+ } -+ -+ /* Get the string representation */ -+ ext_str_len = BIO_get_mem_data (bio, &ext_str); -+ if (ext_str_len <= 0 || !ext_str) -+ { -+ printf (" ERROR: Failed to get extension string data.\n"); -+ BIO_free (bio); -+ return EINVAL; -+ } -+ -+ /* Null-terminate the string for parsing */ -+ char *ext_str_copy = malloc (ext_str_len + 1); -+ if (!ext_str_copy) -+ { -+ printf ( -+ " ERROR: Failed to allocate memory for extension parsing.\n"); -+ BIO_free (bio); -+ return ENOMEM; -+ } -+ memcpy (ext_str_copy, ext_str, ext_str_len); -+ ext_str_copy[ext_str_len] = '\0'; -+ -+ printf (" Name Constraints content:\n%s\n", ext_str_copy); -+ -+ /* Parse the extension string to find constraints */ -+ line = strtok_r (ext_str_copy, "\n", &saveptr); -+ while (line) -+ { -+ /* Look for "Permitted:" sections and DNS/IP entries */ -+ if (strstr (line, "DNS:")) -+ { -+ char *dns_start = strstr (line, "DNS:"); -+ if (dns_start) -+ { -+ dns_start += 4; /* Skip "DNS:" */ -+ /* Trim whitespace */ -+ while (*dns_start == ' ' || *dns_start == '\t') -+ dns_start++; -+ -+ printf (" Found DNS constraint: %s\n", dns_start); -+ -+ /* Check if this matches our expected CN (truncated) */ -+ if (strstr (dns_start, "server")) -+ { -+ found_constraints[0] = 1; -+ } -+ -+ /* Check against our expected SAN list */ -+ if (expected_san_list) -+ { -+ for (j = 0; expected_san_list[j]; j++) -+ { -+ char *expected_dns = NULL; -+ -+ if (!strchr (expected_san_list[j], ':')) -+ { -+ expected_dns = expected_san_list[j]; -+ } -+ else if (strncmp (expected_san_list[j], "DNS:", 4) == 0) -+ { -+ expected_dns = expected_san_list[j] + 4; -+ } -+ -+ if (expected_dns && strstr (dns_start, expected_dns)) -+ { -+ found_constraints[j + 1] = 1; -+ } -+ } -+ } -+ } -+ } -+ else if (strstr (line, "IP:")) -+ { -+ char *ip_start = strstr (line, "IP:"); -+ if (ip_start) -+ { -+ ip_start += 3; /* Skip "IP:" */ -+ while (*ip_start == ' ' || *ip_start == '\t') -+ ip_start++; -+ -+ printf (" Found IP constraint: %s\n", ip_start); -+ -+ /* Check against expected IP SANs */ -+ if (expected_san_list) -+ { -+ for (j = 0; expected_san_list[j]; j++) -+ { -+ if (strncmp (expected_san_list[j], "IP:", 3) == 0) -+ { -+ char *expected_ip = expected_san_list[j] + 3; -+ char *slash = strchr (expected_ip, '/'); -+ char expected_constraint[128]; -+ char clean_ip[64]; -+ -+ /* Extract IP and netmask parts */ -+ if (slash) -+ { -+ int ip_len = slash - expected_ip; -+ strncpy (clean_ip, expected_ip, ip_len); -+ clean_ip[ip_len] = '\0'; -+ -+ /* Parse the CIDR netmask */ -+ char *cidr_str = slash + 1; -+ int cidr_bits = atoi (cidr_str); -+ -+ /* Convert to constraint format with proper netmask */ -+ if (strchr (clean_ip, ':')) -+ { -+ /* IPv6 - convert CIDR to hex netmask */ -+ const char *netmask; -+ if (cidr_bits == 128) -+ netmask = -+ "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:" -+ "FFFF"; -+ else if (cidr_bits == 64) -+ netmask = "FFFF:FFFF:FFFF:FFFF:0:0:0:0"; -+ else -+ netmask = -+ "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:" -+ "FFFF"; /* default to /128 */ -+ -+ /* Handle compressed IPv6 forms */ -+ if (strstr (clean_ip, "2001:db8::1")) -+ { -+ snprintf (expected_constraint, -+ sizeof (expected_constraint), -+ "IP:2001:DB8:0:0:0:0:0:1/%s", -+ netmask); -+ } -+ else if (strstr (clean_ip, -+ "2001:db8:85a3::")) -+ { -+ snprintf ( -+ expected_constraint, -+ sizeof (expected_constraint), -+ "IP:2001:DB8:85A3:0:0:0:0:0/%s", -+ netmask); -+ } -+ else -+ { -+ snprintf (expected_constraint, -+ sizeof (expected_constraint), -+ "IP:%s/%s", -+ clean_ip, -+ netmask); -+ } -+ } -+ else -+ { -+ /* IPv4 - convert CIDR to dotted decimal */ -+ const char *netmask; -+ if (cidr_bits == 32) -+ netmask = "255.255.255.255"; -+ else if (cidr_bits == 24) -+ netmask = "255.255.255.0"; -+ else if (cidr_bits == 16) -+ netmask = "255.255.0.0"; -+ else if (cidr_bits == 8) -+ netmask = "255.0.0.0"; -+ else -+ netmask = -+ "255.255.255.255"; /* default to /32 */ -+ -+ snprintf (expected_constraint, -+ sizeof (expected_constraint), -+ "IP:%s/%s", -+ clean_ip, -+ netmask); -+ } -+ } -+ else -+ { -+ /* No netmask - add single host netmask */ -+ strcpy (clean_ip, expected_ip); -+ -+ if (strchr (clean_ip, ':')) -+ { -+ /* IPv6 with /128 netmask */ -+ if (strstr (clean_ip, "2001:db8::1")) -+ { -+ snprintf (expected_constraint, -+ sizeof (expected_constraint), -+ "IP:2001:DB8:0:0:0:0:0:1/" -+ "FFFF:FFFF:FFFF:FFFF:FFFF:" -+ "FFFF:FFFF:FFFF"); -+ } -+ else if (strstr (clean_ip, -+ "2001:db8:85a3::")) -+ { -+ snprintf (expected_constraint, -+ sizeof (expected_constraint), -+ "IP:2001:DB8:85A3:0:0:0:0:0/" -+ "FFFF:FFFF:FFFF:FFFF:FFFF:" -+ "FFFF:FFFF:FFFF"); -+ } -+ else -+ { -+ snprintf (expected_constraint, -+ sizeof (expected_constraint), -+ "IP:%s/" -+ "FFFF:FFFF:FFFF:FFFF:FFFF:" -+ "FFFF:FFFF:FFFF", -+ clean_ip); -+ } -+ } -+ else -+ { -+ /* IPv4 with /32 netmask */ -+ snprintf (expected_constraint, -+ sizeof (expected_constraint), -+ "IP:%s/255.255.255.255", -+ clean_ip); -+ } -+ } -+ -+ /* Check if this expected constraint matches what we found */ -+ /* Skip the "IP:" prefix for comparison since ip_start doesn't include it */ -+ char *constraint_without_prefix = -+ expected_constraint + 3; /* Skip "IP:" */ -+ if (strcmp (ip_start, constraint_without_prefix) == -+ 0) -+ { -+ found_constraints[j + 1] = 1; -+ } -+ } -+ } -+ } -+ } -+ } -+ -+ line = strtok_r (NULL, "\n", &saveptr); -+ } -+ -+ free (ext_str_copy); -+ BIO_free (bio); -+ -+ /* Verify that we found all expected constraints */ -+ if (!found_constraints[0]) -+ { -+ printf (" MISSING: CN constraint 'server' not found.\n"); -+ missing_count++; -+ } -+ -+ if (expected_san_list) -+ { -+ for (j = 0; expected_san_list[j]; j++) -+ { -+ if (!found_constraints[j + 1]) -+ { -+ /* Only report missing DNS and IP constraints, skip email/URI */ -+ if (!strchr (expected_san_list[j], ':') || -+ strncmp (expected_san_list[j], "DNS:", 4) == 0 || -+ strncmp (expected_san_list[j], "IP:", 3) == 0) -+ { -+ printf (" MISSING: Constraint for '%s' not found.\n", -+ expected_san_list[j]); -+ missing_count++; -+ } -+ } -+ } -+ } -+ -+ if (missing_count > 0) -+ { -+ printf (" %d expected name constraints were missing.\n", -+ missing_count); -+ return EINVAL; -+ } -+ -+ printf (" All expected name constraints found successfully.\n"); -+ return EOK; -+} - - int - main (int argc, char **argv) -@@ -35,6 +887,11 @@ main (int argc, char **argv) - struct sscg_evp_pkey *pkey = NULL; - struct sscg_x509_cert *cert = NULL; - -+ /* Variables for CA testing */ -+ struct sscg_x509_cert *ca_cert = NULL; -+ struct sscg_evp_pkey *ca_key = NULL; -+ struct sscg_options ca_options; -+ - TALLOC_CTX *tmp_ctx = talloc_new (NULL); - if (!tmp_ctx) - { -@@ -98,7 +955,108 @@ main (int argc, char **argv) - tmp_ctx, csr, serial, 3650, NULL, pkey, EVP_sha512 (), &cert); - CHECK_OK (ret); - -- ret = EOK; -+ /* ============= SERVICE CERTIFICATE TESTS ============= */ -+ -+ /* Verify that subject alternative names were properly included */ -+ printf ("Verifying subject alternative names in service certificate. "); -+ int verify_ret = verify_subject_alt_names (cert); -+ if (verify_ret != EOK) -+ { -+ printf ("FAILED.\n"); -+ ret = verify_ret; /* Store first failure but continue testing */ -+ } -+ else -+ { -+ printf ("SUCCESS.\n"); -+ } -+ -+ /* Test additional SAN verification scenarios */ -+ printf ("Testing SAN edge cases and validation. "); -+ int edge_ret = test_san_edge_cases (cert); -+ if (edge_ret != EOK) -+ { -+ printf ("FAILED.\n"); -+ if (ret == EOK) -+ ret = edge_ret; /* Store first failure */ -+ } -+ else -+ { -+ printf ("SUCCESS.\n"); -+ } -+ -+ /* Test IP address netmask handling */ -+ printf ("Testing IP address netmask stripping functionality. "); -+ int netmask_ret = test_ip_netmask_handling (cert); -+ if (netmask_ret != EOK) -+ { -+ printf ("FAILED.\n"); -+ if (ret == EOK) -+ ret = netmask_ret; /* Store first failure */ -+ } -+ else -+ { -+ printf ("SUCCESS.\n"); -+ } -+ -+ /* ============= CA CERTIFICATE TESTS ============= */ -+ -+ printf ("\n=== CA CERTIFICATE TESTS ===\n"); -+ -+ /* Set up options for CA creation */ -+ memset (&ca_options, 0, sizeof (ca_options)); -+ ca_options.country = "US"; -+ ca_options.state = ""; -+ ca_options.locality = ""; -+ ca_options.org = "Unspecified"; -+ ca_options.email = ""; -+ ca_options.hostname = "server.example.com"; -+ ca_options.hash_fn = EVP_sha256 (); -+ ca_options.lifetime = 3650; -+ ca_options.verbosity = SSCG_QUIET; -+ -+ /* Set up the same subject alternative names for the CA */ -+ ca_options.subject_alt_names = certinfo->subject_alt_names; -+ -+ /* Create the private CA */ -+ printf ("Creating private CA certificate. "); -+ ret = create_private_CA (tmp_ctx, &ca_options, &ca_cert, &ca_key); -+ if (ret != EOK) -+ { -+ printf ("FAILED.\n"); -+ goto done; -+ } -+ else -+ { -+ printf ("SUCCESS.\n"); -+ } -+ -+ /* Verify name constraints in the CA certificate */ -+ printf ("Verifying name constraints in CA certificate. "); -+ int ca_constraints_ret = -+ verify_name_constraints (ca_cert, certinfo->subject_alt_names); -+ if (ca_constraints_ret != EOK) -+ { -+ printf ("FAILED.\n"); -+ if (ret == EOK) -+ ret = ca_constraints_ret; -+ } -+ else -+ { -+ printf ("SUCCESS.\n"); -+ } -+ -+ /* Summary of all test results */ -+ printf ("\n=== TEST SUMMARY ===\n"); -+ printf ("Service cert SAN verification: %s\n", -+ verify_ret == EOK ? "PASS" : "FAIL"); -+ printf ("Service cert edge case validation: %s\n", -+ edge_ret == EOK ? "PASS" : "FAIL"); -+ printf ("Service cert netmask handling: %s\n", -+ netmask_ret == EOK ? "PASS" : "FAIL"); -+ printf ("CA certificate creation: %s\n", ca_cert ? "PASS" : "FAIL"); -+ printf ("CA name constraints verification: %s\n", -+ ca_constraints_ret == EOK ? "PASS" : "FAIL"); -+ - done: - if (ret != EOK) - { --- -2.50.1 - diff --git a/changelog b/changelog new file mode 100644 index 0000000..12e69b9 --- /dev/null +++ b/changelog @@ -0,0 +1,264 @@ +* Mon Aug 11 2025 Stephen Gallagher - 3.0.0-10 +- Fix IP address handling in CA certificate SAN constraints +- Resolves: RHEL-107289 + +* Tue Apr 22 2025 Stephen Gallagher - 3.0.0-9 +- Ensure 'critical' basicConstraint for CA cert +- Resolves: RHEL-88119 + +* Wed Apr 02 2025 Stephen Gallagher - 3.0.0-8 +- x509: Use proper version for CSR +- Resolves: RHEL-85851 + +* Fri Dec 02 2022 Stephen Gallagher - 3.0.0-7 +- Use EVP_default_properties_is_fips_enabled() on OpenSSL 3.0 +- Related: rhbz#2083879 + +* Mon Nov 28 2022 Stephen Gallagher - 3.0.0-6 +- Don't fail if default dhparams file can't be created +- Resolves: rhbz#2149064 + +* Wed Mar 09 2022 Stephen Gallagher - 3.0.0-5 +- Handle IP addresses in subjectAlternativeName correctly +- Resolves: rhbz#2061923 + +* Fri Oct 29 2021 Stephen Gallagher - 3.0.0-4 +- Correct certificate lifetime calculation +- Resolves: rhbz#2017667 + +* Tue Aug 10 2021 Mohan Boddu - 3.0.0-3 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Sat Aug 07 2021 Stephen Gallagher - 3.0.0-2 +- Drop usage of removed macro ERR_GET_FUNC() +- Related: rhbz#1964837 + +* Wed Jul 21 2021 Stephen Gallagher - 3.0.0-1 +- Release 3.0.0 +- Support for OpenSSL 3.0 +- Support for outputting named Diffie-Hellman parameter groups +- Support for CentOS Stream 9 +- Resolves: rhbz#1984468 + +* Wed Jun 16 2021 Mohan Boddu - 2.6.2-8 +- Rebuilt for RHEL 9 BETA for openssl 3.0 + Related: rhbz#1971065 + +* Wed May 26 2021 Stephen Gallagher - 2.6.2-7 +- OpenSSL 3.0 compatibility: fix RSA key-generation test +- Resolves: rhbz#1964837 + +* Fri Apr 16 2021 Mohan Boddu - 2.6.2-6 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Wed Mar 17 2021 Stephen Gallagher - 2.6.2-5 +- Fixing incorrect license declaration + +* Wed Mar 17 2021 Stephen Gallagher - 2.6.2-4 +- Updating to rebuild against the latest glibc + +* Wed Jan 27 2021 Fedora Release Engineering - 2.6.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Wed Jul 29 2020 Fedora Release Engineering - 2.6.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue Jun 23 2020 Stephen Gallagher - 2.6.2-1 +- Update to 2.6.2 +- Handle very short and very long passphrases properly (fixes rhbz#1850183) +- Drop upstreamed patch + +* Thu Apr 30 2020 Stephen Gallagher - 2.6.1-4 +- Rebuild with corrected ELN macro definitions + +* Thu Apr 30 2020 Stephen Gallagher - 2.6.1-3 +- Don't bother running clang-format in the RPM build +- Lengthen the test timeout so ARM tests pass + +* Fri Jan 31 2020 Fedora Release Engineering - 2.6.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Jan 09 2020 Stephen Gallagher - 2.6.1-1 +- Bugfixes from upstream + +* Fri Dec 13 2019 Stephen Gallagher - 2.6.0-2 +- Fix incorrect help description for --client-key-file + +* Fri Dec 13 2019 Stephen Gallagher - 2.6.0-1 +- Update to 2.6.0 +- Can now generate an empty CRL file. +- Can now create and store a Diffie-Hellman parameters (dhparams) file. +- Support for setting a password on private keys. +- Support for generating a client authentication certificate and key. +- Better support for OpenSSL 1.0 + +* Sat Jul 27 2019 Fedora Release Engineering - 2.5.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Sun Feb 03 2019 Fedora Release Engineering - 2.5.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Wed Nov 28 2018 Stephen Gallagher - 2.5.1-1 +- Update to 2.5.1 +- Fixes discovered by automated testing. + +* Wed Nov 28 2018 Stephen Gallagher - 2.5.0-1 +- Update to 2.5.0 +- Auto-detect the hash algorithm to use by default. + +* Tue Nov 27 2018 Stephen Gallagher - 2.4.0-1 +- Update to 2.4.0 +- Autodetect the minimum key strength from the system security level. +- Disallow setting a key strength below the system minimum. + +- Drop upstreamed patches + +* Mon Sep 17 2018 Stephen Gallagher - 2.3.3-4 +- Add a manpage. + +* Sat Jul 14 2018 Fedora Release Engineering - 2.3.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Fri Feb 09 2018 Fedora Release Engineering - 2.3.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Fri Feb 02 2018 Stephen Gallagher - 2.3.3-1 +- Update to 2.3.3 +- Do not overwrite destination files without --force + +* Thu Jan 25 2018 Stephen Gallagher - 2.3.2-1 +- Update to 2.3.2 +- Properly support hostnames up to 64 characters +- Resolves: rhbz#1535537 + +* Tue Jan 02 2018 Stephen Gallagher - 2.3.1-2 +- Skip tests on 32-bit ARM for now + +* Tue Jan 02 2018 Stephen Gallagher - 2.3.1-1 +- Update to 2.3.1 +- Bundle popt 1.16 on older releases like EPEL. + +* Mon Dec 18 2017 Stephen Gallagher - 2.3.0-1 +- Update to 2.3.0 +- Switch to meson build system +- Add support for non-DNS subjectAlternativeName values (issue #4) + +* Thu Sep 21 2017 Stephen Gallagher - 2.2.0-1 +- Reorder combined PEM file +- Resolves: RHBZ#1494208 + +* Wed Sep 20 2017 Stephen Gallagher - 2.1.0-1 +- Add --email argument for setting emailAddress in the issuer + +* Thu Aug 03 2017 Fedora Release Engineering - 2.0.4-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 2.0.4-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Mon Apr 03 2017 Stephen Gallagher - 2.0.4-2 +- Bump release to perform taskotron tests + +* Tue Mar 21 2017 Stephen Gallagher - 2.0.4-1 +- Update to 2.0.4 +- Addresses a potential race-condition when the key and certificate share the + same file. + +* Wed Mar 08 2017 Stephen Gallagher - 2.0.3-1 +- Update to 2.0.3 +- Adds support for setting the file mode on the output certificates + and keys. + +* Fri Mar 03 2017 Stephen Gallagher - 2.0.2-1 +- Update to 2.0.2 +- Always run with umask(077) + +* Fri Mar 03 2017 Stephen Gallagher - 2.0.1-1 +- Update to 2.0.1 +- Fix an issue with passing certificate lifetime explicitly + +* Thu Feb 16 2017 Stephen Gallagher - 2.0.0-1 +- Update to 2.0.0 + +* Thu Feb 16 2017 Stephen Gallagher - 1.1.0-6 +- Exclude PPC64 from the build since it doesn't support linking to OpenSSL + +* Sat Feb 11 2017 Fedora Release Engineering - 1.1.0-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Wed Nov 23 2016 Stephen Gallagher - 1.1.0-4 +- Use compat-openssl10-devel on F26+ + +* Thu Jul 21 2016 Fedora Release Engineering - 1.1.0-3 +- https://fedoraproject.org/wiki/Changes/golang1.7 + +* Tue May 31 2016 Stephen Gallagher - 1.1.0-2 +- Debundle spacelog + +* Wed May 25 2016 Stephen Gallagher - 1.1.0-1 +- Update to 1.1.0 +- Add support for signing service keys with an existing CA + +* Wed May 25 2016 Stephen Gallagher - 1.0.4-1 +- Add support for exporting the CA private key +- Fix incorrect output from -version +- Add README.md + +* Tue May 24 2016 Stephen Gallagher - 1.0.3-1 +- Only sign certificates after all extensions have been added + +* Mon May 23 2016 Stephen Gallagher - 1.0.2-1 +- Generate x509v3 certificates + +* Mon May 23 2016 Stephen Gallagher - 1.0.1-1 +- Fix issue with temporary file creation + +* Mon May 23 2016 Stephen Gallagher - 1.0.0-1 +- New upstream release 1.0.0 +- Rewritten in Go +- Runtime depends only on OpenSSL, no more Python +- Support for writing certificate and key in a single file + +* Wed May 18 2016 Stephen Gallagher - 0.4.1-4 +- Add requirement on python-setuptools + +* Fri Feb 05 2016 Fedora Release Engineering - 0.4.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Tue Nov 10 2015 Fedora Release Engineering - 0.4.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Changes/python3.5 + +* Fri Jun 19 2015 Fedora Release Engineering - 0.4.1-1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Mon Mar 30 2015 Stephen Gallagher 0.4.1-1 +- Change default CA location to match service certificate +- Improve error handling + +* Tue Mar 24 2015 Stephen Gallagher 0.4.0-1 +- Spec file cleanups +- PEP8 Cleanups +- Make location arguments optional + +* Mon Mar 23 2015 Stephen Gallagher 0.3.0-1 +- Rename to sscg +- Only build with default python interpreter + +* Tue Mar 17 2015 Stephen Gallagher 0.2.1-1 +- Include the LICENSE file in the tarball + +* Tue Mar 17 2015 Stephen Gallagher 0.2-2 +- Include the license in the build RPMs + +* Tue Mar 17 2015 Stephen Gallagher 0.2-1 +- Add support for namedConstraints +- Add support for subjectAltNames +- Fix packaging issues from Fedora package review + +* Mon Mar 16 2015 Stephen Gallagher 0.1-2 +- Update BuildRequires + +* Mon Mar 16 2015 Stephen Gallagher 0.1-1 +- First packaging + diff --git a/sources b/sources index 0d66b9c..6dc9c06 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (sscg-3.0.0.tar.xz) = d5bbd14c102bb11b387b6018dced09b23b053498c60befd916aa142ece8240f443e364d9a578b6b5aa15c68cb943725ed96ef44cce77eb01013e464a6d4dc0f1 +SHA512 (sscg-4.0.0.tar.gz) = 163fd89520714a8e9643c0f83c84b3d602b77351e4094bb214a2545cacaef10a0b195fd7f176ac3c8bca975c3b96568eb802e562f13d5e94438f728cea6e8965 diff --git a/sscg.spec b/sscg.spec index e0a5d84..c6a2886 100644 --- a/sscg.spec +++ b/sscg.spec @@ -8,14 +8,13 @@ Name: sscg -Version: 3.0.0 -Release: 10%{?dist} -Summary: Simple SSL certificate generator +Version: 4.0.0 +Release: %autorelease +Summary: Simple Signed Certificate Generator -License: GPLv3+ with exceptions +License: GPL-3.0-or-later WITH cryptsetup-OpenSSL-exception URL: https://%{provider_prefix} -Source0: https://%{provider_prefix}/releases/download/%{repo}-%{version}/%{repo}-%{version}.tar.xz - +Source0: %{URL}/archive/refs/tags/sscg-%{version}.tar.gz BuildRequires: gcc BuildRequires: libtalloc-devel BuildRequires: openssl-devel @@ -26,15 +25,6 @@ BuildRequires: ninja-build BuildRequires: help2man -Patch: 0001-Drop-usage-of-ERR_GET_FUNC.patch -Patch: 0002-Correct-certificate-lifetime-calculation.patch -Patch: 0003-Truncate-IP-address-in-SAN.patch -Patch: 0004-dhparams-don-t-fail-if-default-file-can-t-be-created.patch -Patch: 0005-dhparams-Fix-the-FIPS_mode-call-for-OpenSSL-3.0.patch -Patch: 0006-x509-Use-proper-version-for-CSR.patch -Patch: 0007-Ensure-critical-basicConstraint-for-CA-cert.patch -Patch: 0008-Fix-IP-address-handling-in-CA-certificate-SAN-constr.patch - %description A utility to aid in the creation of more secure "self-signed" certificates. The certificates created by this tool are generated in a @@ -44,7 +34,7 @@ up a full PKI environment and without exposing the machine to a risk of false signatures from the service certificate. %prep -%autosetup -p1 +%autosetup -p1 -n sscg-sscg-%{version} %build @@ -64,267 +54,4 @@ false signatures from the service certificate. %{_mandir}/man8/%{name}.8* %changelog -* Mon Aug 11 2025 Stephen Gallagher - 3.0.0-10 -- Fix IP address handling in CA certificate SAN constraints -- Resolves: RHEL-107289 - -* Tue Apr 22 2025 Stephen Gallagher - 3.0.0-9 -- Ensure 'critical' basicConstraint for CA cert -- Resolves: RHEL-88119 - -* Wed Apr 02 2025 Stephen Gallagher - 3.0.0-8 -- x509: Use proper version for CSR -- Resolves: RHEL-85851 - -* Fri Dec 02 2022 Stephen Gallagher - 3.0.0-7 -- Use EVP_default_properties_is_fips_enabled() on OpenSSL 3.0 -- Related: rhbz#2083879 - -* Mon Nov 28 2022 Stephen Gallagher - 3.0.0-6 -- Don't fail if default dhparams file can't be created -- Resolves: rhbz#2149064 - -* Wed Mar 09 2022 Stephen Gallagher - 3.0.0-5 -- Handle IP addresses in subjectAlternativeName correctly -- Resolves: rhbz#2061923 - -* Fri Oct 29 2021 Stephen Gallagher - 3.0.0-4 -- Correct certificate lifetime calculation -- Resolves: rhbz#2017667 - -* Tue Aug 10 2021 Mohan Boddu - 3.0.0-3 -- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags - Related: rhbz#1991688 - -* Sat Aug 07 2021 Stephen Gallagher - 3.0.0-2 -- Drop usage of removed macro ERR_GET_FUNC() -- Related: rhbz#1964837 - -* Wed Jul 21 2021 Stephen Gallagher - 3.0.0-1 -- Release 3.0.0 -- Support for OpenSSL 3.0 -- Support for outputting named Diffie-Hellman parameter groups -- Support for CentOS Stream 9 -- Resolves: rhbz#1984468 - -* Wed Jun 16 2021 Mohan Boddu - 2.6.2-8 -- Rebuilt for RHEL 9 BETA for openssl 3.0 - Related: rhbz#1971065 - -* Wed May 26 2021 Stephen Gallagher - 2.6.2-7 -- OpenSSL 3.0 compatibility: fix RSA key-generation test -- Resolves: rhbz#1964837 - -* Fri Apr 16 2021 Mohan Boddu - 2.6.2-6 -- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 - -* Wed Mar 17 2021 Stephen Gallagher - 2.6.2-5 -- Fixing incorrect license declaration - -* Wed Mar 17 2021 Stephen Gallagher - 2.6.2-4 -- Updating to rebuild against the latest glibc - -* Wed Jan 27 2021 Fedora Release Engineering - 2.6.2-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild - -* Wed Jul 29 2020 Fedora Release Engineering - 2.6.2-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild - -* Tue Jun 23 2020 Stephen Gallagher - 2.6.2-1 -- Update to 2.6.2 -- Handle very short and very long passphrases properly (fixes rhbz#1850183) -- Drop upstreamed patch - -* Thu Apr 30 2020 Stephen Gallagher - 2.6.1-4 -- Rebuild with corrected ELN macro definitions - -* Thu Apr 30 2020 Stephen Gallagher - 2.6.1-3 -- Don't bother running clang-format in the RPM build -- Lengthen the test timeout so ARM tests pass - -* Fri Jan 31 2020 Fedora Release Engineering - 2.6.1-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild - -* Thu Jan 09 2020 Stephen Gallagher - 2.6.1-1 -- Bugfixes from upstream - -* Fri Dec 13 2019 Stephen Gallagher - 2.6.0-2 -- Fix incorrect help description for --client-key-file - -* Fri Dec 13 2019 Stephen Gallagher - 2.6.0-1 -- Update to 2.6.0 -- Can now generate an empty CRL file. -- Can now create and store a Diffie-Hellman parameters (dhparams) file. -- Support for setting a password on private keys. -- Support for generating a client authentication certificate and key. -- Better support for OpenSSL 1.0 - -* Sat Jul 27 2019 Fedora Release Engineering - 2.5.1-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild - -* Sun Feb 03 2019 Fedora Release Engineering - 2.5.1-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild - -* Wed Nov 28 2018 Stephen Gallagher - 2.5.1-1 -- Update to 2.5.1 -- Fixes discovered by automated testing. - -* Wed Nov 28 2018 Stephen Gallagher - 2.5.0-1 -- Update to 2.5.0 -- Auto-detect the hash algorithm to use by default. - -* Tue Nov 27 2018 Stephen Gallagher - 2.4.0-1 -- Update to 2.4.0 -- Autodetect the minimum key strength from the system security level. -- Disallow setting a key strength below the system minimum. - -- Drop upstreamed patches - -* Mon Sep 17 2018 Stephen Gallagher - 2.3.3-4 -- Add a manpage. - -* Sat Jul 14 2018 Fedora Release Engineering - 2.3.3-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild - -* Fri Feb 09 2018 Fedora Release Engineering - 2.3.3-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild - -* Fri Feb 02 2018 Stephen Gallagher - 2.3.3-1 -- Update to 2.3.3 -- Do not overwrite destination files without --force - -* Thu Jan 25 2018 Stephen Gallagher - 2.3.2-1 -- Update to 2.3.2 -- Properly support hostnames up to 64 characters -- Resolves: rhbz#1535537 - -* Tue Jan 02 2018 Stephen Gallagher - 2.3.1-2 -- Skip tests on 32-bit ARM for now - -* Tue Jan 02 2018 Stephen Gallagher - 2.3.1-1 -- Update to 2.3.1 -- Bundle popt 1.16 on older releases like EPEL. - -* Mon Dec 18 2017 Stephen Gallagher - 2.3.0-1 -- Update to 2.3.0 -- Switch to meson build system -- Add support for non-DNS subjectAlternativeName values (issue #4) - -* Thu Sep 21 2017 Stephen Gallagher - 2.2.0-1 -- Reorder combined PEM file -- Resolves: RHBZ#1494208 - -* Wed Sep 20 2017 Stephen Gallagher - 2.1.0-1 -- Add --email argument for setting emailAddress in the issuer - -* Thu Aug 03 2017 Fedora Release Engineering - 2.0.4-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild - -* Thu Jul 27 2017 Fedora Release Engineering - 2.0.4-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild - -* Mon Apr 03 2017 Stephen Gallagher - 2.0.4-2 -- Bump release to perform taskotron tests - -* Tue Mar 21 2017 Stephen Gallagher - 2.0.4-1 -- Update to 2.0.4 -- Addresses a potential race-condition when the key and certificate share the - same file. - -* Wed Mar 08 2017 Stephen Gallagher - 2.0.3-1 -- Update to 2.0.3 -- Adds support for setting the file mode on the output certificates - and keys. - -* Fri Mar 03 2017 Stephen Gallagher - 2.0.2-1 -- Update to 2.0.2 -- Always run with umask(077) - -* Fri Mar 03 2017 Stephen Gallagher - 2.0.1-1 -- Update to 2.0.1 -- Fix an issue with passing certificate lifetime explicitly - -* Thu Feb 16 2017 Stephen Gallagher - 2.0.0-1 -- Update to 2.0.0 - -* Thu Feb 16 2017 Stephen Gallagher - 1.1.0-6 -- Exclude PPC64 from the build since it doesn't support linking to OpenSSL - -* Sat Feb 11 2017 Fedora Release Engineering - 1.1.0-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild - -* Wed Nov 23 2016 Stephen Gallagher - 1.1.0-4 -- Use compat-openssl10-devel on F26+ - -* Thu Jul 21 2016 Fedora Release Engineering - 1.1.0-3 -- https://fedoraproject.org/wiki/Changes/golang1.7 - -* Tue May 31 2016 Stephen Gallagher - 1.1.0-2 -- Debundle spacelog - -* Wed May 25 2016 Stephen Gallagher - 1.1.0-1 -- Update to 1.1.0 -- Add support for signing service keys with an existing CA - -* Wed May 25 2016 Stephen Gallagher - 1.0.4-1 -- Add support for exporting the CA private key -- Fix incorrect output from -version -- Add README.md - -* Tue May 24 2016 Stephen Gallagher - 1.0.3-1 -- Only sign certificates after all extensions have been added - -* Mon May 23 2016 Stephen Gallagher - 1.0.2-1 -- Generate x509v3 certificates - -* Mon May 23 2016 Stephen Gallagher - 1.0.1-1 -- Fix issue with temporary file creation - -* Mon May 23 2016 Stephen Gallagher - 1.0.0-1 -- New upstream release 1.0.0 -- Rewritten in Go -- Runtime depends only on OpenSSL, no more Python -- Support for writing certificate and key in a single file - -* Wed May 18 2016 Stephen Gallagher - 0.4.1-4 -- Add requirement on python-setuptools - -* Fri Feb 05 2016 Fedora Release Engineering - 0.4.1-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild - -* Tue Nov 10 2015 Fedora Release Engineering - 0.4.1-2 -- Rebuilt for https://fedoraproject.org/wiki/Changes/python3.5 - -* Fri Jun 19 2015 Fedora Release Engineering - 0.4.1-1 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild - -* Mon Mar 30 2015 Stephen Gallagher 0.4.1-1 -- Change default CA location to match service certificate -- Improve error handling - -* Tue Mar 24 2015 Stephen Gallagher 0.4.0-1 -- Spec file cleanups -- PEP8 Cleanups -- Make location arguments optional - -* Mon Mar 23 2015 Stephen Gallagher 0.3.0-1 -- Rename to sscg -- Only build with default python interpreter - -* Tue Mar 17 2015 Stephen Gallagher 0.2.1-1 -- Include the LICENSE file in the tarball - -* Tue Mar 17 2015 Stephen Gallagher 0.2-2 -- Include the license in the build RPMs - -* Tue Mar 17 2015 Stephen Gallagher 0.2-1 -- Add support for namedConstraints -- Add support for subjectAltNames -- Fix packaging issues from Fedora package review - -* Mon Mar 16 2015 Stephen Gallagher 0.1-2 -- Update BuildRequires - -* Mon Mar 16 2015 Stephen Gallagher 0.1-1 -- First packaging - +%autochangelog