identity: Fix attestation and documentation problems.

- The docs said that IdentityCredential.createEphemeralKey() returned
  data encoded PKCS#8 which is wrong. It's supposed to be in DER format
  which is also what the VTS tests and credstore expects.

- Clarify that createEphemeralKeyPair(), setReaderEphemeralPublicKey(),
  and createAuthChallenge() are all optional.

- Avoid passing an invalid profile ID in the IdentityCredentialTests.
  verifyOneProfileAndEntryPass test.

- Update requirements for which tags must be present in the attestation
  for CredentialKey as well as the requirements on expiration date and
  the issuer name.  Update default implementation to satisfy these
  requirements. Update VTS tests to carefully verify these requrements
  are met.

- Clarify requirements for X.509 cert for AuthenticationKey. Add VTS
  test to verify.

- Mandate that TAG_IDENTITY_CREDENTIAL_KEY must not be set for test
  credentials. Add VTS test to verify this.

- Make default implementation pretend to be implemented in a trusted
  environment and streamline VTS tests to not special-case for the
  default implementation.

- Switch to using the attestation extension parser from the KM 4.1
  support library instead of the one from system/keymaster. The latter
  one did not support the latest attestation extension and thus would
  fail for pretty much anything that wasn't the default HAL impl.

- Fix a couple of bugs in keymaster::V4_1::parse_attestation_record():
  - Report root_of_trust.security_level
  - Add support for Tag::IDENTITY_CREDENTIAL_KEY

- Fix how EMacKey is calculated.

- Add test vectors to verify how EMacKey and DeviceMac is calculated.

Test: atest VtsHalIdentityTargetTest
Test: atest android.security.identity.cts
Bug: 171745570
Change-Id: I2f8bd772de078556733f769cec2021918d1d7de6
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
index 730b601..702334d 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
@@ -55,7 +55,7 @@
      * This method may only be called once per instance. If called more than once, STATUS_FAILED
      * will be returned.
      *
-     * @return the unencrypted key-pair in PKCS#8 format.
+     * @return the private key, in DER format as specified in RFC 5915.
      */
     byte[] createEphemeralKeyPair();
 
@@ -88,10 +88,10 @@
      * The setRequestedNamespaces() and setVerificationToken() methods will be called before
      * this method is called.
      *
-     * This method be called after createEphemeralKeyPair(), setReaderEphemeralPublicKey(),
-     * createAuthChallenge() and before startRetrieveEntry(). This method call is followed by
-     * multiple calls of startRetrieveEntryValue(), retrieveEntryValue(), and finally
-     * finishRetrieval().
+     * This method is called after createEphemeralKeyPair(), setReaderEphemeralPublicKey(),
+     * createAuthChallenge() (note that those calls are optional) and before startRetrieveEntry().
+     * This method call is followed by multiple calls of startRetrieveEntryValue(),
+     * retrieveEntryValue(), and finally finishRetrieval().
      *
      * It is permissible to perform data retrievals multiple times using the same instance (e.g.
      * startRetrieval(), then multiple calls of startRetrieveEntryValue(), retrieveEntryValue(),
@@ -343,12 +343,13 @@
      *
      *  - signature: must be set to ECDSA.
      *
-     *  - subject: CN shall be set to "Android Identity Credential Authentication Key".
+     *  - subject: CN shall be set to "Android Identity Credential Authentication Key". (fixed
+     *    value: same on all certs)
      *
-     *  - issuer: shall be set to "credentialStoreName (credentialStoreAuthorName)" using the
-     *    values returned in HardwareInformation.
+     *  - issuer: CN shall be set to "Android Identity Credential Key". (fixed value:
+     *    same on all certs)
      *
-     *  - validity: should be from current time and one year in the future.
+     *  - validity: should be from current time and one year in the future (365 days).
      *
      *  - subjectPublicKeyInfo: must contain attested public key.
      *
diff --git a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
index 297fd1d..c48cb66 100644
--- a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -37,12 +37,12 @@
      *
      *  - signature: must be set to ECDSA.
      *
-     *  - subject: CN shall be set to "Android Identity Credential Key".
+     *  - subject: CN shall be set to "Android Identity Credential Key". (fixed value:
+     *    same on all certs)
      *
-     *  - issuer: shall be set to "credentialStoreName (credentialStoreAuthorName)" using the
-     *    values returned in HardwareInformation.
+     *  - issuer: Same as the subject field of the batch attestation key.
      *
-     *  - validity: should be from current time and expire at the same time as the
+     *  - validity: Should be set to current time and expire at the same time as the
      *    attestation batch certificate used.
      *
      *  - subjectPublicKeyInfo: must contain attested public key.
@@ -55,19 +55,14 @@
      *
      *  - 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).
+     *    implemented.
      *
-     *  - 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 keymasterVersion field in the attestation extension must be set to the.
+     *    same value as used for Android Keystore keys.
      *
      *  - 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 Trusted Application backing the HAL implementation is implemented.
      *
      *  - The attestationChallenge field must be set to the passed-in challenge.
      *
@@ -81,7 +76,8 @@
      *
      *    - Tag::IDENTITY_CREDENTIAL_KEY which 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).
+     *      Keystore key (which can be used to sign/MAC anything). This must not be set
+     *      for test credentials.
      *
      *    - Tag::PURPOSE must be set to SIGN
      *
@@ -95,10 +91,13 @@
      *
      *    - Tag::EC_CURVE must be set to P_256
      *
-     * Additional authorizations may be needed in the softwareEnforced and teeEnforced
-     * fields - the above is not an exhaustive list. Specifically, authorizations containing
-     * information about the root of trust, OS version, verified boot state, and so on should
-     * be included.
+     *    - Tag::ROOT_OF_TRUST must be set
+     *
+     *    - Tag::OS_VERSION and Tag::OS_PATCHLEVEL must be set
+     *
+     * Additional authorizations may be appear in the softwareEnforced and teeEnforced
+     * fields. For example if the device has a boot or vendor partitions, then BOOT_PATCHLEVEL
+     * and VENDOR_PATCHLEVEL should be set.
      *
      * Since the chain is required to be generated using Keymaster Attestation, the returned
      * certificate chain has the following properties:
@@ -112,8 +111,8 @@
      * As with any user of attestation, the Issuing Authority (as a relying party) wishing
      * to issue a credential to a device using these APIs, must carefully examine the
      * returned certificate chain for all of the above (and more). In particular, the Issuing
-     * Authority should check the root of trust, verified boot state, patch level,
-     * application id, etc.
+     * Authority should check the root of trust (which include verified boot state), patch level,
+     * attestation application id, etc.
      *
      * This all depends on the needs of the Issuing Authority and the kind of credential but
      * in general an Issuing Authority should never issue a credential to a device without
