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