openssl 3.3.3 → 4.0.2

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 +4 -4
  2. data/CONTRIBUTING.md +3 -0
  3. data/History.md +111 -0
  4. data/README.md +12 -11
  5. data/ext/openssl/extconf.rb +30 -70
  6. data/ext/openssl/openssl_missing.h +0 -210
  7. data/ext/openssl/ossl.c +295 -304
  8. data/ext/openssl/ossl.h +13 -9
  9. data/ext/openssl/ossl_asn1.c +598 -406
  10. data/ext/openssl/ossl_asn1.h +15 -1
  11. data/ext/openssl/ossl_bio.c +8 -4
  12. data/ext/openssl/ossl_bn.c +286 -291
  13. data/ext/openssl/ossl_cipher.c +257 -209
  14. data/ext/openssl/ossl_cipher.h +10 -1
  15. data/ext/openssl/ossl_config.c +1 -6
  16. data/ext/openssl/ossl_digest.c +74 -43
  17. data/ext/openssl/ossl_digest.h +9 -1
  18. data/ext/openssl/ossl_engine.c +39 -103
  19. data/ext/openssl/ossl_hmac.c +30 -36
  20. data/ext/openssl/ossl_kdf.c +42 -53
  21. data/ext/openssl/ossl_ns_spki.c +27 -32
  22. data/ext/openssl/ossl_ocsp.c +208 -236
  23. data/ext/openssl/ossl_pkcs12.c +26 -26
  24. data/ext/openssl/ossl_pkcs7.c +175 -145
  25. data/ext/openssl/ossl_pkey.c +102 -158
  26. data/ext/openssl/ossl_pkey.h +99 -100
  27. data/ext/openssl/ossl_pkey_dh.c +31 -68
  28. data/ext/openssl/ossl_pkey_dsa.c +15 -54
  29. data/ext/openssl/ossl_pkey_ec.c +180 -238
  30. data/ext/openssl/ossl_pkey_rsa.c +56 -103
  31. data/ext/openssl/ossl_provider.c +0 -5
  32. data/ext/openssl/ossl_rand.c +7 -14
  33. data/ext/openssl/ossl_ssl.c +535 -384
  34. data/ext/openssl/ossl_ssl.h +8 -8
  35. data/ext/openssl/ossl_ssl_session.c +93 -97
  36. data/ext/openssl/ossl_ts.c +78 -124
  37. data/ext/openssl/ossl_x509.c +9 -28
  38. data/ext/openssl/ossl_x509attr.c +33 -54
  39. data/ext/openssl/ossl_x509cert.c +70 -101
  40. data/ext/openssl/ossl_x509crl.c +78 -89
  41. data/ext/openssl/ossl_x509ext.c +43 -64
  42. data/ext/openssl/ossl_x509name.c +64 -90
  43. data/ext/openssl/ossl_x509req.c +55 -62
  44. data/ext/openssl/ossl_x509revoked.c +28 -42
  45. data/ext/openssl/ossl_x509store.c +36 -54
  46. data/lib/openssl/buffering.rb +30 -24
  47. data/lib/openssl/digest.rb +1 -1
  48. data/lib/openssl/pkey.rb +71 -49
  49. data/lib/openssl/ssl.rb +12 -79
  50. data/lib/openssl/version.rb +2 -1
  51. data/lib/openssl/x509.rb +9 -0
  52. data/lib/openssl.rb +9 -6
  53. metadata +1 -3
  54. data/ext/openssl/openssl_missing.c +0 -41
  55. data/lib/openssl/asn1.rb +0 -188
@@ -13,14 +13,14 @@
13
13
  TypedData_Wrap_Struct((klass), &ossl_x509rev_type, 0)
14
14
  #define SetX509Rev(obj, rev) do { \
15
15
  if (!(rev)) { \
16
- ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
16
+ ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
17
17
  } \
18
18
  RTYPEDDATA_DATA(obj) = (rev); \
19
19
  } while (0)
20
20
  #define GetX509Rev(obj, rev) do { \
21
21
  TypedData_Get_Struct((obj), X509_REVOKED, &ossl_x509rev_type, (rev)); \
22
22
  if (!(rev)) { \
23
- ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
23
+ ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
24
24
  } \
25
25
  } while (0)
26
26
 
@@ -39,7 +39,7 @@ ossl_x509rev_free(void *ptr)
39
39
  static const rb_data_type_t ossl_x509rev_type = {
40
40
  "OpenSSL/X509/REV",
41
41
  {
42
- 0, ossl_x509rev_free,
42
+ 0, ossl_x509rev_free,
43
43
  },
44
44
  0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
45
45
  };
