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/oidscert.h>
34 #include <Security/x509defs.h>
35 #include <security_utilities/utilities.h>
39 *** Format = DER-encoded int (max of four bytes in this case)
41 static bool getField_Version (
43 unsigned index
, // which occurrence (0 = first)
44 uint32
&numFields
, // RETURNED
45 CssmOwnedData
&fieldValue
) // RETURNED
47 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
48 const CSSM_DATA
&vers
= cert
.mCert
.tbs
.version
;
49 if(!tbsGetCheck(vers
.Data
, index
)) {
50 /* not present, optional */
53 fieldValue
.copy(vers
.Data
, vers
.Length
);
58 static void setField_Version (
60 const CssmData
&fieldValue
)
62 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
63 CSSM_DATA
&vers
= cert
.mCert
.tbs
.version
;
64 tbsSetCheck(vers
.Data
, fieldValue
, 0, "version");
65 cert
.coder().allocCopyItem(fieldValue
, vers
);
69 #if this_is_a_template
72 *** Format = DER-encoded int (always four bytes in this case)
74 static bool getField_Version (
76 unsigned index
, // which occurrence (0 = first)
77 uint32
&numFields
, // RETURNED
78 CssmOwnedData
&fieldValue
) // RETURNED
80 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
81 tbsGetCheck(cert
.certificateToSign
->version
, index
);
83 static void setField_Version (
85 const CssmData
&fieldValue
)
87 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
88 tbsSetCheck(cert
.certificateToSign
->version
, fieldValue
, sizeof(uint32
),
92 static void freeField_Version (
93 CssmOwnedData
&fieldValue
)
100 *** Format = DER-encoded int, variable length
102 static bool getField_SerialNumber (
104 unsigned index
, // which occurrence (0 = first)
105 uint32
&numFields
, // RETURNED
106 CssmOwnedData
&fieldValue
) // RETURNED
108 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
109 const CSSM_DATA
&sn
= cert
.mCert
.tbs
.serialNumber
;
110 if(!tbsGetCheck(sn
.Data
, index
)) {
113 fieldValue
.copy(sn
.Data
, sn
.Length
);
118 static void setField_SerialNumber (
120 const CssmData
&fieldValue
)
122 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
123 CSSM_DATA
&sn
= cert
.mCert
.tbs
.serialNumber
;
124 tbsSetCheck(sn
.Data
, fieldValue
, 0, "SerialNumber");
125 cert
.coder().allocCopyItem(fieldValue
, sn
);
129 *** Format = CSSM_X509_NAME
130 *** class Name from sm_x501if
132 static bool getField_Issuer (
134 unsigned index
, // which occurrence (0 = first)
135 uint32
&numFields
, // RETURNED
136 CssmOwnedData
&fieldValue
) // RETURNED
144 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
146 brtn
= getField_RDN_NSS(cert
.mCert
.tbs
.issuer
, fieldValue
);
152 freeField_RDN(fieldValue
);
158 static void setField_Issuer (
160 const CssmData
&fieldValue
)
162 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
163 const CSSM_X509_NAME
*cssmName
= (const CSSM_X509_NAME
*)fieldValue
.Data
;
164 NSS_Name
&nssName
= cert
.mCert
.tbs
.issuer
;
165 tbsSetCheck(nssName
.rdns
, fieldValue
, sizeof(CSSM_X509_NAME
),
167 CL_cssmNameToNss(*cssmName
, nssName
, cert
.coder());
171 static bool getField_Subject (
173 unsigned index
, // which occurrence (0 = first)
174 uint32
&numFields
, // RETURNED
175 CssmOwnedData
&fieldValue
) // RETURNED
183 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
185 brtn
= getField_RDN_NSS(cert
.mCert
.tbs
.subject
, fieldValue
);
191 freeField_RDN(fieldValue
);
197 static void setField_Subject (
199 const CssmData
&fieldValue
)
201 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
202 const CSSM_X509_NAME
*cssmName
= (const CSSM_X509_NAME
*)fieldValue
.Data
;
203 NSS_Name
&nssName
= cert
.mCert
.tbs
.subject
;
204 tbsSetCheck(nssName
.rdns
, fieldValue
, sizeof(CSSM_X509_NAME
),
206 CL_cssmNameToNss(*cssmName
, nssName
, cert
.coder());
210 *** Issuer Name, Subject Name (normalized and encoded version)
211 *** Format = CSSM_DATA containing the DER encoding of the normalized name
213 static bool getFieldSubjectNorm(
215 unsigned index
, // which occurrence (0 = first)
216 uint32
&numFields
, // RETURNED
217 CssmOwnedData
&fieldValue
) // RETURNED
222 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
223 return getField_normRDN_NSS(cert
.mCert
.tbs
.derSubject
, numFields
,
227 static bool getFieldIssuerNorm(
229 unsigned index
, // which occurrence (0 = first)
230 uint32
&numFields
, // RETURNED
231 CssmOwnedData
&fieldValue
) // RETURNED
236 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
237 return getField_normRDN_NSS(cert
.mCert
.tbs
.derIssuer
, numFields
, fieldValue
);
241 *** Issuer Name, Subject Name (encoded, NON-normalized version)
242 *** Format = CSSM_DATA containing the DER encoding of the name
244 static bool getFieldSubjectStd(
246 unsigned index
, // which occurrence (0 = first)
247 uint32
&numFields
, // RETURNED
248 CssmOwnedData
&fieldValue
) // RETURNED
253 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
254 fieldValue
.copy(cert
.mCert
.tbs
.derSubject
);
259 static bool getFieldIssuerStd(
261 unsigned index
, // which occurrence (0 = first)
262 uint32
&numFields
, // RETURNED
263 CssmOwnedData
&fieldValue
) // RETURNED
268 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
269 fieldValue
.copy(cert
.mCert
.tbs
.derIssuer
);
275 *** TBS AlgId, Signature AlgId
276 *** Format = CSSM_X509_ALGORITHM_IDENTIFIER
279 static bool getField_TbsAlgId (
281 unsigned index
, // which occurrence (0 = first)
282 uint32
&numFields
, // RETURNED
283 CssmOwnedData
&fieldValue
) // RETURNED
285 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
286 const CSSM_X509_ALGORITHM_IDENTIFIER
&srcAlgId
= cert
.mCert
.tbs
.signature
;
287 if(!tbsGetCheck(srcAlgId
.algorithm
.Data
, index
)) {
290 getField_AlgIdNSS(srcAlgId
, fieldValue
);
295 static void setField_TbsAlgId (
297 const CssmData
&fieldValue
)
299 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
300 CSSM_X509_ALGORITHM_IDENTIFIER
&dstAlgId
= cert
.mCert
.tbs
.signature
;
301 tbsSetCheck(dstAlgId
.algorithm
.Data
, fieldValue
,
302 sizeof(CSSM_X509_ALGORITHM_IDENTIFIER
), "TBS_AlgId");
303 setField_AlgIdNSS(fieldValue
, dstAlgId
, cert
.coder());
306 /* Cert AlgId - read only */
307 static bool getField_CertAlgId (
309 unsigned index
, // which occurrence (0 = first)
310 uint32
&numFields
, // RETURNED
311 CssmOwnedData
&fieldValue
) // RETURNED
313 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
314 const CSSM_X509_ALGORITHM_IDENTIFIER
&srcAlgId
= cert
.mCert
.signatureAlgorithm
;
315 if(!tbsGetCheck(srcAlgId
.algorithm
.Data
, index
)) {
318 getField_AlgIdNSS(srcAlgId
, fieldValue
);
324 *** Validity not before, not after
325 *** Format: CSSM_X509_TIME
329 static bool getField_NotBefore (
331 unsigned index
, // which occurrence (0 = first)
332 uint32
&numFields
, // RETURNED
333 CssmOwnedData
&fieldValue
) // RETURNED
335 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
336 const NSS_Time
&srcTime
= cert
.mCert
.tbs
.validity
.notBefore
;
337 return getField_TimeNSS(srcTime
, index
, numFields
, fieldValue
);
340 static void setField_NotBefore (
342 const CssmData
&fieldValue
)
344 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
345 NSS_Time
&dstTime
= cert
.mCert
.tbs
.validity
.notBefore
;
346 tbsSetCheck(dstTime
.item
.Data
, fieldValue
,
347 sizeof(CSSM_X509_TIME
), "NotBefore");
348 setField_TimeNSS(fieldValue
, dstTime
, cert
.coder());
352 static bool getField_NotAfter (
354 unsigned index
, // which occurrence (0 = first)
355 uint32
&numFields
, // RETURNED
356 CssmOwnedData
&fieldValue
) // RETURNED
358 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
359 const NSS_Time
&srcTime
= cert
.mCert
.tbs
.validity
.notAfter
;
360 return getField_TimeNSS(srcTime
, index
, numFields
, fieldValue
);
363 static void setField_NotAfter (
365 const CssmData
&fieldValue
)
367 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
368 NSS_Time
&dstTime
= cert
.mCert
.tbs
.validity
.notAfter
;
369 tbsSetCheck(dstTime
.item
.Data
, fieldValue
,
370 sizeof(CSSM_X509_TIME
), "NotAfter");
371 setField_TimeNSS(fieldValue
, dstTime
, cert
.coder());
375 *** Subject/issuer unique ID
376 *** Format: Raw bytes. It's stored in the cert as an ASN bit string; the decoded
377 *** bytes are present at this level (i.e., not tag and length in the bytes).
378 *** NOTE: this is not quite accurate in that we only provide byte-aligned size,
379 *** not bit-aligned. This field is rarely if ever used so I think it's O, but
382 static bool getField_SubjectUniqueId (
384 unsigned index
, // which occurrence (0 = first)
385 uint32
&numFields
, // RETURNED
386 CssmOwnedData
&fieldValue
) // RETURNED
388 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
389 const CSSM_DATA
&srcBits
= cert
.mCert
.tbs
.subjectID
;
390 if(!tbsGetCheck(srcBits
.Data
, index
)) {
394 /* That CSSM_DATA is a decoded BITSTRING; its length is in bits */
395 CSSM_DATA tmp
= srcBits
;
396 tmp
.Length
= (tmp
.Length
+ 7) / 8;
397 fieldValue
.copy(tmp
.Data
, tmp
.Length
);
402 static void setField_SubjectUniqueId (
404 const CssmData
&fieldValue
)
406 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
407 CSSM_DATA
&dstBits
= cert
.mCert
.tbs
.subjectID
;
408 tbsSetCheck(dstBits
.Data
, fieldValue
, 0, "SubjectUniqueID");
409 cert
.coder().allocCopyItem(fieldValue
, dstBits
);
413 static bool getField_IssuerUniqueId (
415 unsigned index
, // which occurrence (0 = first)
416 uint32
&numFields
, // RETURNED
417 CssmOwnedData
&fieldValue
) // RETURNED
419 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
420 const CSSM_DATA
&srcBits
= cert
.mCert
.tbs
.issuerID
;
421 if(!tbsGetCheck(srcBits
.Data
, index
)) {
425 /* That CSSM_DATA is a decoded BITSTRING; its length is in bits */
426 CSSM_DATA tmp
= srcBits
;
427 tmp
.Length
= (tmp
.Length
+ 7) / 8;
428 fieldValue
.copy(tmp
.Data
, tmp
.Length
);
433 static void setField_IssuerUniqueId (
435 const CssmData
&fieldValue
)
437 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
438 CSSM_DATA
&dstBits
= cert
.mCert
.tbs
.issuerID
;
439 tbsSetCheck(dstBits
.Data
, fieldValue
, 0, "IssuerUniqueID");
440 cert
.coder().allocCopyItem(fieldValue
, dstBits
);
446 *** Format = CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
448 static bool getField_PublicKeyInfo (
450 unsigned index
, // which occurrence (0 = first)
451 uint32
&numFields
, // RETURNED
452 CssmOwnedData
&fieldValue
) // RETURNED
454 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
455 const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
&srcInfo
=
456 cert
.mCert
.tbs
.subjectPublicKeyInfo
;
457 if(!tbsGetCheck(srcInfo
.subjectPublicKey
.Data
, index
)) {
461 Allocator
&alloc
= fieldValue
.allocator
;
462 fieldValue
.malloc(sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
));
463 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*dstInfo
=
464 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*)fieldValue
.data();
466 CL_copySubjPubKeyInfo(srcInfo
, true, // length in bits here
467 *dstInfo
, false, // length in bytes
474 static void setField_PublicKeyInfo (
476 const CssmData
&fieldValue
)
478 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
479 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
&dstKeyInfo
=
480 cert
.mCert
.tbs
.subjectPublicKeyInfo
;
481 tbsSetCheck(dstKeyInfo
.subjectPublicKey
.Data
, fieldValue
,
482 sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
), "PubKeyInfo");
484 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*srcKeyInfo
=
485 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*)fieldValue
.Data
;
486 if((srcKeyInfo
->subjectPublicKey
.Data
== NULL
) ||
487 (srcKeyInfo
->subjectPublicKey
.Length
== 0)) {
488 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER
);
491 ArenaAllocator
arenaAlloc(cert
.coder());
492 CL_copySubjPubKeyInfo(*srcKeyInfo
, false, // length in bytes here
493 dstKeyInfo
, true, // length in bits
497 static void freeField_PublicKeyInfo (
498 CssmOwnedData
&fieldValue
)
500 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*cssmKeyInfo
=
501 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*)fieldValue
.data();
502 if(cssmKeyInfo
== NULL
) {
505 Allocator
&alloc
= fieldValue
.allocator
;
506 CL_freeCssmAlgId(&cssmKeyInfo
->algorithm
, alloc
);
507 alloc
.free(cssmKeyInfo
->subjectPublicKey
.Data
);
508 memset(cssmKeyInfo
, 0, sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
));}
511 *** key info from CSSM_KEY
512 *** Format = CSSM_KEY
514 static bool getField_PublicKeyStruct (
516 unsigned index
, // which occurrence (0 = first)
517 uint32
&numFields
, // RETURNED
518 CssmOwnedData
&fieldValue
) // RETURNED
520 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
521 if(!tbsGetCheck(cert
.mCert
.tbs
.subjectPublicKeyInfo
.subjectPublicKey
.Data
,
525 CSSM_KEY_PTR cssmKey
= cert
.extractCSSMKey(fieldValue
.allocator
);
526 fieldValue
.set(reinterpret_cast<uint8
*>(cssmKey
), sizeof(CSSM_KEY
));
531 static void setField_PublicKeyStruct (
533 const CssmData
&fieldValue
)
535 DecodedCert
&cert
= dynamic_cast<DecodedCert
&>(item
);
536 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
&dstKeyInfo
=
537 cert
.mCert
.tbs
.subjectPublicKeyInfo
;
538 tbsSetCheck(dstKeyInfo
.subjectPublicKey
.Data
, fieldValue
,
539 sizeof(CSSM_KEY
), "PubKeyStruct");
541 CSSM_KEY_PTR cssmKey
= (CSSM_KEY_PTR
)fieldValue
.data();
542 if((cssmKey
->KeyData
.Data
== NULL
) ||
543 (cssmKey
->KeyData
.Data
== 0)) {
544 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER
);
546 CL_CSSMKeyToSubjPubKeyInfoNSS(*cssmKey
, dstKeyInfo
, cert
.coder());
549 static void freeField_PublicKeyStruct (
550 CssmOwnedData
&fieldValue
)
552 CSSM_KEY_PTR cssmKey
= (CSSM_KEY_PTR
)fieldValue
.data();
553 CL_freeCSSMKey(cssmKey
, fieldValue
.allocator
, false);
558 *** Format = raw bytes
561 static bool getField_Signature (
563 unsigned index
, // which occurrence (0 = first)
564 uint32
&numFields
, // RETURNED
565 CssmOwnedData
&fieldValue
) // RETURNED
567 const DecodedCert
&cert
= dynamic_cast<const DecodedCert
&>(item
);
568 const CSSM_DATA
&sigBits
= cert
.mCert
.signature
;
569 if(!tbsGetCheck(sigBits
.Data
, index
)) {
572 fieldValue
.copy(sigBits
.Data
, (sigBits
.Length
+ 7) / 8);
578 *** end of field-specific triplets
582 * Table to map OID to {get,set,free}field
585 const CSSM_OID
*fieldId
;
586 getItemFieldFcn
*getFcn
;
587 setItemFieldFcn
*setFcn
;
588 freeFieldFcn
*freeFcn
; // OPTIONAL - NULL means just free the
592 static const oidToFieldFuncs fieldFuncTable
[] = {
593 { &CSSMOID_X509V1Version
,
594 &getField_Version
, &setField_Version
, NULL
},
595 { &CSSMOID_X509V1SerialNumber
,
596 &getField_SerialNumber
, &setField_SerialNumber
, NULL
},
597 { &CSSMOID_X509V1IssuerNameCStruct
,
598 &getField_Issuer
, &setField_Issuer
, &freeField_RDN
},
599 { &CSSMOID_X509V1SubjectNameCStruct
,
600 &getField_Subject
, &setField_Subject
, &freeField_RDN
},
601 { &CSSMOID_X509V1SignatureAlgorithmTBS
,
602 &getField_TbsAlgId
, &setField_TbsAlgId
, &freeField_AlgId
},
603 { &CSSMOID_X509V1SignatureAlgorithm
,
604 &getField_CertAlgId
, &setField_ReadOnly
, &freeField_AlgId
},
605 { &CSSMOID_X509V1ValidityNotBefore
,
606 &getField_NotBefore
, &setField_NotBefore
, &freeField_Time
},
607 { &CSSMOID_X509V1ValidityNotAfter
,
608 &getField_NotAfter
, &setField_NotAfter
, &freeField_Time
},
609 { &CSSMOID_X509V1CertificateIssuerUniqueId
,
610 &getField_IssuerUniqueId
, &setField_IssuerUniqueId
, NULL
},
611 { &CSSMOID_X509V1CertificateSubjectUniqueId
,
612 &getField_SubjectUniqueId
, &setField_SubjectUniqueId
, NULL
},
613 { &CSSMOID_X509V1SubjectPublicKeyCStruct
,
614 &getField_PublicKeyInfo
, &setField_PublicKeyInfo
, &freeField_PublicKeyInfo
},
615 { &CSSMOID_CSSMKeyStruct
,
616 &getField_PublicKeyStruct
, &setField_PublicKeyStruct
,
617 &freeField_PublicKeyStruct
},
618 { &CSSMOID_X509V1Signature
,
619 &getField_Signature
, &setField_ReadOnly
, NULL
},
620 { &CSSMOID_X509V1IssuerName
,
621 getFieldIssuerNorm
, &setField_ReadOnly
, NULL
},
622 { &CSSMOID_X509V1SubjectName
,
623 getFieldSubjectNorm
, &setField_ReadOnly
, NULL
},
624 { &CSSMOID_X509V1IssuerNameStd
,
625 getFieldIssuerStd
, &setField_ReadOnly
, NULL
},
626 { &CSSMOID_X509V1SubjectNameStd
,
627 getFieldSubjectStd
, &setField_ReadOnly
, NULL
},
630 * Extensions, implemented in CLCertExtensions.cpp
631 * When adding new ones, also add to:
632 * -- clOidToNssInfo() in CLFieldsCommon.cpp
633 * -- get/set/free functions in CLCertExtensions.{cpp,h}
635 { &CSSMOID_KeyUsage
, &getFieldKeyUsage
, &setFieldKeyUsage
,
636 &freeFieldSimpleExtension
},
637 { &CSSMOID_BasicConstraints
, &getFieldBasicConstraints
,
638 &setFieldBasicConstraints
, &freeFieldSimpleExtension
},
639 { &CSSMOID_ExtendedKeyUsage
, &getFieldExtKeyUsage
,
640 &setFieldExtKeyUsage
, &freeFieldExtKeyUsage
} ,
641 { &CSSMOID_SubjectKeyIdentifier
, &getFieldSubjectKeyId
,
642 &setFieldSubjectKeyId
, &freeFieldSubjectKeyId
} ,
643 { &CSSMOID_AuthorityKeyIdentifier
, &getFieldAuthorityKeyId
,
644 &setFieldAuthorityKeyId
, &freeFieldAuthorityKeyId
} ,
645 { &CSSMOID_SubjectAltName
, &getFieldSubjAltName
,
646 &setFieldSubjIssuerAltName
, &freeFieldSubjIssuerAltName
} ,
647 { &CSSMOID_IssuerAltName
, &getFieldIssuerAltName
,
648 &setFieldSubjIssuerAltName
, &freeFieldSubjIssuerAltName
} ,
649 { &CSSMOID_CertificatePolicies
, &getFieldCertPolicies
,
650 &setFieldCertPolicies
, &freeFieldCertPolicies
} ,
651 { &CSSMOID_NetscapeCertType
, &getFieldNetscapeCertType
,
652 &setFieldNetscapeCertType
, &freeFieldSimpleExtension
} ,
653 { &CSSMOID_CrlDistributionPoints
, &getFieldCrlDistPoints
,
654 &setFieldCrlDistPoints
, &freeFieldCrlDistPoints
},
655 { &CSSMOID_X509V3CertificateExtensionCStruct
, &getFieldUnknownExt
,
656 &setFieldUnknownExt
, &freeFieldUnknownExt
},
657 { &CSSMOID_AuthorityInfoAccess
, &getFieldAuthInfoAccess
,
658 &setFieldAuthInfoAccess
, &freeFieldInfoAccess
},
659 { &CSSMOID_SubjectInfoAccess
, &getFieldSubjInfoAccess
,
660 &setFieldAuthInfoAccess
, &freeFieldInfoAccess
},
661 { &CSSMOID_QC_Statements
, &getFieldQualCertStatements
,
662 &setFieldQualCertStatements
, &freeFieldQualCertStatements
},
664 { &CSSMOID_NameConstraints
, &getFieldNameConstraints
,
665 &setFieldNameConstraints
, &freeFieldNameConstraints
},
666 { &CSSMOID_PolicyMappings
, &getFieldPolicyMappings
,
667 &setFieldPolicyMappings
, &freeFieldPolicyMappings
},
668 { &CSSMOID_PolicyConstraints
, &getFieldPolicyConstraints
,
669 &setFieldPolicyConstraints
, &freeFieldPolicyConstraints
},
670 { &CSSMOID_InhibitAnyPolicy
, &getFieldInhibitAnyPolicy
,
671 &setFieldInhibitAnyPolicy
, &freeFieldSimpleExtension
},
675 #define NUM_KNOWN_FIELDS (sizeof(fieldFuncTable) / sizeof(oidToFieldFuncs))
676 #define NUM_STD_CERT_FIELDS 17 /* not including extensions */
678 /* map an OID to an oidToFieldFuncs */
679 static const oidToFieldFuncs
*oidToFields(
680 const CssmOid
&fieldId
)
682 const oidToFieldFuncs
*fieldTable
= fieldFuncTable
;
683 for(unsigned i
=0; i
<NUM_KNOWN_FIELDS
; i
++) {
684 if(fieldId
== CssmData::overlay(*fieldTable
->fieldId
)) {
689 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG
);
698 * Obtain the index'th occurrence of field specified by fieldId in specified cert.
699 * Format of the returned field depends on fieldId.
700 * Returns total number of fieldId fields in the cert if index is 0.
701 * FieldValue assumed to be empty on entry.
702 * Returns true if specified field was found, else returns false.
704 bool DecodedCert::getCertFieldData(
705 const CssmOid
&fieldId
, // which field
706 unsigned index
, // which occurrence (0 = first)
707 uint32
&numFields
, // RETURNED
708 CssmOwnedData
&fieldValue
) // RETURNED
713 clErrorLog("DecodedCert::getCertField: can't parse undecoded cert!");
714 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR
);
719 const oidToFieldFuncs
*fieldFuncs
= oidToFields(fieldId
);
720 return fieldFuncs
->getFcn(*this, index
, numFields
, fieldValue
);
724 * Set the field specified by fieldId in the specified Cert.
725 * Note no index - individual field routines either append (for extensions)
726 * or if field already set ::throwMe(for all others)
728 void DecodedCert::setCertField(
729 const CssmOid
&fieldId
, // which field
730 const CssmData
&fieldValue
)
733 case IS_Empty
: // first time thru
734 mState
= IS_Building
;
736 case IS_Building
: // subsequent passes
740 clErrorLog("DecodedCert::setCertField: can't build on a decoded cert!");
741 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR
);
743 if((fieldValue
.data() == NULL
) || (fieldValue
.length() == 0)) {
744 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER
);
746 const oidToFieldFuncs
*fieldFuncs
= oidToFields(fieldId
);
747 const CssmData
&value
= CssmData::overlay(fieldValue
);
748 fieldFuncs
->setFcn(*this, value
);
752 * Free the fieldId-specific data referred to by fieldValue->Data.
754 void DecodedCert::freeCertFieldData(
755 const CssmOid
&fieldId
,
756 CssmOwnedData
&fieldValue
)
758 if((fieldValue
.data() == NULL
) || (fieldValue
.length() == 0)) {
759 CssmError::throwMe(CSSM_ERRCODE_INVALID_FIELD_POINTER
);
761 const oidToFieldFuncs
*fieldFuncs
= oidToFields(fieldId
);
762 if(fieldFuncs
->freeFcn
!= NULL
) {
763 /* optional - simple cases handled below */
764 fieldFuncs
->freeFcn(fieldValue
);
767 fieldValue
.release();
773 * Common means to get all fields from a decoded cert. Used in
774 * CertGetAllTemplateFields and CertGetAllFields.
776 void DecodedCert::getAllParsedCertFields(
777 uint32
&NumberOfFields
, // RETURNED
778 CSSM_FIELD_PTR
&CertFields
) // RETURNED
780 /* this is the max - some might be missing */
781 uint32 maxFields
= NUM_STD_CERT_FIELDS
+ mDecodedExtensions
.numExtensions();
782 CSSM_FIELD_PTR outFields
= (CSSM_FIELD_PTR
)mAlloc
.malloc(maxFields
* sizeof(CSSM_FIELD
));
785 * We'll be copying oids and values for fields we find into
786 * outFields; current number of valid fields found in numOutFields.
788 memset(outFields
, 0, maxFields
* sizeof(CSSM_FIELD
));
789 uint32 numOutFields
= 0;
790 CSSM_FIELD_PTR currOutField
;
792 const CSSM_OID
*currOid
;
793 CssmAutoData
aData(mAlloc
); // for malloc/copy of outgoing data
795 /* query for each OID we know about */
796 for(currOidDex
=0; currOidDex
<NUM_KNOWN_FIELDS
; currOidDex
++) {
797 const oidToFieldFuncs
*fieldFuncs
= &fieldFuncTable
[currOidDex
];
798 currOid
= fieldFuncs
->fieldId
;
799 uint32 numFields
; // for THIS oid
802 * Return false if field not there, which is not an error here.
803 * Actual exceptions are fatal.
805 if(!fieldFuncs
->getFcn(*this,
806 0, // index - looking for first one
812 /* got some data for this oid - copy it and oid to outgoing CertFields */
813 assert(numOutFields
< maxFields
);
814 currOutField
= &outFields
[numOutFields
];
815 currOutField
->FieldValue
= aData
.release();
816 aData
.copy(*currOid
);
817 currOutField
->FieldOid
= aData
.release();
820 /* if more fields are available for this OID, snag them too */
821 for(uint32 fieldDex
=1; fieldDex
<numFields
; fieldDex
++) {
822 /* note this should always succeed */
823 bool brtn
= fieldFuncs
->getFcn(*this,
825 numFields
, // shouldn't change
828 clErrorLog("getAllParsedCertFields: index screwup");
829 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR
);
831 assert(numOutFields
< maxFields
);
832 currOutField
= &outFields
[numOutFields
];
833 currOutField
->FieldValue
= aData
.release();
834 aData
.copy(*currOid
);
835 currOutField
->FieldOid
= aData
.release();
837 } /* multiple fields for currOid */
838 } /* for each known OID */
840 NumberOfFields
= numOutFields
;
841 CertFields
= outFields
;
845 DecodedCert::describeFormat(
847 uint32
&NumberOfFields
,
848 CSSM_OID_PTR
&OidList
)
850 /* malloc in app's space, do deep copy (including ->Data) */
851 CSSM_OID_PTR oidList
= (CSSM_OID_PTR
)alloc
.malloc(
852 NUM_KNOWN_FIELDS
* sizeof(CSSM_OID
));
853 memset(oidList
, 0, NUM_KNOWN_FIELDS
* sizeof(CSSM_OID
));
854 for(unsigned i
=0; i
<NUM_KNOWN_FIELDS
; i
++) {
855 CssmAutoData
oidCopy(alloc
, *fieldFuncTable
[i
].fieldId
);
856 oidList
[i
] = oidCopy
.release();
858 NumberOfFields
= NUM_KNOWN_FIELDS
;