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