]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / libsecurity_apple_csp / lib / FEEAsymmetricContext.cpp
diff --git a/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp b/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp
deleted file mode 100644 (file)
index 3556c88..0000000
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * Copyright (c) 2000-2001 Apple Computer, 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.
- */
-
-
-/*
- * FEEAsymmetricContext.cpp - CSPContexts for FEE asymmetric encryption
- *
- * Created March 8 2001 by dmitch.
- */
-
-#ifdef CRYPTKIT_CSP_ENABLE
-
-#include "FEEAsymmetricContext.h"
-#include "FEECSPUtils.h"
-#include <security_cryptkit/falloc.h>
-#include <CommonCrypto/CommonDigest.h>
-
-/* validate context for FEED and FEEDExp - no unexpected attributes allowed */
-static void validateFeedContext(
-       const Context &context)
-{
-       /* Note we cannot distinguish between zero and "not there" */
-       uint32 blockSize = context.getInt(CSSM_ATTRIBUTE_BLOCK_SIZE);
-       if(blockSize != 0) {
-               CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_BLOCK_SIZE);
-       }
-       CSSM_ENCRYPT_MODE cssmMode = context.getInt(CSSM_ATTRIBUTE_MODE);
-       if(cssmMode != 0) {
-               CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE);
-       }
-       #if 0
-       /* we allow this for CMS wrapping */
-       CssmData *iv = context.get<CssmData>(CSSM_ATTRIBUTE_INIT_VECTOR);
-       if(iv != NULL) {
-               CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR);
-       }
-       #endif
-       CSSM_PADDING padding = context.getInt(CSSM_ATTRIBUTE_PADDING); 
-       if(padding != 0) {
-               CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING);
-       }
-}
-
-/***
- *** FEED - 1:1 FEED - encrypt n bytes of plaintext, get (roughly) n bytes
- *** of ciphertext. Ciphertext is smaller than with FEED, but this is slower.
- ***/
-CryptKit::FEEDContext::~FEEDContext()
-{
-       if(mFeeFeed) {
-               feeFEEDFree(mFeeFeed);
-               mFeeFeed = NULL;
-       }
-       if(mPrivKey && mAllocdPrivKey) {
-               feePubKeyFree(mPrivKey);
-       }
-       if(mPubKey && mAllocdPubKey) {
-               feePubKeyFree(mPubKey);
-       }
-       mPrivKey = NULL;
-       mPubKey  = NULL;
-       mInitFlag = false;
-}
-
-// called by CSPFullPluginSession; reusable
-void CryptKit::FEEDContext::init(
-       const Context &context, 
-       bool encoding)
-{
-       if(mInitFlag && !opStarted()) {
-               /* reusing - e.g. query followed by encrypt */
-               return;
-       }
-       
-       /* 
-        * Fetch FEE keys from context. This is an unusual algorithm - it requires
-        * two keys, one public and one private. The public key MUST be stored in
-        * the context with attribute type CSSM_ATTRIBUTE_PUBLIC_KEY, and the private 
-        * key with CSSM_ATTRIBUTE_KEY.
-        *
-        * For now, we require CSSM_KEYUSE_ANY for FEE keys used for this algorithm.
-        * Otherwise we'd have to allow both KEYUSE_ENCRYPT and KEYUSE_DECRYPT for
-        * both keys, and that would require some algorithm-specific hack in 
-        * cspValidateKeyUsageBits() which I really don't want to do.
-        */
-       if(mPrivKey == NULL) {
-               assert(!opStarted());
-               mPrivKey = contextToFeeKey(context,
-                       session(),
-                       CSSM_ATTRIBUTE_KEY,
-                       CSSM_KEYCLASS_PRIVATE_KEY,
-                       CSSM_KEYUSE_ANY,
-                       mAllocdPrivKey);
-       }
-       else {
-               assert(opStarted());    
-       }
-       if(mPubKey == NULL) {
-               assert(!opStarted());
-               mPubKey = contextToFeeKey(context,
-                       session(),
-                       CSSM_ATTRIBUTE_PUBLIC_KEY,
-                       CSSM_KEYCLASS_PUBLIC_KEY,
-                       CSSM_KEYUSE_ANY,
-                       mAllocdPubKey);
-       }
-       else {
-               assert(opStarted());    
-       }
-       
-       /* validate context - no other attributes allowed */
-       validateFeedContext(context);
-
-       if(mFeeFeed != NULL) {
-               /* not reusable */
-               assert(opStarted());
-               feeFEEDFree(mFeeFeed);
-               mFeeFeed = NULL;
-       }
-       
-       /* OK, looks good. Cook up a feeFEED object. */
-       mFeeFeed = feeFEEDNewWithPubKey(mPrivKey,
-               mPubKey,
-               encoding ? 1 : 0,
-               feeRandCallback,
-               &session());
-       if(mFeeFeed == NULL) {
-               CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
-       }
-       
-       /* finally, have BlockCryptor set up its stuff. */
-       unsigned plainBlockSize  = feeFEEDPlainBlockSize(mFeeFeed);
-       unsigned cipherBlockSize = feeFEEDCipherBlockSize(mFeeFeed);
-       setup(encoding ? plainBlockSize  : cipherBlockSize, // blockSizeIn
-                 encoding ? cipherBlockSize : plainBlockSize,  // blockSizeOut
-                 false,                                                                                // pkcsPad
-                 true,                                                                                 // needsFinal
-                 BCM_ECB,
-                 NULL);                                                                                // IV
-       mInitFlag = true;
-}
-
-// called by BlockCryptor
-void CryptKit::FEEDContext::encryptBlock(
-       const void              *plainText,                     // length implied (one block)
-       size_t                  plainTextLen,
-       void                    *cipherText,    
-       size_t                  &cipherTextLen,         // in/out, throws on overflow
-       bool                    final)
-{
-       feeReturn frtn;
-       unsigned actMoved;
-       
-       assert(mFeeFeed != NULL);
-       frtn = feeFEEDEncryptBlock(mFeeFeed,
-               (unsigned char *)plainText,
-               (unsigned int)plainTextLen,
-               (unsigned char *)cipherText,
-               &actMoved,
-               final ? 1 : 0);
-       if(frtn) {
-               throwCryptKit(frtn, "feeFEEDEncryptBlock");
-       }
-       if(actMoved > cipherTextLen) {
-               /* Overflow already occurred! */
-               CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
-       }
-       cipherTextLen = actMoved;
-}
-
-void CryptKit::FEEDContext::decryptBlock(
-       const void              *cipherText,            // length implied (one cipher block)
-       size_t                  cipherTextLen,
-       void                    *plainText,     
-       size_t                  &plainTextLen,          // in/out, throws on overflow
-       bool                    final)
-{
-       feeReturn frtn;
-       unsigned actMoved;
-       
-       assert(mFeeFeed != NULL);
-       frtn = feeFEEDDecryptBlock(mFeeFeed,
-               (unsigned char *)cipherText,
-               (unsigned int)inBlockSize(),
-               (unsigned char *)plainText,
-               &actMoved,
-               final ? 1 : 0);
-       if(frtn) {
-               throwCryptKit(frtn, "feeFEEDDecryptBlock");
-       }
-       if(actMoved > plainTextLen) {
-               /* Overflow already occurred! */
-               CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
-       }
-       plainTextLen = actMoved;
-}
-
-/*
- * Additional query size support, necessary because we don't conform to 
- * BlockCryptor's standard one-to-one block scheme
- */
-#define BUFFER_DEBUG   0
-#if            BUFFER_DEBUG
-#define bprintf(s)             printf s
-#else
-#define bprintf(s)
-#endif
-
-size_t CryptKit::FEEDContext::inputSize(
-       size_t                  outSize)                        // input for given output size
-{
-       /*
-        * We've been assured that this is NOT called for the final() op...
-        */
-       unsigned inSize;
-       if(encoding()) {
-               inSize = feeFEEDPlainTextSize(mFeeFeed, (unsigned int)outSize, 0);
-       }
-       else {
-               inSize = feeFEEDCipherTextSize(mFeeFeed, (unsigned int)outSize, 0);
-       }
-       
-       /* account for possible pending buffered input */
-       if(inSize >= inBufSize()) {
-               inSize -= inBufSize();
-       }
-       
-       /* round up to next block size, then lop off one...anything from
-        * blockSize*n to (blockSize*n)-1 has same effect */
-       unsigned inBlocks = (unsigned int)((inSize + inBlockSize()) / inBlockSize());
-       inSize = (unsigned int)(inBlocks * inBlockSize()) - 1;
-       bprintf(("--- FEEDContext::inputSize  inSize 0x%x outSize 0x%x\n",
-               inSize, outSize));
-       return inSize;
-}
-
-size_t CryptKit::FEEDContext::outputSize(
-       bool                    final, 
-       size_t                  inSize)                         // output for given input size
-{
-       size_t rtn;
-       if(encoding()) {
-               rtn = feeFEEDCipherTextSize(mFeeFeed, (unsigned int)(inSize + inBufSize()), final ? 1 : 0);
-       }
-       else {
-               rtn = feeFEEDPlainTextSize(mFeeFeed, (unsigned int)(inSize + inBufSize()), final ? 1 : 0);
-       }
-       bprintf(("--- FEEDContext::outputSize inSize 0x%x outSize 0x%x final %d\n",
-               inSize, rtn, final));
-       return rtn;
-}
-
-void CryptKit::FEEDContext::minimumProgress(
-       size_t                  &in, 
-       size_t                  &out)                           // minimum progress chunks
-{
-       if(encoding()) {
-               /*
-                * -- in  := one block plaintext
-                * -- out := current cipher size for one block plaintext
-                */
-               in  = inBlockSize();
-               out = feeFEEDCipherBufSize(mFeeFeed, 0);
-       }
-       else {
-               /*
-                * -- in  := current cipher size for one block plaintext
-                * -- out := one block plaintext
-                */
-               in  = feeFEEDCipherBufSize(mFeeFeed, 0); 
-               out = outBlockSize();
-       }
-       
-       /* 
-        * Either case - input adjusted for pending. Note inBufSize can be up to one 
-        * input block size, leaving the temp result zero here....
-        */
-       assert(in >= inBufSize());
-       in -= inBufSize();
-       
-       /* if it is zero, bump it up so caller can make something happen */
-       if(in == 0) {
-               in++;
-       }
-       bprintf(("--- FEEDContext::minProgres inSize 0x%x outSize 0x%x\n",
-               in, out));
-}
-
-/***
- *** FEEDExp - 2:1 FEED - encrypt n bytes of plaintext, get (roughly) 2n bytes
- *** of ciphertext. Ciphertext is larger than with FEED, but this is faster.
- ***/
-CryptKit::FEEDExpContext::~FEEDExpContext()
-{
-       if(mFeeFeedExp) {
-               feeFEEDExpFree(mFeeFeedExp);
-               mFeeFeedExp = NULL;
-       }
-       if(mFeeKey && mAllocdFeeKey) {
-               feePubKeyFree(mFeeKey);
-       }
-       mFeeKey = NULL;
-       mInitFlag = false;
-}
-
-// called by CSPFullPluginSession; reusable
-void CryptKit::FEEDExpContext::init(
-       const Context &context, 
-       bool encoding)
-{
-       if(mInitFlag && !opStarted()) {
-               /* reusing - e.g. query followed by encrypt */
-               return;
-       }
-       
-       /* fetch FEE key from context */
-       CSSM_KEYCLASS   keyClass;
-       CSSM_KEYUSE             keyUse;
-       
-       if(encoding) {
-               /* encrypting to public key */
-               keyClass = CSSM_KEYCLASS_PUBLIC_KEY;
-               keyUse   = CSSM_KEYUSE_ENCRYPT;
-       }
-       else {
-               /* decrypting with private key */
-               keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
-               keyUse   = CSSM_KEYUSE_DECRYPT;
-       }
-       if(mFeeKey == NULL) {
-               assert(!opStarted());
-               mFeeKey = contextToFeeKey(context,
-                       session(),
-                       CSSM_ATTRIBUTE_KEY,
-                       keyClass,
-                       keyUse,
-                       mAllocdFeeKey);
-       }
-       else {
-               assert(opStarted());
-       }
-       
-       /* validate context - no other attributes allowed */
-       validateFeedContext(context);
-
-       /* OK, looks good. Cook up a feeFEEDExp object. */
-       if(mFeeFeedExp != NULL) {
-               /* not reusable */
-               assert(opStarted());
-               feeFEEDExpFree(mFeeFeedExp);
-               mFeeFeedExp = NULL;
-       }
-       mFeeFeedExp = feeFEEDExpNewWithPubKey(mFeeKey,
-               feeRandCallback,
-               &session());
-       if(mFeeFeedExp == NULL) {
-               CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
-       }
-       
-       /* finally, have BlockCryptor set up its stuff. */
-       unsigned plainBlockSize = feeFEEDExpPlainBlockSize(mFeeFeedExp);
-       unsigned cipherBlockSize = feeFEEDExpCipherBlockSize(mFeeFeedExp);
-       setup(encoding ? plainBlockSize  : cipherBlockSize, // blockSizeIn
-                 encoding ? cipherBlockSize : plainBlockSize,  // blockSizeOut
-                 false,                                                                                // pkcs5Pad
-                 true,                                                                                 // needsFinal
-                 BCM_ECB,
-                 NULL);                                                                                        // IV
-       mInitFlag = true;
-}
-
-// called by BlockCryptor
-void CryptKit::FEEDExpContext::encryptBlock(
-       const void              *plainText,                     // length implied (one block)
-       size_t                  plainTextLen,
-       void                    *cipherText,    
-       size_t                  &cipherTextLen,         // in/out, throws on overflow
-       bool                    final)
-{
-       feeReturn frtn;
-       unsigned actMoved;
-       
-       assert(mFeeFeedExp != NULL);
-       frtn = feeFEEDExpEncryptBlock(mFeeFeedExp,
-               (unsigned char *)plainText,
-               (unsigned int)plainTextLen,
-               (unsigned char *)cipherText,
-               &actMoved,
-               final ? 1 : 0);
-       if(frtn) {
-               throwCryptKit(frtn, "feeFEEDExpEncryptBlock");
-       }
-       if(actMoved > cipherTextLen) {
-               /* Overflow already occurred! */
-               CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
-       }
-       cipherTextLen = actMoved;
-}
-
-void CryptKit::FEEDExpContext::decryptBlock(
-       const void              *cipherText,            // length implied (one cipher block)
-       size_t                  cipherTextLen,
-       void                    *plainText,     
-       size_t                  &plainTextLen,          // in/out, throws on overflow
-       bool                    final)
-{
-       feeReturn frtn;
-       unsigned actMoved;
-       
-       assert(mFeeFeedExp != NULL);
-       frtn = feeFEEDExpDecryptBlock(mFeeFeedExp,
-               (unsigned char *)cipherText,
-               (unsigned int)inBlockSize(),
-               (unsigned char *)plainText,
-               &actMoved,
-               final ? 1 : 0);
-       if(frtn) {
-               throwCryptKit(frtn, "feeFEEDExpDecryptBlock");
-       }
-       if(actMoved > plainTextLen) {
-               /* Overflow already occurred! */
-               CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
-       }
-       plainTextLen = actMoved;
-}
-
-/* convert uint32 to big-endian 4 bytes */
-static void int32ToBytes(
-       uint32_t i,
-       unsigned char *b)
-{
-       for(int dex=3; dex>=0; dex--) {
-               b[dex] = i;
-               i >>= 8;
-       }
-}
-
-/* 
- * X9.63 key derivation with optional SharedInfo passed as 
- * context attribute CSSM_ATTRIBUTE_SALT.
- */
-static feeReturn ecdhKdf(
-       const Context &context, 
-       const unsigned char *Z,         /* shared secret, i.e., output of ECDH */
-       unsigned ZLen,
-       CSSM_DATA *K)                           /* output RETURNED in K->Data, length K->Length bytes */
-{
-       /* SharedInfo via salt, from context, optional */
-       const unsigned char *sharedInfo = NULL;
-       CSSM_SIZE sharedInfoLen = 0;
-       
-       CssmData *salt = context.get<CssmData>(CSSM_ATTRIBUTE_SALT);
-       if(salt != NULL) {
-               sharedInfo = (const unsigned char *)salt->Data;
-               sharedInfoLen = salt->Length;
-       }
-       
-       unsigned char *outp = K->Data;
-       CSSM_SIZE bytesToGo = K->Length;
-       CC_SHA1_CTX sha1;
-       uint32_t counter = 1;
-       uint8 counterBytes[4];
-       unsigned char digOut[CC_SHA1_DIGEST_LENGTH];
-       
-       do {
-               /* K[i] = Hash(Z || Counter || SharedInfo) */
-               CC_SHA1_Init(&sha1);
-               CC_SHA1_Update(&sha1, Z, ZLen);
-               int32ToBytes(counter, counterBytes);
-               CC_SHA1_Update(&sha1, counterBytes, 4);
-               if(sharedInfoLen) {
-                       CC_SHA1_Update(&sha1, sharedInfo, (CC_LONG)sharedInfoLen);
-               }
-               CC_SHA1_Final(digOut, &sha1);
-               
-               /* digest --> output */
-               unsigned toMove = CC_SHA1_DIGEST_LENGTH;
-               if(toMove > bytesToGo) {
-                       toMove = (unsigned int)bytesToGo;
-               }
-               memmove(outp, digOut, toMove);
-               
-               counter++;
-               outp += toMove;
-               bytesToGo -= toMove;
-               
-       } while(bytesToGo);
-       
-       return FR_Success;
-}
-
-/*
- * Elliptic curve Diffie-Hellman key exchange. The public key is 
- * specified in one of two ways - a raw X9.62 format public key 
- * string in Param, or a CSSM_KEY in the Context. 
- * Requested size, in keyData->Length, must be the same size as
- * the keys' modulus. Data is returned in keyData->Data, which is 
- * allocated by the caller.
- * Optionally performs X9.63 key derivation if algId == 
- * CSSM_ALGID_ECDH_X963_KDF, with the optional SharedInfo passed
- * as optional context attribute CSSM_ATTRIBUTE_SALT.
- */
-void CryptKit::DeriveKey_ECDH (
-       const Context &context,
-       CSSM_ALGORITHMS algId,          
-       const CssmData &Param,                  // other's public key. may be empty
-       CSSM_DATA *keyData,                             // mallocd by caller
-                                                                       // we fill in keyData->Length bytes
-       AppleCSPSession &session)
-{
-       bool mallocdPrivKey;
-       size_t privSize;
-       
-       /* private ECDH key from context - required */
-       feePubKey privKey = contextToFeeKey(context, session, CSSM_ATTRIBUTE_KEY,
-               CSSM_KEYCLASS_PRIVATE_KEY, CSSM_KEYUSE_DERIVE, mallocdPrivKey);
-       if(privKey == NULL) {
-               CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY);
-       }
-       privSize = (feePubKeyBitsize(privKey) + 7) / 8;
-       if((algId == CSSM_ALGID_ECDH) & (privSize != keyData->Length)) {
-               /* exact match required here */
-               CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
-       }
-       
-       /*
-        * Public key ("their" key) can come from two places:
-        * -- in the context as a CSSM_ATTRIBUTE_PUBLIC_KEY. This is how 
-        *    public keys in X509 format must be used in this function.
-        * -- in the incoming Param, the raw unformatted (ANSI X9.62) form 
-        */
-       bool mallocdPubKey = false;
-       feePubKey pubKey = NULL;
-       if(Param.Data == NULL) {
-               /* this throws if no key present */
-               pubKey = contextToFeeKey(context, session, CSSM_ATTRIBUTE_PUBLIC_KEY,
-                       CSSM_KEYCLASS_PUBLIC_KEY, CSSM_KEYUSE_DERIVE, mallocdPubKey);
-       }
-       if((pubKey == NULL) && (Param.Data == NULL)) {
-               errorLog0("DeriveKey_ECDH: no pub_key\n");
-               CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
-       }
-       unsigned char *output = NULL;
-       unsigned outputLen = 0;
-       feeReturn frtn = feePubKeyECDH(privKey, pubKey, 
-               (const unsigned char *)Param.Data, (unsigned)Param.Length,
-               &output, &outputLen);
-       if(frtn) {
-               goto errOut;
-       }
-       switch(algId) {
-               case CSSM_ALGID_ECDH:
-                       /*
-                        * Raw ECDH - requested length must match the generated size
-                        * exactly. If so, return the result unmodified.
-                        */
-                       if(outputLen != keyData->Length) {
-                               errorLog0("DeriveKey_ECDH: length mismatch\n");
-                               frtn = FR_Internal;
-                               break;
-                       }
-                       memmove(keyData->Data, output, outputLen);
-                       break;
-               case CSSM_ALGID_ECDH_X963_KDF:
-                       /* Further processing... */
-                       frtn = ecdhKdf(context, output, outputLen, keyData);
-                       break;
-               default:
-                       /* shouldn't be here */
-                       frtn = FR_Internal;
-                       break;
-       }
-
-errOut:
-       if(mallocdPrivKey) {
-               feePubKeyFree(privKey);
-       }
-       if(mallocdPubKey) {
-               feePubKeyFree(pubKey);
-       }
-       if(output != NULL) {
-               ffree(output);
-       }
-       if(frtn) {
-               throwCryptKit(frtn, NULL);
-       }
-}
-
-#endif /* CRYPTKIT_CSP_ENABLE */