1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4 
5 #include "ppport.h"
6 
7 #include "scep.h"
8 #include <stdlib.h>
9 #include <string.h>
10 #include "config.h"
11 #include <openssl/x509v3.h>
12 
13 // (try and) free all memory
14 void
cleanup_config(Conf * config)15 cleanup_config(Conf *config) {
16     if (! config) return;
17 
18     // only free SCEP* handle if we created it (i.e. was not passed in from Perl code)
19     if (config->handle_autocreated && config->handle) {
20         if (config->handle->configuration && config->handle->configuration->log)
21             BIO_free(config->handle->configuration->log);
22 
23         scep_cleanup(config->handle);
24     }
25 
26     free(config);
27     config = NULL;
28 }
29 
30 /*
31 Puts the OpenSSL error log to a string and frees config.
32 IMPORTANT: This is only for cleanup purposes at the end!
33 
34 additional_msg might be NULL.
35 */
36 void
create_err_msg(Conf * config,char * additional_msg)37 create_err_msg(Conf *config, char *additional_msg) {
38     char *tmp = NULL;
39     char error[4096];
40     long loglen;
41 
42     if (additional_msg) {
43         OPENSSL_strlcpy(error, additional_msg, 4096);
44         OPENSSL_strlcat(error, "\n", 4096);
45     }
46     else {
47         OPENSSL_strlcpy(error, "", 4096);
48     }
49 
50     if (! config) {
51         OPENSSL_strlcat(error, "*** Internal error: 'config' is not set", 4096);
52         goto cleanup_and_croak;
53     }
54     if (! config->handle) {
55         OPENSSL_strlcat(error, "*** Internal error: missing member (SCEP*)handle in 'config'", 4096);
56         goto cleanup_and_croak;
57     }
58     if (! config->handle->configuration) {
59         OPENSSL_strlcat(error, "*** Internal error: missing member (SCEP_CONFIGURATION*)configuration in config->handle", 4096);
60         goto cleanup_and_croak;
61     }
62     if (! config->handle->configuration->log) {
63         OPENSSL_strlcat(error, "*** Internal error: missing member (BIO*)log in config->handle->configuration", 4096);
64         goto cleanup_and_croak;
65     }
66 
67     // Flush all OpenSSL errors into the log BIO
68     ERR_print_errors(config->handle->configuration->log);
69     (void)BIO_flush(config->handle->configuration->log);
70 
71     /* read log data if we were logging to memory
72        i.e.: if there is a BIO_TYPE_MEM somewhere in the BIO chain */
73     if (BIO_find_type(config->handle->configuration->log, BIO_TYPE_MEM) != NULL) {
74         loglen = BIO_get_mem_data(config->handle->configuration->log, &tmp);
75         if (loglen > 0) {
76             // copy at most 4096 bytes from the memory BIO (ensuring a trailing \0)
77             OPENSSL_strlcat(error, tmp, 4096);
78         }
79     }
80 
81 cleanup_and_croak:
82     cleanup_config(config);
83 
84     if (strlen(error) == 0)
85         OPENSSL_strlcpy(error, "*** Internal error: no error message", 4096);
86     Perl_croak(aTHX_ "%s", error);
87 }
88 
89 
90 SV*
bio2str(BIO * b)91 bio2str(BIO *b) {
92     char *tmp = NULL;
93     char *buf = NULL;
94     long size = BIO_get_mem_data(b, &tmp);
95     buf = malloc(size + 1);
96     memcpy(buf, tmp, size);
97     buf[size] = '\0';
98     SV *reply = newSVpv(buf, 0);
99     free(buf);
100     return reply;
101 }
102 
103 /*
104 Creates a new configuration accoring to specified parameter.
105 In case a handle is already present, it will be used instead
106 of creating a new one.
107 */
108 SV*
init_config(SV * rv_config)109 init_config(SV *rv_config) {
110     SCEP_ERROR s;
111     BIO *scep_log = NULL;
112     Conf *config = malloc(sizeof(Conf));
113     if (config == NULL)
114         Perl_croak(aTHX_ "Memory allocation failure for config");
115 
116     config->passin = "plain";
117     config->passwd = "";
118     config->handle = NULL;
119     config->handle_autocreated = FALSE;
120 
121     if (SvROK(rv_config) && (SvTYPE(SvRV(rv_config)) == SVt_PVHV)) {
122         HV *hv_config = (HV*)SvRV(rv_config);
123         SV **svv;
124         svv = hv_fetch(hv_config, "handle", strlen("handle"),FALSE);
125         // use pre-existing SCEP* handle passed in from Perl code
126         if(svv) {
127             SV *sv;
128             if(SvROK(*svv)) {
129                 sv = SvRV(*svv);
130             }
131             else {
132                 create_err_msg(config, "Configuration parameter 'handle' is not a valid reference");
133             }
134             size_t s = SvIV(sv);
135             config->handle = INT2PTR(SCEP*, s);
136         }
137         // initialize new SCEP* handle
138         else {
139             s = scep_init(&config->handle);
140             if (s != SCEPE_OK) {
141                 create_err_msg(config, "Could not create SCEP handle");
142             }
143             config->handle_autocreated = TRUE; // so we know we can destroy it later on
144 
145             svv = hv_fetch(hv_config, "log", strlen("log"),FALSE);
146             if(svv) {
147                 char *md = SvPV_nolen(*svv);
148                 scep_log = BIO_new_file(md, "a");
149                 if(scep_log == NULL) {
150                     create_err_msg(config, "Could not create log file");
151                 }
152             }
153             else {
154                 scep_log = BIO_new(BIO_s_mem());
155                 if(scep_log == NULL) {
156                     create_err_msg(config, "Could not create log buffer");
157                 }
158             }
159             //cannot fail but we want to tolerate changes of scep_conf_set
160             s = scep_conf_set(config->handle, SCEPCFG_LOG, scep_log);
161             if (s != SCEPE_OK) {
162                 create_err_msg(config, "Could set log buffer");
163             }
164             s = scep_conf_set(config->handle, SCEPCFG_VERBOSITY, DEBUG);
165             if (s != SCEPE_OK) {
166                 create_err_msg(config, "Could set log verbosity");
167             }
168         }
169         svv = hv_fetch(hv_config, "passin", strlen("passin"),FALSE);
170         if (svv) {
171             config->passin = SvPV_nolen(*svv);
172         }
173         svv = hv_fetch(hv_config, "sigalg", strlen("sigalg"),FALSE);
174         if (svv) {
175             char *md = SvPV_nolen(*svv);
176             if(!(config->handle->configuration->sigalg = EVP_get_digestbyname(md))) {
177                 scep_log(config->handle, ERROR, "Could not set digest");
178                 create_err_msg(config, NULL);
179             }
180         }
181         svv = hv_fetch(hv_config, "encalg", strlen("encalg"),FALSE);
182         if(svv) {
183             char *encalg = SvPV_nolen(*svv);
184             if(!(config->handle->configuration->encalg = EVP_get_cipherbyname(encalg))) {
185                 scep_log(config->handle, ERROR, "Could not set cipher");
186                 create_err_msg(config, NULL);
187             }
188         }
189         svv = hv_fetch(hv_config, "passwd", strlen("passwd"),FALSE);
190         if (svv) {
191             config->passwd = SvPV_nolen(*svv);
192         }
193     }
194     else {
195         free(config);
196         Perl_croak(aTHX_ "Configuration parameter is not a perl hash structure");
197     }
198     SV *reply = INT2PTR(SV*, PTR2IV(config));
199     return reply;
200 }
201 
202 /*adds an engine to the handle according to config */
203 void
load_engine(SV * rv_engine_conf,Conf * config)204 load_engine(SV *rv_engine_conf, Conf *config) {
205     Engine_conf *engine_config = malloc(sizeof(Engine_conf));
206     if(engine_config == NULL) {
207         scep_log(config->handle, ERROR, "Memory allocation error for engine_conf");
208         create_err_msg(config, NULL);
209     }
210     if (SvROK(rv_engine_conf) && (SvTYPE(SvRV(rv_engine_conf)) == SVt_PVHV)) {
211         SCEP_ERROR s;
212         HV *hv_config = (HV*)SvRV(rv_engine_conf);
213         engine_config->label = "";
214         engine_config->so = "";
215         engine_config->pin = "";
216         engine_config->module = "";
217         SV **svv = hv_fetch(hv_config, "label", strlen("label"),FALSE);
218         if(svv) {
219             engine_config->label = SvPV_nolen(*svv);
220             svv = hv_fetch(hv_config, "so", strlen("so"),FALSE);
221             if(svv) {
222                 engine_config->so = SvPV_nolen(*svv);
223                 //engine-specific configuration
224                 //pkcs11
225                 if(!strcmp(engine_config->label, "pkcs11")) {
226                     svv = hv_fetch(hv_config, "module", strlen("module"),FALSE);
227                     if(svv) {
228                         engine_config->module = SvPV_nolen(*svv);
229                     }
230                     else {
231                         scep_log(config->handle, ERROR, "Engine pkcs11 requires module path");
232                         goto err;
233                     }
234                     s = scep_conf_set(config->handle, SCEPCFG_ENGINE_PARAM, "MODULE_PATH", engine_config->module);
235                     if (s != SCEPE_OK) {
236                         scep_log(config->handle, ERROR, "Could not set module path in handle");
237                         goto err;
238                     }
239                 }
240                 else {
241                     scep_log(config->handle, ERROR, "Sorry, unknown or unsupported engine");
242                     goto err;
243                 }
244                 s = scep_conf_set(config->handle, SCEPCFG_ENGINE, "dynamic", engine_config->label, engine_config->so);
245                 if (s != SCEPE_OK) {
246                     scep_log(config->handle, ERROR, "Could not set dynamic engine in handle");
247                     goto err2;
248                 }
249 
250                 //add engine-specific configuration to loaded engine
251                 //pkcs11
252                 if(!strcmp(engine_config->label, "pkcs11")) {
253                     svv = hv_fetch(hv_config, "pin", strlen("pin"),FALSE);
254                     if(svv) {
255                         engine_config->pin = SvPV_nolen(*svv);
256                         if(!ENGINE_ctrl_cmd_string(config->handle->configuration->engine, "PIN", engine_config->pin, 0)) {
257                             scep_log(config->handle, ERROR, "Setting PIN for engine failed");
258                             goto err2;
259                         }
260                     }
261                     else {
262                         scep_log(config->handle, ERROR, "Engine pkcs11 requires PIN");
263                         goto err2;
264                     }
265                 }
266             }
267             else {
268                 scep_log(config->handle, ERROR, "Engine requires path to shared object");
269                 goto err;
270             }
271         }
272     }
273     else {
274         scep_log(config->handle, ERROR, "Engine config is not a perl hash structure");
275         goto err;
276     }
277     free(engine_config);
278     return;
279 
280     //Only call err2 if yout want do destroy the engine. You dont want this in case it comes from the outside
281     err2:return;
282     if (config->handle->configuration->engine)
283     {
284         ENGINE_finish(config->handle->configuration->engine);
285         ENGINE_free(config->handle->configuration->engine);
286     }
287     if(config->handle->configuration->params) {
288         config->handle->configuration->params = NULL;
289     }
290     err:return;
291         free(engine_config);
292         create_err_msg(config, NULL);
293 }
294 
295 
load_key(char * key_str,Conf * config)296 EVP_PKEY *load_key(char *key_str, Conf *config) {
297     EVP_PKEY *key = NULL;
298     BIO *b = NULL;
299 
300     if (! config)
301       Perl_croak(aTHX_ "*** Internal error: missing config");
302 
303     if (! (config->handle && config->handle->configuration))
304       create_err_msg(config, "*** Internal error: missing config handle configuration");
305 
306     if(config->handle->configuration->engine == NULL) {
307         b = BIO_new(BIO_s_mem());
308         if(b == NULL) {
309             scep_log(config->handle, ERROR, "Memory allocation failure for BIO");
310             create_err_msg(config, NULL);
311         }
312         if(!BIO_write(b, key_str, strlen(key_str))) {
313             scep_log(config->handle, ERROR, "Could not write to BIO");
314             goto err;
315         }
316         char *pwd = NULL;
317         if(!strcmp(config->passin, "env")) {
318             pwd = getenv("pwd");
319             if (pwd == NULL) {
320                 scep_log(config->handle, ERROR, "env:pwd not set");
321                 goto err;
322             }
323         }
324         else if(!strcmp(config->passin, "pass")) {
325             pwd = config->passwd;
326             if(pwd == NULL) {
327                 scep_log(config->handle, ERROR, "pass set but no password provided");
328                 goto err;
329             }
330         }
331         else if (!strcmp(config->passin, "plain")) {
332             pwd = "";
333         }
334         else {
335             scep_log(config->handle, ERROR, "unsupported pass format");
336             goto err;
337         }
338         if(!(key = PEM_read_bio_PrivateKey(b, NULL, 0, pwd))) {
339             scep_log(config->handle, ERROR, "Reading private key failed");
340             goto err;
341         }
342         BIO_free(b);
343     }
344     else {
345         //we got an engine
346         if(!(key = ENGINE_load_private_key(config->handle->configuration->engine, key_str, NULL, NULL))) {
347             scep_log(config->handle, ERROR, "Loading private key from engine failed");
348             create_err_msg(config, NULL);
349         }
350     }
351     return key;
352     err:
353         BIO_free(b);
354         EVP_PKEY_free(key);
355         create_err_msg(config, NULL);
356     return NULL;
357 }
358 
359 
360 X509_CRL *
str2crl(Conf * config,char * str,BIO * b)361 str2crl (Conf *config, char *str, BIO *b) {
362     X509_CRL *c = NULL;
363     if (! config)
364       Perl_croak(aTHX_ "*** Internal error: missing config");
365 
366     if (! config->handle)
367       create_err_msg(config, "*** Internal error: missing config handle");
368 
369     if(BIO_write(b, str, strlen(str)) <= 0) {
370         scep_log(config->handle, ERROR, "Could not write CRL to BIO");
371         BIO_free(b);
372         create_err_msg(config, NULL);
373     }
374     c = PEM_read_bio_X509_CRL(b, NULL, 0, 0);
375     if(c == NULL) {
376         scep_log(config->handle, ERROR, "Could not read CRL");
377         BIO_free(b);
378         create_err_msg(config, NULL);
379     }
380     (void)BIO_reset(b);
381     return c;
382 }
383 
384 
385 X509_REQ *
str2req(Conf * config,char * str,BIO * b)386 str2req (Conf *config, char *str, BIO *b) {
387     X509_REQ *c = NULL;
388     if (! config)
389       Perl_croak(aTHX_ "*** Internal error: missing config");
390 
391     if (! config->handle)
392       create_err_msg(config, "*** Internal error: missing config handle");
393 
394     if(BIO_write(b, str, strlen(str)) <= 0) {
395         scep_log(config->handle, ERROR, "Could not write REQ to BIO");
396         BIO_free(b);
397         create_err_msg(config, NULL);
398     }
399     c = PEM_read_bio_X509_REQ(b, NULL, 0, 0);
400     if(c == NULL) {
401         scep_log(config->handle, ERROR, "Could not read REQ");
402         BIO_free(b);
403         create_err_msg(config, NULL);
404     }
405     (void)BIO_reset(b);
406     return c;
407 }
408 
409 
410 X509 *
str2cert(Conf * config,char * str,BIO * b)411 str2cert (Conf *config, char *str, BIO *b) {
412     X509 *c = NULL;
413     if (! config)
414       Perl_croak(aTHX_ "*** Internal error: missing config");
415 
416     if (! config->handle)
417       create_err_msg(config, "*** Internal error: missing config handle");
418 
419     if(BIO_write(b, str, strlen(str)) <= 0) {
420         scep_log(config->handle, ERROR, "Could not write cert to BIO");
421         BIO_free(b);
422         create_err_msg(config, NULL);
423     }
424     c = PEM_read_bio_X509(b, NULL, 0, 0);
425     if(c == NULL) {
426         scep_log(config->handle, ERROR, "Could not read cert");
427         BIO_free(b);
428         create_err_msg(config, NULL);
429     }
430 
431     /*Snippet that could be used to verify certificate purpose*/
432     /*
433     if (c->ex_flags & EXFLAG_KUSAGE) {
434         if(c->ex_kusage & KU_DECIPHER_ONLY) {
435             scep_log(config->handle, ERROR, "foo");
436             BIO_free(b);
437         }
438         reate_err_msg(config);
439     }*/
440     (void)BIO_reset(b);
441     return c;
442 }
443 
444 
445 PKCS7 *
str2pkcs7(Conf * config,char * str,BIO * b)446 str2pkcs7 (Conf *config, char *str, BIO *b) {
447     PKCS7 *c = NULL;
448     if (! config)
449       Perl_croak(aTHX_ "*** Internal error: missing config");
450 
451     if (! config->handle)
452       create_err_msg(config, "*** Internal error: missing config handle");
453 
454     if(BIO_write(b, str, strlen(str)) <= 0) {
455         scep_log(config->handle, ERROR, "Could not write PKCS7 to BIO");
456         BIO_free(b);
457         create_err_msg(config, NULL);
458     }
459     c = PEM_read_bio_PKCS7(b, NULL, 0, 0);
460     if(c == NULL) {
461         scep_log(config->handle, ERROR, "Could not read PKCS7");
462         BIO_free(b);
463         create_err_msg(config, NULL);
464     }
465     (void)BIO_reset(b);
466     return c;
467 }
468 
469 
STACK_OF(X509_INFO)470 STACK_OF(X509_INFO) *
471 str2x509infos (Conf *config, char *str, BIO *b) {
472     if (! config)
473       Perl_croak(aTHX_ "*** Internal error: missing config");
474 
475     if (! config->handle)
476       create_err_msg(config, "*** Internal error: missing config handle");
477 
478     STACK_OF(X509_INFO) *c = NULL;
479         if(BIO_write(b, str, strlen(str)) <= 0) {
480         scep_log(config->handle, ERROR, "Could not write cert chain to BIO");
481         BIO_free(b);
482         create_err_msg(config, NULL);
483     }
484     c = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL);
485     if(c == NULL) {
486         scep_log(config->handle, ERROR, "Could not read signer infos from cert chain");
487         BIO_free(b);
488         create_err_msg(config, NULL);
489     }
490     (void)BIO_reset(b);
491     return c;
492 }
493 
494 
495 typedef SCEP_DATA *Crypt__LibSCEP;
496 typedef SCEP      *Handle;
497 MODULE = Crypt::LibSCEP    PACKAGE = Crypt::LibSCEP
498 
499 SV*
500 create_certificate_reply_wop7(rv_config, sig_key_str, sig_cert_str, transID, senderNonce, enc_cert_str, chain_str)
501 SV * rv_config
502 char * sig_key_str
503 char * sig_cert_str
504 char * chain_str
505 char * enc_cert_str
506 char * transID
507 unsigned char * senderNonce
508 PREINIT:
509     Conf *config = NULL;
510     BIO *b = NULL;
511     EVP_PKEY *sig_key = NULL;
512     X509 *sig_cert = NULL;
513     X509 *issuedCert = NULL;
514     PKCS7 *p7 = NULL;
515     int i;
516     STACK_OF(X509) *certs = NULL;
517     STACK_OF(X509_INFO) *X509Infos = NULL;
518     X509_INFO *X509Info = NULL;
519     X509 *enc_cert = NULL;
520     SV *reply = NULL;
521     SCEP_ERROR s;
522     bool success = FALSE;
523 CODE:
524     certs = sk_X509_new_null();
525     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
526     sig_key = load_key(sig_key_str, config);
527 
528     b = BIO_new(BIO_s_mem());
529     if(b == NULL) {
530         scep_log(config->handle, ERROR, "Memory allocation error");
531         create_err_msg(config, NULL);
532     }
533 
534     sig_cert = str2cert (config, sig_cert_str, b);
535     X509Infos = str2x509infos (config, chain_str, b);
536     enc_cert = str2cert (config, enc_cert_str, b);
537 
538     for (i = 0; i < sk_X509_INFO_num(X509Infos); i++) {
539         X509Info = sk_X509_INFO_value(X509Infos, i);
540         if (X509Info->x509) {
541             if(!issuedCert) {
542                 issuedCert = X509_dup(X509Info->x509);
543                 X509Info->x509 = NULL;
544                 continue;
545             }
546             if (!sk_X509_push(certs, X509Info->x509)) {
547                 scep_log(config->handle, WARN, "Could not read a signer info from stack of signer infos");
548             }
549             X509Info->x509 = NULL;
550         }
551     }
552     sk_X509_INFO_pop_free(X509Infos, X509_INFO_free);
553 
554     s = scep_certrep(config->handle, transID, senderNonce, SCEP_SUCCESS, 0, issuedCert, sig_cert, sig_key, enc_cert, certs, NULL, &p7);
555     if(s != SCEPE_OK || p7 == NULL) {
556         scep_log(config->handle, ERROR, "scep_certrep failed");
557         goto err;
558     }
559 
560     if(!PEM_write_bio_PKCS7(b, p7)) {
561         scep_log(config->handle, ERROR, "Could not write SCEP result to BIO");
562         goto err;
563     }
564 
565     reply = bio2str(b);
566 
567     success = TRUE;
568     err:
569         sk_X509_pop_free(certs, X509_free);
570         X509_free(sig_cert);
571         X509_free(enc_cert);
572         X509_free(issuedCert);
573         EVP_PKEY_free(sig_key);
574         BIO_free(b);
575         if (success)
576             cleanup_config(config);
577         else
578             create_err_msg(config, NULL);
579 
580     RETVAL = reply;
581 OUTPUT:
582     RETVAL
583 
584 
585 SV *
586 create_certificate_reply(rv_config, sig_key_str, sig_cert_str, pkcsreq_str, chain_str)
587 SV * rv_config
588 char * sig_key_str
589 char * sig_cert_str
590 char * pkcsreq_str
591 char * chain_str
592 PREINIT:
593     Conf *config = NULL;
594     BIO *b = NULL;
595     PKCS7 *p7 = NULL;
596     int i;
597     STACK_OF(X509) *certs = NULL;
598     STACK_OF(X509_INFO) *X509Infos = NULL;
599     X509_INFO *X509Info = NULL;
600     SV *reply = NULL;
601     bool success = FALSE;
602     EVP_PKEY *sig_key = NULL;
603     X509 *sig_cert = NULL;
604     PKCS7 *pkcsreq = NULL;
605     X509 *issuedCert = NULL;
606     X509 *enc_cert = NULL;
607     SCEP_ERROR s;
608     SCEP_DATA *unwrapped = NULL;
609 CODE:
610     certs = sk_X509_new_null();
611     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
612     sig_key = load_key(sig_key_str, config);
613 
614     b = BIO_new(BIO_s_mem());
615     if(b == NULL) {
616         scep_log(config->handle, ERROR, "Memory allocation error");
617         create_err_msg(config, NULL);
618     }
619 
620     sig_cert = str2cert(config, sig_cert_str, b);
621     pkcsreq = str2pkcs7(config, pkcsreq_str, b);
622     X509Infos = str2x509infos (config, chain_str, b);
623 
624     s = scep_unwrap(config->handle, pkcsreq, NULL, NULL, NULL, &unwrapped);
625     if(s != SCEPE_OK || unwrapped == NULL){
626         scep_log(config->handle, ERROR, "scep_unwrap failed");
627         goto err;
628     }
629 
630     //TODO check for unwrapped->certs, then verify which one can be used for encryption
631     //NOTE that this uses the fist certificate from pkcsreq for encryption. If this is not
632     //the right one, the programm will fail.
633     //if you want to use an external encryption cert, use create_certificate_reply_wop7
634     enc_cert = unwrapped->signer_certificate;
635     if(enc_cert == NULL) {
636         //cannot happen as LibSCEP would have failed on unwrap
637         scep_log(config->handle, ERROR, "No encryption certificate in pkcsreq");
638         goto err;
639     }
640 
641     for (i = 0; i < sk_X509_INFO_num(X509Infos); i++) {
642         X509Info = sk_X509_INFO_value(X509Infos, i);
643         if (X509Info->x509) {
644             if(!issuedCert) {
645                 issuedCert = X509_dup(X509Info->x509);
646                 X509Info->x509 = NULL;
647                 continue;
648             }
649             if (!sk_X509_push(certs, X509Info->x509)) {
650                 scep_log(config->handle, WARN, "Could not read a signer info from stack of signer infos");
651             }
652             X509Info->x509 = NULL;
653         }
654     }
655     sk_X509_INFO_pop_free(X509Infos, X509_INFO_free);
656 
657     s = scep_certrep(config->handle, unwrapped->transactionID, unwrapped->senderNonce, SCEP_SUCCESS, 0, issuedCert, sig_cert, sig_key, enc_cert, certs, NULL, &p7);
658     if(s != SCEPE_OK || p7 == NULL) {
659         scep_log(config->handle, ERROR, "scep_certrep failed");
660         goto err;
661     }
662 
663     if(!PEM_write_bio_PKCS7(b, p7)) {
664         scep_log(config->handle, ERROR, "Could not write SCEP result to BIO");
665         goto err;
666     }
667 
668     reply = bio2str(b);
669 
670     success = TRUE;
671     err:
672         sk_X509_pop_free(certs, X509_free);
673         X509_free(sig_cert);
674         X509_free(issuedCert);
675         EVP_PKEY_free(sig_key);
676         PKCS7_free(pkcsreq);
677         BIO_free(b);
678         SCEP_DATA_free(unwrapped);
679         if (success)
680             cleanup_config(config);
681         else
682             create_err_msg(config, NULL);
683     RETVAL = reply;
684 OUTPUT:
685     RETVAL
686 
687 
688 SV *
689 create_error_reply(rv_config, sig_key_str, sig_cert_str, pkcsreq_str, failInfo_str)
690 SV   * rv_config
691 char * sig_key_str
692 char * sig_cert_str
693 char * pkcsreq_str
694 char * failInfo_str
695 PREINIT:
696     Conf *config = NULL;
697     BIO *b = NULL;
698     PKCS7 *p7 = NULL;
699     SV *reply = NULL;
700     EVP_PKEY *sig_key = NULL;
701     bool success = FALSE;
702     X509 *sig_cert = NULL;
703     PKCS7 *pkcsreq = NULL;
704     SCEP_ERROR s;
705     SCEP_DATA *unwrapped = NULL;
706     SCEP_FAILINFO failInfo = 0;
707 CODE:
708     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
709     sig_key = load_key(sig_key_str, config);
710 
711     b = BIO_new(BIO_s_mem());
712     if(b == NULL) {
713         scep_log(config->handle, ERROR, "Memory allocation error");
714         create_err_msg(config, NULL);
715     }
716 
717     sig_cert = str2cert (config, sig_cert_str, b);
718     pkcsreq = str2pkcs7(config, pkcsreq_str, b);
719 
720     s = scep_unwrap(config->handle, pkcsreq, NULL, NULL, NULL, &unwrapped);
721     if(s != SCEPE_OK || unwrapped == NULL) {
722         scep_log(config->handle, ERROR, "scep_unwrap failed");
723         goto err;
724     }
725 
726     if(strcmp("badAlg", failInfo_str) == 0)
727         failInfo = SCEP_BAD_ALG;
728     else if(strcmp("badMessageCheck", failInfo_str) == 0)
729         failInfo = SCEP_BAD_MESSAGE_CHECK;
730     else if(strcmp("badRequest", failInfo_str) == 0)
731         failInfo = SCEP_BAD_REQUEST;
732     else if(strcmp("badTime", failInfo_str) == 0)
733         failInfo = SCEP_BAD_TIME;
734     else if(strcmp("badCertId", failInfo_str) == 0)
735         failInfo = SCEP_BAD_CERT_ID;
736     else  {
737         scep_log(config->handle, ERROR, "Invalid failInfo");
738         goto err;
739     }
740 
741     s = scep_certrep(config->handle, unwrapped->transactionID, unwrapped->senderNonce, SCEP_FAILURE, failInfo, NULL, sig_cert, sig_key, NULL, NULL, NULL, &p7);
742     if(s != SCEPE_OK || p7 == NULL) {
743         scep_log(config->handle, ERROR, "scep_certrep failed");
744         goto err;
745     }
746 
747     if(!PEM_write_bio_PKCS7(b, p7)) {
748         scep_log(config->handle, ERROR, "Could not write SCEP result to BIO");
749         goto err;
750     }
751     reply = bio2str(b);
752     success = TRUE;
753 
754     err:
755         EVP_PKEY_free(sig_key);
756         PKCS7_free(pkcsreq);
757         X509_free(sig_cert);
758         BIO_free(b);
759         SCEP_DATA_free(unwrapped);
760         if (success)
761             cleanup_config(config);
762         else
763             create_err_msg(config, NULL);
764     RETVAL = reply;
765 OUTPUT:
766     RETVAL
767 
768 
769 SV *
770 create_error_reply_wop7(rv_config, sig_key_str, sig_cert_str, transID, senderNonce, failInfo_str)
771 SV   * rv_config
772 char * sig_key_str
773 char * sig_cert_str
774 char * transID
775 unsigned char *senderNonce
776 char * failInfo_str
777 PREINIT:
778     Conf *config = NULL;
779     BIO *b = NULL;
780     PKCS7 *p7 = NULL;
781     EVP_PKEY *sig_key = NULL;
782     SV *reply = NULL;
783     SCEP_ERROR s;
784     bool success = FALSE;
785     X509 *sig_cert = NULL;
786     SCEP_FAILINFO failInfo = 0;
787 CODE:
788     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
789     sig_key = load_key(sig_key_str, config);
790 
791     b = BIO_new(BIO_s_mem());
792     if(b == NULL) {
793         scep_log(config->handle, ERROR, "Memory allocation error");
794         create_err_msg(config, NULL);
795     }
796 
797     sig_cert = str2cert (config, sig_cert_str, b);
798 
799     if(strcmp("badAlg", failInfo_str) == 0)
800         failInfo = SCEP_BAD_ALG;
801     else if(strcmp("badMessageCheck", failInfo_str) == 0)
802         failInfo = SCEP_BAD_MESSAGE_CHECK;
803     else if(strcmp("badRequest", failInfo_str) == 0)
804         failInfo = SCEP_BAD_REQUEST;
805     else if(strcmp("badTime", failInfo_str) == 0)
806         failInfo = SCEP_BAD_TIME;
807     else if(strcmp("badCertId", failInfo_str) == 0)
808         failInfo = SCEP_BAD_CERT_ID;
809     else  {
810         scep_log(config->handle, ERROR, "Invalid fail info");
811         goto err;
812     }
813 
814     s = scep_certrep(config->handle, transID, senderNonce, SCEP_FAILURE, failInfo, NULL, sig_cert, sig_key, NULL, NULL, NULL, &p7);
815     if(s != SCEPE_OK || p7 == NULL) {
816         scep_log(config->handle, ERROR, "scep_certrep failed");
817         goto err;
818     }
819 
820     if(!PEM_write_bio_PKCS7(b, p7)) {
821         scep_log(config->handle, ERROR, "Could not write SCEP result to BIO");
822         goto err;
823     }
824     reply = bio2str(b);
825 
826     success = TRUE;
827     err:
828         EVP_PKEY_free(sig_key);
829         X509_free(sig_cert);
830         BIO_free(b);
831         if (success)
832             cleanup_config(config);
833         else
834             create_err_msg(config, NULL);
835     RETVAL = reply;
836 OUTPUT:
837     RETVAL
838 
839 
840 SV *
841 create_pending_reply_wop7(rv_config, sig_key_str, sig_cert_str, transID, senderNonce)
842 SV   * rv_config
843 char * sig_key_str
844 char * sig_cert_str
845 char * transID
846 unsigned char * senderNonce
847 PREINIT:
848     Conf *config = NULL;
849     BIO *b = NULL;
850     PKCS7 *p7 = NULL;
851     EVP_PKEY *sig_key = NULL;
852     SV *reply = NULL;
853     SCEP_ERROR s;
854     bool success = FALSE;
855     X509 *sig_cert = NULL;
856 CODE:
857     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
858     sig_key = load_key(sig_key_str, config);
859 
860     b = BIO_new(BIO_s_mem());
861     if(b == NULL) {
862         scep_log(config->handle, ERROR, "Memory allocation error");
863         create_err_msg(config, NULL);
864     }
865 
866     sig_cert = str2cert (config, sig_cert_str, b);
867 
868     s = scep_certrep(config->handle, transID, senderNonce, SCEP_PENDING, 0, NULL, sig_cert, sig_key, NULL, NULL, NULL, &p7);
869     if(s != SCEPE_OK || p7 == NULL) {
870         scep_log(config->handle, ERROR, "scep_certrep failed");
871         goto err;
872     }
873 
874     if(!PEM_write_bio_PKCS7(b, p7)) {
875         scep_log(config->handle, ERROR, "Could not write SCEP result to BIO");
876         goto err;
877     }
878     reply = bio2str(b);
879 
880     success = TRUE;
881 
882     err:
883         EVP_PKEY_free(sig_key);
884         X509_free(sig_cert);
885         BIO_free(b);
886         if (success)
887             cleanup_config(config);
888         else
889             create_err_msg(config, NULL);
890     RETVAL = reply;
891 OUTPUT:
892     RETVAL
893 
894 
895 SV *
896 create_pending_reply(rv_config, sig_key_str, sig_cert_str, pkcsreq_str)
897 SV   * rv_config
898 char * sig_key_str
899 char * sig_cert_str
900 char * pkcsreq_str
901 PREINIT:
902     Conf *config = NULL;
903     BIO *b = NULL;
904     PKCS7 *p7 = NULL;
905     EVP_PKEY *sig_key = NULL;
906     SV *reply = NULL;
907     SCEP_ERROR s;
908     bool success = FALSE;
909     X509 *sig_cert = NULL;
910     PKCS7 *pkcsreq = NULL;
911     SCEP_DATA *unwrapped = NULL;
912 CODE:
913     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
914     sig_key = load_key(sig_key_str, config);
915 
916     b = BIO_new(BIO_s_mem());
917     if(b == NULL) {
918         scep_log(config->handle, ERROR, "Memory allocation error");
919         create_err_msg(config, NULL);
920     }
921 
922     sig_cert = str2cert (config, sig_cert_str, b);
923     pkcsreq = str2pkcs7(config, pkcsreq_str, b);
924 
925     s = scep_unwrap(config->handle, pkcsreq, NULL, NULL, NULL, &unwrapped);
926     if(s != SCEPE_OK || unwrapped == NULL) {
927         scep_log(config->handle, ERROR, "scep_unwrap failed");
928         goto err;
929     }
930 
931     s = scep_certrep(config->handle, unwrapped->transactionID, unwrapped->senderNonce, SCEP_PENDING, 0, NULL, sig_cert, sig_key, NULL, NULL, NULL, &p7);
932     if(s != SCEPE_OK || p7 == NULL) {
933         scep_log(config->handle, ERROR, "scep_certrep failed");
934         goto err;
935     }
936 
937     if(!PEM_write_bio_PKCS7(b, p7)) {
938         scep_log(config->handle, ERROR, "Could not write SCEP result to BIO");
939         goto err;
940     }
941     reply = bio2str(b);
942     success = TRUE;
943 
944     err:
945         EVP_PKEY_free(sig_key);
946         X509_free(sig_cert);
947         PKCS7_free(pkcsreq);
948         BIO_free(b);
949         SCEP_DATA_free(unwrapped);
950         if (success)
951             cleanup_config(config);
952         else
953             create_err_msg(config, NULL);
954     RETVAL = reply;
955 OUTPUT:
956     RETVAL
957 
958 
959 SV *
960 pkcsreq(rv_config, sig_key_str, sig_cert_str, enc_cert_str, req_str)
961 SV   * rv_config
962 char * sig_cert_str
963 char * enc_cert_str
964 char * sig_key_str
965 char * req_str
966 PREINIT:
967     Conf *config = NULL;
968     BIO *b = NULL;
969     PKCS7 *p7 = NULL;
970     EVP_PKEY *sig_key = NULL;
971     SV *reply = NULL;
972     SCEP_ERROR s;
973     bool success = FALSE;
974     X509 *sig_cert = NULL;
975     X509_REQ *req = NULL;
976     X509 *enc_cert = NULL;
977 CODE:
978     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
979     sig_key = load_key(sig_key_str, config);
980 
981     b = BIO_new(BIO_s_mem());
982     if(b == NULL) {
983         scep_log(config->handle, ERROR, "Memory allocation error");
984         create_err_msg(config, NULL);
985     }
986 
987     sig_cert = str2cert (config, sig_cert_str, b);
988     req = str2req (config, req_str, b);
989     enc_cert = str2cert (config, enc_cert_str, b);
990 
991     s = scep_pkcsreq(
992         config->handle, req, sig_cert, sig_key, enc_cert, &p7);
993     if(s != SCEPE_OK || p7 == NULL) {
994         scep_log(config->handle, ERROR, "scep_pkcsreq failed");
995         goto err;
996     }
997     if(!PEM_write_bio_PKCS7(b, p7)) {
998         scep_log(config->handle, ERROR, "Could not write SCEP result to BIO");
999         goto err;
1000     }
1001     reply = bio2str(b);
1002 
1003     success = TRUE;
1004 
1005     err:
1006         BIO_free(b);
1007         EVP_PKEY_free(sig_key);
1008         X509_free(sig_cert);
1009         X509_free(enc_cert);
1010         X509_REQ_free(req);
1011         if (success)
1012             cleanup_config(config);
1013         else
1014             create_err_msg(config, NULL);
1015     RETVAL = reply;
1016 OUTPUT:
1017     RETVAL
1018 
1019 
1020 SV *
1021 getcert(rv_config, sig_key_str, sig_cert_str, enc_cert_str, cacert_str, serial_str)
1022 SV   * rv_config
1023 char * sig_key_str
1024 char * sig_cert_str
1025 char * enc_cert_str
1026 char * cacert_str
1027 char * serial_str
1028 PREINIT:
1029     Conf *config = NULL;
1030     BIO *b = NULL;
1031     PKCS7 *p7 = NULL;
1032     SV *reply = NULL;
1033     EVP_PKEY *sig_key = NULL;
1034     bool success = FALSE;
1035     X509 *sig_cert = NULL;
1036     X509 *enc_cert = NULL;
1037     X509 *cacert = NULL;
1038     ASN1_INTEGER *serial = NULL;
1039     X509_NAME *issuer = NULL;
1040     SCEP_ERROR s;
1041 CODE:
1042     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
1043     sig_key = load_key(sig_key_str, config);
1044 
1045     b = BIO_new(BIO_s_mem());
1046     if(b == NULL) {
1047         scep_log(config->handle, ERROR, "Memory allocation error");
1048         create_err_msg(config, NULL);
1049     }
1050 
1051     sig_cert = str2cert (config, sig_cert_str, b);
1052     cacert = str2cert (config, cacert_str, b);
1053     enc_cert = str2cert (config, enc_cert_str, b);
1054 
1055     //TODO are other methods than issuer and serial such as key identifier allowed?
1056     serial = s2i_ASN1_INTEGER(NULL, serial_str);
1057     if(serial == NULL) {
1058         scep_log(config->handle, ERROR, "Serial number must be provided");
1059         goto err;
1060     }
1061     issuer = X509_get_subject_name(cacert);
1062     if(issuer == NULL) {
1063         scep_log(config->handle, ERROR, "Issuer must be present in signer cert");
1064         goto err;
1065     }
1066 
1067     s = scep_get_cert(
1068         config->handle, sig_cert, sig_key,
1069         issuer, serial, enc_cert, &p7);
1070     if(s != SCEPE_OK || p7 == NULL) {
1071         scep_log(config->handle, ERROR, "scep_get_cert failed");
1072         goto err;
1073     }
1074 
1075     if(!PEM_write_bio_PKCS7(b, p7)) {
1076         scep_log(config->handle, ERROR, "Could not write SCEP result to BIO");
1077         goto err;
1078     }
1079     reply = bio2str(b);
1080 
1081     success = TRUE;
1082 
1083     err:
1084         ASN1_INTEGER_free(serial);
1085         X509_free(sig_cert);
1086         X509_free(enc_cert);
1087         X509_free(cacert);
1088         EVP_PKEY_free(sig_key);
1089         BIO_free(b);
1090         if (success)
1091             cleanup_config(config);
1092         else
1093             create_err_msg(config, NULL);
1094     RETVAL = reply;
1095 OUTPUT:
1096     RETVAL
1097 
1098 
1099 char *
1100 get_message_type(pkiMessage)
1101 Crypt::LibSCEP pkiMessage
1102 CODE:
1103     RETVAL = "";
1104     if(SCEP_MSG_PKCSREQ == pkiMessage->messageType)
1105         RETVAL = "PKCSReq";
1106     if(SCEP_MSG_CERTREP == pkiMessage->messageType)
1107         RETVAL = "CertRep";
1108     if(SCEP_MSG_GETCERTINITIAL == pkiMessage->messageType)
1109         RETVAL = "GetCertInitial";
1110     if(SCEP_MSG_GETCERT == pkiMessage->messageType)
1111         RETVAL = "GetCert";
1112     if(SCEP_MSG_GETCRL == pkiMessage->messageType)
1113         RETVAL = "GetCRL";
1114 OUTPUT:
1115     RETVAL
1116 
1117 
1118 Crypt::LibSCEP
1119 parse(rv_config, pkiMessage_str)
1120 SV   * rv_config
1121 char * pkiMessage_str
1122 PREINIT:
1123     BIO *b = NULL;
1124     SCEP_ERROR s;
1125     Conf *config = NULL;
1126     PKCS7 *pkiMessage = NULL;
1127     SCEP_DATA *unwrapped = NULL;
1128     bool success = FALSE;
1129 CODE:
1130     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
1131     Newx(RETVAL, 1, SCEP_DATA);
1132 
1133     b = BIO_new(BIO_s_mem());
1134     if(b == NULL) {
1135         scep_log(config->handle, ERROR, "Memory allocation error");
1136         create_err_msg(config, NULL);
1137     }
1138 
1139     pkiMessage = str2pkcs7(config, pkiMessage_str, b);
1140 
1141     s = scep_unwrap(config->handle, pkiMessage, NULL, NULL, NULL, &unwrapped);
1142     if(s != SCEPE_OK || unwrapped == NULL) {
1143         scep_log(config->handle, ERROR, "scep_unwrap failed");
1144         goto err;
1145     }
1146     success = TRUE;
1147 
1148     err:
1149         PKCS7_free(pkiMessage);
1150         BIO_free(b);
1151         if (success)
1152             cleanup_config(config);
1153         else
1154             create_err_msg(config, NULL);
1155     RETVAL = unwrapped;
1156 OUTPUT:
1157     RETVAL
1158 
1159 
1160 Crypt::LibSCEP
1161 unwrap(rv_config, pkiMessage_str, sig_cert_str, enc_cert_str, enc_key_str)
1162 SV   * rv_config
1163 char * pkiMessage_str
1164 char * sig_cert_str
1165 char * enc_cert_str
1166 char * enc_key_str
1167 PREINIT:
1168     Conf *config = NULL;
1169     BIO *b = NULL;
1170     SCEP_ERROR s;
1171     PKCS7 *pkiMessage = NULL;
1172     SCEP_DATA *unwrapped = NULL;
1173     bool success = FALSE;
1174     EVP_PKEY *enc_key = NULL;
1175     X509 *sig_cert = NULL;
1176     X509 *enc_cert = NULL;
1177 CODE:
1178     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
1179     enc_key = load_key(enc_key_str, config);
1180 
1181     b = BIO_new(BIO_s_mem());
1182     if(b == NULL) {
1183         scep_log(config->handle, ERROR, "Memory allocation error");
1184         create_err_msg(config, NULL);
1185     }
1186 
1187     sig_cert = str2cert (config, sig_cert_str, b);
1188     enc_cert = str2cert (config, enc_cert_str, b);
1189 
1190     Newx(RETVAL, 1, SCEP_DATA);
1191 
1192     pkiMessage = str2pkcs7(config, pkiMessage_str, b);
1193 
1194     s = scep_unwrap(config->handle, pkiMessage, sig_cert, enc_cert, enc_key, &unwrapped);
1195 
1196     if(s != SCEPE_OK || unwrapped == NULL) {
1197         scep_log(config->handle, ERROR, "scep_unwrap failed");
1198         goto err;
1199     }
1200     success = TRUE;
1201     err:
1202         X509_free(sig_cert);
1203         X509_free(enc_cert);
1204         PKCS7_free(pkiMessage);
1205         BIO_free(b);
1206         EVP_PKEY_free(enc_key);
1207         if (success)
1208             cleanup_config(config);
1209         else
1210             create_err_msg(config, NULL);
1211     RETVAL = unwrapped;
1212 OUTPUT:
1213     RETVAL
1214 
1215 
1216 void
1217 create_engine(rv_config, rv_engine_conf)
1218 SV * rv_config
1219 SV * rv_engine_conf
1220 PREINIT:
1221     Conf *config = NULL;
1222 CODE:
1223     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
1224     load_engine(rv_engine_conf, config);
1225     cleanup_config(config);
1226 
1227 
1228 SV *
1229 get_transaction_id(pkiMessage)
1230     Crypt::LibSCEP pkiMessage
1231 CODE:
1232     RETVAL = newSVpv(pkiMessage->transactionID, 0);
1233 OUTPUT:
1234     RETVAL
1235 
1236 
1237 SV *
1238 get_failInfo(pkiMessage)
1239     Crypt::LibSCEP pkiMessage
1240 PREINIT:
1241     char *ret = NULL;
1242 CODE:
1243     ret = "";
1244     switch(pkiMessage->failInfo) {
1245         case 0:
1246             ret = "badAlg";
1247             break;
1248         case 1:
1249             ret = "badMessageCheck";
1250             break;
1251         case 2:
1252             ret = "badRequest";
1253             break;
1254         case 3:
1255             ret = "badTime";
1256             break;
1257         case 4:
1258             ret = "badCertId";
1259             break;
1260     }
1261     RETVAL = newSVpv(ret, 0);
1262 OUTPUT:
1263     RETVAL
1264 
1265 
1266 SV *
1267 get_pkiStatus(pkiMessage)
1268     Crypt::LibSCEP pkiMessage
1269 PREINIT:
1270     char *ret = NULL;
1271 CODE:
1272     ret = "";
1273     switch(pkiMessage->pkiStatus) {
1274         case 0:
1275             ret = "SUCCESS";
1276             break;
1277         case 2:
1278             ret = "FAILURE";
1279             break;
1280         case 3:
1281             ret = "PENDING";
1282             break;
1283     }
1284     RETVAL = newSVpv(ret, 0);
1285 OUTPUT:
1286     RETVAL
1287 
1288 
1289 SV *
1290 get_issuer(pkiMessage)
1291     Crypt::LibSCEP pkiMessage
1292 PREINIT:
1293     char *ret = NULL;
1294 CODE:
1295     ret = "";
1296     if(pkiMessage->issuer_and_serial != NULL) {
1297         ret = X509_NAME_oneline(pkiMessage->issuer_and_serial->issuer, NULL, 0);
1298     }
1299     else if(pkiMessage->issuer_and_subject != NULL) {
1300         ret = X509_NAME_oneline(pkiMessage->issuer_and_subject->issuer, NULL, 0);
1301     }
1302     RETVAL = newSVpv(ret, 0);
1303     OPENSSL_free(ret);
1304 OUTPUT:
1305     RETVAL
1306 
1307 
1308 SV *
1309 get_subject(pkiMessage)
1310     Crypt::LibSCEP pkiMessage
1311 PREINIT:
1312     char *ret = NULL;
1313 CODE:
1314     if(pkiMessage->issuer_and_subject != NULL) {
1315         ret = X509_NAME_oneline(pkiMessage->issuer_and_subject->subject, NULL, 0);
1316     }
1317     RETVAL = newSVpv(ret, 0);
1318     OPENSSL_free(ret);
1319 OUTPUT:
1320     RETVAL
1321 
1322 
1323 SV *
1324 get_crl(pkiMessage)
1325     Crypt::LibSCEP pkiMessage
1326 PREINIT:
1327     STACK_OF(X509_CRL) *crls = NULL;
1328     X509_CRL *crl = NULL;
1329     BIO *b = NULL;
1330 CODE:
1331     if (pkiMessage && pkiMessage->messageData && pkiMessage->messageData->d.sign && pkiMessage->messageData->d.sign->crl) {
1332         crls = pkiMessage->messageData->d.sign->crl;
1333         if(sk_X509_CRL_num(crls) == 1) {
1334             crl = sk_X509_CRL_value(crls, 0);
1335             if(crl != NULL) {
1336                 b = BIO_new(BIO_s_mem());
1337                 if(b == NULL) {
1338                     Perl_croak(aTHX_ "Memory allocation error");
1339                 }
1340                 if(PEM_write_bio_X509_CRL(b, crl)) {
1341                     RETVAL = bio2str(b);
1342                 }
1343                 BIO_free(b);
1344             }
1345         }
1346     }
1347 OUTPUT:
1348     RETVAL
1349 
1350 
1351 SV *
1352 get_cert(pkiMessage)
1353     Crypt::LibSCEP pkiMessage
1354 PREINIT:
1355     STACK_OF(X509) *certs = NULL;
1356     SV *reply = NULL;
1357     BIO *b = NULL;
1358     int i;
1359 CODE:
1360     if (pkiMessage && pkiMessage->messageData && pkiMessage->messageData->d.sign && pkiMessage->messageData->d.sign->cert) {
1361         certs = pkiMessage->messageData->d.sign->cert;
1362         b = BIO_new(BIO_s_mem());
1363         if(b == NULL) {
1364             Perl_croak(aTHX_ "Memory allocation error");
1365         }
1366         for (i = 0; i < sk_X509_num(certs); i++) {
1367             PEM_write_bio_X509(b, sk_X509_value(certs, i));
1368         // BIO_printf(b, "\n");
1369         }
1370         reply = bio2str(b);
1371         RETVAL = reply;
1372         BIO_free(b);
1373     }
1374 OUTPUT:
1375     RETVAL
1376 
1377 
1378 SV*
1379 get_senderNonce(pkiMessage)
1380     Crypt::LibSCEP pkiMessage
1381 CODE:
1382     RETVAL = newSVpvn((char*)pkiMessage->senderNonce, 16);
1383 OUTPUT:
1384     RETVAL
1385 
1386 SV *
1387 get_recipientNonce(pkiMessage)
1388     Crypt::LibSCEP pkiMessage
1389 PREINIT:
1390 CODE:
1391     RETVAL = NULL;
1392     if(strlen((char*)pkiMessage->recipientNonce) > 0) {
1393         RETVAL = newSVpvn((char*)pkiMessage->recipientNonce, 16);
1394     }
1395     else
1396         RETVAL = newSVpv("", 0);
1397 OUTPUT:
1398     RETVAL
1399 
1400 
1401 SV *
1402 create_nextca_reply(rv_config, chain_str, sig_cert_str, sig_key_str)
1403 SV   * rv_config
1404 char * chain_str
1405 char * sig_cert_str
1406 char * sig_key_str
1407 PREINIT:
1408     Conf *config = NULL;
1409     SV *reply = NULL;
1410     BIO *b = NULL;
1411     EVP_PKEY *sig_key = NULL;
1412     X509 *sig_cert = NULL;
1413     int i;
1414     STACK_OF(X509) *certs = NULL;
1415     STACK_OF(X509_INFO) *X509Infos = NULL;
1416     X509_INFO *X509Info = NULL;
1417     PKCS7 *p7 = NULL;
1418     bool success = FALSE;
1419 CODE:
1420     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
1421     certs = sk_X509_new_null();
1422 
1423     b = BIO_new(BIO_s_mem());
1424     if(b == NULL) {
1425         scep_log(config->handle, ERROR, "Memory allocation error");
1426         create_err_msg(config, NULL);
1427     }
1428 
1429     sig_key = load_key(sig_key_str, config);
1430     sig_cert = str2cert (config, sig_cert_str, b);
1431     X509Infos = str2x509infos (config, chain_str, b);
1432 
1433     for (i = 0; i < sk_X509_INFO_num(X509Infos); i++) {
1434         X509Info = sk_X509_INFO_value(X509Infos, i);
1435         if (X509Info->x509) {
1436             if (!sk_X509_push(certs, X509Info->x509)) {
1437                 scep_log(config->handle, WARN, "Could not read a signer info from stack of signer infos");
1438             }
1439             X509Info->x509 = NULL;
1440         }
1441     }
1442     sk_X509_INFO_pop_free(X509Infos, X509_INFO_free);
1443 
1444     if (sk_X509_num(certs) > 0) {
1445         if (!(scep_getcacert_reply(config->handle, certs, sig_cert, sig_key, &p7) == SCEPE_OK) || p7 == NULL) {
1446             scep_log(config->handle, ERROR, "scep_getcacert_reply failed");
1447             goto err;
1448         }
1449     }
1450     else {
1451         scep_log(config->handle, ERROR, "No signer infos found");
1452         goto err;
1453     }
1454 
1455     if(!PEM_write_bio_PKCS7(b, p7)) {
1456         scep_log(config->handle, ERROR, "Could not write SCEP result to BIO");
1457         goto err;
1458     }
1459 
1460     reply = bio2str(b);
1461 
1462     success = TRUE;
1463 
1464     err:
1465         EVP_PKEY_free(sig_key);
1466         sk_X509_pop_free(certs, X509_free);
1467         X509_free(sig_cert);
1468         BIO_free(b);
1469         if (success)
1470             cleanup_config(config);
1471         else
1472             create_err_msg(config, NULL);
1473 
1474     RETVAL = reply;
1475 OUTPUT:
1476     RETVAL
1477 
1478 
1479 SV *
1480 get_getcert_serial(pkiMessage)
1481     Crypt::LibSCEP pkiMessage
1482 PREINIT:
1483     char *ret = NULL;
1484 CODE:
1485     ret = "";
1486     if(pkiMessage->issuer_and_serial != NULL) {
1487         ret = i2s_ASN1_INTEGER(NULL, pkiMessage->issuer_and_serial->serial);
1488     }
1489     RETVAL = newSVpv(ret, 0);
1490 OUTPUT:
1491     RETVAL
1492 
1493 
1494 SV *
1495 get_signer_cert(pkiMessage)
1496     Crypt::LibSCEP pkiMessage
1497   PREINIT:
1498     X509 *cert = NULL;
1499     SV *reply = NULL;
1500     BIO *b = NULL;
1501 CODE:
1502     cert = pkiMessage->signer_certificate;
1503 
1504     b = BIO_new(BIO_s_mem());
1505     if(b == NULL) {
1506         Perl_croak(aTHX_ "Memory allocation error");
1507     }
1508 
1509     if(PEM_write_bio_X509(b, cert)) {
1510         reply = bio2str(b);
1511         RETVAL = reply;
1512     }
1513     BIO_free(b);
1514 OUTPUT:
1515     RETVAL
1516 
1517 
1518 SV *
1519 get_pkcs10(pkiMessage)
1520     Crypt::LibSCEP pkiMessage
1521 PREINIT:
1522     X509_REQ * req = NULL;
1523     SV *reply = NULL;
1524     BIO *b = NULL;
1525 CODE:
1526     if (! pkiMessage)
1527       Perl_croak(aTHX_ "Internal error: no pkiMessage");
1528     if (! pkiMessage->request)
1529       Perl_croak(aTHX_ "Internal error: no request in pkiMessage");
1530     req = pkiMessage->request;
1531 
1532     b = BIO_new(BIO_s_mem());
1533     if(b == NULL) {
1534         Perl_croak(aTHX_ "Memory allocation error");
1535     }
1536 
1537     if(PEM_write_bio_X509_REQ(b, req)) {
1538         reply = bio2str(b);
1539         RETVAL = reply;
1540     }
1541     BIO_free(b);
1542 OUTPUT:
1543     RETVAL
1544 
1545 
1546 Handle
1547 create_handle(rv_config)
1548 SV * rv_config
1549 PREINIT:
1550     Conf *config = NULL;
1551 CODE:
1552     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
1553     Newx(RETVAL, 1, SCEP);
1554     RETVAL = config->handle;
1555     free(config);
1556 OUTPUT:
1557     RETVAL
1558 
1559 
1560 void
1561 cleanup(rv_handle)
1562 SV * rv_handle
1563 PREINIT:
1564     SCEP *handle = NULL;
1565     size_t s;
1566     SV *sv = NULL;
1567 CODE:
1568     if(SvROK(rv_handle)) {
1569         sv = SvRV(rv_handle);
1570         s = SvIV(sv);
1571         handle = INT2PTR(SCEP *, s);
1572     }
1573     else {
1574         Perl_croak(aTHX_ "Handle is not a Perl hash");
1575     }
1576     if(handle) {
1577         scep_cleanup(handle);
1578     }
1579 
1580 
1581 SV *
1582 getcertinitial(rv_config, sig_key_str, sig_cert_str, enc_cert_str, req_str, issuer_cert_str)
1583 SV   * rv_config
1584 char * sig_cert_str
1585 char * enc_cert_str
1586 char * sig_key_str
1587 char * req_str
1588 char * issuer_cert_str
1589 PREINIT:
1590     Conf *config = NULL;
1591     BIO *b = NULL;
1592     PKCS7 *p7 = NULL;
1593     EVP_PKEY *sig_key = NULL;
1594     SV *reply = NULL;
1595     SCEP_ERROR s;
1596     bool success = FALSE;
1597     X509 *sig_cert = NULL;
1598     X509_REQ *req = NULL;
1599     X509 *enc_cert = NULL;
1600     X509 *issuer_cert = NULL;
1601 CODE:
1602     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
1603     sig_key = load_key(sig_key_str, config);
1604 
1605     b = BIO_new(BIO_s_mem());
1606     if(b == NULL) {
1607         scep_log(config->handle, ERROR, "Memory allocation error");
1608         create_err_msg(config, NULL);
1609     }
1610 
1611     sig_cert = str2cert (config, sig_cert_str, b);
1612     issuer_cert = str2cert (config, issuer_cert_str, b);
1613     req = str2req (config, req_str, b);
1614     enc_cert = str2cert (config, enc_cert_str, b);
1615 
1616     s = scep_get_cert_initial(
1617         config->handle, req, sig_cert, sig_key, issuer_cert, enc_cert, &p7);
1618     if(s != SCEPE_OK || p7 == NULL) {
1619         scep_log(config->handle, ERROR, "scep_pkcsreq failed");
1620         goto err;
1621     }
1622     if(!PEM_write_bio_PKCS7(b, p7)) {
1623         scep_log(config->handle, ERROR, "Could not write SCEP result to BIO");
1624         goto err;
1625     }
1626     reply = bio2str(b);
1627 
1628     success = TRUE;
1629 
1630     err:
1631         X509_REQ_free(req);
1632         EVP_PKEY_free(sig_key);
1633         X509_free(sig_cert);
1634         X509_free(issuer_cert);
1635         X509_free(enc_cert);
1636         BIO_free(b);
1637         if (success)
1638             cleanup_config(config);
1639         else
1640             create_err_msg(config, NULL);
1641     RETVAL = reply;
1642 OUTPUT:
1643     RETVAL
1644 
1645 
1646 SV *
1647 getcrl(rv_config, sig_key_str, sig_cert_str, enc_cert_str, validate_cert_str)
1648 SV   * rv_config
1649 char * sig_cert_str
1650 char * enc_cert_str
1651 char * validate_cert_str
1652 char * sig_key_str
1653 PREINIT:
1654     Conf *config = NULL;
1655     BIO *b = NULL;
1656     PKCS7 *p7 = NULL;
1657     EVP_PKEY *sig_key = NULL;
1658     SV *reply = NULL;
1659     SCEP_ERROR s;
1660     bool success = FALSE;
1661     X509 *sig_cert = NULL;
1662     X509 *enc_cert = NULL;
1663     X509 *validate_cert = NULL;
1664 CODE:
1665     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
1666     sig_key = load_key(sig_key_str, config);
1667 
1668     b = BIO_new(BIO_s_mem());
1669     if(b == NULL) {
1670         scep_log(config->handle, ERROR, "Memory allocation error");
1671         create_err_msg(config, NULL);
1672     }
1673 
1674     sig_cert = str2cert (config, sig_cert_str, b);
1675     enc_cert = str2cert (config, enc_cert_str, b);
1676     validate_cert = str2cert (config, validate_cert_str, b);
1677 
1678     s = scep_get_crl(
1679         config->handle, sig_cert, sig_key, validate_cert, enc_cert, &p7);
1680     if(s != SCEPE_OK || p7 == NULL) {
1681         scep_log(config->handle, ERROR, "scep_get_crl failed");
1682         goto err;
1683     }
1684     if(!PEM_write_bio_PKCS7(b, p7)) {
1685         scep_log(config->handle, ERROR, "Could not write SCEP result to BIO");
1686         goto err;
1687     }
1688     reply = bio2str(b);
1689 
1690     success = TRUE;
1691 
1692     err:
1693         EVP_PKEY_free(sig_key);
1694         X509_free(sig_cert);
1695         X509_free(enc_cert);
1696         X509_free(validate_cert);
1697         BIO_free(b);
1698         if (success)
1699             cleanup_config(config);
1700         else
1701             create_err_msg(config, NULL);
1702     RETVAL = reply;
1703 OUTPUT:
1704     RETVAL
1705 
1706 
1707 SV *
1708 create_crl_reply(rv_config, sig_key_str, sig_cert_str, getcrl_str, crl_str)
1709 SV * rv_config
1710 char * sig_key_str
1711 char * sig_cert_str
1712 char * getcrl_str
1713 char * crl_str
1714 PREINIT:
1715     Conf *config = NULL;
1716     BIO *b = NULL;
1717     PKCS7 *p7 = NULL;
1718     SV *reply = NULL;
1719     bool success = FALSE;
1720     EVP_PKEY *sig_key = NULL;
1721     X509 *sig_cert = NULL;
1722     PKCS7 *getcrl = NULL;
1723     X509 *enc_cert = NULL;
1724     SCEP_ERROR s;
1725     SCEP_DATA *unwrapped = NULL;
1726     X509_CRL *crl = NULL;
1727 CODE:
1728     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
1729     sig_key = load_key(sig_key_str, config);
1730 
1731     b = BIO_new(BIO_s_mem());
1732     if(b == NULL) {
1733         scep_log(config->handle, ERROR, "Memory allocation error");
1734         create_err_msg(config, NULL);
1735     }
1736 
1737     sig_cert = str2cert (config, sig_cert_str, b);
1738     getcrl = str2pkcs7(config, getcrl_str, b);
1739     crl = str2crl (config, crl_str, b);
1740 
1741     s = scep_unwrap(config->handle, getcrl, NULL, NULL, NULL, &unwrapped);
1742     if(s != SCEPE_OK || unwrapped == NULL){
1743         scep_log(config->handle, ERROR, "scep_unwrap failed");
1744         goto err;
1745     }
1746 
1747     enc_cert = unwrapped->signer_certificate;
1748     if(enc_cert == NULL) {
1749         //cannot happen as LibSCEP would have failed on unwrap
1750         scep_log(config->handle, ERROR, "No encryption certificate in pkcsreq");
1751         goto err;
1752     }
1753 
1754 
1755     s = scep_certrep(config->handle, unwrapped->transactionID, unwrapped->senderNonce, SCEP_SUCCESS, 0, NULL, sig_cert, sig_key, enc_cert, NULL, crl, &p7);
1756     if(s != SCEPE_OK  || p7 == NULL){
1757         scep_log(config->handle, ERROR, "scep_certrep failed");
1758         goto err;
1759     }
1760 
1761     if(!PEM_write_bio_PKCS7(b, p7)) {
1762         scep_log(config->handle, ERROR, "Could not write SCEP result to BIO");
1763         goto err;
1764     }
1765 
1766     reply = bio2str(b);
1767 
1768     success = TRUE;
1769     err:
1770         EVP_PKEY_free(sig_key);
1771         X509_free(sig_cert);
1772         PKCS7_free(getcrl);
1773         X509_CRL_free(crl);
1774         BIO_free(b);
1775         SCEP_DATA_free(unwrapped);
1776         if (success)
1777             cleanup_config(config);
1778         else
1779             create_err_msg(config, NULL);
1780     RETVAL = reply;
1781 OUTPUT:
1782     RETVAL
1783 
1784 
1785 SV *
1786 create_crl_reply_wop7(rv_config, sig_key_str, sig_cert_str, transID, senderNonce, enc_cert_str, crl_str)
1787 SV * rv_config
1788 char * sig_key_str
1789 char * sig_cert_str
1790 char * crl_str
1791 char * enc_cert_str
1792 char * transID
1793 unsigned char * senderNonce
1794 PREINIT:
1795     Conf *config = NULL;
1796     BIO *b = NULL;
1797     EVP_PKEY *sig_key = NULL;
1798     X509 *sig_cert = NULL;
1799     PKCS7 *p7 = NULL;
1800     X509_CRL *crl = NULL;
1801     X509 *enc_cert = NULL;
1802     SV *reply = NULL;
1803     SCEP_ERROR s;
1804     bool success = FALSE;
1805 CODE:
1806     config = INT2PTR(Conf *, PTR2IV(init_config(rv_config)));
1807     sig_key = load_key(sig_key_str, config);
1808 
1809     b = BIO_new(BIO_s_mem());
1810     if(b == NULL) {
1811         scep_log(config->handle, ERROR, "Memory allocation error");
1812         create_err_msg(config, NULL);
1813     }
1814 
1815     sig_cert = str2cert (config, sig_cert_str, b);
1816     enc_cert = str2cert (config, enc_cert_str, b);
1817     crl = str2crl (config, crl_str, b);
1818 
1819     s = scep_certrep(config->handle, transID, senderNonce, SCEP_SUCCESS, 0, NULL, sig_cert, sig_key, enc_cert, NULL, crl, &p7);
1820     if(s != SCEPE_OK || p7 == NULL) {
1821         scep_log(config->handle, ERROR, "scep_certrep failed");
1822         goto err;
1823     }
1824 
1825     if(!PEM_write_bio_PKCS7(b, p7)) {
1826         scep_log(config->handle, ERROR, "Could not write SCEP result to BIO");
1827         goto err;
1828     }
1829 
1830     reply = bio2str(b);
1831 
1832     success = TRUE;
1833     err:
1834         X509_free(sig_cert);
1835         X509_free(enc_cert);
1836         EVP_PKEY_free(sig_key);
1837         X509_CRL_free(crl);
1838         BIO_free(b);
1839         if (success)
1840             cleanup_config(config);
1841         else
1842             create_err_msg(config, NULL);
1843 
1844     RETVAL = reply;
1845 OUTPUT:
1846     RETVAL
1847 
1848 
1849 void
1850 DESTROY(result)
1851     Crypt::LibSCEP result
1852 CODE:
1853     Safefree(result);
1854