]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
8a50f688 | 2 | * Copyright (c) 2002-2017 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
8a50f688 | 5 | * |
b1ab9ed8 A |
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. | |
8a50f688 | 12 | * |
b1ab9ed8 A |
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. | |
8a50f688 | 20 | * |
b1ab9ed8 A |
21 | * @APPLE_LICENSE_HEADER_END@ |
22 | */ | |
23 | ||
24 | // | |
25 | // CertificateValues.cpp | |
26 | // | |
27 | #include <security_keychain/Certificate.h> | |
28 | #include <Security/oidscert.h> | |
29 | #include <Security/oidsattr.h> | |
30 | #include <Security/SecCertificate.h> | |
31 | #include <Security/SecCertificatePriv.h> | |
b1ab9ed8 A |
32 | #include "SecCertificateOIDs.h" |
33 | #include "CertificateValues.h" | |
b1ab9ed8 | 34 | #include <CoreFoundation/CFNumber.h> |
b1ab9ed8 | 35 | |
8a50f688 A |
36 | // SecCertificateInternal.h cannot be included in this file, due to its |
37 | // use of types which are not resolved in our macOS-only library. | |
38 | // | |
39 | extern "C" CFArrayRef SecCertificateCopyLegacyProperties(SecCertificateRef certificate); | |
40 | extern "C" void appendProperty(CFMutableArrayRef properties, CFStringRef propertyType, | |
41 | CFStringRef label, CFStringRef localizedLabel, CFTypeRef value); | |
b1ab9ed8 | 42 | |
5c19dc3a A |
43 | extern const CFStringRef __nonnull kSecPropertyKeyType; |
44 | extern const CFStringRef __nonnull kSecPropertyKeyLabel; | |
45 | extern const CFStringRef __nonnull kSecPropertyKeyLocalizedLabel; | |
46 | extern const CFStringRef __nonnull kSecPropertyKeyValue; | |
b1ab9ed8 | 47 | |
5c19dc3a A |
48 | extern const CFStringRef __nonnull kSecPropertyTypeData; |
49 | extern const CFStringRef __nonnull kSecPropertyTypeString; | |
50 | extern const CFStringRef __nonnull kSecPropertyTypeURL; | |
51 | extern const CFStringRef __nonnull kSecPropertyTypeDate; | |
b54c578e A |
52 | extern const CFStringRef __nonnull kSecPropertyTypeArray; |
53 | extern const CFStringRef __nonnull kSecPropertyTypeNumber; | |
b1ab9ed8 A |
54 | |
55 | ||
56 | #pragma mark ---------- CertificateValues Implementation ---------- | |
57 | ||
58 | using namespace KeychainCore; | |
59 | ||
60 | void addFieldValues(const void *key, const void *value, void *context); | |
61 | void addPropertyToFieldValues(const void *value, void *context); | |
62 | void filterFieldValues(const void *key, const void *value, void *context); | |
63 | void validateKeys(const void *value, void *context); | |
64 | ||
65 | CFDictionaryRef CertificateValues::mOIDRemap = NULL; | |
66 | ||
67 | typedef struct FieldValueFilterContext | |
68 | { | |
69 | CFMutableDictionaryRef filteredValues; | |
70 | CFArrayRef filterKeys; | |
71 | } FieldValueFilterContext; | |
72 | ||
73 | CertificateValues::CertificateValues(SecCertificateRef certificateRef) : mCertificateRef(certificateRef), | |
8a50f688 A |
74 | mCertificateData(NULL), |
75 | mCertificateProperties(NULL) | |
b1ab9ed8 A |
76 | { |
77 | if (mCertificateRef) | |
78 | CFRetain(mCertificateRef); | |
79 | } | |
80 | ||
d64be36e | 81 | CertificateValues::~CertificateValues() _NOEXCEPT |
b1ab9ed8 | 82 | { |
8a50f688 A |
83 | if (mCertificateProperties) |
84 | CFRelease(mCertificateProperties); | |
b1ab9ed8 A |
85 | if (mCertificateData) |
86 | CFRelease(mCertificateData); | |
87 | if (mCertificateRef) | |
88 | CFRelease(mCertificateRef); | |
89 | } | |
90 | ||
8a50f688 A |
91 | CFArrayRef CertificateValues::copyPropertyValues(CFErrorRef *error) |
92 | { | |
93 | if (!mCertificateProperties) { | |
94 | mCertificateProperties = SecCertificateCopyLegacyProperties(mCertificateRef); | |
95 | } | |
96 | if (mCertificateProperties) { | |
97 | CFRetain(mCertificateProperties); | |
98 | } | |
99 | else if (error) { | |
100 | *error = CFErrorCreate(NULL, | |
101 | kCFErrorDomainOSStatus, errSecInvalidCertificateRef, NULL); | |
102 | } | |
103 | return mCertificateProperties; | |
104 | } | |
105 | ||
b1ab9ed8 A |
106 | CFDictionaryRef CertificateValues::copyFieldValues(CFArrayRef keys, CFErrorRef *error) |
107 | { | |
108 | if (keys) | |
109 | { | |
110 | if (CFGetTypeID(keys)!=CFArrayGetTypeID()) | |
111 | return NULL; | |
112 | CFRange range = CFRangeMake(0, CFArrayGetCount((CFArrayRef)keys)); | |
113 | bool failed = false; | |
114 | CFArrayApplyFunction(keys, range, validateKeys, &failed); | |
115 | if (failed) | |
116 | return NULL; | |
117 | } | |
118 | ||
119 | if (mCertificateData) | |
120 | { | |
121 | CFRelease(mCertificateData); | |
122 | mCertificateData = NULL; | |
123 | } | |
124 | if (!mCertificateData) | |
125 | { | |
126 | mCertificateData = SecCertificateCopyData(mCertificateRef); // OK to call, no big lock | |
127 | if (!mCertificateData) | |
128 | { | |
129 | if (error) { | |
130 | *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidCertificateRef, NULL); | |
131 | } | |
132 | return NULL; | |
133 | } | |
134 | } | |
135 | ||
8a50f688 A |
136 | SecCertificateRef certificate = SecCertificateCreateWithData(kCFAllocatorDefault, mCertificateData); |
137 | if (!certificate) | |
b1ab9ed8 A |
138 | { |
139 | if (error) | |
140 | *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidCertificateGroup, NULL); | |
141 | return NULL; | |
142 | } | |
143 | ||
144 | CFMutableDictionaryRef fieldValues=CFDictionaryCreateMutable(kCFAllocatorDefault, 0, | |
145 | &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); | |
146 | ||
147 | // Return an array of CFStringRefs representing the common names in the certificates subject if any | |
8a50f688 | 148 | CFArrayRef commonNames=SecCertificateCopyCommonNames(certificate); |
b1ab9ed8 A |
149 | if (commonNames) |
150 | { | |
151 | CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); | |
8a50f688 | 152 | appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("CN"), NULL, commonNames); |
b1ab9ed8 A |
153 | CFDictionaryAddValue(fieldValues, kSecOIDCommonName, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); |
154 | CFRelease(commonNames); | |
155 | CFRelease(additionalValues); | |
156 | } | |
157 | ||
158 | // These can exist in the subject alt name or in the subject | |
8a50f688 | 159 | CFArrayRef dnsNames=SecCertificateCopyDNSNames(certificate); |
b1ab9ed8 A |
160 | if (dnsNames) |
161 | { | |
162 | CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); | |
8a50f688 | 163 | appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("DNS"), NULL, dnsNames); |
b1ab9ed8 A |
164 | CFDictionaryAddValue(fieldValues, CFSTR("DNSNAMES"), (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); |
165 | CFRelease(dnsNames); | |
166 | CFRelease(additionalValues); | |
167 | } | |
168 | ||
8a50f688 | 169 | CFArrayRef ipAddresses=SecCertificateCopyIPAddresses(certificate); |
b1ab9ed8 A |
170 | if (ipAddresses) |
171 | { | |
172 | CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); | |
8a50f688 | 173 | appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("IP"), NULL, dnsNames); |
b1ab9ed8 A |
174 | CFDictionaryAddValue(fieldValues, CFSTR("IPADDRESSES"), (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); |
175 | CFRelease(ipAddresses); | |
176 | CFRelease(additionalValues); | |
177 | } | |
178 | ||
179 | // These can exist in the subject alt name or in the subject | |
8a50f688 | 180 | CFArrayRef emailAddrs=SecCertificateCopyRFC822Names(certificate); |
b1ab9ed8 A |
181 | if (emailAddrs) |
182 | { | |
183 | CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); | |
8a50f688 | 184 | appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("DNS"), NULL, dnsNames); |
b1ab9ed8 A |
185 | CFDictionaryAddValue(fieldValues, kSecOIDEmailAddress, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); |
186 | CFRelease(emailAddrs); | |
187 | CFRelease(additionalValues); | |
188 | } | |
189 | ||
8a50f688 | 190 | CFAbsoluteTime notBefore = SecCertificateNotValidBefore(certificate); |
b1ab9ed8 A |
191 | CFNumberRef notBeforeRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, ¬Before); |
192 | if (notBeforeRef) | |
193 | { | |
194 | CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); | |
8a50f688 | 195 | appendProperty(additionalValues, kSecPropertyTypeNumber, CFSTR("Not Valid Before"), NULL, notBeforeRef); |
b1ab9ed8 A |
196 | CFDictionaryAddValue(fieldValues, kSecOIDX509V1ValidityNotBefore, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); |
197 | CFRelease(notBeforeRef); | |
198 | CFRelease(additionalValues); | |
199 | } | |
200 | ||
8a50f688 | 201 | CFAbsoluteTime notAfter = SecCertificateNotValidAfter(certificate); |
b1ab9ed8 A |
202 | CFNumberRef notAfterRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, ¬After); |
203 | if (notAfterRef) | |
204 | { | |
205 | CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); | |
8a50f688 | 206 | appendProperty(additionalValues, kSecPropertyTypeNumber, CFSTR("Not Valid After"), NULL, notAfterRef); |
b1ab9ed8 A |
207 | CFDictionaryAddValue(fieldValues, kSecOIDX509V1ValidityNotAfter, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); |
208 | CFRelease(notAfterRef); | |
209 | CFRelease(additionalValues); | |
210 | } | |
211 | ||
8a50f688 | 212 | SecKeyUsage keyUsage=SecCertificateGetKeyUsage(certificate); |
b1ab9ed8 A |
213 | CFNumberRef ku = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &keyUsage); |
214 | if (ku) | |
215 | { | |
216 | CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); | |
8a50f688 | 217 | appendProperty(additionalValues, kSecPropertyTypeNumber, CFSTR("Key Usage"), NULL, ku); |
b1ab9ed8 A |
218 | CFDictionaryAddValue(fieldValues, kSecOIDKeyUsage, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); |
219 | CFRelease(ku); | |
220 | CFRelease(additionalValues); | |
221 | } | |
222 | ||
8a50f688 | 223 | CFArrayRef ekus = SecCertificateCopyExtendedKeyUsage(certificate); |
b1ab9ed8 A |
224 | if (ekus) |
225 | { | |
226 | CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); | |
8a50f688 | 227 | appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("Extended Key Usage"), NULL, ekus); |
b1ab9ed8 A |
228 | CFDictionaryAddValue(fieldValues, kSecOIDExtendedKeyUsage, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); |
229 | CFRelease(ekus); | |
230 | CFRelease(additionalValues); | |
231 | } | |
232 | ||
233 | // Add all values from properties dictionary | |
8a50f688 | 234 | CFArrayRef properties = copyPropertyValues(NULL); |
b1ab9ed8 A |
235 | if (properties) |
236 | { | |
237 | CFRange range = CFRangeMake(0, CFArrayGetCount((CFArrayRef)properties)); | |
238 | CFArrayApplyFunction(properties, range, addPropertyToFieldValues, fieldValues); | |
239 | // CFDictionaryApplyFunction(properties, addFieldValues, fieldValues); | |
240 | CFRelease(properties); | |
241 | } | |
242 | ||
243 | CFAbsoluteTime verifyTime = CFAbsoluteTimeGetCurrent(); | |
244 | CFMutableArrayRef summaryProperties = | |
8a50f688 | 245 | SecCertificateCopySummaryProperties(certificate, verifyTime); |
b1ab9ed8 A |
246 | if (summaryProperties) |
247 | { | |
248 | CFRange range = CFRangeMake(0, CFArrayGetCount((CFArrayRef)summaryProperties)); | |
249 | CFArrayApplyFunction(summaryProperties, range, addPropertyToFieldValues, fieldValues); | |
250 | // CFDictionaryApplyFunction(summaryProperties, addFieldValues, fieldValues); | |
251 | // CFDictionaryAddValue(fieldValues, CFSTR("summaryProperties"), summaryProperties); | |
252 | CFRelease(summaryProperties); | |
253 | } | |
254 | ||
8a50f688 A |
255 | if (certificate) |
256 | CFRelease(certificate); | |
b1ab9ed8 A |
257 | |
258 | if (keys==NULL) | |
259 | return (CFDictionaryRef)fieldValues; | |
260 | ||
261 | // Otherwise, we need to filter | |
262 | CFMutableDictionaryRef filteredFieldValues=CFDictionaryCreateMutable(kCFAllocatorDefault, 0, | |
263 | &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); | |
264 | ||
265 | FieldValueFilterContext fvcontext; | |
266 | fvcontext.filteredValues = filteredFieldValues; | |
267 | fvcontext.filterKeys = keys; | |
268 | ||
269 | CFDictionaryApplyFunction(fieldValues, filterFieldValues, &fvcontext); | |
270 | ||
271 | CFRelease(fieldValues); | |
272 | return (CFDictionaryRef)filteredFieldValues; | |
273 | } | |
274 | ||
275 | void validateKeys(const void *value, void *context) | |
276 | { | |
277 | if (value == NULL || (CFGetTypeID(value)!=CFStringGetTypeID())) | |
278 | if (context) | |
279 | *(bool *)context = true; | |
280 | } | |
281 | ||
282 | void filterFieldValues(const void *key, const void *value, void *context) | |
283 | { | |
284 | // each element of keys is a CFStringRef with an OID, e.g. | |
5c19dc3a | 285 | // const CFStringRef kSecOIDTitle = CFSTR("2.5.4.12"); |
b1ab9ed8 A |
286 | |
287 | CFTypeRef fieldKey = (CFTypeRef)key; | |
288 | if (fieldKey == NULL || (CFGetTypeID(fieldKey)!=CFStringGetTypeID()) || context==NULL) | |
289 | return; | |
290 | ||
291 | FieldValueFilterContext *fvcontext = (FieldValueFilterContext *)context; | |
292 | ||
293 | CFRange range = CFRangeMake(0, CFArrayGetCount(fvcontext->filterKeys)); | |
294 | CFIndex idx = CFArrayGetFirstIndexOfValue(fvcontext->filterKeys, range, fieldKey); | |
295 | if (idx != kCFNotFound) | |
296 | CFDictionaryAddValue(fvcontext->filteredValues, fieldKey, value); | |
297 | } | |
298 | ||
299 | void addFieldValues(const void *key, const void *value, void *context) | |
300 | { | |
301 | CFMutableDictionaryRef fieldValues = (CFMutableDictionaryRef)context; | |
302 | CFDictionaryAddValue(fieldValues, key, value); | |
303 | } | |
304 | ||
305 | void addPropertyToFieldValues(const void *value, void *context) | |
306 | { | |
307 | CFMutableDictionaryRef fieldValues = (CFMutableDictionaryRef)context; | |
308 | if (CFGetTypeID(value)==CFDictionaryGetTypeID()) | |
309 | { | |
310 | CFStringRef label = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)value, kSecPropertyKeyLabel); | |
311 | #if 0 | |
312 | CFStringRef typeD = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)value, kSecPropertyKeyType); | |
313 | CFTypeRef valueD = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)value, kSecPropertyKeyValue); | |
314 | #endif | |
315 | CFStringRef key = CertificateValues::remapLabelToKey(label); | |
316 | if (key) | |
317 | CFDictionaryAddValue(fieldValues, key, value); | |
318 | } | |
319 | } | |
320 | ||
321 | CFStringRef CertificateValues::remapLabelToKey(CFStringRef label) | |
322 | { | |
323 | if (!label) | |
324 | return NULL; | |
325 | ||
326 | if (!mOIDRemap) | |
327 | { | |
328 | CFTypeRef keys[] = | |
329 | { | |
330 | CFSTR("Subject Name"), | |
331 | CFSTR("Normalized Subject Name"), | |
332 | CFSTR("Issuer Name"), | |
333 | CFSTR("Normalized Subject Name"), | |
334 | CFSTR("Version"), | |
335 | CFSTR("Serial Number"), | |
336 | CFSTR("Signature Algorithm"), | |
337 | CFSTR("Subject Unique ID"), | |
338 | CFSTR("Issuer Unique ID"), | |
339 | CFSTR("Public Key Algorithm"), | |
340 | CFSTR("Public Key Data"), | |
341 | CFSTR("Signature"), | |
342 | CFSTR("Not Valid Before"), | |
343 | CFSTR("Not Valid After"), | |
344 | CFSTR("Expires") | |
345 | }; | |
346 | ||
347 | CFTypeRef values[] = | |
348 | { | |
349 | kSecOIDX509V1SubjectName, | |
350 | kSecOIDX509V1SubjectNameStd, | |
351 | kSecOIDX509V1IssuerName, | |
352 | kSecOIDX509V1IssuerNameStd, | |
353 | kSecOIDX509V1Version, | |
354 | kSecOIDX509V1SerialNumber, | |
355 | kSecOIDX509V1SignatureAlgorithm, // or CSSMOID_X509V1SignatureAlgorithmTBS? | |
356 | kSecOIDX509V1CertificateSubjectUniqueId, | |
357 | kSecOIDX509V1CertificateIssuerUniqueId, | |
358 | kSecOIDX509V1SubjectPublicKeyAlgorithm, | |
359 | kSecOIDX509V1SubjectPublicKey, | |
360 | kSecOIDX509V1Signature, | |
361 | kSecOIDX509V1ValidityNotBefore, | |
362 | kSecOIDX509V1ValidityNotAfter, | |
363 | kSecOIDInvalidityDate | |
364 | }; | |
365 | ||
366 | mOIDRemap = CFDictionaryCreate(NULL, keys, values, | |
367 | (sizeof(keys) / sizeof(*keys)), &kCFTypeDictionaryKeyCallBacks, | |
368 | &kCFTypeDictionaryValueCallBacks); | |
369 | } | |
370 | ||
371 | CFTypeRef result = (CFTypeRef)CFDictionaryGetValue(mOIDRemap, label); | |
372 | ||
373 | return result?(CFStringRef)result:label; | |
374 | } | |
375 | ||
376 | CFDataRef CertificateValues::copySerialNumber(CFErrorRef *error) | |
377 | { | |
427c49bc | 378 | CFDataRef result = NULL; |
8a50f688 | 379 | SecCertificateRef certificate = copySecCertificateRef(error); |
b1ab9ed8 | 380 | |
8a50f688 | 381 | if (certificate) |
427c49bc | 382 | { |
8a50f688 A |
383 | result = SecCertificateCopySerialNumberData(certificate, error); |
384 | CFRelease(certificate); | |
427c49bc A |
385 | } |
386 | return result; | |
b1ab9ed8 A |
387 | } |
388 | ||
427c49bc | 389 | CFDataRef CertificateValues::copyNormalizedIssuerContent(CFErrorRef *error) |
b1ab9ed8 | 390 | { |
427c49bc | 391 | CFDataRef result = NULL; |
8a50f688 A |
392 | SecCertificateRef certificate = copySecCertificateRef(error); |
393 | if (certificate) | |
427c49bc | 394 | { |
8a50f688 A |
395 | // this matches the behavior on OS X prior to 10.12, where |
396 | // normalized content was actually returned as a sequence. | |
397 | ||
398 | result = SecCertificateCopyNormalizedIssuerSequence(certificate); | |
399 | CFRelease(certificate); | |
427c49bc A |
400 | } |
401 | return result; | |
b1ab9ed8 A |
402 | } |
403 | ||
427c49bc | 404 | CFDataRef CertificateValues::copyNormalizedSubjectContent(CFErrorRef *error) |
b1ab9ed8 | 405 | { |
427c49bc | 406 | CFDataRef result = NULL; |
8a50f688 A |
407 | SecCertificateRef certificate = copySecCertificateRef(error); |
408 | if (certificate) | |
427c49bc | 409 | { |
8a50f688 A |
410 | // this matches the behavior on OS X prior to 10.12, where |
411 | // normalized content was actually returned as a sequence. | |
412 | ||
413 | result = SecCertificateCopyNormalizedSubjectSequence(certificate); | |
414 | CFRelease(certificate); | |
427c49bc A |
415 | } |
416 | return result; | |
b1ab9ed8 A |
417 | } |
418 | ||
427c49bc | 419 | CFDataRef CertificateValues::copyIssuerSequence(CFErrorRef *error) |
b1ab9ed8 | 420 | { |
427c49bc | 421 | CFDataRef result = NULL; |
8a50f688 A |
422 | SecCertificateRef certificate = copySecCertificateRef(error); |
423 | if (certificate) | |
427c49bc | 424 | { |
8a50f688 A |
425 | result = SecCertificateCopyIssuerSequence(certificate); |
426 | CFRelease(certificate); | |
427c49bc A |
427 | } |
428 | return result; | |
429 | } | |
430 | ||
431 | CFDataRef CertificateValues::copySubjectSequence(CFErrorRef *error) | |
432 | { | |
433 | CFDataRef result = NULL; | |
8a50f688 A |
434 | SecCertificateRef certificate = copySecCertificateRef(error); |
435 | if (certificate) | |
436 | { | |
437 | result = SecCertificateCopySubjectSequence(certificate); | |
438 | CFRelease(certificate); | |
439 | } | |
440 | return result; | |
441 | } | |
442 | ||
443 | CFStringRef CertificateValues::copyIssuerSummary(CFErrorRef *error) | |
444 | { | |
445 | CFStringRef result = NULL; | |
446 | SecCertificateRef certificate = copySecCertificateRef(error); | |
447 | if (certificate) | |
427c49bc | 448 | { |
8a50f688 A |
449 | result = SecCertificateCopyIssuerSummary(certificate); |
450 | CFRelease(certificate); | |
451 | } | |
452 | return result; | |
453 | } | |
454 | ||
455 | CFStringRef CertificateValues::copySubjectSummary(CFErrorRef *error) | |
456 | { | |
457 | CFStringRef result = NULL; | |
458 | SecCertificateRef certificate = copySecCertificateRef(error); | |
459 | if (certificate) | |
460 | { | |
461 | result = SecCertificateCopySubjectSummary(certificate); | |
462 | CFRelease(certificate); | |
427c49bc A |
463 | } |
464 | return result; | |
465 | } | |
466 | ||
fa7225c8 A |
467 | CFDictionaryRef CertificateValues::copyAttributeDictionary(CFErrorRef *error) |
468 | { | |
8a50f688 A |
469 | CFDictionaryRef result = NULL; |
470 | SecCertificateRef certificate = copySecCertificateRef(error); | |
471 | if (certificate) | |
472 | { | |
473 | result = SecCertificateCopyAttributeDictionary(certificate); | |
474 | CFRelease(certificate); | |
475 | } | |
476 | return result; | |
fa7225c8 A |
477 | } |
478 | ||
427c49bc A |
479 | bool CertificateValues::isValid(CFAbsoluteTime verifyTime, CFErrorRef *error) |
480 | { | |
481 | bool result = NULL; | |
8a50f688 A |
482 | SecCertificateRef certificate = copySecCertificateRef(error); |
483 | if (certificate) | |
427c49bc | 484 | { |
8a50f688 A |
485 | result = SecCertificateIsValid(certificate, verifyTime); |
486 | CFRelease(certificate); | |
427c49bc A |
487 | } |
488 | return result; | |
489 | } | |
490 | ||
491 | CFAbsoluteTime CertificateValues::notValidBefore(CFErrorRef *error) | |
492 | { | |
493 | CFAbsoluteTime result = 0; | |
8a50f688 A |
494 | SecCertificateRef certificate = copySecCertificateRef(error); |
495 | if (certificate) | |
427c49bc | 496 | { |
8a50f688 A |
497 | result = SecCertificateNotValidBefore(certificate); |
498 | CFRelease(certificate); | |
427c49bc A |
499 | } |
500 | return result; | |
501 | } | |
502 | ||
503 | CFAbsoluteTime CertificateValues::notValidAfter(CFErrorRef *error) | |
504 | { | |
505 | CFAbsoluteTime result = 0; | |
8a50f688 A |
506 | SecCertificateRef certificate = copySecCertificateRef(error); |
507 | if (certificate) | |
427c49bc | 508 | { |
8a50f688 A |
509 | result = SecCertificateNotValidAfter(certificate); |
510 | CFRelease(certificate); | |
427c49bc A |
511 | } |
512 | return result; | |
b1ab9ed8 A |
513 | } |
514 | ||
8a50f688 | 515 | SecCertificateRef CertificateValues::copySecCertificateRef(CFErrorRef *error) |
b1ab9ed8 A |
516 | { |
517 | // SecCertificateCopyData returns an object created with CFDataCreate, so we | |
518 | // own it and must release it | |
519 | ||
520 | if (mCertificateData) | |
521 | { | |
522 | CFRelease(mCertificateData); | |
523 | mCertificateData = NULL; | |
524 | } | |
525 | ||
526 | mCertificateData = SecCertificateCopyData(mCertificateRef); // OK to call, no big lock | |
8a50f688 | 527 | if (!mCertificateData) |
b1ab9ed8 | 528 | { |
8a50f688 A |
529 | if (error) |
530 | { | |
531 | *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidCertificateRef, NULL); | |
532 | } | |
b1ab9ed8 A |
533 | return NULL; |
534 | } | |
535 | ||
8a50f688 A |
536 | SecCertificateRef certificate = SecCertificateCreateWithData(kCFAllocatorDefault, mCertificateData); |
537 | if (!certificate) | |
b1ab9ed8 | 538 | { |
8a50f688 A |
539 | if (error) |
540 | { | |
541 | *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidCertificateGroup, NULL); | |
542 | } | |
b1ab9ed8 A |
543 | return NULL; |
544 | } | |
545 | ||
8a50f688 | 546 | return certificate; |
b1ab9ed8 A |
547 | } |
548 | ||
549 | #pragma mark ---------- OID Constants ---------- | |
550 | ||
5c19dc3a A |
551 | const CFStringRef kSecOIDADC_CERT_POLICY = CFSTR("1.2.840.113635.100.5.3"); |
552 | const CFStringRef kSecOIDAPPLE_CERT_POLICY = CFSTR("1.2.840.113635.100.5.1"); | |
553 | const CFStringRef kSecOIDAPPLE_EKU_CODE_SIGNING = CFSTR("1.2.840.113635.100.4.1"); | |
554 | const CFStringRef kSecOIDAPPLE_EKU_CODE_SIGNING_DEV = CFSTR("1.2.840.113635.100.4.1.1"); | |
555 | const CFStringRef kSecOIDAPPLE_EKU_ICHAT_ENCRYPTION = CFSTR("1.2.840.113635.100.4.3"); | |
556 | const CFStringRef kSecOIDAPPLE_EKU_ICHAT_SIGNING = CFSTR("1.2.840.113635.100.4.2"); | |
557 | const CFStringRef kSecOIDAPPLE_EKU_RESOURCE_SIGNING = CFSTR("1.2.840.113635.100.4.1.4"); | |
558 | const CFStringRef kSecOIDAPPLE_EKU_SYSTEM_IDENTITY = CFSTR("1.2.840.113635.100.4.4"); | |
559 | const CFStringRef kSecOIDAPPLE_EXTENSION = CFSTR("1.2.840.113635.100.6"); | |
560 | const CFStringRef kSecOIDAPPLE_EXTENSION_ADC_APPLE_SIGNING = CFSTR("1.2.840.113635.100.6.1.2.0.0"); | |
561 | const CFStringRef kSecOIDAPPLE_EXTENSION_ADC_DEV_SIGNING = CFSTR("1.2.840.113635.100.6.1.2.0"); | |
562 | const CFStringRef kSecOIDAPPLE_EXTENSION_APPLE_SIGNING = CFSTR("1.2.840.113635.100.6.1.1"); | |
563 | const CFStringRef kSecOIDAPPLE_EXTENSION_CODE_SIGNING = CFSTR("1.2.840.113635.100.6.1"); | |
564 | const CFStringRef kSecOIDAPPLE_EXTENSION_INTERMEDIATE_MARKER = CFSTR("1.2.840.113635.100.6.2"); | |
565 | const CFStringRef kSecOIDAPPLE_EXTENSION_WWDR_INTERMEDIATE = CFSTR("1.2.840.113635.100.6.2.1"); | |
566 | const CFStringRef kSecOIDAPPLE_EXTENSION_ITMS_INTERMEDIATE = CFSTR("1.2.840.113635.100.6.2.2"); | |
567 | const CFStringRef kSecOIDAPPLE_EXTENSION_AAI_INTERMEDIATE = CFSTR("1.2.840.113635.100.6.2.3"); | |
568 | const CFStringRef kSecOIDAPPLE_EXTENSION_APPLEID_INTERMEDIATE = CFSTR("1.2.840.113635.100.6.2.7"); | |
569 | const CFStringRef kSecOIDAuthorityInfoAccess = CFSTR("1.3.6.1.5.5.7.1.1"); | |
570 | const CFStringRef kSecOIDAuthorityKeyIdentifier = CFSTR("2.5.29.35"); | |
571 | const CFStringRef kSecOIDBasicConstraints = CFSTR("2.5.29.19"); | |
572 | const CFStringRef kSecOIDBiometricInfo = CFSTR("1.3.6.1.5.5.7.1.2"); | |
573 | const CFStringRef kSecOIDCSSMKeyStruct = CFSTR("2.16.840.1.113741.2.1.1.1.20"); | |
574 | const CFStringRef kSecOIDCertIssuer = CFSTR("2.5.29.29"); | |
575 | const CFStringRef kSecOIDCertificatePolicies = CFSTR("2.5.29.32"); | |
576 | const CFStringRef kSecOIDClientAuth = CFSTR("1.3.6.1.5.5.7.3.2"); | |
577 | const CFStringRef kSecOIDCollectiveStateProvinceName = CFSTR("2.5.4.8.1"); | |
578 | const CFStringRef kSecOIDCollectiveStreetAddress = CFSTR("2.5.4.9.1"); | |
579 | const CFStringRef kSecOIDCommonName = CFSTR("2.5.4.3"); | |
580 | const CFStringRef kSecOIDCountryName = CFSTR("2.5.4.6"); | |
581 | const CFStringRef kSecOIDCrlDistributionPoints = CFSTR("2.5.29.31"); | |
582 | const CFStringRef kSecOIDCrlNumber = CFSTR("2.5.29.20"); | |
583 | const CFStringRef kSecOIDCrlReason = CFSTR("2.5.29.21"); | |
584 | const CFStringRef kSecOIDDOTMAC_CERT_EMAIL_ENCRYPT = CFSTR("1.2.840.113635.100.3.2.3"); | |
585 | const CFStringRef kSecOIDDOTMAC_CERT_EMAIL_SIGN = CFSTR("1.2.840.113635.100.3.2.2"); | |
586 | const CFStringRef kSecOIDDOTMAC_CERT_EXTENSION = CFSTR("1.2.840.113635.100.3.2"); | |
587 | const CFStringRef kSecOIDDOTMAC_CERT_IDENTITY = CFSTR("1.2.840.113635.100.3.2.1"); | |
588 | const CFStringRef kSecOIDDOTMAC_CERT_POLICY = CFSTR("1.2.840.113635.100.5.2"); | |
589 | const CFStringRef kSecOIDDeltaCrlIndicator = CFSTR("2.5.29.27"); | |
590 | const CFStringRef kSecOIDDescription = CFSTR("2.5.4.13"); | |
591 | const CFStringRef kSecOIDEKU_IPSec = CFSTR("1.3.6.1.5.5.8.2.2"); | |
592 | const CFStringRef kSecOIDEmailAddress = CFSTR("1.2.840.113549.1.9.1"); | |
593 | const CFStringRef kSecOIDEmailProtection = CFSTR("1.3.6.1.5.5.7.3.4"); | |
594 | const CFStringRef kSecOIDExtendedKeyUsage = CFSTR("2.5.29.37"); | |
595 | const CFStringRef kSecOIDExtendedKeyUsageAny = CFSTR("2.5.29.37.0"); | |
596 | const CFStringRef kSecOIDExtendedUseCodeSigning = CFSTR("1.3.6.1.5.5.7.3.3"); | |
597 | const CFStringRef kSecOIDGivenName = CFSTR("2.5.4.42"); | |
598 | const CFStringRef kSecOIDHoldInstructionCode = CFSTR("2.5.29.23"); | |
599 | const CFStringRef kSecOIDInvalidityDate = CFSTR("2.5.29.24"); | |
600 | const CFStringRef kSecOIDIssuerAltName = CFSTR("2.5.29.18"); | |
601 | const CFStringRef kSecOIDIssuingDistributionPoint = CFSTR("2.5.29.28"); | |
602 | const CFStringRef kSecOIDIssuingDistributionPoints = CFSTR("2.5.29.28"); | |
603 | const CFStringRef kSecOIDKERBv5_PKINIT_KP_CLIENT_AUTH = CFSTR("1.3.6.1.5.2.3.4"); | |
604 | const CFStringRef kSecOIDKERBv5_PKINIT_KP_KDC = CFSTR("1.3.6.1.5.2.3.5"); | |
605 | const CFStringRef kSecOIDKeyUsage = CFSTR("2.5.29.15"); | |
606 | const CFStringRef kSecOIDLocalityName = CFSTR("2.5.4.7"); | |
607 | const CFStringRef kSecOIDMS_NTPrincipalName = CFSTR("1.3.6.1.4.1.311.20.2.3"); | |
608 | const CFStringRef kSecOIDMicrosoftSGC = CFSTR("1.3.6.1.4.1.311.10.3.3"); | |
609 | const CFStringRef kSecOIDNameConstraints = CFSTR("2.5.29.30"); | |
610 | const CFStringRef kSecOIDNetscapeCertSequence = CFSTR("2.16.840.1.113730.2.5"); | |
611 | const CFStringRef kSecOIDNetscapeCertType = CFSTR("2.16.840.1.113730.1.1"); | |
612 | const CFStringRef kSecOIDNetscapeSGC = CFSTR("2.16.840.1.113730.4.1"); | |
613 | const CFStringRef kSecOIDOCSPSigning = CFSTR("1.3.6.1.5.5.7.3.9"); | |
614 | const CFStringRef kSecOIDOrganizationName = CFSTR("2.5.4.10"); | |
615 | const CFStringRef kSecOIDOrganizationalUnitName = CFSTR("2.5.4.11"); | |
616 | const CFStringRef kSecOIDPolicyConstraints = CFSTR("2.5.29.36"); | |
617 | const CFStringRef kSecOIDPolicyMappings = CFSTR("2.5.29.33"); | |
618 | const CFStringRef kSecOIDPrivateKeyUsagePeriod = CFSTR("2.5.29.16"); | |
619 | const CFStringRef kSecOIDQC_Statements = CFSTR("1.3.6.1.5.5.7.1.3"); | |
620 | const CFStringRef kSecOIDSerialNumber = CFSTR("2.5.4.5"); | |
621 | const CFStringRef kSecOIDServerAuth = CFSTR("1.3.6.1.5.5.7.3.1"); | |
622 | const CFStringRef kSecOIDStateProvinceName = CFSTR("2.5.4.8"); | |
623 | const CFStringRef kSecOIDStreetAddress = CFSTR("2.5.4.9"); | |
624 | const CFStringRef kSecOIDSubjectAltName = CFSTR("2.5.29.17"); | |
625 | const CFStringRef kSecOIDSubjectDirectoryAttributes = CFSTR("2.5.29.9"); | |
626 | const CFStringRef kSecOIDSubjectEmailAddress = CFSTR("2.16.840.1.113741.2.1.1.1.50.3"); | |
627 | const CFStringRef kSecOIDSubjectInfoAccess = CFSTR("1.3.6.1.5.5.7.1.11"); | |
628 | const CFStringRef kSecOIDSubjectKeyIdentifier = CFSTR("2.5.29.14"); | |
629 | const CFStringRef kSecOIDSubjectPicture = CFSTR("2.16.840.1.113741.2.1.1.1.50.2"); | |
630 | const CFStringRef kSecOIDSubjectSignatureBitmap = CFSTR("2.16.840.1.113741.2.1.1.1.50.1"); | |
631 | const CFStringRef kSecOIDSurname = CFSTR("2.5.4.4"); | |
632 | const CFStringRef kSecOIDTimeStamping = CFSTR("1.3.6.1.5.5.7.3.8"); | |
633 | const CFStringRef kSecOIDTitle = CFSTR("2.5.4.12"); | |
634 | const CFStringRef kSecOIDUseExemptions = CFSTR("2.16.840.1.113741.2.1.1.1.50.4"); | |
635 | const CFStringRef kSecOIDX509V1CertificateIssuerUniqueId = CFSTR("2.16.840.1.113741.2.1.1.1.11"); | |
636 | const CFStringRef kSecOIDX509V1CertificateSubjectUniqueId = CFSTR("2.16.840.1.113741.2.1.1.1.12"); | |
637 | const CFStringRef kSecOIDX509V1IssuerName = CFSTR("2.16.840.1.113741.2.1.1.1.5"); | |
638 | const CFStringRef kSecOIDX509V1IssuerNameCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.5.1"); | |
639 | const CFStringRef kSecOIDX509V1IssuerNameLDAP = CFSTR("2.16.840.1.113741.2.1.1.1.5.2"); | |
640 | const CFStringRef kSecOIDX509V1IssuerNameStd = CFSTR("2.16.840.1.113741.2.1.1.1.23"); | |
641 | const CFStringRef kSecOIDX509V1SerialNumber = CFSTR("2.16.840.1.113741.2.1.1.1.3"); | |
642 | const CFStringRef kSecOIDX509V1Signature = CFSTR("2.16.840.1.113741.2.1.3.2.2"); | |
643 | const CFStringRef kSecOIDX509V1SignatureAlgorithm = CFSTR("2.16.840.1.113741.2.1.3.2.1"); | |
644 | const CFStringRef kSecOIDX509V1SignatureAlgorithmParameters = CFSTR("2.16.840.1.113741.2.1.3.2.3"); | |
645 | const CFStringRef kSecOIDX509V1SignatureAlgorithmTBS = CFSTR("2.16.840.1.113741.2.1.3.2.10"); | |
646 | const CFStringRef kSecOIDX509V1SignatureCStruct = CFSTR("2.16.840.1.113741.2.1.3.2.0.1"); | |
647 | const CFStringRef kSecOIDX509V1SignatureStruct = CFSTR("2.16.840.1.113741.2.1.3.2.0"); | |
648 | const CFStringRef kSecOIDX509V1SubjectName = CFSTR("2.16.840.1.113741.2.1.1.1.8"); | |
649 | const CFStringRef kSecOIDX509V1SubjectNameCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.8.1"); | |
650 | const CFStringRef kSecOIDX509V1SubjectNameLDAP = CFSTR("2.16.840.1.113741.2.1.1.1.8.2"); | |
651 | const CFStringRef kSecOIDX509V1SubjectNameStd = CFSTR("2.16.840.1.113741.2.1.1.1.22"); | |
652 | const CFStringRef kSecOIDX509V1SubjectPublicKey = CFSTR("2.16.840.1.113741.2.1.1.1.10"); | |
653 | const CFStringRef kSecOIDX509V1SubjectPublicKeyAlgorithm = CFSTR("2.16.840.1.113741.2.1.1.1.9"); | |
654 | const CFStringRef kSecOIDX509V1SubjectPublicKeyAlgorithmParameters = CFSTR("2.16.840.1.113741.2.1.1.1.18"); | |
655 | const CFStringRef kSecOIDX509V1SubjectPublicKeyCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.20.1"); | |
656 | const CFStringRef kSecOIDX509V1ValidityNotAfter = CFSTR("2.16.840.1.113741.2.1.1.1.7"); | |
657 | const CFStringRef kSecOIDX509V1ValidityNotBefore = CFSTR("2.16.840.1.113741.2.1.1.1.6"); | |
658 | const CFStringRef kSecOIDX509V1Version = CFSTR("2.16.840.1.113741.2.1.1.1.2"); | |
659 | const CFStringRef kSecOIDX509V3Certificate = CFSTR("2.16.840.1.113741.2.1.1.1.1"); | |
660 | const CFStringRef kSecOIDX509V3CertificateCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.1.1"); | |
661 | const CFStringRef kSecOIDX509V3CertificateExtensionCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.13.1"); | |
662 | const CFStringRef kSecOIDX509V3CertificateExtensionCritical = CFSTR("2.16.840.1.113741.2.1.1.1.16"); | |
663 | const CFStringRef kSecOIDX509V3CertificateExtensionId = CFSTR("2.16.840.1.113741.2.1.1.1.15"); | |
664 | const CFStringRef kSecOIDX509V3CertificateExtensionStruct = CFSTR("2.16.840.1.113741.2.1.1.1.13"); | |
665 | const CFStringRef kSecOIDX509V3CertificateExtensionType = CFSTR("2.16.840.1.113741.2.1.1.1.19"); | |
666 | const CFStringRef kSecOIDX509V3CertificateExtensionValue = CFSTR("2.16.840.1.113741.2.1.1.1.17"); | |
667 | const CFStringRef kSecOIDX509V3CertificateExtensionsCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.21.1"); | |
668 | const CFStringRef kSecOIDX509V3CertificateExtensionsStruct = CFSTR("2.16.840.1.113741.2.1.1.1.21"); | |
669 | const CFStringRef kSecOIDX509V3CertificateNumberOfExtensions = CFSTR("2.16.840.1.113741.2.1.1.1.14"); | |
670 | const CFStringRef kSecOIDX509V3SignedCertificate = CFSTR("2.16.840.1.113741.2.1.1.1.0"); | |
671 | const CFStringRef kSecOIDX509V3SignedCertificateCStruct = CFSTR("2.16.840.1.113741.2.1.1.1.0.1"); | |
672 | const CFStringRef kSecOIDSRVName = CFSTR("1.3.6.1.5.5.7.8.7"); | |
b1ab9ed8 | 673 |