]>
Commit | Line | Data |
---|---|---|
bac41a7b A |
1 | /* |
2 | * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. | |
3 | * | |
4 | * The contents of this file constitute Original Code as defined in and are | |
5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). | |
6 | * You may not use this file except in compliance with the License. Please obtain | |
7 | * a copy of the License at http://www.apple.com/publicsource and read it before | |
8 | * using this file. | |
9 | * | |
10 | * This Original Code and all software distributed under the License are | |
11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS | |
12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT | |
13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | |
14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the | |
15 | * specific language governing rights and limitations under the License. | |
16 | */ | |
17 | ||
18 | ||
19 | /* | |
df0e469f | 20 | * CLCertExtensions.cpp - extensions support. A major component of DecodedCert. |
bac41a7b A |
21 | * |
22 | * Created 9/8/2000 by Doug Mitchell. | |
23 | * Copyright (c) 2000 by Apple Computer. | |
24 | * | |
25 | */ | |
26 | ||
27 | #include "DecodedCert.h" | |
28 | #include "cldebugging.h" | |
bac41a7b | 29 | #include "CLCertExtensions.h" |
df0e469f A |
30 | #include "CLFieldsCommon.h" |
31 | #include "clNssUtils.h" | |
32 | #include "clNameUtils.h" | |
bac41a7b A |
33 | #include <Security/utilities.h> |
34 | #include <Security/oidscert.h> | |
df0e469f | 35 | #include <Security/oidsattr.h> |
bac41a7b A |
36 | #include <Security/cssmerr.h> |
37 | #include <Security/x509defs.h> | |
38 | #include <Security/certextensions.h> | |
bac41a7b | 39 | #include <Security/globalizer.h> |
df0e469f | 40 | #include <SecurityNssAsn1/certExtensionTemplates.h> |
bac41a7b | 41 | |
bac41a7b A |
42 | |
43 | /*** | |
44 | *** get/set/free functions called out from CertFields.cpp | |
45 | ***/ | |
46 | ||
bac41a7b A |
47 | /*** |
48 | *** KeyUsage | |
49 | *** CDSA format CE_KeyUsage | |
df0e469f | 50 | *** NSS format CSSM_DATA, length 2 |
bac41a7b A |
51 | *** OID CSSMOID_KeyUsage |
52 | ***/ | |
53 | ||
54 | void setFieldKeyUsage( | |
df0e469f | 55 | DecodedItem &cert, |
bac41a7b A |
56 | const CssmData &fieldValue) |
57 | { | |
df0e469f A |
58 | CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, |
59 | false); | |
bac41a7b A |
60 | CE_KeyUsage *cdsaObj = (CE_KeyUsage *)cssmExt->value.parsedValue; |
61 | ||
df0e469f A |
62 | /* Alloc an NSS-style key usage in cert.coder's memory */ |
63 | SecNssCoder &coder = cert.coder(); | |
64 | CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA)); | |
65 | coder.allocItem(*nssObj, 2); | |
66 | ||
67 | /* cdsaObj --> nssObj */ | |
68 | nssObj->Data[0] = (*cdsaObj) >> 8; | |
69 | nssObj->Data[1] = *cdsaObj; | |
70 | ||
71 | /* Adjust length for BIT STRING encoding */ | |
72 | clCssmBitStringToNss(*nssObj); | |
bac41a7b A |
73 | |
74 | /* add to mExtensions */ | |
df0e469f A |
75 | cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, |
76 | NSS_KeyUsageTemplate); | |
bac41a7b A |
77 | } |
78 | ||
79 | ||
80 | bool getFieldKeyUsage( | |
df0e469f | 81 | DecodedItem &cert, |
bac41a7b A |
82 | unsigned index, // which occurrence (0 = first) |
83 | uint32 &numFields, // RETURNED | |
84 | CssmOwnedData &fieldValue) | |
85 | { | |
df0e469f A |
86 | const DecodedExten *decodedExt; |
87 | CSSM_DATA *nssObj; | |
bac41a7b A |
88 | CE_KeyUsage *cdsaObj; |
89 | bool brtn; | |
90 | ||
df0e469f | 91 | brtn = cert.GetExtenTop<CSSM_DATA, CE_KeyUsage>( |
bac41a7b A |
92 | index, |
93 | numFields, | |
94 | fieldValue.allocator, | |
df0e469f A |
95 | CSSMOID_KeyUsage, |
96 | nssObj, | |
bac41a7b A |
97 | cdsaObj, |
98 | decodedExt); | |
99 | if(!brtn) { | |
100 | return false; | |
101 | } | |
102 | ||
df0e469f A |
103 | /* make a copy - can't modify length in place */ |
104 | CSSM_DATA bitString = *nssObj; | |
105 | clNssBitStringToCssm(bitString); | |
106 | unsigned toCopy = bitString.Length; | |
bac41a7b A |
107 | if(toCopy > 2) { |
108 | /* I hope I never see this... */ | |
df0e469f | 109 | clErrorLog("getFieldKeyUsage: KeyUsage larger than 2 bytes!"); |
bac41a7b A |
110 | toCopy = 2; |
111 | } | |
112 | unsigned char bits[2] = {0, 0}; | |
df0e469f | 113 | memmove(bits, bitString.Data, toCopy); |
bac41a7b A |
114 | *cdsaObj = (((unsigned)bits[0]) << 8) | bits[1]; |
115 | ||
116 | /* pass back to caller */ | |
117 | getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); | |
118 | return true; | |
119 | } | |
120 | ||
121 | /*** | |
122 | *** Basic Constraints | |
123 | *** CDSA format: CE_BasicConstraints | |
df0e469f | 124 | *** NSS format CE_BasicConstraints |
bac41a7b A |
125 | *** OID CSSMOID_BasicConstraints |
126 | ***/ | |
127 | ||
128 | void setFieldBasicConstraints( | |
df0e469f | 129 | DecodedItem &cert, |
bac41a7b A |
130 | const CssmData &fieldValue) |
131 | { | |
df0e469f A |
132 | CSSM_X509_EXTENSION_PTR cssmExt = |
133 | verifySetFreeExtension(fieldValue, false); | |
134 | CE_BasicConstraints *cdsaObj = | |
135 | (CE_BasicConstraints *)cssmExt->value.parsedValue; | |
bac41a7b | 136 | |
df0e469f A |
137 | /* Alloc an NSS-style BasicConstraints in cert.coder's memory */ |
138 | SecNssCoder &coder = cert.coder(); | |
139 | NSS_BasicConstraints *nssObj = | |
140 | (NSS_BasicConstraints *)coder.malloc(sizeof(NSS_BasicConstraints)); | |
141 | memset(nssObj, 0, sizeof(*nssObj)); | |
142 | ||
143 | /* cdsaObj --> nssObj */ | |
144 | ArenaAllocator arenaAlloc(coder); | |
145 | clCssmBoolToNss(cdsaObj->cA, nssObj->cA, arenaAlloc); | |
bac41a7b | 146 | if(cdsaObj->pathLenConstraintPresent) { |
df0e469f A |
147 | clIntToData(cdsaObj->pathLenConstraint, |
148 | nssObj->pathLenConstraint, arenaAlloc); | |
bac41a7b A |
149 | } |
150 | ||
151 | /* add to mExtensions */ | |
df0e469f A |
152 | cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, |
153 | NSS_BasicConstraintsTemplate); | |
bac41a7b A |
154 | } |
155 | ||
156 | ||
157 | bool getFieldBasicConstraints( | |
df0e469f | 158 | DecodedItem &cert, |
bac41a7b A |
159 | unsigned index, // which occurrence (0 = first) |
160 | uint32 &numFields, // RETURNED | |
161 | CssmOwnedData &fieldValue) | |
162 | { | |
df0e469f A |
163 | const DecodedExten *decodedExt; |
164 | NSS_BasicConstraints *nssObj; | |
bac41a7b A |
165 | CE_BasicConstraints *cdsaObj; |
166 | bool brtn; | |
167 | ||
df0e469f | 168 | brtn = cert.GetExtenTop<NSS_BasicConstraints, CE_BasicConstraints>( |
bac41a7b A |
169 | index, |
170 | numFields, | |
171 | fieldValue.allocator, | |
df0e469f A |
172 | CSSMOID_BasicConstraints, |
173 | nssObj, | |
bac41a7b A |
174 | cdsaObj, |
175 | decodedExt); | |
176 | if(!brtn) { | |
177 | return false; | |
178 | } | |
179 | ||
df0e469f | 180 | if(nssObj->cA.Data == NULL) { |
bac41a7b A |
181 | /* default */ |
182 | cdsaObj->cA = CSSM_FALSE; | |
183 | } | |
184 | else { | |
df0e469f | 185 | cdsaObj->cA = clNssBoolToCssm(nssObj->cA); |
bac41a7b | 186 | } |
df0e469f A |
187 | if(nssObj->pathLenConstraint.Data == NULL) { |
188 | /* optional */ | |
bac41a7b A |
189 | cdsaObj->pathLenConstraintPresent = CSSM_FALSE; |
190 | cdsaObj->pathLenConstraint = 0; | |
191 | } | |
192 | else { | |
193 | cdsaObj->pathLenConstraintPresent = CSSM_TRUE; | |
df0e469f | 194 | cdsaObj->pathLenConstraint = clDataToInt(nssObj->pathLenConstraint); |
bac41a7b A |
195 | } |
196 | ||
197 | /* pass back to caller */ | |
198 | getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); | |
199 | return true; | |
200 | } | |
201 | ||
202 | /*** | |
203 | *** Extended Key Usage | |
204 | *** CDSA format: CE_ExtendedKeyUsage | |
df0e469f | 205 | *** NSS format: NSS_ExtKeyUsage |
bac41a7b A |
206 | *** OID CSSMOID_ExtendedKeyUsage |
207 | ***/ | |
208 | void setFieldExtKeyUsage( | |
df0e469f | 209 | DecodedItem &cert, |
bac41a7b A |
210 | const CssmData &fieldValue) |
211 | { | |
df0e469f A |
212 | CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, |
213 | false); | |
214 | CE_ExtendedKeyUsage *cdsaObj = | |
215 | (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue; | |
bac41a7b | 216 | |
df0e469f A |
217 | SecNssCoder &coder = cert.coder(); |
218 | NSS_ExtKeyUsage *nssObj = | |
219 | (NSS_ExtKeyUsage *)coder.malloc(sizeof(NSS_ExtKeyUsage)); | |
220 | memset(nssObj, 0, sizeof(*nssObj)); | |
221 | if(cdsaObj->numPurposes != 0) { | |
222 | nssObj->purposes = | |
223 | (CSSM_OID **)clNssNullArray(cdsaObj->numPurposes, coder); | |
224 | } | |
225 | ||
226 | /* cdsaObj --> nssObj, one 'purpose' (OID) at a time */ | |
227 | for(unsigned dex=0; dex<cdsaObj->numPurposes; dex++) { | |
228 | nssObj->purposes[dex] = (CSSM_OID *)coder.malloc(sizeof(CSSM_OID)); | |
229 | coder.allocCopyItem(cdsaObj->purposes[dex], | |
230 | *nssObj->purposes[dex]); | |
bac41a7b A |
231 | } |
232 | ||
233 | /* add to mExtensions */ | |
df0e469f A |
234 | cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, |
235 | NSS_ExtKeyUsageTemplate); | |
bac41a7b A |
236 | } |
237 | ||
238 | bool getFieldExtKeyUsage( | |
df0e469f | 239 | DecodedItem &cert, |
bac41a7b A |
240 | unsigned index, // which occurrence (0 = first) |
241 | uint32 &numFields, // RETURNED | |
242 | CssmOwnedData &fieldValue) | |
243 | { | |
df0e469f A |
244 | const DecodedExten *decodedExt; |
245 | NSS_ExtKeyUsage *nssObj; | |
bac41a7b A |
246 | CE_ExtendedKeyUsage *cdsaObj; |
247 | bool brtn; | |
df0e469f | 248 | CssmAllocator &alloc = fieldValue.allocator; |
bac41a7b | 249 | |
df0e469f | 250 | brtn = cert.GetExtenTop<NSS_ExtKeyUsage, CE_ExtendedKeyUsage>( |
bac41a7b A |
251 | index, |
252 | numFields, | |
df0e469f A |
253 | alloc, |
254 | CSSMOID_ExtendedKeyUsage, | |
255 | nssObj, | |
bac41a7b A |
256 | cdsaObj, |
257 | decodedExt); | |
258 | if(!brtn) { | |
259 | return false; | |
260 | } | |
261 | ||
df0e469f A |
262 | /* nssObj --> cdsaObj, one purpose at a time */ |
263 | unsigned numPurposes = clNssArraySize((const void **)nssObj->purposes); | |
264 | cdsaObj->numPurposes = numPurposes; | |
265 | if(numPurposes) { | |
266 | unsigned len = numPurposes * sizeof(CSSM_OID); | |
267 | cdsaObj->purposes = (CSSM_OID_PTR)alloc.malloc(len); | |
268 | memset(cdsaObj->purposes, 0, len); | |
269 | } | |
270 | for(unsigned dex=0; dex<numPurposes; dex++) { | |
271 | clAllocCopyData(alloc, *nssObj->purposes[dex], cdsaObj->purposes[dex]); | |
bac41a7b | 272 | } |
df0e469f | 273 | |
bac41a7b A |
274 | getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); |
275 | return true; | |
276 | } | |
277 | ||
278 | void freeFieldExtKeyUsage( | |
279 | CssmOwnedData &fieldValue) | |
280 | { | |
281 | CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); | |
282 | CssmAllocator &alloc = fieldValue.allocator; | |
283 | CE_ExtendedKeyUsage *cdsaObj = | |
284 | (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue; | |
285 | unsigned oidDex; | |
286 | for(oidDex=0; oidDex<cdsaObj->numPurposes; oidDex++) { | |
287 | alloc.free(cdsaObj->purposes[oidDex].Data); | |
288 | } | |
289 | alloc.free(cdsaObj->purposes); | |
290 | freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue | |
291 | } | |
292 | ||
293 | /*** | |
294 | *** Subject Key Identifier | |
295 | *** CDSA format: CE_SubjectKeyID, which is just a CSSM_DATA | |
bac41a7b A |
296 | *** OID CSSMOID_SubjectKeyIdentifier |
297 | ***/ | |
298 | ||
299 | void setFieldSubjectKeyId( | |
df0e469f | 300 | DecodedItem &cert, |
bac41a7b A |
301 | const CssmData &fieldValue) |
302 | { | |
df0e469f A |
303 | CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, |
304 | false); | |
bac41a7b | 305 | CE_SubjectKeyID *cdsaObj = (CE_SubjectKeyID *)cssmExt->value.parsedValue; |
df0e469f A |
306 | SecNssCoder &coder = cert.coder(); |
307 | CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA)); | |
308 | coder.allocCopyItem(*cdsaObj, *nssObj); | |
309 | ||
310 | /* add to mExtensions */ | |
311 | cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, | |
312 | NSS_SubjectKeyIdTemplate); | |
bac41a7b A |
313 | } |
314 | ||
315 | bool getFieldSubjectKeyId( | |
df0e469f | 316 | DecodedItem &cert, |
bac41a7b A |
317 | unsigned index, // which occurrence (0 = first) |
318 | uint32 &numFields, // RETURNED | |
319 | CssmOwnedData &fieldValue) | |
320 | { | |
df0e469f A |
321 | const DecodedExten *decodedExt; |
322 | CSSM_DATA *nssObj; | |
bac41a7b A |
323 | CE_SubjectKeyID *cdsaObj; |
324 | bool brtn; | |
df0e469f | 325 | CssmAllocator &alloc = fieldValue.allocator; |
bac41a7b | 326 | |
df0e469f | 327 | brtn = cert.GetExtenTop<CSSM_DATA, CE_SubjectKeyID>( |
bac41a7b A |
328 | index, |
329 | numFields, | |
df0e469f A |
330 | alloc, |
331 | CSSMOID_SubjectKeyIdentifier, | |
332 | nssObj, | |
bac41a7b A |
333 | cdsaObj, |
334 | decodedExt); | |
335 | if(!brtn) { | |
336 | return false; | |
337 | } | |
df0e469f A |
338 | |
339 | /* if this fails, we're out of sync with nssExtenInfo[] in | |
340 | * CLFieldsCommon.cpp */ | |
341 | assert(nssObj != NULL); | |
342 | clAllocCopyData(alloc, *nssObj, *cdsaObj); | |
bac41a7b A |
343 | getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); |
344 | return true; | |
345 | } | |
346 | ||
347 | void freeFieldSubjectKeyId ( | |
348 | CssmOwnedData &fieldValue) | |
349 | { | |
350 | CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); | |
351 | CssmAllocator &alloc = fieldValue.allocator; | |
352 | CE_SubjectKeyID *cdsaObj = (CE_SubjectKeyID *)cssmExt->value.parsedValue; | |
353 | alloc.free(cdsaObj->Data); | |
354 | freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue | |
355 | } | |
356 | ||
357 | /*** | |
358 | *** Authority Key Identifier | |
359 | *** CDSA format: CE_AuthorityKeyID | |
df0e469f | 360 | *** NSS format: NSS_AuthorityKeyId |
bac41a7b A |
361 | *** OID CSSMOID_AuthorityKeyIdentifier |
362 | ***/ | |
363 | ||
364 | void setFieldAuthorityKeyId( | |
df0e469f | 365 | DecodedItem &cert, |
bac41a7b A |
366 | const CssmData &fieldValue) |
367 | { | |
df0e469f A |
368 | CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, |
369 | false); | |
370 | CE_AuthorityKeyID *cdsaObj = | |
371 | (CE_AuthorityKeyID *)cssmExt->value.parsedValue; | |
bac41a7b | 372 | |
df0e469f A |
373 | /* Alloc an NSS-style AuthorityKeyId in cert.coder's memory */ |
374 | SecNssCoder &coder = cert.coder(); | |
375 | NSS_AuthorityKeyId *nssObj = | |
376 | (NSS_AuthorityKeyId *)coder.malloc(sizeof(NSS_AuthorityKeyId)); | |
377 | memset(nssObj, 0, sizeof(*nssObj)); | |
378 | ||
379 | /* convert caller's CDSA-style CE_AuthorityKeyID to NSS */ | |
380 | CL_cssmAuthorityKeyIdToNss(*cdsaObj, *nssObj, coder); | |
381 | ||
382 | /* add to mExtensions */ | |
383 | cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, | |
384 | NSS_AuthorityKeyIdTemplate); | |
bac41a7b A |
385 | } |
386 | ||
387 | bool getFieldAuthorityKeyId( | |
df0e469f | 388 | DecodedItem &cert, |
bac41a7b A |
389 | unsigned index, // which occurrence (0 = first) |
390 | uint32 &numFields, // RETURNED | |
391 | CssmOwnedData &fieldValue) | |
392 | { | |
df0e469f A |
393 | const DecodedExten *decodedExt; |
394 | NSS_AuthorityKeyId *nssObj; | |
bac41a7b A |
395 | CE_AuthorityKeyID *cdsaObj; |
396 | bool brtn; | |
397 | CssmAllocator &alloc = fieldValue.allocator; | |
398 | ||
df0e469f | 399 | brtn = cert.GetExtenTop<NSS_AuthorityKeyId, CE_AuthorityKeyID>( |
bac41a7b A |
400 | index, |
401 | numFields, | |
402 | alloc, | |
df0e469f A |
403 | CSSMOID_AuthorityKeyIdentifier, |
404 | nssObj, | |
bac41a7b A |
405 | cdsaObj, |
406 | decodedExt); | |
407 | if(!brtn) { | |
408 | return false; | |
409 | } | |
df0e469f A |
410 | assert(nssObj != NULL); |
411 | ||
412 | /* nssObj --> cdsaObj */ | |
413 | CL_nssAuthorityKeyIdToCssm(*nssObj, *cdsaObj, cert.coder(), alloc); | |
bac41a7b | 414 | |
bac41a7b A |
415 | getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); |
416 | return true; | |
417 | } | |
418 | ||
bac41a7b A |
419 | void freeFieldAuthorityKeyId ( |
420 | CssmOwnedData &fieldValue) | |
421 | { | |
422 | CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); | |
423 | CssmAllocator &alloc = fieldValue.allocator; | |
424 | CE_AuthorityKeyID *cdsaObj = (CE_AuthorityKeyID *)cssmExt->value.parsedValue; | |
df0e469f | 425 | CL_freeAuthorityKeyId(*cdsaObj, alloc); |
bac41a7b A |
426 | freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue |
427 | } | |
428 | ||
429 | /*** | |
df0e469f | 430 | *** Subject/Issuer alternate name |
bac41a7b | 431 | *** CDSA Format: CE_GeneralNames |
df0e469f A |
432 | *** NSS format: NSS_GeneralNames |
433 | *** OID: CSSMOID_SubjectAltName, CSSMOID_IssuerAltName | |
bac41a7b | 434 | ***/ |
df0e469f A |
435 | void setFieldSubjIssuerAltName( |
436 | DecodedItem &cert, | |
bac41a7b A |
437 | const CssmData &fieldValue) |
438 | { | |
df0e469f A |
439 | CSSM_X509_EXTENSION_PTR cssmExt = |
440 | verifySetFreeExtension(fieldValue, false); | |
bac41a7b | 441 | CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue; |
df0e469f A |
442 | |
443 | /* Alloc an NSS-style GeneralNames in cert.coder's memory */ | |
444 | SecNssCoder &coder = cert.coder(); | |
445 | NSS_GeneralNames *nssObj = | |
446 | (NSS_GeneralNames *)coder.malloc(sizeof(NSS_GeneralNames)); | |
447 | memset(nssObj, 0, sizeof(*nssObj)); | |
448 | ||
449 | /* cdsaObj --> nssObj */ | |
450 | CL_cssmGeneralNamesToNss(*cdsaObj, *nssObj, coder); | |
451 | ||
452 | /* add to mExtensions */ | |
453 | cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, | |
454 | NSS_GeneralNamesTemplate); | |
bac41a7b A |
455 | } |
456 | ||
457 | bool getFieldSubjAltName( | |
df0e469f A |
458 | DecodedItem &cert, |
459 | unsigned index, // which occurrence (0 = first) | |
460 | uint32 &numFields, // RETURNED | |
461 | CssmOwnedData &fieldValue) | |
462 | { | |
463 | const DecodedExten *decodedExt; | |
464 | NSS_GeneralNames *nssObj; | |
465 | CE_GeneralNames *cdsaObj; | |
466 | bool brtn; | |
467 | ||
468 | brtn = cert.GetExtenTop<NSS_GeneralNames, CE_GeneralNames>( | |
469 | index, | |
470 | numFields, | |
471 | fieldValue.allocator, | |
472 | CSSMOID_SubjectAltName, | |
473 | nssObj, | |
474 | cdsaObj, | |
475 | decodedExt); | |
476 | if(!brtn) { | |
477 | return false; | |
478 | } | |
479 | CL_nssGeneralNamesToCssm(*nssObj, *cdsaObj, | |
480 | cert.coder(), fieldValue.allocator); | |
481 | getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); | |
482 | return true; | |
483 | } | |
484 | ||
485 | bool getFieldIssuerAltName( | |
486 | DecodedItem &cert, | |
bac41a7b A |
487 | unsigned index, // which occurrence (0 = first) |
488 | uint32 &numFields, // RETURNED | |
489 | CssmOwnedData &fieldValue) | |
490 | { | |
df0e469f A |
491 | const DecodedExten *decodedExt; |
492 | NSS_GeneralNames *nssObj; | |
493 | CE_GeneralNames *cdsaObj; | |
bac41a7b A |
494 | bool brtn; |
495 | ||
df0e469f | 496 | brtn = cert.GetExtenTop<NSS_GeneralNames, CE_GeneralNames>( |
bac41a7b A |
497 | index, |
498 | numFields, | |
499 | fieldValue.allocator, | |
df0e469f A |
500 | CSSMOID_IssuerAltName, |
501 | nssObj, | |
bac41a7b A |
502 | cdsaObj, |
503 | decodedExt); | |
504 | if(!brtn) { | |
505 | return false; | |
506 | } | |
df0e469f A |
507 | CL_nssGeneralNamesToCssm(*nssObj, *cdsaObj, |
508 | cert.coder(), fieldValue.allocator); | |
bac41a7b A |
509 | getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); |
510 | return true; | |
511 | } | |
512 | ||
df0e469f | 513 | void freeFieldSubjIssuerAltName ( |
bac41a7b A |
514 | CssmOwnedData &fieldValue) |
515 | { | |
516 | CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); | |
517 | CssmAllocator &alloc = fieldValue.allocator; | |
518 | CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue; | |
df0e469f | 519 | CL_freeCssmGeneralNames(cdsaObj, alloc); |
bac41a7b A |
520 | freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue |
521 | } | |
522 | ||
523 | /*** | |
524 | *** Certificate Policies | |
525 | *** CDSA Format: CE_CertPolicies | |
df0e469f | 526 | *** NSS format : NSS_CertPolicies |
bac41a7b A |
527 | *** OID: CSSMOID_CertificatePolicies |
528 | ***/ | |
529 | ||
530 | #define MAX_IA5_NAME_SIZE 1024 | |
531 | ||
532 | void setFieldCertPolicies( | |
df0e469f | 533 | DecodedItem &cert, |
bac41a7b A |
534 | const CssmData &fieldValue) |
535 | { | |
df0e469f A |
536 | CSSM_X509_EXTENSION_PTR cssmExt = |
537 | verifySetFreeExtension(fieldValue, false); | |
538 | SecNssCoder &coder = cert.coder(); | |
539 | NSS_CertPolicies *nssObj = | |
540 | (NSS_CertPolicies *)coder.malloc(sizeof(NSS_CertPolicies)); | |
541 | memset(nssObj, 0, sizeof(NSS_CertPolicies)); | |
542 | CE_CertPolicies *cdsaObj = | |
543 | (CE_CertPolicies *)cssmExt->value.parsedValue; | |
bac41a7b | 544 | |
df0e469f A |
545 | if(cdsaObj->numPolicies) { |
546 | nssObj->policies = | |
547 | (NSS_PolicyInformation **)clNssNullArray( | |
548 | cdsaObj->numPolicies, coder); | |
549 | } | |
bac41a7b A |
550 | for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) { |
551 | CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex]; | |
df0e469f A |
552 | NSS_PolicyInformation *nPolInfo = (NSS_PolicyInformation *) |
553 | coder.malloc(sizeof(NSS_PolicyInformation)); | |
554 | memset(nPolInfo, 0, sizeof(*nPolInfo)); | |
555 | nssObj->policies[polDex] = nPolInfo; | |
556 | ||
557 | coder.allocCopyItem(cPolInfo->certPolicyId, nPolInfo->certPolicyId); | |
558 | ||
559 | unsigned numQual = cPolInfo->numPolicyQualifiers; | |
560 | if(numQual != 0) { | |
561 | nPolInfo->policyQualifiers = | |
562 | (NSS_PolicyQualifierInfo **)clNssNullArray(numQual, | |
563 | coder); | |
bac41a7b | 564 | } |
df0e469f A |
565 | for(unsigned qualDex=0; qualDex<numQual; qualDex++) { |
566 | CE_PolicyQualifierInfo *cQualInfo = | |
567 | &cPolInfo->policyQualifiers[qualDex]; | |
568 | NSS_PolicyQualifierInfo *nQualInfo = | |
569 | (NSS_PolicyQualifierInfo *)coder.malloc( | |
570 | sizeof(NSS_PolicyQualifierInfo)); | |
571 | memset(nQualInfo, 0, sizeof(NSS_PolicyQualifierInfo)); | |
572 | nPolInfo->policyQualifiers[qualDex] = nQualInfo; | |
bac41a7b | 573 | |
df0e469f A |
574 | /* |
575 | * OK we're at the lowest level. | |
576 | * policyQualifierId == id_qt_cps: qualifier is | |
577 | * an IA5 string, incoming data is its contents. | |
578 | * Else incoming data is an encoded blob we pass on directly. | |
bac41a7b | 579 | */ |
df0e469f A |
580 | coder.allocCopyItem(cQualInfo->policyQualifierId, |
581 | nQualInfo->policyQualifierId); | |
582 | ||
583 | if(clCompareCssmData(&cQualInfo->policyQualifierId, | |
584 | &CSSMOID_QT_CPS)) { | |
585 | if(coder.encodeItem(&cQualInfo->qualifier, | |
586 | SEC_IA5StringTemplate, | |
587 | nQualInfo->qualifier)) { | |
588 | clErrorLog("setFieldCertPOlicies: IA5 encode error\n"); | |
589 | CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); | |
590 | } | |
bac41a7b A |
591 | } |
592 | else { | |
df0e469f A |
593 | /* uninterpreted, copy over directly */ |
594 | coder.allocCopyItem(cQualInfo->qualifier, | |
595 | nQualInfo->qualifier); | |
bac41a7b | 596 | } |
bac41a7b A |
597 | } /* for each qualifier */ |
598 | } /* for each policy */ | |
599 | ||
600 | /* add to mExtensions */ | |
df0e469f A |
601 | cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, |
602 | NSS_CertPoliciesTemplate); | |
bac41a7b A |
603 | } |
604 | ||
df0e469f A |
605 | bool getFieldCertPolicies( |
606 | DecodedItem &cert, | |
bac41a7b A |
607 | unsigned index, // which occurrence (0 = first) |
608 | uint32 &numFields, // RETURNED | |
609 | CssmOwnedData &fieldValue) | |
610 | { | |
df0e469f A |
611 | const DecodedExten *decodedExt; |
612 | NSS_CertPolicies *nssObj; | |
bac41a7b A |
613 | CE_CertPolicies *cdsaObj; |
614 | bool brtn; | |
615 | CssmAllocator &alloc = fieldValue.allocator; | |
df0e469f | 616 | brtn = cert.GetExtenTop<NSS_CertPolicies, CE_CertPolicies>( |
bac41a7b A |
617 | index, |
618 | numFields, | |
619 | fieldValue.allocator, | |
df0e469f A |
620 | CSSMOID_CertificatePolicies, |
621 | nssObj, | |
bac41a7b A |
622 | cdsaObj, |
623 | decodedExt); | |
624 | if(!brtn) { | |
625 | return false; | |
626 | } | |
df0e469f A |
627 | assert(nssObj != NULL); |
628 | ||
629 | memset(cdsaObj, 0, sizeof(*cdsaObj)); | |
630 | cdsaObj->numPolicies = | |
631 | clNssArraySize((const void **)nssObj->policies); | |
bac41a7b | 632 | unsigned sz = cdsaObj->numPolicies * sizeof(CE_PolicyInformation); |
df0e469f A |
633 | if(sz) { |
634 | cdsaObj->policies = (CE_PolicyInformation *)alloc.malloc(sz); | |
635 | memset(cdsaObj->policies, 0, sz); | |
636 | } | |
637 | ||
bac41a7b A |
638 | for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) { |
639 | CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex]; | |
df0e469f A |
640 | NSS_PolicyInformation *nPolInfo = nssObj->policies[polDex]; |
641 | clAllocCopyData(alloc, nPolInfo->certPolicyId, | |
642 | cPolInfo->certPolicyId); | |
643 | if(nPolInfo->policyQualifiers == NULL) { | |
bac41a7b A |
644 | continue; |
645 | } | |
df0e469f A |
646 | |
647 | cPolInfo->numPolicyQualifiers = | |
648 | clNssArraySize((const void **)nPolInfo->policyQualifiers); | |
649 | sz = cPolInfo->numPolicyQualifiers * | |
650 | sizeof(CE_PolicyQualifierInfo); | |
bac41a7b | 651 | cPolInfo->policyQualifiers = (CE_PolicyQualifierInfo *) |
df0e469f A |
652 | alloc.malloc(sz); |
653 | memset(cPolInfo->policyQualifiers, 0, sz); | |
654 | ||
655 | for(unsigned qualDex=0; qualDex<cPolInfo->numPolicyQualifiers; | |
656 | qualDex++) { | |
657 | NSS_PolicyQualifierInfo *nQualInfo = | |
658 | nPolInfo->policyQualifiers[qualDex]; | |
659 | CE_PolicyQualifierInfo *cQualInfo = | |
660 | &cPolInfo->policyQualifiers[qualDex]; | |
bac41a7b A |
661 | |
662 | /* | |
663 | * leaf. | |
df0e469f A |
664 | * policyQualifierId == CSSMOID_QT_CPS : |
665 | * IA5String - decode and return contents. | |
666 | * Else return whole thing. | |
bac41a7b | 667 | */ |
df0e469f A |
668 | clAllocCopyData(alloc, nQualInfo->policyQualifierId, |
669 | cQualInfo->policyQualifierId); | |
670 | CSSM_DATA toCopy = nQualInfo->qualifier; | |
671 | if(clCompareCssmData(&nQualInfo->policyQualifierId, | |
672 | &CSSMOID_QT_CPS)) { | |
673 | /* decode as IA5String to temp memory */ | |
674 | toCopy.Data = NULL; | |
675 | toCopy.Length = 0; | |
676 | if(cert.coder().decodeItem(nQualInfo->qualifier, | |
677 | SEC_IA5StringTemplate, | |
678 | &toCopy)) { | |
679 | clErrorLog("***getCertPolicies: bad IA5String!\n"); | |
680 | CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); | |
681 | } | |
bac41a7b | 682 | } |
df0e469f A |
683 | /* else copy out nQualInfo->qualifier */ |
684 | clAllocCopyData(alloc, toCopy, cQualInfo->qualifier); | |
685 | } /* for each qualifier */ | |
686 | } /* for each policy info */ | |
bac41a7b A |
687 | getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); |
688 | return true; | |
689 | } | |
690 | ||
691 | void freeFieldCertPolicies ( | |
692 | CssmOwnedData &fieldValue) | |
693 | { | |
694 | CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); | |
695 | CssmAllocator &alloc = fieldValue.allocator; | |
696 | CE_CertPolicies *cdsaObj = (CE_CertPolicies *)cssmExt->value.parsedValue; | |
697 | for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) { | |
698 | CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex]; | |
699 | alloc.free(cPolInfo->certPolicyId.Data); | |
df0e469f A |
700 | for(unsigned qualDex=0; |
701 | qualDex<cPolInfo->numPolicyQualifiers; | |
702 | qualDex++) { | |
703 | CE_PolicyQualifierInfo *cQualInfo = | |
704 | &cPolInfo->policyQualifiers[qualDex]; | |
bac41a7b A |
705 | alloc.free(cQualInfo->policyQualifierId.Data); |
706 | alloc.free(cQualInfo->qualifier.Data); | |
707 | } | |
708 | alloc.free(cPolInfo->policyQualifiers); | |
709 | } | |
710 | alloc.free(cdsaObj->policies); | |
df0e469f A |
711 | freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, |
712 | // BERvalue | |
bac41a7b A |
713 | } |
714 | ||
715 | /*** | |
716 | *** Netscape cert type | |
717 | *** CDSA Format: CE_NetscapeCertType (a uint16) | |
df0e469f | 718 | *** NSS format CSSM_DATA, length 2 |
bac41a7b A |
719 | *** OID: CSSMOID_NetscapeCertType |
720 | ***/ | |
721 | void setFieldNetscapeCertType( | |
df0e469f | 722 | DecodedItem &cert, |
bac41a7b A |
723 | const CssmData &fieldValue) |
724 | { | |
df0e469f A |
725 | CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, |
726 | false); | |
727 | CE_NetscapeCertType *cdsaObj = | |
728 | (CE_NetscapeCertType *)cssmExt->value.parsedValue; | |
729 | ||
730 | /* Alloc an NSS-style key usage in cert.coder's memory */ | |
731 | SecNssCoder &coder = cert.coder(); | |
732 | CSSM_DATA *nssObj = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA)); | |
733 | coder.allocItem(*nssObj, 2); | |
734 | ||
735 | /* cdsaObj --> nssObj */ | |
736 | nssObj->Data[0] = (*cdsaObj) >> 8; | |
737 | nssObj->Data[1] = *cdsaObj; | |
bac41a7b | 738 | |
df0e469f A |
739 | /* Adjust length for BIT STRING encoding */ |
740 | clCssmBitStringToNss(*nssObj); | |
bac41a7b A |
741 | |
742 | /* add to mExtensions */ | |
df0e469f A |
743 | cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, |
744 | NSS_NetscapeCertTypeTemplate); | |
bac41a7b A |
745 | } |
746 | ||
747 | bool getFieldNetscapeCertType( | |
df0e469f | 748 | DecodedItem &cert, |
bac41a7b A |
749 | unsigned index, // which occurrence (0 = first) |
750 | uint32 &numFields, // RETURNED | |
751 | CssmOwnedData &fieldValue) | |
752 | { | |
df0e469f A |
753 | const DecodedExten *decodedExt; |
754 | CSSM_DATA *nssObj; | |
bac41a7b A |
755 | CE_NetscapeCertType *cdsaObj; |
756 | bool brtn; | |
757 | ||
df0e469f | 758 | brtn = cert.GetExtenTop<CSSM_DATA, CE_NetscapeCertType>( |
bac41a7b A |
759 | index, |
760 | numFields, | |
761 | fieldValue.allocator, | |
df0e469f A |
762 | CSSMOID_NetscapeCertType, |
763 | nssObj, | |
bac41a7b A |
764 | cdsaObj, |
765 | decodedExt); | |
766 | if(!brtn) { | |
767 | return false; | |
768 | } | |
df0e469f A |
769 | |
770 | /* make a copy - can't modify length in place */ | |
771 | CSSM_DATA bitString = *nssObj; | |
772 | clNssBitStringToCssm(bitString); | |
773 | unsigned toCopy = bitString.Length; | |
bac41a7b A |
774 | if(toCopy > 2) { |
775 | /* I hope I never see this... */ | |
df0e469f | 776 | clErrorLog("getFieldKeyUsage: CertType larger than 2 bytes!"); |
bac41a7b A |
777 | toCopy = 2; |
778 | } | |
779 | unsigned char bits[2] = {0, 0}; | |
df0e469f | 780 | memmove(bits, bitString.Data, toCopy); |
bac41a7b | 781 | *cdsaObj = (((unsigned)bits[0]) << 8) | bits[1]; |
df0e469f A |
782 | |
783 | /* pass back to caller */ | |
bac41a7b A |
784 | getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); |
785 | return true; | |
786 | } | |
787 | ||
788 | /*** | |
df0e469f A |
789 | *** CRL Distribution points |
790 | *** CDSA Format: CE_CRLDistPointsSyntax | |
791 | *** NSS format: NSS_CRLDistributionPoints | |
792 | *** OID: CSSMOID_CrlDistributionPoints | |
bac41a7b | 793 | ***/ |
df0e469f A |
794 | void setFieldCrlDistPoints( |
795 | DecodedItem &cert, | |
796 | const CssmData &fieldValue) | |
bac41a7b | 797 | { |
df0e469f A |
798 | CSSM_X509_EXTENSION_PTR cssmExt = |
799 | verifySetFreeExtension(fieldValue, false); | |
800 | CE_CRLDistPointsSyntax *cdsaObj = | |
801 | (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue; | |
802 | SecNssCoder &coder = cert.coder(); | |
803 | NSS_CRLDistributionPoints *nssObj = | |
804 | (NSS_CRLDistributionPoints *)coder.malloc( | |
805 | sizeof(NSS_CRLDistributionPoints)); | |
806 | ||
807 | CL_cssmDistPointsToNss(*cdsaObj, *nssObj, coder); | |
808 | cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false, | |
809 | NSS_CRLDistributionPointsTemplate); | |
bac41a7b A |
810 | } |
811 | ||
df0e469f A |
812 | bool getFieldCrlDistPoints( |
813 | DecodedItem &cert, | |
bac41a7b A |
814 | unsigned index, // which occurrence (0 = first) |
815 | uint32 &numFields, // RETURNED | |
816 | CssmOwnedData &fieldValue) | |
817 | { | |
df0e469f A |
818 | const DecodedExten *decodedExt; |
819 | NSS_CRLDistributionPoints *nssObj; | |
820 | CE_CRLDistPointsSyntax *cdsaObj; | |
821 | bool brtn; | |
bac41a7b | 822 | CssmAllocator &alloc = fieldValue.allocator; |
bac41a7b | 823 | |
df0e469f A |
824 | brtn = cert.GetExtenTop<NSS_CRLDistributionPoints, |
825 | CE_CRLDistPointsSyntax>( | |
bac41a7b A |
826 | index, |
827 | numFields, | |
df0e469f A |
828 | alloc, |
829 | CSSMOID_CrlDistributionPoints, | |
830 | nssObj, | |
bac41a7b A |
831 | cdsaObj, |
832 | decodedExt); | |
833 | if(!brtn) { | |
834 | return false; | |
835 | } | |
df0e469f A |
836 | assert(nssObj != NULL); |
837 | CL_nssDistPointsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc); | |
bac41a7b A |
838 | getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); |
839 | return true; | |
840 | } | |
841 | ||
df0e469f | 842 | void freeFieldCrlDistPoints ( |
bac41a7b A |
843 | CssmOwnedData &fieldValue) |
844 | { | |
845 | CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false); | |
846 | CssmAllocator &alloc = fieldValue.allocator; | |
df0e469f A |
847 | CE_CRLDistPointsSyntax *cdsaObj = |
848 | (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue; | |
849 | CL_freeCssmDistPoints(cdsaObj, alloc); | |
bac41a7b A |
850 | freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue |
851 | } | |
852 | ||
df0e469f | 853 |