Fix cache consistency on key overwrite (#97)
Android allows applications to generate a new key using an existing alias without explicitly calling `deleteKey` first. In this scenario, the new key effectively replaces the old one. As a simulator, we must strictly follow this logic to prevent returning stale data. Previously, `KeyMintSecurityLevelInterceptor` did not enforce mutual exclusion between the software key cache (`generatedKeys`) and the hardware chain cache (`patchedChains`). This led to state desynchronization where a stale software key could shadow a newly patched hardware chain if the alias was reused. This change ensures `cleanupKeyData` is invoked immediately before caching a new key / chain in both the software (`handleGenerateKey`) and hardware (`onPostTransact`) paths, ensuring the simulator returns the correct key for the most recent generation request.
This commit is contained in:
+6
-3
@@ -157,13 +157,15 @@ class KeyMintSecurityLevelInterceptor(
|
||||
val keyDescriptor = data.readTypedObject(KeyDescriptor.CREATOR)!!
|
||||
val key = metadata.key!!
|
||||
val keyId = KeyIdentifier(callingUid, keyDescriptor.alias)
|
||||
CertificateHelper.updateCertificateChain(metadata, newChain).getOrThrow()
|
||||
|
||||
// We must clean up cached generated keys before storing the patched chain
|
||||
cleanupKeyData(keyId)
|
||||
patchedChains[keyId] = newChain
|
||||
SystemLogger.debug(
|
||||
"Cached patched certificate chain for $keyId. (${key.alias} [${key.domain}, ${key.nspace}])"
|
||||
)
|
||||
|
||||
CertificateHelper.updateCertificateChain(metadata, newChain).getOrThrow()
|
||||
|
||||
return InterceptorUtils.createTypedObjectReply(metadata)
|
||||
}
|
||||
}
|
||||
@@ -258,10 +260,11 @@ class KeyMintSecurityLevelInterceptor(
|
||||
securityLevel,
|
||||
) ?: throw Exception("CertificateGenerator failed to create key pair.")
|
||||
|
||||
// It is unnecessary but a good practice to clean up possible caches
|
||||
cleanupKeyData(keyId)
|
||||
// Store the generated key data.
|
||||
val response =
|
||||
buildKeyEntryResponse(keyData.second, parsedParams, keyDescriptor)
|
||||
|
||||
generatedKeys[keyId] =
|
||||
GeneratedKeyInfo(keyData.first, keyDescriptor.nspace, response)
|
||||
if (isAttestKeyRequest) attestationKeys.add(keyId)
|
||||
|
||||
Reference in New Issue
Block a user