1178825Sdfr/* 2233294Sstas * Copyright (c) 2007 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "hx_locl.h" 35178825Sdfr 36178825Sdfr#ifdef HAVE_FRAMEWORK_SECURITY 37178825Sdfr 38178825Sdfr#include <Security/Security.h> 39178825Sdfr 40178825Sdfr/* Missing function decls in pre Leopard */ 41178825Sdfr#ifdef NEED_SECKEYGETCSPHANDLE_PROTO 42178825SdfrOSStatus SecKeyGetCSPHandle(SecKeyRef, CSSM_CSP_HANDLE *); 43178825SdfrOSStatus SecKeyGetCredentials(SecKeyRef, CSSM_ACL_AUTHORIZATION_TAG, 44178825Sdfr int, const CSSM_ACCESS_CREDENTIALS **); 45178825Sdfr#define kSecCredentialTypeDefault 0 46233294Sstas#define CSSM_SIZE uint32_t 47178825Sdfr#endif 48178825Sdfr 49178825Sdfr 50178825Sdfrstatic int 51178825SdfrgetAttribute(SecKeychainItemRef itemRef, SecItemAttr item, 52178825Sdfr SecKeychainAttributeList **attrs) 53233294Sstas{ 54178825Sdfr SecKeychainAttributeInfo attrInfo; 55178825Sdfr UInt32 attrFormat = 0; 56178825Sdfr OSStatus ret; 57178825Sdfr 58178825Sdfr *attrs = NULL; 59178825Sdfr 60178825Sdfr attrInfo.count = 1; 61178825Sdfr attrInfo.tag = &item; 62178825Sdfr attrInfo.format = &attrFormat; 63233294Sstas 64178825Sdfr ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL, 65178825Sdfr attrs, NULL, NULL); 66178825Sdfr if (ret) 67178825Sdfr return EINVAL; 68178825Sdfr return 0; 69178825Sdfr} 70178825Sdfr 71178825Sdfr 72178825Sdfr/* 73178825Sdfr * 74178825Sdfr */ 75178825Sdfr 76178825Sdfrstruct kc_rsa { 77178825Sdfr SecKeychainItemRef item; 78178825Sdfr size_t keysize; 79178825Sdfr}; 80178825Sdfr 81178825Sdfr 82178825Sdfrstatic int 83178825Sdfrkc_rsa_public_encrypt(int flen, 84178825Sdfr const unsigned char *from, 85178825Sdfr unsigned char *to, 86178825Sdfr RSA *rsa, 87178825Sdfr int padding) 88178825Sdfr{ 89178825Sdfr return -1; 90178825Sdfr} 91178825Sdfr 92178825Sdfrstatic int 93178825Sdfrkc_rsa_public_decrypt(int flen, 94178825Sdfr const unsigned char *from, 95178825Sdfr unsigned char *to, 96178825Sdfr RSA *rsa, 97178825Sdfr int padding) 98178825Sdfr{ 99178825Sdfr return -1; 100178825Sdfr} 101178825Sdfr 102178825Sdfr 103178825Sdfrstatic int 104233294Sstaskc_rsa_private_encrypt(int flen, 105178825Sdfr const unsigned char *from, 106178825Sdfr unsigned char *to, 107178825Sdfr RSA *rsa, 108178825Sdfr int padding) 109178825Sdfr{ 110178825Sdfr struct kc_rsa *kc = RSA_get_app_data(rsa); 111178825Sdfr 112178825Sdfr CSSM_RETURN cret; 113178825Sdfr OSStatus ret; 114178825Sdfr const CSSM_ACCESS_CREDENTIALS *creds; 115178825Sdfr SecKeyRef privKeyRef = (SecKeyRef)kc->item; 116178825Sdfr CSSM_CSP_HANDLE cspHandle; 117178825Sdfr const CSSM_KEY *cssmKey; 118178825Sdfr CSSM_CC_HANDLE sigHandle = 0; 119178825Sdfr CSSM_DATA sig, in; 120178825Sdfr int fret = 0; 121178825Sdfr 122233294Sstas if (padding != RSA_PKCS1_PADDING) 123233294Sstas return -1; 124178825Sdfr 125178825Sdfr cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey); 126178825Sdfr if(cret) abort(); 127178825Sdfr 128178825Sdfr cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle); 129178825Sdfr if(cret) abort(); 130178825Sdfr 131178825Sdfr ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_SIGN, 132178825Sdfr kSecCredentialTypeDefault, &creds); 133178825Sdfr if(ret) abort(); 134178825Sdfr 135178825Sdfr ret = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA, 136178825Sdfr creds, cssmKey, &sigHandle); 137178825Sdfr if(ret) abort(); 138178825Sdfr 139178825Sdfr in.Data = (uint8 *)from; 140178825Sdfr in.Length = flen; 141233294Sstas 142178825Sdfr sig.Data = (uint8 *)to; 143178825Sdfr sig.Length = kc->keysize; 144233294Sstas 145178825Sdfr cret = CSSM_SignData(sigHandle, &in, 1, CSSM_ALGID_NONE, &sig); 146178825Sdfr if(cret) { 147178825Sdfr /* cssmErrorString(cret); */ 148178825Sdfr fret = -1; 149178825Sdfr } else 150178825Sdfr fret = sig.Length; 151178825Sdfr 152178825Sdfr if(sigHandle) 153178825Sdfr CSSM_DeleteContext(sigHandle); 154178825Sdfr 155178825Sdfr return fret; 156178825Sdfr} 157178825Sdfr 158178825Sdfrstatic int 159178825Sdfrkc_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to, 160178825Sdfr RSA * rsa, int padding) 161178825Sdfr{ 162233294Sstas struct kc_rsa *kc = RSA_get_app_data(rsa); 163233294Sstas 164233294Sstas CSSM_RETURN cret; 165233294Sstas OSStatus ret; 166233294Sstas const CSSM_ACCESS_CREDENTIALS *creds; 167233294Sstas SecKeyRef privKeyRef = (SecKeyRef)kc->item; 168233294Sstas CSSM_CSP_HANDLE cspHandle; 169233294Sstas const CSSM_KEY *cssmKey; 170233294Sstas CSSM_CC_HANDLE handle = 0; 171233294Sstas CSSM_DATA out, in, rem; 172233294Sstas int fret = 0; 173233294Sstas CSSM_SIZE outlen = 0; 174233294Sstas char remdata[1024]; 175233294Sstas 176233294Sstas if (padding != RSA_PKCS1_PADDING) 177233294Sstas return -1; 178233294Sstas 179233294Sstas cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey); 180233294Sstas if(cret) abort(); 181233294Sstas 182233294Sstas cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle); 183233294Sstas if(cret) abort(); 184233294Sstas 185233294Sstas ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_DECRYPT, 186233294Sstas kSecCredentialTypeDefault, &creds); 187233294Sstas if(ret) abort(); 188233294Sstas 189233294Sstas 190233294Sstas ret = CSSM_CSP_CreateAsymmetricContext (cspHandle, 191233294Sstas CSSM_ALGID_RSA, 192233294Sstas creds, 193233294Sstas cssmKey, 194233294Sstas CSSM_PADDING_PKCS1, 195233294Sstas &handle); 196233294Sstas if(ret) abort(); 197233294Sstas 198233294Sstas in.Data = (uint8 *)from; 199233294Sstas in.Length = flen; 200233294Sstas 201233294Sstas out.Data = (uint8 *)to; 202233294Sstas out.Length = kc->keysize; 203233294Sstas 204233294Sstas rem.Data = (uint8 *)remdata; 205233294Sstas rem.Length = sizeof(remdata); 206233294Sstas 207233294Sstas cret = CSSM_DecryptData(handle, &in, 1, &out, 1, &outlen, &rem); 208233294Sstas if(cret) { 209233294Sstas /* cssmErrorString(cret); */ 210233294Sstas fret = -1; 211233294Sstas } else 212233294Sstas fret = out.Length; 213233294Sstas 214233294Sstas if(handle) 215233294Sstas CSSM_DeleteContext(handle); 216233294Sstas 217233294Sstas return fret; 218178825Sdfr} 219178825Sdfr 220233294Sstasstatic int 221178825Sdfrkc_rsa_init(RSA *rsa) 222178825Sdfr{ 223178825Sdfr return 1; 224178825Sdfr} 225178825Sdfr 226178825Sdfrstatic int 227178825Sdfrkc_rsa_finish(RSA *rsa) 228178825Sdfr{ 229178825Sdfr struct kc_rsa *kc_rsa = RSA_get_app_data(rsa); 230178825Sdfr CFRelease(kc_rsa->item); 231178825Sdfr memset(kc_rsa, 0, sizeof(*kc_rsa)); 232178825Sdfr free(kc_rsa); 233178825Sdfr return 1; 234178825Sdfr} 235178825Sdfr 236178825Sdfrstatic const RSA_METHOD kc_rsa_pkcs1_method = { 237178825Sdfr "hx509 Keychain PKCS#1 RSA", 238178825Sdfr kc_rsa_public_encrypt, 239178825Sdfr kc_rsa_public_decrypt, 240178825Sdfr kc_rsa_private_encrypt, 241178825Sdfr kc_rsa_private_decrypt, 242178825Sdfr NULL, 243178825Sdfr NULL, 244178825Sdfr kc_rsa_init, 245178825Sdfr kc_rsa_finish, 246178825Sdfr 0, 247178825Sdfr NULL, 248178825Sdfr NULL, 249178825Sdfr NULL 250178825Sdfr}; 251178825Sdfr 252178825Sdfrstatic int 253178825Sdfrset_private_key(hx509_context context, 254178825Sdfr SecKeychainItemRef itemRef, 255178825Sdfr hx509_cert cert) 256178825Sdfr{ 257178825Sdfr struct kc_rsa *kc; 258178825Sdfr hx509_private_key key; 259178825Sdfr RSA *rsa; 260178825Sdfr int ret; 261178825Sdfr 262233294Sstas ret = hx509_private_key_init(&key, NULL, NULL); 263178825Sdfr if (ret) 264178825Sdfr return ret; 265178825Sdfr 266178825Sdfr kc = calloc(1, sizeof(*kc)); 267178825Sdfr if (kc == NULL) 268178825Sdfr _hx509_abort("out of memory"); 269178825Sdfr 270178825Sdfr kc->item = itemRef; 271178825Sdfr 272178825Sdfr rsa = RSA_new(); 273178825Sdfr if (rsa == NULL) 274178825Sdfr _hx509_abort("out of memory"); 275178825Sdfr 276178825Sdfr /* Argh, fake modulus since OpenSSL API is on crack */ 277178825Sdfr { 278178825Sdfr SecKeychainAttributeList *attrs = NULL; 279178825Sdfr uint32_t size; 280178825Sdfr void *data; 281178825Sdfr 282178825Sdfr rsa->n = BN_new(); 283178825Sdfr if (rsa->n == NULL) abort(); 284178825Sdfr 285178825Sdfr ret = getAttribute(itemRef, kSecKeyKeySizeInBits, &attrs); 286178825Sdfr if (ret) abort(); 287178825Sdfr 288178825Sdfr size = *(uint32_t *)attrs->attr[0].data; 289178825Sdfr SecKeychainItemFreeAttributesAndData(attrs, NULL); 290178825Sdfr 291178825Sdfr kc->keysize = (size + 7) / 8; 292178825Sdfr 293178825Sdfr data = malloc(kc->keysize); 294178825Sdfr memset(data, 0xe0, kc->keysize); 295178825Sdfr BN_bin2bn(data, kc->keysize, rsa->n); 296178825Sdfr free(data); 297178825Sdfr } 298178825Sdfr rsa->e = NULL; 299178825Sdfr 300178825Sdfr RSA_set_method(rsa, &kc_rsa_pkcs1_method); 301178825Sdfr ret = RSA_set_app_data(rsa, kc); 302178825Sdfr if (ret != 1) 303178825Sdfr _hx509_abort("RSA_set_app_data"); 304178825Sdfr 305233294Sstas hx509_private_key_assign_rsa(key, rsa); 306178825Sdfr _hx509_cert_assign_key(cert, key); 307178825Sdfr 308178825Sdfr return 0; 309178825Sdfr} 310178825Sdfr 311178825Sdfr/* 312178825Sdfr * 313178825Sdfr */ 314178825Sdfr 315178825Sdfrstruct ks_keychain { 316178825Sdfr int anchors; 317178825Sdfr SecKeychainRef keychain; 318178825Sdfr}; 319178825Sdfr 320178825Sdfrstatic int 321178825Sdfrkeychain_init(hx509_context context, 322178825Sdfr hx509_certs certs, void **data, int flags, 323178825Sdfr const char *residue, hx509_lock lock) 324178825Sdfr{ 325178825Sdfr struct ks_keychain *ctx; 326178825Sdfr 327178825Sdfr ctx = calloc(1, sizeof(*ctx)); 328178825Sdfr if (ctx == NULL) { 329178825Sdfr hx509_clear_error_string(context); 330178825Sdfr return ENOMEM; 331178825Sdfr } 332178825Sdfr 333178825Sdfr if (residue) { 334178825Sdfr if (strcasecmp(residue, "system-anchors") == 0) { 335178825Sdfr ctx->anchors = 1; 336178825Sdfr } else if (strncasecmp(residue, "FILE:", 5) == 0) { 337178825Sdfr OSStatus ret; 338178825Sdfr 339178825Sdfr ret = SecKeychainOpen(residue + 5, &ctx->keychain); 340178825Sdfr if (ret != noErr) { 341233294Sstas hx509_set_error_string(context, 0, ENOENT, 342178825Sdfr "Failed to open %s", residue); 343178825Sdfr return ENOENT; 344178825Sdfr } 345178825Sdfr } else { 346233294Sstas hx509_set_error_string(context, 0, ENOENT, 347178825Sdfr "Unknown subtype %s", residue); 348178825Sdfr return ENOENT; 349178825Sdfr } 350178825Sdfr } 351178825Sdfr 352178825Sdfr *data = ctx; 353178825Sdfr return 0; 354178825Sdfr} 355178825Sdfr 356178825Sdfr/* 357178825Sdfr * 358178825Sdfr */ 359178825Sdfr 360178825Sdfrstatic int 361178825Sdfrkeychain_free(hx509_certs certs, void *data) 362178825Sdfr{ 363178825Sdfr struct ks_keychain *ctx = data; 364178825Sdfr if (ctx->keychain) 365178825Sdfr CFRelease(ctx->keychain); 366178825Sdfr memset(ctx, 0, sizeof(*ctx)); 367178825Sdfr free(ctx); 368178825Sdfr return 0; 369178825Sdfr} 370178825Sdfr 371178825Sdfr/* 372178825Sdfr * 373178825Sdfr */ 374178825Sdfr 375178825Sdfrstruct iter { 376178825Sdfr hx509_certs certs; 377178825Sdfr void *cursor; 378178825Sdfr SecKeychainSearchRef searchRef; 379178825Sdfr}; 380178825Sdfr 381233294Sstasstatic int 382178825Sdfrkeychain_iter_start(hx509_context context, 383178825Sdfr hx509_certs certs, void *data, void **cursor) 384178825Sdfr{ 385178825Sdfr struct ks_keychain *ctx = data; 386178825Sdfr struct iter *iter; 387178825Sdfr 388178825Sdfr iter = calloc(1, sizeof(*iter)); 389178825Sdfr if (iter == NULL) { 390178825Sdfr hx509_set_error_string(context, 0, ENOMEM, "out of memory"); 391178825Sdfr return ENOMEM; 392178825Sdfr } 393178825Sdfr 394178825Sdfr if (ctx->anchors) { 395178825Sdfr CFArrayRef anchors; 396178825Sdfr int ret; 397178825Sdfr int i; 398178825Sdfr 399233294Sstas ret = hx509_certs_init(context, "MEMORY:ks-file-create", 400178825Sdfr 0, NULL, &iter->certs); 401178825Sdfr if (ret) { 402178825Sdfr free(iter); 403178825Sdfr return ret; 404178825Sdfr } 405178825Sdfr 406178825Sdfr ret = SecTrustCopyAnchorCertificates(&anchors); 407178825Sdfr if (ret != 0) { 408178825Sdfr hx509_certs_free(&iter->certs); 409178825Sdfr free(iter); 410233294Sstas hx509_set_error_string(context, 0, ENOMEM, 411178825Sdfr "Can't get trust anchors from Keychain"); 412178825Sdfr return ENOMEM; 413178825Sdfr } 414178825Sdfr for (i = 0; i < CFArrayGetCount(anchors); i++) { 415233294Sstas SecCertificateRef cr; 416178825Sdfr hx509_cert cert; 417178825Sdfr CSSM_DATA cssm; 418178825Sdfr 419178825Sdfr cr = (SecCertificateRef)CFArrayGetValueAtIndex(anchors, i); 420178825Sdfr 421178825Sdfr SecCertificateGetData(cr, &cssm); 422178825Sdfr 423178825Sdfr ret = hx509_cert_init_data(context, cssm.Data, cssm.Length, &cert); 424178825Sdfr if (ret) 425178825Sdfr continue; 426178825Sdfr 427178825Sdfr ret = hx509_certs_add(context, iter->certs, cert); 428178825Sdfr hx509_cert_free(cert); 429178825Sdfr } 430178825Sdfr CFRelease(anchors); 431178825Sdfr } 432178825Sdfr 433178825Sdfr if (iter->certs) { 434178825Sdfr int ret; 435178825Sdfr ret = hx509_certs_start_seq(context, iter->certs, &iter->cursor); 436178825Sdfr if (ret) { 437178825Sdfr hx509_certs_free(&iter->certs); 438178825Sdfr free(iter); 439178825Sdfr return ret; 440178825Sdfr } 441178825Sdfr } else { 442178825Sdfr OSStatus ret; 443178825Sdfr 444178825Sdfr ret = SecKeychainSearchCreateFromAttributes(ctx->keychain, 445178825Sdfr kSecCertificateItemClass, 446178825Sdfr NULL, 447178825Sdfr &iter->searchRef); 448178825Sdfr if (ret) { 449178825Sdfr free(iter); 450233294Sstas hx509_set_error_string(context, 0, ret, 451178825Sdfr "Failed to start search for attributes"); 452178825Sdfr return ENOMEM; 453178825Sdfr } 454178825Sdfr } 455178825Sdfr 456178825Sdfr *cursor = iter; 457178825Sdfr return 0; 458178825Sdfr} 459178825Sdfr 460178825Sdfr/* 461178825Sdfr * 462178825Sdfr */ 463178825Sdfr 464178825Sdfrstatic int 465178825Sdfrkeychain_iter(hx509_context context, 466178825Sdfr hx509_certs certs, void *data, void *cursor, hx509_cert *cert) 467178825Sdfr{ 468178825Sdfr SecKeychainAttributeList *attrs = NULL; 469178825Sdfr SecKeychainAttributeInfo attrInfo; 470178825Sdfr UInt32 attrFormat[1] = { 0 }; 471178825Sdfr SecKeychainItemRef itemRef; 472178825Sdfr SecItemAttr item[1]; 473178825Sdfr struct iter *iter = cursor; 474178825Sdfr OSStatus ret; 475178825Sdfr UInt32 len; 476178825Sdfr void *ptr = NULL; 477178825Sdfr 478178825Sdfr if (iter->certs) 479178825Sdfr return hx509_certs_next_cert(context, iter->certs, iter->cursor, cert); 480178825Sdfr 481178825Sdfr *cert = NULL; 482178825Sdfr 483178825Sdfr ret = SecKeychainSearchCopyNext(iter->searchRef, &itemRef); 484178825Sdfr if (ret == errSecItemNotFound) 485178825Sdfr return 0; 486178825Sdfr else if (ret != 0) 487178825Sdfr return EINVAL; 488233294Sstas 489178825Sdfr /* 490178825Sdfr * Pick out certificate and matching "keyid" 491178825Sdfr */ 492178825Sdfr 493178825Sdfr item[0] = kSecPublicKeyHashItemAttr; 494178825Sdfr 495178825Sdfr attrInfo.count = 1; 496178825Sdfr attrInfo.tag = item; 497178825Sdfr attrInfo.format = attrFormat; 498233294Sstas 499178825Sdfr ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL, 500178825Sdfr &attrs, &len, &ptr); 501178825Sdfr if (ret) 502178825Sdfr return EINVAL; 503178825Sdfr 504178825Sdfr ret = hx509_cert_init_data(context, ptr, len, cert); 505178825Sdfr if (ret) 506178825Sdfr goto out; 507178825Sdfr 508233294Sstas /* 509178825Sdfr * Find related private key if there is one by looking at 510178825Sdfr * kSecPublicKeyHashItemAttr == kSecKeyLabel 511178825Sdfr */ 512178825Sdfr { 513178825Sdfr SecKeychainSearchRef search; 514178825Sdfr SecKeychainAttribute attrKeyid; 515178825Sdfr SecKeychainAttributeList attrList; 516178825Sdfr 517178825Sdfr attrKeyid.tag = kSecKeyLabel; 518178825Sdfr attrKeyid.length = attrs->attr[0].length; 519178825Sdfr attrKeyid.data = attrs->attr[0].data; 520233294Sstas 521178825Sdfr attrList.count = 1; 522178825Sdfr attrList.attr = &attrKeyid; 523178825Sdfr 524178825Sdfr ret = SecKeychainSearchCreateFromAttributes(NULL, 525178825Sdfr CSSM_DL_DB_RECORD_PRIVATE_KEY, 526178825Sdfr &attrList, 527178825Sdfr &search); 528178825Sdfr if (ret) { 529178825Sdfr ret = 0; 530178825Sdfr goto out; 531178825Sdfr } 532178825Sdfr 533178825Sdfr ret = SecKeychainSearchCopyNext(search, &itemRef); 534178825Sdfr CFRelease(search); 535178825Sdfr if (ret == errSecItemNotFound) { 536178825Sdfr ret = 0; 537178825Sdfr goto out; 538178825Sdfr } else if (ret) { 539178825Sdfr ret = EINVAL; 540178825Sdfr goto out; 541178825Sdfr } 542178825Sdfr set_private_key(context, itemRef, *cert); 543178825Sdfr } 544178825Sdfr 545178825Sdfrout: 546178825Sdfr SecKeychainItemFreeAttributesAndData(attrs, ptr); 547178825Sdfr 548178825Sdfr return ret; 549178825Sdfr} 550178825Sdfr 551178825Sdfr/* 552178825Sdfr * 553178825Sdfr */ 554178825Sdfr 555178825Sdfrstatic int 556178825Sdfrkeychain_iter_end(hx509_context context, 557178825Sdfr hx509_certs certs, 558178825Sdfr void *data, 559178825Sdfr void *cursor) 560178825Sdfr{ 561178825Sdfr struct iter *iter = cursor; 562178825Sdfr 563178825Sdfr if (iter->certs) { 564233294Sstas hx509_certs_end_seq(context, iter->certs, iter->cursor); 565178825Sdfr hx509_certs_free(&iter->certs); 566178825Sdfr } else { 567178825Sdfr CFRelease(iter->searchRef); 568178825Sdfr } 569178825Sdfr 570178825Sdfr memset(iter, 0, sizeof(*iter)); 571178825Sdfr free(iter); 572178825Sdfr return 0; 573178825Sdfr} 574178825Sdfr 575178825Sdfr/* 576178825Sdfr * 577178825Sdfr */ 578178825Sdfr 579178825Sdfrstruct hx509_keyset_ops keyset_keychain = { 580178825Sdfr "KEYCHAIN", 581178825Sdfr 0, 582178825Sdfr keychain_init, 583178825Sdfr NULL, 584178825Sdfr keychain_free, 585178825Sdfr NULL, 586178825Sdfr NULL, 587178825Sdfr keychain_iter_start, 588178825Sdfr keychain_iter, 589178825Sdfr keychain_iter_end 590178825Sdfr}; 591178825Sdfr 592178825Sdfr#endif /* HAVE_FRAMEWORK_SECURITY */ 593178825Sdfr 594178825Sdfr/* 595178825Sdfr * 596178825Sdfr */ 597178825Sdfr 598178825Sdfrvoid 599178825Sdfr_hx509_ks_keychain_register(hx509_context context) 600178825Sdfr{ 601178825Sdfr#ifdef HAVE_FRAMEWORK_SECURITY 602178825Sdfr _hx509_ks_register(context, &keyset_keychain); 603178825Sdfr#endif 604178825Sdfr} 605