Identity: Move signingKeyBlob from finishRetrieval() to startRetrieval().

The implementation of the Identity Credential TA in constrained
environments may need to incrementally update the HMAC-SHA256 of
DeviceAuthencation CBOR to avoid keeping the entire CBOR structure in
memory. To do this they need to calculate the derived key before
starting to build the CBOR so they need access to the signingKey
earlier on.

Bug: 150390415
Test: atest android.security.identity.cts
Test: VtsHalIdentityTargetTest
Change-Id: I72ad30ec3ccec0b8161cbea360ef8c9212f8cbbc
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
index 10ce4c2..cc14271 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
@@ -176,6 +176,10 @@
      * @param itemsRequest
      *   If non-empty, contains request data that is signed by the reader. See above.
      *
+     * @param signingKeyBlob is either empty or a signingKeyBlob (see generateSigningKeyPair(),
+     *    below) containing the signing key to use to sign the data retrieved. If this
+     *    is not in the right format the call fails with STATUS_INVALID_DATA.
+     *
      * @param sessionTranscript
      *   Either empty or the CBOR of the SessionTranscript. See above.
      *
@@ -195,8 +199,7 @@
      *   and remove the corresponding requests from the counts.
      */
     void startRetrieval(in SecureAccessControlProfile[] accessControlProfiles,
-        in HardwareAuthToken authToken,
-        in byte[] itemsRequest,
+        in HardwareAuthToken authToken, in byte[] itemsRequest, in byte[] signingKeyBlob,
         in byte[] sessionTranscript, in byte[] readerSignature, in int[] requestCounts);
 
     /**
@@ -254,10 +257,6 @@
      * If signingKeyBlob or the sessionTranscript parameter passed to startRetrieval() is
      * empty then the returned MAC will be empty.
      *
-     * @param signingKeyBlob is either empty or a signingKeyBlob (see generateSigningKeyPair(),
-     *    below) containing the signing key to use to sign the data retrieved. If this
-     *    is not in the right format the call fails with STATUS_INVALID_DATA.
-     *
      * @param out mac is empty if signingKeyBlob or the sessionTranscript passed to
      *    startRetrieval() is empty. Otherwise it is a COSE_Mac0 with empty payload
      *    and the detached content is set to DeviceAuthentication as defined below.
@@ -304,7 +303,7 @@
      *
      * @param out deviceNameSpaces the bytes of DeviceNameSpaces.
      */
