xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/keyring.c (revision 07cd2d7f4155df9bb93647120ce3750eec13203b)
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.33 2010/03/13 23:30:41 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 "netpgpdigest.h"
90 
91 
92 
93 /**
94    \ingroup HighLevel_Keyring
95 
96    \brief Creates a new __ops_key_t struct
97 
98    \return A new __ops_key_t struct, initialised to zero.
99 
100    \note The returned __ops_key_t struct must be freed after use with __ops_keydata_free.
101 */
102 
103 __ops_key_t  *
104 __ops_keydata_new(void)
105 {
106 	return calloc(1, sizeof(__ops_key_t));
107 }
108 
109 
110 /**
111  \ingroup HighLevel_Keyring
112 
113  \brief Frees keydata and its memory
114 
115  \param keydata Key to be freed.
116 
117  \note This frees the keydata itself, as well as any other memory alloc-ed by it.
118 */
119 void
120 __ops_keydata_free(__ops_key_t *keydata)
121 {
122 	unsigned        n;
123 
124 	for (n = 0; n < keydata->uidc; ++n) {
125 		__ops_userid_free(&keydata->uids[n]);
126 	}
127 	free(keydata->uids);
128 	keydata->uids = NULL;
129 	keydata->uidc = 0;
130 
131 	for (n = 0; n < keydata->packetc; ++n) {
132 		__ops_subpacket_free(&keydata->packets[n]);
133 	}
134 	free(keydata->packets);
135 	keydata->packets = NULL;
136 	keydata->packetc = 0;
137 
138 	if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) {
139 		__ops_pubkey_free(&keydata->key.pubkey);
140 	} else {
141 		__ops_seckey_free(&keydata->key.seckey);
142 	}
143 
144 	free(keydata);
145 }
146 
147 /**
148  \ingroup HighLevel_KeyGeneral
149 
150  \brief Returns the public key in the given keydata.
151  \param keydata
152 
153   \return Pointer to public key
154 
155   \note This is not a copy, do not free it after use.
156 */
157 
158 const __ops_pubkey_t *
159 __ops_get_pubkey(const __ops_key_t *keydata)
160 {
161 	return (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) ?
162 				&keydata->key.pubkey :
163 				&keydata->key.seckey.pubkey;
164 }
165 
166 /**
167 \ingroup HighLevel_KeyGeneral
168 
169 \brief Check whether this is a secret key or not.
170 */
171 
172 unsigned
173 __ops_is_key_secret(const __ops_key_t *data)
174 {
175 	return data->type != OPS_PTAG_CT_PUBLIC_KEY;
176 }
177 
178 /**
179  \ingroup HighLevel_KeyGeneral
180 
181  \brief Returns the secret key in the given keydata.
182 
183  \note This is not a copy, do not free it after use.
184 
185  \note This returns a const.  If you need to be able to write to this
186  pointer, use __ops_get_writable_seckey
187 */
188 
189 const __ops_seckey_t *
190 __ops_get_seckey(const __ops_key_t *data)
191 {
192 	return (data->type == OPS_PTAG_CT_SECRET_KEY) ?
193 				&data->key.seckey : NULL;
194 }
195 
196 /**
197  \ingroup HighLevel_KeyGeneral
198 
199   \brief Returns the secret key in the given keydata.
200 
201   \note This is not a copy, do not free it after use.
202 
203   \note If you do not need to be able to modify this key, there is an
204   equivalent read-only function __ops_get_seckey.
205 */
206 
207 __ops_seckey_t *
208 __ops_get_writable_seckey(__ops_key_t *data)
209 {
210 	return (data->type == OPS_PTAG_CT_SECRET_KEY) ?
211 				&data->key.seckey : NULL;
212 }
213 
214 /* utility function to zero out memory */
215 void
216 __ops_forget(void *vp, unsigned size)
217 {
218 	(void) memset(vp, 0x0, size);
219 }
220 
221 typedef struct {
222 	FILE			*passfp;
223 	const __ops_key_t	*key;
224 	char			*passphrase;
225 	__ops_seckey_t		*seckey;
226 } decrypt_t;
227 
228 static __ops_cb_ret_t
229 decrypt_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
230 {
231 	const __ops_contents_t	*content = &pkt->u;
232 	decrypt_t		*decrypt;
233 	char			 pass[MAX_PASSPHRASE_LENGTH];
234 
235 	decrypt = __ops_callback_arg(cbinfo);
236 	switch (pkt->tag) {
237 	case OPS_PARSER_PTAG:
238 	case OPS_PTAG_CT_USER_ID:
239 	case OPS_PTAG_CT_SIGNATURE:
240 	case OPS_PTAG_CT_SIGNATURE_HEADER:
241 	case OPS_PTAG_CT_SIGNATURE_FOOTER:
242 	case OPS_PTAG_CT_TRUST:
243 		break;
244 
245 	case OPS_GET_PASSPHRASE:
246 		(void) __ops_getpassphrase(decrypt->passfp, pass, sizeof(pass));
247 		*content->skey_passphrase.passphrase = netpgp_strdup(pass);
248 		__ops_forget(pass, sizeof(pass));
249 		return OPS_KEEP_MEMORY;
250 
251 	case OPS_PARSER_ERRCODE:
252 		switch (content->errcode.errcode) {
253 		case OPS_E_P_MPI_FORMAT_ERROR:
254 			/* Generally this means a bad passphrase */
255 			fprintf(stderr, "Bad passphrase!\n");
256 			return OPS_RELEASE_MEMORY;
257 
258 		case OPS_E_P_PACKET_CONSUMED:
259 			/* And this is because of an error we've accepted */
260 			return OPS_RELEASE_MEMORY;
261 		default:
262 			break;
263 		}
264 		(void) fprintf(stderr, "parse error: %s\n",
265 				__ops_errcode(content->errcode.errcode));
266 		return OPS_FINISHED;
267 
268 	case OPS_PARSER_ERROR:
269 		fprintf(stderr, "parse error: %s\n", content->error.error);
270 		return OPS_FINISHED;
271 
272 	case OPS_PTAG_CT_SECRET_KEY:
273 		if ((decrypt->seckey = calloc(1, sizeof(*decrypt->seckey))) == NULL) {
274 			(void) fprintf(stderr, "decrypt_cb: bad alloc\n");
275 			return OPS_FINISHED;
276 		}
277 		decrypt->seckey->checkhash = calloc(1, OPS_CHECKHASH_SIZE);
278 		*decrypt->seckey = content->seckey;
279 		return OPS_KEEP_MEMORY;
280 
281 	case OPS_PARSER_PACKET_END:
282 		/* nothing to do */
283 		break;
284 
285 	default:
286 		fprintf(stderr, "Unexpected tag %d (0x%x)\n", pkt->tag,
287 			pkt->tag);
288 		return OPS_FINISHED;
289 	}
290 
291 	return OPS_RELEASE_MEMORY;
292 }
293 
294 /**
295 \ingroup Core_Keys
296 \brief Decrypts secret key from given keydata with given passphrase
297 \param key Key from which to get secret key
298 \param passphrase Passphrase to use to decrypt secret key
299 \return secret key
300 */
301 __ops_seckey_t *
302 __ops_decrypt_seckey(const __ops_key_t *key, void *passfp)
303 {
304 	__ops_stream_t	*stream;
305 	const int	 printerrors = 1;
306 	decrypt_t	 decrypt;
307 
308 	(void) memset(&decrypt, 0x0, sizeof(decrypt));
309 	decrypt.key = key;
310 	decrypt.passfp = passfp;
311 	stream = __ops_new(sizeof(*stream));
312 	__ops_keydata_reader_set(stream, key);
313 	__ops_set_callback(stream, decrypt_cb, &decrypt);
314 	stream->readinfo.accumulate = 1;
315 	__ops_parse(stream, !printerrors);
316 	return decrypt.seckey;
317 }
318 
319 /**
320 \ingroup Core_Keys
321 \brief Set secret key in content
322 \param content Content to be set
323 \param key Keydata to get secret key from
324 */
325 void
326 __ops_set_seckey(__ops_contents_t *cont, const __ops_key_t *key)
327 {
328 	*cont->get_seckey.seckey = &key->key.seckey;
329 }
330 
331 /**
332 \ingroup Core_Keys
333 \brief Get Key ID from keydata
334 \param key Keydata to get Key ID from
335 \return Pointer to Key ID inside keydata
336 */
337 const uint8_t *
338 __ops_get_key_id(const __ops_key_t *key)
339 {
340 	return key->key_id;
341 }
342 
343 /**
344 \ingroup Core_Keys
345 \brief How many User IDs in this key?
346 \param key Keydata to check
347 \return Num of user ids
348 */
349 unsigned
350 __ops_get_userid_count(const __ops_key_t *key)
351 {
352 	return key->uidc;
353 }
354 
355 /**
356 \ingroup Core_Keys
357 \brief Get indexed user id from key
358 \param key Key to get user id from
359 \param index Which key to get
360 \return Pointer to requested user id
361 */
362 const uint8_t *
363 __ops_get_userid(const __ops_key_t *key, unsigned subscript)
364 {
365 	return key->uids[subscript].userid;
366 }
367 
368 /**
369    \ingroup HighLevel_Supported
370    \brief Checks whether key's algorithm and type are supported by OpenPGP::SDK
371    \param keydata Key to be checked
372    \return 1 if key algorithm and type are supported by OpenPGP::SDK; 0 if not
373 */
374 
375 unsigned
376 __ops_is_key_supported(const __ops_key_t *key)
377 {
378 	if (key->type == OPS_PTAG_CT_PUBLIC_KEY) {
379 		if (key->key.pubkey.alg == OPS_PKA_RSA) {
380 			return 1;
381 		}
382 	} else if (key->type == OPS_PTAG_CT_PUBLIC_KEY) {
383 		if (key->key.pubkey.alg == OPS_PKA_DSA) {
384 			return 1;
385 		}
386 	}
387 	return 0;
388 }
389 
390 /* \todo check where userid pointers are copied */
391 /**
392 \ingroup Core_Keys
393 \brief Copy user id, including contents
394 \param dst Destination User ID
395 \param src Source User ID
396 \note If dst already has a userid, it will be freed.
397 */
398 static __ops_userid_t *
399 __ops_copy_userid(__ops_userid_t *dst, const __ops_userid_t *src)
400 {
401 	size_t          len;
402 
403 	len = strlen((char *) src->userid);
404 	if (dst->userid) {
405 		free(dst->userid);
406 	}
407 	if ((dst->userid = calloc(1, len + 1)) == NULL) {
408 		(void) fprintf(stderr, "__ops_copy_userid: bad alloc\n");
409 	} else {
410 		(void) memcpy(dst->userid, src->userid, len);
411 	}
412 	return dst;
413 }
414 
415 /* \todo check where pkt pointers are copied */
416 /**
417 \ingroup Core_Keys
418 \brief Copy packet, including contents
419 \param dst Destination packet
420 \param src Source packet
421 \note If dst already has a packet, it will be freed.
422 */
423 static __ops_subpacket_t *
424 __ops_copy_packet(__ops_subpacket_t *dst, const __ops_subpacket_t *src)
425 {
426 	if (dst->raw) {
427 		free(dst->raw);
428 	}
429 	if ((dst->raw = calloc(1, src->length)) == NULL) {
430 		(void) fprintf(stderr, "__ops_copy_packet: bad alloc\n");
431 	} else {
432 		dst->length = src->length;
433 		(void) memcpy(dst->raw, src->raw, src->length);
434 	}
435 	return dst;
436 }
437 
438 /**
439 \ingroup Core_Keys
440 \brief Add User ID to key
441 \param key Key to which to add User ID
442 \param userid User ID to add
443 \return Pointer to new User ID
444 */
445 __ops_userid_t  *
446 __ops_add_userid(__ops_key_t *key, const __ops_userid_t *userid)
447 {
448 	__ops_userid_t  *uidp;
449 
450 	EXPAND_ARRAY(key, uid);
451 	/* initialise new entry in array */
452 	uidp = &key->uids[key->uidc++];
453 	uidp->userid = NULL;
454 	/* now copy it */
455 	return __ops_copy_userid(uidp, userid);
456 }
457 
458 void print_packet_hex(const __ops_subpacket_t *pkt);
459 
460 /**
461 \ingroup Core_Keys
462 \brief Add packet to key
463 \param keydata Key to which to add packet
464 \param packet Packet to add
465 \return Pointer to new packet
466 */
467 __ops_subpacket_t   *
468 __ops_add_subpacket(__ops_key_t *keydata, const __ops_subpacket_t *packet)
469 {
470 	__ops_subpacket_t   *subpktp;
471 
472 	EXPAND_ARRAY(keydata, packet);
473 	/* initialise new entry in array */
474 	subpktp = &keydata->packets[keydata->packetc++];
475 	subpktp->length = 0;
476 	subpktp->raw = NULL;
477 	/* now copy it */
478 	return __ops_copy_packet(subpktp, packet);
479 }
480 
481 /**
482 \ingroup Core_Keys
483 \brief Add selfsigned User ID to key
484 \param keydata Key to which to add user ID
485 \param userid Self-signed User ID to add
486 \return 1 if OK; else 0
487 */
488 unsigned
489 __ops_add_selfsigned_userid(__ops_key_t *keydata, __ops_userid_t *userid)
490 {
491 	__ops_create_sig_t	*sig;
492 	__ops_subpacket_t	 sigpacket;
493 	__ops_memory_t		*mem_userid = NULL;
494 	__ops_output_t		*useridoutput = NULL;
495 	__ops_memory_t		*mem_sig = NULL;
496 	__ops_output_t		*sigoutput = NULL;
497 
498 	/*
499          * create signature packet for this userid
500          */
501 
502 	/* create userid pkt */
503 	__ops_setup_memory_write(&useridoutput, &mem_userid, 128);
504 	__ops_write_struct_userid(useridoutput, userid);
505 
506 	/* create sig for this pkt */
507 	sig = __ops_create_sig_new();
508 	__ops_sig_start_key_sig(sig, &keydata->key.seckey.pubkey, userid,
509 					OPS_CERT_POSITIVE);
510 	__ops_add_birthtime(sig, time(NULL));
511 	__ops_add_issuer_keyid(sig, keydata->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, &keydata->key.seckey.pubkey,
517 				&keydata->key.seckey);
518 
519 	/* add this packet to keydata */
520 	sigpacket.length = __ops_mem_len(mem_sig);
521 	sigpacket.raw = __ops_mem_data(mem_sig);
522 
523 	/* add userid to keydata */
524 	(void) __ops_add_userid(keydata, userid);
525 	(void) __ops_add_subpacket(keydata, &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_tag_t 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.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.key_id,
609 			      sizeof(pkt->u.ss_issuer.key_id));
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.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.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 /* simple function to print out a binary keyid */
807 void
808 __ops_pkeyid(FILE *fp, const uint8_t *keyid, size_t size)
809 {
810 	size_t	i;
811 
812 	for (i = 0 ; i < size ; i++) {
813 		(void) fprintf(fp, "%02x", keyid[i]);
814 	}
815 }
816 
817 /**
818    \ingroup HighLevel_KeyringFind
819 
820    \brief Finds key in keyring from its Key ID
821 
822    \param keyring Keyring to be searched
823    \param keyid ID of required key
824 
825    \return Pointer to key, if found; NULL, if not found
826 
827    \note This returns a pointer to the key inside the given keyring,
828    not a copy.  Do not free it after use.
829 
830 */
831 const __ops_key_t *
832 __ops_getkeybyid(__ops_io_t *io, const __ops_keyring_t *keyring,
833 			   const uint8_t *keyid, unsigned *from)
834 {
835 	for ( ; keyring && *from < keyring->keyc; *from += 1) {
836 		if (__ops_get_debug_level(__FILE__)) {
837 			(void) fprintf(io->errs,
838 				"__ops_getkeybyid: keyring keyid ");
839 			__ops_pkeyid(io->errs, keyring->keys[*from].key_id,
840 				OPS_KEY_ID_SIZE);
841 			(void) fprintf(io->errs, ", keyid ");
842 			__ops_pkeyid(io->errs, keyid, OPS_KEY_ID_SIZE);
843 			(void) fprintf(io->errs, "\n");
844 		}
845 		if (memcmp(keyring->keys[*from].key_id, keyid,
846 				OPS_KEY_ID_SIZE) == 0) {
847 			return &keyring->keys[*from];
848 		}
849 		if (memcmp(&keyring->keys[*from].key_id[OPS_KEY_ID_SIZE / 2],
850 				keyid, OPS_KEY_ID_SIZE / 2) == 0) {
851 			return &keyring->keys[*from];
852 		}
853 	}
854 	return NULL;
855 }
856 
857 /* convert a string keyid into a binary keyid */
858 static void
859 str2keyid(const char *userid, uint8_t *keyid, size_t len)
860 {
861 	static const char	*uppers = "0123456789ABCDEF";
862 	static const char	*lowers = "0123456789abcdef";
863 	const char		*hi;
864 	const char		*lo;
865 	uint8_t			 hichar;
866 	uint8_t			 lochar;
867 	size_t			 j;
868 	int			 i;
869 
870 	for (i = j = 0 ; j < len && userid[i] && userid[i + 1] ; i += 2, j++) {
871 		if ((hi = strchr(uppers, userid[i])) == NULL) {
872 			if ((hi = strchr(lowers, userid[i])) == NULL) {
873 				break;
874 			}
875 			hichar = (hi - lowers);
876 		} else {
877 			hichar = (hi - uppers);
878 		}
879 		if ((lo = strchr(uppers, userid[i + 1])) == NULL) {
880 			if ((lo = strchr(lowers, userid[i + 1])) == NULL) {
881 				break;
882 			}
883 			lochar = (lo - lowers);
884 		} else {
885 			lochar = (lo - uppers);
886 		}
887 		keyid[j] = (hichar << 4) | (lochar);
888 	}
889 	keyid[j] = 0x0;
890 }
891 
892 /* return the next key which matches, starting searching at *from */
893 static const __ops_key_t *
894 getkeybyname(__ops_io_t *io,
895 			const __ops_keyring_t *keyring,
896 			const char *name,
897 			unsigned *from)
898 {
899 	const __ops_key_t	*kp;
900 	__ops_userid_t		*uidp;
901 	unsigned    	 i = 0;
902 	__ops_key_t		*keyp;
903 	unsigned		 savedstart;
904 	regex_t			 r;
905 	uint8_t		 	 keyid[OPS_KEY_ID_SIZE + 1];
906 	size_t          	 len;
907 
908 	if (!keyring) {
909 		return NULL;
910 	}
911 	len = strlen(name);
912 	if (__ops_get_debug_level(__FILE__)) {
913 		(void) fprintf(io->outs, "[%u] name '%s', len %zu\n",
914 			*from, name, len);
915 	}
916 	/* first try name as a keyid */
917 	(void) memset(keyid, 0x0, sizeof(keyid));
918 	str2keyid(name, keyid, sizeof(keyid));
919 	if (__ops_get_debug_level(__FILE__)) {
920 		(void) fprintf(io->outs,
921 			"name \"%s\", keyid %02x%02x%02x%02x\n",
922 			name,
923 			keyid[0], keyid[1], keyid[2], keyid[3]);
924 	}
925 	savedstart = *from;
926 	if ((kp = __ops_getkeybyid(io, keyring, keyid, from)) != NULL) {
927 		return kp;
928 	}
929 	*from = savedstart;
930 	if (__ops_get_debug_level(__FILE__)) {
931 		(void) fprintf(io->outs, "regex match '%s' from %u\n",
932 			name, *from);
933 	}
934 	/* match on full name or email address as a NOSUB, ICASE regexp */
935 	(void) regcomp(&r, name, REG_EXTENDED | REG_ICASE);
936 	for (keyp = &keyring->keys[*from]; *from < keyring->keyc; *from += 1, keyp++) {
937 		uidp = keyp->uids;
938 		for (i = 0 ; i < keyp->uidc; i++, uidp++) {
939 			if (__ops_get_debug_level(__FILE__)) {
940 				(void) fprintf(io->outs,
941 					"keyid \"%s\" len %"
942 					PRIsize "u, keyid[len] '%c'\n",
943 				       (char *) uidp->userid,
944 				       len, uidp->userid[len]);
945 			}
946 			if (regexec(&r, (char *)uidp->userid, 0, NULL, 0) == 0) {
947 				regfree(&r);
948 				return keyp;
949 			}
950 		}
951 	}
952 	regfree(&r);
953 	return NULL;
954 }
955 
956 /**
957    \ingroup HighLevel_KeyringFind
958 
959    \brief Finds key from its User ID
960 
961    \param keyring Keyring to be searched
962    \param userid User ID of required key
963 
964    \return Pointer to Key, if found; NULL, if not found
965 
966    \note This returns a pointer to the key inside the keyring, not a
967    copy.  Do not free it.
968 
969 */
970 const __ops_key_t *
971 __ops_getkeybyname(__ops_io_t *io,
972 			const __ops_keyring_t *keyring,
973 			const char *name)
974 {
975 	unsigned	from;
976 
977 	from = 0;
978 	return getkeybyname(io, keyring, name, &from);
979 }
980 
981 const __ops_key_t *
982 __ops_getnextkeybyname(__ops_io_t *io,
983 			const __ops_keyring_t *keyring,
984 			const char *name,
985 			unsigned *n)
986 {
987 	return getkeybyname(io, keyring, name, n);
988 }
989 
990 /**
991    \ingroup HighLevel_KeyringList
992 
993    \brief Prints all keys in keyring to stdout.
994 
995    \param keyring Keyring to use
996 
997    \return none
998 */
999 int
1000 __ops_keyring_list(__ops_io_t *io, const __ops_keyring_t *keyring, const int psigs)
1001 {
1002 	__ops_key_t		*key;
1003 	unsigned		 n;
1004 
1005 	(void) fprintf(io->res, "%u key%s\n", keyring->keyc,
1006 		(keyring->keyc == 1) ? "" : "s");
1007 	for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) {
1008 		if (__ops_is_key_secret(key)) {
1009 			__ops_print_keydata(io, keyring, key, "sec",
1010 				&key->key.seckey.pubkey, 0);
1011 		} else {
1012 			__ops_print_keydata(io, keyring, key, "pub", &key->key.pubkey, psigs);
1013 		}
1014 		(void) fputc('\n', io->res);
1015 	}
1016 	return 1;
1017 }
1018 
1019 
1020 /* this interface isn't right - hook into callback for getting passphrase */
1021 char *
1022 __ops_export_key(__ops_io_t *io, const __ops_key_t *keydata, uint8_t *passphrase)
1023 {
1024 	__ops_output_t	*output;
1025 	__ops_memory_t	*mem;
1026 	char		*cp;
1027 
1028 	__OPS_USED(io);
1029 	__ops_setup_memory_write(&output, &mem, 128);
1030 	if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) {
1031 		__ops_write_xfer_pubkey(output, keydata, 1);
1032 	} else {
1033 		__ops_write_xfer_seckey(output, keydata, passphrase,
1034 					strlen((char *)passphrase), 1);
1035 	}
1036 	cp = netpgp_strdup(__ops_mem_data(mem));
1037 	__ops_teardown_memory_write(output, mem);
1038 	return cp;
1039 }
1040 
1041 /* add a key to a public keyring */
1042 int
1043 __ops_add_to_pubring(__ops_keyring_t *keyring, const __ops_pubkey_t *pubkey)
1044 {
1045 	__ops_key_t	*key;
1046 	time_t		 duration;
1047 
1048 	EXPAND_ARRAY(keyring, key);
1049 	key = &keyring->keys[keyring->keyc++];
1050 	duration = key->key.pubkey.duration;
1051 	(void) memset(key, 0x0, sizeof(*key));
1052 	__ops_keyid(key->key_id, OPS_KEY_ID_SIZE, pubkey);
1053 	__ops_fingerprint(&key->fingerprint, pubkey);
1054 	key->type = OPS_PTAG_CT_PUBLIC_KEY;
1055 	key->key.pubkey = *pubkey;
1056 	key->key.pubkey.duration = duration;
1057 	return 1;
1058 }
1059 
1060 /* add a key to a secret keyring */
1061 int
1062 __ops_add_to_secring(__ops_keyring_t *keyring, const __ops_seckey_t *seckey)
1063 {
1064 	const __ops_pubkey_t	*pubkey;
1065 	__ops_key_t		*key;
1066 
1067 	EXPAND_ARRAY(keyring, key);
1068 	key = &keyring->keys[keyring->keyc++];
1069 	(void) memset(key, 0x0, sizeof(*key));
1070 	pubkey = &seckey->pubkey;
1071 	__ops_keyid(key->key_id, OPS_KEY_ID_SIZE, pubkey);
1072 	__ops_fingerprint(&key->fingerprint, pubkey);
1073 	key->type = OPS_PTAG_CT_SECRET_KEY;
1074 	key->key.seckey = *seckey;
1075 	return 1;
1076 }
1077 
1078 /* append one keyring to another */
1079 int
1080 __ops_append_keyring(__ops_keyring_t *keyring, __ops_keyring_t *newring)
1081 {
1082 	unsigned	i;
1083 
1084 	for (i = 0 ; i < newring->keyc ; i++) {
1085 		EXPAND_ARRAY(keyring, key);
1086 		(void) memcpy(&keyring->keys[keyring->keyc], &newring->keys[i],
1087 				sizeof(newring->keys[i]));
1088 		keyring->keyc += 1;
1089 	}
1090 	return 1;
1091 }
1092