2 * Copyright (c) 2000-2001 Apple Computer, 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 * Created 9/1/2000 by Doug Mitchell.
24 * Copyright (c) 2000 by Apple Computer.
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>
40 *** Format = DER-encoded int (max of four bytes in this case)
42 static bool getField_Version (
44 unsigned index
, // which occurrence (0 = first)
45 uint32
&numFields
, // RETURNED
46 CssmOwnedData
&fieldValue
) // RETURNED
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 */
54 fieldValue
.copy(vers
.Data
, vers
.Length
);
59 static void setField_Version (
61 const CssmData
&fieldValue
)
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
);
70 #if this_is_a_template
73 *** Format = DER-encoded int (always four bytes in this case)
75 static bool getField_Version (
77 unsigned index
, // which occurrence (0 = first)
78 uint32
&numFields
, // RETURNED
79 CssmOwnedData
&fieldValue
) // RETURNED
81 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
82 tbsGetCheck(cert
.certificateToSign
->version
, index
);
84 static void setField_Version (
86 const CssmData
&fieldValue
)
88 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
89 tbsSetCheck(cert
.certificateToSign
->version
, fieldValue
, sizeof(uint32
),
93 static void freeField_Version (
94 CssmOwnedData
&fieldValue
)
101 *** Format = DER-encoded int, variable length
103 static bool getField_SerialNumber (
105 unsigned index
, // which occurrence (0 = first)
106 uint32
&numFields
, // RETURNED
107 CssmOwnedData
&fieldValue
) // RETURNED
109 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
110 const CSSM_DATA
&sn
= cert
.mCert
.tbs
.serialNumber
;
111 if(!tbsGetCheck(sn
.Data
, index
)) {
114 fieldValue
.copy(sn
.Data
, sn
.Length
);
119 static void setField_SerialNumber (
121 const CssmData
&fieldValue
)
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
);
130 *** Format = CSSM_X509_NAME
131 *** class Name from sm_x501if
133 static bool getField_Issuer (
135 unsigned index
, // which occurrence (0 = first)
136 uint32
&numFields
, // RETURNED
137 CssmOwnedData
&fieldValue
) // RETURNED
145 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
147 brtn
= getField_RDN_NSS(cert
.mCert
.tbs
.issuer
, fieldValue
);
153 freeField_RDN(fieldValue
);
159 static void setField_Issuer (
161 const CssmData
&fieldValue
)
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
),
168 CL_cssmNameToNss(*cssmName
, nssName
, cert
.coder());
172 static bool getField_Subject (
174 unsigned index
, // which occurrence (0 = first)
175 uint32
&numFields
, // RETURNED
176 CssmOwnedData
&fieldValue
) // RETURNED
184 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
186 brtn
= getField_RDN_NSS(cert
.mCert
.tbs
.subject
, fieldValue
);
192 freeField_RDN(fieldValue
);
198 static void setField_Subject (
200 const CssmData
&fieldValue
)
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
),
207 CL_cssmNameToNss(*cssmName
, nssName
, cert
.coder());
211 *** Issuer Name, Subject Name (normalized and encoded version)
212 *** Format = CSSM_DATA containing the DER encoding of the normalized name
214 static bool getFieldSubjectNorm(
216 unsigned index
, // which occurrence (0 = first)
217 uint32
&numFields
, // RETURNED
218 CssmOwnedData
&fieldValue
) // RETURNED
223 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
224 return getField_normRDN_NSS(cert
.mCert
.tbs
.derSubject
, numFields
,
228 static bool getFieldIssuerNorm(
230 unsigned index
, // which occurrence (0 = first)
231 uint32
&numFields
, // RETURNED
232 CssmOwnedData
&fieldValue
) // RETURNED
237 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
238 return getField_normRDN_NSS(cert
.mCert
.tbs
.derIssuer
, numFields
, fieldValue
);
242 *** Issuer Name, Subject Name (encoded, NON-normalized version)
243 *** Format = CSSM_DATA containing the DER encoding of the name
245 static bool getFieldSubjectStd(
247 unsigned index
, // which occurrence (0 = first)
248 uint32
&numFields
, // RETURNED
249 CssmOwnedData
&fieldValue
) // RETURNED
254 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
255 fieldValue
.copy(cert
.mCert
.tbs
.derSubject
);
260 static bool getFieldIssuerStd(
262 unsigned index
, // which occurrence (0 = first)
263 uint32
&numFields
, // RETURNED
264 CssmOwnedData
&fieldValue
) // RETURNED
269 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
270 fieldValue
.copy(cert
.mCert
.tbs
.derIssuer
);
276 *** TBS AlgId, Signature AlgId
277 *** Format = CSSM_X509_ALGORITHM_IDENTIFIER
280 static bool getField_TbsAlgId (
282 unsigned index
, // which occurrence (0 = first)
283 uint32
&numFields
, // RETURNED
284 CssmOwnedData
&fieldValue
) // RETURNED
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
)) {
291 getField_AlgIdNSS(srcAlgId
, fieldValue
);
296 static void setField_TbsAlgId (
298 const CssmData
&fieldValue
)
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());
307 /* Cert AlgId - read only */
308 static bool getField_CertAlgId (
310 unsigned index
, // which occurrence (0 = first)
311 uint32
&numFields
, // RETURNED
312 CssmOwnedData
&fieldValue
) // RETURNED
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
)) {
319 getField_AlgIdNSS(srcAlgId
, fieldValue
);
325 *** Validity not before, not after
326 *** Format: CSSM_X509_TIME
330 static bool getField_NotBefore (
332 unsigned index
, // which occurrence (0 = first)
333 uint32
&numFields
, // RETURNED
334 CssmOwnedData
&fieldValue
) // RETURNED
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
);
341 static void setField_NotBefore (
343 const CssmData
&fieldValue
)
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());
353 static bool getField_NotAfter (
355 unsigned index
, // which occurrence (0 = first)
356 uint32
&numFields
, // RETURNED
357 CssmOwnedData
&fieldValue
) // RETURNED
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
);
364 static void setField_NotAfter (
366 const CssmData
&fieldValue
)
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());
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
383 static bool getField_SubjectUniqueId (
385 unsigned index
, // which occurrence (0 = first)
386 uint32
&numFields
, // RETURNED
387 CssmOwnedData
&fieldValue
) // RETURNED
389 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
390 const CSSM_DATA
&srcBits
= cert
.mCert
.tbs
.subjectID
;
391 if(!tbsGetCheck(srcBits
.Data
, index
)) {
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
);
403 static void setField_SubjectUniqueId (
405 const CssmData
&fieldValue
)
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
);
414 static bool getField_IssuerUniqueId (
416 unsigned index
, // which occurrence (0 = first)
417 uint32
&numFields
, // RETURNED
418 CssmOwnedData
&fieldValue
) // RETURNED
420 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
421 const CSSM_DATA
&srcBits
= cert
.mCert
.tbs
.issuerID
;
422 if(!tbsGetCheck(srcBits
.Data
, index
)) {
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
);
434 static void setField_IssuerUniqueId (
436 const CssmData
&fieldValue
)
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
);
447 *** Format = CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
449 static bool getField_PublicKeyInfo (
451 unsigned index
, // which occurrence (0 = first)
452 uint32
&numFields
, // RETURNED
453 CssmOwnedData
&fieldValue
) // RETURNED
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
)) {
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();
467 CL_copySubjPubKeyInfo(srcInfo
, true, // length in bits here
468 *dstInfo
, false, // length in bytes
475 static void setField_PublicKeyInfo (
477 const CssmData
&fieldValue
)
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");
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
);
492 ArenaAllocator
arenaAlloc(cert
.coder());
493 CL_copySubjPubKeyInfo(*srcKeyInfo
, false, // length in bytes here
494 dstKeyInfo
, true, // length in bits
498 static void freeField_PublicKeyInfo (
499 CssmOwnedData
&fieldValue
)
501 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*cssmKeyInfo
=
502 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*)fieldValue
.data();
503 if(cssmKeyInfo
== NULL
) {
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
));}
512 *** key info from CSSM_KEY
513 *** Format = CSSM_KEY
515 static bool getField_PublicKeyStruct (
517 unsigned index
, // which occurrence (0 = first)
518 uint32
&numFields
, // RETURNED
519 CssmOwnedData
&fieldValue
) // RETURNED
521 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
522 if(!tbsGetCheck(cert
.mCert
.tbs
.subjectPublicKeyInfo
.subjectPublicKey
.Data
,
526 CSSM_KEY_PTR cssmKey
= cert
.extractCSSMKey(fieldValue
.allocator
);
527 fieldValue
.set(reinterpret_cast<uint8
*>(cssmKey
), sizeof(CSSM_KEY
));
532 static void setField_PublicKeyStruct (
534 const CssmData
&fieldValue
)
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");
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
);
547 CL_CSSMKeyToSubjPubKeyInfoNSS(*cssmKey
, dstKeyInfo
, cert
.coder());
550 static void freeField_PublicKeyStruct (
551 CssmOwnedData
&fieldValue
)
553 CSSM_KEY_PTR cssmKey
= (CSSM_KEY_PTR
)fieldValue
.data();
554 CL_freeCSSMKey(cssmKey
, fieldValue
.allocator
, false);
559 *** Format = raw bytes
562 static bool getField_Signature (
564 unsigned index
, // which occurrence (0 = first)
565 uint32
&numFields
, // RETURNED
566 CssmOwnedData
&fieldValue
) // RETURNED
568 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
569 const CSSM_DATA
&sigBits
= cert
.mCert
.signature
;
570 if(!tbsGetCheck(sigBits
.Data
, index
)) {
573 fieldValue
.copy(sigBits
.Data
, (sigBits
.Length
+ 7) / 8);
579 *** end of field-specific triplets
583 * Table to map OID to {get,set,free}field
586 const CSSM_OID
*fieldId
;
587 getItemFieldFcn
*getFcn
;
588 setItemFieldFcn
*setFcn
;
589 freeFieldFcn
*freeFcn
; // OPTIONAL - NULL means just free the
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
},
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}
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
},
660 #define NUM_KNOWN_FIELDS (sizeof(fieldFuncTable) / sizeof(oidToFieldFuncs))
661 #define NUM_STD_CERT_FIELDS 17 /* not including extensions */
663 /* map an OID to an oidToFieldFuncs */
664 static const oidToFieldFuncs
*oidToFields(
665 const CssmOid
&fieldId
)
667 const oidToFieldFuncs
*fieldTable
= fieldFuncTable
;
668 for(unsigned i
=0; i
<NUM_KNOWN_FIELDS
; i
++) {
669 if(fieldId
== CssmData::overlay(*fieldTable
->fieldId
)) {
674 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG
);
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.
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
698 clErrorLog("DecodedCert::getCertField: can't parse undecoded cert!");
699 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR
);
704 const oidToFieldFuncs
*fieldFuncs
= oidToFields(fieldId
);
705 return fieldFuncs
->getFcn(*this, index
, numFields
, fieldValue
);
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)
713 void DecodedCert::setCertField(
714 const CssmOid
&fieldId
, // which field
715 const CssmData
&fieldValue
)
718 case IS_Empty
: // first time thru
719 mState
= IS_Building
;
721 case IS_Building
: // subsequent passes
725 clErrorLog("DecodedCert::setCertField: can't build on a decoded cert!");
726 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR
);
728 if((fieldValue
.data() == NULL
) || (fieldValue
.length() == 0)) {
729 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER
);
731 const oidToFieldFuncs
*fieldFuncs
= oidToFields(fieldId
);
732 const CssmData
&value
= CssmData::overlay(fieldValue
);
733 fieldFuncs
->setFcn(*this, value
);
737 * Free the fieldId-specific data referred to by fieldValue->Data.
739 void DecodedCert::freeCertFieldData(
740 const CssmOid
&fieldId
,
741 CssmOwnedData
&fieldValue
)
743 if((fieldValue
.data() == NULL
) || (fieldValue
.length() == 0)) {
744 CssmError::throwMe(CSSM_ERRCODE_INVALID_FIELD_POINTER
);
746 const oidToFieldFuncs
*fieldFuncs
= oidToFields(fieldId
);
747 if(fieldFuncs
->freeFcn
!= NULL
) {
748 /* optional - simple cases handled below */
749 fieldFuncs
->freeFcn(fieldValue
);
752 fieldValue
.release();
758 * Common means to get all fields from a decoded cert. Used in
759 * CertGetAllTemplateFields and CertGetAllFields.
761 void DecodedCert::getAllParsedCertFields(
762 uint32
&NumberOfFields
, // RETURNED
763 CSSM_FIELD_PTR
&CertFields
) // RETURNED
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
));
770 * We'll be copying oids and values for fields we find into
771 * outFields; current number of valid fields found in numOutFields.
773 memset(outFields
, 0, maxFields
* sizeof(CSSM_FIELD
));
774 uint32 numOutFields
= 0;
775 CSSM_FIELD_PTR currOutField
;
777 const CSSM_OID
*currOid
;
778 CssmAutoData
aData(mAlloc
); // for malloc/copy of outgoing data
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
787 * Return false if field not there, which is not an error here.
788 * Actual exceptions are fatal.
790 if(!fieldFuncs
->getFcn(*this,
791 0, // index - looking for first one
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();
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,
810 numFields
, // shouldn't change
813 clErrorLog("getAllParsedCertFields: index screwup");
814 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR
);
816 assert(numOutFields
< maxFields
);
817 currOutField
= &outFields
[numOutFields
];
818 currOutField
->FieldValue
= aData
.release();
819 aData
.copy(*currOid
);
820 currOutField
->FieldOid
= aData
.release();
822 } /* multiple fields for currOid */
823 } /* for each known OID */
825 NumberOfFields
= numOutFields
;
826 CertFields
= outFields
;
830 DecodedCert::describeFormat(
831 CssmAllocator
&alloc
,
832 uint32
&NumberOfFields
,
833 CSSM_OID_PTR
&OidList
)
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();
843 NumberOfFields
= NUM_KNOWN_FIELDS
;