Skip to content
This repository has been archived by the owner on Feb 21, 2024. It is now read-only.

Commit

Permalink
fix(attestation-origin-validation): added origin validation when subm…
Browse files Browse the repository at this point in the history
…itting an attestation (#6)
  • Loading branch information
godenzim authored Sep 28, 2022
1 parent 4674cb7 commit 24387f7
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 105 deletions.
5 changes: 4 additions & 1 deletion pallets/acurast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.26" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.26" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.26" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.26" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.26" }

# Attestation
Expand All @@ -36,7 +37,8 @@ hex-literal = "0.3"

sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" }
sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" }

acurast-p256-crypto = { path = "../../p256-crypto" }

[features]
default = ["std"]
Expand All @@ -54,5 +56,6 @@ std = [
"sha2/std",
"num-bigint/std",
"ecdsa-vendored/std",
"sp-io/std",
]
try-runtime = [ "frame-support/try-runtime" ]
15 changes: 8 additions & 7 deletions pallets/acurast/src/attestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,19 +98,19 @@ const RSA_PBK: ObjectIdentifier = oid!(1, 2, 840, 113549, 1, 1, 1);
const ECDSA_PBK: ObjectIdentifier = oid!(1, 2, 840, 10045, 2, 1);

#[derive(Clone)]
enum PublicKey {
pub enum PublicKey {
RSA(RSAPbk),
ECDSA(ECDSACurve),
}

#[derive(Clone)]
struct RSAPbk {
pub struct RSAPbk {
exponent: BigUint,
modulus: BigUint,
}

#[derive(Clone)]
enum ECDSACurve {
pub enum ECDSACurve {
CurveP256(VerifyingKey),
CurveP384(p384::AffinePoint),
}
Expand Down Expand Up @@ -273,7 +273,7 @@ pub fn validate_certificate_chain_root(
/// - the next certificate's public key signs the next one and so on...
pub fn validate_certificate_chain<'a>(
chain: &'a CertificateChainInput,
) -> Result<(Vec<CertificateId>, TBSCertificate<'a>), ValidationError> {
) -> Result<(Vec<CertificateId>, TBSCertificate<'a>, PublicKey), ValidationError> {
let mut cert_ids = Vec::<CertificateId>::new();
let fold_result = chain.iter().try_fold::<_, _, Result<_, ValidationError>>(
(Option::<PublicKey>::None, Option::<Certificate>::None),
Expand All @@ -297,9 +297,10 @@ pub fn validate_certificate_chain<'a>(
)?;

let last_cert = fold_result.1.ok_or(ValidationError::ChainTooShort)?;
let last_cert_pbk = fold_result.0.ok_or(ValidationError::MissingPublicKey)?;

// if the chain is non-empty as ensured above, we know that we always have Some certificate in option
Ok((cert_ids, last_cert.tbs_certificate))
Ok((cert_ids, last_cert.tbs_certificate, last_cert_pbk))
}

/// The list of trusted root certificates, as decoded bytes arrays. [Source](https://developer.android.com/training/articles/security-key-attestation#root_certificate)
Expand Down Expand Up @@ -369,7 +370,7 @@ mod tests {
];
let decoded_chain = decode_certificate_chain(&chain);
validate_certificate_chain_root(&decoded_chain)?;
let (_, cert) = validate_certificate_chain(&decoded_chain)?;
let (_, cert, _) = validate_certificate_chain(&decoded_chain)?;
let key_description = extract_attestation(cert.extensions)?;
match &key_description {
KeyDescription::V100(key_description) => {
Expand All @@ -391,7 +392,7 @@ mod tests {
];
let decoded_chain = decode_certificate_chain(&chain);
validate_certificate_chain_root(&decoded_chain).expect("validating root failed");
let (_, cert) =
let (_, cert, _) =
validate_certificate_chain(&decoded_chain).expect("validating chain failed");
let key_description = extract_attestation(cert.extensions)?;
match &key_description {
Expand Down
1 change: 1 addition & 0 deletions pallets/acurast/src/attestation/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub enum ValidationError {
ParseP256PublicKey,
ParseP384PublicKey,
MissingECDSAAlgorithmTyp,
MissingPublicKey,
InvalidSignatureEncoding,
InvalidSignature,
UnsupportedSignatureAlgorithm,
Expand Down
12 changes: 8 additions & 4 deletions pallets/acurast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,16 @@ pub mod pallet {
CannotGetCertificateId,
/// Failed to convert the attestation to its bounded type.
AttestationToBoundedTypeConversionFailed,
/// Timestamp error
/// Timestamp error.
FailedTimestampConversion,
/// Certificate was revoked
/// Certificate was revoked.
RevokedCertificate,
/// Origin is not allowed to update the certificate revocation list
/// Origin is not allowed to update the certificate revocation list.
CertificateRevocationListUpdateNotAllowed,
/// The attestation was issued for an unsupported public key type.
UnsupportedAttestationPublicKeyType,
/// The submitted attestation public key does not match the source.
AttestationPublicKeyDoesNotMatchSource,
}

#[pallet::hooks]
Expand Down Expand Up @@ -302,7 +306,7 @@ pub mod pallet {
Error::<T>::CertificateChainTooShort,
);

let attestation = validate_and_extract_attestation::<T>(&attestation_chain)?;
let attestation = validate_and_extract_attestation::<T>(&who, &attestation_chain)?;

ensure_not_expired::<T>(&attestation)?;
ensure_not_revoked::<T>(&attestation)?;
Expand Down
32 changes: 28 additions & 4 deletions pallets/acurast/src/mock.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use hex_literal::hex;
use sp_io;
use sp_runtime::{testing::Header, traits::IdentityLookup};
use sp_runtime::{testing::Header, traits::IdentityLookup, AccountId32};

use crate::{AttestationChain, Fulfillment, JobRegistration, Script, SerialNumber};

type AccountId = u64;
type AccountId = AccountId32;
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;

Expand All @@ -31,7 +31,7 @@ impl frame_system::Config for Test {
type Call = Call;
type Hash = sp_core::H256;
type Hashing = ::sp_runtime::traits::BlakeTwo256;
type AccountId = u64;
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = Event;
Expand All @@ -50,7 +50,7 @@ impl frame_system::Config for Test {
frame_support::parameter_types! {
pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights::simple_max(1024);
pub const MinimumPeriod: u64 = 6000;
pub AllowedRevocationListUpdate: Vec<AccountId> = vec![1];
pub AllowedRevocationListUpdate: Vec<AccountId> = vec![alice_account_id()];
pub static ExistentialDeposit: u64 = 0;
}

Expand Down Expand Up @@ -223,3 +223,27 @@ pub fn invalid_attestation_chain_3() -> AttestationChain {
pub fn cert_serial_number() -> SerialNumber {
hex!("15905857467176635834").to_vec().try_into().unwrap()
}

pub fn processor_account_id() -> AccountId {
hex!("b8bc25a2b4c0386b8892b43e435b71fe11fa50533935f027949caf04bcce4694").into()
}

pub fn alice_account_id() -> AccountId {
[0; 32].into()
}

pub fn bob_account_id() -> AccountId {
[1; 32].into()
}

pub fn charlie_account_id() -> AccountId {
[2; 32].into()
}

pub fn dave_account_id() -> AccountId {
[3; 32].into()
}

pub fn eve_account_id() -> AccountId {
[4; 32].into()
}
Loading

0 comments on commit 24387f7

Please sign in to comment.