1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4 
5 #include <openssl/asn1.h>
6 #include <openssl/objects.h>
7 #include <openssl/bio.h>
8 #include <openssl/crypto.h>
9 #include <openssl/err.h>
10 #include <openssl/evp.h>
11 #include <openssl/pem.h>
12 #include <openssl/x509.h>
13 #include <openssl/x509v3.h>
14 #include <openssl/opensslconf.h>
15 #ifndef OPENSSL_NO_EC
16 # include <openssl/ec.h>
17 #endif
18 
19 /* from openssl/apps/apps.h */
20 #define FORMAT_UNDEF    0
21 #define FORMAT_ASN1     1
22 #define FORMAT_TEXT     2
23 #define FORMAT_PEM      3
24 #define FORMAT_PKCS12   5
25 #define FORMAT_SMIME    6
26 #define FORMAT_ENGINE   7
27 #define FORMAT_IISSGC   8
28 
29 /* fake our package name */
30 typedef X509*  Crypt__OpenSSL__X509;
31 typedef X509_EXTENSION* Crypt__OpenSSL__X509__Extension;
32 typedef ASN1_OBJECT* Crypt__OpenSSL__X509__ObjectID;
33 typedef X509_NAME* Crypt__OpenSSL__X509__Name;
34 typedef X509_NAME_ENTRY* Crypt__OpenSSL__X509__Name_Entry;
35 typedef X509_CRL* Crypt__OpenSSL__X509__CRL;
36 
37 /* 1.0 backwards compat */
38 #if OPENSSL_VERSION_NUMBER < 0x10100000
39 #define const_ossl11
40 
41 #ifndef sk_OPENSSL_STRING_num
42 #define sk_OPENSSL_STRING_num sk_num
43 #endif
44 
45 #ifndef sk_OPENSSL_STRING_value
46 #define sk_OPENSSL_STRING_value sk_value
47 #endif
48 
X509_get0_serialNumber(const X509 * a)49 static ASN1_INTEGER *X509_get0_serialNumber(const X509 *a)
50 {
51   return a->cert_info->serialNumber;
52 }
53 
RSA_get0_key(const RSA * r,const BIGNUM ** n,const BIGNUM ** e,const BIGNUM ** d)54 static void RSA_get0_key(const RSA *r,
55                          const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
56 {
57   if (n != NULL)
58     *n = r->n;
59   if (e != NULL)
60     *e = r->e;
61   if (d != NULL)
62     *d = r->d;
63 }
64 
EVP_PKEY_get0_RSA(EVP_PKEY * pkey)65 static RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
66 {
67   if (pkey->type != EVP_PKEY_RSA)
68     return NULL;
69   return pkey->pkey.rsa;
70 }
71 
X509_CRL_get0_signature(const X509_CRL * crl,const ASN1_BIT_STRING ** psig,X509_ALGOR ** palg)72 static void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig,
73                                     X509_ALGOR **palg)
74 {
75   if (psig != NULL)
76     *psig = crl->signature;
77   if (palg != NULL)
78     *palg = crl->sig_alg;
79 }
80 
81 #if OPENSSL_VERSION_NUMBER < 0x10002000
X509_get0_signature(const_ossl11 ASN1_BIT_STRING ** psig,const_ossl11 X509_ALGOR ** palg,const X509 * x)82 static void X509_get0_signature(const_ossl11 ASN1_BIT_STRING **psig, const_ossl11 X509_ALGOR **palg,
83                                 const X509 *x)
84 {
85     if (psig != NULL)
86         *psig = x->signature;
87     if (palg != NULL)
88         *palg = x->sig_alg;
89 }
90 #endif
91 
DSA_get0_pqg(const DSA * d,const BIGNUM ** p,const BIGNUM ** q,const BIGNUM ** g)92 static void DSA_get0_pqg(const DSA *d,
93                          const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
94 {
95   if (p != NULL)
96     *p = d->p;
97   if (q != NULL)
98     *q = d->q;
99   if (g != NULL)
100     *g = d->g;
101 }
102 
DSA_get0_key(const DSA * d,const BIGNUM ** pub_key,const BIGNUM ** priv_key)103 static void DSA_get0_key(const DSA *d,
104                          const BIGNUM **pub_key, const BIGNUM **priv_key)
105 {
106   if (pub_key != NULL)
107     *pub_key = d->pub_key;
108   if (priv_key != NULL)
109     *priv_key = d->priv_key;
110 }
111 
EVP_PKEY_get0_DSA(EVP_PKEY * pkey)112 static DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey)
113 {
114   if (pkey->type != EVP_PKEY_DSA)
115     return NULL;
116   return pkey->pkey.dsa;
117 }
118 
EVP_PKEY_get0_EC_KEY(EVP_PKEY * pkey)119 static EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
120 {
121   if (pkey->type != EVP_PKEY_EC)
122     return NULL;
123   return pkey->pkey.ec;
124 }
125 
126 #else
127 #define const_ossl11 const
128 #endif
129 
130 /* Unicode 0xfffd */
131 static U8 utf8_substitute_char[3] = { 0xef, 0xbf, 0xbd };
132 
133 /* stolen from OpenSSL.xs */
bio_write_cb(struct bio_st * bm,int m,const char * ptr,int l,long x,long y)134 long bio_write_cb(struct bio_st *bm, int m, const char *ptr, int l, long x, long y) {
135 
136   if (m == BIO_CB_WRITE) {
137     SV *sv = (SV *) BIO_get_callback_arg(bm);
138     sv_catpvn(sv, ptr, l);
139   }
140 
141   if (m == BIO_CB_PUTS) {
142     SV *sv = (SV *) BIO_get_callback_arg(bm);
143     l = strlen(ptr);
144     sv_catpvn(sv, ptr, l);
145   }
146 
147   return l;
148 }
149 
sv_bio_create(void)150 static BIO* sv_bio_create(void) {
151 
152   SV *sv = newSVpvn("", 0);
153 
154   /* create an in-memory BIO abstraction and callbacks */
155   BIO *bio = BIO_new(BIO_s_mem());
156 
157   BIO_set_callback(bio, bio_write_cb);
158   BIO_set_callback_arg(bio, (void *)sv);
159 
160   return bio;
161 }
162 
sv_bio_final(BIO * bio)163 static SV* sv_bio_final(BIO *bio) {
164 
165   SV* sv;
166 
167   (void)BIO_flush(bio);
168   sv = (SV *)BIO_get_callback_arg(bio);
169   BIO_set_callback_arg(bio, (void *)NULL);
170   BIO_set_callback(bio, (void *)NULL);
171   BIO_free_all(bio);
172 
173   if (!sv) sv = &PL_sv_undef;
174 
175   return sv;
176 }
177 
178 /* call this just before sv_bio_final if the BIO got an UTF8 encoded text and you want native perl utf-8 strings. */
sv_bio_utf8_on(BIO * bio)179 static SV* sv_bio_utf8_on(BIO *bio) {
180 
181   SV* sv = (SV *)BIO_get_callback_arg(bio);
182 
183   /* Illegal utf-8 in the string */
184   if (!sv_utf8_decode(sv)) {
185     STRLEN len;
186     SV *nsv = newSVpvn("", 0);
187 
188     const U8* start = (U8 *) SvPV(sv, len);
189     const U8* end   = start + len;
190     const U8* cur;
191 
192     while ((start < end) && !is_utf8_string_loclen(start, len, &cur, 0)) {
193       sv_catpvn(nsv, (const char*)start, (cur - start) + 1);  /* text that was ok */
194       sv_catpvn(nsv, (const char*)utf8_substitute_char, 3);  /* insert \x{fffd} */
195       start = cur + 1;
196       len = end - cur;
197     }
198 
199     if (start < end) {
200       sv_catpvn(nsv, (const char*)start, (cur - start) - 1);  /* rest of the string */
201     }
202 
203     sv_copypv(sv, nsv);
204     SvREFCNT_dec(nsv);
205     sv_utf8_decode(sv); /* should be ok now */
206   }
207 
208   return sv;
209 }
210 
211 /*
212 static void sv_bio_error(BIO *bio) {
213 
214   SV* sv = (SV *)BIO_get_callback_arg(bio);
215   if (sv) sv_free(sv);
216 
217   BIO_free_all (bio);
218 }
219 */
220 
ssl_error(void)221 static const char *ssl_error(void) {
222   BIO *bio;
223   SV *sv;
224   STRLEN l;
225 
226   bio = sv_bio_create();
227   ERR_print_errors(bio);
228   sv = sv_bio_final(bio);
229   ERR_clear_error();
230   return SvPV(sv, l);
231 }
232 
233 /* Make a scalar ref to a class object */
sv_make_ref(const char * class,void * object)234 static SV* sv_make_ref(const char* class, void* object) {
235   SV* rv;
236 
237   rv = newSV(0);
238   sv_setref_pv(rv, class, (void*) object);
239 
240   if (! sv_isa(rv, class) ) {
241     croak("Error creating reference to %s", class);
242   }
243 
244   return rv;
245 }
246 
247 /*
248  * hash of extensions from x509.
249  * no_name can be
250  *  0: index by long name,
251  *  1: index by oid string,
252  *  2: index by short name
253 */
hv_exts(X509 * x509,int no_name)254 static HV* hv_exts(X509* x509, int no_name) {
255   X509_EXTENSION *ext;
256   int i, c, r;
257   size_t len = 128;
258   char* key = NULL;
259   SV* rv;
260 
261   HV* RETVAL = newHV();
262   sv_2mortal((SV*)RETVAL);
263   c = X509_get_ext_count(x509);
264 
265   if ( !(c > 0) ) {
266     croak("No extensions found\n");
267   }
268 
269   for (i = 0; i < c; i++) {
270     r = 0;
271 
272     ext = X509_get_ext(x509, i);
273 
274     if (ext == NULL) croak("Extension %d unavailable\n", i);
275 
276     rv = sv_make_ref("Crypt::OpenSSL::X509::Extension", (void*)ext);
277 
278     if (no_name == 0 || no_name == 1) {
279 
280        key = malloc(sizeof(char) * (len + 1)); /*FIXME will it leak?*/
281        r = OBJ_obj2txt(key, len, X509_EXTENSION_get_object(ext), no_name);
282 
283     } else if (no_name == 2) {
284 
285        key = (char*)OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
286        r = strlen(key);
287     }
288 
289     if (! hv_store(RETVAL, key, r, rv, 0) ) croak("Error storing extension in hash\n");
290   }
291 
292   return RETVAL;
293 }
294 
295 MODULE = Crypt::OpenSSL::X509    PACKAGE = Crypt::OpenSSL::X509
296 
297 PROTOTYPES: DISABLE
298 
299 BOOT:
300 {
301   HV *stash = gv_stashpvn("Crypt::OpenSSL::X509", 20, TRUE);
302 
303   struct { char *n; I32 v; } Crypt__OpenSSL__X509__const[] = {
304 
305   {"OPENSSL_VERSION_NUMBER", OPENSSL_VERSION_NUMBER},
306   {"FORMAT_UNDEF", FORMAT_UNDEF},
307   {"FORMAT_ASN1", FORMAT_ASN1},
308   {"FORMAT_TEXT", FORMAT_TEXT},
309   {"FORMAT_PEM", FORMAT_PEM},
310   {"FORMAT_PKCS12", FORMAT_PKCS12},
311   {"FORMAT_SMIME", FORMAT_SMIME},
312   {"FORMAT_ENGINE", FORMAT_ENGINE},
313   {"FORMAT_IISSGC", FORMAT_IISSGC},
314   {"V_ASN1_PRINTABLESTRING",  V_ASN1_PRINTABLESTRING},
315   {"V_ASN1_UTF8STRING",  V_ASN1_UTF8STRING},
316   {"V_ASN1_IA5STRING",  V_ASN1_IA5STRING},
317   {Nullch,0}};
318 
319   char *name;
320   int i;
321 
322   for (i = 0; (name = Crypt__OpenSSL__X509__const[i].n); i++) {
323     newCONSTSUB(stash, name, newSViv(Crypt__OpenSSL__X509__const[i].v));
324   }
325 
326   ERR_load_crypto_strings();
327   OPENSSL_add_all_algorithms_conf();
328 }
329 
330 Crypt::OpenSSL::X509
331 new(class)
332   SV  *class
333 
334   CODE:
335 
336   if ((RETVAL = X509_new()) == NULL) {
337     croak("X509_new");
338   }
339 
340   if (!X509_set_version(RETVAL, 2)) {
341     X509_free(RETVAL);
342     croak ("%s - can't X509_set_version()", SvPV_nolen(class));
343   }
344 
345   ASN1_INTEGER_set(X509_get_serialNumber(RETVAL), 0L);
346 
347   OUTPUT:
348   RETVAL
349 
350 Crypt::OpenSSL::X509
351 new_from_string(class, string, format = FORMAT_PEM)
352   SV  *class
353   SV  *string
354   int  format
355 
356   ALIAS:
357   new_from_file = 1
358 
359   PREINIT:
360   BIO *bio;
361   STRLEN len;
362   char *cert;
363 
364   CODE:
365 
366   cert = SvPV(string, len);
367 
368   if (ix == 1) {
369     bio = BIO_new_file(cert, "r");
370   } else {
371     bio = BIO_new_mem_buf(cert, len);
372   }
373 
374   if (!bio) croak("%s: Failed to create BIO", SvPV_nolen(class));
375 
376   /* this can come in any number of ways */
377   if (format == FORMAT_ASN1) {
378 
379     RETVAL = (X509*)d2i_X509_bio(bio, NULL);
380 
381   } else {
382 
383     RETVAL = (X509*)PEM_read_bio_X509(bio, NULL, NULL, NULL);
384   }
385 
386   BIO_free_all(bio);
387 
388   if (!RETVAL) croak("%s: failed to read X509 certificate.", SvPV_nolen(class));
389 
390   OUTPUT:
391   RETVAL
392 
393 void
394 DESTROY(x509)
395   Crypt::OpenSSL::X509 x509;
396 
397   PPCODE:
398 
399   if (x509) X509_free(x509); x509 = 0;
400 
401 # This is called via an END block in the Perl module to clean up initialization that happened in BOOT.
402 void
403 __X509_cleanup(void)
404   PPCODE:
405 
406   CRYPTO_cleanup_all_ex_data();
407   ERR_free_strings();
408 #if OPENSSL_VERSION_NUMBER < 0x10100000
409   ERR_remove_state(0);
410 #endif
411   EVP_cleanup();
412 
413 SV*
414 accessor(x509)
415   Crypt::OpenSSL::X509 x509;
416 
417   ALIAS:
418   subject = 1
419   issuer  = 2
420   serial  = 3
421   hash    = 4
422   subject_hash = 4
423   notBefore = 5
424   notAfter  = 6
425   email     = 7
426   version   = 8
427   sig_alg_name = 9
428   key_alg_name = 10
429   issuer_hash = 11
430 
431   PREINIT:
432   BIO *bio;
433   X509_NAME *name;
434 
435   CODE:
436 
437   bio = sv_bio_create();
438 
439   /* this includes both subject and issuer since they are so much alike */
440   if (ix == 1 || ix == 2) {
441 
442     if (ix == 1) {
443       name = X509_get_subject_name(x509);
444     } else {
445       name = X509_get_issuer_name(x509);
446     }
447 
448     /* this is prefered over X509_NAME_oneline() */
449     X509_NAME_print_ex(bio, name, 0, (XN_FLAG_SEP_CPLUS_SPC | ASN1_STRFLGS_UTF8_CONVERT) & ~ASN1_STRFLGS_ESC_MSB);
450 
451     /* this need not be pure ascii, try to get a native perl character string with * utf8 */
452     sv_bio_utf8_on(bio);
453 
454   } else if (ix == 3) {
455 
456     i2a_ASN1_INTEGER(bio, X509_get0_serialNumber(x509));
457 
458   } else if (ix == 4) {
459 
460     BIO_printf(bio, "%08lx", X509_subject_name_hash(x509));
461 
462   } else if (ix == 5) {
463 
464     ASN1_TIME_print(bio, X509_get_notBefore(x509));
465 
466   } else if (ix == 6) {
467 
468     ASN1_TIME_print(bio, X509_get_notAfter(x509));
469 
470   } else if (ix == 7) {
471 
472     int j;
473     STACK_OF(OPENSSL_STRING) *emlst = X509_get1_email(x509);
474 
475     for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) {
476       BIO_printf(bio, "%s%s", (j ? " " : ""), sk_OPENSSL_STRING_value(emlst, j));
477     }
478 
479     X509_email_free(emlst);
480 
481   } else if (ix == 8) {
482 
483     BIO_printf(bio, "%02ld", X509_get_version(x509));
484 
485   } else if (ix == 9) {
486     const_ossl11 X509_ALGOR *palg;
487     const_ossl11 ASN1_OBJECT *paobj;
488 
489     X509_get0_signature(NULL, &palg, x509);
490     X509_ALGOR_get0(&paobj, NULL, NULL, palg);
491 
492     i2a_ASN1_OBJECT(bio, paobj);
493   } else if ( ix == 10 ) {
494     X509_PUBKEY *pkey;
495     ASN1_OBJECT *ppkalg;
496 
497     pkey = X509_get_X509_PUBKEY(x509);
498     X509_PUBKEY_get0_param(&ppkalg, NULL, NULL, NULL, pkey);
499 
500     i2a_ASN1_OBJECT(bio, ppkalg);
501   } else if ( ix == 11 ) {
502     BIO_printf(bio, "%08lx", X509_issuer_name_hash(x509));
503   }
504 
505   RETVAL = sv_bio_final(bio);
506 
507   OUTPUT:
508   RETVAL
509 
510 Crypt::OpenSSL::X509::Name
511 subject_name(x509)
512   Crypt::OpenSSL::X509 x509;
513 
514   ALIAS:
515   subject_name = 1
516   issuer_name  = 2
517 
518   CODE:
519   if (ix == 1) {
520     RETVAL = X509_get_subject_name(x509);
521   } else {
522     RETVAL = X509_get_issuer_name(x509);
523   }
524 
525   OUTPUT:
526   RETVAL
527 
528 SV*
529 sig_print(x509)
530   Crypt::OpenSSL::X509 x509;
531 
532   PREINIT:
533   BIO *bio;
534   unsigned char *s;
535   const_ossl11 ASN1_BIT_STRING *psig;
536   int n,i;
537 
538   CODE:
539 
540   X509_get0_signature(&psig, NULL, x509);
541   n   = psig->length;
542   s   = psig->data;
543   bio = sv_bio_create();
544 
545   for (i=0; i<n; i++) {
546     BIO_printf(bio, "%02x", s[i]);
547   }
548 
549   RETVAL = sv_bio_final(bio);
550   OUTPUT:
551   RETVAL
552 
553 SV*
554 as_string(x509, format = FORMAT_PEM)
555   Crypt::OpenSSL::X509 x509;
556   int format;
557 
558   PREINIT:
559   BIO *bio;
560 
561   CODE:
562 
563   bio = sv_bio_create();
564 
565   /* get the certificate back out in a specified format. */
566 
567   if (format == FORMAT_PEM) {
568 
569     PEM_write_bio_X509(bio, x509);
570 
571   } else if (format == FORMAT_ASN1) {
572 
573     i2d_X509_bio(bio, x509);
574 
575   }
576 
577   RETVAL = sv_bio_final(bio);
578 
579   OUTPUT:
580   RETVAL
581 
582 SV*
583 bit_length(x509)
584   Crypt::OpenSSL::X509 x509;
585 
586   PREINIT:
587   EVP_PKEY *pkey;
588   DSA *dsa_pkey;
589   RSA *rsa_pkey;
590   EC_KEY *ec_pkey;
591   const BIGNUM *p;
592   const BIGNUM *n;
593   int length;
594 
595   CODE:
596   pkey = X509_extract_key(x509);
597   if (pkey == NULL) {
598     EVP_PKEY_free(pkey);
599     croak("Public key is unavailable\n");
600   }
601 
602   switch(EVP_PKEY_base_id(pkey)) {
603     case EVP_PKEY_RSA:
604       rsa_pkey = EVP_PKEY_get0_RSA(pkey);
605       RSA_get0_key(rsa_pkey, &n, NULL, NULL);
606       length = BN_num_bits(n);
607       break;
608     case EVP_PKEY_DSA:
609       dsa_pkey = EVP_PKEY_get0_DSA(pkey);
610       DSA_get0_pqg(dsa_pkey, &p, NULL, NULL);
611       length = BN_num_bits(p);
612       break;
613 #ifndef OPENSSL_NO_EC
614     case EVP_PKEY_EC:
615     {
616       const EC_GROUP *group;
617       BIGNUM* ec_order;
618       ec_order = BN_new();
619       if ( !ec_order ) {
620         EVP_PKEY_free(pkey);
621         croak("Could not malloc bignum");
622       }
623       ec_pkey = EVP_PKEY_get0_EC_KEY(pkey);
624       if ( (group = EC_KEY_get0_group(ec_pkey)) == NULL) {
625         EVP_PKEY_free(pkey);
626         croak("No EC group");
627       }
628       /* */
629       if (!EC_GROUP_get_order(group, ec_order, NULL)) {
630         EVP_PKEY_free(pkey);
631         croak("Could not get ec-group order");
632       }
633       length = BN_num_bits(ec_order);
634       /* */
635       BN_free(ec_order);
636       break;
637     }
638 #endif
639     default:
640       EVP_PKEY_free(pkey);
641       croak("Unknown public key type");
642   }
643 
644   RETVAL = newSVuv(length);
645 
646   OUTPUT:
647   RETVAL
648 
649 const char*
650 curve(x509)
651   Crypt::OpenSSL::X509 x509;
652 
653   PREINIT:
654 #ifndef OPENSSL_NO_EC
655   EVP_PKEY *pkey;
656 #endif
657 
658   CODE:
659 #ifdef OPENSSL_NO_EC
660   if ( x509 ) {} /* fix unused variable warning. */
661   croak("OpenSSL without EC-support");
662 #else
663   pkey = X509_extract_key(x509);
664   if (pkey == NULL) {
665     EVP_PKEY_free(pkey);
666     croak("Public key is unavailable\n");
667   }
668   if ( EVP_PKEY_base_id(pkey) == EVP_PKEY_EC ) {
669     const EC_GROUP *group;
670     EC_KEY *ec_pkey;
671     int nid;
672     ec_pkey = EVP_PKEY_get0_EC_KEY(pkey);
673     if ( (group = EC_KEY_get0_group(ec_pkey)) == NULL) {
674        EVP_PKEY_free(pkey);
675        croak("No EC group");
676     }
677     nid = EC_GROUP_get_curve_name(group);
678     if ( nid == 0 ) {
679        EVP_PKEY_free(pkey);
680        croak("invalid nid");
681     }
682     RETVAL = OBJ_nid2sn(nid);
683   } else {
684     EVP_PKEY_free(pkey);
685     croak("Wrong Algorithm type\n");
686   }
687   EVP_PKEY_free(pkey);
688 #endif
689 
690   OUTPUT:
691   RETVAL
692 
693 
694 SV*
695 modulus(x509)
696   Crypt::OpenSSL::X509 x509;
697 
698   PREINIT:
699   EVP_PKEY *pkey;
700   BIO *bio;
701   int pkey_id;
702 
703   CODE:
704 
705   pkey = X509_extract_key(x509);
706   bio  = sv_bio_create();
707 
708   if (pkey == NULL) {
709 
710     BIO_free_all(bio);
711     EVP_PKEY_free(pkey);
712     croak("Modulus is unavailable\n");
713   }
714 
715   pkey_id = EVP_PKEY_base_id(pkey);
716   if (pkey_id == EVP_PKEY_RSA) {
717     RSA *rsa_pkey;
718     const BIGNUM *n;
719 
720     rsa_pkey = EVP_PKEY_get0_RSA(pkey);
721     RSA_get0_key(rsa_pkey, &n, NULL, NULL);
722 
723     BN_print(bio, n);
724 
725   } else if (pkey_id == EVP_PKEY_DSA) {
726     DSA *dsa_pkey;
727     const BIGNUM *pub_key;
728 
729     dsa_pkey = EVP_PKEY_get0_DSA(pkey);
730     DSA_get0_key(dsa_pkey, &pub_key, NULL);
731     BN_print(bio, pub_key);
732 #ifndef OPENSSL_NO_EC
733   } else if ( pkey_id == EVP_PKEY_EC ) {
734     const EC_POINT *public_key;
735     const EC_GROUP *group;
736     EC_KEY *ec_pkey;
737     BIGNUM  *pub_key=NULL;
738 
739     ec_pkey = EVP_PKEY_get0_EC_KEY(pkey);
740     if ( (group = EC_KEY_get0_group(ec_pkey)) == NULL) {
741        BIO_free_all(bio);
742        EVP_PKEY_free(pkey);
743        croak("No EC group");
744     }
745     public_key = EC_KEY_get0_public_key(ec_pkey);
746     if ((pub_key = EC_POINT_point2bn(group, public_key, EC_KEY_get_conv_form(ec_pkey), NULL, NULL)) == NULL) {
747        BIO_free_all(bio);
748        EVP_PKEY_free(pkey);
749        croak("EC library error");
750     }
751     BN_print(bio, pub_key);
752 #endif
753   } else {
754 
755     BIO_free_all(bio);
756     EVP_PKEY_free(pkey);
757     croak("Wrong Algorithm type\n");
758   }
759 
760   RETVAL = sv_bio_final(bio);
761 
762   EVP_PKEY_free(pkey);
763 
764   OUTPUT:
765   RETVAL
766 
767 SV*
768 exponent(x509)
769   Crypt::OpenSSL::X509 x509;
770 
771   PREINIT:
772   EVP_PKEY *pkey;
773   BIO *bio;
774 
775   ALIAS:
776   pub_exponent = 1
777 
778   CODE:
779   pkey = X509_get_pubkey(x509);
780   bio  = sv_bio_create();
781 
782   /* Silence warning */
783   if (ix)
784 
785   if (pkey == NULL) {
786     BIO_free_all(bio);
787     EVP_PKEY_free(pkey);
788     croak("Exponent is unavailable\n");
789   }
790 
791   if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) {
792     RSA *rsa_pkey;
793     const BIGNUM *e;
794 
795     rsa_pkey = EVP_PKEY_get0_RSA(pkey);
796     RSA_get0_key(rsa_pkey, NULL, &e, NULL);
797 
798     BN_print(bio, e);
799   } else {
800     BIO_free_all(bio);
801     EVP_PKEY_free(pkey);
802     croak("Wrong Algorithm type -- exponent only available with RSA\n");
803   }
804 
805   RETVAL = sv_bio_final(bio);
806 
807   EVP_PKEY_free(pkey);
808 
809   OUTPUT:
810   RETVAL
811 
812 SV*
813 fingerprint_md5(x509)
814   Crypt::OpenSSL::X509 x509;
815 
816   ALIAS:
817   fingerprint_sha1 = 1
818   fingerprint_sha224 = 2
819   fingerprint_sha256 = 3
820   fingerprint_sha384 = 4
821   fingerprint_sha512 = 5
822 
823   PREINIT:
824 
825   const EVP_MD *mds[] = { EVP_md5(), EVP_sha1(), EVP_sha224(), EVP_sha256(), EVP_sha384(), EVP_sha512() };
826   unsigned char md[EVP_MAX_MD_SIZE];
827   int i;
828   unsigned int n;
829   BIO *bio;
830 
831   CODE:
832 
833   bio = sv_bio_create();
834 
835   if (!X509_digest(x509, mds[ix], md, &n)) {
836 
837     BIO_free_all(bio);
838     croak("Digest error: %s", ssl_error());
839   }
840 
841   BIO_printf(bio, "%02X", md[0]);
842   for (i = 1; i < n; i++) {
843     BIO_printf(bio, ":%02X", md[i]);
844   }
845 
846   RETVAL = sv_bio_final(bio);
847 
848   OUTPUT:
849   RETVAL
850 
851 SV*
852 checkend(x509, checkoffset)
853   Crypt::OpenSSL::X509 x509;
854   IV checkoffset;
855 
856   PREINIT:
857   time_t now;
858 
859   CODE:
860 
861   now = time(NULL);
862 
863   /* given an offset in seconds, will the certificate be expired? */
864   if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(x509), now + (int)checkoffset) == -1) {
865     RETVAL = &PL_sv_yes;
866   } else {
867     RETVAL = &PL_sv_no;
868   }
869 
870   OUTPUT:
871   RETVAL
872 
873 SV*
874 pubkey(x509)
875   Crypt::OpenSSL::X509 x509;
876 
877   PREINIT:
878   EVP_PKEY *pkey;
879   BIO *bio;
880   int pkey_id;
881 
882   CODE:
883 
884   pkey = X509_get_pubkey(x509);
885   bio  = sv_bio_create();
886 
887   if (pkey == NULL) {
888 
889     BIO_free_all(bio);
890     EVP_PKEY_free(pkey);
891     croak("Public Key is unavailable\n");
892   }
893 
894   pkey_id = EVP_PKEY_base_id(pkey);
895   if (pkey_id == EVP_PKEY_RSA) {
896     RSA *rsa_pkey;
897 
898     rsa_pkey = EVP_PKEY_get0_RSA(pkey);
899     PEM_write_bio_RSAPublicKey(bio, rsa_pkey);
900 
901   } else if (pkey_id == EVP_PKEY_DSA) {
902     DSA *dsa_pkey;
903 
904     dsa_pkey = EVP_PKEY_get0_DSA(pkey);
905 
906     PEM_write_bio_DSA_PUBKEY(bio, dsa_pkey);
907 #ifndef OPENSSL_NO_EC
908   } else if (pkey_id == EVP_PKEY_EC ) {
909     EC_KEY *ec_pkey;
910 
911     ec_pkey = EVP_PKEY_get0_EC_KEY(pkey);
912     PEM_write_bio_EC_PUBKEY(bio, ec_pkey);
913 #endif
914   } else {
915 
916     BIO_free_all(bio);
917     EVP_PKEY_free(pkey);
918     croak("Wrong Algorithm type\n");
919   }
920 
921   EVP_PKEY_free(pkey);
922 
923   RETVAL = sv_bio_final(bio);
924 
925   OUTPUT:
926   RETVAL
927 
928 char*
929 pubkey_type(x509)
930         Crypt::OpenSSL::X509 x509;
931     PREINIT:
932         EVP_PKEY *pkey;
933 	int pkey_id;
934     CODE:
935         RETVAL=NULL;
936         pkey = X509_get_pubkey(x509);
937 
938         if(!pkey)
939             XSRETURN_UNDEF;
940 
941 	pkey_id = EVP_PKEY_base_id(pkey);
942         if (pkey_id == EVP_PKEY_DSA) {
943             RETVAL="dsa";
944 
945         } else if (pkey_id == EVP_PKEY_RSA) {
946             RETVAL="rsa";
947 #ifndef OPENSSL_NO_EC
948         } else if (pkey_id == EVP_PKEY_EC ) {
949             RETVAL="ec";
950 #endif
951         }
952 
953     OUTPUT:
954     RETVAL
955 
956 int
957 num_extensions(x509)
958   Crypt::OpenSSL::X509 x509;
959 
960   CODE:
961   RETVAL = X509_get_ext_count(x509);
962 
963   OUTPUT:
964   RETVAL
965 
966 Crypt::OpenSSL::X509::Extension
967 extension(x509, i)
968   Crypt::OpenSSL::X509 x509;
969   int i;
970 
971   PREINIT:
972   X509_EXTENSION *ext;
973   int c;
974 
975   CODE:
976   ext = NULL;
977 
978   c = X509_get_ext_count(x509);
979 
980   if (!(c > 0)) {
981     croak("No extensions found\n");
982   } else if (i >= c || i < 0) {
983     croak("Requested extension index out of range\n");
984   } else {
985     ext = X509_get_ext(x509, i);
986   }
987 
988   if (ext == NULL) {
989     /* X509_EXTENSION_free(ext); // not needed? */
990     croak("Extension unavailable\n");
991   }
992 
993   RETVAL = ext;
994 
995   OUTPUT:
996   RETVAL
997 
998 HV*
999 extensions(x509)
1000   Crypt::OpenSSL::X509 x509
1001 
1002   ALIAS:
1003   extensions_by_long_name = 0
1004   extensions_by_oid = 1
1005   extensions_by_name = 2
1006 
1007   CODE:
1008   RETVAL = hv_exts(x509, ix);
1009 
1010   OUTPUT:
1011   RETVAL
1012 
1013 MODULE = Crypt::OpenSSL::X509    PACKAGE = Crypt::OpenSSL::X509::Extension
1014 
1015 int
1016 critical(ext)
1017   Crypt::OpenSSL::X509::Extension ext;
1018 
1019   CODE:
1020 
1021   if (ext == NULL) {
1022     croak("No extension supplied\n");
1023   }
1024 
1025   RETVAL = X509_EXTENSION_get_critical(ext);
1026 
1027   OUTPUT:
1028   RETVAL
1029 
1030 Crypt::OpenSSL::X509::ObjectID
1031 object(ext)
1032   Crypt::OpenSSL::X509::Extension ext;
1033 
1034   CODE:
1035 
1036   if (ext == NULL) {
1037     croak("No extension supplied\n");
1038   }
1039 
1040   RETVAL = X509_EXTENSION_get_object(ext);
1041 
1042   OUTPUT:
1043   RETVAL
1044 
1045 SV*
1046 value(ext)
1047   Crypt::OpenSSL::X509::Extension ext;
1048 
1049   PREINIT:
1050   BIO* bio;
1051 
1052   CODE:
1053   bio  = sv_bio_create();
1054 
1055   if (ext == NULL) {
1056     BIO_free_all(bio);
1057     croak("No extension supplied\n");
1058   }
1059 
1060   ASN1_STRING_print_ex(bio, X509_EXTENSION_get_data(ext), ASN1_STRFLGS_DUMP_ALL);
1061 
1062   RETVAL = sv_bio_final(bio);
1063 
1064   OUTPUT:
1065   RETVAL
1066 
1067 SV*
1068 to_string(ext)
1069   Crypt::OpenSSL::X509::Extension ext;
1070 
1071   PREINIT:
1072   BIO* bio;
1073 
1074   CODE:
1075   bio = sv_bio_create();
1076 
1077   if (ext == NULL) {
1078     BIO_free_all(bio);
1079     croak("No extension supplied\n");
1080   }
1081 
1082   X509V3_EXT_print(bio, ext, 0, 0);
1083 
1084   RETVAL = sv_bio_final(bio);
1085 
1086   OUTPUT:
1087   RETVAL
1088 
1089 int
1090 basicC(ext, value)
1091   Crypt::OpenSSL::X509::Extension ext;
1092   char *value;
1093 
1094   PREINIT:
1095   BASIC_CONSTRAINTS *bs;
1096   int ret = 0;
1097 
1098   CODE:
1099 
1100   /* retrieve the value of CA or pathlen in basicConstraints */
1101   bs = X509V3_EXT_d2i(ext);
1102 
1103   if (strcmp(value, "ca") == 0) {
1104     ret = bs->ca ? 1 : 0;
1105 
1106   } else if (strcmp(value, "pathlen") == 0) {
1107     ret = bs->pathlen ? 1 : 0;
1108   }
1109 
1110   BASIC_CONSTRAINTS_free(bs);
1111 
1112   RETVAL = ret;
1113 
1114   OUTPUT:
1115   RETVAL
1116 
1117 SV*
1118 ia5string(ext)
1119   Crypt::OpenSSL::X509::Extension ext;
1120 
1121   PREINIT:
1122   ASN1_IA5STRING *str;
1123   BIO *bio;
1124 
1125   CODE:
1126 
1127   /* retrieving the value of an ia5string object */
1128   bio = sv_bio_create();
1129   str = X509V3_EXT_d2i(ext);
1130   BIO_printf(bio,"%s", str->data);
1131   ASN1_IA5STRING_free(str);
1132 
1133   RETVAL = sv_bio_final(bio);
1134 
1135   OUTPUT:
1136   RETVAL
1137 
1138 SV*
1139 bit_string(ext)
1140   Crypt::OpenSSL::X509::Extension ext;
1141 
1142   PREINIT:
1143   int i, nid;
1144   ASN1_OBJECT *object;
1145   ASN1_BIT_STRING *bit_str;
1146   int string[10];
1147   BIO *bio;
1148 
1149   CODE:
1150   bio = sv_bio_create();
1151 
1152   object = X509_EXTENSION_get_object(ext);
1153   nid = OBJ_obj2nid(object);
1154   bit_str = X509V3_EXT_d2i(ext);
1155 
1156   if (nid == NID_key_usage) {
1157 
1158     for (i = 0; i < 9; i++) {
1159       string[i] = (int)ASN1_BIT_STRING_get_bit(bit_str, i);
1160       BIO_printf(bio, "%d", string[i]);
1161     }
1162 
1163   } else if (nid == NID_netscape_cert_type) {
1164 
1165     for (i = 0; i < 8; i++) {
1166       string[i] = (int)ASN1_BIT_STRING_get_bit(bit_str, i);
1167       BIO_printf(bio, "%d",  string[i]);
1168     }
1169   }
1170 
1171   RETVAL = sv_bio_final(bio);
1172 
1173   OUTPUT:
1174   RETVAL
1175 
1176 SV*
1177 extendedKeyUsage(ext)
1178   Crypt::OpenSSL::X509::Extension ext;
1179 
1180   PREINIT:
1181   BIO *bio;
1182   STACK_OF(ASN1_OBJECT) *extku;
1183   int nid;
1184   const char *value;
1185 
1186   CODE:
1187 
1188   bio   = sv_bio_create();
1189   extku = (STACK_OF(ASN1_OBJECT)*) X509V3_EXT_d2i(ext);
1190 
1191   while(sk_ASN1_OBJECT_num(extku) > 0) {
1192     nid = OBJ_obj2nid(sk_ASN1_OBJECT_pop(extku));
1193     value = OBJ_nid2sn(nid);
1194     BIO_printf(bio, "%s", value);
1195     BIO_printf(bio, " ");
1196   }
1197 
1198   RETVAL = sv_bio_final(bio);
1199 
1200   OUTPUT:
1201   RETVAL
1202 
1203 int
1204 auth_att(ext)
1205   Crypt::OpenSSL::X509::Extension ext;
1206 
1207   PREINIT:
1208   AUTHORITY_KEYID *akid;
1209 
1210   CODE:
1211 
1212   akid   = X509V3_EXT_d2i(ext);
1213   RETVAL = akid->keyid ? 1 : 0;
1214 
1215   OUTPUT:
1216   RETVAL
1217 
1218 SV*
1219 keyid_data(ext)
1220   Crypt::OpenSSL::X509::Extension ext;
1221 
1222   PREINIT:
1223   AUTHORITY_KEYID *akid;
1224   ASN1_OCTET_STRING *skid;
1225   int nid;
1226   ASN1_OBJECT *object;
1227   BIO *bio;
1228 
1229   CODE:
1230 
1231   bio    = sv_bio_create();
1232   object = X509_EXTENSION_get_object(ext);
1233   nid    = OBJ_obj2nid(object);
1234 
1235   if (nid == NID_authority_key_identifier) {
1236 
1237     akid = X509V3_EXT_d2i(ext);
1238     BIO_printf(bio, "%s", akid->keyid->data);
1239 
1240   } else if (nid == NID_subject_key_identifier) {
1241 
1242     skid = X509V3_EXT_d2i(ext);
1243     BIO_printf(bio, "%s", skid->data);
1244   }
1245 
1246   RETVAL = sv_bio_final(bio);
1247 
1248   OUTPUT:
1249   RETVAL
1250 
1251 MODULE = Crypt::OpenSSL::X509    PACKAGE = Crypt::OpenSSL::X509::ObjectID
1252 char*
1253 name(obj)
1254   Crypt::OpenSSL::X509::ObjectID obj;
1255 
1256   PREINIT:
1257   char buf[128];
1258 
1259   CODE:
1260 
1261   if (obj == NULL) {
1262     croak("No ObjectID supplied\n");
1263   }
1264 
1265   (void)OBJ_obj2txt(buf, 128, obj, 0);
1266 
1267   RETVAL = buf;
1268 
1269   OUTPUT:
1270   RETVAL
1271 
1272 char*
1273 oid(obj)
1274   Crypt::OpenSSL::X509::ObjectID obj;
1275 
1276   PREINIT:
1277   char buf[128];
1278 
1279   CODE:
1280 
1281   if (obj == NULL) {
1282     croak("No ObjectID supplied\n");
1283   }
1284 
1285   (void)OBJ_obj2txt(buf, 128, obj, 1);
1286 
1287   RETVAL = buf;
1288 
1289   OUTPUT:
1290   RETVAL
1291 
1292 MODULE = Crypt::OpenSSL::X509    PACKAGE = Crypt::OpenSSL::X509::Name
1293 
1294 SV*
1295 as_string(name)
1296   Crypt::OpenSSL::X509::Name name;
1297 
1298   PREINIT:
1299   BIO *bio;
1300 
1301   CODE:
1302 
1303   bio = sv_bio_create();
1304   /* this is prefered over X509_NAME_oneline() */
1305   X509_NAME_print_ex(bio, name, 0, XN_FLAG_SEP_CPLUS_SPC);
1306 
1307   RETVAL = sv_bio_final(bio);
1308 
1309   OUTPUT:
1310   RETVAL
1311 
1312 AV*
1313 entries(name)
1314   Crypt::OpenSSL::X509::Name name;
1315 
1316   PREINIT:
1317   int i, c;
1318   SV* rv;
1319 
1320   CODE:
1321 
1322   RETVAL = newAV();
1323   sv_2mortal((SV*)RETVAL);
1324 
1325   c = X509_NAME_entry_count(name);
1326 
1327   for (i = 0; i < c; i++) {
1328     rv = sv_make_ref("Crypt::OpenSSL::X509::Name_Entry", (void*)X509_NAME_get_entry(name, i));
1329     av_push(RETVAL, rv);
1330   }
1331 
1332   OUTPUT:
1333   RETVAL
1334 
1335 int
1336 get_index_by_type(name, type, lastpos = -1)
1337   Crypt::OpenSSL::X509::Name name;
1338   const char* type;
1339   int lastpos;
1340 
1341   ALIAS:
1342   get_index_by_long_type = 1
1343   has_entry = 2
1344   has_long_entry = 3
1345   has_oid_entry = 4
1346   get_index_by_oid_type = 5
1347 
1348   PREINIT:
1349   int nid, i;
1350 
1351   CODE:
1352 
1353   if (ix == 1 || ix == 3) {
1354     nid = OBJ_ln2nid(type);
1355   } else if (ix == 4 || ix == 5) {
1356     nid = OBJ_obj2nid(OBJ_txt2obj(type, /*oid*/ 1));
1357   } else {
1358     nid = OBJ_sn2nid(type);
1359   }
1360 
1361   if (!nid) {
1362     croak("Unknown type");
1363   }
1364 
1365   i = X509_NAME_get_index_by_NID(name, nid, lastpos);
1366 
1367   if (ix == 2 || ix == 3 || ix == 4) { /* has_entry */
1368     RETVAL = (i > lastpos)?1:0;
1369   } else { /* get_index */
1370     RETVAL = i;
1371   }
1372 
1373   OUTPUT:
1374   RETVAL
1375 
1376 Crypt::OpenSSL::X509::Name_Entry
1377 get_entry_by_type(name, type, lastpos = -1)
1378   Crypt::OpenSSL::X509::Name name;
1379   const char* type;
1380   int lastpos;
1381 
1382   ALIAS:
1383   get_entry_by_long_type = 1
1384 
1385   PREINIT:
1386   int nid, i;
1387 
1388   CODE:
1389 
1390   if (ix == 1) {
1391     nid = OBJ_ln2nid(type);
1392   } else {
1393     nid = OBJ_sn2nid(type);
1394   }
1395 
1396   if (!nid) {
1397     croak("Unknown type");
1398   }
1399 
1400   i = X509_NAME_get_index_by_NID(name, nid, lastpos);
1401   RETVAL = X509_NAME_get_entry(name, i);
1402 
1403   OUTPUT:
1404   RETVAL
1405 
1406 
1407 MODULE = Crypt::OpenSSL::X509    PACKAGE = Crypt::OpenSSL::X509::Name_Entry
1408 
1409 SV*
1410 as_string(name_entry, ln = 0)
1411   Crypt::OpenSSL::X509::Name_Entry name_entry;
1412   int ln;
1413 
1414   ALIAS:
1415   as_long_string = 1
1416 
1417   PREINIT:
1418   BIO *bio;
1419   const char *n;
1420   int nid;
1421 
1422   CODE:
1423   bio = sv_bio_create();
1424   nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(name_entry));
1425 
1426   if (ix == 1 || ln) {
1427     n = OBJ_nid2ln(nid);
1428   } else {
1429     n = OBJ_nid2sn(nid);
1430   }
1431 
1432   BIO_printf(bio, "%s=", n);
1433 
1434   ASN1_STRING_print_ex(bio, X509_NAME_ENTRY_get_data(name_entry), ASN1_STRFLGS_UTF8_CONVERT & ~ASN1_STRFLGS_ESC_MSB);
1435 
1436   sv_bio_utf8_on(bio);
1437 
1438   RETVAL = sv_bio_final(bio);
1439 
1440   OUTPUT:
1441   RETVAL
1442 
1443 SV*
1444 type(name_entry, ln = 0)
1445   Crypt::OpenSSL::X509::Name_Entry name_entry;
1446   int ln;
1447 
1448   ALIAS:
1449   long_type = 1
1450 
1451   PREINIT:
1452   BIO *bio;
1453   const char *n;
1454   int nid;
1455 
1456   CODE:
1457   bio = sv_bio_create();
1458   nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(name_entry));
1459 
1460   if (ix == 1 || ln) {
1461     n = OBJ_nid2ln(nid);
1462   } else {
1463     n = OBJ_nid2sn(nid);
1464   }
1465 
1466   BIO_printf(bio, "%s", n);
1467   RETVAL = sv_bio_final(bio);
1468 
1469   OUTPUT:
1470   RETVAL
1471 
1472 SV*
1473 value(name_entry)
1474   Crypt::OpenSSL::X509::Name_Entry name_entry;
1475 
1476   PREINIT:
1477   BIO *bio;
1478 
1479   CODE:
1480   bio = sv_bio_create();
1481   ASN1_STRING_print(bio, X509_NAME_ENTRY_get_data(name_entry));
1482   RETVAL = sv_bio_final(bio);
1483 
1484   OUTPUT:
1485   RETVAL
1486 
1487 int
1488 is_printableString(name_entry, asn1_type =  V_ASN1_PRINTABLESTRING)
1489   Crypt::OpenSSL::X509::Name_Entry name_entry;
1490   int asn1_type;
1491 
1492   ALIAS:
1493   is_asn1_type = 1
1494   is_printableString = V_ASN1_PRINTABLESTRING
1495   is_ia5string = V_ASN1_IA5STRING
1496   is_utf8string = V_ASN1_UTF8STRING
1497 
1498   CODE:
1499   RETVAL = (X509_NAME_ENTRY_get_data(name_entry)->type == (ix == 1 ? asn1_type : ix));
1500 
1501   OUTPUT:
1502   RETVAL
1503 
1504 char*
1505 encoding(name_entry)
1506   Crypt::OpenSSL::X509::Name_Entry name_entry;
1507 
1508   CODE:
1509   RETVAL = NULL;
1510 
1511   if (X509_NAME_ENTRY_get_data(name_entry)->type == V_ASN1_PRINTABLESTRING) {
1512     RETVAL = "printableString";
1513 
1514   } else if(X509_NAME_ENTRY_get_data(name_entry)->type == V_ASN1_IA5STRING) {
1515     RETVAL = "ia5String";
1516 
1517   } else if(X509_NAME_ENTRY_get_data(name_entry)->type == V_ASN1_UTF8STRING) {
1518     RETVAL = "utf8String";
1519   }
1520 
1521   OUTPUT:
1522   RETVAL
1523 
1524 MODULE = Crypt::OpenSSL::X509       PACKAGE = Crypt::OpenSSL::X509_CRL
1525 
1526 Crypt::OpenSSL::X509::CRL
1527 new_from_crl_string(class, string, format = FORMAT_PEM)
1528   SV  *class;
1529   SV  *string;
1530   int format;
1531 
1532   ALIAS:
1533   new_from_crl_file = 1
1534 
1535   PREINIT:
1536   BIO *bio;
1537   STRLEN len;
1538   char *crl;
1539 
1540   CODE:
1541 
1542   crl = SvPV(string, len);
1543 
1544   if (ix == 1) {
1545     bio = BIO_new_file(crl, "r");
1546   } else {
1547     bio = BIO_new_mem_buf(crl, len);
1548   }
1549 
1550   if (!bio) {
1551     croak("%s: Failed to create BIO", SvPV_nolen(class));
1552   }
1553 
1554   if (format == FORMAT_ASN1) {
1555     RETVAL = (X509_CRL*)d2i_X509_CRL_bio(bio, NULL);
1556   } else {
1557     RETVAL = (X509_CRL*)PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
1558   }
1559 
1560   if (!RETVAL) {
1561     croak("%s: failed to read X509 certificate.", SvPV_nolen(class));
1562   }
1563 
1564   BIO_free(bio);
1565 
1566   OUTPUT:
1567   RETVAL
1568 
1569 SV*
1570 CRL_accessor(crl)
1571   Crypt::OpenSSL::X509::CRL crl;
1572 
1573   ALIAS:
1574   CRL_issuer = 1
1575   CRL_sig_alg_name = 2
1576 
1577   PREINIT:
1578   BIO *bio;
1579   X509_NAME *name;
1580 
1581   CODE:
1582   bio = sv_bio_create();
1583 
1584   if (ix == 1) {
1585     name = X509_CRL_get_issuer(crl);
1586     sv_bio_utf8_on(bio);
1587     X509_NAME_print_ex(bio, name, 0, (XN_FLAG_SEP_CPLUS_SPC | ASN1_STRFLGS_UTF8_CONVERT) & ~ASN1_STRFLGS_ESC_MSB);
1588 
1589   } else if (ix == 2) {
1590     const_ossl11 X509_ALGOR *palg;
1591     const_ossl11 ASN1_OBJECT *paobj;
1592 
1593     X509_CRL_get0_signature(crl, NULL, &palg);
1594     X509_ALGOR_get0(&paobj, NULL, NULL, palg);
1595 
1596     i2a_ASN1_OBJECT(bio, paobj);
1597   }
1598 
1599   RETVAL = sv_bio_final(bio);
1600 
1601   OUTPUT:
1602   RETVAL
1603