Interact with Azure VM vTPM (Part 0)
How to prove a VM is accually on Azure
0. Intro
Recently, I have been working on Remote Attestation, and because of company need the service to be scalable, instead of the real physical Linux machine, with physical TPM, we need to deploy it on to a Cloud Provider. I start to work on how to implement remotly attestation on Azure VMs.
The goal of this series of blog is to create a system can achieve the following goal.
- Verify this is a VM running on Microsoft Azure
- Remotely verify the VM's bootchain
- Remotely verify system runtime through IMA
Now I have a clear goal and it is time to do some research.
Azure provide a custom Attestation service, called Microsoft Azure Attestation. This service is Azure dependent, and I want to avoid using Microsoft only method to achieve this, and I dont want the attestation process envolve making RESTAPI call to Azure services.
1. Requirement
This verification process need the system to have a vTPM enabled. This kind of VM can be created by enable --enable-vtpm true flag.
Create a VM with vTPM and enable Secure Boot using Azure CLI
$ az vm create -n "${az_vm_name}" \
-g "${az_resource_group}" \
--image "${image_version_id}" \
--admin-username core \
--security-type TrustedLaunch \
--enable-vtpm true \
--enable-secure-boot true
2. Verify TPM in the VM
After the VM is spinned up, check if the TPM exist, using tpm2-tools.
Running the following command to check if TPM is working.
$ sudo tpm2_getcap properties-fixed
And check the output value.
TPM2_PT_FAMILY_INDICATOR:
raw: 0x322E3000
value: "2.0"
TPM2_PT_LEVEL:
raw: 0
TPM2_PT_REVISION:
raw: 0x8A
value: 1.38
TPM2_PT_DAY_OF_YEAR:
raw: 0x19
TPM2_PT_YEAR:
raw: 0x7E1
TPM2_PT_MANUFACTURER:
raw: 0x4D534654
value: "MSFT"
...
By the output, we can see the TPM manufacturer is Microsoft.
3. Extract Certification from TPM
1. Normal TPM
In a normal TPM, we can extract EKCert check if that EK keypair is originated from a real TPM, by verifying EKCert agaist Manufacture's CA public key.
We can extract EKpub from TPM using the following command.
$ sudo tpm2_readpublic -c 0x81010001 -o ek.pub
And get the following output:
name: 000b75e26100d099854a0e6257a0d5d4f536771bfa3c3c6180f67305c42294051e85
qualified name: 000b8443eb529b3fd108a6d2c13d8f65ffe1d3b37363d8d83487355c5408affb1f2f
name-alg:
value: sha256
raw: 0xb
attributes:
value: fixedtpm|fixedparent|sensitivedataorigin|adminwithpolicy|restricted|decrypt
raw: 0x300b2
type:
value: rsa
raw: 0x1
exponent: 65537
bits: 2048
...
We extracted the vTPM EKpub from the commandline, now we just need to generate EKCert and we can verify it just like a regular TPM.
So I run the following command.
$ sudo tpm2_getekcertificate -u ek.pub -o ekcert.pem
ERROR: No EK server address found for manufacturer.
ERROR: Please specify an EK server address on the command line.
ERROR: Unable to run tpm2_getekcertificate
It did not work, and after a quick Google search I did not find what is Azure's EK server address.
2. Azure TPM
Now I am in a weird position, I cannot use EKCert to verify this tpm is from a real Azure vTPM or not.
After digging through some Azure documents, it is very hard to find information about TPM on Azure. After a while I finally found this page, Confidential VM Guest Attestation Design Detail. And it introduced that instead of signing an EKCert, on Azure vTPM, Azure signed an AK and make an AKCert aviliable. And it also included the handle for the AKCert and that AK which can be used to establish as an root of trust.
| Name | NV Index | Size (bytes) | Description |
|---|---|---|---|
| Attestation Report | 0x01400001 | 2600 | Azure-defined format with the hardware report embedded. |
| Report Data | 0x01400002 | 64 | The report data to be included in the Runtime Data. |
| vTPM AK Cert | 0x01C101D0 | 4096 | The certificate used to verify the TPM Quote signed by the vTPM AK. |
| vTPM AK | 0x81000003 | Depending on the key type | The key used to sign the TPM Quote. |
Now we finally have something to verify against Azure.
3. Extract AKCert
We can run the following command to use tpm2-tools to extract the signed AKCert.
$ sudo tpm2_nvread -C o 0x01C101D0 -o ak_cert.der
This command extracted the AKCert from vTPM to file ak_cert.der. And we can view the information of the certificate like this.
$ openssl x509 -inform der -in ak_cert.der -text -noout
We can also convert this der format into pem, for future use
$ openssl x509 -inform DER -in ak_cert.der -out ak_cert.pem
With the AKCert we can verify it against Microsoft's TPM CA to verify this Cert is signed by Microsoft, Microsoft vTPM CA Cert.
Download Microsoft's CA, in this case I downloaded the CA3 cer file. It's already in PEM format, we can verify AKCert against it.
$ openssl verify -partial_chain -CAfile azure_ca3.cer ak_cert.pem
ak_cert.pem: OK
Now we can extract the pubkey portion of the Microsft signed AK from this AKCert.
$ openssl x509 -inform der -in ak_cert.der -pubkey -noout > ak_pub_from_cert.pem
Now we get the AKpub from the AKCert which is signed by Microsoft.
4. Extract AKpub and compare
Run the following command to extract the public part of the AK from vTPM.
$ sudo tpm2_readpublic -c 0x81000003 -f pem -o ak_pub.pem
Now we can compare the AK is the same AK which signed by Microsoft.
$ cmp -s ak_pub.pem ak_pub_from_cert.pem
$ echo $?
0
These two AKpubs are the same that means we can establish trust of this AK is originated from Microsoft Azure.
However, this does not prove that the VM we are currently interacting with actually possesses the corresponding private key for that public key. So this could be defeated by a classic replay attack.
A malicious actor could:
- Spin up one legitimate Azure Trusted VM.
- Follow this blog's steps to extract the ak_cert.der and ak_pub.pem files. These are public information.
- Shut down that VM.
- Spin up a malicious VM (on any cloud or on-premise) that has no vTPM at all.
When a verifier asks this malicious VM to prove its identity, it simply sends back the stolen (but valid) ak_cert.der and ak_pub.pem files.
The verifier, following only the steps in this blog post, would run openssl verify and cmp. Both checks would pass, and the verifier would falsely conclude the malicious VM is a genuine Azure VM.
We will introduce challeges to force the VM to use its private AK, that way we can stop the replay attack and we will also continue extend the trust to other key and other part of the system in the next blog post.