Part 1: Introduction to generation 2 virtual machines
Part 2: Networking and boot order
Part 3: Storage
Part 4: Keyboard for Windows 8 & Windows Server 2012
Part 5: Kernel debugging
Part 6: Secure Boot
Part 7: FAQ
Part 8: Manually migrating generation 1 virtual machines to generation 2
Part 9: Installing from ISO
Part 10: Utility for converting generation 1 virtual machines to generation 2 (Convert-VMGeneration)
This part of the series on generation 2 virtual machines in Hyper-V looks at a new feature – Secure Boot. Secure Boot is essentially a signature checking mechanism during the OS loader to validate that only approved components are allowed to be run. Secure Boot is defined as part of the UEFI specification. Hyper-V implements a subset which allows Windows 8 and Windows 8.1 with default policies to load in a virtual machine with Secure Boot enabled.
While I’m not going into huge detail about how Secure Boot works, it essentially comes down to the contents of four NVRAM variables, some of which are read-only, other read/write. (There are a few other variables in NVRAM too.) The four variables of relevance are:
The public platform key. This contains the public half of the platform key pair, PKpub, which allows the platform “owner” (think of this as the OEM, or in the Hyper-V case, Microsoft), who has the private half of the key, PKpriv. to change platform ownership or enroll a Key Exchange Key. In the physical world, the OEM will keep PKpriv private. This is no different in our implementation - the key pair was generated/signed by the Microsoft corporate PKI infrastructure and the private key secured appropriately.
The Key Exchange Key signature database. The keys in this database establish a trust relationship between the operating system and the platform firmware. In other words, if the operating system attempts to update the authenticated variables db or dbx using a SetVariable() call, the call must have a root of trust back to a certificate held in KEK. In the Hyper-V case, we have a single certificate in this database which allows updates from Windows Update to safely update db and dbx.
db is a essentially an allow list for operating system loaders. Any operating system which starts when secure boot is enabled must have a root of trust to a key in this database. In the RTM version of Windows 8.1, a single key is in this database which allows ‘PRSS’-signed builds of Windows 8 and Windows 8.1 to load. Don’t worry about the term PRSS. That’s an internal Microsoft term. Just suffice it to say that the builds of Windows which go out to customers are signed this way. Internal daily builds and milestone exit builds (such as Windows 8.1 Preview) are not signed the same.
dbx is the converse of db and is a disallow list. In the RTM version of Windows 8.1, no keys are in this database.
While a virtualization platform such as Hyper-V could model itself entirely on a physical platform for features, we don’t entirely for UEFI or secure boot. And with good reason. For example, we don’t support capsule updates (which don’t make sense as the firmware update can be done from the parent partition by updating the worker process). We don’t support authenticated variables outside of the secure boot namespace. We only support specific authenticated variables in the secure boot namespace. We don’t support time based authenticated variables. And potentially the one of most interest – we don’t support setup mode. Strictly, these also means we don’t have a fully compliant UEFI implementation.
So what is setup mode and why should you care? On a physical box, if no PK is enrolled, the system is said to be in setup mode. In this mode, no authentication is required to modify PK or KEK. Once the PK is enrolled, the firmware switches to user mode. (The actual mode is indicated by another UEFI variable, SetupMode.) By having setup mode, it allows the end user (or OEM) to specify exactly what operating systems can and cannot run when Secure Boot is enabled by pre-populating db/dbx, and (assuming those operating systems are signed appropriately) allow those operating systems to perform secure updates to db/dbx if there is a root of trust in the update chained to a key in KEK.
In Hyper-V, the firmware for a virtual machine is always in user mode. PK and KEK are pre-populated and cannot be changed. db and dbx are also prepopulated, but can be changed. In fact, db and dbx are a little more interesting in the Hyper-V case as this is where it differs somewhat from a physical platform.
On a physical platform, there is a single db and dbx. This is true also in Hyper-V from the perspective of a UEFI application, such as an operating system, running in a VM. However, from the perspective of the parent partition, there are actually two instances of db and dbx.
The first instance is global, non-transient and applies to all VMs. When a VM is powered on, regardless of any subsequent updates it might have securely made to db/dbx, the global contents are always present. The second instance is VM-local and transient. In reality, the local copies of db and dbx are held in the configuration file for the VM (as are other NVRAM variables such as those to define boot order and entries). What is actually projected into the VM is the union of the global and VM-local db and dbx variables.
Let’s take an example to make all this a little clearer. Let’s pretend that in a far-off parallel universe (bear with me here, and please no comments!), that Microsoft decides Windows 8 is, in-fact, malware, and should fail to boot on machines with Secure Boot enabled. A few things could be done to make this happen:
First the physical world:
- Microsoft could work with OEMs to update dbx to revoke the signature of the Windows 8 loader. Assuming the OEMs all agree, they build a new version of the firmware to be downloaded by customers, and pre-populate it on new machines coming off the factory floor.
- While most new machines bought from those OEMs off the shelf would be caught, for machines in end users hands, the end user would need to update their firmware. This is, a relatively rare occurrence in the real world for client, less so for server. (Which does remind me, I ought to update my machines as I know at least two are out of date….).
- Or it could be done as a capsule update (assuming the firmware supports such a mechanism) allowing the firmware to be updated safely in the DXE stage of UEFI startup.
- Or it could be done by an update through Windows Update to add the signature of Windows 8 to dbx. Remember from above, the (authenticated variable-) update must chain to a root of trust to a key in KEK. This will mostly be fine, as all Windows 8+ logo machines have KEK pre-populated such that this is viable. (Of course, remember advanced users could enter setup mode from firmware if the OEM supports this, and alter PK/KEK. So it’s not 100% reliable).
- Remember also that the end user could always re-flash their firmware to a previous version, removing the update; turn off Windows Update allowing Windows 8 to once again load with Secure Boot enabled; or remove the root of trust for the dbx Windows Update from KEK. Of course, none of these are good ideas!
And compare to the virtual world:
- Remember Hyper-V doesn’t entirely model itself on a physical machine. We have the VM which thinks it is a physical machine, and the parent partition running at a higher level of trust.
- So, an update from Windows Update running inside the guest would work, the same as for a physical platform.
- But, as PK, KEK and the global db/dbx are maintained by the parent partition which runs Windows, we can simply push out a regular update on the parent partition to add the Windows 8 signature to the binary containing the global copy of dbx. And here’s the important bit – this update does NOT need to chain to a root of trust to a key in KEK. In fact, we can push out an update which patches any of the global secure boot variables.
OK, that was a little more detail than I thought! Let’s get back to end-user land. Secure Boot is a simple on-off setting on a per-VM basis. For the most part, you won’t need to worry about it assuming you are running Windows 8 or Windows 8.1 (and the server counterparts) as a guest operating system. Here’s the salient points to take away.
- When you create a new virtual machine, Secure Boot is enabled by default. The default cannot be changed.
- The setting is on the Firmware tab of the VM settings
- Secure Boot can only be enabled or disabled while a VM is powered off
- The PowerShell equivalent to this checkbox is Set-VMFirmware –EnableSecureBoot On|Off
- (Get-VMFirmware $VM).SecureBoot will return the current setting
- When Secure Boot fails, it will typically look like this:
(Nice logo by the way – yes, that was one of my Friday afternoon jobs for this release. I never did care much for that Windows Server 2003/2003 R2 era brick theme anyway. Sorry, marketing department!)
- Non-Windows guest operating systems will likely not work with Secure Boot enabled due to not having a root of trust back to a key present in KEK
In the next part, I’ll go through some FAQs about generation 2 virtual machines before getting onto the topic of migration from generation 1 to generation 2.