Skip to content

Commit

Permalink
Merge pull request #121 from wlynch/tsa-inclusive
Browse files Browse the repository at this point in the history
Make TSA timestamp checks inclusive.
  • Loading branch information
vcsjones authored Sep 17, 2024
2 parents bb29cbe + 3d9275d commit dab6bdb
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 76 deletions.
155 changes: 79 additions & 76 deletions ietf-cms/timestamp/timestamp.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,16 @@ func GenerateNonce() *big.Int {
}

// Request is a TimeStampReq
// TimeStampReq ::= SEQUENCE {
// version INTEGER { v1(1) },
// messageImprint MessageImprint,
// --a hash algorithm OID and the hash value of the data to be
// --time-stamped
// reqPolicy TSAPolicyId OPTIONAL,
// nonce INTEGER OPTIONAL,
// certReq BOOLEAN DEFAULT FALSE,
// extensions [0] IMPLICIT Extensions OPTIONAL }
//
// TimeStampReq ::= SEQUENCE {
// version INTEGER { v1(1) },
// messageImprint MessageImprint,
// --a hash algorithm OID and the hash value of the data to be
// --time-stamped
// reqPolicy TSAPolicyId OPTIONAL,
// nonce INTEGER OPTIONAL,
// certReq BOOLEAN DEFAULT FALSE,
// extensions [0] IMPLICIT Extensions OPTIONAL }
type Request struct {
Version int
MessageImprint MessageImprint
Expand Down Expand Up @@ -110,11 +111,12 @@ func (req Request) Do(url string) (Response, error) {
}

// Response is a TimeStampResp
// TimeStampResp ::= SEQUENCE {
// status PKIStatusInfo,
// timeStampToken TimeStampToken OPTIONAL }
//
// TimeStampToken ::= ContentInfo
// TimeStampResp ::= SEQUENCE {
// status PKIStatusInfo,
// timeStampToken TimeStampToken OPTIONAL }
//
// TimeStampToken ::= ContentInfo
type Response struct {
Status PKIStatusInfo
TimeStampToken protocol.ContentInfo `asn1:"optional"`
Expand Down Expand Up @@ -156,49 +158,49 @@ func (r Response) Info() (Info, error) {
return ParseInfo(sd.EncapContentInfo)
}

// PKIStatusInfo ::= SEQUENCE {
// status PKIStatus,
// statusString PKIFreeText OPTIONAL,
// failInfo PKIFailureInfo OPTIONAL }
// PKIStatusInfo ::= SEQUENCE {
// status PKIStatus,
// statusString PKIFreeText OPTIONAL,
// failInfo PKIFailureInfo OPTIONAL }
//
// PKIStatus ::= INTEGER {
// granted (0),
// -- when the PKIStatus contains the value zero a TimeStampToken, as
// requested, is present.
// grantedWithMods (1),
// -- when the PKIStatus contains the value one a TimeStampToken,
// with modifications, is present.
// rejection (2),
// waiting (3),
// revocationWarning (4),
// -- this message contains a warning that a revocation is
// -- imminent
// revocationNotification (5)
// -- notification that a revocation has occurred }
// PKIStatus ::= INTEGER {
// granted (0),
// -- when the PKIStatus contains the value zero a TimeStampToken, as
// requested, is present.
// grantedWithMods (1),
// -- when the PKIStatus contains the value one a TimeStampToken,
// with modifications, is present.
// rejection (2),
// waiting (3),
// revocationWarning (4),
// -- this message contains a warning that a revocation is
// -- imminent
// revocationNotification (5)
// -- notification that a revocation has occurred }
//
// -- When the TimeStampToken is not present
// -- failInfo indicates the reason why the
// -- time-stamp request was rejected and
// -- may be one of the following values.
//
// PKIFailureInfo ::= BIT STRING {
// badAlg (0),
// -- unrecognized or unsupported Algorithm Identifier
// badRequest (2),
// -- transaction not permitted or supported
// badDataFormat (5),
// -- the data submitted has the wrong format
// timeNotAvailable (14),
// -- the TSA's time source is not available
// unacceptedPolicy (15),
// -- the requested TSA policy is not supported by the TSA.
// unacceptedExtension (16),
// -- the requested extension is not supported by the TSA.
// addInfoNotAvailable (17)
// -- the additional information requested could not be understood
// -- or is not available
// systemFailure (25)
// -- the request cannot be handled due to system failure }
// PKIFailureInfo ::= BIT STRING {
// badAlg (0),
// -- unrecognized or unsupported Algorithm Identifier
// badRequest (2),
// -- transaction not permitted or supported
// badDataFormat (5),
// -- the data submitted has the wrong format
// timeNotAvailable (14),
// -- the TSA's time source is not available
// unacceptedPolicy (15),
// -- the requested TSA policy is not supported by the TSA.
// unacceptedExtension (16),
// -- the requested extension is not supported by the TSA.
// addInfoNotAvailable (17)
// -- the additional information requested could not be understood
// -- or is not available
// systemFailure (25)
// -- the request cannot be handled due to system failure }
type PKIStatusInfo struct {
Status int
StatusString PKIFreeText `asn1:"optional"`
Expand Down Expand Up @@ -267,25 +269,26 @@ func (ft PKIFreeText) Strings() ([]string, error) {
}

// Info is a TSTInfo
// TSTInfo ::= SEQUENCE {
// version INTEGER { v1(1) },
// policy TSAPolicyId,
// messageImprint MessageImprint,
// -- MUST have the same value as the similar field in
// -- TimeStampReq
// serialNumber INTEGER,
// -- Time-Stamping users MUST be ready to accommodate integers
// -- up to 160 bits.
// genTime GeneralizedTime,
// accuracy Accuracy OPTIONAL,
// ordering BOOLEAN DEFAULT FALSE,
// nonce INTEGER OPTIONAL,
// -- MUST be present if the similar field was present
// -- in TimeStampReq. In that case it MUST have the same value.
// tsa [0] GeneralName OPTIONAL,
// extensions [1] IMPLICIT Extensions OPTIONAL }
//
// TSAPolicyId ::= OBJECT IDENTIFIER
// TSTInfo ::= SEQUENCE {
// version INTEGER { v1(1) },
// policy TSAPolicyId,
// messageImprint MessageImprint,
// -- MUST have the same value as the similar field in
// -- TimeStampReq
// serialNumber INTEGER,
// -- Time-Stamping users MUST be ready to accommodate integers
// -- up to 160 bits.
// genTime GeneralizedTime,
// accuracy Accuracy OPTIONAL,
// ordering BOOLEAN DEFAULT FALSE,
// nonce INTEGER OPTIONAL,
// -- MUST be present if the similar field was present
// -- in TimeStampReq. In that case it MUST have the same value.
// tsa [0] GeneralName OPTIONAL,
// extensions [1] IMPLICIT Extensions OPTIONAL }
//
// TSAPolicyId ::= OBJECT IDENTIFIER
type Info struct {
Version int
Policy asn1.ObjectIdentifier
Expand Down Expand Up @@ -328,14 +331,14 @@ func ParseInfo(eci protocol.EncapsulatedContentInfo) (Info, error) {
// is before the specified time. For example, you might check that a signature
// was made *before* a certificate's not-after date.
func (i *Info) Before(t time.Time) bool {
return i.genTimeMax().Before(t)
return i.genTimeMax().Before(t) || i.genTimeMax().Equal(t)
}

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

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

// MessageImprint ::= SEQUENCE {
// hashAlgorithm AlgorithmIdentifier,
// hashedMessage OCTET STRING }
// MessageImprint ::= SEQUENCE {
// hashAlgorithm AlgorithmIdentifier,
// hashedMessage OCTET STRING }
type MessageImprint struct {
HashAlgorithm pkix.AlgorithmIdentifier
HashedMessage []byte
Expand Down Expand Up @@ -408,10 +411,10 @@ func (mi MessageImprint) Equal(other MessageImprint) bool {
return true
}

// Accuracy ::= SEQUENCE {
// seconds INTEGER OPTIONAL,
// millis [0] INTEGER (1..999) OPTIONAL,
// micros [1] INTEGER (1..999) OPTIONAL }
// Accuracy ::= SEQUENCE {
// seconds INTEGER OPTIONAL,
// millis [0] INTEGER (1..999) OPTIONAL,
// micros [1] INTEGER (1..999) OPTIONAL }
type Accuracy struct {
Seconds int `asn1:"optional"`
Millis int `asn1:"tag:0,optional"`
Expand Down
8 changes: 8 additions & 0 deletions ietf-cms/timestamp/timestamp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,14 @@ func TestTSTInfo(t *testing.T) {
t.Fatalf("expected gentimemax %s, got %s", expectedGenTimeMin.String(), inf.genTimeMin().String())
}

// Timestamp before/after should be inclusive
if !inf.Before(inf.genTimeMax()) {
t.Errorf("before timestamp should be inclusive")
}
if !inf.After(inf.genTimeMin()) {
t.Errorf("after timestamp should be inclusive")
}

expectedOrdering := false
if inf.Ordering != expectedOrdering {
t.Fatalf("expected ordering %t, got %t", expectedOrdering, inf.Ordering)
Expand Down

0 comments on commit dab6bdb

Please sign in to comment.