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