Skip to content

Commit

Permalink
Error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
ameba23 committed Dec 17, 2024
1 parent d1f075f commit 02d0a61
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 43 deletions.
30 changes: 28 additions & 2 deletions crates/shared/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ pub trait AttestationHandler<AccountId> {
x25519_public_key: X25519PublicKey,
quote: Vec<u8>,
context: QuoteContext,
) -> Result<BoundedVecEncodedVerifyingKey, sp_runtime::DispatchError>;
) -> Result<BoundedVecEncodedVerifyingKey, VerifyQuoteError>;

/// Indicate to the attestation handler that a quote is desired.
///
Expand All @@ -184,9 +184,35 @@ impl<AccountId> AttestationHandler<AccountId> for () {
_x25519_public_key: X25519PublicKey,
_quote: Vec<u8>,
_context: QuoteContext,
) -> Result<BoundedVecEncodedVerifyingKey, sp_runtime::DispatchError> {
) -> Result<BoundedVecEncodedVerifyingKey, VerifyQuoteError> {
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,
}
34 changes: 17 additions & 17 deletions pallets/attestation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -209,28 +209,28 @@ pub mod pallet {
x25519_public_key: entropy_shared::X25519PublicKey,
quote: Vec<u8>,
context: QuoteContext,
) -> Result<entropy_shared::BoundedVecEncodedVerifyingKey, DispatchError> {
) -> Result<entropy_shared::BoundedVecEncodedVerifyingKey, VerifyQuoteError> {
// Check that we were expecting a quote from this validator by getting the associated
// nonce from PendingAttestations.
let nonce =
PendingAttestations::<T>::get(attestee).ok_or(Error::<T>::UnexpectedAttestation)?;
let nonce = PendingAttestations::<T>::get(attestee)
.ok_or(VerifyQuoteError::UnexpectedAttestation)?;

// Parse the quote (which internally verifies the attestation key signature)
let quote = Quote::from_bytes(&quote).map_err(|_| Error::<T>::BadQuote)?;
let quote = Quote::from_bytes(&quote).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::<T>::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::<T>::BadMrtdValue)?;
.map_err(|_| VerifyQuoteError::BadMrtdValue)?;
let accepted_mrtd_values = pallet_parameters::Pallet::<T>::accepted_mrtd_values();
ensure!(accepted_mrtd_values.contains(&mrtd_value), Error::<T>::BadMrtdValue);
ensure!(accepted_mrtd_values.contains(&mrtd_value), VerifyQuoteError::BadMrtdValue);

let pck = verify_pck_certificate_chain::<T>(&quote)?;

Expand All @@ -240,10 +240,10 @@ pub mod pallet {

Ok(BoundedVec::try_from(
encode_verifying_key(&pck)
.map_err(|_| Error::<T>::CannotEncodeVerifyingKey)?
.map_err(|_| VerifyQuoteError::CannotEncodeVerifyingKey)?
.to_vec(),
)
.map_err(|_| Error::<T>::CannotEncodeVerifyingKey)?)
.map_err(|_| VerifyQuoteError::CannotEncodeVerifyingKey)?)
}

