rubysl-openssl 2.10 → 2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +5 -5
  2. data/ext/rubysl/openssl/deprecation.rb +7 -3
  3. data/ext/rubysl/openssl/extconf.rb +148 -103
  4. data/ext/rubysl/openssl/openssl_missing.c +94 -275
  5. data/ext/rubysl/openssl/openssl_missing.h +167 -98
  6. data/ext/rubysl/openssl/ossl.c +266 -212
  7. data/ext/rubysl/openssl/ossl.h +27 -89
  8. data/ext/rubysl/openssl/ossl_asn1.c +157 -221
  9. data/ext/rubysl/openssl/ossl_asn1.h +11 -3
  10. data/ext/rubysl/openssl/ossl_bio.c +10 -40
  11. data/ext/rubysl/openssl/ossl_bio.h +1 -2
  12. data/ext/rubysl/openssl/ossl_bn.c +144 -100
  13. data/ext/rubysl/openssl/ossl_bn.h +3 -1
  14. data/ext/rubysl/openssl/ossl_cipher.c +270 -195
  15. data/ext/rubysl/openssl/ossl_config.c +7 -1
  16. data/ext/rubysl/openssl/ossl_config.h +0 -1
  17. data/ext/rubysl/openssl/ossl_digest.c +40 -29
  18. data/ext/rubysl/openssl/ossl_engine.c +23 -62
  19. data/ext/rubysl/openssl/ossl_hmac.c +82 -55
  20. data/ext/rubysl/openssl/ossl_ns_spki.c +22 -22
  21. data/ext/rubysl/openssl/ossl_ocsp.c +894 -144
  22. data/ext/rubysl/openssl/ossl_ocsp.h +1 -1
  23. data/ext/rubysl/openssl/ossl_pkcs12.c +47 -19
  24. data/ext/rubysl/openssl/ossl_pkcs5.c +7 -15
  25. data/ext/rubysl/openssl/ossl_pkcs7.c +38 -15
  26. data/ext/rubysl/openssl/ossl_pkey.c +151 -99
  27. data/ext/rubysl/openssl/ossl_pkey.h +123 -29
  28. data/ext/rubysl/openssl/ossl_pkey_dh.c +143 -92
  29. data/ext/rubysl/openssl/ossl_pkey_dsa.c +149 -104
  30. data/ext/rubysl/openssl/ossl_pkey_ec.c +646 -524
  31. data/ext/rubysl/openssl/ossl_pkey_rsa.c +180 -121
  32. data/ext/rubysl/openssl/ossl_rand.c +25 -21
  33. data/ext/rubysl/openssl/ossl_ssl.c +795 -413
  34. data/ext/rubysl/openssl/ossl_ssl.h +3 -0
  35. data/ext/rubysl/openssl/ossl_ssl_session.c +83 -77
  36. data/ext/rubysl/openssl/ossl_version.h +1 -1
  37. data/ext/rubysl/openssl/ossl_x509.c +92 -8
  38. data/ext/rubysl/openssl/ossl_x509.h +14 -5
  39. data/ext/rubysl/openssl/ossl_x509attr.c +77 -41
  40. data/ext/rubysl/openssl/ossl_x509cert.c +45 -46
  41. data/ext/rubysl/openssl/ossl_x509crl.c +51 -57
  42. data/ext/rubysl/openssl/ossl_x509ext.c +39 -33
  43. data/ext/rubysl/openssl/ossl_x509name.c +68 -45
  44. data/ext/rubysl/openssl/ossl_x509req.c +32 -38
  45. data/ext/rubysl/openssl/ossl_x509revoked.c +43 -9
  46. data/ext/rubysl/openssl/ossl_x509store.c +309 -104
  47. data/ext/rubysl/openssl/ruby_missing.h +8 -6
  48. data/lib/openssl/buffering.rb +11 -5
  49. data/lib/openssl/cipher.rb +23 -15
  50. data/lib/openssl/digest.rb +7 -10
  51. data/lib/openssl/pkey.rb +15 -8
  52. data/lib/openssl/ssl.rb +81 -105
  53. data/lib/rubysl/openssl.rb +1 -4
  54. data/lib/rubysl/openssl/version.rb +1 -1
  55. metadata +3 -4
@@ -11,7 +11,7 @@
11
11
  #if !defined(_OSSL_OCSP_H_)
12
12
  #define _OSSL_OCSP_H_
13
13
 
14
- #if defined(OSSL_OCSP_ENABLED)
14
+ #if !defined(OPENSSL_NO_OCSP)
15
15
  extern VALUE mOCSP;
16
16
  extern VALUE cOPCSReq;
17
17
  extern VALUE cOPCSRes;
@@ -65,6 +65,25 @@ ossl_pkcs12_s_allocate(VALUE klass)
65
65
  return obj;
