openssl 2.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +35 -45
  3. data/History.md +426 -0
  4. data/README.md +38 -21
  5. data/ext/openssl/extconf.rb +132 -72
  6. data/ext/openssl/openssl_missing.c +0 -66
  7. data/ext/openssl/openssl_missing.h +62 -46
  8. data/ext/openssl/ossl.c +177 -252
  9. data/ext/openssl/ossl.h +39 -17
  10. data/ext/openssl/ossl_asn1.c +53 -14
  11. data/ext/openssl/ossl_bn.c +288 -146
  12. data/ext/openssl/ossl_bn.h +2 -1
  13. data/ext/openssl/ossl_cipher.c +42 -32
  14. data/ext/openssl/ossl_config.c +412 -41
  15. data/ext/openssl/ossl_config.h +4 -7
  16. data/ext/openssl/ossl_digest.c +32 -63
  17. data/ext/openssl/ossl_engine.c +19 -28
  18. data/ext/openssl/ossl_hmac.c +61 -146
  19. data/ext/openssl/ossl_kdf.c +15 -23
  20. data/ext/openssl/ossl_ns_spki.c +2 -2
  21. data/ext/openssl/ossl_ocsp.c +17 -70
  22. data/ext/openssl/ossl_ocsp.h +3 -3
  23. data/ext/openssl/ossl_pkcs12.c +23 -4
  24. data/ext/openssl/ossl_pkcs7.c +49 -81
  25. data/ext/openssl/ossl_pkcs7.h +16 -0
  26. data/ext/openssl/ossl_pkey.c +1508 -195
  27. data/ext/openssl/ossl_pkey.h +41 -78
  28. data/ext/openssl/ossl_pkey_dh.c +153 -348
  29. data/ext/openssl/ossl_pkey_dsa.c +157 -413
  30. data/ext/openssl/ossl_pkey_ec.c +257 -343
  31. data/ext/openssl/ossl_pkey_rsa.c +166 -490
  32. data/ext/openssl/ossl_provider.c +211 -0
  33. data/ext/openssl/ossl_provider.h +5 -0
  34. data/ext/openssl/ossl_rand.c +2 -40
  35. data/ext/openssl/ossl_ssl.c +666 -456
  36. data/ext/openssl/ossl_ssl_session.c +29 -30
  37. data/ext/openssl/ossl_ts.c +1539 -0
  38. data/ext/openssl/ossl_ts.h +16 -0
  39. data/ext/openssl/ossl_x509.c +86 -1
  40. data/ext/openssl/ossl_x509attr.c +1 -1
  41. data/ext/openssl/ossl_x509cert.c +170 -14
  42. data/ext/openssl/ossl_x509crl.c +14 -11
  43. data/ext/openssl/ossl_x509ext.c +29 -9
  44. data/ext/openssl/ossl_x509name.c +24 -12
  45. data/ext/openssl/ossl_x509req.c +14 -11
  46. data/ext/openssl/ossl_x509revoked.c +4 -4
  47. data/ext/openssl/ossl_x509store.c +205 -96
  48. data/lib/openssl/bn.rb +1 -1
  49. data/lib/openssl/buffering.rb +42 -20
  50. data/lib/openssl/cipher.rb +1 -1
  51. data/lib/openssl/digest.rb +10 -16
  52. data/lib/openssl/hmac.rb +78 -0
  53. data/lib/openssl/marshal.rb +30 -0
  54. data/lib/openssl/pkcs5.rb +1 -1
  55. data/lib/openssl/pkey.rb +447 -1
  56. data/lib/openssl/ssl.rb +68 -24
  57. data/lib/openssl/version.rb +5 -0
  58. data/lib/openssl/x509.rb +177 -1
  59. data/lib/openssl.rb +24 -9
  60. metadata +18 -71
  61. data/ext/openssl/deprecation.rb +0 -23
  62. data/ext/openssl/ossl_version.h +0 -15
  63. data/ext/openssl/ruby_missing.h +0 -24
  64. data/lib/openssl/config.rb +0 -474
data/ext/openssl/ossl.c CHANGED
@@ -9,13 +9,19 @@
9
9
  */
10
10
  #include "ossl.h"
11
11
  #include <stdarg.h> /* for ossl_raise */
12
- #include <ruby/thread_native.h> /* for OpenSSL < 1.1.0 locks */
12
+
13
+ /* OpenSSL >= 1.1.0 and LibreSSL >= 2.9.0 */
14
+ #if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER >= 0x10100000
15
+ # define HAVE_OPENSSL_110_THREADING_API
16
+ #else
17
+ # include <ruby/thread_native.h>
18
+ #endif
13
19
 
