openssl 2.1.1 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +9 -7
  3. data/History.md +165 -0
  4. data/README.md +2 -2
  5. data/ext/openssl/extconf.rb +51 -27
  6. data/ext/openssl/openssl_missing.h +39 -4
  7. data/ext/openssl/ossl.c +61 -27
  8. data/ext/openssl/ossl.h +8 -5
  9. data/ext/openssl/ossl_asn1.c +27 -1
  10. data/ext/openssl/ossl_bn.c +92 -24
  11. data/ext/openssl/ossl_bn.h +2 -1
  12. data/ext/openssl/ossl_cipher.c +33 -24
  13. data/ext/openssl/ossl_digest.c +22 -53
  14. data/ext/openssl/ossl_engine.c +2 -12
  15. data/ext/openssl/ossl_hmac.c +5 -11
  16. data/ext/openssl/ossl_kdf.c +3 -19
  17. data/ext/openssl/ossl_ns_spki.c +1 -1
  18. data/ext/openssl/ossl_ocsp.c +6 -11
  19. data/ext/openssl/ossl_ocsp.h +3 -3
  20. data/ext/openssl/ossl_pkcs12.c +1 -0
  21. data/ext/openssl/ossl_pkcs7.c +4 -19
  22. data/ext/openssl/ossl_pkcs7.h +16 -0
  23. data/ext/openssl/ossl_pkey.c +206 -17
  24. data/ext/openssl/ossl_pkey.h +6 -6
  25. data/ext/openssl/ossl_pkey_dh.c +1 -1
  26. data/ext/openssl/ossl_pkey_dsa.c +2 -2
  27. data/ext/openssl/ossl_pkey_ec.c +38 -8
  28. data/ext/openssl/ossl_pkey_rsa.c +17 -9
  29. data/ext/openssl/ossl_rand.c +2 -40
  30. data/ext/openssl/ossl_ssl.c +205 -75
  31. data/ext/openssl/ossl_ts.c +1524 -0
  32. data/ext/openssl/ossl_ts.h +16 -0
  33. data/ext/openssl/ossl_x509.c +91 -0
  34. data/ext/openssl/ossl_x509cert.c +2 -2
  35. data/ext/openssl/ossl_x509ext.c +15 -0
  36. data/ext/openssl/ossl_x509name.c +15 -10
  37. data/ext/openssl/ossl_x509store.c +40 -22
  38. data/lib/openssl/bn.rb +1 -1
  39. data/lib/openssl/buffering.rb +33 -17
  40. data/lib/openssl/cipher.rb +1 -1
  41. data/lib/openssl/config.rb +53 -26
  42. data/lib/openssl/digest.rb +10 -12
  43. data/lib/openssl/hmac.rb +13 -0
  44. data/lib/openssl/marshal.rb +30 -0
  45. data/lib/openssl/pkcs5.rb +1 -1
  46. data/lib/openssl/pkey.rb +18 -1
  47. data/lib/openssl/ssl.rb +46 -7
  48. data/lib/openssl/version.rb +5 -0
  49. data/lib/openssl/x509.rb +155 -1
  50. data/lib/openssl.rb +25 -9
  51. metadata +25 -9
  52. data/ext/openssl/deprecation.rb +0 -23
  53. data/ext/openssl/ossl_version.h +0 -15
data/ext/openssl/ossl.c CHANGED
@@ -338,7 +338,7 @@ ossl_clear_error(void)
338
338
  * implementation.
339
339
  */
340
340
  VALUE
341
- ossl_get_errors(void)
341
+ ossl_get_errors(VALUE _)
342
342
  {
343
343
  VALUE ary;
344
344
  long e;
@@ -398,7 +398,7 @@ ossl_debug_set(VALUE self, VALUE val)
398
398
  }
399
399
 
400
400
  /*
401
- * call-seq
401
+ * call-seq:
402
402
  * OpenSSL.fips_mode -> true | false
403
403
  */
404
404
  static VALUE
