#include "p12Crypto.h"
#include "pkcs12Utils.h"
#include <security_cdsa_utils/cuCdsaUtils.h>
#include <Security/cssmapple.h>
static void appFreeCssmMemory(
CSSM_HANDLE hand,
void *p)
{
CSSM_API_MEMORY_FUNCS memFuncs;
CSSM_RETURN crtn = CSSM_GetAPIMemoryFunctions(hand, &memFuncs);
if(crtn) {
cssmPerror("CSSM_GetAPIMemoryFunctions", crtn);
return;
}
memFuncs.free_func(p, memFuncs.AllocRef);
}
#define KEY_LABEL "p12 key"
CSSM_RETURN p12KeyGen_app(
CSSM_CSP_HANDLE cspHand,
CSSM_KEY &key,
bool isForEncr, CSSM_ALGORITHMS keyAlg,
CSSM_ALGORITHMS pbeHashAlg, uint32 keySizeInBits,
uint32 iterCount,
const CSSM_DATA &salt,
const CSSM_DATA &pwd, CSSM_DATA &iv) {
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHand;
CSSM_DATA dummyLabel;
CSSM_ACCESS_CREDENTIALS creds;
memset(&key, 0, sizeof(CSSM_KEY));
memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
CSSM_ALGORITHMS deriveAlg = CSSM_ALGID_NONE;
if(pbeHashAlg != CSSM_ALGID_SHA1) {
return CSSMERR_CSP_INVALID_ALGORITHM;
}
if(isForEncr) {
deriveAlg = CSSM_ALGID_PKCS12_PBE_ENCR;
}
else {
deriveAlg = CSSM_ALGID_PKCS12_PBE_MAC;
}
CSSM_CRYPTO_DATA seed;
seed.Param = pwd;
seed.Callback = NULL;
seed.CallerCtx = NULL;
crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand,
deriveAlg,
keyAlg,
keySizeInBits,
&creds,
NULL, iterCount,
&salt,
&seed, &ccHand);
if(crtn) {
cuPrintError("CSSM_CSP_CreateDeriveKeyContext", crtn);
return crtn;
}
dummyLabel.Length = strlen(KEY_LABEL);
dummyLabel.Data = (uint8 *)KEY_LABEL;
crtn = CSSM_DeriveKey(ccHand,
&iv,
CSSM_KEYUSE_ANY,
CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE,
&dummyLabel,
NULL, &key);
CSSM_DeleteContext(ccHand);
if(crtn) {
cuPrintError("CSSM_DeriveKey", crtn);
}
return crtn;
}
CSSM_RETURN p12Decrypt_app(
CSSM_CSP_HANDLE cspHand,
const CSSM_DATA &cipherText,
CSSM_ALGORITHMS keyAlg,
CSSM_ALGORITHMS encrAlg,
CSSM_ALGORITHMS pbeHashAlg, uint32 keySizeInBits,
uint32 blockSizeInBytes, CSSM_PADDING padding, CSSM_ENCRYPT_MODE mode, uint32 iterCount,
const CSSM_DATA &salt,
const CSSM_DATA &pwd, SecNssCoder &coder, CSSM_DATA &plainText)
{
CSSM_RETURN crtn;
CSSM_KEY ckey;
CSSM_CC_HANDLE ccHand = 0;
CSSM_DATA iv = {0, NULL};
CSSM_DATA_PTR ivPtr = NULL;
if(blockSizeInBytes) {
coder.allocItem(iv, blockSizeInBytes);
ivPtr = &iv;
}
crtn = p12KeyGen_app(cspHand, ckey, true, keyAlg, pbeHashAlg,
keySizeInBits, iterCount, salt, pwd, iv);
if(crtn) {
return crtn;
}
crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
encrAlg,
mode,
NULL, &ckey,
ivPtr, padding,
NULL, &ccHand);
if(crtn) {
cuPrintError("CSSM_CSP_CreateSymmetricContext", crtn);
return crtn;
}
CSSM_DATA ourPtext = {0, NULL};
CSSM_DATA remData = {0, NULL};
uint32 bytesDecrypted;
crtn = CSSM_DecryptData(ccHand,
&cipherText,
1,
&ourPtext,
1,
&bytesDecrypted,
&remData);
if(crtn) {
cuPrintError("CSSM_EncryptData", crtn);
}
else {
coder.allocCopyItem(ourPtext, plainText);
plainText.Length = bytesDecrypted;
appFreeCssmMemory(cspHand, ourPtext.Data);
}
if(remData.Data) {
appFreeCssmMemory(cspHand, remData.Data);
}
CSSM_DeleteContext(ccHand);
CSSM_FreeKey(cspHand, NULL, &ckey, CSSM_FALSE);
return crtn;
}
CSSM_RETURN p12GenMac_app(
CSSM_CSP_HANDLE cspHand,
const CSSM_DATA &ptext, CSSM_ALGORITHMS alg, unsigned iterCount,
const CSSM_DATA &salt,
const CSSM_DATA &pwd, SecNssCoder &coder, CSSM_DATA &macData) {
CSSM_RETURN crtn;
unsigned keySizeInBits;
CSSM_ALGORITHMS hmacAlg;
switch(alg) {
case CSSM_ALGID_SHA1:
keySizeInBits = 160;
hmacAlg = CSSM_ALGID_SHA1HMAC;
break;
case CSSM_ALGID_MD5:
keySizeInBits = 128;
hmacAlg = CSSM_ALGID_MD5HMAC;
break;
default:
return CSSMERR_CSP_INVALID_ALGORITHM;
}
CSSM_KEY macKey;
CSSM_DATA iv = {0, NULL};
crtn = p12KeyGen_app(cspHand, macKey, false, hmacAlg, alg,
keySizeInBits, iterCount, salt, pwd, iv);
if(crtn) {
return crtn;
}
coder.allocItem(macData, keySizeInBits / 8);
CSSM_CC_HANDLE ccHand = 0;
crtn = CSSM_CSP_CreateMacContext(cspHand, hmacAlg, &macKey, &ccHand);
if(crtn) {
cuPrintError("CSSM_CSP_CreateMacContext", crtn);
return crtn;
}
crtn = CSSM_GenerateMac (ccHand, &ptext, 1, &macData);
if(crtn) {
cuPrintError("CSSM_GenerateMac", crtn);
}
CSSM_DeleteContext(ccHand);
CSSM_FreeKey(cspHand, NULL, &macKey, CSSM_FALSE);
return crtn;
}
CSSM_RETURN p12VerifyMac_app(
const NSS_P12_DecodedPFX &pfx,
CSSM_CSP_HANDLE cspHand,
const CSSM_DATA &pwd, SecNssCoder &coder) {
if(pfx.macData == NULL) {
return CSSMERR_CSP_INVALID_SIGNATURE;
}
NSS_P12_MacData &macData = *pfx.macData;
NSS_P7_DigestInfo &digestInfo = macData.mac;
CSSM_OID &algOid = digestInfo.digestAlgorithm.algorithm;
CSSM_ALGORITHMS macAlg;
if(!cssmOidToAlg(&algOid, &macAlg)) {
return CSSMERR_CSP_INVALID_ALGORITHM;
}
uint32 iterCount = 0;
CSSM_DATA &citer = macData.iterations;
if(!p12DataToInt(citer, iterCount)) {
return CSSMERR_CSP_INVALID_ATTR_ROUNDS;
}
if(iterCount == 0) {
iterCount = 1;
}
CSSM_DATA genMac;
CSSM_RETURN crtn = p12GenMac_app(cspHand, *pfx.authSafe.content.data,
macAlg, iterCount, macData.macSalt, pwd, coder, genMac);
if(crtn) {
return crtn;
}
if(nssCompareCssmData(&genMac, &digestInfo.digest)) {
return CSSM_OK;
}
else {
return CSSMERR_CSP_VERIFY_FAILED;
}
}