2 * Copyright (c) 2000-2001 Apple Computer, 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.
18 #ifdef BSAFE_CSP_ENABLE
22 // bsafecspi - implementation layer for C++ BSafe 4 interface
27 #include <Security/CSPsession.h>
28 #include "bsobjects.h"
29 #include "AppleCSPContext.h"
30 #include "AppleCSPSession.h"
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.
41 class BSafeContext
; friend class BSafeContext
;
42 class BSafeFactory
; friend class BSafeFactory
;
45 static void setNormAllocator(CssmAllocator
*alloc
)
46 { assert(!normAllocator
); normAllocator
= alloc
; }
47 static void setPrivAllocator(CssmAllocator
*alloc
)
48 { assert(!privAllocator
); privAllocator
= alloc
; }
51 AppleCSPSession
&session
,
52 CSPFullPluginSession::CSPContext
* &cspCtx
,
53 const Context
&context
);
56 // BSafe's memory allocators
57 static CssmAllocator
*normAllocator
;
58 static CssmAllocator
*privAllocator
;
59 friend POINTER
T_malloc(unsigned int);
60 friend void T_free(POINTER
);
61 friend POINTER
T_realloc(POINTER
, unsigned int);
63 static const B_ALGORITHM_METHOD
* const bsChooser
[];
66 // BSafe-specific BinaryKey class.
67 class BSafeBinaryKey
: public BinaryKey
{
72 uint32 alg
); // CSSM_ALGID_{RSA,DSA}
75 CssmAllocator
&allocator
,
77 CSSM_KEYBLOB_FORMAT
&format
,
78 AppleCSPSession
&session
,
79 const CssmKey
*paramKey
, /* optional, unused here */
80 CSSM_KEYATTR_FLAGS
&attrFlags
); /* IN/OUT */
82 bool isPublic() { return mIsPublic
; }
83 uint32
alg() { return mAlg
; }
84 B_KEY_OBJ
bsKey() { return mBsKey
; }
88 uint32 mAlg
; // CSSM_ALGID_{RSA,DSA}
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.
100 class BSafeContext
: public AppleCSPContext
{
103 BSafeContext(AppleCSPSession
&session
);
104 virtual ~BSafeContext();
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
);
115 // install a BSafe algorithm into bsAlgorithm
116 void setAlgorithm(B_INFO_TYPE bAlgType
, const void *info
= NULL
);
118 // safely create bsKey
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);
131 void setRefKey(CssmKey
&key
);
132 void setRsaOutSize(bool isPubKey
);
134 // create mRandom to be a suitable random-generator BSafe object (if it isn't yet)
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
);
140 // destroy bsAlgorithm and bsKey so we can start over making them
146 // determine if we can reuse the current bsAlgorithm
147 bool reusing(bool encode
= true)
149 if (initialized
&& !opStarted
&&
150 (encode
== encoding
)) return true;
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.
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,
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
); }
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
;
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
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.
197 BSafeBinaryKey
*bsBinKey
;
198 B_KEY_OBJ bsKey
; // BSafe key object or NULL
200 size_t mOutSize
; // simple output size, if applicable
201 }; /* BSafeContext */
203 // contexts for BSafe digest operations
204 class DigestContext
: public BSafeContext
{
206 // do all work in constructor. We have no directions; thus default init() works fine
208 AppleCSPSession
&session
,
210 B_INFO_TYPE bAlgInfo
,
214 // common context features for BSafe cipher operations (both symmetric and asymmetric)
215 class CipherContext
: public BSafeContext
{
218 AppleCSPSession
&session
) :
219 BSafeContext(session
),
223 size_t pending
; // bytes not eaten still pending (staged only)
225 void cipherInit(); // common init code (must be called from init())
228 // contexts for block cipher operations using symmetric algorithms
229 class BlockCipherContext
: public CipherContext
{
236 AppleCSPSession
&session
,
239 CipherContext(session
),
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
);
247 // special case for RC4
248 void RC4init(const Context
&context
);
251 // context for generating public/private key pairs
252 class BSafeKeyPairGenContext
: public BSafeContext
,
253 private AppleKeyPairGenContext
{
255 BSafeKeyPairGenContext(
256 AppleCSPSession
&session
,
258 BSafeContext(session
) {}
260 // generate alg params, not handled by PublicKeyGenerateContext
263 const Context
&context
,
267 Context::Attr
* &attrs
);
269 // this one is specified in CSPFullPluginSession
271 const Context
&context
,
275 // this one in AppleKeyPairGenContext
277 const Context
&context
,
278 BinaryKey
&pubBinKey
,
279 BinaryKey
&privBinKey
,
284 const Context
&context
,
287 }; /* BSafeKeyPairGenContext */
289 // public key cipher operations
290 class PublicKeyCipherContext
: public CipherContext
{
292 PublicKeyCipherContext(
293 AppleCSPSession
&session
,
295 CipherContext(session
) { }
296 void init(const Context
&context
, bool encrypting
);
297 size_t inputSize(size_t outSize
); // unlimited
300 // contexts for BSafe signing/verifying operations
301 class SigningContext
: public BSafeContext
{
302 B_INFO_TYPE algorithm
;
305 AppleCSPSession
&session
,
309 BSafeContext(session
),
310 algorithm(bAlg
) { mOutSize
= sz
; }
311 void init(const Context
&context
, bool signing
);
314 // contexts for BSafe MAC generation and verification
315 class MacContext
: public BSafeContext
{
316 B_INFO_TYPE algorithm
;
319 AppleCSPSession
&session
,
323 BSafeContext(session
),
324 algorithm(bAlg
) { mOutSize
= sz
; }
325 void init(const Context
&context
, bool signing
);
326 void final(const CssmData
&in
);
329 // contexts for BSafe's random number generation
330 class RandomContext
: public BSafeContext
{
331 B_INFO_TYPE algorithm
;
334 AppleCSPSession
&session
,
337 BSafeContext(session
),
339 void init(const Context
&context
, bool);
340 void final(CssmData
&data
);
343 // symmetric key generation context
344 class SymmetricKeyGenContext
: public BSafeContext
,
345 private AppleSymmKeyGenContext
{
347 SymmetricKeyGenContext(
348 AppleCSPSession
&session
,
350 uint32 minSizeInBits
,
351 uint32 maxSizeInBits
,
352 bool mustBeByteSized
) :
353 BSafeContext(session
),
354 AppleSymmKeyGenContext(
360 const Context
&context
,
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".
372 static bool bsafeAlgToInfoType(
375 B_INFO_TYPE
&infoType
, // RETURNED
376 CSSM_KEYBLOB_FORMAT
&format
); // RETURNED
378 /* check result of a BSafe call and throw on error */
379 static void check(int status
, bool isKeyOp
= false);
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
)
386 check(B_GetKeyInfo(&p
, bKey
, type
), true);
387 return reinterpret_cast<KI_Type
*>(p
);
392 // The context generation table - see algmaker.cpp.
395 // Base class for Maker classes
398 virtual ~MakerBase() { }
399 virtual BSafeContext
*make(
400 AppleCSPSession
&session
,
401 const Context
&context
) const = 0;
404 // One entry in Maker table
406 CSSM_ALGORITHMS algorithmId
;
407 CSSM_CONTEXT_TYPE algClass
;
408 const MakerBase
*maker
;
409 ~MakerTable() { delete maker
; }
413 static bug_const MakerTable algorithms
[];
414 static const unsigned int algorithmCount
;
417 * CSPKeyInfoProvider for BSafe keys
419 class BSafeKeyInfoProvider
: public CSPKeyInfoProvider
422 BSafeKeyInfoProvider(
423 const CssmKey
&cssmKey
,
424 AppleCSPSession
&session
);
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
438 }; /* BSAFE namespace */
441 * BSAFE Key Info types.
443 #define BLOB_IS_PUB_KEY_INFO 0
445 #if BLOB_IS_PUB_KEY_INFO
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
453 #else /* BLOB_IS_PUB_KEY_INFO */
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
463 #endif /* BSAFE_CSP_ENABLE */