1/* 2 * Copyright (c) 2000-2002 Apple Computer, 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 */ 141typedef 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 149class AppleX509CLSession; 150 151class DecodedItem 152{ 153public: 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 166public: 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 221protected: 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_ */ 232