#include <haproxy/pattern.h>
#include <haproxy/sink.h>
#include <haproxy/ssl_ckch.h>
+#include <haproxy/ssl_gencert.h>
#include <haproxy/ssl_sock.h>
#include <haproxy/ssl_utils.h>
#include <haproxy/tools.h>
ACME_RET_FAIL = 2
};
-static EVP_PKEY *acme_EVP_PKEY_gen(int keytype, int curves, int bits, char **errmsg);
static int acme_start_task(struct ckch_store *store, char **errmsg);
static struct task *acme_scheduler(struct task *task, void *context, unsigned int state);
} else {
ha_notice("acme: generate account key '%s' for acme section '%s'.\n", path, cur_acme->name);
- if ((key = acme_EVP_PKEY_gen(cur_acme->key.type, cur_acme->key.curves, cur_acme->key.bits, &errmsg)) == NULL) {
+ if ((key = ssl_gen_EVP_PKEY(cur_acme->key.type, cur_acme->key.curves, cur_acme->key.bits, &errmsg)) == NULL) {
ha_alert("acme: %s\n", errmsg);
goto out;
}
}
-/* Return a new Generated private key of type <keytype> with <bits> and <curves> */
-static EVP_PKEY *acme_EVP_PKEY_gen(int keytype, int curves, int bits, char **errmsg)
-{
-
- EVP_PKEY_CTX *pkey_ctx = NULL;
- EVP_PKEY *pkey = NULL;
-
- if ((pkey_ctx = EVP_PKEY_CTX_new_id(keytype, NULL)) == NULL) {
- memprintf(errmsg, "%sCan't generate a private key.\n", errmsg && *errmsg ? *errmsg : "");
- goto err;
- }
-
- if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) {
- memprintf(errmsg, "%sCan't generate a private key.\n", errmsg && *errmsg ? *errmsg : "");
- goto err;
- }
-
- if (keytype == EVP_PKEY_EC) {
- if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pkey_ctx, curves) <= 0) {
- memprintf(errmsg, "%sCan't set the curves on the new private key.\n", errmsg && *errmsg ? *errmsg : "");
- goto err;
- }
- } else if (keytype == EVP_PKEY_RSA) {
- if (EVP_PKEY_CTX_set_rsa_keygen_bits(pkey_ctx, bits) <= 0) {
- memprintf(errmsg, "%sCan't set the bits on the new private key.\n", errmsg && *errmsg ? *errmsg : "");
- goto err;
- }
- }
-
- if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) {
- memprintf(errmsg, "%sCan't generate a private key.\n", errmsg && *errmsg ? *errmsg : "");
- goto err;
- }
-
-err:
- EVP_PKEY_CTX_free(pkey_ctx);
- return pkey;
-}
-
/*
* Generate a temporary expired X509 or reuse the one generated.
* Use tmp_pkey to generate
*/
X509 *acme_gen_tmp_x509()
{
- X509 *newcrt = NULL;
- X509_NAME *name;
- const EVP_MD *digest = NULL;
- 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, (unsigned char *)"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) {
- X509_NAME_free(name);
- 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();
- else
- goto mkcert_error;
-
- if (!(X509_sign(newcrt, pkey, digest)))
- goto mkcert_error;
-
- tmp_x509 = newcrt;
+ return NULL;
- return newcrt;
-
-mkcert_error:
- if (ctmp) NCONF_free(ctmp);
- if (newcrt) X509_free(newcrt);
- return NULL;
+ tmp_x509 = ssl_gen_x509(tmp_pkey);
+ return tmp_x509;
}
-
/*
* Generate a temporary RSA2048 pkey or reuse the one generated.
*
return tmp_pkey;
}
- tmp_pkey = acme_EVP_PKEY_gen(EVP_PKEY_RSA, 0, 2048, NULL);
+ tmp_pkey = ssl_gen_EVP_PKEY(EVP_PKEY_RSA, 0, 2048, NULL);
return tmp_pkey;
}
ctx->retries = ACME_RETRY;
if (!cfg->reuse_key) {
- if ((pkey = acme_EVP_PKEY_gen(cfg->key.type, cfg->key.curves, cfg->key.bits, errmsg)) == NULL)
+ if ((pkey = ssl_gen_EVP_PKEY(cfg->key.type, cfg->key.curves, cfg->key.bits, errmsg)) == NULL)
goto err;
EVP_PKEY_free(newstore->data->key);
}
#endif
}
+
+/* Return a new Generated private key of type <keytype> with <bits> and <curves> */
+EVP_PKEY *ssl_gen_EVP_PKEY(int keytype, int curves, int bits, char **errmsg)
+{
+
+ EVP_PKEY_CTX *pkey_ctx = NULL;
+ EVP_PKEY *pkey = NULL;
+
+ if ((pkey_ctx = EVP_PKEY_CTX_new_id(keytype, NULL)) == NULL) {
+ memprintf(errmsg, "%sCan't generate a private key.\n", errmsg && *errmsg ? *errmsg : "");
+ goto err;
+ }
+
+ if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) {
+ memprintf(errmsg, "%sCan't generate a private key.\n", errmsg && *errmsg ? *errmsg : "");
+ goto err;
+ }
+
+ if (keytype == EVP_PKEY_EC) {
+ if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pkey_ctx, curves) <= 0) {
+ memprintf(errmsg, "%sCan't set the curves on the new private key.\n", errmsg && *errmsg ? *errmsg : "");
+ goto err;
+ }
+ } else if (keytype == EVP_PKEY_RSA) {
+ if (EVP_PKEY_CTX_set_rsa_keygen_bits(pkey_ctx, bits) <= 0) {
+ memprintf(errmsg, "%sCan't set the bits on the new private key.\n", errmsg && *errmsg ? *errmsg : "");
+ goto err;
+ }
+ }
+
+ if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) {
+ memprintf(errmsg, "%sCan't generate a private key.\n", errmsg && *errmsg ? *errmsg : "");
+ goto err;
+ }
+
+err:
+ EVP_PKEY_CTX_free(pkey_ctx);
+ return pkey;
+}
+
+/*
+ * Generate an expired X509 from <pkey> private key which must be initialized.
+ * Return a pointer to the created X509 object if succeeded, NULL if not.
+ */
+X509 *ssl_gen_x509(EVP_PKEY *pkey)
+{
+ X509 *newcrt = NULL;
+ X509_NAME *name;
+ const EVP_MD *digest = NULL;
+ CONF *ctmp = NULL;
+ int key_type;
+
+ /* 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, (unsigned char *)"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) {
+ X509_NAME_free(name);
+ 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();
+ else
+ goto mkcert_error;
+
+ if (!(X509_sign(newcrt, pkey, digest)))
+ goto mkcert_error;
+
+ return newcrt;
+
+mkcert_error:
+ if (ctmp) NCONF_free(ctmp);
+ if (newcrt) X509_free(newcrt);
+ return NULL;
+
+}
+
REGISTER_POST_DEINIT(__ssl_gencert_deinit);