keyring.c revision 1.23
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.23 2009/12/05 07:08:18 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 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 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 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 char pass[MAX_PASSPHRASE_LENGTH]; 232 233 decrypt = __ops_callback_arg(cbinfo); 234 switch (pkt->tag) { 235 case OPS_PARSER_PTAG: 236 case OPS_PTAG_CT_USER_ID: 237 case OPS_PTAG_CT_SIGNATURE: 238 case OPS_PTAG_CT_SIGNATURE_HEADER: 239 case OPS_PTAG_CT_SIGNATURE_FOOTER: 240 case OPS_PTAG_CT_TRUST: 241 break; 242 243 case OPS_GET_PASSPHRASE: 244 (void) __ops_getpassphrase(NULL, pass, sizeof(pass)); 245 *content->skey_passphrase.passphrase = strdup(pass); 246 return OPS_KEEP_MEMORY; 247 248 case OPS_PARSER_ERRCODE: 249 switch (content->errcode.errcode) { 250 case OPS_E_P_MPI_FORMAT_ERROR: 251 /* Generally this means a bad passphrase */ 252 fprintf(stderr, "Bad passphrase!\n"); 253 return OPS_RELEASE_MEMORY; 254 255 case OPS_E_P_PACKET_CONSUMED: 256 /* And this is because of an error we've accepted */ 257 return OPS_RELEASE_MEMORY; 258 default: 259 break; 260 } 261 (void) fprintf(stderr, "parse error: %s\n", 262 __ops_errcode(content->errcode.errcode)); 263 return OPS_FINISHED; 264 265 case OPS_PARSER_ERROR: 266 fprintf(stderr, "parse error: %s\n", content->error.error); 267 return OPS_FINISHED; 268 269 case OPS_PTAG_CT_SECRET_KEY: 270 if ((decrypt->seckey = calloc(1, sizeof(*decrypt->seckey))) == NULL) { 271 (void) fprintf(stderr, "decrypt_cb: bad alloc\n"); 272 return OPS_FINISHED; 273 } 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_key_t *key) 300{ 301 __ops_stream_t *stream; 302 const int printerrors = 1; 303 decrypt_t decrypt; 304 305 (void) memset(&decrypt, 0x0, sizeof(decrypt)); 306 decrypt.key = key; 307 stream = __ops_new(sizeof(*stream)); 308 __ops_keydata_reader_set(stream, key); 309 __ops_set_callback(stream, decrypt_cb, &decrypt); 310 stream->readinfo.accumulate = 1; 311 __ops_parse(stream, !printerrors); 312 return decrypt.seckey; 313} 314 315/** 316\ingroup Core_Keys 317\brief Set secret key in content 318\param content Content to be set 319\param key Keydata to get secret key from 320*/ 321void 322__ops_set_seckey(__ops_contents_t *cont, const __ops_key_t *key) 323{ 324 *cont->get_seckey.seckey = &key->key.seckey; 325} 326 327/** 328\ingroup Core_Keys 329\brief Get Key ID from keydata 330\param key Keydata to get Key ID from 331\return Pointer to Key ID inside keydata 332*/ 333const unsigned char * 334__ops_get_key_id(const __ops_key_t *key) 335{ 336 return key->key_id; 337} 338 339/** 340\ingroup Core_Keys 341\brief How many User IDs in this key? 342\param key Keydata to check 343\return Num of user ids 344*/ 345unsigned 346__ops_get_userid_count(const __ops_key_t *key) 347{ 348 return key->uidc; 349} 350 351/** 352\ingroup Core_Keys 353\brief Get indexed user id from key 354\param key Key to get user id from 355\param index Which key to get 356\return Pointer to requested user id 357*/ 358const unsigned char * 359__ops_get_userid(const __ops_key_t *key, unsigned subscript) 360{ 361 return key->uids[subscript].userid; 362} 363 364/** 365 \ingroup HighLevel_Supported 366 \brief Checks whether key's algorithm and type are supported by OpenPGP::SDK 367 \param keydata Key to be checked 368 \return 1 if key algorithm and type are supported by OpenPGP::SDK; 0 if not 369*/ 370 371unsigned 372__ops_is_key_supported(const __ops_key_t *key) 373{ 374 if (key->type == OPS_PTAG_CT_PUBLIC_KEY) { 375 if (key->key.pubkey.alg == OPS_PKA_RSA) { 376 return 1; 377 } 378 } else if (key->type == OPS_PTAG_CT_PUBLIC_KEY) { 379 if (key->key.pubkey.alg == OPS_PKA_DSA) { 380 return 1; 381 } 382 } 383 return 0; 384} 385 386/* \todo check where userid pointers are copied */ 387/** 388\ingroup Core_Keys 389\brief Copy user id, including contents 390\param dst Destination User ID 391\param src Source User ID 392\note If dst already has a userid, it will be freed. 393*/ 394static __ops_userid_t * 395__ops_copy_userid(__ops_userid_t *dst, const __ops_userid_t *src) 396{ 397 size_t len = strlen((char *) src->userid); 398 399 if (dst->userid) { 400 free(dst->userid); 401 } 402 if ((dst->userid = calloc(1, len + 1)) == NULL) { 403 (void) fprintf(stderr, "__ops_copy_userid: bad alloc\n"); 404 } else { 405 (void) memcpy(dst->userid, src->userid, len); 406 } 407 return dst; 408} 409 410/* \todo check where pkt pointers are copied */ 411/** 412\ingroup Core_Keys 413\brief Copy packet, including contents 414\param dst Destination packet 415\param src Source packet 416\note If dst already has a packet, it will be freed. 417*/ 418static __ops_subpacket_t * 419__ops_copy_packet(__ops_subpacket_t *dst, const __ops_subpacket_t *src) 420{ 421 if (dst->raw) { 422 free(dst->raw); 423 } 424 if ((dst->raw = calloc(1, src->length)) == NULL) { 425 (void) fprintf(stderr, "__ops_copy_packet: bad alloc\n"); 426 } else { 427 dst->length = src->length; 428 (void) memcpy(dst->raw, src->raw, src->length); 429 } 430 return dst; 431} 432 433/** 434\ingroup Core_Keys 435\brief Add User ID to key 436\param key Key to which to add User ID 437\param userid User ID to add 438\return Pointer to new User ID 439*/ 440__ops_userid_t * 441__ops_add_userid(__ops_key_t *key, const __ops_userid_t *userid) 442{ 443 __ops_userid_t *uidp; 444 445 EXPAND_ARRAY(key, uid); 446 /* initialise new entry in array */ 447 uidp = &key->uids[key->uidc++]; 448 uidp->userid = NULL; 449 /* now copy it */ 450 return __ops_copy_userid(uidp, userid); 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_key_t *keydata, const __ops_subpacket_t *packet) 462{ 463 __ops_subpacket_t *subpktp; 464 465 EXPAND_ARRAY(keydata, packet); 466 467 /* initialise new entry in array */ 468 subpktp = &keydata->packets[keydata->packetc++]; 469 subpktp->length = 0; 470 subpktp->raw = NULL; 471 /* now copy it */ 472 return __ops_copy_packet(subpktp, packet); 473} 474 475/** 476\ingroup Core_Keys 477\brief Add signed User ID to key 478\param keydata Key to which to add signed User ID 479\param userid User ID to add 480\param sigpacket Packet to add 481*/ 482void 483__ops_add_signed_userid(__ops_key_t *keydata, 484 const __ops_userid_t *userid, 485 const __ops_subpacket_t *sigpacket) 486{ 487 __ops_subpacket_t *pkt; 488 __ops_userid_t *uid; 489 490 uid = __ops_add_userid(keydata, userid); 491 pkt = __ops_add_subpacket(keydata, sigpacket); 492 493 /* 494 * add entry in sigs array to link the userid and sigpacket 495 * and add ptr to it from the sigs array */ 496 EXPAND_ARRAY(keydata, sig); 497 498 /**setup new entry in array */ 499 keydata->sigs[keydata->sigc].userid = uid; 500 keydata->sigs[keydata->sigc].packet = pkt; 501 502 keydata->sigc++; 503} 504 505/** 506\ingroup Core_Keys 507\brief Add selfsigned User ID to key 508\param keydata Key to which to add user ID 509\param userid Self-signed User ID to add 510\return 1 if OK; else 0 511*/ 512unsigned 513__ops_add_selfsigned_userid(__ops_key_t *keydata, __ops_userid_t *userid) 514{ 515 __ops_create_sig_t *sig; 516 __ops_subpacket_t sigpacket; 517 __ops_memory_t *mem_userid = NULL; 518 __ops_output_t *useridoutput = NULL; 519 __ops_memory_t *mem_sig = NULL; 520 __ops_output_t *sigoutput = NULL; 521 522 /* 523 * create signature packet for this userid 524 */ 525 526 /* create userid pkt */ 527 __ops_setup_memory_write(&useridoutput, &mem_userid, 128); 528 __ops_write_struct_userid(useridoutput, userid); 529 530 /* create sig for this pkt */ 531 sig = __ops_create_sig_new(); 532 __ops_sig_start_key_sig(sig, &keydata->key.seckey.pubkey, userid, 533 OPS_CERT_POSITIVE); 534 __ops_add_birthtime(sig, time(NULL)); 535 __ops_add_issuer_keyid(sig, keydata->key_id); 536 __ops_add_primary_userid(sig, 1); 537 __ops_end_hashed_subpkts(sig); 538 539 __ops_setup_memory_write(&sigoutput, &mem_sig, 128); 540 __ops_write_sig(sigoutput, sig, &keydata->key.seckey.pubkey, 541 &keydata->key.seckey); 542 543 /* add this packet to keydata */ 544 sigpacket.length = __ops_mem_len(mem_sig); 545 sigpacket.raw = __ops_mem_data(mem_sig); 546 547 /* add userid to keydata */ 548 __ops_add_signed_userid(keydata, userid, &sigpacket); 549 550 /* cleanup */ 551 __ops_create_sig_delete(sig); 552 __ops_output_delete(useridoutput); 553 __ops_output_delete(sigoutput); 554 __ops_memory_free(mem_userid); 555 __ops_memory_free(mem_sig); 556 557 return 1; 558} 559 560/** 561\ingroup Core_Keys 562\brief Initialise __ops_key_t 563\param keydata Keydata to initialise 564\param type OPS_PTAG_CT_PUBLIC_KEY or OPS_PTAG_CT_SECRET_KEY 565*/ 566void 567__ops_keydata_init(__ops_key_t *keydata, const __ops_content_tag_t type) 568{ 569 if (keydata->type != OPS_PTAG_CT_RESERVED) { 570 (void) fprintf(stderr, 571 "__ops_keydata_init: wrong keydata type\n"); 572 } else if (type != OPS_PTAG_CT_PUBLIC_KEY && 573 type != OPS_PTAG_CT_SECRET_KEY) { 574 (void) fprintf(stderr, "__ops_keydata_init: wrong type\n"); 575 } else { 576 keydata->type = type; 577 } 578} 579 580 581static __ops_cb_ret_t 582cb_keyring_read(const __ops_packet_t *pkt, __ops_cbdata_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 break; 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, 631 const unsigned armour, 632 const char *filename) 633{ 634 __ops_stream_t *stream; 635 unsigned res = 1; 636 int fd; 637 638 stream = __ops_new(sizeof(*stream)); 639 640 /* add this for the moment, */ 641 /* 642 * \todo need to fix the problems with reading signature subpackets 643 * later 644 */ 645 646 /* __ops_parse_options(parse,OPS_PTAG_SS_ALL,OPS_PARSE_RAW); */ 647 __ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED); 648 649#ifdef O_BINARY 650 fd = open(filename, O_RDONLY | O_BINARY); 651#else 652 fd = open(filename, O_RDONLY); 653#endif 654 if (fd < 0) { 655 __ops_stream_delete(stream); 656 perror(filename); 657 return 0; 658 } 659#ifdef USE_MMAP_FOR_FILES 660 __ops_reader_set_mmap(stream, fd); 661#else 662 __ops_reader_set_fd(stream, fd); 663#endif 664 665 __ops_set_callback(stream, cb_keyring_read, NULL); 666 667 if (armour) { 668 __ops_reader_push_dearmour(stream); 669 } 670 res = __ops_parse_and_accumulate(keyring, stream); 671 __ops_print_errors(__ops_stream_get_errors(stream)); 672 673 if (armour) { 674 __ops_reader_pop_dearmour(stream); 675 } 676 677 (void)close(fd); 678 679 __ops_stream_delete(stream); 680 681 return res; 682} 683 684/** 685 \ingroup HighLevel_KeyringRead 686 687 \brief Reads a keyring from memory 688 689 \param keyring Pointer to existing __ops_keyring_t struct 690 \param armour 1 if file is armoured; else 0 691 \param mem Pointer to a __ops_memory_t struct containing keyring to be read 692 693 \return __ops 1 if OK; 0 on error 694 695 \note Keyring struct must already exist. 696 697 \note Can be used with either a public or secret keyring. 698 699 \note You must call __ops_keyring_free() after usage to free alloc-ed memory. 700 701 \note If you call this twice on the same keyring struct, without calling 702 __ops_keyring_free() between these calls, you will introduce a memory leak. 703 704 \sa __ops_keyring_fileread 705 \sa __ops_keyring_free 706*/ 707unsigned 708__ops_keyring_read_from_mem(__ops_io_t *io, 709 __ops_keyring_t *keyring, 710 const unsigned armour, 711 __ops_memory_t *mem) 712{ 713 __ops_stream_t *stream; 714 const unsigned noaccum = 0; 715 unsigned res; 716 717 stream = __ops_new(sizeof(*stream)); 718 __ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED); 719 __ops_setup_memory_read(io, &stream, mem, NULL, cb_keyring_read, 720 noaccum); 721 if (armour) { 722 __ops_reader_push_dearmour(stream); 723 } 724 res = (unsigned)__ops_parse_and_accumulate(keyring, stream); 725 __ops_print_errors(__ops_stream_get_errors(stream)); 726 if (armour) { 727 __ops_reader_pop_dearmour(stream); 728 } 729 /* don't call teardown_memory_read because memory was passed in */ 730 __ops_stream_delete(stream); 731 return res; 732} 733 734/** 735 \ingroup HighLevel_KeyringRead 736 737 \brief Frees keyring's contents (but not keyring itself) 738 739 \param keyring Keyring whose data is to be freed 740 741 \note This does not free keyring itself, just the memory alloc-ed in it. 742 */ 743void 744__ops_keyring_free(__ops_keyring_t *keyring) 745{ 746 (void)free(keyring->keys); 747 keyring->keys = NULL; 748 keyring->keyc = keyring->keyvsize = 0; 749} 750 751/** 752 \ingroup HighLevel_KeyringFind 753 754 \brief Finds key in keyring from its Key ID 755 756 \param keyring Keyring to be searched 757 \param keyid ID of required key 758 759 \return Pointer to key, if found; NULL, if not found 760 761 \note This returns a pointer to the key inside the given keyring, 762 not a copy. Do not free it after use. 763 764*/ 765const __ops_key_t * 766__ops_getkeybyid(__ops_io_t *io, const __ops_keyring_t *keyring, 767 const unsigned char keyid[OPS_KEY_ID_SIZE]) 768{ 769 unsigned n; 770 771 for (n = 0; keyring && n < keyring->keyc; n++) { 772 if (__ops_get_debug_level(__FILE__)) { 773 int i; 774 775 (void) fprintf(io->errs, 776 "__ops_getkeybyid: keyring keyid "); 777 for (i = 0 ; i < OPS_KEY_ID_SIZE ; i++) { 778 (void) fprintf(io->errs, "%02x", 779 keyring->keys[n].key_id[i]); 780 } 781 (void) fprintf(io->errs, ", keyid "); 782 for (i = 0 ; i < OPS_KEY_ID_SIZE ; i++) { 783 (void) fprintf(io->errs, "%02x", keyid[i]); 784 } 785 (void) fprintf(io->errs, "\n"); 786 } 787 if (memcmp(keyring->keys[n].key_id, keyid, 788 OPS_KEY_ID_SIZE) == 0) { 789 return &keyring->keys[n]; 790 } 791 if (memcmp(&keyring->keys[n].key_id[OPS_KEY_ID_SIZE / 2], 792 keyid, OPS_KEY_ID_SIZE / 2) == 0) { 793 return &keyring->keys[n]; 794 } 795 } 796 return NULL; 797} 798 799/* convert a string keyid into a binary keyid */ 800static void 801str2keyid(const char *userid, unsigned char *keyid, size_t len) 802{ 803 static const char *uppers = "0123456789ABCDEF"; 804 static const char *lowers = "0123456789abcdef"; 805 unsigned char hichar; 806 unsigned char lochar; 807 size_t j; 808 const char *hi; 809 const char *lo; 810 int i; 811 812 for (i = j = 0 ; j < len && userid[i] && userid[i + 1] ; i += 2, j++) { 813 if ((hi = strchr(uppers, userid[i])) == NULL) { 814 if ((hi = strchr(lowers, userid[i])) == NULL) { 815 break; 816 } 817 hichar = (hi - lowers); 818 } else { 819 hichar = (hi - uppers); 820 } 821 if ((lo = strchr(uppers, userid[i + 1])) == NULL) { 822 if ((lo = strchr(lowers, userid[i + 1])) == NULL) { 823 break; 824 } 825 lochar = (lo - lowers); 826 } else { 827 lochar = (lo - uppers); 828 } 829 keyid[j] = (hichar << 4) | (lochar); 830 } 831 keyid[j] = 0x0; 832} 833 834/** 835 \ingroup HighLevel_KeyringFind 836 837 \brief Finds key from its User ID 838 839 \param keyring Keyring to be searched 840 \param userid User ID of required key 841 842 \return Pointer to Key, if found; NULL, if not found 843 844 \note This returns a pointer to the key inside the keyring, not a 845 copy. Do not free it. 846 847*/ 848const __ops_key_t * 849__ops_getkeybyname(__ops_io_t *io, 850 const __ops_keyring_t *keyring, 851 const char *name) 852{ 853 const __ops_key_t *kp; 854 __ops_key_t *keyp; 855 __ops_userid_t *uidp; 856 unsigned char keyid[OPS_KEY_ID_SIZE + 1]; 857 unsigned int i = 0; 858 size_t len; 859 char *cp; 860 unsigned n; 861 862 if (!keyring) { 863 return NULL; 864 } 865 len = strlen(name); 866 n = 0; 867 for (keyp = &keyring->keys[n]; n < keyring->keyc; ++n, keyp++) { 868 for (i = 0, uidp = keyp->uids; i < keyp->uidc; i++, uidp++) { 869 if (__ops_get_debug_level(__FILE__)) { 870 (void) fprintf(io->outs, 871 "[%u][%u] name %s, last '%d'\n", 872 n, i, uidp->userid, 873 uidp->userid[len]); 874 } 875 if (strncmp((char *) uidp->userid, name, len) == 0 && 876 uidp->userid[len] == ' ') { 877 return keyp; 878 } 879 } 880 } 881 882 if (strchr(name, '@') == NULL) { 883 /* no '@' sign */ 884 /* first try name as a keyid */ 885 (void) memset(keyid, 0x0, sizeof(keyid)); 886 str2keyid(name, keyid, sizeof(keyid)); 887 if (__ops_get_debug_level(__FILE__)) { 888 (void) fprintf(io->outs, 889 "name \"%s\", keyid %02x%02x%02x%02x\n", 890 name, 891 keyid[0], keyid[1], keyid[2], keyid[3]); 892 } 893 if ((kp = __ops_getkeybyid(io, keyring, keyid)) != NULL) { 894 return kp; 895 } 896 /* match on full name */ 897 keyp = keyring->keys; 898 for (n = 0; n < keyring->keyc; ++n, keyp++) { 899 uidp = keyp->uids; 900 for (i = 0 ; i < keyp->uidc; i++, uidp++) { 901 if (__ops_get_debug_level(__FILE__)) { 902 (void) fprintf(io->outs, 903 "keyid \"%s\" len %" 904 PRIsize "u, keyid[len] '%c'\n", 905 (char *) uidp->userid, 906 len, uidp->userid[len]); 907 } 908 if (strncasecmp((char *) uidp->userid, name, 909 len) == 0 && uidp->userid[len] == ' ') { 910 return keyp; 911 } 912 } 913 } 914 } 915 /* match on <email@address> */ 916 keyp = keyring->keys; 917 for (n = 0; n < keyring->keyc; ++n, keyp++) { 918 for (i = 0, uidp = keyp->uids; i < keyp->uidc; i++, uidp++) { 919 /* 920 * look for the rightmost '<', in case there is one 921 * in the comment field 922 */ 923 cp = strrchr((char *) uidp->userid, '<'); 924 if (cp != NULL) { 925 if (__ops_get_debug_level(__FILE__)) { 926 (void) fprintf(io->errs, 927 "cp ,%s, name ,%s, len %" 928 PRIsize "u ,%c,\n", 929 cp + 1, 930 name, 931 len, 932 *(cp + len + 1)); 933 } 934 if (strncasecmp(cp + 1, name, len) == 0 && 935 *(cp + len + 1) == '>') { 936 return keyp; 937 } 938 } 939 } 940 } 941 return NULL; 942} 943 944/** 945 \ingroup HighLevel_KeyringList 946 947 \brief Prints all keys in keyring to stdout. 948 949 \param keyring Keyring to use 950 951 \return none 952*/ 953int 954__ops_keyring_list(__ops_io_t *io, const __ops_keyring_t *keyring) 955{ 956 __ops_key_t *key; 957 unsigned n; 958 959 (void) fprintf(io->res, "%u key%s\n", keyring->keyc, 960 (keyring->keyc == 1) ? "" : "s"); 961 for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) { 962 if (__ops_is_key_secret(key)) { 963 __ops_print_keydata(io, key, "sec", 964 &key->key.seckey.pubkey); 965 } else { 966 __ops_print_keydata(io, key, "pub", &key->key.pubkey); 967 } 968 (void) fputc('\n', io->res); 969 } 970 return 1; 971} 972 973static unsigned 974get_contents_type(const __ops_key_t *keydata) 975{ 976 return keydata->type; 977} 978 979/* this interface isn't right - hook into callback for getting passphrase */ 980int 981__ops_export_key(const __ops_key_t *keydata, unsigned char *passphrase) 982{ 983 __ops_output_t *output; 984 __ops_memory_t *mem; 985 986 __ops_setup_memory_write(&output, &mem, 128); 987 if (get_contents_type(keydata) == OPS_PTAG_CT_PUBLIC_KEY) { 988 __ops_write_xfer_pubkey(output, keydata, 1); 989 } else { 990 __ops_write_xfer_seckey(output, keydata, passphrase, 991 strlen((char *)passphrase), 1); 992 } 993 printf("%s", (char *) __ops_mem_data(mem)); 994 __ops_teardown_memory_write(output, mem); 995 return 1; 996} 997 998/* add a key to a public keyring */ 999int 1000__ops_add_to_pubring(__ops_keyring_t *keyring, const __ops_pubkey_t *pubkey) 1001{ 1002 __ops_key_t *key; 1003 1004 EXPAND_ARRAY(keyring, key); 1005 key = &keyring->keys[keyring->keyc++]; 1006 (void) memset(key, 0x0, sizeof(*key)); 1007 __ops_keyid(key->key_id, OPS_KEY_ID_SIZE, pubkey); 1008 __ops_fingerprint(&key->fingerprint, pubkey); 1009 key->type = OPS_PTAG_CT_PUBLIC_KEY; 1010 key->key.pubkey = *pubkey; 1011 return 1; 1012} 1013 1014/* add a key to a secret keyring */ 1015int 1016__ops_add_to_secring(__ops_keyring_t *keyring, const __ops_seckey_t *seckey) 1017{ 1018 const __ops_pubkey_t *pubkey; 1019 __ops_key_t *key; 1020 1021 EXPAND_ARRAY(keyring, key); 1022 key = &keyring->keys[keyring->keyc++]; 1023 (void) memset(key, 0x0, sizeof(*key)); 1024 pubkey = &seckey->pubkey; 1025 __ops_keyid(key->key_id, OPS_KEY_ID_SIZE, pubkey); 1026 __ops_fingerprint(&key->fingerprint, pubkey); 1027 key->type = OPS_PTAG_CT_SECRET_KEY; 1028 key->key.seckey = *seckey; 1029 return 1; 1030} 1031