Ruby  2.5.0dev(2017-10-22revision60238)
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 
72 static void
73 ossl_pkcs7_free(void *ptr)
74 {
75  PKCS7_free(ptr);
76 }
77 
78 static const rb_data_type_t ossl_pkcs7_type = {
79  "OpenSSL/PKCS7",
80  {
81  0, ossl_pkcs7_free,
82  },
84 };
85 
86 static void
87 ossl_pkcs7_signer_info_free(void *ptr)
88 {
89  PKCS7_SIGNER_INFO_free(ptr);
90 }
91 
92 static 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 
100 static void
101 ossl_pkcs7_recip_info_free(void *ptr)
102 {
103  PKCS7_RECIP_INFO_free(ptr);
104 }
105 
106 static 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  */
118 static PKCS7_SIGNER_INFO *
119 ossl_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 
126 static PKCS7_RECIP_INFO *
127 ossl_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 
134 static VALUE
135 ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si)
136 {
137  PKCS7_SIGNER_INFO *pkcs7;
138  VALUE obj;
139 
140  obj = NewPKCS7si(cPKCS7Signer);
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 
148 static PKCS7_SIGNER_INFO *
149 DupPKCS7SignerPtr(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 
161 static VALUE
162 ossl_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 
175 static PKCS7_RECIP_INFO *
176 DupPKCS7RecipientPtr(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  */
192 static VALUE
193 ossl_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  */
217 static VALUE
218 ossl_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  */
252 static VALUE
253 ossl_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  */
296 static VALUE
297 ossl_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 
344 static VALUE
345 ossl_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  */
366 static VALUE
367 ossl_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;
375  arg = ossl_to_der_if_possible(arg);
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);
390  ossl_pkcs7_set_data(self, Qnil);
392 
393  return self;
394 }
395 
396 static VALUE
397 ossl_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 
417 static int
418 ossl_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  */
457 static VALUE
458 ossl_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  */
473 static VALUE
474 ossl_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 
492 static VALUE
493 ossl_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 
506 static VALUE
507 ossl_pkcs7_get_detached(VALUE self)
508 {
509  PKCS7 *p7;
510  GetPKCS7(self, p7);
511  return PKCS7_get_detached(p7) ? Qtrue : Qfalse;
512 }
513 
514 static VALUE
515 ossl_pkcs7_detached_p(VALUE self)
516 {
517  PKCS7 *p7;
518  GetPKCS7(self, p7);
519  return PKCS7_is_detached(p7) ? Qtrue : Qfalse;
520 }
521 
522 static VALUE
523 ossl_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 
535 static VALUE
536 ossl_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 
555 static VALUE
556 ossl_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 
581 static VALUE
582 ossl_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 
597 static VALUE
598 ossl_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 
625 static VALUE
626 ossl_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 
640 static STACK_OF(X509) *
641 pkcs7_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 
663 static STACK_OF(X509_CRL) *
664 pkcs7_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 
686 static VALUE
687 ossl_pkcs7_set_certs_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
688 {
689  return ossl_pkcs7_add_certificate(arg, i);
690 }
691 
692 static VALUE
693 ossl_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 
705 static VALUE
706 ossl_pkcs7_get_certificates(VALUE self)
707 {
708  return ossl_x509_sk2ary(pkcs7_get_certs(self));
709 }
710 
711 static VALUE
712 ossl_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 
726 static VALUE
727 ossl_pkcs7_set_crls_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
728 {
729  return ossl_pkcs7_add_crl(arg, i);
730 }
731 
732 static VALUE
733 ossl_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 
745 static VALUE
746 ossl_pkcs7_get_crls(VALUE self)
747 {
748  return ossl_x509crl_sk2ary(pkcs7_get_crls(self));
749 }
750 
751 static VALUE
752 ossl_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 
795 static VALUE
796 ossl_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 
822 static VALUE
823 ossl_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;
844  ossl_pkcs7_set_data(self, Qnil);
845 
846  err:
847  BIO_free_all(out);
848  BIO_free(in);
849  if(ERR_peek_error()){
851  }
852 
853  return data;
854 }
855 
856 static VALUE
857 ossl_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)
871  ossl_str_adjust(str, p);
872 
873  return str;
874 }
875 
876 static VALUE
877 ossl_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  */
899 static VALUE
900 ossl_pkcs7si_alloc(VALUE klass)
901 {
902  PKCS7_SIGNER_INFO *p7si;
903  VALUE obj;
904 
905  obj = NewPKCS7si(klass);
906  if (!(p7si = PKCS7_SIGNER_INFO_new())) {
908  }
909  SetPKCS7si(obj, p7si);
910 
911  return obj;
912 }
913 
914 static VALUE
915 ossl_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 
933 static VALUE
934 ossl_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 
943 static VALUE
944 ossl_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 
953 static VALUE
954 ossl_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  */
979 static VALUE
980 ossl_pkcs7ri_alloc(VALUE klass)
981 {
982  PKCS7_RECIP_INFO *p7ri;
983  VALUE obj;
984 
985  obj = NewPKCS7ri(klass);
986  if (!(p7ri = PKCS7_RECIP_INFO_new())) {
988  }
989  SetPKCS7ri(obj, p7ri);
990 
991  return obj;
992 }
993 
994 static VALUE
995 ossl_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 
1009 static VALUE
1010 ossl_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 
1019 static VALUE
1020 ossl_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 
1029 static VALUE
1030 ossl_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  */
1042 void
1044 {
1045 #if 0
1046  mOSSL = rb_define_module("OpenSSL");
1048 #endif
1049 
1052  rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
1053  rb_define_singleton_method(cPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1);
1054  rb_define_singleton_method(cPKCS7, "sign", ossl_pkcs7_s_sign, -1);
1055  rb_define_singleton_method(cPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1);
1056  rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse);
1057  rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse);
1058  rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc);
1059  rb_define_method(cPKCS7, "initialize_copy", ossl_pkcs7_copy, 1);
1060  rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1);
1061  rb_define_method(cPKCS7, "type=", ossl_pkcs7_set_type, 1);
1062  rb_define_method(cPKCS7, "type", ossl_pkcs7_get_type, 0);
1063  rb_define_method(cPKCS7, "detached=", ossl_pkcs7_set_detached, 1);
1064  rb_define_method(cPKCS7, "detached", ossl_pkcs7_get_detached, 0);
1065  rb_define_method(cPKCS7, "detached?", ossl_pkcs7_detached_p, 0);
1066  rb_define_method(cPKCS7, "cipher=", ossl_pkcs7_set_cipher, 1);
1067  rb_define_method(cPKCS7, "add_signer", ossl_pkcs7_add_signer, 1);
1068  rb_define_method(cPKCS7, "signers", ossl_pkcs7_get_signer, 0);
1069  rb_define_method(cPKCS7, "add_recipient", ossl_pkcs7_add_recipient, 1);
1070  rb_define_method(cPKCS7, "recipients", ossl_pkcs7_get_recipient, 0);
1071  rb_define_method(cPKCS7, "add_certificate", ossl_pkcs7_add_certificate, 1);
1072  rb_define_method(cPKCS7, "certificates=", ossl_pkcs7_set_certificates, 1);
1073  rb_define_method(cPKCS7, "certificates", ossl_pkcs7_get_certificates, 0);
1074  rb_define_method(cPKCS7, "add_crl", ossl_pkcs7_add_crl, 1);
1075  rb_define_method(cPKCS7, "crls=", ossl_pkcs7_set_crls, 1);
1076  rb_define_method(cPKCS7, "crls", ossl_pkcs7_get_crls, 0);
1077  rb_define_method(cPKCS7, "add_data", ossl_pkcs7_add_data, 1);
1078  rb_define_alias(cPKCS7, "data=", "add_data");
1079  rb_define_method(cPKCS7, "verify", ossl_pkcs7_verify, -1);
1080  rb_define_method(cPKCS7, "decrypt", ossl_pkcs7_decrypt, -1);
1081  rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0);
1082  rb_define_alias(cPKCS7, "to_s", "to_pem");
1083  rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0);
1084 
1086  rb_define_const(cPKCS7, "Signer", cPKCS7Signer);
1087  rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc);
1088  rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3);
1089  rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0);
1090  rb_define_alias(cPKCS7Signer, "name", "issuer");
1091  rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0);
1092  rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0);
1093 
1095  rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc);
1096  rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1);
1097  rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0);
1098  rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0);
1099  rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0);
1100 
1101 #define DefPKCS7Const(x) rb_define_const(cPKCS7, #x, INT2NUM(PKCS7_##x))
1102 
1103  DefPKCS7Const(TEXT);
1104  DefPKCS7Const(NOCERTS);
1105  DefPKCS7Const(NOSIGS);
1106  DefPKCS7Const(NOCHAIN);
1107  DefPKCS7Const(NOINTERN);
1108  DefPKCS7Const(NOVERIFY);
1109  DefPKCS7Const(DETACHED);
1111  DefPKCS7Const(NOATTR);
1112  DefPKCS7Const(NOSMIMECAP);
1113 }
VALUE mOSSL
Definition: ossl.c:231
int *VALUE ossl_x509_sk2ary(const STACK_OF(X509) *certs)
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
size_t strlen(const char *)
#define NUM2INT(x)
Definition: ruby.h:684
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:68
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:821
#define Qtrue
Definition: ruby.h:437
EVP_PKEY * GetPrivPKeyPtr(VALUE obj)
Definition: ossl_pkey.c:216
#define ossl_str_adjust(str, p)
Definition: ossl.h:82
#define ossl_pkcs7_set_data(o, v)
Definition: ossl_pkcs7.c:59
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:924
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:984
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define DATA_PTR(dta)
Definition: ruby.h:1106
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
VALUE asn1integer_to_num(const ASN1_INTEGER *ai)
Definition: ossl_asn1.c:101
#define ossl_pkcs7_set_err_string(o, v)
Definition: ossl_pkcs7.c:61
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:29
VALUE cPKCS7Recipient
Definition: ossl_pkcs7.c:69
#define rb_ary_new2
Definition: intern.h:90
VALUE rb_eArgError
Definition: error.c:802
#define sym(x)
Definition: date_core.c:3721
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1851
X509 * GetX509CertPtr(VALUE)
Definition: ossl_x509cert.c:71
VALUE ossl_to_der_if_possible(VALUE obj)
Definition: ossl.c:255
#define DefPKCS7Const(x)
void ossl_clear_error(void)
Definition: ossl.c:304
#define NewPKCS7si(klass)
Definition: ossl_pkcs7.c:27
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
STACK_OF(X509) *ossl_x509_ary2sk(VALUE)
void rb_attr(VALUE, ID, int, int, int)
Definition: vm_method.c:1137
VALUE rb_ary_new(void)
Definition: array.c:499
const EVP_CIPHER * ossl_evp_get_cipherbyname(VALUE obj)
Definition: ossl_cipher.c:52
#define OSSL_BIO_reset(bio)
Definition: ossl.h:110
#define NIL_P(v)
Definition: ruby.h:451
#define SetPKCS7si(obj, p7si)
Definition: ossl_pkcs7.c:29
#define GetPKCS7(obj, pkcs7)
Definition: ossl_pkcs7.c:20
#define SetPKCS7(obj, pkcs7)
Definition: ossl_pkcs7.c:14
#define numberof(ary)
Definition: ossl_pkcs7.c:57
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2691
VALUE eOSSLError
Definition: ossl.c:236
int argc
Definition: ruby.c:187
#define Qfalse
Definition: ruby.h:436
#define rb_str_new2
Definition: intern.h:835
int err
Definition: win32.c:135
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)
#define SetPKCS7ri(obj, p7ri)
Definition: ossl_pkcs7.c:44
const EVP_MD * ossl_evp_get_digestbyname(VALUE obj)
Definition: ossl_digest.c:45
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1908
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4309
#define PRIsVALUE
Definition: ruby.h:135
#define Qnil
Definition: ruby.h:438
VALUE rb_eStandardError
Definition: error.c:799
unsigned long VALUE
Definition: ruby.h:85
VALUE ePKCS7Error
Definition: ossl_pkcs7.c:70
#define OSSL_Debug
Definition: ossl.h:144
#define NewPKCS7(klass)
Definition: ossl_pkcs7.c:12
X509_STORE * GetX509StorePtr(VALUE)
#define GetPKCS7ri(obj, p7ri)
Definition: ossl_pkcs7.c:50
register unsigned int len
Definition: zonetab.h:51
#define RSTRING_PTR(str)
Definition: ruby.h:975
VALUE asn1str_to_str(const ASN1_STRING *str)
Definition: ossl_asn1.c:92
#define GetPKCS7si(obj, p7si)
Definition: ossl_pkcs7.c:35
VALUE asn1time_to_time(const ASN1_TIME *time)
Definition: ossl_asn1.c:20
VALUE cPKCS7
Definition: ossl_pkcs7.c:67
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
#define ossl_pkcs7_get_data(o)
Definition: ossl_pkcs7.c:60
const char * name
Definition: nkf.c:208
#define ID2SYM(x)
Definition: ruby.h:383
int nid
#define NewPKCS7ri(klass)
Definition: ossl_pkcs7.c:42
void Init_ossl_pkcs7(void)
Definition: ossl_pkcs7.c:1043
VALUE ossl_x509name_new(X509_NAME *)
Definition: ossl_x509name.c:56
Definition: nkf.c:122
#define rb_check_frozen(obj)
Definition: intern.h:271
VALUE rb_define_module(const char *name)
Definition: class.c:768
X509_CRL * GetX509CRLPtr(VALUE)
Definition: ossl_x509crl.c:51
#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
char ** argv
Definition: ruby.c:188
#define StringValue(v)
Definition: ruby.h:569
#define rb_sym2str(sym)
Definition: console.c:107
VALUE rb_str_new(const char *, long)
Definition: string.c:737