]> git.saurik.com Git - apple/security.git/blame - AppleX509CL/CLCertExtensions.cpp
Security-54.1.3.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;
29654253 808 cdsaObj->generalNames = (CE_GeneralNames *)alloc.malloc(sizeof(CE_GeneralNames));
bac41a7b
A
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));
29654253 836 alloc.free(cdsaObj->generalName);
bac41a7b
A
837 }
838 memset(cdsaObj, 0, sizeof(CE_GeneralNames));
839}
840
841void freeFieldAuthorityKeyId (
842 CssmOwnedData &fieldValue)
843{
844 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
845 CssmAllocator &alloc = fieldValue.allocator;
846 CE_AuthorityKeyID *cdsaObj = (CE_AuthorityKeyID *)cssmExt->value.parsedValue;
847 alloc.free(cdsaObj->keyIdentifier.Data);
848 freeFieldGeneralNames(cdsaObj->generalNames, alloc);
29654253 849 alloc.free(cdsaObj->generalNames);
bac41a7b
A
850 alloc.free(cdsaObj->serialNumber.Data);
851 memset(cdsaObj, 0, sizeof(CE_AuthorityKeyID));
852 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
853}
854
855/***
856 *** Subject alternate name
857 *** CDSA Format: CE_GeneralNames
858 *** SNACC format: GeneralNames
859 *** OID: CSSMOID_SubjectAltName
860 ***/
861void setFieldSubjAltName(
862 DecodedCert &cert,
863 const CssmData &fieldValue)
864{
865 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
866 CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue;
867 GeneralNames *snaccObj = CL_cdsaGeneralNamesToSnacc(*cdsaObj);
868 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
869}
870
871bool getFieldSubjAltName(
872 const DecodedCert &cert,
873 unsigned index, // which occurrence (0 = first)
874 uint32 &numFields, // RETURNED
875 CssmOwnedData &fieldValue)
876{
877 DecodedExten *decodedExt;
878 GeneralNames *snaccObj;
879 CE_GeneralNames *cdsaObj;
880 bool brtn;
881
882 brtn = GetFieldTop<GeneralNames, CE_GeneralNames>(
883 cert,
884 index,
885 numFields,
886 fieldValue.allocator,
887 id_ce_subjectAltName,
888 snaccObj,
889 cdsaObj,
890 decodedExt);
891 if(!brtn) {
892 return false;
893 }
894 CL_snaccGeneralNamesToCdsa(*snaccObj, *cdsaObj, fieldValue.allocator);
895 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
896 return true;
897}
898
899void freeFieldSubjAltName (
900 CssmOwnedData &fieldValue)
901{
902 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
903 CssmAllocator &alloc = fieldValue.allocator;
904 CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue;
905 freeFieldGeneralNames(cdsaObj, alloc);
906 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
907}
908
909/***
910 *** Certificate Policies
911 *** CDSA Format: CE_CertPolicies
912 *** SNACC format: CertificatePoliciesSyntax
913 *** OID: CSSMOID_CertificatePolicies
914 ***/
915
916#define MAX_IA5_NAME_SIZE 1024
917
918void setFieldCertPolicies(
919 DecodedCert &cert,
920 const CssmData &fieldValue)
921{
922 CssmAllocator &alloc = CssmAllocator::standard();
923 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
924 CertificatePoliciesSyntax *snaccObj = new CertificatePoliciesSyntax;
925 CE_CertPolicies *cdsaObj = (CE_CertPolicies *)cssmExt->value.parsedValue;
926
927 /* brute-force cdsaObj --> snaccObj */
928 for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
929 CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
930 PolicyInformation *sPolInfo = snaccObj->Append();
931 sPolInfo->policyIdentifier.Set((char *)cPolInfo->certPolicyId.Data,
932 cPolInfo->certPolicyId.Length);
933 if(cPolInfo->numPolicyQualifiers != 0) {
934 sPolInfo->policyQualifiers = new PolicyInformationSeqOf;
935 }
936 for(unsigned qualDex=0; qualDex<cPolInfo->numPolicyQualifiers; qualDex++) {
937 CE_PolicyQualifierInfo *cQualInfo = &cPolInfo->policyQualifiers[qualDex];
938 PolicyQualifierInfo *sQualInfo = sPolInfo->policyQualifiers->Append();
939
940 /* OK we're at the lowest level.
941 * policyQualifierId == id_qt_cps: qualifier is an IA5 string,
942 * incoming data is its contents. Else incoming data is an encoded
943 * blob we pass on directly.
944 */
945 sQualInfo->policyQualifierId.Set(
946 (char *)cQualInfo->policyQualifierId.Data,
947 cQualInfo->policyQualifierId.Length);
948
949 /* we'll convert this incoming ptr/len.... */
950 uint8 *rawData = cQualInfo->qualifier.Data;
951 unsigned rawDataLen = cQualInfo->qualifier.Length;
952 /* to this, somehow; it'll be used to build the required AsnAny. */
953 CssmAutoData aData(alloc);
954
955 if(sQualInfo->policyQualifierId == id_qt_cps) {
956 /* build & encode an IA5String */
957 IA5String *ia5 = new IA5String((char *)rawData, rawDataLen);
958 SC_encodeAsnObj(*ia5, aData, MAX_IA5_NAME_SIZE);
959 delete ia5;
960 }
961 else {
962 /* copy over directly */
963 aData.copy(rawData, rawDataLen);
964 }
965
966 /* install the result into CSM_Buffer, which mallocs & copies */
967 sQualInfo->qualifier = new AsnAny;
968 char *cp = aData;
969 sQualInfo->qualifier->value = new CSM_Buffer(cp, aData.length());
970 aData.reset();
971 } /* for each qualifier */
972 } /* for each policy */
973
974 /* add to mExtensions */
975 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
976}
977
978bool getFieldCertPolicies(
979 const DecodedCert &cert,
980 unsigned index, // which occurrence (0 = first)
981 uint32 &numFields, // RETURNED
982 CssmOwnedData &fieldValue)
983{
984 DecodedExten *decodedExt;
985 CertificatePoliciesSyntax *snaccObj;
986 CE_CertPolicies *cdsaObj;
987 bool brtn;
988 CssmAllocator &alloc = fieldValue.allocator;
989 brtn = GetFieldTop<CertificatePoliciesSyntax, CE_CertPolicies>(
990 cert,
991 index,
992 numFields,
993 fieldValue.allocator,
994 id_ce_certificatePolicies,
995 snaccObj,
996 cdsaObj,
997 decodedExt);
998 if(!brtn) {
999 return false;
1000 }
1001
1002 /* brute force CertificatePoliciesSyntax --> CE_CertPolicies */
1003 cdsaObj->numPolicies = snaccObj->Count();
1004 unsigned sz = cdsaObj->numPolicies * sizeof(CE_PolicyInformation);
1005 cdsaObj->policies = (CE_PolicyInformation *)alloc.malloc(sz);
1006 memset(cdsaObj->policies, 0, sz);
1007 snaccObj->SetCurrToFirst();
1008 for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
1009 CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
1010 PolicyInformation *sPolInfo = snaccObj->Curr();
1011 CssmOid &cOid = CssmOid::overlay(cPolInfo->certPolicyId);
1012 CL_snaccOidToCssm(sPolInfo->policyIdentifier, cOid, alloc);
1013 if(sPolInfo->policyQualifiers == NULL) {
1014 continue;
1015 }
1016 cPolInfo->numPolicyQualifiers = sPolInfo->policyQualifiers->Count();
1017 cPolInfo->policyQualifiers = (CE_PolicyQualifierInfo *)
1018 alloc.malloc(cPolInfo->numPolicyQualifiers *
1019 sizeof(CE_PolicyQualifierInfo));
1020 sPolInfo->policyQualifiers->SetCurrToFirst();
1021 for(unsigned qualDex=0; qualDex<cPolInfo->numPolicyQualifiers; qualDex++) {
1022 PolicyQualifierInfo *sQualInfo = sPolInfo->policyQualifiers->Curr();
1023 CE_PolicyQualifierInfo *cQualInfo = &cPolInfo->policyQualifiers[qualDex];
1024
1025 /*
1026 * leaf.
1027 * policyQualifierId == id_qt_cps : IA5String - decode and return
1028 * contents. Else return whole thing.
1029 */
1030 CssmOid &cOid2 = CssmOid::overlay(cQualInfo->policyQualifierId);
1031 CL_snaccOidToCssm(sQualInfo->policyQualifierId, cOid2, alloc);
1032 /* convert this: */
1033 CSM_Buffer *cbuf = sQualInfo->qualifier->value;
1034 /* to this */
1035 CssmRemoteData outData(alloc, cQualInfo->qualifier);
1036 if(sQualInfo->policyQualifierId == id_qt_cps) {
1037 IA5String ia5;
1038 CssmAutoData berData(alloc, cbuf->Access(), cbuf->Length());
1039 /* error is fatal, punt the whole kit'n'kaboodle and leak */
1040 SC_decodeAsnObj(berData, ia5);
1041 char *src = ia5;
1042 outData.copy(src, ia5.Len());
1043 }
1044 else {
1045 outData.copy(cbuf->Access(), cbuf->Length());
1046 }
1047 outData.release();
1048 sPolInfo->policyQualifiers->GoNext();
1049 }
1050 snaccObj->GoNext();
1051 }
1052 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
1053 return true;
1054}
1055
1056void freeFieldCertPolicies (
1057 CssmOwnedData &fieldValue)
1058{
1059 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
1060 CssmAllocator &alloc = fieldValue.allocator;
1061 CE_CertPolicies *cdsaObj = (CE_CertPolicies *)cssmExt->value.parsedValue;
1062 for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
1063 CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
1064 alloc.free(cPolInfo->certPolicyId.Data);
1065 for(unsigned qualDex=0; qualDex<cPolInfo->numPolicyQualifiers; qualDex++) {
1066 CE_PolicyQualifierInfo *cQualInfo = &cPolInfo->policyQualifiers[qualDex];
1067 alloc.free(cQualInfo->policyQualifierId.Data);
1068 alloc.free(cQualInfo->qualifier.Data);
1069 }
1070 alloc.free(cPolInfo->policyQualifiers);
1071 }
1072 alloc.free(cdsaObj->policies);
1073 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
1074}
1075
1076/***
1077 *** Netscape cert type
1078 *** CDSA Format: CE_NetscapeCertType (a uint16)
1079 *** SNACC format: AsnBits
1080 *** OID: CSSMOID_NetscapeCertType
1081 ***/
1082void setFieldNetscapeCertType(
1083 DecodedCert &cert,
1084 const CssmData &fieldValue)
1085{
1086 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
1087 CE_NetscapeCertType *cdsaObj = (CE_NetscapeCertType *)cssmExt->value.parsedValue;
1088
1089 char bits[sizeof(CE_NetscapeCertType)];
1090 bits[0] = static_cast<char>((*cdsaObj) >> 8);
1091 bits[1] = static_cast<char>(*cdsaObj);
1092 memmove(bits, cdsaObj, sizeof(CE_NetscapeCertType));
1093 AsnBits *snaccObj = new AsnBits(bits, sizeof(CE_NetscapeCertType) * 8);
1094
1095 /* add to mExtensions */
1096 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
1097}
1098
1099bool getFieldNetscapeCertType(
1100 const DecodedCert &cert,
1101 unsigned index, // which occurrence (0 = first)
1102 uint32 &numFields, // RETURNED
1103 CssmOwnedData &fieldValue)
1104{
1105 DecodedExten *decodedExt;
1106 AsnBits *snaccObj;
1107 CE_NetscapeCertType *cdsaObj;
1108 bool brtn;
1109
1110 brtn = GetFieldTop<AsnBits, CE_NetscapeCertType>(
1111 cert,
1112 index,
1113 numFields,
1114 fieldValue.allocator,
1115 id_netscape_cert_type,
1116 snaccObj,
1117 cdsaObj,
1118 decodedExt);
1119 if(!brtn) {
1120 return false;
1121 }
1122
1123 unsigned toCopy = (snaccObj->BitLen() + 7) / 8;
1124 if(toCopy > 2) {
1125 /* I hope I never see this... */
1126 errorLog0("getFieldNetscapeCertType: bitstring larger than 2 bytes!\n");
1127 toCopy = 2;
1128 }
1129 unsigned char bits[2] = {0, 0};
1130 memmove(bits, snaccObj->BitOcts(), toCopy);
1131 *cdsaObj = (((unsigned)bits[0]) << 8) | bits[1];
1132 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
1133 return true;
1134}
1135
1136/***
1137 *** unknown extensions
1138 *** CDSA format: raw bytes in a CSSM_DATA. This data is the BER-encoding of
1139 *** some extension struct we don't know about.
1140 *** SNACC format AsnOcts
1141 *** OID CSSMOID_X509V3CertificateExtensionCStruct
1142 ***/
1143
1144void setFieldUnknownExt(
1145 DecodedCert &cert,
1146 const CssmData &fieldValue)
1147{
1148 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true);
1149 AsnOcts *snaccObj = new AsnOcts(
1150 reinterpret_cast<char *>(cssmExt->BERvalue.Data),
1151 cssmExt->BERvalue.Length);
1152 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, true);
1153}
1154
1155bool getFieldUnknownExt(
1156 const DecodedCert &cert,
1157 unsigned index, // which occurrence (0 = first)
1158 uint32 &numFields, // RETURNED
1159 CssmOwnedData &fieldValue)
1160{
1161 AsnOid noOidLikeThis (1, 2); // a dummy argument
1162 DecodedExten *decodedExt = cert.findDecodedExt(noOidLikeThis,
1163 true, index, numFields);
1164 if(decodedExt == NULL) {
1165 return false;
1166 }
1167 /* failure of this dynamic_cast is fatal */
1168 AsnOcts *snaccObj = dynamic_cast<AsnOcts *>(decodedExt->snaccObj);
1169 if(snaccObj == NULL) {
1170 errorLog0("getFieldUnknownExt: dynamic_cast failure\n");
1171 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
1172 }
1173 char *octData = *snaccObj;
1174 CssmAutoData encodedBytes(fieldValue.allocator, octData, snaccObj->Len());
1175 /* easier way to do this...? */
1176 CssmData cData = encodedBytes.release();
1177 getFieldExtenCommon(&cData, *decodedExt, fieldValue);
1178 return true;
1179}
1180
1181void freeFieldUnknownExt (
1182 CssmOwnedData &fieldValue)
1183{
1184 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true);
1185 CssmAllocator &alloc = fieldValue.allocator;
1186 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
1187}
1188
1189
1190
1191#if template_pcode
1192
1193/***
1194 *** Subject alternate name
1195 *** CDSA Format: CE_GeneralNames
1196 *** SNACC format: GeneralNames
1197 *** OID: CSSMOID_SubjectAltName
1198 ***/
1199void setFieldSomeExt(
1200 DecodedCert &cert,
1201 const CssmData &fieldValue)
1202{
1203 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
1204 new an approppriate AsnType snaccObj (KeyUsage, etc.);
1205 extension-specific e.g. CE_KeyUsage *cdsaObj = cssmExt->value.parsedValue;
1206 /* brute-force cdsaObj --> snaccObj */
1207 ...
1208 /* add to mExtensions */
1209 cert.addExtension(snaccObj, cssmExt->extnId, cssmExt->critical, false);
1210}
1211
1212bool getFieldSomeExt(
1213 const DecodedCert &cert,
1214 unsigned index, // which occurrence (0 = first)
1215 uint32 &numFields, // RETURNED
1216 CssmOwnedData &fieldValue)
1217{
1218 DecodedExten *decodedExt;
1219 e.g. ExtKeyUsageSyntax *snaccObj;
1220 e.g. CE_ExtendedKeyUsage *cdsaObj;
1221 bool brtn;
1222
1223 brtn = GetFieldTop<ExtKeyUsageSyntax, CE_ExtendedKeyUsage>(
1224 cert,
1225 index,
1226 numFields,
1227 fieldValue.allocator,
1228 e.g. id_ce_extKeyUsage,
1229 snaccObj,
1230 cdsaObj,
1231 decodedExt);
1232 if(!brtn) {
1233 return false;
1234 }
1235
1236 brute force snaccObj --> cdsaObj;
1237 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
1238 return true;
1239}
1240
1241/* only used if complex structs below cssmExt->value.parsedValue */
1242void freeFieldSomeExt (
1243 CssmOwnedData &fieldValue)
1244{
1245 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
1246 CssmAllocator &alloc = fieldValue.allocator;
1247 free the stuff in cssmExt->value.parsedValue;
1248 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
1249}
1250
1251#endif