feat: WIP new multisig threshold scheme

with a tree like structure allowing nested m of n schemes.

Signed-off-by: Harald Hoyer <harald@matterlabs.dev>
This commit is contained in:
Harald Hoyer 2024-08-06 09:37:30 +02:00
parent 8ce8f5bccb
commit e2b64d5519
Signed by: harald
GPG key ID: F519A1143B3FBE32
19 changed files with 1138 additions and 173 deletions

108
Cargo.lock generated
View file

@ -310,12 +310,55 @@ dependencies = [
"libc",
]
[[package]]
name = "anstream"
version = "0.6.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
[[package]]
name = "anstyle-parse"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
dependencies = [
"anstyle",
"windows-sys 0.52.0",
]
[[package]]
name = "anyhow"
version = "1.0.86"
@ -735,6 +778,12 @@ dependencies = [
"digest",
]
[[package]]
name = "colorchoice"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
[[package]]
name = "const-oid"
version = "0.9.6"
@ -1156,6 +1205,27 @@ dependencies = [
"syn 2.0.72",
]
[[package]]
name = "env_filter"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
dependencies = [
"log",
]
[[package]]
name = "env_logger"
version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"log",
]
[[package]]
name = "equivalent"
version = "1.0.1"
@ -1615,6 +1685,12 @@ dependencies = [
"bindgen",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "iter-read"
version = "1.0.1"
@ -2926,6 +3002,7 @@ dependencies = [
"serde_json",
"sha2",
"teepot",
"test-log",
"tracing",
"tracing-actix-web",
"tracing-log",
@ -2956,7 +3033,6 @@ dependencies = [
"actix-web",
"anyhow",
"awc",
"base64",
"bytemuck",
"bytes",
"clap",
@ -2979,6 +3055,7 @@ dependencies = [
"sha2",
"signature",
"teepot-tee-quote-verification-rs",
"test-log",
"testaso",
"thiserror",
"tracing",
@ -3035,6 +3112,28 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "test-log"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dffced63c2b5c7be278154d76b479f9f9920ed34e7574201407f0b14e2bbb93"
dependencies = [
"env_logger",
"test-log-macros",
"tracing-subscriber",
]
[[package]]
name = "test-log-macros"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.72",
]
[[package]]
name = "testaso"
version = "0.1.0"
@ -3356,6 +3455,12 @@ dependencies = [
"serde",
]
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.10.0"
@ -3394,7 +3499,6 @@ version = "0.1.2-alpha.1"
dependencies = [
"actix-web",
"anyhow",
"base64",
"clap",
"serde_json",
"teepot",

View file

@ -54,6 +54,7 @@ sha2 = "0.10.8"
signature = "2.2.0"
teepot = { path = "crates/teepot" }
testaso = "0.1.0"
test-log = "0.2.16"
thiserror = "1.0.59"
tokio = { version = "1", features = ["sync", "macros", "rt-multi-thread", "fs", "time"] }
tracing = "0.1"

View file

@ -21,3 +21,6 @@ tracing.workspace = true
tracing-actix-web.workspace = true
tracing-log.workspace = true
tracing-subscriber.workspace = true
[dev-dependencies]
test-log.workspace = true

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023 Matter Labs
// Copyright (c) 2023-2024 Matter Labs
//! post commands
@ -14,7 +14,7 @@ use teepot::json::http::{
VaultCommandRequest, VaultCommandResponse, VaultCommands, VaultCommandsResponse,
};
use teepot::json::secrets::{AdminConfig, AdminState};
use teepot::server::{signatures::VerifySig, HttpResponseError, Status};
use teepot::server::{HttpResponseError, Status};
use tracing::instrument;
/// Post command
@ -52,7 +52,9 @@ pub async fn post_command(
.await?
.context("empty admin config")
.status(StatusCode::BAD_GATEWAY)?;
admin_config.check_sigs(&item.signatures, item.commands.as_bytes())?;
admin_config
.policy
.check_sigs(&item.signatures, item.commands.as_bytes())?;
let mut hasher = Sha256::new();
hasher.update(item.commands.as_bytes());

View file

@ -116,6 +116,7 @@ async fn main() -> Result<()> {
mod tests {
use serde_json::json;
use teepot::json::http::{VaultCommand, VaultCommands};
use test_log::test;
const TEST_DATA: &str = include_str!("../../../crates/teepot/tests/data/test.json");

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023 Matter Labs
// Copyright (c) 2023-2024 Matter Labs
//! post signing request
@ -12,7 +12,6 @@ use std::sync::Arc;
use teepot::client::vault::VaultConnection;
use teepot::json::http::{SignRequest, SignRequestData, SignResponse};
use teepot::json::secrets::{AdminConfig, AdminState, SGXSigningKey};
use teepot::server::signatures::VerifySig as _;
use teepot::server::{HttpResponseError, Status};
use teepot::sgx::sign::PrivateKey as _;
use teepot::sgx::sign::{Author, Signature};
@ -76,7 +75,9 @@ pub async fn post_sign(
.await?
.context("empty admin config")
.status(StatusCode::BAD_GATEWAY)?;
admin_config.check_sigs(&item.signatures, item.sign_request_data.as_bytes())?;
admin_config
.policy
.check_sigs(&item.signatures, item.sign_request_data.as_bytes())?;
let mut hasher = Sha256::new();
hasher.update(item.sign_request_data.as_bytes());

View file

@ -2,14 +2,11 @@
// Copyright (c) 2023-2024 Matter Labs
use crate::{get_vault_status, UnsealServerState, Worker};
use actix_web::error::ErrorBadRequest;
use actix_web::{web, HttpResponse};
use anyhow::{anyhow, Context, Result};
use awc::http::StatusCode;
use serde_json::json;
use teepot::client::TeeConnection;
use teepot::json::http::{Init, InitResponse, VaultInitRequest};
use teepot::json::secrets::AdminConfig;
use teepot::server::{HttpResponseError, Status};
use tracing::{debug, error, info, instrument, trace};
@ -22,8 +19,7 @@ pub async fn post_init(
pgp_keys,
secret_shares,
secret_threshold,
admin_pgp_keys,
admin_threshold,
admin_config,
admin_tee_mrenclave,
} = init.into_inner();
let conn = TeeConnection::new(&worker.vault_attestation);
@ -36,17 +32,10 @@ pub async fn post_init(
secret_threshold,
};
if admin_threshold < 1 {
return Ok(HttpResponse::from_error(ErrorBadRequest(
json!({"error": "admin_threshold must be at least 1"}),
)));
}
if admin_threshold > admin_pgp_keys.len() {
return Ok(HttpResponse::from_error(ErrorBadRequest(
json!({"error": "admin_threshold must be less than or equal to the number of admin_pgp_keys"}),
)));
}
admin_config
.validate()
.context("Invalid admin config")
.status(StatusCode::BAD_REQUEST)?;
loop {
let current_state = worker.state.read().unwrap().clone();
@ -123,10 +112,7 @@ pub async fn post_init(
*/
*worker.state.write().unwrap() = UnsealServerState::VaultInitialized {
admin_config: AdminConfig {
admin_pgp_keys,
admin_threshold,
},
admin_config,
admin_tee_mrenclave,
root_token,
};

View file

@ -9,7 +9,6 @@ repository.workspace = true
[dependencies]
actix-web.workspace = true
anyhow.workspace = true
base64.workspace = true
clap.workspace = true
serde_json.workspace = true
teepot.workspace = true

View file

@ -2,13 +2,13 @@
// Copyright (c) 2023-2024 Matter Labs
use anyhow::{anyhow, bail, Context, Result};
use base64::{engine::general_purpose, Engine as _};
use clap::{Args, Parser, Subcommand};
use serde_json::Value;
use std::fs::File;
use std::io::Read;
use teepot::client::{AttestationArgs, TeeConnection};
use teepot::json::http::{Init, InitResponse, Unseal};
use teepot::json::secrets::AdminConfig;
use tracing::{error, info, trace, warn};
use tracing_log::LogTracer;
use tracing_subscriber::Registry;
@ -16,12 +16,9 @@ use tracing_subscriber::{fmt, prelude::*, EnvFilter};
#[derive(Args, Debug)]
pub struct InitArgs {
/// admin threshold
#[arg(long)]
admin_threshold: usize,
/// PGP keys to sign commands for the admin tee
#[arg(short, long)]
admin_pgp_key_file: Vec<String>,
admin_config_json: String,
/// admin TEE mrenclave
#[arg(long)]
admin_tee_mrenclave: String,
@ -78,17 +75,12 @@ async fn init(args: Arguments) -> Result<()> {
unreachable!()
};
if init_args.admin_threshold == 0 {
bail!("admin threshold must be greater than 0");
}
if init_args.unseal_threshold == 0 {
bail!("unseal threshold must be greater than 0");
}
if init_args.admin_threshold > init_args.admin_pgp_key_file.len() {
bail!("admin threshold must be less than or equal to the number of admin pgp keys");
}
let admin_config: AdminConfig = serde_json::from_str(&init_args.admin_config_json)
.context("failed to parse admin config")?;
if init_args.unseal_threshold > init_args.unseal_pgp_key_file.len() {
bail!("unseal threshold must be less than or equal to the number of unseal pgp keys");
@ -105,30 +97,11 @@ async fn init(args: Arguments) -> Result<()> {
pgp_keys.push(key);
}
let mut admin_pgp_keys = Vec::new();
for filename in init_args.admin_pgp_key_file {
let mut file =
File::open(&filename).context(format!("Failed to open pgp key file {}", &filename))?;
// read all lines from file and concatenate them
let mut key = String::new();
file.read_to_string(&mut key)
.context(format!("Failed to read pgp key file {}", &filename))?;
key.retain(|c| !c.is_ascii_whitespace());
let bytes = general_purpose::STANDARD.decode(key).context(format!(
"Failed to base64 decode pgp key file {}",
&filename
))?;
admin_pgp_keys.push(bytes.into_boxed_slice());
}
let init = Init {
secret_shares: pgp_keys.len() as _,
secret_threshold: init_args.unseal_threshold,
admin_threshold: init_args.admin_threshold,
admin_tee_mrenclave: init_args.admin_tee_mrenclave,
admin_pgp_keys: admin_pgp_keys.into_boxed_slice(),
admin_config,
pgp_keys,
};

View file

@ -45,6 +45,6 @@ zeroize.workspace = true
[dev-dependencies]
anyhow.workspace = true
base64.workspace = true
hex.workspace = true
test-log.workspace = true
testaso.workspace = true

View file

@ -3,6 +3,7 @@
//! Common types for the teepot http JSON API
use crate::json::secrets::AdminConfig;
use crate::sgx::Collateral;
use serde::{Deserialize, Serialize};
use serde_json::Value;
@ -42,11 +43,8 @@ pub struct Init {
pub secret_shares: usize,
/// secret threshold
pub secret_threshold: usize,
/// PGP keys to sign commands for the admin tee
#[serde_as(as = "Box<[Base64]>")]
pub admin_pgp_keys: Box<[Box<[u8]>]>,
/// admin threshold
pub admin_threshold: usize,
/// The m of n admin config
pub admin_config: AdminConfig,
/// admin TEE mrenclave
pub admin_tee_mrenclave: String,
}

View file

@ -1,22 +1,25 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023 Matter Labs
// Copyright (c) 2023-2024 Matter Labs
//! Common types for the teepot secrets JSON API
use crate::server::signatures::MultiSigPolicy;
use crate::sgx::sign::Zeroizing;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use serde_with::base64::Base64;
use serde_with::serde_as;
/// Configuration for the admin tee
#[serde_as]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdminConfig {
/// PGP keys to sign commands for the admin tee
#[serde_as(as = "Box<[Base64]>")]
pub admin_pgp_keys: Box<[Box<[u8]>]>,
/// admin threshold
pub admin_threshold: usize,
/// admin signature policy
pub policy: MultiSigPolicy,
}
impl AdminConfig {
/// validate the configuration
pub fn validate(&self) -> Result<()> {
self.policy.validate()
}
}
/// Configuration for the admin tee

View file

@ -1,15 +1,61 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023 Matter Labs
// Copyright (c) 2023-2024 Matter Labs
//! Signature checking utilities
use crate::json::secrets::AdminConfig;
use crate::server::{HttpResponseError, Status as _};
use actix_web::http::StatusCode;
use anyhow::{anyhow, bail, Context, Result};
use pgp::types::KeyTrait;
use pgp::{Deserializable, SignedPublicKey, StandaloneSignature};
use tracing::debug;
use serde::{Deserialize, Serialize};
use tracing::{error, trace};
impl MultiSigPolicy {
/// validate the policy
pub fn validate(&self) -> Result<()> {
if self.threshold == 0 {
bail!("admin_threshold must be greater than 0");
}
if self.members.is_empty() {
bail!("validation elements must not be empty");
}
if self.threshold > self.members.len() {
bail!("threshold must be smaller than number of elements");
}
for ele in self.members.iter() {
match ele {
KeyOrChilds::Key(key) => {
SignedPublicKey::from_string(key)?;
}
KeyOrChilds::Child(child) => {
child.validate()?;
}
}
}
Ok(())
}
}
/// M of N Signature Policy
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MultiSigPolicy {
/// Name of this level
pub name: String,
/// Array of PGP key for validation or Self
pub members: Box<[KeyOrChilds]>,
/// Threshold for validation
pub threshold: usize,
}
/// A m of n child can be a m of n KeyOrChilds or a key
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum KeyOrChilds {
/// a key
Key(String),
/// a sub m of n
Child(MultiSigPolicy),
}
/// Verify a pgp signature for some message given some public keys
pub fn verify_sig(sig: &str, msg: &[u8], keys: &[SignedPublicKey]) -> anyhow::Result<usize> {
@ -20,90 +66,116 @@ pub fn verify_sig(sig: &str, msg: &[u8], keys: &[SignedPublicKey]) -> anyhow::Re
let signature = match signature {
Ok(s) => s,
Err(e) => {
debug!("Failed to parse signature: {}", e);
error!("Failed to parse signature: {}", e);
continue;
}
};
for (pos, key) in keys.iter().enumerate() {
let actual_key = &key.primary_key;
if actual_key.is_signing_key() && signature.verify(&actual_key, msg).is_ok() {
if actual_key.is_signing_key() {
trace!(
"Checking with key {}",
hex::encode(actual_key.fingerprint())
);
if signature.verify(&actual_key, msg).is_ok() {
trace!(
"Verified with key {}",
hex::encode(actual_key.fingerprint())
);
return Ok(pos);
}
for sub_key in &key.public_subkeys {
if sub_key.is_signing_key() && signature.verify(sub_key, msg).is_ok() {
}
for actual_key in &key.public_subkeys {
if actual_key.is_signing_key() {
trace!(
"Checking with subkey {}",
hex::encode(actual_key.fingerprint())
);
if signature.verify(actual_key, msg).is_ok() {
trace!(
"Verified with key {}",
hex::encode(actual_key.fingerprint())
);
return Ok(pos);
}
}
}
}
eprintln!("Failed to verify signature for `{sig}`");
}
trace!("Failed to verify signature for `{sig}`");
bail!("Failed to verify signature for `{sig}`");
}
/// Verify pgp signatures for a message with some threshold
pub fn check_sigs(
pgp_keys: &[Box<[u8]>],
threshold: usize,
impl MultiSigPolicy {
/// Verify pgp signatures for a message with the current policy
pub fn check_sigs(&self, signatures: &[String], msg: &[u8]) -> Result<(), HttpResponseError> {
fn inner_check_sigs(
admin_config: &MultiSigPolicy,
signatures: &[String],
msg: &[u8],
) -> Result<(), HttpResponseError> {
let mut keys = Vec::new();
let mut verified: usize = 0;
for bytes in pgp_keys {
let key = SignedPublicKey::from_bytes(bytes.as_ref())
for key_or_child in admin_config.members.as_ref() {
match key_or_child {
KeyOrChilds::Key(key) => {
// This is not a performance critical path, so we can import from bytes every time
let (key, _) = SignedPublicKey::from_string(key)
.context("parsing public key")
.status(StatusCode::INTERNAL_SERVER_ERROR)?;
keys.push(key);
}
KeyOrChilds::Child(child) => {
if inner_check_sigs(child, signatures, msg).is_ok() {
verified += 1;
}
}
}
}
let mut verified: usize = 0;
if verified < admin_config.threshold {
for sig in signatures {
if let Ok(pos) = verify_sig(sig, msg, &keys) {
keys.remove(pos);
verified += 1;
}
if verified >= threshold {
if verified >= admin_config.threshold {
break;
}
}
}
if verified < threshold {
if verified < admin_config.threshold {
return Err(anyhow!("not enough valid signatures")).status(StatusCode::BAD_REQUEST);
}
Ok(())
}
/// Verify pgp signatures for a message
pub trait VerifySig {
/// Verify pgp signatures for a message
fn check_sigs(&self, signatures: &[String], msg: &[u8]) -> Result<(), HttpResponseError>;
}
impl VerifySig for AdminConfig {
fn check_sigs(&self, signatures: &[String], msg: &[u8]) -> Result<(), HttpResponseError> {
check_sigs(&self.admin_pgp_keys, self.admin_threshold, signatures, msg)
inner_check_sigs(self, signatures, msg)
}
}
#[cfg(test)]
mod tests {
use super::verify_sig;
use base64::{engine::general_purpose, Engine as _};
use super::*;
use pgp::{Deserializable, SignedPublicKey};
use test_log::test;
const TEST_DATA: &str = include_str!("../../tests/data/test.json");
// gpg --armor --local-user test@example.com --detach-sign bin/tee-vault-admin/tests/data/test.json
const TEST_SIG: &str = include_str!("../../tests/data/test.json.asc");
const TEST_SIG_2: &str = include_str!("../../tests/data/test.json_2.asc");
// gpg --armor --export 81A312C59D679D930FA9E8B06D728F29A2DBABF8 > bin/tee-vault-admin/tests/data/pub-81A312C59D679D930FA9E8B06D728F29A2DBABF8.asc
const TEST_KEY: &str =
include_str!("../../tests/data/pub-81A312C59D679D930FA9E8B06D728F29A2DBABF8.asc");
const TEST_KEY_BASE64: &str =
include_str!("../../tests/data/pub-81A312C59D679D930FA9E8B06D728F29A2DBABF8.b64");
const TEST_KEY_2: &str =
include_str!("../../tests/data/pub-7F3D64824AC0B6B8009E50504BC0896FB5693595.asc");
#[test]
fn test_sig() {
@ -112,9 +184,107 @@ mod tests {
}
#[test]
fn test_key_import() {
let str = TEST_KEY_BASE64.lines().collect::<String>();
let bytes = general_purpose::STANDARD.decode(str).unwrap();
let _ = SignedPublicKey::from_bytes(bytes.as_slice()).unwrap();
fn test_multisig() {
assert!(MultiSigPolicy {
name: "test".to_string(),
members: vec![KeyOrChilds::Key("test".into())].into_boxed_slice(),
threshold: 0,
}
.validate()
.is_err());
assert!(MultiSigPolicy {
name: "test".to_string(),
members: vec![KeyOrChilds::Key("test".into())].into_boxed_slice(),
threshold: 2,
}
.validate()
.is_err());
assert!(MultiSigPolicy {
name: "test".to_string(),
members: vec![KeyOrChilds::Key("test".into()),].into_boxed_slice(),
threshold: 1,
}
.validate()
.is_err());
let policy = MultiSigPolicy {
name: "test".to_string(),
members: vec![
KeyOrChilds::Key(TEST_KEY_2.into()),
KeyOrChilds::Key(TEST_KEY.into()),
]
.into_boxed_slice(),
threshold: 1,
};
assert!(policy.validate().is_ok());
policy
.check_sigs(&[TEST_SIG.into()], TEST_DATA.as_bytes())
.unwrap();
policy
.check_sigs(&[TEST_SIG_2.into()], TEST_DATA.as_bytes())
.unwrap();
policy
.check_sigs(&[TEST_SIG.into(), TEST_SIG_2.into()], TEST_DATA.as_bytes())
.unwrap();
let policy = MultiSigPolicy {
name: "test".to_string(),
members: vec![
KeyOrChilds::Key(TEST_KEY_2.into()),
KeyOrChilds::Key(TEST_KEY.into()),
]
.into_boxed_slice(),
threshold: 2,
};
assert!(policy.validate().is_ok());
assert!(policy
.check_sigs(&[TEST_SIG.into()], TEST_DATA.as_bytes())
.is_err());
assert!(policy
.check_sigs(&[TEST_SIG_2.into()], TEST_DATA.as_bytes())
.is_err());
policy
.check_sigs(&[TEST_SIG.into(), TEST_SIG_2.into()], TEST_DATA.as_bytes())
.unwrap();
let policy = MultiSigPolicy {
name: "test".to_string(),
members: vec![
KeyOrChilds::Child(MultiSigPolicy {
name: "teamA".to_string(),
members: vec![KeyOrChilds::Key(TEST_KEY.into())].into_boxed_slice(),
threshold: 1,
}),
KeyOrChilds::Child(MultiSigPolicy {
name: "teamB".to_string(),
members: vec![KeyOrChilds::Key(TEST_KEY_2.into())].into_boxed_slice(),
threshold: 1,
}),
]
.into_boxed_slice(),
threshold: 2,
};
assert!(policy.validate().is_ok());
assert!(policy
.check_sigs(&[TEST_SIG.into()], TEST_DATA.as_bytes())
.is_err());
policy
.check_sigs(&[TEST_SIG.into(), TEST_SIG_2.into()], TEST_DATA.as_bytes())
.unwrap();
assert!(policy.validate().is_ok());
}
}

View file

@ -316,8 +316,9 @@ impl PrivateKey for RS256PrivateKey {
}
#[cfg(test)]
mod test {
mod tests {
use super::{Author, Body, Signature};
use test_log::test;
use testaso::testaso;
testaso! {

View file

@ -0,0 +1,734 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBF586L8BEADxCazcu1Aetijsryp7+BDHMe2CipKcLk9h/DGxW1Bu+jLxJkDN
PPIS5v8AZbQbRzqfaiK0rnpxuhk4iEAKQUxuh6wzgzqshMgB2n+wqobpYqtSn6Um
WQHqspydRj5w1rxV5ikxL/3MCAhZ/FAz6pMgH1j1mtzth1mdb9yyVTEFSLslapCf
bCXVlKSZeH8Hb3t3nL3Uzv925+MkIsq8qrNxe6HUiscm0aKm3jTCACfsqSo33q/W
TSrrDGeNvr9Ke9kJJczVb4pr66M0KVEGSz5aoFGZxAKHMXNJUu/f0H3s8RBXMQ/M
bcwngNpc1f4RVnO2zeCz/GeSwf+00nouD/xjuy2SlpUPMhs4Qp8r7/Vgi2kaO095
SOKc/hCoKspFY0vX3KVsHVIxyPMFTik4dmatQo4cJy4FW/dp3/2kyXf1HAnf0ZnK
2q8/iebylYxVio5X9UQ4hKIWgLUHu29crr515VPfGIidP+KNq6Lq49WAKPyVH1ex
hJSBoRiiSrNpAmYCubvHzZsIbC9UTCl2my1JahnHnSM4u18qwFki1n1Dj0BXof/Q
FjNIJEjN7b5hMaT0/+kIQN4kbMUhN+xR8HqGkQHrYC312ezKL+J7wI3+mIVSlr6I
88n6N8ZDNOPNHAUFBi9/7KiLGFdydAZT/l4gBvop/DTAzmPL9+RfxP3jNwARAQAB
tB9IYXJhbGQgSG95ZXIgPGhhcmFsZEBob3llci54eXo+iQNVBBMBCAE/AhsDAhkB
QBSAAAAAABAAJ3Byb29mQGFyaWFkbmUuaWRodHRwczovL2dpdGxhYi5jb20vaGFy
YWxkaC9naXRsYWJfcHJvb2ZZFIAAAAAAEABAcHJvb2ZAYXJpYWRuZS5pZGh0dHBz
Oi8vZ2lzdC5naXRodWIuY29tL2hhcmFsZGgvOWVjZjYzNGQ2NzQyZWFlZTRkOGM5
YjZjZDgyZTM0ODA4FIAAAAAAEAAfcHJvb2ZAYXJpYWRuZS5pZGh0dHBzOi8vZmxv
c3Muc29jaWFsL0BiYWNrc2xhc2gvFIAAAAAAEAAWcHJvb2ZAYXJpYWRuZS5pZGRu
czpob3llci54eXo/dHlwZT1UWFQCF4AWIQR/PWSCSsC2uACeUFBLwIlvtWk1lQUC
ZON15QULCQgHAgYVCgkICwIEFgIDAQIeBQAKCRBLwIlvtWk1lcagEADM/a0kcv0l
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
=hAu3
-----END PGP PUBLIC KEY BLOCK-----

View file

@ -1,16 +0,0 @@
mQGNBGTBKKQBDACo28S5h7rvfcj89OIv66evSsOExJJ363oYWBfs0GPkgPG/bS2pgIFe5+yqvW5q
2tnDYHz0WJkYQcwTqQQpt/Ma+UV+uaHc2pJfKvsmpI9o3xf+eV3C9HrU+6lwr8efkBkjLrfzkroQ
f0II/eX9omePt4qXNMX07UKI1ZrmXWmn5BlXiwkQl0M9XWwS3PZ2aiM2MMUjfmDAdi5pc10UgZdd
lbInjK8guXj9/HQt23l3W1df83QNlxC+sDmlekwugeg0HckcgTjGICvML+gwsX/GVDMJe/O8D7Sy
7KKrO23xwus7p8At4C5+0WCqARBKQbTE0IZTyUZUgt6xnn1BhFHBCblpI2KPkRXSUWBkb/Npr40Y
2uMiBZNk2Iwdyuim8+Zs5pHCISvR09COswFgM+K7ikv7EMMr1YsEcFGH4sE3GQXVw4qONdITNBAz
/5+cPWAOUOske6BeUjLaC4XaG4wY2Rg7RVoDCqhKav+VYE2B/X0pNVSfPyZKirkMllHVwA8AEQEA
AbQXdGVzdCA8dGVzdEBleGFtcGxlLmNvbT6JAdEEEwEIADsWIQSBoxLFnWedkw+p6LBtco8potur
+AUCZMEopAIbAwULCQgHAgIiAgYVCgkICwIEFgIDAQIeBwIXgAAKCRBtco8potur+Cb2C/9sc2VY
pi8eYnPrclU/28SoecG9cyPAZ5D+AQfAnVPLDdeBgLLr4FrMkRLvFNEoNwSFWAHNde77ChKFVPjq
s1ubR+P6RJ8YjeuF5l5objn/xXd+fe79gjBfWRVUR36+q9TvJwr51bL/cFNv0eGpvxV4OhiXImF9
9Ik3HtXX2w5b8rkH2DcW39HlQvxqOY3OTskmVn0nv5l6Q9CHrIXsaug11Bp/EQPyMG/E0Qa1SWCI
yDwphEQzIUFIBg0zlAUC2Tlh9PYrgZJ5GjNY18a0ZglwTp48IpwOUXwT9IzOKyrM1jA9lg8P5ih/
MLZKIMvroKrry+IZXQAujnvH0HwMehDuepR+liOx1byI2VitOkl7GpAZ03t+ae/KrsjJ+Dx/oFFk
DVQAF2dDJHiFzZD8DHucIngY4b8Wq7N+8hzyk8AgKFK9rq3HqPH5L+NsJEzS1xOQeaGlI1H1knnA
gRuIBZdZewrR/UosYei3mZtEclHU+YqeeBAsVoKKSVi2ryu8RCk=

View file

@ -1,26 +1,14 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEEC0Pk344t4+guABNk9RmhFDs/vjIFAmT5sBwACgkQ9RmhFDs/
vjIJ2g/9E8kRdvz8hhxOyJRPpNZ9bcGJ+FvMjG7geEdixqu1Bwpfyj+UhGRY7Dgq
4T46w/Hmr8YBZTI3xpafUSldyEvZnFXRuIQoBR+JQYNu8s9Jm9yDIyLLA86quiY8
nU+x6x89sSOOvmTpRUBi6htTC4h0zZHHfAcmu0YS2pMmxXYJX7Rw3T7AJE0Uc4O/
+0Ho1PMFB4BRmnNGlqBFc2u/yXEy38AWrmcheoPNtbdWmI/3leKikW5l2cXfPRuT
tazc92NiIK6qu209jlusMBpADdu8FSAI9ax4dKL1uE8KQyUIKQVQq3sBqQsPTgiW
XT6XznFdWawtW1y2jzt0DbdCt2osSwV7rPYbn6yxEpzQWuPL75JiDmJMktgBV38t
FKBpQl1ZDF9wARwsxBvNRaL0XPSurTtf/x4olue91D3I2fNeymS6P1DNXvLGXPD5
46C2TvS1305wPjCpFAEgS58WpiiJppCYDsU0A7DEHbaIgk5mQ/iEdBOBvrn0xton
Rni5mXt0Vi0WfE8GriR25YajtAOI2/rxTSZjiSJI51WmdnV/lkJiY1YF0ws+KUXG
r2E+Bea0kwcnCMYFzraxwLwiS4mgamdQmp8DNALYZe8m/k+dNKI6tDEdWFMTiwda
PJMDc3+lUOcZCN6+umLUOVvNWQZ2QtZ4RSTzbJyDww4ysgTpFHOJAcUEAAEIAC8W
IQSBoxLFnWedkw+p6LBtco8potur+AUCZPmwIREcdGVzdEBleGFtcGxlLmNvbQAK
CRBtco8potur+CMVDACm+OMPck8lmOnNGphP7kKtMcyMyIvsI2Ik/fB3A2z+iXnX
TQljubYTqN4Hzv5MECoUhm3GiWJOYjGoXnpec1zAk4VAewin1814Dldq/9CQ+YlN
W7HKjCiCBSdk2tPEBUK6gfV+OU9N2mNp/+biuwNTVHpPokIiwBE3MKjtUc0W0xLU
N+S/mb1l0MsA91PPRlZqovEFs6214zo8e31pXcWbLbfhbVY32pqDk4eG1JAFjjGM
oBASk7z1TH8Ealfj3xr8/HCbfyoaMcSmQzYdEr4E7XOp955IjRU91RrHxYjcxQ9f
0VUwak08k6hNBD502jstv5ePJBWoFXYXKuBlaH224Xvhe+9GnaUXsU8rI+OMHJes
g4/98+bparaQ8pjhLeh5BoIhojg0y4qNaFmbJraZxG3uhyH0nDVfepOsUj4QOadS
VbuULwAy97q+UFwUWuVn/XVzrb3B35TpIJWpvJLF6w5f3pyy58XsVOfVmNyyGuyU
jMWUGxIGAsXZusCmsNs=
=qVV5
iQHFBAABCAAvFiEEgaMSxZ1nnZMPqeiwbXKPKaLbq/gFAmaw3l4RHHRlc3RAZXhh
bXBsZS5jb20ACgkQbXKPKaLbq/jgCwwAnry/QNtlp5gagPAjcweL1J3K1vIsAMsN
GI9VUcM+1QtAlz3vLKfXKJXo4SpLS4TBPw/A7A4IATdEdYirp7dG3K6MtWnVl4P5
kNs39SUUlVC2RlfiMOS0NHCMz9lazJsmVjYT1qwdGiO/9BS1Yy1VVbWJuRsPPBRH
kF4WbGiMkW4x0H+8s0tFCMoq9hgqqqcyxMbE6GLHa8u57fhn1TRVGpClRZ/G86xw
1N9I3nKvRvX64AjG3SOslBKDeKM01EIICG81FOTj54pIAiyKY82nRlx5OsRxsSpV
7GvIqE47e+qCmL4WOMykq+B+DHdalH4/5+AWaGfKcZCibXOxHvimfOfBaM/nah9W
wFOGDRihW759yHPq/ZP7JCYqlMRrNoAjoBORJEn/HHYYskYy4KeZSLFUm1eKAxFi
mg2oL6LFZn5O466JrZ4c2b0hOpKBUdC/NkXSgv8O6SuxnFmxGkx8fsdtm+d0T4Ff
PBat77Pnv5bDJ1dOJ5HQlvivKKPU6SK1
=zQsO
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEEC0Pk344t4+guABNk9RmhFDs/vjIFAmaw1WoACgkQ9RmhFDs/
vjK4rRAArFtDoNwQsFVhFCIE3c4RNwfsgqZQp3RhdRBxw6DqCPjv0z41R2pQ5//r
TtKxtfqJqP5wdOHyk18ITd3AB49aRAIcgf2qq9t9Nygt0AR09IXKSFkozi+dtbIH
MR36zxa5DKejF6v6YiCrw6L2QGfDRYg/1IvLxdwyjGy4jwuNsRZJf4JSC8vWnm+n
EIVy4Fqcmd/kikLm1lhHaugIQ8u5HpHOP0uszhGAZHB5WPEHVOlnMKSODWZYSrvi
vhzQZEuvCWeFXH9qKmlC9DyJzUnnhCmnOkBZoSdOZIgnZfH2+pbyfRQ+7Hn8gbHB
VPCPOjRjvmR5EhHmuCdPTLZRl75mPlfQKVvBg5FMgMqXJYPlWSgJndPjWLtbiopD
7yTtrfesxXbJl2N/rSDWw3e3B7liWNgNOZGYY/xrKk/shlT+J2LJThQYvTcWXzdk
qHKGObiiDbZzwKDuTQ2NeI9JnbVk51JjqerhE6XkdGoCiGRyV7hUzF69m/vNnjD3
+saZRANRzkyxxGUvDZbuSNIXAtxcc57to593z38XRIJAaS3/S7+cbBqc0daPJJKH
06gYG2Ak/jE99kZ2P/ULp0I58My14keMBlCRhcl2Y4sq0KL67pBtsqvFh2Vm1hKl
7siJFYSWXkyFit4pVCH2SlJf7s0AB1OZsOATG6Oil3gHpny5ybo=
=X256
-----END PGP SIGNATURE-----

View file

@ -6,6 +6,7 @@ mod sgx {
use intel_tee_quote_verification_rs::{sgx_ql_qv_result_t, Collateral};
use std::time::{Duration, UNIX_EPOCH};
use teepot::sgx::{verify_quote_with_collateral, QuoteVerificationResult};
use test_log::test;
fn check_quote(
quote: &[u8],