fix(attestation): correct leaf CN casing and enforce keystore2 parameter policy
Leaf cert Subject CN used "KeyStore" (capital S) but AOSP KeyGenParameterSpec uses "Keystore" (lowercase s). Fixed in both the Rust native certgen and BouncyCastle paths. Replicate keystore2's security_level.rs parameter validation for software-generated keys: reject CREATION_DATETIME (output-only tag, ResponseCode 20) and device ID attestation tags (CANNOT_ATTEST_IDS -66) that real keystore2 blocks before they reach the HAL. Also fix createErrorReply parcel write order, AIDL protocol expects exception_code, message, error_code but we had message and error_code swapped, causing malformed replies for positive error codes.
This commit is contained in:
@@ -17,8 +17,8 @@ object InterceptorUtils {
|
|||||||
fun createErrorReply(errorCode: Int): BinderInterceptor.TransactionResult.OverrideReply {
|
fun createErrorReply(errorCode: Int): BinderInterceptor.TransactionResult.OverrideReply {
|
||||||
val parcel = Parcel.obtain().apply {
|
val parcel = Parcel.obtain().apply {
|
||||||
writeInt(EX_SERVICE_SPECIFIC)
|
writeInt(EX_SERVICE_SPECIFIC)
|
||||||
writeInt(errorCode)
|
|
||||||
writeString(null)
|
writeString(null)
|
||||||
|
writeInt(errorCode)
|
||||||
}
|
}
|
||||||
return BinderInterceptor.TransactionResult.OverrideReply(parcel)
|
return BinderInterceptor.TransactionResult.OverrideReply(parcel)
|
||||||
}
|
}
|
||||||
|
|||||||
+14
@@ -254,6 +254,18 @@ class KeyMintSecurityLevelInterceptor(
|
|||||||
return InterceptorUtils.createErrorReply(KEYMINT_INVALID_INPUT_LENGTH)
|
return InterceptorUtils.createErrorReply(KEYMINT_INVALID_INPUT_LENGTH)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.any { it.tag == Tag.CREATION_DATETIME }) {
|
||||||
|
SystemLogger.warning("[TX_ID: $txId] Rejecting CREATION_DATETIME in generateKey params")
|
||||||
|
return InterceptorUtils.createErrorReply(RESPONSE_INVALID_ARGUMENT)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedParams.serial != null || parsedParams.imei != null ||
|
||||||
|
parsedParams.meid != null || parsedParams.secondImei != null ||
|
||||||
|
params.any { it.tag == Tag.DEVICE_UNIQUE_ATTESTATION }) {
|
||||||
|
SystemLogger.warning("[TX_ID: $txId] Rejecting device ID attestation for uid=$callingUid")
|
||||||
|
return InterceptorUtils.createErrorReply(KEYMINT_CANNOT_ATTEST_IDS)
|
||||||
|
}
|
||||||
|
|
||||||
val keyId = KeyIdentifier(callingUid, keyDescriptor.alias)
|
val keyId = KeyIdentifier(callingUid, keyDescriptor.alias)
|
||||||
val isAttestKeyRequest = parsedParams.isAttestKey()
|
val isAttestKeyRequest = parsedParams.isAttestKey()
|
||||||
|
|
||||||
@@ -515,6 +527,8 @@ class KeyMintSecurityLevelInterceptor(
|
|||||||
// Binder buffer is ~1MB; 256KB provides 4x safety margin for transaction overhead
|
// Binder buffer is ~1MB; 256KB provides 4x safety margin for transaction overhead
|
||||||
private const val MAX_ALIAS_LENGTH = 256 * 1024
|
private const val MAX_ALIAS_LENGTH = 256 * 1024
|
||||||
private const val KEYMINT_INVALID_INPUT_LENGTH = -21
|
private const val KEYMINT_INVALID_INPUT_LENGTH = -21
|
||||||
|
private const val RESPONSE_INVALID_ARGUMENT = 20
|
||||||
|
private const val KEYMINT_CANNOT_ATTEST_IDS = -66
|
||||||
private const val MAX_CONCURRENT_HW_KEYGEN_PER_UID = 2
|
private const val MAX_CONCURRENT_HW_KEYGEN_PER_UID = 2
|
||||||
// Sliding window: max hardware keygen permits per UID within the burst window
|
// Sliding window: max hardware keygen permits per UID within the burst window
|
||||||
private const val MAX_HW_KEYGEN_PER_WINDOW = 2
|
private const val MAX_HW_KEYGEN_PER_WINDOW = 2
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ object CertificateGenerator {
|
|||||||
uid: Int,
|
uid: Int,
|
||||||
securityLevel: Int,
|
securityLevel: Int,
|
||||||
): Certificate {
|
): Certificate {
|
||||||
val subject = params.certificateSubject ?: X500Name("CN=Android KeyStore Key")
|
val subject = params.certificateSubject ?: X500Name("CN=Android Keystore Key")
|
||||||
val leafNotAfter =
|
val leafNotAfter =
|
||||||
(signingKeyPair.public as? X509Certificate)?.notAfter
|
(signingKeyPair.public as? X509Certificate)?.notAfter
|
||||||
?: Date(System.currentTimeMillis() + 31536000000L)
|
?: Date(System.currentTimeMillis() + 31536000000L)
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ fn build_leaf_cert(
|
|||||||
let subject_dn_der = if let Some(ref subject) = params.cert_subject {
|
let subject_dn_der = if let Some(ref subject) = params.cert_subject {
|
||||||
subject.clone()
|
subject.clone()
|
||||||
} else {
|
} else {
|
||||||
encode_simple_cn_dn("Android KeyStore Key")
|
encode_simple_cn_dn("Android Keystore Key")
|
||||||
};
|
};
|
||||||
|
|
||||||
// Validity
|
// Validity
|
||||||
|
|||||||
Reference in New Issue
Block a user