From a996902a335e61a226c55579890d5d3497e89461 Mon Sep 17 00:00:00 2001
From: Cameron Gutman <aicommander@gmail.com>
Date: Wed, 28 Dec 2022 13:03:41 -0600
Subject: [PATCH] Generate certificates with unique serial numbers (#645)

---
 src/crypto.cpp | 7 ++++++-
 src/crypto.h   | 1 +
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/crypto.cpp b/src/crypto.cpp
index c547b944..c0de0772 100644
--- a/src/crypto.cpp
+++ b/src/crypto.cpp
@@ -410,7 +410,12 @@ creds_t gen_creds(const std::string_view &cn, std::uint32_t key_bits) {
   EVP_PKEY_keygen(ctx.get(), &pkey);
 
   X509_set_version(x509.get(), 2);
-  ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), 0);
+
+  // Generate a real serial number to avoid SEC_ERROR_REUSED_ISSUER_AND_SERIAL with Firefox
+  bignum_t serial { BN_new() };
+  BN_rand(serial.get(), 159, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY); // 159 bits to fit in 20 bytes in DER format
+  BN_set_negative(serial.get(), 0);                                // Serial numbers must be positive
+  BN_to_ASN1_INTEGER(serial.get(), X509_get_serialNumber(x509.get()));
 
   constexpr auto year = 60 * 60 * 24 * 365;
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
diff --git a/src/crypto.h b/src/crypto.h
index b2b1ac12..9f2061c6 100644
--- a/src/crypto.h
+++ b/src/crypto.h
@@ -31,6 +31,7 @@ using md_ctx_t         = util::safe_ptr<EVP_MD_CTX, md_ctx_destroy>;
 using bio_t            = util::safe_ptr<BIO, BIO_free_all>;
 using pkey_t           = util::safe_ptr<EVP_PKEY, EVP_PKEY_free>;
 using pkey_ctx_t       = util::safe_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
+using bignum_t         = util::safe_ptr<BIGNUM, BN_free>;
 
 sha256_t hash(const std::string_view &plaintext);