5 * Created by Conrad Sauerwald on 2/7/08.
6 * Copyright (c) 2008-2011,2013 Apple Inc. All Rights Reserved.
19 #include <libDER/DER_Decode.h>
20 #include <security_asn1/secerr.h>
21 #include <security_asn1/secport.h>
23 #include <Security/SecBase.h>
25 #include <CoreFoundation/CFNumber.h>
26 #include <CoreFoundation/CFString.h>
28 #include <Security/oidsalg.h>
29 #include <Security/SecPolicy.h>
30 #include <Security/SecItem.h>
31 #include <Security/SecIdentity.h>
32 #include <Security/SecCertificateInternal.h>
33 #include <Security/SecKeyPriv.h>
35 #include <CommonCrypto/CommonDigest.h>
36 #include <AssertMacros.h>
39 CERT_VerifyCert(SecKeychainRef keychainOrArray __unused
, CFArrayRef certs
,
40 CFTypeRef policies
, CFAbsoluteTime stime
, SecTrustRef
*trustRef
)
42 SecTrustRef trust
= NULL
;
45 rv
= SecTrustCreateWithCertificates(certs
, policies
, &trust
);
49 CFDateRef verifyDate
= CFDateCreate(NULL
, stime
);
50 rv
= SecTrustSetVerifyDate(trust
, verifyDate
);
51 CFRelease(verifyDate
);
61 SecTrustResultType result
;
62 /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */
63 rv
= SecTrustEvaluate(trust
, &result
);
69 case kSecTrustResultProceed
:
70 case kSecTrustResultUnspecified
:
71 /* TP Verification succeeded and there was either a UserTurst entry
72 telling us to procceed, or no user trust setting was specified. */
76 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT
);
92 SecCertificateRef
CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray
,
93 char *nickname
,SECCertUsage usage
,Boolean validOnly
,void *proto_win
)
95 CFStringRef nickname_cfstr
= CFStringCreateWithCString(kCFAllocatorDefault
, nickname
, kCFStringEncodingUTF8
);
96 const void *keys
[] = { kSecClass
, kSecAttrLabel
};
97 const void *values
[] = { kSecClassCertificate
, nickname_cfstr
};
98 CFDictionaryRef query
= CFDictionaryCreate(kCFAllocatorDefault
, keys
, values
, sizeof(keys
)/sizeof(*keys
), NULL
, NULL
);
99 CFTypeRef result
= NULL
;
100 SecItemCopyMatching(query
, &result
);
102 CFRelease(nickname_cfstr
);
103 return (SecCertificateRef
)result
;
106 CF_RETURNS_RETAINED CFArrayRef
CERT_CertChainFromCert(SecCertificateRef cert
, SECCertUsage usage
, Boolean includeRoot
)
108 CFMutableArrayRef certs
= NULL
;
109 SecPolicyRef policy
= NULL
;
110 SecTrustRef trust
= NULL
;
111 CFArrayRef wrappedCert
= NULL
;
113 policy
= SecPolicyCreateBasicX509();
117 wrappedCert
= CERT_CertListFromCert(cert
);
118 if (SecTrustCreateWithCertificates(wrappedCert
, policy
, &trust
))
121 SecTrustResultType result
;
122 if (SecTrustEvaluate(trust
, &result
))
124 CFIndex idx
, count
= SecTrustGetCertificateCount(trust
);
125 certs
= CFArrayCreateMutable(kCFAllocatorDefault
, count
, &kCFTypeArrayCallBacks
);
126 for(idx
= 0; idx
< count
; idx
++)
127 CFArrayAppendValue(certs
, SecTrustGetCertificateAtIndex(trust
, idx
));
130 if (trust
) CFRelease(trust
);
131 if (policy
) CFRelease(policy
);
132 if (wrappedCert
) CFRelease(wrappedCert
);
137 CFArrayRef
CERT_CertListFromCert(SecCertificateRef cert
)
139 const void *value
= cert
;
140 return cert
? CFArrayCreate(NULL
, &value
, 1, &kCFTypeArrayCallBacks
) : NULL
;
143 CFArrayRef
CERT_DupCertList(CFArrayRef oldList
)
149 // Extract a public key object from a SubjectPublicKeyInfo
150 SecPublicKeyRef
CERT_ExtractPublicKey(SecCertificateRef cert
)
152 return SecCertificateCopyPublicKey(cert
);
155 // Extract the issuer and serial number from a certificate
156 SecCmsIssuerAndSN
*CERT_GetCertIssuerAndSN(PRArenaPool
*pl
, SecCertificateRef cert
)
158 SecCmsIssuerAndSN
*certIssuerAndSN
;
161 mark
= PORT_ArenaMark(pl
);
162 CFDataRef serial_data
= NULL
;
163 CFDataRef issuer_data
= SecCertificateCopyIssuerSequence(cert
);
166 serial_data
= SecCertificateCopySerialNumber(cert
);
170 SecAsn1Item serialNumber
= { CFDataGetLength(serial_data
),
171 (uint8_t *)CFDataGetBytePtr(serial_data
) };
172 SecAsn1Item issuer
= { CFDataGetLength(issuer_data
),
173 (uint8_t *)CFDataGetBytePtr(issuer_data
) };
175 /* Allocate the SecCmsIssuerAndSN struct. */
176 certIssuerAndSN
= (SecCmsIssuerAndSN
*)PORT_ArenaZAlloc (pl
, sizeof(SecCmsIssuerAndSN
));
177 if (certIssuerAndSN
== NULL
)
180 /* Copy the issuer. */
181 certIssuerAndSN
->derIssuer
.Data
= (uint8_t *) PORT_ArenaAlloc(pl
, issuer
.Length
);
182 if (!certIssuerAndSN
->derIssuer
.Data
)
184 PORT_Memcpy(certIssuerAndSN
->derIssuer
.Data
, issuer
.Data
, issuer
.Length
);
185 certIssuerAndSN
->derIssuer
.Length
= issuer
.Length
;
187 /* Copy the serialNumber. */
188 certIssuerAndSN
->serialNumber
.Data
= (uint8_t *) PORT_ArenaAlloc(pl
, serialNumber
.Length
);
189 if (!certIssuerAndSN
->serialNumber
.Data
)
191 PORT_Memcpy(certIssuerAndSN
->serialNumber
.Data
, serialNumber
.Data
, serialNumber
.Length
);
192 certIssuerAndSN
->serialNumber
.Length
= serialNumber
.Length
;
194 CFRelease(serial_data
);
195 CFRelease(issuer_data
);
197 PORT_ArenaUnmark(pl
, mark
);
199 return certIssuerAndSN
;
203 CFRelease(serial_data
);
205 CFRelease(issuer_data
);
206 PORT_ArenaRelease(pl
, mark
);
207 PORT_SetError(SEC_INTERNAL_ONLY
);
212 // find the smime symmetric capabilities profile for a given cert
213 SecAsn1Item
*CERT_FindSMimeProfile(SecCertificateRef cert
)
218 // Generate a certificate key from the issuer and serialnumber, then look it up in the database.
219 // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for
220 static CFTypeRef
CERT_FindByIssuerAndSN (CFTypeRef keychainOrArray
, CFTypeRef
class, const SecCmsIssuerAndSN
*issuerAndSN
)
222 CFTypeRef ident
= NULL
;
223 CFDictionaryRef query
= NULL
;
224 CFDataRef issuer
= NULL
;
225 CFDataRef serial
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
,
226 issuerAndSN
->serialNumber
.Data
, issuerAndSN
->serialNumber
.Length
,
229 DERItem der_issuer
= { issuerAndSN
->derIssuer
.Data
,
230 issuerAndSN
->derIssuer
.Length
};
231 DERDecodedInfo content
;
232 require_noerr_quiet(DERDecodeItem(&der_issuer
, &content
), out
);
233 require_quiet(issuer
= createNormalizedX501Name(kCFAllocatorDefault
,
234 &content
.content
), out
);
236 if (keychainOrArray
&& (CFGetTypeID(keychainOrArray
) == CFArrayGetTypeID()) && CFEqual(class, kSecClassCertificate
))
238 CFIndex c
, count
= CFArrayGetCount((CFArrayRef
)keychainOrArray
);
239 for (c
= 0; c
< count
; c
++) {
240 SecCertificateRef cert
= (SecCertificateRef
)CFArrayGetValueAtIndex((CFArrayRef
)keychainOrArray
, c
);
241 CFDataRef nic
= (cert
) ? SecCertificateGetNormalizedIssuerContent(cert
) : NULL
;
242 if (nic
&& CFEqual(nic
, issuer
)) {
243 CFDataRef cert_serial
= SecCertificateCopySerialNumber(cert
);
245 bool found
= CFEqual(cert_serial
, serial
);
246 CFRelease(cert_serial
);
257 const void *keys
[] = { kSecClass
, kSecAttrIssuer
, kSecAttrSerialNumber
, kSecReturnRef
};
258 const void *values
[] = { class, issuer
, serial
, kCFBooleanTrue
};
259 query
= CFDictionaryCreate(kCFAllocatorDefault
, keys
, values
, sizeof(keys
)/sizeof(*keys
), NULL
, NULL
);
260 require_noerr_quiet(SecItemCopyMatching(query
, (CFTypeRef
*)&ident
), out
);
273 SecIdentityRef
CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray
, const SecCmsIssuerAndSN
*issuerAndSN
)
275 return (SecIdentityRef
)CERT_FindByIssuerAndSN(keychainOrArray
, kSecClassIdentity
, issuerAndSN
);
278 SecCertificateRef
CERT_FindCertificateByIssuerAndSN (CFTypeRef keychainOrArray
, const SecCmsIssuerAndSN
*issuerAndSN
)
280 return (SecCertificateRef
)CERT_FindByIssuerAndSN(keychainOrArray
, kSecClassCertificate
, issuerAndSN
);
283 SecIdentityRef
CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray __unused
, const SecAsn1Item
*subjKeyID
)
285 SecIdentityRef ident
= NULL
;
286 CFDictionaryRef query
= NULL
;
287 CFDataRef subjectkeyid
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, subjKeyID
->Data
, subjKeyID
->Length
, kCFAllocatorNull
);
289 const void *keys
[] = { kSecClass
, kSecAttrSubjectKeyID
, kSecReturnRef
};
290 const void *values
[] = { kSecClassIdentity
, subjectkeyid
, kCFBooleanTrue
};
291 query
= CFDictionaryCreate(kCFAllocatorDefault
, keys
, values
, sizeof(keys
)/sizeof(*keys
), NULL
, NULL
);
292 require_noerr_quiet(SecItemCopyMatching(query
, (CFTypeRef
*)&ident
), out
);
298 CFRelease(subjectkeyid
);
305 SecPublicKeyRef
SECKEY_CopyPublicKey(SecPublicKeyRef pubKey
)
311 void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey
)
316 SecPublicKeyRef
SECKEY_CopyPrivateKey(SecPublicKeyRef privKey
)
322 void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey
)
327 void CERT_DestroyCertificate(SecCertificateRef cert
)
332 SecCertificateRef
CERT_DupCertificate(SecCertificateRef cert
)
339 WRAP_PubWrapSymKey(SecPublicKeyRef publickey
,
340 SecSymmetricKeyRef bulkkey
,
341 SecAsn1Item
* encKey
)
343 return SecKeyEncrypt(publickey
, kSecPaddingPKCS1
,
344 CFDataGetBytePtr(bulkkey
), CFDataGetLength(bulkkey
),
345 encKey
->Data
, &encKey
->Length
);
349 WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey
, const SecAsn1Item
*encKey
, SECOidTag bulkalgtag
)
351 size_t bulkkey_size
= encKey
->Length
;
352 uint8_t bulkkey_buffer
[bulkkey_size
];
353 if (SecKeyDecrypt(privkey
, kSecPaddingPKCS1
,
354 encKey
->Data
, encKey
->Length
, bulkkey_buffer
, &bulkkey_size
))
357 CFDataRef bulkkey
= CFDataCreate(kCFAllocatorDefault
, bulkkey_buffer
, bulkkey_size
);
358 return (SecSymmetricKeyRef
)bulkkey
;
363 CERT_CheckIssuerAndSerial(SecCertificateRef cert
, SecAsn1Item
*issuer
, SecAsn1Item
*serial
)
366 CFDataRef cert_issuer
= SecCertificateCopyIssuerSequence(cert
);
369 if ((issuer
->Length
!= (size_t)CFDataGetLength(cert_issuer
)) ||
370 memcmp(issuer
->Data
, CFDataGetBytePtr(cert_issuer
), issuer
->Length
)) {
371 CFRelease(cert_issuer
);
374 CFRelease(cert_issuer
);
375 CFDataRef cert_serial
= SecCertificateCopySerialNumber(cert
);
378 if ((serial
->Length
!= (size_t)CFDataGetLength(cert_serial
)) ||
379 memcmp(serial
->Data
, CFDataGetBytePtr(cert_serial
), serial
->Length
)) {
380 CFRelease(cert_serial
);
383 CFRelease(cert_serial
);