Merge "Identity Credential: Require passing applicationId when generating attestation." am: 7175150e3f am: 396315d92f

Change-Id: Idca7bf3e5cbe681dc8f1ccccda414dd23d637fee
diff --git a/current.txt b/current.txt
index 4643e0d..a4caf0c 100644
--- a/current.txt
+++ b/current.txt
@@ -626,7 +626,7 @@
 0589e410f519e36514e7ece18f283f022df0f70efd2c12821d822f67f74aba98 android.hardware.identity@1.0::types
 bbeee9604128ede83ee755b67e73b5ad29e6e1dbac9ec41fea6ffe2745b0c50a android.hardware.identity@1.0::IIdentityCredential
 96ce8aad80f4c476f25261f790d357c117e79e18474c7dadd850dac704bbe65e android.hardware.identity@1.0::IIdentityCredentialStore
-6e1e28a96c90ba78d47257faea3f3bb4e6360affbbfa5822f0dc31211f9266ff android.hardware.identity@1.0::IWritableIdentityCredential
+8da9c938e58f7d636ddd2f92c646f99d9a9e79612e6441b6380ab12744251873 android.hardware.identity@1.0::IWritableIdentityCredential
 27ae3724053940462114228872b3ffaf0b8e6177d5ba97f5a76339d12b8a99dd android.hardware.keymaster@4.1::IKeymasterDevice
 adb0efdf1462e9b2e742c0dcadd598666aac551f178be06e755bfcdf5797abd0 android.hardware.keymaster@4.1::IOperation
 ac429fca0da4ce91218768ec31b64ded88251f8a26d8c4f27c06abdc5b1926d9 android.hardware.keymaster@4.1::types
diff --git a/identity/1.0/IWritableIdentityCredential.hal b/identity/1.0/IWritableIdentityCredential.hal
index b1ce00d..f26f763 100644
--- a/identity/1.0/IWritableIdentityCredential.hal
+++ b/identity/1.0/IWritableIdentityCredential.hal
@@ -26,20 +26,56 @@
      * characteristics to an issuing authority.  Must not be called more than once.
      *
      * The certificate chain must be generated using Keymaster Attestation
