1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
extern crate dcap_ql_sys;
#[cfg(not(feature = "link"))]
extern crate libc;

extern crate sgxs_loaders;

use failure::Error;
use num_traits::FromPrimitive;

pub use self::dcap_ql_sys::Quote3Error;
use sgx_isa::{Report, Targetinfo};
use self::sgxs_loaders::sgx_enclave_common::dl::os::unix::Library as Dl;
use self::sgxs_loaders::sgx_enclave_common::Library as EnclaveCommonLibrary;

#[cfg(feature = "link")]
use self::dcap_ql_sys::{get_quote, get_quote_size, get_target_info};
#[cfg(not(feature = "link"))]
use self::dl::{get_quote, get_quote_size, get_target_info};

#[cfg(not(feature = "link"))]
mod dl;

fn err_code_to_result(err: u32) -> Result<(), Quote3Error> {
    match Quote3Error::from_u32(err) {
        Some(Quote3Error::Success) => Ok(()),
        Some(e) => Err(e),
        _ => Err(Quote3Error::InvalidParameter),
    }
}

/// Obtain the `Targetinfo` for the Quoting Enclave.
///
/// Use this `Targetinfo` when calling `EREPORT` in your enclave to generate
/// the report that will be passed into `quote()`.
pub fn target_info() -> Result<Targetinfo, Quote3Error> {
    unsafe {
        let mut targetinfo = Targetinfo::default();
        err_code_to_result(get_target_info(&mut targetinfo))?;
        Ok(targetinfo)
    }
}

/// Turn a `Report` into a quote.
///
/// Call the quoting enclave to get a quote. The quoting enclave will sign the
/// `Report` if the `Report` is valid and generated with the right `Targetinfo`.
pub fn quote(report: &Report) -> Result<Vec<u8>, Quote3Error> {
    unsafe {
        let mut quote_size = 0;
        err_code_to_result(get_quote_size(&mut quote_size))?;

        let mut quote = vec![0; quote_size as _];
        err_code_to_result(get_quote(&report, quote_size, quote.as_mut_ptr()))?;
        Ok(quote)
    }
}

/// Returns `true` if the DCAP Quoting Library could be loaded.
///
/// This doesn't indicate anything else. For example, loading the quoting
/// enclave might still fail even if this returns `true`.
pub fn is_loaded() -> bool {
    #[cfg(not(feature = "link"))]
    {
        dl::load().is_ok()
    }
    #[cfg(feature = "link")]
    {
        true
    }
}

/// Get the enclave loader that is available due to linking with the DCAP
/// Quoting Library.
///
/// Since DCAP is being used, assume that no EINITTOKEN provider is necessary.
pub fn enclave_loader() -> Result<EnclaveCommonLibrary, Error> {
    #[cfg(not(feature = "link"))]
    dl::load().map_err(failure::err_msg)?;
    // NB. libsgx_dcap_ql.so.1 transitively links to libsgx_enclave_common.so.1
    // so we should be able to find it already loaded.
    // We can't use the library from `mod dl` if `not(feature = "link")`,
    // because that is not the right library.
    Ok(EnclaveCommonLibrary::load(Some(Dl::this().into()))?.build())
}