#include "DH_exchange.h"
#include <Security/cssmerr.h>
#include "DH_utils.h"
#include "DH_keys.h"
#include <strings.h>
#include <opensslUtils/opensslUtils.h>
void DeriveKey_DH (
const Context &context,
const CssmData &Param, CSSM_DATA *keyData, AppleCSPSession &session)
{
bool mallocdPrivKey;
size_t privSize;
DH *privKey = contextToDhKey(context, session, CSSM_ATTRIBUTE_KEY,
CSSM_KEYCLASS_PRIVATE_KEY, CSSM_KEYUSE_DERIVE, mallocdPrivKey);
if(privKey == NULL) {
CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY);
}
cspDhDebug("DeriveKey_DH, privKey %p", privKey);
privSize = DH_size(privKey);
if(privSize < keyData->Length) {
CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE);
}
bool mallocdPubKey = false;
BIGNUM *pubKeyBn = NULL;
bool allocdPubKeyBn = false;
DH *pubKey = contextToDhKey(context, session, CSSM_ATTRIBUTE_PUBLIC_KEY,
CSSM_KEYCLASS_PUBLIC_KEY, CSSM_KEYUSE_DERIVE, mallocdPubKey);
if(pubKey != NULL) {
if(pubKey->pub_key == NULL) {
errorLog0("DeriveKey_DH: public key in context with no pub_key\n");
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
}
pubKeyBn = pubKey->pub_key;
cspDhDebug("DeriveKey_DH, pubKey from context %p", pubKey);
}
else {
if((Param.Data == NULL) || (Param.Length == 0)) {
errorLog0("DeriveKey_DH: no pub_key, no Param\n");
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
}
pubKeyBn = BN_bin2bn(Param.Data, (int)Param.Length, NULL);
if(pubKeyBn == NULL) {
CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
}
allocdPubKeyBn = true;
cspDhDebug("DeriveKey_DH, no pubKey in context");
}
unsigned char *buf = (unsigned char *)session.malloc(privSize);
int rtn = DH_compute_key(buf, pubKeyBn, privKey);
if(rtn > 0) {
assert((uint32)rtn <= privSize);
CSSM_SIZE toMove = keyData->Length;
if((uint32)rtn < toMove) {
toMove = (uint32)rtn;
}
memmove(keyData->Data, buf, toMove);
keyData->Length = toMove;
}
if(mallocdPrivKey) {
DH_free(privKey);
}
if(mallocdPubKey) {
DH_free(pubKey);
}
if(allocdPubKeyBn) {
BN_free(pubKeyBn);
}
session.free(buf);
if(rtn <= 0) {
throwRsaDsa("DH_compute_key");
}
}