diff --git a/identity/aidl/default/IdentityCredential.cpp b/identity/aidl/default/IdentityCredential.cpp
index 87d9a93..dfcd4f5 100644
--- a/identity/aidl/default/IdentityCredential.cpp
+++ b/identity/aidl/default/IdentityCredential.cpp
@@ -272,6 +272,7 @@
         const HardwareAuthToken& authToken, const vector<uint8_t>& itemsRequest,
         const vector<uint8_t>& signingKeyBlob, const vector<uint8_t>& sessionTranscript,
         const vector<uint8_t>& readerSignature, const vector<int32_t>& requestCounts) {
+    std::unique_ptr<cppbor::Item> sessionTranscriptItem;
     if (sessionTranscript.size() > 0) {
         auto [item, _, message] = cppbor::parse(sessionTranscript);
         if (item == nullptr) {
@@ -279,7 +280,7 @@
                     IIdentityCredentialStore::STATUS_INVALID_DATA,
                     "SessionTranscript contains invalid CBOR"));
         }
-        sessionTranscriptItem_ = std::move(item);
+        sessionTranscriptItem = std::move(item);
     }
     if (numStartRetrievalCalls_ > 0) {
         if (sessionTranscript_ != sessionTranscript) {
@@ -319,7 +320,7 @@
         vector<uint8_t> encodedReaderAuthentication =
                 cppbor::Array()
                         .add("ReaderAuthentication")
-                        .add(sessionTranscriptItem_->clone())
+                        .add(std::move(sessionTranscriptItem))
                         .add(cppbor::Semantic(24, itemsRequestBytes))
                         .encode();
         vector<uint8_t> encodedReaderAuthenticationBytes =
@@ -776,13 +777,6 @@
     optional<vector<uint8_t>> mac;
     if (signingKeyBlob_.size() > 0 && sessionTranscript_.size() > 0 &&
         readerPublicKey_.size() > 0) {
-        cppbor::Array array;
-        array.add("DeviceAuthentication");
-        array.add(sessionTranscriptItem_->clone());
-        array.add(docType_);
-        array.add(cppbor::Semantic(24, encodedDeviceNameSpaces));
-        vector<uint8_t> deviceAuthenticationBytes = cppbor::Semantic(24, array.encode()).encode();
-
         vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end());
         optional<vector<uint8_t>> signingKey =
                 support::decryptAes128Gcm(storageKey_, signingKeyBlob_, docTypeAsBlob);
@@ -792,31 +786,15 @@
                     "Error decrypting signingKeyBlob"));
         }
 
-        optional<vector<uint8_t>> sharedSecret =
-                support::ecdh(readerPublicKey_, signingKey.value());
-        if (!sharedSecret) {
-            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                    IIdentityCredentialStore::STATUS_FAILED, "Error doing ECDH"));
-        }
-
-        // Mix-in SessionTranscriptBytes
         vector<uint8_t> sessionTranscriptBytes = cppbor::Semantic(24, sessionTranscript_).encode();
-        vector<uint8_t> sharedSecretWithSessionTranscriptBytes = sharedSecret.value();
-        std::copy(sessionTranscriptBytes.begin(), sessionTranscriptBytes.end(),
-                  std::back_inserter(sharedSecretWithSessionTranscriptBytes));
-
-        vector<uint8_t> salt = {0x00};
-        vector<uint8_t> info = {};
-        optional<vector<uint8_t>> derivedKey =
-                support::hkdf(sharedSecretWithSessionTranscriptBytes, salt, info, 32);
-        if (!derivedKey) {
+        optional<vector<uint8_t>> eMacKey =
+                support::calcEMacKey(signingKey.value(), readerPublicKey_, sessionTranscriptBytes);
+        if (!eMacKey) {
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                    IIdentityCredentialStore::STATUS_FAILED,
-                    "Error deriving key from shared secret"));
+                    IIdentityCredentialStore::STATUS_FAILED, "Error calculating EMacKey"));
         }
