Skip to content

Commit d027a6a

Browse files
committed
pruntime: Don't change cpu_svn while handover key
1 parent 173ff5d commit d027a6a

File tree

7 files changed

+143
-54
lines changed

7 files changed

+143
-54
lines changed

crates/phactory/api/proto

crates/phactory/pal/src/lib.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! Platform abstraction layer for Trusted Execution Environments
22
3+
use core::time::Duration;
34
use std::fmt::Debug;
45
use std::path::Path;
5-
use core::time::Duration;
66

77
use phala_types::AttestationProvider;
88

@@ -11,12 +11,26 @@ pub use phactory_api::prpc::MemoryUsage;
1111
pub trait ErrorType: Debug + Into<anyhow::Error> {}
1212
impl<T: Debug + Into<anyhow::Error>> ErrorType for T {}
1313

14+
pub struct UnsealedData {
15+
pub data: Vec<u8>,
16+
pub svn: Vec<u8>,
17+
}
18+
1419
pub trait Sealing {
1520
type SealError: ErrorType;
1621
type UnsealError: ErrorType;
1722

18-
fn seal_data(&self, path: impl AsRef<Path>, data: &[u8]) -> Result<(), Self::SealError>;
19-
fn unseal_data(&self, path: impl AsRef<Path>) -> Result<Option<Vec<u8>>, Self::UnsealError>;
23+
fn current_svn(&self) -> Result<Vec<u8>, Self::SealError>;
24+
fn seal_data(
25+
&self,
26+
path: impl AsRef<Path>,
27+
data: &[u8],
28+
svn: Option<&[u8]>,
29+
) -> Result<(), Self::SealError>;
30+
fn unseal_data(
31+
&self,
32+
path: impl AsRef<Path>,
33+
) -> Result<Option<UnsealedData>, Self::UnsealError>;
2034
}
2135

