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