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