Skip to content

Commit

Permalink
Include URI for CA verified timestamps
Browse files Browse the repository at this point in the history
Signed-off-by: Colleen Murphy <[email protected]>
  • Loading branch information
cmurphy committed Sep 6, 2024
1 parent 01e70e8 commit a912439
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 33 deletions.
4 changes: 3 additions & 1 deletion pkg/root/trusted_root.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,9 @@ func ParseCertificateAuthority(certAuthority *prototrustroot.CertificateAuthorit
}
}

// TODO: Should we inspect/enforce ca.Subject and ca.Uri?
certificateAuthority.URI = certAuthority.Uri

// TODO: Should we inspect/enforce ca.Subject?
// TODO: Handle validity period (ca.ValidFor)

return certificateAuthority, nil
Expand Down
6 changes: 3 additions & 3 deletions pkg/verify/signed_entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ func (v *SignedEntityVerifier) VerifyTransparencyLogInclusion(entity SignedEntit
}

for _, vts := range verifiedTlogTimestamps {
verifiedTimestamps = append(verifiedTimestamps, TimestampVerificationResult{Type: "Tlog", URI: "TODO", Timestamp: vts})
verifiedTimestamps = append(verifiedTimestamps, TimestampVerificationResult{Type: "Tlog", URI: vts.URI, Timestamp: vts.Time})
}
}

Expand All @@ -692,7 +692,7 @@ func (v *SignedEntityVerifier) VerifyObserverTimestamps(entity SignedEntity, log
return nil, err
}
for _, vts := range verifiedSignedTimestamps {
verifiedTimestamps = append(verifiedTimestamps, TimestampVerificationResult{Type: "TimestampAuthority", URI: "TODO", Timestamp: vts})
verifiedTimestamps = append(verifiedTimestamps, TimestampVerificationResult{Type: "TimestampAuthority", URI: vts.URI, Timestamp: vts.Time})
}
}

Expand All @@ -719,7 +719,7 @@ func (v *SignedEntityVerifier) VerifyObserverTimestamps(entity SignedEntity, log
// append all timestamps
verifiedTimestamps = append(verifiedTimestamps, logTimestamps...)
for _, vts := range verifiedSignedTimestamps {
verifiedTimestamps = append(verifiedTimestamps, TimestampVerificationResult{Type: "TimestampAuthority", URI: "TODO", Timestamp: vts})
verifiedTimestamps = append(verifiedTimestamps, TimestampVerificationResult{Type: "TimestampAuthority", URI: vts.URI, Timestamp: vts.Time})
}
}

Expand Down
4 changes: 4 additions & 0 deletions pkg/verify/signed_entity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ func TestEntitySignedByPublicGoodWithTlogVerifiesSuccessfully(t *testing.T) {
assert.NotNil(t, res.Signature.Certificate)
assert.Equal(t, "https://github.com/sigstore/sigstore-js/.github/workflows/release.yml@refs/heads/main", res.Signature.Certificate.SubjectAlternativeName)
assert.NotEmpty(t, res.VerifiedTimestamps)
for _, vts := range res.VerifiedTimestamps[1:] { // TODO: URI for TLog is still "TODO"
assert.NotEmpty(t, vts.Timestamp)
assert.Equal(t, "", vts.URI)
}

// verifies with integrated timestamp threshold too
v, err = verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithIntegratedTimestamps(1))
Expand Down
34 changes: 13 additions & 21 deletions pkg/verify/tlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"encoding/hex"
"errors"
"fmt"
"time"

