]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Copyright (c) 2000-2001 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 | #ifdef BSAFE_CSP_ENABLE | |
19 | ||
20 | ||
21 | // | |
22 | // bsafecspi - implementation layer for C++ BSafe 4 interface | |
23 | // | |
24 | #ifndef _H_BSAFECSPI | |
25 | #define _H_BSAFECSPI | |
26 | ||
27 | #include <security_cdsa_plugin/CSPsession.h> | |
28 | #include "bsobjects.h" | |
29 | #include "AppleCSPContext.h" | |
30 | #include "AppleCSPSession.h" | |
31 | #include <aglobal.h> | |
32 | #include <bsafe.h> | |
33 | ||
34 | // | |
35 | // The BSafe class is more of a namespace than anything else. | |
36 | // Just think of it as the "static binder" for BSafe's objects. | |
37 | // Note that we keep a global, static allocator. We have to; BSafe | |
38 | // doesn't have any state management at that level. | |
39 | // | |
40 | class BSafe { | |
41 | class BSafeContext; friend class BSafeContext; | |
42 | class BSafeFactory; friend class BSafeFactory; | |
43 | ||
44 | public: | |
45 | static void setNormAllocator(Allocator *alloc) | |
46 | { assert(!normAllocator); normAllocator = alloc; } | |
47 | static void setPrivAllocator(Allocator *alloc) | |
48 | { assert(!privAllocator); privAllocator = alloc; } | |
49 | ||
50 | static bool setup( | |
51 | AppleCSPSession &session, | |
52 | CSPFullPluginSession::CSPContext * &cspCtx, | |
53 | const Context &context); | |
54 | ||
55 | private: | |
56 | // BSafe's memory allocators | |
57 | static Allocator *normAllocator; | |
58 | static Allocator *privAllocator; | |
59 | friend POINTER T_malloc(unsigned int); | |
60 | friend void T_free(POINTER); | |
61 | friend POINTER T_realloc(POINTER, unsigned int); | |
62 | ||
63 | static const B_ALGORITHM_METHOD * const bsChooser[]; | |
64 | ||
65 | private: | |
66 | // BSafe-specific BinaryKey class. | |
67 | class BSafeBinaryKey : public BinaryKey { | |
68 | ||
69 | public: | |
70 | BSafeBinaryKey( | |
71 | bool isPub, | |
72 | uint32 alg); // CSSM_ALGID_{RSA,DSA} | |
73 | ~BSafeBinaryKey(); | |
74 | void generateKeyBlob( | |
75 | Allocator &allocator, | |
76 | CssmData &blob, | |
77 | CSSM_KEYBLOB_FORMAT &format, | |
78 | AppleCSPSession &session, | |
79 | const CssmKey *paramKey, /* optional, unused here */ | |
80 | CSSM_KEYATTR_FLAGS &attrFlags); /* IN/OUT */ | |
81 | ||
82 | bool isPublic() { return mIsPublic; } | |
83 | uint32 alg() { return mAlg; } | |
84 | B_KEY_OBJ bsKey() { return mBsKey; } | |
85 | ||
86 | private: | |
87 | bool mIsPublic; | |
88 | uint32 mAlg; // CSSM_ALGID_{RSA,DSA} | |
89 | B_KEY_OBJ mBsKey; | |
90 | }; | |
91 | ||
92 | private: | |
93 | // | |
94 | // The BSafeContext class is the parent of all BSafe-used CSPContext objects. | |
95 | // It implements the CSPContext operation functions (init, update, ...) in terms | |
96 | // of pointer-to-member fields set by its subclasses. This may not be pretty, but | |
97 | // it avoids every subclass having to re-implement all CSPContext operations. | |
98 | // Beyond that, we implement a raftload of utility methods for our children. | |
99 | // | |
100 | class BSafeContext : public AppleCSPContext { | |
101 | friend class BSafe; | |
102 | public: | |
103 | BSafeContext(AppleCSPSession &session); | |
104 | virtual ~BSafeContext(); | |
105 | ||
106 | // called by CSPFullPluginSession | |
107 | void init(const Context &context, bool encoding = true); | |
108 | void update(const CssmData &data); | |
109 | void update(void *inp, size_t &inSize, void *outp, size_t &outSize); | |
110 | void final(CssmData &out); | |
111 | void final(const CssmData &in); | |
112 | size_t outputSize(bool final, size_t inSize); | |
113 | ||
114 | protected: | |
115 | // install a BSafe algorithm into bsAlgorithm | |
116 | void setAlgorithm(B_INFO_TYPE bAlgType, const void *info = NULL); | |
117 | ||
118 | // safely create bsKey | |
119 | void createBsKey(); | |
120 | ||
121 | // set bsKey. The different versions are equivalent | |
122 | void setKeyAtom(B_INFO_TYPE bKeyInfo, const void *info); | |
123 | void setKeyFromItem(B_INFO_TYPE bKeyInfo, const BSafeItem &item) | |
124 | { setKeyAtom(bKeyInfo, &item); } | |
125 | void setKeyFromCssmKey(B_INFO_TYPE bKeyInfo, const CssmKey &key) | |
126 | { BSafeItem item(key.KeyData); setKeyAtom(bKeyInfo, &item); } | |
127 | void setKeyFromCssmData(B_INFO_TYPE bKeyInfo, const CssmData &keyData) | |
128 | { BSafeItem item(keyData); setKeyAtom(bKeyInfo, &item); } | |
129 | void setKeyFromContext(const Context &context, bool required = true); | |
130 | ||
131 | void setRefKey(CssmKey &key); | |
132 | void setRsaOutSize(bool isPubKey); | |
133 | ||
134 | // create mRandom to be a suitable random-generator BSafe object (if it isn't yet) | |
135 | void setRandom(); | |
136 | ||
137 | // trackUpdate is called during crypto-output. Hook it to keep track of data flow | |
138 | virtual void trackUpdate(size_t in, size_t out); | |
139 | ||
140 | // destroy bsAlgorithm and bsKey so we can start over making them | |
141 | void reset(); | |
142 | ||
143 | // clear key state | |
144 | void destroyBsKey(); | |
145 | ||
146 | // determine if we can reuse the current bsAlgorithm | |
147 | bool reusing(bool encode = true) | |
148 | { | |
149 | if (initialized && !opStarted && | |
150 | (encode == encoding)) return true; | |
151 | encoding = encode; | |
152 | return false; | |
153 | } | |
154 | ||
155 | public: | |
156 | // | |
157 | // These pointers-to-member are called by the BSafeContext operations | |
158 | // (update, final). They must be set by a subclasses's init() method. | |
159 | // Not all members are used by all types of operations - check the | |
160 | // source when in doubt. | |
161 | // | |
162 | int (*inUpdate)(B_ALGORITHM_OBJ, POINTER, unsigned int, A_SURRENDER_CTX *); | |
163 | int (*inOutUpdate)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int, | |
164 | POINTER, unsigned int, B_ALGORITHM_OBJ, A_SURRENDER_CTX *); | |
165 | int (*inFinal)(B_ALGORITHM_OBJ, POINTER, unsigned int, A_SURRENDER_CTX *); | |
166 | int (*inFinalR)(B_ALGORITHM_OBJ, POINTER, unsigned int, | |
167 | B_ALGORITHM_OBJ, A_SURRENDER_CTX *); | |
168 | int (*outFinalR)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int, | |
169 | B_ALGORITHM_OBJ, A_SURRENDER_CTX *); | |
170 | int (*outFinal)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int, | |
171 | A_SURRENDER_CTX *); | |
172 | ||
173 | protected: | |
174 | ||
175 | // un-consted bsChooser for BSafe's consumption. BSafe's Bad | |
176 | static B_ALGORITHM_METHOD **chooser() | |
177 | { return const_cast<B_ALGORITHM_METHOD **>(bsChooser); } | |
178 | ||
179 | // a placeholder for a surrender context. Not currently used | |
180 | // @@@ should perhaps test for pthread cancel? --> thread abstraction | |
181 | static A_SURRENDER_CTX * const bsSurrender; | |
182 | ||
183 | protected: | |
184 | B_ALGORITHM_OBJ bsAlgorithm; // BSafe algorithm object or NULL | |
185 | B_ALGORITHM_OBJ bsRandom; // PRNG algorithm | |
186 | bool encoding; // encoding direction | |
187 | bool initialized; // method init() has completed | |
188 | bool opStarted; // method update() has been called | |
189 | // generally means that we can't reuse | |
190 | // the current bsAlgorithm | |
191 | // | |
192 | // We have a binKey only if the caller passed in a reference | |
193 | // key. In that case we avoid deleting bsKey - which is a copy | |
194 | // of binKey.bsKey - because a BinaryKey is persistent | |
195 | // relative to this context. | |
196 | // | |
197 | BSafeBinaryKey *bsBinKey; | |
198 | B_KEY_OBJ bsKey; // BSafe key object or NULL | |
199 | ||
200 | size_t mOutSize; // simple output size, if applicable | |
201 | }; /* BSafeContext */ | |
202 | ||
203 | // contexts for BSafe digest operations | |
204 | class DigestContext : public BSafeContext { | |
205 | public: | |
206 | // do all work in constructor. We have no directions; thus default init() works fine | |
207 | DigestContext( | |
208 | AppleCSPSession &session, | |
209 | const Context &, | |
210 | B_INFO_TYPE bAlgInfo, | |
211 | size_t sz); | |
212 | }; | |
213 | ||
214 | // common context features for BSafe cipher operations (both symmetric and asymmetric) | |
215 | class CipherContext : public BSafeContext { | |
216 | public: | |
217 | CipherContext( | |
218 | AppleCSPSession &session) : | |
219 | BSafeContext(session), | |
220 | pending(0) {} | |
221 | ||
222 | protected: | |
223 | size_t pending; // bytes not eaten still pending (staged only) | |
224 | public: | |
225 | void cipherInit(); // common init code (must be called from init()) | |
226 | }; | |
227 | ||
228 | // contexts for block cipher operations using symmetric algorithms | |
229 | class BlockCipherContext : public CipherContext { | |
230 | size_t blockSize; | |
231 | uint32 cssmAlg; | |
232 | uint32 cssmMode; | |
233 | bool padEnable; | |
234 | public: | |
235 | BlockCipherContext( | |
236 | AppleCSPSession &session, | |
237 | const Context &, | |
238 | size_t sz) : | |
239 | CipherContext(session), | |
240 | blockSize(sz) { } | |
241 | void init(const Context &context, bool encrypting); | |
242 | size_t inputSize(size_t outSize); | |
243 | size_t outputSize(bool final, size_t inSize); | |
244 | void minimumProgress(size_t &in, size_t &out); | |
245 | void trackUpdate(size_t in, size_t out); | |
246 | private: | |
247 | // special case for RC4 | |
248 | void RC4init(const Context &context); | |
249 | }; | |
250 | ||
251 | // context for generating public/private key pairs | |
252 | class BSafeKeyPairGenContext : public BSafeContext, | |
253 | private AppleKeyPairGenContext { | |
254 | public: | |
255 | BSafeKeyPairGenContext( | |
256 | AppleCSPSession &session, | |
257 | const Context &) : | |
258 | BSafeContext(session) {} | |
259 | ||
260 | // generate alg params, not handled by PublicKeyGenerateContext | |
261 | // For DSA only. | |
262 | void generate( | |
263 | const Context &context, | |
264 | uint32 bitSize, | |
265 | CssmData ¶ms, | |
266 | uint32 &attrCount, | |
267 | Context::Attr * &attrs); | |
268 | ||
269 | // this one is specified in CSPFullPluginSession | |
270 | void generate( | |
271 | const Context &context, | |
272 | CssmKey &pubKey, | |
273 | CssmKey &privKey); | |
274 | ||
275 | // this one in AppleKeyPairGenContext | |
276 | void generate( | |
277 | const Context &context, | |
278 | BinaryKey &pubBinKey, | |
279 | BinaryKey &privBinKey, | |
280 | uint32 &keySize); | |
281 | ||
282 | private: | |
283 | void setupAlgorithm( | |
284 | const Context &context, | |
285 | uint32 &keySize); | |
286 | ||
287 | }; /* BSafeKeyPairGenContext */ | |
288 | ||
289 | // public key cipher operations | |
290 | class PublicKeyCipherContext : public CipherContext { | |
291 | public: | |
292 | PublicKeyCipherContext( | |
293 | AppleCSPSession &session, | |
294 | const Context &) : | |
295 | CipherContext(session) { } | |
296 | void init(const Context &context, bool encrypting); | |
297 | size_t inputSize(size_t outSize); // unlimited | |
298 | }; | |
299 | ||
300 | // contexts for BSafe signing/verifying operations | |
301 | class SigningContext : public BSafeContext { | |
302 | B_INFO_TYPE algorithm; | |
303 | public: | |
304 | SigningContext( | |
305 | AppleCSPSession &session, | |
306 | const Context &, | |
307 | B_INFO_TYPE bAlg, | |
308 | size_t sz) : | |
309 | BSafeContext(session), | |
310 | algorithm(bAlg) { mOutSize = sz; } | |
311 | void init(const Context &context, bool signing); | |
312 | }; | |
313 | ||
314 | // contexts for BSafe MAC generation and verification | |
315 | class MacContext : public BSafeContext { | |
316 | B_INFO_TYPE algorithm; | |
317 | public: | |
318 | MacContext( | |
319 | AppleCSPSession &session, | |
320 | const Context &, | |
321 | B_INFO_TYPE bAlg, | |
322 | size_t sz) : | |
323 | BSafeContext(session), | |
324 | algorithm(bAlg) { mOutSize = sz; } | |
325 | void init(const Context &context, bool signing); | |
326 | void final(const CssmData &in); | |
327 | }; | |
328 | ||
329 | // contexts for BSafe's random number generation | |
330 | class RandomContext : public BSafeContext { | |
331 | B_INFO_TYPE algorithm; | |
332 | public: | |
333 | RandomContext( | |
334 | AppleCSPSession &session, | |
335 | const Context &, | |
336 | B_INFO_TYPE alg) : | |
337 | BSafeContext(session), | |
338 | algorithm(alg) { } | |
339 | void init(const Context &context, bool); | |
340 | void final(CssmData &data); | |
341 | }; | |
342 | ||
343 | // symmetric key generation context | |
344 | class SymmetricKeyGenContext : public BSafeContext, | |
345 | private AppleSymmKeyGenContext { | |
346 | public: | |
347 | SymmetricKeyGenContext( | |
348 | AppleCSPSession &session, | |
349 | const Context &ctx, | |
350 | uint32 minSizeInBits, | |
351 | uint32 maxSizeInBits, | |
352 | bool mustBeByteSized) : | |
353 | BSafeContext(session), | |
354 | AppleSymmKeyGenContext( | |
355 | minSizeInBits, | |
356 | maxSizeInBits, | |
357 | mustBeByteSized) { } | |
358 | ||
359 | void generate( | |
360 | const Context &context, | |
361 | CssmKey &symKey, | |
362 | CssmKey &dummyKey); | |
363 | ||
364 | }; | |
365 | ||
366 | public: | |
367 | /* | |
368 | * Stateless, private function to map a CSSM alg and pub/priv state | |
369 | * to B_INFO_TYPE and format. Returns true on success, false on | |
370 | * "I don't understand this algorithm". | |
371 | */ | |
372 | static bool bsafeAlgToInfoType( | |
373 | CSSM_ALGORITHMS alg, | |
374 | bool isPublic, | |
375 | B_INFO_TYPE &infoType, // RETURNED | |
376 | CSSM_KEYBLOB_FORMAT &format); // RETURNED | |
377 | ||
378 | /* check result of a BSafe call and throw on error */ | |
379 | static void check(int status, bool isKeyOp = false); | |
380 | ||
381 | /* moved here from BSafeContext - now works on any key */ | |
382 | template <class KI_Type> | |
383 | static KI_Type *getKey(B_KEY_OBJ bKey, B_INFO_TYPE type) | |
384 | { | |
385 | POINTER p; | |
386 | check(B_GetKeyInfo(&p, bKey, type), true); | |
387 | return reinterpret_cast<KI_Type *>(p); | |
388 | } | |
389 | ||
390 | ||
391 | // | |
392 | // The context generation table - see algmaker.cpp. | |
393 | // | |
394 | public: | |
395 | // Base class for Maker classes | |
396 | class MakerBase { | |
397 | public: | |
398 | virtual ~MakerBase() { } | |
399 | virtual BSafeContext *make( | |
400 | AppleCSPSession &session, | |
401 | const Context &context) const = 0; | |
402 | }; | |
403 | ||
404 | // One entry in Maker table | |
405 | struct MakerTable { | |
406 | CSSM_ALGORITHMS algorithmId; | |
407 | CSSM_CONTEXT_TYPE algClass; | |
408 | const MakerBase *maker; | |
409 | ~MakerTable() { delete maker; } | |
410 | }; | |
411 | ||
412 | private: | |
413 | static bug_const MakerTable algorithms[]; | |
414 | static const unsigned int algorithmCount; | |
415 | ||
416 | /* | |
417 | * CSPKeyInfoProvider for BSafe keys | |
418 | */ | |
419 | class BSafeKeyInfoProvider : public CSPKeyInfoProvider | |
420 | { | |
421 | private: | |
422 | BSafeKeyInfoProvider( | |
423 | const CssmKey &cssmKey, | |
424 | AppleCSPSession &session); | |
425 | public: | |
426 | static CSPKeyInfoProvider *provider( | |
427 | const CssmKey &cssmKey, | |
428 | AppleCSPSession &session); | |
429 | ~BSafeKeyInfoProvider() { } | |
430 | void CssmKeyToBinary( | |
431 | CssmKey *paramKey, // optional | |
432 | CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT | |
433 | BinaryKey **binKey); // RETURNED | |
434 | void QueryKeySizeInBits( | |
435 | CSSM_KEY_SIZE &keySize); // RETURNED | |
436 | }; | |
437 | ||
438 | }; /* BSAFE namespace */ | |
439 | ||
440 | /* | |
441 | * BSAFE Key Info types. | |
442 | */ | |
443 | #define BLOB_IS_PUB_KEY_INFO 0 | |
444 | ||
445 | #if BLOB_IS_PUB_KEY_INFO | |
446 | ||
447 | /* X beta values */ | |
448 | #define RSA_PUB_KEYINFO_TYPE KI_RSAPublicBER | |
449 | #define RSA_PRIV_KEYINFO_TYPE KI_PKCS_RSAPrivateBER | |
450 | #define DSA_PUB_KEYINFO_TYPE KI_DSAPublicBER | |
451 | #define DSA_PRIV_KEYINFO_TYPE KI_DSAPrivateBER | |
452 | ||
453 | #else /* BLOB_IS_PUB_KEY_INFO */ | |
454 | ||
455 | #define RSA_PUB_KEYINFO_TYPE KI_RSAPublic | |
456 | #define RSA_PRIV_KEYINFO_TYPE KI_PKCS_RSAPrivateBER | |
457 | #define DSA_PUB_KEYINFO_TYPE KI_DSAPublicBER | |
458 | #define DSA_PRIV_KEYINFO_TYPE KI_DSAPrivateBER | |
459 | ||
460 | #endif | |
461 | ||
462 | #endif //_H_BSAFECSP | |
463 | #endif /* BSAFE_CSP_ENABLE */ |