keyring.c revision 1.18
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.18 2009/06/10 16:01:37 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_key_t struct 96 97 \return A new __ops_key_t struct, initialised to zero. 98 99 \note The returned __ops_key_t struct must be freed after use with __ops_keydata_free. 100*/ 101 102__ops_key_t * 103__ops_keydata_new(void) 104{ 105 return calloc(1, sizeof(__ops_key_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_key_t *keydata) 120{ 121 unsigned n; 122 123 for (n = 0; n < keydata->uidc; ++n) { 124 __ops_userid_free(&keydata->uids[n]); 125 } 126 (void) free(keydata->uids); 127 keydata->uids = NULL; 128 keydata->uidc = 0; 129 130 for (n = 0; n < keydata->packetc; ++n) { 131 __ops_subpacket_free(&keydata->packets[n]); 132 } 133 (void) free(keydata->packets); 134 keydata->packets = NULL; 135 keydata->packetc = 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_key_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_key_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_key_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_key_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_key_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 *content->skey_passphrase.passphrase = decrypt->passphrase; 244 return OPS_KEEP_MEMORY; 245 246 case OPS_PARSER_ERRCODE: 247 switch (content->errcode.errcode) { 248 case OPS_E_P_MPI_FORMAT_ERROR: 249 /* Generally this means a bad passphrase */ 250 fprintf(stderr, "Bad passphrase!\n"); 251 return OPS_RELEASE_MEMORY; 252 253 case OPS_E_P_PACKET_CONSUMED: 254 /* And this is because of an error we've accepted */ 255 return OPS_RELEASE_MEMORY; 256 default: 257 break; 258 } 259 (void) fprintf(stderr, "parse error: %s\n", 260 __ops_errcode(content->errcode.errcode)); 261 return OPS_FINISHED; 262 263 case OPS_PARSER_ERROR: 264 fprintf(stderr, "parse error: %s\n", content->error.error); 265 return OPS_FINISHED; 266 267 case OPS_PTAG_CT_SECRET_KEY: 268 decrypt->seckey = calloc(1, sizeof(*decrypt->seckey)); 269 decrypt->seckey->checkhash = calloc(1, OPS_CHECKHASH_SIZE); 270 *decrypt->seckey = content->seckey; 271 return OPS_KEEP_MEMORY; 272 273 case OPS_PARSER_PACKET_END: 274 /* nothing to do */ 275 break; 276 277 default: 278 fprintf(stderr, "Unexpected tag %d (0x%x)\n", pkt->tag, 279 pkt->tag); 280 return OPS_FINISHED; 281 } 282 283 return OPS_RELEASE_MEMORY; 284} 285 286/** 287\ingroup Core_Keys 288\brief Decrypts secret key from given keydata with given passphrase 289\param key Key from which to get secret key 290\param passphrase Passphrase to use to decrypt secret key 291\return secret key 292*/ 293__ops_seckey_t * 294__ops_decrypt_seckey(const __ops_key_t *key, const char *passphrase) 295{ 296 __ops_stream_t *stream; 297 const int printerrors = 1; 298 decrypt_t decrypt; 299 300 (void) memset(&decrypt, 0x0, sizeof(decrypt)); 301 decrypt.key = key; 302 decrypt.passphrase = strdup(passphrase); 303 stream = __ops_parseinfo_new(); 304 __ops_keydata_reader_set(stream, key); 305 __ops_set_callback(stream, decrypt_cb, &decrypt); 306 stream->readinfo.accumulate = 1; 307 __ops_parse(stream, !printerrors); 308 __ops_forget(decrypt.passphrase, strlen(decrypt.passphrase)); 309 (void) free(decrypt.passphrase); 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_contents_t *cont, const __ops_key_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_key_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_key_t *key) 345{ 346 return key->uidc; 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_key_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_key_t *key) 371{ 372 if (key->type == OPS_PTAG_CT_PUBLIC_KEY) { 373 if (key->key.pubkey.alg == OPS_PKA_RSA) { 374 return 1; 375 } 376 } else if (key->type == OPS_PTAG_CT_PUBLIC_KEY) { 377 if (key->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*/ 392static __ops_userid_t * 393__ops_copy_userid(__ops_userid_t *dst, const __ops_userid_t *src) 394{ 395 size_t len = strlen((char *) src->userid); 396 397 if (dst->userid) { 398 (void) free(dst->userid); 399 } 400 dst->userid = calloc(1, len + 1); 401 (void) memcpy(dst->userid, src->userid, len); 402 return dst; 403} 404 405/* \todo check where pkt pointers are copied */ 406/** 407\ingroup Core_Keys 408\brief Copy packet, including contents 409\param dst Destination packet 410\param src Source packet 411\note If dst already has a packet, it will be freed. 412*/ 413static __ops_subpacket_t * 414__ops_copy_packet(__ops_subpacket_t *dst, const __ops_subpacket_t *src) 415{ 416 if (dst->raw) { 417 (void) free(dst->raw); 418 } 419 dst->raw = calloc(1, src->length); 420 dst->length = src->length; 421 (void) memcpy(dst->raw, src->raw, src->length); 422 return dst; 423} 424 425/** 426\ingroup Core_Keys 427\brief Add User ID to key 428\param key Key to which to add User ID 429\param userid User ID to add 430\return Pointer to new User ID 431*/ 432__ops_userid_t * 433__ops_add_userid(__ops_key_t *key, const __ops_userid_t *userid) 434{ 435 __ops_userid_t *uidp = NULL; 436 437 EXPAND_ARRAY(key, uid); 438 /* initialise new entry in array */ 439 uidp = &key->uids[key->uidc++]; 440 uidp->userid = NULL; 441 /* now copy it */ 442 return __ops_copy_userid(uidp, userid); 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_subpacket_t * 453__ops_add_subpacket(__ops_key_t *keydata, const __ops_subpacket_t *packet) 454{ 455 __ops_subpacket_t *subpktp = NULL; 456 457 EXPAND_ARRAY(keydata, packet); 458 459 /* initialise new entry in array */ 460 subpktp = &keydata->packets[keydata->packetc++]; 461 subpktp->length = 0; 462 subpktp->raw = NULL; 463 /* now copy it */ 464 return __ops_copy_packet(subpktp, packet); 465} 466 467/** 468\ingroup Core_Keys 469\brief Add signed User ID to key 470\param keydata Key to which to add signed User ID 471\param userid User ID to add 472\param sigpacket Packet to add 473*/ 474void 475__ops_add_signed_userid(__ops_key_t *keydata, 476 const __ops_userid_t *userid, 477 const __ops_subpacket_t *sigpacket) 478{ 479 __ops_subpacket_t *pkt = NULL; 480 __ops_userid_t *uid = NULL; 481 482 uid = __ops_add_userid(keydata, userid); 483 pkt = __ops_add_subpacket(keydata, sigpacket); 484 485 /* 486 * add entry in sigs array to link the userid and sigpacket 487 * and add ptr to it from the sigs array */ 488 EXPAND_ARRAY(keydata, sig); 489 490 /**setup new entry in array */ 491 keydata->sigs[keydata->sigc].userid = uid; 492 keydata->sigs[keydata->sigc].packet = pkt; 493 494 keydata->sigc++; 495} 496 497/** 498\ingroup Core_Keys 499\brief Add selfsigned User ID to key 500\param keydata Key to which to add user ID 501\param userid Self-signed User ID to add 502\return 1 if OK; else 0 503*/ 504unsigned 505__ops_add_selfsigned_userid(__ops_key_t *keydata, __ops_userid_t *userid) 506{ 507 __ops_create_sig_t *sig = NULL; 508 __ops_subpacket_t sigpacket; 509 __ops_memory_t *mem_userid = NULL; 510 __ops_output_t *useridoutput = NULL; 511 __ops_memory_t *mem_sig = NULL; 512 __ops_output_t *sigoutput = NULL; 513 514 /* 515 * create signature packet for this userid 516 */ 517 518 /* create userid pkt */ 519 __ops_setup_memory_write(&useridoutput, &mem_userid, 128); 520 __ops_write_struct_userid(useridoutput, userid); 521 522 /* create sig for this pkt */ 523 sig = __ops_create_sig_new(); 524 __ops_sig_start_key_sig(sig, &keydata->key.seckey.pubkey, userid, 525 OPS_CERT_POSITIVE); 526 __ops_add_birthtime(sig, time(NULL)); 527 __ops_add_issuer_keyid(sig, keydata->key_id); 528 __ops_add_primary_userid(sig, 1); 529 __ops_end_hashed_subpkts(sig); 530 531 __ops_setup_memory_write(&sigoutput, &mem_sig, 128); 532 __ops_write_sig(sigoutput, sig, &keydata->key.seckey.pubkey, 533 &keydata->key.seckey); 534 535 /* add this packet to keydata */ 536 sigpacket.length = __ops_mem_len(mem_sig); 537 sigpacket.raw = __ops_mem_data(mem_sig); 538 539 /* add userid to keydata */ 540 __ops_add_signed_userid(keydata, userid, &sigpacket); 541 542 /* cleanup */ 543 __ops_create_sig_delete(sig); 544 __ops_output_delete(useridoutput); 545 __ops_output_delete(sigoutput); 546 __ops_memory_free(mem_userid); 547 __ops_memory_free(mem_sig); 548 549 return 1; 550} 551 552/** 553\ingroup Core_Keys 554\brief Initialise __ops_key_t 555\param keydata Keydata to initialise 556\param type OPS_PTAG_CT_PUBLIC_KEY or OPS_PTAG_CT_SECRET_KEY 557*/ 558void 559__ops_keydata_init(__ops_key_t *keydata, const __ops_content_tag_t type) 560{ 561 if (keydata->type != OPS_PTAG_CT_RESERVED) { 562 (void) fprintf(stderr, 563 "__ops_keydata_init: wrong keydata type\n"); 564 } else if (type != OPS_PTAG_CT_PUBLIC_KEY && 565 type != OPS_PTAG_CT_SECRET_KEY) { 566 (void) fprintf(stderr, "__ops_keydata_init: wrong type\n"); 567 } else { 568 keydata->type = type; 569 } 570} 571 572 573static __ops_cb_ret_t 574cb_keyring_read(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo) 575{ 576 __OPS_USED(cbinfo); 577 578 switch (pkt->tag) { 579 case OPS_PARSER_PTAG: 580 case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: /* we get these because we 581 * didn't prompt */ 582 case OPS_PTAG_CT_SIGNATURE_HEADER: 583 case OPS_PTAG_CT_SIGNATURE_FOOTER: 584 case OPS_PTAG_CT_SIGNATURE: 585 case OPS_PTAG_CT_TRUST: 586 case OPS_PARSER_ERRCODE: 587 break; 588 589 default: 590 ; 591 } 592 593 return OPS_RELEASE_MEMORY; 594} 595 596/** 597 \ingroup HighLevel_KeyringRead 598 599 \brief Reads a keyring from a file 600 601 \param keyring Pointer to an existing __ops_keyring_t struct 602 \param armour 1 if file is armoured; else 0 603 \param filename Filename of keyring to be read 604 605 \return __ops 1 if OK; 0 on error 606 607 \note Keyring struct must already exist. 608 609 \note Can be used with either a public or secret keyring. 610 611 \note You must call __ops_keyring_free() after usage to free alloc-ed memory. 612 613 \note If you call this twice on the same keyring struct, without calling 614 __ops_keyring_free() between these calls, you will introduce a memory leak. 615 616 \sa __ops_keyring_read_from_mem() 617 \sa __ops_keyring_free() 618 619*/ 620 621unsigned 622__ops_keyring_fileread(__ops_keyring_t *keyring, 623 const unsigned armour, 624 const char *filename) 625{ 626 __ops_stream_t *stream; 627 unsigned res = 1; 628 int fd; 629 630 stream = __ops_parseinfo_new(); 631 632 /* add this for the moment, */ 633 /* 634 * \todo need to fix the problems with reading signature subpackets 635 * later 636 */ 637 638 /* __ops_parse_options(parse,OPS_PTAG_SS_ALL,OPS_PARSE_RAW); */ 639 __ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED); 640 641#ifdef O_BINARY 642 fd = open(filename, O_RDONLY | O_BINARY); 643#else 644 fd = open(filename, O_RDONLY); 645#endif 646 if (fd < 0) { 647 __ops_parseinfo_delete(stream); 648 perror(filename); 649 return 0; 650 } 651#ifdef USE_MMAP_FOR_FILES 652 __ops_reader_set_mmap(stream, fd); 653#else 654 __ops_reader_set_fd(stream, fd); 655#endif 656 657 __ops_set_callback(stream, cb_keyring_read, NULL); 658 659 if (armour) { 660 __ops_reader_push_dearmour(stream); 661 } 662 if (__ops_parse_and_accumulate(keyring, stream) == 0) { 663 res = 0; 664 } else { 665 res = 1; 666 } 667 __ops_print_errors(__ops_parseinfo_get_errors(stream)); 668 669 if (armour) 670 __ops_reader_pop_dearmour(stream); 671 672 close(fd); 673 674 __ops_parseinfo_delete(stream); 675 676 return res; 677} 678 679/** 680 \ingroup HighLevel_KeyringRead 681 682 \brief Reads a keyring from memory 683 684 \param keyring Pointer to existing __ops_keyring_t struct 685 \param armour 1 if file is armoured; else 0 686 \param mem Pointer to a __ops_memory_t struct containing keyring to be read 687 688 \return __ops 1 if OK; 0 on error 689 690 \note Keyring struct must already exist. 691 692 \note Can be used with either a public or secret keyring. 693 694 \note You must call __ops_keyring_free() after usage to free alloc-ed memory. 695 696 \note If you call this twice on the same keyring struct, without calling 697 __ops_keyring_free() between these calls, you will introduce a memory leak. 698 699 \sa __ops_keyring_fileread 700 \sa __ops_keyring_free 701*/ 702unsigned 703__ops_keyring_read_from_mem(__ops_io_t *io, 704 __ops_keyring_t *keyring, 705 const unsigned armour, 706 __ops_memory_t *mem) 707{ 708 __ops_stream_t *stream = NULL; 709 const unsigned noaccum = 0; 710 unsigned res = 1; 711 712 stream = __ops_parseinfo_new(); 713 __ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED); 714 __ops_setup_memory_read(io, &stream, mem, NULL, cb_keyring_read, 715 noaccum); 716 if (armour) { 717 __ops_reader_push_dearmour(stream); 718 } 719 res = __ops_parse_and_accumulate(keyring, stream); 720 __ops_print_errors(__ops_parseinfo_get_errors(stream)); 721 if (armour) { 722 __ops_reader_pop_dearmour(stream); 723 } 724 /* don't call teardown_memory_read because memory was passed in */ 725 __ops_parseinfo_delete(stream); 726 return res; 727} 728 729/** 730 \ingroup HighLevel_KeyringRead 731 732 \brief Frees keyring's contents (but not keyring itself) 733 734 \param keyring Keyring whose data is to be freed 735 736 \note This does not free keyring itself, just the memory alloc-ed in it. 737 */ 738void 739__ops_keyring_free(__ops_keyring_t *keyring) 740{ 741 (void)free(keyring->keys); 742 keyring->keys = NULL; 743 keyring->keyc = keyring->keyvsize = 0; 744} 745 746/** 747 \ingroup HighLevel_KeyringFind 748 749 \brief Finds key in keyring from its Key ID 750 751 \param keyring Keyring to be searched 752 \param keyid ID of required key 753 754 \return Pointer to key, if found; NULL, if not found 755 756 \note This returns a pointer to the key inside the given keyring, 757 not a copy. Do not free it after use. 758 759*/ 760const __ops_key_t * 761__ops_getkeybyid(__ops_io_t *io, const __ops_keyring_t *keyring, 762 const unsigned char keyid[OPS_KEY_ID_SIZE]) 763{ 764 unsigned n; 765 766 for (n = 0; keyring && n < keyring->keyc; n++) { 767 if (__ops_get_debug_level(__FILE__)) { 768 int i; 769 770 (void) fprintf(io->errs, 771 "__ops_getkeybyid: keyring keyid "); 772 for (i = 0 ; i < OPS_KEY_ID_SIZE ; i++) { 773 (void) fprintf(io->errs, "%02x", 774 keyring->keys[n].key_id[i]); 775 } 776 (void) fprintf(io->errs, ", keyid "); 777 for (i = 0 ; i < OPS_KEY_ID_SIZE ; i++) { 778 (void) fprintf(io->errs, "%02x", keyid[i]); 779 } 780 (void) fprintf(io->errs, "\n"); 781 } 782 if (memcmp(keyring->keys[n].key_id, keyid, 783 OPS_KEY_ID_SIZE) == 0) { 784 return &keyring->keys[n]; 785 } 786 if (memcmp(&keyring->keys[n].key_id[OPS_KEY_ID_SIZE / 2], 787 keyid, OPS_KEY_ID_SIZE / 2) == 0) { 788 return &keyring->keys[n]; 789 } 790 } 791 return NULL; 792} 793 794/* convert a string keyid into a binary keyid */ 795static void 796str2keyid(const char *userid, unsigned char *keyid, size_t len) 797{ 798 static const char *uppers = "0123456789ABCDEF"; 799 static const char *lowers = "0123456789abcdef"; 800 unsigned char hichar; 801 unsigned char lochar; 802 size_t j; 803 const char *hi; 804 const char *lo; 805 int i; 806 807 for (i = j = 0 ; j < len && userid[i] && userid[i + 1] ; i += 2, j++) { 808 if ((hi = strchr(uppers, userid[i])) == NULL) { 809 if ((hi = strchr(lowers, userid[i])) == NULL) { 810 break; 811 } 812 hichar = (hi - lowers); 813 } else { 814 hichar = (hi - uppers); 815 } 816 if ((lo = strchr(uppers, userid[i + 1])) == NULL) { 817 if ((lo = strchr(lowers, userid[i + 1])) == NULL) { 818 break; 819 } 820 lochar = (lo - lowers); 821 } else { 822 lochar = (lo - uppers); 823 } 824 keyid[j] = (hichar << 4) | (lochar); 825 } 826 keyid[j] = 0x0; 827} 828 829/** 830 \ingroup HighLevel_KeyringFind 831 832 \brief Finds key from its User ID 833 834 \param keyring Keyring to be searched 835 \param userid User ID of required key 836 837 \return Pointer to Key, if found; NULL, if not found 838 839 \note This returns a pointer to the key inside the keyring, not a 840 copy. Do not free it. 841 842*/ 843const __ops_key_t * 844__ops_getkeybyname(__ops_io_t *io, 845 const __ops_keyring_t *keyring, 846 const char *name) 847{ 848 const __ops_key_t *kp; 849 __ops_key_t *keyp; 850 __ops_userid_t *uidp; 851 unsigned char keyid[OPS_KEY_ID_SIZE + 1]; 852 unsigned int i = 0; 853 size_t len; 854 char *cp; 855 unsigned n = 0; 856 857 if (!keyring) { 858 return NULL; 859 } 860 len = strlen(name); 861 n = 0; 862 for (keyp = &keyring->keys[n]; n < keyring->keyc; ++n, keyp++) { 863 for (i = 0, uidp = keyp->uids; i < keyp->uidc; i++, uidp++) { 864 if (__ops_get_debug_level(__FILE__)) { 865 (void) fprintf(io->outs, 866 "[%d][%d] name %s, last '%d'\n", 867 n, i, uidp->userid, 868 uidp->userid[len]); 869 } 870 if (strncmp((char *) uidp->userid, name, len) == 0 && 871 uidp->userid[len] == ' ') { 872 return keyp; 873 } 874 } 875 } 876 877 if (strchr(name, '@') == NULL) { 878 /* no '@' sign */ 879 /* first try name as a keyid */ 880 (void) memset(keyid, 0x0, sizeof(keyid)); 881 str2keyid(name, keyid, sizeof(keyid)); 882 if (__ops_get_debug_level(__FILE__)) { 883 (void) fprintf(io->outs, 884 "name \"%s\", keyid %02x%02x%02x%02x\n", 885 name, 886 keyid[0], keyid[1], keyid[2], keyid[3]); 887 } 888 if ((kp = __ops_getkeybyid(io, keyring, keyid)) != NULL) { 889 return kp; 890 } 891 /* match on full name */ 892 keyp = keyring->keys; 893 for (n = 0; n < keyring->keyc; ++n, keyp++) { 894 uidp = keyp->uids; 895 for (i = 0 ; i < keyp->uidc; i++, uidp++) { 896 if (__ops_get_debug_level(__FILE__)) { 897 (void) fprintf(io->outs, 898 "keyid \"%s\" len %" 899 PRIsize "u, keyid[len] '%c'\n", 900 (char *) uidp->userid, 901 len, uidp->userid[len]); 902 } 903 if (strncasecmp((char *) uidp->userid, name, 904 len) == 0 && uidp->userid[len] == ' ') { 905 return keyp; 906 } 907 } 908 } 909 } 910 /* match on <email@address> */ 911 keyp = keyring->keys; 912 for (n = 0; n < keyring->keyc; ++n, keyp++) { 913 for (i = 0, uidp = keyp->uids; i < keyp->uidc; i++, uidp++) { 914 /* 915 * look for the rightmost '<', in case there is one 916 * in the comment field 917 */ 918 cp = strrchr((char *) uidp->userid, '<'); 919 if (cp != NULL) { 920 if (__ops_get_debug_level(__FILE__)) { 921 (void) fprintf(io->errs, 922 "cp ,%s, name ,%s, len %" 923 PRIsize "u ,%c,\n", 924 cp + 1, 925 name, 926 len, 927 *(cp + len + 1)); 928 } 929 if (strncasecmp(cp + 1, name, len) == 0 && 930 *(cp + len + 1) == '>') { 931 return keyp; 932 } 933 } 934 } 935 } 936 return NULL; 937} 938 939/** 940 \ingroup HighLevel_KeyringList 941 942 \brief Prints all keys in keyring to stdout. 943 944 \param keyring Keyring to use 945 946 \return none 947*/ 948int 949__ops_keyring_list(__ops_io_t *io, const __ops_keyring_t *keyring) 950{ 951 __ops_key_t *key; 952 unsigned n; 953 954 (void) fprintf(io->res, "%d keys\n", keyring->keyc); 955 for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) { 956 if (__ops_is_key_secret(key)) { 957 __ops_print_seckeydata(io, key); 958 } else { 959 __ops_print_pubkeydata(io, key); 960 } 961 (void) fputc('\n', io->res); 962 } 963 return 1; 964} 965 966static unsigned 967get_contents_type(const __ops_key_t *keydata) 968{ 969 return keydata->type; 970} 971 972/* this interface isn't right - hook into callback for getting passphrase */ 973int 974__ops_export_key(const __ops_key_t *keydata, unsigned char *passphrase) 975{ 976 __ops_output_t *output; 977 __ops_memory_t *mem; 978 979 __ops_setup_memory_write(&output, &mem, 128); 980 if (get_contents_type(keydata) == OPS_PTAG_CT_PUBLIC_KEY) { 981 __ops_write_xfer_pubkey(output, keydata, 1); 982 } else { 983 __ops_write_xfer_seckey(output, keydata, passphrase, 984 strlen((char *)passphrase), 1); 985 } 986 printf("%s", (char *) __ops_mem_data(mem)); 987 __ops_teardown_memory_write(output, mem); 988 return 1; 989} 990