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