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