]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/crypto_cssm.c
ipsec-258.100.1.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / crypto_cssm.c
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
30 #include <Security/SecCertificate.h>
31 #include <Security/SecPolicy.h>
32 #include <Security/SecTrust.h>
33 #include <Security/SecKey.h>
34 #include <Security/SecIdentity.h>
35 #include <Security/SecItem.h>
36 #include <TargetConditionals.h>
37 #if TARGET_OS_EMBEDDED
38 #include <Security/SecTrustPriv.h>
39 #include <Security/SecPolicyPriv.h>
40 #include <Security/SecCertificatePriv.h>
41 #else
42 #include <Security/SecBase.h>
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>
48 #include <Security/SecCertificateOIDs.h>
49 #include <Security/SecKeyPriv.h>
50 #include <Security/oidsalg.h>
51 #include <Security/cssmapi.h>
52 #include <Security/SecPolicySearch.h>
53 #endif
54 #include <CoreFoundation/CoreFoundation.h>
55 #if !TARGET_OS_EMBEDDED
56 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
57 #endif
58 #include "plog.h"
59 #include "debug.h"
60 #include "misc.h"
61 #include "oakley.h"
62 #include "gcmalloc.h"
63
64
65 #include "crypto_cssm.h"
66
67
68 static OSStatus EvaluateCert(SecCertificateRef evalCertArray[], CFIndex evalCertArrayNumValues, CFTypeRef policyRef, SecKeyRef *publicKeyRef);
69
70 #if !TARGET_OS_EMBEDDED
71 #endif
72
73 static SecPolicyRef
74 crypto_cssm_x509cert_get_SecPolicyRef (CFStringRef hostname)
75 {
76 SecPolicyRef policyRef = NULL;
77 CFDictionaryRef properties = NULL;
78 const void *key[] = { kSecPolicyName };
79 const void *value[] = { hostname };
80
81 if (hostname) {
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");
86 }
87 }
88 policyRef = SecPolicyCreateWithProperties(kSecPolicyAppleIPsec, properties);
89 if (properties)
90 CFRelease(properties);
91 return policyRef;
92 }
93
94 SecCertificateRef
95 crypto_cssm_x509cert_CreateSecCertificateRef (vchar_t *cert)
96 {
97 SecCertificateRef certRef = NULL;
98
99 CFDataRef cert_data = CFDataCreateWithBytesNoCopy(NULL, (uint8_t*)cert->v, cert->l, kCFAllocatorNull);
100 if (cert_data) {
101 certRef = SecCertificateCreateWithData(NULL, cert_data);
102 CFRelease(cert_data);
103 }
104
105 if (certRef == NULL) {
106 plog(ASL_LEVEL_ERR,
107 "unable to get a certifcate reference.\n");
108 }
109 return certRef;
110 }
111
112 /* HACK!!! - temporary until this prototype gets moved */
113 extern CFDataRef SecCertificateCopySubjectSequence( SecCertificateRef certificate);
114
115 CFDataRef
116 crypto_cssm_CopySubjectSequence(SecCertificateRef certRef)
117 {
118 CFDataRef subject = NULL;
119
120 subject = SecCertificateCopySubjectSequence(certRef);
121 return subject;
122
123 }
124
125
126 static cert_status_t
127 crypto_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)){
153 if ( (notvalidbeforedate = CFDateGetAbsoluteTime(datevalue))) {
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)){
160 if ( (notvalidafterdate = CFDateGetAbsoluteTime(datevalue))) {
161 if (notvalidafterdatedata) {
162 CFRelease(notvalidafterdatedata);
163 }
164 notvalidafterdatedata = CFDateCreate(NULL, notvalidafterdate);
165 }
166 }
167 }
168 }
169 }
170 }
171 }
172 }
173
174 if ( (timeNow = CFAbsoluteTimeGetCurrent()) && (nowcfdatedata = CFDateCreate( NULL, timeNow))){
175 if ( notvalidbeforedatedata ){
176 gregoriandate = CFAbsoluteTimeGetGregorianDate(notvalidbeforedate, NULL);
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);
179 gregoriandate = CFAbsoluteTimeGetGregorianDate(notvalidafterdate, NULL);
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);
182 if ( CFDateCompare( nowcfdatedata, notvalidbeforedatedata, NULL ) == kCFCompareLessThan){
183 plog(ASL_LEVEL_ERR,
184 "current time before valid time\n");
185 certStatus = CERT_STATUS_PREMATURE;
186 } else if (notvalidafterdatedata && (CFDateCompare( nowcfdatedata, notvalidafterdatedata, NULL ) == kCFCompareGreaterThan)){
187 plog(ASL_LEVEL_ERR,
188 "current time after valid time\n");
189 certStatus = CERT_STATUS_EXPIRED;
190 }else {
191 plog(ASL_LEVEL_INFO, "Certificate expiration date is OK\n");
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 */
212 int crypto_cssm_check_x509cert (cert_t *hostcert, cert_t *certchain, CFStringRef hostname, SecKeyRef *publicKeyRef)
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) {
230 plog(ASL_LEVEL_DEBUG,
231 "%s: checking chain of %d certificates.\n", __FUNCTION__, (int)n);
232 }
233
234 certArraySiz = n * sizeof(CFTypeRef);
235 certArrayRef = CFAllocatorAllocate(NULL, certArraySiz, 0);
236 if (!certArrayRef) {
237 return -1;
238 }
239 bzero(certArrayRef, certArraySiz);
240 if ((certArrayRef[certArrayRefNumValues] = crypto_cssm_x509cert_CreateSecCertificateRef(&hostcert->cert))) {
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) {
245 plog(ASL_LEVEL_ERR,
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) {
254 if ((certArrayRef[certArrayRefNumValues] = crypto_cssm_x509cert_CreateSecCertificateRef(&p->cert))) {
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) {
259 plog(ASL_LEVEL_ERR,
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 }
270
271 // evaluate cert
272 status = EvaluateCert(certArrayRef, certArrayRefNumValues, policyRef, publicKeyRef);
273
274 while (certArrayRefNumValues) {
275 CFRelease(certArrayRef[--certArrayRefNumValues]);
276 }
277 CFAllocatorDeallocate(NULL, certArrayRef);
278
279 if (policyRef)
280 CFRelease(policyRef);
281
282 if (status != noErr && status != -1) {
283 plog(ASL_LEVEL_ERR,
284 "error %d %s.\n", (int)status, GetSecurityErrorString(status));
285 status = -1;
286 } else if (certStatus == CERT_STATUS_PREMATURE || certStatus == CERT_STATUS_EXPIRED) {
287 status = -1;
288 }
289 return status;
290
291 }
292
293
294 int crypto_cssm_verify_x509sign(SecKeyRef publicKeyRef, vchar_t *hash, vchar_t *signature, Boolean useSHA1)
295 {
296 return SecKeyRawVerify(publicKeyRef, useSHA1 ? kSecPaddingPKCS1SHA1 : kSecPaddingPKCS1, (uint8_t*)hash->v, hash->l, (uint8_t*)signature->v, signature->l);
297 }
298
299 /*
300 * Encrypt a hash via CSSM using the private key in the keychain
301 * from an identity.
302 */
303 vchar_t* crypto_cssm_getsign(CFDataRef persistentCertRef, vchar_t* hash)
304 {
305
306 OSStatus status = -1;
307 SecIdentityRef identityRef = NULL;
308 SecKeyRef privateKeyRef = NULL;
309 vchar_t *sig = NULL;
310
311
312 CFDictionaryRef persistFind = NULL;
313 const void *keys_persist[] = { kSecReturnRef, kSecValuePersistentRef, kSecClass};
314 const void *values_persist[] = { kCFBooleanTrue, persistentCertRef, kSecClassIdentity};
315
316 #define SIG_BUF_SIZE 1024
317
318 /* find identity by persistent ref */
319 persistFind = CFDictionaryCreate(NULL, keys_persist, values_persist,
320 (sizeof(keys_persist) / sizeof(*keys_persist)), NULL, NULL);
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
337 status = SecKeyRawSign(privateKeyRef, kSecPaddingPKCS1, (uint8_t*)hash->v,
338 hash->l, (uint8_t*)sig->v, &sig->l);
339
340
341 end:
342 if (identityRef)
343 CFRelease(identityRef);
344 if (privateKeyRef)
345 CFRelease(privateKeyRef);
346
347 if (persistFind)
348 CFRelease(persistFind);
349
350 if (status != noErr) {
351 if (sig) {
352 vfree(sig);
353 sig = NULL;
354 }
355 }
356
357 if (status != noErr && status != -1) {
358 plog(ASL_LEVEL_ERR,
359 "error %d %s.\n", (int)status, GetSecurityErrorString(status));
360 status = -1;
361 }
362 return sig;
363
364 }
365
366
367 /*
368 * Retrieve a cert from the keychain
369 */
370 vchar_t* crypto_cssm_get_x509cert(CFDataRef persistentCertRef,
371 cert_status_t *certStatus)
372 {
373
374 OSStatus status = -1;
375 vchar_t *cert = NULL;
376 SecCertificateRef certificateRef = NULL;
377 CFDictionaryRef persistFind = NULL;
378 size_t dataLen;
379 CFDataRef certData = NULL;
380 SecIdentityRef identityRef = NULL;
381 const void *keys_persist[] = { kSecReturnRef, kSecValuePersistentRef, kSecClass };
382 const void *values_persist[] = { kCFBooleanTrue, persistentCertRef, kSecClassIdentity };
383
384 /* find identity by persistent ref */
385 persistFind = CFDictionaryCreate(NULL, keys_persist, values_persist,
386 (sizeof(keys_persist) / sizeof(*keys_persist)), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
387 if (persistFind == NULL)
388 goto end;
389
390 status = SecItemCopyMatching(persistFind, (CFTypeRef *)&identityRef);
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
410 CFDataGetBytes(certData, CFRangeMake(0, dataLen), (uint8_t*)cert->v);
411
412 // verify expiry or missing fields
413 if (certStatus) {
414 *certStatus = crypto_cssm_check_x509cert_dates(certificateRef);
415 }
416
417 end:
418 if (identityRef)
419 CFRelease(identityRef);
420 if (certificateRef)
421 CFRelease(certificateRef);
422 if (persistFind)
423 CFRelease(persistFind);
424 if (certData)
425 CFRelease(certData);
426
427 if (status != noErr && status != -1) {
428 plog(ASL_LEVEL_ERR,
429 "error %d %s.\n", (int)status, GetSecurityErrorString(status));
430 status = -1;
431 }
432 return cert;
433
434 }
435
436 /*
437 * Evaluate the trust of a cert using the policy provided
438 */
439 static OSStatus EvaluateCert(SecCertificateRef evalCertArray[], CFIndex evalCertArrayNumValues, CFTypeRef policyRef, SecKeyRef *publicKeyRef)
440 {
441 OSStatus status;
442 SecTrustRef trustRef = 0;
443 SecTrustResultType evalResult;
444
445 CFArrayRef errorStrings;
446
447 CFArrayRef cfCertRef = CFArrayCreate((CFAllocatorRef) NULL, (void*)evalCertArray, evalCertArrayNumValues,
448 &kCFTypeArrayCallBacks);
449
450 if (!cfCertRef) {
451 plog(ASL_LEVEL_ERR,
452 "unable to create CFArray.\n");
453 return -1;
454 }
455
456 status = SecTrustCreateWithCertificates(cfCertRef, policyRef, &trustRef);
457 if (status != noErr)
458 goto end;
459
460 status = SecTrustEvaluate(trustRef, &evalResult);
461 if (status != noErr)
462 goto end;
463
464 if (evalResult != kSecTrustResultProceed && evalResult != kSecTrustResultUnspecified) {
465 plog(ASL_LEVEL_ERR, "Error evaluating certificate.\n");
466
467 switch (evalResult) {
468 case kSecTrustResultInvalid:
469 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultInvalid.\n");
470 break;
471 case kSecTrustResultProceed:
472 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultProceed.\n");
473 break;
474 case kSecTrustResultDeny:
475 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultDeny.\n");
476 break;
477 case kSecTrustResultUnspecified:
478 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultUnspecified.\n");
479 break;
480 case kSecTrustResultRecoverableTrustFailure:
481 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultRecoverableTrustFailure.\n");
482 break;
483 case kSecTrustResultFatalTrustFailure:
484 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultFatalTrustFailure.\n");
485 break;
486 case kSecTrustResultOtherError:
487 plog(ASL_LEVEL_DEBUG, "eval result = kSecTrustResultOtherError.\n");
488 break;
489 default:
490 plog(ASL_LEVEL_DEBUG, "eval result unknown: value = %d.\n", (int)evalResult);
491 break;
492 }
493
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
502 plog(ASL_LEVEL_ERR, "---------------Returned error strings: ---------------.\n");
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)
510 plog(ASL_LEVEL_ERR, "type = %s.\n", str);
511 }
512 val = CFDictionaryGetValue(dict, kSecPropertyKeyValue);
513 if (val && (CFGetTypeID(val) == CFStringGetTypeID())) {
514 str = CFStringGetCStringPtr(val, kCFStringEncodingMacRoman);
515 if (str)
516 plog(ASL_LEVEL_ERR, "value = %s.\n", str);
517 }
518 }
519 }
520 plog(ASL_LEVEL_ERR, "-----------------------------------------------------.\n");
521 CFRelease(errorStrings);
522 }
523
524 status = -1;
525 goto end;
526 }
527
528 /* get and return the public key */
529 *publicKeyRef = SecTrustCopyPublicKey(trustRef);
530
531 end:
532 if (cfCertRef)
533 CFRelease(cfCertRef);
534 if (trustRef)
535 CFRelease(trustRef);
536
537 if (status != noErr && status != -1) {
538 plog(ASL_LEVEL_ERR,
539 "error %d %s.\n", (int)status, GetSecurityErrorString(status));
540 status = -1;
541 }
542 return status;
543 }
544
545 /*
546 * Return string representation of Security-related OSStatus.
547 */
548 const char *
549 GetSecurityErrorString(OSStatus err)
550 {
551 switch(err) {
552 case noErr:
553 return "noErr";
554
555 /* SecBase.h: */
556 case errSecNotAvailable:
557 return "errSecNotAvailable";
558
559 #if !TARGET_OS_EMBEDDED
560 case memFullErr:
561 return "memFullErr";
562 case paramErr:
563 return "paramErr";
564 case unimpErr:
565 return "unimpErr";
566
567 /* SecBase.h: */
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";
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";
628 #endif
629 case errSecDuplicateItem:
630 return "errSecDuplicateItem";
631 case errSecItemNotFound:
632 return "errSecItemNotFound";
633 default:
634 return "<unknown>";
635 }
636 }
637