Ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
ossl_pkcs7.c
Go to the documentation of this file.
1/*
2 * 'OpenSSL for Ruby' project
3 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
4 * All rights reserved.
5 */
6/*
7 * This program is licensed under the same licence as Ruby.
8 * (See the file 'LICENCE'.)
9 */
10#include "ossl.h"
11
12#define NewPKCS7(klass) \
13 TypedData_Wrap_Struct((klass), &ossl_pkcs7_type, 0)
14#define SetPKCS7(obj, pkcs7) do { \
15 if (!(pkcs7)) { \
16 ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
17 } \
18 RTYPEDDATA_DATA(obj) = (pkcs7); \
19} while (0)
20#define GetPKCS7(obj, pkcs7) do { \
21 TypedData_Get_Struct((obj), PKCS7, &ossl_pkcs7_type, (pkcs7)); \
22 if (!(pkcs7)) { \
23 ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
24 } \
25} while (0)
26
27#define NewPKCS7si(klass) \
28 TypedData_Wrap_Struct((klass), &ossl_pkcs7_signer_info_type, 0)
29#define SetPKCS7si(obj, p7si) do { \
30 if (!(p7si)) { \
31 ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
32 } \
33 RTYPEDDATA_DATA(obj) = (p7si); \
34} while (0)
35#define GetPKCS7si(obj, p7si) do { \
36 TypedData_Get_Struct((obj), PKCS7_SIGNER_INFO, &ossl_pkcs7_signer_info_type, (p7si)); \
37 if (!(p7si)) { \
38 ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
39 } \
40} while (0)
41
42#define NewPKCS7ri(klass) \
43 TypedData_Wrap_Struct((klass), &ossl_pkcs7_recip_info_type, 0)
44#define SetPKCS7ri(obj, p7ri) do { \
45 if (!(p7ri)) { \
46 ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
47 } \
48 RTYPEDDATA_DATA(obj) = (p7ri); \
49} while (0)
50#define GetPKCS7ri(obj, p7ri) do { \
51 TypedData_Get_Struct((obj), PKCS7_RECIP_INFO, &ossl_pkcs7_recip_info_type, (p7ri)); \
52 if (!(p7ri)) { \
53 ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
54 } \
55} while (0)
56
57#define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
58
59#define ossl_pkcs7_set_data(o,v) rb_iv_set((o), "@data", (v))
60#define ossl_pkcs7_get_data(o) rb_iv_get((o), "@data")
61#define ossl_pkcs7_set_err_string(o,v) rb_iv_set((o), "@error_string", (v))
62#define ossl_pkcs7_get_err_string(o) rb_iv_get((o), "@error_string")
63
64/*
65 * Classes
66 */
71
72static void
73ossl_pkcs7_free(void *ptr)
74{
75 PKCS7_free(ptr);
76}
77
78static const rb_data_type_t ossl_pkcs7_type = {
79 "OpenSSL/PKCS7",
80 {
81 0, ossl_pkcs7_free,
82 },
84};
85
86static void
87ossl_pkcs7_signer_info_free(void *ptr)
88{
89 PKCS7_SIGNER_INFO_free(ptr);
90}
91
92static const rb_data_type_t ossl_pkcs7_signer_info_type = {
93 "OpenSSL/PKCS7/SIGNER_INFO",
94 {
95 0, ossl_pkcs7_signer_info_free,
96 },
98};
99
100static void
101ossl_pkcs7_recip_info_free(void *ptr)
102{
103 PKCS7_RECIP_INFO_free(ptr);
104}
105
106static const rb_data_type_t ossl_pkcs7_recip_info_type = {
107 "OpenSSL/PKCS7/RECIP_INFO",
108 {
109 0, ossl_pkcs7_recip_info_free,
110 },
112};
113
114/*
115 * Public
116 * (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM)
117 */
118static PKCS7_SIGNER_INFO *
119ossl_PKCS7_SIGNER_INFO_dup(const PKCS7_SIGNER_INFO *si)
120{
121 return (PKCS7_SIGNER_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO,
122 (d2i_of_void *)d2i_PKCS7_SIGNER_INFO,
123 (char *)si);
124}
125
126static PKCS7_RECIP_INFO *
127ossl_PKCS7_RECIP_INFO_dup(const PKCS7_RECIP_INFO *si)
128{
129 return (PKCS7_RECIP_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO,
130 (d2i_of_void *)d2i_PKCS7_RECIP_INFO,
131 (char *)si);
132}
133
134static VALUE
135ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si)
136{
137 PKCS7_SIGNER_INFO *pkcs7;
138 VALUE obj;
139
141 pkcs7 = p7si ? ossl_PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new();
142 if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
143 SetPKCS7si(obj, pkcs7);
144
145 return obj;
146}
147
148static PKCS7_SIGNER_INFO *
149DupPKCS7SignerPtr(VALUE obj)
150{
151 PKCS7_SIGNER_INFO *p7si, *pkcs7;
152
153 GetPKCS7si(obj, p7si);
154 if (!(pkcs7 = ossl_PKCS7_SIGNER_INFO_dup(p7si))) {
156 }
157
158 return pkcs7;
159}
160
161static VALUE
162ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri)
163{
164 PKCS7_RECIP_INFO *pkcs7;
165 VALUE obj;
166
168 pkcs7 = p7ri ? ossl_PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new();
169 if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
170 SetPKCS7ri(obj, pkcs7);
171
172 return obj;
173}
174
175static PKCS7_RECIP_INFO *
176DupPKCS7RecipientPtr(VALUE obj)
177{
178 PKCS7_RECIP_INFO *p7ri, *pkcs7;
179
180 GetPKCS7ri(obj, p7ri);
181 if (!(pkcs7 = ossl_PKCS7_RECIP_INFO_dup(p7ri))) {
183 }
184
185 return pkcs7;
186}
187
188/*
189 * call-seq:
190 * PKCS7.read_smime(string) => pkcs7
191 */
192static VALUE
193ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
194{
195 BIO *in, *out;
196 PKCS7 *pkcs7;
197 VALUE ret, data;
198
199 ret = NewPKCS7(cPKCS7);
200 in = ossl_obj2bio(&arg);
201 out = NULL;
202 pkcs7 = SMIME_read_PKCS7(in, &out);
203 BIO_free(in);
204 if(!pkcs7) ossl_raise(ePKCS7Error, NULL);
205 data = out ? ossl_membio2str(out) : Qnil;
206 SetPKCS7(ret, pkcs7);
207 ossl_pkcs7_set_data(ret, data);
209
210 return ret;
211}
212
213/*
214 * call-seq:
215 * PKCS7.write_smime(pkcs7 [, data [, flags]]) => string
216 */
217static VALUE
218ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
219{
220 VALUE pkcs7, data, flags;
221 BIO *out, *in;
222 PKCS7 *p7;
223 VALUE str;
224 int flg;
225
226 rb_scan_args(argc, argv, "12", &pkcs7, &data, &flags);
227 flg = NIL_P(flags) ? 0 : NUM2INT(flags);
228 if(NIL_P(data)) data = ossl_pkcs7_get_data(pkcs7);
229 GetPKCS7(pkcs7, p7);
230 if(!NIL_P(data) && PKCS7_is_detached(p7))
231 flg |= PKCS7_DETACHED;
232 in = NIL_P(data) ? NULL : ossl_obj2bio(&data);
233 if(!(out = BIO_new(BIO_s_mem()))){
234 BIO_free(in);
236 }
237 if(!SMIME_write_PKCS7(out, p7, in, flg)){
238 BIO_free(out);
239 BIO_free(in);
241 }
242 BIO_free(in);
243 str = ossl_membio2str(out);
244
245 return str;
246}
247
248/*
249 * call-seq:
250 * PKCS7.sign(cert, key, data, [, certs [, flags]]) => pkcs7
251 */
252static VALUE
253ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
254{
255 VALUE cert, key, data, certs, flags;
256 X509 *x509;
257 EVP_PKEY *pkey;
258 BIO *in;
259 STACK_OF(X509) *x509s;
260 int flg, status = 0;
261 PKCS7 *pkcs7;
262 VALUE ret;
263
264 rb_scan_args(argc, argv, "32", &cert, &key, &data, &certs, &flags);
265 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
266 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
267 flg = NIL_P(flags) ? 0 : NUM2INT(flags);
268 ret = NewPKCS7(cPKCS7);
269 in = ossl_obj2bio(&data);
270 if(NIL_P(certs)) x509s = NULL;
271 else{
272 x509s = ossl_protect_x509_ary2sk(certs, &status);
273 if(status){
274 BIO_free(in);
275 rb_jump_tag(status);
276 }
277 }
278 if(!(pkcs7 = PKCS7_sign(x509, pkey, x509s, in, flg))){
279 BIO_free(in);
280 sk_X509_pop_free(x509s, X509_free);
282 }
283 SetPKCS7(ret, pkcs7);
284 ossl_pkcs7_set_data(ret, data);
286 BIO_free(in);
287 sk_X509_pop_free(x509s, X509_free);
288
289 return ret;
290}
291
292/*
293 * call-seq:
294 * PKCS7.encrypt(certs, data, [, cipher [, flags]]) => pkcs7
295 */
296static VALUE
297ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
298{
299 VALUE certs, data, cipher, flags;
300 STACK_OF(X509) *x509s;
301 BIO *in;
302 const EVP_CIPHER *ciph;
303 int flg, status = 0;
304 VALUE ret;
305 PKCS7 *p7;
306
307 rb_scan_args(argc, argv, "22", &certs, &data, &cipher, &flags);
308 if(NIL_P(cipher)){
309#if !defined(OPENSSL_NO_RC2)
310 ciph = EVP_rc2_40_cbc();
311#elif !defined(OPENSSL_NO_DES)
312 ciph = EVP_des_ede3_cbc();
313#elif !defined(OPENSSL_NO_RC2)
314 ciph = EVP_rc2_40_cbc();
315#elif !defined(OPENSSL_NO_AES)
316 ciph = EVP_EVP_aes_128_cbc();
317#else
318 ossl_raise(ePKCS7Error, "Must specify cipher");
319#endif
320
321 }
322 else ciph = ossl_evp_get_cipherbyname(cipher);
323 flg = NIL_P(flags) ? 0 : NUM2INT(flags);
324 ret = NewPKCS7(cPKCS7);
325 in = ossl_obj2bio(&data);
326 x509s = ossl_protect_x509_ary2sk(certs, &status);
327 if(status){
328 BIO_free(in);
329 rb_jump_tag(status);
330 }
331 if(!(p7 = PKCS7_encrypt(x509s, in, (EVP_CIPHER*)ciph, flg))){
332 BIO_free(in);
333 sk_X509_pop_free(x509s, X509_free);
335 }
336 BIO_free(in);
337 SetPKCS7(ret, p7);
338 ossl_pkcs7_set_data(ret, data);
339 sk_X509_pop_free(x509s, X509_free);
340
341 return ret;
342}
343
344static VALUE
345ossl_pkcs7_alloc(VALUE klass)
346{
347 PKCS7 *pkcs7;
348 VALUE obj;
349
350 obj = NewPKCS7(klass);
351 if (!(pkcs7 = PKCS7_new())) {
353 }
354 SetPKCS7(obj, pkcs7);
355
356 return obj;
357}
358
359/*
360 * call-seq:
361 * PKCS7.new => pkcs7
362 * PKCS7.new(string) => pkcs7
363 *
364 * Many methods in this class aren't documented.
365 */
366static VALUE
367ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
368{
369 PKCS7 *p7, *pkcs = DATA_PTR(self);
370 BIO *in;
371 VALUE arg;
372
373 if(rb_scan_args(argc, argv, "01", &arg) == 0)
374 return self;
376 in = ossl_obj2bio(&arg);
377 p7 = PEM_read_bio_PKCS7(in, &pkcs, NULL, NULL);
378 if (!p7) {
379 OSSL_BIO_reset(in);
380 p7 = d2i_PKCS7_bio(in, &pkcs);
381 if (!p7) {
382 BIO_free(in);
383 PKCS7_free(pkcs);
384 DATA_PTR(self) = NULL;
385 ossl_raise(rb_eArgError, "Could not parse the PKCS7");
386 }
387 }
388 DATA_PTR(self) = pkcs;
389 BIO_free(in);
392
393 return self;
394}
395
396static VALUE
397ossl_pkcs7_copy(VALUE self, VALUE other)
398{
399 PKCS7 *a, *b, *pkcs7;
400
401 rb_check_frozen(self);
402 if (self == other) return self;
403
404 GetPKCS7(self, a);
405 GetPKCS7(other, b);
406
407 pkcs7 = PKCS7_dup(b);
408 if (!pkcs7) {
410 }
411 DATA_PTR(self) = pkcs7;
412 PKCS7_free(a);
413
414 return self;
415}
416
417static int
418ossl_pkcs7_sym2typeid(VALUE sym)
419{
420 int i, ret = Qnil;
421 const char *s;
422 size_t l;
423
424 static const struct {
425 char name[20];
426 int nid;
427 } p7_type_tab[] = {
428 { "signed", NID_pkcs7_signed },
429 { "data", NID_pkcs7_data },
430 { "signedAndEnveloped", NID_pkcs7_signedAndEnveloped },
431 { "enveloped", NID_pkcs7_enveloped },
432 { "encrypted", NID_pkcs7_encrypted },
433 { "digest", NID_pkcs7_digest },
434 };
435
436 if (SYMBOL_P(sym)) sym = rb_sym2str(sym);
437 else StringValue(sym);
438 RSTRING_GETMEM(sym, s, l);
439
440 for(i = 0; ; i++){
441 if(i == numberof(p7_type_tab))
442 ossl_raise(ePKCS7Error, "unknown type \"%"PRIsVALUE"\"", sym);
443 if(strlen(p7_type_tab[i].name) != l) continue;
444 if(strcmp(p7_type_tab[i].name, s) == 0){
445 ret = p7_type_tab[i].nid;
446 break;
447 }
448 }
449
450 return ret;
451}
452
453/*
454 * call-seq:
455 * pkcs7.type = type => type
456 */
457static VALUE
458ossl_pkcs7_set_type(VALUE self, VALUE type)
459{
460 PKCS7 *p7;
461
462 GetPKCS7(self, p7);
463 if(!PKCS7_set_type(p7, ossl_pkcs7_sym2typeid(type)))
465
466 return type;
467}
468
469/*
470 * call-seq:
471 * pkcs7.type => string or nil
472 */
473static VALUE
474ossl_pkcs7_get_type(VALUE self)
475{
476 PKCS7 *p7;
477
478 GetPKCS7(self, p7);
479 if(PKCS7_type_is_signed(p7))
480 return ID2SYM(rb_intern("signed"));
481 if(PKCS7_type_is_encrypted(p7))
482 return ID2SYM(rb_intern("encrypted"));
483 if(PKCS7_type_is_enveloped(p7))
484 return ID2SYM(rb_intern("enveloped"));
485 if(PKCS7_type_is_signedAndEnveloped(p7))
486 return ID2SYM(rb_intern("signedAndEnveloped"));
487 if(PKCS7_type_is_data(p7))
488 return ID2SYM(rb_intern("data"));
489 return Qnil;
490}
491
492static VALUE
493ossl_pkcs7_set_detached(VALUE self, VALUE flag)
494{
495 PKCS7 *p7;
496
497 GetPKCS7(self, p7);
498 if(flag != Qtrue && flag != Qfalse)
499 ossl_raise(ePKCS7Error, "must specify a boolean");
500 if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0))
502
503 return flag;
504}
505
506static VALUE
507ossl_pkcs7_get_detached(VALUE self)
508{
509 PKCS7 *p7;
510 GetPKCS7(self, p7);
511 return PKCS7_get_detached(p7) ? Qtrue : Qfalse;
512}
513
514static VALUE
515ossl_pkcs7_detached_p(VALUE self)
516{
517 PKCS7 *p7;
518 GetPKCS7(self, p7);
519 return PKCS7_is_detached(p7) ? Qtrue : Qfalse;
520}
521
522static VALUE
523ossl_pkcs7_set_cipher(VALUE self, VALUE cipher)
524{
525 PKCS7 *pkcs7;
526
527 GetPKCS7(self, pkcs7);
528 if (!PKCS7_set_cipher(pkcs7, ossl_evp_get_cipherbyname(cipher))) {
530 }
531
532 return cipher;
533}
534
535static VALUE
536ossl_pkcs7_add_signer(VALUE self, VALUE signer)
537{
538 PKCS7 *pkcs7;
539 PKCS7_SIGNER_INFO *p7si;
540
541 p7si = DupPKCS7SignerPtr(signer); /* NEED TO DUP */
542 GetPKCS7(self, pkcs7);
543 if (!PKCS7_add_signer(pkcs7, p7si)) {
544 PKCS7_SIGNER_INFO_free(p7si);
545 ossl_raise(ePKCS7Error, "Could not add signer.");
546 }
547 if (PKCS7_type_is_signed(pkcs7)){
548 PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
549 V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data));
550 }
551
552 return self;
553}
554
555static VALUE
556ossl_pkcs7_get_signer(VALUE self)
557{
558 PKCS7 *pkcs7;
559 STACK_OF(PKCS7_SIGNER_INFO) *sk;
560 PKCS7_SIGNER_INFO *si;
561 int num, i;
562 VALUE ary;
563
564 GetPKCS7(self, pkcs7);
565 if (!(sk = PKCS7_get_signer_info(pkcs7))) {
566 OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!");
567 return rb_ary_new();
568 }
569 if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) {
570 ossl_raise(ePKCS7Error, "Negative number of signers!");
571 }
572 ary = rb_ary_new2(num);
573 for (i=0; i<num; i++) {
574 si = sk_PKCS7_SIGNER_INFO_value(sk, i);
575 rb_ary_push(ary, ossl_pkcs7si_new(si));
576 }
577
578 return ary;
579}
580
581static VALUE
582ossl_pkcs7_add_recipient(VALUE self, VALUE recip)
583{
584 PKCS7 *pkcs7;
585 PKCS7_RECIP_INFO *ri;
586
587 ri = DupPKCS7RecipientPtr(recip); /* NEED TO DUP */
588 GetPKCS7(self, pkcs7);
589 if (!PKCS7_add_recipient_info(pkcs7, ri)) {
590 PKCS7_RECIP_INFO_free(ri);
591 ossl_raise(ePKCS7Error, "Could not add recipient.");
592 }
593
594 return self;
595}
596
597static VALUE
598ossl_pkcs7_get_recipient(VALUE self)
599{
600 PKCS7 *pkcs7;
601 STACK_OF(PKCS7_RECIP_INFO) *sk;
602 PKCS7_RECIP_INFO *si;
603 int num, i;
604 VALUE ary;
605
606 GetPKCS7(self, pkcs7);
607 if (PKCS7_type_is_enveloped(pkcs7))
608 sk = pkcs7->d.enveloped->recipientinfo;
609 else if (PKCS7_type_is_signedAndEnveloped(pkcs7))
610 sk = pkcs7->d.signed_and_enveloped->recipientinfo;
611 else sk = NULL;
612 if (!sk) return rb_ary_new();
613 if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) {
614 ossl_raise(ePKCS7Error, "Negative number of recipient!");
615 }
616 ary = rb_ary_new2(num);
617 for (i=0; i<num; i++) {
618 si = sk_PKCS7_RECIP_INFO_value(sk, i);
619 rb_ary_push(ary, ossl_pkcs7ri_new(si));
620 }
621
622 return ary;
623}
624
625static VALUE
626ossl_pkcs7_add_certificate(VALUE self, VALUE cert)
627{
628 PKCS7 *pkcs7;
629 X509 *x509;
630
631 GetPKCS7(self, pkcs7);
632 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
633 if (!PKCS7_add_certificate(pkcs7, x509)){
635 }
636
637 return self;
638}
639
640static STACK_OF(X509) *
641pkcs7_get_certs(VALUE self)
642{
643 PKCS7 *pkcs7;
644 STACK_OF(X509) *certs;
645 int i;
646
647 GetPKCS7(self, pkcs7);
648 i = OBJ_obj2nid(pkcs7->type);
649 switch(i){
650 case NID_pkcs7_signed:
651 certs = pkcs7->d.sign->cert;
652 break;
653 case NID_pkcs7_signedAndEnveloped:
654 certs = pkcs7->d.signed_and_enveloped->cert;
655 break;
656 default:
657 certs = NULL;
658 }
659
660 return certs;
661}
662
663static STACK_OF(X509_CRL) *
664pkcs7_get_crls(VALUE self)
665{
666 PKCS7 *pkcs7;
667 STACK_OF(X509_CRL) *crls;
668 int i;
669
670 GetPKCS7(self, pkcs7);
671 i = OBJ_obj2nid(pkcs7->type);
672 switch(i){
673 case NID_pkcs7_signed:
674 crls = pkcs7->d.sign->crl;
675 break;
676 case NID_pkcs7_signedAndEnveloped:
677 crls = pkcs7->d.signed_and_enveloped->crl;
678 break;
679 default:
680 crls = NULL;
681 }
682
683 return crls;
684}
685
686static VALUE
687ossl_pkcs7_set_certs_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
688{
689 return ossl_pkcs7_add_certificate(arg, i);
690}
691
692static VALUE
693ossl_pkcs7_set_certificates(VALUE self, VALUE ary)
694{
695 STACK_OF(X509) *certs;
696 X509 *cert;
697
698 certs = pkcs7_get_certs(self);
699 while((cert = sk_X509_pop(certs))) X509_free(cert);
700 rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self);
701
702 return ary;
703}
704
705static VALUE
706ossl_pkcs7_get_certificates(VALUE self)
707{
708 return ossl_x509_sk2ary(pkcs7_get_certs(self));
709}
710
711static VALUE
712ossl_pkcs7_add_crl(VALUE self, VALUE crl)
713{
714 PKCS7 *pkcs7;
715 X509_CRL *x509crl;
716
717 GetPKCS7(self, pkcs7); /* NO DUP needed! */
718 x509crl = GetX509CRLPtr(crl);
719 if (!PKCS7_add_crl(pkcs7, x509crl)) {
721 }
722
723 return self;
724}
725
726static VALUE
727ossl_pkcs7_set_crls_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
728{
729 return ossl_pkcs7_add_crl(arg, i);
730}
731
732static VALUE
733ossl_pkcs7_set_crls(VALUE self, VALUE ary)
734{
735 STACK_OF(X509_CRL) *crls;
736 X509_CRL *crl;
737
738 crls = pkcs7_get_crls(self);
739 while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl);
740 rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self);
741
742 return ary;
743}
744
745static VALUE
746ossl_pkcs7_get_crls(VALUE self)
747{
748 return ossl_x509crl_sk2ary(pkcs7_get_crls(self));
749}
750
751static VALUE
752ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
753{
754 VALUE certs, store, indata, flags;
755 STACK_OF(X509) *x509s;
756 X509_STORE *x509st;
757 int flg, ok, status = 0;
758 BIO *in, *out;
759 PKCS7 *p7;
760 VALUE data;
761 const char *msg;
762
763 GetPKCS7(self, p7);
764 rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags);
765 x509st = GetX509StorePtr(store);
766 flg = NIL_P(flags) ? 0 : NUM2INT(flags);
767 if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self);
768 in = NIL_P(indata) ? NULL : ossl_obj2bio(&indata);
769 if(NIL_P(certs)) x509s = NULL;
770 else{
771 x509s = ossl_protect_x509_ary2sk(certs, &status);
772 if(status){
773 BIO_free(in);
774 rb_jump_tag(status);
775 }
776 }
777 if(!(out = BIO_new(BIO_s_mem()))){
778 BIO_free(in);
779 sk_X509_pop_free(x509s, X509_free);
781 }
782 ok = PKCS7_verify(p7, x509s, x509st, in, out, flg);
783 BIO_free(in);
784 sk_X509_pop_free(x509s, X509_free);
785 if (ok < 0) ossl_raise(ePKCS7Error, "PKCS7_verify");
786 msg = ERR_reason_error_string(ERR_peek_error());
787 ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil);
789 data = ossl_membio2str(out);
790 ossl_pkcs7_set_data(self, data);
791
792 return (ok == 1) ? Qtrue : Qfalse;
793}
794
795static VALUE
796ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self)
797{
798 VALUE pkey, cert, flags;
799 EVP_PKEY *key;
800 X509 *x509;
801 int flg;
802 PKCS7 *p7;
803 BIO *out;
804 VALUE str;
805
806 rb_scan_args(argc, argv, "21", &pkey, &cert, &flags);
807 key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */
808 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
809 flg = NIL_P(flags) ? 0 : NUM2INT(flags);
810 GetPKCS7(self, p7);
811 if(!(out = BIO_new(BIO_s_mem())))
813 if(!PKCS7_decrypt(p7, key, x509, out, flg)){
814 BIO_free(out);
816 }
817 str = ossl_membio2str(out); /* out will be free */
818
819 return str;
820}
821
822static VALUE
823ossl_pkcs7_add_data(VALUE self, VALUE data)
824{
825 PKCS7 *pkcs7;
826 BIO *out, *in;
827 char buf[4096];
828 int len;
829
830 GetPKCS7(self, pkcs7);
831 if(PKCS7_type_is_signed(pkcs7)){
832 if(!PKCS7_content_new(pkcs7, NID_pkcs7_data))
834 }
835 in = ossl_obj2bio(&data);
836 if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err;
837 for(;;){
838 if((len = BIO_read(in, buf, sizeof(buf))) <= 0)
839 break;
840 if(BIO_write(out, buf, len) != len)
841 goto err;
842 }
843 if(!PKCS7_dataFinal(pkcs7, out)) goto err;
845
846 err:
847 BIO_free_all(out);
848 BIO_free(in);
849 if(ERR_peek_error()){
851 }
852
853 return data;
854}
855
856static VALUE
857ossl_pkcs7_to_der(VALUE self)
858{
859 PKCS7 *pkcs7;
860 VALUE str;
861 long len;
862 unsigned char *p;
863
864 GetPKCS7(self, pkcs7);
865 if((len = i2d_PKCS7(pkcs7, NULL)) <= 0)
867 str = rb_str_new(0, len);
868 p = (unsigned char *)RSTRING_PTR(str);
869 if(i2d_PKCS7(pkcs7, &p) <= 0)
872
873 return str;
874}
875
876static VALUE
877ossl_pkcs7_to_pem(VALUE self)
878{
879 PKCS7 *pkcs7;
880 BIO *out;
881 VALUE str;
882
883 GetPKCS7(self, pkcs7);
884 if (!(out = BIO_new(BIO_s_mem()))) {
886 }
887 if (!PEM_write_bio_PKCS7(out, pkcs7)) {
888 BIO_free(out);
890 }
891 str = ossl_membio2str(out);
892
893 return str;
894}
895
896/*
897 * SIGNER INFO
898 */
899static VALUE
900ossl_pkcs7si_alloc(VALUE klass)
901{
902 PKCS7_SIGNER_INFO *p7si;
903 VALUE obj;
904
906 if (!(p7si = PKCS7_SIGNER_INFO_new())) {
908 }
909 SetPKCS7si(obj, p7si);
910
911 return obj;
912}
913
914static VALUE
915ossl_pkcs7si_initialize(VALUE self, VALUE cert, VALUE key, VALUE digest)
916{
917 PKCS7_SIGNER_INFO *p7si;
918 EVP_PKEY *pkey;
919 X509 *x509;
920 const EVP_MD *md;
921
922 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
923 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
924 md = ossl_evp_get_digestbyname(digest);
925 GetPKCS7si(self, p7si);
926 if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, (EVP_MD*)md))) {
928 }
929
930 return self;
931}
932
933static VALUE
934ossl_pkcs7si_get_issuer(VALUE self)
935{
936 PKCS7_SIGNER_INFO *p7si;
937
938 GetPKCS7si(self, p7si);
939
940 return ossl_x509name_new(p7si->issuer_and_serial->issuer);
941}
942
943static VALUE
944ossl_pkcs7si_get_serial(VALUE self)
945{
946 PKCS7_SIGNER_INFO *p7si;
947
948 GetPKCS7si(self, p7si);
949
950 return asn1integer_to_num(p7si->issuer_and_serial->serial);
951}
952
953static VALUE
954ossl_pkcs7si_get_signed_time(VALUE self)
955{
956 PKCS7_SIGNER_INFO *p7si;
957 ASN1_TYPE *asn1obj;
958
959 GetPKCS7si(self, p7si);
960
961 if (!(asn1obj = PKCS7_get_signed_attribute(p7si, NID_pkcs9_signingTime))) {
963 }
964 if (asn1obj->type == V_ASN1_UTCTIME) {
965 return asn1time_to_time(asn1obj->value.utctime);
966 }
967 /*
968 * OR
969 * ossl_raise(ePKCS7Error, "...");
970 * ?
971 */
972
973 return Qnil;
974}
975
976/*
977 * RECIPIENT INFO
978 */
979static VALUE
980ossl_pkcs7ri_alloc(VALUE klass)
981{
982 PKCS7_RECIP_INFO *p7ri;
983 VALUE obj;
984
986 if (!(p7ri = PKCS7_RECIP_INFO_new())) {
988 }
989 SetPKCS7ri(obj, p7ri);
990
991 return obj;
992}
993
994static VALUE
995ossl_pkcs7ri_initialize(VALUE self, VALUE cert)
996{
997 PKCS7_RECIP_INFO *p7ri;
998 X509 *x509;
999
1000 x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
1001 GetPKCS7ri(self, p7ri);
1002 if (!PKCS7_RECIP_INFO_set(p7ri, x509)) {
1004 }
1005
1006 return self;
1007}
1008
1009static VALUE
1010ossl_pkcs7ri_get_issuer(VALUE self)
1011{
1012 PKCS7_RECIP_INFO *p7ri;
1013
1014 GetPKCS7ri(self, p7ri);
1015
1016 return ossl_x509name_new(p7ri->issuer_and_serial->issuer);
1017}
1018
1019static VALUE
1020ossl_pkcs7ri_get_serial(VALUE self)
1021{
1022 PKCS7_RECIP_INFO *p7ri;
1023
1024 GetPKCS7ri(self, p7ri);
1025
1026 return asn1integer_to_num(p7ri->issuer_and_serial->serial);
1027}
1028
1029static VALUE
1030ossl_pkcs7ri_get_enc_key(VALUE self)
1031{
1032 PKCS7_RECIP_INFO *p7ri;
1033
1034 GetPKCS7ri(self, p7ri);
1035
1036 return asn1str_to_str(p7ri->enc_key);
1037}
1038
1039/*
1040 * INIT
1041 */
1042void
1044{
1045#undef rb_intern
1046#if 0
1047 mOSSL = rb_define_module("OpenSSL");
1049#endif
1050
1053 rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
1054 rb_define_singleton_method(cPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1);
1055 rb_define_singleton_method(cPKCS7, "sign", ossl_pkcs7_s_sign, -1);
1056 rb_define_singleton_method(cPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1);
1057 rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse);
1058 rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse);
1059 rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc);
1060 rb_define_method(cPKCS7, "initialize_copy", ossl_pkcs7_copy, 1);
1061 rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1);
1062 rb_define_method(cPKCS7, "type=", ossl_pkcs7_set_type, 1);
1063 rb_define_method(cPKCS7, "type", ossl_pkcs7_get_type, 0);
1064 rb_define_method(cPKCS7, "detached=", ossl_pkcs7_set_detached, 1);
1065 rb_define_method(cPKCS7, "detached", ossl_pkcs7_get_detached, 0);
1066 rb_define_method(cPKCS7, "detached?", ossl_pkcs7_detached_p, 0);
1067 rb_define_method(cPKCS7, "cipher=", ossl_pkcs7_set_cipher, 1);
1068 rb_define_method(cPKCS7, "add_signer", ossl_pkcs7_add_signer, 1);
1069 rb_define_method(cPKCS7, "signers", ossl_pkcs7_get_signer, 0);
1070 rb_define_method(cPKCS7, "add_recipient", ossl_pkcs7_add_recipient, 1);
1071 rb_define_method(cPKCS7, "recipients", ossl_pkcs7_get_recipient, 0);
1072 rb_define_method(cPKCS7, "add_certificate", ossl_pkcs7_add_certificate, 1);
1073 rb_define_method(cPKCS7, "certificates=", ossl_pkcs7_set_certificates, 1);
1074 rb_define_method(cPKCS7, "certificates", ossl_pkcs7_get_certificates, 0);
1075 rb_define_method(cPKCS7, "add_crl", ossl_pkcs7_add_crl, 1);
1076 rb_define_method(cPKCS7, "crls=", ossl_pkcs7_set_crls, 1);
1077 rb_define_method(cPKCS7, "crls", ossl_pkcs7_get_crls, 0);
1078 rb_define_method(cPKCS7, "add_data", ossl_pkcs7_add_data, 1);
1079 rb_define_alias(cPKCS7, "data=", "add_data");
1080 rb_define_method(cPKCS7, "verify", ossl_pkcs7_verify, -1);
1081 rb_define_method(cPKCS7, "decrypt", ossl_pkcs7_decrypt, -1);
1082 rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0);
1083 rb_define_alias(cPKCS7, "to_s", "to_pem");
1084 rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0);
1085
1088 rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc);
1089 rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3);
1090 rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0);
1091 rb_define_alias(cPKCS7Signer, "name", "issuer");
1092 rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0);
1093 rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0);
1094
1096 rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc);
1097 rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1);
1098 rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0);
1099 rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0);
1100 rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0);
1101
1102#define DefPKCS7Const(x) rb_define_const(cPKCS7, #x, INT2NUM(PKCS7_##x))
1103
1104 DefPKCS7Const(TEXT);
1105 DefPKCS7Const(NOCERTS);
1106 DefPKCS7Const(NOSIGS);
1107 DefPKCS7Const(NOCHAIN);
1108 DefPKCS7Const(NOINTERN);
1109 DefPKCS7Const(NOVERIFY);
1110 DefPKCS7Const(DETACHED);
1112 DefPKCS7Const(NOATTR);
1113 DefPKCS7Const(NOSMIMECAP);
1114}
#define sym(x)
Definition: date_core.c:3717
struct RIMemo * ptr
Definition: debug.c:65
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
VALUE rb_define_class_under(VALUE, const char *, VALUE)
Defines a class under the namespace of outer.
Definition: class.c:711
VALUE rb_define_module(const char *)
Definition: class.c:785
void rb_define_alias(VALUE, const char *, const char *)
Defines an alias of a method.
Definition: class.c:1818
VALUE rb_cObject
Object class.
Definition: ruby.h:2012
VALUE rb_eStandardError
Definition: error.c:921
VALUE rb_eArgError
Definition: error.c:925
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:884
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
const char * name
Definition: nkf.c:208
@ BINARY
Definition: nkf.c:122
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
int nid
VALUE mOSSL
Definition: ossl.c:231
VALUE ossl_to_der_if_possible(VALUE obj)
Definition: ossl.c:255
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
VALUE eOSSLError
Definition: ossl.c:236
void ossl_clear_error(void)
Definition: ossl.c:304
#define ossl_str_adjust(str, p)
Definition: ossl.h:87
int *VALUE ossl_x509_sk2ary(const STACK_OF(X509) *certs)
#define OSSL_BIO_reset(bio)
Definition: ossl.h:115
STACK_OF(X509) *ossl_x509_ary2sk(VALUE)
#define OSSL_Debug
Definition: ossl.h:149
VALUE ossl_x509crl_sk2ary(const STACK_OF(X509_CRL) *crl)
VALUE asn1integer_to_num(const ASN1_INTEGER *ai)
Definition: ossl_asn1.c:101
VALUE asn1time_to_time(const ASN1_TIME *time)
Definition: ossl_asn1.c:20
VALUE asn1str_to_str(const ASN1_STRING *str)
Definition: ossl_asn1.c:92
BIO * ossl_obj2bio(volatile VALUE *pobj)
Definition: ossl_bio.c:13
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:29
const EVP_CIPHER * ossl_evp_get_cipherbyname(VALUE obj)
Definition: ossl_cipher.c:52
const EVP_MD * ossl_evp_get_digestbyname(VALUE obj)
Definition: ossl_digest.c:45
VALUE cPKCS7Recipient
Definition: ossl_pkcs7.c:69
#define GetPKCS7si(obj, p7si)
Definition: ossl_pkcs7.c:35
#define ossl_pkcs7_set_err_string(o, v)
Definition: ossl_pkcs7.c:61
#define NewPKCS7si(klass)
Definition: ossl_pkcs7.c:27
VALUE cPKCS7
Definition: ossl_pkcs7.c:67
#define numberof(ary)
Definition: ossl_pkcs7.c:57
#define NewPKCS7ri(klass)
Definition: ossl_pkcs7.c:42
#define GetPKCS7(obj, pkcs7)
Definition: ossl_pkcs7.c:20
#define ossl_pkcs7_set_data(o, v)
Definition: ossl_pkcs7.c:59
#define SetPKCS7(obj, pkcs7)
Definition: ossl_pkcs7.c:14
void Init_ossl_pkcs7(void)
Definition: ossl_pkcs7.c:1043
#define NewPKCS7(klass)
Definition: ossl_pkcs7.c:12
VALUE ePKCS7Error
Definition: ossl_pkcs7.c:70
#define SetPKCS7si(obj, p7si)
Definition: ossl_pkcs7.c:29
#define ossl_pkcs7_get_data(o)
Definition: ossl_pkcs7.c:60
#define SetPKCS7ri(obj, p7ri)
Definition: ossl_pkcs7.c:44
VALUE cPKCS7Signer
Definition: ossl_pkcs7.c:68
#define DefPKCS7Const(x)
#define GetPKCS7ri(obj, p7ri)
Definition: ossl_pkcs7.c:50
EVP_PKEY * GetPrivPKeyPtr(VALUE obj)
Definition: ossl_pkey.c:239
X509_STORE * GetX509StorePtr(VALUE)
VALUE ossl_x509name_new(X509_NAME *)
Definition: ossl_x509name.c:56
X509 * GetX509CertPtr(VALUE)
Definition: ossl_x509cert.c:71
X509_CRL * GetX509CRLPtr(VALUE)
Definition: ossl_x509crl.c:51
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
#define rb_str_new2
#define NULL
use StringValue() instead")))
void rb_attr(VALUE, ID, int, int, int)
Definition: vm_method.c:1180
size_t strlen(const char *)
int strcmp(const char *, const char *)
const VALUE VALUE obj
#define rb_check_frozen(obj)
#define RSTRING_PTR(str)
#define rb_str_new(str, len)
#define NIL_P(v)
#define ID2SYM(x)
VALUE rb_ary_push(VALUE, VALUE)
Definition: array.c:1195
VALUE rb_sym2str(VALUE)
Definition: symbol.c:784
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
uint32_t i
#define RSTRING_GETMEM(str, ptrvar, lenvar)
__inline__ const void *__restrict__ size_t len
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2891
#define NUM2INT(x)
void rb_define_singleton_method(VALUE, const char *, VALUE(*)(), int)
#define RUBY_TYPED_FREE_IMMEDIATELY
#define PRIsVALUE
VALUE rb_ary_new(void)
Definition: array.c:723
#define rb_scan_args(argc, argvp, fmt,...)
#define rb_intern(str)
#define Qtrue
#define Qnil
#define Qfalse
#define DATA_PTR(dta)
const VALUE * argv
#define SYMBOL_P(x)
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
Definition: vm_eval.c:1470
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
#define rb_ary_new2
unsigned long VALUE
Definition: ruby.h:102