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