14
20
  /*
15
21
  * Data Conversion
16
22
  */
17
23
  #define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \
18
- STACK_OF(type) * \
24
+ VALUE \
19
25
  ossl_##name##_ary2sk0(VALUE ary) \
20
26
  { \
21
27
  STACK_OF(type) *sk; \
@@ -37,7 +43,7 @@ ossl_##name##_ary2sk0(VALUE ary) \
37
43
  x = dup(val); /* NEED TO DUP */ \
38
44
  sk_##type##_push(sk, x); \
39
45
  } \
40
- return sk; \
46
+ return (VALUE)sk; \
41
47
  } \
42
48
  \
43
49
  STACK_OF(type) * \
@@ -201,7 +207,7 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
201
207
 
202
208
  while (1) {
203
209
  /*
204
- * when the flag is nonzero, this passphrase
210
+ * when the flag is nonzero, this password
205
211
  * will be used to perform encryption; otherwise it will
206
212
  * be used to perform decryption.
207
213
  */
@@ -262,31 +268,32 @@ ossl_to_der_if_possible(VALUE obj)
262
268
  /*
263
269
  * Errors
264
270
  */
265
- static VALUE
266
- ossl_make_error(VALUE exc, const char *fmt, va_list args)
271
+ VALUE
272
+ ossl_make_error(VALUE exc, VALUE str)
267
273
  {
268
- VALUE str = Qnil;
269
274
  unsigned long e;
275
+ const char *data;
276
+ int flags;
270
277
 
271
- if (fmt) {
272
- str = rb_vsprintf(fmt, args);
273
- }
274
- e = ERR_peek_last_error();
278
+ if (NIL_P(str))
279
+ str = rb_str_new(NULL, 0);
280
+
281
+ #ifdef HAVE_ERR_GET_ERROR_ALL
282
+ e = ERR_peek_last_error_all(NULL, NULL, NULL, &data, &flags);
283
+ #else
284
+ e = ERR_peek_last_error_line_data(NULL, NULL, &data, &flags);
285
+ #endif
275
286
  if (e) {
276
- const char *msg = ERR_reason_error_string(e);
287
+ const char *msg = ERR_reason_error_string(e);
277
288
 
278
- if (NIL_P(str)) {
279
- if (msg) str = rb_str_new_cstr(msg);
280
- }
281
- else {
282
- if (RSTRING_LEN(str)) rb_str_cat2(str, ": ");
283
- rb_str_cat2(str, msg ? msg : "(null)");
284
- }
285
- ossl_clear_error();
289
+ if (RSTRING_LEN(str)) rb_str_cat_cstr(str, ": ");
290
+ rb_str_cat_cstr(str, msg ? msg : "(null)");
291
+ if (flags & ERR_TXT_STRING && data)
292
+ rb_str_catf(str, " (%s)", data);
293
+ ossl_clear_error();
286
294
  }
287
295
 
288
- if (NIL_P(str)) str = rb_str_new(0, 0);
289
- return rb_exc_new3(exc, str);
296
+ return rb_exc_new_str(exc, str);
290
297
  }
291
298
 
292
299
  void
@@ -294,37 +301,48 @@ ossl_raise(VALUE exc, const char *fmt, ...)
294
301
  {
295
302
  va_list args;
296
303
  VALUE err;
297
- va_start(args, fmt);
298
- err = ossl_make_error(exc, fmt, args);
299
- va_end(args);
300
- rb_exc_raise(err);
304
+
305
+ if (fmt) {
306
+ va_start(args, fmt);
307
+ err = rb_vsprintf(fmt, args);
308
+ va_end(args);
309
+ }
310
+ else {
311
+ err = Qnil;
312
+ }
313
+
314
+ rb_exc_raise(ossl_make_error(exc, err));
301
315
  }
302
316
 
303
317
  void
304
318
  ossl_clear_error(void)
305
319
  {
306
320
  if (dOSSL == Qtrue) {
307
- unsigned long e;
308
- const char *file, *data, *errstr;
309
- int line, flags;
310
-
311
- while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) {
312
- errstr = ERR_error_string(e, NULL);
313
- if (!errstr)
314
- errstr = "(null)";
315
-
316
- if (flags & ERR_TXT_STRING) {
317
- if (!data)
318
- data = "(null)";
319
- rb_warn("error on stack: %s (%s)", errstr, data);
320
- }
321
- else {
322
- rb_warn("error on stack: %s", errstr);
323
- }
324
- }
321
+ unsigned long e;
322
+ const char *file, *data, *func, *lib, *reason;
323
+ char append[256] = "";
324
+ int line, flags;
325
+
326
+ #ifdef HAVE_ERR_GET_ERROR_ALL
327
+ while ((e = ERR_get_error_all(&file, &line, &func, &data, &flags))) {
328
+ #else
329
+ while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) {
330
+ func = ERR_func_error_string(e);
331
+ #endif
332
+ lib = ERR_lib_error_string(e);
333
+ reason = ERR_reason_error_string(e);
334
+
335
+ if (flags & ERR_TXT_STRING) {
336
+ if (!data)
337
+ data = "(null)";
338
+ snprintf(append, sizeof(append), " (%s)", data);
339
+ }
340
+ rb_warn("error on stack: error:%08lX:%s:%s:%s%s", e, lib ? lib : "",
341
+ func ? func : "", reason ? reason : "", append);
342
+ }
325
343
  }
326
344
  else {
327
- ERR_clear_error();
345
+ ERR_clear_error();
328
346
  }
329
347
  }
