Skip to content

Commit 5abe48e

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

File tree

2 files changed

+177
-74
lines changed

2 files changed

+177
-74
lines changed

tss-esapi/src/utils/quote.rs

Lines changed: 172 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -4,105 +4,150 @@ 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+
println!("public convert failed");
49+
return Ok(false);
4450
};
4551

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-
};
52+
let verifying_key = VerifyingKey::from(public);
5653

57-
let verify_result = match signature.hashing_algorithm() {
54+
match hashing_algorithm {
5855
#[cfg(feature = "sha1")]
5956
HashingAlgorithm::Sha1 => {
60-
let mut hasher = sha1::Sha1::new();
61-
Digest::update(&mut hasher, &message);
62-
verifying_key.verify_prehash(&hasher.finalize(), &sig)
57+
let hash = sha1::Sha1::digest(&message);
58+
Ok(verifying_key.verify_prehash(&hash, &signature).is_ok())
59+
}
60+
#[cfg(feature = "sha2")]
61+
HashingAlgorithm::Sha256 => {
62+
let hash = sha2::Sha256::digest(&message);
63+
Ok(verifying_key.verify_prehash(&hash, &signature).is_ok())
64+
}
65+
#[cfg(feature = "sha2")]
66+
HashingAlgorithm::Sha384 => {
67+
let hash = sha2::Sha384::digest(&message);
68+
Ok(verifying_key.verify_prehash(&hash, &signature).is_ok())
6369
}
6470
#[cfg(feature = "sha2")]
65-
HashingAlgorithm::Sha256 => verifying_key.verify(&message, &sig),
71+
HashingAlgorithm::Sha512 => {
72+
let hash = sha2::Sha512::digest(&message);
73+
Ok(verifying_key.verify_prehash(&hash, &signature).is_ok())
74+
}
6675
_ => {
6776
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
6877
}
69-
};
70-
return Ok(match verify_result {
71-
Ok(_) => true,
72-
Err(_) => false,
73-
});
78+
}
7479
}
7580

7681
#[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() {
82+
fn verify_rsa_pss(
83+
public: &Public,
84+
message: &[u8],
85+
signature: &pss::Signature,
86+
hashing_algorithm: HashingAlgorithm,
87+
) -> Result<bool> {
88+
let rsa_key = RsaPublicKey::try_from(public)?;
89+
90+
match hashing_algorithm {
8291
#[cfg(feature = "sha1")]
83-
HashingAlgorithm::Sha1 => Box::new(sha1::Sha1::new()),
92+
HashingAlgorithm::Sha1 => {
93+
let verifying_key = pss::VerifyingKey::<sha1::Sha1>::from(rsa_key);
94+
Ok(verifying_key.verify(message, signature).is_ok())
95+
}
8496
#[cfg(feature = "sha2")]
85-
HashingAlgorithm::Sha256 => Box::new(sha2::Sha256::new()),
97+
HashingAlgorithm::Sha256 => {
98+
let verifying_key = pss::VerifyingKey::<sha2::Sha256>::from(rsa_key);
99+
Ok(verifying_key.verify(message, signature).is_ok())
100+
}
101+
#[cfg(feature = "sha2")]
102+
HashingAlgorithm::Sha384 => {
103+
let verifying_key = pss::VerifyingKey::<sha2::Sha384>::from(rsa_key);
104+
Ok(verifying_key.verify(message, signature).is_ok())
105+
}
106+
#[cfg(feature = "sha2")]
107+
HashingAlgorithm::Sha512 => {
108+
let verifying_key = pss::VerifyingKey::<sha2::Sha512>::from(rsa_key);
109+
Ok(verifying_key.verify(message, signature).is_ok())
110+
}
86111
_ => {
87112
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
88113
}
89-
};
90-
hasher.update(&message);
91-
let hash = hasher.finalize().to_vec();
114+
}
115+
}
92116

93-
let scheme = match signature.hashing_algorithm() {
117+
#[cfg(feature = "rsa")]
118+
fn verify_rsa_pkcs1v15(
119+
public: &Public,
120+
message: &[u8],
121+
signature: &pkcs1v15::Signature,
122+
hashing_algorithm: HashingAlgorithm,
123+
) -> Result<bool> {
124+
let rsa_key = RsaPublicKey::try_from(public)?;
125+
126+
match hashing_algorithm {
94127
#[cfg(feature = "sha1")]
95-
HashingAlgorithm::Sha1 => Pss::new::<sha1::Sha1>(),
128+
HashingAlgorithm::Sha1 => {
129+
let verifying_key = pkcs1v15::VerifyingKey::<sha1::Sha1>::from(rsa_key);
130+
Ok(verifying_key.verify(message, signature).is_ok())
131+
}
96132
#[cfg(feature = "sha2")]
97-
HashingAlgorithm::Sha256 => Pss::new::<sha2::Sha256>(),
133+
HashingAlgorithm::Sha256 => {
134+
let verifying_key = pkcs1v15::VerifyingKey::<sha2::Sha256>::from(rsa_key);
135+
Ok(verifying_key.verify(message, signature).is_ok())
136+
}
137+
#[cfg(feature = "sha2")]
138+
HashingAlgorithm::Sha384 => {
139+
let verifying_key = pkcs1v15::VerifyingKey::<sha2::Sha384>::from(rsa_key);
140+
Ok(verifying_key.verify(message, signature).is_ok())
141+
}
142+
#[cfg(feature = "sha2")]
143+
HashingAlgorithm::Sha512 => {
144+
let verifying_key = pkcs1v15::VerifyingKey::<sha2::Sha512>::from(rsa_key);
145+
Ok(verifying_key.verify(message, signature).is_ok())
146+
}
98147
_ => {
99148
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
100149
}
101-
};
102-
return Ok(match rsa_key.verify(scheme, &hash, &sig) {
103-
Ok(_) => true,
104-
Err(_) => false,
105-
});
150+
}
106151
}
107152

