keyring.c revision 1.27
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.27 2010/02/06 02:24:33 agc Exp $"); 61#endif 62 63#ifdef HAVE_FCNTL_H 64#include <fcntl.h> 65#endif 66 67#include <regex.h> 68#include <stdlib.h> 69#include <string.h> 70 71#ifdef HAVE_TERMIOS_H 72#include <termios.h> 73#endif 74 75#ifdef HAVE_UNISTD_H 76#include <unistd.h> 77#endif 78 79#include "types.h" 80#include "keyring.h" 81#include "packet-parse.h" 82#include "signature.h" 83#include "netpgpsdk.h" 84#include "readerwriter.h" 85#include "netpgpdefs.h" 86#include "packet.h" 87#include "crypto.h" 88#include "validate.h" 89#include "netpgpdigest.h" 90 91 92 93/** 94 \ingroup HighLevel_Keyring 95 96 \brief Creates a new __ops_key_t struct 97 98 \return A new __ops_key_t struct, initialised to zero. 99 100 \note The returned __ops_key_t struct must be freed after use with __ops_keydata_free. 101*/ 102 103__ops_key_t * 104__ops_keydata_new(void) 105{ 106 return calloc(1, sizeof(__ops_key_t)); 107} 108 109 110/** 111 \ingroup HighLevel_Keyring 112 113 \brief Frees keydata and its memory 114 115 \param keydata Key to be freed. 116 117 \note This frees the keydata itself, as well as any other memory alloc-ed by it. 118*/ 119void 120__ops_keydata_free(__ops_key_t *keydata) 121{ 122 unsigned n; 123 124 for (n = 0; n < keydata->uidc; ++n) { 125 __ops_userid_free(&keydata->uids[n]); 126 } 127 free(keydata->uids); 128 keydata->uids = NULL; 129 keydata->uidc = 0; 130 131 for (n = 0; n < keydata->packetc; ++n) { 132 __ops_subpacket_free(&keydata->packets[n]); 133 } 134 free(keydata->packets); 135 keydata->packets = NULL; 136 keydata->packetc = 0; 137 138 if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) { 139 __ops_pubkey_free(&keydata->key.pubkey); 140 } else { 141 __ops_seckey_free(&keydata->key.seckey); 142 } 143 144 free(keydata); 145} 146 147/** 148 \ingroup HighLevel_KeyGeneral 149 150 \brief Returns the public key in the given keydata. 151 \param keydata 152 153 \return Pointer to public key 154 155 \note This is not a copy, do not free it after use. 156*/ 157 158const __ops_pubkey_t * 159__ops_get_pubkey(const __ops_key_t *keydata) 160{ 161 return (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) ? 162 &keydata->key.pubkey : 163 &keydata->key.seckey.pubkey; 164} 165 166/** 167\ingroup HighLevel_KeyGeneral 168 169\brief Check whether this is a secret key or not. 170*/ 171 172unsigned 173__ops_is_key_secret(const __ops_key_t *data) 174{ 175 return data->type != OPS_PTAG_CT_PUBLIC_KEY; 176} 177 178/** 179 \ingroup HighLevel_KeyGeneral 180 181 \brief Returns the secret key in the given keydata. 182 183 \note This is not a copy, do not free it after use. 184 185 \note This returns a const. If you need to be able to write to this 186 pointer, use __ops_get_writable_seckey 187*/ 188 189const __ops_seckey_t * 190__ops_get_seckey(const __ops_key_t *data) 191{ 192 return (data->type == OPS_PTAG_CT_SECRET_KEY) ? 193 &data->key.seckey : NULL; 194} 195 196/** 197 \ingroup HighLevel_KeyGeneral 198 199 \brief Returns the secret key in the given keydata. 200 201 \note This is not a copy, do not free it after use. 202 203 \note If you do not need to be able to modify this key, there is an 204 equivalent read-only function __ops_get_seckey. 205*/ 206 207__ops_seckey_t * 208__ops_get_writable_seckey(__ops_key_t *data) 209{ 210 return (data->type == OPS_PTAG_CT_SECRET_KEY) ? 211 &data->key.seckey : NULL; 212} 213 214/* utility function to zero out memory */ 215void 216__ops_forget(void *vp, unsigned size) 217{ 218 (void) memset(vp, 0x0, size); 219} 220 221typedef struct { 222 FILE *passfp; 223 const __ops_key_t *key; 224 char *passphrase; 225 __ops_seckey_t *seckey; 226} decrypt_t; 227 228static __ops_cb_ret_t 229decrypt_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo) 230{ 231 const __ops_contents_t *content = &pkt->u; 232 decrypt_t *decrypt; 233 char pass[MAX_PASSPHRASE_LENGTH]; 234 235 decrypt = __ops_callback_arg(cbinfo); 236 switch (pkt->tag) { 237 case OPS_PARSER_PTAG: 238 case OPS_PTAG_CT_USER_ID: 239 case OPS_PTAG_CT_SIGNATURE: 240 case OPS_PTAG_CT_SIGNATURE_HEADER: 241 case OPS_PTAG_CT_SIGNATURE_FOOTER: 242 case OPS_PTAG_CT_TRUST: 243 break; 244 245 case OPS_GET_PASSPHRASE: 246 (void) __ops_getpassphrase(decrypt->passfp, pass, sizeof(pass)); 247 *content->skey_passphrase.passphrase = strdup(pass); 248 __ops_forget(pass, sizeof(pass)); 249 return OPS_KEEP_MEMORY; 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 if ((decrypt->seckey = calloc(1, sizeof(*decrypt->seckey))) == NULL) { 274 (void) fprintf(stderr, "decrypt_cb: bad alloc\n"); 275 return OPS_FINISHED; 276 } 277 decrypt->seckey->checkhash = calloc(1, OPS_CHECKHASH_SIZE); 278 *decrypt->seckey = content->seckey; 279 return OPS_KEEP_MEMORY; 280 281 case OPS_PARSER_PACKET_END: 282 /* nothing to do */ 283 break; 284 285 default: 286 fprintf(stderr, "Unexpected tag %d (0x%x)\n", pkt->tag, 287 pkt->tag); 288 return OPS_FINISHED; 289 } 290 291 return OPS_RELEASE_MEMORY; 292} 293 294/** 295\ingroup Core_Keys 296\brief Decrypts secret key from given keydata with given passphrase 297\param key Key from which to get secret key 298\param passphrase Passphrase to use to decrypt secret key 299\return secret key 300*/ 301__ops_seckey_t * 302__ops_decrypt_seckey(const __ops_key_t *key, void *passfp) 303{ 304 __ops_stream_t *stream; 305 const int printerrors = 1; 306 decrypt_t decrypt; 307 308 (void) memset(&decrypt, 0x0, sizeof(decrypt)); 309 decrypt.key = key; 310 decrypt.passfp = passfp; 311 stream = __ops_new(sizeof(*stream)); 312 __ops_keydata_reader_set(stream, key); 313 __ops_set_callback(stream, decrypt_cb, &decrypt); 314 stream->readinfo.accumulate = 1; 315 __ops_parse(stream, !printerrors); 316 return decrypt.seckey; 317} 318 319/** 320\ingroup Core_Keys 321\brief Set secret key in content 322\param content Content to be set 323\param key Keydata to get secret key from 324*/ 325void 326__ops_set_seckey(__ops_contents_t *cont, const __ops_key_t *key) 327{ 328 *cont->get_seckey.seckey = &key->key.seckey; 329} 330 331/** 332\ingroup Core_Keys 333\brief Get Key ID from keydata 334\param key Keydata to get Key ID from 335\return Pointer to Key ID inside keydata 336*/ 337const unsigned char * 338__ops_get_key_id(const __ops_key_t *key) 339{ 340 return key->key_id; 341} 342 343/** 344\ingroup Core_Keys 345\brief How many User IDs in this key? 346\param key Keydata to check 347\return Num of user ids 348*/ 349unsigned 350__ops_get_userid_count(const __ops_key_t *key) 351{ 352 return key->uidc; 353} 354 355/** 356\ingroup Core_Keys 357\brief Get indexed user id from key 358\param key Key to get user id from 359\param index Which key to get 360\return Pointer to requested user id 361*/ 362const unsigned char * 363__ops_get_userid(const __ops_key_t *key, unsigned subscript) 364{ 365 return key->uids[subscript].userid; 366} 367 368/** 369 \ingroup HighLevel_Supported 370 \brief Checks whether key's algorithm and type are supported by OpenPGP::SDK 371 \param keydata Key to be checked 372 \return 1 if key algorithm and type are supported by OpenPGP::SDK; 0 if not 373*/ 374 375unsigned 376__ops_is_key_supported(const __ops_key_t *key) 377{ 378 if (key->type == OPS_PTAG_CT_PUBLIC_KEY) { 379 if (key->key.pubkey.alg == OPS_PKA_RSA) { 380 return 1; 381 } 382 } else if (key->type == OPS_PTAG_CT_PUBLIC_KEY) { 383 if (key->key.pubkey.alg == OPS_PKA_DSA) { 384 return 1; 385 } 386 } 387 return 0; 388} 389 390/* \todo check where userid pointers are copied */ 391/** 392\ingroup Core_Keys 393\brief Copy user id, including contents 394\param dst Destination User ID 395\param src Source User ID 396\note If dst already has a userid, it will be freed. 397*/ 398static __ops_userid_t * 399__ops_copy_userid(__ops_userid_t *dst, const __ops_userid_t *src) 400{ 401 size_t len = strlen((char *) src->userid); 402 403 if (dst->userid) { 404 free(dst->userid); 405 } 406 if ((dst->userid = calloc(1, len + 1)) == NULL) { 407 (void) fprintf(stderr, "__ops_copy_userid: bad alloc\n"); 408 } else { 409 (void) memcpy(dst->userid, src->userid, len); 410 } 411 return dst; 412} 413 414/* \todo check where pkt pointers are copied */ 415/** 416\ingroup Core_Keys 417\brief Copy packet, including contents 418\param dst Destination packet 419\param src Source packet 420\note If dst already has a packet, it will be freed. 421*/ 422static __ops_subpacket_t * 423__ops_copy_packet(__ops_subpacket_t *dst, const __ops_subpacket_t *src) 424{ 425 if (dst->raw) { 426 free(dst->raw); 427 } 428 if ((dst->raw = calloc(1, src->length)) == NULL) { 429 (void) fprintf(stderr, "__ops_copy_packet: bad alloc\n"); 430 } else { 431 dst->length = src->length; 432 (void) memcpy(dst->raw, src->raw, src->length); 433 } 434 return dst; 435} 436 437/** 438\ingroup Core_Keys 439\brief Add User ID to key 440\param key Key to which to add User ID 441\param userid User ID to add 442\return Pointer to new User ID 443*/ 444__ops_userid_t * 445__ops_add_userid(__ops_key_t *key, const __ops_userid_t *userid) 446{ 447 __ops_userid_t *uidp; 448 449 EXPAND_ARRAY(key, uid); 450 /* initialise new entry in array */ 451 uidp = &key->uids[key->uidc++]; 452 uidp->userid = NULL; 453 /* now copy it */ 454 return __ops_copy_userid(uidp, userid); 455} 456 457/** 458\ingroup Core_Keys 459\brief Add packet to key 460\param keydata Key to which to add packet 461\param packet Packet to add 462\return Pointer to new packet 463*/ 464__ops_subpacket_t * 465__ops_add_subpacket(__ops_key_t *keydata, const __ops_subpacket_t *packet) 466{ 467 __ops_subpacket_t *subpktp; 468 469 EXPAND_ARRAY(keydata, packet); 470 471 /* initialise new entry in array */ 472 subpktp = &keydata->packets[keydata->packetc++]; 473 subpktp->length = 0; 474 subpktp->raw = NULL; 475 /* now copy it */ 476 return __ops_copy_packet(subpktp, packet); 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_key_t *keydata, 488 const __ops_userid_t *userid, 489 const __ops_subpacket_t *sigpacket) 490{ 491 __ops_subpacket_t *pkt; 492 __ops_userid_t *uid; 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, sig); 501 502 /**setup new entry in array */ 503 keydata->sigs[keydata->sigc].userid = uid; 504 keydata->sigs[keydata->sigc].packet = pkt; 505 506 keydata->sigc++; 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_key_t *keydata, __ops_userid_t *userid) 518{ 519 __ops_create_sig_t *sig; 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_key_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_key_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 break; 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_stream_t *stream; 639 unsigned res = 1; 640 int fd; 641 642 stream = __ops_new(sizeof(*stream)); 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(stream, 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_stream_delete(stream); 660 perror(filename); 661 return 0; 662 } 663#ifdef USE_MMAP_FOR_FILES 664 __ops_reader_set_mmap(stream, fd); 665#else 666 __ops_reader_set_fd(stream, fd); 667#endif 668 669 __ops_set_callback(stream, cb_keyring_read, NULL); 670 671 if (armour) { 672 __ops_reader_push_dearmour(stream); 673 } 674 res = __ops_parse_and_accumulate(keyring, stream); 675 __ops_print_errors(__ops_stream_get_errors(stream)); 676 677 if (armour) { 678 __ops_reader_pop_dearmour(stream); 679 } 680 681 (void)close(fd); 682 683 __ops_stream_delete(stream); 684 685 return res; 686} 687 688/** 689 \ingroup HighLevel_KeyringRead 690 691 \brief Reads a keyring from memory 692 693 \param keyring Pointer to existing __ops_keyring_t struct 694 \param armour 1 if file is armoured; else 0 695 \param mem Pointer to a __ops_memory_t struct containing keyring to be read 696 697 \return __ops 1 if OK; 0 on error 698 699 \note Keyring struct must already exist. 700 701 \note Can be used with either a public or secret keyring. 702 703 \note You must call __ops_keyring_free() after usage to free alloc-ed memory. 704 705 \note If you call this twice on the same keyring struct, without calling 706 __ops_keyring_free() between these calls, you will introduce a memory leak. 707 708 \sa __ops_keyring_fileread 709 \sa __ops_keyring_free 710*/ 711unsigned 712__ops_keyring_read_from_mem(__ops_io_t *io, 713 __ops_keyring_t *keyring, 714 const unsigned armour, 715 __ops_memory_t *mem) 716{ 717 __ops_stream_t *stream; 718 const unsigned noaccum = 0; 719 unsigned res; 720 721 stream = __ops_new(sizeof(*stream)); 722 __ops_parse_options(stream, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED); 723 __ops_setup_memory_read(io, &stream, mem, NULL, cb_keyring_read, 724 noaccum); 725 if (armour) { 726 __ops_reader_push_dearmour(stream); 727 } 728 res = (unsigned)__ops_parse_and_accumulate(keyring, stream); 729 __ops_print_errors(__ops_stream_get_errors(stream)); 730 if (armour) { 731 __ops_reader_pop_dearmour(stream); 732 } 733 /* don't call teardown_memory_read because memory was passed in */ 734 __ops_stream_delete(stream); 735 return res; 736} 737 738/** 739 \ingroup HighLevel_KeyringRead 740 741 \brief Frees keyring's contents (but not keyring itself) 742 743 \param keyring Keyring whose data is to be freed 744 745 \note This does not free keyring itself, just the memory alloc-ed in it. 746 */ 747void 748__ops_keyring_free(__ops_keyring_t *keyring) 749{ 750 (void)free(keyring->keys); 751 keyring->keys = NULL; 752 keyring->keyc = keyring->keyvsize = 0; 753} 754 755/* simple function to print out a binary keyid */ 756void 757__ops_pkeyid(FILE *fp, const unsigned char *keyid, size_t size) 758{ 759 size_t i; 760 761 for (i = 0 ; i < size ; i++) { 762 (void) fprintf(fp, "%02x", keyid[i]); 763 } 764} 765 766/** 767 \ingroup HighLevel_KeyringFind 768 769 \brief Finds key in keyring from its Key ID 770 771 \param keyring Keyring to be searched 772 \param keyid ID of required key 773 774 \return Pointer to key, if found; NULL, if not found 775 776 \note This returns a pointer to the key inside the given keyring, 777 not a copy. Do not free it after use. 778 779*/ 780const __ops_key_t * 781__ops_getkeybyid(__ops_io_t *io, const __ops_keyring_t *keyring, 782 const unsigned char *keyid, unsigned *from) 783{ 784 for ( ; keyring && *from < keyring->keyc; *from += 1) { 785 if (__ops_get_debug_level(__FILE__)) { 786 (void) fprintf(io->errs, 787 "__ops_getkeybyid: keyring keyid "); 788 __ops_pkeyid(io->errs, keyring->keys[*from].key_id, 789 OPS_KEY_ID_SIZE); 790 (void) fprintf(io->errs, ", keyid "); 791 __ops_pkeyid(io->errs, keyid, OPS_KEY_ID_SIZE); 792 (void) fprintf(io->errs, "\n"); 793 } 794 if (memcmp(keyring->keys[*from].key_id, keyid, 795 OPS_KEY_ID_SIZE) == 0) { 796 return &keyring->keys[*from]; 797 } 798 if (memcmp(&keyring->keys[*from].key_id[OPS_KEY_ID_SIZE / 2], 799 keyid, OPS_KEY_ID_SIZE / 2) == 0) { 800 return &keyring->keys[*from]; 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/* return the next key which matches, starting searching at *from */ 842static const __ops_key_t * 843getkeybyname(__ops_io_t *io, 844 const __ops_keyring_t *keyring, 845 const char *name, 846 unsigned *from) 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 unsigned savedstart; 854 regex_t r; 855 size_t len; 856 857 if (!keyring) { 858 return NULL; 859 } 860 len = strlen(name); 861 if (__ops_get_debug_level(__FILE__)) { 862 (void) fprintf(io->outs, "[%u] name '%s', len %zu\n", 863 *from, name, len); 864 } 865 /* first try name as a keyid */ 866 (void) memset(keyid, 0x0, sizeof(keyid)); 867 str2keyid(name, keyid, sizeof(keyid)); 868 if (__ops_get_debug_level(__FILE__)) { 869 (void) fprintf(io->outs, 870 "name \"%s\", keyid %02x%02x%02x%02x\n", 871 name, 872 keyid[0], keyid[1], keyid[2], keyid[3]); 873 } 874 savedstart = *from; 875 if ((kp = __ops_getkeybyid(io, keyring, keyid, from)) != NULL) { 876 return kp; 877 } 878 *from = savedstart; 879 if (__ops_get_debug_level(__FILE__)) { 880 (void) fprintf(io->outs, "regex match '%s' from %u\n", 881 name, *from); 882 } 883 /* match on full name or email address as a NOSUB, ICASE regexp */ 884 (void) regcomp(&r, name, REG_EXTENDED | REG_ICASE); 885 for (keyp = &keyring->keys[*from]; *from < keyring->keyc; *from += 1, keyp++) { 886 uidp = keyp->uids; 887 for (i = 0 ; i < keyp->uidc; i++, uidp++) { 888 if (__ops_get_debug_level(__FILE__)) { 889 (void) fprintf(io->outs, 890 "keyid \"%s\" len %" 891 PRIsize "u, keyid[len] '%c'\n", 892 (char *) uidp->userid, 893 len, uidp->userid[len]); 894 } 895 if (regexec(&r, (char *)uidp->userid, 0, NULL, 0) == 0) { 896 regfree(&r); 897 return keyp; 898 } 899 } 900 } 901 regfree(&r); 902 return NULL; 903} 904 905/** 906 \ingroup HighLevel_KeyringFind 907 908 \brief Finds key from its User ID 909 910 \param keyring Keyring to be searched 911 \param userid User ID of required key 912 913 \return Pointer to Key, if found; NULL, if not found 914 915 \note This returns a pointer to the key inside the keyring, not a 916 copy. Do not free it. 917 918*/ 919const __ops_key_t * 920__ops_getkeybyname(__ops_io_t *io, 921 const __ops_keyring_t *keyring, 922 const char *name) 923{ 924 unsigned from; 925 926 from = 0; 927 return getkeybyname(io, keyring, name, &from); 928} 929 930const __ops_key_t * 931__ops_getnextkeybyname(__ops_io_t *io, 932 const __ops_keyring_t *keyring, 933 const char *name, 934 unsigned *n) 935{ 936 return getkeybyname(io, keyring, name, n); 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, "%u key%s\n", keyring->keyc, 955 (keyring->keyc == 1) ? "" : "s"); 956 for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) { 957 if (__ops_is_key_secret(key)) { 958 __ops_print_keydata(io, key, "sec", 959 &key->key.seckey.pubkey); 960 } else { 961 __ops_print_keydata(io, key, "pub", &key->key.pubkey); 962 } 963 (void) fputc('\n', io->res); 964 } 965 return 1; 966} 967 968/* this interface isn't right - hook into callback for getting passphrase */ 969int 970__ops_export_key(const __ops_key_t *keydata, unsigned char *passphrase) 971{ 972 __ops_output_t *output; 973 __ops_memory_t *mem; 974 975 __ops_setup_memory_write(&output, &mem, 128); 976 if (keydata->type == OPS_PTAG_CT_PUBLIC_KEY) { 977 __ops_write_xfer_pubkey(output, keydata, 1); 978 } else { 979 __ops_write_xfer_seckey(output, keydata, passphrase, 980 strlen((char *)passphrase), 1); 981 } 982 printf("%s", (char *) __ops_mem_data(mem)); 983 __ops_teardown_memory_write(output, mem); 984 return 1; 985} 986 987/* add a key to a public keyring */ 988int 989__ops_add_to_pubring(__ops_keyring_t *keyring, const __ops_pubkey_t *pubkey) 990{ 991 __ops_key_t *key; 992 993 EXPAND_ARRAY(keyring, key); 994 key = &keyring->keys[keyring->keyc++]; 995 (void) memset(key, 0x0, sizeof(*key)); 996 __ops_keyid(key->key_id, OPS_KEY_ID_SIZE, pubkey); 997 __ops_fingerprint(&key->fingerprint, pubkey); 998 key->type = OPS_PTAG_CT_PUBLIC_KEY; 999 key->key.pubkey = *pubkey; 1000 return 1; 1001} 1002 1003/* add a key to a secret keyring */ 1004int 1005__ops_add_to_secring(__ops_keyring_t *keyring, const __ops_seckey_t *seckey) 1006{ 1007 const __ops_pubkey_t *pubkey; 1008 __ops_key_t *key; 1009 1010 EXPAND_ARRAY(keyring, key); 1011 key = &keyring->keys[keyring->keyc++]; 1012 (void) memset(key, 0x0, sizeof(*key)); 1013 pubkey = &seckey->pubkey; 1014 __ops_keyid(key->key_id, OPS_KEY_ID_SIZE, pubkey); 1015 __ops_fingerprint(&key->fingerprint, pubkey); 1016 key->type = OPS_PTAG_CT_SECRET_KEY; 1017 key->key.seckey = *seckey; 1018 return 1; 1019} 1020 1021/* append one keyring to another */ 1022int 1023__ops_append_keyring(__ops_keyring_t *keyring, __ops_keyring_t *newring) 1024{ 1025 unsigned i; 1026 1027 for (i = 0 ; i < newring->keyc ; i++) { 1028 EXPAND_ARRAY(keyring, key); 1029 (void) memcpy(&keyring->keys[keyring->keyc], &newring->keys[i], 1030 sizeof(newring->keys[i])); 1031 keyring->keyc += 1; 1032 } 1033 return 1; 1034} 1035