1#![cfg(target_os = "linux")]
10#![forbid(unsafe_code)]
11
12mod crypto;
13mod hardware_key_sealing;
14mod igvm_attest;
15mod key_protector;
16mod secure_key_release;
17mod vmgs;
18
19pub use igvm_attest::Error as IgvmAttestError;
20pub use igvm_attest::IgvmAttestRequestHelper;
21pub use igvm_attest::ak_cert::parse_response as parse_ak_cert_response;
22
23use ::vmgs::EncryptionAlgorithm;
24use ::vmgs::Vmgs;
25use cvm_tracing::CVM_ALLOWED;
26use get_protocol::dps_json::GuestStateEncryptionPolicy;
27use guest_emulation_transport::GuestEmulationTransportClient;
28use guest_emulation_transport::api::GspExtendedStatusFlags;
29use guest_emulation_transport::api::GuestStateProtection;
30use guest_emulation_transport::api::GuestStateProtectionById;
31use guid::Guid;
32use hardware_key_sealing::HardwareDerivedKeys;
33use hardware_key_sealing::HardwareKeyProtectorExt as _;
34use key_protector::GetKeysFromKeyProtectorError;
35use key_protector::KeyProtectorExt as _;
36use mesh::MeshPayload;
37use openhcl_attestation_protocol::igvm_attest::get::runtime_claims::AttestationVmConfig;
38use openhcl_attestation_protocol::vmgs::AES_GCM_KEY_LENGTH;
39use openhcl_attestation_protocol::vmgs::HardwareKeyProtector;
40use openhcl_attestation_protocol::vmgs::KeyProtector;
41use openhcl_attestation_protocol::vmgs::SecurityProfile;
42use openssl::pkey::Private;
43use openssl::rsa::Rsa;
44use pal_async::local::LocalDriver;
45use secure_key_release::VmgsEncryptionKeys;
46use static_assertions::const_assert_eq;
47use std::fmt::Debug;
48use tee_call::TeeCall;
49use thiserror::Error;
50use zerocopy::FromZeros;
51use zerocopy::IntoBytes;
52
53#[derive(Debug, Error)]
55#[error(transparent)]
56pub struct Error(AttestationErrorInner);
57
58impl<T: Into<AttestationErrorInner>> From<T> for Error {
59 fn from(value: T) -> Self {
60 Self(value.into())
61 }
62}
63
64#[derive(Debug, Error)]
65enum AttestationErrorInner {
66 #[error("read security profile from vmgs")]
67 ReadSecurityProfile(#[source] vmgs::ReadFromVmgsError),
68 #[error("failed to request vmgs encryption keys")]
69 RequestVmgsEncryptionKeys(#[source] secure_key_release::RequestVmgsEncryptionKeysError),
70 #[error("failed to get derived keys")]
71 GetDerivedKeys(#[source] GetDerivedKeysError),
72 #[error("failed to read key protector from vmgs")]
73 ReadKeyProtector(#[source] vmgs::ReadFromVmgsError),
74 #[error("failed to read key protector by id from vmgs")]
75 ReadKeyProtectorById(#[source] vmgs::ReadFromVmgsError),
76 #[error("failed to unlock vmgs data store")]
77 UnlockVmgsDataStore(#[source] UnlockVmgsDataStoreError),
78 #[error("failed to read guest secret key from vmgs")]
79 ReadGuestSecretKey(#[source] vmgs::ReadFromVmgsError),
80}
81
82#[derive(Debug, Error)]
83enum GetDerivedKeysError {
84 #[error("failed to get ingress/egress keys from the the key protector")]
85 GetKeysFromKeyProtector(#[source] GetKeysFromKeyProtectorError),
86 #[error("failed to fetch GSP")]
87 FetchGuestStateProtectionById(
88 #[source] guest_emulation_transport::error::GuestStateProtectionByIdError,
89 ),
90 #[error("GSP By Id required, but no GSP By Id found")]
91 GspByIdRequiredButNotFound,
92 #[error("failed to unseal the ingress key using hardware derived keys")]
93 UnsealIngressKeyUsingHardwareDerivedKeys(
94 #[source] hardware_key_sealing::HardwareKeySealingError,
95 ),
96 #[error("failed to get an ingress key from key protector")]
97 GetIngressKeyFromKpFailed,
98 #[error("failed to get an ingress key from guest state protection")]
99 GetIngressKeyFromKGspFailed,
100 #[error("failed to get an ingress key from guest state protection by id")]
101 GetIngressKeyFromKGspByIdFailed,
102 #[error("Encryption cannot be disabled if VMGS was previously encrypted")]
103 DisableVmgsEncryptionFailed,
104 #[error("VMGS encryption is required, but no encryption sources were found")]
105 EncryptionRequiredButNotFound,
106 #[error("failed to seal the egress key using hardware derived keys")]
107 SealEgressKeyUsingHardwareDerivedKeys(#[source] hardware_key_sealing::HardwareKeySealingError),
108 #[error("failed to write to `FileId::HW_KEY_PROTECTOR` in vmgs")]
109 VmgsWriteHardwareKeyProtector(#[source] vmgs::WriteToVmgsError),
110 #[error("failed to get derived key by id")]
111 GetDerivedKeyById(#[source] GetDerivedKeysByIdError),
112 #[error("failed to derive an ingress key")]
113 DeriveIngressKey(#[source] crypto::KbkdfError),
114 #[error("failed to derive an egress key")]
115 DeriveEgressKey(#[source] crypto::KbkdfError),
116}
117
118#[derive(Debug, Error)]
119enum GetDerivedKeysByIdError {
120 #[error("failed to derive an egress key based on current vm bios guid")]
121 DeriveEgressKeyUsingCurrentVmId(#[source] crypto::KbkdfError),
122 #[error("invalid derived egress key size {key_size}, expected {expected_size}")]
123 InvalidDerivedEgressKeySize {
124 key_size: usize,
125 expected_size: usize,
126 },
127 #[error("failed to derive an ingress key based on key protector Id from vmgs")]
128 DeriveIngressKeyUsingKeyProtectorId(#[source] crypto::KbkdfError),
129 #[error("invalid derived egress key size {key_size}, expected {expected_size}")]
130 InvalidDerivedIngressKeySize {
131 key_size: usize,
132 expected_size: usize,
133 },
134}
135
136#[derive(Debug, Error)]
137enum UnlockVmgsDataStoreError {
138 #[error("failed to unlock vmgs with the existing egress key")]
139 VmgsUnlockUsingExistingEgressKey(#[source] ::vmgs::Error),
140 #[error("failed to unlock vmgs with the existing ingress key")]
141 VmgsUnlockUsingExistingIngressKey(#[source] ::vmgs::Error),
142 #[error("failed to write key protector to vmgs")]
143 WriteKeyProtector(#[source] vmgs::WriteToVmgsError),
144 #[error("failed to read key protector by id to vmgs")]
145 WriteKeyProtectorById(#[source] vmgs::WriteToVmgsError),
146 #[error("failed to remove the old vmgs encryption key")]
147 RemoveOldVmgsEncryptionKey(#[source] ::vmgs::Error),
148 #[error("failed to add a new vmgs encryption key after removing the old key")]
149 AddNewVmgsEncryptionKeyAfterRemoval(#[source] ::vmgs::Error),
150 #[error("failed to add a new vmgs encryption key")]
151 AddNewVmgsEncryptionKey(#[source] ::vmgs::Error),
152 #[error("failed to persist all key protectors")]
153 PersistAllKeyProtectors(#[source] PersistAllKeyProtectorsError),
154}
155
156#[derive(Debug, Error)]
157enum PersistAllKeyProtectorsError {
158 #[error("failed to write key protector to vmgs")]
159 WriteKeyProtector(#[source] vmgs::WriteToVmgsError),
160 #[error("failed to read key protector by id to vmgs")]
161 WriteKeyProtectorById(#[source] vmgs::WriteToVmgsError),
162}
163
164const VMGS_KEY_DERIVE_LABEL: &[u8; 7] = b"VMGSKEY";
166
167#[derive(Debug)]
168struct Keys {
169 ingress: [u8; AES_GCM_KEY_LENGTH],
170 decrypt_egress: Option<[u8; AES_GCM_KEY_LENGTH]>,
171 encrypt_egress: [u8; AES_GCM_KEY_LENGTH],
172}
173
174struct KeyProtectorSettings {
176 should_write_kp: bool,
178 use_gsp_by_id: bool,
180 use_hardware_unlock: bool,
182}
183
184struct KeyProtectorById {
186 pub inner: openhcl_attestation_protocol::vmgs::KeyProtectorById,
188 pub found_id: bool,
190}
191
192pub struct HostAttestationSettings {
194 pub refresh_tpm_seeds: bool,
196}
197
198struct DerivedKeyResult {
200 derived_keys: Option<Keys>,
202 key_protector_settings: KeyProtectorSettings,
204 gsp_extended_status_flags: GspExtendedStatusFlags,
206}
207
208pub struct PlatformAttestationData {
210 pub host_attestation_settings: HostAttestationSettings,
212 pub agent_data: Option<Vec<u8>>,
214 pub guest_secret_key: Option<Vec<u8>>,
216}
217
218#[derive(Debug, MeshPayload, Copy, Clone, PartialEq, Eq)]
221pub enum AttestationType {
222 Snp,
224 Tdx,
226 Host,
228}
229
230pub async fn initialize_platform_security(
236 get: &GuestEmulationTransportClient,
237 bios_guid: Guid,
238 attestation_vm_config: &AttestationVmConfig,
239 vmgs: &mut Vmgs,
240 attestation_type: AttestationType,
241 suppress_attestation: bool,
242 driver: LocalDriver,
243 guest_state_encryption_policy: GuestStateEncryptionPolicy,
244 strict_encryption_policy: bool,
245) -> Result<PlatformAttestationData, Error> {
246 tracing::info!(CVM_ALLOWED,
247 attestation_type=?attestation_type,
248 secure_boot=attestation_vm_config.secure_boot,
249 tpm_enabled=attestation_vm_config.tpm_enabled,
250 tpm_persisted=attestation_vm_config.tpm_persisted,
251 "Reading security profile");
252
253 let SecurityProfile { mut agent_data } = vmgs::read_security_profile(vmgs)
257 .await
258 .map_err(AttestationErrorInner::ReadSecurityProfile)?;
259
260 if suppress_attestation {
263 tracing::info!(CVM_ALLOWED, "Suppressing attestation");
264
265 return Ok(PlatformAttestationData {
266 host_attestation_settings: HostAttestationSettings {
267 refresh_tpm_seeds: false,
268 },
269 agent_data: Some(agent_data.to_vec()),
270 guest_secret_key: None,
271 });
272 }
273
274 let tee_call: Option<Box<dyn TeeCall>> = match attestation_type {
275 AttestationType::Snp => Some(Box::new(tee_call::SnpCall)),
276 AttestationType::Tdx => Some(Box::new(tee_call::TdxCall)),
277 AttestationType::Host => None,
278 };
279
280 let VmgsEncryptionKeys {
281 ingress_rsa_kek,
282 wrapped_des_key,
283 tcb_version,
284 } = if let Some(tee_call) = tee_call.as_ref() {
285 tracing::info!(CVM_ALLOWED, "Retrieving key-encryption key");
286
287 secure_key_release::request_vmgs_encryption_keys(
289 get,
290 tee_call.as_ref(),
291 vmgs,
292 attestation_vm_config,
293 &mut agent_data,
294 driver,
295 )
296 .await
297 .map_err(AttestationErrorInner::RequestVmgsEncryptionKeys)?
298 } else {
299 tracing::info!(CVM_ALLOWED, "Key-encryption key retrieval not required");
300
301 VmgsEncryptionKeys::default()
303 };
304
305 let dek_minimal_size = if wrapped_des_key.is_some() {
307 key_protector::AES_WRAPPED_AES_KEY_LENGTH
308 } else {
309 key_protector::RSA_WRAPPED_AES_KEY_LENGTH
310 };
311
312 tracing::info!(
314 CVM_ALLOWED,
315 dek_minimal_size = dek_minimal_size,
316 "Reading key protector from VMGS"
317 );
318 let mut key_protector = vmgs::read_key_protector(vmgs, dek_minimal_size)
319 .await
320 .map_err(AttestationErrorInner::ReadKeyProtector)?;
321
322 tracing::info!(CVM_ALLOWED, "Reading VM ID from VMGS");
324 let mut key_protector_by_id = match vmgs::read_key_protector_by_id(vmgs).await {
325 Ok(key_protector_by_id) => KeyProtectorById {
326 inner: key_protector_by_id,
327 found_id: true,
328 },
329 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => KeyProtectorById {
330 inner: openhcl_attestation_protocol::vmgs::KeyProtectorById::new_zeroed(),
331 found_id: false,
332 },
333 Err(e) => { Err(AttestationErrorInner::ReadKeyProtectorById(e)) }?,
334 };
335
336 let vm_id_changed = if key_protector_by_id.found_id {
338 let changed = key_protector_by_id.inner.id_guid != bios_guid;
339 if changed {
340 tracing::info!("VM Id has changed since last boot");
341 };
342 changed
343 } else {
344 tracing::info!("First booting of the VM");
345 false
348 };
349
350 let vmgs_encrypted: bool = vmgs.is_encrypted();
351
352 tracing::info!(tcb_version=?tcb_version, vmgs_encrypted = vmgs_encrypted, "Deriving keys");
353 let derived_keys_result = get_derived_keys(
354 get,
355 tee_call.as_deref(),
356 vmgs,
357 &mut key_protector,
358 &mut key_protector_by_id,
359 bios_guid,
360 attestation_vm_config,
361 vmgs_encrypted,
362 ingress_rsa_kek.as_ref(),
363 wrapped_des_key.as_deref(),
364 tcb_version,
365 guest_state_encryption_policy,
366 strict_encryption_policy,
367 )
368 .await
369 .map_err(AttestationErrorInner::GetDerivedKeys)?;
370
371 tracing::info!("Unlocking VMGS");
373 if let Err(e) = unlock_vmgs_data_store(
374 vmgs,
375 vmgs_encrypted,
376 &mut key_protector,
377 &mut key_protector_by_id,
378 derived_keys_result.derived_keys,
379 derived_keys_result.key_protector_settings,
380 bios_guid,
381 )
382 .await
383 {
384 get.event_log_fatal(guest_emulation_transport::api::EventLogId::ATTESTATION_FAILED)
385 .await;
386
387 Err(AttestationErrorInner::UnlockVmgsDataStore(e))?
388 }
389
390 let state_refresh_request_from_gsp = derived_keys_result
391 .gsp_extended_status_flags
392 .state_refresh_request();
393
394 let host_attestation_settings = HostAttestationSettings {
395 refresh_tpm_seeds: { state_refresh_request_from_gsp | vm_id_changed },
396 };
397
398 tracing::info!(
399 CVM_ALLOWED,
400 state_refresh_request_from_gsp = state_refresh_request_from_gsp,
401 vm_id_changed = vm_id_changed,
402 "determine if refreshing tpm seeds is needed"
403 );
404
405 let guest_secret_key = match vmgs::read_guest_secret_key(vmgs).await {
407 Ok(data) => Some(data.guest_secret_key.to_vec()),
408 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => None,
409 Err(e) => return Err(AttestationErrorInner::ReadGuestSecretKey(e).into()),
410 };
411
412 Ok(PlatformAttestationData {
413 host_attestation_settings,
414 agent_data: Some(agent_data.to_vec()),
415 guest_secret_key,
416 })
417}
418
419async fn unlock_vmgs_data_store(
426 vmgs: &mut Vmgs,
427 vmgs_encrypted: bool,
428 key_protector: &mut KeyProtector,
429 key_protector_by_id: &mut KeyProtectorById,
430 derived_keys: Option<Keys>,
431 key_protector_settings: KeyProtectorSettings,
432 bios_guid: Guid,
433) -> Result<(), UnlockVmgsDataStoreError> {
434 let mut new_key = false; let Some(Keys {
437 ingress: new_ingress_key,
438 decrypt_egress: old_egress_key,
439 encrypt_egress: new_egress_key,
440 }) = derived_keys
441 else {
442 tracing::info!(
443 CVM_ALLOWED,
444 "Encryption disabled, skipping unlock vmgs data store"
445 );
446 return Ok(());
447 };
448
449 if !openssl::memcmp::eq(&new_ingress_key, &new_egress_key) {
450 tracing::trace!(CVM_ALLOWED, "EgressKey is different than IngressKey");
451 new_key = true;
452 }
453
454 let mut old_index = 2;
456 let mut provision = false;
457 if vmgs_encrypted {
458 tracing::info!(CVM_ALLOWED, "Decrypting vmgs file...");
459 match vmgs.unlock_with_encryption_key(&new_ingress_key).await {
460 Ok(index) => old_index = index,
461 Err(e) => {
462 if let Some(key) = old_egress_key {
463 tracing::trace!(CVM_ALLOWED, "Old EgressKey found");
466 old_index = vmgs
467 .unlock_with_encryption_key(&key)
468 .await
469 .map_err(UnlockVmgsDataStoreError::VmgsUnlockUsingExistingEgressKey)?;
470 } else {
471 Err(UnlockVmgsDataStoreError::VmgsUnlockUsingExistingIngressKey(
472 e,
473 ))?
474 }
475 }
476 }
477 } else {
478 tracing::info!(
480 CVM_ALLOWED,
481 "vmgs data store is not encrypted, provisioning."
482 );
483 provision = true;
484 }
485
486 if key_protector_settings.should_write_kp {
487 vmgs::write_key_protector(key_protector, vmgs)
489 .await
490 .map_err(UnlockVmgsDataStoreError::WriteKeyProtector)?;
491
492 if key_protector_settings.use_gsp_by_id {
493 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
494 .await
495 .map_err(UnlockVmgsDataStoreError::WriteKeyProtectorById)?;
496 }
497 }
498
499 if provision || new_key {
501 let result = vmgs
502 .add_new_encryption_key(&new_egress_key, EncryptionAlgorithm::AES_GCM)
503 .await;
504
505 match result {
506 Ok(_new_index) => (),
507 Err(_) if old_index != 2 => {
508 let key_index = if old_index == 0 { 1 } else { 0 };
511 tracing::trace!(CVM_ALLOWED, key_index = key_index, "Remove old key...");
512 vmgs.remove_encryption_key(key_index)
513 .await
514 .map_err(UnlockVmgsDataStoreError::RemoveOldVmgsEncryptionKey)?;
515
516 tracing::trace!(CVM_ALLOWED, "Add egress_key again...");
517 vmgs.add_new_encryption_key(&new_egress_key, EncryptionAlgorithm::AES_GCM)
518 .await
519 .map_err(UnlockVmgsDataStoreError::AddNewVmgsEncryptionKeyAfterRemoval)?;
520 }
521 Err(e) => Err(UnlockVmgsDataStoreError::AddNewVmgsEncryptionKey(e))?,
522 }
523 }
524
525 if !provision && new_key {
527 vmgs.remove_encryption_key(old_index)
528 .await
529 .map_err(UnlockVmgsDataStoreError::RemoveOldVmgsEncryptionKey)?;
530 }
531
532 persist_all_key_protectors(
534 vmgs,
535 key_protector,
536 key_protector_by_id,
537 bios_guid,
538 key_protector_settings,
539 )
540 .await
541 .map_err(UnlockVmgsDataStoreError::PersistAllKeyProtectors)
542}
543
544async fn get_derived_keys(
561 get: &GuestEmulationTransportClient,
562 tee_call: Option<&dyn TeeCall>,
563 vmgs: &mut Vmgs,
564 key_protector: &mut KeyProtector,
565 key_protector_by_id: &mut KeyProtectorById,
566 bios_guid: Guid,
567 attestation_vm_config: &AttestationVmConfig,
568 is_encrypted: bool,
569 ingress_rsa_kek: Option<&Rsa<Private>>,
570 wrapped_des_key: Option<&[u8]>,
571 tcb_version: Option<u64>,
572 guest_state_encryption_policy: GuestStateEncryptionPolicy,
573 strict_encryption_policy: bool,
574) -> Result<DerivedKeyResult, GetDerivedKeysError> {
575 tracing::info!(
576 CVM_ALLOWED,
577 ?guest_state_encryption_policy,
578 strict_encryption_policy,
579 "encryption policy"
580 );
581
582 if matches!(
584 guest_state_encryption_policy,
585 GuestStateEncryptionPolicy::HardwareSealing
586 ) {
587 todo!("hardware sealing")
588 }
589
590 let mut key_protector_settings = KeyProtectorSettings {
591 should_write_kp: true,
592 use_gsp_by_id: false,
593 use_hardware_unlock: false,
594 };
595
596 let mut derived_keys = Keys {
597 ingress: [0u8; AES_GCM_KEY_LENGTH],
598 decrypt_egress: None,
599 encrypt_egress: [0u8; AES_GCM_KEY_LENGTH],
600 };
601
602 let ingress_idx = (key_protector.active_kp % 2) as usize;
604 let egress_idx = if ingress_idx == 0 { 1 } else { 0 } as usize;
605
606 let found_dek = !key_protector.dek[ingress_idx]
607 .dek_buffer
608 .iter()
609 .all(|&x| x == 0);
610
611 let (ingress_key, mut decrypt_egress_key, encrypt_egress_key, no_kek) =
613 if let Some(ingress_kek) = ingress_rsa_kek {
614 let keys = match key_protector.unwrap_and_rotate_keys(
615 ingress_kek,
616 wrapped_des_key,
617 ingress_idx,
618 egress_idx,
619 ) {
620 Ok(keys) => keys,
621 Err(e)
622 if matches!(
623 e,
624 GetKeysFromKeyProtectorError::DesKeyRsaUnwrap(_)
625 | GetKeysFromKeyProtectorError::IngressDekRsaUnwrap(_)
626 ) =>
627 {
628 get.event_log_fatal(
629 guest_emulation_transport::api::EventLogId::DEK_DECRYPTION_FAILED,
630 )
631 .await;
632
633 return Err(GetDerivedKeysError::GetKeysFromKeyProtector(e));
634 }
635 Err(e) => return Err(GetDerivedKeysError::GetKeysFromKeyProtector(e)),
636 };
637 (
638 keys.ingress,
639 keys.decrypt_egress,
640 keys.encrypt_egress,
641 false,
642 )
643 } else {
644 (
645 [0u8; AES_GCM_KEY_LENGTH],
646 None,
647 [0u8; AES_GCM_KEY_LENGTH],
648 true,
649 )
650 };
651
652 let is_gsp_by_id = key_protector_by_id.found_id && key_protector_by_id.inner.ported != 1;
654 let is_gsp = key_protector.gsp[ingress_idx].gsp_length != 0;
655 tracing::info!(
656 CVM_ALLOWED,
657 is_encrypted,
658 is_gsp_by_id,
659 is_gsp,
660 found_dek,
661 "initial vmgs encryption state"
662 );
663 let mut requires_gsp_by_id = is_gsp_by_id;
664
665 let (gsp_response, no_gsp, requires_gsp) = {
667 let response = get_gsp_data(get, key_protector).await;
668
669 tracing::info!(
670 CVM_ALLOWED,
671 request_data_length_in_vmgs = key_protector.gsp[ingress_idx].gsp_length,
672 no_rpc_server = response.extended_status_flags.no_rpc_server(),
673 requires_rpc_server = response.extended_status_flags.requires_rpc_server(),
674 encrypted_gsp_length = response.encrypted_gsp.length,
675 "GSP response"
676 );
677
678 let no_gsp = response.extended_status_flags.no_rpc_server()
679 || response.encrypted_gsp.length == 0
680 || (matches!(
681 guest_state_encryption_policy,
682 GuestStateEncryptionPolicy::GspById | GuestStateEncryptionPolicy::None
683 ) && (!is_gsp || strict_encryption_policy));
684
685 let requires_gsp = is_gsp
686 || response.extended_status_flags.requires_rpc_server()
687 || matches!(
688 guest_state_encryption_policy,
689 GuestStateEncryptionPolicy::GspKey
690 );
691
692 if is_encrypted && !requires_gsp_by_id && !requires_gsp && !found_dek {
695 requires_gsp_by_id = true;
696 }
697
698 (response, no_gsp, requires_gsp)
699 };
700
701 let (gsp_response_by_id, no_gsp_by_id) = if no_gsp || requires_gsp_by_id {
704 let gsp_response_by_id = get
705 .guest_state_protection_data_by_id()
706 .await
707 .map_err(GetDerivedKeysError::FetchGuestStateProtectionById)?;
708
709 let no_gsp_by_id = gsp_response_by_id.extended_status_flags.no_registry_file()
710 || (matches!(
711 guest_state_encryption_policy,
712 GuestStateEncryptionPolicy::None
713 ) && (!requires_gsp_by_id || strict_encryption_policy));
714
715 if no_gsp_by_id && requires_gsp_by_id {
716 Err(GetDerivedKeysError::GspByIdRequiredButNotFound)?
717 }
718
719 (gsp_response_by_id, no_gsp_by_id)
720 } else {
721 (GuestStateProtectionById::new_zeroed(), true)
722 };
723
724 if (no_kek && found_dek) || (no_gsp && requires_gsp) || (no_gsp_by_id && requires_gsp_by_id) {
726 let (hardware_key_protector, hardware_derived_keys) = if let Some(tee_call) = tee_call {
728 let hardware_key_protector = match vmgs::read_hardware_key_protector(vmgs).await {
729 Ok(hardware_key_protector) => Some(hardware_key_protector),
730 Err(e) => {
731 tracing::warn!(
733 CVM_ALLOWED,
734 error = &e as &dyn std::error::Error,
735 "failed to read HW_KEY_PROTECTOR from Vmgs"
736 );
737 None
738 }
739 };
740
741 let hardware_derived_keys = tee_call.supports_get_derived_key().and_then(|tee_call| {
742 if let Some(hardware_key_protector) = &hardware_key_protector {
743 match HardwareDerivedKeys::derive_key(
744 tee_call,
745 attestation_vm_config,
746 hardware_key_protector.header.tcb_version,
747 ) {
748 Ok(hardware_derived_key) => Some(hardware_derived_key),
749 Err(e) => {
750 tracing::warn!(
752 CVM_ALLOWED,
753 error = &e as &dyn std::error::Error,
754 "failed to derive hardware keys using HW_KEY_PROTECTOR",
755 );
756 None
757 }
758 }
759 } else {
760 None
761 }
762 });
763
764 (hardware_key_protector, hardware_derived_keys)
765 } else {
766 (None, None)
767 };
768
769 if let (Some(hardware_key_protector), Some(hardware_derived_keys)) =
770 (hardware_key_protector, hardware_derived_keys)
771 {
772 derived_keys.ingress = hardware_key_protector
773 .unseal_key(&hardware_derived_keys)
774 .map_err(GetDerivedKeysError::UnsealIngressKeyUsingHardwareDerivedKeys)?;
775 derived_keys.decrypt_egress = None;
776 derived_keys.encrypt_egress = derived_keys.ingress;
777
778 key_protector_settings.should_write_kp = false;
779 key_protector_settings.use_hardware_unlock = true;
780
781 tracing::warn!(
782 CVM_ALLOWED,
783 "Using hardware-derived key to recover VMGS DEK"
784 );
785
786 return Ok(DerivedKeyResult {
787 derived_keys: Some(derived_keys),
788 key_protector_settings,
789 gsp_extended_status_flags: gsp_response.extended_status_flags,
790 });
791 } else {
792 if no_kek && found_dek {
793 Err(GetDerivedKeysError::GetIngressKeyFromKpFailed)?
794 } else if no_gsp && requires_gsp {
795 Err(GetDerivedKeysError::GetIngressKeyFromKGspFailed)?
796 } else {
797 Err(GetDerivedKeysError::GetIngressKeyFromKGspByIdFailed)?
799 }
800 }
801 }
802
803 tracing::info!(
804 CVM_ALLOWED,
805 kek = !no_kek,
806 gsp = !no_gsp,
807 gsp_by_id = !no_gsp_by_id,
808 "Encryption sources"
809 );
810
811 if no_kek && no_gsp && no_gsp_by_id {
813 if is_encrypted {
814 Err(GetDerivedKeysError::DisableVmgsEncryptionFailed)?
815 }
816 match guest_state_encryption_policy {
817 GuestStateEncryptionPolicy::GspById
819 | GuestStateEncryptionPolicy::GspKey
820 | GuestStateEncryptionPolicy::HardwareSealing => {
821 Err(GetDerivedKeysError::EncryptionRequiredButNotFound)?
822 }
823 GuestStateEncryptionPolicy::Auto | GuestStateEncryptionPolicy::None => {
824 tracing::info!(CVM_ALLOWED, "No VMGS encryption used.");
825
826 return Ok(DerivedKeyResult {
827 derived_keys: None,
828 key_protector_settings,
829 gsp_extended_status_flags: gsp_response.extended_status_flags,
830 });
831 }
832 }
833 }
834
835 let hardware_derived_keys = tee_call
837 .and_then(|tee_call| tee_call.supports_get_derived_key())
838 .and_then(|tee_call| {
839 if let Some(tcb_version) = tcb_version {
840 match HardwareDerivedKeys::derive_key(tee_call, attestation_vm_config, tcb_version)
841 {
842 Ok(keys) => Some(keys),
843 Err(e) => {
844 tracing::warn!(
846 CVM_ALLOWED,
847 error = &e as &dyn std::error::Error,
848 "failed to derive hardware keys"
849 );
850 None
851 }
852 }
853 } else {
854 None
855 }
856 });
857
858 if no_gsp && no_gsp_by_id {
860 tracing::info!(CVM_ALLOWED, "No GSP used with SKR");
861
862 derived_keys.ingress = ingress_key;
863 derived_keys.decrypt_egress = decrypt_egress_key;
864 derived_keys.encrypt_egress = encrypt_egress_key;
865
866 if let Some(hardware_derived_keys) = hardware_derived_keys {
867 let hardware_key_protector = HardwareKeyProtector::seal_key(
868 &hardware_derived_keys,
869 &derived_keys.encrypt_egress,
870 )
871 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
872 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
873 .await
874 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
875
876 tracing::info!(CVM_ALLOWED, "hardware key protector updated (no GSP used)");
877 }
878
879 return Ok(DerivedKeyResult {
880 derived_keys: Some(derived_keys),
881 key_protector_settings,
882 gsp_extended_status_flags: gsp_response.extended_status_flags,
883 });
884 }
885
886 if (no_kek && no_gsp) || requires_gsp_by_id {
889 let derived_keys_by_id =
890 get_derived_keys_by_id(key_protector_by_id, bios_guid, gsp_response_by_id)
891 .map_err(GetDerivedKeysError::GetDerivedKeyById)?;
892
893 if no_kek && no_gsp {
894 if matches!(
895 guest_state_encryption_policy,
896 GuestStateEncryptionPolicy::None
897 ) {
898 tracing::warn!(CVM_ALLOWED, "Allowing GspById");
905 } else {
906 tracing::info!(CVM_ALLOWED, "Using GspById");
907 }
908
909 key_protector_settings.should_write_kp = false;
911 key_protector_settings.use_gsp_by_id = true;
912
913 return Ok(DerivedKeyResult {
914 derived_keys: Some(derived_keys_by_id),
915 key_protector_settings,
916 gsp_extended_status_flags: gsp_response.extended_status_flags,
917 });
918 }
919
920 derived_keys.ingress = derived_keys_by_id.ingress;
921
922 tracing::info!(CVM_ALLOWED, "Converting GSP method.");
923 }
924
925 let egress_seed;
926 let mut ingress_seed = None;
927
928 if requires_gsp_by_id || no_gsp {
934 if found_dek {
937 if requires_gsp_by_id {
938 ingress_seed = Some(
939 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize]
940 .to_vec(),
941 );
942 } else {
943 derived_keys.ingress = ingress_key;
944 }
945 }
946
947 if no_gsp {
949 egress_seed =
950 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize].to_vec();
951 key_protector_settings.use_gsp_by_id = true;
952 } else {
953 egress_seed =
954 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
955 }
956 } else {
957 if gsp_response.decrypted_gsp[ingress_idx].length == 0
960 && gsp_response.decrypted_gsp[egress_idx].length == 0
961 {
962 tracing::trace!(CVM_ALLOWED, "Applying GSP.");
963
964 egress_seed =
967 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
968
969 if !no_kek {
972 derived_keys.ingress = ingress_key;
973 }
974 } else {
975 tracing::trace!(CVM_ALLOWED, "Using GSP.");
976
977 ingress_seed = Some(
978 gsp_response.decrypted_gsp[ingress_idx].buffer
979 [..gsp_response.decrypted_gsp[ingress_idx].length as usize]
980 .to_vec(),
981 );
982
983 if gsp_response.decrypted_gsp[egress_idx].length == 0 {
984 egress_seed =
986 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
987 } else {
988 egress_seed = gsp_response.decrypted_gsp[egress_idx].buffer
993 [..gsp_response.decrypted_gsp[egress_idx].length as usize]
994 .to_vec();
995 key_protector_settings.should_write_kp = false;
996 decrypt_egress_key = Some(encrypt_egress_key);
997 }
998 }
999 }
1000
1001 if let Some(seed) = ingress_seed {
1003 derived_keys.ingress = crypto::derive_key(&ingress_key, &seed, VMGS_KEY_DERIVE_LABEL)
1004 .map_err(GetDerivedKeysError::DeriveIngressKey)?;
1005 }
1006
1007 derived_keys.decrypt_egress = decrypt_egress_key
1009 .map(|key| crypto::derive_key(&key, &egress_seed, VMGS_KEY_DERIVE_LABEL))
1010 .transpose()
1011 .map_err(GetDerivedKeysError::DeriveEgressKey)?;
1012
1013 derived_keys.encrypt_egress =
1014 crypto::derive_key(&encrypt_egress_key, &egress_seed, VMGS_KEY_DERIVE_LABEL)
1015 .map_err(GetDerivedKeysError::DeriveEgressKey)?;
1016
1017 if key_protector_settings.should_write_kp {
1018 key_protector.gsp[egress_idx]
1020 .gsp_buffer
1021 .copy_from_slice(&gsp_response.encrypted_gsp.buffer);
1022 key_protector.gsp[egress_idx].gsp_length = gsp_response.encrypted_gsp.length;
1023
1024 if let Some(hardware_derived_keys) = hardware_derived_keys {
1025 let hardware_key_protector = HardwareKeyProtector::seal_key(
1026 &hardware_derived_keys,
1027 &derived_keys.encrypt_egress,
1028 )
1029 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
1030
1031 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
1032 .await
1033 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
1034
1035 tracing::info!(CVM_ALLOWED, "hardware key protector updated");
1036 }
1037 }
1038
1039 if matches!(
1040 guest_state_encryption_policy,
1041 GuestStateEncryptionPolicy::None | GuestStateEncryptionPolicy::GspById
1042 ) {
1043 tracing::warn!(CVM_ALLOWED, "Allowing Gsp");
1050 } else {
1051 tracing::info!(CVM_ALLOWED, "Using Gsp");
1052 }
1053
1054 Ok(DerivedKeyResult {
1055 derived_keys: Some(derived_keys),
1056 key_protector_settings,
1057 gsp_extended_status_flags: gsp_response.extended_status_flags,
1058 })
1059}
1060
1061fn get_derived_keys_by_id(
1063 key_protector_by_id: &mut KeyProtectorById,
1064 bios_guid: Guid,
1065 gsp_response_by_id: GuestStateProtectionById,
1066) -> Result<Keys, GetDerivedKeysByIdError> {
1067 let new_egress_key = crypto::derive_key(
1074 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
1075 bios_guid.as_bytes(),
1076 VMGS_KEY_DERIVE_LABEL,
1077 )
1078 .map_err(GetDerivedKeysByIdError::DeriveEgressKeyUsingCurrentVmId)?;
1079
1080 if new_egress_key.len() != AES_GCM_KEY_LENGTH {
1081 Err(GetDerivedKeysByIdError::InvalidDerivedEgressKeySize {
1082 key_size: new_egress_key.len(),
1083 expected_size: AES_GCM_KEY_LENGTH,
1084 })?
1085 }
1086
1087 let new_ingress_key = if key_protector_by_id.inner.id_guid != Guid::default() {
1090 crypto::derive_key(
1092 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
1093 key_protector_by_id.inner.id_guid.as_bytes(),
1094 VMGS_KEY_DERIVE_LABEL,
1095 )
1096 .map_err(GetDerivedKeysByIdError::DeriveIngressKeyUsingKeyProtectorId)?
1097 } else {
1098 new_egress_key
1100 };
1101
1102 if new_ingress_key.len() != AES_GCM_KEY_LENGTH {
1103 Err(GetDerivedKeysByIdError::InvalidDerivedIngressKeySize {
1104 key_size: new_ingress_key.len(),
1105 expected_size: AES_GCM_KEY_LENGTH,
1106 })?
1107 }
1108
1109 Ok(Keys {
1110 ingress: new_ingress_key,
1111 decrypt_egress: None,
1112 encrypt_egress: new_egress_key,
1113 })
1114}
1115
1116async fn get_gsp_data(
1118 get: &GuestEmulationTransportClient,
1119 key_protector: &mut KeyProtector,
1120) -> GuestStateProtection {
1121 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1122 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1123
1124 const_assert_eq!(guest_emulation_transport::api::NUMBER_GSP, NUMBER_KP as u32);
1125 const_assert_eq!(
1126 guest_emulation_transport::api::GSP_CIPHERTEXT_MAX,
1127 GSP_BUFFER_SIZE as u32
1128 );
1129
1130 let mut encrypted_gsp =
1131 [guest_emulation_transport::api::GspCiphertextContent::new_zeroed(); NUMBER_KP];
1132
1133 for (i, gsp) in encrypted_gsp.iter_mut().enumerate().take(NUMBER_KP) {
1134 if key_protector.gsp[i].gsp_length == 0 {
1135 continue;
1136 }
1137
1138 gsp.buffer[..key_protector.gsp[i].gsp_length as usize].copy_from_slice(
1139 &key_protector.gsp[i].gsp_buffer[..key_protector.gsp[i].gsp_length as usize],
1140 );
1141
1142 gsp.length = key_protector.gsp[i].gsp_length;
1143 }
1144
1145 get.guest_state_protection_data(encrypted_gsp, GspExtendedStatusFlags::new())
1146 .await
1147}
1148
1149async fn persist_all_key_protectors(
1151 vmgs: &mut Vmgs,
1152 key_protector: &mut KeyProtector,
1153 key_protector_by_id: &mut KeyProtectorById,
1154 bios_guid: Guid,
1155 key_protector_settings: KeyProtectorSettings,
1156) -> Result<(), PersistAllKeyProtectorsError> {
1157 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1158
1159 if key_protector_settings.use_gsp_by_id && !key_protector_settings.should_write_kp {
1160 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
1161 .await
1162 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1163 } else {
1164 if !key_protector_settings.use_hardware_unlock {
1166 key_protector.dek[key_protector.active_kp as usize % NUMBER_KP]
1168 .dek_buffer
1169 .fill(0);
1170 key_protector.gsp[key_protector.active_kp as usize % NUMBER_KP].gsp_length = 0;
1171 key_protector.active_kp += 1;
1172
1173 vmgs::write_key_protector(key_protector, vmgs)
1174 .await
1175 .map_err(PersistAllKeyProtectorsError::WriteKeyProtector)?;
1176 }
1177
1178 if !key_protector_settings.use_gsp_by_id
1180 && key_protector_by_id.found_id
1181 && key_protector_by_id.inner.ported == 0
1182 {
1183 key_protector_by_id.inner.ported = 1;
1184 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, true, bios_guid)
1185 .await
1186 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1187 }
1188 }
1189
1190 Ok(())
1191}
1192
1193#[cfg(test)]
1194mod tests {
1195 use super::*;
1196 use disk_backend::Disk;
1197 use disklayer_ram::ram_disk;
1198 use get_protocol::GSP_CLEARTEXT_MAX;
1199 use get_protocol::GspExtendedStatusFlags;
1200 use key_protector::AES_WRAPPED_AES_KEY_LENGTH;
1201 use openhcl_attestation_protocol::vmgs::DEK_BUFFER_SIZE;
1202 use openhcl_attestation_protocol::vmgs::DekKp;
1203 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1204 use openhcl_attestation_protocol::vmgs::GspKp;
1205 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1206 use pal_async::async_test;
1207 use vmgs_format::EncryptionAlgorithm;
1208 use vmgs_format::FileId;
1209
1210 const ONE_MEGA_BYTE: u64 = 1024 * 1024;
1211
1212 fn new_test_file() -> Disk {
1213 ram_disk(4 * ONE_MEGA_BYTE, false).unwrap()
1214 }
1215
1216 async fn new_formatted_vmgs() -> Vmgs {
1217 let disk = new_test_file();
1218
1219 let mut vmgs = Vmgs::format_new(disk, None).await.unwrap();
1220
1221 assert!(
1222 key_protector_is_empty(&mut vmgs).await,
1223 "Newly formatted VMGS should have an empty key protector"
1224 );
1225 assert!(
1226 key_protector_by_id_is_empty(&mut vmgs).await,
1227 "Newly formatted VMGS should have an empty key protector by id"
1228 );
1229
1230 vmgs
1231 }
1232
1233 async fn key_protector_is_empty(vmgs: &mut Vmgs) -> bool {
1234 let key_protector = vmgs::read_key_protector(vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1235 .await
1236 .unwrap();
1237
1238 key_protector.as_bytes().iter().all(|&b| b == 0)
1239 }
1240
1241 async fn key_protector_by_id_is_empty(vmgs: &mut Vmgs) -> bool {
1242 vmgs::read_key_protector_by_id(vmgs)
1243 .await
1244 .is_err_and(|err| {
1245 matches!(
1246 err,
1247 vmgs::ReadFromVmgsError::EntryNotFound(FileId::VM_UNIQUE_ID)
1248 )
1249 })
1250 }
1251
1252 fn new_key_protector() -> KeyProtector {
1253 assert_eq!(NUMBER_KP, 2);
1255
1256 let ingress_dek = DekKp {
1257 dek_buffer: [1; DEK_BUFFER_SIZE],
1258 };
1259 let egress_dek = DekKp {
1260 dek_buffer: [2; DEK_BUFFER_SIZE],
1261 };
1262 let ingress_gsp = GspKp {
1263 gsp_length: GSP_BUFFER_SIZE as u32,
1264 gsp_buffer: [3; GSP_BUFFER_SIZE],
1265 };
1266 let egress_gsp = GspKp {
1267 gsp_length: GSP_BUFFER_SIZE as u32,
1268 gsp_buffer: [4; GSP_BUFFER_SIZE],
1269 };
1270 KeyProtector {
1271 dek: [ingress_dek, egress_dek],
1272 gsp: [ingress_gsp, egress_gsp],
1273 active_kp: 0,
1274 }
1275 }
1276
1277 fn new_key_protector_by_id(
1278 id_guid: Option<Guid>,
1279 ported: Option<u8>,
1280 found_id: bool,
1281 ) -> KeyProtectorById {
1282 let key_protector_by_id = openhcl_attestation_protocol::vmgs::KeyProtectorById {
1283 id_guid: id_guid.unwrap_or_else(Guid::new_random),
1284 ported: ported.unwrap_or(0),
1285 pad: [0; 3],
1286 };
1287
1288 KeyProtectorById {
1289 inner: key_protector_by_id,
1290 found_id,
1291 }
1292 }
1293
1294 #[async_test]
1295 async fn do_nothing_without_derived_keys() {
1296 let mut vmgs = new_formatted_vmgs().await;
1297
1298 let mut key_protector = new_key_protector();
1299 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1300
1301 let key_protector_settings = KeyProtectorSettings {
1302 should_write_kp: false,
1303 use_gsp_by_id: false,
1304 use_hardware_unlock: false,
1305 };
1306
1307 let bios_guid = Guid::new_random();
1308
1309 unlock_vmgs_data_store(
1310 &mut vmgs,
1311 false,
1312 &mut key_protector,
1313 &mut key_protector_by_id,
1314 None,
1315 key_protector_settings,
1316 bios_guid,
1317 )
1318 .await
1319 .unwrap();
1320
1321 assert!(key_protector_is_empty(&mut vmgs).await);
1322 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1323
1324 let key_protector_settings = KeyProtectorSettings {
1326 should_write_kp: false,
1327 use_gsp_by_id: false,
1328 use_hardware_unlock: false,
1329 };
1330
1331 unlock_vmgs_data_store(
1333 &mut vmgs,
1334 true,
1335 &mut key_protector,
1336 &mut key_protector_by_id,
1337 None,
1338 key_protector_settings,
1339 bios_guid,
1340 )
1341 .await
1342 .unwrap();
1343
1344 assert!(key_protector_is_empty(&mut vmgs).await);
1345 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1346 }
1347
1348 #[async_test]
1349 async fn provision_vmgs_and_rotate_keys() {
1350 let mut vmgs = new_formatted_vmgs().await;
1351
1352 let mut key_protector = new_key_protector();
1353 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1354
1355 let ingress = [1; AES_GCM_KEY_LENGTH];
1356 let egress = [2; AES_GCM_KEY_LENGTH];
1357 let derived_keys = Keys {
1358 ingress,
1359 decrypt_egress: None,
1360 encrypt_egress: egress,
1361 };
1362
1363 let key_protector_settings = KeyProtectorSettings {
1364 should_write_kp: true,
1365 use_gsp_by_id: true,
1366 use_hardware_unlock: false,
1367 };
1368
1369 let bios_guid = Guid::new_random();
1370
1371 unlock_vmgs_data_store(
1374 &mut vmgs,
1375 false,
1376 &mut key_protector,
1377 &mut key_protector_by_id,
1378 Some(derived_keys),
1379 key_protector_settings,
1380 bios_guid,
1381 )
1382 .await
1383 .unwrap();
1384
1385 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1387
1388 let egress_index = vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1390 assert_eq!(egress_index, 0);
1392
1393 assert!(!key_protector_is_empty(&mut vmgs).await);
1395 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
1396
1397 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1398 .await
1399 .unwrap();
1400 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1401
1402 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1403 assert_eq!(
1404 found_key_protector_by_id.as_bytes(),
1405 key_protector_by_id.inner.as_bytes()
1406 );
1407
1408 let new_egress = [3; AES_GCM_KEY_LENGTH];
1410
1411 let mut new_key_protector = new_key_protector();
1412 let mut new_key_protector_by_id = new_key_protector_by_id(None, None, false);
1413
1414 let key_protector_settings = KeyProtectorSettings {
1415 should_write_kp: true,
1416 use_gsp_by_id: true,
1417 use_hardware_unlock: false,
1418 };
1419
1420 let derived_keys = Keys {
1422 ingress: egress,
1423 decrypt_egress: None,
1424 encrypt_egress: new_egress,
1425 };
1426
1427 unlock_vmgs_data_store(
1428 &mut vmgs,
1429 true,
1430 &mut new_key_protector,
1431 &mut new_key_protector_by_id,
1432 Some(derived_keys),
1433 key_protector_settings,
1434 bios_guid,
1435 )
1436 .await
1437 .unwrap();
1438
1439 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1441 vmgs.unlock_with_encryption_key(&egress).await.unwrap_err();
1443
1444 let new_egress_index = vmgs.unlock_with_encryption_key(&new_egress).await.unwrap();
1446 assert_eq!(new_egress_index, 1);
1448
1449 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1450 .await
1451 .unwrap();
1452 assert_eq!(found_key_protector.as_bytes(), new_key_protector.as_bytes());
1453
1454 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1455 assert_eq!(
1456 found_key_protector_by_id.as_bytes(),
1457 new_key_protector_by_id.inner.as_bytes()
1458 );
1459 }
1460
1461 #[async_test]
1462 async fn unlock_previously_encrypted_vmgs_with_ingress_key() {
1463 let mut vmgs = new_formatted_vmgs().await;
1464
1465 let mut key_protector = new_key_protector();
1466 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1467
1468 let ingress = [1; AES_GCM_KEY_LENGTH];
1469 let egress = [2; AES_GCM_KEY_LENGTH];
1470
1471 let derived_keys = Keys {
1472 ingress,
1473 decrypt_egress: None,
1474 encrypt_egress: egress,
1475 };
1476
1477 vmgs.add_new_encryption_key(&ingress, EncryptionAlgorithm::AES_GCM)
1478 .await
1479 .unwrap();
1480
1481 let ingress_index = vmgs.unlock_with_encryption_key(&ingress).await.unwrap();
1483 assert_eq!(ingress_index, 0);
1484
1485 let key_protector_settings = KeyProtectorSettings {
1486 should_write_kp: true,
1487 use_gsp_by_id: true,
1488 use_hardware_unlock: false,
1489 };
1490
1491 let bios_guid = Guid::new_random();
1492
1493 unlock_vmgs_data_store(
1494 &mut vmgs,
1495 true,
1496 &mut key_protector,
1497 &mut key_protector_by_id,
1498 Some(derived_keys),
1499 key_protector_settings,
1500 bios_guid,
1501 )
1502 .await
1503 .unwrap();
1504
1505 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1507 let egress_index = vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1508 assert_eq!(egress_index, 1);
1510
1511 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1513 .await
1514 .unwrap();
1515 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1516
1517 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1518 assert_eq!(
1519 found_key_protector_by_id.as_bytes(),
1520 key_protector_by_id.inner.as_bytes()
1521 );
1522 }
1523
1524 #[async_test]
1525 async fn failed_to_persist_ingress_key_so_use_egress_key_to_unlock_vmgs() {
1526 let mut vmgs = new_formatted_vmgs().await;
1527
1528 let mut key_protector = new_key_protector();
1529 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1530
1531 let ingress = [1; AES_GCM_KEY_LENGTH];
1532 let decrypt_egress = [2; AES_GCM_KEY_LENGTH];
1533 let encrypt_egress = [3; AES_GCM_KEY_LENGTH];
1534
1535 let derived_keys = Keys {
1536 ingress,
1537 decrypt_egress: Some(decrypt_egress),
1538 encrypt_egress,
1539 };
1540
1541 let egress_key_index = vmgs
1543 .add_new_encryption_key(&decrypt_egress, EncryptionAlgorithm::AES_GCM)
1544 .await
1545 .unwrap();
1546 assert_eq!(egress_key_index, 0);
1547
1548 let found_egress_key_index = vmgs
1549 .unlock_with_encryption_key(&decrypt_egress)
1550 .await
1551 .unwrap();
1552 assert_eq!(found_egress_key_index, egress_key_index);
1553
1554 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1556
1557 let key_protector_settings = KeyProtectorSettings {
1558 should_write_kp: true,
1559 use_gsp_by_id: true,
1560 use_hardware_unlock: false,
1561 };
1562
1563 let bios_guid = Guid::new_random();
1564
1565 unlock_vmgs_data_store(
1566 &mut vmgs,
1567 true,
1568 &mut key_protector,
1569 &mut key_protector_by_id,
1570 Some(derived_keys),
1571 key_protector_settings,
1572 bios_guid,
1573 )
1574 .await
1575 .unwrap();
1576
1577 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1579
1580 vmgs.unlock_with_encryption_key(&decrypt_egress)
1582 .await
1583 .unwrap_err();
1584
1585 let found_egress_key_index = vmgs
1587 .unlock_with_encryption_key(&encrypt_egress)
1588 .await
1589 .unwrap();
1590 assert_eq!(found_egress_key_index, 1);
1591
1592 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1594 .await
1595 .unwrap();
1596 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1597
1598 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1599 assert_eq!(
1600 found_key_protector_by_id.as_bytes(),
1601 key_protector_by_id.inner.as_bytes()
1602 );
1603 }
1604
1605 #[async_test]
1606 async fn fail_to_unlock_vmgs_with_existing_ingress_key() {
1607 let mut vmgs = new_formatted_vmgs().await;
1608
1609 let mut key_protector = new_key_protector();
1610 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1611
1612 let ingress = [1; AES_GCM_KEY_LENGTH];
1613
1614 let derived_keys = Keys {
1616 ingress,
1617 decrypt_egress: None,
1618 encrypt_egress: ingress,
1619 };
1620
1621 let additional_key = [2; AES_GCM_KEY_LENGTH];
1623 let yet_another_key = [3; AES_GCM_KEY_LENGTH];
1624
1625 let additional_key_index = vmgs
1626 .add_new_encryption_key(&additional_key, EncryptionAlgorithm::AES_GCM)
1627 .await
1628 .unwrap();
1629 assert_eq!(additional_key_index, 0);
1630
1631 let yet_another_key_index = vmgs
1632 .add_new_encryption_key(&yet_another_key, EncryptionAlgorithm::AES_GCM)
1633 .await
1634 .unwrap();
1635 assert_eq!(yet_another_key_index, 1);
1636
1637 let key_protector_settings = KeyProtectorSettings {
1638 should_write_kp: true,
1639 use_gsp_by_id: true,
1640 use_hardware_unlock: false,
1641 };
1642
1643 let bios_guid = Guid::new_random();
1644
1645 let unlock_result = unlock_vmgs_data_store(
1646 &mut vmgs,
1647 true,
1648 &mut key_protector,
1649 &mut key_protector_by_id,
1650 Some(derived_keys),
1651 key_protector_settings,
1652 bios_guid,
1653 )
1654 .await;
1655 assert!(unlock_result.is_err());
1656 assert_eq!(
1657 unlock_result.unwrap_err().to_string(),
1658 "failed to unlock vmgs with the existing ingress key".to_string()
1659 );
1660 }
1661
1662 #[async_test]
1663 async fn fail_to_unlock_vmgs_with_new_ingress_key() {
1664 let mut vmgs = new_formatted_vmgs().await;
1665
1666 let mut key_protector = new_key_protector();
1667 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1668
1669 let derived_keys = Keys {
1670 ingress: [1; AES_GCM_KEY_LENGTH],
1671 decrypt_egress: None,
1672 encrypt_egress: [2; AES_GCM_KEY_LENGTH],
1673 };
1674
1675 let additional_key = [3; AES_GCM_KEY_LENGTH];
1677 let yet_another_key = [4; AES_GCM_KEY_LENGTH];
1678
1679 let additional_key_index = vmgs
1680 .add_new_encryption_key(&additional_key, EncryptionAlgorithm::AES_GCM)
1681 .await
1682 .unwrap();
1683 assert_eq!(additional_key_index, 0);
1684
1685 let yet_another_key_index = vmgs
1686 .add_new_encryption_key(&yet_another_key, EncryptionAlgorithm::AES_GCM)
1687 .await
1688 .unwrap();
1689 assert_eq!(yet_another_key_index, 1);
1690
1691 let key_protector_settings = KeyProtectorSettings {
1692 should_write_kp: true,
1693 use_gsp_by_id: true,
1694 use_hardware_unlock: false,
1695 };
1696
1697 let bios_guid = Guid::new_random();
1698
1699 let unlock_result = unlock_vmgs_data_store(
1700 &mut vmgs,
1701 true,
1702 &mut key_protector,
1703 &mut key_protector_by_id,
1704 Some(derived_keys),
1705 key_protector_settings,
1706 bios_guid,
1707 )
1708 .await;
1709 assert!(unlock_result.is_err());
1710 assert_eq!(
1711 unlock_result.unwrap_err().to_string(),
1712 "failed to unlock vmgs with the existing ingress key".to_string()
1713 );
1714 }
1715
1716 #[async_test]
1717 async fn get_derived_keys_using_id() {
1718 let bios_guid = Guid::new_random();
1719
1720 let gsp_response_by_id = GuestStateProtectionById {
1721 seed: guest_emulation_transport::api::GspCleartextContent {
1722 length: GSP_CLEARTEXT_MAX,
1723 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
1724 },
1725 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
1726 };
1727
1728 let mut key_protector_by_id =
1731 new_key_protector_by_id(Some(Guid::new_zeroed()), None, false);
1732 let derived_keys =
1733 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
1734 .unwrap();
1735
1736 assert_eq!(derived_keys.ingress, derived_keys.encrypt_egress);
1737
1738 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1741 let derived_keys =
1742 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
1743 .unwrap();
1744
1745 assert_ne!(derived_keys.ingress, derived_keys.encrypt_egress);
1746
1747 let gsp_response_by_id_with_0_length_seed = GuestStateProtectionById {
1749 seed: guest_emulation_transport::api::GspCleartextContent {
1750 length: 0,
1751 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
1752 },
1753 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
1754 };
1755
1756 let derived_keys_response = get_derived_keys_by_id(
1757 &mut key_protector_by_id,
1758 bios_guid,
1759 gsp_response_by_id_with_0_length_seed,
1760 );
1761 assert!(derived_keys_response.is_err());
1762 assert_eq!(
1763 derived_keys_response.unwrap_err().to_string(),
1764 "failed to derive an egress key based on current vm bios guid".to_string()
1765 );
1766 }
1767
1768 #[async_test]
1769 async fn pass_through_persist_all_key_protectors() {
1770 let mut vmgs = new_formatted_vmgs().await;
1771 let mut key_protector = new_key_protector();
1772 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1773 let bios_guid = Guid::new_random();
1774
1775 let kp_copy = key_protector.as_bytes().to_vec();
1777 let active_kp_copy = key_protector.active_kp;
1778
1779 let key_protector_settings = KeyProtectorSettings {
1781 should_write_kp: true,
1782 use_gsp_by_id: true,
1783 use_hardware_unlock: true,
1784 };
1785 persist_all_key_protectors(
1786 &mut vmgs,
1787 &mut key_protector,
1788 &mut key_protector_by_id,
1789 bios_guid,
1790 key_protector_settings,
1791 )
1792 .await
1793 .unwrap();
1794
1795 assert!(key_protector_is_empty(&mut vmgs).await);
1796 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1797
1798 assert_eq!(active_kp_copy, key_protector.active_kp);
1800 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
1801 }
1802
1803 #[async_test]
1804 async fn persist_all_key_protectors_write_key_protector_by_id() {
1805 let mut vmgs = new_formatted_vmgs().await;
1806 let mut key_protector = new_key_protector();
1807 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1808 let bios_guid = Guid::new_random();
1809
1810 let kp_copy = key_protector.as_bytes().to_vec();
1812 let active_kp_copy = key_protector.active_kp;
1813
1814 let key_protector_settings = KeyProtectorSettings {
1816 should_write_kp: false,
1817 use_gsp_by_id: true,
1818 use_hardware_unlock: false,
1819 };
1820 persist_all_key_protectors(
1821 &mut vmgs,
1822 &mut key_protector,
1823 &mut key_protector_by_id,
1824 bios_guid,
1825 key_protector_settings,
1826 )
1827 .await
1828 .unwrap();
1829
1830 assert!(key_protector_is_empty(&mut vmgs).await);
1832 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
1833
1834 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1835 assert_eq!(
1836 found_key_protector_by_id.as_bytes(),
1837 key_protector_by_id.inner.as_bytes()
1838 );
1839
1840 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
1842 assert_eq!(active_kp_copy, key_protector.active_kp);
1843 }
1844
1845 #[async_test]
1846 async fn persist_all_key_protectors_remove_ingress_kp() {
1847 let mut vmgs = new_formatted_vmgs().await;
1848 let mut key_protector = new_key_protector();
1849 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1850 let bios_guid = Guid::new_random();
1851
1852 let active_kp_copy = key_protector.active_kp;
1854
1855 let key_protector_settings = KeyProtectorSettings {
1858 should_write_kp: true,
1859 use_gsp_by_id: false,
1860 use_hardware_unlock: false,
1861 };
1862 persist_all_key_protectors(
1863 &mut vmgs,
1864 &mut key_protector,
1865 &mut key_protector_by_id,
1866 bios_guid,
1867 key_protector_settings,
1868 )
1869 .await
1870 .unwrap();
1871
1872 assert!(!key_protector_is_empty(&mut vmgs).await);
1873 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1874
1875 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1877 .await
1878 .unwrap();
1879
1880 assert!(
1881 found_key_protector.dek[active_kp_copy as usize]
1882 .dek_buffer
1883 .iter()
1884 .all(|&b| b == 0),
1885 );
1886 assert_eq!(
1887 found_key_protector.gsp[active_kp_copy as usize].gsp_length,
1888 0
1889 );
1890 assert_eq!(found_key_protector.active_kp, active_kp_copy + 1);
1891 }
1892
1893 #[async_test]
1894 async fn persist_all_key_protectors_mark_key_protector_by_id_as_not_in_use() {
1895 let mut vmgs = new_formatted_vmgs().await;
1896 let mut key_protector = new_key_protector();
1897 let mut key_protector_by_id = new_key_protector_by_id(None, None, true);
1898 let bios_guid = Guid::new_random();
1899
1900 let key_protector_settings = KeyProtectorSettings {
1903 should_write_kp: true,
1904 use_gsp_by_id: false,
1905 use_hardware_unlock: true,
1906 };
1907
1908 persist_all_key_protectors(
1909 &mut vmgs,
1910 &mut key_protector,
1911 &mut key_protector_by_id,
1912 bios_guid,
1913 key_protector_settings,
1914 )
1915 .await
1916 .unwrap();
1917
1918 assert!(key_protector_is_empty(&mut vmgs).await);
1919 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
1920
1921 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1923 assert_eq!(found_key_protector_by_id.ported, 1);
1924 assert_eq!(
1925 found_key_protector_by_id.id_guid,
1926 key_protector_by_id.inner.id_guid
1927 );
1928 }
1929}