@@ -54,15 +54,10 @@ ossl_x509revoked_new(const X509_REVOKED *rev)
54
54
  VALUE obj;
55
55
 
56
56
  obj = NewX509Rev(cX509Rev);
57
- if (!rev) {
58
- new = X509_REVOKED_new();
59
- } else {
60
- /* OpenSSL 1.1.1 takes a non-const pointer */
61
- new = X509_REVOKED_dup((X509_REVOKED *)rev);
62
- }
63
- if (!new) {
64
- ossl_raise(eX509RevError, NULL);
65
- }
57
+ /* OpenSSL 1.1.1 takes a non-const pointer */
58
+ new = X509_REVOKED_dup((X509_REVOKED *)rev);
59
+ if (!new)
60
+ ossl_raise(eX509RevError, "X509_REVOKED_dup");
66
61
  SetX509Rev(obj, new);
67
62
 
68
63
  return obj;
@@ -75,7 +70,7 @@ DupX509RevokedPtr(VALUE obj)
75
70
 
76
71
  GetX509Rev(obj, rev);
77
72
  if (!(new = X509_REVOKED_dup(rev))) {
78
- ossl_raise(eX509RevError, NULL);
73
+ ossl_raise(eX509RevError, NULL);
79
74
  }
80
75
 
81
76
  return new;
@@ -92,7 +87,7 @@ ossl_x509revoked_alloc(VALUE klass)
92
87
 
93
88
  obj = NewX509Rev(klass);
94
89
  if (!(rev = X509_REVOKED_new())) {
95
- ossl_raise(eX509RevError, NULL);
90
+ ossl_raise(eX509RevError, NULL);
96
91
  }
97
92
  SetX509Rev(obj, rev);
98
93
 
@@ -106,6 +101,7 @@ ossl_x509revoked_initialize(int argc, VALUE *argv, VALUE self)
106
101
  return self;
107
102
  }
108
103
 
104
+ /* :nodoc: */
109
105
  static VALUE
110
106
  ossl_x509revoked_initialize_copy(VALUE self, VALUE other)
111
107
  {
@@ -117,7 +113,7 @@ ossl_x509revoked_initialize_copy(VALUE self, VALUE other)
117
113
 
118
114
  rev_new = X509_REVOKED_dup(rev_other);
119
115
  if (!rev_new)
120
- ossl_raise(eX509RevError, "X509_REVOKED_dup");
116
+ ossl_raise(eX509RevError, "X509_REVOKED_dup");
121
117
 
122
118
  SetX509Rev(self, rev_new);
123
119
  X509_REVOKED_free(rev);
@@ -144,8 +140,8 @@ ossl_x509revoked_set_serial(VALUE self, VALUE num)
144
140
  GetX509Rev(self, rev);
145
141
  asn1int = num_to_asn1integer(num, NULL);
146
142
  if (!X509_REVOKED_set_serialNumber(rev, asn1int)) {
147
- ASN1_INTEGER_free(asn1int);
148
- ossl_raise(eX509RevError, "X509_REVOKED_set_serialNumber");
143
+ ASN1_INTEGER_free(asn1int);
144
+ ossl_raise(eX509RevError, "X509_REVOKED_set_serialNumber");
149
145
  }
150
146
  ASN1_INTEGER_free(asn1int);
151
147
 
@@ -161,7 +157,7 @@ ossl_x509revoked_get_time(VALUE self)
161
157
  GetX509Rev(self, rev);
162
158
  time = X509_REVOKED_get0_revocationDate(rev);
163
159
  if (!time)
164
- return Qnil;
160
+ return Qnil;
165
161
 
166
162
  return asn1time_to_time(time);
167
163
  }
@@ -175,8 +171,8 @@ ossl_x509revoked_set_time(VALUE self, VALUE time)
175
171
  GetX509Rev(self, rev);
176
172
  asn1time = ossl_x509_time_adjust(NULL, time);
177
173
  if (!X509_REVOKED_set_revocationDate(rev, asn1time)) {
178
- ASN1_TIME_free(asn1time);
179
- ossl_raise(eX509RevError, "X509_REVOKED_set_revocationDate");
174
+ ASN1_TIME_free(asn1time);
175
+ ossl_raise(eX509RevError, "X509_REVOKED_set_revocationDate");
180
176
  }
181
177
  ASN1_TIME_free(asn1time);
182
178
 