66
66
  }
67
67
 
68
+ static VALUE
69
+ ossl_pkcs12_initialize_copy(VALUE self, VALUE other)
70
+ {
71
+ PKCS12 *p12, *p12_old, *p12_new;
72
+
73
+ rb_check_frozen(self);
74
+ GetPKCS12(self, p12_old);
75
+ SafeGetPKCS12(other, p12);
76
+
77
+ p12_new = ASN1_dup((i2d_of_void *)i2d_PKCS12, (d2i_of_void *)d2i_PKCS12, (char *)p12);
78
+ if (!p12_new)
79
+ ossl_raise(ePKCS12Error, "ASN1_dup");
80
+
81
+ SetPKCS12(self, p12_new);
82
+ PKCS12_free(p12_old);
83
+
84
+ return self;
85
+ }
86
+
68
87
  /*
69
88
  * call-seq:
70
89
  * PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]])
@@ -74,8 +93,8 @@ ossl_pkcs12_s_allocate(VALUE klass)
74
93
  * * +name+ - A string describing the key.
75
94
  * * +key+ - Any PKey.
76
95
  * * +cert+ - A X509::Certificate.
77
- * * * The public_key portion of the certificate must contain a valid public key.
78
- * * * The not_before and not_after fields must be filled in.
96
+ * * The public_key portion of the certificate must contain a valid public key.
97
+ * * The not_before and not_after fields must be filled in.
79
98
  * * +ca+ - An optional array of X509::Certificate's.
80
99
  * * +key_pbe+ - string
81
100
  * * +cert_pbe+ - string
@@ -100,18 +119,18 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
100
119
  PKCS12 *p12;
101
120
 
102
121
  rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype);
103
- passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
104
- friendlyname = NIL_P(name) ? NULL : StringValuePtr(name);
122
+ passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass);
123
+ friendlyname = NIL_P(name) ? NULL : StringValueCStr(name);
105
124
  key = GetPKeyPtr(pkey);
106
125
  x509 = GetX509CertPtr(cert);
107
126
  /* TODO: make a VALUE to nid function */
108
127
  if (!NIL_P(key_nid)) {
109
- if ((nkey = OBJ_txt2nid(StringValuePtr(key_nid))) == NID_undef)
110
- ossl_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(key_nid));
128
+ if ((nkey = OBJ_txt2nid(StringValueCStr(key_nid))) == NID_undef)
129
+ ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, key_nid);
111
130
  }
112
131
  if (!NIL_P(cert_nid)) {
113
- if ((ncert = OBJ_txt2nid(StringValuePtr(cert_nid))) == NID_undef)
114
- ossl_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(cert_nid));
132
+ if ((ncert = OBJ_txt2nid(StringValueCStr(cert_nid))) == NID_undef)
133
+ ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, cert_nid);
115
134
  }
116
135
  if (!NIL_P(key_iter))
117
136
  kiter = NUM2INT(key_iter);
@@ -158,8 +177,8 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
158
177
  PKCS12 *pkcs = DATA_PTR(self);
159
178
 
160
179
  if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self;
161
- passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
162
- in = ossl_obj2bio(arg);
180
+ passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass);
181
+ in = ossl_obj2bio(&arg);
163
182
  d2i_PKCS12_bio(in, &pkcs);
164
183
  DATA_PTR(self) = pkcs;
165
184
  BIO_free(in);
@@ -171,15 +190,17 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
171
190
  if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s))
172
191
  ossl_raise(ePKCS12Error, "PKCS12_parse");
173
192
  ERR_pop_to_mark();
