ACME_RET_FAIL = 2
};
-static EVP_PKEY *acme_EVP_PKEY_gen(int keytype, int curves, int bits, char **errmsg);
+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);
}
/* 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 *acme_EVP_PKEY_gen(int keytype, int curves, int bits, char **errmsg)
{
EVP_PKEY_CTX *pkey_ctx = NULL;
}
/*
- * Generate a temporary expired X509 or reuse the one generated.
- * Use tmp_pkey to generate
- *
- * Increment the refcount when returning the existing one
+ * 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 *acme_gen_tmp_x509()
+X509 *acme_gen_x509(EVP_PKEY *pkey)
{
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()))
if (!(X509_sign(newcrt, pkey, digest)))
goto mkcert_error;
- tmp_x509 = newcrt;
-
return newcrt;
mkcert_error:
}
+/*
+ * 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()
+{
+ if (tmp_x509) {
+ X509_up_ref(tmp_x509);
+ return tmp_x509;
+ }
+
+ if (!tmp_pkey)
+ return NULL;
+
+ tmp_x509 = acme_gen_x509(tmp_pkey);
+
+ return tmp_x509;
+}
/*
* Generate a temporary RSA2048 pkey or reuse the one generated.
#ifdef HAVE_ACME
errno = 0;
/* if ACME is enabled and the file does not exists, generate the PEM */
- if (s->conf.acme.id && (stat(path, &sb) == -1 && errno == ENOENT)) {
+ if ((s->conf.acme.id || s->conf.gencrt.on == 1) && (stat(path, &sb) == -1 && errno == ENOENT)) {
/* generate they key and the certificate */
- ha_notice("No certificate available for '%s', generating a temporary key pair before getting the ACME certificate\n", path);
- s->data->key = acme_gen_tmp_pkey();
- s->data->cert = acme_gen_tmp_x509();
+ if (s->conf.gencrt.on != 1) {
+ ha_notice("No certificate available for '%s', generating a temporary key pair before getting the ACME certificate\n", path);
+ s->data->key = acme_gen_tmp_pkey();
+ s->data->cert = acme_gen_tmp_x509();
+ }
+ else {
+ int type, bits, nid = -1;
+ char *curves;
+
+ if (!s->conf.gencrt.key.type)
+ type = EVP_PKEY_RSA;
+ else {
+ if (!strcmp(s->conf.gencrt.key.type, "RSA"))
+ type = EVP_PKEY_RSA;
+ else if (!strcmp(s->conf.gencrt.key.type, "ECDSA"))
+ type = EVP_PKEY_EC;
+ else {
+ memprintf(err, "Couldn't automatically generate a keypair\n");
+ err_code |= ERR_FATAL;
+ goto out;
+ }
+ }
+
+ /* default values: 2048 bits for RSA key, "secp384r1" curves for ECDSA key */
+ bits = s->conf.gencrt.key.bits ? s->conf.gencrt.key.bits : 2048;
+ curves = s->conf.gencrt.key.curves ? s->conf.gencrt.key.curves : "secp384r1";
+
+ if (type == EVP_PKEY_EC && (nid = curves2nid(curves)) == -1) {
+ memprintf(err, "unsupported curves for '%s'\n", path);
+ err_code |= ERR_FATAL;
+ goto out;
+ }
+
+ s->data->key = acme_EVP_PKEY_gen(type, nid, bits, err);
+ if (!s->data->key) {
+ err_code |= ERR_FATAL;
+ goto out;
+ }
+
+ s->data->cert = acme_gen_x509(s->data->key);
+ }
+
if (!s->data->key || !s->data->cert) {
memprintf(err, "Couldn't generate a temporary keypair for '%s'\n", path);
err_code |= ERR_FATAL;
{ "acme", offsetof(struct ckch_conf, acme.id), PARSE_TYPE_STR, ckch_conf_acme_init, },
#endif
{ "domains", offsetof(struct ckch_conf, acme.domains), PARSE_TYPE_ARRAY_SUBSTR, NULL, },
+ { "generate", offsetof(struct ckch_conf, gencrt.on), PARSE_TYPE_ONOFF, NULL, },
+ { "keytype", offsetof(struct ckch_conf, gencrt.key.type), PARSE_TYPE_STR, NULL, },
+ { "bits", offsetof(struct ckch_conf, gencrt.key.bits), PARSE_TYPE_INT, NULL, },
+ { "curves", offsetof(struct ckch_conf, gencrt.key.curves), PARSE_TYPE_STR, NULL, },
{ NULL, -1, PARSE_TYPE_STR, NULL, }
};