@@ -497,8 +497,11 @@ print_mem_leaks(VALUE self)
497
497
  int ret;
498
498
  #endif
499
499
 
500
- BN_CTX_free(ossl_bn_ctx);
501
- ossl_bn_ctx = NULL;
500
+ #ifndef HAVE_RB_EXT_RACTOR_SAFE
501
+ // for Ruby 2.x
502
+ void ossl_bn_ctx_free(void); // ossl_bn.c
503
+ ossl_bn_ctx_free();
504
+ #endif
502
505
 
503
506
  #if OPENSSL_VERSION_NUMBER >= 0x10100000
504
507
  ret = CRYPTO_mem_leaks_fp(stderr);
@@ -604,6 +607,35 @@ static void Init_ossl_locks(void)
604
607
  }
605
608
  #endif /* !HAVE_OPENSSL_110_THREADING_API */
606
609
 
610
+ /*
611
+ * call-seq:
612
+ * OpenSSL.fixed_length_secure_compare(string, string) -> boolean
613
+ *
614
+ * Constant time memory comparison for fixed length strings, such as results
615
+ * of HMAC calculations.
616
+ *
617
+ * Returns +true+ if the strings are identical, +false+ if they are of the same
618
+ * length but not identical. If the length is different, +ArgumentError+ is
619
+ * raised.
620
+ */
621
+ static VALUE
622
+ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
623
+ {
624
+ const unsigned char *p1 = (const unsigned char *)StringValuePtr(str1);
625
+ const unsigned char *p2 = (const unsigned char *)StringValuePtr(str2);
626
+ long len1 = RSTRING_LEN(str1);
627
+ long len2 = RSTRING_LEN(str2);
628
+
629
+ if (len1 != len2) {
630
+ ossl_raise(rb_eArgError, "inputs must be of equal length");
631
+ }
632
+
633
+ switch (CRYPTO_memcmp(p1, p2, len1)) {
634
+ case 0: return Qtrue;
635
+ default: return Qfalse;
636
+ }
637
+ }
638
+
607
639
  /*
608
640
  * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the
609
641
  * OpenSSL[https://www.openssl.org/] library.
@@ -635,7 +667,7 @@ static void Init_ossl_locks(void)
635
667
  * ahold of the key may use it unless it is encrypted. In order to securely
636
668
  * export a key you may export it with a pass phrase.
637
669
  *
638
- * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
670
+ * cipher = OpenSSL::Cipher.new 'AES-256-CBC'
639
671
  * pass_phrase = 'my secure pass phrase goes here'
640
672
  *
641
673
  * key_secure = key.export cipher, pass_phrase
@@ -710,16 +742,14 @@ static void Init_ossl_locks(void)
710
742
  * To sign a document, a cryptographically secure hash of the document is
711
743
  * computed first, which is then signed using the private key.
712
744
  *
713
- * digest = OpenSSL::Digest::SHA256.new
714
- * signature = key.sign digest, document
745
+ * signature = key.sign 'SHA256', document
715
746
  *
716
747
  * To validate the signature, again a hash of the document is computed and
717
748
  * the signature is decrypted using the public key. The result is then
718
749
  * compared to the hash just computed, if they are equal the signature was
719
750
  * valid.
720
751
  *
721
- * digest = OpenSSL::Digest::SHA256.new
722
- * if key.verify digest, signature, document
752
+ * if key.verify 'SHA256', signature, document
723
753
  * puts 'Valid'
724
754
  * else
725
755
  * puts 'Invalid'
@@ -745,7 +775,7 @@ static void Init_ossl_locks(void)
745
775
  * using PBKDF2. PKCS #5 v2.0 recommends at least 8 bytes for the salt,
746
776
  * the number of iterations largely depends on the hardware being used.
747
777
  *
748
- * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
778
+ * cipher = OpenSSL::Cipher.new 'AES-256-CBC'
749
779
  * cipher.encrypt
750
780
  * iv = cipher.random_iv
751
781
  *
@@ -753,7 +783,7 @@ static void Init_ossl_locks(void)
753
783
  * salt = OpenSSL::Random.random_bytes 16
754
784
  * iter = 20000
755
785
  * key_len = cipher.key_len
756
- * digest = OpenSSL::Digest::SHA256.new
786
+ * digest = OpenSSL::Digest.new('SHA256')
757
787
  *
758
788
  * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
759
789
  * cipher.key = key
@@ -768,7 +798,7 @@ static void Init_ossl_locks(void)
768
798
  * Use the same steps as before to derive the symmetric AES key, this time
769
799
  * setting the Cipher up for decryption.
770
800
  *
771
- * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
801
+ * cipher = OpenSSL::Cipher.new 'AES-256-CBC'
772
802
  * cipher.decrypt
773
803
  * cipher.iv = iv # the one generated with #random_iv
774
804
  *
@@ -776,7 +806,7 @@ static void Init_ossl_locks(void)
776
806
  * salt = ... # the one generated above
777
807
  * iter = 20000
778
808
  * key_len = cipher.key_len
779
- * digest = OpenSSL::Digest::SHA256.new
809
+ * digest = OpenSSL::Digest.new('SHA256')
780
810
  *
781
811
  * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
782
812
  * cipher.key = key
@@ -803,7 +833,7 @@ static void Init_ossl_locks(void)
803
833
  *
804
834
  * First set up the cipher for encryption
805
835
  *
806
- * encryptor = OpenSSL::Cipher.new 'AES-128-CBC'
836
+ * encryptor = OpenSSL::Cipher.new 'AES-256-CBC'
807
837
  * encryptor.encrypt
808
838
  * encryptor.pkcs5_keyivgen pass_phrase, salt
809
839
  *
@@ -816,7 +846,7 @@ static void Init_ossl_locks(void)
816
846
  *
817
847
  * Use a new Cipher instance set up for decryption
818
848
  *
819
- * decryptor = OpenSSL::Cipher.new 'AES-128-CBC'
849
+ * decryptor = OpenSSL::Cipher.new 'AES-256-CBC'
820
850
  * decryptor.decrypt
821
851
  * decryptor.pkcs5_keyivgen pass_phrase, salt
822
852
  *
@@ -833,7 +863,7 @@ static void Init_ossl_locks(void)
833
863
  * signature.
834
864
  *
835
865
  * key = OpenSSL::PKey::RSA.new 2048
836
- * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
866
+ * name = OpenSSL::X509::Name.parse '/CN=nobody/DC=example'
837
867
  *
838
868
  * cert = OpenSSL::X509::Certificate.new
839
869
  * cert.version = 2
@@ -872,7 +902,7 @@ static void Init_ossl_locks(void)
872
902
  * certificate.
873
903
  *
874
904
  * cert.issuer = name
875
- * cert.sign key, OpenSSL::Digest::SHA1.new
905
+ * cert.sign key, OpenSSL::Digest.new('SHA1')
876
906
  *
877
907
  * open 'certificate.pem', 'w' do |io| io.write cert.to_pem end
878
908
  *
@@ -904,7 +934,7 @@ static void Init_ossl_locks(void)
904
934
  * ca_key = OpenSSL::PKey::RSA.new 2048
905
935
  * pass_phrase = 'my secure pass phrase goes here'
906
936
  *
907
- * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
937
+ * cipher = OpenSSL::Cipher.new 'AES-256-CBC'
908
938
  *
909
939
  * open 'ca_key.pem', 'w', 0400 do |io|
910
940
  * io.write ca_key.export(cipher, pass_phrase)
@@ -915,7 +945,7 @@ static void Init_ossl_locks(void)
915
945
  * A CA certificate is created the same way we created a certificate above, but
916
946
  * with different extensions.
917
947
  *
918
- * ca_name = OpenSSL::X509::Name.parse 'CN=ca/DC=example'
948
+ * ca_name = OpenSSL::X509::Name.parse '/CN=ca/DC=example'
919
949
  *
920
950
  * ca_cert = OpenSSL::X509::Certificate.new
921
951
  * ca_cert.serial = 0
@@ -948,7 +978,7 @@ static void Init_ossl_locks(void)
948
978
  *
949
979
  * Root CA certificates are self-signed.
950
980
  *
951
- * ca_cert.sign ca_key, OpenSSL::Digest::SHA1.new
981
+ * ca_cert.sign ca_key, OpenSSL::Digest.new('SHA1')
952
982
  *
953
983
  * The CA certificate is saved to disk so it may be distributed to all the
954
984
  * users of the keys this CA will sign.
@@ -966,7 +996,7 @@ static void Init_ossl_locks(void)
966
996
  * csr.version = 0
967
997
  * csr.subject = name
968
998
  * csr.public_key = key.public_key
969
- * csr.sign key, OpenSSL::Digest::SHA1.new
999
+ * csr.sign key, OpenSSL::Digest.new('SHA1')
970
1000
  *
971
1001
  * A CSR is saved to disk and sent to the CA for signing.
972
1002
  *
@@ -1010,7 +1040,7 @@ static void Init_ossl_locks(void)
1010
1040
  * csr_cert.add_extension \
1011
1041
  * extension_factory.create_extension('subjectKeyIdentifier', 'hash')
1012
1042
  *
1013
- * csr_cert.sign ca_key, OpenSSL::Digest::SHA1.new
1043
+ * csr_cert.sign ca_key, OpenSSL::Digest.new('SHA1')
1014
1044
  *
1015
1045
  * open 'csr_cert.pem', 'w' do |io|
1016
1046
  * io.write csr_cert.to_pem
@@ -1099,6 +1129,11 @@ static void Init_ossl_locks(void)
1099
1129
  void
1100
1130
  Init_openssl(void)
1101
1131
  {
1132
+ #if HAVE_RB_EXT_RACTOR_SAFE
1133
+ rb_ext_ractor_safe(true);
1134
+ #endif
1135
+
1136
+ #undef rb_intern
1102
1137
  /*
1103
1138
  * Init timezone info
1104
1139
  */
