commit
8bec269f71
5 changed files with 114 additions and 274 deletions
|
@ -10,10 +10,11 @@ license = "EUPL-1.2"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
tss-esapi = "6.1.1"
|
||||
serde = "1.0"
|
||||
biscuit = "0.5.0"
|
||||
josekit = "0.7.4"
|
||||
serde_json = "1.0"
|
||||
base64 = "0.12.1"
|
||||
atty = "0.2.14"
|
||||
tpm2-policy = "0.5.1"
|
||||
tpm2-policy = "0.5.3"
|
||||
|
|
37
src/cli.rs
37
src/cli.rs
|
@ -1,12 +1,11 @@
|
|||
use std::convert::TryFrom;
|
||||
|
||||
use super::PinError;
|
||||
use crate::utils::get_authorized_policy_step;
|
||||
|
||||
use anyhow::{anyhow, bail, Error, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use tpm2_policy::TPMPolicyStep;
|
||||
|
||||
use crate::utils::get_authorized_policy_step;
|
||||
|
||||
#[derive(Serialize, Deserialize, std::fmt::Debug)]
|
||||
pub(super) struct TPM2Config {
|
||||
pub hash: Option<String>,
|
||||
|
@ -24,9 +23,9 @@ pub(super) struct TPM2Config {
|
|||
}
|
||||
|
||||
impl TryFrom<&TPM2Config> for TPMPolicyStep {
|
||||
type Error = PinError;
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(cfg: &TPM2Config) -> Result<Self, PinError> {
|
||||
fn try_from(cfg: &TPM2Config) -> Result<Self> {
|
||||
if cfg.pcr_ids.is_some() && cfg.policy_pubkey_path.is_some() {
|
||||
Ok(TPMPolicyStep::Or([
|
||||
Box::new(TPMPolicyStep::PCRs(
|
||||
|
@ -104,7 +103,7 @@ impl TPM2Config {
|
|||
}
|
||||
}
|
||||
|
||||
fn normalize(mut self) -> Result<TPM2Config, PinError> {
|
||||
fn normalize(mut self) -> Result<TPM2Config> {
|
||||
self.normalize_pcr_ids()?;
|
||||
if self.pcr_ids.is_some() && self.pcr_bank.is_none() {
|
||||
self.pcr_bank = Some("sha256".to_string());
|
||||
|
@ -133,14 +132,12 @@ impl TPM2Config {
|
|||
|| self.policy_path.is_none()
|
||||
|| self.policy_ref.is_none())
|
||||
{
|
||||
return Err(PinError::Text(
|
||||
"Not all of policy pubkey, path and ref are specified",
|
||||
));
|
||||
bail!("Not all of policy pubkey, path and ref are specified",);
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn normalize_pcr_ids(&mut self) -> Result<(), PinError> {
|
||||
fn normalize_pcr_ids(&mut self) -> Result<()> {
|
||||
// Normalize from array with one string to just string
|
||||
if let Some(serde_json::Value::Array(vals)) = &self.pcr_ids {
|
||||
if vals.len() == 1 {
|
||||
|
@ -168,21 +165,21 @@ impl TPM2Config {
|
|||
Ok(res) => {
|
||||
let new = serde_json::Value::Number(res);
|
||||
if !new.is_u64() {
|
||||
return Err("Non-positive string int");
|
||||
bail!("Non-positive string int");
|
||||
}
|
||||
Ok(new)
|
||||
}
|
||||
Err(_) => Err("Unparseable string int"),
|
||||
Err(_) => Err(anyhow!("Unparseable string int")),
|
||||
}
|
||||
}
|
||||
serde_json::Value::Number(n) => {
|
||||
let new = serde_json::Value::Number(n.clone());
|
||||
if !new.is_u64() {
|
||||
return Err("Non-positive int");
|
||||
return Err(anyhow!("Non-positive int"));
|
||||
}
|
||||
Ok(new)
|
||||
}
|
||||
_ => Err("Invalid value in pcr_ids"),
|
||||
_ => Err(anyhow!("Invalid value in pcr_ids")),
|
||||
})
|
||||
.collect();
|
||||
self.pcr_ids = Some(serde_json::Value::Array(newvals?));
|
||||
|
@ -192,7 +189,7 @@ impl TPM2Config {
|
|||
None => Ok(()),
|
||||
// The normalization above would've caught any non-ints
|
||||
Some(serde_json::Value::Array(_)) => Ok(()),
|
||||
_ => Err(PinError::Text("Invalid type")),
|
||||
_ => Err(anyhow!("Invalid type")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -205,9 +202,7 @@ pub(super) enum ActionMode {
|
|||
Help,
|
||||
}
|
||||
|
||||
pub(super) fn get_mode_and_cfg(
|
||||
args: &[String],
|
||||
) -> Result<(ActionMode, Option<TPM2Config>), PinError> {
|
||||
pub(super) fn get_mode_and_cfg(args: &[String]) -> Result<(ActionMode, Option<TPM2Config>)> {
|
||||
if args.len() > 1 && args[1] == "--summary" {
|
||||
return Ok((ActionMode::Summary, None));
|
||||
}
|
||||
|
@ -227,10 +222,10 @@ pub(super) fn get_mode_and_cfg(
|
|||
} else if args[1] == "decrypt" {
|
||||
(ActionMode::Decrypt, None)
|
||||
} else {
|
||||
return Err(PinError::NoCommand);
|
||||
bail!("No command specified");
|
||||
}
|
||||
} else {
|
||||
return Err(PinError::NoCommand);
|
||||
bail!("No command specified");
|
||||
};
|
||||
|
||||
let cfg: Option<TPM2Config> = match cfgstr {
|
||||
|
|
256
src/main.rs
256
src/main.rs
|
@ -13,18 +13,14 @@
|
|||
// limitations under the License.
|
||||
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
use std::env;
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
use biscuit::jwe;
|
||||
use biscuit::CompactJson;
|
||||
|
||||
use anyhow::{bail, Context, Error, Result};
|
||||
use josekit::jwe::{alg::direct::DirectJweAlgorithm::Dir, enc::A256GCM};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use tpm2_policy::TPMPolicyStep;
|
||||
use tss_esapi::structures::SensitiveData;
|
||||
|
||||
mod cli;
|
||||
mod tpm_objects;
|
||||
|
@ -32,116 +28,7 @@ mod utils;
|
|||
|
||||
use cli::TPM2Config;
|
||||
|
||||
use tss_esapi::structures::SensitiveData;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum PinError {
|
||||
Text(&'static str),
|
||||
NoCommand,
|
||||
Serde(serde_json::Error),
|
||||
IO(std::io::Error),
|
||||
TPM(tss_esapi::Error),
|
||||
JWE(biscuit::errors::Error),
|
||||
Base64Decoding(base64::DecodeError),
|
||||
Utf8(std::str::Utf8Error),
|
||||
FromUtf8(std::string::FromUtf8Error),
|
||||
PolicyError(tpm2_policy::Error),
|
||||
}
|
||||
|
||||
impl PinError {}
|
||||
|
||||
impl fmt::Display for PinError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
PinError::Text(e) => write!(f, "Error: {}", e),
|
||||
PinError::Serde(err) => {
|
||||
write!(f, "Serde error: ")?;
|
||||
err.fmt(f)
|
||||
}
|
||||
PinError::IO(err) => {
|
||||
write!(f, "IO error: ")?;
|
||||
err.fmt(f)
|
||||
}
|
||||
PinError::TPM(err) => {
|
||||
write!(f, "TPM error: ")?;
|
||||
err.fmt(f)
|
||||
}
|
||||
PinError::JWE(err) => {
|
||||
write!(f, "JWE error: ")?;
|
||||
err.fmt(f)
|
||||
}
|
||||
PinError::Base64Decoding(err) => {
|
||||
write!(f, "Base64 Decoding error: ")?;
|
||||
err.fmt(f)
|
||||
}
|
||||
PinError::Utf8(err) => {
|
||||
write!(f, "UTF8 error: ")?;
|
||||
err.fmt(f)
|
||||
}
|
||||
PinError::FromUtf8(err) => {
|
||||
write!(f, "UTF8 error: ")?;
|
||||
err.fmt(f)
|
||||
}
|
||||
PinError::NoCommand => write!(f, "No command provided"),
|
||||
PinError::PolicyError(err) => {
|
||||
write!(f, "Policy Error: ")?;
|
||||
err.fmt(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for PinError {}
|
||||
|
||||
impl From<std::io::Error> for PinError {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
PinError::IO(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<tpm2_policy::Error> for PinError {
|
||||
fn from(err: tpm2_policy::Error) -> Self {
|
||||
PinError::PolicyError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&'static str> for PinError {
|
||||
fn from(err: &'static str) -> Self {
|
||||
PinError::Text(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for PinError {
|
||||
fn from(err: serde_json::Error) -> Self {
|
||||
PinError::Serde(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<tss_esapi::Error> for PinError {
|
||||
fn from(err: tss_esapi::Error) -> Self {
|
||||
PinError::TPM(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<biscuit::errors::Error> for PinError {
|
||||
fn from(err: biscuit::errors::Error) -> Self {
|
||||
PinError::JWE(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<base64::DecodeError> for PinError {
|
||||
fn from(err: base64::DecodeError) -> Self {
|
||||
PinError::Base64Decoding(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::str::Utf8Error> for PinError {
|
||||
fn from(err: std::str::Utf8Error) -> Self {
|
||||
PinError::Utf8(err)
|
||||
}
|
||||
}
|
||||
|
||||
fn perform_encrypt(cfg: TPM2Config, input: Vec<u8>) -> Result<(), PinError> {
|
||||
fn perform_encrypt(cfg: TPM2Config, input: Vec<u8>) -> Result<()> {
|
||||
let key_type = match &cfg.key {
|
||||
None => "ecc",
|
||||
Some(key_type) => key_type,
|
||||
|
@ -161,17 +48,9 @@ fn perform_encrypt(cfg: TPM2Config, input: Vec<u8>) -> Result<(), PinError> {
|
|||
|
||||
let (_, policy_digest) = policy_runner.send_policy(&mut ctx, true)?;
|
||||
|
||||
let key_bytes = ctx.get_random(32)?;
|
||||
let key_bytes: &[u8] = key_bytes.value();
|
||||
let mut jwk = biscuit::jwk::JWK::new_octet_key(&key_bytes, biscuit::Empty {});
|
||||
jwk.common.algorithm = Some(biscuit::jwa::Algorithm::ContentEncryption(
|
||||
biscuit::jwa::ContentEncryptionAlgorithm::A256GCM,
|
||||
));
|
||||
jwk.common.key_operations = Some(vec![
|
||||
biscuit::jwk::KeyOperations::Encrypt,
|
||||
biscuit::jwk::KeyOperations::Decrypt,
|
||||
]);
|
||||
let jwk_str = serde_json::to_string(&jwk)?;
|
||||
let mut jwk = josekit::jwk::Jwk::generate_oct_key(32).context("Error generating random JWK")?;
|
||||
jwk.set_key_operations(vec!["encrypt", "decrypt"]);
|
||||
let jwk_str = serde_json::to_string(&jwk.as_ref())?;
|
||||
|
||||
let public = tpm_objects::create_tpm2b_public_sealed_object(policy_digest)?;
|
||||
let jwk_str = SensitiveData::try_from(jwk_str.as_bytes().to_vec())?;
|
||||
|
@ -183,27 +62,7 @@ fn perform_encrypt(cfg: TPM2Config, input: Vec<u8>) -> Result<(), PinError> {
|
|||
|
||||
let jwk_pub = tpm_objects::get_tpm2b_public(jwk_result.out_public)?;
|
||||
|
||||
let hdr: biscuit::jwe::Header<ClevisHeader> = biscuit::jwe::Header {
|
||||
registered: biscuit::jwe::RegisteredHeader {
|
||||
cek_algorithm: biscuit::jwa::KeyManagementAlgorithm::DirectSymmetricKey,
|
||||
enc_algorithm: biscuit::jwa::ContentEncryptionAlgorithm::A256GCM,
|
||||
compression_algorithm: None,
|
||||
media_type: None,
|
||||
content_type: None,
|
||||
web_key_url: None,
|
||||
web_key: None,
|
||||
key_id: None,
|
||||
x509_url: None,
|
||||
x509_chain: None,
|
||||
x509_fingerprint: None,
|
||||
critical: None,
|
||||
},
|
||||
cek_algorithm: biscuit::jwe::CekAlgorithmHeader {
|
||||
nonce: None,
|
||||
tag: None,
|
||||
},
|
||||
private: ClevisHeader {
|
||||
clevis: ClevisInner {
|
||||
let private_hdr = ClevisInner {
|
||||
pin: pin_type.to_string(),
|
||||
tpm2: Tpm2Inner {
|
||||
hash: cfg.hash.as_ref().unwrap_or(&"sha256".to_string()).clone(),
|
||||
|
@ -216,19 +75,24 @@ fn perform_encrypt(cfg: TPM2Config, input: Vec<u8>) -> Result<(), PinError> {
|
|||
policy_ref: cfg.policy_ref,
|
||||
policy_path: cfg.policy_path,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let rand_nonce = ctx.get_random(12)?;
|
||||
let jwe_enc_options = biscuit::jwa::EncryptionOptions::AES_GCM {
|
||||
nonce: rand_nonce.value().to_vec(),
|
||||
};
|
||||
let mut hdr = josekit::jwe::JweHeader::new();
|
||||
hdr.set_algorithm(Dir.name());
|
||||
hdr.set_content_encryption(A256GCM.name());
|
||||
hdr.set_claim(
|
||||
"clevis",
|
||||
Some(serde_json::value::to_value(private_hdr).context("Error serializing private header")?),
|
||||
)
|
||||
.context("Error adding clevis claim")?;
|
||||
|
||||
let jwe_token = biscuit::jwe::Compact::new_decrypted(hdr, input);
|
||||
let jwe_token_compact = jwe_token.encrypt(&jwk, &jwe_enc_options)?;
|
||||
let encoded_token = jwe_token_compact.encrypted()?.encode();
|
||||
io::stdout().write_all(encoded_token.as_bytes())?;
|
||||
let encrypter = Dir
|
||||
.encrypter_from_jwk(&jwk)
|
||||
.context("Error creating direct encrypter")?;
|
||||
let jwe_token = josekit::jwe::serialize_compact(&input, &hdr, &encrypter)
|
||||
.context("Error serializing JWE token")?;
|
||||
|
||||
io::stdout().write_all(jwe_token.as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -276,9 +140,9 @@ impl Tpm2Inner {
|
|||
}
|
||||
|
||||
impl TryFrom<&Tpm2Inner> for TPMPolicyStep {
|
||||
type Error = PinError;
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(cfg: &Tpm2Inner) -> Result<Self, PinError> {
|
||||
fn try_from(cfg: &Tpm2Inner) -> Result<Self> {
|
||||
if cfg.pcr_ids.is_some() && cfg.policy_pubkey_path.is_some() {
|
||||
Ok(TPMPolicyStep::Or([
|
||||
Box::new(TPMPolicyStep::PCRs(
|
||||
|
@ -322,31 +186,24 @@ struct ClevisInner {
|
|||
tpm2: Tpm2Inner,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
struct ClevisHeader {
|
||||
clevis: ClevisInner,
|
||||
fn perform_decrypt(input: Vec<u8>) -> Result<()> {
|
||||
let input = String::from_utf8(input).context("Error reading input")?;
|
||||
let hdr = josekit::jwt::decode_header(&input).context("Error decoding header")?;
|
||||
let hdr_clevis = hdr.claim("clevis").context("Error getting clevis claim")?;
|
||||
let hdr_clevis: ClevisInner =
|
||||
serde_json::from_value(hdr_clevis.clone()).context("Error deserializing clevis header")?;
|
||||
|
||||
if hdr_clevis.pin != "tpm2" && hdr_clevis.pin != "tpm2plus" {
|
||||
bail!("JWE pin mismatch");
|
||||
}
|
||||
|
||||
impl CompactJson for Tpm2Inner {}
|
||||
impl CompactJson for ClevisHeader {}
|
||||
impl CompactJson for ClevisInner {}
|
||||
let jwkpub = tpm_objects::build_tpm2b_public(&hdr_clevis.tpm2.jwk_pub)?;
|
||||
let jwkpriv = tpm_objects::build_tpm2b_private(&hdr_clevis.tpm2.jwk_priv)?;
|
||||
|
||||
fn perform_decrypt(input: Vec<u8>) -> Result<(), PinError> {
|
||||
let input = String::from_utf8(input).map_err(PinError::FromUtf8)?;
|
||||
let token = biscuit::Compact::decode(input.trim());
|
||||
let hdr: biscuit::jwe::Header<ClevisHeader> = token.part(0)?;
|
||||
let policy = TPMPolicyStep::try_from(&hdr_clevis.tpm2)?;
|
||||
|
||||
if hdr.private.clevis.pin != "tpm2" && hdr.private.clevis.pin != "tpm2plus" {
|
||||
return Err(PinError::Text("JWE pin mismatch"));
|
||||
}
|
||||
|
||||
let jwkpub = tpm_objects::build_tpm2b_public(&hdr.private.clevis.tpm2.jwk_pub)?;
|
||||
let jwkpriv = tpm_objects::build_tpm2b_private(&hdr.private.clevis.tpm2.jwk_priv)?;
|
||||
|
||||
let policy = TPMPolicyStep::try_from(&hdr.private.clevis.tpm2)?;
|
||||
|
||||
let name_alg = crate::utils::get_hash_alg_from_name(Some(&hdr.private.clevis.tpm2.hash));
|
||||
let key_public = tpm_objects::get_key_public(hdr.private.clevis.tpm2.key.as_str(), name_alg)?;
|
||||
let name_alg = crate::utils::get_hash_alg_from_name(Some(&hdr_clevis.tpm2.hash));
|
||||
let key_public = tpm_objects::get_key_public(hdr_clevis.tpm2.key.as_str(), name_alg)?;
|
||||
|
||||
let mut ctx = utils::get_tpm2_ctx()?;
|
||||
let key_handle = utils::get_tpm2_primary_key(&mut ctx, &key_public)?;
|
||||
|
@ -358,20 +215,16 @@ fn perform_decrypt(input: Vec<u8>) -> Result<(), PinError> {
|
|||
|
||||
let unsealed = ctx.execute_with_session(policy_session, |ctx| ctx.unseal(key.into()))?;
|
||||
let unsealed = &unsealed.value();
|
||||
let unsealed = std::str::from_utf8(unsealed)?;
|
||||
let jwk: biscuit::jwk::JWK<biscuit::Empty> = serde_json::from_str(unsealed)?;
|
||||
let mut jwk = josekit::jwk::Jwk::from_bytes(unsealed).context("Error unmarshaling JWK")?;
|
||||
jwk.set_algorithm(Dir.name());
|
||||
let decrypter = Dir
|
||||
.decrypter_from_jwk(&jwk)
|
||||
.context("Error creating decrypter")?;
|
||||
|
||||
let token: biscuit::jwe::Compact<Vec<u8>, biscuit::Empty> = jwe::Compact::Encrypted(token);
|
||||
let (payload, _) =
|
||||
josekit::jwe::deserialize_compact(&input, &decrypter).context("Error decrypting JWE")?;
|
||||
|
||||
let token = token.decrypt(
|
||||
&jwk,
|
||||
biscuit::jwa::KeyManagementAlgorithm::DirectSymmetricKey,
|
||||
biscuit::jwa::ContentEncryptionAlgorithm::A256GCM,
|
||||
)?;
|
||||
// We just decrypted the token, there should be a payload
|
||||
let payload = token.payload()?;
|
||||
|
||||
io::stdout().write_all(payload)?;
|
||||
io::stdout().write_all(&payload)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -411,7 +264,7 @@ This command uses the following configuration properties:
|
|||
std::process::exit(2);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<()> {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let (mode, cfg) = match cli::get_mode_and_cfg(&args) {
|
||||
Err(e) => {
|
||||
|
@ -422,8 +275,8 @@ fn main() {
|
|||
};
|
||||
|
||||
match mode {
|
||||
cli::ActionMode::Summary => return print_summary(),
|
||||
cli::ActionMode::Help => return print_help(),
|
||||
cli::ActionMode::Summary => return Ok(print_summary()),
|
||||
cli::ActionMode::Help => return Ok(print_help()),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
|
@ -433,13 +286,10 @@ fn main() {
|
|||
std::process::exit(1);
|
||||
}
|
||||
|
||||
if let Err(e) = match mode {
|
||||
match mode {
|
||||
cli::ActionMode::Encrypt => perform_encrypt(cfg.unwrap(), input),
|
||||
cli::ActionMode::Decrypt => perform_decrypt(input),
|
||||
cli::ActionMode::Summary => panic!("Summary was already handled supposedly"),
|
||||
cli::ActionMode::Help => panic!("Help was already handled supposedly"),
|
||||
} {
|
||||
eprintln!("Error executing command: {}", e);
|
||||
std::process::exit(2);
|
||||
cli::ActionMode::Summary => unreachable!(),
|
||||
cli::ActionMode::Help => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::convert::TryFrom;
|
||||
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use tss_esapi::attributes::object::ObjectAttributesBuilder;
|
||||
use tss_esapi::constants::tss as tss_constants;
|
||||
use tss_esapi::interface_types::ecc::EccCurve;
|
||||
|
@ -12,12 +13,10 @@ type Sizedu = u64;
|
|||
#[cfg(target_pointer_width = "32")]
|
||||
type Sizedu = u32;
|
||||
|
||||
use crate::PinError;
|
||||
|
||||
pub(super) fn get_key_public(
|
||||
key_type: &str,
|
||||
name_alg: HashingAlgorithm,
|
||||
) -> Result<tss_esapi::tss2_esys::TPM2B_PUBLIC, PinError> {
|
||||
) -> Result<tss_esapi::tss2_esys::TPM2B_PUBLIC> {
|
||||
match key_type {
|
||||
"ecc" => Ok(create_restricted_ecc_public()),
|
||||
"rsa" => Ok(tss_esapi::utils::create_restricted_decryption_rsa_public(
|
||||
|
@ -25,8 +24,9 @@ pub(super) fn get_key_public(
|
|||
2048,
|
||||
0,
|
||||
)?),
|
||||
_ => Err(PinError::Text("Unsupported key type used")),
|
||||
}.map(|mut public| {
|
||||
_ => Err(anyhow!("Unsupported key type used")),
|
||||
}
|
||||
.map(|mut public| {
|
||||
public.publicArea.nameAlg = name_alg.into();
|
||||
public
|
||||
})
|
||||
|
@ -34,7 +34,7 @@ pub(super) fn get_key_public(
|
|||
|
||||
pub(super) fn create_tpm2b_public_sealed_object(
|
||||
policy: Option<Digest>,
|
||||
) -> Result<tss_esapi::tss2_esys::TPM2B_PUBLIC, PinError> {
|
||||
) -> Result<tss_esapi::tss2_esys::TPM2B_PUBLIC> {
|
||||
let mut object_attributes = ObjectAttributesBuilder::new()
|
||||
.with_fixed_tpm(true)
|
||||
.with_fixed_parent(true)
|
||||
|
@ -65,9 +65,7 @@ pub(super) fn create_tpm2b_public_sealed_object(
|
|||
})
|
||||
}
|
||||
|
||||
pub(super) fn get_tpm2b_public(
|
||||
val: tss_esapi::tss2_esys::TPM2B_PUBLIC,
|
||||
) -> Result<Vec<u8>, PinError> {
|
||||
pub(super) fn get_tpm2b_public(val: tss_esapi::tss2_esys::TPM2B_PUBLIC) -> Result<Vec<u8>> {
|
||||
let mut offset = 0 as Sizedu;
|
||||
let mut resp = Vec::with_capacity((val.size + 4) as usize);
|
||||
|
||||
|
@ -79,7 +77,7 @@ pub(super) fn get_tpm2b_public(
|
|||
&mut offset,
|
||||
);
|
||||
if res != 0 {
|
||||
return Err(PinError::Text("Marshalling tpm2b_public failed"));
|
||||
bail!("Marshalling tpm2b_public failed");
|
||||
}
|
||||
resp.set_len(offset as usize);
|
||||
}
|
||||
|
@ -87,9 +85,7 @@ pub(super) fn get_tpm2b_public(
|
|||
Ok(resp)
|
||||
}
|
||||
|
||||
pub(super) fn get_tpm2b_private(
|
||||
val: tss_esapi::tss2_esys::TPM2B_PRIVATE,
|
||||
) -> Result<Vec<u8>, PinError> {
|
||||
pub(super) fn get_tpm2b_private(val: tss_esapi::tss2_esys::TPM2B_PRIVATE) -> Result<Vec<u8>> {
|
||||
let mut offset = 0 as Sizedu;
|
||||
let mut resp = Vec::with_capacity((val.size + 4) as usize);
|
||||
|
||||
|
@ -101,7 +97,7 @@ pub(super) fn get_tpm2b_private(
|
|||
&mut offset,
|
||||
);
|
||||
if res != 0 {
|
||||
return Err(PinError::Text("Marshalling tpm2b_private failed"));
|
||||
bail!("Marshalling tpm2b_private failed");
|
||||
}
|
||||
resp.set_len(offset as usize);
|
||||
}
|
||||
|
@ -109,9 +105,7 @@ pub(super) fn get_tpm2b_private(
|
|||
Ok(resp)
|
||||
}
|
||||
|
||||
pub(super) fn build_tpm2b_private(
|
||||
val: &[u8],
|
||||
) -> Result<tss_esapi::tss2_esys::TPM2B_PRIVATE, PinError> {
|
||||
pub(super) fn build_tpm2b_private(val: &[u8]) -> Result<tss_esapi::tss2_esys::TPM2B_PRIVATE> {
|
||||
let mut resp = tss_esapi::tss2_esys::TPM2B_PRIVATE::default();
|
||||
let mut offset = 0 as Sizedu;
|
||||
|
||||
|
@ -123,16 +117,14 @@ pub(super) fn build_tpm2b_private(
|
|||
&mut resp,
|
||||
);
|
||||
if res != 0 {
|
||||
return Err(PinError::Text("Unmarshalling tpm2b_private failed"));
|
||||
bail!("Unmarshalling tpm2b_private failed");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(resp)
|
||||
}
|
||||
|
||||
pub(super) fn build_tpm2b_public(
|
||||
val: &[u8],
|
||||
) -> Result<tss_esapi::tss2_esys::TPM2B_PUBLIC, PinError> {
|
||||
pub(super) fn build_tpm2b_public(val: &[u8]) -> Result<tss_esapi::tss2_esys::TPM2B_PUBLIC> {
|
||||
let mut resp = tss_esapi::tss2_esys::TPM2B_PUBLIC::default();
|
||||
let mut offset = 0 as Sizedu;
|
||||
|
||||
|
@ -144,7 +136,7 @@ pub(super) fn build_tpm2b_public(
|
|||
&mut resp,
|
||||
);
|
||||
if res != 0 {
|
||||
return Err(PinError::Text("Unmarshalling tpm2b_public failed"));
|
||||
bail!("Unmarshalling tpm2b_public failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
34
src/utils.rs
34
src/utils.rs
|
@ -2,38 +2,40 @@ use std::env;
|
|||
use std::fs;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{Context as anyhow_context, Result};
|
||||
use serde::Deserialize;
|
||||
use tpm2_policy::{PublicKey, SignedPolicyList, TPMPolicyStep};
|
||||
use tss_esapi::{
|
||||
handles::KeyHandle,
|
||||
interface_types::{algorithm::HashingAlgorithm, resource_handles::Hierarchy},
|
||||
Context, Tcti,
|
||||
};
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::PinError;
|
||||
|
||||
use tpm2_policy::{PublicKey, SignedPolicyList, TPMPolicyStep};
|
||||
|
||||
pub(crate) fn get_authorized_policy_step(
|
||||
policy_pubkey_path: &str,
|
||||
policy_path: &Option<String>,
|
||||
policy_ref: &Option<String>,
|
||||
) -> Result<TPMPolicyStep, PinError> {
|
||||
) -> Result<TPMPolicyStep> {
|
||||
let policy_ref = match policy_ref {
|
||||
Some(policy_ref) => policy_ref.as_bytes().to_vec(),
|
||||
None => vec![],
|
||||
};
|
||||
|
||||
let signkey = {
|
||||
let contents = fs::read_to_string(policy_pubkey_path)?;
|
||||
serde_json::from_str::<PublicKey>(&contents)?
|
||||
let contents =
|
||||
fs::read_to_string(policy_pubkey_path).context("Error reading policy signkey")?;
|
||||
serde_json::from_str::<PublicKey>(&contents)
|
||||
.context("Error deserializing signing public key")?
|
||||
};
|
||||
|
||||
let policies = match policy_path {
|
||||
None => None,
|
||||
Some(policy_path) => {
|
||||
let contents = fs::read_to_string(policy_path)?;
|
||||
Some(serde_json::from_str::<SignedPolicyList>(&contents)?)
|
||||
let contents = fs::read_to_string(policy_path).context("Error reading policy")?;
|
||||
Some(
|
||||
serde_json::from_str::<SignedPolicyList>(&contents)
|
||||
.context("Error deserializing policy")?,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -53,7 +55,7 @@ pub(crate) fn get_hash_alg_from_name(name: Option<&String>) -> HashingAlgorithm
|
|||
"sha256" => HashingAlgorithm::Sha256,
|
||||
"sha384" => HashingAlgorithm::Sha384,
|
||||
"sha512" => HashingAlgorithm::Sha512,
|
||||
_ => panic!(format!("Unsupported hash algo: {:?}", name)),
|
||||
_ => panic!("Unsupported hash algo: {:?}", name),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +79,7 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn get_tpm2_ctx() -> Result<tss_esapi::Context, tss_esapi::Error> {
|
||||
pub(crate) fn get_tpm2_ctx() -> Result<tss_esapi::Context> {
|
||||
let tcti_path = match env::var("TCTI") {
|
||||
Ok(val) => val,
|
||||
Err(_) => {
|
||||
|
@ -89,14 +91,14 @@ pub(crate) fn get_tpm2_ctx() -> Result<tss_esapi::Context, tss_esapi::Error> {
|
|||
}
|
||||
};
|
||||
|
||||
let tcti = Tcti::from_str(&tcti_path)?;
|
||||
unsafe { Context::new(tcti) }
|
||||
let tcti = Tcti::from_str(&tcti_path).context("Error parsing TCTI specification")?;
|
||||
Context::new(tcti).context("Error initializing TPM2 context")
|
||||
}
|
||||
|
||||
pub(crate) fn get_tpm2_primary_key(
|
||||
ctx: &mut Context,
|
||||
pub_template: &tss_esapi::tss2_esys::TPM2B_PUBLIC,
|
||||
) -> Result<KeyHandle, PinError> {
|
||||
) -> Result<KeyHandle> {
|
||||
ctx.execute_with_nullauth_session(|ctx| {
|
||||
ctx.create_primary(Hierarchy::Owner, pub_template, None, None, None, None)
|
||||
.map(|r| r.key_handle)
|
||||
|
|
Loading…
Reference in a new issue