-
Bug
-
Resolution: Fixed
-
P4
-
None
-
None
-
b14
When the KeyStore is concurrently modified, keyStore.getEntry might fail or return a non-matching private key / certificate pair. This is because PKCS12KeyStore.engineGetEntry calls engineGetKey and engineGetCertificateChain without any synchronization with engineSetEntry.
This is a problem for the PKIX KeyManager (sun.security.ssl.X509KeyManagerImpl), which retrieves the entries from the KeyStore on every handshake. Currently this only impacts the handshakes that are running at the same time as the keystore update, but in JDK-8322767 we are exploring caching the entries on first use, and caching the incorrect entries would affect all handshakes until the next keystore update.
To reproduce:
- Create a PKCS12 key store, and 2 KeyStore.PrivateKeyEntry instances, one with EC key/certificate, one with RSA key/certificate.
- create one thread that calls setEntry in a loop using the same alias, but alternating between the entries:
- in another thread call getEntry in a loop
see the attached reproducer (incomplete, needs keys).
The code quickly fails with the following exception:
Exception in thread "main" java.lang.IllegalArgumentException: private key algorithm does not match algorithm of public key in end entity certificate (at index 0)
at java.base/java.security.KeyStore$PrivateKeyEntry.<init>(KeyStore.java:552)
at java.base/sun.security.pkcs12.PKCS12KeyStore.engineGetEntry(PKCS12KeyStore.java:1338)
at java.base/sun.security.util.KeyStoreDelegator.engineGetEntry(KeyStoreDelegator.java:174)
at java.base/java.security.KeyStore.getEntry(KeyStore.java:1576)
Reproducer:
public static final String TEST = "test";
private static void test(KeyStore ks, KeyStore.PrivateKeyEntry ec,
KeyStore.PrivateKeyEntry rsa,
KeyStore.PasswordProtection protParam)
throws Exception {
ks.setEntry(TEST, ec, protParam);
new Thread(()->{while(true) {
try {
ks.setEntry(TEST, ec, protParam);
ks.setEntry(TEST, rsa, protParam);
} catch (KeyStoreException e) {
e.printStackTrace();
System.exit(1);
}
}
}).start();
while(true) {
ks.getEntry(TEST, protParam);
}
}
This is a problem for the PKIX KeyManager (sun.security.ssl.X509KeyManagerImpl), which retrieves the entries from the KeyStore on every handshake. Currently this only impacts the handshakes that are running at the same time as the keystore update, but in JDK-8322767 we are exploring caching the entries on first use, and caching the incorrect entries would affect all handshakes until the next keystore update.
To reproduce:
- Create a PKCS12 key store, and 2 KeyStore.PrivateKeyEntry instances, one with EC key/certificate, one with RSA key/certificate.
- create one thread that calls setEntry in a loop using the same alias, but alternating between the entries:
- in another thread call getEntry in a loop
see the attached reproducer (incomplete, needs keys).
The code quickly fails with the following exception:
Exception in thread "main" java.lang.IllegalArgumentException: private key algorithm does not match algorithm of public key in end entity certificate (at index 0)
at java.base/java.security.KeyStore$PrivateKeyEntry.<init>(KeyStore.java:552)
at java.base/sun.security.pkcs12.PKCS12KeyStore.engineGetEntry(PKCS12KeyStore.java:1338)
at java.base/sun.security.util.KeyStoreDelegator.engineGetEntry(KeyStoreDelegator.java:174)
at java.base/java.security.KeyStore.getEntry(KeyStore.java:1576)
Reproducer:
public static final String TEST = "test";
private static void test(KeyStore ks, KeyStore.PrivateKeyEntry ec,
KeyStore.PrivateKeyEntry rsa,
KeyStore.PasswordProtection protParam)
throws Exception {
ks.setEntry(TEST, ec, protParam);
new Thread(()->{while(true) {
try {
ks.setEntry(TEST, ec, protParam);
ks.setEntry(TEST, rsa, protParam);
} catch (KeyStoreException e) {
e.printStackTrace();
System.exit(1);
}
}
}).start();
while(true) {
ks.getEntry(TEST, protParam);
}
}
- relates to
-
JDK-8322767 TLS full handshake is slow with PKCS12KeyStore and X509KeyManagerImpl
- Open