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.output;
28  
29  import com.fasterxml.jackson.core.JsonGenerator;
30  
31  import gov.nist.secauto.swid.builder.resource.firmware.DeviceIdentifier;
32  import gov.nist.secauto.swid.builder.resource.firmware.FirmwareBuilder;
33  import gov.nist.secauto.swid.builder.resource.firmware.FirmwarePayloadBuilder;
34  import gov.nist.secauto.swid.builder.resource.firmware.FirmwarePayloadDigest;
35  import gov.nist.secauto.swid.builder.resource.firmware.FirmwarePayloadPackage;
36  
37  import java.io.IOException;
38  import java.util.List;
39  import java.util.Map;
40  
41  public class CBORFirmwareOutputHandler extends JsonSupport {
42    /**
43     * Firmware.
44     */
45    private static final long FIRMWARE_MANIFEST_ID_FIELD = 63L; // bytes / text / uint
46    private static final long FIRMWARE_MANIFEST_CREATION_TIMESTAMP = 64L; // time
47    private static final long FIRMWARE_MANIFEST_VERSION = 65L; // uint
48    private static final long FIRMWARE_MANIFEST_DESCRIPTION = 66L; // text
49    private static final long FIRMWARE_MANIFEST_NONCE = 67L; // bytes
50    // private static final long FIRMWARE_MANIFEST_DEPENDENCIES = 68L; //
51    // resource-reference
52    // private static final long FIRMWARE_MANIFEST_ALIASES = 69L; //
53    // resource-reference
54    private static final long FIRMWARE_MANIFEST_TARGET_DEVICE_ID = 85L; // object
55    // firmware-payload / [ 2* firmware-payload ]
56    private static final long FIRMWARE_MANIFEST_PAYLOAD_ENTRY = 60L;
57    private static final long FIRMWARE_MANIFEST_SIMPLE_EXTENSIONS = 115L; // { + int => bytes }
58  
59    private static final long FIRMWARE_PAYLOAD_ID = 61L; // bytes / text / uint
60    private static final long FIRMWARE_PAYLOAD_PACKAGE_ID = 62L; // text
61    // private static final long FIRMWARE_PAYLOAD_DESCRIPTION = 70L; // text
62    private static final long FIRMWARE_PAYLOAD_FORMAT = 71L; // object
63    private static final long FIRMWARE_PAYLOAD_SIZE = 74L; // unint
64    // private static final long FIRMWARE_PAYLOAD_SIMPLE_VERSION = 107L; // uint
65    // private static final long FIRMWARE_PAYLOAD_VERSION = 108L; // object
66    private static final long FIRMWARE_PAYLOAD_DIGESTS = 97L; // object
67    // private static final long FIRMWARE_PAYLOAD_TARGET_COMPONENT_INDEX = 79L; //
68    // text
69    private static final long FIRMWARE_PAYLOAD_STORAGE_IDENTIFIER = 80L; // bytes / text / uint
70    // private static final long FIRMWARE_PAYLOAD_CONDITIONS = 101L; // array of
71    // objects
72    // private static final long FIRMWARE_PAYLOAD_DIRECTIVES = 104L; // array of
73    // objects
74    // private static final long FIRMWARE_PAYLOAD_TARGET_DEPENDENCY = 81L; // array
75    // of objects
76    // private static final long FIRMWARE_PAYLOAD_TARGET_MINIMAL_VERSION = 92L; //
77    // object
78    // private static final long FIRMWARE_PAYLOAD_RELATIONSHIPS = 84L; // enum (int)
79    private static final long FIRMWARE_PAYLOAD_PACKAGE = 75L; // object
80    // private static final long FIRMWARE_PAYLOAD_SIMPLE_EXTENSIONS = 116L; // { +
81    // int => bytes }
82  
83    /*
84     * Device Identifier object
85     */
86    private static final long FIRMWARE_TARGET_DEVICE_IDENTIFIER_VENDOR = 86L; // text
87    private static final long FIRMWARE_TARGET_DEVICE_IDENTIFIER_TYPE = 87L; // text
88    private static final long FIRMWARE_TARGET_DEVICE_IDENTIFIER_MODEL = 88L; // text
89    private static final long FIRMWARE_TARGET_DEVICE_IDENTIFIER_CLASS = 89L; // text
90    private static final long FIRMWARE_TARGET_DEVICE_IDENTIFIER_RFC4122 = 90L; // text
91    private static final long FIRMWARE_TARGET_DEVICE_IDENTIFIER_IEEE802_1_AR = 91L; // bytes
92  
93    /*
94     * Payload Format object
95     */
96    private static final long FIRMWARE_PAYLOAD_FORMAT_TYPE = 72L; // int
97    private static final long FIRMWARE_PAYLOAD_FORMAT_GUIDANCE = 73L; // bytes
98  
99    /*
100    * Payload Digest object
101    */
102   private static final long FIRMWARE_PAYLOAD_DIGEST_TYPE = 98L; // enum (int)
103   private static final long FIRMWARE_PAYLOAD_DIGEST_GUIDANCE = 99L; // bytes
104   private static final long FIRMWARE_PAYLOAD_DIGEST_VALUE = 100L; // bytes
105 
106   /*
107    * Firmware Package object (75)
108    */
109   private static final long FIRMWARE_PAYLOAD_PACKAGE_COMPRESSION_TYPE = 76L; // text / int
110   private static final long FIRMWARE_PAYLOAD_PACKAGE_COMPRESSION_GUIDANCE = 77L; // bytes
111   private static final long FIRMWARE_PAYLOAD_PACKAGE_VALUE = 78L; // bytes
112 
113   /**
114    * Generate a CBOR object based on the provided builder.
115    * 
116    * @param generator
117    *          the generator to write data to
118    * @param builder
119    *          the firmware builder to read data from
120    */
121   public void generate(JsonGenerator generator, FirmwareBuilder builder) {
122     try {
123       generator.writeStartObject();
124 
125       writeField(generator, FIRMWARE_MANIFEST_ID_FIELD, builder.getId());
126 
127       writeDateTimeField(generator, FIRMWARE_MANIFEST_CREATION_TIMESTAMP, builder.getCreationTimestamp());
128 
129       writeIntegerField(generator, FIRMWARE_MANIFEST_VERSION, builder.getVersion());
130 
131       if (builder.getDescription() != null) {
132         writeTextField(generator, FIRMWARE_MANIFEST_DESCRIPTION, builder.getDescription());
133       }
134 
135       writeBinaryField(generator, FIRMWARE_MANIFEST_NONCE, builder.getNonce());
136 
137       // FIRMWARE_MANIFEST_DEPENDENCIES
138       // FIRMWARE_MANIFEST_ALIASES
139 
140       writeDeviceIdentifier(generator, FIRMWARE_MANIFEST_TARGET_DEVICE_ID, builder.getTargetDeviceIdentifier());
141 
142       List<FirmwarePayloadBuilder> payloads = builder.getPayloads();
143       if (!payloads.isEmpty()) {
144         generator.writeFieldId(FIRMWARE_MANIFEST_PAYLOAD_ENTRY);
145 
146         if (payloads.size() == 1) {
147           generate(generator, payloads.iterator().next());
148         } else {
149           generator.writeStartArray();
150           for (FirmwarePayloadBuilder payload : payloads) {
151             generate(generator, payload);
152           }
153           generator.writeEndArray();
154         }
155       }
156 
157       Map<Integer, byte[]> extensions = builder.getExtensions();
158       if (!extensions.isEmpty()) {
159         generator.writeFieldId(FIRMWARE_MANIFEST_SIMPLE_EXTENSIONS);
160         generator.writeStartObject();
161 
162         for (Map.Entry<Integer, byte[]> entry : extensions.entrySet()) {
163           writeBinaryField(generator, entry.getKey(), entry.getValue());
164         }
165         generator.writeEndObject();
166       }
167 
168       generator.writeEndObject();
169     } catch (IOException ex) {
170       throw new RuntimeException(ex);
171     }
172   }
173 
174   private void generate(JsonGenerator generator, FirmwarePayloadBuilder builder) throws IOException {
175     generator.writeStartObject();
176 
177     writeField(generator, FIRMWARE_PAYLOAD_ID, builder.getId());
178 
179     if (builder.getPackageIdentifier() != null) {
180       writeTextField(generator, FIRMWARE_PAYLOAD_PACKAGE_ID, builder.getPackageIdentifier());
181     }
182 
183     if (builder.getDescription() != null) {
184       writeTextField(generator, FIRMWARE_MANIFEST_DESCRIPTION, builder.getDescription());
185     }
186 
187     {
188       generator.writeFieldId(FIRMWARE_PAYLOAD_FORMAT);
189       generator.writeStartObject();
190       writeIntegerField(generator, FIRMWARE_PAYLOAD_FORMAT_TYPE, builder.getFormatType());
191 
192       if (builder.getFormatGuidance() != null) {
193         writeBinaryField(generator, FIRMWARE_PAYLOAD_FORMAT_GUIDANCE, builder.getFormatGuidance());
194       }
195       generator.writeEndObject();
196     }
197 
198     writeIntegerField(generator, FIRMWARE_PAYLOAD_SIZE, builder.getSize());
199 
200     // private static final long FIRMWARE_PAYLOAD_SIMPLE_VERSION = 107L; // uint
201     // private static final long FIRMWARE_PAYLOAD_VERSION = 108L; // object
202 
203     List<FirmwarePayloadDigest> digests = builder.getDigests();
204     if (!digests.isEmpty()) {
205       generator.writeFieldId(FIRMWARE_PAYLOAD_DIGESTS);
206 
207       generator.writeStartArray();
208       for (FirmwarePayloadDigest digest : digests) {
209         generate(generator, digest);
210       }
211       generator.writeEndArray();
212     }
213 
214     // private static final long FIRMWARE_PAYLOAD_TARGET_COMPONENT_INDEX = 79L; //
215     // text
216 
217     writeField(generator, FIRMWARE_PAYLOAD_STORAGE_IDENTIFIER, builder.getStorageId());
218 
219     // private static final long FIRMWARE_PAYLOAD_CONDITIONS = 101L; // array of
220     // objects
221     // private static final long FIRMWARE_PAYLOAD_DIRECTIVES = 104L; // array of
222     // objects
223     // private static final long FIRMWARE_PAYLOAD_TARGET_DEPENDENCY = 81L; // array
224     // of objects
225     // private static final long FIRMWARE_PAYLOAD_TARGET_MINIMAL_VERSION = 92L; //
226     // object
227     // private static final long FIRMWARE_PAYLOAD_RELATIONSHIPS = 84L; // enum (int)
228 
229     if (builder.getFirmwarePackage() != null) {
230       writePayload(generator, FIRMWARE_PAYLOAD_PACKAGE, builder.getFirmwarePackage());
231     }
232     // private static final long FIRMWARE_PAYLOAD_SIMPLE_EXTENSIONS = 116L; // { +
233     // int => bytes
234 
235     generator.writeEndObject();
236   }
237 
238   private void generate(JsonGenerator generator, FirmwarePayloadDigest digest) throws IOException {
239     generator.writeStartObject();
240 
241     writeIntegerField(generator, FIRMWARE_PAYLOAD_DIGEST_TYPE, digest.getType().getIndex());
242 
243     if (digest.getGuidance() != null) {
244       writeBinaryField(generator, FIRMWARE_PAYLOAD_DIGEST_GUIDANCE, digest.getGuidance());
245     }
246 
247     writeBinaryField(generator, FIRMWARE_PAYLOAD_DIGEST_VALUE, digest.getValue());
248     generator.writeEndObject();
249   }
250 
251   private void writeDeviceIdentifier(JsonGenerator generator, long fieldId, DeviceIdentifier deviceIdentifier)
252       throws IOException {
253     generator.writeFieldId(fieldId);
254 
255     generator.writeStartObject();
256 
257     writeTextField(generator, FIRMWARE_TARGET_DEVICE_IDENTIFIER_VENDOR, deviceIdentifier.getVendor());
258 
259     if (deviceIdentifier.getType() != null) {
260       writeTextField(generator, FIRMWARE_TARGET_DEVICE_IDENTIFIER_TYPE, deviceIdentifier.getType());
261     }
262 
263     writeTextField(generator, FIRMWARE_TARGET_DEVICE_IDENTIFIER_MODEL, deviceIdentifier.getVendor());
264 
265     if (deviceIdentifier.getClazz() != null) {
266       writeTextField(generator, FIRMWARE_TARGET_DEVICE_IDENTIFIER_CLASS, deviceIdentifier.getClazz());
267     }
268 
269     if (deviceIdentifier.getRfc4122() != null) {
270       writeTextField(generator, FIRMWARE_TARGET_DEVICE_IDENTIFIER_RFC4122, deviceIdentifier.getRfc4122());
271     }
272 
273     if (deviceIdentifier.getIeee8021ar() != null) {
274       writeBinaryField(generator, FIRMWARE_TARGET_DEVICE_IDENTIFIER_IEEE802_1_AR, deviceIdentifier.getIeee8021ar());
275     }
276 
277     generator.writeEndObject();
278   }
279 
280   private void writePayload(JsonGenerator generator, long fieldId, FirmwarePayloadPackage payload) throws IOException {
281     generator.writeFieldId(fieldId);
282 
283     generator.writeStartObject();
284 
285     if (payload.getCompressionType() != null) {
286       writeIntegerOrTextField(generator, FIRMWARE_PAYLOAD_PACKAGE_COMPRESSION_TYPE, payload.getCompressionType());
287     }
288 
289     if (payload.getCompressionGuidance() != null) {
290       writeBinaryField(generator, FIRMWARE_PAYLOAD_PACKAGE_COMPRESSION_GUIDANCE, payload.getCompressionGuidance());
291     }
292     writeBinaryField(generator, FIRMWARE_PAYLOAD_PACKAGE_VALUE, payload.getPackageBytes());
293 
294     generator.writeEndObject();
295   }
296 }