xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/packet-show.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*-
2  * Copyright (c) 2009 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by Alistair Crooks (agc@NetBSD.org)
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 /*
30  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31  * All rights reserved.
32  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33  * their moral rights under the UK Copyright Design and Patents Act 1988 to
34  * be recorded as the authors of this copyright work.
35  *
36  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37  * use this file except in compliance with the License.
38  *
39  * You may obtain a copy of the License at
40  *     http://www.apache.org/licenses/LICENSE-2.0
41  *
42  * Unless required by applicable law or agreed to in writing, software
43  * distributed under the License is distributed on an "AS IS" BASIS,
44  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
45  *
46  * See the License for the specific language governing permissions and
47  * limitations under the License.
48  */
49 
50 /** \file
51  *
52  * Creates printable text strings from packet contents
53  *
54  */
55 #include "config.h"
56 
57 #ifdef HAVE_SYS_CDEFS_H
58 #include <sys/cdefs.h>
59 #endif
60 
61 #if defined(__NetBSD__)
62 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
63 __RCSID("$NetBSD: packet-show.c,v 1.17 2010/08/15 16:36:24 agc Exp $");
64 #endif
65 
66 #include <stdlib.h>
67 #include <string.h>
68 
69 #include "packet-show.h"
70 
71 #include "netpgpsdk.h"
72 #include "netpgpdefs.h"
73 
74 
75 /*
76  * Arrays of value->text maps
77  */
78 
79 static __ops_map_t packet_tag_map[] =
80 {
81 	{OPS_PTAG_CT_RESERVED, "Reserved"},
82 	{OPS_PTAG_CT_PK_SESSION_KEY, "Public-Key Encrypted Session Key"},
83 	{OPS_PTAG_CT_SIGNATURE, "Signature"},
84 	{OPS_PTAG_CT_SK_SESSION_KEY, "Symmetric-Key Encrypted Session Key"},
85 	{OPS_PTAG_CT_1_PASS_SIG, "One-Pass Signature"},
86 	{OPS_PTAG_CT_SECRET_KEY, "Secret Key"},
87 	{OPS_PTAG_CT_PUBLIC_KEY, "Public Key"},
88 	{OPS_PTAG_CT_SECRET_SUBKEY, "Secret Subkey"},
89 	{OPS_PTAG_CT_COMPRESSED, "Compressed Data"},
90 	{OPS_PTAG_CT_SE_DATA, "Symmetrically Encrypted Data"},
91 	{OPS_PTAG_CT_MARKER, "Marker"},
92 	{OPS_PTAG_CT_LITDATA, "Literal Data"},
93 	{OPS_PTAG_CT_TRUST, "Trust"},
94 	{OPS_PTAG_CT_USER_ID, "User ID"},
95 	{OPS_PTAG_CT_PUBLIC_SUBKEY, "Public Subkey"},
96 	{OPS_PTAG_CT_RESERVED2, "reserved2"},
97 	{OPS_PTAG_CT_RESERVED3, "reserved3"},
98 	{OPS_PTAG_CT_USER_ATTR, "User Attribute"},
99 	{OPS_PTAG_CT_SE_IP_DATA,
100 		"Symmetric Encrypted and Integrity Protected Data"},
101 	{OPS_PTAG_CT_MDC, "Modification Detection Code"},
102 	{OPS_PARSER_PTAG, "OPS_PARSER_PTAG"},
103 	{OPS_PTAG_RAW_SS, "OPS_PTAG_RAW_SS"},
104 	{OPS_PTAG_SS_ALL, "OPS_PTAG_SS_ALL"},
105 	{OPS_PARSER_PACKET_END, "OPS_PARSER_PACKET_END"},
106 	{OPS_PTAG_SIG_SUBPKT_BASE, "OPS_PTAG_SIG_SUBPKT_BASE"},
107 	{OPS_PTAG_SS_CREATION_TIME, "SS: Signature Creation Time"},
108 	{OPS_PTAG_SS_EXPIRATION_TIME, "SS: Signature Expiration Time"},
109 	{OPS_PTAG_SS_EXPORT_CERT, "SS: Exportable Certification"},
110 	{OPS_PTAG_SS_TRUST, "SS: Trust Signature"},
111 	{OPS_PTAG_SS_REGEXP, "SS: Regular Expression"},
112 	{OPS_PTAG_SS_REVOCABLE, "SS: Revocable"},
113 	{OPS_PTAG_SS_KEY_EXPIRY, "SS: Key Expiration Time"},
114 	{OPS_PTAG_SS_RESERVED, "SS: Reserved"},
115 	{OPS_PTAG_SS_PREFERRED_SKA, "SS: Preferred Secret Key Algorithm"},
116 	{OPS_PTAG_SS_REVOCATION_KEY, "SS: Revocation Key"},
117 	{OPS_PTAG_SS_ISSUER_KEY_ID, "SS: Issuer Key Id"},
118 	{OPS_PTAG_SS_NOTATION_DATA, "SS: Notation Data"},
119 	{OPS_PTAG_SS_PREFERRED_HASH, "SS: Preferred Hash Algorithm"},
120 	{OPS_PTAG_SS_PREF_COMPRESS, "SS: Preferred Compression Algorithm"},
121 	{OPS_PTAG_SS_KEYSERV_PREFS, "SS: Key Server Preferences"},
122 	{OPS_PTAG_SS_PREF_KEYSERV, "SS: Preferred Key Server"},
123 	{OPS_PTAG_SS_PRIMARY_USER_ID, "SS: Primary User ID"},
124 	{OPS_PTAG_SS_POLICY_URI, "SS: Policy URI"},
125 	{OPS_PTAG_SS_KEY_FLAGS, "SS: Key Flags"},
126 	{OPS_PTAG_SS_SIGNERS_USER_ID, "SS: Signer's User ID"},
127 	{OPS_PTAG_SS_REVOCATION_REASON, "SS: Reason for Revocation"},
128 	{OPS_PTAG_SS_FEATURES, "SS: Features"},
129 	{OPS_PTAG_SS_SIGNATURE_TARGET, "SS: Signature Target"},
130 	{OPS_PTAG_SS_EMBEDDED_SIGNATURE, "SS: Embedded Signature"},
131 
132 	{OPS_PTAG_CT_LITDATA_HEADER, "CT: Literal Data Header"},
133 	{OPS_PTAG_CT_LITDATA_BODY, "CT: Literal Data Body"},
134 	{OPS_PTAG_CT_SIGNATURE_HEADER, "CT: Signature Header"},
135 	{OPS_PTAG_CT_SIGNATURE_FOOTER, "CT: Signature Footer"},
136 	{OPS_PTAG_CT_ARMOUR_HEADER, "CT: Armour Header"},
137 	{OPS_PTAG_CT_ARMOUR_TRAILER, "CT: Armour Trailer"},
138 	{OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER, "CT: Signed Cleartext Header"},
139 	{OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY, "CT: Signed Cleartext Body"},
140 	{OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER, "CT: Signed Cleartext Trailer"},
141 	{OPS_PTAG_CT_UNARMOURED_TEXT, "CT: Unarmoured Text"},
142 	{OPS_PTAG_CT_ENCRYPTED_SECRET_KEY, "CT: Encrypted Secret Key"},
143 	{OPS_PTAG_CT_SE_DATA_HEADER, "CT: Sym Encrypted Data Header"},
144 	{OPS_PTAG_CT_SE_DATA_BODY, "CT: Sym Encrypted Data Body"},
145 	{OPS_PTAG_CT_SE_IP_DATA_HEADER, "CT: Sym Encrypted IP Data Header"},
146 	{OPS_PTAG_CT_SE_IP_DATA_BODY, "CT: Sym Encrypted IP Data Body"},
147 	{OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, "CT: Encrypted PK Session Key"},
148 	{OPS_GET_PASSPHRASE, "CMD: Get Secret Key Passphrase"},
149 	{OPS_GET_SECKEY, "CMD: Get Secret Key"},
150 	{OPS_PARSER_ERROR, "OPS_PARSER_ERROR"},
151 	{OPS_PARSER_ERRCODE, "OPS_PARSER_ERRCODE"},
152 
153 	{0x00, NULL},		/* this is the end-of-array marker */
154 };
155 
156 static __ops_map_t ss_type_map[] =
157 {
158 	{OPS_PTAG_SS_CREATION_TIME, "Signature Creation Time"},
159 	{OPS_PTAG_SS_EXPIRATION_TIME, "Signature Expiration Time"},
160 	{OPS_PTAG_SS_TRUST, "Trust Signature"},
161 	{OPS_PTAG_SS_REGEXP, "Regular Expression"},
162 	{OPS_PTAG_SS_REVOCABLE, "Revocable"},
163 	{OPS_PTAG_SS_KEY_EXPIRY, "Key Expiration Time"},
164 	{OPS_PTAG_SS_PREFERRED_SKA, "Preferred Symmetric Algorithms"},
165 	{OPS_PTAG_SS_REVOCATION_KEY, "Revocation Key"},
166 	{OPS_PTAG_SS_ISSUER_KEY_ID, "Issuer key ID"},
167 	{OPS_PTAG_SS_NOTATION_DATA, "Notation Data"},
168 	{OPS_PTAG_SS_PREFERRED_HASH, "Preferred Hash Algorithms"},
169 	{OPS_PTAG_SS_PREF_COMPRESS, "Preferred Compression Algorithms"},
170 	{OPS_PTAG_SS_KEYSERV_PREFS, "Key Server Preferences"},
171 	{OPS_PTAG_SS_PREF_KEYSERV, "Preferred Key Server"},
172 	{OPS_PTAG_SS_PRIMARY_USER_ID, "Primary User ID"},
173 	{OPS_PTAG_SS_POLICY_URI, "Policy URI"},
174 	{OPS_PTAG_SS_KEY_FLAGS, "Key Flags"},
175 	{OPS_PTAG_SS_REVOCATION_REASON, "Reason for Revocation"},
176 	{OPS_PTAG_SS_FEATURES, "Features"},
177 	{0x00, NULL},		/* this is the end-of-array marker */
178 };
179 
180 
181 static __ops_map_t ss_rr_code_map[] =
182 {
183 	{0x00, "No reason specified"},
184 	{0x01, "Key is superseded"},
185 	{0x02, "Key material has been compromised"},
186 	{0x03, "Key is retired and no longer used"},
187 	{0x20, "User ID information is no longer valid"},
188 	{0x00, NULL},		/* this is the end-of-array marker */
189 };
190 
191 static __ops_map_t sig_type_map[] =
192 {
193 	{OPS_SIG_BINARY, "Signature of a binary document"},
194 	{OPS_SIG_TEXT, "Signature of a canonical text document"},
195 	{OPS_SIG_STANDALONE, "Standalone signature"},
196 	{OPS_CERT_GENERIC, "Generic certification of a User ID and Public Key packet"},
197 	{OPS_CERT_PERSONA, "Personal certification of a User ID and Public Key packet"},
198 	{OPS_CERT_CASUAL, "Casual certification of a User ID and Public Key packet"},
199 	{OPS_CERT_POSITIVE, "Positive certification of a User ID and Public Key packet"},
200 	{OPS_SIG_SUBKEY, "Subkey Binding Signature"},
201 	{OPS_SIG_PRIMARY, "Primary Key Binding Signature"},
202 	{OPS_SIG_DIRECT, "Signature directly on a key"},
203 	{OPS_SIG_REV_KEY, "Key revocation signature"},
204 	{OPS_SIG_REV_SUBKEY, "Subkey revocation signature"},
205 	{OPS_SIG_REV_CERT, "Certification revocation signature"},
206 	{OPS_SIG_TIMESTAMP, "Timestamp signature"},
207 	{OPS_SIG_3RD_PARTY, "Third-Party Confirmation signature"},
208 	{0x00, NULL},		/* this is the end-of-array marker */
209 };
210 
211 static __ops_map_t pubkey_alg_map[] =
212 {
213 	{OPS_PKA_RSA, "RSA (Encrypt or Sign)"},
214 	{OPS_PKA_RSA_ENCRYPT_ONLY, "RSA Encrypt-Only"},
215 	{OPS_PKA_RSA_SIGN_ONLY, "RSA Sign-Only"},
216 	{OPS_PKA_ELGAMAL, "Elgamal (Encrypt-Only)"},
217 	{OPS_PKA_DSA, "DSA"},
218 	{OPS_PKA_RESERVED_ELLIPTIC_CURVE, "Reserved for Elliptic Curve"},
219 	{OPS_PKA_RESERVED_ECDSA, "Reserved for ECDSA"},
220 	{OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN, "Reserved (formerly Elgamal Encrypt or Sign"},
221 	{OPS_PKA_RESERVED_DH, "Reserved for Diffie-Hellman (X9.42)"},
222 	{OPS_PKA_PRIVATE00, "Private/Experimental"},
223 	{OPS_PKA_PRIVATE01, "Private/Experimental"},
224 	{OPS_PKA_PRIVATE02, "Private/Experimental"},
225 	{OPS_PKA_PRIVATE03, "Private/Experimental"},
226 	{OPS_PKA_PRIVATE04, "Private/Experimental"},
227 	{OPS_PKA_PRIVATE05, "Private/Experimental"},
228 	{OPS_PKA_PRIVATE06, "Private/Experimental"},
229 	{OPS_PKA_PRIVATE07, "Private/Experimental"},
230 	{OPS_PKA_PRIVATE08, "Private/Experimental"},
231 	{OPS_PKA_PRIVATE09, "Private/Experimental"},
232 	{OPS_PKA_PRIVATE10, "Private/Experimental"},
233 	{0x00, NULL},		/* this is the end-of-array marker */
234 };
235 
236 static __ops_map_t symm_alg_map[] =
237 {
238 	{OPS_SA_PLAINTEXT, "Plaintext or unencrypted data"},
239 	{OPS_SA_IDEA, "IDEA"},
240 	{OPS_SA_TRIPLEDES, "TripleDES"},
241 	{OPS_SA_CAST5, "CAST5"},
242 	{OPS_SA_BLOWFISH, "Blowfish"},
243 	{OPS_SA_AES_128, "AES (128-bit key)"},
244 	{OPS_SA_AES_192, "AES (192-bit key)"},
245 	{OPS_SA_AES_256, "AES (256-bit key)"},
246 	{OPS_SA_TWOFISH, "Twofish(256-bit key)"},
247 	{0x00, NULL},		/* this is the end-of-array marker */
248 };
249 
250 static __ops_map_t hash_alg_map[] =
251 {
252 	{OPS_HASH_MD5, "MD5"},
253 	{OPS_HASH_SHA1, "SHA1"},
254 	{OPS_HASH_RIPEMD, "RIPEMD160"},
255 	{OPS_HASH_SHA256, "SHA256"},
256 	{OPS_HASH_SHA384, "SHA384"},
257 	{OPS_HASH_SHA512, "SHA512"},
258 	{OPS_HASH_SHA224, "SHA224"},
259 	{0x00, NULL},		/* this is the end-of-array marker */
260 };
261 
262 static __ops_map_t compression_alg_map[] =
263 {
264 	{OPS_C_NONE, "Uncompressed"},
265 	{OPS_C_ZIP, "ZIP(RFC1951)"},
266 	{OPS_C_ZLIB, "ZLIB(RFC1950)"},
267 	{OPS_C_BZIP2, "Bzip2(BZ2)"},
268 	{0x00, NULL},		/* this is the end-of-array marker */
269 };
270 
271 static __ops_bit_map_t ss_notation_map_byte0[] =
272 {
273 	{0x80, "Human-readable"},
274 	{0x00, NULL},
275 };
276 
277 static __ops_bit_map_t *ss_notation_map[] =
278 {
279 	ss_notation_map_byte0,
280 };
281 
282 static __ops_bit_map_t ss_feature_map_byte0[] =
283 {
284 	{0x01, "Modification Detection"},
285 	{0x00, NULL},
286 };
287 
288 static __ops_bit_map_t *ss_feature_map[] =
289 {
290 	ss_feature_map_byte0,
291 };
292 
293 static __ops_bit_map_t ss_key_flags_map[] =
294 {
295 	{0x01, "May be used to certify other keys"},
296 	{0x02, "May be used to sign data"},
297 	{0x04, "May be used to encrypt communications"},
298 	{0x08, "May be used to encrypt storage"},
299 	{0x10, "Private component may have been split by a secret-sharing mechanism"},
300 	{0x80, "Private component may be in possession of more than one person"},
301 	{0x00, NULL},
302 };
303 
304 static __ops_bit_map_t ss_key_server_prefs_map[] =
305 {
306 	{0x80, "Key holder requests that this key only be modified or updated by the key holder or an administrator of the key server"},
307 	{0x00, NULL},
308 };
309 
310 /*
311  * Private functions
312  */
313 
314 static void
315 list_init(__ops_list_t *list)
316 {
317 	list->size = 0;
318 	list->used = 0;
319 	list->strings = NULL;
320 }
321 
322 static void
323 list_free_strings(__ops_list_t *list)
324 {
325 	unsigned        i;
326 
327 	for (i = 0; i < list->used; i++) {
328 		free(list->strings[i]);
329 		list->strings[i] = NULL;
330 	}
331 }
332 
333 static void
334 list_free(__ops_list_t *list)
335 {
336 	if (list->strings)
337 		free(list->strings);
338 	list_init(list);
339 }
340 
341 static unsigned
342 list_resize(__ops_list_t *list)
343 {
344 	/*
345 	 * We only resize in one direction - upwards. Algorithm used : double
346 	 * the current size then add 1
347 	 */
348 	char	**newstrings;
349 	int	  newsize;
350 
351 	newsize = (list->size * 2) + 1;
352 	newstrings = realloc(list->strings, newsize * sizeof(char *));
353 	if (newstrings) {
354 		list->strings = newstrings;
355 		list->size = newsize;
356 		return 1;
357 	}
358 	(void) fprintf(stderr, "list_resize - bad alloc\n");
359 	return 0;
360 }
361 
362 static unsigned
363 add_str(__ops_list_t *list, const char *str)
364 {
365 	if (list->size == list->used && !list_resize(list)) {
366 		return 0;
367 	}
368 	list->strings[list->used++] = __UNCONST(str);
369 	return 1;
370 }
371 
372 /* find a bitfield in a map - serial search */
373 static const char *
374 find_bitfield(__ops_bit_map_t *map, uint8_t octet)
375 {
376 	__ops_bit_map_t  *row;
377 
378 	for (row = map; row->string != NULL && row->mask != octet ; row++) {
379 	}
380 	return (row->string) ? row->string : "Unknown";
381 }
382 
383 /* ! generic function to initialise __ops_text_t structure */
384 void
385 __ops_text_init(__ops_text_t *text)
386 {
387 	list_init(&text->known);
388 	list_init(&text->unknown);
389 }
390 
391 /**
392  * \ingroup Core_Print
393  *
394  * __ops_text_free() frees the memory used by an __ops_text_t structure
395  *
396  * \param text Pointer to a previously allocated structure. This structure and its contents will be freed.
397  */
398 void
399 __ops_text_free(__ops_text_t *text)
400 {
401 	/* Strings in "known" array will be constants, so don't free them */
402 	list_free(&text->known);
403 
404 	/*
405 	 * Strings in "unknown" array will be dynamically allocated, so do
406 	 * free them
407 	 */
408 	list_free_strings(&text->unknown);
409 	list_free(&text->unknown);
410 
411 	free(text);
412 }
413 
414 /* XXX: should this (and many others) be unsigned? */
415 /* ! generic function which adds text derived from single octet map to text */
416 static unsigned
417 add_str_from_octet_map(__ops_text_t *map, char *str, uint8_t octet)
418 {
419 	if (str && !add_str(&map->known, str)) {
420 		/*
421 		 * value recognised, but there was a problem adding it to the
422 		 * list
423 		 */
424 		/* XXX - should print out error msg here, Ben? - rachel */
425 		return 0;
426 	} else if (!str) {
427 		/*
428 		 * value not recognised and there was a problem adding it to
429 		 * the unknown list
430 		 */
431 		unsigned        len = 2 + 2 + 1;	/* 2 for "0x", 2 for
432 							 * single octet in hex
433 							 * format, 1 for NUL */
434 		if ((str = calloc(1, len)) == NULL) {
435 			(void) fprintf(stderr, "add_str_from_octet_map: bad alloc\n");
436 			return 0;
437 		}
438 		(void) snprintf(str, len, "0x%x", octet);
439 		if (!add_str(&map->unknown, str)) {
440 			return 0;
441 		}
442 		free(str);
443 	}
444 	return 1;
445 }
446 
447 /* ! generic function which adds text derived from single bit map to text */
448 static unsigned
449 add_bitmap_entry(__ops_text_t *map, const char *str, uint8_t bit)
450 {
451 	const char     *fmt_unknown = "Unknown bit(0x%x)";
452 
453 	if (str && !add_str(&map->known, str)) {
454 		/*
455 		 * value recognised, but there was a problem adding it to the
456 		 * list
457 		 */
458 		/* XXX - should print out error msg here, Ben? - rachel */
459 		return 0;
460 	} else if (!str) {
461 		/*
462 		 * value not recognised and there was a problem adding it to
463 		 * the unknown list
464 		 * 2 chars of the string are the format definition, this will
465 		 * be replaced in the output by 2 chars of hex, so the length
466 		 * will be correct
467 		 */
468 		unsigned         len = (unsigned)(strlen(fmt_unknown) + 1);
469 		char		*newstr;
470 
471 		if ((newstr = calloc(1, len)) == NULL) {
472 			(void) fprintf(stderr, "add_bitmap_entry: bad alloc\n");
473 			return 0;
474 		}
475 		(void) snprintf(newstr, len, fmt_unknown, bit);
476 		if (!add_str(&map->unknown, newstr)) {
477 			return 0;
478 		}
479 		free(newstr);
480 	}
481 	return 1;
482 }
483 
484 /**
485  * Produce a structure containing human-readable textstrings
486  * representing the recognised and unrecognised contents
487  * of this byte array. text_fn() will be called on each octet in turn.
488  * Each octet will generate one string representing the whole byte.
489  *
490  */
491 
492 static __ops_text_t *
493 text_from_bytemapped_octets(const __ops_data_t *data,
494 			    const char *(*text_fn)(uint8_t octet))
495 {
496 	__ops_text_t	*text;
497 	const char	*str;
498 	unsigned	 i;
499 
500 	/*
501 	 * ! allocate and initialise __ops_text_t structure to store derived
502 	 * strings
503 	 */
504 	if ((text = calloc(1, sizeof(*text))) == NULL) {
505 		return NULL;
506 	}
507 
508 	__ops_text_init(text);
509 
510 	/* ! for each octet in field ... */
511 	for (i = 0; i < data->len; i++) {
512 		/* ! derive string from octet */
513 		str = (*text_fn) (data->contents[i]);
514 
515 		/* ! and add to text */
516 		if (!add_str_from_octet_map(text, netpgp_strdup(str),
517 						data->contents[i])) {
518 			__ops_text_free(text);
519 			return NULL;
520 		}
521 	}
522 	/*
523 	 * ! All values have been added to either the known or the unknown
524 	 * list
525 	 */
526 	return text;
527 }
528 
529 /**
530  * Produce a structure containing human-readable textstrings
531  * representing the recognised and unrecognised contents
532  * of this byte array, derived from each bit of each octet.
533  *
534  */
535 static __ops_text_t *
536 showall_octets_bits(__ops_data_t *data, __ops_bit_map_t **map, size_t nmap)
537 {
538 	__ops_text_t	*text;
539 	const char	*str;
540 	unsigned         i;
541 	uint8_t		 mask, bit;
542 	int              j = 0;
543 
544 	/*
545 	 * ! allocate and initialise __ops_text_t structure to store derived
546 	 * strings
547 	 */
548 	if ((text = calloc(1, sizeof(__ops_text_t))) == NULL) {
549 		return NULL;
550 	}
551 
552 	__ops_text_init(text);
553 
554 	/* ! for each octet in field ... */
555 	for (i = 0; i < data->len; i++) {
556 		/* ! for each bit in octet ... */
557 		mask = 0x80;
558 		for (j = 0; j < 8; j++, mask = (unsigned)mask >> 1) {
559 			bit = data->contents[i] & mask;
560 			if (bit) {
561 				str = (i >= nmap) ? "Unknown" :
562 					find_bitfield(map[i], bit);
563 				if (!add_bitmap_entry(text, str, bit)) {
564 					__ops_text_free(text);
565 					return NULL;
566 				}
567 			}
568 		}
569 	}
570 	return text;
571 }
572 
573 /*
574  * Public Functions
575  */
576 
577 /**
578  * \ingroup Core_Print
579  * returns description of the Packet Tag
580  * \param packet_tag
581  * \return string or "Unknown"
582 */
583 const char     *
584 __ops_show_packet_tag(__ops_content_enum packet_tag)
585 {
586 	const char     *ret;
587 
588 	ret = __ops_str_from_map(packet_tag, packet_tag_map);
589 	if (!ret) {
590 		ret = "Unknown Tag";
591 	}
592 	return ret;
593 }
594 
595 /**
596  * \ingroup Core_Print
597  *
598  * returns description of the Signature Sub-Packet type
599  * \param ss_type Signature Sub-Packet type
600  * \return string or "Unknown"
601  */
602 const char     *
603 __ops_show_ss_type(__ops_content_enum ss_type)
604 {
605 	return __ops_str_from_map(ss_type, ss_type_map);
606 }
607 
608 /**
609  * \ingroup Core_Print
610  *
611  * returns description of the Revocation Reason code
612  * \param ss_rr_code Revocation Reason code
613  * \return string or "Unknown"
614  */
615 const char     *
616 __ops_show_ss_rr_code(__ops_ss_rr_code_t ss_rr_code)
617 {
618 	return __ops_str_from_map(ss_rr_code, ss_rr_code_map);
619 }
620 
621 /**
622  * \ingroup Core_Print
623  *
624  * returns description of the given Signature type
625  * \param sig_type Signature type
626  * \return string or "Unknown"
627  */
628 const char     *
629 __ops_show_sig_type(__ops_sig_type_t sig_type)
630 {
631 	return __ops_str_from_map(sig_type, sig_type_map);
632 }
633 
634 /**
635  * \ingroup Core_Print
636  *
637  * returns description of the given Public Key Algorithm
638  * \param pka Public Key Algorithm type
639  * \return string or "Unknown"
640  */
641 const char     *
642 __ops_show_pka(__ops_pubkey_alg_t pka)
643 {
644 	return __ops_str_from_map(pka, pubkey_alg_map);
645 }
646 
647 /**
648  * \ingroup Core_Print
649  * returns description of the Preferred Compression
650  * \param octet Preferred Compression
651  * \return string or "Unknown"
652 */
653 const char     *
654 __ops_show_ss_zpref(uint8_t octet)
655 {
656 	return __ops_str_from_map(octet, compression_alg_map);
657 }
658 
659 /**
660  * \ingroup Core_Print
661  *
662  * returns set of descriptions of the given Preferred Compression Algorithms
663  * \param ss_zpref Array of Preferred Compression Algorithms
664  * \return NULL if cannot allocate memory or other error
665  * \return pointer to structure, if no error
666  */
667 __ops_text_t     *
668 __ops_showall_ss_zpref(const __ops_data_t *ss_zpref)
669 {
670 	return text_from_bytemapped_octets(ss_zpref,
671 					&__ops_show_ss_zpref);
672 }
673 
674 
675 /**
676  * \ingroup Core_Print
677  *
678  * returns description of the Hash Algorithm type
679  * \param hash Hash Algorithm type
680  * \return string or "Unknown"
681  */
682 const char     *
683 __ops_show_hash_alg(uint8_t hash)
684 {
685 	return __ops_str_from_map(hash, hash_alg_map);
686 }
687 
688 /**
689  * \ingroup Core_Print
690  *
691  * returns set of descriptions of the given Preferred Hash Algorithms
692  * \param ss_hashpref Array of Preferred Hash Algorithms
693  * \return NULL if cannot allocate memory or other error
694  * \return pointer to structure, if no error
695  */
696 __ops_text_t     *
697 __ops_showall_ss_hashpref(const __ops_data_t *ss_hashpref)
698 {
699 	return text_from_bytemapped_octets(ss_hashpref,
700 					   &__ops_show_hash_alg);
701 }
702 
703 const char     *
704 __ops_show_symm_alg(uint8_t hash)
705 {
706 	return __ops_str_from_map(hash, symm_alg_map);
707 }
708 
709 /**
710  * \ingroup Core_Print
711  * returns description of the given Preferred Symmetric Key Algorithm
712  * \param octet
713  * \return string or "Unknown"
714 */
715 const char     *
716 __ops_show_ss_skapref(uint8_t octet)
717 {
718 	return __ops_str_from_map(octet, symm_alg_map);
719 }
720 
721 /**
722  * \ingroup Core_Print
723  *
724  * returns set of descriptions of the given Preferred Symmetric Key Algorithms
725  * \param ss_skapref Array of Preferred Symmetric Key Algorithms
726  * \return NULL if cannot allocate memory or other error
727  * \return pointer to structure, if no error
728  */
729 __ops_text_t     *
730 __ops_showall_ss_skapref(const __ops_data_t *ss_skapref)
731 {
732 	return text_from_bytemapped_octets(ss_skapref,
733 					   &__ops_show_ss_skapref);
734 }
735 
736 /**
737  * \ingroup Core_Print
738  * returns description of one SS Feature
739  * \param octet
740  * \return string or "Unknown"
741 */
742 static const char *
743 __ops_show_ss_feature(uint8_t octet, unsigned offset)
744 {
745 	if (offset >= OPS_ARRAY_SIZE(ss_feature_map)) {
746 		return "Unknown";
747 	}
748 	return find_bitfield(ss_feature_map[offset], octet);
749 }
750 
751 /**
752  * \ingroup Core_Print
753  *
754  * returns set of descriptions of the given SS Features
755  * \param ss_features Signature Sub-Packet Features
756  * \return NULL if cannot allocate memory or other error
757  * \return pointer to structure, if no error
758  */
759 /* XXX: shouldn't this use show_all_octets_bits? */
760 __ops_text_t     *
761 __ops_showall_ss_features(__ops_data_t ss_features)
762 {
763 	__ops_text_t	*text;
764 	const char	*str;
765 	unsigned	 i;
766 	uint8_t		 mask, bit;
767 	int		 j;
768 
769 	if ((text = calloc(1, sizeof(*text))) == NULL) {
770 		return NULL;
771 	}
772 
773 	__ops_text_init(text);
774 
775 	for (i = 0; i < ss_features.len; i++) {
776 		mask = 0x80;
777 		for (j = 0; j < 8; j++, mask = (unsigned)mask >> 1) {
778 			bit = ss_features.contents[i] & mask;
779 			if (bit) {
780 				str = __ops_show_ss_feature(bit, i);
781 				if (!add_bitmap_entry(text, str, bit)) {
782 					__ops_text_free(text);
783 					return NULL;
784 				}
785 			}
786 		}
787 	}
788 	return text;
789 }
790 
791 /**
792  * \ingroup Core_Print
793  * returns description of SS Key Flag
794  * \param octet
795  * \param map
796  * \return
797 */
798 const char     *
799 __ops_show_ss_key_flag(uint8_t octet, __ops_bit_map_t *map)
800 {
801 	return find_bitfield(map, octet);
802 }
803 
804 /**
805  * \ingroup Core_Print
806  *
807  * returns set of descriptions of the given Preferred Key Flags
808  * \param ss_key_flags Array of Key Flags
809  * \return NULL if cannot allocate memory or other error
810  * \return pointer to structure, if no error
811  */
812 __ops_text_t     *
813 __ops_showall_ss_key_flags(const __ops_data_t *ss_key_flags)
814 {
815 	__ops_text_t	*text;
816 	const char	*str;
817 	uint8_t		 mask, bit;
818 	int              i;
819 
820 	if ((text = calloc(1, sizeof(*text))) == NULL) {
821 		return NULL;
822 	}
823 
824 	__ops_text_init(text);
825 
826 	/* xxx - TBD: extend to handle multiple octets of bits - rachel */
827 	for (i = 0, mask = 0x80; i < 8; i++, mask = (unsigned)mask >> 1) {
828 		bit = ss_key_flags->contents[0] & mask;
829 		if (bit) {
830 			str = __ops_show_ss_key_flag(bit, ss_key_flags_map);
831 			if (!add_bitmap_entry(text, netpgp_strdup(str), bit)) {
832 				__ops_text_free(text);
833 				return NULL;
834 			}
835 		}
836 	}
837 	/*
838 	 * xxx - must add error text if more than one octet. Only one
839 	 * currently specified -- rachel
840 	 */
841 	return text;
842 }
843 
844 /**
845  * \ingroup Core_Print
846  *
847  * returns description of one given Key Server Preference
848  *
849  * \param prefs Byte containing bitfield of preferences
850  * \param map
851  * \return string or "Unknown"
852  */
853 const char     *
854 __ops_show_keyserv_pref(uint8_t prefs, __ops_bit_map_t *map)
855 {
856 	return find_bitfield(map, prefs);
857 }
858 
859 /**
860  * \ingroup Core_Print
861  * returns set of descriptions of given Key Server Preferences
862  * \param ss_key_server_prefs
863  * \return NULL if cannot allocate memory or other error
864  * \return pointer to structure, if no error
865  *
866 */
867 __ops_text_t     *
868 __ops_show_keyserv_prefs(const __ops_data_t *prefs)
869 {
870 	__ops_text_t	*text;
871 	const char	*str;
872 	uint8_t		 mask, bit;
873 	int              i = 0;
874 
875 	if ((text = calloc(1, sizeof(*text))) == NULL) {
876 		return NULL;
877 	}
878 
879 	__ops_text_init(text);
880 
881 	/* xxx - TBD: extend to handle multiple octets of bits - rachel */
882 
883 	for (i = 0, mask = 0x80; i < 8; i++, mask = (unsigned)mask >> 1) {
884 		bit = prefs->contents[0] & mask;
885 		if (bit) {
886 			str = __ops_show_keyserv_pref(bit,
887 						ss_key_server_prefs_map);
888 			if (!add_bitmap_entry(text, netpgp_strdup(str), bit)) {
889 				__ops_text_free(text);
890 				return NULL;
891 			}
892 		}
893 	}
894 	/*
895 	 * xxx - must add error text if more than one octet. Only one
896 	 * currently specified -- rachel
897 	 */
898 	return text;
899 }
900 
901 /**
902  * \ingroup Core_Print
903  *
904  * returns set of descriptions of the given SS Notation Data Flags
905  * \param ss_notation Signature Sub-Packet Notation Data
906  * \return NULL if cannot allocate memory or other error
907  * \return pointer to structure, if no error
908  */
909 __ops_text_t     *
910 __ops_showall_notation(__ops_ss_notation_t ss_notation)
911 {
912 	return showall_octets_bits(&ss_notation.flags,
913 				ss_notation_map,
914 				OPS_ARRAY_SIZE(ss_notation_map));
915 }
916