@@ -1124,11 +1159,7 @@ Init_openssl(void)
1124
1159
  */
1125
1160
  mOSSL = rb_define_module("OpenSSL");
1126
1161
  rb_global_variable(&mOSSL);
1127
-
1128
- /*
1129
- * OpenSSL ruby extension version
1130
- */
1131
- rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION));
1162
+ rb_define_singleton_method(mOSSL, "fixed_length_secure_compare", ossl_crypto_fixed_length_secure_compare, 2);
1132
1163
 
1133
1164
  /*
1134
1165
  * Version of OpenSSL the ruby OpenSSL extension was built with
@@ -1204,6 +1235,9 @@ Init_openssl(void)
1204
1235
  Init_ossl_pkey();
1205
1236
  Init_ossl_rand();
1206
1237
  Init_ossl_ssl();
1238
+ #ifndef OPENSSL_NO_TS
1239
+ Init_ossl_ts();
1240
+ #endif
1207
1241
  Init_ossl_x509();
1208
1242
  Init_ossl_ocsp();
1209
1243
  Init_ossl_engine();
data/ext/openssl/ossl.h CHANGED
@@ -13,8 +13,8 @@
13
13
  #include RUBY_EXTCONF_H
14
14
 
15
15
  #include <assert.h>
16
- #include <errno.h>
17
16
  #include <ruby.h>
17
+ #include <errno.h>
18
18
  #include <ruby/io.h>
19
19
  #include <ruby/thread.h>
20
20
  #include <openssl/opensslv.h>
@@ -27,7 +27,9 @@
27
27
  #include <openssl/hmac.h>
28
28
  #include <openssl/rand.h>
29
29
  #include <openssl/conf.h>
30
- #include <openssl/conf_api.h>
30
+ #ifndef OPENSSL_NO_TS
31
+ #include <openssl/ts.h>
32
+ #endif
31
33
  #include <openssl/crypto.h>
32
34
  #if !defined(OPENSSL_NO_ENGINE)
33
35
  # include <openssl/engine.h>
@@ -86,9 +88,8 @@ VALUE ossl_buf2str(char *buf, int len);
86
88
  VALUE ossl_str_new(const char *, long, int *);
87
89
  #define ossl_str_adjust(str, p) \
88
90
  do{\
89
- long len = RSTRING_LEN(str);\
90
91
  long newlen = (long)((p) - (unsigned char*)RSTRING_PTR(str));\
91
- assert(newlen <= len);\
92
+ assert(newlen <= RSTRING_LEN(str));\
92
93
  rb_str_set_len((str), newlen);\
93
94
  }while(0)
94
95
  /*
@@ -168,7 +169,9 @@ void ossl_debug(const char *, ...);
168
169
  #include "ossl_pkey.h"
169
170
  #include "ossl_rand.h"
170
171
  #include "ossl_ssl.h"
171
- #include "ossl_version.h"
172
+ #ifndef OPENSSL_NO_TS
173
+ #include "ossl_ts.h"
174
+ #endif
172
175
  #include "ossl_x509.h"
173
176
  #include "ossl_engine.h"
174
177
  #include "ossl_kdf.h"
@@ -1285,6 +1285,30 @@ ossl_asn1obj_get_ln(VALUE self)
1285
1285
  return ret;
1286
1286
  }
1287
1287
 
1288
+ /*
1289
+ * call-seq:
1290
+ * oid == other_oid => true or false
1291
+ *
1292
+ * Returns +true+ if _other_oid_ is the same as _oid_
1293
+ */
1294
+ static VALUE
1295
+ ossl_asn1obj_eq(VALUE self, VALUE other)
1296
+ {
1297
+ VALUE valSelf, valOther;
1298
+ int nidSelf, nidOther;
1299
+
1300
+ valSelf = ossl_asn1_get_value(self);
1301
+ valOther = ossl_asn1_get_value(other);
1302
+
1303
+ if ((nidSelf = OBJ_txt2nid(StringValueCStr(valSelf))) == NID_undef)
1304
+ ossl_raise(eASN1Error, "OBJ_txt2nid");
1305
+
1306
+ if ((nidOther = OBJ_txt2nid(StringValueCStr(valOther))) == NID_undef)
1307
+ ossl_raise(eASN1Error, "OBJ_txt2nid");
1308
+
1309
+ return nidSelf == nidOther ? Qtrue : Qfalse;
1310
+ }
1311
+
1288
1312
  static VALUE