2236
pub trait RA {

crates/phactory/src/lib.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -338,14 +338,21 @@ impl<Platform: pal::Platform> Phactory<Platform> {
338338
predefined_identity_key: Option<sr25519::Pair>,
339339
) -> Result<PersistentRuntimeData> {
340340
let data = if let Some(identity_sk) = predefined_identity_key {
341-
self.save_runtime_data(genesis_block_hash, para_id, identity_sk, false, true)?
341+
self.save_runtime_data(genesis_block_hash, para_id, identity_sk, false, true, None)?
342342
} else {
343343
match Self::load_runtime_data(&self.platform, &self.args.sealing_path) {
344344
Ok(data) => data,
345345
Err(Error::PersistentRuntimeNotFound) => {
346346
warn!("Persistent data not found.");
347347
let identity_sk = new_sr25519_key();
348-
self.save_runtime_data(genesis_block_hash, para_id, identity_sk, true, false)?
348+
self.save_runtime_data(
349+
genesis_block_hash,
350+
para_id,
351+
identity_sk,
352+
true,
353+
false,
354+
None,
355+
)?
349356
}
350357
Err(err) => return Err(anyhow!("Failed to load persistent data: {}", err)),
351358
}
@@ -375,6 +382,7 @@ impl<Platform: pal::Platform> Phactory<Platform> {
375382
sr25519_sk: sr25519::Pair,
376383
trusted_sk: bool,
377384
dev_mode: bool,
385+
svn: Option<&[u8]>,
378386
) -> Result<PersistentRuntimeData> {
379387
// Put in PresistentRuntimeData
380388
let sk = sr25519_sk.dump_secret_key();
@@ -392,7 +400,7 @@ impl<Platform: pal::Platform> Phactory<Platform> {
392400
info!("Length of encoded slice: {}", encoded_vec.len());
393401
let filepath = PathBuf::from(&self.args.sealing_path).join(RUNTIME_SEALED_DATA_FILE);
394402
self.platform
395-
.seal_data(filepath, &encoded_vec)
403+
.seal_data(filepath, &encoded_vec, svn)
396404
.map_err(Into::into)
397405
.context("Failed to seal runtime data")?;
398406
info!("Persistent Runtime Data V2 saved");
@@ -401,22 +409,31 @@ impl<Platform: pal::Platform> Phactory<Platform> {
401409
}
402410

403411
/// Loads the persistent runtime data from the sealing path
404-
fn persistent_runtime_data(&self) -> Result<PersistentRuntimeData, Error> {
405-
Self::load_runtime_data(&self.platform, &self.args.sealing_path)
412+
fn load_persistent_runtime_data_with_svn(
413+
&self,
414+
) -> Result<(PersistentRuntimeData, Vec<u8>), Error> {
415+
Self::load_runtime_data_with_svn(&self.platform, &self.args.sealing_path)
406416
}
407417

408418
fn load_runtime_data(
409419
platform: &Platform,
410420
sealing_path: &str,
411421
) -> Result<PersistentRuntimeData, Error> {
422+
Self::load_runtime_data_with_svn(platform, sealing_path).map(|(data, _)| data)
423+
}
424+
425+
fn load_runtime_data_with_svn(
426+
platform: &Platform,
427+
sealing_path: &str,
428+
) -> Result<(PersistentRuntimeData, Vec<u8>), Error> {
412429
let filepath = PathBuf::from(sealing_path).join(RUNTIME_SEALED_DATA_FILE);
413-
let data = platform
430+
let pal::UnsealedData { data, svn } = platform
414431
.unseal_data(filepath)
415432
.map_err(Into::into)?
416433
.ok_or(Error::PersistentRuntimeNotFound)?;
417434
let data: RuntimeDataSeal = Decode::decode(&mut &data[..]).map_err(Error::DecodeError)?;
418435
match data {
419-
RuntimeDataSeal::V1(data) => Ok(data),
436+
RuntimeDataSeal::V1(data) => Ok((data, svn)),
420437
}
421438
}
422439

crates/phactory/src/prpc_service.rs

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ use phala_pallets::utils::attestation::{validate as validate_attestation_report,
2929
use phala_types::contract::contract_id_preimage;
3030
use phala_types::{
3131
contract, messaging::EncryptedKey, wrap_content_to_sign, AttestationReport,
32-
ChallengeHandlerInfo, EncryptedWorkerKey, HandoverChallenge, SignedContentType,
33-
VersionedWorkerEndpoints, WorkerEndpointPayload, WorkerPublicKey, WorkerRegistrationInfoV2,
32+
ChallengeHandlerInfo, EncryptedWorkerKeyV0, EncryptedWorkerKeyV1, HandoverChallenge,
33+
SignedContentType, VersionedWorkerEndpoints, WorkerEndpointPayload, WorkerPublicKey,
34+
WorkerRegistrationInfoV2,
3435
};
3536
use sp_application_crypto::UncheckedFrom;
3637
use tracing::{error, info};
@@ -1637,7 +1638,9 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> PhactoryApi for Rpc
16371638
// Share the key with attestation
16381639
let ecdh_pubkey = challenge_handler.ecdh_pubkey;
16391640
let iv = crate::generate_random_iv();
1640-
let runtime_data = phactory.persistent_runtime_data().map_err(from_display)?;
1641+
let (runtime_data, svn) = phactory
1642+
.load_persistent_runtime_data_with_svn()
1643+
.map_err(from_display)?;
16411644
let (my_identity_key, _) = runtime_data.decode_keys();
16421645
let (ecdh_pubkey, encrypted_key) = key_share::encrypt_secret_to(
16431646
&my_identity_key,
@@ -1652,21 +1655,22 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> PhactoryApi for Rpc
16521655
encrypted_key,
16531656
iv,
16541657
};
1655-
let runtime_state = phactory.runtime_state()?;
1656-
let genesis_block_hash = runtime_state.genesis_block_hash;
1657-
let encrypted_worker_key = EncryptedWorkerKey {
1658+
let genesis_block_hash = runtime_data.genesis_block_hash;
1659+
let encrypted_worker_key = EncryptedWorkerKeyV1 {
16581660
genesis_block_hash,
1659-
para_id: runtime_state.para_id,
1661+
para_id: runtime_data.para_id,
16601662
dev_mode,
16611663
encrypted_key,
1664+
svn,
16621665
};
16631666

1664-
let worker_key_hash = sp_core::hashing::blake2_256(&encrypted_worker_key.encode());
1667+
let encoded_worker_key = encrypted_worker_key.encode();
1668+
let payload_hash = sp_core::hashing::blake2_256(&encoded_worker_key);
16651669
let attestation = if !dev_mode && in_sgx {
16661670
Some(create_attestation_report_on(
16671671
&phactory.platform,
16681672
attestation_provider,
1669-
&worker_key_hash,
1673+
&payload_hash,
16701674
phactory.args.ra_timeout,
16711675
phactory.args.ra_max_retries,
16721676
)?)
@@ -1675,10 +1679,11 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> PhactoryApi for Rpc
16751679
None
16761680
};
16771681

1678-
Ok(pb::HandoverWorkerKey::new(
1679-
encrypted_worker_key,
1682+
Ok(pb::HandoverWorkerKey {
16801683
attestation,
1681-
))
1684+
encoded_worker_key_v0: None,
1685+
encoded_worker_key_v1: Some(encoded_worker_key),
1686+
})
16821687
}
16831688

16841689
// WorkerKey Handover Client
@@ -1741,12 +1746,37 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> PhactoryApi for Rpc
17411746

17421747
async fn handover_receive(&mut self, request: pb::HandoverWorkerKey) -> RpcResult<()> {
17431748
let mut phactory = self.lock_phactory(false, true)?;
1744-
let encrypted_worker_key = request.decode_worker_key().map_err(from_display)?;
1745-
1746-
let dev_mode = encrypted_worker_key.dev_mode;
1749+
let received_key;
1750+
let payload_hash;
1751+
match (
1752+
&request.encoded_worker_key_v0,
1753+
&request.encoded_worker_key_v1,
1754+
) {
1755+
(None, None) => return Err(from_display("No worker key found")),
1756+
(Some(_), Some(_)) => return Err(from_display("Both v0 and v1 worker key found")),
1757+
(Some(encoded), None) => {
1758+
payload_hash = sp_core::hashing::blake2_256(encoded);
1759+
let v0 = EncryptedWorkerKeyV0::decode(&mut &encoded[..])
1760+
.map_err(|_| from_display("Decode worker key failed"))?;
1761+
received_key = EncryptedWorkerKeyV1 {
1762+
genesis_block_hash: v0.genesis_block_hash,
1763+
para_id: v0.para_id,
1764+
dev_mode: v0.dev_mode,
1765+
encrypted_key: v0.encrypted_key,
1766+
// If the version of the key is v0, it must from pRuntime v2.0 or v2.1, which never load the
1767+
// keys with a different svn. Thus, we can safely set the svn to current svn.
1768+
svn: phactory.platform.current_svn().map_err(from_debug)?,
1769+
};
1770+
}
1771+
(None, Some(encoded)) => {
1772+
payload_hash = sp_core::hashing::blake2_256(encoded);
1773+
received_key = EncryptedWorkerKeyV1::decode(&mut &encoded[..])
1774+
.map_err(|_| from_display("Decode worker key failed"))?;
1775+
}
1776+
}
1777+
let dev_mode = received_key.dev_mode;
17471778
// verify RA report
17481779
if !dev_mode {
1749-
let worker_key_hash = sp_core::hashing::blake2_256(&encrypted_worker_key.encode());
17501780
let raw_attestation = request
17511781
.attestation
17521782
.ok_or_else(|| from_display("Server attestation not found"))?;
@@ -1755,7 +1785,7 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> PhactoryApi for Rpc
17551785
.map_err(|_| from_display("Decode server attestation failed"))?;
17561786
validate_attestation_report(
17571787
attn_to_validate,
1758-
&worker_key_hash,
1788+
&payload_hash,
17591789
now(),
17601790
false,
17611791
vec![],
@@ -1766,7 +1796,7 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> PhactoryApi for Rpc
17661796
info!("Skip server RA report check for dev mode key");
17671797
}
17681798

1769-
let encrypted_key = encrypted_worker_key.encrypted_key;
1799+
let encrypted_key = received_key.encrypted_key;
17701800
let my_ecdh_key = phactory
17711801
.handover_ecdh_key
17721802
.as_ref()
@@ -1782,11 +1812,12 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> PhactoryApi for Rpc
17821812
// only seal if the key is successfully updated
17831813
phactory
17841814
.save_runtime_data(
1785-
encrypted_worker_key.genesis_block_hash,
1786-
encrypted_worker_key.para_id,
1815+
received_key.genesis_block_hash,
1816+
received_key.para_id,
17871817
sr25519::Pair::restore_from_secret_key(&secret),
17881818
false, // we are not sure whether this key is injected
17891819
dev_mode,
1820+
Some(&received_key.svn),
17901821
)
17911822
.map_err(from_display)?;
17921823

crates/phactory/src/system/master_key.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use sp_core::sr25519;
77

88
use phala_crypto::sr25519::{Signature, Signing, Sr25519SecretKey};
99

10-
use crate::pal::Sealing;
10+
use crate::pal::{Sealing, UnsealedData};
1111

1212
/// Master key filepath
1313
pub const MASTER_KEY_FILE: &str = "master_key.seal";
@@ -66,7 +66,7 @@ pub fn seal(
6666
info!("Seal master key to {}", filepath.as_path().display());
6767
// TODO.shelven: seal with identity key so the newly handovered pRuntime do not need to do an extra sync to get master
6868
// key
69-
sys.seal_data(filepath, &data.encode())
69+
sys.seal_data(filepath, &data.encode(), None)
7070
.expect("Seal master key failed");
7171
}
7272

@@ -84,7 +84,7 @@ pub fn try_unseal(
8484
) -> Vec<RotatedMasterKey> {
8585
let filepath = master_key_file_path(&sealing_path);
8686
info!("Unseal master key from {}", filepath.as_path().display());
87-
let sealed_data = match sys
87+
let UnsealedData { data, .. } = match sys
8888
.unseal_data(&filepath)
8989
.expect("Unseal master key failed")
9090
{
@@ -96,7 +96,7 @@ pub fn try_unseal(
9696
};
9797

9898
let versioned_data =
99-
MasterKeySeal::decode(&mut &sealed_data[..]).expect("Failed to decode sealed master key");
99+
MasterKeySeal::decode(&mut &data[..]).expect("Failed to decode sealed master key");
100100

101101
#[allow(clippy::infallible_destructuring_match)]
102102
let secrets = match versioned_data {

crates/phala-types/src/lib.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,13 +530,22 @@ pub struct ChallengeHandlerInfo<BlockNumber> {
530530
}
531531

532532
#[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, TypeInfo)]
533-
pub struct EncryptedWorkerKey {
533+
pub struct EncryptedWorkerKeyV0 {
534534
pub genesis_block_hash: H256,
535535
pub para_id: u32,
536536
pub dev_mode: bool,
537537
pub encrypted_key: messaging::EncryptedKey,
538538
}
539539

540+
#[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, TypeInfo)]
541+
pub struct EncryptedWorkerKeyV1 {
542+
pub genesis_block_hash: H256,
543+
pub para_id: u32,
544+
pub dev_mode: bool,
545+
pub encrypted_key: messaging::EncryptedKey,
546+
pub svn: Vec<u8>,
547+
}
548+
540549
#[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, TypeInfo)]
541550
pub struct WorkerRegistrationInfo<AccountId> {
542551
pub version: u32,

0 commit comments

Comments
 (0)