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