Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c9fc85a authored by Guojing Yuan's avatar Guojing Yuan Committed by Android (Google) Code Review
Browse files

Merge "Add "key owned by system" optional requirement in AVF"

parents 32a04182 3e060636
Loading
Loading
Loading
Loading
+49 −3
Original line number Original line Diff line number Diff line
@@ -96,6 +96,21 @@ class AttestationVerificationPeerDeviceVerifier {
    private static final boolean DEBUG = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.VERBOSE);
    private static final boolean DEBUG = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.VERBOSE);
    private static final int MAX_PATCH_AGE_MONTHS = 12;
    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 Context mContext;
    private final Set<TrustAnchor> mTrustAnchors;
    private final Set<TrustAnchor> mTrustAnchors;
    private final boolean mRevocationEnabled;
    private final boolean mRevocationEnabled;
@@ -170,7 +185,7 @@ class AttestationVerificationPeerDeviceVerifier {
            final var leafCertificate = certificateChain.get(0);
            final var leafCertificate = certificateChain.get(0);
            final var attestationExtension = fromCertificate(leafCertificate);
            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)) {
            if (!checkAttestationForPeerDeviceProfile(attestationExtension)) {
                return RESULT_FAILURE;
                return RESULT_FAILURE;
            }
            }
@@ -220,8 +235,8 @@ class AttestationVerificationPeerDeviceVerifier {
            return false;
            return false;
        }
        }


        if (requirements.size() != 1) {
        if (requirements.size() < 1) {
            debugVerboseLog("Requirements does not contain exactly 1 key.");
            debugVerboseLog("At least 1 requirement is required.");
            return false;
            return false;
        }
        }


@@ -293,6 +308,7 @@ class AttestationVerificationPeerDeviceVerifier {
            @NonNull AndroidKeystoreAttestationVerificationAttributes attestationAttributes,
            @NonNull AndroidKeystoreAttestationVerificationAttributes attestationAttributes,
            @LocalBindingType int localBindingType,
            @LocalBindingType int localBindingType,
            @NonNull Bundle requirements) {
            @NonNull Bundle requirements) {
        // First: check non-optional (for the given local binding type) requirements.
        switch (localBindingType) {
        switch (localBindingType) {
            case TYPE_PUBLIC_KEY:
            case TYPE_PUBLIC_KEY:
                // Verify leaf public key matches provided public key.
                // Verify leaf public key matches provided public key.
@@ -321,6 +337,24 @@ class AttestationVerificationPeerDeviceVerifier {
                        + localBindingTypeToString(localBindingType));
                        + 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;
        return true;
    }
    }


@@ -407,6 +441,18 @@ class AttestationVerificationPeerDeviceVerifier {
        return Arrays.equals(challenge, expectedChallenge);
        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
     * 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
     * not over one year old. Since the time can be changed on device, just checking the patch date
+81 −0
Original line number Original line Diff line number Diff line
-----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-----
+29 −0
Original line number Original line Diff line number Diff line
@@ -88,6 +88,34 @@ class AttestationVerificationPeerDeviceVerifierTest {
        assertThat(result).isEqualTo(RESULT_SUCCESS)
        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
    @Test
    fun verifyAttestation_returnsFailurePatchDateNotWithinOneYearLocalPatch() {
    fun verifyAttestation_returnsFailurePatchDateNotWithinOneYearLocalPatch() {
        val verifier = AttestationVerificationPeerDeviceVerifier(
        val verifier = AttestationVerificationPeerDeviceVerifier(
@@ -171,5 +199,6 @@ class AttestationVerificationPeerDeviceVerifierTest {
        private const val TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME =
        private const val TEST_ATTESTATION_WITH_ROOT_CERT_FILENAME =
            "test_attestation_with_root_certs.pem"
            "test_attestation_with_root_certs.pem"
        private const val TEST_ATTESTATION_CERT_FILENAME = "test_attestation_wrong_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"
    }
    }
}
}