xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/keyring.c (revision c8da0e5fefd3800856b306200a18b2315c7fbb9f)
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_FCNTL_H
55 #include <fcntl.h>
56 #endif
57 
58 #include <stdlib.h>
59 #include <string.h>
60 
61 #ifdef HAVE_TERMIOS_H
62 #include <termios.h>
63 #endif
64 
65 #ifdef HAVE_UNISTD_H
66 #include <unistd.h>
67 #endif
68 
69 #include "keyring.h"
70 #include "packet-parse.h"
71 #include "signature.h"
72 #include "netpgpsdk.h"
73 #include "readerwriter.h"
74 #include "netpgpdefs.h"
75 #include "keyring_local.h"
76 #include "parse_local.h"
77 #include "validate.h"
78 
79 
80 
81 /**
82    \ingroup HighLevel_Keyring
83 
84    \brief Creates a new __ops_keydata_t struct
85 
86    \return A new __ops_keydata_t struct, initialised to zero.
87 
88    \note The returned __ops_keydata_t struct must be freed after use with __ops_keydata_free.
89 */
90 
91 __ops_keydata_t  *
92 __ops_keydata_new(void)
93 {
94 	return calloc(1, sizeof(__ops_keydata_t));
95 }
96 
97 
98 /**
99  \ingroup HighLevel_Keyring
100 
101  \brief Frees keydata and its memory
102 
103  \param keydata Key to be freed.
104 
105  \note This frees the keydata itself, as well as any other memory alloc-ed by it.
106 */
107 void
108 __ops_keydata_free(__ops_keydata_t *keydata)
109 {
110 	unsigned        n;
111 
112 	for (n = 0; n < keydata->nuids; ++n) {
113 		__ops_user_id_free(&keydata->uids[n]);
114 	}
115 	(void) free(keydata->uids);
116 	keydata->uids = NULL;
117 	keydata->nuids = 0;
118 
119 	for (n = 0; n < keydata->npackets; ++n) {
120 		__ops_subpacket_free(&keydata->packets[n]);
121 	}
122 	(void) free(keydata->packets);
123 	keydata->packets = NULL;
124 	keydata->npackets = 0;
125 
126 	if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) {
127 		__ops_pubkey_free(&keydata->key.pubkey);
128 	} else {
129 		__ops_seckey_free(&keydata->key.seckey);
130 	}
131 
132 	(void) free(keydata);
133 }
134 
135 /**
136  \ingroup HighLevel_KeyGeneral
137 
138  \brief Returns the public key in the given keydata.
139  \param keydata
140 
141   \return Pointer to public key
142 
143   \note This is not a copy, do not free it after use.
144 */
145 
146 const __ops_pubkey_t *
147 __ops_get_pubkey(const __ops_keydata_t * keydata)
148 {
149 	return (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) ? &keydata->key.pubkey :
150 		&keydata->key.seckey.pubkey;
151 }
152 
153 /**
154 \ingroup HighLevel_KeyGeneral
155 
156 \brief Check whether this is a secret key or not.
157 */
158 
159 bool
160 __ops_is_key_secret(const __ops_keydata_t * data)
161 {
162 	return data->type != OPS_PTAG_CT_PUBLIC_KEY;
163 }
164 
165 /**
166  \ingroup HighLevel_KeyGeneral
167 
168  \brief Returns the secret key in the given keydata.
169 
170  \note This is not a copy, do not free it after use.
171 
172  \note This returns a const. If you need to be able to write to this pointer, use __ops_get_writable_seckey
173 */
174 
175 const __ops_seckey_t *
176 __ops_get_seckey(const __ops_keydata_t * data)
177 {
178 	return (data->type == OPS_PTAG_CT_SECRET_KEY) ? &data->key.seckey : NULL;
179 }
180 
181 /**
182  \ingroup HighLevel_KeyGeneral
183 
184   \brief Returns the secret key in the given keydata.
185 
186   \note This is not a copy, do not free it after use.
187 
188   \note If you do not need to be able to modify this key, there is an equivalent read-only function __ops_get_seckey.
189 */
190 
191 __ops_seckey_t *
192 __ops_get_writable_seckey(__ops_keydata_t * data)
193 {
194 	return (data->type == OPS_PTAG_CT_SECRET_KEY) ? &data->key.seckey : NULL;
195 }
196 
197 typedef struct {
198 	const __ops_keydata_t *key;
199 	char           *pphrase;
200 	__ops_seckey_t *seckey;
201 }               decrypt_t;
202 
203 static __ops_parse_cb_return_t
204 decrypt_cb(const __ops_packet_t *pkt, __ops_callback_data_t *cbinfo)
205 {
206 	const __ops_parser_content_union_t *content = &pkt->u;
207 	decrypt_t  *decrypt = __ops_parse_cb_get_arg(cbinfo);
208 
209 	__OPS_USED(cbinfo);
210 
211 	switch (pkt->tag) {
212 	case OPS_PARSER_PTAG:
213 	case OPS_PTAG_CT_USER_ID:
214 	case OPS_PTAG_CT_SIGNATURE:
215 	case OPS_PTAG_CT_SIGNATURE_HEADER:
216 	case OPS_PTAG_CT_SIGNATURE_FOOTER:
217 	case OPS_PTAG_CT_TRUST:
218 		break;
219 
220 	case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
221 		*content->skey_passphrase.passphrase = decrypt->pphrase;
222 		return OPS_KEEP_MEMORY;
223 
224 	case OPS_PARSER_ERRCODE:
225 		switch (content->errcode.errcode) {
226 		case OPS_E_P_MPI_FORMAT_ERROR:
227 			/* Generally this means a bad passphrase */
228 			fprintf(stderr, "Bad passphrase!\n");
229 			return OPS_RELEASE_MEMORY;
230 
231 		case OPS_E_P_PACKET_CONSUMED:
232 			/* And this is because of an error we've accepted */
233 			return OPS_RELEASE_MEMORY;
234 		default:
235 			break;
236 		}
237 		(void) fprintf(stderr, "parse error: %s\n",
238 				__ops_errcode(content->errcode.errcode));
239 		return OPS_FINISHED;
240 
241 	case OPS_PARSER_ERROR:
242 		fprintf(stderr, "parse error: %s\n", content->error.error);
243 		return OPS_FINISHED;
244 
245 	case OPS_PTAG_CT_SECRET_KEY:
246 		decrypt->seckey = calloc(1, sizeof(*decrypt->seckey));
247 		*decrypt->seckey = content->seckey;
248 		return OPS_KEEP_MEMORY;
249 
250 	case OPS_PARSER_PACKET_END:
251 		/* nothing to do */
252 		break;
253 
254 	default:
255 		fprintf(stderr, "Unexpected tag %d (0x%x)\n", pkt->tag,
256 			pkt->tag);
257 		return OPS_FINISHED;
258 	}
259 
260 	return OPS_RELEASE_MEMORY;
261 }
262 
263 /**
264 \ingroup Core_Keys
265 \brief Decrypts secret key from given keydata with given passphrase
266 \param key Key from which to get secret key
267 \param pphrase Passphrase to use to decrypt secret key
268 \return secret key
269 */
270 __ops_seckey_t *
271 __ops_decrypt_seckey(const __ops_keydata_t * key,
272 				 const char *pphrase)
273 {
274 	__ops_parseinfo_t *pinfo;
275 	decrypt_t   decrypt;
276 
277 	(void) memset(&decrypt, 0x0, sizeof(decrypt));
278 	decrypt.key = key;
279 	decrypt.pphrase = strdup(pphrase);
280 
281 	pinfo = __ops_parseinfo_new();
282 
283 	__ops_keydata_reader_set(pinfo, key);
284 	__ops_parse_cb_set(pinfo, decrypt_cb, &decrypt);
285 	pinfo->readinfo.accumulate = true;
286 
287 	__ops_parse(pinfo, 0);
288 
289 	return decrypt.seckey;
290 }
291 
292 /**
293 \ingroup Core_Keys
294 \brief Set secret key in content
295 \param content Content to be set
296 \param key Keydata to get secret key from
297 */
298 void
299 __ops_set_seckey(__ops_parser_content_union_t * content, const __ops_keydata_t * key)
300 {
301 	*content->get_seckey.seckey = &key->key.seckey;
302 }
303 
304 /**
305 \ingroup Core_Keys
306 \brief Get Key ID from keydata
307 \param key Keydata to get Key ID from
308 \return Pointer to Key ID inside keydata
309 */
310 const unsigned char *
311 __ops_get_key_id(const __ops_keydata_t * key)
312 {
313 	return key->key_id;
314 }
315 
316 /**
317 \ingroup Core_Keys
318 \brief How many User IDs in this key?
319 \param key Keydata to check
320 \return Num of user ids
321 */
322 unsigned
323 __ops_get_user_id_count(const __ops_keydata_t * key)
324 {
325 	return key->nuids;
326 }
327 
328 /**
329 \ingroup Core_Keys
330 \brief Get indexed user id from key
331 \param key Key to get user id from
332 \param index Which key to get
333 \return Pointer to requested user id
334 */
335 const unsigned char *
336 __ops_get_user_id(const __ops_keydata_t * key, unsigned subscript)
337 {
338 	return key->uids[subscript].user_id;
339 }
340 
341 /**
342    \ingroup HighLevel_Supported
343    \brief Checks whether key's algorithm and type are supported by OpenPGP::SDK
344    \param keydata Key to be checked
345    \return true if key algorithm and type are supported by OpenPGP::SDK; false if not
346 */
347 
348 bool
349 __ops_is_key_supported(const __ops_keydata_t *keydata)
350 {
351 	if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) {
352 		if (keydata->key.pubkey.alg == OPS_PKA_RSA) {
353 			return true;
354 		}
355 	} else if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) {
356 		if (keydata->key.pubkey.alg == OPS_PKA_DSA) {
357 			return true;
358 		}
359 	}
360 	return false;
361 }
362 
363 
364 /**
365     \ingroup HighLevel_KeyringFind
366 
367     \brief Returns key inside a keyring, chosen by index
368 
369     \param keyring Pointer to existing keyring
370     \param index Index of required key
371 
372     \note Index starts at 0
373 
374     \note This returns a pointer to the original key, not a copy. You do not need to free the key after use.
375 
376     \return Pointer to the required key; or NULL if index too large.
377 
378     Example code:
379     \code
380     void example(const __ops_keyring_t* keyring)
381     {
382     __ops_keydata_t* keydata=NULL;
383     keydata=__ops_keyring_get_key_by_index(keyring, 0);
384     ...
385     }
386     \endcode
387 */
388 
389 const __ops_keydata_t *
390 __ops_keyring_get_key_by_index(const __ops_keyring_t * keyring, int subscript)
391 {
392 	if (subscript >= keyring->nkeys)
393 		return NULL;
394 	return &keyring->keys[subscript];
395 }
396 
397 /* \todo check where userid pointers are copied */
398 /**
399 \ingroup Core_Keys
400 \brief Copy user id, including contents
401 \param dst Destination User ID
402 \param src Source User ID
403 \note If dst already has a user_id, it will be freed.
404 */
405 void
406 __ops_copy_userid(__ops_user_id_t * dst, const __ops_user_id_t * src)
407 {
408 	size_t          len = strlen((char *) src->user_id);
409 	if (dst->user_id)
410 		free(dst->user_id);
411 	dst->user_id = calloc(1, len + 1);
412 
413 	(void) memcpy(dst->user_id, src->user_id, len);
414 }
415 
416 /* \todo check where pkt pointers are copied */
417 /**
418 \ingroup Core_Keys
419 \brief Copy packet, including contents
420 \param dst Destination packet
421 \param src Source packet
422 \note If dst already has a packet, it will be freed.
423 */
424 void
425 __ops_copy_packet(__ops_subpacket_t * dst, const __ops_subpacket_t * src)
426 {
427 	if (dst->raw) {
428 		(void) free(dst->raw);
429 	}
430 	dst->raw = calloc(1, src->length);
431 	dst->length = src->length;
432 	(void) memcpy(dst->raw, src->raw, src->length);
433 }
434 
435 /**
436 \ingroup Core_Keys
437 \brief Add User ID to keydata
438 \param keydata Key to which to add User ID
439 \param userid User ID to add
440 \return Pointer to new User ID
441 */
442 __ops_user_id_t  *
443 __ops_add_userid_to_keydata(__ops_keydata_t * keydata, const __ops_user_id_t * userid)
444 {
445 	__ops_user_id_t  *new_uid = NULL;
446 
447 	EXPAND_ARRAY(keydata, uids);
448 
449 	/* initialise new entry in array */
450 	new_uid = &keydata->uids[keydata->nuids];
451 
452 	new_uid->user_id = NULL;
453 
454 	/* now copy it */
455 	__ops_copy_userid(new_uid, userid);
456 	keydata->nuids++;
457 
458 	return new_uid;
459 }
460 
461 /**
462 \ingroup Core_Keys
463 \brief Add packet to key
464 \param keydata Key to which to add packet
465 \param packet Packet to add
466 \return Pointer to new packet
467 */
468 __ops_subpacket_t   *
469 __ops_add_packet_to_keydata(__ops_keydata_t * keydata, const __ops_subpacket_t * packet)
470 {
471 	__ops_subpacket_t   *new_pkt = NULL;
472 
473 	EXPAND_ARRAY(keydata, packets);
474 
475 	/* initialise new entry in array */
476 	new_pkt = &keydata->packets[keydata->npackets];
477 	new_pkt->length = 0;
478 	new_pkt->raw = NULL;
479 
480 	/* now copy it */
481 	__ops_copy_packet(new_pkt, packet);
482 	keydata->npackets++;
483 
484 	return new_pkt;
485 }
486 
487 /**
488 \ingroup Core_Keys
489 \brief Add signed User ID to key
490 \param keydata Key to which to add signed User ID
491 \param user_id User ID to add
492 \param sigpacket Packet to add
493 */
494 void
495 __ops_add_signed_userid_to_keydata(__ops_keydata_t * keydata, const __ops_user_id_t * user_id, const __ops_subpacket_t * sigpacket)
496 {
497 	__ops_subpacket_t	*pkt = NULL;
498 	__ops_user_id_t		*uid = NULL;
499 
500 	uid = __ops_add_userid_to_keydata(keydata, user_id);
501 	pkt = __ops_add_packet_to_keydata(keydata, sigpacket);
502 
503 	/*
504          * add entry in sigs array to link the userid and sigpacket
505 	 * and add ptr to it from the sigs array */
506 	EXPAND_ARRAY(keydata, sigs);
507 
508 	/**setup new entry in array */
509 	keydata->sigs[keydata->nsigs].userid = uid;
510 	keydata->sigs[keydata->nsigs].packet = pkt;
511 
512 	keydata->nsigs++;
513 }
514 
515 /**
516 \ingroup Core_Keys
517 \brief Add selfsigned User ID to key
518 \param keydata Key to which to add user ID
519 \param userid Self-signed User ID to add
520 \return true if OK; else false
521 */
522 bool
523 __ops_add_selfsigned_userid_to_keydata(__ops_keydata_t * keydata, __ops_user_id_t * userid)
524 {
525 	__ops_subpacket_t    sigpacket;
526 
527 	__ops_memory_t   *mem_userid = NULL;
528 	__ops_createinfo_t *cinfo_userid = NULL;
529 
530 	__ops_memory_t   *mem_sig = NULL;
531 	__ops_createinfo_t *cinfo_sig = NULL;
532 
533 	__ops_create_sig_t *sig = NULL;
534 
535 	/*
536          * create signature packet for this userid
537          */
538 
539 	/* create userid pkt */
540 	__ops_setup_memory_write(&cinfo_userid, &mem_userid, 128);
541 	__ops_write_struct_user_id(userid, cinfo_userid);
542 
543 	/* create sig for this pkt */
544 
545 	sig = __ops_create_sig_new();
546 	__ops_sig_start_key_sig(sig, &keydata->key.seckey.pubkey, userid, OPS_CERT_POSITIVE);
547 	__ops_sig_add_birthtime(sig, time(NULL));
548 	__ops_sig_add_issuer_key_id(sig, keydata->key_id);
549 	__ops_sig_add_primary_user_id(sig, true);
550 	__ops_sig_hashed_subpackets_end(sig);
551 
552 	__ops_setup_memory_write(&cinfo_sig, &mem_sig, 128);
553 	__ops_write_sig(sig, &keydata->key.seckey.pubkey, &keydata->key.seckey, cinfo_sig);
554 
555 	/* add this packet to keydata */
556 
557 	sigpacket.length = __ops_memory_get_length(mem_sig);
558 	sigpacket.raw = __ops_memory_get_data(mem_sig);
559 
560 	/* add userid to keydata */
561 	__ops_add_signed_userid_to_keydata(keydata, userid, &sigpacket);
562 
563 	/* cleanup */
564 	__ops_create_sig_delete(sig);
565 	__ops_createinfo_delete(cinfo_userid);
566 	__ops_createinfo_delete(cinfo_sig);
567 	__ops_memory_free(mem_userid);
568 	__ops_memory_free(mem_sig);
569 
570 	return true;
571 }
572 
573 /**
574 \ingroup Core_Keys
575 \brief Initialise __ops_keydata_t
576 \param keydata Keydata to initialise
577 \param type OPS_PTAG_CT_PUBLIC_KEY or OPS_PTAG_CT_SECRET_KEY
578 */
579 void
580 __ops_keydata_init(__ops_keydata_t * keydata, const __ops_content_tag_t type)
581 {
582 	if (keydata->type != OPS_PTAG_CT_RESERVED) {
583 		(void) fprintf(stderr,
584 			"__ops_keydata_init: wrong keydata type\n");
585 	} else if (type != OPS_PTAG_CT_PUBLIC_KEY &&
586 		   type != OPS_PTAG_CT_SECRET_KEY) {
587 		(void) fprintf(stderr, "__ops_keydata_init: wrong type\n");
588 	} else {
589 		keydata->type = type;
590 	}
591 }
592 
593 /**
594     Example Usage:
595     \code
596 
597     // definition of variables
598     __ops_keyring_t keyring;
599     char* filename="~/.gnupg/pubring.gpg";
600 
601     // Read keyring from file
602     __ops_keyring_fileread(&keyring,filename);
603 
604     // do actions using keyring
605     ...
606 
607     // Free memory alloc-ed in __ops_keyring_fileread()
608     __ops_keyring_free(keyring);
609     \endcode
610 */
611 
612 
613 static          __ops_parse_cb_return_t
614 cb_keyring_read(const __ops_packet_t * pkt,
615 		__ops_callback_data_t * cbinfo)
616 {
617 	__OPS_USED(cbinfo);
618 
619 	switch (pkt->tag) {
620 	case OPS_PARSER_PTAG:
621 	case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:	/* we get these because we
622 						 * didn't prompt */
623 	case OPS_PTAG_CT_SIGNATURE_HEADER:
624 	case OPS_PTAG_CT_SIGNATURE_FOOTER:
625 	case OPS_PTAG_CT_SIGNATURE:
626 	case OPS_PTAG_CT_TRUST:
627 	case OPS_PARSER_ERRCODE:
628 		break;
629 
630 	default:
631 		;
632 	}
633 
634 	return OPS_RELEASE_MEMORY;
635 }
636 
637 /**
638    \ingroup HighLevel_KeyringRead
639 
640    \brief Reads a keyring from a file
641 
642    \param keyring Pointer to an existing __ops_keyring_t struct
643    \param armour true if file is armoured; else false
644    \param filename Filename of keyring to be read
645 
646    \return __ops true if OK; false on error
647 
648    \note Keyring struct must already exist.
649 
650    \note Can be used with either a public or secret keyring.
651 
652    \note You must call __ops_keyring_free() after usage to free alloc-ed memory.
653 
654    \note If you call this twice on the same keyring struct, without calling
655    __ops_keyring_free() between these calls, you will introduce a memory leak.
656 
657    \sa __ops_keyring_read_from_mem()
658    \sa __ops_keyring_free()
659 
660    Example code:
661    \code
662    __ops_keyring_t* keyring=calloc(1, sizeof(*keyring));
663    bool armoured=false;
664    __ops_keyring_fileread(keyring, armoured, "~/.gnupg/pubring.gpg");
665    ...
666    __ops_keyring_free(keyring);
667    free (keyring);
668 
669    \endcode
670 */
671 
672 bool
673 __ops_keyring_fileread(__ops_keyring_t * keyring, const bool armour, const char *filename)
674 {
675 	__ops_parseinfo_t *pinfo;
676 	int             fd;
677 	bool   res = true;
678 
679 	pinfo = __ops_parseinfo_new();
680 
681 	/* add this for the moment, */
682 	/*
683 	 * \todo need to fix the problems with reading signature subpackets
684 	 * later
685 	 */
686 
687 	/* __ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_RAW); */
688 	__ops_parse_options(pinfo, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
689 
690 #ifdef O_BINARY
691 	fd = open(filename, O_RDONLY | O_BINARY);
692 #else
693 	fd = open(filename, O_RDONLY);
694 #endif
695 	if (fd < 0) {
696 		__ops_parseinfo_delete(pinfo);
697 		perror(filename);
698 		return false;
699 	}
700 #ifdef USE_MMAP_FOR_FILES
701 	__ops_reader_set_mmap(pinfo, fd);
702 #else
703 	__ops_reader_set_fd(pinfo, fd);
704 #endif
705 
706 	__ops_parse_cb_set(pinfo, cb_keyring_read, NULL);
707 
708 	if (armour) {
709 		__ops_reader_push_dearmour(pinfo);
710 	}
711 	if (__ops_parse_and_accumulate(keyring, pinfo) == 0) {
712 		res = false;
713 	} else {
714 		res = true;
715 	}
716 	__ops_print_errors(__ops_parseinfo_get_errors(pinfo));
717 
718 	if (armour)
719 		__ops_reader_pop_dearmour(pinfo);
720 
721 	close(fd);
722 
723 	__ops_parseinfo_delete(pinfo);
724 
725 	return res;
726 }
727 
728 #if 0
729 /**
730    \ingroup HighLevel_KeyringRead
731 
732    \brief Reads a keyring from memory
733 
734    \param keyring Pointer to existing __ops_keyring_t struct
735    \param armour true if file is armoured; else false
736    \param mem Pointer to a __ops_memory_t struct containing keyring to be read
737 
738    \return __ops true if OK; false on error
739 
740    \note Keyring struct must already exist.
741 
742    \note Can be used with either a public or secret keyring.
743 
744    \note You must call __ops_keyring_free() after usage to free alloc-ed memory.
745 
746    \note If you call this twice on the same keyring struct, without calling
747    __ops_keyring_free() between these calls, you will introduce a memory leak.
748 
749    \sa __ops_keyring_fileread
750    \sa __ops_keyring_free
751 
752    Example code:
753    \code
754    __ops_memory_t* mem; // Filled with keyring packets
755    __ops_keyring_t* keyring=calloc(1, sizeof(*keyring));
756    bool armoured=false;
757    __ops_keyring_read_from_mem(keyring, armoured, mem);
758    ...
759    __ops_keyring_free(keyring);
760    free (keyring);
761    \endcode
762 */
763 static bool
764 __ops_keyring_read_from_mem(__ops_keyring_t * keyring, const bool armour, __ops_memory_t * mem)
765 {
766 	__ops_parseinfo_t *pinfo = NULL;
767 	bool   res = true;
768 
769 	pinfo = __ops_parseinfo_new();
770 	__ops_parse_options(pinfo, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED);
771 
772 	__ops_setup_memory_read(&pinfo, mem, NULL, cb_keyring_read, false);
773 
774 	if (armour) {
775 		__ops_reader_push_dearmour(pinfo);
776 	}
777 	res = (__ops_parse_and_accumulate(keyring, pinfo) != 0);
778 	__ops_print_errors(__ops_parseinfo_get_errors(pinfo));
779 
780 	if (armour)
781 		__ops_reader_pop_dearmour(pinfo);
782 
783 	/* don't call teardown_memory_read because memory was passed in */
784 	__ops_parseinfo_delete(pinfo);
785 
786 	return res;
787 }
788 #endif
789 
790 /**
791    \ingroup HighLevel_KeyringRead
792 
793    \brief Frees keyring's contents (but not keyring itself)
794 
795    \param keyring Keyring whose data is to be freed
796 
797    \note This does not free keyring itself, just the memory alloc-ed in it.
798  */
799 void
800 __ops_keyring_free(__ops_keyring_t * keyring)
801 {
802 	free(keyring->keys);
803 	keyring->keys = NULL;
804 	keyring->nkeys = 0;
805 	keyring->nkeys_allocated = 0;
806 }
807 
808 /**
809    \ingroup HighLevel_KeyringFind
810 
811    \brief Finds key in keyring from its Key ID
812 
813    \param keyring Keyring to be searched
814    \param keyid ID of required key
815 
816    \return Pointer to key, if found; NULL, if not found
817 
818    \note This returns a pointer to the key inside the given keyring, not a copy. Do not free it after use.
819 
820    Example code:
821    \code
822    void example(__ops_keyring_t* keyring)
823    {
824    __ops_keydata_t* keydata=NULL;
825    unsigned char keyid[OPS_KEY_ID_SIZE]; // value set elsewhere
826    keydata=__ops_keyring_find_key_by_id(keyring,keyid);
827    ...
828    }
829    \endcode
830 */
831 const __ops_keydata_t *
832 __ops_keyring_find_key_by_id(const __ops_keyring_t * keyring,
833 			   const unsigned char keyid[OPS_KEY_ID_SIZE])
834 {
835 	int	n;
836 
837 	for (n = 0; keyring && n < keyring->nkeys; n++) {
838 		if (__ops_get_debug_level(__FILE__)) {
839 			int	i;
840 
841 			printf("__ops_keyring_find_key_by_id: keyring keyid ");
842 			for (i = 0 ; i < OPS_KEY_ID_SIZE ; i++) {
843 				printf("%02x", keyring->keys[n].key_id[i]);
844 			}
845 			printf(", keyid ");
846 			for (i = 0 ; i < OPS_KEY_ID_SIZE ; i++) {
847 				printf("%02x", keyid[i]);
848 			}
849 			printf("\n");
850 		}
851 		if (memcmp(keyring->keys[n].key_id, keyid, OPS_KEY_ID_SIZE) == 0) {
852 			return &keyring->keys[n];
853 		}
854 		if (memcmp(&keyring->keys[n].key_id[OPS_KEY_ID_SIZE / 2],
855 				keyid, OPS_KEY_ID_SIZE / 2) == 0) {
856 			return &keyring->keys[n];
857 		}
858 	}
859 	return NULL;
860 }
861 
862 /* convert a string keyid into a binary keyid */
863 static void
864 str2keyid(const char *userid, unsigned char *keyid, size_t len)
865 {
866 	static const char	*uppers = "0123456789ABCDEF";
867 	static const char	*lowers = "0123456789abcdef";
868 	unsigned char		 hichar;
869 	unsigned char		 lochar;
870 	size_t			 j;
871 	const char		*hi;
872 	const char		*lo;
873 	int			 i;
874 
875 	for (i = j = 0 ; j < len && userid[i] && userid[i + 1] ; i += 2, j++) {
876 		if ((hi = strchr(uppers, userid[i])) == NULL) {
877 			if ((hi = strchr(lowers, userid[i])) == NULL) {
878 				break;
879 			}
880 			hichar = (hi - lowers);
881 		} else {
882 			hichar = (hi - uppers);
883 		}
884 		if ((lo = strchr(uppers, userid[i + 1])) == NULL) {
885 			if ((lo = strchr(lowers, userid[i + 1])) == NULL) {
886 				break;
887 			}
888 			lochar = (lo - lowers);
889 		} else {
890 			lochar = (lo - uppers);
891 		}
892 		keyid[j] = (hichar << 4) | (lochar);
893 	}
894 	keyid[j] = 0x0;
895 }
896 
897 /**
898    \ingroup HighLevel_KeyringFind
899 
900    \brief Finds key from its User ID
901 
902    \param keyring Keyring to be searched
903    \param userid User ID of required key
904 
905    \return Pointer to Key, if found; NULL, if not found
906 
907    \note This returns a pointer to the key inside the keyring, not a copy. Do not free it.
908 
909    Example code:
910    \code
911    void example(__ops_keyring_t* keyring)
912    {
913    __ops_keydata_t* keydata=NULL;
914    keydata=__ops_keyring_find_key_by_userid(keyring,"user@domain.com");
915    ...
916    }
917    \endcode
918 */
919 const __ops_keydata_t *
920 __ops_keyring_find_key_by_userid(const __ops_keyring_t *keyring,
921 			       const char *userid)
922 {
923 	const __ops_keydata_t	*kp;
924 	unsigned char		 keyid[OPS_KEY_ID_SIZE + 1];
925 	unsigned int    	 i = 0;
926 	size_t          	 len;
927 	char	                *cp;
928 	int             	 n = 0;
929 
930 	if (!keyring)
931 		return NULL;
932 
933 	len = strlen(userid);
934 	for (n = 0; n < keyring->nkeys; ++n) {
935 		for (i = 0; i < keyring->keys[n].nuids; i++) {
936 			if (__ops_get_debug_level(__FILE__)) {
937 				printf("[%d][%d] userid %s, last '%d'\n",
938 					n, i, keyring->keys[n].uids[i].user_id,
939 					keyring->keys[n].uids[i].user_id[len]);
940 			}
941 			if (strncmp((char *) keyring->keys[n].uids[i].user_id, userid, len) == 0 &&
942 			    keyring->keys[n].uids[i].user_id[len] == ' ') {
943 				return &keyring->keys[n];
944 			}
945 		}
946 	}
947 
948 	if (strchr(userid, '@') == NULL) {
949 		/* no '@' sign */
950 		/* first try userid as a keyid */
951 		(void) memset(keyid, 0x0, sizeof(keyid));
952 		str2keyid(userid, keyid, sizeof(keyid));
953 		if (__ops_get_debug_level(__FILE__)) {
954 			printf("userid \"%s\", keyid %02x%02x%02x%02x\n",
955 				userid,
956 				keyid[0], keyid[1], keyid[2], keyid[3]);
957 		}
958 		if ((kp = __ops_keyring_find_key_by_id(keyring, keyid)) != NULL) {
959 			return kp;
960 		}
961 		/* match on full name */
962 		for (n = 0; n < keyring->nkeys; n++) {
963 			for (i = 0; i < keyring->keys[n].nuids; i++) {
964 				if (__ops_get_debug_level(__FILE__)) {
965 					printf("keyid \"%s\" len %" PRIsize "u, keyid[len] '%c'\n",
966 					       (char *) keyring->keys[n].uids[i].user_id,
967 					       len, keyring->keys[n].uids[i].user_id[len]);
968 				}
969 				if (strncasecmp((char *) keyring->keys[n].uids[i].user_id, userid, len) == 0 &&
970 				    keyring->keys[n].uids[i].user_id[len] == ' ') {
971 					return &keyring->keys[n];
972 				}
973 			}
974 		}
975 	}
976 	/* match on <email@address> */
977 	for (n = 0; n < keyring->nkeys; n++) {
978 		for (i = 0; i < keyring->keys[n].nuids; i++) {
979 			/*
980 			 * look for the rightmost '<', in case there is one
981 			 * in the comment field
982 			 */
983 			if ((cp = strrchr((char *) keyring->keys[n].uids[i].user_id, '<')) != NULL) {
984 				if (__ops_get_debug_level(__FILE__)) {
985 					printf("cp ,%s, userid ,%s, len %" PRIsize "u ,%c,\n",
986 					       cp + 1, userid, len, *(cp + len + 1));
987 				}
988 				if (strncasecmp(cp + 1, userid, len) == 0 &&
989 				    *(cp + len + 1) == '>') {
990 					return &keyring->keys[n];
991 				}
992 			}
993 		}
994 	}
995 
996 	/* printf("end: n=%d,i=%d\n",n,i); */
997 	return NULL;
998 }
999 
1000 /**
1001    \ingroup HighLevel_KeyringList
1002 
1003    \brief Prints all keys in keyring to stdout.
1004 
1005    \param keyring Keyring to use
1006 
1007    \return none
1008 
1009    Example code:
1010    \code
1011    void example()
1012    {
1013    __ops_keyring_t* keyring=calloc(1, sizeof(*keyring));
1014    bool armoured=false;
1015    __ops_keyring_fileread(keyring, armoured, "~/.gnupg/pubring.gpg");
1016 
1017    __ops_keyring_list(keyring);
1018 
1019    __ops_keyring_free(keyring);
1020    free (keyring);
1021    }
1022    \endcode
1023 */
1024 
1025 void
1026 __ops_keyring_list(const __ops_keyring_t * keyring)
1027 {
1028 	int             n;
1029 	__ops_keydata_t  *key;
1030 
1031 	printf("%d keys\n", keyring->nkeys);
1032 	for (n = 0, key = &keyring->keys[n]; n < keyring->nkeys; ++n, ++key) {
1033 		if (__ops_is_key_secret(key)) {
1034 			__ops_print_seckeydata(key);
1035 		} else {
1036 			__ops_print_pubkeydata(key);
1037 		}
1038 		(void) fputc('\n', stdout);
1039 	}
1040 }
1041 
1042 unsigned
1043 __ops_get_keydata_content_type(const __ops_keydata_t * keydata)
1044 {
1045 	return keydata->type;
1046 }
1047 
1048 /* this interface isn't right - hook into callback for getting passphrase */
1049 int
1050 __ops_export_key(const __ops_keydata_t *keydata, unsigned char *passphrase)
1051 {
1052 	__ops_createinfo_t	*cinfo;
1053 	__ops_memory_t		*mem;
1054 
1055 	__ops_setup_memory_write(&cinfo, &mem, 128);
1056 	if (__ops_get_keydata_content_type(keydata) == OPS_PTAG_CT_PUBLIC_KEY) {
1057 		__ops_write_transferable_pubkey(keydata, true, cinfo);
1058 	} else {
1059 		__ops_write_transferable_seckey(keydata,
1060 				    passphrase,
1061 			    strlen((char *)passphrase), true, cinfo);
1062 	}
1063 	printf("%s", (char *) __ops_memory_get_data(mem));
1064 	__ops_teardown_memory_write(cinfo, mem);
1065 	return 1;
1066 }
1067