Skip to content

Commit dab6bdb

Browse files
authored
Merge pull request #121 from wlynch/tsa-inclusive
Make TSA timestamp checks inclusive.
2 parents bb29cbe + 3d9275d commit dab6bdb

2 files changed

Lines changed: 87 additions & 76 deletions

File tree

ietf-cms/timestamp/timestamp.go

Lines changed: 79 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,16 @@ func GenerateNonce() *big.Int {
4444
}
4545

4646
// Request is a TimeStampReq
47-
// TimeStampReq ::= SEQUENCE {
48-
// version INTEGER { v1(1) },
49-
// messageImprint MessageImprint,
50-
// --a hash algorithm OID and the hash value of the data to be
51-
// --time-stamped
52-
// reqPolicy TSAPolicyId OPTIONAL,
53-
// nonce INTEGER OPTIONAL,
54-
// certReq BOOLEAN DEFAULT FALSE,
55-
// extensions [0] IMPLICIT Extensions OPTIONAL }
47+
//
48+
// TimeStampReq ::= SEQUENCE {
49+
// version INTEGER { v1(1) },
50+
// messageImprint MessageImprint,
51+
// --a hash algorithm OID and the hash value of the data to be
52+
// --time-stamped
53+
// reqPolicy TSAPolicyId OPTIONAL,
54+
// nonce INTEGER OPTIONAL,
55+
// certReq BOOLEAN DEFAULT FALSE,
56+
// extensions [0] IMPLICIT Extensions OPTIONAL }
5657
type Request struct {
5758
Version int
5859
MessageImprint MessageImprint
@@ -110,11 +111,12 @@ func (req Request) Do(url string) (Response, error) {
110111
}
111112

112113
// Response is a TimeStampResp
113-
// TimeStampResp ::= SEQUENCE {
114-
// status PKIStatusInfo,
115-
// timeStampToken TimeStampToken OPTIONAL }
116114
//
117-
// TimeStampToken ::= ContentInfo
115+
// TimeStampResp ::= SEQUENCE {
116+
// status PKIStatusInfo,
117+
// timeStampToken TimeStampToken OPTIONAL }
118+
//
119+
// TimeStampToken ::= ContentInfo
118120
type Response struct {
119121
Status PKIStatusInfo
120122
TimeStampToken protocol.ContentInfo `asn1:"optional"`
@@ -156,49 +158,49 @@ func (r Response) Info() (Info, error) {
156158
return ParseInfo(sd.EncapContentInfo)
157159
}
158160

159-
// PKIStatusInfo ::= SEQUENCE {
160-
// status PKIStatus,
161-
// statusString PKIFreeText OPTIONAL,
162-
// failInfo PKIFailureInfo OPTIONAL }
161+
// PKIStatusInfo ::= SEQUENCE {
162+
// status PKIStatus,
163+
// statusString PKIFreeText OPTIONAL,
164+
// failInfo PKIFailureInfo OPTIONAL }
163165
//
164-
// PKIStatus ::= INTEGER {
165-
// granted (0),
166-
// -- when the PKIStatus contains the value zero a TimeStampToken, as
167-
// requested, is present.
168-
// grantedWithMods (1),
169-
// -- when the PKIStatus contains the value one a TimeStampToken,
170-
// with modifications, is present.
171-
// rejection (2),
172-
// waiting (3),
173-
// revocationWarning (4),
174-
// -- this message contains a warning that a revocation is
175-
// -- imminent
176-
// revocationNotification (5)
177-
// -- notification that a revocation has occurred }
166+
// PKIStatus ::= INTEGER {
167+
// granted (0),
168+
// -- when the PKIStatus contains the value zero a TimeStampToken, as
169+
// requested, is present.
170+
// grantedWithMods (1),
171+
// -- when the PKIStatus contains the value one a TimeStampToken,
172+
// with modifications, is present.
173+
// rejection (2),
174+
// waiting (3),
175+
// revocationWarning (4),
176+
// -- this message contains a warning that a revocation is
177+
// -- imminent
178+
// revocationNotification (5)
179+
// -- notification that a revocation has occurred }
178180
//
179181
// -- When the TimeStampToken is not present
180182
// -- failInfo indicates the reason why the
181183
// -- time-stamp request was rejected and
182184
// -- may be one of the following values.
183185
//
184-
// PKIFailureInfo ::= BIT STRING {
185-
// badAlg (0),
186-
// -- unrecognized or unsupported Algorithm Identifier
187-
// badRequest (2),
188-
// -- transaction not permitted or supported
189-
// badDataFormat (5),
190-
// -- the data submitted has the wrong format
191-
// timeNotAvailable (14),
192-
// -- the TSA's time source is not available
193-
// unacceptedPolicy (15),
194-
// -- the requested TSA policy is not supported by the TSA.
195-
// unacceptedExtension (16),
196-
// -- the requested extension is not supported by the TSA.
197-
// addInfoNotAvailable (17)
198-
// -- the additional information requested could not be understood
199-
// -- or is not available
200-
// systemFailure (25)
201-
// -- the request cannot be handled due to system failure }
186+
// PKIFailureInfo ::= BIT STRING {
187+
// badAlg (0),
188+
// -- unrecognized or unsupported Algorithm Identifier
189+
// badRequest (2),
190+
// -- transaction not permitted or supported
191+
// badDataFormat (5),
192+
// -- the data submitted has the wrong format
193+
// timeNotAvailable (14),
194+
// -- the TSA's time source is not available
195+
// unacceptedPolicy (15),
196+
// -- the requested TSA policy is not supported by the TSA.
197+
// unacceptedExtension (16),
198+
// -- the requested extension is not supported by the TSA.
199+
// addInfoNotAvailable (17)
200+
// -- the additional information requested could not be understood
201+
// -- or is not available
202+
// systemFailure (25)
203+
// -- the request cannot be handled due to system failure }
202204
type PKIStatusInfo struct {
203205
Status int
204206
StatusString PKIFreeText `asn1:"optional"`
@@ -267,25 +269,26 @@ func (ft PKIFreeText) Strings() ([]string, error) {
267269
}
268270

269271
// Info is a TSTInfo
270-
// TSTInfo ::= SEQUENCE {
271-
// version INTEGER { v1(1) },
272-
// policy TSAPolicyId,
273-
// messageImprint MessageImprint,
274-
// -- MUST have the same value as the similar field in
275-
// -- TimeStampReq
276-
// serialNumber INTEGER,
277-
// -- Time-Stamping users MUST be ready to accommodate integers
278-
// -- up to 160 bits.
279-
// genTime GeneralizedTime,
280-
// accuracy Accuracy OPTIONAL,
281-
// ordering BOOLEAN DEFAULT FALSE,
282-
// nonce INTEGER OPTIONAL,
283-
// -- MUST be present if the similar field was present
284-
// -- in TimeStampReq. In that case it MUST have the same value.
285-
// tsa [0] GeneralName OPTIONAL,
286-
// extensions [1] IMPLICIT Extensions OPTIONAL }
287272
//
288-
// TSAPolicyId ::= OBJECT IDENTIFIER
273+
// TSTInfo ::= SEQUENCE {
274+
// version INTEGER { v1(1) },
275+
// policy TSAPolicyId,
276+
// messageImprint MessageImprint,
277+
// -- MUST have the same value as the similar field in
278+
// -- TimeStampReq
279+
// serialNumber INTEGER,
280+
// -- Time-Stamping users MUST be ready to accommodate integers
281+
// -- up to 160 bits.
282+
// genTime GeneralizedTime,
283+
// accuracy Accuracy OPTIONAL,
284+
// ordering BOOLEAN DEFAULT FALSE,
285+
// nonce INTEGER OPTIONAL,
286+
// -- MUST be present if the similar field was present
287+
// -- in TimeStampReq. In that case it MUST have the same value.
288+
// tsa [0] GeneralName OPTIONAL,
289+
// extensions [1] IMPLICIT Extensions OPTIONAL }
290+
//
291+
// TSAPolicyId ::= OBJECT IDENTIFIER
289292
type Info struct {
290293
Version int
291294
Policy asn1.ObjectIdentifier
@@ -328,14 +331,14 @@ func ParseInfo(eci protocol.EncapsulatedContentInfo) (Info, error) {
328331
// is before the specified time. For example, you might check that a signature
329332
// was made *before* a certificate's not-after date.
330333
func (i *Info) Before(t time.Time) bool {
331-
return i.genTimeMax().Before(t)
334+
return i.genTimeMax().Before(t) || i.genTimeMax().Equal(t)
332335
}
333336

334337
// After checks if the earlier time the signature could have been generated at
335338
// is before the specified time. For example, you might check that a signature
336339
// was made *after* a certificate's not-before date.
337340
func (i *Info) After(t time.Time) bool {
338-
return i.genTimeMin().After(t)
341+
return i.genTimeMin().After(t) || i.genTimeMin().Equal(t)
339342
}
340343

341344
// genTimeMax is the latest time at which the token could have been generated
@@ -350,9 +353,9 @@ func (i *Info) genTimeMin() time.Time {
350353
return i.GenTime.Add(-i.Accuracy.Duration())
351354
}
352355

353-
// MessageImprint ::= SEQUENCE {
354-
// hashAlgorithm AlgorithmIdentifier,
355-
// hashedMessage OCTET STRING }
356+
// MessageImprint ::= SEQUENCE {
357+
// hashAlgorithm AlgorithmIdentifier,
358+
// hashedMessage OCTET STRING }
356359
type MessageImprint struct {
357360
HashAlgorithm pkix.AlgorithmIdentifier
358361
HashedMessage []byte
@@ -408,10 +411,10 @@ func (mi MessageImprint) Equal(other MessageImprint) bool {
408411
return true
409412
}
410413

411-
// Accuracy ::= SEQUENCE {
412-
// seconds INTEGER OPTIONAL,
413-
// millis [0] INTEGER (1..999) OPTIONAL,
414-
// micros [1] INTEGER (1..999) OPTIONAL }
414+
// Accuracy ::= SEQUENCE {
415+
// seconds INTEGER OPTIONAL,
416+
// millis [0] INTEGER (1..999) OPTIONAL,
417+
// micros [1] INTEGER (1..999) OPTIONAL }
415418
type Accuracy struct {
416419
Seconds int `asn1:"optional"`
417420
Millis int `asn1:"tag:0,optional"`

ietf-cms/timestamp/timestamp_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,14 @@ func TestTSTInfo(t *testing.T) {
321321
t.Fatalf("expected gentimemax %s, got %s", expectedGenTimeMin.String(), inf.genTimeMin().String())
322322
}
323323

324+
// Timestamp before/after should be inclusive
325+
if !inf.Before(inf.genTimeMax()) {
326+
t.Errorf("before timestamp should be inclusive")
327+
}
328+
if !inf.After(inf.genTimeMin()) {
329+
t.Errorf("after timestamp should be inclusive")
330+
}
331+
324332
expectedOrdering := false
325333
if inf.Ordering != expectedOrdering {
326334
t.Fatalf("expected ordering %t, got %t", expectedOrdering, inf.Ordering)

0 commit comments

Comments
 (0)