1289
1313
  asn1obj_get_oid_i(VALUE vobj)
1290
1314
  {
@@ -1360,6 +1384,7 @@ OSSL_ASN1_IMPL_FACTORY_METHOD(EndOfContent)
1360
1384
  void
1361
1385
  Init_ossl_asn1(void)
1362
1386
  {
1387
+ #undef rb_intern
1363
1388
  VALUE ary;
1364
1389
  int i;
1365
1390
 
@@ -1817,12 +1842,14 @@ do{\
1817
1842
  rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0);
1818
1843
  rb_define_alias(cASN1ObjectId, "short_name", "sn");
1819
1844
  rb_define_alias(cASN1ObjectId, "long_name", "ln");
1845
+ rb_define_method(cASN1ObjectId, "==", ossl_asn1obj_eq, 1);
1820
1846
  rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
1821
1847
 
1822
1848
  rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0);
1823
1849
  rb_define_method(cASN1EndOfContent, "to_der", ossl_asn1eoc_to_der, 0);
1824
1850
 
1825
1851
  class_tag_map = rb_hash_new();
1852
+ rb_gc_register_mark_object(class_tag_map);
1826
1853
  rb_hash_aset(class_tag_map, cASN1EndOfContent, INT2NUM(V_ASN1_EOC));
1827
1854
  rb_hash_aset(class_tag_map, cASN1Boolean, INT2NUM(V_ASN1_BOOLEAN));
1828
1855
  rb_hash_aset(class_tag_map, cASN1Integer, INT2NUM(V_ASN1_INTEGER));
@@ -1846,7 +1873,6 @@ do{\
1846
1873
  rb_hash_aset(class_tag_map, cASN1GeneralString, INT2NUM(V_ASN1_GENERALSTRING));
1847
1874
  rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING));