330
348
 
@@ -338,7 +356,7 @@ ossl_clear_error(void)
338
356
  * implementation.
339
357
  */
340
358
  VALUE
341
- ossl_get_errors(void)
359
+ ossl_get_errors(VALUE _)
342
360
  {
343
361
  VALUE ary;
344
362
  long e;
@@ -356,22 +374,6 @@ ossl_get_errors(void)
356
374
  */
357
375
  VALUE dOSSL;
358
376
 
359
- #if !defined(HAVE_VA_ARGS_MACRO)
360
- void
361
- ossl_debug(const char *fmt, ...)
362
- {
363
- va_list args;
364
-
365
- if (dOSSL == Qtrue) {
366
- fprintf(stderr, "OSSL_DEBUG: ");
367
- va_start(args, fmt);
368
- vfprintf(stderr, fmt, args);
369
- va_end(args);
370
- fprintf(stderr, " [CONTEXT N/A]\n");
371
- }
372
- }
373
- #endif
374
-
375
377
  /*
376
378
  * call-seq:
377
379
  * OpenSSL.debug -> true | false
@@ -386,7 +388,7 @@ ossl_debug_get(VALUE self)
386
388
  * call-seq:
387
389
  * OpenSSL.debug = boolean -> boolean
388
390
  *
389
- * Turns on or off debug mode. With debug mode, all erros added to the OpenSSL
391
+ * Turns on or off debug mode. With debug mode, all errors added to the OpenSSL
390
392
  * error queue will be printed to stderr.
391
393
  */
392
394
  static VALUE
@@ -398,14 +400,18 @@ ossl_debug_set(VALUE self, VALUE val)
398
400
  }
399
401
 
400
402
  /*
401
- * call-seq
403
+ * call-seq:
402
404
  * OpenSSL.fips_mode -> true | false
403
405
  */
404
406
  static VALUE
405
407
  ossl_fips_mode_get(VALUE self)
