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