-
-        mac = support::coseMac0(derivedKey.value(), {},      // payload
-                                deviceAuthenticationBytes);  // detached content
+        mac = support::calcMac(sessionTranscript_, docType_, encodedDeviceNameSpaces,
+                               eMacKey.value());
         if (!mac) {
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                     IIdentityCredentialStore::STATUS_FAILED, "Error MACing data"));
@@ -830,9 +808,9 @@
 
 ndk::ScopedAStatus IdentityCredential::generateSigningKeyPair(
         vector<uint8_t>* outSigningKeyBlob, Certificate* outSigningKeyCertificate) {
-    string serialDecimal = "0";  // TODO: set serial to something unique
-    string issuer = "Android Open Source Project";
-    string subject = "Android IdentityCredential Reference Implementation";
+    string serialDecimal = "1";
+    string issuer = "Android Identity Credential Key";
+    string subject = "Android Identity Credential Authentication Key";
     time_t validityNotBefore = time(nullptr);
     time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
 
diff --git a/identity/aidl/default/IdentityCredential.h b/identity/aidl/default/IdentityCredential.h
index a82531d..a8a6409 100644
--- a/identity/aidl/default/IdentityCredential.h
+++ b/identity/aidl/default/IdentityCredential.h
@@ -103,7 +103,6 @@
     map<int32_t, int> profileIdToAccessCheckResult_;
     vector<uint8_t> signingKeyBlob_;
     vector<uint8_t> sessionTranscript_;
-    std::unique_ptr<cppbor::Item> sessionTranscriptItem_;
     vector<uint8_t> itemsRequest_;
     vector<int32_t> requestCountsRemaining_;
     map<string, set<string>> requestedNameSpacesAndNames_;
diff --git a/identity/aidl/default/WritableIdentityCredential.cpp b/identity/aidl/default/WritableIdentityCredential.cpp
index fea289b..141b4de 100644
--- a/identity/aidl/default/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/WritableIdentityCredential.cpp
@@ -74,7 +74,7 @@
     vector<uint8_t> appId(attestationApplicationId.begin(), attestationApplicationId.end());
 
     optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> keyAttestationPair =
-            support::createEcKeyPairAndAttestation(challenge, appId);
+            support::createEcKeyPairAndAttestation(challenge, appId, testCredential_);
     if (!keyAttestationPair) {
         LOG(ERROR) << "Error creating credentialKey and attestation";
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index c1f44e7..03966de 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -9,7 +9,6 @@
         "VtsIWritableIdentityCredentialTests.cpp",
         "VtsIdentityTestUtils.cpp",
         "VtsAttestationTests.cpp",
-        "VtsAttestationParserSupport.cpp",
         "UserAuthTests.cpp",
         "ReaderAuthTests.cpp",
     ],
@@ -20,13 +19,14 @@
     static_libs: [
         "libcppbor",
         "libkeymaster_portable",
-        "libsoft_attestation_cert",
         "libpuresoftkeymasterdevice",
         "android.hardware.keymaster@4.0",
         "android.hardware.identity-support-lib",
         "android.hardware.identity-cpp",
         "android.hardware.keymaster-cpp",
         "android.hardware.keymaster-ndk_platform",
+        "libkeymaster4support",
+        "libkeymaster4_1support",
     ],
     test_suites: [
         "general-tests",
diff --git a/identity/aidl/vts/VtsAttestationParserSupport.cpp b/identity/aidl/vts/VtsAttestationParserSupport.cpp
deleted file mode 100644
index 71fe733..0000000
--- a/identity/aidl/vts/VtsAttestationParserSupport.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright 2019, 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.
- */
-
-#include "VtsAttestationParserSupport.h"
-
-#include <aidl/Gtest.h>
-#include <map>
-
-namespace android::hardware::identity::test_utils {
-
-using std::endl;
-using std::map;
-using std::optional;
-using std::string;
-using std::vector;
-
-using ::android::sp;
-using ::android::String16;
-using ::android::binder::Status;
-
-using ::keymaster::ASN1_OBJECT_Ptr;
-using ::keymaster::AuthorizationSet;
-using ::keymaster::EVP_PKEY_Ptr;
-using ::keymaster::kAttestionRecordOid;
-using ::keymaster::TAG_ATTESTATION_APPLICATION_ID;
-using ::keymaster::TAG_IDENTITY_CREDENTIAL_KEY;
-using ::keymaster::TAG_INCLUDE_UNIQUE_ID;
-using ::keymaster::TypedTag;
-using ::keymaster::X509_Ptr;
-
-using support::certificateChainSplit;
-
-optional<keymaster_cert_chain_t> AttestationCertificateParser::certificateChainToKeymasterChain(
-        const vector<Certificate>& certificates) {
-    if (certificates.size() <= 0) {
-        return {};
-    }
-
-    keymaster_cert_chain_t kCert;
-    kCert.entry_count = certificates.size();
-    kCert.entries = (keymaster_blob_t*)malloc(sizeof(keymaster_blob_t) * kCert.entry_count);
-
-    int index = 0;
-    for (const auto& c : certificates) {
-        kCert.entries[index].data_length = c.encodedCertificate.size();
-        uint8_t* data = (uint8_t*)malloc(c.encodedCertificate.size());
-
-        memcpy(data, c.encodedCertificate.data(), c.encodedCertificate.size());
-        kCert.entries[index].data = (const uint8_t*)data;
-        index++;
-    }
-
-    return kCert;
-}
-
-bool AttestationCertificateParser::parse() {
-    optional<keymaster_cert_chain_t> cert_chain = certificateChainToKeymasterChain(origCertChain_);
-    if (!cert_chain) {
-        return false;
-    }
-
-    if (cert_chain.value().entry_count < 3) {
-        return false;
-    }
-
-    if (!verifyChain(cert_chain.value())) {
-        return false;
-    }
-
-    if (!verifyAttestationRecord(cert_chain.value().entries[0])) {
-        return false;
-    }
-
-    keymaster_free_cert_chain(&cert_chain.value());
-    return true;
-}
-
-ASN1_OCTET_STRING* AttestationCertificateParser::getAttestationRecord(X509* certificate) {
-    ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1));
-    if (!oid.get()) return nullptr;
-
-    int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1);
-    if (location == -1) return nullptr;
-
-    X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
-    if (!attest_rec_ext) return nullptr;
-
-    ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
-    return attest_rec;
-}
-
-X509* AttestationCertificateParser::parseCertBlob(const keymaster_blob_t& blob) {
-    const uint8_t* p = blob.data;
-    return d2i_X509(nullptr, &p, blob.data_length);
-}
-
-bool AttestationCertificateParser::verifyAttestationRecord(
-        const keymaster_blob_t& attestation_cert) {
-    X509_Ptr cert(parseCertBlob(attestation_cert));
-    if (!cert.get()) {
-        return false;
-    }
-
-    ASN1_OCTET_STRING* attest_rec = getAttestationRecord(cert.get());
-    if (!attest_rec) {
-        return false;
-    }
-
-    keymaster_blob_t att_unique_id = {};
-    keymaster_blob_t att_challenge;
-    keymaster_error_t ret = parse_attestation_record(
-            attest_rec->data, attest_rec->length, &att_attestation_version_,
-            &att_attestation_security_level_, &att_keymaster_version_,
-            &att_keymaster_security_level_, &att_challenge, &att_sw_enforced_, &att_hw_enforced_,
-            &att_unique_id);
-    if (ret) {
-        return false;
-    }
-
-    att_challenge_.assign(att_challenge.data, att_challenge.data + att_challenge.data_length);
-    return true;
-}
-
-uint32_t AttestationCertificateParser::getKeymasterVersion() {
-    return att_keymaster_version_;
-}
-
-uint32_t AttestationCertificateParser::getAttestationVersion() {
-    return att_attestation_version_;
-}
-
-vector<uint8_t> AttestationCertificateParser::getAttestationChallenge() {
-    return att_challenge_;
-}
-
-keymaster_security_level_t AttestationCertificateParser::getKeymasterSecurityLevel() {
-    return att_keymaster_security_level_;
-}
-
-keymaster_security_level_t AttestationCertificateParser::getAttestationSecurityLevel() {
-    return att_attestation_security_level_;
-}
-
-// Verify the Attestation certificates are correctly chained.
-bool AttestationCertificateParser::verifyChain(const keymaster_cert_chain_t& chain) {
-    for (size_t i = 0; i < chain.entry_count - 1; ++i) {
-        keymaster_blob_t& key_cert_blob = chain.entries[i];
-        keymaster_blob_t& signing_cert_blob = chain.entries[i + 1];
-
-        X509_Ptr key_cert(parseCertBlob(key_cert_blob));
-        X509_Ptr signing_cert(parseCertBlob(signing_cert_blob));
-        if (!key_cert.get() || !signing_cert.get()) {
-            return false;
-        }
-
-        EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get()));
-        if (!signing_pubkey.get()) return false;
-
-        if (X509_verify(key_cert.get(), signing_pubkey.get()) != 1) {
-            return false;
-        }
-
-        if (i + 1 == chain.entry_count - 1) {
-            // Last entry is self-signed.
-            if (X509_verify(signing_cert.get(), signing_pubkey.get()) != 1) {
-                return false;
-            }
-        }
-    }
-
-    return true;
-}
-
-}  // namespace android::hardware::identity::test_utils
diff --git a/identity/aidl/vts/VtsAttestationParserSupport.h b/identity/aidl/vts/VtsAttestationParserSupport.h
deleted file mode 100644
index 7c7e1b6..0000000
--- a/identity/aidl/vts/VtsAttestationParserSupport.h
+++ /dev/null
@@ -1,122 +0,0 @@
-
-/*
- * Copyright 2019, 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.
- */
-
-#ifndef VTS_ATTESTATION_PARSER_SUPPORT_H
-#define VTS_ATTESTATION_PARSER_SUPPORT_H
-
-//#include <aidl/Gtest.h>
-#include <android/hardware/identity/IIdentityCredentialStore.h>
-#include <android/hardware/identity/support/IdentityCredentialSupport.h>
-#include <android/hardware/keymaster/4.0/types.h>
-#include <hardware/keymaster_defs.h>
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/authorization_set.h>
-#include <keymaster/contexts/pure_soft_keymaster_context.h>
-#include <keymaster/contexts/soft_attestation_cert.h>
-#include <keymaster/keymaster_tags.h>
-#include <keymaster/km_openssl/attestation_utils.h>
-#include <vector>
-
-namespace android::hardware::identity::test_utils {
-
-using ::std::optional;
-using ::std::string;
-using ::std::vector;
-
-using ::keymaster::AuthorizationSet;
-using ::keymaster::TypedTag;
-
-class AttestationCertificateParser {
-  public:
-    AttestationCertificateParser(const vector<Certificate>& certChain)
-        : origCertChain_(certChain) {}
-
-    bool parse();
-
-    uint32_t getKeymasterVersion();
-    uint32_t getAttestationVersion();
-    vector<uint8_t> getAttestationChallenge();
-    keymaster_security_level_t getKeymasterSecurityLevel();
-    keymaster_security_level_t getAttestationSecurityLevel();
-
-    template <keymaster_tag_t Tag>
-    bool getSwEnforcedBool(TypedTag<KM_BOOL, Tag> tag) {
-        if (att_sw_enforced_.GetTagValue(tag)) {
-            return true;
-        }
-
-        return false;
-    }
-
-    template <keymaster_tag_t Tag>
-    bool getHwEnforcedBool(TypedTag<KM_BOOL, Tag> tag) {
-        if (att_hw_enforced_.GetTagValue(tag)) {
-            return true;
-        }
-
-        return false;
-    }
-
-    template <keymaster_tag_t Tag>
-    optional<vector<uint8_t>> getHwEnforcedBlob(TypedTag<KM_BYTES, Tag> tag) {
-        keymaster_blob_t blob;
-        if (att_hw_enforced_.GetTagValue(tag, &blob)) {
-            return {};
-        }
-
-        vector<uint8_t> ret(blob.data, blob.data + blob.data_length);
-        return ret;
-    }
-
-    template <keymaster_tag_t Tag>
-    optional<vector<uint8_t>> getSwEnforcedBlob(TypedTag<KM_BYTES, Tag> tag) {
-        keymaster_blob_t blob;
-        if (!att_sw_enforced_.GetTagValue(tag, &blob)) {
-            return {};
-        }
-
-        vector<uint8_t> ret(blob.data, blob.data + blob.data_length);
-        return ret;
-    }
-
-  private:
-    // Helper functions.
-    bool verifyChain(const keymaster_cert_chain_t& chain);
-
-    ASN1_OCTET_STRING* getAttestationRecord(X509* certificate);
-
-    X509* parseCertBlob(const keymaster_blob_t& blob);
-
-    bool verifyAttestationRecord(const keymaster_blob_t& attestation_cert);
-
-    optional<keymaster_cert_chain_t> certificateChainToKeymasterChain(
-            const vector<Certificate>& certificates);
-
-    // Private variables.
-    vector<Certificate> origCertChain_;
-    AuthorizationSet att_sw_enforced_;
-    AuthorizationSet att_hw_enforced_;
-    uint32_t att_attestation_version_;
-    uint32_t att_keymaster_version_;
-    keymaster_security_level_t att_attestation_security_level_;
-    keymaster_security_level_t att_keymaster_security_level_;
-    vector<uint8_t> att_challenge_;
-};
-
-}  // namespace android::hardware::identity::test_utils
-
-#endif  // VTS_ATTESTATION_PARSER_SUPPORT_H
diff --git a/identity/aidl/vts/VtsAttestationTests.cpp b/identity/aidl/vts/VtsAttestationTests.cpp
index 673d08b..5529853 100644
--- a/identity/aidl/vts/VtsAttestationTests.cpp
+++ b/identity/aidl/vts/VtsAttestationTests.cpp
@@ -29,7 +29,6 @@
 #include <future>
 #include <map>
 
