[cli] Add verify subcommand to verify enclave info signatures (#354)
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index 19eff35..afd8757 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -11,3 +11,5 @@
structopt = "0.3"
teaclave_crypto = { path = "../crypto" }
hex = { version = "0.4.0" }
+teaclave_types = { path = "../types" }
+pem = "0.7.0"
diff --git a/cli/README.md b/cli/README.md
index 31eaeb3..8ce913c 100644
--- a/cli/README.md
+++ b/cli/README.md
@@ -5,8 +5,12 @@
# Teaclave Command Line Tool
The Teaclave command line tool (`teaclave_cli`) provides utilities to
-interactive with the platform. The command line tool has several subcommands:
+interactive with the platform. The command line tool has several sub-commands:
-- encrypt/decrypt: These two subcommands are to encrypt/decrypt data used on the
- platform. Supported algorithms include AES-GCM (128bit and 256 bit), and
+- `encrypt`/`decrypt`: These two subcommands are to encrypt/decrypt data used on
+ the platform. Supported algorithms include AES-GCM (128bit and 256 bit), and
Teaclave File (128bit).
+- `verify`: Verify the signatures of the enclave info (which contains `MRSIGNER`
+ and `MRENCLAVE`) signed by auditors with their public keys. The enclave info
+ is used for remote attestation, Please verify it before connecting the
+ platform with the client SDK.
diff --git a/cli/src/main.rs b/cli/src/main.rs
index ff94e41..b38c3b2 100644
--- a/cli/src/main.rs
+++ b/cli/src/main.rs
@@ -60,6 +60,21 @@
}
#[derive(Debug, StructOpt)]
+struct VerifyOpt {
+ /// Path of enclave info
+ #[structopt(short, long = "enclave-info")]
+ enclave_info: PathBuf,
+
+ /// Path of signatures
+ #[structopt(required = true, short, long)]
+ signatures: Vec<PathBuf>,
+
+ /// Path of auditor's public key
+ #[structopt(required = true, short, long = "public-keys")]
+ public_keys: Vec<PathBuf>,
+}
+
+#[derive(Debug, StructOpt)]
enum Command {
/// Encrypt file
#[structopt(name = "encrypt")]
@@ -68,6 +83,10 @@
/// Decrypt file
#[structopt(name = "decrypt")]
Decrypt(EncryptDecryptOpt),
+
+ /// Verify signatures of enclave info with auditors' public keys
+ #[structopt(name = "verify")]
+ Verify(VerifyOpt),
}
#[derive(Debug, StructOpt)]
@@ -142,6 +161,27 @@
Ok(cmac)
}
+fn verify(opt: VerifyOpt) -> Result<bool> {
+ let enclave_info = fs::read(opt.enclave_info)?;
+ let mut public_keys = Vec::new();
+ let mut signatures = Vec::new();
+ for p in opt.public_keys {
+ let content = fs::read(p)?;
+ let pem = pem::parse(content).expect("Expect a valid PEM file");
+ public_keys.push(pem.contents);
+ }
+
+ for s in opt.signatures {
+ signatures.push(fs::read(s)?);
+ }
+
+ Ok(teaclave_types::EnclaveInfo::verify(
+ &enclave_info,
+ &public_keys,
+ &signatures,
+ ))
+}
+
fn main() -> Result<()> {
let args = Opt::from_args();
match args.command {
@@ -161,6 +201,13 @@
println!("{}", cmac_string);
}
}
+ Command::Verify(opt) => match verify(opt) {
+ Ok(false) | Err(_) => bail!("Failed to verify signatures."),
+ Ok(true) => {
+ println!("Verify successfully.");
+ return Ok(());
+ }
+ },
};
Ok(())
diff --git a/cmake/scripts/test.sh b/cmake/scripts/test.sh
index f437d02..316e612 100755
--- a/cmake/scripts/test.sh
+++ b/cmake/scripts/test.sh
@@ -138,6 +138,12 @@
echo_title "examples"
mkdir -p /tmp/fusion_data
+ pushd ${TEACLAVE_CLI_INSTALL_DIR}
+ ./teaclave_cli verify \
+ --enclave-info ../examples/enclave_info.toml \
+ --public-keys $(find ../examples -name "*.public.pem") \
+ --signatures $(find ../examples -name "*.sign.sha256")
+ popd
pushd ${TEACLAVE_SERVICE_INSTALL_DIR}
./teaclave_authentication_service &
./teaclave_storage_service &
diff --git a/examples/python/utils.py b/examples/python/utils.py
index ee085de..dd01766 100644
--- a/examples/python/utils.py
+++ b/examples/python/utils.py
@@ -19,4 +19,4 @@
"/release/tests/enclave_info.toml"
else:
AS_ROOT_CA_CERT_PATH = "../../keys/" + AS_ROOT_CERT_FILENAME
- ENCLAVE_INFO_PATH = "../../release/tests/enclave_info.toml"
+ ENCLAVE_INFO_PATH = "../../release/examples/enclave_info.toml"