2 * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved.
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
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.
20 * CertFields.cpp - convert between NSS-based Certificate components and CDSA-style
21 * fields. A major component of DecodedCert.
23 * Copyright (c) 2000,2011-2012,2014 Apple Inc.
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>
38 *** Format = DER-encoded int (max of four bytes in this case)
40 static bool getField_Version (
42 unsigned index
, // which occurrence (0 = first)
43 uint32
&numFields
, // RETURNED
44 CssmOwnedData
&fieldValue
) // RETURNED
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 */
52 fieldValue
.copy(vers
.Data
, vers
.Length
);
57 static void setField_Version (
59 const CssmData
&fieldValue
)
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
);
68 #if this_is_a_template
71 *** Format = DER-encoded int (always four bytes in this case)
73 static bool getField_Version (
75 unsigned index
, // which occurrence (0 = first)
76 uint32
&numFields
, // RETURNED
77 CssmOwnedData
&fieldValue
) // RETURNED
79 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
80 tbsGetCheck(cert
.certificateToSign
->version
, index
);
82 static void setField_Version (
84 const CssmData
&fieldValue
)
86 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
87 tbsSetCheck(cert
.certificateToSign
->version
, fieldValue
, sizeof(uint32
),
91 static void freeField_Version (
92 CssmOwnedData
&fieldValue
)
99 *** Format = DER-encoded int, variable length
101 static bool getField_SerialNumber (
103 unsigned index
, // which occurrence (0 = first)
104 uint32
&numFields
, // RETURNED
105 CssmOwnedData
&fieldValue
) // RETURNED
107 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
108 const CSSM_DATA
&sn
= cert
.mCert
.tbs
.serialNumber
;
109 if(!tbsGetCheck(sn
.Data
, index
)) {
112 fieldValue
.copy(sn
.Data
, sn
.Length
);
117 static void setField_SerialNumber (
119 const CssmData
&fieldValue
)
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
);
128 *** Format = CSSM_X509_NAME
129 *** class Name from sm_x501if
131 static bool getField_Issuer (
133 unsigned index
, // which occurrence (0 = first)
134 uint32
&numFields
, // RETURNED
135 CssmOwnedData
&fieldValue
) // RETURNED
143 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
145 brtn
= getField_RDN_NSS(cert
.mCert
.tbs
.issuer
, fieldValue
);
151 freeField_RDN(fieldValue
);
157 static void setField_Issuer (
159 const CssmData
&fieldValue
)
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
),
166 CL_cssmNameToNss(*cssmName
, nssName
, cert
.coder());
170 static bool getField_Subject (
172 unsigned index
, // which occurrence (0 = first)
173 uint32
&numFields
, // RETURNED
174 CssmOwnedData
&fieldValue
) // RETURNED
182 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
184 brtn
= getField_RDN_NSS(cert
.mCert
.tbs
.subject
, fieldValue
);
190 freeField_RDN(fieldValue
);
196 static void setField_Subject (
198 const CssmData
&fieldValue
)
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
),
205 CL_cssmNameToNss(*cssmName
, nssName
, cert
.coder());
209 *** Issuer Name, Subject Name (normalized and encoded version)
210 *** Format = CSSM_DATA containing the DER encoding of the normalized name
212 static bool getFieldSubjectNorm(
214 unsigned index
, // which occurrence (0 = first)
215 uint32
&numFields
, // RETURNED
216 CssmOwnedData
&fieldValue
) // RETURNED
221 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
222 return getField_normRDN_NSS(cert
.mCert
.tbs
.derSubject
, numFields
,
226 static bool getFieldIssuerNorm(
228 unsigned index
, // which occurrence (0 = first)
229 uint32
&numFields
, // RETURNED
230 CssmOwnedData
&fieldValue
) // RETURNED
235 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
236 return getField_normRDN_NSS(cert
.mCert
.tbs
.derIssuer
, numFields
, fieldValue
);
240 *** Issuer Name, Subject Name (encoded, NON-normalized version)
241 *** Format = CSSM_DATA containing the DER encoding of the name
243 static bool getFieldSubjectStd(
245 unsigned index
, // which occurrence (0 = first)
246 uint32
&numFields
, // RETURNED
247 CssmOwnedData
&fieldValue
) // RETURNED
252 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
253 fieldValue
.copy(cert
.mCert
.tbs
.derSubject
);
258 static bool getFieldIssuerStd(
260 unsigned index
, // which occurrence (0 = first)
261 uint32
&numFields
, // RETURNED
262 CssmOwnedData
&fieldValue
) // RETURNED
267 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
268 fieldValue
.copy(cert
.mCert
.tbs
.derIssuer
);
274 *** TBS AlgId, Signature AlgId
275 *** Format = CSSM_X509_ALGORITHM_IDENTIFIER
278 static bool getField_TbsAlgId (
280 unsigned index
, // which occurrence (0 = first)
281 uint32
&numFields
, // RETURNED
282 CssmOwnedData
&fieldValue
) // RETURNED
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
)) {
289 getField_AlgIdNSS(srcAlgId
, fieldValue
);
294 static void setField_TbsAlgId (
296 const CssmData
&fieldValue
)
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());
305 /* Cert AlgId - read only */
306 static bool getField_CertAlgId (
308 unsigned index
, // which occurrence (0 = first)
309 uint32
&numFields
, // RETURNED
310 CssmOwnedData
&fieldValue
) // RETURNED
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
)) {
317 getField_AlgIdNSS(srcAlgId
, fieldValue
);
323 *** Validity not before, not after
324 *** Format: CSSM_X509_TIME
328 static bool getField_NotBefore (
330 unsigned index
, // which occurrence (0 = first)
331 uint32
&numFields
, // RETURNED
332 CssmOwnedData
&fieldValue
) // RETURNED
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
);
339 static void setField_NotBefore (
341 const CssmData
&fieldValue
)
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());
351 static bool getField_NotAfter (
353 unsigned index
, // which occurrence (0 = first)
354 uint32
&numFields
, // RETURNED
355 CssmOwnedData
&fieldValue
) // RETURNED
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
);
362 static void setField_NotAfter (
364 const CssmData
&fieldValue
)
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());
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
381 static bool getField_SubjectUniqueId (
383 unsigned index
, // which occurrence (0 = first)
384 uint32
&numFields
, // RETURNED
385 CssmOwnedData
&fieldValue
) // RETURNED
387 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
388 const CSSM_DATA
&srcBits
= cert
.mCert
.tbs
.subjectID
;
389 if(!tbsGetCheck(srcBits
.Data
, index
)) {
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
);
401 static void setField_SubjectUniqueId (
403 const CssmData
&fieldValue
)
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
);
412 static bool getField_IssuerUniqueId (
414 unsigned index
, // which occurrence (0 = first)
415 uint32
&numFields
, // RETURNED
416 CssmOwnedData
&fieldValue
) // RETURNED
418 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
419 const CSSM_DATA
&srcBits
= cert
.mCert
.tbs
.issuerID
;
420 if(!tbsGetCheck(srcBits
.Data
, index
)) {
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
);
432 static void setField_IssuerUniqueId (
434 const CssmData
&fieldValue
)
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
);
445 *** Format = CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
447 static bool getField_PublicKeyInfo (
449 unsigned index
, // which occurrence (0 = first)
450 uint32
&numFields
, // RETURNED
451 CssmOwnedData
&fieldValue
) // RETURNED
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
)) {
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();
465 CL_copySubjPubKeyInfo(srcInfo
, true, // length in bits here
466 *dstInfo
, false, // length in bytes
473 static void setField_PublicKeyInfo (
475 const CssmData
&fieldValue
)
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");
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
);
490 ArenaAllocator
arenaAlloc(cert
.coder());
491 CL_copySubjPubKeyInfo(*srcKeyInfo
, false, // length in bytes here
492 dstKeyInfo
, true, // length in bits
496 static void freeField_PublicKeyInfo (
497 CssmOwnedData
&fieldValue
)
499 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*cssmKeyInfo
=
500 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*)fieldValue
.data();
501 if(cssmKeyInfo
== NULL
) {
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
));}
510 *** key info from CSSM_KEY
511 *** Format = CSSM_KEY
513 static bool getField_PublicKeyStruct (
515 unsigned index
, // which occurrence (0 = first)
516 uint32
&numFields
, // RETURNED
517 CssmOwnedData
&fieldValue
) // RETURNED
519 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
520 if(!tbsGetCheck(cert
.mCert
.tbs
.subjectPublicKeyInfo
.subjectPublicKey
.Data
,
524 CSSM_KEY_PTR cssmKey
= cert
.extractCSSMKey(fieldValue
.allocator
);
525 fieldValue
.set(reinterpret_cast<uint8
*>(cssmKey
), sizeof(CSSM_KEY
));
530 static void setField_PublicKeyStruct (
532 const CssmData
&fieldValue
)
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");
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
);
545 CL_CSSMKeyToSubjPubKeyInfoNSS(*cssmKey
, dstKeyInfo
, cert
.coder());
548 static void freeField_PublicKeyStruct (
549 CssmOwnedData
&fieldValue
)
551 CSSM_KEY_PTR cssmKey
= (CSSM_KEY_PTR
)fieldValue
.data();
552 CL_freeCSSMKey(cssmKey
, fieldValue
.allocator
, false);
557 *** Format = raw bytes
560 static bool getField_Signature (
562 unsigned index
, // which occurrence (0 = first)
563 uint32
&numFields
, // RETURNED
564 CssmOwnedData
&fieldValue
) // RETURNED
566 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
567 const CSSM_DATA
&sigBits
= cert
.mCert
.signature
;
568 if(!tbsGetCheck(sigBits
.Data
, index
)) {
571 fieldValue
.copy(sigBits
.Data
, (sigBits
.Length
+ 7) / 8);
577 *** end of field-specific triplets
581 * Table to map OID to {get,set,free}field
584 const CSSM_OID
*fieldId
;
585 getItemFieldFcn
*getFcn
;
586 setItemFieldFcn
*setFcn
;
587 freeFieldFcn
*freeFcn
; // OPTIONAL - NULL means just free the
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
},
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}
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
},
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
},
674 #define NUM_KNOWN_FIELDS (sizeof(fieldFuncTable) / sizeof(oidToFieldFuncs))
675 #define NUM_STD_CERT_FIELDS 17 /* not including extensions */
677 /* map an OID to an oidToFieldFuncs */
678 static const oidToFieldFuncs
*oidToFields(
679 const CssmOid
&fieldId
)
681 const oidToFieldFuncs
*fieldTable
= fieldFuncTable
;
682 for(unsigned i
=0; i
<NUM_KNOWN_FIELDS
; i
++) {
683 if(fieldId
== CssmData::overlay(*fieldTable
->fieldId
)) {
689 clErrorLog("oidToFields: unknown OID (len=%d): %s\n",
690 (int)fieldId
.length(), fieldId
.toHex().c_str());
692 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG
);
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.
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
716 clErrorLog("DecodedCert::getCertField: can't parse undecoded cert!");
717 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR
);
722 const oidToFieldFuncs
*fieldFuncs
= oidToFields(fieldId
);
723 return fieldFuncs
->getFcn(*this, index
, numFields
, fieldValue
);
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)
731 void DecodedCert::setCertField(
732 const CssmOid
&fieldId
, // which field
733 const CssmData
&fieldValue
)
736 case IS_Empty
: // first time thru
737 mState
= IS_Building
;
739 case IS_Building
: // subsequent passes
743 clErrorLog("DecodedCert::setCertField: can't build on a decoded cert!");
744 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR
);
746 if((fieldValue
.data() == NULL
) || (fieldValue
.length() == 0)) {
747 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER
);
749 const oidToFieldFuncs
*fieldFuncs
= oidToFields(fieldId
);
750 const CssmData
&value
= CssmData::overlay(fieldValue
);
751 fieldFuncs
->setFcn(*this, value
);
755 * Free the fieldId-specific data referred to by fieldValue->Data.
757 void DecodedCert::freeCertFieldData(
758 const CssmOid
&fieldId
,
759 CssmOwnedData
&fieldValue
)
761 if((fieldValue
.data() == NULL
) || (fieldValue
.length() == 0)) {
762 CssmError::throwMe(CSSM_ERRCODE_INVALID_FIELD_POINTER
);
764 const oidToFieldFuncs
*fieldFuncs
= oidToFields(fieldId
);
765 if(fieldFuncs
->freeFcn
!= NULL
) {
766 /* optional - simple cases handled below */
767 fieldFuncs
->freeFcn(fieldValue
);
770 fieldValue
.release();
776 * Common means to get all fields from a decoded cert. Used in
777 * CertGetAllTemplateFields and CertGetAllFields.
779 void DecodedCert::getAllParsedCertFields(
780 uint32
&NumberOfFields
, // RETURNED
781 CSSM_FIELD_PTR
&CertFields
) // RETURNED
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
));
788 * We'll be copying oids and values for fields we find into
789 * outFields; current number of valid fields found in numOutFields.
791 memset(outFields
, 0, maxFields
* sizeof(CSSM_FIELD
));
792 uint32 numOutFields
= 0;
793 CSSM_FIELD_PTR currOutField
;
795 const CSSM_OID
*currOid
;
796 CssmAutoData
aData(mAlloc
); // for malloc/copy of outgoing data
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
805 * Return false if field not there, which is not an error here.
806 * Actual exceptions are fatal.
808 if(!fieldFuncs
->getFcn(*this,
809 0, // index - looking for first one
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();
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,
828 numFields
, // shouldn't change
831 clErrorLog("getAllParsedCertFields: index screwup");
832 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR
);
834 assert(numOutFields
< maxFields
);
835 currOutField
= &outFields
[numOutFields
];
836 currOutField
->FieldValue
= aData
.release();
837 aData
.copy(*currOid
);
838 currOutField
->FieldOid
= aData
.release();
840 } /* multiple fields for currOid */
841 } /* for each known OID */
843 NumberOfFields
= numOutFields
;
844 CertFields
= outFields
;
848 DecodedCert::describeFormat(
850 uint32
&NumberOfFields
,
851 CSSM_OID_PTR
&OidList
)
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();
861 NumberOfFields
= NUM_KNOWN_FIELDS
;