1848
1875
  rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING));
1849
- rb_global_variable(&class_tag_map);
1850
1876
 
1851
1877
  id_each = rb_intern_const("each");
1852
1878
  }
@@ -10,6 +10,10 @@
10
10
  /* modified by Michal Rokos <m.rokos@sh.cvut.cz> */
11
11
  #include "ossl.h"
12
12
 
13
+ #if HAVE_RB_EXT_RACTOR_SAFE
14
+ #include <ruby/ractor.h>
15
+ #endif
16
+
13
17
  #define NewBN(klass) \
14
18
  TypedData_Wrap_Struct((klass), &ossl_bn_type, 0)
15
19
  #define SetBN(obj, bn) do { \
@@ -150,12 +154,58 @@ ossl_bn_value_ptr(volatile VALUE *ptr)
150
154
  /*
151
155
  * Private
152
156
  */
153
- /*
154
- * BN_CTX - is used in more difficult math. ops
155
- * (Why just 1? Because Ruby itself isn't thread safe,
156
- * we don't need to care about threads)
157
- */
158
- BN_CTX *ossl_bn_ctx;
157
+
158
+ #if HAVE_RB_EXT_RACTOR_SAFE
159
+ void
160
+ ossl_bn_ctx_free(void *ptr)
161
+ {
162
+ BN_CTX *ctx = (BN_CTX *)ptr;
163
+ BN_CTX_free(ctx);
164
+ }
165
+
166
+ struct rb_ractor_local_storage_type ossl_bn_ctx_key_type = {
167
+ NULL, // mark
168
+ ossl_bn_ctx_free,
169
+ };
170
+
171
+ rb_ractor_local_key_t ossl_bn_ctx_key;
172
+
173
+ BN_CTX *
174
+ ossl_bn_ctx_get(void)
175
+ {
176
+ // stored in ractor local storage
177
+
178
+ BN_CTX *ctx = rb_ractor_local_storage_ptr(ossl_bn_ctx_key);
179
+ if (!ctx) {
180
+ if (!(ctx = BN_CTX_new())) {
181
+ ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
182
+ }
183
+ rb_ractor_local_storage_ptr_set(ossl_bn_ctx_key, ctx);
184
+ }
185
+ return ctx;
186
+ }
187
+ #else
188
+ // for ruby 2.x
189
+ static BN_CTX *gv_ossl_bn_ctx;
190
+
191
+ BN_CTX *
192
+ ossl_bn_ctx_get(void)
193
+ {
194
+ if (gv_ossl_bn_ctx == NULL) {
195
+ if (!(gv_ossl_bn_ctx = BN_CTX_new())) {
196
+ ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
197
+ }
198
+ }
199
+ return gv_ossl_bn_ctx;
200
+ }
201
+
202
+ void
203
+ ossl_bn_ctx_free(void)
204
+ {
205
+ BN_CTX_free(gv_ossl_bn_ctx);
206
+ gv_ossl_bn_ctx = NULL;
207
+ }
208
+ #endif
159
209
 
