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
);
79 bool isPublic() { return mIsPublic
; }
80 uint32
alg() { return mAlg
; }
81 B_KEY_OBJ
bsKey() { return mBsKey
; }
85 uint32 mAlg
; // CSSM_ALGID_{RSA,DSA}
91 // The BSafeContext class is the parent of all BSafe-used CSPContext objects.
92 // It implements the CSPContext operation functions (init, update, ...) in terms
93 // of pointer-to-member fields set by its subclasses. This may not be pretty, but
94 // it avoids every subclass having to re-implement all CSPContext operations.
95 // Beyond that, we implement a raftload of utility methods for our children.
97 class BSafeContext
: public AppleCSPContext
{
100 BSafeContext(AppleCSPSession
&session
);
101 virtual ~BSafeContext();
103 // called by CSPFullPluginSession
104 void init(const Context
&context
, bool encoding
= true);
105 void update(const CssmData
&data
);
106 void update(void *inp
, size_t &inSize
, void *outp
, size_t &outSize
);
107 void final(CssmData
&out
);
108 void final(const CssmData
&in
);
109 size_t outputSize(bool final
, size_t inSize
);
112 // install a BSafe algorithm into bsAlgorithm
113 void setAlgorithm(B_INFO_TYPE bAlgType
, const void *info
= NULL
);
115 // safely create bsKey
118 // set bsKey. The different versions are equivalent
119 void setKeyAtom(B_INFO_TYPE bKeyInfo
, const void *info
);
120 void setKeyFromItem(B_INFO_TYPE bKeyInfo
, const BSafeItem
&item
)
121 { setKeyAtom(bKeyInfo
, &item
); }
122 void setKeyFromCssmKey(B_INFO_TYPE bKeyInfo
, const CssmKey
&key
)
123 { BSafeItem
item(key
.KeyData
); setKeyAtom(bKeyInfo
, &item
); }
124 void setKeyFromCssmData(B_INFO_TYPE bKeyInfo
, const CssmData
&keyData
)
125 { BSafeItem
item(keyData
); setKeyAtom(bKeyInfo
, &item
); }
126 void setKeyFromContext(const Context
&context
, bool required
= true);
128 void setRefKey(CssmKey
&key
);
129 void setRsaOutSize(bool isPubKey
);
131 // create mRandom to be a suitable random-generator BSafe object (if it isn't yet)
134 // trackUpdate is called during crypto-output. Hook it to keep track of data flow
135 virtual void trackUpdate(size_t in
, size_t out
);
137 // destroy bsAlgorithm and bsKey so we can start over making them
143 // determine if we can reuse the current bsAlgorithm
144 bool reusing(bool encode
= true)
146 if (initialized
&& !opStarted
&&
147 (encode
== encoding
)) return true;
154 // These pointers-to-member are called by the BSafeContext operations
155 // (update, final). They must be set by a subclasses's init() method.
156 // Not all members are used by all types of operations - check the
157 // source when in doubt.
159 int (*inUpdate
)(B_ALGORITHM_OBJ
, POINTER
, unsigned int, A_SURRENDER_CTX
*);
160 int (*inOutUpdate
)(B_ALGORITHM_OBJ
, POINTER
, unsigned int *, unsigned int,
161 POINTER
, unsigned int, B_ALGORITHM_OBJ
, A_SURRENDER_CTX
*);
162 int (*inFinal
)(B_ALGORITHM_OBJ
, POINTER
, unsigned int, A_SURRENDER_CTX
*);
163 int (*inFinalR
)(B_ALGORITHM_OBJ
, POINTER
, unsigned int,
164 B_ALGORITHM_OBJ
, A_SURRENDER_CTX
*);
165 int (*outFinalR
)(B_ALGORITHM_OBJ
, POINTER
, unsigned int *, unsigned int,
166 B_ALGORITHM_OBJ
, A_SURRENDER_CTX
*);
167 int (*outFinal
)(B_ALGORITHM_OBJ
, POINTER
, unsigned int *, unsigned int,
172 // un-consted bsChooser for BSafe's consumption. BSafe's Bad
173 static B_ALGORITHM_METHOD
**chooser()
174 { return const_cast<B_ALGORITHM_METHOD
**>(bsChooser
); }
176 // a placeholder for a surrender context. Not currently used
177 // @@@ should perhaps test for pthread cancel? --> thread abstraction
178 static A_SURRENDER_CTX
* const bsSurrender
;
181 B_ALGORITHM_OBJ bsAlgorithm
; // BSafe algorithm object or NULL
182 B_ALGORITHM_OBJ bsRandom
; // PRNG algorithm
183 bool encoding
; // encoding direction
184 bool initialized
; // method init() has completed
185 bool opStarted
; // method update() has been called
186 // generally means that we can't reuse
187 // the current bsAlgorithm
189 // We have a binKey only if the caller passed in a reference
190 // key. In that case we avoid deleting bsKey - which is a copy
191 // of binKey.bsKey - because a BinaryKey is persistent
192 // relative to this context.
194 BSafeBinaryKey
*bsBinKey
;
195 B_KEY_OBJ bsKey
; // BSafe key object or NULL
197 size_t mOutSize
; // simple output size, if applicable
198 }; /* BSafeContext */
200 // contexts for BSafe digest operations
201 class DigestContext
: public BSafeContext
{
203 // do all work in constructor. We have no directions; thus default init() works fine
205 AppleCSPSession
&session
,
207 B_INFO_TYPE bAlgInfo
,
211 // common context features for BSafe cipher operations (both symmetric and asymmetric)
212 class CipherContext
: public BSafeContext
{
215 AppleCSPSession
&session
) :
216 BSafeContext(session
),
220 size_t pending
; // bytes not eaten still pending (staged only)
222 void cipherInit(); // common init code (must be called from init())
225 // contexts for block cipher operations using symmetric algorithms
226 class BlockCipherContext
: public CipherContext
{
233 AppleCSPSession
&session
,
236 CipherContext(session
),
238 void init(const Context
&context
, bool encrypting
);
239 size_t inputSize(size_t outSize
);
240 size_t outputSize(bool final
, size_t inSize
);
241 void minimumProgress(size_t &in
, size_t &out
);
242 void trackUpdate(size_t in
, size_t out
);
244 // special case for RC4
245 void RC4init(const Context
&context
);
248 // context for generating public/private key pairs
249 class BSafeKeyPairGenContext
: public BSafeContext
,
250 private AppleKeyPairGenContext
{
252 BSafeKeyPairGenContext(
253 AppleCSPSession
&session
,
255 BSafeContext(session
) {}
257 // generate alg params, not handled by PublicKeyGenerateContext
260 const Context
&context
,
264 Context::Attr
* &attrs
);
266 // this one is specified in CSPFullPluginSession
268 const Context
&context
,
272 // this one in AppleKeyPairGenContext
274 const Context
&context
,
275 BinaryKey
&pubBinKey
,
276 BinaryKey
&privBinKey
,
281 const Context
&context
,
284 }; /* BSafeKeyPairGenContext */
286 // public key cipher operations
287 class PublicKeyCipherContext
: public CipherContext
{
289 PublicKeyCipherContext(
290 AppleCSPSession
&session
,
292 CipherContext(session
) { }
293 void init(const Context
&context
, bool encrypting
);
294 size_t inputSize(size_t outSize
); // unlimited
297 // contexts for BSafe signing/verifying operations
298 class SigningContext
: public BSafeContext
{
299 B_INFO_TYPE algorithm
;
302 AppleCSPSession
&session
,
306 BSafeContext(session
),
307 algorithm(bAlg
) { mOutSize
= sz
; }
308 void init(const Context
&context
, bool signing
);
311 // contexts for BSafe MAC generation and verification
312 class MacContext
: public BSafeContext
{
313 B_INFO_TYPE algorithm
;
316 AppleCSPSession
&session
,
320 BSafeContext(session
),
321 algorithm(bAlg
) { mOutSize
= sz
; }
322 void init(const Context
&context
, bool signing
);
323 void final(const CssmData
&in
);
326 // contexts for BSafe's random number generation
327 class RandomContext
: public BSafeContext
{
328 B_INFO_TYPE algorithm
;
331 AppleCSPSession
&session
,
334 BSafeContext(session
),
336 void init(const Context
&context
, bool);
337 void final(CssmData
&data
);
340 // symmetric key generation context
341 class SymmetricKeyGenContext
: public BSafeContext
,
342 private AppleSymmKeyGenContext
{
344 SymmetricKeyGenContext(
345 AppleCSPSession
&session
,
347 uint32 minSizeInBits
,
348 uint32 maxSizeInBits
,
349 bool mustBeByteSized
) :
350 BSafeContext(session
),
351 AppleSymmKeyGenContext(
357 const Context
&context
,
365 * Stateless, private function to map a CSSM alg and pub/priv state
366 * to B_INFO_TYPE and format. Returns true on success, false on
367 * "I don't understand this algorithm".
369 static bool bsafeAlgToInfoType(
372 B_INFO_TYPE
&infoType
, // RETURNED
373 CSSM_KEYBLOB_FORMAT
&format
); // RETURNED
375 /* check result of a BSafe call and throw on error */
376 static void check(int status
, bool isKeyOp
= false);
378 /* moved here from BSafeContext - now works on any key */
379 template <class KI_Type
>
380 static KI_Type
*getKey(B_KEY_OBJ bKey
, B_INFO_TYPE type
)
383 check(B_GetKeyInfo(&p
, bKey
, type
), true);
384 return reinterpret_cast<KI_Type
*>(p
);
389 // The context generation table - see algmaker.cpp.
392 // Base class for Maker classes
395 virtual ~MakerBase() { }
396 virtual BSafeContext
*make(
397 AppleCSPSession
&session
,
398 const Context
&context
) const = 0;
401 // One entry in Maker table
403 CSSM_ALGORITHMS algorithmId
;
404 CSSM_CONTEXT_TYPE algClass
;
405 const MakerBase
*maker
;
406 ~MakerTable() { delete maker
; }
410 static bug_const MakerTable algorithms
[];
411 static const unsigned int algorithmCount
;
414 * CSPKeyInfoProvider for BSafe keys
416 class BSafeKeyInfoProvider
: public CSPKeyInfoProvider
419 BSafeKeyInfoProvider(
420 const CssmKey
&cssmKey
);
422 static CSPKeyInfoProvider
*provider(
423 const CssmKey
&cssmKey
);
424 ~BSafeKeyInfoProvider() { }
425 void CssmKeyToBinary(
426 BinaryKey
**binKey
); // RETURNED
427 void QueryKeySizeInBits(
428 CSSM_KEY_SIZE
&keySize
); // RETURNED
431 }; /* BSAFE namespace */
434 * BSAFE Key Info types.
436 #define BLOB_IS_PUB_KEY_INFO 0
438 #if BLOB_IS_PUB_KEY_INFO
441 #define RSA_PUB_KEYINFO_TYPE KI_RSAPublicBER
442 #define RSA_PRIV_KEYINFO_TYPE KI_PKCS_RSAPrivateBER
443 #define DSA_PUB_KEYINFO_TYPE KI_DSAPublicBER
444 #define DSA_PRIV_KEYINFO_TYPE KI_DSAPrivateBER
446 #else /* BLOB_IS_PUB_KEY_INFO */
448 #define RSA_PUB_KEYINFO_TYPE KI_RSAPublic
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
456 #endif /* BSAFE_CSP_ENABLE */