]>
Commit | Line | Data |
---|---|---|
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 | ||
57 | struct RootRecord | |
58 | { | |
59 | size_t _length; | |
60 | UInt8* _bytes; | |
61 | }; | |
62 | ||
63 | /* ========================================================================== | |
64 | Production Escrow Certificates | |
65 | ========================================================================== */ | |
66 | ||
67 | static 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 | ||
132 | static struct RootRecord kProductionEscrowRootRecord = {sizeof(kProductionEscrowRootGM), (UInt8*)kProductionEscrowRootGM}; | |
133 | static struct RootRecord* kProductionEscrowRoots[] = {&kProductionEscrowRootRecord}; | |
134 | static const int kNumberOfProductionEscrowRoots = (int)(sizeof(kProductionEscrowRoots)/sizeof(kProductionEscrowRoots[0])); | |
135 | ||
136 | static struct RootRecord kBaseLineEscrowRootRecord = {sizeof(kProductionEscrowRootGM), (UInt8*)kProductionEscrowRootGM}; | |
137 | static struct RootRecord* kBaseLineEscrowRoots[] = {&kBaseLineEscrowRootRecord}; | |
138 | static const int kNumberOfBaseLineEscrowRoots = (int)(sizeof(kBaseLineEscrowRoots)/sizeof(kBaseLineEscrowRoots[0])); | |
139 | ||
140 | ||
141 | #endif | |
142 | //###################################################################### | |
143 | //%%% end workaround: rdar://14292830 | |
144 | ////###################################################################### | |
145 | ||
b1ab9ed8 A |
146 | |
147 | extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage); | |
148 | ||
427c49bc A |
149 | #define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); |
150 | ||
151 | SEC_CONST_DECL (kSecCertificateProductionEscrowKey, "ProductionEscrowKey"); | |
152 | SEC_CONST_DECL (kSecCertificateEscrowFileName, "AppleESCertificates"); | |
153 | ||
b1ab9ed8 A |
154 | |
155 | using namespace CssmClient; | |
156 | ||
157 | CFTypeID | |
158 | SecCertificateGetTypeID(void) | |
159 | { | |
160 | BEGIN_SECAPI | |
161 | ||
162 | return gTypes().Certificate.typeID; | |
163 | ||
164 | END_SECAPI1(_kCFRuntimeNotATypeID) | |
165 | } | |
166 | ||
167 | ||
168 | OSStatus | |
169 | SecCertificateCreateFromData(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 */ | |
180 | SecCertificateRef | |
181 | SecCertificateCreateWithData(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 | ||
203 | OSStatus | |
204 | SecCertificateAddToKeychain(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 | ||
214 | OSStatus | |
215 | SecCertificateGetData(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 */ | |
225 | CFDataRef | |
226 | SecCertificateCopyData(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 | ||
245 | CFDataRef | |
246 | SecCertificateGetSHA1Digest(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 |
260 | CFArrayRef |
261 | SecCertificateCopyDNSNames(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 |
275 | OSStatus |
276 | SecCertificateGetType(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 | ||
286 | OSStatus | |
287 | SecCertificateGetSubject(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 | ||
297 | OSStatus | |
298 | SecCertificateGetIssuer(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 | ||
308 | OSStatus | |
309 | SecCertificateGetCLHandle(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 | */ | |
322 | OSStatus | |
323 | SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label) | |
324 | { | |
325 | BEGIN_SECAPI | |
326 | ||
327 | Certificate::required(certificate)->inferLabel(false, | |
328 | &Required(label)); | |
329 | ||
330 | END_SECAPI | |
331 | } | |
332 | ||
333 | OSStatus | |
334 | SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key) | |
335 | { | |
336 | BEGIN_SECAPI | |
337 | ||
338 | Required(key) = Certificate::required(certificate)->publicKey()->handle(); | |
339 | ||
340 | END_SECAPI | |
341 | } | |
342 | ||
343 | OSStatus | |
344 | SecCertificateGetAlgorithmID(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 | ||
353 | OSStatus | |
354 | SecCertificateCopyCommonName(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 */ | |
364 | CFStringRef | |
365 | SecCertificateCopySubjectSummary(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 |
381 | CFStringRef |
382 | SecCertificateCopyIssuerSummary(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 |
398 | OSStatus |
399 | SecCertificateCopySubjectComponent(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 | ||
408 | OSStatus | |
409 | SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName) | |
410 | { | |
411 | // deprecated SPI signature; replaced by SecCertificateCopyCommonName | |
412 | return SecCertificateCopyCommonName(certificate, commonName); | |
413 | } | |
414 | ||
415 | OSStatus | |
416 | SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress) | |
417 | { | |
418 | BEGIN_SECAPI | |
419 | ||
420 | Required(emailAddress) = Certificate::required(certificate)->copyFirstEmailAddress(); | |
421 | ||
422 | END_SECAPI | |
423 | } | |
424 | ||
425 | OSStatus | |
426 | SecCertificateCopyEmailAddresses(SecCertificateRef certificate, CFArrayRef *emailAddresses) | |
427 | { | |
428 | BEGIN_SECAPI | |
429 | ||
430 | Required(emailAddresses) = Certificate::required(certificate)->copyEmailAddresses(); | |
431 | ||
432 | END_SECAPI | |
433 | } | |
434 | ||
435 | OSStatus | |
436 | SecCertificateCopyFieldValues(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 | ||
446 | OSStatus | |
447 | SecCertificateReleaseFieldValues(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 | ||
456 | OSStatus | |
457 | SecCertificateCopyFirstFieldValue(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 | ||
466 | OSStatus | |
467 | SecCertificateReleaseFirstFieldValue(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 | ||
476 | OSStatus | |
477 | SecCertificateFindByIssuerAndSN(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 | ||
489 | OSStatus | |
490 | SecCertificateFindBySubjectKeyID(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 | ||
502 | OSStatus | |
503 | SecCertificateFindByEmail(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 | ||
514 | OSStatus | |
515 | SecKeychainSearchCreateForCertificateByIssuerAndSN(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 | ||
530 | OSStatus | |
531 | SecKeychainSearchCreateForCertificateByIssuerAndSN_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 | ||
548 | OSStatus | |
549 | SecKeychainSearchCreateForCertificateBySubjectKeyID(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 | ||
564 | OSStatus | |
565 | SecKeychainSearchCreateForCertificateByEmail(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. | |
581 | CSSM_CSP_HANDLE | |
582 | SecGetAppleCSPHandle() | |
583 | { | |
584 | BEGIN_SECAPI | |
585 | return CSP(gGuidAppleCSP)->handle(); | |
586 | END_SECAPI1(NULL); | |
587 | } | |
588 | ||
589 | CSSM_CL_HANDLE | |
590 | SecGetAppleCLHandle() | |
591 | { | |
592 | BEGIN_SECAPI | |
593 | return CL(gGuidAppleX509CL)->handle(); | |
594 | END_SECAPI1(NULL); | |
595 | } | |
596 | */ | |
597 | ||
598 | CSSM_RETURN | |
599 | SecDigestGetData (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 */ | |
619 | OSStatus 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 | ||
630 | OSStatus | |
631 | SecCertificateCopyPreference( | |
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 | ||
678 | SecCertificateRef | |
679 | SecCertificateCopyPreferred( | |
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 | 699 | static OSStatus |
b1ab9ed8 A |
700 | SecCertificateFindPreferenceItemWithNameAndKeyUsage( |
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 | 739 | static |
b1ab9ed8 A |
740 | OSStatus 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 | ||
765 | OSStatus 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 | ||
878 | OSStatus 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 | ||
887 | CFDictionaryRef 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 | ||
904 | CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error) | |
905 | { | |
906 | return SecCertificateCopyShortDescription(alloc, certificate, error); | |
907 | } | |
908 | ||
909 | CFStringRef 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 | ||
929 | CFDataRef 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 | ||
946 | CFDataRef 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 | ||
963 | CFDataRef 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 |
980 | CFDataRef 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 | ||
997 | CFDataRef 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 | ||
1014 | bool 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 | */ | |
1036 | bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime) | |
1037 | { | |
1038 | return SecCertificateIsValid(certificate, verifyTime); | |
1039 | } | |
1040 | ||
1041 | ||
1042 | CFAbsoluteTime 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 | ||
1061 | CFAbsoluteTime 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 */ | |
1081 | SecCertificateRef 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 */ | |
1103 | CFIndex 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 */ | |
1120 | const 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 |
1136 | static 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 */ | |
1171 | CFArrayRef 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 |