Skip to content

Commit d834616

Browse files
committed
Add verification errors to output of VerifyTimestampAuthority
Signed-off-by: Cody Soyland <[email protected]>
1 parent 6207d62 commit d834616

File tree

3 files changed

+29
-20
lines changed

3 files changed

+29
-20
lines changed

pkg/verify/signed_entity.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -814,16 +814,16 @@ func (v *SignedEntityVerifier) VerifyObserverTimestamps(entity SignedEntity, log
814814
}
815815

816816
if v.config.requireObserverTimestamps {
817-
verifiedSignedTimestamps, err := VerifyTimestampAuthority(entity, v.trustedMaterial)
817+
verifiedSignedTimestamps, verificationErrors, err := VerifyTimestampAuthority(entity, v.trustedMaterial)
818818
if err != nil {
819-
return nil, err
819+
return nil, fmt.Errorf("failed to verify signed timestamps: %w", err)
820820
}
821821

822822
// check threshold for both RFC3161 and log timestamps
823823
tsCount := len(verifiedSignedTimestamps) + len(logTimestamps)
824824
if tsCount < v.config.observerTimestampThreshold {
825-
return nil, fmt.Errorf("threshold not met for verified signed & log entry integrated timestamps: %d < %d",
826-
tsCount, v.config.observerTimestampThreshold)
825+
return nil, fmt.Errorf("threshold not met for verified signed & log entry integrated timestamps: %d < %d; error: %w",
826+
tsCount, v.config.observerTimestampThreshold, errors.Join(verificationErrors...))
827827
}
828828

829829
// append all timestamps

pkg/verify/tsa.go

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,39 +25,40 @@ const maxAllowedTimestamps = 32
2525

2626
// VerifyTimestampAuthority verifies that the given entity has been timestamped
2727
// by a trusted timestamp authority and that the timestamp is valid.
28-
func VerifyTimestampAuthority(entity SignedEntity, trustedMaterial root.TrustedMaterial) ([]*root.Timestamp, error) { //nolint:revive
28+
func VerifyTimestampAuthority(entity SignedEntity, trustedMaterial root.TrustedMaterial) ([]*root.Timestamp, []error, error) { //nolint:revive
2929
signedTimestamps, err := entity.Timestamps()
3030
if err != nil {
31-
return nil, err
31+
return nil, nil, err
3232
}
3333

3434
// limit the number of timestamps to prevent DoS
3535
if len(signedTimestamps) > maxAllowedTimestamps {
36-
return nil, fmt.Errorf("too many signed timestamps: %d > %d", len(signedTimestamps), maxAllowedTimestamps)
36+
return nil, nil, fmt.Errorf("too many signed timestamps: %d > %d", len(signedTimestamps), maxAllowedTimestamps)
3737
}
3838
sigContent, err := entity.SignatureContent()
3939
if err != nil {
40-
return nil, err
40+
return nil, nil, err
4141
}
4242

4343
signatureBytes := sigContent.Signature()
4444

4545
verifiedTimestamps := []*root.Timestamp{}
46+
var verificationErrors []error
4647
for _, timestamp := range signedTimestamps {
4748
verifiedSignedTimestamp, err := verifySignedTimestamp(timestamp, signatureBytes, trustedMaterial)
4849
if err != nil {
50+
verificationErrors = append(verificationErrors, err)
4951
continue
5052
}
5153
if isDuplicateTSA(verifiedTimestamps, verifiedSignedTimestamp) {
52-
// TODO: add below error to `errs` when #325 is merged, and continue
53-
// (https://github.com/sigstore/sigstore-go/issues/325)
54-
return verifiedTimestamps, fmt.Errorf("duplicate timestamps from the same authority, ignoring %s", verifiedSignedTimestamp.URI)
54+
verificationErrors = append(verificationErrors, fmt.Errorf("duplicate timestamps from the same authority, ignoring %s", verifiedSignedTimestamp.URI))
55+
continue
5556
}
5657

5758
verifiedTimestamps = append(verifiedTimestamps, verifiedSignedTimestamp)
5859
}
5960

60-
return verifiedTimestamps, nil
61+
return verifiedTimestamps, verificationErrors, err
6162
}
6263

6364
// isDuplicateTSA checks if the given verified signed timestamp is a duplicate
@@ -79,26 +80,29 @@ func isDuplicateTSA(verifiedTimestamps []*root.Timestamp, verifiedSignedTimestam
7980
// The threshold parameter is the number of unique timestamps that must be
8081
// verified.
8182
func VerifyTimestampAuthorityWithThreshold(entity SignedEntity, trustedMaterial root.TrustedMaterial, threshold int) ([]*root.Timestamp, error) { //nolint:revive
82-
verifiedTimestamps, err := VerifyTimestampAuthority(entity, trustedMaterial)
83+
verifiedTimestamps, verificationErrors, err := VerifyTimestampAuthority(entity, trustedMaterial)
8384
if err != nil {
8485
return nil, err
8586
}
8687
if len(verifiedTimestamps) < threshold {
87-
return nil, fmt.Errorf("threshold not met for verified signed timestamps: %d < %d", len(verifiedTimestamps), threshold)
88+
return nil, fmt.Errorf("threshold not met for verified signed timestamps: %d < %d; error: %w", len(verifiedTimestamps), threshold, errors.Join(verificationErrors...))
8889
}
8990
return verifiedTimestamps, nil
9091
}
9192

9293
func verifySignedTimestamp(signedTimestamp []byte, signatureBytes []byte, trustedMaterial root.TrustedMaterial) (*root.Timestamp, error) {
9394
timestampAuthorities := trustedMaterial.TimestampingAuthorities()
9495

96+
var errs []error
97+
9598
// Iterate through TSA certificate authorities to find one that verifies
9699
for _, tsa := range timestampAuthorities {
97100
ts, err := tsa.Verify(signedTimestamp, signatureBytes)
98101
if err == nil {
99102
return ts, nil
100103
}
104+
errs = append(errs, err)
101105
}
102106

103-
return nil, errors.New("unable to verify signed timestamps")
107+
return nil, fmt.Errorf("unable to verify signed timestamps: %w", errors.Join(errs...))
104108
}

pkg/verify/tsa_test.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,17 @@ func TestTimestampAuthorityVerifierWithoutThreshold(t *testing.T) {
6363
var ts []*root.Timestamp
6464

6565
// expect one verified timestamp
66-
ts, err = verify.VerifyTimestampAuthority(entity, virtualSigstore)
66+
ts, verificationErrors, err := verify.VerifyTimestampAuthority(entity, virtualSigstore)
6767
assert.NoError(t, err)
68+
assert.Empty(t, verificationErrors)
6869
assert.Len(t, ts, 1)
6970

70-
// no failure, but also no verified timestamps
71-
ts, err = verify.VerifyTimestampAuthority(entity, virtualSigstore2)
71+
// wrong instance; expect no verified timestamps
72+
ts, verificationErrors, err = verify.VerifyTimestampAuthority(entity, virtualSigstore2)
7273
assert.NoError(t, err)
7374
assert.Empty(t, ts)
75+
assert.Len(t, verificationErrors, 1)
76+
assert.ErrorContains(t, verificationErrors[0], "ECDSA verification failure")
7477
}
7578

7679
type oneTrustedOneUntrustedTimestampEntity struct {
@@ -112,8 +115,10 @@ func TestDuplicateTimestamps(t *testing.T) {
112115
entity, err := virtualSigstore.Attest("[email protected]", "issuer", []byte("statement"))
113116
assert.NoError(t, err)
114117

115-
_, err = verify.VerifyTimestampAuthority(&dupTimestampEntity{entity}, virtualSigstore)
116-
assert.ErrorContains(t, err, "duplicate timestamps from the same authority, ignoring https://virtual.tsa.sigstore.dev")
118+
timestamps, verificationErrors, err := verify.VerifyTimestampAuthority(&dupTimestampEntity{entity}, virtualSigstore)
119+
assert.ErrorContains(t, verificationErrors[0], "duplicate timestamps from the same authority, ignoring https://virtual.tsa.sigstore.dev")
120+
assert.NoError(t, err)
121+
assert.Len(t, timestamps, 1)
117122
}
118123

119124
type badTSASignatureEntity struct {

0 commit comments

Comments
 (0)