[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