xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/keyring.c (revision 3816d47b2c42fcd6e549e3407f842a5b1a1d23ad)
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.26 2009/12/14 23:29:56 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 	const __ops_key_t	*key;
223 	char			*passphrase;
224 	__ops_seckey_t		*seckey;
225 } decrypt_t;
226 
227 static __ops_cb_ret_t
228 decrypt_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
229 {
230 	const __ops_contents_t	*content = &pkt->u;
231 	decrypt_t		*decrypt;
232 	char			 pass[MAX_PASSPHRASE_LENGTH];
233 
234 	decrypt = __ops_callback_arg(cbinfo);
235 	switch (pkt->tag) {
236 	case OPS_PARSER_PTAG:
237 	case OPS_PTAG_CT_USER_ID:
238 	case OPS_PTAG_CT_SIGNATURE:
239 	case OPS_PTAG_CT_SIGNATURE_HEADER:
240 	case OPS_PTAG_CT_SIGNATURE_FOOTER:
241 	case OPS_PTAG_CT_TRUST:
242 		break;
243 
244 	case OPS_GET_PASSPHRASE:
245 		(void) __ops_getpassphrase(NULL, pass, sizeof(pass));
246 		*content->skey_passphrase.passphrase = strdup(pass);
247 		return OPS_KEEP_MEMORY;
248 
249 	case OPS_PARSER_ERRCODE:
250 		switch (content->errcode.errcode) {
251 		case OPS_E_P_MPI_FORMAT_ERROR:
252 			/* Generally this means a bad passphrase */
253 			fprintf(stderr, "Bad passphrase!\n");
254 			return OPS_RELEASE_MEMORY;
255 
256 		case OPS_E_P_PACKET_CONSUMED:
257 			/* And this is because of an error we've accepted */
258 			return OPS_RELEASE_MEMORY;
259 		default:
260 			break;
261 		}
262 		(void) fprintf(stderr, "parse error: %s\n",
263 				__ops_errcode(content->errcode.errcode));
264 		return OPS_FINISHED;
265 
266 	case OPS_PARSER_ERROR:
267 		fprintf(stderr, "parse error: %s\n", content->error.error);
268 		return OPS_FINISHED;
269 
270 	case OPS_PTAG_CT_SECRET_KEY:
271 		if ((decrypt->seckey = calloc(1, sizeof(*decrypt->seckey))) == NULL) {
272 			(void) fprintf(stderr, "decrypt_cb: bad alloc\n");
273 			return OPS_FINISHED;
274 		}
275 		decrypt->seckey->checkhash = calloc(1, OPS_CHECKHASH_SIZE);
276 		*decrypt->seckey = content->seckey;
277 		return OPS_KEEP_MEMORY;
278 
279 	case OPS_PARSER_PACKET_END:
280 		/* nothing to do */
281 		break;
282 
283 	default:
284 		fprintf(stderr, "Unexpected tag %d (0x%x)\n", pkt->tag,
285 			pkt->tag);
286 		return OPS_FINISHED;
287 	}
288 
289 	return OPS_RELEASE_MEMORY;
290 }
291 
292 /**
293 \ingroup Core_Keys
294 \brief Decrypts secret key from given keydata with given passphrase
295 \param key Key from which to get secret key
296 \param passphrase Passphrase to use to decrypt secret key
297 \return secret key
298 */
299 __ops_seckey_t *
300 __ops_decrypt_seckey(const __ops_key_t *key)
301 {
302 	__ops_stream_t	*stream;
303 	const int	 printerrors = 1;
304 	decrypt_t	 decrypt;
305 
306 	(void) memset(&decrypt, 0x0, sizeof(decrypt));
307 	decrypt.key = key;
308 	stream = __ops_new(sizeof(*stream));
309 	__ops_keydata_reader_set(stream, key);
310 	__ops_set_callback(stream, decrypt_cb, &decrypt);
311 	stream->readinfo.accumulate = 1;
312 	__ops_parse(stream, !printerrors);
313 	return decrypt.seckey;
314 }
315 
316 /**
317 \ingroup Core_Keys
318 \brief Set secret key in content
319 \param content Content to be set
320 \param key Keydata to get secret key from
321 */
322 void
323 __ops_set_seckey(__ops_contents_t *cont, const __ops_key_t *key)
324 {
325 	*cont->get_seckey.seckey = &key->key.seckey;
326 }
327 
328 /**
329 \ingroup Core_Keys
330 \brief Get Key ID from keydata
331 \param key Keydata to get Key ID from
332 \return Pointer to Key ID inside keydata
333 */
334 const unsigned char *
335 __ops_get_key_id(const __ops_key_t *key)
336 {
337 	return key->key_id;
338 }
339 
340 /**
341 \ingroup Core_Keys
342 \brief How many User IDs in this key?
343 \param key Keydata to check
344 \return Num of user ids
345 */
346 unsigned
347 __ops_get_userid_count(const __ops_key_t *key)
348 {
349 	return key->uidc;
350 }
351 
352 /**
353 \ingroup Core_Keys
354 \brief Get indexed user id from key
355 \param key Key to get user id from
356 \param index Which key to get
357 \return Pointer to requested user id
358 */
359 const unsigned char *
360 __ops_get_userid(const __ops_key_t *key, unsigned subscript)
361 {
362 	return key->uids[subscript].userid;
363 }
364 
365 /**
366    \ingroup HighLevel_Supported
367    \brief Checks whether key's algorithm and type are supported by OpenPGP::SDK
368    \param keydata Key to be checked
369    \return 1 if key algorithm and type are supported by OpenPGP::SDK; 0 if not
370 */
371 
372 unsigned
373 __ops_is_key_supported(const __ops_key_t *key)
374 {
375 	if (key->type == OPS_PTAG_CT_PUBLIC_KEY) {
376 		if (key->key.pubkey.alg == OPS_PKA_RSA) {
377 			return 1;
378 		}
379 	} else if (key->type == OPS_PTAG_CT_PUBLIC_KEY) {
380 		if (key->key.pubkey.alg == OPS_PKA_DSA) {
381 			return 1;
382 		}
383 	}
384 	return 0;
385 }
386 
387 /* \todo check where userid pointers are copied */
388 /**
389 \ingroup Core_Keys
390 \brief Copy user id, including contents
391 \param dst Destination User ID
392 \param src Source User ID
393 \note If dst already has a userid, it will be freed.
394 */
395 static __ops_userid_t *
396 __ops_copy_userid(__ops_userid_t *dst, const __ops_userid_t *src)
397 {
398 	size_t          len = strlen((char *) src->userid);
399 
400 	if (dst->userid) {
401 		free(dst->userid);
402 	}
403 	if ((dst->userid = calloc(1, len + 1)) == NULL) {
404 		(void) fprintf(stderr, "__ops_copy_userid: bad alloc\n");
405 	} else {
406 		(void) memcpy(dst->userid, src->userid, len);
407 	}
408 	return dst;
409 }
410 
411 /* \todo check where pkt pointers are copied */
412 /**
413 \ingroup Core_Keys
414 \brief Copy packet, including contents
415 \param dst Destination packet
416 \param src Source packet
417 \note If dst already has a packet, it will be freed.
418 */
419 static __ops_subpacket_t *
420 __ops_copy_packet(__ops_subpacket_t *dst, const __ops_subpacket_t *src)
421 {
422 	if (dst->raw) {
423 		free(dst->raw);
424 	}
425 	if ((dst->raw = calloc(1, src->length)) == NULL) {
426 		(void) fprintf(stderr, "__ops_copy_packet: bad alloc\n");
427 	} else {
428 		dst->length = src->length;
429 		(void) memcpy(dst->raw, src->raw, src->length);
430 	}
431 	return dst;
432 }
433 
434 /**
435 \ingroup Core_Keys
436 \brief Add User ID to key
437 \param key Key to which to add User ID
438 \param userid User ID to add
439 \return Pointer to new User ID
440 */
441 __ops_userid_t  *
442 __ops_add_userid(__ops_key_t *key, const __ops_userid_t *userid)
443 {
444 	__ops_userid_t  *uidp;
445 
446 	EXPAND_ARRAY(key, uid);
447 	/* initialise new entry in array */
448 	uidp = &key->uids[key->uidc++];
449 	uidp->userid = NULL;
450 	/* now copy it */
451 	return __ops_copy_userid(uidp, userid);
452 }
453 
454 /**
455 \ingroup Core_Keys
456 \brief Add packet to key
457 \param keydata Key to which to add packet
458 \param packet Packet to add
459 \return Pointer to new packet
460 */
461 __ops_subpacket_t   *
462 __ops_add_subpacket(__ops_key_t *keydata, const __ops_subpacket_t *packet)
463 {
464 	__ops_subpacket_t   *subpktp;
465 
466 	EXPAND_ARRAY(keydata, packet);
467 
468 	/* initialise new entry in array */
469 	subpktp = &keydata->packets[keydata->packetc++];
470 	subpktp->length = 0;
471 	subpktp->raw = NULL;
472 	/* now copy it */
473 	return __ops_copy_packet(subpktp, packet);
474 }
475 
476 /**
477 \ingroup Core_Keys
478 \brief Add signed User ID to key
479 \param keydata Key to which to add signed User ID
480 \param userid User ID to add
481 \param sigpacket Packet to add
482 */
483 void
484 __ops_add_signed_userid(__ops_key_t *keydata,
485 		const __ops_userid_t *userid,
486 		const __ops_subpacket_t *sigpacket)
487 {
488 	__ops_subpacket_t	*pkt;
489 	__ops_userid_t		*uid;
490 
491 	uid = __ops_add_userid(keydata, userid);
492 	pkt = __ops_add_subpacket(keydata, sigpacket);
493 
494 	/*
495          * add entry in sigs array to link the userid and sigpacket
496 	 * and add ptr to it from the sigs array */
497 	EXPAND_ARRAY(keydata, sig);
498 
499 	/**setup new entry in array */
500 	keydata->sigs[keydata->sigc].userid = uid;
501 	keydata->sigs[keydata->sigc].packet = pkt;
502 
503 	keydata->sigc++;
504 }
505 
506 /**
507 \ingroup Core_Keys
508 \brief Add selfsigned User ID to key
509 \param keydata Key to which to add user ID
510 \param userid Self-signed User ID to add
511 \return 1 if OK; else 0
512 */
513 unsigned
514 __ops_add_selfsigned_userid(__ops_key_t *keydata, __ops_userid_t *userid)
515 {
516 	__ops_create_sig_t	*sig;
517 	__ops_subpacket_t	 sigpacket;
518 	__ops_memory_t		*mem_userid = NULL;
519 	__ops_output_t		*useridoutput = NULL;
520 	__ops_memory_t		*mem_sig = NULL;
521 	__ops_output_t		*sigoutput = NULL;
522 
523 	/*
524          * create signature packet for this userid
525          */
526 
527 	/* create userid pkt */
528 	__ops_setup_memory_write(&useridoutput, &mem_userid, 128);
529 	__ops_write_struct_userid(useridoutput, userid);
530 
531 	/* create sig for this pkt */
532 	sig = __ops_create_sig_new();
533 	__ops_sig_start_key_sig(sig, &keydata->key.seckey.pubkey, userid,
534 					OPS_CERT_POSITIVE);
535 	__ops_add_birthtime(sig, time(NULL));
536 	__ops_add_issuer_keyid(sig, keydata->key_id);
537 	__ops_add_primary_userid(sig, 1);
538 	__ops_end_hashed_subpkts(sig);
539 
540 	__ops_setup_memory_write(&sigoutput, &mem_sig, 128);
541 	__ops_write_sig(sigoutput, sig, &keydata->key.seckey.pubkey,
542 				&keydata->key.seckey);
543 
544 	/* add this packet to keydata */
545 	sigpacket.length = __ops_mem_len(mem_sig);
546 	sigpacket.raw = __ops_mem_data(mem_sig);
547 
548 	/* add userid to keydata */
549 	__ops_add_signed_userid(keydata, userid, &sigpacket);
550 
551 	/* cleanup */
552 	__ops_create_sig_delete(sig);
553 	__ops_output_delete(useridoutput);
554 	__ops_output_delete(sigoutput);
555 	__ops_memory_free(mem_userid);
556 	__ops_memory_free(mem_sig);
557 
558 	return 1;
559 }
560 
561 /**
562 \ingroup Core_Keys
563 \brief Initialise __ops_key_t
564 \param keydata Keydata to initialise
565 \param type OPS_PTAG_CT_PUBLIC_KEY or OPS_PTAG_CT_SECRET_KEY
566 */
567 void
568 __ops_keydata_init(__ops_key_t *keydata, const __ops_content_tag_t type)
569 {
570 	if (keydata->type != OPS_PTAG_CT_RESERVED) {
571 		(void) fprintf(stderr,
572 			"__ops_keydata_init: wrong keydata type\n");
573 	} else if (type != OPS_PTAG_CT_PUBLIC_KEY &&
574 		   type != OPS_PTAG_CT_SECRET_KEY) {
575 		(void) fprintf(stderr, "__ops_keydata_init: wrong type\n");
576 	} else {
577 		keydata->type = type;
578 	}
579 }
580 
581 
582 static __ops_cb_ret_t
583 cb_keyring_read(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
584 {
585 	__OPS_USED(cbinfo);
586 
587 	switch (pkt->tag) {
588 	case OPS_PARSER_PTAG:
589 	case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:	/* we get these because we
590 						 * didn't prompt */
591 	case OPS_PTAG_CT_SIGNATURE_HEADER:
592 	case OPS_PTAG_CT_SIGNATURE_FOOTER:
593 	case OPS_PTAG_CT_SIGNATURE:
594 	case OPS_PTAG_CT_TRUST:
595 	case OPS_PARSER_ERRCODE:
596 		break;
597 
598 	default:
599 		break;
600 	}
601 
602 	return OPS_RELEASE_MEMORY;
603 }
604 
605 /**
606    \ingroup HighLevel_KeyringRead
607 
608    \brief Reads a keyring from a file
609 
610    \param keyring Pointer to an existing __ops_keyring_t struct
611    \param armour 1 if file is armoured; else 0
612    \param filename Filename of keyring to be read
613 
614    \return __ops 1 if OK; 0 on error
615 
616    \note Keyring struct must already exist.
617 
618    \note Can be used with either a public or secret keyring.
619 
620    \note You must call __ops_keyring_free() after usage to free alloc-ed memory.
621 
622    \note If you call this twice on the same keyring struct, without calling
623    __ops_keyring_free() between these calls, you will introduce a memory leak.
624 
625    \sa __ops_keyring_read_from_mem()
626    \sa __ops_keyring_free()
627 
628 */
629 
630 unsigned
631 __ops_keyring_fileread(__ops_keyring_t *keyring,
632 			const unsigned armour,
633 			const char *filename)
634 {
635 	__ops_stream_t	*stream;
636 	unsigned		 res = 1;
637 	int			 fd;
638 
639 	stream = __ops_new(sizeof(*stream));
640 
641 	/* add this for the moment, */
642 	/*
643 	 * \todo need to fix the problems with reading signature subpackets
644 	 * later
645 	 */
646 
647 	/* __ops_parse_options(parse,OPS_PTAG_SS_ALL,OPS_PARSE_RAW); */
648 	__ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
649 
650 #ifdef O_BINARY
651 	fd = open(filename, O_RDONLY | O_BINARY);
652 #else
653 	fd = open(filename, O_RDONLY);
654 #endif
655 	if (fd < 0) {
656 		__ops_stream_delete(stream);
657 		perror(filename);
658 		return 0;
659 	}
660 #ifdef USE_MMAP_FOR_FILES
661 	__ops_reader_set_mmap(stream, fd);
662 #else
663 	__ops_reader_set_fd(stream, fd);
664 #endif
665 
666 	__ops_set_callback(stream, cb_keyring_read, NULL);
667 
668 	if (armour) {
669 		__ops_reader_push_dearmour(stream);
670 	}
671 	res = __ops_parse_and_accumulate(keyring, stream);
672 	__ops_print_errors(__ops_stream_get_errors(stream));
673 
674 	if (armour) {
675 		__ops_reader_pop_dearmour(stream);
676 	}
677 
678 	(void)close(fd);
679 
680 	__ops_stream_delete(stream);
681 
682 	return res;
683 }
684 
685 /**
686    \ingroup HighLevel_KeyringRead
687 
688    \brief Reads a keyring from memory
689 
690    \param keyring Pointer to existing __ops_keyring_t struct
691    \param armour 1 if file is armoured; else 0
692    \param mem Pointer to a __ops_memory_t struct containing keyring to be read
693 
694    \return __ops 1 if OK; 0 on error
695 
696    \note Keyring struct must already exist.
697 
698    \note Can be used with either a public or secret keyring.
699 
700    \note You must call __ops_keyring_free() after usage to free alloc-ed memory.
701 
702    \note If you call this twice on the same keyring struct, without calling
703    __ops_keyring_free() between these calls, you will introduce a memory leak.
704 
705    \sa __ops_keyring_fileread
706    \sa __ops_keyring_free
707 */
708 unsigned
709 __ops_keyring_read_from_mem(__ops_io_t *io,
710 				__ops_keyring_t *keyring,
711 				const unsigned armour,
712 				__ops_memory_t *mem)
713 {
714 	__ops_stream_t	*stream;
715 	const unsigned	 noaccum = 0;
716 	unsigned	 res;
717 
718 	stream = __ops_new(sizeof(*stream));
719 	__ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
720 	__ops_setup_memory_read(io, &stream, mem, NULL, cb_keyring_read,
721 					noaccum);
722 	if (armour) {
723 		__ops_reader_push_dearmour(stream);
724 	}
725 	res = (unsigned)__ops_parse_and_accumulate(keyring, stream);
726 	__ops_print_errors(__ops_stream_get_errors(stream));
727 	if (armour) {
728 		__ops_reader_pop_dearmour(stream);
729 	}
730 	/* don't call teardown_memory_read because memory was passed in */
731 	__ops_stream_delete(stream);
732 	return res;
733 }
734 
735 /**
736    \ingroup HighLevel_KeyringRead
737 
738    \brief Frees keyring's contents (but not keyring itself)
739 
740    \param keyring Keyring whose data is to be freed
741 
742    \note This does not free keyring itself, just the memory alloc-ed in it.
743  */
744 void
745 __ops_keyring_free(__ops_keyring_t *keyring)
746 {
747 	(void)free(keyring->keys);
748 	keyring->keys = NULL;
749 	keyring->keyc = keyring->keyvsize = 0;
750 }
751 
752 /**
753    \ingroup HighLevel_KeyringFind
754 
755    \brief Finds key in keyring from its Key ID
756 
757    \param keyring Keyring to be searched
758    \param keyid ID of required key
759 
760    \return Pointer to key, if found; NULL, if not found
761 
762    \note This returns a pointer to the key inside the given keyring,
763    not a copy.  Do not free it after use.
764 
765 */
766 const __ops_key_t *
767 __ops_getkeybyid(__ops_io_t *io, const __ops_keyring_t *keyring,
768 			   const unsigned char *keyid, unsigned *from)
769 {
770 	for ( ; keyring && *from < keyring->keyc; *from += 1) {
771 		if (__ops_get_debug_level(__FILE__)) {
772 			int	i;
773 
774 			(void) fprintf(io->errs,
775 				"__ops_getkeybyid: keyring keyid ");
776 			for (i = 0 ; i < OPS_KEY_ID_SIZE ; i++) {
777 				(void) fprintf(io->errs, "%02x",
778 					keyring->keys[*from].key_id[i]);
779 			}
780 			(void) fprintf(io->errs, ", keyid ");
781 			for (i = 0 ; i < OPS_KEY_ID_SIZE ; i++) {
782 				(void) fprintf(io->errs, "%02x", keyid[i]);
783 			}
784 			(void) fprintf(io->errs, "\n");
785 		}
786 		if (memcmp(keyring->keys[*from].key_id, keyid,
787 				OPS_KEY_ID_SIZE) == 0) {
788 			return &keyring->keys[*from];
789 		}
790 		if (memcmp(&keyring->keys[*from].key_id[OPS_KEY_ID_SIZE / 2],
791 				keyid, OPS_KEY_ID_SIZE / 2) == 0) {
792 			return &keyring->keys[*from];
793 		}
794 	}
795 	return NULL;
796 }
797 
798 /* convert a string keyid into a binary keyid */
799 static void
800 str2keyid(const char *userid, unsigned char *keyid, size_t len)
801 {
802 	static const char	*uppers = "0123456789ABCDEF";
803 	static const char	*lowers = "0123456789abcdef";
804 	unsigned char		 hichar;
805 	unsigned char		 lochar;
806 	size_t			 j;
807 	const char		*hi;
808 	const char		*lo;
809 	int			 i;
810 
811 	for (i = j = 0 ; j < len && userid[i] && userid[i + 1] ; i += 2, j++) {
812 		if ((hi = strchr(uppers, userid[i])) == NULL) {
813 			if ((hi = strchr(lowers, userid[i])) == NULL) {
814 				break;
815 			}
816 			hichar = (hi - lowers);
817 		} else {
818 			hichar = (hi - uppers);
819 		}
820 		if ((lo = strchr(uppers, userid[i + 1])) == NULL) {
821 			if ((lo = strchr(lowers, userid[i + 1])) == NULL) {
822 				break;
823 			}
824 			lochar = (lo - lowers);
825 		} else {
826 			lochar = (lo - uppers);
827 		}
828 		keyid[j] = (hichar << 4) | (lochar);
829 	}
830 	keyid[j] = 0x0;
831 }
832 
833 /* return the next key which matches, starting searching at *from */
834 static const __ops_key_t *
835 getkeybyname(__ops_io_t *io,
836 			const __ops_keyring_t *keyring,
837 			const char *name,
838 			unsigned *from)
839 {
840 	const __ops_key_t	*kp;
841 	__ops_key_t		*keyp;
842 	__ops_userid_t		*uidp;
843 	unsigned char		 keyid[OPS_KEY_ID_SIZE + 1];
844 	unsigned int    	 i = 0;
845 	unsigned		 savedstart;
846 	regex_t			 r;
847 	size_t          	 len;
848 
849 	if (!keyring) {
850 		return NULL;
851 	}
852 	len = strlen(name);
853 	if (__ops_get_debug_level(__FILE__)) {
854 		(void) fprintf(io->outs, "[%u] name '%s', len %zu\n",
855 			*from, name, len);
856 	}
857 	/* first try name as a keyid */
858 	(void) memset(keyid, 0x0, sizeof(keyid));
859 	str2keyid(name, keyid, sizeof(keyid));
860 	if (__ops_get_debug_level(__FILE__)) {
861 		(void) fprintf(io->outs,
862 			"name \"%s\", keyid %02x%02x%02x%02x\n",
863 			name,
864 			keyid[0], keyid[1], keyid[2], keyid[3]);
865 	}
866 	savedstart = *from;
867 	if ((kp = __ops_getkeybyid(io, keyring, keyid, from)) != NULL) {
868 		return kp;
869 	}
870 	*from = savedstart;
871 	if (__ops_get_debug_level(__FILE__)) {
872 		(void) fprintf(io->outs, "regex match '%s' from %u\n",
873 			name, *from);
874 	}
875 	/* match on full name or email address as a NOSUB, ICASE regexp */
876 	(void) regcomp(&r, name, REG_EXTENDED | REG_ICASE);
877 	for (keyp = &keyring->keys[*from]; *from < keyring->keyc; *from += 1, keyp++) {
878 		uidp = keyp->uids;
879 		for (i = 0 ; i < keyp->uidc; i++, uidp++) {
880 			if (__ops_get_debug_level(__FILE__)) {
881 				(void) fprintf(io->outs,
882 					"keyid \"%s\" len %"
883 					PRIsize "u, keyid[len] '%c'\n",
884 				       (char *) uidp->userid,
885 				       len, uidp->userid[len]);
886 			}
887 			if (regexec(&r, (char *)uidp->userid, 0, NULL, 0) == 0) {
888 				regfree(&r);
889 				return keyp;
890 			}
891 		}
892 	}
893 	regfree(&r);
894 	return NULL;
895 }
896 
897 /**
898    \ingroup HighLevel_KeyringFind
899 
900    \brief Finds key from its User ID
901 
902    \param keyring Keyring to be searched
903    \param userid User ID of required key
904 
905    \return Pointer to Key, if found; NULL, if not found
906 
907    \note This returns a pointer to the key inside the keyring, not a
908    copy.  Do not free it.
909 
910 */
911 const __ops_key_t *
912 __ops_getkeybyname(__ops_io_t *io,
913 			const __ops_keyring_t *keyring,
914 			const char *name)
915 {
916 	unsigned	from;
917 
918 	from = 0;
919 	return getkeybyname(io, keyring, name, &from);
920 }
921 
922 const __ops_key_t *
923 __ops_getnextkeybyname(__ops_io_t *io,
924 			const __ops_keyring_t *keyring,
925 			const char *name,
926 			unsigned *n)
927 {
928 	return getkeybyname(io, keyring, name, n);
929 }
930 
931 /**
932    \ingroup HighLevel_KeyringList
933 
934    \brief Prints all keys in keyring to stdout.
935 
936    \param keyring Keyring to use
937 
938    \return none
939 */
940 int
941 __ops_keyring_list(__ops_io_t *io, const __ops_keyring_t *keyring)
942 {
943 	__ops_key_t		*key;
944 	unsigned		 n;
945 
946 	(void) fprintf(io->res, "%u key%s\n", keyring->keyc,
947 		(keyring->keyc == 1) ? "" : "s");
948 	for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) {
949 		if (__ops_is_key_secret(key)) {
950 			__ops_print_keydata(io, key, "sec",
951 				&key->key.seckey.pubkey);
952 		} else {
953 			__ops_print_keydata(io, key, "pub", &key->key.pubkey);
954 		}
955 		(void) fputc('\n', io->res);
956 	}
957 	return 1;
958 }
959 
960 /* this interface isn't right - hook into callback for getting passphrase */
961 int
962 __ops_export_key(const __ops_key_t *keydata, unsigned char *passphrase)
963 {
964 	__ops_output_t	*output;
965 	__ops_memory_t		*mem;
966 
967 	__ops_setup_memory_write(&output, &mem, 128);
968 	if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) {
969 		__ops_write_xfer_pubkey(output, keydata, 1);
970 	} else {
971 		__ops_write_xfer_seckey(output, keydata, passphrase,
972 					strlen((char *)passphrase), 1);
973 	}
974 	printf("%s", (char *) __ops_mem_data(mem));
975 	__ops_teardown_memory_write(output, mem);
976 	return 1;
977 }
978 
979 /* add a key to a public keyring */
980 int
981 __ops_add_to_pubring(__ops_keyring_t *keyring, const __ops_pubkey_t *pubkey)
982 {
983 	__ops_key_t	*key;
984 
985 	EXPAND_ARRAY(keyring, key);
986 	key = &keyring->keys[keyring->keyc++];
987 	(void) memset(key, 0x0, sizeof(*key));
988 	__ops_keyid(key->key_id, OPS_KEY_ID_SIZE, pubkey);
989 	__ops_fingerprint(&key->fingerprint, pubkey);
990 	key->type = OPS_PTAG_CT_PUBLIC_KEY;
991 	key->key.pubkey = *pubkey;
992 	return 1;
993 }
994 
995 /* add a key to a secret keyring */
996 int
997 __ops_add_to_secring(__ops_keyring_t *keyring, const __ops_seckey_t *seckey)
998 {
999 	const __ops_pubkey_t	*pubkey;
1000 	__ops_key_t		*key;
1001 
1002 	EXPAND_ARRAY(keyring, key);
1003 	key = &keyring->keys[keyring->keyc++];
1004 	(void) memset(key, 0x0, sizeof(*key));
1005 	pubkey = &seckey->pubkey;
1006 	__ops_keyid(key->key_id, OPS_KEY_ID_SIZE, pubkey);
1007 	__ops_fingerprint(&key->fingerprint, pubkey);
1008 	key->type = OPS_PTAG_CT_SECRET_KEY;
1009 	key->key.seckey = *seckey;
1010 	return 1;
1011 }
1012