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