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