rubysl-openssl 0.0.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +0 -1
  3. data/.travis.yml +7 -0
  4. data/README.md +2 -2
  5. data/Rakefile +0 -1
  6. data/ext/rubysl/openssl/extconf.h +50 -0
  7. data/ext/rubysl/openssl/extconf.rb +144 -0
  8. data/ext/rubysl/openssl/openssl_missing.c +343 -0
  9. data/ext/rubysl/openssl/openssl_missing.h +191 -0
  10. data/ext/rubysl/openssl/ossl.c +552 -0
  11. data/ext/rubysl/openssl/ossl.h +233 -0
  12. data/ext/rubysl/openssl/ossl_asn1.c +1160 -0
  13. data/ext/rubysl/openssl/ossl_asn1.h +59 -0
  14. data/ext/rubysl/openssl/ossl_bio.c +86 -0
  15. data/ext/rubysl/openssl/ossl_bio.h +21 -0
  16. data/ext/rubysl/openssl/ossl_bn.c +852 -0
  17. data/ext/rubysl/openssl/ossl_bn.h +25 -0
  18. data/ext/rubysl/openssl/ossl_cipher.c +569 -0
  19. data/ext/rubysl/openssl/ossl_cipher.h +22 -0
  20. data/ext/rubysl/openssl/ossl_config.c +75 -0
  21. data/ext/rubysl/openssl/ossl_config.h +22 -0
  22. data/ext/rubysl/openssl/ossl_digest.c +259 -0
  23. data/ext/rubysl/openssl/ossl_digest.h +22 -0
  24. data/ext/rubysl/openssl/ossl_engine.c +411 -0
  25. data/ext/rubysl/openssl/ossl_engine.h +20 -0
  26. data/ext/rubysl/openssl/ossl_hmac.c +268 -0
  27. data/ext/rubysl/openssl/ossl_hmac.h +19 -0
  28. data/ext/rubysl/openssl/ossl_ns_spki.c +257 -0
  29. data/ext/rubysl/openssl/ossl_ns_spki.h +21 -0
  30. data/ext/rubysl/openssl/ossl_ocsp.c +769 -0
  31. data/ext/rubysl/openssl/ossl_ocsp.h +24 -0
  32. data/ext/rubysl/openssl/ossl_pkcs12.c +210 -0
  33. data/ext/rubysl/openssl/ossl_pkcs12.h +15 -0
  34. data/ext/rubysl/openssl/ossl_pkcs5.c +99 -0
  35. data/ext/rubysl/openssl/ossl_pkcs5.h +6 -0
  36. data/ext/rubysl/openssl/ossl_pkcs7.c +1039 -0
  37. data/ext/rubysl/openssl/ossl_pkcs7.h +22 -0
  38. data/ext/rubysl/openssl/ossl_pkey.c +240 -0
  39. data/ext/rubysl/openssl/ossl_pkey.h +141 -0
  40. data/ext/rubysl/openssl/ossl_pkey_dh.c +532 -0
  41. data/ext/rubysl/openssl/ossl_pkey_dsa.c +484 -0
  42. data/ext/rubysl/openssl/ossl_pkey_ec.c +1593 -0
  43. data/ext/rubysl/openssl/ossl_pkey_rsa.c +593 -0
  44. data/ext/rubysl/openssl/ossl_rand.c +202 -0
  45. data/ext/rubysl/openssl/ossl_rand.h +20 -0
  46. data/ext/rubysl/openssl/ossl_ssl.c +1484 -0
  47. data/ext/rubysl/openssl/ossl_ssl.h +36 -0
  48. data/ext/rubysl/openssl/ossl_ssl_session.c +307 -0
  49. data/ext/rubysl/openssl/ossl_version.h +16 -0
  50. data/ext/rubysl/openssl/ossl_x509.c +104 -0
  51. data/ext/rubysl/openssl/ossl_x509.h +114 -0
  52. data/ext/rubysl/openssl/ossl_x509attr.c +274 -0
  53. data/ext/rubysl/openssl/ossl_x509cert.c +764 -0
  54. data/ext/rubysl/openssl/ossl_x509crl.c +535 -0
  55. data/ext/rubysl/openssl/ossl_x509ext.c +458 -0
  56. data/ext/rubysl/openssl/ossl_x509name.c +399 -0
  57. data/ext/rubysl/openssl/ossl_x509req.c +466 -0
  58. data/ext/rubysl/openssl/ossl_x509revoked.c +229 -0
  59. data/ext/rubysl/openssl/ossl_x509store.c +625 -0
  60. data/ext/rubysl/openssl/ruby_missing.h +41 -0
  61. data/lib/openssl.rb +1 -0
  62. data/lib/openssl/bn.rb +35 -0
  63. data/lib/openssl/buffering.rb +241 -0
  64. data/lib/openssl/cipher.rb +65 -0
  65. data/lib/openssl/config.rb +316 -0
  66. data/lib/openssl/digest.rb +61 -0
  67. data/lib/openssl/net/ftptls.rb +53 -0
  68. data/lib/openssl/net/telnets.rb +251 -0
  69. data/lib/openssl/pkcs7.rb +25 -0
  70. data/lib/openssl/ssl-internal.rb +187 -0
  71. data/lib/openssl/ssl.rb +1 -0
  72. data/lib/openssl/x509-internal.rb +153 -0
  73. data/lib/openssl/x509.rb +1 -0
  74. data/lib/rubysl/openssl.rb +28 -0
  75. data/lib/rubysl/openssl/version.rb +5 -0
  76. data/rubysl-openssl.gemspec +19 -18
  77. data/spec/cipher_spec.rb +16 -0
  78. data/spec/config/freeze_spec.rb +17 -0
  79. data/spec/hmac/digest_spec.rb +15 -0
  80. data/spec/hmac/hexdigest_spec.rb +15 -0
  81. data/spec/random/pseudo_bytes_spec.rb +5 -0
  82. data/spec/random/random_bytes_spec.rb +5 -0
  83. data/spec/random/shared/random_bytes.rb +28 -0
  84. data/spec/shared/constants.rb +11 -0
  85. data/spec/x509/name/parse_spec.rb +47 -0
  86. metadata +153 -89
  87. data/lib/rubysl-openssl.rb +0 -7
  88. data/lib/rubysl-openssl/version.rb +0 -5
