1/* 2 * Copyright (c) 2000-2001,2011,2014 Apple 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// 40class BSafe { 41 class BSafeContext; friend class BSafeContext; 42 class BSafeFactory; friend class BSafeFactory; 43 44public: 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 55private: 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 65private: 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 92private: 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 366public: 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 // 394public: 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 412private: 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 { 421private: 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 */ 464