xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/misc.c (revision 0294a66b694d2a57b43f64b66c7a4aee89316c4e)
12232f800Sagc /*-
2b15ec256Sagc  * Copyright (c) 2009,2010 The NetBSD Foundation, Inc.
32232f800Sagc  * All rights reserved.
42232f800Sagc  *
52232f800Sagc  * This code is derived from software contributed to The NetBSD Foundation
62232f800Sagc  * by Alistair Crooks (agc@NetBSD.org)
72232f800Sagc  *
82232f800Sagc  * Redistribution and use in source and binary forms, with or without
92232f800Sagc  * modification, are permitted provided that the following conditions
102232f800Sagc  * are met:
112232f800Sagc  * 1. Redistributions of source code must retain the above copyright
122232f800Sagc  *    notice, this list of conditions and the following disclaimer.
132232f800Sagc  * 2. Redistributions in binary form must reproduce the above copyright
142232f800Sagc  *    notice, this list of conditions and the following disclaimer in the
152232f800Sagc  *    documentation and/or other materials provided with the distribution.
162232f800Sagc  *
172232f800Sagc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
182232f800Sagc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
192232f800Sagc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
202232f800Sagc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
212232f800Sagc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
222232f800Sagc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
232232f800Sagc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
242232f800Sagc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
252232f800Sagc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
262232f800Sagc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
272232f800Sagc  * POSSIBILITY OF SUCH DAMAGE.
282232f800Sagc  */
2993bf6008Sagc /*
3093bf6008Sagc  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
3193bf6008Sagc  * All rights reserved.
3293bf6008Sagc  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
3393bf6008Sagc  * their moral rights under the UK Copyright Design and Patents Act 1988 to
3493bf6008Sagc  * be recorded as the authors of this copyright work.
3593bf6008Sagc  *
3693bf6008Sagc  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
3793bf6008Sagc  * use this file except in compliance with the License.
3893bf6008Sagc  *
3993bf6008Sagc  * You may obtain a copy of the License at
4093bf6008Sagc  *     http://www.apache.org/licenses/LICENSE-2.0
4193bf6008Sagc  *
4293bf6008Sagc  * Unless required by applicable law or agreed to in writing, software
4393bf6008Sagc  * distributed under the License is distributed on an "AS IS" BASIS,
4493bf6008Sagc  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4593bf6008Sagc  *
4693bf6008Sagc  * See the License for the specific language governing permissions and
4793bf6008Sagc  * limitations under the License.
4893bf6008Sagc  */
4993bf6008Sagc 
5093bf6008Sagc /** \file
5193bf6008Sagc  */
5293bf6008Sagc #include "config.h"
5393bf6008Sagc 
5457324b9fSagc #ifdef HAVE_SYS_CDEFS_H
5557324b9fSagc #include <sys/cdefs.h>
5657324b9fSagc #endif
5757324b9fSagc 
5857324b9fSagc #if defined(__NetBSD__)
5957324b9fSagc __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60*0294a66bSjhigh __RCSID("$NetBSD: misc.c,v 1.44 2022/08/26 19:18:38 jhigh Exp $");
6157324b9fSagc #endif
6257324b9fSagc 
630df5e957Sagc #include <sys/types.h>
640df5e957Sagc #include <sys/stat.h>
650df5e957Sagc #include <sys/mman.h>
660df5e957Sagc 
67fdfbba49Sagc #include <ctype.h>
68bcfd8565Sagc #include <stdarg.h>
69bcfd8565Sagc #include <stdio.h>
70bcfd8565Sagc #include <stdlib.h>
71bcfd8565Sagc #include <string.h>
72bcfd8565Sagc 
73bcfd8565Sagc #ifdef HAVE_UNISTD_H
74bcfd8565Sagc #include <unistd.h>
75bcfd8565Sagc #endif
76bcfd8565Sagc 
77732655c3Sagc #ifdef HAVE_OPENSSL_RAND_H
78efdd9dbaSagc #include <openssl/rand.h>
79732655c3Sagc #endif
80efdd9dbaSagc 
8193bf6008Sagc #include "errors.h"
8293bf6008Sagc #include "packet.h"
8393bf6008Sagc #include "crypto.h"
8493bf6008Sagc #include "create.h"
8593bf6008Sagc #include "packet-parse.h"
8693bf6008Sagc #include "packet-show.h"
8793bf6008Sagc #include "signature.h"
88efdd9dbaSagc #include "netpgpsdk.h"
8993bf6008Sagc #include "netpgpdefs.h"
9093bf6008Sagc #include "memory.h"
9193bf6008Sagc #include "readerwriter.h"
9293bf6008Sagc #include "version.h"
936715e11aSagc #include "netpgpdigest.h"
9493bf6008Sagc 
9593bf6008Sagc #ifdef WIN32
9693bf6008Sagc #define vsnprintf _vsnprintf
9793bf6008Sagc #endif
9893bf6008Sagc 
99*0294a66bSjhigh struct ecdsa_map {
100*0294a66bSjhigh 	char 	*sname;
101*0294a66bSjhigh 	int 	nid;
102*0294a66bSjhigh 	int 	bits;
103*0294a66bSjhigh 	int 	len;
104*0294a66bSjhigh 	uint8_t oid[8];
105*0294a66bSjhigh } ecdsa_map[] = {
106*0294a66bSjhigh 	{ "P-256", NID_X9_62_prime256v1, 256, 8, {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07} },
107*0294a66bSjhigh 	{ "P-384", NID_secp384r1, 384, 5, {0x2B, 0x81, 0x04,  0x00,  0x22} },
108*0294a66bSjhigh 	{ "P-521", NID_secp521r1, 521, 5, {0x2B, 0x81, 0x04, 0x00, 0x23} },
109*0294a66bSjhigh 	{ NULL, 0, 0, 0, {0} }
110*0294a66bSjhigh };
111d21b929eSagc 
11293bf6008Sagc typedef struct {
113fc1f8641Sagc 	pgp_keyring_t		*keyring;
11493bf6008Sagc } accumulate_t;
11593bf6008Sagc 
11693bf6008Sagc /**
11793bf6008Sagc  * \ingroup Core_Callbacks
11893bf6008Sagc  */
119fc1f8641Sagc static pgp_cb_ret_t
accumulate_cb(const pgp_packet_t * pkt,pgp_cbdata_t * cbinfo)120fc1f8641Sagc accumulate_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
12193bf6008Sagc {
122fc1f8641Sagc 	const pgp_contents_t	*content = &pkt->u;
123fc1f8641Sagc 	pgp_keyring_t		*keyring;
12457324b9fSagc 	accumulate_t		*accumulate;
1253118701fSmlelstv 	pgp_key_t		*key;
12693bf6008Sagc 
127fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
128520c968fSagc 		(void) fprintf(stderr, "accumulate callback: packet tag %u\n", pkt->tag);
129520c968fSagc 	}
130fc1f8641Sagc 	accumulate = pgp_callback_arg(cbinfo);
13157324b9fSagc 	keyring = accumulate->keyring;
1323118701fSmlelstv 	key = keyring->keyc > 0 ? &keyring->keys[keyring->keyc - 1] : NULL;
1333326c4c5Sagc 	switch (pkt->tag) {
134fc1f8641Sagc 	case PGP_PTAG_CT_PUBLIC_KEY:
135fc1f8641Sagc 	case PGP_PTAG_CT_PUBLIC_SUBKEY:
136fc1f8641Sagc 		pgp_add_to_pubring(keyring, &content->pubkey, pkt->tag);
137fc1f8641Sagc 		return PGP_KEEP_MEMORY;
138fc1f8641Sagc 	case PGP_PTAG_CT_SECRET_KEY:
139fc1f8641Sagc 	case PGP_PTAG_CT_ENCRYPTED_SECRET_KEY:
140fc1f8641Sagc 		pgp_add_to_secring(keyring, &content->seckey);
141fc1f8641Sagc 		return PGP_KEEP_MEMORY;
142fc1f8641Sagc 	case PGP_PTAG_CT_USER_ID:
143fc1f8641Sagc 		if (pgp_get_debug_level(__FILE__)) {
144ef1ef480Sagc 			(void) fprintf(stderr, "User ID: %s for key %d\n",
145d427c17dSagc 					content->userid,
146ef1ef480Sagc 					keyring->keyc - 1);
14793bf6008Sagc 		}
1483118701fSmlelstv 		if (key != NULL) {
1493118701fSmlelstv 			pgp_add_userid(key, content->userid);
150520c968fSagc 		} else {
1513118701fSmlelstv 			PGP_ERROR_1(cbinfo->errors, PGP_E_P_NO_USERID, "%s",
1523118701fSmlelstv 			    "No key for userid found");
153520c968fSagc 		}
154fc1f8641Sagc 		return PGP_KEEP_MEMORY;
155fc1f8641Sagc 	case PGP_PARSER_PACKET_END:
1563118701fSmlelstv 		if (key != NULL) {
1573118701fSmlelstv 			switch (content->packet.tag) {
1583118701fSmlelstv 			case PGP_PTAG_CT_RESERVED:
1593118701fSmlelstv 				(void) fprintf(stderr, "Invalid packet tag\n");
1603118701fSmlelstv 				break;
1613118701fSmlelstv 			case PGP_PTAG_CT_PUBLIC_KEY:
1623118701fSmlelstv 			case PGP_PTAG_CT_USER_ID:
1633118701fSmlelstv 				break;
1643118701fSmlelstv 			default:
1653118701fSmlelstv 				pgp_add_subpacket(key, &content->packet);
1663118701fSmlelstv 				break;
1673118701fSmlelstv 			}
168fc1f8641Sagc 			return PGP_KEEP_MEMORY;
16957324b9fSagc 		}
170fc1f8641Sagc 		return PGP_RELEASE_MEMORY;
171fc1f8641Sagc 	case PGP_PARSER_ERROR:
172d427c17dSagc 		(void) fprintf(stderr, "Error: %s\n", content->error);
173fc1f8641Sagc 		return PGP_FINISHED;
174fc1f8641Sagc 	case PGP_PARSER_ERRCODE:
17557324b9fSagc 		(void) fprintf(stderr, "parse error: %s\n",
176fc1f8641Sagc 				pgp_errcode(content->errcode.errcode));
17793bf6008Sagc 		break;
17893bf6008Sagc 	default:
17993bf6008Sagc 		break;
18093bf6008Sagc 	}
18193bf6008Sagc 	/* XXX: we now exclude so many things, we should either drop this or */
18293bf6008Sagc 	/* do something to pass on copies of the stuff we keep */
183fc1f8641Sagc 	return pgp_stacked_callback(pkt, cbinfo);
18493bf6008Sagc }
18593bf6008Sagc 
18693bf6008Sagc /**
18793bf6008Sagc  * \ingroup Core_Parse
18893bf6008Sagc  *
18993bf6008Sagc  * Parse packets from an input stream until EOF or error.
19093bf6008Sagc  *
19193bf6008Sagc  * Key data found in the parsed data is added to #keyring.
19293bf6008Sagc  *
19393bf6008Sagc  * \param keyring Pointer to an existing keyring
19493bf6008Sagc  * \param parse Options to use when parsing
19593bf6008Sagc */
19693bf6008Sagc int
pgp_parse_and_accumulate(pgp_keyring_t * keyring,pgp_stream_t * parse)197fc1f8641Sagc pgp_parse_and_accumulate(pgp_keyring_t *keyring, pgp_stream_t *parse)
19893bf6008Sagc {
19993bf6008Sagc 	accumulate_t	accumulate;
200393ecd92Sagc 	const int	printerrors = 1;
20157324b9fSagc 	int             ret;
20293bf6008Sagc 
2032232f800Sagc 	if (parse->readinfo.accumulate) {
204bcfd8565Sagc 		(void) fprintf(stderr,
205fc1f8641Sagc 			"pgp_parse_and_accumulate: already init\n");
206bcfd8565Sagc 		return 0;
207bcfd8565Sagc 	}
20893bf6008Sagc 
20993bf6008Sagc 	(void) memset(&accumulate, 0x0, sizeof(accumulate));
21093bf6008Sagc 
21193bf6008Sagc 	accumulate.keyring = keyring;
21293bf6008Sagc 
213fc1f8641Sagc 	pgp_callback_push(parse, accumulate_cb, &accumulate);
2144b3a3e18Sagc 	parse->readinfo.accumulate = 1;
215fc1f8641Sagc 	ret = pgp_parse(parse, !printerrors);
21693bf6008Sagc 
21757324b9fSagc 	return ret;
21893bf6008Sagc }
21993bf6008Sagc 
22093bf6008Sagc 
22193bf6008Sagc /** \file
22293bf6008Sagc  * \brief Error Handling
22393bf6008Sagc  */
22493bf6008Sagc #define ERRNAME(code)	{ code, #code }
22593bf6008Sagc 
226fc1f8641Sagc static pgp_errcode_name_map_t errcode_name_map[] = {
227fc1f8641Sagc 	ERRNAME(PGP_E_OK),
228fc1f8641Sagc 	ERRNAME(PGP_E_FAIL),
229fc1f8641Sagc 	ERRNAME(PGP_E_SYSTEM_ERROR),
230fc1f8641Sagc 	ERRNAME(PGP_E_UNIMPLEMENTED),
23193bf6008Sagc 
232fc1f8641Sagc 	ERRNAME(PGP_E_R),
233fc1f8641Sagc 	ERRNAME(PGP_E_R_READ_FAILED),
234fc1f8641Sagc 	ERRNAME(PGP_E_R_EARLY_EOF),
235fc1f8641Sagc 	ERRNAME(PGP_E_R_BAD_FORMAT),
236fc1f8641Sagc 	ERRNAME(PGP_E_R_UNCONSUMED_DATA),
23793bf6008Sagc 
238fc1f8641Sagc 	ERRNAME(PGP_E_W),
239fc1f8641Sagc 	ERRNAME(PGP_E_W_WRITE_FAILED),
240fc1f8641Sagc 	ERRNAME(PGP_E_W_WRITE_TOO_SHORT),
24193bf6008Sagc 
242fc1f8641Sagc 	ERRNAME(PGP_E_P),
243fc1f8641Sagc 	ERRNAME(PGP_E_P_NOT_ENOUGH_DATA),
244fc1f8641Sagc 	ERRNAME(PGP_E_P_UNKNOWN_TAG),
245fc1f8641Sagc 	ERRNAME(PGP_E_P_PACKET_CONSUMED),
246fc1f8641Sagc 	ERRNAME(PGP_E_P_MPI_FORMAT_ERROR),
24793bf6008Sagc 
248fc1f8641Sagc 	ERRNAME(PGP_E_C),
24993bf6008Sagc 
250fc1f8641Sagc 	ERRNAME(PGP_E_V),
251fc1f8641Sagc 	ERRNAME(PGP_E_V_BAD_SIGNATURE),
252fc1f8641Sagc 	ERRNAME(PGP_E_V_NO_SIGNATURE),
253fc1f8641Sagc 	ERRNAME(PGP_E_V_UNKNOWN_SIGNER),
25493bf6008Sagc 
255fc1f8641Sagc 	ERRNAME(PGP_E_ALG),
256fc1f8641Sagc 	ERRNAME(PGP_E_ALG_UNSUPPORTED_SYMMETRIC_ALG),
257fc1f8641Sagc 	ERRNAME(PGP_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG),
258fc1f8641Sagc 	ERRNAME(PGP_E_ALG_UNSUPPORTED_SIGNATURE_ALG),
259fc1f8641Sagc 	ERRNAME(PGP_E_ALG_UNSUPPORTED_HASH_ALG),
26093bf6008Sagc 
261fc1f8641Sagc 	ERRNAME(PGP_E_PROTO),
262fc1f8641Sagc 	ERRNAME(PGP_E_PROTO_BAD_SYMMETRIC_DECRYPT),
263fc1f8641Sagc 	ERRNAME(PGP_E_PROTO_UNKNOWN_SS),
264fc1f8641Sagc 	ERRNAME(PGP_E_PROTO_CRITICAL_SS_IGNORED),
265fc1f8641Sagc 	ERRNAME(PGP_E_PROTO_BAD_PUBLIC_KEY_VRSN),
266fc1f8641Sagc 	ERRNAME(PGP_E_PROTO_BAD_SIGNATURE_VRSN),
267fc1f8641Sagc 	ERRNAME(PGP_E_PROTO_BAD_ONE_PASS_SIG_VRSN),
268fc1f8641Sagc 	ERRNAME(PGP_E_PROTO_BAD_PKSK_VRSN),
269fc1f8641Sagc 	ERRNAME(PGP_E_PROTO_DECRYPTED_MSG_WRONG_LEN),
270fc1f8641Sagc 	ERRNAME(PGP_E_PROTO_BAD_SK_CHECKSUM),
27193bf6008Sagc 
27293bf6008Sagc 	{0x00, NULL},		/* this is the end-of-array marker */
27393bf6008Sagc };
27493bf6008Sagc 
27593bf6008Sagc /**
27693bf6008Sagc  * \ingroup Core_Errors
27793bf6008Sagc  * \brief returns error code name
27893bf6008Sagc  * \param errcode
27993bf6008Sagc  * \return error code name or "Unknown"
28093bf6008Sagc  */
28193bf6008Sagc const char     *
pgp_errcode(const pgp_errcode_t errcode)282fc1f8641Sagc pgp_errcode(const pgp_errcode_t errcode)
28393bf6008Sagc {
284fc1f8641Sagc 	return (pgp_str_from_map((int) errcode,
285fc1f8641Sagc 			(pgp_map_t *) errcode_name_map));
28693bf6008Sagc }
28793bf6008Sagc 
2889b753456Sagc /* generic grab new storage function */
2899b753456Sagc void *
pgp_new(size_t size)290fc1f8641Sagc pgp_new(size_t size)
2919b753456Sagc {
2929b753456Sagc 	void	*vp;
2939b753456Sagc 
2949b753456Sagc 	if ((vp = calloc(1, size)) == NULL) {
2959b753456Sagc 		(void) fprintf(stderr,
2969b753456Sagc 			"allocation failure for %" PRIsize "u bytes", size);
2979b753456Sagc 	}
2989b753456Sagc 	return vp;
2999b753456Sagc }
3009b753456Sagc 
30193bf6008Sagc /**
30293bf6008Sagc  * \ingroup Core_Errors
30393bf6008Sagc  * \brief Pushes the given error on the given errorstack
30493bf6008Sagc  * \param errstack Error stack to use
30593bf6008Sagc  * \param errcode Code of error to push
306fc1f8641Sagc  * \param sys_errno System errno (used if errcode=PGP_E_SYSTEM_ERROR)
30793bf6008Sagc  * \param file Source filename where error occurred
30893bf6008Sagc  * \param line Line in source file where error occurred
30993bf6008Sagc  * \param fmt Comment
31093bf6008Sagc  *
31193bf6008Sagc  */
31293bf6008Sagc 
31393bf6008Sagc void
pgp_push_error(pgp_error_t ** errstack,pgp_errcode_t errcode,int sys_errno,const char * file,int line,const char * fmt,...)314fc1f8641Sagc pgp_push_error(pgp_error_t **errstack, pgp_errcode_t errcode,
3154b3a3e18Sagc 		int sys_errno, const char *file, int line, const char *fmt,...)
31693bf6008Sagc {
31793bf6008Sagc 	/* first get the varargs and generate the comment */
318fc1f8641Sagc 	pgp_error_t  *err;
319efdd9dbaSagc 	unsigned	maxbuf = 128;
320efdd9dbaSagc 	va_list		args;
321efdd9dbaSagc 	char           *comment;
32293bf6008Sagc 
323bcfd8565Sagc 	if ((comment = calloc(1, maxbuf + 1)) == NULL) {
324bcfd8565Sagc 		(void) fprintf(stderr, "calloc comment failure\n");
325bcfd8565Sagc 		return;
326bcfd8565Sagc 	}
32793bf6008Sagc 
32893bf6008Sagc 	va_start(args, fmt);
32993bf6008Sagc 	vsnprintf(comment, maxbuf + 1, fmt, args);
33093bf6008Sagc 	va_end(args);
33193bf6008Sagc 
33293bf6008Sagc 	/* alloc a new error and add it to the top of the stack */
33393bf6008Sagc 
334814ccb85Sagc 	if ((err = calloc(1, sizeof(*err))) == NULL) {
335bcfd8565Sagc 		(void) fprintf(stderr, "calloc comment failure\n");
336bcfd8565Sagc 		return;
337bcfd8565Sagc 	}
33893bf6008Sagc 
33993bf6008Sagc 	err->next = *errstack;
34093bf6008Sagc 	*errstack = err;
34193bf6008Sagc 
34293bf6008Sagc 	/* fill in the details */
34393bf6008Sagc 	err->errcode = errcode;
34493bf6008Sagc 	err->sys_errno = sys_errno;
34593bf6008Sagc 	err->file = file;
34693bf6008Sagc 	err->line = line;
34793bf6008Sagc 
34893bf6008Sagc 	err->comment = comment;
34993bf6008Sagc }
35093bf6008Sagc 
35193bf6008Sagc /**
35293bf6008Sagc \ingroup Core_Errors
35393bf6008Sagc \brief print this error
35493bf6008Sagc \param err Error to print
35593bf6008Sagc */
35693bf6008Sagc void
pgp_print_error(pgp_error_t * err)357fc1f8641Sagc pgp_print_error(pgp_error_t *err)
35893bf6008Sagc {
35993bf6008Sagc 	printf("%s:%d: ", err->file, err->line);
360fc1f8641Sagc 	if (err->errcode == PGP_E_SYSTEM_ERROR) {
36193bf6008Sagc 		printf("system error %d returned from %s()\n", err->sys_errno,
36293bf6008Sagc 		       err->comment);
3634b3a3e18Sagc 	} else {
364fc1f8641Sagc 		printf("%s, %s\n", pgp_errcode(err->errcode), err->comment);
36593bf6008Sagc 	}
3664b3a3e18Sagc }
36793bf6008Sagc 
36893bf6008Sagc /**
36993bf6008Sagc \ingroup Core_Errors
37093bf6008Sagc \brief Print all errors on stack
37193bf6008Sagc \param errstack Error stack to print
37293bf6008Sagc */
37393bf6008Sagc void
pgp_print_errors(pgp_error_t * errstack)374fc1f8641Sagc pgp_print_errors(pgp_error_t *errstack)
37593bf6008Sagc {
376fc1f8641Sagc 	pgp_error_t    *err;
37793bf6008Sagc 
3784b3a3e18Sagc 	for (err = errstack; err != NULL; err = err->next) {
379fc1f8641Sagc 		pgp_print_error(err);
38093bf6008Sagc 	}
3814b3a3e18Sagc }
38293bf6008Sagc 
38393bf6008Sagc /**
38493bf6008Sagc \ingroup Core_Errors
3854b3a3e18Sagc \brief Return 1 if given error is present anywhere on stack
38693bf6008Sagc \param errstack Error stack to check
38793bf6008Sagc \param errcode Error code to look for
38893bf6008Sagc \return 1 if found; else 0
38993bf6008Sagc */
39093bf6008Sagc int
pgp_has_error(pgp_error_t * errstack,pgp_errcode_t errcode)391fc1f8641Sagc pgp_has_error(pgp_error_t *errstack, pgp_errcode_t errcode)
39293bf6008Sagc {
393fc1f8641Sagc 	pgp_error_t    *err;
394d21b929eSagc 
39593bf6008Sagc 	for (err = errstack; err != NULL; err = err->next) {
3964b3a3e18Sagc 		if (err->errcode == errcode) {
39793bf6008Sagc 			return 1;
39893bf6008Sagc 		}
3994b3a3e18Sagc 	}
40093bf6008Sagc 	return 0;
40193bf6008Sagc }
40293bf6008Sagc 
40393bf6008Sagc /**
40493bf6008Sagc \ingroup Core_Errors
40593bf6008Sagc \brief Frees all errors on stack
40693bf6008Sagc \param errstack Error stack to free
40793bf6008Sagc */
40893bf6008Sagc void
pgp_free_errors(pgp_error_t * errstack)409fc1f8641Sagc pgp_free_errors(pgp_error_t *errstack)
41093bf6008Sagc {
411fc1f8641Sagc 	pgp_error_t    *next;
4124b3a3e18Sagc 
41393bf6008Sagc 	while (errstack != NULL) {
41493bf6008Sagc 		next = errstack->next;
415814ccb85Sagc 		free(errstack->comment);
416814ccb85Sagc 		free(errstack);
41793bf6008Sagc 		errstack = next;
41893bf6008Sagc 	}
41993bf6008Sagc }
42093bf6008Sagc 
42147561e26Sagc /* hash a 32-bit integer */
42247561e26Sagc static int
hash_uint32(pgp_hash_t * hash,uint32_t n)423fc1f8641Sagc hash_uint32(pgp_hash_t *hash, uint32_t n)
42447561e26Sagc {
42547561e26Sagc 	uint8_t	ibuf[4];
42647561e26Sagc 
42747561e26Sagc 	ibuf[0] = (uint8_t)(n >> 24) & 0xff;
42847561e26Sagc 	ibuf[1] = (uint8_t)(n >> 16) & 0xff;
42947561e26Sagc 	ibuf[2] = (uint8_t)(n >> 8) & 0xff;
43047561e26Sagc 	ibuf[3] = (uint8_t)n & 0xff;
43169d4f30fSagc 	(*hash->add)(hash, (const uint8_t *)(void *)ibuf, (unsigned)sizeof(ibuf));
43247561e26Sagc 	return sizeof(ibuf);
43347561e26Sagc }
43447561e26Sagc 
43547561e26Sagc /* hash a string - first length, then string itself */
43647561e26Sagc static int
hash_string(pgp_hash_t * hash,const uint8_t * buf,uint32_t len)437fc1f8641Sagc hash_string(pgp_hash_t *hash, const uint8_t *buf, uint32_t len)
43847561e26Sagc {
439fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
44047561e26Sagc 		hexdump(stderr, "hash_string", buf, len);
44147561e26Sagc 	}
44247561e26Sagc 	hash_uint32(hash, len);
44347561e26Sagc 	(*hash->add)(hash, buf, len);
44469d4f30fSagc 	return (int)(sizeof(len) + len);
44547561e26Sagc }
44647561e26Sagc 
44747561e26Sagc /* hash a bignum, possibly padded - first length, then string itself */
44847561e26Sagc static int
hash_bignum(pgp_hash_t * hash,BIGNUM * bignum)449fc1f8641Sagc hash_bignum(pgp_hash_t *hash, BIGNUM *bignum)
45047561e26Sagc {
45147561e26Sagc 	uint8_t	*bn;
45247561e26Sagc 	size_t	 len;
45347561e26Sagc 	int	 padbyte;
45447561e26Sagc 
45547561e26Sagc 	if (BN_is_zero(bignum)) {
45647561e26Sagc 		hash_uint32(hash, 0);
45747561e26Sagc 		return sizeof(len);
45847561e26Sagc 	}
45947561e26Sagc 	if ((len = (size_t) BN_num_bytes(bignum)) < 1) {
46047561e26Sagc 		(void) fprintf(stderr, "hash_bignum: bad size\n");
46147561e26Sagc 		return 0;
46247561e26Sagc 	}
46347561e26Sagc 	if ((bn = calloc(1, len)) == NULL) {
46447561e26Sagc 		(void) fprintf(stderr, "hash_bignum: bad bn alloc\n");
46547561e26Sagc 		return 0;
46647561e26Sagc 	}
46747561e26Sagc 	BN_bn2bin(bignum, bn + 1);
46847561e26Sagc 	bn[0] = 0x0;
46947561e26Sagc 	padbyte = (bn[1] & 0x80) ? 1 : 0;
47069d4f30fSagc 	hash_string(hash, bn + 1 - padbyte, (unsigned)(len + padbyte));
47147561e26Sagc 	free(bn);
47269d4f30fSagc 	return (int)(sizeof(len) + len + padbyte);
47347561e26Sagc }
47447561e26Sagc 
47593bf6008Sagc /** \file
47693bf6008Sagc  */
47793bf6008Sagc 
47893bf6008Sagc /**
47993bf6008Sagc  * \ingroup Core_Keys
48093bf6008Sagc  * \brief Calculate a public key fingerprint.
48193bf6008Sagc  * \param fp Where to put the calculated fingerprint
48293bf6008Sagc  * \param key The key for which the fingerprint is calculated
48393bf6008Sagc  */
48447561e26Sagc int
pgp_fingerprint(pgp_fingerprint_t * fp,const pgp_pubkey_t * key,pgp_hash_alg_t hashtype)485fc1f8641Sagc pgp_fingerprint(pgp_fingerprint_t *fp, const pgp_pubkey_t *key, pgp_hash_alg_t hashtype)
48693bf6008Sagc {
487fc1f8641Sagc 	pgp_memory_t	*mem;
488fc1f8641Sagc 	pgp_hash_t	 hash;
48947561e26Sagc 	const char	*type;
49047561e26Sagc 	uint32_t	 len;
49193bf6008Sagc 
492fc1f8641Sagc 	mem = pgp_memory_new();
49347561e26Sagc 	if (key->version == 2 || key->version == 3) {
494fc1f8641Sagc 		if (key->alg != PGP_PKA_RSA &&
495fc1f8641Sagc 		    key->alg != PGP_PKA_RSA_ENCRYPT_ONLY &&
496fc1f8641Sagc 		    key->alg != PGP_PKA_RSA_SIGN_ONLY) {
497bcfd8565Sagc 			(void) fprintf(stderr,
498fc1f8641Sagc 				"pgp_fingerprint: bad algorithm\n");
49947561e26Sagc 			return 0;
500bcfd8565Sagc 		}
501fc1f8641Sagc 		pgp_hash_md5(&hash);
50247561e26Sagc 		if (!hash.init(&hash)) {
5037affbacaSagc 			(void) fprintf(stderr,
504fc1f8641Sagc 				"pgp_fingerprint: bad md5 alloc\n");
50547561e26Sagc 			return 0;
5067affbacaSagc 		}
50747561e26Sagc 		hash_bignum(&hash, key->key.rsa.n);
50847561e26Sagc 		hash_bignum(&hash, key->key.rsa.e);
50947561e26Sagc 		fp->length = hash.finish(&hash, fp->fingerprint);
510fc1f8641Sagc 		if (pgp_get_debug_level(__FILE__)) {
51147561e26Sagc 			hexdump(stderr, "v2/v3 fingerprint", fp->fingerprint, fp->length);
51293bf6008Sagc 		}
513fc1f8641Sagc 	} else if (hashtype == PGP_HASH_MD5) {
514fc1f8641Sagc 		pgp_hash_md5(&hash);
51547561e26Sagc 		if (!hash.init(&hash)) {
51647561e26Sagc 			(void) fprintf(stderr,
517fc1f8641Sagc 				"pgp_fingerprint: bad md5 alloc\n");
51847561e26Sagc 			return 0;
51947561e26Sagc 		}
520fc1f8641Sagc 		type = (key->alg == PGP_PKA_RSA) ? "ssh-rsa" : "ssh-dss";
52169d4f30fSagc 		hash_string(&hash, (const uint8_t *)(const void *)type, (unsigned)strlen(type));
52247561e26Sagc 		switch(key->alg) {
523fc1f8641Sagc 		case PGP_PKA_RSA:
52447561e26Sagc 			hash_bignum(&hash, key->key.rsa.e);
52547561e26Sagc 			hash_bignum(&hash, key->key.rsa.n);
52647561e26Sagc 			break;
527fc1f8641Sagc 		case PGP_PKA_DSA:
52847561e26Sagc 			hash_bignum(&hash, key->key.dsa.p);
52947561e26Sagc 			hash_bignum(&hash, key->key.dsa.q);
53047561e26Sagc 			hash_bignum(&hash, key->key.dsa.g);
53147561e26Sagc 			hash_bignum(&hash, key->key.dsa.y);
53247561e26Sagc 			break;
53347561e26Sagc 		default:
53447561e26Sagc 			break;
53547561e26Sagc 		}
53647561e26Sagc 		fp->length = hash.finish(&hash, fp->fingerprint);
537fc1f8641Sagc 		if (pgp_get_debug_level(__FILE__)) {
53847561e26Sagc 			hexdump(stderr, "md5 fingerprint", fp->fingerprint, fp->length);
53947561e26Sagc 		}
54047561e26Sagc 	} else {
541fc1f8641Sagc 		pgp_build_pubkey(mem, key, 0);
542fc1f8641Sagc 		pgp_hash_sha1(&hash);
54347561e26Sagc 		if (!hash.init(&hash)) {
5447affbacaSagc 			(void) fprintf(stderr,
545fc1f8641Sagc 				"pgp_fingerprint: bad sha1 alloc\n");
54647561e26Sagc 			return 0;
5477affbacaSagc 		}
548fc1f8641Sagc 		len = (unsigned)pgp_mem_len(mem);
549fc1f8641Sagc 		pgp_hash_add_int(&hash, 0x99, 1);
550fc1f8641Sagc 		pgp_hash_add_int(&hash, len, 2);
551fc1f8641Sagc 		hash.add(&hash, pgp_mem_data(mem), len);
55247561e26Sagc 		fp->length = hash.finish(&hash, fp->fingerprint);
553fc1f8641Sagc 		pgp_memory_free(mem);
554fc1f8641Sagc 		if (pgp_get_debug_level(__FILE__)) {
55547561e26Sagc 			hexdump(stderr, "sha1 fingerprint", fp->fingerprint, fp->length);
55693bf6008Sagc 		}
55793bf6008Sagc 	}
55847561e26Sagc 	return 1;
55947561e26Sagc }
56093bf6008Sagc 
56193bf6008Sagc /**
56293bf6008Sagc  * \ingroup Core_Keys
56393bf6008Sagc  * \brief Calculate the Key ID from the public key.
56493bf6008Sagc  * \param keyid Space for the calculated ID to be stored
56593bf6008Sagc  * \param key The key for which the ID is calculated
56693bf6008Sagc  */
56793bf6008Sagc 
56847561e26Sagc int
pgp_keyid(uint8_t * keyid,const size_t idlen,const pgp_pubkey_t * key,pgp_hash_alg_t hashtype)569fc1f8641Sagc pgp_keyid(uint8_t *keyid, const size_t idlen, const pgp_pubkey_t *key, pgp_hash_alg_t hashtype)
57093bf6008Sagc {
571fc1f8641Sagc 	pgp_fingerprint_t finger;
57291c29c74Sagc 
57393bf6008Sagc 	if (key->version == 2 || key->version == 3) {
574814ccb85Sagc 		unsigned	n;
575b15ec256Sagc 		uint8_t		bn[NETPGP_BUFSIZ];
57693bf6008Sagc 
577814ccb85Sagc 		n = (unsigned) BN_num_bytes(key->key.rsa.n);
578bcfd8565Sagc 		if (n > sizeof(bn)) {
579fc1f8641Sagc 			(void) fprintf(stderr, "pgp_keyid: bad num bytes\n");
58047561e26Sagc 			return 0;
581bcfd8565Sagc 		}
582fc1f8641Sagc 		if (key->alg != PGP_PKA_RSA &&
583fc1f8641Sagc 		    key->alg != PGP_PKA_RSA_ENCRYPT_ONLY &&
584fc1f8641Sagc 		    key->alg != PGP_PKA_RSA_SIGN_ONLY) {
585fc1f8641Sagc 			(void) fprintf(stderr, "pgp_keyid: bad algorithm\n");
58647561e26Sagc 			return 0;
587bcfd8565Sagc 		}
58893bf6008Sagc 		BN_bn2bin(key->key.rsa.n, bn);
5899b753456Sagc 		(void) memcpy(keyid, bn + n - idlen, idlen);
59093bf6008Sagc 	} else {
591fc1f8641Sagc 		pgp_fingerprint(&finger, key, hashtype);
59293bf6008Sagc 		(void) memcpy(keyid,
59393bf6008Sagc 				finger.fingerprint + finger.length - idlen,
59493bf6008Sagc 				idlen);
59593bf6008Sagc 	}
59647561e26Sagc 	return 1;
59793bf6008Sagc }
59893bf6008Sagc 
59993bf6008Sagc /**
60093bf6008Sagc \ingroup Core_Hashes
60193bf6008Sagc \brief Add to the hash
60293bf6008Sagc \param hash Hash to add to
60393bf6008Sagc \param n Int to add
60493bf6008Sagc \param length Length of int in bytes
60593bf6008Sagc */
60693bf6008Sagc void
pgp_hash_add_int(pgp_hash_t * hash,unsigned n,unsigned length)607fc1f8641Sagc pgp_hash_add_int(pgp_hash_t *hash, unsigned n, unsigned length)
60893bf6008Sagc {
609b15ec256Sagc 	uint8_t   c;
61093bf6008Sagc 
611b15ec256Sagc 	while (length--) {
61257324b9fSagc 		c = n >> (length * 8);
61357324b9fSagc 		hash->add(hash, &c, 1);
61493bf6008Sagc 	}
61593bf6008Sagc }
61693bf6008Sagc 
61793bf6008Sagc /**
61893bf6008Sagc \ingroup Core_Hashes
61993bf6008Sagc \brief Setup hash for given hash algorithm
62093bf6008Sagc \param hash Hash to set up
62193bf6008Sagc \param alg Hash algorithm to use
62293bf6008Sagc */
62393bf6008Sagc void
pgp_hash_any(pgp_hash_t * hash,pgp_hash_alg_t alg)624fc1f8641Sagc pgp_hash_any(pgp_hash_t *hash, pgp_hash_alg_t alg)
62593bf6008Sagc {
62693bf6008Sagc 	switch (alg) {
627fc1f8641Sagc 	case PGP_HASH_MD5:
628fc1f8641Sagc 		pgp_hash_md5(hash);
62993bf6008Sagc 		break;
63093bf6008Sagc 
631fc1f8641Sagc 	case PGP_HASH_SHA1:
632fc1f8641Sagc 		pgp_hash_sha1(hash);
63393bf6008Sagc 		break;
63493bf6008Sagc 
635fc1f8641Sagc 	case PGP_HASH_SHA256:
636fc1f8641Sagc 		pgp_hash_sha256(hash);
63793bf6008Sagc 		break;
63893bf6008Sagc 
639fc1f8641Sagc 	case PGP_HASH_SHA384:
640fc1f8641Sagc 		pgp_hash_sha384(hash);
64193bf6008Sagc 		break;
64293bf6008Sagc 
643fc1f8641Sagc 	case PGP_HASH_SHA512:
644fc1f8641Sagc 		pgp_hash_sha512(hash);
64593bf6008Sagc 		break;
64693bf6008Sagc 
647fc1f8641Sagc 	case PGP_HASH_SHA224:
648fc1f8641Sagc 		pgp_hash_sha224(hash);
64993bf6008Sagc 		break;
65093bf6008Sagc 
65193bf6008Sagc 	default:
652fc1f8641Sagc 		(void) fprintf(stderr, "pgp_hash_any: bad algorithm\n");
65393bf6008Sagc 	}
65493bf6008Sagc }
65593bf6008Sagc 
65693bf6008Sagc /**
65793bf6008Sagc \ingroup Core_Hashes
65893bf6008Sagc \brief Returns size of hash for given hash algorithm
65993bf6008Sagc \param alg Hash algorithm to use
66093bf6008Sagc \return Size of hash algorithm in bytes
66193bf6008Sagc */
66293bf6008Sagc unsigned
pgp_hash_size(pgp_hash_alg_t alg)663fc1f8641Sagc pgp_hash_size(pgp_hash_alg_t alg)
66493bf6008Sagc {
66593bf6008Sagc 	switch (alg) {
666fc1f8641Sagc 	case PGP_HASH_MD5:
66793bf6008Sagc 		return 16;
66893bf6008Sagc 
669fc1f8641Sagc 	case PGP_HASH_SHA1:
67093bf6008Sagc 		return 20;
67193bf6008Sagc 
672fc1f8641Sagc 	case PGP_HASH_SHA256:
67393bf6008Sagc 		return 32;
67493bf6008Sagc 
675fc1f8641Sagc 	case PGP_HASH_SHA224:
67693bf6008Sagc 		return 28;
67793bf6008Sagc 
678fc1f8641Sagc 	case PGP_HASH_SHA512:
67993bf6008Sagc 		return 64;
68093bf6008Sagc 
681fc1f8641Sagc 	case PGP_HASH_SHA384:
68293bf6008Sagc 		return 48;
68393bf6008Sagc 
68493bf6008Sagc 	default:
685fc1f8641Sagc 		(void) fprintf(stderr, "pgp_hash_size: bad algorithm\n");
68693bf6008Sagc 	}
68793bf6008Sagc 
68893bf6008Sagc 	return 0;
68993bf6008Sagc }
69093bf6008Sagc 
69193bf6008Sagc /**
69293bf6008Sagc \ingroup Core_Hashes
69393bf6008Sagc \brief Returns hash enum corresponding to given string
69493bf6008Sagc \param hash Text name of hash algorithm i.e. "SHA1"
695fc1f8641Sagc \returns Corresponding enum i.e. PGP_HASH_SHA1
69693bf6008Sagc */
697fc1f8641Sagc pgp_hash_alg_t
pgp_str_to_hash_alg(const char * hash)698fc1f8641Sagc pgp_str_to_hash_alg(const char *hash)
69993bf6008Sagc {
700b15ec256Sagc 	if (hash == NULL) {
701fc1f8641Sagc 		return PGP_DEFAULT_HASH_ALGORITHM;
702b15ec256Sagc 	}
703b15ec256Sagc 	if (netpgp_strcasecmp(hash, "SHA1") == 0) {
704fc1f8641Sagc 		return PGP_HASH_SHA1;
705b1b58706Sagc 	}
706b15ec256Sagc 	if (netpgp_strcasecmp(hash, "MD5") == 0) {
707fc1f8641Sagc 		return PGP_HASH_MD5;
708b1b58706Sagc 	}
709b15ec256Sagc 	if (netpgp_strcasecmp(hash, "SHA256") == 0) {
710fc1f8641Sagc 		return PGP_HASH_SHA256;
711b1b58706Sagc 	}
71293bf6008Sagc 	/*
713b15ec256Sagc         if (netpgp_strcasecmp(hash,"SHA224") == 0) {
714fc1f8641Sagc 		return PGP_HASH_SHA224;
715b1b58706Sagc 	}
71693bf6008Sagc         */
717b15ec256Sagc 	if (netpgp_strcasecmp(hash, "SHA512") == 0) {
718fc1f8641Sagc 		return PGP_HASH_SHA512;
719b1b58706Sagc 	}
720b15ec256Sagc 	if (netpgp_strcasecmp(hash, "SHA384") == 0) {
721fc1f8641Sagc 		return PGP_HASH_SHA384;
722b1b58706Sagc 	}
723fc1f8641Sagc 	return PGP_HASH_UNKNOWN;
72493bf6008Sagc }
72593bf6008Sagc 
72693bf6008Sagc /**
72793bf6008Sagc \ingroup Core_Hashes
72893bf6008Sagc \brief Hash given data
72993bf6008Sagc \param out Where to write the hash
73093bf6008Sagc \param alg Hash algorithm to use
73193bf6008Sagc \param in Data to hash
73293bf6008Sagc \param length Length of data
73393bf6008Sagc \return Size of hash created
73493bf6008Sagc */
73593bf6008Sagc unsigned
pgp_hash(uint8_t * out,pgp_hash_alg_t alg,const void * in,size_t length)736fc1f8641Sagc pgp_hash(uint8_t *out, pgp_hash_alg_t alg, const void *in, size_t length)
73793bf6008Sagc {
738fc1f8641Sagc 	pgp_hash_t      hash;
73993bf6008Sagc 
740fc1f8641Sagc 	pgp_hash_any(&hash, alg);
7417affbacaSagc 	if (!hash.init(&hash)) {
742fc1f8641Sagc 		(void) fprintf(stderr, "pgp_hash: bad alloc\n");
7437affbacaSagc 		/* we'll just continue here - don't want to return a 0 hash */
7447affbacaSagc 		/* XXX - agc - no way to return failure */
7457affbacaSagc 	}
74669d4f30fSagc 	hash.add(&hash, in, (unsigned)length);
74793bf6008Sagc 	return hash.finish(&hash, out);
74893bf6008Sagc }
74993bf6008Sagc 
75093bf6008Sagc /**
75193bf6008Sagc \ingroup Core_Hashes
75293bf6008Sagc \brief Calculate hash for MDC packet
75393bf6008Sagc \param preamble Preamble to hash
75493bf6008Sagc \param sz_preamble Size of preamble
75593bf6008Sagc \param plaintext Plaintext to hash
75693bf6008Sagc \param sz_plaintext Size of plaintext
75793bf6008Sagc \param hashed Resulting hash
75893bf6008Sagc */
75993bf6008Sagc void
pgp_calc_mdc_hash(const uint8_t * preamble,const size_t sz_preamble,const uint8_t * plaintext,const unsigned sz_plaintext,uint8_t * hashed)760fc1f8641Sagc pgp_calc_mdc_hash(const uint8_t *preamble,
7612232f800Sagc 			const size_t sz_preamble,
762b15ec256Sagc 			const uint8_t *plaintext,
763814ccb85Sagc 			const unsigned sz_plaintext,
764b15ec256Sagc 			uint8_t *hashed)
76593bf6008Sagc {
766fc1f8641Sagc 	pgp_hash_t	hash;
767b15ec256Sagc 	uint8_t		c;
76893bf6008Sagc 
769fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
77047561e26Sagc 		hexdump(stderr, "preamble", preamble, sz_preamble);
77147561e26Sagc 		hexdump(stderr, "plaintext", plaintext, sz_plaintext);
77293bf6008Sagc 	}
77393bf6008Sagc 	/* init */
774fc1f8641Sagc 	pgp_hash_any(&hash, PGP_HASH_SHA1);
7757affbacaSagc 	if (!hash.init(&hash)) {
776fc1f8641Sagc 		(void) fprintf(stderr, "pgp_calc_mdc_hash: bad alloc\n");
7777affbacaSagc 		/* we'll just continue here - it will die anyway */
7787affbacaSagc 		/* agc - XXX - no way to return failure */
7797affbacaSagc 	}
78093bf6008Sagc 
78193bf6008Sagc 	/* preamble */
78269d4f30fSagc 	hash.add(&hash, preamble, (unsigned)sz_preamble);
78393bf6008Sagc 	/* plaintext */
78493bf6008Sagc 	hash.add(&hash, plaintext, sz_plaintext);
78593bf6008Sagc 	/* MDC packet tag */
7860df5e957Sagc 	c = MDC_PKT_TAG;
78757324b9fSagc 	hash.add(&hash, &c, 1);
78893bf6008Sagc 	/* MDC packet len */
789fc1f8641Sagc 	c = PGP_SHA1_HASH_SIZE;
79057324b9fSagc 	hash.add(&hash, &c, 1);
79193bf6008Sagc 
79293bf6008Sagc 	/* finish */
79393bf6008Sagc 	hash.finish(&hash, hashed);
79493bf6008Sagc 
795fc1f8641Sagc 	if (pgp_get_debug_level(__FILE__)) {
796fc1f8641Sagc 		hexdump(stderr, "hashed", hashed, PGP_SHA1_HASH_SIZE);
79793bf6008Sagc 	}
79893bf6008Sagc }
79993bf6008Sagc 
80093bf6008Sagc /**
80193bf6008Sagc \ingroup HighLevel_Supported
80293bf6008Sagc \brief Is this Hash Algorithm supported?
80393bf6008Sagc \param hash_alg Hash Algorithm to check
8044b3a3e18Sagc \return 1 if supported; else 0
80593bf6008Sagc */
8064b3a3e18Sagc unsigned
pgp_is_hash_alg_supported(const pgp_hash_alg_t * hash_alg)807fc1f8641Sagc pgp_is_hash_alg_supported(const pgp_hash_alg_t *hash_alg)
80893bf6008Sagc {
80993bf6008Sagc 	switch (*hash_alg) {
810fc1f8641Sagc 	case PGP_HASH_MD5:
811fc1f8641Sagc 	case PGP_HASH_SHA1:
812fc1f8641Sagc 	case PGP_HASH_SHA256:
8134b3a3e18Sagc 		return 1;
81493bf6008Sagc 
81593bf6008Sagc 	default:
8164b3a3e18Sagc 		return 0;
81793bf6008Sagc 	}
81893bf6008Sagc }
81993bf6008Sagc 
8203dc7aea1Sagc /* structure to map string to cipher def */
8213dc7aea1Sagc typedef struct str2cipher_t {
8223dc7aea1Sagc 	const char	*s;	/* cipher name */
823fc1f8641Sagc 	pgp_symm_alg_t i;	/* cipher def */
8243dc7aea1Sagc } str2cipher_t;
8253dc7aea1Sagc 
8263dc7aea1Sagc static str2cipher_t	str2cipher[] = {
827fc1f8641Sagc 	{	"cast5",		PGP_SA_CAST5		},
828fc1f8641Sagc 	{	"idea",			PGP_SA_IDEA		},
829fc1f8641Sagc 	{	"aes128",		PGP_SA_AES_128		},
830fc1f8641Sagc 	{	"aes256",		PGP_SA_AES_256		},
8313fba244aSjhigh 	{	"blowfish",		PGP_SA_BLOWFISH		},
832fc1f8641Sagc 	{	"camellia128",		PGP_SA_CAMELLIA_128	},
833fc1f8641Sagc 	{	"camellia256",		PGP_SA_CAMELLIA_256	},
834fc1f8641Sagc 	{	"tripledes",		PGP_SA_TRIPLEDES	},
8353dc7aea1Sagc 	{	NULL,			0			}
8363dc7aea1Sagc };
8373dc7aea1Sagc 
8383dc7aea1Sagc /* convert from a string to a cipher definition */
839fc1f8641Sagc pgp_symm_alg_t
pgp_str_to_cipher(const char * cipher)840fc1f8641Sagc pgp_str_to_cipher(const char *cipher)
8413dc7aea1Sagc {
8423dc7aea1Sagc 	str2cipher_t	*sp;
8433dc7aea1Sagc 
8443dc7aea1Sagc 	for (sp = str2cipher ; cipher && sp->s ; sp++) {
8453dc7aea1Sagc 		if (netpgp_strcasecmp(cipher, sp->s) == 0) {
8463dc7aea1Sagc 			return sp->i;
8473dc7aea1Sagc 		}
8483dc7aea1Sagc 	}
849fc1f8641Sagc 	return PGP_SA_DEFAULT_CIPHER;
8503dc7aea1Sagc }
8513dc7aea1Sagc 
85293bf6008Sagc void
pgp_random(void * dest,size_t length)853fc1f8641Sagc pgp_random(void *dest, size_t length)
85493bf6008Sagc {
855efdd9dbaSagc 	RAND_bytes(dest, (int)length);
85693bf6008Sagc }
85793bf6008Sagc 
85893bf6008Sagc /**
85993bf6008Sagc \ingroup HighLevel_Memory
86093bf6008Sagc \brief Memory to initialise
86193bf6008Sagc \param mem memory to initialise
86293bf6008Sagc \param needed Size to initialise to
86393bf6008Sagc */
86493bf6008Sagc void
pgp_memory_init(pgp_memory_t * mem,size_t needed)865fc1f8641Sagc pgp_memory_init(pgp_memory_t *mem, size_t needed)
86693bf6008Sagc {
867b15ec256Sagc 	uint8_t	*temp;
8687affbacaSagc 
86993bf6008Sagc 	mem->length = 0;
87093bf6008Sagc 	if (mem->buf) {
87193bf6008Sagc 		if (mem->allocated < needed) {
8727affbacaSagc 			if ((temp = realloc(mem->buf, needed)) == NULL) {
873fc1f8641Sagc 				(void) fprintf(stderr, "pgp_memory_init: bad alloc\n");
8747affbacaSagc 			} else {
8757affbacaSagc 				mem->buf = temp;
87693bf6008Sagc 				mem->allocated = needed;
87793bf6008Sagc 			}
87893bf6008Sagc 		}
8797affbacaSagc 	} else {
8807affbacaSagc 		if ((mem->buf = calloc(1, needed)) == NULL) {
881fc1f8641Sagc 			(void) fprintf(stderr, "pgp_memory_init: bad alloc\n");
8827affbacaSagc 		} else {
88393bf6008Sagc 			mem->allocated = needed;
88493bf6008Sagc 		}
8857affbacaSagc 	}
8867affbacaSagc }
88793bf6008Sagc 
88893bf6008Sagc /**
88993bf6008Sagc \ingroup HighLevel_Memory
89093bf6008Sagc \brief Pad memory to required length
89193bf6008Sagc \param mem Memory to use
89293bf6008Sagc \param length New size
89393bf6008Sagc */
89493bf6008Sagc void
pgp_memory_pad(pgp_memory_t * mem,size_t length)895fc1f8641Sagc pgp_memory_pad(pgp_memory_t *mem, size_t length)
89693bf6008Sagc {
897b15ec256Sagc 	uint8_t	*temp;
8980aa9bccaSagc 
899bcfd8565Sagc 	if (mem->allocated < mem->length) {
900fc1f8641Sagc 		(void) fprintf(stderr, "pgp_memory_pad: bad alloc in\n");
901bcfd8565Sagc 		return;
902bcfd8565Sagc 	}
90393bf6008Sagc 	if (mem->allocated < mem->length + length) {
90493bf6008Sagc 		mem->allocated = mem->allocated * 2 + length;
9050aa9bccaSagc 		temp = realloc(mem->buf, mem->allocated);
9060aa9bccaSagc 		if (temp == NULL) {
907fc1f8641Sagc 			(void) fprintf(stderr, "pgp_memory_pad: bad alloc\n");
9080aa9bccaSagc 		} else {
9090aa9bccaSagc 			mem->buf = temp;
9100aa9bccaSagc 		}
91193bf6008Sagc 	}
912bcfd8565Sagc 	if (mem->allocated < mem->length + length) {
913fc1f8641Sagc 		(void) fprintf(stderr, "pgp_memory_pad: bad alloc out\n");
914bcfd8565Sagc 	}
91593bf6008Sagc }
91693bf6008Sagc 
91793bf6008Sagc /**
91893bf6008Sagc \ingroup HighLevel_Memory
91993bf6008Sagc \brief Add data to memory
92093bf6008Sagc \param mem Memory to which to add
92193bf6008Sagc \param src Data to add
92293bf6008Sagc \param length Length of data to add
92393bf6008Sagc */
92493bf6008Sagc void
pgp_memory_add(pgp_memory_t * mem,const uint8_t * src,size_t length)925fc1f8641Sagc pgp_memory_add(pgp_memory_t *mem, const uint8_t *src, size_t length)
92693bf6008Sagc {
927fc1f8641Sagc 	pgp_memory_pad(mem, length);
92893bf6008Sagc 	(void) memcpy(mem->buf + mem->length, src, length);
92993bf6008Sagc 	mem->length += length;
93093bf6008Sagc }
93193bf6008Sagc 
93293bf6008Sagc /* XXX: this could be refactored via the writer, but an awful lot of */
93393bf6008Sagc /* hoops to jump through for 2 lines of code! */
93493bf6008Sagc void
pgp_memory_place_int(pgp_memory_t * mem,unsigned offset,unsigned n,size_t length)935fc1f8641Sagc pgp_memory_place_int(pgp_memory_t *mem, unsigned offset, unsigned n,
93693bf6008Sagc 		     size_t length)
93793bf6008Sagc {
938bcfd8565Sagc 	if (mem->allocated < offset + length) {
939bcfd8565Sagc 		(void) fprintf(stderr,
940fc1f8641Sagc 			"pgp_memory_place_int: bad alloc\n");
941bcfd8565Sagc 	} else {
9422232f800Sagc 		while (length-- > 0) {
94393bf6008Sagc 			mem->buf[offset++] = n >> (length * 8);
94493bf6008Sagc 		}
945bcfd8565Sagc 	}
946bcfd8565Sagc }
94793bf6008Sagc 
94893bf6008Sagc /**
94993bf6008Sagc  * \ingroup HighLevel_Memory
95093bf6008Sagc  * \brief Retains allocated memory and set length of stored data to zero.
95193bf6008Sagc  * \param mem Memory to clear
952fc1f8641Sagc  * \sa pgp_memory_release()
953fc1f8641Sagc  * \sa pgp_memory_free()
95493bf6008Sagc  */
95593bf6008Sagc void
pgp_memory_clear(pgp_memory_t * mem)956fc1f8641Sagc pgp_memory_clear(pgp_memory_t *mem)
95793bf6008Sagc {
95893bf6008Sagc 	mem->length = 0;
95993bf6008Sagc }
96093bf6008Sagc 
96193bf6008Sagc /**
96293bf6008Sagc \ingroup HighLevel_Memory
96393bf6008Sagc \brief Free memory and associated data
96493bf6008Sagc \param mem Memory to free
96593bf6008Sagc \note This does not free mem itself
966fc1f8641Sagc \sa pgp_memory_clear()
967fc1f8641Sagc \sa pgp_memory_free()
96893bf6008Sagc */
96993bf6008Sagc void
pgp_memory_release(pgp_memory_t * mem)970fc1f8641Sagc pgp_memory_release(pgp_memory_t *mem)
97193bf6008Sagc {
9720df5e957Sagc 	if (mem->mmapped) {
9730df5e957Sagc 		(void) munmap(mem->buf, mem->length);
9740df5e957Sagc 	} else {
975814ccb85Sagc 		free(mem->buf);
9760df5e957Sagc 	}
97793bf6008Sagc 	mem->buf = NULL;
97893bf6008Sagc 	mem->length = 0;
97993bf6008Sagc }
98093bf6008Sagc 
98193bf6008Sagc void
pgp_memory_make_packet(pgp_memory_t * out,pgp_content_enum tag)982fc1f8641Sagc pgp_memory_make_packet(pgp_memory_t *out, pgp_content_enum tag)
98393bf6008Sagc {
98493bf6008Sagc 	size_t          extra;
98593bf6008Sagc 
9862232f800Sagc 	extra = (out->length < 192) ? 1 : (out->length < 8192 + 192) ? 2 : 5;
987fc1f8641Sagc 	pgp_memory_pad(out, extra + 1);
98893bf6008Sagc 	memmove(out->buf + extra + 1, out->buf, out->length);
98993bf6008Sagc 
990fc1f8641Sagc 	out->buf[0] = PGP_PTAG_ALWAYS_SET | PGP_PTAG_NEW_FORMAT | tag;
99193bf6008Sagc 
9922232f800Sagc 	if (out->length < 192) {
99369d4f30fSagc 		out->buf[1] = (uint8_t)out->length;
9942232f800Sagc 	} else if (out->length < 8192 + 192) {
99569d4f30fSagc 		out->buf[1] = (uint8_t)((out->length - 192) >> 8) + 192;
99669d4f30fSagc 		out->buf[2] = (uint8_t)(out->length - 192);
99793bf6008Sagc 	} else {
99893bf6008Sagc 		out->buf[1] = 0xff;
99969d4f30fSagc 		out->buf[2] = (uint8_t)(out->length >> 24);
100069d4f30fSagc 		out->buf[3] = (uint8_t)(out->length >> 16);
100169d4f30fSagc 		out->buf[4] = (uint8_t)(out->length >> 8);
100269d4f30fSagc 		out->buf[5] = (uint8_t)(out->length);
100393bf6008Sagc 	}
100493bf6008Sagc 
100593bf6008Sagc 	out->length += extra + 1;
100693bf6008Sagc }
100793bf6008Sagc 
100893bf6008Sagc /**
100993bf6008Sagc    \ingroup HighLevel_Memory
1010fc1f8641Sagc    \brief Create a new zeroed pgp_memory_t
1011fc1f8641Sagc    \return Pointer to new pgp_memory_t
1012fc1f8641Sagc    \note Free using pgp_memory_free() after use.
1013fc1f8641Sagc    \sa pgp_memory_free()
101493bf6008Sagc */
101593bf6008Sagc 
1016fc1f8641Sagc pgp_memory_t   *
pgp_memory_new(void)1017fc1f8641Sagc pgp_memory_new(void)
101893bf6008Sagc {
1019fc1f8641Sagc 	return calloc(1, sizeof(pgp_memory_t));
102093bf6008Sagc }
102193bf6008Sagc 
102293bf6008Sagc /**
102393bf6008Sagc    \ingroup HighLevel_Memory
102493bf6008Sagc    \brief Free memory ptr and associated memory
102593bf6008Sagc    \param mem Memory to be freed
1026fc1f8641Sagc    \sa pgp_memory_release()
1027fc1f8641Sagc    \sa pgp_memory_clear()
102893bf6008Sagc */
102993bf6008Sagc 
103093bf6008Sagc void
pgp_memory_free(pgp_memory_t * mem)1031fc1f8641Sagc pgp_memory_free(pgp_memory_t *mem)
103293bf6008Sagc {
1033fc1f8641Sagc 	pgp_memory_release(mem);
1034814ccb85Sagc 	free(mem);
103593bf6008Sagc }
103693bf6008Sagc 
103793bf6008Sagc /**
103893bf6008Sagc    \ingroup HighLevel_Memory
1039fc1f8641Sagc    \brief Get length of data stored in pgp_memory_t struct
104093bf6008Sagc    \return Number of bytes in data
104193bf6008Sagc */
104293bf6008Sagc size_t
pgp_mem_len(const pgp_memory_t * mem)1043fc1f8641Sagc pgp_mem_len(const pgp_memory_t *mem)
104493bf6008Sagc {
104593bf6008Sagc 	return mem->length;
104693bf6008Sagc }
104793bf6008Sagc 
104893bf6008Sagc /**
104993bf6008Sagc    \ingroup HighLevel_Memory
1050fc1f8641Sagc    \brief Get data stored in pgp_memory_t struct
105193bf6008Sagc    \return Pointer to data
105293bf6008Sagc */
105393bf6008Sagc void *
pgp_mem_data(pgp_memory_t * mem)1054fc1f8641Sagc pgp_mem_data(pgp_memory_t *mem)
105593bf6008Sagc {
105693bf6008Sagc 	return mem->buf;
105793bf6008Sagc }
105893bf6008Sagc 
1059fc1f8641Sagc /* read a gile into an pgp_memory_t */
10600df5e957Sagc int
pgp_mem_readfile(pgp_memory_t * mem,const char * f)1061fc1f8641Sagc pgp_mem_readfile(pgp_memory_t *mem, const char *f)
10620df5e957Sagc {
10630df5e957Sagc 	struct stat	 st;
10640df5e957Sagc 	FILE		*fp;
10650df5e957Sagc 	int		 cc;
10660df5e957Sagc 
10670df5e957Sagc 	if ((fp = fopen(f, "rb")) == NULL) {
10680df5e957Sagc 		(void) fprintf(stderr,
1069fc1f8641Sagc 				"pgp_mem_readfile: can't open \"%s\"\n", f);
10700df5e957Sagc 		return 0;
10710df5e957Sagc 	}
10720df5e957Sagc 	(void) fstat(fileno(fp), &st);
10730df5e957Sagc 	mem->allocated = (size_t)st.st_size;
10740df5e957Sagc 	mem->buf = mmap(NULL, mem->allocated, PROT_READ,
1075814ccb85Sagc 				MAP_PRIVATE | MAP_FILE, fileno(fp), 0);
10760df5e957Sagc 	if (mem->buf == MAP_FAILED) {
10770df5e957Sagc 		/* mmap failed for some reason - try to allocate memory */
10780df5e957Sagc 		if ((mem->buf = calloc(1, mem->allocated)) == NULL) {
1079fc1f8641Sagc 			(void) fprintf(stderr, "pgp_mem_readfile: calloc\n");
10800df5e957Sagc 			(void) fclose(fp);
10810df5e957Sagc 			return 0;
10820df5e957Sagc 		}
10830df5e957Sagc 		/* read into contents of mem */
10840df5e957Sagc 		for (mem->length = 0 ;
1085593d671cSagc 		     (cc = (int)read(fileno(fp), &mem->buf[mem->length],
108669d4f30fSagc 					(size_t)(mem->allocated - mem->length))) > 0 ;
10870df5e957Sagc 		     mem->length += (size_t)cc) {
10880df5e957Sagc 		}
10890df5e957Sagc 	} else {
10900df5e957Sagc 		mem->length = mem->allocated;
10910df5e957Sagc 		mem->mmapped = 1;
10920df5e957Sagc 	}
10930df5e957Sagc 	(void) fclose(fp);
10940df5e957Sagc 	return (mem->allocated == mem->length);
10950df5e957Sagc }
10960df5e957Sagc 
109793bf6008Sagc typedef struct {
1098b15ec256Sagc 	uint16_t  sum;
109993bf6008Sagc } sum16_t;
110093bf6008Sagc 
110193bf6008Sagc 
110293bf6008Sagc /**
110393bf6008Sagc  * Searches the given map for the given type.
110493bf6008Sagc  * Returns a human-readable descriptive string if found,
110593bf6008Sagc  * returns NULL if not found
110693bf6008Sagc  *
110793bf6008Sagc  * It is the responsibility of the calling function to handle the
110893bf6008Sagc  * error case sensibly (i.e. don't just print out the return string.
110993bf6008Sagc  *
111093bf6008Sagc  */
111193bf6008Sagc static const char *
str_from_map_or_null(int type,pgp_map_t * map)1112fc1f8641Sagc str_from_map_or_null(int type, pgp_map_t *map)
111393bf6008Sagc {
1114fc1f8641Sagc 	pgp_map_t      *row;
111593bf6008Sagc 
111693bf6008Sagc 	for (row = map; row->string != NULL; row++) {
111793bf6008Sagc 		if (row->type == type) {
111893bf6008Sagc 			return row->string;
111993bf6008Sagc 		}
112093bf6008Sagc 	}
112193bf6008Sagc 	return NULL;
112293bf6008Sagc }
112393bf6008Sagc 
112493bf6008Sagc /**
112593bf6008Sagc  * \ingroup Core_Print
112693bf6008Sagc  *
112793bf6008Sagc  * Searches the given map for the given type.
112893bf6008Sagc  * Returns a readable string if found, "Unknown" if not.
112993bf6008Sagc  */
113093bf6008Sagc 
113193bf6008Sagc const char     *
pgp_str_from_map(int type,pgp_map_t * map)1132fc1f8641Sagc pgp_str_from_map(int type, pgp_map_t *map)
113393bf6008Sagc {
113493bf6008Sagc 	const char     *str;
113593bf6008Sagc 
113693bf6008Sagc 	str = str_from_map_or_null(type, map);
113793bf6008Sagc 	return (str) ? str : "Unknown";
113893bf6008Sagc }
113993bf6008Sagc 
114047561e26Sagc #define LINELEN	16
114193bf6008Sagc 
114247561e26Sagc /* show hexadecimal/ascii dump */
114347561e26Sagc void
hexdump(FILE * fp,const char * header,const uint8_t * src,size_t length)114447561e26Sagc hexdump(FILE *fp, const char *header, const uint8_t *src, size_t length)
114547561e26Sagc {
114647561e26Sagc 	size_t	i;
114747561e26Sagc 	char	line[LINELEN + 1];
114847561e26Sagc 
114947561e26Sagc 	(void) fprintf(fp, "%s%s", (header) ? header : "", (header) ? "\n" : "");
1150ad39646bSagc 	(void) fprintf(fp, "[%" PRIsize "u char%s]\n", length, (length == 1) ? "" : "s");
115147561e26Sagc 	for (i = 0 ; i < length ; i++) {
115247561e26Sagc 		if (i % LINELEN == 0) {
1153ad39646bSagc 			(void) fprintf(fp, "%.5" PRIsize "u | ", i);
115447561e26Sagc 		}
115547561e26Sagc 		(void) fprintf(fp, "%.02x ", (uint8_t)src[i]);
115647561e26Sagc 		line[i % LINELEN] = (isprint(src[i])) ? src[i] : '.';
115747561e26Sagc 		if (i % LINELEN == LINELEN - 1) {
115847561e26Sagc 			line[LINELEN] = 0x0;
115947561e26Sagc 			(void) fprintf(fp, " | %s\n", line);
116047561e26Sagc 		}
116147561e26Sagc 	}
116247561e26Sagc 	if (i % LINELEN != 0) {
116347561e26Sagc 		for ( ; i % LINELEN != 0 ; i++) {
116447561e26Sagc 			(void) fprintf(fp, "   ");
116547561e26Sagc 			line[i % LINELEN] = ' ';
116647561e26Sagc 		}
116747561e26Sagc 		line[LINELEN] = 0x0;
116847561e26Sagc 		(void) fprintf(fp, " | %s\n", line);
116993bf6008Sagc 	}
117093bf6008Sagc }
117193bf6008Sagc 
117293bf6008Sagc /**
117393bf6008Sagc  * \ingroup HighLevel_Functions
117493bf6008Sagc  * \brief Closes down OpenPGP::SDK.
117593bf6008Sagc  *
117693bf6008Sagc  * Close down OpenPGP:SDK, release any resources under the control of
1177651dd288Sagc  * the library.
117893bf6008Sagc  */
117993bf6008Sagc 
118093bf6008Sagc void
pgp_finish(void)1181fc1f8641Sagc pgp_finish(void)
118293bf6008Sagc {
1183fc1f8641Sagc 	pgp_crypto_finish();
118493bf6008Sagc }
118593bf6008Sagc 
118693bf6008Sagc static int
sum16_reader(pgp_stream_t * stream,void * dest_,size_t length,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)1187b0df0a22Sagc sum16_reader(pgp_stream_t *stream, void *dest_, size_t length, pgp_error_t **errors,
1188fc1f8641Sagc 	     pgp_reader_t *readinfo, pgp_cbdata_t *cbinfo)
118993bf6008Sagc {
1190b15ec256Sagc 	const uint8_t	*dest = dest_;
1191fc1f8641Sagc 	sum16_t		*arg = pgp_reader_get_arg(readinfo);
11922232f800Sagc 	int		 r;
119393bf6008Sagc 	int		 n;
119493bf6008Sagc 
1195b0df0a22Sagc 	r = pgp_stacked_read(stream, dest_, length, errors, readinfo, cbinfo);
119693bf6008Sagc 	if (r < 0) {
119793bf6008Sagc 		return r;
119893bf6008Sagc 	}
119993bf6008Sagc 	for (n = 0; n < r; ++n) {
120093bf6008Sagc 		arg->sum = (arg->sum + dest[n]) & 0xffff;
120193bf6008Sagc 	}
120293bf6008Sagc 	return r;
120393bf6008Sagc }
120493bf6008Sagc 
120593bf6008Sagc static void
sum16_destroyer(pgp_reader_t * readinfo)1206fc1f8641Sagc sum16_destroyer(pgp_reader_t *readinfo)
120793bf6008Sagc {
1208fc1f8641Sagc 	free(pgp_reader_get_arg(readinfo));
120993bf6008Sagc }
121093bf6008Sagc 
121193bf6008Sagc /**
121293bf6008Sagc    \ingroup Internal_Readers_Sum16
121341335e2dSagc    \param stream Parse settings
121493bf6008Sagc */
121593bf6008Sagc 
121693bf6008Sagc void
pgp_reader_push_sum16(pgp_stream_t * stream)1217fc1f8641Sagc pgp_reader_push_sum16(pgp_stream_t *stream)
121893bf6008Sagc {
12197affbacaSagc 	sum16_t    *arg;
122093bf6008Sagc 
12217affbacaSagc 	if ((arg = calloc(1, sizeof(*arg))) == NULL) {
1222fc1f8641Sagc 		(void) fprintf(stderr, "pgp_reader_push_sum16: bad alloc\n");
12237affbacaSagc 	} else {
1224fc1f8641Sagc 		pgp_reader_push(stream, sum16_reader, sum16_destroyer, arg);
122593bf6008Sagc 	}
12267affbacaSagc }
122793bf6008Sagc 
122893bf6008Sagc /**
122993bf6008Sagc    \ingroup Internal_Readers_Sum16
123041335e2dSagc    \param stream Parse settings
123193bf6008Sagc    \return sum
123293bf6008Sagc */
1233b15ec256Sagc uint16_t
pgp_reader_pop_sum16(pgp_stream_t * stream)1234fc1f8641Sagc pgp_reader_pop_sum16(pgp_stream_t *stream)
123593bf6008Sagc {
1236b15ec256Sagc 	uint16_t	 sum;
12374b3a3e18Sagc 	sum16_t		*arg;
123893bf6008Sagc 
1239fc1f8641Sagc 	arg = pgp_reader_get_arg(pgp_readinfo(stream));
12404b3a3e18Sagc 	sum = arg->sum;
1241fc1f8641Sagc 	pgp_reader_pop(stream);
124293bf6008Sagc 	free(arg);
124393bf6008Sagc 	return sum;
124493bf6008Sagc }
124593bf6008Sagc 
124693bf6008Sagc /* small useful functions for setting the file-level debugging levels */
124793bf6008Sagc /* if the debugv list contains the filename in question, we're debugging it */
124893bf6008Sagc 
124993bf6008Sagc enum {
125093bf6008Sagc 	MAX_DEBUG_NAMES = 32
125193bf6008Sagc };
125293bf6008Sagc 
125393bf6008Sagc static int      debugc;
125493bf6008Sagc static char    *debugv[MAX_DEBUG_NAMES];
125593bf6008Sagc 
125693bf6008Sagc /* set the debugging level per filename */
125793bf6008Sagc int
pgp_set_debug_level(const char * f)1258fc1f8641Sagc pgp_set_debug_level(const char *f)
125993bf6008Sagc {
126093bf6008Sagc 	const char     *name;
126193bf6008Sagc 	int             i;
126293bf6008Sagc 
126393bf6008Sagc 	if (f == NULL) {
126493bf6008Sagc 		f = "all";
126593bf6008Sagc 	}
126693bf6008Sagc 	if ((name = strrchr(f, '/')) == NULL) {
126793bf6008Sagc 		name = f;
126893bf6008Sagc 	} else {
126993bf6008Sagc 		name += 1;
127093bf6008Sagc 	}
127193bf6008Sagc 	for (i = 0; i < debugc && i < MAX_DEBUG_NAMES; i++) {
127293bf6008Sagc 		if (strcmp(debugv[i], name) == 0) {
127393bf6008Sagc 			return 1;
127493bf6008Sagc 		}
127593bf6008Sagc 	}
127693bf6008Sagc 	if (i == MAX_DEBUG_NAMES) {
127793bf6008Sagc 		return 0;
127893bf6008Sagc 	}
1279b15ec256Sagc 	debugv[debugc++] = netpgp_strdup(name);
128093bf6008Sagc 	return 1;
128193bf6008Sagc }
128293bf6008Sagc 
128393bf6008Sagc /* get the debugging level per filename */
128493bf6008Sagc int
pgp_get_debug_level(const char * f)1285fc1f8641Sagc pgp_get_debug_level(const char *f)
128693bf6008Sagc {
128793bf6008Sagc 	const char     *name;
128893bf6008Sagc 	int             i;
128993bf6008Sagc 
129093bf6008Sagc 	if ((name = strrchr(f, '/')) == NULL) {
129193bf6008Sagc 		name = f;
129293bf6008Sagc 	} else {
129393bf6008Sagc 		name += 1;
129493bf6008Sagc 	}
129593bf6008Sagc 	for (i = 0; i < debugc; i++) {
129693bf6008Sagc 		if (strcmp(debugv[i], "all") == 0 ||
129793bf6008Sagc 		    strcmp(debugv[i], name) == 0) {
129893bf6008Sagc 			return 1;
129993bf6008Sagc 		}
130093bf6008Sagc 	}
130193bf6008Sagc 	return 0;
130293bf6008Sagc }
130393bf6008Sagc 
130493bf6008Sagc /* return the version for the library */
130593bf6008Sagc const char *
pgp_get_info(const char * type)1306fc1f8641Sagc pgp_get_info(const char *type)
130793bf6008Sagc {
130893bf6008Sagc 	if (strcmp(type, "version") == 0) {
130993bf6008Sagc 		return NETPGP_VERSION_STRING;
131093bf6008Sagc 	}
131193bf6008Sagc 	if (strcmp(type, "maintainer") == 0) {
131293bf6008Sagc 		return NETPGP_MAINTAINER;
131393bf6008Sagc 	}
131493bf6008Sagc 	return "[unknown]";
131593bf6008Sagc }
1316d21b929eSagc 
13179e63cf3fSagc /* local version of asprintf so we don't have to play autoconf games */
13189e63cf3fSagc int
pgp_asprintf(char ** ret,const char * fmt,...)1319fc1f8641Sagc pgp_asprintf(char **ret, const char *fmt, ...)
13209e63cf3fSagc {
13219e63cf3fSagc 	va_list args;
13229e63cf3fSagc 	char    buf[120 * 1024];	/* XXX - "huge" buffer on stack */
13239e63cf3fSagc 	int     cc;
13249e63cf3fSagc 
13259e63cf3fSagc 	va_start(args, fmt);
13269e63cf3fSagc 	cc = vsnprintf(buf, sizeof(buf), fmt, args);
13279e63cf3fSagc 	va_end(args);
13289e63cf3fSagc 	if ((*ret = calloc(1, (size_t)(cc + 1))) == NULL) {
13299e63cf3fSagc 		*ret = NULL;
13309e63cf3fSagc 		return -1;
13319e63cf3fSagc 	}
13329e63cf3fSagc 	(void) memcpy(*ret, buf, (size_t)cc);
13339e63cf3fSagc 	(*ret)[cc] = 0x0;
13349e63cf3fSagc 	return cc;
13359e63cf3fSagc }
13369e63cf3fSagc 
1337d21b929eSagc void
netpgp_log(const char * fmt,...)1338d21b929eSagc netpgp_log(const char *fmt, ...)
1339d21b929eSagc {
1340d21b929eSagc 	va_list	 vp;
1341d21b929eSagc 	time_t	 t;
1342d21b929eSagc 	char	 buf[BUFSIZ * 2];
1343d21b929eSagc 	int	 cc;
1344d21b929eSagc 
1345d21b929eSagc 	(void) time(&t);
13464167ec87Schristos 	cc = snprintf(buf, sizeof(buf), "%.24s: netpgp: ", ctime(&t));
1347d21b929eSagc 	va_start(vp, fmt);
1348814ccb85Sagc 	(void) vsnprintf(&buf[cc], sizeof(buf) - (size_t)cc, fmt, vp);
1349d21b929eSagc 	va_end(vp);
1350d21b929eSagc 	/* do something with message */
1351d21b929eSagc 	/* put into log buffer? */
1352d21b929eSagc }
1353b15ec256Sagc 
1354b15ec256Sagc /* portable replacement for strdup(3) */
1355b15ec256Sagc char *
netpgp_strdup(const char * s)1356b15ec256Sagc netpgp_strdup(const char *s)
1357b15ec256Sagc {
1358b15ec256Sagc 	size_t	 len;
1359b15ec256Sagc 	char	*cp;
1360b15ec256Sagc 
1361b15ec256Sagc 	len = strlen(s);
1362b15ec256Sagc 	if ((cp = calloc(1, len + 1)) != NULL) {
1363b15ec256Sagc 		(void) memcpy(cp, s, len);
1364b15ec256Sagc 		cp[len] = 0x0;
1365b15ec256Sagc 	}
1366b15ec256Sagc 	return cp;
1367b15ec256Sagc }
1368b15ec256Sagc 
1369b15ec256Sagc /* portable replacement for strcasecmp(3) */
1370b15ec256Sagc int
netpgp_strcasecmp(const char * s1,const char * s2)1371b15ec256Sagc netpgp_strcasecmp(const char *s1, const char *s2)
1372b15ec256Sagc {
1373b15ec256Sagc 	int	n;
1374b15ec256Sagc 
1375fdfbba49Sagc 	for (n = 0 ; *s1 && *s2 && (n = tolower((uint8_t)*s1) - tolower((uint8_t)*s2)) == 0 ; s1++, s2++) {
1376b15ec256Sagc 	}
1377b15ec256Sagc 	return n;
1378b15ec256Sagc }
1379*0294a66bSjhigh 
1380*0294a66bSjhigh int
ecdsa_nid(const pgp_ecdsa_pubkey_t * pub)1381*0294a66bSjhigh ecdsa_nid(const pgp_ecdsa_pubkey_t * pub)
1382*0294a66bSjhigh {
1383*0294a66bSjhigh 	int i;
1384*0294a66bSjhigh 
1385*0294a66bSjhigh 	for (i = 0; ecdsa_map[i].sname; i++ ) {
1386*0294a66bSjhigh 		if (pub->len == ecdsa_map[i].len) {
1387*0294a66bSjhigh 			if (memcmp(pub->oid, ecdsa_map[i].oid, pub->len) == 0) {
1388*0294a66bSjhigh 				return ecdsa_map[i].nid;
1389*0294a66bSjhigh 			}
1390*0294a66bSjhigh 		}
1391*0294a66bSjhigh 	}
1392*0294a66bSjhigh 	return -1;
1393*0294a66bSjhigh }
1394*0294a66bSjhigh 
1395*0294a66bSjhigh int
ecdsa_numbits(const pgp_ecdsa_pubkey_t * pub)1396*0294a66bSjhigh ecdsa_numbits(const pgp_ecdsa_pubkey_t * pub)
1397*0294a66bSjhigh {
1398*0294a66bSjhigh 	int i;
1399*0294a66bSjhigh 
1400*0294a66bSjhigh 	for (i = 0; ecdsa_map[i].sname; i++ ) {
1401*0294a66bSjhigh 		if (pub->len == ecdsa_map[i].len) {
1402*0294a66bSjhigh 			if (memcmp(pub->oid, ecdsa_map[i].oid, pub->len) == 0) {
1403*0294a66bSjhigh 				return ecdsa_map[i].bits;
1404*0294a66bSjhigh 			}
1405*0294a66bSjhigh 		}
1406*0294a66bSjhigh 	}
1407*0294a66bSjhigh 	return -1;
1408*0294a66bSjhigh }
1409*0294a66bSjhigh 
1410*0294a66bSjhigh int
ecdsa_hashsize(const pgp_ecdsa_pubkey_t * pub)1411*0294a66bSjhigh ecdsa_hashsize(const pgp_ecdsa_pubkey_t * pub)
1412*0294a66bSjhigh {
1413*0294a66bSjhigh 	int bits;
1414*0294a66bSjhigh 
1415*0294a66bSjhigh 	bits = ecdsa_numbits(pub);
1416*0294a66bSjhigh 
1417*0294a66bSjhigh 	if (bits == -1) {
1418*0294a66bSjhigh 		return -1;
1419*0294a66bSjhigh 	}
1420*0294a66bSjhigh 
1421*0294a66bSjhigh 	return (bits/8) - (bits%8);
1422*0294a66bSjhigh }
1423*0294a66bSjhigh 
1424*0294a66bSjhigh pgp_hash_alg_t
ecdsa_hashalg(const pgp_ecdsa_pubkey_t * pub)1425*0294a66bSjhigh ecdsa_hashalg(const pgp_ecdsa_pubkey_t * pub)
1426*0294a66bSjhigh {
1427*0294a66bSjhigh 	int nid;
1428*0294a66bSjhigh 
1429*0294a66bSjhigh 	if (pub == NULL) {
1430*0294a66bSjhigh 		return PGP_HASH_UNKNOWN;
1431*0294a66bSjhigh 	}
1432*0294a66bSjhigh 
1433*0294a66bSjhigh 	nid = ecdsa_nid(pub);
1434*0294a66bSjhigh 
1435*0294a66bSjhigh 	switch (nid) {
1436*0294a66bSjhigh 		case NID_X9_62_prime256v1:
1437*0294a66bSjhigh 			return PGP_HASH_SHA256;
1438*0294a66bSjhigh 
1439*0294a66bSjhigh 		case NID_secp384r1:
1440*0294a66bSjhigh 			return PGP_HASH_SHA384;
1441*0294a66bSjhigh 
1442*0294a66bSjhigh 		case NID_secp521r1:
1443*0294a66bSjhigh 			return PGP_HASH_SHA512;
1444*0294a66bSjhigh 
1445*0294a66bSjhigh 		default:
1446*0294a66bSjhigh 			(void) fprintf(stderr, "ecdsa_hashalg: unknown NID\n");
1447*0294a66bSjhigh 	}
1448*0294a66bSjhigh 
1449*0294a66bSjhigh 	return PGP_HASH_UNKNOWN;
1450*0294a66bSjhigh }
1451