174
- pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key,
175
- &st); /* NO DUP */
176
- if(st) goto err;
177
- cert = rb_protect((VALUE(*)_((VALUE)))ossl_x509_new, (VALUE)x509, &st);
178
- if(st) goto err;
179
- if(x509s){
180
- ca =
181
- rb_protect((VALUE(*)_((VALUE)))ossl_x509_sk2ary, (VALUE)x509s, &st);
182
- if(st) goto err;
193
+ if (key) {
194
+ pkey = rb_protect((VALUE (*)(VALUE))ossl_pkey_new, (VALUE)key, &st);
195
+ if (st) goto err;
196
+ }
197
+ if (x509) {
198
+ cert = rb_protect((VALUE (*)(VALUE))ossl_x509_new, (VALUE)x509, &st);
199
+ if (st) goto err;
200
+ }
201
+ if (x509s) {
202
+ ca = rb_protect((VALUE (*)(VALUE))ossl_x509_sk2ary, (VALUE)x509s, &st);
203
+ if (st) goto err;
183
204
  }
184
205
 
185
206
  err:
@@ -216,6 +237,12 @@ ossl_pkcs12_to_der(VALUE self)
216
237
  void
217
238
  Init_ossl_pkcs12(void)
218
239
  {
240
+ #undef rb_intern
241
+ #if 0
242
+ mOSSL = rb_define_module("OpenSSL");
243
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
244
+ #endif
245
+
219
246
  /*
220
247
  * Defines a file format commonly used to store private keys with
221
248
  * accompanying public key certificates, protected with a password-based
@@ -226,6 +253,7 @@ Init_ossl_pkcs12(void)
226
253
  rb_define_singleton_method(cPKCS12, "create", ossl_pkcs12_s_create, -1);
227
254
 
228
255
  rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate);
256
+ rb_define_copy_func(cPKCS12, ossl_pkcs12_initialize_copy);
229
257
  rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse);
230
258
  rb_attr(cPKCS12, rb_intern("certificate"), 1, 0, Qfalse);
231
259
  rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse);
@@ -18,7 +18,7 @@ VALUE ePKCS5;
18
18
  * * +keylen+ - integer
19
19
  * * +digest+ - a string or OpenSSL::Digest object.
20
20
  *
21
- * Available in OpenSSL 0.9.4.
21
+ * Available in OpenSSL >= 1.0.0.
22
22
  *
23
23
  * Digests other than SHA1 may not be supported by other cryptography libraries.
24
24
  */
@@ -48,7 +48,6 @@ ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE key
48
48
  #endif
49
49
 
50
50
 
51
- #ifdef HAVE_PKCS5_PBKDF2_HMAC_SHA1
52
51
  /*
53
52
  * call-seq:
54
53
  * PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, keylen) => string
@@ -61,7 +60,7 @@ ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE key
61
60
  *
62
61
  * This method is available in almost any version of OpenSSL.
63
62
  *
64
- * Conforms to rfc2898.
63
+ * Conforms to RFC 2898.
65
64
  */
66
65
  static VALUE
67
66
  ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen)
@@ -81,21 +80,14 @@ ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALU
81
80
 
82
81
  return str;
83
82
  }
84
- #else
85
- #define ossl_pkcs5_pbkdf2_hmac_sha1 rb_f_notimplement
86
- #endif
87
83
 
88
84
  void
89
85
  Init_ossl_pkcs5(void)
90
86
  {
91
- /*
92
- * Password-based Encryption
93
- *
94
- */
95
-
96
- #if 0
97
- mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
98
- #endif
87
+ #if 0
88
+ mOSSL = rb_define_module("OpenSSL");
89
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
90
+ #endif
99
91
 
100
92
  /* Document-class: OpenSSL::PKCS5
101
93
  *
@@ -108,7 +100,7 @@ Init_ossl_pkcs5(void)
108
100
  *
109
101
  * PKCS5 offers support for PBKDF2 with an OpenSSL::Digest::SHA1-based
110
102
  * HMAC, or an arbitrary Digest if the underlying version of OpenSSL
111
- * already supports it (>= 0.9.4).
103
+ * already supports it (>= 1.0.0).
112
104
  *
113
105
  * === Parameters
114
106
  * ==== Password
@@ -127,6 +127,22 @@ static const rb_data_type_t ossl_pkcs7_recip_info_type = {
127
127
  * Public
128
128
  * (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM)
129
129
  */
130
+ static PKCS7_SIGNER_INFO *
131
+ ossl_PKCS7_SIGNER_INFO_dup(const PKCS7_SIGNER_INFO *si)
132
+ {
133
+ return (PKCS7_SIGNER_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO,
134
+ (d2i_of_void *)d2i_PKCS7_SIGNER_INFO,
135
+ (char *)si);
136
+ }
137
+
138
+ static PKCS7_RECIP_INFO *
139
+ ossl_PKCS7_RECIP_INFO_dup(const PKCS7_RECIP_INFO *si)
140
+ {
141
+ return (PKCS7_RECIP_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO,
142
+ (d2i_of_void *)d2i_PKCS7_RECIP_INFO,
143
+ (char *)si);
144
+ }
145
+
130
146
  static VALUE
131
147
  ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si)
132
148
  {
@@ -134,7 +150,7 @@ ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si)
134
150
  VALUE obj;
135
151
 
136
152
  obj = NewPKCS7si(cPKCS7Signer);
137
- pkcs7 = p7si ? PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new();
153
+ pkcs7 = p7si ? ossl_PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new();
138
154
  if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
139
155
  SetPKCS7si(obj, pkcs7);
140
156
 
@@ -147,7 +163,7 @@ DupPKCS7SignerPtr(VALUE obj)
147
163
  PKCS7_SIGNER_INFO *p7si, *pkcs7;
148
164
 
149
165
  SafeGetPKCS7si(obj, p7si);
