2 * Copyright (c) 2000-2002,2011,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 * DecodedItem.h - class representing the common portions of NSS-format
21 * decoded certs and CRLs, with extensions parsed and decoded (still in
24 * When a DecodedItem (cert or CRL) is quiescent and cached in the CL
25 * (either by an explicit cache call like CSSM_CL_CertCache or
26 * CSSM_CL_CrlCache(), or during a succession of GetFirst/GetNext field
27 * ops), the item is stored in the CL in what we call NSS form. NSS is
28 * the module we use to perform DER encoding and decoding; NSS form
29 * refers to structs defining Certs, CRLs, and extensions which are
30 * directly encodable and decodable by the NSS library. NSS structs are
31 * similar to their CDSA counterparts, sometimes identical, usually
32 * subtly different (due to requirements of the NSS module).
34 * Decoding a cert or a CRL:
35 * -------------------------
37 * When an app decodes a cert or CRL for any reason, the following phases
43 * Basic BER-decode if the incoming CSSM_DATA blob. This happens in the
44 * constructors for DecodedCert and DecodedCrl. A modified/restricted
45 * version of this occurs in DecodedCert::decodeTbs(), which is used
46 * during a CSSM_CL_CertGetAllTemplateFields() call.
51 * Extensions are converted from untyped blobs - which is how they look
52 * after PHASE I - to NSS-style C structs. This is done by examining
53 * the ExtnId of each cert's or CRL's extensions and doing a BER decode
54 * specific to that extension type. This is performed in
55 * DecodedExtensions.decodeFromNss() which is called immediately after
56 * the top-level decode performed in PHASE I.
58 * It is at this point that a cert or CRL can be cached in the CL's
59 * cacheMap or queryMap (see AppleX509CLSession.{h,cpp}. We call this
62 * PHASE III (CRLs only)
63 * --------------------
65 * This occurs when an app is actually fetching a full CRL in
66 * CDSA form. Individual entries in a CRL's revocation list also
67 * contain per-entry extension lists. These are converted from
68 * untyped blobs to meaningful NSS-style extension structs as
69 * in PHASE II prior to the conversion to CDSA form in PHASE IV.
74 * This occurs when an app is actually fetching fields in CDSA form.
75 * This involves converting objects from NSS form to CDSA form
76 * (if necessary) and copying to the session allocator's memory space.
78 * The rationale behind this phased approach - in particular, the
79 * reason that in-memory items are stored in NSS form - is that this
80 * minimizes the number of copies between the intiial parse of a cert
81 * or CRL and the final GetField op. Since a GetField op inherently
82 * requires a copy (from internal memory to the session allocator's
83 * space), and conversion from NSS to CDSA form is basically a bunch of
84 * copies as well, we might as well just stop with the item in CRL
85 * format as soon as PHASE II is complete. Note that completion of
86 * PHASE II is in fact required before caching a cert since that enables
87 * us to have access to extension-specific info while a cert is
88 * cached. The KeyUsage and ExtendedKeyUsage extensions are used in
89 * this manner to get key info from a TBS cert.
92 * Creating and encoding a cert:
93 * -----------------------------
95 * Creating a cert (creating CRLs is not supported in this release)
96 * follows more or less the reverse procedure, as follows:
101 * During a CSSM_CL_CertCreateTemplate() op, all fields which the
102 * app wishes to specify are passed into the CL in CDSA form. These
103 * fields are converted to NSS form in a temporary DecodedCert. This
104 * includes extensions (in NSS form).
109 * Extensions in NSS form are encoded and bundled up into the final,
110 * BER-encode ready NSS_CertExtension array form. This occurs
111 * in DecodedCert::encodeExtensions(), called from the top of
112 * DecodedCert::encodeTbs(). We're still processing an app's
113 * CSSM_CL_CertCreateTemplate() call at this point.
118 * Final DER-encoding of a TBS cert is performed in
119 * DecodedCert::encodeTbs(). The resulting CSSM_DATA is
120 * passed back to the app as what CDSA calls a template.
121 * This completes the CSSM_CL_CertCreateTemplate() call.
126 * The TBS cert blob is signed and the resulting DER-encoded
127 * cert is passed back to the app.
130 #ifndef _DECODED_ITEM_H_
131 #define _DECODED_ITEM_H_
133 #include <Security/cssmtype.h>
134 #include <security_cdsa_utilities/cssmdata.h>
136 #include "cldebugging.h"
137 #include "DecodedExtensions.h"
138 #include <security_asn1/SecNssCoder.h>
140 /* state of a DecodedItem */
143 IS_DecodedAll
, // can't set fields in this state
144 IS_DecodedTBS
, // ditto
145 IS_Building
// in the process of setting fields
149 class AppleX509CLSession
;
155 AppleX509CLSession
&session
);
157 virtual ~DecodedItem();
159 SecNssCoder
&coder() { return mCoder
; }
161 static void describeFormat(
163 uint32
&NumberOfFields
,
164 CSSM_OID_PTR
&OidList
);
168 *** Extensions support
171 /* called from decodeExtensions and setField* */
173 void *nssThing
, // e.g. NSS_KeyUsage
174 const CSSM_OID
&extnId
,
177 const SecAsn1Template
*templ
, // to decode/encode if !berEncoded
178 const CSSM_DATA
*rawExtn
=NULL
) // Extension.extnValue, copied, only for
180 { mDecodedExtensions
.addExtension(extnId
, critical
, nssThing
,
181 berEncoded
, templ
, rawExtn
);
184 const DecodedExten
*findDecodedExt(
185 const CSSM_OID
&extnId
, // for known extensions
186 bool unknown
, // otherwise
188 uint32
&numFields
) const;
190 const DecodedExtensions
&decodedExtens() const
191 { return mDecodedExtensions
; }
194 * Common code for get extension field routines.
195 * Given an OID identifying an extension and an index, see if
196 * we have the specified extension in mDecodedExtensions and
197 * return the NSS and CDSA style objects as well as the
200 template<class NssType
, class CdsaType
>
202 unsigned index
, // which occurrence (0 = first)
203 uint32
&numFields
, // RETURNED
205 const CSSM_OID
&fieldId
, // identifies extension we seek
206 NssType
*&nssObj
, // RETURNED
207 CdsaType
*&cdsaObj
, // mallocd and RETURNED
208 const DecodedExten
*&decodedExt
) const // RETURNED
210 /* See if we have one of these in our list of DecodedExtens */
211 decodedExt
= findDecodedExt(fieldId
, false, index
, numFields
);
212 if(decodedExt
== NULL
) {
215 nssObj
= (NssType
*)decodedExt
->nssObj();
216 cdsaObj
= (CdsaType
*)alloc
.malloc(sizeof(CdsaType
));
217 memset(cdsaObj
, 0, sizeof(CdsaType
));
224 SecNssCoder mCoder
; // from which all local allocs come
225 AppleX509CLSession
&mSession
;
226 DecodedExtensions mDecodedExtensions
;
231 #endif /* _DECODED_ITEM_H_ */