]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/crypto_cssm.c
ipsec-286.1.1.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / crypto_cssm.c
CommitLineData
52b7d2ce
A
1
2/*
3 * Copyright (c) 2001-2004 Apple Computer, Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
7 * The contents of this file constitute Original Code as defined in and
8 * are subject to the Apple Public Source License Version 1.1 (the
9 * "License"). You may not use this file except in compliance with the
10 * License. Please obtain a copy of the License at
11 * http://www.apple.com/publicsource and read it before using this file.
12 *
13 * This Original Code and all software distributed under the License are
14 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
18 * License for the specific language governing rights and limitations
19 * under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25/*
26 * Racoon module for verifying and signing certificates through Security
27 * Framework and CSSM
28 */
29
52b7d2ce
A
30#include <Security/SecCertificate.h>
31#include <Security/SecPolicy.h>
d1e348cf
A
32#include <Security/SecTrust.h>
33#include <Security/SecKey.h>
52b7d2ce 34#include <Security/SecIdentity.h>
85f41bec 35#include <Security/SecItem.h>
d1e348cf
A
36#include <TargetConditionals.h>
37#if TARGET_OS_EMBEDDED
fce29cd9
A
38#include <Security/SecTrustPriv.h>
39#include <Security/SecPolicyPriv.h>
40#include <Security/SecCertificatePriv.h>
d1e348cf
A
41#else
42#include <Security/SecBase.h>
52b7d2ce
A
43#include <Security/SecIdentityPriv.h>
44#include <Security/SecIdentitySearch.h>
45#include <Security/SecKeychain.h>
46#include <Security/SecKeychainItem.h>
47#include <Security/SecKeychainItemPriv.h>
65c25746 48#include <Security/SecCertificateOIDs.h>
52b7d2ce 49#include <Security/SecKeyPriv.h>
52b7d2ce
A
50#include <Security/oidsalg.h>
51#include <Security/cssmapi.h>
52#include <Security/SecPolicySearch.h>
d1e348cf 53#endif
52b7d2ce 54#include <CoreFoundation/CoreFoundation.h>
65c25746 55#if !TARGET_OS_EMBEDDED
52b7d2ce 56#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
65c25746 57#endif
52b7d2ce
A
58#include "plog.h"
59#include "debug.h"
60#include "misc.h"
fce29cd9 61#include "oakley.h"
65c25746 62#include "gcmalloc.h"
52b7d2ce 63
52b7d2ce 64
d1e348cf 65#include "crypto_cssm.h"
52b7d2ce 66
85f41bec 67
e8d9021d 68static OSStatus EvaluateCert(SecCertificateRef evalCertArray[], CFIndex evalCertArrayNumValues, CFTypeRef policyRef, SecKeyRef *publicKeyRef);
52b7d2ce 69
d1e348cf 70#if !TARGET_OS_EMBEDDED
d1e348cf 71#endif
52b7d2ce 72
e8d9021d
A
73static SecPolicyRef
74crypto_cssm_x509cert_get_SecPolicyRef (CFStringRef hostname)
52b7d2ce 75{
d1e348cf 76 SecPolicyRef policyRef = NULL;
65c25746
A
77 CFDictionaryRef properties = NULL;
78 const void *key[] = { kSecPolicyName };
79 const void *value[] = { hostname };
d1e348cf 80
e8d9021d 81 if (hostname) {
65c25746
A
82 properties = CFDictionaryCreate(NULL, key, value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
83 if (properties == NULL) {
84 plog(ASL_LEVEL_ERR,
85 "unable to create dictionary for policy properties.\n");
e8d9021d
A
86 }
87 }
65c25746
A
88 policyRef = SecPolicyCreateWithProperties(kSecPolicyAppleIPsec, properties);
89 if (properties)
90 CFRelease(properties);
e8d9021d
A
91 return policyRef;
92}
93
94SecCertificateRef
65c25746 95crypto_cssm_x509cert_CreateSecCertificateRef (vchar_t *cert)
e8d9021d 96{
e8d9021d 97 SecCertificateRef certRef = NULL;
52b7d2ce 98
65c25746 99 CFDataRef cert_data = CFDataCreateWithBytesNoCopy(NULL, (uint8_t*)cert->v, cert->l, kCFAllocatorNull);
d1e348cf
A
100 if (cert_data) {
101 certRef = SecCertificateCreateWithData(NULL, cert_data);
102 CFRelease(cert_data);
103 }
85f41bec 104
d1e348cf 105 if (certRef == NULL) {
65c25746
A
106 plog(ASL_LEVEL_ERR,
107 "unable to get a certifcate reference.\n");
d1e348cf 108 }
e8d9021d
A
109 return certRef;
110}
d1e348cf 111
65c25746
A
112/* HACK!!! - temporary until this prototype gets moved */
113extern CFDataRef SecCertificateCopySubjectSequence( SecCertificateRef certificate);
114
115CFDataRef
116crypto_cssm_CopySubjectSequence(SecCertificateRef certRef)
117{
118 CFDataRef subject = NULL;
119
120 subject = SecCertificateCopySubjectSequence(certRef);
121 return subject;
122
123}
124
125
e8d9021d
A
126static cert_status_t
127crypto_cssm_check_x509cert_dates (SecCertificateRef certificateRef)
128{
129 cert_status_t certStatus = CERT_STATUS_OK;
130#if TARGET_OS_EMBEDDED
131 CFAbsoluteTime timeNow = 0;
132 CFAbsoluteTime notvalidbeforedate = 0;
133 CFAbsoluteTime notvalidafterdate = 0;
134 CFDateRef nowcfdatedata = NULL;
135 CFDateRef notvalidbeforedatedata = NULL;
136 CFDateRef notvalidafterdatedata = NULL;
137 CFArrayRef certProparray = NULL;
138 CFDictionaryRef propDict = NULL;
139 const void *datevalue = NULL;
140 const void *labelvalue = NULL;
141 CFGregorianDate gregoriandate;
142 CFIndex count;
143 CFIndex i;
144
145 if ((certProparray = SecCertificateCopyProperties(certificateRef))){
146 if ((count = CFArrayGetCount( certProparray ))){
147 for( i = 0; i < count; i++) {
148 if ((propDict = CFArrayGetValueAtIndex(certProparray, i))) {
149 if ( CFDictionaryGetValueIfPresent(propDict, kSecPropertyKeyValue, (const void**)&datevalue)){
150 /* get kSecPropertyKeyLabel */
151 if ( (datevalue) && (CFDictionaryGetValueIfPresent(propDict, kSecPropertyKeyLabel, (const void**)&labelvalue))){
152 if ( (labelvalue) && (CFStringCompare( (CFStringRef)labelvalue, CFSTR("Not Valid Before"), 0) == kCFCompareEqualTo)){
65c25746 153 if ( (notvalidbeforedate = CFDateGetAbsoluteTime(datevalue))) {
e8d9021d
A
154 if (notvalidbeforedatedata) {
155 CFRelease(notvalidbeforedatedata);
156 }
157 notvalidbeforedatedata = CFDateCreate(NULL, notvalidbeforedate);
158 }
159 }else if ((labelvalue) && (CFStringCompare( (CFStringRef)labelvalue, CFSTR("Not Valid After"), 0 ) == kCFCompareEqualTo)){
65c25746 160 if ( (notvalidafterdate = CFDateGetAbsoluteTime(datevalue))) {
e8d9021d
A
161 if (notvalidafterdatedata) {
162 CFRelease(notvalidafterdatedata);
163 }
164 notvalidafterdatedata = CFDateCreate(NULL, notvalidafterdate);
165 }
166 }
167 }
168 }
169 }
170 }
d1e348cf 171 }
d1e348cf 172 }
e8d9021d
A
173
174 if ( (timeNow = CFAbsoluteTimeGetCurrent()) && (nowcfdatedata = CFDateCreate( NULL, timeNow))){
175 if ( notvalidbeforedatedata ){
176 gregoriandate = CFAbsoluteTimeGetGregorianDate(notvalidbeforedate, NULL);
65c25746
A
177 plog(ASL_LEVEL_DEBUG,
178 "Certificate not valid before yr %d, mon %d, days %d, hours %d, min %d\n", (int)gregoriandate.year, gregoriandate.month, gregoriandate.day, gregoriandate.hour, gregoriandate.minute);
e8d9021d 179 gregoriandate = CFAbsoluteTimeGetGregorianDate(notvalidafterdate, NULL);
65c25746
A
180 plog(ASL_LEVEL_DEBUG,
181 "Certificate not valid after yr %d, mon %d, days %d, hours %d, min %d\n", (int)gregoriandate.year, gregoriandate.month, gregoriandate.day, gregoriandate.hour, gregoriandate.minute);
e8d9021d 182 if ( CFDateCompare( nowcfdatedata, notvalidbeforedatedata, NULL ) == kCFCompareLessThan){
65c25746 183 plog(ASL_LEVEL_ERR,
e8d9021d
A
184 "current time before valid time\n");
185 certStatus = CERT_STATUS_PREMATURE;
186 } else if (notvalidafterdatedata && (CFDateCompare( nowcfdatedata, notvalidafterdatedata, NULL ) == kCFCompareGreaterThan)){
65c25746 187 plog(ASL_LEVEL_ERR,
e8d9021d
A
188 "current time after valid time\n");
189 certStatus = CERT_STATUS_EXPIRED;
190 }else {
65c25746 191 plog(ASL_LEVEL_INFO, "Certificate expiration date is OK\n");
e8d9021d
A
192 certStatus = CERT_STATUS_OK;
193 }
194 }
195 }
196
197 if (notvalidbeforedatedata)
198 CFRelease(notvalidbeforedatedata);
199 if (notvalidafterdatedata)
200 CFRelease(notvalidafterdatedata);
201 if (certProparray)
202 CFRelease(certProparray);
203 if (nowcfdatedata)
204 CFRelease(nowcfdatedata);
205#endif
206 return certStatus;
207}
208
209/*
210 * Verify cert using security framework
211 */
e8d9021d 212int crypto_cssm_check_x509cert (cert_t *hostcert, cert_t *certchain, CFStringRef hostname, SecKeyRef *publicKeyRef)
e8d9021d
A
213{
214 cert_t *p;
215 cert_status_t certStatus = 0;
216 OSStatus status;
217 CFIndex certArrayRefNumValues = 0;
218 CFIndex n = 0;
219 int certArraySiz;
220 SecCertificateRef *certArrayRef = NULL;
221 SecPolicyRef policyRef = crypto_cssm_x509cert_get_SecPolicyRef(hostname);
222
223 if (!hostcert || !certchain) {
224 return -1;
225 }
226
227 // find the total number of certs
228 for (p = certchain; p; p = p->chain, n++);
229 if (n> 1) {
65c25746
A
230 plog(ASL_LEVEL_DEBUG,
231 "%s: checking chain of %d certificates.\n", __FUNCTION__, (int)n);
e8d9021d
A
232 }
233
234 certArraySiz = n * sizeof(CFTypeRef);
235 certArrayRef = CFAllocatorAllocate(NULL, certArraySiz, 0);
236 if (!certArrayRef) {
237 return -1;
238 }
239 bzero(certArrayRef, certArraySiz);
65c25746 240 if ((certArrayRef[certArrayRefNumValues] = crypto_cssm_x509cert_CreateSecCertificateRef(&hostcert->cert))) {
e8d9021d
A
241 /* don't overwrite any pending status */
242 if (!hostcert->status) {
243 hostcert->status = crypto_cssm_check_x509cert_dates(certArrayRef[certArrayRefNumValues]);
244 if (hostcert->status) {
65c25746 245 plog(ASL_LEVEL_ERR,
e8d9021d
A
246 "host certificate failed date verification: %d.\n", hostcert->status);
247 certStatus = hostcert->status;
248 }
249 }
250 certArrayRefNumValues++;
251 }
252 for (p = certchain; p && certArrayRefNumValues < n; p = p->chain) {
253 if (p != hostcert) {
65c25746 254 if ((certArrayRef[certArrayRefNumValues] = crypto_cssm_x509cert_CreateSecCertificateRef(&p->cert))) {
e8d9021d
A
255 /* don't overwrite any pending status */
256 if (!p->status) {
257 p->status = crypto_cssm_check_x509cert_dates(certArrayRef[certArrayRefNumValues]);
258 if (p->status) {
65c25746 259 plog(ASL_LEVEL_ERR,
e8d9021d
A
260 "other certificate in chain failed date verification: %d.\n", p->status);
261 if (!certStatus) {
262 certStatus = p->status;
263 }
264 }
265 }
266 certArrayRefNumValues++;
267 }
268 }
269 }
52b7d2ce
A
270
271 // evaluate cert
e8d9021d 272 status = EvaluateCert(certArrayRef, certArrayRefNumValues, policyRef, publicKeyRef);
e8d9021d
A
273
274 while (certArrayRefNumValues) {
275 CFRelease(certArrayRef[--certArrayRefNumValues]);
276 }
277 CFAllocatorDeallocate(NULL, certArrayRef);
52b7d2ce 278
52b7d2ce
A
279 if (policyRef)
280 CFRelease(policyRef);
281
282 if (status != noErr && status != -1) {
65c25746
A
283 plog(ASL_LEVEL_ERR,
284 "error %d %s.\n", (int)status, GetSecurityErrorString(status));
52b7d2ce 285 status = -1;
e8d9021d 286 } else if (certStatus == CERT_STATUS_PREMATURE || certStatus == CERT_STATUS_EXPIRED) {
fce29cd9
A
287 status = -1;
288 }
52b7d2ce 289 return status;
e8d9021d
A
290
291}
52b7d2ce 292
85f41bec 293
65c25746 294int crypto_cssm_verify_x509sign(SecKeyRef publicKeyRef, vchar_t *hash, vchar_t *signature, Boolean useSHA1)
e8d9021d 295{
65c25746 296 return SecKeyRawVerify(publicKeyRef, useSHA1 ? kSecPaddingPKCS1SHA1 : kSecPaddingPKCS1, (uint8_t*)hash->v, hash->l, (uint8_t*)signature->v, signature->l);
52b7d2ce
A
297}
298
299/*
300 * Encrypt a hash via CSSM using the private key in the keychain
301 * from an identity.
302 */
303vchar_t* crypto_cssm_getsign(CFDataRef persistentCertRef, vchar_t* hash)
304{
305
e8d9021d 306 OSStatus status = -1;
52b7d2ce 307 SecIdentityRef identityRef = NULL;
d1e348cf
A
308 SecKeyRef privateKeyRef = NULL;
309 vchar_t *sig = NULL;
310
d1e348cf
A
311
312 CFDictionaryRef persistFind = NULL;
85f41bec
A
313 const void *keys_persist[] = { kSecReturnRef, kSecValuePersistentRef, kSecClass};
314 const void *values_persist[] = { kCFBooleanTrue, persistentCertRef, kSecClassIdentity};
315
316#define SIG_BUF_SIZE 1024
d1e348cf
A
317
318 /* find identity by persistent ref */
319 persistFind = CFDictionaryCreate(NULL, keys_persist, values_persist,
85f41bec 320 (sizeof(keys_persist) / sizeof(*keys_persist)), NULL, NULL);
d1e348cf
A
321 if (persistFind == NULL)
322 goto end;
323
324 status = SecItemCopyMatching(persistFind, (CFTypeRef *)&identityRef);
325 if (status != noErr)
326 goto end;
327
328 status = SecIdentityCopyPrivateKey(identityRef, &privateKeyRef);
329 if (status != noErr)
330 goto end;
331
332 // alloc buffer for result
333 sig = vmalloc(SIG_BUF_SIZE);
334 if (sig == NULL)
335 goto end;
336
65c25746
A
337 status = SecKeyRawSign(privateKeyRef, kSecPaddingPKCS1, (uint8_t*)hash->v,
338 hash->l, (uint8_t*)sig->v, &sig->l);
d1e348cf 339
52b7d2ce
A
340
341end:
52b7d2ce
A
342 if (identityRef)
343 CFRelease(identityRef);
344 if (privateKeyRef)
345 CFRelease(privateKeyRef);
d1e348cf 346
d1e348cf
A
347 if (persistFind)
348 CFRelease(persistFind);
d1e348cf 349
52b7d2ce
A
350 if (status != noErr) {
351 if (sig) {
352 vfree(sig);
353 sig = NULL;
354 }
355 }
356
357 if (status != noErr && status != -1) {
65c25746
A
358 plog(ASL_LEVEL_ERR,
359 "error %d %s.\n", (int)status, GetSecurityErrorString(status));
52b7d2ce
A
360 status = -1;
361 }
362 return sig;
363
364}
365
366
367/*
368 * Retrieve a cert from the keychain
369 */
fce29cd9
A
370vchar_t* crypto_cssm_get_x509cert(CFDataRef persistentCertRef,
371 cert_status_t *certStatus)
52b7d2ce
A
372{
373
e8d9021d 374 OSStatus status = -1;
52b7d2ce 375 vchar_t *cert = NULL;
65c25746
A
376 SecCertificateRef certificateRef = NULL;
377 CFDictionaryRef persistFind = NULL;
378 size_t dataLen;
379 CFDataRef certData = NULL;
52b7d2ce 380 SecIdentityRef identityRef = NULL;
65c25746
A
381 const void *keys_persist[] = { kSecReturnRef, kSecValuePersistentRef, kSecClass };
382 const void *values_persist[] = { kCFBooleanTrue, persistentCertRef, kSecClassIdentity };
d1e348cf
A
383
384 /* find identity by persistent ref */
385 persistFind = CFDictionaryCreate(NULL, keys_persist, values_persist,
e8d9021d 386 (sizeof(keys_persist) / sizeof(*keys_persist)), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
d1e348cf
A
387 if (persistFind == NULL)
388 goto end;
65c25746
A
389
390 status = SecItemCopyMatching(persistFind, (CFTypeRef *)&identityRef);
d1e348cf
A
391 if (status != noErr)
392 goto end;
393
394 status = SecIdentityCopyCertificate(identityRef, &certificateRef);
395 if (status != noErr)
396 goto end;
397
398 certData = SecCertificateCopyData(certificateRef);
399 if (certData == NULL)
400 goto end;
401
402 dataLen = CFDataGetLength(certData);
403 if (dataLen == 0)
404 goto end;
405
406 cert = vmalloc(dataLen);
407 if (cert == NULL)
408 goto end;
409
65c25746 410 CFDataGetBytes(certData, CFRangeMake(0, dataLen), (uint8_t*)cert->v);
d1e348cf 411
fce29cd9
A
412 // verify expiry or missing fields
413 if (certStatus) {
e8d9021d 414 *certStatus = crypto_cssm_check_x509cert_dates(certificateRef);
fce29cd9 415 }
52b7d2ce
A
416
417end:
65c25746
A
418 if (identityRef)
419 CFRelease(identityRef);
52b7d2ce
A
420 if (certificateRef)
421 CFRelease(certificateRef);
d1e348cf
A
422 if (persistFind)
423 CFRelease(persistFind);
424 if (certData)
425 CFRelease(certData);
d1e348cf 426
52b7d2ce 427 if (status != noErr && status != -1) {
65c25746
A
428 plog(ASL_LEVEL_ERR,
429 "error %d %s.\n", (int)status, GetSecurityErrorString(status));
52b7d2ce
A
430 status = -1;
431 }
432 return cert;
433
434}
435
52b7d2ce
A
436/*
437 * Evaluate the trust of a cert using the policy provided
438 */
e8d9021d 439static OSStatus EvaluateCert(SecCertificateRef evalCertArray[], CFIndex evalCertArrayNumValues, CFTypeRef policyRef, SecKeyRef *publicKeyRef)
52b7d2ce
A
440{
441 OSStatus status;
442 SecTrustRef trustRef = 0;
443 SecTrustResultType evalResult;
fce29cd9 444
fce29cd9 445 CFArrayRef errorStrings;
52b7d2ce 446
e8d9021d 447 CFArrayRef cfCertRef = CFArrayCreate((CFAllocatorRef) NULL, (void*)evalCertArray, evalCertArrayNumValues,
d1e348cf 448 &kCFTypeArrayCallBacks);
52b7d2ce
A
449
450 if (!cfCertRef) {
65c25746 451 plog(ASL_LEVEL_ERR,
52b7d2ce
A
452 "unable to create CFArray.\n");
453 return -1;
454 }
455
456 status = SecTrustCreateWithCertificates(cfCertRef, policyRef, &trustRef);
457 if (status != noErr)
458 goto end;
fce29cd9 459
52b7d2ce
A
460 status = SecTrustEvaluate(trustRef, &evalResult);
461 if (status != noErr)
462 goto end;
463
464 if (evalResult != kSecTrustResultProceed && evalResult != kSecTrustResultUnspecified) {
65c25746 465 plog(ASL_LEVEL_ERR, "Error evaluating certificate.\n");
fce29cd9
A
466
467 switch (evalResult) {
468 case kSecTrustResultInvalid:
65c25746 469 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultInvalid.\n");
fce29cd9
A
470 break;
471 case kSecTrustResultProceed:
65c25746 472 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultProceed.\n");
fce29cd9 473 break;
fce29cd9 474 case kSecTrustResultDeny:
65c25746 475 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultDeny.\n");
fce29cd9
A
476 break;
477 case kSecTrustResultUnspecified:
65c25746 478 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultUnspecified.\n");
fce29cd9
A
479 break;
480 case kSecTrustResultRecoverableTrustFailure:
65c25746 481 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultRecoverableTrustFailure.\n");
fce29cd9
A
482 break;
483 case kSecTrustResultFatalTrustFailure:
65c25746 484 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultFatalTrustFailure.\n");
fce29cd9
A
485 break;
486 case kSecTrustResultOtherError:
65c25746 487 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultOtherError.\n");
fce29cd9
A
488 break;
489 default:
65c25746 490 plog(ASL_LEVEL_DEBUG, "eval result unknown: value = %d.\n", (int)evalResult);
fce29cd9
A
491 break;
492 }
493
fce29cd9
A
494 errorStrings = SecTrustCopyProperties(trustRef);
495 if (errorStrings) {
496
497 CFDictionaryRef dict;
498 CFStringRef val;
499 const char *str;
500 CFIndex count, maxcount = CFArrayGetCount(errorStrings);
501
65c25746 502 plog(ASL_LEVEL_ERR, "---------------Returned error strings: ---------------.\n");
fce29cd9
A
503 for (count = 0; count < maxcount; count++) {
504 dict = CFArrayGetValueAtIndex(errorStrings, count);
505 if (dict && (CFGetTypeID(dict) == CFDictionaryGetTypeID())) {
506 val = CFDictionaryGetValue(dict, kSecPropertyKeyType);
507 if (val && (CFGetTypeID(val) == CFStringGetTypeID())) {
508 str = CFStringGetCStringPtr(val, kCFStringEncodingMacRoman);
509 if (str)
65c25746 510 plog(ASL_LEVEL_ERR, "type = %s.\n", str);
fce29cd9
A
511 }
512 val = CFDictionaryGetValue(dict, kSecPropertyKeyValue);
513 if (val && (CFGetTypeID(val) == CFStringGetTypeID())) {
514 str = CFStringGetCStringPtr(val, kCFStringEncodingMacRoman);
515 if (str)
65c25746 516 plog(ASL_LEVEL_ERR, "value = %s.\n", str);
fce29cd9
A
517 }
518 }
519 }
65c25746 520 plog(ASL_LEVEL_ERR, "-----------------------------------------------------.\n");
fce29cd9
A
521 CFRelease(errorStrings);
522 }
85f41bec 523
52b7d2ce 524 status = -1;
e8d9021d 525 goto end;
52b7d2ce
A
526 }
527
e8d9021d
A
528 /* get and return the public key */
529 *publicKeyRef = SecTrustCopyPublicKey(trustRef);
e8d9021d 530
52b7d2ce
A
531end:
532 if (cfCertRef)
533 CFRelease(cfCertRef);
534 if (trustRef)
535 CFRelease(trustRef);
536
537 if (status != noErr && status != -1) {
65c25746
A
538 plog(ASL_LEVEL_ERR,
539 "error %d %s.\n", (int)status, GetSecurityErrorString(status));
52b7d2ce
A
540 status = -1;
541 }
542 return status;
543}
544
52b7d2ce
A
545/*
546 * Return string representation of Security-related OSStatus.
547 */
548const char *
549GetSecurityErrorString(OSStatus err)
550{
551 switch(err) {
552 case noErr:
553 return "noErr";
52b7d2ce
A
554
555 /* SecBase.h: */
556 case errSecNotAvailable:
557 return "errSecNotAvailable";
65c25746 558
d1e348cf 559#if !TARGET_OS_EMBEDDED
65c25746
A
560 case memFullErr:
561 return "memFullErr";
562 case paramErr:
563 return "paramErr";
564 case unimpErr:
565 return "unimpErr";
566
567 /* SecBase.h: */
52b7d2ce
A
568 case errSecReadOnly:
569 return "errSecReadOnly";
570 case errSecAuthFailed:
571 return "errSecAuthFailed";
572 case errSecNoSuchKeychain:
573 return "errSecNoSuchKeychain";
574 case errSecInvalidKeychain:
575 return "errSecInvalidKeychain";
576 case errSecDuplicateKeychain:
577 return "errSecDuplicateKeychain";
578 case errSecDuplicateCallback:
579 return "errSecDuplicateCallback";
580 case errSecInvalidCallback:
581 return "errSecInvalidCallback";
52b7d2ce
A
582 case errSecBufferTooSmall:
583 return "errSecBufferTooSmall";
584 case errSecDataTooLarge:
585 return "errSecDataTooLarge";
586 case errSecNoSuchAttr:
587 return "errSecNoSuchAttr";
588 case errSecInvalidItemRef:
589 return "errSecInvalidItemRef";
590 case errSecInvalidSearchRef:
591 return "errSecInvalidSearchRef";
592 case errSecNoSuchClass:
593 return "errSecNoSuchClass";
594 case errSecNoDefaultKeychain:
595 return "errSecNoDefaultKeychain";
596 case errSecInteractionNotAllowed:
597 return "errSecInteractionNotAllowed";
598 case errSecReadOnlyAttr:
599 return "errSecReadOnlyAttr";
600 case errSecWrongSecVersion:
601 return "errSecWrongSecVersion";
602 case errSecKeySizeNotAllowed:
603 return "errSecKeySizeNotAllowed";
604 case errSecNoStorageModule:
605 return "errSecNoStorageModule";
606 case errSecNoCertificateModule:
607 return "errSecNoCertificateModule";
608 case errSecNoPolicyModule:
609 return "errSecNoPolicyModule";
610 case errSecInteractionRequired:
611 return "errSecInteractionRequired";
612 case errSecDataNotAvailable:
613 return "errSecDataNotAvailable";
614 case errSecDataNotModifiable:
615 return "errSecDataNotModifiable";
616 case errSecCreateChainFailed:
617 return "errSecCreateChainFailed";
618 case errSecACLNotSimple:
619 return "errSecACLNotSimple";
620 case errSecPolicyNotFound:
621 return "errSecPolicyNotFound";
622 case errSecInvalidTrustSetting:
623 return "errSecInvalidTrustSetting";
624 case errSecNoAccessForItem:
625 return "errSecNoAccessForItem";
626 case errSecInvalidOwnerEdit:
627 return "errSecInvalidOwnerEdit";
d1e348cf
A
628#endif
629 case errSecDuplicateItem:
630 return "errSecDuplicateItem";
631 case errSecItemNotFound:
632 return "errSecItemNotFound";
52b7d2ce
A
633 default:
634 return "<unknown>";
635 }
636}
637