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