fn request_quote(who: &T::AccountId, nonce: [u8; 32]) {
Expand All @@ -254,8 +254,8 @@ pub mod pallet {
#[cfg(feature = "production")]
fn verify_pck_certificate_chain<T: Config>(
quote: &Quote,
) -> Result<VerifyingKey, DispatchError> {
Ok(quote.verify().map_err(|_| Error::<T>::PckVerification)?)
) -> Result<VerifyingKey, VerifyQuoteError> {
Ok(quote.verify().map_err(|_| VerifyQuoteError::PckCertificateVerify)?)
}

/// A mock version of verifying the PCK certificate chain.
Expand All @@ -264,19 +264,19 @@ pub mod pallet {
#[cfg(not(feature = "production"))]
fn verify_pck_certificate_chain<T: Config>(
quote: &Quote,
) -> Result<VerifyingKey, DispatchError> {
) -> Result<VerifyingKey, VerifyQuoteError> {
let provisioning_certification_key =
quote.pck_cert_chain().map_err(|_| Error::<T>::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::<T>::CannotDecodeVerifyingKey)?,
.map_err(|_| VerifyQuoteError::CannotDecodeVerifyingKey)?,
)
.map_err(|_| Error::<T>::CannotDecodeVerifyingKey)?;
.map_err(|_| VerifyQuoteError::CannotDecodeVerifyingKey)?;

ensure!(
quote.verify_with_pck(&provisioning_certification_key).is_ok(),
Error::<T>::PckVerification
VerifyQuoteError::PckCertificateVerify
);
Ok(provisioning_certification_key)
}
Expand Down
69 changes: 45 additions & 24 deletions pallets/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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<T> From<pck::PckParseVerifyError> for Error<T> {
// fn from(error: pck::PckParseVerifyError) -> Self {
// match error {
// pck::PckParseVerifyError::Parse => Error::<T>::PckCertificateParse,
// pck::PckParseVerifyError::Verify => Error::<T>::PckCertificateVerify,
// pck::PckParseVerifyError::BadPublicKey => Error::<T>::PckCertificateBadPublicKey,
// pck::PckParseVerifyError::NoCertificate => Error::<T>::PckCertificateNoCertificate,
// }
// }
// }
impl<T> From<VerifyQuoteError> for Error<T> {
fn from(error: VerifyQuoteError) -> Self {
match error {
VerifyQuoteError::BadQuote => Error::<T>::BadQuote,
VerifyQuoteError::UnexpectedAttestation => Error::<T>::UnexpectedAttestation,
VerifyQuoteError::IncorrectInputData => Error::<T>::IncorrectInputData,
VerifyQuoteError::BadMrtdValue => Error::<T>::BadMrtdValue,
VerifyQuoteError::CannotEncodeVerifyingKey => Error::<T>::CannotEncodeVerifyingKey,
VerifyQuoteError::PckCertificateParse => Error::<T>::PckCertificateParse,
VerifyQuoteError::PckCertificateVerify => Error::<T>::PckCertificateVerify,
VerifyQuoteError::PckCertificateBadPublicKey => {
Error::<T>::PckCertificateBadPublicKey
},
VerifyQuoteError::PckCertificateNoCertificate => {
Error::<T>::PckCertificateNoCertificate
},
VerifyQuoteError::CannotDecodeVerifyingKey => Error::<T>::CannotDecodeVerifyingKey,
}
}
}

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
Expand Down Expand Up @@ -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!(
<T::AttestationHandler as entropy_shared::AttestationHandler<_>>::verify_quote(
&server_info.tss_account.clone(),
server_info.x25519_public_key,
quote,
QuoteContext::ChangeEndpoint,
)
.is_ok(),
Error::<T>::FailedAttestationCheck
);
<T::AttestationHandler as entropy_shared::AttestationHandler<_>>::verify_quote(
&server_info.tss_account.clone(),
server_info.x25519_public_key,
quote,
QuoteContext::ChangeEndpoint,
)?;

server_info.endpoint.clone_from(&endpoint);

Expand Down Expand Up @@ -495,7 +516,7 @@ pub mod pallet {
x25519_public_key,
quote,
QuoteContext::ChangeThresholdAccounts,
).map_err(|_| Error::<T>::FailedAttestationCheck)?;
)?;

server_info.tss_account = tss_account;
server_info.x25519_public_key = x25519_public_key;
Expand Down Expand Up @@ -631,7 +652,7 @@ pub mod pallet {
quote,
QuoteContext::Validate,
)
.map_err(|_| Error::<T>::FailedAttestationCheck)?;
.map_err(|e| <VerifyQuoteError as Into<Error<T>>>::into(e))?;

let server_info = ServerInfo::<T::AccountId> {
tss_account: joining_server_info.tss_account,
Expand Down

0 comments on commit 02d0a61

Please sign in to comment.