Create static factory methods for AppAuthenticator
The AppAuthenticator will facilitate guarding resources by package /
signing identities as well as verifying expected signing identities
of apps installed on the device before interacting with them. This
initial commit creates the static factory methods that can be used
to create a new AppAuthenticator instance based on an XML config
file.
Bug: 171453012
Test: AppAuthenticatorTest
Relnote: "Added the AppAuthenticator to facilitate app signature
verification."
Change-Id: I157878a12192e9f179025a54938644926b684e17
diff --git a/security/security-app-authenticator/api/current.txt b/security/security-app-authenticator/api/current.txt
index e6f50d0..56563be 100644
--- a/security/security-app-authenticator/api/current.txt
+++ b/security/security-app-authenticator/api/current.txt
@@ -1 +1,13 @@
// Signature format: 4.0
+package androidx.security.app.authenticator {
+
+ public class AppAuthenticator {
+ method public static androidx.security.app.authenticator.AppAuthenticator createFromInputStream(android.content.Context, java.io.InputStream) throws androidx.security.app.authenticator.AppAuthenticatorXmlException, java.io.IOException;
+ method public static androidx.security.app.authenticator.AppAuthenticator createFromResource(android.content.Context, @XmlRes int) throws androidx.security.app.authenticator.AppAuthenticatorXmlException, java.io.IOException;
+ }
+
+ public class AppAuthenticatorXmlException extends java.lang.Exception {
+ }
+
+}
+
diff --git a/security/security-app-authenticator/api/public_plus_experimental_current.txt b/security/security-app-authenticator/api/public_plus_experimental_current.txt
index e6f50d0..56563be 100644
--- a/security/security-app-authenticator/api/public_plus_experimental_current.txt
+++ b/security/security-app-authenticator/api/public_plus_experimental_current.txt
@@ -1 +1,13 @@
// Signature format: 4.0
+package androidx.security.app.authenticator {
+
+ public class AppAuthenticator {
+ method public static androidx.security.app.authenticator.AppAuthenticator createFromInputStream(android.content.Context, java.io.InputStream) throws androidx.security.app.authenticator.AppAuthenticatorXmlException, java.io.IOException;
+ method public static androidx.security.app.authenticator.AppAuthenticator createFromResource(android.content.Context, @XmlRes int) throws androidx.security.app.authenticator.AppAuthenticatorXmlException, java.io.IOException;
+ }
+
+ public class AppAuthenticatorXmlException extends java.lang.Exception {
+ }
+
+}
+
diff --git a/security/security-app-authenticator/api/restricted_current.txt b/security/security-app-authenticator/api/restricted_current.txt
index e6f50d0..56563be 100644
--- a/security/security-app-authenticator/api/restricted_current.txt
+++ b/security/security-app-authenticator/api/restricted_current.txt
@@ -1 +1,13 @@
// Signature format: 4.0
+package androidx.security.app.authenticator {
+
+ public class AppAuthenticator {
+ method public static androidx.security.app.authenticator.AppAuthenticator createFromInputStream(android.content.Context, java.io.InputStream) throws androidx.security.app.authenticator.AppAuthenticatorXmlException, java.io.IOException;
+ method public static androidx.security.app.authenticator.AppAuthenticator createFromResource(android.content.Context, @XmlRes int) throws androidx.security.app.authenticator.AppAuthenticatorXmlException, java.io.IOException;
+ }
+
+ public class AppAuthenticatorXmlException extends java.lang.Exception {
+ }
+
+}
+
diff --git a/security/security-app-authenticator/build.gradle b/security/security-app-authenticator/build.gradle
index 60e92d2..ddfa7f9 100644
--- a/security/security-app-authenticator/build.gradle
+++ b/security/security-app-authenticator/build.gradle
@@ -13,6 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+import static androidx.build.dependencies.DependenciesKt.*
+
import androidx.build.LibraryGroups
import androidx.build.LibraryVersions
import androidx.build.LibraryType
@@ -24,7 +27,16 @@
}
dependencies {
- // Add dependencies here
+ api("androidx.annotation:annotation:1.1.0")
+
+ implementation("androidx.collection:collection:1.1.0")
+
+ androidTestImplementation("junit:junit:4.13")
+ androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
+ androidTestImplementation(ANDROIDX_TEST_CORE)
+ androidTestImplementation(ANDROIDX_TEST_RUNNER)
+ androidTestImplementation(ANDROIDX_TEST_RULES)
+ androidTestImplementation(MOCKITO_CORE)
}
androidx {
diff --git a/security/security-app-authenticator/src/androidTest/java/androidx/security/app/authenticator/AppAuthenticatorTest.java b/security/security-app-authenticator/src/androidTest/java/androidx/security/app/authenticator/AppAuthenticatorTest.java
new file mode 100644
index 0000000..32fedae
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/java/androidx/security/app/authenticator/AppAuthenticatorTest.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.security.app.authenticator;
+
+import static org.junit.Assert.assertThrows;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+import androidx.security.app.authenticator.test.R;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.MediumTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public final class AppAuthenticatorTest {
+ private Context mContext;
+ private Resources mResources;
+
+ @Before
+ public void setUp() {
+ mContext = ApplicationProvider.getApplicationContext();
+ mResources = mContext.getResources();
+ }
+
+ @Test
+ public void createFrom_singleExpectedIdentity() throws Exception {
+ // An XML resource with a single expected-identity tag should parse successfully.
+ AppAuthenticator.createFromResource(mContext, R.xml.single_expected_identity);
+ AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.single_expected_identity));
+ }
+
+ @Test
+ public void createFromInputStream_noRootElement() throws Exception {
+ // This test verifies if the caller is attempting to create a new AppAuthenticator with
+ // an empty XML InputStream then an appropriate Exception is thrown. Note, only the
+ // InputStream static factory method is used as an empty XML file is not added to the
+ // resources when under the res/xml directory.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.no_root_element)));
+ }
+
+ @Test
+ public void createFrom_invalidRootElement() throws Exception {
+ // An XML resource with a root element other than app-authenticator should result in an
+ // Exception.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext, R.xml.invalid_root_element));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.invalid_root_element)));
+ }
+
+ @Test
+ public void createFrom_invalidDigestAlgorithm() throws Exception {
+ // Insecure digest algorithms are not supported by the AppAuthenticator; ensure if an
+ // unsupported digest algorithm is specified then an Exception is thrown.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext, R.xml.invalid_digest_algo));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.invalid_digest_algo)));
+ }
+
+ @Test
+ public void createFrom_multipleUnsupportedAttributes() throws Exception {
+ // The static factory methods will verify tags contain only supported attributes to notify
+ // the caller if they are expecting behavior based on the values for the attributes. This
+ // test verifies if multiple unsupported attributes are specified then an Exception is
+ // thrown.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext,
+ R.xml.multiple_unsupported_attributes));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.multiple_unsupported_attributes)));
+ }
+
+ @Test
+ public void createFrom_invalidExpectedIdentityAttribute() throws Exception {
+ // The expected-identity tag does not support any attributes; this test verifies if an
+ // attribute is specified then an Exception is thrown.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext,
+ R.xml.invalid_expected_identity_attribute));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.invalid_expected_identity_attribute)));
+ }
+
+ @Test
+ public void createFrom_allPackagesTagInExpectedIdentity() throws Exception {
+ // The expected-identity element does not support the all-packages element since it is
+ // expected that a caller is specifying this tag to verify the identity of a specific app.
+ // This test verifies if an all-packages tag is within the expected-identity element then an
+ // Exception is thrown.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext,
+ R.xml.all_packages_expected_identity));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.all_packages_expected_identity)));
+ }
+
+ @Test
+ public void createFrom_invalidTagWithinRootElement() throws Exception {
+ // The XML should only contain permission and expected-identity tags under the root element;
+ // this test verifies if an invalid tag is specified then an Exception is thrown.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext,
+ R.xml.invalid_tag_within_root_element));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.invalid_tag_within_root_element)));
+ }
+
+ @Test
+ public void createFrom_invalidTagWithinPermissionElement() throws Exception {
+ // The permission element supports both the package and all-packages tags; this test
+ // verifies if another tag is specified then an Exception is thrown.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext,
+ R.xml.invalid_tag_within_permission_element));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.invalid_tag_within_permission_element)));
+ }
+
+ @Test
+ public void createFrom_invalidTagWithinPackageElement() throws Exception {
+ // The package / all-packages element require one or more cert-digest elements containing
+ // the certificate digests of the signer. This test verifies if another tag is specified
+ // under one of these elements then an Exception is thrown.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext,
+ R.xml.invalid_tag_within_package_element));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.invalid_tag_within_package_element)));
+ }
+
+ @Test
+ public void createFrom_noCertDigestWithinPackageElement() throws Exception {
+ // The package / all-packages element require one or more cert-digest elements containing
+ // the certificate digests of the signer. This test verifies is no cert-digest is
+ // specified under one of these elements then an Exception is thrown.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext,
+ R.xml.no_cert_digest_within_package_element));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.no_cert_digest_within_package_element)));
+ }
+
+ @Test
+ public void createFrom_emptyCertDigestElement() throws Exception {
+ // The package / all-packages element require one or more cert-digest elements containing
+ // the certificate digests of the signer. This test verifies if the cert-digest element
+ // does not contain any text then an Exception is thrown.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext,
+ R.xml.empty_cert_digest_element));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.empty_cert_digest_element)));
+ }
+
+ @Test
+ public void createFrom_emptyPermissionElement() throws Exception {
+ // A permission element could potentially be left empty during development if a developer
+ // wishes to guard a resource behind a permission but does not yet know the expected
+ // signing identity of the callers. This test ensures the static factory methods properly
+ // handle an empty permission declaration.
+ AppAuthenticator.createFromResource(mContext, R.xml.empty_permission_element);
+ AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.empty_permission_element));
+ }
+
+ @Test
+ public void createFrom_multipleCertDigestElements() throws Exception {
+ // The package / all-packages element allow multiple cert-digest elements to support key
+ // rotation and multiple signers. This test verifies an AppAuthenticator can be
+ // successfully instantiated when the provided XML contains multiple cert-digest elements
+ // within a package element.
+ AppAuthenticator.createFromResource(mContext, R.xml.multiple_cert_digest_elements);
+ AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.multiple_cert_digest_elements));
+ }
+
+ @Test
+ public void createFrom_multiplePackagesUnderPermission() throws Exception {
+ // The permission element supports one or more packages; this test verifies a new
+ // AppAuthenticator can be successfully instantiated when there are multiple packages
+ // within the permission element.
+ AppAuthenticator.createFromResource(mContext, R.xml.multiple_packages_under_permission);
+ AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.multiple_packages_under_permission));
+ }
+
+ @Test
+ public void createFrom_noNameAttributeInPackageTag() throws Exception {
+ // The package tag requires a non-empty name attribute; this test verifies if the name
+ // attribute is not specified then an Exception is thrown.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext,
+ R.xml.no_name_attribute_in_package_tag));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.no_name_attribute_in_package_tag)));
+ }
+
+ @Test
+ public void createFrom_emptyNameAttributeInPackageTag() throws Exception {
+ // The package tag requires a non-empty name attribute; this test verifies if the name
+ // attribute is specified but empty then an Exception is thrown.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext,
+ R.xml.empty_name_attribute_in_package_tag));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.empty_name_attribute_in_package_tag)));
+ }
+
+ @Test
+ public void createFrom_noNameAttributeInPermissionTag() throws Exception {
+ // The permission tag requires a non-empty name attribute to identify the permission; this
+ // test verifies if the name attribute is not specified then an Exception is thrown.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext,
+ R.xml.no_name_attribute_in_permission_tag));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.no_name_attribute_in_permission_tag)));
+ }
+
+ @Test
+ public void createFrom_emptyNameAttributeInPermissionTag() throws Exception {
+ // The package tag requires a non-empty name attribute; this test verifies if the name
+ // attribute is specified but empty then an Exception is thrown.
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromResource(mContext,
+ R.xml.empty_name_attribute_in_permission_tag));
+ assertThrows(AppAuthenticatorXmlException.class,
+ () -> AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.empty_name_attribute_in_permission_tag)));
+ }
+
+ @Test
+ public void createFrom_allSupportedElementsAndAttributes() throws Exception {
+ // This test verifies a new AppAuthenticator instance can be instantiated when the
+ // provided XML contains all of the supported elements and attributes.
+ AppAuthenticator.createFromResource(mContext,
+ R.xml.all_supported_elements_and_attributes);
+ AppAuthenticator.createFromInputStream(mContext,
+ mResources.openRawResource(R.raw.all_supported_elements_and_attributes));
+ }
+}
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/all_packages_expected_identity.xml b/security/security-app-authenticator/src/androidTest/res/raw/all_packages_expected_identity.xml
new file mode 100644
index 0000000..9196cab
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/all_packages_expected_identity.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <expected-identity>
+ <all-packages>
+ <cert-digest>bc8b6df1d3920cfa81800fd5a58ea893c0571e36193925b8c9dea2836e963384
+ </cert-digest>
+ </all-packages>
+ </expected-identity>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/all_supported_elements_and_attributes.xml b/security/security-app-authenticator/src/androidTest/res/raw/all_supported_elements_and_attributes.xml
new file mode 100644
index 0000000..a600c8e
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/all_supported_elements_and_attributes.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator digestAlgorithm="sha-256">
+ <expected-identity>
+ <package name="com.bank.app">
+ <cert-digest>fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8
+ </cert-digest>
+ </package>
+ <package name="com.social.app">
+ <cert-digest>6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599
+ </cert-digest>
+ <cert-digest>d78405f761ff6236cc9b570347a570aba0c62a129a3ac30c831c64d09ad95469
+ </cert-digest>
+ </package>
+ </expected-identity>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <all-packages>
+ <cert-digest>fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8
+ </cert-digest>
+ <cert-digest>681b0e56a796350c08647352a4db800cc44b2adc8f4c72fa350bd05d4d50264d
+ </cert-digest>
+ </all-packages>
+ <package name="com.android.app1">
+ <cert-digest>fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8
+ </cert-digest>
+ </package>
+ <package name="com.android.app2">
+ <cert-digest>6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599
+ </cert-digest>
+ <cert-digest>d78405f761ff6236cc9b570347a570aba0c62a129a3ac30c831c64d09ad95469
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/empty_cert_digest_element.xml b/security/security-app-authenticator/src/androidTest/res/raw/empty_cert_digest_element.xml
new file mode 100644
index 0000000..6d9aa0f
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/empty_cert_digest_element.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="com.android.app1">
+ <cert-digest></cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/empty_name_attribute_in_package_tag.xml b/security/security-app-authenticator/src/androidTest/res/raw/empty_name_attribute_in_package_tag.xml
new file mode 100644
index 0000000..289dcb9
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/empty_name_attribute_in_package_tag.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator digestAlgorithm="sha-256">
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="">
+ <cert-digest>cbfc520b3ba3a44f6e39029b992c1cb77973a374be1a814d9b41304123cd6c3f
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/empty_name_attribute_in_permission_tag.xml b/security/security-app-authenticator/src/androidTest/res/raw/empty_name_attribute_in_permission_tag.xml
new file mode 100644
index 0000000..f3bcaa4
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/empty_name_attribute_in_permission_tag.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator digestAlgorithm="sha-256">
+ <permission name="">
+ <package name="com.android.app">
+ <cert-digest>cbfc520b3ba3a44f6e39029b992c1cb77973a374be1a814d9b41304123cd6c3f
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/empty_permission_element.xml b/security/security-app-authenticator/src/androidTest/res/raw/empty_permission_element.xml
new file mode 100644
index 0000000..d4cd4b1
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/empty_permission_element.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION"></permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/invalid_digest_algo.xml b/security/security-app-authenticator/src/androidTest/res/raw/invalid_digest_algo.xml
new file mode 100644
index 0000000..45cdd32
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/invalid_digest_algo.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator digestAlgorithm="MD5">
+ <expected-identity>
+ <package name="com.bank.app">
+ <cert-digest>169fb46f598556518575e1fdfc597003</cert-digest>
+ </package>
+ </expected-identity>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/invalid_expected_identity_attribute.xml b/security/security-app-authenticator/src/androidTest/res/raw/invalid_expected_identity_attribute.xml
new file mode 100644
index 0000000..b95332a
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/invalid_expected_identity_attribute.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <expected-identity category="banking">
+ <package name="com.bank.app">
+ <cert-digest>bc8b6df1d3920cfa81800fd5a58ea893c0571e36193925b8c9dea2836e963384
+ </cert-digest>
+ </package>
+ </expected-identity>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/invalid_root_element.xml b/security/security-app-authenticator/src/androidTest/res/raw/invalid_root_element.xml
new file mode 100644
index 0000000..7ef422f
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/invalid_root_element.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<invalid-root-element>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="com.android.app1">
+ <cert-digest>8ec69bfa1211b0daf10b14beeb0167906e5d4d23c33e5cd8d12a0de6f143a6f6
+ </cert-digest>
+ </package>
+ </permission>
+</invalid-root-element>
\ No newline at end of file
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/invalid_tag_within_package_element.xml b/security/security-app-authenticator/src/androidTest/res/raw/invalid_tag_within_package_element.xml
new file mode 100644
index 0000000..21bd3e6
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/invalid_tag_within_package_element.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="com.android.app1">
+ <invalid>8ec69bfa1211b0daf10b14beeb0167906e5d4d23c33e5cd8d12a0de6f143a6f6</invalid>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/invalid_tag_within_permission_element.xml b/security/security-app-authenticator/src/androidTest/res/raw/invalid_tag_within_permission_element.xml
new file mode 100644
index 0000000..c31d1e2
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/invalid_tag_within_permission_element.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <invalid name="com.android.app1">
+ <cert-digest>8ec69bfa1211b0daf10b14beeb0167906e5d4d23c33e5cd8d12a0de6f143a6f6
+ </cert-digest>
+ </invalid>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/invalid_tag_within_root_element.xml b/security/security-app-authenticator/src/androidTest/res/raw/invalid_tag_within_root_element.xml
new file mode 100644
index 0000000..36f031d
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/invalid_tag_within_root_element.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <invalid>
+ <package name="com.android.app">
+ <cert-digest>cbfc520b3ba3a44f6e39029b992c1cb77973a374be1a814d9b41304123cd6c3f
+ </cert-digest>
+ </package>
+ </invalid>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/multiple_cert_digest_elements.xml b/security/security-app-authenticator/src/androidTest/res/raw/multiple_cert_digest_elements.xml
new file mode 100644
index 0000000..7127dbb
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/multiple_cert_digest_elements.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="com.android.app1">
+ <cert-digest>6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599
+ </cert-digest>
+ <cert-digest>d78405f761ff6236cc9b570347a570aba0c62a129a3ac30c831c64d09ad95469
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/multiple_packages_under_permission.xml b/security/security-app-authenticator/src/androidTest/res/raw/multiple_packages_under_permission.xml
new file mode 100644
index 0000000..91796b0
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/multiple_packages_under_permission.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="com.android.app1">
+ <cert-digest>6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599
+ </cert-digest>
+ </package>
+ <package name="com.android.app2">
+ <cert-digest>fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8
+ </cert-digest>
+ <cert-digest>681b0e56a796350c08647352a4db800cc44b2adc8f4c72fa350bd05d4d50264d
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/multiple_unsupported_attributes.xml b/security/security-app-authenticator/src/androidTest/res/raw/multiple_unsupported_attributes.xml
new file mode 100644
index 0000000..982fca0
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/multiple_unsupported_attributes.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator
+ name="test-app-authenticator"
+ digestAlgorithm="SHA-256"
+ method="signature">
+ <expected-identity>
+ <package name="com.bank.app">
+ <cert-digest>169fb46f598556518575e1fdfc597003</cert-digest>
+ </package>
+ </expected-identity>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/no_cert_digest_within_package_element.xml b/security/security-app-authenticator/src/androidTest/res/raw/no_cert_digest_within_package_element.xml
new file mode 100644
index 0000000..08ef25c
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/no_cert_digest_within_package_element.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="com.android.app1"></package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/no_name_attribute_in_package_tag.xml b/security/security-app-authenticator/src/androidTest/res/raw/no_name_attribute_in_package_tag.xml
new file mode 100644
index 0000000..3e16665
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/no_name_attribute_in_package_tag.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator digestAlgorithm="sha-256">
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package>
+ <cert-digest>cbfc520b3ba3a44f6e39029b992c1cb77973a374be1a814d9b41304123cd6c3f
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/no_name_attribute_in_permission_tag.xml b/security/security-app-authenticator/src/androidTest/res/raw/no_name_attribute_in_permission_tag.xml
new file mode 100644
index 0000000..ae1e069
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/no_name_attribute_in_permission_tag.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator digestAlgorithm="sha-256">
+ <permission>
+ <package name="com.android.app">
+ <cert-digest>cbfc520b3ba3a44f6e39029b992c1cb77973a374be1a814d9b41304123cd6c3f
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/no_root_element.xml b/security/security-app-authenticator/src/androidTest/res/raw/no_root_element.xml
new file mode 100644
index 0000000..5999db9
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/no_root_element.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
diff --git a/security/security-app-authenticator/src/androidTest/res/raw/single_expected_identity.xml b/security/security-app-authenticator/src/androidTest/res/raw/single_expected_identity.xml
new file mode 100644
index 0000000..c2a46a8
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/raw/single_expected_identity.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <expected-identity>
+ <package name="com.bank.app">
+ <cert-digest>fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8
+ </cert-digest>
+ </package>
+ </expected-identity>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/all_packages_expected_identity.xml b/security/security-app-authenticator/src/androidTest/res/xml/all_packages_expected_identity.xml
new file mode 100644
index 0000000..9196cab
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/all_packages_expected_identity.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <expected-identity>
+ <all-packages>
+ <cert-digest>bc8b6df1d3920cfa81800fd5a58ea893c0571e36193925b8c9dea2836e963384
+ </cert-digest>
+ </all-packages>
+ </expected-identity>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/all_supported_elements_and_attributes.xml b/security/security-app-authenticator/src/androidTest/res/xml/all_supported_elements_and_attributes.xml
new file mode 100644
index 0000000..a600c8e
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/all_supported_elements_and_attributes.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator digestAlgorithm="sha-256">
+ <expected-identity>
+ <package name="com.bank.app">
+ <cert-digest>fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8
+ </cert-digest>
+ </package>
+ <package name="com.social.app">
+ <cert-digest>6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599
+ </cert-digest>
+ <cert-digest>d78405f761ff6236cc9b570347a570aba0c62a129a3ac30c831c64d09ad95469
+ </cert-digest>
+ </package>
+ </expected-identity>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <all-packages>
+ <cert-digest>fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8
+ </cert-digest>
+ <cert-digest>681b0e56a796350c08647352a4db800cc44b2adc8f4c72fa350bd05d4d50264d
+ </cert-digest>
+ </all-packages>
+ <package name="com.android.app1">
+ <cert-digest>fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8
+ </cert-digest>
+ </package>
+ <package name="com.android.app2">
+ <cert-digest>6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599
+ </cert-digest>
+ <cert-digest>d78405f761ff6236cc9b570347a570aba0c62a129a3ac30c831c64d09ad95469
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/empty_cert_digest_element.xml b/security/security-app-authenticator/src/androidTest/res/xml/empty_cert_digest_element.xml
new file mode 100644
index 0000000..6d9aa0f
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/empty_cert_digest_element.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="com.android.app1">
+ <cert-digest></cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/empty_name_attribute_in_package_tag.xml b/security/security-app-authenticator/src/androidTest/res/xml/empty_name_attribute_in_package_tag.xml
new file mode 100644
index 0000000..289dcb9
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/empty_name_attribute_in_package_tag.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator digestAlgorithm="sha-256">
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="">
+ <cert-digest>cbfc520b3ba3a44f6e39029b992c1cb77973a374be1a814d9b41304123cd6c3f
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/empty_name_attribute_in_permission_tag.xml b/security/security-app-authenticator/src/androidTest/res/xml/empty_name_attribute_in_permission_tag.xml
new file mode 100644
index 0000000..f3bcaa4
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/empty_name_attribute_in_permission_tag.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator digestAlgorithm="sha-256">
+ <permission name="">
+ <package name="com.android.app">
+ <cert-digest>cbfc520b3ba3a44f6e39029b992c1cb77973a374be1a814d9b41304123cd6c3f
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/empty_permission_element.xml b/security/security-app-authenticator/src/androidTest/res/xml/empty_permission_element.xml
new file mode 100644
index 0000000..d4cd4b1
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/empty_permission_element.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION"></permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/invalid_digest_algo.xml b/security/security-app-authenticator/src/androidTest/res/xml/invalid_digest_algo.xml
new file mode 100644
index 0000000..45cdd32
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/invalid_digest_algo.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator digestAlgorithm="MD5">
+ <expected-identity>
+ <package name="com.bank.app">
+ <cert-digest>169fb46f598556518575e1fdfc597003</cert-digest>
+ </package>
+ </expected-identity>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/invalid_expected_identity_attribute.xml b/security/security-app-authenticator/src/androidTest/res/xml/invalid_expected_identity_attribute.xml
new file mode 100644
index 0000000..b95332a
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/invalid_expected_identity_attribute.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <expected-identity category="banking">
+ <package name="com.bank.app">
+ <cert-digest>bc8b6df1d3920cfa81800fd5a58ea893c0571e36193925b8c9dea2836e963384
+ </cert-digest>
+ </package>
+ </expected-identity>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/invalid_root_element.xml b/security/security-app-authenticator/src/androidTest/res/xml/invalid_root_element.xml
new file mode 100644
index 0000000..7ef422f
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/invalid_root_element.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<invalid-root-element>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="com.android.app1">
+ <cert-digest>8ec69bfa1211b0daf10b14beeb0167906e5d4d23c33e5cd8d12a0de6f143a6f6
+ </cert-digest>
+ </package>
+ </permission>
+</invalid-root-element>
\ No newline at end of file
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/invalid_tag_within_package_element.xml b/security/security-app-authenticator/src/androidTest/res/xml/invalid_tag_within_package_element.xml
new file mode 100644
index 0000000..21bd3e6
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/invalid_tag_within_package_element.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="com.android.app1">
+ <invalid>8ec69bfa1211b0daf10b14beeb0167906e5d4d23c33e5cd8d12a0de6f143a6f6</invalid>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/invalid_tag_within_permission_element.xml b/security/security-app-authenticator/src/androidTest/res/xml/invalid_tag_within_permission_element.xml
new file mode 100644
index 0000000..c31d1e2
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/invalid_tag_within_permission_element.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <invalid name="com.android.app1">
+ <cert-digest>8ec69bfa1211b0daf10b14beeb0167906e5d4d23c33e5cd8d12a0de6f143a6f6
+ </cert-digest>
+ </invalid>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/invalid_tag_within_root_element.xml b/security/security-app-authenticator/src/androidTest/res/xml/invalid_tag_within_root_element.xml
new file mode 100644
index 0000000..36f031d
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/invalid_tag_within_root_element.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <invalid>
+ <package name="com.android.app">
+ <cert-digest>cbfc520b3ba3a44f6e39029b992c1cb77973a374be1a814d9b41304123cd6c3f
+ </cert-digest>
+ </package>
+ </invalid>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/multiple_cert_digest_elements.xml b/security/security-app-authenticator/src/androidTest/res/xml/multiple_cert_digest_elements.xml
new file mode 100644
index 0000000..7127dbb
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/multiple_cert_digest_elements.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="com.android.app1">
+ <cert-digest>6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599
+ </cert-digest>
+ <cert-digest>d78405f761ff6236cc9b570347a570aba0c62a129a3ac30c831c64d09ad95469
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/multiple_packages_under_permission.xml b/security/security-app-authenticator/src/androidTest/res/xml/multiple_packages_under_permission.xml
new file mode 100644
index 0000000..91796b0
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/multiple_packages_under_permission.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="com.android.app1">
+ <cert-digest>6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599
+ </cert-digest>
+ </package>
+ <package name="com.android.app2">
+ <cert-digest>fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8
+ </cert-digest>
+ <cert-digest>681b0e56a796350c08647352a4db800cc44b2adc8f4c72fa350bd05d4d50264d
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/multiple_unsupported_attributes.xml b/security/security-app-authenticator/src/androidTest/res/xml/multiple_unsupported_attributes.xml
new file mode 100644
index 0000000..982fca0
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/multiple_unsupported_attributes.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator
+ name="test-app-authenticator"
+ digestAlgorithm="SHA-256"
+ method="signature">
+ <expected-identity>
+ <package name="com.bank.app">
+ <cert-digest>169fb46f598556518575e1fdfc597003</cert-digest>
+ </package>
+ </expected-identity>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/no_cert_digest_within_package_element.xml b/security/security-app-authenticator/src/androidTest/res/xml/no_cert_digest_within_package_element.xml
new file mode 100644
index 0000000..08ef25c
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/no_cert_digest_within_package_element.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package name="com.android.app1"></package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/no_name_attribute_in_package_tag.xml b/security/security-app-authenticator/src/androidTest/res/xml/no_name_attribute_in_package_tag.xml
new file mode 100644
index 0000000..3e16665
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/no_name_attribute_in_package_tag.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator digestAlgorithm="sha-256">
+ <permission name="androidx.security.app.authenticator.TEST_PERMISSION">
+ <package>
+ <cert-digest>cbfc520b3ba3a44f6e39029b992c1cb77973a374be1a814d9b41304123cd6c3f
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/no_name_attribute_in_permission_tag.xml b/security/security-app-authenticator/src/androidTest/res/xml/no_name_attribute_in_permission_tag.xml
new file mode 100644
index 0000000..ae1e069
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/no_name_attribute_in_permission_tag.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator digestAlgorithm="sha-256">
+ <permission>
+ <package name="com.android.app">
+ <cert-digest>cbfc520b3ba3a44f6e39029b992c1cb77973a374be1a814d9b41304123cd6c3f
+ </cert-digest>
+ </package>
+ </permission>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/androidTest/res/xml/single_expected_identity.xml b/security/security-app-authenticator/src/androidTest/res/xml/single_expected_identity.xml
new file mode 100644
index 0000000..c2a46a8
--- /dev/null
+++ b/security/security-app-authenticator/src/androidTest/res/xml/single_expected_identity.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<app-authenticator>
+ <expected-identity>
+ <package name="com.bank.app">
+ <cert-digest>fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8
+ </cert-digest>
+ </package>
+ </expected-identity>
+</app-authenticator>
diff --git a/security/security-app-authenticator/src/main/java/androidx/security/app/authenticator/AppAuthenticator.java b/security/security-app-authenticator/src/main/java/androidx/security/app/authenticator/AppAuthenticator.java
new file mode 100644
index 0000000..14c8c67
--- /dev/null
+++ b/security/security-app-authenticator/src/main/java/androidx/security/app/authenticator/AppAuthenticator.java
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.security.app.authenticator;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.XmlRes;
+import androidx.collection.ArrayMap;
+import androidx.collection.ArraySet;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Provides methods to verify the signing identity of other apps on the device.
+ */
+// TODO(b/175503230): Add usage details to class level documentation once implementation is
+// complete.
+public class AppAuthenticator {
+ /**
+ * The root tag for an AppAuthenticator XMl config file.
+ */
+ private static final String ROOT_TAG = "app-authenticator";
+ /**
+ * The tag to declare a new permission that can be granted to enclosed packages / signing
+ * identities.
+ */
+ private static final String PERMISSION_TAG = "permission";
+ /**
+ * The tag to begin declaration of the expected signing identities for the enclosed packages.
+ */
+ private static final String EXPECTED_IDENTITY_TAG = "expected-identity";
+ /**
+ * The tag to declare a new signing identity of a package within either a permission or
+ * expected-identity element.
+ */
+ private static final String PACKAGE_TAG = "package";
+ /**
+ * The tag to declare all packages signed with the enclosed signing identities are to be
+ * granted to the enclosing permission.
+ */
+ private static final String ALL_PACKAGES_TAG = "all-packages";
+ /**
+ * The tag to declare a known signing certificate digest for the enclosing package.
+ */
+ private static final String CERT_DIGEST_TAG = "cert-digest";
+ /**
+ * The attribute to declare the name within a permission or package element.
+ */
+ private static final String NAME_ATTRIBUTE = "name";
+ /**
+ * The attribute to declare the digest algorithm used for all certificate digests.
+ */
+ private static final String DIGEST_ALGORITHM_ATTRIBUTE = "digestAlgorithm";
+ /**
+ * The default digest algorithm used for all certificate digests if one is not specified in
+ * the root element.
+ */
+ private static final String DEFAULT_DIGEST_ALGORITHM = "SHA-256";
+ /**
+ * The set of digest algorithms supported by the AppAuthenticator; insecure algorithms and
+ * those that do not support all platform levels have been removed.
+ */
+ private static final Set<String> SUPPORTED_DIGEST_ALGORITHMS;
+
+ static {
+ SUPPORTED_DIGEST_ALGORITHMS = new ArraySet<>(3);
+ SUPPORTED_DIGEST_ALGORITHMS.add("SHA-256");
+ SUPPORTED_DIGEST_ALGORITHMS.add("SHA-384");
+ SUPPORTED_DIGEST_ALGORITHMS.add("SHA-512");
+ }
+
+ /**
+ * A mapping from permission to allowed packages / signing identities.
+ */
+ // TODO(b/171453012): This initial commit is focused on instantiating the AppAuthenticator
+ // through the static factory methods using the provided configuration; these
+ // SuppressWarning annotations will be removed in a subsequent commit when signature
+ // verification is added.
+ @SuppressWarnings("unused")
+ private final Map<String, Map<String, Set<String>>> mPermissionAllowMap;
+ /**
+ * A mapping from package name to expected signing identities.
+ */
+ @SuppressWarnings("unused")
+ private final Map<String, Set<String>> mExpectedIdentities;
+
+ @SuppressWarnings("unused")
+ private final String mDigestAlgorithm;
+ @SuppressWarnings("unused")
+ private final Context mContext;
+ @SuppressWarnings("unused")
+ private final PackageManager mPackageManager;
+
+ /**
+ * Private constructor; instances should be created through the static factory methods.
+ *
+ * @param context the context within which to create the {@code AppAuthenticator}
+ * @param permissionAllowMap a mapping from permission to allowed packages / signing identities
+ * @param expectedIdentities a mapping from package name to expected signing identities
+ * @param digestAlgorithm the digest algorithm used for all signing certificate digests
+ */
+ private AppAuthenticator(Context context,
+ Map<String, Map<String, Set<String>>> permissionAllowMap,
+ Map<String, Set<String>> expectedIdentities, String digestAlgorithm) {
+ mContext = context;
+ mPackageManager = context.getPackageManager();
+ mPermissionAllowMap = permissionAllowMap;
+ mExpectedIdentities = expectedIdentities;
+ mDigestAlgorithm = digestAlgorithm;
+ }
+
+
+ /**
+ * Creates a new {@code AppAuthenticator} that can be used to guard resources based on
+ * package name / signing identity as well as allow verification of expected signing identities
+ * before interacting with other apps on a device using the configuration defined in the
+ * provided {@code xmlInputStream}.
+ *
+ * @param context the context within which to create the {@code AppAuthenticator}
+ * @param xmlInputStream the XML {@link InputStream} containing the definitions for the
+ * permissions and expected identities based on packages / expected
+ * signing certificate digests
+ * @return a new {@code AppAuthenticator} that can be used to enforce the signing
+ * identities defined in the provided XML {@code InputStream}
+ * @throws AppAuthenticatorXmlException if the provided XML {@code InputStream} is not in the
+ * proper format to create a new {@code AppAuthenticator}
+ * @throws IOException if an IO error is encountered when attempting to read
+ * the XML {@code InputStream}
+ */
+ public static @NonNull AppAuthenticator createFromInputStream(@NonNull Context context,
+ @NonNull InputStream xmlInputStream) throws AppAuthenticatorXmlException, IOException {
+ XmlPullParser parser;
+ try {
+ parser = XmlPullParserFactory.newInstance().newPullParser();
+ parser.setInput(xmlInputStream, null);
+ } catch (XmlPullParserException e) {
+ throw new AppAuthenticatorXmlException("Unable to create parser from provided "
+ + "InputStream", e);
+ }
+ return createFromParser(context, parser);
+ }
+
+ /**
+ * Creates a new {@code AppAuthenticator} that can be used to guard resources based on
+ * package name / signing identity as well as allow verification of expected signing identities
+ * before interacting with other apps on a device using the configuration defined in the
+ * provided XML resource.
+ *
+ * @param context the context within which to create the {@code AppAuthenticator}
+ * @param xmlResource the ID of the XML resource containing the definitions for the
+ * permissions and expected identities based on package / expected signing
+ * certificate digests
+ * @return a new {@code AppAuthenticator} that can be used to enforce the signing identities
+ * defined in the provided XML resource
+ * @throws AppAuthenticatorXmlException if the provided XML resource is not in the proper format
+ * to create a new {@code AppAuthenticator}
+ * @throws IOException if an IO error is encountered when attempting to read
+ * the XML resource
+ */
+ public static @NonNull AppAuthenticator createFromResource(@NonNull Context context,
+ @XmlRes int xmlResource) throws AppAuthenticatorXmlException, IOException {
+ Resources resources = context.getResources();
+ XmlPullParser parser = resources.getXml(xmlResource);
+ return createFromParser(context, parser);
+ }
+
+ /**
+ * Creates a new {@code AppAuthenticator} that can be used to guard resources based on
+ * package name / signing identity as well as allow verification of expected signing identities
+ * before interacting with other apps on a device using the configuration defined in the
+ * provided {@code parser}.
+ *
+ * @param context the context within which to create the {@code AppAuthenticator}
+ * @param parser an {@link XmlPullParser} containing the definitions for the
+ * permissions and expected identities based on package / expected signing
+ * certificate digests
+ * @return a new {@code AppAuthenticator} that can be used to enforce the signing identities
+ * defined in the provided {@code XmlPullParser}
+ * @throws AppAuthenticatorXmlException if the provided XML parsed by the {@code XmlPullParser}
+ * is not in the proper format to create a new
+ * {@code AppAuthenticator}
+ * @throws IOException if an IO error is encountered when attempting to read
+ * from the {@code XmlPullParser}
+ */
+ private static AppAuthenticator createFromParser(Context context, XmlPullParser parser)
+ throws AppAuthenticatorXmlException, IOException {
+ Map<String, Map<String, Set<String>>> permissionAllowMap = new ArrayMap<>();
+ Map<String, Set<String>> expectedIdentities = new ArrayMap<>();
+ try {
+ parseToNextStartTag(parser);
+ String tag = parser.getName();
+ if (TextUtils.isEmpty(tag) || !tag.equalsIgnoreCase(ROOT_TAG)) {
+ throw new AppAuthenticatorXmlException(
+ "Provided XML does not contain the expected root tag: " + ROOT_TAG);
+ }
+ assertExpectedAttribute(parser, ROOT_TAG, DIGEST_ALGORITHM_ATTRIBUTE, false);
+ String digestAlgorithm = parser.getAttributeValue(null, DIGEST_ALGORITHM_ATTRIBUTE);
+ if (TextUtils.isEmpty(digestAlgorithm)) {
+ digestAlgorithm = DEFAULT_DIGEST_ALGORITHM;
+ } else {
+ // Using US locale as this call is only intended to match the MessageDigest
+ // constants in the supported set as taken from the Android MessageDigest
+ // documentation.
+ digestAlgorithm = digestAlgorithm.toUpperCase(Locale.US);
+ if (!SUPPORTED_DIGEST_ALGORITHMS.contains(digestAlgorithm)) {
+ throw new AppAuthenticatorXmlException("Provided XML contains an unsupported "
+ + "digest algorithm, " + digestAlgorithm + "; must be one of the "
+ + "following: " + Arrays.toString(
+ SUPPORTED_DIGEST_ALGORITHMS.toArray()));
+ }
+ }
+ int eventType = parser.nextTag();
+ // Each new start tag should be for a new permission / expected-identity.
+ while (eventType == XmlPullParser.START_TAG) {
+ tag = parser.getName();
+ if (tag.equalsIgnoreCase(PERMISSION_TAG)) {
+ assertExpectedAttribute(parser, PERMISSION_TAG, NAME_ATTRIBUTE, true);
+ String permissionName = parser.getAttributeValue(null, NAME_ATTRIBUTE);
+ if (TextUtils.isEmpty(permissionName)) {
+ throw new AppAuthenticatorXmlException(
+ "The " + PERMISSION_TAG + " tag requires a non-empty value for the "
+ + NAME_ATTRIBUTE + " attribute");
+ }
+ Map<String, Set<String>> allowedPackageCerts = parsePackages(parser, true);
+ if (permissionAllowMap.containsKey(permissionName)) {
+ permissionAllowMap.get(permissionName).putAll(allowedPackageCerts);
+ } else {
+ permissionAllowMap.put(permissionName, allowedPackageCerts);
+ }
+ } else if (tag.equalsIgnoreCase(EXPECTED_IDENTITY_TAG)) {
+ assertExpectedAttribute(parser, EXPECTED_IDENTITY_TAG, null, true);
+ expectedIdentities.putAll(parsePackages(parser, false));
+ } else {
+ throw new AppAuthenticatorXmlException(
+ "Expected " + PERMISSION_TAG + " or " + EXPECTED_IDENTITY_TAG
+ + " under root tag at line " + parser.getLineNumber());
+ }
+ eventType = parser.nextTag();
+ }
+ return new AppAuthenticator(context, permissionAllowMap, expectedIdentities,
+ digestAlgorithm);
+ } catch (XmlPullParserException e) {
+ throw new AppAuthenticatorXmlException("Caught an exception parsing the provided "
+ + "XML:", e);
+ }
+ }
+
+ /**
+ * Parses package tags from the provided {@code parser}, allowing the {@code all-packages}
+ * tag if the {@code allPackagesAllowed} boolean is true.
+ *
+ * @param parser the {@link XmlPullParser} from which to parser the packages
+ * @param allPackagesAllowed boolean indicating whether the {@code all-packages} element is
+ * allowed
+ * @return a mapping from the enclosed packages to signing identities
+ * @throws AppAuthenticatorXmlException if the provided XML parsed by the {@code XmlPullParser}
+ * is not in the proper format
+ * @throws IOException if an IO error is encountered when attempting to read
+ * from the {@code XmlPullParser}
+ * @throws XmlPullParserException if any errors are encountered when attempting to
+ * parse the provided {@code XmlPullParser}
+ */
+ private static Map<String, Set<String>> parsePackages(XmlPullParser parser,
+ boolean allPackagesAllowed)
+ throws AppAuthenticatorXmlException, IOException, XmlPullParserException {
+ Map<String, Set<String>> allowedPackageCerts = new ArrayMap<>();
+ int eventType = parser.nextTag();
+ while (eventType == XmlPullParser.START_TAG) {
+ String tag = parser.getName();
+ String packageName;
+ if (tag.equalsIgnoreCase(PACKAGE_TAG)) {
+ assertExpectedAttribute(parser, PACKAGE_TAG, NAME_ATTRIBUTE, true);
+ packageName = parser.getAttributeValue(null, NAME_ATTRIBUTE);
+ if (TextUtils.isEmpty(packageName)) {
+ throw new AppAuthenticatorXmlException(
+ "The " + PACKAGE_TAG + " tag requires a non-empty value for the "
+ + NAME_ATTRIBUTE + " attribute");
+ }
+ } else if (tag.equalsIgnoreCase(ALL_PACKAGES_TAG)) {
+ packageName = ALL_PACKAGES_TAG;
+ if (!allPackagesAllowed) {
+ throw new AppAuthenticatorXmlException("The " + ALL_PACKAGES_TAG
+ + " tag is not allowed within this element on line "
+ + parser.getLineNumber());
+ }
+ } else {
+ throw new AppAuthenticatorXmlException(
+ "Unexpected tag " + tag + " on line " + parser.getLineNumber()
+ + "; expected " + PACKAGE_TAG + "" + (allPackagesAllowed ? " or "
+ + ALL_PACKAGES_TAG : ""));
+ }
+ Set<String> allowedCertDigests = parseCertDigests(parser);
+ if (allowedCertDigests.isEmpty()) {
+ throw new AppAuthenticatorXmlException("No " + CERT_DIGEST_TAG + " tag found "
+ + "within " + tag + " element on line " + parser.getLineNumber());
+ }
+ if (allowedPackageCerts.containsKey(packageName)) {
+ allowedPackageCerts.get(packageName).addAll(allowedCertDigests);
+ } else {
+ allowedPackageCerts.put(packageName, allowedCertDigests);
+ }
+ eventType = parser.nextTag();
+ }
+ return allowedPackageCerts;
+ }
+
+ /**
+ * Parses certificate digests from the provided {@code parser}, returning a {@link Set} of
+ * parsed digests.
+ *
+ * @param parser the {@link XmlPullParser} from which to parser the digests
+ * @return a {@code Set} of certificate digests
+ * @throws AppAuthenticatorXmlException if the provided XML parsed by the {@code XmlPullParser}
+ * is not in the proper format
+ * @throws IOException if an IO error is encountered when attempting to read
+ * from the {@code XmlPullParser}
+ * @throws XmlPullParserException if any errors are encountered when attempting to
+ * parse the provided {@code XmlPullParser}
+ */
+ private static Set<String> parseCertDigests(XmlPullParser parser)
+ throws AppAuthenticatorXmlException, IOException,
+ XmlPullParserException {
+ Set<String> allowedCertDigests = new ArraySet<>();
+ int eventType = parser.nextTag();
+ while (eventType == XmlPullParser.START_TAG) {
+ String tag = parser.getName();
+ if (!tag.equalsIgnoreCase(CERT_DIGEST_TAG)) {
+ throw new AppAuthenticatorXmlException(
+ "Expected " + CERT_DIGEST_TAG + " on line " + parser.getLineNumber());
+ }
+ String digest = parser.nextText();
+ if (TextUtils.isEmpty(digest)) {
+ throw new AppAuthenticatorXmlException("The " + CERT_DIGEST_TAG + " element "
+ + "on line " + parser.getLineNumber() + " must have non-empty text "
+ + "containing the certificate digest of the signer");
+ }
+ allowedCertDigests.add(digest);
+ eventType = parser.nextTag();
+ }
+ return allowedCertDigests;
+ }
+
+ /**
+ * Moves the provided {@code parser} to the next {@link XmlPullParser#START_TAG} or {@link
+ * XmlPullParser#END_DOCUMENT} if the end of the document is reached, returning the value of
+ * the event type.
+ */
+ private static int parseToNextStartTag(XmlPullParser parser) throws IOException,
+ XmlPullParserException {
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // Empty loop to reach the first start tag or end of the document.
+ }
+ return type;
+ }
+
+ /**
+ * Asserts the current {@code tagName} contains only the specified {@code expectedAttribute},
+ * or no elements if not {@code required}; a null {@code expectedAttribute} can be used to
+ * assert no attributes are provided.
+ *
+ * <p>This method is intended to report if unsupported attributes are specified to warn the
+ * caller that the provided value will not be used by this instance. Since this method is
+ * checking the attributes it must only be called when the current event type is {@link
+ * XmlPullParser#START_TAG}.
+ */
+ private static void assertExpectedAttribute(XmlPullParser parser, String tagName,
+ String expectedAttribute, boolean required)
+ throws AppAuthenticatorXmlException, XmlPullParserException {
+ int attributeCount = parser.getAttributeCount();
+ if (attributeCount == -1) {
+ throw new AssertionError(
+ "parser#getAttributeCount called for event type " + parser.getEventType()
+ + " on line " + parser.getLineNumber());
+ }
+ if (attributeCount == 0 && expectedAttribute != null && required) {
+ throw new AppAuthenticatorXmlException("The attribute " + expectedAttribute + " is "
+ + "required for tag " + tagName + " on line " + parser.getLineNumber());
+ }
+ StringBuilder unsupportedAttributes = null;
+ for (int i = 0; i < attributeCount; i++) {
+ String attributeName = parser.getAttributeName(i);
+ if (!attributeName.equalsIgnoreCase(expectedAttribute)) {
+ if (unsupportedAttributes == null) {
+ unsupportedAttributes = new StringBuilder();
+ } else {
+ unsupportedAttributes.append(", ");
+ }
+ unsupportedAttributes.append(attributeName);
+ }
+ }
+ if (unsupportedAttributes != null) {
+ String prefixMessage;
+ if (expectedAttribute == null) {
+ prefixMessage = "Tag " + tagName + " does not support any attributes";
+ } else {
+ prefixMessage = "Tag " + tagName + " only supports attribute " + expectedAttribute;
+ }
+ throw new AppAuthenticatorXmlException(
+ prefixMessage + "; found the following unsupported attributes on line "
+ + parser.getLineNumber() + ": " + unsupportedAttributes);
+ }
+ }
+}
diff --git a/security/security-app-authenticator/src/main/java/androidx/security/app/authenticator/AppAuthenticatorXmlException.java b/security/security-app-authenticator/src/main/java/androidx/security/app/authenticator/AppAuthenticatorXmlException.java
new file mode 100644
index 0000000..6ce4ce6
--- /dev/null
+++ b/security/security-app-authenticator/src/main/java/androidx/security/app/authenticator/AppAuthenticatorXmlException.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.security.app.authenticator;
+
+import androidx.annotation.NonNull;
+
+/**
+ * This {@code Exception} is thrown when the XML configuration file is not in the proper format
+ * to instantiate a new {@link AppAuthenticator}.
+ */
+public class AppAuthenticatorXmlException extends Exception {
+ /**
+ * Creates a new {@code AppAuthenticatorXmlException} with the provided {@code message}.
+ */
+ AppAuthenticatorXmlException(@NonNull String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new {@code AppAuthenticationXmlException} with the provided {@code message} and
+ * the specified {@code cause}.
+ */
+ AppAuthenticatorXmlException(@NonNull String message, @NonNull Throwable cause) {
+ super(message, cause);
+ }
+}