@@ -195,14 +191,10 @@ ossl_x509revoked_get_extensions(VALUE self)
195
191
 
196
192
  GetX509Rev(self, rev);
197
193
  count = X509_REVOKED_get_ext_count(rev);
198
- if (count < 0) {
199
- OSSL_Debug("count < 0???");
200
- return rb_ary_new();
201
- }
202
- ary = rb_ary_new2(count);
194
+ ary = rb_ary_new_capa(count);
203
195
  for (i=0; i<count; i++) {
204
- ext = X509_REVOKED_get_ext(rev, i);
205
- rb_ary_push(ary, ossl_x509ext_new(ext));
196
+ ext = X509_REVOKED_get_ext(rev, i);
197
+ rb_ary_push(ary, ossl_x509ext_new(ext));
206
198
  }
207
199
 
208
200
  return ary;
@@ -221,17 +213,17 @@ ossl_x509revoked_set_extensions(VALUE self, VALUE ary)
221
213
 
222
214
  Check_Type(ary, T_ARRAY);
223
215
  for (i=0; i<RARRAY_LEN(ary); i++) {
224
- OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
216
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
225
217
  }
226
218
  GetX509Rev(self, rev);
227
219
  for (i = X509_REVOKED_get_ext_count(rev); i > 0; i--)
228
220
  X509_EXTENSION_free(X509_REVOKED_delete_ext(rev, 0));
229
221
  for (i=0; i<RARRAY_LEN(ary); i++) {
230
- item = RARRAY_AREF(ary, i);
231
- ext = GetX509ExtPtr(item);
232
- if(!X509_REVOKED_add_ext(rev, ext, -1)) {
233
- ossl_raise(eX509RevError, "X509_REVOKED_add_ext");
234
- }
222
+ item = RARRAY_AREF(ary, i);
223
+ ext = GetX509ExtPtr(item);
224
+ if(!X509_REVOKED_add_ext(rev, ext, -1)) {
225
+ ossl_raise(eX509RevError, "X509_REVOKED_add_ext");
226
+ }
235
227
  }
236
228
 
237
229
  return ary;
@@ -244,7 +236,7 @@ ossl_x509revoked_add_extension(VALUE self, VALUE ext)
244
236
 
245
237
  GetX509Rev(self, rev);
246
238
  if (!X509_REVOKED_add_ext(rev, GetX509ExtPtr(ext), -1)) {
247
- ossl_raise(eX509RevError, NULL);
239
+ ossl_raise(eX509RevError, NULL);
248
240
  }
249
241
 
250
242
  return ext;
@@ -261,11 +253,11 @@ ossl_x509revoked_to_der(VALUE self)
261
253
  GetX509Rev(self, rev);
262
254
  len = i2d_X509_REVOKED(rev, NULL);
263
255
  if (len <= 0)
264
- ossl_raise(eX509RevError, "i2d_X509_REVOKED");
256
+ ossl_raise(eX509RevError, "i2d_X509_REVOKED");
265
257
  str = rb_str_new(NULL, len);
266
258
  p = (unsigned char *)RSTRING_PTR(str);
267
259
  if (i2d_X509_REVOKED(rev, &p) <= 0)
268
- ossl_raise(eX509RevError, "i2d_X509_REVOKED");
260
+ ossl_raise(eX509RevError, "i2d_X509_REVOKED");
269
261
  ossl_str_adjust(str, p);
270
262
  return str;
271
263
  }
@@ -276,12 +268,6 @@ ossl_x509revoked_to_der(VALUE self)
276
268
  void
277
269
  Init_ossl_x509revoked(void)
278
270
  {
279
- #if 0
280
- mOSSL = rb_define_module("OpenSSL");
281
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
282
- mX509 = rb_define_module_under(mOSSL, "X509");
283
- #endif
284
-
285
271
  eX509RevError = rb_define_class_under(mX509, "RevokedError", eOSSLError);
286
272
 
287
273
  cX509Rev = rb_define_class_under(mX509, "Revoked", rb_cObject);
@@ -13,14 +13,14 @@
13
13
  TypedData_Wrap_Struct((klass), &ossl_x509store_type, 0)
14
14
  #define SetX509Store(obj, st) do { \
15
15
  if (!(st)) { \
16
- ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
16
+ ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
17
17
  } \
18
18
  RTYPEDDATA_DATA(obj) = (st); \
19
19
  } while (0)
20
20
  #define GetX509Store(obj, st) do { \
21
21
  TypedData_Get_Struct((obj), X509_STORE, &ossl_x509store_type, (st)); \
