xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/misc.c (revision 9ee9e0d7de4c59c936a17df52be682915dc66f43)
1 /*
2  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
3  * All rights reserved.
4  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
5  * their moral rights under the UK Copyright Design and Patents Act 1988 to
6  * be recorded as the authors of this copyright work.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
9  * use this file except in compliance with the License.
10  *
11  * You may obtain a copy of the License at
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 /** \file
23  */
24 #include "config.h"
25 
26 #include <openssl/rand.h>
27 
28 #include "errors.h"
29 #include "packet.h"
30 #include "crypto.h"
31 #include "create.h"
32 #include "packet-parse.h"
33 #include "packet-show.h"
34 #include "signature.h"
35 #include "netpgpsdk.h"
36 #include "netpgpdefs.h"
37 #include "memory.h"
38 #include "keyring_local.h"
39 #include "parse_local.h"
40 #include "readerwriter.h"
41 #include "loccreate.h"
42 #include "version.h"
43 
44 #ifdef HAVE_ASSERT_H
45 #include <assert.h>
46 #endif
47 
48 #include <stdarg.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56 
57 #ifdef WIN32
58 #define vsnprintf _vsnprintf
59 #endif
60 
61 typedef struct {
62 	__ops_keyring_t  *keyring;
63 }               accumulate_t;
64 
65 /**
66  * \ingroup Core_Callbacks
67  */
68 static          __ops_parse_cb_return_t
69 accumulate_cb(const __ops_parser_content_t * contents, __ops_parse_cb_info_t * cbinfo)
70 {
71 	accumulate_t *accumulate = __ops_parse_cb_get_arg(cbinfo);
72 	const __ops_parser_content_union_t *content = &contents->u;
73 	__ops_keyring_t  *keyring = accumulate->keyring;
74 	__ops_keydata_t  *cur = NULL;
75 	const __ops_public_key_t *pkey;
76 
77 	if (keyring->nkeys >= 0)
78 		cur = &keyring->keys[keyring->nkeys];
79 
80 	switch (contents->tag) {
81 	case OPS_PTAG_CT_PUBLIC_KEY:
82 	case OPS_PTAG_CT_SECRET_KEY:
83 	case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
84 		if (__ops_get_debug_level(__FILE__)) {
85 			(void) fprintf(stderr, "New key - tag %d\n", contents->tag);
86 		}
87 		++keyring->nkeys;
88 		EXPAND_ARRAY(keyring, keys);
89 
90 		if (contents->tag == OPS_PTAG_CT_PUBLIC_KEY)
91 			pkey = &content->public_key;
92 		else
93 			pkey = &content->secret_key.public_key;
94 
95 		(void) memset(&keyring->keys[keyring->nkeys], 0x0,
96 		       sizeof(keyring->keys[keyring->nkeys]));
97 
98 		__ops_keyid(keyring->keys[keyring->nkeys].key_id,
99 			OPS_KEY_ID_SIZE, OPS_KEY_ID_SIZE, pkey);
100 		__ops_fingerprint(&keyring->keys[keyring->nkeys].fingerprint, pkey);
101 
102 		keyring->keys[keyring->nkeys].type = contents->tag;
103 
104 		if (contents->tag == OPS_PTAG_CT_PUBLIC_KEY)
105 			keyring->keys[keyring->nkeys].key.pkey = *pkey;
106 		else
107 			keyring->keys[keyring->nkeys].key.skey = content->secret_key;
108 		return OPS_KEEP_MEMORY;
109 
110 	case OPS_PTAG_CT_USER_ID:
111 		if (__ops_get_debug_level(__FILE__)) {
112 			(void) fprintf(stderr, "User ID: %s\n", content->user_id.user_id);
113 		}
114 		if (!cur) {
115 			OPS_ERROR(cbinfo->errors, OPS_E_P_NO_USERID, "No user id found");
116 			return OPS_KEEP_MEMORY;
117 		}
118 		/* assert(cur); */
119 		__ops_add_userid_to_keydata(cur, &content->user_id);
120 		return OPS_KEEP_MEMORY;
121 
122 	case OPS_PARSER_PACKET_END:
123 		if (!cur)
124 			return OPS_RELEASE_MEMORY;
125 		__ops_add_packet_to_keydata(cur, &content->packet);
126 		return OPS_KEEP_MEMORY;
127 
128 	case OPS_PARSER_ERROR:
129 		fprintf(stderr, "Error: %s\n", content->error.error);
130 		assert( /* CONSTCOND */ 0);
131 		break;
132 
133 	case OPS_PARSER_ERRCODE:
134 		switch (content->errcode.errcode) {
135 		default:
136 			fprintf(stderr, "parse error: %s\n",
137 				__ops_errcode(content->errcode.errcode));
138 			/* assert(0); */
139 		}
140 		break;
141 
142 	default:
143 		break;
144 	}
145 
146 	/* XXX: we now exclude so many things, we should either drop this or */
147 	/* do something to pass on copies of the stuff we keep */
148 	return __ops_parse_stacked_cb(contents, cbinfo);
149 }
150 
151 /**
152  * \ingroup Core_Parse
153  *
154  * Parse packets from an input stream until EOF or error.
155  *
156  * Key data found in the parsed data is added to #keyring.
157  *
158  * \param keyring Pointer to an existing keyring
159  * \param parse Options to use when parsing
160 */
161 
162 int
163 __ops_parse_and_accumulate(__ops_keyring_t * keyring, __ops_parse_info_t *parse)
164 {
165 	int             rtn;
166 	accumulate_t accumulate;
167 
168 	assert(!parse->rinfo.accumulate);
169 
170 	(void) memset(&accumulate, 0x0, sizeof(accumulate));
171 
172 	accumulate.keyring = keyring;
173 	/* Kinda weird, but to do with counting, and we put it back after */
174 	keyring->nkeys -= 1;
175 
176 	__ops_parse_cb_push(parse, accumulate_cb, &accumulate);
177 	parse->rinfo.accumulate = true;
178 	rtn = __ops_parse(parse);
179 
180 	keyring->nkeys += 1;
181 
182 	return rtn;
183 }
184 
185 static void
186 dump_one_keydata(const __ops_keydata_t * key)
187 {
188 	unsigned        n;
189 
190 	printf("Key ID: ");
191 	hexdump(key->key_id, OPS_KEY_ID_SIZE, "");
192 
193 	printf("\nFingerpint: ");
194 	hexdump(key->fingerprint.fingerprint, key->fingerprint.length, "");
195 
196 	printf("\n\nUIDs\n====\n\n");
197 	for (n = 0; n < key->nuids; ++n)
198 		printf("%s\n", key->uids[n].user_id);
199 
200 	printf("\nPackets\n=======\n");
201 	for (n = 0; n < key->npackets; ++n) {
202 		printf("\n%03d: ", n);
203 		hexdump(key->packets[n].raw, key->packets[n].length, "");
204 	}
205 	printf("\n\n");
206 }
207 
208 /* XXX: not a maintained part of the API - use __ops_keyring_list() */
209 /** __ops_dump_keyring
210 */
211 void
212 __ops_dump_keyring(const __ops_keyring_t * keyring)
213 {
214 	int             n;
215 
216 	for (n = 0; n < keyring->nkeys; ++n) {
217 		dump_one_keydata(&keyring->keys[n]);
218 	}
219 }
220 
221 
222 /** \file
223  * \brief Error Handling
224  */
225 #define ERRNAME(code)	{ code, #code }
226 
227 static __ops_errcode_name_map_t errcode_name_map[] = {
228 	ERRNAME(OPS_E_OK),
229 	ERRNAME(OPS_E_FAIL),
230 	ERRNAME(OPS_E_SYSTEM_ERROR),
231 	ERRNAME(OPS_E_UNIMPLEMENTED),
232 
233 	ERRNAME(OPS_E_R),
234 	ERRNAME(OPS_E_R_READ_FAILED),
235 	ERRNAME(OPS_E_R_EARLY_EOF),
236 	ERRNAME(OPS_E_R_BAD_FORMAT),
237 	ERRNAME(OPS_E_R_UNCONSUMED_DATA),
238 
239 	ERRNAME(OPS_E_W),
240 	ERRNAME(OPS_E_W_WRITE_FAILED),
241 	ERRNAME(OPS_E_W_WRITE_TOO_SHORT),
242 
243 	ERRNAME(OPS_E_P),
244 	ERRNAME(OPS_E_P_NOT_ENOUGH_DATA),
245 	ERRNAME(OPS_E_P_UNKNOWN_TAG),
246 	ERRNAME(OPS_E_P_PACKET_CONSUMED),
247 	ERRNAME(OPS_E_P_MPI_FORMAT_ERROR),
248 
249 	ERRNAME(OPS_E_C),
250 
251 	ERRNAME(OPS_E_V),
252 	ERRNAME(OPS_E_V_BAD_SIGNATURE),
253 	ERRNAME(OPS_E_V_NO_SIGNATURE),
254 	ERRNAME(OPS_E_V_UNKNOWN_SIGNER),
255 
256 	ERRNAME(OPS_E_ALG),
257 	ERRNAME(OPS_E_ALG_UNSUPPORTED_SYMMETRIC_ALG),
258 	ERRNAME(OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG),
259 	ERRNAME(OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG),
260 	ERRNAME(OPS_E_ALG_UNSUPPORTED_HASH_ALG),
261 
262 	ERRNAME(OPS_E_PROTO),
263 	ERRNAME(OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT),
264 	ERRNAME(OPS_E_PROTO_UNKNOWN_SS),
265 	ERRNAME(OPS_E_PROTO_CRITICAL_SS_IGNORED),
266 	ERRNAME(OPS_E_PROTO_BAD_PUBLIC_KEY_VRSN),
267 	ERRNAME(OPS_E_PROTO_BAD_SIGNATURE_VRSN),
268 	ERRNAME(OPS_E_PROTO_BAD_ONE_PASS_SIG_VRSN),
269 	ERRNAME(OPS_E_PROTO_BAD_PKSK_VRSN),
270 	ERRNAME(OPS_E_PROTO_DECRYPTED_MSG_WRONG_LEN),
271 	ERRNAME(OPS_E_PROTO_BAD_SK_CHECKSUM),
272 
273 	{0x00, NULL},		/* this is the end-of-array marker */
274 };
275 
276 /**
277  * \ingroup Core_Errors
278  * \brief returns error code name
279  * \param errcode
280  * \return error code name or "Unknown"
281  */
282 const char     *
283 __ops_errcode(const __ops_errcode_t errcode)
284 {
285 	return (__ops_str_from_map((int) errcode, (__ops_map_t *) errcode_name_map));
286 }
287 
288 /**
289  * \ingroup Core_Errors
290  * \brief Pushes the given error on the given errorstack
291  * \param errstack Error stack to use
292  * \param errcode Code of error to push
293  * \param sys_errno System errno (used if errcode=OPS_E_SYSTEM_ERROR)
294  * \param file Source filename where error occurred
295  * \param line Line in source file where error occurred
296  * \param fmt Comment
297  *
298  */
299 
300 void
301 __ops_push_error(__ops_error_t ** errstack, __ops_errcode_t errcode, int sys_errno,
302 	       const char *file, int line, const char *fmt,...)
303 {
304 	/* first get the varargs and generate the comment */
305 	__ops_error_t  *err;
306 	unsigned	maxbuf = 128;
307 	va_list		args;
308 	char           *comment;
309 
310 	comment = calloc(1, maxbuf + 1);
311 	assert(comment);
312 
313 	va_start(args, fmt);
314 	vsnprintf(comment, maxbuf + 1, fmt, args);
315 	va_end(args);
316 
317 	/* alloc a new error and add it to the top of the stack */
318 
319 	err = calloc(1, sizeof(__ops_error_t));
320 	assert(err);
321 
322 	err->next = *errstack;
323 	*errstack = err;
324 
325 	/* fill in the details */
326 	err->errcode = errcode;
327 	err->sys_errno = sys_errno;
328 	err->file = file;
329 	err->line = line;
330 
331 	err->comment = comment;
332 }
333 
334 /**
335 \ingroup Core_Errors
336 \brief print this error
337 \param err Error to print
338 */
339 void
340 __ops_print_error(__ops_error_t * err)
341 {
342 	printf("%s:%d: ", err->file, err->line);
343 	if (err->errcode == OPS_E_SYSTEM_ERROR)
344 		printf("system error %d returned from %s()\n", err->sys_errno,
345 		       err->comment);
346 	else
347 		printf("%s, %s\n", __ops_errcode(err->errcode), err->comment);
348 }
349 
350 /**
351 \ingroup Core_Errors
352 \brief Print all errors on stack
353 \param errstack Error stack to print
354 */
355 void
356 __ops_print_errors(__ops_error_t * errstack)
357 {
358 	__ops_error_t    *err;
359 
360 	for (err = errstack; err != NULL; err = err->next)
361 		__ops_print_error(err);
362 }
363 
364 /**
365 \ingroup Core_Errors
366 \brief Return true if given error is present anywhere on stack
367 \param errstack Error stack to check
368 \param errcode Error code to look for
369 \return 1 if found; else 0
370 */
371 int
372 __ops_has_error(__ops_error_t * errstack, __ops_errcode_t errcode)
373 {
374 	__ops_error_t    *err;
375 	for (err = errstack; err != NULL; err = err->next) {
376 		if (err->errcode == errcode)
377 			return 1;
378 	}
379 	return 0;
380 }
381 
382 /**
383 \ingroup Core_Errors
384 \brief Frees all errors on stack
385 \param errstack Error stack to free
386 */
387 void
388 __ops_free_errors(__ops_error_t * errstack)
389 {
390 	__ops_error_t    *next;
391 	while (errstack != NULL) {
392 		next = errstack->next;
393 		free(errstack->comment);
394 		free(errstack);
395 		errstack = next;
396 	}
397 }
398 
399 /** \file
400  */
401 
402 /**
403  * \ingroup Core_Keys
404  * \brief Calculate a public key fingerprint.
405  * \param fp Where to put the calculated fingerprint
406  * \param key The key for which the fingerprint is calculated
407  */
408 
409 void
410 __ops_fingerprint(__ops_fingerprint_t * fp, const __ops_public_key_t * key)
411 {
412 	if (key->version == 2 || key->version == 3) {
413 		unsigned char  *bn;
414 		size_t		n;
415 		__ops_hash_t	md5;
416 
417 		assert(key->algorithm == OPS_PKA_RSA
418 		       || key->algorithm == OPS_PKA_RSA_ENCRYPT_ONLY
419 		       || key->algorithm == OPS_PKA_RSA_SIGN_ONLY);
420 
421 		__ops_hash_md5(&md5);
422 		md5.init(&md5);
423 
424 		n = BN_num_bytes(key->key.rsa.n);
425 		bn = calloc(1, n);
426 		BN_bn2bin(key->key.rsa.n, bn);
427 		md5.add(&md5, bn, n);
428 		(void) free(bn);
429 
430 		n = BN_num_bytes(key->key.rsa.e);
431 		bn = calloc(1, n);
432 		BN_bn2bin(key->key.rsa.e, bn);
433 		md5.add(&md5, bn, n);
434 		(void) free(bn);
435 
436 		md5.finish(&md5, fp->fingerprint);
437 		fp->length = 16;
438 	} else {
439 		__ops_memory_t   *mem = __ops_memory_new();
440 		__ops_hash_t      sha1;
441 		size_t          l;
442 
443 		__ops_build_public_key(mem, key, false);
444 
445 		if (__ops_get_debug_level(__FILE__)) {
446 			fprintf(stderr, "--- creating key fingerprint\n");
447 		}
448 		__ops_hash_sha1(&sha1);
449 		sha1.init(&sha1);
450 
451 		l = __ops_memory_get_length(mem);
452 
453 		__ops_hash_add_int(&sha1, 0x99, 1);
454 		__ops_hash_add_int(&sha1, l, 2);
455 		sha1.add(&sha1, __ops_memory_get_data(mem), l);
456 		sha1.finish(&sha1, fp->fingerprint);
457 
458 		if (__ops_get_debug_level(__FILE__)) {
459 			fprintf(stderr, "--- finished creating key fingerprint\n");
460 		}
461 		fp->length = 20;
462 
463 		__ops_memory_free(mem);
464 	}
465 }
466 
467 /**
468  * \ingroup Core_Keys
469  * \brief Calculate the Key ID from the public key.
470  * \param keyid Space for the calculated ID to be stored
471  * \param key The key for which the ID is calculated
472  */
473 
474 void
475 __ops_keyid(unsigned char *keyid, const size_t idlen, const int last,
476 	const __ops_public_key_t *key)
477 {
478 	if (key->version == 2 || key->version == 3) {
479 		unsigned char   bn[NETPGP_BUFSIZ];
480 		unsigned        n = BN_num_bytes(key->key.rsa.n);
481 
482 		assert(n <= sizeof(bn));
483 		assert(key->algorithm == OPS_PKA_RSA
484 		       || key->algorithm == OPS_PKA_RSA_ENCRYPT_ONLY
485 		       || key->algorithm == OPS_PKA_RSA_SIGN_ONLY);
486 		BN_bn2bin(key->key.rsa.n, bn);
487 		(void) memcpy(keyid, (last == 0) ? bn : bn + n - idlen, idlen);
488 	} else {
489 		__ops_fingerprint_t finger;
490 
491 		__ops_fingerprint(&finger, key);
492 		(void) memcpy(keyid,
493 			(last == 0) ? finger.fingerprint :
494 				finger.fingerprint + finger.length - idlen,
495 			idlen);
496 	}
497 }
498 
499 /**
500 \ingroup Core_Hashes
501 \brief Add to the hash
502 \param hash Hash to add to
503 \param n Int to add
504 \param length Length of int in bytes
505 */
506 void
507 __ops_hash_add_int(__ops_hash_t * hash, unsigned n, unsigned length)
508 {
509 	while (length--) {
510 		unsigned char   c[1];
511 
512 		c[0] = n >> (length * 8);
513 		hash->add(hash, c, 1);
514 	}
515 }
516 
517 /**
518 \ingroup Core_Hashes
519 \brief Setup hash for given hash algorithm
520 \param hash Hash to set up
521 \param alg Hash algorithm to use
522 */
523 void
524 __ops_hash_any(__ops_hash_t * hash, __ops_hash_algorithm_t alg)
525 {
526 	switch (alg) {
527 	case OPS_HASH_MD5:
528 		__ops_hash_md5(hash);
529 		break;
530 
531 	case OPS_HASH_SHA1:
532 		__ops_hash_sha1(hash);
533 		break;
534 
535 	case OPS_HASH_SHA256:
536 		__ops_hash_sha256(hash);
537 		break;
538 
539 	case OPS_HASH_SHA384:
540 		__ops_hash_sha384(hash);
541 		break;
542 
543 	case OPS_HASH_SHA512:
544 		__ops_hash_sha512(hash);
545 		break;
546 
547 	case OPS_HASH_SHA224:
548 		__ops_hash_sha224(hash);
549 		break;
550 
551 	default:
552 		assert( /* CONSTCOND */ 0);
553 	}
554 }
555 
556 /**
557 \ingroup Core_Hashes
558 \brief Returns size of hash for given hash algorithm
559 \param alg Hash algorithm to use
560 \return Size of hash algorithm in bytes
561 */
562 unsigned
563 __ops_hash_size(__ops_hash_algorithm_t alg)
564 {
565 	switch (alg) {
566 	case OPS_HASH_MD5:
567 		return 16;
568 
569 	case OPS_HASH_SHA1:
570 		return 20;
571 
572 	case OPS_HASH_SHA256:
573 		return 32;
574 
575 	case OPS_HASH_SHA224:
576 		return 28;
577 
578 	case OPS_HASH_SHA512:
579 		return 64;
580 
581 	case OPS_HASH_SHA384:
582 		return 48;
583 
584 	default:
585 		assert( /* CONSTCOND */ 0);
586 	}
587 
588 	return 0;
589 }
590 
591 /**
592 \ingroup Core_Hashes
593 \brief Returns hash enum corresponding to given string
594 \param hash Text name of hash algorithm i.e. "SHA1"
595 \returns Corresponding enum i.e. OPS_HASH_SHA1
596 */
597 __ops_hash_algorithm_t
598 __ops_hash_algorithm_from_text(const char *hash)
599 {
600 	if (!strcmp(hash, "SHA1"))
601 		return OPS_HASH_SHA1;
602 	else if (!strcmp(hash, "MD5"))
603 		return OPS_HASH_MD5;
604 	else if (!strcmp(hash, "SHA256"))
605 		return OPS_HASH_SHA256;
606 	/*
607         else if (!strcmp(hash,"SHA224"))
608             return OPS_HASH_SHA224;
609         */
610 	else if (!strcmp(hash, "SHA512"))
611 		return OPS_HASH_SHA512;
612 	else if (!strcmp(hash, "SHA384"))
613 		return OPS_HASH_SHA384;
614 
615 	return OPS_HASH_UNKNOWN;
616 }
617 
618 /**
619 \ingroup Core_Hashes
620 \brief Hash given data
621 \param out Where to write the hash
622 \param alg Hash algorithm to use
623 \param in Data to hash
624 \param length Length of data
625 \return Size of hash created
626 */
627 unsigned
628 __ops_hash(unsigned char *out, __ops_hash_algorithm_t alg, const void *in,
629 	 size_t length)
630 {
631 	__ops_hash_t      hash;
632 
633 	__ops_hash_any(&hash, alg);
634 	hash.init(&hash);
635 	hash.add(&hash, in, length);
636 	return hash.finish(&hash, out);
637 }
638 
639 /**
640 \ingroup Core_Hashes
641 \brief Calculate hash for MDC packet
642 \param preamble Preamble to hash
643 \param sz_preamble Size of preamble
644 \param plaintext Plaintext to hash
645 \param sz_plaintext Size of plaintext
646 \param hashed Resulting hash
647 */
648 void
649 __ops_calc_mdc_hash(const unsigned char *preamble, const size_t sz_preamble, const unsigned char *plaintext, const unsigned int sz_plaintext, unsigned char *hashed)
650 {
651 	__ops_hash_t      hash;
652 	unsigned char   c[1];
653 
654 	if (__ops_get_debug_level(__FILE__)) {
655 		unsigned int    i = 0;
656 		fprintf(stderr, "__ops_calc_mdc_hash():\n");
657 
658 		fprintf(stderr, "\npreamble: ");
659 		for (i = 0; i < sz_preamble; i++)
660 			fprintf(stderr, " 0x%02x", preamble[i]);
661 		fprintf(stderr, "\n");
662 
663 		fprintf(stderr, "\nplaintext (len=%d): ", sz_plaintext);
664 		for (i = 0; i < sz_plaintext; i++)
665 			fprintf(stderr, " 0x%02x", plaintext[i]);
666 		fprintf(stderr, "\n");
667 	}
668 	/* init */
669 	__ops_hash_any(&hash, OPS_HASH_SHA1);
670 	hash.init(&hash);
671 
672 	/* preamble */
673 	hash.add(&hash, preamble, sz_preamble);
674 	/* plaintext */
675 	hash.add(&hash, plaintext, sz_plaintext);
676 	/* MDC packet tag */
677 	c[0] = 0xD3;
678 	hash.add(&hash, &c[0], 1);
679 	/* MDC packet len */
680 	c[0] = 0x14;
681 	hash.add(&hash, &c[0], 1);
682 
683 	/* finish */
684 	hash.finish(&hash, hashed);
685 
686 	if (__ops_get_debug_level(__FILE__)) {
687 		unsigned int    i = 0;
688 		fprintf(stderr, "\nhashed (len=%d): ", OPS_SHA1_HASH_SIZE);
689 		for (i = 0; i < OPS_SHA1_HASH_SIZE; i++)
690 			fprintf(stderr, " 0x%02x", hashed[i]);
691 		fprintf(stderr, "\n");
692 	}
693 }
694 
695 /**
696 \ingroup HighLevel_Supported
697 \brief Is this Hash Algorithm supported?
698 \param hash_alg Hash Algorithm to check
699 \return true if supported; else false
700 */
701 bool
702 __ops_is_hash_alg_supported(const __ops_hash_algorithm_t * hash_alg)
703 {
704 	switch (*hash_alg) {
705 	case OPS_HASH_MD5:
706 	case OPS_HASH_SHA1:
707 	case OPS_HASH_SHA256:
708 		return true;
709 
710 	default:
711 		return false;
712 	}
713 }
714 
715 void
716 __ops_random(void *dest, size_t length)
717 {
718 	RAND_bytes(dest, (int)length);
719 }
720 
721 /**
722 \ingroup HighLevel_Memory
723 \brief Memory to initialise
724 \param mem memory to initialise
725 \param needed Size to initialise to
726 */
727 void
728 __ops_memory_init(__ops_memory_t * mem, size_t needed)
729 {
730 	mem->length = 0;
731 	if (mem->buf) {
732 		if (mem->allocated < needed) {
733 			mem->buf = realloc(mem->buf, needed);
734 			mem->allocated = needed;
735 		}
736 		return;
737 	}
738 	mem->buf = calloc(1, needed);
739 	mem->allocated = needed;
740 }
741 
742 /**
743 \ingroup HighLevel_Memory
744 \brief Pad memory to required length
745 \param mem Memory to use
746 \param length New size
747 */
748 void
749 __ops_memory_pad(__ops_memory_t * mem, size_t length)
750 {
751 	assert(mem->allocated >= mem->length);
752 	if (mem->allocated < mem->length + length) {
753 		mem->allocated = mem->allocated * 2 + length;
754 		mem->buf = realloc(mem->buf, mem->allocated);
755 	}
756 	assert(mem->allocated >= mem->length + length);
757 }
758 
759 /**
760 \ingroup HighLevel_Memory
761 \brief Add data to memory
762 \param mem Memory to which to add
763 \param src Data to add
764 \param length Length of data to add
765 */
766 void
767 __ops_memory_add(__ops_memory_t * mem, const unsigned char *src, size_t length)
768 {
769 	__ops_memory_pad(mem, length);
770 	(void) memcpy(mem->buf + mem->length, src, length);
771 	mem->length += length;
772 }
773 
774 /* XXX: this could be refactored via the writer, but an awful lot of */
775 /* hoops to jump through for 2 lines of code! */
776 void
777 __ops_memory_place_int(__ops_memory_t * mem, unsigned offset, unsigned n,
778 		     size_t length)
779 {
780 	assert(mem->allocated >= offset + length);
781 
782 	while (length--)
783 		mem->buf[offset++] = n >> (length * 8);
784 }
785 
786 /**
787  * \ingroup HighLevel_Memory
788  * \brief Retains allocated memory and set length of stored data to zero.
789  * \param mem Memory to clear
790  * \sa __ops_memory_release()
791  * \sa __ops_memory_free()
792  */
793 void
794 __ops_memory_clear(__ops_memory_t * mem)
795 {
796 	mem->length = 0;
797 }
798 
799 /**
800 \ingroup HighLevel_Memory
801 \brief Free memory and associated data
802 \param mem Memory to free
803 \note This does not free mem itself
804 \sa __ops_memory_clear()
805 \sa __ops_memory_free()
806 */
807 void
808 __ops_memory_release(__ops_memory_t * mem)
809 {
810 	free(mem->buf);
811 	mem->buf = NULL;
812 	mem->length = 0;
813 }
814 
815 void
816 __ops_memory_make_packet(__ops_memory_t * out, __ops_content_tag_t tag)
817 {
818 	size_t          extra;
819 
820 	if (out->length < 192)
821 		extra = 1;
822 	else if (out->length < 8384)
823 		extra = 2;
824 	else
825 		extra = 5;
826 
827 	__ops_memory_pad(out, extra + 1);
828 	memmove(out->buf + extra + 1, out->buf, out->length);
829 
830 	out->buf[0] = OPS_PTAG_ALWAYS_SET | OPS_PTAG_NEW_FORMAT | tag;
831 
832 	if (out->length < 192)
833 		out->buf[1] = out->length;
834 	else if (out->length < 8192 + 192) {
835 		out->buf[1] = ((out->length - 192) >> 8) + 192;
836 		out->buf[2] = out->length - 192;
837 	} else {
838 		out->buf[1] = 0xff;
839 		out->buf[2] = out->length >> 24;
840 		out->buf[3] = out->length >> 16;
841 		out->buf[4] = out->length >> 8;
842 		out->buf[5] = out->length;
843 	}
844 
845 	out->length += extra + 1;
846 }
847 
848 /**
849    \ingroup HighLevel_Memory
850    \brief Create a new zeroed __ops_memory_t
851    \return Pointer to new __ops_memory_t
852    \note Free using __ops_memory_free() after use.
853    \sa __ops_memory_free()
854 */
855 
856 __ops_memory_t   *
857 __ops_memory_new(void)
858 {
859 	return calloc(1, sizeof(__ops_memory_t));
860 }
861 
862 /**
863    \ingroup HighLevel_Memory
864    \brief Free memory ptr and associated memory
865    \param mem Memory to be freed
866    \sa __ops_memory_release()
867    \sa __ops_memory_clear()
868 */
869 
870 void
871 __ops_memory_free(__ops_memory_t * mem)
872 {
873 	__ops_memory_release(mem);
874 	free(mem);
875 }
876 
877 /**
878    \ingroup HighLevel_Memory
879    \brief Get length of data stored in __ops_memory_t struct
880    \return Number of bytes in data
881 */
882 size_t
883 __ops_memory_get_length(const __ops_memory_t * mem)
884 {
885 	return mem->length;
886 }
887 
888 /**
889    \ingroup HighLevel_Memory
890    \brief Get data stored in __ops_memory_t struct
891    \return Pointer to data
892 */
893 void           *
894 __ops_memory_get_data(__ops_memory_t * mem)
895 {
896 	return mem->buf;
897 }
898 
899 typedef struct {
900 	unsigned short  sum;
901 }               sum16_t;
902 
903 
904 /**
905  * Searches the given map for the given type.
906  * Returns a human-readable descriptive string if found,
907  * returns NULL if not found
908  *
909  * It is the responsibility of the calling function to handle the
910  * error case sensibly (i.e. don't just print out the return string.
911  *
912  */
913 static const char *
914 str_from_map_or_null(int type, __ops_map_t * map)
915 {
916 	__ops_map_t      *row;
917 
918 	for (row = map; row->string != NULL; row++) {
919 		if (row->type == type) {
920 			return row->string;
921 		}
922 	}
923 	return NULL;
924 }
925 
926 /**
927  * \ingroup Core_Print
928  *
929  * Searches the given map for the given type.
930  * Returns a readable string if found, "Unknown" if not.
931  */
932 
933 const char     *
934 __ops_str_from_map(int type, __ops_map_t * map)
935 {
936 	const char     *str;
937 
938 	str = str_from_map_or_null(type, map);
939 	return (str) ? str : "Unknown";
940 }
941 
942 void
943 hexdump(const unsigned char *src, size_t length, const char *sep)
944 {
945 	unsigned i;
946 
947 	for (i = 0 ; i < length ; i += 2) {
948 		printf("%02x", *src++);
949 		printf("%02x%s", *src++, sep);
950 	}
951 }
952 
953 /**
954  * \ingroup HighLevel_Functions
955  * \brief Initialises OpenPGP::SDK. To be called before any other OPS function.
956  *
957  * Initialises OpenPGP::SDK and the underlying openssl library.
958  */
959 
960 void
961 __ops_init(void)
962 {
963 	__ops_crypto_init();
964 }
965 
966 /**
967  * \ingroup HighLevel_Functions
968  * \brief Closes down OpenPGP::SDK.
969  *
970  * Close down OpenPGP:SDK, release any resources under the control of
971  * the library. No OpenPGP:SDK function other than __ops_init() should
972  * be called after this function.
973  */
974 
975 void
976 __ops_finish(void)
977 {
978 	__ops_crypto_finish();
979 }
980 
981 static int
982 sum16_reader(void *dest_, size_t length, __ops_error_t ** errors,
983 	     __ops_reader_info_t * rinfo, __ops_parse_cb_info_t * cbinfo)
984 {
985 	const unsigned char *dest = dest_;
986 	sum16_t    *arg = __ops_reader_get_arg(rinfo);
987 	int             r = __ops_stacked_read(dest_, length, errors, rinfo, cbinfo);
988 	int             n;
989 
990 	if (r < 0) {
991 		return r;
992 	}
993 
994 	for (n = 0; n < r; ++n) {
995 		arg->sum = (arg->sum + dest[n]) & 0xffff;
996 	}
997 
998 	return r;
999 }
1000 
1001 static void
1002 sum16_destroyer(__ops_reader_info_t * rinfo)
1003 {
1004 	free(__ops_reader_get_arg(rinfo));
1005 }
1006 
1007 /**
1008    \ingroup Internal_Readers_Sum16
1009    \param pinfo Parse settings
1010 */
1011 
1012 void
1013 __ops_reader_push_sum16(__ops_parse_info_t * pinfo)
1014 {
1015 	sum16_t    *arg = calloc(1, sizeof(*arg));
1016 
1017 	__ops_reader_push(pinfo, sum16_reader, sum16_destroyer, arg);
1018 }
1019 
1020 /**
1021    \ingroup Internal_Readers_Sum16
1022    \param pinfo Parse settings
1023    \return sum
1024 */
1025 unsigned short
1026 __ops_reader_pop_sum16(__ops_parse_info_t * pinfo)
1027 {
1028 	sum16_t    *arg = __ops_reader_get_arg(__ops_parse_get_rinfo(pinfo));
1029 	unsigned short  sum = arg->sum;
1030 
1031 	__ops_reader_pop(pinfo);
1032 	free(arg);
1033 
1034 	return sum;
1035 }
1036 
1037 /* small useful functions for setting the file-level debugging levels */
1038 /* if the debugv list contains the filename in question, we're debugging it */
1039 
1040 enum {
1041 	MAX_DEBUG_NAMES = 32
1042 };
1043 
1044 static int      debugc;
1045 static char    *debugv[MAX_DEBUG_NAMES];
1046 
1047 /* set the debugging level per filename */
1048 int
1049 __ops_set_debug_level(const char *f)
1050 {
1051 	const char     *name;
1052 	int             i;
1053 
1054 	if (f == NULL) {
1055 		f = "all";
1056 	}
1057 	if ((name = strrchr(f, '/')) == NULL) {
1058 		name = f;
1059 	} else {
1060 		name += 1;
1061 	}
1062 	for (i = 0; i < debugc && i < MAX_DEBUG_NAMES; i++) {
1063 		if (strcmp(debugv[i], name) == 0) {
1064 			return 1;
1065 		}
1066 	}
1067 	if (i == MAX_DEBUG_NAMES) {
1068 		return 0;
1069 	}
1070 	debugv[debugc++] = strdup(name);
1071 	return 1;
1072 }
1073 
1074 /* get the debugging level per filename */
1075 int
1076 __ops_get_debug_level(const char *f)
1077 {
1078 	const char     *name;
1079 	int             i;
1080 
1081 	if ((name = strrchr(f, '/')) == NULL) {
1082 		name = f;
1083 	} else {
1084 		name += 1;
1085 	}
1086 	for (i = 0; i < debugc; i++) {
1087 		if (strcmp(debugv[i], "all") == 0 ||
1088 		    strcmp(debugv[i], name) == 0) {
1089 			return 1;
1090 		}
1091 	}
1092 	return 0;
1093 }
1094 
1095 /* return the version for the library */
1096 const char *
1097 __ops_get_info(const char *type)
1098 {
1099 	if (strcmp(type, "version") == 0) {
1100 		return NETPGP_VERSION_STRING;
1101 	}
1102 	if (strcmp(type, "maintainer") == 0) {
1103 		return NETPGP_MAINTAINER;
1104 	}
1105 	return "[unknown]";
1106 }
1107