-#include "VtsAttestationParserSupport.h"
 #include "VtsIdentityTestUtils.h"
 
 namespace android::hardware::identity {
@@ -44,7 +43,6 @@
 using ::android::String16;
 using ::android::binder::Status;
 
-using test_utils::AttestationCertificateParser;
 using test_utils::setupWritableCredential;
 using test_utils::validateAttestationCertificate;
 
@@ -61,38 +59,12 @@
     sp<IIdentityCredentialStore> credentialStore_;
 };
 
-TEST_P(VtsAttestationTests, verifyAttestationWithNonemptyChallengeEmptyId) {
-    Status result;
-
-    HardwareInformation hwInfo;
-    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
-
-    sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
-
-    string challenge = "NotSoRandomChallenge";
-    vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
-    vector<Certificate> attestationCertificate;
-    vector<uint8_t> attestationApplicationId = {};
-
-    result = writableCredential->getAttestationCertificate(
-            attestationApplicationId, attestationChallenge, &attestationCertificate);
-
-    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
-                               << endl;
-
-    EXPECT_TRUE(validateAttestationCertificate(attestationCertificate, attestationChallenge,
-                                               attestationApplicationId, hwInfo));
-}
-
 TEST_P(VtsAttestationTests, verifyAttestationWithNonemptyChallengeNonemptyId) {
     Status result;
 
-    HardwareInformation hwInfo;
-    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
-
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_,
+                                        false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
     vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
@@ -106,18 +78,16 @@
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    EXPECT_TRUE(validateAttestationCertificate(attestationCertificate, attestationChallenge,
-                                               attestationApplicationId, hwInfo));
+    validateAttestationCertificate(attestationCertificate, attestationChallenge,
+                                   attestationApplicationId, false);
 }
 
 TEST_P(VtsAttestationTests, verifyAttestationWithVeryShortChallengeAndId) {
     Status result;
 
-    HardwareInformation hwInfo;
-    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
-
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_,
+                                        false /* testCredential */));
 
     string challenge = "c";
     vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
@@ -131,8 +101,8 @@
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    EXPECT_TRUE(validateAttestationCertificate(attestationCertificate, attestationChallenge,
-                                               attestationApplicationId, hwInfo));
+    validateAttestationCertificate(attestationCertificate, attestationChallenge,
+                                   attestationApplicationId, false);
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VtsAttestationTests);
diff --git a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
index 500b79f..cdecb97 100644
--- a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
+++ b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
@@ -174,16 +174,17 @@
 
     string cborPretty;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    true /* testCredential */));
 
     string challenge = "attestationChallenge";
-    test_utils::AttestationData attData(writableCredential, challenge, {});
+    test_utils::AttestationData attData(writableCredential, challenge,
+                                        {1} /* atteestationApplicationId */);
     ASSERT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
-    EXPECT_TRUE(validateAttestationCertificate(attData.attestationCertificate,
-                                               attData.attestationChallenge,
-                                               attData.attestationApplicationId, hwInfo));
+    validateAttestationCertificate(attData.attestationCertificate, attData.attestationChallenge,
+                                   attData.attestationApplicationId, true);
 
     // This is kinda of a hack but we need to give the size of
     // ProofOfProvisioning that we'll expect to receive.
@@ -368,6 +369,7 @@
     optional<vector<uint8_t>> signingPubKey =
             support::certificateChainGetTopMostKey(signingKeyCertificate.encodedCertificate);
     EXPECT_TRUE(signingPubKey);
+    test_utils::verifyAuthKeyCertificate(signingKeyCertificate.encodedCertificate);
 
     // Since we're using a test-credential we know storageKey meaning we can get the
     // private key. Do this, derive the public key from it, and check this matches what
@@ -418,9 +420,9 @@
     }
 
     vector<uint8_t> mac;
