Merge "Add INFO_VIN to DefaultProperties.json for CTS tests"
diff --git a/dumpstate/aidl/Android.bp b/dumpstate/aidl/Android.bp
index 63670bb..1eb8b32 100644
--- a/dumpstate/aidl/Android.bp
+++ b/dumpstate/aidl/Android.bp
@@ -31,7 +31,8 @@
             enabled: false,
         },
         java: {
-            enabled: false,
+            enabled: true,
+            sdk_version: "module_current",
         },
     },
     versions_with_info: [
diff --git a/identity/aidl/Android.bp b/identity/aidl/Android.bp
index f6855e8..57451ed 100644
--- a/identity/aidl/Android.bp
+++ b/identity/aidl/Android.bp
@@ -59,3 +59,27 @@
     ],
 
 }
+
+// cc_defaults that includes the latest Identity AIDL library.
+// Modules that depend on Identity directly can include this cc_defaults to
+// avoid managing dependency versions explicitly.
+cc_defaults {
+    name: "identity_use_latest_hal_aidl_ndk_static",
+    static_libs: [
+        "android.hardware.identity-V4-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "identity_use_latest_hal_aidl_ndk_shared",
+    shared_libs: [
+        "android.hardware.identity-V4-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "identity_use_latest_hal_aidl_cpp_static",
+    static_libs: [
+        "android.hardware.identity-V4-cpp",
+    ],
+}
diff --git a/security/keymint/RKP_CHANGELOG.md b/security/keymint/RKP_CHANGELOG.md
index 67d68d4..dfcc938 100644
--- a/security/keymint/RKP_CHANGELOG.md
+++ b/security/keymint/RKP_CHANGELOG.md
@@ -6,13 +6,28 @@
 ## Releases
 * **Android S (12):** IRemotelyProvisionedComponent v1
 * **Android T (13):** IRemotelyProvisionedComponent v2
+* **Android U (14):** IRemotelyProvisionedComponent v3
 
 ## IRemotelyProvisionedComponent 1 -> 2
 * DeviceInfo
- * Most entries are no longer optional.
- * `att_id_state` is now `fused`. `fused` is used to indicate if SecureBoot is enabled.
- * `version` is now `2`.
- * `board` has been removed.
- * `device` has been added.
+  * Most entries are no longer optional.
+  * `att_id_state` is now `fused`. `fused` is used to indicate if SecureBoot is enabled.
+  * `version` is now `2`.
+  * `board` has been removed.
+  * `device` has been added.
 * RpcHardwareInfo
- * `uniqueId` String added as a field in order to differentiate IRPC instances on device.
\ No newline at end of file
+  * `uniqueId` String added as a field in order to differentiate IRPC instances on device.
+
+## IRemotelyProvisionedComponent 2 -> 3
+* ProtectedData has been removed.
+* DeviceInfo
+  * `cert_type` has been added, with values corresponding to `widevine` or `keymint`
+  * `version` has moved to a top-level field within the CSR generated by the HAL
+* IRemotelyProvisionedComponent
+  * The need for an EEK has been removed. There is no longer an encrypted portion of the CSR.
+  * Test mode has been removed.
+  * The schema for the CSR itself has been significantly simplified, please see
+    IRemotelyProvisionedComponent.aidl for more details.
+    * Notably, the chain of signing, MACing, and encryption operations has been replaced with a single
+      COSE_Sign1 object.
+
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index f566462..626ece8 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -38,9 +38,11 @@
   android.hardware.security.keymint.RpcHardwareInfo getHardwareInfo();
   byte[] generateEcdsaP256KeyPair(in boolean testMode, out android.hardware.security.keymint.MacedPublicKey macedPublicKey);
   byte[] generateCertificateRequest(in boolean testMode, in android.hardware.security.keymint.MacedPublicKey[] keysToSign, in byte[] endpointEncryptionCertChain, in byte[] challenge, out android.hardware.security.keymint.DeviceInfo deviceInfo, out android.hardware.security.keymint.ProtectedData protectedData);
+  byte[] generateCertificateRequestV2(in android.hardware.security.keymint.MacedPublicKey[] keysToSign, in byte[] challenge);
   const int STATUS_FAILED = 1;
   const int STATUS_INVALID_MAC = 2;
   const int STATUS_PRODUCTION_KEY_IN_TEST_REQUEST = 3;
   const int STATUS_TEST_KEY_IN_PRODUCTION_REQUEST = 4;
   const int STATUS_INVALID_EEK = 5;
+  const int STATUS_REMOVED = 6;
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
index abb2a7b..6954d65 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -37,19 +37,19 @@
      *         "product" : tstr,
      *         "model" : tstr,
      *         "device" : tstr,
-     *         "vb_state" : "green" / "yellow" / "orange",    // Taken from the AVB values
-     *         "bootloader_state" : "locked" / "unlocked",    // Taken from the AVB values
-     *         "vbmeta_digest": bstr,                         // Taken from the AVB values
-     *         ? "os_version" : tstr,                         // Same as
-     *                                                        // android.os.Build.VERSION.release
-     *                                                        // Not optional for TEE.
-     *         "system_patch_level" : uint,                   // YYYYMMDD
-     *         "boot_patch_level" : uint,                     // YYYYMMDD
-     *         "vendor_patch_level" : uint,                   // YYYYMMDD
-     *         "version" : 2,                                 // The CDDL schema version.
+     *         "vb_state" : "green" / "yellow" / "orange",    ; Taken from the AVB values
+     *         "bootloader_state" : "locked" / "unlocked",    ; Taken from the AVB values
+     *         "vbmeta_digest": bstr,                         ; Taken from the AVB values
+     *         ? "os_version" : tstr,                         ; Same as
+     *                                                        ; android.os.Build.VERSION.release
+     *                                                        ; Not optional for TEE.
+     *         "system_patch_level" : uint,                   ; YYYYMMDD
+     *         "boot_patch_level" : uint,                     ; YYYYMMDD
+     *         "vendor_patch_level" : uint,                   ; YYYYMMDD
      *         "security_level" : "tee" / "strongbox",
-     *         "fused": 1 / 0,  // 1 if secure boot is enforced for the processor that the IRPC
-     *                          // implementation is contained in. 0 otherwise.
+     *         "fused": 1 / 0,  ; 1 if secure boot is enforced for the processor that the IRPC
+     *                          ; implementation is contained in. 0 otherwise.
+     *         "cert_type": "widevine" / "keymint"
      *     }
      */
     byte[] deviceInfo;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index a29fb08..c2acbed 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -31,26 +31,31 @@
  * This interface does not provide any way to use the generated and certified key pairs. It's
  * intended to be implemented by a HAL service that does other things with keys (e.g. Keymint).
  *
- * The root of trust for secure provisioning is something called the "Boot Certificate Chain", or
- * BCC. The BCC is a chain of public key certificates, represented as COSE_Sign1 objects containing
- * COSE_Key representations of the public keys. The "root" of the BCC is
- * a device-unique public key, denoted DK_pub. All public keys in the BCC are device-unique. The
- * public key from each certificate in the chain is used to sign the next certificate in the
- * chain. The final, "leaf" certificate contains a public key, denoted KM_pub, whose corresponding
- * private key, denoted KM_priv, is available for use by the IRemotelyProvisionedComponent.
+ * The root of trust for secure provisioning is something called the Device Identifier Composition
+ * Engine (DICE) Chain. The DICE Chain is a chain of certificates, represented as COSE_Sign1 objects
+ * containing CBOR Web Tokens (CWT) which have descriptions about the stage of firmware being
+ * signed, including a COSE_Key representation of that stage's public key.
  *
- * BCC Design
- * ==========
+ * DICE Chain Design
+ * =================
  *
- * The BCC is designed to mirror the boot stages of a device, and to prove the content and integrity
- * of each firmware image. In a proper BCC, each boot stage hashes its own private key with the code
- * and any relevant configuration parameters of the next stage to produce a key pair for the next
- * stage. Each stage also uses its own private key to sign the public key of the next stage,
- * including in the certificate the hash of the next firmware stage, then loads the next stage,
- * passing the private key and certificate to it in a manner that does not leak the private key to
- * later boot stages. The BCC root key pair is generated by immutable code (e.g. ROM), from a
- * device-unique secret. After the device-unique secret is used, it must be made unavailable to any
- * later boot stage.
+ * For a more exhaustive and thorough look at DICE and the implementation used within this protocol,
+ * please see: https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md
+ *
+ * The DICE Chain is designed to mirror the boot stages of a device, and to prove the content and
+ * integrity of each firmware image. In a proper DICE Chain, each boot stage hashes its own private
+ * key material with the code and any relevant configuration parameters of the next stage to produce
+ * a Compound Device Identifier, or CDI, which is used as the secret key material for the next
+ * stage. From the CDI, a key pair - CDI_*_Pub and CDI_*_Priv - is derived and certified for the
+ * next stage by the current stages CDI_*_Priv. The next stage is then loaded and given its CDI and
+ * the DICE certificate chain generated so far in a manner that does not leak the previous stage's
+ * CDI_*_Priv or CDI to later boot stages. The final, "leaf" CDI certificate contains a public key,
+ * denoted CDI_Leaf_Pub, whose corresponding private key, denoted CDI_Leaf_Priv, is available for
+ * use by the IRemotelyProvisionedComponent.
+ *
+ * The root keypair is generated by immutable code (e.g. ROM), from a Unique Device Secret (UDS).
+ * The keypair that is generated from it can be referred to as the UDS_Pub/UDS_Priv keys. After the
+ * device-unique secret is used, it must be made unavailable to any later boot stage.
  *
  * In this way, booting the device incrementally builds a certificate chain that (a) identifies and
  * validates the integrity of every stage and (b) contains a set of public keys that correspond to
@@ -58,64 +63,64 @@
  * (given the necessary input), but no stage can compute the secret of any preceding stage. Updating
  * the firmware or configuration of any stage changes the key pair of that stage, and of all
  * subsequent stages, and no attacker who compromised the previous version of the updated firmware
- * can know or predict the post-update key pairs. It is recommended and expected that the BCC is
- * constructed using the Open Profile for DICE.
+ * can know or predict the post-update key pairs. It is recommended and expected that the DICE Chain
+ * is constructed using the Open Profile for DICE.
  *
- * When the provisioning server receives a message signed by KM_priv and containing a BCC that
- * chains from DK_pub to KM_pub, it can be certain that (barring vulnerabilities in some boot
- * stage), the CertificateRequest came from the device associated with DK_pub, running the specific
- * software identified by the certificates in the BCC. If the server has some mechanism for knowing
- * which the DK_pub values of "valid" devices, it can determine whether signing certificates is
- * appropriate.
+ * When the provisioning server receives a message signed by CDI_Leaf_Priv and containing a DICE
+ * chain that chains from UDS_Pub to CDI_Leaf_Pub, it can be certain that (barring vulnerabilities
+ * in some boot stage), the CertificateRequest came from the device associated with UDS_Pub, running
+ * the specific software identified by the certificates in the chain. If the server has some
+ * mechanism for knowing the hash values of compromised stages, it can determine whether signing
+ * certificates is appropriate.
  *
- * Degenerate BCCs
- * ===============
+ * Degenerate DICE Chains
+ * ======================
  *
- * While a proper BCC, as described above, reflects the complete boot sequence from boot ROM to the
- * secure area image of the IRemotelyProvisionedComponent, it's also possible to use a "degenerate"
- * BCC which consists only of a single, self-signed certificate containing the public key of a
- * hardware-bound key pair. This is an appopriate solution for devices which haven't implemented
- * everything necessary to produce a proper BCC, but can derive a unique key pair in the secure
- * area.  In this degenerate case, DK_pub is the same as KM_pub.
+ * While a proper DICE Chain, as described above, reflects the complete boot sequence from boot ROM
+ * to the secure area image of the IRemotelyProvisionedComponent, it's also possible to use a
+ * "degenerate" DICE Chain which consists only of a single, self-signed certificate containing the
+ * public key of a hardware-bound key pair. This is an appopriate solution for devices which haven't
+ * implemented everything necessary to produce a proper DICE Chain, but can derive a unique key pair
+ * in the secure area. In this degenerate case, UDS_Pub is the same as CDI_Leaf_Pub.
  *
- * BCC Privacy
- * ===========
+ * DICE Chain Privacy
+ * ==================
  *
- * Because the BCC constitutes an unspoofable, device-unique identifier, special care is taken to
- * prevent its availability to entities who may wish to track devices. Two precautions are taken:
+ * Because the DICE Chain constitutes an unspoofable, device-unique identifier, special care is
+ * taken to prevent its availability to entities who may wish to track devices. Three precautions
+ * are taken:
  *
- * 1.  The BCC is never exported from the IRemotelyProvisionedComponent except in encrypted
- *     form. The portion of the CertificateRequest that contains the BCC is encrypted using an
- *     Endpoint Encryption Key (EEK).  The EEK is provided in the form of a certificate chain whose
- *     root must be pre-provisioned into the secure area (hardcoding the roots into the secure area
- *     firmware image is a recommended approach). Multiple roots may be provisioned. If the provided
- *     EEK does not chain back to this already-known root, the IRemotelyProvisionedComponent must
- *     reject it.
+ * 1) The DICE chain is only handled by the native Remote Key Provisioning Daemon (RKPD) service on
+ *    the HLOS and is not exposed to apps running on device.
  *
