feeDigitalSignature.c [plain text]
#include "ckconfig.h"
#include "feeTypes.h"
#include "feePublicKey.h"
#include "feePublicKeyPrivate.h"
#include "feeDigitalSignature.h"
#include "giantIntegers.h"
#include "elliptic.h"
#include "feeRandom.h"
#include "curveParams.h"
#include "falloc.h"
#include "ckutilities.h"
#include "feeDebug.h"
#include "platform.h"
#include "byteRep.h"
#include "feeECDSA.h"
#if CRYPTKIT_DER_ENABLE
#include "CryptKitDER.h"
#endif
#include <stdlib.h>
#include "ellipticProj.h"
#define SIG_DEBUG 0
#if SIG_DEBUG
int sigDebug=1; #endif // SIG_DEBUG
#define SIG_CURVE DEFAULT_CURVE
#define RAND_JUST_X1_ORDER_PLUS 1
#define FEE_SIG_VERSION 4
#define FEE_SIG_VERSION_MIN 4
#ifndef max
#define max(a,b) ((a)>(b)? (a) : (b))
#endif // max
typedef struct {
giant PmX; #if CRYPTKIT_ELL_PROJ_ENABLE
giant PmY; #endif
giant u;
giant randGiant; } sigInst;
static sigInst *sinstAlloc()
{
sigInst *sinst = (sigInst*) fmalloc(sizeof(sigInst));
bzero(sinst, sizeof(sigInst));
return sinst;
}
feeSig feeSigNewWithKey(
feePubKey pubKey,
feeRandFcn randFcn,
void *randRef)
{
sigInst *sinst = sinstAlloc();
feeRand frand;
unsigned char *randBytes;
unsigned randBytesLen;
curveParams *cp;
if(pubKey == NULL) {
return NULL;
}
cp = feePubKeyCurveParams(pubKey);
if(cp == NULL) {
return NULL;
}
randBytesLen = (feePubKeyBitsize(pubKey) / 8) + 1 + 8; randBytes = (unsigned char*) fmalloc(randBytesLen);
if(randFcn) {
randFcn(randRef, randBytes, randBytesLen);
}
else {
frand = feeRandAlloc();
feeRandBytes(frand, randBytes, randBytesLen);
feeRandFree(frand);
}
sinst->randGiant = giant_with_data(randBytes, randBytesLen);
memset(randBytes, 0, randBytesLen);
ffree(randBytes);
#if FEE_DEBUG
if(isZero(sinst->randGiant)) {
printf("feeSigNewWithKey: randGiant = 0!\n");
}
#endif
x1OrderPlusJustify(sinst->randGiant, cp);
sinst->PmX = newGiant(cp->maxDigits);
#if CRYPTKIT_ELL_PROJ_ENABLE
if(cp->curveType == FCT_Weierstrass) {
pointProjStruct pt0;
sinst->PmY = newGiant(cp->maxDigits);
pt0.x = sinst->PmX;
pt0.y = sinst->PmY;
pt0.z = borrowGiant(cp->maxDigits);
gtog(cp->x1Plus, pt0.x);
gtog(cp->y1Plus, pt0.y);
int_to_giant(1, pt0.z);
ellMulProjSimple(&pt0, sinst->randGiant, cp);
returnGiant(pt0.z);
}
else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
if(SIG_CURVE == CURVE_PLUS) {
gtog(cp->x1Plus, sinst->PmX);
}
else {
gtog(cp->x1Minus, sinst->PmX);
}
#pragma clang diagnostic pop
elliptic_simple(sinst->PmX, sinst->randGiant, cp);
}
#else
if(SIG_CURVE == CURVE_PLUS) {
gtog(cp->x1Plus, sinst->PmX);
}
else {
gtog(cp->x1Minus, sinst->PmX);
}
elliptic_simple(sinst->PmX, sinst->randGiant, cp);
#endif
return sinst;
}
void feeSigFree(feeSig sig)
{
sigInst *sinst = (sigInst*) sig;
if(sinst->PmX) {
clearGiant(sinst->PmX);
freeGiant(sinst->PmX);
}
#if CRYPTKIT_ELL_PROJ_ENABLE
if(sinst->PmY) {
clearGiant(sinst->PmY);
freeGiant(sinst->PmY);
}
#endif
if(sinst->u) {
clearGiant(sinst->u);
freeGiant(sinst->u);
}
if(sinst->randGiant) {
clearGiant(sinst->randGiant);
freeGiant(sinst->randGiant);
}
ffree(sinst);
}
unsigned char *feeSigPm(feeSig sig,
unsigned *PmLen)
{
sigInst *sinst = (sigInst*) sig;
unsigned char *Pm;
if(sinst->PmX == NULL) {
dbgLog(("feeSigPm: no PmX!\n"));
return NULL;
}
else {
Pm = mem_from_giant(sinst->PmX, PmLen);
#if SIG_DEBUG
if(sigDebug)
{
int i;
printf("Pm : "); printGiant(sinst->PmX);
printf("PmData: ");
for(i=0; i<*PmLen; i++) {
printf("%x:", Pm[i]);
}
printf("\n");
}
#endif }
return Pm;
}
feeReturn feeSigSign(feeSig sig,
const unsigned char *data, unsigned dataLen, feePubKey pubKey)
{
sigInst *sinst = (sigInst*) sig;
giant messageGiant = NULL;
unsigned maxlen;
giant privGiant;
unsigned privGiantBytes;
feeReturn frtn = FR_Success;
unsigned randBytesLen;
unsigned uDigits; curveParams *cp;
if(pubKey == NULL) {
return FR_BadPubKey;
}
cp = feePubKeyCurveParams(pubKey);
if(cp == NULL) {
return FR_BadPubKey;
}
privGiant = feePubKeyPrivData(pubKey);
if(privGiant == NULL) {
dbgLog(("Attempt to Sign without private data\n"));
frtn = FR_IllegalArg;
goto abort;
}
privGiantBytes = abs(privGiant->sign) * GIANT_BYTES_PER_DIGIT;
messageGiant = giant_with_data(data, dataLen); randBytesLen = feePubKeyBitsize(pubKey) / 8;
maxlen = max(randBytesLen, dataLen);
uDigits = (3 * (privGiantBytes + maxlen)) / GIANT_BYTES_PER_DIGIT;
sinst->u = newGiant(uDigits);
gtog(privGiant, sinst->u); mulg(messageGiant, sinst->u); addg(sinst->randGiant, sinst->u);
calcX1OrderPlusRecip(cp);
#if SIG_DEBUG
if(sigDebug) {
printf("sigSign:\n");
printf("u pre-modg : ");
printGiant(sinst->u);
}
#endif
modg_via_recip(cp->x1OrderPlus, cp->x1OrderPlusRecip, sinst->u);
#if SIG_DEBUG
if(sigDebug) {
printf("privGiant : ");
printGiant(privGiant);
printf("u : ");
printGiant(sinst->u);
printf("messageGiant: ");
printGiant(messageGiant);
printf("curveParams :\n");
printCurveParams(cp);
}
#endif abort:
if(messageGiant) {
freeGiant(messageGiant);
}
return frtn;
}
feeReturn feeSigData(feeSig sig,
unsigned char **sigData, unsigned *sigDataLen) {
sigInst *sinst = (sigInst*) sig;
#if CRYPTKIT_DER_ENABLE
return feeDEREncodeElGamalSignature(sinst->u, sinst->PmX, sigData, sigDataLen);
#else
*sigDataLen = lengthOfByteRepSig(sinst->u, sinst->PmX);
*sigData = (unsigned char*) fmalloc(*sigDataLen);
sigToByteRep(FEE_SIG_MAGIC,
FEE_SIG_VERSION,
FEE_SIG_VERSION_MIN,
sinst->u,
sinst->PmX,
*sigData);
return FR_Success;
#endif
}
feeReturn feeSigParse(const unsigned char *sigData,
size_t sigDataLen,
feeSig *sig) {
sigInst *sinst = NULL;
feeReturn frtn;
#if !CRYPTKIT_DER_ENABLE
int version;
int magic;
int minVersion;
int rtn;
#endif
sinst = sinstAlloc();
#if CRYPTKIT_DER_ENABLE
frtn = feeDERDecodeElGamalSignature(sigData, sigDataLen, &sinst->u, &sinst->PmX);
if(frtn) {
goto abort;
}
#else
rtn = byteRepToSig(sigData,
sigDataLen,
FEE_SIG_VERSION,
&magic,
&version,
&minVersion,
&sinst->u,
&sinst->PmX);
if(rtn == 0) {
frtn = FR_BadSignatureFormat;
goto abort;
}
switch(magic) {
case FEE_ECDSA_MAGIC:
frtn = FR_WrongSignatureType; goto abort;
case FEE_SIG_MAGIC:
break; default:
frtn = FR_BadSignatureFormat;
goto abort;
}
#endif
#if SIG_DEBUG
if(sigDebug) {
printf("sigParse: \n");
printf("u: ");
printGiant(sinst->u);
}
#endif
*sig = sinst;
return FR_Success;
abort:
if(sinst) {
feeSigFree(sinst);
}
return frtn;
}
#define LOG_BAD_SIG 0
#if CRYPTKIT_ELL_PROJ_ENABLE
feeReturn feeSigVerifyNoProj(feeSig sig,
const unsigned char *data,
unsigned dataLen,
feePubKey pubKey);
static void borrowPointProj(pointProj pt, unsigned maxDigits)
{
pt->x = borrowGiant(maxDigits);
pt->y = borrowGiant(maxDigits);
pt->z = borrowGiant(maxDigits);
}
static void returnPointProj(pointProj pt)
{
returnGiant(pt->x);
returnGiant(pt->y);
returnGiant(pt->z);
}
feeReturn feeSigVerify(feeSig sig,
const unsigned char *data,
unsigned dataLen,
feePubKey pubKey)
{
pointProjStruct Q;
giant messageGiant = NULL;
pointProjStruct scratch;
sigInst *sinst = (sigInst*) sig;
feeReturn frtn;
curveParams *cp;
key origKey;
if(sinst->PmX == NULL) {
dbgLog(("sigVerify without parse!\n"));
return FR_IllegalArg;
}
cp = feePubKeyCurveParams(pubKey);
if(cp->curveType != FCT_Weierstrass) {
return feeSigVerifyNoProj(sig, data, dataLen, pubKey);
}
borrowPointProj(&Q, cp->maxDigits);
borrowPointProj(&scratch, cp->maxDigits);
gtog(cp->x1Plus, Q.x);
gtog(cp->y1Plus, Q.y);
int_to_giant(1, Q.z);
messageGiant = giant_with_data(data, dataLen);
ellMulProjSimple(&Q, sinst->u, cp);
origKey = feePubKeyPlusCurve(pubKey);
gtog(origKey->x, scratch.x);
gtog(origKey->y, scratch.y);
int_to_giant(1, scratch.z);
#if SIG_DEBUG
if(sigDebug) {
printf("verify origKey:\n");
printKey(origKey);
printf("messageGiant: ");
printGiant(messageGiant);
printf("curveParams:\n");
printCurveParams(cp);
}
#endif
ellMulProjSimple(&scratch, messageGiant, cp);
#if SIG_DEBUG
if(sigDebug) {
printf("signature_compare, with\n");
printf("p0 = Q:\n");
printGiant(Q.x);
printf("p1 = Pm:\n");
printGiant(sinst->PmX);
printf("p2 = scratch = R:\n");
printGiant(scratch.x);
}
#endif
if(signature_compare(Q.x, sinst->PmX, scratch.x, cp)) {
frtn = FR_InvalidSignature;
#if LOG_BAD_SIG
printf("***yup, bad sig***\n");
#endif }
else {
frtn = FR_Success;
}
freeGiant(messageGiant);
returnPointProj(&Q);
returnPointProj(&scratch);
return frtn;
}
#else
#define feeSigVerifyNoProj(s, d, l, k) feeSigVerify(s, d, l, k)
#endif
feeReturn feeSigVerifyNoProj(feeSig sig,
const unsigned char *data,
unsigned dataLen,
feePubKey pubKey)
{
giant Q = NULL;
giant messageGiant = NULL;
giant scratch = NULL;
sigInst *sinst = (sigInst*) sig;
feeReturn frtn;
curveParams *cp;
key origKey;
if(sinst->PmX == NULL) {
dbgLog(("sigVerify without parse!\n"));
frtn = FR_IllegalArg;
goto out;
}
cp = feePubKeyCurveParams(pubKey);
Q = newGiant(cp->maxDigits);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
if(SIG_CURVE == CURVE_PLUS) {
origKey = feePubKeyPlusCurve(pubKey);
gtog(cp->x1Plus, Q);
}
else {
origKey = feePubKeyMinusCurve(pubKey);
gtog(cp->x1Minus, Q);
}
#pragma clang diagnostic pop
messageGiant = giant_with_data(data, dataLen);
elliptic_simple(Q, sinst->u, cp);
scratch = newGiant(cp->maxDigits);
gtog(origKey->x, scratch);
#if SIG_DEBUG
if(sigDebug) {
printf("verify origKey:\n");
printKey(origKey);
printf("messageGiant: ");
printGiant(messageGiant);
printf("curveParams:\n");
printCurveParams(cp);
}
#endif
elliptic_simple(scratch, messageGiant, cp);
#if SIG_DEBUG
if(sigDebug) {
printf("signature_compare, with\n");
printf("p0 = Q:\n");
printGiant(Q);
printf("p1 = Pm:\n");
printGiant(sinst->PmX);
printf("p2 = scratch = R:\n");
printGiant(scratch);
}
#endif
if(signature_compare(Q, sinst->PmX, scratch, cp)) {
frtn = FR_InvalidSignature;
#if LOG_BAD_SIG
printf("***yup, bad sig***\n");
#endif }
else {
frtn = FR_Success;
}
out:
if(messageGiant != NULL) {
freeGiant(messageGiant);
}
if(Q != NULL) {
freeGiant(Q);
}
if(scratch != NULL) {
freeGiant(scratch);
}
return frtn;
}
feeReturn feeSigSize(
feePubKey pubKey,
unsigned *maxSigLen)
{
curveParams *cp = feePubKeyCurveParams(pubKey);
if(cp == NULL) {
return FR_BadPubKey;
}
#if CRYPTKIT_DER_ENABLE
*maxSigLen = feeSizeOfDERSig(cp->basePrime, cp->basePrime);
#else
*maxSigLen = (unsigned)lengthOfByteRepSig(cp->basePrime, cp->basePrime);
#endif
return FR_Success;
}