diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb index 2a883fe..4da13c7 100644 --- a/lib/drb/drb.rb +++ b/lib/drb/drb.rb @@ -463,6 +463,9 @@ def initialize(error) attr_reader :reason end + # Error raised when an error occurs on the bad configuration. + class DRbBadConfig < DRbError; end + # Class wrapping a marshalled object whose type is unknown locally. # # If an object is returned by a method invoked over drb, but the diff --git a/lib/drb/ssl.rb b/lib/drb/ssl.rb index 096f355..a856866 100644 --- a/lib/drb/ssl.rb +++ b/lib/drb/ssl.rb @@ -25,19 +25,25 @@ class SSLConfig # # See DRb::DRbSSLSocket::SSLConfig.new for more details DEFAULT = { - :SSLCertificate => nil, - :SSLPrivateKey => nil, - :SSLClientCA => nil, - :SSLCACertificatePath => nil, - :SSLCACertificateFile => nil, - :SSLTmpDhCallback => nil, - :SSLVerifyMode => ::OpenSSL::SSL::VERIFY_NONE, - :SSLVerifyDepth => nil, - :SSLVerifyCallback => nil, # custom verification - :SSLCertificateStore => nil, + :SSLCertificates => nil, + :SSLCertificate => nil, + :SSLPrivateKey => nil, + :SSLPrivateKeyAlgorithms => ["RSA"], + :SSLClientCA => nil, + :SSLCACertificatePath => nil, + :SSLCACertificateFile => nil, + :SSLSignatureAlgorithms => nil, + :SSLClientSignatureAlgorithms => nil, + :SSLGroups => nil, + :SSLTmpDhCallback => nil, + :SSLVerifyMode => ::OpenSSL::SSL::VERIFY_NONE, + :SSLVerifyDepth => nil, + :SSLVerifyCallback => nil, # custom verification + :SSLCertificateStore => nil, # Must specify if you use auto generated certificate. - :SSLCertName => nil, # e.g. [["CN","fqdn.example.com"]] - :SSLCertComment => "Generated by Ruby/OpenSSL" + # e.g. [["CN","fqdn.example.com"]] + :SSLCertName => nil, + :SSLCertComment => "Generated by Ruby/OpenSSL" } # Create a new DRb::DRbSSLSocket::SSLConfig instance @@ -51,13 +57,29 @@ class SSLConfig # # From +config+ Hash: # + # :SSLCertificates :: + # An Array of [certificate, private_key] pairs. Each element + # is an Array of an OpenSSL::X509::Certificate and its + # corresponding private key. This option is prioritized over + # :SSLCertificate and :SSLPrivateKey. See + # OpenSSL::SSL::SSLContext#add_certificate + # # :SSLCertificate :: # An instance of OpenSSL::X509::Certificate. If this is not provided, # then a generic X509 is generated, with a correspond :SSLPrivateKey # # :SSLPrivateKey :: - # A private key instance, like OpenSSL::PKey::RSA. This key must be - # the key that signed the :SSLCertificate + # A private key instance, like OpenSSL::PKey::RSA for RSA + # and OpenSSL::PKey::PKey for ML-DSA-44, ML-DSA-65, + # ML-DSA-87. This key must be the key that signed the + # :SSLCertificate + # + # :SSLPrivateKeyAlgorithms :: + # An Array of private key algorithms used to generate + # certificates when :SSLCertificates, :SSLCertificate and + # :SSLPrivateKey are not provided. Supported algorithms are + # RSA, ML-DSA-44, ML-DSA-65, and ML-DSA-87. + # Defaults to ["RSA"] # # :SSLClientCA :: # An OpenSSL::X509::Certificate, or Array of certificates that will @@ -70,6 +92,15 @@ class SSLConfig # :SSLCACertificateFile :: # A path to a CA certificate file, in PEM format. # + # :SSLSignatureAlgorithms :: + # Signature algorithms. See OpenSSL::SSL::SSLContext#sigalgs= + # + # :SSLClientSignatureAlgorithms :: + # Client signature algorithms. See OpenSSL::SSL::SSLContext#client_sigalgs= + # + # :SSLGroups :: + # Key exchange groups. See OpenSSL::SSL::SSLContext#groups= + # # :SSLTmpDhCallback :: # A DH callback. See OpenSSL::SSL::SSLContext.tmp_dh_callback # @@ -133,10 +164,15 @@ class SSLConfig # c.setup_certificate # def initialize(config) - @config = config - @cert = config[:SSLCertificate] - @pkey = config[:SSLPrivateKey] - @ssl_ctx = nil + @config = config + @certs = nil + if config[:SSLCertificate] && config[:SSLPrivateKey] + @certs = [[config[:SSLCertificate], config[:SSLPrivateKey]]] + end + @certs = config[:SSLCertificates] if config.key?(:SSLCertificates) + @pkey_algs = config[:SSLPrivateKeyAlgorithms] || + self[:SSLPrivateKeyAlgorithms] + @ssl_ctx = nil end # A convenience method to access the values like a Hash @@ -162,17 +198,114 @@ def accept(tcp) ssl end - # Ensures that :SSLCertificate and :SSLPrivateKey have been provided - # or that a new certificate is generated with the other parameters - # provided. + # Ensures that :SSLCertificates or :SSLCertificate and + # :SSLPrivateKey have been provided, or that new certificates + # are generated with the other parameters provided. def setup_certificate - if @cert && @pkey + if @certs return end - rsa = OpenSSL::PKey::RSA.new(2048) + @certs = @pkey_algs.map { |pkey_alg| setup_certificate_one(pkey_alg) } + end + + # Establish the OpenSSL::SSL::SSLContext with the configuration + # parameters provided. + def setup_ssl_context + ctx = ::OpenSSL::SSL::SSLContext.new + @certs&.each do |cert, pkey| + ctx.add_certificate(cert, pkey) + end + ctx.min_version = self[:SSLMinVersion] + ctx.max_version = self[:SSLMaxVersion] + ctx.client_ca = self[:SSLClientCA] + ctx.ca_path = self[:SSLCACertificatePath] + ctx.ca_file = self[:SSLCACertificateFile] + + if self[:SSLSignatureAlgorithms] + # OpenSSL::SSL::SSLContext#sigalgs=, #client_sigalgs=, #groups= were + # added in openssl gem 4.0.0. + # https://github.com/ruby/openssl/blob/v4.0.0/History.md?plain=1#L25-L31 + # OpenSSL::SSL::SSLContext#sigalgs= is supported in OpenSSL >= 1.0.2. + # https://github.com/ruby/openssl/blob/v4.0.0/ext/openssl/extconf.rb#L142-L143 + unless ctx.respond_to?(:sigalgs=) + raise(DRbBadConfig, + unsupported_message( + ':SSLSignatureAlgorithms', '4.0.0', '1.0.2' + )) + end + ctx.sigalgs = self[:SSLSignatureAlgorithms] + end + + if self[:SSLClientSignatureAlgorithms] + # OpenSSL::SSL::SSLContext#client_sigalgs= is supported in + # OpenSSL >= 1.0.2. + # https://github.com/ruby/openssl/blob/v4.0.0/ext/openssl/extconf.rb#L144-L145 + unless ctx.respond_to?(:client_sigalgs=) + raise(DRbBadConfig, + unsupported_message( + ':SSLClientSignatureAlgorithms', '4.0.0', '1.0.2' + )) + end + ctx.client_sigalgs = self[:SSLClientSignatureAlgorithms] + end + + if self[:SSLGroups] + # OpenSSL::SSL::SSLContext#groups is supported in all OpenSSL + # versions. + # https://github.com/ruby/openssl/blob/v4.0.0/ext/openssl/ossl_ssl.c#L3031 + unless ctx.respond_to?(:groups=) + raise(DRbBadConfig, + unsupported_message( + ':SSLGroups', '4.0.0' + )) + end + ctx.groups = self[:SSLGroups] + end + + ctx.tmp_dh_callback = self[:SSLTmpDhCallback] + ctx.verify_mode = self[:SSLVerifyMode] + ctx.verify_depth = self[:SSLVerifyDepth] + ctx.verify_callback = self[:SSLVerifyCallback] + ctx.cert_store = self[:SSLCertificateStore] + @ssl_ctx = ctx + end + + private + def setup_certificate_one(pkey_alg) cert = OpenSSL::X509::Certificate.new + + case pkey_alg + when "RSA" + pkey = OpenSSL::PKey::RSA.new(2048) + cert.public_key = pkey.public_key + digest = "SHA256" + when "ML-DSA-44", "ML-DSA-65", "ML-DSA-87" + # openssl gem >= 4.0.0 and OpenSSL >= 3.5.0 support ML-DSA. + # https://github.com/ruby/openssl/blob/v4.0.0/History.md#notable-changes + # https://openssl-library.org/post/2025-04-08-openssl-35-final-release/ + begin + pkey = OpenSSL::PKey.generate_key(pkey_alg) + rescue OpenSSL::PKey::PKeyError + raise(DRbBadConfig, + unsupported_message( + "#{pkey_alg} algorithm", '4.0.0', '3.5.0' + )) + end + # OpenSSL::PKey::PKey#public_to_der was added in openssl gem 2.2.0. + # https://github.com/ruby/openssl/blob/v2.2.0/History.md?plain=1#L72-L75 + cert.public_key = OpenSSL::PKey.read(pkey.public_to_der) + # OpenSSL::X509::Certificate#sign doesn't accept explicit digest + # algorithm, in ML-DSA because ML-DSA has a built-in digest. + digest = nil + else + raise(DRbBadConfig, + "#{pkey_alg} algorithm not found. "\ + "RSA, ML-DSA-44, ML-DSA-65, and ML-DSA-87 "\ + "algorithms are supported") + end + cert.version = 2 # This means v3 cert.serial = 0 name = OpenSSL::X509::Name.new(self[:SSLCertName]) @@ -180,7 +313,6 @@ def setup_certificate cert.issuer = name cert.not_before = Time.now cert.not_after = Time.now + (365*24*60*60) - cert.public_key = rsa.public_key ef = OpenSSL::X509::ExtensionFactory.new(nil,cert) cert.extensions = [ @@ -192,29 +324,19 @@ def setup_certificate if comment = self[:SSLCertComment] cert.add_extension(ef.create_extension("nsComment", comment)) end - cert.sign(rsa, "SHA256") + cert.sign(pkey, digest) - @cert = cert - @pkey = rsa + [cert, pkey] end - # Establish the OpenSSL::SSL::SSLContext with the configuration - # parameters provided. - def setup_ssl_context - ctx = ::OpenSSL::SSL::SSLContext.new - ctx.cert = @cert - ctx.key = @pkey - ctx.min_version = self[:SSLMinVersion] - ctx.max_version = self[:SSLMaxVersion] - ctx.client_ca = self[:SSLClientCA] - ctx.ca_path = self[:SSLCACertificatePath] - ctx.ca_file = self[:SSLCACertificateFile] - ctx.tmp_dh_callback = self[:SSLTmpDhCallback] - ctx.verify_mode = self[:SSLVerifyMode] - ctx.verify_depth = self[:SSLVerifyDepth] - ctx.verify_callback = self[:SSLVerifyCallback] - ctx.cert_store = self[:SSLCertificateStore] - @ssl_ctx = ctx + def unsupported_message(name, ruby_openssl_version, + openssl_version=nil) + message = "#{name} not supported. "\ + "Install openssl gem >= #{ruby_openssl_version}" + if openssl_version + message += " building with OpenSSL >= #{openssl_version}" + end + message end end diff --git a/test/drb/drbtest.rb b/test/drb/drbtest.rb index 03e4ca1..0fab567 100644 --- a/test/drb/drbtest.rb +++ b/test/drb/drbtest.rb @@ -4,6 +4,7 @@ require 'drb/drb' require 'drb/extservm' require 'timeout' +require_relative 'drbtest_utils' module DRbTests @@ -393,4 +394,90 @@ def test_07_break_18 end +# A PQC Utilities module inspired from ruby/rubygems omit_unless_support_pqc +module DRbPQCUtilities + # PQC algorithms ML-KEM and ML-DSA require OpenSSL >= 3.5. + # https://openssl-library.org/post/2025-04-08-openssl-35-final-release/ + def support_pqc_openssl? + OpenSSL::OPENSSL_VERSION_NUMBER >= 0x30500000 + end + + # Ruby OpenSSL >= 4.0 supports OpenSSL::SSL::SSLContext#groups, + # OpenSSL::SSL::SSLSocket#sigalg, #peer_sigalg used in PQC cases, fixing the + # following issue. + # https://github.com/ruby/openssl/blob/v4.0.0/History.md#notable-changes + # https://github.com/ruby/openssl/commit/9614b7f67a629cc8d31b6fe5be5040c68263ca8b + def support_pqc_ruby_openssl? + Gem::Version.new(OpenSSL::VERSION) >= Gem::Version.new('4.0') + end + + # Probe an actual PQC handshake between a forced-PQC server and a + # default-configured client, mirroring what the integration tests exercise. + # Memoized so the probe runs at most once per process. + def support_pqc_handshake? + return @support_pqc_handshake unless @support_pqc_handshake.nil? + + @support_pqc_handshake = probe_pqc_handshake + end + + def probe_pqc_handshake + server = TCPServer.new('127.0.0.1', 0) + ctx = OpenSSL::SSL::SSLContext.new + ctx.add_certificate( + Fixtures.read_cert('mldsa65_server.crt'), + Fixtures.read_pkey('mldsa65_server.key')) + ctx.groups = 'X25519MLKEM768' + ssl_server = OpenSSL::SSL::SSLServer.new(server, ctx) + + port = server.addr[1] + server_thread = Thread.new do + client = ssl_server.accept + client.close + rescue OpenSSL::OpenSSLError + nil + end + + client_ctx = OpenSSL::SSL::SSLContext.new + client_ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE + socket = TCPSocket.new('127.0.0.1', port) + ssl = OpenSSL::SSL::SSLSocket.new(socket, client_ctx) + ssl.connect + ssl.close + true + rescue OpenSSL::OpenSSLError, SystemCallError + false + ensure + server_thread&.join(5) + server_thread&.kill if server_thread&.alive? + ssl_server&.close + server&.close + end + + def omit_unless_support_pqc + unless support_pqc_openssl? + yield if block_given? + omit 'PQC algorithms require OpenSSL >= 3.5' + return + end + unless support_pqc_ruby_openssl? + yield if block_given? + omit 'PQC test requires Ruby OpenSSL >= 4.0' + return + end + unless support_pqc_handshake? + yield if block_given? + omit 'PQC handshake is not available in this OpenSSL configuration' + end + end +end + +module DRbPQC + include DRbBase + include DRbPQCUtilities + + def test_01_hello + assert_equal('hello', @there.hello) + end +end + end diff --git a/test/drb/drbtest_utils.rb b/test/drb/drbtest_utils.rb new file mode 100644 index 0000000..a6ab0c5 --- /dev/null +++ b/test/drb/drbtest_utils.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: false + +# This file does not require test/unit unlike drbtest.rb because it can +# be loaded by child processes (ut_drb_drbssl_pqc_multi_cert.rb) where +# test-unit's at_exit autorunner would cause errors. + +require 'openssl' + +module DRbTests + +module Fixtures + module_function + + def file_path(name) + File.join(__dir__, 'fixtures', name) + end + + def read_file(name) + @file_cache ||= {} + @file_cache[name] ||= File.read(file_path(name)) + end + + def read_pkey(name) + OpenSSL::PKey.read(read_file(name)) + end + + def read_cert(name) + OpenSSL::X509::Certificate.new(read_file(name)) + end +end + +end diff --git a/test/drb/fixtures/mldsa65_ca.crt b/test/drb/fixtures/mldsa65_ca.crt new file mode 100644 index 0000000..94c8d12 --- /dev/null +++ b/test/drb/fixtures/mldsa65_ca.crt @@ -0,0 +1,119 @@ +-----BEGIN CERTIFICATE----- +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 +seAAAAAAAAAAAAAAAAAAAAcNFBskKQ== +-----END CERTIFICATE----- diff --git a/test/drb/fixtures/mldsa65_client.crt b/test/drb/fixtures/mldsa65_client.crt new file mode 100644 index 0000000..ea5c558 --- /dev/null +++ b/test/drb/fixtures/mldsa65_client.crt @@ -0,0 +1,118 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/test/drb/fixtures/mldsa65_client.key b/test/drb/fixtures/mldsa65_client.key new file mode 100644 index 0000000..3240071 --- /dev/null +++ b/test/drb/fixtures/mldsa65_client.key @@ -0,0 +1,88 @@ +-----BEGIN PRIVATE KEY----- +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 +ptO3I2kHVduBiJ3zETRAQZmB +-----END PRIVATE KEY----- diff --git a/test/drb/fixtures/mldsa65_server.crt b/test/drb/fixtures/mldsa65_server.crt new file mode 100644 index 0000000..ec87616 --- /dev/null +++ b/test/drb/fixtures/mldsa65_server.crt @@ -0,0 +1,119 @@ +-----BEGIN CERTIFICATE----- +MIIVyzCCCMigAwIBAgIBATALBglghkgBZQMEAxIwPDELMAkGA1UEBhMCSlAxDjAM +BgNVBAgMBVRva3lvMRAwDgYDVQQKDAdEUmJUZXN0MQswCQYDVQQDDAJDQTAeFw0w +OTAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMEMxCzAJBgNVBAYTAkpQMQ4wDAYD +VQQIDAVUb2t5bzEQMA4GA1UECgwHRFJiVGVzdDESMBAGA1UEAwwJbG9jYWxob3N0 +MIIHsjALBglghkgBZQMEAxIDggehAL5ZuYuRPDjt9mvNpeknNiLVP1eS+R51NuZ/ +vGdKrxJ/9daseRUbb953pQkFqo4hIUe9qllth5/ZyflkyF1YVsIB2F+44887ItU/ +1rtu+7IvMJ6I3imyv+iaXMKjMpwkBoOLoE4JJxHnW1S00S0/dxyRljJvGLV53I2U +liwMLGkxbqIkl+cKPrEHVAUHq4PYyu4QAowbNWR1nMp2w4VdEUYjtKxASzjSs+sV +1nABe8wZJyBgxodlXApQEflleeVymWN6oxIGAw4XIE50KOfzIXIvIOTcA74v0qlM +lhEXqc1nX1CxydWA75JsBGUEXknk7DGbKGzeVtomuVZERmGfiqXNbdyIY9u5Dxja ++GeeS1LCHQfQkey5zDyhRxlkMLLiW/fSdwf4X4spfKoVHeD77lrTZiYfJlfTvfPb +0l96iRdvqHQG1BqZQJ9RPNKytKKzug0sHsjXIjYCZvtOlZe1Hyohr7lKrpl83j6+ +Iec0FzSpEBEb+fR1Gdb9TT7d3kWfT4wuyBwdVtEURVBgtL60csUMhdTyJCjdQjKT +rN04u9Q7h1jADz9SOR63BOJWhVJmu1kC+agT5aAo1RTtbxD84L7IxOpT0ufFjJRh +5sFsrvUdRhYMgAiQHPRPLyRfERjrQEIKakHKHDm5X48L3CcFPV5kxdlZENTuFS4y +qdOE+j9nNBk7fRssmPqrIb8LIlcNPpyshVqzGOfaGrs/vG5GlL4ZpJ4a4MSLp6qM +jPsf2fVO7BUsh2yeo6zzA6NnisrMknjbV+llHnuTHldFS/oPMswKMvXvrW65fUL9 +VGNrLJnIBW9+DqePHSLsSiG4daZ7OC1u+7z6FZla6CwBjo1vBTec1HKtynd8dx8W +0n2AxLbLOUKk6BNrC3dwleddKeVzP30Dp/ik1N7d1c0DsOu06wAG4fQPkOExyWp0 +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 +AAAAAAAAAAAAAwgSGyIp +-----END CERTIFICATE----- diff --git a/test/drb/fixtures/mldsa65_server.key b/test/drb/fixtures/mldsa65_server.key new file mode 100644 index 0000000..a9211f8 --- /dev/null +++ b/test/drb/fixtures/mldsa65_server.key @@ -0,0 +1,88 @@ +-----BEGIN PRIVATE KEY----- +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 +yx7mOp+5y+smrygQsuzE6ImM +-----END PRIVATE KEY----- diff --git a/test/drb/fixtures/rsa_ca.crt b/test/drb/fixtures/rsa_ca.crt new file mode 100644 index 0000000..d6cdde9 --- /dev/null +++ b/test/drb/fixtures/rsa_ca.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDWTCCAkGgAwIBAgIUct6NFabaXDcIk+brkXjM2axOIUAwDQYJKoZIhvcNAQEL +BQAwPDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMRAwDgYDVQQKDAdEUmJU +ZXN0MQswCQYDVQQDDAJDQTAeFw0wOTAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTla +MDwxCzAJBgNVBAYTAkpQMQ4wDAYDVQQIDAVUb2t5bzEQMA4GA1UECgwHRFJiVGVz +dDELMAkGA1UEAwwCQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCG ++KpP122EWUghnEk8VwIapDKVyVNwYzppzmDEv9jVX2xJ0pGQjXA3kCtCYndpYfIu +nWBDCMJfa3aPs9/eaCfSiltiRqiesrLt2nGSykUXFcrD6LDBUBD8oZOcunkpdp5L +JyN8VCaZ1AfSMzrjnzTlG405qi9kRGBZvM7mQW2pdkCmfIuOpbvIhGRHQPUQUTjK +lNAP+jB8uoKq2yK41xdeIt4ZcDCNaaY03/YsWH5CsDJw21OIA53kVij6rvwzEaiB +HlHrVAhZiYr2ECaJ6DCefrI/YZ8iJwkqSmxv69fbbALM1k9Gy3NdHZQ7K8uOlk49 +N3KT4rBLm0SV25A3q/ovAgMBAAGjUzBRMB0GA1UdDgQWBBQdTSuai6rYhHr9HkGS +LkAq6N5NazAfBgNVHSMEGDAWgBQdTSuai6rYhHr9HkGSLkAq6N5NazAPBgNVHRMB +Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBMe2eXVFPzIryLxXPfUS7KZtjT +dBlB52gATiI/6+W0QogzHdFs7xr0QrC5gLqtEglTGPXfzFZsRbRkCKj9BINkdO1J +EOVJ+RzUoFrUzH6/wJ10ylJmDSKLofh8NxtRzfMIb46UTRAEi7QyieH7AGsu926V +/ajEj5CAgeZP9mlEYLe7aOxJNqFwvHt5t3kBOCmcv3Bn3cgLK3DyXh6NHxgza4PF +6ZrajWLxNj8KyNYwCxU2n2lwDBe0eHxlNAENUICN0s4/opoJjPiC26zUWaaFitL1 +3vNhhfeGR61QynQLG/U8drfIirSrd/bP/Wbloqr32k/kqka4/1rXfVmemjVS +-----END CERTIFICATE----- diff --git a/test/drb/fixtures/rsa_client.crt b/test/drb/fixtures/rsa_client.crt new file mode 100644 index 0000000..07576e9 --- /dev/null +++ b/test/drb/fixtures/rsa_client.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDOTCCAiGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADA8MQswCQYDVQQGEwJKUDEO +MAwGA1UECAwFVG9reW8xEDAOBgNVBAoMB0RSYlRlc3QxCzAJBgNVBAMMAkNBMB4X +DTA5MDEwMTAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowQDELMAkGA1UEBhMCSlAxDjAM +BgNVBAgMBVRva3lvMRAwDgYDVQQKDAdEUmJUZXN0MQ8wDQYDVQQDDAZDbGllbnQw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCTeiJjLNe+A8+U5zw6N1Zz +sXCg39qM/RbFkH+yDc53o/OzOVqwETbz/hX4Ix3avfauh8N8ES8MbjsC8IsPU7gE +KyVuCbMbX8pFV/GgtfFJkCqBiJO1wBdKqeA2QAi4cM8luZjVdjrVSucTNABU1UsB +ERHa57v3jErk1X7xvhoPMCBQ9XLCXuJz23met6TUE0OU/QFOzDiKvoKX/2G3TGOG +qWrdxizQ6BzSk08uNmGOyHByIvcDk0txECvTM/g92WoYhpWWQDL7HK7FmKvdKFJe +l6Yk9x6OSMUMlrRrUQ+LTgkiD58p8t/Z5ytmyYAiqc16vaRKuimMaORvV+s2LZPV +AgMBAAGjQjBAMB0GA1UdDgQWBBTUPoJpd325/p1+OR1iZBTXGeC9dDAfBgNVHSME +GDAWgBQdTSuai6rYhHr9HkGSLkAq6N5NazANBgkqhkiG9w0BAQsFAAOCAQEANS9W +Z2n8iXDbgcseLqSmymOwhUUgvllAfBQciEknycwOG0gj5SNrhXXCLpduMwl7kc5d +Rd/iYX5ZQLK8+Wdc75GdUCnw/uQA4NLPkTw+DxDlT92HLqP0y8680CGmDCa8wf+K +sjSCoM94bzrVuIwvGEf+sIdjm+rPAMpxWK1bpVKzbGivS5RtkNGVFuUs22IAIg2A +UeuZRqnYAhbcyI/gksBfNKCXCtvZO2Qfys54BnG5As15QlyxrkM89RkFg2y35wMl +ooKpev3RjMQWPRsdic9LB8xA0Tm7p8vYU/XhrS+mjmhlqwhzf6/e9lXWLxIsUt6a +6zNXbAOLTRVioSvGQA== +-----END CERTIFICATE----- diff --git a/test/drb/fixtures/rsa_client.key b/test/drb/fixtures/rsa_client.key new file mode 100644 index 0000000..55349c2 --- /dev/null +++ b/test/drb/fixtures/rsa_client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCTeiJjLNe+A8+U +5zw6N1ZzsXCg39qM/RbFkH+yDc53o/OzOVqwETbz/hX4Ix3avfauh8N8ES8MbjsC +8IsPU7gEKyVuCbMbX8pFV/GgtfFJkCqBiJO1wBdKqeA2QAi4cM8luZjVdjrVSucT +NABU1UsBERHa57v3jErk1X7xvhoPMCBQ9XLCXuJz23met6TUE0OU/QFOzDiKvoKX +/2G3TGOGqWrdxizQ6BzSk08uNmGOyHByIvcDk0txECvTM/g92WoYhpWWQDL7HK7F +mKvdKFJel6Yk9x6OSMUMlrRrUQ+LTgkiD58p8t/Z5ytmyYAiqc16vaRKuimMaORv +V+s2LZPVAgMBAAECggEAGQeFvgy+ieCGMsii+2NocAa5rYgIhNywaHPrhDndJIeG +JRETH+YwDC1/p4c4Oid67iibCBu3fzXXHJrcEwwbo1N6TQhm5jq17tpr5yFx89D8 +sdLO9O4G1fRqWfK4uCrnMUkkU/g2qHwHp0XwV3WCvwnZXKxvRaaBEIDehGNF83Uu +zL4M/VMrIVxIwXfFT5iS3zLw2kOaypfxNaRktAqn0H9mcH1ybujTtGy+tvh0vCJN +ZQqOjpuG/oI/LT6JeLdIC5WRzOrTvMp161nWXSOkaWcbjAj2zsThovxCRSKTnvUd +IBz03WH48P/EPedDW+vPjZFI4TmXNx4EHsLzeZXR8QKBgQDJCiO2z/+95x7jLhGI +koepclLc9fxI9P4f3FXTFp4ZlGqyreEZPWEVFutK81sKx1c1RaB8k6xwBopQLKGS +IAkFBi600SUJIKgAfGgHIeIYR9ufdn4fimoXiAGzg8TPzJp0MaDpjZYajxADDSEY +Qh+vuck1kr29Up/4cqudMV/vxQKBgQC7y2TtTSvkprZKRk9+wuime6AWrqmaBNIh +NHKGIWruLyPd/MpomDMPUo4vCNVlakRyg2+huiqXLFQSA7ByaaJSjvdG93BdYKDM +JFAJuFV6wbUjxq3pzm2nmaHqUpS94fq9QIafmYvzmGBPPMdN57pjC74w5dWYqKuK +1hdOUqjE0QKBgQCUgeT3+paUldJ/R1y0YmnMhiMoDp4a1r+SkZTkpeSMSNK4wzFx +D6JTjeaqKzKpt694LsLqw7ux1WL+7rk71GZVS8fc0lJld7YjBcNi4Wi/PvXByipI +6lqMn2+CSGhuiFngU3jmjiy/2caeOmikHtSBXuB/rrJy1EJPqYWUTRDtcQKBgBEn +1JGFIkRiIncIk0yOO7ixxH8t95p1ZEjaRLgSJ3WY4trttAP4G3oD3a9YTD5Wheg8 +L5+DpU5oI0n+AkmBcu2918Mo6Z/uKuJbUuCAcXakaYraJJseW5AbDdqdLq9mDITr +dyDvYwSe3/V9JOvuBm3z7a0D4g5vIjStuDVUgcxxAoGBAL5wYVAdu86/+JyccOtn +B2K9ZPoThvJ9MI+YrFqKQfLtTeobXPJRwJjET1rXKM037QsexzRx85lZ6f+8TcbG +J0/VlMxZfgBxD+aKoA8v0ctgl4hByWCc8qvSihvwvXn/nD/WCFx0KSRVetseuEl4 +QA9yt0Klxf/bV3BeHNhCW3VI +-----END PRIVATE KEY----- diff --git a/test/drb/fixtures/rsa_server.crt b/test/drb/fixtures/rsa_server.crt new file mode 100644 index 0000000..aa85452 --- /dev/null +++ b/test/drb/fixtures/rsa_server.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDUjCCAjqgAwIBAgIBATANBgkqhkiG9w0BAQsFADA8MQswCQYDVQQGEwJKUDEO +MAwGA1UECAwFVG9reW8xEDAOBgNVBAoMB0RSYlRlc3QxCzAJBgNVBAMMAkNBMB4X +DTA5MDEwMTAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowQzELMAkGA1UEBhMCSlAxDjAM +BgNVBAgMBVRva3lvMRAwDgYDVQQKDAdEUmJUZXN0MRIwEAYDVQQDDAlsb2NhbGhv +c3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDDEULHw7Rqk2kypGh +P7Tfg8iTviNbqQ1D6xATM24bV2MyeNlOYRBIidIYPazQnkSE9wYbP7zH6DUhhhV7 +My5JxEwueu5QD+wdKVw3iUonBtQWX0ln4a34Jn6NaQSShQJZpOj9ZRe4brIIM2Hw +MUmFC4XBHAvSd3e+4bBsRir619anJoSXuHzCMJo6WDdhIpwBdjW7LTvv+EZ/1aVx +kX2ya21hbCoucqznl2L4Y3uVLRTK9D9g5vQoLgk6uh6oPPCf54cgwka5fghkPP1q +Ru0MBwgwcCI3eDMgUg+On0UfHk3OKgfaMENri5yfg+55XU6jyKopCwbTToRAPkgT +NZQvAgMBAAGjWDBWMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAdBgNVHQ4EFgQUXpGe +a1Y+s5vdH0hMPkdtfcQbi8YwHwYDVR0jBBgwFoAUHU0rmouq2IR6/R5Bki5AKuje +TWswDQYJKoZIhvcNAQELBQADggEBAC2nEdXrTAmTwi9Od/croljKN7QqB0ywvthQ +Jl7YIOCCrIJvUwLXoicU9YFl8yz3O38Zi7GPBjLm3Pe6ykglEc0d//GfftME2PH0 +jNlL9L0oAcCNOmPBowtVIq6ASy4TrF71scKdCsUdlbqkA0smMdkvpxgCfefmt1ea +LU4EuEkoMGuBG91M5Ci7JMEhsFPmImhT5FnQwWz+Bz2k5JsMrWClGA+/+5brL3jv +E6heORnWSsbxPTDPiEffRDzCyro2PAoKZ1Lx9yfMTk5Wz692YOlE7cErGF3sfMPI +CXfDBAYCmSrKw14vk7dGVxh8JKpBdhkyGtyy4X/qfGVipR81t5Q= +-----END CERTIFICATE----- diff --git a/test/drb/fixtures/rsa_server.key b/test/drb/fixtures/rsa_server.key new file mode 100644 index 0000000..5420d55 --- /dev/null +++ b/test/drb/fixtures/rsa_server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDDDEULHw7Rqk2k +ypGhP7Tfg8iTviNbqQ1D6xATM24bV2MyeNlOYRBIidIYPazQnkSE9wYbP7zH6DUh +hhV7My5JxEwueu5QD+wdKVw3iUonBtQWX0ln4a34Jn6NaQSShQJZpOj9ZRe4brII +M2HwMUmFC4XBHAvSd3e+4bBsRir619anJoSXuHzCMJo6WDdhIpwBdjW7LTvv+EZ/ +1aVxkX2ya21hbCoucqznl2L4Y3uVLRTK9D9g5vQoLgk6uh6oPPCf54cgwka5fghk +PP1qRu0MBwgwcCI3eDMgUg+On0UfHk3OKgfaMENri5yfg+55XU6jyKopCwbTToRA +PkgTNZQvAgMBAAECggEAJK99mvpj+KZ+BRU+r+QCGpo4UyWLk/Vnc9NWCi59srHM +jBUz1iymeeZGOF39T529CH9HzD9APB9eQuhryOjW93Pu2j0v7qoYAGIjoKR3aIC9 +yllwvpOxe3+OBP3wKLjQuNiuI97sR7m2TZmQfbNffyEsLqaeSJ9EzAe5/ZtzAQvc +I52SIWtfB/7sd6TIBxl4Af/WGLFTywaTpQE7XN8aik8u2xV+iCJm5Ud7kcnTUSqz +frKKSjWmVCi6i8KdgA832Spg5tP8XHasLuC1Ax007Dmu7UUZsJEpywYD0ha3H2TU +tb8P4IEPMW+VmJzcr/JFlmtAARN4O9rTEC97Oi2YsQKBgQD4MZORPpnUNbBZfCF/ +LjoZHl7icqtaujUdAOSvzsCDgKYajWPaxreifgDtXA+RbVKkzmB7Tu33VSC8Uw51 +Z1xGFHqqq9f2CvuSN/y2NL49OdcycX58DvytIWHrpfrFPJ8DpviPt2Ljkyi6qT4M +i+oYOPxO/BX113AhdsGNnRR6vwKBgQDJLsVJqUZbouaG6D5ZKm9Tg+x9IXRG3QMK +rzg6gwVTWBAV+2mGJc2bXFxiVQMCfGE1sTVdMH4pzVRAPI63FNrPu40M8kEMxUAK +qjZ/o+RWHSsgtbuPF2yoAABPxOj31wi7W/sDKEaoLmRrOcqd3RCSr8XmGR/HvONB ++77Yj81ykQKBgQDL0/s650xyCP2hH95qkk5IXrbSBhZP1mjUPu2QrJ1R4g+H8uI0 +w8n/+rdMN7TZXAzpKEv4OKQZ4aGWyCcxqAcRzrPHAoXDnNVqCezSvpIVujDPToHv +5GcC0E2Yt6Ew5k45M6EidhsShsKGOYOpziYcaoBbZY+rbJi8AsmGQaCWBQKBgQCt +t7MnrgFQ81L3vubHe7rxdILqcc7Duef8e9yjuasJkoshUById3AY7SHgzuNwbBJM +mJ4pv8vRMLnFVgUt1dYzdhGP0keVTWXFT8ELamuqaDlrX0F7h5CNaKLcPn2kNIwX +rI8M5OROKPERHa/1rIO5Bgpua9djU5kwyr66pUGT4QKBgDQJvWJ+D82VVHC8Tpwq +AyIK5G36ORZBQs3Qana8qkKc4yvZTT5ehmmM1mhexxPwzLxYSDdpeXyKHE3ZiMM8 +AT+wKO92G/zQpUPRnIDcrIQRFnkf6UJsLNfPV4RW1HhSgREDwMGIRYB2OleESLgn +sVXfCR89dc4DMyhH+LoXJtVA +-----END PRIVATE KEY----- diff --git a/test/drb/test_drbssl.rb b/test/drb/test_drbssl.rb index f2d9a20..3c3b875 100644 --- a/test/drb/test_drbssl.rb +++ b/test/drb/test_drbssl.rb @@ -78,6 +78,207 @@ def setup end end +class DRbSSLPQCService < DRbService + %w(ut_drb_drbssl_pqc.rb).each do |nm| + add_service_command(nm) + end + + def start + config = Hash.new + + config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER + config[:SSLVerifyCallback] = lambda{ |ok, x509_store| + true + } + config[:SSLCertName] = + [ ['C','JP'], ['O','Foo.DRuby.Org'], ['CN', 'Sample'] ] + config[:SSLPrivateKeyAlgorithms] = ['ML-DSA-65'] + config[:SSLGroups] = 'SecP256r1MLKEM768' + config[:SSLSignatureAlgorithms] = 'mldsa65' + + @server = DRb::DRbServer.new('drbssl://localhost:0', manager, config) + end +end + +class TestDRbSSLPQC < Test::Unit::TestCase + include DRbPQC + + def setup + if RUBY_PLATFORM.match?(/mswin|mingw/) + @omitted = true + omit 'This test seems to randomly hang on Windows' + end + omit_unless_support_pqc do + @omitted = true + end + + @drb_service = DRbSSLPQCService.new + super + setup_service 'ut_drb_drbssl_pqc.rb' + end + + def test_group_sigalg + # Server connection + assert_equal('OpenSSL::SSL::SSLSocket', + @there.stream_class_name) + server_ssl = @there.stream + assert_equal('SecP256r1MLKEM768', server_ssl.group) + assert_equal('mldsa65', server_ssl.sigalg) + assert_nil(server_ssl.peer_sigalg) + + # Client connection + DRb::DRbConn.open(@there.__drburi) do |conn| + ssl = conn.instance_variable_get(:@protocol).stream + assert_instance_of(OpenSSL::SSL::SSLSocket, ssl) + assert_equal('SecP256r1MLKEM768', ssl.group) + assert_nil(ssl.sigalg) + assert_equal('mldsa65', ssl.peer_sigalg) + [true, nil] + end + end +end + +class DRbSSLPQCMultiCertMLDSA65Service < DRbService + %w(ut_drb_drbssl_pqc_multi_cert.rb).each do |nm| + add_service_command(nm) + end + + def start + # Manager config with pre-generated ML-DSA-65 cert so the child + # process can verify the manager's cert via mldsa65_ca.crt in its + # store. + manager_config = Hash.new + manager_config[:SSLCertificate] = OpenSSL::X509::Certificate.new( + Fixtures.read_file('mldsa65_server.crt')) + manager_config[:SSLPrivateKey] = OpenSSL::PKey.read( + Fixtures.read_file('mldsa65_server.key')) + manager_config[:SSLSignatureAlgorithms] = 'mldsa65' + manager_config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_NONE + @server = DRb::DRbServer.new('drbssl://localhost:0', manager, + manager_config) + + # Client config to connect to server ut_drb_drbssl_pqc_multi_cert.rb + client_config = Hash.new + client_config[:SSLCertificate] = OpenSSL::X509::Certificate.new( + Fixtures.read_file('mldsa65_client.crt')) + client_config[:SSLPrivateKey] = OpenSSL::PKey.read( + Fixtures.read_file('mldsa65_client.key')) + client_config[:SSLSignatureAlgorithms] = 'mldsa65' + client_config[:SSLCACertificateFile] = + Fixtures.file_path('mldsa65_ca.crt') + client_config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER | + OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT + DRb.start_service(nil, nil, client_config) + end +end + +class DRbSSLPQCMultiCertRSAService < DRbService + %w(ut_drb_drbssl_pqc_multi_cert.rb).each do |nm| + add_service_command(nm) + end + + def start + # Manager config with pre-generated RSA cert so the child process + # can verify the manager's cert via rsa_ca.crt in its store. + manager_config = Hash.new + manager_config[:SSLCertificate] = OpenSSL::X509::Certificate.new( + Fixtures.read_file('rsa_server.crt')) + manager_config[:SSLPrivateKey] = OpenSSL::PKey::RSA.new( + Fixtures.read_file('rsa_server.key')) + manager_config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_NONE + @server = DRb::DRbServer.new('drbssl://localhost:0', manager, + manager_config) + + # Client config to connect to server ut_drb_drbssl_pqc_multi_cert.rb + client_config = Hash.new + client_config[:SSLCertificate] = OpenSSL::X509::Certificate.new( + Fixtures.read_file('rsa_client.crt')) + client_config[:SSLPrivateKey] = OpenSSL::PKey::RSA.new( + Fixtures.read_file('rsa_client.key')) + client_config[:SSLSignatureAlgorithms] = 'rsa_pss_rsae_sha256' + client_config[:SSLCACertificateFile] = + Fixtures.file_path('rsa_ca.crt') + client_config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER | + OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT + DRb.start_service(nil, nil, client_config) + end +end + +class TestDRbSSLPQCMultiCertMLDSA65 < Test::Unit::TestCase + include DRbPQC + + def setup + if RUBY_PLATFORM.match?(/mswin|mingw/) + @omitted = true + omit 'This test seems to randomly hang on Windows' + end + omit_unless_support_pqc do + @omitted = true + end + + @drb_service = DRbSSLPQCMultiCertMLDSA65Service.new + super + setup_service 'ut_drb_drbssl_pqc_multi_cert.rb' + end + + def test_group_sigalg + # Server connection + assert_equal('OpenSSL::SSL::SSLSocket', + @there.stream_class_name) + server_ssl = @there.stream + assert_equal('X25519MLKEM768', server_ssl.group) + assert_equal('mldsa65', server_ssl.sigalg) + assert_equal('mldsa65', server_ssl.peer_sigalg) + + # Client connection + DRb::DRbConn.open(@there.__drburi) do |conn| + ssl = conn.instance_variable_get(:@protocol).stream + assert_instance_of(OpenSSL::SSL::SSLSocket, ssl) + assert_equal('X25519MLKEM768', ssl.group) + assert_equal('mldsa65', ssl.sigalg) + assert_equal('mldsa65', ssl.peer_sigalg) + [true, nil] + end + end +end + +class TestDRbSSLPQCMultiCertRSA < Test::Unit::TestCase + include DRbPQC + + def setup + if RUBY_PLATFORM.match?(/mswin|mingw/) + @omitted = true + omit 'This test seems to randomly hang on Windows' + end + omit_unless_support_pqc do + @omitted = true + end + + @drb_service = DRbSSLPQCMultiCertRSAService.new + super + setup_service 'ut_drb_drbssl_pqc_multi_cert.rb' + end + + def test_group_sigalg + # Server connection + assert_equal('OpenSSL::SSL::SSLSocket', + @there.stream_class_name) + server_ssl = @there.stream + assert_equal('X25519MLKEM768', server_ssl.group) + assert_equal('rsa_pss_rsae_sha256', server_ssl.sigalg) + assert_equal('rsa_pss_rsae_sha256', server_ssl.peer_sigalg) + + # Client connection + DRb::DRbConn.open(@there.__drburi) do |conn| + ssl = conn.instance_variable_get(:@protocol).stream + assert_instance_of(OpenSSL::SSL::SSLSocket, ssl) + assert_equal('X25519MLKEM768', ssl.group) + assert_equal('rsa_pss_rsae_sha256', ssl.sigalg) + assert_equal('rsa_pss_rsae_sha256', ssl.peer_sigalg) + [true, nil] + end + end +end end diff --git a/test/drb/test_ssl.rb b/test/drb/test_ssl.rb new file mode 100644 index 0000000..97aa491 --- /dev/null +++ b/test/drb/test_ssl.rb @@ -0,0 +1,365 @@ +# frozen_string_literal: false +require 'test/unit' +require_relative 'drbtest' + +begin + require 'drb/ssl' +rescue LoadError +end + +module DRbTests + +if Object.const_defined?('OpenSSL') + +class TestSSLConfig < Test::Unit::TestCase + include DRbPQCUtilities + + CERT_NAME = [['C', 'JP'], ['O', 'Foo.DRuby.Org'], ['CN', 'localhost']] + + def test_setup_certificate_default + config = { + SSLCertName: CERT_NAME + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_instance_of(Array, certs) + assert_instance_of(OpenSSL::X509::Certificate, certs[0][0]) + assert_instance_of(OpenSSL::PKey::RSA, certs[0][1]) + end + + def test_setup_certificate_rsa + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['RSA'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_instance_of(Array, certs) + assert_instance_of(OpenSSL::X509::Certificate, certs[0][0]) + assert_instance_of(OpenSSL::PKey::RSA, certs[0][1]) + end + + def test_setup_certificate_ml_dsa_44 + omit_unless_support_pqc + + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['ML-DSA-44'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_instance_of(Array, certs) + assert_instance_of(OpenSSL::X509::Certificate, certs[0][0]) + assert_instance_of(OpenSSL::PKey::PKey, certs[0][1]) + assert_match(/type_name=ML-DSA-44/, certs[0][1].inspect) + end + + def test_setup_certificate_ml_dsa_65 + omit_unless_support_pqc + + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['ML-DSA-65'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_instance_of(Array, certs) + assert_instance_of(OpenSSL::X509::Certificate, certs[0][0]) + assert_instance_of(OpenSSL::PKey::PKey, certs[0][1]) + assert_match(/type_name=ML-DSA-65/, certs[0][1].inspect) + end + + def test_setup_certificate_ml_dsa_87 + omit_unless_support_pqc + + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['ML-DSA-87'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_instance_of(Array, certs) + assert_instance_of(OpenSSL::X509::Certificate, certs[0][0]) + assert_instance_of(OpenSSL::PKey::PKey, certs[0][1]) + assert_match(/type_name=ML-DSA-87/, certs[0][1].inspect) + end + + def test_setup_certificate_ml_dsa_65_rsa + omit_unless_support_pqc + + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['ML-DSA-65', 'RSA'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_instance_of(Array, certs) + assert_equal(2, certs.length) + assert_instance_of(OpenSSL::X509::Certificate, certs[0][0]) + assert_instance_of(OpenSSL::PKey::PKey, certs[0][1]) + assert_match(/type_name=ML-DSA-65/, certs[0][1].inspect) + assert_instance_of(OpenSSL::X509::Certificate, certs[1][0]) + assert_instance_of(OpenSSL::PKey::RSA, certs[1][1]) + end + + def test_setup_certificate_invalid_algorithm + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['INVALID'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + error = assert_raise(DRb::DRbBadConfig) do + ssl_conf.setup_certificate + end + assert_equal('INVALID algorithm not found. '\ + 'RSA, ML-DSA-44, ML-DSA-65, and ML-DSA-87 '\ + 'algorithms are supported', + error.message) + end + + def test_setup_certificate_unsupported_mldsa + unless OpenSSL::PKey.respond_to?(:generate_key) + omit 'OpenSSL::PKey.generate_key not available' + end + + orig = OpenSSL::PKey.method(:generate_key) + OpenSSL::PKey.define_singleton_method(:generate_key) do |alg| + raise OpenSSL::PKey::PKeyError, 'algorithm ML-DSA-65 not found' + end + begin + config = { + SSLCertName: CERT_NAME, + SSLPrivateKeyAlgorithms: ['ML-DSA-65'] + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + error = assert_raise(DRb::DRbBadConfig) do + ssl_conf.setup_certificate + end + assert_equal('ML-DSA-65 algorithm not supported. '\ + 'Install openssl gem >= 4.0.0 '\ + 'building with OpenSSL >= 3.5.0', + error.message) + ensure + OpenSSL::PKey.define_singleton_method( + :generate_key, orig) + end + end + + def test_setup_certificate_preserves_existing_cert_and_key + pkey = Fixtures.read_pkey('rsa_server.key') + cert = Fixtures.read_cert('rsa_server.crt') + config = { + SSLCertificate: cert, + SSLPrivateKey: pkey + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_certificate + certs = ssl_conf.instance_variable_get(:@certs) + + assert_same(cert, certs[0][0]) + assert_same(pkey, certs[0][1]) + end + + def test_setup_ssl_context_sigalgs + ctx_class = OpenSSL::SSL::SSLContext + omit 'sigalgs= not supported' unless ctx_class.method_defined?(:sigalgs=) + + config = { + SSLCertificate: Fixtures.read_cert('rsa_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('rsa_server.key'), + SSLSignatureAlgorithms: 'rsa_pss_rsae_sha256' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_ssl_context + ssl_ctx = ssl_conf.instance_variable_get(:@ssl_ctx) + + assert_instance_of(OpenSSL::SSL::SSLContext, ssl_ctx) + end + + def test_setup_ssl_context_sigalgs_pqc + ctx_class = OpenSSL::SSL::SSLContext + omit 'sigalgs= not supported' unless ctx_class.method_defined?(:sigalgs=) + omit_unless_support_pqc + + config = { + SSLCertificates: [ + [Fixtures.read_cert('mldsa65_server.crt'), + Fixtures.read_pkey('mldsa65_server.key')], + [Fixtures.read_cert('rsa_server.crt'), + Fixtures.read_pkey('rsa_server.key')] + ], + SSLSignatureAlgorithms: 'mldsa65:rsa_pss_rsae_sha256' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_ssl_context + ssl_ctx = ssl_conf.instance_variable_get(:@ssl_ctx) + + assert_instance_of(OpenSSL::SSL::SSLContext, ssl_ctx) + end + + def test_setup_ssl_context_sigalgs_method_not_supported + ctx_class = OpenSSL::SSL::SSLContext + unless ctx_class.method_defined?(:sigalgs=) + omit 'sigalgs= already not supported' + end + + orig = ctx_class.instance_method(:sigalgs=) + ctx_class.undef_method(:sigalgs=) + begin + config = { + SSLCertificate: Fixtures.read_cert('rsa_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('rsa_server.key'), + SSLSignatureAlgorithms: 'rsa_pss_rsae_sha256' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + error = assert_raise(DRb::DRbBadConfig) do + ssl_conf.setup_ssl_context + end + assert_equal(':SSLSignatureAlgorithms not supported. '\ + 'Install openssl gem >= 4.0.0 '\ + 'building with OpenSSL >= 1.0.2', + error.message) + ensure + ctx_class.define_method(:sigalgs=, orig) + end + end + + def test_setup_ssl_context_client_sigalgs + ctx_class = OpenSSL::SSL::SSLContext + unless ctx_class.method_defined?(:client_sigalgs=) + omit 'client_sigalgs= not supported' + end + + config = { + SSLCertificate: Fixtures.read_cert('rsa_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('rsa_server.key'), + SSLClientSignatureAlgorithms: 'rsa_pss_rsae_sha256' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_ssl_context + ssl_ctx = ssl_conf.instance_variable_get(:@ssl_ctx) + + assert_instance_of(OpenSSL::SSL::SSLContext, ssl_ctx) + end + + def test_setup_ssl_context_client_sigalgs_pqc + ctx_class = OpenSSL::SSL::SSLContext + unless ctx_class.method_defined?(:client_sigalgs=) + omit 'client_sigalgs= not supported' + end + omit_unless_support_pqc + + config = { + SSLCertificate: Fixtures.read_cert('mldsa65_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('mldsa65_server.key'), + SSLClientSignatureAlgorithms: 'mldsa44:mldsa65:mldsa87' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_ssl_context + ssl_ctx = ssl_conf.instance_variable_get(:@ssl_ctx) + + assert_instance_of(OpenSSL::SSL::SSLContext, ssl_ctx) + end + + def test_setup_ssl_context_client_sigalgs_not_supported + ctx_class = OpenSSL::SSL::SSLContext + unless ctx_class.method_defined?(:client_sigalgs=) + omit 'client_sigalgs= already not supported' + end + + orig = ctx_class.instance_method(:client_sigalgs=) + ctx_class.undef_method(:client_sigalgs=) + begin + config = { + SSLCertificate: Fixtures.read_cert('rsa_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('rsa_server.key'), + SSLClientSignatureAlgorithms: 'rsa_pss_rsae_sha256' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + error = assert_raise(DRb::DRbBadConfig) do + ssl_conf.setup_ssl_context + end + assert_equal(':SSLClientSignatureAlgorithms not supported. '\ + 'Install openssl gem >= 4.0.0 '\ + 'building with OpenSSL >= 1.0.2', + error.message) + ensure + ctx_class.define_method(:client_sigalgs=, orig) + end + end + + def test_setup_ssl_context_groups + ctx_class = OpenSSL::SSL::SSLContext + omit 'groups= not supported' unless ctx_class.method_defined?(:groups=) + + config = { + SSLCertificate: Fixtures.read_cert('rsa_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('rsa_server.key'), + SSLGroups: 'P-256:P-384' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_ssl_context + ssl_ctx = ssl_conf.instance_variable_get(:@ssl_ctx) + + assert_instance_of(OpenSSL::SSL::SSLContext, ssl_ctx) + end + + def test_setup_ssl_context_groups_pqc + ctx_class = OpenSSL::SSL::SSLContext + omit 'groups= not supported' unless ctx_class.method_defined?(:groups=) + omit_unless_support_pqc + + config = { + SSLCertificate: Fixtures.read_cert('mldsa65_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('mldsa65_server.key'), + SSLGroups: 'X25519MLKEM768' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + ssl_conf.setup_ssl_context + ssl_ctx = ssl_conf.instance_variable_get(:@ssl_ctx) + + assert_instance_of(OpenSSL::SSL::SSLContext, ssl_ctx) + end + + def test_setup_ssl_context_groups_not_supported + ctx_class = OpenSSL::SSL::SSLContext + unless ctx_class.method_defined?(:groups=) + omit 'groups= already not supported' + end + + orig = ctx_class.instance_method(:groups=) + ctx_class.undef_method(:groups=) + begin + config = { + SSLCertificate: Fixtures.read_cert('rsa_server.crt'), + SSLPrivateKey: Fixtures.read_pkey('rsa_server.key'), + SSLGroups: 'P-256:P-384' + } + ssl_conf = DRb::DRbSSLSocket::SSLConfig.new(config) + error = assert_raise(DRb::DRbBadConfig) do + ssl_conf.setup_ssl_context + end + assert_equal(':SSLGroups not supported. '\ + 'Install openssl gem >= 4.0.0', + error.message) + ensure + ctx_class.define_method(:groups=, orig) + end + end +end + +end + +end diff --git a/test/drb/ut_drb.rb b/test/drb/ut_drb.rb index 7c0603b..7ed72f3 100644 --- a/test/drb/ut_drb.rb +++ b/test/drb/ut_drb.rb @@ -41,6 +41,14 @@ def initialize end attr_reader :hello + def stream + Thread.current['DRb']['client'].stream + end + + def stream_class_name + stream.class.name + end + def sample(a, b, c) a.to_i + b.to_i + c.to_i end diff --git a/test/drb/ut_drb_drbssl_pqc.rb b/test/drb/ut_drb_drbssl_pqc.rb new file mode 100644 index 0000000..83dd705 --- /dev/null +++ b/test/drb/ut_drb_drbssl_pqc.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: false +require_relative 'ut_drb' +require 'drb/ssl' + +if __FILE__ == $0 + def ARGV.shift + it = super() + raise "usage: #{$0} " unless it + it + end + + config = Hash.new + config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER + config[:SSLVerifyCallback] = lambda{|ok, x509_store| + true + } + config[:SSLCertName] = + [ ['C','JP'], ['O','Foo.DRuby.Org'], ['CN', 'Sample'] ] + config[:SSLPrivateKeyAlgorithms] = ['ML-DSA-65'] + config[:SSLGroups] = 'SecP256r1MLKEM768' + config[:SSLSignatureAlgorithms] = 'mldsa65' + + DRb.start_service('drbssl://localhost:0', DRbTests::DRbEx.new, config) + es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) + DRb.thread.join + es.stop_service if es.alive? +end diff --git a/test/drb/ut_drb_drbssl_pqc_multi_cert.rb b/test/drb/ut_drb_drbssl_pqc_multi_cert.rb new file mode 100644 index 0000000..42c1527 --- /dev/null +++ b/test/drb/ut_drb_drbssl_pqc_multi_cert.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: false + +# drbssl server with pre-generated ML-DSA-65/RSA multi cert and client cert + +require_relative 'ut_drb' +require_relative 'drbtest_utils' +require 'drb/ssl' + +if __FILE__ == $0 + def ARGV.shift + it = super() + raise "usage: #{$0} " unless it + it + end + + config = Hash.new + config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER | + OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT + config[:SSLCertificates] = [ + [ + OpenSSL::X509::Certificate.new( + DRbTests::Fixtures.read_file('mldsa65_server.crt')), + OpenSSL::PKey.read( + DRbTests::Fixtures.read_file('mldsa65_server.key')) + ], + [ + OpenSSL::X509::Certificate.new( + DRbTests::Fixtures.read_file('rsa_server.crt')), + OpenSSL::PKey::RSA.new( + DRbTests::Fixtures.read_file('rsa_server.key')) + ] + ] + config[:SSLGroups] = 'X25519MLKEM768' + config[:SSLSignatureAlgorithms] = 'mldsa65:rsa_pss_rsae_sha256' + # CA certificates to verify client's certificate + store = OpenSSL::X509::Store.new + store.add_cert(OpenSSL::X509::Certificate.new( + DRbTests::Fixtures.read_file('mldsa65_ca.crt'))) + store.add_cert(OpenSSL::X509::Certificate.new( + DRbTests::Fixtures.read_file('rsa_ca.crt'))) + config[:SSLCertificateStore] = store + # CA certificate(s) sent to the client indicating which certificates the + # server accepts. Helps the client choose which certificate to present. + config[:SSLClientCA] = [ + OpenSSL::X509::Certificate.new( + DRbTests::Fixtures.read_file('mldsa65_ca.crt')), + OpenSSL::X509::Certificate.new( + DRbTests::Fixtures.read_file('rsa_ca.crt')) + ] + + DRb.start_service('drbssl://localhost:0', DRbTests::DRbEx.new, config) + es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) + DRb.thread.join + es.stop_service if es.alive? +end diff --git a/tool/create_certs.sh b/tool/create_certs.sh new file mode 100755 index 0000000..0e59783 --- /dev/null +++ b/tool/create_certs.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +# This script creates RSA and ML-DSA-65 SSL/TLS test certificates. +# It requires OpenSSL >= 3.5 for ML-DSA-65 support. + +set -eu + +TOP_DIR="$(git rev-parse --show-toplevel)" +FIXTURES_DIR="${TOP_DIR}/test/drb/fixtures" +TMP_DIR="${TOP_DIR}/tmp/create_certs" + +create_certs() { + genpkey_args="${1}" + prefix="${2}" + + # CA + mkdir -p "${TMP_DIR}/${prefix}" + openssl genpkey ${genpkey_args} -out "${TMP_DIR}/${prefix}/ca.key" + openssl req -x509 \ + -key "${TMP_DIR}/${prefix}/ca.key" \ + -subj "/C=JP/ST=Tokyo/O=DRbTest/CN=CA" \ + -not_before 090101000000Z -not_after 491231235959Z \ + -out "${TMP_DIR}/${prefix}/ca.crt" + + # Server + openssl genpkey ${genpkey_args} -out "${TMP_DIR}/${prefix}/server.key" + openssl req -new \ + -key "${TMP_DIR}/${prefix}/server.key" \ + -subj "/C=JP/ST=Tokyo/O=DRbTest/CN=localhost" \ + -addext "subjectAltName=DNS:localhost" \ + -out "${TMP_DIR}/${prefix}/server.csr" + openssl x509 -req \ + -in "${TMP_DIR}/${prefix}/server.csr" \ + -CA "${TMP_DIR}/${prefix}/ca.crt" \ + -CAkey "${TMP_DIR}/${prefix}/ca.key" \ + -set_serial 1 \ + -copy_extensions copyall \ + -not_before 090101000000Z -not_after 491231235959Z \ + -out "${TMP_DIR}/${prefix}/server.crt" + + # Client + openssl genpkey ${genpkey_args} -out "${TMP_DIR}/${prefix}/client.key" + openssl req -new \ + -key "${TMP_DIR}/${prefix}/client.key" \ + -subj "/C=JP/ST=Tokyo/O=DRbTest/CN=Client" \ + -out "${TMP_DIR}/${prefix}/client.csr" + openssl x509 -req \ + -in "${TMP_DIR}/${prefix}/client.csr" \ + -CA "${TMP_DIR}/${prefix}/ca.crt" \ + -CAkey "${TMP_DIR}/${prefix}/ca.key" \ + -set_serial 2 \ + -not_before 090101000000Z -not_after 491231235959Z \ + -out "${TMP_DIR}/${prefix}/client.crt" + + cp "${TMP_DIR}/${prefix}/ca.crt" "${FIXTURES_DIR}/${prefix}_ca.crt" + cp "${TMP_DIR}/${prefix}/server.crt" "${FIXTURES_DIR}/${prefix}_server.crt" + cp "${TMP_DIR}/${prefix}/server.key" "${FIXTURES_DIR}/${prefix}_server.key" + cp "${TMP_DIR}/${prefix}/client.crt" "${FIXTURES_DIR}/${prefix}_client.crt" + cp "${TMP_DIR}/${prefix}/client.key" "${FIXTURES_DIR}/${prefix}_client.key" +} + +rm -rf "${TMP_DIR}" +mkdir -p "${FIXTURES_DIR}" + +# RSA +create_certs "-algorithm rsa -pkeyopt rsa_keygen_bits:2048" "rsa" + +# ML-DSA-65 +create_certs "-algorithm mldsa65" "mldsa65" + +echo "OK"