406
408
  {
407
409
 
408
- #ifdef OPENSSL_FIPS
410
+ #if OSSL_OPENSSL_PREREQ(3, 0, 0)
411
+ VALUE enabled;
412
+ enabled = EVP_default_properties_is_fips_enabled(NULL) ? Qtrue : Qfalse;
413
+ return enabled;
414
+ #elif defined(OPENSSL_FIPS)
409
415
  VALUE enabled;
410
416
  enabled = FIPS_mode() ? Qtrue : Qfalse;
411
417
  return enabled;
@@ -429,8 +435,18 @@ ossl_fips_mode_get(VALUE self)
429
435
  static VALUE
430
436
  ossl_fips_mode_set(VALUE self, VALUE enabled)
431
437
  {
432
-
433
- #ifdef OPENSSL_FIPS
438
+ #if OSSL_OPENSSL_PREREQ(3, 0, 0)
439
+ if (RTEST(enabled)) {
440
+ if (!EVP_default_properties_enable_fips(NULL, 1)) {
441
+ ossl_raise(eOSSLError, "Turning on FIPS mode failed");
442
+ }
443
+ } else {
444
+ if (!EVP_default_properties_enable_fips(NULL, 0)) {
445
+ ossl_raise(eOSSLError, "Turning off FIPS mode failed");
446
+ }
447
+ }
448
+ return enabled;
449
+ #elif defined(OPENSSL_FIPS)
434
450
  if (RTEST(enabled)) {
435
451
  int mode = FIPS_mode();
436
452
  if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */
@@ -447,72 +463,6 @@ ossl_fips_mode_set(VALUE self, VALUE enabled)
447
463
  #endif
448
464
  }
449
465
 
450
- #if defined(OSSL_DEBUG)
451
- #if !defined(LIBRESSL_VERSION_NUMBER) && \
452
- (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG) || \
453
- defined(CRYPTO_malloc_debug_init))
454
- /*
455
- * call-seq:
456
- * OpenSSL.mem_check_start -> nil
457
- *
458
- * Calls CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON). Starts tracking memory
459
- * allocations. See also OpenSSL.print_mem_leaks.
460
- *
461
- * This is available only when built with a capable OpenSSL and --enable-debug
462
- * configure option.
463
- */
464
- static VALUE
465
- mem_check_start(VALUE self)
466
- {
467
- CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
468
- return Qnil;
469
- }
470
-
471
- /*
472
- * call-seq:
473
- * OpenSSL.print_mem_leaks -> true | false
474
- *
475
- * For debugging the Ruby/OpenSSL library. Calls CRYPTO_mem_leaks_fp(stderr).
476
- * Prints detected memory leaks to standard error. This cleans the global state
477
- * up thus you cannot use any methods of the library after calling this.
478
- *
479
- * Returns +true+ if leaks detected, +false+ otherwise.
480
- *
481
- * This is available only when built with a capable OpenSSL and --enable-debug
482
- * configure option.
483
- *
484
- * === Example
485
- * OpenSSL.mem_check_start
486
- * NOT_GCED = OpenSSL::PKey::RSA.new(256)
487
- *
488
- * END {
489
- * GC.start
490
- * OpenSSL.print_mem_leaks # will print the leakage
491
- * }
492
- */
493
- static VALUE
494
- print_mem_leaks(VALUE self)
495
- {
496
- #if OPENSSL_VERSION_NUMBER >= 0x10100000
497
- int ret;
498
- #endif
499
-
500
- BN_CTX_free(ossl_bn_ctx);
501
- ossl_bn_ctx = NULL;
502
-
503
- #if OPENSSL_VERSION_NUMBER >= 0x10100000
504
- ret = CRYPTO_mem_leaks_fp(stderr);
505
- if (ret < 0)
506
- ossl_raise(eOSSLError, "CRYPTO_mem_leaks_fp");
507
- return ret ? Qfalse : Qtrue;
508
- #else
509
- CRYPTO_mem_leaks_fp(stderr);
510
- return Qnil;
511
- #endif
512
- }
513
- #endif
514
- #endif
515
-
516
466
  #if !defined(HAVE_OPENSSL_110_THREADING_API)
517
467
  /**
518
468
  * Stores locks needed for OpenSSL thread safety
@@ -604,6 +554,35 @@ static void Init_ossl_locks(void)
604
554
  }
605
555
  #endif /* !HAVE_OPENSSL_110_THREADING_API */
606
556
 
557
+ /*
558
+ * call-seq:
559
+ * OpenSSL.fixed_length_secure_compare(string, string) -> boolean
560
+ *
561
+ * Constant time memory comparison for fixed length strings, such as results
562
+ * of HMAC calculations.
563
+ *
564
+ * Returns +true+ if the strings are identical, +false+ if they are of the same
565
+ * length but not identical. If the length is different, +ArgumentError+ is
566
+ * raised.
567
+ */
568
+ static VALUE
569
+ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
570
+ {
571
+ const unsigned char *p1 = (const unsigned char *)StringValuePtr(str1);
572
+ const unsigned char *p2 = (const unsigned char *)StringValuePtr(str2);
573
+ long len1 = RSTRING_LEN(str1);
574
+ long len2 = RSTRING_LEN(str2);
575
+
576
+ if (len1 != len2) {
577
+ ossl_raise(rb_eArgError, "inputs must be of equal length");
578
+ }
579
+
580
+ switch (CRYPTO_memcmp(p1, p2, len1)) {
581
+ case 0: return Qtrue;
582
+ default: return Qfalse;
583
+ }
584
+ }
585
+
607
586
  /*
608
587
  * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the
609
588
  * OpenSSL[https://www.openssl.org/] library.
@@ -626,23 +605,21 @@ static void Init_ossl_locks(void)
626
605
  *
627
606
  * key = OpenSSL::PKey::RSA.new 2048
628
607
  *
629
- * open 'private_key.pem', 'w' do |io| io.write key.to_pem end
630
- * open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end
608
+ * File.write 'private_key.pem', key.private_to_pem
609
+ * File.write 'public_key.pem', key.public_to_pem
631
610
  *
632
611
  * === Exporting a Key
633
612
  *
634
613
  * Keys saved to disk without encryption are not secure as anyone who gets
635
614
  * ahold of the key may use it unless it is encrypted. In order to securely
636
- * export a key you may export it with a pass phrase.
615
+ * export a key you may export it with a password.
637
616
  *
638
- * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
639
- * pass_phrase = 'my secure pass phrase goes here'
617
+ * cipher = OpenSSL::Cipher.new 'aes-256-cbc'
618
+ * password = 'my secure password goes here'
640
619
  *
641
- * key_secure = key.export cipher, pass_phrase
620
+ * key_secure = key.private_to_pem cipher, password
642
621
  *
643
- * open 'private.secure.pem', 'w' do |io|
644
- * io.write key_secure
645
- * end
622
+ * File.write 'private.secure.pem', key_secure
646
623
  *
647
624
  * OpenSSL::Cipher.ciphers returns a list of available ciphers.
648
625
  *
@@ -650,25 +627,25 @@ static void Init_ossl_locks(void)
650
627
  *
651
628
  * A key can also be loaded from a file.
652
629
  *
653
- * key2 = OpenSSL::PKey::RSA.new File.read 'private_key.pem'
630
+ * key2 = OpenSSL::PKey.read File.read 'private_key.pem'
654
631
  * key2.public? # => true
655
632
  * key2.private? # => true
656
633
  *
657
634
  * or
658
635
  *
659
- * key3 = OpenSSL::PKey::RSA.new File.read 'public_key.pem'
636
+ * key3 = OpenSSL::PKey.read File.read 'public_key.pem'
660
637
  * key3.public? # => true
661
638
  * key3.private? # => false
662
639
  *
663
640
  * === Loading an Encrypted Key
664
641
  *
665
- * OpenSSL will prompt you for your pass phrase when loading an encrypted key.
666
- * If you will not be able to type in the pass phrase you may provide it when
642
+ * OpenSSL will prompt you for your password when loading an encrypted key.
643
+ * If you will not be able to type in the password you may provide it when
667
644
  * loading the key:
668
645
  *
669
646
  * key4_pem = File.read 'private.secure.pem'
670
- * pass_phrase = 'my secure pass phrase goes here'
671
- * key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase
647
+ * password = 'my secure password goes here'
648
+ * key4 = OpenSSL::PKey.read key4_pem, password
672
649
  *
673
650
  * == RSA Encryption
674
651
  *
@@ -710,16 +687,14 @@ static void Init_ossl_locks(void)
710
687
  * To sign a document, a cryptographically secure hash of the document is
711
688
  * computed first, which is then signed using the private key.
712
689
  *
713
- * digest = OpenSSL::Digest::SHA256.new
714
- * signature = key.sign digest, document
690
+ * signature = key.sign 'SHA256', document
715
691
  *
716
692
  * To validate the signature, again a hash of the document is computed and
717
693
  * the signature is decrypted using the public key. The result is then
718
694
  * compared to the hash just computed, if they are equal the signature was
719
695
  * valid.
720
696
  *
721
- * digest = OpenSSL::Digest::SHA256.new
722
- * if key.verify digest, signature, document
697
+ * if key.verify 'SHA256', signature, document
723
698
  * puts 'Valid'
724
699
  * else
725
700
  * puts 'Invalid'
@@ -745,7 +720,7 @@ static void Init_ossl_locks(void)
745
720
  * using PBKDF2. PKCS #5 v2.0 recommends at least 8 bytes for the salt,
746
721
  * the number of iterations largely depends on the hardware being used.
747
722
  *
748
- * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
723
+ * cipher = OpenSSL::Cipher.new 'aes-256-cbc'
749
724
  * cipher.encrypt
750
725
  * iv = cipher.random_iv
751
726
  *
@@ -753,7 +728,7 @@ static void Init_ossl_locks(void)
753
728
  * salt = OpenSSL::Random.random_bytes 16
754
729
  * iter = 20000
755
730
  * key_len = cipher.key_len
756
- * digest = OpenSSL::Digest::SHA256.new
731
+ * digest = OpenSSL::Digest.new('SHA256')
757
732
  *
758
733
  * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
759
734
  * cipher.key = key
@@ -768,7 +743,7 @@ static void Init_ossl_locks(void)
768
743
  * Use the same steps as before to derive the symmetric AES key, this time
769
744
  * setting the Cipher up for decryption.
770
745
  *
771
- * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
746
+ * cipher = OpenSSL::Cipher.new 'aes-256-cbc'
772
747
  * cipher.decrypt
773
748
  * cipher.iv = iv # the one generated with #random_iv
774
749
  *
@@ -776,7 +751,7 @@ static void Init_ossl_locks(void)
776
751
  * salt = ... # the one generated above
777
752
  * iter = 20000
778
753
  * key_len = cipher.key_len
779
- * digest = OpenSSL::Digest::SHA256.new
754
+ * digest = OpenSSL::Digest.new('SHA256')
780
755
  *
781
756
  * key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
782
757
  * cipher.key = key
@@ -786,45 +761,6 @@ static void Init_ossl_locks(void)
786
761
  * decrypted = cipher.update encrypted
787
762
  * decrypted << cipher.final
788
763
  *
789
- * == PKCS #5 Password-based Encryption
790
- *
791
- * PKCS #5 is a password-based encryption standard documented at
792
- * RFC2898[http://www.ietf.org/rfc/rfc2898.txt]. It allows a short password or
793
- * passphrase to be used to create a secure encryption key. If possible, PBKDF2
794
- * as described above should be used if the circumstances allow it.
795
- *
796
- * PKCS #5 uses a Cipher, a pass phrase and a salt to generate an encryption
797
- * key.
798
- *
799
- * pass_phrase = 'my secure pass phrase goes here'
800
- * salt = '8 octets'
801
- *
802
- * === Encryption
803
- *
804
- * First set up the cipher for encryption
805
- *
806
- * encryptor = OpenSSL::Cipher.new 'AES-128-CBC'
807
- * encryptor.encrypt
808
- * encryptor.pkcs5_keyivgen pass_phrase, salt
809
- *
810
- * Then pass the data you want to encrypt through
811
- *
812
- * encrypted = encryptor.update 'top secret document'
813
- * encrypted << encryptor.final
814
- *
815
- * === Decryption
816
- *
817
- * Use a new Cipher instance set up for decryption
818
- *
819
- * decryptor = OpenSSL::Cipher.new 'AES-128-CBC'
820
- * decryptor.decrypt
821
- * decryptor.pkcs5_keyivgen pass_phrase, salt
822
- *
823
- * Then pass the data you want to decrypt through
824
- *
825
- * plain = decryptor.update encrypted
826
- * plain << decryptor.final
827
- *
828
764
  * == X509 Certificates
829
765
  *
830
766
  * === Creating a Certificate
@@ -833,7 +769,7 @@ static void Init_ossl_locks(void)
833
769
  * signature.
834
770
  *
835
771
  * key = OpenSSL::PKey::RSA.new 2048
836
- * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
772
+ * name = OpenSSL::X509::Name.parse '/CN=nobody/DC=example'
837
773
  *
838
774
  * cert = OpenSSL::X509::Certificate.new
839
775
  * cert.version = 2
@@ -872,7 +808,7 @@ static void Init_ossl_locks(void)
872
808
  * certificate.
873
809
  *
874
810
  * cert.issuer = name
875
- * cert.sign key, OpenSSL::Digest::SHA1.new
811
+ * cert.sign key, OpenSSL::Digest.new('SHA1')
876
812
  *
877
813
  * open 'certificate.pem', 'w' do |io| io.write cert.to_pem end
878
814
  *
@@ -902,12 +838,12 @@ static void Init_ossl_locks(void)
902
838
  * not readable by other users.
903
839
  *
904
840
  * ca_key = OpenSSL::PKey::RSA.new 2048
905
- * pass_phrase = 'my secure pass phrase goes here'
841
+ * password = 'my secure password goes here'
906
842
  *
907
- * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
843
+ * cipher = 'aes-256-cbc'
908
844
  *
909
845
  * open 'ca_key.pem', 'w', 0400 do |io|
910
- * io.write ca_key.export(cipher, pass_phrase)
846
+ * io.write ca_key.private_to_pem(cipher, password)
911
847
  * end
912
848
  *
913
849
  * === CA Certificate
@@ -915,7 +851,7 @@ static void Init_ossl_locks(void)
915
851
  * A CA certificate is created the same way we created a certificate above, but
916
852
  * with different extensions.
917
853
  *
918
- * ca_name = OpenSSL::X509::Name.parse 'CN=ca/DC=example'
854
+ * ca_name = OpenSSL::X509::Name.parse '/CN=ca/DC=example'
919
855
  *
920
856
  * ca_cert = OpenSSL::X509::Certificate.new
921
857
  * ca_cert.serial = 0
@@ -948,7 +884,7 @@ static void Init_ossl_locks(void)
948
884
  *
949
885
  * Root CA certificates are self-signed.
950
886
  *
951
- * ca_cert.sign ca_key, OpenSSL::Digest::SHA1.new
887
+ * ca_cert.sign ca_key, OpenSSL::Digest.new('SHA1')
952
888
  *
953
889
  * The CA certificate is saved to disk so it may be distributed to all the
954
890
  * users of the keys this CA will sign.
@@ -966,7 +902,7 @@ static void Init_ossl_locks(void)
966
902
  * csr.version = 0
967
903
  * csr.subject = name
968
904
  * csr.public_key = key.public_key
969
- * csr.sign key, OpenSSL::Digest::SHA1.new
905
+ * csr.sign key, OpenSSL::Digest.new('SHA1')
970
906
  *
971
907
  * A CSR is saved to disk and sent to the CA for signing.
972
908
  *
@@ -1010,7 +946,7 @@ static void Init_ossl_locks(void)
1010
946
  * csr_cert.add_extension \
1011
947
  * extension_factory.create_extension('subjectKeyIdentifier', 'hash')
1012
948
  *
1013
- * csr_cert.sign ca_key, OpenSSL::Digest::SHA1.new
949
+ * csr_cert.sign ca_key, OpenSSL::Digest.new('SHA1')
1014
950
  *
1015
951
  * open 'csr_cert.pem', 'w' do |io|
1016
952
  * io.write csr_cert.to_pem
@@ -1042,13 +978,13 @@ static void Init_ossl_locks(void)
1042
978
  * loop do
1043
979
  * ssl_connection = ssl_server.accept
1044
980
  *
1045
- * data = connection.gets
981
+ * data = ssl_connection.gets
1046
982
  *
1047
983
  * response = "I got #{data.dump}"
1048
984
  * puts response
1049
985
  *
1050
- * connection.puts "I got #{data.dump}"
1051
- * connection.close
986
+ * ssl_connection.puts "I got #{data.dump}"
987
+ * ssl_connection.close
1052
988
  * end
1053
989
  *
1054
990
  * === SSL client
@@ -1099,6 +1035,11 @@ static void Init_ossl_locks(void)
1099
1035
  void
1100
1036
  Init_openssl(void)
1101
1037
  {
1038
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
1039
+ rb_ext_ractor_safe(true);
1040
+ #endif
1041
+
1042
+ #undef rb_intern
1102
1043
  /*
1103
1044
  * Init timezone info
1104
1045
  */
@@ -1122,13 +1063,9 @@ Init_openssl(void)
1122
1063
  /*
1123
1064
  * Init main module
1124
1065
  */
1125
- mOSSL = rb_define_module("OpenSSL");
1126
1066
  rb_global_variable(&mOSSL);
1127
-
1128
- /*
1129
- * OpenSSL ruby extension version
1130
- */
1131
- rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION));
1067
+ mOSSL = rb_define_module("OpenSSL");
1068
+ rb_define_singleton_method(mOSSL, "fixed_length_secure_compare", ossl_crypto_fixed_length_secure_compare, 2);
1132
1069
 
