File: 0005-fix-enable-timestamping-cert-chain-revocation-check-.patch

package info (click to toggle)
golang-github-notaryproject-notation-go 1.2.1-5
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 4,724 kB
  • sloc: makefile: 21
file content (174 lines) | stat: -rw-r--r-- 6,528 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
From: Patrick Zheng <patrickzheng@microsoft.com>
Date: Mon, 2 Dec 2024 08:30:56 +0800
Subject: fix: enable timestamping cert chain revocation check during signing
 (#482)

Signed-off-by: Patrick Zheng <patrickzheng@microsoft.com>
---
 example_signWithTimestmap_test.go | 17 ++++++++++++++---
 notation.go                       |  6 ++++++
 signer/signer.go                  | 22 +++++++++++++---------
 signer/signer_test.go             | 23 +++++++++++++++++++++++
 4 files changed, 56 insertions(+), 12 deletions(-)

diff --git a/example_signWithTimestmap_test.go b/example_signWithTimestmap_test.go
index 8e0ebe5..ef4eeb4 100644
--- a/example_signWithTimestmap_test.go
+++ b/example_signWithTimestmap_test.go
@@ -21,6 +21,8 @@ import (
 
 	"oras.land/oras-go/v2/registry/remote"
 
+	"github.com/notaryproject/notation-core-go/revocation"
+	"github.com/notaryproject/notation-core-go/revocation/purpose"
 	"github.com/notaryproject/notation-core-go/testhelper"
 	"github.com/notaryproject/notation-go"
 	"github.com/notaryproject/notation-go/registry"
@@ -77,12 +79,21 @@ func Example_signWithTimestamp() {
 	tsaRootCAs := x509.NewCertPool()
 	tsaRootCAs.AddCert(tsaRootCert)
 
+	// enable timestamping certificate chain revocation check
+	tsaRevocationValidator, err := revocation.NewWithOptions(revocation.Options{
+		CertChainPurpose: purpose.Timestamping,
+	})
+	if err != nil {
+		panic(err) // Handle error
+	}
+
 	// exampleSignOptions is an example of notation.SignOptions.
 	exampleSignOptions := notation.SignOptions{
 		SignerSignOptions: notation.SignerSignOptions{
-			SignatureMediaType: exampleSignatureMediaType,
-			Timestamper:        httpTimestamper,
-			TSARootCAs:         tsaRootCAs,
+			SignatureMediaType:     exampleSignatureMediaType,
+			Timestamper:            httpTimestamper,
+			TSARootCAs:             tsaRootCAs,
+			TSARevocationValidator: tsaRevocationValidator,
 		},
 		ArtifactReference: exampleArtifactReference,
 	}
diff --git a/notation.go b/notation.go
index d64fd2c..bb051d1 100644
--- a/notation.go
+++ b/notation.go
@@ -29,6 +29,7 @@ import (
 	orasRegistry "oras.land/oras-go/v2/registry"
 	"oras.land/oras-go/v2/registry/remote"
 
+	"github.com/notaryproject/notation-core-go/revocation"
 	"github.com/notaryproject/notation-core-go/signature"
 	"github.com/notaryproject/notation-core-go/signature/cose"
 	"github.com/notaryproject/notation-core-go/signature/jws"
@@ -67,6 +68,11 @@ type SignerSignOptions struct {
 
 	// TSARootCAs is the cert pool holding caller's TSA trust anchor
 	TSARootCAs *x509.CertPool
+
+	// TSARevocationValidator is used for validating revocation status of
+	// timestamping certificate chain with context during signing.
+	// When present, only used when timestamping is performed.
+	TSARevocationValidator revocation.Validator
 }
 
 // Signer is a generic interface for signing an OCI artifact.
diff --git a/signer/signer.go b/signer/signer.go
index 40d23ec..ae77f8c 100644
--- a/signer/signer.go
+++ b/signer/signer.go
@@ -107,7 +107,6 @@ func (s *GenericSigner) Sign(ctx context.Context, desc ocispec.Descriptor, opts
 	if err != nil {
 		return nil, nil, fmt.Errorf("envelope payload can't be marshalled: %w", err)
 	}
-
 	var signingAgentId string
 	if opts.SigningAgent != "" {
 		signingAgentId = opts.SigningAgent
@@ -125,12 +124,13 @@ func (s *GenericSigner) Sign(ctx context.Context, desc ocispec.Descriptor, opts
 			ContentType: envelope.MediaTypePayloadV1,
 			Content:     payloadBytes,
 		},
-		Signer:        s.signer,
-		SigningTime:   time.Now(),
-		SigningScheme: signature.SigningSchemeX509,
-		SigningAgent:  signingAgentId,
-		Timestamper:   opts.Timestamper,
-		TSARootCAs:    opts.TSARootCAs,
+		Signer:                 s.signer,
+		SigningTime:            time.Now(),
+		SigningScheme:          signature.SigningSchemeX509,
+		SigningAgent:           signingAgentId,
+		Timestamper:            opts.Timestamper,
+		TSARootCAs:             opts.TSARootCAs,
+		TSARevocationValidator: opts.TSARevocationValidator,
 	}
 
 	// Add expiry only if ExpiryDuration is not zero
@@ -144,6 +144,12 @@ func (s *GenericSigner) Sign(ctx context.Context, desc ocispec.Descriptor, opts
 	logger.Debugf("  Expiry:        %v", signReq.Expiry)
 	logger.Debugf("  SigningScheme: %v", signReq.SigningScheme)
 	logger.Debugf("  SigningAgent:  %v", signReq.SigningAgent)
+	if signReq.Timestamper != nil {
+		logger.Debug("Enabled timestamping")
+		if signReq.TSARevocationValidator != nil {
+			logger.Debug("Enabled timestamping certificate chain revocation check")
+		}
+	}
 
 	// Add ctx to the SignRequest
 	signReq = signReq.WithContext(ctx)
@@ -153,12 +159,10 @@ func (s *GenericSigner) Sign(ctx context.Context, desc ocispec.Descriptor, opts
 	if err != nil {
 		return nil, nil, err
 	}
-
 	sig, err := sigEnv.Sign(signReq)
 	if err != nil {
 		return nil, nil, err
 	}
-
 	envContent, err := sigEnv.Verify()
 	if err != nil {
 		return nil, nil, fmt.Errorf("generated signature failed verification: %v", err)
diff --git a/signer/signer_test.go b/signer/signer_test.go
index 80fc4af..2e9a844 100644
--- a/signer/signer_test.go
+++ b/signer/signer_test.go
@@ -31,6 +31,8 @@ import (
 	"testing"
 	"time"
 
+	"github.com/notaryproject/notation-core-go/revocation"
+	"github.com/notaryproject/notation-core-go/revocation/purpose"
 	"github.com/notaryproject/notation-core-go/signature"
 	_ "github.com/notaryproject/notation-core-go/signature/cose"
 	_ "github.com/notaryproject/notation-core-go/signature/jws"
@@ -259,6 +261,27 @@ t.Skip("Disabled because it tries to access the network")
 	if err == nil || err.Error() != expectedErrMsg {
 		t.Fatalf("expected %s, but got %s", expectedErrMsg, err)
 	}
+
+	// timestamping with unknown authority
+	desc, sOpts = generateSigningContent()
+	sOpts.SignatureMediaType = envelopeType
+	sOpts.Timestamper, err = tspclient.NewHTTPTimestamper(nil, rfc3161URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	sOpts.TSARootCAs = x509.NewCertPool()
+	tsaRevocationValidator, err := revocation.NewWithOptions(revocation.Options{
+		CertChainPurpose: purpose.Timestamping,
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+	sOpts.TSARevocationValidator = tsaRevocationValidator
+	_, _, err = s.Sign(ctx, desc, sOpts)
+	expectedErrMsg = "timestamp: failed to verify signed token: cms verification failure: x509: certificate signed by unknown authority"
+	if err == nil || err.Error() != expectedErrMsg {
+		t.Fatalf("expected %s, but got %s", expectedErrMsg, err)
+	}
 }
 
 func TestSignWithoutExpiry(t *testing.T) {