diff options
Diffstat (limited to 'test/openssl')
33 files changed, 725 insertions, 230 deletions
diff --git a/test/openssl/fixtures/pkey/dh1024.pem b/test/openssl/fixtures/pkey/dh1024.pem deleted file mode 100644 index f99c757f21..0000000000 --- a/test/openssl/fixtures/pkey/dh1024.pem +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0 -pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG -AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC ------END DH PARAMETERS----- diff --git a/test/openssl/fixtures/pkey/dh2048_ffdhe2048.pem b/test/openssl/fixtures/pkey/dh2048_ffdhe2048.pem new file mode 100644 index 0000000000..9b182b7201 --- /dev/null +++ b/test/openssl/fixtures/pkey/dh2048_ffdhe2048.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz ++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a +87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 +YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi +7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD +ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== +-----END DH PARAMETERS----- diff --git a/test/openssl/fixtures/pkey/dsa2048.pem b/test/openssl/fixtures/pkey/dsa2048.pem new file mode 100644 index 0000000000..3f22b22b58 --- /dev/null +++ b/test/openssl/fixtures/pkey/dsa2048.pem @@ -0,0 +1,15 @@ +-----BEGIN PRIVATE KEY----- +MIICXgIBADCCAjYGByqGSM44BAEwggIpAoIBAQDXZhJ/dQoWkQELzjzlx8FtIp96 +voCYe5NY0H8j0jz7GyHpXt41+MteqkZK3/Ah+cNR9uG8iEYArAZ71LcWotfee2Gz +xdxozr9bRt0POYhO2YIsfMpBrEskPsDH2g/2nFV8l4OJgxU2qZUrF4PN5ha+Mu6u +sVtN8hjvAvnbf4Pxn0b8NN9f4PJncroUa8acv5WsV85E1RW7NYCefggU4LytYIHg +euRF9eY9gVCX5MkUgW2xODHIYJhwk/+5lJxG7qUsSahD/nPHO/yoWgdVHq2DkdTq +KYXkAxx2PJcTBOHTglhE6mgCbEKp8vcfElnBWyCT6QykclZiPXXD2JV829J/Ah0A +vYa+/G/gUZiomyejVje6UsGoCc+vInxmovOL8QKCAQEAhnKEigYPw6u8JY7v5iGo +Ylz8qiMFYmaJCwevf3KCjWeEXuNO4OrKdfzkQl1tPuGLioYFfP1A2yGosjdUdLEB +0JqnzlKxUp+G6RfBj+WYzbgc5hr7t0M+reAJh09/hDzqfxjcgiHstq7mpRXBP8Y7 +iu27s7TRYJNSAYRvWcXNSBEUym3mHBBbZn7VszYooSrn60/iZ8I+VY1UF/fgqhbj +JfaaZNQCDO9K3Vb3rsXoYd8+bOZIen9uHB+pNjMqhpl4waysqrlpGFeeqdxivH6S +vkrHLs6/eWVMnS08RdcryoCrI3Bm8mMBKQglDwKLnWLfzG565qEhslzyCd/l9k9a +cwQfAh0Ao8/g72fSFmo04FizM7DZJSIPqDLjfZu9hLvUFA== +-----END PRIVATE KEY----- diff --git a/test/openssl/fixtures/pkey/p256_too_large.pem b/test/openssl/fixtures/pkey/p256_too_large.pem new file mode 100644 index 0000000000..a73ac37f87 --- /dev/null +++ b/test/openssl/fixtures/pkey/p256_too_large.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIP+TT0V8Fndsnacji9tyf6hmhHywcOWTee9XkiBeJoVloAoGCCqGSM49 +AwEHoUQDQgAEBkhhJIU/2/YdPSlY2I1k25xjK4trr5OXSgXvBC21PtY0HQ7lor7A +jzT0giJITqmcd81fwGw5+96zLcdxTF1hVQ== +-----END EC PRIVATE KEY----- diff --git a/test/openssl/fixtures/pkey/p384_invalid.pem b/test/openssl/fixtures/pkey/p384_invalid.pem new file mode 100644 index 0000000000..d5cdc9a3af --- /dev/null +++ b/test/openssl/fixtures/pkey/p384_invalid.pem @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDDA1Tm0m7YhkfeVpFuarAJYVlHp2tQj+1fOBiLa10t9E8TiQO/hVfxB +vGaVEQwOheWgBwYFK4EEACKhZANiAASyGqmryZGqdpsq5gEDIfNvgC3AwSJxiBCL +XKHBTFRp+tCezLDOK/6V8KK/vVGBJlGFW6/I7ahyXprxS7xs7hPA9iz5YiuqXlu+ +lbrIpZOz7b73hyQQCkvbBO/Avg+hPAk= +-----END EC PRIVATE KEY----- diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb index 0fd7971585..7b1722e5df 100644 --- a/test/openssl/test_asn1.rb +++ b/test/openssl/test_asn1.rb @@ -14,7 +14,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase ["keyUsage","keyCertSign, cRLSign",true], ["subjectKeyIdentifier","hash",false], ] - dgst = OpenSSL::Digest.new('SHA1') + dgst = OpenSSL::Digest.new('SHA256') cert = OpenSSL::TestUtils.issue_cert( subj, key, s, exts, nil, nil, digest: dgst, not_before: now, not_after: now+3600) @@ -42,7 +42,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase assert_equal(OpenSSL::ASN1::Sequence, sig.class) assert_equal(2, sig.value.size) assert_equal(OpenSSL::ASN1::ObjectId, sig.value[0].class) - assert_equal("1.2.840.113549.1.1.5", sig.value[0].oid) + assert_equal("1.2.840.113549.1.1.11", sig.value[0].oid) assert_equal(OpenSSL::ASN1::Null, sig.value[1].class) dn = tbs_cert.value[3] # issuer @@ -189,7 +189,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase assert_equal(OpenSSL::ASN1::Null, pkey.value[0].value[1].class) assert_equal(OpenSSL::ASN1::BitString, sig_val.class) - cululated_sig = key.sign(OpenSSL::Digest.new('SHA1'), tbs_cert.to_der) + cululated_sig = key.sign(OpenSSL::Digest.new('SHA256'), tbs_cert.to_der) assert_equal(cululated_sig, sig_val.value) end @@ -323,14 +323,9 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase assert_raise(OpenSSL::ASN1::ASN1Error) { OpenSSL::ASN1::ObjectId.new("3.0".b).to_der } assert_raise(OpenSSL::ASN1::ASN1Error) { OpenSSL::ASN1::ObjectId.new("0.40".b).to_der } - begin - oid = (0...100).to_a.join(".").b - obj = OpenSSL::ASN1::ObjectId.new(oid) - assert_equal oid, obj.oid - rescue OpenSSL::ASN1::ASN1Error - pend "OBJ_obj2txt() not working (LibreSSL?)" if $!.message =~ /OBJ_obj2txt/ - raise - end + oid = (0...100).to_a.join(".").b + obj = OpenSSL::ASN1::ObjectId.new(oid) + assert_equal oid, obj.oid aki = [ OpenSSL::ASN1::ObjectId.new("authorityKeyIdentifier"), @@ -404,9 +399,6 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase def test_utctime encode_decode_test B(%w{ 17 0D }) + "160908234339Z".b, OpenSSL::ASN1::UTCTime.new(Time.utc(2016, 9, 8, 23, 43, 39)) - # Seconds is omitted - decode_test B(%w{ 17 0B }) + "1609082343Z".b, - OpenSSL::ASN1::UTCTime.new(Time.utc(2016, 9, 8, 23, 43, 0)) begin # possible range of UTCTime is 1969-2068 currently encode_decode_test B(%w{ 17 0D }) + "690908234339Z".b, @@ -432,8 +424,6 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 29)) encode_decode_test B(%w{ 18 0F }) + "99990908234339Z".b, OpenSSL::ASN1::GeneralizedTime.new(Time.utc(9999, 9, 8, 23, 43, 39)) - decode_test B(%w{ 18 0D }) + "201612081934Z".b, - OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 0)) # not implemented # decode_test B(%w{ 18 13 }) + "20161208193439+0930".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.new(2016, 12, 8, 19, 34, 39, "+09:30")) diff --git a/test/openssl/test_bn.rb b/test/openssl/test_bn.rb index 346602dada..ea88ff06ce 100644 --- a/test/openssl/test_bn.rb +++ b/test/openssl/test_bn.rb @@ -174,6 +174,14 @@ class OpenSSL::TestBN < OpenSSL::TestCase assert_equal(0, 59.to_bn.mod_sqr(59)) end + def test_mod_sqrt + assert_equal(4, 4.to_bn.mod_sqrt(5).mod_sqr(5)) + # One of 189484 or 326277 is returned as a square root of 2 (mod 515761). + assert_equal(2, 2.to_bn.mod_sqrt(515761).mod_sqr(515761)) + assert_equal(0, 5.to_bn.mod_sqrt(5)) + assert_raise(OpenSSL::BNError) { 3.to_bn.mod_sqrt(5) } + end + def test_mod_inverse assert_equal(2, 3.to_bn.mod_inverse(5)) assert_raise(OpenSSL::BNError) { 3.to_bn.mod_inverse(6) } diff --git a/test/openssl/test_cipher.rb b/test/openssl/test_cipher.rb index b5fdf0b3d1..41885fd59b 100644 --- a/test/openssl/test_cipher.rb +++ b/test/openssl/test_cipher.rb @@ -108,12 +108,6 @@ class OpenSSL::TestCipher < OpenSSL::TestCase assert_not_equal s1, s2 end - def test_empty_data - cipher = OpenSSL::Cipher.new("DES-EDE3-CBC").encrypt - cipher.random_key - assert_raise(ArgumentError) { cipher.update("") } - end - def test_initialize cipher = OpenSSL::Cipher.new("DES-EDE3-CBC") assert_raise(RuntimeError) { cipher.__send__(:initialize, "DES-EDE3-CBC") } @@ -211,7 +205,7 @@ class OpenSSL::TestCipher < OpenSSL::TestCase assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct2) } end if has_cipher?("aes-128-ccm") && OpenSSL::Cipher.new("aes-128-ccm").authenticated? && - OpenSSL::OPENSSL_VERSION_NUMBER >= 0x1010103f # version >= 1.1.1c + openssl?(1, 1, 1, 0x03, 0xf) # version >= 1.1.1c def test_aes_gcm # GCM spec Appendix B Test Case 4 @@ -337,6 +331,22 @@ class OpenSSL::TestCipher < OpenSSL::TestCase assert_equal tag1, tag2 end + def test_aes_keywrap_pad + # RFC 5649 Section 6; The second example + kek = ["5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8"].pack("H*") + key = ["466f7250617369"].pack("H*") + wrap = ["afbeb0f07dfbf5419200f2ccb50bb24f"].pack("H*") + + begin + cipher = OpenSSL::Cipher.new("id-aes192-wrap-pad").encrypt + rescue OpenSSL::Cipher::CipherError, RuntimeError + omit "id-aes192-wrap-pad is not supported: #$!" + end + cipher.key = kek + ct = cipher.update(key) << cipher.final + assert_equal wrap, ct + end + def test_non_aead_cipher_set_auth_data assert_raise(OpenSSL::Cipher::CipherError) { cipher = OpenSSL::Cipher.new("aes-128-cfb").encrypt diff --git a/test/openssl/test_config.rb b/test/openssl/test_config.rb index 24a215a486..6dbb9c6138 100644 --- a/test/openssl/test_config.rb +++ b/test/openssl/test_config.rb @@ -91,22 +91,19 @@ __EOC__ assert_equal('123baz456bar798', c['dollar']['qux']) assert_equal('123baz456bar798.123baz456bar798', c['dollar']['quxx']) - excn = assert_raise(OpenSSL::ConfigError) do + assert_raise_with_message(OpenSSL::ConfigError, /error in line 1: variable has no value/) do OpenSSL::Config.parse("foo = $bar") end - assert_equal("error in line 1: variable has no value", excn.message) - excn = assert_raise(OpenSSL::ConfigError) do + assert_raise_with_message(OpenSSL::ConfigError, /error in line 1: no close brace/) do OpenSSL::Config.parse("foo = $(bar") end - assert_equal("error in line 1: no close brace", excn.message) - excn = assert_raise(OpenSSL::ConfigError) do + assert_raise_with_message(OpenSSL::ConfigError, /error in line 1: missing equal sign/) do OpenSSL::Config.parse("f o =b ar # no space in key") end - assert_equal("error in line 1: missing equal sign", excn.message) - excn = assert_raise(OpenSSL::ConfigError) do + assert_raise_with_message(OpenSSL::ConfigError, /error in line 7: missing close square bracket/) do OpenSSL::Config.parse(<<__EOC__) # comment 1 # comments @@ -117,7 +114,6 @@ __EOC__ [third # section not terminated __EOC__ end - assert_equal("error in line 7: missing close square bracket", excn.message) end def test_s_parse_include diff --git a/test/openssl/test_digest.rb b/test/openssl/test_digest.rb index 84c128c12f..988330e405 100644 --- a/test/openssl/test_digest.rb +++ b/test/openssl/test_digest.rb @@ -67,7 +67,7 @@ class OpenSSL::TestDigest < OpenSSL::TestCase end def encode16(str) - str.unpack("H*").first + str.unpack1("H*") end def test_sha2 @@ -88,7 +88,7 @@ class OpenSSL::TestDigest < OpenSSL::TestCase end def test_sha512_truncate - pend "SHA512_224 is not implemented" unless digest_available?('SHA512-224') + pend "SHA512_224 is not implemented" unless digest_available?('sha512-224') sha512_224_a = "d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327" sha512_256_a = "455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8" @@ -100,7 +100,7 @@ class OpenSSL::TestDigest < OpenSSL::TestCase end def test_sha3 - pend "SHA3 is not implemented" unless digest_available?('SHA3-224') + pend "SHA3 is not implemented" unless digest_available?('sha3-224') s224 = '6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7' s256 = 'a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a' s384 = '0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004' @@ -126,6 +126,15 @@ class OpenSSL::TestDigest < OpenSSL::TestCase end end + def test_digests + digests = OpenSSL::Digest.digests + assert_kind_of Array, digests + assert_include digests, "md5" + assert_include digests, "sha1" + assert_include digests, "sha256" + assert_include digests, "sha512" + end + private def check_digest(oid) @@ -138,11 +147,8 @@ class OpenSSL::TestDigest < OpenSSL::TestCase end def digest_available?(name) - begin - OpenSSL::Digest.new(name) - rescue RuntimeError - false - end + @digests ||= OpenSSL::Digest.digests + @digests.include?(name) end end diff --git a/test/openssl/test_engine.rb b/test/openssl/test_engine.rb index 1ede6ed086..b6025f915b 100644 --- a/test/openssl/test_engine.rb +++ b/test/openssl/test_engine.rb @@ -26,7 +26,7 @@ class OpenSSL::TestEngine < OpenSSL::TestCase with_openssl <<-'end;' orig = OpenSSL::Engine.engines pend "'openssl' is already loaded" if orig.any? { |e| e.id == "openssl" } - engine = get_engine + engine = OpenSSL::Engine.by_id("openssl") assert_not_nil(engine) assert_equal(1, OpenSSL::Engine.engines.size - orig.size) end; @@ -34,7 +34,7 @@ class OpenSSL::TestEngine < OpenSSL::TestCase def test_openssl_engine_id_name_inspect with_openssl <<-'end;' - engine = get_engine + engine = OpenSSL::Engine.by_id("openssl") assert_equal("openssl", engine.id) assert_not_nil(engine.name) assert_not_nil(engine.inspect) @@ -43,7 +43,7 @@ class OpenSSL::TestEngine < OpenSSL::TestCase def test_openssl_engine_digest_sha1 with_openssl <<-'end;' - engine = get_engine + engine = OpenSSL::Engine.by_id("openssl") digest = engine.digest("SHA1") assert_not_nil(digest) data = "test" @@ -59,12 +59,21 @@ class OpenSSL::TestEngine < OpenSSL::TestCase end with_openssl(<<-'end;', ignore_stderr: true) - engine = get_engine + engine = OpenSSL::Engine.by_id("openssl") algo = "RC4" data = "a" * 1000 key = OpenSSL::Random.random_bytes(16) - encrypted = crypt_data(data, key, :encrypt) { engine.cipher(algo) } - decrypted = crypt_data(encrypted, key, :decrypt) { OpenSSL::Cipher.new(algo) } + + cipher = engine.cipher(algo) + cipher.encrypt + cipher.key = key + encrypted = cipher.update(data) + cipher.final + + cipher = OpenSSL::Cipher.new(algo) + cipher.decrypt + cipher.key = key + decrypted = cipher.update(encrypted) + cipher.final + assert_equal(data, decrypted) end; end @@ -73,25 +82,10 @@ class OpenSSL::TestEngine < OpenSSL::TestCase # this is required because OpenSSL::Engine methods change global state def with_openssl(code, **opts) - assert_separately([{ "OSSL_MDEBUG" => nil }, "-ropenssl"], <<~"end;", **opts) - require #{__FILE__.dump} - include OpenSSL::TestEngine::Utils + assert_separately(["-ropenssl"], <<~"end;", **opts) #{code} end; end - - module Utils - def get_engine - OpenSSL::Engine.by_id("openssl") - end - - def crypt_data(data, key, mode) - cipher = yield - cipher.send mode - cipher.key = key - cipher.update(data) + cipher.final - end - end end end diff --git a/test/openssl/test_fips.rb b/test/openssl/test_fips.rb index 8cd474f9a3..4a3dd43a41 100644 --- a/test/openssl/test_fips.rb +++ b/test/openssl/test_fips.rb @@ -4,22 +4,46 @@ require_relative 'utils' if defined?(OpenSSL) class OpenSSL::TestFIPS < OpenSSL::TestCase + def test_fips_mode_get_is_true_on_fips_mode_enabled + unless ENV["TEST_RUBY_OPENSSL_FIPS_ENABLED"] + omit "Only for FIPS mode environment" + end + + assert_separately(["-ropenssl"], <<~"end;") + assert OpenSSL.fips_mode == true, ".fips_mode should return true on FIPS mode enabled" + end; + end + + def test_fips_mode_get_is_false_on_fips_mode_disabled + if ENV["TEST_RUBY_OPENSSL_FIPS_ENABLED"] + omit "Only for non-FIPS mode environment" + end + + assert_separately(["-ropenssl"], <<~"end;") + message = ".fips_mode should return false on FIPS mode disabled. " \ + "If you run the test on FIPS mode, please set " \ + "TEST_RUBY_OPENSSL_FIPS_ENABLED=true" + assert OpenSSL.fips_mode == false, message + end; + end + def test_fips_mode_is_reentrant - OpenSSL.fips_mode = false - OpenSSL.fips_mode = false + assert_separately(["-ropenssl"], <<~"end;") + OpenSSL.fips_mode = false + OpenSSL.fips_mode = false + end; end - def test_fips_mode_get - return unless OpenSSL::OPENSSL_FIPS - assert_separately([{ "OSSL_MDEBUG" => nil }, "-ropenssl"], <<~"end;") - require #{__FILE__.dump} + def test_fips_mode_get_with_fips_mode_set + omit('OpenSSL is not FIPS-capable') unless OpenSSL::OPENSSL_FIPS + assert_separately(["-ropenssl"], <<~"end;") begin OpenSSL.fips_mode = true - assert OpenSSL.fips_mode == true, ".fips_mode returns true when .fips_mode=true" + assert OpenSSL.fips_mode == true, ".fips_mode should return true when .fips_mode=true" OpenSSL.fips_mode = false - assert OpenSSL.fips_mode == false, ".fips_mode returns false when .fips_mode=false" + assert OpenSSL.fips_mode == false, ".fips_mode should return false when .fips_mode=false" rescue OpenSSL::OpenSSLError pend "Could not set FIPS mode (OpenSSL::OpenSSLError: \#$!); skipping" end diff --git a/test/openssl/test_hmac.rb b/test/openssl/test_hmac.rb index 47cb3718df..3cb707448a 100644 --- a/test/openssl/test_hmac.rb +++ b/test/openssl/test_hmac.rb @@ -21,7 +21,6 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase end def test_dup - pend "HMAC#initialize_copy is currently broken on OpenSSL 3.0.0" if openssl?(3, 0, 0) h1 = OpenSSL::HMAC.new("KEY", "MD5") h1.update("DATA") h = h1.dup @@ -63,6 +62,14 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase b64digest = OpenSSL::HMAC.base64digest("MD5", key, "Hi There") assert_equal "kpRyejY4uxwT9I74FYv8nQ==", b64digest end + + def test_zero_length_key + # Empty string as the key + hexdigest = OpenSSL::HMAC.hexdigest("SHA256", "\0"*32, "test") + assert_equal "43b0cef99265f9e34c10ea9d3501926d27b39f57c6d674561d8ba236e7a819fb", hexdigest + hexdigest = OpenSSL::HMAC.hexdigest("SHA256", "", "test") + assert_equal "43b0cef99265f9e34c10ea9d3501926d27b39f57c6d674561d8ba236e7a819fb", hexdigest + end end end diff --git a/test/openssl/test_ns_spki.rb b/test/openssl/test_ns_spki.rb index ed3be86e2c..d76fc9e5cf 100644 --- a/test/openssl/test_ns_spki.rb +++ b/test/openssl/test_ns_spki.rb @@ -22,7 +22,7 @@ class OpenSSL::TestNSSPI < OpenSSL::TestCase spki = OpenSSL::Netscape::SPKI.new spki.challenge = "RandomString" spki.public_key = key1.public_key - spki.sign(key1, OpenSSL::Digest.new('SHA1')) + spki.sign(key1, OpenSSL::Digest.new('SHA256')) assert(spki.verify(spki.public_key)) assert(spki.verify(key1.public_key)) assert(!spki.verify(key2.public_key)) @@ -38,13 +38,13 @@ class OpenSSL::TestNSSPI < OpenSSL::TestCase def test_decode_data spki = OpenSSL::Netscape::SPKI.new(@b64) assert_equal(@b64, spki.to_pem) - assert_equal(@b64.unpack("m").first, spki.to_der) + assert_equal(@b64.unpack1("m"), spki.to_der) assert_equal("MozillaIsMyFriend", spki.challenge) assert_equal(OpenSSL::PKey::RSA, spki.public_key.class) - spki = OpenSSL::Netscape::SPKI.new(@b64.unpack("m").first) + spki = OpenSSL::Netscape::SPKI.new(@b64.unpack1("m")) assert_equal(@b64, spki.to_pem) - assert_equal(@b64.unpack("m").first, spki.to_der) + assert_equal(@b64.unpack1("m"), spki.to_der) assert_equal("MozillaIsMyFriend", spki.challenge) assert_equal(OpenSSL::PKey::RSA, spki.public_key.class) end diff --git a/test/openssl/test_ocsp.rb b/test/openssl/test_ocsp.rb index 85f133752c..cf96fc22e5 100644 --- a/test/openssl/test_ocsp.rb +++ b/test/openssl/test_ocsp.rb @@ -228,7 +228,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase assert_equal OpenSSL::OCSP::V_CERTSTATUS_REVOKED, single.cert_status assert_equal OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED, single.revocation_reason assert_equal now - 400, single.revocation_time - assert_in_delta (now - 301), single.this_update, 1 + assert_in_delta (now - 300), single.this_update, 1 assert_equal nil, single.next_update assert_equal [], single.extensions diff --git a/test/openssl/test_ossl.rb b/test/openssl/test_ossl.rb index e1d86bd40b..979669a003 100644 --- a/test/openssl/test_ossl.rb +++ b/test/openssl/test_ossl.rb @@ -60,6 +60,19 @@ class OpenSSL::OSSL < OpenSSL::SSLTestCase assert_operator(a_b_time, :<, a_c_time * 10, "fixed_length_secure_compare timing test failed") assert_operator(a_c_time, :<, a_b_time * 10, "fixed_length_secure_compare timing test failed") end + + def test_error_data + # X509V3_EXT_nconf_nid() called from OpenSSL::X509::ExtensionFactory#create_ext is a function + # that uses ERR_raise_data() to append additional information about the error. + # + # The generated message should look like: + # "subjectAltName = IP:not.a.valid.ip.address: bad ip address (value=not.a.valid.ip.address)" + # "subjectAltName = IP:not.a.valid.ip.address: error in extension (name=subjectAltName, value=IP:not.a.valid.ip.address)" + ef = OpenSSL::X509::ExtensionFactory.new + assert_raise_with_message(OpenSSL::X509::ExtensionError, /value=(IP:)?not.a.valid.ip.address\)/) { + ef.create_ext("subjectAltName", "IP:not.a.valid.ip.address") + } + end end end diff --git a/test/openssl/test_pair.rb b/test/openssl/test_pair.rb index 4249b4afb7..66e36a7ab4 100644 --- a/test/openssl/test_pair.rb +++ b/test/openssl/test_pair.rb @@ -2,7 +2,7 @@ require_relative 'utils' require_relative 'ut_eof' -if defined?(OpenSSL) +if defined?(OpenSSL::SSL) module OpenSSL::SSLPairM def setup @@ -115,6 +115,17 @@ module OpenSSL::TestPairM } end + def test_gets_chomp + ssl_pair {|s1, s2| + s1 << "line1\r\nline2\r\nline3\r\n" + s1.close + + assert_equal("line1", s2.gets("\r\n", chomp: true)) + assert_equal("line2\r\n", s2.gets("\r\n", chomp: false)) + assert_equal("line3", s2.gets(chomp: true)) + } + end + def test_gets_eof_limit ssl_pair {|s1, s2| s1.write("hello") @@ -239,12 +250,17 @@ module OpenSSL::TestPairM buf = +"garbage" assert_equal :wait_readable, s2.read_nonblock(100, buf, exception: false) - assert_equal "", buf + assert_equal "garbage", buf s1.close buf = +"garbage" - assert_equal nil, s2.read(100, buf) + assert_nil s2.read(100, buf) assert_equal "", buf + + buf = +"garbage" + ret = s2.read(0, buf) + assert_same buf, ret + assert_equal "", ret } end diff --git a/test/openssl/test_pkcs12.rb b/test/openssl/test_pkcs12.rb index ec676743bc..e6b91b52af 100644 --- a/test/openssl/test_pkcs12.rb +++ b/test/openssl/test_pkcs12.rb @@ -181,7 +181,7 @@ module OpenSSL def test_new_with_no_keys # generated with: # openssl pkcs12 -certpbe PBE-SHA1-3DES -in <@mycert> -nokeys -export - str = <<~EOF.unpack("m").first + str = <<~EOF.unpack1("m") MIIGJAIBAzCCBeoGCSqGSIb3DQEHAaCCBdsEggXXMIIF0zCCBc8GCSqGSIb3 DQEHBqCCBcAwggW8AgEAMIIFtQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQMw DgQIjv5c3OHvnBgCAggAgIIFiMJa8Z/w7errRvCQPXh9dGQz3eJaFq3S2gXD @@ -230,7 +230,7 @@ AA== def test_new_with_no_certs # generated with: # openssl pkcs12 -inkey fixtures/openssl/pkey/rsa-1.pem -nocerts -export - str = <<~EOF.unpack("m").first + str = <<~EOF.unpack1("m") MIIJ7wIBAzCCCbUGCSqGSIb3DQEHAaCCCaYEggmiMIIJnjCCCZoGCSqGSIb3 DQEHAaCCCYsEggmHMIIJgzCCCX8GCyqGSIb3DQEMCgECoIIJbjCCCWowHAYK KoZIhvcNAQwBAzAOBAjX5nN8jyRKwQICCAAEgglIBIRLHfiY1mNHpl3FdX6+ diff --git a/test/openssl/test_pkcs7.rb b/test/openssl/test_pkcs7.rb index ba8b93d034..c049ed444a 100644 --- a/test/openssl/test_pkcs7.rb +++ b/test/openssl/test_pkcs7.rb @@ -155,6 +155,21 @@ class OpenSSL::TestPKCS7 < OpenSSL::TestCase assert_equal(data, p7.decrypt(@rsa1024)) end + def test_empty_signed_data_ruby_bug_19974 + data = "-----BEGIN PKCS7-----\nMAsGCSqGSIb3DQEHAg==\n-----END PKCS7-----\n" + assert_raise(ArgumentError) { OpenSSL::PKCS7.new(data) } + + data = <<END +MIME-Version: 1.0 +Content-Disposition: attachment; filename="smime.p7m" +Content-Type: application/x-pkcs7-mime; smime-type=signed-data; name="smime.p7m" +Content-Transfer-Encoding: base64 + +#{data} +END + assert_raise(OpenSSL::PKCS7::PKCS7Error) { OpenSSL::PKCS7.read_smime(data) } + end + def test_graceful_parsing_failure #[ruby-core:43250] contents = File.read(__FILE__) assert_raise(ArgumentError) { OpenSSL::PKCS7.new(contents) } @@ -212,6 +227,12 @@ END assert_equal(p7.to_der, OpenSSL::PKCS7.read_smime(smime).to_der) end + def test_to_text + p7 = OpenSSL::PKCS7.new + p7.type = "signed" + assert_match(/signed/, p7.to_text) + end + def test_degenerate_pkcs7 ca_cert_pem = <<END -----BEGIN CERTIFICATE----- diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb index 544340e378..aee0546f63 100644 --- a/test/openssl/test_pkey.rb +++ b/test/openssl/test_pkey.rb @@ -40,6 +40,11 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase } # Parameter generation callback is called + if openssl?(3, 0, 0, 0) && !openssl?(3, 0, 0, 6) + # Errors in BN_GENCB were not properly handled. This special pend is to + # suppress failures on Ubuntu 22.04, which uses OpenSSL 3.0.2. + pend "unstable test on OpenSSL 3.0.[0-5]" + end cb_called = [] assert_raise(RuntimeError) { OpenSSL::PKey.generate_parameters("DSA") { |*args| @@ -77,6 +82,9 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase end def test_ed25519 + # Ed25519 is not FIPS-approved. + omit_on_fips + # Test vector from RFC 8032 Section 7.1 TEST 2 priv_pem = <<~EOF -----BEGIN PRIVATE KEY----- @@ -91,9 +99,11 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase begin priv = OpenSSL::PKey.read(priv_pem) pub = OpenSSL::PKey.read(pub_pem) - rescue OpenSSL::PKey::PKeyError + rescue OpenSSL::PKey::PKeyError => e # OpenSSL < 1.1.1 - pend "Ed25519 is not implemented" + pend "Ed25519 is not implemented" unless openssl?(1, 1, 1) + + raise e end assert_instance_of OpenSSL::PKey::PKey, priv assert_instance_of OpenSSL::PKey::PKey, pub @@ -101,6 +111,19 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase assert_equal pub_pem, priv.public_to_pem assert_equal pub_pem, pub.public_to_pem + begin + assert_equal "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb", + priv.raw_private_key.unpack1("H*") + assert_equal OpenSSL::PKey.new_raw_private_key("ED25519", priv.raw_private_key).private_to_pem, + priv.private_to_pem + assert_equal "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", + priv.raw_public_key.unpack1("H*") + assert_equal OpenSSL::PKey.new_raw_public_key("ED25519", priv.raw_public_key).public_to_pem, + pub.public_to_pem + rescue NoMethodError + pend "running OpenSSL version does not have raw public key support" + end + sig = [<<~EOF.gsub(/[^0-9a-f]/, "")].pack("H*") 92a009a9f0d4cab8720e820b5f642540 a2b27b5416503f8fb3762223ebdb69da @@ -121,6 +144,32 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase assert_raise(OpenSSL::PKey::PKeyError) { priv.derive(pub) } end + def test_ed25519_not_approved_on_fips + omit_on_non_fips + # Ed25519 is technically allowed in the OpenSSL 3.0 code as a kind of bug. + # So, we need to omit OpenSSL 3.0. + # + # See OpenSSL providers/fips/fipsprov.c PROV_NAMES_ED25519 entries with + # FIPS_DEFAULT_PROPERTIES on openssl-3.0 branch and + # FIPS_UNAPPROVED_PROPERTIES on openssl-3.1 branch. + # + # See also + # https://github.com/openssl/openssl/issues/20758#issuecomment-1639658102 + # for details. + unless openssl?(3, 1, 0, 0) + omit 'Ed25519 is allowed in the OpenSSL 3.0 FIPS code as a kind of bug' + end + + priv_pem = <<~EOF + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIEzNCJso/5banbbDRuwRTg9bijGfNaumJNqM9u1PuKb7 + -----END PRIVATE KEY----- + EOF + assert_raise(OpenSSL::PKey::PKeyError) do + OpenSSL::PKey.read(priv_pem) + end + end + def test_x25519 # Test vector from RFC 7748 Section 6.1 alice_pem = <<~EOF @@ -145,6 +194,32 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase assert_equal alice_pem, alice.private_to_pem assert_equal bob_pem, bob.public_to_pem assert_equal [shared_secret].pack("H*"), alice.derive(bob) + begin + alice_private = OpenSSL::PKey.new_raw_private_key("X25519", alice.raw_private_key) + bob_public = OpenSSL::PKey.new_raw_public_key("X25519", bob.raw_public_key) + alice_private_raw = alice.raw_private_key.unpack1("H*") + bob_public_raw = bob.raw_public_key.unpack1("H*") + rescue NoMethodError + # OpenSSL < 1.1.1 + pend "running OpenSSL version does not have raw public key support" + end + assert_equal alice_private.private_to_pem, + alice.private_to_pem + assert_equal bob_public.public_to_pem, + bob.public_to_pem + assert_equal "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a", + alice_private_raw + assert_equal "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f", + bob_public_raw + end + + def raw_initialize + pend "Ed25519 is not implemented" unless openssl?(1, 1, 1) # >= v1.1.1 + + assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("foo123", "xxx") } + assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("ED25519", "xxx") } + assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_public_key("foo123", "xxx") } + assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_public_key("ED25519", "xxx") } end def test_compare? diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb index 161af1897b..d32ffaf6b1 100644 --- a/test/openssl/test_pkey_dh.rb +++ b/test/openssl/test_pkey_dh.rb @@ -18,15 +18,26 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase assert_key(dh) end if ENV["OSSL_TEST_ALL"] - def test_new_break + def test_new_break_on_non_fips + omit_on_fips + assert_nil(OpenSSL::PKey::DH.new(NEW_KEYLEN) { break }) assert_raise(RuntimeError) do OpenSSL::PKey::DH.new(NEW_KEYLEN) { raise } end end + def test_new_break_on_fips + omit_on_non_fips + + # The block argument is not executed in FIPS case. + # See https://github.com/ruby/openssl/issues/692 for details. + assert(OpenSSL::PKey::DH.new(NEW_KEYLEN) { break }) + assert(OpenSSL::PKey::DH.new(NEW_KEYLEN) { raise }) + end + def test_derive_key - params = Fixtures.pkey("dh1024") + params = Fixtures.pkey("dh2048_ffdhe2048") dh1 = OpenSSL::PKey.generate_key(params) dh2 = OpenSSL::PKey.generate_key(params) dh1_pub = OpenSSL::PKey.read(dh1.public_to_der) @@ -44,34 +55,38 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase end def test_DHparams - dh1024 = Fixtures.pkey("dh1024") - dh1024params = dh1024.public_key + dh = Fixtures.pkey("dh2048_ffdhe2048") + dh_params = dh.public_key asn1 = OpenSSL::ASN1::Sequence([ - OpenSSL::ASN1::Integer(dh1024.p), - OpenSSL::ASN1::Integer(dh1024.g) + OpenSSL::ASN1::Integer(dh.p), + OpenSSL::ASN1::Integer(dh.g) ]) key = OpenSSL::PKey::DH.new(asn1.to_der) - assert_same_dh dh1024params, key + assert_same_dh dh_params, key pem = <<~EOF -----BEGIN DH PARAMETERS----- - MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0 - pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG - AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC + MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz + +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a + 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 + YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi + 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD + ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== -----END DH PARAMETERS----- EOF + key = OpenSSL::PKey::DH.new(pem) - assert_same_dh dh1024params, key + assert_same_dh dh_params, key key = OpenSSL::PKey.read(pem) - assert_same_dh dh1024params, key + assert_same_dh dh_params, key - assert_equal asn1.to_der, dh1024.to_der - assert_equal pem, dh1024.export + assert_equal asn1.to_der, dh.to_der + assert_equal pem, dh.export end def test_public_key - dh = Fixtures.pkey("dh1024") + dh = Fixtures.pkey("dh2048_ffdhe2048") public_key = dh.public_key assert_no_key(public_key) #implies public_key.public? is false! assert_equal(dh.to_der, public_key.to_der) @@ -80,7 +95,8 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase def test_generate_key # Deprecated in v3.0.0; incompatible with OpenSSL 3.0 - dh = Fixtures.pkey("dh1024").public_key # creates a copy with params only + # Creates a copy with params only + dh = Fixtures.pkey("dh2048_ffdhe2048").public_key assert_no_key(dh) dh.generate_key! assert_key(dh) @@ -91,7 +107,15 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase end if !openssl?(3, 0, 0) def test_params_ok? - dh0 = Fixtures.pkey("dh1024") + # Skip the tests in old OpenSSL version 1.1.1c or early versions before + # applying the following commits in OpenSSL 1.1.1d to make `DH_check` + # function pass the RFC 7919 FFDHE group texts. + # https://github.com/openssl/openssl/pull/9435 + unless openssl?(1, 1, 1, 4) + pend 'DH check for RFC 7919 FFDHE group texts is not implemented' + end + + dh0 = Fixtures.pkey("dh2048_ffdhe2048") dh1 = OpenSSL::PKey::DH.new(OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(dh0.p), @@ -108,7 +132,7 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase def test_dup # Parameters only - dh1 = Fixtures.pkey("dh1024") + dh1 = Fixtures.pkey("dh2048_ffdhe2048") dh2 = dh1.dup assert_equal dh1.to_der, dh2.to_der assert_not_equal nil, dh1.p @@ -125,7 +149,7 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase end # With a key pair - dh3 = OpenSSL::PKey.generate_key(Fixtures.pkey("dh1024")) + dh3 = OpenSSL::PKey.generate_key(Fixtures.pkey("dh2048_ffdhe2048")) dh4 = dh3.dup assert_equal dh3.to_der, dh4.to_der assert_equal dh1.to_der, dh4.to_der # encodes parameters only @@ -136,7 +160,7 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase end def test_marshal - dh = Fixtures.pkey("dh1024") + dh = Fixtures.pkey("dh2048_ffdhe2048") deserialized = Marshal.load(Marshal.dump(dh)) assert_equal dh.to_der, deserialized.to_der diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb index 726b7dbf7e..4c93f2869d 100644 --- a/test/openssl/test_pkey_dsa.rb +++ b/test/openssl/test_pkey_dsa.rb @@ -28,28 +28,55 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase end end + def test_generate + # DSA.generate used to call DSA_generate_parameters_ex(), which adjusts the + # size of q according to the size of p + key2048 = OpenSSL::PKey::DSA.generate(2048) + assert_equal 2048, key2048.p.num_bits + assert_equal 256, key2048.q.num_bits + + if ENV["OSSL_TEST_ALL"] == "1" # slow + key3072 = OpenSSL::PKey::DSA.generate(3072) + assert_equal 3072, key3072.p.num_bits + assert_equal 256, key3072.q.num_bits + end + end + + def test_generate_on_non_fips + # DSA with 1024 bits is invalid on FIPS 186-4. + # https://github.com/openssl/openssl/commit/49ed5ba8f62875074f04417189147fd3dda072ab + omit_on_fips + + key1024 = OpenSSL::PKey::DSA.generate(1024) + assert_predicate key1024, :private? + assert_equal 1024, key1024.p.num_bits + assert_equal 160, key1024.q.num_bits + end + def test_sign_verify - dsa512 = Fixtures.pkey("dsa512") + # The DSA valid size is 2048 or 3072 on FIPS. + # https://github.com/openssl/openssl/blob/7649b5548e5c0352b91d9d3ed695e42a2ac1e99c/providers/common/securitycheck.c#L185-L188 + dsa = Fixtures.pkey("dsa2048") data = "Sign me!" if defined?(OpenSSL::Digest::DSS1) - signature = dsa512.sign(OpenSSL::Digest.new('DSS1'), data) - assert_equal true, dsa512.verify(OpenSSL::Digest.new('DSS1'), signature, data) + signature = dsa.sign(OpenSSL::Digest.new('DSS1'), data) + assert_equal true, dsa.verify(OpenSSL::Digest.new('DSS1'), signature, data) end - signature = dsa512.sign("SHA1", data) - assert_equal true, dsa512.verify("SHA1", signature, data) + signature = dsa.sign("SHA256", data) + assert_equal true, dsa.verify("SHA256", signature, data) - signature0 = (<<~'end;').unpack("m")[0] - MCwCFH5h40plgU5Fh0Z4wvEEpz0eE9SnAhRPbkRB8ggsN/vsSEYMXvJwjGg/ - 6g== + signature0 = (<<~'end;').unpack1("m") + MD4CHQC0zmRkVOAHJTm28fS5PVUv+4LtBeNaKqr/yfmVAh0AsTcLqofWHoW8X5oWu8AOvngOcFVZ + cLTvhY3XNw== end; - assert_equal true, dsa512.verify("SHA256", signature0, data) + assert_equal true, dsa.verify("SHA256", signature0, data) signature1 = signature0.succ - assert_equal false, dsa512.verify("SHA256", signature1, data) + assert_equal false, dsa.verify("SHA256", signature1, data) end def test_sign_verify_raw - key = Fixtures.pkey("dsa512") + key = Fixtures.pkey("dsa2048") data = 'Sign me!' digest = OpenSSL::Digest.digest('SHA1', data) @@ -108,6 +135,8 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase end def test_DSAPrivateKey_encrypted + omit_on_fips + # key = abcdef dsa512 = Fixtures.pkey("dsa512") pem = <<~EOF diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb index ffe5a94e5b..2cb8e287ab 100644 --- a/test/openssl/test_pkey_ec.rb +++ b/test/openssl/test_pkey_ec.rb @@ -5,20 +5,6 @@ if defined?(OpenSSL) class OpenSSL::TestEC < OpenSSL::PKeyTestCase def test_ec_key - builtin_curves = OpenSSL::PKey::EC.builtin_curves - assert_not_empty builtin_curves - - builtin_curves.each do |curve_name, comment| - # Oakley curves and X25519 are not suitable for signing and causes - # FIPS-selftest failure on some environment, so skip for now. - next if ["Oakley", "X25519"].any? { |n| curve_name.start_with?(n) } - - key = OpenSSL::PKey::EC.generate(curve_name) - assert_predicate key, :private? - assert_predicate key, :public? - assert_nothing_raised { key.check_key } - end - key1 = OpenSSL::PKey::EC.generate("prime256v1") # PKey is immutable in OpenSSL >= 3.0; constructing an empty EC object is @@ -49,6 +35,17 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase end end + def test_builtin_curves + builtin_curves = OpenSSL::PKey::EC.builtin_curves + assert_not_empty builtin_curves + assert_equal 2, builtin_curves[0].size + assert_kind_of String, builtin_curves[0][0] + assert_kind_of String, builtin_curves[0][1] + + builtin_curve_names = builtin_curves.map { |name, comment| name } + assert_include builtin_curve_names, "prime256v1" + end + def test_generate assert_raise(OpenSSL::PKey::ECError) { OpenSSL::PKey::EC.generate("non-existent") } g = OpenSSL::PKey::EC::Group.new("prime256v1") @@ -61,8 +58,10 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase def test_generate_key ec = OpenSSL::PKey::EC.new("prime256v1") assert_equal false, ec.private? + assert_raise(OpenSSL::PKey::ECError) { ec.to_der } ec.generate_key! assert_equal true, ec.private? + assert_nothing_raised { ec.to_der } end if !openssl?(3, 0, 0) def test_marshal @@ -88,6 +87,13 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase assert_equal(true, key2.public?) assert_equal(true, key2.check_key) + # Behavior of EVP_PKEY_public_check changes between OpenSSL 1.1.1 and 3.0 + key4 = Fixtures.pkey("p256_too_large") + assert_raise(OpenSSL::PKey::ECError) { key4.check_key } + + key5 = Fixtures.pkey("p384_invalid") + assert_raise(OpenSSL::PKey::ECError) { key5.check_key } + # EC#private_key= is deprecated in 3.0 and won't work on OpenSSL 3.0 if !openssl?(3, 0, 0) key2.private_key += 1 @@ -98,10 +104,10 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase def test_sign_verify p256 = Fixtures.pkey("p256") data = "Sign me!" - signature = p256.sign("SHA1", data) - assert_equal true, p256.verify("SHA1", signature, data) + signature = p256.sign("SHA256", data) + assert_equal true, p256.verify("SHA256", signature, data) - signature0 = (<<~'end;').unpack("m")[0] + signature0 = (<<~'end;').unpack1("m") MEQCIEOTY/hD7eI8a0qlzxkIt8LLZ8uwiaSfVbjX2dPAvN11AiAQdCYx56Fq QdBp1B4sxJoA8jvODMMklMyBKVmudboA6A== end; @@ -199,7 +205,32 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase assert_equal pem, p256.export end + def test_ECPrivateKey_with_parameters + p256 = Fixtures.pkey("p256") + + # The format used by "openssl ecparam -name prime256v1 -genkey -outform PEM" + # + # "EC PARAMETERS" block should be ignored if it is followed by an + # "EC PRIVATE KEY" block + in_pem = <<~EOF + -----BEGIN EC PARAMETERS----- + BggqhkjOPQMBBw== + -----END EC PARAMETERS----- + -----BEGIN EC PRIVATE KEY----- + MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49 + AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt + CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg== + -----END EC PRIVATE KEY----- + EOF + + key = OpenSSL::PKey::EC.new(in_pem) + assert_same_ec p256, key + assert_equal p256.to_der, key.to_der + end + def test_ECPrivateKey_encrypted + omit_on_fips + p256 = Fixtures.pkey("p256") # key = abcdef pem = <<~EOF diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb index 4bb39ed4a6..61c55c60b2 100644 --- a/test/openssl/test_pkey_rsa.rb +++ b/test/openssl/test_pkey_rsa.rb @@ -80,10 +80,10 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase def test_sign_verify rsa1024 = Fixtures.pkey("rsa1024") data = "Sign me!" - signature = rsa1024.sign("SHA1", data) - assert_equal true, rsa1024.verify("SHA1", signature, data) + signature = rsa1024.sign("SHA256", data) + assert_equal true, rsa1024.verify("SHA256", signature, data) - signature0 = (<<~'end;').unpack("m")[0] + signature0 = (<<~'end;').unpack1("m") oLCgbprPvfhM4pjFQiDTFeWI9Sk+Og7Nh9TmIZ/xSxf2CGXQrptlwo7NQ28+ WA6YQo8jPH4hSuyWIM4Gz4qRYiYRkl5TDMUYob94zm8Si1HxEiS9354tzvqS zS8MLW2BtNPuTubMxTItHGTnOzo9sUg0LAHVFt8kHG2NfKAw/gQ= @@ -108,15 +108,20 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase salt_length: 20, mgf1_hash: "SHA1") # Defaults to PKCS #1 v1.5 padding => verification failure assert_equal false, key.verify("SHA256", sig_pss, data) + + # option type check + assert_raise_with_message(TypeError, /expected Hash/) { + key.sign("SHA256", data, ["x"]) + } end def test_sign_verify_raw key = Fixtures.pkey("rsa-1") data = "Sign me!" - hash = OpenSSL::Digest.digest("SHA1", data) - signature = key.sign_raw("SHA1", hash) - assert_equal true, key.verify_raw("SHA1", signature, hash) - assert_equal true, key.verify("SHA1", signature, data) + hash = OpenSSL::Digest.digest("SHA256", data) + signature = key.sign_raw("SHA256", hash) + assert_equal true, key.verify_raw("SHA256", signature, hash) + assert_equal true, key.verify("SHA256", signature, data) # Too long data assert_raise(OpenSSL::PKey::PKeyError) { @@ -129,9 +134,9 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase "rsa_pss_saltlen" => 20, "rsa_mgf1_md" => "SHA256" } - sig_pss = key.sign_raw("SHA1", hash, pssopts) - assert_equal true, key.verify("SHA1", sig_pss, data, pssopts) - assert_equal true, key.verify_raw("SHA1", sig_pss, hash, pssopts) + sig_pss = key.sign_raw("SHA256", hash, pssopts) + assert_equal true, key.verify("SHA256", sig_pss, data, pssopts) + assert_equal true, key.verify_raw("SHA256", sig_pss, hash, pssopts) end def test_sign_verify_raw_legacy diff --git a/test/openssl/test_provider.rb b/test/openssl/test_provider.rb new file mode 100644 index 0000000000..b0ffae9ce7 --- /dev/null +++ b/test/openssl/test_provider.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true +require_relative 'utils' +if defined?(OpenSSL) && defined?(OpenSSL::Provider) && !OpenSSL.fips_mode + +class OpenSSL::TestProvider < OpenSSL::TestCase + def test_openssl_provider_name_inspect + with_openssl <<-'end;' + provider = OpenSSL::Provider.load("default") + assert_equal("default", provider.name) + assert_not_nil(provider.inspect) + end; + end + + def test_openssl_provider_names + with_openssl <<-'end;' + base_provider = OpenSSL::Provider.load("base") + assert_equal(2, OpenSSL::Provider.provider_names.size) + assert_includes(OpenSSL::Provider.provider_names, "base") + + assert_equal(true, base_provider.unload) + assert_equal(1, OpenSSL::Provider.provider_names.size) + assert_not_includes(OpenSSL::Provider.provider_names, "base") + end; + end + + def test_unloaded_openssl_provider + with_openssl <<-'end;' + default_provider = OpenSSL::Provider.load("default") + assert_equal(true, default_provider.unload) + assert_raise(OpenSSL::Provider::ProviderError) { default_provider.name } + assert_raise(OpenSSL::Provider::ProviderError) { default_provider.unload } + end; + end + + def test_openssl_legacy_provider + with_openssl(<<-'end;') + begin + OpenSSL::Provider.load("legacy") + rescue OpenSSL::Provider::ProviderError + omit "Only for OpenSSL with legacy provider" + end + + algo = "RC4" + data = "a" * 1000 + key = OpenSSL::Random.random_bytes(16) + + # default provider does not support RC4 + cipher = OpenSSL::Cipher.new(algo) + cipher.encrypt + cipher.key = key + encrypted = cipher.update(data) + cipher.final + + other_cipher = OpenSSL::Cipher.new(algo) + other_cipher.decrypt + other_cipher.key = key + decrypted = other_cipher.update(encrypted) + other_cipher.final + + assert_equal(data, decrypted) + end; + end + + private + + # this is required because OpenSSL::Provider methods change global state + def with_openssl(code, **opts) + assert_separately(["-ropenssl"], <<~"end;", **opts) + #{code} + end; + end +end + +end diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index 5679ae77d7..1471b0cb36 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require_relative "utils" -if defined?(OpenSSL) +if defined?(OpenSSL::SSL) class OpenSSL::TestSSL < OpenSSL::SSLTestCase def test_bad_socket @@ -117,6 +117,30 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase } end + def test_socket_close_write + server_proc = proc do |ctx, ssl| + message = ssl.read + ssl.write(message) + ssl.close_write + ensure + ssl.close + end + + start_server(server_proc: server_proc) do |port| + ctx = OpenSSL::SSL::SSLContext.new + ssl = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port, context: ctx) + ssl.sync_close = true + ssl.connect + + message = "abc"*1024 + ssl.write message + ssl.close_write + assert_equal message, ssl.read + ensure + ssl&.close + end + end + def test_add_certificate ctx_proc = -> ctx { # Unset values set by start_server @@ -193,6 +217,24 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase } end + def test_read_with_timeout + omit "does not support timeout" unless IO.method_defined?(:timeout) + + start_server do |port| + server_connect(port) do |ssl| + str = +("x" * 100 + "\n") + ssl.syswrite(str) + assert_equal(str, ssl.sysread(str.bytesize)) + + ssl.timeout = 1 + assert_raise(IO::TimeoutError) {ssl.read(1)} + + ssl.syswrite(str) + assert_equal(str, ssl.sysread(str.bytesize)) + end + end + end + def test_getbyte start_server { |port| server_connect(port) { |ssl| @@ -481,6 +523,40 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase } end + def test_ca_file + start_server(ignore_listener_error: true) { |port| + # X509_STORE is shared; setting ca_file to SSLContext affects store + store = OpenSSL::X509::Store.new + assert_equal false, store.verify(@svr_cert) + + ctx = Tempfile.create("ca_cert.pem") { |f| + f.puts(@ca_cert.to_pem) + f.close + + ctx = OpenSSL::SSL::SSLContext.new + ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER + ctx.cert_store = store + ctx.ca_file = f.path + ctx.setup + ctx + } + assert_nothing_raised { + server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets } + } + assert_equal true, store.verify(@svr_cert) + } + end + + def test_ca_file_not_found + path = Tempfile.create("ca_cert.pem") { |f| f.path } + ctx = OpenSSL::SSL::SSLContext.new + ctx.ca_file = path + # OpenSSL >= 1.1.0: /no certificate or crl found/ + assert_raise(OpenSSL::SSL::SSLError) { + ctx.setup + } + end + def test_finished_messages server_finished = nil server_peer_finished = nil @@ -639,7 +715,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase assert_equal(true, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "xn--qdk4b9b")) end - # Comments in this test is excerpted from http://tools.ietf.org/html/rfc6125#page-27 + # Comments in this test is excerpted from https://www.rfc-editor.org/rfc/rfc6125#page-27 def test_post_connection_check_wildcard_san # case-insensitive ASCII comparison # RFC 6125, section 6.4.1 @@ -804,6 +880,54 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end end + def test_keylog_cb + pend "Keylog callback is not supported" if !openssl?(1, 1, 1) || libressl? + + prefix = 'CLIENT_RANDOM' + context = OpenSSL::SSL::SSLContext.new + context.min_version = context.max_version = OpenSSL::SSL::TLS1_2_VERSION + + cb_called = false + context.keylog_cb = proc do |_sock, line| + cb_called = true + assert_equal(prefix, line.split.first) + end + + start_server do |port| + server_connect(port, context) do |ssl| + ssl.puts "abc" + assert_equal("abc\n", ssl.gets) + assert_equal(true, cb_called) + end + end + + if tls13_supported? + prefixes = [ + 'SERVER_HANDSHAKE_TRAFFIC_SECRET', + 'EXPORTER_SECRET', + 'SERVER_TRAFFIC_SECRET_0', + 'CLIENT_HANDSHAKE_TRAFFIC_SECRET', + 'CLIENT_TRAFFIC_SECRET_0', + ] + context = OpenSSL::SSL::SSLContext.new + context.min_version = context.max_version = OpenSSL::SSL::TLS1_3_VERSION + cb_called = false + context.keylog_cb = proc do |_sock, line| + cb_called = true + assert_not_nil(prefixes.delete(line.split.first)) + end + + start_server do |port| + server_connect(port, context) do |ssl| + ssl.puts "abc" + assert_equal("abc\n", ssl.gets) + assert_equal(true, cb_called) + end + assert_equal(0, prefixes.size) + end + end + end + def test_tlsext_hostname fooctx = OpenSSL::SSL::SSLContext.new fooctx.cert = @cli_cert @@ -1331,9 +1455,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end def test_npn_protocol_selection_ary - pend "NPN is not supported" unless \ - OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) - pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1) + return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) advertised = ["http/1.1", "spdy/2"] ctx_proc = proc { |ctx| ctx.npn_protocols = advertised } @@ -1351,9 +1473,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end def test_npn_protocol_selection_enum - pend "NPN is not supported" unless \ - OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) - pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1) + return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) advertised = Object.new def advertised.each @@ -1375,9 +1495,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end def test_npn_protocol_selection_cancel - pend "NPN is not supported" unless \ - OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) - pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1) + return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] } start_server_version(:TLSv1_2, ctx_proc) { |port| @@ -1388,9 +1506,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end def test_npn_advertised_protocol_too_long - pend "NPN is not supported" unless \ - OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) - pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1) + return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["a" * 256] } start_server_version(:TLSv1_2, ctx_proc) { |port| @@ -1401,9 +1517,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end def test_npn_selected_protocol_too_long - pend "NPN is not supported" unless \ - OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) - pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1) + return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] } start_server_version(:TLSv1_2, ctx_proc) { |port| @@ -1817,6 +1931,19 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase sock2.close end + def test_export_keying_material + start_server do |port| + cli_ctx = OpenSSL::SSL::SSLContext.new + server_connect(port, cli_ctx) do |ssl| + assert_instance_of(String, ssl.export_keying_material('ttls keying material', 64)) + assert_operator(64, :==, ssl.export_keying_material('ttls keying material', 64).b.length) + assert_operator(8, :==, ssl.export_keying_material('ttls keying material', 8).b.length) + assert_operator(5, :==, ssl.export_keying_material('test', 5, 'context').b.length) + ssl.puts "abc"; ssl.gets # workaround to make tests work on windows + end + end + end + private def start_server_version(version, ctx_proc = nil, diff --git a/test/openssl/test_ssl_session.rb b/test/openssl/test_ssl_session.rb index b72b10d3b5..89cf672a7b 100644 --- a/test/openssl/test_ssl_session.rb +++ b/test/openssl/test_ssl_session.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require_relative "utils" -if defined?(OpenSSL) +if defined?(OpenSSL::SSL) class OpenSSL::TestSSLSession < OpenSSL::SSLTestCase def test_session @@ -22,7 +22,7 @@ class OpenSSL::TestSSLSession < OpenSSL::SSLTestCase assert_match(/\A-----BEGIN SSL SESSION PARAMETERS-----/, pem) assert_match(/-----END SSL SESSION PARAMETERS-----\Z/, pem) pem.gsub!(/-----(BEGIN|END) SSL SESSION PARAMETERS-----/, '').gsub!(/[\r\n]+/m, '') - assert_equal(session.to_der, pem.unpack('m*')[0]) + assert_equal(session.to_der, pem.unpack1('m')) assert_not_nil(session.to_text) } end diff --git a/test/openssl/test_ts.rb b/test/openssl/test_ts.rb index 7cb1a1fe8e..ac0469ad56 100644 --- a/test/openssl/test_ts.rb +++ b/test/openssl/test_ts.rb @@ -323,6 +323,8 @@ _end_of_pem_ resp = fac.create_timestamp(ee_key, ts_cert_ee, req) assert_equal(OpenSSL::Timestamp::Response::GRANTED, resp.status) assert_equal("1.2.3.4.6", resp.token_info.policy_id) + + assert_match(/1\.2\.3\.4\.6/, resp.to_text) end def test_response_bad_purpose diff --git a/test/openssl/test_x509cert.rb b/test/openssl/test_x509cert.rb index d696b98c0a..64805504de 100644 --- a/test/openssl/test_x509cert.rb +++ b/test/openssl/test_x509cert.rb @@ -173,13 +173,14 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase end def test_sign_and_verify_rsa_sha1 - cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: "sha1") + cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: "SHA1") assert_equal(false, cert.verify(@rsa1024)) assert_equal(true, cert.verify(@rsa2048)) assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) }) assert_equal(false, certificate_error_returns_false { cert.verify(@dsa512) }) cert.serial = 2 assert_equal(false, cert.verify(@rsa2048)) + rescue OpenSSL::X509::CertificateError # RHEL 9 disables SHA1 end def test_sign_and_verify_rsa_md5 @@ -229,6 +230,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase # SHA1 is allowed from OpenSSL 1.0.0 (0.9.8 requires DSS1) cert = issue_cert(@ca, @dsa256, 1, [], nil, nil, digest: "sha1") assert_equal("dsaWithSHA1", cert.signature_algorithm) + rescue OpenSSL::X509::CertificateError # RHEL 9 disables SHA1 end def test_check_private_key diff --git a/test/openssl/test_x509crl.rb b/test/openssl/test_x509crl.rb index bcdb0a697c..146ee07309 100644 --- a/test/openssl/test_x509crl.rb +++ b/test/openssl/test_x509crl.rb @@ -20,7 +20,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) crl = issue_crl([], 1, now, now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA1')) + cert, @rsa2048, OpenSSL::Digest.new('SHA256')) assert_equal(1, crl.version) assert_equal(cert.issuer.to_der, crl.issuer.to_der) assert_equal(now, crl.last_update) @@ -57,7 +57,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase ] cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA1')) + cert, @rsa2048, OpenSSL::Digest.new('SHA256')) revoked = crl.revoked assert_equal(5, revoked.size) assert_equal(1, revoked[0].serial) @@ -98,7 +98,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase revoke_info = (1..1000).collect{|i| [i, now, 0] } crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA1')) + cert, @rsa2048, OpenSSL::Digest.new('SHA256')) revoked = crl.revoked assert_equal(1000, revoked.size) assert_equal(1, revoked[0].serial) @@ -124,7 +124,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase cert = issue_cert(@ca, @rsa2048, 1, cert_exts, nil, nil) crl = issue_crl([], 1, Time.now, Time.now+1600, crl_exts, - cert, @rsa2048, OpenSSL::Digest.new('SHA1')) + cert, @rsa2048, OpenSSL::Digest.new('SHA256')) exts = crl.extensions assert_equal(3, exts.size) assert_equal("1", exts[0].value) @@ -160,24 +160,24 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase assert_equal(false, exts[2].critical?) no_ext_crl = issue_crl([], 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA1')) + cert, @rsa2048, OpenSSL::Digest.new('SHA256')) assert_equal nil, no_ext_crl.authority_key_identifier end def test_crlnumber cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) crl = issue_crl([], 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA1')) + cert, @rsa2048, OpenSSL::Digest.new('SHA256')) assert_match(1.to_s, crl.extensions[0].value) assert_match(/X509v3 CRL Number:\s+#{1}/m, crl.to_text) crl = issue_crl([], 2**32, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA1')) + cert, @rsa2048, OpenSSL::Digest.new('SHA256')) assert_match((2**32).to_s, crl.extensions[0].value) assert_match(/X509v3 CRL Number:\s+#{2**32}/m, crl.to_text) crl = issue_crl([], 2**100, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA1')) + cert, @rsa2048, OpenSSL::Digest.new('SHA256')) assert_match(/X509v3 CRL Number:\s+#{2**100}/m, crl.to_text) assert_match((2**100).to_s, crl.extensions[0].value) end @@ -185,7 +185,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase def test_sign_and_verify cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) crl = issue_crl([], 1, Time.now, Time.now+1600, [], - cert, @rsa2048, OpenSSL::Digest.new('SHA1')) + cert, @rsa2048, OpenSSL::Digest.new('SHA256')) assert_equal(false, crl.verify(@rsa1024)) assert_equal(true, crl.verify(@rsa2048)) assert_equal(false, crl_error_returns_false { crl.verify(@dsa256) }) @@ -195,7 +195,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase cert = issue_cert(@ca, @dsa512, 1, [], nil, nil) crl = issue_crl([], 1, Time.now, Time.now+1600, [], - cert, @dsa512, OpenSSL::Digest.new('SHA1')) + cert, @dsa512, OpenSSL::Digest.new('SHA256')) assert_equal(false, crl_error_returns_false { crl.verify(@rsa1024) }) assert_equal(false, crl_error_returns_false { crl.verify(@rsa2048) }) assert_equal(false, crl.verify(@dsa256)) diff --git a/test/openssl/test_x509ext.rb b/test/openssl/test_x509ext.rb index 7ad010d1ed..59a41ed736 100644 --- a/test/openssl/test_x509ext.rb +++ b/test/openssl/test_x509ext.rb @@ -50,24 +50,41 @@ class OpenSSL::TestX509Extension < OpenSSL::TestCase cdp = ef.create_extension("crlDistributionPoints", "@crlDistPts") assert_equal(false, cdp.critical?) assert_equal("crlDistributionPoints", cdp.oid) - assert_match(%{URI:http://www\.example\.com/crl}, cdp.value) - assert_match( - %r{URI:ldap://ldap\.example\.com/cn=ca\?certificateRevocationList;binary}, - cdp.value) + assert_include(cdp.value, "URI:http://www.example.com/crl") + assert_include(cdp.value, + "URI:ldap://ldap.example.com/cn=ca?certificateRevocationList;binary") cdp = ef.create_extension("crlDistributionPoints", "critical, @crlDistPts") assert_equal(true, cdp.critical?) assert_equal("crlDistributionPoints", cdp.oid) - assert_match(%{URI:http://www.example.com/crl}, cdp.value) - assert_match( - %r{URI:ldap://ldap.example.com/cn=ca\?certificateRevocationList;binary}, - cdp.value) + assert_include(cdp.value, "URI:http://www.example.com/crl") + assert_include(cdp.value, + "URI:ldap://ldap.example.com/cn=ca?certificateRevocationList;binary") cp = ef.create_extension("certificatePolicies", "@certPolicies") assert_equal(false, cp.critical?) assert_equal("certificatePolicies", cp.oid) - assert_match(%r{2.23.140.1.2.1}, cp.value) - assert_match(%r{http://cps.example.com}, cp.value) + assert_include(cp.value, "2.23.140.1.2.1") + assert_include(cp.value, "http://cps.example.com") + end + + def test_factory_create_extension_sn_ln + ef = OpenSSL::X509::ExtensionFactory.new + bc_sn = ef.create_extension("basicConstraints", "critical, CA:TRUE, pathlen:2") + bc_ln = ef.create_extension("X509v3 Basic Constraints", "critical, CA:TRUE, pathlen:2") + assert_equal(@basic_constraints.to_der, bc_sn.to_der) + assert_equal(@basic_constraints.to_der, bc_ln.to_der) + end + + def test_factory_create_extension_oid + ef = OpenSSL::X509::ExtensionFactory.new + ef.config = OpenSSL::Config.parse(<<~_end_of_cnf_) + [basic_constraints] + cA = BOOLEAN:TRUE + pathLenConstraint = INTEGER:2 + _end_of_cnf_ + bc_oid = ef.create_extension("2.5.29.19", "ASN1:SEQUENCE:basic_constraints", true) + assert_equal(@basic_constraints.to_der, bc_oid.to_der) end def test_dup diff --git a/test/openssl/test_x509req.rb b/test/openssl/test_x509req.rb index ee9c678fbb..b98754b8c8 100644 --- a/test/openssl/test_x509req.rb +++ b/test/openssl/test_x509req.rb @@ -23,31 +23,26 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase end def test_public_key - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) + req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) assert_equal(@rsa1024.public_key.to_der, req.public_key.to_der) req = OpenSSL::X509::Request.new(req.to_der) assert_equal(@rsa1024.public_key.to_der, req.public_key.to_der) - req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA1')) + req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA256')) assert_equal(@dsa512.public_key.to_der, req.public_key.to_der) req = OpenSSL::X509::Request.new(req.to_der) assert_equal(@dsa512.public_key.to_der, req.public_key.to_der) end def test_version - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) + req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) assert_equal(0, req.version) req = OpenSSL::X509::Request.new(req.to_der) assert_equal(0, req.version) - - req = issue_csr(1, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) - assert_equal(1, req.version) - req = OpenSSL::X509::Request.new(req.to_der) - assert_equal(1, req.version) end def test_subject - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) + req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) assert_equal(@dn.to_der, req.subject.to_der) req = OpenSSL::X509::Request.new(req.to_der) assert_equal(@dn.to_der, req.subject.to_der) @@ -78,9 +73,9 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase OpenSSL::X509::Attribute.new("msExtReq", attrval), ] - req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) + req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) attrs.each{|attr| req0.add_attribute(attr) } - req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) + req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) req1.attributes = attrs assert_equal(req0.to_der, req1.to_der) @@ -106,8 +101,9 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase assert_equal(false, req.verify(@rsa2048)) assert_equal(false, request_error_returns_false { req.verify(@dsa256) }) assert_equal(false, request_error_returns_false { req.verify(@dsa512) }) - req.version = 1 + req.subject = OpenSSL::X509::Name.parse("/C=JP/CN=FooBarFooBar") assert_equal(false, req.verify(@rsa1024)) + rescue OpenSSL::X509::RequestError # RHEL 9 disables SHA1 end def test_sign_and_verify_rsa_md5 @@ -122,7 +118,7 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase end def test_sign_and_verify_dsa - req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA1')) + req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA256')) assert_equal(false, request_error_returns_false { req.verify(@rsa1024) }) assert_equal(false, request_error_returns_false { req.verify(@rsa2048) }) assert_equal(false, req.verify(@dsa256)) @@ -137,14 +133,14 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase end def test_dup - req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) + req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256')) assert_equal(req.to_der, req.dup.to_der) end def test_eq - req1 = issue_csr(0, @dn, @rsa1024, "sha1") - req2 = issue_csr(0, @dn, @rsa1024, "sha1") - req3 = issue_csr(0, @dn, @rsa1024, "sha256") + req1 = issue_csr(0, @dn, @rsa1024, "sha256") + req2 = issue_csr(0, @dn, @rsa1024, "sha256") + req3 = issue_csr(0, @dn, @rsa1024, "sha512") assert_equal false, req1 == 12345 assert_equal true, req1 == req2 diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb index 4ebcb9837b..f6c84eef67 100644 --- a/test/openssl/utils.rb +++ b/test/openssl/utils.rb @@ -1,38 +1,13 @@ # frozen_string_literal: true begin require "openssl" - - # Disable FIPS mode for tests for installations - # where FIPS mode would be enabled by default. - # Has no effect on all other installations. - OpenSSL.fips_mode=false rescue LoadError end -# Compile OpenSSL with crypto-mdebug and run this test suite with OSSL_MDEBUG=1 -# environment variable to enable memory leak check. -if ENV["OSSL_MDEBUG"] == "1" - if OpenSSL.respond_to?(:print_mem_leaks) - OpenSSL.mem_check_start - - END { - GC.start - case OpenSSL.print_mem_leaks - when nil - warn "mdebug: check what is printed" - when true - raise "mdebug: memory leaks detected" - end - } - else - warn "OSSL_MDEBUG=1 is specified but OpenSSL is not built with crypto-mdebug" - end -end - require "test/unit" +require "core_assertions" require "tempfile" require "socket" -require "envutil" if defined?(OpenSSL) @@ -131,11 +106,12 @@ module OpenSSL::TestUtils end end - def openssl?(major = nil, minor = nil, fix = nil, patch = 0) + def openssl?(major = nil, minor = nil, fix = nil, patch = 0, status = 0) return false if OpenSSL::OPENSSL_VERSION.include?("LibreSSL") return true unless major OpenSSL::OPENSSL_VERSION_NUMBER >= - major * 0x10000000 + minor * 0x100000 + fix * 0x1000 + patch * 0x10 + major * 0x10000000 + minor * 0x100000 + fix * 0x1000 + patch * 0x10 + + status * 0x1 end def libressl?(major = nil, minor = nil, fix = nil) @@ -148,6 +124,7 @@ end class OpenSSL::TestCase < Test::Unit::TestCase include OpenSSL::TestUtils extend OpenSSL::TestUtils + include Test::Unit::CoreAssertions def setup if ENV["OSSL_GC_STRESS"] == "1" @@ -162,6 +139,30 @@ class OpenSSL::TestCase < Test::Unit::TestCase # OpenSSL error stack must be empty assert_equal([], OpenSSL.errors) end + + # Omit the tests in FIPS. + # + # For example, the password based encryption used in the PEM format uses MD5 + # for deriving the encryption key from the password, and MD5 is not + # FIPS-approved. + # + # See https://github.com/openssl/openssl/discussions/21830#discussioncomment-6865636 + # for details. + def omit_on_fips + return unless OpenSSL.fips_mode + + omit <<~MESSAGE + Only for OpenSSL non-FIPS with the following possible reasons: + * A testing logic is non-FIPS specific. + * An encryption used in the test is not FIPS-approved. + MESSAGE + end + + def omit_on_non_fips + return if OpenSSL.fips_mode + + omit "Only for OpenSSL FIPS" + end end class OpenSSL::SSLTestCase < OpenSSL::TestCase |