]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_apple_x509_cl/lib/DecodedItem.h
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_apple_x509_cl / lib / DecodedItem.h
1 /*
2 * Copyright (c) 2000-2002,2011,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 * DecodedItem.h - class representing the common portions of NSS-format
21 * decoded certs and CRLs, with extensions parsed and decoded (still in
22 * NSS format).
23 *
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).
33 *
34 * Decoding a cert or a CRL:
35 * -------------------------
36 *
37 * When an app decodes a cert or CRL for any reason, the following phases
38 * are executed:
39 *
40 * PHASE I
41 * -------
42 *
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.
47 *
48 * PHASE II
49 * --------
50 *
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.
57 *
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
60 * state "NSS Form".
61 *
62 * PHASE III (CRLs only)
63 * --------------------
64 *
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.
70 *
71 * PHASE IV
72 * ---------
73 *
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.
77 *
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.
90 *
91 *
92 * Creating and encoding a cert:
93 * -----------------------------
94 *
95 * Creating a cert (creating CRLs is not supported in this release)
96 * follows more or less the reverse procedure, as follows:
97 *
98 * PHASE I
99 * -------
100 *
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).
105 *
106 * PHASE II
107 * --------
108 *
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.
114 *
115 * PHASE III
116 * ---------
117 *
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.
122 *
123 * PHASE IV
124 * --------
125 *
126 * The TBS cert blob is signed and the resulting DER-encoded
127 * cert is passed back to the app.
128 */
129
130 #ifndef _DECODED_ITEM_H_
131 #define _DECODED_ITEM_H_
132
133 #include <Security/cssmtype.h>
134 #include <security_cdsa_utilities/cssmdata.h>
135
136 #include "cldebugging.h"
137 #include "DecodedExtensions.h"
138 #include <security_asn1/SecNssCoder.h>
139
140 /* state of a DecodedItem */
141 typedef enum {
142 IS_Empty,
143 IS_DecodedAll, // can't set fields in this state
144 IS_DecodedTBS, // ditto
145 IS_Building // in the process of setting fields
146 } ItemState;
147
148
149 class AppleX509CLSession;
150
151 class DecodedItem
152 {
153 public:
154 DecodedItem(
155 AppleX509CLSession &session);
156
157 virtual ~DecodedItem();
158
159 SecNssCoder &coder() { return mCoder; }
160
161 static void describeFormat(
162 Allocator &alloc,
163 uint32 &NumberOfFields,
164 CSSM_OID_PTR &OidList);
165
166 public:
167 /***
168 *** Extensions support
169 ***/
170
171 /* called from decodeExtensions and setField* */
172 void addExtension(
173 void *nssThing, // e.g. NSS_KeyUsage
174 const CSSM_OID &extnId,
175 bool critical,
176 bool berEncoded,
177 const SecAsn1Template *templ, // to decode/encode if !berEncoded
178 const CSSM_DATA *rawExtn=NULL) // Extension.extnValue, copied, only for
179 // setField*()
180 { mDecodedExtensions.addExtension(extnId, critical, nssThing,
181 berEncoded, templ, rawExtn);
182 }
183
184 const DecodedExten *findDecodedExt(
185 const CSSM_OID &extnId, // for known extensions
186 bool unknown, // otherwise
187 uint32 index,
188 uint32 &numFields) const;
189
190 const DecodedExtensions &decodedExtens() const
191 { return mDecodedExtensions; }
192
193 /*
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
198 * DecodedExten.
199 */
200 template<class NssType, class CdsaType>
201 bool GetExtenTop(
202 unsigned index, // which occurrence (0 = first)
203 uint32 &numFields, // RETURNED
204 Allocator &alloc,
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
209 {
210 /* See if we have one of these in our list of DecodedExtens */
211 decodedExt = findDecodedExt(fieldId, false, index, numFields);
212 if(decodedExt == NULL) {
213 return false;
214 }
215 nssObj = (NssType *)decodedExt->nssObj();
216 cdsaObj = (CdsaType *)alloc.malloc(sizeof(CdsaType));
217 memset(cdsaObj, 0, sizeof(CdsaType));
218 return true;
219 }
220
221 protected:
222 ItemState mState;
223 Allocator &mAlloc;
224 SecNssCoder mCoder; // from which all local allocs come
225 AppleX509CLSession &mSession;
226 DecodedExtensions mDecodedExtensions;
227
228 };
229
230
231 #endif /* _DECODED_ITEM_H_ */