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 update the vmgs encryption key")]
147 UpdateVmgsEncryptionKey(#[source] ::vmgs::Error),
148 #[error("failed to persist all key protectors")]
149 PersistAllKeyProtectors(#[source] PersistAllKeyProtectorsError),
150}
151
152#[derive(Debug, Error)]
153enum PersistAllKeyProtectorsError {
154 #[error("failed to write key protector to vmgs")]
155 WriteKeyProtector(#[source] vmgs::WriteToVmgsError),
156 #[error("failed to read key protector by id to vmgs")]
157 WriteKeyProtectorById(#[source] vmgs::WriteToVmgsError),
158}
159
160const VMGS_KEY_DERIVE_LABEL: &[u8; 7] = b"VMGSKEY";
162
163#[derive(Debug)]
164struct Keys {
165 ingress: [u8; AES_GCM_KEY_LENGTH],
166 decrypt_egress: Option<[u8; AES_GCM_KEY_LENGTH]>,
167 encrypt_egress: [u8; AES_GCM_KEY_LENGTH],
168}
169
170struct KeyProtectorSettings {
172 should_write_kp: bool,
174 use_gsp_by_id: bool,
176 use_hardware_unlock: bool,
178}
179
180struct KeyProtectorById {
182 pub inner: openhcl_attestation_protocol::vmgs::KeyProtectorById,
184 pub found_id: bool,
186}
187
188pub struct HostAttestationSettings {
190 pub refresh_tpm_seeds: bool,
192}
193
194struct DerivedKeyResult {
196 derived_keys: Option<Keys>,
198 key_protector_settings: KeyProtectorSettings,
200 gsp_extended_status_flags: GspExtendedStatusFlags,
202}
203
204pub struct PlatformAttestationData {
206 pub host_attestation_settings: HostAttestationSettings,
208 pub agent_data: Option<Vec<u8>>,
210 pub guest_secret_key: Option<Vec<u8>>,
212}
213
214#[derive(Debug, MeshPayload, Copy, Clone, PartialEq, Eq)]
217pub enum AttestationType {
218 Snp,
220 Tdx,
222 Vbs,
224 Host,
226}
227
228pub async fn initialize_platform_security(
234 get: &GuestEmulationTransportClient,
235 bios_guid: Guid,
236 attestation_vm_config: &AttestationVmConfig,
237 vmgs: &mut Vmgs,
238 attestation_type: AttestationType,
239 suppress_attestation: bool,
240 driver: LocalDriver,
241 guest_state_encryption_policy: GuestStateEncryptionPolicy,
242 strict_encryption_policy: bool,
243) -> Result<PlatformAttestationData, Error> {
244 tracing::info!(CVM_ALLOWED,
245 attestation_type=?attestation_type,
246 secure_boot=attestation_vm_config.secure_boot,
247 tpm_enabled=attestation_vm_config.tpm_enabled,
248 tpm_persisted=attestation_vm_config.tpm_persisted,
249 "Reading security profile");
250
251 let SecurityProfile { mut agent_data } = vmgs::read_security_profile(vmgs)
255 .await
256 .map_err(AttestationErrorInner::ReadSecurityProfile)?;
257
258 if suppress_attestation {
261 tracing::info!(CVM_ALLOWED, "Suppressing attestation");
262
263 return Ok(PlatformAttestationData {
264 host_attestation_settings: HostAttestationSettings {
265 refresh_tpm_seeds: false,
266 },
267 agent_data: Some(agent_data.to_vec()),
268 guest_secret_key: None,
269 });
270 }
271
272 let tee_call: Option<Box<dyn TeeCall>> = match attestation_type {
273 AttestationType::Snp => Some(Box::new(tee_call::SnpCall)),
274 AttestationType::Tdx => Some(Box::new(tee_call::TdxCall)),
275 AttestationType::Vbs => Some(Box::new(tee_call::VbsCall)),
276 AttestationType::Host => None,
277 };
278
279 let VmgsEncryptionKeys {
280 ingress_rsa_kek,
281 wrapped_des_key,
282 tcb_version,
283 } = if let Some(tee_call) = tee_call.as_ref() {
284 tracing::info!(CVM_ALLOWED, "Retrieving key-encryption key");
285
286 secure_key_release::request_vmgs_encryption_keys(
288 get,
289 tee_call.as_ref(),
290 vmgs,
291 attestation_vm_config,
292 &mut agent_data,
293 driver,
294 )
295 .await
296 .map_err(AttestationErrorInner::RequestVmgsEncryptionKeys)?
297 } else {
298 tracing::info!(CVM_ALLOWED, "Key-encryption key retrieval not required");
299
300 VmgsEncryptionKeys::default()
302 };
303
304 let dek_minimal_size = if wrapped_des_key.is_some() {
306 key_protector::AES_WRAPPED_AES_KEY_LENGTH
307 } else {
308 key_protector::RSA_WRAPPED_AES_KEY_LENGTH
309 };
310
311 tracing::info!(
313 CVM_ALLOWED,
314 dek_minimal_size = dek_minimal_size,
315 "Reading key protector from VMGS"
316 );
317 let mut key_protector = vmgs::read_key_protector(vmgs, dek_minimal_size)
318 .await
319 .map_err(AttestationErrorInner::ReadKeyProtector)?;
320
321 tracing::info!(CVM_ALLOWED, "Reading VM ID from VMGS");
323 let mut key_protector_by_id = match vmgs::read_key_protector_by_id(vmgs).await {
324 Ok(key_protector_by_id) => KeyProtectorById {
325 inner: key_protector_by_id,
326 found_id: true,
327 },
328 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => KeyProtectorById {
329 inner: openhcl_attestation_protocol::vmgs::KeyProtectorById::new_zeroed(),
330 found_id: false,
331 },
332 Err(e) => { Err(AttestationErrorInner::ReadKeyProtectorById(e)) }?,
333 };
334
335 let vm_id_changed = if key_protector_by_id.found_id {
337 let changed = key_protector_by_id.inner.id_guid != bios_guid;
338 if changed {
339 tracing::info!("VM Id has changed since last boot");
340 };
341 changed
342 } else {
343 tracing::info!("First booting of the VM");
344 false
347 };
348
349 let vmgs_encrypted: bool = vmgs.is_encrypted();
350
351 tracing::info!(tcb_version=?tcb_version, vmgs_encrypted = vmgs_encrypted, "Deriving keys");
352 let derived_keys_result = get_derived_keys(
353 get,
354 tee_call.as_deref(),
355 vmgs,
356 &mut key_protector,
357 &mut key_protector_by_id,
358 bios_guid,
359 attestation_vm_config,
360 vmgs_encrypted,
361 ingress_rsa_kek.as_ref(),
362 wrapped_des_key.as_deref(),
363 tcb_version,
364 guest_state_encryption_policy,
365 strict_encryption_policy,
366 )
367 .await
368 .map_err(AttestationErrorInner::GetDerivedKeys)?;
369
370 tracing::info!("Unlocking VMGS");
372 if let Err(e) = unlock_vmgs_data_store(
373 vmgs,
374 vmgs_encrypted,
375 &mut key_protector,
376 &mut key_protector_by_id,
377 derived_keys_result.derived_keys,
378 derived_keys_result.key_protector_settings,
379 bios_guid,
380 )
381 .await
382 {
383 get.event_log_fatal(guest_emulation_transport::api::EventLogId::ATTESTATION_FAILED)
384 .await;
385
386 Err(AttestationErrorInner::UnlockVmgsDataStore(e))?
387 }
388
389 let state_refresh_request_from_gsp = derived_keys_result
390 .gsp_extended_status_flags
391 .state_refresh_request();
392
393 let host_attestation_settings = HostAttestationSettings {
394 refresh_tpm_seeds: { state_refresh_request_from_gsp | vm_id_changed },
395 };
396
397 tracing::info!(
398 CVM_ALLOWED,
399 state_refresh_request_from_gsp = state_refresh_request_from_gsp,
400 vm_id_changed = vm_id_changed,
401 "determine if refreshing tpm seeds is needed"
402 );
403
404 let guest_secret_key = match vmgs::read_guest_secret_key(vmgs).await {
406 Ok(data) => Some(data.guest_secret_key.to_vec()),
407 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => None,
408 Err(e) => return Err(AttestationErrorInner::ReadGuestSecretKey(e).into()),
409 };
410
411 Ok(PlatformAttestationData {
412 host_attestation_settings,
413 agent_data: Some(agent_data.to_vec()),
414 guest_secret_key,
415 })
416}
417
418async fn unlock_vmgs_data_store(
425 vmgs: &mut Vmgs,
426 vmgs_encrypted: bool,
427 key_protector: &mut KeyProtector,
428 key_protector_by_id: &mut KeyProtectorById,
429 derived_keys: Option<Keys>,
430 key_protector_settings: KeyProtectorSettings,
431 bios_guid: Guid,
432) -> Result<(), UnlockVmgsDataStoreError> {
433 let mut new_key = false; let Some(Keys {
436 ingress: new_ingress_key,
437 decrypt_egress: old_egress_key,
438 encrypt_egress: new_egress_key,
439 }) = derived_keys
440 else {
441 tracing::info!(
442 CVM_ALLOWED,
443 "Encryption disabled, skipping unlock vmgs data store"
444 );
445 return Ok(());
446 };
447
448 if !openssl::memcmp::eq(&new_ingress_key, &new_egress_key) {
449 tracing::trace!(CVM_ALLOWED, "EgressKey is different than IngressKey");
450 new_key = true;
451 }
452
453 let mut provision = false;
455 if vmgs_encrypted {
456 tracing::info!(CVM_ALLOWED, "Decrypting vmgs file...");
457 if let Err(e) = vmgs.unlock_with_encryption_key(&new_ingress_key).await {
458 if let Some(key) = old_egress_key {
459 tracing::trace!(CVM_ALLOWED, "Old EgressKey found");
462 vmgs.unlock_with_encryption_key(&key)
463 .await
464 .map_err(UnlockVmgsDataStoreError::VmgsUnlockUsingExistingEgressKey)?;
465 } else {
466 Err(UnlockVmgsDataStoreError::VmgsUnlockUsingExistingIngressKey(
467 e,
468 ))?
469 }
470 }
471 } else {
472 tracing::info!(
474 CVM_ALLOWED,
475 "vmgs data store is not encrypted, provisioning."
476 );
477 provision = true;
478 }
479
480 if key_protector_settings.should_write_kp {
481 vmgs::write_key_protector(key_protector, vmgs)
483 .await
484 .map_err(UnlockVmgsDataStoreError::WriteKeyProtector)?;
485
486 if key_protector_settings.use_gsp_by_id {
487 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
488 .await
489 .map_err(UnlockVmgsDataStoreError::WriteKeyProtectorById)?;
490 }
491 }
492
493 if provision || new_key {
494 vmgs.update_encryption_key(&new_egress_key, EncryptionAlgorithm::AES_GCM)
498 .await
499 .map_err(UnlockVmgsDataStoreError::UpdateVmgsEncryptionKey)?;
500 }
501
502 persist_all_key_protectors(
504 vmgs,
505 key_protector,
506 key_protector_by_id,
507 bios_guid,
508 key_protector_settings,
509 )
510 .await
511 .map_err(UnlockVmgsDataStoreError::PersistAllKeyProtectors)
512}
513
514async fn get_derived_keys(
531 get: &GuestEmulationTransportClient,
532 tee_call: Option<&dyn TeeCall>,
533 vmgs: &mut Vmgs,
534 key_protector: &mut KeyProtector,
535 key_protector_by_id: &mut KeyProtectorById,
536 bios_guid: Guid,
537 attestation_vm_config: &AttestationVmConfig,
538 is_encrypted: bool,
539 ingress_rsa_kek: Option<&Rsa<Private>>,
540 wrapped_des_key: Option<&[u8]>,
541 tcb_version: Option<u64>,
542 guest_state_encryption_policy: GuestStateEncryptionPolicy,
543 strict_encryption_policy: bool,
544) -> Result<DerivedKeyResult, GetDerivedKeysError> {
545 tracing::info!(
546 CVM_ALLOWED,
547 ?guest_state_encryption_policy,
548 strict_encryption_policy,
549 "encryption policy"
550 );
551
552 if matches!(
554 guest_state_encryption_policy,
555 GuestStateEncryptionPolicy::HardwareSealing
556 ) {
557 todo!("hardware sealing")
558 }
559
560 let mut key_protector_settings = KeyProtectorSettings {
561 should_write_kp: true,
562 use_gsp_by_id: false,
563 use_hardware_unlock: false,
564 };
565
566 let mut derived_keys = Keys {
567 ingress: [0u8; AES_GCM_KEY_LENGTH],
568 decrypt_egress: None,
569 encrypt_egress: [0u8; AES_GCM_KEY_LENGTH],
570 };
571
572 let ingress_idx = (key_protector.active_kp % 2) as usize;
574 let egress_idx = if ingress_idx == 0 { 1 } else { 0 } as usize;
575
576 let found_dek = !key_protector.dek[ingress_idx]
577 .dek_buffer
578 .iter()
579 .all(|&x| x == 0);
580
581 let (ingress_key, mut decrypt_egress_key, encrypt_egress_key, no_kek) =
583 if let Some(ingress_kek) = ingress_rsa_kek {
584 let keys = match key_protector.unwrap_and_rotate_keys(
585 ingress_kek,
586 wrapped_des_key,
587 ingress_idx,
588 egress_idx,
589 ) {
590 Ok(keys) => keys,
591 Err(e)
592 if matches!(
593 e,
594 GetKeysFromKeyProtectorError::DesKeyRsaUnwrap(_)
595 | GetKeysFromKeyProtectorError::IngressDekRsaUnwrap(_)
596 ) =>
597 {
598 get.event_log_fatal(
599 guest_emulation_transport::api::EventLogId::DEK_DECRYPTION_FAILED,
600 )
601 .await;
602
603 return Err(GetDerivedKeysError::GetKeysFromKeyProtector(e));
604 }
605 Err(e) => return Err(GetDerivedKeysError::GetKeysFromKeyProtector(e)),
606 };
607 (
608 keys.ingress,
609 keys.decrypt_egress,
610 keys.encrypt_egress,
611 false,
612 )
613 } else {
614 (
615 [0u8; AES_GCM_KEY_LENGTH],
616 None,
617 [0u8; AES_GCM_KEY_LENGTH],
618 true,
619 )
620 };
621
622 let is_gsp_by_id = key_protector_by_id.found_id && key_protector_by_id.inner.ported != 1;
624 let is_gsp = key_protector.gsp[ingress_idx].gsp_length != 0;
625 tracing::info!(
626 CVM_ALLOWED,
627 is_encrypted,
628 is_gsp_by_id,
629 is_gsp,
630 found_dek,
631 "initial vmgs encryption state"
632 );
633 let mut requires_gsp_by_id = is_gsp_by_id;
634
635 let (gsp_response, no_gsp, requires_gsp) = {
637 let response = get_gsp_data(get, key_protector).await;
638
639 tracing::info!(
640 CVM_ALLOWED,
641 request_data_length_in_vmgs = key_protector.gsp[ingress_idx].gsp_length,
642 no_rpc_server = response.extended_status_flags.no_rpc_server(),
643 requires_rpc_server = response.extended_status_flags.requires_rpc_server(),
644 encrypted_gsp_length = response.encrypted_gsp.length,
645 "GSP response"
646 );
647
648 let no_gsp = response.extended_status_flags.no_rpc_server()
649 || response.encrypted_gsp.length == 0
650 || (matches!(
651 guest_state_encryption_policy,
652 GuestStateEncryptionPolicy::GspById | GuestStateEncryptionPolicy::None
653 ) && (!is_gsp || strict_encryption_policy));
654
655 let requires_gsp = is_gsp
656 || response.extended_status_flags.requires_rpc_server()
657 || matches!(
658 guest_state_encryption_policy,
659 GuestStateEncryptionPolicy::GspKey
660 );
661
662 if is_encrypted && !requires_gsp_by_id && !requires_gsp && !found_dek {
665 requires_gsp_by_id = true;
666 }
667
668 (response, no_gsp, requires_gsp)
669 };
670
671 let (gsp_response_by_id, no_gsp_by_id) = if no_gsp || requires_gsp_by_id {
674 let gsp_response_by_id = get
675 .guest_state_protection_data_by_id()
676 .await
677 .map_err(GetDerivedKeysError::FetchGuestStateProtectionById)?;
678
679 let no_gsp_by_id = gsp_response_by_id.extended_status_flags.no_registry_file()
680 || (matches!(
681 guest_state_encryption_policy,
682 GuestStateEncryptionPolicy::None
683 ) && (!requires_gsp_by_id || strict_encryption_policy));
684
685 if no_gsp_by_id && requires_gsp_by_id {
686 Err(GetDerivedKeysError::GspByIdRequiredButNotFound)?
687 }
688
689 (gsp_response_by_id, no_gsp_by_id)
690 } else {
691 (GuestStateProtectionById::new_zeroed(), true)
692 };
693
694 if (no_kek && found_dek) || (no_gsp && requires_gsp) || (no_gsp_by_id && requires_gsp_by_id) {
696 let (hardware_key_protector, hardware_derived_keys) = if let Some(tee_call) = tee_call {
698 let hardware_key_protector = match vmgs::read_hardware_key_protector(vmgs).await {
699 Ok(hardware_key_protector) => Some(hardware_key_protector),
700 Err(e) => {
701 tracing::warn!(
703 CVM_ALLOWED,
704 error = &e as &dyn std::error::Error,
705 "failed to read HW_KEY_PROTECTOR from Vmgs"
706 );
707 None
708 }
709 };
710
711 let hardware_derived_keys = tee_call.supports_get_derived_key().and_then(|tee_call| {
712 if let Some(hardware_key_protector) = &hardware_key_protector {
713 match HardwareDerivedKeys::derive_key(
714 tee_call,
715 attestation_vm_config,
716 hardware_key_protector.header.tcb_version,
717 ) {
718 Ok(hardware_derived_key) => Some(hardware_derived_key),
719 Err(e) => {
720 tracing::warn!(
722 CVM_ALLOWED,
723 error = &e as &dyn std::error::Error,
724 "failed to derive hardware keys using HW_KEY_PROTECTOR",
725 );
726 None
727 }
728 }
729 } else {
730 None
731 }
732 });
733
734 (hardware_key_protector, hardware_derived_keys)
735 } else {
736 (None, None)
737 };
738
739 if let (Some(hardware_key_protector), Some(hardware_derived_keys)) =
740 (hardware_key_protector, hardware_derived_keys)
741 {
742 derived_keys.ingress = hardware_key_protector
743 .unseal_key(&hardware_derived_keys)
744 .map_err(GetDerivedKeysError::UnsealIngressKeyUsingHardwareDerivedKeys)?;
745 derived_keys.decrypt_egress = None;
746 derived_keys.encrypt_egress = derived_keys.ingress;
747
748 key_protector_settings.should_write_kp = false;
749 key_protector_settings.use_hardware_unlock = true;
750
751 tracing::warn!(
752 CVM_ALLOWED,
753 "Using hardware-derived key to recover VMGS DEK"
754 );
755
756 return Ok(DerivedKeyResult {
757 derived_keys: Some(derived_keys),
758 key_protector_settings,
759 gsp_extended_status_flags: gsp_response.extended_status_flags,
760 });
761 } else {
762 if no_kek && found_dek {
763 Err(GetDerivedKeysError::GetIngressKeyFromKpFailed)?
764 } else if no_gsp && requires_gsp {
765 Err(GetDerivedKeysError::GetIngressKeyFromKGspFailed)?
766 } else {
767 Err(GetDerivedKeysError::GetIngressKeyFromKGspByIdFailed)?
769 }
770 }
771 }
772
773 tracing::info!(
774 CVM_ALLOWED,
775 kek = !no_kek,
776 gsp = !no_gsp,
777 gsp_by_id = !no_gsp_by_id,
778 "Encryption sources"
779 );
780
781 if no_kek && no_gsp && no_gsp_by_id {
783 if is_encrypted {
784 Err(GetDerivedKeysError::DisableVmgsEncryptionFailed)?
785 }
786 match guest_state_encryption_policy {
787 GuestStateEncryptionPolicy::GspById
789 | GuestStateEncryptionPolicy::GspKey
790 | GuestStateEncryptionPolicy::HardwareSealing => {
791 Err(GetDerivedKeysError::EncryptionRequiredButNotFound)?
792 }
793 GuestStateEncryptionPolicy::Auto | GuestStateEncryptionPolicy::None => {
794 tracing::info!(CVM_ALLOWED, "No VMGS encryption used.");
795
796 return Ok(DerivedKeyResult {
797 derived_keys: None,
798 key_protector_settings,
799 gsp_extended_status_flags: gsp_response.extended_status_flags,
800 });
801 }
802 }
803 }
804
805 let hardware_derived_keys = tee_call
807 .and_then(|tee_call| tee_call.supports_get_derived_key())
808 .and_then(|tee_call| {
809 if let Some(tcb_version) = tcb_version {
810 match HardwareDerivedKeys::derive_key(tee_call, attestation_vm_config, tcb_version)
811 {
812 Ok(keys) => Some(keys),
813 Err(e) => {
814 tracing::warn!(
816 CVM_ALLOWED,
817 error = &e as &dyn std::error::Error,
818 "failed to derive hardware keys"
819 );
820 None
821 }
822 }
823 } else {
824 None
825 }
826 });
827
828 if no_gsp && no_gsp_by_id {
830 tracing::info!(CVM_ALLOWED, "No GSP used with SKR");
831
832 derived_keys.ingress = ingress_key;
833 derived_keys.decrypt_egress = decrypt_egress_key;
834 derived_keys.encrypt_egress = encrypt_egress_key;
835
836 if let Some(hardware_derived_keys) = hardware_derived_keys {
837 let hardware_key_protector = HardwareKeyProtector::seal_key(
838 &hardware_derived_keys,
839 &derived_keys.encrypt_egress,
840 )
841 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
842 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
843 .await
844 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
845
846 tracing::info!(CVM_ALLOWED, "hardware key protector updated (no GSP used)");
847 }
848
849 return Ok(DerivedKeyResult {
850 derived_keys: Some(derived_keys),
851 key_protector_settings,
852 gsp_extended_status_flags: gsp_response.extended_status_flags,
853 });
854 }
855
856 if (no_kek && no_gsp) || requires_gsp_by_id {
859 let derived_keys_by_id =
860 get_derived_keys_by_id(key_protector_by_id, bios_guid, gsp_response_by_id)
861 .map_err(GetDerivedKeysError::GetDerivedKeyById)?;
862
863 if no_kek && no_gsp {
864 if matches!(
865 guest_state_encryption_policy,
866 GuestStateEncryptionPolicy::None
867 ) {
868 tracing::warn!(CVM_ALLOWED, "Allowing GspById");
875 } else {
876 tracing::info!(CVM_ALLOWED, "Using GspById");
877 }
878
879 key_protector_settings.should_write_kp = false;
881 key_protector_settings.use_gsp_by_id = true;
882
883 return Ok(DerivedKeyResult {
884 derived_keys: Some(derived_keys_by_id),
885 key_protector_settings,
886 gsp_extended_status_flags: gsp_response.extended_status_flags,
887 });
888 }
889
890 derived_keys.ingress = derived_keys_by_id.ingress;
891
892 tracing::info!(CVM_ALLOWED, "Converting GSP method.");
893 }
894
895 let egress_seed;
896 let mut ingress_seed = None;
897
898 if requires_gsp_by_id || no_gsp {
904 if found_dek {
907 if requires_gsp_by_id {
908 ingress_seed = Some(
909 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize]
910 .to_vec(),
911 );
912 } else {
913 derived_keys.ingress = ingress_key;
914 }
915 }
916
917 if no_gsp {
919 egress_seed =
920 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize].to_vec();
921 key_protector_settings.use_gsp_by_id = true;
922 } else {
923 egress_seed =
924 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
925 }
926 } else {
927 if gsp_response.decrypted_gsp[ingress_idx].length == 0
930 && gsp_response.decrypted_gsp[egress_idx].length == 0
931 {
932 tracing::trace!(CVM_ALLOWED, "Applying GSP.");
933
934 egress_seed =
937 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
938
939 if !no_kek {
942 derived_keys.ingress = ingress_key;
943 }
944 } else {
945 tracing::trace!(CVM_ALLOWED, "Using GSP.");
946
947 ingress_seed = Some(
948 gsp_response.decrypted_gsp[ingress_idx].buffer
949 [..gsp_response.decrypted_gsp[ingress_idx].length as usize]
950 .to_vec(),
951 );
952
953 if gsp_response.decrypted_gsp[egress_idx].length == 0 {
954 egress_seed =
956 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
957 } else {
958 egress_seed = gsp_response.decrypted_gsp[egress_idx].buffer
963 [..gsp_response.decrypted_gsp[egress_idx].length as usize]
964 .to_vec();
965 key_protector_settings.should_write_kp = false;
966 decrypt_egress_key = Some(encrypt_egress_key);
967 }
968 }
969 }
970
971 if let Some(seed) = ingress_seed {
973 derived_keys.ingress = crypto::derive_key(&ingress_key, &seed, VMGS_KEY_DERIVE_LABEL)
974 .map_err(GetDerivedKeysError::DeriveIngressKey)?;
975 }
976
977 derived_keys.decrypt_egress = decrypt_egress_key
979 .map(|key| crypto::derive_key(&key, &egress_seed, VMGS_KEY_DERIVE_LABEL))
980 .transpose()
981 .map_err(GetDerivedKeysError::DeriveEgressKey)?;
982
983 derived_keys.encrypt_egress =
984 crypto::derive_key(&encrypt_egress_key, &egress_seed, VMGS_KEY_DERIVE_LABEL)
985 .map_err(GetDerivedKeysError::DeriveEgressKey)?;
986
987 if key_protector_settings.should_write_kp {
988 key_protector.gsp[egress_idx]
990 .gsp_buffer
991 .copy_from_slice(&gsp_response.encrypted_gsp.buffer);
992 key_protector.gsp[egress_idx].gsp_length = gsp_response.encrypted_gsp.length;
993
994 if let Some(hardware_derived_keys) = hardware_derived_keys {
995 let hardware_key_protector = HardwareKeyProtector::seal_key(
996 &hardware_derived_keys,
997 &derived_keys.encrypt_egress,
998 )
999 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
1000
1001 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
1002 .await
1003 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
1004
1005 tracing::info!(CVM_ALLOWED, "hardware key protector updated");
1006 }
1007 }
1008
1009 if matches!(
1010 guest_state_encryption_policy,
1011 GuestStateEncryptionPolicy::None | GuestStateEncryptionPolicy::GspById
1012 ) {
1013 tracing::warn!(CVM_ALLOWED, "Allowing Gsp");
1020 } else {
1021 tracing::info!(CVM_ALLOWED, "Using Gsp");
1022 }
1023
1024 Ok(DerivedKeyResult {
1025 derived_keys: Some(derived_keys),
1026 key_protector_settings,
1027 gsp_extended_status_flags: gsp_response.extended_status_flags,
1028 })
1029}
1030
1031fn get_derived_keys_by_id(
1033 key_protector_by_id: &mut KeyProtectorById,
1034 bios_guid: Guid,
1035 gsp_response_by_id: GuestStateProtectionById,
1036) -> Result<Keys, GetDerivedKeysByIdError> {
1037 let new_egress_key = crypto::derive_key(
1044 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
1045 bios_guid.as_bytes(),
1046 VMGS_KEY_DERIVE_LABEL,
1047 )
1048 .map_err(GetDerivedKeysByIdError::DeriveEgressKeyUsingCurrentVmId)?;
1049
1050 if new_egress_key.len() != AES_GCM_KEY_LENGTH {
1051 Err(GetDerivedKeysByIdError::InvalidDerivedEgressKeySize {
1052 key_size: new_egress_key.len(),
1053 expected_size: AES_GCM_KEY_LENGTH,
1054 })?
1055 }
1056
1057 let new_ingress_key = if key_protector_by_id.inner.id_guid != Guid::default() {
1060 crypto::derive_key(
1062 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
1063 key_protector_by_id.inner.id_guid.as_bytes(),
1064 VMGS_KEY_DERIVE_LABEL,
1065 )
1066 .map_err(GetDerivedKeysByIdError::DeriveIngressKeyUsingKeyProtectorId)?
1067 } else {
1068 new_egress_key
1070 };
1071
1072 if new_ingress_key.len() != AES_GCM_KEY_LENGTH {
1073 Err(GetDerivedKeysByIdError::InvalidDerivedIngressKeySize {
1074 key_size: new_ingress_key.len(),
1075 expected_size: AES_GCM_KEY_LENGTH,
1076 })?
1077 }
1078
1079 Ok(Keys {
1080 ingress: new_ingress_key,
1081 decrypt_egress: None,
1082 encrypt_egress: new_egress_key,
1083 })
1084}
1085
1086async fn get_gsp_data(
1088 get: &GuestEmulationTransportClient,
1089 key_protector: &mut KeyProtector,
1090) -> GuestStateProtection {
1091 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1092 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1093
1094 const_assert_eq!(guest_emulation_transport::api::NUMBER_GSP, NUMBER_KP as u32);
1095 const_assert_eq!(
1096 guest_emulation_transport::api::GSP_CIPHERTEXT_MAX,
1097 GSP_BUFFER_SIZE as u32
1098 );
1099
1100 let mut encrypted_gsp =
1101 [guest_emulation_transport::api::GspCiphertextContent::new_zeroed(); NUMBER_KP];
1102
1103 for (i, gsp) in encrypted_gsp.iter_mut().enumerate().take(NUMBER_KP) {
1104 if key_protector.gsp[i].gsp_length == 0 {
1105 continue;
1106 }
1107
1108 gsp.buffer[..key_protector.gsp[i].gsp_length as usize].copy_from_slice(
1109 &key_protector.gsp[i].gsp_buffer[..key_protector.gsp[i].gsp_length as usize],
1110 );
1111
1112 gsp.length = key_protector.gsp[i].gsp_length;
1113 }
1114
1115 get.guest_state_protection_data(encrypted_gsp, GspExtendedStatusFlags::new())
1116 .await
1117}
1118
1119async fn persist_all_key_protectors(
1121 vmgs: &mut Vmgs,
1122 key_protector: &mut KeyProtector,
1123 key_protector_by_id: &mut KeyProtectorById,
1124 bios_guid: Guid,
1125 key_protector_settings: KeyProtectorSettings,
1126) -> Result<(), PersistAllKeyProtectorsError> {
1127 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1128
1129 if key_protector_settings.use_gsp_by_id && !key_protector_settings.should_write_kp {
1130 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
1131 .await
1132 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1133 } else {
1134 if !key_protector_settings.use_hardware_unlock {
1136 key_protector.dek[key_protector.active_kp as usize % NUMBER_KP]
1138 .dek_buffer
1139 .fill(0);
1140 key_protector.gsp[key_protector.active_kp as usize % NUMBER_KP].gsp_length = 0;
1141 key_protector.active_kp += 1;
1142
1143 vmgs::write_key_protector(key_protector, vmgs)
1144 .await
1145 .map_err(PersistAllKeyProtectorsError::WriteKeyProtector)?;
1146 }
1147
1148 if !key_protector_settings.use_gsp_by_id
1150 && key_protector_by_id.found_id
1151 && key_protector_by_id.inner.ported == 0
1152 {
1153 key_protector_by_id.inner.ported = 1;
1154 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, true, bios_guid)
1155 .await
1156 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1157 }
1158 }
1159
1160 Ok(())
1161}
1162
1163#[cfg(test)]
1164mod tests {
1165 use super::*;
1166 use disk_backend::Disk;
1167 use disklayer_ram::ram_disk;
1168 use get_protocol::GSP_CLEARTEXT_MAX;
1169 use get_protocol::GspExtendedStatusFlags;
1170 use key_protector::AES_WRAPPED_AES_KEY_LENGTH;
1171 use openhcl_attestation_protocol::vmgs::DEK_BUFFER_SIZE;
1172 use openhcl_attestation_protocol::vmgs::DekKp;
1173 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1174 use openhcl_attestation_protocol::vmgs::GspKp;
1175 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1176 use pal_async::async_test;
1177 use vmgs_format::EncryptionAlgorithm;
1178 use vmgs_format::FileId;
1179
1180 const ONE_MEGA_BYTE: u64 = 1024 * 1024;
1181
1182 fn new_test_file() -> Disk {
1183 ram_disk(4 * ONE_MEGA_BYTE, false).unwrap()
1184 }
1185
1186 async fn new_formatted_vmgs() -> Vmgs {
1187 let disk = new_test_file();
1188
1189 let mut vmgs = Vmgs::format_new(disk, None).await.unwrap();
1190
1191 assert!(
1192 key_protector_is_empty(&mut vmgs).await,
1193 "Newly formatted VMGS should have an empty key protector"
1194 );
1195 assert!(
1196 key_protector_by_id_is_empty(&mut vmgs).await,
1197 "Newly formatted VMGS should have an empty key protector by id"
1198 );
1199
1200 vmgs
1201 }
1202
1203 async fn key_protector_is_empty(vmgs: &mut Vmgs) -> bool {
1204 let key_protector = vmgs::read_key_protector(vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1205 .await
1206 .unwrap();
1207
1208 key_protector.as_bytes().iter().all(|&b| b == 0)
1209 }
1210
1211 async fn key_protector_by_id_is_empty(vmgs: &mut Vmgs) -> bool {
1212 vmgs::read_key_protector_by_id(vmgs)
1213 .await
1214 .is_err_and(|err| {
1215 matches!(
1216 err,
1217 vmgs::ReadFromVmgsError::EntryNotFound(FileId::VM_UNIQUE_ID)
1218 )
1219 })
1220 }
1221
1222 fn new_key_protector() -> KeyProtector {
1223 assert_eq!(NUMBER_KP, 2);
1225
1226 let ingress_dek = DekKp {
1227 dek_buffer: [1; DEK_BUFFER_SIZE],
1228 };
1229 let egress_dek = DekKp {
1230 dek_buffer: [2; DEK_BUFFER_SIZE],
1231 };
1232 let ingress_gsp = GspKp {
1233 gsp_length: GSP_BUFFER_SIZE as u32,
1234 gsp_buffer: [3; GSP_BUFFER_SIZE],
1235 };
1236 let egress_gsp = GspKp {
1237 gsp_length: GSP_BUFFER_SIZE as u32,
1238 gsp_buffer: [4; GSP_BUFFER_SIZE],
1239 };
1240 KeyProtector {
1241 dek: [ingress_dek, egress_dek],
1242 gsp: [ingress_gsp, egress_gsp],
1243 active_kp: 0,
1244 }
1245 }
1246
1247 fn new_key_protector_by_id(
1248 id_guid: Option<Guid>,
1249 ported: Option<u8>,
1250 found_id: bool,
1251 ) -> KeyProtectorById {
1252 let key_protector_by_id = openhcl_attestation_protocol::vmgs::KeyProtectorById {
1253 id_guid: id_guid.unwrap_or_else(Guid::new_random),
1254 ported: ported.unwrap_or(0),
1255 pad: [0; 3],
1256 };
1257
1258 KeyProtectorById {
1259 inner: key_protector_by_id,
1260 found_id,
1261 }
1262 }
1263
1264 #[async_test]
1265 async fn do_nothing_without_derived_keys() {
1266 let mut vmgs = new_formatted_vmgs().await;
1267
1268 let mut key_protector = new_key_protector();
1269 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1270
1271 let key_protector_settings = KeyProtectorSettings {
1272 should_write_kp: false,
1273 use_gsp_by_id: false,
1274 use_hardware_unlock: false,
1275 };
1276
1277 let bios_guid = Guid::new_random();
1278
1279 unlock_vmgs_data_store(
1280 &mut vmgs,
1281 false,
1282 &mut key_protector,
1283 &mut key_protector_by_id,
1284 None,
1285 key_protector_settings,
1286 bios_guid,
1287 )
1288 .await
1289 .unwrap();
1290
1291 assert!(key_protector_is_empty(&mut vmgs).await);
1292 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1293
1294 let key_protector_settings = KeyProtectorSettings {
1296 should_write_kp: false,
1297 use_gsp_by_id: false,
1298 use_hardware_unlock: false,
1299 };
1300
1301 unlock_vmgs_data_store(
1303 &mut vmgs,
1304 true,
1305 &mut key_protector,
1306 &mut key_protector_by_id,
1307 None,
1308 key_protector_settings,
1309 bios_guid,
1310 )
1311 .await
1312 .unwrap();
1313
1314 assert!(key_protector_is_empty(&mut vmgs).await);
1315 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1316 }
1317
1318 #[async_test]
1319 async fn provision_vmgs_and_rotate_keys() {
1320 let mut vmgs = new_formatted_vmgs().await;
1321
1322 let mut key_protector = new_key_protector();
1323 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1324
1325 let ingress = [1; AES_GCM_KEY_LENGTH];
1326 let egress = [2; AES_GCM_KEY_LENGTH];
1327 let derived_keys = Keys {
1328 ingress,
1329 decrypt_egress: None,
1330 encrypt_egress: egress,
1331 };
1332
1333 let key_protector_settings = KeyProtectorSettings {
1334 should_write_kp: true,
1335 use_gsp_by_id: true,
1336 use_hardware_unlock: false,
1337 };
1338
1339 let bios_guid = Guid::new_random();
1340
1341 unlock_vmgs_data_store(
1344 &mut vmgs,
1345 false,
1346 &mut key_protector,
1347 &mut key_protector_by_id,
1348 Some(derived_keys),
1349 key_protector_settings,
1350 bios_guid,
1351 )
1352 .await
1353 .unwrap();
1354
1355 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1357
1358 vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1360 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1362
1363 assert!(!key_protector_is_empty(&mut vmgs).await);
1365 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
1366
1367 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1368 .await
1369 .unwrap();
1370 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1371
1372 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1373 assert_eq!(
1374 found_key_protector_by_id.as_bytes(),
1375 key_protector_by_id.inner.as_bytes()
1376 );
1377
1378 let new_egress = [3; AES_GCM_KEY_LENGTH];
1380
1381 let mut new_key_protector = new_key_protector();
1382 let mut new_key_protector_by_id = new_key_protector_by_id(None, None, false);
1383
1384 let key_protector_settings = KeyProtectorSettings {
1385 should_write_kp: true,
1386 use_gsp_by_id: true,
1387 use_hardware_unlock: false,
1388 };
1389
1390 let derived_keys = Keys {
1392 ingress: egress,
1393 decrypt_egress: None,
1394 encrypt_egress: new_egress,
1395 };
1396
1397 unlock_vmgs_data_store(
1398 &mut vmgs,
1399 true,
1400 &mut new_key_protector,
1401 &mut new_key_protector_by_id,
1402 Some(derived_keys),
1403 key_protector_settings,
1404 bios_guid,
1405 )
1406 .await
1407 .unwrap();
1408
1409 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1411 vmgs.unlock_with_encryption_key(&egress).await.unwrap_err();
1413
1414 vmgs.unlock_with_encryption_key(&new_egress).await.unwrap();
1416 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1418
1419 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1420 .await
1421 .unwrap();
1422 assert_eq!(found_key_protector.as_bytes(), new_key_protector.as_bytes());
1423
1424 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1425 assert_eq!(
1426 found_key_protector_by_id.as_bytes(),
1427 new_key_protector_by_id.inner.as_bytes()
1428 );
1429 }
1430
1431 #[async_test]
1432 async fn unlock_previously_encrypted_vmgs_with_ingress_key() {
1433 let mut vmgs = new_formatted_vmgs().await;
1434
1435 let mut key_protector = new_key_protector();
1436 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1437
1438 let ingress = [1; AES_GCM_KEY_LENGTH];
1439 let egress = [2; AES_GCM_KEY_LENGTH];
1440
1441 let derived_keys = Keys {
1442 ingress,
1443 decrypt_egress: None,
1444 encrypt_egress: egress,
1445 };
1446
1447 vmgs.update_encryption_key(&ingress, EncryptionAlgorithm::AES_GCM)
1448 .await
1449 .unwrap();
1450
1451 vmgs.unlock_with_encryption_key(&ingress).await.unwrap();
1453 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1454
1455 let key_protector_settings = KeyProtectorSettings {
1456 should_write_kp: true,
1457 use_gsp_by_id: true,
1458 use_hardware_unlock: false,
1459 };
1460
1461 let bios_guid = Guid::new_random();
1462
1463 unlock_vmgs_data_store(
1464 &mut vmgs,
1465 true,
1466 &mut key_protector,
1467 &mut key_protector_by_id,
1468 Some(derived_keys),
1469 key_protector_settings,
1470 bios_guid,
1471 )
1472 .await
1473 .unwrap();
1474
1475 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1477 vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1478 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1480
1481 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1483 .await
1484 .unwrap();
1485 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1486
1487 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1488 assert_eq!(
1489 found_key_protector_by_id.as_bytes(),
1490 key_protector_by_id.inner.as_bytes()
1491 );
1492 }
1493
1494 #[async_test]
1495 async fn failed_to_persist_ingress_key_so_use_egress_key_to_unlock_vmgs() {
1496 let mut vmgs = new_formatted_vmgs().await;
1497
1498 let mut key_protector = new_key_protector();
1499 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1500
1501 let ingress = [1; AES_GCM_KEY_LENGTH];
1502 let decrypt_egress = [2; AES_GCM_KEY_LENGTH];
1503 let encrypt_egress = [3; AES_GCM_KEY_LENGTH];
1504
1505 let derived_keys = Keys {
1506 ingress,
1507 decrypt_egress: Some(decrypt_egress),
1508 encrypt_egress,
1509 };
1510
1511 vmgs.test_add_new_encryption_key(&decrypt_egress, EncryptionAlgorithm::AES_GCM)
1513 .await
1514 .unwrap();
1515 let egress_key_index = vmgs.test_get_active_datastore_key_index().unwrap();
1516 assert_eq!(egress_key_index, 0);
1517
1518 vmgs.unlock_with_encryption_key(&decrypt_egress)
1519 .await
1520 .unwrap();
1521 let found_egress_key_index = vmgs.test_get_active_datastore_key_index().unwrap();
1522 assert_eq!(found_egress_key_index, egress_key_index);
1523
1524 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1526
1527 let key_protector_settings = KeyProtectorSettings {
1528 should_write_kp: true,
1529 use_gsp_by_id: true,
1530 use_hardware_unlock: false,
1531 };
1532
1533 let bios_guid = Guid::new_random();
1534
1535 unlock_vmgs_data_store(
1536 &mut vmgs,
1537 true,
1538 &mut key_protector,
1539 &mut key_protector_by_id,
1540 Some(derived_keys),
1541 key_protector_settings,
1542 bios_guid,
1543 )
1544 .await
1545 .unwrap();
1546
1547 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1549
1550 vmgs.unlock_with_encryption_key(&decrypt_egress)
1552 .await
1553 .unwrap_err();
1554
1555 vmgs.unlock_with_encryption_key(&encrypt_egress)
1557 .await
1558 .unwrap();
1559 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1560
1561 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1563 .await
1564 .unwrap();
1565 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1566
1567 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1568 assert_eq!(
1569 found_key_protector_by_id.as_bytes(),
1570 key_protector_by_id.inner.as_bytes()
1571 );
1572 }
1573
1574 #[async_test]
1575 async fn fail_to_unlock_vmgs_with_existing_ingress_key() {
1576 let mut vmgs = new_formatted_vmgs().await;
1577
1578 let mut key_protector = new_key_protector();
1579 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1580
1581 let ingress = [1; AES_GCM_KEY_LENGTH];
1582
1583 let derived_keys = Keys {
1585 ingress,
1586 decrypt_egress: None,
1587 encrypt_egress: ingress,
1588 };
1589
1590 let additional_key = [2; AES_GCM_KEY_LENGTH];
1592 let yet_another_key = [3; AES_GCM_KEY_LENGTH];
1593
1594 vmgs.test_add_new_encryption_key(&additional_key, EncryptionAlgorithm::AES_GCM)
1595 .await
1596 .unwrap();
1597 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1598
1599 vmgs.test_add_new_encryption_key(&yet_another_key, EncryptionAlgorithm::AES_GCM)
1600 .await
1601 .unwrap();
1602 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1603
1604 let key_protector_settings = KeyProtectorSettings {
1605 should_write_kp: true,
1606 use_gsp_by_id: true,
1607 use_hardware_unlock: false,
1608 };
1609
1610 let bios_guid = Guid::new_random();
1611
1612 let unlock_result = unlock_vmgs_data_store(
1613 &mut vmgs,
1614 true,
1615 &mut key_protector,
1616 &mut key_protector_by_id,
1617 Some(derived_keys),
1618 key_protector_settings,
1619 bios_guid,
1620 )
1621 .await;
1622 assert!(unlock_result.is_err());
1623 assert_eq!(
1624 unlock_result.unwrap_err().to_string(),
1625 "failed to unlock vmgs with the existing ingress key".to_string()
1626 );
1627 }
1628
1629 #[async_test]
1630 async fn fail_to_unlock_vmgs_with_new_ingress_key() {
1631 let mut vmgs = new_formatted_vmgs().await;
1632
1633 let mut key_protector = new_key_protector();
1634 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1635
1636 let derived_keys = Keys {
1637 ingress: [1; AES_GCM_KEY_LENGTH],
1638 decrypt_egress: None,
1639 encrypt_egress: [2; AES_GCM_KEY_LENGTH],
1640 };
1641
1642 let additional_key = [3; AES_GCM_KEY_LENGTH];
1644 let yet_another_key = [4; AES_GCM_KEY_LENGTH];
1645
1646 vmgs.test_add_new_encryption_key(&additional_key, EncryptionAlgorithm::AES_GCM)
1647 .await
1648 .unwrap();
1649 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1650
1651 vmgs.test_add_new_encryption_key(&yet_another_key, EncryptionAlgorithm::AES_GCM)
1652 .await
1653 .unwrap();
1654 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1655
1656 let key_protector_settings = KeyProtectorSettings {
1657 should_write_kp: true,
1658 use_gsp_by_id: true,
1659 use_hardware_unlock: false,
1660 };
1661
1662 let bios_guid = Guid::new_random();
1663
1664 let unlock_result = unlock_vmgs_data_store(
1665 &mut vmgs,
1666 true,
1667 &mut key_protector,
1668 &mut key_protector_by_id,
1669 Some(derived_keys),
1670 key_protector_settings,
1671 bios_guid,
1672 )
1673 .await;
1674 assert!(unlock_result.is_err());
1675 assert_eq!(
1676 unlock_result.unwrap_err().to_string(),
1677 "failed to unlock vmgs with the existing ingress key".to_string()
1678 );
1679 }
1680
1681 #[async_test]
1682 async fn get_derived_keys_using_id() {
1683 let bios_guid = Guid::new_random();
1684
1685 let gsp_response_by_id = GuestStateProtectionById {
1686 seed: guest_emulation_transport::api::GspCleartextContent {
1687 length: GSP_CLEARTEXT_MAX,
1688 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
1689 },
1690 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
1691 };
1692
1693 let mut key_protector_by_id =
1696 new_key_protector_by_id(Some(Guid::new_zeroed()), None, false);
1697 let derived_keys =
1698 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
1699 .unwrap();
1700
1701 assert_eq!(derived_keys.ingress, derived_keys.encrypt_egress);
1702
1703 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1706 let derived_keys =
1707 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
1708 .unwrap();
1709
1710 assert_ne!(derived_keys.ingress, derived_keys.encrypt_egress);
1711
1712 let gsp_response_by_id_with_0_length_seed = GuestStateProtectionById {
1714 seed: guest_emulation_transport::api::GspCleartextContent {
1715 length: 0,
1716 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
1717 },
1718 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
1719 };
1720
1721 let derived_keys_response = get_derived_keys_by_id(
1722 &mut key_protector_by_id,
1723 bios_guid,
1724 gsp_response_by_id_with_0_length_seed,
1725 );
1726 assert!(derived_keys_response.is_err());
1727 assert_eq!(
1728 derived_keys_response.unwrap_err().to_string(),
1729 "failed to derive an egress key based on current vm bios guid".to_string()
1730 );
1731 }
1732
1733 #[async_test]
1734 async fn pass_through_persist_all_key_protectors() {
1735 let mut vmgs = new_formatted_vmgs().await;
1736 let mut key_protector = new_key_protector();
1737 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1738 let bios_guid = Guid::new_random();
1739
1740 let kp_copy = key_protector.as_bytes().to_vec();
1742 let active_kp_copy = key_protector.active_kp;
1743
1744 let key_protector_settings = KeyProtectorSettings {
1746 should_write_kp: true,
1747 use_gsp_by_id: true,
1748 use_hardware_unlock: true,
1749 };
1750 persist_all_key_protectors(
1751 &mut vmgs,
1752 &mut key_protector,
1753 &mut key_protector_by_id,
1754 bios_guid,
1755 key_protector_settings,
1756 )
1757 .await
1758 .unwrap();
1759
1760 assert!(key_protector_is_empty(&mut vmgs).await);
1761 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1762
1763 assert_eq!(active_kp_copy, key_protector.active_kp);
1765 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
1766 }
1767
1768 #[async_test]
1769 async fn persist_all_key_protectors_write_key_protector_by_id() {
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: false,
1782 use_gsp_by_id: true,
1783 use_hardware_unlock: false,
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);
1797 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
1798
1799 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1800 assert_eq!(
1801 found_key_protector_by_id.as_bytes(),
1802 key_protector_by_id.inner.as_bytes()
1803 );
1804
1805 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
1807 assert_eq!(active_kp_copy, key_protector.active_kp);
1808 }
1809
1810 #[async_test]
1811 async fn persist_all_key_protectors_remove_ingress_kp() {
1812 let mut vmgs = new_formatted_vmgs().await;
1813 let mut key_protector = new_key_protector();
1814 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1815 let bios_guid = Guid::new_random();
1816
1817 let active_kp_copy = key_protector.active_kp;
1819
1820 let key_protector_settings = KeyProtectorSettings {
1823 should_write_kp: true,
1824 use_gsp_by_id: false,
1825 use_hardware_unlock: false,
1826 };
1827 persist_all_key_protectors(
1828 &mut vmgs,
1829 &mut key_protector,
1830 &mut key_protector_by_id,
1831 bios_guid,
1832 key_protector_settings,
1833 )
1834 .await
1835 .unwrap();
1836
1837 assert!(!key_protector_is_empty(&mut vmgs).await);
1838 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1839
1840 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1842 .await
1843 .unwrap();
1844
1845 assert!(
1846 found_key_protector.dek[active_kp_copy as usize]
1847 .dek_buffer
1848 .iter()
1849 .all(|&b| b == 0),
1850 );
1851 assert_eq!(
1852 found_key_protector.gsp[active_kp_copy as usize].gsp_length,
1853 0
1854 );
1855 assert_eq!(found_key_protector.active_kp, active_kp_copy + 1);
1856 }
1857
1858 #[async_test]
1859 async fn persist_all_key_protectors_mark_key_protector_by_id_as_not_in_use() {
1860 let mut vmgs = new_formatted_vmgs().await;
1861 let mut key_protector = new_key_protector();
1862 let mut key_protector_by_id = new_key_protector_by_id(None, None, true);
1863 let bios_guid = Guid::new_random();
1864
1865 let key_protector_settings = KeyProtectorSettings {
1868 should_write_kp: true,
1869 use_gsp_by_id: false,
1870 use_hardware_unlock: true,
1871 };
1872
1873 persist_all_key_protectors(
1874 &mut vmgs,
1875 &mut key_protector,
1876 &mut key_protector_by_id,
1877 bios_guid,
1878 key_protector_settings,
1879 )
1880 .await
1881 .unwrap();
1882
1883 assert!(key_protector_is_empty(&mut vmgs).await);
1884 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
1885
1886 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1888 assert_eq!(found_key_protector_by_id.ported, 1);
1889 assert_eq!(
1890 found_key_protector_by_id.id_guid,
1891 key_protector_by_id.inner.id_guid
1892 );
1893 }
1894}