From f5aee2480a4fb2aafa4e6e50eab6d9aef1976bc5 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 27 Jul 2025 14:58:53 +0900 Subject: [PATCH 01/10] [ruby/json] Functions defined in headers should be `static inline` If `load_uint8x16_4` has an external linkage, it is defined in both `generator` and `parser` extension libraries. This duplicate symbol causes a linker error when `--with-static-linked-ext` is given, on some platforms. https://github.com/ruby/json/commit/020693b17a --- ext/json/simd/simd.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/json/simd/simd.h b/ext/json/simd/simd.h index f8503d1395c271..e424bda9a8f035 100644 --- a/ext/json/simd/simd.h +++ b/ext/json/simd/simd.h @@ -103,7 +103,8 @@ static inline FORCE_INLINE int string_scan_simd_neon(const char **ptr, const cha return 0; } -uint8x16x4_t load_uint8x16_4(const unsigned char *table) { +static inline uint8x16x4_t load_uint8x16_4(const unsigned char *table) +{ uint8x16x4_t tab; tab.val[0] = vld1q_u8(table); tab.val[1] = vld1q_u8(table+16); From 0adecf500ac91125e989462d05f4ae137c72ffb2 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 27 Jul 2025 15:34:28 +0900 Subject: [PATCH 02/10] [ruby/json] Keep indentation consistent across functions [ci skip] https://github.com/ruby/json/commit/1988a3ae4c --- ext/json/simd/simd.h | 90 ++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/ext/json/simd/simd.h b/ext/json/simd/simd.h index e424bda9a8f035..3abbdb020958a8 100644 --- a/ext/json/simd/simd.h +++ b/ext/json/simd/simd.h @@ -7,45 +7,45 @@ typedef enum { #ifdef JSON_ENABLE_SIMD #ifdef __clang__ - #if __has_builtin(__builtin_ctzll) - #define HAVE_BUILTIN_CTZLL 1 - #else - #define HAVE_BUILTIN_CTZLL 0 - #endif +# if __has_builtin(__builtin_ctzll) +# define HAVE_BUILTIN_CTZLL 1 +# else +# define HAVE_BUILTIN_CTZLL 0 +# endif #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) - #define HAVE_BUILTIN_CTZLL 1 +# define HAVE_BUILTIN_CTZLL 1 #else - #define HAVE_BUILTIN_CTZLL 0 +# define HAVE_BUILTIN_CTZLL 0 #endif static inline uint32_t trailing_zeros64(uint64_t input) { #if HAVE_BUILTIN_CTZLL - return __builtin_ctzll(input); + return __builtin_ctzll(input); #else - uint32_t trailing_zeros = 0; - uint64_t temp = input; - while ((temp & 1) == 0 && temp > 0) { - trailing_zeros++; - temp >>= 1; - } - return trailing_zeros; + uint32_t trailing_zeros = 0; + uint64_t temp = input; + while ((temp & 1) == 0 && temp > 0) { + trailing_zeros++; + temp >>= 1; + } + return trailing_zeros; #endif } static inline int trailing_zeros(int input) { - #if HAVE_BUILTIN_CTZLL +#if HAVE_BUILTIN_CTZLL return __builtin_ctz(input); - #else +#else int trailing_zeros = 0; int temp = input; while ((temp & 1) == 0 && temp > 0) { - trailing_zeros++; - temp >>= 1; + trailing_zeros++; + temp >>= 1; } return trailing_zeros; - #endif +#endif } #if (defined(__GNUC__ ) || defined(__clang__)) @@ -79,38 +79,38 @@ static inline FORCE_INLINE uint64_t neon_match_mask(uint8x16_t matches) static inline FORCE_INLINE uint64_t compute_chunk_mask_neon(const char *ptr) { - uint8x16_t chunk = vld1q_u8((const unsigned char *)ptr); + uint8x16_t chunk = vld1q_u8((const unsigned char *)ptr); - // Trick: c < 32 || c == 34 can be factored as c ^ 2 < 33 - // https://lemire.me/blog/2025/04/13/detect-control-characters-quotes-and-backslashes-efficiently-using-swar/ - const uint8x16_t too_low_or_dbl_quote = vcltq_u8(veorq_u8(chunk, vdupq_n_u8(2)), vdupq_n_u8(33)); + // Trick: c < 32 || c == 34 can be factored as c ^ 2 < 33 + // https://lemire.me/blog/2025/04/13/detect-control-characters-quotes-and-backslashes-efficiently-using-swar/ + const uint8x16_t too_low_or_dbl_quote = vcltq_u8(veorq_u8(chunk, vdupq_n_u8(2)), vdupq_n_u8(33)); - uint8x16_t has_backslash = vceqq_u8(chunk, vdupq_n_u8('\\')); - uint8x16_t needs_escape = vorrq_u8(too_low_or_dbl_quote, has_backslash); - return neon_match_mask(needs_escape); + uint8x16_t has_backslash = vceqq_u8(chunk, vdupq_n_u8('\\')); + uint8x16_t needs_escape = vorrq_u8(too_low_or_dbl_quote, has_backslash); + return neon_match_mask(needs_escape); } static inline FORCE_INLINE int string_scan_simd_neon(const char **ptr, const char *end, uint64_t *mask) { while (*ptr + sizeof(uint8x16_t) <= end) { - uint64_t chunk_mask = compute_chunk_mask_neon(*ptr); - if (chunk_mask) { - *mask = chunk_mask; - return 1; - } - *ptr += sizeof(uint8x16_t); + uint64_t chunk_mask = compute_chunk_mask_neon(*ptr); + if (chunk_mask) { + *mask = chunk_mask; + return 1; + } + *ptr += sizeof(uint8x16_t); } return 0; } static inline uint8x16x4_t load_uint8x16_4(const unsigned char *table) { - uint8x16x4_t tab; - tab.val[0] = vld1q_u8(table); - tab.val[1] = vld1q_u8(table+16); - tab.val[2] = vld1q_u8(table+32); - tab.val[3] = vld1q_u8(table+48); - return tab; + uint8x16x4_t tab; + tab.val[0] = vld1q_u8(table); + tab.val[1] = vld1q_u8(table+16); + tab.val[2] = vld1q_u8(table+32); + tab.val[3] = vld1q_u8(table+48); + return tab; } #endif /* ARM Neon Support.*/ @@ -151,12 +151,12 @@ static inline TARGET_SSE2 FORCE_INLINE int compute_chunk_mask_sse2(const char *p static inline TARGET_SSE2 FORCE_INLINE int string_scan_simd_sse2(const char **ptr, const char *end, int *mask) { while (*ptr + sizeof(__m128i) <= end) { - int chunk_mask = compute_chunk_mask_sse2(*ptr); - if (chunk_mask) { - *mask = chunk_mask; - return 1; - } - *ptr += sizeof(__m128i); + int chunk_mask = compute_chunk_mask_sse2(*ptr); + if (chunk_mask) { + *mask = chunk_mask; + return 1; + } + *ptr += sizeof(__m128i); } return 0; From 6e0181db3ac98e8415c0b130c90ae1bbc5089ee8 Mon Sep 17 00:00:00 2001 From: Jun Aruga Date: Mon, 21 Jul 2025 22:04:55 +0200 Subject: [PATCH 03/10] [ruby/openssl] ssl: add post-quantum cryptography (PQC) tests The key files were created by the following commands. ``` $ ${HOME}/.local/openssl-3.6.0-dev-fips-debug-8253b58d60/bin/openssl genpkey \ -algorithm mldsa65 \ -out mldsa65-1.pem $ ${HOME}/.local/openssl-3.6.0-dev-fips-debug-8253b58d60/bin/openssl genpkey \ -algorithm mldsa65 \ -out mldsa65-2.pem ``` PQC algorithms, ML-KEM (FIPS 203) and ML-DSA (FIPS 204) used in the PQC tests are supported on OpenSSL 3.5 or later. https://openssl-library.org/post/2025-04-08-openssl-35-final-release/ https://github.com/ruby/openssl/commit/f3bb316018 --- test/openssl/fixtures/pkey/mldsa65-1.pem | 88 ++++++++++++++++++++++++ test/openssl/fixtures/pkey/mldsa65-2.pem | 88 ++++++++++++++++++++++++ test/openssl/test_ssl.rb | 74 ++++++++++++++++++++ test/openssl/utils.rb | 10 +-- 4 files changed, 255 insertions(+), 5 deletions(-) create mode 100644 test/openssl/fixtures/pkey/mldsa65-1.pem create mode 100644 test/openssl/fixtures/pkey/mldsa65-2.pem diff --git a/test/openssl/fixtures/pkey/mldsa65-1.pem b/test/openssl/fixtures/pkey/mldsa65-1.pem new file mode 100644 index 00000000000000..21f08e3ac607c1 --- /dev/null +++ b/test/openssl/fixtures/pkey/mldsa65-1.pem @@ -0,0 +1,88 @@ +-----BEGIN PRIVATE KEY----- +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 +qclQDtLzvC0mHUNlhcds4I20 +-----END PRIVATE KEY----- diff --git a/test/openssl/fixtures/pkey/mldsa65-2.pem b/test/openssl/fixtures/pkey/mldsa65-2.pem new file mode 100644 index 00000000000000..0ae64c2c5d2446 --- /dev/null +++ b/test/openssl/fixtures/pkey/mldsa65-2.pem @@ -0,0 +1,88 @@ +-----BEGIN PRIVATE KEY----- +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 +qX4cmZjkE9fKw15cRjvQt1K1 +-----END PRIVATE KEY----- diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index 05f29507650749..fc19f4d9459d86 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -2062,6 +2062,57 @@ def test_get_sigalg end end + def test_pqc_sigalg + # PQC algorithm ML-DSA (FIPS 204) is supported on OpenSSL 3.5 or later. + return unless openssl?(3, 5, 0) + + mldsa = Fixtures.pkey("mldsa65-1") + mldsa_ca_key = Fixtures.pkey("mldsa65-2") + mldsa_ca_cert = issue_cert(@ca, mldsa_ca_key, 1, @ca_exts, nil, nil, + digest: nil) + mldsa_cert = issue_cert(@svr, mldsa, 60, [], mldsa_ca_cert, mldsa_ca_key, + digest: nil) + rsa = Fixtures.pkey("rsa2048") + rsa_cert = issue_cert(@svr, rsa, 61, [], @ca_cert, @ca_key) + ctx_proc = -> ctx { + # Unset values set by start_server + ctx.cert = ctx.key = ctx.extra_chain_cert = nil + ctx.add_certificate(mldsa_cert, mldsa) + ctx.add_certificate(rsa_cert, rsa) + } + + server_proc = -> (ctx, ssl) { + assert_equal('mldsa65', ssl.sigalg) + + readwrite_loop(ctx, ssl) + } + start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |port| + ctx = OpenSSL::SSL::SSLContext.new + # Set signature algorithm because while OpenSSL may use ML-DSA by + # default, the system OpenSSL configuration affects the used signature + # algorithm. + ctx.sigalgs = 'mldsa65' + server_connect(port, ctx) { |ssl| + assert_equal('mldsa65', ssl.peer_sigalg) + ssl.puts "abc"; ssl.gets + } + end + + server_proc = -> (ctx, ssl) { + assert_equal('rsa_pss_rsae_sha256', ssl.sigalg) + + readwrite_loop(ctx, ssl) + } + start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.sigalgs = 'rsa_pss_rsae_sha256' + server_connect(port, ctx) { |ssl| + assert_equal('rsa_pss_rsae_sha256', ssl.peer_sigalg) + ssl.puts "abc"; ssl.gets + } + end + end + def test_connect_works_when_setting_dh_callback_to_nil omit "AWS-LC does not support DHE ciphersuites" if aws_lc? @@ -2158,6 +2209,29 @@ def test_set_groups_tls13 end end + def test_pqc_group + # PQC algorithm ML-KEM (FIPS 203) is supported on OpenSSL 3.5 or later. + return unless openssl?(3, 5, 0) + + [ + 'X25519MLKEM768', + 'SecP256r1MLKEM768', + 'SecP384r1MLKEM1024' + ].each do |group| + ctx_proc = -> ctx { + ctx.groups = group + } + start_server(ctx_proc: ctx_proc) do |port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.groups = group + server_connect(port, ctx) { |ssl| + assert_equal(group, ssl.group) + ssl.puts "abc"; ssl.gets + } + end + end + end + def test_security_level ctx = OpenSSL::SSL::SSLContext.new ctx.security_level = 1 diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb index ff789ff284e589..8d6261253159aa 100644 --- a/test/openssl/utils.rb +++ b/test/openssl/utils.rb @@ -177,16 +177,16 @@ def setup @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") - ca_exts = [ + @ca_exts = [ ["basicConstraints","CA:TRUE",true], ["keyUsage","cRLSign,keyCertSign",true], ] - ee_exts = [ + @ee_exts = [ ["keyUsage","keyEncipherment,digitalSignature",true], ] - @ca_cert = issue_cert(@ca, @ca_key, 1, ca_exts, nil, nil) - @svr_cert = issue_cert(@svr, @svr_key, 2, ee_exts, @ca_cert, @ca_key) - @cli_cert = issue_cert(@cli, @cli_key, 3, ee_exts, @ca_cert, @ca_key) + @ca_cert = issue_cert(@ca, @ca_key, 1, @ca_exts, nil, nil) + @svr_cert = issue_cert(@svr, @svr_key, 2, @ee_exts, @ca_cert, @ca_key) + @cli_cert = issue_cert(@cli, @cli_key, 3, @ee_exts, @ca_cert, @ca_key) @server = nil end From 64e8368f5b83a570086793047fa01bc5862b5b63 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sun, 6 Jul 2025 02:25:26 +0900 Subject: [PATCH 04/10] [ruby/openssl] lib/openssl.rb: require files in alphabetical order This list was originally in alphabetical order. Sort it again. This change should be safe since the .rb sources should only depend on the extension and not each other. https://github.com/ruby/openssl/commit/eb3998728a --- ext/openssl/lib/openssl.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/openssl/lib/openssl.rb b/ext/openssl/lib/openssl.rb index 08899238903fbb..48f88dcbba9a6c 100644 --- a/ext/openssl/lib/openssl.rb +++ b/ext/openssl/lib/openssl.rb @@ -12,16 +12,16 @@ require 'openssl.so' -require_relative 'openssl/bn' require_relative 'openssl/asn1' -require_relative 'openssl/pkey' +require_relative 'openssl/bn' require_relative 'openssl/cipher' require_relative 'openssl/digest' require_relative 'openssl/hmac' -require_relative 'openssl/x509' -require_relative 'openssl/ssl' require_relative 'openssl/pkcs5' +require_relative 'openssl/pkey' +require_relative 'openssl/ssl' require_relative 'openssl/version' +require_relative 'openssl/x509' module OpenSSL # call-seq: From ba0b3ad4f338a43f1d59e89d9c1c6d785644b682 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Tue, 21 May 2024 17:22:47 +0900 Subject: [PATCH 05/10] [ruby/openssl] bn: avoid ossl_bn_new(NULL) Currently, calling ossl_bn_new() with a NULL argument allocates a new OpenSSL::BN instance representing 0. This behavior is confusing. Raise an exception if this is attempted, instead. https://github.com/ruby/openssl/commit/6fa793d997 --- ext/openssl/ossl_bn.c | 7 +++---- ext/openssl/ossl_pkey_ec.c | 10 ++++------ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c index 8699ce8ec5665b..a6fa2c1daba3e9 100644 --- a/ext/openssl/ossl_bn.c +++ b/ext/openssl/ossl_bn.c @@ -61,10 +61,9 @@ ossl_bn_new(const BIGNUM *bn) VALUE obj; obj = NewBN(cBN); - newbn = bn ? BN_dup(bn) : BN_new(); - if (!newbn) { - ossl_raise(eBNError, NULL); - } + newbn = BN_dup(bn); + if (!newbn) + ossl_raise(eBNError, "BN_dup"); SetBN(obj, newbn); return obj; diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index 45e8bf19b246e7..1d20f63e0c4648 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -805,11 +805,10 @@ static VALUE ossl_ec_group_get_order(VALUE self) { VALUE bn_obj; BIGNUM *bn; - EC_GROUP *group = NULL; + EC_GROUP *group; GetECGroup(self, group); - - bn_obj = ossl_bn_new(NULL); + bn_obj = ossl_bn_new(BN_value_one()); bn = GetBNPtr(bn_obj); if (EC_GROUP_get_order(group, bn, ossl_bn_ctx) != 1) @@ -830,11 +829,10 @@ static VALUE ossl_ec_group_get_cofactor(VALUE self) { VALUE bn_obj; BIGNUM *bn; - EC_GROUP *group = NULL; + EC_GROUP *group; GetECGroup(self, group); - - bn_obj = ossl_bn_new(NULL); + bn_obj = ossl_bn_new(BN_value_one()); bn = GetBNPtr(bn_obj); if (EC_GROUP_get_cofactor(group, bn, ossl_bn_ctx) != 1) From 4e8bbb07dd4936b97a6b39d54a6977a107518e1f Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Tue, 21 May 2024 23:36:12 +0900 Subject: [PATCH 06/10] [ruby/openssl] x509: disallow ossl_x509{,attr,crl,ext,revoked,name}*_new(NULL) These functions are not actually called with NULL. It also doesn't make sense to do so, so let's simplify the definitions. https://github.com/ruby/openssl/commit/ef277083ba --- ext/openssl/ossl_x509attr.c | 11 +++-------- ext/openssl/ossl_x509cert.c | 11 +++-------- ext/openssl/ossl_x509crl.c | 5 +++-- ext/openssl/ossl_x509ext.c | 11 +++-------- ext/openssl/ossl_x509name.c | 11 +++-------- ext/openssl/ossl_x509revoked.c | 11 +++-------- 6 files changed, 18 insertions(+), 42 deletions(-) diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c index 3f6b89bdde5af3..d983af59686946 100644 --- a/ext/openssl/ossl_x509attr.c +++ b/ext/openssl/ossl_x509attr.c @@ -54,14 +54,9 @@ ossl_x509attr_new(X509_ATTRIBUTE *attr) VALUE obj; obj = NewX509Attr(cX509Attr); - if (!attr) { - new = X509_ATTRIBUTE_new(); - } else { - new = X509_ATTRIBUTE_dup(attr); - } - if (!new) { - ossl_raise(eX509AttrError, NULL); - } + new = X509_ATTRIBUTE_dup(attr); + if (!new) + ossl_raise(eX509AttrError, "X509_ATTRIBUTE_dup"); SetX509Attr(obj, new); return obj; diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c index 4734602bef187c..bdde5e414bb564 100644 --- a/ext/openssl/ossl_x509cert.c +++ b/ext/openssl/ossl_x509cert.c @@ -54,14 +54,9 @@ ossl_x509_new(X509 *x509) VALUE obj; obj = NewX509(cX509Cert); - if (!x509) { - new = X509_new(); - } else { - new = X509_dup(x509); - } - if (!new) { - ossl_raise(eX509CertError, NULL); - } + new = X509_dup(x509); + if (!new) + ossl_raise(eX509CertError, "X509_dup"); SetX509(obj, new); return obj; diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c index 135dfe3d758d18..52174d1711487b 100644 --- a/ext/openssl/ossl_x509crl.c +++ b/ext/openssl/ossl_x509crl.c @@ -64,8 +64,9 @@ ossl_x509crl_new(X509_CRL *crl) VALUE obj; obj = NewX509CRL(cX509CRL); - tmp = crl ? X509_CRL_dup(crl) : X509_CRL_new(); - if(!tmp) ossl_raise(eX509CRLError, NULL); + tmp = X509_CRL_dup(crl); + if (!tmp) + ossl_raise(eX509CRLError, "X509_CRL_dup"); SetX509CRL(obj, tmp); return obj; diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c index 9b0d9aa651977d..01aa3a8f51cd17 100644 --- a/ext/openssl/ossl_x509ext.c +++ b/ext/openssl/ossl_x509ext.c @@ -68,14 +68,9 @@ ossl_x509ext_new(X509_EXTENSION *ext) VALUE obj; obj = NewX509Ext(cX509Ext); - if (!ext) { - new = X509_EXTENSION_new(); - } else { - new = X509_EXTENSION_dup(ext); - } - if (!new) { - ossl_raise(eX509ExtError, NULL); - } + new = X509_EXTENSION_dup(ext); + if (!new) + ossl_raise(eX509ExtError, "X509_EXTENSION_dup"); SetX509Ext(obj, new); return obj; diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c index b3791aefa38826..7d0fd35247f5cb 100644 --- a/ext/openssl/ossl_x509name.c +++ b/ext/openssl/ossl_x509name.c @@ -59,14 +59,9 @@ ossl_x509name_new(X509_NAME *name) VALUE obj; obj = NewX509Name(cX509Name); - if (!name) { - new = X509_NAME_new(); - } else { - new = X509_NAME_dup(name); - } - if (!new) { - ossl_raise(eX509NameError, NULL); - } + new = X509_NAME_dup(name); + if (!new) + ossl_raise(eX509NameError, "X509_NAME_dup"); SetX509Name(obj, new); return obj; diff --git a/ext/openssl/ossl_x509revoked.c b/ext/openssl/ossl_x509revoked.c index 1eff5dd3556d57..9496c4bf1b49fc 100644 --- a/ext/openssl/ossl_x509revoked.c +++ b/ext/openssl/ossl_x509revoked.c @@ -54,14 +54,9 @@ ossl_x509revoked_new(X509_REVOKED *rev) VALUE obj; obj = NewX509Rev(cX509Rev); - if (!rev) { - new = X509_REVOKED_new(); - } else { - new = X509_REVOKED_dup(rev); - } - if (!new) { - ossl_raise(eX509RevError, NULL); - } + new = X509_REVOKED_dup(rev); + if (!new) + ossl_raise(eX509RevError, "X509_REVOKED_dup"); SetX509Rev(obj, new); return obj; From e80c3f3ba933e9dae6c44350ddc99cab485a9a59 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 6 May 2024 03:02:03 +0900 Subject: [PATCH 07/10] [ruby/openssl] pkcs7: disallow ossl_pkcs7{si,ri}_new(NULL) These functions are not actually called with NULL. https://github.com/ruby/openssl/commit/c089301e56 --- ext/openssl/ossl_pkcs7.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c index 4d719c96da141c..944cbb5e97f5d8 100644 --- a/ext/openssl/ossl_pkcs7.c +++ b/ext/openssl/ossl_pkcs7.c @@ -153,13 +153,14 @@ ossl_PKCS7_RECIP_INFO_dup(PKCS7_RECIP_INFO *si) static VALUE ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si) { - PKCS7_SIGNER_INFO *pkcs7; + PKCS7_SIGNER_INFO *p7si_new; VALUE obj; obj = NewPKCS7si(cPKCS7Signer); - pkcs7 = p7si ? ossl_PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new(); - if (!pkcs7) ossl_raise(ePKCS7Error, NULL); - SetPKCS7si(obj, pkcs7); + p7si_new = ossl_PKCS7_SIGNER_INFO_dup(p7si); + if (!p7si_new) + ossl_raise(ePKCS7Error, "ASN1_dup"); + SetPKCS7si(obj, p7si_new); return obj; } @@ -167,13 +168,14 @@ ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si) static VALUE ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri) { - PKCS7_RECIP_INFO *pkcs7; + PKCS7_RECIP_INFO *p7ri_new; VALUE obj; obj = NewPKCS7ri(cPKCS7Recipient); - pkcs7 = p7ri ? ossl_PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new(); - if (!pkcs7) ossl_raise(ePKCS7Error, NULL); - SetPKCS7ri(obj, pkcs7); + p7ri_new = ossl_PKCS7_RECIP_INFO_dup(p7ri); + if (!p7ri_new) + ossl_raise(ePKCS7Error,"ASN1_dup"); + SetPKCS7ri(obj, p7ri_new); return obj; } From 5a04353417f6ded7ea73ade4e979101c1a314f82 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Wed, 22 May 2024 00:02:07 +0900 Subject: [PATCH 08/10] [ruby/openssl] ocsp: refactor ossl_ocspsres_new() Similar to most of the other ossl_*_new() functions, let it take a const pointer and make a copy of the object. This also fixes a potential memory leak when the wrapper object allocation fails. https://github.com/ruby/openssl/commit/eaabf6d8a3 --- ext/openssl/ossl_ocsp.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c index cb2f1a62d0aa69..002395a3a016ea 100644 --- a/ext/openssl/ossl_ocsp.c +++ b/ext/openssl/ossl_ocsp.c @@ -940,7 +940,7 @@ ossl_ocspbres_get_status(VALUE self) return ret; } -static VALUE ossl_ocspsres_new(OCSP_SINGLERESP *); +static VALUE ossl_ocspsres_new(const OCSP_SINGLERESP *); /* * call-seq: @@ -958,17 +958,10 @@ ossl_ocspbres_get_responses(VALUE self) GetOCSPBasicRes(self, bs); count = OCSP_resp_count(bs); - ret = rb_ary_new2(count); + ret = rb_ary_new_capa(count); for (i = 0; i < count; i++) { - OCSP_SINGLERESP *sres, *sres_new; - - sres = OCSP_resp_get0(bs, i); - sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), sres); - if (!sres_new) - ossl_raise(eOCSPError, "ASN1_item_dup"); - - rb_ary_push(ret, ossl_ocspsres_new(sres_new)); + rb_ary_push(ret, ossl_ocspsres_new(OCSP_resp_get0(bs, i))); } return ret; @@ -986,7 +979,6 @@ static VALUE ossl_ocspbres_find_response(VALUE self, VALUE target) { OCSP_BASICRESP *bs; - OCSP_SINGLERESP *sres, *sres_new; OCSP_CERTID *id; int n; @@ -995,13 +987,7 @@ ossl_ocspbres_find_response(VALUE self, VALUE target) if ((n = OCSP_resp_find(bs, id, -1)) == -1) return Qnil; - - sres = OCSP_resp_get0(bs, n); - sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), sres); - if (!sres_new) - ossl_raise(eOCSPError, "ASN1_item_dup"); - - return ossl_ocspsres_new(sres_new); + return ossl_ocspsres_new(OCSP_resp_get0(bs, n)); } /* @@ -1110,12 +1096,18 @@ ossl_ocspbres_to_der(VALUE self) * OCSP::SingleResponse */ static VALUE -ossl_ocspsres_new(OCSP_SINGLERESP *sres) +ossl_ocspsres_new(const OCSP_SINGLERESP *sres) { VALUE obj; + OCSP_SINGLERESP *sres_new; obj = NewOCSPSingleRes(cOCSPSingleRes); - SetOCSPSingleRes(obj, sres); + /* OpenSSL 1.1.1 takes a non-const pointer */ + sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), + (OCSP_SINGLERESP *)sres); + if (!sres_new) + ossl_raise(eOCSPError, "ASN1_item_dup"); + SetOCSPSingleRes(obj, sres_new); return obj; } From f85dafebe8fc95817b224a602b3de840c744ac8b Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 6 May 2024 01:29:03 +0900 Subject: [PATCH 09/10] [ruby/openssl] ocsp: refactor ossl_ocspcertid_new() Likewise, let it take a const pointer and not the ownership of the OpenSSL object. This fixes potential memory leak in OpenSSL::OCSP::BasicResponse#status. https://github.com/ruby/openssl/commit/7e0288ebbd --- ext/openssl/ossl_ocsp.c | 97 +++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c index 002395a3a016ea..5a3a71cae0d83e 100644 --- a/ext/openssl/ossl_ocsp.c +++ b/ext/openssl/ossl_ocsp.c @@ -149,10 +149,14 @@ static const rb_data_type_t ossl_ocsp_certid_type = { * Public */ static VALUE -ossl_ocspcertid_new(OCSP_CERTID *cid) +ossl_ocspcid_new(const OCSP_CERTID *cid) { VALUE obj = NewOCSPCertId(cOCSPCertId); - SetOCSPCertId(obj, cid); + /* OpenSSL 1.1.1 takes a non-const pointer */ + OCSP_CERTID *cid_new = OCSP_CERTID_dup((OCSP_CERTID *)cid); + if (!cid_new) + ossl_raise(eOCSPError, "OCSP_CERTID_dup"); + SetOCSPCertId(obj, cid_new); return obj; } @@ -328,21 +332,19 @@ static VALUE ossl_ocspreq_get_certid(VALUE self) { OCSP_REQUEST *req; - OCSP_ONEREQ *one; - OCSP_CERTID *id; - VALUE ary, tmp; - int i, count; GetOCSPReq(self, req); - count = OCSP_request_onereq_count(req); - ary = (count > 0) ? rb_ary_new() : Qnil; - for(i = 0; i < count; i++){ - one = OCSP_request_onereq_get0(req, i); - tmp = NewOCSPCertId(cOCSPCertId); - if(!(id = OCSP_CERTID_dup(OCSP_onereq_get0_id(one)))) - ossl_raise(eOCSPError, NULL); - SetOCSPCertId(tmp, id); - rb_ary_push(ary, tmp); + int count = OCSP_request_onereq_count(req); + if (count < 0) + ossl_raise(eOCSPError, "OCSP_request_onereq_count"); + if (count == 0) + return Qnil; + + VALUE ary = rb_ary_new_capa(count); + for (int i = 0; i < count; i++) { + OCSP_ONEREQ *one = OCSP_request_onereq_get0(req, i); + OCSP_CERTID *cid = OCSP_onereq_get0_id(one); + rb_ary_push(ary, ossl_ocspcid_new(cid)); } return ary; @@ -899,42 +901,34 @@ static VALUE ossl_ocspbres_get_status(VALUE self) { OCSP_BASICRESP *bs; - OCSP_SINGLERESP *single; - OCSP_CERTID *cid; - ASN1_TIME *revtime, *thisupd, *nextupd; - int status, reason; - X509_EXTENSION *x509ext; - VALUE ret, ary, ext; - int count, ext_count, i, j; GetOCSPBasicRes(self, bs); - ret = rb_ary_new(); - count = OCSP_resp_count(bs); - for(i = 0; i < count; i++){ - single = OCSP_resp_get0(bs, i); - if(!single) continue; - - revtime = thisupd = nextupd = NULL; - status = OCSP_single_get0_status(single, &reason, &revtime, - &thisupd, &nextupd); - if(status < 0) continue; - if(!(cid = OCSP_CERTID_dup((OCSP_CERTID *)OCSP_SINGLERESP_get0_id(single)))) /* FIXME */ - ossl_raise(eOCSPError, NULL); - ary = rb_ary_new(); - rb_ary_push(ary, ossl_ocspcertid_new(cid)); - rb_ary_push(ary, INT2NUM(status)); - rb_ary_push(ary, INT2NUM(reason)); - rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil); - rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil); - rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil); - ext = rb_ary_new(); - ext_count = OCSP_SINGLERESP_get_ext_count(single); - for(j = 0; j < ext_count; j++){ - x509ext = OCSP_SINGLERESP_get_ext(single, j); - rb_ary_push(ext, ossl_x509ext_new(x509ext)); - } - rb_ary_push(ary, ext); - rb_ary_push(ret, ary); + VALUE ret = rb_ary_new(); + int count = OCSP_resp_count(bs); + for (int i = 0; i < count; i++) { + OCSP_SINGLERESP *single = OCSP_resp_get0(bs, i); + ASN1_TIME *revtime, *thisupd, *nextupd; + int reason; + + int status = OCSP_single_get0_status(single, &reason, &revtime, &thisupd, &nextupd); + if (status < 0) + ossl_raise(eOCSPError, "OCSP_single_get0_status"); + + VALUE ary = rb_ary_new(); + rb_ary_push(ary, ossl_ocspcid_new(OCSP_SINGLERESP_get0_id(single))); + rb_ary_push(ary, INT2NUM(status)); + rb_ary_push(ary, INT2NUM(reason)); + rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil); + rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil); + rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil); + VALUE ext = rb_ary_new(); + int ext_count = OCSP_SINGLERESP_get_ext_count(single); + for (int j = 0; j < ext_count; j++) { + X509_EXTENSION *x509ext = OCSP_SINGLERESP_get_ext(single, j); + rb_ary_push(ext, ossl_x509ext_new(x509ext)); + } + rb_ary_push(ary, ext); + rb_ary_push(ret, ary); } return ret; @@ -1225,12 +1219,9 @@ static VALUE ossl_ocspsres_get_certid(VALUE self) { OCSP_SINGLERESP *sres; - OCSP_CERTID *id; GetOCSPSingleRes(self, sres); - id = OCSP_CERTID_dup((OCSP_CERTID *)OCSP_SINGLERESP_get0_id(sres)); /* FIXME */ - - return ossl_ocspcertid_new(id); + return ossl_ocspcid_new(OCSP_SINGLERESP_get0_id(sres)); } /* From 1c18ab81dbf4a8006222d7f10752dde362ba05a6 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 21 Jul 2025 23:52:03 +0900 Subject: [PATCH 10/10] [ruby/openssl] pkey: rename ossl_pkey_new() to ossl_pkey_wrap() Among functions named ossl_*_new(), ossl_pkey_new() is now the only one that takes ownership of the passed OpenSSL object instead of making a copy or incrementing its reference counter. Rename it to make this behavior easier to understand. https://github.com/ruby/openssl/commit/54c1c26eb5 --- ext/openssl/ossl_engine.c | 4 ++-- ext/openssl/ossl_ns_spki.c | 2 +- ext/openssl/ossl_pkcs12.c | 6 +++--- ext/openssl/ossl_pkey.c | 14 +++++++------- ext/openssl/ossl_pkey.h | 2 +- ext/openssl/ossl_ssl.c | 2 +- ext/openssl/ossl_x509cert.c | 2 +- ext/openssl/ossl_x509req.c | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c index cb08049a8214b7..1565068743802e 100644 --- a/ext/openssl/ossl_engine.c +++ b/ext/openssl/ossl_engine.c @@ -320,7 +320,7 @@ ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self) GetEngine(self, e); pkey = ENGINE_load_private_key(e, sid, NULL, sdata); if (!pkey) ossl_raise(eEngineError, NULL); - obj = ossl_pkey_new(pkey); + obj = ossl_pkey_wrap(pkey); OSSL_PKEY_SET_PRIVATE(obj); return obj; @@ -350,7 +350,7 @@ ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self) pkey = ENGINE_load_public_key(e, sid, NULL, sdata); if (!pkey) ossl_raise(eEngineError, NULL); - return ossl_pkey_new(pkey); + return ossl_pkey_wrap(pkey); } /* diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c index 445aeeba152fa4..ffed3a64a602f6 100644 --- a/ext/openssl/ossl_ns_spki.c +++ b/ext/openssl/ossl_ns_spki.c @@ -190,7 +190,7 @@ ossl_spki_get_public_key(VALUE self) ossl_raise(eSPKIError, NULL); } - return ossl_pkey_new(pkey); /* NO DUP - OK */ + return ossl_pkey_wrap(pkey); } /* diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c index be09eb2071c125..0b7469e673f77c 100644 --- a/ext/openssl/ossl_pkcs12.c +++ b/ext/openssl/ossl_pkcs12.c @@ -161,9 +161,9 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self) } static VALUE -ossl_pkey_new_i(VALUE arg) +ossl_pkey_wrap_i(VALUE arg) { - return ossl_pkey_new((EVP_PKEY *)arg); + return ossl_pkey_wrap((EVP_PKEY *)arg); } static VALUE @@ -211,7 +211,7 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self) if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s)) ossl_raise(ePKCS12Error, "PKCS12_parse"); if (key) { - pkey = rb_protect(ossl_pkey_new_i, (VALUE)key, &st); + pkey = rb_protect(ossl_pkey_wrap_i, (VALUE)key, &st); if (st) goto err; } if (x509) { diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index b00a3648d141c6..e88074ddf2582c 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -39,7 +39,7 @@ const rb_data_type_t ossl_evp_pkey_type = { }; static VALUE -pkey_new0(VALUE arg) +pkey_wrap0(VALUE arg) { EVP_PKEY *pkey = (EVP_PKEY *)arg; VALUE klass, obj; @@ -65,12 +65,12 @@ pkey_new0(VALUE arg) } VALUE -ossl_pkey_new(EVP_PKEY *pkey) +ossl_pkey_wrap(EVP_PKEY *pkey) { VALUE obj; int status; - obj = rb_protect(pkey_new0, (VALUE)pkey, &status); + obj = rb_protect(pkey_wrap0, (VALUE)pkey, &status); if (status) { EVP_PKEY_free(pkey); rb_jump_tag(status); @@ -239,7 +239,7 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self) BIO_free(bio); if (!pkey) ossl_raise(ePKeyError, "Could not parse PKey"); - return ossl_pkey_new(pkey); + return ossl_pkey_wrap(pkey); } static VALUE @@ -443,7 +443,7 @@ pkey_generate(int argc, VALUE *argv, VALUE self, int genparam) } } - return ossl_pkey_new(gen_arg.pkey); + return ossl_pkey_wrap(gen_arg.pkey); } /* @@ -687,7 +687,7 @@ ossl_pkey_new_raw_private_key(VALUE self, VALUE type, VALUE key) ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key"); #endif - return ossl_pkey_new(pkey); + return ossl_pkey_wrap(pkey); } /* @@ -719,7 +719,7 @@ ossl_pkey_new_raw_public_key(VALUE self, VALUE type, VALUE key) ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key"); #endif - return ossl_pkey_new(pkey); + return ossl_pkey_wrap(pkey); } /* diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h index fdc5e94aed0e8c..6778381210e882 100644 --- a/ext/openssl/ossl_pkey.h +++ b/ext/openssl/ossl_pkey.h @@ -27,7 +27,7 @@ extern const rb_data_type_t ossl_evp_pkey_type; } while (0) /* Takes ownership of the EVP_PKEY */ -VALUE ossl_pkey_new(EVP_PKEY *); +VALUE ossl_pkey_wrap(EVP_PKEY *); void ossl_pkey_check_public_key(const EVP_PKEY *); EVP_PKEY *ossl_pkey_read_generic(BIO *, VALUE); EVP_PKEY *GetPKeyPtr(VALUE); diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index f3da26517ff4a7..29564a8139ac2e 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -2642,7 +2642,7 @@ ossl_ssl_tmp_key(VALUE self) GetSSL(self, ssl); if (!SSL_get_server_tmp_key(ssl, &key)) return Qnil; - return ossl_pkey_new(key); + return ossl_pkey_wrap(key); } #ifdef HAVE_SSL_GET0_PEER_SIGNATURE_NAME diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c index bdde5e414bb564..30e3c617531bde 100644 --- a/ext/openssl/ossl_x509cert.c +++ b/ext/openssl/ossl_x509cert.c @@ -504,7 +504,7 @@ ossl_x509_get_public_key(VALUE self) ossl_raise(eX509CertError, NULL); } - return ossl_pkey_new(pkey); /* NO DUP - OK */ + return ossl_pkey_wrap(pkey); } /* diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c index add1f8d077e888..b4c29f877e8536 100644 --- a/ext/openssl/ossl_x509req.c +++ b/ext/openssl/ossl_x509req.c @@ -289,7 +289,7 @@ ossl_x509req_get_public_key(VALUE self) ossl_raise(eX509ReqError, NULL); } - return ossl_pkey_new(pkey); /* NO DUP - OK */ + return ossl_pkey_wrap(pkey); } static VALUE