oasis_core_runtime/
attestation.rs1use std::sync::Arc;
3
4use anyhow::{bail, Result};
5use slog::{info, Logger};
6
7use crate::{
8 app::App,
9 common::{
10 crypto::signature::Signer, logger::get_logger, namespace::Namespace, panic::AbortOnPanic,
11 sgx::Quote, version::Version,
12 },
13 consensus::{
14 registry::{EndorsedCapabilityTEE, SGXAttestation, ATTESTATION_SIGNATURE_CONTEXT},
15 verifier::Verifier,
16 },
17 host::Host,
18 identity::Identity,
19 policy::PolicyVerifier,
20 types::Body,
21};
22
23#[derive(Clone)]
25pub struct Handler {
26 identity: Arc<Identity>,
27 host: Arc<dyn Host>,
28 consensus_verifier: Arc<dyn Verifier>,
29 runtime_id: Namespace,
30 version: Version,
31 app: Arc<dyn App>,
32 logger: Logger,
33}
34
35impl Handler {
36 pub fn new(
38 identity: Arc<Identity>,
39 host: Arc<dyn Host>,
40 consensus_verifier: Arc<dyn Verifier>,
41 runtime_id: Namespace,
42 version: Version,
43 app: Arc<dyn App>,
44 ) -> Self {
45 Self {
46 identity,
47 host,
48 consensus_verifier,
49 runtime_id,
50 version,
51 app,
52 logger: get_logger("runtime/attestation"),
53 }
54 }
55}
56
57impl Handler {
58 pub async fn handle(&self, request: Body) -> Result<Body> {
60 match request {
61 Body::RuntimeCapabilityTEERakInitRequest { target_info } => {
62 self.target_info_init(target_info)
63 }
64 Body::RuntimeCapabilityTEERakReportRequest {} => self.report_init(),
65 Body::RuntimeCapabilityTEERakAvrRequest { avr } => {
66 self.set_quote(Quote::Ias(avr)).await
68 }
69 Body::RuntimeCapabilityTEERakQuoteRequest { quote } => self.set_quote(quote).await,
70 Body::RuntimeCapabilityTEEUpdateEndorsementRequest { ect } => {
71 self.update_endorsement(ect).await
72 }
73
74 _ => bail!("unsupported attestation request"),
75 }
76 }
77
78 fn target_info_init(&self, target_info: Vec<u8>) -> Result<Body> {
79 let _guard = AbortOnPanic;
81
82 info!(self.logger, "Initializing the runtime target info");
83 self.identity.init_target_info(target_info)?;
84 Ok(Body::RuntimeCapabilityTEERakInitResponse {})
85 }
86
87 fn report_init(&self) -> Result<Body> {
88 let _guard = AbortOnPanic;
90
91 info!(self.logger, "Initializing the runtime key report");
92 let (rak_pub, rek_pub, report, nonce) = self.identity.init_report()?;
93
94 Ok(Body::RuntimeCapabilityTEERakReportResponse {
95 rak_pub,
96 rek_pub,
97 report,
98 nonce,
99 })
100 }
101
102 async fn set_quote_policy(&self) -> Result<()> {
103 info!(self.logger, "Configuring quote policy");
104
105 let policy = if self.app.is_rofl() {
108 self.app.quote_policy().await?
110 } else {
111 let consensus_verifier = self.consensus_verifier.clone();
114 let version = self.version;
115 let runtime_id = self.runtime_id;
116 tokio::task::block_in_place(move || {
117 PolicyVerifier::new(consensus_verifier).quote_policy(&runtime_id, Some(version))
119 })?
120 };
121
122 self.identity.set_quote_policy(policy)?;
123
124 Ok(())
125 }
126
127 async fn set_quote(&self, quote: Quote) -> Result<Body> {
128 let _guard = AbortOnPanic;
130
131 self.set_quote_policy().await?;
133
134 info!(
135 self.logger,
136 "Configuring quote for the runtime attestation key binding"
137 );
138
139 let node_id = self.host.identity().await?;
141 let verified_quote = self.identity.set_quote(node_id, quote)?;
142
143 let consensus_state = self.consensus_verifier.latest_state().await?;
145 let height = consensus_state.height();
146 let rek = self.identity.public_rek();
147 let h = SGXAttestation::hash(&verified_quote.report_data, &node_id, height, &rek);
148 let signature = self.identity.sign(ATTESTATION_SIGNATURE_CONTEXT, &h)?;
149
150 Ok(Body::RuntimeCapabilityTEERakQuoteResponse { height, signature })
151 }
152
153 async fn update_endorsement(&self, ect: EndorsedCapabilityTEE) -> Result<Body> {
154 info!(self.logger, "Updating endorsed TEE capability");
155
156 self.identity.set_endorsed_capability_tee(ect)?;
158
159 Ok(Body::RuntimeCapabilityTEEUpdateEndorsementResponse {})
160 }
161}