Skip to content

Commit 0ac2a2b

Browse files
MhmRddXiaoTong6666
authored andcommitted
Handle IV/nonce, OAEP, GCM tags, CTR mode, and ECDH in software operations
(cherry picked from commit 25538da)
1 parent 8e94056 commit 0ac2a2b

1 file changed

Lines changed: 65 additions & 11 deletions

File tree

app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/SoftwareOperation.kt

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,10 @@ private sealed interface CryptoPrimitive {
9191
fun getBeginParameters(): Array<KeyParameter>? = null
9292
}
9393

94-
// Helper object to map KeyMint constants to JCA algorithm strings.
94+
// Helper object to map KeyMint parameters onto the simulated software primitives we expose via JCA.
9595
private object JcaAlgorithmMapper {
96+
// AOSP sign operations derive the effective signature behavior from the key algorithm and the
97+
// selected digest (ecdsa_operation.cpp: l=79; rsa_operation.cpp: l=63).
9698
fun mapSignatureAlgorithm(params: KeyMintAttestation): String {
9799
val digest =
98100
when (params.digest.firstOrNull()) {
@@ -114,6 +116,8 @@ private object JcaAlgorithmMapper {
114116
return "${digest}with${keyAlgo}"
115117
}
116118

119+
// AOSP cipher operations derive behavior from algorithm, block mode, and padding tags
120+
// (block_cipher_operation.cpp: l=39, 79; rsa_operation.cpp: l=66).
117121
fun mapCipherAlgorithm(params: KeyMintAttestation): String {
118122
val keyAlgo =
119123
when (params.algorithm) {
@@ -129,6 +133,7 @@ private object JcaAlgorithmMapper {
129133
when (params.blockMode.firstOrNull()) {
130134
BlockMode.ECB -> "ECB"
131135
BlockMode.CBC -> "CBC"
136+
BlockMode.CTR -> "CTR"
132137
BlockMode.GCM -> "GCM"
133138
else -> "ECB" // Default for RSA
134139
}
@@ -144,7 +149,8 @@ private object JcaAlgorithmMapper {
144149
}
145150
}
146151

147-
// Concrete implementation for Signing.
152+
// Concrete implementation for Signing
153+
// (ecdsa_operation.cpp: l=138; rsa_operation.cpp: l=305).
148154
private class Signer(keyPair: KeyPair, params: KeyMintAttestation) : CryptoPrimitive {
149155
private val signature: Signature =
150156
Signature.getInstance(JcaAlgorithmMapper.mapSignatureAlgorithm(params)).apply {
@@ -168,7 +174,8 @@ private class Signer(keyPair: KeyPair, params: KeyMintAttestation) : CryptoPrimi
168174
override fun abort() {}
169175
}
170176

171-
// Concrete implementation for Verification.
177+
// Concrete implementation for Verification
178+
// (ecdsa_operation.cpp: l=273; rsa_operation.cpp: l=438).
172179
private class Verifier(keyPair: KeyPair, params: KeyMintAttestation) : CryptoPrimitive {
173180
private val signature: Signature =
174181
Signature.getInstance(JcaAlgorithmMapper.mapSignatureAlgorithm(params)).apply {
@@ -203,15 +210,46 @@ private class Verifier(keyPair: KeyPair, params: KeyMintAttestation) : CryptoPri
203210
override fun abort() {}
204211
}
205212

206-
// Concrete implementation for Encryption/Decryption.
213+
// Concrete implementation for Encryption/Decryption (block_cipher_operation.cpp: l=79).
207214
private class CipherPrimitive(
208215
cryptoKey: java.security.Key,
209216
params: KeyMintAttestation,
210217
private val opMode: Int,
218+
nonce: ByteArray?,
219+
macLength: Int?,
211220
) : CryptoPrimitive {
212221
private val cipher: Cipher =
213222
Cipher.getInstance(JcaAlgorithmMapper.mapCipherAlgorithm(params)).apply {
214-
init(opMode, cryptoKey)
223+
val algSpec =
224+
when {
225+
nonce != null && params.blockMode.contains(BlockMode.GCM) ->
226+
javax.crypto.spec.GCMParameterSpec((macLength ?: 128), nonce)
227+
params.padding.contains(PaddingMode.RSA_OAEP) -> {
228+
val mgfDigest =
229+
when (params.rsaOaepMgfDigest.firstOrNull()) {
230+
Digest.SHA_2_256 -> "SHA-256"
231+
Digest.SHA_2_384 -> "SHA-384"
232+
Digest.SHA_2_512 -> "SHA-512"
233+
else -> "SHA-1"
234+
}
235+
val mainDigest =
236+
when (params.digest.firstOrNull()) {
237+
Digest.SHA_2_256 -> "SHA-256"
238+
Digest.SHA_2_384 -> "SHA-384"
239+
Digest.SHA_2_512 -> "SHA-512"
240+
else -> "SHA-1"
241+
}
242+
javax.crypto.spec.OAEPParameterSpec(
243+
mainDigest,
244+
"MGF1",
245+
java.security.spec.MGF1ParameterSpec(mgfDigest),
246+
javax.crypto.spec.PSource.PSpecified.DEFAULT,
247+
)
248+
}
249+
nonce != null -> javax.crypto.spec.IvParameterSpec(nonce)
250+
else -> null
251+
}
252+
if (algSpec != null) init(opMode, cryptoKey, algSpec) else init(opMode, cryptoKey)
215253
}
216254

217255
override fun updateAad(data: ByteArray?) {
@@ -221,8 +259,16 @@ private class CipherPrimitive(
221259
override fun update(data: ByteArray?): ByteArray? =
222260
if (data != null) cipher.update(data) else null
223261

224-
override fun finish(data: ByteArray?, signature: ByteArray?): ByteArray? =
225-
if (data != null) cipher.doFinal(data) else cipher.doFinal()
262+
override fun finish(data: ByteArray?, signature: ByteArray?): ByteArray? {
263+
return try {
264+
if (data != null) cipher.doFinal(data) else cipher.doFinal()
265+
} catch (e: javax.crypto.AEADBadTagException) {
266+
throw ServiceSpecificException(
267+
KeystoreErrorCode.VERIFICATION_FAILED,
268+
"GCM tag verification failed",
269+
)
270+
}
271+
}
226272

227273
override fun abort() {}
228274

@@ -238,7 +284,7 @@ private class CipherPrimitive(
238284
}
239285
}
240286

241-
// Concrete implementation for ECDH Key Agreement.
287+
// Concrete implementation for ECDH Key Agreement (ecdh_operation.cpp: l=52).
242288
private class KeyAgreementPrimitive(keyPair: KeyPair) : CryptoPrimitive {
243289
private val agreement: javax.crypto.KeyAgreement =
244290
javax.crypto.KeyAgreement.getInstance("ECDH").apply { init(keyPair.private) }
@@ -296,11 +342,15 @@ class SoftwareOperation(
296342
KeyPurpose.VERIFY -> Verifier(keyPair!!, params)
297343
KeyPurpose.ENCRYPT -> {
298344
val key: java.security.Key = secretKey ?: keyPair!!.public
299-
CipherPrimitive(key, params, Cipher.ENCRYPT_MODE)
345+
val nonce = opParams.find { it.tag == Tag.NONCE }?.value?.blob
346+
val macLen = opParams.find { it.tag == Tag.MAC_LENGTH }?.value?.integer
347+
CipherPrimitive(key, params, Cipher.ENCRYPT_MODE, nonce, macLen)
300348
}
301349
KeyPurpose.DECRYPT -> {
302350
val key: java.security.Key = secretKey ?: keyPair!!.private
303-
CipherPrimitive(key, params, Cipher.DECRYPT_MODE)
351+
val nonce = opParams.find { it.tag == Tag.NONCE }?.value?.blob
352+
val macLen = opParams.find { it.tag == Tag.MAC_LENGTH }?.value?.integer
353+
CipherPrimitive(key, params, Cipher.DECRYPT_MODE, nonce, macLen)
304354
}
305355
KeyPurpose.AGREE_KEY -> KeyAgreementPrimitive(keyPair!!)
306356
else ->
@@ -361,7 +411,11 @@ class SoftwareOperation(
361411
try {
362412
val result = primitive.finish(data, signature)
363413
SystemLogger.info("[SoftwareOp TX_ID: $txId] Finished operation successfully.")
364-
onFinishCallback?.invoke()
414+
try {
415+
onFinishCallback?.invoke()
416+
} catch (e: Exception) {
417+
SystemLogger.error("[SoftwareOp TX_ID: $txId] onFinishCallback failed.", e)
418+
}
365419
return result
366420
} catch (e: ServiceSpecificException) {
367421
throw e

0 commit comments

Comments
 (0)