]> git.saurik.com Git - apple/security.git/blob - AppleX509CL/CLCertExtensions.cpp
7cc7d90a2342ba0365fc3ffbdecb6777bb7a8be2
[apple/security.git] / AppleX509CL / CLCertExtensions.cpp
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 "CLCertExtensions.h"
30 #include "CLFieldsCommon.h"
31 #include "clNssUtils.h"
32 #include "clNameUtils.h"
33 #include <Security/utilities.h>
34 #include <Security/oidscert.h>
35 #include <Security/oidsattr.h>
36 #include <Security/cssmerr.h>
37 #include <Security/x509defs.h>
38 #include <Security/certextensions.h>
39 #include <Security/globalizer.h>
40 #include <SecurityNssAsn1/certExtensionTemplates.h>
41
42
43 /***
44 *** get/set/free functions called out from CertFields.cpp
45 ***/
46
47 /***
48 *** KeyUsage
49 *** CDSA format CE_KeyUsage
50 *** NSS format CSSM_DATA, length 2
51 *** OID CSSMOID_KeyUsage
52 ***/
53
54 void setFieldKeyUsage(
55 DecodedItem &cert,
56 const CssmData &fieldValue)
57 {
58 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue,
59 false);
60 CE_KeyUsage *cdsaObj = (CE_KeyUsage *)cssmExt->value.parsedValue;
61
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);
73
74 /* add to mExtensions */
75 cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
76 NSS_KeyUsageTemplate);
77 }
78
79
80 bool getFieldKeyUsage(
81 DecodedItem &cert,
82 unsigned index, // which occurrence (0 = first)
83 uint32 &numFields, // RETURNED
84 CssmOwnedData &fieldValue)
85 {
86 const DecodedExten *decodedExt;
87 CSSM_DATA *nssObj;
88 CE_KeyUsage *cdsaObj;
89 bool brtn;
90
91 brtn = cert.GetExtenTop<CSSM_DATA, CE_KeyUsage>(
92 index,
93 numFields,
94 fieldValue.allocator,
95 CSSMOID_KeyUsage,
96 nssObj,
97 cdsaObj,
98 decodedExt);
99 if(!brtn) {
100 return false;
101 }
102
103 /* make a copy - can't modify length in place */
104 CSSM_DATA bitString = *nssObj;
105 clNssBitStringToCssm(bitString);
106 unsigned toCopy = bitString.Length;
107 if(toCopy > 2) {
108 /* I hope I never see this... */
109 clErrorLog("getFieldKeyUsage: KeyUsage larger than 2 bytes!");
110 toCopy = 2;
111 }
112 unsigned char bits[2] = {0, 0};
113 memmove(bits, bitString.Data, toCopy);
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
124 *** NSS format CE_BasicConstraints
125 *** OID CSSMOID_BasicConstraints
126 ***/
127
128 void setFieldBasicConstraints(
129 DecodedItem &cert,
130 const CssmData &fieldValue)
131 {
132 CSSM_X509_EXTENSION_PTR cssmExt =
133 verifySetFreeExtension(fieldValue, false);
134 CE_BasicConstraints *cdsaObj =
135 (CE_BasicConstraints *)cssmExt->value.parsedValue;
136
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);
146 if(cdsaObj->pathLenConstraintPresent) {
147 clIntToData(cdsaObj->pathLenConstraint,
148 nssObj->pathLenConstraint, arenaAlloc);
149 }
150
151 /* add to mExtensions */
152 cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
153 NSS_BasicConstraintsTemplate);
154 }
155
156
157 bool getFieldBasicConstraints(
158 DecodedItem &cert,
159 unsigned index, // which occurrence (0 = first)
160 uint32 &numFields, // RETURNED
161 CssmOwnedData &fieldValue)
162 {
163 const DecodedExten *decodedExt;
164 NSS_BasicConstraints *nssObj;
165 CE_BasicConstraints *cdsaObj;
166 bool brtn;
167
168 brtn = cert.GetExtenTop<NSS_BasicConstraints, CE_BasicConstraints>(
169 index,
170 numFields,
171 fieldValue.allocator,
172 CSSMOID_BasicConstraints,
173 nssObj,
174 cdsaObj,
175 decodedExt);
176 if(!brtn) {
177 return false;
178 }
179
180 if(nssObj->cA.Data == NULL) {
181 /* default */
182 cdsaObj->cA = CSSM_FALSE;
183 }
184 else {
185 cdsaObj->cA = clNssBoolToCssm(nssObj->cA);
186 }
187 if(nssObj->pathLenConstraint.Data == NULL) {
188 /* optional */
189 cdsaObj->pathLenConstraintPresent = CSSM_FALSE;
190 cdsaObj->pathLenConstraint = 0;
191 }
192 else {
193 cdsaObj->pathLenConstraintPresent = CSSM_TRUE;
194 cdsaObj->pathLenConstraint = clDataToInt(nssObj->pathLenConstraint);
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
205 *** NSS format: NSS_ExtKeyUsage
206 *** OID CSSMOID_ExtendedKeyUsage
207 ***/
208 void setFieldExtKeyUsage(
209 DecodedItem &cert,
210 const CssmData &fieldValue)
211 {
212 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue,
213 false);
214 CE_ExtendedKeyUsage *cdsaObj =
215 (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue;
216
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]);
231 }
232
233 /* add to mExtensions */
234 cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
235 NSS_ExtKeyUsageTemplate);
236 }
237
238 bool getFieldExtKeyUsage(
239 DecodedItem &cert,
240 unsigned index, // which occurrence (0 = first)
241 uint32 &numFields, // RETURNED
242 CssmOwnedData &fieldValue)
243 {
244 const DecodedExten *decodedExt;
245 NSS_ExtKeyUsage *nssObj;
246 CE_ExtendedKeyUsage *cdsaObj;
247 bool brtn;
248 CssmAllocator &alloc = fieldValue.allocator;
249
250 brtn = cert.GetExtenTop<NSS_ExtKeyUsage, CE_ExtendedKeyUsage>(
251 index,
252 numFields,
253 alloc,
254 CSSMOID_ExtendedKeyUsage,
255 nssObj,
256 cdsaObj,
257 decodedExt);
258 if(!brtn) {
259 return false;
260 }
261
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]);
272 }
273
274 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
275 return true;
276 }
277
278 void freeFieldExtKeyUsage(
279 CssmOwnedData &fieldValue)
280 {
281 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
282 CssmAllocator &alloc = fieldValue.allocator;
283 CE_ExtendedKeyUsage *cdsaObj =
284 (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue;
285 unsigned oidDex;
286 for(oidDex=0; oidDex<cdsaObj->numPurposes; oidDex++) {
287 alloc.free(cdsaObj->purposes[oidDex].Data);
288 }
289 alloc.free(cdsaObj->purposes);
290 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
291 }
292
293 /***
294 *** Subject Key Identifier
295 *** CDSA format: CE_SubjectKeyID, which is just a CSSM_DATA
296 *** OID CSSMOID_SubjectKeyIdentifier
297 ***/
298
299 void setFieldSubjectKeyId(
300 DecodedItem &cert,
301 const CssmData &fieldValue)
302 {
303 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue,
304 false);
305 CE_SubjectKeyID *cdsaObj = (CE_SubjectKeyID *)cssmExt->value.parsedValue;
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);
313 }
314
315 bool getFieldSubjectKeyId(
316 DecodedItem &cert,
317 unsigned index, // which occurrence (0 = first)
318 uint32 &numFields, // RETURNED
319 CssmOwnedData &fieldValue)
320 {
321 const DecodedExten *decodedExt;
322 CSSM_DATA *nssObj;
323 CE_SubjectKeyID *cdsaObj;
324 bool brtn;
325 CssmAllocator &alloc = fieldValue.allocator;
326
327 brtn = cert.GetExtenTop<CSSM_DATA, CE_SubjectKeyID>(
328 index,
329 numFields,
330 alloc,
331 CSSMOID_SubjectKeyIdentifier,
332 nssObj,
333 cdsaObj,
334 decodedExt);
335 if(!brtn) {
336 return false;
337 }
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);
343 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
344 return true;
345 }
346
347 void freeFieldSubjectKeyId (
348 CssmOwnedData &fieldValue)
349 {
350 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
351 CssmAllocator &alloc = fieldValue.allocator;
352 CE_SubjectKeyID *cdsaObj = (CE_SubjectKeyID *)cssmExt->value.parsedValue;
353 alloc.free(cdsaObj->Data);
354 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
355 }
356
357 /***
358 *** Authority Key Identifier
359 *** CDSA format: CE_AuthorityKeyID
360 *** NSS format: NSS_AuthorityKeyId
361 *** OID CSSMOID_AuthorityKeyIdentifier
362 ***/
363
364 void setFieldAuthorityKeyId(
365 DecodedItem &cert,
366 const CssmData &fieldValue)
367 {
368 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue,
369 false);
370 CE_AuthorityKeyID *cdsaObj =
371 (CE_AuthorityKeyID *)cssmExt->value.parsedValue;
372
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);
385 }
386
387 bool getFieldAuthorityKeyId(
388 DecodedItem &cert,
389 unsigned index, // which occurrence (0 = first)
390 uint32 &numFields, // RETURNED
391 CssmOwnedData &fieldValue)
392 {
393 const DecodedExten *decodedExt;
394 NSS_AuthorityKeyId *nssObj;
395 CE_AuthorityKeyID *cdsaObj;
396 bool brtn;
397 CssmAllocator &alloc = fieldValue.allocator;
398
399 brtn = cert.GetExtenTop<NSS_AuthorityKeyId, CE_AuthorityKeyID>(
400 index,
401 numFields,
402 alloc,
403 CSSMOID_AuthorityKeyIdentifier,
404 nssObj,
405 cdsaObj,
406 decodedExt);
407 if(!brtn) {
408 return false;
409 }
410 assert(nssObj != NULL);
411
412 /* nssObj --> cdsaObj */
413 CL_nssAuthorityKeyIdToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
414
415 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
416 return true;
417 }
418
419 void freeFieldAuthorityKeyId (
420 CssmOwnedData &fieldValue)
421 {
422 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
423 CssmAllocator &alloc = fieldValue.allocator;
424 CE_AuthorityKeyID *cdsaObj = (CE_AuthorityKeyID *)cssmExt->value.parsedValue;
425 CL_freeAuthorityKeyId(*cdsaObj, alloc);
426 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
427 }
428
429 /***
430 *** Subject/Issuer alternate name
431 *** CDSA Format: CE_GeneralNames
432 *** NSS format: NSS_GeneralNames
433 *** OID: CSSMOID_SubjectAltName, CSSMOID_IssuerAltName
434 ***/
435 void setFieldSubjIssuerAltName(
436 DecodedItem &cert,
437 const CssmData &fieldValue)
438 {
439 CSSM_X509_EXTENSION_PTR cssmExt =
440 verifySetFreeExtension(fieldValue, false);
441 CE_GeneralNames *cdsaObj = (CE_GeneralNames *)cssmExt->value.parsedValue;
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);
455 }
456
457 bool getFieldSubjAltName(
458 DecodedItem &cert,
459 unsigned index, // which occurrence (0 = first)
460 uint32 &numFields, // RETURNED
461 CssmOwnedData &fieldValue)
462 {
463 const DecodedExten *decodedExt;
464 NSS_GeneralNames *nssObj;
465 CE_GeneralNames *cdsaObj;
466 bool brtn;
467
468 brtn = cert.GetExtenTop<NSS_GeneralNames, CE_GeneralNames>(
469 index,
470 numFields,
471 fieldValue.allocator,
472 CSSMOID_SubjectAltName,
473 nssObj,
474 cdsaObj,
475 decodedExt);
476 if(!brtn) {
477 return false;
478 }
479 CL_nssGeneralNamesToCssm(*nssObj, *cdsaObj,
480 cert.coder(), fieldValue.allocator);
481 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
482 return true;
483 }
484
485 bool getFieldIssuerAltName(
486 DecodedItem &cert,
487 unsigned index, // which occurrence (0 = first)
488 uint32 &numFields, // RETURNED
489 CssmOwnedData &fieldValue)
490 {
491 const DecodedExten *decodedExt;
492 NSS_GeneralNames *nssObj;
493 CE_GeneralNames *cdsaObj;
494 bool brtn;
495
496 brtn = cert.GetExtenTop<NSS_GeneralNames, CE_GeneralNames>(
497 index,
498 numFields,
499 fieldValue.allocator,
500 CSSMOID_IssuerAltName,
501 nssObj,
502 cdsaObj,
503 decodedExt);
504 if(!brtn) {
505 return false;
506 }
507 CL_nssGeneralNamesToCssm(*nssObj, *cdsaObj,
508 cert.coder(), fieldValue.allocator);
509 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
510 return true;
511 }
512
513 void freeFieldSubjIssuerAltName (
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;
519 CL_freeCssmGeneralNames(cdsaObj, alloc);
520 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
521 }
522
523 /***
524 *** Certificate Policies
525 *** CDSA Format: CE_CertPolicies
526 *** NSS format : NSS_CertPolicies
527 *** OID: CSSMOID_CertificatePolicies
528 ***/
529
530 #define MAX_IA5_NAME_SIZE 1024
531
532 void setFieldCertPolicies(
533 DecodedItem &cert,
534 const CssmData &fieldValue)
535 {
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;
544
545 if(cdsaObj->numPolicies) {
546 nssObj->policies =
547 (NSS_PolicyInformation **)clNssNullArray(
548 cdsaObj->numPolicies, coder);
549 }
550 for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
551 CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
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);
564 }
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;
573
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.
579 */
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 }
591 }
592 else {
593 /* uninterpreted, copy over directly */
594 coder.allocCopyItem(cQualInfo->qualifier,
595 nQualInfo->qualifier);
596 }
597 } /* for each qualifier */
598 } /* for each policy */
599
600 /* add to mExtensions */
601 cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
602 NSS_CertPoliciesTemplate);
603 }
604
605 bool getFieldCertPolicies(
606 DecodedItem &cert,
607 unsigned index, // which occurrence (0 = first)
608 uint32 &numFields, // RETURNED
609 CssmOwnedData &fieldValue)
610 {
611 const DecodedExten *decodedExt;
612 NSS_CertPolicies *nssObj;
613 CE_CertPolicies *cdsaObj;
614 bool brtn;
615 CssmAllocator &alloc = fieldValue.allocator;
616 brtn = cert.GetExtenTop<NSS_CertPolicies, CE_CertPolicies>(
617 index,
618 numFields,
619 fieldValue.allocator,
620 CSSMOID_CertificatePolicies,
621 nssObj,
622 cdsaObj,
623 decodedExt);
624 if(!brtn) {
625 return false;
626 }
627 assert(nssObj != NULL);
628
629 memset(cdsaObj, 0, sizeof(*cdsaObj));
630 cdsaObj->numPolicies =
631 clNssArraySize((const void **)nssObj->policies);
632 unsigned sz = cdsaObj->numPolicies * sizeof(CE_PolicyInformation);
633 if(sz) {
634 cdsaObj->policies = (CE_PolicyInformation *)alloc.malloc(sz);
635 memset(cdsaObj->policies, 0, sz);
636 }
637
638 for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
639 CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
640 NSS_PolicyInformation *nPolInfo = nssObj->policies[polDex];
641 clAllocCopyData(alloc, nPolInfo->certPolicyId,
642 cPolInfo->certPolicyId);
643 if(nPolInfo->policyQualifiers == NULL) {
644 continue;
645 }
646
647 cPolInfo->numPolicyQualifiers =
648 clNssArraySize((const void **)nPolInfo->policyQualifiers);
649 sz = cPolInfo->numPolicyQualifiers *
650 sizeof(CE_PolicyQualifierInfo);
651 cPolInfo->policyQualifiers = (CE_PolicyQualifierInfo *)
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];
661
662 /*
663 * leaf.
664 * policyQualifierId == CSSMOID_QT_CPS :
665 * IA5String - decode and return contents.
666 * Else return whole thing.
667 */
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 }
682 }
683 /* else copy out nQualInfo->qualifier */
684 clAllocCopyData(alloc, toCopy, cQualInfo->qualifier);
685 } /* for each qualifier */
686 } /* for each policy info */
687 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
688 return true;
689 }
690
691 void freeFieldCertPolicies (
692 CssmOwnedData &fieldValue)
693 {
694 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
695 CssmAllocator &alloc = fieldValue.allocator;
696 CE_CertPolicies *cdsaObj = (CE_CertPolicies *)cssmExt->value.parsedValue;
697 for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) {
698 CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex];
699 alloc.free(cPolInfo->certPolicyId.Data);
700 for(unsigned qualDex=0;
701 qualDex<cPolInfo->numPolicyQualifiers;
702 qualDex++) {
703 CE_PolicyQualifierInfo *cQualInfo =
704 &cPolInfo->policyQualifiers[qualDex];
705 alloc.free(cQualInfo->policyQualifierId.Data);
706 alloc.free(cQualInfo->qualifier.Data);
707 }
708 alloc.free(cPolInfo->policyQualifiers);
709 }
710 alloc.free(cdsaObj->policies);
711 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue,
712 // BERvalue
713 }
714
715 /***
716 *** Netscape cert type
717 *** CDSA Format: CE_NetscapeCertType (a uint16)
718 *** NSS format CSSM_DATA, length 2
719 *** OID: CSSMOID_NetscapeCertType
720 ***/
721 void setFieldNetscapeCertType(
722 DecodedItem &cert,
723 const CssmData &fieldValue)
724 {
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;
738
739 /* Adjust length for BIT STRING encoding */
740 clCssmBitStringToNss(*nssObj);
741
742 /* add to mExtensions */
743 cert.addExtension(nssObj, cssmExt->extnId, cssmExt->critical, false,
744 NSS_NetscapeCertTypeTemplate);
745 }
746
747 bool getFieldNetscapeCertType(
748 DecodedItem &cert,
749 unsigned index, // which occurrence (0 = first)
750 uint32 &numFields, // RETURNED
751 CssmOwnedData &fieldValue)
752 {
753 const DecodedExten *decodedExt;
754 CSSM_DATA *nssObj;
755 CE_NetscapeCertType *cdsaObj;
756 bool brtn;
757
758 brtn = cert.GetExtenTop<CSSM_DATA, CE_NetscapeCertType>(
759 index,
760 numFields,
761 fieldValue.allocator,
762 CSSMOID_NetscapeCertType,
763 nssObj,
764 cdsaObj,
765 decodedExt);
766 if(!brtn) {
767 return false;
768 }
769
770 /* make a copy - can't modify length in place */
771 CSSM_DATA bitString = *nssObj;
772 clNssBitStringToCssm(bitString);
773 unsigned toCopy = bitString.Length;
774 if(toCopy > 2) {
775 /* I hope I never see this... */
776 clErrorLog("getFieldKeyUsage: CertType larger than 2 bytes!");
777 toCopy = 2;
778 }
779 unsigned char bits[2] = {0, 0};
780 memmove(bits, bitString.Data, toCopy);
781 *cdsaObj = (((unsigned)bits[0]) << 8) | bits[1];
782
783 /* pass back to caller */
784 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
785 return true;
786 }
787
788 /***
789 *** CRL Distribution points
790 *** CDSA Format: CE_CRLDistPointsSyntax
791 *** NSS format: NSS_CRLDistributionPoints
792 *** OID: CSSMOID_CrlDistributionPoints
793 ***/
794 void setFieldCrlDistPoints(
795 DecodedItem &cert,
796 const CssmData &fieldValue)
797 {
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);
810 }
811
812 bool getFieldCrlDistPoints(
813 DecodedItem &cert,
814 unsigned index, // which occurrence (0 = first)
815 uint32 &numFields, // RETURNED
816 CssmOwnedData &fieldValue)
817 {
818 const DecodedExten *decodedExt;
819 NSS_CRLDistributionPoints *nssObj;
820 CE_CRLDistPointsSyntax *cdsaObj;
821 bool brtn;
822 CssmAllocator &alloc = fieldValue.allocator;
823
824 brtn = cert.GetExtenTop<NSS_CRLDistributionPoints,
825 CE_CRLDistPointsSyntax>(
826 index,
827 numFields,
828 alloc,
829 CSSMOID_CrlDistributionPoints,
830 nssObj,
831 cdsaObj,
832 decodedExt);
833 if(!brtn) {
834 return false;
835 }
836 assert(nssObj != NULL);
837 CL_nssDistPointsToCssm(*nssObj, *cdsaObj, cert.coder(), alloc);
838 getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue);
839 return true;
840 }
841
842 void freeFieldCrlDistPoints (
843 CssmOwnedData &fieldValue)
844 {
845 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, false);
846 CssmAllocator &alloc = fieldValue.allocator;
847 CE_CRLDistPointsSyntax *cdsaObj =
848 (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue;
849 CL_freeCssmDistPoints(cdsaObj, alloc);
850 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue
851 }
852
853