File Coverage

PKCS10.xs
Criterion Covered Total %
statement 189 271 69.7
branch 95 202 47.0
condition n/a
subroutine n/a
pod n/a
total 284 473 60.0


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4              
5             #include
6             #include
7              
8             #include
9             #include
10             #include
11             #include
12             #include
13              
14             #include "ppport.h"
15              
16             #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
17             #define EVP_PKEY_get0_RSA(pkey) ((pkey)->pkey.rsa)
18             #define EVP_PKEY_get0_DSA(pkey) ((pkey)->pkey.dsa)
19             #if( !defined OPENSSL_NO_EC || defined LIBRESSL_VERSION_NUMBER)
20             #define EVP_PKEY_get0_EC_KEY(pkey) ((pkey)->pkey.ec)
21             #endif
22             #endif
23              
24             typedef struct
25             {
26             X509_REQ* req;
27             EVP_PKEY *pk;
28             RSA **rsa;
29             STACK_OF(X509_EXTENSION) *exts;
30             } pkcs10Data;
31              
32             typedef struct
33             {
34             RSA* rsa;
35             int padding;
36             int hashMode;
37             } Crypt__OpenSSL__RSA;
38              
39             #define PACKAGE_NAME "Crypt::OpenSSL::PKCS10"
40             #define PACKAGE_CROAK(p_message) croak("%s", (p_message))
41             #define CHECK_NEW(p_var, p_size, p_type) \
42             if (New(0, p_var, p_size, p_type) == NULL) \
43             { PACKAGE_CROAK("unable to alloc buffer"); }
44              
45             //int add_ext_raw(STACK_OF(X509_REQUEST) *sk, int nid, unsigned char *value, int length);
46             //int add_ext(STACK_OF(X509_REQUEST) *sk, int nid, char *value);
47             X509_NAME *parse_name(char *str, long chtype, int multirdn);
48              
49             /*
50             * subject is expected to be in the format /type0=value0/type1=value1/type2=...
51             * where characters may be escaped by \
52             */
53 1           X509_NAME *parse_name(char *subject, long chtype, int multirdn)
54             {
55 1           size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
56 1           char *buf = OPENSSL_malloc(buflen);
57 1           size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
58 1           const char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *));
59 1           char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *));
60 1           int *mval = OPENSSL_malloc (max_ne * sizeof (int));
61              
62 1           char *sp = subject, *bp = buf;
63 1           int i, ne_num = 0;
64              
65 1           X509_NAME *n = NULL;
66              
67 1 50         if (!buf || !ne_types || !ne_values || !mval)
    50          
    50          
    50          