- * 2.  Precaution 1 above ensures that only an entity with a valid EEK private key can decrypt the
- *     BCC. To make it feasible to build a provisioning server which cannot use the BCC to track
- *     devices, the CertificateRequest is structured so that the server can be partitioned into two
- *     components.  The "decrypter" decrypts the BCC, verifies DK_pub and the device's right to
- *     receive provisioned certificates, but does not see the public keys to be signed or the
- *     resulting certificates.  The "certifier" gets informed of the results of the decrypter's
- *     validation and sees the public keys to be signed and resulting certificates, but does not see
- *     the BCC.
+ * 2) The CDI_Leaf_Priv key cannot be used to sign arbitrary data.
  *
- * Test Mode
- * =========
+ * 3) Backend infrastructure does not correlate UDS_Pub with the certificates signed and sent back
+ *    to the device.
  *
- * The IRemotelyProvisionedComponent supports a test mode, allowing the generation of test key pairs
- * and test CertificateRequests. Test keys/requests are annotated as such, and the BCC used for test
- * CertificateRequests must contain freshly-generated keys, not the real BCC key pairs.
+ * Versioning
+ * ==========
+ * Versions 1 and 2 of the schema, as previously defined in DeviceInfo.aidl, diverge in
+ * functionality from Version 3. Version 3 removes the need to have testMode in function calls and
+ * deprecates the Endpoint Encryption Key (EEK) as well. Vendors implementing Version 1
+ * (Android S/12) or Version 2 (Android T/13) do not need to implement generateCertificateRequestV2.
+ * Vendors implementing Version 3 (Android U/14) need to implement generateCertificateRequestV2.
+ *
+ * For better coverage of changes from version to version, please see RKP_CHANGELOG.md in the root
+ * of the keymint interface directory.
+ *
  * @hide
  */
 @VintfStability
 interface IRemotelyProvisionedComponent {
     const int STATUS_FAILED = 1;
     const int STATUS_INVALID_MAC = 2;
+    // --------- START: Versions 1 and 2 Only ----------
     const int STATUS_PRODUCTION_KEY_IN_TEST_REQUEST = 3;
     const int STATUS_TEST_KEY_IN_PRODUCTION_REQUEST = 4;
     const int STATUS_INVALID_EEK = 5;
+    // --------- END: Versions 1 and 2 Only ------------
+    const int STATUS_REMOVED = 6;
 
     /**
      * @return info which contains information about the underlying IRemotelyProvisionedComponent
@@ -124,11 +129,14 @@
     RpcHardwareInfo getHardwareInfo();
 
     /**
-     * generateKeyPair generates a new ECDSA P-256 key pair that can be certified.  Note that this
-     * method only generates ECDSA P-256 key pairs, but the interface can be extended to add methods
-     * for generating keys for other algorithms, if necessary.
+     * generateKeyPair generates a new ECDSA P-256 key pair that can be attested by the remote
+     * server.
      *
-     * @param in boolean testMode indicates whether the generated key is for testing only. Test keys
+     * @param in boolean testMode this field is now deprecated. It is ignored by the implementation
+     *        in v3, but retained to simplify backwards compatibility support. V1 and V2
+     *        implementations must still respect the testMode flag.
+     *
+     *        testMode indicates whether the generated key is for testing only. Test keys
      *        are marked (see the definition of PublicKey in the MacedPublicKey structure) to
      *        prevent them from being confused with production keys.
      *
@@ -142,6 +150,10 @@
     byte[] generateEcdsaP256KeyPair(in boolean testMode, out MacedPublicKey macedPublicKey);
 
     /**
+     * This method has been removed in version 3 of the HAL. The header is kept around for
+     * backwards compatibility purposes. Calling this method should return STATUS_REMOVED on v3.
+     *
+     * For v1 and v2 implementations:
      * generateCertificateRequest creates a certificate request to be sent to the provisioning
      * server.
      *
@@ -167,9 +179,9 @@
      *
      *            EekChain = [ + SignedSignatureKey, SignedEek ]
      *
-     *            SignedSignatureKey = [              // COSE_Sign1
+     *            SignedSignatureKey = [              ; COSE_Sign1
      *                protected: bstr .cbor {
-     *                    1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
+     *                    1 : AlgorithmEdDSA / AlgorithmES256,  ; Algorithm
      *                },
      *                unprotected: {},
      *                payload: bstr .cbor SignatureKeyEd25519 /
@@ -178,63 +190,58 @@
      *                           bstr ECDSA(.cbor SignatureKeySignatureInput)
      *            ]
      *
-     *            SignatureKeyEd25519 = {                    // COSE_Key
-     *                 1 : 1,                         // Key type : Octet Key Pair
-     *                 3 : AlgorithmEdDSA,            // Algorithm
-     *                 -1 : 6,                        // Curve : Ed25519
-     *                 -2 : bstr                      // Ed25519 public key
+     *            SignatureKeyEd25519 = {             ; COSE_Key
+     *                 1 : 1,                         ; Key type : Octet Key Pair
+     *                 3 : AlgorithmEdDSA,            ; Algorithm
+     *                 -1 : 6,                        ; Curve : Ed25519
+     *                 -2 : bstr                      ; Ed25519 public key
      *            }
      *
      *            SignatureKeyP256 = {
-     *                 1 : 2,                         // Key type : EC2
-     *                 3 : AlgorithmES256,            // Algorithm
-     *                 -1 : 1,                        // Curve: P256
-     *                 -2 : bstr,                     // X coordinate
-     *                 -3 : bstr                      // Y coordinate
+     *                 1 : 2,                         ; Key type : EC2
+     *                 3 : AlgorithmES256,            ; Algorithm
+     *                 -1 : 1,                        ; Curve: P256
+     *                 -2 : bstr,                     ; X coordinate
+     *                 -3 : bstr                      ; Y coordinate
      *            }
      *
      *            SignatureKeySignatureInput = [
      *                context: "Signature1",
-     *                body_protected: bstr .cbor {
-     *                    1 : AlgorithmEdDSA / AlgorithmES256,     // Algorithm
-     *                },
+     *                body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
      *                external_aad: bstr .size 0,
      *                payload: bstr .cbor SignatureKeyEd25519 /
      *                         bstr .cbor SignatureKeyP256
      *            ]
      *
-     *            SignedEek = [                       // COSE_Sign1
-     *                protected: bstr .cbor {
-     *                    1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
-     *                },
+     *            ; COSE_Sign1
+     *            SignedEek = [
+     *                protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
      *                unprotected: {},
      *                payload: bstr .cbor EekX25519 / .cbor EekP256,
      *                signature: bstr PureEd25519(.cbor EekSignatureInput) /
      *                           bstr ECDSA(.cbor EekSignatureInput)
      *            ]
      *
-     *            EekX25519 = {            // COSE_Key
-     *                1 : 1,               // Key type : Octet Key Pair
-     *                2 : bstr             // KID : EEK ID
-     *                3 : -25,             // Algorithm : ECDH-ES + HKDF-256
-     *                -1 : 4,              // Curve : X25519
-     *                -2 : bstr            // Ed25519 public key
+     *            EekX25519 = {            ; COSE_Key
+     *                1 : 1,               ; Key type : Octet Key Pair
+     *                2 : bstr             ; KID : EEK ID
+     *                3 : -25,             ; Algorithm : ECDH-ES + HKDF-256
+     *                -1 : 4,              ; Curve : X25519
+     *                -2 : bstr            ; Ed25519 public key
      *            }
      *
-     *            EekP256 = {              // COSE_Key
-     *                1 : 2,               // Key type : EC2
-     *                2 : bstr             // KID : EEK ID
-     *                3 : -25,             // Algorithm : ECDH-ES + HKDF-256
-     *                -1 : 1,              // Curve : P256
-     *                -2 : bstr            // Sender X coordinate
-     *                -3 : bstr            // Sender Y coordinate
+     *            EekP256 = {              ; COSE_Key
+     *                1 : 2,               ; Key type : EC2
+     *                2 : bstr             ; KID : EEK ID
+     *                3 : -25,             ; Algorithm : ECDH-ES + HKDF-256
+     *                -1 : 1,              ; Curve : P256
+     *                -2 : bstr            ; Sender X coordinate
+     *                -3 : bstr            ; Sender Y coordinate
      *            }
      *
      *            EekSignatureInput = [
      *                context: "Signature1",
-     *                body_protected: bstr .cbor {
-     *                    1 : AlgorithmEdDSA / AlgorithmES256,     // Algorithm
-     *                },
+     *                body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
      *                external_aad: bstr .size 0,
      *                payload: bstr .cbor EekX25519 / .cbor EekP256
      *            ]
@@ -270,25 +277,188 @@
      *        Where EK_mac is an ephemeral MAC key, found in ProtectedData (see below).  The MACed
      *        data is the "tag" field of a COSE_Mac0 structure like:
      *
-     *            MacedKeys = [                            // COSE_Mac0
+     *            MacedKeys = [                            ; COSE_Mac0
      *                protected : bstr .cbor {
-     *                    1 : 5,                           // Algorithm : HMAC-256
+     *                    1 : 5,                           ; Algorithm : HMAC-256
      *                },
      *                unprotected : {},
-     *                // Payload is PublicKeys from keysToSign argument, in provided order.
+     *                ; Payload is PublicKeys from keysToSign argument, in provided order.
      *                payload: bstr .cbor [ * PublicKey ],
      *                tag: bstr
      *            ]
      *
      *            KeysToMacStructure = [
      *                context : "MAC0",
-     *                protected : bstr .cbor { 1 : 5 },    // Algorithm : HMAC-256
+     *                protected : bstr .cbor { 1 : 5 },    ; Algorithm : HMAC-256
      *                external_aad : bstr .size 0,
-     *                // Payload is PublicKeys from keysToSign argument, in provided order.
+     *                ; Payload is PublicKeys from keysToSign argument, in provided order.
      *                payload : bstr .cbor [ * PublicKey ]
      *            ]
      */
     byte[] generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
             in byte[] endpointEncryptionCertChain, in byte[] challenge, out DeviceInfo deviceInfo,
             out ProtectedData protectedData);
