openssl 2.1.1 → 2.2.1

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 (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