diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb index c9b5f56f7..544d9e0b3 100644 --- a/test/openssl/test_pkey.rb +++ b/test/openssl/test_pkey.rb @@ -307,6 +307,52 @@ def test_ml_kem assert_equal(shared_secret, privkey.decapsulate(ciphertext)) end + def test_dhkem_x25519 + # DHKEM (RFC 9180) and the X25519/X448 curves are not FIPS-approved; the + # KEM is built into the default provider only, not the FIPS module. + omit_on_fips + # EVP_KEM-X25519 / EVP_KEM-X448 were added in OpenSSL 3.2, but the DHKEM + # operation defaults correctly (without an explicit OSSL_KEM_PARAM_OPERATION) + # only since OpenSSL 3.5. + omit "DHKEM is not supported" unless openssl?(3, 5, 0) + + pkey = OpenSSL::PKey.generate_key("X25519") + raw_public_key = pkey.raw_public_key + raw_private_key = pkey.raw_private_key + + assert_match(/type_name=X25519/, pkey.inspect) + assert_equal(32, raw_public_key.bytesize) # Npk + assert_equal(32, raw_private_key.bytesize) # Nsk + + pubkey = OpenSSL::PKey.new_raw_public_key("X25519", raw_public_key) + ciphertext, shared_secret = pubkey.encapsulate + assert_equal(32, ciphertext.bytesize) # Nenc + assert_equal(32, shared_secret.bytesize) # Nsecret + assert_equal(shared_secret, pkey.decapsulate(ciphertext)) + + privkey = OpenSSL::PKey.new_raw_private_key("X25519", raw_private_key) + assert_equal(shared_secret, privkey.decapsulate(ciphertext)) + end + + def test_dhkem_ec + # DHKEM (RFC 9180) is built into the default provider only, not the FIPS + # module. + omit_on_fips + # EVP_KEM-EC (RFC 9180 DHKEM over NIST curves) was added in OpenSSL 3.2, but + # the DHKEM operation defaults correctly (without an explicit + # OSSL_KEM_PARAM_OPERATION) only since OpenSSL 3.5. + omit "DHKEM is not supported" unless openssl?(3, 5, 0) + + pkey = OpenSSL::PKey::EC.generate("prime256v1") + assert_match(/type_name=EC/, pkey.inspect) + + pubkey = OpenSSL::PKey.read(pkey.public_to_der) + ciphertext, shared_secret = pubkey.encapsulate + assert_equal(65, ciphertext.bytesize) # Nenc + assert_equal(32, shared_secret.bytesize) # Nsecret + assert_equal(shared_secret, pkey.decapsulate(ciphertext)) + end + def test_raw_initialize_errors 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") }