]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | /* | |
25 | * pkcs12Coder.h - main PKCS12 encode/decode engine. This class | |
26 | * corresponds to a SecPkcs12CoderRef in the public API. | |
27 | */ | |
28 | ||
29 | #ifndef _PKCS12_CODER_H_ | |
30 | #define _PKCS12_CODER_H_ | |
31 | ||
32 | #include <security_pkcs12/SecPkcs12.h> | |
33 | #include <security_pkcs12/pkcs12SafeBag.h> | |
34 | #include <vector> | |
35 | ||
36 | /* | |
37 | * This class essentially consists of the following: | |
38 | * | |
39 | * -- bags of certs, CRLs, keys, and opaque blobs in the | |
40 | * form of P12SafeBag subclasses. | |
41 | * | |
42 | * -- getters and setters to let the app access those bags. | |
43 | * | |
44 | * -- a decode routine which takes an encoded PFX, rips it apart, | |
45 | * and drops what it finds into the bags of cert, CRLS, etc. | |
46 | * | |
47 | * -- an encode routine which takes the contents of the bag and | |
48 | * creates an encoded PFX. | |
49 | * | |
50 | * Everything else is ephemera supporting the above four things. | |
51 | * | |
52 | * Memory usage: | |
53 | * ------------- | |
54 | * | |
55 | * Memory allocation is done in three flavors: | |
56 | * | |
57 | * 1. Via CF objects, when exporting contents of bags to the app. | |
58 | * 2. Via our own member variable SecNssCoder. This is used to allocate | |
59 | * the contents of the bags (certs, etc.) which persist across | |
60 | * API calls. | |
61 | * 3. "Local" SecNssCoders for encode and decode. Allocated in the | |
62 | * stack for those two exported functions and used for all decoding | |
63 | * and encoding. | |
64 | * | |
65 | * The contents of the bags persist as long as an instance of | |
66 | * P12Coder does. | |
67 | * | |
68 | * CF objects the app gives us (e..g, passphrases) | |
69 | * are retained when get them and released in our destructor. | |
70 | * | |
71 | * CF objects we give the app are, of course, the app's responsibility. | |
72 | * | |
73 | * Everything else is allocd locally via the SecNssCoders in encode() | |
74 | * and decode() and has a scope not exceeding those functions. | |
75 | */ | |
76 | ||
77 | class P12Coder { | |
78 | public: | |
79 | /* only constructor */ | |
80 | P12Coder(); | |
81 | ~P12Coder(); | |
82 | ||
83 | /* | |
84 | * These public functions more or less correspond to | |
85 | * the public functions in SecPkcs12.h. | |
86 | */ | |
87 | void setMacPassPhrase( | |
88 | CFStringRef passphrase); | |
89 | void setEncrPassPhrase( | |
90 | CFStringRef passphrase); | |
91 | void setMacPassKey( | |
92 | const CSSM_KEY *passKey); | |
93 | void setEncrPassKey( | |
94 | const CSSM_KEY *passKey); | |
95 | ||
96 | /* main decode function */ | |
97 | void decode( | |
98 | CFDataRef pfx); | |
99 | ||
100 | /* | |
101 | * CSP and DLDB associated with keys. | |
102 | * CSP handle is required, DLDB optional. | |
103 | */ | |
104 | void setKeychain( | |
105 | SecKeychainRef keychain); | |
106 | void setCsp( | |
107 | CSSM_CSP_HANDLE cspHand) { mCspHand = cspHand; } | |
108 | void setDlDb( | |
109 | CSSM_DL_DB_HANDLE dlDbHand) { mDlDbHand = dlDbHand; } | |
110 | ||
111 | CSSM_CSP_HANDLE cspHand() { return mCspHand; } | |
112 | ||
113 | /* private key import attributes */ | |
114 | void setAccess( | |
115 | SecAccessRef access); | |
116 | void setKeyUsage( | |
117 | CSSM_KEYUSE keyUsage) { mKeyUsage = keyUsage; } | |
118 | void setKeyAttrs( | |
119 | CSSM_KEYATTR_FLAGS keyAttrs); | |
120 | ||
121 | /* High-level import/export */ | |
122 | void importFlags( | |
123 | SecPkcs12ImportFlags flags) { mImportFlags = flags; } | |
124 | SecPkcs12ImportFlags importFlags() | |
125 | { return mImportFlags; } | |
126 | ||
127 | void exportKeychainItems( | |
128 | CFArrayRef items); | |
129 | ||
130 | /* getters */ | |
131 | unsigned numCerts(); | |
132 | unsigned numCrls(); | |
133 | unsigned numKeys(); | |
134 | unsigned numOpaqueBlobs(); | |
135 | ||
136 | P12CertBag *getCert( | |
137 | unsigned dex); | |
138 | P12CrlBag *getCrl( | |
139 | unsigned dex); | |
140 | P12KeyBag *getKey( | |
141 | unsigned dex); | |
142 | P12OpaqueBag *getOpaque( | |
143 | unsigned dex); | |
144 | ||
145 | /* encoding */ | |
146 | void encode( | |
147 | CFDataRef *pfx); // RETURNED | |
148 | ||
149 | void addCert( | |
150 | P12CertBag *cert); | |
151 | void addCrl( | |
152 | P12CrlBag *crl); | |
153 | void addKey( | |
154 | P12KeyBag *key); | |
155 | void addOpaque( | |
156 | P12OpaqueBag *opaque); | |
157 | ||
158 | /* little known, but public, functions */ | |
159 | SecPkcs12Mode integrityMode() { return mIntegrityMode; } | |
160 | SecPkcs12Mode privacyMode() { return mPrivacyMode; } | |
161 | void integrityMode( | |
162 | SecPkcs12Mode mode); | |
163 | void privacyMode( | |
164 | SecPkcs12Mode mode); | |
165 | ||
166 | /* | |
167 | * Public API calls use our coder to create P12SafeBags | |
168 | */ | |
169 | SecNssCoder &coder() { return mCoder; } | |
170 | ||
171 | /* encryption parameter getters/setters */ | |
172 | unsigned weakEncrIterCount() { return mWeakEncrIterCount; } | |
173 | unsigned strongEncrIterCount() { return mStrongEncrIterCount; } | |
174 | unsigned macEncrIterCount() { return mMacIterCount; } | |
175 | ||
176 | void weakEncrIterCount( | |
177 | unsigned ic) { mWeakEncrIterCount = ic; } | |
178 | void strongEncrIterCount( | |
179 | unsigned ic) { mStrongEncrIterCount = ic; } | |
180 | void macEncrIterCount( | |
181 | unsigned ic) { mMacIterCount = ic; } | |
182 | ||
183 | CFDataRef weakEncrAlg(); | |
184 | CFDataRef strongEncrAlg(); | |
185 | ||
186 | void weakEncrAlg( | |
187 | CFDataRef alg); | |
188 | void strongEncrAlg( | |
189 | CFDataRef alg); | |
190 | ||
191 | /* panic button, delete anything stored in a DB during decode */ | |
192 | void deleteDecodedItems(); | |
193 | ||
194 | void limitPrivKeyImport( | |
195 | bool foundOneKey); | |
196 | ||
197 | private: | |
198 | void init(); // one-time init from all constructors | |
199 | ||
200 | /* | |
201 | * Passphrase handling. | |
202 | * | |
203 | * These two convert the app-supplied CFStringRefs into | |
204 | * CSSM_DATAs; if PassKeys are used, these just NULL out | |
205 | * the returned data. | |
206 | */ | |
207 | const CSSM_DATA *getMacPassPhrase(); | |
208 | const CSSM_DATA *getEncrPassPhrase(); | |
209 | ||
210 | /* | |
211 | * These return a CSSM_KEY_PTR is the app had specified | |
212 | * PassKeys, else they return NULL. | |
213 | */ | |
214 | const CSSM_KEY *getMacPassKey(); | |
215 | const CSSM_KEY *getEncrPassKey(); | |
216 | ||
217 | /* in pkcs12Keychain.cpp */ | |
218 | void storeDecodeResults(); | |
219 | void setPrivateKeyHashes(); | |
220 | void notifyKeyImport(); | |
221 | P12CertBag *findCertForKey( | |
222 | P12KeyBag *keyBag); | |
223 | ||
224 | void addSecKey( | |
225 | SecKeyRef keyRef); | |
226 | void addSecCert( | |
227 | SecCertificateRef certRef); | |
228 | ||
229 | /* Lazy evaluation of module handles. */ | |
230 | CSSM_CSP_HANDLE rawCspHand(); | |
231 | CSSM_CL_HANDLE clHand(); | |
232 | ||
233 | /* | |
234 | * A bunch of private encode/decode methods. This makes me | |
235 | * long for ObjC-style categories so these would not | |
236 | * have to appear in this file. | |
237 | * | |
238 | * See implementation for comments and descriptions. | |
239 | */ | |
240 | void encryptedDataDecrypt( | |
241 | const NSS_P7_EncryptedData &edata, | |
242 | SecNssCoder &localCdr, | |
243 | NSS_P12_PBE_Params *pbep, | |
244 | CSSM_DATA &ptext); | |
245 | ||
246 | void algIdParse( | |
247 | const CSSM_X509_ALGORITHM_IDENTIFIER &algId, | |
248 | NSS_P12_PBE_Params *pbeParams, | |
249 | SecNssCoder &localCdr); | |
250 | ||
251 | void encryptedDataParse( | |
252 | const NSS_P7_EncryptedData &edata, | |
253 | SecNssCoder &localCdr, | |
254 | NSS_P12_PBE_Params *pbep); | |
255 | ||
256 | void shroudedKeyBagParse( | |
257 | const NSS_P12_SafeBag &safeBag, | |
258 | SecNssCoder &localCdr); | |
259 | ||
260 | void keyBagParse( | |
261 | const NSS_P12_SafeBag &safeBag, | |
262 | SecNssCoder &localCdr); | |
263 | ||
264 | void certBagParse( | |
265 | const NSS_P12_SafeBag &safeBag, | |
266 | SecNssCoder &localCdr); | |
267 | ||
268 | void crlBagParse( | |
269 | const NSS_P12_SafeBag &safeBag, | |
270 | SecNssCoder &localCdr); | |
271 | ||
272 | void secretBagParse( | |
273 | const NSS_P12_SafeBag &safeBag, | |
274 | SecNssCoder &localCdr); | |
275 | ||
276 | void safeContentsBagParse( | |
277 | const NSS_P12_SafeBag &safeBag, | |
278 | SecNssCoder &localCdr); | |
279 | ||
280 | void safeContentsParse( | |
281 | const CSSM_DATA &contentsBlob, | |
282 | SecNssCoder &localCdr); | |
283 | ||
284 | void authSafeElementParse( | |
285 | const NSS_P7_DecodedContentInfo *info, | |
286 | SecNssCoder &localCdr); | |
287 | ||
288 | void macParse( | |
289 | const NSS_P12_MacData &macData, | |
290 | SecNssCoder &localCdr); | |
291 | ||
292 | void authSafeParse( | |
293 | const CSSM_DATA &authSafeBlob, | |
294 | SecNssCoder &localCdr); | |
295 | ||
296 | /* private encoding routines */ | |
297 | NSS_P7_DecodedContentInfo *safeContentsBuild( | |
298 | NSS_P12_SafeBag **bags, | |
299 | NSS_P7_CI_Type type, // CT_Data, CT_EncryptedData | |
300 | CSSM_OID *encrOid, // only for CT_EncryptedData | |
301 | unsigned iterCount, // ditto | |
302 | SecNssCoder &localCdr); | |
303 | ||
304 | void authSafeBuild( | |
305 | NSS_P7_DecodedContentInfo &authSafe, | |
306 | SecNssCoder &localCdr); | |
307 | ||
308 | void encryptData( | |
309 | const CSSM_DATA &ptext, | |
310 | CSSM_OID &encrOid, | |
311 | unsigned iterCount, | |
312 | NSS_P7_EncryptedData &ed, | |
313 | SecNssCoder &localCdr); | |
314 | ||
315 | void algIdBuild( | |
316 | CSSM_X509_ALGORITHM_IDENTIFIER &algId, | |
317 | const CSSM_OID &algOid, | |
318 | const CSSM_DATA &salt, | |
319 | unsigned iterCount, | |
320 | SecNssCoder &localCdr); | |
321 | ||
322 | void macSignPfx( | |
323 | NSS_P12_DecodedPFX &pfx, | |
324 | SecNssCoder &localCdr); | |
325 | ||
326 | NSS_P12_SafeBag *certBagBuild( | |
327 | P12CertBag *cert, | |
328 | SecNssCoder &localCdr); | |
329 | ||
330 | NSS_P12_SafeBag *crlBagBuild( | |
331 | P12CrlBag *crl, | |
332 | SecNssCoder &localCdr); | |
333 | ||
334 | NSS_P12_SafeBag *keyBagBuild( | |
335 | P12KeyBag *key, | |
336 | SecNssCoder &localCdr); | |
337 | ||
338 | NSS_P12_SafeBag *opaqueBagBuild( | |
339 | P12OpaqueBag *op, | |
340 | SecNssCoder &localCdr); | |
341 | ||
342 | /* member variables */ | |
343 | SecPkcs12Mode mPrivacyMode; | |
344 | SecPkcs12Mode mIntegrityMode; | |
345 | ||
346 | /* passwords - as app gave us, and translated into ready-to-use | |
347 | * unicode strings */ | |
348 | CFStringRef mMacPassphrase; | |
349 | CFStringRef mEncrPassPhrase; | |
350 | CSSM_DATA mMacPassData; | |
351 | CSSM_DATA mEncrPassData; | |
352 | ||
353 | /* passphrases in key form */ | |
354 | const CSSM_KEY *mMacPassKey; | |
355 | const CSSM_KEY *mEncrPassKey; | |
356 | ||
357 | /* | |
358 | * App has to either set mKeychain or mCspHand. In the former | |
359 | * case we infer both mCspHand and mDlDbHand from the keychainRef. | |
360 | */ | |
361 | SecKeychainRef mKeychain; | |
362 | CSSM_CSP_HANDLE mCspHand; | |
363 | CSSM_DL_DB_HANDLE mDlDbHand; | |
364 | ||
365 | /* | |
366 | * LimitPrivateKeyImport mechanism | |
367 | */ | |
368 | typedef enum { | |
369 | PKIS_NoLimit, // no limit | |
370 | PKIS_AllowOne, // allow import of at most one | |
371 | PKIS_NoMore // found one, no more allowed | |
372 | } p12PrivKeyImportState; | |
373 | ||
374 | p12PrivKeyImportState mPrivKeyImportState; | |
375 | ||
376 | /* | |
377 | * Encryption/MAC parameters | |
378 | */ | |
379 | CSSM_OID mWeakEncrAlg; // for certs and CRLs | |
380 | CSSM_OID mStrongEncrAlg; | |
381 | unsigned mWeakEncrIterCount; | |
382 | unsigned mStrongEncrIterCount; | |
383 | unsigned mMacIterCount; | |
384 | ||
385 | /* | |
386 | * Import flags | |
387 | */ | |
388 | SecPkcs12ImportFlags mImportFlags; | |
389 | ||
390 | /* | |
391 | * Four individual piles of safe bags | |
392 | */ | |
393 | vector<P12CertBag *> mCerts; | |
394 | vector<P12CrlBag *> mCrls; | |
395 | vector<P12KeyBag *> mKeys; | |
396 | vector<P12OpaqueBag *> mOpaques; | |
397 | ||
398 | /* | |
399 | * Internal CSSM module handles, lazily evaluated. | |
400 | */ | |
401 | CSSM_CSP_HANDLE mRawCspHand; | |
402 | CSSM_CL_HANDLE mClHand; | |
403 | ||
404 | /* | |
405 | * Imported private key attributes | |
406 | */ | |
407 | SecAccessRef mAccess; | |
408 | bool mNoAcl; /* true when NULL passed to setAccess() */ | |
409 | CSSM_KEYUSE mKeyUsage; | |
410 | CSSM_KEYATTR_FLAGS mKeyAttrs; | |
411 | ||
412 | /* | |
413 | * The source of most (all?) of our privately allocated data | |
414 | */ | |
415 | SecNssCoder mCoder; | |
416 | }; | |
417 | ||
418 | #endif /* _PKCS12_CODER_H_ */ | |
419 |