| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| //! This crate provides TLS-based remote attestation mechanism for Teaclave, |
| //! supporting both EPID and ECDSA attestation. By default, Intel Attestation |
| //! Service is used for RA. |
| |
| #![allow(clippy::nonstandard_macro_braces)] |
| |
| extern crate sgx_types; |
| |
| use std::sync::Arc; |
| |
| use anyhow::{Context, Result}; |
| use serde::{Deserialize, Serialize}; |
| use sgx_types::error::SgxStatus; |
| use sgx_types::types::Spid; |
| |
| /// Errors that can happen during attestation and verification process |
| #[derive(thiserror::Error, Debug)] |
| pub enum AttestationError { |
| #[error("OCall error")] |
| OCallError(SgxStatus), |
| #[error("Attestation Service error")] |
| AttestationServiceError, |
| #[error("Platform error")] |
| PlatformError(SgxStatus), |
| #[error("Report error")] |
| ReportError, |
| #[error("Report error")] |
| ConnectionError, |
| #[error("Attestation Service API version not compatible")] |
| ApiVersionNotCompatible, |
| } |
| |
| /// Remote attestation configuration |
| #[derive(Clone)] |
| pub enum AttestationConfig { |
| /// Trust enclave without attestation |
| NoAttestation, |
| /// Perform attestation before trusting enclave |
| WithAttestation(AttestationServiceConfig), |
| } |
| |
| /// Remote attestation algorithm |
| #[derive(Clone)] |
| pub(crate) enum AttestationAlgorithm { |
| /// Use Intel EPID |
| SgxEpid, |
| /// Use ECDSA |
| SgxEcdsa, |
| } |
| |
| impl AttestationAlgorithm { |
| pub(crate) fn from_str(s: &str) -> Option<Self> { |
| match s { |
| "sgx_epid" => Some(AttestationAlgorithm::SgxEpid), |
| "sgx_ecdsa" => Some(AttestationAlgorithm::SgxEcdsa), |
| _ => None, |
| } |
| } |
| } |
| |
| /// Attestation Service Configuration |
| #[derive(Clone)] |
| #[allow(dead_code)] |
| pub struct AttestationServiceConfig { |
| /// Algorithm to use |
| algo: AttestationAlgorithm, |
| /// URL of attestation service |
| as_url: url::Url, |
| /// IAS API Key |
| api_key: String, |
| /// SPID |
| spid: Spid, |
| } |
| |
| pub struct DcapConfig {} |
| |
| impl AttestationConfig { |
| /// Creates `AttestationConfig` for no attestation |
| pub fn no_attestation() -> Arc<Self> { |
| Arc::new(Self::NoAttestation) |
| } |
| |
| /// Creates `AttestationConfig` for attestation using given values |
| pub fn new(algorithm: &str, url: &str, api_key: &str, spid_str: &str) -> Result<Arc<Self>> { |
| if cfg!(sgx_sim) { |
| return Ok(Self::no_attestation()); |
| } |
| |
| let mut spid = Spid::default(); |
| let hex = hex::decode(spid_str).context("Illegal SPID provided")?; |
| spid.id = <[u8; 16]>::try_from(hex.as_slice()).context("Illegal SPID provided")?; |
| |
| let algo = AttestationAlgorithm::from_str(algorithm) |
| .context("Unsupported remote attestation algorithm")?; |
| |
| let att_service_cfg = AttestationServiceConfig { |
| algo, |
| as_url: url::Url::parse(url).context("Invalid URL")?, |
| api_key: api_key.to_string(), |
| spid, |
| }; |
| |
| Ok(Arc::new(Self::WithAttestation(att_service_cfg))) |
| } |
| |
| /// Crate attestation config from Teaclave runtime configuration. |
| pub fn from_teaclave_config(config: &teaclave_config::RuntimeConfig) -> Result<Arc<Self>> { |
| let as_config = &config.attestation; |
| Self::new( |
| &as_config.algorithm, |
| &as_config.url, |
| &as_config.key, |
| &as_config.spid, |
| ) |
| } |
| } |
| |
| /// AttestationReport can be endorsed by either the Intel Attestation Service |
| /// using EPID or Data Center Attestation |
| /// Service (platform dependent) using ECDSA. |
| #[derive(Debug, Default, Serialize, Deserialize)] |
| pub struct EndorsedAttestationReport { |
| /// Attestation report generated by the hardware |
| pub report: Vec<u8>, |
| /// Singature of the report |
| pub signature: Vec<u8>, |
| /// Certificate matching the signing key of the signature |
| pub certs: Vec<Vec<u8>>, |
| } |
| |
| /// Configuration for TLS communication in Remote Attestation |
| #[derive(Debug)] |
| pub struct AttestedTlsConfig { |
| pub cert: Vec<u8>, |
| pub private_key: Vec<u8>, |
| pub time: std::time::SystemTime, |
| pub validity: std::time::Duration, |
| } |
| |
| #[macro_use] |
| mod cert; |
| pub mod report; |
| pub mod verifier; |
| |
| cfg_if::cfg_if! { |
| if #[cfg(feature = "mesalock_sgx")] { |
| mod service; |
| pub mod key; |
| mod platform; |
| mod attestation; |
| pub use attestation::RemoteAttestation; |
| } |
| } |
| |
| #[cfg(all(feature = "enclave_unit_test", feature = "mesalock_sgx"))] |
| pub mod tests { |
| use super::*; |
| use teaclave_test_utils::*; |
| |
| pub fn run_tests() -> bool { |
| run_tests!( |
| platform::tests::test_init_sgx_quote, |
| platform::tests::test_create_sgx_isv_enclave_report, |
| platform::tests::test_get_sgx_quote, |
| report::tests::test_sgx_quote_parse_from, |
| report::tests::test_attestation_report_from_cert, |
| report::tests::test_attestation_report_from_cert_api_version_not_compatible |
| ) |
| } |
| } |