150
- if (!(pkcs7 = PKCS7_SIGNER_INFO_dup(p7si))) {
166
+ if (!(pkcs7 = ossl_PKCS7_SIGNER_INFO_dup(p7si))) {
151
167
  ossl_raise(ePKCS7Error, NULL);
152
168
  }
153
169
 
@@ -161,7 +177,7 @@ ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri)
161
177
  VALUE obj;
162
178
 
163
179
  obj = NewPKCS7ri(cPKCS7Recipient);
164
- pkcs7 = p7ri ? PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new();
180
+ pkcs7 = p7ri ? ossl_PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new();
165
181
  if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
166
182
  SetPKCS7ri(obj, pkcs7);
167
183
 
@@ -174,7 +190,7 @@ DupPKCS7RecipientPtr(VALUE obj)
174
190
  PKCS7_RECIP_INFO *p7ri, *pkcs7;
175
191
 
176
192
  SafeGetPKCS7ri(obj, p7ri);
177
- if (!(pkcs7 = PKCS7_RECIP_INFO_dup(p7ri))) {
193
+ if (!(pkcs7 = ossl_PKCS7_RECIP_INFO_dup(p7ri))) {
178
194
  ossl_raise(ePKCS7Error, NULL);
179
195
  }
180
196
 
@@ -193,7 +209,7 @@ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
193
209
  VALUE ret, data;
194
210
 
195
211
  ret = NewPKCS7(cPKCS7);
196
- in = ossl_obj2bio(arg);
212
+ in = ossl_obj2bio(&arg);
197
213
  out = NULL;
198
214
  pkcs7 = SMIME_read_PKCS7(in, &out);
199
215
  BIO_free(in);
@@ -225,7 +241,7 @@ ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
225
241
  SafeGetPKCS7(pkcs7, p7);
226
242
  if(!NIL_P(data) && PKCS7_is_detached(p7))
227
243
  flg |= PKCS7_DETACHED;
228
- in = NIL_P(data) ? NULL : ossl_obj2bio(data);
244
+ in = NIL_P(data) ? NULL : ossl_obj2bio(&data);
229
245
  if(!(out = BIO_new(BIO_s_mem()))){
230
246
  BIO_free(in);
231
247
  ossl_raise(ePKCS7Error, NULL);
@@ -262,7 +278,7 @@ ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
262
278
  pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
263
279
  flg = NIL_P(flags) ? 0 : NUM2INT(flags);
264
280
  ret = NewPKCS7(cPKCS7);
265
- in = ossl_obj2bio(data);
281
+ in = ossl_obj2bio(&data);
266
282
  if(NIL_P(certs)) x509s = NULL;
267
283
  else{
268
284
  x509s = ossl_protect_x509_ary2sk(certs, &status);
@@ -318,7 +334,7 @@ ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
318
334
  else ciph = GetCipherPtr(cipher); /* NO NEED TO DUP */
319
335
  flg = NIL_P(flags) ? 0 : NUM2INT(flags);
320
336
  ret = NewPKCS7(cPKCS7);
321
- in = ossl_obj2bio(data);
337
+ in = ossl_obj2bio(&data);
322
338
  x509s = ossl_protect_x509_ary2sk(certs, &status);
323
339
  if(status){
324
340
  BIO_free(in);
@@ -369,7 +385,7 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
369
385
  if(rb_scan_args(argc, argv, "01", &arg) == 0)
370
386
  return self;
371
387
  arg = ossl_to_der_if_possible(arg);
372
- in = ossl_obj2bio(arg);
388
+ in = ossl_obj2bio(&arg);
373
389
  p7 = PEM_read_bio_PKCS7(in, &pkcs, NULL, NULL);
374
390
  if (!p7) {
375
391
  OSSL_BIO_reset(in);
@@ -429,12 +445,13 @@ ossl_pkcs7_sym2typeid(VALUE sym)
429
445
  { "digest", NID_pkcs7_digest },
430
446
  };
431
447
 
432
- if (RB_TYPE_P(sym, T_SYMBOL)) sym = rb_sym2str(sym);
448
+ if (SYMBOL_P(sym)) sym = rb_sym2str(sym);
433
449
  else StringValue(sym);
434
450
  RSTRING_GETMEM(sym, s, l);
451
+
435
452
  for(i = 0; ; i++){
436
453
  if(i == numberof(p7_type_tab))
437
- ossl_raise(ePKCS7Error, "unknown type \"%s\"", s);
454
+ ossl_raise(ePKCS7Error, "unknown type \"%"PRIsVALUE"\"", sym);
438
455
  if(strlen(p7_type_tab[i].name) != l) continue;
439
456
  if(strcmp(p7_type_tab[i].name, s) == 0){
440
457
  ret = p7_type_tab[i].nid;
@@ -760,7 +777,7 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
760
777
  x509st = GetX509StorePtr(store);
761
778
  flg = NIL_P(flags) ? 0 : NUM2INT(flags);
762
779
  if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self);
763
- in = NIL_P(indata) ? NULL : ossl_obj2bio(indata);
780
+ in = NIL_P(indata) ? NULL : ossl_obj2bio(&indata);
764
781
  if(NIL_P(certs)) x509s = NULL;
765
782
  else{
766
783
  x509s = ossl_protect_x509_ary2sk(certs, &status);
@@ -778,9 +795,9 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
778
795
  BIO_free(in);
779
796
  sk_X509_pop_free(x509s, X509_free);
780
797
  if (ok < 0) ossl_raise(ePKCS7Error, "PKCS7_verify");
781
- msg = ERR_reason_error_string(ERR_get_error());
798
+ msg = ERR_reason_error_string(ERR_peek_error());
782
799
  ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil);
783
- ERR_clear_error();
800
+ ossl_clear_error();
784
801
  data = ossl_membio2str(out);
785
802
  ossl_pkcs7_set_data(self, data);
786
803
 
@@ -827,7 +844,7 @@ ossl_pkcs7_add_data(VALUE self, VALUE data)
827
844
  if(!PKCS7_content_new(pkcs7, NID_pkcs7_data))
828
845
  ossl_raise(ePKCS7Error, NULL);
829
846
  }
830
- in = ossl_obj2bio(data);
847
+ in = ossl_obj2bio(&data);
831
848
  if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err;
832
849
  for(;;){
833
850
  if((len = BIO_read(in, buf, sizeof(buf))) <= 0)
@@ -1037,6 +1054,12 @@ ossl_pkcs7ri_get_enc_key(VALUE self)
1037
1054
  void
1038
1055
  Init_ossl_pkcs7(void)
1039
1056
  {
1057
+ #undef rb_intern
1058
+ #if 0
1059
+ mOSSL = rb_define_module("OpenSSL");
1060
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
1061
+ #endif
1062
+
1040
1063
  cPKCS7 = rb_define_class_under(mOSSL, "PKCS7", rb_cObject);
1041
1064
  ePKCS7Error = rb_define_class_under(cPKCS7, "PKCS7Error", eOSSLError);
1042
1065
  rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
@@ -15,25 +15,26 @@
15
15
  VALUE mPKey;
16
16
  VALUE cPKey;
17
17
  VALUE ePKeyError;
18
- ID id_private_q;
18
+ static ID id_private_q;
19
19
 
20
20
  /*
21
21
  * callback for generating keys
22
22
  */
23
- void
24
- ossl_generate_cb(int p, int n, void *arg)
23
+ static VALUE
24
+ call_check_ints0(VALUE arg)
25
25
  {
26
- VALUE ary;
27
-
28
- ary = rb_ary_new2(2);
29
- rb_ary_store(ary, 0, INT2NUM(p));
30
- rb_ary_store(ary, 1, INT2NUM(n));
26
+ rb_thread_check_ints();
27
+ return Qnil;
28
+ }
31
29
 
32
- rb_yield(ary);
30
+ static void *
31
+ call_check_ints(void *arg)
32
+ {
33
+ int state;
34
+ rb_protect(call_check_ints0, Qnil, &state);
35
+ return (void *)(VALUE)state;
33
36
  }
34
37
 
35
- #if HAVE_BN_GENCB
36
- /* OpenSSL 2nd version of GN generation callback */
37
38
  int
38
39
  ossl_generate_cb_2(int p, int n, BN_GENCB *cb)
39
40
  {
@@ -41,7 +42,7 @@ ossl_generate_cb_2(int p, int n, BN_GENCB *cb)
41
42
  struct ossl_generate_cb_arg *arg;
42
43
  int state;
43
44
 
44
- arg = (struct ossl_generate_cb_arg *)cb->arg;
45
+ arg = (struct ossl_generate_cb_arg *)BN_GENCB_get_arg(cb);
45
46
  if (arg->yield) {
46
47
  ary = rb_ary_new2(2);
47
48
  rb_ary_store(ary, 0, INT2NUM(p));
@@ -52,11 +53,18 @@ ossl_generate_cb_2(int p, int n, BN_GENCB *cb)
52
53
  */
53
54
  rb_protect(rb_yield, ary, &state);
54
55
  if (state) {
55
- arg->stop = 1;
56
56
  arg->state = state;
57
+ return 0;
58
+ }
59
+ }
60
+ if (arg->interrupted) {
61
+ arg->interrupted = 0;
62
+ state = (int)(VALUE)rb_thread_call_with_gvl(call_check_ints, NULL);
63
+ if (state) {
64
+ arg->state = state;
65
+ return 0;
57
66
  }
58
67
  }
59
- if (arg->stop) return 0;
60
68
  return 1;
61
69
  }
62
70
 
@@ -64,9 +72,8 @@ void
64
72
  ossl_generate_cb_stop(void *ptr)
65
73
  {
66
74
  struct ossl_generate_cb_arg *arg = (struct ossl_generate_cb_arg *)ptr;
67
- arg->stop = 1;
75
+ arg->interrupted = 1;
68
76
  }
69
- #endif
70
77
 
71
78
  static void
72
79
  ossl_evp_pkey_free(void *ptr)
@@ -85,13 +92,16 @@ const rb_data_type_t ossl_evp_pkey_type = {
85
92
  0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
86
93
  };
87
94
 
88
- VALUE
89
- ossl_pkey_new(EVP_PKEY *pkey)
95
+ static VALUE
96
+ pkey_new0(EVP_PKEY *pkey)
90
97
  {
91
- if (!pkey) {
92
- ossl_raise(ePKeyError, "Cannot make new key from NULL.");
93
- }
94
- switch (EVP_PKEY_type(pkey->type)) {
98
+ VALUE obj;
99
+ int type;
100
+
101
+ if (!pkey || (type = EVP_PKEY_base_id(pkey)) == EVP_PKEY_NONE)
102
+ ossl_raise(rb_eRuntimeError, "pkey is empty");
103
+
104
+ switch (type) {
95
105
  #if !defined(OPENSSL_NO_RSA)
96
106
  case EVP_PKEY_RSA:
97
107
  return ossl_rsa_new(pkey);
@@ -109,80 +119,112 @@ ossl_pkey_new(EVP_PKEY *pkey)
109
119
  return ossl_ec_new(pkey);
110
120
  #endif
111
121
  default:
112
- ossl_raise(ePKeyError, "unsupported key type");
122
+ obj = NewPKey(cPKey);
123
+ SetPKey(obj, pkey);
124
+ return obj;
113
125
  }
114
-
115
- UNREACHABLE;
116
126
  }
117
127
 
118
128
  VALUE
119
- ossl_pkey_new_from_file(VALUE filename)
129
+ ossl_pkey_new(EVP_PKEY *pkey)
120
130
  {
121
- FILE *fp;
122
- EVP_PKEY *pkey;
123
-
124
- SafeStringValue(filename);
125
- if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
126
- ossl_raise(ePKeyError, "%s", strerror(errno));
127
- }
128
- rb_fd_fix_cloexec(fileno(fp));
131
+ VALUE obj;
132
+ int status;
129
133
 
130
- pkey = PEM_read_PrivateKey(fp, NULL, ossl_pem_passwd_cb, NULL);
131
- fclose(fp);
132
- if (!pkey) {
133
- ossl_raise(ePKeyError, NULL);
134
+ obj = rb_protect((VALUE (*)(VALUE))pkey_new0, (VALUE)pkey, &status);
135
+ if (status) {
136
+ EVP_PKEY_free(pkey);
137
+ rb_jump_tag(status);
134
138
  }
135
139
 
136
- return ossl_pkey_new(pkey);
140
+ return obj;
137
141
  }
138
142
 
139
143
  /*
140
144
  * call-seq:
141
- * OpenSSL::PKey.read(string [, pwd ] ) -> PKey
142
- * OpenSSL::PKey.read(file [, pwd ]) -> PKey
145
+ * OpenSSL::PKey.read(string [, pwd ]) -> PKey
146
+ * OpenSSL::PKey.read(io [, pwd ]) -> PKey
147
+ *
148
+ * Reads a DER or PEM encoded string from +string+ or +io+ and returns an
149
+ * instance of the appropriate PKey class.
143
150
  *
144
151
  * === Parameters
145
152
  * * +string+ is a DER- or PEM-encoded string containing an arbitrary private
146
- * or public key.
147
- * * +file+ is an instance of +File+ containing a DER- or PEM-encoded
148
- * arbitrary private or public key.
153
+ * or public key.
154
+ * * +io+ is an instance of +IO+ containing a DER- or PEM-encoded
155
+ * arbitrary private or public key.
149
156
  * * +pwd+ is an optional password in case +string+ or +file+ is an encrypted
150
- * PEM resource.
157
+ * PEM resource.
151
158
  */
152
159
  static VALUE
153
160
  ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
154
161
  {
155
- EVP_PKEY *pkey;
156
- BIO *bio;
157
- VALUE data, pass;
158
- char *passwd = NULL;
162
+ EVP_PKEY *pkey;
163
+ BIO *bio;
164
+ VALUE data, pass;
159
165
 
160
- rb_scan_args(argc, argv, "11", &data, &pass);
166
+ rb_scan_args(argc, argv, "11", &data, &pass);
167
+ pass = ossl_pem_passwd_value(pass);
161
168
 
162
- bio = ossl_obj2bio(data);
163
- if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) {
169
+ bio = ossl_obj2bio(&data);
170
+ if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) {
164
171
  OSSL_BIO_reset(bio);
165
- if (!NIL_P(pass)) {
166
- passwd = StringValuePtr(pass);
167
- }
168
- if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, passwd))) {
172
+ if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, (void *)pass))) {
169
173
  OSSL_BIO_reset(bio);
170
174
  if (!(pkey = d2i_PUBKEY_bio(bio, NULL))) {
171
175
  OSSL_BIO_reset(bio);
172
- if (!NIL_P(pass)) {
173
- passwd = StringValuePtr(pass);
174
- }
175
- pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, passwd);
176
+ pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, (void *)pass);
176
177
  }
177
178
  }
178
179
  }