160
210
  static VALUE
161
211
  ossl_bn_alloc(VALUE klass)
@@ -173,7 +223,6 @@ ossl_bn_alloc(VALUE klass)
173
223
 
174
224
  /*
175
225
  * call-seq:
176
- * OpenSSL::BN.new => aBN
177
226
  * OpenSSL::BN.new(bn) => aBN
178
227
  * OpenSSL::BN.new(integer) => aBN
179
228
  * OpenSSL::BN.new(string) => aBN
@@ -187,11 +236,16 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
187
236
  BIGNUM *bn;
188
237
  VALUE str, bs;
189
238
  int base = 10;
239
+ char *ptr;
190
240
 
191
241
  if (rb_scan_args(argc, argv, "11", &str, &bs) == 2) {
192
242
  base = NUM2INT(bs);
193
243
  }
194
244
 
245
+ if (NIL_P(str)) {
246
+ ossl_raise(rb_eArgError, "invalid argument");
247
+ }
248
+
195
249
  if (RB_INTEGER_TYPE_P(str)) {
196
250
  GetBN(self, bn);
197
251
  integer_to_bnptr(str, bn);
@@ -213,12 +267,14 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
213
267
  GetBN(self, bn);
214
268
  switch (base) {
215
269
  case 0:
216
- if (!BN_mpi2bn((unsigned char *)StringValuePtr(str), RSTRING_LENINT(str), bn)) {
270
+ ptr = StringValuePtr(str);
271
+ if (!BN_mpi2bn((unsigned char *)ptr, RSTRING_LENINT(str), bn)) {
217
272
  ossl_raise(eBNError, NULL);
218
273
  }
219
274
  break;
220
275
  case 2:
221
- if (!BN_bin2bn((unsigned char *)StringValuePtr(str), RSTRING_LENINT(str), bn)) {
276
+ ptr = StringValuePtr(str);
277
+ if (!BN_bin2bn((unsigned char *)ptr, RSTRING_LENINT(str), bn)) {
222
278
  ossl_raise(eBNError, NULL);
223
279
  }
224
280
  break;
@@ -397,7 +453,7 @@ ossl_bn_is_negative(VALUE self)
397
453
  if (!(result = BN_new())) { \
398
454
  ossl_raise(eBNError, NULL); \
399
455
  } \
400
- if (!BN_##func(result, bn, ossl_bn_ctx)) { \
456
+ if (BN_##func(result, bn, ossl_bn_ctx) <= 0) { \
401
457
  BN_free(result); \
402
458
  ossl_raise(eBNError, NULL); \
403
459
  } \
@@ -423,7 +479,7 @@ BIGNUM_1c(sqr)
423
479
  if (!(result = BN_new())) { \
424
480
  ossl_raise(eBNError, NULL); \
425
481
  } \
426
- if (!BN_##func(result, bn1, bn2)) { \
482
+ if (BN_##func(result, bn1, bn2) <= 0) { \
427
483
  BN_free(result); \
428
484
  ossl_raise(eBNError, NULL); \
429
485
  } \
@@ -456,7 +512,7 @@ BIGNUM_2(sub)
456
512
  if (!(result = BN_new())) { \
457
513
  ossl_raise(eBNError, NULL); \
458
514
  } \
459
- if (!BN_##func(result, bn1, bn2, ossl_bn_ctx)) { \
515
+ if (BN_##func(result, bn1, bn2, ossl_bn_ctx) <= 0) { \
460
516
  BN_free(result); \
461
517
  ossl_raise(eBNError, NULL); \
462
518
  } \
@@ -500,11 +556,21 @@ BIGNUM_2c(gcd)
500
556
  BIGNUM_2c(mod_sqr)
501
557
 
502
558
  /*
503
- * Document-method: OpenSSL::BN#mod_inverse
504
559
  * call-seq:
505
- * bn.mod_inverse(bn2) => aBN
560
+ * bn.mod_inverse(bn2) => aBN
506
561
  */