-     * (see https://source.android.com/security/keystore/attestation) and must also
-     * have the Tag::IDENTITY_CREDENTIAL_KEY tag from KeyMaster 4.1 set. This tag indicates
-     * that this key is an Identity Credential key (which can only sign/MAC very
-     * specific messages) and not an Android Keystore key (which can be used to sign/MAC
-     * anything).
+     * (see https://source.android.com/security/keystore/attestation) with the
+     * following additional requirements:
+     *
+     *  - The attestationVersion field in the attestation extension must be at least 3.
+     *
+     *  - The attestationSecurityLevel field must be set to either Software (0),
+     *    TrustedEnvironment (1), or StrongBox (2) depending on how attestation is
+     *    implemented. Only the default AOSP implementation of this HAL may use
+     *    value 0 (additionally, this implementation must not be used on production
+     *    devices).
+     *
+     *  - The keymasterVersion field in the attestation extension must be set to (10*major + minor)
+     *    where major and minor are the Identity Credential interface major and minor versions.
+     *    Specifically for this version of the interface (1.0) this value is 10.
+     *
+     *  - The keymasterSecurityLevel field in the attestation extension must be set to
+     *    either Software (0), TrustedEnvironment (1), or StrongBox (2) depending on how
+     *    the Trusted Application backing the HAL implementation is implemented. Only
+     *    the default AOSP implementation of this HAL may use value 0 (additionally, this
+     *    implementation must not be used on production devices)
+     *
+     *  - The attestationChallenge field must be set to the passed-in challenge.
+     *
+     *  - The uniqueId field must be empty.
+     *
+     *  - The softwareEnforced field in the attestation extension must include
+     *    Tag::ATTESTATION_APPLICATION_ID which must be set to the bytes of the passed-in
+     *    attestationApplicationId.
+     *
+     *  - The teeEnforced field in the attestation extension must include
+     *    Tag::IDENTITY_CREDENTIAL_KEY. This tag indicates that the key is an Identity
+     *    Credential key (which can only sign/MAC very specific messages) and not an Android
+     *    Keystore key (which can be used to sign/MAC anything).
+     *
+     * Additional authorizations may be needed in the softwareEnforced and teeEnforced
+     * fields - the above is not an exhaustive list.
+     *
+     * @param attestationApplicationId is the DER encoded value to be stored
+     *     in Tag::ATTESTATION_APPLICATION_ID. This schema is described in
+     *     https://developer.android.com/training/articles/security-key-attestation#certificate_schema_attestationid
      *
      * @param attestationChallenge a challenge set by the issuer to ensure freshness.
      *
      * @return result is OK on success, FAILED if an error occurred.
      *
-     * @return certificate is the X.509 certificate chain for the credentialKey
+     * @return certificateChain is the X.509 certificate chain for the credentialKey
      */
-    getAttestationCertificate(vec<uint8_t> attestationChallenge)
-        generates(Result result, vec<uint8_t> certificate);
+    getAttestationCertificate(vec<uint8_t> attestationApplicationId,
+                              vec<uint8_t> attestationChallenge)
+        generates(Result result, vec<vec<uint8_t>> certificateChain);
 
     /**
      * Start the personalization process.
diff --git a/identity/1.0/default/WritableIdentityCredential.cpp b/identity/1.0/default/WritableIdentityCredential.cpp
index 548b4c0..4c39f85 100644
--- a/identity/1.0/default/WritableIdentityCredential.cpp
+++ b/identity/1.0/default/WritableIdentityCredential.cpp
@@ -108,7 +108,12 @@
     return true;
 }
 
+// TODO: use |attestationApplicationId| and |attestationChallenge| and also
+//       ensure the returned certificate chain satisfy the requirements listed in
+//       the docs for IWritableIdentityCredential::getAttestationCertificate()
+//
 Return<void> WritableIdentityCredential::getAttestationCertificate(
+        const hidl_vec<uint8_t>& /* attestationApplicationId */,
         const hidl_vec<uint8_t>& /* attestationChallenge */,
         getAttestationCertificate_cb _hidl_cb) {
     // For now, we dynamically generate an attestion key on each and every
@@ -181,7 +186,16 @@
     certificateChain.insert(certificateChain.end(), attestationKeyCertificate.value().begin(),
                             attestationKeyCertificate.value().end());
 
-    _hidl_cb(support::resultOK(), certificateChain);
+    optional<vector<vector<uint8_t>>> splitCertChain =
+            support::certificateChainSplit(certificateChain);
+    if (!splitCertChain) {
+        _hidl_cb(support::result(ResultCode::FAILED, "Error splitting certificate chain"), {});
+        return Void();
+    }
+    hidl_vec<hidl_vec<uint8_t>> ret;
+    ret.resize(splitCertChain.value().size());
+    std::copy(splitCertChain.value().begin(), splitCertChain.value().end(), ret.begin());
+    _hidl_cb(support::resultOK(), ret);
     return Void();
 }
 
diff --git a/identity/1.0/default/WritableIdentityCredential.h b/identity/1.0/default/WritableIdentityCredential.h
index 9f4e303..b1deb16 100644
--- a/identity/1.0/default/WritableIdentityCredential.h
+++ b/identity/1.0/default/WritableIdentityCredential.h
@@ -51,7 +51,8 @@
 
     // Methods from ::android::hardware::identity::IWritableIdentityCredential
     // follow.
-    Return<void> getAttestationCertificate(const hidl_vec<uint8_t>& attestationChallenge,
+    Return<void> getAttestationCertificate(const hidl_vec<uint8_t>& attestationApplicationId,
+                                           const hidl_vec<uint8_t>& attestationChallenge,
                                            getAttestationCertificate_cb _hidl_cb) override;
 
     Return<void> startPersonalization(uint16_t accessControlProfileCount,
diff --git a/identity/1.0/vts/functional/VtsHalIdentityCredentialTargetTest.cpp b/identity/1.0/vts/functional/VtsHalIdentityCredentialTargetTest.cpp
index 903e912..88b06df 100644
--- a/identity/1.0/vts/functional/VtsHalIdentityCredentialTargetTest.cpp
+++ b/identity/1.0/vts/functional/VtsHalIdentityCredentialTargetTest.cpp
@@ -201,13 +201,18 @@
     ASSERT_NE(writableCredential, nullptr);
 
     string challenge = "attestationChallenge";
+    // TODO: set it to something random and check it's in the cert chain
+    vector<uint8_t> attestationApplicationId = {};
     vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
     vector<uint8_t> attestationCertificate;
     writableCredential->getAttestationCertificate(
-            attestationChallenge,
-            [&](const Result& _result, const hidl_vec<uint8_t>& _attestationCertificate) {
+            attestationApplicationId, attestationChallenge,
+            [&](const Result& _result, const hidl_vec<hidl_vec<uint8_t>>& _splitCertChain) {
                 result = _result;
-                attestationCertificate = _attestationCertificate;
+                vector<vector<uint8_t>> splitCerts;
+                std::copy(_splitCertChain.begin(), _splitCertChain.end(),
+                          std::back_inserter(splitCerts));
+                attestationCertificate = support::certificateChainJoin(splitCerts);
             });
     EXPECT_EQ("", result.message);
     ASSERT_EQ(ResultCode::OK, result.code);