Identity Credential changes for Android 12

- Add IIdentityCredential.deleteCredentialWithChallenge()
- Deprecate IIdentityCredential.deleteCredential()
- Add IIdentityCredential.proveOwership()
- Add IIdentityCredential.updateCredential()
- Add ProofOfBinding CBOR to AuthenticationKey X.509 certificate
- Document which API versions new methods/features appeared in.
- Mention need to declare android.hardware.identity_credential system
  feature (w/ feature version number) and do this for the default
  implementation.

Bug: 170146643
Test: atest VtsHalIdentityTargetTest
Change-Id: Ib47c7caa5f3d6fff6919f019eee44a735dba9cf8
diff --git a/identity/aidl/default/common/IdentityCredential.cpp b/identity/aidl/default/common/IdentityCredential.cpp
index 270fcfa..9477997 100644
--- a/identity/aidl/default/common/IdentityCredential.cpp
+++ b/identity/aidl/default/common/IdentityCredential.cpp
@@ -30,6 +30,7 @@
 #include <cppbor_parse.h>
 
 #include "FakeSecureHardwareProxy.h"
+#include "WritableIdentityCredential.h"
 
 namespace aidl::android::hardware::identity {
 
@@ -70,14 +71,8 @@
     docType_ = docTypeItem->value();
     testCredential_ = testCredentialItem->value();
 
-    const vector<uint8_t>& encryptedCredentialKeys = encryptedCredentialKeysItem->value();
-
-    if (encryptedCredentialKeys.size() != 80) {
-        LOG(ERROR) << "Unexpected size for encrypted CredentialKeys";
-        return IIdentityCredentialStore::STATUS_INVALID_DATA;
-    }
-
-    if (!hwProxy_->initialize(testCredential_, docType_, encryptedCredentialKeys)) {
+    encryptedCredentialKeys_ = encryptedCredentialKeysItem->value();
+    if (!hwProxy_->initialize(testCredential_, docType_, encryptedCredentialKeys_)) {
         LOG(ERROR) << "hwProxy->initialize failed";
         return false;
     }
@@ -87,12 +82,32 @@
 
 ndk::ScopedAStatus IdentityCredential::deleteCredential(
         vector<uint8_t>* outProofOfDeletionSignature) {
+    return deleteCredentialCommon({}, false, outProofOfDeletionSignature);
+}
+
+ndk::ScopedAStatus IdentityCredential::deleteCredentialWithChallenge(
+        const vector<uint8_t>& challenge, vector<uint8_t>* outProofOfDeletionSignature) {
+    return deleteCredentialCommon(challenge, true, outProofOfDeletionSignature);
+}
+
+ndk::ScopedAStatus IdentityCredential::deleteCredentialCommon(
+        const vector<uint8_t>& challenge, bool includeChallenge,
+        vector<uint8_t>* outProofOfDeletionSignature) {
+    if (challenge.size() > 32) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA, "Challenge too big"));
+    }
+
     cppbor::Array array = {"ProofOfDeletion", docType_, testCredential_};
+    if (includeChallenge) {
+        array = {"ProofOfDeletion", docType_, challenge, testCredential_};
+    }
+
     vector<uint8_t> proofOfDeletionCbor = array.encode();
     vector<uint8_t> podDigest = support::sha256(proofOfDeletionCbor);
 
-    optional<vector<uint8_t>> signatureOfToBeSigned =
-            hwProxy_->deleteCredential(docType_, proofOfDeletionCbor.size());
+    optional<vector<uint8_t>> signatureOfToBeSigned = hwProxy_->deleteCredential(
+            docType_, challenge, includeChallenge, proofOfDeletionCbor.size());
     if (!signatureOfToBeSigned) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                 IIdentityCredentialStore::STATUS_FAILED, "Error signing ProofOfDeletion"));
