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