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