2  * Copyright (c) 2008-2011,2013,2015 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@ 
  33 #include <libDER/DER_Decode.h> 
  34 #include <security_asn1/secerr.h> 
  35 #include <security_asn1/secport.h> 
  37 #include <Security/SecBase.h> 
  39 #include <CoreFoundation/CFNumber.h> 
  40 #include <CoreFoundation/CFString.h> 
  42 #include <Security/oidsalg.h> 
  43 #include <Security/SecPolicy.h> 
  44 #include <Security/SecItem.h> 
  45 #include <Security/SecItemPriv.h> 
  46 #include <Security/SecIdentity.h> 
  47 #include <Security/SecCertificateInternal.h> 
  48 #include <Security/SecKeyPriv.h> 
  50 #include <CommonCrypto/CommonDigest.h> 
  51 #include <AssertMacros.h> 
  54 CERT_VerifyCert(SecKeychainRef keychainOrArray __unused
, CFArrayRef certs
, 
  55                 CFTypeRef policies
, CFAbsoluteTime stime
, SecTrustRef 
*trustRef
) 
  57     SecTrustRef trust 
= NULL
; 
  60     rv 
= SecTrustCreateWithCertificates(certs
, policies
, &trust
); 
  64     CFDateRef verifyDate 
= CFDateCreate(NULL
, stime
); 
  65     rv 
= SecTrustSetVerifyDate(trust
, verifyDate
); 
  66     CFRelease(verifyDate
); 
  76         SecTrustResultType result
; 
  77         /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */ 
  78         rv 
= SecTrustEvaluate(trust
, &result
); 
  84         case kSecTrustResultProceed
: 
  85         case kSecTrustResultUnspecified
: 
  86             /* TP Verification succeeded and there was either a UserTurst entry 
  87                telling us to procceed, or no user trust setting was specified. */ 
  91             PORT_SetError(SEC_ERROR_UNTRUSTED_CERT
); 
 106 static CFTypeRef 
