#include <CommonCrypto/CommonDH.h>
#include <CommonCrypto/CommonRandomSPI.h>
#include "ccDispatch.h"
#include <corecrypto/ccn.h>
#include <corecrypto/ccdh.h>
#include <corecrypto/ccdh_gp.h>
#include "ccMemory.h"
#include "ccErrors.h"
#include "ccGlobals.h"
#include "ccdebug.h"
typedef struct CCDHParameters_s {
ccdh_const_gp_t gp;
size_t malloced;
} CCDHParmSetstruct, *CCDHParmSet;
typedef struct DH_ {
CCDHParmSet parms;
ccdh_full_ctx_t ctx;
} CCDHstruct, *CCDH;
static void kCCDHRFC2409Group2_storage(void) {}
static void kCCDHRFC3526Group5_storage(void) {}
const CCDHParameters kCCDHRFC2409Group2 = (CCDHParameters)&kCCDHRFC2409Group2_storage;
const CCDHParameters kCCDHRFC3526Group5 = (CCDHParameters)&kCCDHRFC3526Group5_storage;
CCDHRef
CCDHCreate(CCDHParameters dhParameter)
{
CCDHParmSet CCDHParm = (CCDHParmSet)dhParameter;
CCDHParmSet stockParm = NULL;
CCDH retval = NULL;
size_t retSize = 0;
CC_DEBUG_LOG("Entering\n");
CC_NONULLPARMRETNULL(dhParameter);
if (dhParameter == kCCDHRFC2409Group2) {
stockParm = CC_XMALLOC(sizeof(CCDHParmSetstruct));
stockParm->gp = ccdh_gp_rfc2409group02();
stockParm->malloced = true;
CCDHParm = stockParm;
} else if (dhParameter == kCCDHRFC3526Group5) {
stockParm = CC_XMALLOC(sizeof(CCDHParmSetstruct));
stockParm->gp = ccdh_gp_rfc3526group05();
stockParm->malloced = true;
CCDHParm = stockParm;
} else {
}
retval = CC_XMALLOC(sizeof(CCDHstruct));
if(retval == NULL) goto error;
retSize = ccdh_full_ctx_size(ccdh_ccn_size(CCDHParm->gp));
retval->ctx = CC_XMALLOC(retSize);
if(retval->ctx == NULL) goto error;
ccdh_ctx_init(CCDHParm->gp, ccdh_ctx_public(retval->ctx));
retval->parms = CCDHParm;
return (CCDHRef) retval;
error:
if(stockParm) CC_XFREE(stockParm, sizeof(CCDHParmSetstruct));
if(retval) CC_XFREE(retval, retSize);
return NULL;
}
void
CCDHRelease(CCDHRef ref)
{
CC_DEBUG_LOG("Entering\n");
if(ref == NULL) return;
CCDH keyref = (CCDH) ref;
if(keyref->ctx)
CC_XFREE(keyref->ctx, ccdh_full_ctx_size(ccdh_ccn_size(keyref->parms->gp)));
keyref->ctx = NULL;
CC_XFREE(keyref->parms, sizeof(CCDHParmSetstruct));
keyref->parms = NULL;
CC_XFREE(keyref, sizeof(CCDHstruct));
}
int
CCDHGenerateKey(CCDHRef ref, void *output, size_t *outputLength)
{
CC_DEBUG_LOG("Entering\n");
CC_NONULLPARM(ref);
CC_NONULLPARM(output);
CC_NONULLPARM(outputLength);
CCDH keyref = (CCDH) ref;
if(ccdh_generate_key(keyref->parms->gp, ccDRBGGetRngState(), keyref->ctx))
return -1;
size_t size_needed = ccdh_export_pub_size(ccdh_ctx_public(keyref->ctx));
if(size_needed > *outputLength) {
*outputLength = size_needed;
return -1;
}
*outputLength = size_needed;
ccdh_export_pub(ccdh_ctx_public(keyref->ctx), output);
return 0;
}
int
CCDHComputeKey(unsigned char *sharedKey, size_t *sharedKeyLen, const void *peerPubKey, size_t peerPubKeyLen, CCDHRef ref)
{
CC_DEBUG_LOG("Entering\n");
CC_NONULLPARM(sharedKey);
CC_NONULLPARM(sharedKeyLen);
CC_NONULLPARM(peerPubKey);
CC_NONULLPARM(ref);
CCDH keyref = (CCDH) ref;
ccdh_pub_ctx_decl_gp(keyref->parms->gp, peer_pub);
cc_size n = ccdh_ctx_n(keyref->ctx);
cc_unit skey[n];
if(ccdh_import_pub(keyref->parms->gp, peerPubKeyLen, peerPubKey,
peer_pub))
return -1;
if(ccdh_compute_key(keyref->ctx, peer_pub, skey))
return -1;
size_t size_needed = ccn_write_uint_size(n, skey);
if(size_needed > *sharedKeyLen) {
*sharedKeyLen = size_needed;
return -1;
}
*sharedKeyLen = size_needed;
(void) ccn_write_uint_padded(n, skey, *sharedKeyLen, sharedKey);
return 0;
}
CCDHParameters
CCDHParametersCreateFromData(const void *p, size_t pLen, const void *g, size_t gLen, size_t l)
{
CC_DEBUG_LOG("Entering\n");
CC_NONULLPARMRETNULL(p);
CC_NONULLPARMRETNULL(g);
cc_size psize = ccn_nof_size(pLen);
cc_size gsize = ccn_nof_size(gLen);
cc_size n = (psize > gsize) ? psize: gsize;
cc_unit pval[n], gval[n];
CCDHParmSet retval = CC_XMALLOC(sizeof(CCDHParmSetstruct));
if(!retval) goto error;
retval->malloced = ccdh_gp_size(n);
retval->gp = CC_XMALLOC(retval->malloced);
if(retval->gp==NULL) goto error;
if(ccdh_init_gp((ccdh_gp_t)retval->gp, n, pval, gval, (cc_size) l)) goto error;
return retval;
error:
if(retval && retval->gp) CC_XFREE((ccdh_gp_t)retval->gp, retval->malloced); if(retval) CC_XFREE(retval, sizeof(CCDHParmSetstruct));
return NULL;
}
void
CCDHParametersRelease(CCDHParameters parameters)
{
CC_DEBUG_LOG("Entering\n");
if(parameters == NULL) return;
if(parameters == kCCDHRFC2409Group2) return;
if(parameters == kCCDHRFC3526Group5) return;
CCDHParmSet CCDHParm = (CCDHParmSet) parameters;
if(CCDHParm->malloced) {
CC_XFREE((ccdh_gp_t)parameters->gp, retval->malloced); }
CCDHParm->malloced = 0;
CCDHParm->gp = NULL;
CC_XFREE(CCDHParm, sizeof(CCDHParmSetstruct));
}
CCDHParameters
CCDHParametersCreateFromPKCS3(const void *data, size_t __unused len)
{
CC_DEBUG_LOG("Entering\n");
CC_NONULLPARMRETNULL(data);
return NULL;
}
size_t
CCDHParametersPKCS3EncodeLength(CCDHParameters __unused parms)
{
CC_DEBUG_LOG("Entering\n");
return 0;
}
size_t
CCDHParametersPKCS3Encode(CCDHParameters __unused parms, void * __unused data, size_t __unused dataAvailable)
{
CC_DEBUG_LOG("Entering\n");
return 0;
}