Skip to content

Commit a1b00e3

Browse files
committed
Fix FailureInfo and add RawToken
1 parent 5ff4365 commit a1b00e3

File tree

4 files changed

+111
-25
lines changed

4 files changed

+111
-25
lines changed

Diff for: borrowed.go

+22-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"encoding/asn1"
66
)
77

8-
// TODO(vanbroup): content of this file is taken from "golang.org/x/crypto/ocsp"
8+
// TODO(vanbroup): taken from "golang.org/x/crypto/ocsp"
99
// use directly from crypto/x509 when exported as suggested below.
1010

1111
var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{
@@ -33,3 +33,24 @@ func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier {
3333
}
3434
return nil
3535
}
36+
37+
// TODO(vanbroup): taken from golang.org/x/crypto/x509
38+
// asn1BitLength returns the bit-length of bitString by considering the
39+
// most-significant bit in a byte to be the "first" bit. This convention
40+
// matches ASN.1, but differs from almost everything else.
41+
func asn1BitLength(bitString []byte) int {
42+
bitLen := len(bitString) * 8
43+
44+
for i := range bitString {
45+
b := bitString[len(bitString)-i-1]
46+
47+
for bit := uint(0); bit < 8; bit++ {
48+
if (b>>bit)&1 == 1 {
49+
return bitLen
50+
}
51+
bitLen--
52+
}
53+
}
54+
55+
return 0
56+
}

Diff for: rfc3161_struct.go

+15-2
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,24 @@ type response struct {
3030
}
3131

3232
type pkiStatusInfo struct {
33-
Status PKIStatus
34-
StatusString string `asn1:"optional"`
33+
Status Status
34+
StatusString []string `asn1:"optional,utf8"`
3535
FailInfo asn1.BitString `asn1:"optional"`
3636
}
3737

