3 * Copyright (c) 2001-2004 Apple Computer, Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
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.
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
21 * @APPLE_LICENSE_HEADER_END@
26 * Racoon module for verifying and signing certificates through Security
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>
36 #include <TargetConditionals.h>
37 #if TARGET_OS_EMBEDDED
38 #include <Security/SecItem.h>
39 #include <Security/SecTrustPriv.h>
40 #include <Security/SecPolicyPriv.h>
41 #include <Security/SecCertificatePriv.h>
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>
50 #include <Security/SecKeyPriv.h>
51 #include <Security/oidsalg.h>
52 #include <Security/cssmapi.h>
53 #include <Security/SecPolicySearch.h>
56 #include <CoreFoundation/CoreFoundation.h>
57 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
64 #include "crypto_cssm.h"
67 static OSStatus
EvaluateCert(SecCertificateRef cert
, CFTypeRef policyRef
);
68 static const char *GetSecurityErrorString(OSStatus err
);
69 #if !TARGET_OS_EMBEDDED
70 static OSStatus
FindPolicy(const CSSM_OID
*policyOID
, SecPolicyRef
*policyRef
);
71 static OSStatus
CopySystemKeychain(SecKeychainRef
*keychainRef
);
75 * Verify cert using security framework
77 int crypto_cssm_check_x509cert(vchar_t
*cert
, CFStringRef hostname
, cert_status_t certStatus
)
80 SecCertificateRef certRef
= NULL
;
81 SecPolicyRef policyRef
= NULL
;
83 #if !TARGET_OS_EMBEDDED
85 CSSM_OID ourPolicyOID
= CSSMOID_APPLE_TP_IP_SEC
;
88 certData
.Length
= cert
->l
;
89 certData
.Data
= (uint8
*)cert
->v
;
90 status
= SecCertificateCreateFromData(&certData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
95 // get our policy object
96 status
= FindPolicy(&ourPolicyOID
, &policyRef
);
99 // no options used at present - verification of subjectAltName fields, etc.
100 // are done elsewhere in racoon in oakley_check_certid()
103 CFDataRef cert_data
= CFDataCreateWithBytesNoCopy(NULL
, cert
->v
, cert
->l
, kCFAllocatorNull
);
105 certRef
= SecCertificateCreateWithData(NULL
, cert_data
);
106 CFRelease(cert_data
);
109 if (certRef
== NULL
) {
110 plog(LLV_ERROR
, LOCATION
, NULL
,
111 "unable to create a certRef.\n");
117 policyRef
= SecPolicyCreateIPSec(FALSE
, hostname
);
118 if (policyRef
== NULL
) {
119 plog(LLV_ERROR
, LOCATION
, NULL
,
120 "unable to create a SSL policyRef.\n");
129 status
= EvaluateCert(certRef
, policyRef
);
136 CFRelease(policyRef
);
138 if (status
!= noErr
&& status
!= -1) {
139 plog(LLV_ERROR
, LOCATION
, NULL
,
140 "error %d %s.\n", status
, GetSecurityErrorString(status
));
142 } else if (certStatus
) {
143 plog(LLV_ERROR
, LOCATION
, NULL
,
144 "certificate failed date verification: %d.\n", certStatus
);
152 * Encrypt a hash via CSSM using the private key in the keychain
155 vchar_t
* crypto_cssm_getsign(CFDataRef persistentCertRef
, vchar_t
* hash
)
159 SecIdentityRef identityRef
= NULL
;
160 SecKeyRef privateKeyRef
= NULL
;
163 #if !TARGET_OS_EMBEDDED
164 u_int32_t bytesEncrypted
= 0;
165 SecCertificateRef certificateRef
= NULL
;
166 SecIdentitySearchRef idSearchRef
= NULL
;
167 SecKeychainRef keychainRef
= NULL
;
168 const CSSM_KEY
*cssmKey
= NULL
;
169 CSSM_CSP_HANDLE cspHandle
= nil
;
170 CSSM_CC_HANDLE cssmContextHandle
= nil
;
171 const CSSM_ACCESS_CREDENTIALS
*credentials
= NULL
;
172 //CSSM_SIZE bytesEncrypted = 0; //%%%%HWR fix this - need new headers on Leopard
174 CSSM_DATA cipherData
;
176 CSSM_CONTEXT_ATTRIBUTE newAttr
;
181 if (persistentCertRef
) {
182 // get cert from keychain
183 status
= SecKeychainItemCopyFromPersistentReference(persistentCertRef
, (SecKeychainItemRef
*)&certificateRef
);
187 // get keychain ref where cert is contained
188 status
= SecKeychainItemCopyKeychain((SecKeychainItemRef
)certificateRef
, &keychainRef
);
192 // get identity from the certificate
193 status
= SecIdentityCreateWithCertificate(keychainRef
, certificateRef
, &identityRef
);
199 // copy system keychain
200 status
= CopySystemKeychain(&keychainRef
);
204 // serach for first identity in system keychain
205 status
= SecIdentitySearchCreate(keychainRef
, CSSM_KEYUSE_SIGN
, &idSearchRef
);
209 status
= SecIdentitySearchCopyNext(idSearchRef
, &identityRef
);
213 // get certificate from identity
214 status
= SecIdentityCopyCertificate(identityRef
, &certificateRef
);
219 // get private key from identity
220 status
= SecIdentityCopyPrivateKey(identityRef
, &privateKeyRef
);
224 // get CSSM_KEY pointer from key ref
225 status
= SecKeyGetCSSMKey(privateKeyRef
, &cssmKey
);
229 // get CSSM CSP handle
230 status
= SecKeychainGetCSPHandle(keychainRef
, &cspHandle
);
234 // create CSSM credentials to unlock private key for encryption - no UI to be used
235 status
= SecKeyGetCredentials(privateKeyRef
, CSSM_ACL_AUTHORIZATION_ENCRYPT
,
236 kSecCredentialTypeNoUI
, &credentials
);
240 // create asymmetric context for encryption
241 status
= CSSM_CSP_CreateAsymmetricContext(cspHandle
, CSSM_ALGID_RSA
, credentials
, cssmKey
,
242 CSSM_PADDING_PKCS1
, &cssmContextHandle
);
246 // add mode attribute to use private key for encryption
247 newAttr
.AttributeType
= CSSM_ATTRIBUTE_MODE
;
248 newAttr
.AttributeLength
= sizeof(uint32
);
249 newAttr
.Attribute
.Data
= (CSSM_DATA_PTR
)CSSM_ALGMODE_PRIVATE_KEY
;
250 status
= CSSM_UpdateContextAttributes(cssmContextHandle
, 1, &newAttr
);
254 // and finally - encrypt data
255 clearData
.Length
= hash
->l
;
256 clearData
.Data
= (uint8
*)hash
->v
;
257 cipherData
.Length
= 0;
258 cipherData
.Data
= NULL
;
259 status
= CSSM_EncryptData(cssmContextHandle
, &clearData
, 1, &cipherData
, 1, &bytesEncrypted
,
264 if (remData
.Length
!= 0) { // something didn't go right - should be zero
266 plog(LLV_ERROR
, LOCATION
, NULL
,
267 "unencrypted data remaining after encrypting hash.\n");
271 // alloc buffer for result
276 sig
->l
= cipherData
.Length
;
277 sig
->v
= (caddr_t
)cipherData
.Data
;
281 CFDictionaryRef persistFind
= NULL
;
282 const void *keys_persist
[] = { kSecReturnRef
, kSecValuePersistentRef
};
283 const void *values_persist
[] = { kCFBooleanTrue
, persistentCertRef
};
285 #define SIG_BUF_SIZE 1024
287 /* find identity by persistent ref */
288 persistFind
= CFDictionaryCreate(NULL
, keys_persist
, values_persist
,
289 (sizeof(keys_persist
) / sizeof(*keys_persist
)), NULL
, NULL
);
290 if (persistFind
== NULL
)
293 status
= SecItemCopyMatching(persistFind
, (CFTypeRef
*)&identityRef
);
297 status
= SecIdentityCopyPrivateKey(identityRef
, &privateKeyRef
);
301 // alloc buffer for result
302 sig
= vmalloc(SIG_BUF_SIZE
);
306 status
= SecKeyRawSign(privateKeyRef
, kSecPaddingPKCS1
, hash
->v
,
307 hash
->l
, sig
->v
, &sig
->l
);
314 CFRelease(identityRef
);
316 CFRelease(privateKeyRef
);
318 #if !TARGET_OS_EMBEDDED
320 CFRelease(certificateRef
);
322 CFRelease(keychainRef
);
324 CFRelease(idSearchRef
);
325 if (cssmContextHandle
)
326 CSSM_DeleteContext(cssmContextHandle
);
329 CFRelease(persistFind
);
332 if (status
!= noErr
) {
339 if (status
!= noErr
&& status
!= -1) {
340 plog(LLV_ERROR
, LOCATION
, NULL
,
341 "error %d %s.\n", status
, GetSecurityErrorString(status
));
350 * Retrieve a cert from the keychain
352 vchar_t
* crypto_cssm_get_x509cert(CFDataRef persistentCertRef
,
353 cert_status_t
*certStatus
)
357 vchar_t
*cert
= NULL
;
358 SecIdentityRef identityRef
= NULL
;
359 SecCertificateRef certificateRef
= NULL
;
361 #if !TARGET_OS_EMBEDDED
363 SecIdentitySearchRef idSearchRef
= NULL
;
364 SecKeychainRef keychainRef
= NULL
;
367 if (persistentCertRef
) {
368 status
= SecKeychainItemCopyFromPersistentReference(persistentCertRef
, (SecKeychainItemRef
*)&certificateRef
);
372 // copy system keychain
373 status
= CopySystemKeychain(&keychainRef
);
377 // find first identity in system keychain
378 status
= SecIdentitySearchCreate(keychainRef
, CSSM_KEYUSE_SIGN
, &idSearchRef
);
382 status
= SecIdentitySearchCopyNext(idSearchRef
, &identityRef
);
386 // get certificate from identity
387 status
= SecIdentityCopyCertificate(identityRef
, &certificateRef
);
393 // get certificate data
395 cssmData
.Data
= NULL
;
396 status
= SecCertificateGetData(certificateRef
, &cssmData
);
400 if (cssmData
.Length
== 0)
403 cert
= vmalloc(cssmData
.Length
);
407 // cssmData struct just points to the data
408 // data must be copied to be returned
409 memcpy(cert
->v
, cssmData
.Data
, cssmData
.Length
);
411 // verify expiry or missing fields
413 *certStatus
= CERT_STATUS_OK
;
417 CFDictionaryRef persistFind
= NULL
;
418 const void *keys_persist
[] = { kSecReturnRef
, kSecValuePersistentRef
};
419 const void *values_persist
[] = { kCFBooleanTrue
, persistentCertRef
};
421 CFDataRef certData
= NULL
;
422 CFAbsoluteTime timeNow
= 0;
423 CFAbsoluteTime notvalidbeforedate
= 0;
424 CFAbsoluteTime notvalidafterdate
= 0;
425 CFDateRef nowcfdatedata
= NULL
;
426 CFDateRef notvalidbeforedatedata
= NULL
;
427 CFDateRef notvalidafterdatedata
= NULL
;
428 CFArrayRef certProparray
= NULL
;
430 CFDictionaryRef
*values
= NULL
;
431 CFDictionaryRef propDict
= NULL
;
432 const void *datevalue
= NULL
;
433 const void *labelvalue
= NULL
;
434 CFGregorianDate gregoriandate
;
438 /* find identity by persistent ref */
439 persistFind
= CFDictionaryCreate(NULL
, keys_persist
, values_persist
,
440 (sizeof(keys_persist
) / sizeof(*keys_persist
)), NULL
, NULL
);
441 if (persistFind
== NULL
)
444 status
= SecItemCopyMatching(persistFind
, (CFTypeRef
*)&identityRef
);
448 status
= SecIdentityCopyCertificate(identityRef
, &certificateRef
);
452 certData
= SecCertificateCopyData(certificateRef
);
453 if (certData
== NULL
)
456 dataLen
= CFDataGetLength(certData
);
460 cert
= vmalloc(dataLen
);
464 CFDataGetBytes(certData
, CFRangeMake(0, dataLen
), cert
->v
);
466 // verify expiry or missing fields
469 *certStatus
= CERT_STATUS_OK
;
471 if ((certProparray
= SecCertificateCopyProperties(certificateRef
))){
472 if ((count
= CFArrayGetCount( certProparray
))){
474 range
.length
= count
;
475 if ( (values
= CFAllocatorAllocate(NULL
, count
* sizeof(CFDictionaryRef
), 0))){
476 CFArrayGetValues(certProparray
, range
, (const void **)values
);
477 for( i
= 0; i
< count
; i
++)
479 if ((propDict
= values
[i
])){
480 if ( CFDictionaryContainsValue(propDict
, kSecPropertyTypeDate
) ){
481 if ( CFDictionaryGetValueIfPresent(propDict
, kSecPropertyKeyValue
, (const void**)&datevalue
)){
482 /* get kSecPropertyKeyLabel */
483 if ( (datevalue
) && (CFDictionaryGetValueIfPresent(propDict
, kSecPropertyKeyLabel
, (const void**)&labelvalue
))){
484 if ( (labelvalue
) && (CFStringCompare( (CFStringRef
)labelvalue
, CFSTR("Not Valid Before"), 0) == kCFCompareEqualTo
)){
485 if ( notvalidbeforedate
= CFDateGetAbsoluteTime(datevalue
))
486 notvalidbeforedatedata
= CFDateCreate(NULL
, notvalidbeforedate
);
487 }else if ((labelvalue
) && (CFStringCompare( (CFStringRef
)labelvalue
, CFSTR("Not Valid After"), 0 ) == kCFCompareEqualTo
)){
488 if ( notvalidafterdate
= CFDateGetAbsoluteTime(datevalue
))
489 notvalidafterdatedata
= CFDateCreate(NULL
, notvalidafterdate
);
501 if ( (timeNow
= CFAbsoluteTimeGetCurrent()) && (nowcfdatedata
= CFDateCreate( NULL
, timeNow
))){
502 if ( notvalidbeforedatedata
){
503 gregoriandate
= CFAbsoluteTimeGetGregorianDate(notvalidbeforedate
, NULL
);
504 plog(LLV_DEBUG
, LOCATION
, NULL
,
505 "cert not valid before yr %d, mon %d, days %d, hours %d, min %d\n", gregoriandate
.year
, gregoriandate
.month
, gregoriandate
.day
, gregoriandate
.hour
, gregoriandate
.minute
);
506 gregoriandate
= CFAbsoluteTimeGetGregorianDate(notvalidafterdate
, NULL
);
507 plog(LLV_DEBUG
, LOCATION
, NULL
,
508 "cert not valid after yr %d, mon %d, days %d, hours %d, min %d\n", gregoriandate
.year
, gregoriandate
.month
, gregoriandate
.day
, gregoriandate
.hour
, gregoriandate
.minute
);
509 if ( CFDateCompare( nowcfdatedata
, notvalidbeforedatedata
, NULL
) == kCFCompareLessThan
){
510 plog(LLV_ERROR
, LOCATION
, NULL
,
511 "current time before valid time\n");
512 *certStatus
= CERT_STATUS_PREMATURE
;
514 else if (notvalidafterdatedata
&& (CFDateCompare( nowcfdatedata
, notvalidafterdatedata
, NULL
) == kCFCompareGreaterThan
)){
515 plog(LLV_ERROR
, LOCATION
, NULL
,
516 "current time after valid time\n");
517 *certStatus
= CERT_STATUS_EXPIRED
;
519 plog(LLV_INFO
, LOCATION
, NULL
, "certificate expiration date OK\n");
520 *certStatus
= CERT_STATUS_OK
;
532 CFRelease(certificateRef
);
534 CFRelease(identityRef
);
535 #if !TARGET_OS_EMBEDDED
537 CFRelease(idSearchRef
);
539 CFRelease(keychainRef
);
541 if (notvalidbeforedatedata
)
542 CFRelease(notvalidbeforedatedata
);
543 if (notvalidafterdatedata
)
544 CFRelease(notvalidafterdatedata
);
546 CFRelease(certProparray
);
548 CFAllocatorDeallocate(NULL
, values
);
550 CFRelease(nowcfdatedata
);
552 CFRelease(persistFind
);
557 if (status
!= noErr
&& status
!= -1) {
558 plog(LLV_ERROR
, LOCATION
, NULL
,
559 "error %d %s.\n", status
, GetSecurityErrorString(status
));
566 #if !TARGET_OS_EMBEDDED
568 * Find a policy ref by OID
570 static OSStatus
FindPolicy(const CSSM_OID
*policyOID
, SecPolicyRef
*policyRef
)
574 SecPolicySearchRef searchRef
= nil
;
576 status
= SecPolicySearchCreate(CSSM_CERT_X_509v3
, policyOID
, NULL
, &searchRef
);
580 status
= SecPolicySearchCopyNext(searchRef
, policyRef
);
584 CFRelease(searchRef
);
586 if (status
!= noErr
) {
587 plog(LLV_ERROR
, LOCATION
, NULL
,
588 "error %d %s.\n", status
, GetSecurityErrorString(status
));
596 * Evaluate the trust of a cert using the policy provided
598 static OSStatus
EvaluateCert(SecCertificateRef cert
, CFTypeRef policyRef
)
601 SecTrustRef trustRef
= 0;
602 SecTrustResultType evalResult
;
604 #if TARGET_OS_EMBEDDED
605 CFArrayRef errorStrings
;
607 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
;
608 CFArrayRef certChain
;
611 SecCertificateRef evalCertArray
[1] = { cert
};
613 CFArrayRef cfCertRef
= CFArrayCreate((CFAllocatorRef
) NULL
, (void*)evalCertArray
, 1,
614 &kCFTypeArrayCallBacks
);
617 plog(LLV_ERROR
, LOCATION
, NULL
,
618 "unable to create CFArray.\n");
622 status
= SecTrustCreateWithCertificates(cfCertRef
, policyRef
, &trustRef
);
626 status
= SecTrustEvaluate(trustRef
, &evalResult
);
630 if (evalResult
!= kSecTrustResultProceed
&& evalResult
!= kSecTrustResultUnspecified
) {
631 plog(LLV_ERROR
, LOCATION
, NULL
, "Error evaluating certificate.\n");
633 switch (evalResult
) {
634 case kSecTrustResultInvalid
:
635 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultInvalid.\n");
637 case kSecTrustResultProceed
:
638 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultProceed.\n");
640 case kSecTrustResultConfirm
:
641 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultConfirm.\n");
643 case kSecTrustResultDeny
:
644 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultDeny.\n");
646 case kSecTrustResultUnspecified
:
647 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultUnspecified.\n");
649 case kSecTrustResultRecoverableTrustFailure
:
650 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultRecoverableTrustFailure.\n");
652 case kSecTrustResultFatalTrustFailure
:
653 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultFatalTrustFailure.\n");
655 case kSecTrustResultOtherError
:
656 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultOtherError.\n");
659 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result unknown: value = %d.\n", (int)evalResult
);
664 #if TARGET_OS_EMBEDDED
665 errorStrings
= SecTrustCopyProperties(trustRef
);
668 CFDictionaryRef dict
;
671 CFIndex count
, maxcount
= CFArrayGetCount(errorStrings
);
673 plog(LLV_ERROR
, LOCATION
, NULL
, "---------------Returned error strings: ---------------.\n");
674 for (count
= 0; count
< maxcount
; count
++) {
675 dict
= CFArrayGetValueAtIndex(errorStrings
, count
);
676 if (dict
&& (CFGetTypeID(dict
) == CFDictionaryGetTypeID())) {
677 val
= CFDictionaryGetValue(dict
, kSecPropertyKeyType
);
678 if (val
&& (CFGetTypeID(val
) == CFStringGetTypeID())) {
679 str
= CFStringGetCStringPtr(val
, kCFStringEncodingMacRoman
);
681 plog(LLV_ERROR
, LOCATION
, NULL
, "type = %s.\n", str
);
683 val
= CFDictionaryGetValue(dict
, kSecPropertyKeyValue
);
684 if (val
&& (CFGetTypeID(val
) == CFStringGetTypeID())) {
685 str
= CFStringGetCStringPtr(val
, kCFStringEncodingMacRoman
);
687 plog(LLV_ERROR
, LOCATION
, NULL
, "value = %s.\n", str
);
691 plog(LLV_ERROR
, LOCATION
, NULL
, "-----------------------------------------------------.\n");
692 CFRelease(errorStrings
);
696 SecTrustGetResult(trustRef
, &evalResult
, &certChain
, &statusChain
);
697 plog(LLV_ERROR
, LOCATION
, NULL
, "Cert status bits = 0x%x.\n", statusChain
->StatusBits
);
698 plog(LLV_ERROR
, LOCATION
, NULL
, "Cert status NumStatusCodes = 0x%x.\n", statusChain
->NumStatusCodes
);
701 for (i
= 0; i
< statusChain
->NumStatusCodes
; i
++)
702 plog(LLV_ERROR
, LOCATION
, NULL
, "Cert status code i = 0x%x %d.\n", *(statusChain
->StatusCodes
+ i
), *(statusChain
->StatusCodes
+ i
));
704 plog(LLV_ERROR
, LOCATION
, NULL
, "Cert status Index = %d.\n", statusChain
->Index
);
705 CFRelease(certChain
);
714 CFRelease(cfCertRef
);
718 if (status
!= noErr
&& status
!= -1) {
719 plog(LLV_ERROR
, LOCATION
, NULL
,
720 "error %d %s.\n", status
, GetSecurityErrorString(status
));
726 #if !TARGET_OS_EMBEDDED
728 * Copy the system keychain
730 static OSStatus
CopySystemKeychain(SecKeychainRef
*keychainRef
)
735 status
= SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem
);
739 status
= SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem
, keychainRef
);
743 if (status
!= noErr
) {
744 plog(LLV_ERROR
, LOCATION
, NULL
,
745 "error %d %s.\n", status
, GetSecurityErrorString(status
));
754 * Return string representation of Security-related OSStatus.
757 GetSecurityErrorString(OSStatus err
)
770 case errSecNotAvailable
:
771 return "errSecNotAvailable";
772 #if !TARGET_OS_EMBEDDED
774 return "errSecReadOnly";
775 case errSecAuthFailed
:
776 return "errSecAuthFailed";
777 case errSecNoSuchKeychain
:
778 return "errSecNoSuchKeychain";
779 case errSecInvalidKeychain
:
780 return "errSecInvalidKeychain";
781 case errSecDuplicateKeychain
:
782 return "errSecDuplicateKeychain";
783 case errSecDuplicateCallback
:
784 return "errSecDuplicateCallback";
785 case errSecInvalidCallback
:
786 return "errSecInvalidCallback";
787 case errSecBufferTooSmall
:
788 return "errSecBufferTooSmall";
789 case errSecDataTooLarge
:
790 return "errSecDataTooLarge";
791 case errSecNoSuchAttr
:
792 return "errSecNoSuchAttr";
793 case errSecInvalidItemRef
:
794 return "errSecInvalidItemRef";
795 case errSecInvalidSearchRef
:
796 return "errSecInvalidSearchRef";
797 case errSecNoSuchClass
:
798 return "errSecNoSuchClass";
799 case errSecNoDefaultKeychain
:
800 return "errSecNoDefaultKeychain";
801 case errSecInteractionNotAllowed
:
802 return "errSecInteractionNotAllowed";
803 case errSecReadOnlyAttr
:
804 return "errSecReadOnlyAttr";
805 case errSecWrongSecVersion
:
806 return "errSecWrongSecVersion";
807 case errSecKeySizeNotAllowed
:
808 return "errSecKeySizeNotAllowed";
809 case errSecNoStorageModule
:
810 return "errSecNoStorageModule";
811 case errSecNoCertificateModule
:
812 return "errSecNoCertificateModule";
813 case errSecNoPolicyModule
:
814 return "errSecNoPolicyModule";
815 case errSecInteractionRequired
:
816 return "errSecInteractionRequired";
817 case errSecDataNotAvailable
:
818 return "errSecDataNotAvailable";
819 case errSecDataNotModifiable
:
820 return "errSecDataNotModifiable";
821 case errSecCreateChainFailed
:
822 return "errSecCreateChainFailed";
823 case errSecACLNotSimple
:
824 return "errSecACLNotSimple";
825 case errSecPolicyNotFound
:
826 return "errSecPolicyNotFound";
827 case errSecInvalidTrustSetting
:
828 return "errSecInvalidTrustSetting";
829 case errSecNoAccessForItem
:
830 return "errSecNoAccessForItem";
831 case errSecInvalidOwnerEdit
:
832 return "errSecInvalidOwnerEdit";
834 case errSecDuplicateItem
:
835 return "errSecDuplicateItem";
836 case errSecItemNotFound
:
837 return "errSecItemNotFound";