Skip to content

Commit b217e84

Browse files
baloobrandsimon
authored andcommitted
checkquote: support more curves and hashes
Signed-off-by: Arthur Gautier <[email protected]>
1 parent 7dcc24b commit b217e84

File tree

3 files changed

+201
-79
lines changed

3 files changed

+201
-79
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 & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -4,105 +4,149 @@ 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())
58+
}
59+
#[cfg(feature = "sha2")]
60+
HashingAlgorithm::Sha256 => {
61+
let hash = sha2::Sha256::digest(&message);
62+
Ok(verifying_key.verify_prehash(&hash, &signature).is_ok())
6363
}
6464
#[cfg(feature = "sha2")]
65-
HashingAlgorithm::Sha256 => verifying_key.verify(&message, &sig),
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+
}
6674
_ => {
6775
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
6876
}
69-
};
70-
return Ok(match verify_result {
71-
Ok(_) => true,
72-
Err(_) => false,
73-
});
77+
}
7478
}
7579

7680
#[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() {
81+
fn verify_rsa_pss(
82+
public: &Public,
83+
message: &[u8],
84+
signature: &pss::Signature,
85+
hashing_algorithm: HashingAlgorithm,
86+
) -> Result<bool> {
87+
let rsa_key = RsaPublicKey::try_from(public)?;
88+
89+
match hashing_algorithm {
8290
#[cfg(feature = "sha1")]
83-
HashingAlgorithm::Sha1 => Box::new(sha1::Sha1::new()),
91+
HashingAlgorithm::Sha1 => {
92+
let verifying_key = pss::VerifyingKey::<sha1::Sha1>::from(rsa_key);
93+
Ok(verifying_key.verify(message, signature).is_ok())
94+
}
8495
#[cfg(feature = "sha2")]
85-
HashingAlgorithm::Sha256 => Box::new(sha2::Sha256::new()),
96+
HashingAlgorithm::Sha256 => {
97+
let verifying_key = pss::VerifyingKey::<sha2::Sha256>::from(rsa_key);
98+
Ok(verifying_key.verify(message, signature).is_ok())
99+
}
100+
#[cfg(feature = "sha2")]
101+
HashingAlgorithm::Sha384 => {
102+
let verifying_key = pss::VerifyingKey::<sha2::Sha384>::from(rsa_key);
103+
Ok(verifying_key.verify(message, signature).is_ok())
104+
}
105+
#[cfg(feature = "sha2")]
106+
HashingAlgorithm::Sha512 => {
107+
let verifying_key = pss::VerifyingKey::<sha2::Sha512>::from(rsa_key);
108+
Ok(verifying_key.verify(message, signature).is_ok())
109+
}
86110
_ => {
87111
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
88112
}
89-
};
90-
hasher.update(&message);
91-
let hash = hasher.finalize().to_vec();
113+
}
114+
}
115+
116+
#[cfg(feature = "rsa")]
117+
fn verify_rsa_pkcs1v15(
118+
public: &Public,
119+
message: &[u8],
120+
signature: &pkcs1v15::Signature,
121+
hashing_algorithm: HashingAlgorithm,
122+
) -> Result<bool> {
123+
let rsa_key = RsaPublicKey::try_from(public)?;
92124

93-
let scheme = match signature.hashing_algorithm() {
125+
match hashing_algorithm {
94126
#[cfg(feature = "sha1")]
95-
HashingAlgorithm::Sha1 => Pss::new::<sha1::Sha1>(),
127+
HashingAlgorithm::Sha1 => {
128+
let verifying_key = pkcs1v15::VerifyingKey::<sha1::Sha1>::new(rsa_key);
129+
Ok(verifying_key.verify(message, signature).is_ok())
130+
}
131+
#[cfg(feature = "sha2")]
132+
HashingAlgorithm::Sha256 => {
133+
let verifying_key = pkcs1v15::VerifyingKey::<sha2::Sha256>::new(rsa_key);
134+
Ok(verifying_key.verify(message, signature).is_ok())
135+
}
96136
#[cfg(feature = "sha2")]
97-
HashingAlgorithm::Sha256 => Pss::new::<sha2::Sha256>(),
137+
HashingAlgorithm::Sha384 => {
138+
let verifying_key = pkcs1v15::VerifyingKey::<sha2::Sha384>::new(rsa_key);
139+
Ok(verifying_key.verify(message, signature).is_ok())
140+
}
141+
#[cfg(feature = "sha2")]
142+
HashingAlgorithm::Sha512 => {
143+
let verifying_key = pkcs1v15::VerifyingKey::<sha2::Sha512>::new(rsa_key);
144+
Ok(verifying_key.verify(message, signature).is_ok())
145+
}
98146
_ => {
99147
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
100148
}
101-
};
102-
return Ok(match rsa_key.verify(scheme, &hash, &sig) {
103-
Ok(_) => true,
104-
Err(_) => false,
105-
});
149+
}
106150
}
107151

