1 /**
2 * Portions of this software was developed by employees of the National Institute
3 * of Standards and Technology (NIST), an agency of the Federal Government and is
4 * being made available as a public service. Pursuant to title 17 United States
5 * Code Section 105, works of NIST employees are not subject to copyright
6 * protection in the United States. This software may be subject to foreign
7 * copyright. Permission in the United States and in foreign countries, to the
8 * extent that NIST may hold copyright, to use, copy, modify, create derivative
9 * works, and distribute this software and its documentation without fee is hereby
10 * granted on a non-exclusive basis, provided that this notice and disclaimer
11 * of warranty appears in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14 * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15 * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17 * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18 * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT
19 * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20 * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21 * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22 * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24 * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25 */
26
27 package gov.nist.secauto.swid.builder.resource.firmware;
28
29 import gov.nist.secauto.swid.builder.AbstractBuilder;
30 import gov.nist.secauto.swid.builder.ValidationException;
31 import gov.nist.secauto.swid.builder.resource.HashAlgorithm;
32 import gov.nist.secauto.swid.builder.resource.HashUtils;
33 import gov.nist.secauto.swid.builder.util.Util;
34
35 import java.io.BufferedInputStream;
36 import java.io.File;
37 import java.io.FileInputStream;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.math.BigInteger;
41 import java.security.NoSuchAlgorithmException;
42 import java.util.LinkedList;
43 import java.util.List;
44 import java.util.Objects;
45
46 public class FirmwarePayloadBuilder extends AbstractBuilder {
47
48 private FirmwareIdentifier id;
49 private String packageIdentifier;
50 private String description;
51 private Integer formatType;
52 private byte[] formatGuidance;
53 private BigInteger size;
54 private BigInteger simpleVersion;
55 // private FirmwarePayloadVersion version;
56 private List<FirmwarePayloadDigest> digests = new LinkedList<>();
57 private String componentIndex;
58 private FirmwareIdentifier storageId;
59 private List<FirmwareRequirement<FirmwareCondition>> conditions = new LinkedList<>();
60 private List<FirmwareRequirement<FirmwareDirective>> directives = new LinkedList<>();
61 // private VersionedDependency targetDependency;
62 // private MinimalVersion targetMinimalVersion;
63 // private List<FirmwarePayloadRelationship> relationships;
64 private FirmwarePayloadPackage firmwarePackage;
65
66 /**
67 * Retrieve the identifier of the firmware payload.
68 *
69 * @return the id
70 */
71 public FirmwareIdentifier getId() {
72 return id;
73 }
74
75 /**
76 * Set the id of the firmware payload.
77 *
78 * @param id
79 * the firmware's identifier
80 * @return the same builder instance
81 */
82 public FirmwarePayloadBuilder id(FirmwareIdentifier id) {
83 Objects.requireNonNull(id, "id");
84 this.id = id;
85 return this;
86 }
87
88 /**
89 * Retrieve the package identifier of the firmware manifest.
90 *
91 * @return the packageIdentifier
92 */
93 public String getPackageIdentifier() {
94 return packageIdentifier;
95 }
96
97 /**
98 * Set the package identifier.
99 *
100 * @param packageIdentifier
101 * a {@code non-null} package identifier
102 * @return the same builder instance
103 */
104 public FirmwarePayloadBuilder packageIdentifier(String packageIdentifier) {
105 Util.requireNonEmpty(packageIdentifier, "packageIdentifier");
106 this.packageIdentifier = packageIdentifier;
107 return this;
108 }
109
110 /**
111 * Retrieve the description of the firmware payload.
112 *
113 * @return the description
114 */
115 public String getDescription() {
116 return description;
117 }
118
119 /**
120 * Set the version of the firmware payload.
121 *
122 * @param description
123 * the firmware's description
124 * @return the same builder instance
125 */
126 public FirmwarePayloadBuilder description(String description) {
127 Util.requireNonEmpty(description, "description");
128 this.description = description;
129 return this;
130 }
131
132 /**
133 * Retrieve the format type of the firmware payload.
134 *
135 * @return the type
136 */
137 public int getFormatType() {
138 return formatType;
139 }
140
141 /**
142 * Set the format type.
143 *
144 * @param type
145 * a format type
146 * @return the same builder instance
147 */
148 public FirmwarePayloadBuilder formatType(int type) {
149 this.formatType = type;
150 return this;
151 }
152
153 /**
154 * Retrieve the firmware payload's format guidance.
155 *
156 * @return the format guidance
157 */
158 public byte[] getFormatGuidance() {
159 return formatGuidance;
160 }
161
162 /**
163 * Set the firmware payload's format guidance.
164 *
165 * @param bytes
166 * guidance a {@code non-null} byte string
167 * @return the same builder instance
168 */
169 public FirmwarePayloadBuilder formatGuidance(byte[] bytes) {
170 Objects.requireNonNull(bytes, "bytes");
171 this.formatGuidance = bytes;
172 return this;
173 }
174
175 /**
176 * Retrieve the size the firmware payload.
177 *
178 * @return the size
179 */
180 public BigInteger getSize() {
181 return size;
182 }
183
184 /**
185 * Set the size.
186 *
187 * @param size
188 * a {@code non-null} size
189 * @return the same builder instance
190 */
191 public FirmwarePayloadBuilder size(BigInteger size) {
192 Objects.requireNonNull(size, "size");
193 this.size = size;
194 return this;
195 }
196
197 /**
198 * Retrieve the simple version of the firmware payload.
199 *
200 * @return the version
201 */
202 public BigInteger getSimpleVersion() {
203 return simpleVersion;
204 }
205
206 // /**
207 // * Set the version of the payload.
208 // *
209 // * @param version
210 // * a {@code non-null} version
211 // * @return the same builder instance
212 // */
213 // public FirmwarePayloadBuilder version(FirmwarePayloadVersion version) {
214 // Objects.requireNonNull(version, "version");
215 // this.version = version;
216 // return this;
217 // }
218 //
219 // /**
220 // * Retrieve the simple version of the firmware payload.
221 // *
222 // * @return the version
223 // */
224 // public FirmwarePayloadVersion getVersion() {
225 // return version;
226 // }
227
228 /**
229 * Set the simple version of the payload.
230 *
231 * @param version
232 * a {@code non-null} version
233 * @return the same builder instance
234 */
235 public FirmwarePayloadBuilder simpleVersion(BigInteger version) {
236 Objects.requireNonNull(version, "version");
237 this.simpleVersion = version;
238 return this;
239 }
240
241 /**
242 * Retrieve the digests of the firmware payload.
243 *
244 * @return the digests
245 */
246 public List<FirmwarePayloadDigest> getDigests() {
247 return digests;
248 }
249
250 /**
251 * Adds a new digest to the list of digests.
252 *
253 * @param digest
254 * the digest to add
255 * @return the same builder instance
256 */
257 public FirmwarePayloadBuilder addDigest(FirmwarePayloadDigest digest) {
258 Objects.requireNonNull(digest, "digest");
259 this.digests.add(digest);
260 return this;
261 }
262
263 /**
264 * Sets the to-be-built file's hash value, for the provided algorithm, to the provided value. An
265 * {@link InputStream} is used to retrieve the files contents to calculate the hash value. The
266 * caller is responsible for closing the stream used by this method.
267 *
268 * @param type
269 * the type of resource this digest is for
270 * @param algorithm
271 * the algorithm to establish a hash value for
272 * @param file
273 * the file to hash
274 * @return the same builder instance
275 * @throws NoSuchAlgorithmException
276 * if the hash algorithm is not supported
277 * @throws IOException
278 * if an error occurs while reading the stream
279 */
280 public FirmwarePayloadBuilder addDigest(DigestType type, HashAlgorithm algorithm, File file)
281 throws NoSuchAlgorithmException, IOException {
282 try (InputStream is = new BufferedInputStream(new FileInputStream(file))) {
283 return addDigest(type, algorithm, is);
284 }
285 }
286
287 /**
288 * Sets the file's hash value, for the provided algorithm, to the provided value. An
289 * {@link InputStream} is used to retrieve the files contents to calculate the hash value. The
290 * caller is responsible for closing the stream used by this method.
291 *
292 * @param type
293 * the type of resource this digest is for
294 * @param algorithm
295 * the algorithm to establish a hash value for
296 * @param is
297 * an {@link InputStream} that can be used to read the file
298 * @return the same builder instance
299 * @throws NoSuchAlgorithmException
300 * if the hash algorithm is not supported
301 * @throws IOException
302 * if an error occurs while reading the stream
303 */
304 public FirmwarePayloadBuilder addDigest(DigestType type, HashAlgorithm algorithm, InputStream is)
305 throws NoSuchAlgorithmException, IOException {
306 byte[] digest = HashUtils.hash(algorithm, is);
307 return addDigest(type, algorithm, digest);
308 }
309
310 /**
311 * Sets the file's hash value, for the provided algorithm, to the provided value.
312 *
313 * @param type
314 * the type of resource this digest is for
315 * @param algorithm
316 * the algorithm to establish a hash value for
317 * @param digest
318 * an array of bytes representing the digest value
319 * @return the same builder instance
320 */
321 public FirmwarePayloadBuilder addDigest(DigestType type, HashAlgorithm algorithm, byte[] digest) {
322 Objects.requireNonNull(type, "type");
323 Objects.requireNonNull(algorithm, "algorithm");
324 Objects.requireNonNull(digest, "digest");
325
326 FirmwarePayloadDigestrmware/FirmwarePayloadDigest.html#FirmwarePayloadDigest">FirmwarePayloadDigest payloadDigest = new FirmwarePayloadDigest(type, algorithm, digest);
327 return addDigest(payloadDigest);
328 }
329
330 /**
331 * Retrieve the index value of the firmware component.
332 *
333 * @return the componentIndex
334 */
335 public String getComponentIndex() {
336 return componentIndex;
337 }
338
339 /**
340 * Set the component index.
341 *
342 * @param componentIndex
343 * a {@code non-null} component index
344 * @return the same builder instance
345 */
346 public FirmwarePayloadBuilder componentIndex(String componentIndex) {
347 Util.requireNonEmpty(componentIndex, "componentIndex");
348 this.componentIndex = componentIndex;
349 return this;
350 }
351
352 /**
353 * Retrieve the storage id of the firmware component.
354 *
355 * @return the storage id
356 */
357 public FirmwareIdentifier getStorageId() {
358 return storageId;
359 }
360
361 /**
362 * Set the storage id.
363 *
364 * @param id
365 * a {@code non-null} storage id
366 * @return the same builder instance
367 */
368 public FirmwarePayloadBuilder storageId(FirmwareIdentifier id) {
369 Objects.requireNonNull(id, "storageId");
370 this.storageId = id;
371 return this;
372 }
373
374 /**
375 * Retrieve the conditions of the firmware payload.
376 *
377 * @return the conditions
378 */
379 public List<FirmwareRequirement<FirmwareCondition>> getConditions() {
380 return conditions;
381 }
382
383 /**
384 * Adds a new condition to the list of conditions.
385 *
386 * @param condition
387 * the condition to add
388 * @return the same builder instance
389 */
390 public FirmwarePayloadBuilder addCondition(FirmwareRequirement<FirmwareCondition> condition) {
391 Objects.requireNonNull(condition, "condition");
392 this.conditions.add(condition);
393 return this;
394 }
395
396 /**
397 * Retrieve the directives of the firmware payload.
398 *
399 * @return the directives
400 */
401 public List<FirmwareRequirement<FirmwareDirective>> getDirectives() {
402 return directives;
403 }
404
405 /**
406 * Adds a new directive to the list of directives.
407 *
408 * @param directive
409 * the directive to add
410 * @return the same builder instance
411 */
412 public FirmwarePayloadBuilder addDirective(FirmwareRequirement<FirmwareDirective> directive) {
413 Objects.requireNonNull(directive, "directive");
414 this.directives.add(directive);
415 return this;
416 }
417
418 // /**
419 // * Retrieve the targetDependency of the firmware component.
420 // *
421 // * @return the targetDependency
422 // */
423 // public VersionedDependency getTargetDependency() {
424 // return targetDependency;
425 // }
426 //
427 // /**
428 // * Set the component targetDependency.
429 // *
430 // * @param targetDependency
431 // * a {@code non-null} targetDependency
432 // * @return the same builder instance
433 // */
434 // public FirmwarePayloadBuilder targetDependency(VersionedDependency
435 // targetDependency) {
436 // Objects.requireNonNull(targetDependency, "targetDependency");
437 // this.targetDependency = targetDependency;
438 // return this;
439 // }
440
441 // /**
442 // * Retrieve the targetMinimalVersion of the firmware component.
443 // *
444 // * @return the targetMinimalVersion
445 // */
446 // public MinimalVersion getTargetMinimalVersion() {
447 // return targetMinimalVersion;
448 // }
449 //
450 // /**
451 // * Set the component targetMinimalVersion.
452 // *
453 // * @param targetMinimalVersion
454 // * a {@code non-null} targetMinimalVersion
455 // * @return the same builder instance
456 // */
457 // public FirmwarePayloadBuilder targetMinimalVersion(MinimalVersion
458 // targetMinimalVersion) {
459 // Objects.requireNonNull(targetDependency, "targetDependency");
460 // this.targetMinimalVersion = targetMinimalVersion;
461 // return this;
462 // }
463
464 // /**
465 // * Retrieve the relationships of the firmware payload.
466 // *
467 // * @return the relationships
468 // */
469 // public List<FirmwarePayloadRelationship> getRelationships() {
470 // return relationships;
471 // }
472 //
473 // /**
474 // * Adds a new relationship to the list of relationships.
475 // *
476 // * @param relationship
477 // * the relationship to add
478 // * @return the same builder instance
479 // */
480 // public FirmwarePayloadBuilder addRelationship(FirmwarePayloadRelationship
481 // relationship) {
482 // Objects.requireNonNull(relationship, "relationship");
483 // this.relationships.add(relationship);
484 // return this;
485 // }
486
487 /**
488 * Retrieve the firmwarePackage of the firmware component.
489 *
490 * @return the targetMinimalVersion
491 */
492 public FirmwarePayloadPackage getFirmwarePackage() {
493 return firmwarePackage;
494 }
495
496 /**
497 * Set the component firmwarePackage.
498 *
499 * @param firmwarePackage
500 * a {@code non-null} firmwarePackage
501 * @return the same builder instance
502 */
503 public FirmwarePayloadBuilder firmwarePackage(FirmwarePayloadPackage firmwarePackage) {
504 Objects.requireNonNull(firmwarePackage, "firmwarePackage");
505 this.firmwarePackage = firmwarePackage;
506 return this;
507 }
508
509 @Override
510 public void validate() throws ValidationException {
511 validateNonNull("id", id);
512 validateNonNull("formatType", formatType);
513 validateNonNull("size", size);
514 validateNonEmpty("digests", digests);
515 validateNonNull("storageId", storageId);
516 validateNonEmpty("conditions", conditions);
517 }
518
519 @Override
520 public void reset() {
521 // TODO: implement
522 }
523 }