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