aesm_client/imp/
unix.rs

1use std::ffi::OsStr;
2use std::os::unix::ffi::OsStrExt;
3use std::path::{Path, PathBuf};
4use std::time::Duration;
5
6use unix_socket::UnixStream;
7#[cfg(feature = "sgxs")]
8use sgxs::sigstruct::{Attributes, Sigstruct};
9
10pub use error::Result;
11
12mod aesm_protobuf;
13
14#[cfg(feature = "sgxs")]
15use Request_GetLaunchTokenRequest;
16
17#[derive(Clone, Debug, Default)]
18pub struct AesmClient {
19    path: Option<PathBuf>,
20}
21
22impl AesmClient {
23    pub fn new() -> Self {
24        Default::default()
25    }
26
27    fn open_socket(&self) -> Result<UnixStream> {
28        lazy_static! {
29            static ref AESM_SOCKET_ABSTRACT_PATH: PathBuf = {
30                // This is defined in <linux/un.h>, although if aesm didn't pad
31                // its address we wouldn't need to use it here.
32                const UNIX_PATH_MAX: usize = 108;
33
34                // The address of the AESM socket is "sgx_aesm_socket_base" followed by
35                // enough NULs to pad to UNIX_PATH_MAX (and with a leading NUL to indicate
36                // the abstract namespace).
37                let mut path = [0; UNIX_PATH_MAX];
38                path[1..21].copy_from_slice(b"sgx_aesm_socket_base");
39                OsStr::from_bytes(&path).into()
40            };
41        };
42        static AESM_SOCKET_FILE_PATH: &'static str = "/var/run/aesmd/aesm.socket";
43
44        // AESM only accepts one request per connection, so we have to open
45        // a fresh socket here.
46        let path = if let Some(ref path) = self.path {
47            &**path
48        } else if Path::new(AESM_SOCKET_FILE_PATH).exists() {
49            Path::new(AESM_SOCKET_FILE_PATH)
50        } else {
51            &**AESM_SOCKET_ABSTRACT_PATH
52        };
53
54        let sock = UnixStream::connect_timeout(path, Duration::from_micros(aesm_protobuf::LOCAL_AESM_TIMEOUT_US as _))?;
55        let _ = sock.set_write_timeout(Some(Duration::from_micros(aesm_protobuf::LOCAL_AESM_TIMEOUT_US as _)))?;
56        Ok(sock)
57    }
58
59    /// Obtain launch token
60    #[cfg(feature = "sgxs")]
61    pub fn get_launch_token(
62        &self,
63        sigstruct: &Sigstruct,
64        attributes: Attributes,
65    ) -> Result<Vec<u8>> {
66        let mut req = Request_GetLaunchTokenRequest::new();
67        req.set_mr_enclave(sigstruct.enclavehash.to_vec());
68        // The field in the request protobuf is called mr_signer, but it wants the modulus.
69        req.set_mr_signer(sigstruct.modulus.to_vec());
70        req.set_se_attributes(attributes.as_ref().to_vec());
71        req.set_timeout(aesm_protobuf::REMOTE_AESM_TIMEOUT_US);
72
73        let mut res = self.transact(req)?;
74
75        let token = res.take_token();
76
77        Ok(token)
78    }
79}
80
81impl crate::unix::AesmClientExt for crate::AesmClient {
82    fn with_path<P: AsRef<Path>>(path: P) -> Self {
83        crate::AesmClient {
84            inner: self::AesmClient {
85                path: Some(path.as_ref().to_owned()),
86            },
87        }
88    }
89}