@@ -0,0 +1,24 @@
1
+ /*
2
+ * $Id: ossl_ocsp.h 11708 2007-02-12 23:01:19Z shyouhei $
3
+ * 'OpenSSL for Ruby' project
4
+ * Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz>
5
+ * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
6
+ * All rights reserved.
7
+ */
8
+ /*
9
+ * This program is licenced under the same licence as Ruby.
10
+ * (See the file 'LICENCE'.)
11
+ */
12
+ #if !defined(_OSSL_OCSP_H_)
13
+ #define _OSSL_OCSP_H_
14
+
15
+ #if defined(OSSL_OCSP_ENABLED)
16
+ extern VALUE mOCSP;
17
+ extern VALUE cOPCSReq;
18
+ extern VALUE cOPCSRes;
19
+ extern VALUE cOPCSBasicRes;
20
+ #endif
21
+
22
+ void Init_ossl_ocsp(void);
23
+
24
+ #endif /* _OSSL_OCSP_H_ */
@@ -0,0 +1,210 @@
1
+ /*
2
+ * This program is licenced under the same licence as Ruby.
3
+ * (See the file 'LICENCE'.)
4
+ * $Id: ossl_pkcs12.c 12496 2007-06-08 15:02:04Z technorama $
5
+ */
6
+ #include "ossl.h"
7
+
8
+ #define WrapPKCS12(klass, obj, p12) do { \
9
+ if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
10
+ obj = Data_Wrap_Struct(klass, 0, PKCS12_free, p12); \
11
+ } while (0)
12
+
13
+ #define GetPKCS12(obj, p12) do { \
14
+ Data_Get_Struct(obj, PKCS12, p12); \
15
+ if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
16
+ } while (0)
17
+
18
+ #define SafeGetPKCS12(obj, p12) do { \
19
+ OSSL_Check_Kind(obj, cPKCS12); \
20
+ GetPKCS12(obj, p12); \
21
+ } while (0)
22
+
23
+ #define ossl_pkcs12_set_key(o,v) rb_iv_set((o), "@key", (v))
24
+ #define ossl_pkcs12_set_cert(o,v) rb_iv_set((o), "@certificate", (v))
25
+ #define ossl_pkcs12_set_ca_certs(o,v) rb_iv_set((o), "@ca_certs", (v))
26
+ #define ossl_pkcs12_get_key(o) rb_iv_get((o), "@key")
27
+ #define ossl_pkcs12_get_cert(o) rb_iv_get((o), "@certificate")
28
+ #define ossl_pkcs12_get_ca_certs(o) rb_iv_get((o), "@ca_certs")
29
+
30
+ /*
31
+ * Classes
32
+ */
33
+ VALUE cPKCS12;
34
+ VALUE ePKCS12Error;
35
+
36
+ /*
37
+ * Private
38
+ */
39
+ static VALUE
40
+ ossl_pkcs12_s_allocate(VALUE klass)
41
+ {
42
+ PKCS12 *p12;
43
+ VALUE obj;
44
+
45
+ if(!(p12 = PKCS12_new())) ossl_raise(ePKCS12Error, NULL);
46
+ WrapPKCS12(klass, obj, p12);
47
+
48
+ return obj;
49
+ }
50
+
51
+ /*
52
+ * call-seq:
53
+ * PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]])
54
+ *
55
+ * === Parameters
56
+ * * +pass+ - string
57
+ * * +name+ - A string describing the key.
58
+ * * +key+ - Any PKey.
59
+ * * +cert+ - A X509::Certificate.
60
+ * * * The public_key portion of the certificate must contain a valid public key.
61
+ * * * The not_before and not_after fields must be filled in.
62
+ * * +ca+ - An optional array of X509::Certificate's.
63
+ * * +key_pbe+ - string
64
+ * * +cert_pbe+ - string
65
+ * * +key_iter+ - integer
66
+ * * +mac_iter+ - integer
67
+ * * +keytype+ - An integer representing an MSIE specific extension.
68
+ *
69
+ * Any optional arguments may be supplied as nil to preserve the OpenSSL defaults.
70
+ *
71
+ * See the OpenSSL documentation for PKCS12_create().
72
+ */
73
+ static VALUE
74
+ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
75
+ {
76
+ VALUE pass, name, pkey, cert, ca, key_nid, cert_nid, key_iter, mac_iter, keytype;
77
+ VALUE obj;
78
+ char *passphrase, *friendlyname;
79
+ EVP_PKEY *key;
80
+ X509 *x509;
81
+ STACK_OF(X509) *x509s;
82
+ int nkey = 0, ncert = 0, kiter = 0, miter = 0, ktype = 0;
83
+ PKCS12 *p12;
84
+
85
+ rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype);
86
+ passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
87
+ friendlyname = NIL_P(name) ? NULL : StringValuePtr(name);
88
+ key = GetPKeyPtr(pkey);
89
+ x509 = GetX509CertPtr(cert);
90
+ x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca);
91
+ /* TODO: make a VALUE to nid function */
92
+ if (!NIL_P(key_nid)) {
93
+ if ((nkey = OBJ_txt2nid(StringValuePtr(key_nid))) == NID_undef)
94
+ rb_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(key_nid));
95
+ }
96
+ if (!NIL_P(cert_nid)) {
97
+ if ((ncert = OBJ_txt2nid(StringValuePtr(cert_nid))) == NID_undef)
98
+ rb_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(cert_nid));
99
+ }
100
+ if (!NIL_P(key_iter))
101
+ kiter = NUM2INT(key_iter);
102
+ if (!NIL_P(mac_iter))
103
+ miter = NUM2INT(mac_iter);
104
+ if (!NIL_P(keytype))
105
+ ktype = NUM2INT(keytype);
106
+
107
+ p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s,
108
+ nkey, ncert, kiter, miter, ktype);
109
+ sk_X509_pop_free(x509s, X509_free);
110
+ if(!p12) ossl_raise(ePKCS12Error, NULL);
111
+ WrapPKCS12(cPKCS12, obj, p12);
112
+
113
+ ossl_pkcs12_set_key(obj, pkey);
114
+ ossl_pkcs12_set_cert(obj, cert);
115
+ ossl_pkcs12_set_ca_certs(obj, ca);
116
+
117
+ return obj;
118
+ }
119
+
120
+ /*
121
+ * call-seq:
122
+ * PKCS12.new -> pkcs12
123
+ * PKCS12.new(str) -> pkcs12
124
+ * PKCS12.new(str, pass) -> pkcs12
125
+ *
126
+ * === Parameters
127
+ * * +str+ - Must be a DER encoded PKCS12 string.
128
+ * * +pass+ - string
129
+ */
130
+ static VALUE
131
+ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
132
+ {
133
+ BIO *in;
134
+ VALUE arg, pass, pkey, cert, ca;
135
+ char *passphrase;
136
+ EVP_PKEY *key;
137
+ X509 *x509;
138
+ STACK_OF(X509) *x509s = NULL;
139
+ int st = 0;
140
+
141
+ if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self;
142
+ passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
143
+ in = ossl_obj2bio(arg);
144
+ d2i_PKCS12_bio(in, (PKCS12 **)&DATA_PTR(self));
145
+ BIO_free(in);
146
+
147
+ pkey = cert = ca = Qnil;
148
+ if(!PKCS12_parse((PKCS12*)DATA_PTR(self), passphrase, &key, &x509, &x509s))
149
+ ossl_raise(ePKCS12Error, "PKCS12_parse");
150
+ pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key,
151
+ &st); /* NO DUP */
152
+ if(st) goto err;
153
+ cert = rb_protect((VALUE(*)_((VALUE)))ossl_x509_new, (VALUE)x509, &st);
154
+ if(st) goto err;
155
+ if(x509s){
156
+ ca =
157
+ rb_protect((VALUE(*)_((VALUE)))ossl_x509_sk2ary, (VALUE)x509s, &st);
158
+ if(st) goto err;
159
+ }
160
+
161
+ err:
162
+ X509_free(x509);
163
+ sk_X509_pop_free(x509s, X509_free);
164
+ ossl_pkcs12_set_key(self, pkey);
165
+ ossl_pkcs12_set_cert(self, cert);
166
+ ossl_pkcs12_set_ca_certs(self, ca);
167
+ if(st) rb_jump_tag(st);
168
+
169
+ return self;
170
+ }
171
+
172
+ static VALUE
173
+ ossl_pkcs12_to_der(VALUE self)
174
+ {
175
+ PKCS12 *p12;
176
+ VALUE str;
177
+ long len;
178
+ unsigned char *p;
179
+
180
+ GetPKCS12(self, p12);
181
+ if((len = i2d_PKCS12(p12, NULL)) <= 0)
182
+ ossl_raise(ePKCS12Error, NULL);
183
+ str = rb_str_new(0, len);
184
+ p = RSTRING_PTR(str);
185
+ if(i2d_PKCS12(p12, &p) <= 0)
186
+ ossl_raise(ePKCS12Error, NULL);
187
+ ossl_str_adjust(str, p);
188
+
189
+ return str;
190
+ }
191
+
192
+ void
193
+ Init_ossl_pkcs12()
194
+ {
195
+ /*
196
+ * Defines a file format commonly used to store private keys with
197
+ * accompanying public key certificates, protected with a password-based
198
+ * symmetric key.
199
+ */
200
+ cPKCS12 = rb_define_class_under(mOSSL, "PKCS12", rb_cObject);
201
+ ePKCS12Error = rb_define_class_under(cPKCS12, "PKCS12Error", eOSSLError);
202
+ rb_define_singleton_method(cPKCS12, "create", ossl_pkcs12_s_create, -1);
203
+
204
+ rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate);
205
+ rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse);
206
+ rb_attr(cPKCS12, rb_intern("certificate"), 1, 0, Qfalse);
207
+ rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse);
208
+ rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1);
209
+ rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0);
210
+ }
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This program is licenced under the same licence as Ruby.
3
+ * (See the file 'LICENCE'.)
4
+ * $Id: ossl_pkcs12.h 12496 2007-06-08 15:02:04Z technorama $
5
+ */
6
+ #if !defined(_OSSL_PKCS12_H_)
7
+ #define _OSSL_PKCS12_H_
8
+
9
+ extern VALUE cPKCS12;
10
+ extern VALUE ePKCS12Error;
11
+
12
+ void Init_ossl_pkcs12(void);
13
+
14
+ #endif /* _OSSL_PKCS12_H_ */
15
+
@@ -0,0 +1,99 @@
1
+ /*
2
+ * $Id$
3
+ * Copyright (C) 2007 Technorama Ltd. <oss-ruby@technorama.net>
4
+ */
5
+ #include "ossl.h"
6
+
7
+ VALUE mPKCS5;
8
+ VALUE ePKCS5;
9
+
10
+ /*
11
+ * call-seq:
12
+ * PKCS5.pbkdf2_hmac(pass, salt, iter, keylen, digest) => string
13
+ *
14
+ * === Parameters
15
+ * * +pass+ - string
16
+ * * +salt+ - string
17
+ * * +iter+ - integer - should be greater than 1000. 2000 is better.
18
+ * * +keylen+ - integer
19
+ * * +digest+ - a string or OpenSSL::Digest object.
20
+ *
21
+ * Available in OpenSSL 0.9.9?.
22
+ *
23
+ * Digests other than SHA1 may not be supported by other cryptography libraries.
24
+ */
25
+ static VALUE
26
+ ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen, VALUE digest)
27
+ {
28
+ #ifdef HAVE_PKCS5_PBKDF2_HMAC
29
+ VALUE str;
30
+ const EVP_MD *md;
31
+ int len = NUM2INT(keylen);
32
+ unsigned char* salt_p;
33
+ unsigned char* str_p;
34
+
35
+ StringValue(pass);
36
+ StringValue(salt);
37
+ md = GetDigestPtr(digest);
38
+ str = rb_str_new(0, len);
39
+ salt_p = (unsigned char*)RSTRING_PTR(salt);
40
+ str_p = (unsigned char*)RSTRING_PTR(str);
41
+
42
+ if (PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LEN(pass), salt_p, RSTRING_LEN(salt), NUM2INT(iter), md, len, str_p) != 1)
43
+ ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC");
44
+
45
+ return str;
46
+ #else
47
+ rb_notimplement();
48
+ #endif
49
+ }
50
+
51
+
52
+ /*
53
+ * call-seq:
54
+ * PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, keylen) => string
55
+ *
56
+ * === Parameters
57
+ * * +pass+ - string
58
+ * * +salt+ - string
59
+ * * +iter+ - integer - should be greater than 1000. 2000 is better.
60
+ * * +keylen+ - integer
61
+ *
62
+ * This method is available almost any version OpenSSL.
63
+ *
64
+ * Conforms to rfc2898.
65
+ */
66
+ static VALUE
67
+ ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen)
68
+ {
69
+ #ifdef HAVE_PKCS5_PBKDF2_HMAC_SHA1
70
+ VALUE str;
71
+ int len = NUM2INT(keylen);
72
+
73
+ StringValue(pass);
74
+ StringValue(salt);
75
+
76
+ str = rb_str_new(0, len);
77
+
78
+ if (PKCS5_PBKDF2_HMAC_SHA1(RSTRING_PTR(pass), RSTRING_LEN(pass), RSTRING_PTR(salt), RSTRING_LEN(salt), NUM2INT(iter), len, RSTRING_PTR(str)) != 1)
79
+ ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC_SHA1");
80
+
81
+ return str;
82
+ #else
83
+ rb_notimplement();
84
+ #endif
85
+ }
86
+
87
+ void
88
+ Init_ossl_pkcs5()
89
+ {
90
+ /*
91
+ * Password-based Encryption
92
+ *
93
+ */
94
+ mPKCS5 = rb_define_module_under(mOSSL, "PKCS5");
95
+ ePKCS5 = rb_define_class_under(mPKCS5, "PKCS5Error", eOSSLError);
96
+
97
+ rb_define_module_function(mPKCS5, "pbkdf2_hmac", ossl_pkcs5_pbkdf2_hmac, 5);
98
+ rb_define_module_function(mPKCS5, "pbkdf2_hmac_sha1", ossl_pkcs5_pbkdf2_hmac_sha1, 4);
99
+ }
@@ -0,0 +1,6 @@
1
+ #if !defined(_OSSL_PKCS5_H_)
2
+ #define _OSSL_PKCS5_H_
3
+
4
+ void Init_ossl_pkcs5(void);
5
+
6
+ #endif /* _OSSL_PKCS5_H_ */
@@ -0,0 +1,1039 @@
1
+ /*
2
+ * $Id: ossl_pkcs7.c 28367 2010-06-21 09:18:59Z shyouhei $
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) (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
+ */
74
+ VALUE cPKCS7;
75
+ VALUE cPKCS7Signer;
76
+ VALUE cPKCS7Recipient;
77
+ VALUE ePKCS7Error;
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 *
97
+ DupPKCS7SignerPtr(VALUE obj)
98
+ {
99
+ PKCS7_SIGNER_INFO *p7si, *pkcs7;
100
+
101
+ SafeGetPKCS7si(obj, p7si);
102
+ if (!(pkcs7 = PKCS7_SIGNER_INFO_dup(p7si))) {
103
+ ossl_raise(ePKCS7Error, NULL);
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 *
123
+ DupPKCS7RecipientPtr(VALUE obj)
124
+ {
125
+ PKCS7_RECIP_INFO *p7ri, *pkcs7;
126
+
127
+ SafeGetPKCS7ri(obj, p7ri);
128
+ if (!(pkcs7 = PKCS7_RECIP_INFO_dup(p7ri))) {
129
+ ossl_raise(ePKCS7Error, NULL);
130
+ }
131
+
132
+ return pkcs7;
133
+ }
134
+
135
+ /*
136
+ * call-seq:
137
+ * PKCS7.read_smime(string) => pkcs7
138
+ */
139
+ static VALUE
140
+ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
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);
154
+ ossl_pkcs7_set_err_string(ret, Qnil);
155
+
156
+ return ret;
157
+ }
158
+
159
+ /*
160
+ * call-seq:
161
+ * PKCS7.write_smime(pkcs7 [, data [, flags]]) => string
162
+ */
163
+ static VALUE
164
+ ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
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);
181
+ ossl_raise(ePKCS7Error, NULL);
182
+ }
183
+ if(!SMIME_write_PKCS7(out, p7, in, flg)){
184
+ BIO_free(out);
185
+ BIO_free(in);
186
+ ossl_raise(ePKCS7Error, NULL);
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
199
+ ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
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);
226
+ ossl_raise(ePKCS7Error, NULL);
227
+ }
228
+ WrapPKCS7(cPKCS7, ret, pkcs7);
229
+ ossl_pkcs7_set_data(ret, data);
230
+ ossl_pkcs7_set_err_string(ret, Qnil);
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
242
+ ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
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);
278
+ ossl_raise(ePKCS7Error, NULL);
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
289
+ ossl_pkcs7_alloc(VALUE klass)
290
+ {
291
+ PKCS7 *pkcs7;
292
+ VALUE obj;
293
+
294
+ if (!(pkcs7 = PKCS7_new())) {
295
+ ossl_raise(ePKCS7Error, NULL);
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
310
+ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
311
+ {
312
+ PKCS7 *p7;
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, (PKCS7 **)&DATA_PTR(self), NULL, NULL);
321
+ if (!p7) {
322
+ BIO_reset(in);
323
+ p7 = d2i_PKCS7_bio(in, (PKCS7 **)&DATA_PTR(self));
324
+ }
325
+ BIO_free(in);
326
+ ossl_pkcs7_set_data(self, Qnil);
327
+ ossl_pkcs7_set_err_string(self, Qnil);
328
+
329
+ return self;
330
+ }
331
+
332
+ static VALUE
333
+ ossl_pkcs7_copy(VALUE self, VALUE other)
334
+ {
335
+ PKCS7 *a, *b, *pkcs7;
336
+
337
+ rb_check_frozen(self);
338
+ if (self == other) return self;
339
+
340
+ GetPKCS7(self, a);
341
+ SafeGetPKCS7(other, b);
342
+
343
+ pkcs7 = PKCS7_dup(b);
344
+ if (!pkcs7) {
345
+ ossl_raise(ePKCS7Error, NULL);
346
+ }
347
+ DATA_PTR(self) = pkcs7;
348
+ PKCS7_free(a);
349
+
350
+ return self;
351
+ }
352
+
353
+ static int
354
+ ossl_pkcs7_sym2typeid(VALUE sym)
355
+ {
356
+ int i, ret = Qnil;
357
+ const char *s;
358
+
359
+ static struct {
360
+ const char *name;
361
+ int nid;
362
+ } p7_type_tab[] = {
363
+ { "signed", NID_pkcs7_signed },
364
+ { "data", NID_pkcs7_data },
365
+ { "signedAndEnveloped", NID_pkcs7_signedAndEnveloped },
366
+ { "enveloped", NID_pkcs7_enveloped },
367
+ { "encrypted", NID_pkcs7_encrypted },
368
+ { "digest", NID_pkcs7_digest },
369
+ { NULL, 0 },
370
+ };
371
+
372
+ if(TYPE(sym) == T_SYMBOL) s = rb_id2name(SYM2ID(sym));
373
+ else s = StringValuePtr(sym);
374
+ for(i = 0; i < numberof(p7_type_tab); i++){
375
+ if(p7_type_tab[i].name == NULL)
376
+ ossl_raise(ePKCS7Error, "unknown type \"%s\"", s);
377
+ if(strcmp(p7_type_tab[i].name, s) == 0){
378
+ ret = p7_type_tab[i].nid;
379
+ break;
380
+ }
381
+ }
382
+
383
+ return ret;
384
+ }
385
+
386
+ /*
387
+ * call-seq:
388
+ * pkcs7.type = type => type
389
+ */
390
+ static VALUE
391
+ ossl_pkcs7_set_type(VALUE self, VALUE type)
392
+ {
393
+ PKCS7 *p7;
394
+
395
+ GetPKCS7(self, p7);
396
+ if(!PKCS7_set_type(p7, ossl_pkcs7_sym2typeid(type)))
397
+ ossl_raise(ePKCS7Error, NULL);
398
+
399
+ return type;
400
+ }
401
+
402
+ /*
403
+ * call-seq:
404
+ * pkcs7.type => string or nil
405
+ */
406
+ static VALUE
407
+ ossl_pkcs7_get_type(VALUE self)
408
+ {
409
+ PKCS7 *p7;
410
+
411
+ GetPKCS7(self, p7);
412
+ if(PKCS7_type_is_signed(p7))
413
+ return ID2SYM(rb_intern("signed"));
414
+ if(PKCS7_type_is_encrypted(p7))
415
+ return ID2SYM(rb_intern("encrypted"));
416
+ if(PKCS7_type_is_enveloped(p7))
417
+ return ID2SYM(rb_intern("enveloped"));
418
+ if(PKCS7_type_is_signedAndEnveloped(p7))
419
+ return ID2SYM(rb_intern("signedAndEnveloped"));
420
+ if(PKCS7_type_is_data(p7))
421
+ return ID2SYM(rb_intern("data"));
422
+ return Qnil;
423
+ }
424
+
425
+ static VALUE
426
+ ossl_pkcs7_set_detached(VALUE self, VALUE flag)
427
+ {
428
+ PKCS7 *p7;
429
+
430
+ GetPKCS7(self, p7);
431
+ if(flag != Qtrue && flag != Qfalse)
432
+ ossl_raise(ePKCS7Error, "must specify a boolean");
433
+ if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0))
434
+ ossl_raise(ePKCS7Error, NULL);
435
+
436
+ return flag;
437
+ }
438
+
439
+ static VALUE
440
+ ossl_pkcs7_get_detached(VALUE self)
441
+ {
442
+ PKCS7 *p7;
443
+ GetPKCS7(self, p7);
444
+ return PKCS7_get_detached(p7) ? Qtrue : Qfalse;
445
+ }
446
+
447
+ static VALUE
448
+ ossl_pkcs7_detached_p(VALUE self)
449
+ {
450
+ PKCS7 *p7;
451
+ GetPKCS7(self, p7);
452
+ return PKCS7_is_detached(p7) ? Qtrue : Qfalse;
453
+ }
454
+
455
+ static VALUE
456
+ ossl_pkcs7_set_cipher(VALUE self, VALUE cipher)
457
+ {
458
+ PKCS7 *pkcs7;
459
+
460
+ GetPKCS7(self, pkcs7);
461
+ if (!PKCS7_set_cipher(pkcs7, GetCipherPtr(cipher))) {
462
+ ossl_raise(ePKCS7Error, NULL);
463
+ }
464
+
465
+ return cipher;
466
+ }
467
+
468
+ static VALUE
469
+ ossl_pkcs7_add_signer(VALUE self, VALUE signer)
470
+ {
471
+ PKCS7 *pkcs7;
472
+ PKCS7_SIGNER_INFO *p7si;
473
+
474
+ p7si = DupPKCS7SignerPtr(signer); /* NEED TO DUP */
475
+ GetPKCS7(self, pkcs7);
476
+ if (!PKCS7_add_signer(pkcs7, p7si)) {
477
+ PKCS7_SIGNER_INFO_free(p7si);
478
+ ossl_raise(ePKCS7Error, "Could not add signer.");
479
+ }
480
+ if (PKCS7_type_is_signed(pkcs7)){
481
+ PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
482
+ V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data));
483
+ }
484
+
485
+ return self;
486
+ }
487
+
488
+ static VALUE
489
+ ossl_pkcs7_get_signer(VALUE self)
490
+ {
491
+ PKCS7 *pkcs7;
492
+ STACK_OF(PKCS7_SIGNER_INFO) *sk;
493
+ PKCS7_SIGNER_INFO *si;
494
+ int num, i;
495
+ VALUE ary;
496
+
497
+ GetPKCS7(self, pkcs7);
498
+ if (!(sk = PKCS7_get_signer_info(pkcs7))) {
499
+ OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!");
500
+ return rb_ary_new();
501
+ }
502
+ if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) {
503
+ ossl_raise(ePKCS7Error, "Negative number of signers!");
504
+ }
505
+ ary = rb_ary_new2(num);
506
+ for (i=0; i<num; i++) {
507
+ si = sk_PKCS7_SIGNER_INFO_value(sk, i);
508
+ rb_ary_push(ary, ossl_pkcs7si_new(si));
509
+ }
510
+
511
+ return ary;
512
+ }
513
+
514
+ static VALUE
515
+ ossl_pkcs7_add_recipient(VALUE self, VALUE recip)
516
+ {
517
+ PKCS7 *pkcs7;
518
+ PKCS7_RECIP_INFO *ri;
519
+
520
+ ri = DupPKCS7RecipientPtr(recip); /* NEED TO DUP */
521
+ GetPKCS7(self, pkcs7);
522
+ if (!PKCS7_add_recipient_info(pkcs7, ri)) {
523
+ PKCS7_RECIP_INFO_free(ri);
524
+ ossl_raise(ePKCS7Error, "Could not add recipient.");
525
+ }
526
+
527
+ return self;
528
+ }
529
+
530
+ static VALUE
531
+ ossl_pkcs7_get_recipient(VALUE self)
532
+ {
533
+ PKCS7 *pkcs7;
534
+ STACK_OF(PKCS7_RECIP_INFO) *sk;
535
+ PKCS7_RECIP_INFO *si;
536
+ int num, i;
537
+ VALUE ary;
538
+
539
+ GetPKCS7(self, pkcs7);
540
+ if (PKCS7_type_is_enveloped(pkcs7))
541
+ sk = pkcs7->d.enveloped->recipientinfo;
542
+ else if (PKCS7_type_is_signedAndEnveloped(pkcs7))
543
+ sk = pkcs7->d.signed_and_enveloped->recipientinfo;
544
+ else sk = NULL;
545
+ if (!sk) return rb_ary_new();
546
+ if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) {
547
+ ossl_raise(ePKCS7Error, "Negative number of recipient!");
548
+ }
549
+ ary = rb_ary_new2(num);
550
+ for (i=0; i<num; i++) {
551
+ si = sk_PKCS7_RECIP_INFO_value(sk, i);
552
+ rb_ary_push(ary, ossl_pkcs7ri_new(si));
553
+ }
554
+
555
+ return ary;
556
+ }
557
+
558
+ static VALUE
559
+ ossl_pkcs7_add_certificate(VALUE self, VALUE cert)
560
+ {
561
+ PKCS7 *pkcs7;
562
+ X509 *x509;
563
+
564
+ GetPKCS7(self, pkcs7);
565
+ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
566
+ if (!PKCS7_add_certificate(pkcs7, x509)){
567
+ ossl_raise(ePKCS7Error, NULL);
568
+ }
569
+
570
+ return self;
571
+ }
572
+
573
+ static STACK_OF(X509) *
574
+ pkcs7_get_certs(VALUE self)
575
+ {
576
+ PKCS7 *pkcs7;
577
+ STACK_OF(X509) *certs;
578
+ int i;
579
+
580
+ GetPKCS7(self, pkcs7);
581
+ i = OBJ_obj2nid(pkcs7->type);
582
+ switch(i){
583
+ case NID_pkcs7_signed:
584
+ certs = pkcs7->d.sign->cert;
585
+ break;
586
+ case NID_pkcs7_signedAndEnveloped:
587
+ certs = pkcs7->d.signed_and_enveloped->cert;
588
+ break;
589
+ default:
590
+ certs = NULL;
591
+ }
592
+
593
+ return certs;
594
+ }
595
+
596
+ static STACK_OF(X509_CRL) *
597
+ pkcs7_get_crls(VALUE self)
598
+ {
599
+ PKCS7 *pkcs7;
600
+ STACK_OF(X509_CRL) *crls;
601
+ int i;
602
+
603
+ GetPKCS7(self, pkcs7);
604
+ i = OBJ_obj2nid(pkcs7->type);
605
+ switch(i){
606
+ case NID_pkcs7_signed:
607
+ crls = pkcs7->d.sign->crl;
608
+ break;
609
+ case NID_pkcs7_signedAndEnveloped:
610
+ crls = pkcs7->d.signed_and_enveloped->crl;
611
+ break;
612
+ default:
613
+ crls = NULL;
614
+ }
615
+
616
+ return crls;
617
+ }
618
+
619
+ static VALUE
620
+ ossl_pkcs7_set_certs_i(VALUE i, VALUE arg)
621
+ {
622
+ return ossl_pkcs7_add_certificate(arg, i);
623
+ }
624
+
625
+ static VALUE
626
+ ossl_pkcs7_set_certificates(VALUE self, VALUE ary)
627
+ {
628
+ STACK_OF(X509) *certs;
629
+ X509 *cert;
630
+
631
+ certs = pkcs7_get_certs(self);
632
+ while((cert = sk_X509_pop(certs))) X509_free(cert);
633
+ rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self);
634
+
635
+ return ary;
636
+ }
637
+
638
+ static VALUE
639
+ ossl_pkcs7_get_certificates(VALUE self)
640
+ {
641
+ return ossl_x509_sk2ary(pkcs7_get_certs(self));
642
+ }
643
+
644
+ static VALUE
645
+ ossl_pkcs7_add_crl(VALUE self, VALUE crl)
646
+ {
647
+ PKCS7 *pkcs7;
648
+ X509_CRL *x509crl;
649
+
650
+ GetPKCS7(self, pkcs7); /* NO DUP needed! */
651
+ x509crl = GetX509CRLPtr(crl);
652
+ if (!PKCS7_add_crl(pkcs7, x509crl)) {
653
+ ossl_raise(ePKCS7Error, NULL);
654
+ }
655
+
656
+ return self;
657
+ }
658
+
659
+ static VALUE
660
+ ossl_pkcs7_set_crls_i(VALUE i, VALUE arg)
661
+ {
662
+ return ossl_pkcs7_add_crl(arg, i);
663
+ }
664
+
665
+ static VALUE
666
+ ossl_pkcs7_set_crls(VALUE self, VALUE ary)
667
+ {
668
+ STACK_OF(X509_CRL) *crls;
669
+ X509_CRL *crl;
670
+
671
+ crls = pkcs7_get_crls(self);
672
+ while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl);
673
+ rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self);
674
+
675
+ return ary;
676
+ }
677
+
678
+ static VALUE
679
+ ossl_pkcs7_get_crls(VALUE self)
680
+ {
681
+ return ossl_x509crl_sk2ary(pkcs7_get_crls(self));
682
+ }
683
+
684
+ static VALUE
685
+ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
686
+ {
687
+ VALUE certs, store, indata, flags;
688
+ STACK_OF(X509) *x509s;
689
+ X509_STORE *x509st;
690
+ int flg, ok, status = 0;
691
+ BIO *in, *out;
692
+ PKCS7 *p7;
693
+ VALUE data;
694
+ const char *msg;
695
+
696
+ rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags);
697
+ flg = NIL_P(flags) ? 0 : NUM2INT(flags);
698
+ if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self);
699
+ in = NIL_P(indata) ? NULL : ossl_obj2bio(indata);
700
+ if(NIL_P(certs)) x509s = NULL;
701
+ else{
702
+ x509s = ossl_protect_x509_ary2sk(certs, &status);
703
+ if(status){
704
+ BIO_free(in);
705
+ rb_jump_tag(status);
706
+ }
707
+ }
708
+ x509st = GetX509StorePtr(store);
709
+ GetPKCS7(self, p7);
710
+ if(!(out = BIO_new(BIO_s_mem()))){
711
+ BIO_free(in);
712
+ sk_X509_pop_free(x509s, X509_free);
713
+ ossl_raise(ePKCS7Error, NULL);
714
+ }
715
+ ok = PKCS7_verify(p7, x509s, x509st, in, out, flg);
716
+ BIO_free(in);
717
+ if (ok < 0) ossl_raise(ePKCS7Error, NULL);
718
+ msg = ERR_reason_error_string(ERR_get_error());
719
+ ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil);
720
+ ERR_clear_error();
721
+ data = ossl_membio2str(out);
722
+ ossl_pkcs7_set_data(self, data);
723
+ sk_X509_pop_free(x509s, X509_free);
724
+
725
+ return (ok == 1) ? Qtrue : Qfalse;
726
+ }
727
+
728
+ static VALUE
729
+ ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self)
730
+ {
731
+ VALUE pkey, cert, flags;
732
+ EVP_PKEY *key;
733
+ X509 *x509;
734
+ int flg;
735
+ PKCS7 *p7;
736
+ BIO *out;
737
+ VALUE str;
738
+
739
+ rb_scan_args(argc, argv, "21", &pkey, &cert, &flags);
740
+ key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */
741
+ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
742
+ flg = NIL_P(flags) ? 0 : NUM2INT(flags);
743
+ GetPKCS7(self, p7);
744
+ if(!(out = BIO_new(BIO_s_mem())))
745
+ ossl_raise(ePKCS7Error, NULL);
746
+ if(!PKCS7_decrypt(p7, key, x509, out, flg)){
747
+ BIO_free(out);
748
+ ossl_raise(ePKCS7Error, NULL);
749
+ }
750
+ str = ossl_membio2str(out); /* out will be free */
751
+
752
+ return str;
753
+ }
754
+
755
+ static VALUE
756
+ ossl_pkcs7_add_data(VALUE self, VALUE data)
757
+ {
758
+ PKCS7 *pkcs7;
759
+ BIO *out, *in;
760
+ char buf[4096];
761
+ int len;
762
+
763
+ in = ossl_obj2bio(data);
764
+ GetPKCS7(self, pkcs7);
765
+ if(PKCS7_type_is_signed(pkcs7)){
766
+ if(!PKCS7_content_new(pkcs7, NID_pkcs7_data))
767
+ ossl_raise(ePKCS7Error, NULL);
768
+ }
769
+ if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err;
770
+ for(;;){
771
+ if((len = BIO_read(in, buf, sizeof(buf))) <= 0)
772
+ break;
773
+ if(BIO_write(out, buf, len) != len)
774
+ goto err;
775
+ }
776
+ if(!PKCS7_dataFinal(pkcs7, out)) goto err;
777
+ ossl_pkcs7_set_data(self, Qnil);
778
+
779
+ err:
780
+ BIO_free(out);
781
+ BIO_free(in);
782
+ if(ERR_peek_error()){
783
+ ossl_raise(ePKCS7Error, NULL);
784
+ }
785
+
786
+ return data;
787
+ }
788
+
789
+ static VALUE
790
+ ossl_pkcs7_to_der(VALUE self)
791
+ {
792
+ PKCS7 *pkcs7;
793
+ VALUE str;
794
+ long len;
795
+ unsigned char *p;
796
+
797
+ GetPKCS7(self, pkcs7);
798
+ if((len = i2d_PKCS7(pkcs7, NULL)) <= 0)
799
+ ossl_raise(ePKCS7Error, NULL);
800
+ str = rb_str_new(0, len);
801
+ p = RSTRING_PTR(str);
802
+ if(i2d_PKCS7(pkcs7, &p) <= 0)
803
+ ossl_raise(ePKCS7Error, NULL);
804
+ ossl_str_adjust(str, p);
805
+
806
+ return str;
807
+ }
808
+
809
+ static VALUE
810
+ ossl_pkcs7_to_pem(VALUE self)
811
+ {
812
+ PKCS7 *pkcs7;
813
+ BIO *out;
814
+ VALUE str;
815
+
816
+ GetPKCS7(self, pkcs7);
817
+ if (!(out = BIO_new(BIO_s_mem()))) {
818
+ ossl_raise(ePKCS7Error, NULL);
819
+ }
820
+ if (!PEM_write_bio_PKCS7(out, pkcs7)) {
821
+ BIO_free(out);
822
+ ossl_raise(ePKCS7Error, NULL);
823
+ }
824
+ str = ossl_membio2str(out);
825
+
826
+ return str;
827
+ }
828
+
829
+ /*
830
+ * SIGNER INFO
831
+ */
832
+ static VALUE
833
+ ossl_pkcs7si_alloc(VALUE klass)
834
+ {
835
+ PKCS7_SIGNER_INFO *p7si;
836
+ VALUE obj;
837
+
838
+ if (!(p7si = PKCS7_SIGNER_INFO_new())) {
839
+ ossl_raise(ePKCS7Error, NULL);
840
+ }
841
+ WrapPKCS7si(klass, obj, p7si);
842
+
843
+ return obj;
844
+ }
845
+
846
+ static VALUE
847
+ ossl_pkcs7si_initialize(VALUE self, VALUE cert, VALUE key, VALUE digest)
848
+ {
849
+ PKCS7_SIGNER_INFO *p7si;
850
+ EVP_PKEY *pkey;
851
+ X509 *x509;
852
+ const EVP_MD *md;
853
+
854
+ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
855
+ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
856
+ md = GetDigestPtr(digest);
857
+ GetPKCS7si(self, p7si);
858
+ if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, (EVP_MD*)md))) {
859
+ ossl_raise(ePKCS7Error, NULL);
860
+ }
861
+
862
+ return self;
863
+ }
864
+
865
+ static VALUE
866
+ ossl_pkcs7si_get_issuer(VALUE self)
867
+ {
868
+ PKCS7_SIGNER_INFO *p7si;
869
+
870
+ GetPKCS7si(self, p7si);
871
+
872
+ return ossl_x509name_new(p7si->issuer_and_serial->issuer);
873
+ }
874
+
875
+ static VALUE
876
+ ossl_pkcs7si_get_serial(VALUE self)
877
+ {
878
+ PKCS7_SIGNER_INFO *p7si;
879
+
880
+ GetPKCS7si(self, p7si);
881
+
882
+ return asn1integer_to_num(p7si->issuer_and_serial->serial);
883
+ }
884
+
885
+ static VALUE
886
+ ossl_pkcs7si_get_signed_time(VALUE self)
887
+ {
888
+ PKCS7_SIGNER_INFO *p7si;
889
+ ASN1_TYPE *asn1obj;
890
+
891
+ GetPKCS7si(self, p7si);
892
+
893
+ if (!(asn1obj = PKCS7_get_signed_attribute(p7si, NID_pkcs9_signingTime))) {
894
+ ossl_raise(ePKCS7Error, NULL);
895
+ }
896
+ if (asn1obj->type == V_ASN1_UTCTIME) {
897
+ return asn1time_to_time(asn1obj->value.utctime);
898
+ }
899
+ /*
900
+ * OR
901
+ * ossl_raise(ePKCS7Error, "...");
902
+ * ?
903
+ */
904
+
905
+ return Qnil;
906
+ }
907
+
908
+ /*
909
+ * RECIPIENT INFO
910
+ */
911
+ static VALUE
912
+ ossl_pkcs7ri_alloc(VALUE klass)
913
+ {
914
+ PKCS7_RECIP_INFO *p7ri;
915
+ VALUE obj;
916
+
917
+ if (!(p7ri = PKCS7_RECIP_INFO_new())) {
918
+ ossl_raise(ePKCS7Error, NULL);
919
+ }
920
+ WrapPKCS7ri(klass, obj, p7ri);
921
+
922
+ return obj;
923
+ }
924
+
925
+ static VALUE
926
+ ossl_pkcs7ri_initialize(VALUE self, VALUE cert)
927
+ {
928
+ PKCS7_RECIP_INFO *p7ri;
929
+ X509 *x509;
930
+
931
+ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
932
+ GetPKCS7ri(self, p7ri);
933
+ if (!PKCS7_RECIP_INFO_set(p7ri, x509)) {
934
+ ossl_raise(ePKCS7Error, NULL);
935
+ }
936
+
937
+ return self;
938
+ }
939
+
940
+ static VALUE
941
+ ossl_pkcs7ri_get_issuer(VALUE self)
942
+ {
943
+ PKCS7_RECIP_INFO *p7ri;
944
+
945
+ GetPKCS7ri(self, p7ri);
946
+
947
+ return ossl_x509name_new(p7ri->issuer_and_serial->issuer);
948
+ }
949
+
950
+ static VALUE
951
+ ossl_pkcs7ri_get_serial(VALUE self)
952
+ {
953
+ PKCS7_RECIP_INFO *p7ri;
954
+
955
+ GetPKCS7ri(self, p7ri);
956
+
957
+ return asn1integer_to_num(p7ri->issuer_and_serial->serial);
958
+ }
959
+
960
+ static VALUE
961
+ ossl_pkcs7ri_get_enc_key(VALUE self)
962
+ {
963
+ PKCS7_RECIP_INFO *p7ri;
964
+
965
+ GetPKCS7ri(self, p7ri);
966
+
967
+ return asn1str_to_str(p7ri->enc_key);
968
+ }
969
+
970
+ /*
971
+ * INIT
972
+ */
973
+ void
974
+ Init_ossl_pkcs7()
975
+ {
976
+ cPKCS7 = rb_define_class_under(mOSSL, "PKCS7", rb_cObject);
977
+ ePKCS7Error = rb_define_class_under(cPKCS7, "PKCS7Error", eOSSLError);
978
+ rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
979
+ rb_define_singleton_method(cPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1);
980
+ rb_define_singleton_method(cPKCS7, "sign", ossl_pkcs7_s_sign, -1);
981
+ rb_define_singleton_method(cPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1);
982
+ rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse);
983
+ rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse);
984
+ rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc);
985
+ rb_define_copy_func(cPKCS7, ossl_pkcs7_copy);
986
+ rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1);
987
+ rb_define_method(cPKCS7, "type=", ossl_pkcs7_set_type, 1);
988
+ rb_define_method(cPKCS7, "type", ossl_pkcs7_get_type, 0);
989
+ rb_define_method(cPKCS7, "detached=", ossl_pkcs7_set_detached, 1);
990
+ rb_define_method(cPKCS7, "detached", ossl_pkcs7_get_detached, 0);
991
+ rb_define_method(cPKCS7, "detached?", ossl_pkcs7_detached_p, 0);
992
+ rb_define_method(cPKCS7, "cipher=", ossl_pkcs7_set_cipher, 1);
993
+ rb_define_method(cPKCS7, "add_signer", ossl_pkcs7_add_signer, 1);
994
+ rb_define_method(cPKCS7, "signers", ossl_pkcs7_get_signer, 0);
995
+ rb_define_method(cPKCS7, "add_recipient", ossl_pkcs7_add_recipient, 1);
996
+ rb_define_method(cPKCS7, "recipients", ossl_pkcs7_get_recipient, 0);
997
+ rb_define_method(cPKCS7, "add_certificate", ossl_pkcs7_add_certificate, 1);
998
+ rb_define_method(cPKCS7, "certificates=", ossl_pkcs7_set_certificates, 1);
999
+ rb_define_method(cPKCS7, "certificates", ossl_pkcs7_get_certificates, 0);
1000
+ rb_define_method(cPKCS7, "add_crl", ossl_pkcs7_add_crl, 1);
1001
+ rb_define_method(cPKCS7, "crls=", ossl_pkcs7_set_crls, 1);
1002
+ rb_define_method(cPKCS7, "crls", ossl_pkcs7_get_crls, 0);
1003
+ rb_define_method(cPKCS7, "add_data", ossl_pkcs7_add_data, 1);
1004
+ rb_define_alias(cPKCS7, "data=", "add_data");
1005
+ rb_define_method(cPKCS7, "verify", ossl_pkcs7_verify, -1);
1006
+ rb_define_method(cPKCS7, "decrypt", ossl_pkcs7_decrypt, -1);
1007
+ rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0);
1008
+ rb_define_alias(cPKCS7, "to_s", "to_pem");
1009
+ rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0);
1010
+
1011
+ cPKCS7Signer = rb_define_class_under(cPKCS7, "SignerInfo", rb_cObject);
1012
+ rb_define_const(cPKCS7, "Signer", cPKCS7Signer);
1013
+ rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc);
1014
+ rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3);
1015
+ rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0);
1016
+ rb_define_alias(cPKCS7Signer, "name", "issuer");
1017
+ rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0);
1018
+ rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0);
1019
+
1020
+ cPKCS7Recipient = rb_define_class_under(cPKCS7,"RecipientInfo",rb_cObject);
1021
+ rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc);
1022
+ rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1);
1023
+ rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0);
1024
+ rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0);
1025
+ rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0);
1026
+
1027
+ #define DefPKCS7Const(x) rb_define_const(cPKCS7, #x, INT2NUM(PKCS7_##x))
1028
+
1029
+ DefPKCS7Const(TEXT);
1030
+ DefPKCS7Const(NOCERTS);
1031
+ DefPKCS7Const(NOSIGS);
1032
+ DefPKCS7Const(NOCHAIN);
1033
+ DefPKCS7Const(NOINTERN);
1034
+ DefPKCS7Const(NOVERIFY);
1035
+ DefPKCS7Const(DETACHED);
1036
+ DefPKCS7Const(BINARY);
1037
+ DefPKCS7Const(NOATTR);
1038
+ DefPKCS7Const(NOSMIMECAP);
1039
+ }