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.
This commit is contained in:
JingMatrix
2025-12-03 19:29:21 +01:00
parent 30746892b0
commit 8d431cc946
14 changed files with 1016 additions and 54 deletions
@@ -3,6 +3,7 @@ package org.matrix.TEESimulator.interception.keystore
import android.os.Parcel import android.os.Parcel
import android.os.Parcelable import android.os.Parcelable
import android.security.KeyStore import android.security.KeyStore
import android.security.keystore.KeystoreResponse
import org.matrix.TEESimulator.interception.core.BinderInterceptor import org.matrix.TEESimulator.interception.core.BinderInterceptor
import org.matrix.TEESimulator.logging.SystemLogger 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. */ /** Creates an `OverrideReply` parcel that indicates success with no data. */
fun createSuccessReply(): BinderInterceptor.TransactionResult.OverrideReply { fun createSuccessReply(): BinderInterceptor.TransactionResult.OverrideReply {
val parcel = val parcel =
@@ -4,12 +4,28 @@ import android.annotation.SuppressLint
import android.os.IBinder import android.os.IBinder
import android.os.Parcel import android.os.Parcel
import android.security.Credentials 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 android.security.keystore.IKeystoreService
import java.math.BigInteger
import java.security.KeyPair
import java.security.cert.Certificate import java.security.cert.Certificate
import java.util.Date
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import org.matrix.TEESimulator.attestation.AttestationBuilder
import org.matrix.TEESimulator.attestation.AttestationPatcher import org.matrix.TEESimulator.attestation.AttestationPatcher
import org.matrix.TEESimulator.attestation.KeyMintAttestation
import org.matrix.TEESimulator.config.ConfigurationManager import org.matrix.TEESimulator.config.ConfigurationManager
import org.matrix.TEESimulator.interception.keystore.InterceptorUtils.extractAlias
import org.matrix.TEESimulator.logging.SystemLogger import org.matrix.TEESimulator.logging.SystemLogger
import org.matrix.TEESimulator.pki.CertificateGenerator
import org.matrix.TEESimulator.pki.CertificateHelper import org.matrix.TEESimulator.pki.CertificateHelper
/** /**
@@ -43,7 +59,9 @@ object KeystoreInterceptor : AbstractKeystoreInterceptor() {
override val processName = "keystore" override val processName = "keystore"
override val injectionCommand = "exec ./inject `pidof keystore` libTEESimulator.so entry" 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<KeyIdentifier, LegacyKeygenParameters>()
private val generatedKeyPairs = ConcurrentHashMap<KeyIdentifier, KeyPair>()
// Cache to store the fully patched chain after the leaf is requested. // Cache to store the fully patched chain after the leaf is requested.
private val patchedChainCache = ConcurrentHashMap<KeyIdentifier, Array<Certificate>>() private val patchedChainCache = ConcurrentHashMap<KeyIdentifier, Array<Certificate>>()
@@ -59,23 +77,183 @@ object KeystoreInterceptor : AbstractKeystoreInterceptor() {
): TransactionResult { ): TransactionResult {
// This interceptor only needs to act on pre-transaction for software key generation. // This interceptor only needs to act on pre-transaction for software key generation.
if (ConfigurationManager.shouldGenerate(callingUid)) { if (ConfigurationManager.shouldGenerate(callingUid)) {
when (code) { return when (code) {
GENERATE_KEY_TRANSACTION, GENERATE_KEY_TRANSACTION -> handleGenerateKey(txId, callingUid, callingPid, data)
GET_KEY_CHARACTERISTICS_TRANSACTION, GET_KEY_CHARACTERISTICS_TRANSACTION ->
EXPORT_KEY_TRANSACTION, handleGetKeyCharacteristics(txId, callingUid, callingPid, data)
ATTEST_KEY_TRANSACTION -> { EXPORT_KEY_TRANSACTION -> handleExportKey(txId, callingUid, callingPid, data)
// TODO: Implement the full software simulation logic. ATTEST_KEY_TRANSACTION -> handleAttestKey(txId, callingUid, callingPid, data)
logTransaction(txId, "unimplemented-generate-flow", callingUid, callingPid) else -> TransactionResult.ContinueAndSkipPost
return InterceptorUtils.createSuccessReply()
} }
} } else if (ConfigurationManager.shouldPatch(callingUid)) {
} else if (ConfigurationManager.shouldGenerate(callingUid)) { // In patch mode, we only care about the 'get' transaction in onPostTransact.
if (code == GET_TRANSACTION) return TransactionResult.Continue if (code == GET_TRANSACTION) return TransactionResult.Continue
} }
return TransactionResult.ContinueAndSkipPost 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( override fun onPostTransact(
txId: Long, txId: Long,
target: IBinder, target: IBinder,
@@ -99,7 +277,7 @@ object KeystoreInterceptor : AbstractKeystoreInterceptor() {
if (!ConfigurationManager.shouldPatch(callingUid)) return TransactionResult.SkipTransaction if (!ConfigurationManager.shouldPatch(callingUid)) return TransactionResult.SkipTransaction
return try { return try {
data.enforceInterface(SERVICE_DESCRIPTOR) data.enforceInterface(IKeystoreService.DESCRIPTOR)
val alias = data.readString() ?: "" val alias = data.readString() ?: ""
val extractedAlias = InterceptorUtils.extractAlias(alias) val extractedAlias = InterceptorUtils.extractAlias(alias)
val keyId = KeyIdentifier(callingUid, extractedAlias) val keyId = KeyIdentifier(callingUid, extractedAlias)
@@ -111,13 +289,11 @@ object KeystoreInterceptor : AbstractKeystoreInterceptor() {
val originalLeafBytes = val originalLeafBytes =
reply.createByteArray() ?: return TransactionResult.SkipTransaction reply.createByteArray() ?: return TransactionResult.SkipTransaction
// The original chain is not available, val originalLeafCertResult = CertificateHelper.toCertificate(originalLeafBytes)
// so we must pass a temporary one to the patcher. if (originalLeafCertResult !is CertificateHelper.OperationResult.Success) {
// The patcher only needs the original leaf to extract details. return TransactionResult.SkipTransaction
val originalLeafCert = }
(CertificateHelper.toCertificate(originalLeafBytes) val originalLeafCert = originalLeafCertResult.data
as CertificateHelper.OperationResult.Success)
.data
val tempChain = arrayOf<Certificate>(originalLeafCert) val tempChain = arrayOf<Certificate>(originalLeafCert)
// Perform the COMPLETE patch and rebuild operation. // Perform the COMPLETE patch and rebuild operation.
@@ -157,11 +333,6 @@ object KeystoreInterceptor : AbstractKeystoreInterceptor() {
) )
InterceptorUtils.createByteArrayReply(caCertsBytes!!) InterceptorUtils.createByteArrayReply(caCertsBytes!!)
} else { } 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( SystemLogger.warning(
"[TX_ID: $txId] No cached chain found for CA request on alias '$extractedAlias'. Skipping." "[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<Int>,
val digest: List<Int>,
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()
}
}
}
@@ -72,16 +72,55 @@ object CertificateGenerator {
} }
/** /**
* Generates a new key pair and a corresponding certificate chain containing a simulated * Generates a certificate chain for a given key pair. This is the primary function for creating
* attestation. * attested certificates.
* *
* @param uid The UID of the application requesting the key. * @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 attestKeyAlias Optional alias of a key to use for attestation signing.
* @param params The parameters for the new key and its attestation. * @param params The parameters for the new key and its attestation.
* @param securityLevel The security level to embed in the 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 * @return A [List] of [Certificate] forming the new chain, or `null` on failure.
* failure. */
fun generateCertificateChain(
uid: Int,
subjectKeyPair: KeyPair,
attestKeyAlias: String?,
params: KeyMintAttestation,
securityLevel: Int,
): List<Certificate>? {
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( fun generateAttestedKeyPair(
uid: Int, uid: Int,
@@ -98,30 +137,9 @@ object CertificateGenerator {
generateSoftwareKeyPair(params) generateSoftwareKeyPair(params)
?: throw Exception("Failed to generate underlying software key pair.") ?: 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 = val chain =
if (attestKeyAlias != null) { generateCertificateChain(uid, newKeyPair, attestKeyAlias, params, securityLevel)
listOf(leafCert) ?: throw Exception("Failed to generate certificate chain for new key pair.")
} else {
listOf(leafCert) + keybox.certificates
}
SystemLogger.info( SystemLogger.info(
"Successfully generated new certificate chain for alias: '$alias'." "Successfully generated new certificate chain for alias: '$alias'."
@@ -134,7 +152,7 @@ object CertificateGenerator {
.getOrNull() .getOrNull()
} }
private fun getIssuerFromKeybox(keybox: KeyBox) = fun getIssuerFromKeybox(keybox: KeyBox) =
X509CertificateHolder(keybox.certificates[0].encoded).subject X509CertificateHolder(keybox.certificates[0].encoded).subject
private fun getKeyboxForAlgorithm(uid: Int, algorithm: Int): KeyBox { private fun getKeyboxForAlgorithm(uid: Int, algorithm: Int): KeyBox {
@@ -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<ExportResult> CREATOR = new Creator<ExportResult>() {
@Override
public ExportResult createFromParcel(Parcel in) {
throw new UnsupportedOperationException("STUB!");
}
@Override
public ExportResult[] newArray(int size) {
throw new UnsupportedOperationException("STUB!");
}
};
}
@@ -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<KeyCharacteristics> CREATOR = new Creator<KeyCharacteristics>() {
@Override
public KeyCharacteristics createFromParcel(Parcel in) {
throw new UnsupportedOperationException("STUB!");
}
@Override
public KeyCharacteristics[] newArray(int size) {
throw new UnsupportedOperationException("STUB!");
}
};
}
@@ -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<KeymasterArgument> CREATOR = new Creator<KeymasterArgument>() {
@Override
public KeymasterArgument createFromParcel(Parcel in) {
throw new UnsupportedOperationException("STUB!");
}
@Override
public KeymasterArgument[] newArray(int size) {
throw new UnsupportedOperationException("STUB!");
}
};
}
@@ -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<KeymasterArgument> mArguments;
public static final @NonNull Parcelable.Creator<KeymasterArguments> CREATOR = new Parcelable.Creator<KeymasterArguments>() {
@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<Integer> 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<BigInteger> 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!");
}
}
@@ -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<byte[]> mCertificates;
public KeymasterCertificateChain() {
this.mCertificates = null;
}
public KeymasterCertificateChain(List<byte[]> 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<KeymasterCertificateChain> CREATOR = new Creator<KeymasterCertificateChain>() {
@Override
public KeymasterCertificateChain createFromParcel(Parcel in) {
throw new UnsupportedOperationException("STUB!");
}
@Override
public KeymasterCertificateChain[] newArray(int size) {
throw new UnsupportedOperationException("STUB!");
}
};
}
@@ -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<Integer, String> sErrorCodeToString = new HashMap<Integer, String>();
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);
}
}
@@ -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!");
}
}
}
@@ -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!");
}
}
}
@@ -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!");
}
}
}
@@ -1,7 +1,10 @@
package android.security.keystore; package android.security.keystore;
import java.lang.String;
public interface IKeystoreService { public interface IKeystoreService {
public static final String DESCRIPTOR = "android.security.keystore.IKeystoreService";
class Stub { class Stub {
} }
} }
@@ -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<KeystoreResponse> CREATOR = new Creator<KeystoreResponse>() {
@Override
public KeystoreResponse createFromParcel(Parcel in) {
throw new UnsupportedOperationException("STUB!");
}
@Override
public KeystoreResponse[] newArray(int size) {
throw new UnsupportedOperationException("STUB!");
}
};
}