diff --git a/tee-worker/omni-executor/executor-primitives/src/lib.rs b/tee-worker/omni-executor/executor-primitives/src/lib.rs index ed441b75ab..3a7dd0529d 100644 --- a/tee-worker/omni-executor/executor-primitives/src/lib.rs +++ b/tee-worker/omni-executor/executor-primitives/src/lib.rs @@ -18,9 +18,11 @@ pub mod signature; pub mod utils; pub use heima_primitives::{ omni_account::{MemberAccount, OmniAccountAuthType}, - AccountId, BlockNumber, Hash, Identity, Nonce, ShardIdentifier, Web2IdentityType, + AccountId, BlockNumber, Hash, Identity, Nonce, Web2IdentityType, }; +pub type MrEnclave = Hash; + use parity_scale_codec::{Decode, Encode}; use std::fmt::Debug; diff --git a/tee-worker/omni-executor/rpc-server/src/authentication.rs b/tee-worker/omni-executor/rpc-server/src/authentication.rs index 2218cea43c..62de2674b6 100644 --- a/tee-worker/omni-executor/rpc-server/src/authentication.rs +++ b/tee-worker/omni-executor/rpc-server/src/authentication.rs @@ -2,8 +2,8 @@ use crate::server::RpcContext; use executor_core::native_call::NativeCall; use executor_crypto::hashing::blake2_256; use executor_primitives::{ - signature::HeimaMultiSignature, utils::hex::hex_encode, Identity, OmniAccountAuthType, - ShardIdentifier, Web2IdentityType, + signature::HeimaMultiSignature, utils::hex::hex_encode, Identity, MrEnclave, + OmniAccountAuthType, Web2IdentityType, }; use executor_storage::{OAuth2StateVerifierStorage, Storage, VerificationCodeStorage}; use heima_authentication::auth_token::{AuthTokenValidator, Validation}; @@ -89,13 +89,11 @@ pub fn verify_web3_authentication( signature: &HeimaMultiSignature, call: &NativeCall, nonce: u32, - mrenclave: &[u8; 32], - shard: &ShardIdentifier, + mrenclave: MrEnclave, ) -> Result<(), AuthenticationError> { let mut payload = call.encode(); payload.append(&mut nonce.encode()); payload.append(&mut mrenclave.encode()); - payload.append(&mut shard.encode()); // The signature should be valid in either case: // 1. blake2_256(payload) diff --git a/tee-worker/omni-executor/rpc-server/src/error_code.rs b/tee-worker/omni-executor/rpc-server/src/error_code.rs index 126f58fccc..3eba432d26 100644 --- a/tee-worker/omni-executor/rpc-server/src/error_code.rs +++ b/tee-worker/omni-executor/rpc-server/src/error_code.rs @@ -2,7 +2,9 @@ // see https://www.jsonrpc.org/specification#error_object pub const INVALID_AES_REQUEST_CODE: i32 = -32000; -pub const INVALID_SHARD_CODE: i32 = -32001; -pub const REQUEST_DECRYPTION_FAILED_CODE: i32 = -32002; -pub const INVALID_AUTHENTICATED_CALL_CODE: i32 = -32003; -pub const AUTHENTICATION_FAILED_CODE: i32 = -32004; +pub const INVALID_PLAIN_REQUEST_CODE: i32 = -32001; +pub const INVALID_MRENCLAVE_CODE: i32 = -32002; +pub const REQUEST_DECRYPTION_FAILED_CODE: i32 = -32003; +pub const INVALID_AUTHENTICATED_CALL_CODE: i32 = -32004; +pub const AUTHENTICATION_FAILED_CODE: i32 = -32005; +pub const INVALID_NATIVE_CALL_AUTHENTICATED_CODE: i32 = -32006; diff --git a/tee-worker/omni-executor/rpc-server/src/lib.rs b/tee-worker/omni-executor/rpc-server/src/lib.rs index 98f1de4b88..6a6dda3be7 100644 --- a/tee-worker/omni-executor/rpc-server/src/lib.rs +++ b/tee-worker/omni-executor/rpc-server/src/lib.rs @@ -1,6 +1,7 @@ mod authentication; mod error_code; mod methods; +mod native_call_authenticated; mod request; mod server; mod shielding_key; diff --git a/tee-worker/omni-executor/rpc-server/src/methods/mod.rs b/tee-worker/omni-executor/rpc-server/src/methods/mod.rs index 354914a5f7..45efa80175 100644 --- a/tee-worker/omni-executor/rpc-server/src/methods/mod.rs +++ b/tee-worker/omni-executor/rpc-server/src/methods/mod.rs @@ -2,6 +2,7 @@ mod get_oauth2_google_authorization_url; mod get_shielding_key; mod request_email_verification_code; mod submit_aes_request; +mod submit_plain_request; use crate::server::RpcContext; use get_oauth2_google_authorization_url::register_get_oauth2_google_authorization_url; @@ -10,6 +11,7 @@ use jsonrpsee::RpcModule; use parentchain_rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory}; use request_email_verification_code::register_request_email_verification_code; use submit_aes_request::register_submit_aes_request; +use submit_plain_request::register_submit_plain_request; pub fn register_methods< AccountId: Send + Sync + 'static, @@ -23,4 +25,5 @@ pub fn register_methods< register_submit_aes_request(module); register_request_email_verification_code(module); register_get_oauth2_google_authorization_url(module); + register_submit_plain_request(module); } diff --git a/tee-worker/omni-executor/rpc-server/src/methods/submit_aes_request.rs b/tee-worker/omni-executor/rpc-server/src/methods/submit_aes_request.rs index 2250313503..e25600a9a0 100644 --- a/tee-worker/omni-executor/rpc-server/src/methods/submit_aes_request.rs +++ b/tee-worker/omni-executor/rpc-server/src/methods/submit_aes_request.rs @@ -1,16 +1,13 @@ use crate::{ - authentication::{ - verify_auth_token_authentication, verify_email_authentication, - verify_oauth2_authentication, verify_web3_authentication, Authentication, - }, error_code::*, + native_call_authenticated::{verify_native_call_authenticated, NativeCallAuthenticated}, request::{AesRequest, DecryptableRequest}, server::RpcContext, }; use executor_core::native_call::NativeCall; use executor_primitives::{ utils::hex::{FromHexPrefixed, ToHexPrefixed}, - Nonce, OmniAccountAuthType, + OmniAccountAuthType, }; use jsonrpsee::{ types::{ErrorCode, ErrorObject}, @@ -18,17 +15,10 @@ use jsonrpsee::{ }; use native_task_handler::NativeTask; use parentchain_rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory}; -use parity_scale_codec::{Decode, Encode}; -use std::{fmt::Debug, sync::Arc}; +use parity_scale_codec::Decode; +use std::sync::Arc; use tokio::{runtime::Handle, sync::oneshot, task}; -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] -pub struct AuthenticatedCall { - pub call: NativeCall, - pub nonce: Nonce, - pub authentication: Authentication, -} - pub fn register_submit_aes_request< AccountId: Send + Sync + 'static, Header: Send + Sync + 'static, @@ -45,11 +35,11 @@ pub fn register_submit_aes_request< let Ok(request) = AesRequest::from_hex(&hex_request) else { return Err(ErrorCode::ServerError(INVALID_AES_REQUEST_CODE).into()); }; - let context = ctx.clone(); - let aes_request = request.clone(); - let handle = Handle::current(); - let join_handle = - task::spawn_blocking(|| handle_aes_request(aes_request, context, handle)); + let join_handle = task::spawn_blocking({ + let ctx = ctx.clone(); + let aes_request = request.clone(); + || handle_aes_request(aes_request, ctx, Handle::current()) + }); let (native_call, auth_type) = join_handle.await.map_err(|e| { log::error!("Failed to handle AES request: {:?}", e); ErrorCode::InternalError @@ -64,7 +54,7 @@ pub fn register_submit_aes_request< match response_receiver.await { Ok(response) => Ok::(response.to_hex()), Err(e) => { - log::error!("Failed to receive response from native call executor: {:?}", e); + log::error!("Failed to receive response from native call handler: {:?}", e); Err(ErrorCode::InternalError.into()) }, } @@ -83,50 +73,22 @@ fn handle_aes_request< ctx: Arc>, handle: Handle, ) -> Result<(NativeCall, OmniAccountAuthType), ErrorObject<'a>> { - if request.shard().encode() != ctx.mrenclave.encode() { - return Err(ErrorCode::ServerError(INVALID_SHARD_CODE).into()); + if request.mrenclave() != ctx.mrenclave { + return Err(ErrorCode::ServerError(INVALID_MRENCLAVE_CODE).into()); } - let Ok(encoded_auth_call) = request.decrypt(Box::new(ctx.shielding_key.clone())) else { + let Ok(encoded_nca) = request.decrypt(Box::new(ctx.shielding_key.clone())) else { return Err(ErrorCode::ServerError(REQUEST_DECRYPTION_FAILED_CODE).into()); }; - let authenticated_call: AuthenticatedCall = - match AuthenticatedCall::decode(&mut encoded_auth_call.as_slice()) { - Ok(auth_call) => auth_call, - Err(e) => { - log::error!("Failed to decode authenticated call: {:?}", e); - return Err(ErrorCode::ServerError(INVALID_AUTHENTICATED_CALL_CODE).into()); - }, - }; - let authentication_result = match authenticated_call.authentication { - Authentication::Web3(ref signature) => verify_web3_authentication( - signature, - &authenticated_call.call, - authenticated_call.nonce, - &ctx.mrenclave, - &request.shard, - ), - Authentication::Email(ref verification_code) => verify_email_authentication( - ctx, - authenticated_call.call.sender_identity(), - verification_code, - ), - Authentication::OAuth2(ref oauth2_data) => verify_oauth2_authentication( - ctx, - handle, - authenticated_call.call.sender_identity(), - oauth2_data, - ), - Authentication::AuthToken(ref auth_token) => verify_auth_token_authentication( - ctx, - handle, - authenticated_call.call.sender_identity(), - auth_token, - ), + let nca = match NativeCallAuthenticated::decode(&mut encoded_nca.as_slice()) { + Ok(nca) => nca, + Err(e) => { + log::error!("Failed to decode authenticated call: {:?}", e); + return Err(ErrorCode::ServerError(INVALID_AUTHENTICATED_CALL_CODE).into()); + }, }; - - if authentication_result.is_err() { + if verify_native_call_authenticated(ctx, handle, &nca).is_err() { return Err(ErrorCode::ServerError(AUTHENTICATION_FAILED_CODE).into()); } - Ok((authenticated_call.call, authenticated_call.authentication.into())) + Ok((nca.call, nca.authentication.into())) } diff --git a/tee-worker/omni-executor/rpc-server/src/methods/submit_plain_request.rs b/tee-worker/omni-executor/rpc-server/src/methods/submit_plain_request.rs new file mode 100644 index 0000000000..e864fcd23d --- /dev/null +++ b/tee-worker/omni-executor/rpc-server/src/methods/submit_plain_request.rs @@ -0,0 +1,87 @@ +use crate::{ + error_code::*, + native_call_authenticated::{verify_native_call_authenticated, NativeCallAuthenticated}, + request::PlainRequest, + server::RpcContext, +}; +use executor_core::native_call::NativeCall; +use executor_primitives::{ + utils::hex::{FromHexPrefixed, ToHexPrefixed}, + OmniAccountAuthType, +}; +use jsonrpsee::{ + types::{ErrorCode, ErrorObject}, + RpcModule, +}; +use native_task_handler::NativeTask; +use parentchain_rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory}; +use parity_scale_codec::Decode; +use std::sync::Arc; +use tokio::{runtime::Handle, sync::oneshot, task}; + +pub fn register_submit_plain_request< + AccountId: Send + Sync + 'static, + Header: Send + Sync + 'static, + RpcClient: SubstrateRpcClient + Send + Sync + 'static, + RpcClientFactory: SubstrateRpcClientFactory + Send + Sync + 'static, +>( + module: &mut RpcModule>, +) { + module + .register_async_method("native_submitPlainRequest", |params, ctx, _| async move { + let Ok(hex_request) = params.one::() else { + return Err(ErrorCode::ParseError.into()); + }; + let Ok(request) = PlainRequest::from_hex(&hex_request) else { + return Err(ErrorCode::ServerError(INVALID_PLAIN_REQUEST_CODE).into()); + }; + let join_handle = task::spawn_blocking({ + let ctx = ctx.clone(); + let plain_request = request.clone(); + || handle_plain_request(plain_request, ctx, Handle::current()) + }); + let (native_call, auth_type) = join_handle.await.map_err(|e| { + log::error!("Failed to handle Plain request: {:?}", e); + ErrorCode::InternalError + })??; + let (response_sender, response_receiver) = oneshot::channel(); + let native_task = NativeTask { call: native_call, auth_type, response_sender }; + + if ctx.native_task_sender.send(native_task).await.is_err() { + log::error!("Failed to send request to native call executor"); + return Err(ErrorCode::InternalError.into()); + } + match response_receiver.await { + Ok(response) => Ok::(response.to_hex()), + Err(e) => { + log::error!("Failed to receive response from native call handler: {:?}", e); + Err(ErrorCode::InternalError.into()) + }, + } + }) + .expect("Failed to register native_submitPlainRequest method"); +} + +fn handle_plain_request< + 'a, + AccountId, + Header, + RpcClient: SubstrateRpcClient, + RpcClientFactory: SubstrateRpcClientFactory, +>( + request: PlainRequest, + ctx: Arc>, + handle: Handle, +) -> Result<(NativeCall, OmniAccountAuthType), ErrorObject<'a>> { + if request.mrenclave != ctx.mrenclave { + return Err(ErrorCode::ServerError(INVALID_MRENCLAVE_CODE).into()); + } + let nca = NativeCallAuthenticated::decode(&mut request.payload.as_slice()) + .map_err(|_| ErrorCode::ServerError(INVALID_NATIVE_CALL_AUTHENTICATED_CODE))?; + + if verify_native_call_authenticated(ctx, handle, &nca).is_err() { + return Err(ErrorCode::ServerError(AUTHENTICATION_FAILED_CODE).into()); + } + + Ok((nca.call, nca.authentication.into())) +} diff --git a/tee-worker/omni-executor/rpc-server/src/native_call_authenticated.rs b/tee-worker/omni-executor/rpc-server/src/native_call_authenticated.rs new file mode 100644 index 0000000000..76e8a63416 --- /dev/null +++ b/tee-worker/omni-executor/rpc-server/src/native_call_authenticated.rs @@ -0,0 +1,59 @@ +use crate::{ + authentication::{ + verify_auth_token_authentication, verify_email_authentication, + verify_oauth2_authentication, verify_web3_authentication, Authentication, + AuthenticationError, + }, + server::RpcContext, +}; +use executor_core::native_call::NativeCall; +use executor_primitives::Nonce; +use parentchain_rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory}; +use parity_scale_codec::{Decode, Encode}; +use std::sync::Arc; +use tokio::runtime::Handle; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub struct NativeCallAuthenticated { + pub call: NativeCall, + pub nonce: Nonce, + pub authentication: Authentication, +} + +pub fn verify_native_call_authenticated< + AccountId, + Header, + RpcClient: SubstrateRpcClient, + RpcClientFactory: SubstrateRpcClientFactory, +>( + ctx: Arc>, + handle: Handle, + authenticated_call: &NativeCallAuthenticated, +) -> Result<(), AuthenticationError> { + let authentication_result = match authenticated_call.authentication { + Authentication::Web3(ref signature) => verify_web3_authentication( + signature, + &authenticated_call.call, + authenticated_call.nonce, + ctx.mrenclave, + ), + Authentication::Email(ref verification_code) => verify_email_authentication( + ctx, + authenticated_call.call.sender_identity(), + verification_code, + ), + Authentication::OAuth2(ref oauth2_data) => verify_oauth2_authentication( + ctx, + handle, + authenticated_call.call.sender_identity(), + oauth2_data, + ), + Authentication::AuthToken(ref auth_token) => verify_auth_token_authentication( + ctx, + handle, + authenticated_call.call.sender_identity(), + auth_token, + ), + }; + authentication_result +} diff --git a/tee-worker/omni-executor/rpc-server/src/request.rs b/tee-worker/omni-executor/rpc-server/src/request.rs index 2efd450001..dbb81b9be6 100644 --- a/tee-worker/omni-executor/rpc-server/src/request.rs +++ b/tee-worker/omni-executor/rpc-server/src/request.rs @@ -18,15 +18,21 @@ use executor_crypto::{ aes256::{aes_decrypt, Aes256Key as RequestAesKey, AesOutput}, traits::Decrypt, }; -use executor_primitives::ShardIdentifier; +use executor_primitives::MrEnclave; use parity_scale_codec::{Decode, Encode}; use std::fmt::Debug; +#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug)] +pub struct PlainRequest { + pub mrenclave: MrEnclave, + pub payload: Vec, +} + // Represent a request that can be decrypted by the enclave pub trait DecryptableRequest { type Error; - // the shard getter - fn shard(&self) -> ShardIdentifier; + // the mrenclave getter + fn mrenclave(&self) -> MrEnclave; // how to decrypt the payload fn decrypt( &mut self, @@ -36,7 +42,7 @@ pub trait DecryptableRequest { #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)] pub struct AesRequest { - pub shard: ShardIdentifier, + pub mrenclave: MrEnclave, pub key: Vec, pub payload: AesOutput, } @@ -44,8 +50,8 @@ pub struct AesRequest { impl DecryptableRequest for AesRequest { type Error = (); - fn shard(&self) -> ShardIdentifier { - self.shard + fn mrenclave(&self) -> MrEnclave { + self.mrenclave } fn decrypt( diff --git a/tee-worker/omni-executor/rpc-server/src/server.rs b/tee-worker/omni-executor/rpc-server/src/server.rs index b4de35a1b8..fc0042a5de 100644 --- a/tee-worker/omni-executor/rpc-server/src/server.rs +++ b/tee-worker/omni-executor/rpc-server/src/server.rs @@ -1,4 +1,5 @@ use crate::{methods::register_methods, ShieldingKey}; +use executor_primitives::MrEnclave; use executor_storage::StorageDB; use heima_identity_verification::web2::email::Mailer; use jsonrpsee::{server::Server, RpcModule}; @@ -16,7 +17,7 @@ pub(crate) struct RpcContext< pub native_task_sender: Arc, pub parentchain_rpc_client_factory: Arc, pub storage_db: Arc, - pub mrenclave: [u8; 32], + pub mrenclave: MrEnclave, pub mailer: Mailer, pub jwt_secret: String, pub google_client_id: String, @@ -50,7 +51,7 @@ impl< native_task_sender, parentchain_rpc_client_factory, storage_db, - mrenclave, + mrenclave: MrEnclave::from(mrenclave), mailer, jwt_secret, google_client_id,