22
22
  if (!(st)) { \
23
- ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
23
+ ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
24
24
  } \
25
25
  } while (0)
26
26
 
@@ -28,14 +28,14 @@
28
28
  TypedData_Wrap_Struct((klass), &ossl_x509stctx_type, 0)
29
29
  #define SetX509StCtx(obj, ctx) do { \
30
30
  if (!(ctx)) { \
31
- ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \
31
+ ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \
32
32
  } \
33
33
  RTYPEDDATA_DATA(obj) = (ctx); \
34
34
  } while (0)
35
35
  #define GetX509StCtx(obj, ctx) do { \
36
36
  TypedData_Get_Struct((obj), X509_STORE_CTX, &ossl_x509stctx_type, (ctx)); \
37
37
  if (!(ctx)) { \
38
- ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \
38
+ ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \
39
39
  } \
40
40
  } while (0)
41
41
 
@@ -62,7 +62,7 @@ call_verify_cb_proc(VALUE arg)
62
62
  {
63
63
  struct ossl_verify_cb_args *args = (struct ossl_verify_cb_args *)arg;
64
64
  return rb_funcall(args->proc, rb_intern("call"), 2,
65
- args->preverify_ok, args->store_ctx);
65
+ args->preverify_ok, args->store_ctx);
66
66
  }
67
67
 
68
68
  int
@@ -73,33 +73,33 @@ ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
73
73
  int state;
74
74
 
75
75
  if (NIL_P(proc))
76
- return ok;
76
+ return ok;
77
77
 
78
78
  ret = Qfalse;
79
79
  rctx = rb_protect(ossl_x509stctx_new_i, (VALUE)ctx, &state);
80
80
  if (state) {
81
- rb_set_errinfo(Qnil);
82
- rb_warn("StoreContext initialization failure");
81
+ rb_set_errinfo(Qnil);
82
+ rb_warn("StoreContext initialization failure");
83
83
  }
84
84
  else {
85
- args.proc = proc;
86
- args.preverify_ok = ok ? Qtrue : Qfalse;
87
- args.store_ctx = rctx;
88
- ret = rb_protect(call_verify_cb_proc, (VALUE)&args, &state);
89
- if (state) {
90
- rb_set_errinfo(Qnil);
91
- rb_warn("exception in verify_callback is ignored");
92
- }
93
- RTYPEDDATA_DATA(rctx) = NULL;
85
+ args.proc = proc;
86
+ args.preverify_ok = ok ? Qtrue : Qfalse;
87
+ args.store_ctx = rctx;
88
+ ret = rb_protect(call_verify_cb_proc, (VALUE)&args, &state);
89
+ if (state) {
90
+ rb_set_errinfo(Qnil);
91
+ rb_warn("exception in verify_callback is ignored");
92
+ }
93
+ RTYPEDDATA_DATA(rctx) = NULL;
94
94
  }
95
95
  if (ret == Qtrue) {
96
- X509_STORE_CTX_set_error(ctx, X509_V_OK);
97
- ok = 1;
96
+ X509_STORE_CTX_set_error(ctx, X509_V_OK);
97
+ ok = 1;
98
98
  }
99
99
  else {
100
- if (X509_STORE_CTX_get_error(ctx) == X509_V_OK)
101
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
102
- ok = 0;
100
+ if (X509_STORE_CTX_get_error(ctx) == X509_V_OK)
101
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
102
+ ok = 0;
103
103
  }
104
104
 
105
105
  return ok;
@@ -159,10 +159,10 @@ x509store_verify_cb(int ok, X509_STORE_CTX *ctx)
159
159
 
160
160
  proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx);
161
161
  if (!proc)
162
- proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx),
163
- store_ex_verify_cb_idx);
162
+ proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx),
163
+ store_ex_verify_cb_idx);
164
164
  if (!proc)
165
- return ok;
165
+ return ok;
166
166
 
167
167
  return ossl_verify_cb_call(proc, ok, ctx);
168
168
  }
@@ -191,8 +191,8 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
191
191
 
192
192
  GetX509Store(self, store);
193
193
  rb_iv_set(self, "@verify_callback", cb);
194
- // We don't need to trigger a write barrier because `rb_iv_set` did it.
195
194
  X509_STORE_set_ex_data(store, store_ex_verify_cb_idx, (void *)cb);
195
+ RB_OBJ_WRITTEN(self, Qundef, cb);
196
196
 
197
197
  return cb;
198
198
  }
