1#![cfg(target_os = "linux")]
10#![forbid(unsafe_code)]
11
12mod crypto;
13mod hardware_key_sealing;
14mod igvm_attest;
15mod key_protector;
16mod secure_key_release;
17mod vmgs;
18
19pub use igvm_attest::Error as IgvmAttestError;
20pub use igvm_attest::IgvmAttestRequestHelper;
21pub use igvm_attest::ak_cert::parse_response as parse_ak_cert_response;
22
23use ::vmgs::EncryptionAlgorithm;
24use ::vmgs::Vmgs;
25use cvm_tracing::CVM_ALLOWED;
26use get_protocol::dps_json::GuestStateEncryptionPolicy;
27use guest_emulation_transport::GuestEmulationTransportClient;
28use guest_emulation_transport::api::GspExtendedStatusFlags;
29use guest_emulation_transport::api::GuestStateProtection;
30use guest_emulation_transport::api::GuestStateProtectionById;
31use guid::Guid;
32use hardware_key_sealing::HardwareDerivedKeys;
33use hardware_key_sealing::HardwareKeyProtectorExt as _;
34use key_protector::GetKeysFromKeyProtectorError;
35use key_protector::KeyProtectorExt as _;
36use mesh::MeshPayload;
37use openhcl_attestation_protocol::igvm_attest::get::runtime_claims::AttestationVmConfig;
38use openhcl_attestation_protocol::vmgs::AES_GCM_KEY_LENGTH;
39use openhcl_attestation_protocol::vmgs::HardwareKeyProtector;
40use openhcl_attestation_protocol::vmgs::KeyProtector;
41use openhcl_attestation_protocol::vmgs::SecurityProfile;
42use openssl::pkey::Private;
43use openssl::rsa::Rsa;
44use pal_async::local::LocalDriver;
45use secure_key_release::VmgsEncryptionKeys;
46use static_assertions::const_assert_eq;
47use std::fmt::Debug;
48use tee_call::TeeCall;
49use thiserror::Error;
50use zerocopy::FromZeros;
51use zerocopy::IntoBytes;
52
53#[derive(Debug, Error)]
55#[error(transparent)]
56pub struct Error(AttestationErrorInner);
57
58impl<T: Into<AttestationErrorInner>> From<T> for Error {
59 fn from(value: T) -> Self {
60 Self(value.into())
61 }
62}
63
64#[derive(Debug, Error)]
65enum AttestationErrorInner {
66 #[error("read security profile from vmgs")]
67 ReadSecurityProfile(#[source] vmgs::ReadFromVmgsError),
68 #[error("failed to get derived keys")]
69 GetDerivedKeys(#[source] GetDerivedKeysError),
70 #[error("failed to read key protector from vmgs")]
71 ReadKeyProtector(#[source] vmgs::ReadFromVmgsError),
72 #[error("failed to read key protector by id from vmgs")]
73 ReadKeyProtectorById(#[source] vmgs::ReadFromVmgsError),
74 #[error("failed to unlock vmgs data store")]
75 UnlockVmgsDataStore(#[source] UnlockVmgsDataStoreError),
76 #[error("failed to read guest secret key from vmgs")]
77 ReadGuestSecretKey(#[source] vmgs::ReadFromVmgsError),
78}
79
80#[derive(Debug, Error)]
81enum GetDerivedKeysError {
82 #[error("failed to get ingress/egress keys from the the key protector")]
83 GetKeysFromKeyProtector(#[source] GetKeysFromKeyProtectorError),
84 #[error("failed to fetch GSP")]
85 FetchGuestStateProtectionById(
86 #[source] guest_emulation_transport::error::GuestStateProtectionByIdError,
87 ),
88 #[error("GSP By Id required, but no GSP By Id found")]
89 GspByIdRequiredButNotFound,
90 #[error("failed to unseal the ingress key using hardware derived keys")]
91 UnsealIngressKeyUsingHardwareDerivedKeys(
92 #[source] hardware_key_sealing::HardwareKeySealingError,
93 ),
94 #[error("failed to get an ingress key from key protector")]
95 GetIngressKeyFromKpFailed,
96 #[error("failed to get an ingress key from guest state protection")]
97 GetIngressKeyFromKGspFailed,
98 #[error("failed to get an ingress key from guest state protection by id")]
99 GetIngressKeyFromKGspByIdFailed,
100 #[error("Encryption cannot be disabled if VMGS was previously encrypted")]
101 DisableVmgsEncryptionFailed,
102 #[error("VMGS encryption is required, but no encryption sources were found")]
103 EncryptionRequiredButNotFound,
104 #[error("failed to seal the egress key using hardware derived keys")]
105 SealEgressKeyUsingHardwareDerivedKeys(#[source] hardware_key_sealing::HardwareKeySealingError),
106 #[error("failed to write to `FileId::HW_KEY_PROTECTOR` in vmgs")]
107 VmgsWriteHardwareKeyProtector(#[source] vmgs::WriteToVmgsError),
108 #[error("failed to get derived key by id")]
109 GetDerivedKeyById(#[source] GetDerivedKeysByIdError),
110 #[error("failed to derive an ingress key")]
111 DeriveIngressKey(#[source] crypto::KbkdfError),
112 #[error("failed to derive an egress key")]
113 DeriveEgressKey(#[source] crypto::KbkdfError),
114}
115
116#[derive(Debug, Error)]
117enum GetDerivedKeysByIdError {
118 #[error("failed to derive an egress key based on current vm bios guid")]
119 DeriveEgressKeyUsingCurrentVmId(#[source] crypto::KbkdfError),
120 #[error("invalid derived egress key size {key_size}, expected {expected_size}")]
121 InvalidDerivedEgressKeySize {
122 key_size: usize,
123 expected_size: usize,
124 },
125 #[error("failed to derive an ingress key based on key protector Id from vmgs")]
126 DeriveIngressKeyUsingKeyProtectorId(#[source] crypto::KbkdfError),
127 #[error("invalid derived egress key size {key_size}, expected {expected_size}")]
128 InvalidDerivedIngressKeySize {
129 key_size: usize,
130 expected_size: usize,
131 },
132}
133
134#[derive(Debug, Error)]
135enum UnlockVmgsDataStoreError {
136 #[error("failed to unlock vmgs with the existing egress key")]
137 VmgsUnlockUsingExistingEgressKey(#[source] ::vmgs::Error),
138 #[error("failed to unlock vmgs with the existing ingress key")]
139 VmgsUnlockUsingExistingIngressKey(#[source] ::vmgs::Error),
140 #[error("failed to write key protector to vmgs")]
141 WriteKeyProtector(#[source] vmgs::WriteToVmgsError),
142 #[error("failed to read key protector by id to vmgs")]
143 WriteKeyProtectorById(#[source] vmgs::WriteToVmgsError),
144 #[error("failed to update the vmgs encryption key")]
145 UpdateVmgsEncryptionKey(#[source] ::vmgs::Error),
146 #[error("failed to persist all key protectors")]
147 PersistAllKeyProtectors(#[source] PersistAllKeyProtectorsError),
148}
149
150#[derive(Debug, Error)]
151enum PersistAllKeyProtectorsError {
152 #[error("failed to write key protector to vmgs")]
153 WriteKeyProtector(#[source] vmgs::WriteToVmgsError),
154 #[error("failed to read key protector by id to vmgs")]
155 WriteKeyProtectorById(#[source] vmgs::WriteToVmgsError),
156}
157
158const VMGS_KEY_DERIVE_LABEL: &[u8; 7] = b"VMGSKEY";
160
161#[derive(Debug)]
162struct Keys {
163 ingress: [u8; AES_GCM_KEY_LENGTH],
164 decrypt_egress: Option<[u8; AES_GCM_KEY_LENGTH]>,
165 encrypt_egress: [u8; AES_GCM_KEY_LENGTH],
166}
167
168struct KeyProtectorSettings {
170 should_write_kp: bool,
172 use_gsp_by_id: bool,
174 use_hardware_unlock: bool,
176}
177
178struct KeyProtectorById {
180 pub inner: openhcl_attestation_protocol::vmgs::KeyProtectorById,
182 pub found_id: bool,
184}
185
186pub struct HostAttestationSettings {
188 pub refresh_tpm_seeds: bool,
190}
191
192struct DerivedKeyResult {
194 derived_keys: Option<Keys>,
196 key_protector_settings: KeyProtectorSettings,
198 gsp_extended_status_flags: GspExtendedStatusFlags,
200}
201
202pub struct PlatformAttestationData {
204 pub host_attestation_settings: HostAttestationSettings,
206 pub agent_data: Option<Vec<u8>>,
208 pub guest_secret_key: Option<Vec<u8>>,
210}
211
212#[derive(Debug, MeshPayload, Copy, Clone, PartialEq, Eq)]
215pub enum AttestationType {
216 Snp,
218 Tdx,
220 Vbs,
222 Host,
224}
225
226pub async fn initialize_platform_security(
232 get: &GuestEmulationTransportClient,
233 bios_guid: Guid,
234 attestation_vm_config: &AttestationVmConfig,
235 vmgs: &mut Vmgs,
236 tee_call: Option<&dyn TeeCall>,
237 suppress_attestation: bool,
238 driver: LocalDriver,
239 guest_state_encryption_policy: GuestStateEncryptionPolicy,
240 strict_encryption_policy: bool,
241) -> Result<PlatformAttestationData, Error> {
242 tracing::info!(CVM_ALLOWED,
243 tee_type=?tee_call.map(|tee| tee.tee_type()),
244 secure_boot=attestation_vm_config.secure_boot,
245 tpm_enabled=attestation_vm_config.tpm_enabled,
246 tpm_persisted=attestation_vm_config.tpm_persisted,
247 "Reading security profile");
248
249 let SecurityProfile { mut agent_data } = vmgs::read_security_profile(vmgs)
253 .await
254 .map_err(AttestationErrorInner::ReadSecurityProfile)?;
255
256 if suppress_attestation {
259 tracing::info!(CVM_ALLOWED, "Suppressing attestation");
260
261 return Ok(PlatformAttestationData {
262 host_attestation_settings: HostAttestationSettings {
263 refresh_tpm_seeds: false,
264 },
265 agent_data: Some(agent_data.to_vec()),
266 guest_secret_key: None,
267 });
268 }
269
270 let VmgsEncryptionKeys {
271 ingress_rsa_kek,
272 wrapped_des_key,
273 tcb_version,
274 } = if let Some(tee_call) = tee_call {
275 tracing::info!(CVM_ALLOWED, "Retrieving key-encryption key");
276
277 match secure_key_release::request_vmgs_encryption_keys(
279 get,
280 tee_call,
281 vmgs,
282 attestation_vm_config,
283 &mut agent_data,
284 driver,
285 )
286 .await
287 {
288 Ok(VmgsEncryptionKeys {
289 ingress_rsa_kek,
290 wrapped_des_key,
291 tcb_version,
292 }) => {
293 tracing::info!(CVM_ALLOWED, "Successfully retrieved key-encryption key");
294
295 VmgsEncryptionKeys {
296 ingress_rsa_kek,
297 wrapped_des_key,
298 tcb_version,
299 }
300 }
301 Err(e) => {
302 tracing::error!(
304 CVM_ALLOWED,
305 error = &e as &dyn std::error::Error,
306 "Failed to retrieve key-encryption key"
307 );
308
309 VmgsEncryptionKeys::default()
310 }
311 }
312 } else {
313 tracing::info!(CVM_ALLOWED, "Key-encryption key retrieval not required");
314
315 VmgsEncryptionKeys::default()
317 };
318
319 let dek_minimal_size = if wrapped_des_key.is_some() {
321 key_protector::AES_WRAPPED_AES_KEY_LENGTH
322 } else {
323 key_protector::RSA_WRAPPED_AES_KEY_LENGTH
324 };
325
326 tracing::info!(
328 CVM_ALLOWED,
329 dek_minimal_size = dek_minimal_size,
330 "Reading key protector from VMGS"
331 );
332 let mut key_protector = vmgs::read_key_protector(vmgs, dek_minimal_size)
333 .await
334 .map_err(AttestationErrorInner::ReadKeyProtector)?;
335
336 tracing::info!(CVM_ALLOWED, "Reading VM ID from VMGS");
338 let mut key_protector_by_id = match vmgs::read_key_protector_by_id(vmgs).await {
339 Ok(key_protector_by_id) => KeyProtectorById {
340 inner: key_protector_by_id,
341 found_id: true,
342 },
343 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => KeyProtectorById {
344 inner: openhcl_attestation_protocol::vmgs::KeyProtectorById::new_zeroed(),
345 found_id: false,
346 },
347 Err(e) => { Err(AttestationErrorInner::ReadKeyProtectorById(e)) }?,
348 };
349
350 let vm_id_changed = if key_protector_by_id.found_id {
352 let changed = key_protector_by_id.inner.id_guid != bios_guid;
353 if changed {
354 tracing::info!("VM Id has changed since last boot");
355 };
356 changed
357 } else {
358 false
361 };
362
363 let vmgs_encrypted: bool = vmgs.is_encrypted();
364
365 tracing::info!(tcb_version=?tcb_version, vmgs_encrypted = vmgs_encrypted, "Deriving keys");
366 let derived_keys_result = get_derived_keys(
367 get,
368 tee_call,
369 vmgs,
370 &mut key_protector,
371 &mut key_protector_by_id,
372 bios_guid,
373 attestation_vm_config,
374 vmgs_encrypted,
375 ingress_rsa_kek.as_ref(),
376 wrapped_des_key.as_deref(),
377 tcb_version,
378 guest_state_encryption_policy,
379 strict_encryption_policy,
380 )
381 .await
382 .map_err(AttestationErrorInner::GetDerivedKeys)?;
383
384 tracing::info!("Unlocking VMGS");
386 if let Err(e) = unlock_vmgs_data_store(
387 vmgs,
388 vmgs_encrypted,
389 &mut key_protector,
390 &mut key_protector_by_id,
391 derived_keys_result.derived_keys,
392 derived_keys_result.key_protector_settings,
393 bios_guid,
394 )
395 .await
396 {
397 get.event_log_fatal(guest_emulation_transport::api::EventLogId::ATTESTATION_FAILED)
398 .await;
399
400 Err(AttestationErrorInner::UnlockVmgsDataStore(e))?
401 }
402
403 let state_refresh_request_from_gsp = derived_keys_result
404 .gsp_extended_status_flags
405 .state_refresh_request();
406
407 let host_attestation_settings = HostAttestationSettings {
408 refresh_tpm_seeds: { state_refresh_request_from_gsp | vm_id_changed },
409 };
410
411 tracing::info!(
412 CVM_ALLOWED,
413 state_refresh_request_from_gsp = state_refresh_request_from_gsp,
414 vm_id_changed = vm_id_changed,
415 "determine if refreshing tpm seeds is needed"
416 );
417
418 let guest_secret_key = match vmgs::read_guest_secret_key(vmgs).await {
420 Ok(data) => Some(data.guest_secret_key.to_vec()),
421 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => None,
422 Err(e) => return Err(AttestationErrorInner::ReadGuestSecretKey(e).into()),
423 };
424
425 Ok(PlatformAttestationData {
426 host_attestation_settings,
427 agent_data: Some(agent_data.to_vec()),
428 guest_secret_key,
429 })
430}
431
432async fn unlock_vmgs_data_store(
439 vmgs: &mut Vmgs,
440 vmgs_encrypted: bool,
441 key_protector: &mut KeyProtector,
442 key_protector_by_id: &mut KeyProtectorById,
443 derived_keys: Option<Keys>,
444 key_protector_settings: KeyProtectorSettings,
445 bios_guid: Guid,
446) -> Result<(), UnlockVmgsDataStoreError> {
447 let mut new_key = false; let Some(Keys {
450 ingress: new_ingress_key,
451 decrypt_egress: old_egress_key,
452 encrypt_egress: new_egress_key,
453 }) = derived_keys
454 else {
455 tracing::info!(
456 CVM_ALLOWED,
457 "Encryption disabled, skipping unlock vmgs data store"
458 );
459 return Ok(());
460 };
461
462 if !openssl::memcmp::eq(&new_ingress_key, &new_egress_key) {
463 tracing::trace!(CVM_ALLOWED, "EgressKey is different than IngressKey");
464 new_key = true;
465 }
466
467 let mut provision = false;
469 if vmgs_encrypted {
470 tracing::info!(CVM_ALLOWED, "Decrypting vmgs file...");
471 if let Err(e) = vmgs.unlock_with_encryption_key(&new_ingress_key).await {
472 if let Some(key) = old_egress_key {
473 tracing::info!(CVM_ALLOWED, "Old EgressKey found");
476 vmgs.unlock_with_encryption_key(&key)
477 .await
478 .map_err(UnlockVmgsDataStoreError::VmgsUnlockUsingExistingEgressKey)?;
479 } else {
480 Err(UnlockVmgsDataStoreError::VmgsUnlockUsingExistingIngressKey(
481 e,
482 ))?
483 }
484 }
485 } else {
486 tracing::info!(
488 CVM_ALLOWED,
489 "vmgs data store is not encrypted, provisioning."
490 );
491 provision = true;
492 }
493
494 tracing::info!(
495 CVM_ALLOWED,
496 should_write_kp = key_protector_settings.should_write_kp,
497 use_gsp_by_id = key_protector_settings.use_gsp_by_id,
498 use_hardware_unlock = key_protector_settings.use_hardware_unlock,
499 "key protector settings"
500 );
501
502 if key_protector_settings.should_write_kp {
503 vmgs::write_key_protector(key_protector, vmgs)
505 .await
506 .map_err(UnlockVmgsDataStoreError::WriteKeyProtector)?;
507
508 if key_protector_settings.use_gsp_by_id {
509 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
510 .await
511 .map_err(UnlockVmgsDataStoreError::WriteKeyProtectorById)?;
512 }
513 }
514
515 if provision || new_key {
516 vmgs.update_encryption_key(&new_egress_key, EncryptionAlgorithm::AES_GCM)
520 .await
521 .map_err(UnlockVmgsDataStoreError::UpdateVmgsEncryptionKey)?;
522 }
523
524 persist_all_key_protectors(
526 vmgs,
527 key_protector,
528 key_protector_by_id,
529 bios_guid,
530 key_protector_settings,
531 )
532 .await
533 .map_err(UnlockVmgsDataStoreError::PersistAllKeyProtectors)
534}
535
536async fn get_derived_keys(
553 get: &GuestEmulationTransportClient,
554 tee_call: Option<&dyn TeeCall>,
555 vmgs: &mut Vmgs,
556 key_protector: &mut KeyProtector,
557 key_protector_by_id: &mut KeyProtectorById,
558 bios_guid: Guid,
559 attestation_vm_config: &AttestationVmConfig,
560 is_encrypted: bool,
561 ingress_rsa_kek: Option<&Rsa<Private>>,
562 wrapped_des_key: Option<&[u8]>,
563 tcb_version: Option<u64>,
564 guest_state_encryption_policy: GuestStateEncryptionPolicy,
565 strict_encryption_policy: bool,
566) -> Result<DerivedKeyResult, GetDerivedKeysError> {
567 tracing::info!(
568 CVM_ALLOWED,
569 ?guest_state_encryption_policy,
570 strict_encryption_policy,
571 "encryption policy"
572 );
573
574 if matches!(
576 guest_state_encryption_policy,
577 GuestStateEncryptionPolicy::HardwareSealing
578 ) {
579 todo!("hardware sealing")
580 }
581
582 let mut key_protector_settings = KeyProtectorSettings {
583 should_write_kp: true,
584 use_gsp_by_id: false,
585 use_hardware_unlock: false,
586 };
587
588 let mut derived_keys = Keys {
589 ingress: [0u8; AES_GCM_KEY_LENGTH],
590 decrypt_egress: None,
591 encrypt_egress: [0u8; AES_GCM_KEY_LENGTH],
592 };
593
594 let ingress_idx = (key_protector.active_kp % 2) as usize;
596 let egress_idx = if ingress_idx == 0 { 1 } else { 0 } as usize;
597
598 let found_dek = !key_protector.dek[ingress_idx]
599 .dek_buffer
600 .iter()
601 .all(|&x| x == 0);
602
603 let (ingress_key, mut decrypt_egress_key, encrypt_egress_key, no_kek) =
605 if let Some(ingress_kek) = ingress_rsa_kek {
606 let keys = match key_protector.unwrap_and_rotate_keys(
607 ingress_kek,
608 wrapped_des_key,
609 ingress_idx,
610 egress_idx,
611 ) {
612 Ok(keys) => keys,
613 Err(e)
614 if matches!(
615 e,
616 GetKeysFromKeyProtectorError::DesKeyRsaUnwrap(_)
617 | GetKeysFromKeyProtectorError::IngressDekRsaUnwrap(_)
618 ) =>
619 {
620 get.event_log_fatal(
621 guest_emulation_transport::api::EventLogId::DEK_DECRYPTION_FAILED,
622 )
623 .await;
624
625 return Err(GetDerivedKeysError::GetKeysFromKeyProtector(e));
626 }
627 Err(e) => return Err(GetDerivedKeysError::GetKeysFromKeyProtector(e)),
628 };
629 (
630 keys.ingress,
631 keys.decrypt_egress,
632 keys.encrypt_egress,
633 false,
634 )
635 } else {
636 (
637 [0u8; AES_GCM_KEY_LENGTH],
638 None,
639 [0u8; AES_GCM_KEY_LENGTH],
640 true,
641 )
642 };
643
644 let is_gsp_by_id = key_protector_by_id.found_id && key_protector_by_id.inner.ported != 1;
646 let is_gsp = key_protector.gsp[ingress_idx].gsp_length != 0;
647 tracing::info!(
648 CVM_ALLOWED,
649 is_encrypted,
650 is_gsp_by_id,
651 is_gsp,
652 found_dek,
653 "initial vmgs encryption state"
654 );
655 let mut requires_gsp_by_id = is_gsp_by_id;
656
657 let (gsp_response, no_gsp, requires_gsp) = {
659 tracing::info!(CVM_ALLOWED, "attempting GSP");
660
661 let response = get_gsp_data(get, key_protector).await;
662
663 tracing::info!(
664 CVM_ALLOWED,
665 request_data_length_in_vmgs = key_protector.gsp[ingress_idx].gsp_length,
666 no_rpc_server = response.extended_status_flags.no_rpc_server(),
667 requires_rpc_server = response.extended_status_flags.requires_rpc_server(),
668 encrypted_gsp_length = response.encrypted_gsp.length,
669 "GSP response"
670 );
671
672 let no_gsp = response.extended_status_flags.no_rpc_server()
673 || response.encrypted_gsp.length == 0
674 || (matches!(
675 guest_state_encryption_policy,
676 GuestStateEncryptionPolicy::GspById | GuestStateEncryptionPolicy::None
677 ) && (!is_gsp || strict_encryption_policy));
678
679 let requires_gsp = is_gsp
680 || response.extended_status_flags.requires_rpc_server()
681 || (matches!(
682 guest_state_encryption_policy,
683 GuestStateEncryptionPolicy::GspKey
684 ) && strict_encryption_policy);
685
686 if is_encrypted && !requires_gsp_by_id && !requires_gsp && !found_dek {
689 requires_gsp_by_id = true;
690 }
691
692 (response, no_gsp, requires_gsp)
693 };
694
695 let (gsp_response_by_id, no_gsp_by_id) = if no_gsp || requires_gsp_by_id {
698 tracing::info!(CVM_ALLOWED, "attempting GSP By Id");
699
700 let gsp_response_by_id = get
701 .guest_state_protection_data_by_id()
702 .await
703 .map_err(GetDerivedKeysError::FetchGuestStateProtectionById)?;
704
705 let no_gsp_by_id = gsp_response_by_id.extended_status_flags.no_registry_file()
706 || (matches!(
707 guest_state_encryption_policy,
708 GuestStateEncryptionPolicy::None
709 ) && (!requires_gsp_by_id || strict_encryption_policy));
710
711 if no_gsp_by_id && requires_gsp_by_id {
712 Err(GetDerivedKeysError::GspByIdRequiredButNotFound)?
713 }
714
715 (gsp_response_by_id, no_gsp_by_id)
716 } else {
717 (GuestStateProtectionById::new_zeroed(), true)
718 };
719
720 if (no_kek && found_dek) || (no_gsp && requires_gsp) || (no_gsp_by_id && requires_gsp_by_id) {
722 let (hardware_key_protector, hardware_derived_keys) = if let Some(tee_call) = tee_call {
724 let hardware_key_protector = match vmgs::read_hardware_key_protector(vmgs).await {
725 Ok(hardware_key_protector) => Some(hardware_key_protector),
726 Err(e) => {
727 tracing::warn!(
729 CVM_ALLOWED,
730 error = &e as &dyn std::error::Error,
731 "failed to read HW_KEY_PROTECTOR from Vmgs"
732 );
733 None
734 }
735 };
736
737 let hardware_derived_keys = tee_call.supports_get_derived_key().and_then(|tee_call| {
738 if let Some(hardware_key_protector) = &hardware_key_protector {
739 match HardwareDerivedKeys::derive_key(
740 tee_call,
741 attestation_vm_config,
742 hardware_key_protector.header.tcb_version,
743 ) {
744 Ok(hardware_derived_key) => Some(hardware_derived_key),
745 Err(e) => {
746 tracing::warn!(
748 CVM_ALLOWED,
749 error = &e as &dyn std::error::Error,
750 "failed to derive hardware keys using HW_KEY_PROTECTOR",
751 );
752 None
753 }
754 }
755 } else {
756 None
757 }
758 });
759
760 (hardware_key_protector, hardware_derived_keys)
761 } else {
762 (None, None)
763 };
764
765 if let (Some(hardware_key_protector), Some(hardware_derived_keys)) =
766 (hardware_key_protector, hardware_derived_keys)
767 {
768 derived_keys.ingress = hardware_key_protector
769 .unseal_key(&hardware_derived_keys)
770 .map_err(GetDerivedKeysError::UnsealIngressKeyUsingHardwareDerivedKeys)?;
771 derived_keys.decrypt_egress = None;
772 derived_keys.encrypt_egress = derived_keys.ingress;
773
774 key_protector_settings.should_write_kp = false;
775 key_protector_settings.use_hardware_unlock = true;
776
777 tracing::warn!(
778 CVM_ALLOWED,
779 "Using hardware-derived key to recover VMGS DEK"
780 );
781
782 return Ok(DerivedKeyResult {
783 derived_keys: Some(derived_keys),
784 key_protector_settings,
785 gsp_extended_status_flags: gsp_response.extended_status_flags,
786 });
787 } else {
788 if no_kek && found_dek {
789 Err(GetDerivedKeysError::GetIngressKeyFromKpFailed)?
790 } else if no_gsp && requires_gsp {
791 Err(GetDerivedKeysError::GetIngressKeyFromKGspFailed)?
792 } else {
793 Err(GetDerivedKeysError::GetIngressKeyFromKGspByIdFailed)?
795 }
796 }
797 }
798
799 tracing::info!(
800 CVM_ALLOWED,
801 kek = !no_kek,
802 gsp = !no_gsp,
803 gsp_by_id = !no_gsp_by_id,
804 "Encryption sources"
805 );
806
807 if no_kek && no_gsp && no_gsp_by_id {
809 if is_encrypted {
810 Err(GetDerivedKeysError::DisableVmgsEncryptionFailed)?
811 }
812 match guest_state_encryption_policy {
813 GuestStateEncryptionPolicy::GspById
815 | GuestStateEncryptionPolicy::GspKey
816 | GuestStateEncryptionPolicy::HardwareSealing => {
817 Err(GetDerivedKeysError::EncryptionRequiredButNotFound)?
818 }
819 GuestStateEncryptionPolicy::Auto | GuestStateEncryptionPolicy::None => {
820 tracing::info!(CVM_ALLOWED, "No VMGS encryption used.");
821
822 return Ok(DerivedKeyResult {
823 derived_keys: None,
824 key_protector_settings,
825 gsp_extended_status_flags: gsp_response.extended_status_flags,
826 });
827 }
828 }
829 }
830
831 let hardware_derived_keys = tee_call
833 .and_then(|tee_call| tee_call.supports_get_derived_key())
834 .and_then(|tee_call| {
835 if let Some(tcb_version) = tcb_version {
836 match HardwareDerivedKeys::derive_key(tee_call, attestation_vm_config, tcb_version)
837 {
838 Ok(keys) => Some(keys),
839 Err(e) => {
840 tracing::warn!(
842 CVM_ALLOWED,
843 error = &e as &dyn std::error::Error,
844 "failed to derive hardware keys"
845 );
846 None
847 }
848 }
849 } else {
850 None
851 }
852 });
853
854 if no_gsp && no_gsp_by_id {
856 tracing::info!(CVM_ALLOWED, "No GSP used with SKR");
857
858 derived_keys.ingress = ingress_key;
859 derived_keys.decrypt_egress = decrypt_egress_key;
860 derived_keys.encrypt_egress = encrypt_egress_key;
861
862 if let Some(hardware_derived_keys) = hardware_derived_keys {
863 let hardware_key_protector = HardwareKeyProtector::seal_key(
864 &hardware_derived_keys,
865 &derived_keys.encrypt_egress,
866 )
867 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
868 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
869 .await
870 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
871
872 tracing::info!(CVM_ALLOWED, "hardware key protector updated (no GSP used)");
873 }
874
875 return Ok(DerivedKeyResult {
876 derived_keys: Some(derived_keys),
877 key_protector_settings,
878 gsp_extended_status_flags: gsp_response.extended_status_flags,
879 });
880 }
881
882 if (no_kek && no_gsp) || requires_gsp_by_id {
885 let derived_keys_by_id =
886 get_derived_keys_by_id(key_protector_by_id, bios_guid, gsp_response_by_id)
887 .map_err(GetDerivedKeysError::GetDerivedKeyById)?;
888
889 if no_kek && no_gsp {
890 if matches!(
891 guest_state_encryption_policy,
892 GuestStateEncryptionPolicy::GspById | GuestStateEncryptionPolicy::Auto
893 ) {
894 tracing::info!(CVM_ALLOWED, "Using GspById");
895 } else {
896 tracing::warn!(CVM_ALLOWED, "Allowing GspById");
906 };
907
908 key_protector_settings.should_write_kp = false;
910 key_protector_settings.use_gsp_by_id = true;
911
912 return Ok(DerivedKeyResult {
913 derived_keys: Some(derived_keys_by_id),
914 key_protector_settings,
915 gsp_extended_status_flags: gsp_response.extended_status_flags,
916 });
917 }
918
919 derived_keys.ingress = derived_keys_by_id.ingress;
920
921 tracing::info!(CVM_ALLOWED, "Converting GSP method.");
922 }
923
924 let egress_seed;
925 let mut ingress_seed = None;
926
927 if requires_gsp_by_id || no_gsp {
933 if found_dek {
936 if requires_gsp_by_id {
937 ingress_seed = Some(
938 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize]
939 .to_vec(),
940 );
941 } else {
942 derived_keys.ingress = ingress_key;
943 }
944 }
945
946 if no_gsp {
948 egress_seed =
949 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize].to_vec();
950 key_protector_settings.use_gsp_by_id = true;
951 } else {
952 egress_seed =
953 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
954 }
955 } else {
956 if gsp_response.decrypted_gsp[ingress_idx].length == 0
959 && gsp_response.decrypted_gsp[egress_idx].length == 0
960 {
961 tracing::info!(CVM_ALLOWED, "Applying GSP.");
962
963 egress_seed =
966 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
967
968 if !no_kek {
971 derived_keys.ingress = ingress_key;
972 }
973 } else {
974 tracing::info!(CVM_ALLOWED, "Using existing GSP.");
975
976 ingress_seed = Some(
977 gsp_response.decrypted_gsp[ingress_idx].buffer
978 [..gsp_response.decrypted_gsp[ingress_idx].length as usize]
979 .to_vec(),
980 );
981
982 if gsp_response.decrypted_gsp[egress_idx].length == 0 {
983 egress_seed =
985 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
986 } else {
987 egress_seed = gsp_response.decrypted_gsp[egress_idx].buffer
992 [..gsp_response.decrypted_gsp[egress_idx].length as usize]
993 .to_vec();
994 key_protector_settings.should_write_kp = false;
995 decrypt_egress_key = Some(encrypt_egress_key);
996 }
997 }
998 }
999
1000 if let Some(seed) = ingress_seed {
1002 derived_keys.ingress = crypto::derive_key(&ingress_key, &seed, VMGS_KEY_DERIVE_LABEL)
1003 .map_err(GetDerivedKeysError::DeriveIngressKey)?;
1004 }
1005
1006 derived_keys.decrypt_egress = decrypt_egress_key
1008 .map(|key| crypto::derive_key(&key, &egress_seed, VMGS_KEY_DERIVE_LABEL))
1009 .transpose()
1010 .map_err(GetDerivedKeysError::DeriveEgressKey)?;
1011
1012 derived_keys.encrypt_egress =
1013 crypto::derive_key(&encrypt_egress_key, &egress_seed, VMGS_KEY_DERIVE_LABEL)
1014 .map_err(GetDerivedKeysError::DeriveEgressKey)?;
1015
1016 if key_protector_settings.should_write_kp {
1017 key_protector.gsp[egress_idx]
1019 .gsp_buffer
1020 .copy_from_slice(&gsp_response.encrypted_gsp.buffer);
1021 key_protector.gsp[egress_idx].gsp_length = gsp_response.encrypted_gsp.length;
1022
1023 if let Some(hardware_derived_keys) = hardware_derived_keys {
1024 let hardware_key_protector = HardwareKeyProtector::seal_key(
1025 &hardware_derived_keys,
1026 &derived_keys.encrypt_egress,
1027 )
1028 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
1029
1030 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
1031 .await
1032 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
1033
1034 tracing::info!(CVM_ALLOWED, "hardware key protector updated");
1035 }
1036 }
1037
1038 if matches!(
1039 guest_state_encryption_policy,
1040 GuestStateEncryptionPolicy::GspKey | GuestStateEncryptionPolicy::Auto
1041 ) {
1042 tracing::info!(CVM_ALLOWED, "Using Gsp");
1043 } else {
1044 tracing::warn!(CVM_ALLOWED, "Allowing Gsp");
1051 }
1052
1053 Ok(DerivedKeyResult {
1054 derived_keys: Some(derived_keys),
1055 key_protector_settings,
1056 gsp_extended_status_flags: gsp_response.extended_status_flags,
1057 })
1058}
1059
1060fn get_derived_keys_by_id(
1062 key_protector_by_id: &mut KeyProtectorById,
1063 bios_guid: Guid,
1064 gsp_response_by_id: GuestStateProtectionById,
1065) -> Result<Keys, GetDerivedKeysByIdError> {
1066 let new_egress_key = crypto::derive_key(
1073 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
1074 bios_guid.as_bytes(),
1075 VMGS_KEY_DERIVE_LABEL,
1076 )
1077 .map_err(GetDerivedKeysByIdError::DeriveEgressKeyUsingCurrentVmId)?;
1078
1079 if new_egress_key.len() != AES_GCM_KEY_LENGTH {
1080 Err(GetDerivedKeysByIdError::InvalidDerivedEgressKeySize {
1081 key_size: new_egress_key.len(),
1082 expected_size: AES_GCM_KEY_LENGTH,
1083 })?
1084 }
1085
1086 let new_ingress_key = if key_protector_by_id.inner.id_guid != Guid::default() {
1089 crypto::derive_key(
1091 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
1092 key_protector_by_id.inner.id_guid.as_bytes(),
1093 VMGS_KEY_DERIVE_LABEL,
1094 )
1095 .map_err(GetDerivedKeysByIdError::DeriveIngressKeyUsingKeyProtectorId)?
1096 } else {
1097 new_egress_key
1099 };
1100
1101 if new_ingress_key.len() != AES_GCM_KEY_LENGTH {
1102 Err(GetDerivedKeysByIdError::InvalidDerivedIngressKeySize {
1103 key_size: new_ingress_key.len(),
1104 expected_size: AES_GCM_KEY_LENGTH,
1105 })?
1106 }
1107
1108 Ok(Keys {
1109 ingress: new_ingress_key,
1110 decrypt_egress: None,
1111 encrypt_egress: new_egress_key,
1112 })
1113}
1114
1115async fn get_gsp_data(
1117 get: &GuestEmulationTransportClient,
1118 key_protector: &mut KeyProtector,
1119) -> GuestStateProtection {
1120 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1121 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1122
1123 const_assert_eq!(guest_emulation_transport::api::NUMBER_GSP, NUMBER_KP as u32);
1124 const_assert_eq!(
1125 guest_emulation_transport::api::GSP_CIPHERTEXT_MAX,
1126 GSP_BUFFER_SIZE as u32
1127 );
1128
1129 let mut encrypted_gsp =
1130 [guest_emulation_transport::api::GspCiphertextContent::new_zeroed(); NUMBER_KP];
1131
1132 for (i, gsp) in encrypted_gsp.iter_mut().enumerate().take(NUMBER_KP) {
1133 if key_protector.gsp[i].gsp_length == 0 {
1134 continue;
1135 }
1136
1137 gsp.buffer[..key_protector.gsp[i].gsp_length as usize].copy_from_slice(
1138 &key_protector.gsp[i].gsp_buffer[..key_protector.gsp[i].gsp_length as usize],
1139 );
1140
1141 gsp.length = key_protector.gsp[i].gsp_length;
1142 }
1143
1144 get.guest_state_protection_data(encrypted_gsp, GspExtendedStatusFlags::new())
1145 .await
1146}
1147
1148async fn persist_all_key_protectors(
1150 vmgs: &mut Vmgs,
1151 key_protector: &mut KeyProtector,
1152 key_protector_by_id: &mut KeyProtectorById,
1153 bios_guid: Guid,
1154 key_protector_settings: KeyProtectorSettings,
1155) -> Result<(), PersistAllKeyProtectorsError> {
1156 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1157
1158 if key_protector_settings.use_gsp_by_id && !key_protector_settings.should_write_kp {
1159 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
1160 .await
1161 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1162 } else {
1163 if !key_protector_settings.use_hardware_unlock {
1165 key_protector.dek[key_protector.active_kp as usize % NUMBER_KP]
1167 .dek_buffer
1168 .fill(0);
1169 key_protector.gsp[key_protector.active_kp as usize % NUMBER_KP].gsp_length = 0;
1170 key_protector.active_kp += 1;
1171
1172 vmgs::write_key_protector(key_protector, vmgs)
1173 .await
1174 .map_err(PersistAllKeyProtectorsError::WriteKeyProtector)?;
1175 }
1176
1177 if !key_protector_settings.use_gsp_by_id
1179 && key_protector_by_id.found_id
1180 && key_protector_by_id.inner.ported == 0
1181 {
1182 key_protector_by_id.inner.ported = 1;
1183 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, true, bios_guid)
1184 .await
1185 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1186 }
1187 }
1188
1189 Ok(())
1190}
1191
1192#[cfg(test)]
1194pub mod test_utils {
1195 use tee_call::GetAttestationReportResult;
1196 use tee_call::HW_DERIVED_KEY_LENGTH;
1197 use tee_call::REPORT_DATA_SIZE;
1198 use tee_call::TeeCall;
1199 use tee_call::TeeCallGetDerivedKey;
1200 use tee_call::TeeType;
1201
1202 pub struct MockTeeCall {
1204 pub tcb_version: u64,
1206 }
1207
1208 impl MockTeeCall {
1209 pub fn new(tcb_version: u64) -> Self {
1211 Self { tcb_version }
1212 }
1213 }
1214
1215 impl TeeCall for MockTeeCall {
1216 fn get_attestation_report(
1217 &self,
1218 report_data: &[u8; REPORT_DATA_SIZE],
1219 ) -> Result<GetAttestationReportResult, tee_call::Error> {
1220 let mut report =
1221 [0x6c; openhcl_attestation_protocol::igvm_attest::get::SNP_VM_REPORT_SIZE];
1222 report[..REPORT_DATA_SIZE].copy_from_slice(report_data);
1223
1224 Ok(GetAttestationReportResult {
1225 report: report.to_vec(),
1226 tcb_version: Some(self.tcb_version),
1227 })
1228 }
1229
1230 fn supports_get_derived_key(&self) -> Option<&dyn TeeCallGetDerivedKey> {
1231 Some(self)
1232 }
1233
1234 fn tee_type(&self) -> TeeType {
1235 TeeType::Snp
1237 }
1238 }
1239
1240 impl TeeCallGetDerivedKey for MockTeeCall {
1241 fn get_derived_key(&self, tcb_version: u64) -> Result<[u8; 32], tee_call::Error> {
1242 let mut key: [u8; HW_DERIVED_KEY_LENGTH] = [0xab; HW_DERIVED_KEY_LENGTH];
1244
1245 let tcb = tcb_version.to_le_bytes();
1247 for (i, b) in key.iter_mut().enumerate() {
1248 *b ^= tcb[i % tcb.len()];
1249 }
1250
1251 Ok(key)
1252 }
1253 }
1254
1255 pub struct MockTeeCallNoGetDerivedKey;
1257
1258 impl TeeCall for MockTeeCallNoGetDerivedKey {
1259 fn get_attestation_report(
1260 &self,
1261 report_data: &[u8; REPORT_DATA_SIZE],
1262 ) -> Result<GetAttestationReportResult, tee_call::Error> {
1263 let mut report =
1264 [0x6c; openhcl_attestation_protocol::igvm_attest::get::SNP_VM_REPORT_SIZE];
1265 report[..REPORT_DATA_SIZE].copy_from_slice(report_data);
1266
1267 Ok(GetAttestationReportResult {
1268 report: report.to_vec(),
1269 tcb_version: None,
1270 })
1271 }
1272
1273 fn supports_get_derived_key(&self) -> Option<&dyn TeeCallGetDerivedKey> {
1274 None
1275 }
1276
1277 fn tee_type(&self) -> TeeType {
1278 TeeType::Snp
1280 }
1281 }
1282}
1283
1284#[cfg(test)]
1285mod tests {
1286 use super::*;
1287 use crate::test_utils::MockTeeCallNoGetDerivedKey;
1288 use disk_backend::Disk;
1289 use disklayer_ram::ram_disk;
1290 use get_protocol::GSP_CLEARTEXT_MAX;
1291 use get_protocol::GspExtendedStatusFlags;
1292 use guest_emulation_device::IgvmAgentAction;
1293 use guest_emulation_device::IgvmAgentTestPlan;
1294 use guest_emulation_transport::test_utilities::TestGet;
1295 use key_protector::AES_WRAPPED_AES_KEY_LENGTH;
1296 use openhcl_attestation_protocol::igvm_attest::get::IgvmAttestRequestType;
1297 use openhcl_attestation_protocol::vmgs::DEK_BUFFER_SIZE;
1298 use openhcl_attestation_protocol::vmgs::DekKp;
1299 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1300 use openhcl_attestation_protocol::vmgs::GspKp;
1301 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1302 use pal_async::DefaultDriver;
1303 use pal_async::async_test;
1304 use pal_async::task::Spawn;
1305 use std::collections::VecDeque;
1306 use test_utils::MockTeeCall;
1307 use test_with_tracing::test;
1308 use vmgs_format::EncryptionAlgorithm;
1309 use vmgs_format::FileId;
1310
1311 const ONE_MEGA_BYTE: u64 = 1024 * 1024;
1312
1313 fn new_test_file() -> Disk {
1314 ram_disk(4 * ONE_MEGA_BYTE, false).unwrap()
1315 }
1316
1317 async fn new_formatted_vmgs() -> Vmgs {
1318 let disk = new_test_file();
1319
1320 let mut vmgs = Vmgs::format_new(disk, None).await.unwrap();
1321
1322 assert!(
1323 key_protector_is_empty(&mut vmgs).await,
1324 "Newly formatted VMGS should have an empty key protector"
1325 );
1326 assert!(
1327 key_protector_by_id_is_empty(&mut vmgs).await,
1328 "Newly formatted VMGS should have an empty key protector by id"
1329 );
1330
1331 vmgs
1332 }
1333
1334 async fn key_protector_is_empty(vmgs: &mut Vmgs) -> bool {
1335 let key_protector = vmgs::read_key_protector(vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1336 .await
1337 .unwrap();
1338
1339 key_protector.as_bytes().iter().all(|&b| b == 0)
1340 }
1341
1342 async fn key_protector_by_id_is_empty(vmgs: &mut Vmgs) -> bool {
1343 vmgs::read_key_protector_by_id(vmgs)
1344 .await
1345 .is_err_and(|err| {
1346 matches!(
1347 err,
1348 vmgs::ReadFromVmgsError::EntryNotFound(FileId::VM_UNIQUE_ID)
1349 )
1350 })
1351 }
1352
1353 async fn hardware_key_protector_is_empty(vmgs: &mut Vmgs) -> bool {
1354 vmgs::read_hardware_key_protector(vmgs)
1355 .await
1356 .is_err_and(|err| {
1357 matches!(
1358 err,
1359 vmgs::ReadFromVmgsError::EntryNotFound(FileId::HW_KEY_PROTECTOR)
1360 )
1361 })
1362 }
1363
1364 fn new_key_protector() -> KeyProtector {
1365 assert_eq!(NUMBER_KP, 2);
1367
1368 let ingress_dek = DekKp {
1369 dek_buffer: [1; DEK_BUFFER_SIZE],
1370 };
1371 let egress_dek = DekKp {
1372 dek_buffer: [2; DEK_BUFFER_SIZE],
1373 };
1374 let ingress_gsp = GspKp {
1375 gsp_length: GSP_BUFFER_SIZE as u32,
1376 gsp_buffer: [3; GSP_BUFFER_SIZE],
1377 };
1378 let egress_gsp = GspKp {
1379 gsp_length: GSP_BUFFER_SIZE as u32,
1380 gsp_buffer: [4; GSP_BUFFER_SIZE],
1381 };
1382 KeyProtector {
1383 dek: [ingress_dek, egress_dek],
1384 gsp: [ingress_gsp, egress_gsp],
1385 active_kp: 0,
1386 }
1387 }
1388
1389 fn new_key_protector_by_id(
1390 id_guid: Option<Guid>,
1391 ported: Option<u8>,
1392 found_id: bool,
1393 ) -> KeyProtectorById {
1394 let key_protector_by_id = openhcl_attestation_protocol::vmgs::KeyProtectorById {
1395 id_guid: id_guid.unwrap_or_else(Guid::new_random),
1396 ported: ported.unwrap_or(0),
1397 pad: [0; 3],
1398 };
1399
1400 KeyProtectorById {
1401 inner: key_protector_by_id,
1402 found_id,
1403 }
1404 }
1405
1406 async fn new_test_get(
1407 spawn: impl Spawn,
1408 enable_igvm_attest: bool,
1409 plan: Option<IgvmAgentTestPlan>,
1410 ) -> TestGet {
1411 if enable_igvm_attest {
1412 const TEST_DEVICE_MEMORY_SIZE: u64 = 64;
1413 let dev_test_mem = user_driver_emulated_mock::DeviceTestMemory::new(
1415 TEST_DEVICE_MEMORY_SIZE,
1416 true,
1417 "test-attest",
1418 );
1419
1420 let mut test_get = guest_emulation_transport::test_utilities::new_transport_pair(
1421 spawn,
1422 None,
1423 get_protocol::ProtocolVersion::NICKEL_REV2,
1424 Some(dev_test_mem.guest_memory()),
1425 plan,
1426 )
1427 .await;
1428
1429 test_get.client.set_gpa_allocator(dev_test_mem.dma_client());
1430
1431 test_get
1432 } else {
1433 guest_emulation_transport::test_utilities::new_transport_pair(
1434 spawn,
1435 None,
1436 get_protocol::ProtocolVersion::NICKEL_REV2,
1437 None,
1438 None,
1439 )
1440 .await
1441 }
1442 }
1443
1444 fn new_attestation_vm_config() -> AttestationVmConfig {
1445 AttestationVmConfig {
1446 current_time: None,
1447 root_cert_thumbprint: String::new(),
1448 console_enabled: false,
1449 secure_boot: false,
1450 tpm_enabled: true,
1451 tpm_persisted: true,
1452 filtered_vpci_devices_allowed: false,
1453 vm_unique_id: String::new(),
1454 }
1455 }
1456
1457 #[async_test]
1458 async fn do_nothing_without_derived_keys() {
1459 let mut vmgs = new_formatted_vmgs().await;
1460
1461 let mut key_protector = new_key_protector();
1462 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1463
1464 let key_protector_settings = KeyProtectorSettings {
1465 should_write_kp: false,
1466 use_gsp_by_id: false,
1467 use_hardware_unlock: false,
1468 };
1469
1470 let bios_guid = Guid::new_random();
1471
1472 unlock_vmgs_data_store(
1473 &mut vmgs,
1474 false,
1475 &mut key_protector,
1476 &mut key_protector_by_id,
1477 None,
1478 key_protector_settings,
1479 bios_guid,
1480 )
1481 .await
1482 .unwrap();
1483
1484 assert!(key_protector_is_empty(&mut vmgs).await);
1485 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1486
1487 let key_protector_settings = KeyProtectorSettings {
1489 should_write_kp: false,
1490 use_gsp_by_id: false,
1491 use_hardware_unlock: false,
1492 };
1493
1494 unlock_vmgs_data_store(
1496 &mut vmgs,
1497 true,
1498 &mut key_protector,
1499 &mut key_protector_by_id,
1500 None,
1501 key_protector_settings,
1502 bios_guid,
1503 )
1504 .await
1505 .unwrap();
1506
1507 assert!(key_protector_is_empty(&mut vmgs).await);
1508 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1509 }
1510
1511 #[async_test]
1512 async fn provision_vmgs_and_rotate_keys() {
1513 let mut vmgs = new_formatted_vmgs().await;
1514
1515 let mut key_protector = new_key_protector();
1516 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1517
1518 let ingress = [1; AES_GCM_KEY_LENGTH];
1519 let egress = [2; AES_GCM_KEY_LENGTH];
1520 let derived_keys = Keys {
1521 ingress,
1522 decrypt_egress: None,
1523 encrypt_egress: egress,
1524 };
1525
1526 let key_protector_settings = KeyProtectorSettings {
1527 should_write_kp: true,
1528 use_gsp_by_id: true,
1529 use_hardware_unlock: false,
1530 };
1531
1532 let bios_guid = Guid::new_random();
1533
1534 unlock_vmgs_data_store(
1537 &mut vmgs,
1538 false,
1539 &mut key_protector,
1540 &mut key_protector_by_id,
1541 Some(derived_keys),
1542 key_protector_settings,
1543 bios_guid,
1544 )
1545 .await
1546 .unwrap();
1547
1548 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1550
1551 vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1553 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1555
1556 assert!(!key_protector_is_empty(&mut vmgs).await);
1558 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
1559
1560 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1561 .await
1562 .unwrap();
1563 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1564
1565 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1566 assert_eq!(
1567 found_key_protector_by_id.as_bytes(),
1568 key_protector_by_id.inner.as_bytes()
1569 );
1570
1571 let new_egress = [3; AES_GCM_KEY_LENGTH];
1573
1574 let mut new_key_protector = new_key_protector();
1575 let mut new_key_protector_by_id = new_key_protector_by_id(None, None, false);
1576
1577 let key_protector_settings = KeyProtectorSettings {
1578 should_write_kp: true,
1579 use_gsp_by_id: true,
1580 use_hardware_unlock: false,
1581 };
1582
1583 let derived_keys = Keys {
1585 ingress: egress,
1586 decrypt_egress: None,
1587 encrypt_egress: new_egress,
1588 };
1589
1590 unlock_vmgs_data_store(
1591 &mut vmgs,
1592 true,
1593 &mut new_key_protector,
1594 &mut new_key_protector_by_id,
1595 Some(derived_keys),
1596 key_protector_settings,
1597 bios_guid,
1598 )
1599 .await
1600 .unwrap();
1601
1602 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1604 vmgs.unlock_with_encryption_key(&egress).await.unwrap_err();
1606
1607 vmgs.unlock_with_encryption_key(&new_egress).await.unwrap();
1609 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1611
1612 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1613 .await
1614 .unwrap();
1615 assert_eq!(found_key_protector.as_bytes(), new_key_protector.as_bytes());
1616
1617 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1618 assert_eq!(
1619 found_key_protector_by_id.as_bytes(),
1620 new_key_protector_by_id.inner.as_bytes()
1621 );
1622 }
1623
1624 #[async_test]
1625 async fn unlock_previously_encrypted_vmgs_with_ingress_key() {
1626 let mut vmgs = new_formatted_vmgs().await;
1627
1628 let mut key_protector = new_key_protector();
1629 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1630
1631 let ingress = [1; AES_GCM_KEY_LENGTH];
1632 let egress = [2; AES_GCM_KEY_LENGTH];
1633
1634 let derived_keys = Keys {
1635 ingress,
1636 decrypt_egress: None,
1637 encrypt_egress: egress,
1638 };
1639
1640 vmgs.update_encryption_key(&ingress, EncryptionAlgorithm::AES_GCM)
1641 .await
1642 .unwrap();
1643
1644 vmgs.unlock_with_encryption_key(&ingress).await.unwrap();
1646 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1647
1648 let key_protector_settings = KeyProtectorSettings {
1649 should_write_kp: true,
1650 use_gsp_by_id: true,
1651 use_hardware_unlock: false,
1652 };
1653
1654 let bios_guid = Guid::new_random();
1655
1656 unlock_vmgs_data_store(
1657 &mut vmgs,
1658 true,
1659 &mut key_protector,
1660 &mut key_protector_by_id,
1661 Some(derived_keys),
1662 key_protector_settings,
1663 bios_guid,
1664 )
1665 .await
1666 .unwrap();
1667
1668 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1670 vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1671 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1673
1674 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1676 .await
1677 .unwrap();
1678 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1679
1680 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1681 assert_eq!(
1682 found_key_protector_by_id.as_bytes(),
1683 key_protector_by_id.inner.as_bytes()
1684 );
1685 }
1686
1687 #[async_test]
1688 async fn failed_to_persist_ingress_key_so_use_egress_key_to_unlock_vmgs() {
1689 let mut vmgs = new_formatted_vmgs().await;
1690
1691 let mut key_protector = new_key_protector();
1692 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1693
1694 let ingress = [1; AES_GCM_KEY_LENGTH];
1695 let decrypt_egress = [2; AES_GCM_KEY_LENGTH];
1696 let encrypt_egress = [3; AES_GCM_KEY_LENGTH];
1697
1698 let derived_keys = Keys {
1699 ingress,
1700 decrypt_egress: Some(decrypt_egress),
1701 encrypt_egress,
1702 };
1703
1704 vmgs.test_add_new_encryption_key(&decrypt_egress, EncryptionAlgorithm::AES_GCM)
1706 .await
1707 .unwrap();
1708 let egress_key_index = vmgs.test_get_active_datastore_key_index().unwrap();
1709 assert_eq!(egress_key_index, 0);
1710
1711 vmgs.unlock_with_encryption_key(&decrypt_egress)
1712 .await
1713 .unwrap();
1714 let found_egress_key_index = vmgs.test_get_active_datastore_key_index().unwrap();
1715 assert_eq!(found_egress_key_index, egress_key_index);
1716
1717 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1719
1720 let key_protector_settings = KeyProtectorSettings {
1721 should_write_kp: true,
1722 use_gsp_by_id: true,
1723 use_hardware_unlock: false,
1724 };
1725
1726 let bios_guid = Guid::new_random();
1727
1728 unlock_vmgs_data_store(
1729 &mut vmgs,
1730 true,
1731 &mut key_protector,
1732 &mut key_protector_by_id,
1733 Some(derived_keys),
1734 key_protector_settings,
1735 bios_guid,
1736 )
1737 .await
1738 .unwrap();
1739
1740 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1742
1743 vmgs.unlock_with_encryption_key(&decrypt_egress)
1745 .await
1746 .unwrap_err();
1747
1748 vmgs.unlock_with_encryption_key(&encrypt_egress)
1750 .await
1751 .unwrap();
1752 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1753
1754 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1756 .await
1757 .unwrap();
1758 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1759
1760 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1761 assert_eq!(
1762 found_key_protector_by_id.as_bytes(),
1763 key_protector_by_id.inner.as_bytes()
1764 );
1765 }
1766
1767 #[async_test]
1768 async fn fail_to_unlock_vmgs_with_existing_ingress_key() {
1769 let mut vmgs = new_formatted_vmgs().await;
1770
1771 let mut key_protector = new_key_protector();
1772 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1773
1774 let ingress = [1; AES_GCM_KEY_LENGTH];
1775
1776 let derived_keys = Keys {
1778 ingress,
1779 decrypt_egress: None,
1780 encrypt_egress: ingress,
1781 };
1782
1783 let additional_key = [2; AES_GCM_KEY_LENGTH];
1785 let yet_another_key = [3; AES_GCM_KEY_LENGTH];
1786
1787 vmgs.test_add_new_encryption_key(&additional_key, EncryptionAlgorithm::AES_GCM)
1788 .await
1789 .unwrap();
1790 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1791
1792 vmgs.test_add_new_encryption_key(&yet_another_key, EncryptionAlgorithm::AES_GCM)
1793 .await
1794 .unwrap();
1795 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1796
1797 let key_protector_settings = KeyProtectorSettings {
1798 should_write_kp: true,
1799 use_gsp_by_id: true,
1800 use_hardware_unlock: false,
1801 };
1802
1803 let bios_guid = Guid::new_random();
1804
1805 let unlock_result = unlock_vmgs_data_store(
1806 &mut vmgs,
1807 true,
1808 &mut key_protector,
1809 &mut key_protector_by_id,
1810 Some(derived_keys),
1811 key_protector_settings,
1812 bios_guid,
1813 )
1814 .await;
1815 assert!(unlock_result.is_err());
1816 assert_eq!(
1817 unlock_result.unwrap_err().to_string(),
1818 "failed to unlock vmgs with the existing ingress key".to_string()
1819 );
1820 }
1821
1822 #[async_test]
1823 async fn fail_to_unlock_vmgs_with_new_ingress_key() {
1824 let mut vmgs = new_formatted_vmgs().await;
1825
1826 let mut key_protector = new_key_protector();
1827 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1828
1829 let derived_keys = Keys {
1830 ingress: [1; AES_GCM_KEY_LENGTH],
1831 decrypt_egress: None,
1832 encrypt_egress: [2; AES_GCM_KEY_LENGTH],
1833 };
1834
1835 let additional_key = [3; AES_GCM_KEY_LENGTH];
1837 let yet_another_key = [4; AES_GCM_KEY_LENGTH];
1838
1839 vmgs.test_add_new_encryption_key(&additional_key, EncryptionAlgorithm::AES_GCM)
1840 .await
1841 .unwrap();
1842 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1843
1844 vmgs.test_add_new_encryption_key(&yet_another_key, EncryptionAlgorithm::AES_GCM)
1845 .await
1846 .unwrap();
1847 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1848
1849 let key_protector_settings = KeyProtectorSettings {
1850 should_write_kp: true,
1851 use_gsp_by_id: true,
1852 use_hardware_unlock: false,
1853 };
1854
1855 let bios_guid = Guid::new_random();
1856
1857 let unlock_result = unlock_vmgs_data_store(
1858 &mut vmgs,
1859 true,
1860 &mut key_protector,
1861 &mut key_protector_by_id,
1862 Some(derived_keys),
1863 key_protector_settings,
1864 bios_guid,
1865 )
1866 .await;
1867 assert!(unlock_result.is_err());
1868 assert_eq!(
1869 unlock_result.unwrap_err().to_string(),
1870 "failed to unlock vmgs with the existing ingress key".to_string()
1871 );
1872 }
1873
1874 #[async_test]
1875 async fn get_derived_keys_using_id() {
1876 let bios_guid = Guid::new_random();
1877
1878 let gsp_response_by_id = GuestStateProtectionById {
1879 seed: guest_emulation_transport::api::GspCleartextContent {
1880 length: GSP_CLEARTEXT_MAX,
1881 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
1882 },
1883 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
1884 };
1885
1886 let mut key_protector_by_id =
1889 new_key_protector_by_id(Some(Guid::new_zeroed()), None, false);
1890 let derived_keys =
1891 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
1892 .unwrap();
1893
1894 assert_eq!(derived_keys.ingress, derived_keys.encrypt_egress);
1895
1896 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1899 let derived_keys =
1900 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
1901 .unwrap();
1902
1903 assert_ne!(derived_keys.ingress, derived_keys.encrypt_egress);
1904
1905 let gsp_response_by_id_with_0_length_seed = GuestStateProtectionById {
1907 seed: guest_emulation_transport::api::GspCleartextContent {
1908 length: 0,
1909 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
1910 },
1911 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
1912 };
1913
1914 let derived_keys_response = get_derived_keys_by_id(
1915 &mut key_protector_by_id,
1916 bios_guid,
1917 gsp_response_by_id_with_0_length_seed,
1918 );
1919 assert!(derived_keys_response.is_err());
1920 assert_eq!(
1921 derived_keys_response.unwrap_err().to_string(),
1922 "failed to derive an egress key based on current vm bios guid".to_string()
1923 );
1924 }
1925
1926 #[async_test]
1927 async fn pass_through_persist_all_key_protectors() {
1928 let mut vmgs = new_formatted_vmgs().await;
1929 let mut key_protector = new_key_protector();
1930 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1931 let bios_guid = Guid::new_random();
1932
1933 let kp_copy = key_protector.as_bytes().to_vec();
1935 let active_kp_copy = key_protector.active_kp;
1936
1937 let key_protector_settings = KeyProtectorSettings {
1939 should_write_kp: true,
1940 use_gsp_by_id: true,
1941 use_hardware_unlock: true,
1942 };
1943 persist_all_key_protectors(
1944 &mut vmgs,
1945 &mut key_protector,
1946 &mut key_protector_by_id,
1947 bios_guid,
1948 key_protector_settings,
1949 )
1950 .await
1951 .unwrap();
1952
1953 assert!(key_protector_is_empty(&mut vmgs).await);
1954 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1955
1956 assert_eq!(active_kp_copy, key_protector.active_kp);
1958 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
1959 }
1960
1961 #[async_test]
1962 async fn persist_all_key_protectors_write_key_protector_by_id() {
1963 let mut vmgs = new_formatted_vmgs().await;
1964 let mut key_protector = new_key_protector();
1965 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1966 let bios_guid = Guid::new_random();
1967
1968 let kp_copy = key_protector.as_bytes().to_vec();
1970 let active_kp_copy = key_protector.active_kp;
1971
1972 let key_protector_settings = KeyProtectorSettings {
1974 should_write_kp: false,
1975 use_gsp_by_id: true,
1976 use_hardware_unlock: false,
1977 };
1978 persist_all_key_protectors(
1979 &mut vmgs,
1980 &mut key_protector,
1981 &mut key_protector_by_id,
1982 bios_guid,
1983 key_protector_settings,
1984 )
1985 .await
1986 .unwrap();
1987
1988 assert!(key_protector_is_empty(&mut vmgs).await);
1990 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
1991
1992 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1993 assert_eq!(
1994 found_key_protector_by_id.as_bytes(),
1995 key_protector_by_id.inner.as_bytes()
1996 );
1997
1998 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
2000 assert_eq!(active_kp_copy, key_protector.active_kp);
2001 }
2002
2003 #[async_test]
2004 async fn persist_all_key_protectors_remove_ingress_kp() {
2005 let mut vmgs = new_formatted_vmgs().await;
2006 let mut key_protector = new_key_protector();
2007 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2008 let bios_guid = Guid::new_random();
2009
2010 let active_kp_copy = key_protector.active_kp;
2012
2013 let key_protector_settings = KeyProtectorSettings {
2016 should_write_kp: true,
2017 use_gsp_by_id: false,
2018 use_hardware_unlock: false,
2019 };
2020 persist_all_key_protectors(
2021 &mut vmgs,
2022 &mut key_protector,
2023 &mut key_protector_by_id,
2024 bios_guid,
2025 key_protector_settings,
2026 )
2027 .await
2028 .unwrap();
2029
2030 assert!(!key_protector_is_empty(&mut vmgs).await);
2031 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
2032
2033 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
2035 .await
2036 .unwrap();
2037
2038 assert!(
2039 found_key_protector.dek[active_kp_copy as usize]
2040 .dek_buffer
2041 .iter()
2042 .all(|&b| b == 0),
2043 );
2044 assert_eq!(
2045 found_key_protector.gsp[active_kp_copy as usize].gsp_length,
2046 0
2047 );
2048 assert_eq!(found_key_protector.active_kp, active_kp_copy + 1);
2049 }
2050
2051 #[async_test]
2052 async fn persist_all_key_protectors_mark_key_protector_by_id_as_not_in_use() {
2053 let mut vmgs = new_formatted_vmgs().await;
2054 let mut key_protector = new_key_protector();
2055 let mut key_protector_by_id = new_key_protector_by_id(None, None, true);
2056 let bios_guid = Guid::new_random();
2057
2058 let key_protector_settings = KeyProtectorSettings {
2061 should_write_kp: true,
2062 use_gsp_by_id: false,
2063 use_hardware_unlock: true,
2064 };
2065
2066 persist_all_key_protectors(
2067 &mut vmgs,
2068 &mut key_protector,
2069 &mut key_protector_by_id,
2070 bios_guid,
2071 key_protector_settings,
2072 )
2073 .await
2074 .unwrap();
2075
2076 assert!(key_protector_is_empty(&mut vmgs).await);
2077 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
2078
2079 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
2081 assert_eq!(found_key_protector_by_id.ported, 1);
2082 assert_eq!(
2083 found_key_protector_by_id.id_guid,
2084 key_protector_by_id.inner.id_guid
2085 );
2086 }
2087
2088 #[async_test]
2091 async fn init_sec_suppress_attestation(driver: DefaultDriver) {
2092 let mut vmgs = new_formatted_vmgs().await;
2093
2094 let agent = SecurityProfile {
2096 agent_data: [0xAA; openhcl_attestation_protocol::vmgs::AGENT_DATA_MAX_SIZE],
2097 };
2098 vmgs.write_file(FileId::ATTEST, agent.as_bytes())
2099 .await
2100 .unwrap();
2101
2102 let get_pair = new_test_get(driver, false, None).await;
2104
2105 let bios_guid = Guid::new_random();
2106 let att_cfg = new_attestation_vm_config();
2107
2108 assert!(!vmgs.is_encrypted());
2110
2111 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2113 let res = initialize_platform_security(
2114 &get_pair.client,
2115 bios_guid,
2116 &att_cfg,
2117 &mut vmgs,
2118 None, true, ldriver,
2121 GuestStateEncryptionPolicy::None,
2122 true,
2123 )
2124 .await
2125 .unwrap();
2126
2127 assert!(!vmgs.is_encrypted());
2129 assert!(key_protector_is_empty(&mut vmgs).await);
2130 assert!(hardware_key_protector_is_empty(&mut vmgs).await);
2131 assert_eq!(res.agent_data.unwrap(), agent.agent_data.to_vec());
2133 assert!(res.guest_secret_key.is_none());
2135 }
2136
2137 #[async_test]
2138 async fn init_sec_secure_key_release_with_wrapped_key_request(driver: DefaultDriver) {
2139 let mut vmgs = new_formatted_vmgs().await;
2140
2141 let get_pair = new_test_get(driver, true, None).await;
2143
2144 let bios_guid = Guid::new_random();
2145 let att_cfg = new_attestation_vm_config();
2146 let tee = MockTeeCall::new(0x1234);
2147
2148 assert!(!vmgs.is_encrypted());
2150
2151 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2153 let res = initialize_platform_security(
2154 &get_pair.client,
2155 bios_guid,
2156 &att_cfg,
2157 &mut vmgs,
2158 Some(&tee),
2159 false,
2160 ldriver.clone(),
2161 GuestStateEncryptionPolicy::Auto,
2162 true,
2163 )
2164 .await
2165 .unwrap();
2166
2167 assert!(vmgs.is_encrypted());
2169 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2170
2171 let key_reference = serde_json::json!({
2174 "key_info": {
2175 "host": "name"
2176 },
2177 "attestation_info": {
2178 "host": "attestation_name"
2179 }
2180 });
2181 let key_reference = serde_json::to_string(&key_reference).unwrap();
2182 let key_reference = key_reference.as_bytes();
2183 let mut expected_agent_data =
2184 [0u8; openhcl_attestation_protocol::vmgs::AGENT_DATA_MAX_SIZE];
2185 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2186 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2187 assert!(res.guest_secret_key.is_none());
2189
2190 initialize_platform_security(
2192 &get_pair.client,
2193 bios_guid,
2194 &att_cfg,
2195 &mut vmgs,
2196 Some(&tee),
2197 false,
2198 ldriver,
2199 GuestStateEncryptionPolicy::Auto,
2200 true,
2201 )
2202 .await
2203 .unwrap();
2204
2205 assert!(vmgs.is_encrypted());
2207 }
2208
2209 #[async_test]
2210 async fn init_sec_secure_key_release_without_wrapped_key_request(driver: DefaultDriver) {
2211 let mut vmgs = new_formatted_vmgs().await;
2212
2213 let agent = SecurityProfile {
2215 agent_data: [0xAA; openhcl_attestation_protocol::vmgs::AGENT_DATA_MAX_SIZE],
2216 };
2217 vmgs.write_file(FileId::ATTEST, agent.as_bytes())
2218 .await
2219 .unwrap();
2220
2221 let mut plan = IgvmAgentTestPlan::default();
2223 plan.insert(
2224 IgvmAttestRequestType::WRAPPED_KEY_REQUEST,
2225 VecDeque::from([IgvmAgentAction::NoResponse, IgvmAgentAction::NoResponse]),
2226 );
2227
2228 let get_pair = new_test_get(driver, true, Some(plan)).await;
2230
2231 let bios_guid = Guid::new_random();
2232 let att_cfg = new_attestation_vm_config();
2233 let tee = MockTeeCall::new(0x1234);
2234
2235 assert!(!vmgs.is_encrypted());
2237
2238 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2240 let res = initialize_platform_security(
2241 &get_pair.client,
2242 bios_guid,
2243 &att_cfg,
2244 &mut vmgs,
2245 Some(&tee),
2246 false,
2247 ldriver.clone(),
2248 GuestStateEncryptionPolicy::Auto,
2249 true,
2250 )
2251 .await
2252 .unwrap();
2253
2254 assert!(vmgs.is_encrypted());
2256 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2257 assert_eq!(res.agent_data.clone().unwrap(), agent.agent_data.to_vec());
2259 assert!(res.guest_secret_key.is_none());
2261
2262 let res = initialize_platform_security(
2264 &get_pair.client,
2265 bios_guid,
2266 &att_cfg,
2267 &mut vmgs,
2268 Some(&tee),
2269 false,
2270 ldriver,
2271 GuestStateEncryptionPolicy::Auto,
2272 true,
2273 )
2274 .await
2275 .unwrap();
2276
2277 assert!(vmgs.is_encrypted());
2279 assert_eq!(res.agent_data.clone().unwrap(), agent.agent_data.to_vec());
2281 assert!(res.guest_secret_key.is_none());
2283 }
2284
2285 #[async_test]
2286 async fn init_sec_secure_key_release_hw_sealing_backup(driver: DefaultDriver) {
2287 let mut vmgs = new_formatted_vmgs().await;
2288
2289 let mut plan = IgvmAgentTestPlan::default();
2291 plan.insert(
2292 IgvmAttestRequestType::WRAPPED_KEY_REQUEST,
2293 VecDeque::from([
2294 IgvmAgentAction::RespondSuccess,
2295 IgvmAgentAction::RespondFailure,
2296 ]),
2297 );
2298
2299 let get_pair = new_test_get(driver, true, Some(plan)).await;
2300
2301 let bios_guid = Guid::new_random();
2302 let att_cfg = new_attestation_vm_config();
2303
2304 assert!(!vmgs.is_encrypted());
2306
2307 let tee = MockTeeCall::new(0x1234);
2309 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2310 let res = initialize_platform_security(
2311 &get_pair.client,
2312 bios_guid,
2313 &att_cfg,
2314 &mut vmgs,
2315 Some(&tee),
2316 false,
2317 ldriver.clone(),
2318 GuestStateEncryptionPolicy::Auto,
2319 true,
2320 )
2321 .await
2322 .unwrap();
2323
2324 assert!(vmgs.is_encrypted());
2326 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2327 let key_reference = serde_json::json!({
2330 "key_info": {
2331 "host": "name"
2332 },
2333 "attestation_info": {
2334 "host": "attestation_name"
2335 }
2336 });
2337 let key_reference = serde_json::to_string(&key_reference).unwrap();
2338 let key_reference = key_reference.as_bytes();
2339 let mut expected_agent_data =
2340 [0u8; openhcl_attestation_protocol::vmgs::AGENT_DATA_MAX_SIZE];
2341 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2342 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2343 assert!(res.guest_secret_key.is_none());
2345
2346 initialize_platform_security(
2352 &get_pair.client,
2353 bios_guid,
2354 &att_cfg,
2355 &mut vmgs,
2356 Some(&tee),
2357 false,
2358 ldriver,
2359 GuestStateEncryptionPolicy::Auto,
2360 true,
2361 )
2362 .await
2363 .unwrap();
2364
2365 assert!(vmgs.is_encrypted());
2367 }
2368
2369 #[async_test]
2370 async fn init_sec_secure_key_release_no_hw_sealing_backup(driver: DefaultDriver) {
2371 let mut vmgs = new_formatted_vmgs().await;
2372
2373 let mut plan = IgvmAgentTestPlan::default();
2375 plan.insert(
2376 IgvmAttestRequestType::WRAPPED_KEY_REQUEST,
2377 VecDeque::from([
2378 IgvmAgentAction::RespondSuccess,
2379 IgvmAgentAction::RespondFailure,
2380 ]),
2381 );
2382
2383 let get_pair = new_test_get(driver, true, Some(plan)).await;
2384
2385 let bios_guid = Guid::new_random();
2386 let att_cfg = new_attestation_vm_config();
2387 let tee = MockTeeCallNoGetDerivedKey {};
2389
2390 assert!(!vmgs.is_encrypted());
2392
2393 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2395 let res = initialize_platform_security(
2396 &get_pair.client,
2397 bios_guid,
2398 &att_cfg,
2399 &mut vmgs,
2400 Some(&tee),
2401 false,
2402 ldriver.clone(),
2403 GuestStateEncryptionPolicy::Auto,
2404 true,
2405 )
2406 .await
2407 .unwrap();
2408
2409 assert!(vmgs.is_encrypted());
2411 assert!(hardware_key_protector_is_empty(&mut vmgs).await);
2412 let key_reference = serde_json::json!({
2415 "key_info": {
2416 "host": "name"
2417 },
2418 "attestation_info": {
2419 "host": "attestation_name"
2420 }
2421 });
2422 let key_reference = serde_json::to_string(&key_reference).unwrap();
2423 let key_reference = key_reference.as_bytes();
2424 let mut expected_agent_data =
2425 [0u8; openhcl_attestation_protocol::vmgs::AGENT_DATA_MAX_SIZE];
2426 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2427 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2428 assert!(res.guest_secret_key.is_none());
2430
2431 let result = initialize_platform_security(
2433 &get_pair.client,
2434 bios_guid,
2435 &att_cfg,
2436 &mut vmgs,
2437 Some(&tee),
2438 false,
2439 ldriver,
2440 GuestStateEncryptionPolicy::Auto,
2441 true,
2442 )
2443 .await;
2444
2445 assert!(result.is_err());
2446 }
2447}