File Coverage

SignCSR.xs
Criterion Covered Total %
statement 204 292 69.8
branch 102 228 44.7
condition n/a
subroutine n/a
pod n/a
total 306 520 58.8


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5              
6             #include
7             #include
8              
9             #include "ppport.h"
10              
11             #include
12             #include
13             #include
14             #include
15             #include
16             #include
17             #include
18             #include
19             #include
20             #include
21             #include
22             #include
23             #include
24              
25             # define OPT_FMT_PEM (1L << 1)
26             # define CHECK_OPEN_SSL(p_result) if (!(p_result)) croakSsl(__FILE__, __LINE__);
27             # define EXT_COPY_NONE 0
28             # define EXT_COPY_ADD 1
29             # define EXT_COPY_ALL 2
30             # define EXT_COPY_UNSET -1
31             # define SERIAL_RAND_BITS 159
32              
33             BIO *bio_err;
34             #if OPENSSL_API_COMPAT >= 30000
35             OSSL_LIB_CTX *libctx = NULL;
36             static const char *propq = NULL;
37             #endif
38             static unsigned long nmflag = 0;
39             static char nmflag_set = 0;
40              
41             // Taken from p5-Git-Raw
42 2           STATIC HV *ensure_hv(SV *sv, const char *identifier) {
43 2 50         if (!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVHV)
    50          
44 0           croak("Invalid type for '%s', expected a hash", identifier);
45              
46 2           return (HV *) SvRV(sv);
47             }
48              
49 2           int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
50             {
51             BIGNUM *btmp;
52 2           int ret = 0;
53              
54 2 50         btmp = b == NULL ? BN_new() : b;
55 2 50         if (btmp == NULL)
56 0           return 0;
57              
58             #if OPENSSL_API_COMPAT <= 10100
59 2 50         if (!BN_rand(btmp, SERIAL_RAND_BITS, 0, 0))
60             #else
61             if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
62             #endif
63 0           goto error;
64 2 50         if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
    50          
65 0           goto error;
66              
67 2           ret = 1;
68              
69             error:
70              
71 2 50         if (btmp != b)
72 2           BN_free(btmp);
73              
74 2           return ret;
75             }
76              
77 2           int set_cert_times(X509 *x, const char *startdate, const char *enddate,
78             int days)
79             {
80 2 50         if (startdate == NULL || strcmp(startdate, "today") == 0) {
    0          
81             #if OPENSSL_API_COMPAT <= 10100
82 2 50         if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
83             #else
84             if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL)
85             #endif
86 0           return 0;
87             } else {
88             #if OPENSSL_API_COMPAT <= 10101
89 0 0         if (!ASN1_TIME_set_string(X509_get_notBefore(x), startdate))
90             #else
91             if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate))
92             #endif
93 0           return 0;
94             }
95 2 50         if (enddate == NULL) {
96             #if OPENSSL_API_COMPAT <= 10100
97 2 50         if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL)
98             #else
99             if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL)
100             #endif
101             == NULL)
102 0           return 0;
103             #if OPENSSL_API_COMPAT < 10101
104 0 0         } else if (!ASN1_TIME_set_string(X509_get_notAfter(x), enddate)) {
105             #else
106             } else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) {
107             #endif
108 0           return 0;
109             }
110 2           return 1;
111             }
112              
113 2           int copy_extensions(X509 *x, X509_REQ *req, int copy_type)
114             {
115             STACK_OF(X509_EXTENSION) *exts;
116 2           int i, ret = 0;
117              
118 2 50         if (x == NULL || req == NULL)
    50          
119 0           return 0;
120 2 50         if (copy_type == EXT_COPY_NONE)
121 0           return 1;
122 2           exts = X509_REQ_get_extensions(req);
123              
124 9 100         for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
125 7           X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
126 7           ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext);
127 7           int idx = X509_get_ext_by_OBJ(x, obj, -1);
128              
129             /* Does extension exist in target? */
130 7 50         if (idx != -1) {
131             /* If normal copy don't override existing extension */
132 0 0         if (copy_type == EXT_COPY_ADD)
133 0           continue;
134             /* Delete all extensions of same type */
135             do {
136 0           X509_EXTENSION_free(X509_delete_ext(x, idx));
137 0           idx = X509_get_ext_by_OBJ(x, obj, -1);
138 0 0         } while (idx != -1);
139             }
140 7 50         if (!X509_add_ext(x, ext, -1))
141 0           goto end;
142             }
143 2           ret = 1;
144              
145             end:
146 2           sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
147 2           return ret;
148             }
149              
150 2           int cert_matches_key(const X509 *cert, const EVP_PKEY *pkey)
151             {
152             int match;
153              
154 2           ERR_set_mark();
155 2           match = X509_check_private_key((X509 *) cert, (EVP_PKEY *) pkey);
156 2           ERR_pop_to_mark();
157 2           return match;
158             }
159              
160 2           static int do_x509_req_init(X509_REQ *x, STACK_OF(OPENSSL_STRING) *opts)
161             {
162             //int i;
163              
164 2           opts = NULL;
165 2 50         if (opts == NULL)
166 2           return 1;
167              
168             //for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
169             // char *opt = sk_OPENSSL_STRING_value(opts, i);
170              
171             // if (x509_req_ctrl_string(x, opt) <= 0) {
172             // croak("parameter error "); //$, n", opt);
173             // ERR_print_errors(bio_err);
174             // return 0;
175             // }
176             //}
177              
178 0           return 1;
179             }
180              
181             /*
182             * do_X509_REQ_verify returns 1 if the signature is valid,
183             * 0 if the signature check fails, or -1 if error occurs.
184             */
185 2           int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts)
186             {
187 2           int rv = 0;
188              
189 2 50         if (do_x509_req_init(x, vfyopts) > 0){
190             #if OPENSSL_API_COMPAT >= 30000
191             rv = X509_REQ_verify_ex(x, pkey, libctx, propq);
192             #else
193 2           rv = X509_REQ_verify(x, pkey);
194             #endif
195             }
196             else
197 0           rv = -1;
198 2           return rv;
199             }
200              
201 0           void croakSsl(char* p_file, int p_line)
202             {
203             const char* errorReason;
204             /* Just return the top error on the stack */
205 0           errorReason = ERR_reason_error_string(ERR_get_error());
206 0           ERR_clear_error();
207 0           croak("%s:%d: OpenSSL error: %s", p_file, p_line, errorReason);
208             }
209              
210 2           SV* extractBioString(pTHX_ BIO* p_stringBio)
211             {
212             SV* sv;
213             BUF_MEM* bptr;
214              
215 2 50         CHECK_OPEN_SSL(BIO_flush(p_stringBio) == 1);
216 2           BIO_get_mem_ptr(p_stringBio, &bptr);
217 2           sv = newSVpv(bptr->data, bptr->length);
218              
219 2 50         CHECK_OPEN_SSL(BIO_set_close(p_stringBio, BIO_CLOSE) == 1);
220 2           BIO_free(p_stringBio);
221 2           return sv;
222             }
223              
224 0           int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value)
225             {
226 0           int rv = 0;
227 0           char *stmp, *vtmp = NULL;
228              
229 0           stmp = OPENSSL_strdup(value);
230 0 0         if (stmp == NULL)
231 0           return -1;
232 0           vtmp = strchr(stmp, ':');
233 0 0         if (vtmp == NULL)
234 0           goto err;
235              
236 0           *vtmp = 0;
237 0           vtmp++;
238 0           rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp);
239              
240             err:
241 0           OPENSSL_free(stmp);
242 0           return rv;
243             }
244              
245 2           static int do_pkey_ctx_init(EVP_PKEY_CTX *pkctx, STACK_OF(OPENSSL_STRING) *opts)
246             {
247             int i;
248              
249 2 50         if (opts == NULL)
250 2           return 1;
251              
252 0 0         for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
253 0           char *opt = sk_OPENSSL_STRING_value(opts, i);
254              
255 0 0         if (pkey_ctrl_string(pkctx, opt) <= 0) {
256 0           BIO_printf(bio_err, "parameter error \"%s\"\n", opt);
257 0           ERR_print_errors(bio_err);
258 0           return 0;
259             }
260             }
261              
262 0           return 1;
263             }
264              
265 0           unsigned long get_nameopt(void)
266             {
267             return
268 0 0         nmflag_set ? nmflag : XN_FLAG_SEP_CPLUS_SPC | ASN1_STRFLGS_UTF8_CONVERT;
269             }
270              
271             #if OPENSSL_API_COMPAT >= 30101
272             static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, const char *md, STACK_OF(OPENSSL_STRING) *sigopts)
273             #else
274 2           static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts)
275             #endif
276             {
277 2           EVP_PKEY_CTX *pkctx = NULL;
278             #if OPENSSL_API_COMPAT >= 30101
279             char def_md[80];
280             #else
281             int def_nid;
282             #endif
283              
284 2 50         if (ctx == NULL)
285 0           return 0;
286             /*
287             * EVP_PKEY_get_default_digest_name() returns 2 if the digest is mandatory
288             * for this algorithm.
289             */
290             #if OPENSSL_API_COMPAT >= 30101
291             if (EVP_PKEY_get_default_digest_name(pkey, def_md, sizeof(def_md)) == 2
292             && strcmp(def_md, "UNDEF") == 0) {
293             #else
294 2 50         if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) == 2
295 0 0         && def_nid == NID_undef) {
296             #endif
297             /* The signing algorithm requires there to be no digest */
298 0           md = NULL;
299             }
300              
301             #if OPENSSL_API_COMPAT >= 30101
302             int val = EVP_DigestSignInit_ex(ctx, &pkctx, md, libctx,
303             propq, pkey, NULL);
304             #else
305 2           int val = EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey);
306             #endif
307 2           return val
308 2 50         && do_pkey_ctx_init(pkctx, sigopts);
    50          