@@ -212,10 +212,6 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
212
212
  GetX509Store(self, store);
213
213
  if (argc != 0)
214
214
  rb_warn("OpenSSL::X509::Store.new does not take any arguments");
215
- #if !defined(HAVE_OPAQUE_OPENSSL)
216
- /* [Bug #405] [Bug #1678] [Bug #3000]; already fixed? */
217
- store->ex_data.sk = NULL;
218
- #endif
219
215
  X509_STORE_set_verify_cb(store, x509store_verify_cb);
220
216
  ossl_x509store_set_vfy_cb(self, Qnil);
221
217
 
@@ -332,11 +328,7 @@ ossl_x509store_set_time(VALUE self, VALUE time)
332
328
  X509_VERIFY_PARAM *param;
333
329
 
334
330
  GetX509Store(self, store);
335
- #ifdef HAVE_X509_STORE_GET0_PARAM
336
331
  param = X509_STORE_get0_param(store);
337
- #else
338
- param = store->param;
339
- #endif
340
332
  X509_VERIFY_PARAM_set_time(param, NUM2LONG(rb_Integer(time)));
341
333
  return time;
342
334
  }
@@ -365,15 +357,6 @@ ossl_x509store_add_file(VALUE self, VALUE file)
365
357
  ossl_raise(eX509StoreError, "X509_STORE_add_lookup");
366
358
  if (X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1)
367
359
  ossl_raise(eX509StoreError, "X509_LOOKUP_load_file");
368
- #if OPENSSL_VERSION_NUMBER < 0x10101000 || defined(LIBRESSL_VERSION_NUMBER)
369
- /*
370
- * X509_load_cert_crl_file() which is called from X509_LOOKUP_load_file()
371
- * did not check the return value of X509_STORE_add_{cert,crl}(), leaking
372
- * "cert already in hash table" errors on the error queue, if duplicate
373
- * certificates are found. This will be fixed by OpenSSL 1.1.1.
374
- */
375
- ossl_clear_error();
376
- #endif
377
360
 
378
361
  return self;
379
362
  }
@@ -501,7 +484,7 @@ ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
501
484
  rb_scan_args(argc, argv, "11", &cert, &chain);
502
485
  ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain);
503
486
  proc = rb_block_given_p() ? rb_block_proc() :
504
- rb_iv_get(self, "@verify_callback");
487
+ rb_iv_get(self, "@verify_callback");
505
488
  rb_iv_set(ctx, "@verify_callback", proc);
506
489
  result = rb_funcall(ctx, rb_intern("verify"), 0);
507
490
 
@@ -626,6 +609,7 @@ ossl_x509stctx_verify(VALUE self)
626
609
  GetX509StCtx(self, ctx);
627
610
  VALUE cb = rb_iv_get(self, "@verify_callback");
628
611
  X509_STORE_CTX_set_ex_data(ctx, stctx_ex_verify_cb_idx, (void *)cb);
612
+ RB_OBJ_WRITTEN(self, Qundef, cb);
629
613
 
630
614
  switch (X509_verify_cert(ctx)) {
631
615
  case 1:
@@ -750,10 +734,14 @@ static VALUE
750
734
  ossl_x509stctx_get_curr_cert(VALUE self)
751
735
  {
752
736
  X509_STORE_CTX *ctx;
737
+ const X509 *x509;
753
738
 
754
739
  GetX509StCtx(self, ctx);
740
+ x509 = X509_STORE_CTX_get_current_cert(ctx);
741
+ if (!x509)
742
+ return Qnil;
755
743
 
756
- return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
744
+ return ossl_x509_new(x509);
757
745
  }
758
746
 
759
747
  /*
@@ -773,7 +761,7 @@ ossl_x509stctx_get_curr_crl(VALUE self)
773
761
  GetX509StCtx(self, ctx);
774
762
  crl = X509_STORE_CTX_get0_current_crl(ctx);
775
763
  if (!crl)
776
- return Qnil;
764
+ return Qnil;
777
765
 
778
766
  return ossl_x509crl_new(crl);
779
767
  }
@@ -869,19 +857,13 @@ void
869
857
  Init_ossl_x509store(void)
870
858
  {
871
859
  #undef rb_intern
872
- #if 0
873
- mOSSL = rb_define_module("OpenSSL");
874
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
875
- mX509 = rb_define_module_under(mOSSL, "X509");
876
- #endif
877
-
878
860
  /* Register ext_data slot for verify callback Proc */
879
861
  stctx_ex_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"stctx_ex_verify_cb_idx", 0, 0, 0);
