Add "key owned by system" optional requirement in AVF
Introduce "android.key_owned_by_system" optional requirement to AttestationVerificationPeerDeviceVerifier that may be used with both supprted binding types - TYPE_PUBLIC_KEY and TYPE_CHALLENGE. Implement checking if the leaf certificate public key is owned by the system if the "android.key_owned_by_system" key is present in the requiremenets bundle. Bug: 224954254 Bug: 202926196 Test: AVF tests Change-Id: I79ca0ff2263bd8babb7dace1a9a3f8848ab21454
This commit is contained in:
@@ -96,6 +96,21 @@ class AttestationVerificationPeerDeviceVerifier {
|
||||
private static final boolean DEBUG = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.VERBOSE);
|
||||
private static final int MAX_PATCH_AGE_MONTHS = 12;
|
||||
|
||||
/**
|
||||
* Optional requirements bundle parameter key for {@code TYPE_PUBLIC_KEY} and
|
||||
* {@code TYPE_CHALLENGE}.
|
||||
*
|
||||
* <p>
|
||||
* This is NOT a part of the AVF API surface (neither public SDK nor internal to the
|
||||
* system_server) and should really only be used by the CompanionDeviceManagerService (which
|
||||
* duplicates the value rather than referencing it directly here).
|
||||
*/
|
||||
private static final String PARAM_OWNED_BY_SYSTEM = "android.key_owned_by_system";
|
||||
|
||||
private static final String ANDROID_SYSTEM_PACKAGE_NAME = "AndroidSystem";
|
||||
private static final Set<String> ANDROID_SYSTEM_PACKAGE_NAME_SET =
|
||||
Collections.singleton(ANDROID_SYSTEM_PACKAGE_NAME);
|
||||
|
||||
private final Context mContext;
|
||||
private final Set<TrustAnchor> mTrustAnchors;
|
||||
private final boolean mRevocationEnabled;
|
||||
@@ -170,7 +185,7 @@ class AttestationVerificationPeerDeviceVerifier {
|
||||
final var leafCertificate = certificateChain.get(0);
|
||||
final var attestationExtension = fromCertificate(leafCertificate);
|
||||
|
||||
// Second: verify if the attestation satisfies the "peer device" porfile.
|
||||
// Second: verify if the attestation satisfies the "peer device" profile.
|
||||
if (!checkAttestationForPeerDeviceProfile(attestationExtension)) {
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
@@ -220,8 +235,8 @@ class AttestationVerificationPeerDeviceVerifier {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (requirements.size() != 1) {
|
||||
debugVerboseLog("Requirements does not contain exactly 1 key.");
|
||||
if (requirements.size() < 1) {
|
||||
debugVerboseLog("At least 1 requirement is required.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -293,6 +308,7 @@ class AttestationVerificationPeerDeviceVerifier {
|
||||
@NonNull AndroidKeystoreAttestationVerificationAttributes attestationAttributes,
|
||||
@LocalBindingType int localBindingType,
|
||||
@NonNull Bundle requirements) {
|
||||
// First: check non-optional (for the given local binding type) requirements.
|
||||
switch (localBindingType) {
|
||||
case TYPE_PUBLIC_KEY:
|
||||
// Verify leaf public key matches provided public key.
|
||||
@@ -321,6 +337,24 @@ class AttestationVerificationPeerDeviceVerifier {
|
||||
+ localBindingTypeToString(localBindingType));
|
||||
}
|
||||
|
||||
// Second: check specified optional requirements.
|
||||
if (requirements.containsKey(PARAM_OWNED_BY_SYSTEM)) {
|
||||
if (requirements.getBoolean(PARAM_OWNED_BY_SYSTEM)) {
|
||||
// Verify key is owned by the system.
|
||||
final boolean ownedBySystem = checkOwnedBySystem(
|
||||
leafCertificate, attestationAttributes);
|
||||
if (!ownedBySystem) {
|
||||
debugVerboseLog("Certificate public key is not owned by the AndroidSystem.");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("The value of the requirement key "
|
||||
+ PARAM_OWNED_BY_SYSTEM
|
||||
+ " cannot be false. You can remove the key if you don't want to verify "
|
||||
+ "it.");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -407,6 +441,18 @@ class AttestationVerificationPeerDeviceVerifier {
|
||||
return Arrays.equals(challenge, expectedChallenge);
|
||||
}
|
||||
|
||||
private boolean checkOwnedBySystem(@NonNull X509Certificate certificate,
|
||||
@NonNull AndroidKeystoreAttestationVerificationAttributes attestationAttributes) {
|
||||
final Set<String> ownerPackages =
|
||||
attestationAttributes.getApplicationPackageNameVersion().keySet();
|
||||
if (!ANDROID_SYSTEM_PACKAGE_NAME_SET.equals(ownerPackages)) {
|
||||
debugVerboseLog("Owner is not system, packages=" + ownerPackages);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates patchLevel passed is within range of the local device patch date if local patch is
|
||||
* not over one year old. Since the time can be changed on device, just checking the patch date
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIClzCCAjygAwIBAgIBATAKBggqhkjOPQQDAjA5MQwwCgYDVQQMDANURUUxKTAn
|
||||
BgNVBAUTIDRiY2Q3MzM5MjZmZDkwYjhlMDE1ZDczYmIxYmE0MjZhMCAXDTIzMDIw
|
||||
OTAwMDQwMloYDzIyOTYxMTI0MDAwNDAyWjAfMR0wGwYDVQQDExRBbmRyb2lkIEtl
|
||||
eXN0b3JlIEtleTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAxz70D0rX31tqv+
|
||||
mMjyet+KlfVF4h5zJeHVP6BPtqP9AM/l0KQEuttYEKbtmw4k/phS9hdjHoiitUTO
|
||||
7gD5gRqjggFLMIIBRzAOBgNVHQ8BAf8EBAMCB4AwggEzBgorBgEEAdZ5AgERBIIB
|
||||
IzCCAR8CAgDICgEBAgIAyAoBAQQRYWN0aXZlVW5sb2NrVmFsaWQEADBQv4MQCAIG
|
||||
AYYzfH33v4MRCAIGCWHbnf33v4MSCAIGCWHbnf33v4U9CAIGAYYzfICnv4VFHAQa
|
||||
MBgxFDASBA1BbmRyb2lkU3lzdGVtAgEBMQAwgaehCDEGAgECAgEDogMCAQOjBAIC
|
||||
AQClCDEGAgEEAgEGqgMCAQG/g3cCBQC/hT4DAgEAv4VATDBKBCAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAAoBAgQguYuTO2l0Dwq5FwpSl+Selr+Y
|
||||
ky0NvCPbBXFMqRVWStW/hUEFAgMB+9C/hUIFAgMDFj+/hU4GAgQBNLChv4VPBgIE
|
||||
ATSwoTAKBggqhkjOPQQDAgNJADBGAiEA9+6Y5LEvdxER46O3V+2H4MYn1ILLJk56
|
||||
Uo5uGZqbIfECIQDtITu0l4fKeTVE3sQo50oFd4iCVKVp62PlpTEJ+D1hOQ==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB8zCCAXmgAwIBAgIQD9aWSuFM+VgqbBcSDskVWjAKBggqhkjOPQQDAjA5MQww
|
||||
CgYDVQQMDANURUUxKTAnBgNVBAUTIDRiODI4ZTI2MjM2YjRmMGJiNjIwZWRiZjI4
|
||||
MTRiMmQyMB4XDTIxMDExMzIwNTkxOVoXDTMxMDExMTIwNTkxOVowOTEMMAoGA1UE
|
||||
DAwDVEVFMSkwJwYDVQQFEyA0YmNkNzMzOTI2ZmQ5MGI4ZTAxNWQ3M2JiMWJhNDI2
|
||||
YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKhknO2s1yuEK9NXTneVzwHXVL9N
|
||||
+AyjLIakshRvMupH341gZNI8H9nuGomXhfPLH4igCB50IIdpjZyUe87DWrmjYzBh
|
||||
MB0GA1UdDgQWBBSVB/mrPxEP0okhRNeyAxgtM1KDlzAfBgNVHSMEGDAWgBRGO8we
|
||||
F/IGW5HwMQUf5yM8ZmQ/JjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIC
|
||||
BDAKBggqhkjOPQQDAgNoADBlAjEA0+6jQMnBNqmzHGRTjrq6bC5PHlF/nN4FOLt3
|
||||
a8HhiiXAKddnq38PBI5JBM/+kT7jAjBMpt56pMdwDWag+c+FCB1wCtRvIVic6ATU
|
||||
EvY+ZsuRQ0d1ZGvfO3s79j9T/xv7B7E=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDkzCCAXugAwIBAgIQBMTs9wahoh5aI97uDtkVIjANBgkqhkiG9w0BAQsFADAb
|
||||
MRkwFwYDVQQFExBmOTIwMDllODUzYjZiMDQ1MB4XDTIxMDExMzIwNTgyM1oXDTMx
|
||||
MDExMTIwNTgyM1owOTEMMAoGA1UEDAwDVEVFMSkwJwYDVQQFEyA0YjgyOGUyNjIz
|
||||
NmI0ZjBiYjYyMGVkYmYyODE0YjJkMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJTy
|
||||
ijqyb9Ay9rys3DDQgn2Lr8n/NDzKmbmITHWWrnbc2POKyCBzcBXo597ewSyLgQcp
|
||||
CKSW7R2vRzTWvxFHVNRdEM1H3k4OKhQS8VpTVeHIlGsN37G6jXJJpFhHOW40uqNj
|
||||
MGEwHQYDVR0OBBYEFEY7zB4X8gZbkfAxBR/nIzxmZD8mMB8GA1UdIwQYMBaAFDZh
|
||||
4QB8iAUJUYtEbEf/GkzJ6k8SMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
|
||||
AgIEMA0GCSqGSIb3DQEBCwUAA4ICAQBFoMIAhtEFxu5YUKD7WJj4X8nTRAK7W1Li
|
||||
X3AssR769CyrNO5OttkU+5LQb8EGyGs90OhTy/eA7m1sPAh4mMHV5yL+td/Sdg2j
|
||||
fZ2ZBayeZuteihaLwB9SpHKUPR3+VDMPBNevUWLpjiwRfbNzb1A40LlRIsfFFs2s
|
||||
I33WVcpEH5KAj5ci7UtRIF8ryw3FyFNsbHqvdVf1Wet4JosIhnbZuOruB4qUq8oW
|
||||
ZOi6nXBKnY+ebdZusPRUE/6h8pDS5xZrN/is2HmFDXuEjuMibw1bZirQ5cygn+fQ
|
||||
DUjjK+4/k/IlfoLL8A07XdrtlYynMZm88FzB5tkwdwXkJTW8l+vZv6fhXv34go6N
|
||||
MoZNpLZZaoJDckvpPP4oXdpOLtUJyaNoMWPtn97q8eQklkHK1e8SSfYN5GShCxOF
|
||||
wC+797rRfm1qG2CLZ3lMsI70AGOFAyb76VS0s8vpTjDbU5RBHQqfZ1HbYzRSt8GS
|
||||
4QlOeJx71IZjI8F3BhkjrQncjKLrcF+lDUA/AVuezn2kxAAeNiNHYWrDq+C6Odaj
|
||||
PIr4DDrtfgsnemBy7TG2eubWmc761DVqtgP/To7QySg7vbwqNsX3BcJsE0AeD1Jy
|
||||
0BhfNgvhhq9N8zlzLhv4dAHK/HiRQdtb7Z6qEPawihXxY5so3R+K4shfHet98Ri9
|
||||
naCVlMdaOg==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFHDCCAwSgAwIBAgIJANUP8luj8tazMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV
|
||||
BAUTEGY5MjAwOWU4NTNiNmIwNDUwHhcNMTkxMTIyMjAzNzU4WhcNMzQxMTE4MjAz
|
||||
NzU4WjAbMRkwFwYDVQQFExBmOTIwMDllODUzYjZiMDQ1MIICIjANBgkqhkiG9w0B
|
||||
AQEFAAOCAg8AMIICCgKCAgEAr7bHgiuxpwHsK7Qui8xUFmOr75gvMsd/dTEDDJdS
|
||||
Sxtf6An7xyqpRR90PL2abxM1dEqlXnf2tqw1Ne4Xwl5jlRfdnJLmN0pTy/4lj4/7
|
||||
tv0Sk3iiKkypnEUtR6WfMgH0QZfKHM1+di+y9TFRtv6y//0rb+T+W8a9nsNL/ggj
|
||||
nar86461qO0rOs2cXjp3kOG1FEJ5MVmFmBGtnrKpa73XpXyTqRxB/M0n1n/W9nGq
|
||||
C4FSYa04T6N5RIZGBN2z2MT5IKGbFlbC8UrW0DxW7AYImQQcHtGl/m00QLVWutHQ
|
||||
oVJYnFPlXTcHYvASLu+RhhsbDmxMgJJ0mcDpvsC4PjvB+TxywElgS70vE0XmLD+O
|
||||
JtvsBslHZvPBKCOdT0MS+tgSOIfga+z1Z1g7+DVagf7quvmag8jfPioyKvxnK/Eg
|
||||
sTUVi2ghzq8wm27ud/mIM7AY2qEORR8Go3TVB4HzWQgpZrt3i5MIlCaY504LzSRi
|
||||
igHCzAPlHws+W0rB5N+er5/2pJKnfBSDiCiFAVtCLOZ7gLiMm0jhO2B6tUXHI/+M
|
||||
RPjy02i59lINMRRev56GKtcd9qO/0kUJWdZTdA2XoS82ixPvZtXQpUpuL12ab+9E
|
||||
aDK8Z4RHJYYfCT3Q5vNAXaiWQ+8PTWm2QgBR/bkwSWc+NpUFgNPN9PvQi8WEg5Um
|
||||
AGMCAwEAAaNjMGEwHQYDVR0OBBYEFDZh4QB8iAUJUYtEbEf/GkzJ6k8SMB8GA1Ud
|
||||
IwQYMBaAFDZh4QB8iAUJUYtEbEf/GkzJ6k8SMA8GA1UdEwEB/wQFMAMBAf8wDgYD
|
||||
VR0PAQH/BAQDAgIEMA0GCSqGSIb3DQEBCwUAA4ICAQBOMaBc8oumXb2voc7XCWnu
|
||||
XKhBBK3e2KMGz39t7lA3XXRe2ZLLAkLM5y3J7tURkf5a1SutfdOyXAmeE6SRo83U
|
||||
h6WszodmMkxK5GM4JGrnt4pBisu5igXEydaW7qq2CdC6DOGjG+mEkN8/TA6p3cno
|
||||
L/sPyz6evdjLlSeJ8rFBH6xWyIZCbrcpYEJzXaUOEaxxXxgYz5/cTiVKN2M1G2ok
|
||||
QBUIYSY6bjEL4aUN5cfo7ogP3UvliEo3Eo0YgwuzR2v0KR6C1cZqZJSTnghIC/vA
|
||||
D32KdNQ+c3N+vl2OTsUVMC1GiWkngNx1OO1+kXW+YTnnTUOtOIswUP/Vqd5SYgAI
|
||||
mMAfY8U9/iIgkQj6T2W6FsScy94IN9fFhE1UtzmLoBIuUFsVXJMTz+Jucth+IqoW
|
||||
Fua9v1R93/k98p41pjtFX+H8DslVgfP097vju4KDlqN64xV1grw3ZLl4CiOe/A91
|
||||
oeLm2UHOq6wn3esB4r2EIQKb6jTVGu5sYCcdWpXr0AUVqcABPdgL+H7qJguBw09o
|
||||
jm6xNIrw2OocrDKsudk/okr/AwqEyPKw9WnMlQgLIKw1rODG2NvU9oR3GVGdMkUB
|
||||
ZutL8VuFkERQGt6vQ2OCw0sV47VMkuYbacK/xyZFiRcrPJPb41zgbQj9XAEyLKCH
|
||||
ex0SdDrx+tWUDqG8At2JHA==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -88,6 +88,34 @@ class AttestationVerificationPeerDeviceVerifierTest {
|
||||
assertThat(result).isEqualTo(RESULT_SUCCESS)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun verifyAttestation_returnsSuccessOwnedBySystem() {
|
||||
val verifier = AttestationVerificationPeerDeviceVerifier(
|
||||
context, trustAnchors, false, LocalDate.of(2022, 2, 1),
|
||||
LocalDate.of(2021, 1, 1))
|
||||
val challengeRequirements = Bundle()
|
||||
challengeRequirements.putByteArray(PARAM_CHALLENGE, "activeUnlockValid".encodeToByteArray())
|
||||
challengeRequirements.putBoolean("android.key_owned_by_system", true)
|
||||
|
||||
val result = verifier.verifyAttestation(TYPE_CHALLENGE, challengeRequirements,
|
||||
TEST_OWNED_BY_SYSTEM_FILENAME.fromPEMFileToByteArray())
|
||||
assertThat(result).isEqualTo(RESULT_SUCCESS)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun verifyAttestation_returnsFailureOwnedBySystem() {
|
||||
val verifier = AttestationVerificationPeerDeviceVerifier(
|
||||
context, trustAnchors, false, LocalDate.of(2022, 2, 1),
|
||||
LocalDate.of(2021, 1, 1))
|
||||
val challengeRequirements = Bundle()
|
||||
challengeRequirements.putByteArray(PARAM_CHALLENGE, "player456".encodeToByteArray())
|
||||
challengeRequirements.putBoolean("android.key_owned_by_system", true)
|
||||
|
||||
val result = verifier.verifyAttestation(TYPE_CHALLENGE, challengeRequirements,
|
||||
TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME.fromPEMFileToByteArray())
|
||||
assertThat(result).isEqualTo(RESULT_FAILURE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun verifyAttestation_returnsFailurePatchDateNotWithinOneYearLocalPatch() {
|
||||
val verifier = AttestationVerificationPeerDeviceVerifier(
|
||||
@@ -171,5 +199,6 @@ class AttestationVerificationPeerDeviceVerifierTest {
|
||||
private const val TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME =
|
||||
"test_attestation_with_root_certs.pem"
|
||||
private const val TEST_ATTESTATION_CERT_FILENAME = "test_attestation_wrong_root_certs.pem"
|
||||
private const val TEST_OWNED_BY_SYSTEM_FILENAME = "test_owned_by_system_certs.pem"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user