Skip to content

Commit

Permalink
Merge pull request #69 from ionut-arm/ec-support
Browse files Browse the repository at this point in the history
Add support for elliptic curves for transient context
  • Loading branch information
ionut-arm authored May 6, 2020
2 parents 0a30773 + 5bf2f06 commit 43d9aff
Show file tree
Hide file tree
Showing 7 changed files with 757 additions and 132 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ Cargo.lock
*DS_Store
*.patch
*NVChip
.vscode
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tss-esapi"
version = "4.0.0-alpha.1"
version = "4.0.1-alpha.1"
authors = ["Ionut Mihalcea <ionut.mihalcea@arm.com>",
"Hugues de Valon <hugues.devalon@arm.com>"]
edition = "2018"
Expand Down
99 changes: 74 additions & 25 deletions src/abstraction/transient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
use crate::constants::*;
use crate::response_code::{Error, Result, WrapperErrorKind as ErrorKind};
use crate::tss2_esys::*;
use crate::utils::algorithm_specifiers::Cipher;
use crate::utils::algorithm_specifiers::{Cipher, EllipticCurve, HashingAlgorithm};
use crate::utils::{
self, create_restricted_decryption_rsa_public, create_unrestricted_signing_rsa_public,
AsymSchemeUnion, Hierarchy, PublicIdUnion, TpmaSessionBuilder, TpmsContext, TpmtTkVerified,
RSA_KEY_SIZES,
self, create_restricted_decryption_rsa_public, create_unrestricted_signing_ecc_public,
create_unrestricted_signing_rsa_public, AsymSchemeUnion, Hierarchy, PublicIdUnion, PublicKey,
TpmaSessionBuilder, TpmsContext, TpmtTkVerified, RSA_KEY_SIZES,
};
use crate::{Context, Tcti};
use log::error;
Expand All @@ -42,51 +42,43 @@ pub struct TransientKeyContext {
}

