xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/keyring.c (revision 5c46dd73a9bcb28b2994504ea090f64066b17a77)
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.37 2010/05/25 01:05:10 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, 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->key_id;
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 		if (key->key.pubkey.alg == OPS_PKA_RSA) {
381 			return 1;
382 		}
383 	} else if (key->type == OPS_PTAG_CT_PUBLIC_KEY) {
384 		if (key->key.pubkey.alg == OPS_PKA_DSA) {
385 			return 1;
386 		}
387 	}
388 	return 0;
389 }
390 
391 /* \todo check where userid pointers are copied */
392 /**
393 \ingroup Core_Keys
394 \brief Copy user id, including contents
395 \param dst Destination User ID
396 \param src Source User ID
397 \note If dst already has a userid, it will be freed.
398 */
399 static uint8_t *
400 __ops_copy_userid(uint8_t **dst, const uint8_t *src)
401 {
402 	size_t          len;
403 
404 	len = strlen((const char *) src);
405 	if (*dst) {
406 		free(*dst);
407 	}
408 	if ((*dst = calloc(1, len + 1)) == NULL) {
409 		(void) fprintf(stderr, "__ops_copy_userid: bad alloc\n");
410 	} else {
411 		(void) memcpy(*dst, src, len);
412 	}
413 	return *dst;
414 }
415 
416 /* \todo check where pkt pointers are copied */
417 /**
418 \ingroup Core_Keys
419 \brief Copy packet, including contents
420 \param dst Destination packet
421 \param src Source packet
422 \note If dst already has a packet, it will be freed.
423 */
424 static __ops_subpacket_t *
425 __ops_copy_packet(__ops_subpacket_t *dst, const __ops_subpacket_t *src)
426 {
427 	if (dst->raw) {
428 		free(dst->raw);
429 	}
430 	if ((dst->raw = calloc(1, src->length)) == NULL) {
431 		(void) fprintf(stderr, "__ops_copy_packet: bad alloc\n");
432 	} else {
433 		dst->length = src->length;
434 		(void) memcpy(dst->raw, src->raw, src->length);
435 	}
436 	return dst;
437 }
438 
439 /**
440 \ingroup Core_Keys
441 \brief Add User ID to key
442 \param key Key to which to add User ID
443 \param userid User ID to add
444 \return Pointer to new User ID
445 */
446 uint8_t  *
447 __ops_add_userid(__ops_key_t *key, const uint8_t *userid)
448 {
449 	uint8_t  **uidp;
450 
451 	EXPAND_ARRAY(key, uid);
452 	/* initialise new entry in array */
453 	uidp = &key->uids[key->uidc++];
454 	*uidp = NULL;
455 	/* now copy it */
456 	return __ops_copy_userid(uidp, userid);
457 }
458 
459 void print_packet_hex(const __ops_subpacket_t *pkt);
460 
461 /**
462 \ingroup Core_Keys
463 \brief Add packet to key
464 \param keydata Key to which to add packet
465 \param packet Packet to add
466 \return Pointer to new packet
467 */
468 __ops_subpacket_t   *
469 __ops_add_subpacket(__ops_key_t *keydata, const __ops_subpacket_t *packet)
470 {
471 	__ops_subpacket_t   *subpktp;
472 
473 	EXPAND_ARRAY(keydata, packet);
474 	/* initialise new entry in array */
475 	subpktp = &keydata->packets[keydata->packetc++];
476 	subpktp->length = 0;
477 	subpktp->raw = NULL;
478 	/* now copy it */
479 	return __ops_copy_packet(subpktp, packet);
480 }
481 
482 /**
483 \ingroup Core_Keys
484 \brief Add selfsigned User ID to key
485 \param keydata Key to which to add user ID
486 \param userid Self-signed User ID to add
487 \return 1 if OK; else 0
488 */
489 unsigned
490 __ops_add_selfsigned_userid(__ops_key_t *key, uint8_t *userid)
491 {
492 	__ops_create_sig_t	*sig;
493 	__ops_subpacket_t	 sigpacket;
494 	__ops_memory_t		*mem_userid = NULL;
495 	__ops_output_t		*useridoutput = NULL;
496 	__ops_memory_t		*mem_sig = NULL;
497 	__ops_output_t		*sigoutput = NULL;
498 
499 	/*
500          * create signature packet for this userid
501          */
502 
503 	/* create userid pkt */
504 	__ops_setup_memory_write(&useridoutput, &mem_userid, 128);
505 	__ops_write_struct_userid(useridoutput, userid);
506 
507 	/* create sig for this pkt */
508 	sig = __ops_create_sig_new();
509 	__ops_sig_start_key_sig(sig, &key->key.seckey.pubkey, userid, OPS_CERT_POSITIVE);
510 	__ops_add_birthtime(sig, time(NULL));
511 	__ops_add_issuer_keyid(sig, key->key_id);
512 	__ops_add_primary_userid(sig, 1);
513 	__ops_end_hashed_subpkts(sig);
514 
515 	__ops_setup_memory_write(&sigoutput, &mem_sig, 128);
516 	__ops_write_sig(sigoutput, sig, &key->key.seckey.pubkey, &key->key.seckey);
517 
518 	/* add this packet to key */
519 	sigpacket.length = __ops_mem_len(mem_sig);
520 	sigpacket.raw = __ops_mem_data(mem_sig);
521 
522 	/* add userid to key */
523 	(void) __ops_add_userid(key, userid);
524 	(void) __ops_add_subpacket(key, &sigpacket);
525 
526 	/* cleanup */
527 	__ops_create_sig_delete(sig);
528 	__ops_output_delete(useridoutput);
529 	__ops_output_delete(sigoutput);
530 	__ops_memory_free(mem_userid);
531 	__ops_memory_free(mem_sig);
532 
533 	return 1;
534 }
535 
536 /**
537 \ingroup Core_Keys
538 \brief Initialise __ops_key_t
539 \param keydata Keydata to initialise
540 \param type OPS_PTAG_CT_PUBLIC_KEY or OPS_PTAG_CT_SECRET_KEY
541 */
542 void
543 __ops_keydata_init(__ops_key_t *keydata, const __ops_content_enum type)
544 {
545 	if (keydata->type != OPS_PTAG_CT_RESERVED) {
546 		(void) fprintf(stderr,
547 			"__ops_keydata_init: wrong keydata type\n");
548 	} else if (type != OPS_PTAG_CT_PUBLIC_KEY &&
549 		   type != OPS_PTAG_CT_SECRET_KEY) {
550 		(void) fprintf(stderr, "__ops_keydata_init: wrong type\n");
551 	} else {
552 		keydata->type = type;
553 	}
554 }
555 
556 /* used to point to data during keyring read */
557 typedef struct keyringcb_t {
558 	__ops_keyring_t		*keyring;	/* the keyring we're reading */
559 } keyringcb_t;
560 
561 
562 static __ops_cb_ret_t
563 cb_keyring_read(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
564 {
565 	__ops_keyring_t	*keyring;
566 	__ops_revoke_t	*revocation;
567 	__ops_key_t	*key;
568 	keyringcb_t	*cb;
569 
570 	cb = __ops_callback_arg(cbinfo);
571 	keyring = cb->keyring;
572 	switch (pkt->tag) {
573 	case OPS_PARSER_PTAG:
574 	case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
575 		/* we get these because we didn't prompt */
576 		break;
577 	case OPS_PTAG_CT_SIGNATURE_HEADER:
578 		key = &keyring->keys[keyring->keyc - 1];
579 		EXPAND_ARRAY(key, subsig);
580 		key->subsigs[key->subsigc].uid = key->uidc - 1;
581 		(void) memcpy(&key->subsigs[key->subsigc].sig, &pkt->u.sig,
582 				sizeof(pkt->u.sig));
583 		key->subsigc += 1;
584 		break;
585 	case OPS_PTAG_CT_SIGNATURE:
586 		key = &keyring->keys[keyring->keyc - 1];
587 		EXPAND_ARRAY(key, subsig);
588 		key->subsigs[key->subsigc].uid = key->uidc - 1;
589 		(void) memcpy(&key->subsigs[key->subsigc].sig, &pkt->u.sig,
590 				sizeof(pkt->u.sig));
591 		key->subsigc += 1;
592 		break;
593 	case OPS_PTAG_CT_TRUST:
594 		key = &keyring->keys[keyring->keyc - 1];
595 		key->subsigs[key->subsigc - 1].trustlevel = pkt->u.ss_trust.level;
596 		key->subsigs[key->subsigc - 1].trustamount = pkt->u.ss_trust.amount;
597 		break;
598 	case OPS_PTAG_SS_KEY_EXPIRY:
599 		EXPAND_ARRAY(keyring, key);
600 		if (keyring->keyc > 0) {
601 			keyring->keys[keyring->keyc - 1].key.pubkey.duration = pkt->u.ss_time;
602 		}
603 		break;
604 	case OPS_PTAG_SS_ISSUER_KEY_ID:
605 		key = &keyring->keys[keyring->keyc - 1];
606 		(void) memcpy(&key->subsigs[key->subsigc - 1].sig.info.signer_id,
607 			      pkt->u.ss_issuer,
608 			      sizeof(pkt->u.ss_issuer));
609 		key->subsigs[key->subsigc - 1].sig.info.signer_id_set = 1;
610 		break;
611 	case OPS_PTAG_SS_CREATION_TIME:
612 		key = &keyring->keys[keyring->keyc - 1];
613 		key->subsigs[key->subsigc - 1].sig.info.birthtime = pkt->u.ss_time;
614 		key->subsigs[key->subsigc - 1].sig.info.birthtime_set = 1;
615 		break;
616 	case OPS_PTAG_SS_EXPIRATION_TIME:
617 		key = &keyring->keys[keyring->keyc - 1];
618 		key->subsigs[key->subsigc - 1].sig.info.duration = pkt->u.ss_time;
619 		key->subsigs[key->subsigc - 1].sig.info.duration_set = 1;
620 		break;
621 	case OPS_PTAG_SS_PRIMARY_USER_ID:
622 		key = &keyring->keys[keyring->keyc - 1];
623 		key->uid0 = key->uidc - 1;
624 		break;
625 	case OPS_PTAG_SS_REVOCATION_REASON:
626 		key = &keyring->keys[keyring->keyc - 1];
627 		if (key->uidc == 0) {
628 			/* revoke whole key */
629 			key->revoked = 1;
630 			revocation = &key->revocation;
631 		} else {
632 			/* revoke the user id */
633 			EXPAND_ARRAY(key, revoke);
634 			revocation = &key->revokes[key->revokec];
635 			key->revokes[key->revokec].uid = key->uidc - 1;
636 			key->revokec += 1;
637 		}
638 		revocation->code = pkt->u.ss_revocation.code;
639 		revocation->reason = netpgp_strdup(__ops_show_ss_rr_code(pkt->u.ss_revocation.code));
640 		break;
641 	case OPS_PTAG_CT_SIGNATURE_FOOTER:
642 	case OPS_PARSER_ERRCODE:
643 		break;
644 
645 	default:
646 		break;
647 	}
648 
649 	return OPS_RELEASE_MEMORY;
650 }
651 
652 /**
653    \ingroup HighLevel_KeyringRead
654 
655    \brief Reads a keyring from a file
656 
657    \param keyring Pointer to an existing __ops_keyring_t struct
658    \param armour 1 if file is armoured; else 0
659    \param filename Filename of keyring to be read
660 
661    \return __ops 1 if OK; 0 on error
662 
663    \note Keyring struct must already exist.
664 
665    \note Can be used with either a public or secret keyring.
666 
667    \note You must call __ops_keyring_free() after usage to free alloc-ed memory.
668 
669    \note If you call this twice on the same keyring struct, without calling
670    __ops_keyring_free() between these calls, you will introduce a memory leak.
671 
672    \sa __ops_keyring_read_from_mem()
673    \sa __ops_keyring_free()
674 
675 */
676 
677 unsigned
678 __ops_keyring_fileread(__ops_keyring_t *keyring,
679 			const unsigned armour,
680 			const char *filename)
681 {
682 	__ops_stream_t	*stream;
683 	keyringcb_t	 cb;
684 	unsigned	 res = 1;
685 	int		 fd;
686 
687 	(void) memset(&cb, 0x0, sizeof(cb));
688 	cb.keyring = keyring;
689 	stream = __ops_new(sizeof(*stream));
690 
691 	/* add this for the moment, */
692 	/*
693 	 * \todo need to fix the problems with reading signature subpackets
694 	 * later
695 	 */
696 
697 	/* __ops_parse_options(parse,OPS_PTAG_SS_ALL,OPS_PARSE_RAW); */
698 	__ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
699 
700 #ifdef O_BINARY
701 	fd = open(filename, O_RDONLY | O_BINARY);
702 #else
703 	fd = open(filename, O_RDONLY);
704 #endif
705 	if (fd < 0) {
706 		__ops_stream_delete(stream);
707 		perror(filename);
708 		return 0;
709 	}
710 #ifdef USE_MMAP_FOR_FILES
711 	__ops_reader_set_mmap(stream, fd);
712 #else
713 	__ops_reader_set_fd(stream, fd);
714 #endif
715 
716 	__ops_set_callback(stream, cb_keyring_read, &cb);
717 
718 	if (armour) {
719 		__ops_reader_push_dearmour(stream);
720 	}
721 	res = __ops_parse_and_accumulate(keyring, stream);
722 	__ops_print_errors(__ops_stream_get_errors(stream));
723 
724 	if (armour) {
725 		__ops_reader_pop_dearmour(stream);
726 	}
727 
728 	(void)close(fd);
729 
730 	__ops_stream_delete(stream);
731 
732 	return res;
733 }
734 
735 /**
736    \ingroup HighLevel_KeyringRead
737 
738    \brief Reads a keyring from memory
739 
740    \param keyring Pointer to existing __ops_keyring_t struct
741    \param armour 1 if file is armoured; else 0
742    \param mem Pointer to a __ops_memory_t struct containing keyring to be read
743 
744    \return __ops 1 if OK; 0 on error
745 
746    \note Keyring struct must already exist.
747 
748    \note Can be used with either a public or secret keyring.
749 
750    \note You must call __ops_keyring_free() after usage to free alloc-ed memory.
751 
752    \note If you call this twice on the same keyring struct, without calling
753    __ops_keyring_free() between these calls, you will introduce a memory leak.
754 
755    \sa __ops_keyring_fileread
756    \sa __ops_keyring_free
757 */
758 unsigned
759 __ops_keyring_read_from_mem(__ops_io_t *io,
760 				__ops_keyring_t *keyring,
761 				const unsigned armour,
762 				__ops_memory_t *mem)
763 {
764 	__ops_stream_t	*stream;
765 	const unsigned	 noaccum = 0;
766 	keyringcb_t	 cb;
767 	unsigned	 res;
768 
769 	(void) memset(&cb, 0x0, sizeof(cb));
770 	cb.keyring = keyring;
771 	stream = __ops_new(sizeof(*stream));
772 	__ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
773 	__ops_setup_memory_read(io, &stream, mem, &cb, cb_keyring_read,
774 					noaccum);
775 	if (armour) {
776 		__ops_reader_push_dearmour(stream);
777 	}
778 	res = (unsigned)__ops_parse_and_accumulate(keyring, stream);
779 	__ops_print_errors(__ops_stream_get_errors(stream));
780 	if (armour) {
781 		__ops_reader_pop_dearmour(stream);
782 	}
783 	/* don't call teardown_memory_read because memory was passed in */
784 	__ops_stream_delete(stream);
785 	return res;
786 }
787 
788 /**
789    \ingroup HighLevel_KeyringRead
790 
791    \brief Frees keyring's contents (but not keyring itself)
792 
793    \param keyring Keyring whose data is to be freed
794 
795    \note This does not free keyring itself, just the memory alloc-ed in it.
796  */
797 void
798 __ops_keyring_free(__ops_keyring_t *keyring)
799 {
800 	(void)free(keyring->keys);
801 	keyring->keys = NULL;
802 	keyring->keyc = keyring->keyvsize = 0;
803 }
804 
805 /**
806    \ingroup HighLevel_KeyringFind
807 
808    \brief Finds key in keyring from its Key ID
809 
810    \param keyring Keyring to be searched
811    \param keyid ID of required key
812 
813    \return Pointer to key, if found; NULL, if not found
814 
815    \note This returns a pointer to the key inside the given keyring,
816    not a copy.  Do not free it after use.
817 
818 */
819 const __ops_key_t *
820 __ops_getkeybyid(__ops_io_t *io, const __ops_keyring_t *keyring,
821 			   const uint8_t *keyid, unsigned *from)
822 {
823 	for ( ; keyring && *from < keyring->keyc; *from += 1) {
824 		if (__ops_get_debug_level(__FILE__)) {
825 			(void) fprintf(io->errs,
826 				"__ops_getkeybyid: keyring keyid ");
827 			hexdump(io->errs, keyring->keys[*from].key_id, OPS_KEY_ID_SIZE, "");
828 			(void) fprintf(io->errs, ", keyid ");
829 			hexdump(io->errs, keyid, OPS_KEY_ID_SIZE, "");
830 			(void) fprintf(io->errs, "\n");
831 		}
832 		if (memcmp(keyring->keys[*from].key_id, keyid,
833 				OPS_KEY_ID_SIZE) == 0) {
834 			return &keyring->keys[*from];
835 		}
836 		if (memcmp(&keyring->keys[*from].key_id[OPS_KEY_ID_SIZE / 2],
837 				keyid, OPS_KEY_ID_SIZE / 2) == 0) {
838 			return &keyring->keys[*from];
839 		}
840 	}
841 	return NULL;
842 }
843 
844 /* convert a string keyid into a binary keyid */
845 static void
846 str2keyid(const char *userid, uint8_t *keyid, size_t len)
847 {
848 	static const char	*uppers = "0123456789ABCDEF";
849 	static const char	*lowers = "0123456789abcdef";
850 	const char		*hi;
851 	const char		*lo;
852 	uint8_t			 hichar;
853 	uint8_t			 lochar;
854 	size_t			 j;
855 	int			 i;
856 
857 	for (i = j = 0 ; j < len && userid[i] && userid[i + 1] ; i += 2, j++) {
858 		if ((hi = strchr(uppers, userid[i])) == NULL) {
859 			if ((hi = strchr(lowers, userid[i])) == NULL) {
860 				break;
861 			}
862 			hichar = (hi - lowers);
863 		} else {
864 			hichar = (hi - uppers);
865 		}
866 		if ((lo = strchr(uppers, userid[i + 1])) == NULL) {
867 			if ((lo = strchr(lowers, userid[i + 1])) == NULL) {
868 				break;
869 			}
870 			lochar = (lo - lowers);
871 		} else {
872 			lochar = (lo - uppers);
873 		}
874 		keyid[j] = (hichar << 4) | (lochar);
875 	}
876 	keyid[j] = 0x0;
877 }
878 
879 /* return the next key which matches, starting searching at *from */
880 static const __ops_key_t *
881 getkeybyname(__ops_io_t *io,
882 			const __ops_keyring_t *keyring,
883 			const char *name,
884 			unsigned *from)
885 {
886 	const __ops_key_t	*kp;
887 	uint8_t			**uidp;
888 	unsigned    	 	 i = 0;
889 	__ops_key_t		*keyp;
890 	unsigned		 savedstart;
891 	regex_t			 r;
892 	uint8_t		 	 keyid[OPS_KEY_ID_SIZE + 1];
893 	size_t          	 len;
894 
895 	if (!keyring) {
896 		return NULL;
897 	}
898 	len = strlen(name);
899 	if (__ops_get_debug_level(__FILE__)) {
900 		(void) fprintf(io->outs, "[%u] name '%s', len %zu\n",
901 			*from, name, len);
902 	}
903 	/* first try name as a keyid */
904 	(void) memset(keyid, 0x0, sizeof(keyid));
905 	str2keyid(name, keyid, sizeof(keyid));
906 	if (__ops_get_debug_level(__FILE__)) {
907 		hexdump(io->outs, keyid, 4, "");
908 	}
909 	savedstart = *from;
910 	if ((kp = __ops_getkeybyid(io, keyring, keyid, from)) != NULL) {
911 		return kp;
912 	}
913 	*from = savedstart;
914 	if (__ops_get_debug_level(__FILE__)) {
915 		(void) fprintf(io->outs, "regex match '%s' from %u\n",
916 			name, *from);
917 	}
918 	/* match on full name or email address as a NOSUB, ICASE regexp */
919 	(void) regcomp(&r, name, REG_EXTENDED | REG_ICASE);
920 	for (keyp = &keyring->keys[*from]; *from < keyring->keyc; *from += 1, keyp++) {
921 		uidp = keyp->uids;
922 		for (i = 0 ; i < keyp->uidc; i++, uidp++) {
923 			if (__ops_get_debug_level(__FILE__)) {
924 				(void) fprintf(io->outs,
925 					"keyid \"%s\" len %" PRIsize "u\n",
926 				       (char *) *uidp, len);
927 			}
928 			if (regexec(&r, (char *)*uidp, 0, NULL, 0) == 0) {
929 				regfree(&r);
930 				return keyp;
931 			}
932 		}
933 	}
934 	regfree(&r);
935 	return NULL;
936 }
937 
938 /**
939    \ingroup HighLevel_KeyringFind
940 
941    \brief Finds key from its User ID
942 
943    \param keyring Keyring to be searched
944    \param userid User ID of required key
945 
946    \return Pointer to Key, if found; NULL, if not found
947 
948    \note This returns a pointer to the key inside the keyring, not a
949    copy.  Do not free it.
950 
951 */
952 const __ops_key_t *
953 __ops_getkeybyname(__ops_io_t *io,
954 			const __ops_keyring_t *keyring,
955 			const char *name)
956 {
957 	unsigned	from;
958 
959 	from = 0;
960 	return getkeybyname(io, keyring, name, &from);
961 }
962 
963 const __ops_key_t *
964 __ops_getnextkeybyname(__ops_io_t *io,
965 			const __ops_keyring_t *keyring,
966 			const char *name,
967 			unsigned *n)
968 {
969 	return getkeybyname(io, keyring, name, n);
970 }
971 
972 /**
973    \ingroup HighLevel_KeyringList
974 
975    \brief Prints all keys in keyring to stdout.
976 
977    \param keyring Keyring to use
978 
979    \return none
980 */
981 int
982 __ops_keyring_list(__ops_io_t *io, const __ops_keyring_t *keyring, const int psigs)
983 {
984 	__ops_key_t		*key;
985 	unsigned		 n;
986 
987 	(void) fprintf(io->res, "%u key%s\n", keyring->keyc,
988 		(keyring->keyc == 1) ? "" : "s");
989 	for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) {
990 		if (__ops_is_key_secret(key)) {
991 			__ops_print_keydata(io, keyring, key, "sec",
992 				&key->key.seckey.pubkey, 0);
993 		} else {
994 			__ops_print_keydata(io, keyring, key, "pub", &key->key.pubkey, psigs);
995 		}
996 		(void) fputc('\n', io->res);
997 	}
998 	return 1;
999 }
1000 
1001 
1002 /* this interface isn't right - hook into callback for getting passphrase */
1003 char *
1004 __ops_export_key(__ops_io_t *io, const __ops_key_t *keydata, uint8_t *passphrase)
1005 {
1006 	__ops_output_t	*output;
1007 	__ops_memory_t	*mem;
1008 	char		*cp;
1009 
1010 	__OPS_USED(io);
1011 	__ops_setup_memory_write(&output, &mem, 128);
1012 	if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) {
1013 		__ops_write_xfer_pubkey(output, keydata, 1);
1014 	} else {
1015 		__ops_write_xfer_seckey(output, keydata, passphrase,
1016 					strlen((char *)passphrase), 1);
1017 	}
1018 	cp = netpgp_strdup(__ops_mem_data(mem));
1019 	__ops_teardown_memory_write(output, mem);
1020 	return cp;
1021 }
1022 
1023 /* add a key to a public keyring */
1024 int
1025 __ops_add_to_pubring(__ops_keyring_t *keyring, const __ops_pubkey_t *pubkey)
1026 {
1027 	__ops_key_t	*key;
1028 	time_t		 duration;
1029 
1030 	EXPAND_ARRAY(keyring, key);
1031 	key = &keyring->keys[keyring->keyc++];
1032 	duration = key->key.pubkey.duration;
1033 	(void) memset(key, 0x0, sizeof(*key));
1034 	__ops_keyid(key->key_id, OPS_KEY_ID_SIZE, pubkey);
1035 	__ops_fingerprint(&key->fingerprint, pubkey);
1036 	key->type = OPS_PTAG_CT_PUBLIC_KEY;
1037 	key->key.pubkey = *pubkey;
1038 	key->key.pubkey.duration = duration;
1039 	return 1;
1040 }
1041 
1042 /* add a key to a secret keyring */
1043 int
1044 __ops_add_to_secring(__ops_keyring_t *keyring, const __ops_seckey_t *seckey)
1045 {
1046 	const __ops_pubkey_t	*pubkey;
1047 	__ops_key_t		*key;
1048 
1049 	EXPAND_ARRAY(keyring, key);
1050 	key = &keyring->keys[keyring->keyc++];
1051 	(void) memset(key, 0x0, sizeof(*key));
1052 	pubkey = &seckey->pubkey;
1053 	__ops_keyid(key->key_id, OPS_KEY_ID_SIZE, pubkey);
1054 	__ops_fingerprint(&key->fingerprint, pubkey);
1055 	key->type = OPS_PTAG_CT_SECRET_KEY;
1056 	key->key.seckey = *seckey;
1057 	return 1;
1058 }
1059 
1060 /* append one keyring to another */
1061 int
1062 __ops_append_keyring(__ops_keyring_t *keyring, __ops_keyring_t *newring)
1063 {
1064 	unsigned	i;
1065 
1066 	for (i = 0 ; i < newring->keyc ; i++) {
1067 		EXPAND_ARRAY(keyring, key);
1068 		(void) memcpy(&keyring->keys[keyring->keyc], &newring->keys[i],
1069 				sizeof(newring->keys[i]));
1070 		keyring->keyc += 1;
1071 	}
1072 	return 1;
1073 }
1074