X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/84aacf34eae6543be9f0280b2015385f91e5c2c6..b54c578e17e9bcbd74aa30ea75e25e955b9a6205:/OSX/libsecurity_apple_csp/lib/bsafeContext.cpp?ds=inline diff --git a/OSX/libsecurity_apple_csp/lib/bsafeContext.cpp b/OSX/libsecurity_apple_csp/lib/bsafeContext.cpp deleted file mode 100644 index e69c8bd8..00000000 --- a/OSX/libsecurity_apple_csp/lib/bsafeContext.cpp +++ /dev/null @@ -1,448 +0,0 @@ -/* - * 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 - - -// -// bsafeContext.cpp - implementation of class BSafe::BSafeContext -// and some of its subclasses -// - -#include "bsafecspi.h" -#include "bsafePKCS1.h" -#include -#include -#include -#include "cspdebugging.h" - -#define DATA(cData) POINTER(cData.data()), cData.length() - -A_SURRENDER_CTX * const BSafe::BSafeContext::bsSurrender = NULL; - - -// -// Construct an algorithm object -// -BSafe::BSafeContext::BSafeContext(AppleCSPSession &session) - : AppleCSPContext(session) -{ - bsAlgorithm = NULL; - bsKey = NULL; - bsBinKey = NULL; - bsRandom = NULL; - initialized = false; - opStarted = false; -#ifdef SAFER - inUpdate = NULL; - inOutUpdate = NULL; - inFinal = NULL; - outFinal = NULL; - outFinalR = NULL; -#endif //SAFER -} - -BSafe::BSafeContext::~BSafeContext() -{ - reset(); -} - -void BSafe::BSafeContext::reset() -{ - B_DestroyAlgorithmObject(&bsAlgorithm); - B_DestroyAlgorithmObject(&bsRandom); - destroyBsKey(); -} - -/* - * Clear key state. We only destroy bsKey if we don't have a - * BinaryKey. - */ -void BSafe::BSafeContext::destroyBsKey() -{ - if(bsBinKey == NULL) { - B_DestroyKeyObject(&bsKey); - } - else { - // bsKey gets destroyed when bsBinKey gets deleted - bsBinKey = NULL; - bsKey = NULL; - } -} - -void BSafe::check(int status, bool isKeyOp) -{ - if(status == 0) { - return; - } - dprintf1("BSAFE Error %d\n", status); - switch (status) { - case BE_ALLOC: - throw std::bad_alloc(); - case BE_SIGNATURE: - CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED); - case BE_OUTPUT_LEN: - CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); - case BE_INPUT_LEN: - CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR); - case BE_EXPONENT_EVEN: - case BE_EXPONENT_LEN: - case BE_EXPONENT_ONE: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - case BE_DATA: - case BE_INPUT_DATA: - if(isKeyOp) { - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - } - else { - CssmError::throwMe(CSSMERR_CSP_INVALID_DATA); - } - case BE_MODULUS_LEN: - case BE_OVER_32K: - case BE_INPUT_COUNT: - case BE_CANCEL: - //@@@ later... - default: - //@@@ translate BSafe errors intelligently - CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); - } -} - - -void BSafe::BSafeContext::setAlgorithm( - B_INFO_TYPE bAlgType, - const void *info) -{ - B_DestroyAlgorithmObject(&bsAlgorithm); // clear any old BSafe algorithm - check(B_CreateAlgorithmObject(&bsAlgorithm)); - check(B_SetAlgorithmInfo(bsAlgorithm, bAlgType, POINTER(info))); -} - -/* safely create bsKey */ -void BSafe::BSafeContext::createBsKey() -{ - /* reset to initial key state - some keys can't be reused */ - destroyBsKey(); - check(B_CreateKeyObject(&bsKey)); -} - -/* form of *info varies per bKeyInfo */ -void BSafe::BSafeContext::setKeyAtom( - B_INFO_TYPE bKeyInfo, - const void *info) -{ - /* debug only */ - if((bKeyInfo == KI_RSAPublicBER) || (bKeyInfo == KI_RSAPublic)) { - printf("Aargh! Unhandled KI_RSAPublic!\n"); - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - } - assert(bKeyInfo != KI_RSAPublicBER); // handled elsewhere for now - assert(bKeyInfo != KI_RSAPublic); // handled elsewhere for now - createBsKey(); - check(B_SetKeyInfo(bsKey, bKeyInfo, POINTER(info)), true); -} - -// -// Set outSize for RSA keys. -// -void BSafe::BSafeContext::setRsaOutSize( - bool isPubKey) -{ - assert(bsKey != NULL); - - A_RSA_KEY *keyInfo; - if(isPubKey) { - keyInfo = getKey(bsKey, KI_RSAPublic); - } - else { - keyInfo = getKey(bsKey, KI_RSAPrivate); - } - mOutSize = (B_IntegerBits(keyInfo->modulus.data, - keyInfo->modulus.len) + 7) / 8; -} - -// -// Handle various forms of reference key. Symmetric -// keys are stored as SymmetricBinaryKey, with raw key bytes -// in keyData. Our asymmetric keys are stored as BSafeBinaryKeys, -// with an embedded ready-to-use B_KEY_OBJ. -// -void BSafe::BSafeContext::setRefKey(CssmKey &key) -{ - bool isPubKey = false; - - switch(key.keyClass()) { - case CSSM_KEYCLASS_SESSION_KEY: - { - assert(key.blobFormat() == - CSSM_KEYBLOB_REF_FORMAT_INTEGER); - - BinaryKey &binKey = session().lookupRefKey(key); - // fails if this is not a SymmetricBinaryKey - SymmetricBinaryKey *symBinKey = - dynamic_cast(&binKey); - if(symBinKey == NULL) { - errorLog0("BSafe::setRefKey(1): wrong BinaryKey subclass\n"); - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - } - setKeyFromCssmData(KI_Item, symBinKey->mKeyData); - return; - } - case CSSM_KEYCLASS_PUBLIC_KEY: - isPubKey = true; // and fall thru - case CSSM_KEYCLASS_PRIVATE_KEY: - { - BinaryKey &binKey = session().lookupRefKey(key); - destroyBsKey(); - bsBinKey = dynamic_cast(&binKey); - /* this cast failing means that this is some other - * kind of binary key */ - if(bsBinKey == NULL) { - errorLog0("BSafe::setRefKey(2): wrong BinaryKey subclass\n"); - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - } - assert(bsBinKey->bsKey() != NULL); - bsKey = bsBinKey->bsKey(); - if(key.algorithm() == CSSM_ALGID_RSA) { - setRsaOutSize(isPubKey); - } - return; - } - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); - } -} - -void BSafe::BSafeContext::setKeyFromContext( - const Context &context, - bool required) -{ - CssmKey &key = - context.get(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY); - - switch(key.blobType()) { - case CSSM_KEYBLOB_REFERENCE: - setRefKey(key); - return; - case CSSM_KEYBLOB_RAW: - break; // to main routine - default: - CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); - } - - bool isPubKey; - switch (key.keyClass()) { - case CSSM_KEYCLASS_SESSION_KEY: - /* symmetric, one format supported for all algs */ - switch (key.blobFormat()) { - case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: - setKeyFromCssmKey(KI_Item, key); - return; - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); - } - case CSSM_KEYCLASS_PUBLIC_KEY: - isPubKey = true; - break; - case CSSM_KEYCLASS_PRIVATE_KEY: - isPubKey = false; - break; - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); - } - - /* We know it's an asymmetric key; get some info */ - B_INFO_TYPE infoType; - CSSM_KEYBLOB_FORMAT expectedFormat; - - if(!bsafeAlgToInfoType(key.algorithm(), - isPubKey, - infoType, - expectedFormat)) { - /* unknown alg! */ - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - } - - /* - * Correct format? - * NOTE: if we end up supporting multiple incoming key formats, they'll - * have to be handled here. - */ - if(expectedFormat != key.blobFormat()) { - errorLog1("setKeyFromContext: invalid blob format (%d)\n", - (int)key.blobFormat()); - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); - } - - /* - * Most formats can be handled directly by BSAFE. Handle the special cases - * requiring additional processing here. - */ - switch(expectedFormat) { - case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: - /* RSA public keys */ - createBsKey(); - BS_setKeyPkcs1(CssmData::overlay(key.KeyData), bsKey); - break; - default: - setKeyFromCssmKey(infoType, key); - break; - } - - /* - * One more thing - set mOutSize for RSA keys - */ - if(key.algorithm() == CSSM_ALGID_RSA) { - setRsaOutSize(isPubKey); - } -} - -#define BSAFE_RANDSIZE 32 - -void BSafe::BSafeContext::setRandom() -{ - if (bsRandom == NULL) { - check(B_CreateAlgorithmObject(&bsRandom)); - check(B_SetAlgorithmInfo(bsRandom, AI_X962Random_V0, NULL_PTR)); - check(B_RandomInit(bsRandom, chooser(), bsSurrender)); - uint8 seed[BSAFE_RANDSIZE]; - session().getRandomBytes(BSAFE_RANDSIZE, seed); - check(B_RandomUpdate(bsRandom, seed, sizeof(seed), bsSurrender)); - } -} - - -// -// Operational methods of BSafeContext -// -void BSafe::BSafeContext::init(const Context &, bool) -{ - // some algorithms don't need init(), because all is done in the context constructor -} - -// update for input-only block/stream algorithms -void BSafe::BSafeContext::update(const CssmData &data) -{ - opStarted = true; - check(inUpdate(bsAlgorithm, POINTER(data.data()), data.length(), bsSurrender)); -} - -// update for input/output block/stream algorithms -void BSafe::BSafeContext::update(void *inp, size_t &inSize, void *outp, size_t &outSize) -{ - unsigned int length; - opStarted = true; - check(inOutUpdate(bsAlgorithm, POINTER(outp), &length, outSize, - POINTER(inp), inSize, bsRandom, bsSurrender)); - // always eat all input (inSize unchanged) - outSize = length; - - // let the algorithm manager track I/O sizes, if needed - trackUpdate(inSize, outSize); -} - -// output-generating final call -void BSafe::BSafeContext::final(CssmData &out) -{ - unsigned int length; - if (outFinal) { - check(outFinal(bsAlgorithm, - POINTER(out.data()), - &length, - out.length(), - bsSurrender)); - } - else { - check(outFinalR(bsAlgorithm, - POINTER(out.data()), - &length, - out.length(), - bsRandom, - bsSurrender)); - } - out.length(length); - initialized = false; -} - -// verifying final call (takes additional input) -void BSafe::BSafeContext::final(const CssmData &in) -{ - int status; - - /* note sig verify errors can show up as lots of BSAFE statuses; - * munge them all into the appropriate error */ - if (inFinal) { - status = inFinal(bsAlgorithm, - POINTER(in.data()), - in.length(), - bsSurrender); - } - else { - status = inFinalR(bsAlgorithm, - POINTER(in.data()), - in.length(), - bsRandom, - bsSurrender); - } - if(status != 0) { - if((mType == CSSM_ALGCLASS_SIGNATURE) && (mDirection == false)) { - /* yep, sig verify error */ - CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED); - } - /* other error, use standard trap */ - check(status); - } - initialized = false; -} - -size_t BSafe::BSafeContext::outputSize(bool final, size_t inSize) -{ - // this default implementation only makes sense for single-output end-loaded algorithms - return final ? mOutSize : 0; -} - -void BSafe::BSafeContext::trackUpdate(size_t, size_t) -{ /* do nothing */ } - -// -// Common features of CipherContexts. -// -void BSafe::CipherContext::cipherInit() -{ - // set handlers - if (encoding) { - inOutUpdate = B_EncryptUpdate; - outFinalR = B_EncryptFinal; - } else { - inOutUpdate = B_DecryptUpdate; - outFinalR = B_DecryptFinal; - } - outFinal = NULL; - - // init the algorithm - check((encoding ? B_EncryptInit : B_DecryptInit) - (bsAlgorithm, bsKey, chooser(), bsSurrender)); - - // buffers start empty - pending = 0; - - // state is now valid - initialized = true; - opStarted = false; -} -#endif /* BSAFE_CSP_ENABLE */ -