38+
func (s pkiStatusInfo) FailureInfo() FailureInfo {
39+
fi := []FailureInfo{BadAlgorithm, BadRequest, BadDataFormat, TimeNotAvailable,
40+
UnacceptedPolicy, UnacceptedExtension, AddInfoNotAvailable, SystemFailure}
41+
42+
for _, f := range fi {
43+
if s.FailInfo.At(int(f)) != 0 {
44+
return f
45+
}
46+
}
47+
48+
return UnkownFailureInfo
49+
}
50+
3851
// eContent within SignedData is TSTInfo
3952
type tstInfo struct {
4053
Version int

Diff for: timestamp.go

+48-22
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"io"
1313
"math/big"
1414
"strconv"
15+
"strings"
1516
"time"
1617

1718
"github.com/digitorus/pkcs7"
@@ -22,6 +23,8 @@ import (
2223
type FailureInfo int
2324

2425
const (
26+
// UnkownFailureInfo mean that no known failure info was provided
27+
UnkownFailureInfo FailureInfo = -1
2528
// BadAlgorithm defines an unrecognized or unsupported Algorithm Identifier
2629
BadAlgorithm FailureInfo = 0
2730
// BadRequest indicates that the transaction not permitted or supported
@@ -63,35 +66,32 @@ func (f FailureInfo) String() string {
6366
case SystemFailure:
6467
return "the request cannot be handled due to system failure"
6568
default:
66-
return "unknown failure: " + strconv.Itoa(int(f))
69+
return "unknown failure"
6770
}
6871
}
6972

70-
// PKIStatus contains the status of an Time-Stamp request. See
73+
// Status contains the status of an Time-Stamp request. See
7174
// https://tools.ietf.org/html/rfc3161#section-2.4.2
72-
type PKIStatus int
75+
type Status int
7376

7477
const (
75-
// Granted PKIStatus contains the value zero a TimeStampToken, as requested, is present.
76-
Granted PKIStatus = 0
77-
78-
// GrantedWithMods PKIStatus contains the value one a TimeStampToken, with modifications, is present.
79-
GrantedWithMods PKIStatus = 1
80-
78+
// Granted PKIStatus contains the value zero a TimeStampToken, as requested,
79+
// is present.
80+
Granted Status = 0
81+
// GrantedWithMods PKIStatus contains the value one a TimeStampToken, with
82+
// modifications, is present.
83+
GrantedWithMods Status = 1
8184
// Rejection PKIStatus
82-
Rejection PKIStatus = 2
83-
85+
Rejection Status = 2
8486
// Waiting PKIStatus
85-
Waiting PKIStatus = 3
86-
87+
Waiting Status = 3
8788
// RevocationWarning PKIStatus
88-
RevocationWarning PKIStatus = 4
89-
89+
RevocationWarning Status = 4
9090
// RevocationNotification PKIStatus
91-
RevocationNotification PKIStatus = 5
91+
RevocationNotification Status = 5
9292
)
9393

94-
func (s PKIStatus) String() string {
94+
func (s Status) String() string {
9595
switch s {
9696
case Granted:
9797
return "the request is granted"
@@ -215,6 +215,9 @@ func (req *Request) Marshal() ([]byte, error) {
215215
// Timestamp represents an Time-Stamp. See:
216216
// https://tools.ietf.org/html/rfc3161#section-2.4.1
217217
type Timestamp struct {
218+
// Timestamp token part of raw ASN.1 DER content.
219+
RawToken []byte
220+
218221
HashAlgorithm crypto.Hash
219222
HashedMessage []byte
220223

@@ -263,8 +266,15 @@ func ParseResponse(bytes []byte) (*Timestamp, error) {
263266
}
264267

265268
if resp.Status.Status > 0 {
266-
return nil, ParseError(fmt.Sprintf("%s: %s",
267-
FailureInfo(int(resp.Status.FailInfo.Bytes[0])).String(), resp.Status.StatusString))
269+
var fis string
270+
fi := resp.Status.FailureInfo()
271+
if fi != UnkownFailureInfo {
272+
fis = fi.String()
273+
}
274+
return nil, fmt.Errorf("%s: %s (%v)",
275+
resp.Status.Status.String(),
276+
strings.Join(resp.Status.StatusString, ","),
277+
fis)
268278
}
269279

270280
if len(resp.TimeStampToken.Bytes) == 0 {
@@ -305,6 +315,7 @@ func Parse(bytes []byte) (*Timestamp, error) {
305315
}
306316

307317
ret := &Timestamp{
318+
RawToken: bytes,
308319
HashedMessage: inf.MessageImprint.HashedMessage,
309320
Time: inf.Time,
310321
Accuracy: time.Duration((time.Second * time.Duration(inf.Accuracy.Seconds)) +
@@ -427,12 +438,15 @@ func (t *Timestamp) CreateResponse(signingCert *x509.Certificate, priv crypto.Si
427438
return tspResponseBytes, nil
428439
}
429440

430-
//CreateErrorResponse is used to create response other than granted and granted with mod status
431-
func CreateErrorResponse(pkiStatus PKIStatus, pkiFailureInfo FailureInfo) ([]byte, error) {
441+
// CreateErrorResponse is used to create response other than granted and granted with mod status
442+
func CreateErrorResponse(pkiStatus Status, pkiFailureInfo FailureInfo) ([]byte, error) {
443+
var bs asn1.BitString
444+
setFlag(&bs, int(pkiFailureInfo))
445+
432446
timestampRes := response{
433447
Status: pkiStatusInfo{
434448
Status: pkiStatus,
435-
FailInfo: asn1.BitString{Bytes: []byte{byte(pkiFailureInfo)}, BitLength: 8},
449+
FailInfo: bs,
436450
},
437451
}
438452
tspResponseBytes, err := asn1.Marshal(timestampRes)
@@ -442,6 +456,18 @@ func CreateErrorResponse(pkiStatus PKIStatus, pkiFailureInfo FailureInfo) ([]byt
442456
return tspResponseBytes, nil
443457
}
444458

459+
func setFlag(bs *asn1.BitString, i int) {
460+
for l := len(bs.Bytes); l < 4; l++ {
461+
(*bs).Bytes = append((*bs).Bytes, byte(0))
462+
(*bs).BitLength = len((*bs).Bytes) * 8
463+
}
464+
b := i / 8
465+
p := uint(7 - (i - 8*b))
466+
(*bs).Bytes[b] = (*bs).Bytes[b] | (1 << p)
467+
bs.BitLength = asn1BitLength(bs.Bytes)
468+
bs.Bytes = bs.Bytes[0 : (bs.BitLength/8)+1]
469+
}
470+
445471
func getMessageImprint(hashAlgorithm crypto.Hash, hashedMessage []byte) messageImprint {
446472
messageImprint := messageImprint{
447473
HashAlgorithm: pkix.AlgorithmIdentifier{

0 commit comments

Comments
 (0)