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