309             }
310              
311 2           static int key_destroy(pTHX_ SV* var, MAGIC* magic) {
312             EVP_PKEY * key;
313              
314 2           key = (EVP_PKEY *) magic->mg_ptr;
315 2 50         if (!key)
316 0           return 0;
317              
318 2           EVP_PKEY_free(key);
319 2           return 1;
320             }
321              
322             static const MGVTBL key_magic = { NULL, NULL, NULL, NULL, key_destroy };
323              
324              
325             MODULE = Crypt::OpenSSL::SignCSR PACKAGE = Crypt::OpenSSL::SignCSR PREFIX = signcsr_
326              
327             BOOT:
328 3           ERR_load_crypto_strings();
329             #if OPENSSL_API_COMPAT <= 10100
330 3           ERR_load_ERR_strings();
331 3           OpenSSL_add_all_algorithms();
332 3           OpenSSL_add_all_ciphers();
333 3           OpenSSL_add_all_digests();
334             #endif
335              
336             PROTOTYPES: DISABLE
337              
338             SV * new(class, ...)
339             const char * class
340              
341             PREINIT:
342 2           SV * private_key = NULL;
343 2           HV * options = newHV();
344              
345             CODE:
346             STRLEN keyStringLength;
347             char* keyString;
348             BIO *bio;
349 2           SV * key = newSV(0);
350             SV **svp; // Temporary storage of options
351 2           SV *digest = NULL;
352 2           SV *format = newSVpv("pem", 3);
353 2           IV days = 365;
354              
355 2 50         if (items > 1) {
356 2 50         if (ST(1) != NULL) {
357             // TODO: ensure_string_sv
358 2           private_key = ST(1);
359 2 50         if (strlen(SvPV_nolen(private_key)) == 0) {
    50          
360 0           private_key = NULL;
361             }
362             }
363              
364 2 50         if (items > 2)
365 2           options = ensure_hv(ST(2), "options");
366             }
367              
368             // Get the number of days for specified - default 365
369 2 50         if (hv_exists(options, "days", strlen("days"))) {
370 2           svp = hv_fetch(options, "days", strlen("days"), 0);
371 2 50         if (SvIOKp(*svp)) {
372 2 50         days = SvIV(*svp);
373             }
374             }
375              
376             // Get the digest format - default NULL uses the openssl default
377 2 50         if (hv_exists(options, "digest", strlen("digest"))) {
378 2           svp = hv_fetch(options, "digest", strlen("digest"), 0);
379 2 50         if (SvPOKp(*svp)) {
380 2           digest = *svp;
381             }
382             } // No defaut value - sign will use openssl default
383              
384             // Get the output format - default is pem format
385 2 50         if (hv_exists(options, "format", strlen("format"))) {
386 2           svp = hv_fetch(options, "format", strlen("format"), 0);
387 2 50         if (SvPOKp(*svp)) {
388 2           format = *svp;
389             }
390             }
391              
392             // Get the private key and save it in memory
393 2 50         keyString = SvPV(private_key, keyStringLength);
394 2           bio = BIO_new_mem_buf(keyString, keyStringLength);
395 2 50         if (bio == NULL) {
396 0           croak ("Bio is null **** \n");
397             }
398              
399             // Create the PrivateKey as EVP_PKEY
400 2           EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, 0, NULL);
401 2 50         if (pkey == NULL) {
402 0           croak("Failed operation error code %d\n", errno);
403             }
404              
405             // This uses "Magic" to hold the private key object
406             // so it can be accessed later
407 2           HV * attributes = newHV();
408              
409 2           sv_magicext(key, NULL, PERL_MAGIC_ext,
410             &key_magic, (const char *)pkey, 0);
411              
412 2 50         if((hv_store(attributes, "privkey", 7, key, 0)) == NULL)
413 0           croak("unable to init privkey store");
414              
415 2 50         if (format != NULL)
416 2 50         if((hv_store(attributes, "format", 6, newRV_inc(format), 0)) == NULL)
417 0           croak("unable to init format store");
418              
419 2 50         if (digest != NULL)
420 2 50         if((hv_store(attributes, "digest", 6, newRV_inc(digest), 0)) == NULL)
421 0           croak("unable to init digest store");
422              
423 2 50         if((hv_store(attributes, "days", 4, newSViv(days), 0)) == NULL)
424 0           croak("unable to init days store");
425              
426 2           SV *const self = newRV_noinc( (SV *)attributes );
427              
428 2           RETVAL = sv_bless( self, gv_stashpv( class, 0 ) );
429              
430             OUTPUT:
431              
432             RETVAL
433              
434             char * get_digest(self)
435             HV * self;
436              
437             CODE:
438             SV **svp;
439              
440             // Get the output format - default is pem format
441 2 50         if (hv_exists(self, "digest", strlen("digest"))) {
442 2           svp = hv_fetch(self, "digest", strlen("digest"), 0);
443 2 50         if (SvROK(*svp)) {
444 2 50         RETVAL = SvPV_nolen(SvRV(*svp));
445             }
446             }
447             else {
448             //FIXME this should probably get the default for openssl
449             //but since nothing was set this is likely most accurate
450 0 0         RETVAL = SvPV_nolen(newSVpv("",0));
451             }
452              
453             OUTPUT:
454              
455             RETVAL
456              
457             IV set_digest(self, SV* digest)
458             HV * self;
459              
460             CODE:
461 1           const char * digestname = NULL;
462             STRLEN digestname_length;
463              
464 1           RETVAL = 0;
465             // Get digestname parameter - verify that it is valid
466             #if OPENSSL_API_COMPAT >= 30101
467             const EVP_MD *dgst;
468             #else
469 1           EVP_MD * md = NULL;
470             #endif
471 1 50         if (digest != NULL) {
472 1 50         digestname = (const char*) SvPV(digest, digestname_length);
473             // printf("Digest Name: %s\n", digestname);
474 1           md = (EVP_MD *)EVP_get_digestbyname(digestname);
475             }
476              
477 1 50         if (md != NULL) {
478 1 50         if((hv_store(self, "digest", 6, newRV_inc(digest), 0)) == NULL)
479 0           RETVAL = 0;
480             else
481 1           RETVAL = 1;
482             } else {
483             //printf("Can't change digets to %s\n", digestname);
484             }
485              
486             OUTPUT:
487              
488             RETVAL
489              
490             char * get_format(self)
491             HV * self;
492              
493             CODE:
494             SV **svp;
495              
496             // Get the output format - default is pem format
497 2 50         if (hv_exists(self, "format", strlen("format"))) {
498 2           svp = hv_fetch(self, "format", strlen("format"), 0);
499 2 50         if (SvROK(*svp)) {
500 2 50         RETVAL = SvPV_nolen(SvRV(*svp));
501             }
502             }
503             else {
504 0 0         RETVAL = SvPV_nolen(newSVpv("",0));
505             }
506              
507             OUTPUT:
508              
509             RETVAL
510              
511             IV set_format(self, SV* format)
512             HV * self;
513              
514             CODE:
515 1           IV ret = 0;
516              
517 2           if (sv_cmp(format, newSVpv("pem", 0)) == 0 ||
518 1           sv_cmp(format, newSVpv("text", 0)) == 0 )
519             {
520 2 50         if((hv_store(self, "format", 6, newRV_inc(format), 0)) == NULL)
521 0           RETVAL = 0;
522             else
523 1           RETVAL = 1;
524             } else {
525 0           RETVAL = ret;
526             }
527              
528             OUTPUT:
529              
530             RETVAL
531              
532             IV get_days(self)
533             HV * self;
534              
535             CODE:
536             SV **svp;
537              
538             // Get the number of days for specified - default 365
539 2 50         if (hv_exists(self, "days", strlen("days"))) {
540 2           svp = hv_fetch(self, "days", strlen("days"), 0);
541 2 50         if (SvIOKp(*svp)) {
542 2 50         RETVAL = SvIV(*svp);
543             }
544             }
545              
546             OUTPUT:
547              
548             RETVAL
549              
550             IV set_days(self, IV days)
551             HV * self;
552              
553             CODE:
554              
555 1 50         if((hv_store(self, "days", 4, newSViv(days), 0)) == NULL)
556 0           RETVAL = 0;
557             else
558 1           RETVAL = 1;
559              
560             OUTPUT:
561              
562             RETVAL
563              
564             SV * sign(self, request_SV)
565             HV * self;
566             SV * request_SV;
567              
568             PREINIT:
569             EVP_MD_CTX *mctx;
570              
571             CODE:
572              
573             SV **svp;
574             MAGIC* mg;
575             EVP_PKEY *private_key;
576             X509_REQ * csr;
577 2           int rv = 0;
578             STRLEN request_length;
579             unsigned char* request;
580             BIO *csrbio;
581             const char * digestname;
582             STRLEN digestname_length;
583             IV days;
584 2           SV * digest = NULL;
585             SV * format;
586              
587 2 50         if (!hv_exists(self, "privkey", strlen("privkey")))
588 0           croak("privkey not found in self!\n");
589              
590 2           svp = hv_fetch(self, "privkey", strlen("privkey"), 0);
591              
592 2 50         if (!SvMAGICAL(*svp) || (mg = mg_findext(*svp, PERL_MAGIC_ext, &key_magic)) == NULL)
    50          