68             {
69 0           croak("malloc error\n");
70             goto error;
71             }
72              
73 1 50         if (*subject != '/')
74             {
75 0           croak("Subject does not start with '/'.\n");
76             goto error;
77             }
78 1           sp++; /* skip leading / */
79              
80             /* no multivalued RDN by default */
81 1           mval[ne_num] = 0;
82              
83 4 100         while (*sp)
84             {
85             /* collect type */
86 3           ne_types[ne_num] = bp;
87 7 50         while (*sp)
88             {
89 7 50         if (*sp == '\\') /* is there anything to escape in the type...? */
90             {
91 0 0         if (*++sp)
92 0           *bp++ = *sp++;
93             else
94             {
95 0           croak("escape character at end of string\n");
96             goto error;
97             }
98             }
99 7 100         else if (*sp == '=')
100             {
101 3           sp++;
102 3           *bp++ = '\0';
103 3           break;
104             }
105             else
106 4           *bp++ = *sp++;
107             }
108 3 50         if (!*sp)
109             {
110 0           croak("end of string encountered while processing type of subject name element #%d\n", ne_num);
111             goto error;
112             }
113 3           ne_values[ne_num] = bp;
114 11 100         while (*sp)
115             {
116 10 50         if (*sp == '\\')
117             {
118 0 0         if (*++sp)
119 0           *bp++ = *sp++;
120             else
121             {
122 0           croak("escape character at end of string\n");
123             goto error;
124             }
125             }
126 10 100         else if (*sp == '/')
127             {
128 2           sp++;
129             /* no multivalued RDN by default */
130 2           mval[ne_num+1] = 0;
131 2           break;
132             }
133 8 50         else if (*sp == '+' && multirdn)
    0          
134             {
135             /* a not escaped + signals a mutlivalued RDN */
136 0           sp++;
137 0           mval[ne_num+1] = -1;
138 0           break;
139             }
140             else
141 8           *bp++ = *sp++;
142             }
143 3           *bp++ = '\0';
144 3           ne_num++;
145             }
146              
147 1 50         if (!(n = X509_NAME_new()))
148 0           goto error;
149              
150 4 100         for (i = 0; i < ne_num; i++)
151             {
152 3 50         if (!*ne_values[i])
153             {
154 0           croak("No value provided for Subject Attribute %s, skipped\n", ne_types[i]);
155             continue;
156             }
157              
158 3 50         if (!X509_NAME_add_entry_by_txt(n, ne_types[i], chtype, (unsigned char*)ne_values[i], -1,-1,mval[i]))
159 0           goto error;
160             }
161              
162 1           OPENSSL_free(mval);
163 1           OPENSSL_free(ne_values);
164 1           OPENSSL_free(ne_types);
165 1           OPENSSL_free(buf);
166 1           return n;
167              
168             error:
169 0           X509_NAME_free(n);
170 0 0         if (ne_values)
171 0           OPENSSL_free(ne_values);
172 0 0         if (ne_types)
173 0           OPENSSL_free(ne_types);
174 0 0         if (buf)
175 0           OPENSSL_free(buf);
176 0 0         if (mval)
177 0           OPENSSL_free(mval);
178 0           return NULL;
179             }
180              
181             /* Add extension using V3 code: we can set the config file as NULL
182             * because we wont reference any other sections.
183             */
184              
185 5           int add_ext(STACK_OF(X509_EXTENSION) *sk, X509_REQ *req, int nid, char *value)
186             {
187             X509_EXTENSION *ex;
188             X509V3_CTX v3ctx;
189 5           X509V3_set_ctx(&v3ctx, NULL, NULL, req, NULL, 0);
190 5           ex = X509V3_EXT_conf_nid(NULL, &v3ctx, nid, value);
191 5 50         if (!ex)
192 0           return 0;
193 5           sk_X509_EXTENSION_push(sk, ex);
194              
195 5           return 1;
196             }
197              
198             /* Add an extention by setting the raw ASN1 octet string.
199             */
200 1           int add_ext_raw(STACK_OF(X509_EXTENSION) *sk, int nid, char *value, int length)
201             {
202             X509_EXTENSION *ex;
203             ASN1_STRING *asn;
204              
205 1           asn = ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
206 1           ASN1_OCTET_STRING_set(asn, (unsigned char *) value, length);
207              
208 1           ex = X509_EXTENSION_create_by_NID(NULL, nid, 0, asn);
209 1 50         if (!ex)
210 0           return 0;
211 1           sk_X509_EXTENSION_push(sk, ex);
212              
213 1           return 1;
214             }
215              
216              
217 4           SV* make_pkcs10_obj(SV* p_proto, X509_REQ* p_req, EVP_PKEY* p_pk, STACK_OF(X509_EXTENSION)* p_exts, RSA **p_rsa)
218             {
219             pkcs10Data* pkcs10;
220              
221 4 50         CHECK_NEW(pkcs10, 1, pkcs10Data);
222 4           pkcs10->req = p_req;
223 4           pkcs10->pk = p_pk;
224 4           pkcs10->exts = p_exts;
225 4           pkcs10->rsa = p_rsa;
226              
227 4 50         return sv_bless(
228             newRV_noinc(newSViv((IV) pkcs10)),
229             (SvROK(p_proto) ? SvSTASH(SvRV(p_proto)) : gv_stashsv(p_proto, 1)));
230             }
231              
232             /* stolen from OpenSSL.xs */
233             #if OPENSSL_VERSION_NUMBER >= 0x30000000L
234             long bio_write_cb(struct bio_st *bm, int m, const char *ptr, size_t len, int l, long x, int y, size_t *processed) {
235             #else
236 316           long bio_write_cb(struct bio_st *bm, int m, const char *ptr, int len, long x, long y) {
237             #endif
238 316 100         if (m == BIO_CB_WRITE) {
239 133           SV *sv = (SV *) BIO_get_callback_arg(bm);
240 133           sv_catpvn(sv, ptr, len);
241             }
242              
243 316 100         if (m == BIO_CB_PUTS) {
244 4           SV *sv = (SV *) BIO_get_callback_arg(bm);
245 4           len = strlen(ptr);
246 4           sv_catpvn(sv, ptr, len);
247             }
248              
249 316           return len;
250             }
251              
252 14           static BIO* sv_bio_create(void) {
253              
254 14           SV *sv = newSVpvn("",0);
255              
256             /* create an in-memory BIO abstraction and callbacks */
257 14           BIO *bio = BIO_new(BIO_s_mem());
258              
259             #if OPENSSL_VERSION_NUMBER >= 0x30000000L
260             BIO_set_callback_ex(bio, bio_write_cb);
261             #else
262 14           BIO_set_callback(bio, bio_write_cb);
263             #endif
264 14           BIO_set_callback_arg(bio, (void *)sv);
265              
266 14           return bio;
267             }
268              
269 0           static BIO *sv_bio_create_file(SV *filename)
270             {
271             STRLEN l;
272              
273 0 0         return BIO_new_file(SvPV(filename, l), "wb");
274             }
275              
276 14           static SV* sv_bio_final(BIO *bio) {
277              
278             SV* sv;
279              
280 14           BIO_flush(bio);
281 14           sv = (SV *)BIO_get_callback_arg(bio);
282 14           BIO_free_all(bio);
283              
284 14 50         if (!sv) sv = &PL_sv_undef;
285              
286 14           return sv;
287             }
288              
289             /*
290             * subject is expected to be in the format /type0=value0/type1=value1/type2=...
291             * where characters may be escaped by \
292             */
293 1           static int build_subject(X509_REQ *req, char *subject, unsigned long chtype, int multirdn)
294             {
295             X509_NAME *n;
296              
297 1 50         if (!(n = parse_name(subject, chtype, multirdn)))
298 0           return 0;
299              
300 1 50         if (!X509_REQ_set_subject_name(req, n))
301             {
302 0           X509_NAME_free(n);
303 0           return 0;
304             }
305 1           X509_NAME_free(n);
306 1           return 1;
307             }
308              
309             MODULE = Crypt::OpenSSL::PKCS10 PACKAGE = Crypt::OpenSSL::PKCS10
310              
311             PROTOTYPES: DISABLE
312              
313             BOOT:
314             {
315             /*OpenSSL_add_all_algorithms();
316             OpenSSL_add_all_ciphers();
317             OpenSSL_add_all_digests();
318             ERR_load_PEM_strings();
319             ERR_load_ASN1_strings();
320             ERR_load_crypto_strings();
321             ERR_load_X509_strings();
322             ERR_load_DSA_strings();
323             ERR_load_RSA_strings();*/
324 1           HV *stash = gv_stashpvn("Crypt::OpenSSL::PKCS10", 22, TRUE);
325              
326 1           struct { char *n; I32 v; } Crypt__OpenSSL__PKCS10__const[] = {
327              
328             {"NID_key_usage", NID_key_usage},
329             {"NID_subject_alt_name", NID_subject_alt_name},
330             {"NID_netscape_cert_type", NID_netscape_cert_type},
331             {"NID_netscape_comment", NID_netscape_comment},
332             {"NID_ext_key_usage", NID_ext_key_usage},
333             {"NID_subject_key_identifier", NID_subject_key_identifier},
334             {Nullch,0}};
335              
336             char *name;
337             int i;
338              
339 7 100         for (i = 0; (name = Crypt__OpenSSL__PKCS10__const[i].n); i++) {
340 6           newCONSTSUB(stash, name, newSViv(Crypt__OpenSSL__PKCS10__const[i].v));
341             }
342             }
343              
344             SV*
345             new(class, keylen = 1024)
346             SV *class
347             int keylen
348              
349             PREINIT:
350             X509_REQ *x;
351             EVP_PKEY *pk;
352 2 50         char *classname = SvPVutf8_nolen(class);
353              
354             CODE:
355             //CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
356 2 50         if (!RAND_status())
357 0           printf("Warning: generating random key material may take a long time\n"
358             "if the system has a poor entropy source\n");
359              
360 2 50         if ((x=X509_REQ_new()) == NULL)
361 0           croak ("%s - can't create req", classname);
362             #if OPENSSL_VERSION_NUMBER >= 0x30000000L
363             pk = EVP_RSA_gen(keylen);
364             #elif OPENSSL_VERSION_NUMBER <= 0x10000000L
365             RSA *rsa;
366             if ((pk=EVP_PKEY_new()) == NULL)
367             croak ("%s - can't create PKEY", classname);
368              
369             rsa=RSA_generate_key(keylen, RSA_F4, NULL, NULL);
370             if (!EVP_PKEY_assign_RSA(pk,rsa))
371             croak ("%s - EVP_PKEY_assign_RSA", classname);
372             #else
373 2           RSA *rsa = RSA_new();
374 2           BIGNUM *bne = BN_new();
375 2 50         if (bne == NULL)
376 0           croak ("%s - BN_new failed", classname);
377              
378 2 50         if (BN_set_word(bne, RSA_F4) != 1)
379 0           croak ("%s - BN_set_word failed", classname);
380              
381 2 50         if ((pk=EVP_PKEY_new()) == NULL)
382 0           croak ("%s - can't create PKEY", classname);
383              
384 2 50         if (!RSA_generate_key_ex(rsa, keylen, bne, NULL))
385 0           croak ("%s - RSA_generate_key_ex failed", classname);
386              
387 2 50         if (!EVP_PKEY_assign_RSA(pk,rsa))
388 0           croak ("%s - EVP_PKEY_assign_RSA", classname);
389             #endif
390 2           X509_REQ_set_pubkey(x,pk);
391 2           X509_REQ_set_version(x,0L);
392 2 50         if (!X509_REQ_sign(x,pk,EVP_sha256()))
393 0           croak ("%s - X509_REQ_sign failed", classname);
394            
395 2           RETVAL = make_pkcs10_obj(class, x, pk, NULL, NULL);
396            
397             OUTPUT:
398             RETVAL
399              
400             void
401             DESTROY(pkcs10)
402             pkcs10Data *pkcs10;
403              
404             PREINIT:
405             //BIO *bio_err;
406            
407             PPCODE:
408             //bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
409 4 100         if (pkcs10->pk) EVP_PKEY_free(pkcs10->pk); pkcs10->pk = 0;
410 4 100         if (pkcs10->rsa) *pkcs10->rsa = 0;
411 4 50         if (pkcs10->req) X509_REQ_free(pkcs10->req); pkcs10->req = 0;
412 4           Safefree(pkcs10);
413 4           CRYPTO_cleanup_all_ex_data();
414             /*CRYPTO_mem_leaks(bio_err);
415             BIO_free(bio_err);*/
416              
417             SV*
418             _new_from_rsa(class, p_rsa, priv)
419             SV *class
420             SV *p_rsa
421             SV *priv
422              
423             PREINIT:
424             Crypt__OpenSSL__RSA *rsa;
425             char *keyString;
426             STRLEN keylen;
427             BIO *bio;
428             X509_REQ *x;
429             EVP_PKEY *pk;
430 1 50         char *classname = SvPVutf8_nolen(class);
431            
432             CODE:
433              
434             // Get the private key and save it in memory
435 1 50         keyString = SvPV(priv, keylen);
436 1           bio = BIO_new_mem_buf(keyString, keylen);
437 1 50         if (bio == NULL) {
438 0           croak ("Bio is null **** \n");
439             }
440              
441             // Create the PrivateKey as EVP_PKEY
442 1           pk = PEM_read_bio_PrivateKey(bio, NULL, 0, NULL);
443 1 50         if (pk == NULL) {
444 0           croak("Failed operation error code %d\n", errno);
445             }
446              
447 1 50         if ((x=X509_REQ_new()) == NULL)
448 0           croak ("%s - can't create req", classname);
449              
450 1 50         rsa = (Crypt__OpenSSL__RSA *) SvIV(SvRV(p_rsa));
451 1           X509_REQ_set_pubkey(x,pk);
452 1           X509_REQ_set_version(x,0L);
453 1 50         if (!X509_REQ_sign(x,pk,EVP_sha256()))
454 0           croak ("%s - X509_REQ_sign", classname);
455            
456 1           RETVAL = make_pkcs10_obj(class, x, pk, NULL, &rsa->rsa);
457              
458             OUTPUT:
459             RETVAL
460              
461             int
462             sign(pkcs10)
463             pkcs10Data *pkcs10;
464              
465             PREINIT:
466              
467             CODE:
468              
469 1           RETVAL = X509_REQ_sign(pkcs10->req,pkcs10->pk,EVP_sha256());
470 1 50         if (!RETVAL)
471 0           croak ("X509_REQ_sign");
472              
473             OUTPUT:
474             RETVAL
475              
476             SV*
477             get_pem_pubkey(pkcs10)
478             pkcs10Data *pkcs10;
479              
480             PREINIT:
481             EVP_PKEY *pkey;
482             BIO *bio;
483             int type;
484              
485             CODE:
486              
487 3           pkey = X509_REQ_get_pubkey(pkcs10->req);
488 3           bio = sv_bio_create();
489              
490 3 50         if (pkey == NULL) {
491              
492 0           BIO_free_all(bio);
493 0           EVP_PKEY_free(pkey);
494 0           croak("Public Key is unavailable\n");
495             }
496              
497 3           type = EVP_PKEY_base_id(pkey);
498 3 50         if (type == EVP_PKEY_RSA) {
499 3           PEM_write_bio_PUBKEY(bio, pkey);
500 0 0         } else if (type == EVP_PKEY_DSA) {
501 0           PEM_write_bio_PUBKEY(bio, pkey);
502             #ifndef OPENSSL_NO_EC
503 0 0         } else if ( type == EVP_PKEY_EC ) {
504 0           PEM_write_bio_PUBKEY(bio, pkey);
505             #endif
506             } else {
507              
508 0           BIO_free_all(bio);
509 0           EVP_PKEY_free(pkey);
510 0           croak("Wrong Algorithm type\n");
511             }
512 3           EVP_PKEY_free(pkey);
513              
514 3           RETVAL = sv_bio_final(bio);
515              
516             OUTPUT:
517             RETVAL
518              
519             char*
520             pubkey_type(pkcs10)
521             pkcs10Data *pkcs10;
522              
523             PREINIT:
524             EVP_PKEY *pkey;
525             int type;
526              
527             CODE:
528 3           RETVAL=NULL;
529 3           pkey = X509_REQ_get_pubkey(pkcs10->req);
530              
531 3 50         if(!pkey)
532 0           XSRETURN_UNDEF;
533              
534 3           type = EVP_PKEY_base_id(pkey);
535 3 50         if (type == EVP_PKEY_DSA) {
536 0           RETVAL="dsa";
537              
538 3 50         } else if (type == EVP_PKEY_RSA) {
539 3           RETVAL="rsa";
540             #ifndef OPENSSL_NO_EC
541 0 0         } else if ( type == EVP_PKEY_EC ) {
542 0           RETVAL="ec";
543             #endif
544             }
545              
546             OUTPUT:
547             RETVAL
548              
549             SV*
550             get_pem_req(pkcs10,...)
551             pkcs10Data *pkcs10;
552            
553             ALIAS:
554             write_pem_req = 1
555             PROTOTYPE: $;$
556              
557             PREINIT:
558             BIO *bio;
559              
560             CODE:
561 3 50         if((ix != 1 && items > 1) || (ix == 1 && items != 2))
    50          
    50          
    0          
562 0           croak("get_pem_req illegal/missing args");
563 3 50         if(items > 1) {
564 0           bio = sv_bio_create_file(ST(1));
565             } else {
566 3           bio = sv_bio_create();
567             }
568              
569             /* get the certificate back out in a specified format. */
570              
571 3 50         if(!PEM_write_bio_X509_REQ(bio,pkcs10->req))
572 0           croak ("PEM_write_bio_X509_REQ");
573              
574 3           RETVAL = sv_bio_final(bio);
575              
576             OUTPUT:
577             RETVAL
578              
579             SV*
580             get_pem_pk(pkcs10,...)
581             pkcs10Data *pkcs10;
582              
583             ALIAS:
584             write_pem_pk = 1
585             PROTOTYPE: $;$
586              
587             PREINIT:
588             BIO *bio;
589              
590             CODE:
591 0 0         if((ix != 1 && items > 1) || (ix == 1 && items != 2))
    0          
    0          
    0          
592 0           croak("get_pem_pk illegal/missing args");
593 0 0         if(items > 1) {
594 0           bio = sv_bio_create_file(ST(1));
595             } else {
596 0           bio = sv_bio_create();
597             }
598              
599 0 0         if(!pkcs10->pk)
600 0           croak ("Private key doesn't exist");
601              
602             /* get the certificate back out in a specified format. */
603              
604 0 0         if(!PEM_write_bio_PrivateKey(bio,pkcs10->pk,NULL,NULL,0,NULL,NULL))
605 0           croak ("%s - PEM_write_bio_PrivateKey", (char *) pkcs10->pk);
606              
607 0           RETVAL = sv_bio_final(bio);
608              
609             OUTPUT:
610             RETVAL
611              
612             int
613             set_subject(pkcs10, subj_SV, utf8 = 0)
614             pkcs10Data *pkcs10;
615             SV* subj_SV;
616             int utf8;
617              
618             PREINIT:
619             char* subj;
620             STRLEN subj_length;
621              
622             CODE:
623 1 50         subj = SvPV(subj_SV, subj_length);
624              
625 1 50         RETVAL = build_subject(pkcs10->req, subj, utf8 ? MBSTRING_UTF8 : MBSTRING_ASC, 0);
626 1 50         if (!RETVAL)
627 0           croak ("build_subject");
628              
629             OUTPUT:
630             RETVAL
631              
632             int
633             add_ext(pkcs10, nid = NID_key_usage, ext_SV)
634             pkcs10Data *pkcs10;
635             int nid;
636             SV* ext_SV;
637              
638             PREINIT:
639             char* ext;
640             STRLEN ext_length;
641              
642             CODE:
643 4 50         ext = SvPV(ext_SV, ext_length);
644              
645 4 100         if(!pkcs10->exts)
646 1           pkcs10->exts = sk_X509_EXTENSION_new_null();
647            
648 4           RETVAL = add_ext(pkcs10->exts, pkcs10->req, nid, ext);
649 4 50         if (!RETVAL)
650 0           croak ("add_ext key_usage: %d, ext: %s", nid, ext);
651              
652             OUTPUT:
653             RETVAL
654              
655             int
656             add_custom_ext_raw(pkcs10, oid_SV, ext_SV)
657             pkcs10Data *pkcs10;
658             SV* oid_SV;
659             SV* ext_SV;
660              
661             PREINIT:
662             char* oid;
663             char* ext;
664             STRLEN ext_length;
665             int nid;
666              
667             CODE:
668 1 50         oid = SvPV(oid_SV, ext_length);
669 1 50         ext = SvPV(ext_SV, ext_length);
670            
671 1 50         if(!pkcs10->exts)
672 0           pkcs10->exts = sk_X509_EXTENSION_new_null();
673              
674 1 50         if ((nid = OBJ_create(oid, oid, oid)) == NID_undef)
675 0           croak ("add_custom_ext: OBJ_create() for OID %s failed", oid);
676 1           RETVAL = add_ext_raw(pkcs10->exts, nid, ext, ext_length);
677              
678 1 50         if (!RETVAL)
679 0           croak ("add_custom_ext_raw oid: %s, ext: %s", oid, ext);
680              
681             OUTPUT:
682             RETVAL
683              
684              
685             int
686             add_custom_ext(pkcs10, oid_SV, ext_SV)
687             pkcs10Data *pkcs10;
688             SV* oid_SV;
689             SV* ext_SV;
690              
691             PREINIT:
692             char* oid;
693             char* ext;
694             STRLEN ext_length;
695             int nid;
696              
697             CODE:
698 1 50         oid = SvPV(oid_SV, ext_length);
699 1 50         ext = SvPV(ext_SV, ext_length);
700              
701 1 50         if(!pkcs10->exts)
702 0           pkcs10->exts = sk_X509_EXTENSION_new_null();
703              
704 1 50         if ((nid = OBJ_create(oid, oid, oid)) == NID_undef)
705 0           croak ("add_custom_ext_raw: OBJ_create() for OID %s failed", oid);
706 1           X509V3_EXT_add_alias(nid, NID_netscape_comment);
707 1           RETVAL = add_ext(pkcs10->exts, pkcs10->req, nid, ext);
708              
709 1 50         if (!RETVAL)
710 0           croak ("add_custom_ext oid: %s, ext: %s", oid, ext);
711              
712             OUTPUT:
713             RETVAL
714              
715             int
716             add_ext_final(pkcs10)
717             pkcs10Data *pkcs10;
718              
719             CODE:
720 1 50         if(pkcs10->exts) {
721 1           RETVAL = X509_REQ_add_extensions(pkcs10->req, pkcs10->exts);
722            
723 1 50         if (!RETVAL)
724 0           croak ("X509_REQ_add_extensions");
725              
726 1 50         if(pkcs10->exts)
727 1           sk_X509_EXTENSION_pop_free(pkcs10->exts, X509_EXTENSION_free);
728             } else {
729 0           RETVAL = 0;
730             }
731              
732             OUTPUT:
733             RETVAL
734              
735             SV*
736             new_from_file(class, filename_SV)
737             SV* class;
738             SV* filename_SV;
739              
740             PREINIT:
741             char* filename;
742             STRLEN filename_length;
743             FILE* fp;
744             X509_REQ *req;
745              
746             CODE:
747 2 50         filename = SvPV(filename_SV, filename_length);
748 2           fp = fopen(filename, "r");
749 2 100         if (fp == NULL) {
750 1           croak ("Cannot open file '%s'", filename);
751             }
752 1           req = PEM_read_X509_REQ (fp, NULL, NULL, NULL);
753 1           fclose(fp);
754              
755 1           RETVAL = make_pkcs10_obj(class, req, NULL, NULL, NULL);
756              
757             OUTPUT:
758             RETVAL
759              
760              
761             SV*
762             accessor(pkcs10)
763             pkcs10Data *pkcs10;
764              
765             ALIAS:
766             subject = 1
767             keyinfo = 2
768              
769              
770             PREINIT:
771             BIO *bio;
772             X509_NAME *name;
773             EVP_PKEY *key;
774              
775             CODE:
776              
777 8           bio = sv_bio_create();
778              
779 8 50         if (pkcs10->req != NULL) {
780 8 100         if (ix == 1) {
781 4           name = X509_REQ_get_subject_name(pkcs10->req);
782 4           X509_NAME_print_ex(bio, name, 0, XN_FLAG_SEP_CPLUS_SPC);
783 4 50         } else if (ix == 2 ) {
784 4           key = X509_REQ_get_pubkey(pkcs10->req);
785             #if OPENSSL_VERSION_NUMBER >= 0x30000000L
786             EVP_PKEY_print_public(bio, key, 0, NULL);
787             #else
788 4           RSA_print(bio, EVP_PKEY_get1_RSA(key), 0);
789             #endif
790             }
791             }
792              
793 8           RETVAL = sv_bio_final(bio);
794              
795             OUTPUT:
796             RETVAL