#include "byteRep.h"
#include "feeTypes.h"
#include "curveParams.h"
#include "giantIntegers.h"
#include "elliptic.h"
#include "falloc.h"
#include "ckutilities.h"
#include "feeDebug.h"
#include <stdlib.h>
#ifndef NULL
#define NULL ((void *)0)
#endif
#define ENC_BYTE(n, b, bytes) \
*b++ = n; \
bytes++;
#define ENC_INT(n, b, bytes, i) \
i = intToByteRep(n, b); \
bytes += i; \
b += i;
#define ENC_GIANT(g, b, bytes, i) \
i = giantToByteRep(g, b); \
bytes += i; \
b += i;
#define DEC_BYTE(n, b, blen, bytes) \
n = *b++; \
bytes++; \
blen--;
#define DEC_INT(n, b, blen, bytes) \
n = byteRepToInt(b); \
b += sizeof(int); \
bytes += sizeof(int); \
blen -= gLen;
#define DEC_GIANT(g, b, blen, glen, bytes, out) \
g = byteRepToGiant(b, blen, &glen); \
if(g == NULL) { \
goto out; \
} \
b += glen; \
bytes += glen; \
blen -= gLen;
int intToByteRep(int i, unsigned char *buf)
{
*buf++ = (unsigned char)((i >> 24) & 0xff);
*buf++ = (unsigned char)((i >> 16) & 0xff);
*buf++ = (unsigned char)((i >> 8) & 0xff);
*buf = (unsigned char)(i & 0xff);
return 4;
}
int shortToByteRep(short s, unsigned char *buf)
{
*buf++ = (unsigned char)((s >> 8) & 0xff);
*buf = (unsigned char)(s & 0xff);
return 2;
}
int giantToByteRep(giant g, unsigned char *buf)
{
int numBytes = g->sign * GIANT_BYTES_PER_DIGIT;
unsigned aNumBytes = abs(numBytes);
CKASSERT(g != NULL);
intToByteRep(numBytes, buf);
buf += sizeof(int);
serializeGiant(g, buf, aNumBytes);
return (sizeof(int) + aNumBytes);
}
int keyToByteRep(key k, unsigned char *buf)
{
int numBytes = 0;
int i;
CKASSERT(k != NULL);
ENC_GIANT(k->x, buf, numBytes, i);
if(k->twist == CURVE_PLUS) {
CKASSERT(k->y != NULL);
ENC_GIANT(k->y, buf, numBytes, i);
}
return numBytes;
}
#define CURVE_PARAM_VERSION 3
#define CURVE_PARAM_VERSION_MIN 3
int curveParamsToByteRep(curveParams *cp, unsigned char *buf)
{
int numBytes = 0;
int i;
CKASSERT(cp != NULL);
ENC_INT(CURVE_PARAM_VERSION, buf, numBytes, i);
ENC_INT(CURVE_PARAM_VERSION_MIN, buf, numBytes, i);
ENC_BYTE(cp->primeType, buf, numBytes);
ENC_BYTE(cp->curveType, buf, numBytes);
ENC_INT(cp->q, buf, numBytes, i);
ENC_INT(cp->k, buf, numBytes, i);
ENC_INT(cp->m, buf, numBytes, i);
ENC_INT(0, buf, numBytes, i);
ENC_GIANT(cp->a, buf, numBytes, i);
ENC_GIANT(cp->b, buf, numBytes, i);
ENC_GIANT(cp->c, buf, numBytes, i);
ENC_GIANT(cp->x1Plus, buf, numBytes, i);
ENC_GIANT(cp->x1Minus, buf, numBytes, i);
ENC_GIANT(cp->cOrderPlus, buf, numBytes, i);
ENC_GIANT(cp->cOrderMinus, buf, numBytes, i);
ENC_GIANT(cp->x1OrderPlus, buf, numBytes, i);
ENC_GIANT(cp->x1OrderMinus, buf, numBytes, i);
if(cp->primeType == FPT_General) {
ENC_GIANT(cp->basePrime, buf, numBytes, i);
}
return numBytes;
}
int sigToByteRep(int magic,
int version,
int minVersion,
giant g0,
giant g1,
unsigned char *buf)
{
int numBytes = 0;
int i;
ENC_INT(magic, buf, numBytes, i);
ENC_INT(version, buf, numBytes, i);
ENC_INT(minVersion, buf, numBytes, i);
ENC_INT(0, buf, numBytes, i); ENC_GIANT(g0, buf, numBytes, i);
ENC_GIANT(g1, buf, numBytes, i);
return numBytes;
}
int lengthOfByteRepGiant(giant g)
{
CKASSERT(g != NULL);
return sizeof(int) + (GIANT_BYTES_PER_DIGIT * abs(g->sign));
}
int lengthOfByteRepKey(key k)
{
int len = lengthOfByteRepGiant(k->x);
CKASSERT(k != NULL);
if(k->twist == CURVE_PLUS) {
CKASSERT(k->y != NULL);
len += lengthOfByteRepGiant(k->y);
}
return len;
}
int lengthOfByteRepCurveParams(curveParams *cp)
{
int length;
CKASSERT(cp != NULL);
length = (6 * sizeof(int)) + 2 + lengthOfByteRepGiant(cp->a) +
lengthOfByteRepGiant(cp->b) +
lengthOfByteRepGiant(cp->c) +
lengthOfByteRepGiant(cp->x1Plus) +
lengthOfByteRepGiant(cp->x1Minus) +
lengthOfByteRepGiant(cp->cOrderPlus) +
lengthOfByteRepGiant(cp->cOrderMinus) +
lengthOfByteRepGiant(cp->x1OrderPlus) +
lengthOfByteRepGiant(cp->x1OrderMinus);
if(cp->primeType == FPT_General) {
length += lengthOfByteRepGiant(cp->basePrime);
}
return length;
}
int lengthOfByteRepSig(giant g0,
giant g1)
{
int length = (4 * sizeof(int)) + lengthOfByteRepGiant(g0) +
lengthOfByteRepGiant(g1);
return length;
}
int byteRepToInt(const unsigned char *buf) {
int result;
result = (((int)buf[0] << 24) & 0xff000000) |
(((int)buf[1] << 16) & 0x00ff0000) |
(((int)buf[2] << 8) & 0xff00) |
(((int)buf[3]) & 0xff);
return result;
}
unsigned short byteRepToShort(const unsigned char *buf) {
unsigned short result;
result = (((unsigned short)buf[0] << 8) & 0xff00) |
(((unsigned short)buf[1]) & 0xff);
return result;
}
giant byteRepToGiant(const unsigned char *buf,
unsigned bufLen,
unsigned *giantLen)
{
giant g;
int numDigits;
int numBytes; unsigned aNumBytes;
if(bufLen < sizeof(int)) {
return (giant)NULL;
}
numBytes = byteRepToInt(buf);
aNumBytes = abs(numBytes);
numDigits = BYTES_TO_GIANT_DIGITS(aNumBytes);
buf += sizeof(int);
bufLen -= sizeof(int);
if(numDigits > MAX_DIGITS) {
return (giant)NULL;
}
if(bufLen < aNumBytes) {
return (giant)NULL;
}
if(aNumBytes == 0) {
g = (giant)fmalloc(sizeof(giantstruct));
g->capacity = 1;
}
else {
g = (giant)fmalloc(sizeof(giantstruct) +
aNumBytes - GIANT_BYTES_PER_DIGIT);
g->capacity = numDigits;
}
deserializeGiant(buf, g, aNumBytes);
if(numBytes < 0) {
g->sign = -g->sign;
}
*giantLen = sizeof(int) + aNumBytes;
return g;
}
key byteRepToKey(const unsigned char *buf,
unsigned bufLen,
int twist,
curveParams *cp,
unsigned *keyLen) {
key k;
giant x;
giant y;
unsigned gLen;
unsigned totalLen;
x = byteRepToGiant(buf, bufLen, &gLen);
if(x == NULL) {
return NULL;
}
bufLen -= gLen;
buf += gLen;
totalLen = gLen;
if(twist == CURVE_PLUS) {
y = byteRepToGiant(buf, bufLen, &gLen);
if(y == NULL) {
freeGiant(x);
return NULL;
}
totalLen += gLen;
}
else {
y = newGiant(1);
int_to_giant(0, y);
}
k = (key)fmalloc(sizeof(keystruct));
k->twist = twist;
k->cp = cp;
k->x = x;
k->y = y;
*keyLen = totalLen;
return k;
}
curveParams *byteRepToCurveParams(const unsigned char *buf,
unsigned bufLen,
unsigned *cpLen)
{
curveParams *cp;
unsigned gLen = 0;
int version;
int minVersion;
int spare;
int bytes = 0;
if(bufLen < (5 * sizeof(int))) { return NULL;
}
cp = newCurveParams();
DEC_INT(version, buf, bufLen, bytes);
DEC_INT(minVersion, buf, bufLen, bytes);
if(minVersion > CURVE_PARAM_VERSION) {
goto abort;
}
DEC_BYTE(cp->primeType, buf, bufLen, bytes);
DEC_BYTE(cp->curveType, buf, bufLen, bytes);
DEC_INT(cp->q, buf, bufLen, bytes);
DEC_INT(cp->k, buf, bufLen, bytes);
DEC_INT(cp->m, buf, bufLen, bytes);
DEC_INT(spare, buf, bufLen, bytes);
DEC_GIANT(cp->a, buf, bufLen, gLen, bytes, abort);
DEC_GIANT(cp->b, buf, bufLen, gLen, bytes, abort);
DEC_GIANT(cp->c, buf, bufLen, gLen, bytes, abort);
DEC_GIANT(cp->x1Plus, buf, bufLen, gLen, bytes, abort);
DEC_GIANT(cp->x1Minus, buf, bufLen, gLen, bytes, abort);
DEC_GIANT(cp->cOrderPlus, buf, bufLen, gLen, bytes, abort);
DEC_GIANT(cp->cOrderMinus, buf, bufLen, gLen, bytes, abort);
DEC_GIANT(cp->x1OrderPlus, buf, bufLen, gLen, bytes, abort);
DEC_GIANT(cp->x1OrderMinus, buf, bufLen, gLen, bytes, abort);
if(cp->primeType == FPT_General) {
DEC_GIANT(cp->basePrime, buf, bufLen, gLen, bytes, abort);
}
curveParamsInferFields(cp);
allocRecipGiants(cp);
*cpLen = bytes;
return cp;
abort:
freeCurveParams(cp);
return NULL;
}
int byteRepToSig(const unsigned char *buf,
unsigned bufLen,
int codeVersion,
int *sigMagic, int *sigVersion, int *sigMinVersion, giant *g0, giant *g1) {
unsigned gLen = 0;
int spare;
int bytes = 0;
if(bufLen < (4 * sizeof(int))) { return 0;
}
DEC_INT(*sigMagic, buf, bufLen, bytes);
DEC_INT(*sigVersion, buf, bufLen, bytes);
DEC_INT(*sigMinVersion, buf, bufLen, bytes);
if(*sigMinVersion > codeVersion) {
return 0;
}
DEC_INT(spare, buf, bufLen, bytes);
DEC_GIANT(*g0, buf, bufLen, gLen, bytes, abort);
DEC_GIANT(*g1, buf, bufLen, gLen, bytes, abort);
return 1;
abort:
return 0;
}