#include "p12Crypto.h"
#include "p12pbe.h"
#include <security_pkcs12/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);
}
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, SecNssCoder &coder) {
memset(&key, 0, sizeof(CSSM_KEY));
unsigned keyBytes = (keySizeInBits + 7) / 8;
coder.allocItem(key.KeyData, keyBytes);
CSSM_RETURN crtn = p12PbeGen_app(pwd,
salt.Data, salt.Length,
iterCount,
isForEncr ? PBE_ID_Key : PBE_ID_Mac,
pbeHashAlg,
cspHand,
(unsigned char *)key.KeyData.Data,
key.KeyData.Length);
if(crtn) {
cuPrintError("p12PbeGen(key)", crtn);
return crtn;
}
CSSM_KEYHEADER &hdr = key.KeyHeader;
hdr.HeaderVersion = CSSM_KEYHEADER_VERSION;
hdr.BlobType = CSSM_KEYBLOB_RAW;
hdr.AlgorithmId = keyAlg;
hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
hdr.KeyClass = CSSM_KEYCLASS_SESSION_KEY;
hdr.KeyUsage = CSSM_KEYUSE_ANY;
hdr.WrapAlgorithmId = CSSM_ALGID_NONE;
hdr.WrapMode = CSSM_ALGMODE_NONE;
hdr.LogicalKeySizeInBits = keySizeInBits;
if(iv.Data != NULL) {
crtn = p12PbeGen_app(pwd,
salt.Data, salt.Length,
iterCount,
PBE_ID_IV,
pbeHashAlg,
cspHand,
iv.Data, iv.Length);
if(crtn) {
cuPrintError("p12PbeGen (IV)", crtn);
return crtn;
}
}
return CSSM_OK;
}
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, coder);
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);
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, coder);
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);
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;
}
}