]> git.saurik.com Git - apple/security.git/blob - libsecurity_apple_x509_cl/lib/CertFields.cpp
Security-55178.0.1.tar.gz
[apple/security.git] / libsecurity_apple_x509_cl / lib / CertFields.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 * CertFields.cpp - convert between NSS-based Certificate components and CDSA-style
21 * fields. A major component of DecodedCert.
22 *
23 * Created 9/1/2000 by Doug Mitchell.
24 * Copyright (c) 2000 by Apple Computer.
25 */
26
27 #include "DecodedCert.h"
28 #include "cldebugging.h"
29 #include "CLCertExtensions.h"
30 #include "clNssUtils.h"
31 #include "clNameUtils.h"
32 #include "CLFieldsCommon.h"
33 #include <Security/oidscert.h>
34 #include <Security/x509defs.h>
35 #include <security_utilities/utilities.h>
36
37 /***
38 *** Version
39 *** Format = DER-encoded int (max of four bytes in this case)
40 ***/
41 static bool getField_Version (
42 DecodedItem &item,
43 unsigned index, // which occurrence (0 = first)
44 uint32 &numFields, // RETURNED
45 CssmOwnedData &fieldValue) // RETURNED
46 {
47 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
48 const CSSM_DATA &vers = cert.mCert.tbs.version;
49 if(!tbsGetCheck(vers.Data, index)) {
50 /* not present, optional */
51 return false;
52 }
53 fieldValue.copy(vers.Data, vers.Length);
54 numFields = 1;
55 return true;
56 }
57
58 static void setField_Version (
59 DecodedItem &item,
60 const CssmData &fieldValue)
61 {
62 DecodedCert &cert = dynamic_cast<DecodedCert &>(item);
63 CSSM_DATA &vers = cert.mCert.tbs.version;
64 tbsSetCheck(vers.Data, fieldValue, 0, "version");
65 cert.coder().allocCopyItem(fieldValue, vers);
66 }
67
68
69 #if this_is_a_template
70 /***
71 *** Version
72 *** Format = DER-encoded int (always four bytes in this case)
73 ***/
74 static bool getField_Version (
75 DecodedItem &item,
76 unsigned index, // which occurrence (0 = first)
77 uint32 &numFields, // RETURNED
78 CssmOwnedData &fieldValue) // RETURNED
79 {
80 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
81 tbsGetCheck(cert.certificateToSign->version, index);
82 }
83 static void setField_Version (
84 DecodedItem &item,
85 const CssmData &fieldValue)
86 {
87 DecodedCert &cert = dynamic_cast<DecodedCert &>(item);
88 tbsSetCheck(cert.certificateToSign->version, fieldValue, sizeof(uint32),
89 "version");
90
91 }
92 static void freeField_Version (
93 CssmOwnedData &fieldValue)
94 {
95 }
96 #endif
97
98 /***
99 *** Serial Number
100 *** Format = DER-encoded int, variable length
101 ***/
102 static bool getField_SerialNumber (
103 DecodedItem &item,
104 unsigned index, // which occurrence (0 = first)
105 uint32 &numFields, // RETURNED
106 CssmOwnedData &fieldValue) // RETURNED
107 {
108 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
109 const CSSM_DATA &sn = cert.mCert.tbs.serialNumber;
110 if(!tbsGetCheck(sn.Data, index)) {
111 return false;
112 }
113 fieldValue.copy(sn.Data, sn.Length);
114 numFields = 1;
115 return true;
116 }
117
118 static void setField_SerialNumber (
119 DecodedItem &item,
120 const CssmData &fieldValue)
121 {
122 DecodedCert &cert = dynamic_cast<DecodedCert &>(item);
123 CSSM_DATA &sn = cert.mCert.tbs.serialNumber;
124 tbsSetCheck(sn.Data, fieldValue, 0, "SerialNumber");
125 cert.coder().allocCopyItem(fieldValue, sn);
126 }
127
128 /*** issuer/subject
129 *** Format = CSSM_X509_NAME
130 *** class Name from sm_x501if
131 ***/
132 static bool getField_Issuer (
133 DecodedItem &item,
134 unsigned index, // which occurrence (0 = first)
135 uint32 &numFields, // RETURNED
136 CssmOwnedData &fieldValue) // RETURNED
137 {
138 if(index != 0) {
139 return false;
140 }
141
142 bool brtn;
143
144 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
145 try {
146 brtn = getField_RDN_NSS(cert.mCert.tbs.issuer, fieldValue);
147 if(brtn) {
148 numFields = 1;
149 }
150 }
151 catch (...) {
152 freeField_RDN(fieldValue);
153 throw;
154 }
155 return brtn;
156 }
157
158 static void setField_Issuer (
159 DecodedItem &item,
160 const CssmData &fieldValue)
161 {
162 DecodedCert &cert = dynamic_cast<DecodedCert &>(item);
163 const CSSM_X509_NAME *cssmName = (const CSSM_X509_NAME *)fieldValue.Data;
164 NSS_Name &nssName = cert.mCert.tbs.issuer;
165 tbsSetCheck(nssName.rdns, fieldValue, sizeof(CSSM_X509_NAME),
166 "IssuerName");
167 CL_cssmNameToNss(*cssmName, nssName, cert.coder());
168 }
169
170 /*** subject ***/
171 static bool getField_Subject (
172 DecodedItem &item,
173 unsigned index, // which occurrence (0 = first)
174 uint32 &numFields, // RETURNED
175 CssmOwnedData &fieldValue) // RETURNED
176 {
177 if(index != 0) {
178 return false;
179 }
180
181 bool brtn;
182
183 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
184 try {
185 brtn = getField_RDN_NSS(cert.mCert.tbs.subject, fieldValue);
186 if(brtn) {
187 numFields = 1;
188 }
189 }
190 catch (...) {
191 freeField_RDN(fieldValue);
192 throw;
193 }
194 return brtn;
195 }
196
197 static void setField_Subject (
198 DecodedItem &item,
199 const CssmData &fieldValue)
200 {
201 DecodedCert &cert = dynamic_cast<DecodedCert &>(item);
202 const CSSM_X509_NAME *cssmName = (const CSSM_X509_NAME *)fieldValue.Data;
203 NSS_Name &nssName = cert.mCert.tbs.subject;
204 tbsSetCheck(nssName.rdns, fieldValue, sizeof(CSSM_X509_NAME),
205 "SubjectName");
206 CL_cssmNameToNss(*cssmName, nssName, cert.coder());
207 }
208
209 /***
210 *** Issuer Name, Subject Name (normalized and encoded version)
211 *** Format = CSSM_DATA containing the DER encoding of the normalized name
212 ***/
213 static bool getFieldSubjectNorm(
214 DecodedItem &item,
215 unsigned index, // which occurrence (0 = first)
216 uint32 &numFields, // RETURNED
217 CssmOwnedData &fieldValue) // RETURNED
218 {
219 if(index != 0) {
220 return false;
221 }
222 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
223 return getField_normRDN_NSS(cert.mCert.tbs.derSubject, numFields,
224 fieldValue);
225 }
226
227 static bool getFieldIssuerNorm(
228 DecodedItem &item,
229 unsigned index, // which occurrence (0 = first)
230 uint32 &numFields, // RETURNED
231 CssmOwnedData &fieldValue) // RETURNED
232 {
233 if(index != 0) {
234 return false;
235 }
236 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
237 return getField_normRDN_NSS(cert.mCert.tbs.derIssuer, numFields, fieldValue);
238 }
239
240 /***
241 *** Issuer Name, Subject Name (encoded, NON-normalized version)
242 *** Format = CSSM_DATA containing the DER encoding of the name
243 ***/
244 static bool getFieldSubjectStd(
245 DecodedItem &item,
246 unsigned index, // which occurrence (0 = first)
247 uint32 &numFields, // RETURNED
248 CssmOwnedData &fieldValue) // RETURNED
249 {
250 if(index != 0) {
251 return false;
252 }
253 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
254 fieldValue.copy(cert.mCert.tbs.derSubject);
255 numFields = 1;
256 return true;
257 }
258
259 static bool getFieldIssuerStd(
260 DecodedItem &item,
261 unsigned index, // which occurrence (0 = first)
262 uint32 &numFields, // RETURNED
263 CssmOwnedData &fieldValue) // RETURNED
264 {
265 if(index != 0) {
266 return false;
267 }
268 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
269 fieldValue.copy(cert.mCert.tbs.derIssuer);
270 numFields = 1;
271 return true;
272 }
273
274 /***
275 *** TBS AlgId, Signature AlgId
276 *** Format = CSSM_X509_ALGORITHM_IDENTIFIER
277 ***/
278 /* TBS AlgId */
279 static bool getField_TbsAlgId (
280 DecodedItem &item,
281 unsigned index, // which occurrence (0 = first)
282 uint32 &numFields, // RETURNED
283 CssmOwnedData &fieldValue) // RETURNED
284 {
285 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
286 const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId = cert.mCert.tbs.signature;
287 if(!tbsGetCheck(srcAlgId.algorithm.Data, index)) {
288 return false;
289 }
290 getField_AlgIdNSS(srcAlgId, fieldValue);
291 numFields = 1;
292 return true;
293 }
294
295 static void setField_TbsAlgId (
296 DecodedItem &item,
297 const CssmData &fieldValue)
298 {
299 DecodedCert &cert = dynamic_cast<DecodedCert &>(item);
300 CSSM_X509_ALGORITHM_IDENTIFIER &dstAlgId = cert.mCert.tbs.signature;
301 tbsSetCheck(dstAlgId.algorithm.Data, fieldValue,
302 sizeof(CSSM_X509_ALGORITHM_IDENTIFIER), "TBS_AlgId");
303 setField_AlgIdNSS(fieldValue, dstAlgId, cert.coder());
304 }
305
306 /* Cert AlgId - read only */
307 static bool getField_CertAlgId (
308 DecodedItem &item,
309 unsigned index, // which occurrence (0 = first)
310 uint32 &numFields, // RETURNED
311 CssmOwnedData &fieldValue) // RETURNED
312 {
313 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
314 const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId = cert.mCert.signatureAlgorithm;
315 if(!tbsGetCheck(srcAlgId.algorithm.Data, index)) {
316 return false;
317 }
318 getField_AlgIdNSS(srcAlgId, fieldValue);
319 numFields = 1;
320 return true;
321 }
322
323 /***
324 *** Validity not before, not after
325 *** Format: CSSM_X509_TIME
326 ***/
327
328 /*** not before ***/
329 static bool getField_NotBefore (
330 DecodedItem &item,
331 unsigned index, // which occurrence (0 = first)
332 uint32 &numFields, // RETURNED
333 CssmOwnedData &fieldValue) // RETURNED
334 {
335 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
336 const NSS_Time &srcTime = cert.mCert.tbs.validity.notBefore;
337 return getField_TimeNSS(srcTime, index, numFields, fieldValue);
338 }
339
340 static void setField_NotBefore (
341 DecodedItem &item,
342 const CssmData &fieldValue)
343 {
344 DecodedCert &cert = dynamic_cast<DecodedCert &>(item);
345 NSS_Time &dstTime = cert.mCert.tbs.validity.notBefore;
346 tbsSetCheck(dstTime.item.Data, fieldValue,
347 sizeof(CSSM_X509_TIME), "NotBefore");
348 setField_TimeNSS(fieldValue, dstTime, cert.coder());
349 }
350
351 /*** not after ***/
352 static bool getField_NotAfter (
353 DecodedItem &item,
354 unsigned index, // which occurrence (0 = first)
355 uint32 &numFields, // RETURNED
356 CssmOwnedData &fieldValue) // RETURNED
357 {
358 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
359 const NSS_Time &srcTime = cert.mCert.tbs.validity.notAfter;
360 return getField_TimeNSS(srcTime, index, numFields, fieldValue);
361 }
362
363 static void setField_NotAfter (
364 DecodedItem &item,
365 const CssmData &fieldValue)
366 {
367 DecodedCert &cert = dynamic_cast<DecodedCert &>(item);
368 NSS_Time &dstTime = cert.mCert.tbs.validity.notAfter;
369 tbsSetCheck(dstTime.item.Data, fieldValue,
370 sizeof(CSSM_X509_TIME), "NotAfter");
371 setField_TimeNSS(fieldValue, dstTime, cert.coder());
372 }
373
374 /***
375 *** Subject/issuer unique ID
376 *** Format: Raw bytes. It's stored in the cert as an ASN bit string; the decoded
377 *** bytes are present at this level (i.e., not tag and length in the bytes).
378 *** NOTE: this is not quite accurate in that we only provide byte-aligned size,
379 *** not bit-aligned. This field is rarely if ever used so I think it's O, but
380 *** beware.
381 ***/
382 static bool getField_SubjectUniqueId (
383 DecodedItem &item,
384 unsigned index, // which occurrence (0 = first)
385 uint32 &numFields, // RETURNED
386 CssmOwnedData &fieldValue) // RETURNED
387 {
388 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
389 const CSSM_DATA &srcBits = cert.mCert.tbs.subjectID;
390 if(!tbsGetCheck(srcBits.Data, index)) {
391 return false;
392 }
393
394 /* That CSSM_DATA is a decoded BITSTRING; its length is in bits */
395 CSSM_DATA tmp = srcBits;
396 tmp.Length = (tmp.Length + 7) / 8;
397 fieldValue.copy(tmp.Data, tmp.Length);
398 numFields = 1;
399 return true;
400 }
401
402 static void setField_SubjectUniqueId (
403 DecodedItem &item,
404 const CssmData &fieldValue)
405 {
406 DecodedCert &cert = dynamic_cast<DecodedCert &>(item);
407 CSSM_DATA &dstBits = cert.mCert.tbs.subjectID;
408 tbsSetCheck(dstBits.Data, fieldValue, 0, "SubjectUniqueID");
409 cert.coder().allocCopyItem(fieldValue, dstBits);
410 dstBits.Length *= 8;
411 }
412
413 static bool getField_IssuerUniqueId (
414 DecodedItem &item,
415 unsigned index, // which occurrence (0 = first)
416 uint32 &numFields, // RETURNED
417 CssmOwnedData &fieldValue) // RETURNED
418 {
419 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
420 const CSSM_DATA &srcBits = cert.mCert.tbs.issuerID;
421 if(!tbsGetCheck(srcBits.Data, index)) {
422 return false;
423 }
424
425 /* That CSSM_DATA is a decoded BITSTRING; its length is in bits */
426 CSSM_DATA tmp = srcBits;
427 tmp.Length = (tmp.Length + 7) / 8;
428 fieldValue.copy(tmp.Data, tmp.Length);
429 numFields = 1;
430 return true;
431 }
432
433 static void setField_IssuerUniqueId (
434 DecodedItem &item,
435 const CssmData &fieldValue)
436 {
437 DecodedCert &cert = dynamic_cast<DecodedCert &>(item);
438 CSSM_DATA &dstBits = cert.mCert.tbs.issuerID;
439 tbsSetCheck(dstBits.Data, fieldValue, 0, "IssuerUniqueID");
440 cert.coder().allocCopyItem(fieldValue, dstBits);
441 dstBits.Length *= 8;
442 }
443
444 /***
445 *** Public key info
446 *** Format = CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
447 ***/
448 static bool getField_PublicKeyInfo (
449 DecodedItem &item,
450 unsigned index, // which occurrence (0 = first)
451 uint32 &numFields, // RETURNED
452 CssmOwnedData &fieldValue) // RETURNED
453 {
454 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
455 const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &srcInfo =
456 cert.mCert.tbs.subjectPublicKeyInfo;
457 if(!tbsGetCheck(srcInfo.subjectPublicKey.Data, index)) {
458 return false;
459 }
460
461 Allocator &alloc = fieldValue.allocator;
462 fieldValue.malloc(sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO));
463 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *dstInfo =
464 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.data();
465
466 CL_copySubjPubKeyInfo(srcInfo, true, // length in bits here
467 *dstInfo, false, // length in bytes
468 alloc);
469
470 numFields = 1;
471 return true;
472 }
473
474 static void setField_PublicKeyInfo (
475 DecodedItem &item,
476 const CssmData &fieldValue)
477 {
478 DecodedCert &cert = dynamic_cast<DecodedCert &>(item);
479 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &dstKeyInfo =
480 cert.mCert.tbs.subjectPublicKeyInfo;
481 tbsSetCheck(dstKeyInfo.subjectPublicKey.Data, fieldValue,
482 sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO), "PubKeyInfo");
483
484 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *srcKeyInfo =
485 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.Data;
486 if((srcKeyInfo->subjectPublicKey.Data == NULL) ||
487 (srcKeyInfo->subjectPublicKey.Length == 0)) {
488 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
489 }
490
491 ArenaAllocator arenaAlloc(cert.coder());
492 CL_copySubjPubKeyInfo(*srcKeyInfo, false, // length in bytes here
493 dstKeyInfo, true, // length in bits
494 arenaAlloc);
495 }
496
497 static void freeField_PublicKeyInfo (
498 CssmOwnedData &fieldValue)
499 {
500 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *cssmKeyInfo =
501 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.data();
502 if(cssmKeyInfo == NULL) {
503 return;
504 }
505 Allocator &alloc = fieldValue.allocator;
506 CL_freeCssmAlgId(&cssmKeyInfo->algorithm, alloc);
507 alloc.free(cssmKeyInfo->subjectPublicKey.Data);
508 memset(cssmKeyInfo, 0, sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO));}
509
510 /***
511 *** key info from CSSM_KEY
512 *** Format = CSSM_KEY
513 ***/
514 static bool getField_PublicKeyStruct (
515 DecodedItem &item,
516 unsigned index, // which occurrence (0 = first)
517 uint32 &numFields, // RETURNED
518 CssmOwnedData &fieldValue) // RETURNED
519 {
520 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
521 if(!tbsGetCheck(cert.mCert.tbs.subjectPublicKeyInfo.subjectPublicKey.Data,
522 index)) {
523 return false;
524 }
525 CSSM_KEY_PTR cssmKey = cert.extractCSSMKey(fieldValue.allocator);
526 fieldValue.set(reinterpret_cast<uint8 *>(cssmKey), sizeof(CSSM_KEY));
527 numFields = 1;
528 return true;
529 }
530
531 static void setField_PublicKeyStruct (
532 DecodedItem &item,
533 const CssmData &fieldValue)
534 {
535 DecodedCert &cert = dynamic_cast<DecodedCert &>(item);
536 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &dstKeyInfo =
537 cert.mCert.tbs.subjectPublicKeyInfo;
538 tbsSetCheck(dstKeyInfo.subjectPublicKey.Data, fieldValue,
539 sizeof(CSSM_KEY), "PubKeyStruct");
540
541 CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)fieldValue.data();
542 if((cssmKey->KeyData.Data == NULL) ||
543 (cssmKey->KeyData.Data == 0)) {
544 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
545 }
546 CL_CSSMKeyToSubjPubKeyInfoNSS(*cssmKey, dstKeyInfo, cert.coder());
547 }
548
549 static void freeField_PublicKeyStruct (
550 CssmOwnedData &fieldValue)
551 {
552 CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)fieldValue.data();
553 CL_freeCSSMKey(cssmKey, fieldValue.allocator, false);
554 }
555
556 /***
557 *** Signature
558 *** Format = raw bytes
559 *** read-only
560 ***/
561 static bool getField_Signature (
562 DecodedItem &item,
563 unsigned index, // which occurrence (0 = first)
564 uint32 &numFields, // RETURNED
565 CssmOwnedData &fieldValue) // RETURNED
566 {
567 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item);
568 const CSSM_DATA &sigBits = cert.mCert.signature;
569 if(!tbsGetCheck(sigBits.Data, index)) {
570 return false;
571 }
572 fieldValue.copy(sigBits.Data, (sigBits.Length + 7) / 8);
573 numFields = 1;
574 return true;
575 }
576
577 /***
578 *** end of field-specific triplets
579 ***/
580
581 /*
582 * Table to map OID to {get,set,free}field
583 */
584 typedef struct {
585 const CSSM_OID *fieldId;
586 getItemFieldFcn *getFcn;
587 setItemFieldFcn *setFcn;
588 freeFieldFcn *freeFcn; // OPTIONAL - NULL means just free the
589 // top-level data
590 } oidToFieldFuncs;
591
592 static const oidToFieldFuncs fieldFuncTable[] = {
593 { &CSSMOID_X509V1Version,
594 &getField_Version, &setField_Version, NULL },
595 { &CSSMOID_X509V1SerialNumber,
596 &getField_SerialNumber, &setField_SerialNumber, NULL },
597 { &CSSMOID_X509V1IssuerNameCStruct,
598 &getField_Issuer, &setField_Issuer, &freeField_RDN },
599 { &CSSMOID_X509V1SubjectNameCStruct,
600 &getField_Subject, &setField_Subject, &freeField_RDN },
601 { &CSSMOID_X509V1SignatureAlgorithmTBS,
602 &getField_TbsAlgId, &setField_TbsAlgId, &freeField_AlgId },
603 { &CSSMOID_X509V1SignatureAlgorithm,
604 &getField_CertAlgId, &setField_ReadOnly, &freeField_AlgId },
605 { &CSSMOID_X509V1ValidityNotBefore,
606 &getField_NotBefore, &setField_NotBefore, &freeField_Time },
607 { &CSSMOID_X509V1ValidityNotAfter,
608 &getField_NotAfter, &setField_NotAfter, &freeField_Time },
609 { &CSSMOID_X509V1CertificateIssuerUniqueId,
610 &getField_IssuerUniqueId, &setField_IssuerUniqueId, NULL },
611 { &CSSMOID_X509V1CertificateSubjectUniqueId,
612 &getField_SubjectUniqueId, &setField_SubjectUniqueId, NULL },
613 { &CSSMOID_X509V1SubjectPublicKeyCStruct,
614 &getField_PublicKeyInfo, &setField_PublicKeyInfo, &freeField_PublicKeyInfo },
615 { &CSSMOID_CSSMKeyStruct,
616 &getField_PublicKeyStruct, &setField_PublicKeyStruct,
617 &freeField_PublicKeyStruct },
618 { &CSSMOID_X509V1Signature,
619 &getField_Signature, &setField_ReadOnly, NULL },
620 { &CSSMOID_X509V1IssuerName,
621 getFieldIssuerNorm, &setField_ReadOnly, NULL },
622 { &CSSMOID_X509V1SubjectName,
623 getFieldSubjectNorm, &setField_ReadOnly, NULL },
624 { &CSSMOID_X509V1IssuerNameStd,
625 getFieldIssuerStd, &setField_ReadOnly, NULL },
626 { &CSSMOID_X509V1SubjectNameStd,
627 getFieldSubjectStd, &setField_ReadOnly, NULL },
628
629 /*
630 * Extensions, implemented in CLCertExtensions.cpp
631 * When adding new ones, also add to:
632 * -- clOidToNssInfo() in CLFieldsCommon.cpp
633 * -- get/set/free functions in CLCertExtensions.{cpp,h}
634 */
635 { &CSSMOID_KeyUsage, &getFieldKeyUsage, &setFieldKeyUsage,
636 &freeFieldSimpleExtension },
637 { &CSSMOID_BasicConstraints, &getFieldBasicConstraints,
638 &setFieldBasicConstraints, &freeFieldSimpleExtension },
639 { &CSSMOID_ExtendedKeyUsage, &getFieldExtKeyUsage,
640 &setFieldExtKeyUsage, &freeFieldExtKeyUsage } ,
641 { &CSSMOID_SubjectKeyIdentifier, &getFieldSubjectKeyId,
642 &setFieldSubjectKeyId, &freeFieldSubjectKeyId } ,
643 { &CSSMOID_AuthorityKeyIdentifier, &getFieldAuthorityKeyId,
644 &setFieldAuthorityKeyId, &freeFieldAuthorityKeyId } ,
645 { &CSSMOID_SubjectAltName, &getFieldSubjAltName,
646 &setFieldSubjIssuerAltName, &freeFieldSubjIssuerAltName } ,
647 { &CSSMOID_IssuerAltName, &getFieldIssuerAltName,
648 &setFieldSubjIssuerAltName, &freeFieldSubjIssuerAltName } ,
649 { &CSSMOID_CertificatePolicies, &getFieldCertPolicies,
650 &setFieldCertPolicies, &freeFieldCertPolicies } ,
651 { &CSSMOID_NetscapeCertType, &getFieldNetscapeCertType,
652 &setFieldNetscapeCertType, &freeFieldSimpleExtension } ,
653 { &CSSMOID_CrlDistributionPoints, &getFieldCrlDistPoints,
654 &setFieldCrlDistPoints, &freeFieldCrlDistPoints },
655 { &CSSMOID_X509V3CertificateExtensionCStruct, &getFieldUnknownExt,
656 &setFieldUnknownExt, &freeFieldUnknownExt },
657 { &CSSMOID_AuthorityInfoAccess, &getFieldAuthInfoAccess,
658 &setFieldAuthInfoAccess, &freeFieldInfoAccess },
659 { &CSSMOID_SubjectInfoAccess, &getFieldSubjInfoAccess,
660 &setFieldAuthInfoAccess, &freeFieldInfoAccess },
661 { &CSSMOID_QC_Statements, &getFieldQualCertStatements,
662 &setFieldQualCertStatements, &freeFieldQualCertStatements },
663
664 { &CSSMOID_NameConstraints, &getFieldNameConstraints,
665 &setFieldNameConstraints, &freeFieldNameConstraints },
666 { &CSSMOID_PolicyMappings, &getFieldPolicyMappings,
667 &setFieldPolicyMappings, &freeFieldPolicyMappings },
668 { &CSSMOID_PolicyConstraints, &getFieldPolicyConstraints,
669 &setFieldPolicyConstraints, &freeFieldPolicyConstraints },
670 { &CSSMOID_InhibitAnyPolicy, &getFieldInhibitAnyPolicy,
671 &setFieldInhibitAnyPolicy, &freeFieldSimpleExtension },
672
673 };
674
675 #define NUM_KNOWN_FIELDS (sizeof(fieldFuncTable) / sizeof(oidToFieldFuncs))
676 #define NUM_STD_CERT_FIELDS 17 /* not including extensions */
677
678 /* map an OID to an oidToFieldFuncs */
679 static const oidToFieldFuncs *oidToFields(
680 const CssmOid &fieldId)
681 {
682 const oidToFieldFuncs *fieldTable = fieldFuncTable;
683 for(unsigned i=0; i<NUM_KNOWN_FIELDS; i++) {
684 if(fieldId == CssmData::overlay(*fieldTable->fieldId)) {
685 return fieldTable;
686 }
687 fieldTable++;
688 }
689 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG);
690 }
691
692
693 /***
694 *** Public functions
695 ***/
696
697 /*
698 * Obtain the index'th occurrence of field specified by fieldId in specified cert.
699 * Format of the returned field depends on fieldId.
700 * Returns total number of fieldId fields in the cert if index is 0.
701 * FieldValue assumed to be empty on entry.
702 * Returns true if specified field was found, else returns false.
703 */
704 bool DecodedCert::getCertFieldData(
705 const CssmOid &fieldId, // which field
706 unsigned index, // which occurrence (0 = first)
707 uint32 &numFields, // RETURNED
708 CssmOwnedData &fieldValue) // RETURNED
709 {
710 switch(mState) {
711 case IS_Empty:
712 case IS_Building:
713 clErrorLog("DecodedCert::getCertField: can't parse undecoded cert!");
714 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
715 case IS_DecodedAll:
716 case IS_DecodedTBS:
717 break;
718 }
719 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId);
720 return fieldFuncs->getFcn(*this, index, numFields, fieldValue);
721 }
722
723 /*
724 * Set the field specified by fieldId in the specified Cert.
725 * Note no index - individual field routines either append (for extensions)
726 * or if field already set ::throwMe(for all others)
727 */
728 void DecodedCert::setCertField(
729 const CssmOid &fieldId, // which field
730 const CssmData &fieldValue)
731 {
732 switch(mState) {
733 case IS_Empty: // first time thru
734 mState = IS_Building;
735 break;
736 case IS_Building: // subsequent passes
737 break;
738 case IS_DecodedAll:
739 case IS_DecodedTBS:
740 clErrorLog("DecodedCert::setCertField: can't build on a decoded cert!");
741 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
742 }
743 if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) {
744 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
745 }
746 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId);
747 const CssmData &value = CssmData::overlay(fieldValue);
748 fieldFuncs->setFcn(*this, value);
749 }
750
751 /*
752 * Free the fieldId-specific data referred to by fieldValue->Data.
753 */
754 void DecodedCert::freeCertFieldData(
755 const CssmOid &fieldId,
756 CssmOwnedData &fieldValue)
757 {
758 if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) {
759 CssmError::throwMe(CSSM_ERRCODE_INVALID_FIELD_POINTER);
760 }
761 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId);
762 if(fieldFuncs->freeFcn != NULL) {
763 /* optional - simple cases handled below */
764 fieldFuncs->freeFcn(fieldValue);
765 }
766 fieldValue.reset();
767 fieldValue.release();
768
769 }
770
771
772 /*
773 * Common means to get all fields from a decoded cert. Used in
774 * CertGetAllTemplateFields and CertGetAllFields.
775 */
776 void DecodedCert::getAllParsedCertFields(
777 uint32 &NumberOfFields, // RETURNED
778 CSSM_FIELD_PTR &CertFields) // RETURNED
779 {
780 /* this is the max - some might be missing */
781 uint32 maxFields = NUM_STD_CERT_FIELDS + mDecodedExtensions.numExtensions();
782 CSSM_FIELD_PTR outFields = (CSSM_FIELD_PTR)mAlloc.malloc(maxFields * sizeof(CSSM_FIELD));
783
784 /*
785 * We'll be copying oids and values for fields we find into
786 * outFields; current number of valid fields found in numOutFields.
787 */
788 memset(outFields, 0, maxFields * sizeof(CSSM_FIELD));
789 uint32 numOutFields = 0;
790 CSSM_FIELD_PTR currOutField;
791 uint32 currOidDex;
792 const CSSM_OID *currOid;
793 CssmAutoData aData(mAlloc); // for malloc/copy of outgoing data
794
795 /* query for each OID we know about */
796 for(currOidDex=0; currOidDex<NUM_KNOWN_FIELDS; currOidDex++) {
797 const oidToFieldFuncs *fieldFuncs = &fieldFuncTable[currOidDex];
798 currOid = fieldFuncs->fieldId;
799 uint32 numFields; // for THIS oid
800
801 /*
802 * Return false if field not there, which is not an error here.
803 * Actual exceptions are fatal.
804 */
805 if(!fieldFuncs->getFcn(*this,
806 0, // index - looking for first one
807 numFields,
808 aData)) {
809 continue;
810 }
811
812 /* got some data for this oid - copy it and oid to outgoing CertFields */
813 assert(numOutFields < maxFields);
814 currOutField = &outFields[numOutFields];
815 currOutField->FieldValue = aData.release();
816 aData.copy(*currOid);
817 currOutField->FieldOid = aData.release();
818 numOutFields++;
819
820 /* if more fields are available for this OID, snag them too */
821 for(uint32 fieldDex=1; fieldDex<numFields; fieldDex++) {
822 /* note this should always succeed */
823 bool brtn = fieldFuncs->getFcn(*this,
824 fieldDex,
825 numFields, // shouldn't change
826 aData);
827 if(!brtn) {
828 clErrorLog("getAllParsedCertFields: index screwup");
829 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
830 }
831 assert(numOutFields < maxFields);
832 currOutField = &outFields[numOutFields];
833 currOutField->FieldValue = aData.release();
834 aData.copy(*currOid);
835 currOutField->FieldOid = aData.release();
836 numOutFields++;
837 } /* multiple fields for currOid */
838 } /* for each known OID */
839
840 NumberOfFields = numOutFields;
841 CertFields = outFields;
842 }
843
844 void
845 DecodedCert::describeFormat(
846 Allocator &alloc,
847 uint32 &NumberOfFields,
848 CSSM_OID_PTR &OidList)
849 {
850 /* malloc in app's space, do deep copy (including ->Data) */
851 CSSM_OID_PTR oidList = (CSSM_OID_PTR)alloc.malloc(
852 NUM_KNOWN_FIELDS * sizeof(CSSM_OID));
853 memset(oidList, 0, NUM_KNOWN_FIELDS * sizeof(CSSM_OID));
854 for(unsigned i=0; i<NUM_KNOWN_FIELDS; i++) {
855 CssmAutoData oidCopy(alloc, *fieldFuncTable[i].fieldId);
856 oidList[i] = oidCopy.release();
857 }
858 NumberOfFields = NUM_KNOWN_FIELDS;
859 OidList = oidList;
860 }