1133
1070
  /*
1134
1071
  * Version of OpenSSL the ruby OpenSSL extension was built with
@@ -1146,15 +1083,35 @@ Init_openssl(void)
1146
1083
 
1147
1084
  /*
1148
1085
  * Version number of OpenSSL the ruby OpenSSL extension was built with
1149
- * (base 16)
1086
+ * (base 16). The formats are below.
1087
+ *
1088
+ * [OpenSSL 3] <tt>0xMNN00PP0 (major minor 00 patch 0)</tt>
1089
+ * [OpenSSL before 3] <tt>0xMNNFFPPS (major minor fix patch status)</tt>
1090
+ * [LibreSSL] <tt>0x20000000 (fixed value)</tt>
1091
+ *
1092
+ * See also the man page OPENSSL_VERSION_NUMBER(3).
1150
1093
  */
1151
1094
  rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER));
1152
1095
 
1096
+ #if defined(LIBRESSL_VERSION_NUMBER)
1097
+ /*
1098
+ * Version number of LibreSSL the ruby OpenSSL extension was built with
1099
+ * (base 16). The format is <tt>0xMNNFF00f (major minor fix 00
1100
+ * status)</tt>. This constant is only defined in LibreSSL cases.
1101
+ *
1102
+ * See also the man page LIBRESSL_VERSION_NUMBER(3).
1103
+ */
1104
+ rb_define_const(mOSSL, "LIBRESSL_VERSION_NUMBER", INT2NUM(LIBRESSL_VERSION_NUMBER));
1105
+ #endif
1106
+
1153
1107
  /*
1154
1108
  * Boolean indicating whether OpenSSL is FIPS-capable or not
1155
1109
  */
