X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/libsecurity_apple_csp/lib/DH_keys.cpp diff --git a/libsecurity_apple_csp/lib/DH_keys.cpp b/libsecurity_apple_csp/lib/DH_keys.cpp deleted file mode 100644 index 3ad1b392..00000000 --- a/libsecurity_apple_csp/lib/DH_keys.cpp +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright (c) 2000-2002 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. - */ - - -/* - * DH_keys.cpp - Diffie-Hellman key pair support. - */ - -#include "DH_keys.h" -#include "DH_utils.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define dhKeyDebug(args...) secdebug("dhKey", ## args) - -/* - * FIXME - the CDSA Algorithm Guide claims that the incoming params argument - * for a GenerateAlgorithmParameters call is ignored for D-H. This means - * that there is no way for the caller to specify 'g' (typically 2, 3, or - * 5). This seems WAY bogus but we'll code to the spec for now, assuming - * a hard-coded default generator. - */ -#define DH_GENERATOR_DEFAULT DH_GENERATOR_2 - - -/*** - *** Diffie-Hellman-style BinaryKey - ***/ - -/* constructor with optional existing DSA key */ -DHBinaryKey::DHBinaryKey(DH *dhKey) - : mDhKey(dhKey) -{ -} - -DHBinaryKey::~DHBinaryKey() -{ - if(mDhKey) { - DH_free(mDhKey); - mDhKey = NULL; - } -} - -void DHBinaryKey::generateKeyBlob( - Allocator &allocator, - CssmData &blob, - CSSM_KEYBLOB_FORMAT &format, - AppleCSPSession &session, - const CssmKey *paramKey, /* optional, unused here */ - CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */ -{ - - switch(mKeyHeader.KeyClass) { - case CSSM_KEYCLASS_PUBLIC_KEY: - { - switch(format) { - case CSSM_KEYBLOB_RAW_FORMAT_NONE: - // take default - format = DH_PUB_KEY_FORMAT; - break; - case DH_PUB_KEY_FORMAT: - case CSSM_KEYBLOB_RAW_FORMAT_X509: - // proceed - break; - case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: - /* use PKCS3 - caller won't care if we change this...right? */ - format = DH_PUB_KEY_FORMAT; - break; - default: - CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT); - } - - assert(mDhKey != NULL); - CssmAutoData encodedKey(allocator); - CSSM_RETURN crtn = DHPublicKeyEncode(mDhKey, format, - encodedKey); - if(crtn) { - CssmError::throwMe(crtn); - } - blob = encodedKey.release(); - break; - } - case CSSM_KEYCLASS_PRIVATE_KEY: - { - switch(format) { - case CSSM_KEYBLOB_RAW_FORMAT_NONE: - // i.e., use default - format = DH_PRIV_KEY_FORMAT; - break; - case DH_PRIV_KEY_FORMAT: - case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: - // proceed - break; - - case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: - { - /* - * Use public blob; calculate it if we - * don't already have it. - */ - assert(mDhKey != NULL); - if(mDhKey->pub_key == NULL) { - int irtn = DH_generate_key(mDhKey); - if(!irtn) { - throwRsaDsa("DH_generate_key"); - } - } - assert(mDhKey->pub_key != NULL); - setUpData(blob, - BN_num_bytes(mDhKey->pub_key), - *DH_Factory::privAllocator); - BN_bn2bin(mDhKey->pub_key, blob); - format = DH_PUB_KEY_FORMAT; - return; - } - - default: - CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT); - } - assert(mDhKey != NULL); - CssmAutoData encodedKey(allocator); - CSSM_RETURN crtn = DHPrivateKeyEncode(mDhKey, format, - encodedKey); - if(crtn) { - CssmError::throwMe(crtn); - } - blob = encodedKey.release(); - break; - } - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); - } -} - -/*** - *** Diffie-Hellman style AppleKeyPairGenContext - ***/ - -/* - * This one is specified in, and called from, CSPFullPluginSession. Our - * only job is to prepare two subclass-specific BinaryKeys and call up to - * AppleKeyPairGenContext. - */ -void DHKeyPairGenContext::generate( - const Context &context, - CssmKey &pubKey, - CssmKey &privKey) -{ - DHBinaryKey *pubBinKey = new DHBinaryKey(); - DHBinaryKey *privBinKey = new DHBinaryKey(); - - try { - AppleKeyPairGenContext::generate(context, - session(), - pubKey, - pubBinKey, - privKey, - privBinKey); - } - catch (...) { - delete pubBinKey; - delete privBinKey; - throw; - } -} - -/* - * This one is specified in, and called from, AppleKeyPairGenContext - */ -void DHKeyPairGenContext::generate( - const Context &context, - BinaryKey &pubBinKey, - BinaryKey &privBinKey, - uint32 &keyBits) -{ - /* - * These casts throw exceptions if the keys are of the - * wrong classes, which would be a major bogon, since we created - * the keys in the above generate() function. - */ - DHBinaryKey &rPubBinKey = - dynamic_cast(pubBinKey); - DHBinaryKey &rPrivBinKey = - dynamic_cast(privBinKey); - - /* - * Parameters from context: - * Key size in bits, required; - * {p,g,privKeyLength} from generateParams, optional - * NOTE: currently the openssl D-H imnplementation ignores the - * privKeyLength field. - */ - keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH, - CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH); - CssmData *paramData = context.get(CSSM_ATTRIBUTE_ALG_PARAMS); - - NSS_DHParameterBlock algParamBlock; - NSS_DHParameter &algParams = algParamBlock.params; - uint32 privValueLen = 0; // only nonzero from externally generated - // params - SecNssCoder coder; // for temp allocs of decoded parameters - - if(paramData != NULL) { - /* this contains the DER encoding of a DHParameterBlock */ - CSSM_RETURN crtn; - crtn = DHParamBlockDecode(*paramData, algParamBlock, coder); - if(crtn) { - CssmError::throwMe(crtn); - } - - /* snag the optional private key length field */ - if(algParams.privateValueLength.Data) { - privValueLen = cssmDataToInt(algParams.privateValueLength); - } - - /* ensure caller's key size matches the incoming params */ - size_t paramKeyBytes; - if(privValueLen) { - paramKeyBytes = (privValueLen + 7) / 8; - } - else { - paramKeyBytes = algParams.prime.Length; - /* trim off possible m.s. byte of zero */ - const unsigned char *uo = - (const unsigned char *)algParams.prime.Data; - if(*uo == 0) { - paramKeyBytes--; - } - } - uint32 reqBytes = (keyBits + 7) / 8; - if(paramKeyBytes != reqBytes) { - dhKeyDebug("DH key size mismatch (req %d param %d)", - (int)reqBytes, (int)paramKeyBytes); - CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE); - } - } - else { - /* no alg params specified; generate them now */ - dhKeyDebug("DH implicit alg param calculation"); - memset(&algParamBlock, 0, sizeof(algParamBlock)); - dhGenParams(keyBits, DH_GENERATOR_DEFAULT, 0, algParams, coder); - } - - /* create key, stuff params into it */ - rPrivBinKey.mDhKey = DH_new(); - if(rPrivBinKey.mDhKey == NULL) { - CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); - } - DH *dhKey = rPrivBinKey.mDhKey; - dhKey->p = cssmDataToBn(algParams.prime); - dhKey->g = cssmDataToBn(algParams.base); - dhKey->length = privValueLen; - cspDhDebug("private DH binary key dhKey %p", dhKey); - - /* generate the key (both public and private capabilities) */ - int irtn = DH_generate_key(dhKey); - if(!irtn) { - throwRsaDsa("DH_generate_key"); - } - - /* public key is a subset */ - rPubBinKey.mDhKey = DH_new(); - if(rPubBinKey.mDhKey == NULL) { - CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); - } - DH *pubDhKey = rPubBinKey.mDhKey; - pubDhKey->pub_key = BN_dup(dhKey->pub_key); - /* these params used for X509 style key blobs */ - pubDhKey->p = BN_dup(dhKey->p); - pubDhKey->g = BN_dup(dhKey->g); - cspDhDebug("public DH binary key pubDhKey %p", pubDhKey); -} - - - -/*** - *** Diffie-Hellman CSPKeyInfoProvider. - ***/ -DHKeyInfoProvider::DHKeyInfoProvider( - const CssmKey &cssmKey, - AppleCSPSession &session) : - CSPKeyInfoProvider(cssmKey, session) -{ -} - -CSPKeyInfoProvider *DHKeyInfoProvider::provider( - const CssmKey &cssmKey, - AppleCSPSession &session) -{ - switch(cssmKey.algorithm()) { - case CSSM_ALGID_DH: - break; - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); - } - switch(cssmKey.keyClass()) { - case CSSM_KEYCLASS_PUBLIC_KEY: - case CSSM_KEYCLASS_PRIVATE_KEY: - break; - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); - } - /* OK, we'll handle this one */ - return new DHKeyInfoProvider(cssmKey, session); -} - -/* Given a raw key, cook up a Binary key */ -void DHKeyInfoProvider::CssmKeyToBinary( - CssmKey *paramKey, // optional, ignored here - CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT - BinaryKey **binKey) -{ - *binKey = NULL; - - assert(mKey.blobType() == CSSM_KEYBLOB_RAW); - switch(mKey.keyClass()) { - case CSSM_KEYCLASS_PUBLIC_KEY: - case CSSM_KEYCLASS_PRIVATE_KEY: - break; - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); - } - - /* first cook up an DH key, then drop that into a BinaryKey */ - DH *dhKey = rawCssmKeyToDh(mKey); - DHBinaryKey *dhBinKey = new DHBinaryKey(dhKey); - *binKey = dhBinKey; - cspDhDebug("CssmKeyToBinary dhKey %p", dhKey); -} - -/* - * Obtain key size in bits. - * FIXME - I doubt that this is, or can be, exactly accurate..... - */ -void DHKeyInfoProvider::QueryKeySizeInBits( - CSSM_KEY_SIZE &keySize) -{ - uint32 numBits = 0; - - if(mKey.blobType() != CSSM_KEYBLOB_RAW) { - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); - } - DH *dhKey = rawCssmKeyToDh(mKey); - - /* DH_size requires the p parameter, which some public keys don't have */ - if(dhKey->p != NULL) { - numBits = DH_size(dhKey) * 8; - } - else { - assert(dhKey->pub_key != NULL); - numBits = BN_num_bytes(dhKey->pub_key) * 8; - } - DH_free(dhKey); - keySize.LogicalKeySizeInBits = numBits; - keySize.EffectiveKeySizeInBits = numBits; -} - -/* - * Obtain blob suitable for hashing in CSSM_APPLECSP_KEYDIGEST - * passthrough. - */ -bool DHKeyInfoProvider::getHashableBlob( - Allocator &allocator, - CssmData &blob) // blob to hash goes here -{ - /* - * The optimized case, a raw key in the "proper" format already. - */ - assert(mKey.blobType() == CSSM_KEYBLOB_RAW); - bool useAsIs = false; - - switch(mKey.keyClass()) { - case CSSM_KEYCLASS_PUBLIC_KEY: - if(mKey.blobFormat() == CSSM_KEYBLOB_RAW_FORMAT_PKCS3) { - useAsIs = true; - } - break; - case CSSM_KEYCLASS_PRIVATE_KEY: - break; - default: - /* shouldn't be here */ - assert(0); - CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); - } - if(useAsIs) { - const CssmData &keyBlob = CssmData::overlay(mKey.KeyData); - copyCssmData(keyBlob, blob, allocator); - return true; - } - - /* caller converts to binary and proceeds */ - return false; -} - -/* - * Generate keygen parameters, stash them in a context attr array for later use - * when actually generating the keys. - */ - -void DHKeyPairGenContext::generate( - const Context &context, - uint32 bitSize, - CssmData ¶ms, // RETURNED here, - uint32 &attrCount, // here, - Context::Attr * &attrs) // and here -{ - /* generate the params */ - NSS_DHParameterBlock algParamBlock; - SecNssCoder coder; - NSS_DHParameter &algParams = algParamBlock.params; - dhGenParams(bitSize, DH_GENERATOR_DEFAULT, 0, algParams, coder); - - /* drop in the required OID */ - algParamBlock.oid = CSSMOID_PKCS3; - - /* - * Here comes the fun part. - * We "return" the DER encoding of these generated params in two ways: - * 1. Copy out to app via the params argument, mallocing if Data ptr is NULL. - * The app must free this. - * 2. Cook up a 1-element Context::attr array containing one ALG_PARAM attr, - * a CSSM_DATA_PTR containing the DER encoding. We have to save a ptr to - * this attr array and free it, the CSSM_DATA it points to, and the DER - * encoding *that* points to, in our destructor. - * - * First, DER encode. - */ - CssmAutoData aDerData(session()); - PRErrorCode perr; - perr = SecNssEncodeItemOdata(&algParamBlock, kSecAsn1DHParameterBlockTemplate, - aDerData); - if(perr) { - /* only known error... */ - CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); - } - - /* copy/release that into a mallocd CSSM_DATA. */ - CSSM_DATA_PTR derData = (CSSM_DATA_PTR)session().malloc(sizeof(CSSM_DATA)); - *derData = aDerData.release(); - - /* stuff that into a one-element Attr array which we keep after returning */ - freeGenAttrs(); - mGenAttrs = (Context::Attr *)session().malloc(sizeof(Context::Attr)); - mGenAttrs->AttributeType = CSSM_ATTRIBUTE_ALG_PARAMS; - mGenAttrs->AttributeLength = sizeof(CSSM_DATA); - mGenAttrs->Attribute.Data = derData; - - /* and "return" this stuff */ - copyCssmData(CssmData::overlay(*derData), params, session()); - attrCount = 1; - attrs = mGenAttrs; -} - -/* free mGenAttrs and its referents if present */ -void DHKeyPairGenContext::freeGenAttrs() -{ - if(mGenAttrs == NULL) { - return; - } - if(mGenAttrs->Attribute.Data) { - if(mGenAttrs->Attribute.Data->Data) { - session().free(mGenAttrs->Attribute.Data->Data); - } - session().free(mGenAttrs->Attribute.Data); - } - session().free(mGenAttrs); -} - -/* - * Generate DSA algorithm parameters returning result - * into DHParameter.{prime,base,privateValueLength]. - * This is called from both GenerateParameters and from - * KeyPairGenerate (if no GenerateParameters has yet been called). - * - * FIXME - privateValueLength not implemented in openssl, not here - * either for now. - */ - -void DHKeyPairGenContext::dhGenParams( - uint32 keySizeInBits, - unsigned g, // probably should be BIGNUM - int privValueLength, // optional - NSS_DHParameter &algParams, - SecNssCoder &coder) // temp contents of algParams - // mallocd here -{ - /* validate key size */ - if((keySizeInBits < DH_MIN_KEY_SIZE) || - (keySizeInBits > DH_MAX_KEY_SIZE)) { - CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); - } - - /* create an openssl-style DH key with minimal setup */ - DH *dhKey = DH_generate_parameters(keySizeInBits, g, NULL, NULL); - if(dhKey == NULL) { - throwRsaDsa("DSA_generate_parameters"); - } - - /* stuff dhKey->{p,g,length}] into a caller's NSS_DHParameter */ - bnToCssmData(dhKey->p, algParams.prime, coder); - bnToCssmData(dhKey->g, algParams.base, coder); - CSSM_DATA &privValData = algParams.privateValueLength; - if(privValueLength) { - intToCssmData(privValueLength, privValData, coder); - } - else { - privValData.Data = NULL; - privValData.Length = 0; - } - DH_free(dhKey); -} -