880
862
  if (stctx_ex_verify_cb_idx < 0)
881
- ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
863
+ ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
882
864
  store_ex_verify_cb_idx = X509_STORE_get_ex_new_index(0, (void *)"store_ex_verify_cb_idx", 0, 0, 0);
883
865
  if (store_ex_verify_cb_idx < 0)
884
- ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index");
866
+ ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index");
885
867
 
886
868
  eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError);
887
869
 
@@ -24,25 +24,21 @@ module OpenSSL::Buffering
24
24
 
25
25
  # A buffer which will retain binary encoding.
26
26
  class Buffer < String
27
- BINARY = Encoding::BINARY
28
-
29
- def initialize
30
- super
31
-
32
- force_encoding(BINARY)
33
- end
27
+ unless String.method_defined?(:append_as_bytes)
28
+ alias_method :_append, :<<
29
+ def append_as_bytes(string)
30
+ if string.encoding == Encoding::BINARY
31
+ _append(string)
32
+ else
33
+ _append(string.b)
34
+ end
34
35
 
35
- def << string
36
- if string.encoding == BINARY
37
- super(string)
38
- else
39
- super(string.b)
36
+ self
40
37
  end
41
-
42
- return self
43
38
  end
44
39
 
45
- alias concat <<
40
+ undef_method :concat
41
+ undef_method :<<
46
42
  end
47
43
 
48
44
  ##
@@ -77,7 +73,7 @@ module OpenSSL::Buffering
77
73
 
78
74
  def fill_rbuff
79
75
  begin
80
- @rbuffer << self.sysread(BLOCK_SIZE)
76
+ @rbuffer.append_as_bytes(self.sysread(BLOCK_SIZE))
81
77
  rescue Errno::EAGAIN
82
78
  retry
83
79
  rescue EOFError
@@ -352,22 +348,32 @@ module OpenSSL::Buffering
352
348
 
353
349
  def do_write(s)
354
350
  @wbuffer = Buffer.new unless defined? @wbuffer
355
- @wbuffer << s
356
- @wbuffer.force_encoding(Encoding::BINARY)
351
+ @wbuffer.append_as_bytes(s)
352
+
357
353
  @sync ||= false
358
- buffer_size = @wbuffer.size
354
+ buffer_size = @wbuffer.bytesize
359
355
  if @sync or buffer_size > BLOCK_SIZE
360
356
  nwrote = 0
361
357
  begin
362
358
  while nwrote < buffer_size do
363
359
  begin
364
- nwrote += syswrite(@wbuffer[nwrote, buffer_size - nwrote])
360
+ chunk = if nwrote > 0
361
+ @wbuffer.byteslice(nwrote, @wbuffer.bytesize)
362
+ else
363
+ @wbuffer
364
+ end
365
+
366
+ nwrote += syswrite(chunk)
365
367
  rescue Errno::EAGAIN
366
368
  retry
367
369
  end
368
370
  end
369
371
  ensure
370
- @wbuffer[0, nwrote] = ""
372
+ if nwrote < @wbuffer.bytesize
373
+ @wbuffer[0, nwrote] = ""
374
+ else
375
+ @wbuffer.clear
376
+ end
371
377
  end
372
378
  end
373
379
  end
@@ -444,10 +450,10 @@ module OpenSSL::Buffering
444
450
  def puts(*args)
445
451
  s = Buffer.new
446
452
  if args.empty?
447
- s << "\n"
453
+ s.append_as_bytes("\n")
448
454
  end
449
455
  args.each{|arg|
450
- s << arg.to_s
456
+ s.append_as_bytes(arg.to_s)
451
457
  s.sub!(/(?<!\n)\z/, "\n")
452
458
  }
453
459
  do_write(s)
@@ -461,7 +467,7 @@ module OpenSSL::Buffering
461
467
 
462
468
  def print(*args)
463
469
  s = Buffer.new
464
- args.each{ |arg| s << arg.to_s }
470
+ args.each{ |arg| s.append_as_bytes(arg.to_s) }
465
471
  do_write(s)
466
472
  nil
467
473
  end
@@ -57,7 +57,7 @@ module OpenSSL
57
57
  # OpenSSL::Digest("MD5")
58
58
  # # => OpenSSL::Digest::MD5
59
59
  #
60
- # Digest("Foo")
60
+ # OpenSSL::Digest("Foo")
61
61
  # # => NameError: wrong constant name Foo
62
62
 
63
63
  def Digest(name)