When the Android HLOS receives its CDI values and the DICE chain from the previous stage, it reads them and then derives and wipes the necessary secrets (such as public and private key pairs and further CDI stages) for SDV Service Discovery.
This process takes place as soon as possible in the bootflow during
early-init in the second stage init. Doing so makes sure that Android
HLOS consumes and wipes the CDI values before any third-party code executes.
The Android Bootloader (or the guest loader in the hypervisor, if no Android
Bootloader exists) passes the following values through the SDV's Linux Kernel to
second stage init in Android user-space:
- Attestation CDI value of the Android HLOS layer.
- Sealing CDI value of the Android HLOS layer.
- CBOR-encoded DICE chain until the Android HLOS layer.
These values use the SdvDiceHandover format. The SdvDiceHandover is a
CBOR-encoded map described by this CDDL fragment:
SdvDiceHandover = {
1 : bstr .size 32, ; CDI_Attest
2 : bstr .size 32, ; CDI_Seal
3 : DiceCertChain, ; Android SDV DICE chain
}
The IRemotelyProvisionedComponent HAL DiceCertChain specifies the
format of the DiceCertChain. You don't require
deterministically encoded CBOR for SdvDiceHandover, though it's highly
recommended as it supports a wider range of DICE policies.
The SdvDiceHandover format is very similar to the:
AndroidDiceHandoverformat that the Open Profile for DICE reference implementation defines,PvmfwDiceHandoverformat that thepvmfwuses to hand over the DICE chain to a pVM. For example, Microdroid.
In contrast to the AndroidDiceHandover and similarly to the
PvmfwDiceHandover format, the DiceCertChain is required and not optional.
Open Profile for DICE kernel driver
The DICE handover of the Android HLOS CDI from the Android Bootloader (or the guest loader in the hypervisor, if there's no bootloader) to the Android HLOS relies on the Open Profile for DICE kernel driver. The Android Bootloader writes the DICE Chain entry to a region in the guest's memory that the Device Tree (DT) must specify.
The driver reads this memory region that the DT specifies and exposes it the
user space as an /dev/open-dice0 device. The driver allows reading and wiping
this memory region. The Open Profile for DICE driver only exists on arm64
architectures because device tree is an arm64-only concept.
Specify the memory region that the Open Profile for DICE driver exposes using a
reserved-memory node in the DT that you tag for the driver by specifying
"google,open-dice" in the compatible property. For example:
reserved-memory {
// The number of u32 cells to represent the address of a memory region
#address-cells = <2>;
// The number of u32 cells to represent the size of a memory region
#size-cells = <2>;
ranges;
// The unit address (after the @) must match the address in the reg property
dice@D1C30000 {
compatible = "google,open-dice";
no-map;
// The address and the size of the memory region that is passed to the Open
// Profile for DICE driver. The address must be page-aligned, and the size a
// multiple of the page size. The first two hex numbers (cells) represent
// the address of the memory region, the last two represent its size.
reg = <0x0 0xD1C30000 0x0 0x1000>;
};
};