[rs-commit] r52 - in /mod_ca/trunk: ChangeLog mod_ca_simple.c
rs-commit at redwax.eu
rs-commit at redwax.eu
Thu Apr 25 00:02:23 CEST 2019
Author: minfrin at redwax.eu
Date: Thu Apr 25 00:02:22 2019
New Revision: 52
Log:
Add an implementation of the ca_makekey hook to mod_ca_simple.
Modified:
mod_ca/trunk/ChangeLog
mod_ca/trunk/mod_ca_simple.c
Modified: mod_ca/trunk/ChangeLog
==============================================================================
--- mod_ca/trunk/ChangeLog (original)
+++ mod_ca/trunk/ChangeLog Thu Apr 25 00:02:22 2019
@@ -1,5 +1,8 @@
Changes with v0.2.0
+
+ *) Add an implementation of the ca_makekey hook to mod_ca_simple.
+ [Graham Leggett]
*) Add the ca_makekey hook. [Graham Leggett]
Modified: mod_ca/trunk/mod_ca_simple.c
==============================================================================
--- mod_ca/trunk/mod_ca_simple.c (original)
+++ mod_ca/trunk/mod_ca_simple.c Thu Apr 25 00:02:22 2019
@@ -20,12 +20,8 @@
* Author: Graham Leggett
*
*/
-#include <apr_lib.h>
-#include <apr_sha1.h>
#include <apr_strings.h>
#include <apr_hash.h>
-#include <apr_uuid.h>
-#include <apr_base64.h>
#include <openssl/err.h>
#include <openssl/evp.h>
@@ -52,36 +48,38 @@
typedef struct
{
+ int signer_set :1;
+ int next_signer_set :1;
+ int key_set :1;
+ int days_set :1;
+ int serial_random_set :1;
+ int serial_subject_set :1;
+ int time_set :1;
+ int ext_set :1;
+ int pkey_ctx_set :1;
X509 *signer;
+ X509 *signer_ca;
+ X509 *next_signer;
X509_NAME *signer_name;
+ EVP_PKEY *key;
+ EVP_PKEY_CTX *pkey_ctx;
+ apr_array_header_t *ext;
unsigned char *signer_der;
+ unsigned char *signer_chain_der;
+ unsigned char *signer_ca_der;
+ unsigned char *next_signer_der;
+ apr_time_t signer_expires;
+ apr_time_t signer_chain_expires;
+ apr_time_t signer_ca_expires;
+ apr_time_t next_signer_expires;
int signer_der_len;
- apr_time_t signer_expires;
- unsigned char *signer_chain_der;
int signer_chain_der_len;
- apr_time_t signer_chain_expires;
- X509 *signer_ca;
- unsigned char *signer_ca_der;
int signer_ca_der_len;
- apr_time_t signer_ca_expires;
- int signer_set;
- X509 *next_signer;
- unsigned char *next_signer_der;
int next_signer_der_len;
- apr_time_t next_signer_expires;
- int next_signer_set;
- EVP_PKEY *key;
- int key_set;
int days;
- int days_set;
int serial_random;
- int serial_random_set;
int serial_subject;
- int serial_subject_set;
int time;
- int time_set;
- apr_array_header_t *ext;
- int ext_set;
} ca_config_rec;
struct ap_ca_instance_t
@@ -155,6 +153,18 @@
else {
return message;
}
+}
+
+static apr_status_t ca_EVP_PKEY_cleanup(void *data)
+{
+ EVP_PKEY_free((EVP_PKEY *) data);
+ return APR_SUCCESS;
+}
+
+static apr_status_t ca_EVP_PKEY_CTX_cleanup(void *data)
+{
+ EVP_PKEY_CTX_free((EVP_PKEY_CTX *) data);
+ return APR_SUCCESS;
}
static apr_status_t ca_PKCS7_cleanup(void *data)
@@ -723,6 +733,49 @@
}
if (amicro) {
*amicro = 0;
+ }
+
+ return OK;
+}
+
+static int ca_simple_makekey(request_rec *r, apr_hash_t *params,
+ const unsigned char **key, apr_size_t *len)
+{
+ ca_config_rec *conf = ap_get_module_config(r->per_dir_config,
+ &ca_simple_module);
+
+ EVP_PKEY *pkey = NULL;
+ unsigned char *tmp;
+
+ /* return a private key? */
+ if (!conf->pkey_ctx) {
+ return DECLINED;
+ }
+
+ if (EVP_PKEY_keygen(conf->pkey_ctx, &pkey) <= 0) {
+ log_message(r, APR_SUCCESS, "could not generate a private key");
+
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ apr_pool_cleanup_register(r->pool, pkey, ca_EVP_PKEY_cleanup,
+ apr_pool_cleanup_null);
+
+ /* write out the key */
+ *len = i2d_PrivateKey(pkey, NULL);
+ if (*len <= 0) {
+ log_message(r, APR_SUCCESS,
+ "could not DER encode the private key");
+
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ *key = tmp = apr_palloc(r->pool, *len);
+
+ if (!i2d_PrivateKey(pkey, &tmp)) {
+ log_message(r, APR_SUCCESS,
+ "could not DER encode the private key");
+
+ return HTTP_INTERNAL_SERVER_ERROR;
}
return OK;
@@ -796,6 +849,8 @@
new->time_set = add->time_set || base->time_set;
new->ext = (add->ext_set == 0) ? base->ext : add->ext;
new->ext_set = add->ext_set || base->ext_set;
+ new->pkey_ctx = (add->pkey_ctx_set == 0) ? base->pkey_ctx : add->pkey_ctx;
+ new->pkey_ctx_set = add->pkey_ctx_set || base->pkey_ctx_set;
return new;
}
@@ -1033,6 +1088,114 @@
apr_pool_cleanup_null);
conf->ext_set = 1;
+
+ return NULL;
+}
+
+static const char *set_ca_algorithm(cmd_parms *cmd, void *dconf, const char *args)
+{
+ ca_config_rec *conf = dconf;
+
+ char *arg;
+ char *tok;
+
+ const EVP_PKEY_ASN1_METHOD *method;
+ int pkey_id;
+
+ arg = apr_strtok(apr_pstrdup(cmd->pool, args), " \t", &tok);
+
+ method = EVP_PKEY_asn1_find_str(NULL, arg, -1);
+ if (!method) {
+ return log_config(cmd,
+ apr_psprintf(cmd->pool,
+ "CASimpleAlgorithm '%s' was not found", arg));
+ }
+
+ ERR_clear_error();
+
+ EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, method);
+ conf->pkey_ctx = EVP_PKEY_CTX_new_id(pkey_id, NULL);
+ if (!conf->pkey_ctx) {
+ return log_config(cmd,
+ apr_psprintf(cmd->pool,
+ "CASimpleAlgorithm '%s': EVP_PKEY_CTX could not be created for private key ID %d", arg, pkey_id));
+ }
+
+ apr_pool_cleanup_register(cmd->pool, conf->pkey_ctx, ca_EVP_PKEY_CTX_cleanup,
+ apr_pool_cleanup_null);
+
+ if (EVP_PKEY_keygen_init(conf->pkey_ctx) <= 0) {
+ return log_config(cmd,
+ apr_psprintf(cmd->pool,
+ "CASimpleAlgorithm '%s': EVP_PKEY keygen could not be initialised", arg));
+ }
+
+ while ((arg = apr_strtok(NULL,",", &tok))) {
+ char *val = strchr(arg, '=');
+ if (val) {
+ *(val++) = 0;
+ }
+ else {
+ return log_config(cmd,
+ apr_psprintf(cmd->pool,
+ "CASimpleAlgorithm parameter '%s' must be a name=value pair", arg));
+ }
+
+ if (EVP_PKEY_CTX_ctrl_str(conf->pkey_ctx, arg, val) <= 0) {
+ return log_config(cmd,
+ apr_psprintf(cmd->pool,
+ "CASimpleAlgorithm parameter '%s' cannot be set to '%s'", arg, val));
+ }
+
+ }
+
+ conf->pkey_ctx_set = 1;
+
+ return NULL;
+}
+
+static const char *set_ca_paramfile(cmd_parms *cmd, void *dconf, const char *arg)
+{
+ ca_config_rec *conf = dconf;
+
+ BIO *pbio;
+ EVP_PKEY *pkey = NULL;
+
+ pbio = BIO_new_file(arg, "r");
+ if (!pbio) {
+ return log_config(cmd,
+ apr_psprintf(cmd->pool,
+ "CASimpleParamFile '%s': Can't open parameter file", arg));
+ }
+
+ pkey = PEM_read_bio_Parameters(pbio, NULL);
+ BIO_free(pbio);
+
+ if (!pkey) {
+ return log_config(cmd,
+ apr_psprintf(cmd->pool,
+ "CASimpleParamFile '%s': Error reading parameter file", arg));
+ }
+
+ conf->pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ EVP_PKEY_free(pkey);
+
+ if (!conf->pkey_ctx) {
+ return log_config(cmd,
+ apr_psprintf(cmd->pool,
+ "CASimpleParamFile '%s': EVP_PKEY_CTX could not be created", arg));
+ }
+
+ apr_pool_cleanup_register(cmd->pool, conf->pkey_ctx, ca_EVP_PKEY_CTX_cleanup,
+ apr_pool_cleanup_null);
+
+ if (EVP_PKEY_keygen_init(conf->pkey_ctx) <= 0) {
+ return log_config(cmd,
+ apr_psprintf(cmd->pool,
+ "CASimpleParamFile '%s': EVP_PKEY keygen could not be initialised", arg));
+ }
+
+ conf->pkey_ctx_set = 1;
return NULL;
}
@@ -1063,6 +1226,12 @@
AP_INIT_TAKE2("CASimpleExtension",
set_ca_extension, NULL, RSRC_CONF | ACCESS_CONF,
"Certificate extension to add to the certificate when signed."),
+ AP_INIT_RAW_ARGS("CASimpleAlgorithm",
+ set_ca_algorithm, NULL, RSRC_CONF | ACCESS_CONF,
+ "When enabled, private keys will be generated with this algorithm."),
+ AP_INIT_TAKE1("CASimpleParamFile",
+ set_ca_paramfile, NULL, RSRC_CONF | ACCESS_CONF,
+ "When enabled, private keys will be generated with this parameter file."),
{ NULL }
};
@@ -1096,6 +1265,8 @@
APR_HOOK_MIDDLE);
ap_hook_ca_makeserial(ca_simple_makeserial_random, NULL, NULL,
APR_HOOK_LAST);
+ ap_hook_ca_makekey(ca_simple_makekey, NULL, NULL,
+ APR_HOOK_LAST);
ap_hook_ca_gettime(ca_simple_gettime, NULL, NULL, APR_HOOK_LAST);
}
More information about the rs-commit
mailing list