-    void finishRetrieval(in byte[] signingKeyBlob, out byte[] mac, out byte[] deviceNameSpaces);
+    void finishRetrieval(out byte[] mac, out byte[] deviceNameSpaces);
 
     /**
      * Generate a key pair to be used for signing session data and retrieved data items.
diff --git a/identity/aidl/default/IdentityCredential.cpp b/identity/aidl/default/IdentityCredential.cpp
index d5b3a0f..341fae6 100644
--- a/identity/aidl/default/IdentityCredential.cpp
+++ b/identity/aidl/default/IdentityCredential.cpp
@@ -256,8 +256,8 @@
 ndk::ScopedAStatus IdentityCredential::startRetrieval(
         const vector<SecureAccessControlProfile>& accessControlProfiles,
         const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequestS,
-        const vector<int8_t>& sessionTranscriptS, const vector<int8_t>& readerSignatureS,
-        const vector<int32_t>& requestCounts) {
+        const vector<int8_t>& signingKeyBlobS, const vector<int8_t>& sessionTranscriptS,
+        const vector<int8_t>& readerSignatureS, const vector<int32_t>& requestCounts) {
     auto sessionTranscript = byteStringToUnsigned(sessionTranscriptS);
     auto itemsRequest = byteStringToUnsigned(itemsRequestS);
     auto readerSignature = byteStringToUnsigned(readerSignatureS);
@@ -498,6 +498,7 @@
     currentNameSpace_ = "";
 
     itemsRequest_ = itemsRequest;
+    signingKeyBlob_ = byteStringToUnsigned(signingKeyBlobS);
 
     numStartRetrievalCalls_ += 1;
     return ndk::ScopedAStatus::ok();
@@ -650,11 +651,8 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus IdentityCredential::finishRetrieval(const vector<int8_t>& signingKeyBlobS,
-                                                       vector<int8_t>* outMac,
+ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<int8_t>* outMac,
                                                        vector<int8_t>* outDeviceNameSpaces) {
-    auto signingKeyBlob = byteStringToUnsigned(signingKeyBlobS);
-
     if (currentNameSpaceDeviceNameSpacesMap_.size() > 0) {
         deviceNameSpacesMap_.add(currentNameSpace_,
                                  std::move(currentNameSpaceDeviceNameSpacesMap_));
@@ -664,7 +662,8 @@
     // If there's no signing key or no sessionTranscript or no reader ephemeral
     // public key, we return the empty MAC.
     optional<vector<uint8_t>> mac;
-    if (signingKeyBlob.size() > 0 && sessionTranscript_.size() > 0 && readerPublicKey_.size() > 0) {
+    if (signingKeyBlob_.size() > 0 && sessionTranscript_.size() > 0 &&
+        readerPublicKey_.size() > 0) {
         cppbor::Array array;
         array.add("DeviceAuthentication");
         array.add(sessionTranscriptItem_->clone());
@@ -674,7 +673,7 @@
 
         vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end());
         optional<vector<uint8_t>> signingKey =
-                support::decryptAes128Gcm(storageKey_, signingKeyBlob, docTypeAsBlob);
+                support::decryptAes128Gcm(storageKey_, signingKeyBlob_, docTypeAsBlob);
         if (!signingKey) {
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                     IIdentityCredentialStore::STATUS_INVALID_DATA,
diff --git a/identity/aidl/default/IdentityCredential.h b/identity/aidl/default/IdentityCredential.h
index 49ed0d4..fc29254 100644
--- a/identity/aidl/default/IdentityCredential.h
+++ b/identity/aidl/default/IdentityCredential.h
@@ -54,14 +54,14 @@
     ndk::ScopedAStatus startRetrieval(
             const vector<SecureAccessControlProfile>& accessControlProfiles,
             const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequest,
-            const vector<int8_t>& sessionTranscript, const vector<int8_t>& readerSignature,
-            const vector<int32_t>& requestCounts) override;
+            const vector<int8_t>& signingKeyBlob, const vector<int8_t>& sessionTranscript,
+            const vector<int8_t>& readerSignature, const vector<int32_t>& requestCounts) override;
     ndk::ScopedAStatus startRetrieveEntryValue(
             const string& nameSpace, const string& name, int32_t entrySize,
             const vector<int32_t>& accessControlProfileIds) override;
     ndk::ScopedAStatus retrieveEntryValue(const vector<int8_t>& encryptedContent,
                                           vector<int8_t>* outContent) override;
-    ndk::ScopedAStatus finishRetrieval(const vector<int8_t>& signingKeyBlob, vector<int8_t>* outMac,
+    ndk::ScopedAStatus finishRetrieval(vector<int8_t>* outMac,
                                        vector<int8_t>* outDeviceNameSpaces) override;
     ndk::ScopedAStatus generateSigningKeyPair(vector<int8_t>* outSigningKeyBlob,
                                               Certificate* outSigningKeyCertificate) override;
@@ -88,6 +88,7 @@
 
     // Set at startRetrieval() time.
     map<int32_t, int> profileIdToAccessCheckResult_;
+    vector<uint8_t> signingKeyBlob_;
     vector<uint8_t> sessionTranscript_;
     std::unique_ptr<cppbor::Item> sessionTranscriptItem_;
     vector<uint8_t> itemsRequest_;
diff --git a/identity/aidl/vts/VtsHalIdentityTargetTest.cpp b/identity/aidl/vts/VtsHalIdentityTargetTest.cpp
index 5abe5a2..ea37fdc 100644
--- a/identity/aidl/vts/VtsHalIdentityTargetTest.cpp
+++ b/identity/aidl/vts/VtsHalIdentityTargetTest.cpp
@@ -352,10 +352,15 @@
                                    readerCertificate.value());
     ASSERT_TRUE(readerSignature);
 
+    // Generate the key that will be used to sign AuthenticatedData.
+    vector<uint8_t> signingKeyBlob;
+    Certificate signingKeyCertificate;
+    ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
+
     ASSERT_TRUE(credential
                         ->startRetrieval(returnedSecureProfiles, authToken, itemsRequestBytes,
-                                         sessionTranscriptBytes, readerSignature.value(),
-                                         testEntriesEntryCounts)
+                                         signingKeyBlob, sessionTranscriptBytes,
+                                         readerSignature.value(), testEntriesEntryCounts)
                         .isOk());
 
     for (const auto& entry : testEntries) {
@@ -377,14 +382,9 @@
         EXPECT_EQ(content, entry.valueCbor);
     }
 
-    // Generate the key that will be used to sign AuthenticatedData.
-    vector<uint8_t> signingKeyBlob;
-    Certificate signingKeyCertificate;
-    ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
-
     vector<uint8_t> mac;
     vector<uint8_t> deviceNameSpacesBytes;
-    ASSERT_TRUE(credential->finishRetrieval(signingKeyBlob, &mac, &deviceNameSpacesBytes).isOk());
+    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
     cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
     ASSERT_EQ(
             "{\n"