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.20 2010/11/15 08:50:32 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 pgp_map_t packet_tag_map[] =
80 {
81 	{PGP_PTAG_CT_RESERVED, "Reserved"},
82 	{PGP_PTAG_CT_PK_SESSION_KEY, "Public-Key Encrypted Session Key"},
83 	{PGP_PTAG_CT_SIGNATURE, "Signature"},
84 	{PGP_PTAG_CT_SK_SESSION_KEY, "Symmetric-Key Encrypted Session Key"},
85 	{PGP_PTAG_CT_1_PASS_SIG, "One-Pass Signature"},
86 	{PGP_PTAG_CT_SECRET_KEY, "Secret Key"},
87 	{PGP_PTAG_CT_PUBLIC_KEY, "Public Key"},
88 	{PGP_PTAG_CT_SECRET_SUBKEY, "Secret Subkey"},
89 	{PGP_PTAG_CT_COMPRESSED, "Compressed Data"},
90 	{PGP_PTAG_CT_SE_DATA, "Symmetrically Encrypted Data"},
91 	{PGP_PTAG_CT_MARKER, "Marker"},
92 	{PGP_PTAG_CT_LITDATA, "Literal Data"},
93 	{PGP_PTAG_CT_TRUST, "Trust"},
94 	{PGP_PTAG_CT_USER_ID, "User ID"},
95 	{PGP_PTAG_CT_PUBLIC_SUBKEY, "Public Subkey"},
96 	{PGP_PTAG_CT_RESERVED2, "reserved2"},
97 	{PGP_PTAG_CT_RESERVED3, "reserved3"},
98 	{PGP_PTAG_CT_USER_ATTR, "User Attribute"},
99 	{PGP_PTAG_CT_SE_IP_DATA,
100 		"Symmetric Encrypted and Integrity Protected Data"},
101 	{PGP_PTAG_CT_MDC, "Modification Detection Code"},
102 	{PGP_PARSER_PTAG, "PGP_PARSER_PTAG"},
103 	{PGP_PTAG_RAW_SS, "PGP_PTAG_RAW_SS"},
104 	{PGP_PTAG_SS_ALL, "PGP_PTAG_SS_ALL"},
105 	{PGP_PARSER_PACKET_END, "PGP_PARSER_PACKET_END"},
106 	{PGP_PTAG_SIG_SUBPKT_BASE, "PGP_PTAG_SIG_SUBPKT_BASE"},
107 	{PGP_PTAG_SS_CREATION_TIME, "SS: Signature Creation Time"},
108 	{PGP_PTAG_SS_EXPIRATION_TIME, "SS: Signature Expiration Time"},
109 	{PGP_PTAG_SS_EXPORT_CERT, "SS: Exportable Certification"},
110 	{PGP_PTAG_SS_TRUST, "SS: Trust Signature"},
111 	{PGP_PTAG_SS_REGEXP, "SS: Regular Expression"},
112 	{PGP_PTAG_SS_REVOCABLE, "SS: Revocable"},
113 	{PGP_PTAG_SS_KEY_EXPIRY, "SS: Key Expiration Time"},
114 	{PGP_PTAG_SS_RESERVED, "SS: Reserved"},
115 	{PGP_PTAG_SS_PREFERRED_SKA, "SS: Preferred Secret Key Algorithm"},
116 	{PGP_PTAG_SS_REVOCATION_KEY, "SS: Revocation Key"},
117 	{PGP_PTAG_SS_ISSUER_KEY_ID, "SS: Issuer Key Id"},
118 	{PGP_PTAG_SS_NOTATION_DATA, "SS: Notation Data"},
119 	{PGP_PTAG_SS_PREFERRED_HASH, "SS: Preferred Hash Algorithm"},
120 	{PGP_PTAG_SS_PREF_COMPRESS, "SS: Preferred Compression Algorithm"},
121 	{PGP_PTAG_SS_KEYSERV_PREFS, "SS: Key Server Preferences"},
122 	{PGP_PTAG_SS_PREF_KEYSERV, "SS: Preferred Key Server"},
123 	{PGP_PTAG_SS_PRIMARY_USER_ID, "SS: Primary User ID"},
124 	{PGP_PTAG_SS_POLICY_URI, "SS: Policy URI"},
125 	{PGP_PTAG_SS_KEY_FLAGS, "SS: Key Flags"},
126 	{PGP_PTAG_SS_SIGNERS_USER_ID, "SS: Signer's User ID"},
127 	{PGP_PTAG_SS_REVOCATION_REASON, "SS: Reason for Revocation"},
128 	{PGP_PTAG_SS_FEATURES, "SS: Features"},
129 	{PGP_PTAG_SS_SIGNATURE_TARGET, "SS: Signature Target"},
130 	{PGP_PTAG_SS_EMBEDDED_SIGNATURE, "SS: Embedded Signature"},
131 
132 	{PGP_PTAG_CT_LITDATA_HEADER, "CT: Literal Data Header"},
133 	{PGP_PTAG_CT_LITDATA_BODY, "CT: Literal Data Body"},
134 	{PGP_PTAG_CT_SIGNATURE_HEADER, "CT: Signature Header"},
135 	{PGP_PTAG_CT_SIGNATURE_FOOTER, "CT: Signature Footer"},
136 	{PGP_PTAG_CT_ARMOUR_HEADER, "CT: Armour Header"},
137 	{PGP_PTAG_CT_ARMOUR_TRAILER, "CT: Armour Trailer"},
138 	{PGP_PTAG_CT_SIGNED_CLEARTEXT_HEADER, "CT: Signed Cleartext Header"},
139 	{PGP_PTAG_CT_SIGNED_CLEARTEXT_BODY, "CT: Signed Cleartext Body"},
140 	{PGP_PTAG_CT_SIGNED_CLEARTEXT_TRAILER, "CT: Signed Cleartext Trailer"},
141 	{PGP_PTAG_CT_UNARMOURED_TEXT, "CT: Unarmoured Text"},
142 	{PGP_PTAG_CT_ENCRYPTED_SECRET_KEY, "CT: Encrypted Secret Key"},
143 	{PGP_PTAG_CT_SE_DATA_HEADER, "CT: Sym Encrypted Data Header"},
144 	{PGP_PTAG_CT_SE_DATA_BODY, "CT: Sym Encrypted Data Body"},
145 	{PGP_PTAG_CT_SE_IP_DATA_HEADER, "CT: Sym Encrypted IP Data Header"},
146 	{PGP_PTAG_CT_SE_IP_DATA_BODY, "CT: Sym Encrypted IP Data Body"},
147 	{PGP_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, "CT: Encrypted PK Session Key"},
148 	{PGP_GET_PASSPHRASE, "CMD: Get Secret Key Passphrase"},
149 	{PGP_GET_SECKEY, "CMD: Get Secret Key"},
150 	{PGP_PARSER_ERROR, "PGP_PARSER_ERROR"},
151 	{PGP_PARSER_ERRCODE, "PGP_PARSER_ERRCODE"},
152 
153 	{0x00, NULL},		/* this is the end-of-array marker */
154 };
155 
156 static pgp_map_t ss_type_map[] =
157 {
158 	{PGP_PTAG_SS_CREATION_TIME, "Signature Creation Time"},
159 	{PGP_PTAG_SS_EXPIRATION_TIME, "Signature Expiration Time"},
160 	{PGP_PTAG_SS_TRUST, "Trust Signature"},
161 	{PGP_PTAG_SS_REGEXP, "Regular Expression"},
162 	{PGP_PTAG_SS_REVOCABLE, "Revocable"},
163 	{PGP_PTAG_SS_KEY_EXPIRY, "Key Expiration Time"},
164 	{PGP_PTAG_SS_PREFERRED_SKA, "Preferred Symmetric Algorithms"},
165 	{PGP_PTAG_SS_REVOCATION_KEY, "Revocation Key"},
166 	{PGP_PTAG_SS_ISSUER_KEY_ID, "Issuer key ID"},
167 	{PGP_PTAG_SS_NOTATION_DATA, "Notation Data"},
168 	{PGP_PTAG_SS_PREFERRED_HASH, "Preferred Hash Algorithms"},
169 	{PGP_PTAG_SS_PREF_COMPRESS, "Preferred Compression Algorithms"},
170 	{PGP_PTAG_SS_KEYSERV_PREFS, "Key Server Preferences"},
171 	{PGP_PTAG_SS_PREF_KEYSERV, "Preferred Key Server"},
172 	{PGP_PTAG_SS_PRIMARY_USER_ID, "Primary User ID"},
173 	{PGP_PTAG_SS_POLICY_URI, "Policy URI"},
174 	{PGP_PTAG_SS_KEY_FLAGS, "Key Flags"},
175 	{PGP_PTAG_SS_REVOCATION_REASON, "Reason for Revocation"},
176 	{PGP_PTAG_SS_FEATURES, "Features"},
177 	{0x00, NULL},		/* this is the end-of-array marker */
178 };
179 
180 
181 static pgp_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 pgp_map_t sig_type_map[] =
192 {
193 	{PGP_SIG_BINARY, "Signature of a binary document"},
194 	{PGP_SIG_TEXT, "Signature of a canonical text document"},
195 	{PGP_SIG_STANDALONE, "Standalone signature"},
196 	{PGP_CERT_GENERIC, "Generic certification of a User ID and Public Key packet"},
197 	{PGP_CERT_PERSONA, "Personal certification of a User ID and Public Key packet"},
198 	{PGP_CERT_CASUAL, "Casual certification of a User ID and Public Key packet"},
199 	{PGP_CERT_POSITIVE, "Positive certification of a User ID and Public Key packet"},
200 	{PGP_SIG_SUBKEY, "Subkey Binding Signature"},
201 	{PGP_SIG_PRIMARY, "Primary Key Binding Signature"},
202 	{PGP_SIG_DIRECT, "Signature directly on a key"},
203 	{PGP_SIG_REV_KEY, "Key revocation signature"},
204 	{PGP_SIG_REV_SUBKEY, "Subkey revocation signature"},
205 	{PGP_SIG_REV_CERT, "Certification revocation signature"},
206 	{PGP_SIG_TIMESTAMP, "Timestamp signature"},
207 	{PGP_SIG_3RD_PARTY, "Third-Party Confirmation signature"},
208 	{0x00, NULL},		/* this is the end-of-array marker */
209 };
210 
211 static pgp_map_t pubkey_alg_map[] =
212 {
213 	{PGP_PKA_RSA, "RSA (Encrypt or Sign)"},
214 	{PGP_PKA_RSA_ENCRYPT_ONLY, "RSA Encrypt-Only"},
215 	{PGP_PKA_RSA_SIGN_ONLY, "RSA Sign-Only"},
216 	{PGP_PKA_ELGAMAL, "Elgamal (Encrypt-Only)"},
217 	{PGP_PKA_DSA, "DSA"},
218 	{PGP_PKA_RESERVED_ELLIPTIC_CURVE, "Reserved for Elliptic Curve"},
219 	{PGP_PKA_RESERVED_ECDSA, "Reserved for ECDSA"},
220 	{PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN, "Reserved (formerly Elgamal Encrypt or Sign"},
221 	{PGP_PKA_RESERVED_DH, "Reserved for Diffie-Hellman (X9.42)"},
222 	{PGP_PKA_PRIVATE00, "Private/Experimental"},
223 	{PGP_PKA_PRIVATE01, "Private/Experimental"},
224 	{PGP_PKA_PRIVATE02, "Private/Experimental"},
225 	{PGP_PKA_PRIVATE03, "Private/Experimental"},
226 	{PGP_PKA_PRIVATE04, "Private/Experimental"},
227 	{PGP_PKA_PRIVATE05, "Private/Experimental"},
228 	{PGP_PKA_PRIVATE06, "Private/Experimental"},
229 	{PGP_PKA_PRIVATE07, "Private/Experimental"},
230 	{PGP_PKA_PRIVATE08, "Private/Experimental"},
231 	{PGP_PKA_PRIVATE09, "Private/Experimental"},
232 	{PGP_PKA_PRIVATE10, "Private/Experimental"},
233 	{0x00, NULL},		/* this is the end-of-array marker */
234 };
235 
236 static pgp_map_t symm_alg_map[] =
237 {
238 	{PGP_SA_PLAINTEXT, "Plaintext or unencrypted data"},
239 	{PGP_SA_IDEA, "IDEA"},
240 	{PGP_SA_TRIPLEDES, "TripleDES"},
241 	{PGP_SA_CAST5, "CAST5"},
242 	{PGP_SA_BLOWFISH, "Blowfish"},
243 	{PGP_SA_AES_128, "AES (128-bit key)"},
244 	{PGP_SA_AES_192, "AES (192-bit key)"},
245 	{PGP_SA_AES_256, "AES (256-bit key)"},
246 	{PGP_SA_TWOFISH, "Twofish(256-bit key)"},
247 	{PGP_SA_CAMELLIA_128, "Camellia (128-bit key)"},
248 	{PGP_SA_CAMELLIA_192, "Camellia (192-bit key)"},
249 	{PGP_SA_CAMELLIA_256, "Camellia (256-bit key)"},
250 	{0x00, NULL},		/* this is the end-of-array marker */
251 };
252 
253 static pgp_map_t hash_alg_map[] =
254 {
255 	{PGP_HASH_MD5, "MD5"},
256 	{PGP_HASH_SHA1, "SHA1"},
257 	{PGP_HASH_RIPEMD, "RIPEMD160"},
258 	{PGP_HASH_SHA256, "SHA256"},
259 	{PGP_HASH_SHA384, "SHA384"},
260 	{PGP_HASH_SHA512, "SHA512"},
261 	{PGP_HASH_SHA224, "SHA224"},
262 	{0x00, NULL},		/* this is the end-of-array marker */
263 };
264 
265 static pgp_map_t compression_alg_map[] =
266 {
267 	{PGP_C_NONE, "Uncompressed"},
268 	{PGP_C_ZIP, "ZIP(RFC1951)"},
269 	{PGP_C_ZLIB, "ZLIB(RFC1950)"},
270 	{PGP_C_BZIP2, "Bzip2(BZ2)"},
271 	{0x00, NULL},		/* this is the end-of-array marker */
272 };
273 
274 static pgp_bit_map_t ss_notation_map_byte0[] =
275 {
276 	{0x80, "Human-readable"},
277 	{0x00, NULL},
278 };
279 
280 static pgp_bit_map_t *ss_notation_map[] =
281 {
282 	ss_notation_map_byte0,
283 };
284 
285 static pgp_bit_map_t ss_feature_map_byte0[] =
286 {
287 	{0x01, "Modification Detection"},
288 	{0x00, NULL},
289 };
290 
291 static pgp_bit_map_t *ss_feature_map[] =
292 {
293 	ss_feature_map_byte0,
294 };
295 
296 static pgp_bit_map_t ss_key_flags_map[] =
297 {
298 	{0x01, "May be used to certify other keys"},
299 	{0x02, "May be used to sign data"},
300 	{0x04, "May be used to encrypt communications"},
301 	{0x08, "May be used to encrypt storage"},
302 	{0x10, "Private component may have been split by a secret-sharing mechanism"},
303 	{0x80, "Private component may be in possession of more than one person"},
304 	{0x00, NULL},
305 };
306 
307 static pgp_bit_map_t ss_key_server_prefs_map[] =
308 {
309 	{0x80, "Key holder requests that this key only be modified or updated by the key holder or an administrator of the key server"},
310 	{0x00, NULL},
311 };
312 
313 /*
314  * Private functions
315  */
316 
317 static void
318 list_init(pgp_list_t *list)
319 {
320 	list->size = 0;
321 	list->used = 0;
322 	list->strings = NULL;
323 }
324 
325 static void
326 list_free_strings(pgp_list_t *list)
327 {
328 	unsigned        i;
329 
330 	for (i = 0; i < list->used; i++) {
331 		free(list->strings[i]);
332 		list->strings[i] = NULL;
333 	}
334 }
335 
336 static void
337 list_free(pgp_list_t *list)
338 {
339 	if (list->strings)
340 		free(list->strings);
341 	list_init(list);
342 }
343 
344 static unsigned
345 list_resize(pgp_list_t *list)
346 {
347 	/*
348 	 * We only resize in one direction - upwards. Algorithm used : double
349 	 * the current size then add 1
350 	 */
351 	char	**newstrings;
352 	int	  newsize;
353 
354 	newsize = (list->size * 2) + 1;
355 	newstrings = realloc(list->strings, newsize * sizeof(char *));
356 	if (newstrings) {
357 		list->strings = newstrings;
358 		list->size = newsize;
359 		return 1;
360 	}
361 	(void) fprintf(stderr, "list_resize - bad alloc\n");
362 	return 0;
363 }
364 
365 static unsigned
366 add_str(pgp_list_t *list, const char *str)
367 {
368 	if (list->size == list->used && !list_resize(list)) {
369 		return 0;
370 	}
371 	list->strings[list->used++] = __UNCONST(str);
372 	return 1;
373 }
374 
375 /* find a bitfield in a map - serial search */
376 static const char *
377 find_bitfield(pgp_bit_map_t *map, uint8_t octet)
378 {
379 	pgp_bit_map_t  *row;
380 
381 	for (row = map; row->string != NULL && row->mask != octet ; row++) {
382 	}
383 	return (row->string) ? row->string : "Unknown";
384 }
385 
386 /* ! generic function to initialise pgp_text_t structure */
387 void
388 pgp_text_init(pgp_text_t *text)
389 {
390 	list_init(&text->known);
391 	list_init(&text->unknown);
392 }
393 
394 /**
395  * \ingroup Core_Print
396  *
397  * pgp_text_free() frees the memory used by an pgp_text_t structure
398  *
399  * \param text Pointer to a previously allocated structure. This structure and its contents will be freed.
400  */
401 void
402 pgp_text_free(pgp_text_t *text)
403 {
404 	/* Strings in "known" array will be constants, so don't free them */
405 	list_free(&text->known);
406 
407 	/*
408 	 * Strings in "unknown" array will be dynamically allocated, so do
409 	 * free them
410 	 */
411 	list_free_strings(&text->unknown);
412 	list_free(&text->unknown);
413 
414 	free(text);
415 }
416 
417 /* XXX: should this (and many others) be unsigned? */
418 /* ! generic function which adds text derived from single octet map to text */
419 static unsigned
420 add_str_from_octet_map(pgp_text_t *map, char *str, uint8_t octet)
421 {
422 	if (str && !add_str(&map->known, str)) {
423 		/*
424 		 * value recognised, but there was a problem adding it to the
425 		 * list
426 		 */
427 		/* XXX - should print out error msg here, Ben? - rachel */
428 		return 0;
429 	} else if (!str) {
430 		/*
431 		 * value not recognised and there was a problem adding it to
432 		 * the unknown list
433 		 */
434 		unsigned        len = 2 + 2 + 1;	/* 2 for "0x", 2 for
435 							 * single octet in hex
436 							 * format, 1 for NUL */
437 		if ((str = calloc(1, len)) == NULL) {
438 			(void) fprintf(stderr, "add_str_from_octet_map: bad alloc\n");
439 			return 0;
440 		}
441 		(void) snprintf(str, len, "0x%x", octet);
442 		if (!add_str(&map->unknown, str)) {
443 			return 0;
444 		}
445 		free(str);
446 	}
447 	return 1;
448 }
449 
450 /* ! generic function which adds text derived from single bit map to text */
451 static unsigned
452 add_bitmap_entry(pgp_text_t *map, const char *str, uint8_t bit)
453 {
454 	const char     *fmt_unknown = "Unknown bit(0x%x)";
455 
456 	if (str && !add_str(&map->known, str)) {
457 		/*
458 		 * value recognised, but there was a problem adding it to the
459 		 * list
460 		 */
461 		/* XXX - should print out error msg here, Ben? - rachel */
462 		return 0;
463 	} else if (!str) {
464 		/*
465 		 * value not recognised and there was a problem adding it to
466 		 * the unknown list
467 		 * 2 chars of the string are the format definition, this will
468 		 * be replaced in the output by 2 chars of hex, so the length
469 		 * will be correct
470 		 */
471 		unsigned         len = (unsigned)(strlen(fmt_unknown) + 1);
472 		char		*newstr;
473 
474 		if ((newstr = calloc(1, len)) == NULL) {
475 			(void) fprintf(stderr, "add_bitmap_entry: bad alloc\n");
476 			return 0;
477 		}
478 		(void) snprintf(newstr, len, fmt_unknown, bit);
479 		if (!add_str(&map->unknown, newstr)) {
480 			return 0;
481 		}
482 		free(newstr);
483 	}
484 	return 1;
485 }
486 
487 /**
488  * Produce a structure containing human-readable textstrings
489  * representing the recognised and unrecognised contents
490  * of this byte array. text_fn() will be called on each octet in turn.
491  * Each octet will generate one string representing the whole byte.
492  *
493  */
494 
495 static pgp_text_t *
496 text_from_bytemapped_octets(const pgp_data_t *data,
497 			    const char *(*text_fn)(uint8_t octet))
498 {
499 	pgp_text_t	*text;
500 	const char	*str;
501 	unsigned	 i;
502 
503 	/*
504 	 * ! allocate and initialise pgp_text_t structure to store derived
505 	 * strings
506 	 */
507 	if ((text = calloc(1, sizeof(*text))) == NULL) {
508 		return NULL;
509 	}
510 
511 	pgp_text_init(text);
512 
513 	/* ! for each octet in field ... */
514 	for (i = 0; i < data->len; i++) {
515 		/* ! derive string from octet */
516 		str = (*text_fn) (data->contents[i]);
517 
518 		/* ! and add to text */
519 		if (!add_str_from_octet_map(text, netpgp_strdup(str),
520 						data->contents[i])) {
521 			pgp_text_free(text);
522 			return NULL;
523 		}
524 	}
525 	/*
526 	 * ! All values have been added to either the known or the unknown
527 	 * list
528 	 */
529 	return text;
530 }
531 
532 /**
533  * Produce a structure containing human-readable textstrings
534  * representing the recognised and unrecognised contents
535  * of this byte array, derived from each bit of each octet.
536  *
537  */
538 static pgp_text_t *
539 showall_octets_bits(pgp_data_t *data, pgp_bit_map_t **map, size_t nmap)
540 {
541 	pgp_text_t	*text;
542 	const char	*str;
543 	unsigned         i;
544 	uint8_t		 mask, bit;
545 	int              j = 0;
546 
547 	/*
548 	 * ! allocate and initialise pgp_text_t structure to store derived
549 	 * strings
550 	 */
551 	if ((text = calloc(1, sizeof(pgp_text_t))) == NULL) {
552 		return NULL;
553 	}
554 
555 	pgp_text_init(text);
556 
557 	/* ! for each octet in field ... */
558 	for (i = 0; i < data->len; i++) {
559 		/* ! for each bit in octet ... */
560 		mask = 0x80;
561 		for (j = 0; j < 8; j++, mask = (unsigned)mask >> 1) {
562 			bit = data->contents[i] & mask;
563 			if (bit) {
564 				str = (i >= nmap) ? "Unknown" :
565 					find_bitfield(map[i], bit);
566 				if (!add_bitmap_entry(text, str, bit)) {
567 					pgp_text_free(text);
568 					return NULL;
569 				}
570 			}
571 		}
572 	}
573 	return text;
574 }
575 
576 /*
577  * Public Functions
578  */
579 
580 /**
581  * \ingroup Core_Print
582  * returns description of the Packet Tag
583  * \param packet_tag
584  * \return string or "Unknown"
585 */
586 const char     *
587 pgp_show_packet_tag(pgp_content_enum packet_tag)
588 {
589 	const char     *ret;
590 
591 	ret = pgp_str_from_map(packet_tag, packet_tag_map);
592 	if (!ret) {
593 		ret = "Unknown Tag";
594 	}
595 	return ret;
596 }
597 
598 /**
599  * \ingroup Core_Print
600  *
601  * returns description of the Signature Sub-Packet type
602  * \param ss_type Signature Sub-Packet type
603  * \return string or "Unknown"
604  */
605 const char     *
606 pgp_show_ss_type(pgp_content_enum ss_type)
607 {
608 	return pgp_str_from_map(ss_type, ss_type_map);
609 }
610 
611 /**
612  * \ingroup Core_Print
613  *
614  * returns description of the Revocation Reason code
615  * \param ss_rr_code Revocation Reason code
616  * \return string or "Unknown"
617  */
618 const char     *
619 pgp_show_ss_rr_code(pgp_ss_rr_code_t ss_rr_code)
620 {
621 	return pgp_str_from_map(ss_rr_code, ss_rr_code_map);
622 }
623 
624 /**
625  * \ingroup Core_Print
626  *
627  * returns description of the given Signature type
628  * \param sig_type Signature type
629  * \return string or "Unknown"
630  */
631 const char     *
632 pgp_show_sig_type(pgp_sig_type_t sig_type)
633 {
634 	return pgp_str_from_map(sig_type, sig_type_map);
635 }
636 
637 /**
638  * \ingroup Core_Print
639  *
640  * returns description of the given Public Key Algorithm
641  * \param pka Public Key Algorithm type
642  * \return string or "Unknown"
643  */
644 const char     *
645 pgp_show_pka(pgp_pubkey_alg_t pka)
646 {
647 	return pgp_str_from_map(pka, pubkey_alg_map);
648 }
649 
650 /**
651  * \ingroup Core_Print
652  * returns description of the Preferred Compression
653  * \param octet Preferred Compression
654  * \return string or "Unknown"
655 */
656 const char     *
657 pgp_show_ss_zpref(uint8_t octet)
658 {
659 	return pgp_str_from_map(octet, compression_alg_map);
660 }
661 
662 /**
663  * \ingroup Core_Print
664  *
665  * returns set of descriptions of the given Preferred Compression Algorithms
666  * \param ss_zpref Array of Preferred Compression Algorithms
667  * \return NULL if cannot allocate memory or other error
668  * \return pointer to structure, if no error
669  */
670 pgp_text_t     *
671 pgp_showall_ss_zpref(const pgp_data_t *ss_zpref)
672 {
673 	return text_from_bytemapped_octets(ss_zpref,
674 					&pgp_show_ss_zpref);
675 }
676 
677 
678 /**
679  * \ingroup Core_Print
680  *
681  * returns description of the Hash Algorithm type
682  * \param hash Hash Algorithm type
683  * \return string or "Unknown"
684  */
685 const char     *
686 pgp_show_hash_alg(uint8_t hash)
687 {
688 	return pgp_str_from_map(hash, hash_alg_map);
689 }
690 
691 /**
692  * \ingroup Core_Print
693  *
694  * returns set of descriptions of the given Preferred Hash Algorithms
695  * \param ss_hashpref Array of Preferred Hash Algorithms
696  * \return NULL if cannot allocate memory or other error
697  * \return pointer to structure, if no error
698  */
699 pgp_text_t     *
700 pgp_showall_ss_hashpref(const pgp_data_t *ss_hashpref)
701 {
702 	return text_from_bytemapped_octets(ss_hashpref,
703 					   &pgp_show_hash_alg);
704 }
705 
706 const char     *
707 pgp_show_symm_alg(uint8_t hash)
708 {
709 	return pgp_str_from_map(hash, symm_alg_map);
710 }
711 
712 /**
713  * \ingroup Core_Print
714  * returns description of the given Preferred Symmetric Key Algorithm
715  * \param octet
716  * \return string or "Unknown"
717 */
718 const char     *
719 pgp_show_ss_skapref(uint8_t octet)
720 {
721 	return pgp_str_from_map(octet, symm_alg_map);
722 }
723 
724 /**
725  * \ingroup Core_Print
726  *
727  * returns set of descriptions of the given Preferred Symmetric Key Algorithms
728  * \param ss_skapref Array of Preferred Symmetric Key Algorithms
729  * \return NULL if cannot allocate memory or other error
730  * \return pointer to structure, if no error
731  */
732 pgp_text_t     *
733 pgp_showall_ss_skapref(const pgp_data_t *ss_skapref)
734 {
735 	return text_from_bytemapped_octets(ss_skapref,
736 					   &pgp_show_ss_skapref);
737 }
738 
739 /**
740  * \ingroup Core_Print
741  * returns description of one SS Feature
742  * \param octet
743  * \return string or "Unknown"
744 */
745 static const char *
746 show_ss_feature(uint8_t octet, unsigned offset)
747 {
748 	if (offset >= PGP_ARRAY_SIZE(ss_feature_map)) {
749 		return "Unknown";
750 	}
751 	return find_bitfield(ss_feature_map[offset], octet);
752 }
753 
754 /**
755  * \ingroup Core_Print
756  *
757  * returns set of descriptions of the given SS Features
758  * \param ss_features Signature Sub-Packet Features
759  * \return NULL if cannot allocate memory or other error
760  * \return pointer to structure, if no error
761  */
762 /* XXX: shouldn't this use show_all_octets_bits? */
763 pgp_text_t     *
764 pgp_showall_ss_features(pgp_data_t ss_features)
765 {
766 	pgp_text_t	*text;
767 	const char	*str;
768 	unsigned	 i;
769 	uint8_t		 mask, bit;
770 	int		 j;
771 
772 	if ((text = calloc(1, sizeof(*text))) == NULL) {
773 		return NULL;
774 	}
775 
776 	pgp_text_init(text);
777 
778 	for (i = 0; i < ss_features.len; i++) {
779 		mask = 0x80;
780 		for (j = 0; j < 8; j++, mask = (unsigned)mask >> 1) {
781 			bit = ss_features.contents[i] & mask;
782 			if (bit) {
783 				str = show_ss_feature(bit, i);
784 				if (!add_bitmap_entry(text, str, bit)) {
785 					pgp_text_free(text);
786 					return NULL;
787 				}
788 			}
789 		}
790 	}
791 	return text;
792 }
793 
794 /**
795  * \ingroup Core_Print
796  * returns description of SS Key Flag
797  * \param octet
798  * \param map
799  * \return
800 */
801 const char     *
802 pgp_show_ss_key_flag(uint8_t octet, pgp_bit_map_t *map)
803 {
804 	return find_bitfield(map, octet);
805 }
806 
807 /**
808  * \ingroup Core_Print
809  *
810  * returns set of descriptions of the given Preferred Key Flags
811  * \param ss_key_flags Array of Key Flags
812  * \return NULL if cannot allocate memory or other error
813  * \return pointer to structure, if no error
814  */
815 pgp_text_t     *
816 pgp_showall_ss_key_flags(const pgp_data_t *ss_key_flags)
817 {
818 	pgp_text_t	*text;
819 	const char	*str;
820 	uint8_t		 mask, bit;
821 	int              i;
822 
823 	if ((text = calloc(1, sizeof(*text))) == NULL) {
824 		return NULL;
825 	}
826 
827 	pgp_text_init(text);
828 
829 	/* xxx - TBD: extend to handle multiple octets of bits - rachel */
830 	for (i = 0, mask = 0x80; i < 8; i++, mask = (unsigned)mask >> 1) {
831 		bit = ss_key_flags->contents[0] & mask;
832 		if (bit) {
833 			str = pgp_show_ss_key_flag(bit, ss_key_flags_map);
834 			if (!add_bitmap_entry(text, netpgp_strdup(str), bit)) {
835 				pgp_text_free(text);
836 				return NULL;
837 			}
838 		}
839 	}
840 	/*
841 	 * xxx - must add error text if more than one octet. Only one
842 	 * currently specified -- rachel
843 	 */
844 	return text;
845 }
846 
847 /**
848  * \ingroup Core_Print
849  *
850  * returns description of one given Key Server Preference
851  *
852  * \param prefs Byte containing bitfield of preferences
853  * \param map
854  * \return string or "Unknown"
855  */
856 const char     *
857 pgp_show_keyserv_pref(uint8_t prefs, pgp_bit_map_t *map)
858 {
859 	return find_bitfield(map, prefs);
860 }
861 
862 /**
863  * \ingroup Core_Print
864  * returns set of descriptions of given Key Server Preferences
865  * \param ss_key_server_prefs
866  * \return NULL if cannot allocate memory or other error
867  * \return pointer to structure, if no error
868  *
869 */
870 pgp_text_t     *
871 pgp_show_keyserv_prefs(const pgp_data_t *prefs)
872 {
873 	pgp_text_t	*text;
874 	const char	*str;
875 	uint8_t		 mask, bit;
876 	int              i = 0;
877 
878 	if ((text = calloc(1, sizeof(*text))) == NULL) {
879 		return NULL;
880 	}
881 
882 	pgp_text_init(text);
883 
884 	/* xxx - TBD: extend to handle multiple octets of bits - rachel */
885 
886 	for (i = 0, mask = 0x80; i < 8; i++, mask = (unsigned)mask >> 1) {
887 		bit = prefs->contents[0] & mask;
888 		if (bit) {
889 			str = pgp_show_keyserv_pref(bit,
890 						ss_key_server_prefs_map);
891 			if (!add_bitmap_entry(text, netpgp_strdup(str), bit)) {
892 				pgp_text_free(text);
893 				return NULL;
894 			}
895 		}
896 	}
897 	/*
898 	 * xxx - must add error text if more than one octet. Only one
899 	 * currently specified -- rachel
900 	 */
901 	return text;
902 }
903 
904 /**
905  * \ingroup Core_Print
906  *
907  * returns set of descriptions of the given SS Notation Data Flags
908  * \param ss_notation Signature Sub-Packet Notation Data
909  * \return NULL if cannot allocate memory or other error
910  * \return pointer to structure, if no error
911  */
912 pgp_text_t     *
913 pgp_showall_notation(pgp_ss_notation_t ss_notation)
914 {
915 	return showall_octets_bits(&ss_notation.flags,
916 				ss_notation_map,
917 				PGP_ARRAY_SIZE(ss_notation_map));
918 }
919