xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/packet-show.c (revision 648b5a9919b5145bc84b46ae7369f9ff766ac9e7)
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.8 2009/05/21 00:33:31 agc Exp $");
64 #endif
65 
66 #include <stdlib.h>
67 #include <string.h>
68 
69 #include "packet-show.h"
70 
71 #include "netpgpdefs.h"
72 
73 
74 /*
75  * Arrays of value->text maps
76  */
77 
78 static __ops_map_t packet_tag_map[] =
79 {
80 	{OPS_PTAG_CT_RESERVED, "Reserved"},
81 	{OPS_PTAG_CT_PK_SESSION_KEY, "Public-Key Encrypted Session Key"},
82 	{OPS_PTAG_CT_SIGNATURE, "Signature"},
83 	{OPS_PTAG_CT_SK_SESSION_KEY, "Symmetric-Key Encrypted Session Key"},
84 	{OPS_PTAG_CT_1_PASS_SIG, "One-Pass Signature"},
85 	{OPS_PTAG_CT_SECRET_KEY, "Secret Key"},
86 	{OPS_PTAG_CT_PUBLIC_KEY, "Public Key"},
87 	{OPS_PTAG_CT_SECRET_SUBKEY, "Secret Subkey"},
88 	{OPS_PTAG_CT_COMPRESSED, "Compressed Data"},
89 	{OPS_PTAG_CT_SE_DATA, "Symmetrically Encrypted Data"},
90 	{OPS_PTAG_CT_MARKER, "Marker"},
91 	{OPS_PTAG_CT_LITERAL_DATA, "Literal Data"},
92 	{OPS_PTAG_CT_TRUST, "Trust"},
93 	{OPS_PTAG_CT_USER_ID, "User ID"},
94 	{OPS_PTAG_CT_PUBLIC_SUBKEY, "Public Subkey"},
95 	{OPS_PTAG_CT_RESERVED2, "reserved2"},
96 	{OPS_PTAG_CT_RESERVED3, "reserved3"},
97 	{OPS_PTAG_CT_USER_ATTR, "User Attribute"},
98 	{OPS_PTAG_CT_SE_IP_DATA,
99 		"Symmetric Encrypted and Integrity Protected Data"},
100 	{OPS_PTAG_CT_MDC, "Modification Detection Code"},
101 	{OPS_PARSER_PTAG, "OPS_PARSER_PTAG"},
102 	{OPS_PTAG_RAW_SS, "OPS_PTAG_RAW_SS"},
103 	{OPS_PTAG_SS_ALL, "OPS_PTAG_SS_ALL"},
104 	{OPS_PARSER_PACKET_END, "OPS_PARSER_PACKET_END"},
105 	{OPS_PTAG_SIG_SUBPKT_BASE, "OPS_PTAG_SIG_SUBPKT_BASE"},
106 	{OPS_PTAG_SS_CREATION_TIME, "SS: Signature Creation Time"},
107 	{OPS_PTAG_SS_EXPIRATION_TIME, "SS: Signature Expiration Time"},
108 	{OPS_PTAG_SS_EXPORT_CERT, "SS: Exportable Certification"},
109 	{OPS_PTAG_SS_TRUST, "SS: Trust Signature"},
110 	{OPS_PTAG_SS_REGEXP, "SS: Regular Expression"},
111 	{OPS_PTAG_SS_REVOCABLE, "SS: Revocable"},
112 	{OPS_PTAG_SS_KEY_EXPIRY, "SS: Key Expiration Time"},
113 	{OPS_PTAG_SS_RESERVED, "SS: Reserved"},
114 	{OPS_PTAG_SS_PREFERRED_SKA, "SS: Preferred Secret Key Algorithm"},
115 	{OPS_PTAG_SS_REVOCATION_KEY, "SS: Revocation Key"},
116 	{OPS_PTAG_SS_ISSUER_KEY_ID, "SS: Issuer Key Id"},
117 	{OPS_PTAG_SS_NOTATION_DATA, "SS: Notation Data"},
118 	{OPS_PTAG_SS_PREFERRED_HASH, "SS: Preferred Hash Algorithm"},
119 	{OPS_PTAG_SS_PREF_COMPRESS, "SS: Preferred Compression Algorithm"},
120 	{OPS_PTAG_SS_KEYSERV_PREFS, "SS: Key Server Preferences"},
121 	{OPS_PTAG_SS_PREF_KEYSERV, "SS: Preferred Key Server"},
122 	{OPS_PTAG_SS_PRIMARY_USER_ID, "SS: Primary User ID"},
123 	{OPS_PTAG_SS_POLICY_URI, "SS: Policy URI"},
124 	{OPS_PTAG_SS_KEY_FLAGS, "SS: Key Flags"},
125 	{OPS_PTAG_SS_SIGNERS_USER_ID, "SS: Signer's User ID"},
126 	{OPS_PTAG_SS_REVOCATION_REASON, "SS: Reason for Revocation"},
127 	{OPS_PTAG_SS_FEATURES, "SS: Features"},
128 	{OPS_PTAG_SS_SIGNATURE_TARGET, "SS: Signature Target"},
129 	{OPS_PTAG_SS_EMBEDDED_SIGNATURE, "SS: Embedded Signature"},
130 
131 	{OPS_PTAG_CT_LITERAL_DATA_HEADER, "CT: Literal Data Header"},
132 	{OPS_PTAG_CT_LITERAL_DATA_BODY, "CT: Literal Data Body"},
133 	{OPS_PTAG_CT_SIGNATURE_HEADER, "CT: Signature Header"},
134 	{OPS_PTAG_CT_SIGNATURE_FOOTER, "CT: Signature Footer"},
135 	{OPS_PTAG_CT_ARMOUR_HEADER, "CT: Armour Header"},
136 	{OPS_PTAG_CT_ARMOUR_TRAILER, "CT: Armour Trailer"},
137 	{OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER, "CT: Signed Cleartext Header"},
138 	{OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY, "CT: Signed Cleartext Body"},
139 	{OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER, "CT: Signed Cleartext Trailer"},
140 	{OPS_PTAG_CT_UNARMOURED_TEXT, "CT: Unarmoured Text"},
141 	{OPS_PTAG_CT_ENCRYPTED_SECRET_KEY, "CT: Encrypted Secret Key"},
142 	{OPS_PTAG_CT_SE_DATA_HEADER, "CT: Sym Encrypted Data Header"},
143 	{OPS_PTAG_CT_SE_DATA_BODY, "CT: Sym Encrypted Data Body"},
144 	{OPS_PTAG_CT_SE_IP_DATA_HEADER, "CT: Sym Encrypted IP Data Header"},
145 	{OPS_PTAG_CT_SE_IP_DATA_BODY, "CT: Sym Encrypted IP Data Body"},
146 	{OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, "CT: Encrypted PK Session Key"},
147 	{OPS_PARSER_CMD_GET_SK_PASSPHRASE, "CMD: Get Secret Key Passphrase"},
148 	{OPS_PARSER_CMD_GET_SECRET_KEY, "CMD: Get Secret Key"},
149 	{OPS_PARSER_ERROR, "OPS_PARSER_ERROR"},
150 	{OPS_PARSER_ERRCODE, "OPS_PARSER_ERRCODE"},
151 
152 	{0x00, NULL},		/* this is the end-of-array marker */
153 };
154 typedef __ops_map_t packet_tag_map_t;
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 typedef __ops_map_t ss_type_map_t;
180 
181 
182 static __ops_map_t ss_rr_code_map[] =
183 {
184 	{0x00, "No reason specified"},
185 	{0x01, "Key is superseded"},
186 	{0x02, "Key material has been compromised"},
187 	{0x03, "Key is retired and no longer used"},
188 	{0x20, "User ID information is no longer valid"},
189 	{0x00, NULL},		/* this is the end-of-array marker */
190 };
191 typedef __ops_map_t ss_rr_code_map_t;
192 
193 static __ops_map_t sig_type_map[] =
194 {
195 	{OPS_SIG_BINARY, "Signature of a binary document"},
196 	{OPS_SIG_TEXT, "Signature of a canonical text document"},
197 	{OPS_SIG_STANDALONE, "Standalone signature"},
198 	{OPS_CERT_GENERIC, "Generic certification of a User ID and Public Key packet"},
199 	{OPS_CERT_PERSONA, "Personal certification of a User ID and Public Key packet"},
200 	{OPS_CERT_CASUAL, "Casual certification of a User ID and Public Key packet"},
201 	{OPS_CERT_POSITIVE, "Positive certification of a User ID and Public Key packet"},
202 	{OPS_SIG_SUBKEY, "Subkey Binding Signature"},
203 	{OPS_SIG_PRIMARY, "Primary Key Binding Signature"},
204 	{OPS_SIG_DIRECT, "Signature directly on a key"},
205 	{OPS_SIG_REV_KEY, "Key revocation signature"},
206 	{OPS_SIG_REV_SUBKEY, "Subkey revocation signature"},
207 	{OPS_SIG_REV_CERT, "Certification revocation signature"},
208 	{OPS_SIG_TIMESTAMP, "Timestamp signature"},
209 	{OPS_SIG_3RD_PARTY, "Third-Party Confirmation signature"},
210 	{0x00, NULL},		/* this is the end-of-array marker */
211 };
212 typedef __ops_map_t sig_type_map_t;
213 
214 static __ops_map_t pubkey_alg_map[] =
215 {
216 	{OPS_PKA_RSA, "RSA (Encrypt or Sign)"},
217 	{OPS_PKA_RSA_ENCRYPT_ONLY, "RSA Encrypt-Only"},
218 	{OPS_PKA_RSA_SIGN_ONLY, "RSA Sign-Only"},
219 	{OPS_PKA_ELGAMAL, "Elgamal (Encrypt-Only)"},
220 	{OPS_PKA_DSA, "DSA"},
221 	{OPS_PKA_RESERVED_ELLIPTIC_CURVE, "Reserved for Elliptic Curve"},
222 	{OPS_PKA_RESERVED_ECDSA, "Reserved for ECDSA"},
223 	{OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN, "Reserved (formerly Elgamal Encrypt or Sign"},
224 	{OPS_PKA_RESERVED_DH, "Reserved for Diffie-Hellman (X9.42)"},
225 	{OPS_PKA_PRIVATE00, "Private/Experimental"},
226 	{OPS_PKA_PRIVATE01, "Private/Experimental"},
227 	{OPS_PKA_PRIVATE02, "Private/Experimental"},
228 	{OPS_PKA_PRIVATE03, "Private/Experimental"},
229 	{OPS_PKA_PRIVATE04, "Private/Experimental"},
230 	{OPS_PKA_PRIVATE05, "Private/Experimental"},
231 	{OPS_PKA_PRIVATE06, "Private/Experimental"},
232 	{OPS_PKA_PRIVATE07, "Private/Experimental"},
233 	{OPS_PKA_PRIVATE08, "Private/Experimental"},
234 	{OPS_PKA_PRIVATE09, "Private/Experimental"},
235 	{OPS_PKA_PRIVATE10, "Private/Experimental"},
236 	{0x00, NULL},		/* this is the end-of-array marker */
237 };
238 typedef __ops_map_t pubkey_alg_map_t;
239 
240 static __ops_map_t symm_alg_map[] =
241 {
242 	{OPS_SA_PLAINTEXT, "Plaintext or unencrypted data"},
243 	{OPS_SA_IDEA, "IDEA"},
244 	{OPS_SA_TRIPLEDES, "TripleDES"},
245 	{OPS_SA_CAST5, "CAST5"},
246 	{OPS_SA_BLOWFISH, "Blowfish"},
247 	{OPS_SA_AES_128, "AES (128-bit key)"},
248 	{OPS_SA_AES_192, "AES (192-bit key)"},
249 	{OPS_SA_AES_256, "AES (256-bit key)"},
250 	{OPS_SA_TWOFISH, "Twofish(256-bit key)"},
251 	{0x00, NULL},		/* this is the end-of-array marker */
252 };
253 
254 static __ops_map_t hash_alg_map[] =
255 {
256 	{OPS_HASH_MD5, "MD5"},
257 	{OPS_HASH_SHA1, "SHA1"},
258 	{OPS_HASH_RIPEMD, "RIPEMD160"},
259 	{OPS_HASH_SHA256, "SHA256"},
260 	{OPS_HASH_SHA384, "SHA384"},
261 	{OPS_HASH_SHA512, "SHA512"},
262 	{OPS_HASH_SHA224, "SHA224"},
263 	{0x00, NULL},		/* this is the end-of-array marker */
264 };
265 
266 static __ops_map_t compression_alg_map[] =
267 {
268 	{OPS_C_NONE, "Uncompressed"},
269 	{OPS_C_ZIP, "ZIP(RFC1951)"},
270 	{OPS_C_ZLIB, "ZLIB(RFC1950)"},
271 	{OPS_C_BZIP2, "Bzip2(BZ2)"},
272 	{0x00, NULL},		/* this is the end-of-array marker */
273 };
274 
275 static __ops_bit_map_t ss_notation_map_byte0[] =
276 {
277 	{0x80, "Human-readable"},
278 	{0x00, NULL},
279 };
280 
281 static __ops_bit_map_t *ss_notation_map[] =
282 {
283 	ss_notation_map_byte0,
284 };
285 
286 static __ops_bit_map_t ss_feature_map_byte0[] =
287 {
288 	{0x01, "Modification Detection"},
289 	{0x00, NULL},
290 };
291 
292 static __ops_bit_map_t *ss_feature_map[] =
293 {
294 	ss_feature_map_byte0,
295 };
296 
297 static __ops_bit_map_t ss_key_flags_map[] =
298 {
299 	{0x01, "May be used to certify other keys"},
300 	{0x02, "May be used to sign data"},
301 	{0x04, "May be used to encrypt communications"},
302 	{0x08, "May be used to encrypt storage"},
303 	{0x10, "Private component may have been split by a secret-sharing mechanism"},
304 	{0x80, "Private component may be in possession of more than one person"},
305 	{0x00, NULL},
306 };
307 
308 static __ops_bit_map_t ss_key_server_prefs_map[] =
309 {
310 	{0x80, "Key holder requests that this key only be modified or updated by the key holder or an administrator of the key server"},
311 	{0x00, NULL},
312 };
313 
314 #include "packet-show-cast.h"
315 
316 /*
317  * Private functions
318  */
319 
320 static void
321 list_init(__ops_list_t * list)
322 {
323 	list->size = 0;
324 	list->used = 0;
325 	list->strings = NULL;
326 }
327 
328 static void
329 list_free_strings(__ops_list_t * list)
330 {
331 	unsigned        i;
332 
333 	for (i = 0; i < list->used; i++) {
334 		free(list->strings[i]);
335 		list->strings[i] = NULL;
336 	}
337 }
338 
339 static void
340 list_free(__ops_list_t * list)
341 {
342 	if (list->strings)
343 		free(list->strings);
344 	list_init(list);
345 }
346 
347 static unsigned int
348 list_resize(__ops_list_t * list)
349 {
350 	/*
351 	 * We only resize in one direction - upwards. Algorithm used : double
352 	 * the current size then add 1
353 	 */
354 
355 	int             newsize = 0;
356 
357 	newsize = list->size * 2 + 1;
358 	list->strings = realloc(list->strings, newsize * sizeof(char *));
359 	if (list->strings) {
360 		list->size = newsize;
361 		return 1;
362 	} else {
363 		/* xxx - realloc failed. error message? - rachel */
364 		return 0;
365 	}
366 }
367 
368 static unsigned int
369 add_str(__ops_list_t * list, const char *str)
370 {
371 	if (list->size == list->used)
372 		if (!list_resize(list))
373 			return 0;
374 
375 	list->strings[list->used] = __UNCONST(str);
376 	list->used++;
377 	return 1;
378 }
379 
380 /* find a bitfield in a map - serial search */
381 static const char *
382 find_bitfield(__ops_bit_map_t *map, unsigned char octet)
383 {
384 	__ops_bit_map_t  *row;
385 
386 	for (row = map; row->string != NULL && row->mask != octet ; row++) {
387 	}
388 	return (row->string) ? row->string : "Unknown";
389 }
390 
391 /* ! generic function to initialise __ops_text_t structure */
392 void
393 __ops_text_init(__ops_text_t *text)
394 {
395 	list_init(&text->known);
396 	list_init(&text->unknown);
397 }
398 
399 /**
400  * \ingroup Core_Print
401  *
402  * __ops_text_free() frees the memory used by an __ops_text_t structure
403  *
404  * \param text Pointer to a previously allocated structure. This structure and its contents will be freed.
405  */
406 void
407 __ops_text_free(__ops_text_t * text)
408 {
409 	/* Strings in "known" array will be constants, so don't free them */
410 	list_free(&text->known);
411 
412 	/*
413 	 * Strings in "unknown" array will be dynamically allocated, so do
414 	 * free them
415 	 */
416 	list_free_strings(&text->unknown);
417 	list_free(&text->unknown);
418 
419 	(void) free(text);
420 }
421 
422 /* XXX: should this (and many others) be unsigned? */
423 /* ! generic function which adds text derived from single octet map to text */
424 static unsigned
425 add_str_from_octet_map(__ops_text_t *map, char *str, unsigned char octet)
426 {
427 	if (str && !add_str(&map->known, str)) {
428 		/*
429 		 * value recognised, but there was a problem adding it to the
430 		 * list
431 		 */
432 		/* XXX - should print out error msg here, Ben? - rachel */
433 		return 0;
434 	} else if (!str) {
435 		/*
436 		 * value not recognised and there was a problem adding it to
437 		 * the unknown list
438 		 */
439 		unsigned        len = 2 + 2 + 1;	/* 2 for "0x", 2 for
440 							 * single octet in hex
441 							 * format, 1 for NUL */
442 		str = calloc(1, len);
443 		(void) snprintf(str, len, "0x%x", octet);
444 		if (!add_str(&map->unknown, str)) {
445 			return 0;
446 		}
447 	}
448 	return 1;
449 }
450 
451 /* ! generic function which adds text derived from single bit map to text */
452 static unsigned int
453 add_bitmap_entry(__ops_text_t *map, const char *str, unsigned char bit)
454 {
455 	const char     *fmt_unknown = "Unknown bit(0x%x)";
456 
457 	if (str && !add_str(&map->known, str)) {
458 		/*
459 		 * value recognised, but there was a problem adding it to the
460 		 * list
461 		 */
462 		/* XXX - should print out error msg here, Ben? - rachel */
463 		return 0;
464 	} else if (!str) {
465 		/*
466 		 * value not recognised and there was a problem adding it to
467 		 * the unknown list
468 		 * 2 chars of the string are the format definition, this will
469 		 * be replaced in the output by 2 chars of hex, so the length
470 		 * will be correct
471 		 */
472 		unsigned        len = strlen(fmt_unknown) + 1;
473 
474 		str = calloc(1, len);
475 		(void) snprintf(__UNCONST(str), len, fmt_unknown, bit);
476 		if (!add_str(&map->unknown, str)) {
477 			return 0;
478 		}
479 	}
480 	return 1;
481 }
482 
483 /**
484  * Produce a structure containing human-readable textstrings
485  * representing the recognised and unrecognised contents
486  * of this byte array. text_fn() will be called on each octet in turn.
487  * Each octet will generate one string representing the whole byte.
488  *
489  */
490 
491 static __ops_text_t *
492 text_from_bytemapped_octets(__ops_data_t *data,
493 			    const char *(*text_fn)(unsigned char octet))
494 {
495 
496 	__ops_text_t     *text = NULL;
497 	const char     *str;
498 	unsigned        i;
499 
500 	/*
501 	 * ! allocate and initialise __ops_text_t structure to store derived
502 	 * strings
503 	 */
504 	text = calloc(1, sizeof(__ops_text_t));
505 	if (!text) {
506 		return NULL;
507 	}
508 
509 	__ops_text_init(text);
510 
511 	/* ! for each octet in field ... */
512 	for (i = 0; i < data->len; i++) {
513 		/* ! derive string from octet */
514 		str = (*text_fn) (data->contents[i]);
515 
516 		/* ! and add to text */
517 		if (!add_str_from_octet_map(text, strdup(str),
518 						data->contents[i])) {
519 			__ops_text_free(text);
520 			return NULL;
521 		}
522 	}
523 	/*
524 	 * ! All values have been added to either the known or the unknown
525 	 * list
526 	 */
527 	return text;
528 }
529 
530 /**
531  * Produce a structure containing human-readable textstrings
532  * representing the recognised and unrecognised contents
533  * of this byte array, derived from each bit of each octet.
534  *
535  */
536 static __ops_text_t *
537 showall_octets_bits(__ops_data_t * data, __ops_bit_map_t ** map,
538 		    size_t nmap)
539 {
540 	unsigned char	 mask, bit;
541 	__ops_text_t	*text = NULL;
542 	const char	*str;
543 	unsigned         i;
544 	int              j = 0;
545 
546 	/*
547 	 * ! allocate and initialise __ops_text_t structure to store derived
548 	 * strings
549 	 */
550 	text = calloc(1, sizeof(__ops_text_t));
551 	if (!text) {
552 		return NULL;
553 	}
554 
555 	__ops_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 					__ops_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 __ops_show_packet_tag(__ops_packet_tag_t packet_tag)
588 {
589 	const char     *ret;
590 
591 	ret = show_packet_tag(packet_tag, packet_tag_map);
592 	if (!ret) {
593 		ret = "Unknown Tag";
594 	}
595 
596 	return ret;
597 }
598 
599 /**
600  * \ingroup Core_Print
601  *
602  * returns description of the Signature Sub-Packet type
603  * \param ss_type Signature Sub-Packet type
604  * \return string or "Unknown"
605  */
606 const char     *
607 __ops_show_ss_type(__ops_ss_type_t ss_type)
608 {
609 	return show_ss_type(ss_type, ss_type_map);
610 }
611 
612 /**
613  * \ingroup Core_Print
614  *
615  * returns description of the Revocation Reason code
616  * \param ss_rr_code Revocation Reason code
617  * \return string or "Unknown"
618  */
619 const char     *
620 __ops_show_ss_rr_code(__ops_ss_rr_code_t ss_rr_code)
621 {
622 	return show_ss_rr_code(ss_rr_code, ss_rr_code_map);
623 }
624 
625 /**
626  * \ingroup Core_Print
627  *
628  * returns description of the given Signature type
629  * \param sig_type Signature type
630  * \return string or "Unknown"
631  */
632 const char     *
633 __ops_show_sig_type(__ops_sig_type_t sig_type)
634 {
635 	return show_sig_type(sig_type, sig_type_map);
636 }
637 
638 /**
639  * \ingroup Core_Print
640  *
641  * returns description of the given Public Key Algorithm
642  * \param pka Public Key Algorithm type
643  * \return string or "Unknown"
644  */
645 const char     *
646 __ops_show_pka(__ops_pubkey_alg_t pka)
647 {
648 	return show_pka(pka, pubkey_alg_map);
649 }
650 
651 /**
652  * \ingroup Core_Print
653  * returns description of the Preferred Compression
654  * \param octet Preferred Compression
655  * \return string or "Unknown"
656 */
657 const char     *
658 __ops_show_ss_zpref(unsigned char octet)
659 {
660 	return __ops_str_from_map(octet, compression_alg_map);
661 }
662 
663 /**
664  * \ingroup Core_Print
665  *
666  * returns set of descriptions of the given Preferred Compression Algorithms
667  * \param ss_zpref Array of Preferred Compression Algorithms
668  * \return NULL if cannot allocate memory or other error
669  * \return pointer to structure, if no error
670  */
671 __ops_text_t     *
672 __ops_showall_ss_zpref(__ops_ss_zpref_t ss_zpref)
673 {
674 	return text_from_bytemapped_octets(&ss_zpref.data,
675 					&__ops_show_ss_zpref);
676 }
677 
678 
679 /**
680  * \ingroup Core_Print
681  *
682  * returns description of the Hash Algorithm type
683  * \param hash Hash Algorithm type
684  * \return string or "Unknown"
685  */
686 const char     *
687 __ops_show_hash_alg(unsigned char hash)
688 {
689 	return show_hash_alg(hash);
690 }
691 
692 /**
693  * \ingroup Core_Print
694  *
695  * returns set of descriptions of the given Preferred Hash Algorithms
696  * \param ss_hashpref Array of Preferred Hash Algorithms
697  * \return NULL if cannot allocate memory or other error
698  * \return pointer to structure, if no error
699  */
700 __ops_text_t     *
701 __ops_showall_ss_hashpref(__ops_ss_hashpref_t ss_hashpref)
702 {
703 	return text_from_bytemapped_octets(&ss_hashpref.data,
704 					   &__ops_show_hash_alg);
705 }
706 
707 const char     *
708 __ops_show_symm_alg(unsigned char hash)
709 {
710 	return show_symm_alg(hash);
711 }
712 
713 /**
714  * \ingroup Core_Print
715  * returns description of the given Preferred Symmetric Key Algorithm
716  * \param octet
717  * \return string or "Unknown"
718 */
719 const char     *
720 __ops_show_ss_skapref(unsigned char octet)
721 {
722 	return __ops_str_from_map(octet, symm_alg_map);
723 }
724 
725 /**
726  * \ingroup Core_Print
727  *
728  * returns set of descriptions of the given Preferred Symmetric Key Algorithms
729  * \param ss_skapref Array of Preferred Symmetric Key Algorithms
730  * \return NULL if cannot allocate memory or other error
731  * \return pointer to structure, if no error
732  */
733 __ops_text_t     *
734 __ops_showall_ss_skapref(__ops_ss_skapref_t ss_skapref)
735 {
736 	return text_from_bytemapped_octets(&ss_skapref.data,
737 					   &__ops_show_ss_skapref);
738 }
739 
740 /**
741  * \ingroup Core_Print
742  * returns description of one SS Feature
743  * \param octet
744  * \return string or "Unknown"
745 */
746 static const char *
747 __ops_show_ss_feature(unsigned char octet, unsigned offset)
748 {
749 	if (offset >= OPS_ARRAY_SIZE(ss_feature_map)) {
750 		return "Unknown";
751 	}
752 	return find_bitfield(ss_feature_map[offset], octet);
753 }
754 
755 /**
756  * \ingroup Core_Print
757  *
758  * returns set of descriptions of the given SS Features
759  * \param ss_features Signature Sub-Packet Features
760  * \return NULL if cannot allocate memory or other error
761  * \return pointer to structure, if no error
762  */
763 /* XXX: shouldn't this use show_all_octets_bits? */
764 __ops_text_t     *
765 __ops_showall_ss_features(__ops_ss_features_t ss_features)
766 {
767 	unsigned char	 mask, bit;
768 	__ops_text_t	*text = NULL;
769 	const char	*str;
770 	unsigned	 i;
771 	int		 j = 0;
772 
773 	text = calloc(1, sizeof(__ops_text_t));
774 	if (!text) {
775 		return NULL;
776 	}
777 
778 	__ops_text_init(text);
779 
780 	for (i = 0; i < ss_features.data.len; i++) {
781 		mask = 0x80;
782 		for (j = 0; j < 8; j++, mask = (unsigned)mask >> 1) {
783 			bit = ss_features.data.contents[i] & mask;
784 			if (bit) {
785 				str = __ops_show_ss_feature(bit, i);
786 				if (!add_bitmap_entry(text, str, bit)) {
787 					__ops_text_free(text);
788 					return NULL;
789 				}
790 			}
791 		}
792 	}
793 	return text;
794 }
795 
796 /**
797  * \ingroup Core_Print
798  * returns description of SS Key Flag
799  * \param octet
800  * \param map
801  * \return
802 */
803 const char     *
804 __ops_show_ss_key_flag(unsigned char octet, __ops_bit_map_t * map)
805 {
806 	return find_bitfield(map, octet);
807 }
808 
809 /**
810  * \ingroup Core_Print
811  *
812  * returns set of descriptions of the given Preferred Key Flags
813  * \param ss_key_flags Array of Key Flags
814  * \return NULL if cannot allocate memory or other error
815  * \return pointer to structure, if no error
816  */
817 __ops_text_t     *
818 __ops_showall_ss_key_flags(__ops_ss_key_flags_t ss_key_flags)
819 {
820 	unsigned char    mask, bit;
821 	__ops_text_t	*text = NULL;
822 	const char	*str;
823 	int              i = 0;
824 
825 	text = calloc(1, sizeof(__ops_text_t));
826 	if (!text) {
827 		return NULL;
828 	}
829 
830 	__ops_text_init(text);
831 
832 	/* xxx - TBD: extend to handle multiple octets of bits - rachel */
833 	for (i = 0, mask = 0x80; i < 8; i++, mask = (unsigned)mask >> 1) {
834 		bit = ss_key_flags.data.contents[0] & mask;
835 		if (bit) {
836 			str = __ops_show_ss_key_flag(bit, &ss_key_flags_map[0]);
837 			if (!add_bitmap_entry(text, strdup(str), bit)) {
838 				__ops_text_free(text);
839 				return NULL;
840 			}
841 		}
842 	}
843 	/*
844 	 * xxx - must add error text if more than one octet. Only one
845 	 * currently specified -- rachel
846 	 */
847 	return text;
848 }
849 
850 /**
851  * \ingroup Core_Print
852  *
853  * returns description of one given Key Server Preference
854  *
855  * \param prefs Byte containing bitfield of preferences
856  * \param map
857  * \return string or "Unknown"
858  */
859 const char     *
860 __ops_show_keyserv_pref(unsigned char prefs, __ops_bit_map_t * map)
861 {
862 	return find_bitfield(map, prefs);
863 }
864 
865 /**
866  * \ingroup Core_Print
867  * returns set of descriptions of given Key Server Preferences
868  * \param ss_key_server_prefs
869  * \return NULL if cannot allocate memory or other error
870  * \return pointer to structure, if no error
871  *
872 */
873 __ops_text_t     *
874 __ops_show_keyserv_prefs(__ops_ss_key_server_prefs_t prefs)
875 {
876 	unsigned char	 mask, bit;
877 	__ops_text_t	*text = NULL;
878 	const char	*str;
879 	int              i = 0;
880 
881 	text = calloc(1, sizeof(__ops_text_t));
882 	if (!text) {
883 		return NULL;
884 	}
885 
886 	__ops_text_init(text);
887 
888 	/* xxx - TBD: extend to handle multiple octets of bits - rachel */
889 
890 	for (i = 0, mask = 0x80; i < 8; i++, mask = (unsigned)mask >> 1) {
891 		bit = prefs.data.contents[0] & mask;
892 		if (bit) {
893 			str = __ops_show_keyserv_pref(bit,
894 						ss_key_server_prefs_map);
895 			if (!add_bitmap_entry(text, strdup(str), bit)) {
896 				__ops_text_free(text);
897 				return NULL;
898 			}
899 		}
900 	}
901 	/*
902 	 * xxx - must add error text if more than one octet. Only one
903 	 * currently specified -- rachel
904 	 */
905 	return text;
906 }
907 
908 /**
909  * \ingroup Core_Print
910  *
911  * returns set of descriptions of the given SS Notation Data Flags
912  * \param ss_notation Signature Sub-Packet Notation Data
913  * \return NULL if cannot allocate memory or other error
914  * \return pointer to structure, if no error
915  */
916 __ops_text_t     *
917 __ops_showall_notation(__ops_ss_notation_t ss_notation)
918 {
919 	return showall_octets_bits(&ss_notation.flags,
920 				ss_notation_map,
921 				OPS_ARRAY_SIZE(ss_notation_map));
922 }
923