+
+    /**
+     * generateCertificateRequestV2 creates a certificate signing request to be sent to the
+     * provisioning server.
+     *
+     * @param in MacedPublicKey[] keysToSign contains the set of keys to certify. The
+     *        IRemotelyProvisionedComponent must validate the MACs on each key.  If any entry in the
+     *        array lacks a valid MAC, the method must return STATUS_INVALID_MAC.
+     *
+     * @param in challenge contains a byte string from the provisioning server which will be
+     *        included in the signed data of the CSR structure. Different provisioned backends may
+     *        use different semantic data for this field, but the supported sizes must be between 32
+     *        and 64 bytes, inclusive.
+     *
+     * @return the following CBOR Certificate Signing Request (Csr) serialized into a byte array:
+     *
+     * Csr = [
+     *    version: 3,              ; The CDDL Schema version.
+     *    UdsCerts,
+     *    DiceCertChain,
+     *    SignedData
+     * ]
+     *
+     * ; COSE_Sign1 (untagged)
+     * SignedData = [
+     *     protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+     *     unprotected: {},
+     *     payload: bstr .cbor SignedDataPayload,
+     *     signature: bstr            ; PureEd25519(CDI_Leaf_Priv, bstr .cbor SignedDataSigStruct) /
+     *                                ; ECDSA(CDI_Leaf_Priv, bstr .cbor SignedDataSigStruct)
+     * ]
+     *
+     * ; Sig_structure for SignedData
+     * SignedDataSigStruct = [
+     *     context: "Signature1",
+     *     protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+     *     external_aad: bstr .size 0,
+     *     payload: bstr .cbor SignedDataPayload
+     * ]
+     *
+     * SignedDataPayload = [               ; CBOR Array defining the payload for SignedData
+     *     DeviceInfo,                     ; Defined in DeviceInfo.aidl
+     *     challenge: bstr .size (32..64), ; Provided by the method parameters
+     *     KeysToSign,                     ; Provided by the method parameters
+     * ]
+     *
+     * KeysToSign = [ * PublicKey ]   ; Please see MacedPublicKey.aidl for the PublicKey definition.
+     *
+     * ; UdsCerts allows the platform to provide additional certifications for the UDS_Pub. For
+     * ; example, this could be provided by the hardware vendor, who certifies all of their chips.
+     * ; The SignerName is a free-form string describing who generated the signature. The root
+     * ; certificate will need to be communicated to the verifier out of band, along with the
+     * ; SignerName that is expected for the given root certificate.
+     * UdsCerts = {
+     *     * SignerName => UdsCertChain
+     * }
+     *
+     * ; SignerName is a string identifier that indicates both the signing authority as
+     * ; well as the format of the UdsCertChain
+     * SignerName = tstr
+     *
+     * UdsCertChain = [
+     *     2* X509Certificate       ; Root -> ... -> Leaf. "Root" is the vendor self-signed
+     *                              ; cert, "Leaf" contains UDS_Public. There may also be
+     *                              ; intermediate certificates between Root and Leaf.
+     * ]
+     *
+     * ; A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or edDSA)
+     * X509Certificate = bstr
+     *
+     * ; The DICE Chain contains measurements about the device firmware.
+     * ; The first entry in the DICE Chain is the UDS_Pub, encoded as a COSE_key. All entries
+     * ; after the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN)
+     * ; Note that there is no DiceChainEntry for UDS_pub, only a "bare" COSE_key.
+     * DiceCertChain = [
+     *     PubKeyEd25519 / PubKeyECDSA256,  ; UDS_Pub
+     *     + DiceChainEntry,                ; First CDI_Certificate -> Last CDI_Certificate
+     *                                      ; Last certificate corresponds to KeyMint's DICE key.
+     * ]
+     *
+     * ; This is the signed payload for each entry in the DCC. Note that the "Configuration
+     * ; Input Values" described by the Open Profile are not used here. Instead, the Dcc
+     * ; defines its own configuration values for the Configuration Descriptor field. See
+     * ; the Open Profile for DICE for more details on the fields. SHA256 and SHA512 are acceptable
+     * ; hash algorithms. The digest bstr values in the payload are the digest values without any
+     * ; padding. Note that for SHA256, this implies the digest bstr is 32 bytes. This is an
+     * ; intentional, minor deviation from Open Profile for DICE, which specifies all digests are
+     * ; 64 bytes.
+     * DiceChainEntryPayload = {                    ; CWT [RFC8392]
+     *     1 : tstr,                                ; Issuer
+     *     2 : tstr,                                ; Subject
+     *     -4670552 : bstr .cbor PubKeyEd25519 /
+     *                bstr .cbor PubKeyECDSA256,    ; Subject Public Key
+     *     -4670553 : bstr                          ; Key Usage
+     *
+     *     ; NOTE: All of the following fields may be omitted for a "Degenerate DICE Chain", as
+     *     ;       described above.
+     *     -4670545 : bstr,                         ; Code Hash
+     *     ? -4670546 : bstr,                       ; Code Descriptor
+     *     ? -4670547 : bstr,                       ; Configuration Hash
+     *     -4670548 : bstr .cbor {                  ; Configuration Descriptor
+     *         ? -70002 : tstr,                         ; Component name
+     *         ? -70003 : int,                          ; Firmware version
+     *         ? -70004 : null,                         ; Resettable
+     *     },
+     *     -4670549 : bstr,                         ; Authority Hash
+     *     ? -4670550 : bstr,                       ; Authority Descriptor
+     *     -4670551 : bstr,                         ; Mode
+     * }
+     *
+     * ; Each entry in the Dcc is a DiceChainEntryPayload signed by the key from the previous entry
+     * ; in the Dcc array.
+     * DiceChainEntry = [                            ; COSE_Sign1 (untagged)
+     *     protected : bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+     *     unprotected: {},
+     *     payload: bstr .cbor DiceChainEntryPayload,
+     *     signature: bstr ; PureEd25519(SigningKey, bstr .cbor DiceChainEntryInput) /
+     *                     ; ECDSA(SigningKey, bstr .cbor DiceChainEntryInput)
+     *                     ; See RFC 8032 for details of how to encode the signature value
+     *                     ; for Ed25519.
+     * ]
+     *
+     * DiceChainEntryInput = [
+     *     context: "Signature1",
+     *     protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+     *     external_aad: bstr .size 0,
+     *     payload: bstr .cbor DiceChainEntryPayload
+     * ]
+     *
+     * ; The following section defines some types that are reused throughout the above
+     * ; data structures.
+     * PubKeyX25519 = {                 ; COSE_Key
+     *      1 : 1,                      ; Key type : Octet Key Pair
+     *     -1 : 4,                      ; Curve : X25519
+     *     -2 : bstr                    ; Sender X25519 public key
+     * }
+     *
+     * PubKeyEd25519 = {                ; COSE_Key
+     *     1 : 1,                       ; Key type : octet key pair
+     *     3 : AlgorithmEdDSA,          ; Algorithm : EdDSA
+     *     -1 : 6,                      ; Curve : Ed25519
+     *     -2 : bstr                    ; X coordinate, little-endian
+     * }
+     *
+     * PubKeyEcdhP256 = {               ; COSE_Key
+     *      1 : 2,                      ; Key type : EC2
+     *      -1 : 1,                     ; Curve : P256
+     *      -2 : bstr                   ; Sender X coordinate
+     *      -3 : bstr                   ; Sender Y coordinate
+     * }
+     *
+     * PubKeyECDSA256 = {               ; COSE_Key
+     *     1 : 2,                       ; Key type : EC2
+     *     3 : AlgorithmES256,          ; Algorithm : ECDSA w/ SHA-256
+     *     -1 : 1,                      ; Curve: P256
+     *     -2 : bstr,                   ; X coordinate
+     *     -3 : bstr                    ; Y coordinate
+     * }
+     *
+     * AlgorithmES256 = -7
+     * AlgorithmEdDSA = -8
+     */
+    byte[] generateCertificateRequestV2(in MacedPublicKey[] keysToSign, in byte[] challenge);
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl b/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
index ad97443..275e322 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
@@ -28,21 +28,22 @@
      * only to the secure environment, as proof that the public key was generated by that
      * environment. In CDDL, assuming the contained key is a P-256 public key:
      *