179
180
 
180
181
  BIO_free(bio);
181
182
  if (!pkey)
182
- ossl_raise(rb_eArgError, "Could not parse PKey");
183
+ ossl_raise(ePKeyError, "Could not parse PKey");
184
+
183
185
  return ossl_pkey_new(pkey);
184
186
  }
185
187
 
188
+ void
189
+ ossl_pkey_check_public_key(const EVP_PKEY *pkey)
190
+ {
191
+ void *ptr;
192
+ const BIGNUM *n, *e, *pubkey;
193
+
194
+ if (EVP_PKEY_missing_parameters(pkey))
195
+ ossl_raise(ePKeyError, "parameters missing");
196
+
197
+ /* OpenSSL < 1.1.0 takes non-const pointer */
198
+ ptr = EVP_PKEY_get0((EVP_PKEY *)pkey);
199
+ switch (EVP_PKEY_base_id(pkey)) {
200
+ case EVP_PKEY_RSA:
201
+ RSA_get0_key(ptr, &n, &e, NULL);
202
+ if (n && e)
203
+ return;
204
+ break;
205
+ case EVP_PKEY_DSA:
206
+ DSA_get0_key(ptr, &pubkey, NULL);
207
+ if (pubkey)
208
+ return;
209
+ break;
210
+ case EVP_PKEY_DH:
211
+ DH_get0_key(ptr, &pubkey, NULL);
212
+ if (pubkey)
213
+ return;
214
+ break;
215
+ #if !defined(OPENSSL_NO_EC)
216
+ case EVP_PKEY_EC:
217
+ if (EC_KEY_get0_public_key(ptr))
218
+ return;
219
+ break;
220
+ #endif
221
+ default:
222
+ /* unsupported type; assuming ok */
223
+ return;
224
+ }
225
+ ossl_raise(ePKeyError, "public key missing");
226
+ }
227
+
186
228
  EVP_PKEY *
