2  * Copyright (c) 2007-2008 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  24 #include <Security/SecBase.h> 
  25 #include <Security/SecBasePriv.h> 
  26 #include <Security/SecItem.h> 
  27 #include <Security/SecRSAKey.h> 
  28 #include <Security/SecCertificate.h> 
  29 #include <Security/SecIdentityPriv.h> 
  30 #include <Security/SecPolicy.h> 
  31 #include <Security/SecTrust.h> 
  32 #include <Security/SecInternal.h> 
  34 #include <AssertMacros.h> 
  36 #include "p12import.h" 
  37 #include "SecImportExport.h" 
  39 CFStringRef kSecImportExportPassphrase 
= CFSTR("passphrase"); 
  40 CFStringRef kSecImportItemLabel 
= CFSTR("label"); 
  41 CFStringRef kSecImportItemKeyID 
= CFSTR("keyid"); 
  42 CFStringRef kSecImportItemTrust 
= CFSTR("trust"); 
  43 CFStringRef kSecImportItemCertChain 
= CFSTR("chain"); 
  44 CFStringRef kSecImportItemIdentity 
= CFSTR("identity"); 
  47 static void collect_certs(const void *key
, const void *value
, void *context
) 
  49     if (!CFDictionaryContainsKey(value
, CFSTR("key"))) { 
  50         CFDataRef cert_bytes 
= CFDictionaryGetValue(value
, CFSTR("cert")); 
  53         SecCertificateRef cert 
=  
  54             SecCertificateCreateWithData(kCFAllocatorDefault
, cert_bytes
); 
  57         CFMutableArrayRef cert_array 
= (CFMutableArrayRef
)context
; 
  58         CFArrayAppendValue(cert_array
, cert
); 
  64     CFMutableArrayRef identities
; 
  66 } build_trust_chains_context
; 
  68 static void build_trust_chains(const void *key
, const void *value
,  
  71     CFMutableDictionaryRef identity_dict 
= CFDictionaryCreateMutable(kCFAllocatorDefault
,  
  72         0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
  73     SecKeyRef private_key 
= NULL
; 
  74     SecCertificateRef cert 
= NULL
; 
  75     SecIdentityRef identity 
= NULL
; 
  76     SecPolicyRef policy 
= NULL
; 
  77     CFMutableArrayRef cert_chain 
= NULL
, eval_chain 
= NULL
; 
  78     SecTrustRef trust 
= NULL
; 
  79     build_trust_chains_context 
* a_build_trust_chains_context 
= (build_trust_chains_context
*)context
; 
  81     CFDataRef key_bytes 
= CFDictionaryGetValue(value
, CFSTR("key")); 
  82     require(key_bytes
, out
); 
  83     CFDataRef cert_bytes 
= CFDictionaryGetValue(value
, CFSTR("cert")); 
  84     require(cert_bytes
, out
); 
  86     /* p12import only passes up rsa keys */ 
  87     require (private_key 
= SecKeyCreateRSAPrivateKey(kCFAllocatorDefault
,  
  88         CFDataGetBytePtr(key_bytes
), CFDataGetLength(key_bytes
), 
  89         kSecKeyEncodingPkcs1
), out
); 
  90     require(cert 
= SecCertificateCreateWithData(kCFAllocatorDefault
, cert_bytes
), out
); 
  91     require(identity 
= SecIdentityCreate(kCFAllocatorDefault
, cert
, private_key
), out
); 
  92     CFDictionarySetValue(identity_dict
, kSecImportItemIdentity
, identity
); 
  94     eval_chain 
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
); 
  95     require(eval_chain
, out
); 
  96     CFArrayAppendValue(eval_chain
, cert
); 
  97     CFRange all_certs 
= { 0, CFArrayGetCount(a_build_trust_chains_context
->certs
) }; 
  98     CFArrayAppendArray(eval_chain
, a_build_trust_chains_context
->certs
, all_certs
); 
  99     require(policy 
= SecPolicyCreateBasicX509(), out
); 
 100     SecTrustResultType result
; 
 101     SecTrustCreateWithCertificates(eval_chain
, policy
, &trust
); 
 103     SecTrustEvaluate(trust
, &result
); 
 104     CFDictionarySetValue(identity_dict
, kSecImportItemTrust
, trust
); 
 106     require(cert_chain 
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
), out
); 
 107     CFIndex cert_chain_length 
= SecTrustGetCertificateCount(trust
); 
 109     for (i 
= 0; i 
< cert_chain_length
; i
++) 
 110         CFArrayAppendValue(cert_chain
, SecTrustGetCertificateAtIndex(trust
, i
)); 
 111     CFDictionarySetValue(identity_dict
, kSecImportItemCertChain
, cert_chain
); 
 113     CFArrayAppendValue(a_build_trust_chains_context
->identities
, identity_dict
); 
 115     CFReleaseSafe(identity_dict
); 
 116     CFReleaseSafe(identity
); 
 117     CFReleaseSafe(private_key
); 
 119     CFReleaseSafe(policy
); 
 120     CFReleaseSafe(cert_chain
); 
 121     CFReleaseSafe(eval_chain
); 
 122     CFReleaseSafe(trust
); 
 125 OSStatus 
SecPKCS12Import(CFDataRef pkcs12_data
, CFDictionaryRef options
, CFArrayRef 
*items
) 
 127     pkcs12_context context 
= {}; 
 128     SecAsn1CoderCreate(&context
.coder
); 
 130         context
.passphrase 
= CFDictionaryGetValue(options
, kSecImportExportPassphrase
); 
 131     context
.items 
= CFDictionaryCreateMutable(kCFAllocatorDefault
,  
 132         0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
 133     int status 
= p12decode(&context
, pkcs12_data
); 
 135         CFMutableArrayRef certs 
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
); 
 136         CFDictionaryApplyFunction(context
.items
, collect_certs
, certs
); 
 138         CFMutableArrayRef identities 
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
); 
 139         build_trust_chains_context a_build_trust_chains_context 
= { identities
, certs 
}; 
 140         CFDictionaryApplyFunction(context
.items
, build_trust_chains
, &a_build_trust_chains_context
); 
 141         CFReleaseSafe(certs
); 
 143         /* ignoring certs that weren't picked up as part of the certchain for found keys */ 
 148     CFReleaseSafe(context
.items
); 
 149     SecAsn1CoderRelease(context
.coder
); 
 152     case p12_noErr
: return noErr
; 
 153     case p12_passwordErr
: return errSecAuthFailed
; 
 154     case p12_decodeErr
: return errSecDecode
; 
 155     default: return errSecInternal
;