1#[cfg(feature = "tsa-verify")]
5pub use inner::{verify, verify_with_extra_cert, TsaProvider, VerifiedToken};
6
7#[cfg(feature = "tsa-verify")]
8pub(crate) mod inner {
9 use rasn::prelude::*;
10 use rasn_pkix::Certificate;
11 use sha2::{Digest, Sha256, Sha384, Sha512};
12
13 use crate::error::Error;
14
15 const OID_SIGNED_DATA: &[u32] = &[1, 2, 840, 113549, 1, 7, 2];
18 const OID_TST_INFO: &[u32] = &[1, 2, 840, 113549, 1, 9, 16, 1, 4];
19 const OID_MESSAGE_DIGEST: &[u32] = &[1, 2, 840, 113549, 1, 9, 4];
20 const OID_SHA256: &[u32] = &[2, 16, 840, 1, 101, 3, 4, 2, 1];
21 const OID_SHA384: &[u32] = &[2, 16, 840, 1, 101, 3, 4, 2, 2];
22 const OID_SHA512: &[u32] = &[2, 16, 840, 1, 101, 3, 4, 2, 3];
23 const OID_RSA_ENCRYPTION: &[u32] = &[1, 2, 840, 113549, 1, 1, 1];
24 const OID_RSA_SHA256: &[u32] = &[1, 2, 840, 113549, 1, 1, 11];
25 const OID_RSA_SHA384: &[u32] = &[1, 2, 840, 113549, 1, 1, 12];
26 const OID_RSA_SHA512: &[u32] = &[1, 2, 840, 113549, 1, 1, 13];
27 const OID_ECDSA_SHA256: &[u32] = &[1, 2, 840, 10045, 4, 3, 2];
28 const OID_ECDSA_SHA384: &[u32] = &[1, 2, 840, 10045, 4, 3, 3];
29 const OID_ECDSA_SHA512: &[u32] = &[1, 2, 840, 10045, 4, 3, 4];
30 const OID_SUBJECT_KEY_ID: &[u32] = &[2, 5, 29, 14];
31
32 fn oid(parts: &[u32]) -> ObjectIdentifier {
33 ObjectIdentifier::new(parts.to_vec()).expect("static OID is valid")
34 }
35
36 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
39 pub struct AlgorithmIdentifier {
40 pub algorithm: ObjectIdentifier,
41 pub parameters: Option<Any>,
42 }
43
44 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
45 pub struct IssuerAndSerialNumber {
46 pub issuer: Any,
47 pub serial_number: Integer,
48 }
49
50 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
51 #[rasn(choice)]
52 pub enum SignerIdentifier {
53 IssuerAndSerialNumber(IssuerAndSerialNumber),
54 #[rasn(tag(0))]
55 SubjectKeyIdentifier(OctetString),
56 }
57
58 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
59 pub struct Attribute {
60 pub attr_type: ObjectIdentifier,
61 pub attr_values: SetOf<Any>,
62 }
63
64 pub type Attributes = SetOf<Attribute>;
65
66 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
67 pub struct SignerInfo {
68 pub version: Integer,
69 pub sid: SignerIdentifier,
70 pub digest_algorithm: AlgorithmIdentifier,
71 #[rasn(tag(0))]
72 pub signed_attrs: Option<Attributes>,
73 pub signature_algorithm: AlgorithmIdentifier,
74 pub signature: OctetString,
75 }
76
77 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
78 pub struct EncapsulatedContentInfo {
79 pub e_content_type: ObjectIdentifier,
80 #[rasn(tag(explicit(0)))]
81 pub e_content: Option<OctetString>,
82 }
83
84 #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
85 pub struct SignedData {
86 pub version: Integer,
87 pub digest_algorithms: SetOf<AlgorithmIdentifier>,
88 pub encap_content_info: EncapsulatedContentInfo,
89 #[rasn(tag(0))]
90 pub certificates: Option<SetOf<Any>>,
91 pub signer_infos: SetOf<SignerInfo>,
92 }
93
94 #[derive(AsnType, Clone, Debug, Decode, Encode)]
95 pub struct ContentInfo {
96 pub content_type: ObjectIdentifier,
97 #[rasn(tag(explicit(0)))]
98 pub content: Any,
99 }
100
101 #[derive(AsnType, Clone, Debug, Decode, Encode)]
103 pub struct TstAccuracy {
104 pub seconds: Option<Integer>,
105 #[rasn(tag(0))]
106 pub millis: Option<Integer>,
107 #[rasn(tag(1))]
108 pub micros: Option<Integer>,
109 }
110
111 #[derive(AsnType, Clone, Debug, Decode, Encode)]
113 pub struct TstInfo {
114 pub version: Integer,
115 pub policy: ObjectIdentifier,
116 pub message_imprint: MessageImprint,
117 pub serial_number: Integer,
118 pub gen_time: GeneralizedTime,
119 pub accuracy: Option<TstAccuracy>,
121 pub ordering: Option<bool>,
123 pub nonce: Option<Integer>,
124 #[rasn(tag(explicit(0)))]
126 pub tsa: Option<Any>,
127 #[rasn(tag(1))]
128 pub extensions: Option<Any>,
129 }
130
131 #[derive(AsnType, Clone, Debug, Decode, Encode)]
132 pub struct MessageImprint {
133 pub hash_algorithm: AlgorithmIdentifier,
134 pub hashed_message: OctetString,
135 }
136
137 #[derive(Debug, Clone, PartialEq, Eq)]
139 pub enum TsaProvider {
140 FreeTsa,
141 Sectigo,
142 Qtsa,
143 }
144
145 #[derive(Debug, Clone)]
146 pub struct VerifiedToken {
147 pub provider: TsaProvider,
148 pub hashed_message: Vec<u8>,
149 pub serial_number: String,
150 pub gen_time_unix: i64,
151 }
152
153 struct TrustAnchor {
154 provider: TsaProvider,
155 chain: &'static [&'static [u8]],
156 }
157
158 fn trust_anchors() -> Vec<TrustAnchor> {
159 vec![
160 TrustAnchor {
161 provider: TsaProvider::FreeTsa,
162 chain: &[
163 include_bytes!("certs/freetsa_root.der"),
164 include_bytes!("certs/freetsa_tsa.der"),
165 ],
166 },
167 TrustAnchor {
168 provider: TsaProvider::Sectigo,
169 chain: &[
170 include_bytes!("certs/sectigo_usertrust_root.der"),
171 include_bytes!("certs/sectigo_tsa_r36.der"),
172 ],
173 },
174 TrustAnchor {
175 provider: TsaProvider::Qtsa,
176 chain: &[
177 include_bytes!("certs/qtsa_root.der"),
178 include_bytes!("certs/qtsa_intermediate.der"),
179 include_bytes!("certs/qtsa_tsa_g4.der"),
180 ],
181 },
182 ]
183 }
184
185 pub fn verify(token_der: &[u8], message: &[u8]) -> crate::Result<VerifiedToken> {
187 verify_inner(token_der, message, &[])
188 }
189
190 pub fn verify_with_extra_cert(
192 token_der: &[u8],
193 message: &[u8],
194 extra_cert_der: &[u8],
195 extra_provider: TsaProvider,
196 ) -> crate::Result<VerifiedToken> {
197 verify_inner(token_der, message, &[(extra_cert_der, extra_provider)])
198 }
199
200 fn verify_inner(
201 token_der: &[u8],
202 message: &[u8],
203 extra_trusted: &[(&[u8], TsaProvider)],
204 ) -> crate::Result<VerifiedToken> {
205 let ci: ContentInfo = rasn::der::decode(token_der)
206 .map_err(|e| Error::TsaParse(format!("ContentInfo: {e}")))?;
207
208 if ci.content_type != oid(OID_SIGNED_DATA) {
209 return Err(Error::TsaParse("not a SignedData content type".into()));
210 }
211
212 let sd: SignedData = rasn::der::decode(ci.content.as_bytes())
213 .map_err(|e| Error::TsaParse(format!("SignedData: {e}")))?;
214
215 if sd.encap_content_info.e_content_type != oid(OID_TST_INFO) {
216 return Err(Error::TsaParse("encapContentInfo is not TSTInfo".into()));
217 }
218
219 let e_content = sd
220 .encap_content_info
221 .e_content
222 .as_ref()
223 .ok_or_else(|| Error::TsaParse("missing eContent".into()))?;
224 let tst_der: &[u8] = e_content.as_ref();
225
226 let tst: TstInfo =
227 rasn::der::decode(tst_der).map_err(|e| Error::TsaParse(format!("TSTInfo: {e}")))?;
228
229 verify_message_imprint(&tst, message)?;
230
231 let signer_infos = sd.signer_infos.to_vec();
232 let signer = signer_infos
233 .into_iter()
234 .next()
235 .ok_or_else(|| Error::TsaParse("no SignerInfo in SignedData".into()))?;
236
237 let signer_cert_der = find_signer_cert(&sd, signer, extra_trusted)?;
238 let provider = identify_provider(&signer_cert_der, extra_trusted)?;
239
240 verify_signature(signer, &signer_cert_der, tst_der)?;
241
242 Ok(VerifiedToken {
243 provider,
244 hashed_message: tst.message_imprint.hashed_message.to_vec(),
245 serial_number: format!("{}", tst.serial_number),
246 gen_time_unix: tst.gen_time.timestamp(),
247 })
248 }
249
250 fn verify_message_imprint(tst: &TstInfo, message: &[u8]) -> crate::Result<()> {
251 let alg_oid = &tst.message_imprint.hash_algorithm.algorithm;
252 let expected: Vec<u8> = if *alg_oid == oid(OID_SHA256) {
253 Sha256::digest(message).to_vec()
254 } else if *alg_oid == oid(OID_SHA384) {
255 Sha384::digest(message).to_vec()
256 } else if *alg_oid == oid(OID_SHA512) {
257 Sha512::digest(message).to_vec()
258 } else {
259 return Err(Error::TsaVerification(
260 "unsupported hash algorithm in message imprint".into(),
261 ));
262 };
263
264 if tst.message_imprint.hashed_message.as_ref() != expected.as_slice() {
265 return Err(Error::TsaVerification(
266 "message imprint hash mismatch".into(),
267 ));
268 }
269 Ok(())
270 }
271
272 fn find_signer_cert(
273 sd: &SignedData,
274 signer: &SignerInfo,
275 extra_trusted: &[(&[u8], TsaProvider)],
276 ) -> crate::Result<Vec<u8>> {
277 if let Some(certs) = &sd.certificates {
279 for cert_any in certs.to_vec() {
280 let cert_der = cert_any.as_bytes();
281 if signer_matches_cert(signer, cert_der) {
282 return Ok(cert_der.to_vec());
283 }
284 }
285 }
286
287 for anchor in trust_anchors() {
289 for &cert_der in anchor.chain {
290 if signer_matches_cert(signer, cert_der) {
291 return Ok(cert_der.to_vec());
292 }
293 }
294 }
295
296 for (cert_der, _) in extra_trusted {
298 if signer_matches_cert(signer, cert_der) {
299 return Ok(cert_der.to_vec());
300 }
301 }
302
303 Err(Error::TsaParse(
304 "signer certificate not found in token or trust anchors".into(),
305 ))
306 }
307
308 fn signer_matches_cert(signer: &SignerInfo, cert_der: &[u8]) -> bool {
309 let Ok(cert) = rasn::der::decode::<Certificate>(cert_der) else {
310 return false;
311 };
312 match &signer.sid {
313 SignerIdentifier::IssuerAndSerialNumber(isn) => {
314 cert.tbs_certificate.serial_number == isn.serial_number
315 }
316 SignerIdentifier::SubjectKeyIdentifier(skid) => cert
317 .tbs_certificate
318 .extensions
319 .as_ref()
320 .and_then(|exts| exts.iter().find(|e| e.extn_id == oid(OID_SUBJECT_KEY_ID)))
321 .map(|e| e.extn_value.as_ref() == skid.as_ref())
322 .unwrap_or(false),
323 }
324 }
325
326 fn identify_provider(
327 signer_cert_der: &[u8],
328 extra_trusted: &[(&[u8], TsaProvider)],
329 ) -> crate::Result<TsaProvider> {
330 for (cert, provider) in extra_trusted {
331 if *cert == signer_cert_der {
332 return Ok(provider.clone());
333 }
334 }
335 for anchor in trust_anchors() {
336 if anchor.chain.contains(&signer_cert_der) {
337 return Ok(anchor.provider);
338 }
339 }
340 Err(Error::TsaUntrustedProvider)
341 }
342
343 fn verify_signature(
344 signer: &SignerInfo,
345 cert_der: &[u8],
346 e_content_der: &[u8],
347 ) -> crate::Result<()> {
348 let cert: Certificate = rasn::der::decode(cert_der)
349 .map_err(|e| Error::TsaParse(format!("signer cert: {e}")))?;
350
351 let spki_der = rasn::der::encode(&cert.tbs_certificate.subject_public_key_info)
352 .map_err(|e| Error::TsaParse(format!("SPKI encode: {e}")))?;
353
354 let signed_bytes: Vec<u8> = match &signer.signed_attrs {
355 Some(attrs) => {
356 rasn::der::encode(attrs)
358 .map_err(|e| Error::TsaParse(format!("signedAttrs encode: {e}")))?
359 }
360 None => e_content_der.to_vec(),
361 };
362
363 if let Some(attrs) = &signer.signed_attrs {
364 verify_message_digest_attr(attrs, e_content_der, &signer.digest_algorithm)?;
365 }
366
367 let sig_alg = &signer.signature_algorithm.algorithm;
368 let sig_bytes = signer.signature.as_ref();
369
370 if *sig_alg == oid(OID_RSA_SHA256) {
371 verify_rsa_sha256(sig_bytes, &signed_bytes, &spki_der)
372 } else if *sig_alg == oid(OID_RSA_SHA384) {
373 verify_rsa_sha384(sig_bytes, &signed_bytes, &spki_der)
374 } else if *sig_alg == oid(OID_RSA_SHA512) {
375 verify_rsa_sha512(sig_bytes, &signed_bytes, &spki_der)
376 } else if *sig_alg == oid(OID_RSA_ENCRYPTION) {
377 let digest_oid = &signer.digest_algorithm.algorithm;
380 if *digest_oid == oid(OID_SHA256) {
381 verify_rsa_sha256(sig_bytes, &signed_bytes, &spki_der)
382 } else if *digest_oid == oid(OID_SHA384) {
383 verify_rsa_sha384(sig_bytes, &signed_bytes, &spki_der)
384 } else if *digest_oid == oid(OID_SHA512) {
385 verify_rsa_sha512(sig_bytes, &signed_bytes, &spki_der)
386 } else {
387 Err(Error::TsaVerification(format!(
388 "unsupported digest for rsaEncryption: {:?}",
389 digest_oid
390 )))
391 }
392 } else if *sig_alg == oid(OID_ECDSA_SHA256) {
393 verify_ecdsa_p256(sig_bytes, &signed_bytes, &spki_der)
394 } else if *sig_alg == oid(OID_ECDSA_SHA384) {
395 verify_ecdsa_p384(sig_bytes, &signed_bytes, &spki_der)
396 } else if *sig_alg == oid(OID_ECDSA_SHA512) {
397 verify_ecdsa_sha512(sig_bytes, &signed_bytes, &spki_der)
398 } else {
399 Err(Error::TsaVerification(format!(
400 "unsupported signature algorithm: {:?}",
401 sig_alg
402 )))
403 }
404 }
405
406 fn verify_message_digest_attr(
407 attrs: &Attributes,
408 e_content_der: &[u8],
409 digest_alg: &AlgorithmIdentifier,
410 ) -> crate::Result<()> {
411 let md_oid = oid(OID_MESSAGE_DIGEST);
412 let attrs_vec = attrs.to_vec();
413 let Some(md_attr) = attrs_vec.into_iter().find(|a| a.attr_type == md_oid) else {
414 return Err(Error::TsaVerification(
415 "messageDigest attribute missing".into(),
416 ));
417 };
418
419 let vals = md_attr.attr_values.to_vec();
420 let Some(md_any) = vals.into_iter().next() else {
421 return Err(Error::TsaVerification("empty messageDigest value".into()));
422 };
423
424 let expected: OctetString = rasn::der::decode(md_any.as_bytes())
425 .map_err(|e| Error::TsaParse(format!("messageDigest: {e}")))?;
426
427 let actual: Vec<u8> = if digest_alg.algorithm == oid(OID_SHA256) {
428 Sha256::digest(e_content_der).to_vec()
429 } else if digest_alg.algorithm == oid(OID_SHA384) {
430 Sha384::digest(e_content_der).to_vec()
431 } else if digest_alg.algorithm == oid(OID_SHA512) {
432 Sha512::digest(e_content_der).to_vec()
433 } else {
434 return Err(Error::TsaVerification(
435 "unsupported digest algorithm".into(),
436 ));
437 };
438
439 if expected.as_ref() != actual.as_slice() {
440 return Err(Error::TsaVerification("messageDigest mismatch".into()));
441 }
442 Ok(())
443 }
444
445 fn verify_rsa_sha256(sig: &[u8], data: &[u8], spki_der: &[u8]) -> crate::Result<()> {
446 use rsa::{pkcs1v15::VerifyingKey, pkcs8::DecodePublicKey, signature::Verifier};
447 let pk = rsa::RsaPublicKey::from_public_key_der(spki_der)
448 .map_err(|e| Error::TsaVerification(format!("RSA key: {e}")))?;
449 let vk: VerifyingKey<Sha256> = VerifyingKey::new(pk);
450 let sig = rsa::pkcs1v15::Signature::try_from(sig)
451 .map_err(|e| Error::TsaVerification(format!("RSA sig: {e}")))?;
452 vk.verify(data, &sig)
453 .map_err(|_| Error::TsaVerification("RSA-SHA256 invalid".into()))
454 }
455
456 fn verify_rsa_sha384(sig: &[u8], data: &[u8], spki_der: &[u8]) -> crate::Result<()> {
457 use rsa::{pkcs1v15::VerifyingKey, pkcs8::DecodePublicKey, signature::Verifier};
458 let pk = rsa::RsaPublicKey::from_public_key_der(spki_der)
459 .map_err(|e| Error::TsaVerification(format!("RSA key: {e}")))?;
460 let vk: VerifyingKey<Sha384> = VerifyingKey::new(pk);
461 let sig = rsa::pkcs1v15::Signature::try_from(sig)
462 .map_err(|e| Error::TsaVerification(format!("RSA sig: {e}")))?;
463 vk.verify(data, &sig)
464 .map_err(|_| Error::TsaVerification("RSA-SHA384 invalid".into()))
465 }
466
467 fn verify_rsa_sha512(sig: &[u8], data: &[u8], spki_der: &[u8]) -> crate::Result<()> {
468 use rsa::{pkcs1v15::VerifyingKey, pkcs8::DecodePublicKey, signature::Verifier};
469 let pk = rsa::RsaPublicKey::from_public_key_der(spki_der)
470 .map_err(|e| Error::TsaVerification(format!("RSA key: {e}")))?;
471 let vk: VerifyingKey<Sha512> = VerifyingKey::new(pk);
472 let sig = rsa::pkcs1v15::Signature::try_from(sig)
473 .map_err(|e| Error::TsaVerification(format!("RSA sig: {e}")))?;
474 vk.verify(data, &sig)
475 .map_err(|_| Error::TsaVerification("RSA-SHA512 invalid".into()))
476 }
477
478 fn verify_ecdsa_p256(sig: &[u8], data: &[u8], spki_der: &[u8]) -> crate::Result<()> {
479 use p256::{
480 ecdsa::{signature::Verifier, DerSignature, VerifyingKey},
481 pkcs8::DecodePublicKey,
482 };
483 let vk = VerifyingKey::from_public_key_der(spki_der)
484 .map_err(|e| Error::TsaVerification(format!("P-256 key: {e}")))?;
485 let sig = DerSignature::try_from(sig)
486 .map_err(|e| Error::TsaVerification(format!("P-256 sig: {e}")))?;
487 vk.verify(data, &sig)
488 .map_err(|_| Error::TsaVerification("ECDSA-P256-SHA256 invalid".into()))
489 }
490
491 fn verify_ecdsa_p384(sig: &[u8], data: &[u8], spki_der: &[u8]) -> crate::Result<()> {
492 use p384::ecdsa::{signature::Verifier, DerSignature, VerifyingKey};
493 use p384::pkcs8::DecodePublicKey;
494 let vk = VerifyingKey::from_public_key_der(spki_der)
495 .map_err(|e| Error::TsaVerification(format!("P-384 key: {e}")))?;
496 let sig = DerSignature::try_from(sig)
497 .map_err(|e| Error::TsaVerification(format!("P-384 sig: {e}")))?;
498 vk.verify(data, &sig)
499 .map_err(|_| Error::TsaVerification("ECDSA-P384-SHA384 invalid".into()))
500 }
501
502 fn verify_ecdsa_sha512(sig: &[u8], data: &[u8], spki_der: &[u8]) -> crate::Result<()> {
504 let prehash = Sha512::digest(data);
505
506 {
507 use p256::pkcs8::DecodePublicKey;
509 if let Ok(vk) = p256::ecdsa::VerifyingKey::from_public_key_der(spki_der) {
510 use p256::ecdsa::signature::hazmat::PrehashVerifier;
511 let raw = p256::ecdsa::Signature::from_der(sig)
512 .map_err(|e| Error::TsaVerification(format!("sig: {e}")))?;
513 return vk
514 .verify_prehash(prehash.as_slice(), &raw)
515 .map_err(|_| Error::TsaVerification("ECDSA-P256-SHA512 invalid".into()));
516 }
517 }
518
519 {
520 use p384::pkcs8::DecodePublicKey;
522 if let Ok(vk) = p384::ecdsa::VerifyingKey::from_public_key_der(spki_der) {
523 use p384::ecdsa::signature::hazmat::PrehashVerifier;
524 let raw = p384::ecdsa::Signature::from_der(sig)
525 .map_err(|e| Error::TsaVerification(format!("sig: {e}")))?;
526 return vk
527 .verify_prehash(prehash.as_slice(), &raw)
528 .map_err(|_| Error::TsaVerification("ECDSA-P384-SHA512 invalid".into()));
529 }
530 }
531
532 Err(Error::TsaVerification(
533 "ECDSA-SHA512: unsupported EC curve (expected P-256 or P-384)".into(),
534 ))
535 }
536
537 #[cfg(test)]
538 pub mod mock {
539 use rasn::prelude::*;
542 use rsa::{
543 pkcs1v15::SigningKey,
544 pkcs8::EncodePublicKey,
545 rand_core::OsRng,
546 signature::{RandomizedSigner, SignatureEncoding},
547 RsaPrivateKey,
548 };
549 use sha2::{Digest, Sha256};
550
551 use super::*;
552
553 const TEST_RSA_BITS: usize = 512;
554
555 const OID_SHA256_OBJ: &[u32] = &[2, 16, 840, 1, 101, 3, 4, 2, 1];
556 const OID_RSA_SHA256_OBJ: &[u32] = &[1, 2, 840, 113549, 1, 1, 11];
557 const OID_SIGNED_DATA_OBJ: &[u32] = &[1, 2, 840, 113549, 1, 7, 2];
558 const OID_TST_INFO_OBJ: &[u32] = &[1, 2, 840, 113549, 1, 9, 16, 1, 4];
559 const OID_MESSAGE_DIGEST_OBJ: &[u32] = &[1, 2, 840, 113549, 1, 9, 4];
560 const OID_MOCK_POLICY: &[u32] = &[1, 3, 6, 1, 4, 1, 0, 1];
561
562 fn o(parts: &[u32]) -> ObjectIdentifier {
563 ObjectIdentifier::new(parts.to_vec()).unwrap()
564 }
565
566 fn sha256_alg() -> AlgorithmIdentifier {
567 AlgorithmIdentifier {
568 algorithm: o(OID_SHA256_OBJ),
569 parameters: None,
570 }
571 }
572
573 fn rsa_sha256_alg() -> AlgorithmIdentifier {
574 AlgorithmIdentifier {
575 algorithm: o(OID_RSA_SHA256_OBJ),
576 parameters: None,
577 }
578 }
579
580 pub fn build(message: &[u8]) -> (Vec<u8>, Vec<u8>) {
582 let sk = RsaPrivateKey::new(&mut OsRng, TEST_RSA_BITS).expect("RSA key gen");
583 let signing_key: SigningKey<Sha256> = SigningKey::new(sk.clone());
584
585 let spki_der = sk.to_public_key().to_public_key_der().unwrap().to_vec();
586
587 let msg_hash = Sha256::digest(message);
589 let tst = TstInfo {
590 version: Integer::from(1u8),
591 policy: o(OID_MOCK_POLICY),
592 message_imprint: MessageImprint {
593 hash_algorithm: sha256_alg(),
594 hashed_message: OctetString::from(msg_hash.to_vec()),
595 },
596 serial_number: Integer::from(42u8),
597 gen_time: chrono::Utc::now().fixed_offset(),
598 accuracy: None,
599 ordering: None,
600 nonce: None,
601 tsa: None,
602 extensions: None,
603 };
604 let tst_der = rasn::der::encode(&tst).unwrap();
605
606 let tst_digest = Sha256::digest(&tst_der);
608 let digest_attr = build_message_digest_attr(&tst_digest);
609 let mut signed_attrs = Attributes::new();
610 signed_attrs.insert(digest_attr);
611 let signed_attrs_der = rasn::der::encode(&signed_attrs).unwrap();
612
613 let sig_bytes: Vec<u8> = signing_key
615 .sign_with_rng(&mut OsRng, &signed_attrs_der)
616 .to_bytes()
617 .to_vec();
618
619 let signer_info = SignerInfo {
621 version: Integer::from(1u8),
622 sid: SignerIdentifier::IssuerAndSerialNumber(IssuerAndSerialNumber {
623 issuer: Any::new(vec![]),
624 serial_number: Integer::from(42u8),
625 }),
626 digest_algorithm: sha256_alg(),
627 signed_attrs: Some(signed_attrs),
628 signature_algorithm: rsa_sha256_alg(),
629 signature: OctetString::from(sig_bytes),
630 };
631
632 let mut certs_set = SetOf::<Any>::new();
634 certs_set.insert(Any::new(spki_der.clone()));
635
636 let mut digest_algs = SetOf::new();
637 digest_algs.insert(sha256_alg());
638 let mut signer_infos = SetOf::new();
639 signer_infos.insert(signer_info);
640
641 let sd = SignedData {
642 version: Integer::from(3u8),
643 digest_algorithms: digest_algs,
644 encap_content_info: EncapsulatedContentInfo {
645 e_content_type: o(OID_TST_INFO_OBJ),
646 e_content: Some(OctetString::from(tst_der)),
647 },
648 certificates: Some(certs_set),
649 signer_infos,
650 };
651 let sd_der = rasn::der::encode(&sd).unwrap();
652
653 let ci = ContentInfo {
654 content_type: o(OID_SIGNED_DATA_OBJ),
655 content: Any::new(sd_der),
656 };
657 let token_der = rasn::der::encode(&ci).unwrap();
658
659 (token_der, spki_der)
660 }
661
662 fn build_message_digest_attr(digest: &[u8]) -> Attribute {
663 let val_der = rasn::der::encode(&OctetString::from(digest.to_vec())).unwrap();
664 let mut vals = SetOf::<Any>::new();
665 vals.insert(Any::new(val_der));
666 Attribute {
667 attr_type: o(OID_MESSAGE_DIGEST_OBJ),
668 attr_values: vals,
669 }
670 }
671
672 }
675
676 #[cfg(test)]
677 mod tests {
678 use super::mock;
679 use super::*;
680
681 #[test]
682 fn mock_token_parses_and_imprint_matches() {
683 let message = b"hello from the test suite";
684 let (token_der, _spki_der) = mock::build(message);
685
686 let ci: ContentInfo = rasn::der::decode(&token_der).unwrap();
688 assert_eq!(ci.content_type, oid(OID_SIGNED_DATA));
689
690 let sd: SignedData = rasn::der::decode(ci.content.as_bytes()).unwrap();
691 let tst_der: &[u8] = sd.encap_content_info.e_content.as_ref().unwrap().as_ref();
692 let tst: TstInfo = rasn::der::decode(tst_der).unwrap();
693
694 let expected: Vec<u8> = sha2::Sha256::digest(message).to_vec();
695 assert_eq!(
696 tst.message_imprint.hashed_message.as_ref(),
697 expected.as_slice()
698 );
699 }
700
701 #[test]
702 fn wrong_message_imprint_detected() {
703 let message = b"correct message";
704 let (token_der, _spki_der) = mock::build(message);
705
706 let ci: ContentInfo = rasn::der::decode(&token_der).unwrap();
708 let sd: SignedData = rasn::der::decode(ci.content.as_bytes()).unwrap();
709 let tst_der: &[u8] = sd.encap_content_info.e_content.as_ref().unwrap().as_ref();
710 let tst: TstInfo = rasn::der::decode(tst_der).unwrap();
711
712 let wrong_hash: Vec<u8> = sha2::Sha256::digest(b"wrong message").to_vec();
713 assert_ne!(
714 tst.message_imprint.hashed_message.as_ref(),
715 wrong_hash.as_slice()
716 );
717 }
718 }
719}