xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/keyring.c (revision a26eaed1f0add07c87a0f66f4d46be96bb31e778)
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.60 2022/10/03 05:34:31 rillig 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 pgp_key_t struct
98 
99    \return A new pgp_key_t struct, initialised to zero.
100 
101    \note The returned pgp_key_t struct must be freed after use with pgp_keydata_free.
102 */
103 
104 pgp_key_t  *
pgp_keydata_new(void)105 pgp_keydata_new(void)
106 {
107 	return calloc(1, sizeof(pgp_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 */
120 void
pgp_keydata_free(pgp_key_t * keydata)121 pgp_keydata_free(pgp_key_t *keydata)
122 {
123 	unsigned        n;
124 
125 	for (n = 0; n < keydata->uidc; ++n) {
126 		pgp_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 		pgp_subpacket_free(&keydata->packets[n]);
134 	}
135 	free(keydata->packets);
136 	keydata->packets = NULL;
137 	keydata->packetc = 0;
138 
139 	if (keydata->type == PGP_PTAG_CT_PUBLIC_KEY) {
140 		pgp_pubkey_free(&keydata->key.pubkey);
141 	} else {
142 		pgp_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 
159 const pgp_pubkey_t *
pgp_get_pubkey(const pgp_key_t * keydata)160 pgp_get_pubkey(const pgp_key_t *keydata)
161 {
162 	return (keydata->type == PGP_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 
173 unsigned
pgp_is_key_secret(const pgp_key_t * data)174 pgp_is_key_secret(const pgp_key_t *data)
175 {
176 	return data->type != PGP_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 pgp_get_writable_seckey
188 */
189 
190 const pgp_seckey_t *
pgp_get_seckey(const pgp_key_t * data)191 pgp_get_seckey(const pgp_key_t *data)
192 {
193 	return (data->type == PGP_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 pgp_get_seckey.
206 */
207 
208 pgp_seckey_t *
pgp_get_writable_seckey(pgp_key_t * data)209 pgp_get_writable_seckey(pgp_key_t *data)
210 {
211 	return (data->type == PGP_PTAG_CT_SECRET_KEY) ?
212 				&data->key.seckey : NULL;
213 }
214 
215 /* utility function to zero out memory */
216 void
pgp_forget(void * vp,size_t size)217 pgp_forget(void *vp, size_t size)
218 {
219 	(void) memset(vp, 0x0, size);
220 }
221 
222 typedef struct {
223 	FILE			*passfp;
224 	const pgp_key_t	*key;
225 	char			*passphrase;
226 	pgp_seckey_t		*seckey;
227 } decrypt_t;
228 
229 static pgp_cb_ret_t
decrypt_cb(const pgp_packet_t * pkt,pgp_cbdata_t * cbinfo)230 decrypt_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
231 {
232 	const pgp_contents_t	*content = &pkt->u;
233 	decrypt_t		*decrypt;
234 	char			 pass[MAX_PASSPHRASE_LENGTH];
235 
236 	decrypt = pgp_callback_arg(cbinfo);
237 	switch (pkt->tag) {
238 	case PGP_PARSER_PTAG:
239 	case PGP_PTAG_CT_USER_ID:
240 	case PGP_PTAG_CT_SIGNATURE:
241 	case PGP_PTAG_CT_SIGNATURE_HEADER:
242 	case PGP_PTAG_CT_SIGNATURE_FOOTER:
243 	case PGP_PTAG_CT_TRUST:
244 		break;
245 
246 	case PGP_GET_PASSPHRASE:
247 		if (pgp_getpassphrase(decrypt->passfp, pass, sizeof(pass)) == 0) {
248 			pass[0] = '\0';
249 		}
250 		*content->skey_passphrase.passphrase = netpgp_strdup(pass);
251 		pgp_forget(pass, sizeof(pass));
252 		return PGP_KEEP_MEMORY;
253 
254 	case PGP_PARSER_ERRCODE:
255 		switch (content->errcode.errcode) {
256 		case PGP_E_P_MPI_FORMAT_ERROR:
257 			/* Generally this means a bad passphrase */
258 			fprintf(stderr, "Bad passphrase!\n");
259 			return PGP_RELEASE_MEMORY;
260 
261 		case PGP_E_P_PACKET_CONSUMED:
262 			/* And this is because of an error we've accepted */
263 			return PGP_RELEASE_MEMORY;
264 		default:
265 			break;
266 		}
267 		(void) fprintf(stderr, "parse error: %s\n",
268 				pgp_errcode(content->errcode.errcode));
269 		return PGP_FINISHED;
270 
271 	case PGP_PARSER_ERROR:
272 		fprintf(stderr, "parse error: %s\n", content->error);
273 		return PGP_FINISHED;
274 
275 	case PGP_PTAG_CT_SECRET_KEY:
276 		if ((decrypt->seckey = calloc(1, sizeof(*decrypt->seckey))) == NULL) {
277 			(void) fprintf(stderr, "decrypt_cb: bad alloc\n");
278 			return PGP_FINISHED;
279 		}
280 		decrypt->seckey->checkhash = calloc(1, PGP_CHECKHASH_SIZE);
281 		*decrypt->seckey = content->seckey;
282 		return PGP_KEEP_MEMORY;
283 
284 	case PGP_PARSER_PACKET_END:
285 		/* nothing to do */
286 		break;
287 
288 	default:
289 		fprintf(stderr, "Unexpected tag %d (0x%x)\n", pkt->tag,
290 			pkt->tag);
291 		return PGP_FINISHED;
292 	}
293 
294 	return PGP_RELEASE_MEMORY;
295 }
296 
297 static pgp_cb_ret_t
decrypt_cb_empty(const pgp_packet_t * pkt,pgp_cbdata_t * cbinfo)298 decrypt_cb_empty(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
299 {
300 	const pgp_contents_t	*content = &pkt->u;
301 
302 	switch (pkt->tag) {
303 	case PGP_GET_PASSPHRASE:
304 		*content->skey_passphrase.passphrase = netpgp_strdup("");
305 		return PGP_KEEP_MEMORY;
306 	default:
307 		return decrypt_cb(pkt, cbinfo);
308 	}
309 }
310 
311 /**
312 \ingroup Core_Keys
313 \brief Decrypts secret key from given keydata with given passphrase
314 \param key Key from which to get secret key
315 \param passphrase Passphrase to use to decrypt secret key
316 \return secret key
317 */
318 pgp_seckey_t *
pgp_decrypt_seckey(const pgp_key_t * key,FILE * passfp)319 pgp_decrypt_seckey(const pgp_key_t *key, FILE *passfp)
320 {
321 	pgp_stream_t	*stream;
322 	const int	 printerrors = 1;
323 	decrypt_t	 decrypt;
324 
325 	/* XXX first try with an empty passphrase */
326 	(void) memset(&decrypt, 0x0, sizeof(decrypt));
327 	decrypt.key = key;
328 	stream = pgp_new(sizeof(*stream));
329 	pgp_keydata_reader_set(stream, key);
330 	pgp_set_callback(stream, decrypt_cb_empty, &decrypt);
331 	stream->readinfo.accumulate = 1;
332 	pgp_parse(stream, !printerrors);
333 	if (decrypt.seckey != NULL) {
334 		return decrypt.seckey;
335 	}
336 	/* ask for a passphrase */
337 	decrypt.passfp = passfp;
338 	stream = pgp_new(sizeof(*stream));
339 	pgp_keydata_reader_set(stream, key);
340 	pgp_set_callback(stream, decrypt_cb, &decrypt);
341 	stream->readinfo.accumulate = 1;
342 	pgp_parse(stream, !printerrors);
343 	return decrypt.seckey;
344 }
345 
346 /**
347 \ingroup Core_Keys
348 \brief Set secret key in content
349 \param content Content to be set
350 \param key Keydata to get secret key from
351 */
352 void
pgp_set_seckey(pgp_contents_t * cont,const pgp_key_t * key)353 pgp_set_seckey(pgp_contents_t *cont, const pgp_key_t *key)
354 {
355 	*cont->get_seckey.seckey = &key->key.seckey;
356 }
357 
358 /**
359 \ingroup Core_Keys
360 \brief Get Key ID from keydata
361 \param key Keydata to get Key ID from
362 \return Pointer to Key ID inside keydata
363 */
364 const uint8_t *
pgp_get_key_id(const pgp_key_t * key)365 pgp_get_key_id(const pgp_key_t *key)
366 {
367 	return key->sigid;
368 }
369 
370 /**
371 \ingroup Core_Keys
372 \brief How many User IDs in this key?
373 \param key Keydata to check
374 \return Num of user ids
375 */
376 unsigned
pgp_get_userid_count(const pgp_key_t * key)377 pgp_get_userid_count(const pgp_key_t *key)
378 {
379 	return key->uidc;
380 }
381 
382 /**
383 \ingroup Core_Keys
384 \brief Get indexed user id from key
385 \param key Key to get user id from
386 \param index Which key to get
387 \return Pointer to requested user id
388 */
389 const uint8_t *
pgp_get_userid(const pgp_key_t * key,unsigned subscript)390 pgp_get_userid(const pgp_key_t *key, unsigned subscript)
391 {
392 	return key->uids[subscript];
393 }
394 
395 /**
396    \ingroup HighLevel_Supported
397    \brief Checks whether key's algorithm and type are supported by OpenPGP::SDK
398    \param keydata Key to be checked
399    \return 1 if key algorithm and type are supported by OpenPGP::SDK; 0 if not
400 */
401 
402 unsigned
pgp_is_key_supported(const pgp_key_t * key)403 pgp_is_key_supported(const pgp_key_t *key)
404 {
405 	if (key->type == PGP_PTAG_CT_PUBLIC_KEY) {
406 		switch(key->key.pubkey.alg) {
407 		case PGP_PKA_RSA:
408 		case PGP_PKA_DSA:
409 		case PGP_PKA_ELGAMAL:
410 			return 1;
411 		default:
412 			break;
413 		}
414 	}
415 	return 0;
416 }
417 
418 /* \todo check where userid pointers are copied */
419 /**
420 \ingroup Core_Keys
421 \brief Copy user id, including contents
422 \param dst Destination User ID
423 \param src Source User ID
424 \note If dst already has a userid, it will be freed.
425 */
426 static uint8_t *
copy_userid(uint8_t ** dst,const uint8_t * src)427 copy_userid(uint8_t **dst, const uint8_t *src)
428 {
429 	size_t          len;
430 
431 	len = strlen((const char *) src);
432 	if (*dst) {
433 		free(*dst);
434 	}
435 	if ((*dst = calloc(1, len + 1)) == NULL) {
436 		(void) fprintf(stderr, "copy_userid: bad alloc\n");
437 	} else {
438 		(void) memcpy(*dst, src, len);
439 	}
440 	return *dst;
441 }
442 
443 /* \todo check where pkt pointers are copied */
444 /**
445 \ingroup Core_Keys
446 \brief Copy packet, including contents
447 \param dst Destination packet
448 \param src Source packet
449 \note If dst already has a packet, it will be freed.
450 */
451 static pgp_subpacket_t *
copy_packet(pgp_subpacket_t * dst,const pgp_subpacket_t * src)452 copy_packet(pgp_subpacket_t *dst, const pgp_subpacket_t *src)
453 {
454 	if (dst->raw) {
455 		free(dst->raw);
456 	}
457 	if ((dst->raw = calloc(1, src->length)) == NULL) {
458 		(void) fprintf(stderr, "copy_packet: bad alloc\n");
459 		dst->length = 0;
460 	} else {
461 		dst->length = src->length;
462 		(void) memcpy(dst->raw, src->raw, src->length);
463 	}
464 	dst->tag = src->tag;
465 	return dst;
466 }
467 
468 /**
469 \ingroup Core_Keys
470 \brief Add User ID to key
471 \param key Key to which to add User ID
472 \param userid User ID to add
473 \return Pointer to new User ID
474 */
475 uint8_t  *
pgp_add_userid(pgp_key_t * key,const uint8_t * userid)476 pgp_add_userid(pgp_key_t *key, const uint8_t *userid)
477 {
478 	uint8_t  **uidp;
479 
480 	EXPAND_ARRAY(key, uid);
481 	/* initialise new entry in array */
482 	uidp = &key->uids[key->uidc++];
483 	*uidp = NULL;
484 	/* now copy it */
485 	return copy_userid(uidp, userid);
486 }
487 
488 void print_packet_hex(const pgp_subpacket_t *pkt);
489 
490 /**
491 \ingroup Core_Keys
492 \brief Add packet to key
493 \param keydata Key to which to add packet
494 \param packet Packet to add
495 \return Pointer to new packet
496 */
497 pgp_subpacket_t   *
pgp_add_subpacket(pgp_key_t * keydata,const pgp_subpacket_t * packet)498 pgp_add_subpacket(pgp_key_t *keydata, const pgp_subpacket_t *packet)
499 {
500 	pgp_subpacket_t   *subpktp;
501 
502 	EXPAND_ARRAY(keydata, packet);
503 	/* initialise new entry in array */
504 	subpktp = &keydata->packets[keydata->packetc++];
505 	subpktp->raw = NULL;
506 	/* now copy it */
507 	return copy_packet(subpktp, packet);
508 }
509 
510 /**
511 \ingroup Core_Keys
512 \brief Add selfsigned User ID to key
513 \param keydata Key to which to add user ID
514 \param userid Self-signed User ID to add
515 \return 1 if OK; else 0
516 */
517 unsigned
pgp_add_selfsigned_userid(pgp_key_t * key,uint8_t * userid)518 pgp_add_selfsigned_userid(pgp_key_t *key, uint8_t *userid)
519 {
520 	pgp_create_sig_t	*sig;
521 	pgp_subpacket_t	 sigpacket;
522 	pgp_memory_t		*mem_userid = NULL;
523 	pgp_output_t		*useridoutput = NULL;
524 	pgp_memory_t		*mem_sig = NULL;
525 	pgp_output_t		*sigoutput = NULL;
526 
527 	/*
528          * create signature packet for this userid
529          */
530 
531 	/* create userid pkt */
532 	pgp_setup_memory_write(&useridoutput, &mem_userid, 128);
533 	pgp_write_struct_userid(useridoutput, userid);
534 
535 	/* create sig for this pkt */
536 	sig = pgp_create_sig_new();
537 	pgp_sig_start_key_sig(sig, &key->key.seckey.pubkey, userid, PGP_CERT_POSITIVE);
538 	pgp_add_time(sig, (int64_t)time(NULL), "birth");
539 	pgp_add_issuer_keyid(sig, key->sigid);
540 	pgp_add_primary_userid(sig, 1);
541 	pgp_end_hashed_subpkts(sig);
542 
543 	pgp_setup_memory_write(&sigoutput, &mem_sig, 128);
544 	pgp_write_sig(sigoutput, sig, &key->key.seckey.pubkey, &key->key.seckey);
545 
546 	/* add this packet to key */
547 	sigpacket.length = pgp_mem_len(mem_sig);
548 	sigpacket.raw = pgp_mem_data(mem_sig);
549 	sigpacket.tag = PGP_PTAG_CT_SIGNATURE;
550 
551 	/* add userid to key */
552 	(void) pgp_add_userid(key, userid);
553 	(void) pgp_add_subpacket(key, &sigpacket);
554 
555 	/* cleanup */
556 	pgp_create_sig_delete(sig);
557 	pgp_output_delete(useridoutput);
558 	pgp_output_delete(sigoutput);
559 	pgp_memory_free(mem_userid);
560 	pgp_memory_free(mem_sig);
561 
562 	return 1;
563 }
564 
565 /**
566 \ingroup Core_Keys
567 \brief Initialise pgp_key_t
568 \param keydata Keydata to initialise
569 \param type PGP_PTAG_CT_PUBLIC_KEY or PGP_PTAG_CT_SECRET_KEY
570 */
571 void
pgp_keydata_init(pgp_key_t * keydata,const pgp_content_enum type)572 pgp_keydata_init(pgp_key_t *keydata, const pgp_content_enum type)
573 {
574 	if (keydata->type != PGP_PTAG_CT_RESERVED) {
575 		(void) fprintf(stderr,
576 			"pgp_keydata_init: wrong keydata type\n");
577 	} else if (type != PGP_PTAG_CT_PUBLIC_KEY &&
578 		   type != PGP_PTAG_CT_SECRET_KEY) {
579 		(void) fprintf(stderr, "pgp_keydata_init: wrong type\n");
580 	} else {
581 		keydata->type = type;
582 	}
583 }
584 
585 /* used to point to data during keyring read */
586 typedef struct keyringcb_t {
587 	pgp_keyring_t		*keyring;	/* the keyring we're reading */
588 } keyringcb_t;
589 
590 
591 static pgp_cb_ret_t
cb_keyring_read(const pgp_packet_t * pkt,pgp_cbdata_t * cbinfo)592 cb_keyring_read(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
593 {
594 	pgp_keyring_t	*keyring;
595 	pgp_revoke_t	*revocation;
596 	pgp_key_t	*key;
597 	keyringcb_t	*cb;
598 
599 	cb = pgp_callback_arg(cbinfo);
600 	keyring = cb->keyring;
601 	key = keyring->keyc > 0 ? &keyring->keys[keyring->keyc - 1] : NULL;
602 
603 	switch (pkt->tag) {
604 	case PGP_PARSER_PTAG:
605 	case PGP_PTAG_CT_ENCRYPTED_SECRET_KEY:
606 		/* we get these because we didn't prompt */
607 		break;
608 	case PGP_PTAG_CT_SIGNATURE_HEADER:
609 		EXPAND_ARRAY(key, subsig);
610 		key->subsigs[key->subsigc].uid = key->uidc - 1;
611 		(void) memcpy(&key->subsigs[key->subsigc].sig, &pkt->u.sig,
612 				sizeof(pkt->u.sig));
613 		key->subsigc += 1;
614 		break;
615 	case PGP_PTAG_CT_SIGNATURE:
616 		EXPAND_ARRAY(key, subsig);
617 		key->subsigs[key->subsigc].uid = key->uidc - 1;
618 		(void) memcpy(&key->subsigs[key->subsigc].sig, &pkt->u.sig,
619 				sizeof(pkt->u.sig));
620 		key->subsigc += 1;
621 		break;
622 	case PGP_PTAG_CT_TRUST:
623 		EXPAND_ARRAY(key, subsig);
624 		key->subsigs[key->subsigc].trustlevel = pkt->u.ss_trust.level;
625 		key->subsigs[key->subsigc].trustamount = pkt->u.ss_trust.amount;
626 
627 		key->subsigc += 1;
628 
629 		break;
630 	case PGP_PTAG_SS_KEY_EXPIRY:
631 		EXPAND_ARRAY(keyring, key);
632 		if (keyring->keyc > 0) {
633 			keyring->keys[keyring->keyc - 1].key.pubkey.duration = pkt->u.ss_time;
634 		}
635 		break;
636 	case PGP_PTAG_SS_ISSUER_KEY_ID:
637 		(void) memcpy(&key->subsigs[key->subsigc - 1].sig.info.signer_id,
638 			      pkt->u.ss_issuer,
639 			      sizeof(pkt->u.ss_issuer));
640 		key->subsigs[key->subsigc - 1].sig.info.signer_id_set = 1;
641 		break;
642 	case PGP_PTAG_SS_CREATION_TIME:
643 		key->subsigs[key->subsigc - 1].sig.info.birthtime = pkt->u.ss_time;
644 		key->subsigs[key->subsigc - 1].sig.info.birthtime_set = 1;
645 		break;
646 	case PGP_PTAG_SS_EXPIRATION_TIME:
647 		key->subsigs[key->subsigc - 1].sig.info.duration = pkt->u.ss_time;
648 		key->subsigs[key->subsigc - 1].sig.info.duration_set = 1;
649 		break;
650 	case PGP_PTAG_SS_PRIMARY_USER_ID:
651 		key->uid0 = key->uidc - 1;
652 		break;
653 	case PGP_PTAG_SS_REVOCATION_REASON:
654 		if (key->uidc == 0) {
655 			/* revoke whole key */
656 			key->revoked = 1;
657 			revocation = &key->revocation;
658 		} else {
659 			/* revoke the user id */
660 			EXPAND_ARRAY(key, revoke);
661 			revocation = &key->revokes[key->revokec];
662 			key->revokes[key->revokec].uid = key->uidc - 1;
663 			key->revokec += 1;
664 		}
665 		revocation->code = pkt->u.ss_revocation.code;
666 		revocation->reason = netpgp_strdup(pgp_show_ss_rr_code(pkt->u.ss_revocation.code));
667 		break;
668 	case PGP_PTAG_CT_SIGNATURE_FOOTER:
669 	case PGP_PARSER_ERRCODE:
670 		break;
671 	default:
672 		break;
673 	}
674 	return PGP_RELEASE_MEMORY;
675 }
676 
677 /**
678    \ingroup HighLevel_KeyringRead
679 
680    \brief Reads a keyring from a file
681 
682    \param keyring Pointer to an existing pgp_keyring_t struct
683    \param armour 1 if file is armoured; else 0
684    \param filename Filename of keyring to be read
685 
686    \return pgp 1 if OK; 0 on error
687 
688    \note Keyring struct must already exist.
689 
690    \note Can be used with either a public or secret keyring.
691 
692    \note You must call pgp_keyring_free() after usage to free alloc-ed memory.
693 
694    \note If you call this twice on the same keyring struct, without calling
695    pgp_keyring_free() between these calls, you will introduce a memory leak.
696 
697    \sa pgp_keyring_read_from_mem()
698    \sa pgp_keyring_free()
699 
700 */
701 
702 unsigned
pgp_keyring_fileread(pgp_keyring_t * keyring,const unsigned armour,const char * filename)703 pgp_keyring_fileread(pgp_keyring_t *keyring,
704 			const unsigned armour,
705 			const char *filename)
706 {
707 	pgp_stream_t	*stream;
708 	keyringcb_t	 cb;
709 	unsigned	 res = 1;
710 	int		 fd;
711 
712 	(void) memset(&cb, 0x0, sizeof(cb));
713 	cb.keyring = keyring;
714 	stream = pgp_new(sizeof(*stream));
715 
716 	/* add this for the moment, */
717 	/*
718 	 * \todo need to fix the problems with reading signature subpackets
719 	 * later
720 	 */
721 
722 	/* pgp_parse_options(parse,PGP_PTAG_SS_ALL,PGP_PARSE_RAW); */
723 	pgp_parse_options(stream, PGP_PTAG_SS_ALL, PGP_PARSE_PARSED);
724 
725 #ifdef O_BINARY
726 	fd = open(filename, O_RDONLY | O_BINARY);
727 #else
728 	fd = open(filename, O_RDONLY);
729 #endif
730 	if (fd < 0) {
731 		pgp_stream_delete(stream);
732 		perror(filename);
733 		return 0;
734 	}
735 #ifdef USE_MMAP_FOR_FILES
736 	pgp_reader_set_mmap(stream, fd);
737 #else
738 	pgp_reader_set_fd(stream, fd);
739 #endif
740 
741 	pgp_set_callback(stream, cb_keyring_read, &cb);
742 
743 	if (armour) {
744 		pgp_reader_push_dearmour(stream);
745 	}
746 	res = pgp_parse_and_accumulate(keyring, stream);
747 	pgp_print_errors(pgp_stream_get_errors(stream));
748 
749 	if (armour) {
750 		pgp_reader_pop_dearmour(stream);
751 	}
752 
753 	(void)close(fd);
754 
755 	pgp_stream_delete(stream);
756 
757 	return res;
758 }
759 
760 /**
761    \ingroup HighLevel_KeyringRead
762 
763    \brief Reads a keyring from memory
764 
765    \param keyring Pointer to existing pgp_keyring_t struct
766    \param armour 1 if file is armoured; else 0
767    \param mem Pointer to a pgp_memory_t struct containing keyring to be read
768 
769    \return pgp 1 if OK; 0 on error
770 
771    \note Keyring struct must already exist.
772 
773    \note Can be used with either a public or secret keyring.
774 
775    \note You must call pgp_keyring_free() after usage to free alloc-ed memory.
776 
777    \note If you call this twice on the same keyring struct, without calling
778    pgp_keyring_free() between these calls, you will introduce a memory leak.
779 
780    \sa pgp_keyring_fileread
781    \sa pgp_keyring_free
782 */
783 unsigned
pgp_keyring_read_from_mem(pgp_io_t * io,pgp_keyring_t * keyring,const unsigned armour,pgp_memory_t * mem)784 pgp_keyring_read_from_mem(pgp_io_t *io,
785 				pgp_keyring_t *keyring,
786 				const unsigned armour,
787 				pgp_memory_t *mem)
788 {
789 	pgp_stream_t	*stream;
790 	const unsigned	 noaccum = 0;
791 	keyringcb_t	 cb;
792 	unsigned	 res;
793 
794 	(void) memset(&cb, 0x0, sizeof(cb));
795 	cb.keyring = keyring;
796 	stream = pgp_new(sizeof(*stream));
797 	pgp_parse_options(stream, PGP_PTAG_SS_ALL, PGP_PARSE_PARSED);
798 	pgp_setup_memory_read(io, &stream, mem, &cb, cb_keyring_read,
799 					noaccum);
800 	if (armour) {
801 		pgp_reader_push_dearmour(stream);
802 	}
803 	res = (unsigned)pgp_parse_and_accumulate(keyring, stream);
804 	pgp_print_errors(pgp_stream_get_errors(stream));
805 	if (armour) {
806 		pgp_reader_pop_dearmour(stream);
807 	}
808 	/* don't call teardown_memory_read because memory was passed in */
809 	pgp_stream_delete(stream);
810 	return res;
811 }
812 
813 /**
814    \ingroup HighLevel_KeyringWrite
815 
816    \brief Writes a keyring to a file
817 
818    \param keyring Pointer to an existing pgp_keyring_t struct
819    \param armour 1 if file is armoured; else 0
820    \param filename Filename of keyring to be written
821 
822    \return pgp 1 if OK; 0 on error
823 
824    \note Keyring struct must already exist.
825 
826    \note Can be used with either a public or secret keyring.
827 */
828 
829 unsigned
pgp_keyring_filewrite(pgp_keyring_t * keyring,unsigned armour,const char * filename,uint8_t * passphrase)830 pgp_keyring_filewrite(pgp_keyring_t *keyring,
831 			unsigned armour,
832 			const char *filename,
833 			uint8_t *passphrase)
834 {
835 	pgp_output_t		*output;
836 	int			fd;
837 	unsigned	 	res = 1;
838 	pgp_key_t		*key;
839 	unsigned	 	n;
840 	pgp_content_enum	type;
841 	pgp_armor_type_t	atype;
842 
843 	fd = pgp_setup_file_write(&output, filename, 1);
844 	if (fd < 0) {
845 		perror(filename);
846 		return 0;
847 	}
848 
849 	type = keyring->keyc > 0 ? keyring->keys->type : PGP_PTAG_CT_PUBLIC_KEY;
850 
851 	if (armour) {
852 		if (type == PGP_PTAG_CT_PUBLIC_KEY)
853 			atype = PGP_PGP_PUBLIC_KEY_BLOCK;
854 		else
855 			atype = PGP_PGP_PRIVATE_KEY_BLOCK;
856 		pgp_writer_push_armoured(output, atype);
857 	}
858 	for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) {
859 		/* write only keys of a single type */
860 		if (key->type != type) {
861 			(void) fprintf(stderr, "ERROR: skip key %d\n", n);
862 			continue;
863 		}
864 		if (key->type == PGP_PTAG_CT_PUBLIC_KEY) {
865 			pgp_write_xfer_pubkey(output, key, 0);
866 		} else {
867 			pgp_write_xfer_seckey(output, key, passphrase,
868 					strlen((char *)passphrase), 0);
869 		}
870 	}
871 	if (armour) {
872 		pgp_writer_info_finalise(&output->errors, &output->writer);
873 		pgp_writer_pop(output);
874 	}
875 
876 	pgp_teardown_file_write(output, fd);
877 
878 	return res;
879 }
880 
881 /**
882    \ingroup HighLevel_KeyringRead
883 
884    \brief Frees keyring's contents (but not keyring itself)
885 
886    \param keyring Keyring whose data is to be freed
887 
888    \note This does not free keyring itself, just the memory alloc-ed in it.
889  */
890 void
pgp_keyring_free(pgp_keyring_t * keyring)891 pgp_keyring_free(pgp_keyring_t *keyring)
892 {
893 	(void)free(keyring->keys);
894 	keyring->keys = NULL;
895 	keyring->keyc = keyring->keyvsize = 0;
896 }
897 
898 /**
899    \ingroup HighLevel_KeyringFind
900 
901    \brief Finds key in keyring from its Key ID
902 
903    \param keyring Keyring to be searched
904    \param keyid ID of required key
905 
906    \return Pointer to key, if found; NULL, if not found
907 
908    \note This returns a pointer to the key inside the given keyring,
909    not a copy.  Do not free it after use.
910 
911 */
912 const pgp_key_t *
pgp_getkeybyid(pgp_io_t * io,const pgp_keyring_t * keyring,const uint8_t * keyid,unsigned * from,pgp_pubkey_t ** pubkey)913 pgp_getkeybyid(pgp_io_t *io, const pgp_keyring_t *keyring,
914 			   const uint8_t *keyid, unsigned *from, pgp_pubkey_t **pubkey)
915 {
916 	uint8_t	nullid[PGP_KEY_ID_SIZE];
917 
918 	(void) memset(nullid, 0x0, sizeof(nullid));
919 	for ( ; keyring && *from < keyring->keyc; *from += 1) {
920 		if (pgp_get_debug_level(__FILE__)) {
921 			hexdump(io->errs, "keyring keyid", keyring->keys[*from].sigid, PGP_KEY_ID_SIZE);
922 			hexdump(io->errs, "keyid", keyid, PGP_KEY_ID_SIZE);
923 		}
924 		if (memcmp(keyring->keys[*from].sigid, keyid, PGP_KEY_ID_SIZE) == 0 ||
925 		    memcmp(&keyring->keys[*from].sigid[PGP_KEY_ID_SIZE / 2],
926 				keyid, PGP_KEY_ID_SIZE / 2) == 0) {
927 			if (pubkey) {
928 				*pubkey = &keyring->keys[*from].key.pubkey;
929 			}
930 			return &keyring->keys[*from];
931 		}
932 		if (memcmp(&keyring->keys[*from].encid, nullid, sizeof(nullid)) == 0) {
933 			continue;
934 		}
935 		if (memcmp(&keyring->keys[*from].encid, keyid, PGP_KEY_ID_SIZE) == 0 ||
936 		    memcmp(&keyring->keys[*from].encid[PGP_KEY_ID_SIZE / 2], keyid, PGP_KEY_ID_SIZE / 2) == 0) {
937 			if (pubkey) {
938 				*pubkey = &keyring->keys[*from].enckey;
939 			}
940 			return &keyring->keys[*from];
941 		}
942 	}
943 	return NULL;
944 }
945 
946 /* convert a string keyid into a binary keyid */
947 static void
str2keyid(const char * userid,uint8_t * keyid,size_t len)948 str2keyid(const char *userid, uint8_t *keyid, size_t len)
949 {
950 	static const char	*uppers = "0123456789ABCDEF";
951 	static const char	*lowers = "0123456789abcdef";
952 	const char		*hi;
953 	const char		*lo;
954 	uint8_t			 hichar;
955 	uint8_t			 lochar;
956 	size_t			 j;
957 	int			 i;
958 
959 	for (i = 0, j = 0 ; j < len && userid[i] && userid[i + 1] ; i += 2, j++) {
960 		if ((hi = strchr(uppers, userid[i])) == NULL) {
961 			if ((hi = strchr(lowers, userid[i])) == NULL) {
962 				break;
963 			}
964 			hichar = (uint8_t)(hi - lowers);
965 		} else {
966 			hichar = (uint8_t)(hi - uppers);
967 		}
968 		if ((lo = strchr(uppers, userid[i + 1])) == NULL) {
969 			if ((lo = strchr(lowers, userid[i + 1])) == NULL) {
970 				break;
971 			}
972 			lochar = (uint8_t)(lo - lowers);
973 		} else {
974 			lochar = (uint8_t)(lo - uppers);
975 		}
976 		keyid[j] = (hichar << 4) | (lochar);
977 	}
978 	keyid[j] = 0x0;
979 }
980 
981 /* return the next key which matches, starting searching at *from */
982 static const pgp_key_t *
getkeybyname(pgp_io_t * io,const pgp_keyring_t * keyring,const char * name,unsigned * from)983 getkeybyname(pgp_io_t *io,
984 			const pgp_keyring_t *keyring,
985 			const char *name,
986 			unsigned *from)
987 {
988 	const pgp_key_t	*kp;
989 	uint8_t			**uidp;
990 	unsigned    	 	 i = 0;
991 	pgp_key_t		*keyp;
992 	unsigned		 savedstart;
993 	regex_t			 r;
994 	uint8_t		 	 keyid[PGP_KEY_ID_SIZE + 1];
995 	size_t          	 len;
996 
997 	if (!keyring || !name || !from) {
998 		return NULL;
999 	}
1000 	len = strlen(name);
1001 	if (pgp_get_debug_level(__FILE__)) {
1002 		(void) fprintf(io->outs, "[%u] name '%s', len %zu\n",
1003 			*from, name, len);
1004 	}
1005 	/* first try name as a keyid */
1006 	(void) memset(keyid, 0x0, sizeof(keyid));
1007 	str2keyid(name, keyid, sizeof(keyid));
1008 	if (pgp_get_debug_level(__FILE__)) {
1009 		hexdump(io->outs, "keyid", keyid, 4);
1010 	}
1011 	savedstart = *from;
1012 	if ((kp = pgp_getkeybyid(io, keyring, keyid, from, NULL)) != NULL) {
1013 		return kp;
1014 	}
1015 	*from = savedstart;
1016 	if (pgp_get_debug_level(__FILE__)) {
1017 		(void) fprintf(io->outs, "regex match '%s' from %u\n",
1018 			name, *from);
1019 	}
1020 	/* match on full name or email address as a NOSUB, ICASE regexp */
1021 	(void) regcomp(&r, name, REG_EXTENDED | REG_ICASE);
1022 	for (keyp = &keyring->keys[*from]; *from < keyring->keyc; *from += 1, keyp++) {
1023 		uidp = keyp->uids;
1024 		for (i = 0 ; i < keyp->uidc; i++, uidp++) {
1025 			if (regexec(&r, (char *)*uidp, 0, NULL, 0) == 0) {
1026 				if (pgp_get_debug_level(__FILE__)) {
1027 					(void) fprintf(io->outs,
1028 						"MATCHED keyid \"%s\" len %" PRIsize "u\n",
1029 					       (char *) *uidp, len);
1030 				}
1031 				regfree(&r);
1032 				return keyp;
1033 			}
1034 		}
1035 	}
1036 	regfree(&r);
1037 	return NULL;
1038 }
1039 
1040 /**
1041    \ingroup HighLevel_KeyringFind
1042 
1043    \brief Finds key from its User ID
1044 
1045    \param keyring Keyring to be searched
1046    \param userid User ID of required key
1047 
1048    \return Pointer to Key, if found; NULL, if not found
1049 
1050    \note This returns a pointer to the key inside the keyring, not a
1051    copy.  Do not free it.
1052 
1053 */
1054 const pgp_key_t *
pgp_getkeybyname(pgp_io_t * io,const pgp_keyring_t * keyring,const char * name)1055 pgp_getkeybyname(pgp_io_t *io,
1056 			const pgp_keyring_t *keyring,
1057 			const char *name)
1058 {
1059 	unsigned	from;
1060 
1061 	from = 0;
1062 	return getkeybyname(io, keyring, name, &from);
1063 }
1064 
1065 const pgp_key_t *
pgp_getnextkeybyname(pgp_io_t * io,const pgp_keyring_t * keyring,const char * name,unsigned * n)1066 pgp_getnextkeybyname(pgp_io_t *io,
1067 			const pgp_keyring_t *keyring,
1068 			const char *name,
1069 			unsigned *n)
1070 {
1071 	return getkeybyname(io, keyring, name, n);
1072 }
1073 
1074 /**
1075    \ingroup HighLevel_KeyringList
1076 
1077    \brief Prints all keys in keyring to stdout.
1078 
1079    \param keyring Keyring to use
1080 
1081    \return none
1082 */
1083 int
pgp_keyring_list(pgp_io_t * io,const pgp_keyring_t * keyring,const int psigs)1084 pgp_keyring_list(pgp_io_t *io, const pgp_keyring_t *keyring, const int psigs)
1085 {
1086 	pgp_key_t		*key;
1087 	unsigned		 n;
1088 	unsigned		 keyc = (keyring != NULL) ? keyring->keyc : 0;
1089 
1090 	(void) fprintf(io->res, "%u key%s\n", keyc, (keyc == 1) ? "" : "s");
1091 	if (keyring == NULL) {
1092 		return 1;
1093 	}
1094 	for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) {
1095 		if (pgp_is_key_secret(key)) {
1096 			pgp_print_keydata(io, keyring, key, "sec",
1097 				&key->key.seckey.pubkey, 0);
1098 		} else {
1099 			pgp_print_keydata(io, keyring, key, "pub",
1100 				&key->key.pubkey, psigs);
1101 		}
1102 		(void) fputc('\n', io->res);
1103 	}
1104 	return 1;
1105 }
1106 
1107 int
pgp_keyring_json(pgp_io_t * io,const pgp_keyring_t * keyring,mj_t * obj,const int psigs)1108 pgp_keyring_json(pgp_io_t *io, const pgp_keyring_t *keyring, mj_t *obj, const int psigs)
1109 {
1110 	pgp_key_t		*key;
1111 	unsigned		 n;
1112 
1113 	(void) memset(obj, 0x0, sizeof(*obj));
1114 	mj_create(obj, "array");
1115 	obj->size = keyring->keyvsize;
1116 	if (pgp_get_debug_level(__FILE__)) {
1117 		(void) fprintf(io->errs, "pgp_keyring_json: vsize %u\n", obj->size);
1118 	}
1119 	if ((obj->value.v = calloc(sizeof(*obj->value.v), obj->size)) == NULL) {
1120 		(void) fprintf(io->errs, "calloc failure\n");
1121 		return 0;
1122 	}
1123 	for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) {
1124 		if (pgp_is_key_secret(key)) {
1125 			pgp_sprint_mj(io, keyring, key, &obj->value.v[obj->c],
1126 				"sec", &key->key.seckey.pubkey, psigs);
1127 		} else {
1128 			pgp_sprint_mj(io, keyring, key, &obj->value.v[obj->c],
1129 				"pub", &key->key.pubkey, psigs);
1130 		}
1131 		if (obj->value.v[obj->c].type != 0) {
1132 			obj->c += 1;
1133 		}
1134 	}
1135 	if (pgp_get_debug_level(__FILE__)) {
1136 		char	*s;
1137 
1138 		mj_asprint(&s, obj, MJ_JSON_ENCODE);
1139 		(void) fprintf(stderr, "pgp_keyring_json: '%s'\n", s);
1140 		free(s);
1141 	}
1142 	return 1;
1143 }
1144 
1145 
1146 /* this interface isn't right - hook into callback for getting passphrase */
1147 char *
pgp_export_key(pgp_io_t * io,const pgp_key_t * keydata,uint8_t * passphrase)1148 pgp_export_key(pgp_io_t *io, const pgp_key_t *keydata, uint8_t *passphrase)
1149 {
1150 	pgp_output_t	*output;
1151 	pgp_memory_t	*mem;
1152 	char		*cp;
1153 
1154 	__PGP_USED(io);
1155 	pgp_setup_memory_write(&output, &mem, 128);
1156 	if (keydata->type == PGP_PTAG_CT_PUBLIC_KEY) {
1157 		pgp_write_xfer_pubkey(output, keydata, 1);
1158 	} else {
1159 		pgp_write_xfer_seckey(output, keydata, passphrase,
1160 					strlen((char *)passphrase), 1);
1161 	}
1162 	pgp_memory_add(mem, (uint8_t[]){0}, 1);
1163 	cp = netpgp_strdup(pgp_mem_data(mem));
1164 	pgp_teardown_memory_write(output, mem);
1165 	return cp;
1166 }
1167 
1168 /* add a key to a public keyring */
1169 int
pgp_add_to_pubring(pgp_keyring_t * keyring,const pgp_pubkey_t * pubkey,pgp_content_enum tag)1170 pgp_add_to_pubring(pgp_keyring_t *keyring, const pgp_pubkey_t *pubkey, pgp_content_enum tag)
1171 {
1172 	pgp_key_t	*key;
1173 	time_t		 duration;
1174 
1175 	if (pgp_get_debug_level(__FILE__)) {
1176 		fprintf(stderr, "pgp_add_to_pubring (type %u)\n", tag);
1177 	}
1178 	switch(tag) {
1179 	case PGP_PTAG_CT_PUBLIC_KEY:
1180 		EXPAND_ARRAY(keyring, key);
1181 		key = &keyring->keys[keyring->keyc++];
1182 		duration = key->key.pubkey.duration;
1183 		(void) memset(key, 0x0, sizeof(*key));
1184 		key->type = tag;
1185 		pgp_keyid(key->sigid, PGP_KEY_ID_SIZE, pubkey, keyring->hashtype);
1186 		pgp_fingerprint(&key->sigfingerprint, pubkey, keyring->hashtype);
1187 		key->key.pubkey = *pubkey;
1188 		key->key.pubkey.duration = duration;
1189 		return 1;
1190 	case PGP_PTAG_CT_PUBLIC_SUBKEY:
1191 		/* subkey is not the first */
1192 		key = &keyring->keys[keyring->keyc - 1];
1193 		pgp_keyid(key->encid, PGP_KEY_ID_SIZE, pubkey, keyring->hashtype);
1194 		duration = key->key.pubkey.duration;
1195 		(void) memcpy(&key->enckey, pubkey, sizeof(key->enckey));
1196 		key->enckey.duration = duration;
1197 		return 1;
1198 	default:
1199 		return 0;
1200 	}
1201 }
1202 
1203 /* add a key to a secret keyring */
1204 int
pgp_add_to_secring(pgp_keyring_t * keyring,const pgp_seckey_t * seckey)1205 pgp_add_to_secring(pgp_keyring_t *keyring, const pgp_seckey_t *seckey)
1206 {
1207 	const pgp_pubkey_t	*pubkey;
1208 	pgp_key_t		*key;
1209 
1210 	if (pgp_get_debug_level(__FILE__)) {
1211 		fprintf(stderr, "pgp_add_to_secring\n");
1212 	}
1213 	if (keyring->keyc > 0) {
1214 		key = &keyring->keys[keyring->keyc - 1];
1215 		if (pgp_get_debug_level(__FILE__) &&
1216 		    key->key.pubkey.alg == PGP_PKA_DSA &&
1217 		    seckey->pubkey.alg == PGP_PKA_ELGAMAL) {
1218 			fprintf(stderr, "pgp_add_to_secring: found elgamal seckey\n");
1219 		}
1220 	}
1221 	EXPAND_ARRAY(keyring, key);
1222 	key = &keyring->keys[keyring->keyc++];
1223 	(void) memset(key, 0x0, sizeof(*key));
1224 	pubkey = &seckey->pubkey;
1225 	pgp_keyid(key->sigid, PGP_KEY_ID_SIZE, pubkey, keyring->hashtype);
1226 	pgp_fingerprint(&key->sigfingerprint, pubkey, keyring->hashtype);
1227 	key->type = PGP_PTAG_CT_SECRET_KEY;
1228 	key->key.seckey = *seckey;
1229 	if (pgp_get_debug_level(__FILE__)) {
1230 		fprintf(stderr, "pgp_add_to_secring: keyc %u\n", keyring->keyc);
1231 	}
1232 	return 1;
1233 }
1234 
1235 /* append one keyring to another */
1236 int
pgp_append_keyring(pgp_keyring_t * keyring,pgp_keyring_t * newring)1237 pgp_append_keyring(pgp_keyring_t *keyring, pgp_keyring_t *newring)
1238 {
1239 	unsigned	i;
1240 
1241 	for (i = 0 ; i < newring->keyc ; i++) {
1242 		EXPAND_ARRAY(keyring, key);
1243 		(void) memcpy(&keyring->keys[keyring->keyc], &newring->keys[i],
1244 				sizeof(newring->keys[i]));
1245 		keyring->keyc += 1;
1246 	}
1247 	return 1;
1248 }
1249