]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_keychain/lib/SecCertificate.cpp
Security-57337.60.2.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / SecCertificate.cpp
CommitLineData
b1ab9ed8 1/*
5c19dc3a 2 * Copyright (c) 2002-2015 Apple Inc. All Rights Reserved.
b1ab9ed8
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include <Security/SecCertificate.h>
25#include <Security/SecCertificatePriv.h>
26#include <security_keychain/Certificate.h>
27#include <security_keychain/Item.h>
28#include <security_keychain/KCCursor.h>
29#include <Security/cssmapi.h>
30#include <Security/cssmapple.h>
31#include <security_cdsa_client/cspclient.h>
32#include <security_cdsa_client/clclient.h>
33#include <security_cdsa_client/tpclient.h>
34#include <Security/cssmtype.h>
35
36#include "SecBridge.h"
37
38// %%% used by SecCertificate{Copy,Set}Preference
39#include <Security/SecKeychainItemPriv.h>
40#include <Security/SecIdentityPriv.h>
41#include <security_keychain/KCCursor.h>
42#include <security_cdsa_utilities/Schema.h>
5c19dc3a 43#include <security_cdsa_utils/cuCdsaUtils.h>
b1ab9ed8 44#include <sys/param.h>
5c19dc3a 45#include <syslog.h>
b1ab9ed8
A
46#include "CertificateValues.h"
47#include "SecCertificateP.h"
4d3cab3d 48#include "SecCertificatePrivP.h"
427c49bc 49
d8f41ccd 50#include "AppleBaselineEscrowCertificates.h"
427c49bc 51
b1ab9ed8 52
5c19dc3a
A
53SecCertificateRef SecCertificateCreateItemImplInstance(SecCertificateRef certificate);
54OSStatus SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle);
b1ab9ed8
A
55extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage);
56
5c19dc3a 57#define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v);
427c49bc
A
58
59SEC_CONST_DECL (kSecCertificateProductionEscrowKey, "ProductionEscrowKey");
d8f41ccd 60SEC_CONST_DECL (kSecCertificateProductionPCSEscrowKey, "ProductionPCSEscrowKey");
427c49bc
A
61SEC_CONST_DECL (kSecCertificateEscrowFileName, "AppleESCertificates");
62
b1ab9ed8
A
63
64using namespace CssmClient;
65
5c19dc3a 66#if !SECTRUST_OSX
b1ab9ed8
A
67CFTypeID
68SecCertificateGetTypeID(void)
69{
70 BEGIN_SECAPI
71
72 return gTypes().Certificate.typeID;
73
74 END_SECAPI1(_kCFRuntimeNotATypeID)
75}
5c19dc3a 76#endif
b1ab9ed8 77
5c19dc3a
A
78/* convert a new-world SecCertificateRef to an old-world ItemImpl instance */
79SecCertificateRef
80SecCertificateCreateItemImplInstance(SecCertificateRef certificate)
81{
82#if !SECTRUST_OSX
83 return (SecCertificateRef)(certificate ? CFRetain(certificate) : NULL);
84#else
85 if (!certificate) {
86 return NULL;
87 }
88 SecCertificateRef implCertRef = (SecCertificateRef) SecCertificateCopyKeychainItem(certificate);
89 if (implCertRef) {
90 return implCertRef;
91 }
92 CFDataRef data = SecCertificateCopyData(certificate);
93 if (!data) {
94 return NULL;
95 }
96 try {
97 CSSM_DATA cssmCertData;
98 cssmCertData.Length = (data) ? (CSSM_SIZE)CFDataGetLength(data) : 0;
99 cssmCertData.Data = (data) ? (uint8 *)CFDataGetBytePtr(data) : NULL;
b1ab9ed8 100
5c19dc3a
A
101 SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER));
102 implCertRef = certificatePtr->handle();
103 }
104 catch (...) {}
105 CFRelease(data);
106 return implCertRef;
107#endif
108}
109
110/* convert an old-world ItemImpl instance to a new-world SecCertificateRef */
111SecCertificateRef
112SecCertificateCreateFromItemImplInstance(SecCertificateRef certificate)
113{
114#if !SECTRUST_OSX
115 return (SecCertificateRef)(certificate ? CFRetain(certificate) : NULL);
116#else
117 if (!certificate) {
118 return NULL;
119 }
120 SecCertificateRef result = NULL;
121 CFDataRef data = NULL;
122 try {
123 CssmData certData = Certificate::required(certificate)->data();
124 if (certData.Data && certData.Length) {
125 data = CFDataCreate(NULL, certData.Data, certData.Length);
126 }
127 if (!data) {
128 if (certData.Data && !certData.Length) {
129 /* zero-length certs can exist, so don't bother logging this */
130 }
131 else {
132 syslog(LOG_ERR, "WARNING: SecKeychainSearchCopyNext failed to retrieve certificate data (length=%ld, data=0x%lX)",
133 (long)certData.Length, (uintptr_t)certData.Data);
134 }
135 return NULL;
136 }
137 }
138 catch (...) {}
139
140 result = SecCertificateCreateWithKeychainItem(NULL, data, certificate);
141 if (data)
142 CFRelease(data);
143 return result;
144#endif
145}
146
147/* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
b1ab9ed8
A
148OSStatus
149SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding, SecCertificateRef *certificate)
150{
5c19dc3a 151#if !SECTRUST_OSX
b1ab9ed8
A
152 BEGIN_SECAPI
153
154 SecPointer<Certificate> certificatePtr(new Certificate(Required(data), type, encoding));
155 Required(certificate) = certificatePtr->handle();
156
157 END_SECAPI
5c19dc3a
A
158#else
159 /* bridge to support old functionality */
160 if (!data || !data->Data || !data->Length || !certificate) {
161 return errSecParam;
162 }
163 SecCertificateRef certRef = NULL;
164 CFDataRef dataRef = CFDataCreate(NULL, data->Data, data->Length);
165 if (dataRef) {
166 certRef = SecCertificateCreateWithData(NULL, dataRef);
167 CFRelease(dataRef);
168 }
169 *certificate = certRef;
170 return (certRef) ? errSecSuccess : errSecUnknownFormat;
171#endif
b1ab9ed8
A
172}
173
5c19dc3a 174#if !SECTRUST_OSX
b1ab9ed8
A
175/* new in 10.6 */
176SecCertificateRef
177SecCertificateCreateWithData(CFAllocatorRef allocator, CFDataRef data)
178{
179 SecCertificateRef certificate = NULL;
180 OSStatus __secapiresult;
181 try {
182 CSSM_DATA cssmCertData;
183 cssmCertData.Length = (data) ? (CSSM_SIZE)CFDataGetLength(data) : 0;
184 cssmCertData.Data = (data) ? (uint8 *)CFDataGetBytePtr(data) : NULL;
185
186 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
187 SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER));
188 certificate = certificatePtr->handle();
189
427c49bc 190 __secapiresult=errSecSuccess;
b1ab9ed8
A
191 }
192 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
193 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
194 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
195 catch (...) { __secapiresult=errSecInternalComponent; }
b1ab9ed8
A
196 return certificate;
197}
5c19dc3a 198#endif
b1ab9ed8 199
5c19dc3a 200/* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */
b1ab9ed8
A
201OSStatus
202SecCertificateAddToKeychain(SecCertificateRef certificate, SecKeychainRef keychain)
203{
5c19dc3a
A
204 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
205 BEGIN_SECCERTAPI
b1ab9ed8 206
5c19dc3a 207 Item item(Certificate::required(__itemImplRef));
b1ab9ed8
A
208 Keychain::optional(keychain)->add(item);
209
5c19dc3a 210 END_SECCERTAPI
b1ab9ed8
A
211}
212
5c19dc3a 213/* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
b1ab9ed8
A
214OSStatus
215SecCertificateGetData(SecCertificateRef certificate, CSSM_DATA_PTR data)
216{
5c19dc3a
A
217 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
218 BEGIN_SECCERTAPI
b1ab9ed8 219
5c19dc3a 220 Required(data) = Certificate::required(__itemImplRef)->data();
b1ab9ed8 221
5c19dc3a 222 END_SECCERTAPI
b1ab9ed8
A
223}
224
5c19dc3a 225#if !SECTRUST_OSX
b1ab9ed8
A
226/* new in 10.6 */
227CFDataRef
228SecCertificateCopyData(SecCertificateRef certificate)
229{
230 CFDataRef data = NULL;
427c49bc 231 OSStatus __secapiresult = errSecSuccess;
b1ab9ed8
A
232 try {
233 CssmData output = Certificate::required(certificate)->data();
234 CFIndex length = (CFIndex)output.length();
235 const UInt8 *bytes = (const UInt8 *)output.data();
236 if (length && bytes) {
237 data = CFDataCreate(NULL, bytes, length);
238 }
b1ab9ed8
A
239 }
240 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
241 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
242 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
243 catch (...) { __secapiresult=errSecInternalComponent; }
244 return data;
245}
5c19dc3a 246#endif
427c49bc 247
5c19dc3a 248#if !SECTRUST_OSX
427c49bc
A
249CFDataRef
250SecCertificateGetSHA1Digest(SecCertificateRef certificate)
251{
252 CFDataRef data = NULL;
253 OSStatus __secapiresult = errSecSuccess;
254 try {
255 data = Certificate::required(certificate)->sha1Hash();
256 }
257 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
258 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
259 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
260 catch (...) { __secapiresult=errSecInternalComponent; }
b1ab9ed8
A
261 return data;
262}
e3d460c9
A
263
264CFDataRef
265SecCertificateCopySHA256Digest(SecCertificateRef certificate)
266{
267 CFDataRef data = NULL;
268 OSStatus __secapiresult = errSecSuccess;
269 try {
270 data = Certificate::required(certificate)->sha256Hash();
271 if (data)
272 CFRetain(data);
273 }
274 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
275 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
276 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
277 catch (...) { __secapiresult=errSecInternalComponent; }
278 return data;
279}
280
281
5c19dc3a 282#endif
b1ab9ed8 283
5c19dc3a
A
284#if !SECTRUST_OSX
285CFDataRef
286SecCertificateCopyPublicKeySHA1Digest(SecCertificateRef certificate)
287{
288 CFDataRef data = NULL;
289 OSStatus __secapiresult = errSecSuccess;
290 try {
291 CssmData output = Certificate::required(certificate)->publicKeyHash();
292 CFIndex length = (CFIndex)output.length();
293 const UInt8 *bytes = (const UInt8 *)output.data();
294 if (length && bytes) {
295 data = CFDataCreate(NULL, bytes, length);
296 }
297 }
298 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
299 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
300 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
301 catch (...) { __secapiresult=errSecInternalComponent; }
302 return data;
303}
304#endif
305
306#if !SECTRUST_OSX
4d3cab3d
A
307CFArrayRef
308SecCertificateCopyDNSNames(SecCertificateRef certificate)
309{
310 CFArrayRef names = NULL;
311 OSStatus __secapiresult = errSecSuccess;
312 try {
313 names = Certificate::required(certificate)->copyDNSNames();
314 }
315 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
316 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
317 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
318 catch (...) { __secapiresult=errSecInternalComponent; }
319 return names;
320}
5c19dc3a 321#endif
427c49bc 322
5c19dc3a 323/* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
b1ab9ed8
A
324OSStatus
325SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificateType)
326{
5c19dc3a
A
327 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
328 BEGIN_SECCERTAPI
b1ab9ed8 329
5c19dc3a 330 Required(certificateType) = Certificate::required(__itemImplRef)->type();
b1ab9ed8 331
5c19dc3a 332 END_SECCERTAPI
b1ab9ed8
A
333}
334
5c19dc3a 335/* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
b1ab9ed8
A
336OSStatus
337SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **subject)
338{
5c19dc3a
A
339 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
340 BEGIN_SECCERTAPI
b1ab9ed8 341
5c19dc3a 342 Required(subject) = Certificate::required(__itemImplRef)->subjectName();
b1ab9ed8 343
5c19dc3a 344 END_SECCERTAPI
b1ab9ed8
A
345}
346
5c19dc3a 347/* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
b1ab9ed8
A
348OSStatus
349SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **issuer)
350{
5c19dc3a
A
351 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
352 BEGIN_SECCERTAPI
353
354 Required(issuer) = Certificate::required(__itemImplRef)->issuerName();
355
356 END_SECCERTAPI
357}
358
359/* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
360OSStatus
361SecCertificateGetCLHandle(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle)
362{
363#if !SECTRUST_OSX
b1ab9ed8
A
364 BEGIN_SECAPI
365
5c19dc3a 366 Required(clHandle) = Certificate::required(certificate)->clHandle();
b1ab9ed8
A
367
368 END_SECAPI
5c19dc3a
A
369#else
370#if 0
371 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
372 BEGIN_SECCERTAPI
373
374 Required(clHandle) = Certificate::required(__itemImplRef)->clHandle();
375
376 END_SECCERTAPI
377#endif
378 /* bridge code to support deprecated functionality */
379 OSStatus __secapiresult=errSecSuccess;
380 bool kcItem=true;
381 SecCertificateRef __itemImplRef=(SecCertificateRef)SecCertificateCopyKeychainItem(certificate);
382 if (!__itemImplRef) { __itemImplRef=SecCertificateCreateItemImplInstance(certificate); kcItem=false; }
383 try {
384 Required(clHandle) = Certificate::required(__itemImplRef)->clHandle();
385 }
386 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
387 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
388 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
389 catch (...) { __secapiresult=errSecInternalComponent; }
390 if (__itemImplRef) {
391 if (!kcItem) {
392 /* we can't release the temporary certificate, or the CL handle becomes invalid.
393 * for now, just stick the temporary certificate into an array.
394 * TBD: use a dictionary, indexed by hash of certificate. */
395 static CFMutableArrayRef sLegacyCertArray = NULL;
396 if (!sLegacyCertArray) {
397 sLegacyCertArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
398 if (!sLegacyCertArray) {
399 return errSecAllocate;
400 }
401 }
402 CFArrayAppendValue(sLegacyCertArray, __itemImplRef);
403#ifndef NDEBUG
404 syslog(LOG_ERR, "WARNING: SecCertificateGetCLHandle called on certificate which is not in a keychain.");
405#endif
406 }
407 CFRelease(__itemImplRef);
408 }
409 return __secapiresult;
b1ab9ed8 410
5c19dc3a
A
411#endif
412}
b1ab9ed8 413
5c19dc3a
A
414/* private function; assumes input is old-style ItemImpl certificate reference,
415 and does not release that certificate reference!
416 */
b1ab9ed8 417OSStatus
5c19dc3a 418SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle)
b1ab9ed8
A
419{
420 BEGIN_SECAPI
421
5c19dc3a 422 Required(clHandle) = Certificate::required(certificate)->clHandle();
b1ab9ed8
A
423
424 END_SECAPI
425}
426
5c19dc3a 427
b1ab9ed8
A
428/*
429 * Private API to infer a display name for a SecCertificateRef which
430 * may or may not be in a keychain.
5c19dc3a
A
431 *
432 * OS X only
b1ab9ed8
A
433 */
434OSStatus
435SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label)
436{
5c19dc3a
A
437 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
438 BEGIN_SECCERTAPI
b1ab9ed8 439
5c19dc3a 440 Certificate::required(__itemImplRef)->inferLabel(false, &Required(label));
b1ab9ed8 441
5c19dc3a 442 END_SECCERTAPI
b1ab9ed8
A
443}
444
5c19dc3a 445/* OS X only (note: iOS version has different arguments and return value) */
b1ab9ed8
A
446OSStatus
447SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key)
448{
5c19dc3a
A
449 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
450 BEGIN_SECCERTAPI
b1ab9ed8 451
5c19dc3a 452 Required(key) = Certificate::required(__itemImplRef)->publicKey()->handle();
b1ab9ed8 453
5c19dc3a 454 END_SECCERTAPI
b1ab9ed8
A
455}
456
5c19dc3a 457/* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
b1ab9ed8
A
458OSStatus
459SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGORITHM_IDENTIFIER **algid)
460{
5c19dc3a
A
461 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
462 BEGIN_SECCERTAPI
b1ab9ed8 463
5c19dc3a 464 Required(algid) = Certificate::required(__itemImplRef)->algorithmID();
b1ab9ed8 465
5c19dc3a 466 END_SECCERTAPI
b1ab9ed8
A
467}
468
5c19dc3a 469/* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
b1ab9ed8
A
470OSStatus
471SecCertificateCopyCommonName(SecCertificateRef certificate, CFStringRef *commonName)
472{
5c19dc3a
A
473 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
474 BEGIN_SECCERTAPI
b1ab9ed8 475
5c19dc3a 476 Required(commonName) = Certificate::required(__itemImplRef)->commonName();
b1ab9ed8 477
5c19dc3a 478 END_SECCERTAPI
b1ab9ed8
A
479}
480
5c19dc3a 481#if !SECTRUST_OSX
b1ab9ed8
A
482/* new in 10.6 */
483CFStringRef
484SecCertificateCopySubjectSummary(SecCertificateRef certificate)
485{
486 CFStringRef summary = NULL;
487 OSStatus __secapiresult;
488 try {
489 Certificate::required(certificate)->inferLabel(false, &summary);
490
427c49bc 491 __secapiresult=errSecSuccess;
b1ab9ed8
A
492 }
493 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
494 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
495 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
496 catch (...) { __secapiresult=errSecInternalComponent; }
b1ab9ed8
A
497 return summary;
498}
5c19dc3a 499#endif
b1ab9ed8 500
5c19dc3a 501#if !SECTRUST_OSX
4d3cab3d
A
502CFStringRef
503SecCertificateCopyIssuerSummary(SecCertificateRef certificate)
504{
505 CFStringRef issuerStr = NULL;
506 SecCertificateRefP certP = NULL;
507 CFDataRef certData = SecCertificateCopyData(certificate);
508 if (certData) {
509 certP = SecCertificateCreateWithDataP(NULL, certData);
510 CFRelease(certData);
511 }
512 if (certP) {
513 issuerStr = SecCertificateCopyIssuerSummaryP(certP);
514 CFRelease(certP);
515 }
516 return issuerStr;
517}
5c19dc3a 518#endif
4d3cab3d 519
5c19dc3a 520/* OS X only */
b1ab9ed8
A
521OSStatus
522SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, CFStringRef *result)
523{
5c19dc3a
A
524 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
525 BEGIN_SECCERTAPI
b1ab9ed8 526
5c19dc3a 527 Required(result) = Certificate::required(__itemImplRef)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct, component);
b1ab9ed8 528
5c19dc3a 529 END_SECCERTAPI
b1ab9ed8
A
530}
531
5c19dc3a 532/* OS X only; deprecated SPI */
b1ab9ed8
A
533OSStatus
534SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName)
535{
536 // deprecated SPI signature; replaced by SecCertificateCopyCommonName
537 return SecCertificateCopyCommonName(certificate, commonName);
538}
539
5c19dc3a 540/* OS X only; deprecated SPI */
b1ab9ed8
A
541OSStatus
542SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress)
543{
5c19dc3a
A
544 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
545 BEGIN_SECCERTAPI
b1ab9ed8 546
5c19dc3a 547 Required(emailAddress) = Certificate::required(__itemImplRef)->copyFirstEmailAddress();
b1ab9ed8 548
5c19dc3a 549 END_SECCERTAPI
b1ab9ed8
A
550}
551
5c19dc3a 552/* OS X only */
b1ab9ed8
A
553OSStatus
554SecCertificateCopyEmailAddresses(SecCertificateRef certificate, CFArrayRef *emailAddresses)
555{
5c19dc3a
A
556 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
557 BEGIN_SECCERTAPI
b1ab9ed8 558
5c19dc3a 559 Required(emailAddresses) = Certificate::required(__itemImplRef)->copyEmailAddresses();
b1ab9ed8 560
5c19dc3a 561 END_SECCERTAPI
b1ab9ed8
A
562}
563
5c19dc3a
A
564/* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field.
565 * Caller must call releaseFieldValues to free the storage allocated by this call.
566 *
567 * OS X only
568 */
b1ab9ed8
A
569OSStatus
570SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues)
571{
5c19dc3a
A
572 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
573 BEGIN_SECCERTAPI
b1ab9ed8 574
5c19dc3a 575 Required(fieldValues) = Certificate::required(__itemImplRef)->copyFieldValues(Required(field));
b1ab9ed8 576
5c19dc3a 577 END_SECCERTAPI
b1ab9ed8
A
578}
579
5c19dc3a 580/* OS X only */
b1ab9ed8
A
581OSStatus
582SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValues)
583{
5c19dc3a
A
584 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
585 BEGIN_SECCERTAPI
b1ab9ed8 586
5c19dc3a 587 Certificate::required(__itemImplRef)->releaseFieldValues(Required(field), fieldValues);
b1ab9ed8 588
5c19dc3a 589 END_SECCERTAPI
b1ab9ed8
A
590}
591
5c19dc3a 592/* OS X only */
b1ab9ed8
A
593OSStatus
594SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue)
595{
5c19dc3a
A
596 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
597 BEGIN_SECCERTAPI
b1ab9ed8 598
5c19dc3a 599 Required(fieldValue) = Certificate::required(__itemImplRef)->copyFirstFieldValue(Required(field));
b1ab9ed8 600
5c19dc3a 601 END_SECCERTAPI
b1ab9ed8
A
602}
603
5c19dc3a 604/* OS X only */
b1ab9ed8
A
605OSStatus
606SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR fieldValue)
607{
5c19dc3a
A
608 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
609 BEGIN_SECCERTAPI
b1ab9ed8 610
5c19dc3a 611 Certificate::required(__itemImplRef)->releaseFieldValue(Required(field), fieldValue);
b1ab9ed8 612
5c19dc3a 613 END_SECCERTAPI
b1ab9ed8
A
614}
615
5c19dc3a 616/* OS X only */
b1ab9ed8
A
617OSStatus
618SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray,const CSSM_DATA *issuer,
619 const CSSM_DATA *serialNumber, SecCertificateRef *certificate)
620{
621 BEGIN_SECAPI
622
623 StorageManager::KeychainList keychains;
624 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
625 Required(certificate) = Certificate::findByIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber))->handle();
626
5c19dc3a
A
627#if SECTRUST_OSX
628 // convert ItemImpl-based SecCertificateRef to new-world version before returning
629 CssmData certData = Certificate::required(*certificate)->data();
630 CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length));
631 SecCertificateRef tmpRef = *certificate;
632 *certificate = SecCertificateCreateWithData(NULL, cfData);
633 CFRelease(tmpRef);
634#endif
635
b1ab9ed8
A
636 END_SECAPI
637}
638
5c19dc3a 639/* OS X only */
b1ab9ed8
A
640OSStatus
641SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
642 SecCertificateRef *certificate)
643{
644 BEGIN_SECAPI
645
646 StorageManager::KeychainList keychains;
647 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
648 Required(certificate) = Certificate::findBySubjectKeyID(keychains, CssmData::required(subjectKeyID))->handle();
649
5c19dc3a
A
650#if SECTRUST_OSX
651 // convert ItemImpl-based SecCertificateRef to new-world version before returning
652 CssmData certData = Certificate::required(*certificate)->data();
653 CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length));
654 SecCertificateRef tmpRef = *certificate;
655 *certificate = SecCertificateCreateWithData(NULL, cfData);
656 CFRelease(tmpRef);
657#endif
658
b1ab9ed8
A
659 END_SECAPI
660}
661
5c19dc3a 662/* OS X only */
b1ab9ed8
A
663OSStatus
664SecCertificateFindByEmail(CFTypeRef keychainOrArray, const char *emailAddress, SecCertificateRef *certificate)
665{
666 BEGIN_SECAPI
667
668 StorageManager::KeychainList keychains;
669 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
670 Required(certificate) = Certificate::findByEmail(keychains, emailAddress)->handle();
671
5c19dc3a
A
672#if SECTRUST_OSX
673 // convert ItemImpl-based SecCertificateRef to new-world version before returning
674 CssmData certData = Certificate::required(*certificate)->data();
675 CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length));
676 SecCertificateRef tmpRef = *certificate;
677 *certificate = SecCertificateCreateWithData(NULL, cfData);
678 CFRelease(tmpRef);
679#endif
680
b1ab9ed8
A
681 END_SECAPI
682}
683
5c19dc3a 684/* OS X only */
b1ab9ed8
A
685OSStatus
686SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer,
687 const CSSM_DATA *serialNumber, SecKeychainSearchRef *searchRef)
688{
689 BEGIN_SECAPI
690
691 Required(searchRef);
692
693 StorageManager::KeychainList keychains;
694 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
695 KCCursor cursor(Certificate::cursorForIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber)));
696 *searchRef = cursor->handle();
697
698 END_SECAPI
699}
700
5c19dc3a 701/* OS X only */
b1ab9ed8
A
702OSStatus
703SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray, CFDataRef issuer,
704 CFDataRef serialNumber, SecKeychainSearchRef *searchRef)
705{
706 BEGIN_SECAPI
707
708 Required(searchRef);
709
710 StorageManager::KeychainList keychains;
711 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
712 Required(issuer);
713 Required(serialNumber);
714 KCCursor cursor(Certificate::cursorForIssuerAndSN_CF(keychains, issuer, serialNumber));
715 *searchRef = cursor->handle();
716
717 END_SECAPI
718}
719
5c19dc3a 720/* OS X only */
b1ab9ed8
A
721OSStatus
722SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
723 SecKeychainSearchRef *searchRef)
724{
725 BEGIN_SECAPI
726
727 Required(searchRef);
728
729 StorageManager::KeychainList keychains;
730 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
731 KCCursor cursor(Certificate::cursorForSubjectKeyID(keychains, CssmData::required(subjectKeyID)));
732 *searchRef = cursor->handle();
733
734 END_SECAPI
735}
736
5c19dc3a 737/* OS X only */
b1ab9ed8
A
738OSStatus
739SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray, const char *emailAddress,
740 SecKeychainSearchRef *searchRef)
741{
742 BEGIN_SECAPI
743
744 Required(searchRef);
745
746 StorageManager::KeychainList keychains;
747 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
748 KCCursor cursor(Certificate::cursorForEmail(keychains, emailAddress));
749 *searchRef = cursor->handle();
750
751 END_SECAPI
752}
753
5c19dc3a 754/* OS X only */
b1ab9ed8
A
755CSSM_RETURN
756SecDigestGetData (CSSM_ALGORITHMS alg, CSSM_DATA* digest, const CSSM_DATA* data)
757{
758 BEGIN_SECAPI
759 // sanity checking
760 if (!digest || !digest->Data || !digest->Length || !data || !data->Data || !data->Length)
427c49bc 761 return errSecParam;
b1ab9ed8
A
762
763 CSP csp(gGuidAppleCSP);
764 Digest context(csp, alg);
765 CssmData input(data->Data, data->Length);
766 CssmData output(digest->Data, digest->Length);
767
768 context.digest(input, output);
769 digest->Length = output.length();
770
771 return CSSM_OK;
772 END_SECAPI1(1);
773}
774
5c19dc3a 775#if !SECTRUST_OSX
b1ab9ed8
A
776/* determine whether a cert is self-signed */
777OSStatus SecCertificateIsSelfSigned(
778 SecCertificateRef certificate,
779 Boolean *isSelfSigned) /* RETURNED */
780{
781 BEGIN_SECAPI
782
783 *isSelfSigned = Certificate::required(certificate)->isSelfSigned();
784
785 END_SECAPI
786}
5c19dc3a 787#endif
b1ab9ed8 788
5c19dc3a 789/* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
b1ab9ed8
A
790OSStatus
791SecCertificateCopyPreference(
792 CFStringRef name,
793 CSSM_KEYUSE keyUsage,
794 SecCertificateRef *certificate)
795{
796 BEGIN_SECAPI
797
798 Required(name);
799 Required(certificate);
800 StorageManager::KeychainList keychains;
801 globals().storageManager.getSearchList(keychains);
802 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
803
804 char idUTF8[MAXPATHLEN];
805 if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
806 idUTF8[0] = (char)'\0';
807 CssmData service(const_cast<char *>(idUTF8), strlen(idUTF8));
808 FourCharCode itemType = 'cprf';
809 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
810 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
811 if (keyUsage)
812 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
813
814 Item prefItem;
815 if (!cursor->next(prefItem))
816 MacOSError::throwMe(errSecItemNotFound);
817
818 // get persistent certificate reference
819 SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } };
820 SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
821 prefItem->getContent(NULL, &itemAttrList, NULL, NULL);
822
823 // find certificate, given persistent reference data
824 CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull);
825 SecKeychainItemRef certItemRef = nil;
826 OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); //%%% need to make this a method of ItemImpl
827 prefItem->freeContent(&itemAttrList, NULL);
828 if (pItemRef)
829 CFRelease(pItemRef);
830 if (status)
831 return status;
832
833 *certificate = (SecCertificateRef)certItemRef;
834
5c19dc3a
A
835#if SECTRUST_OSX
836 // convert ItemImpl-based SecCertificateRef to new-world version before returning
837 CssmData certData = Certificate::required(*certificate)->data();
838 CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length));
839 SecCertificateRef tmpRef = *certificate;
840 *certificate = SecCertificateCreateWithData(NULL, cfData);
841 CFRelease(tmpRef);
842#endif
843
b1ab9ed8
A
844 END_SECAPI
845}
846
5c19dc3a 847/* OS X only */
b1ab9ed8
A
848SecCertificateRef
849SecCertificateCopyPreferred(
850 CFStringRef name,
851 CFArrayRef keyUsage)
852{
853 // This function will look for a matching preference in the following order:
854 // - matches the name and the supplied key use
855 // - matches the name and the special 'ANY' key use
856 // - matches the name with no key usage constraint
857
858 SecCertificateRef certRef = NULL;
859 CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
860 OSStatus status = SecCertificateCopyPreference(name, keyUse, &certRef);
427c49bc 861 if (status != errSecSuccess && keyUse != CSSM_KEYUSE_ANY)
b1ab9ed8 862 status = SecCertificateCopyPreference(name, CSSM_KEYUSE_ANY, &certRef);
427c49bc 863 if (status != errSecSuccess && keyUse != 0)
b1ab9ed8
A
864 status = SecCertificateCopyPreference(name, 0, &certRef);
865
866 return certRef;
867}
868
5c19dc3a 869/* OS X only; not exported */
427c49bc 870static OSStatus
b1ab9ed8
A
871SecCertificateFindPreferenceItemWithNameAndKeyUsage(
872 CFTypeRef keychainOrArray,
873 CFStringRef name,
874 int32_t keyUsage,
875 SecKeychainItemRef *itemRef)
876{
877 BEGIN_SECAPI
878
879 StorageManager::KeychainList keychains;
880 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
881 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
882
883 char idUTF8[MAXPATHLEN];
884 idUTF8[0] = (char)'\0';
885 if (name)
886 {
887 if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
888 idUTF8[0] = (char)'\0';
889 }
890 size_t idUTF8Len = strlen(idUTF8);
891 if (!idUTF8Len)
427c49bc 892 MacOSError::throwMe(errSecParam);
b1ab9ed8
A
893
894 CssmData service(const_cast<char *>(idUTF8), idUTF8Len);
895 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
896 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'cprf');
897 if (keyUsage)
898 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
899
900 Item item;
901 if (!cursor->next(item))
902 MacOSError::throwMe(errSecItemNotFound);
903
904 if (itemRef)
905 *itemRef=item->handle();
906
907 END_SECAPI
908}
909
5c19dc3a 910/* OS X only; not exported */
427c49bc 911static
b1ab9ed8
A
912OSStatus SecCertificateDeletePreferenceItemWithNameAndKeyUsage(
913 CFTypeRef keychainOrArray,
914 CFStringRef name,
915 int32_t keyUsage)
916{
917 // when a specific key usage is passed, we'll only match & delete that pref;
918 // when a key usage of 0 is passed, all matching prefs should be deleted.
919 // maxUsages represents the most matches there could theoretically be, so
920 // cut things off at that point if we're still finding items (if they can't
921 // be deleted for some reason, we'd never break out of the loop.)
922
923 OSStatus status;
924 SecKeychainItemRef item = NULL;
925 int count = 0, maxUsages = 12;
926 while (++count <= maxUsages &&
427c49bc 927 (status = SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray, name, keyUsage, &item)) == errSecSuccess) {
b1ab9ed8
A
928 status = SecKeychainItemDelete(item);
929 CFRelease(item);
930 item = NULL;
931 }
932
933 // it's not an error if the item isn't found
427c49bc 934 return (status == errSecItemNotFound) ? errSecSuccess : status;
b1ab9ed8
A
935}
936
5c19dc3a 937/* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
b1ab9ed8
A
938OSStatus SecCertificateSetPreference(
939 SecCertificateRef certificate,
940 CFStringRef name,
941 CSSM_KEYUSE keyUsage,
942 CFDateRef date)
943{
944 if (!name) {
427c49bc 945 return errSecParam;
b1ab9ed8
A
946 }
947 if (!certificate) {
948 // treat NULL certificate as a request to clear the preference
949 // (note: if keyUsage is 0, this clears all key usage prefs for name)
950 return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL, name, keyUsage);
951 }
952
5c19dc3a
A
953 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
954 BEGIN_SECCERTAPI
b1ab9ed8
A
955
956 // determine the account attribute
957 //
958 // This attribute must be synthesized from certificate label + pref item type + key usage,
959 // as only the account and service attributes can make a generic keychain item unique.
960 // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that
961 // we can save a certificate preference if an identity preference already exists for the
962 // given service name, and vice-versa.
963 // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string.
964 //
965 CFStringRef labelStr = nil;
5c19dc3a 966 Certificate::required(__itemImplRef)->inferLabel(false, &labelStr);
b1ab9ed8
A
967 if (!labelStr) {
968 MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed"
969 }
970 CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1;
971 const char *templateStr = "%s [key usage 0x%X]";
972 const int keyUsageMaxStrLen = 8;
973 accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen;
974 char accountUTF8[accountUTF8Len];
975 if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8))
976 accountUTF8[0] = (char)'\0';
977 if (keyUsage)
978 snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage);
979 CssmData account(const_cast<char *>(accountUTF8), strlen(accountUTF8));
980 CFRelease(labelStr);
981
982 // service attribute (name provided by the caller)
983 CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8) + 1;;
984 char serviceUTF8[serviceUTF8Len];
985 if (!CFStringGetCString(name, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8))
986 serviceUTF8[0] = (char)'\0';
987 CssmData service(const_cast<char *>(serviceUTF8), strlen(serviceUTF8));
988
989 // look for existing preference item, in case this is an update
990 StorageManager::KeychainList keychains;
991 globals().storageManager.getSearchList(keychains);
992 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
993 FourCharCode itemType = 'cprf';
994 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
995 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
996 if (keyUsage)
997 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
998 if (date)
999 ; // %%%TBI
1000
1001 Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false);
1002 bool add = (!cursor->next(item));
1003 // at this point, we either have a new item to add or an existing item to update
1004
1005 // set item attribute values
1006 item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service);
1007 item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), itemType);
1008 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
1009 item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
1010 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service);
1011
1012 // date
1013 if (date)
1014 ; // %%%TBI
1015
1016 // generic attribute (store persistent certificate reference)
1017 CFDataRef pItemRef = nil;
5c19dc3a 1018 Certificate::required(__itemImplRef)->copyPersistentReference(pItemRef);
b1ab9ed8
A
1019 if (!pItemRef) {
1020 MacOSError::throwMe(errSecInvalidItemRef);
1021 }
1022 const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef);
1023 CFIndex dataLen = CFDataGetLength(pItemRef);
1024 CssmData pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr)), dataLen);
1025 item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref);
1026 CFRelease(pItemRef);
1027
1028 if (add) {
1029 Keychain keychain = nil;
1030 try {
1031 keychain = globals().storageManager.defaultKeychain();
1032 if (!keychain->exists())
1033 MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time.
1034 }
1035 catch(...) {
1036 keychain = globals().storageManager.defaultKeychainUI(item);
1037 }
1038
1039 try {
1040 keychain->add(item);
1041 }
1042 catch (const MacOSError &err) {
1043 if (err.osStatus() != errSecDuplicateItem)
1044 throw; // if item already exists, fall through to update
1045 }
1046 }
1047 item->update();
1048
5c19dc3a 1049 END_SECCERTAPI
b1ab9ed8
A
1050}
1051
5c19dc3a 1052/* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
b1ab9ed8
A
1053OSStatus SecCertificateSetPreferred(
1054 SecCertificateRef certificate,
1055 CFStringRef name,
1056 CFArrayRef keyUsage)
1057{
1058 CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
1059 return SecCertificateSetPreference(certificate, name, keyUse, NULL);
1060}
1061
5c19dc3a 1062/* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
b1ab9ed8
A
1063CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayRef keys, CFErrorRef *error)
1064{
1065 CFDictionaryRef result = NULL;
427c49bc 1066 OSStatus __secapiresult;
b1ab9ed8
A
1067 try
1068 {
1069 CertificateValues cv(certificate);
1070 result = cv.copyFieldValues(keys,error);
1071 __secapiresult=0;
1072 }
1073 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1074 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
1075 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1076 catch (...) { __secapiresult=errSecInternalComponent; }
1077 return result;
b1ab9ed8
A
1078}
1079
5c19dc3a 1080/* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
b1ab9ed8
A
1081CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
1082{
1083 return SecCertificateCopyShortDescription(alloc, certificate, error);
1084}
1085
5c19dc3a 1086/* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
b1ab9ed8
A
1087CFStringRef SecCertificateCopyShortDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
1088{
1089 CFStringRef result = NULL;
5c19dc3a 1090 OSStatus __secapiresult = SecCertificateInferLabel(certificate, &result);
427c49bc 1091 if (error!=NULL && __secapiresult!=errSecSuccess)
b1ab9ed8
A
1092 {
1093 *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus,
1094 __secapiresult ? __secapiresult : CSSM_ERRCODE_INTERNAL_ERROR, NULL);
1095 }
427c49bc 1096 return result;
b1ab9ed8
A
1097}
1098
5c19dc3a 1099/* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
b1ab9ed8
A
1100CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error)
1101{
1102 CFDataRef result = NULL;
427c49bc 1103 OSStatus __secapiresult;
b1ab9ed8
A
1104 try
1105 {
1106 CertificateValues cv(certificate);
1107 result = cv.copySerialNumber(error);
1108 __secapiresult=0;
1109 }
1110 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1111 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
1112 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1113 catch (...) { __secapiresult=errSecInternalComponent; }
1114 return result;
b1ab9ed8
A
1115}
1116
5c19dc3a 1117/* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
b1ab9ed8
A
1118CFDataRef SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate, CFErrorRef *error)
1119{
1120 CFDataRef result = NULL;
427c49bc 1121 OSStatus __secapiresult;
b1ab9ed8
A
1122 try
1123 {
1124 CertificateValues cv(certificate);
427c49bc 1125 result = cv.copyNormalizedIssuerContent(error);
b1ab9ed8
A
1126 __secapiresult=0;
1127 }
1128 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1129 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
1130 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1131 catch (...) { __secapiresult=errSecInternalComponent; }
1132 return result;
b1ab9ed8
A
1133}
1134
5c19dc3a 1135/* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
b1ab9ed8
A
1136CFDataRef SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate, CFErrorRef *error)
1137{
1138 CFDataRef result = NULL;
427c49bc 1139 OSStatus __secapiresult;
b1ab9ed8
A
1140 try
1141 {
1142 CertificateValues cv(certificate);
427c49bc 1143 result = cv.copyNormalizedSubjectContent(error);
b1ab9ed8
A
1144 __secapiresult=0;
1145 }
1146 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1147 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
1148 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1149 catch (...) { __secapiresult=errSecInternalComponent; }
1150 return result;
b1ab9ed8
A
1151}
1152
5c19dc3a 1153#if !SECTRUST_OSX
427c49bc
A
1154CFDataRef SecCertificateCopyIssuerSequence(SecCertificateRef certificate)
1155{
1156 CFDataRef result = NULL;
1157 OSStatus __secapiresult;
1158 try
1159 {
1160 CertificateValues cv(certificate);
1161 result = cv.copyIssuerSequence(NULL);
1162 __secapiresult=0;
1163 }
1164 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1165 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1166 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1167 catch (...) { __secapiresult=errSecInternalComponent; }
1168 return result;
1169}
5c19dc3a 1170#endif
427c49bc 1171
5c19dc3a 1172#if !SECTRUST_OSX
427c49bc
A
1173CFDataRef SecCertificateCopySubjectSequence(SecCertificateRef certificate)
1174{
1175 CFDataRef result = NULL;
1176 OSStatus __secapiresult;
1177 try
1178 {
1179 CertificateValues cv(certificate);
1180 result = cv.copySubjectSequence(NULL);
1181 __secapiresult=0;
1182 }
1183 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1184 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1185 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1186 catch (...) { __secapiresult=errSecInternalComponent; }
1187 return result;
1188}
5c19dc3a 1189#endif
427c49bc 1190
5c19dc3a 1191#if !SECTRUST_OSX
427c49bc 1192bool SecCertificateIsValid(SecCertificateRef certificate, CFAbsoluteTime verifyTime)
b1ab9ed8
A
1193{
1194 bool result = NULL;
427c49bc 1195 OSStatus __secapiresult;
b1ab9ed8
A
1196 try
1197 {
427c49bc 1198 CFErrorRef error = NULL;
b1ab9ed8 1199 CertificateValues cv(certificate);
427c49bc
A
1200 result = cv.isValid(verifyTime, &error);
1201 if (error) CFRelease(error);
b1ab9ed8
A
1202 __secapiresult=0;
1203 }
1204 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1205 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
1206 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1207 catch (...) { __secapiresult=errSecInternalComponent; }
1208 return result;
1209}
5c19dc3a 1210#endif
427c49bc 1211
5c19dc3a 1212/* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA) */
427c49bc
A
1213bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime)
1214{
5c19dc3a
A
1215 /*
1216 * deprecated function name
1217 */
427c49bc
A
1218 return SecCertificateIsValid(certificate, verifyTime);
1219}
1220
5c19dc3a 1221#if !SECTRUST_OSX
427c49bc
A
1222CFAbsoluteTime SecCertificateNotValidBefore(SecCertificateRef certificate)
1223{
1224 CFAbsoluteTime result = 0;
1225 OSStatus __secapiresult;
1226 try
1227 {
1228 CFErrorRef error = NULL;
1229 CertificateValues cv(certificate);
1230 result = cv.notValidBefore(&error);
1231 if (error) CFRelease(error);
1232 __secapiresult=0;
1233 }
1234 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1235 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1236 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1237 catch (...) { __secapiresult=errSecInternalComponent; }
1238 return result;
1239}
5c19dc3a 1240#endif
427c49bc 1241
5c19dc3a 1242#if !SECTRUST_OSX
427c49bc
A
1243CFAbsoluteTime SecCertificateNotValidAfter(SecCertificateRef certificate)
1244{
1245 CFAbsoluteTime result = 0;
1246 OSStatus __secapiresult;
1247 try
1248 {
1249 CFErrorRef error = NULL;
1250 CertificateValues cv(certificate);
1251 result = cv.notValidAfter(&error);
1252 if (error) CFRelease(error);
1253 __secapiresult=0;
1254 }
1255 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1256 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1257 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1258 catch (...) { __secapiresult=errSecInternalComponent; }
1259 return result;
b1ab9ed8 1260}
5c19dc3a 1261#endif
b1ab9ed8 1262
5c19dc3a 1263#if !SECTRUST_OSX
b1ab9ed8
A
1264/* new in 10.8 */
1265SecCertificateRef SecCertificateCreateWithBytes(CFAllocatorRef allocator,
1266 const UInt8 *bytes, CFIndex length)
1267{
1268 SecCertificateRef certificate = NULL;
1269 OSStatus __secapiresult;
1270 try {
1271 CSSM_DATA cssmCertData = { (CSSM_SIZE)length, (uint8 *)bytes };
1272
1273 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
1274 SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER));
1275 certificate = certificatePtr->handle();
1276
427c49bc 1277 __secapiresult=errSecSuccess;
b1ab9ed8
A
1278 }
1279 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1280 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
1281 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1282 catch (...) { __secapiresult=errSecInternalComponent; }
b1ab9ed8
A
1283 return certificate;
1284}
5c19dc3a 1285#endif
b1ab9ed8 1286
5c19dc3a 1287#if !SECTRUST_OSX
b1ab9ed8
A
1288/* new in 10.8 */
1289CFIndex SecCertificateGetLength(SecCertificateRef certificate)
1290{
1291 CFIndex length = 0;
1292 OSStatus __secapiresult;
1293 try {
1294 CssmData output = Certificate::required(certificate)->data();
1295 length = (CFIndex)output.length();
427c49bc 1296 __secapiresult=errSecSuccess;
b1ab9ed8
A
1297 }
1298 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1299 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
1300 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1301 catch (...) { __secapiresult=errSecInternalComponent; }
b1ab9ed8
A
1302 return length;
1303}
5c19dc3a 1304#endif
b1ab9ed8 1305
5c19dc3a 1306#if !SECTRUST_OSX
b1ab9ed8
A
1307/* new in 10.8 */
1308const UInt8 *SecCertificateGetBytePtr(SecCertificateRef certificate)
1309{
1310 const UInt8 *bytes = NULL;
1311 OSStatus __secapiresult;
1312 try {
1313 CssmData output = Certificate::required(certificate)->data();
1314 bytes = (const UInt8 *)output.data();
427c49bc 1315 __secapiresult=errSecSuccess;
b1ab9ed8
A
1316 }
1317 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1318 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
427c49bc
A
1319 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1320 catch (...) { __secapiresult=errSecInternalComponent; }
b1ab9ed8
A
1321 return bytes;
1322}
5c19dc3a 1323#endif
b1ab9ed8 1324
5c19dc3a
A
1325#if !SECTRUST_OSX
1326/* not exported */
d8f41ccd 1327static CFArrayRef CopyEscrowCertificates(SecCertificateEscrowRootType escrowRootType, CFErrorRef *error)
427c49bc
A
1328{
1329 // Return array of CFDataRef certificates.
1330 CFArrayRef result = NULL;
1331 int iCnt;
1332 int numRoots = 0;
1333
1334 // Get the hard coded set of production roots
1335 // static struct RootRecord* kProductionEscrowRoots[] = {&kOldEscrowRootRecord, &kProductionEscrowRootRecord};
1336
d8f41ccd
A
1337 struct RootRecord** pEscrowRoots = NULL;
1338 switch (escrowRootType) {
1339 case kSecCertificateBaselineEscrowRoot:
1340 numRoots = kNumberOfBaseLineEscrowRoots;
1341 pEscrowRoots = kBaseLineEscrowRoots;
1342 break;
1343 case kSecCertificateProductionEscrowRoot:
1344 numRoots = kNumberOfBaseLineEscrowRoots; //%%% currently, production == baseline on OS X
1345 pEscrowRoots = kBaseLineEscrowRoots;
1346 break;
1347 case kSecCertificateBaselinePCSEscrowRoot:
1348 numRoots = kNumberOfBaseLinePCSEscrowRoots;
1349 pEscrowRoots = kBaseLinePCSEscrowRoots;
1350 break;
1351 case kSecCertificateProductionPCSEscrowRoot:
1352 numRoots = kNumberOfBaseLinePCSEscrowRoots; //%%% currently, production == baseline on OS X
1353 pEscrowRoots = kBaseLinePCSEscrowRoots;
1354 break;
1355 default:
1356 break;
1357 }
1358
427c49bc
A
1359 CFDataRef productionCerts[numRoots];
1360 struct RootRecord* pRootRecord = NULL;
1361
d8f41ccd 1362 for (iCnt = 0; pEscrowRoots != NULL && iCnt < numRoots; iCnt++)
427c49bc 1363 {
d8f41ccd 1364 pRootRecord = pEscrowRoots[iCnt];
427c49bc
A
1365 if (NULL != pRootRecord && pRootRecord->_length > 0 && NULL != pRootRecord->_bytes)
1366 {
1367 productionCerts[iCnt] = CFDataCreate(kCFAllocatorDefault, pRootRecord->_bytes, pRootRecord->_length);
1368 }
1369 }
1370 result = CFArrayCreate(kCFAllocatorDefault, (const void **)productionCerts, numRoots, &kCFTypeArrayCallBacks);
1371 for (iCnt = 0; iCnt < numRoots; iCnt++)
1372 {
1373 if (NULL != productionCerts[iCnt])
1374 {
1375 CFRelease(productionCerts[iCnt]);
1376 }
1377 }
1378
1379 return result;
1380}
5c19dc3a 1381#endif
427c49bc 1382
5c19dc3a 1383#if !SECTRUST_OSX
427c49bc
A
1384/* new in 10.9 */
1385CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType)
1386{
1387 CFArrayRef result = NULL;
1388 int iCnt;
1389 int numRoots = 0;
1390 CFDataRef certData = NULL;
1391
1392 // The request is for the base line certificates.
1393 // Use the hard coded data to generate the return array
1394 if (kSecCertificateBaselineEscrowRoot == escrowRootType)
1395 {
1396 // Get the hard coded set of roots
1397 numRoots = kNumberOfBaseLineEscrowRoots;
1398 SecCertificateRef baseLineCerts[numRoots];
1399 struct RootRecord* pRootRecord = NULL;
1400
1401 for (iCnt = 0; iCnt < numRoots; iCnt++)
1402 {
1403 pRootRecord = kBaseLineEscrowRoots[iCnt];
1404 if (NULL != pRootRecord && pRootRecord->_length > 0 && NULL != pRootRecord->_bytes)
1405 {
1406 certData = CFDataCreate(kCFAllocatorDefault, pRootRecord->_bytes, pRootRecord->_length);
1407 if (NULL != certData)
1408 {
1409 baseLineCerts[iCnt] = SecCertificateCreateWithData(kCFAllocatorDefault, certData);
1410 CFRelease(certData);
1411 }
1412 }
1413 }
1414 result = CFArrayCreate(kCFAllocatorDefault, (const void **)baseLineCerts, numRoots, &kCFTypeArrayCallBacks);
1415 for (iCnt = 0; iCnt < numRoots; iCnt++)
1416 {
1417 if (NULL != baseLineCerts[iCnt])
1418 {
1419 CFRelease(baseLineCerts[iCnt]);
1420 }
1421 }
1422 }
1423 // The request is for the current certificates.
d8f41ccd 1424 else
427c49bc
A
1425 {
1426 CFErrorRef error = NULL;
d8f41ccd 1427 CFArrayRef cert_datas = CopyEscrowCertificates(escrowRootType, &error);
427c49bc
A
1428 if (NULL != error || NULL == cert_datas || 0 == (numRoots = (int)CFArrayGetCount(cert_datas)))
1429 {
1430 if (NULL != error)
1431 {
1432 CFRelease(error);
1433 }
1434
1435 if (NULL != cert_datas)
1436 {
1437 CFRelease(cert_datas);
1438 }
1439 return result;
1440 }
1441
1442 SecCertificateRef assetCerts[numRoots];
1443 for (iCnt = 0; iCnt < numRoots; iCnt++)
1444 {
1445 certData = (CFDataRef)CFArrayGetValueAtIndex(cert_datas, iCnt);
1446 if (NULL != certData)
1447 {
1448 SecCertificateRef aCertRef = SecCertificateCreateWithData(kCFAllocatorDefault, certData);
1449 assetCerts[iCnt] = aCertRef;
1450 }
1451 else
1452 {
1453 assetCerts[iCnt] = NULL;
1454 }
1455 }
1456
1457 if (numRoots > 0)
1458 {
1459 result = CFArrayCreate(kCFAllocatorDefault, (const void **)assetCerts, numRoots, &kCFTypeArrayCallBacks);
1460 for (iCnt = 0; iCnt < numRoots; iCnt++)
1461 {
1462 if (NULL != assetCerts[iCnt])
1463 {
1464 CFRelease(assetCerts[iCnt]);
1465 }
1466 }
1467 }
1468 CFRelease(cert_datas);
1469 }
5c19dc3a 1470
427c49bc
A
1471 return result;
1472}
5c19dc3a
A
1473#endif
1474
1475#if !SECTRUST_OSX
1476/* new in 10.11 */
1477SecSignatureHashAlgorithm SecCertificateGetSignatureHashAlgorithm(SecCertificateRef certificate)
1478{
1479 SecSignatureHashAlgorithm result = kSecSignatureHashAlgorithmUnknown;
1480 CSSM_X509_ALGORITHM_IDENTIFIER_PTR algId = NULL;
1481 CSSM_DATA_PTR fieldValue = NULL;
1482 CSSM_OID_PTR algOID = NULL;
1483 const CSSM_OID *sigAlgOID = &CSSMOID_X509V1SignatureAlgorithm;
1484 OSStatus status;
1485
1486 status = SecCertificateCopyFirstFieldValue(certificate, sigAlgOID, &fieldValue);
1487 if (status || !fieldValue) {
1488 return result;
1489 }
1490 algId = (CSSM_X509_ALGORITHM_IDENTIFIER_PTR)fieldValue->Data;
1491 algOID = (algId) ? &algId->algorithm : NULL;
1492
1493 while (algOID) {
1494 if (!algOID->Data || !algOID->Length) {
1495 break;
1496 }
1497 /* classify the signature algorithm OID into one of our known types */
1498 if (cuCompareCssmData(algOID, &CSSMOID_ECDSA_WithSHA512) ||
1499 cuCompareCssmData(algOID, &CSSMOID_SHA512WithRSA) ||
1500 cuCompareCssmData(algOID, &CSSMOID_SHA512)) {
1501 result = kSecSignatureHashAlgorithmSHA512;
1502 break;
1503 }
1504 if (cuCompareCssmData(algOID, &CSSMOID_ECDSA_WithSHA384) ||
1505 cuCompareCssmData(algOID, &CSSMOID_SHA384WithRSA) ||
1506 cuCompareCssmData(algOID, &CSSMOID_SHA384)) {
1507 result = kSecSignatureHashAlgorithmSHA384;
1508 break;
1509 }
1510 if (cuCompareCssmData(algOID, &CSSMOID_ECDSA_WithSHA256) ||
1511 cuCompareCssmData(algOID, &CSSMOID_SHA256WithRSA) ||
1512 cuCompareCssmData(algOID, &CSSMOID_SHA256)) {
1513 result = kSecSignatureHashAlgorithmSHA256;
1514 break;
1515 }
1516 if (cuCompareCssmData(algOID, &CSSMOID_ECDSA_WithSHA224) ||
1517 cuCompareCssmData(algOID, &CSSMOID_SHA224WithRSA) ||
1518 cuCompareCssmData(algOID, &CSSMOID_SHA224)) {
1519 result = kSecSignatureHashAlgorithmSHA224;
1520 break;
1521 }
1522 if (cuCompareCssmData(algOID, &CSSMOID_ECDSA_WithSHA1) ||
1523 cuCompareCssmData(algOID, &CSSMOID_SHA1WithRSA) ||
1524 cuCompareCssmData(algOID, &CSSMOID_SHA1WithDSA) ||
1525 cuCompareCssmData(algOID, &CSSMOID_SHA1WithDSA_CMS) ||
1526 cuCompareCssmData(algOID, &CSSMOID_SHA1WithDSA_JDK) ||
1527 cuCompareCssmData(algOID, &CSSMOID_SHA1WithRSA_OIW) ||
1528 cuCompareCssmData(algOID, &CSSMOID_APPLE_FEE_SHA1) ||
1529 cuCompareCssmData(algOID, &CSSMOID_SHA1)) {
1530 result = kSecSignatureHashAlgorithmSHA1;
1531 break;
1532 }
1533 if (cuCompareCssmData(algOID, &CSSMOID_MD5WithRSA) ||
1534 cuCompareCssmData(algOID, &CSSMOID_APPLE_FEE_MD5) ||
1535 cuCompareCssmData(algOID, &CSSMOID_MD5)) {
1536 result = kSecSignatureHashAlgorithmMD5;
1537 break;
1538 }
1539 if (cuCompareCssmData(algOID, &CSSMOID_MD4WithRSA) ||
1540 cuCompareCssmData(algOID, &CSSMOID_MD4)) {
1541 result = kSecSignatureHashAlgorithmMD4;
1542 break;
1543 }
1544 if (cuCompareCssmData(algOID, &CSSMOID_MD2WithRSA) ||
1545 cuCompareCssmData(algOID, &CSSMOID_MD2)) {
1546 result = kSecSignatureHashAlgorithmMD2;
1547 break;
1548 }
1549 break;
1550 }
1551
1552 (void)SecCertificateReleaseFirstFieldValue(certificate, sigAlgOID, fieldValue);
1553
1554 return result;
1555}
1556#endif
427c49bc 1557