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"
66 #if TARGET_OS_EMBEDDED
67 static OSStatus
EvaluateCert(SecCertificateRef evalCertArray
[], CFIndex evalCertArrayNumValues
, CFTypeRef policyRef
, SecKeyRef
*publicKeyRef
);
69 static OSStatus
EvaluateCert(SecCertificateRef evalCertArray
[], CFIndex evalCertArrayNumValues
, CFTypeRef policyRef
);
72 #if !TARGET_OS_EMBEDDED
73 static OSStatus
FindPolicy(const CSSM_OID
*policyOID
, SecPolicyRef
*policyRef
);
74 static OSStatus
CopySystemKeychain(SecKeychainRef
*keychainRef
);
78 crypto_cssm_x509cert_get_SecPolicyRef (CFStringRef hostname
)
81 SecPolicyRef policyRef
= NULL
;
82 #if !TARGET_OS_EMBEDDED
83 CSSM_OID ourPolicyOID
= CSSMOID_APPLE_TP_IP_SEC
;
85 // get our policy object
86 status
= FindPolicy(&ourPolicyOID
, &policyRef
);
87 if (status
!= noErr
&& status
!= -1) {
88 plog(LLV_ERROR
, LOCATION
, NULL
,
89 "error %d %s.\n", status
, GetSecurityErrorString(status
));
93 policyRef
= SecPolicyCreateIPSec(FALSE
, hostname
);
94 if (policyRef
== NULL
) {
95 plog(LLV_ERROR
, LOCATION
, NULL
,
96 "unable to create a SSL policyRef.\n");
104 crypto_cssm_x509cert_get_SecCertificateRef (vchar_t
*cert
)
107 SecCertificateRef certRef
= NULL
;
108 #if !TARGET_OS_EMBEDDED
112 certData
.Length
= cert
->l
;
113 certData
.Data
= (uint8
*)cert
->v
;
114 status
= SecCertificateCreateFromData(&certData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
,
116 if (status
!= noErr
&& status
!= -1) {
117 plog(LLV_ERROR
, LOCATION
, NULL
,
118 "error %d %s.\n", status
, GetSecurityErrorString(status
));
121 CFDataRef cert_data
= CFDataCreateWithBytesNoCopy(NULL
, cert
->v
, cert
->l
, kCFAllocatorNull
);
123 certRef
= SecCertificateCreateWithData(NULL
, cert_data
);
124 CFRelease(cert_data
);
127 if (certRef
== NULL
) {
128 plog(LLV_ERROR
, LOCATION
, NULL
,
129 "unable to create a certRef.\n");
135 crypto_cssm_check_x509cert_dates (SecCertificateRef certificateRef
)
137 cert_status_t certStatus
= CERT_STATUS_OK
;
138 #if TARGET_OS_EMBEDDED
139 CFAbsoluteTime timeNow
= 0;
140 CFAbsoluteTime notvalidbeforedate
= 0;
141 CFAbsoluteTime notvalidafterdate
= 0;
142 CFDateRef nowcfdatedata
= NULL
;
143 CFDateRef notvalidbeforedatedata
= NULL
;
144 CFDateRef notvalidafterdatedata
= NULL
;
145 CFArrayRef certProparray
= NULL
;
146 CFDictionaryRef propDict
= NULL
;
147 const void *datevalue
= NULL
;
148 const void *labelvalue
= NULL
;
149 CFGregorianDate gregoriandate
;
153 if ((certProparray
= SecCertificateCopyProperties(certificateRef
))){
154 if ((count
= CFArrayGetCount( certProparray
))){
155 for( i
= 0; i
< count
; i
++) {
156 if ((propDict
= CFArrayGetValueAtIndex(certProparray
, i
))) {
157 if ( CFDictionaryGetValueIfPresent(propDict
, kSecPropertyKeyValue
, (const void**)&datevalue
)){
158 /* get kSecPropertyKeyLabel */
159 if ( (datevalue
) && (CFDictionaryGetValueIfPresent(propDict
, kSecPropertyKeyLabel
, (const void**)&labelvalue
))){
160 if ( (labelvalue
) && (CFStringCompare( (CFStringRef
)labelvalue
, CFSTR("Not Valid Before"), 0) == kCFCompareEqualTo
)){
161 if ( notvalidbeforedate
= CFDateGetAbsoluteTime(datevalue
)) {
162 if (notvalidbeforedatedata
) {
163 CFRelease(notvalidbeforedatedata
);
165 notvalidbeforedatedata
= CFDateCreate(NULL
, notvalidbeforedate
);
167 }else if ((labelvalue
) && (CFStringCompare( (CFStringRef
)labelvalue
, CFSTR("Not Valid After"), 0 ) == kCFCompareEqualTo
)){
168 if ( notvalidafterdate
= CFDateGetAbsoluteTime(datevalue
)) {
169 if (notvalidafterdatedata
) {
170 CFRelease(notvalidafterdatedata
);
172 notvalidafterdatedata
= CFDateCreate(NULL
, notvalidafterdate
);
182 if ( (timeNow
= CFAbsoluteTimeGetCurrent()) && (nowcfdatedata
= CFDateCreate( NULL
, timeNow
))){
183 if ( notvalidbeforedatedata
){
184 gregoriandate
= CFAbsoluteTimeGetGregorianDate(notvalidbeforedate
, NULL
);
185 plog(LLV_DEBUG
, LOCATION
, NULL
,
186 "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
);
187 gregoriandate
= CFAbsoluteTimeGetGregorianDate(notvalidafterdate
, NULL
);
188 plog(LLV_DEBUG
, LOCATION
, NULL
,
189 "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
);
190 if ( CFDateCompare( nowcfdatedata
, notvalidbeforedatedata
, NULL
) == kCFCompareLessThan
){
191 plog(LLV_ERROR
, LOCATION
, NULL
,
192 "current time before valid time\n");
193 certStatus
= CERT_STATUS_PREMATURE
;
194 } else if (notvalidafterdatedata
&& (CFDateCompare( nowcfdatedata
, notvalidafterdatedata
, NULL
) == kCFCompareGreaterThan
)){
195 plog(LLV_ERROR
, LOCATION
, NULL
,
196 "current time after valid time\n");
197 certStatus
= CERT_STATUS_EXPIRED
;
199 plog(LLV_INFO
, LOCATION
, NULL
, "certificate expiration date OK\n");
200 certStatus
= CERT_STATUS_OK
;
205 if (notvalidbeforedatedata
)
206 CFRelease(notvalidbeforedatedata
);
207 if (notvalidafterdatedata
)
208 CFRelease(notvalidafterdatedata
);
210 CFRelease(certProparray
);
212 CFRelease(nowcfdatedata
);
218 * Verify cert using security framework
220 #if TARGET_OS_EMBEDDED
221 int crypto_cssm_check_x509cert (cert_t
*hostcert
, cert_t
*certchain
, CFStringRef hostname
, SecKeyRef
*publicKeyRef
)
223 int crypto_cssm_check_x509cert (cert_t
*hostcert
, cert_t
*certchain
, CFStringRef hostname
)
227 cert_status_t certStatus
= 0;
229 CFIndex certArrayRefNumValues
= 0;
232 SecCertificateRef
*certArrayRef
= NULL
;
233 SecPolicyRef policyRef
= crypto_cssm_x509cert_get_SecPolicyRef(hostname
);
235 if (!hostcert
|| !certchain
) {
239 // find the total number of certs
240 for (p
= certchain
; p
; p
= p
->chain
, n
++);
242 plog(LLV_DEBUG2
, LOCATION
, NULL
,
243 "%s: checking chain of %d certificates.\n", __FUNCTION__
, n
);
246 certArraySiz
= n
* sizeof(CFTypeRef
);
247 certArrayRef
= CFAllocatorAllocate(NULL
, certArraySiz
, 0);
251 bzero(certArrayRef
, certArraySiz
);
252 if ((certArrayRef
[certArrayRefNumValues
] = crypto_cssm_x509cert_get_SecCertificateRef(&hostcert
->cert
))) {
253 /* don't overwrite any pending status */
254 if (!hostcert
->status
) {
255 hostcert
->status
= crypto_cssm_check_x509cert_dates(certArrayRef
[certArrayRefNumValues
]);
256 if (hostcert
->status
) {
257 plog(LLV_ERROR
, LOCATION
, NULL
,
258 "host certificate failed date verification: %d.\n", hostcert
->status
);
259 certStatus
= hostcert
->status
;
262 certArrayRefNumValues
++;
264 for (p
= certchain
; p
&& certArrayRefNumValues
< n
; p
= p
->chain
) {
266 if ((certArrayRef
[certArrayRefNumValues
] = crypto_cssm_x509cert_get_SecCertificateRef(&p
->cert
))) {
267 /* don't overwrite any pending status */
269 p
->status
= crypto_cssm_check_x509cert_dates(certArrayRef
[certArrayRefNumValues
]);
271 plog(LLV_ERROR
, LOCATION
, NULL
,
272 "other certificate in chain failed date verification: %d.\n", p
->status
);
274 certStatus
= p
->status
;
278 certArrayRefNumValues
++;
284 #if TARGET_OS_EMBEDDED
285 status
= EvaluateCert(certArrayRef
, certArrayRefNumValues
, policyRef
, publicKeyRef
);
287 status
= EvaluateCert(certArrayRef
, certArrayRefNumValues
, policyRef
);
290 while (certArrayRefNumValues
) {
291 CFRelease(certArrayRef
[--certArrayRefNumValues
]);
293 CFAllocatorDeallocate(NULL
, certArrayRef
);
296 CFRelease(policyRef
);
298 if (status
!= noErr
&& status
!= -1) {
299 plog(LLV_ERROR
, LOCATION
, NULL
,
300 "error %d %s.\n", status
, GetSecurityErrorString(status
));
302 } else if (certStatus
== CERT_STATUS_PREMATURE
|| certStatus
== CERT_STATUS_EXPIRED
) {
309 #if TARGET_OS_EMBEDDED
310 int crypto_cssm_verify_x509sign(SecKeyRef publicKeyRef
, vchar_t
*hash
, vchar_t
*signature
)
312 return SecKeyRawVerify(publicKeyRef
, kSecPaddingPKCS1
, hash
->v
, hash
->l
, signature
->v
, signature
->l
);
317 * Encrypt a hash via CSSM using the private key in the keychain
320 vchar_t
* crypto_cssm_getsign(CFDataRef persistentCertRef
, vchar_t
* hash
)
323 OSStatus status
= -1;
324 SecIdentityRef identityRef
= NULL
;
325 SecKeyRef privateKeyRef
= NULL
;
328 #if !TARGET_OS_EMBEDDED
329 CSSM_SIZE bytesEncrypted
= 0;
330 SecCertificateRef certificateRef
= NULL
;
331 SecIdentitySearchRef idSearchRef
= NULL
;
332 SecKeychainRef keychainRef
= NULL
;
333 const CSSM_KEY
*cssmKey
= NULL
;
334 CSSM_CSP_HANDLE cspHandle
= nil
;
335 CSSM_CC_HANDLE cssmContextHandle
= nil
;
336 const CSSM_ACCESS_CREDENTIALS
*credentials
= NULL
;
338 CSSM_DATA cipherData
;
340 CSSM_CONTEXT_ATTRIBUTE newAttr
;
345 if (persistentCertRef
) {
346 // get cert from keychain
347 status
= SecKeychainItemCopyFromPersistentReference(persistentCertRef
, (SecKeychainItemRef
*)&certificateRef
);
351 // get keychain ref where cert is contained
352 status
= SecKeychainItemCopyKeychain((SecKeychainItemRef
)certificateRef
, &keychainRef
);
356 // get identity from the certificate
357 status
= SecIdentityCreateWithCertificate(keychainRef
, certificateRef
, &identityRef
);
363 // copy system keychain
364 status
= CopySystemKeychain(&keychainRef
);
368 // serach for first identity in system keychain
369 status
= SecIdentitySearchCreate(keychainRef
, CSSM_KEYUSE_SIGN
, &idSearchRef
);
373 status
= SecIdentitySearchCopyNext(idSearchRef
, &identityRef
);
377 // get certificate from identity
378 status
= SecIdentityCopyCertificate(identityRef
, &certificateRef
);
383 // get private key from identity
384 status
= SecIdentityCopyPrivateKey(identityRef
, &privateKeyRef
);
388 // get CSSM_KEY pointer from key ref
389 status
= SecKeyGetCSSMKey(privateKeyRef
, &cssmKey
);
393 // get CSSM CSP handle
394 status
= SecKeychainGetCSPHandle(keychainRef
, &cspHandle
);
398 // create CSSM credentials to unlock private key for encryption - no UI to be used
399 status
= SecKeyGetCredentials(privateKeyRef
, CSSM_ACL_AUTHORIZATION_ENCRYPT
,
400 kSecCredentialTypeNoUI
, &credentials
);
404 // create asymmetric context for encryption
405 status
= CSSM_CSP_CreateAsymmetricContext(cspHandle
, CSSM_ALGID_RSA
, credentials
, cssmKey
,
406 CSSM_PADDING_PKCS1
, &cssmContextHandle
);
410 // add mode attribute to use private key for encryption
411 newAttr
.AttributeType
= CSSM_ATTRIBUTE_MODE
;
412 newAttr
.AttributeLength
= sizeof(uint32
);
413 newAttr
.Attribute
.Data
= (CSSM_DATA_PTR
)CSSM_ALGMODE_PRIVATE_KEY
;
414 status
= CSSM_UpdateContextAttributes(cssmContextHandle
, 1, &newAttr
);
418 // and finally - encrypt data
419 clearData
.Length
= hash
->l
;
420 clearData
.Data
= (uint8
*)hash
->v
;
421 cipherData
.Length
= 0;
422 cipherData
.Data
= NULL
;
423 status
= CSSM_EncryptData(cssmContextHandle
, &clearData
, 1, &cipherData
, 1, &bytesEncrypted
,
428 if (remData
.Length
!= 0) { // something didn't go right - should be zero
430 plog(LLV_ERROR
, LOCATION
, NULL
,
431 "unencrypted data remaining after encrypting hash.\n");
435 // alloc buffer for result
440 sig
->l
= cipherData
.Length
;
441 sig
->v
= (caddr_t
)cipherData
.Data
;
445 CFDictionaryRef persistFind
= NULL
;
446 const void *keys_persist
[] = { kSecReturnRef
, kSecValuePersistentRef
};
447 const void *values_persist
[] = { kCFBooleanTrue
, persistentCertRef
};
449 #define SIG_BUF_SIZE 1024
451 /* find identity by persistent ref */
452 persistFind
= CFDictionaryCreate(NULL
, keys_persist
, values_persist
,
453 (sizeof(keys_persist
) / sizeof(*keys_persist
)), NULL
, NULL
);
454 if (persistFind
== NULL
)
457 status
= SecItemCopyMatching(persistFind
, (CFTypeRef
*)&identityRef
);
461 status
= SecIdentityCopyPrivateKey(identityRef
, &privateKeyRef
);
465 // alloc buffer for result
466 sig
= vmalloc(SIG_BUF_SIZE
);
470 status
= SecKeyRawSign(privateKeyRef
, kSecPaddingPKCS1
, hash
->v
,
471 hash
->l
, sig
->v
, &sig
->l
);
478 CFRelease(identityRef
);
480 CFRelease(privateKeyRef
);
482 #if !TARGET_OS_EMBEDDED
484 CFRelease(certificateRef
);
486 CFRelease(keychainRef
);
488 CFRelease(idSearchRef
);
489 if (cssmContextHandle
)
490 CSSM_DeleteContext(cssmContextHandle
);
493 CFRelease(persistFind
);
496 if (status
!= noErr
) {
503 if (status
!= noErr
&& status
!= -1) {
504 plog(LLV_ERROR
, LOCATION
, NULL
,
505 "error %d %s.\n", status
, GetSecurityErrorString(status
));
514 * Retrieve a cert from the keychain
516 vchar_t
* crypto_cssm_get_x509cert(CFDataRef persistentCertRef
,
517 cert_status_t
*certStatus
)
520 OSStatus status
= -1;
521 vchar_t
*cert
= NULL
;
522 SecIdentityRef identityRef
= NULL
;
523 SecCertificateRef certificateRef
= NULL
;
525 #if !TARGET_OS_EMBEDDED
527 SecIdentitySearchRef idSearchRef
= NULL
;
528 SecKeychainRef keychainRef
= NULL
;
531 if (persistentCertRef
) {
532 status
= SecKeychainItemCopyFromPersistentReference(persistentCertRef
, (SecKeychainItemRef
*)&certificateRef
);
536 // copy system keychain
537 status
= CopySystemKeychain(&keychainRef
);
541 // find first identity in system keychain
542 status
= SecIdentitySearchCreate(keychainRef
, CSSM_KEYUSE_SIGN
, &idSearchRef
);
546 status
= SecIdentitySearchCopyNext(idSearchRef
, &identityRef
);
550 // get certificate from identity
551 status
= SecIdentityCopyCertificate(identityRef
, &certificateRef
);
557 // get certificate data
559 cssmData
.Data
= NULL
;
560 status
= SecCertificateGetData(certificateRef
, &cssmData
);
564 if (cssmData
.Length
== 0)
567 cert
= vmalloc(cssmData
.Length
);
571 // cssmData struct just points to the data
572 // data must be copied to be returned
573 memcpy(cert
->v
, cssmData
.Data
, cssmData
.Length
);
575 // verify expiry or missing fields
577 *certStatus
= CERT_STATUS_OK
;
581 CFDictionaryRef persistFind
= NULL
;
582 const void *keys_persist
[] = { kSecReturnRef
, kSecValuePersistentRef
};
583 const void *values_persist
[] = { kCFBooleanTrue
, persistentCertRef
};
585 CFDataRef certData
= NULL
;
587 /* find identity by persistent ref */
588 persistFind
= CFDictionaryCreate(NULL
, keys_persist
, values_persist
,
589 (sizeof(keys_persist
) / sizeof(*keys_persist
)), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
590 if (persistFind
== NULL
)
593 status
= SecItemCopyMatching(persistFind
, (CFTypeRef
*)&identityRef
);
597 status
= SecIdentityCopyCertificate(identityRef
, &certificateRef
);
601 certData
= SecCertificateCopyData(certificateRef
);
602 if (certData
== NULL
)
605 dataLen
= CFDataGetLength(certData
);
609 cert
= vmalloc(dataLen
);
613 CFDataGetBytes(certData
, CFRangeMake(0, dataLen
), cert
->v
);
615 // verify expiry or missing fields
617 *certStatus
= crypto_cssm_check_x509cert_dates(certificateRef
);
624 CFRelease(certificateRef
);
626 CFRelease(identityRef
);
627 #if !TARGET_OS_EMBEDDED
629 CFRelease(idSearchRef
);
631 CFRelease(keychainRef
);
634 CFRelease(persistFind
);
639 if (status
!= noErr
&& status
!= -1) {
640 plog(LLV_ERROR
, LOCATION
, NULL
,
641 "error %d %s.\n", status
, GetSecurityErrorString(status
));
648 #if !TARGET_OS_EMBEDDED
650 * Find a policy ref by OID
652 static OSStatus
FindPolicy(const CSSM_OID
*policyOID
, SecPolicyRef
*policyRef
)
656 SecPolicySearchRef searchRef
= nil
;
658 status
= SecPolicySearchCreate(CSSM_CERT_X_509v3
, policyOID
, NULL
, &searchRef
);
662 status
= SecPolicySearchCopyNext(searchRef
, policyRef
);
666 CFRelease(searchRef
);
668 if (status
!= noErr
) {
669 plog(LLV_ERROR
, LOCATION
, NULL
,
670 "error %d %s.\n", status
, GetSecurityErrorString(status
));
678 * Evaluate the trust of a cert using the policy provided
680 #if TARGET_OS_EMBEDDED
681 static OSStatus
EvaluateCert(SecCertificateRef evalCertArray
[], CFIndex evalCertArrayNumValues
, CFTypeRef policyRef
, SecKeyRef
*publicKeyRef
)
683 static OSStatus
EvaluateCert(SecCertificateRef evalCertArray
[], CFIndex evalCertArrayNumValues
, CFTypeRef policyRef
)
688 SecTrustRef trustRef
= 0;
689 SecTrustResultType evalResult
;
691 #if TARGET_OS_EMBEDDED
692 CFArrayRef errorStrings
;
694 CSSM_TP_APPLE_EVIDENCE_INFO
*statusChain
;
695 CFArrayRef certChain
;
698 CFArrayRef cfCertRef
= CFArrayCreate((CFAllocatorRef
) NULL
, (void*)evalCertArray
, evalCertArrayNumValues
,
699 &kCFTypeArrayCallBacks
);
702 plog(LLV_ERROR
, LOCATION
, NULL
,
703 "unable to create CFArray.\n");
707 status
= SecTrustCreateWithCertificates(cfCertRef
, policyRef
, &trustRef
);
711 status
= SecTrustEvaluate(trustRef
, &evalResult
);
715 if (evalResult
!= kSecTrustResultProceed
&& evalResult
!= kSecTrustResultUnspecified
) {
716 plog(LLV_ERROR
, LOCATION
, NULL
, "Error evaluating certificate.\n");
718 switch (evalResult
) {
719 case kSecTrustResultInvalid
:
720 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultInvalid.\n");
722 case kSecTrustResultProceed
:
723 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultProceed.\n");
725 case kSecTrustResultConfirm
:
726 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultConfirm.\n");
728 case kSecTrustResultDeny
:
729 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultDeny.\n");
731 case kSecTrustResultUnspecified
:
732 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultUnspecified.\n");
734 case kSecTrustResultRecoverableTrustFailure
:
735 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultRecoverableTrustFailure.\n");
737 case kSecTrustResultFatalTrustFailure
:
738 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultFatalTrustFailure.\n");
740 case kSecTrustResultOtherError
:
741 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result = kSecTrustResultOtherError.\n");
744 plog(LLV_DEBUG
, LOCATION
, NULL
, "eval result unknown: value = %d.\n", (int)evalResult
);
749 #if TARGET_OS_EMBEDDED
750 errorStrings
= SecTrustCopyProperties(trustRef
);
753 CFDictionaryRef dict
;
756 CFIndex count
, maxcount
= CFArrayGetCount(errorStrings
);
758 plog(LLV_ERROR
, LOCATION
, NULL
, "---------------Returned error strings: ---------------.\n");
759 for (count
= 0; count
< maxcount
; count
++) {
760 dict
= CFArrayGetValueAtIndex(errorStrings
, count
);
761 if (dict
&& (CFGetTypeID(dict
) == CFDictionaryGetTypeID())) {
762 val
= CFDictionaryGetValue(dict
, kSecPropertyKeyType
);
763 if (val
&& (CFGetTypeID(val
) == CFStringGetTypeID())) {
764 str
= CFStringGetCStringPtr(val
, kCFStringEncodingMacRoman
);
766 plog(LLV_ERROR
, LOCATION
, NULL
, "type = %s.\n", str
);
768 val
= CFDictionaryGetValue(dict
, kSecPropertyKeyValue
);
769 if (val
&& (CFGetTypeID(val
) == CFStringGetTypeID())) {
770 str
= CFStringGetCStringPtr(val
, kCFStringEncodingMacRoman
);
772 plog(LLV_ERROR
, LOCATION
, NULL
, "value = %s.\n", str
);
776 plog(LLV_ERROR
, LOCATION
, NULL
, "-----------------------------------------------------.\n");
777 CFRelease(errorStrings
);
781 SecTrustGetResult(trustRef
, &evalResult
, &certChain
, &statusChain
);
782 plog(LLV_ERROR
, LOCATION
, NULL
, "Cert status bits = 0x%x.\n", statusChain
->StatusBits
);
783 plog(LLV_ERROR
, LOCATION
, NULL
, "Cert status NumStatusCodes = 0x%x.\n", statusChain
->NumStatusCodes
);
786 for (i
= 0; i
< statusChain
->NumStatusCodes
; i
++)
787 plog(LLV_ERROR
, LOCATION
, NULL
, "Cert status code i = 0x%x %d.\n", *(statusChain
->StatusCodes
+ i
), *(statusChain
->StatusCodes
+ i
));
789 plog(LLV_ERROR
, LOCATION
, NULL
, "Cert status Index = %d.\n", statusChain
->Index
);
790 CFRelease(certChain
);
798 #if TARGET_OS_EMBEDDED
799 /* get and return the public key */
800 *publicKeyRef
= SecTrustCopyPublicKey(trustRef
);
805 CFRelease(cfCertRef
);
809 if (status
!= noErr
&& status
!= -1) {
810 plog(LLV_ERROR
, LOCATION
, NULL
,
811 "error %d %s.\n", status
, GetSecurityErrorString(status
));
817 #if !TARGET_OS_EMBEDDED
819 * Copy the system keychain
821 static OSStatus
CopySystemKeychain(SecKeychainRef
*keychainRef
)
826 status
= SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem
);
830 status
= SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem
, keychainRef
);
834 if (status
!= noErr
) {
835 plog(LLV_ERROR
, LOCATION
, NULL
,
836 "error %d %s.\n", status
, GetSecurityErrorString(status
));
845 * Return string representation of Security-related OSStatus.
848 GetSecurityErrorString(OSStatus err
)
861 case errSecNotAvailable
:
862 return "errSecNotAvailable";
863 #if !TARGET_OS_EMBEDDED
865 return "errSecReadOnly";
866 case errSecAuthFailed
:
867 return "errSecAuthFailed";
868 case errSecNoSuchKeychain
:
869 return "errSecNoSuchKeychain";
870 case errSecInvalidKeychain
:
871 return "errSecInvalidKeychain";
872 case errSecDuplicateKeychain
:
873 return "errSecDuplicateKeychain";
874 case errSecDuplicateCallback
:
875 return "errSecDuplicateCallback";
876 case errSecInvalidCallback
:
877 return "errSecInvalidCallback";
878 case errSecBufferTooSmall
:
879 return "errSecBufferTooSmall";
880 case errSecDataTooLarge
:
881 return "errSecDataTooLarge";
882 case errSecNoSuchAttr
:
883 return "errSecNoSuchAttr";
884 case errSecInvalidItemRef
:
885 return "errSecInvalidItemRef";
886 case errSecInvalidSearchRef
:
887 return "errSecInvalidSearchRef";
888 case errSecNoSuchClass
:
889 return "errSecNoSuchClass";
890 case errSecNoDefaultKeychain
:
891 return "errSecNoDefaultKeychain";
892 case errSecInteractionNotAllowed
:
893 return "errSecInteractionNotAllowed";
894 case errSecReadOnlyAttr
:
895 return "errSecReadOnlyAttr";
896 case errSecWrongSecVersion
:
897 return "errSecWrongSecVersion";
898 case errSecKeySizeNotAllowed
:
899 return "errSecKeySizeNotAllowed";
900 case errSecNoStorageModule
:
901 return "errSecNoStorageModule";
902 case errSecNoCertificateModule
:
903 return "errSecNoCertificateModule";
904 case errSecNoPolicyModule
:
905 return "errSecNoPolicyModule";
906 case errSecInteractionRequired
:
907 return "errSecInteractionRequired";
908 case errSecDataNotAvailable
:
909 return "errSecDataNotAvailable";
910 case errSecDataNotModifiable
:
911 return "errSecDataNotModifiable";
912 case errSecCreateChainFailed
:
913 return "errSecCreateChainFailed";
914 case errSecACLNotSimple
:
915 return "errSecACLNotSimple";
916 case errSecPolicyNotFound
:
917 return "errSecPolicyNotFound";
918 case errSecInvalidTrustSetting
:
919 return "errSecInvalidTrustSetting";
920 case errSecNoAccessForItem
:
921 return "errSecNoAccessForItem";
922 case errSecInvalidOwnerEdit
:
923 return "errSecInvalidOwnerEdit";
925 case errSecDuplicateItem
:
926 return "errSecDuplicateItem";
927 case errSecItemNotFound
:
928 return "errSecItemNotFound";