2
* Copyright (c) 2007 Kungliga Tekniska Högskolan
3
* (Royal Institute of Technology, Stockholm, Sweden).
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
10
* 1. Redistributions of source code must retain the above copyright
11
* 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.
17
* 3. Neither the name of the Institute nor the names of its contributors
18
* may be used to endorse or promote products derived from this software
19
* without specific prior written permission.
21
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37
#ifdef HAVE_FRAMEWORK_SECURITY
39
#include <Security/Security.h>
41
/* Missing function decls in pre Leopard */
42
#ifdef NEED_SECKEYGETCSPHANDLE_PROTO
43
OSStatus SecKeyGetCSPHandle(SecKeyRef, CSSM_CSP_HANDLE *);
44
OSStatus SecKeyGetCredentials(SecKeyRef, CSSM_ACL_AUTHORIZATION_TAG,
45
int, const CSSM_ACCESS_CREDENTIALS **);
46
#define kSecCredentialTypeDefault 0
51
getAttribute(SecKeychainItemRef itemRef, SecItemAttr item,
52
SecKeychainAttributeList **attrs)
54
SecKeychainAttributeInfo attrInfo;
55
UInt32 attrFormat = 0;
62
attrInfo.format = &attrFormat;
64
ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL,
77
SecKeychainItemRef item;
83
kc_rsa_public_encrypt(int flen,
84
const unsigned char *from,
93
kc_rsa_public_decrypt(int flen,
94
const unsigned char *from,
104
kc_rsa_private_encrypt(int flen,
105
const unsigned char *from,
110
struct kc_rsa *kc = RSA_get_app_data(rsa);
114
const CSSM_ACCESS_CREDENTIALS *creds;
115
SecKeyRef privKeyRef = (SecKeyRef)kc->item;
116
CSSM_CSP_HANDLE cspHandle;
117
const CSSM_KEY *cssmKey;
118
CSSM_CC_HANDLE sigHandle = 0;
123
cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey);
126
cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle);
129
ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_SIGN,
130
kSecCredentialTypeDefault, &creds);
133
ret = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA,
134
creds, cssmKey, &sigHandle);
137
in.Data = (uint8 *)from;
140
sig.Data = (uint8 *)to;
141
sig.Length = kc->keysize;
143
cret = CSSM_SignData(sigHandle, &in, 1, CSSM_ALGID_NONE, &sig);
145
/* cssmErrorString(cret); */
151
CSSM_DeleteContext(sigHandle);
157
kc_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
158
RSA * rsa, int padding)
164
kc_rsa_init(RSA *rsa)
170
kc_rsa_finish(RSA *rsa)
172
struct kc_rsa *kc_rsa = RSA_get_app_data(rsa);
173
CFRelease(kc_rsa->item);
174
memset(kc_rsa, 0, sizeof(*kc_rsa));
179
static const RSA_METHOD kc_rsa_pkcs1_method = {
180
"hx509 Keychain PKCS#1 RSA",
181
kc_rsa_public_encrypt,
182
kc_rsa_public_decrypt,
183
kc_rsa_private_encrypt,
184
kc_rsa_private_decrypt,
196
set_private_key(hx509_context context,
197
SecKeychainItemRef itemRef,
201
hx509_private_key key;
205
ret = _hx509_private_key_init(&key, NULL, NULL);
209
kc = calloc(1, sizeof(*kc));
211
_hx509_abort("out of memory");
217
_hx509_abort("out of memory");
219
/* Argh, fake modulus since OpenSSL API is on crack */
221
SecKeychainAttributeList *attrs = NULL;
226
if (rsa->n == NULL) abort();
228
ret = getAttribute(itemRef, kSecKeyKeySizeInBits, &attrs);
231
size = *(uint32_t *)attrs->attr[0].data;
232
SecKeychainItemFreeAttributesAndData(attrs, NULL);
234
kc->keysize = (size + 7) / 8;
236
data = malloc(kc->keysize);
237
memset(data, 0xe0, kc->keysize);
238
BN_bin2bn(data, kc->keysize, rsa->n);
243
RSA_set_method(rsa, &kc_rsa_pkcs1_method);
244
ret = RSA_set_app_data(rsa, kc);
246
_hx509_abort("RSA_set_app_data");
248
_hx509_private_key_assign_rsa(key, rsa);
249
_hx509_cert_assign_key(cert, key);
260
SecKeychainRef keychain;
264
keychain_init(hx509_context context,
265
hx509_certs certs, void **data, int flags,
266
const char *residue, hx509_lock lock)
268
struct ks_keychain *ctx;
270
ctx = calloc(1, sizeof(*ctx));
272
hx509_clear_error_string(context);
277
if (strcasecmp(residue, "system-anchors") == 0) {
279
} else if (strncasecmp(residue, "FILE:", 5) == 0) {
282
ret = SecKeychainOpen(residue + 5, &ctx->keychain);
284
hx509_set_error_string(context, 0, ENOENT,
285
"Failed to open %s", residue);
289
hx509_set_error_string(context, 0, ENOENT,
290
"Unknown subtype %s", residue);
304
keychain_free(hx509_certs certs, void *data)
306
struct ks_keychain *ctx = data;
308
CFRelease(ctx->keychain);
309
memset(ctx, 0, sizeof(*ctx));
321
SecKeychainSearchRef searchRef;
325
keychain_iter_start(hx509_context context,
326
hx509_certs certs, void *data, void **cursor)
328
struct ks_keychain *ctx = data;
331
iter = calloc(1, sizeof(*iter));
333
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
342
ret = hx509_certs_init(context, "MEMORY:ks-file-create",
343
0, NULL, &iter->certs);
349
ret = SecTrustCopyAnchorCertificates(&anchors);
351
hx509_certs_free(&iter->certs);
353
hx509_set_error_string(context, 0, ENOMEM,
354
"Can't get trust anchors from Keychain");
357
for (i = 0; i < CFArrayGetCount(anchors); i++) {
358
SecCertificateRef cr;
362
cr = (SecCertificateRef)CFArrayGetValueAtIndex(anchors, i);
364
SecCertificateGetData(cr, &cssm);
366
ret = hx509_cert_init_data(context, cssm.Data, cssm.Length, &cert);
370
ret = hx509_certs_add(context, iter->certs, cert);
371
hx509_cert_free(cert);
378
ret = hx509_certs_start_seq(context, iter->certs, &iter->cursor);
380
hx509_certs_free(&iter->certs);
387
ret = SecKeychainSearchCreateFromAttributes(ctx->keychain,
388
kSecCertificateItemClass,
393
hx509_set_error_string(context, 0, ret,
394
"Failed to start search for attributes");
408
keychain_iter(hx509_context context,
409
hx509_certs certs, void *data, void *cursor, hx509_cert *cert)
411
SecKeychainAttributeList *attrs = NULL;
412
SecKeychainAttributeInfo attrInfo;
413
UInt32 attrFormat[1] = { 0 };
414
SecKeychainItemRef itemRef;
416
struct iter *iter = cursor;
422
return hx509_certs_next_cert(context, iter->certs, iter->cursor, cert);
426
ret = SecKeychainSearchCopyNext(iter->searchRef, &itemRef);
427
if (ret == errSecItemNotFound)
433
* Pick out certificate and matching "keyid"
436
item[0] = kSecPublicKeyHashItemAttr;
440
attrInfo.format = attrFormat;
442
ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL,
447
ret = hx509_cert_init_data(context, ptr, len, cert);
452
* Find related private key if there is one by looking at
453
* kSecPublicKeyHashItemAttr == kSecKeyLabel
456
SecKeychainSearchRef search;
457
SecKeychainAttribute attrKeyid;
458
SecKeychainAttributeList attrList;
460
attrKeyid.tag = kSecKeyLabel;
461
attrKeyid.length = attrs->attr[0].length;
462
attrKeyid.data = attrs->attr[0].data;
465
attrList.attr = &attrKeyid;
467
ret = SecKeychainSearchCreateFromAttributes(NULL,
468
CSSM_DL_DB_RECORD_PRIVATE_KEY,
476
ret = SecKeychainSearchCopyNext(search, &itemRef);
478
if (ret == errSecItemNotFound) {
485
set_private_key(context, itemRef, *cert);
489
SecKeychainItemFreeAttributesAndData(attrs, ptr);
499
keychain_iter_end(hx509_context context,
504
struct iter *iter = cursor;
508
ret = hx509_certs_end_seq(context, iter->certs, iter->cursor);
509
hx509_certs_free(&iter->certs);
511
CFRelease(iter->searchRef);
514
memset(iter, 0, sizeof(*iter));
523
struct hx509_keyset_ops keyset_keychain = {
536
#endif /* HAVE_FRAMEWORK_SECURITY */
543
_hx509_ks_keychain_register(hx509_context context)
545
#ifdef HAVE_FRAMEWORK_SECURITY
546
_hx509_ks_register(context, &keyset_keychain);