diff --git a/pvmfw/README.md b/pvmfw/README.md index 2d2b253a..6fc2fd6a 100644 --- a/pvmfw/README.md +++ b/pvmfw/README.md @@ -270,3 +270,119 @@ OS's device tree and config header of `pvmfw`. Both `virtualizationmanager` and For details about device tree properties for debug policies, see [microdroid's debugging policy guide](../microdroid/README.md#option-1-running-microdroid-on-avf-debug-policy-configured-device). + +## Booting Protected Virtual Machines + +### Boot Protocol + +As the hypervisor makes pvmfw the entry point of the VM, the initial value of +the registers it receives is configured by the VMM and is expected to follow the +[Linux ABI] _i.e._ + +- x0 = physical address of device tree blob (dtb) in system RAM. +- x1 = 0 (reserved for future use) +- x2 = 0 (reserved for future use) +- x3 = 0 (reserved for future use) + +Images to be verified, which have been loaded to guest memory by the VMM prior +to booting the VM, are described to pvmfw using the device tree (x0): + +- the kernel in the `/config` DT node _e.g._ + + ``` + / { + config { + kernel-address = <0x80200000>; + kernel-size = <0x1000000>; + }; + }; + ```` + +- the (optional) ramdisk in the standard `/chosen` node _e.g._ + + ``` + / { + chosen { + linux,initrd-start = <0x82000000>; + linux,initrd-end = <0x82800000>; + }; + }; + ``` + +[Linux ABI]: https://www.kernel.org/doc/Documentation/arm64/booting.txt + +### Handover ABI + +After verifying the guest kernel, pvmfw boots it using the Linux ABI described +above. It uses the device tree to pass the following: + +- a reserved memory node containing the produced BCC: + + ``` + / { + reserved-memory { + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges; + dice { + compatible = "google,open-dice"; + no-map; + reg = <0x0 0x7fe0000>, <0x0 0x1000>; + }; + }; + }; + ``` + +- the `/chosen/avf,new-instance` flag, set when pvmfw generated a new secret + (_i.e._ the pVM instance was booted for the first time). This should be used + by the next stages to ensure that an attacker isn't trying to force new + secrets to be generated by one stage, in isolation; + +- the `/chosen/avf,strict-boot` flag, always set and can be used by guests to + enable extra validation + +### Guest Image Signing + +pvmfw verifies the guest kernel image (loaded by the VMM) by re-using tools and +formats introduced by the Android Verified Boot. In particular, it expects the +kernel region (see `/config/kernel-{address,size}` described above) to contain +an appended VBMeta structure, which can be generated as follows: + +``` +avbtool add_hash_footer --image \ + --partition_name boot \ + --dynamic_partition_size \ + --key $KEY +``` + +In cases where a ramdisk is required by the guest, pvmfw must also verify it. To +do so, it must be covered by a hash descriptor in the VBMeta of the kernel: + +``` +cp /tmp/ +avbtool add_hash_footer --image /tmp/ \ + --partition_name $INITRD_NAME \ + --dynamic_partition_size \ + --key $KEY +avbtool add_hash_footer --image \ + --partition_name boot \ + --dynamic_partition_size \ + --include_descriptor_from_image /tmp/ \ + --key $KEY +``` + +Note that the `/tmp/` file is only created to temporarily hold the +hash descriptor to be added to the kernel footer and that the unsigned +`` should be passed to the VMM when booting a pVM. + +The name of the AVB "partition" for the ramdisk (`$INITRD_NAME`) can be used by +the signer to specify if pvmfw must consider the guest to be debuggable +(`initrd_debug`) or not (`initrd_normal`), which will be reflected in the +certificate of the guest and will affect the secrets being provisioned. + +If pVM guest kernels are built and/or packaged using the Android Build system, +the signing described above is recommended to be done through an +`avb_add_hash_footer` Soong module (see [how we sign the Microdroid +kernel][soong-udroid]). + +[soong-udroid]: https://cs.android.com/android/platform/superproject/+/master:packages/modules/Virtualization/microdroid/Android.bp;l=427;drc=ca0049be4d84897b8c9956924cfae506773103eb