593 0           croak("privkey is invalid");
594              
595 2 50         if (!hv_exists(self, "days", strlen("days")))
596 0           croak("days not found in self!\n");
597              
598 2           svp = hv_fetch(self, "days", strlen("days"), 0);
599 2 50         if (SvIOKp(*svp)) {
600 2 50         days = SvIV(*svp);
601             }
602             else {
603 0           days = 365;
604             }
605              
606 2 50         if (hv_exists(self, "digest", strlen("digest"))) {
607 2           svp = hv_fetch(self, "digest", strlen("digest"), 0);
608 2 50         if (SvROK(*svp)) {
609 2           digest = SvRV(*svp);
610             }
611             }
612              
613             //printf("Digest: %s\n", (char *) SvPV_nolen(digest));
614              
615 2 50         if (!hv_exists(self, "format", strlen("format")))
616 0           croak("format not found in self!\n");
617              
618 2           svp = hv_fetch(self, "format", strlen("format"), 0);
619 2 50         if (SvROK(*svp)) {
620 2           format = SvRV(*svp);
621             }
622              
623 2           private_key = (EVP_PKEY *) mg->mg_ptr;
624              
625             // Get the request that was passed into the sign function
626 2 50         request = (unsigned char*) SvPV(request_SV, request_length);
627              
628             // Create the X509_REQ from the request
629 2           csrbio = BIO_new_mem_buf(request, request_length);
630 2 50         if (csrbio == NULL) {
631 0           croak ("Bio for CRS Request is null **** \n");
632             }
633 2           csr = PEM_read_bio_X509_REQ(csrbio, NULL, NULL, NULL);
634              
635 2 50         if (csr == NULL) {
636 0           croak ("PEM_read_bio_X509_REQ failed **** \n");
637             }
638              
639             // Verify the CSR is properly signed
640             EVP_PKEY *pkey;
641 2 50         if (csr != NULL) {
642             #if OPENSSL_API_COMPAT <= 10100
643 2           pkey = X509_REQ_get_pubkey(csr);
644             #else
645             pkey = X509_REQ_get0_pubkey(csr);
646             #endif
647 2 50         if (pkey == NULL)
648 0           croak ("Warning: unable to get public key from CSR\n");
649              
650 2           int ret = do_X509_REQ_verify(csr, pkey, NULL);
651 2 50         if (ret == 0)
652 0           croak ("Verification of CSR failed\n");
653 2 50         if ( ret < 0)
654 2           croak ("Warning: error while verifying CSR self-signature\n");
655             }
656             else
657 0           croak("Unable to properly parse the Certificate Signing Request\n");
658              
659             // Create a new certificate store
660             X509 * x;
661             #if OPENSSL_API_COMPAT >= 30101
662             if ((x = X509_new_ex(libctx, propq)) == NULL)
663             #else
664 2 50         if ((x = X509_new()) == NULL)
665             #endif
666 0           croak("X509_new_ex failed ...\n");
667              
668             // FIXME need to look at this
669 2           int ext_copy = EXT_COPY_UNSET;
670 2 50         if (!copy_extensions(x, csr, ext_copy))
671 0           croak("Unable to copy extensions\n");
672              
673             // Update the certificate with the CSR's subject name
674 2 50         if (!X509_set_subject_name(x, X509_REQ_get_subject_name(csr)))
675 0           croak("X509_set_subject_name cannot set subject name\n");
676              
677             // Update the certificate with the CSR's public key
678             #if OPENSSL_API_COMPAT <= 10100
679 2 50         if (!X509_set_pubkey(x, X509_REQ_get_pubkey(csr)))
680             #else
681             if (!X509_set_pubkey(x, X509_REQ_get0_pubkey(csr)))
682             #endif
683 0           croak("X509_set_pubkey cannot set public key\n");
684              
685             // FIXME need to look at this
686             //for (int i = X509_get_ext_count(x) - 1; i >= 0; i--) {
687             // X509_EXTENSION *ex = X509_get_ext(x, i);
688             // const char *sn = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ex)));
689              
690             // if (clrext || (ext_names != NULL && strstr(ext_names, sn) == NULL))
691             // X509_EXTENSION_free(X509_delete_ext(x, i));
692             //}
693              
694             // FIXME - this may need to change to support signing by different certificates
695 2 50         if (private_key != NULL && !cert_matches_key(x, private_key))
    50          
