Skip to content

Commit 7e2eea0

Browse files
committed
implement zkdcap_register_enclave_key for LCPClient
Signed-off-by: Jun Kimura <[email protected]>
1 parent c1e32ca commit 7e2eea0

File tree

12 files changed

+139
-8
lines changed

12 files changed

+139
-8
lines changed

Cargo.lock

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

modules/attestation-report/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ base64 = { version = "0.22.1", default-features = false, features = ["alloc"] }
1616
pem = { version = "2.0", default-features = false }
1717
webpki = { version = "0.22", features = ["alloc"] }
1818

19-
dcap-rs = { git = "https://github.com/bluele/dcap-rs", rev = "71fe1e02f151a28bf5661b01dba5096730564840", optional = true }
19+
dcap-rs = { git = "https://github.com/bluele/dcap-rs", rev = "c3098b6a3c9faa4a884c87db65d0f586000bcf16", optional = true }
2020

2121
[dev-dependencies]
2222
tokio = { version = "1.0", default-features = false, features = ["macros"] }

modules/attestation-report/src/report.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl From<DCAPQuote> for RAQuote {
7676
/// ReportData is a 64-byte value that is embedded in the Quote
7777
/// | version: 1 byte | enclave key: 20 bytes | operator: 20 bytes | nonce: 22 bytes |
7878
#[derive(Debug, Clone, PartialEq)]
79-
pub struct ReportData(pub(crate) [u8; 64]);
79+
pub struct ReportData(pub [u8; 64]);
8080

8181
impl ReportData {
8282
/// Creates a new report data

modules/lcp-client/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ flex-error = { version = "0.4.4", default-features = false }
1111
tiny-keccak = { version = "2.0" }
1212
hex-literal = { version = "0.4.1" }
1313
alloy-sol-types = { version = "0.8", default-features = false }
14+
dcap-rs = { git = "https://github.com/bluele/dcap-rs", rev = "c3098b6a3c9faa4a884c87db65d0f586000bcf16" }
1415

1516
attestation-report = { path = "../attestation-report", default-features = false }
1617
light-client = { path = "../light-client", default-features = false }

modules/lcp-client/src/client_def.rs

+69-3
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ use crate::consensus_state::ConsensusState;
33
use crate::errors::Error;
44
use crate::message::{
55
ClientMessage, CommitmentProofs, RegisterEnclaveKeyMessage, UpdateOperatorsMessage,
6+
ZKDCAPRegisterEnclaveKeyMessage,
67
};
78
use alloy_sol_types::{sol, SolValue};
89
use attestation_report::{IASSignedReport, ReportData};
910
use crypto::{verify_signature_address, Address, Keccak256};
11+
use dcap_rs::types::quotes::body::QuoteBody;
1012
use hex_literal::hex;
1113
use light_client::commitments::{
1214
CommitmentPrefix, EthABIEncoder, MisbehaviourProxyMessage, ProxyMessage,
@@ -125,6 +127,9 @@ impl LCPClient {
125127
ClientMessage::RegisterEnclaveKey(msg) => {
126128
self.register_enclave_key(ctx, client_id, client_state, msg)
127129
}
130+
ClientMessage::ZKDCAPRegisterEnclaveKey(msg) => {
131+
self.zkdcap_register_enclave_key(ctx, client_id, client_state, msg)
132+
}
128133
ClientMessage::UpdateOperators(msg) => {
129134
self.update_operators(ctx, client_id, client_state, msg)
130135
}
@@ -192,7 +197,7 @@ impl LCPClient {
192197
assert!(!client_state.frozen);
193198

194199
let (report_data, attestation_time) =
195-
verify_report(ctx.host_timestamp(), &client_state, &message.report)?;
200+
verify_ias_report(ctx.host_timestamp(), &client_state, &message.report)?;
196201

197202
let operator = if let Some(operator_signature) = message.operator_signature {
198203
verify_signature_address(
@@ -217,6 +222,50 @@ impl LCPClient {
217222
Ok(())
218223
}
219224

225+
fn zkdcap_register_enclave_key(
226+
&self,
227+
ctx: &mut dyn HostClientKeeper,
228+
client_id: ClientId,
229+
client_state: ClientState,
230+
message: ZKDCAPRegisterEnclaveKeyMessage,
231+
) -> Result<(), Error> {
232+
assert!(!client_state.frozen);
233+
234+
// TODO
235+
// verify_zkdcap_report(ctx.host_timestamp(), &client_state, &message.commit, &message.proof)?;
236+
237+
let attestation_time =
238+
Time::from_unix_timestamp(message.commit.attestation_time as i64, 0)?;
239+
let report = if let QuoteBody::SGXQuoteBody(report) = message.commit.output.quote_body {
240+
report
241+
} else {
242+
return Err(Error::unexpected_quote_body());
243+
};
244+
let report_data = ReportData(report.report_data);
245+
246+
let operator = if let Some(operator_signature) = message.operator_signature {
247+
verify_signature_address(
248+
compute_eip712_zkdcap_register_enclave_key(message.commit.hash()).as_ref(),
249+
operator_signature.as_ref(),
250+
)?
251+
} else {
252+
Default::default()
253+
};
254+
let expected_operator = report_data.operator();
255+
// check if the operator matches the expected operator in the report data
256+
assert!(expected_operator.is_zero() || operator == expected_operator);
257+
self.set_enclave_operator_info(
258+
ctx,
259+
&client_id,
260+
report_data.enclave_key(),
261+
EKOperatorInfo::new(
262+
(attestation_time + client_state.key_expiration)?.as_unix_timestamp_secs(),
263+
operator,
264+
),
265+
);
266+
Ok(())
267+
}
268+
220269
fn update_operators(
221270
&self,
222271
ctx: &mut dyn HostClientKeeper,
@@ -456,6 +505,23 @@ pub fn compute_eip712_register_enclave_key_hash(avr: &str) -> [u8; 32] {
456505
keccak256(&compute_eip712_register_enclave_key(avr))
457506
}
458507

508+
pub fn compute_eip712_zkdcap_register_enclave_key(commit_hash: [u8; 32]) -> Vec<u8> {
509+
// 0x1901 | DOMAIN_SEPARATOR_ZKDCAP_REGISTER_ENCLAVE_KEY | keccak256(keccak256("ZKDCAPRegisterEnclaveKey(bytes32 commit_hash)") | commit_hash)
510+
let type_hash = {
511+
let mut h = Keccak::v256();
512+
h.update(&keccak256(b"ZKDCAPRegisterEnclaveKey(bytes32 commit_hash)"));
513+
h.update(&commit_hash);
514+
let mut result = [0u8; 32];
515+
h.finalize(result.as_mut());
516+
result
517+
};
518+
[0x19, 0x01]
519+
.into_iter()
520+
.chain(LCP_CLIENT_DOMAIN_SEPARATOR)
521+
.chain(type_hash)
522+
.collect()
523+
}
524+
459525
pub fn compute_eip712_update_operators(
460526
client_id: ClientId,
461527
nonce: u64,
@@ -521,10 +587,10 @@ pub fn compute_eip712_update_operators_hash(
521587
))
522588
}
523589

524-
// verify_report
590+
// verify_ias_report
525591
// - verifies the Attestation Verification Report
526592
// - calculate a key expiration with client_state and report's timestamp
527-
fn verify_report(
593+
fn verify_ias_report(
528594
current_timestamp: Time,
529595
client_state: &ClientState,
530596
signed_avr: &IASSignedReport,

modules/lcp-client/src/errors.rs

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ define_error! {
1919
format_args!("unexpected header type: type_url={}", e.type_url)
2020
},
2121

22+
UnexpectedQuoteBody
23+
|e| {
24+
"unexpected quote body"
25+
},
26+
2227
ExpiredAvr {
2328
current_timestamp: light_client::types::Time,
2429
attestation_time: light_client::types::Time,

modules/lcp-client/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ mod prelude {
2424
pub mod client_def;
2525
pub mod client_state;
2626
pub mod consensus_state;
27+
pub mod dcap;
2728
pub mod errors;
2829
pub mod message;

modules/lcp-client/src/message.rs

+42-1
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,33 @@
1+
use crate::dcap::DCAPVerifierCommit;
12
use crate::errors::Error;
23
use crate::prelude::*;
34
use alloy_sol_types::{sol, SolValue};
45
use attestation_report::IASSignedReport;
56
use crypto::Address;
7+
use dcap_rs::types::VerifiedOutput;
68
use light_client::commitments::{Error as CommitmentError, EthABIEncoder, ProxyMessage};
79
use light_client::types::proto::ibc::lightclients::lcp::v1::{
810
RegisterEnclaveKeyMessage as RawRegisterEnclaveKeyMessage,
911
UpdateClientMessage as RawUpdateClientMessage,
1012
UpdateOperatorsMessage as RawUpdateOperatorsMessage,
13+
ZkdcapRegisterEnclaveKeyMessage as RawZKDCAPRegisterEnclaveKeyMessage,
1114
};
1215
use light_client::types::{proto::protobuf::Protobuf, Any};
1316
use serde::{Deserialize, Serialize};
1417

1518
pub const LCP_REGISTER_ENCLAVE_KEY_MESSAGE_TYPE_URL: &str =
1619
"/ibc.lightclients.lcp.v1.RegisterEnclaveKeyMessage";
20+
pub const LCP_ZKDCAP_REGISTER_ENCLAVE_KEY_MESSAGE_TYPE_URL: &str =
21+
"/ibc.lightclients.lcp.v1.ZKDCAPRegisterEnclaveKeyMessage";
1722
pub const LCP_UPDATE_CLIENT_MESSAGE_TYPE_URL: &str = "/ibc.lightclients.lcp.v1.UpdateClientMessage";
1823
pub const LCP_UPDATE_OPERATORS_MESSAGE_TYPE_URL: &str =
1924
"/ibc.lightclients.lcp.v1.UpdateOperatorsMessage";
2025

2126
#[allow(clippy::large_enum_variant)]
22-
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
27+
#[derive(Debug, Clone, PartialEq)]
2328
pub enum ClientMessage {
2429
RegisterEnclaveKey(RegisterEnclaveKeyMessage),
30+
ZKDCAPRegisterEnclaveKey(ZKDCAPRegisterEnclaveKeyMessage),
2531
UpdateClient(UpdateClientMessage),
2632
UpdateOperators(UpdateOperatorsMessage),
2733
}
@@ -54,6 +60,10 @@ impl From<ClientMessage> for Any {
5460
LCP_REGISTER_ENCLAVE_KEY_MESSAGE_TYPE_URL.to_string(),
5561
h.encode_vec().unwrap(),
5662
),
63+
ClientMessage::ZKDCAPRegisterEnclaveKey(h) => Any::new(
64+
LCP_ZKDCAP_REGISTER_ENCLAVE_KEY_MESSAGE_TYPE_URL.to_string(),
65+
h.encode_vec().unwrap(),
66+
),
5767
ClientMessage::UpdateClient(h) => Any::new(
5868
LCP_UPDATE_CLIENT_MESSAGE_TYPE_URL.to_string(),
5969
h.encode_vec().unwrap(),
@@ -100,6 +110,37 @@ impl From<RegisterEnclaveKeyMessage> for RawRegisterEnclaveKeyMessage {
100110
}
101111
}
102112

113+
#[derive(Debug, Clone, PartialEq)]
114+
pub struct ZKDCAPRegisterEnclaveKeyMessage {
115+
pub commit: DCAPVerifierCommit,
116+
pub proof: Vec<u8>,
117+
pub operator_signature: Option<Vec<u8>>,
118+
}
119+
120+
impl Protobuf<RawZKDCAPRegisterEnclaveKeyMessage> for ZKDCAPRegisterEnclaveKeyMessage {}
121+
122+
impl TryFrom<RawZKDCAPRegisterEnclaveKeyMessage> for ZKDCAPRegisterEnclaveKeyMessage {
123+
type Error = Error;
124+
fn try_from(value: RawZKDCAPRegisterEnclaveKeyMessage) -> Result<Self, Self::Error> {
125+
Ok(ZKDCAPRegisterEnclaveKeyMessage {
126+
commit: DCAPVerifierCommit::from_bytes(&value.commit),
127+
proof: value.proof,
128+
operator_signature: (!value.operator_signature.is_empty())
129+
.then_some(value.operator_signature),
130+
})
131+
}
132+
}
133+
134+
impl From<ZKDCAPRegisterEnclaveKeyMessage> for RawZKDCAPRegisterEnclaveKeyMessage {
135+
fn from(value: ZKDCAPRegisterEnclaveKeyMessage) -> Self {
136+
RawZKDCAPRegisterEnclaveKeyMessage {
137+
commit: value.commit.to_bytes(),
138+
proof: value.proof,
139+
operator_signature: value.operator_signature.unwrap_or_default(),
140+
}
141+
}
142+
}
143+
103144
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
104145
pub struct UpdateClientMessage {
105146
pub signatures: Vec<Vec<u8>>,

modules/remote-attestation/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ reqwest = { version = "0.12.9", default-features = false, features = [
2525
] }
2626
urlencoding = { version = "2" }
2727

28-
dcap-rs = { git = "https://github.com/bluele/dcap-rs", rev = "71fe1e02f151a28bf5661b01dba5096730564840" }
28+
dcap-rs = { git = "https://github.com/bluele/dcap-rs", rev = "c3098b6a3c9faa4a884c87db65d0f586000bcf16" }
2929

3030
lcp-types = { path = "../types" }
3131
crypto = { path = "../crypto", default-features = false }

proto/definitions/ibc/lightclients/lcp/v1/lcp.proto

+6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ message RegisterEnclaveKeyMessage {
1919
bytes operator_signature = 4;
2020
}
2121

22+
message ZKDCAPRegisterEnclaveKeyMessage {
23+
bytes commit = 1;
24+
bytes proof = 2;
25+
bytes operator_signature = 3;
26+
}
27+
2228
message UpdateOperatorsMessage {
2329
uint64 nonce = 1;
2430
repeated bytes new_operators = 2;

proto/src/descriptor.bin

317 Bytes
Binary file not shown.

proto/src/prost/ibc.lightclients.lcp.v1.rs

+10
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ pub struct RegisterEnclaveKeyMessage {
2020
}
2121
#[allow(clippy::derive_partial_eq_without_eq)]
2222
#[derive(Clone, PartialEq, ::prost::Message)]
23+
pub struct ZkdcapRegisterEnclaveKeyMessage {
24+
#[prost(bytes = "vec", tag = "1")]
25+
pub commit: ::prost::alloc::vec::Vec<u8>,
26+
#[prost(bytes = "vec", tag = "2")]
27+
pub proof: ::prost::alloc::vec::Vec<u8>,
28+
#[prost(bytes = "vec", tag = "3")]
29+
pub operator_signature: ::prost::alloc::vec::Vec<u8>,
30+
}
31+
#[allow(clippy::derive_partial_eq_without_eq)]
32+
#[derive(Clone, PartialEq, ::prost::Message)]
2333
pub struct UpdateOperatorsMessage {
2434
#[prost(uint64, tag = "1")]
2535
pub nonce: u64,

0 commit comments

Comments
 (0)