Skip to content

Commit 21c8791

Browse files
baloobrandsimon
authored andcommitted
checkquote: support more curves and hashes
Signed-off-by: Arthur Gautier <arthur.gautier@arista.com>
1 parent ce43b68 commit 21c8791

File tree

3 files changed

+201
-85
lines changed

3 files changed

+201
-85
lines changed

tss-esapi/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,6 @@ integration-tests = ["strum", "strum_macros"]
8080

8181
rustcrypto = ["digest", "ecdsa", "elliptic-curve", "pkcs8", "signature", "x509-cert"]
8282
rustcrypto-full = ["rustcrypto", "p192", "p224", "p256", "p384", "p521", "rsa", "sha1", "sha2", "sha3", "sm2", "sm3"]
83+
84+
sha1 = ["dep:sha1", "rsa?/sha1"]
85+
sha2 = ["dep:sha2", "rsa?/sha2"]

tss-esapi/src/utils/quote.rs

Lines changed: 166 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -4,105 +4,143 @@ use crate::error::Error;
44
use crate::error::Result;
55
use crate::WrapperErrorKind;
66
use crate::{
7+
abstraction::public::AssociatedTpmCurve,
78
interface_types::algorithm::HashingAlgorithm,
8-
structures::{Attest, AttestInfo, DigestList, PcrSelectionList, Public, QuoteInfo, Signature},
9+
structures::{
10+
Attest, AttestInfo, DigestList, EccSignature, PcrSelectionList, Public, QuoteInfo,
11+
Signature,
12+
},
913
traits::Marshall,
10-
utils::PublicKey,
1114
};
1215
use digest::{Digest, DynDigest};
1316

14-
#[cfg(feature = "p256")]
15-
use crate::structures::EccSignature;
16-
#[cfg(feature = "p256")]
17-
use p256::ecdsa::{Signature as SignatureP256, VerifyingKey};
18-
#[cfg(feature = "p256")]
17+
use ecdsa::{
18+
hazmat::{DigestPrimitive, VerifyPrimitive},
19+
PrimeCurve, SignatureSize, VerifyingKey,
20+
};
21+
use elliptic_curve::{
22+
generic_array::ArrayLength,
23+
point::AffinePoint,
24+
sec1::{FromEncodedPoint, ModulusSize, ToEncodedPoint},
25+
CurveArithmetic, FieldBytesSize,
26+
};
1927
use signature::{hazmat::PrehashVerifier, Verifier};
2028

2129
#[cfg(feature = "rsa")]
22-
use crate::structures::RsaSignature;
23-
#[cfg(feature = "rsa")]
24-
use rsa::{pss::Pss, RsaPublicKey};
30+
use rsa::{pkcs1v15, pss, RsaPublicKey};
2531

