1#![cfg(target_os = "linux")]
10#![forbid(unsafe_code)]
11
12mod crypto;
13mod hardware_key_sealing;
14mod igvm_attest;
15mod jwt;
16mod key_protector;
17mod secure_key_release;
18mod vmgs;
19
20#[cfg(test)]
21mod test_helpers;
22
23pub use igvm_attest::Error as IgvmAttestError;
24pub use igvm_attest::IgvmAttestRequestHelper;
25pub use igvm_attest::ak_cert::parse_response as parse_ak_cert_response;
26
27use ::vmgs::EncryptionAlgorithm;
28use ::vmgs::GspType;
29use ::vmgs::Vmgs;
30use cvm_tracing::CVM_ALLOWED;
31use get_protocol::dps_json::GuestStateEncryptionPolicy;
32use guest_emulation_transport::GuestEmulationTransportClient;
33use guest_emulation_transport::api::GspExtendedStatusFlags;
34use guest_emulation_transport::api::GuestStateProtection;
35use guest_emulation_transport::api::GuestStateProtectionById;
36use guid::Guid;
37use hardware_key_sealing::HardwareDerivedKeys;
38use hardware_key_sealing::HardwareKeyProtectorExt as _;
39use key_protector::GetKeysFromKeyProtectorError;
40use key_protector::KeyProtectorExt as _;
41use mesh::MeshPayload;
42use openhcl_attestation_protocol::igvm_attest::get::runtime_claims::AttestationVmConfig;
43use openhcl_attestation_protocol::vmgs::AES_GCM_KEY_LENGTH;
44use openhcl_attestation_protocol::vmgs::AGENT_DATA_MAX_SIZE;
45use openhcl_attestation_protocol::vmgs::HardwareKeyProtector;
46use openhcl_attestation_protocol::vmgs::KeyProtector;
47use openhcl_attestation_protocol::vmgs::SecurityProfile;
48use openssl::pkey::Private;
49use openssl::rsa::Rsa;
50use pal_async::local::LocalDriver;
51use secure_key_release::VmgsEncryptionKeys;
52use static_assertions::const_assert_eq;
53use std::fmt::Debug;
54use tee_call::TeeCall;
55use thiserror::Error;
56use zerocopy::FromZeros;
57use zerocopy::IntoBytes;
58
59#[derive(Debug, Error)]
61#[error(transparent)]
62pub struct Error(AttestationErrorInner);
63
64impl<T: Into<AttestationErrorInner>> From<T> for Error {
65 fn from(value: T) -> Self {
66 Self(value.into())
67 }
68}
69
70#[derive(Debug, Error)]
71enum AttestationErrorInner {
72 #[error("read security profile from vmgs")]
73 ReadSecurityProfile(#[source] vmgs::ReadFromVmgsError),
74 #[error("failed to get derived keys")]
75 GetDerivedKeys(#[source] GetDerivedKeysError),
76 #[error("failed to read key protector from vmgs")]
77 ReadKeyProtector(#[source] vmgs::ReadFromVmgsError),
78 #[error("failed to read key protector by id from vmgs")]
79 ReadKeyProtectorById(#[source] vmgs::ReadFromVmgsError),
80 #[error("failed to unlock vmgs data store")]
81 UnlockVmgsDataStore(#[source] UnlockVmgsDataStoreError),
82 #[error("failed to read guest secret key from vmgs")]
83 ReadGuestSecretKey(#[source] vmgs::ReadFromVmgsError),
84}
85
86#[derive(Debug, Error)]
87enum GetDerivedKeysError {
88 #[error("failed to get ingress/egress keys from the the key protector")]
89 GetKeysFromKeyProtector(#[source] GetKeysFromKeyProtectorError),
90 #[error("failed to fetch GSP")]
91 FetchGuestStateProtectionById(
92 #[source] guest_emulation_transport::error::GuestStateProtectionByIdError,
93 ),
94 #[error("GSP By Id required, but no GSP By Id found")]
95 GspByIdRequiredButNotFound,
96 #[error("failed to unseal the ingress key using hardware derived keys")]
97 UnsealIngressKeyUsingHardwareDerivedKeys(
98 #[source] hardware_key_sealing::HardwareKeySealingError,
99 ),
100 #[error("failed to get an ingress key from key protector")]
101 GetIngressKeyFromKpFailed,
102 #[error("failed to get an ingress key from guest state protection")]
103 GetIngressKeyFromKGspFailed,
104 #[error("failed to get an ingress key from guest state protection by id")]
105 GetIngressKeyFromKGspByIdFailed,
106 #[error("Encryption cannot be disabled if VMGS was previously encrypted")]
107 DisableVmgsEncryptionFailed,
108 #[error("VMGS encryption is required, but no encryption sources were found")]
109 EncryptionRequiredButNotFound,
110 #[error("failed to seal the egress key using hardware derived keys")]
111 SealEgressKeyUsingHardwareDerivedKeys(#[source] hardware_key_sealing::HardwareKeySealingError),
112 #[error("failed to write to `FileId::HW_KEY_PROTECTOR` in vmgs")]
113 VmgsWriteHardwareKeyProtector(#[source] vmgs::WriteToVmgsError),
114 #[error("failed to get derived key by id")]
115 GetDerivedKeyById(#[source] GetDerivedKeysByIdError),
116 #[error("failed to derive an ingress key")]
117 DeriveIngressKey(#[source] crypto::KbkdfError),
118 #[error("failed to derive an egress key")]
119 DeriveEgressKey(#[source] crypto::KbkdfError),
120}
121
122#[derive(Debug, Error)]
123enum GetDerivedKeysByIdError {
124 #[error("failed to derive an egress key based on current vm bios guid")]
125 DeriveEgressKeyUsingCurrentVmId(#[source] crypto::KbkdfError),
126 #[error("invalid derived egress key size {key_size}, expected {expected_size}")]
127 InvalidDerivedEgressKeySize {
128 key_size: usize,
129 expected_size: usize,
130 },
131 #[error("failed to derive an ingress key based on key protector Id from vmgs")]
132 DeriveIngressKeyUsingKeyProtectorId(#[source] crypto::KbkdfError),
133 #[error("invalid derived egress key size {key_size}, expected {expected_size}")]
134 InvalidDerivedIngressKeySize {
135 key_size: usize,
136 expected_size: usize,
137 },
138}
139
140#[derive(Debug, Error)]
141enum UnlockVmgsDataStoreError {
142 #[error("failed to unlock vmgs with the existing egress key")]
143 VmgsUnlockUsingExistingEgressKey(#[source] ::vmgs::Error),
144 #[error("failed to unlock vmgs with the existing ingress key")]
145 VmgsUnlockUsingExistingIngressKey(#[source] ::vmgs::Error),
146 #[error("failed to write key protector to vmgs")]
147 WriteKeyProtector(#[source] vmgs::WriteToVmgsError),
148 #[error("failed to read key protector by id to vmgs")]
149 WriteKeyProtectorById(#[source] vmgs::WriteToVmgsError),
150 #[error("failed to update the vmgs encryption key")]
151 UpdateVmgsEncryptionKey(#[source] ::vmgs::Error),
152 #[error("failed to persist all key protectors")]
153 PersistAllKeyProtectors(#[source] PersistAllKeyProtectorsError),
154}
155
156#[derive(Debug, Error)]
157enum PersistAllKeyProtectorsError {
158 #[error("failed to write key protector to vmgs")]
159 WriteKeyProtector(#[source] vmgs::WriteToVmgsError),
160 #[error("failed to read key protector by id to vmgs")]
161 WriteKeyProtectorById(#[source] vmgs::WriteToVmgsError),
162}
163
164#[derive(Debug)]
166enum LogOpType {
167 BeginDecryptVmgs,
168 DecryptVmgs,
169 ConvertEncryptionType,
170}
171
172const VMGS_KEY_DERIVE_LABEL: &[u8; 7] = b"VMGSKEY";
174
175#[derive(Debug)]
176struct Keys {
177 ingress: [u8; AES_GCM_KEY_LENGTH],
178 decrypt_egress: Option<[u8; AES_GCM_KEY_LENGTH]>,
179 encrypt_egress: [u8; AES_GCM_KEY_LENGTH],
180}
181
182#[derive(Clone, Copy)]
184struct KeyProtectorSettings {
185 should_write_kp: bool,
187 use_gsp_by_id: bool,
189 use_hardware_unlock: bool,
191 decrypt_gsp_type: GspType,
193 encrypt_gsp_type: GspType,
195}
196
197struct KeyProtectorById {
199 pub inner: openhcl_attestation_protocol::vmgs::KeyProtectorById,
201 pub found_id: bool,
203}
204
205pub struct HostAttestationSettings {
207 pub refresh_tpm_seeds: bool,
209}
210
211struct DerivedKeyResult {
213 derived_keys: Option<Keys>,
215 key_protector_settings: KeyProtectorSettings,
217 gsp_extended_status_flags: GspExtendedStatusFlags,
219}
220
221pub struct PlatformAttestationData {
223 pub host_attestation_settings: HostAttestationSettings,
225 pub agent_data: Option<Vec<u8>>,
227 pub guest_secret_key: Option<Vec<u8>>,
229}
230
231#[derive(Debug, MeshPayload, Copy, Clone, PartialEq, Eq)]
234pub enum AttestationType {
235 Snp,
237 Tdx,
239 Vbs,
241 Host,
243}
244
245async fn try_unlock_vmgs(
250 get: &GuestEmulationTransportClient,
251 bios_guid: Guid,
252 attestation_vm_config: &AttestationVmConfig,
253 vmgs: &mut Vmgs,
254 tee_call: Option<&dyn TeeCall>,
255 guest_state_encryption_policy: GuestStateEncryptionPolicy,
256 strict_encryption_policy: bool,
257 agent_data: &mut [u8; AGENT_DATA_MAX_SIZE],
258 key_protector_by_id: &mut KeyProtectorById,
259) -> Result<bool, (AttestationErrorInner, bool)> {
260 let skr_response = if let Some(tee_call) = tee_call {
261 tracing::info!(CVM_ALLOWED, "Retrieving key-encryption key");
262
263 secure_key_release::request_vmgs_encryption_keys(
265 get,
266 tee_call,
267 vmgs,
268 attestation_vm_config,
269 agent_data,
270 )
271 .await
272 } else {
273 tracing::info!(CVM_ALLOWED, "Key-encryption key retrieval not required");
274
275 Ok(VmgsEncryptionKeys::default())
277 };
278
279 let retry = match skr_response {
280 Ok(_) => false,
281 Err((_, r)) => r,
282 };
283
284 let VmgsEncryptionKeys {
285 ingress_rsa_kek,
286 wrapped_des_key,
287 tcb_version,
288 } = match skr_response {
289 Ok(k) => {
290 tracing::info!(CVM_ALLOWED, "Successfully retrieved key-encryption key");
291 k
292 }
293 Err((e, _)) => {
294 tracing::error!(
296 CVM_ALLOWED,
297 error = &e as &dyn std::error::Error,
298 "Failed to retrieve key-encryption key"
299 );
300
301 VmgsEncryptionKeys::default()
302 }
303 };
304
305 let dek_minimal_size = if wrapped_des_key.is_some() {
307 key_protector::AES_WRAPPED_AES_KEY_LENGTH
308 } else {
309 key_protector::RSA_WRAPPED_AES_KEY_LENGTH
310 };
311
312 tracing::info!(
314 CVM_ALLOWED,
315 dek_minimal_size = dek_minimal_size,
316 "Reading key protector from VMGS"
317 );
318 let mut key_protector = vmgs::read_key_protector(vmgs, dek_minimal_size)
319 .await
320 .map_err(|e| (AttestationErrorInner::ReadKeyProtector(e), false))?;
321
322 let start_time = std::time::SystemTime::now();
323 let vmgs_encrypted = vmgs.is_encrypted();
324 tracing::info!(
325 ?tcb_version,
326 vmgs_encrypted,
327 op_type = ?LogOpType::BeginDecryptVmgs,
328 "Deriving keys"
329 );
330
331 let derived_keys_result = get_derived_keys(
332 get,
333 tee_call,
334 vmgs,
335 &mut key_protector,
336 key_protector_by_id,
337 bios_guid,
338 attestation_vm_config,
339 vmgs_encrypted,
340 ingress_rsa_kek.as_ref(),
341 wrapped_des_key.as_deref(),
342 tcb_version,
343 guest_state_encryption_policy,
344 strict_encryption_policy,
345 )
346 .await
347 .map_err(|e| {
348 tracing::error!(
349 CVM_ALLOWED,
350 op_type = ?LogOpType::DecryptVmgs,
351 success = false,
352 err = &e as &dyn std::error::Error,
353 latency = std::time::SystemTime::now()
354 .duration_since(start_time)
355 .map_or(0, |d| d.as_millis()),
356 "Failed to derive keys"
357 );
358 (AttestationErrorInner::GetDerivedKeys(e), retry)
359 })?;
360
361 tracing::info!("Unlocking VMGS");
363 if let Err(e) = unlock_vmgs_data_store(
364 vmgs,
365 vmgs_encrypted,
366 &mut key_protector,
367 key_protector_by_id,
368 derived_keys_result.derived_keys,
369 derived_keys_result.key_protector_settings,
370 bios_guid,
371 )
372 .await
373 {
374 tracing::error!(
375 CVM_ALLOWED,
376 op_type = ?LogOpType::DecryptVmgs,
377 success = false,
378 err = &e as &dyn std::error::Error,
379 latency = std::time::SystemTime::now()
380 .duration_since(start_time)
381 .map_or(0, |d| d.as_millis()),
382 "Failed to unlock datastore"
383 );
384 get.event_log_fatal(guest_emulation_transport::api::EventLogId::ATTESTATION_FAILED)
385 .await;
386
387 Err((AttestationErrorInner::UnlockVmgsDataStore(e), retry))?;
388 }
389
390 tracing::info!(
391 CVM_ALLOWED,
392 op_type = ?LogOpType::DecryptVmgs,
393 success = true,
394 decrypt_gsp_type = ?derived_keys_result
395 .key_protector_settings
396 .decrypt_gsp_type,
397 encrypt_gsp_type = ?derived_keys_result
398 .key_protector_settings
399 .encrypt_gsp_type,
400 latency = std::time::SystemTime::now().duration_since(start_time).map_or(0, |d| d.as_millis()),
401 "Unlocked datastore"
402 );
403
404 Ok(derived_keys_result
405 .gsp_extended_status_flags
406 .state_refresh_request())
407}
408
409pub async fn initialize_platform_security(
415 get: &GuestEmulationTransportClient,
416 bios_guid: Guid,
417 attestation_vm_config: &AttestationVmConfig,
418 vmgs: &mut Vmgs,
419 tee_call: Option<&dyn TeeCall>,
420 suppress_attestation: bool,
421 driver: LocalDriver,
422 guest_state_encryption_policy: GuestStateEncryptionPolicy,
423 strict_encryption_policy: bool,
424) -> Result<PlatformAttestationData, Error> {
425 const MAXIMUM_RETRY_COUNT: usize = 10;
426 const NO_RETRY_COUNT: usize = 1;
427
428 tracing::info!(CVM_ALLOWED,
429 tee_type=?tee_call.map(|tee| tee.tee_type()),
430 secure_boot=attestation_vm_config.secure_boot,
431 tpm_enabled=attestation_vm_config.tpm_enabled,
432 tpm_persisted=attestation_vm_config.tpm_persisted,
433 "Reading security profile");
434
435 let SecurityProfile { mut agent_data } = vmgs::read_security_profile(vmgs)
439 .await
440 .map_err(AttestationErrorInner::ReadSecurityProfile)?;
441
442 if suppress_attestation {
445 tracing::info!(CVM_ALLOWED, "Suppressing attestation");
446
447 return Ok(PlatformAttestationData {
448 host_attestation_settings: HostAttestationSettings {
449 refresh_tpm_seeds: false,
450 },
451 agent_data: Some(agent_data.to_vec()),
452 guest_secret_key: None,
453 });
454 }
455
456 tracing::info!(CVM_ALLOWED, "Reading VM ID from VMGS");
458 let mut key_protector_by_id = match vmgs::read_key_protector_by_id(vmgs).await {
459 Ok(key_protector_by_id) => KeyProtectorById {
460 inner: key_protector_by_id,
461 found_id: true,
462 },
463 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => KeyProtectorById {
464 inner: openhcl_attestation_protocol::vmgs::KeyProtectorById::new_zeroed(),
465 found_id: false,
466 },
467 Err(e) => { Err(AttestationErrorInner::ReadKeyProtectorById(e)) }?,
468 };
469
470 let vm_id_changed = if key_protector_by_id.found_id {
472 let changed = key_protector_by_id.inner.id_guid != bios_guid;
473 if changed {
474 tracing::info!("VM Id has changed since last boot");
475 };
476 changed
477 } else {
478 false
481 };
482
483 let vmgs_encrypted: bool = vmgs.is_encrypted();
487 let max_retry = if vmgs_encrypted {
488 MAXIMUM_RETRY_COUNT
489 } else {
490 NO_RETRY_COUNT
491 };
492
493 let mut timer = pal_async::timer::PolledTimer::new(&driver);
494 let mut i = 0;
495
496 let state_refresh_request_from_gsp = loop {
497 tracing::info!(CVM_ALLOWED, attempt = i, "attempt to unlock VMGS file");
498
499 let response = try_unlock_vmgs(
500 get,
501 bios_guid,
502 attestation_vm_config,
503 vmgs,
504 tee_call,
505 guest_state_encryption_policy,
506 strict_encryption_policy,
507 &mut agent_data,
508 &mut key_protector_by_id,
509 )
510 .await;
511
512 match response {
513 Ok(b) => break b,
514 Err((e, false)) => Err(e)?,
515 Err((e, true)) => {
516 if i >= max_retry - 1 {
517 Err(e)?
518 }
519 }
520 }
521
522 timer.sleep(std::time::Duration::new(1, 0)).await;
524 i += 1;
525 };
526
527 let host_attestation_settings = HostAttestationSettings {
528 refresh_tpm_seeds: { state_refresh_request_from_gsp | vm_id_changed },
529 };
530
531 tracing::info!(
532 CVM_ALLOWED,
533 state_refresh_request_from_gsp = state_refresh_request_from_gsp,
534 vm_id_changed = vm_id_changed,
535 "determine if refreshing tpm seeds is needed"
536 );
537
538 let guest_secret_key = match vmgs::read_guest_secret_key(vmgs).await {
540 Ok(data) => Some(data.guest_secret_key.to_vec()),
541 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => None,
542 Err(e) => return Err(AttestationErrorInner::ReadGuestSecretKey(e).into()),
543 };
544
545 Ok(PlatformAttestationData {
546 host_attestation_settings,
547 agent_data: Some(agent_data.to_vec()),
548 guest_secret_key,
549 })
550}
551
552async fn unlock_vmgs_data_store(
559 vmgs: &mut Vmgs,
560 vmgs_encrypted: bool,
561 key_protector: &mut KeyProtector,
562 key_protector_by_id: &mut KeyProtectorById,
563 derived_keys: Option<Keys>,
564 key_protector_settings: KeyProtectorSettings,
565 bios_guid: Guid,
566) -> Result<(), UnlockVmgsDataStoreError> {
567 let mut new_key = false; let Some(Keys {
570 ingress: new_ingress_key,
571 decrypt_egress: old_egress_key,
572 encrypt_egress: new_egress_key,
573 }) = derived_keys
574 else {
575 tracing::info!(
576 CVM_ALLOWED,
577 "Encryption disabled, skipping unlock vmgs data store"
578 );
579 return Ok(());
580 };
581
582 if !openssl::memcmp::eq(&new_ingress_key, &new_egress_key) {
583 tracing::trace!(CVM_ALLOWED, "EgressKey is different than IngressKey");
584 new_key = true;
585 }
586
587 let mut provision = false;
589 if vmgs_encrypted {
590 tracing::info!(CVM_ALLOWED, "Decrypting vmgs file...");
591 if let Err(e) = vmgs.unlock_with_encryption_key(&new_ingress_key).await {
592 if let Some(key) = old_egress_key {
593 tracing::info!(CVM_ALLOWED, "Old EgressKey found");
596 vmgs.unlock_with_encryption_key(&key)
597 .await
598 .map_err(UnlockVmgsDataStoreError::VmgsUnlockUsingExistingEgressKey)?;
599 } else {
600 Err(UnlockVmgsDataStoreError::VmgsUnlockUsingExistingIngressKey(
601 e,
602 ))?
603 }
604 }
605 } else {
606 tracing::info!(
608 CVM_ALLOWED,
609 "vmgs data store is not encrypted, provisioning."
610 );
611 provision = true;
612 }
613
614 tracing::info!(
615 CVM_ALLOWED,
616 should_write_kp = key_protector_settings.should_write_kp,
617 use_gsp_by_id = key_protector_settings.use_gsp_by_id,
618 use_hardware_unlock = key_protector_settings.use_hardware_unlock,
619 "key protector settings"
620 );
621
622 if key_protector_settings.should_write_kp {
623 vmgs::write_key_protector(key_protector, vmgs)
625 .await
626 .map_err(UnlockVmgsDataStoreError::WriteKeyProtector)?;
627
628 if key_protector_settings.use_gsp_by_id {
629 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
630 .await
631 .map_err(UnlockVmgsDataStoreError::WriteKeyProtectorById)?;
632 }
633 }
634
635 if provision || new_key {
636 vmgs.update_encryption_key(&new_egress_key, EncryptionAlgorithm::AES_GCM)
640 .await
641 .map_err(UnlockVmgsDataStoreError::UpdateVmgsEncryptionKey)?;
642 }
643
644 persist_all_key_protectors(
646 vmgs,
647 key_protector,
648 key_protector_by_id,
649 bios_guid,
650 key_protector_settings,
651 )
652 .await
653 .map_err(UnlockVmgsDataStoreError::PersistAllKeyProtectors)
654}
655
656async fn get_derived_keys(
673 get: &GuestEmulationTransportClient,
674 tee_call: Option<&dyn TeeCall>,
675 vmgs: &mut Vmgs,
676 key_protector: &mut KeyProtector,
677 key_protector_by_id: &mut KeyProtectorById,
678 bios_guid: Guid,
679 attestation_vm_config: &AttestationVmConfig,
680 is_encrypted: bool,
681 ingress_rsa_kek: Option<&Rsa<Private>>,
682 wrapped_des_key: Option<&[u8]>,
683 tcb_version: Option<u64>,
684 guest_state_encryption_policy: GuestStateEncryptionPolicy,
685 strict_encryption_policy: bool,
686) -> Result<DerivedKeyResult, GetDerivedKeysError> {
687 tracing::info!(
688 CVM_ALLOWED,
689 ?guest_state_encryption_policy,
690 strict_encryption_policy,
691 "encryption policy"
692 );
693
694 if matches!(
696 guest_state_encryption_policy,
697 GuestStateEncryptionPolicy::HardwareSealing
698 ) {
699 todo!("hardware sealing")
700 }
701
702 let mut key_protector_settings = KeyProtectorSettings {
703 should_write_kp: true,
704 use_gsp_by_id: false,
705 use_hardware_unlock: false,
706 decrypt_gsp_type: GspType::None,
707 encrypt_gsp_type: GspType::None,
708 };
709
710 let mut derived_keys = Keys {
711 ingress: [0u8; AES_GCM_KEY_LENGTH],
712 decrypt_egress: None,
713 encrypt_egress: [0u8; AES_GCM_KEY_LENGTH],
714 };
715
716 let ingress_idx = (key_protector.active_kp % 2) as usize;
718 let egress_idx = if ingress_idx == 0 { 1 } else { 0 } as usize;
719
720 let found_dek = !key_protector.dek[ingress_idx]
721 .dek_buffer
722 .iter()
723 .all(|&x| x == 0);
724
725 let (ingress_key, mut decrypt_egress_key, encrypt_egress_key, no_kek) =
727 if let Some(ingress_kek) = ingress_rsa_kek {
728 let keys = match key_protector.unwrap_and_rotate_keys(
729 ingress_kek,
730 wrapped_des_key,
731 ingress_idx,
732 egress_idx,
733 ) {
734 Ok(keys) => keys,
735 Err(e)
736 if matches!(
737 e,
738 GetKeysFromKeyProtectorError::DesKeyRsaUnwrap(_)
739 | GetKeysFromKeyProtectorError::IngressDekRsaUnwrap(_)
740 ) =>
741 {
742 get.event_log_fatal(
743 guest_emulation_transport::api::EventLogId::DEK_DECRYPTION_FAILED,
744 )
745 .await;
746
747 return Err(GetDerivedKeysError::GetKeysFromKeyProtector(e));
748 }
749 Err(e) => return Err(GetDerivedKeysError::GetKeysFromKeyProtector(e)),
750 };
751 (
752 keys.ingress,
753 keys.decrypt_egress,
754 keys.encrypt_egress,
755 false,
756 )
757 } else {
758 (
759 [0u8; AES_GCM_KEY_LENGTH],
760 None,
761 [0u8; AES_GCM_KEY_LENGTH],
762 true,
763 )
764 };
765
766 let existing_unencrypted = !vmgs.is_encrypted() && !vmgs.was_provisioned_this_boot();
768 let is_gsp_by_id = key_protector_by_id.found_id && key_protector_by_id.inner.ported != 1;
769 let is_gsp = key_protector.gsp[ingress_idx].gsp_length != 0;
770 tracing::info!(
771 CVM_ALLOWED,
772 is_encrypted,
773 is_gsp_by_id,
774 is_gsp,
775 found_dek,
776 "initial vmgs encryption state"
777 );
778 let mut requires_gsp_by_id = is_gsp_by_id;
779
780 let (gsp_response, gsp_available, no_gsp, requires_gsp) = {
782 tracing::info!(CVM_ALLOWED, "attempting GSP");
783
784 let response = get_gsp_data(get, key_protector).await;
785
786 tracing::info!(
787 CVM_ALLOWED,
788 request_data_length_in_vmgs = key_protector.gsp[ingress_idx].gsp_length,
789 no_rpc_server = response.extended_status_flags.no_rpc_server(),
790 requires_rpc_server = response.extended_status_flags.requires_rpc_server(),
791 encrypted_gsp_length = response.encrypted_gsp.length,
792 "GSP response"
793 );
794
795 let no_gsp_available =
796 response.extended_status_flags.no_rpc_server() || response.encrypted_gsp.length == 0;
797
798 let no_gsp = no_gsp_available
799 || (matches!(
803 guest_state_encryption_policy,
804 GuestStateEncryptionPolicy::Auto
805 ) && (is_gsp_by_id || existing_unencrypted))
806 || (matches!(
808 guest_state_encryption_policy,
809 GuestStateEncryptionPolicy::GspById | GuestStateEncryptionPolicy::None
810 ) && (!is_gsp || strict_encryption_policy));
811
812 let requires_gsp = is_gsp
813 || response.extended_status_flags.requires_rpc_server()
814 || (matches!(
815 guest_state_encryption_policy,
816 GuestStateEncryptionPolicy::GspKey
817 ) && strict_encryption_policy);
818
819 if is_encrypted && !requires_gsp_by_id && !requires_gsp && !found_dek {
822 requires_gsp_by_id = true;
823 }
824
825 (response, !no_gsp_available, no_gsp, requires_gsp)
826 };
827
828 let (gsp_response_by_id, gsp_by_id_available, no_gsp_by_id) = if no_gsp || requires_gsp_by_id {
831 tracing::info!(CVM_ALLOWED, "attempting GSP By Id");
832
833 let gsp_response_by_id = get
834 .guest_state_protection_data_by_id()
835 .await
836 .map_err(GetDerivedKeysError::FetchGuestStateProtectionById)?;
837
838 let no_gsp_by_id_available = gsp_response_by_id.extended_status_flags.no_registry_file();
839
840 let no_gsp_by_id = no_gsp_by_id_available
841 || (matches!(
844 guest_state_encryption_policy,
845 GuestStateEncryptionPolicy::Auto
846 ) && existing_unencrypted)
847 || (matches!(
849 guest_state_encryption_policy,
850 GuestStateEncryptionPolicy::None
851 ) && (!requires_gsp_by_id || strict_encryption_policy));
852
853 if no_gsp_by_id && requires_gsp_by_id {
854 Err(GetDerivedKeysError::GspByIdRequiredButNotFound)?
855 }
856
857 (
858 gsp_response_by_id,
859 Some(!no_gsp_by_id_available),
860 no_gsp_by_id,
861 )
862 } else {
863 (GuestStateProtectionById::new_zeroed(), None, true)
864 };
865
866 if (no_kek && found_dek) || (no_gsp && requires_gsp) || (no_gsp_by_id && requires_gsp_by_id) {
868 let (hardware_key_protector, hardware_derived_keys) = if let Some(tee_call) = tee_call {
870 let hardware_key_protector = match vmgs::read_hardware_key_protector(vmgs).await {
871 Ok(hardware_key_protector) => Some(hardware_key_protector),
872 Err(e) => {
873 tracing::warn!(
875 CVM_ALLOWED,
876 error = &e as &dyn std::error::Error,
877 "failed to read HW_KEY_PROTECTOR from Vmgs"
878 );
879 None
880 }
881 };
882
883 let hardware_derived_keys = tee_call.supports_get_derived_key().and_then(|tee_call| {
884 if let Some(hardware_key_protector) = &hardware_key_protector {
885 match HardwareDerivedKeys::derive_key(
886 tee_call,
887 attestation_vm_config,
888 hardware_key_protector.header.tcb_version,
889 ) {
890 Ok(hardware_derived_key) => Some(hardware_derived_key),
891 Err(e) => {
892 tracing::warn!(
894 CVM_ALLOWED,
895 error = &e as &dyn std::error::Error,
896 "failed to derive hardware keys using HW_KEY_PROTECTOR",
897 );
898 None
899 }
900 }
901 } else {
902 None
903 }
904 });
905
906 (hardware_key_protector, hardware_derived_keys)
907 } else {
908 (None, None)
909 };
910
911 if let (Some(hardware_key_protector), Some(hardware_derived_keys)) =
912 (hardware_key_protector, hardware_derived_keys)
913 {
914 derived_keys.ingress = hardware_key_protector
915 .unseal_key(&hardware_derived_keys)
916 .map_err(GetDerivedKeysError::UnsealIngressKeyUsingHardwareDerivedKeys)?;
917 derived_keys.decrypt_egress = None;
918 derived_keys.encrypt_egress = derived_keys.ingress;
919
920 key_protector_settings.should_write_kp = false;
921 key_protector_settings.use_hardware_unlock = true;
922
923 tracing::warn!(
924 CVM_ALLOWED,
925 "Using hardware-derived key to recover VMGS DEK"
926 );
927
928 return Ok(DerivedKeyResult {
929 derived_keys: Some(derived_keys),
930 key_protector_settings,
931 gsp_extended_status_flags: gsp_response.extended_status_flags,
932 });
933 } else {
934 if no_kek && found_dek {
935 Err(GetDerivedKeysError::GetIngressKeyFromKpFailed)?
936 } else if no_gsp && requires_gsp {
937 Err(GetDerivedKeysError::GetIngressKeyFromKGspFailed)?
938 } else {
939 Err(GetDerivedKeysError::GetIngressKeyFromKGspByIdFailed)?
941 }
942 }
943 }
944
945 tracing::info!(
946 CVM_ALLOWED,
947 kek = !no_kek,
948 gsp_available,
949 gsp = !no_gsp,
950 gsp_by_id_available = ?gsp_by_id_available,
951 gsp_by_id = !no_gsp_by_id,
952 "Encryption sources"
953 );
954
955 if no_kek && no_gsp && no_gsp_by_id {
957 if is_encrypted {
958 Err(GetDerivedKeysError::DisableVmgsEncryptionFailed)?
959 }
960 match guest_state_encryption_policy {
961 GuestStateEncryptionPolicy::GspById
963 | GuestStateEncryptionPolicy::GspKey
964 | GuestStateEncryptionPolicy::HardwareSealing => {
965 Err(GetDerivedKeysError::EncryptionRequiredButNotFound)?
966 }
967 GuestStateEncryptionPolicy::Auto | GuestStateEncryptionPolicy::None => {
968 tracing::info!(CVM_ALLOWED, "No VMGS encryption used.");
969
970 return Ok(DerivedKeyResult {
971 derived_keys: None,
972 key_protector_settings,
973 gsp_extended_status_flags: gsp_response.extended_status_flags,
974 });
975 }
976 }
977 }
978
979 let hardware_derived_keys = tee_call
981 .and_then(|tee_call| tee_call.supports_get_derived_key())
982 .and_then(|tee_call| {
983 if let Some(tcb_version) = tcb_version {
984 match HardwareDerivedKeys::derive_key(tee_call, attestation_vm_config, tcb_version)
985 {
986 Ok(keys) => Some(keys),
987 Err(e) => {
988 tracing::warn!(
990 CVM_ALLOWED,
991 error = &e as &dyn std::error::Error,
992 "failed to derive hardware keys"
993 );
994 None
995 }
996 }
997 } else {
998 None
999 }
1000 });
1001
1002 if no_gsp && no_gsp_by_id {
1004 tracing::info!(CVM_ALLOWED, "No GSP used with SKR");
1005
1006 derived_keys.ingress = ingress_key;
1007 derived_keys.decrypt_egress = decrypt_egress_key;
1008 derived_keys.encrypt_egress = encrypt_egress_key;
1009
1010 if let Some(hardware_derived_keys) = hardware_derived_keys {
1011 let hardware_key_protector = HardwareKeyProtector::seal_key(
1012 &hardware_derived_keys,
1013 &derived_keys.encrypt_egress,
1014 )
1015 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
1016 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
1017 .await
1018 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
1019
1020 tracing::info!(CVM_ALLOWED, "hardware key protector updated (no GSP used)");
1021 }
1022
1023 return Ok(DerivedKeyResult {
1024 derived_keys: Some(derived_keys),
1025 key_protector_settings,
1026 gsp_extended_status_flags: gsp_response.extended_status_flags,
1027 });
1028 }
1029
1030 if (no_kek && no_gsp) || requires_gsp_by_id {
1033 let derived_keys_by_id =
1034 get_derived_keys_by_id(key_protector_by_id, bios_guid, gsp_response_by_id)
1035 .map_err(GetDerivedKeysError::GetDerivedKeyById)?;
1036
1037 if no_kek && no_gsp {
1038 if matches!(
1039 guest_state_encryption_policy,
1040 GuestStateEncryptionPolicy::GspById | GuestStateEncryptionPolicy::Auto
1041 ) {
1042 tracing::info!(CVM_ALLOWED, "Using GspById");
1043 } else {
1044 tracing::warn!(CVM_ALLOWED, "Allowing GspById");
1054 };
1055
1056 key_protector_settings.should_write_kp = false;
1058 key_protector_settings.use_gsp_by_id = true;
1059 key_protector_settings.decrypt_gsp_type = GspType::GspById;
1060 key_protector_settings.encrypt_gsp_type = GspType::GspById;
1061
1062 return Ok(DerivedKeyResult {
1063 derived_keys: Some(derived_keys_by_id),
1064 key_protector_settings,
1065 gsp_extended_status_flags: gsp_response.extended_status_flags,
1066 });
1067 }
1068
1069 derived_keys.ingress = derived_keys_by_id.ingress;
1070
1071 tracing::info!(
1072 CVM_ALLOWED,
1073 op_type = ?LogOpType::ConvertEncryptionType,
1074 "Converting GSP method."
1075 );
1076 }
1077
1078 let egress_seed;
1079 let mut ingress_seed = None;
1080
1081 if requires_gsp_by_id || no_gsp {
1087 if found_dek {
1090 if requires_gsp_by_id {
1091 ingress_seed = Some(
1092 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize]
1093 .to_vec(),
1094 );
1095 key_protector_settings.decrypt_gsp_type = GspType::GspById;
1096 } else {
1097 derived_keys.ingress = ingress_key;
1098 }
1099 } else {
1100 key_protector_settings.decrypt_gsp_type = GspType::GspById;
1101 }
1102
1103 if no_gsp {
1105 egress_seed =
1106 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize].to_vec();
1107 key_protector_settings.use_gsp_by_id = true;
1108 key_protector_settings.encrypt_gsp_type = GspType::GspById;
1109 } else {
1110 egress_seed =
1111 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
1112 key_protector_settings.encrypt_gsp_type = GspType::GspKey;
1113 }
1114 } else {
1115 if gsp_response.decrypted_gsp[ingress_idx].length == 0
1118 && gsp_response.decrypted_gsp[egress_idx].length == 0
1119 {
1120 tracing::info!(CVM_ALLOWED, "Applying GSP.");
1121
1122 egress_seed =
1125 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
1126
1127 if !no_kek {
1130 derived_keys.ingress = ingress_key;
1131 }
1132
1133 key_protector_settings.encrypt_gsp_type = GspType::GspKey;
1134 } else {
1135 tracing::info!(CVM_ALLOWED, "Using existing GSP.");
1136
1137 ingress_seed = Some(
1138 gsp_response.decrypted_gsp[ingress_idx].buffer
1139 [..gsp_response.decrypted_gsp[ingress_idx].length as usize]
1140 .to_vec(),
1141 );
1142
1143 if gsp_response.decrypted_gsp[egress_idx].length == 0 {
1144 egress_seed =
1146 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
1147 } else {
1148 egress_seed = gsp_response.decrypted_gsp[egress_idx].buffer
1153 [..gsp_response.decrypted_gsp[egress_idx].length as usize]
1154 .to_vec();
1155 key_protector_settings.should_write_kp = false;
1156 decrypt_egress_key = Some(encrypt_egress_key);
1157 }
1158
1159 key_protector_settings.decrypt_gsp_type = GspType::GspKey;
1160 key_protector_settings.encrypt_gsp_type = GspType::GspKey;
1161 }
1162 }
1163
1164 if let Some(seed) = ingress_seed {
1166 derived_keys.ingress = crypto::derive_key(&ingress_key, &seed, VMGS_KEY_DERIVE_LABEL)
1167 .map_err(GetDerivedKeysError::DeriveIngressKey)?;
1168 }
1169
1170 derived_keys.decrypt_egress = decrypt_egress_key
1172 .map(|key| crypto::derive_key(&key, &egress_seed, VMGS_KEY_DERIVE_LABEL))
1173 .transpose()
1174 .map_err(GetDerivedKeysError::DeriveEgressKey)?;
1175
1176 derived_keys.encrypt_egress =
1177 crypto::derive_key(&encrypt_egress_key, &egress_seed, VMGS_KEY_DERIVE_LABEL)
1178 .map_err(GetDerivedKeysError::DeriveEgressKey)?;
1179
1180 if key_protector_settings.should_write_kp {
1181 key_protector.gsp[egress_idx]
1183 .gsp_buffer
1184 .copy_from_slice(&gsp_response.encrypted_gsp.buffer);
1185 key_protector.gsp[egress_idx].gsp_length = gsp_response.encrypted_gsp.length;
1186
1187 if let Some(hardware_derived_keys) = hardware_derived_keys {
1188 let hardware_key_protector = HardwareKeyProtector::seal_key(
1189 &hardware_derived_keys,
1190 &derived_keys.encrypt_egress,
1191 )
1192 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
1193
1194 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
1195 .await
1196 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
1197
1198 tracing::info!(CVM_ALLOWED, "hardware key protector updated");
1199 }
1200 }
1201
1202 if matches!(
1203 guest_state_encryption_policy,
1204 GuestStateEncryptionPolicy::GspKey | GuestStateEncryptionPolicy::Auto
1205 ) {
1206 tracing::info!(CVM_ALLOWED, "Using Gsp");
1207 } else {
1208 tracing::warn!(CVM_ALLOWED, "Allowing Gsp");
1215 }
1216
1217 Ok(DerivedKeyResult {
1218 derived_keys: Some(derived_keys),
1219 key_protector_settings,
1220 gsp_extended_status_flags: gsp_response.extended_status_flags,
1221 })
1222}
1223
1224fn get_derived_keys_by_id(
1226 key_protector_by_id: &mut KeyProtectorById,
1227 bios_guid: Guid,
1228 gsp_response_by_id: GuestStateProtectionById,
1229) -> Result<Keys, GetDerivedKeysByIdError> {
1230 let new_egress_key = crypto::derive_key(
1237 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
1238 bios_guid.as_bytes(),
1239 VMGS_KEY_DERIVE_LABEL,
1240 )
1241 .map_err(GetDerivedKeysByIdError::DeriveEgressKeyUsingCurrentVmId)?;
1242
1243 if new_egress_key.len() != AES_GCM_KEY_LENGTH {
1244 Err(GetDerivedKeysByIdError::InvalidDerivedEgressKeySize {
1245 key_size: new_egress_key.len(),
1246 expected_size: AES_GCM_KEY_LENGTH,
1247 })?
1248 }
1249
1250 let new_ingress_key = if key_protector_by_id.inner.id_guid != Guid::default() {
1253 crypto::derive_key(
1255 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
1256 key_protector_by_id.inner.id_guid.as_bytes(),
1257 VMGS_KEY_DERIVE_LABEL,
1258 )
1259 .map_err(GetDerivedKeysByIdError::DeriveIngressKeyUsingKeyProtectorId)?
1260 } else {
1261 new_egress_key
1263 };
1264
1265 if new_ingress_key.len() != AES_GCM_KEY_LENGTH {
1266 Err(GetDerivedKeysByIdError::InvalidDerivedIngressKeySize {
1267 key_size: new_ingress_key.len(),
1268 expected_size: AES_GCM_KEY_LENGTH,
1269 })?
1270 }
1271
1272 Ok(Keys {
1273 ingress: new_ingress_key,
1274 decrypt_egress: None,
1275 encrypt_egress: new_egress_key,
1276 })
1277}
1278
1279async fn get_gsp_data(
1281 get: &GuestEmulationTransportClient,
1282 key_protector: &mut KeyProtector,
1283) -> GuestStateProtection {
1284 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1285 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1286
1287 const_assert_eq!(guest_emulation_transport::api::NUMBER_GSP, NUMBER_KP as u32);
1288 const_assert_eq!(
1289 guest_emulation_transport::api::GSP_CIPHERTEXT_MAX,
1290 GSP_BUFFER_SIZE as u32
1291 );
1292
1293 let mut encrypted_gsp =
1294 [guest_emulation_transport::api::GspCiphertextContent::new_zeroed(); NUMBER_KP];
1295
1296 for (i, gsp) in encrypted_gsp.iter_mut().enumerate().take(NUMBER_KP) {
1297 if key_protector.gsp[i].gsp_length == 0 {
1298 continue;
1299 }
1300
1301 gsp.buffer[..key_protector.gsp[i].gsp_length as usize].copy_from_slice(
1302 &key_protector.gsp[i].gsp_buffer[..key_protector.gsp[i].gsp_length as usize],
1303 );
1304
1305 gsp.length = key_protector.gsp[i].gsp_length;
1306 }
1307
1308 get.guest_state_protection_data(encrypted_gsp, GspExtendedStatusFlags::new())
1309 .await
1310}
1311
1312async fn persist_all_key_protectors(
1314 vmgs: &mut Vmgs,
1315 key_protector: &mut KeyProtector,
1316 key_protector_by_id: &mut KeyProtectorById,
1317 bios_guid: Guid,
1318 key_protector_settings: KeyProtectorSettings,
1319) -> Result<(), PersistAllKeyProtectorsError> {
1320 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1321
1322 if key_protector_settings.use_gsp_by_id && !key_protector_settings.should_write_kp {
1323 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
1324 .await
1325 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1326 } else {
1327 if !key_protector_settings.use_hardware_unlock {
1329 key_protector.dek[key_protector.active_kp as usize % NUMBER_KP]
1331 .dek_buffer
1332 .fill(0);
1333 key_protector.gsp[key_protector.active_kp as usize % NUMBER_KP].gsp_length = 0;
1334 key_protector.active_kp += 1;
1335
1336 vmgs::write_key_protector(key_protector, vmgs)
1337 .await
1338 .map_err(PersistAllKeyProtectorsError::WriteKeyProtector)?;
1339 }
1340
1341 if !key_protector_settings.use_gsp_by_id
1343 && key_protector_by_id.found_id
1344 && key_protector_by_id.inner.ported == 0
1345 {
1346 key_protector_by_id.inner.ported = 1;
1347 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, true, bios_guid)
1348 .await
1349 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1350 }
1351 }
1352
1353 Ok(())
1354}
1355
1356#[cfg(test)]
1358pub mod test_utils {
1359 use tee_call::GetAttestationReportResult;
1360 use tee_call::HW_DERIVED_KEY_LENGTH;
1361 use tee_call::REPORT_DATA_SIZE;
1362 use tee_call::TeeCall;
1363 use tee_call::TeeCallGetDerivedKey;
1364 use tee_call::TeeType;
1365
1366 pub struct MockTeeCall {
1368 pub tcb_version: u64,
1370 }
1371
1372 impl MockTeeCall {
1373 pub fn new(tcb_version: u64) -> Self {
1375 Self { tcb_version }
1376 }
1377 }
1378
1379 impl TeeCall for MockTeeCall {
1380 fn get_attestation_report(
1381 &self,
1382 report_data: &[u8; REPORT_DATA_SIZE],
1383 ) -> Result<GetAttestationReportResult, tee_call::Error> {
1384 let mut report =
1385 [0x6c; openhcl_attestation_protocol::igvm_attest::get::SNP_VM_REPORT_SIZE];
1386 report[..REPORT_DATA_SIZE].copy_from_slice(report_data);
1387
1388 Ok(GetAttestationReportResult {
1389 report: report.to_vec(),
1390 tcb_version: Some(self.tcb_version),
1391 })
1392 }
1393
1394 fn supports_get_derived_key(&self) -> Option<&dyn TeeCallGetDerivedKey> {
1395 Some(self)
1396 }
1397
1398 fn tee_type(&self) -> TeeType {
1399 TeeType::Snp
1401 }
1402 }
1403
1404 impl TeeCallGetDerivedKey for MockTeeCall {
1405 fn get_derived_key(&self, tcb_version: u64) -> Result<[u8; 32], tee_call::Error> {
1406 let mut key: [u8; HW_DERIVED_KEY_LENGTH] = [0xab; HW_DERIVED_KEY_LENGTH];
1408
1409 let tcb = tcb_version.to_le_bytes();
1411 for (i, b) in key.iter_mut().enumerate() {
1412 *b ^= tcb[i % tcb.len()];
1413 }
1414
1415 Ok(key)
1416 }
1417 }
1418
1419 pub struct MockTeeCallNoGetDerivedKey;
1421
1422 impl TeeCall for MockTeeCallNoGetDerivedKey {
1423 fn get_attestation_report(
1424 &self,
1425 report_data: &[u8; REPORT_DATA_SIZE],
1426 ) -> Result<GetAttestationReportResult, tee_call::Error> {
1427 let mut report =
1428 [0x6c; openhcl_attestation_protocol::igvm_attest::get::SNP_VM_REPORT_SIZE];
1429 report[..REPORT_DATA_SIZE].copy_from_slice(report_data);
1430
1431 Ok(GetAttestationReportResult {
1432 report: report.to_vec(),
1433 tcb_version: None,
1434 })
1435 }
1436
1437 fn supports_get_derived_key(&self) -> Option<&dyn TeeCallGetDerivedKey> {
1438 None
1439 }
1440
1441 fn tee_type(&self) -> TeeType {
1442 TeeType::Snp
1444 }
1445 }
1446}
1447
1448#[cfg(test)]
1449mod tests {
1450 use super::*;
1451 use crate::test_utils::MockTeeCallNoGetDerivedKey;
1452 use disk_backend::Disk;
1453 use disklayer_ram::ram_disk;
1454 use get_protocol::GSP_CLEARTEXT_MAX;
1455 use get_protocol::GspExtendedStatusFlags;
1456 use guest_emulation_device::IgvmAgentAction;
1457 use guest_emulation_device::IgvmAgentTestPlan;
1458 use guest_emulation_transport::test_utilities::TestGet;
1459 use key_protector::AES_WRAPPED_AES_KEY_LENGTH;
1460 use openhcl_attestation_protocol::igvm_attest::get::IgvmAttestRequestType;
1461 use openhcl_attestation_protocol::vmgs::DEK_BUFFER_SIZE;
1462 use openhcl_attestation_protocol::vmgs::DekKp;
1463 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1464 use openhcl_attestation_protocol::vmgs::GspKp;
1465 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1466 use pal_async::DefaultDriver;
1467 use pal_async::async_test;
1468 use pal_async::task::Spawn;
1469 use std::collections::VecDeque;
1470 use test_utils::MockTeeCall;
1471 use test_with_tracing::test;
1472 use vmgs_format::EncryptionAlgorithm;
1473 use vmgs_format::FileId;
1474
1475 const ONE_MEGA_BYTE: u64 = 1024 * 1024;
1476
1477 fn new_test_file() -> Disk {
1478 ram_disk(4 * ONE_MEGA_BYTE, false).unwrap()
1479 }
1480
1481 async fn new_formatted_vmgs() -> Vmgs {
1482 let disk = new_test_file();
1483
1484 let mut vmgs = Vmgs::format_new(disk, None).await.unwrap();
1485
1486 assert!(
1487 key_protector_is_empty(&mut vmgs).await,
1488 "Newly formatted VMGS should have an empty key protector"
1489 );
1490 assert!(
1491 key_protector_by_id_is_empty(&mut vmgs).await,
1492 "Newly formatted VMGS should have an empty key protector by id"
1493 );
1494
1495 vmgs
1496 }
1497
1498 async fn key_protector_is_empty(vmgs: &mut Vmgs) -> bool {
1499 let key_protector = vmgs::read_key_protector(vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1500 .await
1501 .unwrap();
1502
1503 key_protector.as_bytes().iter().all(|&b| b == 0)
1504 }
1505
1506 async fn key_protector_by_id_is_empty(vmgs: &mut Vmgs) -> bool {
1507 vmgs::read_key_protector_by_id(vmgs)
1508 .await
1509 .is_err_and(|err| {
1510 matches!(
1511 err,
1512 vmgs::ReadFromVmgsError::EntryNotFound(FileId::VM_UNIQUE_ID)
1513 )
1514 })
1515 }
1516
1517 async fn hardware_key_protector_is_empty(vmgs: &mut Vmgs) -> bool {
1518 vmgs::read_hardware_key_protector(vmgs)
1519 .await
1520 .is_err_and(|err| {
1521 matches!(
1522 err,
1523 vmgs::ReadFromVmgsError::EntryNotFound(FileId::HW_KEY_PROTECTOR)
1524 )
1525 })
1526 }
1527
1528 fn new_key_protector() -> KeyProtector {
1529 assert_eq!(NUMBER_KP, 2);
1531
1532 let ingress_dek = DekKp {
1533 dek_buffer: [1; DEK_BUFFER_SIZE],
1534 };
1535 let egress_dek = DekKp {
1536 dek_buffer: [2; DEK_BUFFER_SIZE],
1537 };
1538 let ingress_gsp = GspKp {
1539 gsp_length: GSP_BUFFER_SIZE as u32,
1540 gsp_buffer: [3; GSP_BUFFER_SIZE],
1541 };
1542 let egress_gsp = GspKp {
1543 gsp_length: GSP_BUFFER_SIZE as u32,
1544 gsp_buffer: [4; GSP_BUFFER_SIZE],
1545 };
1546 KeyProtector {
1547 dek: [ingress_dek, egress_dek],
1548 gsp: [ingress_gsp, egress_gsp],
1549 active_kp: 0,
1550 }
1551 }
1552
1553 fn new_key_protector_by_id(
1554 id_guid: Option<Guid>,
1555 ported: Option<u8>,
1556 found_id: bool,
1557 ) -> KeyProtectorById {
1558 let key_protector_by_id = openhcl_attestation_protocol::vmgs::KeyProtectorById {
1559 id_guid: id_guid.unwrap_or_else(Guid::new_random),
1560 ported: ported.unwrap_or(0),
1561 pad: [0; 3],
1562 };
1563
1564 KeyProtectorById {
1565 inner: key_protector_by_id,
1566 found_id,
1567 }
1568 }
1569
1570 async fn new_test_get(
1571 spawn: impl Spawn,
1572 enable_igvm_attest: bool,
1573 plan: Option<IgvmAgentTestPlan>,
1574 ) -> TestGet {
1575 if enable_igvm_attest {
1576 const TEST_DEVICE_MEMORY_SIZE: u64 = 64;
1577 let dev_test_mem = user_driver_emulated_mock::DeviceTestMemory::new(
1579 TEST_DEVICE_MEMORY_SIZE,
1580 true,
1581 "test-attest",
1582 );
1583
1584 let mut test_get = guest_emulation_transport::test_utilities::new_transport_pair(
1585 spawn,
1586 None,
1587 get_protocol::ProtocolVersion::NICKEL_REV2,
1588 Some(dev_test_mem.guest_memory()),
1589 plan,
1590 )
1591 .await;
1592
1593 test_get.client.set_gpa_allocator(dev_test_mem.dma_client());
1594
1595 test_get
1596 } else {
1597 guest_emulation_transport::test_utilities::new_transport_pair(
1598 spawn,
1599 None,
1600 get_protocol::ProtocolVersion::NICKEL_REV2,
1601 None,
1602 None,
1603 )
1604 .await
1605 }
1606 }
1607
1608 fn new_attestation_vm_config() -> AttestationVmConfig {
1609 AttestationVmConfig {
1610 current_time: None,
1611 root_cert_thumbprint: String::new(),
1612 console_enabled: false,
1613 interactive_console_enabled: false,
1614 secure_boot: false,
1615 tpm_enabled: true,
1616 tpm_persisted: true,
1617 filtered_vpci_devices_allowed: false,
1618 vm_unique_id: String::new(),
1619 }
1620 }
1621
1622 #[async_test]
1623 async fn do_nothing_without_derived_keys() {
1624 let mut vmgs = new_formatted_vmgs().await;
1625
1626 let mut key_protector = new_key_protector();
1627 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1628
1629 let key_protector_settings = KeyProtectorSettings {
1630 should_write_kp: false,
1631 use_gsp_by_id: false,
1632 use_hardware_unlock: false,
1633 decrypt_gsp_type: GspType::None,
1634 encrypt_gsp_type: GspType::None,
1635 };
1636
1637 let bios_guid = Guid::new_random();
1638
1639 unlock_vmgs_data_store(
1640 &mut vmgs,
1641 false,
1642 &mut key_protector,
1643 &mut key_protector_by_id,
1644 None,
1645 key_protector_settings,
1646 bios_guid,
1647 )
1648 .await
1649 .unwrap();
1650
1651 assert!(key_protector_is_empty(&mut vmgs).await);
1652 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1653
1654 let key_protector_settings = KeyProtectorSettings {
1656 should_write_kp: false,
1657 use_gsp_by_id: false,
1658 use_hardware_unlock: false,
1659 decrypt_gsp_type: GspType::None,
1660 encrypt_gsp_type: GspType::None,
1661 };
1662
1663 unlock_vmgs_data_store(
1665 &mut vmgs,
1666 true,
1667 &mut key_protector,
1668 &mut key_protector_by_id,
1669 None,
1670 key_protector_settings,
1671 bios_guid,
1672 )
1673 .await
1674 .unwrap();
1675
1676 assert!(key_protector_is_empty(&mut vmgs).await);
1677 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1678 }
1679
1680 #[async_test]
1681 async fn provision_vmgs_and_rotate_keys() {
1682 let mut vmgs = new_formatted_vmgs().await;
1683
1684 let mut key_protector = new_key_protector();
1685 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1686
1687 let ingress = [1; AES_GCM_KEY_LENGTH];
1688 let egress = [2; AES_GCM_KEY_LENGTH];
1689 let derived_keys = Keys {
1690 ingress,
1691 decrypt_egress: None,
1692 encrypt_egress: egress,
1693 };
1694
1695 let key_protector_settings = KeyProtectorSettings {
1696 should_write_kp: true,
1697 use_gsp_by_id: true,
1698 use_hardware_unlock: false,
1699 decrypt_gsp_type: GspType::GspById,
1700 encrypt_gsp_type: GspType::GspById,
1701 };
1702
1703 let bios_guid = Guid::new_random();
1704
1705 unlock_vmgs_data_store(
1708 &mut vmgs,
1709 false,
1710 &mut key_protector,
1711 &mut key_protector_by_id,
1712 Some(derived_keys),
1713 key_protector_settings,
1714 bios_guid,
1715 )
1716 .await
1717 .unwrap();
1718
1719 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1721
1722 vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1724 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1726
1727 assert!(!key_protector_is_empty(&mut vmgs).await);
1729 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
1730
1731 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1732 .await
1733 .unwrap();
1734 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1735
1736 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1737 assert_eq!(
1738 found_key_protector_by_id.as_bytes(),
1739 key_protector_by_id.inner.as_bytes()
1740 );
1741
1742 let new_egress = [3; AES_GCM_KEY_LENGTH];
1744
1745 let mut new_key_protector = new_key_protector();
1746 let mut new_key_protector_by_id = new_key_protector_by_id(None, None, false);
1747
1748 let key_protector_settings = KeyProtectorSettings {
1749 should_write_kp: true,
1750 use_gsp_by_id: true,
1751 use_hardware_unlock: false,
1752 decrypt_gsp_type: GspType::GspById,
1753 encrypt_gsp_type: GspType::GspById,
1754 };
1755
1756 let derived_keys = Keys {
1758 ingress: egress,
1759 decrypt_egress: None,
1760 encrypt_egress: new_egress,
1761 };
1762
1763 unlock_vmgs_data_store(
1764 &mut vmgs,
1765 true,
1766 &mut new_key_protector,
1767 &mut new_key_protector_by_id,
1768 Some(derived_keys),
1769 key_protector_settings,
1770 bios_guid,
1771 )
1772 .await
1773 .unwrap();
1774
1775 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1777 vmgs.unlock_with_encryption_key(&egress).await.unwrap_err();
1779
1780 vmgs.unlock_with_encryption_key(&new_egress).await.unwrap();
1782 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1784
1785 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1786 .await
1787 .unwrap();
1788 assert_eq!(found_key_protector.as_bytes(), new_key_protector.as_bytes());
1789
1790 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1791 assert_eq!(
1792 found_key_protector_by_id.as_bytes(),
1793 new_key_protector_by_id.inner.as_bytes()
1794 );
1795 }
1796
1797 #[async_test]
1798 async fn unlock_previously_encrypted_vmgs_with_ingress_key() {
1799 let mut vmgs = new_formatted_vmgs().await;
1800
1801 let mut key_protector = new_key_protector();
1802 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1803
1804 let ingress = [1; AES_GCM_KEY_LENGTH];
1805 let egress = [2; AES_GCM_KEY_LENGTH];
1806
1807 let derived_keys = Keys {
1808 ingress,
1809 decrypt_egress: None,
1810 encrypt_egress: egress,
1811 };
1812
1813 vmgs.update_encryption_key(&ingress, EncryptionAlgorithm::AES_GCM)
1814 .await
1815 .unwrap();
1816
1817 vmgs.unlock_with_encryption_key(&ingress).await.unwrap();
1819 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1820
1821 let key_protector_settings = KeyProtectorSettings {
1822 should_write_kp: true,
1823 use_gsp_by_id: true,
1824 use_hardware_unlock: false,
1825 decrypt_gsp_type: GspType::GspById,
1826 encrypt_gsp_type: GspType::GspById,
1827 };
1828
1829 let bios_guid = Guid::new_random();
1830
1831 unlock_vmgs_data_store(
1832 &mut vmgs,
1833 true,
1834 &mut key_protector,
1835 &mut key_protector_by_id,
1836 Some(derived_keys),
1837 key_protector_settings,
1838 bios_guid,
1839 )
1840 .await
1841 .unwrap();
1842
1843 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1845 vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1846 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1848
1849 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1851 .await
1852 .unwrap();
1853 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1854
1855 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1856 assert_eq!(
1857 found_key_protector_by_id.as_bytes(),
1858 key_protector_by_id.inner.as_bytes()
1859 );
1860 }
1861
1862 #[async_test]
1863 async fn failed_to_persist_ingress_key_so_use_egress_key_to_unlock_vmgs() {
1864 let mut vmgs = new_formatted_vmgs().await;
1865
1866 let mut key_protector = new_key_protector();
1867 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1868
1869 let ingress = [1; AES_GCM_KEY_LENGTH];
1870 let decrypt_egress = [2; AES_GCM_KEY_LENGTH];
1871 let encrypt_egress = [3; AES_GCM_KEY_LENGTH];
1872
1873 let derived_keys = Keys {
1874 ingress,
1875 decrypt_egress: Some(decrypt_egress),
1876 encrypt_egress,
1877 };
1878
1879 vmgs.test_add_new_encryption_key(&decrypt_egress, EncryptionAlgorithm::AES_GCM)
1881 .await
1882 .unwrap();
1883 let egress_key_index = vmgs.test_get_active_datastore_key_index().unwrap();
1884 assert_eq!(egress_key_index, 0);
1885
1886 vmgs.unlock_with_encryption_key(&decrypt_egress)
1887 .await
1888 .unwrap();
1889 let found_egress_key_index = vmgs.test_get_active_datastore_key_index().unwrap();
1890 assert_eq!(found_egress_key_index, egress_key_index);
1891
1892 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1894
1895 let key_protector_settings = KeyProtectorSettings {
1896 should_write_kp: true,
1897 use_gsp_by_id: true,
1898 use_hardware_unlock: false,
1899 decrypt_gsp_type: GspType::GspById,
1900 encrypt_gsp_type: GspType::GspById,
1901 };
1902
1903 let bios_guid = Guid::new_random();
1904
1905 unlock_vmgs_data_store(
1906 &mut vmgs,
1907 true,
1908 &mut key_protector,
1909 &mut key_protector_by_id,
1910 Some(derived_keys),
1911 key_protector_settings,
1912 bios_guid,
1913 )
1914 .await
1915 .unwrap();
1916
1917 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1919
1920 vmgs.unlock_with_encryption_key(&decrypt_egress)
1922 .await
1923 .unwrap_err();
1924
1925 vmgs.unlock_with_encryption_key(&encrypt_egress)
1927 .await
1928 .unwrap();
1929 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1930
1931 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1933 .await
1934 .unwrap();
1935 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1936
1937 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1938 assert_eq!(
1939 found_key_protector_by_id.as_bytes(),
1940 key_protector_by_id.inner.as_bytes()
1941 );
1942 }
1943
1944 #[async_test]
1945 async fn fail_to_unlock_vmgs_with_existing_ingress_key() {
1946 let mut vmgs = new_formatted_vmgs().await;
1947
1948 let mut key_protector = new_key_protector();
1949 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1950
1951 let ingress = [1; AES_GCM_KEY_LENGTH];
1952
1953 let derived_keys = Keys {
1955 ingress,
1956 decrypt_egress: None,
1957 encrypt_egress: ingress,
1958 };
1959
1960 let additional_key = [2; AES_GCM_KEY_LENGTH];
1962 let yet_another_key = [3; AES_GCM_KEY_LENGTH];
1963
1964 vmgs.test_add_new_encryption_key(&additional_key, EncryptionAlgorithm::AES_GCM)
1965 .await
1966 .unwrap();
1967 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1968
1969 vmgs.test_add_new_encryption_key(&yet_another_key, EncryptionAlgorithm::AES_GCM)
1970 .await
1971 .unwrap();
1972 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1973
1974 let key_protector_settings = KeyProtectorSettings {
1975 should_write_kp: true,
1976 use_gsp_by_id: true,
1977 use_hardware_unlock: false,
1978 decrypt_gsp_type: GspType::GspById,
1979 encrypt_gsp_type: GspType::GspById,
1980 };
1981
1982 let bios_guid = Guid::new_random();
1983
1984 let unlock_result = unlock_vmgs_data_store(
1985 &mut vmgs,
1986 true,
1987 &mut key_protector,
1988 &mut key_protector_by_id,
1989 Some(derived_keys),
1990 key_protector_settings,
1991 bios_guid,
1992 )
1993 .await;
1994 assert!(unlock_result.is_err());
1995 assert_eq!(
1996 unlock_result.unwrap_err().to_string(),
1997 "failed to unlock vmgs with the existing ingress key".to_string()
1998 );
1999 }
2000
2001 #[async_test]
2002 async fn fail_to_unlock_vmgs_with_new_ingress_key() {
2003 let mut vmgs = new_formatted_vmgs().await;
2004
2005 let mut key_protector = new_key_protector();
2006 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2007
2008 let derived_keys = Keys {
2009 ingress: [1; AES_GCM_KEY_LENGTH],
2010 decrypt_egress: None,
2011 encrypt_egress: [2; AES_GCM_KEY_LENGTH],
2012 };
2013
2014 let additional_key = [3; AES_GCM_KEY_LENGTH];
2016 let yet_another_key = [4; AES_GCM_KEY_LENGTH];
2017
2018 vmgs.test_add_new_encryption_key(&additional_key, EncryptionAlgorithm::AES_GCM)
2019 .await
2020 .unwrap();
2021 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
2022
2023 vmgs.test_add_new_encryption_key(&yet_another_key, EncryptionAlgorithm::AES_GCM)
2024 .await
2025 .unwrap();
2026 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
2027
2028 let key_protector_settings = KeyProtectorSettings {
2029 should_write_kp: true,
2030 use_gsp_by_id: true,
2031 use_hardware_unlock: false,
2032 decrypt_gsp_type: GspType::GspById,
2033 encrypt_gsp_type: GspType::GspById,
2034 };
2035
2036 let bios_guid = Guid::new_random();
2037
2038 let unlock_result = unlock_vmgs_data_store(
2039 &mut vmgs,
2040 true,
2041 &mut key_protector,
2042 &mut key_protector_by_id,
2043 Some(derived_keys),
2044 key_protector_settings,
2045 bios_guid,
2046 )
2047 .await;
2048 assert!(unlock_result.is_err());
2049 assert_eq!(
2050 unlock_result.unwrap_err().to_string(),
2051 "failed to unlock vmgs with the existing ingress key".to_string()
2052 );
2053 }
2054
2055 #[async_test]
2056 async fn get_derived_keys_using_id() {
2057 let bios_guid = Guid::new_random();
2058
2059 let gsp_response_by_id = GuestStateProtectionById {
2060 seed: guest_emulation_transport::api::GspCleartextContent {
2061 length: GSP_CLEARTEXT_MAX,
2062 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
2063 },
2064 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
2065 };
2066
2067 let mut key_protector_by_id =
2070 new_key_protector_by_id(Some(Guid::new_zeroed()), None, false);
2071 let derived_keys =
2072 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
2073 .unwrap();
2074
2075 assert_eq!(derived_keys.ingress, derived_keys.encrypt_egress);
2076
2077 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2080 let derived_keys =
2081 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
2082 .unwrap();
2083
2084 assert_ne!(derived_keys.ingress, derived_keys.encrypt_egress);
2085
2086 let gsp_response_by_id_with_0_length_seed = GuestStateProtectionById {
2088 seed: guest_emulation_transport::api::GspCleartextContent {
2089 length: 0,
2090 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
2091 },
2092 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
2093 };
2094
2095 let derived_keys_response = get_derived_keys_by_id(
2096 &mut key_protector_by_id,
2097 bios_guid,
2098 gsp_response_by_id_with_0_length_seed,
2099 );
2100 assert!(derived_keys_response.is_err());
2101 assert_eq!(
2102 derived_keys_response.unwrap_err().to_string(),
2103 "failed to derive an egress key based on current vm bios guid".to_string()
2104 );
2105 }
2106
2107 #[async_test]
2108 async fn pass_through_persist_all_key_protectors() {
2109 let mut vmgs = new_formatted_vmgs().await;
2110 let mut key_protector = new_key_protector();
2111 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2112 let bios_guid = Guid::new_random();
2113
2114 let kp_copy = key_protector.as_bytes().to_vec();
2116 let active_kp_copy = key_protector.active_kp;
2117
2118 let key_protector_settings = KeyProtectorSettings {
2120 should_write_kp: true,
2121 use_gsp_by_id: true,
2122 use_hardware_unlock: true,
2123 decrypt_gsp_type: GspType::GspById,
2124 encrypt_gsp_type: GspType::GspById,
2125 };
2126 persist_all_key_protectors(
2127 &mut vmgs,
2128 &mut key_protector,
2129 &mut key_protector_by_id,
2130 bios_guid,
2131 key_protector_settings,
2132 )
2133 .await
2134 .unwrap();
2135
2136 assert!(key_protector_is_empty(&mut vmgs).await);
2137 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
2138
2139 assert_eq!(active_kp_copy, key_protector.active_kp);
2141 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
2142 }
2143
2144 #[async_test]
2145 async fn persist_all_key_protectors_write_key_protector_by_id() {
2146 let mut vmgs = new_formatted_vmgs().await;
2147 let mut key_protector = new_key_protector();
2148 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2149 let bios_guid = Guid::new_random();
2150
2151 let kp_copy = key_protector.as_bytes().to_vec();
2153 let active_kp_copy = key_protector.active_kp;
2154
2155 let key_protector_settings = KeyProtectorSettings {
2157 should_write_kp: false,
2158 use_gsp_by_id: true,
2159 use_hardware_unlock: false,
2160 decrypt_gsp_type: GspType::GspById,
2161 encrypt_gsp_type: GspType::GspById,
2162 };
2163 persist_all_key_protectors(
2164 &mut vmgs,
2165 &mut key_protector,
2166 &mut key_protector_by_id,
2167 bios_guid,
2168 key_protector_settings,
2169 )
2170 .await
2171 .unwrap();
2172
2173 assert!(key_protector_is_empty(&mut vmgs).await);
2175 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
2176
2177 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
2178 assert_eq!(
2179 found_key_protector_by_id.as_bytes(),
2180 key_protector_by_id.inner.as_bytes()
2181 );
2182
2183 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
2185 assert_eq!(active_kp_copy, key_protector.active_kp);
2186 }
2187
2188 #[async_test]
2189 async fn persist_all_key_protectors_remove_ingress_kp() {
2190 let mut vmgs = new_formatted_vmgs().await;
2191 let mut key_protector = new_key_protector();
2192 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2193 let bios_guid = Guid::new_random();
2194
2195 let active_kp_copy = key_protector.active_kp;
2197
2198 let key_protector_settings = KeyProtectorSettings {
2201 should_write_kp: true,
2202 use_gsp_by_id: false,
2203 use_hardware_unlock: false,
2204 decrypt_gsp_type: GspType::None,
2205 encrypt_gsp_type: GspType::None,
2206 };
2207 persist_all_key_protectors(
2208 &mut vmgs,
2209 &mut key_protector,
2210 &mut key_protector_by_id,
2211 bios_guid,
2212 key_protector_settings,
2213 )
2214 .await
2215 .unwrap();
2216
2217 assert!(!key_protector_is_empty(&mut vmgs).await);
2218 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
2219
2220 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
2222 .await
2223 .unwrap();
2224
2225 assert!(
2226 found_key_protector.dek[active_kp_copy as usize]
2227 .dek_buffer
2228 .iter()
2229 .all(|&b| b == 0),
2230 );
2231 assert_eq!(
2232 found_key_protector.gsp[active_kp_copy as usize].gsp_length,
2233 0
2234 );
2235 assert_eq!(found_key_protector.active_kp, active_kp_copy + 1);
2236 }
2237
2238 #[async_test]
2239 async fn persist_all_key_protectors_mark_key_protector_by_id_as_not_in_use() {
2240 let mut vmgs = new_formatted_vmgs().await;
2241 let mut key_protector = new_key_protector();
2242 let mut key_protector_by_id = new_key_protector_by_id(None, None, true);
2243 let bios_guid = Guid::new_random();
2244
2245 let key_protector_settings = KeyProtectorSettings {
2248 should_write_kp: true,
2249 use_gsp_by_id: false,
2250 use_hardware_unlock: true,
2251 decrypt_gsp_type: GspType::None,
2252 encrypt_gsp_type: GspType::None,
2253 };
2254
2255 persist_all_key_protectors(
2256 &mut vmgs,
2257 &mut key_protector,
2258 &mut key_protector_by_id,
2259 bios_guid,
2260 key_protector_settings,
2261 )
2262 .await
2263 .unwrap();
2264
2265 assert!(key_protector_is_empty(&mut vmgs).await);
2266 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
2267
2268 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
2270 assert_eq!(found_key_protector_by_id.ported, 1);
2271 assert_eq!(
2272 found_key_protector_by_id.id_guid,
2273 key_protector_by_id.inner.id_guid
2274 );
2275 }
2276
2277 #[async_test]
2280 async fn init_sec_suppress_attestation(driver: DefaultDriver) {
2281 let mut vmgs = new_formatted_vmgs().await;
2282
2283 let agent = SecurityProfile {
2285 agent_data: [0xAA; AGENT_DATA_MAX_SIZE],
2286 };
2287 vmgs.write_file(FileId::ATTEST, agent.as_bytes())
2288 .await
2289 .unwrap();
2290
2291 let get_pair = new_test_get(driver, false, None).await;
2293
2294 let bios_guid = Guid::new_random();
2295 let att_cfg = new_attestation_vm_config();
2296
2297 assert!(!vmgs.is_encrypted());
2299
2300 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2302 let res = initialize_platform_security(
2303 &get_pair.client,
2304 bios_guid,
2305 &att_cfg,
2306 &mut vmgs,
2307 None, true, ldriver,
2310 GuestStateEncryptionPolicy::None,
2311 true,
2312 )
2313 .await
2314 .unwrap();
2315
2316 assert!(!vmgs.is_encrypted());
2318 assert!(key_protector_is_empty(&mut vmgs).await);
2319 assert!(hardware_key_protector_is_empty(&mut vmgs).await);
2320 assert_eq!(res.agent_data.unwrap(), agent.agent_data.to_vec());
2322 assert!(res.guest_secret_key.is_none());
2324 }
2325
2326 #[async_test]
2327 async fn init_sec_secure_key_release_with_wrapped_key_request(driver: DefaultDriver) {
2328 let mut vmgs = new_formatted_vmgs().await;
2329
2330 let get_pair = new_test_get(driver, true, None).await;
2332
2333 let bios_guid = Guid::new_random();
2334 let att_cfg = new_attestation_vm_config();
2335 let tee = MockTeeCall::new(0x1234);
2336
2337 assert!(!vmgs.is_encrypted());
2339
2340 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2342 let res = initialize_platform_security(
2343 &get_pair.client,
2344 bios_guid,
2345 &att_cfg,
2346 &mut vmgs,
2347 Some(&tee),
2348 false,
2349 ldriver.clone(),
2350 GuestStateEncryptionPolicy::Auto,
2351 true,
2352 )
2353 .await
2354 .unwrap();
2355
2356 assert!(vmgs.is_encrypted());
2358 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2359
2360 let key_reference = serde_json::json!({
2363 "key_info": {
2364 "host": "name"
2365 },
2366 "attestation_info": {
2367 "host": "attestation_name"
2368 }
2369 });
2370 let key_reference = serde_json::to_string(&key_reference).unwrap();
2371 let key_reference = key_reference.as_bytes();
2372 let mut expected_agent_data = [0u8; AGENT_DATA_MAX_SIZE];
2373 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2374 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2375 assert!(res.guest_secret_key.is_none());
2377
2378 initialize_platform_security(
2380 &get_pair.client,
2381 bios_guid,
2382 &att_cfg,
2383 &mut vmgs,
2384 Some(&tee),
2385 false,
2386 ldriver,
2387 GuestStateEncryptionPolicy::Auto,
2388 true,
2389 )
2390 .await
2391 .unwrap();
2392
2393 assert!(vmgs.is_encrypted());
2395 }
2396
2397 #[async_test]
2398 async fn init_sec_secure_key_release_without_wrapped_key_request(driver: DefaultDriver) {
2399 let mut vmgs = new_formatted_vmgs().await;
2400
2401 let agent = SecurityProfile {
2403 agent_data: [0xAA; AGENT_DATA_MAX_SIZE],
2404 };
2405 vmgs.write_file(FileId::ATTEST, agent.as_bytes())
2406 .await
2407 .unwrap();
2408
2409 let mut plan = IgvmAgentTestPlan::default();
2411 plan.insert(
2412 IgvmAttestRequestType::WRAPPED_KEY_REQUEST,
2413 VecDeque::from([IgvmAgentAction::NoResponse, IgvmAgentAction::NoResponse]),
2414 );
2415
2416 let get_pair = new_test_get(driver, true, Some(plan)).await;
2418
2419 let bios_guid = Guid::new_random();
2420 let att_cfg = new_attestation_vm_config();
2421 let tee = MockTeeCall::new(0x1234);
2422
2423 assert!(!vmgs.is_encrypted());
2425
2426 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2428 let res = initialize_platform_security(
2429 &get_pair.client,
2430 bios_guid,
2431 &att_cfg,
2432 &mut vmgs,
2433 Some(&tee),
2434 false,
2435 ldriver.clone(),
2436 GuestStateEncryptionPolicy::Auto,
2437 true,
2438 )
2439 .await
2440 .unwrap();
2441
2442 assert!(vmgs.is_encrypted());
2444 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2445 assert_eq!(res.agent_data.clone().unwrap(), agent.agent_data.to_vec());
2447 assert!(res.guest_secret_key.is_none());
2449
2450 let res = initialize_platform_security(
2452 &get_pair.client,
2453 bios_guid,
2454 &att_cfg,
2455 &mut vmgs,
2456 Some(&tee),
2457 false,
2458 ldriver,
2459 GuestStateEncryptionPolicy::Auto,
2460 true,
2461 )
2462 .await
2463 .unwrap();
2464
2465 assert!(vmgs.is_encrypted());
2467 assert_eq!(res.agent_data.clone().unwrap(), agent.agent_data.to_vec());
2469 assert!(res.guest_secret_key.is_none());
2471 }
2472
2473 #[async_test]
2474 async fn init_sec_secure_key_release_hw_sealing_backup(driver: DefaultDriver) {
2475 let mut vmgs = new_formatted_vmgs().await;
2476
2477 let mut plan = IgvmAgentTestPlan::default();
2479 plan.insert(
2480 IgvmAttestRequestType::WRAPPED_KEY_REQUEST,
2481 VecDeque::from([
2482 IgvmAgentAction::RespondSuccess,
2483 IgvmAgentAction::RespondFailure,
2485 IgvmAgentAction::RespondFailure,
2486 IgvmAgentAction::RespondFailure,
2487 IgvmAgentAction::RespondFailure,
2488 IgvmAgentAction::RespondFailure,
2489 IgvmAgentAction::RespondFailure,
2490 IgvmAgentAction::RespondFailure,
2491 IgvmAgentAction::RespondFailure,
2492 IgvmAgentAction::RespondFailure,
2493 IgvmAgentAction::RespondFailure,
2494 ]),
2495 );
2496
2497 let get_pair = new_test_get(driver, true, Some(plan)).await;
2498
2499 let bios_guid = Guid::new_random();
2500 let att_cfg = new_attestation_vm_config();
2501
2502 assert!(!vmgs.is_encrypted());
2504
2505 let tee = MockTeeCall::new(0x1234);
2507 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2508 let res = initialize_platform_security(
2509 &get_pair.client,
2510 bios_guid,
2511 &att_cfg,
2512 &mut vmgs,
2513 Some(&tee),
2514 false,
2515 ldriver.clone(),
2516 GuestStateEncryptionPolicy::Auto,
2517 true,
2518 )
2519 .await
2520 .unwrap();
2521
2522 assert!(vmgs.is_encrypted());
2524 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2525 let key_reference = serde_json::json!({
2528 "key_info": {
2529 "host": "name"
2530 },
2531 "attestation_info": {
2532 "host": "attestation_name"
2533 }
2534 });
2535 let key_reference = serde_json::to_string(&key_reference).unwrap();
2536 let key_reference = key_reference.as_bytes();
2537 let mut expected_agent_data = [0u8; AGENT_DATA_MAX_SIZE];
2538 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2539 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2540 assert!(res.guest_secret_key.is_none());
2542
2543 initialize_platform_security(
2549 &get_pair.client,
2550 bios_guid,
2551 &att_cfg,
2552 &mut vmgs,
2553 Some(&tee),
2554 false,
2555 ldriver,
2556 GuestStateEncryptionPolicy::Auto,
2557 true,
2558 )
2559 .await
2560 .unwrap();
2561
2562 assert!(vmgs.is_encrypted());
2564 }
2565
2566 #[async_test]
2567 async fn init_sec_secure_key_release_no_hw_sealing_backup(driver: DefaultDriver) {
2568 let mut vmgs = new_formatted_vmgs().await;
2569
2570 let mut plan = IgvmAgentTestPlan::default();
2572 plan.insert(
2573 IgvmAttestRequestType::WRAPPED_KEY_REQUEST,
2574 VecDeque::from([
2575 IgvmAgentAction::RespondSuccess,
2576 IgvmAgentAction::RespondFailure,
2578 IgvmAgentAction::RespondFailure,
2579 IgvmAgentAction::RespondFailure,
2580 IgvmAgentAction::RespondFailure,
2581 IgvmAgentAction::RespondFailure,
2582 IgvmAgentAction::RespondFailure,
2583 IgvmAgentAction::RespondFailure,
2584 IgvmAgentAction::RespondFailure,
2585 IgvmAgentAction::RespondFailure,
2586 IgvmAgentAction::RespondFailure,
2587 ]),
2588 );
2589
2590 let get_pair = new_test_get(driver, true, Some(plan)).await;
2591
2592 let bios_guid = Guid::new_random();
2593 let att_cfg = new_attestation_vm_config();
2594 let tee = MockTeeCallNoGetDerivedKey {};
2596
2597 assert!(!vmgs.is_encrypted());
2599
2600 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2602 let res = initialize_platform_security(
2603 &get_pair.client,
2604 bios_guid,
2605 &att_cfg,
2606 &mut vmgs,
2607 Some(&tee),
2608 false,
2609 ldriver.clone(),
2610 GuestStateEncryptionPolicy::Auto,
2611 true,
2612 )
2613 .await
2614 .unwrap();
2615
2616 assert!(vmgs.is_encrypted());
2618 assert!(hardware_key_protector_is_empty(&mut vmgs).await);
2619 let key_reference = serde_json::json!({
2622 "key_info": {
2623 "host": "name"
2624 },
2625 "attestation_info": {
2626 "host": "attestation_name"
2627 }
2628 });
2629 let key_reference = serde_json::to_string(&key_reference).unwrap();
2630 let key_reference = key_reference.as_bytes();
2631 let mut expected_agent_data = [0u8; AGENT_DATA_MAX_SIZE];
2632 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2633 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2634 assert!(res.guest_secret_key.is_none());
2636
2637 let result = initialize_platform_security(
2639 &get_pair.client,
2640 bios_guid,
2641 &att_cfg,
2642 &mut vmgs,
2643 Some(&tee),
2644 false,
2645 ldriver,
2646 GuestStateEncryptionPolicy::Auto,
2647 true,
2648 )
2649 .await;
2650
2651 assert!(result.is_err());
2652 }
2653}