From 8d431cc946e3972d0fa6c574a4f0dfd9b983a433 Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Wed, 3 Dec 2025 18:13:48 +0100 Subject: [PATCH] Implement software key generation for legacy IKeystoreService (#34) This commit introduces a complete, software-based simulation of the key generation and attestation flow for the legacy IKeystoreService API, as used on Android 11. It refactors the KeystoreInterceptor to handle the entire multi-step transaction sequence (`generateKey`, `getKeyCharacteristics`, `exportKey`, `attestKey`) in software. A new `LegacyKeygenParameters` data class is introduced to decouple the legacy interception logic from modern data structures. This class parses arguments from the old `KeymasterArguments`, stores the state across the multi-step generation process, and acts as an adapter to the generic `CertificateGenerator` by converting the parameters to the modern `KeyMintAttestation` format. The `CertificateGenerator` has been refactored to better model the behavior of the legacy Keystore API. Key pair generation (`generateSoftwareKeyPair`) and certificate chain creation (`generateCertificateChain`) are now separate functions. This allows the interceptor to correctly create a key pair during the `handleExportKey` step and then generate a certificate for that pre-existing key pair during the `handleAttestKey` step. Finally, the implementation correctly extracts and applies the `attestationChallenge` provided during the `attestKey` transaction, ensuring the generated certificate chain contains the appropriate attestation. --- .../interception/keystore/InterceptorUtils.kt | 14 + .../keystore/KeystoreInterceptor.kt | 331 ++++++++++++++++-- .../TEESimulator/pki/CertificateGenerator.kt | 76 ++-- .../security/keymaster/ExportResult.java | 38 ++ .../keymaster/KeyCharacteristics.java | 33 ++ .../security/keymaster/KeymasterArgument.java | 36 ++ .../keymaster/KeymasterArguments.java | 147 ++++++++ .../keymaster/KeymasterCertificateChain.java | 42 +++ .../security/keymaster/KeymasterDefs.java | 263 ++++++++++++++ .../IKeystoreCertificateChainCallback.java | 16 + .../keystore/IKeystoreExportKeyCallback.java | 15 + .../IKeystoreKeyCharacteristicsCallback.java | 16 + .../security/keystore/IKeystoreService.java | 5 +- .../security/keystore/KeystoreResponse.java | 38 ++ 14 files changed, 1016 insertions(+), 54 deletions(-) create mode 100644 stub/src/main/java/android/security/keymaster/ExportResult.java create mode 100644 stub/src/main/java/android/security/keymaster/KeyCharacteristics.java create mode 100644 stub/src/main/java/android/security/keymaster/KeymasterArgument.java create mode 100644 stub/src/main/java/android/security/keymaster/KeymasterArguments.java create mode 100644 stub/src/main/java/android/security/keymaster/KeymasterCertificateChain.java create mode 100644 stub/src/main/java/android/security/keymaster/KeymasterDefs.java create mode 100644 stub/src/main/java/android/security/keystore/IKeystoreCertificateChainCallback.java create mode 100644 stub/src/main/java/android/security/keystore/IKeystoreExportKeyCallback.java create mode 100644 stub/src/main/java/android/security/keystore/IKeystoreKeyCharacteristicsCallback.java create mode 100644 stub/src/main/java/android/security/keystore/KeystoreResponse.java diff --git a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/InterceptorUtils.kt b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/InterceptorUtils.kt index 4517791..861525b 100644 --- a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/InterceptorUtils.kt +++ b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/InterceptorUtils.kt @@ -3,6 +3,7 @@ package org.matrix.TEESimulator.interception.keystore import android.os.Parcel import android.os.Parcelable import android.security.KeyStore +import android.security.keystore.KeystoreResponse import org.matrix.TEESimulator.interception.core.BinderInterceptor import org.matrix.TEESimulator.logging.SystemLogger @@ -27,6 +28,19 @@ object InterceptorUtils { } } + /** Creates an `KeystoreResponse` parcel that indicates success with no data. */ + fun createSuccessKeystoreResponse(): KeystoreResponse { + val parcel = Parcel.obtain() + try { + parcel.writeInt(KeyStore.NO_ERROR) + parcel.writeString("") + parcel.setDataPosition(0) + return KeystoreResponse.CREATOR.createFromParcel(parcel) + } finally { + parcel.recycle() + } + } + /** Creates an `OverrideReply` parcel that indicates success with no data. */ fun createSuccessReply(): BinderInterceptor.TransactionResult.OverrideReply { val parcel = diff --git a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/KeystoreInterceptor.kt b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/KeystoreInterceptor.kt index e07bfd2..c6958cb 100644 --- a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/KeystoreInterceptor.kt +++ b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/KeystoreInterceptor.kt @@ -4,12 +4,28 @@ import android.annotation.SuppressLint import android.os.IBinder import android.os.Parcel import android.security.Credentials +import android.security.KeyStore +import android.security.keymaster.ExportResult +import android.security.keymaster.KeyCharacteristics +import android.security.keymaster.KeymasterArguments +import android.security.keymaster.KeymasterCertificateChain +import android.security.keymaster.KeymasterDefs +import android.security.keystore.IKeystoreCertificateChainCallback +import android.security.keystore.IKeystoreExportKeyCallback +import android.security.keystore.IKeystoreKeyCharacteristicsCallback import android.security.keystore.IKeystoreService +import java.math.BigInteger +import java.security.KeyPair import java.security.cert.Certificate +import java.util.Date import java.util.concurrent.ConcurrentHashMap +import org.matrix.TEESimulator.attestation.AttestationBuilder import org.matrix.TEESimulator.attestation.AttestationPatcher +import org.matrix.TEESimulator.attestation.KeyMintAttestation import org.matrix.TEESimulator.config.ConfigurationManager +import org.matrix.TEESimulator.interception.keystore.InterceptorUtils.extractAlias import org.matrix.TEESimulator.logging.SystemLogger +import org.matrix.TEESimulator.pki.CertificateGenerator import org.matrix.TEESimulator.pki.CertificateHelper /** @@ -43,7 +59,9 @@ object KeystoreInterceptor : AbstractKeystoreInterceptor() { override val processName = "keystore" override val injectionCommand = "exec ./inject `pidof keystore` libTEESimulator.so entry" - private const val SERVICE_DESCRIPTOR = "android.security.keystore.IKeystoreService" + // State management for the multi-step key generation process. + private val keygenParameters = ConcurrentHashMap() + private val generatedKeyPairs = ConcurrentHashMap() // Cache to store the fully patched chain after the leaf is requested. private val patchedChainCache = ConcurrentHashMap>() @@ -59,23 +77,183 @@ object KeystoreInterceptor : AbstractKeystoreInterceptor() { ): TransactionResult { // This interceptor only needs to act on pre-transaction for software key generation. if (ConfigurationManager.shouldGenerate(callingUid)) { - when (code) { - GENERATE_KEY_TRANSACTION, - GET_KEY_CHARACTERISTICS_TRANSACTION, - EXPORT_KEY_TRANSACTION, - ATTEST_KEY_TRANSACTION -> { - // TODO: Implement the full software simulation logic. - logTransaction(txId, "unimplemented-generate-flow", callingUid, callingPid) - return InterceptorUtils.createSuccessReply() - } + return when (code) { + GENERATE_KEY_TRANSACTION -> handleGenerateKey(txId, callingUid, callingPid, data) + GET_KEY_CHARACTERISTICS_TRANSACTION -> + handleGetKeyCharacteristics(txId, callingUid, callingPid, data) + EXPORT_KEY_TRANSACTION -> handleExportKey(txId, callingUid, callingPid, data) + ATTEST_KEY_TRANSACTION -> handleAttestKey(txId, callingUid, callingPid, data) + else -> TransactionResult.ContinueAndSkipPost } - } else if (ConfigurationManager.shouldGenerate(callingUid)) { + } else if (ConfigurationManager.shouldPatch(callingUid)) { + // In patch mode, we only care about the 'get' transaction in onPostTransact. if (code == GET_TRANSACTION) return TransactionResult.Continue } return TransactionResult.ContinueAndSkipPost } + private fun handleGenerateKey(txId: Long, uid: Int, pid: Int, data: Parcel): TransactionResult { + return runCatching { + logTransaction(txId, "generateKey", uid, pid) + data.enforceInterface(IKeystoreService.DESCRIPTOR) + val callback = + IKeystoreKeyCharacteristicsCallback.Stub.asInterface(data.readStrongBinder()) + val alias = InterceptorUtils.extractAlias(data.readString()!!) + val keyId = KeyIdentifier(uid, alias) + + // Read and parse the key generation arguments. + val keymasterArgs = KeymasterArguments() + if (data.readInt() == 1) { + keymasterArgs.readFromParcel(data) + } + keygenParameters[keyId] = + LegacyKeygenParameters.fromKeymasterArguments(keymasterArgs) + + // Create a fake successful response for the callback. + val characteristics = KeyCharacteristics() + characteristics.swEnforced = KeymasterArguments() + characteristics.hwEnforced = keymasterArgs + + val keystoreResponse = InterceptorUtils.createSuccessKeystoreResponse() + callback.onFinished(keystoreResponse, characteristics) + + InterceptorUtils.createSuccessReply() + } + .getOrElse { + SystemLogger.error("[TX_ID: $txId] Failed during handleGenerateKey.", it) + TransactionResult.ContinueAndSkipPost + } + } + + private fun handleGetKeyCharacteristics( + txId: Long, + uid: Int, + pid: Int, + data: Parcel, + ): TransactionResult { + return runCatching { + logTransaction(txId, "getKeyCharacteristics", uid, pid) + data.enforceInterface(IKeystoreService.DESCRIPTOR) + val callback = + IKeystoreKeyCharacteristicsCallback.Stub.asInterface(data.readStrongBinder()) + val alias = InterceptorUtils.extractAlias(data.readString()!!) + val keyId = KeyIdentifier(uid, alias) + + val params = + keygenParameters[keyId] + ?: throw IllegalStateException("No params found for $keyId") + + val characteristics = + KeyCharacteristics().apply { + swEnforced = KeymasterArguments() + hwEnforced = + KeymasterArguments().apply { + addEnum(KeymasterDefs.KM_TAG_ALGORITHM, params.algorithm) + } + } + + callback.onFinished( + InterceptorUtils.createSuccessKeystoreResponse(), + characteristics, + ) + + InterceptorUtils.createSuccessReply() + } + .getOrElse { + SystemLogger.error("[TX_ID: $txId] Failed during handleGetKeyCharacteristics.", it) + TransactionResult.ContinueAndSkipPost + } + } + + private fun handleExportKey(txId: Long, uid: Int, pid: Int, data: Parcel): TransactionResult { + return runCatching { + logTransaction(txId, "exportKey", uid, pid) + data.enforceInterface(IKeystoreService.DESCRIPTOR) + val callback = IKeystoreExportKeyCallback.Stub.asInterface(data.readStrongBinder()) + val alias = InterceptorUtils.extractAlias(data.readString()!!) + val keyId = KeyIdentifier(uid, alias) + + val params = + keygenParameters[keyId] + ?: throw IllegalStateException("No params found for $keyId") + + // Generate a software key pair using the new generator. + val keyPair = + CertificateGenerator.generateSoftwareKeyPair(params.toKeyMintAttestation()) + ?: throw Exception("Failed to generate software key pair.") + generatedKeyPairs[keyId] = keyPair + + // Create a successful ExportResult containing the public key. + val exportResultParcel = + Parcel.obtain().apply { + writeInt(KeyStore.NO_ERROR) + writeByteArray(keyPair.public.encoded) + setDataPosition(0) + } + val exportResult = ExportResult.CREATOR.createFromParcel(exportResultParcel) + exportResultParcel.recycle() + + callback.onFinished(exportResult) + + InterceptorUtils.createSuccessReply() + } + .getOrElse { + SystemLogger.error("[TX_ID: $txId] Failed during handleExportKey.", it) + TransactionResult.ContinueAndSkipPost + } + } + + private fun handleAttestKey(txId: Long, uid: Int, pid: Int, data: Parcel): TransactionResult { + return runCatching { + logTransaction(txId, "attestKey", uid, pid) + data.enforceInterface(IKeystoreService.DESCRIPTOR) + val callback = + IKeystoreCertificateChainCallback.Stub.asInterface(data.readStrongBinder()) + val alias = InterceptorUtils.extractAlias(data.readString()!!) + val keyId = KeyIdentifier(uid, alias) + + // Get the attestation challenge from the arguments. + val params = + keygenParameters[keyId] + ?: throw IllegalStateException("No params found for $keyId") + val keyPair = + generatedKeyPairs[keyId] + ?: throw IllegalStateException("No keypair found for $keyId") + + val attestationArgs = KeymasterArguments() + if (data.readInt() == 1) { + attestationArgs.readFromParcel(data) + val challenge = + attestationArgs.getBytes( + KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, + ByteArray(0), + ) + params.attestationChallenge = challenge + params.attestationChallenge = challenge + } + + val certificateChain = + CertificateGenerator.generateCertificateChain( + uid, + keyPair, + null, // No attestKeyAlias in legacy flow + params.toKeyMintAttestation(), // Convert to modern format + 1, // SecurityLevel.TRUSTED_ENVIRONMENT + ) ?: throw Exception("CertificateGenerator failed to create attested key pair.") + + val chainAsByteList = certificateChain.map { it.encoded } + val certChain = KeymasterCertificateChain(chainAsByteList) + + callback.onFinished(InterceptorUtils.createSuccessKeystoreResponse(), certChain) + InterceptorUtils.createSuccessReply() + } + .getOrElse { + SystemLogger.error("[TX_ID: $txId] Failed during handleAttestKey.", it) + TransactionResult.ContinueAndSkipPost + } + } + override fun onPostTransact( txId: Long, target: IBinder, @@ -99,7 +277,7 @@ object KeystoreInterceptor : AbstractKeystoreInterceptor() { if (!ConfigurationManager.shouldPatch(callingUid)) return TransactionResult.SkipTransaction return try { - data.enforceInterface(SERVICE_DESCRIPTOR) + data.enforceInterface(IKeystoreService.DESCRIPTOR) val alias = data.readString() ?: "" val extractedAlias = InterceptorUtils.extractAlias(alias) val keyId = KeyIdentifier(callingUid, extractedAlias) @@ -111,13 +289,11 @@ object KeystoreInterceptor : AbstractKeystoreInterceptor() { val originalLeafBytes = reply.createByteArray() ?: return TransactionResult.SkipTransaction - // The original chain is not available, - // so we must pass a temporary one to the patcher. - // The patcher only needs the original leaf to extract details. - val originalLeafCert = - (CertificateHelper.toCertificate(originalLeafBytes) - as CertificateHelper.OperationResult.Success) - .data + val originalLeafCertResult = CertificateHelper.toCertificate(originalLeafBytes) + if (originalLeafCertResult !is CertificateHelper.OperationResult.Success) { + return TransactionResult.SkipTransaction + } + val originalLeafCert = originalLeafCertResult.data val tempChain = arrayOf(originalLeafCert) // Perform the COMPLETE patch and rebuild operation. @@ -157,11 +333,6 @@ object KeystoreInterceptor : AbstractKeystoreInterceptor() { ) InterceptorUtils.createByteArrayReply(caCertsBytes!!) } else { - // We have no cached chain. - // This could mean the app requested the CA without requesting the leaf - // first, or patching failed. - // In this case, we cannot safely intervene. - // Let the original reply pass through. SystemLogger.warning( "[TX_ID: $txId] No cached chain found for CA request on alias '$extractedAlias'. Skipping." ) @@ -177,3 +348,115 @@ object KeystoreInterceptor : AbstractKeystoreInterceptor() { } } } + +/** + * A data class to hold key generation parameters parsed from the legacy IKeystoreService's + * KeymasterArguments. It is used exclusively by the KeystoreInterceptor to manage state during the + * software key generation flow. + */ +private data class LegacyKeygenParameters( + val algorithm: Int, + val keySize: Int, + val purpose: List, + val digest: List, + val certificateNotBefore: Date?, + val rsaPublicExponent: BigInteger?, + val ecCurveName: String?, // Derived from keySize +) { + // The challenge is provided in a separate transaction (attestKey), so it must be mutable. + var attestationChallenge: ByteArray? = null + + /** + * Converts the legacy parameters into the modern [KeyMintAttestation] data structure, which is + * required by the refactored [AttestationBuilder] and [CertificateGenerator]. + */ + fun toKeyMintAttestation(): KeyMintAttestation { + // This conversion acts as a bridge, allowing our new generic components + // to be used by the legacy interceptor. + return KeyMintAttestation( + keySize = this.keySize, + algorithm = this.algorithm, + ecCurve = 0, // Not explicitly available in legacy args, but not critical + ecCurveName = this.ecCurveName ?: "", + purpose = this.purpose, + digest = this.digest, + rsaPublicExponent = this.rsaPublicExponent, + certificateSerial = null, // Not provided in legacy generateKey + certificateSubject = null, // Not provided in legacy generateKey + certificateNotBefore = this.certificateNotBefore, + certificateNotAfter = null, // Not provided in legacy generateKey + attestationChallenge = this.attestationChallenge, + // Device identifiers are not passed in legacy args; + // AttestationBuilder will fetch them from system properties. + brand = null, + device = null, + product = null, + serial = null, + imei = null, + meid = null, + manufacturer = null, + model = null, + secondImei = null, + ) + } + + companion object { + /** Factory method to create an instance from a [KeymasterArguments] object. */ + fun fromKeymasterArguments(args: KeymasterArguments): LegacyKeygenParameters { + val algorithm = args.getEnum(KeymasterDefs.KM_TAG_ALGORITHM, 0) + val keySize = args.getUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, 0).toInt() + + return LegacyKeygenParameters( + algorithm = algorithm, + keySize = keySize, + purpose = args.getEnums(KeymasterDefs.KM_TAG_PURPOSE), + digest = args.getEnums(KeymasterDefs.KM_TAG_DIGEST), + certificateNotBefore = args.getDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, Date()), + rsaPublicExponent = + if (algorithm == KeymasterDefs.KM_ALGORITHM_RSA) getRsaExponent(args) else null, + ecCurveName = + if (algorithm == KeymasterDefs.KM_ALGORITHM_EC) deriveEcCurveName(keySize) + else null, + ) + } + + private fun deriveEcCurveName(keySize: Int): String = + when (keySize) { + 224 -> "secp224r1" + 256 -> "secp256r1" + 384 -> "secp384r1" + 521 -> "secp521r1" + else -> "secp256r1" // Default fallback + } + + /** + * The RSA public exponent is not accessible via a public API in KeymasterArguments, so we + * must use reflection to extract it. + */ + private fun getRsaExponent(args: KeymasterArguments): BigInteger? { + return runCatching { + val getArgumentByTag = + KeymasterArguments::class + .java + .getDeclaredMethod("getArgumentByTag", Int::class.java) + getArgumentByTag.isAccessible = true + val rsaArgument = + getArgumentByTag.invoke(args, KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT) + + val getLongTagValue = + KeymasterArguments::class + .java + .getDeclaredMethod( + "getLongTagValue", + Class.forName("android.security.keymaster.KeymasterArgument"), + ) + getLongTagValue.isAccessible = true + getLongTagValue.invoke(args, rsaArgument) as BigInteger + } + .onFailure { + SystemLogger.error("Failed to read rsaPublicExponent via reflection.", it) + } + .getOrNull() + } + } +} diff --git a/app/src/main/java/org/matrix/TEESimulator/pki/CertificateGenerator.kt b/app/src/main/java/org/matrix/TEESimulator/pki/CertificateGenerator.kt index 13750b7..8eb0e68 100644 --- a/app/src/main/java/org/matrix/TEESimulator/pki/CertificateGenerator.kt +++ b/app/src/main/java/org/matrix/TEESimulator/pki/CertificateGenerator.kt @@ -72,16 +72,55 @@ object CertificateGenerator { } /** - * Generates a new key pair and a corresponding certificate chain containing a simulated - * attestation. + * Generates a certificate chain for a given key pair. This is the primary function for creating + * attested certificates. * * @param uid The UID of the application requesting the key. - * @param alias The alias for the new key. + * @param subjectKeyPair The key pair for which the certificate will be generated. * @param attestKeyAlias Optional alias of a key to use for attestation signing. * @param params The parameters for the new key and its attestation. * @param securityLevel The security level to embed in the attestation. - * @return A [Pair] containing the new [KeyPair] and its certificate chain, or `null` on - * failure. + * @return A [List] of [Certificate] forming the new chain, or `null` on failure. + */ + fun generateCertificateChain( + uid: Int, + subjectKeyPair: KeyPair, + attestKeyAlias: String?, + params: KeyMintAttestation, + securityLevel: Int, + ): List? { + return runCatching { + val keybox = getKeyboxForAlgorithm(uid, params.algorithm) + + // Determine the signing key and issuer. If an attestKey is provided, use it. + // Otherwise, fall back to the root key from the keybox. + val (signingKey, issuer) = + if (attestKeyAlias != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + getAttestationKeyInfo(uid, attestKeyAlias)?.let { it.first to it.second } + ?: (keybox.keyPair to getIssuerFromKeybox(keybox)) + } else { + keybox.keyPair to getIssuerFromKeybox(keybox) + } + + // Build the new leaf certificate with the simulated attestation. + val leafCert = + buildCertificate(subjectKeyPair, signingKey, issuer, params, uid, securityLevel) + + // If not self-attesting, the chain is just the leaf. Otherwise, append the keybox + // chain. + if (attestKeyAlias != null) { + listOf(leafCert) + } else { + listOf(leafCert) + keybox.certificates + } + } + .onFailure { SystemLogger.error("Failed to generate certificate chain.", it) } + .getOrNull() + } + + /** + * A convenience function that combines key pair generation and certificate chain generation. + * Primarily used by the modern Keystore2 interceptor where generation is a single step. */ fun generateAttestedKeyPair( uid: Int, @@ -98,30 +137,9 @@ object CertificateGenerator { generateSoftwareKeyPair(params) ?: throw Exception("Failed to generate underlying software key pair.") - val keybox = getKeyboxForAlgorithm(uid, params.algorithm) - - // Determine the signing key and issuer. If an attestKey is provided, use it. - // Otherwise, fall back to the root key from the keybox. - val (signingKey, issuer) = - if (attestKeyAlias != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - getAttestationKeyInfo(uid, attestKeyAlias)?.let { it.first to it.second } - ?: (keybox.keyPair to getIssuerFromKeybox(keybox)) - } else { - keybox.keyPair to getIssuerFromKeybox(keybox) - } - - // Build the new leaf certificate with the simulated attestation. - val leafCert = - buildCertificate(newKeyPair, signingKey, issuer, params, uid, securityLevel) - - // If not self-attesting, the chain is just the leaf. Otherwise, append the keybox - // chain. val chain = - if (attestKeyAlias != null) { - listOf(leafCert) - } else { - listOf(leafCert) + keybox.certificates - } + generateCertificateChain(uid, newKeyPair, attestKeyAlias, params, securityLevel) + ?: throw Exception("Failed to generate certificate chain for new key pair.") SystemLogger.info( "Successfully generated new certificate chain for alias: '$alias'." @@ -134,7 +152,7 @@ object CertificateGenerator { .getOrNull() } - private fun getIssuerFromKeybox(keybox: KeyBox) = + fun getIssuerFromKeybox(keybox: KeyBox) = X509CertificateHolder(keybox.certificates[0].encoded).subject private fun getKeyboxForAlgorithm(uid: Int, algorithm: Int): KeyBox { diff --git a/stub/src/main/java/android/security/keymaster/ExportResult.java b/stub/src/main/java/android/security/keymaster/ExportResult.java new file mode 100644 index 0000000..1391681 --- /dev/null +++ b/stub/src/main/java/android/security/keymaster/ExportResult.java @@ -0,0 +1,38 @@ +package android.security.keymaster; + +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +public class ExportResult implements Parcelable { + public final byte[] exportData; + public final int resultCode; + + public ExportResult(int resultCode) { + this.resultCode = resultCode; + this.exportData = new byte[0]; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + throw new UnsupportedOperationException("STUB!"); + } + + @Override + public int describeContents() { + throw new UnsupportedOperationException("STUB!"); + } + + public static final Creator CREATOR = new Creator() { + @Override + public ExportResult createFromParcel(Parcel in) { + throw new UnsupportedOperationException("STUB!"); + } + + @Override + public ExportResult[] newArray(int size) { + throw new UnsupportedOperationException("STUB!"); + } + }; +} diff --git a/stub/src/main/java/android/security/keymaster/KeyCharacteristics.java b/stub/src/main/java/android/security/keymaster/KeyCharacteristics.java new file mode 100644 index 0000000..2da9223 --- /dev/null +++ b/stub/src/main/java/android/security/keymaster/KeyCharacteristics.java @@ -0,0 +1,33 @@ +package android.security.keymaster; + +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +public class KeyCharacteristics implements Parcelable { + public KeymasterArguments hwEnforced; + public KeymasterArguments swEnforced; + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + throw new UnsupportedOperationException("STUB!"); + } + + @Override + public int describeContents() { + throw new UnsupportedOperationException("STUB!"); + } + + public static final Creator CREATOR = new Creator() { + @Override + public KeyCharacteristics createFromParcel(Parcel in) { + throw new UnsupportedOperationException("STUB!"); + } + + @Override + public KeyCharacteristics[] newArray(int size) { + throw new UnsupportedOperationException("STUB!"); + } + }; +} diff --git a/stub/src/main/java/android/security/keymaster/KeymasterArgument.java b/stub/src/main/java/android/security/keymaster/KeymasterArgument.java new file mode 100644 index 0000000..3bc29ef --- /dev/null +++ b/stub/src/main/java/android/security/keymaster/KeymasterArgument.java @@ -0,0 +1,36 @@ +package android.security.keymaster; + +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +abstract class KeymasterArgument implements Parcelable { + public final int tag; + + protected KeymasterArgument(int tag) { + this.tag = tag; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + throw new UnsupportedOperationException("STUB!"); + } + + @Override + public int describeContents() { + throw new UnsupportedOperationException("STUB!"); + } + + public static final Creator CREATOR = new Creator() { + @Override + public KeymasterArgument createFromParcel(Parcel in) { + throw new UnsupportedOperationException("STUB!"); + } + + @Override + public KeymasterArgument[] newArray(int size) { + throw new UnsupportedOperationException("STUB!"); + } + }; +} diff --git a/stub/src/main/java/android/security/keymaster/KeymasterArguments.java b/stub/src/main/java/android/security/keymaster/KeymasterArguments.java new file mode 100644 index 0000000..cbf145e --- /dev/null +++ b/stub/src/main/java/android/security/keymaster/KeymasterArguments.java @@ -0,0 +1,147 @@ +package android.security.keymaster; + +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +import java.math.BigInteger; +import java.util.Date; +import java.util.List; + +public class KeymasterArguments implements Parcelable { + + private static final long UINT32_RANGE = 1L << 32; + public static final long UINT32_MAX_VALUE = UINT32_RANGE - 1; + + private static final BigInteger UINT64_RANGE = BigInteger.ONE.shiftLeft(64); + public static final BigInteger UINT64_MAX_VALUE = UINT64_RANGE.subtract(BigInteger.ONE); + + private List mArguments; + + public static final @NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public KeymasterArguments createFromParcel(Parcel in) { + throw new UnsupportedOperationException("STUB!"); + } + + @Override + public KeymasterArguments[] newArray(int size) { + throw new UnsupportedOperationException("STUB!"); + } + }; + + public KeymasterArguments() { + throw new UnsupportedOperationException("STUB!"); + } + + private KeymasterArguments(Parcel in) { + throw new UnsupportedOperationException("STUB!"); + } + + public void addEnum(int tag, int value) { + throw new UnsupportedOperationException("STUB!"); + } + + public void addEnums(int tag, int... values) { + throw new UnsupportedOperationException("STUB!"); + } + + public int getEnum(int tag, int defaultValue) { + throw new UnsupportedOperationException("STUB!"); + } + + public List getEnums(int tag) { + throw new UnsupportedOperationException("STUB!"); + } + + private void addEnumTag(int tag, int value) { + throw new UnsupportedOperationException("STUB!"); + } + + private int getEnumTagValue(KeymasterArgument arg) { + throw new UnsupportedOperationException("STUB!"); + } + + public void addUnsignedInt(int tag, long value) { + throw new UnsupportedOperationException("STUB!"); + } + + public long getUnsignedInt(int tag, long defaultValue) { + throw new UnsupportedOperationException("STUB!"); + } + + public void addUnsignedLong(int tag, BigInteger value) { + throw new UnsupportedOperationException("STUB!"); + } + + public List getUnsignedLongs(int tag) { + throw new UnsupportedOperationException("STUB!"); + } + + private void addLongTag(int tag, BigInteger value) { + throw new UnsupportedOperationException("STUB!"); + } + + private BigInteger getLongTagValue(KeymasterArgument arg) { + throw new UnsupportedOperationException("STUB!"); + } + + public void addBoolean(int tag) { + throw new UnsupportedOperationException("STUB!"); + } + + public boolean getBoolean(int tag) { + throw new UnsupportedOperationException("STUB!"); + } + + public void addBytes(int tag, byte[] value) { + throw new UnsupportedOperationException("STUB!"); + } + + public byte[] getBytes(int tag, byte[] defaultValue) { + throw new UnsupportedOperationException("STUB!"); + } + + public void addDate(int tag, Date value) { + throw new UnsupportedOperationException("STUB!"); + } + + public void addDateIfNotNull(int tag, Date value) { + throw new UnsupportedOperationException("STUB!"); + } + + public Date getDate(int tag, Date defaultValue) { + throw new UnsupportedOperationException("STUB!"); + } + + private KeymasterArgument getArgumentByTag(int tag) { + throw new UnsupportedOperationException("STUB!"); + } + + public boolean containsTag(int tag) { + throw new UnsupportedOperationException("STUB!"); + } + + public int size() { + throw new UnsupportedOperationException("STUB!"); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + throw new UnsupportedOperationException("STUB!"); + } + + public void readFromParcel(Parcel in) { + throw new UnsupportedOperationException("STUB!"); + } + + @Override + public int describeContents() { + throw new UnsupportedOperationException("STUB!"); + } + + public static BigInteger toUint64(long value) { + throw new UnsupportedOperationException("STUB!"); + } +} diff --git a/stub/src/main/java/android/security/keymaster/KeymasterCertificateChain.java b/stub/src/main/java/android/security/keymaster/KeymasterCertificateChain.java new file mode 100644 index 0000000..175ede3 --- /dev/null +++ b/stub/src/main/java/android/security/keymaster/KeymasterCertificateChain.java @@ -0,0 +1,42 @@ +package android.security.keymaster; + +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +import java.util.List; + +public class KeymasterCertificateChain implements Parcelable { + private List mCertificates; + + public KeymasterCertificateChain() { + this.mCertificates = null; + } + + public KeymasterCertificateChain(List mCertificates) { + this.mCertificates = mCertificates; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + throw new UnsupportedOperationException("STUB!"); + } + + @Override + public int describeContents() { + throw new UnsupportedOperationException("STUB!"); + } + + public static final Creator CREATOR = new Creator() { + @Override + public KeymasterCertificateChain createFromParcel(Parcel in) { + throw new UnsupportedOperationException("STUB!"); + } + + @Override + public KeymasterCertificateChain[] newArray(int size) { + throw new UnsupportedOperationException("STUB!"); + } + }; +} diff --git a/stub/src/main/java/android/security/keymaster/KeymasterDefs.java b/stub/src/main/java/android/security/keymaster/KeymasterDefs.java new file mode 100644 index 0000000..d601a46 --- /dev/null +++ b/stub/src/main/java/android/security/keymaster/KeymasterDefs.java @@ -0,0 +1,263 @@ +package android.security.keymaster; + +import java.util.HashMap; +import java.util.Map; + +public final class KeymasterDefs { + + private KeymasterDefs() { + } + + // Tag types. + public static final int KM_INVALID = 0 << 28; + public static final int KM_ENUM = 1 << 28; + public static final int KM_ENUM_REP = 2 << 28; + public static final int KM_UINT = 3 << 28; + public static final int KM_UINT_REP = 4 << 28; + public static final int KM_ULONG = 5 << 28; + public static final int KM_DATE = 6 << 28; + public static final int KM_BOOL = 7 << 28; + public static final int KM_BIGNUM = 8 << 28; + public static final int KM_BYTES = 9 << 28; + public static final int KM_ULONG_REP = 10 << 28; + + // Tag values. + public static final int KM_TAG_INVALID = KM_INVALID | 0; + public static final int KM_TAG_PURPOSE = KM_ENUM_REP | 1; + public static final int KM_TAG_ALGORITHM = KM_ENUM | 2; + public static final int KM_TAG_KEY_SIZE = KM_UINT | 3; + public static final int KM_TAG_BLOCK_MODE = KM_ENUM_REP | 4; + public static final int KM_TAG_DIGEST = KM_ENUM_REP | 5; + public static final int KM_TAG_PADDING = KM_ENUM_REP | 6; + public static final int KM_TAG_CALLER_NONCE = KM_BOOL | 7; + public static final int KM_TAG_MIN_MAC_LENGTH = KM_UINT | 8; + + public static final int KM_TAG_RESCOPING_ADD = KM_ENUM_REP | 101; + public static final int KM_TAG_RESCOPING_DEL = KM_ENUM_REP | 102; + public static final int KM_TAG_BLOB_USAGE_REQUIREMENTS = KM_ENUM | 705; + + public static final int KM_TAG_RSA_PUBLIC_EXPONENT = KM_ULONG | 200; + public static final int KM_TAG_INCLUDE_UNIQUE_ID = KM_BOOL | 202; + + public static final int KM_TAG_ACTIVE_DATETIME = KM_DATE | 400; + public static final int KM_TAG_ORIGINATION_EXPIRE_DATETIME = KM_DATE | 401; + public static final int KM_TAG_USAGE_EXPIRE_DATETIME = KM_DATE | 402; + public static final int KM_TAG_MIN_SECONDS_BETWEEN_OPS = KM_UINT | 403; + public static final int KM_TAG_MAX_USES_PER_BOOT = KM_UINT | 404; + + public static final int KM_TAG_ALL_USERS = KM_BOOL | 500; + public static final int KM_TAG_USER_ID = KM_UINT | 501; + public static final int KM_TAG_USER_SECURE_ID = KM_ULONG_REP | 502; + public static final int KM_TAG_NO_AUTH_REQUIRED = KM_BOOL | 503; + public static final int KM_TAG_USER_AUTH_TYPE = KM_ENUM | 504; + public static final int KM_TAG_AUTH_TIMEOUT = KM_UINT | 505; + public static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506; + public static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED = KM_BOOL | 507; + public static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED = KM_BOOL | 508; + public static final int KM_TAG_UNLOCKED_DEVICE_REQUIRED = KM_BOOL | 509; + + public static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600; + public static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601; + + public static final int KM_TAG_CREATION_DATETIME = KM_DATE | 701; + public static final int KM_TAG_ORIGIN = KM_ENUM | 702; + public static final int KM_TAG_ROLLBACK_RESISTANT = KM_BOOL | 703; + public static final int KM_TAG_ROOT_OF_TRUST = KM_BYTES | 704; + public static final int KM_TAG_UNIQUE_ID = KM_BYTES | 707; + public static final int KM_TAG_ATTESTATION_CHALLENGE = KM_BYTES | 708; + public static final int KM_TAG_ATTESTATION_ID_BRAND = KM_BYTES | 710; + public static final int KM_TAG_ATTESTATION_ID_DEVICE = KM_BYTES | 711; + public static final int KM_TAG_ATTESTATION_ID_PRODUCT = KM_BYTES | 712; + public static final int KM_TAG_ATTESTATION_ID_SERIAL = KM_BYTES | 713; + public static final int KM_TAG_ATTESTATION_ID_IMEI = KM_BYTES | 714; + public static final int KM_TAG_ATTESTATION_ID_MEID = KM_BYTES | 715; + public static final int KM_TAG_ATTESTATION_ID_MANUFACTURER = KM_BYTES | 716; + public static final int KM_TAG_ATTESTATION_ID_MODEL = KM_BYTES | 717; + public static final int KM_TAG_DEVICE_UNIQUE_ATTESTATION = KM_BOOL | 720; + + public static final int KM_TAG_ASSOCIATED_DATA = KM_BYTES | 1000; + public static final int KM_TAG_NONCE = KM_BYTES | 1001; + public static final int KM_TAG_AUTH_TOKEN = KM_BYTES | 1002; + public static final int KM_TAG_MAC_LENGTH = KM_UINT | 1003; + + // Algorithm values. + public static final int KM_ALGORITHM_RSA = 1; + public static final int KM_ALGORITHM_EC = 3; + public static final int KM_ALGORITHM_AES = 32; + public static final int KM_ALGORITHM_3DES = 33; + public static final int KM_ALGORITHM_HMAC = 128; + + // Block modes. + public static final int KM_MODE_ECB = 1; + public static final int KM_MODE_CBC = 2; + public static final int KM_MODE_CTR = 3; + public static final int KM_MODE_GCM = 32; + + // Padding modes. + public static final int KM_PAD_NONE = 1; + public static final int KM_PAD_RSA_OAEP = 2; + public static final int KM_PAD_RSA_PSS = 3; + public static final int KM_PAD_RSA_PKCS1_1_5_ENCRYPT = 4; + public static final int KM_PAD_RSA_PKCS1_1_5_SIGN = 5; + public static final int KM_PAD_PKCS7 = 64; + + // Digest modes. + public static final int KM_DIGEST_NONE = 0; + public static final int KM_DIGEST_MD5 = 1; + public static final int KM_DIGEST_SHA1 = 2; + public static final int KM_DIGEST_SHA_2_224 = 3; + public static final int KM_DIGEST_SHA_2_256 = 4; + public static final int KM_DIGEST_SHA_2_384 = 5; + public static final int KM_DIGEST_SHA_2_512 = 6; + + // Key origins. + public static final int KM_ORIGIN_GENERATED = 0; + public static final int KM_ORIGIN_IMPORTED = 2; + public static final int KM_ORIGIN_UNKNOWN = 3; + public static final int KM_ORIGIN_SECURELY_IMPORTED = 4; + + // Key usability requirements. + public static final int KM_BLOB_STANDALONE = 0; + public static final int KM_BLOB_REQUIRES_FILE_SYSTEM = 1; + + // Operation Purposes. + public static final int KM_PURPOSE_ENCRYPT = 0; + public static final int KM_PURPOSE_DECRYPT = 1; + public static final int KM_PURPOSE_SIGN = 2; + public static final int KM_PURPOSE_VERIFY = 3; + public static final int KM_PURPOSE_WRAP = 5; + + // Key formats. + public static final int KM_KEY_FORMAT_X509 = 0; + public static final int KM_KEY_FORMAT_PKCS8 = 1; + public static final int KM_KEY_FORMAT_RAW = 3; + + // User authenticators. + public static final int HW_AUTH_PASSWORD = 1 << 0; + public static final int HW_AUTH_BIOMETRIC = 1 << 1; + + // Error codes. + public static final int KM_ERROR_OK = 0; + public static final int KM_ERROR_ROOT_OF_TRUST_ALREADY_SET = -1; + public static final int KM_ERROR_UNSUPPORTED_PURPOSE = -2; + public static final int KM_ERROR_INCOMPATIBLE_PURPOSE = -3; + public static final int KM_ERROR_UNSUPPORTED_ALGORITHM = -4; + public static final int KM_ERROR_INCOMPATIBLE_ALGORITHM = -5; + public static final int KM_ERROR_UNSUPPORTED_KEY_SIZE = -6; + public static final int KM_ERROR_UNSUPPORTED_BLOCK_MODE = -7; + public static final int KM_ERROR_INCOMPATIBLE_BLOCK_MODE = -8; + public static final int KM_ERROR_UNSUPPORTED_MAC_LENGTH = -9; + public static final int KM_ERROR_UNSUPPORTED_PADDING_MODE = -10; + public static final int KM_ERROR_INCOMPATIBLE_PADDING_MODE = -11; + public static final int KM_ERROR_UNSUPPORTED_DIGEST = -12; + public static final int KM_ERROR_INCOMPATIBLE_DIGEST = -13; + public static final int KM_ERROR_INVALID_EXPIRATION_TIME = -14; + public static final int KM_ERROR_INVALID_USER_ID = -15; + public static final int KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT = -16; + public static final int KM_ERROR_UNSUPPORTED_KEY_FORMAT = -17; + public static final int KM_ERROR_INCOMPATIBLE_KEY_FORMAT = -18; + public static final int KM_ERROR_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = -19; + public static final int KM_ERROR_UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = -20; + public static final int KM_ERROR_INVALID_INPUT_LENGTH = -21; + public static final int KM_ERROR_KEY_EXPORT_OPTIONS_INVALID = -22; + public static final int KM_ERROR_DELEGATION_NOT_ALLOWED = -23; + public static final int KM_ERROR_KEY_NOT_YET_VALID = -24; + public static final int KM_ERROR_KEY_EXPIRED = -25; + public static final int KM_ERROR_KEY_USER_NOT_AUTHENTICATED = -26; + public static final int KM_ERROR_OUTPUT_PARAMETER_NULL = -27; + public static final int KM_ERROR_INVALID_OPERATION_HANDLE = -28; + public static final int KM_ERROR_INSUFFICIENT_BUFFER_SPACE = -29; + public static final int KM_ERROR_VERIFICATION_FAILED = -30; + public static final int KM_ERROR_TOO_MANY_OPERATIONS = -31; + public static final int KM_ERROR_UNEXPECTED_NULL_POINTER = -32; + public static final int KM_ERROR_INVALID_KEY_BLOB = -33; + public static final int KM_ERROR_IMPORTED_KEY_NOT_ENCRYPTED = -34; + public static final int KM_ERROR_IMPORTED_KEY_DECRYPTION_FAILED = -35; + public static final int KM_ERROR_IMPORTED_KEY_NOT_SIGNED = -36; + public static final int KM_ERROR_IMPORTED_KEY_VERIFICATION_FAILED = -37; + public static final int KM_ERROR_INVALID_ARGUMENT = -38; + public static final int KM_ERROR_UNSUPPORTED_TAG = -39; + public static final int KM_ERROR_INVALID_TAG = -40; + public static final int KM_ERROR_MEMORY_ALLOCATION_FAILED = -41; + public static final int KM_ERROR_INVALID_RESCOPING = -42; + public static final int KM_ERROR_IMPORT_PARAMETER_MISMATCH = -44; + public static final int KM_ERROR_SECURE_HW_ACCESS_DENIED = -45; + public static final int KM_ERROR_OPERATION_CANCELLED = -46; + public static final int KM_ERROR_CONCURRENT_ACCESS_CONFLICT = -47; + public static final int KM_ERROR_SECURE_HW_BUSY = -48; + public static final int KM_ERROR_SECURE_HW_COMMUNICATION_FAILED = -49; + public static final int KM_ERROR_UNSUPPORTED_EC_FIELD = -50; + public static final int KM_ERROR_MISSING_NONCE = -51; + public static final int KM_ERROR_INVALID_NONCE = -52; + public static final int KM_ERROR_MISSING_MAC_LENGTH = -53; + public static final int KM_ERROR_KEY_RATE_LIMIT_EXCEEDED = -54; + public static final int KM_ERROR_CALLER_NONCE_PROHIBITED = -55; + public static final int KM_ERROR_KEY_MAX_OPS_EXCEEDED = -56; + public static final int KM_ERROR_INVALID_MAC_LENGTH = -57; + public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH = -58; + public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59; + public static final int KM_ERROR_CANNOT_ATTEST_IDS = -66; + public static final int KM_ERROR_DEVICE_LOCKED = -72; + public static final int KM_ERROR_UNIMPLEMENTED = -100; + public static final int KM_ERROR_VERSION_MISMATCH = -101; + public static final int KM_ERROR_UNKNOWN_ERROR = -1000; + + public static final Map sErrorCodeToString = new HashMap(); + static { + sErrorCodeToString.put(KM_ERROR_OK, "OK"); + sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_PURPOSE, "Unsupported purpose"); + sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_PURPOSE, "Incompatible purpose"); + sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_ALGORITHM, "Unsupported algorithm"); + sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_ALGORITHM, "Incompatible algorithm"); + sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_KEY_SIZE, "Unsupported key size"); + sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_BLOCK_MODE, "Unsupported block mode"); + sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_BLOCK_MODE, "Incompatible block mode"); + sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_MAC_LENGTH, + "Unsupported MAC or authentication tag length"); + sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_PADDING_MODE, "Unsupported padding mode"); + sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_PADDING_MODE, "Incompatible padding mode"); + sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_DIGEST, "Unsupported digest"); + sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_DIGEST, "Incompatible digest"); + sErrorCodeToString.put(KM_ERROR_INVALID_EXPIRATION_TIME, "Invalid expiration time"); + sErrorCodeToString.put(KM_ERROR_INVALID_USER_ID, "Invalid user ID"); + sErrorCodeToString.put(KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT, + "Invalid user authorization timeout"); + sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_KEY_FORMAT, "Unsupported key format"); + sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_KEY_FORMAT, "Incompatible key format"); + sErrorCodeToString.put(KM_ERROR_INVALID_INPUT_LENGTH, "Invalid input length"); + sErrorCodeToString.put(KM_ERROR_KEY_NOT_YET_VALID, "Key not yet valid"); + sErrorCodeToString.put(KM_ERROR_KEY_EXPIRED, "Key expired"); + sErrorCodeToString.put(KM_ERROR_KEY_USER_NOT_AUTHENTICATED, "Key user not authenticated"); + sErrorCodeToString.put(KM_ERROR_INVALID_OPERATION_HANDLE, "Invalid operation handle"); + sErrorCodeToString.put(KM_ERROR_VERIFICATION_FAILED, "Signature/MAC verification failed"); + sErrorCodeToString.put(KM_ERROR_TOO_MANY_OPERATIONS, "Too many operations"); + sErrorCodeToString.put(KM_ERROR_INVALID_KEY_BLOB, "Invalid key blob"); + sErrorCodeToString.put(KM_ERROR_INVALID_ARGUMENT, "Invalid argument"); + sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_TAG, "Unsupported tag"); + sErrorCodeToString.put(KM_ERROR_INVALID_TAG, "Invalid tag"); + sErrorCodeToString.put(KM_ERROR_MEMORY_ALLOCATION_FAILED, "Memory allocation failed"); + sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_EC_FIELD, "Unsupported EC field"); + sErrorCodeToString.put(KM_ERROR_MISSING_NONCE, "Required IV missing"); + sErrorCodeToString.put(KM_ERROR_INVALID_NONCE, "Invalid IV"); + sErrorCodeToString.put(KM_ERROR_CALLER_NONCE_PROHIBITED, + "Caller-provided IV not permitted"); + sErrorCodeToString.put(KM_ERROR_INVALID_MAC_LENGTH, + "Invalid MAC or authentication tag length"); + sErrorCodeToString.put(KM_ERROR_CANNOT_ATTEST_IDS, "Unable to attest device ids"); + sErrorCodeToString.put(KM_ERROR_DEVICE_LOCKED, "Device locked"); + sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented"); + sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error"); + } + + public static int getTagType(int tag) { + return tag & (0xF << 28); + } + + public static String getErrorMessage(int errorCode) { + String result = sErrorCodeToString.get(errorCode); + if (result != null) { + return result; + } + return String.valueOf(errorCode); + } +} diff --git a/stub/src/main/java/android/security/keystore/IKeystoreCertificateChainCallback.java b/stub/src/main/java/android/security/keystore/IKeystoreCertificateChainCallback.java new file mode 100644 index 0000000..65f2513 --- /dev/null +++ b/stub/src/main/java/android/security/keystore/IKeystoreCertificateChainCallback.java @@ -0,0 +1,16 @@ +package android.security.keystore; + +import android.os.IBinder; +import android.os.RemoteException; +import android.security.keymaster.KeymasterCertificateChain; + +public interface IKeystoreCertificateChainCallback { + void onFinished(KeystoreResponse keystoreResponse, KeymasterCertificateChain keymasterCertificateChain) + throws RemoteException; + + public static abstract class Stub { + public static IKeystoreCertificateChainCallback asInterface(IBinder b) { + throw new UnsupportedOperationException("STUB!"); + } + } +} diff --git a/stub/src/main/java/android/security/keystore/IKeystoreExportKeyCallback.java b/stub/src/main/java/android/security/keystore/IKeystoreExportKeyCallback.java new file mode 100644 index 0000000..7ece585 --- /dev/null +++ b/stub/src/main/java/android/security/keystore/IKeystoreExportKeyCallback.java @@ -0,0 +1,15 @@ +package android.security.keystore; + +import android.os.IBinder; +import android.os.RemoteException; +import android.security.keymaster.ExportResult; + +public interface IKeystoreExportKeyCallback { + void onFinished(ExportResult exportResult) throws RemoteException; + + public static abstract class Stub { + public static IKeystoreExportKeyCallback asInterface(IBinder b) { + throw new UnsupportedOperationException("STUB!"); + } + } +} diff --git a/stub/src/main/java/android/security/keystore/IKeystoreKeyCharacteristicsCallback.java b/stub/src/main/java/android/security/keystore/IKeystoreKeyCharacteristicsCallback.java new file mode 100644 index 0000000..2e9c8b6 --- /dev/null +++ b/stub/src/main/java/android/security/keystore/IKeystoreKeyCharacteristicsCallback.java @@ -0,0 +1,16 @@ +package android.security.keystore; + +import android.os.IBinder; +import android.os.IInterface; +import android.os.RemoteException; +import android.security.keymaster.KeyCharacteristics; + +public interface IKeystoreKeyCharacteristicsCallback extends IInterface { + void onFinished(KeystoreResponse keystoreResponse, KeyCharacteristics keyCharacteristics) throws RemoteException; + + public static abstract class Stub { + public static IKeystoreKeyCharacteristicsCallback asInterface(IBinder b) { + throw new UnsupportedOperationException("STUB!"); + } + } +} diff --git a/stub/src/main/java/android/security/keystore/IKeystoreService.java b/stub/src/main/java/android/security/keystore/IKeystoreService.java index 6a866aa..420d3ad 100644 --- a/stub/src/main/java/android/security/keystore/IKeystoreService.java +++ b/stub/src/main/java/android/security/keystore/IKeystoreService.java @@ -1,7 +1,10 @@ package android.security.keystore; +import java.lang.String; + public interface IKeystoreService { + public static final String DESCRIPTOR = "android.security.keystore.IKeystoreService"; + class Stub { } } - diff --git a/stub/src/main/java/android/security/keystore/KeystoreResponse.java b/stub/src/main/java/android/security/keystore/KeystoreResponse.java new file mode 100644 index 0000000..08d942d --- /dev/null +++ b/stub/src/main/java/android/security/keystore/KeystoreResponse.java @@ -0,0 +1,38 @@ +package android.security.keystore; + +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +public class KeystoreResponse implements Parcelable { + public final int error_code_; + public final String error_msg_; + + protected KeystoreResponse(int error_code, String error_msg) { + this.error_code_ = error_code; + this.error_msg_ = error_msg; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + throw new UnsupportedOperationException("STUB!"); + } + + @Override + public int describeContents() { + throw new UnsupportedOperationException("STUB!"); + } + + public static final Creator CREATOR = new Creator() { + @Override + public KeystoreResponse createFromParcel(Parcel in) { + throw new UnsupportedOperationException("STUB!"); + } + + @Override + public KeystoreResponse[] newArray(int size) { + throw new UnsupportedOperationException("STUB!"); + } + }; +}