xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/misc.c (revision 4167ec87c5dd05d129a0a76f78b747012d21ce6b)
1 /*-
2  * Copyright (c) 2009,2010 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by Alistair Crooks (agc@NetBSD.org)
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 /*
30  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31  * All rights reserved.
32  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33  * their moral rights under the UK Copyright Design and Patents Act 1988 to
34  * be recorded as the authors of this copyright work.
35  *
36  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37  * use this file except in compliance with the License.
38  *
39  * You may obtain a copy of the License at
40  *     http://www.apache.org/licenses/LICENSE-2.0
41  *
42  * Unless required by applicable law or agreed to in writing, software
43  * distributed under the License is distributed on an "AS IS" BASIS,
44  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
45  *
46  * See the License for the specific language governing permissions and
47  * limitations under the License.
48  */
49 
50 /** \file
51  */
52 #include "config.h"
53 
54 #ifdef HAVE_SYS_CDEFS_H
55 #include <sys/cdefs.h>
56 #endif
57 
58 #if defined(__NetBSD__)
59 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60 __RCSID("$NetBSD: misc.c,v 1.28 2010/04/02 15:28:16 christos Exp $");
61 #endif
62 
63 #include <sys/types.h>
64 #include <sys/stat.h>
65 #include <sys/mman.h>
66 
67 #include <stdarg.h>
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71 
72 #ifdef HAVE_UNISTD_H
73 #include <unistd.h>
74 #endif
75 
76 #ifdef HAVE_OPENSSL_RAND_H
77 #include <openssl/rand.h>
78 #endif
79 
80 #include "errors.h"
81 #include "packet.h"
82 #include "crypto.h"
83 #include "create.h"
84 #include "fastctype.h"
85 #include "packet-parse.h"
86 #include "packet-show.h"
87 #include "signature.h"
88 #include "netpgpsdk.h"
89 #include "netpgpdefs.h"
90 #include "memory.h"
91 #include "readerwriter.h"
92 #include "version.h"
93 #include "netpgpdigest.h"
94 
95 #ifdef WIN32
96 #define vsnprintf _vsnprintf
97 #endif
98 
99 
100 typedef struct {
101 	__ops_keyring_t  *keyring;
102 } accumulate_t;
103 
104 /**
105  * \ingroup Core_Callbacks
106  */
107 static __ops_cb_ret_t
108 accumulate_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
109 {
110 	const __ops_contents_t	*content = &pkt->u;
111 	__ops_keyring_t		*keyring;
112 	accumulate_t		*accumulate;
113 
114 	accumulate = __ops_callback_arg(cbinfo);
115 	keyring = accumulate->keyring;
116 	switch (pkt->tag) {
117 	case OPS_PTAG_CT_PUBLIC_KEY:
118 	case OPS_PTAG_CT_SECRET_KEY:
119 	case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
120 		if (__ops_get_debug_level(__FILE__)) {
121 			(void) fprintf(stderr, "Creating key %u - tag %u\n",
122 				keyring->keyc, pkt->tag);
123 		}
124 		if (pkt->tag == OPS_PTAG_CT_PUBLIC_KEY) {
125 			__ops_add_to_pubring(keyring, &content->pubkey);
126 		} else {
127 			__ops_add_to_secring(keyring, &content->seckey);
128 		}
129 		return OPS_KEEP_MEMORY;
130 	case OPS_PTAG_CT_USER_ID:
131 		if (__ops_get_debug_level(__FILE__)) {
132 			(void) fprintf(stderr, "User ID: %s for key %d\n",
133 					content->userid.userid,
134 					keyring->keyc - 1);
135 		}
136 		if (keyring->keyc > 0) {
137 			__ops_add_userid(&keyring->keys[keyring->keyc - 1],
138 						&content->userid);
139 			return OPS_KEEP_MEMORY;
140 		}
141 		OPS_ERROR(cbinfo->errors, OPS_E_P_NO_USERID, "No userid found");
142 		return OPS_KEEP_MEMORY;
143 
144 	case OPS_PARSER_PACKET_END:
145 		if (keyring->keyc > 0) {
146 			__ops_add_subpacket(&keyring->keys[keyring->keyc - 1],
147 						&content->packet);
148 			return OPS_KEEP_MEMORY;
149 		}
150 		return OPS_RELEASE_MEMORY;
151 
152 	case OPS_PARSER_ERROR:
153 		(void) fprintf(stderr, "Error: %s\n", content->error.error);
154 		return OPS_FINISHED;
155 
156 	case OPS_PARSER_ERRCODE:
157 		(void) fprintf(stderr, "parse error: %s\n",
158 				__ops_errcode(content->errcode.errcode));
159 		break;
160 
161 	default:
162 		break;
163 	}
164 
165 	/* XXX: we now exclude so many things, we should either drop this or */
166 	/* do something to pass on copies of the stuff we keep */
167 	return __ops_stacked_callback(pkt, cbinfo);
168 }
169 
170 /**
171  * \ingroup Core_Parse
172  *
173  * Parse packets from an input stream until EOF or error.
174  *
175  * Key data found in the parsed data is added to #keyring.
176  *
177  * \param keyring Pointer to an existing keyring
178  * \param parse Options to use when parsing
179 */
180 int
181 __ops_parse_and_accumulate(__ops_keyring_t *keyring, __ops_stream_t *parse)
182 {
183 	accumulate_t	accumulate;
184 	const int	printerrors = 1;
185 	int             ret;
186 
187 	if (parse->readinfo.accumulate) {
188 		(void) fprintf(stderr,
189 			"__ops_parse_and_accumulate: already init\n");
190 		return 0;
191 	}
192 
193 	(void) memset(&accumulate, 0x0, sizeof(accumulate));
194 
195 	accumulate.keyring = keyring;
196 
197 	__ops_callback_push(parse, accumulate_cb, &accumulate);
198 	parse->readinfo.accumulate = 1;
199 	ret = __ops_parse(parse, !printerrors);
200 
201 	return ret;
202 }
203 
204 
205 /** \file
206  * \brief Error Handling
207  */
208 #define ERRNAME(code)	{ code, #code }
209 
210 static __ops_errcode_name_map_t errcode_name_map[] = {
211 	ERRNAME(OPS_E_OK),
212 	ERRNAME(OPS_E_FAIL),
213 	ERRNAME(OPS_E_SYSTEM_ERROR),
214 	ERRNAME(OPS_E_UNIMPLEMENTED),
215 
216 	ERRNAME(OPS_E_R),
217 	ERRNAME(OPS_E_R_READ_FAILED),
218 	ERRNAME(OPS_E_R_EARLY_EOF),
219 	ERRNAME(OPS_E_R_BAD_FORMAT),
220 	ERRNAME(OPS_E_R_UNCONSUMED_DATA),
221 
222 	ERRNAME(OPS_E_W),
223 	ERRNAME(OPS_E_W_WRITE_FAILED),
224 	ERRNAME(OPS_E_W_WRITE_TOO_SHORT),
225 
226 	ERRNAME(OPS_E_P),
227 	ERRNAME(OPS_E_P_NOT_ENOUGH_DATA),
228 	ERRNAME(OPS_E_P_UNKNOWN_TAG),
229 	ERRNAME(OPS_E_P_PACKET_CONSUMED),
230 	ERRNAME(OPS_E_P_MPI_FORMAT_ERROR),
231 
232 	ERRNAME(OPS_E_C),
233 
234 	ERRNAME(OPS_E_V),
235 	ERRNAME(OPS_E_V_BAD_SIGNATURE),
236 	ERRNAME(OPS_E_V_NO_SIGNATURE),
237 	ERRNAME(OPS_E_V_UNKNOWN_SIGNER),
238 
239 	ERRNAME(OPS_E_ALG),
240 	ERRNAME(OPS_E_ALG_UNSUPPORTED_SYMMETRIC_ALG),
241 	ERRNAME(OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG),
242 	ERRNAME(OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG),
243 	ERRNAME(OPS_E_ALG_UNSUPPORTED_HASH_ALG),
244 
245 	ERRNAME(OPS_E_PROTO),
246 	ERRNAME(OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT),
247 	ERRNAME(OPS_E_PROTO_UNKNOWN_SS),
248 	ERRNAME(OPS_E_PROTO_CRITICAL_SS_IGNORED),
249 	ERRNAME(OPS_E_PROTO_BAD_PUBLIC_KEY_VRSN),
250 	ERRNAME(OPS_E_PROTO_BAD_SIGNATURE_VRSN),
251 	ERRNAME(OPS_E_PROTO_BAD_ONE_PASS_SIG_VRSN),
252 	ERRNAME(OPS_E_PROTO_BAD_PKSK_VRSN),
253 	ERRNAME(OPS_E_PROTO_DECRYPTED_MSG_WRONG_LEN),
254 	ERRNAME(OPS_E_PROTO_BAD_SK_CHECKSUM),
255 
256 	{0x00, NULL},		/* this is the end-of-array marker */
257 };
258 
259 /**
260  * \ingroup Core_Errors
261  * \brief returns error code name
262  * \param errcode
263  * \return error code name or "Unknown"
264  */
265 const char     *
266 __ops_errcode(const __ops_errcode_t errcode)
267 {
268 	return (__ops_str_from_map((int) errcode,
269 			(__ops_map_t *) errcode_name_map));
270 }
271 
272 /* generic grab new storage function */
273 void *
274 __ops_new(size_t size)
275 {
276 	void	*vp;
277 
278 	if ((vp = calloc(1, size)) == NULL) {
279 		(void) fprintf(stderr,
280 			"allocation failure for %" PRIsize "u bytes", size);
281 	}
282 	return vp;
283 }
284 
285 /**
286  * \ingroup Core_Errors
287  * \brief Pushes the given error on the given errorstack
288  * \param errstack Error stack to use
289  * \param errcode Code of error to push
290  * \param sys_errno System errno (used if errcode=OPS_E_SYSTEM_ERROR)
291  * \param file Source filename where error occurred
292  * \param line Line in source file where error occurred
293  * \param fmt Comment
294  *
295  */
296 
297 void
298 __ops_push_error(__ops_error_t **errstack, __ops_errcode_t errcode,
299 		int sys_errno, const char *file, int line, const char *fmt,...)
300 {
301 	/* first get the varargs and generate the comment */
302 	__ops_error_t  *err;
303 	unsigned	maxbuf = 128;
304 	va_list		args;
305 	char           *comment;
306 
307 	if ((comment = calloc(1, maxbuf + 1)) == NULL) {
308 		(void) fprintf(stderr, "calloc comment failure\n");
309 		return;
310 	}
311 
312 	va_start(args, fmt);
313 	vsnprintf(comment, maxbuf + 1, fmt, args);
314 	va_end(args);
315 
316 	/* alloc a new error and add it to the top of the stack */
317 
318 	if ((err = calloc(1, sizeof(*err))) == NULL) {
319 		(void) fprintf(stderr, "calloc comment failure\n");
320 		return;
321 	}
322 
323 	err->next = *errstack;
324 	*errstack = err;
325 
326 	/* fill in the details */
327 	err->errcode = errcode;
328 	err->sys_errno = sys_errno;
329 	err->file = file;
330 	err->line = line;
331 
332 	err->comment = comment;
333 }
334 
335 /**
336 \ingroup Core_Errors
337 \brief print this error
338 \param err Error to print
339 */
340 void
341 __ops_print_error(__ops_error_t *err)
342 {
343 	printf("%s:%d: ", err->file, err->line);
344 	if (err->errcode == OPS_E_SYSTEM_ERROR) {
345 		printf("system error %d returned from %s()\n", err->sys_errno,
346 		       err->comment);
347 	} else {
348 		printf("%s, %s\n", __ops_errcode(err->errcode), err->comment);
349 	}
350 }
351 
352 /**
353 \ingroup Core_Errors
354 \brief Print all errors on stack
355 \param errstack Error stack to print
356 */
357 void
358 __ops_print_errors(__ops_error_t *errstack)
359 {
360 	__ops_error_t    *err;
361 
362 	for (err = errstack; err != NULL; err = err->next) {
363 		__ops_print_error(err);
364 	}
365 }
366 
367 /**
368 \ingroup Core_Errors
369 \brief Return 1 if given error is present anywhere on stack
370 \param errstack Error stack to check
371 \param errcode Error code to look for
372 \return 1 if found; else 0
373 */
374 int
375 __ops_has_error(__ops_error_t *errstack, __ops_errcode_t errcode)
376 {
377 	__ops_error_t    *err;
378 
379 	for (err = errstack; err != NULL; err = err->next) {
380 		if (err->errcode == errcode) {
381 			return 1;
382 		}
383 	}
384 	return 0;
385 }
386 
387 /**
388 \ingroup Core_Errors
389 \brief Frees all errors on stack
390 \param errstack Error stack to free
391 */
392 void
393 __ops_free_errors(__ops_error_t *errstack)
394 {
395 	__ops_error_t    *next;
396 
397 	while (errstack != NULL) {
398 		next = errstack->next;
399 		free(errstack->comment);
400 		free(errstack);
401 		errstack = next;
402 	}
403 }
404 
405 /** \file
406  */
407 
408 /**
409  * \ingroup Core_Keys
410  * \brief Calculate a public key fingerprint.
411  * \param fp Where to put the calculated fingerprint
412  * \param key The key for which the fingerprint is calculated
413  */
414 
415 void
416 __ops_fingerprint(__ops_fingerprint_t *fp, const __ops_pubkey_t *key)
417 {
418 	if (key->version == 2 || key->version == 3) {
419 		unsigned char  *bn;
420 		size_t		n;
421 		__ops_hash_t	md5;
422 
423 		if (key->alg != OPS_PKA_RSA &&
424 		    key->alg != OPS_PKA_RSA_ENCRYPT_ONLY &&
425 		    key->alg != OPS_PKA_RSA_SIGN_ONLY) {
426 			(void) fprintf(stderr,
427 				"__ops_fingerprint: bad algorithm\n");
428 			return;
429 		}
430 
431 		__ops_hash_md5(&md5);
432 		if (!md5.init(&md5)) {
433 			(void) fprintf(stderr,
434 				"__ops_fingerprint: bad md5 alloc\n");
435 				return;
436 		}
437 
438 		n = (size_t) BN_num_bytes(key->key.rsa.n);
439 		if ((bn = calloc(1, n)) == NULL) {
440 			(void) fprintf(stderr,
441 				"__ops_fingerprint: bad bn alloc\n");
442 			return;
443 		}
444 		BN_bn2bin(key->key.rsa.n, bn);
445 		md5.add(&md5, bn, n);
446 		free(bn);
447 
448 		n = (size_t) BN_num_bytes(key->key.rsa.e);
449 		if ((bn = calloc(1, n)) == NULL) {
450 			(void) fprintf(stderr,
451 				"__ops_fingerprint: bad bn alloc 2\n");
452 			return;
453 		}
454 		BN_bn2bin(key->key.rsa.e, bn);
455 		md5.add(&md5, bn, n);
456 		free(bn);
457 
458 		md5.finish(&md5, fp->fingerprint);
459 		fp->length = 16;
460 	} else {
461 		__ops_memory_t	*mem = __ops_memory_new();
462 		__ops_hash_t	 sha1;
463 		size_t		 len;
464 
465 		__ops_build_pubkey(mem, key, 0);
466 
467 		if (__ops_get_debug_level(__FILE__)) {
468 			fprintf(stderr, "-> creating key fingerprint\n");
469 		}
470 		__ops_hash_sha1(&sha1);
471 		if (!sha1.init(&sha1)) {
472 			(void) fprintf(stderr,
473 				"__ops_fingerprint: bad sha1 alloc\n");
474 			return;
475 		}
476 
477 		len = __ops_mem_len(mem);
478 
479 		__ops_hash_add_int(&sha1, 0x99, 1);
480 		__ops_hash_add_int(&sha1, len, 2);
481 		sha1.add(&sha1, __ops_mem_data(mem), len);
482 		sha1.finish(&sha1, fp->fingerprint);
483 
484 		if (__ops_get_debug_level(__FILE__)) {
485 			fprintf(stderr, "<- finished making key fingerprint\n");
486 		}
487 		fp->length = OPS_FINGERPRINT_SIZE;
488 
489 		__ops_memory_free(mem);
490 	}
491 }
492 
493 /**
494  * \ingroup Core_Keys
495  * \brief Calculate the Key ID from the public key.
496  * \param keyid Space for the calculated ID to be stored
497  * \param key The key for which the ID is calculated
498  */
499 
500 void
501 __ops_keyid(uint8_t *keyid, const size_t idlen, const __ops_pubkey_t *key)
502 {
503 	__ops_fingerprint_t finger;
504 
505 	if (key->version == 2 || key->version == 3) {
506 		unsigned	n;
507 		uint8_t		bn[NETPGP_BUFSIZ];
508 
509 		n = (unsigned) BN_num_bytes(key->key.rsa.n);
510 		if (n > sizeof(bn)) {
511 			(void) fprintf(stderr, "__ops_keyid: bad num bytes\n");
512 			return;
513 		}
514 		if (key->alg != OPS_PKA_RSA &&
515 		    key->alg != OPS_PKA_RSA_ENCRYPT_ONLY &&
516 		    key->alg != OPS_PKA_RSA_SIGN_ONLY) {
517 			(void) fprintf(stderr, "__ops_keyid: bad algorithm\n");
518 			return;
519 		}
520 		BN_bn2bin(key->key.rsa.n, bn);
521 		(void) memcpy(keyid, bn + n - idlen, idlen);
522 	} else {
523 		__ops_fingerprint(&finger, key);
524 		(void) memcpy(keyid,
525 				finger.fingerprint + finger.length - idlen,
526 				idlen);
527 	}
528 }
529 
530 /**
531 \ingroup Core_Hashes
532 \brief Add to the hash
533 \param hash Hash to add to
534 \param n Int to add
535 \param length Length of int in bytes
536 */
537 void
538 __ops_hash_add_int(__ops_hash_t *hash, unsigned n, unsigned length)
539 {
540 	uint8_t   c;
541 
542 	while (length--) {
543 		c = n >> (length * 8);
544 		hash->add(hash, &c, 1);
545 	}
546 }
547 
548 /**
549 \ingroup Core_Hashes
550 \brief Setup hash for given hash algorithm
551 \param hash Hash to set up
552 \param alg Hash algorithm to use
553 */
554 void
555 __ops_hash_any(__ops_hash_t *hash, __ops_hash_alg_t alg)
556 {
557 	switch (alg) {
558 	case OPS_HASH_MD5:
559 		__ops_hash_md5(hash);
560 		break;
561 
562 	case OPS_HASH_SHA1:
563 		__ops_hash_sha1(hash);
564 		break;
565 
566 	case OPS_HASH_SHA256:
567 		__ops_hash_sha256(hash);
568 		break;
569 
570 	case OPS_HASH_SHA384:
571 		__ops_hash_sha384(hash);
572 		break;
573 
574 	case OPS_HASH_SHA512:
575 		__ops_hash_sha512(hash);
576 		break;
577 
578 	case OPS_HASH_SHA224:
579 		__ops_hash_sha224(hash);
580 		break;
581 
582 	default:
583 		(void) fprintf(stderr, "__ops_hash_any: bad algorithm\n");
584 	}
585 }
586 
587 /**
588 \ingroup Core_Hashes
589 \brief Returns size of hash for given hash algorithm
590 \param alg Hash algorithm to use
591 \return Size of hash algorithm in bytes
592 */
593 unsigned
594 __ops_hash_size(__ops_hash_alg_t alg)
595 {
596 	switch (alg) {
597 	case OPS_HASH_MD5:
598 		return 16;
599 
600 	case OPS_HASH_SHA1:
601 		return 20;
602 
603 	case OPS_HASH_SHA256:
604 		return 32;
605 
606 	case OPS_HASH_SHA224:
607 		return 28;
608 
609 	case OPS_HASH_SHA512:
610 		return 64;
611 
612 	case OPS_HASH_SHA384:
613 		return 48;
614 
615 	default:
616 		(void) fprintf(stderr, "__ops_hash_size: bad algorithm\n");
617 	}
618 
619 	return 0;
620 }
621 
622 /**
623 \ingroup Core_Hashes
624 \brief Returns hash enum corresponding to given string
625 \param hash Text name of hash algorithm i.e. "SHA1"
626 \returns Corresponding enum i.e. OPS_HASH_SHA1
627 */
628 __ops_hash_alg_t
629 __ops_str_to_hash_alg(const char *hash)
630 {
631 	if (hash == NULL) {
632 		return OPS_DEFAULT_HASH_ALGORITHM;
633 	}
634 	if (netpgp_strcasecmp(hash, "SHA1") == 0) {
635 		return OPS_HASH_SHA1;
636 	}
637 	if (netpgp_strcasecmp(hash, "MD5") == 0) {
638 		return OPS_HASH_MD5;
639 	}
640 	if (netpgp_strcasecmp(hash, "SHA256") == 0) {
641 		return OPS_HASH_SHA256;
642 	}
643 	/*
644         if (netpgp_strcasecmp(hash,"SHA224") == 0) {
645 		return OPS_HASH_SHA224;
646 	}
647         */
648 	if (netpgp_strcasecmp(hash, "SHA512") == 0) {
649 		return OPS_HASH_SHA512;
650 	}
651 	if (netpgp_strcasecmp(hash, "SHA384") == 0) {
652 		return OPS_HASH_SHA384;
653 	}
654 	return OPS_HASH_UNKNOWN;
655 }
656 
657 /**
658 \ingroup Core_Hashes
659 \brief Hash given data
660 \param out Where to write the hash
661 \param alg Hash algorithm to use
662 \param in Data to hash
663 \param length Length of data
664 \return Size of hash created
665 */
666 unsigned
667 __ops_hash(uint8_t *out, __ops_hash_alg_t alg, const void *in, size_t length)
668 {
669 	__ops_hash_t      hash;
670 
671 	__ops_hash_any(&hash, alg);
672 	if (!hash.init(&hash)) {
673 		(void) fprintf(stderr, "__ops_hash: bad alloc\n");
674 		/* we'll just continue here - don't want to return a 0 hash */
675 		/* XXX - agc - no way to return failure */
676 	}
677 	hash.add(&hash, in, length);
678 	return hash.finish(&hash, out);
679 }
680 
681 /**
682 \ingroup Core_Hashes
683 \brief Calculate hash for MDC packet
684 \param preamble Preamble to hash
685 \param sz_preamble Size of preamble
686 \param plaintext Plaintext to hash
687 \param sz_plaintext Size of plaintext
688 \param hashed Resulting hash
689 */
690 void
691 __ops_calc_mdc_hash(const uint8_t *preamble,
692 			const size_t sz_preamble,
693 			const uint8_t *plaintext,
694 			const unsigned sz_plaintext,
695 			uint8_t *hashed)
696 {
697 	__ops_hash_t	hash;
698 	uint8_t		c;
699 
700 	if (__ops_get_debug_level(__FILE__)) {
701 		unsigned	i;
702 
703 		(void) fprintf(stderr, "__ops_calc_mdc_hash():\n");
704 		(void) fprintf(stderr, "\npreamble: ");
705 		for (i = 0; i < sz_preamble; i++)
706 			(void) fprintf(stderr, " 0x%02x", preamble[i]);
707 		(void) fprintf(stderr, "\n");
708 		(void) fprintf(stderr, "\nplaintext (len=%u): ", sz_plaintext);
709 		for (i = 0; i < sz_plaintext; i++)
710 			(void) fprintf(stderr, " 0x%02x", plaintext[i]);
711 		(void) fprintf(stderr, "\n");
712 	}
713 	/* init */
714 	__ops_hash_any(&hash, OPS_HASH_SHA1);
715 	if (!hash.init(&hash)) {
716 		(void) fprintf(stderr, "__ops_calc_mdc_hash: bad alloc\n");
717 		/* we'll just continue here - it will die anyway */
718 		/* agc - XXX - no way to return failure */
719 	}
720 
721 	/* preamble */
722 	hash.add(&hash, preamble, sz_preamble);
723 	/* plaintext */
724 	hash.add(&hash, plaintext, sz_plaintext);
725 	/* MDC packet tag */
726 	c = MDC_PKT_TAG;
727 	hash.add(&hash, &c, 1);
728 	/* MDC packet len */
729 	c = OPS_SHA1_HASH_SIZE;
730 	hash.add(&hash, &c, 1);
731 
732 	/* finish */
733 	hash.finish(&hash, hashed);
734 
735 	if (__ops_get_debug_level(__FILE__)) {
736 		unsigned	i;
737 
738 		(void) fprintf(stderr, "\nhashed (len=%d): ",
739 				OPS_SHA1_HASH_SIZE);
740 		for (i = 0; i < OPS_SHA1_HASH_SIZE; i++) {
741 			(void) fprintf(stderr, " 0x%02x", hashed[i]);
742 		}
743 		(void) fprintf(stderr, "\n");
744 	}
745 }
746 
747 /**
748 \ingroup HighLevel_Supported
749 \brief Is this Hash Algorithm supported?
750 \param hash_alg Hash Algorithm to check
751 \return 1 if supported; else 0
752 */
753 unsigned
754 __ops_is_hash_alg_supported(const __ops_hash_alg_t *hash_alg)
755 {
756 	switch (*hash_alg) {
757 	case OPS_HASH_MD5:
758 	case OPS_HASH_SHA1:
759 	case OPS_HASH_SHA256:
760 		return 1;
761 
762 	default:
763 		return 0;
764 	}
765 }
766 
767 void
768 __ops_random(void *dest, size_t length)
769 {
770 	RAND_bytes(dest, (int)length);
771 }
772 
773 /**
774 \ingroup HighLevel_Memory
775 \brief Memory to initialise
776 \param mem memory to initialise
777 \param needed Size to initialise to
778 */
779 void
780 __ops_memory_init(__ops_memory_t *mem, size_t needed)
781 {
782 	uint8_t	*temp;
783 
784 	mem->length = 0;
785 	if (mem->buf) {
786 		if (mem->allocated < needed) {
787 			if ((temp = realloc(mem->buf, needed)) == NULL) {
788 				(void) fprintf(stderr, "__ops_memory_init: bad alloc\n");
789 			} else {
790 				mem->buf = temp;
791 				mem->allocated = needed;
792 			}
793 		}
794 	} else {
795 		if ((mem->buf = calloc(1, needed)) == NULL) {
796 			(void) fprintf(stderr, "__ops_memory_init: bad alloc\n");
797 		} else {
798 			mem->allocated = needed;
799 		}
800 	}
801 }
802 
803 /**
804 \ingroup HighLevel_Memory
805 \brief Pad memory to required length
806 \param mem Memory to use
807 \param length New size
808 */
809 void
810 __ops_memory_pad(__ops_memory_t *mem, size_t length)
811 {
812 	uint8_t	*temp;
813 
814 	if (mem->allocated < mem->length) {
815 		(void) fprintf(stderr, "__ops_memory_pad: bad alloc in\n");
816 		return;
817 	}
818 	if (mem->allocated < mem->length + length) {
819 		mem->allocated = mem->allocated * 2 + length;
820 		temp = realloc(mem->buf, mem->allocated);
821 		if (temp == NULL) {
822 			(void) fprintf(stderr, "__ops_memory_pad: bad alloc\n");
823 		} else {
824 			mem->buf = temp;
825 		}
826 	}
827 	if (mem->allocated < mem->length + length) {
828 		(void) fprintf(stderr, "__ops_memory_pad: bad alloc out\n");
829 	}
830 }
831 
832 /**
833 \ingroup HighLevel_Memory
834 \brief Add data to memory
835 \param mem Memory to which to add
836 \param src Data to add
837 \param length Length of data to add
838 */
839 void
840 __ops_memory_add(__ops_memory_t *mem, const uint8_t *src, size_t length)
841 {
842 	__ops_memory_pad(mem, length);
843 	(void) memcpy(mem->buf + mem->length, src, length);
844 	mem->length += length;
845 }
846 
847 /* XXX: this could be refactored via the writer, but an awful lot of */
848 /* hoops to jump through for 2 lines of code! */
849 void
850 __ops_memory_place_int(__ops_memory_t *mem, unsigned offset, unsigned n,
851 		     size_t length)
852 {
853 	if (mem->allocated < offset + length) {
854 		(void) fprintf(stderr,
855 			"__ops_memory_place_int: bad alloc\n");
856 	} else {
857 		while (length-- > 0) {
858 			mem->buf[offset++] = n >> (length * 8);
859 		}
860 	}
861 }
862 
863 /**
864  * \ingroup HighLevel_Memory
865  * \brief Retains allocated memory and set length of stored data to zero.
866  * \param mem Memory to clear
867  * \sa __ops_memory_release()
868  * \sa __ops_memory_free()
869  */
870 void
871 __ops_memory_clear(__ops_memory_t *mem)
872 {
873 	mem->length = 0;
874 }
875 
876 /**
877 \ingroup HighLevel_Memory
878 \brief Free memory and associated data
879 \param mem Memory to free
880 \note This does not free mem itself
881 \sa __ops_memory_clear()
882 \sa __ops_memory_free()
883 */
884 void
885 __ops_memory_release(__ops_memory_t *mem)
886 {
887 	if (mem->mmapped) {
888 		(void) munmap(mem->buf, mem->length);
889 	} else {
890 		free(mem->buf);
891 	}
892 	mem->buf = NULL;
893 	mem->length = 0;
894 }
895 
896 void
897 __ops_memory_make_packet(__ops_memory_t *out, __ops_content_tag_t tag)
898 {
899 	size_t          extra;
900 
901 	extra = (out->length < 192) ? 1 : (out->length < 8192 + 192) ? 2 : 5;
902 	__ops_memory_pad(out, extra + 1);
903 	memmove(out->buf + extra + 1, out->buf, out->length);
904 
905 	out->buf[0] = OPS_PTAG_ALWAYS_SET | OPS_PTAG_NEW_FORMAT | tag;
906 
907 	if (out->length < 192) {
908 		out->buf[1] = out->length;
909 	} else if (out->length < 8192 + 192) {
910 		out->buf[1] = ((out->length - 192) >> 8) + 192;
911 		out->buf[2] = out->length - 192;
912 	} else {
913 		out->buf[1] = 0xff;
914 		out->buf[2] = out->length >> 24;
915 		out->buf[3] = out->length >> 16;
916 		out->buf[4] = out->length >> 8;
917 		out->buf[5] = out->length;
918 	}
919 
920 	out->length += extra + 1;
921 }
922 
923 /**
924    \ingroup HighLevel_Memory
925    \brief Create a new zeroed __ops_memory_t
926    \return Pointer to new __ops_memory_t
927    \note Free using __ops_memory_free() after use.
928    \sa __ops_memory_free()
929 */
930 
931 __ops_memory_t   *
932 __ops_memory_new(void)
933 {
934 	return calloc(1, sizeof(__ops_memory_t));
935 }
936 
937 /**
938    \ingroup HighLevel_Memory
939    \brief Free memory ptr and associated memory
940    \param mem Memory to be freed
941    \sa __ops_memory_release()
942    \sa __ops_memory_clear()
943 */
944 
945 void
946 __ops_memory_free(__ops_memory_t *mem)
947 {
948 	__ops_memory_release(mem);
949 	free(mem);
950 }
951 
952 /**
953    \ingroup HighLevel_Memory
954    \brief Get length of data stored in __ops_memory_t struct
955    \return Number of bytes in data
956 */
957 size_t
958 __ops_mem_len(const __ops_memory_t *mem)
959 {
960 	return mem->length;
961 }
962 
963 /**
964    \ingroup HighLevel_Memory
965    \brief Get data stored in __ops_memory_t struct
966    \return Pointer to data
967 */
968 void *
969 __ops_mem_data(__ops_memory_t *mem)
970 {
971 	return mem->buf;
972 }
973 
974 /* read a gile into an __ops_memory_t */
975 int
976 __ops_mem_readfile(__ops_memory_t *mem, const char *f)
977 {
978 	struct stat	 st;
979 	FILE		*fp;
980 	int		 cc;
981 
982 	if ((fp = fopen(f, "rb")) == NULL) {
983 		(void) fprintf(stderr,
984 				"__ops_mem_readfile: can't open \"%s\"\n", f);
985 		return 0;
986 	}
987 	(void) fstat(fileno(fp), &st);
988 	mem->allocated = (size_t)st.st_size;
989 	mem->buf = mmap(NULL, mem->allocated, PROT_READ,
990 				MAP_PRIVATE | MAP_FILE, fileno(fp), 0);
991 	if (mem->buf == MAP_FAILED) {
992 		/* mmap failed for some reason - try to allocate memory */
993 		if ((mem->buf = calloc(1, mem->allocated)) == NULL) {
994 			(void) fprintf(stderr, "__ops_mem_readfile: calloc\n");
995 			(void) fclose(fp);
996 			return 0;
997 		}
998 		/* read into contents of mem */
999 		for (mem->length = 0 ;
1000 		     (cc = read(fileno(fp), &mem->buf[mem->length],
1001 					mem->allocated - mem->length)) > 0 ;
1002 		     mem->length += (size_t)cc) {
1003 		}
1004 	} else {
1005 		mem->length = mem->allocated;
1006 		mem->mmapped = 1;
1007 	}
1008 	(void) fclose(fp);
1009 	return (mem->allocated == mem->length);
1010 }
1011 
1012 typedef struct {
1013 	uint16_t  sum;
1014 } sum16_t;
1015 
1016 
1017 /**
1018  * Searches the given map for the given type.
1019  * Returns a human-readable descriptive string if found,
1020  * returns NULL if not found
1021  *
1022  * It is the responsibility of the calling function to handle the
1023  * error case sensibly (i.e. don't just print out the return string.
1024  *
1025  */
1026 static const char *
1027 str_from_map_or_null(int type, __ops_map_t *map)
1028 {
1029 	__ops_map_t      *row;
1030 
1031 	for (row = map; row->string != NULL; row++) {
1032 		if (row->type == type) {
1033 			return row->string;
1034 		}
1035 	}
1036 	return NULL;
1037 }
1038 
1039 /**
1040  * \ingroup Core_Print
1041  *
1042  * Searches the given map for the given type.
1043  * Returns a readable string if found, "Unknown" if not.
1044  */
1045 
1046 const char     *
1047 __ops_str_from_map(int type, __ops_map_t *map)
1048 {
1049 	const char     *str;
1050 
1051 	str = str_from_map_or_null(type, map);
1052 	return (str) ? str : "Unknown";
1053 }
1054 
1055 void
1056 hexdump(FILE *fp, const uint8_t *src, size_t length, const char *sep)
1057 {
1058 	unsigned i;
1059 
1060 	for (i = 0 ; i < length ; i += 2) {
1061 		(void) fprintf(fp, "%02x", *src++);
1062 		(void) fprintf(fp, "%02x%s", *src++, sep);
1063 	}
1064 }
1065 
1066 /**
1067  * \ingroup HighLevel_Functions
1068  * \brief Initialises OpenPGP::SDK. To be called before any other OPS function.
1069  *
1070  * Initialises OpenPGP::SDK and the underlying openssl library.
1071  */
1072 
1073 void
1074 __ops_init(void)
1075 {
1076 	__ops_crypto_init();
1077 }
1078 
1079 /**
1080  * \ingroup HighLevel_Functions
1081  * \brief Closes down OpenPGP::SDK.
1082  *
1083  * Close down OpenPGP:SDK, release any resources under the control of
1084  * the library. No OpenPGP:SDK function other than __ops_init() should
1085  * be called after this function.
1086  */
1087 
1088 void
1089 __ops_finish(void)
1090 {
1091 	__ops_crypto_finish();
1092 }
1093 
1094 static int
1095 sum16_reader(void *dest_, size_t length, __ops_error_t **errors,
1096 	     __ops_reader_t *readinfo, __ops_cbdata_t *cbinfo)
1097 {
1098 	const uint8_t	*dest = dest_;
1099 	sum16_t		*arg = __ops_reader_get_arg(readinfo);
1100 	int		 r;
1101 	int		 n;
1102 
1103 	r = __ops_stacked_read(dest_, length, errors, readinfo, cbinfo);
1104 	if (r < 0) {
1105 		return r;
1106 	}
1107 	for (n = 0; n < r; ++n) {
1108 		arg->sum = (arg->sum + dest[n]) & 0xffff;
1109 	}
1110 	return r;
1111 }
1112 
1113 static void
1114 sum16_destroyer(__ops_reader_t *readinfo)
1115 {
1116 	free(__ops_reader_get_arg(readinfo));
1117 }
1118 
1119 /**
1120    \ingroup Internal_Readers_Sum16
1121    \param stream Parse settings
1122 */
1123 
1124 void
1125 __ops_reader_push_sum16(__ops_stream_t *stream)
1126 {
1127 	sum16_t    *arg;
1128 
1129 	if ((arg = calloc(1, sizeof(*arg))) == NULL) {
1130 		(void) fprintf(stderr, "__ops_reader_push_sum16: bad alloc\n");
1131 	} else {
1132 		__ops_reader_push(stream, sum16_reader, sum16_destroyer, arg);
1133 	}
1134 }
1135 
1136 /**
1137    \ingroup Internal_Readers_Sum16
1138    \param stream Parse settings
1139    \return sum
1140 */
1141 uint16_t
1142 __ops_reader_pop_sum16(__ops_stream_t *stream)
1143 {
1144 	uint16_t	 sum;
1145 	sum16_t		*arg;
1146 
1147 	arg = __ops_reader_get_arg(__ops_readinfo(stream));
1148 	sum = arg->sum;
1149 	__ops_reader_pop(stream);
1150 	free(arg);
1151 	return sum;
1152 }
1153 
1154 /* small useful functions for setting the file-level debugging levels */
1155 /* if the debugv list contains the filename in question, we're debugging it */
1156 
1157 enum {
1158 	MAX_DEBUG_NAMES = 32
1159 };
1160 
1161 static int      debugc;
1162 static char    *debugv[MAX_DEBUG_NAMES];
1163 
1164 /* set the debugging level per filename */
1165 int
1166 __ops_set_debug_level(const char *f)
1167 {
1168 	const char     *name;
1169 	int             i;
1170 
1171 	if (f == NULL) {
1172 		f = "all";
1173 	}
1174 	if ((name = strrchr(f, '/')) == NULL) {
1175 		name = f;
1176 	} else {
1177 		name += 1;
1178 	}
1179 	for (i = 0; i < debugc && i < MAX_DEBUG_NAMES; i++) {
1180 		if (strcmp(debugv[i], name) == 0) {
1181 			return 1;
1182 		}
1183 	}
1184 	if (i == MAX_DEBUG_NAMES) {
1185 		return 0;
1186 	}
1187 	debugv[debugc++] = netpgp_strdup(name);
1188 	return 1;
1189 }
1190 
1191 /* get the debugging level per filename */
1192 int
1193 __ops_get_debug_level(const char *f)
1194 {
1195 	const char     *name;
1196 	int             i;
1197 
1198 	if ((name = strrchr(f, '/')) == NULL) {
1199 		name = f;
1200 	} else {
1201 		name += 1;
1202 	}
1203 	for (i = 0; i < debugc; i++) {
1204 		if (strcmp(debugv[i], "all") == 0 ||
1205 		    strcmp(debugv[i], name) == 0) {
1206 			return 1;
1207 		}
1208 	}
1209 	return 0;
1210 }
1211 
1212 /* return the version for the library */
1213 const char *
1214 __ops_get_info(const char *type)
1215 {
1216 	if (strcmp(type, "version") == 0) {
1217 		return NETPGP_VERSION_STRING;
1218 	}
1219 	if (strcmp(type, "maintainer") == 0) {
1220 		return NETPGP_MAINTAINER;
1221 	}
1222 	return "[unknown]";
1223 }
1224 
1225 /* local version of asprintf so we don't have to play autoconf games */
1226 int
1227 __ops_asprintf(char **ret, const char *fmt, ...)
1228 {
1229 	va_list args;
1230 	char    buf[120 * 1024];	/* XXX - "huge" buffer on stack */
1231 	int     cc;
1232 
1233 	va_start(args, fmt);
1234 	cc = vsnprintf(buf, sizeof(buf), fmt, args);
1235 	va_end(args);
1236 	if ((*ret = calloc(1, (size_t)(cc + 1))) == NULL) {
1237 		*ret = NULL;
1238 		return -1;
1239 	}
1240 	(void) memcpy(*ret, buf, (size_t)cc);
1241 	(*ret)[cc] = 0x0;
1242 	return cc;
1243 }
1244 
1245 void
1246 netpgp_log(const char *fmt, ...)
1247 {
1248 	va_list	 vp;
1249 	time_t	 t;
1250 	char	 buf[BUFSIZ * 2];
1251 	int	 cc;
1252 
1253 	(void) time(&t);
1254 	cc = snprintf(buf, sizeof(buf), "%.24s: netpgp: ", ctime(&t));
1255 	va_start(vp, fmt);
1256 	(void) vsnprintf(&buf[cc], sizeof(buf) - (size_t)cc, fmt, vp);
1257 	va_end(vp);
1258 	/* do something with message */
1259 	/* put into log buffer? */
1260 }
1261 
1262 /* portable replacement for strdup(3) */
1263 char *
1264 netpgp_strdup(const char *s)
1265 {
1266 	size_t	 len;
1267 	char	*cp;
1268 
1269 	len = strlen(s);
1270 	if ((cp = calloc(1, len + 1)) != NULL) {
1271 		(void) memcpy(cp, s, len);
1272 		cp[len] = 0x0;
1273 	}
1274 	return cp;
1275 }
1276 
1277 /* portable replacement for strcasecmp(3) */
1278 int
1279 netpgp_strcasecmp(const char *s1, const char *s2)
1280 {
1281 	int	n;
1282 
1283 	for (n = 0 ; *s1 && *s2 && (n = tolower(*s1) - tolower(*s2)) == 0 ; s1++, s2++) {
1284 	}
1285 	return n;
1286 }
1287