Uploaded image for project: 'OpenJDK'
  1. OpenJDK
  2. OPENJDK-4545

nssadapter should not use a single PKCS #11 session for multi-thread operations

XMLWordPrintable

    • nssadapter-concurrency-issue
    • False
    • Hide

      None

      Show
      None
    • False
    • OPENJDK-1043 - FIPS Epics
    • Important

      nssadapter v0.1.0 has a concurrency issue, where a single PKCS #11 session is being shared among different threads that can use it at the same time, leading to several errors including crashes. That session holds the wrapping key employed for the import/export operations, and is necessary to handle the key lifespan. However, we shouldn't use that session for the import/export operation. Instead, we should use the session passed to C_CreateObject (when importing) or C_GetAttributeValue (when exporting), as these are already meant to properly handle the concurrent operations.

      Steps to reproduce

      1. Drop the test case file:
        mkdir -p /tmp/fipstest; cat <<'EOF' >/tmp/fipstest/Main.java
        import javax.crypto.Cipher;
        import javax.crypto.KeyGenerator;
        import javax.crypto.spec.SecretKeySpec;
        import java.util.concurrent.ExecutorService;
        import java.util.concurrent.Executors;
        
        public final class Main {
            private static final int PARALLELISM = 10;
            private static final String ALGORITHM = "AES";
            private static final SecretKeySpec KEY_SPEC = new SecretKeySpec(
                    "12345678901234567890123456789012".getBytes(), ALGORITHM);
        
            private static void importSecretKey() {
                try {
                    Cipher c = Cipher.getInstance(ALGORITHM);
                    c.init(Cipher.ENCRYPT_MODE, KEY_SPEC);
                } catch (Throwable t) {
                    t.printStackTrace();
                    System.exit(1);
                }
            }
        
            private static void exportSecretKey() {
                try {
                    KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
                    kg.generateKey().getEncoded();
                } catch (Throwable t) {
                    t.printStackTrace();
                    System.exit(1);
                }
            }
        
            public static void main(String[] args) {
                try (ExecutorService pool = Executors.newFixedThreadPool(PARALLELISM)) {
                    for (int t = 0; t < PARALLELISM * 100; t++) {
                        pool.submit(Main::importSecretKey);
                        pool.submit(Main::exportSecretKey);
                    }
                }
            }
        }
        EOF
        
      2. Choose an option to repeatedly run the test (usually fails at the first attempt):
        • On a FIPS-mode enabled system, directly:
          while java /tmp/fipstest/Main.java
              do echo Did not fail, retrying...; done
          
        • On a FIPS-mode enabled system, containerized:
          while podman run --name=fipstest --rm \
              -v/tmp/fipstest/Main.java:/home/default/Main.java:ro,Z,bind,private \
              registry.access.redhat.com/ubi9/openjdk-25 java Main.java
              do echo Did not fail, retrying...; done
          
          • If the container hangs, you can kill it with podman kill fipstest from another terminal
        • On a standard RHEL/Fedora system, simulating a FIPS system to the container's userspace layer:
          echo 1 >/tmp/fipstest/1
          while podman run --name=fipstest --rm \
              -v/tmp/fipstest/1:/proc/sys/crypto/fips_enabled:ro,Z,bind,private \
              -v/tmp/fipstest/Main.java:/home/default/Main.java:ro,Z,bind,private \
              registry.access.redhat.com/ubi9/openjdk-25 java Main.java
              do echo Did not fail, retrying...; done
          
          • If the container hangs, you can kill it with podman kill fipstest from another terminal
      3. Remove the created files and the pulled container image:
        rm -rf /tmp/fipstest
        podman rmi registry.access.redhat.com/ubi9/openjdk-25
        

      In addition to the provided steps to reproduce, this issue can also be triggered by ssl-tests in FIPS, as follows:

      git clone https://github.com/rh-openjdk/ssl-tests && cd ssl-tests
      make clean ssl-tests-build certgen_all
      while SSLTESTS_SSL_CONFIG_FILTER=SunJSSE,Default,TLSv1.3,TLS_AES_256_GCM_SHA384 make ssl-tests; do echo Did not fail, retrying...; done
      

      Expected behavior

      No errors occur, the test is indefinitely run, and the shell keeps printing Did not fail, retrying....

      Actual behavior

      Depending on the execution, several different errors occur, ranging from SIGSEGV crashes in NSS to other PKCS #11 errors reported as sun.security.pkcs11.wrapper.PKCS11Exception (CKR_OPERATION_NOT_INITIALIZED, CKR_OPERATION_ACTIVE, CKR_WRAPPED_KEY_INVALID, CKR_GENERAL_ERROR, CKR_BUFFER_TOO_SMALL).

              fferrari@redhat.com Francisco Ferrari Bihurriet
              fferrari@redhat.com Francisco Ferrari Bihurriet
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated: