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