1#![cfg(target_os = "linux")]
10#![forbid(unsafe_code)]
11
12mod hardware_key_sealing;
13mod igvm_attest;
14mod jwt;
15mod key_protector;
16mod secure_key_release;
17mod vmgs;
18
19#[cfg(test)]
20mod test_helpers;
21
22pub use igvm_attest::Error as IgvmAttestError;
23pub use igvm_attest::IgvmAttestRequestHelper;
24pub use igvm_attest::ak_cert::parse_response as parse_ak_cert_response;
25
26use crate::jwt::JwtError;
27use crate::jwt::JwtHelper;
28use ::vmgs::EncryptionAlgorithm;
29use ::vmgs::GspType;
30use ::vmgs::Vmgs;
31use crypto::rsa::RsaKeyPair;
32use crypto::sha_256::sha_256;
33use cvm_tracing::CVM_ALLOWED;
34use get_protocol::dps_json::GuestStateEncryptionPolicy;
35use guest_emulation_transport::GuestEmulationTransportClient;
36use guest_emulation_transport::api::GspExtendedStatusFlags;
37use guest_emulation_transport::api::GuestStateProtection;
38use guest_emulation_transport::api::GuestStateProtectionById;
39use guid::Guid;
40use hardware_key_sealing::HardwareDerivedKeys;
41use hardware_key_sealing::HardwareKeyProtectorExt as _;
42use key_protector::GetKeysFromKeyProtectorError;
43use key_protector::KeyProtectorExt as _;
44use mesh::MeshPayload;
45use openhcl_attestation_protocol::igvm_attest::get::runtime_claims::AttestationVmConfig;
46use openhcl_attestation_protocol::igvm_attest::get::runtime_claims::VmgsProvisioner;
47use openhcl_attestation_protocol::vmgs::AES_GCM_KEY_LENGTH;
48use openhcl_attestation_protocol::vmgs::AGENT_DATA_MAX_SIZE;
49use openhcl_attestation_protocol::vmgs::HardwareKeyProtector;
50use openhcl_attestation_protocol::vmgs::KeyProtector;
51use openhcl_attestation_protocol::vmgs::SecurityProfile;
52use pal_async::local::LocalDriver;
53use secure_key_release::VmgsEncryptionKeys;
54use serde::Deserialize;
55use serde::Serialize;
56use static_assertions::const_assert_eq;
57use std::fmt::Debug;
58use tee_call::TeeCall;
59use thiserror::Error;
60use zerocopy::FromZeros;
61use zerocopy::IntoBytes;
62
63#[derive(Debug, Error)]
65#[error(transparent)]
66pub struct Error(AttestationErrorInner);
67
68impl<T: Into<AttestationErrorInner>> From<T> for Error {
69 fn from(value: T) -> Self {
70 Self(value.into())
71 }
72}
73
74#[derive(Debug, Error)]
75enum AttestationErrorInner {
76 #[error("read security profile from vmgs")]
77 ReadSecurityProfile(#[source] vmgs::ReadFromVmgsError),
78 #[error("failed to get derived keys")]
79 GetDerivedKeys(#[source] GetDerivedKeysError),
80 #[error("failed to read key protector from vmgs")]
81 ReadKeyProtector(#[source] vmgs::ReadFromVmgsError),
82 #[error("failed to read key protector by id from vmgs")]
83 ReadKeyProtectorById(#[source] vmgs::ReadFromVmgsError),
84 #[error("failed to unlock vmgs data store")]
85 UnlockVmgsDataStore(#[source] UnlockVmgsDataStoreError),
86 #[error("failed to read guest secret key from vmgs")]
87 ReadGuestSecretKey(#[source] vmgs::ReadFromVmgsError),
88 #[error("failed to verify VMGS provenance")]
89 Provenance(#[source] ProvenanceError),
90}
91
92#[derive(Debug, Error)]
93enum GetDerivedKeysError {
94 #[error("failed to get ingress/egress keys from the the key protector")]
95 GetKeysFromKeyProtector(#[source] GetKeysFromKeyProtectorError),
96 #[error("failed to fetch GSP")]
97 FetchGuestStateProtectionById(
98 #[source] guest_emulation_transport::error::GuestStateProtectionByIdError,
99 ),
100 #[error("GSP By Id required, but no GSP By Id found")]
101 GspByIdRequiredButNotFound,
102 #[error("failed to unseal the ingress key using hardware derived keys")]
103 UnsealIngressKeyUsingHardwareDerivedKeys(
104 #[source] hardware_key_sealing::HardwareKeySealingError,
105 ),
106 #[error("failed to get an ingress key from key protector")]
107 GetIngressKeyFromKpFailed,
108 #[error("failed to get an ingress key from guest state protection")]
109 GetIngressKeyFromKGspFailed,
110 #[error("failed to get an ingress key from guest state protection by id")]
111 GetIngressKeyFromKGspByIdFailed,
112 #[error("Encryption cannot be disabled if VMGS was previously encrypted")]
113 DisableVmgsEncryptionFailed,
114 #[error("VMGS encryption is required, but no encryption sources were found")]
115 EncryptionRequiredButNotFound,
116 #[error("failed to seal the egress key using hardware derived keys")]
117 SealEgressKeyUsingHardwareDerivedKeys(#[source] hardware_key_sealing::HardwareKeySealingError),
118 #[error("failed to write to `FileId::HW_KEY_PROTECTOR` in vmgs")]
119 VmgsWriteHardwareKeyProtector(#[source] vmgs::WriteToVmgsError),
120 #[error("failed to get derived key by id")]
121 GetDerivedKeyById(#[source] GetDerivedKeysByIdError),
122 #[error("failed to derive an ingress key")]
123 DeriveIngressKey(#[source] crypto::kbkdf::KbkdfError),
124 #[error("failed to derive an egress key")]
125 DeriveEgressKey(#[source] crypto::kbkdf::KbkdfError),
126}
127
128#[derive(Debug, Error)]
129enum GetDerivedKeysByIdError {
130 #[error("failed to derive an egress key based on current vm bios guid")]
131 DeriveEgressKeyUsingCurrentVmId(#[source] crypto::kbkdf::KbkdfError),
132 #[error("invalid derived egress key size {key_size}, expected {expected_size}")]
133 InvalidDerivedEgressKeySize {
134 key_size: usize,
135 expected_size: usize,
136 },
137 #[error("failed to derive an ingress key based on key protector Id from vmgs")]
138 DeriveIngressKeyUsingKeyProtectorId(#[source] crypto::kbkdf::KbkdfError),
139 #[error("invalid derived egress key size {key_size}, expected {expected_size}")]
140 InvalidDerivedIngressKeySize {
141 key_size: usize,
142 expected_size: usize,
143 },
144}
145
146#[derive(Debug, Error)]
147enum UnlockVmgsDataStoreError {
148 #[error("failed to unlock vmgs with the existing egress key")]
149 VmgsUnlockUsingExistingEgressKey(#[source] ::vmgs::Error),
150 #[error("failed to unlock vmgs with the existing ingress key")]
151 VmgsUnlockUsingExistingIngressKey(#[source] ::vmgs::Error),
152 #[error("failed to write key protector to vmgs")]
153 WriteKeyProtector(#[source] vmgs::WriteToVmgsError),
154 #[error("failed to read key protector by id to vmgs")]
155 WriteKeyProtectorById(#[source] vmgs::WriteToVmgsError),
156 #[error("failed to update the vmgs encryption key")]
157 UpdateVmgsEncryptionKey(#[source] ::vmgs::Error),
158 #[error("failed to persist all key protectors")]
159 PersistAllKeyProtectors(#[source] PersistAllKeyProtectorsError),
160}
161
162#[derive(Debug, Error)]
163enum PersistAllKeyProtectorsError {
164 #[error("failed to write key protector to vmgs")]
165 WriteKeyProtector(#[source] vmgs::WriteToVmgsError),
166 #[error("failed to read key protector by id to vmgs")]
167 WriteKeyProtectorById(#[source] vmgs::WriteToVmgsError),
168}
169
170#[derive(Debug, Error)]
171enum ProvenanceError {
172 #[error("failed to decode provenance doc")]
173 DecodeProvenanceDoc(#[source] JwtError),
174 #[error("failed to verify JWT signature")]
175 VerifySignature(#[source] JwtError),
176 #[error("invalid signature")]
177 InvalidSignature,
178 #[error("missing leaf certificate subject common name")]
179 MissingLeafCertSubjectName,
180 #[error("invalid root certificate")]
181 InvalidRootCert,
182 #[error("failed to convert VMGSID data")]
183 InvalidVmgsidData(#[source] std::str::Utf8Error),
184 #[error("failed to parse VMGSID seed data")]
185 ParseVmgsidSeedData,
186 #[error("failed to decode VMGSID seed data")]
187 DecodeVmgsidData(#[source] hex::FromHexError),
188 #[error("X509 certificate error")]
189 X509Error(#[source] crypto::x509::X509Error),
190 #[error("SP800-108 KDF error")]
191 KdfError(#[source] crypto::kbkdf::KbkdfError),
192 #[error("failed to parse VMGSID")]
193 ParseVmgsid(#[source] guid::ParseError),
194}
195
196#[derive(Debug)]
198enum LogOpType {
199 BeginDecryptVmgs,
200 DecryptVmgs,
201 ConvertEncryptionType,
202}
203
204const VMGS_KEY_DERIVE_LABEL: &[u8; 7] = b"VMGSKEY";
206
207fn derive_key(
209 key: &[u8],
210 context: &[u8],
211 label: &[u8],
212) -> Result<[u8; AES_GCM_KEY_LENGTH], crypto::kbkdf::KbkdfError> {
213 let output = crypto::kbkdf::kbkdf_hmac_sha256(key, context, label, AES_GCM_KEY_LENGTH)?;
214 Ok(output.try_into().unwrap())
215}
216
217#[derive(Debug)]
218struct Keys {
219 ingress: [u8; AES_GCM_KEY_LENGTH],
220 decrypt_egress: Option<[u8; AES_GCM_KEY_LENGTH]>,
221 encrypt_egress: [u8; AES_GCM_KEY_LENGTH],
222}
223
224#[derive(Clone, Copy)]
226struct KeyProtectorSettings {
227 should_write_kp: bool,
229 use_gsp_by_id: bool,
231 use_hardware_unlock: bool,
233 decrypt_gsp_type: GspType,
235 encrypt_gsp_type: GspType,
237}
238
239struct KeyProtectorById {
241 pub inner: openhcl_attestation_protocol::vmgs::KeyProtectorById,
243 pub found_id: bool,
245}
246
247pub struct HostAttestationSettings {
249 pub refresh_tpm_seeds: bool,
251}
252
253struct DerivedKeyResult {
255 derived_keys: Option<Keys>,
257 key_protector_settings: KeyProtectorSettings,
259 gsp_extended_status_flags: GspExtendedStatusFlags,
261}
262
263pub struct PlatformAttestationData {
265 pub host_attestation_settings: HostAttestationSettings,
267 pub agent_data: Option<Vec<u8>>,
269 pub guest_secret_key: Option<Vec<u8>>,
271}
272
273#[derive(Debug, MeshPayload, Copy, Clone, PartialEq, Eq)]
276pub enum AttestationType {
277 Snp,
279 Tdx,
281 Vbs,
283 Cca,
285 Host,
287}
288
289async fn try_unlock_vmgs(
294 get: &GuestEmulationTransportClient,
295 bios_guid: Guid,
296 attestation_vm_config: &AttestationVmConfig,
297 vmgs: &mut Vmgs,
298 tee_call: Option<&dyn TeeCall>,
299 guest_state_encryption_policy: GuestStateEncryptionPolicy,
300 strict_encryption_policy: bool,
301 agent_data: &mut [u8; AGENT_DATA_MAX_SIZE],
302 key_protector_by_id: &mut KeyProtectorById,
303) -> Result<bool, (AttestationErrorInner, bool)> {
304 let skr_response = if let Some(tee_call) = tee_call {
305 tracing::info!(CVM_ALLOWED, "Retrieving key-encryption key");
306
307 secure_key_release::request_vmgs_encryption_keys(
309 get,
310 tee_call,
311 vmgs,
312 attestation_vm_config,
313 agent_data,
314 )
315 .await
316 } else {
317 tracing::info!(CVM_ALLOWED, "Key-encryption key retrieval not required");
318
319 Ok(VmgsEncryptionKeys::default())
321 };
322
323 let retry = match &skr_response {
324 Ok(_) => false,
325 Err((_, r)) => *r,
326 };
327
328 let skip_hw_unsealing = matches!(
329 &skr_response,
330 Err((
331 secure_key_release::RequestVmgsEncryptionKeysError::ParseIgvmAttestKeyReleaseResponse(
332 igvm_attest::key_release::KeyReleaseError::ParseHeader(
333 igvm_attest::Error::Attestation {
334 skip_hw_unsealing_signal: true,
335 ..
336 },
337 ),
338 ),
339 _,
340 ))
341 );
342
343 let VmgsEncryptionKeys {
344 ingress_rsa_kek,
345 wrapped_des_key,
346 tcb_version,
347 } = match skr_response {
348 Ok(k) => {
349 tracing::info!(CVM_ALLOWED, "Successfully retrieved key-encryption key");
350 k
351 }
352 Err((e, _)) => {
353 tracing::error!(
355 CVM_ALLOWED,
356 error = &e as &dyn std::error::Error,
357 "Failed to retrieve key-encryption key"
358 );
359
360 VmgsEncryptionKeys::default()
361 }
362 };
363
364 let dek_minimal_size = if wrapped_des_key.is_some() {
366 key_protector::AES_WRAPPED_AES_KEY_LENGTH
367 } else {
368 key_protector::RSA_WRAPPED_AES_KEY_LENGTH
369 };
370
371 tracing::info!(
373 CVM_ALLOWED,
374 dek_minimal_size = dek_minimal_size,
375 "Reading key protector from VMGS"
376 );
377 let mut key_protector = vmgs::read_key_protector(vmgs, dek_minimal_size)
378 .await
379 .map_err(|e| (AttestationErrorInner::ReadKeyProtector(e), false))?;
380
381 let start_time = std::time::SystemTime::now();
382 let vmgs_encrypted = vmgs.encrypted();
383 tracing::info!(
384 ?tcb_version,
385 vmgs_encrypted,
386 op_type = ?LogOpType::BeginDecryptVmgs,
387 "Deriving keys"
388 );
389
390 let derived_keys_result = get_derived_keys(
391 get,
392 tee_call,
393 vmgs,
394 &mut key_protector,
395 key_protector_by_id,
396 bios_guid,
397 attestation_vm_config,
398 vmgs_encrypted,
399 ingress_rsa_kek.as_ref(),
400 wrapped_des_key.as_deref(),
401 tcb_version,
402 guest_state_encryption_policy,
403 strict_encryption_policy,
404 skip_hw_unsealing,
405 )
406 .await
407 .map_err(|e| {
408 tracing::error!(
409 CVM_ALLOWED,
410 op_type = ?LogOpType::DecryptVmgs,
411 success = false,
412 err = &e as &dyn std::error::Error,
413 latency = std::time::SystemTime::now()
414 .duration_since(start_time)
415 .map_or(0, |d| d.as_millis()),
416 "Failed to derive keys"
417 );
418 (AttestationErrorInner::GetDerivedKeys(e), retry)
419 })?;
420
421 tracing::info!("Unlocking VMGS");
423 if let Err(e) = unlock_vmgs_data_store(
424 vmgs,
425 vmgs_encrypted,
426 &mut key_protector,
427 key_protector_by_id,
428 derived_keys_result.derived_keys,
429 derived_keys_result.key_protector_settings,
430 bios_guid,
431 )
432 .await
433 {
434 tracing::error!(
435 CVM_ALLOWED,
436 op_type = ?LogOpType::DecryptVmgs,
437 success = false,
438 err = &e as &dyn std::error::Error,
439 latency = std::time::SystemTime::now()
440 .duration_since(start_time)
441 .map_or(0, |d| d.as_millis()),
442 "Failed to unlock datastore"
443 );
444 get.event_log_fatal(guest_emulation_transport::api::EventLogId::ATTESTATION_FAILED)
445 .await;
446
447 Err((AttestationErrorInner::UnlockVmgsDataStore(e), retry))?;
448 }
449
450 tracing::info!(
451 CVM_ALLOWED,
452 op_type = ?LogOpType::DecryptVmgs,
453 success = true,
454 decrypt_gsp_type = ?derived_keys_result
455 .key_protector_settings
456 .decrypt_gsp_type,
457 encrypt_gsp_type = ?derived_keys_result
458 .key_protector_settings
459 .encrypt_gsp_type,
460 latency = std::time::SystemTime::now().duration_since(start_time).map_or(0, |d| d.as_millis()),
461 "Unlocked datastore"
462 );
463
464 Ok(derived_keys_result
465 .gsp_extended_status_flags
466 .state_refresh_request())
467}
468
469pub async fn initialize_platform_security(
475 get: &GuestEmulationTransportClient,
476 bios_guid: Guid,
477 attestation_vm_config: &AttestationVmConfig,
478 vmgs: &mut Vmgs,
479 tee_call: Option<&dyn TeeCall>,
480 suppress_attestation: bool,
481 driver: LocalDriver,
482 guest_state_encryption_policy: GuestStateEncryptionPolicy,
483 strict_encryption_policy: bool,
484) -> Result<PlatformAttestationData, Error> {
485 const MAXIMUM_RETRY_COUNT: usize = 10;
486 const NO_RETRY_COUNT: usize = 1;
487
488 tracing::info!(CVM_ALLOWED,
489 tee_type=?tee_call.map(|tee| tee.tee_type()),
490 secure_boot=attestation_vm_config.secure_boot,
491 tpm_enabled=attestation_vm_config.tpm_enabled,
492 tpm_persisted=attestation_vm_config.tpm_persisted,
493 "Reading security profile");
494
495 let SecurityProfile { mut agent_data } = vmgs::read_security_profile(vmgs)
499 .await
500 .map_err(AttestationErrorInner::ReadSecurityProfile)?;
501
502 if suppress_attestation {
505 tracing::info!(CVM_ALLOWED, "Suppressing attestation");
506
507 return Ok(PlatformAttestationData {
508 host_attestation_settings: HostAttestationSettings {
509 refresh_tpm_seeds: false,
510 },
511 agent_data: Some(agent_data.to_vec()),
512 guest_secret_key: None,
513 });
514 }
515
516 tracing::info!(CVM_ALLOWED, "Reading VM ID from VMGS");
518 let mut key_protector_by_id = match vmgs::read_key_protector_by_id(vmgs).await {
519 Ok(key_protector_by_id) => KeyProtectorById {
520 inner: key_protector_by_id,
521 found_id: true,
522 },
523 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => KeyProtectorById {
524 inner: openhcl_attestation_protocol::vmgs::KeyProtectorById::new_zeroed(),
525 found_id: false,
526 },
527 Err(e) => { Err(AttestationErrorInner::ReadKeyProtectorById(e)) }?,
528 };
529
530 let vm_id_changed = if key_protector_by_id.found_id {
532 let changed = key_protector_by_id.inner.id_guid != bios_guid;
533 if changed {
534 tracing::info!("VM Id has changed since last boot");
535 };
536 changed
537 } else {
538 false
541 };
542
543 let vmgs_encrypted: bool = vmgs.encrypted();
547 let max_retry = if vmgs_encrypted {
548 MAXIMUM_RETRY_COUNT
549 } else {
550 NO_RETRY_COUNT
551 };
552
553 let mut timer = pal_async::timer::PolledTimer::new(&driver);
554 let mut i = 0;
555
556 let state_refresh_request_from_gsp = loop {
557 tracing::info!(CVM_ALLOWED, attempt = i, "attempt to unlock VMGS file");
558
559 let response = try_unlock_vmgs(
560 get,
561 bios_guid,
562 attestation_vm_config,
563 vmgs,
564 tee_call,
565 guest_state_encryption_policy,
566 strict_encryption_policy,
567 &mut agent_data,
568 &mut key_protector_by_id,
569 )
570 .await;
571
572 match response {
573 Ok(b) => break b,
574 Err((e, false)) => Err(e)?,
575 Err((e, true)) => {
576 if i >= max_retry - 1 {
577 Err(e)?
578 }
579 }
580 }
581
582 timer.sleep(std::time::Duration::new(1, 0)).await;
584 i += 1;
585 };
586
587 let host_attestation_settings = HostAttestationSettings {
588 refresh_tpm_seeds: { state_refresh_request_from_gsp | vm_id_changed },
589 };
590
591 tracing::info!(
592 CVM_ALLOWED,
593 state_refresh_request_from_gsp = state_refresh_request_from_gsp,
594 vm_id_changed = vm_id_changed,
595 "determine if refreshing tpm seeds is needed"
596 );
597
598 let guest_secret_key = match vmgs::read_guest_secret_key(vmgs).await {
600 Ok(data) => Some(data.guest_secret_key.to_vec()),
601 Err(vmgs::ReadFromVmgsError::EntryNotFound(_)) => None,
602 Err(e) => return Err(AttestationErrorInner::ReadGuestSecretKey(e).into()),
603 };
604
605 Ok(PlatformAttestationData {
606 host_attestation_settings,
607 agent_data: Some(agent_data.to_vec()),
608 guest_secret_key,
609 })
610}
611
612async fn unlock_vmgs_data_store(
619 vmgs: &mut Vmgs,
620 vmgs_encrypted: bool,
621 key_protector: &mut KeyProtector,
622 key_protector_by_id: &mut KeyProtectorById,
623 derived_keys: Option<Keys>,
624 key_protector_settings: KeyProtectorSettings,
625 bios_guid: Guid,
626) -> Result<(), UnlockVmgsDataStoreError> {
627 let mut new_key = false; let Some(Keys {
630 ingress: new_ingress_key,
631 decrypt_egress: old_egress_key,
632 encrypt_egress: new_egress_key,
633 }) = derived_keys
634 else {
635 tracing::info!(
636 CVM_ALLOWED,
637 "Encryption disabled, skipping unlock vmgs data store"
638 );
639 return Ok(());
640 };
641
642 if !constant_time_eq::constant_time_eq_32(&new_ingress_key, &new_egress_key) {
643 tracing::trace!(CVM_ALLOWED, "EgressKey is different than IngressKey");
644 new_key = true;
645 }
646
647 let mut provision = false;
649 if vmgs_encrypted {
650 tracing::info!(CVM_ALLOWED, "Decrypting vmgs file...");
651 if let Err(e) = vmgs.unlock_with_encryption_key(&new_ingress_key).await {
652 if let Some(key) = old_egress_key {
653 tracing::info!(CVM_ALLOWED, "Old EgressKey found");
656 vmgs.unlock_with_encryption_key(&key)
657 .await
658 .map_err(UnlockVmgsDataStoreError::VmgsUnlockUsingExistingEgressKey)?;
659 } else {
660 Err(UnlockVmgsDataStoreError::VmgsUnlockUsingExistingIngressKey(
661 e,
662 ))?
663 }
664 }
665 } else {
666 tracing::info!(
668 CVM_ALLOWED,
669 "vmgs data store is not encrypted, provisioning."
670 );
671 provision = true;
672 }
673
674 tracing::info!(
675 CVM_ALLOWED,
676 should_write_kp = key_protector_settings.should_write_kp,
677 use_gsp_by_id = key_protector_settings.use_gsp_by_id,
678 use_hardware_unlock = key_protector_settings.use_hardware_unlock,
679 "key protector settings"
680 );
681
682 if key_protector_settings.should_write_kp {
683 vmgs::write_key_protector(key_protector, vmgs)
685 .await
686 .map_err(UnlockVmgsDataStoreError::WriteKeyProtector)?;
687
688 if key_protector_settings.use_gsp_by_id {
689 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
690 .await
691 .map_err(UnlockVmgsDataStoreError::WriteKeyProtectorById)?;
692 }
693 }
694
695 if provision || new_key {
696 vmgs.update_encryption_key(&new_egress_key, EncryptionAlgorithm::AES_GCM)
700 .await
701 .map_err(UnlockVmgsDataStoreError::UpdateVmgsEncryptionKey)?;
702 }
703
704 persist_all_key_protectors(
706 vmgs,
707 key_protector,
708 key_protector_by_id,
709 bios_guid,
710 key_protector_settings,
711 )
712 .await
713 .map_err(UnlockVmgsDataStoreError::PersistAllKeyProtectors)
714}
715
716async fn get_derived_keys(
733 get: &GuestEmulationTransportClient,
734 tee_call: Option<&dyn TeeCall>,
735 vmgs: &mut Vmgs,
736 key_protector: &mut KeyProtector,
737 key_protector_by_id: &mut KeyProtectorById,
738 bios_guid: Guid,
739 attestation_vm_config: &AttestationVmConfig,
740 is_encrypted: bool,
741 ingress_rsa_kek: Option<&RsaKeyPair>,
742 wrapped_des_key: Option<&[u8]>,
743 tcb_version: Option<u64>,
744 guest_state_encryption_policy: GuestStateEncryptionPolicy,
745 strict_encryption_policy: bool,
746 skip_hw_unsealing: bool,
747) -> Result<DerivedKeyResult, GetDerivedKeysError> {
748 tracing::info!(
749 CVM_ALLOWED,
750 ?guest_state_encryption_policy,
751 strict_encryption_policy,
752 "encryption policy"
753 );
754
755 if matches!(
757 guest_state_encryption_policy,
758 GuestStateEncryptionPolicy::HardwareSealing
759 ) {
760 todo!("hardware sealing")
761 }
762
763 let mut key_protector_settings = KeyProtectorSettings {
764 should_write_kp: true,
765 use_gsp_by_id: false,
766 use_hardware_unlock: false,
767 decrypt_gsp_type: GspType::None,
768 encrypt_gsp_type: GspType::None,
769 };
770
771 let mut derived_keys = Keys {
772 ingress: [0u8; AES_GCM_KEY_LENGTH],
773 decrypt_egress: None,
774 encrypt_egress: [0u8; AES_GCM_KEY_LENGTH],
775 };
776
777 let ingress_idx = (key_protector.active_kp % 2) as usize;
779 let egress_idx = if ingress_idx == 0 { 1 } else { 0 } as usize;
780
781 let found_dek = !key_protector.dek[ingress_idx]
782 .dek_buffer
783 .iter()
784 .all(|&x| x == 0);
785
786 let (ingress_key, mut decrypt_egress_key, encrypt_egress_key, no_kek) =
788 if let Some(ingress_kek) = ingress_rsa_kek {
789 let keys = match key_protector.unwrap_and_rotate_keys(
790 ingress_kek,
791 wrapped_des_key,
792 ingress_idx,
793 egress_idx,
794 ) {
795 Ok(keys) => keys,
796 Err(e)
797 if matches!(
798 e,
799 GetKeysFromKeyProtectorError::DesKeyRsaUnwrap(_)
800 | GetKeysFromKeyProtectorError::IngressDekRsaUnwrap(_)
801 ) =>
802 {
803 get.event_log_fatal(
804 guest_emulation_transport::api::EventLogId::DEK_DECRYPTION_FAILED,
805 )
806 .await;
807
808 return Err(GetDerivedKeysError::GetKeysFromKeyProtector(e));
809 }
810 Err(e) => return Err(GetDerivedKeysError::GetKeysFromKeyProtector(e)),
811 };
812 (
813 keys.ingress,
814 keys.decrypt_egress,
815 keys.encrypt_egress,
816 false,
817 )
818 } else {
819 (
820 [0u8; AES_GCM_KEY_LENGTH],
821 None,
822 [0u8; AES_GCM_KEY_LENGTH],
823 true,
824 )
825 };
826
827 let existing_unencrypted = !vmgs.encrypted() && !vmgs.was_provisioned_this_boot();
829 let is_gsp_by_id = key_protector_by_id.found_id && key_protector_by_id.inner.ported != 1;
830 let is_gsp = key_protector.gsp[ingress_idx].gsp_length != 0;
831 tracing::info!(
832 CVM_ALLOWED,
833 is_encrypted,
834 is_gsp_by_id,
835 is_gsp,
836 found_dek,
837 "initial vmgs encryption state"
838 );
839 let mut requires_gsp_by_id = is_gsp_by_id;
840
841 let (gsp_response, gsp_available, no_gsp, requires_gsp) = {
843 tracing::info!(CVM_ALLOWED, "attempting GSP");
844
845 let response = get_gsp_data(get, key_protector).await;
846
847 tracing::info!(
848 CVM_ALLOWED,
849 request_data_length_in_vmgs = key_protector.gsp[ingress_idx].gsp_length,
850 no_rpc_server = response.extended_status_flags.no_rpc_server(),
851 requires_rpc_server = response.extended_status_flags.requires_rpc_server(),
852 encrypted_gsp_length = response.encrypted_gsp.length,
853 "GSP response"
854 );
855
856 let no_gsp_available =
857 response.extended_status_flags.no_rpc_server() || response.encrypted_gsp.length == 0;
858
859 let no_gsp = no_gsp_available
860 || (matches!(
864 guest_state_encryption_policy,
865 GuestStateEncryptionPolicy::Auto
866 ) && (is_gsp_by_id || existing_unencrypted))
867 || (matches!(
869 guest_state_encryption_policy,
870 GuestStateEncryptionPolicy::GspById | GuestStateEncryptionPolicy::None
871 ) && (!is_gsp || strict_encryption_policy));
872
873 let requires_gsp = is_gsp
874 || response.extended_status_flags.requires_rpc_server()
875 || (matches!(
876 guest_state_encryption_policy,
877 GuestStateEncryptionPolicy::GspKey
878 ) && strict_encryption_policy);
879
880 if is_encrypted && !requires_gsp_by_id && !requires_gsp && !found_dek {
883 requires_gsp_by_id = true;
884 }
885
886 (response, !no_gsp_available, no_gsp, requires_gsp)
887 };
888
889 let (gsp_response_by_id, gsp_by_id_available, no_gsp_by_id) = if no_gsp || requires_gsp_by_id {
892 tracing::info!(CVM_ALLOWED, "attempting GSP By Id");
893
894 let gsp_response_by_id = get
895 .guest_state_protection_data_by_id()
896 .await
897 .map_err(GetDerivedKeysError::FetchGuestStateProtectionById)?;
898
899 let no_gsp_by_id_available = gsp_response_by_id.extended_status_flags.no_registry_file();
900
901 let no_gsp_by_id = no_gsp_by_id_available
902 || (matches!(
905 guest_state_encryption_policy,
906 GuestStateEncryptionPolicy::Auto
907 ) && existing_unencrypted)
908 || (matches!(
910 guest_state_encryption_policy,
911 GuestStateEncryptionPolicy::None
912 ) && (!requires_gsp_by_id || strict_encryption_policy));
913
914 if no_gsp_by_id && requires_gsp_by_id {
915 Err(GetDerivedKeysError::GspByIdRequiredButNotFound)?
916 }
917
918 (
919 gsp_response_by_id,
920 Some(!no_gsp_by_id_available),
921 no_gsp_by_id,
922 )
923 } else {
924 (GuestStateProtectionById::new_zeroed(), None, true)
925 };
926
927 if (no_kek && found_dek) || (no_gsp && requires_gsp) || (no_gsp_by_id && requires_gsp_by_id) {
929 let (hardware_key_protector, hardware_derived_keys) = if let Some(tee_call) = tee_call {
931 let hardware_key_protector = match vmgs::read_hardware_key_protector(vmgs).await {
932 Ok(hardware_key_protector) => Some(hardware_key_protector),
933 Err(e) => {
934 tracing::warn!(
936 CVM_ALLOWED,
937 error = &e as &dyn std::error::Error,
938 "failed to read HW_KEY_PROTECTOR from Vmgs"
939 );
940 None
941 }
942 };
943
944 let hardware_derived_keys = tee_call.supports_get_derived_key().and_then(|tee_call| {
945 if let Some(hardware_key_protector) = &hardware_key_protector {
946 match HardwareDerivedKeys::derive_key(
947 tee_call,
948 attestation_vm_config,
949 hardware_key_protector.header.tcb_version,
950 ) {
951 Ok(hardware_derived_key) => Some(hardware_derived_key),
952 Err(e) => {
953 tracing::warn!(
955 CVM_ALLOWED,
956 error = &e as &dyn std::error::Error,
957 "failed to derive hardware keys using HW_KEY_PROTECTOR",
958 );
959 None
960 }
961 }
962 } else {
963 None
964 }
965 });
966
967 if skip_hw_unsealing {
973 if hardware_key_protector.is_some() && hardware_derived_keys.is_some() {
974 tracing::warn!(
975 CVM_ALLOWED,
976 "Skipping hardware unsealing of VMGS DEK as signaled by IGVM agent"
977 );
978 get.event_log_fatal(
979 guest_emulation_transport::api::EventLogId::DEK_HARDWARE_UNSEALING_SKIPPED,
980 )
981 .await;
982
983 (None, None)
984 } else {
985 tracing::info!(
986 CVM_ALLOWED,
987 hardware_key_protector = hardware_key_protector.is_some(),
988 hardware_derived_keys = hardware_derived_keys.is_some(),
989 "skip_hw_unsealing signaled but hardware key data not available, \
990 falling through to scheme-specific error"
991 );
992 (None, None)
993 }
994 } else {
995 (hardware_key_protector, hardware_derived_keys)
996 }
997 } else {
998 (None, None)
999 };
1000
1001 if let (Some(hardware_key_protector), Some(hardware_derived_keys)) =
1002 (hardware_key_protector, hardware_derived_keys)
1003 {
1004 derived_keys.ingress = hardware_key_protector
1005 .unseal_key(&hardware_derived_keys)
1006 .map_err(GetDerivedKeysError::UnsealIngressKeyUsingHardwareDerivedKeys)?;
1007 derived_keys.decrypt_egress = None;
1008 derived_keys.encrypt_egress = derived_keys.ingress;
1009
1010 key_protector_settings.should_write_kp = false;
1011 key_protector_settings.use_hardware_unlock = true;
1012
1013 tracing::warn!(
1014 CVM_ALLOWED,
1015 "Using hardware-derived key to recover VMGS DEK"
1016 );
1017
1018 return Ok(DerivedKeyResult {
1019 derived_keys: Some(derived_keys),
1020 key_protector_settings,
1021 gsp_extended_status_flags: gsp_response.extended_status_flags,
1022 });
1023 } else {
1024 if no_kek && found_dek {
1025 return Err(GetDerivedKeysError::GetIngressKeyFromKpFailed);
1026 } else if no_gsp && requires_gsp {
1027 return Err(GetDerivedKeysError::GetIngressKeyFromKGspFailed);
1028 } else {
1029 return Err(GetDerivedKeysError::GetIngressKeyFromKGspByIdFailed);
1031 }
1032 }
1033 }
1034
1035 tracing::info!(
1036 CVM_ALLOWED,
1037 kek = !no_kek,
1038 gsp_available,
1039 gsp = !no_gsp,
1040 gsp_by_id_available = ?gsp_by_id_available,
1041 gsp_by_id = !no_gsp_by_id,
1042 "Encryption sources"
1043 );
1044
1045 if no_kek && no_gsp && no_gsp_by_id {
1047 if is_encrypted {
1048 Err(GetDerivedKeysError::DisableVmgsEncryptionFailed)?
1049 }
1050 match guest_state_encryption_policy {
1051 GuestStateEncryptionPolicy::GspById
1053 | GuestStateEncryptionPolicy::GspKey
1054 | GuestStateEncryptionPolicy::HardwareSealing => {
1055 Err(GetDerivedKeysError::EncryptionRequiredButNotFound)?
1056 }
1057 GuestStateEncryptionPolicy::Auto | GuestStateEncryptionPolicy::None => {
1058 tracing::info!(CVM_ALLOWED, "No VMGS encryption used.");
1059
1060 return Ok(DerivedKeyResult {
1061 derived_keys: None,
1062 key_protector_settings,
1063 gsp_extended_status_flags: gsp_response.extended_status_flags,
1064 });
1065 }
1066 }
1067 }
1068
1069 let hardware_derived_keys = tee_call
1071 .and_then(|tee_call| tee_call.supports_get_derived_key())
1072 .and_then(|tee_call| {
1073 if let Some(tcb_version) = tcb_version {
1074 match HardwareDerivedKeys::derive_key(tee_call, attestation_vm_config, tcb_version)
1075 {
1076 Ok(keys) => Some(keys),
1077 Err(e) => {
1078 tracing::warn!(
1080 CVM_ALLOWED,
1081 error = &e as &dyn std::error::Error,
1082 "failed to derive hardware keys"
1083 );
1084 None
1085 }
1086 }
1087 } else {
1088 None
1089 }
1090 });
1091
1092 if no_gsp && no_gsp_by_id {
1094 tracing::info!(CVM_ALLOWED, "No GSP used with SKR");
1095
1096 derived_keys.ingress = ingress_key;
1097 derived_keys.decrypt_egress = decrypt_egress_key;
1098 derived_keys.encrypt_egress = encrypt_egress_key;
1099
1100 if let Some(hardware_derived_keys) = hardware_derived_keys {
1101 let hardware_key_protector = HardwareKeyProtector::seal_key(
1102 &hardware_derived_keys,
1103 &derived_keys.encrypt_egress,
1104 )
1105 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
1106 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
1107 .await
1108 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
1109
1110 tracing::info!(CVM_ALLOWED, "hardware key protector updated (no GSP used)");
1111 }
1112
1113 return Ok(DerivedKeyResult {
1114 derived_keys: Some(derived_keys),
1115 key_protector_settings,
1116 gsp_extended_status_flags: gsp_response.extended_status_flags,
1117 });
1118 }
1119
1120 if (no_kek && no_gsp) || requires_gsp_by_id {
1123 let derived_keys_by_id =
1124 get_derived_keys_by_id(key_protector_by_id, bios_guid, gsp_response_by_id)
1125 .map_err(GetDerivedKeysError::GetDerivedKeyById)?;
1126
1127 if no_kek && no_gsp {
1128 if matches!(
1129 guest_state_encryption_policy,
1130 GuestStateEncryptionPolicy::GspById | GuestStateEncryptionPolicy::Auto
1131 ) {
1132 tracing::info!(CVM_ALLOWED, "Using GspById");
1133 } else {
1134 tracing::warn!(CVM_ALLOWED, "Allowing GspById");
1144 };
1145
1146 key_protector_settings.should_write_kp = false;
1148 key_protector_settings.use_gsp_by_id = true;
1149 key_protector_settings.decrypt_gsp_type = GspType::GspById;
1150 key_protector_settings.encrypt_gsp_type = GspType::GspById;
1151
1152 return Ok(DerivedKeyResult {
1153 derived_keys: Some(derived_keys_by_id),
1154 key_protector_settings,
1155 gsp_extended_status_flags: gsp_response.extended_status_flags,
1156 });
1157 }
1158
1159 derived_keys.ingress = derived_keys_by_id.ingress;
1160
1161 tracing::info!(
1162 CVM_ALLOWED,
1163 op_type = ?LogOpType::ConvertEncryptionType,
1164 "Converting GSP method."
1165 );
1166 }
1167
1168 let egress_seed;
1169 let mut ingress_seed = None;
1170
1171 if requires_gsp_by_id || no_gsp {
1177 if found_dek {
1180 if requires_gsp_by_id {
1181 ingress_seed = Some(
1182 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize]
1183 .to_vec(),
1184 );
1185 key_protector_settings.decrypt_gsp_type = GspType::GspById;
1186 } else {
1187 derived_keys.ingress = ingress_key;
1188 }
1189 } else {
1190 key_protector_settings.decrypt_gsp_type = GspType::GspById;
1191 }
1192
1193 if no_gsp {
1195 egress_seed =
1196 gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize].to_vec();
1197 key_protector_settings.use_gsp_by_id = true;
1198 key_protector_settings.encrypt_gsp_type = GspType::GspById;
1199 } else {
1200 egress_seed =
1201 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
1202 key_protector_settings.encrypt_gsp_type = GspType::GspKey;
1203 }
1204 } else {
1205 if gsp_response.decrypted_gsp[ingress_idx].length == 0
1208 && gsp_response.decrypted_gsp[egress_idx].length == 0
1209 {
1210 tracing::info!(CVM_ALLOWED, "Applying GSP.");
1211
1212 egress_seed =
1215 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
1216
1217 if !no_kek {
1220 derived_keys.ingress = ingress_key;
1221 }
1222
1223 key_protector_settings.encrypt_gsp_type = GspType::GspKey;
1224 } else {
1225 tracing::info!(CVM_ALLOWED, "Using existing GSP.");
1226
1227 ingress_seed = Some(
1228 gsp_response.decrypted_gsp[ingress_idx].buffer
1229 [..gsp_response.decrypted_gsp[ingress_idx].length as usize]
1230 .to_vec(),
1231 );
1232
1233 if gsp_response.decrypted_gsp[egress_idx].length == 0 {
1234 egress_seed =
1236 gsp_response.new_gsp.buffer[..gsp_response.new_gsp.length as usize].to_vec();
1237 } else {
1238 egress_seed = gsp_response.decrypted_gsp[egress_idx].buffer
1243 [..gsp_response.decrypted_gsp[egress_idx].length as usize]
1244 .to_vec();
1245 key_protector_settings.should_write_kp = false;
1246 decrypt_egress_key = Some(encrypt_egress_key);
1247 }
1248
1249 key_protector_settings.decrypt_gsp_type = GspType::GspKey;
1250 key_protector_settings.encrypt_gsp_type = GspType::GspKey;
1251 }
1252 }
1253
1254 if let Some(seed) = ingress_seed {
1256 derived_keys.ingress = derive_key(&ingress_key, &seed, VMGS_KEY_DERIVE_LABEL)
1257 .map_err(GetDerivedKeysError::DeriveIngressKey)?;
1258 }
1259
1260 derived_keys.decrypt_egress = decrypt_egress_key
1262 .map(|key| derive_key(&key, &egress_seed, VMGS_KEY_DERIVE_LABEL))
1263 .transpose()
1264 .map_err(GetDerivedKeysError::DeriveEgressKey)?;
1265
1266 derived_keys.encrypt_egress =
1267 derive_key(&encrypt_egress_key, &egress_seed, VMGS_KEY_DERIVE_LABEL)
1268 .map_err(GetDerivedKeysError::DeriveEgressKey)?;
1269
1270 if key_protector_settings.should_write_kp {
1271 key_protector.gsp[egress_idx]
1273 .gsp_buffer
1274 .copy_from_slice(&gsp_response.encrypted_gsp.buffer);
1275 key_protector.gsp[egress_idx].gsp_length = gsp_response.encrypted_gsp.length;
1276
1277 if let Some(hardware_derived_keys) = hardware_derived_keys {
1278 let hardware_key_protector = HardwareKeyProtector::seal_key(
1279 &hardware_derived_keys,
1280 &derived_keys.encrypt_egress,
1281 )
1282 .map_err(GetDerivedKeysError::SealEgressKeyUsingHardwareDerivedKeys)?;
1283
1284 vmgs::write_hardware_key_protector(&hardware_key_protector, vmgs)
1285 .await
1286 .map_err(GetDerivedKeysError::VmgsWriteHardwareKeyProtector)?;
1287
1288 tracing::info!(CVM_ALLOWED, "hardware key protector updated");
1289 }
1290 }
1291
1292 if matches!(
1293 guest_state_encryption_policy,
1294 GuestStateEncryptionPolicy::GspKey | GuestStateEncryptionPolicy::Auto
1295 ) {
1296 tracing::info!(CVM_ALLOWED, "Using Gsp");
1297 } else {
1298 tracing::warn!(CVM_ALLOWED, "Allowing Gsp");
1305 }
1306
1307 Ok(DerivedKeyResult {
1308 derived_keys: Some(derived_keys),
1309 key_protector_settings,
1310 gsp_extended_status_flags: gsp_response.extended_status_flags,
1311 })
1312}
1313
1314fn get_derived_keys_by_id(
1316 key_protector_by_id: &mut KeyProtectorById,
1317 bios_guid: Guid,
1318 gsp_response_by_id: GuestStateProtectionById,
1319) -> Result<Keys, GetDerivedKeysByIdError> {
1320 let new_egress_key = derive_key(
1327 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
1328 bios_guid.as_bytes(),
1329 VMGS_KEY_DERIVE_LABEL,
1330 )
1331 .map_err(GetDerivedKeysByIdError::DeriveEgressKeyUsingCurrentVmId)?;
1332
1333 if new_egress_key.len() != AES_GCM_KEY_LENGTH {
1334 Err(GetDerivedKeysByIdError::InvalidDerivedEgressKeySize {
1335 key_size: new_egress_key.len(),
1336 expected_size: AES_GCM_KEY_LENGTH,
1337 })?
1338 }
1339
1340 let new_ingress_key = if key_protector_by_id.inner.id_guid != Guid::default() {
1343 derive_key(
1345 &gsp_response_by_id.seed.buffer[..gsp_response_by_id.seed.length as usize],
1346 key_protector_by_id.inner.id_guid.as_bytes(),
1347 VMGS_KEY_DERIVE_LABEL,
1348 )
1349 .map_err(GetDerivedKeysByIdError::DeriveIngressKeyUsingKeyProtectorId)?
1350 } else {
1351 new_egress_key
1353 };
1354
1355 if new_ingress_key.len() != AES_GCM_KEY_LENGTH {
1356 Err(GetDerivedKeysByIdError::InvalidDerivedIngressKeySize {
1357 key_size: new_ingress_key.len(),
1358 expected_size: AES_GCM_KEY_LENGTH,
1359 })?
1360 }
1361
1362 Ok(Keys {
1363 ingress: new_ingress_key,
1364 decrypt_egress: None,
1365 encrypt_egress: new_egress_key,
1366 })
1367}
1368
1369async fn get_gsp_data(
1371 get: &GuestEmulationTransportClient,
1372 key_protector: &mut KeyProtector,
1373) -> GuestStateProtection {
1374 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1375 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1376
1377 const_assert_eq!(guest_emulation_transport::api::NUMBER_GSP, NUMBER_KP as u32);
1378 const_assert_eq!(
1379 guest_emulation_transport::api::GSP_CIPHERTEXT_MAX,
1380 GSP_BUFFER_SIZE as u32
1381 );
1382
1383 let mut encrypted_gsp =
1384 [guest_emulation_transport::api::GspCiphertextContent::new_zeroed(); NUMBER_KP];
1385
1386 for (i, gsp) in encrypted_gsp.iter_mut().enumerate().take(NUMBER_KP) {
1387 if key_protector.gsp[i].gsp_length == 0 {
1388 continue;
1389 }
1390
1391 gsp.buffer[..key_protector.gsp[i].gsp_length as usize].copy_from_slice(
1392 &key_protector.gsp[i].gsp_buffer[..key_protector.gsp[i].gsp_length as usize],
1393 );
1394
1395 gsp.length = key_protector.gsp[i].gsp_length;
1396 }
1397
1398 get.guest_state_protection_data(encrypted_gsp, GspExtendedStatusFlags::new())
1399 .await
1400}
1401
1402async fn persist_all_key_protectors(
1404 vmgs: &mut Vmgs,
1405 key_protector: &mut KeyProtector,
1406 key_protector_by_id: &mut KeyProtectorById,
1407 bios_guid: Guid,
1408 key_protector_settings: KeyProtectorSettings,
1409) -> Result<(), PersistAllKeyProtectorsError> {
1410 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1411
1412 if key_protector_settings.use_gsp_by_id && !key_protector_settings.should_write_kp {
1413 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, false, bios_guid)
1414 .await
1415 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1416 } else {
1417 if !key_protector_settings.use_hardware_unlock {
1419 key_protector.dek[key_protector.active_kp as usize % NUMBER_KP]
1421 .dek_buffer
1422 .fill(0);
1423 key_protector.gsp[key_protector.active_kp as usize % NUMBER_KP].gsp_length = 0;
1424 key_protector.active_kp += 1;
1425
1426 vmgs::write_key_protector(key_protector, vmgs)
1427 .await
1428 .map_err(PersistAllKeyProtectorsError::WriteKeyProtector)?;
1429 }
1430
1431 if !key_protector_settings.use_gsp_by_id
1433 && key_protector_by_id.found_id
1434 && key_protector_by_id.inner.ported == 0
1435 {
1436 key_protector_by_id.inner.ported = 1;
1437 vmgs::write_key_protector_by_id(&mut key_protector_by_id.inner, vmgs, true, bios_guid)
1438 .await
1439 .map_err(PersistAllKeyProtectorsError::WriteKeyProtectorById)?;
1440 }
1441 }
1442
1443 Ok(())
1444}
1445
1446#[derive(Debug, Serialize, Deserialize)]
1447struct ProvenanceJwtBody {
1448 #[serde(rename = "VMGSID")]
1449 pub vmgsid: String,
1450}
1451
1452pub fn get_provenance_claims(prov_file: &[u8]) -> Result<VmgsProvisioner, Error> {
1454 let jwt = JwtHelper::<ProvenanceJwtBody>::from(prov_file)
1455 .map_err(ProvenanceError::DecodeProvenanceDoc)
1456 .map_err(AttestationErrorInner::Provenance)?;
1457 let valid = jwt
1458 .verify_signature()
1459 .map_err(ProvenanceError::VerifySignature)
1460 .map_err(AttestationErrorInner::Provenance)?;
1461
1462 if !valid {
1463 return Err(Error(AttestationErrorInner::Provenance(
1464 ProvenanceError::InvalidSignature,
1465 )));
1466 }
1467
1468 let cert_chain = jwt
1469 .cert_chain()
1470 .map_err(ProvenanceError::DecodeProvenanceDoc)
1471 .map_err(AttestationErrorInner::Provenance)?;
1472 let leaf = &cert_chain[0];
1473
1474 let sn = leaf
1475 .subject_common_name()
1476 .map_err(ProvenanceError::X509Error)
1477 .map_err(AttestationErrorInner::Provenance)?
1478 .ok_or(AttestationErrorInner::Provenance(
1479 ProvenanceError::MissingLeafCertSubjectName,
1480 ))?;
1481
1482 let root = cert_chain.last().ok_or(AttestationErrorInner::Provenance(
1483 ProvenanceError::InvalidRootCert,
1484 ))?;
1485 let digest = sha_256(
1486 &(root
1487 .to_der()
1488 .map_err(ProvenanceError::X509Error)
1489 .map_err(AttestationErrorInner::Provenance)?),
1490 );
1491 let signer = format!("did:x509:0:sha256:{}:subject:{}", hex::encode(digest), sn);
1492 let vmgsid = jwt.jwt.body.vmgsid;
1493
1494 Ok(VmgsProvisioner {
1495 id: Guid::parse(vmgsid.as_bytes())
1496 .map_err(ProvenanceError::ParseVmgsid)
1497 .map_err(AttestationErrorInner::Provenance)?,
1498 signer,
1499 })
1500}
1501
1502pub fn derive_vmgsid(seed_file: &[u8]) -> Result<Guid, Error> {
1504 let seed_file_str = str::from_utf8(seed_file)
1505 .map_err(ProvenanceError::InvalidVmgsidData)
1506 .map_err(AttestationErrorInner::Provenance)?;
1507
1508 let parts = seed_file_str
1513 .split(',')
1514 .map(|s| s.trim())
1515 .collect::<Vec<&str>>();
1516 if parts.len() < 3 {
1517 Err(AttestationErrorInner::Provenance(
1518 ProvenanceError::ParseVmgsidSeedData,
1519 ))?;
1520 }
1521
1522 let seed = hex::decode(parts[0])
1523 .map_err(ProvenanceError::DecodeVmgsidData)
1524 .map_err(AttestationErrorInner::Provenance)?;
1525 let label = hex::decode(parts[1])
1526 .map_err(ProvenanceError::DecodeVmgsidData)
1527 .map_err(AttestationErrorInner::Provenance)?;
1528 let context = hex::decode(parts[2])
1529 .map_err(ProvenanceError::DecodeVmgsidData)
1530 .map_err(AttestationErrorInner::Provenance)?;
1531
1532 let key = crypto::kbkdf::kbkdf_hmac_sha256(&seed, &context, &label, 32)
1533 .map_err(ProvenanceError::KdfError)
1534 .map_err(AttestationErrorInner::Provenance)?;
1535
1536 Ok(Guid::from_slice(&key[0..16].try_into().unwrap()))
1537}
1538
1539#[cfg(test)]
1541pub mod test_utils {
1542 use tee_call::GetAttestationReportResult;
1543 use tee_call::HW_DERIVED_KEY_LENGTH;
1544 use tee_call::REPORT_DATA_SIZE;
1545 use tee_call::TeeCall;
1546 use tee_call::TeeCallGetDerivedKey;
1547 use tee_call::TeeType;
1548
1549 pub struct MockTeeCall {
1551 pub tcb_version: u64,
1553 }
1554
1555 impl MockTeeCall {
1556 pub fn new(tcb_version: u64) -> Self {
1558 Self { tcb_version }
1559 }
1560 }
1561
1562 impl TeeCall for MockTeeCall {
1563 fn get_attestation_report(
1564 &self,
1565 report_data: &[u8; REPORT_DATA_SIZE],
1566 ) -> Result<GetAttestationReportResult, tee_call::Error> {
1567 let mut report =
1568 [0x6c; openhcl_attestation_protocol::igvm_attest::get::SNP_VM_REPORT_SIZE];
1569 report[..REPORT_DATA_SIZE].copy_from_slice(report_data);
1570
1571 Ok(GetAttestationReportResult {
1572 report: report.to_vec(),
1573 tcb_version: Some(self.tcb_version),
1574 })
1575 }
1576
1577 fn supports_get_derived_key(&self) -> Option<&dyn TeeCallGetDerivedKey> {
1578 Some(self)
1579 }
1580
1581 fn tee_type(&self) -> TeeType {
1582 TeeType::Snp
1584 }
1585 }
1586
1587 impl TeeCallGetDerivedKey for MockTeeCall {
1588 fn get_derived_key(&self, tcb_version: u64) -> Result<[u8; 32], tee_call::Error> {
1589 let mut key: [u8; HW_DERIVED_KEY_LENGTH] = [0xab; HW_DERIVED_KEY_LENGTH];
1591
1592 let tcb = tcb_version.to_le_bytes();
1594 for (i, b) in key.iter_mut().enumerate() {
1595 *b ^= tcb[i % tcb.len()];
1596 }
1597
1598 Ok(key)
1599 }
1600 }
1601
1602 pub struct MockTeeCallNoGetDerivedKey;
1604
1605 impl TeeCall for MockTeeCallNoGetDerivedKey {
1606 fn get_attestation_report(
1607 &self,
1608 report_data: &[u8; REPORT_DATA_SIZE],
1609 ) -> Result<GetAttestationReportResult, tee_call::Error> {
1610 let mut report =
1611 [0x6c; openhcl_attestation_protocol::igvm_attest::get::SNP_VM_REPORT_SIZE];
1612 report[..REPORT_DATA_SIZE].copy_from_slice(report_data);
1613
1614 Ok(GetAttestationReportResult {
1615 report: report.to_vec(),
1616 tcb_version: None,
1617 })
1618 }
1619
1620 fn supports_get_derived_key(&self) -> Option<&dyn TeeCallGetDerivedKey> {
1621 None
1622 }
1623
1624 fn tee_type(&self) -> TeeType {
1625 TeeType::Snp
1627 }
1628 }
1629}
1630
1631#[cfg(test)]
1632mod tests {
1633 use super::*;
1634 use crate::test_utils::MockTeeCallNoGetDerivedKey;
1635 use disk_backend::Disk;
1636 use disklayer_ram::ram_disk;
1637 use get_protocol::GSP_CLEARTEXT_MAX;
1638 use get_protocol::GspExtendedStatusFlags;
1639 use guest_emulation_device::IgvmAgentAction;
1640 use guest_emulation_device::IgvmAgentTestPlan;
1641 use guest_emulation_transport::test_utilities::TestGet;
1642 use key_protector::AES_WRAPPED_AES_KEY_LENGTH;
1643 use openhcl_attestation_protocol::igvm_attest::get::IgvmAttestRequestType;
1644 use openhcl_attestation_protocol::vmgs::DEK_BUFFER_SIZE;
1645 use openhcl_attestation_protocol::vmgs::DekKp;
1646 use openhcl_attestation_protocol::vmgs::GSP_BUFFER_SIZE;
1647 use openhcl_attestation_protocol::vmgs::GspKp;
1648 use openhcl_attestation_protocol::vmgs::NUMBER_KP;
1649 use pal_async::DefaultDriver;
1650 use pal_async::async_test;
1651 use pal_async::task::Spawn;
1652 use std::collections::VecDeque;
1653 use test_utils::MockTeeCall;
1654 use test_with_tracing::test;
1655 use vmgs_format::EncryptionAlgorithm;
1656 use vmgs_format::FileId;
1657
1658 const ONE_MEGA_BYTE: u64 = 1024 * 1024;
1659
1660 fn new_test_file() -> Disk {
1661 ram_disk(4 * ONE_MEGA_BYTE, false).unwrap()
1662 }
1663
1664 async fn new_formatted_vmgs() -> Vmgs {
1665 let disk = new_test_file();
1666
1667 let mut vmgs = Vmgs::format_new(disk, None).await.unwrap();
1668
1669 assert!(
1670 key_protector_is_empty(&mut vmgs).await,
1671 "Newly formatted VMGS should have an empty key protector"
1672 );
1673 assert!(
1674 key_protector_by_id_is_empty(&mut vmgs).await,
1675 "Newly formatted VMGS should have an empty key protector by id"
1676 );
1677
1678 vmgs
1679 }
1680
1681 async fn key_protector_is_empty(vmgs: &mut Vmgs) -> bool {
1682 let key_protector = vmgs::read_key_protector(vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1683 .await
1684 .unwrap();
1685
1686 key_protector.as_bytes().iter().all(|&b| b == 0)
1687 }
1688
1689 async fn key_protector_by_id_is_empty(vmgs: &mut Vmgs) -> bool {
1690 vmgs::read_key_protector_by_id(vmgs)
1691 .await
1692 .is_err_and(|err| {
1693 matches!(
1694 err,
1695 vmgs::ReadFromVmgsError::EntryNotFound(FileId::VM_UNIQUE_ID)
1696 )
1697 })
1698 }
1699
1700 async fn hardware_key_protector_is_empty(vmgs: &mut Vmgs) -> bool {
1701 vmgs::read_hardware_key_protector(vmgs)
1702 .await
1703 .is_err_and(|err| {
1704 matches!(
1705 err,
1706 vmgs::ReadFromVmgsError::EntryNotFound(FileId::HW_KEY_PROTECTOR)
1707 )
1708 })
1709 }
1710
1711 fn new_key_protector() -> KeyProtector {
1712 assert_eq!(NUMBER_KP, 2);
1714
1715 let ingress_dek = DekKp {
1716 dek_buffer: [1; DEK_BUFFER_SIZE],
1717 };
1718 let egress_dek = DekKp {
1719 dek_buffer: [2; DEK_BUFFER_SIZE],
1720 };
1721 let ingress_gsp = GspKp {
1722 gsp_length: GSP_BUFFER_SIZE as u32,
1723 gsp_buffer: [3; GSP_BUFFER_SIZE],
1724 };
1725 let egress_gsp = GspKp {
1726 gsp_length: GSP_BUFFER_SIZE as u32,
1727 gsp_buffer: [4; GSP_BUFFER_SIZE],
1728 };
1729 KeyProtector {
1730 dek: [ingress_dek, egress_dek],
1731 gsp: [ingress_gsp, egress_gsp],
1732 active_kp: 0,
1733 }
1734 }
1735
1736 fn new_key_protector_by_id(
1737 id_guid: Option<Guid>,
1738 ported: Option<u8>,
1739 found_id: bool,
1740 ) -> KeyProtectorById {
1741 let key_protector_by_id = openhcl_attestation_protocol::vmgs::KeyProtectorById {
1742 id_guid: id_guid.unwrap_or_else(Guid::new_random),
1743 ported: ported.unwrap_or(0),
1744 pad: [0; 3],
1745 };
1746
1747 KeyProtectorById {
1748 inner: key_protector_by_id,
1749 found_id,
1750 }
1751 }
1752
1753 async fn new_test_get(
1754 spawn: impl Spawn,
1755 enable_igvm_attest: bool,
1756 plan: Option<IgvmAgentTestPlan>,
1757 ) -> TestGet {
1758 if enable_igvm_attest {
1759 const TEST_DEVICE_MEMORY_SIZE: u64 = 64;
1760 let dev_test_mem = user_driver_emulated_mock::DeviceTestMemory::new(
1762 TEST_DEVICE_MEMORY_SIZE,
1763 true,
1764 "test-attest",
1765 );
1766
1767 let mut test_get = guest_emulation_transport::test_utilities::new_transport_pair(
1768 spawn,
1769 None,
1770 get_protocol::ProtocolVersion::NICKEL_REV2,
1771 Some(dev_test_mem.guest_memory()),
1772 plan,
1773 )
1774 .await;
1775
1776 test_get.client.set_gpa_allocator(dev_test_mem.dma_client());
1777
1778 test_get
1779 } else {
1780 guest_emulation_transport::test_utilities::new_transport_pair(
1781 spawn,
1782 None,
1783 get_protocol::ProtocolVersion::NICKEL_REV2,
1784 None,
1785 None,
1786 )
1787 .await
1788 }
1789 }
1790
1791 #[async_test]
1792 async fn do_nothing_without_derived_keys() {
1793 let mut vmgs = new_formatted_vmgs().await;
1794
1795 let mut key_protector = new_key_protector();
1796 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1797
1798 let key_protector_settings = KeyProtectorSettings {
1799 should_write_kp: false,
1800 use_gsp_by_id: false,
1801 use_hardware_unlock: false,
1802 decrypt_gsp_type: GspType::None,
1803 encrypt_gsp_type: GspType::None,
1804 };
1805
1806 let bios_guid = Guid::new_random();
1807
1808 unlock_vmgs_data_store(
1809 &mut vmgs,
1810 false,
1811 &mut key_protector,
1812 &mut key_protector_by_id,
1813 None,
1814 key_protector_settings,
1815 bios_guid,
1816 )
1817 .await
1818 .unwrap();
1819
1820 assert!(key_protector_is_empty(&mut vmgs).await);
1821 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1822
1823 let key_protector_settings = KeyProtectorSettings {
1825 should_write_kp: false,
1826 use_gsp_by_id: false,
1827 use_hardware_unlock: false,
1828 decrypt_gsp_type: GspType::None,
1829 encrypt_gsp_type: GspType::None,
1830 };
1831
1832 unlock_vmgs_data_store(
1834 &mut vmgs,
1835 true,
1836 &mut key_protector,
1837 &mut key_protector_by_id,
1838 None,
1839 key_protector_settings,
1840 bios_guid,
1841 )
1842 .await
1843 .unwrap();
1844
1845 assert!(key_protector_is_empty(&mut vmgs).await);
1846 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
1847 }
1848
1849 #[async_test]
1850 async fn provision_vmgs_and_rotate_keys() {
1851 let mut vmgs = new_formatted_vmgs().await;
1852
1853 let mut key_protector = new_key_protector();
1854 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1855
1856 let ingress = [1; AES_GCM_KEY_LENGTH];
1857 let egress = [2; AES_GCM_KEY_LENGTH];
1858 let derived_keys = Keys {
1859 ingress,
1860 decrypt_egress: None,
1861 encrypt_egress: egress,
1862 };
1863
1864 let key_protector_settings = KeyProtectorSettings {
1865 should_write_kp: true,
1866 use_gsp_by_id: true,
1867 use_hardware_unlock: false,
1868 decrypt_gsp_type: GspType::GspById,
1869 encrypt_gsp_type: GspType::GspById,
1870 };
1871
1872 let bios_guid = Guid::new_random();
1873
1874 unlock_vmgs_data_store(
1877 &mut vmgs,
1878 false,
1879 &mut key_protector,
1880 &mut key_protector_by_id,
1881 Some(derived_keys),
1882 key_protector_settings,
1883 bios_guid,
1884 )
1885 .await
1886 .unwrap();
1887
1888 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1890
1891 vmgs.unlock_with_encryption_key(&egress).await.unwrap();
1893 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1895
1896 assert!(!key_protector_is_empty(&mut vmgs).await);
1898 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
1899
1900 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1901 .await
1902 .unwrap();
1903 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
1904
1905 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1906 assert_eq!(
1907 found_key_protector_by_id.as_bytes(),
1908 key_protector_by_id.inner.as_bytes()
1909 );
1910
1911 let new_egress = [3; AES_GCM_KEY_LENGTH];
1913
1914 let mut new_key_protector = new_key_protector();
1915 let mut new_key_protector_by_id = new_key_protector_by_id(None, None, false);
1916
1917 let key_protector_settings = KeyProtectorSettings {
1918 should_write_kp: true,
1919 use_gsp_by_id: true,
1920 use_hardware_unlock: false,
1921 decrypt_gsp_type: GspType::GspById,
1922 encrypt_gsp_type: GspType::GspById,
1923 };
1924
1925 let derived_keys = Keys {
1927 ingress: egress,
1928 decrypt_egress: None,
1929 encrypt_egress: new_egress,
1930 };
1931
1932 unlock_vmgs_data_store(
1933 &mut vmgs,
1934 true,
1935 &mut new_key_protector,
1936 &mut new_key_protector_by_id,
1937 Some(derived_keys),
1938 key_protector_settings,
1939 bios_guid,
1940 )
1941 .await
1942 .unwrap();
1943
1944 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
1946 vmgs.unlock_with_encryption_key(&egress).await.unwrap_err();
1948
1949 vmgs.unlock_with_encryption_key(&new_egress).await.unwrap();
1951 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
1953
1954 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
1955 .await
1956 .unwrap();
1957 assert_eq!(found_key_protector.as_bytes(), new_key_protector.as_bytes());
1958
1959 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
1960 assert_eq!(
1961 found_key_protector_by_id.as_bytes(),
1962 new_key_protector_by_id.inner.as_bytes()
1963 );
1964 }
1965
1966 #[async_test]
1967 async fn unlock_previously_encrypted_vmgs_with_ingress_key() {
1968 let mut vmgs = new_formatted_vmgs().await;
1969
1970 let mut key_protector = new_key_protector();
1971 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
1972
1973 let ingress = [1; AES_GCM_KEY_LENGTH];
1974 let egress = [2; AES_GCM_KEY_LENGTH];
1975
1976 let derived_keys = Keys {
1977 ingress,
1978 decrypt_egress: None,
1979 encrypt_egress: egress,
1980 };
1981
1982 vmgs.update_encryption_key(&ingress, EncryptionAlgorithm::AES_GCM)
1983 .await
1984 .unwrap();
1985
1986 vmgs.unlock_with_encryption_key(&ingress).await.unwrap();
1988 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
1989
1990 let key_protector_settings = KeyProtectorSettings {
1991 should_write_kp: true,
1992 use_gsp_by_id: true,
1993 use_hardware_unlock: false,
1994 decrypt_gsp_type: GspType::GspById,
1995 encrypt_gsp_type: GspType::GspById,
1996 };
1997
1998 let bios_guid = Guid::new_random();
1999
2000 unlock_vmgs_data_store(
2001 &mut vmgs,
2002 true,
2003 &mut key_protector,
2004 &mut key_protector_by_id,
2005 Some(derived_keys),
2006 key_protector_settings,
2007 bios_guid,
2008 )
2009 .await
2010 .unwrap();
2011
2012 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
2014 vmgs.unlock_with_encryption_key(&egress).await.unwrap();
2015 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
2017
2018 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
2020 .await
2021 .unwrap();
2022 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
2023
2024 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
2025 assert_eq!(
2026 found_key_protector_by_id.as_bytes(),
2027 key_protector_by_id.inner.as_bytes()
2028 );
2029 }
2030
2031 #[async_test]
2032 async fn failed_to_persist_ingress_key_so_use_egress_key_to_unlock_vmgs() {
2033 let mut vmgs = new_formatted_vmgs().await;
2034
2035 let mut key_protector = new_key_protector();
2036 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2037
2038 let ingress = [1; AES_GCM_KEY_LENGTH];
2039 let decrypt_egress = [2; AES_GCM_KEY_LENGTH];
2040 let encrypt_egress = [3; AES_GCM_KEY_LENGTH];
2041
2042 let derived_keys = Keys {
2043 ingress,
2044 decrypt_egress: Some(decrypt_egress),
2045 encrypt_egress,
2046 };
2047
2048 vmgs.test_add_new_encryption_key(&decrypt_egress, EncryptionAlgorithm::AES_GCM)
2050 .await
2051 .unwrap();
2052 let egress_key_index = vmgs.test_get_active_datastore_key_index().unwrap();
2053 assert_eq!(egress_key_index, 0);
2054
2055 vmgs.unlock_with_encryption_key(&decrypt_egress)
2056 .await
2057 .unwrap();
2058 let found_egress_key_index = vmgs.test_get_active_datastore_key_index().unwrap();
2059 assert_eq!(found_egress_key_index, egress_key_index);
2060
2061 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
2063
2064 let key_protector_settings = KeyProtectorSettings {
2065 should_write_kp: true,
2066 use_gsp_by_id: true,
2067 use_hardware_unlock: false,
2068 decrypt_gsp_type: GspType::GspById,
2069 encrypt_gsp_type: GspType::GspById,
2070 };
2071
2072 let bios_guid = Guid::new_random();
2073
2074 unlock_vmgs_data_store(
2075 &mut vmgs,
2076 true,
2077 &mut key_protector,
2078 &mut key_protector_by_id,
2079 Some(derived_keys),
2080 key_protector_settings,
2081 bios_guid,
2082 )
2083 .await
2084 .unwrap();
2085
2086 vmgs.unlock_with_encryption_key(&ingress).await.unwrap_err();
2088
2089 vmgs.unlock_with_encryption_key(&decrypt_egress)
2091 .await
2092 .unwrap_err();
2093
2094 vmgs.unlock_with_encryption_key(&encrypt_egress)
2096 .await
2097 .unwrap();
2098 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
2099
2100 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
2102 .await
2103 .unwrap();
2104 assert_eq!(found_key_protector.as_bytes(), key_protector.as_bytes());
2105
2106 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
2107 assert_eq!(
2108 found_key_protector_by_id.as_bytes(),
2109 key_protector_by_id.inner.as_bytes()
2110 );
2111 }
2112
2113 #[async_test]
2114 async fn fail_to_unlock_vmgs_with_existing_ingress_key() {
2115 let mut vmgs = new_formatted_vmgs().await;
2116
2117 let mut key_protector = new_key_protector();
2118 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2119
2120 let ingress = [1; AES_GCM_KEY_LENGTH];
2121
2122 let derived_keys = Keys {
2124 ingress,
2125 decrypt_egress: None,
2126 encrypt_egress: ingress,
2127 };
2128
2129 let additional_key = [2; AES_GCM_KEY_LENGTH];
2131 let yet_another_key = [3; AES_GCM_KEY_LENGTH];
2132
2133 vmgs.test_add_new_encryption_key(&additional_key, EncryptionAlgorithm::AES_GCM)
2134 .await
2135 .unwrap();
2136 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
2137
2138 vmgs.test_add_new_encryption_key(&yet_another_key, EncryptionAlgorithm::AES_GCM)
2139 .await
2140 .unwrap();
2141 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
2142
2143 let key_protector_settings = KeyProtectorSettings {
2144 should_write_kp: true,
2145 use_gsp_by_id: true,
2146 use_hardware_unlock: false,
2147 decrypt_gsp_type: GspType::GspById,
2148 encrypt_gsp_type: GspType::GspById,
2149 };
2150
2151 let bios_guid = Guid::new_random();
2152
2153 let unlock_result = unlock_vmgs_data_store(
2154 &mut vmgs,
2155 true,
2156 &mut key_protector,
2157 &mut key_protector_by_id,
2158 Some(derived_keys),
2159 key_protector_settings,
2160 bios_guid,
2161 )
2162 .await;
2163 assert!(unlock_result.is_err());
2164 assert_eq!(
2165 unlock_result.unwrap_err().to_string(),
2166 "failed to unlock vmgs with the existing ingress key".to_string()
2167 );
2168 }
2169
2170 #[async_test]
2171 async fn fail_to_unlock_vmgs_with_new_ingress_key() {
2172 let mut vmgs = new_formatted_vmgs().await;
2173
2174 let mut key_protector = new_key_protector();
2175 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2176
2177 let derived_keys = Keys {
2178 ingress: [1; AES_GCM_KEY_LENGTH],
2179 decrypt_egress: None,
2180 encrypt_egress: [2; AES_GCM_KEY_LENGTH],
2181 };
2182
2183 let additional_key = [3; AES_GCM_KEY_LENGTH];
2185 let yet_another_key = [4; AES_GCM_KEY_LENGTH];
2186
2187 vmgs.test_add_new_encryption_key(&additional_key, EncryptionAlgorithm::AES_GCM)
2188 .await
2189 .unwrap();
2190 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(0));
2191
2192 vmgs.test_add_new_encryption_key(&yet_another_key, EncryptionAlgorithm::AES_GCM)
2193 .await
2194 .unwrap();
2195 assert_eq!(vmgs.test_get_active_datastore_key_index(), Some(1));
2196
2197 let key_protector_settings = KeyProtectorSettings {
2198 should_write_kp: true,
2199 use_gsp_by_id: true,
2200 use_hardware_unlock: false,
2201 decrypt_gsp_type: GspType::GspById,
2202 encrypt_gsp_type: GspType::GspById,
2203 };
2204
2205 let bios_guid = Guid::new_random();
2206
2207 let unlock_result = unlock_vmgs_data_store(
2208 &mut vmgs,
2209 true,
2210 &mut key_protector,
2211 &mut key_protector_by_id,
2212 Some(derived_keys),
2213 key_protector_settings,
2214 bios_guid,
2215 )
2216 .await;
2217 assert!(unlock_result.is_err());
2218 assert_eq!(
2219 unlock_result.unwrap_err().to_string(),
2220 "failed to unlock vmgs with the existing ingress key".to_string()
2221 );
2222 }
2223
2224 #[async_test]
2225 async fn get_derived_keys_using_id() {
2226 let bios_guid = Guid::new_random();
2227
2228 let gsp_response_by_id = GuestStateProtectionById {
2229 seed: guest_emulation_transport::api::GspCleartextContent {
2230 length: GSP_CLEARTEXT_MAX,
2231 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
2232 },
2233 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
2234 };
2235
2236 let mut key_protector_by_id =
2239 new_key_protector_by_id(Some(Guid::new_zeroed()), None, false);
2240 let derived_keys =
2241 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
2242 .unwrap();
2243
2244 assert_eq!(derived_keys.ingress, derived_keys.encrypt_egress);
2245
2246 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2249 let derived_keys =
2250 get_derived_keys_by_id(&mut key_protector_by_id, bios_guid, gsp_response_by_id)
2251 .unwrap();
2252
2253 assert_ne!(derived_keys.ingress, derived_keys.encrypt_egress);
2254
2255 let gsp_response_by_id_with_0_length_seed = GuestStateProtectionById {
2257 seed: guest_emulation_transport::api::GspCleartextContent {
2258 length: 0,
2259 buffer: [1; GSP_CLEARTEXT_MAX as usize * 2],
2260 },
2261 extended_status_flags: GspExtendedStatusFlags::from_bits(0),
2262 };
2263
2264 let derived_keys_response = get_derived_keys_by_id(
2265 &mut key_protector_by_id,
2266 bios_guid,
2267 gsp_response_by_id_with_0_length_seed,
2268 );
2269 assert!(derived_keys_response.is_err());
2270 assert_eq!(
2271 derived_keys_response.unwrap_err().to_string(),
2272 "failed to derive an egress key based on current vm bios guid".to_string()
2273 );
2274 }
2275
2276 #[async_test]
2277 async fn pass_through_persist_all_key_protectors() {
2278 let mut vmgs = new_formatted_vmgs().await;
2279 let mut key_protector = new_key_protector();
2280 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2281 let bios_guid = Guid::new_random();
2282
2283 let kp_copy = key_protector.as_bytes().to_vec();
2285 let active_kp_copy = key_protector.active_kp;
2286
2287 let key_protector_settings = KeyProtectorSettings {
2289 should_write_kp: true,
2290 use_gsp_by_id: true,
2291 use_hardware_unlock: true,
2292 decrypt_gsp_type: GspType::GspById,
2293 encrypt_gsp_type: GspType::GspById,
2294 };
2295 persist_all_key_protectors(
2296 &mut vmgs,
2297 &mut key_protector,
2298 &mut key_protector_by_id,
2299 bios_guid,
2300 key_protector_settings,
2301 )
2302 .await
2303 .unwrap();
2304
2305 assert!(key_protector_is_empty(&mut vmgs).await);
2306 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
2307
2308 assert_eq!(active_kp_copy, key_protector.active_kp);
2310 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
2311 }
2312
2313 #[async_test]
2314 async fn persist_all_key_protectors_write_key_protector_by_id() {
2315 let mut vmgs = new_formatted_vmgs().await;
2316 let mut key_protector = new_key_protector();
2317 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2318 let bios_guid = Guid::new_random();
2319
2320 let kp_copy = key_protector.as_bytes().to_vec();
2322 let active_kp_copy = key_protector.active_kp;
2323
2324 let key_protector_settings = KeyProtectorSettings {
2326 should_write_kp: false,
2327 use_gsp_by_id: true,
2328 use_hardware_unlock: false,
2329 decrypt_gsp_type: GspType::GspById,
2330 encrypt_gsp_type: GspType::GspById,
2331 };
2332 persist_all_key_protectors(
2333 &mut vmgs,
2334 &mut key_protector,
2335 &mut key_protector_by_id,
2336 bios_guid,
2337 key_protector_settings,
2338 )
2339 .await
2340 .unwrap();
2341
2342 assert!(key_protector_is_empty(&mut vmgs).await);
2344 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
2345
2346 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
2347 assert_eq!(
2348 found_key_protector_by_id.as_bytes(),
2349 key_protector_by_id.inner.as_bytes()
2350 );
2351
2352 assert_eq!(kp_copy.as_slice(), key_protector.as_bytes());
2354 assert_eq!(active_kp_copy, key_protector.active_kp);
2355 }
2356
2357 #[async_test]
2358 async fn persist_all_key_protectors_remove_ingress_kp() {
2359 let mut vmgs = new_formatted_vmgs().await;
2360 let mut key_protector = new_key_protector();
2361 let mut key_protector_by_id = new_key_protector_by_id(None, None, false);
2362 let bios_guid = Guid::new_random();
2363
2364 let active_kp_copy = key_protector.active_kp;
2366
2367 let key_protector_settings = KeyProtectorSettings {
2370 should_write_kp: true,
2371 use_gsp_by_id: false,
2372 use_hardware_unlock: false,
2373 decrypt_gsp_type: GspType::None,
2374 encrypt_gsp_type: GspType::None,
2375 };
2376 persist_all_key_protectors(
2377 &mut vmgs,
2378 &mut key_protector,
2379 &mut key_protector_by_id,
2380 bios_guid,
2381 key_protector_settings,
2382 )
2383 .await
2384 .unwrap();
2385
2386 assert!(!key_protector_is_empty(&mut vmgs).await);
2387 assert!(key_protector_by_id_is_empty(&mut vmgs).await);
2388
2389 let found_key_protector = vmgs::read_key_protector(&mut vmgs, AES_WRAPPED_AES_KEY_LENGTH)
2391 .await
2392 .unwrap();
2393
2394 assert!(
2395 found_key_protector.dek[active_kp_copy as usize]
2396 .dek_buffer
2397 .iter()
2398 .all(|&b| b == 0),
2399 );
2400 assert_eq!(
2401 found_key_protector.gsp[active_kp_copy as usize].gsp_length,
2402 0
2403 );
2404 assert_eq!(found_key_protector.active_kp, active_kp_copy + 1);
2405 }
2406
2407 #[async_test]
2408 async fn persist_all_key_protectors_mark_key_protector_by_id_as_not_in_use() {
2409 let mut vmgs = new_formatted_vmgs().await;
2410 let mut key_protector = new_key_protector();
2411 let mut key_protector_by_id = new_key_protector_by_id(None, None, true);
2412 let bios_guid = Guid::new_random();
2413
2414 let key_protector_settings = KeyProtectorSettings {
2417 should_write_kp: true,
2418 use_gsp_by_id: false,
2419 use_hardware_unlock: true,
2420 decrypt_gsp_type: GspType::None,
2421 encrypt_gsp_type: GspType::None,
2422 };
2423
2424 persist_all_key_protectors(
2425 &mut vmgs,
2426 &mut key_protector,
2427 &mut key_protector_by_id,
2428 bios_guid,
2429 key_protector_settings,
2430 )
2431 .await
2432 .unwrap();
2433
2434 assert!(key_protector_is_empty(&mut vmgs).await);
2435 assert!(!key_protector_by_id_is_empty(&mut vmgs).await);
2436
2437 let found_key_protector_by_id = vmgs::read_key_protector_by_id(&mut vmgs).await.unwrap();
2439 assert_eq!(found_key_protector_by_id.ported, 1);
2440 assert_eq!(
2441 found_key_protector_by_id.id_guid,
2442 key_protector_by_id.inner.id_guid
2443 );
2444 }
2445
2446 #[async_test]
2449 async fn init_sec_suppress_attestation(driver: DefaultDriver) {
2450 let mut vmgs = new_formatted_vmgs().await;
2451
2452 let agent = SecurityProfile {
2454 agent_data: [0xAA; AGENT_DATA_MAX_SIZE],
2455 };
2456 vmgs.write_file(FileId::ATTEST, agent.as_bytes())
2457 .await
2458 .unwrap();
2459
2460 let get_pair = new_test_get(driver, false, None).await;
2462
2463 let bios_guid = Guid::new_random();
2464 let att_cfg = Default::default();
2465
2466 assert!(!vmgs.encrypted());
2468
2469 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2471 let res = initialize_platform_security(
2472 &get_pair.client,
2473 bios_guid,
2474 &att_cfg,
2475 &mut vmgs,
2476 None, true, ldriver,
2479 GuestStateEncryptionPolicy::None,
2480 true,
2481 )
2482 .await
2483 .unwrap();
2484
2485 assert!(!vmgs.encrypted());
2487 assert!(key_protector_is_empty(&mut vmgs).await);
2488 assert!(hardware_key_protector_is_empty(&mut vmgs).await);
2489 assert_eq!(res.agent_data.unwrap(), agent.agent_data.to_vec());
2491 assert!(res.guest_secret_key.is_none());
2493 }
2494
2495 #[async_test]
2496 async fn init_sec_secure_key_release_with_wrapped_key_request(driver: DefaultDriver) {
2497 let mut vmgs = new_formatted_vmgs().await;
2498
2499 let get_pair = new_test_get(driver, true, None).await;
2501
2502 let bios_guid = Guid::new_random();
2503 let att_cfg = Default::default();
2504 let tee = MockTeeCall::new(0x1234);
2505
2506 assert!(!vmgs.encrypted());
2508
2509 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2511 let res = initialize_platform_security(
2512 &get_pair.client,
2513 bios_guid,
2514 &att_cfg,
2515 &mut vmgs,
2516 Some(&tee),
2517 false,
2518 ldriver.clone(),
2519 GuestStateEncryptionPolicy::Auto,
2520 true,
2521 )
2522 .await
2523 .unwrap();
2524
2525 assert!(vmgs.encrypted());
2527 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2528
2529 let key_reference = serde_json::json!({
2532 "key_info": {
2533 "host": "name"
2534 },
2535 "attestation_info": {
2536 "host": "attestation_name"
2537 }
2538 });
2539 let key_reference = serde_json::to_string(&key_reference).unwrap();
2540 let key_reference = key_reference.as_bytes();
2541 let mut expected_agent_data = [0u8; AGENT_DATA_MAX_SIZE];
2542 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2543 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2544 assert!(res.guest_secret_key.is_none());
2546
2547 initialize_platform_security(
2549 &get_pair.client,
2550 bios_guid,
2551 &att_cfg,
2552 &mut vmgs,
2553 Some(&tee),
2554 false,
2555 ldriver,
2556 GuestStateEncryptionPolicy::Auto,
2557 true,
2558 )
2559 .await
2560 .unwrap();
2561
2562 assert!(vmgs.encrypted());
2564 }
2565
2566 #[async_test]
2567 async fn init_sec_secure_key_release_without_wrapped_key_request(driver: DefaultDriver) {
2568 let mut vmgs = new_formatted_vmgs().await;
2569
2570 let agent = SecurityProfile {
2572 agent_data: [0xAA; AGENT_DATA_MAX_SIZE],
2573 };
2574 vmgs.write_file(FileId::ATTEST, agent.as_bytes())
2575 .await
2576 .unwrap();
2577
2578 let mut plan = IgvmAgentTestPlan::default();
2580 plan.insert(
2581 IgvmAttestRequestType::WRAPPED_KEY_REQUEST,
2582 VecDeque::from([IgvmAgentAction::NoResponse, IgvmAgentAction::NoResponse]),
2583 );
2584
2585 let get_pair = new_test_get(driver, true, Some(plan)).await;
2587
2588 let bios_guid = Guid::new_random();
2589 let att_cfg = Default::default();
2590 let tee = MockTeeCall::new(0x1234);
2591
2592 assert!(!vmgs.encrypted());
2594
2595 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2597 let res = initialize_platform_security(
2598 &get_pair.client,
2599 bios_guid,
2600 &att_cfg,
2601 &mut vmgs,
2602 Some(&tee),
2603 false,
2604 ldriver.clone(),
2605 GuestStateEncryptionPolicy::Auto,
2606 true,
2607 )
2608 .await
2609 .unwrap();
2610
2611 assert!(vmgs.encrypted());
2613 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2614 assert_eq!(res.agent_data.clone().unwrap(), agent.agent_data.to_vec());
2616 assert!(res.guest_secret_key.is_none());
2618
2619 let res = initialize_platform_security(
2621 &get_pair.client,
2622 bios_guid,
2623 &att_cfg,
2624 &mut vmgs,
2625 Some(&tee),
2626 false,
2627 ldriver,
2628 GuestStateEncryptionPolicy::Auto,
2629 true,
2630 )
2631 .await
2632 .unwrap();
2633
2634 assert!(vmgs.encrypted());
2636 assert_eq!(res.agent_data.clone().unwrap(), agent.agent_data.to_vec());
2638 assert!(res.guest_secret_key.is_none());
2640 }
2641
2642 #[async_test]
2643 async fn init_sec_secure_key_release_hw_sealing_backup(driver: DefaultDriver) {
2644 let mut vmgs = new_formatted_vmgs().await;
2645
2646 let mut plan = IgvmAgentTestPlan::default();
2648 plan.insert(
2649 IgvmAttestRequestType::WRAPPED_KEY_REQUEST,
2650 VecDeque::from([
2651 IgvmAgentAction::RespondSuccess,
2652 IgvmAgentAction::RespondFailure,
2654 IgvmAgentAction::RespondFailure,
2655 IgvmAgentAction::RespondFailure,
2656 IgvmAgentAction::RespondFailure,
2657 IgvmAgentAction::RespondFailure,
2658 IgvmAgentAction::RespondFailure,
2659 IgvmAgentAction::RespondFailure,
2660 IgvmAgentAction::RespondFailure,
2661 IgvmAgentAction::RespondFailure,
2662 IgvmAgentAction::RespondFailure,
2663 ]),
2664 );
2665
2666 let get_pair = new_test_get(driver, true, Some(plan)).await;
2667
2668 let bios_guid = Guid::new_random();
2669 let att_cfg = Default::default();
2670
2671 assert!(!vmgs.encrypted());
2673
2674 let tee = MockTeeCall::new(0x1234);
2676 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2677 let res = initialize_platform_security(
2678 &get_pair.client,
2679 bios_guid,
2680 &att_cfg,
2681 &mut vmgs,
2682 Some(&tee),
2683 false,
2684 ldriver.clone(),
2685 GuestStateEncryptionPolicy::Auto,
2686 true,
2687 )
2688 .await
2689 .unwrap();
2690
2691 assert!(vmgs.encrypted());
2693 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2694 let key_reference = serde_json::json!({
2697 "key_info": {
2698 "host": "name"
2699 },
2700 "attestation_info": {
2701 "host": "attestation_name"
2702 }
2703 });
2704 let key_reference = serde_json::to_string(&key_reference).unwrap();
2705 let key_reference = key_reference.as_bytes();
2706 let mut expected_agent_data = [0u8; AGENT_DATA_MAX_SIZE];
2707 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2708 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2709 assert!(res.guest_secret_key.is_none());
2711
2712 initialize_platform_security(
2718 &get_pair.client,
2719 bios_guid,
2720 &att_cfg,
2721 &mut vmgs,
2722 Some(&tee),
2723 false,
2724 ldriver,
2725 GuestStateEncryptionPolicy::Auto,
2726 true,
2727 )
2728 .await
2729 .unwrap();
2730
2731 assert!(vmgs.encrypted());
2733 }
2734
2735 #[async_test]
2736 async fn init_sec_secure_key_release_skip_hw_unsealing(driver: DefaultDriver) {
2737 let mut vmgs = new_formatted_vmgs().await;
2738
2739 let mut plan = IgvmAgentTestPlan::default();
2743 plan.insert(
2744 IgvmAttestRequestType::KEY_RELEASE_REQUEST,
2745 VecDeque::from([
2746 IgvmAgentAction::RespondSuccess,
2747 IgvmAgentAction::RespondFailureSkipHwUnsealing,
2748 ]),
2749 );
2750
2751 let get_pair = new_test_get(driver, true, Some(plan)).await;
2752
2753 let bios_guid = Guid::new_random();
2754 let att_cfg = Default::default();
2755
2756 assert!(!vmgs.encrypted());
2758
2759 let tee = MockTeeCall::new(0x1234);
2761 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2762 let res = initialize_platform_security(
2763 &get_pair.client,
2764 bios_guid,
2765 &att_cfg,
2766 &mut vmgs,
2767 Some(&tee),
2768 false,
2769 ldriver.clone(),
2770 GuestStateEncryptionPolicy::Auto,
2771 true,
2772 )
2773 .await
2774 .unwrap();
2775
2776 assert!(vmgs.encrypted());
2778 assert!(!hardware_key_protector_is_empty(&mut vmgs).await);
2779 let key_reference = serde_json::json!({
2781 "key_info": {
2782 "host": "name"
2783 },
2784 "attestation_info": {
2785 "host": "attestation_name"
2786 }
2787 });
2788 let key_reference = serde_json::to_string(&key_reference).unwrap();
2789 let key_reference = key_reference.as_bytes();
2790 let mut expected_agent_data = [0u8; AGENT_DATA_MAX_SIZE];
2791 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2792 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2793 assert!(res.guest_secret_key.is_none());
2795
2796 let result = initialize_platform_security(
2804 &get_pair.client,
2805 bios_guid,
2806 &att_cfg,
2807 &mut vmgs,
2808 Some(&tee),
2809 false,
2810 ldriver,
2811 GuestStateEncryptionPolicy::Auto,
2812 true,
2813 )
2814 .await;
2815
2816 assert!(result.is_err());
2817 }
2818
2819 #[async_test]
2820 async fn init_sec_secure_key_release_no_hw_sealing_backup(driver: DefaultDriver) {
2821 let mut vmgs = new_formatted_vmgs().await;
2822
2823 let mut plan = IgvmAgentTestPlan::default();
2825 plan.insert(
2826 IgvmAttestRequestType::WRAPPED_KEY_REQUEST,
2827 VecDeque::from([
2828 IgvmAgentAction::RespondSuccess,
2829 IgvmAgentAction::RespondFailure,
2831 IgvmAgentAction::RespondFailure,
2832 IgvmAgentAction::RespondFailure,
2833 IgvmAgentAction::RespondFailure,
2834 IgvmAgentAction::RespondFailure,
2835 IgvmAgentAction::RespondFailure,
2836 IgvmAgentAction::RespondFailure,
2837 IgvmAgentAction::RespondFailure,
2838 IgvmAgentAction::RespondFailure,
2839 IgvmAgentAction::RespondFailure,
2840 ]),
2841 );
2842
2843 let get_pair = new_test_get(driver, true, Some(plan)).await;
2844
2845 let bios_guid = Guid::new_random();
2846 let att_cfg = Default::default();
2847 let tee = MockTeeCallNoGetDerivedKey {};
2849
2850 assert!(!vmgs.encrypted());
2852
2853 let ldriver = pal_async::local::block_with_io(|ld| async move { ld });
2855 let res = initialize_platform_security(
2856 &get_pair.client,
2857 bios_guid,
2858 &att_cfg,
2859 &mut vmgs,
2860 Some(&tee),
2861 false,
2862 ldriver.clone(),
2863 GuestStateEncryptionPolicy::Auto,
2864 true,
2865 )
2866 .await
2867 .unwrap();
2868
2869 assert!(vmgs.encrypted());
2871 assert!(hardware_key_protector_is_empty(&mut vmgs).await);
2872 let key_reference = serde_json::json!({
2875 "key_info": {
2876 "host": "name"
2877 },
2878 "attestation_info": {
2879 "host": "attestation_name"
2880 }
2881 });
2882 let key_reference = serde_json::to_string(&key_reference).unwrap();
2883 let key_reference = key_reference.as_bytes();
2884 let mut expected_agent_data = [0u8; AGENT_DATA_MAX_SIZE];
2885 expected_agent_data[..key_reference.len()].copy_from_slice(key_reference);
2886 assert_eq!(res.agent_data.unwrap(), expected_agent_data.to_vec());
2887 assert!(res.guest_secret_key.is_none());
2889
2890 let result = initialize_platform_security(
2892 &get_pair.client,
2893 bios_guid,
2894 &att_cfg,
2895 &mut vmgs,
2896 Some(&tee),
2897 false,
2898 ldriver,
2899 GuestStateEncryptionPolicy::Auto,
2900 true,
2901 )
2902 .await;
2903
2904 assert!(result.is_err());
2905 }
2906
2907 #[test]
2908 fn test_get_provenance_claims() {
2909 const PROVENANCE_DOC: &str = include_str!("../test_data/valid_jwt");
2911 let doc = PROVENANCE_DOC.trim().strip_prefix("placeholder_").unwrap();
2912 let claims = get_provenance_claims(doc.as_bytes()).unwrap();
2913 assert_eq!(
2914 claims.id,
2915 guid::guid!("03020100-0504-0706-0809-0a0b0c0d0e0f")
2916 );
2917 assert_eq!(
2918 claims.signer,
2919 "did:x509:0:sha256:ea76599d86897382aa519ff2bc0fa6b9c15d60da2ebe53e72139cd317b0797ed:subject:fican.cvmprovisioningservice.core.azure-test.net"
2920 );
2921 }
2922
2923 #[test]
2924 fn test_derive_vmgsid() {
2925 const SEED_DOC_1: &str = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F,4C6162656C5F435053,436F6E746578745F564D4753,32";
2926 const SEED_DOC_2: &str = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F,4C6162656C5F435053,436F6E746578745F564D4753";
2927 const SEED_DOC_3: &str = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F,4C6162656C5F435053,436F6E746578745F564D4753,32,ABCDEF";
2928 const GUID: Guid = guid::guid!("b0587f2d-11e6-9f66-1af4-8b4a619147c8");
2929
2930 let vmgsid1 = derive_vmgsid(SEED_DOC_1.as_bytes()).unwrap();
2931 assert_eq!(vmgsid1, GUID);
2932
2933 let vmgsid2 = derive_vmgsid(SEED_DOC_2.as_bytes()).unwrap();
2934 assert_eq!(vmgsid2, GUID);
2935
2936 let vmgsid3 = derive_vmgsid(SEED_DOC_3.as_bytes()).unwrap();
2937 assert_eq!(vmgsid3, GUID);
2938 }
2939}