@@ -111,6 +126,38 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus IdentityCredential::proveOwnership(
+        const vector<uint8_t>& challenge, vector<uint8_t>* outProofOfOwnershipSignature) {
+    if (challenge.size() > 32) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA, "Challenge too big"));
+    }
+
+    cppbor::Array array;
+    array = {"ProofOfOwnership", docType_, challenge, testCredential_};
+    vector<uint8_t> proofOfOwnershipCbor = array.encode();
+    vector<uint8_t> podDigest = support::sha256(proofOfOwnershipCbor);
+
+    optional<vector<uint8_t>> signatureOfToBeSigned = hwProxy_->proveOwnership(
+            docType_, testCredential_, challenge, proofOfOwnershipCbor.size());
+    if (!signatureOfToBeSigned) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error signing ProofOfOwnership"));
+    }
+
+    optional<vector<uint8_t>> signature =
+            support::coseSignEcDsaWithSignature(signatureOfToBeSigned.value(),
+                                                proofOfOwnershipCbor,  // data
+                                                {});                   // certificateChain
+    if (!signature) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error signing data"));
+    }
+
+    *outProofOfOwnershipSignature = signature.value();
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus IdentityCredential::createEphemeralKeyPair(vector<uint8_t>* outKeyPair) {
     optional<vector<uint8_t>> ephemeralPriv = hwProxy_->createEphemeralKeyPair();
     if (!ephemeralPriv) {
@@ -833,4 +880,19 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus IdentityCredential::updateCredential(
+        shared_ptr<IWritableIdentityCredential>* outWritableCredential) {
+    sp<SecureHardwareProvisioningProxy> hwProxy = hwProxyFactory_->createProvisioningProxy();
+    shared_ptr<WritableIdentityCredential> wc =
+            ndk::SharedRefBase::make<WritableIdentityCredential>(hwProxy, docType_,
+                                                                 testCredential_);
+    if (!wc->initializeForUpdate(encryptedCredentialKeys_)) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Error initializing WritableIdentityCredential for update"));
+    }
+    *outWritableCredential = wc;
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/common/IdentityCredential.h b/identity/aidl/default/common/IdentityCredential.h
index 2281821..9913b86 100644
--- a/identity/aidl/default/common/IdentityCredential.h
+++ b/identity/aidl/default/common/IdentityCredential.h
@@ -45,9 +45,11 @@
 
 class IdentityCredential : public BnIdentityCredential {
   public:
-    IdentityCredential(sp<SecureHardwarePresentationProxy> hwProxy,
+    IdentityCredential(sp<SecureHardwareProxyFactory> hwProxyFactory,
+                       sp<SecureHardwarePresentationProxy> hwProxy,
                        const vector<uint8_t>& credentialData)
-        : hwProxy_(hwProxy),
+        : hwProxyFactory_(hwProxyFactory),
+          hwProxy_(hwProxy),
           credentialData_(credentialData),
           numStartRetrievalCalls_(0),
           expectedDeviceNameSpacesSize_(0) {}
@@ -58,6 +60,11 @@
 
     // Methods from IIdentityCredential follow.
     ndk::ScopedAStatus deleteCredential(vector<uint8_t>* outProofOfDeletionSignature) override;
+    ndk::ScopedAStatus deleteCredentialWithChallenge(
+            const vector<uint8_t>& challenge,
+            vector<uint8_t>* outProofOfDeletionSignature) override;
+    ndk::ScopedAStatus proveOwnership(const vector<uint8_t>& challenge,
+                                      vector<uint8_t>* outProofOfOwnershipSignature) override;
     ndk::ScopedAStatus createEphemeralKeyPair(vector<uint8_t>* outKeyPair) override;
     ndk::ScopedAStatus setReaderEphemeralPublicKey(const vector<uint8_t>& publicKey) override;
     ndk::ScopedAStatus createAuthChallenge(int64_t* outChallenge) override;
@@ -79,8 +86,16 @@
     ndk::ScopedAStatus generateSigningKeyPair(vector<uint8_t>* outSigningKeyBlob,
                                               Certificate* outSigningKeyCertificate) override;
 
+    ndk::ScopedAStatus updateCredential(
+            shared_ptr<IWritableIdentityCredential>* outWritableCredential) override;
+
   private:
+    ndk::ScopedAStatus deleteCredentialCommon(const vector<uint8_t>& challenge,
+                                              bool includeChallenge,
+                                              vector<uint8_t>* outProofOfDeletionSignature);
+
     // Set by constructor
+    sp<SecureHardwareProxyFactory> hwProxyFactory_;
     sp<SecureHardwarePresentationProxy> hwProxy_;
     vector<uint8_t> credentialData_;
     int numStartRetrievalCalls_;
@@ -88,6 +103,7 @@
     // Set by initialize()
     string docType_;
     bool testCredential_;
+    vector<uint8_t> encryptedCredentialKeys_;
 
     // Set by createEphemeralKeyPair()
     vector<uint8_t> ephemeralPublicKey_;
diff --git a/identity/aidl/default/common/IdentityCredentialStore.cpp b/identity/aidl/default/common/IdentityCredentialStore.cpp
index 13f91aa..e6b5466 100644
--- a/identity/aidl/default/common/IdentityCredentialStore.cpp
+++ b/identity/aidl/default/common/IdentityCredentialStore.cpp
@@ -63,7 +63,7 @@
 
     sp<SecureHardwarePresentationProxy> hwProxy = hwProxyFactory_->createPresentationProxy();
     shared_ptr<IdentityCredential> credential =
-            ndk::SharedRefBase::make<IdentityCredential>(hwProxy, credentialData);
+            ndk::SharedRefBase::make<IdentityCredential>(hwProxyFactory_, hwProxy, credentialData);
     auto ret = credential->initialize();
     if (ret != IIdentityCredentialStore::STATUS_OK) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
diff --git a/identity/aidl/default/common/SecureHardwareProxy.h b/identity/aidl/default/common/SecureHardwareProxy.h
index b89ad87..a1ed1ef 100644
--- a/identity/aidl/default/common/SecureHardwareProxy.h
+++ b/identity/aidl/default/common/SecureHardwareProxy.h
@@ -64,6 +64,9 @@
 
     virtual bool initialize(bool testCredential) = 0;
 
+    virtual bool initializeForUpdate(bool testCredential, string docType,
+                                     vector<uint8_t> encryptedCredentialKeys) = 0;
+
     // Returns public key certificate chain with attestation.
     //
     // This must return an entire certificate chain and its implementation must
@@ -164,8 +167,14 @@
     virtual optional<vector<uint8_t>> finishRetrieval();
 
     virtual optional<vector<uint8_t>> deleteCredential(const string& docType,
+                                                       const vector<uint8_t>& challenge,
+                                                       bool includeChallenge,
                                                        size_t proofOfDeletionCborSize) = 0;
 
+    virtual optional<vector<uint8_t>> proveOwnership(const string& docType, bool testCredential,
+                                                     const vector<uint8_t>& challenge,
+                                                     size_t proofOfOwnershipCborSize) = 0;
+
     virtual bool shutdown() = 0;
 };
 
diff --git a/identity/aidl/default/common/WritableIdentityCredential.cpp b/identity/aidl/default/common/WritableIdentityCredential.cpp
index 1328f36..2d897c7 100644
--- a/identity/aidl/default/common/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/common/WritableIdentityCredential.cpp
@@ -40,7 +40,20 @@
 
 bool WritableIdentityCredential::initialize() {
     if (!hwProxy_->initialize(testCredential_)) {
-        LOG(ERROR) << "hwProxy->initialize failed";
+        LOG(ERROR) << "hwProxy->initialize() failed";
+        return false;
+    }
+    startPersonalizationCalled_ = false;
+    firstEntry_ = true;
+
+    return true;
+}
+
+// Used when updating a credential. Returns false on failure.
+bool WritableIdentityCredential::initializeForUpdate(
+        const vector<uint8_t>& encryptedCredentialKeys) {
+    if (!hwProxy_->initializeForUpdate(testCredential_, docType_, encryptedCredentialKeys)) {
+        LOG(ERROR) << "hwProxy->initializeForUpdate() failed";
         return false;
     }
     startPersonalizationCalled_ = false;
diff --git a/identity/aidl/default/common/WritableIdentityCredential.h b/identity/aidl/default/common/WritableIdentityCredential.h
index c6f0628..36ad430 100644
--- a/identity/aidl/default/common/WritableIdentityCredential.h
+++ b/identity/aidl/default/common/WritableIdentityCredential.h
@@ -36,16 +36,22 @@
 
 class WritableIdentityCredential : public BnWritableIdentityCredential {
   public:
+    // For a new credential, call initialize() right after construction.
+    //
+    // For an updated credential, call initializeForUpdate() right after construction.
+    //
     WritableIdentityCredential(sp<SecureHardwareProvisioningProxy> hwProxy, const string& docType,
                                bool testCredential)
         : hwProxy_(hwProxy), docType_(docType), testCredential_(testCredential) {}
 
     ~WritableIdentityCredential();
 
-    // Creates the Credential Key. Returns false on failure. Must be called
-    // right after construction.
+    // Creates the Credential Key. Returns false on failure.
     bool initialize();
 
+    // Used when updating a credential. Returns false on failure.
+    bool initializeForUpdate(const vector<uint8_t>& encryptedCredentialKeys);
+
     // Methods from IWritableIdentityCredential follow.
     ndk::ScopedAStatus getAttestationCertificate(const vector<uint8_t>& attestationApplicationId,
                                                  const vector<uint8_t>& attestationChallenge,