-    vector<uint8_t> deviceNameSpacesBytes;
-    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
-    cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
+    vector<uint8_t> deviceNameSpacesEncoded;
+    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+    cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
     ASSERT_EQ(
             "{\n"
             "  'PersonalData' : {\n"
@@ -435,37 +437,19 @@
             "  },\n"
             "}",
             cborPretty);
-    // The data that is MACed is ["DeviceAuthentication", sessionTranscript, docType,
-    // deviceNameSpacesBytes] so build up that structure
-    cppbor::Array deviceAuthentication;
-    deviceAuthentication.add("DeviceAuthentication");
-    deviceAuthentication.add(sessionTranscript.clone());
 
     string docType = "org.iso.18013-5.2019.mdl";
-    deviceAuthentication.add(docType);
-    deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
-    vector<uint8_t> deviceAuthenticationBytes =
-            cppbor::Semantic(24, deviceAuthentication.encode()).encode();
-    // Derive the key used for MACing.
     optional<vector<uint8_t>> readerEphemeralPrivateKey =
             support::ecKeyPairGetPrivateKey(readerEphemeralKeyPair.value());
-    optional<vector<uint8_t>> sharedSecret =
-            support::ecdh(signingPubKey.value(), readerEphemeralPrivateKey.value());
-    ASSERT_TRUE(sharedSecret);
-    // Mix-in SessionTranscriptBytes
-    vector<uint8_t> sessionTranscriptBytes =
-            cppbor::Semantic(24, sessionTranscript.encode()).encode();
-    vector<uint8_t> sharedSecretWithSessionTranscriptBytes = sharedSecret.value();
-    std::copy(sessionTranscriptBytes.begin(), sessionTranscriptBytes.end(),
-              std::back_inserter(sharedSecretWithSessionTranscriptBytes));
-    vector<uint8_t> salt = {0x00};
-    vector<uint8_t> info = {};
-    optional<vector<uint8_t>> derivedKey =
-            support::hkdf(sharedSecretWithSessionTranscriptBytes, salt, info, 32);
-    ASSERT_TRUE(derivedKey);
+    optional<vector<uint8_t>> eMacKey = support::calcEMacKey(
+            readerEphemeralPrivateKey.value(),                           // Private Key
+            signingPubKey.value(),                                       // Public Key
+            cppbor::Semantic(24, sessionTranscript.encode()).encode());  // SessionTranscriptBytes
     optional<vector<uint8_t>> calculatedMac =
-            support::coseMac0(derivedKey.value(), {},      // payload
-                              deviceAuthenticationBytes);  // detached content
+            support::calcMac(sessionTranscript.encode(),  // SessionTranscript
+                             docType,                     // DocType
+                             deviceNameSpacesEncoded,     // DeviceNamespaces
+                             eMacKey.value());            // EMacKey
     ASSERT_TRUE(calculatedMac);
     EXPECT_EQ(mac, calculatedMac);
 
@@ -480,18 +464,14 @@
                                 signingKeyBlob, sessionTranscriptEncoded, {},  // readerSignature,
                                 testEntriesEntryCounts)
                         .isOk());
-    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
-    cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
+    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+    cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
     ASSERT_EQ("{}", cborPretty);
     // Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
-    deviceAuthentication = cppbor::Array();
-    deviceAuthentication.add("DeviceAuthentication");
-    deviceAuthentication.add(sessionTranscript.clone());
-    deviceAuthentication.add(docType);
-    deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
-    deviceAuthenticationBytes = cppbor::Semantic(24, deviceAuthentication.encode()).encode();
-    calculatedMac = support::coseMac0(derivedKey.value(), {},      // payload
-                                      deviceAuthenticationBytes);  // detached content
+    calculatedMac = support::calcMac(sessionTranscript.encode(),  // SessionTranscript
+                                     docType,                     // DocType
+                                     deviceNameSpacesEncoded,     // DeviceNamespaces
+                                     eMacKey.value());            // EMacKey
     ASSERT_TRUE(calculatedMac);
     EXPECT_EQ(mac, calculatedMac);
 
@@ -506,18 +486,14 @@
                                 signingKeyBlob, sessionTranscriptEncoded, {},  // readerSignature,
                                 testEntriesEntryCounts)
                         .isOk());
-    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
-    cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
+    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+    cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
     ASSERT_EQ("{}", cborPretty);
     // Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
-    deviceAuthentication = cppbor::Array();
-    deviceAuthentication.add("DeviceAuthentication");
-    deviceAuthentication.add(sessionTranscript.clone());
-    deviceAuthentication.add(docType);
-    deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
-    deviceAuthenticationBytes = cppbor::Semantic(24, deviceAuthentication.encode()).encode();
-    calculatedMac = support::coseMac0(derivedKey.value(), {},      // payload
-                                      deviceAuthenticationBytes);  // detached content
+    calculatedMac = support::calcMac(sessionTranscript.encode(),  // SessionTranscript
+                                     docType,                     // DocType
+                                     deviceNameSpacesEncoded,     // DeviceNamespaces
+                                     eMacKey.value());            // EMacKey
     ASSERT_TRUE(calculatedMac);
     EXPECT_EQ(mac, calculatedMac);
 }
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index 8c35952..56e17ba 100644
--- a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -61,7 +61,8 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     vector<uint8_t> attestationChallenge;
     vector<Certificate> attestationCertificate;
@@ -82,12 +83,13 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
     vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
     vector<Certificate> attestationCertificate;
-    vector<uint8_t> attestationApplicationId = {};
+    vector<uint8_t> attestationApplicationId = {1};
 
     result = writableCredential->getAttestationCertificate(
             attestationApplicationId, attestationChallenge, &attestationCertificate);
@@ -95,27 +97,27 @@
     EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    EXPECT_TRUE(test_utils::validateAttestationCertificate(
-            attestationCertificate, attestationChallenge, attestationApplicationId, hwInfo));
+    test_utils::validateAttestationCertificate(attestationCertificate, attestationChallenge,
+                                               attestationApplicationId, false);
 }
 
 TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
     Status result;
 
-    HardwareInformation hwInfo;
-    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
-
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge1";
-    test_utils::AttestationData attData(writableCredential, challenge, {});
-    ASSERT_TRUE(test_utils::validateAttestationCertificate(
-            attData.attestationCertificate, attData.attestationChallenge,
-            attData.attestationApplicationId, hwInfo));
+    test_utils::AttestationData attData(writableCredential, challenge,
+                                        {1} /* atteestationApplicationId */);
+    test_utils::validateAttestationCertificate(attData.attestationCertificate,
+                                               attData.attestationChallenge,
+                                               attData.attestationApplicationId, false);
 
     string challenge2 = "NotSoRandomChallenge2";
-    test_utils::AttestationData attData2(writableCredential, challenge2, {});
+    test_utils::AttestationData attData2(writableCredential, challenge2,
+                                         {} /* atteestationApplicationId */);
     EXPECT_FALSE(attData2.result.isOk()) << attData2.result.exceptionCode() << "; "
                                          << attData2.result.exceptionMessage() << endl;
     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, attData2.result.exceptionCode());
@@ -125,7 +127,8 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalization) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     // First call should go through
     const vector<int32_t> entryCounts = {2, 4};