108152
fn checkquote_pcr_digests(
@@ -121,6 +165,10 @@ fn checkquote_pcr_digests(
121165
HashingAlgorithm::Sha1 => Box::new(sha1::Sha1::new()),
122166
#[cfg(feature = "sha2")]
123167
HashingAlgorithm::Sha256 => Box::new(sha2::Sha256::new()),
168+
#[cfg(feature = "sha2")]
169+
HashingAlgorithm::Sha384 => Box::new(sha2::Sha384::new()),
170+
#[cfg(feature = "sha2")]
171+
HashingAlgorithm::Sha512 => Box::new(sha2::Sha512::new()),
124172
_ => {
125173
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
126174
}
@@ -265,26 +313,71 @@ pub fn checkquote(
265313
return Err(Error::WrapperError(WrapperErrorKind::InvalidParam));
266314
}
267315
};
316+
268317
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)? {
318+
319+
let mut hash_alg = None;
320+
match (public, signature) {
321+
(Public::Ecc { parameters, .. }, _) => {
322+
macro_rules! impl_check_ecdsa {
323+
($curve: ty) => {
324+
if parameters.ecc_curve() == <$curve>::TPM_CURVE {
325+
let Signature::EcDsa(sig) = signature else {
326+
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
327+
};
328+
if !verify_ecdsa::<$curve>(&public, &bytes, &sig, sig.hashing_algorithm())?
329+
{
330+
return Ok(false);
331+
}
332+
333+
hash_alg = Some(sig.hashing_algorithm());
334+
}
335+
};
336+
}
337+
338+
//#[cfg(feature = "p192")]
339+
//impl_check_ecdsa!(p192::NistP192);
340+
#[cfg(feature = "p224")]
341+
impl_check_ecdsa!(p224::NistP224);
342+
#[cfg(feature = "p256")]
343+
impl_check_ecdsa!(p256::NistP256);
344+
#[cfg(feature = "p384")]
345+
impl_check_ecdsa!(p384::NistP384);
346+
//#[cfg(feature = "p521")]
347+
//impl_check_ecdsa!(p521::NistP521);
348+
//#[cfg(feature = "sm2")]
349+
//impl_check_ecdsa!(sm2::Sm2);
350+
}
351+
#[cfg(feature = "rsa")]
352+
(Public::Rsa { .. }, sig @ Signature::RsaSsa(pkcs_sig)) => {
353+
let Ok(sig) = pkcs1v15::Signature::try_from(sig.clone()) else {
354+
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
355+
};
356+
357+
if !verify_rsa_pkcs1v15(public, &bytes, &sig, pkcs_sig.hashing_algorithm())? {
273358
return Ok(false);
274359
}
275-
sig.hashing_algorithm()
360+
hash_alg = Some(pkcs_sig.hashing_algorithm());
276361
}
277362
#[cfg(feature = "rsa")]
278-
Signature::RsaPss(sig) => {
279-
if !verify_rsa(&public, &bytes, &sig)? {
363+
(Public::Rsa { .. }, sig @ Signature::RsaPss(pkcs_sig)) => {
364+
let Ok(sig) = pss::Signature::try_from(sig.clone()) else {
365+
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
366+
};
367+
368+
if !verify_rsa_pss(public, &bytes, &sig, pkcs_sig.hashing_algorithm())? {
280369
return Ok(false);
281370
}
282-
sig.hashing_algorithm()
371+
hash_alg = Some(pkcs_sig.hashing_algorithm());
283372
}
284373
_ => {
285374
return Err(Error::WrapperError(WrapperErrorKind::UnsupportedParam));
286375
}
287376
};
377+
378+
let Some(hash_alg) = hash_alg else {
379+
return Ok(false);
380+
};
288381
if qualifying_data != attest.extra_data().as_bytes() {
289382
return Ok(false);
290383
}

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

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,16 @@ mod test_quote {
193193
checkquote_ecc(HashingAlgorithm::Sha256);
194194
}
195195

196-
fn checkquote_rsa(keybits: RsaKeyBits, hash_alg: HashingAlgorithm) {
196+
#[test]
197+
fn checkquote_ecc_sha512() {
198+
checkquote_ecc(HashingAlgorithm::Sha512);
199+
}
200+
201+
fn checkquote_rsa(
202+
keybits: RsaKeyBits,
203+
hash_alg: HashingAlgorithm,
204+
sig_scheme: SignatureSchemeAlgorithm,
205+
) {
197206
let mut context = create_ctx_with_session();
198207
let ek_rsa = ek::create_ek_object(
199208
&mut context,
@@ -207,7 +216,7 @@ mod test_quote {
207216
ek_rsa,
208217
hash_alg,
209218
AsymmetricAlgorithmSelection::Rsa(keybits),
210-
SignatureSchemeAlgorithm::RsaPss,
219+
sig_scheme,
211220
Some(ak_auth.clone()),
212221
None,
213222
)
@@ -252,12 +261,29 @@ mod test_quote {
252261
}
253262

254263
#[test]
255-
fn checkquote_rsa_sha1() {
256-
checkquote_rsa(RsaKeyBits::Rsa2048, HashingAlgorithm::Sha1);
264+
fn checkquote_rsa_pss_sha1() {
265+
checkquote_rsa(
266+
RsaKeyBits::Rsa1024,
267+
HashingAlgorithm::Sha1,
268+
SignatureSchemeAlgorithm::RsaPss,
269+
);
257270
}
258271

259272
#[test]
260-
fn checkquote_rsa_sha256() {
261-
checkquote_rsa(RsaKeyBits::Rsa3072, HashingAlgorithm::Sha256);
273+
fn checkquote_rsa_ssa_sha256() {
274+
checkquote_rsa(
275+
RsaKeyBits::Rsa2048,
276+
HashingAlgorithm::Sha256,
277+
SignatureSchemeAlgorithm::RsaSsa,
278+
);
279+
}
280+
281+
#[test]
282+
fn checkquote_rsa_pss_sha384() {
283+
checkquote_rsa(
284+
RsaKeyBits::Rsa3072,
285+
HashingAlgorithm::Sha384,
286+
SignatureSchemeAlgorithm::RsaPss,
287+
);
262288
}
263289
}

0 commit comments

Comments
 (0)