feeCipherFileAtom.c [plain text]
#include "feeCipherFile.h"
#include "falloc.h"
#include "platform.h"
#include "feeDebug.h"
#include "byteRep.h"
#ifndef NULL
#define NULL ((void *)0)
#endif
#define CFILE_MAGIC 0xfeecf111
#define CFILE_VERSION 1
#define CFILE_MIN_VERSION 1
typedef struct {
unsigned magic;
unsigned version;
unsigned minVersion;
unsigned totalLength; cipherFileEncrType encrType;
unsigned cipherTextOffset; unsigned cipherTextLen; unsigned sendPubKeyDataOffset; unsigned sendPubKeyDataLen;
unsigned otherKeyDataOffset; unsigned otherKeyDataLen;
unsigned sigDataOffset; unsigned sigDataLen; unsigned userData;
} cFileHeader;
typedef struct {
cFileHeader header;
unsigned char *dataRep; unsigned dataRepLen;
} cFileInst;
static unsigned lengthOfByteRepCfileHdr(void);
static unsigned cfileHdrToByteRep(cFileHeader *hdr,
unsigned char *s);
static void byteRepToCfileHdr(const unsigned char *s,
cFileHeader *hdr);
static cFileInst *cFileInstAlloc()
{
cFileInst *cfinst = (cFileInst *) fmalloc(sizeof(cFileInst));
bzero(cfinst, sizeof(cFileInst));
return cfinst;
}
static void cFileInstFree(cFileInst *cfinst)
{
if(cfinst->dataRep) {
ffree(cfinst->dataRep);
}
ffree(cfinst);
}
feeCipherFile feeCFileNewFromCipherText(cipherFileEncrType encrType,
const unsigned char *cipherText,
unsigned cipherTextLen,
const unsigned char *sendPubKeyData, unsigned sendPubKeyDataLen, const unsigned char *otherKeyData, unsigned otherKeyDataLen, const unsigned char *sigData, unsigned sigDataLen, unsigned userData) {
cFileInst *cfinst;
cFileHeader *header;
unsigned char *data;
if(cipherTextLen == 0) {
return NULL;
}
cfinst = cFileInstAlloc();
header = &cfinst->header;
header->magic = CFILE_MAGIC;
header->version = CFILE_VERSION;
header->minVersion = CFILE_MIN_VERSION;
header->totalLength = lengthOfByteRepCfileHdr() + cipherTextLen +
sendPubKeyDataLen + otherKeyDataLen +
sigDataLen;
header->encrType = encrType;
header->cipherTextOffset = lengthOfByteRepCfileHdr();
header->cipherTextLen = cipherTextLen;
header->sendPubKeyDataOffset = header->cipherTextOffset +
cipherTextLen;
header->sendPubKeyDataLen = sendPubKeyDataLen;
header->otherKeyDataOffset = header->sendPubKeyDataOffset +
sendPubKeyDataLen;
header->otherKeyDataLen = otherKeyDataLen;
header->sigDataOffset = header->otherKeyDataOffset +
otherKeyDataLen;
header->sigDataLen = sigDataLen;
header->userData = userData;
cfinst->dataRepLen = header->totalLength;
data = cfinst->dataRep = (unsigned char*) fmalloc(cfinst->dataRepLen);
cfileHdrToByteRep(header, data);
data = cfinst->dataRep + header->cipherTextOffset;
bcopy(cipherText, data, cipherTextLen);
if(sendPubKeyDataLen) {
data = cfinst->dataRep + header->sendPubKeyDataOffset;
bcopy(sendPubKeyData, data, sendPubKeyDataLen);
}
if(otherKeyDataLen) {
data = cfinst->dataRep + header->otherKeyDataOffset;
bcopy(otherKeyData, data, otherKeyDataLen);
}
if(sigDataLen) {
data = cfinst->dataRep + header->sigDataOffset;
bcopy(sigData, data, sigDataLen);
}
return (feeCipherFile)cfinst;
}
feeReturn feeCFileDataRepresentation(feeCipherFile cipherFile,
const unsigned char **dataRep,
unsigned *dataRepLen)
{
cFileInst *cfinst = (cFileInst *)cipherFile;
if(cfinst->dataRepLen == 0) {
*dataRep = NULL;
*dataRepLen = 0;
return FR_BadCipherFile;
}
*dataRep = (unsigned char*) fmallocWithData(cfinst->dataRep, cfinst->dataRepLen);
*dataRepLen = cfinst->dataRepLen;
return FR_Success;
}
feeReturn feeCFileNewFromDataRep(const unsigned char *dataRep,
unsigned dataRepLen,
feeCipherFile *cipherFile) {
cFileInst *cfinst = cFileInstAlloc();
cFileHeader *header;
if(dataRepLen < lengthOfByteRepCfileHdr()) {
dbgLog(("datRep too short\n"));
goto abort;
}
cfinst->dataRep = (unsigned char*) fmallocWithData(dataRep, dataRepLen);
cfinst->dataRepLen = dataRepLen;
header = &cfinst->header;
byteRepToCfileHdr(dataRep, header);
if(header->magic != CFILE_MAGIC) {
dbgLog(("Bad cipherFile magic number\n"));
goto abort;
}
if(header->minVersion > CFILE_VERSION) {
dbgLog(("Incompatible cipherFile version\n"));
goto abort;
}
if(header->totalLength != dataRepLen) {
dbgLog(("Bad totalLength in cipherFile header\n"));
goto abort;
}
if(((header->cipherTextOffset + header->cipherTextLen) >
header->totalLength) ||
((header->sendPubKeyDataOffset + header->sendPubKeyDataLen) >
header->totalLength) ||
((header->otherKeyDataOffset + header->otherKeyDataLen) >
header->totalLength) ||
((header->sigDataOffset + header->sigDataLen) >
header->totalLength)) {
dbgLog(("Bad element lengths in cipherFile header\n"));
goto abort;
}
*cipherFile = (feeCipherFile)cfinst;
return FR_Success;
abort:
cFileInstFree(cfinst);
*cipherFile = NULL;
return FR_BadCipherFile;
}
void feeCFileFree(feeCipherFile cipherFile)
{
cFileInstFree((cFileInst *)cipherFile);
}
cipherFileEncrType feeCFileEncrType(feeCipherFile cipherFile)
{
cFileInst *cfinst = (cFileInst *)cipherFile;
return cfinst->header.encrType;
}
unsigned char *feeCFileCipherText(feeCipherFile cipherFile,
unsigned *cipherTextLen)
{
cFileInst *cfinst = (cFileInst *)cipherFile;
if(cfinst->header.cipherTextLen) {
*cipherTextLen = cfinst->header.cipherTextLen;
return (unsigned char*) fmallocWithData(cfinst->dataRep +
cfinst->header.cipherTextOffset, *cipherTextLen);
}
else {
dbgLog(("feeCFileCipherText: no cipherText\n"));
*cipherTextLen = 0;
return NULL;
}
}
unsigned char *feeCFileSendPubKeyData(feeCipherFile cipherFile,
unsigned *sendPubKeyDataLen)
{
cFileInst *cfinst = (cFileInst *)cipherFile;
if(cfinst->header.sendPubKeyDataLen) {
*sendPubKeyDataLen = cfinst->header.sendPubKeyDataLen;
return (unsigned char*) fmallocWithData(cfinst->dataRep +
cfinst->header.sendPubKeyDataOffset,
*sendPubKeyDataLen);
}
else {
*sendPubKeyDataLen = 0;
return NULL;
}
}
unsigned char *feeCFileOtherKeyData(feeCipherFile cipherFile,
unsigned *otherKeyDataLen)
{
cFileInst *cfinst = (cFileInst *)cipherFile;
if(cfinst->header.otherKeyDataLen) {
*otherKeyDataLen = cfinst->header.otherKeyDataLen;
return (unsigned char*) fmallocWithData(cfinst->dataRep +
cfinst->header.otherKeyDataOffset, *otherKeyDataLen);
}
else {
*otherKeyDataLen = 0;
return NULL;
}
}
unsigned char *feeCFileSigData(feeCipherFile cipherFile,
unsigned *sigDataLen)
{
cFileInst *cfinst = (cFileInst *)cipherFile;
if(cfinst->header.sigDataLen) {
*sigDataLen = cfinst->header.sigDataLen;
return (unsigned char*) fmallocWithData(cfinst->dataRep +
cfinst->header.sigDataOffset, *sigDataLen);
}
else {
*sigDataLen = 0;
return NULL;
}
}
unsigned feeCFileUserData(feeCipherFile cipherFile)
{
cFileInst *cfinst = (cFileInst *)cipherFile;
return cfinst->header.userData;
}
static unsigned lengthOfByteRepCfileHdr(void)
{
return sizeof(cFileHeader);
}
static unsigned cfileHdrToByteRep(cFileHeader *hdr,
unsigned char *s)
{
s += intToByteRep(hdr->magic, s);
s += intToByteRep(hdr->version, s);
s += intToByteRep(hdr->minVersion, s);
s += intToByteRep(hdr->totalLength, s);
s += intToByteRep(hdr->encrType, s);
s += intToByteRep(hdr->cipherTextOffset, s);
s += intToByteRep(hdr->cipherTextLen, s);
s += intToByteRep(hdr->sendPubKeyDataOffset, s);
s += intToByteRep(hdr->sendPubKeyDataLen, s);
s += intToByteRep(hdr->otherKeyDataOffset, s);
s += intToByteRep(hdr->otherKeyDataLen, s);
s += intToByteRep(hdr->sigDataOffset, s);
s += intToByteRep(hdr->sigDataLen, s);
s += intToByteRep(hdr->userData, s);
return sizeof(cFileHeader);
}
#define DEC_INT(n, b) \
n = byteRepToInt(b); \
b += sizeof(int);
static void byteRepToCfileHdr(const unsigned char *s,
cFileHeader *hdr)
{
DEC_INT(hdr->magic, s);
DEC_INT(hdr->version, s);
DEC_INT(hdr->minVersion, s);
DEC_INT(hdr->totalLength, s);
hdr->encrType = (cipherFileEncrType) byteRepToInt(s);
s += sizeof(int);
DEC_INT(hdr->cipherTextOffset, s);
DEC_INT(hdr->cipherTextLen, s);
DEC_INT(hdr->sendPubKeyDataOffset, s);
DEC_INT(hdr->sendPubKeyDataLen, s);
DEC_INT(hdr->otherKeyDataOffset, s);
DEC_INT(hdr->otherKeyDataLen, s);
DEC_INT(hdr->sigDataOffset, s);
DEC_INT(hdr->sigDataLen, s);
DEC_INT(hdr->userData, s);
}