]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/crypto_cssm.c
ipsec-93.8.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>
d1e348cf
A
35
36#include <TargetConditionals.h>
37#if TARGET_OS_EMBEDDED
38#include <Security/SecItem.h>
fce29cd9
A
39#include <Security/SecTrustPriv.h>
40#include <Security/SecPolicyPriv.h>
41#include <Security/SecCertificatePriv.h>
d1e348cf
A
42#else
43#include <Security/SecBase.h>
52b7d2ce
A
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>
d1e348cf 49
52b7d2ce 50#include <Security/SecKeyPriv.h>
52b7d2ce
A
51#include <Security/oidsalg.h>
52#include <Security/cssmapi.h>
53#include <Security/SecPolicySearch.h>
d1e348cf
A
54#endif
55
52b7d2ce
A
56#include <CoreFoundation/CoreFoundation.h>
57#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
58#include "plog.h"
59#include "debug.h"
60#include "misc.h"
fce29cd9 61#include "oakley.h"
52b7d2ce 62
52b7d2ce 63
d1e348cf 64#include "crypto_cssm.h"
52b7d2ce
A
65
66
52b7d2ce 67static OSStatus EvaluateCert(SecCertificateRef cert, CFTypeRef policyRef);
52b7d2ce 68static const char *GetSecurityErrorString(OSStatus err);
d1e348cf
A
69#if !TARGET_OS_EMBEDDED
70static OSStatus FindPolicy(const CSSM_OID *policyOID, SecPolicyRef *policyRef);
71static OSStatus CopySystemKeychain(SecKeychainRef *keychainRef);
72#endif
52b7d2ce
A
73
74/*
75 * Verify cert using security framework
76 */
fce29cd9 77int crypto_cssm_check_x509cert(vchar_t *cert, CFStringRef hostname, cert_status_t certStatus)
52b7d2ce
A
78{
79 OSStatus status;
d1e348cf
A
80 SecCertificateRef certRef = NULL;
81 SecPolicyRef policyRef = NULL;
82
83#if !TARGET_OS_EMBEDDED
52b7d2ce
A
84 CSSM_DATA certData;
85 CSSM_OID ourPolicyOID = CSSMOID_APPLE_TP_IP_SEC;
52b7d2ce
A
86
87 // create cert ref
88 certData.Length = cert->l;
89 certData.Data = (uint8 *)cert->v;
90 status = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER,
91 &certRef);
92 if (status != noErr)
93 goto end;
94
95 // get our policy object
96 status = FindPolicy(&ourPolicyOID, &policyRef);
97 if (status != noErr)
98 goto end;
52b7d2ce
A
99 // no options used at present - verification of subjectAltName fields, etc.
100 // are done elsewhere in racoon in oakley_check_certid()
d1e348cf
A
101
102#else
103 CFDataRef cert_data = CFDataCreateWithBytesNoCopy(NULL, cert->v, cert->l, kCFAllocatorNull);
104 if (cert_data) {
105 certRef = SecCertificateCreateWithData(NULL, cert_data);
106 CFRelease(cert_data);
107 }
108
109 if (certRef == NULL) {
110 plog(LLV_ERROR, LOCATION, NULL,
111 "unable to create a certRef.\n");
112 status = -1;
113 goto end;
114 }
115
116 if (hostname) {
fce29cd9 117 policyRef = SecPolicyCreateIPSec(FALSE, hostname);
d1e348cf
A
118 if (policyRef == NULL) {
119 plog(LLV_ERROR, LOCATION, NULL,
120 "unable to create a SSL policyRef.\n");
121 status = -1;
122 goto end;
123 }
d1e348cf
A
124 }
125
126#endif
52b7d2ce
A
127
128 // evaluate cert
129 status = EvaluateCert(certRef, policyRef);
130
52b7d2ce
A
131end:
132
133 if (certRef)
134 CFRelease(certRef);
135 if (policyRef)
136 CFRelease(policyRef);
137
138 if (status != noErr && status != -1) {
139 plog(LLV_ERROR, LOCATION, NULL,
140 "error %d %s.\n", status, GetSecurityErrorString(status));
141 status = -1;
fce29cd9
A
142 } else if (certStatus) {
143 plog(LLV_ERROR, LOCATION, NULL,
144 "certificate failed date verification: %d.\n", certStatus);
145 status = -1;
146 }
52b7d2ce
A
147 return status;
148
149}
150
151/*
152 * Encrypt a hash via CSSM using the private key in the keychain
153 * from an identity.
154 */
155vchar_t* crypto_cssm_getsign(CFDataRef persistentCertRef, vchar_t* hash)
156{
157
158 OSStatus status;
52b7d2ce 159 SecIdentityRef identityRef = NULL;
d1e348cf
A
160 SecKeyRef privateKeyRef = NULL;
161 vchar_t *sig = NULL;
162
163#if !TARGET_OS_EMBEDDED
164 u_int32_t bytesEncrypted = 0;
165 SecCertificateRef certificateRef = NULL;
52b7d2ce
A
166 SecIdentitySearchRef idSearchRef = NULL;
167 SecKeychainRef keychainRef = NULL;
52b7d2ce
A
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
52b7d2ce
A
173 CSSM_DATA clearData;
174 CSSM_DATA cipherData;
175 CSSM_DATA remData;
176 CSSM_CONTEXT_ATTRIBUTE newAttr;
52b7d2ce
A
177
178 remData.Length = 0;
179 remData.Data = 0;
180
d1e348cf 181 if (persistentCertRef) {
52b7d2ce
A
182 // get cert from keychain
183 status = SecKeychainItemCopyFromPersistentReference(persistentCertRef, (SecKeychainItemRef*)&certificateRef);
184 if (status != noErr)
185 goto end;
186
187 // get keychain ref where cert is contained
188 status = SecKeychainItemCopyKeychain((SecKeychainItemRef)certificateRef, &keychainRef);
189 if (status != noErr)
190 goto end;
191
192 // get identity from the certificate
193 status = SecIdentityCreateWithCertificate(keychainRef, certificateRef, &identityRef);
194 if (status != noErr)
195 goto end;
196
197 } else {
d1e348cf 198
52b7d2ce
A
199 // copy system keychain
200 status = CopySystemKeychain(&keychainRef);
201 if (status != noErr)
202 goto end;
203
204 // serach for first identity in system keychain
205 status = SecIdentitySearchCreate(keychainRef, CSSM_KEYUSE_SIGN, &idSearchRef);
206 if (status != noErr)
207 goto end;
208
209 status = SecIdentitySearchCopyNext(idSearchRef, &identityRef);
210 if (status != noErr)
211 goto end;
212
213 // get certificate from identity
214 status = SecIdentityCopyCertificate(identityRef, &certificateRef);
215 if (status != noErr)
216 goto end;
217 }
218
52b7d2ce
A
219 // get private key from identity
220 status = SecIdentityCopyPrivateKey(identityRef, &privateKeyRef);
221 if (status != noErr)
222 goto end;
223
224 // get CSSM_KEY pointer from key ref
225 status = SecKeyGetCSSMKey(privateKeyRef, &cssmKey);
226 if (status != noErr)
227 goto end;
228
229 // get CSSM CSP handle
230 status = SecKeychainGetCSPHandle(keychainRef, &cspHandle);
231 if (status != noErr)
232 goto end;
233
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);
237 if (status != noErr)
238 goto end;
239
240 // create asymmetric context for encryption
241 status = CSSM_CSP_CreateAsymmetricContext(cspHandle, CSSM_ALGID_RSA, credentials, cssmKey,
242 CSSM_PADDING_PKCS1, &cssmContextHandle);
243 if (status != noErr)
244 goto end;
245
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);
251 if(status != noErr)
252 goto end;
253
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,
260 &remData);
261 if (status != noErr)
262 goto end;
263
264 if (remData.Length != 0) { // something didn't go right - should be zero
265 status = -1;
266 plog(LLV_ERROR, LOCATION, NULL,
267 "unencrypted data remaining after encrypting hash.\n");
268 goto end;
269 }
270
271 // alloc buffer for result
272 sig = vmalloc(0);
273 if (sig == NULL)
274 goto end;
275
276 sig->l = cipherData.Length;
277 sig->v = (caddr_t)cipherData.Data;
d1e348cf
A
278
279#else
280
281 CFDictionaryRef persistFind = NULL;
282 const void *keys_persist[] = { kSecReturnRef, kSecValuePersistentRef };
283 const void *values_persist[] = { kCFBooleanTrue, persistentCertRef };
284
285 #define SIG_BUF_SIZE 1024
286
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)
291 goto end;
292
293 status = SecItemCopyMatching(persistFind, (CFTypeRef *)&identityRef);
294 if (status != noErr)
295 goto end;
296
297 status = SecIdentityCopyPrivateKey(identityRef, &privateKeyRef);
298 if (status != noErr)
299 goto end;
300
301 // alloc buffer for result
302 sig = vmalloc(SIG_BUF_SIZE);
303 if (sig == NULL)
304 goto end;
305
306 status = SecKeyRawSign(privateKeyRef, kSecPaddingPKCS1, hash->v,
307 hash->l, sig->v, &sig->l);
308
309#endif
310
52b7d2ce
A
311
312end:
52b7d2ce
A
313 if (identityRef)
314 CFRelease(identityRef);
315 if (privateKeyRef)
316 CFRelease(privateKeyRef);
d1e348cf
A
317
318#if !TARGET_OS_EMBEDDED
319 if (certificateRef)
320 CFRelease(certificateRef);
321 if (keychainRef)
322 CFRelease(keychainRef);
52b7d2ce
A
323 if (idSearchRef)
324 CFRelease(idSearchRef);
325 if (cssmContextHandle)
326 CSSM_DeleteContext(cssmContextHandle);
d1e348cf
A
327#else
328 if (persistFind)
329 CFRelease(persistFind);
330#endif
331
52b7d2ce
A
332 if (status != noErr) {
333 if (sig) {
334 vfree(sig);
335 sig = NULL;
336 }
337 }
338
339 if (status != noErr && status != -1) {
340 plog(LLV_ERROR, LOCATION, NULL,
341 "error %d %s.\n", status, GetSecurityErrorString(status));
342 status = -1;
343 }
344 return sig;
345
346}
347
348
349/*
350 * Retrieve a cert from the keychain
351 */
fce29cd9
A
352vchar_t* crypto_cssm_get_x509cert(CFDataRef persistentCertRef,
353 cert_status_t *certStatus)
52b7d2ce
A
354{
355
356 OSStatus status;
52b7d2ce
A
357 vchar_t *cert = NULL;
358 SecIdentityRef identityRef = NULL;
52b7d2ce
A
359 SecCertificateRef certificateRef = NULL;
360
d1e348cf
A
361#if !TARGET_OS_EMBEDDED
362 CSSM_DATA cssmData;
363 SecIdentitySearchRef idSearchRef = NULL;
364 SecKeychainRef keychainRef = NULL;
52b7d2ce
A
365
366 // get cert ref
367 if (persistentCertRef) {
368 status = SecKeychainItemCopyFromPersistentReference(persistentCertRef, (SecKeychainItemRef*)&certificateRef);
369 if (status != noErr)
370 goto end;
371 } else {
372 // copy system keychain
373 status = CopySystemKeychain(&keychainRef);
374 if (status != noErr)
375 goto end;
376
377 // find first identity in system keychain
378 status = SecIdentitySearchCreate(keychainRef, CSSM_KEYUSE_SIGN, &idSearchRef);
379 if (status != noErr)
380 goto end;
381
382 status = SecIdentitySearchCopyNext(idSearchRef, &identityRef);
383 if (status != noErr)
384 goto end;
385
386 // get certificate from identity
387 status = SecIdentityCopyCertificate(identityRef, &certificateRef);
388 if (status != noErr)
389 goto end;
390
391 }
d1e348cf 392
52b7d2ce
A
393 // get certificate data
394 cssmData.Length = 0;
395 cssmData.Data = NULL;
396 status = SecCertificateGetData(certificateRef, &cssmData);
397 if (status != noErr)
398 goto end;
399
400 if (cssmData.Length == 0)
401 goto end;
402
403 cert = vmalloc(cssmData.Length);
404 if (cert == NULL)
405 goto end;
406
407 // cssmData struct just points to the data
408 // data must be copied to be returned
409 memcpy(cert->v, cssmData.Data, cssmData.Length);
d1e348cf 410
fce29cd9
A
411 // verify expiry or missing fields
412 if (certStatus) {
413 *certStatus = CERT_STATUS_OK;
414 }
d1e348cf
A
415#else
416
417 CFDictionaryRef persistFind = NULL;
418 const void *keys_persist[] = { kSecReturnRef, kSecValuePersistentRef };
419 const void *values_persist[] = { kCFBooleanTrue, persistentCertRef };
420 size_t dataLen;
421 CFDataRef certData = NULL;
fce29cd9
A
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;
429 CFRange range;
430 CFDictionaryRef *values = NULL;
431 CFDictionaryRef propDict = NULL;
432 const void *datevalue = NULL;
433 const void *labelvalue = NULL;
434 CFGregorianDate gregoriandate;
435 int count;
436 int i;
d1e348cf
A
437
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)
442 goto end;
443
444 status = SecItemCopyMatching(persistFind, (CFTypeRef *)&identityRef);
445 if (status != noErr)
446 goto end;
447
448 status = SecIdentityCopyCertificate(identityRef, &certificateRef);
449 if (status != noErr)
450 goto end;
451
452 certData = SecCertificateCopyData(certificateRef);
453 if (certData == NULL)
454 goto end;
455
456 dataLen = CFDataGetLength(certData);
457 if (dataLen == 0)
458 goto end;
459
460 cert = vmalloc(dataLen);
461 if (cert == NULL)
462 goto end;
463
464 CFDataGetBytes(certData, CFRangeMake(0, dataLen), cert->v);
465
fce29cd9
A
466 // verify expiry or missing fields
467 if (certStatus) {
468
469 *certStatus = CERT_STATUS_OK;
470
471 if ((certProparray = SecCertificateCopyProperties(certificateRef))){
472 if ((count = CFArrayGetCount( certProparray ))){
473 range.location = 0;
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++)
478 {
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);
490 }
491 }
492 }
493 }
494 }
495
496 }
497 }
498 }
499 }
500
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;
513 }
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;
518 }else {
519 plog(LLV_INFO, LOCATION, NULL, "certificate expiration date OK\n");
520 *certStatus = CERT_STATUS_OK;
521 }
522
523 }
524
525 }
526 }
527
d1e348cf 528#endif
52b7d2ce
A
529
530end:
531 if (certificateRef)
532 CFRelease(certificateRef);
533 if (identityRef)
534 CFRelease(identityRef);
d1e348cf 535#if !TARGET_OS_EMBEDDED
52b7d2ce
A
536 if (idSearchRef)
537 CFRelease(idSearchRef);
538 if (keychainRef)
539 CFRelease(keychainRef);
d1e348cf 540#else
fce29cd9
A
541 if (notvalidbeforedatedata)
542 CFRelease(notvalidbeforedatedata);
543 if (notvalidafterdatedata)
544 CFRelease(notvalidafterdatedata);
545 if (certProparray)
546 CFRelease(certProparray);
547 if (values)
548 CFAllocatorDeallocate(NULL, values);
549 if (nowcfdatedata)
550 CFRelease(nowcfdatedata);
d1e348cf
A
551 if (persistFind)
552 CFRelease(persistFind);
553 if (certData)
554 CFRelease(certData);
555#endif
556
52b7d2ce
A
557 if (status != noErr && status != -1) {
558 plog(LLV_ERROR, LOCATION, NULL,
559 "error %d %s.\n", status, GetSecurityErrorString(status));
560 status = -1;
561 }
562 return cert;
563
564}
565
d1e348cf 566#if !TARGET_OS_EMBEDDED
52b7d2ce
A
567/*
568 * Find a policy ref by OID
569 */
570static OSStatus FindPolicy(const CSSM_OID *policyOID, SecPolicyRef *policyRef)
571{
572
573 OSStatus status;
574 SecPolicySearchRef searchRef = nil;
575
576 status = SecPolicySearchCreate(CSSM_CERT_X_509v3, policyOID, NULL, &searchRef);
577 if (status != noErr)
578 goto end;
579
580 status = SecPolicySearchCopyNext(searchRef, policyRef);
581
582end:
583 if (searchRef)
584 CFRelease(searchRef);
585
586 if (status != noErr) {
587 plog(LLV_ERROR, LOCATION, NULL,
588 "error %d %s.\n", status, GetSecurityErrorString(status));
589 status = -1;
590 }
591 return status;
592}
d1e348cf 593#endif
52b7d2ce
A
594
595/*
596 * Evaluate the trust of a cert using the policy provided
597 */
598static OSStatus EvaluateCert(SecCertificateRef cert, CFTypeRef policyRef)
599{
600 OSStatus status;
601 SecTrustRef trustRef = 0;
602 SecTrustResultType evalResult;
fce29cd9
A
603
604#if TARGET_OS_EMBEDDED
605 CFArrayRef errorStrings;
606#else
607 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain;
608 CFArrayRef certChain;
609#endif
52b7d2ce
A
610
611 SecCertificateRef evalCertArray[1] = { cert };
612
d1e348cf
A
613 CFArrayRef cfCertRef = CFArrayCreate((CFAllocatorRef) NULL, (void*)evalCertArray, 1,
614 &kCFTypeArrayCallBacks);
52b7d2ce
A
615
616 if (!cfCertRef) {
617 plog(LLV_ERROR, LOCATION, NULL,
618 "unable to create CFArray.\n");
619 return -1;
620 }
621
622 status = SecTrustCreateWithCertificates(cfCertRef, policyRef, &trustRef);
623 if (status != noErr)
624 goto end;
fce29cd9 625
52b7d2ce
A
626 status = SecTrustEvaluate(trustRef, &evalResult);
627 if (status != noErr)
628 goto end;
629
630 if (evalResult != kSecTrustResultProceed && evalResult != kSecTrustResultUnspecified) {
fce29cd9
A
631 plog(LLV_ERROR, LOCATION, NULL, "Error evaluating certificate.\n");
632
633 switch (evalResult) {
634 case kSecTrustResultInvalid:
635 plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultInvalid.\n");
636 break;
637 case kSecTrustResultProceed:
638 plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultProceed.\n");
639 break;
640 case kSecTrustResultConfirm:
641 plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultConfirm.\n");
642 break;
643 case kSecTrustResultDeny:
644 plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultDeny.\n");
645 break;
646 case kSecTrustResultUnspecified:
647 plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultUnspecified.\n");
648 break;
649 case kSecTrustResultRecoverableTrustFailure:
650 plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultRecoverableTrustFailure.\n");
651 break;
652 case kSecTrustResultFatalTrustFailure:
653 plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultFatalTrustFailure.\n");
654 break;
655 case kSecTrustResultOtherError:
656 plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultOtherError.\n");
657 break;
658 default:
659 plog(LLV_DEBUG, LOCATION, NULL, "eval result unknown: value = %d.\n", (int)evalResult);
660 break;
661 }
662
663
664#if TARGET_OS_EMBEDDED
665 errorStrings = SecTrustCopyProperties(trustRef);
666 if (errorStrings) {
667
668 CFDictionaryRef dict;
669 CFStringRef val;
670 const char *str;
671 CFIndex count, maxcount = CFArrayGetCount(errorStrings);
672
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);
680 if (str)
681 plog(LLV_ERROR, LOCATION, NULL, "type = %s.\n", str);
682 }
683 val = CFDictionaryGetValue(dict, kSecPropertyKeyValue);
684 if (val && (CFGetTypeID(val) == CFStringGetTypeID())) {
685 str = CFStringGetCStringPtr(val, kCFStringEncodingMacRoman);
686 if (str)
687 plog(LLV_ERROR, LOCATION, NULL, "value = %s.\n", str);
688 }
689 }
690 }
691 plog(LLV_ERROR, LOCATION, NULL, "-----------------------------------------------------.\n");
692 CFRelease(errorStrings);
693 }
694
695#else
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);
699 {
700 int i;
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));
703 }
704 plog(LLV_ERROR, LOCATION, NULL, "Cert status Index = %d.\n", statusChain->Index);
705 CFRelease(certChain);
706#endif
707
52b7d2ce
A
708 status = -1;
709 }
710
711
712end:
713 if (cfCertRef)
714 CFRelease(cfCertRef);
715 if (trustRef)
716 CFRelease(trustRef);
717
718 if (status != noErr && status != -1) {
719 plog(LLV_ERROR, LOCATION, NULL,
720 "error %d %s.\n", status, GetSecurityErrorString(status));
721 status = -1;
722 }
723 return status;
724}
725
d1e348cf 726#if !TARGET_OS_EMBEDDED
52b7d2ce
A
727/*
728 * Copy the system keychain
729 */
730static OSStatus CopySystemKeychain(SecKeychainRef *keychainRef)
731{
732
733 OSStatus status;
734
735 status = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
736 if (status != noErr)
737 goto end;
738
739 status = SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, keychainRef);
740
741end:
742
743 if (status != noErr) {
744 plog(LLV_ERROR, LOCATION, NULL,
745 "error %d %s.\n", status, GetSecurityErrorString(status));
746 status = -1;
747 }
748 return status;
749
750}
d1e348cf 751#endif
52b7d2ce
A
752
753/*
754 * Return string representation of Security-related OSStatus.
755 */
756const char *
757GetSecurityErrorString(OSStatus err)
758{
759 switch(err) {
760 case noErr:
761 return "noErr";
762 case memFullErr:
763 return "memFullErr";
764 case paramErr:
765 return "paramErr";
766 case unimpErr:
767 return "unimpErr";
768
769 /* SecBase.h: */
770 case errSecNotAvailable:
771 return "errSecNotAvailable";
d1e348cf 772#if !TARGET_OS_EMBEDDED
52b7d2ce
A
773 case errSecReadOnly:
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";
52b7d2ce
A
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";
d1e348cf
A
833#endif
834 case errSecDuplicateItem:
835 return "errSecDuplicateItem";
836 case errSecItemNotFound:
837 return "errSecItemNotFound";
52b7d2ce
A
838 default:
839 return "<unknown>";
840 }
841}
842