]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. | |
427c49bc | 3 | * |
b1ab9ed8 A |
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. | |
427c49bc | 9 | * |
b1ab9ed8 A |
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 | /* | |
427c49bc A |
20 | * DecodedItem.cpp - class representing the common portions of |
21 | * NSS-format decoded certs and CRLs, with extensions parsed and | |
b1ab9ed8 A |
22 | * decoded (still in NSS format). |
23 | */ | |
24 | ||
25 | #include "DecodedItem.h" | |
26 | #include "cldebugging.h" | |
427c49bc | 27 | #include "AppleX509CLSession.h" |
b1ab9ed8 A |
28 | #include "CSPAttacher.h" |
29 | #include "CLFieldsCommon.h" | |
30 | #include "clNssUtils.h" | |
31 | #include "clNameUtils.h" | |
427c49bc | 32 | #include <security_asn1/SecAsn1Types.h> |
b1ab9ed8 A |
33 | #include <Security/cssmapple.h> |
34 | #include <Security/oidscert.h> | |
35 | ||
36 | #define MIN_EXTENSIONS 4 // initial size of *mExtensions | |
37 | ||
38 | DecodedExten::DecodedExten( | |
39 | const CSSM_OID &extnId, // copied | |
40 | bool critical, | |
427c49bc | 41 | void *nssObj, // NSS_KeyUsage, NSS_BasicConstraints, |
b1ab9ed8 A |
42 | // etc. NOT COPIED, exists in same |
43 | // memory space as coder | |
44 | bool berEncoded, // indicates unknown extension which we | |
45 | // do not BER-decode when parsing a cert | |
46 | const SecAsn1Template *templ, // to decode/encode if !berEncoded | |
47 | SecNssCoder &coder, // all local allocs from here | |
48 | const CSSM_DATA *rawExtn) // NSS_CertExtension.value, copied to | |
49 | // mRawExtn | |
50 | : mCritical(critical), | |
51 | mNssObj(nssObj), | |
52 | mBerEncoded(berEncoded), | |
53 | mTempl(templ), | |
54 | mCoder(coder), | |
55 | mRawExtn(NULL) | |
56 | { | |
57 | coder.allocCopyItem(extnId, mExtnId); | |
58 | if(rawExtn) { | |
59 | mRawExtn = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA)); | |
60 | coder.allocCopyItem(*rawExtn, *mRawExtn); | |
61 | } | |
62 | } | |
63 | ||
64 | DecodedExten::~DecodedExten() | |
65 | { | |
66 | /* the only stuff we allocated was in the coder pool and will be freed | |
67 | * when coder is freed */ | |
68 | } | |
69 | ||
427c49bc | 70 | /* |
b1ab9ed8 | 71 | * Given a fully encoded BER object, create a CSSM_X509EXT_TAGandVALUE |
427c49bc | 72 | * representing it. We malloc the CSSM_X509EXT_TAGandVALUE itself using |
b1ab9ed8 | 73 | * specified allocator, but the referent (in CSSM_X509EXT_TAGandVALUE.value) |
427c49bc | 74 | * merely points to data inside the berValue. |
b1ab9ed8 A |
75 | */ |
76 | CSSM_X509EXT_TAGandVALUE *DecodedExten::createTagAndValue( | |
77 | const CSSM_DATA &berValue, | |
78 | Allocator &alloc) const | |
79 | { | |
80 | if((berValue.Data == NULL) || (berValue.Length == 0)) { | |
81 | return NULL; | |
82 | } | |
83 | CSSM_X509EXT_TAGandVALUE *tv = (CSSM_X509EXT_TAGandVALUE *) | |
84 | alloc.malloc(sizeof(CSSM_X509EXT_TAGandVALUE)); | |
427c49bc A |
85 | |
86 | // Important: by the time we get called, the extension data | |
87 | // has already been deconstructed, and the raw value we are | |
88 | // handed in berValue does not include ASN.1 type or length. | |
89 | // Since createTagAndValue is only called in the case where | |
90 | // the contents are unknown (and thus opaque), always treat | |
91 | // as an octet string. | |
92 | ||
93 | tv->type = SEC_ASN1_OCTET_STRING; | |
94 | tv->value.Length = berValue.Length; | |
95 | tv->value.Data = berValue.Data; | |
96 | return tv; | |
97 | ||
98 | #if 0 | |
b1ab9ed8 | 99 | tv->type = berValue.Data[0]; |
427c49bc A |
100 | |
101 | /* | |
102 | * length of length is variable; ASN spec says it can actually be up to | |
b1ab9ed8 A |
103 | * 127 bytes, but we only have room for 32 bits! |
104 | */ | |
105 | const uint8 *lp = berValue.Data + 1; | |
106 | uint8 len1 = *lp; | |
107 | if((len1 & 0x80) == 0) { | |
108 | /* short form */ | |
109 | tv->value.Length = len1; | |
110 | tv->value.Data = const_cast<uint8 *>(lp + 1); | |
111 | return tv; | |
112 | } | |
427c49bc | 113 | |
b1ab9ed8 A |
114 | unsigned numLenBytes = len1 & 0x7f; |
115 | if(numLenBytes > 4) { | |
116 | clErrorLog("createTagAndValue: impossible length of length (%u)\n", numLenBytes); | |
117 | alloc.free(tv); | |
118 | CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); | |
119 | } | |
427c49bc | 120 | |
b1ab9ed8 A |
121 | uint32 len = 0; |
122 | lp++; // points to first length byte | |
123 | for(uint32 dex=0; dex<numLenBytes; dex++) { | |
124 | len <<= 8; | |
125 | len += *lp; | |
126 | lp++; | |
127 | } | |
128 | tv->value.Length = len; | |
129 | tv->value.Data = const_cast<uint8 *>(lp); | |
130 | return tv; | |
427c49bc | 131 | #endif |
b1ab9ed8 A |
132 | } |
133 | ||
134 | /* | |
135 | * Convert this extension to a CSSM_X509_EXTENSION, in the specified | |
136 | * (app-level) alloc space, after its contents have | |
137 | * been converted to a native CDSA object (CE_KeyUsage, etc.). | |
138 | */ | |
139 | void DecodedExten::convertToCdsa( | |
140 | void *cdsaObj, // e.g. CE_KeyUsage | |
141 | // CSSM_DATA_PTR for berEncoded | |
142 | CSSM_X509_EXTENSION_PTR cssmExt, // contents RETURNED | |
143 | Allocator &alloc) const | |
144 | { | |
145 | clAllocCopyData(alloc, mExtnId, cssmExt->extnId); | |
146 | cssmExt->critical = mCritical ? CSSM_TRUE : CSSM_FALSE; | |
427c49bc A |
147 | |
148 | /* | |
b1ab9ed8 | 149 | * in either case copy the raw extension data if we have it (we may not |
427c49bc | 150 | * have it if this was created via setField). |
b1ab9ed8 A |
151 | */ |
152 | if(mRawExtn) { | |
153 | clAllocCopyData(alloc, *mRawExtn, cssmExt->BERvalue); | |
154 | } | |
155 | else { | |
156 | cssmExt->BERvalue.Data = NULL; | |
157 | cssmExt->BERvalue.Length = 0; | |
158 | } | |
159 | if(mBerEncoded) { | |
160 | /* an extension we never parsed or understood */ | |
161 | assert(cdsaObj == NULL); | |
162 | cssmExt->format = CSSM_X509_DATAFORMAT_ENCODED; | |
163 | cssmExt->value.tagAndValue = createTagAndValue(cssmExt->BERvalue, alloc); | |
164 | } | |
165 | else { | |
166 | /* caller sees parsed version plus raw BER-encoded bytes */ | |
167 | assert(cdsaObj != NULL); | |
168 | cssmExt->format = CSSM_X509_DATAFORMAT_PARSED; | |
169 | /* in app alloc's space, mallocd by getField*() */ | |
170 | cssmExt->value.parsedValue = cdsaObj; | |
171 | } | |
172 | } | |
173 | ||
174 | /* | |
175 | * Convert a DecodedExten to a CSSM_X509_EXTENSION. This includes | |
427c49bc A |
176 | * the mapping of the extnId to a known CDSA type and type and doing the |
177 | * actual NSS-to-CDSA conversion. At the time this function is | |
178 | * called, the DecodedExten either has a valid mNssObj, or it's an | |
b1ab9ed8 | 179 | * unknown extension type in which case mNssObj is an AsnOcts containing |
427c49bc A |
180 | * the opaquely DER-encoded extension value. |
181 | * | |
b1ab9ed8 A |
182 | * Currently only used when decoding a CRL and converting it en masse |
183 | * to CDSA. | |
184 | */ | |
185 | template<class NssType, class CdsaType> | |
186 | void nssToCssm( | |
187 | const DecodedExten &decodedExt, | |
188 | NssType *&nssObj, // RETURNED | |
189 | CdsaType *&cdsaObj, // mallocd and RETURNED | |
190 | Allocator &alloc) | |
191 | { | |
427c49bc | 192 | nssObj = (NssType *)(decodedExt.nssObj()); |
b1ab9ed8 A |
193 | assert(nssObj != NULL); |
194 | cdsaObj = (CdsaType *)alloc.malloc(sizeof(CdsaType)); | |
195 | memset(cdsaObj, 0, sizeof(CdsaType)); | |
196 | } | |
197 | ||
198 | void DecodedExten::parse( | |
199 | CSSM_X509_EXTENSION_PTR cssmExt, // mallocd by caller, RETURNED | |
200 | Allocator &alloc) const | |
201 | { | |
202 | void *vCdsaObj = NULL; | |
203 | if(mBerEncoded) { | |
204 | /* non-understood extension */ | |
205 | convertToCdsa(NULL, cssmExt, alloc); | |
206 | return; | |
207 | } | |
208 | if(clCompareCssmData(&mExtnId, &CSSMOID_AuthorityKeyIdentifier)) { | |
209 | CE_AuthorityKeyID *cdsaObj; | |
210 | NSS_AuthorityKeyId *nssObj; | |
211 | nssToCssm<NSS_AuthorityKeyId, CE_AuthorityKeyID>( | |
212 | *this, | |
213 | nssObj, | |
214 | cdsaObj, | |
215 | alloc); | |
216 | CL_nssAuthorityKeyIdToCssm(*nssObj, *cdsaObj, mCoder, alloc); | |
217 | vCdsaObj = cdsaObj; | |
218 | } | |
219 | /* same encoding (uint32) for all of these: */ | |
220 | else if(clCompareCssmData(&mExtnId, &CSSMOID_CrlNumber) || | |
221 | clCompareCssmData(&mExtnId, &CSSMOID_DeltaCrlIndicator) || | |
222 | clCompareCssmData(&mExtnId, &CSSMOID_CrlReason)) { | |
223 | CE_CrlNumber *cdsaObj; | |
224 | CSSM_DATA *nssObj; | |
225 | nssToCssm<CSSM_DATA, CE_CrlNumber>( | |
226 | *this, | |
227 | nssObj, | |
228 | cdsaObj, | |
229 | alloc); | |
230 | CSSM_RETURN toThrow; | |
231 | if(clCompareCssmData(&mExtnId, &CSSMOID_CrlReason)) { | |
232 | toThrow = CSSMERR_CL_INVALID_CRL_POINTER; | |
233 | } | |
234 | else { | |
235 | /* tolerate crlNumber > 4 bytes */ | |
236 | toThrow = CSSM_OK; | |
237 | } | |
238 | *cdsaObj = clDataToInt(*nssObj, toThrow); | |
239 | vCdsaObj = cdsaObj; | |
240 | } | |
241 | /* same encoding (GeneralNames) for all of these: */ | |
242 | else if(clCompareCssmData(&mExtnId, &CSSMOID_IssuerAltName) || | |
243 | clCompareCssmData(&mExtnId, &CSSMOID_SubjectAltName) || | |
244 | clCompareCssmData(&mExtnId, &CSSMOID_CertIssuer)) { | |
245 | CE_GeneralNames *cdsaObj; | |
246 | NSS_GeneralNames *nssObj; | |
247 | nssToCssm<NSS_GeneralNames, CE_GeneralNames>( | |
248 | *this, | |
249 | nssObj, | |
250 | cdsaObj, | |
251 | alloc); | |
252 | CL_nssGeneralNamesToCssm(*nssObj, *cdsaObj, mCoder, alloc); | |
253 | vCdsaObj = cdsaObj; | |
254 | } | |
255 | else if(clCompareCssmData(&mExtnId, &CSSMOID_IssuingDistributionPoint)) { | |
256 | CE_IssuingDistributionPoint *cdsaObj; | |
257 | NSS_IssuingDistributionPoint *nssObj; | |
258 | nssToCssm<NSS_IssuingDistributionPoint, CE_IssuingDistributionPoint>( | |
259 | *this, | |
260 | nssObj, | |
261 | cdsaObj, | |
262 | alloc); | |
263 | CL_nssIssuingDistPointToCssm(nssObj, cdsaObj, mCoder, alloc); | |
264 | vCdsaObj = cdsaObj; | |
265 | } | |
266 | /* | |
267 | <rdar://problem/9580989> CrashTracer: [USER] 48 crashes in WebProcess at ... | |
268 | This code should not normally be executed, since it seems from RFC5280 that | |
269 | CSSMOID_IssuingDistributionPoint is the correct extension to use. | |
270 | */ | |
271 | else if(clCompareCssmData(&mExtnId, &CSSMOID_CrlDistributionPoints)) { | |
272 | CE_CRLDistPointsSyntax *cdsaObj; | |
273 | NSS_CRLDistributionPoints *nssObj; | |
274 | nssToCssm<NSS_CRLDistributionPoints, CE_CRLDistPointsSyntax>( | |
275 | *this, | |
427c49bc | 276 | nssObj, |
b1ab9ed8 A |
277 | cdsaObj, |
278 | alloc); | |
279 | CL_nssDistPointsToCssm((const NSS_CRLDistributionPoints&)*nssObj, *cdsaObj, mCoder, alloc); | |
280 | vCdsaObj = cdsaObj; | |
281 | } | |
282 | /* | |
427c49bc | 283 | * cert entry extensions |
b1ab9ed8 A |
284 | */ |
285 | else if(clCompareCssmData(&mExtnId, &CSSMOID_HoldInstructionCode)) { | |
286 | /* value is just an OID */ | |
287 | CSSM_OID *cdsaObj; | |
288 | CSSM_DATA *nssObj; | |
289 | nssToCssm<CSSM_DATA, CSSM_OID>( | |
290 | *this, | |
291 | nssObj, | |
292 | cdsaObj, | |
293 | alloc); | |
294 | clAllocCopyData(alloc, *nssObj, *cdsaObj); | |
295 | vCdsaObj = cdsaObj; | |
296 | } | |
297 | else if(clCompareCssmData(&mExtnId, &CSSMOID_InvalidityDate)) { | |
298 | /* GeneralizedTime */ | |
299 | CSSM_DATA *cdsaObj; | |
300 | CSSM_DATA *nssObj; | |
301 | nssToCssm<CSSM_DATA, CSSM_DATA>( | |
302 | *this, | |
303 | nssObj, | |
304 | cdsaObj, | |
305 | alloc); | |
306 | clAllocCopyData(alloc, *nssObj, *cdsaObj); | |
307 | vCdsaObj = cdsaObj; | |
308 | } | |
309 | else { | |
427c49bc | 310 | /* if we get here, this routine is not keeping up with |
b1ab9ed8 A |
311 | * clOidToNssInfo() */ |
312 | // assert(0); | |
313 | CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); | |
314 | } | |
315 | convertToCdsa(vCdsaObj, cssmExt, alloc); | |
316 | } | |
317 | ||
318 | ||
319 | #pragma mark ------ DecodedExtensions ------ | |
320 | ||
321 | /* | |
322 | * A variable-size array of DecodedExtens. | |
427c49bc | 323 | * Used for storing cert and CRL extensions as well as per-CRL-entry |
b1ab9ed8 A |
324 | * extensions. |
325 | */ | |
427c49bc | 326 | DecodedExtensions::DecodedExtensions( |
b1ab9ed8 A |
327 | SecNssCoder &coder, |
328 | Allocator &alloc) | |
329 | : mCoder(coder), | |
330 | mAlloc(alloc), | |
331 | mExtensions(NULL), | |
332 | mNumExtensions(0), | |
333 | mSizeofExtensions(0) | |
334 | { | |
335 | ||
336 | } | |
427c49bc | 337 | |
b1ab9ed8 A |
338 | DecodedExtensions::~DecodedExtensions() |
339 | { | |
340 | for(unsigned i=0; i<mNumExtensions; i++) { | |
341 | assert(mExtensions[i] != NULL); | |
342 | delete mExtensions[i]; | |
343 | } | |
344 | mAlloc.free(mExtensions); | |
345 | mExtensions = NULL; | |
346 | mNumExtensions = 0; | |
347 | mSizeofExtensions = 0; | |
348 | } | |
349 | ||
350 | ||
351 | /* | |
352 | * Initialize by decoding a NSS-style NSS_CertExtension array. | |
427c49bc A |
353 | * This involves figuring out what kind of object is represented in the |
354 | * octet string in the extension, decoding it, and appending the resulting | |
b1ab9ed8 A |
355 | * NSS object to mExtensions in the form of a DecodedExten. |
356 | * | |
427c49bc A |
357 | * Called when decoding either a cert or a CRL (for caching it or |
358 | * getting its fields) or a cert template (only via | |
b1ab9ed8 A |
359 | * CertGetAllTemplateFields()). |
360 | */ | |
361 | void DecodedExtensions::decodeFromNss( | |
427c49bc | 362 | NSS_CertExtension **extensions) |
b1ab9ed8 A |
363 | { |
364 | if(extensions == NULL) { | |
365 | /* OK, no extensions present */ | |
366 | return; | |
367 | } | |
368 | unsigned numExtens = clNssArraySize((const void **)extensions); | |
369 | ||
370 | /* traverse extension list */ | |
371 | for(unsigned dex=0; dex<numExtens; dex++) { | |
372 | NSS_CertExtension *nssExten = extensions[dex]; | |
427c49bc | 373 | |
b1ab9ed8 | 374 | /* |
427c49bc | 375 | * For this extension->extnId, cook up an appropriate |
b1ab9ed8 A |
376 | * NSS-specific type (NSS_KeyUsage, etc.); |
377 | */ | |
378 | CSSM_DATA &rawExtn = nssExten->value; | |
379 | bool berEncoded = false; | |
380 | bool found; // we understand this OID | |
381 | unsigned nssObjLen; // size of associated NSS object | |
382 | const SecAsn1Template *templ = NULL; // template for decoding | |
383 | void *nssObj = NULL; // decode destination | |
384 | found = clOidToNssInfo(nssExten->extnId, nssObjLen, templ); | |
385 | if(!found) { | |
427c49bc | 386 | /* |
b1ab9ed8 A |
387 | * We don't know how to deal with this. |
388 | */ | |
389 | berEncoded = true; | |
390 | } | |
391 | else { | |
427c49bc | 392 | /* |
b1ab9ed8 | 393 | * Create NSS-style object specific to this extension, just |
427c49bc | 394 | * by knowing its length and ASN template. |
b1ab9ed8 | 395 | * Decode the extensions's extnValue into that object. We don't |
427c49bc | 396 | * have to know what kind of object it is anymore. |
b1ab9ed8 A |
397 | */ |
398 | assert(templ != NULL); | |
399 | nssObj = mCoder.malloc(nssObjLen); | |
400 | memset(nssObj, 0, nssObjLen); | |
401 | PRErrorCode prtn; | |
427c49bc | 402 | prtn = mCoder.decodeItem(rawExtn, templ, nssObj); |
b1ab9ed8 | 403 | if(prtn) { |
427c49bc A |
404 | /* |
405 | * FIXME - what do we do here? For now flag it | |
b1ab9ed8 A |
406 | * as an non-understood extension... |
407 | */ | |
408 | clErrorLog("decodeExtensions: extension decode error\n"); | |
409 | nssObj = NULL; | |
410 | berEncoded = true; | |
411 | } | |
427c49bc | 412 | } |
b1ab9ed8 A |
413 | if((nssObj != NULL) || berEncoded) { |
414 | /* append if the decode was successful */ | |
415 | addExtension(nssExten->extnId, | |
416 | clNssBoolToCssm(nssExten->critical), | |
427c49bc | 417 | nssObj, |
b1ab9ed8 A |
418 | berEncoded, |
419 | templ, | |
420 | &rawExtn); | |
421 | } | |
422 | } | |
423 | } | |
424 | ||
425 | /* | |
426 | * Encode into a NSS-style Extensions. | |
427 | * | |
428 | * Each extension object, currently stored as some AsnType subclass, | |
429 | * is BER-encoded and the result is stored as an octet string | |
430 | * (AsnOcts) in a new Extension object in the TBS. | |
431 | * | |
427c49bc | 432 | * Called from {Crl,Cert}CreateTemplate via encode{Tbs,Cts}(). |
b1ab9ed8 A |
433 | */ |
434 | void DecodedExtensions::encodeToNss( | |
435 | NSS_CertExtension **&extensions) | |
436 | { | |
437 | assert(extensions == NULL); | |
438 | ||
439 | if(mNumExtensions == 0) { | |
440 | /* no extensions, no error */ | |
441 | return; | |
442 | } | |
427c49bc | 443 | |
b1ab9ed8 A |
444 | /* malloc a NULL_terminated array of NSS_CertExtension pointers */ |
445 | unsigned len = (mNumExtensions + 1) * sizeof(NSS_CertExtension *); | |
446 | extensions = (NSS_CertExtension **)mCoder.malloc(len); | |
447 | memset(extensions, 0, len); | |
427c49bc A |
448 | |
449 | /* grind thru our DecodedExtens, creating an NSS_CertExtension for | |
b1ab9ed8 A |
450 | * each one */ |
451 | for(unsigned extenDex=0; extenDex<mNumExtensions; extenDex++) { | |
427c49bc | 452 | NSS_CertExtension *thisNssExten = |
b1ab9ed8 A |
453 | (NSS_CertExtension *)mCoder.malloc(sizeof(NSS_CertExtension)); |
454 | memset(thisNssExten, 0, sizeof(NSS_CertExtension)); | |
455 | extensions[extenDex] = thisNssExten; | |
427c49bc | 456 | |
b1ab9ed8 | 457 | const DecodedExten *decodedExt = getExtension(extenDex); |
427c49bc | 458 | |
b1ab9ed8 A |
459 | /* BER-encode the extension object if appropriate */ |
460 | if(decodedExt->berEncoded()) { | |
461 | /* unknown extension type, it's already encoded */ | |
462 | const CSSM_DATA *srcBer = (const CSSM_DATA *)decodedExt->rawExtn(); | |
463 | assert(srcBer != NULL); | |
464 | mCoder.allocCopyItem(*srcBer, thisNssExten->value); | |
465 | } | |
466 | else { | |
467 | PRErrorCode prtn; | |
468 | prtn = mCoder.encodeItem(decodedExt->nssObj(), | |
469 | decodedExt->templ(), thisNssExten->value); | |
470 | if(prtn) { | |
471 | clErrorLog("encodeToNss: extension encode error"); | |
472 | CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); | |
473 | } | |
474 | } | |
475 | ArenaAllocator arenaAlloc(mCoder); | |
476 | if(decodedExt->critical()) { | |
477 | /* optional, default false */ | |
478 | clCssmBoolToNss(CSSM_TRUE, thisNssExten->critical, arenaAlloc); | |
479 | } | |
480 | mCoder.allocCopyItem(decodedExt->extnId(), thisNssExten->extnId); | |
481 | } | |
482 | } | |
483 | ||
484 | /* add/retrieve entries */ | |
485 | void DecodedExtensions::addExtension( | |
486 | const CSSM_OID &extnId, // copied | |
487 | bool critical, | |
427c49bc | 488 | void *nssObj, // NSS_KeyUsage, NSS_BasicConstraints, |
b1ab9ed8 A |
489 | // etc. NOT COPIED, exists in same |
490 | // memory space as coder | |
491 | bool berEncoded, // indicates unknown extension which we | |
492 | // do not BER-decode when parsing a cert | |
493 | const SecAsn1Template *templ, // required if !berEncoded | |
494 | const CSSM_DATA *rawExtn) // NSS_CertExtension.value, copied, | |
427c49bc | 495 | // optional (not present during a |
b1ab9ed8 A |
496 | // SetField op) |
497 | { | |
498 | if(mNumExtensions == mSizeofExtensions) { | |
499 | /* expand by doubling, or initial malloc */ | |
427c49bc | 500 | mSizeofExtensions = mNumExtensions ? |
b1ab9ed8 A |
501 | (2 * mNumExtensions) : MIN_EXTENSIONS; |
502 | mExtensions = (DecodedExten **)mAlloc.realloc( | |
503 | mExtensions, mSizeofExtensions * sizeof(DecodedExten)); | |
504 | } | |
505 | mExtensions[mNumExtensions++] = new DecodedExten(extnId, | |
506 | critical, nssObj, berEncoded, templ, mCoder, rawExtn); | |
507 | } | |
427c49bc | 508 | |
b1ab9ed8 A |
509 | const DecodedExten *DecodedExtensions::getExtension( |
510 | unsigned extenDex) const | |
511 | { | |
512 | assert(extenDex < mNumExtensions); | |
513 | return mExtensions[extenDex]; | |
514 | } | |
515 | ||
516 | /* Convert to CSSM_X509_EXTENSIONS */ | |
517 | /* Currently only used when decoding a CRL and converting it en masse | |
518 | * to CDSA */ | |
519 | void DecodedExtensions::convertToCdsa( | |
520 | CSSM_X509_EXTENSIONS &cssmExtens, | |
521 | Allocator &alloc) const | |
522 | { | |
523 | memset(&cssmExtens, 0, sizeof(cssmExtens)); | |
524 | if(mNumExtensions == 0) { | |
525 | return; | |
526 | } | |
527 | cssmExtens.extensions = (CSSM_X509_EXTENSION_PTR)alloc.malloc( | |
528 | sizeof(CSSM_X509_EXTENSION) * mNumExtensions); | |
427c49bc | 529 | memset(cssmExtens.extensions, 0, |
b1ab9ed8 A |
530 | sizeof(CSSM_X509_EXTENSION) * mNumExtensions); |
531 | cssmExtens.numberOfExtensions = mNumExtensions; | |
532 | for(unsigned dex=0; dex<mNumExtensions; dex++) { | |
533 | try { | |
534 | getExtension(dex)->parse(&cssmExtens.extensions[dex], alloc); | |
535 | } | |
536 | catch(...) { | |
537 | /* FIXME - what now? */ | |
538 | clFieldLog("DecodedExtensions:convertToCdsa: extension " | |
539 | "decode error"); | |
540 | } | |
541 | } | |
542 | } | |
543 |