View Javadoc
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 }