@@ -147,7 +150,8 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationMin) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     // Verify minimal number of profile count and entry count
     const vector<int32_t> entryCounts = {1, 1};
@@ -160,7 +164,8 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationOne) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     // Verify minimal number of profile count and entry count
     const vector<int32_t> entryCounts = {1};
@@ -173,7 +178,8 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationLarge) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     // Verify set a large number of profile count and entry count is ok
     const vector<int32_t> entryCounts = {3000};
@@ -186,7 +192,8 @@
 TEST_P(IdentityCredentialTests, verifyProfileNumberMismatchShouldFail) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     // Enter mismatched entry and profile numbers
     const vector<int32_t> entryCounts = {5, 6};
@@ -224,7 +231,8 @@
 TEST_P(IdentityCredentialTests, verifyDuplicateProfileId) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     const vector<int32_t> entryCounts = {3, 6};
     writableCredential->setExpectedProofOfProvisioningSize(123456);
@@ -283,10 +291,12 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge1";
-    test_utils::AttestationData attData(writableCredential, challenge, {});
+    test_utils::AttestationData attData(writableCredential, challenge,
+                                        {} /* atteestationApplicationId */);
     EXPECT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
@@ -294,7 +304,7 @@
     ASSERT_TRUE(readerCertificate1);
 
     const vector<int32_t> entryCounts = {1u};
-    size_t expectedPoPSize = 186 + readerCertificate1.value().size();
+    size_t expectedPoPSize = 185 + readerCertificate1.value().size();
     // OK to fail, not available in v1 HAL
     writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
     result = writableCredential->startPersonalization(1, entryCounts);
@@ -308,7 +318,7 @@
     ASSERT_TRUE(secureProfiles);
 
     const vector<test_utils::TestEntryData> testEntries1 = {
-            {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
+            {"Name Space", "Last name", string("Turing"), vector<int32_t>{1}},
     };
 
     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
@@ -347,11 +357,11 @@
             "      {\n"
             "        'name' : 'Last name',\n"
             "        'value' : 'Turing',\n"
-            "        'accessControlProfiles' : [0, 1, ],\n"
+            "        'accessControlProfiles' : [1, ],\n"
             "      },\n"
             "    ],\n"
             "  },\n"
-            "  true,\n"
+            "  false,\n"
             "]",
             cborPretty);
 
@@ -370,10 +380,12 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge";
-    test_utils::AttestationData attData(writableCredential, challenge, {});
+    test_utils::AttestationData attData(writableCredential, challenge,
+                                        {} /* atteestationApplicationId */);
     EXPECT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
@@ -510,7 +522,7 @@
             "      },\n"
             "    ],\n"
             "  },\n"
-            "  true,\n"
+            "  false,\n"
             "]",
             cborPretty);
 
@@ -529,10 +541,12 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge";
-    test_utils::AttestationData attData(writableCredential, challenge, {});
+    test_utils::AttestationData attData(writableCredential, challenge,
+                                        {} /* atteestationApplicationId */);
     ASSERT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
@@ -591,10 +605,12 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge";
-    test_utils::AttestationData attData(writableCredential, challenge, {});
+    test_utils::AttestationData attData(writableCredential, challenge,
+                                        {} /* atteestationApplicationId */);
     ASSERT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
@@ -667,7 +683,8 @@
 
 TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     const vector<int32_t> entryCounts = {1};
     writableCredential->setExpectedProofOfProvisioningSize(123456);
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.cpp b/identity/aidl/vts/VtsIdentityTestUtils.cpp
index b6ed80f..3b10651 100644
--- a/identity/aidl/vts/VtsIdentityTestUtils.cpp
+++ b/identity/aidl/vts/VtsIdentityTestUtils.cpp
@@ -14,13 +14,17 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "VtsIdentityTestUtils"
+
 #include "VtsIdentityTestUtils.h"
 
 #include <aidl/Gtest.h>
+#include <android-base/logging.h>
+#include <keymaster/km_openssl/openssl_utils.h>
+#include <keymasterV4_1/attestation_record.h>
+#include <charconv>
 #include <map>
 
-#include "VtsAttestationParserSupport.h"
-
 namespace android::hardware::identity::test_utils {
 
 using std::endl;
@@ -32,15 +36,15 @@
 using ::android::sp;
 using ::android::String16;
 using ::android::binder::Status;
+using ::keymaster::X509_Ptr;
 
 bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
-                             sp<IIdentityCredentialStore>& credentialStore) {
+                             sp<IIdentityCredentialStore>& credentialStore, bool testCredential) {
     if (credentialStore == nullptr) {
         return false;
     }
 
     string docType = "org.iso.18013-5.2019.mdl";
-    bool testCredential = true;
     Status result = credentialStore->createCredential(docType, testCredential, &writableCredential);
 
     if (result.isOk() && writableCredential != nullptr) {
@@ -178,63 +182,269 @@
     }
 }
 
