Line data Source code
1 : /*
2 : * output.c - Pretty print PSKC data.
3 : * Copyright (C) 2012-2021 Simon Josefsson
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Lesser General Public License
7 : * as published by the Free Software Foundation; either version 2.1 of
8 : * the License, or (at your option) any later version.
9 : *
10 : * This library is distributed in the hope that it will be useful, but
11 : * WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Lesser General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public
16 : * License along with this library; if not, write to the Free Software
17 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 : * 02110-1301 USA
19 : *
20 : */
21 :
22 : #include <config.h>
23 :
24 : #include <pskc/pskc.h>
25 :
26 : #include "minmax.h"
27 :
28 : #define INTERNAL_NEED_PSKC_STRUCT
29 : #include "internal.h"
30 : #include <stdlib.h> /* malloc */
31 : #include <string.h> /* memmove */
32 : #include <inttypes.h> /* PRId64 */
33 : #include <libxml/parser.h> /* xmlInitParser */
34 :
35 : struct buffer
36 : {
37 : char *mem; /* NULL if malloc has failed */
38 : size_t memlen; /* length of allocated buffer */
39 : size_t dlen; /* length of data in buffer */
40 : };
41 :
42 : #define CHUNK 1024
43 :
44 : static void
45 4 : buffer_init (struct buffer *buf)
46 : {
47 4 : buf->memlen = CHUNK;
48 4 : buf->mem = malloc (buf->memlen);
49 4 : if (buf->mem)
50 4 : buf->mem[0] = '\0';
51 4 : buf->dlen = 0;
52 4 : }
53 :
54 : static void
55 4 : buffer_getstr (struct buffer *buf, char **str, size_t *dlen)
56 : {
57 4 : *str = buf->mem;
58 4 : *dlen = buf->dlen;
59 4 : }
60 :
61 : static void
62 152 : buffer_add (struct buffer *buf, size_t len, const void *data)
63 : {
64 : size_t n;
65 :
66 152 : if (len == 0 || buf->mem == NULL)
67 0 : return;
68 :
69 152 : n = buf->dlen + len;
70 152 : if (buf->memlen > n)
71 : {
72 149 : memmove (&buf->mem[buf->dlen], data, len);
73 149 : buf->dlen = n;
74 149 : buf->mem[buf->dlen] = '\0';
75 : }
76 : else
77 : {
78 3 : size_t newlen = buf->memlen + MAX (len, CHUNK);
79 : char *tmp;
80 :
81 3 : tmp = realloc (buf->mem, newlen);
82 3 : if (tmp == NULL)
83 : {
84 0 : free (buf->mem);
85 0 : buf->mem = NULL;
86 0 : return;
87 : }
88 3 : buf->mem = tmp;
89 3 : buf->memlen = newlen;
90 :
91 3 : memmove (&buf->mem[buf->dlen], data, len);
92 :
93 3 : buf->dlen = n;
94 3 : buf->mem[buf->dlen] = '\0';
95 : }
96 : }
97 :
98 : static void
99 152 : buffer_addz (struct buffer *buf, const char *str)
100 : {
101 152 : buffer_add (buf, strlen (str), str);
102 152 : }
103 :
104 : static void
105 : buffer_addf (struct buffer *buf, const char *fmt, ...)
106 : __attribute__((format (printf, 2, 3)));
107 :
108 : static void
109 140 : buffer_addf (struct buffer *buf, const char *fmt, ...)
110 : {
111 : va_list args;
112 : int len;
113 : char *str;
114 :
115 140 : va_start (args, fmt);
116 140 : len = vasprintf (&str, fmt, args);
117 140 : va_end (args);
118 :
119 140 : if (len < 0 || !str)
120 : {
121 0 : free (buf->mem);
122 0 : buf->mem = NULL;
123 0 : return;
124 : }
125 :
126 140 : buffer_addz (buf, str);
127 :
128 140 : free (str);
129 : }
130 :
131 : static void
132 4 : print_keypackage (struct buffer *buf, pskc_key_t * kp)
133 : {
134 4 : const char *device_manufacturer = pskc_get_device_manufacturer (kp);
135 4 : const char *device_serialno = pskc_get_device_serialno (kp);
136 4 : const char *device_model = pskc_get_device_model (kp);
137 4 : const char *device_issueno = pskc_get_device_issueno (kp);
138 4 : const char *device_devicebinding = pskc_get_device_devicebinding (kp);
139 4 : const struct tm *device_startdate = pskc_get_device_startdate (kp);
140 4 : const struct tm *device_expirydate = pskc_get_device_expirydate (kp);
141 4 : const char *device_userid = pskc_get_device_userid (kp);
142 4 : const char *cryptomodule_id = pskc_get_cryptomodule_id (kp);
143 4 : const char *key_id = pskc_get_key_id (kp);
144 4 : const char *key_friendlyname = pskc_get_key_friendlyname (kp);
145 4 : const char *key_issuer = pskc_get_key_issuer (kp);
146 4 : const char *key_profileid = pskc_get_key_profileid (kp);
147 4 : const char *key_reference = pskc_get_key_reference (kp);
148 4 : const char *key_userid = pskc_get_key_userid (kp);
149 4 : const char *key_algorithm = pskc_get_key_algorithm (kp);
150 4 : const char *key_b64secret = pskc_get_key_data_b64secret (kp);
151 : int key_counter_present;
152 4 : uint64_t key_counter = pskc_get_key_data_counter (kp, &key_counter_present);
153 : int key_time_present;
154 4 : uint32_t key_time = pskc_get_key_data_time (kp, &key_time_present);
155 : int key_timedrift_present;
156 4 : uint32_t key_timedrift = pskc_get_key_data_timedrift
157 : (kp, &key_timedrift_present);
158 : int key_timeinterval_present;
159 4 : uint32_t key_timeinterval = pskc_get_key_data_timeinterval
160 : (kp, &key_timeinterval_present);
161 4 : const char *key_policy_pinkeyid = pskc_get_key_policy_pinkeyid (kp);
162 : int key_policy_pinminlength_present;
163 4 : uint32_t key_policy_pinminlength = pskc_get_key_policy_pinminlength
164 : (kp, &key_policy_pinminlength_present);
165 : int key_policy_pinmaxlength_present;
166 4 : uint32_t key_policy_pinmaxlength = pskc_get_key_policy_pinmaxlength
167 : (kp, &key_policy_pinmaxlength_present);
168 : int key_policy_pinmaxfailedattempts_present;
169 : uint32_t key_policy_pinmaxfailedattempts =
170 4 : pskc_get_key_policy_pinmaxfailedattempts (kp,
171 : &key_policy_pinmaxfailedattempts_present);
172 : int key_policy_pinusagemode_present;
173 : pskc_pinusagemode key_policy_pinusagemode =
174 4 : pskc_get_key_policy_pinusagemode (kp, &key_policy_pinusagemode_present);
175 : int key_policy_pinencoding_present;
176 : pskc_valueformat key_policy_pinencoding =
177 4 : pskc_get_key_policy_pinencoding (kp, &key_policy_pinencoding_present);
178 : int key_policy_keyusages_present;
179 : int key_policy_keyusages =
180 4 : pskc_get_key_policy_keyusages (kp, &key_policy_keyusages_present);
181 4 : const char *key_algparm_suite = pskc_get_key_algparm_suite (kp);
182 : int key_algparm_chall_encoding_present;
183 : pskc_valueformat key_algparm_chall_encoding =
184 4 : pskc_get_key_algparm_chall_encoding (kp,
185 : &key_algparm_chall_encoding_present);
186 : int key_algparm_chall_min_present;
187 : uint32_t key_algparm_chall_min =
188 4 : pskc_get_key_algparm_chall_min (kp, &key_algparm_chall_min_present);
189 : int key_algparm_chall_max_present;
190 : uint32_t key_algparm_chall_max =
191 4 : pskc_get_key_algparm_chall_max (kp, &key_algparm_chall_max_present);
192 : int key_algparm_resp_encoding_present;
193 : pskc_valueformat key_algparm_resp_encoding =
194 4 : pskc_get_key_algparm_resp_encoding (kp,
195 : &key_algparm_resp_encoding_present);
196 : int key_algparm_resp_length_present;
197 : uint32_t key_algparm_resp_length =
198 4 : pskc_get_key_algparm_resp_length (kp, &key_algparm_resp_length_present);
199 4 : const struct tm *key_policy_startdate = pskc_get_key_policy_startdate (kp);
200 : const struct tm *key_policy_expirydate =
201 4 : pskc_get_key_policy_expirydate (kp);
202 :
203 4 : buffer_addz (buf, "\t\tDeviceInfo:\n");
204 4 : if (device_manufacturer)
205 4 : buffer_addf (buf, "\t\t\tManufacturer: %s\n", device_manufacturer);
206 4 : if (device_serialno)
207 4 : buffer_addf (buf, "\t\t\tSerialNo: %s\n", device_serialno);
208 4 : if (device_model)
209 3 : buffer_addf (buf, "\t\t\tModel: %s\n", device_model);
210 4 : if (device_issueno)
211 3 : buffer_addf (buf, "\t\t\tIssueNo: %s\n", device_issueno);
212 4 : if (device_devicebinding)
213 3 : buffer_addf (buf, "\t\t\tDeviceBinding: %s\n", device_devicebinding);
214 4 : if (device_startdate)
215 : {
216 : char t[100];
217 3 : strftime (t, sizeof (t), "%Y-%m-%d %H:%M:%S", device_startdate);
218 3 : buffer_addf (buf, "\t\t\tDevice StartDate: %s\n", t);
219 : }
220 4 : if (device_expirydate)
221 : {
222 : char t[100];
223 3 : strftime (t, sizeof (t), "%Y-%m-%d %H:%M:%S", device_expirydate);
224 3 : buffer_addf (buf, "\t\t\tDevice ExpiryDate: %s\n", t);
225 : }
226 4 : if (device_userid)
227 3 : buffer_addf (buf, "\t\t\tUserId: %s\n", device_userid);
228 :
229 4 : if (cryptomodule_id)
230 3 : buffer_addf (buf, "\t\tCryptoModuleInfo Id: %s\n", cryptomodule_id);
231 :
232 4 : buffer_addz (buf, "\t\tKey:\n");
233 4 : if (key_id)
234 4 : buffer_addf (buf, "\t\t\tId: %s\n", key_id);
235 4 : if (key_friendlyname)
236 3 : buffer_addf (buf, "\t\t\tFriendlyName: %s\n", key_friendlyname);
237 4 : if (key_issuer)
238 3 : buffer_addf (buf, "\t\t\tIssuer: %s\n", key_issuer);
239 4 : if (key_algorithm)
240 4 : buffer_addf (buf, "\t\t\tAlgorithm: %s\n", key_algorithm);
241 4 : if (key_userid)
242 3 : buffer_addf (buf, "\t\t\tKey User Id: %s\n", key_userid);
243 4 : if (key_profileid)
244 3 : buffer_addf (buf, "\t\t\tKey Profile Id: %s\n", key_profileid);
245 4 : if (key_reference)
246 3 : buffer_addf (buf, "\t\t\tKey Reference: %s\n", key_reference);
247 4 : if (key_b64secret)
248 4 : buffer_addf (buf, "\t\t\tKey Secret (base64): %s\n", key_b64secret);
249 4 : if (key_counter_present)
250 4 : buffer_addf (buf, "\t\t\tKey Counter: %" PRIu64 "\n", key_counter);
251 4 : if (key_time_present)
252 3 : buffer_addf (buf, "\t\t\tKey Time: %" PRIu32 "\n", key_time);
253 4 : if (key_timeinterval_present)
254 3 : buffer_addf (buf, "\t\t\tKey TimeInterval: %" PRIu32 "\n",
255 : key_timeinterval);
256 4 : if (key_timedrift_present)
257 3 : buffer_addf (buf, "\t\t\tKey TimeDrift: %" PRIu32 "\n", key_timedrift);
258 4 : if (key_policy_keyusages_present)
259 : {
260 : int i;
261 3 : buffer_addf (buf, "\t\t\tKey Usage:");
262 36 : for (i = 1; i <= PSKC_KEYUSAGE_LAST; i = i << 1)
263 : {
264 33 : const char *keyusage_str = pskc_keyusage2str (i);
265 :
266 33 : if (key_policy_keyusages & i)
267 6 : buffer_addf (buf, " %s", keyusage_str);
268 : }
269 3 : buffer_addf (buf, "\n");
270 : }
271 4 : if (key_policy_startdate)
272 : {
273 : char t[100];
274 3 : strftime (t, sizeof (t), "%Y-%m-%d %H:%M:%S", key_policy_startdate);
275 3 : buffer_addf (buf, "\t\t\tPolicy StartDate: %s\n", t);
276 : }
277 4 : if (key_policy_expirydate)
278 : {
279 : char t[100];
280 3 : strftime (t, sizeof (t), "%Y-%m-%d %H:%M:%S", key_policy_expirydate);
281 3 : buffer_addf (buf, "\t\t\tPolicy ExpiryDate: %s\n", t);
282 : }
283 4 : if (key_policy_pinminlength_present)
284 3 : buffer_addf (buf, "\t\t\tPIN Policy Minimum Length: %" PRIu32 "\n",
285 : key_policy_pinminlength);
286 4 : if (key_policy_pinmaxlength_present)
287 3 : buffer_addf (buf, "\t\t\tPIN Policy Maximum Length: %" PRIu32 "\n",
288 : key_policy_pinmaxlength);
289 4 : if (key_policy_pinkeyid)
290 3 : buffer_addf (buf, "\t\t\tPIN Policy PIN Key Id: %s\n",
291 : key_policy_pinkeyid);
292 4 : if (key_policy_pinencoding_present)
293 3 : buffer_addf (buf, "\t\t\tPIN Policy PIN Encoding: %s\n",
294 : pskc_valueformat2str (key_policy_pinencoding));
295 4 : if (key_policy_pinusagemode_present)
296 3 : buffer_addf (buf, "\t\t\tPIN Policy PIN Usage Mode: %s\n",
297 : pskc_pinusagemode2str (key_policy_pinusagemode));
298 4 : if (key_policy_pinmaxfailedattempts_present)
299 3 : buffer_addf (buf,
300 : "\t\t\tPIN Policy PIN Max Failed Attempts: %" PRIu32 "\n",
301 : key_policy_pinmaxfailedattempts);
302 4 : if (key_algparm_suite)
303 3 : buffer_addf (buf, "\t\t\tAlgorithm Parameters Suite: %s\n",
304 : key_algparm_suite);
305 4 : if (key_algparm_chall_encoding_present)
306 3 : buffer_addf (buf, "\t\t\tChallenge Format Encoding: %s\n",
307 : pskc_valueformat2str (key_algparm_chall_encoding));
308 4 : if (key_algparm_chall_min_present)
309 3 : buffer_addf (buf, "\t\t\tChallenge Format Min: %" PRIu32 "\n",
310 : key_algparm_chall_min);
311 4 : if (key_algparm_chall_max_present)
312 3 : buffer_addf (buf, "\t\t\tChallenge Format Max: %" PRIu32 "\n",
313 : key_algparm_chall_max);
314 4 : if (key_algparm_resp_length_present)
315 4 : buffer_addf (buf, "\t\t\tResponse Format Length: %" PRIu32 "\n",
316 : key_algparm_resp_length);
317 4 : if (key_algparm_resp_encoding_present)
318 4 : buffer_addf (buf, "\t\t\tResponse Format Encoding: %s\n",
319 : pskc_valueformat2str (key_algparm_resp_encoding));
320 4 : }
321 :
322 : static void
323 4 : print_keycontainer (pskc_t * data, struct buffer *buf)
324 : {
325 4 : const char *version = pskc_get_version (data);
326 4 : const char *id = pskc_get_id (data);
327 4 : int signed_p = pskc_get_signed_p (data);
328 : pskc_key_t *key;
329 : size_t i;
330 :
331 4 : if (version)
332 4 : buffer_addf (buf, "\tVersion: %s\n", version);
333 4 : if (id)
334 3 : buffer_addf (buf, "\tId: %s\n", id);
335 4 : buffer_addf (buf, "\tSigned: %s\n", signed_p ? "YES" : "NO");
336 :
337 8 : for (i = 0; (key = pskc_get_keypackage (data, i)); i++)
338 : {
339 4 : buffer_addf (buf, "\tKeyPackage %zu:\n", i);
340 4 : print_keypackage (buf, key);
341 : }
342 4 : }
343 :
344 : /**
345 : * pskc_output:
346 : * @container: a #pskc_t handle, from pskc_init().
347 : * @format: an #pskc_output_formats_t enumeration type indicating format.
348 : * @out: pointer to output variable holding newly allocated string.
349 : * @len: pointer to output variable hold length of *@out.
350 : *
351 : * Convert PSKC data to a serialized string of the indicated type.
352 : * This is usually used to convert the PSKC data to some human
353 : * readable form.
354 : *
355 : * Returns: %PSKC_OK on success, or an error code.
356 : */
357 : int
358 13 : pskc_output (pskc_t * container,
359 : pskc_output_formats_t format, char **out, size_t *len)
360 : {
361 13 : if (format == PSKC_OUTPUT_HUMAN_COMPLETE)
362 : {
363 : struct buffer buf;
364 :
365 4 : buffer_init (&buf);
366 4 : buffer_addz (&buf, "Portable Symmetric Key Container (PSKC):\n");
367 :
368 4 : print_keycontainer (container, &buf);
369 :
370 4 : buffer_getstr (&buf, out, len);
371 4 : if (*out == NULL)
372 0 : return PSKC_MALLOC_ERROR;
373 : }
374 9 : else if (format == PSKC_OUTPUT_XML || format == PSKC_OUTPUT_INDENTED_XML)
375 8 : {
376 : xmlChar *mem;
377 : int size;
378 :
379 8 : xmlDocDumpMemory (container->xmldoc, &mem, &size);
380 :
381 8 : if (format == PSKC_OUTPUT_INDENTED_XML)
382 : {
383 : xmlDocPtr xmldoc;
384 :
385 1 : xmldoc = xmlReadMemory ((const char *) mem, size, NULL, NULL,
386 : XML_PARSE_NONET | XML_PARSE_NOBLANKS);
387 1 : if (xmldoc == NULL)
388 0 : return PSKC_XML_ERROR;
389 :
390 1 : xmlFree (mem);
391 :
392 1 : xmlDocDumpFormatMemory (xmldoc, &mem, &size, 1);
393 :
394 1 : xmlFreeDoc (xmldoc);
395 : }
396 :
397 8 : if (mem == NULL || size <= 0)
398 : {
399 0 : if (format == PSKC_OUTPUT_XML)
400 0 : _pskc_debug ("xmlDocDumpMemory failed");
401 : else
402 0 : _pskc_debug ("xmlDocDumpFormatMemory failed");
403 0 : return PSKC_XML_ERROR;
404 : }
405 :
406 8 : if (len)
407 8 : *len = size;
408 8 : if (out)
409 : {
410 8 : *out = malloc (size);
411 8 : if (*out == NULL)
412 0 : return PSKC_MALLOC_ERROR;
413 :
414 8 : memcpy (*out, mem, size);
415 : }
416 :
417 8 : xmlFree (mem);
418 : }
419 : else
420 1 : return PSKC_UNKNOWN_OUTPUT_FORMAT;
421 :
422 12 : return PSKC_OK;
423 : }
|