1
- use cms:: cert:: x509:: spki:: AlgorithmIdentifierOwned ;
1
+ use cms:: {
2
+ content_info:: CmsVersion ,
3
+ signed_data:: { DigestAlgorithmIdentifiers , EncapsulatedContentInfo , SignerInfos } ,
4
+ } ;
2
5
use der:: {
3
- asn1:: { GeneralizedTime , OctetString } ,
6
+ asn1:: { GeneralizedTime , OctetString , SetOfVec } ,
4
7
oid:: ObjectIdentifier ,
5
- Any , Enumerated , Sequence , ValueOrd ,
8
+ Any , Decode , Enumerated , Sequence , ValueOrd ,
9
+ } ;
10
+ use x509_cert:: {
11
+ ext:: Extensions , impl_newtype, serial_number:: SerialNumber , spki:: AlgorithmIdentifierOwned ,
6
12
} ;
7
- use x509_cert:: { ext:: Extensions , serial_number:: SerialNumber } ;
8
13
9
14
pub const ID_SPC_INDIRECT_DATA : ObjectIdentifier =
10
15
ObjectIdentifier :: new_unwrap ( "1.3.6.1.4.1.311.2.1.4" ) ;
@@ -42,13 +47,25 @@ pub struct SpcIndirectDataContent {
42
47
pub message_digest : DigestInfo ,
43
48
}
44
49
50
+ /// Timestamps on TrustedTpm.cab feature mis-encoded GeneralizedTime values, as shown in this dump
51
+ /// generated using dumpasn1:
52
+ ///
53
+ /// ```text
54
+ /// 4477 19: GeneralizedTime '20240614203756.847Z'
55
+ /// : Error: Time is encoded incorrectly.
56
+ ///```
57
+ ///
58
+ /// This structure treats the time field as an Any, which at least allows the message digest to be
59
+ /// compared.
60
+ ///
61
+ /// References from https://github.com/carl-wallace/tpm_cab_verify/blob/main/src/asn1.rs#L39C1-L48C14
45
62
#[ derive( Clone , Debug , Eq , PartialEq , Sequence ) ]
46
63
pub struct TSTInfo {
47
64
pub version : TSTVersion ,
48
65
pub policy : ObjectIdentifier ,
49
66
pub message_imprint : MessageImprint ,
50
67
pub serial_number : SerialNumber ,
51
- pub gen_time : GeneralizedTime ,
68
+ pub gen_time : Any ,
52
69
#[ asn1( optional = "true" ) ]
53
70
pub accuracy : Option < Any > ,
54
71
#[ asn1( optional = "true" ) ]
@@ -61,6 +78,21 @@ pub struct TSTInfo {
61
78
pub extensions : Option < Extensions > ,
62
79
}
63
80
81
+ impl TSTInfo {
82
+ pub fn get_gen_time ( self : & Self ) -> Result < GeneralizedTime , der:: Error > {
83
+ let value = self . gen_time . value ( ) ;
84
+ if value. len ( ) > 15 {
85
+ let mut fix_value = vec ! [ 0x18 , 0x0F ] ;
86
+ fix_value. extend ( & value[ ..14 ] ) ;
87
+ fix_value. extend ( & [ b'Z' ] ) ;
88
+
89
+ Ok ( GeneralizedTime :: from_der ( & fix_value) ?)
90
+ } else {
91
+ Ok ( GeneralizedTime :: from_der ( & value) ?)
92
+ }
93
+ }
94
+ }
95
+
64
96
#[ derive( Clone , Debug , Copy , PartialEq , Eq , PartialOrd , Ord , Enumerated ) ]
65
97
#[ asn1( type = "INTEGER" ) ]
66
98
#[ repr( u8 ) ]
@@ -74,3 +106,45 @@ pub struct MessageImprint {
74
106
pub hash_algorithm : AlgorithmIdentifierOwned ,
75
107
pub hashed_message : OctetString ,
76
108
}
109
+
110
+ /// Alternative SignedData decoder that tolerates v1 attribute certificates.
111
+ ///
112
+ /// For some bizarre reason, the SignedData used for the timestamp includes v1 attribute certs (!!!),
113
+ /// which are marked as obsolete in CMS and are not supported in the cms crate.
114
+ ///
115
+ /// References from https://github.com/carl-wallace/tpm_cab_verify/blob/main/src/asn1.rs#L23.
116
+ #[ derive( Clone , Debug , Eq , PartialEq , Sequence ) ]
117
+ #[ allow( missing_docs) ]
118
+ pub ( crate ) struct SignedData {
119
+ pub version : CmsVersion ,
120
+ pub digest_algorithms : DigestAlgorithmIdentifiers ,
121
+ pub encap_content_info : EncapsulatedContentInfo ,
122
+ //todo consider defer decoding certs and CRLs
123
+ #[ asn1( context_specific = "0" , tag_mode = "IMPLICIT" , optional = "true" ) ]
124
+ pub certificates : Option < AnySet > ,
125
+ #[ asn1( context_specific = "1" , tag_mode = "IMPLICIT" , optional = "true" ) ]
126
+ pub crls : Option < AnySet > ,
127
+ pub signer_infos : SignerInfos ,
128
+ }
129
+
130
+ /// Used in lieu of full support for all certificate and CRL types
131
+ #[ derive( Clone , Eq , PartialEq , Debug ) ]
132
+ pub ( crate ) struct AnySet ( pub SetOfVec < Any > ) ;
133
+ impl_newtype ! ( AnySet , SetOfVec <Any >) ;
134
+
135
+ #[ cfg( test) ]
136
+ mod test {
137
+ use der:: Decode ;
138
+
139
+ use super :: TSTInfo ;
140
+
141
+ #[ test]
142
+ fn test_tstinfo_with_malformed_generalizedtime ( ) {
143
+ let tstinfo = TSTInfo :: from_der ( include_bytes ! (
144
+ "./examples/tstinfo_with_malformed_generalizedtime.bin"
145
+ ) )
146
+ . unwrap ( ) ;
147
+
148
+ assert ! ( tstinfo. get_gen_time( ) . is_ok( ) ) ;
149
+ }
150
+ }
0 commit comments