1#![cfg(target_os = "linux")]
10#![forbid(unsafe_code)]
11
12mod hardware_key_sealing;
13mod igvm_attest;
14mod jwt;
15mod key_protector;
16mod secure_key_release;
17mod vmgs;
18
19#[cfg(test)]
20mod test_helpers;
21
22pub use igvm_attest::Error as IgvmAttestError;
23pub use igvm_attest::IgvmAttestRequestHelper;
24pub use igvm_attest::ak_cert::parse_response as parse_ak_cert_response;
25
26use ::vmgs::EncryptionAlgorithm;
27use ::vmgs::GspType;
28use ::vmgs::Vmgs;
29use crypto::rsa::RsaKeyPair;
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 pal_async::local::LocalDriver;
49use secure_key_release::VmgsEncryptionKeys;
50use static_assertions::const_assert_eq;
51use std::fmt::Debug;
52use tee_call::TeeCall;
53use thiserror::Error;
54use zerocopy::FromZeros;
55use zerocopy::IntoBytes;
56
57#[derive(Debug, Error)]
59#[error(transparent)]
60pub struct Error(AttestationErrorInner);
61
62impl<T: Into<AttestationErrorInner>> From<T> for Error {
63 fn from(value: T) -> Self {
64 Self(value.into())
65 }
66}
67
68#[derive(Debug, Error)]
69enum AttestationErrorInner {
70 #[error("read security profile from vmgs")]
71 ReadSecurityProfile(#[source] vmgs::ReadFromVmgsError),
72 #[error("failed to get derived keys")]
73 GetDerivedKeys(#[source] GetDerivedKeysError),
74 #[error("failed to read key protector from vmgs")]
75 ReadKeyProtector(#[source] vmgs::ReadFromVmgsError),
76 #[error("failed to read key protector by id from vmgs")]
77 ReadKeyProtectorById(#[source] vmgs::ReadFromVmgsError),
78 #[error("failed to unlock vmgs data store")]
79 UnlockVmgsDataStore(#[source] UnlockVmgsDataStoreError),
80 #[error("failed to read guest secret key from vmgs")]
81 ReadGuestSecretKey(#[source] vmgs::ReadFromVmgsError),
82}
83
84#[derive(Debug, Error)]
85enum GetDerivedKeysError {
86 #[error("failed to get ingress/egress keys from the the key protector")]
87 GetKeysFromKeyProtector(#[source] GetKeysFromKeyProtectorError),
88 #[error("failed to fetch GSP")]
89 FetchGuestStateProtectionById(
90 #[source] guest_emulation_transport::error::GuestStateProtectionByIdError,
91 ),
92 #[error("GSP By Id required, but no GSP By Id found")]
93 GspByIdRequiredButNotFound,
94 #[error("failed to unseal the ingress key using hardware derived keys")]
95 UnsealIngressKeyUsingHardwareDerivedKeys(
96 #[source] hardware_key_sealing::HardwareKeySealingError,
97 ),
98 #[error("failed to get an ingress key from key protector")]
99 GetIngressKeyFromKpFailed,
100 #[error("failed to get an ingress key from guest state protection")]
101 GetIngressKeyFromKGspFailed,
102 #[error("failed to get an ingress key from guest state protection by id")]
103 GetIngressKeyFromKGspByIdFailed,
104 #[error("Encryption cannot be disabled if VMGS was previously encrypted")]
105 DisableVmgsEncryptionFailed,
106 #[error("VMGS encryption is required, but no encryption sources were found")]
107 EncryptionRequiredButNotFound,
108 #[error("failed to seal the egress key using hardware derived keys")]
109 SealEgressKeyUsingHardwareDerivedKeys(#[source] hardware_key_sealing::HardwareKeySealingError),
110 #[error("failed to write to `FileId::HW_KEY_PROTECTOR` in vmgs")]
111 VmgsWriteHardwareKeyProtector(#[source] vmgs::WriteToVmgsError),
112 #[error("failed to get derived key by id")]
113 GetDerivedKeyById(#[source] GetDerivedKeysByIdError),
114 #[error("failed to derive an ingress key")]
115 DeriveIngressKey(#[source] crypto::kdf::KdfError),
116 #[error("failed to derive an egress key")]
117 DeriveEgressKey(#[source] crypto::kdf::KdfError),
118}
119
120#[derive(Debug, Error)]
121enum GetDerivedKeysByIdError {
122 #[error("failed to derive an egress key based on current vm bios guid")]
123 DeriveEgressKeyUsingCurrentVmId(#[source] crypto::kdf::KdfError),
124 #[error("invalid derived egress key size {key_size}, expected {expected_size}")]
125 InvalidDerivedEgressKeySize {
126 key_size: usize,
127 expected_size: usize,
128 },
129 #[error("failed to derive an ingress key based on key protector Id from vmgs")]
130 DeriveIngressKeyUsingKeyProtectorId(#[source] crypto::kdf::KdfError),
131 #[error("invalid derived egress key size {key_size}, expected {expected_size}")]
132 InvalidDerivedIngressKeySize {
133 key_size: usize,
134 expected_size: usize,
135 },
136}
137
138#[derive(Debug, Error)]
139enum UnlockVmgsDataStoreError {
140 #[error("failed to unlock vmgs with the existing egress key")]
141 VmgsUnlockUsingExistingEgressKey(#[source] ::vmgs::Error),
142 #[error("failed to unlock vmgs with the existing ingress key")]
143 VmgsUnlockUsingExistingIngressKey(#[source] ::vmgs::Error),
144 #[error("failed to write key protector to vmgs")]
145 WriteKeyProtector(#[source] vmgs::WriteToVmgsError),
146 #[error("failed to read key protector by id to vmgs")]
147 WriteKeyProtectorById(#[source] vmgs::WriteToVmgsError),
148 #[error("failed to update the vmgs encryption key")]
149 UpdateVmgsEncryptionKey(#[source] ::vmgs::Error),
150 #[error("failed to persist all key protectors")]
151 PersistAllKeyProtectors(#[source] PersistAllKeyProtectorsError),
152}
153
154#[derive(Debug, Error)]
155enum PersistAllKeyProtectorsError {
156 #[error("failed to write key protector to vmgs")]
157 WriteKeyProtector(#[source] vmgs::WriteToVmgsError),
158 #[error("failed to read key protector by id to vmgs")]
159 WriteKeyProtectorById(#[source] vmgs::WriteToVmgsError),
160}
161
162#[derive(Debug)]
164enum LogOpType {
165 BeginDecryptVmgs,
166 DecryptVmgs,
167 ConvertEncryptionType,
168}
169
170const VMGS_KEY_DERIVE_LABEL: &[u8; 7] = b"VMGSKEY";
172
173fn derive_key(
175 key: &[u8],
176 context: &[u8],
177 label: &[u8],
178) -> Result<[u8; AES_GCM_KEY_LENGTH], crypto::kdf::KdfError> {
179 let output = crypto::kdf::kbkdf_hmac_sha256(key, context, label, AES_GCM_KEY_LENGTH)?;
180 Ok(output.try_into().unwrap())
181}
182
183#[derive(Debug)]
184struct Keys {
185 ingress: [u8; AES_GCM_KEY_LENGTH],
186 decrypt_egress: Option<[u8; AES_GCM_KEY_LENGTH]>,
187 encrypt_egress: [u8; AES_GCM_KEY_LENGTH],
188}
189
190#[derive(Clone, Copy)]
192struct KeyProtectorSettings {
193 should_write_kp: bool,
195 use_gsp_by_id: bool,
197 use_hardware_unlock: bool,
199 decrypt_gsp_type: GspType,
201 encrypt_gsp_type: GspType,
203}
204
205struct KeyProtectorById {
207 pub inner: openhcl_attestation_protocol::vmgs::KeyProtectorById,
209 pub found_id: bool,
211}
212
213pub struct HostAttestationSettings {
215 pub refresh_tpm_seeds: bool,
217}
218
219struct DerivedKeyResult {
221 derived_keys: Option<Keys>,
223 key_protector_settings: KeyProtectorSettings,
225 gsp_extended_status_flags: GspExtendedStatusFlags,
227}
228
229pub struct PlatformAttestationData {
231 pub host_attestation_settings: HostAttestationSettings,
233 pub agent_data: Option<Vec<u8>>,
235 pub guest_secret_key: Option<Vec<u8>>,
237}
238
239#[derive(Debug, MeshPayload, Copy, Clone, PartialEq, Eq)]
242pub enum AttestationType {
243 Snp,
245 Tdx,
247 Vbs,
249 Host,
251}
252
253async fn try_unlock_vmgs(
258 get: &GuestEmulationTransportClient,
259 bios_guid: Guid,
260 attestation_vm_config: &AttestationVmConfig,
261 vmgs: &mut Vmgs,
262 tee_call: Option<&dyn TeeCall>,
263 guest_state_encryption_policy: GuestStateEncryptionPolicy,
264 strict_encryption_policy: bool,
265 agent_data: &mut [u8; AGENT_DATA_MAX_SIZE],
266 key_protector_by_id: &mut KeyProtectorById,
267) -> Result<bool, (AttestationErrorInner, bool)> {
268 let skr_response = if let Some(tee_call) = tee_call {
269 tracing::info!(CVM_ALLOWED, "Retrieving key-encryption key");
270
271 secure_key_release::request_vmgs_encryption_keys(
273 get,
274 tee_call,
275 vmgs,
276 attestation_vm_config,
277 agent_data,
278 )
279 .await
280 } else {
281 tracing::info!(CVM_ALLOWED, "Key-encryption key retrieval not required");
282
283 Ok(VmgsEncryptionKeys::default())
285 };
286
287 let retry = match &skr_response {
288 Ok(_) => false,
289 Err((_, r)) => *r,
290 };
291
292 let skip_hw_unsealing = matches!(
293 &skr_response,
294 Err((
295 secure_key_release::RequestVmgsEncryptionKeysError::ParseIgvmAttestKeyReleaseResponse(
296 igvm_attest::key_release::KeyReleaseError::ParseHeader(
297 igvm_attest::Error::Attestation {
298 skip_hw_unsealing_signal: true,
299 ..
300 },
301 ),
302 ),
303 _,
304 ))
305 );
306
307 let VmgsEncryptionKeys {
308 ingress_rsa_kek,
309 wrapped_des_key,
310 tcb_version,
311 } = match skr_response {
312 Ok(k) => {
313 tracing::info!(CVM_ALLOWED, "Successfully retrieved key-encryption key");
314 k
315 }
316 Err((e, _)) => {
317 tracing::error!(
319 CVM_ALLOWED,
320 error = &e as &dyn std::error::Error,
321 "Failed to retrieve key-encryption key"
322 );
323
324 VmgsEncryptionKeys::default()
325 }
326 };
327
328 let dek_minimal_size = if wrapped_des_key.is_some() {
330 key_protector::AES_WRAPPED_AES_KEY_LENGTH
331 } else {
332 key_protector::RSA_WRAPPED_AES_KEY_LENGTH
333 };
334
335 tracing::info!(
337 CVM_ALLOWED,
338 dek_minimal_size = dek_minimal_size,
339 "Reading key protector from VMGS"
340 );
341 let mut key_protector = vmgs::read_key_protector(vmgs, dek_minimal_size)
342 .await
343 .map_err(|e| (AttestationErrorInner::ReadKeyProtector(e), false))?;
344
345 let start_time = std::time::SystemTime::now();
346 let vmgs_encrypted = vmgs.encrypted();
347 tracing::info!(
348 ?tcb_version,
349 vmgs_encrypted,
350 op_type = ?LogOpType::BeginDecryptVmgs,
351 "Deriving keys"
352 );
353
354 let derived_keys_result = get_derived_keys(
355 get,
356 tee_call,
357 vmgs,
358 &mut key_protector,
359 key_protector_by_id,
360 bios_guid,
361 attestation_vm_config,
362 vmgs_encrypted,
363 ingress_rsa_kek.as_ref(),
364 wrapped_des_key.as_deref(),
365 tcb_version,
366 guest_state_encryption_policy,
367 strict_encryption_policy,
368 skip_hw_unsealing,
369 )
370 .await
371 .map_err(|e| {
372 tracing::error!(
373 CVM_ALLOWED,
374 op_type = ?LogOpType::DecryptVmgs,
375 success = false,
376 err = &e as &dyn std::error::Error,
377 latency = std::time::SystemTime::now()
378 .duration_since(start_time)
379 .map_or(0, |d| d.as_millis()),
380 "Failed to derive keys"
381 );
382 (AttestationErrorInner::GetDerivedKeys(e), retry)
383 })?;
384
385 tracing::info!("Unlocking VMGS");
387 if let Err(e) = unlock_vmgs_data_store(
388 vmgs,
389 vmgs_encrypted,
390 &mut key_protector,
391 key_protector_by_id,
392 derived_keys_result.derived_keys,
393 derived_keys_result.key_protector_settings,
394 bios_guid,
395 )
396 .await
397 {
398 tracing::error!(
399 CVM_ALLOWED,
400 op_type = ?LogOpType::DecryptVmgs,
401 success = false,
402 err = &e as &dyn std::error::Error,
403 latency = std::time::SystemTime::now()
404 .duration_since(start_time)
405 .map_or(0, |d| d.as_millis()),
406 "Failed to unlock datastore"
407 );
408 get.event_log_fatal(guest_emulation_transport::api::EventLogId::ATTESTATION_FAILED)
409 .await;
410
411 Err((AttestationErrorInner::UnlockVmgsDataStore(e), retry))?;
412 }
413
414 tracing::info!(
415 CVM_ALLOWED,
416 op_type = ?LogOpType::DecryptVmgs,
417 success = true,
418 decrypt_gsp_type = ?derived_keys_result
419 .key_protector_settings
420 .decrypt_gsp_type,
421 encrypt_gsp_type = ?derived_keys_result
422 .key_protector_settings
423 .encrypt_gsp_type,
424 latency = std::time::SystemTime::now().duration_since(start_time).map_or(0, |d| d.as_millis()),
425 "Unlocked datastore"
426 );
427
428 Ok(derived_keys_result
429 .gsp_extended_status_flags
430 .state_refresh_request())
431}
432
433pub async fn initialize_platform_security(
439 get: &GuestEmulationTransportClient,
440 bios_guid: Guid,
441 attestation_vm_config: &AttestationVmConfig,
442 vmgs: &mut Vmgs,
443 tee_call: Option<&dyn TeeCall>,
444 suppress_attestation: bool,
445 driver: LocalDriver,
446 guest_state_encryption_policy: GuestStateEncryptionPolicy,
447 strict_encryption_policy: bool,
448) -> Result<PlatformAttestationData, Error> {
449 const MAXIMUM_RETRY_COUNT: usize = 10;
450 const NO_RETRY_COUNT: usize = 1;
451
452 tracing::info!(CVM_ALLOWED,
453 tee_type=?tee_call.map(|tee| tee.tee_type()),
454 secure_boot=attestation_vm_config.secure_boot,
455 tpm_enabled=attestation_vm_config.tpm_enabled,
456 tpm_persisted=attestation_vm_config.tpm_persisted,
457 "Reading security profile");
458
459 let SecurityProfile { mut agent_data } = vmgs::read_security_profile(vmgs)
463 .await
464 .map_err(AttestationErrorInner::ReadSecurityProfile)?;
465
466 if suppress_attestation {
469 tracing::info!(CVM_ALLOWED, "Suppressing attestation");
470
471 return Ok(PlatformAttestationData {
472 host_attestation_settings: HostAttestationSettings {
473 refresh_tpm_seeds: false,
474 },
475 agent_data: Some(agent_data.to_vec()),
476 guest_secret_key: None,
477 });
478 }
479
480 tracing::info!(CVM_ALLOWED, "Reading VM ID from VMGS");
482 let mut key_protector_by_id = match vmgs::read_key_protector_by_id(vmgs).await {
483 Ok(key_protector_by_id) => KeyProtectorById {
484 inner: key_protector_by_id,
485 found_id: true,
486 },
487 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => KeyProtectorById {
488 inner: openhcl_attestation_protocol::vmgs::KeyProtectorById::new_zeroed(),
489 found_id: false,
490 },
491 Err(e) => { Err(AttestationErrorInner::ReadKeyProtectorById(e)) }?,
492 };
493
494 let vm_id_changed = if key_protector_by_id.found_id {
496 let changed = key_protector_by_id.inner.id_guid != bios_guid;
497 if changed {
498 tracing::info!("VM Id has changed since last boot");
499 };
500 changed
501 } else {
502 false
505 };
506
507 let vmgs_encrypted: bool = vmgs.encrypted();
511 let max_retry = if vmgs_encrypted {
512 MAXIMUM_RETRY_COUNT
513 } else {
514 NO_RETRY_COUNT
515 };
516
517 let mut timer = pal_async::timer::PolledTimer::new(&driver);
518 let mut i = 0;
519
520 let state_refresh_request_from_gsp = loop {
521 tracing::info!(CVM_ALLOWED, attempt = i, "attempt to unlock VMGS file");
522
523 let response = try_unlock_vmgs(
524 get,
525 bios_guid,
526 attestation_vm_config,
527 vmgs,
528 tee_call,
529 guest_state_encryption_policy,
530 strict_encryption_policy,
531 &mut agent_data,
532 &mut key_protector_by_id,
533 )
534 .await;
535
536 match response {
537 Ok(b) => break b,
538 Err((e, false)) => Err(e)?,
539 Err((e, true)) => {
540 if i >= max_retry - 1 {
541 Err(e)?
542 }
543 }
544 }
545
546 timer.sleep(std::time::Duration::new(1, 0)).await;
548 i += 1;
549 };
550
551 let host_attestation_settings = HostAttestationSettings {
552 refresh_tpm_seeds: { state_refresh_request_from_gsp | vm_id_changed },
553 };
554
555 tracing::info!(
556 CVM_ALLOWED,
557 state_refresh_request_from_gsp = state_refresh_request_from_gsp,
558 vm_id_changed = vm_id_changed,
559 "determine if refreshing tpm seeds is needed"
560 );
561
562 let guest_secret_key = match vmgs::read_guest_secret_key(vmgs).await {
564 Ok(data) => Some(data.guest_secret_key.to_vec()),
565 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => None,
566 Err(e) => return Err(AttestationErrorInner::ReadGuestSecretKey(e).into()),
567 };
568
569 Ok(PlatformAttestationData {
570 host_attestation_settings,
571 agent_data: Some(agent_data.to_vec()),
572 guest_secret_key,
573 })
574}
575
576async fn unlock_vmgs_data_store(
583 vmgs: &mut Vmgs,
584 vmgs_encrypted: bool,
585 key_protector: &mut KeyProtector,
586 key_protector_by_id: &mut KeyProtectorById,
587 derived_keys: Option<Keys>,
588 key_protector_settings: KeyProtectorSettings,
589 bios_guid: Guid,
590) -> Result<(), UnlockVmgsDataStoreError> {
591 let mut new_key = false; let Some(Keys {
594 ingress: new_ingress_key,
595 decrypt_egress: old_egress_key,
596 encrypt_egress: new_egress_key,
597 }) = derived_keys
598 else {
599 tracing::info!(
600 CVM_ALLOWED,
601 "Encryption disabled, skipping unlock vmgs data store"
602 );
603 return Ok(());
604 };
605
606 if !constant_time_eq::constant_time_eq(&new_ingress_key, &new_egress_key) {
607 tracing::trace!(CVM_ALLOWED, "EgressKey is different than IngressKey");
608 new_key = true;
609 }
610
611 let mut provision = false;
613 if vmgs_encrypted {
614 tracing::info!(CVM_ALLOWED, "Decrypting vmgs file...");
615 if let Err(e) = vmgs.unlock_with_encryption_key(&new_ingress_key).await {
616 if let Some(key) = old_egress_key {
617 tracing::info!(CVM_ALLOWED, "Old EgressKey found");
620 vmgs.unlock_with_encryption_key(&key)
621 .await
622 .map_err(UnlockVmgsDataStoreError::VmgsUnlockUsingExistingEgressKey)?;
623 } else {
624 Err(UnlockVmgsDataStoreError::VmgsUnlockUsingExistingIngressKey(
625 e,
626 ))?
627 }
628 }
629 } else {
630 tracing::info!(
632 CVM_ALLOWED,
633 "vmgs data store is not encrypted, provisioning."
634 );
635 provision = true;
636 }
637
638 tracing::info!(
639 CVM_ALLOWED,
640 should_write_kp = key_protector_settings.should_write_kp,
641 use_gsp_by_id = key_protector_settings.use_gsp_by_id,
642 use_hardware_unlock = key_protector_settings.use_hardware_unlock,
643 "key protector settings"
644 );
645
646 if key_protector_settings.should_write_kp {
647 vmgs::write_key_protector(key_protector, vmgs)
649 .await
650 .map_err(UnlockVmgsDataStoreError::WriteKeyProtector)?;
651
652 if key_protector_settings.use_gsp_by_id {
653 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
654 .await
655 .map_err(UnlockVmgsDataStoreError::WriteKeyProtectorById)?;
656 }
657 }
658
659 if provision || new_key {
660 vmgs.update_encryption_key(&new_egress_key, EncryptionAlgorithm::AES_GCM)
664 .await
665 .map_err(UnlockVmgsDataStoreError::UpdateVmgsEncryptionKey)?;
666 }
667
668 persist_all_key_protectors(
670 vmgs,
671 key_protector,
672 key_protector_by_id,
673 bios_guid,
674 key_protector_settings,
675 )
676 .await
677 .map_err(UnlockVmgsDataStoreError::PersistAllKeyProtectors)
678}
679
680async fn get_derived_keys(
697 get: &GuestEmulationTransportClient,
698 tee_call: Option<&dyn TeeCall>,
699 vmgs: &mut Vmgs,
700 key_protector: &mut KeyProtector,
701 key_protector_by_id: &mut KeyProtectorById,
702 bios_guid: Guid,
703 attestation_vm_config: &AttestationVmConfig,
704 is_encrypted: bool,
705 ingress_rsa_kek: Option<&RsaKeyPair>,
706 wrapped_des_key: Option<&[u8]>,
707 tcb_version: Option<u64>,
708 guest_state_encryption_policy: GuestStateEncryptionPolicy,
709 strict_encryption_policy: bool,
710 skip_hw_unsealing: bool,
711) -> Result<DerivedKeyResult, GetDerivedKeysError> {
712 tracing::info!(
713 CVM_ALLOWED,
714 ?guest_state_encryption_policy,
715 strict_encryption_policy,
716 "encryption policy"
717 );
718
719 if matches!(
721 guest_state_encryption_policy,
722 GuestStateEncryptionPolicy::HardwareSealing
723 ) {
724 todo!("hardware sealing")
725 }
726
727 let mut key_protector_settings = KeyProtectorSettings {
728 should_write_kp: true,
729 use_gsp_by_id: false,
730 use_hardware_unlock: false,
731 decrypt_gsp_type: GspType::None,
732 encrypt_gsp_type: GspType::None,
733 };
734
735 let mut derived_keys = Keys {
736 ingress: [0u8; AES_GCM_KEY_LENGTH],
737 decrypt_egress: None,
738 encrypt_egress: [0u8; AES_GCM_KEY_LENGTH],
739 };
740
741 let ingress_idx = (key_protector.active_kp % 2) as usize;
743 let egress_idx = if ingress_idx == 0 { 1 } else { 0 } as usize;
744
745 let found_dek = !key_protector.dek[ingress_idx]
746 .dek_buffer
747 .iter()
748 .all(|&x| x == 0);
749
750 let (ingress_key, mut decrypt_egress_key, encrypt_egress_key, no_kek) =
752 if let Some(ingress_kek) = ingress_rsa_kek {
753 let keys = match key_protector.unwrap_and_rotate_keys(
754 ingress_kek,
755 wrapped_des_key,
756 ingress_idx,
757 egress_idx,
758 ) {
759 Ok(keys) => keys,
760 Err(e)
761 if matches!(
762 e,
763 GetKeysFromKeyProtectorError::DesKeyRsaUnwrap(_)
764 | GetKeysFromKeyProtectorError::IngressDekRsaUnwrap(_)
765 ) =>
766 {
767 get.event_log_fatal(
768 guest_emulation_transport::api::EventLogId::DEK_DECRYPTION_FAILED,
769 )
770 .await;
771
772 return Err(GetDerivedKeysError::GetKeysFromKeyProtector(e));
773 }
774 Err(e) => return Err(GetDerivedKeysError::GetKeysFromKeyProtector(e)),
775 };
776 (
777 keys.ingress,
778 keys.decrypt_egress,
779 keys.encrypt_egress,
780 false,
781 )
782 } else {
783 (
784 [0u8; AES_GCM_KEY_LENGTH],
785 None,
786 [0u8; AES_GCM_KEY_LENGTH],
787 true,
788 )
789 };
790
791 let existing_unencrypted = !vmgs.encrypted() && !vmgs.was_provisioned_this_boot();
793 let is_gsp_by_id = key_protector_by_id.found_id && key_protector_by_id.inner.ported != 1;
794 let is_gsp = key_protector.gsp[ingress_idx].gsp_length != 0;
795 tracing::info!(
796 CVM_ALLOWED,
797 is_encrypted,
798 is_gsp_by_id,
799 is_gsp,
800 found_dek,
801 "initial vmgs encryption state"
802 );
803 let mut requires_gsp_by_id = is_gsp_by_id;
804
805 let (gsp_response, gsp_available, no_gsp, requires_gsp) = {
807 tracing::info!(CVM_ALLOWED, "attempting GSP");
808
809 let response = get_gsp_data(get, key_protector).await;
810
811 tracing::info!(
812 CVM_ALLOWED,
813 request_data_length_in_vmgs = key_protector.gsp[ingress_idx].gsp_length,
814 no_rpc_server = response.extended_status_flags.no_rpc_server(),
815 requires_rpc_server = response.extended_status_flags.requires_rpc_server(),
816 encrypted_gsp_length = response.encrypted_gsp.length,
817 "GSP response"
818 );
819
820 let no_gsp_available =
821 response.extended_status_flags.no_rpc_server() || response.encrypted_gsp.length == 0;
822
823 let no_gsp = no_gsp_available
824 || (matches!(
828 guest_state_encryption_policy,
829 GuestStateEncryptionPolicy::Auto
830 ) && (is_gsp_by_id || existing_unencrypted))
831 || (matches!(
833 guest_state_encryption_policy,
834 GuestStateEncryptionPolicy::GspById | GuestStateEncryptionPolicy::None
835 ) && (!is_gsp || strict_encryption_policy));
836
837 let requires_gsp = is_gsp
838 || response.extended_status_flags.requires_rpc_server()
839 || (matches!(
840 guest_state_encryption_policy,
841 GuestStateEncryptionPolicy::GspKey
842 ) && strict_encryption_policy);
843
844 if is_encrypted && !requires_gsp_by_id && !requires_gsp && !found_dek {
847 requires_gsp_by_id = true;
848 }
849
850 (response, !no_gsp_available, no_gsp, requires_gsp)
851 };
852
853 let (gsp_response_by_id, gsp_by_id_available, no_gsp_by_id) = if no_gsp || requires_gsp_by_id {
856 tracing::info!(CVM_ALLOWED, "attempting GSP By Id");
857
858 let gsp_response_by_id = get
859 .guest_state_protection_data_by_id()
860 .await
861 .map_err(GetDerivedKeysError::FetchGuestStateProtectionById)?;
862
863 let no_gsp_by_id_available = gsp_response_by_id.extended_status_flags.no_registry_file();
864
865 let no_gsp_by_id = no_gsp_by_id_available
866 || (matches!(
869 guest_state_encryption_policy,
870 GuestStateEncryptionPolicy::Auto
871 ) && existing_unencrypted)
872 || (matches!(
874 guest_state_encryption_policy,
875 GuestStateEncryptionPolicy::None
876 ) && (!requires_gsp_by_id || strict_encryption_policy));
877
878 if no_gsp_by_id && requires_gsp_by_id {
879 Err(GetDerivedKeysError::GspByIdRequiredButNotFound)?
880 }
881
882 (
883 gsp_response_by_id,
884 Some(!no_gsp_by_id_available),
885 no_gsp_by_id,
886 )
887 } else {
888 (GuestStateProtectionById::new_zeroed(), None, true)
889 };
890
891 if (no_kek && found_dek) || (no_gsp && requires_gsp) || (no_gsp_by_id && requires_gsp_by_id) {
893 let (hardware_key_protector, hardware_derived_keys) = if let Some(tee_call) = tee_call {
895 let hardware_key_protector = match vmgs::read_hardware_key_protector(vmgs).await {
896 Ok(hardware_key_protector) => Some(hardware_key_protector),
897 Err(e) => {
898 tracing::warn!(
900 CVM_ALLOWED,
901 error = &e as &dyn std::error::Error,
902 "failed to read HW_KEY_PROTECTOR from Vmgs"
903 );
904 None
905 }
906 };
907
908 let hardware_derived_keys = tee_call.supports_get_derived_key().and_then(|tee_call| {
909 if let Some(hardware_key_protector) = &hardware_key_protector {
910 match HardwareDerivedKeys::derive_key(
911 tee_call,
912 attestation_vm_config,
913 hardware_key_protector.header.tcb_version,
914 ) {
915 Ok(hardware_derived_key) => Some(hardware_derived_key),
916 Err(e) => {
917 tracing::warn!(
919 CVM_ALLOWED,
920 error = &e as &dyn std::error::Error,
921 "failed to derive hardware keys using HW_KEY_PROTECTOR",
922 );
923 None
924 }
925 }
926 } else {
927 None
928 }
929 });
930
931 if skip_hw_unsealing {
937 if hardware_key_protector.is_some() && hardware_derived_keys.is_some() {
938 tracing::warn!(
939 CVM_ALLOWED,
940 "Skipping hardware unsealing of VMGS DEK as signaled by IGVM agent"
941 );
942 get.event_log_fatal(
943 guest_emulation_transport::api::EventLogId::DEK_HARDWARE_UNSEALING_SKIPPED,
944 )
945 .await;
946
947 (None, None)
948 } else {
949 tracing::info!(
950 CVM_ALLOWED,
951 hardware_key_protector = hardware_key_protector.is_some(),
952 hardware_derived_keys = hardware_derived_keys.is_some(),
953 "skip_hw_unsealing signaled but hardware key data not available, \
954 falling through to scheme-specific error"
955 );
956 (None, None)
957 }
958 } else {
959 (hardware_key_protector, hardware_derived_keys)
960 }
961 } else {
962 (None, None)
963 };
964
965 if let (Some(hardware_key_protector), Some(hardware_derived_keys)) =
966 (hardware_key_protector, hardware_derived_keys)
967 {
968 derived_keys.ingress = hardware_key_protector
969 .unseal_key(&hardware_derived_keys)
970 .map_err(GetDerivedKeysError::UnsealIngressKeyUsingHardwareDerivedKeys)?;
971 derived_keys.decrypt_egress = None;
972 derived_keys.encrypt_egress = derived_keys.ingress;
973
974 key_protector_settings.should_write_kp = false;
975 key_protector_settings.use_hardware_unlock = true;
976
977 tracing::warn!(
978 CVM_ALLOWED,
979 "Using hardware-derived key to recover VMGS DEK"
980 );
981
982 return Ok(DerivedKeyResult {
983 derived_keys: Some(derived_keys),
984 key_protector_settings,
985 gsp_extended_status_flags: gsp_response.extended_status_flags,
986 });
987 } else {
988 if no_kek && found_dek {
989 return Err(GetDerivedKeysError::GetIngressKeyFromKpFailed);
990 } else if no_gsp && requires_gsp {
991 return Err(GetDerivedKeysError::GetIngressKeyFromKGspFailed);
992 } else {
993 return Err(GetDerivedKeysError::GetIngressKeyFromKGspByIdFailed);
995 }
996 }
997 }
998
999 tracing::info!(
1000 CVM_ALLOWED,
1001 kek = !no_kek,
1002 gsp_available,
1003 gsp = !no_gsp,
1004 gsp_by_id_available = ?gsp_by_id_available,
1005 gsp_by_id = !no_gsp_by_id,
1006 "Encryption sources"
1007 );
1008
1009 if no_kek && no_gsp && no_gsp_by_id {
1011 if is_encrypted {
1012 Err(GetDerivedKeysError::DisableVmgsEncryptionFailed)?
1013 }
1014 match guest_state_encryption_policy {
1015 GuestStateEncryptionPolicy::GspById
1017 | GuestStateEncryptionPolicy::GspKey
1018 | GuestStateEncryptionPolicy::HardwareSealing => {
1019 Err(GetDerivedKeysError::EncryptionRequiredButNotFound)?
1020 }
1021 GuestStateEncryptionPolicy::Auto | GuestStateEncryptionPolicy::None => {
1022 tracing::info!(CVM_ALLOWED, "No VMGS encryption used.");
1023
1024 return Ok(DerivedKeyResult {
1025 derived_keys: None,
1026 key_protector_settings,
1027 gsp_extended_status_flags: gsp_response.extended_status_flags,
1028 });
1029 }
1030 }
1031 }
1032
1033 let hardware_derived_keys = tee_call
1035 .and_then(|tee_call| tee_call.supports_get_derived_key())
1036 .and_then(|tee_call| {
1037 if let Some(tcb_version) = tcb_version {
1038 match HardwareDerivedKeys::derive_key(tee_call, attestation_vm_config, tcb_version)
1039 {
1040 Ok(keys) => Some(keys),
1041 Err(e) => {
1042 tracing::warn!(
1044 CVM_ALLOWED,
1045 error = &e as &dyn std::error::Error,
1046 "failed to derive hardware keys"
1047 );
1048 None
1049 }
1050 }
1051 } else {
1052 None
1053 }
1054 });
1055
1056 if no_gsp && no_gsp_by_id {
1058 tracing::info!(CVM_ALLOWED, "No GSP used with SKR");
1059
1060 derived_keys.ingress = ingress_key;
1061 derived_keys.decrypt_egress = decrypt_egress_key;
1062 derived_keys.encrypt_egress = encrypt_egress_key;
1063
1064 if let Some(hardware_derived_keys) = hardware_derived_keys {
1065 let hardware_key_protector = HardwareKeyProtector::seal_key(
1066 &hardware_derived_keys,
1067 &derived_keys.encrypt_egress,
1068 )
1069 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
1070 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
1071 .await
1072 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
1073
1074 tracing::info!(CVM_ALLOWED, "hardware key protector updated (no GSP used)");
1075 }
1076
1077 return Ok(DerivedKeyResult {
1078 derived_keys: Some(derived_keys),
1079 key_protector_settings,
1080 gsp_extended_status_flags: gsp_response.extended_status_flags,
1081 });
1082 }
1083
1084 if (no_kek && no_gsp) || requires_gsp_by_id {
1087 let derived_keys_by_id =
1088 get_derived_keys_by_id(key_protector_by_id, bios_guid, gsp_response_by_id)
1089 .map_err(GetDerivedKeysError::GetDerivedKeyById)?;
1090
1091 if no_kek && no_gsp {
1092 if matches!(
1093 guest_state_encryption_policy,
1094 GuestStateEncryptionPolicy::GspById | GuestStateEncryptionPolicy::Auto
1095 ) {
1096 tracing::info!(CVM_ALLOWED, "Using GspById");
1097 } else {
1098 tracing::warn!(CVM_ALLOWED, "Allowing GspById");
1108 };
1109
1110 key_protector_settings.should_write_kp = false;
1112 key_protector_settings.use_gsp_by_id = true;
1113 key_protector_settings.decrypt_gsp_type = GspType::GspById;
1114 key_protector_settings.encrypt_gsp_type = GspType::GspById;
1115
1116 return Ok(DerivedKeyResult {
1117 derived_keys: Some(derived_keys_by_id),
1118 key_protector_settings,
1119 gsp_extended_status_flags: gsp_response.extended_status_flags,
1120 });
1121 }
1122
1123 derived_keys.ingress = derived_keys_by_id.ingress;
1124
1125 tracing::info!(
1126 CVM_ALLOWED,
1127 op_type = ?LogOpType::ConvertEncryptionType,
1128 "Converting GSP method."
1129 );
1130 }
1131
1132 let egress_seed;
1133 let mut ingress_seed = None;
1134
1135 if requires_gsp_by_id || no_gsp {
1141 if found_dek {
1144 if requires_gsp_by_id {
1145 ingress_seed = Some(
1146 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize]
1147 .to_vec(),
1148 );
1149 key_protector_settings.decrypt_gsp_type = GspType::GspById;
1150 } else {
1151 derived_keys.ingress = ingress_key;
1152 }
1153 } else {
1154 key_protector_settings.decrypt_gsp_type = GspType::GspById;
1155 }
1156
1157 if no_gsp {
1159 egress_seed =
1160 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize].to_vec();
1161 key_protector_settings.use_gsp_by_id = true;
1162 key_protector_settings.encrypt_gsp_type = GspType::GspById;
1163 } else {
1164 egress_seed =
1165 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
1166 key_protector_settings.encrypt_gsp_type = GspType::GspKey;
1167 }
1168 } else {
1169 if gsp_response.decrypted_gsp[ingress_idx].length == 0
1172 && gsp_response.decrypted_gsp[egress_idx].length == 0
1173 {
1174 tracing::info!(CVM_ALLOWED, "Applying GSP.");
1175
1176 egress_seed =
1179 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
1180
1181 if !no_kek {
1184 derived_keys.ingress = ingress_key;
1185 }
1186
1187 key_protector_settings.encrypt_gsp_type = GspType::GspKey;
1188 } else {
1189 tracing::info!(CVM_ALLOWED, "Using existing GSP.");
1190
1191 ingress_seed = Some(
1192 gsp_response.decrypted_gsp[ingress_idx].buffer
1193 [..gsp_response.decrypted_gsp[ingress_idx].length as usize]
1194 .to_vec(),
1195 );
1196
1197 if gsp_response.decrypted_gsp[egress_idx].length == 0 {
1198 egress_seed =
1200 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
1201 } else {
1202 egress_seed = gsp_response.decrypted_gsp[egress_idx].buffer
1207 [..gsp_response.decrypted_gsp[egress_idx].length as usize]
1208 .to_vec();
1209 key_protector_settings.should_write_kp = false;
1210 decrypt_egress_key = Some(encrypt_egress_key);
1211 }
1212
1213 key_protector_settings.decrypt_gsp_type = GspType::GspKey;
1214 key_protector_settings.encrypt_gsp_type = GspType::GspKey;
1215 }
1216 }
1217
1218 if let Some(seed) = ingress_seed {
1220 derived_keys.ingress = derive_key(&ingress_key, &seed, VMGS_KEY_DERIVE_LABEL)
1221 .map_err(GetDerivedKeysError::DeriveIngressKey)?;
1222 }
1223
1224 derived_keys.decrypt_egress = decrypt_egress_key
1226 .map(|key| derive_key(&key, &egress_seed, VMGS_KEY_DERIVE_LABEL))
1227 .transpose()
1228 .map_err(GetDerivedKeysError::DeriveEgressKey)?;
1229
1230 derived_keys.encrypt_egress =
1231 derive_key(&encrypt_egress_key, &egress_seed, VMGS_KEY_DERIVE_LABEL)
1232 .map_err(GetDerivedKeysError::DeriveEgressKey)?;
1233
1234 if key_protector_settings.should_write_kp {
1235 key_protector.gsp[egress_idx]
1237 .gsp_buffer
1238 .copy_from_slice(&gsp_response.encrypted_gsp.buffer);
1239 key_protector.gsp[egress_idx].gsp_length = gsp_response.encrypted_gsp.length;
1240
1241 if let Some(hardware_derived_keys) = hardware_derived_keys {
1242 let hardware_key_protector = HardwareKeyProtector::seal_key(
1243 &hardware_derived_keys,
1244 &derived_keys.encrypt_egress,
1245 )
1246 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
1247
1248 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
1249 .await
1250 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
1251
1252 tracing::info!(CVM_ALLOWED, "hardware key protector updated");
1253 }
1254 }
1255
1256 if matches!(
1257 guest_state_encryption_policy,
1258 GuestStateEncryptionPolicy::GspKey | GuestStateEncryptionPolicy::Auto
1259 ) {
1260 tracing::info!(CVM_ALLOWED, "Using Gsp");
1261 } else {
1262 tracing::warn!(CVM_ALLOWED, "Allowing Gsp");
1269 }
1270
1271 Ok(DerivedKeyResult {
1272 derived_keys: Some(derived_keys),
1273 key_protector_settings,
1274 gsp_extended_status_flags: gsp_response.extended_status_flags,
1275 })
1276}
1277
1278fn get_derived_keys_by_id(
1280 key_protector_by_id: &mut KeyProtectorById,
1281 bios_guid: Guid,
1282 gsp_response_by_id: GuestStateProtectionById,
1283) -> Result<Keys, GetDerivedKeysByIdError> {
1284 let new_egress_key = derive_key(
1291 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
1292 bios_guid.as_bytes(),
1293 VMGS_KEY_DERIVE_LABEL,
1294 )
1295 .map_err(GetDerivedKeysByIdError::DeriveEgressKeyUsingCurrentVmId)?;
1296
1297 if new_egress_key.len() != AES_GCM_KEY_LENGTH {
1298 Err(GetDerivedKeysByIdError::InvalidDerivedEgressKeySize {
1299 key_size: new_egress_key.len(),
1300 expected_size: AES_GCM_KEY_LENGTH,
1301 })?
1302 }
1303
1304 let new_ingress_key = if key_protector_by_id.inner.id_guid != Guid::default() {
1307 derive_key(
1309 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
1310 key_protector_by_id.inner.id_guid.as_bytes(),
1311 VMGS_KEY_DERIVE_LABEL,
1312 )
1313 .map_err(GetDerivedKeysByIdError::DeriveIngressKeyUsingKeyProtectorId)?
1314 } else {
1315 new_egress_key
1317 };
1318
1319 if new_ingress_key.len() != AES_GCM_KEY_LENGTH {
1320 Err(GetDerivedKeysByIdError::InvalidDerivedIngressKeySize {
1321 key_size: new_ingress_key.len(),
1322 expected_size: AES_GCM_KEY_LENGTH,
1323 })?
1324 }
1325
1326 Ok(Keys {
1327 ingress: new_ingress_key,
1328 decrypt_egress: None,
1329 encrypt_egress: new_egress_key,
1330 })
1331}
1332
1333async fn get_gsp_data(
1335 get: &GuestEmulationTransportClient,
1336 key_protector: &mut KeyProtector,
1337) -> GuestStateProtection {
1338 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1339 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1340
1341 const_assert_eq!(guest_emulation_transport::api::NUMBER_GSP, NUMBER_KP as u32);
1342 const_assert_eq!(
1343 guest_emulation_transport::api::GSP_CIPHERTEXT_MAX,
1344 GSP_BUFFER_SIZE as u32
1345 );
1346
1347 let mut encrypted_gsp =
1348 [guest_emulation_transport::api::GspCiphertextContent::new_zeroed(); NUMBER_KP];
1349
1350 for (i, gsp) in encrypted_gsp.iter_mut().enumerate().take(NUMBER_KP) {
1351 if key_protector.gsp[i].gsp_length == 0 {
1352 continue;
1353 }
1354
1355 gsp.buffer[..key_protector.gsp[i].gsp_length as usize].copy_from_slice(
1356 &key_protector.gsp[i].gsp_buffer[..key_protector.gsp[i].gsp_length as usize],
1357 );
1358
1359 gsp.length = key_protector.gsp[i].gsp_length;
1360 }
1361
1362 get.guest_state_protection_data(encrypted_gsp, GspExtendedStatusFlags::new())
1363 .await
1364}
1365
1366async fn persist_all_key_protectors(
1368 vmgs: &mut Vmgs,
1369 key_protector: &mut KeyProtector,
1370 key_protector_by_id: &mut KeyProtectorById,
1371 bios_guid: Guid,
1372 key_protector_settings: KeyProtectorSettings,
1373) -> Result<(), PersistAllKeyProtectorsError> {
1374 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1375
1376 if key_protector_settings.use_gsp_by_id && !key_protector_settings.should_write_kp {
1377 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
1378 .await
1379 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1380 } else {
1381 if !key_protector_settings.use_hardware_unlock {
1383 key_protector.dek[key_protector.active_kp as usize % NUMBER_KP]
1385 .dek_buffer
1386 .fill(0);
1387 key_protector.gsp[key_protector.active_kp as usize % NUMBER_KP].gsp_length = 0;
1388 key_protector.active_kp += 1;
1389
1390 vmgs::write_key_protector(key_protector, vmgs)
1391 .await
1392 .map_err(PersistAllKeyProtectorsError::WriteKeyProtector)?;
1393 }
1394
1395 if !key_protector_settings.use_gsp_by_id
1397 && key_protector_by_id.found_id
1398 && key_protector_by_id.inner.ported == 0
1399 {
1400 key_protector_by_id.inner.ported = 1;
1401 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, true, bios_guid)
1402 .await
1403 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1404 }
1405 }
1406
1407 Ok(())
1408}
1409
1410#[cfg(test)]
1412pub mod test_utils {
1413 use tee_call::GetAttestationReportResult;
1414 use tee_call::HW_DERIVED_KEY_LENGTH;
1415 use tee_call::REPORT_DATA_SIZE;
1416 use tee_call::TeeCall;
1417 use tee_call::TeeCallGetDerivedKey;
1418 use tee_call::TeeType;
1419
1420 pub struct MockTeeCall {
1422 pub tcb_version: u64,
1424 }
1425
1426 impl MockTeeCall {
1427 pub fn new(tcb_version: u64) -> Self {
1429 Self { tcb_version }
1430 }
1431 }
1432
1433 impl TeeCall for MockTeeCall {
1434 fn get_attestation_report(
1435 &self,
1436 report_data: &[u8; REPORT_DATA_SIZE],
1437 ) -> Result<GetAttestationReportResult, tee_call::Error> {
1438 let mut report =
1439 [0x6c; openhcl_attestation_protocol::igvm_attest::get::SNP_VM_REPORT_SIZE];
1440 report[..REPORT_DATA_SIZE].copy_from_slice(report_data);
1441
1442 Ok(GetAttestationReportResult {
1443 report: report.to_vec(),
1444 tcb_version: Some(self.tcb_version),
1445 })
1446 }
1447
1448 fn supports_get_derived_key(&self) -> Option<&dyn TeeCallGetDerivedKey> {
1449 Some(self)
1450 }
1451
1452 fn tee_type(&self) -> TeeType {
1453 TeeType::Snp
1455 }
1456 }
1457
1458 impl TeeCallGetDerivedKey for MockTeeCall {
1459 fn get_derived_key(&self, tcb_version: u64) -> Result<[u8; 32], tee_call::Error> {
1460 let mut key: [u8; HW_DERIVED_KEY_LENGTH] = [0xab; HW_DERIVED_KEY_LENGTH];
1462
1463 let tcb = tcb_version.to_le_bytes();
1465 for (i, b) in key.iter_mut().enumerate() {
1466 *b ^= tcb[i % tcb.len()];
1467 }
1468
1469 Ok(key)
1470 }
1471 }
1472
1473 pub struct MockTeeCallNoGetDerivedKey;
1475
1476 impl TeeCall for MockTeeCallNoGetDerivedKey {
1477 fn get_attestation_report(
1478 &self,
1479 report_data: &[u8; REPORT_DATA_SIZE],
1480 ) -> Result<GetAttestationReportResult, tee_call::Error> {
1481 let mut report =
1482 [0x6c; openhcl_attestation_protocol::igvm_attest::get::SNP_VM_REPORT_SIZE];
1483 report[..REPORT_DATA_SIZE].copy_from_slice(report_data);
1484
1485 Ok(GetAttestationReportResult {
1486 report: report.to_vec(),
1487 tcb_version: None,
1488 })
1489 }
1490
1491 fn supports_get_derived_key(&self) -> Option<&dyn TeeCallGetDerivedKey> {
1492 None
1493 }
1494
1495 fn tee_type(&self) -> TeeType {
1496 TeeType::Snp
1498 }
1499 }
1500}
1501
1502#[cfg(test)]
1503mod tests {
1504 use super::*;
1505 use crate::test_utils::MockTeeCallNoGetDerivedKey;
1506 use disk_backend::Disk;
1507 use disklayer_ram::ram_disk;
1508 use get_protocol::GSP_CLEARTEXT_MAX;
1509 use get_protocol::GspExtendedStatusFlags;
1510 use guest_emulation_device::IgvmAgentAction;
1511 use guest_emulation_device::IgvmAgentTestPlan;
1512 use guest_emulation_transport::test_utilities::TestGet;
1513 use key_protector::AES_WRAPPED_AES_KEY_LENGTH;
1514 use openhcl_attestation_protocol::igvm_attest::get::IgvmAttestRequestType;
1515 use openhcl_attestation_protocol::vmgs::DEK_BUFFER_SIZE;
1516 use openhcl_attestation_protocol::vmgs::DekKp;
1517 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1518 use openhcl_attestation_protocol::vmgs::GspKp;
1519 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1520 use pal_async::DefaultDriver;
1521 use pal_async::async_test;
1522 use pal_async::task::Spawn;
1523 use std::collections::VecDeque;
1524 use test_utils::MockTeeCall;
1525 use test_with_tracing::test;
1526 use vmgs_format::EncryptionAlgorithm;
1527 use vmgs_format::FileId;
1528
1529 const ONE_MEGA_BYTE: u64 = 1024 * 1024;
1530
1531 fn new_test_file() -> Disk {
1532 ram_disk(4 * ONE_MEGA_BYTE, false).unwrap()
1533 }
1534
1535 async fn new_formatted_vmgs() -> Vmgs {
1536 let disk = new_test_file();
1537
1538 let mut vmgs = Vmgs::format_new(disk, None).await.unwrap();
1539
1540 assert!(
1541 key_protector_is_empty(&mut vmgs).await,
1542 "Newly formatted VMGS should have an empty key protector"
1543 );
1544 assert!(
1545 key_protector_by_id_is_empty(&mut vmgs).await,
1546 "Newly formatted VMGS should have an empty key protector by id"
1547 );
1548
1549 vmgs
1550 }
1551
1552 async fn key_protector_is_empty(vmgs: &mut Vmgs) -> bool {
1553 let key_protector = vmgs::read_key_protector(vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1554 .await
1555 .unwrap();
1556
1557 key_protector.as_bytes().iter().all(|&b| b == 0)
1558 }
1559
1560 async fn key_protector_by_id_is_empty(vmgs: &mut Vmgs) -> bool {
1561 vmgs::read_key_protector_by_id(vmgs)
1562 .await
1563 .is_err_and(|err| {
1564 matches!(
1565 err,
1566 vmgs::ReadFromVmgsError::EntryNotFound(FileId::VM_UNIQUE_ID)
1567 )
1568 })
1569 }
1570
1571 async fn hardware_key_protector_is_empty(vmgs: &mut Vmgs) -> bool {
1572 vmgs::read_hardware_key_protector(vmgs)
1573 .await
1574 .is_err_and(|err| {
1575 matches!(
1576 err,
1577 vmgs::ReadFromVmgsError::EntryNotFound(FileId::HW_KEY_PROTECTOR)
1578 )
1579 })
1580 }
1581
1582 fn new_key_protector() -> KeyProtector {
1583 assert_eq!(NUMBER_KP, 2);
1585
1586 let ingress_dek = DekKp {
1587 dek_buffer: [1; DEK_BUFFER_SIZE],
1588 };
1589 let egress_dek = DekKp {
1590 dek_buffer: [2; DEK_BUFFER_SIZE],
1591 };
1592 let ingress_gsp = GspKp {
1593 gsp_length: GSP_BUFFER_SIZE as u32,
1594 gsp_buffer: [3; GSP_BUFFER_SIZE],
1595 };
1596 let egress_gsp = GspKp {
1597 gsp_length: GSP_BUFFER_SIZE as u32,
1598 gsp_buffer: [4; GSP_BUFFER_SIZE],
1599 };
1600 KeyProtector {
1601 dek: [ingress_dek, egress_dek],
1602 gsp: [ingress_gsp, egress_gsp],
1603 active_kp: 0,
1604 }
1605 }
1606
1607 fn new_key_protector_by_id(
1608 id_guid: Option<Guid>,
1609 ported: Option<u8>,
1610 found_id: bool,
1611 ) -> KeyProtectorById {
1612 let key_protector_by_id = openhcl_attestation_protocol::vmgs::KeyProtectorById {
1613 id_guid: id_guid.unwrap_or_else(Guid::new_random),
1614 ported: ported.unwrap_or(0),
1615 pad: [0; 3],
1616 };
1617
1618 KeyProtectorById {
1619 inner: key_protector_by_id,
1620 found_id,
1621 }
1622 }
1623
1624 async fn new_test_get(
1625 spawn: impl Spawn,
1626 enable_igvm_attest: bool,
1627 plan: Option<IgvmAgentTestPlan>,
1628 ) -> TestGet {
1629 if enable_igvm_attest {
1630 const TEST_DEVICE_MEMORY_SIZE: u64 = 64;
1631 let dev_test_mem = user_driver_emulated_mock::DeviceTestMemory::new(
1633 TEST_DEVICE_MEMORY_SIZE,
1634 true,
1635 "test-attest",
1636 );
1637
1638 let mut test_get = guest_emulation_transport::test_utilities::new_transport_pair(
1639 spawn,
1640 None,
1641 get_protocol::ProtocolVersion::NICKEL_REV2,
1642 Some(dev_test_mem.guest_memory()),
1643 plan,
1644 )
1645 .await;
1646
1647 test_get.client.set_gpa_allocator(dev_test_mem.dma_client());
1648
1649 test_get
1650 } else {
1651 guest_emulation_transport::test_utilities::new_transport_pair(
1652 spawn,
1653 None,
1654 get_protocol::ProtocolVersion::NICKEL_REV2,
1655 None,
1656 None,
1657 )
1658 .await
1659 }
1660 }
1661
1662 fn new_attestation_vm_config() -> AttestationVmConfig {
1663 AttestationVmConfig {
1664 current_time: None,
1665 root_cert_thumbprint: String::new(),
1666 console_enabled: false,
1667 interactive_console_enabled: false,
1668 secure_boot: false,
1669 tpm_enabled: true,
1670 tpm_persisted: true,
1671 filtered_vpci_devices_allowed: false,
1672 vm_unique_id: String::new(),
1673 }
1674 }
1675
1676 #[async_test]
1677 async fn do_nothing_without_derived_keys() {
1678 let mut vmgs = new_formatted_vmgs().await;
1679
1680 let mut key_protector = new_key_protector();
1681 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1682
1683 let key_protector_settings = KeyProtectorSettings {
1684 should_write_kp: false,
1685 use_gsp_by_id: false,
1686 use_hardware_unlock: false,
1687 decrypt_gsp_type: GspType::None,
1688 encrypt_gsp_type: GspType::None,
1689 };
1690
1691 let bios_guid = Guid::new_random();
1692
1693 unlock_vmgs_data_store(
1694 &mut vmgs,
1695 false,
1696 &mut key_protector,
1697 &mut key_protector_by_id,
1698 None,
1699 key_protector_settings,
1700 bios_guid,
1701 )
1702 .await
1703 .unwrap();
1704
1705 assert!(key_protector_is_empty(&mut vmgs).await);
1706 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1707
1708 let key_protector_settings = KeyProtectorSettings {
1710 should_write_kp: false,
1711 use_gsp_by_id: false,
1712 use_hardware_unlock: false,
1713 decrypt_gsp_type: GspType::None,
1714 encrypt_gsp_type: GspType::None,
1715 };
1716
1717 unlock_vmgs_data_store(
1719 &mut vmgs,
1720 true,
1721 &mut key_protector,
1722 &mut key_protector_by_id,
1723 None,
1724 key_protector_settings,
1725 bios_guid,
1726 )
1727 .await
1728 .unwrap();
1729
1730 assert!(key_protector_is_empty(&mut vmgs).await);
1731 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1732 }
1733
1734 #[async_test]
1735 async fn provision_vmgs_and_rotate_keys() {
1736 let mut vmgs = new_formatted_vmgs().await;
1737
1738 let mut key_protector = new_key_protector();
1739 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1740
1741 let ingress = [1; AES_GCM_KEY_LENGTH];
1742 let egress = [2; AES_GCM_KEY_LENGTH];
1743 let derived_keys = Keys {
1744 ingress,
1745 decrypt_egress: None,
1746 encrypt_egress: egress,
1747 };
1748
1749 let key_protector_settings = KeyProtectorSettings {
1750 should_write_kp: true,
1751 use_gsp_by_id: true,
1752 use_hardware_unlock: false,
1753 decrypt_gsp_type: GspType::GspById,
1754 encrypt_gsp_type: GspType::GspById,
1755 };
1756
1757 let bios_guid = Guid::new_random();
1758
1759 unlock_vmgs_data_store(
1762 &mut vmgs,
1763 false,
1764 &mut key_protector,
1765 &mut key_protector_by_id,
1766 Some(derived_keys),
1767 key_protector_settings,
1768 bios_guid,
1769 )
1770 .await
1771 .unwrap();
1772
1773 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1775
1776 vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1778 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1780
1781 assert!(!key_protector_is_empty(&mut vmgs).await);
1783 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
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(), 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 key_protector_by_id.inner.as_bytes()
1794 );
1795
1796 let new_egress = [3; AES_GCM_KEY_LENGTH];
1798
1799 let mut new_key_protector = new_key_protector();
1800 let mut new_key_protector_by_id = new_key_protector_by_id(None, None, false);
1801
1802 let key_protector_settings = KeyProtectorSettings {
1803 should_write_kp: true,
1804 use_gsp_by_id: true,
1805 use_hardware_unlock: false,
1806 decrypt_gsp_type: GspType::GspById,
1807 encrypt_gsp_type: GspType::GspById,
1808 };
1809
1810 let derived_keys = Keys {
1812 ingress: egress,
1813 decrypt_egress: None,
1814 encrypt_egress: new_egress,
1815 };
1816
1817 unlock_vmgs_data_store(
1818 &mut vmgs,
1819 true,
1820 &mut new_key_protector,
1821 &mut new_key_protector_by_id,
1822 Some(derived_keys),
1823 key_protector_settings,
1824 bios_guid,
1825 )
1826 .await
1827 .unwrap();
1828
1829 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1831 vmgs.unlock_with_encryption_key(&egress).await.unwrap_err();
1833
1834 vmgs.unlock_with_encryption_key(&new_egress).await.unwrap();
1836 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1838
1839 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1840 .await
1841 .unwrap();
1842 assert_eq!(found_key_protector.as_bytes(), new_key_protector.as_bytes());
1843
1844 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1845 assert_eq!(
1846 found_key_protector_by_id.as_bytes(),
1847 new_key_protector_by_id.inner.as_bytes()
1848 );
1849 }
1850
1851 #[async_test]
1852 async fn unlock_previously_encrypted_vmgs_with_ingress_key() {
1853 let mut vmgs = new_formatted_vmgs().await;
1854
1855 let mut key_protector = new_key_protector();
1856 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1857
1858 let ingress = [1; AES_GCM_KEY_LENGTH];
1859 let egress = [2; AES_GCM_KEY_LENGTH];
1860
1861 let derived_keys = Keys {
1862 ingress,
1863 decrypt_egress: None,
1864 encrypt_egress: egress,
1865 };
1866
1867 vmgs.update_encryption_key(&ingress, EncryptionAlgorithm::AES_GCM)
1868 .await
1869 .unwrap();
1870
1871 vmgs.unlock_with_encryption_key(&ingress).await.unwrap();
1873 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1874
1875 let key_protector_settings = KeyProtectorSettings {
1876 should_write_kp: true,
1877 use_gsp_by_id: true,
1878 use_hardware_unlock: false,
1879 decrypt_gsp_type: GspType::GspById,
1880 encrypt_gsp_type: GspType::GspById,
1881 };
1882
1883 let bios_guid = Guid::new_random();
1884
1885 unlock_vmgs_data_store(
1886 &mut vmgs,
1887 true,
1888 &mut key_protector,
1889 &mut key_protector_by_id,
1890 Some(derived_keys),
1891 key_protector_settings,
1892 bios_guid,
1893 )
1894 .await
1895 .unwrap();
1896
1897 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1899 vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1900 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1902
1903 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1905 .await
1906 .unwrap();
1907 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1908
1909 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1910 assert_eq!(
1911 found_key_protector_by_id.as_bytes(),
1912 key_protector_by_id.inner.as_bytes()
1913 );
1914 }
1915
1916 #[async_test]
1917 async fn failed_to_persist_ingress_key_so_use_egress_key_to_unlock_vmgs() {
1918 let mut vmgs = new_formatted_vmgs().await;
1919
1920 let mut key_protector = new_key_protector();
1921 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1922
1923 let ingress = [1; AES_GCM_KEY_LENGTH];
1924 let decrypt_egress = [2; AES_GCM_KEY_LENGTH];
1925 let encrypt_egress = [3; AES_GCM_KEY_LENGTH];
1926
1927 let derived_keys = Keys {
1928 ingress,
1929 decrypt_egress: Some(decrypt_egress),
1930 encrypt_egress,
1931 };
1932
1933 vmgs.test_add_new_encryption_key(&decrypt_egress, EncryptionAlgorithm::AES_GCM)
1935 .await
1936 .unwrap();
1937 let egress_key_index = vmgs.test_get_active_datastore_key_index().unwrap();
1938 assert_eq!(egress_key_index, 0);
1939
1940 vmgs.unlock_with_encryption_key(&decrypt_egress)
1941 .await
1942 .unwrap();
1943 let found_egress_key_index = vmgs.test_get_active_datastore_key_index().unwrap();
1944 assert_eq!(found_egress_key_index, egress_key_index);
1945
1946 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1948
1949 let key_protector_settings = KeyProtectorSettings {
1950 should_write_kp: true,
1951 use_gsp_by_id: true,
1952 use_hardware_unlock: false,
1953 decrypt_gsp_type: GspType::GspById,
1954 encrypt_gsp_type: GspType::GspById,
1955 };
1956
1957 let bios_guid = Guid::new_random();
1958
1959 unlock_vmgs_data_store(
1960 &mut vmgs,
1961 true,
1962 &mut key_protector,
1963 &mut key_protector_by_id,
1964 Some(derived_keys),
1965 key_protector_settings,
1966 bios_guid,
1967 )
1968 .await
1969 .unwrap();
1970
1971 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1973
1974 vmgs.unlock_with_encryption_key(&decrypt_egress)
1976 .await
1977 .unwrap_err();
1978
1979 vmgs.unlock_with_encryption_key(&encrypt_egress)
1981 .await
1982 .unwrap();
1983 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1984
1985 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1987 .await
1988 .unwrap();
1989 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1990
1991 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1992 assert_eq!(
1993 found_key_protector_by_id.as_bytes(),
1994 key_protector_by_id.inner.as_bytes()
1995 );
1996 }
1997
1998 #[async_test]
1999 async fn fail_to_unlock_vmgs_with_existing_ingress_key() {
2000 let mut vmgs = new_formatted_vmgs().await;
2001
2002 let mut key_protector = new_key_protector();
2003 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2004
2005 let ingress = [1; AES_GCM_KEY_LENGTH];
2006
2007 let derived_keys = Keys {
2009 ingress,
2010 decrypt_egress: None,
2011 encrypt_egress: ingress,
2012 };
2013
2014 let additional_key = [2; AES_GCM_KEY_LENGTH];
2016 let yet_another_key = [3; 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 fail_to_unlock_vmgs_with_new_ingress_key() {
2057 let mut vmgs = new_formatted_vmgs().await;
2058
2059 let mut key_protector = new_key_protector();
2060 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2061
2062 let derived_keys = Keys {
2063 ingress: [1; AES_GCM_KEY_LENGTH],
2064 decrypt_egress: None,
2065 encrypt_egress: [2; AES_GCM_KEY_LENGTH],
2066 };
2067
2068 let additional_key = [3; AES_GCM_KEY_LENGTH];
2070 let yet_another_key = [4; AES_GCM_KEY_LENGTH];
2071
2072 vmgs.test_add_new_encryption_key(&additional_key, EncryptionAlgorithm::AES_GCM)
2073 .await
2074 .unwrap();
2075 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
2076
2077 vmgs.test_add_new_encryption_key(&yet_another_key, EncryptionAlgorithm::AES_GCM)
2078 .await
2079 .unwrap();
2080 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
2081
2082 let key_protector_settings = KeyProtectorSettings {
2083 should_write_kp: true,
2084 use_gsp_by_id: true,
2085 use_hardware_unlock: false,
2086 decrypt_gsp_type: GspType::GspById,
2087 encrypt_gsp_type: GspType::GspById,
2088 };
2089
2090 let bios_guid = Guid::new_random();
2091
2092 let unlock_result = unlock_vmgs_data_store(
2093 &mut vmgs,
2094 true,
2095 &mut key_protector,
2096 &mut key_protector_by_id,
2097 Some(derived_keys),
2098 key_protector_settings,
2099 bios_guid,
2100 )
2101 .await;
2102 assert!(unlock_result.is_err());
2103 assert_eq!(
2104 unlock_result.unwrap_err().to_string(),
2105 "failed to unlock vmgs with the existing ingress key".to_string()
2106 );
2107 }
2108
2109 #[async_test]
2110 async fn get_derived_keys_using_id() {
2111 let bios_guid = Guid::new_random();
2112
2113 let gsp_response_by_id = GuestStateProtectionById {
2114 seed: guest_emulation_transport::api::GspCleartextContent {
2115 length: GSP_CLEARTEXT_MAX,
2116 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
2117 },
2118 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
2119 };
2120
2121 let mut key_protector_by_id =
2124 new_key_protector_by_id(Some(Guid::new_zeroed()), None, false);
2125 let derived_keys =
2126 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
2127 .unwrap();
2128
2129 assert_eq!(derived_keys.ingress, derived_keys.encrypt_egress);
2130
2131 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2134 let derived_keys =
2135 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
2136 .unwrap();
2137
2138 assert_ne!(derived_keys.ingress, derived_keys.encrypt_egress);
2139
2140 let gsp_response_by_id_with_0_length_seed = GuestStateProtectionById {
2142 seed: guest_emulation_transport::api::GspCleartextContent {
2143 length: 0,
2144 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
2145 },
2146 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
2147 };
2148
2149 let derived_keys_response = get_derived_keys_by_id(
2150 &mut key_protector_by_id,
2151 bios_guid,
2152 gsp_response_by_id_with_0_length_seed,
2153 );
2154 assert!(derived_keys_response.is_err());
2155 assert_eq!(
2156 derived_keys_response.unwrap_err().to_string(),
2157 "failed to derive an egress key based on current vm bios guid".to_string()
2158 );
2159 }
2160
2161 #[async_test]
2162 async fn pass_through_persist_all_key_protectors() {
2163 let mut vmgs = new_formatted_vmgs().await;
2164 let mut key_protector = new_key_protector();
2165 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2166 let bios_guid = Guid::new_random();
2167
2168 let kp_copy = key_protector.as_bytes().to_vec();
2170 let active_kp_copy = key_protector.active_kp;
2171
2172 let key_protector_settings = KeyProtectorSettings {
2174 should_write_kp: true,
2175 use_gsp_by_id: true,
2176 use_hardware_unlock: true,
2177 decrypt_gsp_type: GspType::GspById,
2178 encrypt_gsp_type: GspType::GspById,
2179 };
2180 persist_all_key_protectors(
2181 &mut vmgs,
2182 &mut key_protector,
2183 &mut key_protector_by_id,
2184 bios_guid,
2185 key_protector_settings,
2186 )
2187 .await
2188 .unwrap();
2189
2190 assert!(key_protector_is_empty(&mut vmgs).await);
2191 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
2192
2193 assert_eq!(active_kp_copy, key_protector.active_kp);
2195 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
2196 }
2197
2198 #[async_test]
2199 async fn persist_all_key_protectors_write_key_protector_by_id() {
2200 let mut vmgs = new_formatted_vmgs().await;
2201 let mut key_protector = new_key_protector();
2202 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2203 let bios_guid = Guid::new_random();
2204
2205 let kp_copy = key_protector.as_bytes().to_vec();
2207 let active_kp_copy = key_protector.active_kp;
2208
2209 let key_protector_settings = KeyProtectorSettings {
2211 should_write_kp: false,
2212 use_gsp_by_id: true,
2213 use_hardware_unlock: false,
2214 decrypt_gsp_type: GspType::GspById,
2215 encrypt_gsp_type: GspType::GspById,
2216 };
2217 persist_all_key_protectors(
2218 &mut vmgs,
2219 &mut key_protector,
2220 &mut key_protector_by_id,
2221 bios_guid,
2222 key_protector_settings,
2223 )
2224 .await
2225 .unwrap();
2226
2227 assert!(key_protector_is_empty(&mut vmgs).await);
2229 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
2230
2231 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
2232 assert_eq!(
2233 found_key_protector_by_id.as_bytes(),
2234 key_protector_by_id.inner.as_bytes()
2235 );
2236
2237 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
2239 assert_eq!(active_kp_copy, key_protector.active_kp);
2240 }
2241
2242 #[async_test]
2243 async fn persist_all_key_protectors_remove_ingress_kp() {
2244 let mut vmgs = new_formatted_vmgs().await;
2245 let mut key_protector = new_key_protector();
2246 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2247 let bios_guid = Guid::new_random();
2248
2249 let active_kp_copy = key_protector.active_kp;
2251
2252 let key_protector_settings = KeyProtectorSettings {
2255 should_write_kp: true,
2256 use_gsp_by_id: false,
2257 use_hardware_unlock: false,
2258 decrypt_gsp_type: GspType::None,
2259 encrypt_gsp_type: GspType::None,
2260 };
2261 persist_all_key_protectors(
2262 &mut vmgs,
2263 &mut key_protector,
2264 &mut key_protector_by_id,
2265 bios_guid,
2266 key_protector_settings,
2267 )
2268 .await
2269 .unwrap();
2270
2271 assert!(!key_protector_is_empty(&mut vmgs).await);
2272 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
2273
2274 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
2276 .await
2277 .unwrap();
2278
2279 assert!(
2280 found_key_protector.dek[active_kp_copy as usize]
2281 .dek_buffer
2282 .iter()
2283 .all(|&b| b == 0),
2284 );
2285 assert_eq!(
2286 found_key_protector.gsp[active_kp_copy as usize].gsp_length,
2287 0
2288 );
2289 assert_eq!(found_key_protector.active_kp, active_kp_copy + 1);
2290 }
2291
2292 #[async_test]
2293 async fn persist_all_key_protectors_mark_key_protector_by_id_as_not_in_use() {
2294 let mut vmgs = new_formatted_vmgs().await;
2295 let mut key_protector = new_key_protector();
2296 let mut key_protector_by_id = new_key_protector_by_id(None, None, true);
2297 let bios_guid = Guid::new_random();
2298
2299 let key_protector_settings = KeyProtectorSettings {
2302 should_write_kp: true,
2303 use_gsp_by_id: false,
2304 use_hardware_unlock: true,
2305 decrypt_gsp_type: GspType::None,
2306 encrypt_gsp_type: GspType::None,
2307 };
2308
2309 persist_all_key_protectors(
2310 &mut vmgs,
2311 &mut key_protector,
2312 &mut key_protector_by_id,
2313 bios_guid,
2314 key_protector_settings,
2315 )
2316 .await
2317 .unwrap();
2318
2319 assert!(key_protector_is_empty(&mut vmgs).await);
2320 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
2321
2322 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
2324 assert_eq!(found_key_protector_by_id.ported, 1);
2325 assert_eq!(
2326 found_key_protector_by_id.id_guid,
2327 key_protector_by_id.inner.id_guid
2328 );
2329 }
2330
2331 #[async_test]
2334 async fn init_sec_suppress_attestation(driver: DefaultDriver) {
2335 let mut vmgs = new_formatted_vmgs().await;
2336
2337 let agent = SecurityProfile {
2339 agent_data: [0xAA; AGENT_DATA_MAX_SIZE],
2340 };
2341 vmgs.write_file(FileId::ATTEST, agent.as_bytes())
2342 .await
2343 .unwrap();
2344
2345 let get_pair = new_test_get(driver, false, None).await;
2347
2348 let bios_guid = Guid::new_random();
2349 let att_cfg = new_attestation_vm_config();
2350
2351 assert!(!vmgs.encrypted());
2353
2354 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2356 let res = initialize_platform_security(
2357 &get_pair.client,
2358 bios_guid,
2359 &att_cfg,
2360 &mut vmgs,
2361 None, true, ldriver,
2364 GuestStateEncryptionPolicy::None,
2365 true,
2366 )
2367 .await
2368 .unwrap();
2369
2370 assert!(!vmgs.encrypted());
2372 assert!(key_protector_is_empty(&mut vmgs).await);
2373 assert!(hardware_key_protector_is_empty(&mut vmgs).await);
2374 assert_eq!(res.agent_data.unwrap(), agent.agent_data.to_vec());
2376 assert!(res.guest_secret_key.is_none());
2378 }
2379
2380 #[async_test]
2381 async fn init_sec_secure_key_release_with_wrapped_key_request(driver: DefaultDriver) {
2382 let mut vmgs = new_formatted_vmgs().await;
2383
2384 let get_pair = new_test_get(driver, true, None).await;
2386
2387 let bios_guid = Guid::new_random();
2388 let att_cfg = new_attestation_vm_config();
2389 let tee = MockTeeCall::new(0x1234);
2390
2391 assert!(!vmgs.encrypted());
2393
2394 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2396 let res = initialize_platform_security(
2397 &get_pair.client,
2398 bios_guid,
2399 &att_cfg,
2400 &mut vmgs,
2401 Some(&tee),
2402 false,
2403 ldriver.clone(),
2404 GuestStateEncryptionPolicy::Auto,
2405 true,
2406 )
2407 .await
2408 .unwrap();
2409
2410 assert!(vmgs.encrypted());
2412 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2413
2414 let key_reference = serde_json::json!({
2417 "key_info": {
2418 "host": "name"
2419 },
2420 "attestation_info": {
2421 "host": "attestation_name"
2422 }
2423 });
2424 let key_reference = serde_json::to_string(&key_reference).unwrap();
2425 let key_reference = key_reference.as_bytes();
2426 let mut expected_agent_data = [0u8; AGENT_DATA_MAX_SIZE];
2427 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2428 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2429 assert!(res.guest_secret_key.is_none());
2431
2432 initialize_platform_security(
2434 &get_pair.client,
2435 bios_guid,
2436 &att_cfg,
2437 &mut vmgs,
2438 Some(&tee),
2439 false,
2440 ldriver,
2441 GuestStateEncryptionPolicy::Auto,
2442 true,
2443 )
2444 .await
2445 .unwrap();
2446
2447 assert!(vmgs.encrypted());
2449 }
2450
2451 #[async_test]
2452 async fn init_sec_secure_key_release_without_wrapped_key_request(driver: DefaultDriver) {
2453 let mut vmgs = new_formatted_vmgs().await;
2454
2455 let agent = SecurityProfile {
2457 agent_data: [0xAA; AGENT_DATA_MAX_SIZE],
2458 };
2459 vmgs.write_file(FileId::ATTEST, agent.as_bytes())
2460 .await
2461 .unwrap();
2462
2463 let mut plan = IgvmAgentTestPlan::default();
2465 plan.insert(
2466 IgvmAttestRequestType::WRAPPED_KEY_REQUEST,
2467 VecDeque::from([IgvmAgentAction::NoResponse, IgvmAgentAction::NoResponse]),
2468 );
2469
2470 let get_pair = new_test_get(driver, true, Some(plan)).await;
2472
2473 let bios_guid = Guid::new_random();
2474 let att_cfg = new_attestation_vm_config();
2475 let tee = MockTeeCall::new(0x1234);
2476
2477 assert!(!vmgs.encrypted());
2479
2480 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2482 let res = initialize_platform_security(
2483 &get_pair.client,
2484 bios_guid,
2485 &att_cfg,
2486 &mut vmgs,
2487 Some(&tee),
2488 false,
2489 ldriver.clone(),
2490 GuestStateEncryptionPolicy::Auto,
2491 true,
2492 )
2493 .await
2494 .unwrap();
2495
2496 assert!(vmgs.encrypted());
2498 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2499 assert_eq!(res.agent_data.clone().unwrap(), agent.agent_data.to_vec());
2501 assert!(res.guest_secret_key.is_none());
2503
2504 let res = initialize_platform_security(
2506 &get_pair.client,
2507 bios_guid,
2508 &att_cfg,
2509 &mut vmgs,
2510 Some(&tee),
2511 false,
2512 ldriver,
2513 GuestStateEncryptionPolicy::Auto,
2514 true,
2515 )
2516 .await
2517 .unwrap();
2518
2519 assert!(vmgs.encrypted());
2521 assert_eq!(res.agent_data.clone().unwrap(), agent.agent_data.to_vec());
2523 assert!(res.guest_secret_key.is_none());
2525 }
2526
2527 #[async_test]
2528 async fn init_sec_secure_key_release_hw_sealing_backup(driver: DefaultDriver) {
2529 let mut vmgs = new_formatted_vmgs().await;
2530
2531 let mut plan = IgvmAgentTestPlan::default();
2533 plan.insert(
2534 IgvmAttestRequestType::WRAPPED_KEY_REQUEST,
2535 VecDeque::from([
2536 IgvmAgentAction::RespondSuccess,
2537 IgvmAgentAction::RespondFailure,
2539 IgvmAgentAction::RespondFailure,
2540 IgvmAgentAction::RespondFailure,
2541 IgvmAgentAction::RespondFailure,
2542 IgvmAgentAction::RespondFailure,
2543 IgvmAgentAction::RespondFailure,
2544 IgvmAgentAction::RespondFailure,
2545 IgvmAgentAction::RespondFailure,
2546 IgvmAgentAction::RespondFailure,
2547 IgvmAgentAction::RespondFailure,
2548 ]),
2549 );
2550
2551 let get_pair = new_test_get(driver, true, Some(plan)).await;
2552
2553 let bios_guid = Guid::new_random();
2554 let att_cfg = new_attestation_vm_config();
2555
2556 assert!(!vmgs.encrypted());
2558
2559 let tee = MockTeeCall::new(0x1234);
2561 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2562 let res = initialize_platform_security(
2563 &get_pair.client,
2564 bios_guid,
2565 &att_cfg,
2566 &mut vmgs,
2567 Some(&tee),
2568 false,
2569 ldriver.clone(),
2570 GuestStateEncryptionPolicy::Auto,
2571 true,
2572 )
2573 .await
2574 .unwrap();
2575
2576 assert!(vmgs.encrypted());
2578 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2579 let key_reference = serde_json::json!({
2582 "key_info": {
2583 "host": "name"
2584 },
2585 "attestation_info": {
2586 "host": "attestation_name"
2587 }
2588 });
2589 let key_reference = serde_json::to_string(&key_reference).unwrap();
2590 let key_reference = key_reference.as_bytes();
2591 let mut expected_agent_data = [0u8; AGENT_DATA_MAX_SIZE];
2592 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2593 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2594 assert!(res.guest_secret_key.is_none());
2596
2597 initialize_platform_security(
2603 &get_pair.client,
2604 bios_guid,
2605 &att_cfg,
2606 &mut vmgs,
2607 Some(&tee),
2608 false,
2609 ldriver,
2610 GuestStateEncryptionPolicy::Auto,
2611 true,
2612 )
2613 .await
2614 .unwrap();
2615
2616 assert!(vmgs.encrypted());
2618 }
2619
2620 #[async_test]
2621 async fn init_sec_secure_key_release_skip_hw_unsealing(driver: DefaultDriver) {
2622 let mut vmgs = new_formatted_vmgs().await;
2623
2624 let mut plan = IgvmAgentTestPlan::default();
2628 plan.insert(
2629 IgvmAttestRequestType::KEY_RELEASE_REQUEST,
2630 VecDeque::from([
2631 IgvmAgentAction::RespondSuccess,
2632 IgvmAgentAction::RespondFailureSkipHwUnsealing,
2633 ]),
2634 );
2635
2636 let get_pair = new_test_get(driver, true, Some(plan)).await;
2637
2638 let bios_guid = Guid::new_random();
2639 let att_cfg = new_attestation_vm_config();
2640
2641 assert!(!vmgs.encrypted());
2643
2644 let tee = MockTeeCall::new(0x1234);
2646 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2647 let res = initialize_platform_security(
2648 &get_pair.client,
2649 bios_guid,
2650 &att_cfg,
2651 &mut vmgs,
2652 Some(&tee),
2653 false,
2654 ldriver.clone(),
2655 GuestStateEncryptionPolicy::Auto,
2656 true,
2657 )
2658 .await
2659 .unwrap();
2660
2661 assert!(vmgs.encrypted());
2663 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2664 let key_reference = serde_json::json!({
2666 "key_info": {
2667 "host": "name"
2668 },
2669 "attestation_info": {
2670 "host": "attestation_name"
2671 }
2672 });
2673 let key_reference = serde_json::to_string(&key_reference).unwrap();
2674 let key_reference = key_reference.as_bytes();
2675 let mut expected_agent_data = [0u8; AGENT_DATA_MAX_SIZE];
2676 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2677 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2678 assert!(res.guest_secret_key.is_none());
2680
2681 let result = initialize_platform_security(
2689 &get_pair.client,
2690 bios_guid,
2691 &att_cfg,
2692 &mut vmgs,
2693 Some(&tee),
2694 false,
2695 ldriver,
2696 GuestStateEncryptionPolicy::Auto,
2697 true,
2698 )
2699 .await;
2700
2701 assert!(result.is_err());
2702 }
2703
2704 #[async_test]
2705 async fn init_sec_secure_key_release_no_hw_sealing_backup(driver: DefaultDriver) {
2706 let mut vmgs = new_formatted_vmgs().await;
2707
2708 let mut plan = IgvmAgentTestPlan::default();
2710 plan.insert(
2711 IgvmAttestRequestType::WRAPPED_KEY_REQUEST,
2712 VecDeque::from([
2713 IgvmAgentAction::RespondSuccess,
2714 IgvmAgentAction::RespondFailure,
2716 IgvmAgentAction::RespondFailure,
2717 IgvmAgentAction::RespondFailure,
2718 IgvmAgentAction::RespondFailure,
2719 IgvmAgentAction::RespondFailure,
2720 IgvmAgentAction::RespondFailure,
2721 IgvmAgentAction::RespondFailure,
2722 IgvmAgentAction::RespondFailure,
2723 IgvmAgentAction::RespondFailure,
2724 IgvmAgentAction::RespondFailure,
2725 ]),
2726 );
2727
2728 let get_pair = new_test_get(driver, true, Some(plan)).await;
2729
2730 let bios_guid = Guid::new_random();
2731 let att_cfg = new_attestation_vm_config();
2732 let tee = MockTeeCallNoGetDerivedKey {};
2734
2735 assert!(!vmgs.encrypted());
2737
2738 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2740 let res = initialize_platform_security(
2741 &get_pair.client,
2742 bios_guid,
2743 &att_cfg,
2744 &mut vmgs,
2745 Some(&tee),
2746 false,
2747 ldriver.clone(),
2748 GuestStateEncryptionPolicy::Auto,
2749 true,
2750 )
2751 .await
2752 .unwrap();
2753
2754 assert!(vmgs.encrypted());
2756 assert!(hardware_key_protector_is_empty(&mut vmgs).await);
2757 let key_reference = serde_json::json!({
2760 "key_info": {
2761 "host": "name"
2762 },
2763 "attestation_info": {
2764 "host": "attestation_name"
2765 }
2766 });
2767 let key_reference = serde_json::to_string(&key_reference).unwrap();
2768 let key_reference = key_reference.as_bytes();
2769 let mut expected_agent_data = [0u8; AGENT_DATA_MAX_SIZE];
2770 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2771 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2772 assert!(res.guest_secret_key.is_none());
2774
2775 let result = initialize_platform_security(
2777 &get_pair.client,
2778 bios_guid,
2779 &att_cfg,
2780 &mut vmgs,
2781 Some(&tee),
2782 false,
2783 ldriver,
2784 GuestStateEncryptionPolicy::Auto,
2785 true,
2786 )
2787 .await;
2788
2789 assert!(result.is_err());
2790 }
2791}