108153
fn checkquote_pcr_digests(
@@ -121,6 +166,10 @@ fn checkquote_pcr_digests(
121166
HashingAlgorithm::Sha1 => Box::new(sha1::Sha1::new()),
122167
#[cfg(feature = "sha2")]
123168
HashingAlgorithm::Sha256 => Box::new(sha2::Sha256::new()),
169+
#[cfg(feature = "sha2")]
170+
HashingAlgorithm::Sha384 => Box::new(sha2::Sha384::new()),
171+
#[cfg(feature = "sha2")]
172+
HashingAlgorithm::Sha512 => Box::new(sha2::Sha512::new()),
124173
_ => {
125174
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
126175
}
@@ -265,26 +314,75 @@ pub fn checkquote(
265314
return Err(Error::WrapperError(WrapperErrorKind::InvalidParam));
266315
}
267316
};
317+
268318
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)? {
319+
320+
let mut hash_alg = None;
321+
match (public, signature) {
322+
(Public::Ecc { parameters, .. }, _) => {
323+
macro_rules! impl_check_ecdsa {
324+
($curve: ty) => {
325+
if parameters.ecc_curve() == <$curve>::TPM_CURVE {
326+
let Signature::EcDsa(sig) = signature else {
327+
return Ok(false);
328+
};
329+
println!("hash_alg: {:?}", sig.hashing_algorithm());
330+
331+
if !verify_ecdsa::<$curve>(&public, &bytes, &sig, sig.hashing_algorithm())?
332+
{
333+
println!("verification failed");
334+
return Ok(false);
335+
}
336+
337+
hash_alg = Some(sig.hashing_algorithm());
338+
println!("hash_alg: {hash_alg:?}");
339+
}
340+
};
341+
}
342+
343+
//#[cfg(feature = "p192")]
344+
//impl_check_ecdsa!(p192::NistP192);
345+
#[cfg(feature = "p224")]
346+
impl_check_ecdsa!(p224::NistP224);
347+
#[cfg(feature = "p256")]
348+
impl_check_ecdsa!(p256::NistP256);
349+
#[cfg(feature = "p384")]
350+
impl_check_ecdsa!(p384::NistP384);
351+
//#[cfg(feature = "p521")]
352+
//impl_check_ecdsa!(p521::NistP521);
353+
//#[cfg(feature = "sm2")]
354+
//impl_check_ecdsa!(sm2::Sm2);
355+
}
356+
#[cfg(feature = "rsa")]
357+
(Public::Rsa { .. }, sig @ Signature::RsaSsa(pkcs_sig)) => {
358+
let Ok(sig) = pkcs1v15::Signature::try_from(sig.clone()) else {
359+
return Ok(false);
360+
};
361+
362+
if !verify_rsa_pkcs1v15(public, &bytes, &sig, pkcs_sig.hashing_algorithm())? {
273363
return Ok(false);
274364
}
275-
sig.hashing_algorithm()
365+
hash_alg = Some(pkcs_sig.hashing_algorithm());
276366
}
277367
#[cfg(feature = "rsa")]
278-
Signature::RsaPss(sig) => {
279-
if !verify_rsa(&public, &bytes, &sig)? {
368+
(Public::Rsa { .. }, sig @ Signature::RsaPss(pkcs_sig)) => {
369+
let Ok(sig) = pss::Signature::try_from(sig.clone()) else {
370+
return Ok(false);
371+
};
372+
373+
if !verify_rsa_pss(public, &bytes, &sig, pkcs_sig.hashing_algorithm())? {
280374
return Ok(false);
281375
}
282-
sig.hashing_algorithm()
376+
hash_alg = Some(pkcs_sig.hashing_algorithm());
283377
}
284378
_ => {
285-
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
379+
return Ok(false);
286380
}
287381
};
382+
383+
let Some(hash_alg) = hash_alg else {
384+
return Ok(false);
385+
};
288386
if qualifying_data != attest.extra_data().as_bytes() {
289387
return Ok(false);
290388
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,4 +260,9 @@ mod test_quote {
260260
fn checkquote_rsa_sha256() {
261261
checkquote_rsa(RsaKeyBits::Rsa3072, HashingAlgorithm::Sha256);
262262
}
263+
264+
#[test]
265+
fn checkquote_rsa_sha384() {
266+
checkquote_rsa(RsaKeyBits::Rsa3072, HashingAlgorithm::Sha384);
267+
}
263268
}

0 commit comments

Comments
 (0)