187
229
  GetPKeyPtr(VALUE obj)
188
230
  {
@@ -212,21 +254,7 @@ DupPKeyPtr(VALUE obj)
212
254
  EVP_PKEY *pkey;
213
255
 
214
256
  SafeGetPKey(obj, pkey);
215
- CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
216
-
217
- return pkey;
218
- }
219
-
220
- EVP_PKEY *
221
- DupPrivPKeyPtr(VALUE obj)
222
- {
223
- EVP_PKEY *pkey;
224
-
225
- if (rb_funcallv(obj, id_private_q, 0, NULL) != Qtrue) {
226
- ossl_raise(rb_eArgError, "Private key is needed.");
227
- }
228
- SafeGetPKey(obj, pkey);
229
- CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
257
+ EVP_PKEY_up_ref(pkey);
230
258
 
231
259
  return pkey;
232
260
  }
@@ -260,7 +288,7 @@ static VALUE
260
288
  ossl_pkey_initialize(VALUE self)
261
289
  {
262
290
  if (rb_obj_is_instance_of(self, cPKey)) {
263
- ossl_raise(rb_eNotImpError, "OpenSSL::PKey::PKey is an abstract class.");
291
+ ossl_raise(rb_eTypeError, "OpenSSL::PKey::PKey can't be instantiated directly");
264
292
  }
265
293
  return self;
266
294
  }
