]> git.saurik.com Git - apple/security.git/blob - libsecurity_keychain/lib/SecCertificate.cpp
01e0e9820900071013583415bb81fdeaf7c5b0e7
[apple/security.git] / libsecurity_keychain / lib / SecCertificate.cpp
1 /*
2 * Copyright (c) 2002-2013 Apple Inc. All Rights Reserved.
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>
43 #include <sys/param.h>
44 #include "CertificateValues.h"
45 #include "SecCertificateP.h"
46 //
47 //#include "AppleBaselineEscrowCertificates.h"
48 //
49 //######################################################################
50 //%%% start workaround: rdar://14292830
51 //######################################################################
52
53 #ifndef sec_AppleBaselineEscrowCertificates_h
54 #define sec_AppleBaselineEscrowCertificates_h
55
56 struct RootRecord
57 {
58 size_t _length;
59 UInt8* _bytes;
60 };
61
62 /* ==========================================================================
63 Production Escrow Certificates
64 ========================================================================== */
65
66 static const UInt8 kProductionEscrowRootGM[] = {
67 0x30,0x82,0x03,0xD0,0x30,0x82,0x02,0xB8,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x64,
68 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,
69 0x79,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31,0x30,0x30,0x31,
70 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,
71 0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,
72 0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70,0x6C,
73 0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,
74 0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,
75 0x04,0x03,0x13,0x16,0x45,0x73,0x63,0x72,0x6F,0x77,0x20,0x53,0x65,0x72,0x76,0x69,
76 0x63,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x33,
77 0x30,0x38,0x30,0x32,0x32,0x33,0x32,0x34,0x34,0x34,0x5A,0x17,0x0D,0x32,0x33,0x30,
78 0x38,0x30,0x32,0x32,0x33,0x32,0x34,0x34,0x34,0x5A,0x30,0x79,0x31,0x0C,0x30,0x0A,
79 0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31,0x30,0x30,0x31,0x0B,0x30,0x09,0x06,0x03,
80 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,
81 0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,
82 0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,
83 0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,
84 0x72,0x69,0x74,0x79,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x45,
85 0x73,0x63,0x72,0x6F,0x77,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x20,0x52,0x6F,
86 0x6F,0x74,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,
87 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,
88 0x0A,0x02,0x82,0x01,0x01,0x00,0xD0,0xA3,0xF4,0x56,0x7D,0x3F,0x46,0x31,0xD2,0x56,
89 0xA0,0xDF,0x42,0xA0,0x29,0x83,0x1E,0xB9,0x82,0xB5,0xA5,0xFF,0x3E,0xDE,0xB5,0x0F,
90 0x4A,0x8A,0x28,0x60,0xCF,0x75,0xB4,0xA0,0x70,0x7C,0xF5,0xE2,0x94,0xF3,0x22,0x02,
91 0xC8,0x81,0xCE,0x34,0xC7,0x66,0x6A,0x18,0xAA,0xB4,0xFD,0x6D,0xB0,0x0B,0xDD,0x4A,
92 0xDD,0xCF,0xE0,0x08,0x1B,0x1C,0xA6,0xDB,0xBA,0xB2,0xC1,0xA4,0x10,0x5F,0x35,0x4F,
93 0x8B,0x8B,0x7A,0xA3,0xDB,0x3C,0xF6,0x54,0x95,0x42,0xAD,0x2A,0x3B,0xFE,0x06,0x8C,
94 0xE1,0x92,0xF1,0x60,0x97,0x58,0x1B,0xD9,0x8F,0xBE,0xFB,0x46,0x4C,0x29,0x5C,0x1C,
95 0xF0,0x20,0xB6,0x2B,0xA5,0x12,0x09,0x9B,0x28,0x41,0x34,0x97,0x9F,0xF3,0x88,0x4B,
96 0x69,0x72,0xEA,0x3A,0x27,0xB0,0x50,0x1D,0x88,0x29,0x0D,0xBB,0xED,0x04,0xA2,0x11,
97 0xCF,0x0C,0x5B,0x65,0x61,0x35,0xBD,0xF2,0x0D,0xFC,0xE2,0xB9,0x20,0xD3,0xB7,0x03,
98 0x70,0x39,0xD5,0xE0,0x86,0x7C,0x04,0xCC,0xC9,0xA1,0x85,0xB4,0x9B,0xBC,0x88,0x4E,
99 0xD7,0xAD,0x5C,0xFF,0x2C,0x0D,0x80,0x8E,0x51,0x39,0x20,0x8B,0xAF,0x1E,0x46,0x95,
100 0xFA,0x0D,0x1B,0xD2,0xBF,0x80,0xE0,0x9F,0x6D,0x4A,0xF5,0x31,0x67,0x18,0x11,0xA5,
101 0x63,0x27,0x08,0xEE,0xD9,0x07,0x29,0xD0,0xD4,0x36,0x91,0x5B,0xFB,0x4A,0x0B,0x07,
102 0xD1,0x0D,0x79,0x16,0x6E,0x16,0x02,0x23,0x80,0xC6,0x15,0x07,0x6D,0xA0,0x06,0xB6,
103 0x45,0x90,0xB0,0xAE,0xA4,0xAD,0x0E,0x75,0x04,0x2B,0x2B,0x78,0xF1,0x57,0x84,0x23,
104 0x87,0x24,0xEC,0x58,0xC4,0xF1,0x02,0x03,0x01,0x00,0x01,0xA3,0x63,0x30,0x61,0x30,
105 0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,
106 0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,
107 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xFD,0x78,0x96,0x53,0x80,
108 0xD6,0xF6,0xDC,0xA6,0xC3,0x59,0x06,0x38,0xED,0x79,0x3E,0x8F,0x50,0x1B,0x50,0x30,
109 0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xFD,0x78,0x96,0x53,
110 0x80,0xD6,0xF6,0xDC,0xA6,0xC3,0x59,0x06,0x38,0xED,0x79,0x3E,0x8F,0x50,0x1B,0x50,
111 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,
112 0x82,0x01,0x01,0x00,0x71,0x15,0xCA,0x87,0xD0,0x2D,0xB5,0x18,0xD5,0x35,0x7A,0xCD,
113 0xDF,0x62,0x28,0xF0,0x0B,0x63,0x4D,0x4E,0x02,0xBA,0x3D,0xB8,0xB4,0x37,0xEA,0xB0,
114 0x93,0x93,0xAB,0x1C,0xFD,0x9F,0xE8,0x72,0xBF,0xF3,0xDB,0xE6,0xAD,0x16,0xFE,0x71,
115 0x61,0xA8,0x5A,0xD0,0x58,0x0F,0x65,0x7A,0x57,0x7A,0xE0,0x34,0x80,0x8E,0xBB,0x41,
116 0x01,0xE7,0xB0,0x3B,0xF7,0x2B,0x3A,0x6D,0x44,0x2A,0x3A,0x04,0x52,0xFA,0x2B,0x7B,
117 0x3B,0x21,0xDD,0x0C,0x70,0x3D,0xFB,0x45,0xC6,0x79,0x68,0x62,0xE2,0x89,0xB8,0x25,
118 0xEE,0x63,0x76,0x02,0xB2,0x22,0xE9,0x53,0x85,0x68,0x3E,0x75,0xB6,0x0B,0x65,0xE9,
119 0x1C,0xBA,0x84,0x93,0xB0,0x8A,0xEF,0xB5,0x1A,0x12,0xE4,0x8F,0xAE,0xD5,0x5C,0xA1,
120 0x05,0x4A,0x01,0xBC,0x6F,0xF9,0x58,0x5E,0xF7,0x04,0x61,0xEE,0xF5,0xC6,0xA0,0x1B,
121 0x44,0x2E,0x5A,0x3A,0x59,0xA1,0xB3,0xB0,0xF4,0xB6,0xCB,0xE0,0x6C,0x2B,0x59,0x8A,
122 0xFB,0x6A,0xE0,0xA2,0x57,0x09,0x79,0xC1,0xDD,0xFB,0x84,0x86,0xEB,0x66,0x29,0x73,
123 0xAE,0xBF,0x58,0xAE,0x47,0x4D,0x48,0x37,0xD6,0xB1,0x8C,0x5F,0x26,0x5F,0xB5,0x26,
124 0x07,0x0B,0x85,0xB7,0x36,0x37,0x14,0xCF,0x5E,0x55,0xA5,0x3C,0xF3,0x1E,0x79,0x50,
125 0xBB,0x85,0x3B,0xB2,0x94,0x68,0xB0,0x25,0x4F,0x75,0xEC,0xF0,0xF9,0xC0,0x5A,0x2D,
126 0xE5,0xED,0x67,0xCD,0x88,0x55,0xA0,0x42,0xDE,0x78,0xBC,0xFE,0x30,0xB1,0x62,0x2D,
127 0xE1,0xFD,0xEC,0x75,0x03,0xA6,0x1F,0x7C,0xC4,0x3A,0x4A,0x59,0xFE,0x77,0xC3,0x99,
128 0x96,0x87,0x44,0xC3,
129 };
130
131 static struct RootRecord kProductionEscrowRootRecord = {sizeof(kProductionEscrowRootGM), (UInt8*)kProductionEscrowRootGM};
132 static struct RootRecord* kProductionEscrowRoots[] = {&kProductionEscrowRootRecord};
133 static const int kNumberOfProductionEscrowRoots = (int)(sizeof(kProductionEscrowRoots)/sizeof(kProductionEscrowRoots[0]));
134
135 static struct RootRecord kBaseLineEscrowRootRecord = {sizeof(kProductionEscrowRootGM), (UInt8*)kProductionEscrowRootGM};
136 static struct RootRecord* kBaseLineEscrowRoots[] = {&kBaseLineEscrowRootRecord};
137 static const int kNumberOfBaseLineEscrowRoots = (int)(sizeof(kBaseLineEscrowRoots)/sizeof(kBaseLineEscrowRoots[0]));
138
139
140 #endif
141 //######################################################################
142 //%%% end workaround: rdar://14292830
143 ////######################################################################
144
145
146 extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage);
147
148 #define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v));
149
150 SEC_CONST_DECL (kSecCertificateProductionEscrowKey, "ProductionEscrowKey");
151 SEC_CONST_DECL (kSecCertificateEscrowFileName, "AppleESCertificates");
152
153
154 using namespace CssmClient;
155
156 CFTypeID
157 SecCertificateGetTypeID(void)
158 {
159 BEGIN_SECAPI
160
161 return gTypes().Certificate.typeID;
162
163 END_SECAPI1(_kCFRuntimeNotATypeID)
164 }
165
166
167 OSStatus
168 SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding, SecCertificateRef *certificate)
169 {
170 BEGIN_SECAPI
171
172 SecPointer<Certificate> certificatePtr(new Certificate(Required(data), type, encoding));
173 Required(certificate) = certificatePtr->handle();
174
175 END_SECAPI
176 }
177
178 /* new in 10.6 */
179 SecCertificateRef
180 SecCertificateCreateWithData(CFAllocatorRef allocator, CFDataRef data)
181 {
182 SecCertificateRef certificate = NULL;
183 OSStatus __secapiresult;
184 try {
185 CSSM_DATA cssmCertData;
186 cssmCertData.Length = (data) ? (CSSM_SIZE)CFDataGetLength(data) : 0;
187 cssmCertData.Data = (data) ? (uint8 *)CFDataGetBytePtr(data) : NULL;
188
189 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
190 SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER));
191 certificate = certificatePtr->handle();
192
193 __secapiresult=errSecSuccess;
194 }
195 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
196 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
197 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
198 catch (...) { __secapiresult=errSecInternalComponent; }
199 return certificate;
200 }
201
202 OSStatus
203 SecCertificateAddToKeychain(SecCertificateRef certificate, SecKeychainRef keychain)
204 {
205 BEGIN_SECAPI
206
207 Item item(Certificate::required(certificate));
208 Keychain::optional(keychain)->add(item);
209
210 END_SECAPI
211 }
212
213 OSStatus
214 SecCertificateGetData(SecCertificateRef certificate, CSSM_DATA_PTR data)
215 {
216 BEGIN_SECAPI
217
218 Required(data) = Certificate::required(certificate)->data();
219
220 END_SECAPI
221 }
222
223 /* new in 10.6 */
224 CFDataRef
225 SecCertificateCopyData(SecCertificateRef certificate)
226 {
227 CFDataRef data = NULL;
228 OSStatus __secapiresult = errSecSuccess;
229 try {
230 CssmData output = Certificate::required(certificate)->data();
231 CFIndex length = (CFIndex)output.length();
232 const UInt8 *bytes = (const UInt8 *)output.data();
233 if (length && bytes) {
234 data = CFDataCreate(NULL, bytes, length);
235 }
236 }
237 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
238 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
239 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
240 catch (...) { __secapiresult=errSecInternalComponent; }
241 return data;
242 }
243
244 CFDataRef
245 SecCertificateGetSHA1Digest(SecCertificateRef certificate)
246 {
247 CFDataRef data = NULL;
248 OSStatus __secapiresult = errSecSuccess;
249 try {
250 data = Certificate::required(certificate)->sha1Hash();
251 }
252 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
253 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
254 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
255 catch (...) { __secapiresult=errSecInternalComponent; }
256 return data;
257 }
258
259
260 OSStatus
261 SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificateType)
262 {
263 BEGIN_SECAPI
264
265 Required(certificateType) = Certificate::required(certificate)->type();
266
267 END_SECAPI
268 }
269
270
271 OSStatus
272 SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **subject)
273 {
274 BEGIN_SECAPI
275
276 Required(subject) = Certificate::required(certificate)->subjectName();
277
278 END_SECAPI
279 }
280
281
282 OSStatus
283 SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **issuer)
284 {
285 BEGIN_SECAPI
286
287 Required(issuer) = Certificate::required(certificate)->issuerName();
288
289 END_SECAPI
290 }
291
292
293 OSStatus
294 SecCertificateGetCLHandle(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle)
295 {
296 BEGIN_SECAPI
297
298 Required(clHandle) = Certificate::required(certificate)->clHandle();
299
300 END_SECAPI
301 }
302
303 /*
304 * Private API to infer a display name for a SecCertificateRef which
305 * may or may not be in a keychain.
306 */
307 OSStatus
308 SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label)
309 {
310 BEGIN_SECAPI
311
312 Certificate::required(certificate)->inferLabel(false,
313 &Required(label));
314
315 END_SECAPI
316 }
317
318 OSStatus
319 SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key)
320 {
321 BEGIN_SECAPI
322
323 Required(key) = Certificate::required(certificate)->publicKey()->handle();
324
325 END_SECAPI
326 }
327
328 OSStatus
329 SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGORITHM_IDENTIFIER **algid)
330 {
331 BEGIN_SECAPI
332
333 Required(algid) = Certificate::required(certificate)->algorithmID();
334
335 END_SECAPI
336 }
337
338 OSStatus
339 SecCertificateCopyCommonName(SecCertificateRef certificate, CFStringRef *commonName)
340 {
341 BEGIN_SECAPI
342
343 Required(commonName) = Certificate::required(certificate)->commonName();
344
345 END_SECAPI
346 }
347
348 /* new in 10.6 */
349 CFStringRef
350 SecCertificateCopySubjectSummary(SecCertificateRef certificate)
351 {
352 CFStringRef summary = NULL;
353 OSStatus __secapiresult;
354 try {
355 Certificate::required(certificate)->inferLabel(false, &summary);
356
357 __secapiresult=errSecSuccess;
358 }
359 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
360 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
361 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
362 catch (...) { __secapiresult=errSecInternalComponent; }
363 return summary;
364 }
365
366 OSStatus
367 SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, CFStringRef *result)
368 {
369 BEGIN_SECAPI
370
371 Required(result) = Certificate::required(certificate)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct, component);
372
373 END_SECAPI
374 }
375
376 OSStatus
377 SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName)
378 {
379 // deprecated SPI signature; replaced by SecCertificateCopyCommonName
380 return SecCertificateCopyCommonName(certificate, commonName);
381 }
382
383 OSStatus
384 SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress)
385 {
386 BEGIN_SECAPI
387
388 Required(emailAddress) = Certificate::required(certificate)->copyFirstEmailAddress();
389
390 END_SECAPI
391 }
392
393 OSStatus
394 SecCertificateCopyEmailAddresses(SecCertificateRef certificate, CFArrayRef *emailAddresses)
395 {
396 BEGIN_SECAPI
397
398 Required(emailAddresses) = Certificate::required(certificate)->copyEmailAddresses();
399
400 END_SECAPI
401 }
402
403 OSStatus
404 SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues)
405 {
406 /* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field. Caller must call releaseFieldValues to free the storage allocated by this call. */
407 BEGIN_SECAPI
408
409 Required(fieldValues) = Certificate::required(certificate)->copyFieldValues(Required(field));
410
411 END_SECAPI
412 }
413
414 OSStatus
415 SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValues)
416 {
417 BEGIN_SECAPI
418
419 Certificate::required(certificate)->releaseFieldValues(Required(field), fieldValues);
420
421 END_SECAPI
422 }
423
424 OSStatus
425 SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue)
426 {
427 BEGIN_SECAPI
428
429 Required(fieldValue) = Certificate::required(certificate)->copyFirstFieldValue(Required(field));
430
431 END_SECAPI
432 }
433
434 OSStatus
435 SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR fieldValue)
436 {
437 BEGIN_SECAPI
438
439 Certificate::required(certificate)->releaseFieldValue(Required(field), fieldValue);
440
441 END_SECAPI
442 }
443
444 OSStatus
445 SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray,const CSSM_DATA *issuer,
446 const CSSM_DATA *serialNumber, SecCertificateRef *certificate)
447 {
448 BEGIN_SECAPI
449
450 StorageManager::KeychainList keychains;
451 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
452 Required(certificate) = Certificate::findByIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber))->handle();
453
454 END_SECAPI
455 }
456
457 OSStatus
458 SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
459 SecCertificateRef *certificate)
460 {
461 BEGIN_SECAPI
462
463 StorageManager::KeychainList keychains;
464 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
465 Required(certificate) = Certificate::findBySubjectKeyID(keychains, CssmData::required(subjectKeyID))->handle();
466
467 END_SECAPI
468 }
469
470 OSStatus
471 SecCertificateFindByEmail(CFTypeRef keychainOrArray, const char *emailAddress, SecCertificateRef *certificate)
472 {
473 BEGIN_SECAPI
474
475 StorageManager::KeychainList keychains;
476 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
477 Required(certificate) = Certificate::findByEmail(keychains, emailAddress)->handle();
478
479 END_SECAPI
480 }
481
482 OSStatus
483 SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer,
484 const CSSM_DATA *serialNumber, SecKeychainSearchRef *searchRef)
485 {
486 BEGIN_SECAPI
487
488 Required(searchRef);
489
490 StorageManager::KeychainList keychains;
491 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
492 KCCursor cursor(Certificate::cursorForIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber)));
493 *searchRef = cursor->handle();
494
495 END_SECAPI
496 }
497
498 OSStatus
499 SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray, CFDataRef issuer,
500 CFDataRef serialNumber, SecKeychainSearchRef *searchRef)
501 {
502 BEGIN_SECAPI
503
504 Required(searchRef);
505
506 StorageManager::KeychainList keychains;
507 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
508 Required(issuer);
509 Required(serialNumber);
510 KCCursor cursor(Certificate::cursorForIssuerAndSN_CF(keychains, issuer, serialNumber));
511 *searchRef = cursor->handle();
512
513 END_SECAPI
514 }
515
516 OSStatus
517 SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
518 SecKeychainSearchRef *searchRef)
519 {
520 BEGIN_SECAPI
521
522 Required(searchRef);
523
524 StorageManager::KeychainList keychains;
525 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
526 KCCursor cursor(Certificate::cursorForSubjectKeyID(keychains, CssmData::required(subjectKeyID)));
527 *searchRef = cursor->handle();
528
529 END_SECAPI
530 }
531
532 OSStatus
533 SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray, const char *emailAddress,
534 SecKeychainSearchRef *searchRef)
535 {
536 BEGIN_SECAPI
537
538 Required(searchRef);
539
540 StorageManager::KeychainList keychains;
541 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
542 KCCursor cursor(Certificate::cursorForEmail(keychains, emailAddress));
543 *searchRef = cursor->handle();
544
545 END_SECAPI
546 }
547
548 /* NOT EXPORTED YET; copied from SecurityInterface but could be useful in the future.
549 CSSM_CSP_HANDLE
550 SecGetAppleCSPHandle()
551 {
552 BEGIN_SECAPI
553 return CSP(gGuidAppleCSP)->handle();
554 END_SECAPI1(NULL);
555 }
556
557 CSSM_CL_HANDLE
558 SecGetAppleCLHandle()
559 {
560 BEGIN_SECAPI
561 return CL(gGuidAppleX509CL)->handle();
562 END_SECAPI1(NULL);
563 }
564 */
565
566 CSSM_RETURN
567 SecDigestGetData (CSSM_ALGORITHMS alg, CSSM_DATA* digest, const CSSM_DATA* data)
568 {
569 BEGIN_SECAPI
570 // sanity checking
571 if (!digest || !digest->Data || !digest->Length || !data || !data->Data || !data->Length)
572 return errSecParam;
573
574 CSP csp(gGuidAppleCSP);
575 Digest context(csp, alg);
576 CssmData input(data->Data, data->Length);
577 CssmData output(digest->Data, digest->Length);
578
579 context.digest(input, output);
580 digest->Length = output.length();
581
582 return CSSM_OK;
583 END_SECAPI1(1);
584 }
585
586 /* determine whether a cert is self-signed */
587 OSStatus SecCertificateIsSelfSigned(
588 SecCertificateRef certificate,
589 Boolean *isSelfSigned) /* RETURNED */
590 {
591 BEGIN_SECAPI
592
593 *isSelfSigned = Certificate::required(certificate)->isSelfSigned();
594
595 END_SECAPI
596 }
597
598 OSStatus
599 SecCertificateCopyPreference(
600 CFStringRef name,
601 CSSM_KEYUSE keyUsage,
602 SecCertificateRef *certificate)
603 {
604 BEGIN_SECAPI
605
606 Required(name);
607 Required(certificate);
608 StorageManager::KeychainList keychains;
609 globals().storageManager.getSearchList(keychains);
610 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
611
612 char idUTF8[MAXPATHLEN];
613 if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
614 idUTF8[0] = (char)'\0';
615 CssmData service(const_cast<char *>(idUTF8), strlen(idUTF8));
616 FourCharCode itemType = 'cprf';
617 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
618 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
619 if (keyUsage)
620 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
621
622 Item prefItem;
623 if (!cursor->next(prefItem))
624 MacOSError::throwMe(errSecItemNotFound);
625
626 // get persistent certificate reference
627 SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } };
628 SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
629 prefItem->getContent(NULL, &itemAttrList, NULL, NULL);
630
631 // find certificate, given persistent reference data
632 CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull);
633 SecKeychainItemRef certItemRef = nil;
634 OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); //%%% need to make this a method of ItemImpl
635 prefItem->freeContent(&itemAttrList, NULL);
636 if (pItemRef)
637 CFRelease(pItemRef);
638 if (status)
639 return status;
640
641 *certificate = (SecCertificateRef)certItemRef;
642
643 END_SECAPI
644 }
645
646 SecCertificateRef
647 SecCertificateCopyPreferred(
648 CFStringRef name,
649 CFArrayRef keyUsage)
650 {
651 // This function will look for a matching preference in the following order:
652 // - matches the name and the supplied key use
653 // - matches the name and the special 'ANY' key use
654 // - matches the name with no key usage constraint
655
656 SecCertificateRef certRef = NULL;
657 CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
658 OSStatus status = SecCertificateCopyPreference(name, keyUse, &certRef);
659 if (status != errSecSuccess && keyUse != CSSM_KEYUSE_ANY)
660 status = SecCertificateCopyPreference(name, CSSM_KEYUSE_ANY, &certRef);
661 if (status != errSecSuccess && keyUse != 0)
662 status = SecCertificateCopyPreference(name, 0, &certRef);
663
664 return certRef;
665 }
666
667 static OSStatus
668 SecCertificateFindPreferenceItemWithNameAndKeyUsage(
669 CFTypeRef keychainOrArray,
670 CFStringRef name,
671 int32_t keyUsage,
672 SecKeychainItemRef *itemRef)
673 {
674 BEGIN_SECAPI
675
676 StorageManager::KeychainList keychains;
677 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
678 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
679
680 char idUTF8[MAXPATHLEN];
681 idUTF8[0] = (char)'\0';
682 if (name)
683 {
684 if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
685 idUTF8[0] = (char)'\0';
686 }
687 size_t idUTF8Len = strlen(idUTF8);
688 if (!idUTF8Len)
689 MacOSError::throwMe(errSecParam);
690
691 CssmData service(const_cast<char *>(idUTF8), idUTF8Len);
692 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
693 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'cprf');
694 if (keyUsage)
695 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
696
697 Item item;
698 if (!cursor->next(item))
699 MacOSError::throwMe(errSecItemNotFound);
700
701 if (itemRef)
702 *itemRef=item->handle();
703
704 END_SECAPI
705 }
706
707 static
708 OSStatus SecCertificateDeletePreferenceItemWithNameAndKeyUsage(
709 CFTypeRef keychainOrArray,
710 CFStringRef name,
711 int32_t keyUsage)
712 {
713 // when a specific key usage is passed, we'll only match & delete that pref;
714 // when a key usage of 0 is passed, all matching prefs should be deleted.
715 // maxUsages represents the most matches there could theoretically be, so
716 // cut things off at that point if we're still finding items (if they can't
717 // be deleted for some reason, we'd never break out of the loop.)
718
719 OSStatus status;
720 SecKeychainItemRef item = NULL;
721 int count = 0, maxUsages = 12;
722 while (++count <= maxUsages &&
723 (status = SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray, name, keyUsage, &item)) == errSecSuccess) {
724 status = SecKeychainItemDelete(item);
725 CFRelease(item);
726 item = NULL;
727 }
728
729 // it's not an error if the item isn't found
730 return (status == errSecItemNotFound) ? errSecSuccess : status;
731 }
732
733 OSStatus SecCertificateSetPreference(
734 SecCertificateRef certificate,
735 CFStringRef name,
736 CSSM_KEYUSE keyUsage,
737 CFDateRef date)
738 {
739 if (!name) {
740 return errSecParam;
741 }
742 if (!certificate) {
743 // treat NULL certificate as a request to clear the preference
744 // (note: if keyUsage is 0, this clears all key usage prefs for name)
745 return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL, name, keyUsage);
746 }
747
748 BEGIN_SECAPI
749
750 // determine the account attribute
751 //
752 // This attribute must be synthesized from certificate label + pref item type + key usage,
753 // as only the account and service attributes can make a generic keychain item unique.
754 // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that
755 // we can save a certificate preference if an identity preference already exists for the
756 // given service name, and vice-versa.
757 // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string.
758 //
759 CFStringRef labelStr = nil;
760 Certificate::required(certificate)->inferLabel(false, &labelStr);
761 if (!labelStr) {
762 MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed"
763 }
764 CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1;
765 const char *templateStr = "%s [key usage 0x%X]";
766 const int keyUsageMaxStrLen = 8;
767 accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen;
768 char accountUTF8[accountUTF8Len];
769 if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8))
770 accountUTF8[0] = (char)'\0';
771 if (keyUsage)
772 snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage);
773 CssmData account(const_cast<char *>(accountUTF8), strlen(accountUTF8));
774 CFRelease(labelStr);
775
776 // service attribute (name provided by the caller)
777 CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8) + 1;;
778 char serviceUTF8[serviceUTF8Len];
779 if (!CFStringGetCString(name, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8))
780 serviceUTF8[0] = (char)'\0';
781 CssmData service(const_cast<char *>(serviceUTF8), strlen(serviceUTF8));
782
783 // look for existing preference item, in case this is an update
784 StorageManager::KeychainList keychains;
785 globals().storageManager.getSearchList(keychains);
786 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
787 FourCharCode itemType = 'cprf';
788 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
789 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
790 if (keyUsage)
791 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
792 if (date)
793 ; // %%%TBI
794
795 Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false);
796 bool add = (!cursor->next(item));
797 // at this point, we either have a new item to add or an existing item to update
798
799 // set item attribute values
800 item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service);
801 item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), itemType);
802 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
803 item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
804 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service);
805
806 // date
807 if (date)
808 ; // %%%TBI
809
810 // generic attribute (store persistent certificate reference)
811 CFDataRef pItemRef = nil;
812 Certificate::required(certificate)->copyPersistentReference(pItemRef);
813 if (!pItemRef) {
814 MacOSError::throwMe(errSecInvalidItemRef);
815 }
816 const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef);
817 CFIndex dataLen = CFDataGetLength(pItemRef);
818 CssmData pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr)), dataLen);
819 item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref);
820 CFRelease(pItemRef);
821
822 if (add) {
823 Keychain keychain = nil;
824 try {
825 keychain = globals().storageManager.defaultKeychain();
826 if (!keychain->exists())
827 MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time.
828 }
829 catch(...) {
830 keychain = globals().storageManager.defaultKeychainUI(item);
831 }
832
833 try {
834 keychain->add(item);
835 }
836 catch (const MacOSError &err) {
837 if (err.osStatus() != errSecDuplicateItem)
838 throw; // if item already exists, fall through to update
839 }
840 }
841 item->update();
842
843 END_SECAPI
844 }
845
846 OSStatus SecCertificateSetPreferred(
847 SecCertificateRef certificate,
848 CFStringRef name,
849 CFArrayRef keyUsage)
850 {
851 CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
852 return SecCertificateSetPreference(certificate, name, keyUse, NULL);
853 }
854
855 CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayRef keys, CFErrorRef *error)
856 {
857 CFDictionaryRef result = NULL;
858 OSStatus __secapiresult;
859 try
860 {
861 CertificateValues cv(certificate);
862 result = cv.copyFieldValues(keys,error);
863 __secapiresult=0;
864 }
865 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
866 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
867 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
868 catch (...) { __secapiresult=errSecInternalComponent; }
869 return result;
870 }
871
872 CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
873 {
874 return SecCertificateCopyShortDescription(alloc, certificate, error);
875 }
876
877 CFStringRef SecCertificateCopyShortDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
878 {
879 CFStringRef result = NULL;
880 OSStatus __secapiresult;
881 try
882 {
883 __secapiresult = SecCertificateInferLabel(certificate, &result);
884 }
885 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
886 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
887 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
888 catch (...) { __secapiresult=errSecInternalComponent; }
889 if (error!=NULL && __secapiresult!=errSecSuccess)
890 {
891 *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus,
892 __secapiresult ? __secapiresult : CSSM_ERRCODE_INTERNAL_ERROR, NULL);
893 }
894 return result;
895 }
896
897 CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error)
898 {
899 CFDataRef result = NULL;
900 OSStatus __secapiresult;
901 try
902 {
903 CertificateValues cv(certificate);
904 result = cv.copySerialNumber(error);
905 __secapiresult=0;
906 }
907 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
908 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
909 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
910 catch (...) { __secapiresult=errSecInternalComponent; }
911 return result;
912 }
913
914 CFDataRef SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate, CFErrorRef *error)
915 {
916 CFDataRef result = NULL;
917 OSStatus __secapiresult;
918 try
919 {
920 CertificateValues cv(certificate);
921 result = cv.copyNormalizedIssuerContent(error);
922 __secapiresult=0;
923 }
924 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
925 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
926 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
927 catch (...) { __secapiresult=errSecInternalComponent; }
928 return result;
929 }
930
931 CFDataRef SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate, CFErrorRef *error)
932 {
933 CFDataRef result = NULL;
934 OSStatus __secapiresult;
935 try
936 {
937 CertificateValues cv(certificate);
938 result = cv.copyNormalizedSubjectContent(error);
939 __secapiresult=0;
940 }
941 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
942 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
943 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
944 catch (...) { __secapiresult=errSecInternalComponent; }
945 return result;
946 }
947
948 CFDataRef SecCertificateCopyIssuerSequence(SecCertificateRef certificate)
949 {
950 CFDataRef result = NULL;
951 OSStatus __secapiresult;
952 try
953 {
954 CertificateValues cv(certificate);
955 result = cv.copyIssuerSequence(NULL);
956 __secapiresult=0;
957 }
958 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
959 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
960 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
961 catch (...) { __secapiresult=errSecInternalComponent; }
962 return result;
963 }
964
965 CFDataRef SecCertificateCopySubjectSequence(SecCertificateRef certificate)
966 {
967 CFDataRef result = NULL;
968 OSStatus __secapiresult;
969 try
970 {
971 CertificateValues cv(certificate);
972 result = cv.copySubjectSequence(NULL);
973 __secapiresult=0;
974 }
975 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
976 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
977 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
978 catch (...) { __secapiresult=errSecInternalComponent; }
979 return result;
980 }
981
982 bool SecCertificateIsValid(SecCertificateRef certificate, CFAbsoluteTime verifyTime)
983 {
984 bool result = NULL;
985 OSStatus __secapiresult;
986 try
987 {
988 CFErrorRef error = NULL;
989 CertificateValues cv(certificate);
990 result = cv.isValid(verifyTime, &error);
991 if (error) CFRelease(error);
992 __secapiresult=0;
993 }
994 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
995 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
996 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
997 catch (...) { __secapiresult=errSecInternalComponent; }
998 return result;
999 }
1000
1001 /*
1002 * deprecated function name
1003 */
1004 bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime)
1005 {
1006 return SecCertificateIsValid(certificate, verifyTime);
1007 }
1008
1009
1010 CFAbsoluteTime SecCertificateNotValidBefore(SecCertificateRef certificate)
1011 {
1012 CFAbsoluteTime result = 0;
1013 OSStatus __secapiresult;
1014 try
1015 {
1016 CFErrorRef error = NULL;
1017 CertificateValues cv(certificate);
1018 result = cv.notValidBefore(&error);
1019 if (error) CFRelease(error);
1020 __secapiresult=0;
1021 }
1022 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1023 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1024 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1025 catch (...) { __secapiresult=errSecInternalComponent; }
1026 return result;
1027 }
1028
1029 CFAbsoluteTime SecCertificateNotValidAfter(SecCertificateRef certificate)
1030 {
1031 CFAbsoluteTime result = 0;
1032 OSStatus __secapiresult;
1033 try
1034 {
1035 CFErrorRef error = NULL;
1036 CertificateValues cv(certificate);
1037 result = cv.notValidAfter(&error);
1038 if (error) CFRelease(error);
1039 __secapiresult=0;
1040 }
1041 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1042 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1043 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1044 catch (...) { __secapiresult=errSecInternalComponent; }
1045 return result;
1046 }
1047
1048 /* new in 10.8 */
1049 SecCertificateRef SecCertificateCreateWithBytes(CFAllocatorRef allocator,
1050 const UInt8 *bytes, CFIndex length)
1051 {
1052 SecCertificateRef certificate = NULL;
1053 OSStatus __secapiresult;
1054 try {
1055 CSSM_DATA cssmCertData = { (CSSM_SIZE)length, (uint8 *)bytes };
1056
1057 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
1058 SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER));
1059 certificate = certificatePtr->handle();
1060
1061 __secapiresult=errSecSuccess;
1062 }
1063 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1064 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1065 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1066 catch (...) { __secapiresult=errSecInternalComponent; }
1067 return certificate;
1068 }
1069
1070 /* new in 10.8 */
1071 CFIndex SecCertificateGetLength(SecCertificateRef certificate)
1072 {
1073 CFIndex length = 0;
1074 OSStatus __secapiresult;
1075 try {
1076 CssmData output = Certificate::required(certificate)->data();
1077 length = (CFIndex)output.length();
1078 __secapiresult=errSecSuccess;
1079 }
1080 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1081 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1082 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1083 catch (...) { __secapiresult=errSecInternalComponent; }
1084 return length;
1085 }
1086
1087 /* new in 10.8 */
1088 const UInt8 *SecCertificateGetBytePtr(SecCertificateRef certificate)
1089 {
1090 const UInt8 *bytes = NULL;
1091 OSStatus __secapiresult;
1092 try {
1093 CssmData output = Certificate::required(certificate)->data();
1094 bytes = (const UInt8 *)output.data();
1095 __secapiresult=errSecSuccess;
1096 }
1097 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1098 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1099 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1100 catch (...) { __secapiresult=errSecInternalComponent; }
1101 return bytes;
1102 }
1103
1104 static CFArrayRef CopyEscrowCertificates(CFErrorRef *error)
1105 {
1106 // Return array of CFDataRef certificates.
1107 CFArrayRef result = NULL;
1108 int iCnt;
1109 int numRoots = 0;
1110
1111 // Get the hard coded set of production roots
1112 // static struct RootRecord* kProductionEscrowRoots[] = {&kOldEscrowRootRecord, &kProductionEscrowRootRecord};
1113
1114 numRoots = kNumberOfProductionEscrowRoots;
1115 CFDataRef productionCerts[numRoots];
1116 struct RootRecord* pRootRecord = NULL;
1117
1118 for (iCnt = 0; iCnt < numRoots; iCnt++)
1119 {
1120 pRootRecord = kProductionEscrowRoots[iCnt];
1121 if (NULL != pRootRecord && pRootRecord->_length > 0 && NULL != pRootRecord->_bytes)
1122 {
1123 productionCerts[iCnt] = CFDataCreate(kCFAllocatorDefault, pRootRecord->_bytes, pRootRecord->_length);
1124 }
1125 }
1126 result = CFArrayCreate(kCFAllocatorDefault, (const void **)productionCerts, numRoots, &kCFTypeArrayCallBacks);
1127 for (iCnt = 0; iCnt < numRoots; iCnt++)
1128 {
1129 if (NULL != productionCerts[iCnt])
1130 {
1131 CFRelease(productionCerts[iCnt]);
1132 }
1133 }
1134
1135 return result;
1136 }
1137
1138 /* new in 10.9 */
1139 CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType)
1140 {
1141 CFArrayRef result = NULL;
1142 int iCnt;
1143 int numRoots = 0;
1144 CFDataRef certData = NULL;
1145
1146 // The request is for the base line certificates.
1147 // Use the hard coded data to generate the return array
1148 if (kSecCertificateBaselineEscrowRoot == escrowRootType)
1149 {
1150 // Get the hard coded set of roots
1151 numRoots = kNumberOfBaseLineEscrowRoots;
1152 SecCertificateRef baseLineCerts[numRoots];
1153 struct RootRecord* pRootRecord = NULL;
1154
1155 for (iCnt = 0; iCnt < numRoots; iCnt++)
1156 {
1157 pRootRecord = kBaseLineEscrowRoots[iCnt];
1158 if (NULL != pRootRecord && pRootRecord->_length > 0 && NULL != pRootRecord->_bytes)
1159 {
1160 certData = CFDataCreate(kCFAllocatorDefault, pRootRecord->_bytes, pRootRecord->_length);
1161 if (NULL != certData)
1162 {
1163 baseLineCerts[iCnt] = SecCertificateCreateWithData(kCFAllocatorDefault, certData);
1164 CFRelease(certData);
1165 }
1166 }
1167 }
1168 result = CFArrayCreate(kCFAllocatorDefault, (const void **)baseLineCerts, numRoots, &kCFTypeArrayCallBacks);
1169 for (iCnt = 0; iCnt < numRoots; iCnt++)
1170 {
1171 if (NULL != baseLineCerts[iCnt])
1172 {
1173 CFRelease(baseLineCerts[iCnt]);
1174 }
1175 }
1176 }
1177 // The request is for the current certificates.
1178 else if (kSecCertificateProductionEscrowRoot == escrowRootType)
1179 {
1180 CFErrorRef error = NULL;
1181 CFArrayRef cert_datas = CopyEscrowCertificates(&error);
1182 if (NULL != error || NULL == cert_datas || 0 == (numRoots = (int)CFArrayGetCount(cert_datas)))
1183 {
1184 if (NULL != error)
1185 {
1186 CFRelease(error);
1187 }
1188
1189 if (NULL != cert_datas)
1190 {
1191 CFRelease(cert_datas);
1192 }
1193 return result;
1194 }
1195
1196 SecCertificateRef assetCerts[numRoots];
1197 for (iCnt = 0; iCnt < numRoots; iCnt++)
1198 {
1199 certData = (CFDataRef)CFArrayGetValueAtIndex(cert_datas, iCnt);
1200 if (NULL != certData)
1201 {
1202 SecCertificateRef aCertRef = SecCertificateCreateWithData(kCFAllocatorDefault, certData);
1203 assetCerts[iCnt] = aCertRef;
1204 }
1205 else
1206 {
1207 assetCerts[iCnt] = NULL;
1208 }
1209 }
1210
1211 if (numRoots > 0)
1212 {
1213 result = CFArrayCreate(kCFAllocatorDefault, (const void **)assetCerts, numRoots, &kCFTypeArrayCallBacks);
1214 for (iCnt = 0; iCnt < numRoots; iCnt++)
1215 {
1216 if (NULL != assetCerts[iCnt])
1217 {
1218 CFRelease(assetCerts[iCnt]);
1219 }
1220 }
1221 }
1222 CFRelease(cert_datas);
1223 }
1224 return result;
1225 }
1226