keyring.c revision 1.3
11638Srgrimes/*
21638Srgrimes * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31638Srgrimes * All rights reserved.
41638Srgrimes * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
51638Srgrimes * their moral rights under the UK Copyright Design and Patents Act 1988 to
61638Srgrimes * be recorded as the authors of this copyright work.
71638Srgrimes *
81638Srgrimes * Licensed under the Apache License, Version 2.0 (the "License"); you may not
91638Srgrimes * use this file except in compliance with the License.
101638Srgrimes *
111638Srgrimes * You may obtain a copy of the License at
121638Srgrimes *     http://www.apache.org/licenses/LICENSE-2.0
131638Srgrimes *
141638Srgrimes * Unless required by applicable law or agreed to in writing, software
151638Srgrimes * distributed under the License is distributed on an "AS IS" BASIS,
161638Srgrimes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
171638Srgrimes *
181638Srgrimes * See the License for the specific language governing permissions and
191638Srgrimes * limitations under the License.
201638Srgrimes */
211638Srgrimes
221638Srgrimes/** \file
231638Srgrimes */
241638Srgrimes#include "config.h"
251638Srgrimes
261638Srgrimes#include "keyring.h"
271638Srgrimes#include "packet-parse.h"
281638Srgrimes#include "signature.h"
291638Srgrimes#include "netpgpsdk.h"
301638Srgrimes
311638Srgrimes#include "readerwriter.h"
321638Srgrimes#include "netpgpdefs.h"
331638Srgrimes#include "keyring_local.h"
341638Srgrimes#include "parse_local.h"
351638Srgrimes#include "validate.h"
361638Srgrimes
371638Srgrimes#include <stdlib.h>
381638Srgrimes#include <string.h>
391638Srgrimes
401638Srgrimes#ifdef HAVE_UNISTD_H
411638Srgrimes#include <unistd.h>
421638Srgrimes#endif
431638Srgrimes
441638Srgrimes#ifdef HAVE_TERMIOS_H
451638Srgrimes#include <termios.h>
461638Srgrimes#endif
471638Srgrimes
481638Srgrimes#include <fcntl.h>
491638Srgrimes
501638Srgrimes#ifdef HAVE_ASSERT_H
511638Srgrimes#include <assert.h>
521638Srgrimes#endif
531638Srgrimes
541638Srgrimes
551638Srgrimes/**
561638Srgrimes   \ingroup HighLevel_Keyring
571638Srgrimes
581638Srgrimes   \brief Creates a new __ops_keydata_t struct
591638Srgrimes
601638Srgrimes   \return A new __ops_keydata_t struct, initialised to zero.
611638Srgrimes
621638Srgrimes   \note The returned __ops_keydata_t struct must be freed after use with __ops_keydata_free.
631638Srgrimes*/
641638Srgrimes
651638Srgrimes__ops_keydata_t  *
661638Srgrimes__ops_keydata_new(void)
671638Srgrimes{
681638Srgrimes	return calloc(1, sizeof(__ops_keydata_t));
691638Srgrimes}
701638Srgrimes
711638Srgrimes
721638Srgrimes/**
731638Srgrimes \ingroup HighLevel_Keyring
741638Srgrimes
751638Srgrimes \brief Frees keydata and its memory
761638Srgrimes
771638Srgrimes \param keydata Key to be freed.
781638Srgrimes
791638Srgrimes \note This frees the keydata itself, as well as any other memory alloc-ed by it.
801638Srgrimes*/
811638Srgrimesvoid
821638Srgrimes__ops_keydata_free(__ops_keydata_t * keydata)
831638Srgrimes{
841638Srgrimes	unsigned        n;
851638Srgrimes
861638Srgrimes	for (n = 0; n < keydata->nuids; ++n)
871638Srgrimes		__ops_user_id_free(&keydata->uids[n]);
881638Srgrimes	free(keydata->uids);
891638Srgrimes	keydata->uids = NULL;
901638Srgrimes	keydata->nuids = 0;
911638Srgrimes
921638Srgrimes	for (n = 0; n < keydata->npackets; ++n)
931638Srgrimes		__ops_packet_free(&keydata->packets[n]);
941638Srgrimes	free(keydata->packets);
951638Srgrimes	keydata->packets = NULL;
961638Srgrimes	keydata->npackets = 0;
971638Srgrimes
981638Srgrimes	if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY)
991638Srgrimes		__ops_public_key_free(&keydata->key.pkey);
1001638Srgrimes	else
1011638Srgrimes		__ops_secret_key_free(&keydata->key.skey);
1021638Srgrimes
1031638Srgrimes	free(keydata);
1041638Srgrimes}
1051638Srgrimes
1061638Srgrimes/**
1071638Srgrimes \ingroup HighLevel_KeyGeneral
1081638Srgrimes
1091638Srgrimes \brief Returns the public key in the given keydata.
1101638Srgrimes \param keydata
1111638Srgrimes
1121638Srgrimes  \return Pointer to public key
1131638Srgrimes
1141638Srgrimes  \note This is not a copy, do not free it after use.
1151638Srgrimes*/
1161638Srgrimes
1171638Srgrimesconst __ops_public_key_t *
1181638Srgrimes__ops_get_public_key_from_data(const __ops_keydata_t * keydata)
1191638Srgrimes{
1201638Srgrimes	if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY)
1211638Srgrimes		return &keydata->key.pkey;
1221638Srgrimes	return &keydata->key.skey.public_key;
1231638Srgrimes}
1241638Srgrimes
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	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
175typedef struct {
176	const __ops_keydata_t *key;
177	char           *pphrase;
178	__ops_secret_key_t *skey;
179}               decrypt_t;
180
181static __ops_parse_cb_return_t
182decrypt_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
243done:
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*/
282void
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*/
294const 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*/
306unsigned
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*/
319const 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
332bool
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
373const __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*/
389void
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*/
408void
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*/
478void
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*/
510bool
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*/
567void
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
596static          __ops_parse_cb_return_t
597cb_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
655bool
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*/
746static 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 */
782void
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*/
814const __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 */
846static void
847str2keyid(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*/
902const __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
1008void
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
1024unsigned
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 */
1031int
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