]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_apple_csp/lib/bsafecspi.h
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_apple_csp / lib / bsafecspi.h
diff --git a/Security/libsecurity_apple_csp/lib/bsafecspi.h b/Security/libsecurity_apple_csp/lib/bsafecspi.h
new file mode 100644 (file)
index 0000000..f5d6d4f
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved.
+ * 
+ * The contents of this file constitute Original Code as defined in and are
+ * subject to the Apple Public Source License Version 1.2 (the 'License').
+ * You may not use this file except in compliance with the License. Please obtain
+ * a copy of the License at http://www.apple.com/publicsource and read it before
+ * using this file.
+ * 
+ * This Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
+ * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
+ * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
+ * specific language governing rights and limitations under the License.
+ */
+
+#ifdef BSAFE_CSP_ENABLE
+
+
+//
+// bsafecspi - implementation layer for C++ BSafe 4 interface
+//
+#ifndef _H_BSAFECSPI
+#define _H_BSAFECSPI
+
+#include <security_cdsa_plugin/CSPsession.h>
+#include "bsobjects.h"
+#include "AppleCSPContext.h"
+#include "AppleCSPSession.h"
+#include <aglobal.h>
+#include <bsafe.h>
+
+//
+// The BSafe class is more of a namespace than anything else.
+// Just think of it as the "static binder" for BSafe's objects.
+// Note that we keep a global, static allocator. We have to; BSafe
+// doesn't have any state management at that level.
+//
+class BSafe {
+    class BSafeContext; friend class BSafeContext;
+       class BSafeFactory; friend class BSafeFactory;
+
+public:
+    static void setNormAllocator(Allocator *alloc)
+    { assert(!normAllocator); normAllocator = alloc; }
+    static void setPrivAllocator(Allocator *alloc)
+    { assert(!privAllocator); privAllocator = alloc; }
+       
+       static bool setup(
+               AppleCSPSession &session,
+               CSPFullPluginSession::CSPContext * &cspCtx, 
+               const Context &context);
+
+private:
+    // BSafe's memory allocators
+    static Allocator *normAllocator;
+    static Allocator *privAllocator;
+    friend POINTER T_malloc(unsigned int);
+    friend void T_free(POINTER);
+    friend POINTER T_realloc(POINTER, unsigned int);
+    
+    static const B_ALGORITHM_METHOD * const bsChooser[];
+
+private:
+       // BSafe-specific BinaryKey class.
+       class BSafeBinaryKey : public BinaryKey {
+       
+       public:
+               BSafeBinaryKey(
+                       bool                    isPub,
+                       uint32                  alg);   // CSSM_ALGID_{RSA,DSA}
+               ~BSafeBinaryKey();
+               void generateKeyBlob(
+                       Allocator               &allocator,
+                       CssmData                        &blob,
+                       CSSM_KEYBLOB_FORMAT     &format,
+                       AppleCSPSession         &session,
+                       const CssmKey           *paramKey,              /* optional, unused here */
+                       CSSM_KEYATTR_FLAGS      &attrFlags);    /* IN/OUT */
+                       
+               bool                    isPublic()      { return mIsPublic; }
+               uint32                  alg()           { return mAlg; }
+               B_KEY_OBJ               bsKey()         { return mBsKey; }
+               
+       private:
+               bool                    mIsPublic;
+               uint32                  mAlg;           // CSSM_ALGID_{RSA,DSA}
+               B_KEY_OBJ               mBsKey;
+       };
+       
+private:
+       //
+       // The BSafeContext class is the parent of all BSafe-used CSPContext objects.
+       // It implements the CSPContext operation functions (init, update, ...) in terms
+       // of pointer-to-member fields set by its subclasses. This may not be pretty, but
+       // it avoids every subclass having to re-implement all CSPContext operations.
+       // Beyond that, we implement a raftload of utility methods for our children.
+       //
+    class BSafeContext : public AppleCSPContext {
+        friend class BSafe;
+    public:
+        BSafeContext(AppleCSPSession &session);
+        virtual ~BSafeContext();
+        
+               // called by CSPFullPluginSession
+        void init(const Context &context, bool encoding = true);
+        void update(const CssmData &data);
+        void update(void *inp, size_t &inSize, void *outp, size_t &outSize);
+        void final(CssmData &out);
+        void final(const CssmData &in);
+        size_t outputSize(bool final, size_t inSize);
+
+    protected:
+               // install a BSafe algorithm into bsAlgorithm
+        void setAlgorithm(B_INFO_TYPE bAlgType, const void *info = NULL);
+               
+               // safely create bsKey 
+               void createBsKey();
+               
+               // set bsKey. The different versions are equivalent
+        void setKeyAtom(B_INFO_TYPE bKeyInfo, const void *info);
+        void setKeyFromItem(B_INFO_TYPE bKeyInfo, const BSafeItem &item)
+                       { setKeyAtom(bKeyInfo, &item); }
+        void setKeyFromCssmKey(B_INFO_TYPE bKeyInfo, const CssmKey &key)
+                       { BSafeItem item(key.KeyData); setKeyAtom(bKeyInfo, &item); }
+        void setKeyFromCssmData(B_INFO_TYPE bKeyInfo, const CssmData &keyData)
+                       { BSafeItem item(keyData); setKeyAtom(bKeyInfo, &item); }
+        void setKeyFromContext(const Context &context, bool required = true);
+       
+               void setRefKey(CssmKey &key);
+               void setRsaOutSize(bool isPubKey);
+               
+               // create mRandom to be a suitable random-generator BSafe object (if it isn't yet)
+        void setRandom();
+
+               // trackUpdate is called during crypto-output. Hook it to keep track of data flow
+        virtual void trackUpdate(size_t in, size_t out);
+
+               // destroy bsAlgorithm and bsKey so we can start over making them
+        void reset();
+
+               // clear key state
+               void destroyBsKey();
+               
+               // determine if we can reuse the current bsAlgorithm
+        bool reusing(bool encode = true)
+        {
+            if (initialized && !opStarted && 
+                               (encode == encoding)) return true;
+            encoding = encode;
+            return false;
+        }
+
+    public:
+               //
+               // These pointers-to-member are called by the BSafeContext operations
+               // (update, final). They must be set by a subclasses's init() method.
+               // Not all members are used by all types of operations - check the 
+               // source when in doubt.
+               //
+        int (*inUpdate)(B_ALGORITHM_OBJ, POINTER, unsigned int, A_SURRENDER_CTX *);
+        int (*inOutUpdate)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int,
+                            POINTER, unsigned int, B_ALGORITHM_OBJ, A_SURRENDER_CTX *);
+        int (*inFinal)(B_ALGORITHM_OBJ, POINTER, unsigned int, A_SURRENDER_CTX *);
+        int (*inFinalR)(B_ALGORITHM_OBJ, POINTER, unsigned int,
+                        B_ALGORITHM_OBJ, A_SURRENDER_CTX *);
+        int (*outFinalR)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int,
+                        B_ALGORITHM_OBJ, A_SURRENDER_CTX *);
+        int (*outFinal)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int,
+                        A_SURRENDER_CTX *);
+        
+    protected:
+
+        // un-consted bsChooser for BSafe's consumption. BSafe's Bad
+        static B_ALGORITHM_METHOD **chooser()
+        { return const_cast<B_ALGORITHM_METHOD **>(bsChooser); }
+
+               // a placeholder for a surrender context. Not currently used
+               // @@@ should perhaps test for pthread cancel? --> thread abstraction
+        static A_SURRENDER_CTX * const bsSurrender;
+
+    protected:
+        B_ALGORITHM_OBJ bsAlgorithm; // BSafe algorithm object or NULL
+        B_ALGORITHM_OBJ bsRandom;      // PRNG algorithm
+        bool encoding;                         // encoding direction
+        bool initialized;                      // method init() has completed
+               bool opStarted;                         // method update() has been called
+                                                                       // generally means that we can't reuse
+                                                                       // the current bsAlgorithm
+               //
+               // We have a binKey only if the caller passed in a reference 
+               // key. In that case we avoid deleting bsKey - which is a copy
+               // of binKey.bsKey - because a BinaryKey is persistent
+               // relative to this context. 
+               //
+               BSafeBinaryKey  *bsBinKey;
+        B_KEY_OBJ              bsKey;          // BSafe key object or NULL
+        
+        size_t                         mOutSize;       // simple output size, if applicable
+    }; /* BSafeContext */
+
+       // contexts for BSafe digest operations
+    class DigestContext : public BSafeContext {
+    public:
+               // do all work in constructor. We have no directions; thus default init() works fine
+        DigestContext(
+                       AppleCSPSession &session,
+                       const Context &, 
+                       B_INFO_TYPE bAlgInfo, 
+                       size_t sz);
+    };
+
+       // common context features for BSafe cipher operations (both symmetric and asymmetric)
+    class CipherContext : public BSafeContext {
+       public:
+               CipherContext(
+                       AppleCSPSession &session) :
+                               BSafeContext(session), 
+                               pending(0) {}
+                       
+       protected:
+        size_t pending;                                // bytes not eaten still pending (staged only)
+    public:
+        void cipherInit();                     // common init code (must be called from init())
+    };            
+
+       // contexts for block cipher operations using symmetric algorithms
+    class BlockCipherContext : public CipherContext {
+        size_t blockSize;
+               uint32 cssmAlg;
+               uint32 cssmMode;
+               bool padEnable;
+    public:
+        BlockCipherContext(
+                       AppleCSPSession &session,
+                       const Context &, 
+                       size_t sz) :
+                               CipherContext(session),
+                               blockSize(sz) { }
+        void init(const Context &context, bool encrypting);
+        size_t inputSize(size_t outSize);
+        size_t outputSize(bool final, size_t inSize);
+        void minimumProgress(size_t &in, size_t &out);
+        void trackUpdate(size_t in, size_t out);
+       private:
+               // special case for RC4
+               void RC4init(const Context &context);
+    };
+
+       // context for generating public/private key pairs
+    class BSafeKeyPairGenContext : public BSafeContext,
+                                        private AppleKeyPairGenContext  {
+       public:
+               BSafeKeyPairGenContext(
+                       AppleCSPSession &session,
+                       const Context &) :
+                               BSafeContext(session) {}
+
+               // generate alg params, not handled by PublicKeyGenerateContext
+               // For DSA only. 
+        void generate(
+                       const Context                   &context, 
+                       uint32                                  bitSize, 
+                       CssmData                                &params,
+                       uint32                                  &attrCount, 
+                       Context::Attr *                 &attrs);
+                       
+               // this one is specified in CSPFullPluginSession
+               void generate(
+                       const Context   &context, 
+                       CssmKey                 &pubKey, 
+                       CssmKey                 &privKey);
+                       
+               // this one in AppleKeyPairGenContext
+               void generate(
+                       const Context   &context,
+                       BinaryKey               &pubBinKey,     
+                       BinaryKey               &privBinKey,
+                       uint32                  &keySize);
+       
+       private:
+               void setupAlgorithm(
+                       const Context   &context,
+                       uint32                  &keySize);
+                       
+    }; /* BSafeKeyPairGenContext */
+
+       // public key cipher operations
+    class PublicKeyCipherContext : public CipherContext {
+    public:
+               PublicKeyCipherContext(
+                       AppleCSPSession &session,
+                       const Context &) :
+                               CipherContext(session) { }
+        void init(const Context &context, bool encrypting);
+        size_t inputSize(size_t outSize);      // unlimited
+    };
+
+       // contexts for BSafe signing/verifying operations
+    class SigningContext : public BSafeContext {
+        B_INFO_TYPE algorithm;
+    public:
+        SigningContext(
+                       AppleCSPSession &session,
+                       const Context &,
+                       B_INFO_TYPE bAlg, 
+                       size_t sz) : 
+                               BSafeContext(session),
+                               algorithm(bAlg) { mOutSize = sz; }
+        void init(const Context &context, bool signing);
+    };
+
+       // contexts for BSafe MAC generation and verification
+    class MacContext : public BSafeContext {
+        B_INFO_TYPE algorithm;
+    public:
+        MacContext(
+                       AppleCSPSession &session,
+                       const Context &,
+            B_INFO_TYPE bAlg, 
+                       size_t sz) : 
+                               BSafeContext(session),
+                               algorithm(bAlg) { mOutSize = sz; }
+        void init(const Context &context, bool signing);
+        void final(const CssmData &in);
+    };
+       
+       // contexts for BSafe's random number generation
+       class RandomContext : public BSafeContext {
+               B_INFO_TYPE algorithm;
+       public:
+               RandomContext(
+                       AppleCSPSession &session,
+                       const Context &, 
+                       B_INFO_TYPE alg) :
+                               BSafeContext(session),
+                               algorithm(alg) { }
+               void init(const Context &context, bool);
+               void final(CssmData &data);
+       };
+
+       // symmetric key generation context
+       class SymmetricKeyGenContext : public BSafeContext,
+               private AppleSymmKeyGenContext {
+    public:
+               SymmetricKeyGenContext(
+                       AppleCSPSession &session,
+                       const Context   &ctx,
+                       uint32                  minSizeInBits,
+                       uint32                  maxSizeInBits,
+                       bool                    mustBeByteSized) :
+                               BSafeContext(session),
+                               AppleSymmKeyGenContext(
+                                       minSizeInBits,
+                                       maxSizeInBits,
+                                       mustBeByteSized) { }
+                                       
+               void generate(
+                       const Context   &context, 
+                       CssmKey                 &symKey, 
+                       CssmKey                 &dummyKey);
+
+    };
+
+public:
+       /*
+        * Stateless, private function to map a CSSM alg and pub/priv state
+        * to B_INFO_TYPE and format. Returns true on success, false on
+        * "I don't understand this algorithm". 
+        */
+       static bool bsafeAlgToInfoType(
+               CSSM_ALGORITHMS         alg,
+               bool                            isPublic,
+               B_INFO_TYPE                     &infoType,      // RETURNED
+               CSSM_KEYBLOB_FORMAT     &format);       // RETURNED
+
+       /* check result of a BSafe call and throw on error */
+       static void check(int status, bool isKeyOp = false);
+               
+       /* moved here from BSafeContext - now works on any key */
+       template <class KI_Type>
+       static KI_Type *getKey(B_KEY_OBJ bKey, B_INFO_TYPE type)
+       { 
+               POINTER p; 
+               check(B_GetKeyInfo(&p, bKey, type), true); 
+               return reinterpret_cast<KI_Type *>(p); 
+       }
+
+
+    //
+    // The context generation table - see algmaker.cpp.
+    //
+public:
+       // Base class for Maker classes
+       class MakerBase {
+       public:
+               virtual ~MakerBase() { }
+               virtual BSafeContext *make(
+                       AppleCSPSession &session,
+                       const Context &context) const = 0;
+       };
+
+       // One entry in Maker table
+       struct MakerTable {
+               CSSM_ALGORITHMS         algorithmId;
+               CSSM_CONTEXT_TYPE       algClass;
+               const MakerBase         *maker;
+               ~MakerTable() { delete maker; }
+       };
+       
+private:
+       static bug_const MakerTable algorithms[];
+       static const unsigned int algorithmCount;
+       
+       /*
+        * CSPKeyInfoProvider for BSafe keys
+        */
+       class BSafeKeyInfoProvider : public CSPKeyInfoProvider 
+       {
+private:
+               BSafeKeyInfoProvider(
+                       const CssmKey           &cssmKey,
+                       AppleCSPSession         &session);
+       public:
+               static CSPKeyInfoProvider *provider(
+               const CssmKey                   &cssmKey,
+               AppleCSPSession                 &session);
+               ~BSafeKeyInfoProvider() { }
+               void CssmKeyToBinary(
+                       CssmKey                         *paramKey,      // optional
+                       CSSM_KEYATTR_FLAGS      &attrFlags,     // IN/OUT
+                       BinaryKey                       **binKey);      // RETURNED
+               void QueryKeySizeInBits(
+                       CSSM_KEY_SIZE           &keySize);      // RETURNED
+       };
+
+}; /* BSAFE namespace */
+
+/*
+ * BSAFE Key Info types.
+ */
+#define BLOB_IS_PUB_KEY_INFO   0
+
+#if            BLOB_IS_PUB_KEY_INFO
+
+/* X beta values */
+#define RSA_PUB_KEYINFO_TYPE           KI_RSAPublicBER
+#define RSA_PRIV_KEYINFO_TYPE          KI_PKCS_RSAPrivateBER
+#define DSA_PUB_KEYINFO_TYPE           KI_DSAPublicBER
+#define DSA_PRIV_KEYINFO_TYPE          KI_DSAPrivateBER
+
+#else  /* BLOB_IS_PUB_KEY_INFO */
+
+#define RSA_PUB_KEYINFO_TYPE           KI_RSAPublic
+#define RSA_PRIV_KEYINFO_TYPE          KI_PKCS_RSAPrivateBER
+#define DSA_PUB_KEYINFO_TYPE           KI_DSAPublicBER
+#define DSA_PRIV_KEYINFO_TYPE          KI_DSAPrivateBER
+
+#endif
+
+#endif //_H_BSAFECSP
+#endif /* BSAFE_CSP_ENABLE */