diff --git a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/GeneratedKeyPersistence.kt b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/GeneratedKeyPersistence.kt index 3f2e76e..af5fbae 100644 --- a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/GeneratedKeyPersistence.kt +++ b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/GeneratedKeyPersistence.kt @@ -16,7 +16,7 @@ import java.util.concurrent.locks.ReentrantLock import org.matrix.TEESimulator.config.ConfigurationManager.CONFIG_PATH import org.matrix.TEESimulator.interception.keystore.KeyIdentifier import org.matrix.TEESimulator.logging.SystemLogger -import org.matrix.TEESimulator.pki.CertificateHelper + data class PersistedKeyData( val uid: Int, @@ -250,77 +250,6 @@ object GeneratedKeyPersistence { return result } - // Re-persist updates the cert chain for an already-persisted key without - // reconstructing authorization parameters from the response. This avoids - // pulling keymint Tag dependencies into this file and is correct because - // the only field that changes post-generation is the patched cert chain. - fun rePersistIfNeeded( - callingUid: Int, - generatedKeyInfo: KeyMintSecurityLevelInterceptor.GeneratedKeyInfo, - ) { - val metadata = generatedKeyInfo.response.metadata - if (metadata == null) { - SystemLogger.debug("rePersist: no metadata, skipping") - return - } - val secLevel = metadata.keySecurityLevel - - val entry = KeyMintSecurityLevelInterceptor.generatedKeys.entries.find { (id, info) -> - id.uid == callingUid && info.nspace == generatedKeyInfo.nspace - } - if (entry == null) { - SystemLogger.debug("rePersist: key not found in map for uid=$callingUid nspace=${generatedKeyInfo.nspace}") - return - } - - val keyId = entry.key - val filename = keyFileName(keyId.uid, keyId.alias) - val existing = File(PERSISTENCE_DIR, filename) - - if (!existing.exists()) { - SystemLogger.debug("rePersist: no existing file for $keyId, skipping") - return - } - - val newChain = CertificateHelper.getCertificateChain(metadata) - if (newChain == null) { - SystemLogger.warning("rePersist: could not extract cert chain for $keyId") - return - } - - val persisted = runCatching { - DataInputStream(BufferedInputStream(FileInputStream(existing))).use { input -> - val version = input.readInt() - if (version != FORMAT_VERSION) { - SystemLogger.warning("rePersist: unknown format version $version for $keyId") - return - } - readPersistedKeyData(input) - } - }.getOrNull() - if (persisted == null) { - SystemLogger.warning("rePersist: failed to read existing data for $keyId") - return - } - - val keyPair = generatedKeyInfo.keyPair ?: return - save( - keyId = keyId, - keyPair = keyPair, - nspace = generatedKeyInfo.nspace, - securityLevel = secLevel, - certChain = newChain.toList(), - algorithm = persisted.algorithm, - keySize = persisted.keySize, - ecCurve = persisted.ecCurve, - purposes = persisted.purposes, - digests = persisted.digests, - isAttestationKey = persisted.isAttestationKey, - ) - SystemLogger.debug("Re-persisted key $keyId with updated cert chain") - } - - // Corrupted binary files can have arbitrary length fields — cap allocations private fun requireBounds(value: Int, max: Int, name: String): Int { require(value in 0..max) { "$name out of bounds: $value (max $max)" } return value @@ -331,49 +260,4 @@ object GeneratedKeyPersistence { .digest("$uid:$alias".toByteArray(Charsets.UTF_8)) return digest.joinToString("") { "%02x".format(it) } + ".bin" } - - // Reads all fields after version has already been consumed - private fun readPersistedKeyData(input: DataInputStream): PersistedKeyData { - val secLevel = input.readInt() - val uid = input.readInt() - val alias = input.readUTF() - val nspace = input.readLong() - val isAttestKey = input.readBoolean() - val algo = input.readInt() - val kSize = input.readInt() - val curve = input.readInt() - - val purposeCount = requireBounds(input.readInt(), 64, "purposeCount") - val purposes = (0 until purposeCount).map { input.readInt() } - - val digestCount = requireBounds(input.readInt(), 64, "digestCount") - val digests = (0 until digestCount).map { input.readInt() } - - val pkLen = requireBounds(input.readInt(), 8192, "pkLen") - val pkBytes = ByteArray(pkLen) - input.readFully(pkBytes) - - val certCount = requireBounds(input.readInt(), 10, "certCount") - val certChainBytes = (0 until certCount).map { - val certLen = requireBounds(input.readInt(), 65536, "certLen") - val certBytes = ByteArray(certLen) - input.readFully(certBytes) - certBytes - } - - return PersistedKeyData( - uid = uid, - alias = alias, - nspace = nspace, - securityLevel = secLevel, - isAttestationKey = isAttestKey, - algorithm = algo, - keySize = kSize, - ecCurve = curve, - purposes = purposes, - digests = digests, - privateKeyBytes = pkBytes, - certChainBytes = certChainBytes, - ) - } }