File Coverage

PKCS10.xs
Criterion Covered Total %
statement 224 313 71.5
branch 114 216 52.7
condition n/a
subroutine n/a
pod n/a
total 338 529 63.8


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