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 guest_emulation_transport::GuestEmulationTransportClient;
27use guest_emulation_transport::api::GspExtendedStatusFlags;
28use guest_emulation_transport::api::GuestStateProtection;
29use guest_emulation_transport::api::GuestStateProtectionById;
30use guid::Guid;
31use hardware_key_sealing::HardwareDerivedKeys;
32use hardware_key_sealing::HardwareKeyProtectorExt as _;
33use key_protector::GetKeysFromKeyProtectorError;
34use key_protector::KeyProtectorExt as _;
35use mesh::MeshPayload;
36use openhcl_attestation_protocol::igvm_attest::get::runtime_claims::AttestationVmConfig;
37use openhcl_attestation_protocol::vmgs::AES_GCM_KEY_LENGTH;
38use openhcl_attestation_protocol::vmgs::HardwareKeyProtector;
39use openhcl_attestation_protocol::vmgs::KeyProtector;
40use openhcl_attestation_protocol::vmgs::SecurityProfile;
41use openssl::pkey::Private;
42use openssl::rsa::Rsa;
43use pal_async::local::LocalDriver;
44use secure_key_release::VmgsEncryptionKeys;
45use static_assertions::const_assert_eq;
46use std::fmt::Debug;
47use tee_call::TeeCall;
48use thiserror::Error;
49use zerocopy::FromZeros;
50use zerocopy::IntoBytes;
51
52#[derive(Debug, Error)]
54#[error(transparent)]
55pub struct Error(AttestationErrorInner);
56
57impl<T: Into<AttestationErrorInner>> From<T> for Error {
58 fn from(value: T) -> Self {
59 Self(value.into())
60 }
61}
62
63#[derive(Debug, Error)]
64enum AttestationErrorInner {
65 #[error("read security profile from vmgs")]
66 ReadSecurityProfile(#[source] vmgs::ReadFromVmgsError),
67 #[error("failed to request vmgs encryption keys")]
68 RequestVmgsEncryptionKeys(#[source] secure_key_release::RequestVmgsEncryptionKeysError),
69 #[error("failed to get derived keys")]
70 GetDerivedKeys(#[source] GetDerivedKeysError),
71 #[error("failed to read key protector from vmgs")]
72 ReadKeyProtector(#[source] vmgs::ReadFromVmgsError),
73 #[error("failed to read key protector by id from vmgs")]
74 ReadKeyProtectorById(#[source] vmgs::ReadFromVmgsError),
75 #[error("failed to unlock vmgs data store")]
76 UnlockVmgsDataStore(#[source] UnlockVmgsDataStoreError),
77 #[error("failed to read guest secret key from vmgs")]
78 ReadGuestSecretKey(#[source] vmgs::ReadFromVmgsError),
79}
80
81#[derive(Debug, Error)]
82enum GetDerivedKeysError {
83 #[error("failed to get ingress/egress keys from the the key protector")]
84 GetKeysFromKeyProtector(#[source] GetKeysFromKeyProtectorError),
85 #[error("failed to fetch GSP")]
86 FetchGuestStateProtectionById(
87 #[source] guest_emulation_transport::error::GuestStateProtectionByIdError,
88 ),
89 #[error("GSP By Id required, but no GSP By Id found")]
90 GspByIdRequiredButNotFound,
91 #[error("failed to unseal the ingress key using hardware derived keys")]
92 UnsealIngressKeyUsingHardwareDerivedKeys(
93 #[source] hardware_key_sealing::HardwareKeySealingError,
94 ),
95 #[error("failed to get an ingress key from key protector")]
96 GetIngressKeyFromKpFailed,
97 #[error("failed to get an ingress key from guest state protection")]
98 GetIngressKeyFromKGspFailed,
99 #[error("failed to get an ingress key from guest state protection by id")]
100 GetIngressKeyFromKGspByIdFailed,
101 #[error("Encryption cannot be disabled if VMGS was previously encrypted")]
102 DisableVmgsEncryptionFailed,
103 #[error("failed to seal the egress key using hardware derived keys")]
104 SealEgressKeyUsingHardwareDerivedKeys(#[source] hardware_key_sealing::HardwareKeySealingError),
105 #[error("failed to write to `FileId::HW_KEY_PROTECTOR` in vmgs")]
106 VmgsWriteHardwareKeyProtector(#[source] vmgs::WriteToVmgsError),
107 #[error("failed to get derived key by id")]
108 GetDerivedKeyById(#[source] GetDerivedKeysByIdError),
109 #[error("failed to derive an ingress key")]
110 DeriveIngressKey(#[source] crypto::KbkdfError),
111 #[error("failed to derive an egress key")]
112 DeriveEgressKey(#[source] crypto::KbkdfError),
113}
114
115#[derive(Debug, Error)]
116enum GetDerivedKeysByIdError {
117 #[error("failed to derive an egress key based on current vm bios guid")]
118 DeriveEgressKeyUsingCurrentVmId(#[source] crypto::KbkdfError),
119 #[error("invalid derived egress key size {key_size}, expected {expected_size}")]
120 InvalidDerivedEgressKeySize {
121 key_size: usize,
122 expected_size: usize,
123 },
124 #[error("failed to derive an ingress key based on key protector Id from vmgs")]
125 DeriveIngressKeyUsingKeyProtectorId(#[source] crypto::KbkdfError),
126 #[error("invalid derived egress key size {key_size}, expected {expected_size}")]
127 InvalidDerivedIngressKeySize {
128 key_size: usize,
129 expected_size: usize,
130 },
131}
132
133#[derive(Debug, Error)]
134enum UnlockVmgsDataStoreError {
135 #[error("failed to unlock vmgs with the new ingress key")]
136 VmgsUnlockUsingNewIngressKey(#[source] ::vmgs::Error),
137 #[error("failed to unlock vmgs with the existing ingress key")]
138 VmgsUnlockUsingExistingIngressKey(#[source] ::vmgs::Error),
139 #[error("failed to write key protector to vmgs")]
140 WriteKeyProtector(#[source] vmgs::WriteToVmgsError),
141 #[error("failed to read key protector by id to vmgs")]
142 WriteKeyProtectorById(#[source] vmgs::WriteToVmgsError),
143 #[error("failed to remove the old vmgs encryption key")]
144 RemoveOldVmgsEncryptionKey(#[source] ::vmgs::Error),
145 #[error("failed to add a new vmgs encryption key after removing the old key")]
146 AddNewVmgsEncryptionKeyAfterRemoval(#[source] ::vmgs::Error),
147 #[error("failed to add a new vmgs encryption key")]
148 AddNewVmgsEncryptionKey(#[source] ::vmgs::Error),
149 #[error("failed to persist all key protectors")]
150 PersistAllKeyProtectors(#[source] PersistAllKeyProtectorsError),
151}
152
153#[derive(Debug, Error)]
154enum PersistAllKeyProtectorsError {
155 #[error("failed to write key protector to vmgs")]
156 WriteKeyProtector(#[source] vmgs::WriteToVmgsError),
157 #[error("failed to read key protector by id to vmgs")]
158 WriteKeyProtectorById(#[source] vmgs::WriteToVmgsError),
159}
160
161const VMGS_KEY_DERIVE_LABEL: &[u8; 7] = b"VMGSKEY";
163
164#[derive(Debug)]
165struct Keys {
166 ingress: [u8; AES_GCM_KEY_LENGTH],
167 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 Host,
224}
225
226pub async fn initialize_platform_security(
232 get: &GuestEmulationTransportClient,
233 bios_guid: Guid,
234 attestation_vm_config: &AttestationVmConfig,
235 vmgs: &mut Vmgs,
236 attestation_type: AttestationType,
237 suppress_attestation: bool,
238 driver: LocalDriver,
239) -> Result<PlatformAttestationData, Error> {
240 tracing::info!(CVM_ALLOWED,
241 attestation_type=?attestation_type,
242 secure_boot=attestation_vm_config.secure_boot,
243 tpm_enabled=attestation_vm_config.tpm_enabled,
244 tpm_persisted=attestation_vm_config.tpm_persisted,
245 "Reading security profile");
246
247 let SecurityProfile { mut agent_data } = vmgs::read_security_profile(vmgs)
251 .await
252 .map_err(AttestationErrorInner::ReadSecurityProfile)?;
253
254 if suppress_attestation {
257 tracing::info!(CVM_ALLOWED, "Suppressing attestation");
258
259 return Ok(PlatformAttestationData {
260 host_attestation_settings: HostAttestationSettings {
261 refresh_tpm_seeds: false,
262 },
263 agent_data: Some(agent_data.to_vec()),
264 guest_secret_key: None,
265 });
266 }
267
268 let tee_call: Option<Box<dyn TeeCall>> = match attestation_type {
269 AttestationType::Snp => Some(Box::new(tee_call::SnpCall)),
270 AttestationType::Tdx => Some(Box::new(tee_call::TdxCall)),
271 AttestationType::Host => None,
272 };
273
274 let VmgsEncryptionKeys {
275 ingress_rsa_kek,
276 wrapped_des_key,
277 tcb_version,
278 } = if let Some(tee_call) = tee_call.as_ref() {
279 tracing::info!(CVM_ALLOWED, "Retrieving key-encryption key");
280
281 secure_key_release::request_vmgs_encryption_keys(
283 get,
284 tee_call.as_ref(),
285 vmgs,
286 attestation_vm_config,
287 &mut agent_data,
288 driver,
289 )
290 .await
291 .map_err(AttestationErrorInner::RequestVmgsEncryptionKeys)?
292 } else {
293 tracing::info!(CVM_ALLOWED, "Key-encryption key retrieval not required");
294
295 VmgsEncryptionKeys::default()
297 };
298
299 let dek_minimal_size = if wrapped_des_key.is_some() {
301 key_protector::AES_WRAPPED_AES_KEY_LENGTH
302 } else {
303 key_protector::RSA_WRAPPED_AES_KEY_LENGTH
304 };
305
306 tracing::info!(
308 CVM_ALLOWED,
309 dek_minimal_size = dek_minimal_size,
310 "Reading key protector from VMGS"
311 );
312 let mut key_protector = vmgs::read_key_protector(vmgs, dek_minimal_size)
313 .await
314 .map_err(AttestationErrorInner::ReadKeyProtector)?;
315
316 tracing::info!(CVM_ALLOWED, "Reading VM ID from VMGS");
318 let mut key_protector_by_id = match vmgs::read_key_protector_by_id(vmgs).await {
319 Ok(key_protector_by_id) => KeyProtectorById {
320 inner: key_protector_by_id,
321 found_id: true,
322 },
323 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => KeyProtectorById {
324 inner: openhcl_attestation_protocol::vmgs::KeyProtectorById::new_zeroed(),
325 found_id: false,
326 },
327 Err(e) => { Err(AttestationErrorInner::ReadKeyProtectorById(e)) }?,
328 };
329
330 let vm_id_changed = if key_protector_by_id.found_id {
332 let changed = key_protector_by_id.inner.id_guid != bios_guid;
333 if changed {
334 tracing::info!("VM Id has changed since last boot");
335 };
336 changed
337 } else {
338 tracing::info!("First booting of the VM");
339 false
342 };
343
344 let vmgs_encrypted: bool = vmgs.is_encrypted();
345
346 tracing::info!(tcb_version=?tcb_version, vmgs_encrypted = vmgs_encrypted, "Deriving keys");
347 let derived_keys_result = get_derived_keys(
348 get,
349 tee_call.as_deref(),
350 vmgs,
351 &mut key_protector,
352 &mut key_protector_by_id,
353 bios_guid,
354 attestation_vm_config,
355 vmgs_encrypted,
356 ingress_rsa_kek.as_ref(),
357 wrapped_des_key.as_deref(),
358 tcb_version,
359 )
360 .await
361 .map_err(AttestationErrorInner::GetDerivedKeys)?;
362
363 tracing::info!("Unlocking VMGS");
365 if let Err(e) = unlock_vmgs_data_store(
366 vmgs,
367 vmgs_encrypted,
368 &mut key_protector,
369 &mut key_protector_by_id,
370 derived_keys_result.derived_keys,
371 derived_keys_result.key_protector_settings,
372 bios_guid,
373 )
374 .await
375 {
376 get.event_log_fatal(guest_emulation_transport::api::EventLogId::ATTESTATION_FAILED)
377 .await;
378
379 Err(AttestationErrorInner::UnlockVmgsDataStore(e))?
380 }
381
382 let state_refresh_request_from_gsp = derived_keys_result
383 .gsp_extended_status_flags
384 .state_refresh_request();
385
386 let host_attestation_settings = HostAttestationSettings {
387 refresh_tpm_seeds: { state_refresh_request_from_gsp | vm_id_changed },
388 };
389
390 tracing::info!(
391 CVM_ALLOWED,
392 state_refresh_request_from_gsp = state_refresh_request_from_gsp,
393 vm_id_changed = vm_id_changed,
394 "determine if refreshing tpm seeds is needed"
395 );
396
397 let guest_secret_key = match vmgs::read_guest_secret_key(vmgs).await {
399 Ok(data) => Some(data.guest_secret_key.to_vec()),
400 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => None,
401 Err(e) => return Err(AttestationErrorInner::ReadGuestSecretKey(e).into()),
402 };
403
404 Ok(PlatformAttestationData {
405 host_attestation_settings,
406 agent_data: Some(agent_data.to_vec()),
407 guest_secret_key,
408 })
409}
410
411async fn unlock_vmgs_data_store(
414 vmgs: &mut Vmgs,
415 vmgs_encrypted: bool,
416 key_protector: &mut KeyProtector,
417 key_protector_by_id: &mut KeyProtectorById,
418 derived_keys: Option<Keys>,
419 key_protector_settings: KeyProtectorSettings,
420 bios_guid: Guid,
421) -> Result<(), UnlockVmgsDataStoreError> {
422 let mut new_key = false; let Some(Keys {
425 ingress: new_ingress_key,
426 egress: new_egress_key,
427 }) = derived_keys
428 else {
429 tracing::info!(
430 CVM_ALLOWED,
431 "Encryption disabled, skipping unlock vmgs data store"
432 );
433 return Ok(());
434 };
435
436 if new_ingress_key != new_egress_key {
437 tracing::trace!(CVM_ALLOWED, "EgressKey is different than IngressKey");
438 new_key = true;
439 }
440
441 let mut old_index = 2;
443 let mut provision = false;
444 if vmgs_encrypted {
445 tracing::info!(CVM_ALLOWED, "Decrypting vmgs file...");
446 match vmgs.unlock_with_encryption_key(&new_ingress_key).await {
447 Ok(index) => old_index = index,
448 Err(e) if new_key => {
449 tracing::trace!(
451 CVM_ALLOWED,
452 error = &e as &dyn std::error::Error,
453 "Unlock with ingress key error"
454 );
455 old_index = vmgs
457 .unlock_with_encryption_key(&new_egress_key)
458 .await
459 .map_err(UnlockVmgsDataStoreError::VmgsUnlockUsingNewIngressKey)?;
460 new_key = false;
461 }
462 Err(e) => Err(UnlockVmgsDataStoreError::VmgsUnlockUsingExistingIngressKey(
463 e,
464 ))?,
465 }
466 } else {
467 tracing::info!(
469 CVM_ALLOWED,
470 "vmgs data store is not encrypted, provisioning."
471 );
472 provision = true;
473 }
474
475 if key_protector_settings.should_write_kp {
476 vmgs::write_key_protector(key_protector, vmgs)
478 .await
479 .map_err(UnlockVmgsDataStoreError::WriteKeyProtector)?;
480
481 if key_protector_settings.use_gsp_by_id {
482 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
483 .await
484 .map_err(UnlockVmgsDataStoreError::WriteKeyProtectorById)?;
485 }
486 }
487
488 if provision || new_key {
490 let result = vmgs
491 .add_new_encryption_key(&new_egress_key, EncryptionAlgorithm::AES_GCM)
492 .await;
493
494 match result {
495 Ok(_new_index) => (),
496 Err(_) if old_index != 2 => {
497 let key_index = if old_index == 0 { 1 } else { 0 };
500 tracing::trace!(CVM_ALLOWED, key_index = key_index, "Remove old key...");
501 vmgs.remove_encryption_key(key_index)
502 .await
503 .map_err(UnlockVmgsDataStoreError::RemoveOldVmgsEncryptionKey)?;
504
505 tracing::trace!(CVM_ALLOWED, "Add egress_key again...");
506 vmgs.add_new_encryption_key(&new_egress_key, EncryptionAlgorithm::AES_GCM)
507 .await
508 .map_err(UnlockVmgsDataStoreError::AddNewVmgsEncryptionKeyAfterRemoval)?;
509 }
510 Err(e) => Err(UnlockVmgsDataStoreError::AddNewVmgsEncryptionKey(e))?,
511 }
512 }
513
514 if !provision && new_key {
516 vmgs.remove_encryption_key(old_index)
517 .await
518 .map_err(UnlockVmgsDataStoreError::RemoveOldVmgsEncryptionKey)?;
519 }
520
521 persist_all_key_protectors(
523 vmgs,
524 key_protector,
525 key_protector_by_id,
526 bios_guid,
527 key_protector_settings,
528 )
529 .await
530 .map_err(UnlockVmgsDataStoreError::PersistAllKeyProtectors)
531}
532
533async fn get_derived_keys(
550 get: &GuestEmulationTransportClient,
551 tee_call: Option<&dyn TeeCall>,
552 vmgs: &mut Vmgs,
553 key_protector: &mut KeyProtector,
554 key_protector_by_id: &mut KeyProtectorById,
555 bios_guid: Guid,
556 attestation_vm_config: &AttestationVmConfig,
557 is_encrypted: bool,
558 ingress_rsa_kek: Option<&Rsa<Private>>,
559 wrapped_des_key: Option<&[u8]>,
560 tcb_version: Option<u64>,
561) -> Result<DerivedKeyResult, GetDerivedKeysError> {
562 let mut key_protector_settings = KeyProtectorSettings {
563 should_write_kp: true,
564 use_gsp_by_id: false,
565 use_hardware_unlock: false,
566 };
567
568 let mut derived_keys = Keys {
569 ingress: [0u8; AES_GCM_KEY_LENGTH],
570 egress: [0u8; AES_GCM_KEY_LENGTH],
571 };
572
573 let ingress_idx = (key_protector.active_kp % 2) as usize;
575 let egress_idx = if ingress_idx == 0 { 1 } else { 0 } as usize;
576
577 let found_dek = !key_protector.dek[ingress_idx]
578 .dek_buffer
579 .iter()
580 .all(|&x| x == 0);
581
582 let (ingress_key, egress_key, no_kek) = 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 (keys.ingress, keys.egress, false)
608 } else {
609 ([0u8; AES_GCM_KEY_LENGTH], [0u8; AES_GCM_KEY_LENGTH], true)
610 };
611
612 let mut requires_gsp_by_id =
614 key_protector_by_id.found_id && key_protector_by_id.inner.ported != 1;
615
616 let (gsp_response, no_gsp, requires_gsp) = {
618 let found_kp = key_protector.gsp[ingress_idx].gsp_length != 0;
619
620 let response = get_gsp_data(get, key_protector).await;
621
622 tracing::info!(
623 CVM_ALLOWED,
624 request_data_length_in_vmgs = key_protector.gsp[ingress_idx].gsp_length,
625 no_rpc_server = response.extended_status_flags.no_rpc_server(),
626 requires_rpc_server = response.extended_status_flags.requires_rpc_server(),
627 encrypted_gsp_length = response.encrypted_gsp.length,
628 "GSP response"
629 );
630
631 let no_gsp =
632 response.extended_status_flags.no_rpc_server() || response.encrypted_gsp.length == 0;
633
634 let requires_gsp = found_kp || response.extended_status_flags.requires_rpc_server();
635
636 if is_encrypted && !requires_gsp_by_id && !requires_gsp && !found_dek {
639 requires_gsp_by_id = true;
640 }
641
642 (response, no_gsp, requires_gsp)
643 };
644
645 let (gsp_response_by_id, no_gsp_by_id) = if no_gsp || requires_gsp_by_id {
647 let gsp_response_by_id = get
648 .guest_state_protection_data_by_id()
649 .await
650 .map_err(GetDerivedKeysError::FetchGuestStateProtectionById)?;
651
652 let no_gsp_by_id = gsp_response_by_id.extended_status_flags.no_registry_file();
653
654 if no_gsp_by_id && requires_gsp_by_id {
655 Err(GetDerivedKeysError::GspByIdRequiredButNotFound)?
656 }
657
658 (gsp_response_by_id, no_gsp_by_id)
659 } else {
660 (GuestStateProtectionById::new_zeroed(), true)
661 };
662
663 if (no_kek && found_dek) || (no_gsp && requires_gsp) || (no_gsp_by_id && requires_gsp_by_id) {
665 let (hardware_key_protector, hardware_derived_keys) = if let Some(tee_call) = tee_call {
667 let hardware_key_protector = match vmgs::read_hardware_key_protector(vmgs).await {
668 Ok(hardware_key_protector) => Some(hardware_key_protector),
669 Err(e) => {
670 tracing::warn!(
672 CVM_ALLOWED,
673 error = &e as &dyn std::error::Error,
674 "failed to read HW_KEY_PROTECTOR from Vmgs"
675 );
676 None
677 }
678 };
679
680 let hardware_derived_keys = tee_call.supports_get_derived_key().and_then(|tee_call| {
681 if let Some(hardware_key_protector) = &hardware_key_protector {
682 match HardwareDerivedKeys::derive_key(
683 tee_call,
684 attestation_vm_config,
685 hardware_key_protector.header.tcb_version,
686 ) {
687 Ok(hardware_derived_key) => Some(hardware_derived_key),
688 Err(e) => {
689 tracing::warn!(
691 CVM_ALLOWED,
692 error = &e as &dyn std::error::Error,
693 "failed to derive hardware keys using HW_KEY_PROTECTOR",
694 );
695 None
696 }
697 }
698 } else {
699 None
700 }
701 });
702
703 (hardware_key_protector, hardware_derived_keys)
704 } else {
705 (None, None)
706 };
707
708 if let (Some(hardware_key_protector), Some(hardware_derived_keys)) =
709 (hardware_key_protector, hardware_derived_keys)
710 {
711 derived_keys.ingress = hardware_key_protector
712 .unseal_key(&hardware_derived_keys)
713 .map_err(GetDerivedKeysError::UnsealIngressKeyUsingHardwareDerivedKeys)?;
714 derived_keys.egress = derived_keys.ingress;
715
716 key_protector_settings.should_write_kp = false;
717 key_protector_settings.use_hardware_unlock = true;
718
719 tracing::warn!(
720 CVM_ALLOWED,
721 "Using hardware-derived key to recover VMGS DEK"
722 );
723
724 return Ok(DerivedKeyResult {
725 derived_keys: Some(derived_keys),
726 key_protector_settings,
727 gsp_extended_status_flags: gsp_response.extended_status_flags,
728 });
729 } else {
730 if no_kek && found_dek {
731 Err(GetDerivedKeysError::GetIngressKeyFromKpFailed)?
732 } else if no_gsp && requires_gsp {
733 Err(GetDerivedKeysError::GetIngressKeyFromKGspFailed)?
734 } else {
735 Err(GetDerivedKeysError::GetIngressKeyFromKGspByIdFailed)?
737 }
738 }
739 }
740
741 tracing::info!(
742 CVM_ALLOWED,
743 kek = !no_kek,
744 gsp = !no_gsp,
745 gsp_by_id = !no_gsp_by_id,
746 "Encryption sources"
747 );
748
749 if no_kek && no_gsp && no_gsp_by_id {
751 if is_encrypted {
752 Err(GetDerivedKeysError::DisableVmgsEncryptionFailed)?
753 }
754
755 tracing::trace!(CVM_ALLOWED, "No VMGS encryption used.");
756
757 return Ok(DerivedKeyResult {
758 derived_keys: None,
759 key_protector_settings,
760 gsp_extended_status_flags: gsp_response.extended_status_flags,
761 });
762 }
763
764 let hardware_derived_keys = tee_call
766 .and_then(|tee_call| tee_call.supports_get_derived_key())
767 .and_then(|tee_call| {
768 if let Some(tcb_version) = tcb_version {
769 match HardwareDerivedKeys::derive_key(tee_call, attestation_vm_config, tcb_version)
770 {
771 Ok(keys) => Some(keys),
772 Err(e) => {
773 tracing::warn!(
775 CVM_ALLOWED,
776 error = &e as &dyn std::error::Error,
777 "failed to derive hardware keys"
778 );
779 None
780 }
781 }
782 } else {
783 None
784 }
785 });
786
787 if no_gsp && no_gsp_by_id {
789 tracing::trace!(CVM_ALLOWED, "No GSP used with SKR");
790
791 derived_keys.ingress = ingress_key;
792 derived_keys.egress = egress_key;
793
794 if let Some(hardware_derived_keys) = hardware_derived_keys {
795 let hardware_key_protector =
796 HardwareKeyProtector::seal_key(&hardware_derived_keys, &derived_keys.egress)
797 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
798 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
799 .await
800 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
801
802 tracing::info!(CVM_ALLOWED, "hardware key protector updated (no GSP used)");
803 }
804
805 return Ok(DerivedKeyResult {
806 derived_keys: Some(derived_keys),
807 key_protector_settings,
808 gsp_extended_status_flags: gsp_response.extended_status_flags,
809 });
810 }
811
812 if (no_kek && no_gsp) || requires_gsp_by_id {
815 let derived_keys_by_id =
816 get_derived_keys_by_id(key_protector_by_id, bios_guid, gsp_response_by_id)
817 .map_err(GetDerivedKeysError::GetDerivedKeyById)?;
818
819 if no_kek && no_gsp {
820 tracing::trace!(CVM_ALLOWED, "Using GSP with ID.");
821
822 key_protector_settings.should_write_kp = false;
824 key_protector_settings.use_gsp_by_id = true;
825
826 return Ok(DerivedKeyResult {
827 derived_keys: Some(derived_keys_by_id),
828 key_protector_settings,
829 gsp_extended_status_flags: gsp_response.extended_status_flags,
830 });
831 }
832
833 derived_keys.ingress = derived_keys_by_id.ingress;
834
835 tracing::trace!(CVM_ALLOWED, "Converting GSP method.");
836 }
837
838 let egress_seed;
839 let mut ingress_seed = None;
840
841 if requires_gsp_by_id || no_gsp {
847 if found_dek {
850 if requires_gsp_by_id {
851 ingress_seed = Some(
852 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize]
853 .to_vec(),
854 );
855 } else {
856 derived_keys.ingress = ingress_key;
857 }
858 }
859
860 if no_gsp {
862 egress_seed =
863 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize].to_vec();
864 key_protector_settings.use_gsp_by_id = true;
865 } else {
866 egress_seed =
867 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
868 }
869 } else {
870 if gsp_response.decrypted_gsp[ingress_idx].length == 0
873 && gsp_response.decrypted_gsp[egress_idx].length == 0
874 {
875 tracing::trace!(CVM_ALLOWED, "Applying GSP.");
876
877 egress_seed =
880 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
881
882 if !no_kek {
885 derived_keys.ingress = ingress_key;
886 }
887 } else {
888 tracing::trace!(CVM_ALLOWED, "Using GSP.");
889
890 ingress_seed = Some(
891 gsp_response.decrypted_gsp[ingress_idx].buffer
892 [..gsp_response.decrypted_gsp[ingress_idx].length as usize]
893 .to_vec(),
894 );
895
896 if gsp_response.decrypted_gsp[egress_idx].length == 0 {
897 egress_seed =
899 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
900 } else {
901 egress_seed = gsp_response.decrypted_gsp[egress_idx].buffer
906 [..gsp_response.decrypted_gsp[egress_idx].length as usize]
907 .to_vec();
908 key_protector_settings.should_write_kp = false;
909 }
910 }
911 }
912
913 if let Some(seed) = ingress_seed {
915 derived_keys.ingress = crypto::derive_key(&ingress_key, &seed, VMGS_KEY_DERIVE_LABEL)
916 .map_err(GetDerivedKeysError::DeriveIngressKey)?;
917 }
918
919 derived_keys.egress = crypto::derive_key(&egress_key, &egress_seed, VMGS_KEY_DERIVE_LABEL)
921 .map_err(GetDerivedKeysError::DeriveEgressKey)?;
922
923 if key_protector_settings.should_write_kp {
924 key_protector.gsp[egress_idx]
926 .gsp_buffer
927 .copy_from_slice(&gsp_response.encrypted_gsp.buffer);
928 key_protector.gsp[egress_idx].gsp_length = gsp_response.encrypted_gsp.length;
929
930 if let Some(hardware_derived_keys) = hardware_derived_keys {
931 let hardware_key_protector =
932 HardwareKeyProtector::seal_key(&hardware_derived_keys, &derived_keys.egress)
933 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
934
935 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
936 .await
937 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
938
939 tracing::info!(CVM_ALLOWED, "hardware key protector updated");
940 }
941 }
942
943 Ok(DerivedKeyResult {
944 derived_keys: Some(derived_keys),
945 key_protector_settings,
946 gsp_extended_status_flags: gsp_response.extended_status_flags,
947 })
948}
949
950fn get_derived_keys_by_id(
952 key_protector_by_id: &mut KeyProtectorById,
953 bios_guid: Guid,
954 gsp_response_by_id: GuestStateProtectionById,
955) -> Result<Keys, GetDerivedKeysByIdError> {
956 let new_egress_key = crypto::derive_key(
963 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
964 bios_guid.as_bytes(),
965 VMGS_KEY_DERIVE_LABEL,
966 )
967 .map_err(GetDerivedKeysByIdError::DeriveEgressKeyUsingCurrentVmId)?;
968
969 if new_egress_key.len() != AES_GCM_KEY_LENGTH {
970 Err(GetDerivedKeysByIdError::InvalidDerivedEgressKeySize {
971 key_size: new_egress_key.len(),
972 expected_size: AES_GCM_KEY_LENGTH,
973 })?
974 }
975
976 let new_ingress_key = if key_protector_by_id.inner.id_guid != Guid::default() {
979 crypto::derive_key(
981 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
982 key_protector_by_id.inner.id_guid.as_bytes(),
983 VMGS_KEY_DERIVE_LABEL,
984 )
985 .map_err(GetDerivedKeysByIdError::DeriveIngressKeyUsingKeyProtectorId)?
986 } else {
987 new_egress_key
989 };
990
991 if new_ingress_key.len() != AES_GCM_KEY_LENGTH {
992 Err(GetDerivedKeysByIdError::InvalidDerivedIngressKeySize {
993 key_size: new_ingress_key.len(),
994 expected_size: AES_GCM_KEY_LENGTH,
995 })?
996 }
997
998 Ok(Keys {
999 ingress: new_ingress_key,
1000 egress: new_egress_key,
1001 })
1002}
1003
1004async fn get_gsp_data(
1006 get: &GuestEmulationTransportClient,
1007 key_protector: &mut KeyProtector,
1008) -> GuestStateProtection {
1009 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1010 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1011
1012 const_assert_eq!(guest_emulation_transport::api::NUMBER_GSP, NUMBER_KP as u32);
1013 const_assert_eq!(
1014 guest_emulation_transport::api::GSP_CIPHERTEXT_MAX,
1015 GSP_BUFFER_SIZE as u32
1016 );
1017
1018 let mut encrypted_gsp =
1019 [guest_emulation_transport::api::GspCiphertextContent::new_zeroed(); NUMBER_KP];
1020
1021 for (i, gsp) in encrypted_gsp.iter_mut().enumerate().take(NUMBER_KP) {
1022 if key_protector.gsp[i].gsp_length == 0 {
1023 continue;
1024 }
1025
1026 gsp.buffer[..key_protector.gsp[i].gsp_length as usize].copy_from_slice(
1027 &key_protector.gsp[i].gsp_buffer[..key_protector.gsp[i].gsp_length as usize],
1028 );
1029
1030 gsp.length = key_protector.gsp[i].gsp_length;
1031 }
1032
1033 get.guest_state_protection_data(encrypted_gsp, GspExtendedStatusFlags::new())
1034 .await
1035}
1036
1037async fn persist_all_key_protectors(
1039 vmgs: &mut Vmgs,
1040 key_protector: &mut KeyProtector,
1041 key_protector_by_id: &mut KeyProtectorById,
1042 bios_guid: Guid,
1043 key_protector_settings: KeyProtectorSettings,
1044) -> Result<(), PersistAllKeyProtectorsError> {
1045 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1046
1047 if key_protector_settings.use_gsp_by_id && !key_protector_settings.should_write_kp {
1048 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
1049 .await
1050 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1051 } else {
1052 if !key_protector_settings.use_hardware_unlock {
1054 key_protector.dek[key_protector.active_kp as usize % NUMBER_KP]
1056 .dek_buffer
1057 .fill(0);
1058 key_protector.gsp[key_protector.active_kp as usize % NUMBER_KP].gsp_length = 0;
1059 key_protector.active_kp += 1;
1060
1061 vmgs::write_key_protector(key_protector, vmgs)
1062 .await
1063 .map_err(PersistAllKeyProtectorsError::WriteKeyProtector)?;
1064 }
1065
1066 if !key_protector_settings.use_gsp_by_id
1068 && key_protector_by_id.found_id
1069 && key_protector_by_id.inner.ported == 0
1070 {
1071 key_protector_by_id.inner.ported = 1;
1072 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, true, bios_guid)
1073 .await
1074 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1075 }
1076 }
1077
1078 Ok(())
1079}
1080
1081#[cfg(test)]
1082mod tests {
1083 use super::*;
1084 use disk_backend::Disk;
1085 use disklayer_ram::ram_disk;
1086 use get_protocol::GSP_CLEARTEXT_MAX;
1087 use get_protocol::GspExtendedStatusFlags;
1088 use key_protector::AES_WRAPPED_AES_KEY_LENGTH;
1089 use openhcl_attestation_protocol::vmgs::DEK_BUFFER_SIZE;
1090 use openhcl_attestation_protocol::vmgs::DekKp;
1091 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1092 use openhcl_attestation_protocol::vmgs::GspKp;
1093 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1094 use pal_async::async_test;
1095 use vmgs_format::EncryptionAlgorithm;
1096 use vmgs_format::FileId;
1097
1098 const ONE_MEGA_BYTE: u64 = 1024 * 1024;
1099
1100 fn new_test_file() -> Disk {
1101 ram_disk(4 * ONE_MEGA_BYTE, false).unwrap()
1102 }
1103
1104 async fn new_formatted_vmgs() -> Vmgs {
1105 let disk = new_test_file();
1106
1107 let mut vmgs = Vmgs::format_new(disk, None).await.unwrap();
1108
1109 assert!(
1110 key_protector_is_empty(&mut vmgs).await,
1111 "Newly formatted VMGS should have an empty key protector"
1112 );
1113 assert!(
1114 key_protector_by_id_is_empty(&mut vmgs).await,
1115 "Newly formatted VMGS should have an empty key protector by id"
1116 );
1117
1118 vmgs
1119 }
1120
1121 async fn key_protector_is_empty(vmgs: &mut Vmgs) -> bool {
1122 let key_protector = vmgs::read_key_protector(vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1123 .await
1124 .unwrap();
1125
1126 key_protector.as_bytes().iter().all(|&b| b == 0)
1127 }
1128
1129 async fn key_protector_by_id_is_empty(vmgs: &mut Vmgs) -> bool {
1130 vmgs::read_key_protector_by_id(vmgs)
1131 .await
1132 .is_err_and(|err| {
1133 matches!(
1134 err,
1135 vmgs::ReadFromVmgsError::EntryNotFound(FileId::VM_UNIQUE_ID)
1136 )
1137 })
1138 }
1139
1140 fn new_key_protector() -> KeyProtector {
1141 assert_eq!(NUMBER_KP, 2);
1143
1144 let ingress_dek = DekKp {
1145 dek_buffer: [1; DEK_BUFFER_SIZE],
1146 };
1147 let egress_dek = DekKp {
1148 dek_buffer: [2; DEK_BUFFER_SIZE],
1149 };
1150 let ingress_gsp = GspKp {
1151 gsp_length: GSP_BUFFER_SIZE as u32,
1152 gsp_buffer: [3; GSP_BUFFER_SIZE],
1153 };
1154 let egress_gsp = GspKp {
1155 gsp_length: GSP_BUFFER_SIZE as u32,
1156 gsp_buffer: [4; GSP_BUFFER_SIZE],
1157 };
1158 KeyProtector {
1159 dek: [ingress_dek, egress_dek],
1160 gsp: [ingress_gsp, egress_gsp],
1161 active_kp: 0,
1162 }
1163 }
1164
1165 fn new_key_protector_by_id(
1166 id_guid: Option<Guid>,
1167 ported: Option<u8>,
1168 found_id: bool,
1169 ) -> KeyProtectorById {
1170 let key_protector_by_id = openhcl_attestation_protocol::vmgs::KeyProtectorById {
1171 id_guid: id_guid.unwrap_or_else(Guid::new_random),
1172 ported: ported.unwrap_or(0),
1173 pad: [0; 3],
1174 };
1175
1176 KeyProtectorById {
1177 inner: key_protector_by_id,
1178 found_id,
1179 }
1180 }
1181
1182 #[async_test]
1183 async fn do_nothing_without_derived_keys() {
1184 let mut vmgs = new_formatted_vmgs().await;
1185
1186 let mut key_protector = new_key_protector();
1187 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1188
1189 let key_protector_settings = KeyProtectorSettings {
1190 should_write_kp: false,
1191 use_gsp_by_id: false,
1192 use_hardware_unlock: false,
1193 };
1194
1195 let bios_guid = Guid::new_random();
1196
1197 unlock_vmgs_data_store(
1198 &mut vmgs,
1199 false,
1200 &mut key_protector,
1201 &mut key_protector_by_id,
1202 None,
1203 key_protector_settings,
1204 bios_guid,
1205 )
1206 .await
1207 .unwrap();
1208
1209 assert!(key_protector_is_empty(&mut vmgs).await);
1210 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1211
1212 let key_protector_settings = KeyProtectorSettings {
1214 should_write_kp: false,
1215 use_gsp_by_id: false,
1216 use_hardware_unlock: false,
1217 };
1218
1219 unlock_vmgs_data_store(
1221 &mut vmgs,
1222 true,
1223 &mut key_protector,
1224 &mut key_protector_by_id,
1225 None,
1226 key_protector_settings,
1227 bios_guid,
1228 )
1229 .await
1230 .unwrap();
1231
1232 assert!(key_protector_is_empty(&mut vmgs).await);
1233 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1234 }
1235
1236 #[async_test]
1237 async fn provision_vmgs_and_rotate_keys() {
1238 let mut vmgs = new_formatted_vmgs().await;
1239
1240 let mut key_protector = new_key_protector();
1241 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1242
1243 let ingress = [1; AES_GCM_KEY_LENGTH];
1244 let egress = [2; AES_GCM_KEY_LENGTH];
1245 let derived_keys = Keys { ingress, egress };
1246
1247 let key_protector_settings = KeyProtectorSettings {
1248 should_write_kp: true,
1249 use_gsp_by_id: true,
1250 use_hardware_unlock: false,
1251 };
1252
1253 let bios_guid = Guid::new_random();
1254
1255 unlock_vmgs_data_store(
1258 &mut vmgs,
1259 false,
1260 &mut key_protector,
1261 &mut key_protector_by_id,
1262 Some(derived_keys),
1263 key_protector_settings,
1264 bios_guid,
1265 )
1266 .await
1267 .unwrap();
1268
1269 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1271
1272 let egress_index = vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1274 assert_eq!(egress_index, 0);
1276
1277 assert!(!key_protector_is_empty(&mut vmgs).await);
1279 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
1280
1281 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1282 .await
1283 .unwrap();
1284 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1285
1286 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1287 assert_eq!(
1288 found_key_protector_by_id.as_bytes(),
1289 key_protector_by_id.inner.as_bytes()
1290 );
1291
1292 let new_egress = [3; AES_GCM_KEY_LENGTH];
1294
1295 let mut new_key_protector = new_key_protector();
1296 let mut new_key_protector_by_id = new_key_protector_by_id(None, None, false);
1297
1298 let key_protector_settings = KeyProtectorSettings {
1299 should_write_kp: true,
1300 use_gsp_by_id: true,
1301 use_hardware_unlock: false,
1302 };
1303
1304 let derived_keys = Keys {
1306 ingress: egress,
1307 egress: new_egress,
1308 };
1309
1310 unlock_vmgs_data_store(
1311 &mut vmgs,
1312 true,
1313 &mut new_key_protector,
1314 &mut new_key_protector_by_id,
1315 Some(derived_keys),
1316 key_protector_settings,
1317 bios_guid,
1318 )
1319 .await
1320 .unwrap();
1321
1322 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1324 vmgs.unlock_with_encryption_key(&egress).await.unwrap_err();
1326
1327 let new_egress_index = vmgs.unlock_with_encryption_key(&new_egress).await.unwrap();
1329 assert_eq!(new_egress_index, 1);
1331
1332 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1333 .await
1334 .unwrap();
1335 assert_eq!(found_key_protector.as_bytes(), new_key_protector.as_bytes());
1336
1337 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1338 assert_eq!(
1339 found_key_protector_by_id.as_bytes(),
1340 new_key_protector_by_id.inner.as_bytes()
1341 );
1342 }
1343
1344 #[async_test]
1345 async fn unlock_previously_encrypted_vmgs_with_ingress_key() {
1346 let mut vmgs = new_formatted_vmgs().await;
1347
1348 let mut key_protector = new_key_protector();
1349 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1350
1351 let ingress = [1; AES_GCM_KEY_LENGTH];
1352 let egress = [2; AES_GCM_KEY_LENGTH];
1353
1354 let derived_keys = Keys { ingress, egress };
1355
1356 vmgs.add_new_encryption_key(&ingress, EncryptionAlgorithm::AES_GCM)
1357 .await
1358 .unwrap();
1359
1360 let ingress_index = vmgs.unlock_with_encryption_key(&ingress).await.unwrap();
1362 assert_eq!(ingress_index, 0);
1363
1364 let key_protector_settings = KeyProtectorSettings {
1365 should_write_kp: true,
1366 use_gsp_by_id: true,
1367 use_hardware_unlock: false,
1368 };
1369
1370 let bios_guid = Guid::new_random();
1371
1372 unlock_vmgs_data_store(
1373 &mut vmgs,
1374 true,
1375 &mut key_protector,
1376 &mut key_protector_by_id,
1377 Some(derived_keys),
1378 key_protector_settings,
1379 bios_guid,
1380 )
1381 .await
1382 .unwrap();
1383
1384 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1386 let egress_index = vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1387 assert_eq!(egress_index, 1);
1389
1390 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1392 .await
1393 .unwrap();
1394 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1395
1396 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1397 assert_eq!(
1398 found_key_protector_by_id.as_bytes(),
1399 key_protector_by_id.inner.as_bytes()
1400 );
1401 }
1402
1403 #[async_test]
1404 async fn failed_to_persist_ingress_key_so_use_egress_key_to_unlock_vmgs() {
1405 let mut vmgs = new_formatted_vmgs().await;
1406
1407 let mut key_protector = new_key_protector();
1408 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1409
1410 let ingress = [1; AES_GCM_KEY_LENGTH];
1411 let egress = [2; AES_GCM_KEY_LENGTH];
1412
1413 let derived_keys = Keys { ingress, egress };
1414
1415 let egress_key_index = vmgs
1417 .add_new_encryption_key(&egress, EncryptionAlgorithm::AES_GCM)
1418 .await
1419 .unwrap();
1420 assert_eq!(egress_key_index, 0);
1421
1422 let found_egress_key_index = vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1423 assert_eq!(found_egress_key_index, egress_key_index);
1424
1425 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1427
1428 let key_protector_settings = KeyProtectorSettings {
1429 should_write_kp: true,
1430 use_gsp_by_id: true,
1431 use_hardware_unlock: false,
1432 };
1433
1434 let bios_guid = Guid::new_random();
1435
1436 unlock_vmgs_data_store(
1437 &mut vmgs,
1438 true,
1439 &mut key_protector,
1440 &mut key_protector_by_id,
1441 Some(derived_keys),
1442 key_protector_settings,
1443 bios_guid,
1444 )
1445 .await
1446 .unwrap();
1447
1448 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1450
1451 let found_egress_key_index = vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1453 assert_eq!(found_egress_key_index, egress_key_index);
1454
1455 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1457 .await
1458 .unwrap();
1459 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1460
1461 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1462 assert_eq!(
1463 found_key_protector_by_id.as_bytes(),
1464 key_protector_by_id.inner.as_bytes()
1465 );
1466 }
1467
1468 #[async_test]
1469 async fn fail_to_unlock_vmgs_with_existing_ingress_key() {
1470 let mut vmgs = new_formatted_vmgs().await;
1471
1472 let mut key_protector = new_key_protector();
1473 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1474
1475 let ingress = [1; AES_GCM_KEY_LENGTH];
1476
1477 let derived_keys = Keys {
1479 ingress,
1480 egress: ingress,
1481 };
1482
1483 let additional_key = [2; AES_GCM_KEY_LENGTH];
1485 let yet_another_key = [3; AES_GCM_KEY_LENGTH];
1486
1487 let additional_key_index = vmgs
1488 .add_new_encryption_key(&additional_key, EncryptionAlgorithm::AES_GCM)
1489 .await
1490 .unwrap();
1491 assert_eq!(additional_key_index, 0);
1492
1493 let yet_another_key_index = vmgs
1494 .add_new_encryption_key(&yet_another_key, EncryptionAlgorithm::AES_GCM)
1495 .await
1496 .unwrap();
1497 assert_eq!(yet_another_key_index, 1);
1498
1499 let key_protector_settings = KeyProtectorSettings {
1500 should_write_kp: true,
1501 use_gsp_by_id: true,
1502 use_hardware_unlock: false,
1503 };
1504
1505 let bios_guid = Guid::new_random();
1506
1507 let unlock_result = unlock_vmgs_data_store(
1508 &mut vmgs,
1509 true,
1510 &mut key_protector,
1511 &mut key_protector_by_id,
1512 Some(derived_keys),
1513 key_protector_settings,
1514 bios_guid,
1515 )
1516 .await;
1517 assert!(unlock_result.is_err());
1518 assert_eq!(
1519 unlock_result.unwrap_err().to_string(),
1520 "failed to unlock vmgs with the existing ingress key".to_string()
1521 );
1522 }
1523
1524 #[async_test]
1525 async fn fail_to_unlock_vmgs_with_new_ingress_key() {
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 derived_keys = Keys {
1532 ingress: [1; AES_GCM_KEY_LENGTH],
1533 egress: [2; AES_GCM_KEY_LENGTH],
1534 };
1535
1536 let additional_key = [3; AES_GCM_KEY_LENGTH];
1538 let yet_another_key = [4; AES_GCM_KEY_LENGTH];
1539
1540 let additional_key_index = vmgs
1541 .add_new_encryption_key(&additional_key, EncryptionAlgorithm::AES_GCM)
1542 .await
1543 .unwrap();
1544 assert_eq!(additional_key_index, 0);
1545
1546 let yet_another_key_index = vmgs
1547 .add_new_encryption_key(&yet_another_key, EncryptionAlgorithm::AES_GCM)
1548 .await
1549 .unwrap();
1550 assert_eq!(yet_another_key_index, 1);
1551
1552 let key_protector_settings = KeyProtectorSettings {
1553 should_write_kp: true,
1554 use_gsp_by_id: true,
1555 use_hardware_unlock: false,
1556 };
1557
1558 let bios_guid = Guid::new_random();
1559
1560 let unlock_result = unlock_vmgs_data_store(
1561 &mut vmgs,
1562 true,
1563 &mut key_protector,
1564 &mut key_protector_by_id,
1565 Some(derived_keys),
1566 key_protector_settings,
1567 bios_guid,
1568 )
1569 .await;
1570 assert!(unlock_result.is_err());
1571 assert_eq!(
1572 unlock_result.unwrap_err().to_string(),
1573 "failed to unlock vmgs with the new ingress key".to_string()
1574 );
1575 }
1576
1577 #[async_test]
1578 async fn get_derived_keys_using_id() {
1579 let bios_guid = Guid::new_random();
1580
1581 let gsp_response_by_id = GuestStateProtectionById {
1582 seed: guest_emulation_transport::api::GspCleartextContent {
1583 length: GSP_CLEARTEXT_MAX,
1584 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
1585 },
1586 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
1587 };
1588
1589 let mut key_protector_by_id =
1592 new_key_protector_by_id(Some(Guid::new_zeroed()), None, false);
1593 let derived_keys =
1594 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
1595 .unwrap();
1596
1597 assert_eq!(derived_keys.ingress, derived_keys.egress);
1598
1599 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1602 let derived_keys =
1603 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
1604 .unwrap();
1605
1606 assert_ne!(derived_keys.ingress, derived_keys.egress);
1607
1608 let gsp_response_by_id_with_0_length_seed = GuestStateProtectionById {
1610 seed: guest_emulation_transport::api::GspCleartextContent {
1611 length: 0,
1612 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
1613 },
1614 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
1615 };
1616
1617 let derived_keys_response = get_derived_keys_by_id(
1618 &mut key_protector_by_id,
1619 bios_guid,
1620 gsp_response_by_id_with_0_length_seed,
1621 );
1622 assert!(derived_keys_response.is_err());
1623 assert_eq!(
1624 derived_keys_response.unwrap_err().to_string(),
1625 "failed to derive an egress key based on current vm bios guid".to_string()
1626 );
1627 }
1628
1629 #[async_test]
1630 async fn pass_through_persist_all_key_protectors() {
1631 let mut vmgs = new_formatted_vmgs().await;
1632 let mut key_protector = new_key_protector();
1633 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1634 let bios_guid = Guid::new_random();
1635
1636 let kp_copy = key_protector.as_bytes().to_vec();
1638 let active_kp_copy = key_protector.active_kp;
1639
1640 let key_protector_settings = KeyProtectorSettings {
1642 should_write_kp: true,
1643 use_gsp_by_id: true,
1644 use_hardware_unlock: true,
1645 };
1646 persist_all_key_protectors(
1647 &mut vmgs,
1648 &mut key_protector,
1649 &mut key_protector_by_id,
1650 bios_guid,
1651 key_protector_settings,
1652 )
1653 .await
1654 .unwrap();
1655
1656 assert!(key_protector_is_empty(&mut vmgs).await);
1657 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1658
1659 assert_eq!(active_kp_copy, key_protector.active_kp);
1661 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
1662 }
1663
1664 #[async_test]
1665 async fn persist_all_key_protectors_write_key_protector_by_id() {
1666 let mut vmgs = new_formatted_vmgs().await;
1667 let mut key_protector = new_key_protector();
1668 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1669 let bios_guid = Guid::new_random();
1670
1671 let kp_copy = key_protector.as_bytes().to_vec();
1673 let active_kp_copy = key_protector.active_kp;
1674
1675 let key_protector_settings = KeyProtectorSettings {
1677 should_write_kp: false,
1678 use_gsp_by_id: true,
1679 use_hardware_unlock: false,
1680 };
1681 persist_all_key_protectors(
1682 &mut vmgs,
1683 &mut key_protector,
1684 &mut key_protector_by_id,
1685 bios_guid,
1686 key_protector_settings,
1687 )
1688 .await
1689 .unwrap();
1690
1691 assert!(key_protector_is_empty(&mut vmgs).await);
1693 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
1694
1695 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1696 assert_eq!(
1697 found_key_protector_by_id.as_bytes(),
1698 key_protector_by_id.inner.as_bytes()
1699 );
1700
1701 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
1703 assert_eq!(active_kp_copy, key_protector.active_kp);
1704 }
1705
1706 #[async_test]
1707 async fn persist_all_key_protectors_remove_ingress_kp() {
1708 let mut vmgs = new_formatted_vmgs().await;
1709 let mut key_protector = new_key_protector();
1710 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1711 let bios_guid = Guid::new_random();
1712
1713 let active_kp_copy = key_protector.active_kp;
1715
1716 let key_protector_settings = KeyProtectorSettings {
1719 should_write_kp: true,
1720 use_gsp_by_id: false,
1721 use_hardware_unlock: false,
1722 };
1723 persist_all_key_protectors(
1724 &mut vmgs,
1725 &mut key_protector,
1726 &mut key_protector_by_id,
1727 bios_guid,
1728 key_protector_settings,
1729 )
1730 .await
1731 .unwrap();
1732
1733 assert!(!key_protector_is_empty(&mut vmgs).await);
1734 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1735
1736 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1738 .await
1739 .unwrap();
1740
1741 assert!(
1742 found_key_protector.dek[active_kp_copy as usize]
1743 .dek_buffer
1744 .iter()
1745 .all(|&b| b == 0),
1746 );
1747 assert_eq!(
1748 found_key_protector.gsp[active_kp_copy as usize].gsp_length,
1749 0
1750 );
1751 assert_eq!(found_key_protector.active_kp, active_kp_copy + 1);
1752 }
1753
1754 #[async_test]
1755 async fn persist_all_key_protectors_mark_key_protector_by_id_as_not_in_use() {
1756 let mut vmgs = new_formatted_vmgs().await;
1757 let mut key_protector = new_key_protector();
1758 let mut key_protector_by_id = new_key_protector_by_id(None, None, true);
1759 let bios_guid = Guid::new_random();
1760
1761 let key_protector_settings = KeyProtectorSettings {
1764 should_write_kp: true,
1765 use_gsp_by_id: false,
1766 use_hardware_unlock: true,
1767 };
1768
1769 persist_all_key_protectors(
1770 &mut vmgs,
1771 &mut key_protector,
1772 &mut key_protector_by_id,
1773 bios_guid,
1774 key_protector_settings,
1775 )
1776 .await
1777 .unwrap();
1778
1779 assert!(key_protector_is_empty(&mut vmgs).await);
1780 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
1781
1782 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1784 assert_eq!(found_key_protector_by_id.ported, 1);
1785 assert_eq!(
1786 found_key_protector_by_id.id_guid,
1787 key_protector_by_id.inner.id_guid
1788 );
1789 }
1790}