Ruby  1.9.3p448(2013-06-27revision41675)
ossl_pkcs7.c
Go to the documentation of this file.
1 /*
2  * $Id: ossl_pkcs7.c 35179 2012-03-30 05:17:45Z naruse $
3  * 'OpenSSL for Ruby' project
4  * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5  * All rights reserved.
6  */
7 /*
8  * This program is licenced under the same licence as Ruby.
9  * (See the file 'LICENCE'.)
10  */
11 #include "ossl.h"
12 
13 #define WrapPKCS7(klass, obj, pkcs7) do { \
14  if (!(pkcs7)) { \
15  ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
16  } \
17  (obj) = Data_Wrap_Struct((klass), 0, PKCS7_free, (pkcs7)); \
18 } while (0)
19 #define GetPKCS7(obj, pkcs7) do { \
20  Data_Get_Struct((obj), PKCS7, (pkcs7)); \
21  if (!(pkcs7)) { \
22  ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
23  } \
24 } while (0)
25 #define SafeGetPKCS7(obj, pkcs7) do { \
26  OSSL_Check_Kind((obj), cPKCS7); \
27  GetPKCS7((obj), (pkcs7)); \
28 } while (0)
29 
30 #define WrapPKCS7si(klass, obj, p7si) do { \
31  if (!(p7si)) { \
32  ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
33  } \
34  (obj) = Data_Wrap_Struct((klass), 0, PKCS7_SIGNER_INFO_free, (p7si)); \
35 } while (0)
36 #define GetPKCS7si(obj, p7si) do { \
37  Data_Get_Struct((obj), PKCS7_SIGNER_INFO, (p7si)); \
38  if (!(p7si)) { \
39  ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
40  } \
41 } while (0)
42 #define SafeGetPKCS7si(obj, p7si) do { \
43  OSSL_Check_Kind((obj), cPKCS7Signer); \
44  GetPKCS7si((obj), (p7si)); \
45 } while (0)
46 
47 #define WrapPKCS7ri(klass, obj, p7ri) do { \
48  if (!(p7ri)) { \
49  ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
50  } \
51  (obj) = Data_Wrap_Struct((klass), 0, PKCS7_RECIP_INFO_free, (p7ri)); \
52 } while (0)
53 #define GetPKCS7ri(obj, p7ri) do { \
54  Data_Get_Struct((obj), PKCS7_RECIP_INFO, (p7ri)); \
55  if (!(p7ri)) { \
56  ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
57  } \
58 } while (0)
59 #define SafeGetPKCS7ri(obj, p7ri) do { \
60  OSSL_Check_Kind((obj), cPKCS7Recipient); \
61  GetPKCS7ri((obj), (p7ri)); \
62 } while (0)
63 
64 #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
65 
66 #define ossl_pkcs7_set_data(o,v) rb_iv_set((o), "@data", (v))
67 #define ossl_pkcs7_get_data(o) rb_iv_get((o), "@data")
68 #define ossl_pkcs7_set_err_string(o,v) rb_iv_set((o), "@error_string", (v))
69 #define ossl_pkcs7_get_err_string(o) rb_iv_get((o), "@error_string")
70 
71 /*
72  * Classes
73  */
78 
79 /*
80  * Public
81  * (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM)
82  */
83 static VALUE
84 ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si)
85 {
86  PKCS7_SIGNER_INFO *pkcs7;
87  VALUE obj;
88 
89  pkcs7 = p7si ? PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new();
90  if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
91  WrapPKCS7si(cPKCS7Signer, obj, pkcs7);
92 
93  return obj;
94 }
95 
96 static PKCS7_SIGNER_INFO *
98 {
99  PKCS7_SIGNER_INFO *p7si, *pkcs7;
100 
101  SafeGetPKCS7si(obj, p7si);
102  if (!(pkcs7 = PKCS7_SIGNER_INFO_dup(p7si))) {
104  }
105 
106  return pkcs7;
107 }
108 
109 static VALUE
110 ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri)
111 {
112  PKCS7_RECIP_INFO *pkcs7;
113  VALUE obj;
114 
115  pkcs7 = p7ri ? PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new();
116  if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
117  WrapPKCS7ri(cPKCS7Recipient, obj, pkcs7);
118 
119  return obj;
120 }
121 
122 static PKCS7_RECIP_INFO *
124 {
125  PKCS7_RECIP_INFO *p7ri, *pkcs7;
126 
127  SafeGetPKCS7ri(obj, p7ri);
128  if (!(pkcs7 = PKCS7_RECIP_INFO_dup(p7ri))) {
130  }
131 
132  return pkcs7;
133 }
134 
135 /*
136  * call-seq:
137  * PKCS7.read_smime(string) => pkcs7
138  */
139 static VALUE
141 {
142  BIO *in, *out;
143  PKCS7 *pkcs7;
144  VALUE ret, data;
145 
146  in = ossl_obj2bio(arg);
147  out = NULL;
148  pkcs7 = SMIME_read_PKCS7(in, &out);
149  BIO_free(in);
150  if(!pkcs7) ossl_raise(ePKCS7Error, NULL);
151  data = out ? ossl_membio2str(out) : Qnil;
152  WrapPKCS7(cPKCS7, ret, pkcs7);
153  ossl_pkcs7_set_data(ret, data);
155 
156  return ret;
157 }
158 
159 /*
160  * call-seq:
161  * PKCS7.write_smime(pkcs7 [, data [, flags]]) => string
162  */
163 static VALUE
165 {
166  VALUE pkcs7, data, flags;
167  BIO *out, *in;
168  PKCS7 *p7;
169  VALUE str;
170  int flg;
171 
172  rb_scan_args(argc, argv, "12", &pkcs7, &data, &flags);
173  flg = NIL_P(flags) ? 0 : NUM2INT(flags);
174  if(NIL_P(data)) data = ossl_pkcs7_get_data(pkcs7);
175  SafeGetPKCS7(pkcs7, p7);
176  if(!NIL_P(data) && PKCS7_is_detached(p7))
177  flg |= PKCS7_DETACHED;
178  in = NIL_P(data) ? NULL : ossl_obj2bio(data);
179  if(!(out = BIO_new(BIO_s_mem()))){
180  BIO_free(in);
182  }
183  if(!SMIME_write_PKCS7(out, p7, in, flg)){
184  BIO_free(out);
185  BIO_free(in);
187  }
188  BIO_free(in);
189  str = ossl_membio2str(out);
190 
191  return str;
192 }
193 
194 /*
195  * call-seq:
196  * PKCS7.sign(cert, key, data, [, certs [, flags]]) => pkcs7
197  */
198 static VALUE
200 {
201  VALUE cert, key, data, certs, flags;
202  X509 *x509;
203  EVP_PKEY *pkey;
204  BIO *in;
205  STACK_OF(X509) *x509s;
206  int flg, status = 0;
207  PKCS7 *pkcs7;
208  VALUE ret;
209 
210  rb_scan_args(argc, argv, "32", &cert, &key, &data, &certs, &flags);
211  x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
212  pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
213  flg = NIL_P(flags) ? 0 : NUM2INT(flags);
214  in = ossl_obj2bio(data);
215  if(NIL_P(certs)) x509s = NULL;
216  else{
217  x509s = ossl_protect_x509_ary2sk(certs, &status);
218  if(status){
219  BIO_free(in);
220  rb_jump_tag(status);
221  }
222  }
223  if(!(pkcs7 = PKCS7_sign(x509, pkey, x509s, in, flg))){
224  BIO_free(in);
225  sk_X509_pop_free(x509s, X509_free);
227  }
228  WrapPKCS7(cPKCS7, ret, pkcs7);
229  ossl_pkcs7_set_data(ret, data);
231  BIO_free(in);
232  sk_X509_pop_free(x509s, X509_free);
233 
234  return ret;
235 }
236 
237 /*
238  * call-seq:
239  * PKCS7.encrypt(certs, data, [, cipher [, flags]]) => pkcs7
240  */
241 static VALUE
243 {
244  VALUE certs, data, cipher, flags;
245  STACK_OF(X509) *x509s;
246  BIO *in;
247  const EVP_CIPHER *ciph;
248  int flg, status = 0;
249  VALUE ret;
250  PKCS7 *p7;
251 
252  rb_scan_args(argc, argv, "22", &certs, &data, &cipher, &flags);
253  if(NIL_P(cipher)){
254 #if !defined(OPENSSL_NO_RC2)
255  ciph = EVP_rc2_40_cbc();
256 #elif !defined(OPENSSL_NO_DES)
257  ciph = EVP_des_ede3_cbc();
258 #elif !defined(OPENSSL_NO_RC2)
259  ciph = EVP_rc2_40_cbc();
260 #elif !defined(OPENSSL_NO_AES)
261  ciph = EVP_EVP_aes_128_cbc();
262 #else
263  ossl_raise(ePKCS7Error, "Must specify cipher");
264 #endif
265 
266  }
267  else ciph = GetCipherPtr(cipher); /* NO NEED TO DUP */
268  flg = NIL_P(flags) ? 0 : NUM2INT(flags);
269  in = ossl_obj2bio(data);
270  x509s = ossl_protect_x509_ary2sk(certs, &status);
271  if(status){
272  BIO_free(in);
273  rb_jump_tag(status);
274  }
275  if(!(p7 = PKCS7_encrypt(x509s, in, (EVP_CIPHER*)ciph, flg))){
276  BIO_free(in);
277  sk_X509_pop_free(x509s, X509_free);
279  }
280  BIO_free(in);
281  WrapPKCS7(cPKCS7, ret, p7);
282  ossl_pkcs7_set_data(ret, data);
283  sk_X509_pop_free(x509s, X509_free);
284 
285  return ret;
286 }
287 
288 static VALUE
290 {
291  PKCS7 *pkcs7;
292  VALUE obj;
293 
294  if (!(pkcs7 = PKCS7_new())) {
296  }
297  WrapPKCS7(klass, obj, pkcs7);
298 
299  return obj;
300 }
301 
302 /*
303  * call-seq:
304  * PKCS7.new => pkcs7
305  * PKCS7.new(string) => pkcs7
306  *
307  * Many methods in this class aren't documented.
308  */
309 static VALUE
311 {
312  PKCS7 *p7, *pkcs = DATA_PTR(self);
313  BIO *in;
314  VALUE arg;
315 
316  if(rb_scan_args(argc, argv, "01", &arg) == 0)
317  return self;
318  arg = ossl_to_der_if_possible(arg);
319  in = ossl_obj2bio(arg);
320  p7 = PEM_read_bio_PKCS7(in, &pkcs, NULL, NULL);
321  if (!p7) {
322  OSSL_BIO_reset(in);
323  p7 = d2i_PKCS7_bio(in, &pkcs);
324  if (!p7) {
325  BIO_free(in);
326  PKCS7_free(pkcs);
327  DATA_PTR(self) = NULL;
328  ossl_raise(rb_eArgError, "Could not parse the PKCS7");
329  }
330  }
331  DATA_PTR(self) = pkcs;
332  BIO_free(in);
333  ossl_pkcs7_set_data(self, Qnil);
335 
336  return self;
337 }
338 
339 static VALUE
341 {
342  PKCS7 *a, *b, *pkcs7;
343 
344  rb_check_frozen(self);
345  if (self == other) return self;
346 
347  GetPKCS7(self, a);
348  SafeGetPKCS7(other, b);
349 
350  pkcs7 = PKCS7_dup(b);
351  if (!pkcs7) {
353  }
354  DATA_PTR(self) = pkcs7;
355  PKCS7_free(a);
356 
357  return self;
358 }
359 
360 static int
362 {
363  int i, ret = Qnil;
364  const char *s;
365 
366  static struct {
367  const char *name;
368  int nid;
369  } p7_type_tab[] = {
370  { "signed", NID_pkcs7_signed },
371  { "data", NID_pkcs7_data },
372  { "signedAndEnveloped", NID_pkcs7_signedAndEnveloped },
373  { "enveloped", NID_pkcs7_enveloped },
374  { "encrypted", NID_pkcs7_encrypted },
375  { "digest", NID_pkcs7_digest },
376  { NULL, 0 },
377  };
378 
379  if(TYPE(sym) == T_SYMBOL) s = rb_id2name(SYM2ID(sym));
380  else s = StringValuePtr(sym);
381  for(i = 0; i < numberof(p7_type_tab); i++){
382  if(p7_type_tab[i].name == NULL)
383  ossl_raise(ePKCS7Error, "unknown type \"%s\"", s);
384  if(strcmp(p7_type_tab[i].name, s) == 0){
385  ret = p7_type_tab[i].nid;
386  break;
387  }
388  }
389 
390  return ret;
391 }
392 
393 /*
394  * call-seq:
395  * pkcs7.type = type => type
396  */
397 static VALUE
399 {
400  PKCS7 *p7;
401 
402  GetPKCS7(self, p7);
403  if(!PKCS7_set_type(p7, ossl_pkcs7_sym2typeid(type)))
405 
406  return type;
407 }
408 
409 /*
410  * call-seq:
411  * pkcs7.type => string or nil
412  */
413 static VALUE
415 {
416  PKCS7 *p7;
417 
418  GetPKCS7(self, p7);
419  if(PKCS7_type_is_signed(p7))
420  return ID2SYM(rb_intern("signed"));
422  return ID2SYM(rb_intern("encrypted"));
423  if(PKCS7_type_is_enveloped(p7))
424  return ID2SYM(rb_intern("enveloped"));
425  if(PKCS7_type_is_signedAndEnveloped(p7))
426  return ID2SYM(rb_intern("signedAndEnveloped"));
427  if(PKCS7_type_is_data(p7))
428  return ID2SYM(rb_intern("data"));
429  return Qnil;
430 }
431 
432 static VALUE
434 {
435  PKCS7 *p7;
436 
437  GetPKCS7(self, p7);
438  if(flag != Qtrue && flag != Qfalse)
439  ossl_raise(ePKCS7Error, "must specify a boolean");
440  if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0))
442 
443  return flag;
444 }
445 
446 static VALUE
448 {
449  PKCS7 *p7;
450  GetPKCS7(self, p7);
451  return PKCS7_get_detached(p7) ? Qtrue : Qfalse;
452 }
453 
454 static VALUE
456 {
457  PKCS7 *p7;
458  GetPKCS7(self, p7);
459  return PKCS7_is_detached(p7) ? Qtrue : Qfalse;
460 }
461 
462 static VALUE
464 {
465  PKCS7 *pkcs7;
466 
467  GetPKCS7(self, pkcs7);
468  if (!PKCS7_set_cipher(pkcs7, GetCipherPtr(cipher))) {
470  }
471 
472  return cipher;
473 }
474 
475 static VALUE
477 {
478  PKCS7 *pkcs7;
479  PKCS7_SIGNER_INFO *p7si;
480 
481  p7si = DupPKCS7SignerPtr(signer); /* NEED TO DUP */
482  GetPKCS7(self, pkcs7);
483  if (!PKCS7_add_signer(pkcs7, p7si)) {
484  PKCS7_SIGNER_INFO_free(p7si);
485  ossl_raise(ePKCS7Error, "Could not add signer.");
486  }
487  if (PKCS7_type_is_signed(pkcs7)){
488  PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
489  V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data));
490  }
491 
492  return self;
493 }
494 
495 static VALUE
497 {
498  PKCS7 *pkcs7;
499  STACK_OF(PKCS7_SIGNER_INFO) *sk;
500  PKCS7_SIGNER_INFO *si;
501  int num, i;
502  VALUE ary;
503 
504  GetPKCS7(self, pkcs7);
505  if (!(sk = PKCS7_get_signer_info(pkcs7))) {
506  OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!");
507  return rb_ary_new();
508  }
509  if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) {
510  ossl_raise(ePKCS7Error, "Negative number of signers!");
511  }
512  ary = rb_ary_new2(num);
513  for (i=0; i<num; i++) {
514  si = sk_PKCS7_SIGNER_INFO_value(sk, i);
515  rb_ary_push(ary, ossl_pkcs7si_new(si));
516  }
517 
518  return ary;
519 }
520 
521 static VALUE
523 {
524  PKCS7 *pkcs7;
525  PKCS7_RECIP_INFO *ri;
526 
527  ri = DupPKCS7RecipientPtr(recip); /* NEED TO DUP */
528  GetPKCS7(self, pkcs7);
529  if (!PKCS7_add_recipient_info(pkcs7, ri)) {
530  PKCS7_RECIP_INFO_free(ri);
531  ossl_raise(ePKCS7Error, "Could not add recipient.");
532  }
533 
534  return self;
535 }
536 
537 static VALUE
539 {
540  PKCS7 *pkcs7;
541  STACK_OF(PKCS7_RECIP_INFO) *sk;
542  PKCS7_RECIP_INFO *si;
543  int num, i;
544  VALUE ary;
545 
546  GetPKCS7(self, pkcs7);
547  if (PKCS7_type_is_enveloped(pkcs7))
548  sk = pkcs7->d.enveloped->recipientinfo;
549  else if (PKCS7_type_is_signedAndEnveloped(pkcs7))
550  sk = pkcs7->d.signed_and_enveloped->recipientinfo;
551  else sk = NULL;
552  if (!sk) return rb_ary_new();
553  if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) {
554  ossl_raise(ePKCS7Error, "Negative number of recipient!");
555  }
556  ary = rb_ary_new2(num);
557  for (i=0; i<num; i++) {
558  si = sk_PKCS7_RECIP_INFO_value(sk, i);
559  rb_ary_push(ary, ossl_pkcs7ri_new(si));
560  }
561 
562  return ary;
563 }
564 
565 static VALUE
567 {
568  PKCS7 *pkcs7;
569  X509 *x509;
570 
571  GetPKCS7(self, pkcs7);
572  x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
573  if (!PKCS7_add_certificate(pkcs7, x509)){
575  }
576 
577  return self;
578 }
579 
580 static STACK_OF(X509) *
581 pkcs7_get_certs(VALUE self)
582 {
583  PKCS7 *pkcs7;
584  STACK_OF(X509) *certs;
585  int i;
586 
587  GetPKCS7(self, pkcs7);
588  i = OBJ_obj2nid(pkcs7->type);
589  switch(i){
590  case NID_pkcs7_signed:
591  certs = pkcs7->d.sign->cert;
592  break;
593  case NID_pkcs7_signedAndEnveloped:
594  certs = pkcs7->d.signed_and_enveloped->cert;
595  break;
596  default:
597  certs = NULL;
598  }
599 
600  return certs;
601 }
602 
603 static STACK_OF(X509_CRL) *
604 pkcs7_get_crls(VALUE self)
605 {
606  PKCS7 *pkcs7;
607  STACK_OF(X509_CRL) *crls;
608  int i;
609 
610  GetPKCS7(self, pkcs7);
611  i = OBJ_obj2nid(pkcs7->type);
612  switch(i){
613  case NID_pkcs7_signed:
614  crls = pkcs7->d.sign->crl;
615  break;
616  case NID_pkcs7_signedAndEnveloped:
617  crls = pkcs7->d.signed_and_enveloped->crl;
618  break;
619  default:
620  crls = NULL;
621  }
622 
623  return crls;
624 }
625 
626 static VALUE
628 {
629  return ossl_pkcs7_add_certificate(arg, i);
630 }
631 
632 static VALUE
634 {
635  STACK_OF(X509) *certs;
636  X509 *cert;
637 
638  certs = pkcs7_get_certs(self);
639  while((cert = sk_X509_pop(certs))) X509_free(cert);
640  rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self);
641 
642  return ary;
643 }
644 
645 static VALUE
647 {
648  return ossl_x509_sk2ary(pkcs7_get_certs(self));
649 }
650 
651 static VALUE
653 {
654  PKCS7 *pkcs7;
655  X509_CRL *x509crl;
656 
657  GetPKCS7(self, pkcs7); /* NO DUP needed! */
658  x509crl = GetX509CRLPtr(crl);
659  if (!PKCS7_add_crl(pkcs7, x509crl)) {
661  }
662 
663  return self;
664 }
665 
666 static VALUE
668 {
669  return ossl_pkcs7_add_crl(arg, i);
670 }
671 
672 static VALUE
674 {
675  STACK_OF(X509_CRL) *crls;
676  X509_CRL *crl;
677 
678  crls = pkcs7_get_crls(self);
679  while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl);
680  rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self);
681 
682  return ary;
683 }
684 
685 static VALUE
687 {
688  return ossl_x509crl_sk2ary(pkcs7_get_crls(self));
689 }
690 
691 static VALUE
693 {
694  VALUE certs, store, indata, flags;
695  STACK_OF(X509) *x509s;
696  X509_STORE *x509st;
697  int flg, ok, status = 0;
698  BIO *in, *out;
699  PKCS7 *p7;
700  VALUE data;
701  const char *msg;
702 
703  rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags);
704  flg = NIL_P(flags) ? 0 : NUM2INT(flags);
705  if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self);
706  in = NIL_P(indata) ? NULL : ossl_obj2bio(indata);
707  if(NIL_P(certs)) x509s = NULL;
708  else{
709  x509s = ossl_protect_x509_ary2sk(certs, &status);
710  if(status){
711  BIO_free(in);
712  rb_jump_tag(status);
713  }
714  }
715  x509st = GetX509StorePtr(store);
716  GetPKCS7(self, p7);
717  if(!(out = BIO_new(BIO_s_mem()))){
718  BIO_free(in);
719  sk_X509_pop_free(x509s, X509_free);
721  }
722  ok = PKCS7_verify(p7, x509s, x509st, in, out, flg);
723  BIO_free(in);
724  if (ok < 0) ossl_raise(ePKCS7Error, NULL);
725  msg = ERR_reason_error_string(ERR_get_error());
726  ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil);
727  ERR_clear_error();
728  data = ossl_membio2str(out);
729  ossl_pkcs7_set_data(self, data);
730  sk_X509_pop_free(x509s, X509_free);
731 
732  return (ok == 1) ? Qtrue : Qfalse;
733 }
734 
735 static VALUE
737 {
738  VALUE pkey, cert, flags;
739  EVP_PKEY *key;
740  X509 *x509;
741  int flg;
742  PKCS7 *p7;
743  BIO *out;
744  VALUE str;
745 
746  rb_scan_args(argc, argv, "21", &pkey, &cert, &flags);
747  key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */
748  x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
749  flg = NIL_P(flags) ? 0 : NUM2INT(flags);
750  GetPKCS7(self, p7);
751  if(!(out = BIO_new(BIO_s_mem())))
753  if(!PKCS7_decrypt(p7, key, x509, out, flg)){
754  BIO_free(out);
756  }
757  str = ossl_membio2str(out); /* out will be free */
758 
759  return str;
760 }
761 
762 static VALUE
764 {
765  PKCS7 *pkcs7;
766  BIO *out, *in;
767  char buf[4096];
768  int len;
769 
770  in = ossl_obj2bio(data);
771  GetPKCS7(self, pkcs7);
772  if(PKCS7_type_is_signed(pkcs7)){
773  if(!PKCS7_content_new(pkcs7, NID_pkcs7_data))
775  }
776  if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err;
777  for(;;){
778  if((len = BIO_read(in, buf, sizeof(buf))) <= 0)
779  break;
780  if(BIO_write(out, buf, len) != len)
781  goto err;
782  }
783  if(!PKCS7_dataFinal(pkcs7, out)) goto err;
784  ossl_pkcs7_set_data(self, Qnil);
785 
786  err:
787  BIO_free(out);
788  BIO_free(in);
789  if(ERR_peek_error()){
791  }
792 
793  return data;
794 }
795 
796 static VALUE
798 {
799  PKCS7 *pkcs7;
800  VALUE str;
801  long len;
802  unsigned char *p;
803 
804  GetPKCS7(self, pkcs7);
805  if((len = i2d_PKCS7(pkcs7, NULL)) <= 0)
807  str = rb_str_new(0, len);
808  p = (unsigned char *)RSTRING_PTR(str);
809  if(i2d_PKCS7(pkcs7, &p) <= 0)
811  ossl_str_adjust(str, p);
812 
813  return str;
814 }
815 
816 static VALUE
818 {
819  PKCS7 *pkcs7;
820  BIO *out;
821  VALUE str;
822 
823  GetPKCS7(self, pkcs7);
824  if (!(out = BIO_new(BIO_s_mem()))) {
826  }
827  if (!PEM_write_bio_PKCS7(out, pkcs7)) {
828  BIO_free(out);
830  }
831  str = ossl_membio2str(out);
832 
833  return str;
834 }
835 
836 /*
837  * SIGNER INFO
838  */
839 static VALUE
841 {
842  PKCS7_SIGNER_INFO *p7si;
843  VALUE obj;
844 
845  if (!(p7si = PKCS7_SIGNER_INFO_new())) {
847  }
848  WrapPKCS7si(klass, obj, p7si);
849 
850  return obj;
851 }
852 
853 static VALUE
855 {
856  PKCS7_SIGNER_INFO *p7si;
857  EVP_PKEY *pkey;
858  X509 *x509;
859  const EVP_MD *md;
860 
861  pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
862  x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
863  md = GetDigestPtr(digest);
864  GetPKCS7si(self, p7si);
865  if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, (EVP_MD*)md))) {
867  }
868 
869  return self;
870 }
871 
872 static VALUE
874 {
875  PKCS7_SIGNER_INFO *p7si;
876 
877  GetPKCS7si(self, p7si);
878 
879  return ossl_x509name_new(p7si->issuer_and_serial->issuer);
880 }
881 
882 static VALUE
884 {
885  PKCS7_SIGNER_INFO *p7si;
886 
887  GetPKCS7si(self, p7si);
888 
889  return asn1integer_to_num(p7si->issuer_and_serial->serial);
890 }
891 
892 static VALUE
894 {
895  PKCS7_SIGNER_INFO *p7si;
896  ASN1_TYPE *asn1obj;
897 
898  GetPKCS7si(self, p7si);
899 
900  if (!(asn1obj = PKCS7_get_signed_attribute(p7si, NID_pkcs9_signingTime))) {
902  }
903  if (asn1obj->type == V_ASN1_UTCTIME) {
904  return asn1time_to_time(asn1obj->value.utctime);
905  }
906  /*
907  * OR
908  * ossl_raise(ePKCS7Error, "...");
909  * ?
910  */
911 
912  return Qnil;
913 }
914 
915 /*
916  * RECIPIENT INFO
917  */
918 static VALUE
920 {
921  PKCS7_RECIP_INFO *p7ri;
922  VALUE obj;
923 
924  if (!(p7ri = PKCS7_RECIP_INFO_new())) {
926  }
927  WrapPKCS7ri(klass, obj, p7ri);
928 
929  return obj;
930 }
931 
932 static VALUE
934 {
935  PKCS7_RECIP_INFO *p7ri;
936  X509 *x509;
937 
938  x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
939  GetPKCS7ri(self, p7ri);
940  if (!PKCS7_RECIP_INFO_set(p7ri, x509)) {
942  }
943 
944  return self;
945 }
946 
947 static VALUE
949 {
950  PKCS7_RECIP_INFO *p7ri;
951 
952  GetPKCS7ri(self, p7ri);
953 
954  return ossl_x509name_new(p7ri->issuer_and_serial->issuer);
955 }
956 
957 static VALUE
959 {
960  PKCS7_RECIP_INFO *p7ri;
961 
962  GetPKCS7ri(self, p7ri);
963 
964  return asn1integer_to_num(p7ri->issuer_and_serial->serial);
965 }
966 
967 static VALUE
969 {
970  PKCS7_RECIP_INFO *p7ri;
971 
972  GetPKCS7ri(self, p7ri);
973 
974  return asn1str_to_str(p7ri->enc_key);
975 }
976 
977 /*
978  * INIT
979  */
980 void
982 {
989  rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse);
990  rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse);
993  rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1);
1000  rb_define_method(cPKCS7, "add_signer", ossl_pkcs7_add_signer, 1);
1002  rb_define_method(cPKCS7, "add_recipient", ossl_pkcs7_add_recipient, 1);
1004  rb_define_method(cPKCS7, "add_certificate", ossl_pkcs7_add_certificate, 1);
1005  rb_define_method(cPKCS7, "certificates=", ossl_pkcs7_set_certificates, 1);
1007  rb_define_method(cPKCS7, "add_crl", ossl_pkcs7_add_crl, 1);
1010  rb_define_method(cPKCS7, "add_data", ossl_pkcs7_add_data, 1);
1011  rb_define_alias(cPKCS7, "data=", "add_data");
1012  rb_define_method(cPKCS7, "verify", ossl_pkcs7_verify, -1);
1013  rb_define_method(cPKCS7, "decrypt", ossl_pkcs7_decrypt, -1);
1014  rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0);
1015  rb_define_alias(cPKCS7, "to_s", "to_pem");
1016  rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0);
1017 
1019  rb_define_const(cPKCS7, "Signer", cPKCS7Signer);
1023  rb_define_alias(cPKCS7Signer, "name", "issuer");
1026 
1033 
1034 #define DefPKCS7Const(x) rb_define_const(cPKCS7, #x, INT2NUM(PKCS7_##x))
1035 
1036  DefPKCS7Const(TEXT);
1037  DefPKCS7Const(NOCERTS);
1038  DefPKCS7Const(NOSIGS);
1039  DefPKCS7Const(NOCHAIN);
1040  DefPKCS7Const(NOINTERN);
1041  DefPKCS7Const(NOVERIFY);
1042  DefPKCS7Const(DETACHED);
1044  DefPKCS7Const(NOATTR);
1045  DefPKCS7Const(NOSMIMECAP);
1046 }
1047