Skip to content

Commit

Permalink
Fixes problem with sign requiring a HashcheckTicket.
Browse files Browse the repository at this point in the history
- This fixes parallaxsecond#475 by making the HashcheckTicket that was
  previously required in the ```sign``` context method
  optional instead. If it is ```None``` it is then internally
  converted into the HashcheckTicket version of the `Null ticket`
  before being converted to the corresponding TSS type.
  This has the benefit of removing the need to use the TSS type in
  order to create a `Null ticket`.

Signed-off-by: Jesper Brynolf <[email protected]>
  • Loading branch information
Superhepper committed Dec 11, 2023
1 parent 2dfc315 commit 5ded0e7
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 66 deletions.
15 changes: 2 additions & 13 deletions tss-esapi/src/abstraction/transient/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//! client.
use crate::{
attributes::{ObjectAttributesBuilder, SessionAttributesBuilder},
constants::{tss::*, SessionType, TpmFormatZeroError},
constants::{SessionType, TpmFormatZeroError},
error::{TpmFormatZeroResponseCode, TpmResponseCode},
handles::{KeyHandle, SessionHandle},
interface_types::{
Expand All @@ -23,7 +23,6 @@ use crate::{
RsaScheme, Signature, SignatureScheme, SymmetricDefinitionObject, VerifiedTicket,
},
tcti_ldr::TctiNameConf,
tss2_esys::*,
utils::{create_restricted_decryption_rsa_public, PublicKey, TpmsContext},
Context, Error, Result, ReturnCode, WrapperErrorKind as ErrorKind,
};
Expand Down Expand Up @@ -287,20 +286,10 @@ impl TransientKeyContext {
) -> Result<Signature> {
let key_handle = self.load_key(key_params, key_material, key_auth)?;

let validation = TPMT_TK_HASHCHECK {
tag: TPM2_ST_HASHCHECK,
hierarchy: TPM2_RH_NULL,
digest: Default::default(),
};
self.set_session_attrs()?;
let signature = self
.context
.sign(
key_handle,
digest,
SignatureScheme::Null,
validation.try_into()?,
)
.sign(key_handle, digest, SignatureScheme::Null, None)
.or_else(|e| {
self.context.flush_context(key_handle.into())?;
Err(e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,66 @@ impl Context {
}

/// Sign a digest with a key present in the TPM and return the signature.
///
/// # Details
/// For signatures using a restricted key, a hashcheck must be provided. For unrestricted keys, this may be None.
///
/// # Parameters
/// `key_handle` - Handle to the key be used for signing.
/// `digest` - The digest that is going to be signed.
/// `scheme` - The scheme to use if the scheme for the key referenced by the key handle is null.
/// `validation` - An optional [HashcheckTicket] that proof that the digest was created by the TPM.
/// N.B. None will be treated as a "Null ticket".
/// # Example
///
/// ```rust
/// # use tss_esapi::{Context, TctiNameConf,
/// # interface_types::{
/// # algorithm::{HashingAlgorithm, RsaSchemeAlgorithm},
/// # key_bits::RsaKeyBits,
/// # resource_handles::Hierarchy,
/// # },
/// # structures::{RsaScheme, RsaExponent},
/// # utils::create_unrestricted_signing_rsa_public
/// # };
/// use tss_esapi::structures::SignatureScheme;
/// # let mut context =
/// # Context::new(
/// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
/// # ).expect("Failed to create Context");
/// # let signing_key_pub = create_unrestricted_signing_rsa_public(
/// # RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256))
/// # .expect("Failed to create RSA scheme"),
/// # RsaKeyBits::Rsa2048,
/// # RsaExponent::default(),
/// # )
/// # .expect("Failed to create an unrestricted signing rsa public structure");
/// # let unrestricted_signing_key_handle = context
/// # .execute_with_nullauth_session(|ctx| {
/// # ctx.create_primary(Hierarchy::Owner, signing_key_pub, None, None, None, None)
/// # })
/// # .unwrap()
/// # .key_handle;
/// # let digest = context.get_random(32).unwrap();
/// let signature = context.execute_with_nullauth_session(|ctx| {
/// ctx.sign(
/// unrestricted_signing_key_handle,
/// digest,
/// SignatureScheme::Null,
/// None,
/// )
/// })
/// .expect("Failed to sign digest");
/// ```
pub fn sign(
&mut self,
key_handle: KeyHandle,
digest: Digest,
scheme: SignatureScheme,
validation: HashcheckTicket,
validation: impl Into<Option<HashcheckTicket>>,
) -> Result<Signature> {
let mut signature_ptr = null_mut();
let validation_ticket = validation.into().unwrap_or_default().try_into()?;
ReturnCode::ensure_success(
unsafe {
Esys_Sign(
Expand All @@ -58,7 +110,7 @@ impl Context {
self.optional_session_3(),
&digest.into(),
&scheme.into(),
&validation.try_into()?,
&validation_ticket,
&mut signature_ptr,
)
},
Expand Down
16 changes: 15 additions & 1 deletion tss-esapi/src/structures/tickets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use crate::{
};

use log::error;
use std::convert::{TryFrom, TryInto};
use std::{
convert::{TryFrom, TryInto},
default::Default,
};

/// Macro used for implementing try_from
/// TssTicketType -> TicketType
Expand Down Expand Up @@ -124,6 +127,17 @@ pub struct HashcheckTicket {
digest: Vec<u8>,
}

impl Default for HashcheckTicket {
/// The default for the Hashcheck ticket is the Null ticket.
fn default() -> Self {
Self {
tag: StructureTag::Hashcheck,
hierarchy: Hierarchy::Null,
digest: Vec::<u8>::new(),
}
}
}

impl Ticket for HashcheckTicket {
/// The tag of the verified ticket.
const POSSIBLE_TAGS: &'static [StructureTag] = &[StructureTag::Hashcheck];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -530,12 +530,11 @@ mod test_policy_name_hash {

mod test_policy_authorize {
use crate::common::{create_ctx_with_session, get_pcr_policy_digest, signing_key_pub};
use std::convert::{TryFrom, TryInto};
use std::convert::TryFrom;
use tss_esapi::{
constants::tss::{TPM2_RH_NULL, TPM2_ST_HASHCHECK},
interface_types::{algorithm::HashingAlgorithm, resource_handles::Hierarchy},
structures::{Auth, MaxBuffer, Nonce, SignatureScheme},
tss2_esys::{TPM2B_NONCE, TPMT_TK_HASHCHECK},
tss2_esys::TPM2B_NONCE,
};
#[test]
fn test_policy_authorize() {
Expand Down Expand Up @@ -569,19 +568,9 @@ mod test_policy_authorize {
.unwrap()
.0;

let validation = TPMT_TK_HASHCHECK {
tag: TPM2_ST_HASHCHECK,
hierarchy: TPM2_RH_NULL,
digest: Default::default(),
};
// A signature over just the policy_digest, since the policy_ref is empty
let signature = context
.sign(
key_handle,
ahash.clone(),
SignatureScheme::Null,
validation.try_into().unwrap(),
)
.sign(key_handle, ahash.clone(), SignatureScheme::Null, None)
.unwrap();
let tkt = context
.verify_signature(key_handle, ahash, signature)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
// SPDX-License-Identifier: Apache-2.0
mod test_verify_signature {
use crate::common::{create_ctx_with_session, signing_key_pub, HASH};
use std::convert::{TryFrom, TryInto};
use std::convert::TryFrom;
use tss_esapi::{
constants::tss::{TPM2_RH_NULL, TPM2_ST_HASHCHECK},
interface_types::{algorithm::HashingAlgorithm, resource_handles::Hierarchy},
structures::{Auth, Digest, PublicKeyRsa, RsaSignature, Signature, SignatureScheme},
tss2_esys::TPMT_TK_HASHCHECK,
};

#[test]
Expand All @@ -28,17 +26,12 @@ mod test_verify_signature {
.unwrap()
.key_handle;

let validation = TPMT_TK_HASHCHECK {
tag: TPM2_ST_HASHCHECK,
hierarchy: TPM2_RH_NULL,
digest: Default::default(),
};
let signature = context
.sign(
key_handle,
Digest::try_from(HASH[..32].to_vec()).unwrap(),
SignatureScheme::Null,
validation.try_into().unwrap(),
None,
)
.unwrap();

Expand Down Expand Up @@ -69,17 +62,12 @@ mod test_verify_signature {
.unwrap()
.key_handle;

let validation = TPMT_TK_HASHCHECK {
tag: TPM2_ST_HASHCHECK,
hierarchy: TPM2_RH_NULL,
digest: Default::default(),
};
let mut signature = context
.sign(
key_handle,
Digest::try_from(HASH[..32].to_vec()).unwrap(),
SignatureScheme::Null,
validation.try_into().unwrap(),
None,
)
.unwrap();

Expand Down Expand Up @@ -176,12 +164,10 @@ mod test_verify_signature {

mod test_sign {
use crate::common::{create_ctx_with_session, signing_key_pub, HASH};
use std::convert::{TryFrom, TryInto};
use std::convert::TryFrom;
use tss_esapi::{
constants::tss::{TPM2_RH_NULL, TPM2_ST_HASHCHECK},
interface_types::resource_handles::Hierarchy,
structures::{Auth, Digest, SignatureScheme},
tss2_esys::TPMT_TK_HASHCHECK,
};

#[test]
Expand All @@ -202,17 +188,12 @@ mod test_sign {
.unwrap()
.key_handle;

let validation = TPMT_TK_HASHCHECK {
tag: TPM2_ST_HASHCHECK,
hierarchy: TPM2_RH_NULL,
digest: Default::default(),
};
context
.sign(
key_handle,
Digest::try_from(HASH[..32].to_vec()).unwrap(),
SignatureScheme::Null,
validation.try_into().unwrap(),
None,
)
.unwrap();
}
Expand All @@ -235,17 +216,12 @@ mod test_sign {
.unwrap()
.key_handle;

let validation = TPMT_TK_HASHCHECK {
tag: TPM2_ST_HASHCHECK,
hierarchy: TPM2_RH_NULL,
digest: Default::default(),
};
context
.sign(
key_handle,
Digest::try_from(Vec::<u8>::new()).unwrap(),
SignatureScheme::Null,
validation.try_into().unwrap(),
None,
)
.unwrap_err();
}
Expand All @@ -268,17 +244,12 @@ mod test_sign {
.unwrap()
.key_handle;

let validation = TPMT_TK_HASHCHECK {
tag: TPM2_ST_HASHCHECK,
hierarchy: TPM2_RH_NULL,
digest: Default::default(),
};
context
.sign(
key_handle,
Digest::try_from([0xbb; 40].to_vec()).unwrap(),
SignatureScheme::Null,
validation.try_into().unwrap(),
None,
)
.unwrap_err();
}
Expand Down

0 comments on commit 5ded0e7

Please sign in to comment.