1156
1110
  rb_define_const(mOSSL, "OPENSSL_FIPS",
1157
- #ifdef OPENSSL_FIPS
1111
+ /* OpenSSL 3 is FIPS-capable even when it is installed without fips option */
1112
+ #if OSSL_OPENSSL_PREREQ(3, 0, 0)
1113
+ Qtrue
1114
+ #elif defined(OPENSSL_FIPS)
1158
1115
  Qtrue
1159
1116
  #else
1160
1117
  Qfalse
@@ -1164,12 +1121,12 @@ Init_openssl(void)
1164
1121
  rb_define_module_function(mOSSL, "fips_mode", ossl_fips_mode_get, 0);
1165
1122
  rb_define_module_function(mOSSL, "fips_mode=", ossl_fips_mode_set, 1);
1166
1123
 
1124
+ rb_global_variable(&eOSSLError);
1167
1125
  /*
1168
1126
  * Generic error,
1169
1127
  * common for all classes under OpenSSL module
1170
1128
  */
1171
1129
  eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError);
1172
- rb_global_variable(&eOSSLError);
1173
1130
 
1174
1131
  /*
1175
1132
  * Init debug core
@@ -1204,45 +1161,13 @@ Init_openssl(void)
1204
1161
  Init_ossl_pkey();
1205
1162
  Init_ossl_rand();
1206
1163
  Init_ossl_ssl();
1164
+ #ifndef OPENSSL_NO_TS
1165
+ Init_ossl_ts();
1166
+ #endif
1207
1167
  Init_ossl_x509();
1208
1168
  Init_ossl_ocsp();
1209
1169
  Init_ossl_engine();
1170
+ Init_ossl_provider();
1210
1171
  Init_ossl_asn1();
1211
1172
  Init_ossl_kdf();
1212
-
1213
- #if defined(OSSL_DEBUG)
1214
- /*
1215
- * For debugging Ruby/OpenSSL. Enable only when built with --enable-debug
1216
- */
1217
- #if !defined(LIBRESSL_VERSION_NUMBER) && \
1218
- (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG) || \
1219
- defined(CRYPTO_malloc_debug_init))
1220
- rb_define_module_function(mOSSL, "mem_check_start", mem_check_start, 0);
1221
- rb_define_module_function(mOSSL, "print_mem_leaks", print_mem_leaks, 0);
1222
-
1223
- #if defined(CRYPTO_malloc_debug_init) /* <= 1.0.2 */
1224
- CRYPTO_malloc_debug_init();
1225
- #endif
1226
-
1227
- #if defined(V_CRYPTO_MDEBUG_ALL) /* <= 1.0.2 */
1228
- CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
1229
- #endif
1230
-
1231
- #if OPENSSL_VERSION_NUMBER < 0x10100000 /* <= 1.0.2 */
1232
- {
1233
- int i;
1234
- /*
1235
- * See crypto/ex_data.c; call def_get_class() immediately to avoid
1236
- * allocations. 15 is the maximum number that is used as the class index
1237
- * in OpenSSL 1.0.2.
1238
- */
1239
- for (i = 0; i <= 15; i++) {
1240
- if (CRYPTO_get_ex_new_index(i, 0, (void *)"ossl-mdebug-dummy", 0, 0, 0) < 0)
1241
- rb_raise(rb_eRuntimeError, "CRYPTO_get_ex_new_index for "
1242
- "class index %d failed", i);
1243
- }
1244
- }
1245
- #endif
1246
- #endif
1247
- #endif
1248
1173
  }