F-4356: commit WKS entries only after HMAC verification in engineLoad
parent
865c769427
commit
801e0eed1a
|
|
@ -24,6 +24,7 @@ package com.wolfssl.provider.jce;
|
|||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
|
@ -2348,6 +2349,12 @@ public class WolfSSLKeyStore extends KeyStoreSpi {
|
|||
WKSSecretKey sKeyEntry = null;
|
||||
WKSCertificate certEntry = null;
|
||||
|
||||
/* Parse entries into a local map first. They are only committed
|
||||
* into the shared this.entries map after the HMAC integrity check
|
||||
* passes, so a failed or tampered load never exposes unverified
|
||||
* entries to engineGetKey()/engineGetCertificate() callers. */
|
||||
Map<String, Object> loadedEntries = new LinkedHashMap<String, Object>();
|
||||
|
||||
log("loading KeyStore from InputStream");
|
||||
|
||||
/* Clear any cached KEK entries from previous keystore */
|
||||
|
|
@ -2431,19 +2438,19 @@ public class WolfSSLKeyStore extends KeyStoreSpi {
|
|||
case WKS_ENTRY_ID_PRIVATE_KEY:
|
||||
log("loading PrivateKey: " + alias);
|
||||
keyEntry = new WKSPrivateKey(encodedEntry);
|
||||
entries.put(alias, keyEntry);
|
||||
loadedEntries.put(alias, keyEntry);
|
||||
break;
|
||||
|
||||
case WKS_ENTRY_ID_SECRET_KEY:
|
||||
log("loading SecretKey: " + alias);
|
||||
sKeyEntry = new WKSSecretKey(encodedEntry);
|
||||
entries.put(alias, sKeyEntry);
|
||||
loadedEntries.put(alias, sKeyEntry);
|
||||
break;
|
||||
|
||||
case WKS_ENTRY_ID_CERTIFICATE:
|
||||
log("loading Certificate: " + alias);
|
||||
certEntry = new WKSCertificate(encodedEntry);
|
||||
entries.put(alias, certEntry);
|
||||
loadedEntries.put(alias, certEntry);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -2510,6 +2517,11 @@ public class WolfSSLKeyStore extends KeyStoreSpi {
|
|||
"no password provided");
|
||||
}
|
||||
|
||||
/* Commit parsed entries into the shared map, replacing any
|
||||
* previous contents */
|
||||
this.entries.clear();
|
||||
this.entries.putAll(loadedEntries);
|
||||
|
||||
} finally {
|
||||
if (dis != null) {
|
||||
dis.close();
|
||||
|
|
|
|||
|
|
@ -458,6 +458,50 @@ public class WolfSSLKeyStoreTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A WKS load that fails its HMAC integrity check must not expose the
|
||||
* parsed entries. A KeyStore already initialized by a prior successful
|
||||
* load keeps initialized == true, so getCertificate() stays reachable
|
||||
* after a failed second load. Entries from the failed load must not be
|
||||
* visible.
|
||||
*/
|
||||
@Test
|
||||
public void testEngineLoadFailureDoesNotExposeEntries()
|
||||
throws Exception {
|
||||
|
||||
Assume.assumeTrue("test certificate not available",
|
||||
serverCertRsa != null);
|
||||
|
||||
char[] pass = storePass.toCharArray();
|
||||
|
||||
/* Build a valid WKS blob, then tamper the trailing HMAC so the
|
||||
* integrity check fails while the entries still parse. */
|
||||
KeyStore src = KeyStore.getInstance("WKS", "wolfJCE");
|
||||
src.load(null, pass);
|
||||
src.setCertificateEntry("evil", serverCertRsa);
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
src.store(bos, pass);
|
||||
byte[] tampered = bos.toByteArray();
|
||||
tampered[tampered.length - 1] ^= 0x01;
|
||||
|
||||
/* Initialize the victim with an empty load so it stays usable
|
||||
* after the failed load below. */
|
||||
KeyStore victim = KeyStore.getInstance("WKS", "wolfJCE");
|
||||
victim.load(null, pass);
|
||||
|
||||
try {
|
||||
victim.load(new ByteArrayInputStream(tampered), pass);
|
||||
fail("tampered WKS should fail the integrity check");
|
||||
} catch (IOException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
assertNull("failed load must not expose an entry",
|
||||
victim.getCertificate("evil"));
|
||||
assertFalse("failed load must not expose an alias",
|
||||
victim.containsAlias("evil"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create PrivateKey and Certificate objects based on files.
|
||||
|
|
|
|||
Loading…
Reference in New Issue