xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/keyring.c (revision 179b12252ecaf3553d9c2b7458ce62b6a2203d0c)
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 #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: keyring.c,v 1.44 2010/08/21 19:00:43 agc Exp $");
61 #endif
62 
63 #ifdef HAVE_FCNTL_H
64 #include <fcntl.h>
65 #endif
66 
67 #include <regex.h>
68 #include <stdlib.h>
69 #include <string.h>
70 
71 #ifdef HAVE_TERMIOS_H
72 #include <termios.h>
73 #endif
74 
75 #ifdef HAVE_UNISTD_H
76 #include <unistd.h>
77 #endif
78 
79 #include "types.h"
80 #include "keyring.h"
81 #include "packet-parse.h"
82 #include "signature.h"
83 #include "netpgpsdk.h"
84 #include "readerwriter.h"
85 #include "netpgpdefs.h"
86 #include "packet.h"
87 #include "crypto.h"
88 #include "validate.h"
89 #include "netpgpdefs.h"
90 #include "netpgpdigest.h"
91 
92 
93 
94 /**
95    \ingroup HighLevel_Keyring
96 
97    \brief Creates a new __ops_key_t struct
98 
99    \return A new __ops_key_t struct, initialised to zero.
100 
101    \note The returned __ops_key_t struct must be freed after use with __ops_keydata_free.
102 */
103 
104 __ops_key_t  *
105 __ops_keydata_new(void)
106 {
107 	return calloc(1, sizeof(__ops_key_t));
108 }
109 
110 
111 /**
112  \ingroup HighLevel_Keyring
113 
114  \brief Frees keydata and its memory
115 
116  \param keydata Key to be freed.
117 
118  \note This frees the keydata itself, as well as any other memory alloc-ed by it.
119 */
120 void
121 __ops_keydata_free(__ops_key_t *keydata)
122 {
123 	unsigned        n;
124 
125 	for (n = 0; n < keydata->uidc; ++n) {
126 		__ops_userid_free(&keydata->uids[n]);
127 	}
128 	free(keydata->uids);
129 	keydata->uids = NULL;
130 	keydata->uidc = 0;
131 
132 	for (n = 0; n < keydata->packetc; ++n) {
133 		__ops_subpacket_free(&keydata->packets[n]);
134 	}
135 	free(keydata->packets);
136 	keydata->packets = NULL;
137 	keydata->packetc = 0;
138 
139 	if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) {
140 		__ops_pubkey_free(&keydata->key.pubkey);
141 	} else {
142 		__ops_seckey_free(&keydata->key.seckey);
143 	}
144 
145 	free(keydata);
146 }
147 
148 /**
149  \ingroup HighLevel_KeyGeneral
150 
151  \brief Returns the public key in the given keydata.
152  \param keydata
153 
154   \return Pointer to public key
155 
156   \note This is not a copy, do not free it after use.
157 */
158 
159 const __ops_pubkey_t *
160 __ops_get_pubkey(const __ops_key_t *keydata)
161 {
162 	return (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) ?
163 				&keydata->key.pubkey :
164 				&keydata->key.seckey.pubkey;
165 }
166 
167 /**
168 \ingroup HighLevel_KeyGeneral
169 
170 \brief Check whether this is a secret key or not.
171 */
172 
173 unsigned
174 __ops_is_key_secret(const __ops_key_t *data)
175 {
176 	return data->type != OPS_PTAG_CT_PUBLIC_KEY;
177 }
178 
179 /**
180  \ingroup HighLevel_KeyGeneral
181 
182  \brief Returns the secret key in the given keydata.
183 
184  \note This is not a copy, do not free it after use.
185 
186  \note This returns a const.  If you need to be able to write to this
187  pointer, use __ops_get_writable_seckey
188 */
189 
190 const __ops_seckey_t *
191 __ops_get_seckey(const __ops_key_t *data)
192 {
193 	return (data->type == OPS_PTAG_CT_SECRET_KEY) ?
194 				&data->key.seckey : NULL;
195 }
196 
197 /**
198  \ingroup HighLevel_KeyGeneral
199 
200   \brief Returns the secret key in the given keydata.
201 
202   \note This is not a copy, do not free it after use.
203 
204   \note If you do not need to be able to modify this key, there is an
205   equivalent read-only function __ops_get_seckey.
206 */
207 
208 __ops_seckey_t *
209 __ops_get_writable_seckey(__ops_key_t *data)
210 {
211 	return (data->type == OPS_PTAG_CT_SECRET_KEY) ?
212 				&data->key.seckey : NULL;
213 }
214 
215 /* utility function to zero out memory */
216 void
217 __ops_forget(void *vp, unsigned size)
218 {
219 	(void) memset(vp, 0x0, size);
220 }
221 
222 typedef struct {
223 	FILE			*passfp;
224 	const __ops_key_t	*key;
225 	char			*passphrase;
226 	__ops_seckey_t		*seckey;
227 } decrypt_t;
228 
229 static __ops_cb_ret_t
230 decrypt_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
231 {
232 	const __ops_contents_t	*content = &pkt->u;
233 	decrypt_t		*decrypt;
234 	char			 pass[MAX_PASSPHRASE_LENGTH];
235 
236 	decrypt = __ops_callback_arg(cbinfo);
237 	switch (pkt->tag) {
238 	case OPS_PARSER_PTAG:
239 	case OPS_PTAG_CT_USER_ID:
240 	case OPS_PTAG_CT_SIGNATURE:
241 	case OPS_PTAG_CT_SIGNATURE_HEADER:
242 	case OPS_PTAG_CT_SIGNATURE_FOOTER:
243 	case OPS_PTAG_CT_TRUST:
244 		break;
245 
246 	case OPS_GET_PASSPHRASE:
247 		(void) __ops_getpassphrase(decrypt->passfp, pass, sizeof(pass));
248 		*content->skey_passphrase.passphrase = netpgp_strdup(pass);
249 		__ops_forget(pass, (unsigned)sizeof(pass));
250 		return OPS_KEEP_MEMORY;
251 
252 	case OPS_PARSER_ERRCODE:
253 		switch (content->errcode.errcode) {
254 		case OPS_E_P_MPI_FORMAT_ERROR:
255 			/* Generally this means a bad passphrase */
256 			fprintf(stderr, "Bad passphrase!\n");
257 			return OPS_RELEASE_MEMORY;
258 
259 		case OPS_E_P_PACKET_CONSUMED:
260 			/* And this is because of an error we've accepted */
261 			return OPS_RELEASE_MEMORY;
262 		default:
263 			break;
264 		}
265 		(void) fprintf(stderr, "parse error: %s\n",
266 				__ops_errcode(content->errcode.errcode));
267 		return OPS_FINISHED;
268 
269 	case OPS_PARSER_ERROR:
270 		fprintf(stderr, "parse error: %s\n", content->error);
271 		return OPS_FINISHED;
272 
273 	case OPS_PTAG_CT_SECRET_KEY:
274 		if ((decrypt->seckey = calloc(1, sizeof(*decrypt->seckey))) == NULL) {
275 			(void) fprintf(stderr, "decrypt_cb: bad alloc\n");
276 			return OPS_FINISHED;
277 		}
278 		decrypt->seckey->checkhash = calloc(1, OPS_CHECKHASH_SIZE);
279 		*decrypt->seckey = content->seckey;
280 		return OPS_KEEP_MEMORY;
281 
282 	case OPS_PARSER_PACKET_END:
283 		/* nothing to do */
284 		break;
285 
286 	default:
287 		fprintf(stderr, "Unexpected tag %d (0x%x)\n", pkt->tag,
288 			pkt->tag);
289 		return OPS_FINISHED;
290 	}
291 
292 	return OPS_RELEASE_MEMORY;
293 }
294 
295 /**
296 \ingroup Core_Keys
297 \brief Decrypts secret key from given keydata with given passphrase
298 \param key Key from which to get secret key
299 \param passphrase Passphrase to use to decrypt secret key
300 \return secret key
301 */
302 __ops_seckey_t *
303 __ops_decrypt_seckey(const __ops_key_t *key, void *passfp)
304 {
305 	__ops_stream_t	*stream;
306 	const int	 printerrors = 1;
307 	decrypt_t	 decrypt;
308 
309 	(void) memset(&decrypt, 0x0, sizeof(decrypt));
310 	decrypt.key = key;
311 	decrypt.passfp = passfp;
312 	stream = __ops_new(sizeof(*stream));
313 	__ops_keydata_reader_set(stream, key);
314 	__ops_set_callback(stream, decrypt_cb, &decrypt);
315 	stream->readinfo.accumulate = 1;
316 	__ops_parse(stream, !printerrors);
317 	return decrypt.seckey;
318 }
319 
320 /**
321 \ingroup Core_Keys
322 \brief Set secret key in content
323 \param content Content to be set
324 \param key Keydata to get secret key from
325 */
326 void
327 __ops_set_seckey(__ops_contents_t *cont, const __ops_key_t *key)
328 {
329 	*cont->get_seckey.seckey = &key->key.seckey;
330 }
331 
332 /**
333 \ingroup Core_Keys
334 \brief Get Key ID from keydata
335 \param key Keydata to get Key ID from
336 \return Pointer to Key ID inside keydata
337 */
338 const uint8_t *
339 __ops_get_key_id(const __ops_key_t *key)
340 {
341 	return key->sigid;
342 }
343 
344 /**
345 \ingroup Core_Keys
346 \brief How many User IDs in this key?
347 \param key Keydata to check
348 \return Num of user ids
349 */
350 unsigned
351 __ops_get_userid_count(const __ops_key_t *key)
352 {
353 	return key->uidc;
354 }
355 
356 /**
357 \ingroup Core_Keys
358 \brief Get indexed user id from key
359 \param key Key to get user id from
360 \param index Which key to get
361 \return Pointer to requested user id
362 */
363 const uint8_t *
364 __ops_get_userid(const __ops_key_t *key, unsigned subscript)
365 {
366 	return key->uids[subscript];
367 }
368 
369 /**
370    \ingroup HighLevel_Supported
371    \brief Checks whether key's algorithm and type are supported by OpenPGP::SDK
372    \param keydata Key to be checked
373    \return 1 if key algorithm and type are supported by OpenPGP::SDK; 0 if not
374 */
375 
376 unsigned
377 __ops_is_key_supported(const __ops_key_t *key)
378 {
379 	if (key->type == OPS_PTAG_CT_PUBLIC_KEY) {
380 		switch(key->key.pubkey.alg) {
381 		case OPS_PKA_RSA:
382 		case OPS_PKA_DSA:
383 		case OPS_PKA_ELGAMAL:
384 			return 1;
385 		default:
386 			break;
387 		}
388 	}
389 	return 0;
390 }
391 
392 /* \todo check where userid pointers are copied */
393 /**
394 \ingroup Core_Keys
395 \brief Copy user id, including contents
396 \param dst Destination User ID
397 \param src Source User ID
398 \note If dst already has a userid, it will be freed.
399 */
400 static uint8_t *
401 __ops_copy_userid(uint8_t **dst, const uint8_t *src)
402 {
403 	size_t          len;
404 
405 	len = strlen((const char *) src);
406 	if (*dst) {
407 		free(*dst);
408 	}
409 	if ((*dst = calloc(1, len + 1)) == NULL) {
410 		(void) fprintf(stderr, "__ops_copy_userid: bad alloc\n");
411 	} else {
412 		(void) memcpy(*dst, src, len);
413 	}
414 	return *dst;
415 }
416 
417 /* \todo check where pkt pointers are copied */
418 /**
419 \ingroup Core_Keys
420 \brief Copy packet, including contents
421 \param dst Destination packet
422 \param src Source packet
423 \note If dst already has a packet, it will be freed.
424 */
425 static __ops_subpacket_t *
426 __ops_copy_packet(__ops_subpacket_t *dst, const __ops_subpacket_t *src)
427 {
428 	if (dst->raw) {
429 		free(dst->raw);
430 	}
431 	if ((dst->raw = calloc(1, src->length)) == NULL) {
432 		(void) fprintf(stderr, "__ops_copy_packet: bad alloc\n");
433 	} else {
434 		dst->length = src->length;
435 		(void) memcpy(dst->raw, src->raw, src->length);
436 	}
437 	return dst;
438 }
439 
440 /**
441 \ingroup Core_Keys
442 \brief Add User ID to key
443 \param key Key to which to add User ID
444 \param userid User ID to add
445 \return Pointer to new User ID
446 */
447 uint8_t  *
448 __ops_add_userid(__ops_key_t *key, const uint8_t *userid)
449 {
450 	uint8_t  **uidp;
451 
452 	EXPAND_ARRAY(key, uid);
453 	/* initialise new entry in array */
454 	uidp = &key->uids[key->uidc++];
455 	*uidp = NULL;
456 	/* now copy it */
457 	return __ops_copy_userid(uidp, userid);
458 }
459 
460 void print_packet_hex(const __ops_subpacket_t *pkt);
461 
462 /**
463 \ingroup Core_Keys
464 \brief Add packet to key
465 \param keydata Key to which to add packet
466 \param packet Packet to add
467 \return Pointer to new packet
468 */
469 __ops_subpacket_t   *
470 __ops_add_subpacket(__ops_key_t *keydata, const __ops_subpacket_t *packet)
471 {
472 	__ops_subpacket_t   *subpktp;
473 
474 	EXPAND_ARRAY(keydata, packet);
475 	/* initialise new entry in array */
476 	subpktp = &keydata->packets[keydata->packetc++];
477 	subpktp->length = 0;
478 	subpktp->raw = NULL;
479 	/* now copy it */
480 	return __ops_copy_packet(subpktp, packet);
481 }
482 
483 /**
484 \ingroup Core_Keys
485 \brief Add selfsigned User ID to key
486 \param keydata Key to which to add user ID
487 \param userid Self-signed User ID to add
488 \return 1 if OK; else 0
489 */
490 unsigned
491 __ops_add_selfsigned_userid(__ops_key_t *key, uint8_t *userid)
492 {
493 	__ops_create_sig_t	*sig;
494 	__ops_subpacket_t	 sigpacket;
495 	__ops_memory_t		*mem_userid = NULL;
496 	__ops_output_t		*useridoutput = NULL;
497 	__ops_memory_t		*mem_sig = NULL;
498 	__ops_output_t		*sigoutput = NULL;
499 
500 	/*
501          * create signature packet for this userid
502          */
503 
504 	/* create userid pkt */
505 	__ops_setup_memory_write(&useridoutput, &mem_userid, 128);
506 	__ops_write_struct_userid(useridoutput, userid);
507 
508 	/* create sig for this pkt */
509 	sig = __ops_create_sig_new();
510 	__ops_sig_start_key_sig(sig, &key->key.seckey.pubkey, userid, OPS_CERT_POSITIVE);
511 	__ops_add_time(sig, (int64_t)time(NULL), "birth");
512 	__ops_add_issuer_keyid(sig, key->sigid);
513 	__ops_add_primary_userid(sig, 1);
514 	__ops_end_hashed_subpkts(sig);
515 
516 	__ops_setup_memory_write(&sigoutput, &mem_sig, 128);
517 	__ops_write_sig(sigoutput, sig, &key->key.seckey.pubkey, &key->key.seckey);
518 
519 	/* add this packet to key */
520 	sigpacket.length = __ops_mem_len(mem_sig);
521 	sigpacket.raw = __ops_mem_data(mem_sig);
522 
523 	/* add userid to key */
524 	(void) __ops_add_userid(key, userid);
525 	(void) __ops_add_subpacket(key, &sigpacket);
526 
527 	/* cleanup */
528 	__ops_create_sig_delete(sig);
529 	__ops_output_delete(useridoutput);
530 	__ops_output_delete(sigoutput);
531 	__ops_memory_free(mem_userid);
532 	__ops_memory_free(mem_sig);
533 
534 	return 1;
535 }
536 
537 /**
538 \ingroup Core_Keys
539 \brief Initialise __ops_key_t
540 \param keydata Keydata to initialise
541 \param type OPS_PTAG_CT_PUBLIC_KEY or OPS_PTAG_CT_SECRET_KEY
542 */
543 void
544 __ops_keydata_init(__ops_key_t *keydata, const __ops_content_enum type)
545 {
546 	if (keydata->type != OPS_PTAG_CT_RESERVED) {
547 		(void) fprintf(stderr,
548 			"__ops_keydata_init: wrong keydata type\n");
549 	} else if (type != OPS_PTAG_CT_PUBLIC_KEY &&
550 		   type != OPS_PTAG_CT_SECRET_KEY) {
551 		(void) fprintf(stderr, "__ops_keydata_init: wrong type\n");
552 	} else {
553 		keydata->type = type;
554 	}
555 }
556 
557 /* used to point to data during keyring read */
558 typedef struct keyringcb_t {
559 	__ops_keyring_t		*keyring;	/* the keyring we're reading */
560 } keyringcb_t;
561 
562 
563 static __ops_cb_ret_t
564 cb_keyring_read(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
565 {
566 	__ops_keyring_t	*keyring;
567 	__ops_revoke_t	*revocation;
568 	__ops_key_t	*key;
569 	keyringcb_t	*cb;
570 
571 	cb = __ops_callback_arg(cbinfo);
572 	keyring = cb->keyring;
573 	switch (pkt->tag) {
574 	case OPS_PARSER_PTAG:
575 	case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
576 		/* we get these because we didn't prompt */
577 		break;
578 	case OPS_PTAG_CT_SIGNATURE_HEADER:
579 		key = &keyring->keys[keyring->keyc - 1];
580 		EXPAND_ARRAY(key, subsig);
581 		key->subsigs[key->subsigc].uid = key->uidc - 1;
582 		(void) memcpy(&key->subsigs[key->subsigc].sig, &pkt->u.sig,
583 				sizeof(pkt->u.sig));
584 		key->subsigc += 1;
585 		break;
586 	case OPS_PTAG_CT_SIGNATURE:
587 		key = &keyring->keys[keyring->keyc - 1];
588 		EXPAND_ARRAY(key, subsig);
589 		key->subsigs[key->subsigc].uid = key->uidc - 1;
590 		(void) memcpy(&key->subsigs[key->subsigc].sig, &pkt->u.sig,
591 				sizeof(pkt->u.sig));
592 		key->subsigc += 1;
593 		break;
594 	case OPS_PTAG_CT_TRUST:
595 		key = &keyring->keys[keyring->keyc - 1];
596 		key->subsigs[key->subsigc - 1].trustlevel = pkt->u.ss_trust.level;
597 		key->subsigs[key->subsigc - 1].trustamount = pkt->u.ss_trust.amount;
598 		break;
599 	case OPS_PTAG_SS_KEY_EXPIRY:
600 		EXPAND_ARRAY(keyring, key);
601 		if (keyring->keyc > 0) {
602 			keyring->keys[keyring->keyc - 1].key.pubkey.duration = pkt->u.ss_time;
603 		}
604 		break;
605 	case OPS_PTAG_SS_ISSUER_KEY_ID:
606 		key = &keyring->keys[keyring->keyc - 1];
607 		(void) memcpy(&key->subsigs[key->subsigc - 1].sig.info.signer_id,
608 			      pkt->u.ss_issuer,
609 			      sizeof(pkt->u.ss_issuer));
610 		key->subsigs[key->subsigc - 1].sig.info.signer_id_set = 1;
611 		break;
612 	case OPS_PTAG_SS_CREATION_TIME:
613 		key = &keyring->keys[keyring->keyc - 1];
614 		key->subsigs[key->subsigc - 1].sig.info.birthtime = pkt->u.ss_time;
615 		key->subsigs[key->subsigc - 1].sig.info.birthtime_set = 1;
616 		break;
617 	case OPS_PTAG_SS_EXPIRATION_TIME:
618 		key = &keyring->keys[keyring->keyc - 1];
619 		key->subsigs[key->subsigc - 1].sig.info.duration = pkt->u.ss_time;
620 		key->subsigs[key->subsigc - 1].sig.info.duration_set = 1;
621 		break;
622 	case OPS_PTAG_SS_PRIMARY_USER_ID:
623 		key = &keyring->keys[keyring->keyc - 1];
624 		key->uid0 = key->uidc - 1;
625 		break;
626 	case OPS_PTAG_SS_REVOCATION_REASON:
627 		key = &keyring->keys[keyring->keyc - 1];
628 		if (key->uidc == 0) {
629 			/* revoke whole key */
630 			key->revoked = 1;
631 			revocation = &key->revocation;
632 		} else {
633 			/* revoke the user id */
634 			EXPAND_ARRAY(key, revoke);
635 			revocation = &key->revokes[key->revokec];
636 			key->revokes[key->revokec].uid = key->uidc - 1;
637 			key->revokec += 1;
638 		}
639 		revocation->code = pkt->u.ss_revocation.code;
640 		revocation->reason = netpgp_strdup(__ops_show_ss_rr_code(pkt->u.ss_revocation.code));
641 		break;
642 	case OPS_PTAG_CT_SIGNATURE_FOOTER:
643 	case OPS_PARSER_ERRCODE:
644 		break;
645 
646 	default:
647 		break;
648 	}
649 
650 	return OPS_RELEASE_MEMORY;
651 }
652 
653 /**
654    \ingroup HighLevel_KeyringRead
655 
656    \brief Reads a keyring from a file
657 
658    \param keyring Pointer to an existing __ops_keyring_t struct
659    \param armour 1 if file is armoured; else 0
660    \param filename Filename of keyring to be read
661 
662    \return __ops 1 if OK; 0 on error
663 
664    \note Keyring struct must already exist.
665 
666    \note Can be used with either a public or secret keyring.
667 
668    \note You must call __ops_keyring_free() after usage to free alloc-ed memory.
669 
670    \note If you call this twice on the same keyring struct, without calling
671    __ops_keyring_free() between these calls, you will introduce a memory leak.
672 
673    \sa __ops_keyring_read_from_mem()
674    \sa __ops_keyring_free()
675 
676 */
677 
678 unsigned
679 __ops_keyring_fileread(__ops_keyring_t *keyring,
680 			const unsigned armour,
681 			const char *filename)
682 {
683 	__ops_stream_t	*stream;
684 	keyringcb_t	 cb;
685 	unsigned	 res = 1;
686 	int		 fd;
687 
688 	(void) memset(&cb, 0x0, sizeof(cb));
689 	cb.keyring = keyring;
690 	stream = __ops_new(sizeof(*stream));
691 
692 	/* add this for the moment, */
693 	/*
694 	 * \todo need to fix the problems with reading signature subpackets
695 	 * later
696 	 */
697 
698 	/* __ops_parse_options(parse,OPS_PTAG_SS_ALL,OPS_PARSE_RAW); */
699 	__ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
700 
701 #ifdef O_BINARY
702 	fd = open(filename, O_RDONLY | O_BINARY);
703 #else
704 	fd = open(filename, O_RDONLY);
705 #endif
706 	if (fd < 0) {
707 		__ops_stream_delete(stream);
708 		perror(filename);
709 		return 0;
710 	}
711 #ifdef USE_MMAP_FOR_FILES
712 	__ops_reader_set_mmap(stream, fd);
713 #else
714 	__ops_reader_set_fd(stream, fd);
715 #endif
716 
717 	__ops_set_callback(stream, cb_keyring_read, &cb);
718 
719 	if (armour) {
720 		__ops_reader_push_dearmour(stream);
721 	}
722 	res = __ops_parse_and_accumulate(keyring, stream);
723 	__ops_print_errors(__ops_stream_get_errors(stream));
724 
725 	if (armour) {
726 		__ops_reader_pop_dearmour(stream);
727 	}
728 
729 	(void)close(fd);
730 
731 	__ops_stream_delete(stream);
732 
733 	return res;
734 }
735 
736 /**
737    \ingroup HighLevel_KeyringRead
738 
739    \brief Reads a keyring from memory
740 
741    \param keyring Pointer to existing __ops_keyring_t struct
742    \param armour 1 if file is armoured; else 0
743    \param mem Pointer to a __ops_memory_t struct containing keyring to be read
744 
745    \return __ops 1 if OK; 0 on error
746 
747    \note Keyring struct must already exist.
748 
749    \note Can be used with either a public or secret keyring.
750 
751    \note You must call __ops_keyring_free() after usage to free alloc-ed memory.
752 
753    \note If you call this twice on the same keyring struct, without calling
754    __ops_keyring_free() between these calls, you will introduce a memory leak.
755 
756    \sa __ops_keyring_fileread
757    \sa __ops_keyring_free
758 */
759 unsigned
760 __ops_keyring_read_from_mem(__ops_io_t *io,
761 				__ops_keyring_t *keyring,
762 				const unsigned armour,
763 				__ops_memory_t *mem)
764 {
765 	__ops_stream_t	*stream;
766 	const unsigned	 noaccum = 0;
767 	keyringcb_t	 cb;
768 	unsigned	 res;
769 
770 	(void) memset(&cb, 0x0, sizeof(cb));
771 	cb.keyring = keyring;
772 	stream = __ops_new(sizeof(*stream));
773 	__ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
774 	__ops_setup_memory_read(io, &stream, mem, &cb, cb_keyring_read,
775 					noaccum);
776 	if (armour) {
777 		__ops_reader_push_dearmour(stream);
778 	}
779 	res = (unsigned)__ops_parse_and_accumulate(keyring, stream);
780 	__ops_print_errors(__ops_stream_get_errors(stream));
781 	if (armour) {
782 		__ops_reader_pop_dearmour(stream);
783 	}
784 	/* don't call teardown_memory_read because memory was passed in */
785 	__ops_stream_delete(stream);
786 	return res;
787 }
788 
789 /**
790    \ingroup HighLevel_KeyringRead
791 
792    \brief Frees keyring's contents (but not keyring itself)
793 
794    \param keyring Keyring whose data is to be freed
795 
796    \note This does not free keyring itself, just the memory alloc-ed in it.
797  */
798 void
799 __ops_keyring_free(__ops_keyring_t *keyring)
800 {
801 	(void)free(keyring->keys);
802 	keyring->keys = NULL;
803 	keyring->keyc = keyring->keyvsize = 0;
804 }
805 
806 /**
807    \ingroup HighLevel_KeyringFind
808 
809    \brief Finds key in keyring from its Key ID
810 
811    \param keyring Keyring to be searched
812    \param keyid ID of required key
813 
814    \return Pointer to key, if found; NULL, if not found
815 
816    \note This returns a pointer to the key inside the given keyring,
817    not a copy.  Do not free it after use.
818 
819 */
820 const __ops_key_t *
821 __ops_getkeybyid(__ops_io_t *io, const __ops_keyring_t *keyring,
822 			   const uint8_t *keyid, unsigned *from, __ops_pubkey_t **pubkey)
823 {
824 	for ( ; keyring && *from < keyring->keyc; *from += 1) {
825 		if (__ops_get_debug_level(__FILE__)) {
826 			hexdump(io->errs, "keyring keyid", keyring->keys[*from].sigid, OPS_KEY_ID_SIZE);
827 			hexdump(io->errs, "keyid", keyid, OPS_KEY_ID_SIZE);
828 		}
829 		if (memcmp(keyring->keys[*from].sigid, keyid, OPS_KEY_ID_SIZE) == 0 ||
830 		    memcmp(&keyring->keys[*from].sigid[OPS_KEY_ID_SIZE / 2],
831 				keyid, OPS_KEY_ID_SIZE / 2) == 0) {
832 			if (pubkey) {
833 				*pubkey = &keyring->keys[*from].key.pubkey;
834 			}
835 			return &keyring->keys[*from];
836 		}
837 		if (memcmp(&keyring->keys[*from].encid, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", OPS_KEY_ID_SIZE) == 0) {
838 			continue;
839 		}
840 		if (memcmp(&keyring->keys[*from].encid, keyid, OPS_KEY_ID_SIZE) == 0 ||
841 		    memcmp(&keyring->keys[*from].encid[OPS_KEY_ID_SIZE / 2], keyid, OPS_KEY_ID_SIZE / 2) == 0) {
842 			if (pubkey) {
843 				*pubkey = &keyring->keys[*from].enckey;
844 			}
845 			return &keyring->keys[*from];
846 		}
847 	}
848 	return NULL;
849 }
850 
851 /* convert a string keyid into a binary keyid */
852 static void
853 str2keyid(const char *userid, uint8_t *keyid, size_t len)
854 {
855 	static const char	*uppers = "0123456789ABCDEF";
856 	static const char	*lowers = "0123456789abcdef";
857 	const char		*hi;
858 	const char		*lo;
859 	uint8_t			 hichar;
860 	uint8_t			 lochar;
861 	size_t			 j;
862 	int			 i;
863 
864 	for (i = 0, j = 0 ; j < len && userid[i] && userid[i + 1] ; i += 2, j++) {
865 		if ((hi = strchr(uppers, userid[i])) == NULL) {
866 			if ((hi = strchr(lowers, userid[i])) == NULL) {
867 				break;
868 			}
869 			hichar = (uint8_t)(hi - lowers);
870 		} else {
871 			hichar = (uint8_t)(hi - uppers);
872 		}
873 		if ((lo = strchr(uppers, userid[i + 1])) == NULL) {
874 			if ((lo = strchr(lowers, userid[i + 1])) == NULL) {
875 				break;
876 			}
877 			lochar = (uint8_t)(lo - lowers);
878 		} else {
879 			lochar = (uint8_t)(lo - uppers);
880 		}
881 		keyid[j] = (hichar << 4) | (lochar);
882 	}
883 	keyid[j] = 0x0;
884 }
885 
886 /* return the next key which matches, starting searching at *from */
887 static const __ops_key_t *
888 getkeybyname(__ops_io_t *io,
889 			const __ops_keyring_t *keyring,
890 			const char *name,
891 			unsigned *from)
892 {
893 	const __ops_key_t	*kp;
894 	uint8_t			**uidp;
895 	unsigned    	 	 i = 0;
896 	__ops_key_t		*keyp;
897 	unsigned		 savedstart;
898 	regex_t			 r;
899 	uint8_t		 	 keyid[OPS_KEY_ID_SIZE + 1];
900 	size_t          	 len;
901 
902 	if (!keyring) {
903 		return NULL;
904 	}
905 	len = strlen(name);
906 	if (__ops_get_debug_level(__FILE__)) {
907 		(void) fprintf(io->outs, "[%u] name '%s', len %zu\n",
908 			*from, name, len);
909 	}
910 	/* first try name as a keyid */
911 	(void) memset(keyid, 0x0, sizeof(keyid));
912 	str2keyid(name, keyid, sizeof(keyid));
913 	if (__ops_get_debug_level(__FILE__)) {
914 		hexdump(io->outs, "keyid", keyid, 4);
915 	}
916 	savedstart = *from;
917 	if ((kp = __ops_getkeybyid(io, keyring, keyid, from, NULL)) != NULL) {
918 		return kp;
919 	}
920 	*from = savedstart;
921 	if (__ops_get_debug_level(__FILE__)) {
922 		(void) fprintf(io->outs, "regex match '%s' from %u\n",
923 			name, *from);
924 	}
925 	/* match on full name or email address as a NOSUB, ICASE regexp */
926 	(void) regcomp(&r, name, REG_EXTENDED | REG_ICASE);
927 	for (keyp = &keyring->keys[*from]; *from < keyring->keyc; *from += 1, keyp++) {
928 		uidp = keyp->uids;
929 		for (i = 0 ; i < keyp->uidc; i++, uidp++) {
930 			if (regexec(&r, (char *)*uidp, 0, NULL, 0) == 0) {
931 				if (__ops_get_debug_level(__FILE__)) {
932 					(void) fprintf(io->outs,
933 						"MATCHED keyid \"%s\" len %" PRIsize "u\n",
934 					       (char *) *uidp, len);
935 				}
936 				regfree(&r);
937 				return keyp;
938 			}
939 		}
940 	}
941 	regfree(&r);
942 	return NULL;
943 }
944 
945 /**
946    \ingroup HighLevel_KeyringFind
947 
948    \brief Finds key from its User ID
949 
950    \param keyring Keyring to be searched
951    \param userid User ID of required key
952 
953    \return Pointer to Key, if found; NULL, if not found
954 
955    \note This returns a pointer to the key inside the keyring, not a
956    copy.  Do not free it.
957 
958 */
959 const __ops_key_t *
960 __ops_getkeybyname(__ops_io_t *io,
961 			const __ops_keyring_t *keyring,
962 			const char *name)
963 {
964 	unsigned	from;
965 
966 	from = 0;
967 	return getkeybyname(io, keyring, name, &from);
968 }
969 
970 const __ops_key_t *
971 __ops_getnextkeybyname(__ops_io_t *io,
972 			const __ops_keyring_t *keyring,
973 			const char *name,
974 			unsigned *n)
975 {
976 	return getkeybyname(io, keyring, name, n);
977 }
978 
979 /**
980    \ingroup HighLevel_KeyringList
981 
982    \brief Prints all keys in keyring to stdout.
983 
984    \param keyring Keyring to use
985 
986    \return none
987 */
988 int
989 __ops_keyring_list(__ops_io_t *io, const __ops_keyring_t *keyring, const int psigs)
990 {
991 	__ops_key_t		*key;
992 	unsigned		 n;
993 
994 	(void) fprintf(io->res, "%u key%s\n", keyring->keyc,
995 		(keyring->keyc == 1) ? "" : "s");
996 	for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) {
997 		if (__ops_is_key_secret(key)) {
998 			__ops_print_keydata(io, keyring, key, "sec",
999 				&key->key.seckey.pubkey, 0);
1000 		} else {
1001 			__ops_print_keydata(io, keyring, key, "pub", &key->key.pubkey, psigs);
1002 		}
1003 		(void) fputc('\n', io->res);
1004 	}
1005 	return 1;
1006 }
1007 
1008 int
1009 __ops_keyring_json(__ops_io_t *io, const __ops_keyring_t *keyring, mj_t *obj, const int psigs)
1010 {
1011 	__ops_key_t		*key;
1012 	unsigned		 n;
1013 
1014 	(void) memset(obj, 0x0, sizeof(*obj));
1015 	mj_create(obj, "array");
1016 	obj->size = keyring->keyvsize;
1017 	if (__ops_get_debug_level(__FILE__)) {
1018 		(void) fprintf(io->errs, "__ops_keyring_json: vsize %u\n", obj->size);
1019 	}
1020 	if ((obj->value.v = calloc(sizeof(*obj->value.v), obj->size)) == NULL) {
1021 		(void) fprintf(io->errs, "calloc failure\n");
1022 		return 0;
1023 	}
1024 	for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) {
1025 		if (__ops_is_key_secret(key)) {
1026 			__ops_sprint_mj(io, keyring, key, &obj->value.v[obj->c],
1027 				"sec", &key->key.seckey.pubkey, psigs);
1028 		} else {
1029 			__ops_sprint_mj(io, keyring, key, &obj->value.v[obj->c],
1030 				"signature ", &key->key.pubkey, psigs);
1031 		}
1032 		if (obj->value.v[obj->c].type != 0) {
1033 			obj->c += 1;
1034 		}
1035 	}
1036 	if (__ops_get_debug_level(__FILE__)) {
1037 		char	*s;
1038 
1039 		mj_asprint(&s, obj);
1040 		(void) fprintf(stderr, "__ops_keyring_json: '%s'\n", s);
1041 		free(s);
1042 	}
1043 	return 1;
1044 }
1045 
1046 
1047 /* this interface isn't right - hook into callback for getting passphrase */
1048 char *
1049 __ops_export_key(__ops_io_t *io, const __ops_key_t *keydata, uint8_t *passphrase)
1050 {
1051 	__ops_output_t	*output;
1052 	__ops_memory_t	*mem;
1053 	char		*cp;
1054 
1055 	__OPS_USED(io);
1056 	__ops_setup_memory_write(&output, &mem, 128);
1057 	if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) {
1058 		__ops_write_xfer_pubkey(output, keydata, 1);
1059 	} else {
1060 		__ops_write_xfer_seckey(output, keydata, passphrase,
1061 					strlen((char *)passphrase), 1);
1062 	}
1063 	cp = netpgp_strdup(__ops_mem_data(mem));
1064 	__ops_teardown_memory_write(output, mem);
1065 	return cp;
1066 }
1067 
1068 /* add a key to a public keyring */
1069 int
1070 __ops_add_to_pubring(__ops_keyring_t *keyring, const __ops_pubkey_t *pubkey, __ops_content_enum tag)
1071 {
1072 	__ops_key_t	*key;
1073 	time_t		 duration;
1074 
1075 	if (__ops_get_debug_level(__FILE__)) {
1076 		fprintf(stderr, "__ops_add_to_pubring (type %u)\n", tag);
1077 	}
1078 	switch(tag) {
1079 	case OPS_PTAG_CT_PUBLIC_KEY:
1080 		EXPAND_ARRAY(keyring, key);
1081 		key = &keyring->keys[keyring->keyc++];
1082 		duration = key->key.pubkey.duration;
1083 		(void) memset(key, 0x0, sizeof(*key));
1084 		key->type = tag;
1085 		__ops_keyid(key->sigid, OPS_KEY_ID_SIZE, pubkey, keyring->hashtype);
1086 		__ops_fingerprint(&key->sigfingerprint, pubkey, keyring->hashtype);
1087 		key->key.pubkey = *pubkey;
1088 		key->key.pubkey.duration = duration;
1089 		return 1;
1090 	case OPS_PTAG_CT_PUBLIC_SUBKEY:
1091 		/* subkey is not the first */
1092 		key = &keyring->keys[keyring->keyc - 1];
1093 		__ops_keyid(key->encid, OPS_KEY_ID_SIZE, pubkey, keyring->hashtype);
1094 		duration = key->key.pubkey.duration;
1095 		(void) memcpy(&key->enckey, pubkey, sizeof(key->enckey));
1096 		key->enckey.duration = duration;
1097 		return 1;
1098 	default:
1099 		return 0;
1100 	}
1101 }
1102 
1103 /* add a key to a secret keyring */
1104 int
1105 __ops_add_to_secring(__ops_keyring_t *keyring, const __ops_seckey_t *seckey)
1106 {
1107 	const __ops_pubkey_t	*pubkey;
1108 	__ops_key_t		*key;
1109 
1110 	if (__ops_get_debug_level(__FILE__)) {
1111 		fprintf(stderr, "__ops_add_to_secring\n");
1112 	}
1113 	if (keyring->keyc > 0) {
1114 		key = &keyring->keys[keyring->keyc - 1];
1115 		if (__ops_get_debug_level(__FILE__) &&
1116 		    key->key.pubkey.alg == OPS_PKA_DSA &&
1117 		    seckey->pubkey.alg == OPS_PKA_ELGAMAL) {
1118 			fprintf(stderr, "__ops_add_to_secring: found elgamal seckey\n");
1119 		}
1120 	}
1121 	EXPAND_ARRAY(keyring, key);
1122 	key = &keyring->keys[keyring->keyc++];
1123 	(void) memset(key, 0x0, sizeof(*key));
1124 	pubkey = &seckey->pubkey;
1125 	__ops_keyid(key->sigid, OPS_KEY_ID_SIZE, pubkey, keyring->hashtype);
1126 	__ops_fingerprint(&key->sigfingerprint, pubkey, keyring->hashtype);
1127 	key->type = OPS_PTAG_CT_SECRET_KEY;
1128 	key->key.seckey = *seckey;
1129 	if (__ops_get_debug_level(__FILE__)) {
1130 		fprintf(stderr, "__ops_add_to_secring: keyc %u\n", keyring->keyc);
1131 	}
1132 	return 1;
1133 }
1134 
1135 /* append one keyring to another */
1136 int
1137 __ops_append_keyring(__ops_keyring_t *keyring, __ops_keyring_t *newring)
1138 {
1139 	unsigned	i;
1140 
1141 	for (i = 0 ; i < newring->keyc ; i++) {
1142 		EXPAND_ARRAY(keyring, key);
1143 		(void) memcpy(&keyring->keys[keyring->keyc], &newring->keys[i],
1144 				sizeof(newring->keys[i]));
1145 		keyring->keyc += 1;
1146 	}
1147 	return 1;
1148 }
1149