mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-03-14 03:22:06 +01:00
MINOR: ssl/ckch: Move EVP_PKEY and cert code generation from acme
Move acme_EVP_PKEY_gen() implementation to ssl_gencrt.c and rename it to ssl_EVP_PKEY_gen(). Also extract from acme_gen_tmp_x509() the generic part to implement ssl_gen_x509() into ssl_gencrt.c. To generate a self-signed expired certificate ssl_EVP_PKEY_gen() must be used to generate the private key. Then, ssl_gen_x509() must be called with the private key as argument. acme_gen_tmp_x509() is also modified to called these two functions to generate a temporary certificate has done before modifying this part. Such an expired self-signed certificate should not be use on the field but only during testing and development steps.
This commit is contained in:
parent
b0240bcfaf
commit
36b1fba871
@ -32,6 +32,8 @@ int ssl_sock_set_generated_cert(SSL_CTX *ctx, unsigned int key, struct bind_conf
|
||||
unsigned int ssl_sock_generated_cert_key(const void *data, size_t len);
|
||||
int ssl_sock_gencert_load_ca(struct bind_conf *bind_conf);
|
||||
void ssl_sock_gencert_free_ca(struct bind_conf *bind_conf);
|
||||
EVP_PKEY *ssl_gen_EVP_PKEY(int keytype, int curves, int bits, char **errmsg);
|
||||
X509 *ssl_gen_x509(EVP_PKEY *pkey);
|
||||
|
||||
#endif /* USE_OPENSSL */
|
||||
#endif /* _HAPROXY_SSL_GENCERT_H */
|
||||
|
||||
118
src/acme.c
118
src/acme.c
@ -30,6 +30,7 @@
|
||||
#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>
|
||||
@ -157,7 +158,6 @@ enum acme_ret {
|
||||
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);
|
||||
|
||||
@ -698,7 +698,7 @@ static int cfg_postsection_acme()
|
||||
} 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;
|
||||
}
|
||||
@ -2587,45 +2587,6 @@ error:
|
||||
|
||||
}
|
||||
|
||||
/* 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
|
||||
@ -2634,84 +2595,19 @@ err:
|
||||
*/
|
||||
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;
|
||||
return NULL;
|
||||
|
||||
/* 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 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.
|
||||
*
|
||||
@ -2725,7 +2621,7 @@ EVP_PKEY *acme_gen_tmp_pkey()
|
||||
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;
|
||||
}
|
||||
@ -2784,7 +2680,7 @@ static int acme_start_task(struct ckch_store *store, char **errmsg)
|
||||
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);
|
||||
|
||||
@ -475,5 +475,117 @@ static void __ssl_gencert_deinit(void)
|
||||
}
|
||||
#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);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user