]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: acme: generate a temporary key pair
authorWilliam Lallemand <wlallemand@haproxy.com>
Wed, 5 Nov 2025 17:44:22 +0000 (18:44 +0100)
committerWilliam Lallemand <wlallemand@haproxy.com>
Thu, 6 Nov 2025 10:56:27 +0000 (11:56 +0100)
This patch provides two functions acme_gen_tmp_pkey() and
acme_gen_tmp_x509().

These functions generates a unique keypair and X509 certificate that
will be stored in tmp_x509 and tmp_pkey. If the key pair or certificate
was already generated they will return the existing one.

The key is an RSA2048 and the X509 is generated with a expiration in the
past. The CN is "expired".

These are just placeholders to be used if we don't have files.

include/haproxy/acme.h
src/acme.c

index a6a0ed810ba52965bf43d66772d533c94b22b7f9..763a4692af54ea2078bdb906e432232109b98697 100644 (file)
@@ -5,5 +5,8 @@
 #include <haproxy/ssl_ckch-t.h>
 
 int ckch_conf_acme_init(void *value, char *buf, struct ckch_store *s, int cli, const char *filename, int linenum, char **err);
+EVP_PKEY *acme_gen_tmp_pkey();
+X509 *acme_gen_tmp_x509();
+
 
 #endif
index 9a34ab5e43bf9a76dc83f35ab91a959c066b96f4..9af0a6540f44d9ba73e6f41d4a6923aeec389fa3 100644 (file)
 
 #if defined(HAVE_ACME)
 
+static EVP_PKEY *tmp_pkey = NULL;
+static X509 *tmp_x509 = NULL;
+
+
 static void acme_trace(enum trace_level level, uint64_t mask, const struct trace_source *src,
                        const struct ist where, const struct ist func,
                        const void *a1, const void *a2, const void *a3, const void *a4);
@@ -2611,6 +2615,109 @@ err:
        return pkey;
 }
 
+/*
+ * Generate a temporary expired X509  or reuse the one generated.
+ * Use tmp_pkey to generate
+ *
+ * Increment the refcount when returning the existing one
+ */
+X509 *acme_gen_tmp_x509()
+{
+       X509         *newcrt  = NULL;
+       X509_NAME    *name;
+       const EVP_MD *digest;
+       X509V3_CTX    ctx;
+       unsigned int  i;
+       CONF         *ctmp    = NULL;
+       int           key_type;
+       EVP_PKEY *pkey = tmp_pkey;
+
+       if (tmp_x509) {
+               X509_up_ref(tmp_x509);
+               return tmp_x509;
+       }
+
+       if (!tmp_pkey)
+               goto mkcert_error;
+
+       /* Create the certificate */
+       if (!(newcrt = X509_new()))
+               goto mkcert_error;
+
+       /* Set version number for the certificate (X509v3) and the serial
+        * number */
+       if (X509_set_version(newcrt, 2L) != 1)
+               goto mkcert_error;
+
+       /* Generate an expired certificate */
+       if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*48) ||
+           !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)-60*60*24))
+               goto mkcert_error;
+
+       /* set public key in the certificate */
+       if (X509_set_pubkey(newcrt, pkey) != 1)
+               goto mkcert_error;
+
+       if ((name = X509_NAME_new()) == NULL)
+               goto mkcert_error;
+
+       /* Set the subject name using the servername but the CN */
+       if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, "expired",
+                                      -1, -1, 0) != 1) {
+               X509_NAME_free(name);
+               goto mkcert_error;
+       }
+       if (X509_set_subject_name(newcrt, name) != 1) {
+               X509_NAME_free(name);
+               goto mkcert_error;
+       }
+       /* Set issuer name as itself */
+       if (X509_set_issuer_name(newcrt, name) != 1)
+               goto mkcert_error;
+       X509_NAME_free(name);
+
+       /* Autosign the certificate with the private key */
+       key_type = EVP_PKEY_base_id(pkey);
+
+       if (key_type == EVP_PKEY_RSA)
+               digest = EVP_sha256();
+       else if (key_type == EVP_PKEY_EC)
+               digest = EVP_sha256();
+
+       if (!(X509_sign(newcrt, pkey, digest)))
+               goto mkcert_error;
+
+       tmp_x509 = newcrt;
+
+       return newcrt;
+
+mkcert_error:
+       if (ctmp) NCONF_free(ctmp);
+       if (newcrt)  X509_free(newcrt);
+       return NULL;
+
+}
+
+
+/*
+ * Generate a temporary RSA2048 pkey or reuse the one generated.
+ *
+ * Increment the refcount when returning the existing one
+ *
+ */
+EVP_PKEY *acme_gen_tmp_pkey()
+{
+       if (tmp_pkey) {
+               EVP_PKEY_up_ref(tmp_pkey);
+               return tmp_pkey;
+       }
+
+       tmp_pkey = acme_EVP_PKEY_gen(EVP_PKEY_RSA, 0, 2048, NULL);
+
+       return tmp_pkey;
+}
+
+
 /* start an ACME task */
 static int acme_start_task(struct ckch_store *store, char **errmsg)
 {