507
- BIGNUM_2c(mod_inverse)
562
+ static VALUE
563
+ ossl_bn_mod_inverse(VALUE self, VALUE other)
564
+ {
565
+ BIGNUM *bn1, *bn2 = GetBNPtr(other), *result;
566
+ VALUE obj;
567
+ GetBN(self, bn1);
568
+ obj = NewBN(rb_obj_class(self));
569
+ if (!(result = BN_mod_inverse(NULL, bn1, bn2, ossl_bn_ctx)))
570
+ ossl_raise(eBNError, "BN_mod_inverse");
571
+ SetBN(obj, result);
572
+ return obj;
573
+ }
508
574
 
509
575
  /*
510
576
  * call-seq:
@@ -553,7 +619,7 @@ ossl_bn_div(VALUE self, VALUE other)
553
619
  if (!(result = BN_new())) { \
554
620
  ossl_raise(eBNError, NULL); \
555
621
  } \
556
- if (!BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx)) { \
622
+ if (BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx) <= 0) { \
557
623
  BN_free(result); \
558
624
  ossl_raise(eBNError, NULL); \
559
625
  } \
@@ -595,7 +661,7 @@ BIGNUM_3c(mod_exp)
595
661
  { \
596
662
  BIGNUM *bn; \
597
663
  GetBN(self, bn); \
598
- if (!BN_##func(bn, NUM2INT(bit))) { \
664
+ if (BN_##func(bn, NUM2INT(bit)) <= 0) { \
599
665
  ossl_raise(eBNError, NULL); \
600
666
  } \
601
667
  return self; \
@@ -655,7 +721,7 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit)
655
721
  if (!(result = BN_new())) { \
656
722
  ossl_raise(eBNError, NULL); \
657
723
  } \
658
- if (!BN_##func(result, bn, b)) { \
724
+ if (BN_##func(result, bn, b) <= 0) { \
659
725
  BN_free(result); \
660
726
  ossl_raise(eBNError, NULL); \
661
727
  } \
@@ -685,7 +751,7 @@ BIGNUM_SHIFT(rshift)
685
751
  int b; \
686
752
  b = NUM2INT(bits); \
687
753
  GetBN(self, bn); \
688
- if (!BN_##func(bn, bn, b)) \
754
+ if (BN_##func(bn, bn, b) <= 0) \
689
755
  ossl_raise(eBNError, NULL); \
690
756
  return self; \
691
757
  }
@@ -724,7 +790,7 @@ BIGNUM_SELF_SHIFT(rshift)
724
790
  if (!(result = BN_new())) { \
725
791
  ossl_raise(eBNError, NULL); \
726
792
  } \
727
- if (!BN_##func(result, b, top, bottom)) { \
793
+ if (BN_##func(result, b, top, bottom) <= 0) { \
728
794
  BN_free(result); \
729
795
  ossl_raise(eBNError, NULL); \
730
796
  } \
@@ -753,7 +819,7 @@ BIGNUM_RAND(pseudo_rand)
753
819
  if (!(result = BN_new())) { \
754
820
  ossl_raise(eBNError, NULL); \
755
821
  } \
756
- if (!BN_##func##_range(result, bn)) { \
822
+ if (BN_##func##_range(result, bn) <= 0) { \
757
823
  BN_free(result); \
758
824
  ossl_raise(eBNError, NULL); \
759
825
  } \
@@ -1086,9 +1152,11 @@ Init_ossl_bn(void)
1086
1152
  eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
1087
1153
  #endif
1088
1154
 
1089
- if (!(ossl_bn_ctx = BN_CTX_new())) {
1090
- ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
1091
- }
1155
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
1156
+ ossl_bn_ctx_key = rb_ractor_local_storage_ptr_newkey(&ossl_bn_ctx_key_type);
1157
+ #else
1158
+ ossl_bn_ctx_get();
1159
+ #endif
1092
1160
 
1093
1161
  eBNError = rb_define_class_under(mOSSL, "BNError", eOSSLError);
1094
1162
 
@@ -13,7 +13,8 @@
13
13
  extern VALUE cBN;
14
14
  extern VALUE eBNError;
15
15
 
16
- extern BN_CTX *ossl_bn_ctx;
16
+ BN_CTX *ossl_bn_ctx_get(void);
17
+ #define ossl_bn_ctx ossl_bn_ctx_get()
17
18
 
18
19
  #define GetBNPtr(obj) ossl_bn_value_ptr(&(obj))
19
20