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