1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package fuzz
17
18 import (
19 "archive/zip"
20 "bytes"
21 "errors"
22 "fmt"
23 "net/url"
24 "os"
25 "path/filepath"
26
27 "go.uber.org/zap"
28 "go.uber.org/zap/zapcore"
29
30 fuzz "github.com/AdamKorcz/go-fuzz-headers-1"
31
32 "github.com/sigstore/rekor/pkg/log"
33 "github.com/sigstore/rekor/pkg/types"
34 )
35
36
37 func setArtifactHash(ff *fuzz.ConsumeFuzzer, props *types.ArtifactProperties) error {
38 artifactHash, err := ff.GetString()
39 if err != nil {
40 return err
41 }
42 props.ArtifactHash = artifactHash
43 return nil
44 }
45
46
47 func createAbsFile(_ *fuzz.ConsumeFuzzer, fileName string, fileContents []byte) (*url.URL, error) {
48 file, err := os.Create(fileName)
49 if err != nil {
50 return nil, err
51 }
52 defer file.Close()
53
54 filePath, err := filepath.Abs(fileName)
55 if err != nil {
56 return nil, err
57 }
58 fileURL, err := url.Parse(filePath)
59 if err != nil {
60 return nil, err
61 }
62 _, err = file.Write(fileContents)
63 if err != nil {
64 return nil, err
65 }
66 return fileURL, err
67 }
68
69
70
71 func setSignatureFields(ff *fuzz.ConsumeFuzzer, props *types.ArtifactProperties) (func(), error) {
72 cleanup := func() {}
73 shouldSetSignatureBytes, err := ff.GetBool()
74 if err != nil {
75 return cleanup, err
76 }
77
78 signatureBytes, err := ff.GetBytes()
79 if err != nil {
80 return cleanup, err
81 }
82
83 if shouldSetSignatureBytes {
84 props.SignatureBytes = signatureBytes
85 return cleanup, nil
86 }
87 signatureURL, err := createAbsFile(ff, "SignatureFile", signatureBytes)
88
89 if err != nil {
90 os.Remove("SignatureFile")
91 return cleanup, err
92 }
93 props.SignaturePath = signatureURL
94 return func() {
95 os.Remove("SignatureFile")
96 }, nil
97
98 }
99
100 func setPublicKeyFields(ff *fuzz.ConsumeFuzzer, props *types.ArtifactProperties) (func(), error) {
101 cleanup := func() {}
102
103 shouldSetPublicKeyBytes, err := ff.GetBool()
104 if err != nil {
105 return cleanup, err
106 }
107
108 if shouldSetPublicKeyBytes {
109 publicKeyBytes := make([][]byte, 0)
110 err := ff.GenerateStruct(&publicKeyBytes)
111 if err != nil || len(publicKeyBytes) == 0 {
112 return cleanup, err
113 }
114 props.PublicKeyBytes = publicKeyBytes
115 return cleanup, nil
116 }
117 publicKeyBytes, err := ff.GetBytes()
118 if err != nil {
119 return cleanup, err
120 }
121 publicKeyURL, err := createAbsFile(ff, "PublicKeyFile", publicKeyBytes)
122 if err != nil {
123 os.Remove("PublicKeyFile")
124 return cleanup, err
125 }
126 props.PublicKeyPaths = []*url.URL{publicKeyURL}
127 return func() {
128 os.Remove("PublicKeyFile")
129 }, nil
130 }
131
132
133 func setAdditionalAuthenticatedData(ff *fuzz.ConsumeFuzzer, props *types.ArtifactProperties) error {
134 shouldSetAdditionalAuthenticatedData, err := ff.GetBool()
135 if err != nil {
136 return err
137 }
138 if shouldSetAdditionalAuthenticatedData {
139 additionalAuthenticatedData, err := ff.GetBytes()
140 if err != nil {
141 return err
142 }
143 props.AdditionalAuthenticatedData = additionalAuthenticatedData
144 }
145 return nil
146 }
147
148
149 func setPKIFormat(ff *fuzz.ConsumeFuzzer, props *types.ArtifactProperties) error {
150 shouldSetPKIFormat, err := ff.GetBool()
151 if err != nil {
152 return err
153 }
154
155 if shouldSetPKIFormat {
156 pkiFormat, err := ff.GetString()
157 if err != nil {
158 return err
159 }
160 props.PKIFormat = pkiFormat
161 }
162
163 return nil
164 }
165
166 func createArtifactFiles(ff *fuzz.ConsumeFuzzer, artifactType string) ([]*fuzz.TarFile, error) {
167 switch artifactType {
168 case "jarV001":
169 return createJarArtifactFiles(ff)
170 default:
171 return createDefaultArtifactFiles(ff)
172 }
173 }
174
175 func createDefaultArtifactFiles(ff *fuzz.ConsumeFuzzer) ([]*fuzz.TarFile, error) {
176 var files []*fuzz.TarFile
177 files, err := ff.TarFiles()
178 if err != nil {
179 return files, err
180 }
181 if len(files) <= 1 {
182 return files, err
183 }
184 for _, file := range files {
185 if len(file.Body) == 0 {
186 return files, errors.New("Created an empty file")
187 }
188 }
189 return files, nil
190 }
191
192
193 func CreateProps(ff *fuzz.ConsumeFuzzer, fuzzType string) (types.ArtifactProperties, []func(), error) {
194 var cleanups []func()
195
196 props := &types.ArtifactProperties{}
197
198 err := setArtifactHash(ff, props)
199 if err != nil {
200 return *props, cleanups, err
201 }
202
203 artifactFiles, err := createArtifactFiles(ff, fuzzType)
204 if err != nil {
205 return *props, cleanups, err
206 }
207
208 err = setAdditionalAuthenticatedData(ff, props)
209 if err != nil {
210 return *props, cleanups, errors.New("Failed setting AdditionalAuthenticatedData")
211 }
212
213 cleanupSignatureFile, err := setSignatureFields(ff, props)
214 if err != nil {
215 return *props, cleanups, fmt.Errorf("failed setting signature fields: %w", err)
216 }
217 cleanups = append(cleanups, cleanupSignatureFile)
218
219 cleanupPublicKeyFile, err := setPublicKeyFields(ff, props)
220 if err != nil {
221 return *props, cleanups, fmt.Errorf("failed setting public key fields: %w", err)
222 }
223 cleanups = append(cleanups, cleanupPublicKeyFile)
224
225 err = setPKIFormat(ff, props)
226 if err != nil {
227 return *props, cleanups, fmt.Errorf("failed setting PKI Format: %w", err)
228 }
229
230 artifactBytes, err := tarFilesToBytes(artifactFiles, fuzzType)
231 if err != nil {
232 return *props, cleanups, fmt.Errorf("failed converting artifact bytes: %w", err)
233 }
234
235 setArtifactBytes, err := ff.GetBool()
236 if err != nil {
237 return *props, cleanups, fmt.Errorf("failed converting artifact bytes: %w", err)
238 }
239 if setArtifactBytes {
240 props.ArtifactBytes = artifactBytes
241 } else {
242 artifactFile, err := createAbsFile(ff, "ArtifactFile", artifactBytes)
243 cleanups = append(cleanups, func() { os.Remove("ArtifactFile") })
244 if err != nil {
245 return *props, cleanups, fmt.Errorf("failed converting artifact bytes: %w", err)
246 }
247 props.ArtifactPath = artifactFile
248 }
249
250 props.ArtifactBytes = artifactBytes
251 return *props, cleanups, nil
252 }
253
254 func tarFilesToBytes(artifactFiles []*fuzz.TarFile, artifactType string) ([]byte, error) {
255 switch artifactType {
256 case "jarV001":
257 return tarfilesToJar(artifactFiles)
258 default:
259 return defaultTarToBytes(artifactFiles)
260 }
261 }
262
263 func defaultTarToBytes(artifactFiles []*fuzz.TarFile) ([]byte, error) {
264 b := new(bytes.Buffer)
265 w := zip.NewWriter(b)
266
267 for _, file := range artifactFiles {
268 f, err := w.Create(file.Hdr.Name)
269 if err != nil {
270 continue
271 }
272 _, _ = f.Write(file.Body)
273 }
274
275 w.Close()
276 return b.Bytes(), nil
277 }
278
279 func SetFuzzLogger() {
280 config := zap.NewProductionConfig()
281 config.Level = zap.NewAtomicLevelAt(zapcore.FatalLevel)
282 logger, err := config.Build()
283 if err != nil {
284 panic(err)
285 }
286 log.Logger = logger.Named("rekor-fuzz-logger").Sugar()
287 }
288
View as plain text