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