696 0           croak("cert_matches_key: signature key and public key of cert do not match\n");
697              
698             // Generate a serial number and update the certificate
699 2           ASN1_INTEGER *sno = ASN1_INTEGER_new();
700 2 50         if (sno == NULL || !rand_serial(NULL, sno))
    50          
701 0           croak ("Unable to get ASN1INTEGER or random_serial\n");
702              
703 2 50         if (sno != NULL && !X509_set_serialNumber(x, sno))
    50          
704 0           croak("X509_set_serialNumber cannot set serial number\n");
705              
706 2           set_cert_times(x, NULL, NULL, (int) days);
707              
708             // Set the certificate's issuer based on the issuer's certificate
709             // In self-signed certificates it is the same issuer
710             // FIXME this needs to be fixed to support non-self-signed certificate
711 2           X509 * issuer_cert = x;
712 2 50         if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert)))
713 0           croak("X509_set_issuer_name cannot set issuer name\n");
714              
715             // Create the X509 v3 extensions for the certificate
716             X509V3_CTX ext_ctx;
717              
718             // Set the certificate issuer from the private key
719             #if OPENSSL_API_COMPAT >= 30000
720             X509V3_set_ctx(&ext_ctx, issuer_cert, x, NULL, NULL, X509V3_CTX_REPLACE);
721             if (!X509V3_set_issuer_pkey(&ext_ctx, private_key))
722             croak("X509V3_set_issuer_pkey cannot set issuer private key\n");
723             #elseif OPENSSL_API_COMPAT >=10010
724             X509V3_set_ctx(&ext_ctx, issuer_cert, x, csr, NULL, X509V3_CTX_REPLACE);
725 2           #else
726             X509V3_set_ctx(&ext_ctx, issuer_cert, x, csr, NULL, 0);
727             #endif
728              
729             // Set the X509 version of the certificate
730             #if OPENSSL_API_COMPAT >= 30000
731             if (!X509_set_version(x, X509_VERSION_3))
732 2 50         #else
733             if (!X509_set_version(x, 2))
734 0           #endif
735             croak("X509_set_version cannot set version 3\n");
736              
737             // Get digestname parameter - verify that it is valid
738             #if OPENSSL_API_COMPAT >= 30101
739             const EVP_MD *dgst;
740 2           #else
741             EVP_MD * md = NULL;
742 2 50         #endif
743 2 50         if (digest != NULL) {
744 2           digestname = (const char*) SvPV(digest, digestname_length);
745             md = (EVP_MD *)EVP_get_digestbyname(digestname);
746 2 50         }
747 2           if (md != NULL)
748             digestname = (const char *) digestname;
749 0           else {
750 0           digestname = NULL;
751             printf("Failed to set the digest md = Null\n");
752             }
753             //printf ("DIGEST NAME = %s\n", digestname);
754             // Allocate and a new digest context for certificate signing
755 2           #if OPENSSL_API_COMPAT <= 10100
756             mctx = EVP_MD_CTX_create();
757             #else
758             mctx = EVP_MD_CTX_new();
759             #endif
760              
761             // Sign the new certificate
762             #if OPENSSL_API_COMPAT >= 30101
763             if (mctx != NULL && do_sign_init(mctx, private_key, digestname, NULL) > 0)
764 2 50         #else
    50          
