@@ -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 .
9595private 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).
148154private 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).
172179private 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) .
207214private 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) .
242288private 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