rekorClient "github.com/sigstore/rekor/pkg/client"
rekorGeneratedClient "github.com/sigstore/rekor/pkg/generated/client"
Expand All @@ -43,7 +42,7 @@ const maxAllowedTlogEntries = 32
// that must be verified.
//
// If online is true, the log entry is verified against the Rekor server.
func VerifyArtifactTransparencyLog(entity SignedEntity, trustedMaterial root.TrustedMaterial, logThreshold int, trustIntegratedTime, online bool) ([]time.Time, error) { //nolint:revive
func VerifyArtifactTransparencyLog(entity SignedEntity, trustedMaterial root.TrustedMaterial, logThreshold int, trustIntegratedTime, online bool) ([]Timestamp, error) { //nolint:revive
entries, err := entity.TlogEntries()
if err != nil {
return nil, err
Expand Down Expand Up @@ -75,7 +74,7 @@ func VerifyArtifactTransparencyLog(entity SignedEntity, trustedMaterial root.Tru
return nil, err
}

verifiedTimestamps := []time.Time{}
verifiedTimestamps := []Timestamp{}
logEntriesVerified := 0

for _, entry := range entries {
Expand All @@ -84,28 +83,29 @@ func VerifyArtifactTransparencyLog(entity SignedEntity, trustedMaterial root.Tru
return nil, err
}

rekorLogs := trustedMaterial.RekorLogs()
keyID := entry.LogKeyID()
hex64Key := hex.EncodeToString([]byte(keyID))
tlogVerifier, ok := trustedMaterial.RekorLogs()[hex64Key]
if !ok {
// skip entries the trust root cannot verify
continue
}
if !online {
if !entry.HasInclusionPromise() && !entry.HasInclusionProof() {
return nil, fmt.Errorf("entry must contain an inclusion proof and/or promise")
}
if entry.HasInclusionPromise() {
err = tlog.VerifySET(entry, trustedMaterial.RekorLogs())
err = tlog.VerifySET(entry, rekorLogs)
if err != nil {
// skip entries the trust root cannot verify
continue
}
if trustIntegratedTime {
verifiedTimestamps = append(verifiedTimestamps, entry.IntegratedTime())
verifiedTimestamps = append(verifiedTimestamps, Timestamp{Time: entry.IntegratedTime(), URI: tlogVerifier.BaseURL})
}
}
if entity.HasInclusionProof() {

Check failure on line 108 in pkg/verify/tlog.go

View workflow job for this annotation

GitHub Actions / lint

unnecessary leading newline (whitespace)
keyID := entry.LogKeyID()
hex64Key := hex.EncodeToString([]byte(keyID))
tlogVerifier, ok := trustedMaterial.RekorLogs()[hex64Key]
if !ok {
// skip entries the trust root cannot verify
continue
}

verifier, err := getVerifier(tlogVerifier.PublicKey, tlogVerifier.SignatureHashFunc)
if err != nil {
Expand All @@ -119,14 +119,6 @@ func VerifyArtifactTransparencyLog(entity SignedEntity, trustedMaterial root.Tru
// DO NOT use timestamp with only an inclusion proof, because it is not signed metadata
}
} else {
keyID := entry.LogKeyID()
hex64Key := hex.EncodeToString([]byte(keyID))
tlogVerifier, ok := trustedMaterial.RekorLogs()[hex64Key]
if !ok {
// skip entries the trust root cannot verify
continue
}

client, err := getRekorClient(tlogVerifier.BaseURL)
if err != nil {
return nil, err
Expand Down Expand Up @@ -160,7 +152,7 @@ func VerifyArtifactTransparencyLog(entity SignedEntity, trustedMaterial root.Tru
}
}
if trustIntegratedTime {
verifiedTimestamps = append(verifiedTimestamps, entry.IntegratedTime())
verifiedTimestamps = append(verifiedTimestamps, Timestamp{Time: entry.IntegratedTime(), URI: tlogVerifier.BaseURL})
}
}
// Ensure entry signature matches signature from bundle
Expand Down
2 changes: 1 addition & 1 deletion pkg/verify/tlog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestTlogVerifier(t *testing.T) {
entity, err := virtualSigstore.Attest("[email protected]", "issuer", statement)
assert.NoError(t, err)

var ts []time.Time
var ts []verify.Timestamp
ts, err = verify.VerifyArtifactTransparencyLog(entity, virtualSigstore, 1, true, false)
assert.NoError(t, err)
// 1 verified timestamp
Expand Down
17 changes: 11 additions & 6 deletions pkg/verify/tsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,14 @@ import (

const maxAllowedTimestamps = 32

type Timestamp struct {
Time time.Time
URI string
}

// VerifyTimestampAuthority verifies that the given entity has been timestamped
// by a trusted timestamp authority and that the timestamp is valid.
func VerifyTimestampAuthority(entity SignedEntity, trustedMaterial root.TrustedMaterial) ([]time.Time, error) { //nolint:revive
func VerifyTimestampAuthority(entity SignedEntity, trustedMaterial root.TrustedMaterial) ([]Timestamp, error) { //nolint:revive
signedTimestamps, err := entity.Timestamps()
if err != nil {
return nil, err
Expand Down Expand Up @@ -62,7 +67,7 @@ func VerifyTimestampAuthority(entity SignedEntity, trustedMaterial root.TrustedM
return nil, err
}

verifiedTimestamps := []time.Time{}
verifiedTimestamps := []Timestamp{}
for _, timestamp := range signedTimestamps {
verifiedSignedTimestamp, err := verifySignedTimestamp(timestamp, signatureBytes, trustedMaterial, verificationContent)

Expand All @@ -82,7 +87,7 @@ func VerifyTimestampAuthority(entity SignedEntity, trustedMaterial root.TrustedM
//
// The threshold parameter is the number of unique timestamps that must be
// verified.
func VerifyTimestampAuthorityWithThreshold(entity SignedEntity, trustedMaterial root.TrustedMaterial, threshold int) ([]time.Time, error) { //nolint:revive
func VerifyTimestampAuthorityWithThreshold(entity SignedEntity, trustedMaterial root.TrustedMaterial, threshold int) ([]Timestamp, error) { //nolint:revive
verifiedTimestamps, err := VerifyTimestampAuthority(entity, trustedMaterial)
if err != nil {
return nil, err
Expand All @@ -93,7 +98,7 @@ func VerifyTimestampAuthorityWithThreshold(entity SignedEntity, trustedMaterial
return verifiedTimestamps, nil
}

func verifySignedTimestamp(signedTimestamp []byte, dsseSignatureBytes []byte, trustedMaterial root.TrustedMaterial, verificationContent VerificationContent) (time.Time, error) {
func verifySignedTimestamp(signedTimestamp []byte, dsseSignatureBytes []byte, trustedMaterial root.TrustedMaterial, verificationContent VerificationContent) (Timestamp, error) {
certAuthorities := trustedMaterial.TimestampingAuthorities()

// Iterate through TSA certificate authorities to find one that verifies
Expand Down Expand Up @@ -124,8 +129,8 @@ func verifySignedTimestamp(signedTimestamp []byte, dsseSignatureBytes []byte, tr
}

// All above verification successful, so return nil
return timestamp.Time, nil
return Timestamp{Time: timestamp.Time, URI: ca.URI}, nil
}

return time.Time{}, errors.New("unable to verify signed timestamps")
return Timestamp{}, errors.New("unable to verify signed timestamps")
}
2 changes: 1 addition & 1 deletion pkg/verify/tsa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func TestTimestampAuthorityVerifierWithoutThreshold(t *testing.T) {
virtualSigstore2, err := ca.NewVirtualSigstore()
assert.NoError(t, err)

var ts []time.Time
var ts []verify.Timestamp

// expect one verified timestamp
ts, err = verify.VerifyTimestampAuthority(entity, virtualSigstore)
Expand Down

0 comments on commit a912439

Please sign in to comment.