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