Skip to main content

openhcl_attestation_protocol/
vmgs.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Include modules that define the data structures of VMGS entries.
5
6use zerocopy::FromBytes;
7use zerocopy::Immutable;
8use zerocopy::IntoBytes;
9use zerocopy::KnownLayout;
10
11/// Number of the key protector entries.
12/// One for ingress, and one for egress
13pub const NUMBER_KP: usize = 2;
14
15/// DEK buffer size
16pub const DEK_BUFFER_SIZE: usize = 512;
17
18/// GSP buffer size
19pub const GSP_BUFFER_SIZE: usize = 512;
20
21/// Size of the `FileId::KEY_PROTECTOR` VMGS file entry.
22pub const KEY_PROTECTOR_SIZE: usize = size_of::<KeyProtector>();
23
24/// DEK key protector entry.
25#[repr(C)]
26#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
27pub struct DekKp {
28    /// DEK buffer
29    pub dek_buffer: [u8; DEK_BUFFER_SIZE],
30}
31
32/// GSP key protector entry.
33#[repr(C)]
34#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
35pub struct GspKp {
36    /// GSP data size
37    pub gsp_length: u32,
38    /// GSP buffer
39    pub gsp_buffer: [u8; GSP_BUFFER_SIZE],
40}
41
42/// The data format of the `FileId::KEY_PROTECTOR` entry in the VMGS file.
43#[repr(C)]
44#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
45pub struct KeyProtector {
46    /// Array of DEK entries
47    pub dek: [DekKp; NUMBER_KP],
48    /// Array of GSP entries
49    pub gsp: [GspKp; NUMBER_KP],
50    /// Index of the activate entry
51    pub active_kp: u32,
52}
53
54/// The data format of the host/fabric-provided key protector.
55#[repr(C)]
56#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
57pub struct KeyProtectorById {
58    /// Id
59    pub id_guid: guid::Guid,
60    /// Ported (boolean)
61    pub ported: u8,
62    /// Padding
63    pub pad: [u8; 3],
64}
65
66/// Maximum size of the `agent_data`.
67pub const AGENT_DATA_MAX_SIZE: usize = 2048;
68
69/// The data format of the `FileId::ATTEST` entry in the VMGS file.
70#[repr(C)]
71#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
72pub struct SecurityProfile {
73    /// the agent data used during attestation requests
74    pub agent_data: [u8; AGENT_DATA_MAX_SIZE],
75}
76
77/// VMGS hardware key protector entry that includes the metadata of
78/// local hardware sealing with AES-CBC-HMAC-SHA256.
79///
80/// Version 1 is incompatible with newer versions.
81/// Version 2 or newer is forward-compatible if header.mix_measurement is not set.
82pub const HW_KEY_PROTECTOR_VERSION_1: u32 = 1;
83pub const HW_KEY_PROTECTOR_VERSION_2: u32 = 2;
84pub const HW_KEY_PROTECTOR_CURRENT_VERSION: u32 = HW_KEY_PROTECTOR_VERSION_2;
85
86/// The size of the `FileId::HW_KEY_PROTECTOR` entry in the VMGS file.
87pub const HW_KEY_PROTECTOR_SIZE: usize = size_of::<HardwareKeyProtector>();
88
89/// AES-GCM key size
90pub const AES_GCM_KEY_LENGTH: usize = 32;
91
92/// AES-CBC key size
93pub const AES_CBC_KEY_LENGTH: usize = AES_GCM_KEY_LENGTH;
94
95/// AES-CBC IV size
96pub const AES_CBC_IV_LENGTH: usize = 16;
97
98/// HMAC-SHA-256 key size
99pub const HMAC_SHA_256_KEY_LENGTH: usize = 32;
100
101/// The header of [`HardwareKeyProtector`].
102#[repr(C)]
103#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
104pub struct HardwareKeyProtectorHeader {
105    /// Version of the format
106    pub version: u32,
107    /// Size of the [`HardwareKeyProtector`] data blob
108    pub length: u32,
109    /// TCB version obtained from the hardware
110    pub tcb_version: u64,
111    /// Whether to mix the measurement in hardware key derivation
112    /// Only supported in version 2 and above
113    pub mix_measurement: u8,
114    /// Reserved bytes for future use
115    pub _reserved: [u8; 7],
116}
117
118impl HardwareKeyProtectorHeader {
119    /// Create a `HardwareKeyProtectorHeader` instance.
120    pub fn new(version: u32, length: u32, tcb_version: u64, mix_measurement: u8) -> Self {
121        Self {
122            version,
123            length,
124            tcb_version,
125            mix_measurement,
126            _reserved: [0; 7],
127        }
128    }
129}
130
131/// The data format of the `FileId::HW_KEY_PROTECTOR` entry in the VMGS file.
132#[repr(C)]
133#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
134pub struct HardwareKeyProtector {
135    /// Header
136    pub header: HardwareKeyProtectorHeader,
137    /// Random IV for AES-CBC
138    pub iv: [u8; AES_CBC_IV_LENGTH],
139    /// Encrypted key
140    pub ciphertext: [u8; AES_GCM_KEY_LENGTH],
141    /// HMAC-SHA-256 of [header, iv, ciphertext]
142    pub hmac: [u8; HMAC_SHA_256_KEY_LENGTH],
143}
144
145/// Maximum size of the `guest_secret_key`.
146pub const GUEST_SECRET_KEY_MAX_SIZE: usize = 2048;
147
148/// The data format of the `FileId::GUEST_SECRET_KEY` entry in the VMGS file.
149#[repr(C)]
150#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
151pub struct GuestSecretKey {
152    /// the guest secret key to be provisioned to vTPM
153    pub guest_secret_key: [u8; GUEST_SECRET_KEY_MAX_SIZE],
154}
155
156#[cfg(test)]
157mod tests {
158    use super::*;
159
160    #[test]
161    fn hardware_key_protector_header_new() {
162        let h = HardwareKeyProtectorHeader::new(2, 104, 0x1234, 1);
163        assert_eq!(h.version, 2);
164        assert_eq!(h.length, 104);
165        assert_eq!(h.tcb_version, 0x1234);
166        assert_eq!(h.mix_measurement, 1);
167        assert_eq!(h._reserved, [0; 7]);
168    }
169}