]> git.saurik.com Git - apple/security.git/blame - AppleX509CL/CLCertExtensions.cpp
Security-30.1.tar.gz
[apple/security.git] / AppleX509CL / CLCertExtensions.cpp
CommitLineData
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/*
20 * CLCertExtensions.cpp - extensions support. A major component of DecodedCert.
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"
29#include "CertBuilder.h"
30#include "CLCertExtensions.h"
31#include "SnaccUtils.h"
32#include <Security/utilities.h>
33#include <Security/oidscert.h>
34#include <Security/cssmerr.h>
35#include <Security/x509defs.h>
36#include <Security/certextensions.h>
37#include <Security/cdsaUtils.h>
38#include <Security/sm_x509ce.h>
39#include <Security/globalizer.h>
40
41static AsnType *oidToSnaccObj(
42 const AsnOid &extnId);
43
44#define MIN_EXTENSIONS 4 // initial size of *mExtensions
45
46/*
47 * AsnOid "constants" which we construct and cache on demand to avoid the
48 * somewhat expensive op of constructing them every time we test for equality
49 * in oidToSnaccObj().
50 */
51class ExtOidCache
52{
53public:
54 ExtOidCache() :
55 mId_ce_keyUsage(id_ce_keyUsage_arc),
56 mId_ce_basicConstraints(id_ce_basicConstraints_arc),
57 mId_ce_extKeyUsage(id_ce_extKeyUsage_arc),
58 mId_ce_subjectKeyIdentifier(id_ce_subjectKeyIdentifier_arc),
59 mId_ce_authorityKeyIdentifier(id_ce_authorityKeyIdentifier_arc),
60 mId_ce_subjectAltName(id_ce_subjectAltName_arc),
61 mId_ce_certificatePolicies(id_ce_certificatePolicies_arc),
62 mId_netscape_cert_type(id_netscape_cert_type_arc)
63 { }
64
65 AsnOid mId_ce_keyUsage;
66 AsnOid mId_ce_basicConstraints;
67 AsnOid mId_ce_extKeyUsage;
68 AsnOid mId_ce_subjectKeyIdentifier;
69 AsnOid mId_ce_authorityKeyIdentifier;
70 AsnOid mId_ce_subjectAltName;
71 AsnOid mId_ce_certificatePolicies;
72 AsnOid mId_netscape_cert_type;
73};
74
75static ModuleNexus<ExtOidCache> extOidCache;
76
77/*
78 * Decode tbs->Extensions into mExtensions. This involves figuring out
79 * what kind of object is represented in the octet string in the
80 * extension, decoding it, and placing the resulting AsnType in a
81 * new DecodedExten struct.
82 *
83 * Called when decoding either a cert (for caching it or getting its fields)
84 * or a template (only via CertGetAllTemplateFields()).
85 */
86void DecodedCert::decodeExtensions()
87{
88 CASSERT(certificateToSign != NULL);
89 Extensions *extensions = certificateToSign->extensions;
90 if(extensions == NULL) {
91 /* OK, no extensions present */
92 return;
93 }
94
95 Extension *snaccExten = extensions->First();
96 extensions->SetCurrToFirst();
97
98 /* traverse extension list */
99 while(snaccExten != 0) {
100 /*
101 * For this extension->extnId, cook up an approppriate
102 * AsnType (KeyUsage, etc.);
103 */
104 AsnOid &extnId = snaccExten->extnId;
105 bool berEncoded = false;
106 AsnType *snaccObj = oidToSnaccObj(extnId);
107 if(snaccObj == NULL) {
108 /*
109 * We don't know how to deal with this, just take the
110 * raw bytes, copied from snaccExte.
111 */
112 snaccObj = new AsnOcts(snaccExten->extnValue);
113 berEncoded = true;
114 }
115 else {
116 /*
117 * We have a snacc-style object specific to this extension.
118 * Decode the extensions's extnValue into that object. We don't
119 * have to know what kind of object it is anymore.
120 */
121 CssmData cData(snaccExten->extnValue, snaccExten->extnValue.Len());
122 try {
123 SC_decodeAsnObj(cData, *snaccObj);
124 }
125 catch (...) {
126 /*
127 * FIXME - what do we do here? Is it safe to just ignore this
128 * extension, or is the whole cert invalid?
129 */
130 errorLog0("decodeExtensions: extension decode error\n");
131 delete snaccObj;
132 snaccObj = NULL;
133 }
134 }
135 if(snaccObj != NULL) {
136 /* add to mExtensions if the decode was successful */
137 bool critical = false; // default
138 if(snaccExten->critical != NULL) {
139 critical = *snaccExten->critical;
140 }
141 addExtension(snaccObj,
142 snaccExten->extnId,
143 critical,
144 berEncoded);
145 }
146 extensions->GoNext();
147 snaccExten = extensions->Curr();
148 }
149}
150
151/*
152 * Encode mExtensions into tbs->Extensions.
153 *
154 * Each extension object, currently stored as some AsnType subclass,
155 * is BER-encoded and the reesult is stored as an octet string
156 * (AsnOcts) in a new Extension object in the TBS.
157 *
158 * Only called from CertCreateTemplate via encodeTbs().
159 */
160#define MAX_EXTEN_SIZE (4 * 1024) /* SWAG for max encoded size */
161
162void DecodedCert::encodeExtensions()
163{
164 CertificateToSign *tbs = certificateToSign;
165 CASSERT(mState == CS_Building);
166 CASSERT((tbs != NULL) && (tbs->extensions == NULL));
167
168 if(mNumExtensions == 0) {
169 /* no extensions, no error */
170 return;
171 }
172 tbs->extensions = new Extensions;
173 Extensions *extns = tbs->extensions;
174
175 /* for each of our DecodedExtens, append an Extension object to
176 * tbs->extensions */
177 unsigned extenDex;
178 for(extenDex=0; extenDex<mNumExtensions; extenDex++) {
179 Extension *snaccExt = extns->Append();
180 DecodedExten *decodedExt = &mExtensions[extenDex];
181
182 /* BER-encode the extension object if appropriate */
183 if(decodedExt->berEncoded) {
184 /* unknown extension type, it's already encoded */
185 /* A failure of this dynamic cast is a fata internal error */
186 AsnOcts *rawOcts = dynamic_cast<AsnOcts *>(decodedExt->snaccObj);
187 if(rawOcts == NULL) {
188 errorLog0("encodeExtensions: dynamic_cast failure!\n");
189 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
190 }
191 snaccExt->extnValue.Set(*rawOcts);
192 }
193 else {
194 CssmAutoData aData(alloc);
195 try {
196 SC_encodeAsnObj(*decodedExt->snaccObj, aData, MAX_EXTEN_SIZE);
197 }
198 catch (...) {
199 errorLog0("encodeExtensions: extension encode error\n");
200 throw;
201 }
202 CssmData &cData = aData.get();
203 snaccExt->extnValue.Set((char *)cData.data(), cData.length());
204 }
205 snaccExt->critical = new AsnBool(decodedExt->critical);
206 snaccExt->extnId.Set(*decodedExt->extnId);
207 }
208}
209
210
211/*
212 * Add a new DecodedExten to mExtensions.
213 * Called from decodeExtensions and setField*.
214 * At this point, the actual extenmsion data is represented by some subclass
215 * of AsnType - either a specific extension type (e.g. KeyUsage), or as an
216 * octet string (AsnOcts) for extension types we don't understand (and which
217 * are encoded by the app).
218 */
219void DecodedCert::addExtension(
220 AsnType *snaccObj, // e.g. KeyUsage
221 const AsnOid &extnId,
222 bool critical,
223 bool berEncoded) // i.e., we don't know how to parse
224{
225 /* cook up a new DecodedExten, reallocing mExtensions is necessary */
226 if(mNumExtensions == mSizeofExtensions) {
227 /* expand by doubling, or initial malloc */
228 mSizeofExtensions = mNumExtensions ?
229 (2 * mNumExtensions) : MIN_EXTENSIONS;
230 mExtensions = (DecodedExten *)alloc.realloc(
231 mExtensions, mSizeofExtensions * sizeof(DecodedExten));
232 }
233 DecodedExten *decodedExt = &mExtensions[mNumExtensions++];
234 decodedExt->extnId = new AsnOid(extnId);
235 decodedExt->critical = critical;
236 decodedExt->snaccObj = snaccObj;
237 decodedExt->berEncoded = berEncoded;
238}
239
240/*
241 * Search for DecodedExten by AsnOid or "any unknown extension".
242 * Called from getField*() and inferKeyUsage.
243 * Returns NULL if specified extension not found.
244 */
245DecodedExten *DecodedCert::findDecodedExt(
246 const AsnOid &extnId, // for known extensions
247 bool unknown, // otherwise
248 uint32 index,
249 uint32 &numFields) const
250{
251 unsigned dex;
252 DecodedExten *decodedExt;
253 DecodedExten *rtnExt = NULL;
254 unsigned found = 0;
255
256 for(dex=0; dex<mNumExtensions; dex++) {
257 CASSERT(mExtensions != NULL);
258 decodedExt = &mExtensions[dex];
259 /*
260 * known extensions: OID match
261 * unknown extensions: just know that we didn't decode it
262 */
263 if( (!unknown && (*decodedExt->extnId == extnId)) ||
264 (unknown && decodedExt->berEncoded)) {
265
266 if(found++ == index) {
267 /* the one we want */
268 rtnExt = decodedExt;
269 }
270 if((rtnExt != NULL) && (index != 0)) {
271 /* only determine numFields on search for first one */
272 break;
273 }
274 }
275 }
276 if(rtnExt != NULL) {
277 /* sucessful return */
278 if(index == 0) {
279 numFields = found;
280 }
281 return rtnExt;
282 }
283 else {
284 return NULL;
285 }
286}
287
288/*
289 * Common code to pass info from a DecodedExten back to app.
290 * Called from getField*().
291 */
292static void getFieldExtenCommon(
293 void *cdsaObj, // e.g. CE_KeyUsage
294 // CSSM_DATA_PTR for berEncoded
295 const DecodedExten &decodedExt,
296 CssmOwnedData &fieldValue)
297{
298 CSSM_X509_EXTENSION_PTR cssmExt;
299 CssmAllocator &alloc = fieldValue.allocator;
300 CssmData &fdata = fieldValue.get();
301
302 cssmExt = (CSSM_X509_EXTENSION_PTR)alloc.malloc(sizeof(CSSM_X509_EXTENSION));
303 fdata.Data = (uint8 *)cssmExt;
304 fdata.Length = sizeof(CSSM_X509_EXTENSION);
305 CL_snaccOidToCssm(*decodedExt.extnId,
306 CssmOid::overlay(cssmExt->extnId),
307 alloc);
308 if(decodedExt.critical != NULL) {
309 cssmExt->critical = decodedExt.critical ? CSSM_TRUE : CSSM_FALSE;
310 }
311 else {
312 /* default */
313 cssmExt->critical = false;
314 }
315 if(decodedExt.berEncoded) {
316 /* an extension we never parsed or understood */
317 cssmExt->format = CSSM_X509_DATAFORMAT_ENCODED;
318 cssmExt->value.parsedValue = NULL;
319 cssmExt->BERvalue = *(reinterpret_cast<CSSM_DATA_PTR>(cdsaObj));
320 }
321 else {
322 cssmExt->format = CSSM_X509_DATAFORMAT_PARSED;
323 cssmExt->value.parsedValue = cdsaObj;
324 cssmExt->BERvalue.Data = NULL;
325 cssmExt->BERvalue.Length = 0;
326 }
327}
328
329/*
330 * Common code for top of setField* and freeField*().
331 */
332static CSSM_X509_EXTENSION_PTR verifySetFreeExtension(
333 const CssmData &fieldValue,
334 bool berEncoded) // false: value in value.parsedValue
335 // true : value in BERValue
336{
337 if(fieldValue.length() != sizeof(CSSM_X509_EXTENSION)) {
338 errorLog2("Set/FreeExtension: bad length : exp %d got %d\n",
339 (int)sizeof(CSSM_X509_EXTENSION), (int)fieldValue.length());
340 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
341 }
342 CSSM_X509_EXTENSION_PTR cssmExt =
343 reinterpret_cast<CSSM_X509_EXTENSION_PTR>(fieldValue.data());
344 if(berEncoded) {
345 if((cssmExt->value.parsedValue != NULL) || (cssmExt->BERvalue.Data == NULL)) {
346 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
347 }
348 }
349 else {
350 if((cssmExt->value.parsedValue == NULL) || (cssmExt->BERvalue.Data != NULL)) {
351 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
352 }
353 }
354 return cssmExt;
355}
356
357/*
358 * Common free code for all extensions. Extension-specific code must
359 * free anything beyond cdsaExt->Value.parsedValue, then we free everything
360 * else (except the extension struct itself, which is freed by
361 * DecodedCert::freeCertFieldData()).
362 */
363static void freeFieldExtenCommon(
364 CSSM_X509_EXTENSION_PTR exten,
365 CssmAllocator &alloc)
366{
367 alloc.free(exten->extnId.Data);
368 alloc.free(exten->BERvalue.Data); // may be NULL
369 alloc.free(exten->value.parsedValue); // may be NULL
370}
371
372
373/*
374 * Cook up an AsnType associated with specified extnId
375 * When adding oid/type pairs here, also add to:
376 * -- fieldFuncs[] in CertFields.cpp
377 * -- and the get/set/free functions in this file.
378 */
379static AsnType *oidToSnaccObj(
380 const AsnOid &extnId)
381{
382 ExtOidCache &oc = extOidCache();
383
384 if(extnId == oc.mId_ce_keyUsage) {
385 return new KeyUsage;
386 }
387 else if(extnId == oc.mId_ce_basicConstraints) {
388 return new BasicConstraintsSyntax;
389 }
390 else if(extnId == oc.mId_ce_extKeyUsage) {
391 return new ExtKeyUsageSyntax;
392 }
393 else if(extnId == oc.mId_ce_subjectKeyIdentifier) {
394 return new AsnOcts;
395 }
396 else if(extnId == oc.mId_ce_authorityKeyIdentifier) {
397 return new AuthorityKeyIdentifier;
398 }
399 else if(extnId == oc.mId_ce_subjectAltName) {
400 return new GeneralNames;
401 }
402 else if(extnId == oc.mId_ce_certificatePolicies) {
403 return new CertificatePoliciesSyntax;
404 }
405 else if(extnId == oc.mId_netscape_cert_type) {
406 return new AsnBits;
407 }
408 else {
409 return NULL;
410 }
411}
412
413/* common code for top of getField* */
414template<class SnaccType, class CdsaType>
415bool GetFieldTop(
416 const DecodedCert &cert,
417 unsigned index, // which occurrence (0 = first)
418 uint32 &numFields, // RETURNED
419 CssmAllocator &alloc,
420 const AsnOid &fieldId,
421 SnaccType *&snaccObj,
422 CdsaType *&cdsaObj,
423 DecodedExten *&decodedExt)
424{
425 /* See if we have one of these in our list of DecodedExtens */
426 decodedExt = cert.findDecodedExt(fieldId, false, index, numFields);
427 if(decodedExt == NULL) {
428 return false;
429 }
430
431 /* failure of this dynamic_cast is fatal */
432 snaccObj = dynamic_cast<SnaccType *>(decodedExt->snaccObj);
433 if(snaccObj == NULL) {
434 errorLog0("GetFieldTop: dynamic_cast failure\n");
435 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
436 }
437 cdsaObj = (CdsaType *)alloc.malloc(sizeof(CdsaType));
438 memset(cdsaObj, 0, sizeof(CdsaType));
439 return true;
440}
441
442/***
443 *** get/set/free functions called out from CertFields.cpp
444 ***/
445
446/*
447 * One common free for extensions whose parsed value doesn't go any deeper
448 * than cssmExt->value.parsedValue.
449 */
450void freeFieldSimpleExtension (
451 CssmOwnedData &fieldValue)
452{
453 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
454 freeFieldExtenCommon(cssmExt, fieldValue.allocator);
455}
456
457/***
458 *** KeyUsage
459 *** CDSA format CE_KeyUsage
460 *** SNACC format KeyUsage
461 *** OID CSSMOID_KeyUsage
462 ***/
463
464void setFieldKeyUsage(
465 DecodedCert &cert,
466 const CssmData &fieldValue)
467{
468 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
469 CE_KeyUsage *cdsaObj = (CE_KeyUsage *)cssmExt->value.parsedValue;
470
471 /* brute-force cdsaObj --> snaccObj */
472 char bits[sizeof(CE_KeyUsage)];
473 bits[0] = static_cast<char>((*cdsaObj) >> 8);
474 bits[1] = static_cast<char>(*cdsaObj);
475 memmove(bits, cdsaObj, sizeof(CE_KeyUsage));
476 KeyUsage *snaccObj = new KeyUsage(bits, sizeof(CE_KeyUsage) * 8);
477
478 /* add to mExtensions */
479 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
480}
481
482
483bool getFieldKeyUsage(
484 const DecodedCert &cert,
485 unsigned index, // which occurrence (0 = first)
486 uint32 &numFields, // RETURNED
487 CssmOwnedData &fieldValue)
488{
489 DecodedExten *decodedExt;
490 KeyUsage *snaccObj;
491 CE_KeyUsage *cdsaObj;
492 bool brtn;
493
494 brtn = GetFieldTop<KeyUsage, CE_KeyUsage>(
495 cert,
496 index,
497 numFields,
498 fieldValue.allocator,
499 id_ce_keyUsage,
500 snaccObj,
501 cdsaObj,
502 decodedExt);
503 if(!brtn) {
504 return false;
505 }
506
507 unsigned toCopy = (snaccObj->BitLen() + 7) / 8;
508 if(toCopy > 2) {
509 /* I hope I never see this... */
510 errorLog0("getFieldKeyUsage: KeyUsage larger than 2 bytes!\n");
511 toCopy = 2;
512 }
513 unsigned char bits[2] = {0, 0};
514 memmove(bits, snaccObj->BitOcts(), toCopy);
515 *cdsaObj = (((unsigned)bits[0]) << 8) | bits[1];
516
517 /* pass back to caller */
518 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
519 return true;
520}
521
522/***
523 *** Basic Constraints
524 *** CDSA format: CE_BasicConstraints
525 *** SNACC format BasicConstraintsSyntax
526 *** OID CSSMOID_BasicConstraints
527 ***/
528
529void setFieldBasicConstraints(
530 DecodedCert &cert,
531 const CssmData &fieldValue)
532{
533 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
534 BasicConstraintsSyntax *snaccObj = new BasicConstraintsSyntax;
535 CE_BasicConstraints *cdsaObj = (CE_BasicConstraints *)cssmExt->value.parsedValue;
536
537 /* brute-force cdsaObj --> snaccObj */
538 snaccObj->cA = new AsnBool(cdsaObj->cA ? true : false);
539 if(cdsaObj->pathLenConstraintPresent) {
540 AsnIntType val = cdsaObj->pathLenConstraint;
541 snaccObj->pathLenConstraint = new AsnInt(val);
542 }
543
544 /* add to mExtensions */
545 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
546}
547
548
549bool getFieldBasicConstraints(
550 const DecodedCert &cert,
551 unsigned index, // which occurrence (0 = first)
552 uint32 &numFields, // RETURNED
553 CssmOwnedData &fieldValue)
554{
555 DecodedExten *decodedExt;
556 BasicConstraintsSyntax *snaccObj;
557 CE_BasicConstraints *cdsaObj;
558 bool brtn;
559
560 brtn = GetFieldTop<BasicConstraintsSyntax, CE_BasicConstraints>(
561 cert,
562 index,
563 numFields,
564 fieldValue.allocator,
565 id_ce_basicConstraints,
566 snaccObj,
567 cdsaObj,
568 decodedExt);
569 if(!brtn) {
570 return false;
571 }
572
573 if(snaccObj->cA == NULL) {
574 /* default */
575 cdsaObj->cA = CSSM_FALSE;
576 }
577 else {
578 bool val = *snaccObj->cA;
579 cdsaObj->cA = val ? CSSM_TRUE : CSSM_FALSE;
580 }
581 if(snaccObj->pathLenConstraint == NULL) {
582 cdsaObj->pathLenConstraintPresent = CSSM_FALSE;
583 cdsaObj->pathLenConstraint = 0;
584 }
585 else {
586 cdsaObj->pathLenConstraintPresent = CSSM_TRUE;
587 AsnIntType val = *snaccObj->pathLenConstraint;
588 cdsaObj->pathLenConstraint = val;
589 }
590
591 /* pass back to caller */
592 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
593 return true;
594}
595
596/***
597 *** Extended Key Usage
598 *** CDSA format: CE_ExtendedKeyUsage
599 *** SNACC format ExtKeyUsageSyntax
600 *** OID CSSMOID_ExtendedKeyUsage
601 ***/
602void setFieldExtKeyUsage(
603 DecodedCert &cert,
604 const CssmData &fieldValue)
605{
606 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
607 ExtKeyUsageSyntax *snaccObj = new ExtKeyUsageSyntax;
608 CE_ExtendedKeyUsage *cdsaObj = (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue;
609
610 /* brute-force cdsaObj --> snaccObj, one 'purpose' (OID) at a time */
611 unsigned oidDex;
612 for(oidDex=0; oidDex<cdsaObj->numPurposes; oidDex++) {
613 KeyPurposeId *snaccPurp = snaccObj->Append();
614 CSSM_OID_PTR cdsaPurp = &cdsaObj->purposes[oidDex];
615 snaccPurp->Set(reinterpret_cast<char *>(cdsaPurp->Data), cdsaPurp->Length);
616 }
617
618 /* add to mExtensions */
619 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
620}
621
622bool getFieldExtKeyUsage(
623 const DecodedCert &cert,
624 unsigned index, // which occurrence (0 = first)
625 uint32 &numFields, // RETURNED
626 CssmOwnedData &fieldValue)
627{
628 DecodedExten *decodedExt;
629 ExtKeyUsageSyntax *snaccObj;
630 CE_ExtendedKeyUsage *cdsaObj;
631 bool brtn;
632
633 brtn = GetFieldTop<ExtKeyUsageSyntax, CE_ExtendedKeyUsage>(
634 cert,
635 index,
636 numFields,
637 fieldValue.allocator,
638 id_ce_extKeyUsage,
639 snaccObj,
640 cdsaObj,
641 decodedExt);
642 if(!brtn) {
643 return false;
644 }
645
646 /* brute force snaccObj --> cdsaObj, one purpose at a time */
647 CssmAllocator &alloc = fieldValue.allocator;
648 cdsaObj->numPurposes = snaccObj->Count();
649 cdsaObj->purposes = (CSSM_OID_PTR)alloc.malloc(cdsaObj->numPurposes *
650 sizeof(CSSM_OID));
651 snaccObj->SetCurrToFirst();
652 unsigned oidDex;
653 for(oidDex=0; oidDex<cdsaObj->numPurposes; oidDex++) {
654 CL_snaccOidToCssm(*snaccObj->Curr(),
655 CssmOid::overlay(cdsaObj->purposes[oidDex]),
656 alloc);
657 snaccObj->GoNext();
658 }
659 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
660 return true;
661}
662
663void freeFieldExtKeyUsage(
664 CssmOwnedData &fieldValue)
665{
666 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
667 CssmAllocator &alloc = fieldValue.allocator;
668 CE_ExtendedKeyUsage *cdsaObj =
669 (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue;
670 unsigned oidDex;
671 for(oidDex=0; oidDex<cdsaObj->numPurposes; oidDex++) {
672 alloc.free(cdsaObj->purposes[oidDex].Data);
673 }
674 alloc.free(cdsaObj->purposes);
675 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
676}
677
678/***
679 *** Subject Key Identifier
680 *** CDSA format: CE_SubjectKeyID, which is just a CSSM_DATA
681 *** SNACC format AsnOcts
682 *** OID CSSMOID_SubjectKeyIdentifier
683 ***/
684
685void setFieldSubjectKeyId(
686 DecodedCert &cert,
687 const CssmData &fieldValue)
688{
689 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
690 CE_SubjectKeyID *cdsaObj = (CE_SubjectKeyID *)cssmExt->value.parsedValue;
691 AsnOcts *snaccObj = new AsnOcts((char *)cdsaObj->Data, cdsaObj->Length);
692 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
693}
694
695bool getFieldSubjectKeyId(
696 const DecodedCert &cert,
697 unsigned index, // which occurrence (0 = first)
698 uint32 &numFields, // RETURNED
699 CssmOwnedData &fieldValue)
700{
701 DecodedExten *decodedExt;
702 AsnOcts *snaccObj;
703 CE_SubjectKeyID *cdsaObj;
704 bool brtn;
705
706 brtn = GetFieldTop<AsnOcts, CE_SubjectKeyID>(
707 cert,
708 index,
709 numFields,
710 fieldValue.allocator,
711 id_ce_subjectKeyIdentifier,
712 snaccObj,
713 cdsaObj,
714 decodedExt);
715 if(!brtn) {
716 return false;
717 }
718 CL_AsnOctsToCssmData(*snaccObj, *cdsaObj, fieldValue.allocator);
719 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
720 return true;
721}
722
723void freeFieldSubjectKeyId (
724 CssmOwnedData &fieldValue)
725{
726 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
727 CssmAllocator &alloc = fieldValue.allocator;
728 CE_SubjectKeyID *cdsaObj = (CE_SubjectKeyID *)cssmExt->value.parsedValue;
729 alloc.free(cdsaObj->Data);
730 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
731}
732
733/***
734 *** Authority Key Identifier
735 *** CDSA format: CE_AuthorityKeyID
736 *** SNACC format AuthorityKeyIdentifier
737 *** OID CSSMOID_AuthorityKeyIdentifier
738 ***/
739
740void setFieldAuthorityKeyId(
741 DecodedCert &cert,
742 const CssmData &fieldValue)
743{
744 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
745 CE_AuthorityKeyID *cdsaObj = (CE_AuthorityKeyID *)cssmExt->value.parsedValue;
746 AuthorityKeyIdentifier *snaccObj = new AuthorityKeyIdentifier;
747
748 /*
749 * brute-force a CDSA-style CE_AuthorityKeyID into snacc-style
750 * AuthorityKeyIdentifier
751 */
752 if(cdsaObj->keyIdentifierPresent) {
753 /* Just an AsnOcts */
754 snaccObj->keyIdentifier = new AsnOcts((char *)cdsaObj->keyIdentifier.Data,
755 cdsaObj->keyIdentifier.Length);
756 }
757 if(cdsaObj->generalNamesPresent ) {
758 /* GeneralNames, the hard one */
759 snaccObj->authorityCertIssuer = CL_cdsaGeneralNamesToSnacc(
760 *cdsaObj->generalNames);
761 }
762 if(cdsaObj->serialNumberPresent) {
763 /* boils down to BigIntegerStr, or AsnOcts */
764 snaccObj->authorityCertSerialNumber =
765 new CertificateSerialNumber((char *)cdsaObj->serialNumber.Data,
766 cdsaObj->serialNumber.Length);
767 }
768
769 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
770}
771
772bool getFieldAuthorityKeyId(
773 const DecodedCert &cert,
774 unsigned index, // which occurrence (0 = first)
775 uint32 &numFields, // RETURNED
776 CssmOwnedData &fieldValue)
777{
778 DecodedExten *decodedExt;
779 AuthorityKeyIdentifier *snaccObj;
780 CE_AuthorityKeyID *cdsaObj;
781 bool brtn;
782 CssmAllocator &alloc = fieldValue.allocator;
783
784 brtn = GetFieldTop<AuthorityKeyIdentifier, CE_AuthorityKeyID>(
785 cert,
786 index,
787 numFields,
788 alloc,
789 id_ce_authorityKeyIdentifier,
790 snaccObj,
791 cdsaObj,
792 decodedExt);
793 if(!brtn) {
794 return false;
795 }
796
797 /* brute-force a snacc-style AuthorityKeyIdentifier into CDSA format */
798 if(snaccObj->keyIdentifier != NULL) {
799 /* Just an AsnOcts */
800 cdsaObj->keyIdentifierPresent = CSSM_TRUE;
801 CL_AsnOctsToCssmData(*snaccObj->keyIdentifier,
802 cdsaObj->keyIdentifier,
803 alloc);
804 }
805 if(snaccObj->authorityCertIssuer != NULL) {
806 /* GeneralNames, the hard one */
807 cdsaObj->generalNamesPresent = CSSM_TRUE;
808 cdsaObj->generalNames = (CE_GeneralNames *)alloc.malloc(sizeof(CE_GeneralName));
809 CL_snaccGeneralNamesToCdsa(*snaccObj->authorityCertIssuer,
810 *cdsaObj->generalNames,
811 alloc);
812 }
813 if(snaccObj->authorityCertSerialNumber != NULL) {
814 /* boils down to BigIntegerStr, or AsnOcts */
815 cdsaObj->serialNumberPresent = CSSM_TRUE;
816 CL_AsnOctsToCssmData(*snaccObj->authorityCertSerialNumber,
817 cdsaObj->serialNumber,
818 alloc);
819 }
820 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
821 return true;
822}
823
824static void freeFieldGeneralNames(
825 CE_GeneralNames *cdsaObj,
826 CssmAllocator &alloc)
827{
828 if(cdsaObj == NULL) {
829 return;
830 }
831 for(unsigned i=0; i<cdsaObj->numNames; i++) {
832 alloc.free(cdsaObj->generalName[i].name.Data);
833 }
834 if(cdsaObj->numNames) {
835 memset(cdsaObj->generalName, 0, cdsaObj->numNames * sizeof(CE_GeneralName));
836 }
837 memset(cdsaObj, 0, sizeof(CE_GeneralNames));
838}
839
840void freeFieldAuthorityKeyId (
841 CssmOwnedData &fieldValue)
842{
843 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
844 CssmAllocator &alloc = fieldValue.allocator;
845 CE_AuthorityKeyID *cdsaObj = (CE_AuthorityKeyID *)cssmExt->value.parsedValue;
846 alloc.free(cdsaObj->keyIdentifier.Data);
847 freeFieldGeneralNames(cdsaObj->generalNames, alloc);
848 alloc.free(cdsaObj->serialNumber.Data);
849 memset(cdsaObj, 0, sizeof(CE_AuthorityKeyID));
850 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
851}
852
853/***
854 *** Subject alternate name
855 *** CDSA Format: CE_GeneralNames
856 *** SNACC format: GeneralNames
857 *** OID: CSSMOID_SubjectAltName
858 ***/
859void setFieldSubjAltName(
860 DecodedCert &cert,
861 const CssmData &fieldValue)
862{
863 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
864 CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue;
865 GeneralNames *snaccObj = CL_cdsaGeneralNamesToSnacc(*cdsaObj);
866 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
867}
868
869bool getFieldSubjAltName(
870 const DecodedCert &cert,
871 unsigned index, // which occurrence (0 = first)
872 uint32 &numFields, // RETURNED
873 CssmOwnedData &fieldValue)
874{
875 DecodedExten *decodedExt;
876 GeneralNames *snaccObj;
877 CE_GeneralNames *cdsaObj;
878 bool brtn;
879
880 brtn = GetFieldTop<GeneralNames, CE_GeneralNames>(
881 cert,
882 index,
883 numFields,
884 fieldValue.allocator,
885 id_ce_subjectAltName,
886 snaccObj,
887 cdsaObj,
888 decodedExt);
889 if(!brtn) {
890 return false;
891 }
892 CL_snaccGeneralNamesToCdsa(*snaccObj, *cdsaObj, fieldValue.allocator);
893 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
894 return true;
895}
896
897void freeFieldSubjAltName (
898 CssmOwnedData &fieldValue)
899{
900 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
901 CssmAllocator &alloc = fieldValue.allocator;
902 CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue;
903 freeFieldGeneralNames(cdsaObj, alloc);
904 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
905}
906
907/***
908 *** Certificate Policies
909 *** CDSA Format: CE_CertPolicies
910 *** SNACC format: CertificatePoliciesSyntax
911 *** OID: CSSMOID_CertificatePolicies
912 ***/
913
914#define MAX_IA5_NAME_SIZE 1024
915
916void setFieldCertPolicies(
917 DecodedCert &cert,
918 const CssmData &fieldValue)
919{
920 CssmAllocator &alloc = CssmAllocator::standard();
921 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
922 CertificatePoliciesSyntax *snaccObj = new CertificatePoliciesSyntax;
923 CE_CertPolicies *cdsaObj = (CE_CertPolicies *)cssmExt->value.parsedValue;
924
925 /* brute-force cdsaObj --> snaccObj */
926 for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
927 CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
928 PolicyInformation *sPolInfo = snaccObj->Append();
929 sPolInfo->policyIdentifier.Set((char *)cPolInfo->certPolicyId.Data,
930 cPolInfo->certPolicyId.Length);
931 if(cPolInfo->numPolicyQualifiers != 0) {
932 sPolInfo->policyQualifiers = new PolicyInformationSeqOf;
933 }
934 for(unsigned qualDex=0; qualDex<cPolInfo->numPolicyQualifiers; qualDex++) {
935 CE_PolicyQualifierInfo *cQualInfo = &cPolInfo->policyQualifiers[qualDex];
936 PolicyQualifierInfo *sQualInfo = sPolInfo->policyQualifiers->Append();
937
938 /* OK we're at the lowest level.
939 * policyQualifierId == id_qt_cps: qualifier is an IA5 string,
940 * incoming data is its contents. Else incoming data is an encoded
941 * blob we pass on directly.
942 */
943 sQualInfo->policyQualifierId.Set(
944 (char *)cQualInfo->policyQualifierId.Data,
945 cQualInfo->policyQualifierId.Length);
946
947 /* we'll convert this incoming ptr/len.... */
948 uint8 *rawData = cQualInfo->qualifier.Data;
949 unsigned rawDataLen = cQualInfo->qualifier.Length;
950 /* to this, somehow; it'll be used to build the required AsnAny. */
951 CssmAutoData aData(alloc);
952
953 if(sQualInfo->policyQualifierId == id_qt_cps) {
954 /* build & encode an IA5String */
955 IA5String *ia5 = new IA5String((char *)rawData, rawDataLen);
956 SC_encodeAsnObj(*ia5, aData, MAX_IA5_NAME_SIZE);
957 delete ia5;
958 }
959 else {
960 /* copy over directly */
961 aData.copy(rawData, rawDataLen);
962 }
963
964 /* install the result into CSM_Buffer, which mallocs & copies */
965 sQualInfo->qualifier = new AsnAny;
966 char *cp = aData;
967 sQualInfo->qualifier->value = new CSM_Buffer(cp, aData.length());
968 aData.reset();
969 } /* for each qualifier */
970 } /* for each policy */
971
972 /* add to mExtensions */
973 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
974}
975
976bool getFieldCertPolicies(
977 const DecodedCert &cert,
978 unsigned index, // which occurrence (0 = first)
979 uint32 &numFields, // RETURNED
980 CssmOwnedData &fieldValue)
981{
982 DecodedExten *decodedExt;
983 CertificatePoliciesSyntax *snaccObj;
984 CE_CertPolicies *cdsaObj;
985 bool brtn;
986 CssmAllocator &alloc = fieldValue.allocator;
987 brtn = GetFieldTop<CertificatePoliciesSyntax, CE_CertPolicies>(
988 cert,
989 index,
990 numFields,
991 fieldValue.allocator,
992 id_ce_certificatePolicies,
993 snaccObj,
994 cdsaObj,
995 decodedExt);
996 if(!brtn) {
997 return false;
998 }
999
1000 /* brute force CertificatePoliciesSyntax --> CE_CertPolicies */
1001 cdsaObj->numPolicies = snaccObj->Count();
1002 unsigned sz = cdsaObj->numPolicies * sizeof(CE_PolicyInformation);
1003 cdsaObj->policies = (CE_PolicyInformation *)alloc.malloc(sz);
1004 memset(cdsaObj->policies, 0, sz);
1005 snaccObj->SetCurrToFirst();
1006 for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
1007 CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
1008 PolicyInformation *sPolInfo = snaccObj->Curr();
1009 CssmOid &cOid = CssmOid::overlay(cPolInfo->certPolicyId);
1010 CL_snaccOidToCssm(sPolInfo->policyIdentifier, cOid, alloc);
1011 if(sPolInfo->policyQualifiers == NULL) {
1012 continue;
1013 }
1014 cPolInfo->numPolicyQualifiers = sPolInfo->policyQualifiers->Count();
1015 cPolInfo->policyQualifiers = (CE_PolicyQualifierInfo *)
1016 alloc.malloc(cPolInfo->numPolicyQualifiers *
1017 sizeof(CE_PolicyQualifierInfo));
1018 sPolInfo->policyQualifiers->SetCurrToFirst();
1019 for(unsigned qualDex=0; qualDex<cPolInfo->numPolicyQualifiers; qualDex++) {
1020 PolicyQualifierInfo *sQualInfo = sPolInfo->policyQualifiers->Curr();
1021 CE_PolicyQualifierInfo *cQualInfo = &cPolInfo->policyQualifiers[qualDex];
1022
1023 /*
1024 * leaf.
1025 * policyQualifierId == id_qt_cps : IA5String - decode and return
1026 * contents. Else return whole thing.
1027 */
1028 CssmOid &cOid2 = CssmOid::overlay(cQualInfo->policyQualifierId);
1029 CL_snaccOidToCssm(sQualInfo->policyQualifierId, cOid2, alloc);
1030 /* convert this: */
1031 CSM_Buffer *cbuf = sQualInfo->qualifier->value;
1032 /* to this */
1033 CssmRemoteData outData(alloc, cQualInfo->qualifier);
1034 if(sQualInfo->policyQualifierId == id_qt_cps) {
1035 IA5String ia5;
1036 CssmAutoData berData(alloc, cbuf->Access(), cbuf->Length());
1037 /* error is fatal, punt the whole kit'n'kaboodle and leak */
1038 SC_decodeAsnObj(berData, ia5);
1039 char *src = ia5;
1040 outData.copy(src, ia5.Len());
1041 }
1042 else {
1043 outData.copy(cbuf->Access(), cbuf->Length());
1044 }
1045 outData.release();
1046 sPolInfo->policyQualifiers->GoNext();
1047 }
1048 snaccObj->GoNext();
1049 }
1050 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
1051 return true;
1052}
1053
1054void freeFieldCertPolicies (
1055 CssmOwnedData &fieldValue)
1056{
1057 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
1058 CssmAllocator &alloc = fieldValue.allocator;
1059 CE_CertPolicies *cdsaObj = (CE_CertPolicies *)cssmExt->value.parsedValue;
1060 for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
1061 CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
1062 alloc.free(cPolInfo->certPolicyId.Data);
1063 for(unsigned qualDex=0; qualDex<cPolInfo->numPolicyQualifiers; qualDex++) {
1064 CE_PolicyQualifierInfo *cQualInfo = &cPolInfo->policyQualifiers[qualDex];
1065 alloc.free(cQualInfo->policyQualifierId.Data);
1066 alloc.free(cQualInfo->qualifier.Data);
1067 }
1068 alloc.free(cPolInfo->policyQualifiers);
1069 }
1070 alloc.free(cdsaObj->policies);
1071 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
1072}
1073
1074/***
1075 *** Netscape cert type
1076 *** CDSA Format: CE_NetscapeCertType (a uint16)
1077 *** SNACC format: AsnBits
1078 *** OID: CSSMOID_NetscapeCertType
1079 ***/
1080void setFieldNetscapeCertType(
1081 DecodedCert &cert,
1082 const CssmData &fieldValue)
1083{
1084 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
1085 CE_NetscapeCertType *cdsaObj = (CE_NetscapeCertType *)cssmExt->value.parsedValue;
1086
1087 char bits[sizeof(CE_NetscapeCertType)];
1088 bits[0] = static_cast<char>((*cdsaObj) >> 8);
1089 bits[1] = static_cast<char>(*cdsaObj);
1090 memmove(bits, cdsaObj, sizeof(CE_NetscapeCertType));
1091 AsnBits *snaccObj = new AsnBits(bits, sizeof(CE_NetscapeCertType) * 8);
1092
1093 /* add to mExtensions */
1094 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
1095}
1096
1097bool getFieldNetscapeCertType(
1098 const DecodedCert &cert,
1099 unsigned index, // which occurrence (0 = first)
1100 uint32 &numFields, // RETURNED
1101 CssmOwnedData &fieldValue)
1102{
1103 DecodedExten *decodedExt;
1104 AsnBits *snaccObj;
1105 CE_NetscapeCertType *cdsaObj;
1106 bool brtn;
1107
1108 brtn = GetFieldTop<AsnBits, CE_NetscapeCertType>(
1109 cert,
1110 index,
1111 numFields,
1112 fieldValue.allocator,
1113 id_netscape_cert_type,
1114 snaccObj,
1115 cdsaObj,
1116 decodedExt);
1117 if(!brtn) {
1118 return false;
1119 }
1120
1121 unsigned toCopy = (snaccObj->BitLen() + 7) / 8;
1122 if(toCopy > 2) {
1123 /* I hope I never see this... */
1124 errorLog0("getFieldNetscapeCertType: bitstring larger than 2 bytes!\n");
1125 toCopy = 2;
1126 }
1127 unsigned char bits[2] = {0, 0};
1128 memmove(bits, snaccObj->BitOcts(), toCopy);
1129 *cdsaObj = (((unsigned)bits[0]) << 8) | bits[1];
1130 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
1131 return true;
1132}
1133
1134/***
1135 *** unknown extensions
1136 *** CDSA format: raw bytes in a CSSM_DATA. This data is the BER-encoding of
1137 *** some extension struct we don't know about.
1138 *** SNACC format AsnOcts
1139 *** OID CSSMOID_X509V3CertificateExtensionCStruct
1140 ***/
1141
1142void setFieldUnknownExt(
1143 DecodedCert &cert,
1144 const CssmData &fieldValue)
1145{
1146 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true);
1147 AsnOcts *snaccObj = new AsnOcts(
1148 reinterpret_cast<char *>(cssmExt->BERvalue.Data),
1149 cssmExt->BERvalue.Length);
1150 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, true);
1151}
1152
1153bool getFieldUnknownExt(
1154 const DecodedCert &cert,
1155 unsigned index, // which occurrence (0 = first)
1156 uint32 &numFields, // RETURNED
1157 CssmOwnedData &fieldValue)
1158{
1159 AsnOid noOidLikeThis (1, 2); // a dummy argument
1160 DecodedExten *decodedExt = cert.findDecodedExt(noOidLikeThis,
1161 true, index, numFields);
1162 if(decodedExt == NULL) {
1163 return false;
1164 }
1165 /* failure of this dynamic_cast is fatal */
1166 AsnOcts *snaccObj = dynamic_cast<AsnOcts *>(decodedExt->snaccObj);
1167 if(snaccObj == NULL) {
1168 errorLog0("getFieldUnknownExt: dynamic_cast failure\n");
1169 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
1170 }
1171 char *octData = *snaccObj;
1172 CssmAutoData encodedBytes(fieldValue.allocator, octData, snaccObj->Len());
1173 /* easier way to do this...? */
1174 CssmData cData = encodedBytes.release();
1175 getFieldExtenCommon(&cData, *decodedExt, fieldValue);
1176 return true;
1177}
1178
1179void freeFieldUnknownExt (
1180 CssmOwnedData &fieldValue)
1181{
1182 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true);
1183 CssmAllocator &alloc = fieldValue.allocator;
1184 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
1185}
1186
1187
1188
1189#if template_pcode
1190
1191/***
1192 *** Subject alternate name
1193 *** CDSA Format: CE_GeneralNames
1194 *** SNACC format: GeneralNames
1195 *** OID: CSSMOID_SubjectAltName
1196 ***/
1197void setFieldSomeExt(
1198 DecodedCert &cert,
1199 const CssmData &fieldValue)
1200{
1201 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
1202 new an approppriate AsnType snaccObj (KeyUsage, etc.);
1203 extension-specific e.g. CE_KeyUsage *cdsaObj = cssmExt->value.parsedValue;
1204 /* brute-force cdsaObj --> snaccObj */
1205 ...
1206 /* add to mExtensions */
1207 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
1208}
1209
1210bool getFieldSomeExt(
1211 const DecodedCert &cert,
1212 unsigned index, // which occurrence (0 = first)
1213 uint32 &numFields, // RETURNED
1214 CssmOwnedData &fieldValue)
1215{
1216 DecodedExten *decodedExt;
1217 e.g. ExtKeyUsageSyntax *snaccObj;
1218 e.g. CE_ExtendedKeyUsage *cdsaObj;
1219 bool brtn;
1220
1221 brtn = GetFieldTop<ExtKeyUsageSyntax, CE_ExtendedKeyUsage>(
1222 cert,
1223 index,
1224 numFields,
1225 fieldValue.allocator,
1226 e.g. id_ce_extKeyUsage,
1227 snaccObj,
1228 cdsaObj,
1229 decodedExt);
1230 if(!brtn) {
1231 return false;
1232 }
1233
1234 brute force snaccObj --> cdsaObj;
1235 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
1236 return true;
1237}
1238
1239/* only used if complex structs below cssmExt->value.parsedValue */
1240void freeFieldSomeExt (
1241 CssmOwnedData &fieldValue)
1242{
1243 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
1244 CssmAllocator &alloc = fieldValue.allocator;
1245 free the stuff in cssmExt->value.parsedValue;
1246 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
1247}
1248
1249#endif