-bool validateAttestationCertificate(const vector<Certificate>& inputCertificates,
-                                    const vector<uint8_t>& expectedChallenge,
-                                    const vector<uint8_t>& expectedAppId,
-                                    const HardwareInformation& hwInfo) {
-    AttestationCertificateParser certParser_(inputCertificates);
-    bool ret = certParser_.parse();
-    EXPECT_TRUE(ret);
-    if (!ret) {
+string x509NameToRfc2253String(X509_NAME* name) {
+    char* buf;
+    size_t bufSize;
+    BIO* bio;
+
+    bio = BIO_new(BIO_s_mem());
+    X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253);
+    bufSize = BIO_get_mem_data(bio, &buf);
+    string ret = string(buf, bufSize);
+    BIO_free(bio);
+
+    return ret;
+}
+
+int parseDigits(const char** s, int numDigits) {
+    int result;
+    auto [_, ec] = std::from_chars(*s, *s + numDigits, result);
+    if (ec != std::errc()) {
+        LOG(ERROR) << "Error parsing " << numDigits << " digits "
+                   << " from " << s;
+        return 0;
+    }
+    *s += numDigits;
+    return result;
+}
+
+bool parseAsn1Time(const ASN1_TIME* asn1Time, time_t* outTime) {
+    struct tm tm;
+
+    memset(&tm, '\0', sizeof(tm));
+    const char* timeStr = (const char*)asn1Time->data;
+    const char* s = timeStr;
+    if (asn1Time->type == V_ASN1_UTCTIME) {
+        tm.tm_year = parseDigits(&s, 2);
+        if (tm.tm_year < 70) {
+            tm.tm_year += 100;
+        }
+    } else if (asn1Time->type == V_ASN1_GENERALIZEDTIME) {
+        tm.tm_year = parseDigits(&s, 4) - 1900;
+        tm.tm_year -= 1900;
+    } else {
+        LOG(ERROR) << "Unsupported ASN1_TIME type " << asn1Time->type;
+        return false;
+    }
+    tm.tm_mon = parseDigits(&s, 2) - 1;
+    tm.tm_mday = parseDigits(&s, 2);
+    tm.tm_hour = parseDigits(&s, 2);
+    tm.tm_min = parseDigits(&s, 2);
+    tm.tm_sec = parseDigits(&s, 2);
+    // This may need to be updated if someone create certificates using +/- instead of Z.
+    //
+    if (*s != 'Z') {
+        LOG(ERROR) << "Expected Z in string '" << timeStr << "' at offset " << (s - timeStr);
         return false;
     }
 
-    // As per the IC HAL, the version of the Identity
-    // Credential HAL is 1.0 - and this is encoded as major*10 + minor. This field is used by
-    // Keymaster which is known to report integers less than or equal to 4 (for KM up to 4.0)
-    // and integers greater or equal than 41 (for KM starting with 4.1).
-    //
-    // Since we won't get to version 4.0 of the IC HAL for a while, let's also check that a KM
-    // version isn't errornously returned.
-    EXPECT_LE(10, certParser_.getKeymasterVersion());
-    EXPECT_GT(40, certParser_.getKeymasterVersion());
-    EXPECT_LE(3, certParser_.getAttestationVersion());
-
-    // Verify the app id matches to whatever we set it to be.
-    optional<vector<uint8_t>> appId =
-            certParser_.getSwEnforcedBlob(::keymaster::TAG_ATTESTATION_APPLICATION_ID);
-    if (appId) {
-        EXPECT_EQ(expectedAppId.size(), appId.value().size());
-        EXPECT_EQ(0, memcmp(expectedAppId.data(), appId.value().data(), expectedAppId.size()));
-    } else {
-        // app id not found
-        EXPECT_EQ(0, expectedAppId.size());
+    time_t t = timegm(&tm);
+    if (t == -1) {
+        LOG(ERROR) << "Error converting broken-down time to time_t";
+        return false;
     }
-
-    EXPECT_TRUE(certParser_.getHwEnforcedBool(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY));
-    EXPECT_FALSE(certParser_.getHwEnforcedBool(::keymaster::TAG_INCLUDE_UNIQUE_ID));
-
-    // Verify the challenge always matches in size and data of what is passed
-    // in.
-    vector<uint8_t> attChallenge = certParser_.getAttestationChallenge();
-    EXPECT_EQ(expectedChallenge.size(), attChallenge.size());
-    EXPECT_EQ(0, memcmp(expectedChallenge.data(), attChallenge.data(), expectedChallenge.size()));
-
-    // Ensure the attestation conveys that it's implemented in secure hardware (with carve-out
-    // for the reference implementation which cannot be implemented in secure hardware).
-    if (hwInfo.credentialStoreName == "Identity Credential Reference Implementation" &&
-        hwInfo.credentialStoreAuthorName == "Google") {
-        EXPECT_LE(KM_SECURITY_LEVEL_SOFTWARE, certParser_.getKeymasterSecurityLevel());
-        EXPECT_LE(KM_SECURITY_LEVEL_SOFTWARE, certParser_.getAttestationSecurityLevel());
-
-    } else {
-        // Actual devices should use TrustedEnvironment or StrongBox.
-        EXPECT_LE(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT, certParser_.getKeymasterSecurityLevel());
-        EXPECT_LE(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT, certParser_.getAttestationSecurityLevel());
-    }
+    *outTime = t;
     return true;
 }
 
+void validateAttestationCertificate(const vector<Certificate>& credentialKeyCertChain,
+                                    const vector<uint8_t>& expectedChallenge,
+                                    const vector<uint8_t>& expectedAppId, bool isTestCredential) {
+    ASSERT_GE(credentialKeyCertChain.size(), 2);
+
+    vector<uint8_t> certBytes = credentialKeyCertChain[0].encodedCertificate;
+    const uint8_t* certData = certBytes.data();
+    X509_Ptr cert = X509_Ptr(d2i_X509(nullptr, &certData, certBytes.size()));
+
+    vector<uint8_t> batchCertBytes = credentialKeyCertChain[1].encodedCertificate;
+    const uint8_t* batchCertData = batchCertBytes.data();
+    X509_Ptr batchCert = X509_Ptr(d2i_X509(nullptr, &batchCertData, batchCertBytes.size()));
+
+    // First get some values from the batch certificate which is checked
+    // against the top-level certificate (subject, notAfter)
+    //
+
+    X509_NAME* batchSubject = X509_get_subject_name(batchCert.get());
+    ASSERT_NE(nullptr, batchSubject);
+    time_t batchNotAfter;
+    ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(batchCert.get()), &batchNotAfter));
+
+    // Check all the requirements from IWritableIdentityCredential::getAttestationCertificate()...
+    //
+
+    //  - version: INTEGER 2 (means v3 certificate).
+    EXPECT_EQ(2, X509_get_version(cert.get()));
+
+    //  - serialNumber: INTEGER 1 (fixed value: same on all certs).
+    EXPECT_EQ(1, ASN1_INTEGER_get(X509_get_serialNumber(cert.get())));
+
+    //  - signature: must be set to ECDSA.
+    EXPECT_EQ(NID_ecdsa_with_SHA256, X509_get_signature_nid(cert.get()));
+
+    //  - subject: CN shall be set to "Android Identity Credential Key". (fixed value:
+    //    same on all certs)
+    X509_NAME* subject = X509_get_subject_name(cert.get());
+    ASSERT_NE(nullptr, subject);
+    EXPECT_EQ("CN=Android Identity Credential Key", x509NameToRfc2253String(subject));
+
+    //  - issuer: Same as the subject field of the batch attestation key.
+    X509_NAME* issuer = X509_get_issuer_name(cert.get());
+    ASSERT_NE(nullptr, issuer);
+    EXPECT_EQ(x509NameToRfc2253String(batchSubject), x509NameToRfc2253String(issuer));
+
+    //  - validity: Should be from current time and expire at the same time as the
+    //    attestation batch certificate used.
+    //
+    //  Allow for 10 seconds drift to account for the time drift between Secure HW
+    //  and this environment plus the difference between when the certificate was
+    //  created and until now
+    //
+    time_t notBefore;
+    ASSERT_TRUE(parseAsn1Time(X509_get0_notBefore(cert.get()), &notBefore));
+    uint64_t now = time(nullptr);
+    int64_t diffSecs = now - notBefore;
+    int64_t allowDriftSecs = 10;
+    EXPECT_LE(-allowDriftSecs, diffSecs);
+    EXPECT_GE(allowDriftSecs, diffSecs);
+
+    time_t notAfter;
+    ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(cert.get()), &notAfter));
+    EXPECT_EQ(notAfter, batchNotAfter);
+
+    auto [err, attRec] = keymaster::V4_1::parse_attestation_record(certBytes);
+    ASSERT_EQ(keymaster::V4_1::ErrorCode::OK, err);
+
+    //  - subjectPublicKeyInfo: must contain attested public key.
+
+    //  - The attestationVersion field in the attestation extension must be at least 3.
+    EXPECT_GE(attRec.attestation_version, 3);
+
+    //  - The attestationSecurityLevel field must be set to either Software (0),
+    //    TrustedEnvironment (1), or StrongBox (2) depending on how attestation is
+    //    implemented.
+    EXPECT_GE(attRec.attestation_security_level,
+              keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
+
+    //  - The keymasterVersion field in the attestation extension must be set to the.
+    //    same value as used for Android Keystore keys.
+    //
+    // Nothing to check here...
+
+    //  - 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.
+    EXPECT_GE(attRec.keymaster_security_level, keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
+
+    //  - The attestationChallenge field must be set to the passed-in challenge.
+    EXPECT_EQ(expectedChallenge.size(), attRec.attestation_challenge.size());
+    EXPECT_TRUE(memcmp(expectedChallenge.data(), attRec.attestation_challenge.data(),
+                       attRec.attestation_challenge.size()) == 0);
+
+    //  - The uniqueId field must be empty.
+    EXPECT_EQ(attRec.unique_id.size(), 0);
+
+    //  - 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.
+    EXPECT_TRUE(attRec.software_enforced.Contains(keymaster::V4_0::TAG_ATTESTATION_APPLICATION_ID,
+                                                  expectedAppId));
+
+    //  - The teeEnforced field in the attestation extension must include
+    //
+    //    - Tag::IDENTITY_CREDENTIAL_KEY which 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). This must not be set
+    //      for test credentials.
+    bool hasIcKeyTag =
+            attRec.hardware_enforced.Contains(static_cast<android::hardware::keymaster::V4_0::Tag>(
+                    keymaster::V4_1::Tag::IDENTITY_CREDENTIAL_KEY));
+    if (isTestCredential) {
+        EXPECT_FALSE(hasIcKeyTag);
+    } else {
+        EXPECT_TRUE(hasIcKeyTag);
+    }
+
+    //    - Tag::PURPOSE must be set to SIGN
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_PURPOSE,
+                                                  keymaster::V4_0::KeyPurpose::SIGN));
+
+    //    - Tag::KEY_SIZE must be set to the appropriate key size, in bits (e.g. 256)
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_KEY_SIZE, 256));
+
+    //    - Tag::ALGORITHM must be set to EC
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_ALGORITHM,
+                                                  keymaster::V4_0::Algorithm::EC));
+
+    //    - Tag::NO_AUTH_REQUIRED must be set
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_NO_AUTH_REQUIRED));
+
+    //    - Tag::DIGEST must be include SHA_2_256
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_DIGEST,
+                                                  keymaster::V4_0::Digest::SHA_2_256));
+
+    //    - Tag::EC_CURVE must be set to P_256
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_EC_CURVE,
+                                                  keymaster::V4_0::EcCurve::P_256));
+
+    //    - Tag::ROOT_OF_TRUST must be set
+    //
+    EXPECT_GE(attRec.root_of_trust.security_level,
+              keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
+
+    //    - Tag::OS_VERSION and Tag::OS_PATCHLEVEL must be set
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_OS_VERSION));
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_OS_PATCHLEVEL));
+
+    // TODO: we could retrieve osVersion and osPatchLevel from Android itself and compare it
+    // with what was reported in the certificate.
+}
+
+void verifyAuthKeyCertificate(const vector<uint8_t>& authKeyCertChain) {
+    const uint8_t* data = authKeyCertChain.data();
+    auto cert = X509_Ptr(d2i_X509(nullptr, &data, authKeyCertChain.size()));
+
+    //  - version: INTEGER 2 (means v3 certificate).
+    EXPECT_EQ(X509_get_version(cert.get()), 2);
+
+    //  - serialNumber: INTEGER 1 (fixed value: same on all certs).
+    EXPECT_EQ(ASN1_INTEGER_get(X509_get_serialNumber(cert.get())), 1);
+
+    //  - signature: must be set to ECDSA.
+    EXPECT_EQ(X509_get_signature_nid(cert.get()), NID_ecdsa_with_SHA256);
+
+    //  - subject: CN shall be set to "Android Identity Credential Authentication Key". (fixed
+    //    value: same on all certs)
+    X509_NAME* subject = X509_get_subject_name(cert.get());
+    ASSERT_NE(subject, nullptr);
+    EXPECT_EQ(x509NameToRfc2253String(subject),
+              "CN=Android Identity Credential Authentication Key");
+
+    //  - issuer: CN shall be set to "Android Identity Credential Key". (fixed value:
+    //    same on all certs)
+    X509_NAME* issuer = X509_get_issuer_name(cert.get());
+    ASSERT_NE(issuer, nullptr);
+    EXPECT_EQ(x509NameToRfc2253String(issuer), "CN=Android Identity Credential Key");
+
+    //  - subjectPublicKeyInfo: must contain attested public key.
+
+    //  - validity: should be from current time and one year in the future (365 days).
+    time_t notBefore, notAfter;
+    ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(cert.get()), &notAfter));
+    ASSERT_TRUE(parseAsn1Time(X509_get0_notBefore(cert.get()), &notBefore));
+
+    //  Allow for 10 seconds drift to account for the time drift between Secure HW
+    //  and this environment plus the difference between when the certificate was
+    //  created and until now
+    //
+    uint64_t now = time(nullptr);
+    int64_t diffSecs = now - notBefore;
+    int64_t allowDriftSecs = 10;
+    EXPECT_LE(-allowDriftSecs, diffSecs);
+    EXPECT_GE(allowDriftSecs, diffSecs);
+    constexpr uint64_t kSecsInOneYear = 365 * 24 * 60 * 60;
+    EXPECT_EQ(notBefore + kSecsInOneYear, notAfter);
+}
+
 vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries) {
     vector<RequestNamespace> ret;
     RequestNamespace curNs;
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.h b/identity/aidl/vts/VtsIdentityTestUtils.h
index 673b736..85c24f8 100644
--- a/identity/aidl/vts/VtsIdentityTestUtils.h
+++ b/identity/aidl/vts/VtsIdentityTestUtils.h
@@ -34,8 +34,8 @@
 
 struct AttestationData {
     AttestationData(sp<IWritableIdentityCredential>& writableCredential, string challenge,
-                    vector<uint8_t> applicationId)
-        : attestationApplicationId(applicationId) {
+                    vector<uint8_t> attestationAppId)
+        : attestationApplicationId(attestationAppId) {
         // ASSERT_NE(writableCredential, nullptr);
 
         if (!challenge.empty()) {
@@ -94,7 +94,7 @@
 };
 
 bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
-                             sp<IIdentityCredentialStore>& credentialStore);
+                             sp<IIdentityCredentialStore>& credentialStore, bool testCredential);
 
 optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal);
 
@@ -111,13 +111,17 @@
 
 void setImageData(vector<uint8_t>& image);
 
-bool validateAttestationCertificate(const vector<Certificate>& inputCertificates,
+void validateAttestationCertificate(const vector<Certificate>& credentialKeyCertChain,
                                     const vector<uint8_t>& expectedChallenge,
-                                    const vector<uint8_t>& expectedAppId,
-                                    const HardwareInformation& hwInfo);
+                                    const vector<uint8_t>& expectedAppId, bool isTestCredential);
 
 vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries);
 
+// Verifies that the X.509 certificate for a just created authentication key
+// is valid.
+//
+void verifyAuthKeyCertificate(const vector<uint8_t>& authKeyCertChain);
+
 }  // namespace android::hardware::identity::test_utils
 
 #endif  // VTS_IDENTITY_TEST_UTILS_H