-     *     MacedPublicKey = [                     // COSE_Mac0
-     *         protected: bstr .cbor { 1 : 5},    // Algorithm : HMAC-256
+     *     MacedPublicKey = [                     ; COSE_Mac0
+     *         protected: bstr .cbor { 1 : 5},    ; Algorithm : HMAC-256
      *         unprotected: { },
      *         payload : bstr .cbor PublicKey,
      *         tag : bstr HMAC-256(K_mac, MAC_structure)
      *     ]
      *
-     *     PublicKey = {               // COSE_Key
-     *         1 : 2,                  // Key type : EC2
-     *         3 : -7,                 // Algorithm : ES256
-     *         -1 : 1,                 // Curve : P256
-     *         -2 : bstr,              // X coordinate, little-endian
-     *         -3 : bstr,              // Y coordinate, little-endian
-     *         ? -70000 : nil          // Presence indicates this is a test key.  If set, K_mac is
-     *                                 // all zeros.
+     *     ; NOTE: -70000 is deprecated for v3 HAL implementations.
+     *     PublicKey = {               ; COSE_Key
+     *         1 : 2,                  ; Key type : EC2
+     *         3 : -7,                 ; Algorithm : ES256
+     *         -1 : 1,                 ; Curve : P256
+     *         -2 : bstr,              ; X coordinate, little-endian
+     *         -3 : bstr,              ; Y coordinate, little-endian
+     *         -70000 : nil            ; Presence indicates this is a test key. If set, K_mac is
+     *                                 ; all zeros.
      *     },
      *
      *     MAC_structure = [
@@ -51,9 +52,6 @@
      *         external_aad : bstr .size 0,
      *         payload : bstr .cbor PublicKey
      *     ]
-     *
-     * if a non-P256 public key were contained, the contents of the PublicKey map would change a
-     * little; see RFC 8152 for details.
      */
     byte[] macedKey;
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
index 8b3875b..d59508b 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
@@ -17,9 +17,13 @@
 package android.hardware.security.keymint;
 
 /**
+ * NOTE: ProtectedData has been removed as of version 3, but is kept around for backwards
+ * compatibility reasons. For versions 1 and 2:
+ *
  * ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
  * authenticate the keysToSign (see keysToSignMac output argument of
  * IRemotelyProvisionedComponent.generateCertificateRequest).
+ *
  * @hide
  */
 @VintfStability
@@ -33,201 +37,201 @@
      *   - None of the CBOR in ProtectedData uses CBOR tags. If an implementation includes
      *     tags, parsers may reject the data.
      *
-     *     ProtectedData = [               // COSE_Encrypt
+     *     ProtectedData = [               ; COSE_Encrypt
      *         protected: bstr .cbor {
-     *             1 : 3                   // Algorithm : AES-GCM 256
+     *             1 : 3                   ; Algorithm : AES-GCM 256
      *         },
      *         unprotected: {
-     *             5 : bstr .size 12       // IV
+     *             5 : bstr .size 12       ; IV
      *         },
-     *         ciphertext: bstr,           // AES-GCM-256(K, .cbor ProtectedDataPayload)
-     *                                     // Where the encryption key 'K' is derived as follows:
-     *                                     // ikm = ECDH(EEK_pub, Ephemeral_priv)
-     *                                     // salt = null
-     *                                     // info = .cbor Context (see below)
-     *                                     // K = HKDF-SHA-256(ikm, salt, info)
+     *         ciphertext: bstr,           ; AES-GCM-256(K, .cbor ProtectedDataPayload)
+     *                                     ; Where the encryption key 'K' is derived as follows:
+     *                                     ; ikm = ECDH(EEK_pub, Ephemeral_priv)
+     *                                     ; salt = null
+     *                                     ; info = .cbor Context (see below)
+     *                                     ; K = HKDF-SHA-256(ikm, salt, info)
      *         recipients : [
-     *             [                       // COSE_Recipient
+     *             [                       ; COSE_Recipient
      *                 protected : bstr .cbor {
-     *                     1 : -25         // Algorithm : ECDH-ES + HKDF-256
+     *                     1 : -25         ; Algorithm : ECDH-ES + HKDF-256
      *                 },
      *                 unprotected : {
-     *                     -1 : PubKeyX25519 / PubKeyEcdhP256  // Ephemeral_pub
-     *                     4 : bstr,       // KID : EEK ID
+     *                     -1 : PubKeyX25519 / PubKeyEcdhP256  ; Ephemeral_pub
+     *                     4 : bstr,       ; KID : EEK ID
      *                 },
      *                 ciphertext : nil
      *             ]
      *         ]
      *     ]
      *
-     *     // The COSE_KDF_Context that is used to derive the ProtectedData encryption key with
-     *     // HKDF. See details on use in ProtectedData comments above.
+     *     ; The COSE_KDF_Context that is used to derive the ProtectedData encryption key with
+     *     ; HKDF. See details on use in ProtectedData comments above.
      *     Context = [
-     *         AlgorithmID : 3             // AES-GCM 256
+     *         AlgorithmID : 3             ; AES-GCM 256
      *         PartyUInfo : [
      *             identity : bstr "client"
      *             nonce : bstr .size 0,
-     *             other : bstr            // Ephemeral_pub
+     *             other : bstr            ; Ephemeral_pub
      *         ],
      *         PartyVInfo : [
      *             identity : bstr "server",
      *             nonce : bstr .size 0,
-     *             other : bstr            // EEK pubkey
+     *             other : bstr            ; EEK pubkey
      *         ],
      *         SuppPubInfo : [
-     *             256,                    // Output key length
+     *             256,                    ; Output key length
      *             protected : bstr .size 0
      *         ]
      *     ]
      *
-     *     // The data that is encrypted and included in ProtectedData ciphertext (see above).
+     *     ; The data that is encrypted and included in ProtectedData ciphertext (see above).
      *     ProtectedDataPayload [
      *         SignedMac,
      *         Bcc,
      *         ? AdditionalDKSignatures,
      *     ]
      *
-     *     // AdditionalDKSignatures allows the platform to provide additional certifications
-     *     // for the DK_pub. For example, this could be provided by the hardware vendor, who
-     *     // certifies all of their devices. The SignerName is a free-form string describing
-     *     // who generated the signature.
+     *     ; AdditionalDKSignatures allows the platform to provide additional certifications
+     *     ; for the DK_pub. For example, this could be provided by the hardware vendor, who
+     *     ; certifies all of their devices. The SignerName is a free-form string describing
+     *     ; who generated the signature.
      *     AdditionalDKSignatures = {
      *         + SignerName => DKCertChain
      *     }
      *
-     *     // SignerName is a string identifier that indicates both the signing authority as
-     *     // well as the format of the DKCertChain
+     *     ; SignerName is a string identifier that indicates both the signing authority as
+     *     ; well as the format of the DKCertChain
      *     SignerName = tstr
      *
      *     DKCertChain = [
-     *         2* X509Certificate       // Root -> ... -> Leaf. "Root" is the vendor self-signed
-     *                                  // cert, "Leaf" contains DK_pub. There may also be
-     *                                  // intermediate certificates between Root and Leaf.
+     *         2* X509Certificate       ; Root -> ... -> Leaf. "Root" is the vendor self-signed
+     *                                  ; cert, "Leaf" contains DK_pub. There may also be
+     *                                  ; intermediate certificates between Root and Leaf.
      *     ]
      *
-     *     // A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or edDSA)
+     *     ; A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or edDSA)
      *     X509Certificate = bstr
      *
-     *     // The SignedMac, which authenticates the MAC key that is used to authenticate the
-     *     // keysToSign.
-     *     SignedMac = [                                // COSE_Sign1
-     *         bstr .cbor {                             // Protected params
-     *             1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
+     *     ; The SignedMac, which authenticates the MAC key that is used to authenticate the
+     *     ; keysToSign.
+     *     SignedMac = [                                ; COSE_Sign1
+     *         bstr .cbor {                             ; Protected params
+     *             1 : AlgorithmEdDSA / AlgorithmES256, ; Algorithm
      *         },
-     *         {},                                      // Unprotected params
-     *         bstr .size 32,                           // Payload: MAC key
-     *         bstr // PureEd25519(KM_priv, bstr .cbor SignedMac_structure) /
-     *              // ECDSA(KM_priv, bstr .cbor SignedMac_structure)
+     *         {},                                      ; Unprotected params
+     *         bstr .size 32,                           ; Payload: MAC key
+     *         bstr ; PureEd25519(KM_priv, bstr .cbor SignedMac_structure) /
+     *              ; ECDSA(KM_priv, bstr .cbor SignedMac_structure)
      *     ]
      *
-     *     SignedMac_structure = [                      //  COSE Sig_structure
+     *     SignedMac_structure = [                      ;  COSE Sig_structure
      *         "Signature1",
-     *         bstr .cbor {                             // Protected params
-     *             1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
+     *         bstr .cbor {                             ; Protected params
+     *             1 : AlgorithmEdDSA / AlgorithmES256, ; Algorithm
      *         },
      *         bstr .cbor SignedMacAad,
-     *         bstr .size 32                            // MAC key
+     *         bstr .size 32                            ; MAC key
      *     ]
      *
      *     SignedMacAad = [
-     *         challenge : bstr .size (32..64),   // Size between 32 - 64
-     *                                            // bytes inclusive
+     *         challenge : bstr .size (32..64),   ; Size between 32 - 64
+     *                                            ; bytes inclusive
      *         VerifiedDeviceInfo,
-     *         tag: bstr                 // This is the tag from COSE_Mac0 of
-     *                                   // KeysToCertify, to tie the key set to
-     *                                   // the signature.
+     *         tag: bstr                 ; This is the tag from COSE_Mac0 of
+     *                                   ; KeysToCertify, to tie the key set to
+     *                                   ; the signature.
      *     ]
      *
-     *     VerifiedDeviceInfo = DeviceInfo  // See DeviceInfo.aidl
+     *     VerifiedDeviceInfo = DeviceInfo  ; See DeviceInfo.aidl
      *
-     *     // The BCC is the boot certificate chain, containing measurements about the device
-     *     // boot chain. The BCC generally follows the Open Profile for DICE specification at
-     *     // https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md.
-     *     //
-     *     // The first entry in the Bcc is the DK_pub, encoded as a COSE_key. All entries after
-     *     // the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN).
-     *     // Note that there is no BccEntry for DK_pub, only a "bare" COSE_key.
+     *     ; The BCC is the boot certificate chain, containing measurements about the device
+     *     ; boot chain. The BCC generally follows the Open Profile for DICE specification at
+     *     ; https:;pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md.
+     *     ;
+     *     ; The first entry in the Bcc is the DK_pub, encoded as a COSE_key. All entries after
+     *     ; the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN).
+     *     ; Note that there is no BccEntry for DK_pub, only a "bare" COSE_key.
      *     Bcc = [
-     *         PubKeyEd25519 / PubKeyECDSA256, // DK_pub
-     *         + BccEntry,                     // Root -> leaf (KM_pub)
+     *         PubKeyEd25519 / PubKeyECDSA256, ; DK_pub
+     *         + BccEntry,                     ; Root -> leaf (KM_pub)
      *     ]
      *
-     *     // This is the signed payload for each entry in the Bcc. Note that the "Configuration
-     *     // Input Values" described by the Open Profile are not used here. Instead, the Bcc
-     *     // defines its own configuration values for the Configuration Descriptor field. See
-     *     // the Open Profile for DICE for more details on the fields. All hashes are SHA256.
-     *     BccPayload = {                               // CWT [RFC8392]
-     *         1 : tstr,                                // Issuer
-     *         2 : tstr,                                // Subject
+     *     ; This is the signed payload for each entry in the Bcc. Note that the "Configuration
+     *     ; Input Values" described by the Open Profile are not used here. Instead, the Bcc
+     *     ; defines its own configuration values for the Configuration Descriptor field. See
+     *     ; the Open Profile for DICE for more details on the fields. All hashes are SHA256.
+     *     BccPayload = {                               ; CWT [RFC8392]
+     *         1 : tstr,                                ; Issuer
+     *         2 : tstr,                                ; Subject
      *         -4670552 : bstr .cbor PubKeyEd25519 /
-     *                    bstr .cbor PubKeyECDSA256,    // Subject Public Key
-     *         -4670553 : bstr                          // Key Usage
+     *                    bstr .cbor PubKeyECDSA256,    ; Subject Public Key
+     *         -4670553 : bstr                          ; Key Usage
      *
-     *         // NOTE: All of the following fields may be omitted for a "Degenerate BCC", as
-     *         //       described by IRemotelyProvisionedComponent.aidl.
-     *         -4670545 : bstr,                         // Code Hash
-     *         ? -4670546 : bstr,                       // Code Descriptor
-     *         ? -4670547 : bstr,                       // Configuration Hash
-     *         -4670548 : bstr .cbor {                  // Configuration Descriptor
-     *             ? -70002 : tstr,                         // Component name
-     *             ? -70003 : int,                          // Firmware version
-     *             ? -70004 : null,                         // Resettable
+     *         ; NOTE: All of the following fields may be omitted for a "Degenerate BCC", as
+     *         ;       described by IRemotelyProvisionedComponent.aidl.
+     *         -4670545 : bstr,                         ; Code Hash
+     *         ? -4670546 : bstr,                       ; Code Descriptor
+     *         ? -4670547 : bstr,                       ; Configuration Hash
+     *         -4670548 : bstr .cbor {                  ; Configuration Descriptor
+     *             ? -70002 : tstr,                         ; Component name
+     *             ? -70003 : int,                          ; Firmware version
+     *             ? -70004 : null,                         ; Resettable
      *         },
-     *         -4670549 : bstr,                         // Authority Hash
-     *         ? -4670550 : bstr,                       // Authority Descriptor
-     *         -4670551 : bstr,                         // Mode
+     *         -4670549 : bstr,                         ; Authority Hash
+     *         ? -4670550 : bstr,                       ; Authority Descriptor
+     *         -4670551 : bstr,                         ; Mode
      *     }
      *
-     *     // Each entry in the Bcc is a BccPayload signed by the key from the previous entry
-     *     // in the Bcc array.
-     *     BccEntry = [                                  // COSE_Sign1 (untagged)
+     *     ; Each entry in the Bcc is a BccPayload signed by the key from the previous entry
+     *     ; in the Bcc array.
+     *     BccEntry = [                                  ; COSE_Sign1 (untagged)
      *         protected : bstr .cbor {
-     *             1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
+     *             1 : AlgorithmEdDSA / AlgorithmES256,  ; Algorithm
      *         },
      *         unprotected: {},
      *         payload: bstr .cbor BccPayload,
-     *         signature: bstr // PureEd25519(SigningKey, bstr .cbor BccEntryInput) /
-     *                         // ECDSA(SigningKey, bstr .cbor BccEntryInput)
-     *         // See RFC 8032 for details of how to encode the signature value for Ed25519.
+     *         signature: bstr ; PureEd25519(SigningKey, bstr .cbor BccEntryInput) /
+     *                         ; ECDSA(SigningKey, bstr .cbor BccEntryInput)
+     *         ; See RFC 8032 for details of how to encode the signature value for Ed25519.
      *     ]
      *
      *     BccEntryInput = [
      *         context: "Signature1",
      *         protected: bstr .cbor {
-     *             1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
+     *             1 : AlgorithmEdDSA / AlgorithmES256,  ; Algorithm
      *         },
      *         external_aad: bstr .size 0,
      *         payload: bstr .cbor BccPayload
      *     ]
      *
-     *     // The following section defines some types that are reused throughout the above
-     *     // data structures.
-     *     PubKeyX25519 = {                 // COSE_Key
-     *          1 : 1,                      // Key type : Octet Key Pair
-     *         -1 : 4,                      // Curve : X25519
-     *         -2 : bstr                    // Sender X25519 public key
+     *     ; The following section defines some types that are reused throughout the above
+     *     ; data structures.
+     *     PubKeyX25519 = {                 ; COSE_Key
+     *          1 : 1,                      ; Key type : Octet Key Pair
+     *         -1 : 4,                      ; Curve : X25519
+     *         -2 : bstr                    ; Sender X25519 public key
      *     }
      *
-     *     PubKeyEd25519 = {                // COSE_Key
-     *         1 : 1,                       // Key type : octet key pair
-     *         3 : AlgorithmEdDSA,          // Algorithm : EdDSA
-     *         -1 : 6,                      // Curve : Ed25519
-     *         -2 : bstr                    // X coordinate, little-endian
+     *     PubKeyEd25519 = {                ; COSE_Key
+     *         1 : 1,                       ; Key type : octet key pair
+     *         3 : AlgorithmEdDSA,          ; Algorithm : EdDSA
+     *         -1 : 6,                      ; Curve : Ed25519
+     *         -2 : bstr                    ; X coordinate, little-endian
      *     }
      *
-     *     PubKeyEcdhP256 = {               // COSE_Key
-     *          1 : 2,                      // Key type : EC2
-     *          -1 : 1,                     // Curve : P256
-     *          -2 : bstr                   // Sender X coordinate
-     *          -3 : bstr                   // Sender Y coordinate
+     *     PubKeyEcdhP256 = {               ; COSE_Key
+     *          1 : 2,                      ; Key type : EC2
+     *          -1 : 1,                     ; Curve : P256
+     *          -2 : bstr                   ; Sender X coordinate
+     *          -3 : bstr                   ; Sender Y coordinate
      *     }
      *
-     *     PubKeyECDSA256 = {               // COSE_Key
-     *         1 : 2,                       // Key type : EC2
-     *         3 : AlgorithmES256,          // Algorithm : ECDSA w/ SHA-256
-     *         -1 : 1,                      // Curve: P256
-     *         -2 : bstr,                   // X coordinate
-     *         -3 : bstr                    // Y coordinate
+     *     PubKeyECDSA256 = {               ; COSE_Key
+     *         1 : 2,                       ; Key type : EC2
+     *         3 : AlgorithmES256,          ; Algorithm : ECDSA w/ SHA-256
+     *         -1 : 1,                      ; Curve: P256
+     *         -2 : bstr,                   ; X coordinate
+     *         -3 : bstr                    ; Y coordinate
      *     }
      *
      *     AlgorithmES256 = -7
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 7184613..2e282e0 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -30,6 +30,7 @@
 #include <openssl/ec_key.h>
 #include <openssl/x509.h>
 #include <remote_prov/remote_prov_utils.h>
+#include <optional>
 #include <set>
 #include <vector>
 
@@ -73,6 +74,10 @@
     return {"locked", "open"};
 }
 
+std::set<std::string> getAttestationIdEntrySet() {
+    return {"brand", "manufacturer", "product", "model", "device"};
+}
+
 bytevec string_to_bytevec(const char* s) {
     const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
     return bytevec(p, p + strlen(s));
@@ -431,7 +436,7 @@
         auto [deviceInfoMap, __2, deviceInfoErrMsg] = cppbor::parse(deviceInfo.deviceInfo);
         ASSERT_TRUE(deviceInfoMap) << "Failed to parse deviceInfo: " << deviceInfoErrMsg;
         ASSERT_TRUE(deviceInfoMap->asMap());
-        checkDeviceInfo(deviceInfoMap->asMap(), deviceInfo.deviceInfo);
+        checkDeviceInfo(*deviceInfoMap->asMap(), deviceInfo.deviceInfo);
         auto& signingKey = bccContents->back().pubKey;
         deviceInfoMap->asMap()->canonicalize();
         auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
@@ -459,72 +464,92 @@
         }
     }
 
-    void checkType(const cppbor::Map* devInfo, uint8_t majorType, std::string entryName) {
-        const auto& val = devInfo->get(entryName);
-        ASSERT_TRUE(val) << entryName << " does not exist";
-        ASSERT_EQ(val->type(), majorType) << entryName << " has the wrong type.";
+    std::optional<std::string> assertAttribute(const cppbor::Map& devInfo,
+                                               cppbor::MajorType majorType, std::string entryName) {
+        const auto& val = devInfo.get(entryName);
+        if (!val) return entryName + " is missing.\n";
+        if (val->type() != majorType) return entryName + " has the wrong type.\n";
         switch (majorType) {
             case cppbor::TSTR:
-                EXPECT_GT(val->asTstr()->value().size(), 0);
+                if (val->asTstr()->value().size() <= 0) {
+                    return entryName + " is present but the value is empty.\n";
+                }
                 break;
             case cppbor::BSTR:
-                EXPECT_GT(val->asBstr()->value().size(), 0);
+                if (val->asBstr()->value().size() <= 0) {
+                    return entryName + " is present but the value is empty.\n";
+                }
                 break;
             default:
                 break;
         }
+        return {};
     }
 
-    void checkDeviceInfo(const cppbor::Map* deviceInfo, bytevec deviceInfoBytes) {
-        EXPECT_EQ(deviceInfo->clone()->asMap()->canonicalize().encode(), deviceInfoBytes)
+    void checkType(const cppbor::Map& devInfo, cppbor::MajorType majorType, std::string entryName) {
+        if (auto error = assertAttribute(devInfo, majorType, entryName)) {
+            FAIL() << *error;
+        }
+    }
+
+    void checkDeviceInfo(const cppbor::Map& deviceInfo, bytevec deviceInfoBytes) {
+        EXPECT_EQ(deviceInfo.clone()->asMap()->canonicalize().encode(), deviceInfoBytes)
                 << "DeviceInfo ordering is non-canonical.";
-        const auto& version = deviceInfo->get("version");
+        const auto& version = deviceInfo.get("version");
         ASSERT_TRUE(version);
         ASSERT_TRUE(version->asUint());
         RpcHardwareInfo info;
         provisionable_->getHardwareInfo(&info);
         ASSERT_EQ(version->asUint()->value(), info.versionNumber);
         std::set<std::string> allowList;
+        std::string problemEntries;
         switch (version->asUint()->value()) {
             // These fields became mandated in version 2.
             case 2:
-                checkType(deviceInfo, cppbor::TSTR, "brand");
-                checkType(deviceInfo, cppbor::TSTR, "manufacturer");
-                checkType(deviceInfo, cppbor::TSTR, "product");
-                checkType(deviceInfo, cppbor::TSTR, "model");
-                checkType(deviceInfo, cppbor::TSTR, "device");
+                for (auto attId : getAttestationIdEntrySet()) {
+                    if (auto errMsg = assertAttribute(deviceInfo, cppbor::TSTR, attId)) {
+                        problemEntries += *errMsg;
+                    }
+                }
+                EXPECT_EQ("", problemEntries)
+                        << problemEntries
+                        << "Attestation IDs are missing or malprovisioned. If this test is being "
+                           "run against an early proto or EVT build, this error is probably WAI "
+                           "and indicates that Device IDs were not provisioned in the factory. If "
+                           "this error is returned on a DVT or later build revision, then "
+                           "something is likely wrong with the factory provisioning process.";
                 // TODO: Refactor the KeyMint code that validates these fields and include it here.
                 checkType(deviceInfo, cppbor::TSTR, "vb_state");
                 allowList = getAllowedVbStates();
-                EXPECT_NE(allowList.find(deviceInfo->get("vb_state")->asTstr()->value()),
+                EXPECT_NE(allowList.find(deviceInfo.get("vb_state")->asTstr()->value()),
                           allowList.end());
                 checkType(deviceInfo, cppbor::TSTR, "bootloader_state");
                 allowList = getAllowedBootloaderStates();
-                EXPECT_NE(allowList.find(deviceInfo->get("bootloader_state")->asTstr()->value()),
+                EXPECT_NE(allowList.find(deviceInfo.get("bootloader_state")->asTstr()->value()),
                           allowList.end());
                 checkType(deviceInfo, cppbor::BSTR, "vbmeta_digest");
                 checkType(deviceInfo, cppbor::UINT, "system_patch_level");
                 checkType(deviceInfo, cppbor::UINT, "boot_patch_level");
                 checkType(deviceInfo, cppbor::UINT, "vendor_patch_level");
                 checkType(deviceInfo, cppbor::UINT, "fused");
-                EXPECT_LT(deviceInfo->get("fused")->asUint()->value(), 2);  // Must be 0 or 1.
+                EXPECT_LT(deviceInfo.get("fused")->asUint()->value(), 2);  // Must be 0 or 1.
                 checkType(deviceInfo, cppbor::TSTR, "security_level");
                 allowList = getAllowedSecurityLevels();
-                EXPECT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
+                EXPECT_NE(allowList.find(deviceInfo.get("security_level")->asTstr()->value()),
                           allowList.end());
-                if (deviceInfo->get("security_level")->asTstr()->value() == "tee") {
+                if (deviceInfo.get("security_level")->asTstr()->value() == "tee") {
                     checkType(deviceInfo, cppbor::TSTR, "os_version");
                 }
                 break;
             case 1:
                 checkType(deviceInfo, cppbor::TSTR, "security_level");
                 allowList = getAllowedSecurityLevels();
-                EXPECT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
+                EXPECT_NE(allowList.find(deviceInfo.get("security_level")->asTstr()->value()),
                           allowList.end());
                 if (version->asUint()->value() == 1) {
                     checkType(deviceInfo, cppbor::TSTR, "att_id_state");
                     allowList = getAllowedAttIdStates();
-                    EXPECT_NE(allowList.find(deviceInfo->get("att_id_state")->asTstr()->value()),
+                    EXPECT_NE(allowList.find(deviceInfo.get("att_id_state")->asTstr()->value()),
                               allowList.end());
                 }
                 break;
diff --git a/wifi/1.6/default/wifi_chip.cpp b/wifi/1.6/default/wifi_chip.cpp
index c7c00b1..920beb8 100644
--- a/wifi/1.6/default/wifi_chip.cpp
+++ b/wifi/1.6/default/wifi_chip.cpp
@@ -1926,9 +1926,10 @@
 // concurrent STA and not dual AP, else start with idx 0.
 std::string WifiChip::allocateApIfaceName() {
     // Check if we have a dedicated iface for AP.
-    std::vector<std::string> ifnames = getPredefinedApIfaceNames(false);
-    if (!ifnames.empty()) {
-        return ifnames[0];
+    std::vector<std::string> ifnames = getPredefinedApIfaceNames(true);
+    for (auto const& ifname : ifnames) {
+        if (findUsingName(ap_ifaces_, ifname)) continue;
+        return ifname;
     }
     return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface());
 }