diff --git a/tss-esapi/Cargo.toml b/tss-esapi/Cargo.toml index 48b0f5ca..05375b05 100644 --- a/tss-esapi/Cargo.toml +++ b/tss-esapi/Cargo.toml @@ -80,3 +80,6 @@ integration-tests = ["strum", "strum_macros"] rustcrypto = ["digest", "ecdsa", "elliptic-curve", "pkcs8", "signature", "x509-cert"] rustcrypto-full = ["rustcrypto", "p192", "p224", "p256", "p384", "p521", "rsa", "sha1", "sha2", "sha3", "sm2", "sm3"] + +sha1 = ["dep:sha1", "rsa?/sha1"] +sha2 = ["dep:sha2", "rsa?/sha2"] diff --git a/tss-esapi/src/abstraction/mod.rs b/tss-esapi/src/abstraction/mod.rs index b066351f..fbce9203 100644 --- a/tss-esapi/src/abstraction/mod.rs +++ b/tss-esapi/src/abstraction/mod.rs @@ -4,6 +4,7 @@ pub mod ak; pub mod cipher; pub mod ek; +pub mod no_tpm; pub mod nv; pub mod pcr; pub mod public; diff --git a/tss-esapi/src/abstraction/no_tpm/mod.rs b/tss-esapi/src/abstraction/no_tpm/mod.rs new file mode 100644 index 00000000..51f09f91 --- /dev/null +++ b/tss-esapi/src/abstraction/no_tpm/mod.rs @@ -0,0 +1,10 @@ +#[cfg(all( + any(feature = "p224", feature = "p256", feature = "p384", feature = "rsa"), + any(feature = "sha1", feature = "sha2",) +))] +mod quote; +#[cfg(all( + any(feature = "p224", feature = "p256", feature = "p384", feature = "rsa"), + any(feature = "sha1", feature = "sha2",) +))] +pub use quote::checkquote; diff --git a/tss-esapi/src/abstraction/no_tpm/quote.rs b/tss-esapi/src/abstraction/no_tpm/quote.rs new file mode 100644 index 00000000..59733df3 --- /dev/null +++ b/tss-esapi/src/abstraction/no_tpm/quote.rs @@ -0,0 +1,379 @@ +// Copyright 2021 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 +use crate::error::Error; +use crate::error::Result; +use crate::WrapperErrorKind; +use crate::{ + interface_types::algorithm::HashingAlgorithm, + structures::{Attest, AttestInfo, DigestList, PcrSelectionList, Public, QuoteInfo, Signature}, + traits::Marshall, +}; +use digest::{Digest, DynDigest}; + +#[cfg(any(feature = "p224", feature = "p256", feature = "p384"))] +use crate::{abstraction::public::AssociatedTpmCurve, structures::EccSignature}; +#[cfg(any(feature = "p224", feature = "p256", feature = "p384"))] +use ecdsa::{ + hazmat::{DigestPrimitive, VerifyPrimitive}, + PrimeCurve, SignatureSize, VerifyingKey, +}; +#[cfg(any(feature = "p224", feature = "p256", feature = "p384"))] +use elliptic_curve::{ + generic_array::ArrayLength, + point::AffinePoint, + sec1::{FromEncodedPoint, ModulusSize, ToEncodedPoint}, + CurveArithmetic, FieldBytesSize, +}; +#[cfg(any(feature = "p224", feature = "p256", feature = "p384"))] +use signature::hazmat::PrehashVerifier; + +#[cfg(feature = "rsa")] +use rsa::{pkcs1v15, pss, RsaPublicKey}; +#[cfg(feature = "rsa")] +use signature::Verifier; + +#[cfg(any(feature = "p224", feature = "p256", feature = "p384"))] +fn verify_ecdsa( + public: &Public, + message: &[u8], + signature: &EccSignature, + hashing_algorithm: HashingAlgorithm, +) -> Result +where + C: PrimeCurve + CurveArithmetic + DigestPrimitive + AssociatedTpmCurve, + AffinePoint: VerifyPrimitive + FromEncodedPoint + ToEncodedPoint, + SignatureSize: ArrayLength, + FieldBytesSize: ModulusSize, +{ + let Ok(signature) = ecdsa::Signature::::try_from(signature.clone()) else { + return Ok(false); + }; + let Ok(public) = elliptic_curve::PublicKey::::try_from(public) else { + return Ok(false); + }; + + let verifying_key = VerifyingKey::from(public); + + match hashing_algorithm { + #[cfg(feature = "sha1")] + HashingAlgorithm::Sha1 => { + let hash = sha1::Sha1::digest(message); + Ok(verifying_key.verify_prehash(&hash, &signature).is_ok()) + } + #[cfg(feature = "sha2")] + HashingAlgorithm::Sha256 => { + let hash = sha2::Sha256::digest(message); + Ok(verifying_key.verify_prehash(&hash, &signature).is_ok()) + } + #[cfg(feature = "sha2")] + HashingAlgorithm::Sha384 => { + let hash = sha2::Sha384::digest(message); + Ok(verifying_key.verify_prehash(&hash, &signature).is_ok()) + } + #[cfg(feature = "sha2")] + HashingAlgorithm::Sha512 => { + let hash = sha2::Sha512::digest(message); + Ok(verifying_key.verify_prehash(&hash, &signature).is_ok()) + } + _ => Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)), + } +} + +#[cfg(feature = "rsa")] +fn verify_rsa_pss( + public: &Public, + message: &[u8], + signature: &pss::Signature, + hashing_algorithm: HashingAlgorithm, +) -> Result { + let rsa_key = RsaPublicKey::try_from(public)?; + + match hashing_algorithm { + #[cfg(feature = "sha1")] + HashingAlgorithm::Sha1 => { + let verifying_key = pss::VerifyingKey::::from(rsa_key); + Ok(verifying_key.verify(message, signature).is_ok()) + } + #[cfg(feature = "sha2")] + HashingAlgorithm::Sha256 => { + let verifying_key = pss::VerifyingKey::::from(rsa_key); + Ok(verifying_key.verify(message, signature).is_ok()) + } + #[cfg(feature = "sha2")] + HashingAlgorithm::Sha384 => { + let verifying_key = pss::VerifyingKey::::from(rsa_key); + Ok(verifying_key.verify(message, signature).is_ok()) + } + #[cfg(feature = "sha2")] + HashingAlgorithm::Sha512 => { + let verifying_key = pss::VerifyingKey::::from(rsa_key); + Ok(verifying_key.verify(message, signature).is_ok()) + } + _ => Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)), + } +} + +#[cfg(feature = "rsa")] +fn verify_rsa_pkcs1v15( + public: &Public, + message: &[u8], + signature: &pkcs1v15::Signature, + hashing_algorithm: HashingAlgorithm, +) -> Result { + let rsa_key = RsaPublicKey::try_from(public)?; + + match hashing_algorithm { + #[cfg(feature = "sha1")] + HashingAlgorithm::Sha1 => { + let verifying_key = pkcs1v15::VerifyingKey::::new(rsa_key); + Ok(verifying_key.verify(message, signature).is_ok()) + } + #[cfg(feature = "sha2")] + HashingAlgorithm::Sha256 => { + let verifying_key = pkcs1v15::VerifyingKey::::new(rsa_key); + Ok(verifying_key.verify(message, signature).is_ok()) + } + #[cfg(feature = "sha2")] + HashingAlgorithm::Sha384 => { + let verifying_key = pkcs1v15::VerifyingKey::::new(rsa_key); + Ok(verifying_key.verify(message, signature).is_ok()) + } + #[cfg(feature = "sha2")] + HashingAlgorithm::Sha512 => { + let verifying_key = pkcs1v15::VerifyingKey::::new(rsa_key); + Ok(verifying_key.verify(message, signature).is_ok()) + } + _ => Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)), + } +} + +fn checkquote_pcr_digests( + quote: &QuoteInfo, + selections: &PcrSelectionList, + digests: &DigestList, + hash_alg: HashingAlgorithm, +) -> Result { + if selections != quote.pcr_selection() { + return Ok(false); + } + let digests_val = digests.value(); + let mut digest_pos = 0; + let mut hasher: Box = match hash_alg { + #[cfg(feature = "sha1")] + HashingAlgorithm::Sha1 => Box::new(sha1::Sha1::new()), + #[cfg(feature = "sha2")] + HashingAlgorithm::Sha256 => Box::new(sha2::Sha256::new()), + #[cfg(feature = "sha2")] + HashingAlgorithm::Sha384 => Box::new(sha2::Sha384::new()), + #[cfg(feature = "sha2")] + HashingAlgorithm::Sha512 => Box::new(sha2::Sha512::new()), + _ => { + return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)); + } + }; + + for selection in selections.get_selections() { + let sel_count = selection.selected().len(); + if digest_pos + sel_count > digests.len() { + return Err(Error::WrapperError(WrapperErrorKind::WrongParamSize)); + } + for _ in 0..sel_count { + hasher.update(&digests_val[digest_pos]); + digest_pos += 1; + } + } + if digest_pos != digests.len() { + return Err(Error::WrapperError(WrapperErrorKind::WrongParamSize)); + } + let digest = hasher.finalize(); + Ok(digest.as_ref() == quote.pcr_digest().as_ref()) +} + +/// Verify a quote +/// +/// # Arguments +/// * `attest` - Attestation data containing a quote +/// * `signature` - Signature for the attestation data +/// * `public` - TPM2 public struct which contains the public key for verification +/// * `pcr_data` - Optional pcr values to verify +/// * `qualifying_data` - qualifying data to verify +/// +/// # Returns +/// The command returns `true` if the quote is valid or `false` otherwise. +/// +/// # Errors +/// * if the qualifying data provided is too long, a `WrongParamSize` wrapper error will be returned +/// +/// # Examples +/// +/// ```rust +/// # use std::convert::TryFrom; +/// # use tss_esapi::{ +/// # attributes::SessionAttributes, +/// # abstraction::{ak, ek, AsymmetricAlgorithmSelection, no_tpm}, +/// # constants::SessionType, Context, +/// # interface_types::{ +/// # algorithm::{HashingAlgorithm, SignatureSchemeAlgorithm}, +/// # ecc::EccCurve, +/// # }, +/// # structures::{ +/// # Data, PcrSelectionListBuilder, PcrSlot, +/// # SignatureScheme, SymmetricDefinition, +/// # }, +/// # TctiNameConf, +/// # }; +/// # let mut context = +/// # Context::new( +/// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), +/// # ).expect("Failed to create Context"); +/// # let session = context +/// # .start_auth_session( +/// # None, +/// # None, +/// # None, +/// # SessionType::Hmac, +/// # SymmetricDefinition::AES_256_CFB, +/// # tss_esapi::interface_types::algorithm::HashingAlgorithm::Sha256, +/// # ) +/// # .expect("Failed to create session") +/// # .expect("Received invalid handle"); +/// # let (session_attributes, session_attributes_mask) = SessionAttributes::builder() +/// # .with_decrypt(true) +/// # .with_encrypt(true) +/// # .build(); +/// # context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask) +/// # .expect("Failed to set attributes on session"); +/// # context.set_sessions((Some(session), None, None)); +/// # let qualifying_data = vec![0xff; 16]; +/// # let ek_ecc = ek::create_ek_object( +/// # &mut context, +/// # AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256), +/// # None, +/// # ) +/// # .unwrap(); +/// # let ak_res = ak::create_ak( +/// # &mut context, +/// # ek_ecc, +/// # HashingAlgorithm::Sha256, +/// # AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256), +/// # SignatureSchemeAlgorithm::EcDsa, +/// # None, +/// # None, +/// # ) +/// # .unwrap(); +/// # let ak_ecc = ak::load_ak( +/// # &mut context, +/// # ek_ecc, +/// # None, +/// # ak_res.out_private, +/// # ak_res.out_public.clone(), +/// # ) +/// # .unwrap(); +/// # let pcr_selection_list = PcrSelectionListBuilder::new() +/// # .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot2]) +/// # .build() +/// # .expect("Failed to create PcrSelectionList"); +/// let (attest, signature) = context +/// .quote( +/// ak_ecc, +/// Data::try_from(qualifying_data.clone()).unwrap(), +/// SignatureScheme::Null, +/// pcr_selection_list.clone(), +/// ) +/// .expect("Failed to get a quote"); +/// let (_update_counter, pcr_sel, pcr_data) = context +/// .execute_without_session(|ctx| ctx.pcr_read(pcr_selection_list)) +/// .unwrap(); +/// let public = ak_res.out_public; +/// no_tpm::checkquote( +/// &attest, +/// &signature, +/// &public, +/// &Some((pcr_sel.clone(), pcr_data.clone())), +/// &qualifying_data +/// ) +/// .unwrap(); +/// ``` +pub fn checkquote( + attest: &Attest, + signature: &Signature, + public: &Public, + pcr_data: &Option<(PcrSelectionList, DigestList)>, + qualifying_data: &Vec, +) -> Result { + let quote = if let AttestInfo::Quote { info } = attest.attested() { + info + } else { + return Err(Error::WrapperError(WrapperErrorKind::InvalidParam)); + }; + + let bytes = attest.marshall()?; + + let hash_alg = match (public, signature) { + #[cfg(any(feature = "p224", feature = "p256", feature = "p384"))] + (Public::Ecc { parameters, .. }, _) => { + let mut hash_alg = None; + macro_rules! impl_check_ecdsa { + ($curve: ty) => { + if parameters.ecc_curve() == <$curve>::TPM_CURVE { + let Signature::EcDsa(sig) = signature else { + return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)); + }; + if !verify_ecdsa::<$curve>(&public, &bytes, &sig, sig.hashing_algorithm())? + { + return Ok(false); + } + hash_alg = Some(sig.hashing_algorithm()); + } + }; + } + #[cfg(feature = "p224")] + impl_check_ecdsa!(p224::NistP224); + #[cfg(feature = "p256")] + impl_check_ecdsa!(p256::NistP256); + #[cfg(feature = "p384")] + impl_check_ecdsa!(p384::NistP384); + + if let Some(h) = hash_alg { + h + } else { + return Err(Error::WrapperError(WrapperErrorKind::InvalidParam)); + } + } + #[cfg(feature = "rsa")] + (Public::Rsa { .. }, sig @ Signature::RsaSsa(pkcs_sig)) => { + let Ok(sig) = pkcs1v15::Signature::try_from(sig.clone()) else { + return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)); + }; + + if !verify_rsa_pkcs1v15(public, &bytes, &sig, pkcs_sig.hashing_algorithm())? { + return Ok(false); + } + pkcs_sig.hashing_algorithm() + } + #[cfg(feature = "rsa")] + (Public::Rsa { .. }, sig @ Signature::RsaPss(pkcs_sig)) => { + let Ok(sig) = pss::Signature::try_from(sig.clone()) else { + return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)); + }; + + if !verify_rsa_pss(public, &bytes, &sig, pkcs_sig.hashing_algorithm())? { + return Ok(false); + } + pkcs_sig.hashing_algorithm() + } + _ => { + return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)); + } + }; + + if qualifying_data != attest.extra_data().as_bytes() { + return Ok(false); + } + if let Some((selections, digests)) = pcr_data { + if !checkquote_pcr_digests(quote, selections, digests, hash_alg)? { + return Ok(false); + } + } + Ok(true) +} diff --git a/tss-esapi/tests/integration_tests/abstraction_tests/mod.rs b/tss-esapi/tests/integration_tests/abstraction_tests/mod.rs index 1a08d637..2d56d05e 100644 --- a/tss-esapi/tests/integration_tests/abstraction_tests/mod.rs +++ b/tss-esapi/tests/integration_tests/abstraction_tests/mod.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 mod ak_tests; mod ek_tests; +mod no_tpm; mod nv_tests; mod pcr_data_tests; mod pcr_tests; diff --git a/tss-esapi/tests/integration_tests/abstraction_tests/no_tpm/mod.rs b/tss-esapi/tests/integration_tests/abstraction_tests/no_tpm/mod.rs new file mode 100644 index 00000000..08711c6e --- /dev/null +++ b/tss-esapi/tests/integration_tests/abstraction_tests/no_tpm/mod.rs @@ -0,0 +1 @@ +mod quote_test; diff --git a/tss-esapi/tests/integration_tests/abstraction_tests/no_tpm/quote_test.rs b/tss-esapi/tests/integration_tests/abstraction_tests/no_tpm/quote_test.rs new file mode 100644 index 00000000..a373ffbe --- /dev/null +++ b/tss-esapi/tests/integration_tests/abstraction_tests/no_tpm/quote_test.rs @@ -0,0 +1,264 @@ +// Copyright 2021 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 + +mod test_quote { + use crate::common::create_ctx_with_session; + use std::convert::TryFrom; + use tss_esapi::{ + abstraction::{ak, ek, no_tpm, AsymmetricAlgorithmSelection}, + handles::PcrHandle, + interface_types::{ + algorithm::{HashingAlgorithm, SignatureSchemeAlgorithm}, + ecc::EccCurve, + key_bits::RsaKeyBits, + }, + structures::{ + Auth, Data, Digest, DigestList, DigestValues, EccSignature, PcrSelectionListBuilder, + PcrSlot, Signature, SignatureScheme, + }, + }; + + fn checkquote_ecc(hash_alg: HashingAlgorithm) { + let mut context = create_ctx_with_session(); + let ek_ecc = ek::create_ek_object( + &mut context, + AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256), + None, + ) + .unwrap(); + // change pcr values for tests + let mut vals = DigestValues::new(); + vals.set( + HashingAlgorithm::Sha256, + Digest::try_from(vec![ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, + ]) + .unwrap(), + ); + context.pcr_extend(PcrHandle::Pcr7, vals).unwrap(); + + let ak_res = ak::create_ak( + &mut context, + ek_ecc, + hash_alg, + AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256), + SignatureSchemeAlgorithm::EcDsa, + None, + None, + ) + .unwrap(); + let ak_ecc = ak::load_ak( + &mut context, + ek_ecc, + None, + ak_res.out_private, + ak_res.out_public.clone(), + ) + .unwrap(); + + let pcr_selection_list = PcrSelectionListBuilder::new() + .with_selection(HashingAlgorithm::Sha1, &[PcrSlot::Slot4]) + .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot2]) + .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot7]) + .with_selection(HashingAlgorithm::Sha512, &[PcrSlot::Slot4]) + .build() + .expect("Failed to create PcrSelectionList"); + let qualifying_data = vec![5, 2, 3, 8, 1, 4, 8, 28, 1, 4, 8, 2]; + let (attest, signature) = context + .quote( + ak_ecc, + Data::try_from(qualifying_data.clone()).unwrap(), + SignatureScheme::Null, + pcr_selection_list.clone(), + ) + .expect("Failed to get a quote"); + let (_update_counter, pcr_sel, pcr_data) = context + .execute_without_session(|ctx| ctx.pcr_read(pcr_selection_list)) + .unwrap(); + + let public = ak_res.out_public; + assert!(no_tpm::checkquote( + &attest, + &signature, + &public, + &Some((pcr_sel.clone(), pcr_data.clone())), + &qualifying_data + ) + .unwrap()); + // Test without pcrs + assert!(no_tpm::checkquote(&attest, &signature, &public, &None, &qualifying_data).unwrap()); + + let wrong_nonce = vec![5, 2, 3, 8, 1, 4, 8]; + assert!(!no_tpm::checkquote(&attest, &signature, &public, &None, &wrong_nonce).unwrap()); + + let wrong_ak_res = ak::create_ak( + &mut context, + ek_ecc, + hash_alg, + AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256), + SignatureSchemeAlgorithm::EcDsa, + None, + None, + ) + .unwrap(); + assert!(!no_tpm::checkquote( + &attest, + &signature, + &wrong_ak_res.out_public, + &Some((pcr_sel.clone(), pcr_data.clone())), + &qualifying_data + ) + .unwrap()); + + let wrong_selection = PcrSelectionListBuilder::new() + .with_selection(HashingAlgorithm::Sha1, &[PcrSlot::Slot4]) + .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot2]) + .build() + .expect("Failed to create PcrSelectionList"); + assert!(!no_tpm::checkquote( + &attest, + &signature, + &public, + &Some((wrong_selection, pcr_data.clone())), + &qualifying_data + ) + .unwrap()); + + let mut wrong_pcr_data = DigestList::new(); + for i in 1..pcr_data.len() { + wrong_pcr_data.add(pcr_data.value()[i].clone()).unwrap(); + } + wrong_pcr_data.add(pcr_data.value()[0].clone()).unwrap(); + assert!(!no_tpm::checkquote( + &attest, + &signature, + &public, + &Some((pcr_sel.clone(), wrong_pcr_data)), + &qualifying_data + ) + .unwrap()); + + let ecc = match signature { + Signature::EcDsa(e) => e, + _ => { + panic!("Wrong signature created"); + } + }; + let wrong_signature = EccSignature::create( + HashingAlgorithm::Sha256, + ecc.signature_s().clone(), + ecc.signature_r().clone(), + ) + .unwrap(); + assert!(!no_tpm::checkquote( + &attest, + &Signature::EcDsa(wrong_signature), + &public, + &Some((pcr_sel.clone(), pcr_data.clone())), + &qualifying_data + ) + .unwrap()); + } + + #[test] + fn checkquote_ecc_sha1() { + checkquote_ecc(HashingAlgorithm::Sha1); + } + + #[test] + fn checkquote_ecc_sha256() { + checkquote_ecc(HashingAlgorithm::Sha256); + } + + #[test] + fn checkquote_ecc_sha512() { + checkquote_ecc(HashingAlgorithm::Sha512); + } + + fn checkquote_rsa( + keybits: RsaKeyBits, + hash_alg: HashingAlgorithm, + sig_scheme: SignatureSchemeAlgorithm, + ) { + let mut context = create_ctx_with_session(); + let ek_rsa = ek::create_ek_object( + &mut context, + AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), + None, + ) + .unwrap(); + let ak_auth = Auth::try_from(vec![0x1, 0x2, 0x42]).unwrap(); + let ak_rsa = ak::create_ak( + &mut context, + ek_rsa, + hash_alg, + AsymmetricAlgorithmSelection::Rsa(keybits), + sig_scheme, + Some(ak_auth.clone()), + None, + ) + .unwrap(); + let loaded_ak = ak::load_ak( + &mut context, + ek_rsa, + Some(ak_auth), + ak_rsa.out_private, + ak_rsa.out_public.clone(), + ) + .unwrap(); + + let pcr_selection_list = PcrSelectionListBuilder::new() + .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot7]) + .build() + .expect("Failed to create PcrSelectionList"); + let qualifying_data = vec![5, 8, 1, 4, 8, 28, 18, 4, 8, 2]; + let (attest, signature) = context + .quote( + loaded_ak, + Data::try_from(qualifying_data.clone()).unwrap(), + SignatureScheme::Null, + pcr_selection_list.clone(), + ) + .expect("Failed to get a quote"); + let (_update_counter, pcr_sel, pcr_data) = context + .execute_without_session(|ctx| ctx.pcr_read(pcr_selection_list)) + .unwrap(); + + assert!(no_tpm::checkquote( + &attest, + &signature, + &ak_rsa.out_public, + &Some((pcr_sel.clone(), pcr_data.clone())), + &qualifying_data + ) + .unwrap()); + } + + #[test] + fn checkquote_rsa_pss_sha1() { + checkquote_rsa( + RsaKeyBits::Rsa1024, + HashingAlgorithm::Sha1, + SignatureSchemeAlgorithm::RsaPss, + ); + } + + #[test] + fn checkquote_rsa_ssa_sha256() { + checkquote_rsa( + RsaKeyBits::Rsa2048, + HashingAlgorithm::Sha256, + SignatureSchemeAlgorithm::RsaSsa, + ); + } + + #[test] + fn checkquote_rsa_pss_sha384() { + checkquote_rsa( + RsaKeyBits::Rsa3072, + HashingAlgorithm::Sha384, + SignatureSchemeAlgorithm::RsaPss, + ); + } +}