CERT_FindItemInAllAvailableKeychains(CFDictionaryRef query
) { 
 107     CFTypeRef item 
= NULL
; 
 108     CFMutableDictionaryRef q 
= NULL
; 
 109     CFDictionaryRef whoAmI 
= NULL
; 
 110     CFErrorRef error 
= NULL
; 
 111     CFDataRef musr 
= NULL
; 
 112     const uint8_t activeUserUuid
[16] = "\xA7\x5A\x3A\x35\xA5\x57\x4B\x10\xBE\x2E\x83\x94\x7E\x4A\x34\x72"; 
 114     /* Do the standard keychain query */ 
 115     require_quiet(errSecItemNotFound 
== SecItemCopyMatching(query
, &item
), out
); 
 117     /* No item found. Can caller use the system keychain? */ 
 118     whoAmI 
= _SecSecuritydCopyWhoAmI(&error
); 
 119     require_quiet(NULL 
== error 
&& whoAmI 
&& CFDictionaryGetValue(whoAmI
, CFSTR("status")), out
); 
 120     musr 
= CFDictionaryGetValue(whoAmI
, CFSTR("musr")); 
 121     /* Caller has system-keychain entitlement, is in multi-user mode, and is an active user. */ 
 122     if (CFDictionaryGetValue(whoAmI
, CFSTR("system-keychain")) && musr 
&& 
 123         (16 == CFDataGetLength(musr
)) && (0 == memcmp(activeUserUuid
,CFDataGetBytePtr(musr
),12))) { 
 124         q 
= CFDictionaryCreateMutableCopy(NULL
, CFDictionaryGetCount(query
) + 1, query
); 
 125         CFDictionaryAddValue(q
, kSecUseSystemKeychain
, kCFBooleanTrue
); 
 126         SecItemCopyMatching(q
, &item
); 
 140 SecCertificateRef 
CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray
, 
 141                          char *nickname
,SECCertUsage usage
,Boolean validOnly
,void *proto_win
) 
 143         CFStringRef nickname_cfstr 
= CFStringCreateWithCString(kCFAllocatorDefault
, nickname
, kCFStringEncodingUTF8
); 
 144         const void *keys
[] = { kSecClass
, kSecAttrLabel 
}; 
 145         const void *values
[] = { kSecClassCertificate
,  nickname_cfstr 
}; 
 146         CFDictionaryRef query 
= CFDictionaryCreate(kCFAllocatorDefault
, keys
, values
, sizeof(keys
)/sizeof(*keys
), NULL
, NULL
); 
 147         CFTypeRef result 
= NULL
; 
 148         result 
= CERT_FindItemInAllAvailableKeychains(query
); 
 150         CFRelease(nickname_cfstr
); 
 151         return (SecCertificateRef
)result
; 
 154 CF_RETURNS_RETAINED CFArrayRef 
CERT_CertChainFromCert(SecCertificateRef cert
, SECCertUsage usage
, Boolean includeRoot
) 
 156     CFMutableArrayRef certs 
= NULL
; 
 157     SecPolicyRef policy 
= NULL
; 
 158     SecTrustRef trust 
= NULL
; 
 159     CFArrayRef wrappedCert 
= NULL
; 
 161     policy 
= SecPolicyCreateBasicX509(); 
 165     wrappedCert 
= CERT_CertListFromCert(cert
); 
 166     if (SecTrustCreateWithCertificates(wrappedCert
, policy
, &trust
)) 
 169         SecTrustResultType result
; 
 170     if (SecTrustEvaluate(trust
, &result
)) 
 172     CFIndex idx
, count 
= SecTrustGetCertificateCount(trust
); 
 173     certs 
= CFArrayCreateMutable(kCFAllocatorDefault
, count
, &kCFTypeArrayCallBacks
); 
 174     for(idx 
= 0; idx 
< count
; idx
++) 
 175         CFArrayAppendValue(certs
, SecTrustGetCertificateAtIndex(trust
, idx
)); 
 178     if (trust
) CFRelease(trust
); 
 179     if (policy
) CFRelease(policy
); 
 180     if (wrappedCert
) CFRelease(wrappedCert
); 
 185 CFArrayRef 
CERT_CertListFromCert(SecCertificateRef cert
) 
 187     const void *value 
= cert
; 
 188     return cert 
? CFArrayCreate(NULL
, &value
, 1, &kCFTypeArrayCallBacks
) : NULL
; 
 191 CFArrayRef 
CERT_DupCertList(CFArrayRef oldList
) 
 197 // Extract a public key object from a SubjectPublicKeyInfo 
 198 SecPublicKeyRef 
CERT_ExtractPublicKey(SecCertificateRef cert
) 
 200     return SecCertificateCopyPublicKey(cert
); 
 203 // Extract the issuer and serial number from a certificate 
 204 SecCmsIssuerAndSN 
*CERT_GetCertIssuerAndSN(PRArenaPool 
*pl
, SecCertificateRef cert
) 
 206     SecCmsIssuerAndSN 
*certIssuerAndSN
; 
 209     mark 
= PORT_ArenaMark(pl
); 
 210     CFDataRef serial_data 
= NULL
; 
 211     CFDataRef issuer_data 
= SecCertificateCopyIssuerSequence(cert
); 
 214     serial_data 
= SecCertificateCopySerialNumber(cert
); 
 218     SecAsn1Item serialNumber 
= { CFDataGetLength(serial_data
), 
 219         (uint8_t *)CFDataGetBytePtr(serial_data
) }; 
 220     SecAsn1Item issuer 
= { CFDataGetLength(issuer_data
), 
 221         (uint8_t *)CFDataGetBytePtr(issuer_data
) }; 
 223         /* Allocate the SecCmsIssuerAndSN struct. */ 
 224     certIssuerAndSN 
= (SecCmsIssuerAndSN 
*)PORT_ArenaZAlloc (pl
, sizeof(SecCmsIssuerAndSN
)); 
 225     if (certIssuerAndSN 
== NULL
) 
 228     /* Copy the issuer. */ 
 229     certIssuerAndSN
->derIssuer
.Data 
= (uint8_t *) PORT_ArenaAlloc(pl
, issuer
.Length
); 
 230     if (!certIssuerAndSN
->derIssuer
.Data
) 
 232     PORT_Memcpy(certIssuerAndSN
->derIssuer
.Data
, issuer
.Data
, issuer
.Length
); 
 233     certIssuerAndSN
->derIssuer
.Length 
= issuer
.Length
; 
 235     /* Copy the serialNumber. */ 
 236     certIssuerAndSN
->serialNumber
.Data 
= (uint8_t *) PORT_ArenaAlloc(pl
, serialNumber
.Length
); 
 237     if (!certIssuerAndSN
->serialNumber
.Data
) 
 239     PORT_Memcpy(certIssuerAndSN
->serialNumber
.Data
, serialNumber
.Data
, serialNumber
.Length
); 
 240     certIssuerAndSN
->serialNumber
.Length 
= serialNumber
.Length
; 
 242     CFRelease(serial_data
); 
 243     CFRelease(issuer_data
); 
 245     PORT_ArenaUnmark(pl
, mark
); 
 247     return certIssuerAndSN
; 
 251         CFRelease(serial_data
); 
 253         CFRelease(issuer_data
); 
 254     PORT_ArenaRelease(pl
, mark
); 
 255     PORT_SetError(SEC_INTERNAL_ONLY
); 
 260 // find the smime symmetric capabilities profile for a given cert 
 261 SecAsn1Item 
*CERT_FindSMimeProfile(SecCertificateRef cert
) 
 266 // Generate a certificate key from the issuer and serialnumber, then look it up in the database. 
 267 // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for 
 268 static CFTypeRef 
CERT_FindByIssuerAndSN (CFTypeRef keychainOrArray
, CFTypeRef 
class, const SecCmsIssuerAndSN 
*issuerAndSN
) 
 270     CFTypeRef ident 
= NULL
; 
 271         CFDictionaryRef query 
= NULL
; 
 272         CFDataRef issuer 
= NULL
; 
 273     CFDataRef serial 
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
,  
 274         issuerAndSN
->serialNumber
.Data
, issuerAndSN
->serialNumber
.Length
,  
 277         DERItem der_issuer 
= { issuerAndSN
->derIssuer
.Data
, 
 278                                                         issuerAndSN
->derIssuer
.Length 
}; 
 279         DERDecodedInfo content
;  
 280         require_noerr_quiet(DERDecodeItem(&der_issuer
, &content
), out
); 
 281     require_quiet(issuer 
= createNormalizedX501Name(kCFAllocatorDefault
, 
 282                 &content
.content
), out
); 
 284     if (keychainOrArray 
&& (CFGetTypeID(keychainOrArray
) == CFArrayGetTypeID()) && CFEqual(class, kSecClassCertificate
)) 
 286         CFIndex c
, count 
= CFArrayGetCount((CFArrayRef
)keychainOrArray
); 
 287         for (c 
= 0; c 
< count
; c
++) { 
 288             SecCertificateRef cert 
= (SecCertificateRef
)CFArrayGetValueAtIndex((CFArrayRef
)keychainOrArray
, c
); 
 289             CFDataRef nic 
= (cert
) ? SecCertificateGetNormalizedIssuerContent(cert
) : NULL
; 
 290             if (nic 
&& CFEqual(nic
, issuer
)) { 
 291                 CFDataRef cert_serial 
= SecCertificateCopySerialNumber(cert
); 
 293                     bool found 
= CFEqual(cert_serial
, serial
); 
 294                     CFRelease(cert_serial
); 
 305         const void *keys
[] = { kSecClass
, kSecAttrIssuer
, kSecAttrSerialNumber
, kSecReturnRef 
}; 
 306         const void *values
[] = { class, issuer
, serial
, kCFBooleanTrue 
}; 
 307         query 
= CFDictionaryCreate(kCFAllocatorDefault
, keys
, values
, sizeof(keys
)/sizeof(*keys
), NULL
, NULL
); 
 308         ident 
= CERT_FindItemInAllAvailableKeychains(query
); 
 321 SecIdentityRef 
CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray
, const SecCmsIssuerAndSN 
*issuerAndSN
) 
 323     return (SecIdentityRef
)CERT_FindByIssuerAndSN(keychainOrArray
, kSecClassIdentity
, issuerAndSN
); 
 326 SecCertificateRef 
CERT_FindCertificateByIssuerAndSN (CFTypeRef keychainOrArray
, const SecCmsIssuerAndSN 
*issuerAndSN
) 
 328     return (SecCertificateRef
)CERT_FindByIssuerAndSN(keychainOrArray
, kSecClassCertificate
, issuerAndSN
); 
 331 SecIdentityRef 
CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray __unused
, const SecAsn1Item 
*subjKeyID
) 
 333     SecIdentityRef ident 
= NULL
; 
 334         CFDictionaryRef query 
= NULL
; 
 335     CFDataRef subjectkeyid 
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, subjKeyID
->Data
, subjKeyID
->Length
, kCFAllocatorNull
); 
 337         const void *keys