765             if (mctx != NULL && do_sign_init(mctx, private_key, md, NULL) > 0)
766 2           #endif
767             rv = (X509_sign_ctx(x, mctx) > 0);
768 2 50          
769 0           if (rv == 0)
770             croak("X509_sign_ctx cannot sign the new certificate\n");
771              
772 2           // Prepare to output new certificate
773             BIO * out = BIO_new(BIO_s_mem());
774              
775 2 50         int i;
776             if (sv_cmp(format, newSVpv("pem", 0)) == 0){
777 2           // Output the PEM encoded certificate
778             i = PEM_write_bio_X509(out, x);}
779             else
780 0           // Output the text format of the certificate
781             i = X509_print_ex(out, x, get_nameopt(), 0);
782 2 50          
783 0           if (!i)
784             croak("unable to output certificate data\n");
785 2            
786             RETVAL = extractBioString(aTHX_ out);
787              
788             OUTPUT:
789              
790             RETVAL
791              
792             #if OPENSSL_API_COMPAT > 10200
793             void signcsr_DESTROY(void)
794              
795             CODE:
796             /* deinitialisation is done automatically */
797              
798             #else
799             void signcsr_DESTROY(void)
800              
801             CODE:
802              
803 2           CRYPTO_cleanup_all_ex_data();
804 2           ERR_free_strings();
805 2           ERR_remove_state(0);
806 2           EVP_cleanup();
807              
808             #endif
809