@@ -286,24 +314,32 @@ static VALUE
286
314
  ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
287
315
  {
288
316
  EVP_PKEY *pkey;
289
- EVP_MD_CTX ctx;
317
+ const EVP_MD *md;
318
+ EVP_MD_CTX *ctx;
290
319
  unsigned int buf_len;
291
320
  VALUE str;
292
321
  int result;
293
322
 
294
- if (rb_funcallv(self, id_private_q, 0, NULL) != Qtrue) {
295
- ossl_raise(rb_eArgError, "Private key is needed.");
296
- }
297
- GetPKey(self, pkey);
298
- EVP_SignInit(&ctx, GetDigestPtr(digest));
323
+ pkey = GetPrivPKeyPtr(self);
324
+ md = GetDigestPtr(digest);
299
325
  StringValue(data);
300
- EVP_SignUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
301
- str = rb_str_new(0, EVP_PKEY_size(pkey)+16);
302
- result = EVP_SignFinal(&ctx, (unsigned char *)RSTRING_PTR(str), &buf_len, pkey);
303
- EVP_MD_CTX_cleanup(&ctx);
326
+ str = rb_str_new(0, EVP_PKEY_size(pkey));
327
+
328
+ ctx = EVP_MD_CTX_new();
329
+ if (!ctx)
330
+ ossl_raise(ePKeyError, "EVP_MD_CTX_new");
331
+ if (!EVP_SignInit_ex(ctx, md, NULL)) {
332
+ EVP_MD_CTX_free(ctx);
333
+ ossl_raise(ePKeyError, "EVP_SignInit_ex");
334
+ }
335
+ if (!EVP_SignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) {
336
+ EVP_MD_CTX_free(ctx);
337
+ ossl_raise(ePKeyError, "EVP_SignUpdate");
338
+ }
339
+ result = EVP_SignFinal(ctx, (unsigned char *)RSTRING_PTR(str), &buf_len, pkey);
340
+ EVP_MD_CTX_free(ctx);
304
341
  if (!result)
305
- ossl_raise(ePKeyError, NULL);
306
- assert((long)buf_len <= RSTRING_LEN(str));
342
+ ossl_raise(ePKeyError, "EVP_SignFinal");
307
343
  rb_str_set_len(str, buf_len);
308
344
 
309
345
  return str;
@@ -334,25 +370,39 @@ static VALUE
334
370
  ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
335
371
  {
336
372
  EVP_PKEY *pkey;
337
- EVP_MD_CTX ctx;
338
- int result;
373
+ const EVP_MD *md;
374
+ EVP_MD_CTX *ctx;
375
+ int siglen, result;
339
376
 
340
377
  GetPKey(self, pkey);
378
+ ossl_pkey_check_public_key(pkey);
379
+ md = GetDigestPtr(digest);
341
380
  StringValue(sig);
381
+ siglen = RSTRING_LENINT(sig);
342
382
  StringValue(data);
343
- EVP_VerifyInit(&ctx, GetDigestPtr(digest));
344
- EVP_VerifyUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
345
- result = EVP_VerifyFinal(&ctx, (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey);
346
- EVP_MD_CTX_cleanup(&ctx);
383
+
384
+ ctx = EVP_MD_CTX_new();
385
+ if (!ctx)
386
+ ossl_raise(ePKeyError, "EVP_MD_CTX_new");
387
+ if (!EVP_VerifyInit_ex(ctx, md, NULL)) {
388
+ EVP_MD_CTX_free(ctx);
389
+ ossl_raise(ePKeyError, "EVP_VerifyInit_ex");
390
+ }
391
+ if (!EVP_VerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) {
392
+ EVP_MD_CTX_free(ctx);
393
+ ossl_raise(ePKeyError, "EVP_VerifyUpdate");
394
+ }
395
+ result = EVP_VerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig), siglen, pkey);
396
+ EVP_MD_CTX_free(ctx);
347
397
  switch (result) {
348
398
  case 0:
399
+ ossl_clear_error();
349
400
  return Qfalse;
350
401
  case 1:
351
402
  return Qtrue;
352
403
  default:
353
- ossl_raise(ePKeyError, NULL);
404
+ ossl_raise(ePKeyError, "EVP_VerifyFinal");
354
405
  }
355
- return Qnil; /* dummy */
356
406
  }
357
407
 
358
408
  /*
@@ -361,8 +411,10 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
361
411
  void
362
412
  Init_ossl_pkey(void)
363
413
  {
414
+ #undef rb_intern
364
415
  #if 0
365
- mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
416
+ mOSSL = rb_define_module("OpenSSL");
417
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
366
418
  #endif
367
419
 
368
420
  /* Document-module: OpenSSL::PKey
@@ -374,7 +426,7 @@ Init_ossl_pkey(void)
374
426
  * algorithm consists of two parts: a public key that may be distributed
375
427
  * to others and a private key that needs to remain secret.
376
428
  *
377
- * Messages encrypted with a public key can only be encrypted by
429
+ * Messages encrypted with a public key can only be decrypted by
378
430
  * recipients that are in possession of the associated private key.
379
431
  * Since public key algorithms are considerably slower than symmetric
380
432
  * key algorithms (cf. OpenSSL::Cipher) they are often used to establish