[] = { kSecClass
, kSecAttrSubjectKeyID
, kSecReturnRef 
}; 
 338         const void *values
[] = { kSecClassIdentity
, subjectkeyid
, kCFBooleanTrue 
}; 
 339         query 
= CFDictionaryCreate(kCFAllocatorDefault
, keys
, values
, sizeof(keys
)/sizeof(*keys
), NULL
, NULL
); 
 340         ident 
= (SecIdentityRef
) CERT_FindItemInAllAvailableKeychains(query
); 
 345         CFRelease(subjectkeyid
); 
 352 SecPublicKeyRef 
SECKEY_CopyPublicKey(SecPublicKeyRef pubKey
) 
 358 void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey
) 
 363 SecPublicKeyRef 
SECKEY_CopyPrivateKey(SecPublicKeyRef privKey
) 
 369 void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey
) 
 374 void CERT_DestroyCertificate(SecCertificateRef cert
) 
 379 SecCertificateRef 
CERT_DupCertificate(SecCertificateRef cert
) 
 386 WRAP_PubWrapSymKey(SecPublicKeyRef publickey
, 
 387                    SecSymmetricKeyRef bulkkey
, 
 388                    SecAsn1Item 
* encKey
) 
 390     return SecKeyEncrypt(publickey
, kSecPaddingPKCS1
,  
 391                         CFDataGetBytePtr(bulkkey
), CFDataGetLength(bulkkey
), 
 392                         encKey
->Data
, &encKey
->Length
); 
 396 WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey
