X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/libsecurity_apple_csp/lib/pkcs12Derive.cpp diff --git a/libsecurity_apple_csp/lib/pkcs12Derive.cpp b/libsecurity_apple_csp/lib/pkcs12Derive.cpp deleted file mode 100644 index 10d465b2..00000000 --- a/libsecurity_apple_csp/lib/pkcs12Derive.cpp +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (c) 2003 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. - */ -/* - * pkcs12Derive.cpp - PKCS12 PBE routine - * - * Created 2/28/03 by Doug Mitchell. - */ - -#include -#include -#include - -#include "pkcs12Derive.h" -#include "AppleCSPUtils.h" -#include "AppleCSPContext.h" - -#include -#include -#include -#include -#include - -#include - -/* specify which flavor of bits to generate */ -typedef enum { - PBE_ID_Key = 1, - PBE_ID_IV = 2, - PBE_ID_MAC = 3 -} P12_PBE_ID; - -/* - * Create a "string" (in the loose p12 notation) of specified length - * from the concatention of copies of the specified input string. - */ -static unsigned char *p12StrCat( - const unsigned char *inStr, - unsigned inStrLen, - SecNssCoder &coder, - unsigned outLen, - unsigned char *outStr = NULL) // if not present, we malloc -{ - if(outStr == NULL) { - outStr = (unsigned char *)coder.malloc(outLen); - } - unsigned toMove = outLen; - unsigned char *outp = outStr; - while(toMove) { - unsigned thisMove = inStrLen; - if(thisMove > toMove) { - thisMove = toMove; - } - memmove(outp, inStr, thisMove); - toMove -= thisMove; - outp += thisMove; - } - return outStr; -} - -/* - * PBE generator per PKCS12 v.1 section B.2. - */ -static CSSM_RETURN p12PbeGen( - const CSSM_DATA &pwd, // unicode, double null terminated - const uint8 *salt, - unsigned saltLen, - unsigned iterCount, - P12_PBE_ID pbeId, - CSSM_ALGORITHMS hashAlg, // MS5 or SHA1 only - SecNssCoder &coder, // for temp allocs - /* result goes here, mallocd by caller */ - uint8 *outbuf, - unsigned outbufLen) -{ - CSSM_RETURN ourRtn = CSSM_OK; - unsigned unipassLen = (unsigned)pwd.Length; - unsigned char *unipass = pwd.Data; - int irtn; - - /* - * all variables of the form p12_ represent from the - * PKCS12 spec. E.g., p12_u is u, the length of the digest output. - * Only difference here is: all of our sizes are in BYTES, not - * bits. - */ - unsigned p12_r = iterCount; - unsigned p12_n = outbufLen; - - unsigned p12_u; // hash output size - unsigned p12_v; // hash block size - unsigned char *p12_P = NULL; // catted passwords - unsigned char *p12_S = NULL; // catted salts - - switch(hashAlg) { - case CSSM_ALGID_MD5: - p12_u = kMD5DigestSize; - p12_v = kMD5BlockSize; - break; - case CSSM_ALGID_SHA1: - p12_u = kSHA1DigestSize; - p12_v = kSHA1BlockSize; - break; - default: - return CSSMERR_CSP_INVALID_ALGORITHM; - } - - /* - * 1. Construct a string, D (the diversifier), by - * concatenating v/8 copies of ID. - */ - unsigned char *p12_D = NULL; // diversifier - p12_D = (unsigned char *)coder.malloc(p12_v); - for(unsigned dex=0; dex p12_v) { - BN_bn2bin (Ij, p12_B); - memcpy (p12_I + j, p12_B + 1, p12_v); - /* If less than v bytes pad with zeroes */ - } else if (Ijlen < p12_v) { - memset(p12_I + j, 0, p12_v - Ijlen); - BN_bn2bin(Ij, p12_I + j + p12_v - Ijlen); - } else BN_bn2bin (Ij, p12_I + j); - } - } - - if(ourRtn == CSSM_OK) { - /* - * 7. Concatenate A[1], A[2], ..., A[c] together to form a - * pseudo-random bit string, A. - * - * 8. Use the first n bits of A as the output of this entire - * process. - */ - memmove(outbuf, p12_A, outbufLen); - } - - /* clear all these strings */ - if(p12_D) { - memset(p12_D, 0, p12_v); - } - if(p12_S) { - memset(p12_S, 0, p12_Slen); - } - if(p12_P) { - memset(p12_P, 0, p12_Plen); - } - if(p12_I) { - memset(p12_I, 0, p12_Slen + p12_Plen); - } - if(p12_A) { - memset(p12_A, 0, p12_c * p12_u); - } - if(p12_B) { - memset(p12_B, 0, p12_v); - } - if(hashHand) { - DigestCtxFree(hashHand); - } - BN_free(Bpl1); - BN_free(Ij); - return ourRtn; -} - -/* - * Public P12 derive key function, called out from - * AppleCSPSession::DeriveKey() - * - * On input: - * --------- - * Context parameters: - * Salt - * Iteration Count - * CSSM_CRYPTO_DATA.Param - Unicode passphrase, double-NULL terminated - * Algorithm - CSSM_ALGID_PKCS12_PBE_{ENCR,MAC} - * Passed explicitly from DeriveKey(): - * CSSM_DATA Param - IN/OUT - optional IV - caller mallocs space to - * tell us to generate an IV. The param itself is not - * optional; the presence or absence of allocated data in it - * is our IV indicator (present/absent as well as size) - * KeyData - mallocd by caller, we fill in keyData->Length bytes - */ -void DeriveKey_PKCS12 ( - const Context &context, - AppleCSPSession &session, - const CssmData &Param, // other's public key - CSSM_DATA *keyData) // mallocd by caller - // we fill in keyData->Length bytes -{ - SecNssCoder tmpCoder; - - /* - * According to the spec, both passphrase and salt are optional. - * Get them from context if they're present. In practical terms - * the user really should supply a passphrase either in the - * seed attribute (as a Unicode passphrase) or as the BaseKey - * as a CSSM_ALGID_SECURE_PASSPHRASE key). - */ - CSSM_DATA pwd = {0, NULL}; - CSSM_DATA appPwd = {0, NULL}; - CssmCryptoData *cryptData = - context.get(CSSM_ATTRIBUTE_SEED); - if((cryptData != NULL) && (cryptData->Param.Length != 0)) { - appPwd = cryptData->Param; - } - else { - /* Get pwd from base key */ - CssmKey *passKey = context.get(CSSM_ATTRIBUTE_KEY); - if (passKey != NULL) { - AppleCSPContext::symmetricKeyBits(context, session, - CSSM_ALGID_SECURE_PASSPHRASE, CSSM_KEYUSE_DERIVE, - appPwd.Data, appPwd.Length); - } - } - if(appPwd.Data) { - /* - * The incoming passphrase is a UTF8 encoded enternal representation - * of a CFString. Convert to CFString and obtain the unicode characters - * from the string. - */ - CFDataRef cfData = CFDataCreate(NULL, appPwd.Data, appPwd.Length); - CFStringRef cfStr = CFStringCreateFromExternalRepresentation(NULL, - cfData, kCFStringEncodingUTF8); - if (cfData) - CFRelease(cfData); - if(cfStr == NULL) { - CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SEED); - } - - /* convert unicode to chars with an extra double-NULL */ - CFIndex len = CFStringGetLength(cfStr); - tmpCoder.allocItem(pwd, sizeof(UniChar) * (len + 1)); - unsigned char *cp = pwd.Data; - UniChar uc = 0; - for(CFIndex dex=0; dex> 8; - *cp++ = uc & 0xff; - } - /* CFString tends to include a NULL at the end; add it if it's not there */ - if(uc == 0) { - if(pwd.Length < 2) { - CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SEED); - } - pwd.Length -= 2; - } - else { - *cp++ = 0; - *cp++ = 0; - } - if (cfStr) - CFRelease(cfStr); - } - - /* salt from context */ - uint32 saltLen = 0; - uint8 *salt = NULL; - CssmData *csalt = context.get(CSSM_ATTRIBUTE_SALT); - if(csalt) { - salt = csalt->Data; - saltLen = (uint32)csalt->Length; - } - - /* - * Iteration count, from context, required. - * The spec's ASN1 definition says this is optional with a default - * of one but that's a BER encode/decode issue. Here we require - * a nonzero value. - */ - uint32 iterCount = context.getInt(CSSM_ATTRIBUTE_ITERATION_COUNT, - CSSMERR_CSP_MISSING_ATTR_ITERATION_COUNT); - if(iterCount == 0) { - CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ITERATION_COUNT); - } - - /* - * Algorithm determines which of {PBE_ID_Key,PBE_ID_MAC} we now - * generate. We'll also do an optional PBE_ID_IV later. - */ - P12_PBE_ID pbeId = PBE_ID_Key; - switch(context.algorithm()) { - case CSSM_ALGID_PKCS12_PBE_ENCR: - pbeId = PBE_ID_Key; - break; - case CSSM_ALGID_PKCS12_PBE_MAC: - pbeId = PBE_ID_MAC; - break; - default: - /* really should not be here */ - assert(0); - CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); - } - - /* Go */ - CSSM_RETURN crtn = p12PbeGen(pwd, - salt, saltLen, - iterCount, - pbeId, - CSSM_ALGID_SHA1, // all we support for now - tmpCoder, - keyData->Data, - (unsigned)keyData->Length); - if(crtn) { - CssmError::throwMe(crtn); - } - - /* - * Optional IV - makes no sense if we just did PBE_ID_MAC, but why - * bother restricting? - */ - if(Param.Data) { - crtn = p12PbeGen(pwd, - salt, saltLen, - iterCount, - PBE_ID_IV, - CSSM_ALGID_SHA1, // all we support for now - tmpCoder, - Param.Data, - (unsigned)Param.Length); - if(crtn) { - CssmError::throwMe(crtn); - } - } -} -