impl TransientKeyContext {
/// Create a new RSA signing key.
/// Create a new signing key.
///
/// The key is created with most parameters defaulted as described for the
/// `create_unrestricted_signing_rsa_public` function. The authentication value is
/// generated by the TPM. Key size is provided by user as a parameter, and must be
/// given in **bits**.
/// A key is created as a descendant of the context root key, with the given parameters.
///
/// If successful, the result contains the saved context of the key and a vector of
/// bytes forming the authentication value for said key.
///
/// # Constraints
/// * `key_size` must be 1024, 2048, 3072 or 4096
/// * `auth_size` must be at most 32
///
/// # Errors
/// * if the authentication size is larger than 32 or if the requested key size is not
/// 1024, 2048, 3072 or 4096, a `WrongParamSize` wrapper error is returned
/// * if the authentication size is larger than 32 a `WrongParamSize` wrapper error is returned
/// * for RSA keys, if the specified key size is not one of 1024, 2048, 3072 or 4096, `WrongParamSize`
/// is returned
/// * if the asymmetric scheme is not a signing scheme, `InconsistentParams` is returned
/// * errors are returned if any method calls return an error: `Context::get_random`,
/// `TransientKeyContext::set_session_attrs`, `Context::create_key`, `Context::load`,
/// `Context::context_save`, `Context::context_flush`
pub fn create_rsa_signing_key(
pub fn create_signing_key(
&mut self,
key_size: u16,
key_params: KeyParams,
auth_size: usize,
) -> Result<(TpmsContext, Vec<u8>)> {
if auth_size > 32 {
return Err(Error::local_error(ErrorKind::WrongParamSize));
}
if RSA_KEY_SIZES.iter().find(|sz| **sz == key_size).is_none() {
return Err(Error::local_error(ErrorKind::WrongParamSize));
}
let key_auth = if auth_size > 0 {
self.set_session_attrs()?;
self.context.get_random(auth_size)?
} else {
vec![]
};

self.set_session_attrs()?;
let (key_priv, key_pub) = self.context.create_key(
self.root_key_handle,
&create_unrestricted_signing_rsa_public(
AsymSchemeUnion::RSASSA(TPM2_ALG_SHA256),
key_size.try_into().unwrap(),
0,
)?,
&self.get_public_from_params(key_params)?,
&key_auth,
&[],
&[],
Expand All @@ -104,6 +96,29 @@ impl TransientKeyContext {
Ok((key_context, key_auth))
}

fn get_public_from_params(&self, params: KeyParams) -> Result<TPM2B_PUBLIC> {
match params {
KeyParams::Rsa {
size,
scheme,
pub_exponent,
} => {
if RSA_KEY_SIZES.iter().find(|sz| **sz == size).is_none() {
return Err(Error::local_error(ErrorKind::WrongParamSize));
}

Ok(create_unrestricted_signing_rsa_public(
scheme,
size,
pub_exponent,
)?)
}
KeyParams::Ecc { curve, scheme } => {
Ok(create_unrestricted_signing_ecc_public(scheme, curve)?)
}
}
}

/// Load a previously generated RSA public key.
///
/// Returns the key context.
Expand Down Expand Up @@ -135,7 +150,7 @@ impl TransientKeyContext {
};

let mut public = create_unrestricted_signing_rsa_public(
AsymSchemeUnion::RSASSA(TPM2_ALG_SHA256),
AsymSchemeUnion::RSASSA(HashingAlgorithm::Sha256),
u16::try_from(public_key.len()).unwrap() * 8_u16,
0,
)?;
Expand All @@ -162,7 +177,7 @@ impl TransientKeyContext {
/// * errors are returned if any method calls return an error: `Context::context_load`,
/// `Context::read_public`, `Context::flush_context`,
/// `TransientKeyContext::set_session_attrs`
pub fn read_public_key(&mut self, key_context: TpmsContext) -> Result<Vec<u8>> {
pub fn read_public_key(&mut self, key_context: TpmsContext) -> Result<PublicKey> {
self.set_session_attrs()?;
let key_handle = self.context.context_load(key_context)?;

Expand All @@ -176,7 +191,14 @@ impl TransientKeyContext {
PublicIdUnion::Rsa(pub_key) => {
let mut key = pub_key.buffer.to_vec();
key.truncate(pub_key.size.try_into().unwrap()); // should not fail on supported targets
key
PublicKey::Rsa(key)
}
PublicIdUnion::Ecc(pub_key) => {
let mut x = pub_key.x.buffer.to_vec();
x.truncate(pub_key.x.size.try_into().unwrap()); // should not fail on supported targets
let mut y = pub_key.y.buffer.to_vec();
y.truncate(pub_key.y.size.try_into().unwrap()); // should not fail on supported targets
PublicKey::Ecc { x, y }
}
_ => return Err(Error::local_error(ErrorKind::UnsupportedParam)),
};
Expand Down Expand Up @@ -456,3 +478,30 @@ impl Default for TransientKeyContextBuilder {
TransientKeyContextBuilder::new()
}
}

/// Parameters for the kinds of keys supported by the context
#[derive(Debug, Clone, Copy)]
pub enum KeyParams {
Rsa {
/// Size of key in bits
///
/// Can only be one of: 1024, 2048, 3072 or 4096
size: u16,
/// Asymmetric scheme to be used with the key
///
/// *Must* be an RSA-specific scheme
scheme: AsymSchemeUnion,
/// Public exponent of the key
///
/// If set to 0, it will default to 2^16 - 1
pub_exponent: u32,
},
Ecc {
/// Curve that the key will be based on
curve: EllipticCurve,
/// Asymmetric scheme to be used with the key
///
/// *Must* be an ECC scheme
scheme: AsymSchemeUnion,
},
}
54 changes: 52 additions & 2 deletions src/utils/algorithm_specifiers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ use crate::constants::{
TPM2_ALG_OAEP, TPM2_ALG_OFB, TPM2_ALG_RSA, TPM2_ALG_RSAES, TPM2_ALG_RSAPSS, TPM2_ALG_RSASSA,
TPM2_ALG_SHA1, TPM2_ALG_SHA256, TPM2_ALG_SHA384, TPM2_ALG_SHA3_256, TPM2_ALG_SHA3_384,
TPM2_ALG_SHA3_512, TPM2_ALG_SHA512, TPM2_ALG_SM2, TPM2_ALG_SM3_256, TPM2_ALG_SM4,
TPM2_ALG_SYMCIPHER, TPM2_ALG_TDES, TPM2_ALG_XOR,
TPM2_ALG_SYMCIPHER, TPM2_ALG_TDES, TPM2_ALG_XOR, TPM2_ECC_BN_P256, TPM2_ECC_BN_P638,
TPM2_ECC_NIST_P192, TPM2_ECC_NIST_P224, TPM2_ECC_NIST_P256, TPM2_ECC_NIST_P384,
TPM2_ECC_NIST_P521, TPM2_ECC_SM2_P256,
};

use crate::response_code::{Error, Result, WrapperErrorKind};
use crate::tss2_esys::{TPM2_ALG_ID, TPMS_SYMCIPHER_PARMS, TPMT_SYM_DEF, TPMT_SYM_DEF_OBJECT};
use crate::tss2_esys::{
TPM2_ALG_ID, TPMI_ECC_CURVE, TPMS_SYMCIPHER_PARMS, TPMT_SYM_DEF, TPMT_SYM_DEF_OBJECT,
};
use crate::utils::TpmtSymDefBuilder;
use std::convert::{From, TryFrom};

Expand Down Expand Up @@ -728,3 +732,49 @@ impl From<Cipher> for TPMS_SYMCIPHER_PARMS {
TPMS_SYMCIPHER_PARMS { sym: cipher.into() }
}
}

/// Identifiers for elliptic curves supported by TPMs.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum EllipticCurve {
NistP192,
NistP224,
NistP256,
NistP384,
NistP521,
BnP256,
BnP638,
Sm2P256,
}

impl From<EllipticCurve> for TPMI_ECC_CURVE {
fn from(curve: EllipticCurve) -> Self {
match curve {
EllipticCurve::NistP192 => TPM2_ECC_NIST_P192,
EllipticCurve::NistP224 => TPM2_ECC_NIST_P224,
EllipticCurve::NistP256 => TPM2_ECC_NIST_P256,
EllipticCurve::NistP384 => TPM2_ECC_NIST_P384,
EllipticCurve::NistP521 => TPM2_ECC_NIST_P521,
EllipticCurve::BnP256 => TPM2_ECC_BN_P256,
EllipticCurve::BnP638 => TPM2_ECC_BN_P638,
EllipticCurve::Sm2P256 => TPM2_ECC_SM2_P256,
}
}
}

impl TryFrom<TPMI_ECC_CURVE> for EllipticCurve {
type Error = Error;

fn try_from(curve: TPMI_ECC_CURVE) -> Result<Self> {
match curve {
TPM2_ECC_NIST_P192 => Ok(EllipticCurve::NistP192),
TPM2_ECC_NIST_P224 => Ok(EllipticCurve::NistP224),
TPM2_ECC_NIST_P256 => Ok(EllipticCurve::NistP256),
TPM2_ECC_NIST_P384 => Ok(EllipticCurve::NistP384),
TPM2_ECC_NIST_P521 => Ok(EllipticCurve::NistP521),
TPM2_ECC_BN_P256 => Ok(EllipticCurve::BnP256),
TPM2_ECC_BN_P638 => Ok(EllipticCurve::BnP638),
TPM2_ECC_SM2_P256 => Ok(EllipticCurve::Sm2P256),
_ => Err(Error::local_error(WrapperErrorKind::InvalidParam)),
}
}
}
Loading

0 comments on commit 43d9aff

Please sign in to comment.