, const SecAsn1Item 
*encKey
, SECOidTag bulkalgtag
) 
 398     size_t bulkkey_size 
= encKey
->Length
; 
 399     if (bulkkey_size 
> 16384) { 
 403     uint8_t bulkkey_buffer
[bulkkey_size
]; 
 404     if (SecKeyDecrypt(privkey
, kSecPaddingPKCS1
,  
 405         encKey
->Data
, encKey
->Length
, bulkkey_buffer
, &bulkkey_size
)) 
 408     CFDataRef bulkkey 
= CFDataCreate(kCFAllocatorDefault
, bulkkey_buffer
, bulkkey_size
); 
 409     return (SecSymmetricKeyRef
)bulkkey
; 
 414 CERT_CheckIssuerAndSerial(SecCertificateRef cert
, SecAsn1Item 
*issuer
, SecAsn1Item 
*serial
) 
 417         CFDataRef cert_issuer 
= SecCertificateCopyIssuerSequence(cert
); 
 420         if ((issuer
->Length 
!= (size_t)CFDataGetLength(cert_issuer
)) || 
 421             memcmp(issuer
->Data
, CFDataGetBytePtr(cert_issuer
), issuer
->Length
)) { 
 422                 CFRelease(cert_issuer
); 
 425         CFRelease(cert_issuer
); 
 426         CFDataRef cert_serial 
= SecCertificateCopySerialNumber(cert
); 
 429         if ((serial
->Length 
!= (size_t)CFDataGetLength(cert_serial
)) || 
 430             memcmp(serial
->Data
, CFDataGetBytePtr(cert_serial
), serial
->Length
)) { 
 431                 CFRelease(cert_serial
); 
 434         CFRelease(cert_serial
);