Skip to content

Validate the private key before returning the KEM decapsulator #1005

@farshadasl

Description

@farshadasl

engineNewDecapsulator implementation accepts any non-null PrivateKey object, regardless of whether it is the correct algorithm or holds valid key material. The test passes a dummy key (likely with the wrong algorithm name or garbage encoding), and your code proceeds to create the MLKEMDecapsulator instead of rejecting it.

throws InvalidAlgorithmParameterException, InvalidKeyException {

Test:

import javax.crypto.KEM;
import java.security.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class KemMethodTest {

    public static void main(String[] args) {
        System.out.println("Starting Standalone KEM Test...");

        // 1. Simulate @TestData: Find all KEM algorithms available on this JVM
        List<Map.Entry<Provider, String>> testData = getKemProviderAlgEntries();

        if (testData.isEmpty()) {
            System.out.println("No KEM Providers found. (Are you running Java 21+?)");
            return;
        }

        int passCount = 0;
        int failCount = 0;

        // 2. Define the Invalid Key
        PrivateKey invalidKey = new InvalidPrivateKey();

        // 3. Iterate and Test
        for (Map.Entry<Provider, String> entry : testData) {
            Provider provider = entry.getKey();
            String alg = entry.getValue();

            System.out.printf("Testing Algorithm: [%s] Provider: [%s]... ", alg, provider.getName());

            try {
                // Equivalent to: KEM.getInstance(...)
                KEM kem = KEM.getInstance(alg, provider);

                // Equivalent to: Assert.assertThrows(...)
                try {
                    kem.newDecapsulator(invalidKey);

                    // If we reach here, no exception was thrown -> FAIL
                    System.out.println("FAILED");
                    System.err.println("  Expected InvalidKeyException, but method returned successfully.");
                    failCount++;
                } catch (InvalidKeyException e) {
                    // Exception caught -> PASS
                    System.out.println("PASSED");
                    passCount++;
                } catch (Exception e) {
                    // Wrong exception type -> FAIL
                    System.out.println("FAILED");
                    System.err.println("  Expected InvalidKeyException, but caught " + e.getClass().getSimpleName());
                    failCount++;
                }

            } catch (NoSuchAlgorithmException e) {
                System.out.println("SKIPPED (Algorithm not actually available)");
            }
        }

        System.out.println("---------------------------------------------------");
        System.out.printf("Test Complete. Passed: %d, Failed: %d%n", passCount, failCount);

        if (failCount > 0) System.exit(1); // Exit with error code if failures occurred
    }

    // --- Helpers and Mocks ---

    /**
     * Mocks the invalid private key.
     */
    static class InvalidPrivateKey implements PrivateKey {
        @Override public String getAlgorithm() { return "TotallyInvalidAlgo"; }
        @Override public String getFormat() { return "RAW"; }
        @Override public byte[] getEncoded() { return new byte[] { 0x00, 0x01, 0x02 }; } // Junk data
    }

    /**
     * Scans installed Security Providers to find KEM implementations.
     * Equivalent to populating @TestData("kemProviderAlgEntryList")
     */
    private static List<Map.Entry<Provider, String>> getKemProviderAlgEntries() {
        List<Map.Entry<Provider, String>> list = new ArrayList<>();

        for (Provider p : Security.getProviders()) {
            for (Provider.Service s : p.getServices()) {
                if ("KEM".equals(s.getType())) {
                    list.add(Map.entry(p, s.getAlgorithm()));
                }
            }
        }
        return list;
    }
}

Result:

Starting Standalone KEM Test...
Testing Algorithm: [ML-KEM-1024] Provider: [OpenJCEPlus]... FAILED
  Expected InvalidKeyException, but method returned successfully.
Testing Algorithm: [ML-KEM-768] Provider: [OpenJCEPlus]... FAILED
  Expected InvalidKeyException, but method returned successfully.
Testing Algorithm: [ML-KEM-512] Provider: [OpenJCEPlus]... FAILED
  Expected InvalidKeyException, but method returned successfully.
Testing Algorithm: [ML-KEM-1024] Provider: [SunJCE]... PASSED
Testing Algorithm: [ML-KEM-768] Provider: [SunJCE]... PASSED
Testing Algorithm: [ML-KEM-512] Provider: [SunJCE]... PASSED
Testing Algorithm: [ML-KEM] Provider: [SunJCE]... PASSED
Testing Algorithm: [DHKEM] Provider: [SunJCE]... PASSED
---------------------------------------------------
Test Complete. Passed: 5, Failed: 3

@johnpeck-us-ibm @jasonkatonica

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions