diff --git a/crates/shared/src/types.rs b/crates/shared/src/types.rs index 95a9d37cf..948fb713d 100644 --- a/crates/shared/src/types.rs +++ b/crates/shared/src/types.rs @@ -167,7 +167,7 @@ pub trait AttestationHandler { x25519_public_key: X25519PublicKey, quote: Vec, context: QuoteContext, - ) -> Result; + ) -> Result; /// Indicate to the attestation handler that a quote is desired. /// @@ -184,9 +184,35 @@ impl AttestationHandler for () { _x25519_public_key: X25519PublicKey, _quote: Vec, _context: QuoteContext, - ) -> Result { + ) -> Result { Ok(sp_runtime::BoundedVec::new()) } fn request_quote(_attestee: &AccountId, _nonce: [u8; 32]) {} } + +/// An error when verifying a quote +#[cfg(not(feature = "wasm"))] +#[derive(Eq, PartialEq)] +pub enum VerifyQuoteError { + /// Quote could not be parsed or verified + BadQuote, + /// Attestation extrinsic submitted when not requested + UnexpectedAttestation, + /// Hashed input data does not match what was expected + IncorrectInputData, + /// Unacceptable VM image running + BadMrtdValue, + /// Cannot encode verifying key (PCK) + CannotEncodeVerifyingKey, + /// Cannot decode verifying key (PCK) + CannotDecodeVerifyingKey, + /// PCK certificate chain cannot be parsed + PckCertificateParse, + /// PCK certificate chain cannot be verified + PckCertificateVerify, + /// PCK certificate chain public key is not well formed + PckCertificateBadPublicKey, + /// Pck certificate could not be extracted from quote + PckCertificateNoCertificate, +} diff --git a/pallets/attestation/src/lib.rs b/pallets/attestation/src/lib.rs index 778529341..801aa1b11 100644 --- a/pallets/attestation/src/lib.rs +++ b/pallets/attestation/src/lib.rs @@ -47,7 +47,7 @@ mod tests; #[frame_support::pallet] pub mod pallet { - use entropy_shared::{AttestationHandler, QuoteContext, QuoteInputData}; + use entropy_shared::{AttestationHandler, QuoteContext, QuoteInputData, VerifyQuoteError}; use frame_support::pallet_prelude::*; use frame_support::traits::Randomness; use frame_system::pallet_prelude::*; @@ -209,28 +209,28 @@ pub mod pallet { x25519_public_key: entropy_shared::X25519PublicKey, quote: Vec, context: QuoteContext, - ) -> Result { + ) -> Result { // Check that we were expecting a quote from this validator by getting the associated // nonce from PendingAttestations. - let nonce = - PendingAttestations::::get(attestee).ok_or(Error::::UnexpectedAttestation)?; + let nonce = PendingAttestations::::get(attestee) + .ok_or(VerifyQuoteError::UnexpectedAttestation)?; // Parse the quote (which internally verifies the attestation key signature) - let quote = Quote::from_bytes("e).map_err(|_| Error::::BadQuote)?; + let quote = Quote::from_bytes("e).map_err(|_| VerifyQuoteError::BadQuote)?; // Check report input data matches the nonce, TSS details and block number let expected_input_data = QuoteInputData::new(attestee, x25519_public_key, nonce, context); ensure!( quote.report_input_data() == expected_input_data.0, - Error::::IncorrectInputData + VerifyQuoteError::IncorrectInputData ); // Check build-time measurement matches a current-supported release of entropy-tss let mrtd_value = BoundedVec::try_from(quote.mrtd().to_vec()) - .map_err(|_| Error::::BadMrtdValue)?; + .map_err(|_| VerifyQuoteError::BadMrtdValue)?; let accepted_mrtd_values = pallet_parameters::Pallet::::accepted_mrtd_values(); - ensure!(accepted_mrtd_values.contains(&mrtd_value), Error::::BadMrtdValue); + ensure!(accepted_mrtd_values.contains(&mrtd_value), VerifyQuoteError::BadMrtdValue); let pck = verify_pck_certificate_chain::("e)?; @@ -240,10 +240,10 @@ pub mod pallet { Ok(BoundedVec::try_from( encode_verifying_key(&pck) - .map_err(|_| Error::::CannotEncodeVerifyingKey)? + .map_err(|_| VerifyQuoteError::CannotEncodeVerifyingKey)? .to_vec(), ) - .map_err(|_| Error::::CannotEncodeVerifyingKey)?) + .map_err(|_| VerifyQuoteError::CannotEncodeVerifyingKey)?) } fn request_quote(who: &T::AccountId, nonce: [u8; 32]) { @@ -254,8 +254,8 @@ pub mod pallet { #[cfg(feature = "production")] fn verify_pck_certificate_chain( quote: &Quote, - ) -> Result { - Ok(quote.verify().map_err(|_| Error::::PckVerification)?) + ) -> Result { + Ok(quote.verify().map_err(|_| VerifyQuoteError::PckCertificateVerify)?) } /// A mock version of verifying the PCK certificate chain. @@ -264,19 +264,19 @@ pub mod pallet { #[cfg(not(feature = "production"))] fn verify_pck_certificate_chain( quote: &Quote, - ) -> Result { + ) -> Result { let provisioning_certification_key = - quote.pck_cert_chain().map_err(|_| Error::::NoPckCertChain)?; + quote.pck_cert_chain().map_err(|_| VerifyQuoteError::PckCertificateNoCertificate)?; let provisioning_certification_key = tdx_quote::decode_verifying_key( &provisioning_certification_key .try_into() - .map_err(|_| Error::::CannotDecodeVerifyingKey)?, + .map_err(|_| VerifyQuoteError::CannotDecodeVerifyingKey)?, ) - .map_err(|_| Error::::CannotDecodeVerifyingKey)?; + .map_err(|_| VerifyQuoteError::CannotDecodeVerifyingKey)?; ensure!( quote.verify_with_pck(&provisioning_certification_key).is_ok(), - Error::::PckVerification + VerifyQuoteError::PckCertificateVerify ); Ok(provisioning_certification_key) } diff --git a/pallets/staking/src/lib.rs b/pallets/staking/src/lib.rs index ba0e52092..cc279fbf0 100644 --- a/pallets/staking/src/lib.rs +++ b/pallets/staking/src/lib.rs @@ -58,7 +58,7 @@ use sp_staking::SessionIndex; #[frame_support::pallet] pub mod pallet { use entropy_shared::{ - QuoteContext, ValidatorInfo, X25519PublicKey, MAX_SIGNERS, + QuoteContext, ValidatorInfo, VerifyQuoteError, X25519PublicKey, MAX_SIGNERS, PREGENERATED_NETWORK_VERIFYING_KEY, TEST_RESHARE_BLOCK_NUMBER, VERIFICATION_KEY_LENGTH, }; use frame_support::{ @@ -339,23 +339,48 @@ pub mod pallet { NoUnnominatingWhenSigner, NoUnnominatingWhenNextSigner, NoChangingThresholdAccountWhenSigner, + /// Quote could not be parsed or verified + BadQuote, + /// Attestation extrinsic submitted when not requested + UnexpectedAttestation, + /// Hashed input data does not match what was expected + IncorrectInputData, + /// Unacceptable VM image running + BadMrtdValue, + /// Cannot encode verifying key (PCK) + CannotEncodeVerifyingKey, + /// Cannot decode verifying key (PCK) + CannotDecodeVerifyingKey, + /// PCK certificate chain cannot be parsed PckCertificateParse, + /// PCK certificate chain cannot be verified PckCertificateVerify, + /// PCK certificate chain public key is not well formed PckCertificateBadPublicKey, + /// Pck certificate could not be extracted from quote PckCertificateNoCertificate, - FailedAttestationCheck, } - // impl From for Error { - // fn from(error: pck::PckParseVerifyError) -> Self { - // match error { - // pck::PckParseVerifyError::Parse => Error::::PckCertificateParse, - // pck::PckParseVerifyError::Verify => Error::::PckCertificateVerify, - // pck::PckParseVerifyError::BadPublicKey => Error::::PckCertificateBadPublicKey, - // pck::PckParseVerifyError::NoCertificate => Error::::PckCertificateNoCertificate, - // } - // } - // } + impl From for Error { + fn from(error: VerifyQuoteError) -> Self { + match error { + VerifyQuoteError::BadQuote => Error::::BadQuote, + VerifyQuoteError::UnexpectedAttestation => Error::::UnexpectedAttestation, + VerifyQuoteError::IncorrectInputData => Error::::IncorrectInputData, + VerifyQuoteError::BadMrtdValue => Error::::BadMrtdValue, + VerifyQuoteError::CannotEncodeVerifyingKey => Error::::CannotEncodeVerifyingKey, + VerifyQuoteError::PckCertificateParse => Error::::PckCertificateParse, + VerifyQuoteError::PckCertificateVerify => Error::::PckCertificateVerify, + VerifyQuoteError::PckCertificateBadPublicKey => { + Error::::PckCertificateBadPublicKey + }, + VerifyQuoteError::PckCertificateNoCertificate => { + Error::::PckCertificateNoCertificate + }, + VerifyQuoteError::CannotDecodeVerifyingKey => Error::::CannotDecodeVerifyingKey, + } + } + } #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] @@ -422,16 +447,12 @@ pub mod pallet { if let Some(server_info) = maybe_server_info { // Before we modify the `server_info`, we want to check that the validator is // still running TDX hardware. - ensure!( - >::verify_quote( - &server_info.tss_account.clone(), - server_info.x25519_public_key, - quote, - QuoteContext::ChangeEndpoint, - ) - .is_ok(), - Error::::FailedAttestationCheck - ); + >::verify_quote( + &server_info.tss_account.clone(), + server_info.x25519_public_key, + quote, + QuoteContext::ChangeEndpoint, + )?; server_info.endpoint.clone_from(&endpoint); @@ -495,7 +516,7 @@ pub mod pallet { x25519_public_key, quote, QuoteContext::ChangeThresholdAccounts, - ).map_err(|_| Error::::FailedAttestationCheck)?; + )?; server_info.tss_account = tss_account; server_info.x25519_public_key = x25519_public_key; @@ -631,7 +652,7 @@ pub mod pallet { quote, QuoteContext::Validate, ) - .map_err(|_| Error::::FailedAttestationCheck)?; + .map_err(|e| >>::into(e))?; let server_info = ServerInfo:: { tss_account: joining_server_info.tss_account,