keyring.c revision 1.33
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*/
119void
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
158const __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
172unsigned
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
189const __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 */
215void
216__ops_forget(void *vp, unsigned size)
217{
218	(void) memset(vp, 0x0, size);
219}
220
221typedef struct {
222	FILE			*passfp;
223	const __ops_key_t	*key;
224	char			*passphrase;
225	__ops_seckey_t		*seckey;
226} decrypt_t;
227
228static __ops_cb_ret_t
229decrypt_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*/
325void
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*/
337const 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*/
349unsigned
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*/
362const 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
375unsigned
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*/
398static __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*/
423static __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
458void 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*/
488unsigned
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*/
543void
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 */
558typedef struct keyringcb_t {
559	__ops_keyring_t		*keyring;	/* the keyring we're reading */
560} keyringcb_t;
561
562
563static __ops_cb_ret_t
564cb_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
678unsigned
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*/
759unsigned
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 */
798void
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 */
807void
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*/
831const __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 */
858static void
859str2keyid(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 */
893static const __ops_key_t *
894getkeybyname(__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*/
970const __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
981const __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*/
999int
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 */
1021char *
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 */
1042int
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 */
1061int
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 */
1079int
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