26-
#[cfg(feature = "p256")]
27-
fn verify_p256(public: &Public, message: &[u8], signature: &EccSignature) -> Result<bool> {
28-
let public_key = PublicKey::try_from(public.clone())?;
29-
let (x, y) = match public_key {
30-
PublicKey::Ecc { x, y } => (x, y),
31-
_ => {
32-
return Err(Error::WrapperError(WrapperErrorKind::InvalidParam));
33-
}
32+
fn verify_ecdsa<C>(
33+
public: &Public,
34+
message: &[u8],
35+
signature: &EccSignature,
36+
hashing_algorithm: HashingAlgorithm,
37+
) -> Result<bool>
38+
where
39+
C: PrimeCurve + CurveArithmetic + DigestPrimitive + AssociatedTpmCurve,
40+
AffinePoint<C>: VerifyPrimitive<C> + FromEncodedPoint<C> + ToEncodedPoint<C>,
41+
SignatureSize<C>: ArrayLength<u8>,
42+
FieldBytesSize<C>: ModulusSize,
43+
{
44+
let Ok(signature) = ecdsa::Signature::<C>::try_from(signature.clone()) else {
45+
return Ok(false);
3446
};
35-
let mut sec1_bytes = Vec::<u8>::with_capacity(1 + x.len() + y.len());
36-
sec1_bytes.push(0x04);
37-
sec1_bytes.extend_from_slice(&x);
38-
sec1_bytes.extend_from_slice(&y);
39-
let verifying_key = match VerifyingKey::from_sec1_bytes(&sec1_bytes) {
40-
Ok(s) => s,
41-
Err(_) => {
42-
return Err(Error::WrapperError(WrapperErrorKind::InvalidParam));
43-
}
47+
let Ok(public) = elliptic_curve::PublicKey::<C>::try_from(public) else {
48+
return Ok(false);
4449
};
4550

46-
let mut sig_bytes = Vec::with_capacity(64);
47-
sig_bytes.extend_from_slice(signature.signature_r().as_ref());
48-
sig_bytes.extend_from_slice(signature.signature_s().as_ref());
49-
let generic_sig = digest::generic_array::GenericArray::clone_from_slice(&sig_bytes);
50-
let sig = match SignatureP256::from_bytes(&generic_sig) {
51-
Ok(s) => s,
52-
Err(_) => {
53-
return Err(Error::WrapperError(WrapperErrorKind::InvalidParam));
54-
}
55-
};
51+
let verifying_key = VerifyingKey::from(public);
5652

57-
let verify_result = match signature.hashing_algorithm() {
53+
match hashing_algorithm {
5854
#[cfg(feature = "sha1")]
5955
HashingAlgorithm::Sha1 => {
60-
let mut hasher = sha1::Sha1::new();
61-
Digest::update(&mut hasher, &message);
62-
verifying_key.verify_prehash(&hasher.finalize(), &sig)
56+
let hash = sha1::Sha1::digest(message);
57+
Ok(verifying_key.verify_prehash(&hash, &signature).is_ok())
6358
}
6459
#[cfg(feature = "sha2")]
65-
HashingAlgorithm::Sha256 => verifying_key.verify(&message, &sig),
66-
_ => {
67-
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
60+
HashingAlgorithm::Sha256 => {
61+
let hash = sha2::Sha256::digest(message);
62+
Ok(verifying_key.verify_prehash(&hash, &signature).is_ok())
6863
}
69-
};
70-
return Ok(match verify_result {
71-
Ok(_) => true,
72-
Err(_) => false,
73-
});
64+
#[cfg(feature = "sha2")]
65+
HashingAlgorithm::Sha384 => {
66+
let hash = sha2::Sha384::digest(message);
67+
Ok(verifying_key.verify_prehash(&hash, &signature).is_ok())
68+
}
69+
#[cfg(feature = "sha2")]
70+
HashingAlgorithm::Sha512 => {
71+
let hash = sha2::Sha512::digest(message);
72+
Ok(verifying_key.verify_prehash(&hash, &signature).is_ok())
73+
}
74+
_ => Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)),
75+
}
7476
}
7577

7678
#[cfg(feature = "rsa")]
77-
fn verify_rsa(public: &Public, message: &[u8], signature: &RsaSignature) -> Result<bool> {
78-
let public_key = PublicKey::try_from(public.clone())?;
79-
let rsa_key = RsaPublicKey::try_from(&public_key)?;
80-
let sig = signature.signature();
81-
let mut hasher: Box<dyn DynDigest> = match signature.hashing_algorithm() {
79+
fn verify_rsa_pss(
80+
public: &Public,
81+
message: &[u8],
82+
signature: &pss::Signature,
83+
hashing_algorithm: HashingAlgorithm,
84+
) -> Result<bool> {
85+
let rsa_key = RsaPublicKey::try_from(public)?;
86+
87+
match hashing_algorithm {
8288
#[cfg(feature = "sha1")]
83-
HashingAlgorithm::Sha1 => Box::new(sha1::Sha1::new()),
89+
HashingAlgorithm::Sha1 => {
90+
let verifying_key = pss::VerifyingKey::<sha1::Sha1>::from(rsa_key);
91+
Ok(verifying_key.verify(message, signature).is_ok())
92+
}
8493
#[cfg(feature = "sha2")]
85-
HashingAlgorithm::Sha256 => Box::new(sha2::Sha256::new()),
86-
_ => {
87-
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
94+
HashingAlgorithm::Sha256 => {
95+
let verifying_key = pss::VerifyingKey::<sha2::Sha256>::from(rsa_key);
96+
Ok(verifying_key.verify(message, signature).is_ok())
8897
}
89-
};
90-
hasher.update(&message);
91-
let hash = hasher.finalize().to_vec();
98+
#[cfg(feature = "sha2")]
99+
HashingAlgorithm::Sha384 => {
100+
let verifying_key = pss::VerifyingKey::<sha2::Sha384>::from(rsa_key);
101+
Ok(verifying_key.verify(message, signature).is_ok())
102+
}
103+
#[cfg(feature = "sha2")]
104+
HashingAlgorithm::Sha512 => {
105+
let verifying_key = pss::VerifyingKey::<sha2::Sha512>::from(rsa_key);
106+
Ok(verifying_key.verify(message, signature).is_ok())
107+
}
108+
_ => Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)),
109+
}
110+
}
111+
112+
#[cfg(feature = "rsa")]
113+
fn verify_rsa_pkcs1v15(
114+
public: &Public,
115+
message: &[u8],
116+
signature: &pkcs1v15::Signature,
117+
hashing_algorithm: HashingAlgorithm,
118+
) -> Result<bool> {
119+
let rsa_key = RsaPublicKey::try_from(public)?;
92120

93-
let scheme = match signature.hashing_algorithm() {
121+
match hashing_algorithm {
94122
#[cfg(feature = "sha1")]
95-
HashingAlgorithm::Sha1 => Pss::new::<sha1::Sha1>(),
123+
HashingAlgorithm::Sha1 => {
124+
let verifying_key = pkcs1v15::VerifyingKey::<sha1::Sha1>::new(rsa_key);
125+
Ok(verifying_key.verify(message, signature).is_ok())
126+
}
96127
#[cfg(feature = "sha2")]
97-
HashingAlgorithm::Sha256 => Pss::new::<sha2::Sha256>(),
98-
_ => {
99-
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
128+
HashingAlgorithm::Sha256 => {
129+
let verifying_key = pkcs1v15::VerifyingKey::<sha2::Sha256>::new(rsa_key);
130+
Ok(verifying_key.verify(message, signature).is_ok())
100131
}
101-
};
102-
return Ok(match rsa_key.verify(scheme, &hash, &sig) {
103-
Ok(_) => true,
104-
Err(_) => false,
105-
});
132+
#[cfg(feature = "sha2")]
133+
HashingAlgorithm::Sha384 => {
134+
let verifying_key = pkcs1v15::VerifyingKey::<sha2::Sha384>::new(rsa_key);
135+
Ok(verifying_key.verify(message, signature).is_ok())
136+
}
137+
#[cfg(feature = "sha2")]
138+
HashingAlgorithm::Sha512 => {
139+
let verifying_key = pkcs1v15::VerifyingKey::<sha2::Sha512>::new(rsa_key);
140+
Ok(verifying_key.verify(message, signature).is_ok())
141+
}
142+
_ => Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam)),
143+
}
106144
}
107145

108146
fn checkquote_pcr_digests(
@@ -121,6 +159,10 @@ fn checkquote_pcr_digests(
121159
HashingAlgorithm::Sha1 => Box::new(sha1::Sha1::new()),
122160
#[cfg(feature = "sha2")]
123161
HashingAlgorithm::Sha256 => Box::new(sha2::Sha256::new()),
162+
#[cfg(feature = "sha2")]
163+
HashingAlgorithm::Sha384 => Box::new(sha2::Sha384::new()),
164+
#[cfg(feature = "sha2")]
165+
HashingAlgorithm::Sha512 => Box::new(sha2::Sha512::new()),
124166
_ => {
125167
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
126168
}
@@ -265,26 +307,71 @@ pub fn checkquote(
265307
return Err(Error::WrapperError(WrapperErrorKind::InvalidParam));
266308
}
267309
};
310+
268311
let bytes = attest.marshall()?;
269-
let hash_alg = match signature {
270-
#[cfg(feature = "p256")]
271-
Signature::EcDsa(sig) => {
272-
if !verify_p256(&public, &bytes, &sig)? {
312+
313+
let mut hash_alg = None;
314+
match (public, signature) {
315+
(Public::Ecc { parameters, .. }, _) => {
316+
macro_rules! impl_check_ecdsa {
317+
($curve: ty) => {
318+
if parameters.ecc_curve() == <$curve>::TPM_CURVE {
319+
let Signature::EcDsa(sig) = signature else {
320+
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
321+
};
322+
if !verify_ecdsa::<$curve>(&public, &bytes, &sig, sig.hashing_algorithm())?
323+
{
324+
return Ok(false);
325+
}
326+
327+
hash_alg = Some(sig.hashing_algorithm());
328+
}
329+
};
330+
}
331+
332+
//#[cfg(feature = "p192")]
333+
//impl_check_ecdsa!(p192::NistP192);
334+
#[cfg(feature = "p224")]
335+
impl_check_ecdsa!(p224::NistP224);
336+
#[cfg(feature = "p256")]
337+
impl_check_ecdsa!(p256::NistP256);
338+
#[cfg(feature = "p384")]
339+
impl_check_ecdsa!(p384::NistP384);
340+
//#[cfg(feature = "p521")]
341+
//impl_check_ecdsa!(p521::NistP521);
342+
//#[cfg(feature = "sm2")]
343+
//impl_check_ecdsa!(sm2::Sm2);
344+
}
345+
#[cfg(feature = "rsa")]
346+
(Public::Rsa { .. }, sig @ Signature::RsaSsa(pkcs_sig)) => {
347+
let Ok(sig) = pkcs1v15::Signature::try_from(sig.clone()) else {
348+
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
349+
};
350+
351+
if !verify_rsa_pkcs1v15(public, &bytes, &sig, pkcs_sig.hashing_algorithm())? {
273352
return Ok(false);
274353
}
275-
sig.hashing_algorithm()
354+
hash_alg = Some(pkcs_sig.hashing_algorithm());
276355
}
277356
#[cfg(feature = "rsa")]
278-
Signature::RsaPss(sig) => {
279-
if !verify_rsa(&public, &bytes, &sig)? {
357+
(Public::Rsa { .. }, sig @ Signature::RsaPss(pkcs_sig)) => {
358+
let Ok(sig) = pss::Signature::try_from(sig.clone()) else {
359+
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
360+
};
361+
362+
if !verify_rsa_pss(public, &bytes, &sig, pkcs_sig.hashing_algorithm())? {
280363
return Ok(false);
281364
}
282-
sig.hashing_algorithm()
365+
hash_alg = Some(pkcs_sig.hashing_algorithm());
283366
}
284367
_ => {
285368
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
286369
}
287370
};
371+
372+
let Some(hash_alg) = hash_alg else {
373+
return Ok(false);
374+
};
288375
if qualifying_data != attest.extra_data().as_bytes() {
289376
return Ok(false);
290377
}

tss-esapi/tests/integration_tests/utils_tests/quote_test.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,16 @@ mod test_quote {
172172
checkquote_ecc(HashingAlgorithm::Sha256);
173173
}
174174

175-
fn checkquote_rsa(keybits: RsaKeyBits, hash_alg: HashingAlgorithm) {
175+
#[test]
176+
fn checkquote_ecc_sha512() {
177+
checkquote_ecc(HashingAlgorithm::Sha512);
178+
}
179+
180+
fn checkquote_rsa(
181+
keybits: RsaKeyBits,
182+
hash_alg: HashingAlgorithm,
183+
sig_scheme: SignatureSchemeAlgorithm,
184+
) {
176185
let mut context = create_ctx_with_session();
177186
let ek_rsa = ek::create_ek_object(
178187
&mut context,
@@ -186,7 +195,7 @@ mod test_quote {
186195
ek_rsa,
187196
hash_alg,
188197
AsymmetricAlgorithmSelection::Rsa(keybits),
189-
SignatureSchemeAlgorithm::RsaPss,
198+
sig_scheme,
190199
Some(ak_auth.clone()),
191200
None,
192201
)
@@ -228,12 +237,29 @@ mod test_quote {
228237
}
229238

230239
#[test]
231-
fn checkquote_rsa_sha1() {
232-
checkquote_rsa(RsaKeyBits::Rsa2048, HashingAlgorithm::Sha1);
240+
fn checkquote_rsa_pss_sha1() {
241+
checkquote_rsa(
242+
RsaKeyBits::Rsa1024,
243+
HashingAlgorithm::Sha1,
244+
SignatureSchemeAlgorithm::RsaPss,
245+
);
233246
}
234247

235248
#[test]
236-
fn checkquote_rsa_sha256() {
237-
checkquote_rsa(RsaKeyBits::Rsa3072, HashingAlgorithm::Sha256);
249+
fn checkquote_rsa_ssa_sha256() {
250+
checkquote_rsa(
251+
RsaKeyBits::Rsa2048,
252+
HashingAlgorithm::Sha256,
253+
SignatureSchemeAlgorithm::RsaSsa,
254+
);
255+
}
256+
257+
#[test]
258+
fn checkquote_rsa_pss_sha384() {
259+
checkquote_rsa(
260+
RsaKeyBits::Rsa3072,
261+
HashingAlgorithm::Sha384,
262+
SignatureSchemeAlgorithm::RsaPss,
263+
);
238264
}
239265
}

0 commit comments

Comments
 (0)