]> granicus.if.org Git - apache/blob - modules/md/md_crypt.c
On the trunk:
[apache] / modules / md / md_crypt.c
1 /* Copyright 2017 greenbytes GmbH (https://www.greenbytes.de)
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <assert.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19
20 #include <apr_lib.h>
21 #include <apr_buckets.h>
22 #include <apr_file_io.h>
23 #include <apr_strings.h>
24
25 #include <openssl/err.h>
26 #include <openssl/evp.h>
27 #include <openssl/pem.h>
28 #include <openssl/rand.h>
29 #include <openssl/rsa.h>
30 #include <openssl/x509v3.h>
31
32 #include "md.h"
33 #include "md_crypt.h"
34 #include "md_json.h"
35 #include "md_log.h"
36 #include "md_http.h"
37 #include "md_util.h"
38
39 /* getpid for *NIX */
40 #if APR_HAVE_SYS_TYPES_H
41 #include <sys/types.h>
42 #endif
43 #if APR_HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
46
47 /* getpid for Windows */
48 #if APR_HAVE_PROCESS_H
49 #include <process.h>
50 #endif
51
52 static int initialized;
53
54 struct md_pkey_t {
55     apr_pool_t *pool;
56     EVP_PKEY   *pkey;
57 };
58
59 #ifdef MD_HAVE_ARC4RANDOM
60
61 static void seed_RAND(int pid)
62 {
63     char seed[128];
64     
65     (void)pid;
66     arc4random_buf(seed, sizeof(seed));
67     RAND_seed(seed, sizeof(seed));
68 }
69
70 #else /* ifdef MD_HAVE_ARC4RANDOM */
71
72 static int rand_choosenum(int l, int h)
73 {
74     int i;
75     char buf[50];
76
77     apr_snprintf(buf, sizeof(buf), "%.0f",
78                  (((double)(rand()%RAND_MAX)/RAND_MAX)*(h-l)));
79     i = atoi(buf)+1;
80     if (i < l) i = l;
81     if (i > h) i = h;
82     return i;
83 }
84
85 static void seed_RAND(int pid)
86 {   
87     unsigned char stackdata[256];
88     /* stolen from mod_ssl/ssl_engine_rand.c */
89     int n;
90     struct {
91         time_t t;
92         pid_t pid;
93     } my_seed;
94     
95     /*
96      * seed in the current time (usually just 4 bytes)
97      */
98     my_seed.t = time(NULL);
99     
100     /*
101      * seed in the current process id (usually just 4 bytes)
102      */
103     my_seed.pid = pid;
104     
105     RAND_seed((unsigned char *)&my_seed, sizeof(my_seed));
106     
107     /*
108      * seed in some current state of the run-time stack (128 bytes)
109      */
110     n = rand_choosenum(0, sizeof(stackdata)-128-1);
111     RAND_seed(stackdata+n, 128);
112 }
113
114 #endif /*ifdef MD_HAVE_ARC4RANDOM (else part) */
115
116
117 apr_status_t md_crypt_init(apr_pool_t *pool)
118 {
119     (void)pool;
120     
121     if (!initialized) {
122         int pid = getpid();
123         
124         ERR_load_crypto_strings();
125         OpenSSL_add_all_algorithms();
126         
127         md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, 0, pool, "initializing RAND"); 
128         while (!RAND_status()) {
129             seed_RAND(pid);
130         }
131
132         initialized = 1;
133     }
134     return APR_SUCCESS;
135 }
136
137 typedef struct {
138     char *data;
139     apr_size_t len;
140 } buffer_rec;
141
142 static apr_status_t fwrite_buffer(void *baton, apr_file_t *f, apr_pool_t *p) 
143 {
144     buffer_rec *buf = baton;
145     
146     (void)p;
147     return apr_file_write_full(f, buf->data, buf->len, &buf->len);
148 }
149
150 apr_status_t md_rand_bytes(unsigned char *buf, apr_size_t len, apr_pool_t *p)
151 {
152     apr_status_t rv;
153     
154     if (len > INT_MAX) {
155         return APR_ENOTIMPL;
156     }
157     if (APR_SUCCESS == (rv = md_crypt_init(p))) {
158         RAND_bytes((unsigned char*)buf, (int)len);
159     }
160     return rv;
161 }
162
163 typedef struct {
164     const char *pass_phrase;
165     int pass_len;
166 } passwd_ctx;
167
168 static int pem_passwd(char *buf, int size, int rwflag, void *baton)
169 {
170     passwd_ctx *ctx = baton;
171     
172     (void)rwflag;
173     if (ctx->pass_len > 0) {
174         if (ctx->pass_len < size) {
175             size = (int)ctx->pass_len;
176         }
177         memcpy(buf, ctx->pass_phrase, (size_t)size);
178     }
179     return ctx->pass_len;
180 }
181
182 /**************************************************************************************************/
183 /* date time things */
184
185 /* Get the apr time (micro seconds, since 1970) from an ASN1 time, as stored in X509
186  * certificates. OpenSSL now has a utility function, but other *SSL derivatives have
187  * not caughts up yet or chose to ignore. An alternative is implemented, we prefer 
188  * however the *SSL to maintain such things.
189  */
190 static apr_time_t md_asn1_time_get(const ASN1_TIME* time)
191 {
192 #ifdef LIBRESSL_VERSION_NUMBER
193     /* courtesy: https://stackoverflow.com/questions/10975542/asn1-time-to-time-t-conversion#11263731
194      * all bugs are mine */
195     apr_time_exp_t t;
196     apr_time_t ts;
197     const char* str = (const char*) time->data;
198     apr_size_t i = 0;
199
200     memset(&t, 0, sizeof(t));
201
202     if (time->type == V_ASN1_UTCTIME) {/* two digit year */
203         t.tm_year = (str[i++] - '0') * 10;
204         t.tm_year += (str[i++] - '0');
205         if (t.tm_year < 70)
206             t.tm_year += 100;
207     } 
208     else if (time->type == V_ASN1_GENERALIZEDTIME) {/* four digit year */
209         t.tm_year = (str[i++] - '0') * 1000;
210         t.tm_year+= (str[i++] - '0') * 100;
211         t.tm_year+= (str[i++] - '0') * 10;
212         t.tm_year+= (str[i++] - '0');
213         t.tm_year -= 1900;
214     }
215     t.tm_mon  = (str[i++] - '0') * 10;
216     t.tm_mon += (str[i++] - '0') - 1; /* -1 since January is 0 not 1. */
217     t.tm_mday = (str[i++] - '0') * 10;
218     t.tm_mday+= (str[i++] - '0');
219     t.tm_hour = (str[i++] - '0') * 10;
220     t.tm_hour+= (str[i++] - '0');
221     t.tm_min  = (str[i++] - '0') * 10;
222     t.tm_min += (str[i++] - '0');
223     t.tm_sec  = (str[i++] - '0') * 10;
224     t.tm_sec += (str[i++] - '0');
225     
226     if (APR_SUCCESS == apr_time_exp_gmt_get(&ts, &t)) {
227         return ts;
228     }
229     return 0;
230 #else 
231     int secs, days;
232     apr_time_t ts = apr_time_now();
233     
234     if (ASN1_TIME_diff(&days, &secs, NULL, time)) {
235         ts += apr_time_from_sec((days * MD_SECS_PER_DAY) + secs); 
236     }
237     return ts;
238 #endif
239 }
240
241
242 /**************************************************************************************************/
243 /* private keys */
244
245 md_json_t *md_pkey_spec_to_json(const md_pkey_spec_t *spec, apr_pool_t *p)
246 {
247     md_json_t *json = md_json_create(p);
248     if (json) {
249         switch (spec->type) {
250             case MD_PKEY_TYPE_DEFAULT:
251                 md_json_sets("Default", json, MD_KEY_TYPE, NULL);
252                 break;
253             case MD_PKEY_TYPE_RSA:
254                 md_json_sets("RSA", json, MD_KEY_TYPE, NULL);
255                 if (spec->params.rsa.bits >= MD_PKEY_RSA_BITS_MIN) {
256                     md_json_setl((long)spec->params.rsa.bits, json, MD_KEY_BITS, NULL);
257                 }
258                 break;
259             default:
260                 md_json_sets("Unsupported", json, MD_KEY_TYPE, NULL);
261                 break;
262         }
263     }
264     return json;    
265 }
266
267 md_pkey_spec_t *md_pkey_spec_from_json(struct md_json_t *json, apr_pool_t *p)
268 {
269     md_pkey_spec_t *spec = apr_pcalloc(p, sizeof(*spec));
270     const char *s;
271     long l;
272     
273     if (spec) {
274         s = md_json_gets(json, MD_KEY_TYPE, NULL);
275         if (!s || !apr_strnatcasecmp("Default", s)) {
276             spec->type = MD_PKEY_TYPE_DEFAULT;
277         }
278         else if (!apr_strnatcasecmp("RSA", s)) {
279             spec->type = MD_PKEY_TYPE_RSA;
280             l = md_json_getl(json, MD_KEY_BITS, NULL);
281             if (l >= MD_PKEY_RSA_BITS_MIN) {
282                 spec->params.rsa.bits = (unsigned int)l;
283             }
284             else {
285                 spec->params.rsa.bits = MD_PKEY_RSA_BITS_DEF;
286             }
287         }
288     }
289     return spec;
290 }
291
292 int md_pkey_spec_eq(md_pkey_spec_t *spec1, md_pkey_spec_t *spec2)
293 {
294     if (spec1 == spec2) {
295         return 1;
296     }
297     if (spec1 && spec2 && spec1->type == spec2->type) {
298         switch (spec1->type) {
299             case MD_PKEY_TYPE_DEFAULT:
300                 return 1;
301             case MD_PKEY_TYPE_RSA:
302                 if (spec1->params.rsa.bits == spec2->params.rsa.bits) {
303                     return 1;
304                 }
305                 break;
306         }
307     }
308     return 0;
309 }
310
311 static md_pkey_t *make_pkey(apr_pool_t *p) 
312 {
313     md_pkey_t *pkey = apr_pcalloc(p, sizeof(*pkey));
314     pkey->pool = p;
315     return pkey;
316 }
317
318 static apr_status_t pkey_cleanup(void *data)
319 {
320     md_pkey_t *pkey = data;
321     if (pkey->pkey) {
322         EVP_PKEY_free(pkey->pkey);
323         pkey->pkey = NULL;
324     }
325     return APR_SUCCESS;
326 }
327
328 void md_pkey_free(md_pkey_t *pkey)
329 {
330     pkey_cleanup(pkey);
331 }
332
333 void *md_pkey_get_EVP_PKEY(struct md_pkey_t *pkey)
334 {
335     return pkey->pkey;
336 }
337
338 apr_status_t md_pkey_fload(md_pkey_t **ppkey, apr_pool_t *p, 
339                            const char *key, apr_size_t key_len,
340                            const char *fname)
341 {
342     apr_status_t rv = APR_ENOENT;
343     md_pkey_t *pkey;
344     BIO *bf;
345     passwd_ctx ctx;
346     
347     pkey =  make_pkey(p);
348     if (NULL != (bf = BIO_new_file(fname, "r"))) {
349         ctx.pass_phrase = key;
350         ctx.pass_len = (int)key_len;
351         
352         ERR_clear_error();
353         pkey->pkey = PEM_read_bio_PrivateKey(bf, NULL, pem_passwd, &ctx);
354         BIO_free(bf);
355         
356         if (pkey->pkey != NULL) {
357             rv = APR_SUCCESS;
358             apr_pool_cleanup_register(p, pkey, pkey_cleanup, apr_pool_cleanup_null);
359         }
360         else {
361             unsigned long err = ERR_get_error();
362             rv = APR_EINVAL;
363             md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p, 
364                           "error loading pkey %s: %s (pass phrase was %snull)", fname,
365                           ERR_error_string(err, NULL), key? "not " : ""); 
366         }
367     }
368     *ppkey = (APR_SUCCESS == rv)? pkey : NULL;
369     return rv;
370 }
371
372 static apr_status_t pkey_to_buffer(buffer_rec *buffer, md_pkey_t *pkey, apr_pool_t *p,
373                                    const char *pass, apr_size_t pass_len)
374 {
375     BIO *bio = BIO_new(BIO_s_mem());
376     const EVP_CIPHER *cipher = NULL;
377     pem_password_cb *cb = NULL;
378     void *cb_baton = NULL;
379     passwd_ctx ctx;
380     unsigned long err;
381     int i;
382     
383     if (!bio) {
384         return APR_ENOMEM;
385     }
386     if (pass_len > INT_MAX) {
387         return APR_EINVAL;
388     }
389     if (pass && pass_len > 0) {
390         ctx.pass_phrase = pass;
391         ctx.pass_len = (int)pass_len;
392         cb = pem_passwd;
393         cb_baton = &ctx;
394         cipher = EVP_aes_256_cbc();
395         if (!cipher) {
396             return APR_ENOTIMPL;
397         }
398     }
399     
400     ERR_clear_error();
401     if (!PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_baton)) {
402         BIO_free(bio);
403         err = ERR_get_error();
404         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "PEM_write key: %ld %s", 
405                       err, ERR_error_string(err, NULL)); 
406         return APR_EINVAL;
407     }
408
409     i = BIO_pending(bio);
410     if (i > 0) {
411         buffer->data = apr_palloc(p, (apr_size_t)i + 1);
412         i = BIO_read(bio, buffer->data, i);
413         buffer->data[i] = '\0';
414         buffer->len = (apr_size_t)i;
415     }
416     BIO_free(bio);
417     return APR_SUCCESS;
418 }
419
420 apr_status_t md_pkey_fsave(md_pkey_t *pkey, apr_pool_t *p, 
421                            const char *pass_phrase, apr_size_t pass_len,
422                            const char *fname, apr_fileperms_t perms)
423 {
424     buffer_rec buffer;
425     apr_status_t rv;
426     
427     if (APR_SUCCESS == (rv = pkey_to_buffer(&buffer, pkey, p, pass_phrase, pass_len))) {
428         return md_util_freplace(fname, perms, p, fwrite_buffer, &buffer); 
429     }
430     md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "save pkey %s (%s pass phrase, len=%d)",
431                   fname, pass_len > 0? "with" : "without", (int)pass_len); 
432     return rv;
433 }
434
435 static apr_status_t gen_rsa(md_pkey_t **ppkey, apr_pool_t *p, unsigned int bits)
436 {
437     EVP_PKEY_CTX *ctx = NULL;
438     apr_status_t rv;
439     
440     *ppkey = make_pkey(p);
441     ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
442     if (ctx 
443         && EVP_PKEY_keygen_init(ctx) >= 0
444         && EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, (int)bits) >= 0
445         && EVP_PKEY_keygen(ctx, &(*ppkey)->pkey) >= 0) {
446         rv = APR_SUCCESS;
447     }
448     else {
449         md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, 0, p, "error generate pkey RSA %d", bits); 
450         *ppkey = NULL;
451         rv = APR_EGENERAL;
452     }
453     
454     if (ctx != NULL) {
455         EVP_PKEY_CTX_free(ctx);
456     }
457     return rv;
458 }
459
460 apr_status_t md_pkey_gen(md_pkey_t **ppkey, apr_pool_t *p, md_pkey_spec_t *spec)
461 {
462     md_pkey_type_t ptype = spec? spec->type : MD_PKEY_TYPE_DEFAULT;
463     switch (ptype) {
464         case MD_PKEY_TYPE_DEFAULT:
465             return gen_rsa(ppkey, p, MD_PKEY_RSA_BITS_DEF);
466         case MD_PKEY_TYPE_RSA:
467             return gen_rsa(ppkey, p, spec->params.rsa.bits);
468         default:
469             return APR_ENOTIMPL;
470     }
471 }
472
473 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
474
475 #ifndef NID_tlsfeature
476 #define NID_tlsfeature          1020
477 #endif
478
479 static void RSA_get0_key(const RSA *r,
480                          const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
481 {
482     if (n != NULL)
483         *n = r->n;
484     if (e != NULL)
485         *e = r->e;
486     if (d != NULL)
487         *d = r->d;
488 }
489
490 #endif
491
492 static const char *bn64(const BIGNUM *b, apr_pool_t *p) 
493 {
494     if (b) {
495          apr_size_t len = (apr_size_t)BN_num_bytes(b);
496          char *buffer = apr_pcalloc(p, len);
497          if (buffer) {
498             BN_bn2bin(b, (unsigned char *)buffer);
499             return md_util_base64url_encode(buffer, len, p);
500          }
501     }
502     return NULL;
503 }
504
505 const char *md_pkey_get_rsa_e64(md_pkey_t *pkey, apr_pool_t *p)
506 {
507     const BIGNUM *e;
508     RSA *rsa = EVP_PKEY_get1_RSA(pkey->pkey);
509     
510     if (!rsa) {
511         return NULL;
512     }
513     RSA_get0_key(rsa, NULL, &e, NULL);
514     return bn64(e, p);
515 }
516
517 const char *md_pkey_get_rsa_n64(md_pkey_t *pkey, apr_pool_t *p)
518 {
519     const BIGNUM *n;
520     RSA *rsa = EVP_PKEY_get1_RSA(pkey->pkey);
521     
522     if (!rsa) {
523         return NULL;
524     }
525     RSA_get0_key(rsa, &n, NULL, NULL);
526     return bn64(n, p);
527 }
528
529 apr_status_t md_crypt_sign64(const char **psign64, md_pkey_t *pkey, apr_pool_t *p, 
530                              const char *d, size_t dlen)
531 {
532     EVP_MD_CTX *ctx = NULL;
533     char *buffer;
534     unsigned int blen;
535     const char *sign64 = NULL;
536     apr_status_t rv = APR_ENOMEM;
537     
538     buffer = apr_pcalloc(p, (apr_size_t)EVP_PKEY_size(pkey->pkey));
539     if (buffer) {
540         ctx = EVP_MD_CTX_create();
541         if (ctx) {
542             rv = APR_ENOTIMPL;
543             if (EVP_SignInit_ex(ctx, EVP_sha256(), NULL)) {
544                 rv = APR_EGENERAL;
545                 if (EVP_SignUpdate(ctx, d, dlen)) {
546                     if (EVP_SignFinal(ctx, (unsigned char*)buffer, &blen, pkey->pkey)) {
547                         sign64 = md_util_base64url_encode(buffer, blen, p);
548                         if (sign64) {
549                             rv = APR_SUCCESS;
550                         }
551                     }
552                 }
553             }
554         }
555         
556         if (ctx) {
557             EVP_MD_CTX_destroy(ctx);
558         }
559     }
560     
561     if (rv != APR_SUCCESS) {
562         md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p, "signing"); 
563     }
564     
565     *psign64 = sign64;
566     return rv;
567 }
568
569 static apr_status_t sha256_digest(unsigned char **pdigest, size_t *pdigest_len,
570                                   apr_pool_t *p, const char *d, size_t dlen)
571 {
572     EVP_MD_CTX *ctx = NULL;
573     unsigned char *buffer;
574     apr_status_t rv = APR_ENOMEM;
575     unsigned int blen;
576     
577     buffer = apr_pcalloc(p, EVP_MAX_MD_SIZE);
578     if (buffer) {
579         ctx = EVP_MD_CTX_create();
580         if (ctx) {
581             rv = APR_ENOTIMPL;
582             if (EVP_DigestInit_ex(ctx, EVP_sha256(), NULL)) {
583                 rv = APR_EGENERAL;
584                 if (EVP_DigestUpdate(ctx, d, dlen)) {
585                     if (EVP_DigestFinal(ctx, buffer, &blen)) {
586                         rv = APR_SUCCESS;
587                     }
588                 }
589             }
590         }
591         
592         if (ctx) {
593             EVP_MD_CTX_destroy(ctx);
594         }
595     }
596     
597     if (APR_SUCCESS == rv) {
598         *pdigest = buffer;
599         *pdigest_len = blen;
600     }
601     else {
602         md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p, "digest"); 
603         *pdigest = NULL;
604         *pdigest_len = 0;
605     }
606     return rv;
607 }
608
609 apr_status_t md_crypt_sha256_digest64(const char **pdigest64, apr_pool_t *p, 
610                                       const char *d, size_t dlen)
611 {
612     const char *digest64 = NULL;
613     unsigned char *buffer;
614     size_t blen;
615     apr_status_t rv;
616     
617     if (APR_SUCCESS == (rv = sha256_digest(&buffer, &blen, p, d, dlen))) {
618         if (NULL == (digest64 = md_util_base64url_encode((const char*)buffer, blen, p))) {
619             rv = APR_EGENERAL;
620         }
621     }
622     *pdigest64 = digest64;
623     return rv;
624 }
625
626 static const char * const hex_const[] = {
627     "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", 
628     "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", 
629     "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", 
630     "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", 
631     "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", 
632     "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", 
633     "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", 
634     "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", 
635     "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", 
636     "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", 
637     "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", 
638     "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", 
639     "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", 
640     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", 
641     "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", 
642     "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff", 
643 };
644
645 apr_status_t md_crypt_sha256_digest_hex(const char **pdigesthex, apr_pool_t *p, 
646                                         const char *d, size_t dlen)
647 {
648     char *dhex = NULL, *cp;
649     const char * x;
650     unsigned char *buffer;
651     size_t blen;
652     apr_status_t rv;
653     unsigned int i;
654     
655     if (APR_SUCCESS == (rv = sha256_digest(&buffer, &blen, p, d, dlen))) {
656         cp = dhex = apr_pcalloc(p,  2 * blen + 1);
657         if (!dhex) {
658             rv = APR_EGENERAL;
659         }
660         for (i = 0; i < blen; ++i, cp += 2) {
661             x = hex_const[buffer[i]];
662             cp[0] = x[0];
663             cp[1] = x[1];
664         }
665     }
666     *pdigesthex = dhex;
667     return rv;
668 }
669
670 /**************************************************************************************************/
671 /* certificates */
672
673 struct md_cert_t {
674     apr_pool_t *pool;
675     X509 *x509;
676     apr_array_header_t *alt_names;
677 };
678
679 static apr_status_t cert_cleanup(void *data)
680 {
681     md_cert_t *cert = data;
682     if (cert->x509) {
683         X509_free(cert->x509);
684         cert->x509 = NULL;
685     }
686     return APR_SUCCESS;
687 }
688
689 static md_cert_t *make_cert(apr_pool_t *p, X509 *x509) 
690 {
691     md_cert_t *cert = apr_pcalloc(p, sizeof(*cert));
692     cert->pool = p;
693     cert->x509 = x509;
694     apr_pool_cleanup_register(p, cert, cert_cleanup, apr_pool_cleanup_null);
695     
696     return cert;
697 }
698
699 void md_cert_free(md_cert_t *cert)
700 {
701     cert_cleanup(cert);
702 }
703
704 void *md_cert_get_X509(struct md_cert_t *cert)
705 {
706     return cert->x509;
707 }
708
709 int md_cert_is_valid_now(const md_cert_t *cert)
710 {
711     return ((X509_cmp_current_time(X509_get_notBefore(cert->x509)) < 0)
712             && (X509_cmp_current_time(X509_get_notAfter(cert->x509)) > 0));
713 }
714
715 int md_cert_has_expired(const md_cert_t *cert)
716 {
717     return (X509_cmp_current_time(X509_get_notAfter(cert->x509)) <= 0);
718 }
719
720 apr_time_t md_cert_get_not_after(md_cert_t *cert)
721 {
722     return md_asn1_time_get(X509_get_notAfter(cert->x509));
723 }
724
725 apr_time_t md_cert_get_not_before(md_cert_t *cert)
726 {
727     return md_asn1_time_get(X509_get_notBefore(cert->x509));
728 }
729
730 int md_cert_covers_domain(md_cert_t *cert, const char *domain_name)
731 {
732     if (!cert->alt_names) {
733         md_cert_get_alt_names(&cert->alt_names, cert, cert->pool);
734     }
735     if (cert->alt_names) {
736         return md_array_str_index(cert->alt_names, domain_name, 0, 0) >= 0;
737     }
738     return 0;
739 }
740
741 int md_cert_covers_md(md_cert_t *cert, const md_t *md)
742 {
743     const char *name;
744     int i;
745     
746     if (!cert->alt_names) {
747         md_cert_get_alt_names(&cert->alt_names, cert, cert->pool);
748     }
749     if (cert->alt_names) {
750         md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, cert->pool, "cert has %d alt names",
751                       cert->alt_names->nelts); 
752         for (i = 0; i < md->domains->nelts; ++i) {
753             name = APR_ARRAY_IDX(md->domains, i, const char *);
754             if (md_array_str_index(cert->alt_names, name, 0, 0) < 0) {
755                 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, cert->pool, 
756                               "md domain %s not covered by cert", name);
757                 return 0;
758             }
759         }
760         return 1;
761     }
762     else {
763         md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, 0, cert->pool, "cert has NO alt names");
764     }
765     return 0;
766 }
767
768 apr_status_t md_cert_get_issuers_uri(const char **puri, md_cert_t *cert, apr_pool_t *p)
769 {
770     int i, ext_idx, nid = NID_info_access;
771     X509_EXTENSION *ext;
772     X509V3_EXT_METHOD *ext_cls;
773     void *ext_data;
774     const char *uri = NULL;
775     apr_status_t rv = APR_ENOENT;
776     
777     /* Waddle through x509  API history to get someone that may be able
778      * to hand us the issuer url for the cert chain */
779     ext_idx = X509_get_ext_by_NID(cert->x509, nid, -1);
780     ext = (ext_idx >= 0)? X509_get_ext(cert->x509, ext_idx) : NULL;
781     ext_cls = ext? (X509V3_EXT_METHOD*)X509V3_EXT_get(ext) : NULL;
782     if (ext_cls && (ext_data = X509_get_ext_d2i(cert->x509, nid, 0, 0))) {
783         CONF_VALUE *cval;
784         STACK_OF(CONF_VALUE) *ext_vals = ext_cls->i2v(ext_cls, ext_data, 0);
785         
786         for (i = 0; i < sk_CONF_VALUE_num(ext_vals); ++i) {
787             cval = sk_CONF_VALUE_value(ext_vals, i);
788             if (!strcmp("CA Issuers - URI", cval->name)) {
789                 uri = apr_pstrdup(p, cval->value);
790                 rv = APR_SUCCESS;
791                 break;
792             }
793         }
794     } 
795     *puri = (APR_SUCCESS == rv)? uri : NULL;
796     return rv;
797 }
798
799 apr_status_t md_cert_get_alt_names(apr_array_header_t **pnames, md_cert_t *cert, apr_pool_t *p)
800 {
801     apr_array_header_t *names;
802     apr_status_t rv = APR_ENOENT;
803     STACK_OF(GENERAL_NAME) *xalt_names;
804     unsigned char *buf;
805     int i;
806     
807     xalt_names = (GENERAL_NAMES*)X509_get_ext_d2i(cert->x509, NID_subject_alt_name, NULL, NULL);
808     if (xalt_names) {
809         GENERAL_NAME *cval;
810         
811         names = apr_array_make(p, sk_GENERAL_NAME_num(xalt_names), sizeof(char *));
812         for (i = 0; i < sk_GENERAL_NAME_num(xalt_names); ++i) {
813             cval = sk_GENERAL_NAME_value(xalt_names, i);
814             switch (cval->type) {
815                 case GEN_DNS:
816                 case GEN_URI:
817                 case GEN_IPADD:
818                     ASN1_STRING_to_UTF8(&buf, cval->d.ia5);
819                     APR_ARRAY_PUSH(names, const char *) = apr_pstrdup(p, (char*)buf);
820                     OPENSSL_free(buf);
821                     break;
822                 default:
823                     break;
824             }
825         }
826         rv = APR_SUCCESS;
827     }
828     *pnames = (APR_SUCCESS == rv)? names : NULL;
829     return rv;
830 }
831
832 apr_status_t md_cert_fload(md_cert_t **pcert, apr_pool_t *p, const char *fname)
833 {
834     FILE *f;
835     apr_status_t rv;
836     md_cert_t *cert;
837     X509 *x509;
838     
839     rv = md_util_fopen(&f, fname, "r");
840     if (rv == APR_SUCCESS) {
841     
842         x509 = PEM_read_X509(f, NULL, NULL, NULL);
843         rv = fclose(f);
844         if (x509 != NULL) {
845             cert =  make_cert(p, x509);
846         }
847         else {
848             rv = APR_EINVAL;
849         }
850     }
851
852     *pcert = (APR_SUCCESS == rv)? cert : NULL;
853     return rv;
854 }
855
856 static apr_status_t cert_to_buffer(buffer_rec *buffer, md_cert_t *cert, apr_pool_t *p)
857 {
858     BIO *bio = BIO_new(BIO_s_mem());
859     int i;
860     
861     if (!bio) {
862         return APR_ENOMEM;
863     }
864
865     ERR_clear_error();
866     PEM_write_bio_X509(bio, cert->x509);
867     if (ERR_get_error() > 0) {
868         BIO_free(bio);
869         return APR_EINVAL;
870     }
871
872     i = BIO_pending(bio);
873     if (i > 0) {
874         buffer->data = apr_palloc(p, (apr_size_t)i + 1);
875         i = BIO_read(bio, buffer->data, i);
876         buffer->data[i] = '\0';
877         buffer->len = (apr_size_t)i;
878     }
879     BIO_free(bio);
880     return APR_SUCCESS;
881 }
882
883 apr_status_t md_cert_fsave(md_cert_t *cert, apr_pool_t *p, 
884                            const char *fname, apr_fileperms_t perms)
885 {
886     buffer_rec buffer;
887     apr_status_t rv;
888     
889     if (APR_SUCCESS == (rv = cert_to_buffer(&buffer, cert, p))) {
890         return md_util_freplace(fname, perms, p, fwrite_buffer, &buffer); 
891     }
892     return rv;
893 }
894
895 apr_status_t md_cert_to_base64url(const char **ps64, md_cert_t *cert, apr_pool_t *p)
896 {
897     buffer_rec buffer;
898     apr_status_t rv;
899     
900     if (APR_SUCCESS == (rv = cert_to_buffer(&buffer, cert, p))) {
901         *ps64 = md_util_base64url_encode(buffer.data, buffer.len, p);
902         return APR_SUCCESS;
903     }
904     *ps64 = NULL;
905     return rv;
906 }
907
908 apr_status_t md_cert_read_http(md_cert_t **pcert, apr_pool_t *p, 
909                                const md_http_response_t *res)
910 {
911     const char *ct;
912     apr_off_t data_len;
913     apr_size_t der_len;
914     apr_status_t rv;
915     
916     ct = apr_table_get(res->headers, "Content-Type");
917     if (!res->body || !ct  || strcmp("application/pkix-cert", ct)) {
918         return APR_ENOENT;
919     }
920     
921     if (APR_SUCCESS == (rv = apr_brigade_length(res->body, 1, &data_len))) {
922         char *der;
923         if (data_len > 1024*1024) { /* certs usually are <2k each */
924             return APR_EINVAL;
925         }
926         if (APR_SUCCESS == (rv = apr_brigade_pflatten(res->body, &der, &der_len, p))) {
927             const unsigned char *bf = (const unsigned char*)der;
928             X509 *x509;
929             
930             if (NULL == (x509 = d2i_X509(NULL, &bf, (long)der_len))) {
931                 rv = APR_EINVAL;
932             }
933             else {
934                 *pcert = make_cert(p, x509);
935                 rv = APR_SUCCESS;
936             }
937         }
938         md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p, "cert parsed");
939     }
940     return rv;
941 }
942
943 md_cert_state_t md_cert_state_get(md_cert_t *cert)
944 {
945     if (cert->x509) {
946         return md_cert_is_valid_now(cert)? MD_CERT_VALID : MD_CERT_EXPIRED;
947     }
948     return MD_CERT_UNKNOWN;
949 }
950
951 apr_status_t md_chain_fappend(struct apr_array_header_t *certs, apr_pool_t *p, const char *fname)
952 {
953     FILE *f;
954     apr_status_t rv;
955     X509 *x509;
956     md_cert_t *cert;
957     unsigned long err;
958     
959     rv = md_util_fopen(&f, fname, "r");
960     if (rv == APR_SUCCESS) {
961         ERR_clear_error();
962         while (NULL != (x509 = PEM_read_X509(f, NULL, NULL, NULL))) {
963             cert = make_cert(p, x509);
964             APR_ARRAY_PUSH(certs, md_cert_t *) = cert;
965         }
966         fclose(f);
967         
968         if (0 < (err =  ERR_get_error())
969             && !(ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
970             /* not the expected one when no more PEM encodings are found */
971             rv = APR_EINVAL;
972             goto out;
973         }
974         
975         if (certs->nelts == 0) {
976             /* Did not find any. This is acceptable unless the file has a certain size
977              * when we no longer accept it as empty chain file. Something seems to be
978              * wrong then. */
979             apr_finfo_t info;
980             if (APR_SUCCESS == apr_stat(&info, fname, APR_FINFO_SIZE, p) && info.size >= 1024) {
981                 /* "Too big for a moon." */
982                 rv = APR_EINVAL;
983                 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, 
984                               "no certificates in non-empty chain %s", fname);
985                 goto out;
986             }
987         }        
988     }
989 out:
990     md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p, "read chain file %s, found %d certs", 
991                   fname, certs? certs->nelts : 0);
992     return rv;
993 }
994
995 apr_status_t md_chain_fload(apr_array_header_t **pcerts, apr_pool_t *p, const char *fname)
996 {
997     apr_array_header_t *certs;
998     apr_status_t rv;
999
1000     certs = apr_array_make(p, 5, sizeof(md_cert_t *));
1001     rv = md_chain_fappend(certs, p, fname);
1002     *pcerts = (APR_SUCCESS == rv)? certs : NULL;
1003     return rv;
1004 }
1005
1006 apr_status_t md_chain_fsave(apr_array_header_t *certs, apr_pool_t *p, 
1007                             const char *fname, apr_fileperms_t perms)
1008 {
1009     FILE *f;
1010     apr_status_t rv;
1011     const md_cert_t *cert;
1012     unsigned long err = 0;
1013     int i;
1014     
1015     (void)p;
1016     rv = md_util_fopen(&f, fname, "w");
1017     if (rv == APR_SUCCESS) {
1018         apr_file_perms_set(fname, perms);
1019         ERR_clear_error();
1020         for (i = 0; i < certs->nelts; ++i) {
1021             cert = APR_ARRAY_IDX(certs, i, const md_cert_t *);
1022             assert(cert->x509);
1023             
1024             PEM_write_X509(f, cert->x509);
1025             
1026             if (0 < (err = ERR_get_error())) {
1027                 break;
1028             }
1029             
1030         }
1031         rv = fclose(f);
1032         if (err) {
1033             rv = APR_EINVAL;
1034         }
1035     }
1036     return rv;
1037 }
1038
1039 /**************************************************************************************************/
1040 /* certificate signing requests */
1041
1042 static const char *alt_names(apr_array_header_t *domains, apr_pool_t *p)
1043 {
1044     const char *alts = "", *sep = "", *domain;
1045     int i;
1046     
1047     for (i = 0; i < domains->nelts; ++i) {
1048         domain = APR_ARRAY_IDX(domains, i, const char *);
1049         alts = apr_psprintf(p, "%s%sDNS:%s", alts, sep, domain);
1050         sep = ",";
1051     }
1052     return alts;
1053 }
1054
1055 static apr_status_t add_ext(X509 *x, int nid, const char *value, apr_pool_t *p)
1056 {
1057     X509_EXTENSION *ext = NULL;
1058     X509V3_CTX ctx;
1059     apr_status_t rv;
1060
1061     X509V3_set_ctx_nodb(&ctx);
1062     X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
1063     if (NULL == (ext = X509V3_EXT_conf_nid(NULL, &ctx, nid, (char*)value))) {
1064         return APR_EGENERAL;
1065     }
1066     
1067     ERR_clear_error();
1068     rv = X509_add_ext(x, ext, -1)? APR_SUCCESS : APR_EINVAL;
1069     if (APR_SUCCESS != rv) {
1070         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "add_ext nid=%dd value='%s'", 
1071                       nid, value); 
1072         
1073     }
1074     X509_EXTENSION_free(ext);
1075     return rv;
1076 }
1077
1078 static apr_status_t sk_add_alt_names(STACK_OF(X509_EXTENSION) *exts,
1079                                      apr_array_header_t *domains, apr_pool_t *p)
1080 {
1081     if (domains->nelts > 0) {
1082         X509_EXTENSION *x;
1083         
1084         x = X509V3_EXT_conf_nid(NULL, NULL, NID_subject_alt_name, (char*)alt_names(domains, p));
1085         if (NULL == x) {
1086             return APR_EGENERAL;
1087         }
1088         sk_X509_EXTENSION_push(exts, x);
1089     }
1090     return APR_SUCCESS;
1091 }
1092
1093 static apr_status_t add_must_staple(STACK_OF(X509_EXTENSION) *exts, const md_t *md, apr_pool_t *p)
1094 {
1095     
1096     if (md->must_staple) {
1097         X509_EXTENSION *x;
1098         int nid;
1099         
1100         nid = OBJ_create("1.3.6.1.5.5.7.1.24", "OCSPReq", "OCSP Request");
1101         if (NID_undef == nid) {
1102             md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, 
1103                           "%s: unable to get NID for must-staple", md->name);
1104             return APR_EGENERAL;
1105         }
1106         x = X509V3_EXT_conf_nid(NULL, NULL, nid, (char*)"DER:30:03:02:01:05");
1107         if (NULL == x) {
1108             md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, 
1109                           "%s: unable to get x509 extension for must-staple", md->name);
1110             return APR_EGENERAL;
1111         }
1112         sk_X509_EXTENSION_push(exts, x);
1113     }
1114     return APR_SUCCESS;
1115 }
1116
1117 apr_status_t md_cert_req_create(const char **pcsr_der_64, const md_t *md, 
1118                                 md_pkey_t *pkey, apr_pool_t *p)
1119 {
1120     const char *s, *csr_der, *csr_der_64 = NULL;
1121     const unsigned char *domain;
1122     X509_REQ *csr;
1123     X509_NAME *n = NULL;
1124     STACK_OF(X509_EXTENSION) *exts = NULL;
1125     apr_status_t rv;
1126     int csr_der_len;
1127     
1128     assert(md->domains->nelts > 0);
1129     
1130     if (NULL == (csr = X509_REQ_new()) 
1131         || NULL == (exts = sk_X509_EXTENSION_new_null())
1132         || NULL == (n = X509_NAME_new())) {
1133         rv = APR_ENOMEM;
1134         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: openssl alloc X509 things", md->name);
1135         goto out; 
1136     }
1137
1138     /* subject name == first domain */
1139     domain = APR_ARRAY_IDX(md->domains, 0, const unsigned char *);
1140     if (!X509_NAME_add_entry_by_txt(n, "CN", MBSTRING_ASC, domain, -1, -1, 0)
1141         || !X509_REQ_set_subject_name(csr, n)) {
1142         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "%s: REQ name add entry", md->name);
1143         rv = APR_EGENERAL; goto out;
1144     }
1145     /* collect extensions, such as alt names and must staple */
1146     if (APR_SUCCESS != (rv = sk_add_alt_names(exts, md->domains, p))) {
1147         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: collecting alt names", md->name);
1148         rv = APR_EGENERAL; goto out;
1149     }
1150     if (APR_SUCCESS != (rv = add_must_staple(exts, md, p))) {
1151         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: must staple", md->name);
1152         rv = APR_EGENERAL; goto out;
1153     }
1154     /* add extensions to csr */
1155     if (sk_X509_EXTENSION_num(exts) > 0 && !X509_REQ_add_extensions(csr, exts)) {
1156         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: adding exts", md->name);
1157         rv = APR_EGENERAL; goto out;
1158     }
1159     /* add our key */
1160     if (!X509_REQ_set_pubkey(csr, pkey->pkey)) {
1161         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: set pkey in csr", md->name);
1162         rv = APR_EGENERAL; goto out;
1163     }
1164     /* sign, der encode and base64url encode */
1165     if (!X509_REQ_sign(csr, pkey->pkey, EVP_sha256())) {
1166         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: sign csr", md->name);
1167         rv = APR_EGENERAL; goto out;
1168     }
1169     if ((csr_der_len = i2d_X509_REQ(csr, NULL)) < 0) {
1170         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: der length", md->name);
1171         rv = APR_EGENERAL; goto out;
1172     }
1173     s = csr_der = apr_pcalloc(p, (apr_size_t)csr_der_len + 1);
1174     if (i2d_X509_REQ(csr, (unsigned char**)&s) != csr_der_len) {
1175         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: csr der enc", md->name);
1176         rv = APR_EGENERAL; goto out;
1177     }
1178     csr_der_64 = md_util_base64url_encode(csr_der, (apr_size_t)csr_der_len, p);
1179     rv = APR_SUCCESS;
1180     
1181 out:
1182     if (exts) {
1183         sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
1184     }
1185     if (csr) {
1186         X509_REQ_free(csr);
1187     }
1188     if (n) {
1189         X509_NAME_free(n);
1190     }
1191     *pcsr_der_64 = (APR_SUCCESS == rv)? csr_der_64 : NULL;
1192     return rv;
1193 }
1194
1195 apr_status_t md_cert_self_sign(md_cert_t **pcert, const char *cn, 
1196                                apr_array_header_t *domains, md_pkey_t *pkey,
1197                                apr_interval_time_t valid_for, apr_pool_t *p)
1198 {
1199     X509 *x;
1200     X509_NAME *n = NULL;
1201     md_cert_t *cert = NULL;
1202     apr_status_t rv;
1203     int days;
1204     BIGNUM *big_rnd = NULL;
1205     ASN1_INTEGER *asn1_rnd = NULL;
1206     unsigned char rnd[20];
1207     
1208     assert(domains);
1209     
1210     if (NULL == (x = X509_new()) 
1211         || NULL == (n = X509_NAME_new())) {
1212         rv = APR_ENOMEM;
1213         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "%s: openssl alloc X509 things", cn);
1214         goto out; 
1215     }
1216     
1217     if (APR_SUCCESS != (rv = md_rand_bytes(rnd, sizeof(rnd), p))
1218         || !(big_rnd = BN_bin2bn(rnd, sizeof(rnd), NULL))
1219         || !(asn1_rnd = BN_to_ASN1_INTEGER(big_rnd, NULL))) {
1220         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "%s: setup random serial", cn);
1221         rv = APR_EGENERAL; goto out;
1222     }
1223      
1224     if (1 != X509_set_version(x, 2L)) {
1225         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "%s: setting x.509v3", cn);
1226         rv = APR_EGENERAL; goto out;
1227     }
1228
1229     if (!X509_set_serialNumber(x, asn1_rnd)) {
1230         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "%s: set serial number", cn);
1231         rv = APR_EGENERAL; goto out;
1232     }
1233     /* set common name and issue */
1234     if (!X509_NAME_add_entry_by_txt(n, "CN", MBSTRING_ASC, (const unsigned char*)cn, -1, -1, 0)
1235         || !X509_set_subject_name(x, n)
1236         || !X509_set_issuer_name(x, n)) {
1237         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "%s: name add entry", cn);
1238         rv = APR_EGENERAL; goto out;
1239     }
1240     /* cert are uncontrained (but not very trustworthy) */
1241     if (APR_SUCCESS != (rv = add_ext(x, NID_basic_constraints, "CA:FALSE, pathlen:0", p))) {
1242         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: set basic constraints ext", cn);
1243         goto out;
1244     }
1245     /* add the domain as alt name */
1246     if (APR_SUCCESS != (rv = add_ext(x, NID_subject_alt_name, alt_names(domains, p), p))) {
1247         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: set alt_name ext", cn);
1248         goto out;
1249     }
1250     /* add our key */
1251     if (!X509_set_pubkey(x, pkey->pkey)) {
1252         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: set pkey in x509", cn);
1253         rv = APR_EGENERAL; goto out;
1254     }
1255     
1256     days = (int)((apr_time_sec(valid_for) + MD_SECS_PER_DAY - 1)/ MD_SECS_PER_DAY);
1257     if (!X509_set_notBefore(x, ASN1_TIME_set(NULL, time(NULL)))) {
1258         rv = APR_EGENERAL; goto out;
1259     }
1260     if (!X509_set_notAfter(x, ASN1_TIME_adj(NULL, time(NULL), days, 0))) {
1261         rv = APR_EGENERAL; goto out;
1262     }
1263
1264     /* sign with same key */
1265     if (!X509_sign(x, pkey->pkey, EVP_sha256())) {
1266         md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: sign x509", cn);
1267         rv = APR_EGENERAL; goto out;
1268     }
1269
1270     cert = make_cert(p, x);
1271     rv = APR_SUCCESS;
1272     
1273 out:
1274     if (!cert && x) {
1275         X509_free(x);
1276     }
1277     if (n) {
1278         X509_NAME_free(n);
1279     }
1280     if (big_rnd) {
1281         BN_free(big_rnd);
1282     }
1283     if (asn1_rnd) {
1284         ASN1_INTEGER_free(asn1_rnd);
1285     }
1286     *pcert = (APR_SUCCESS == rv)? cert : NULL;
1287     return rv;
1288 }
1289