X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_cryptkit/lib/feeCipherFileAtom.c diff --git a/Security/libsecurity_cryptkit/lib/feeCipherFileAtom.c b/Security/libsecurity_cryptkit/lib/feeCipherFileAtom.c new file mode 100644 index 00000000..3576551d --- /dev/null +++ b/Security/libsecurity_cryptkit/lib/feeCipherFileAtom.c @@ -0,0 +1,400 @@ +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * feeCipherFile.c + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 05 Feb 97 at Apple + * Modified to use portable byte representation. + * 23 Oct 96 at NeXT + * Created. + */ + +#include "feeCipherFile.h" +#include "falloc.h" +#include "platform.h" +#include "feeDebug.h" +#include "byteRep.h" + +#ifndef NULL +#define NULL ((void *)0) +#endif /* NULL */ + +/* + * These must match constants of same name in CipherFileAtom.java. + */ +#define CFILE_MAGIC 0xfeecf111 +#define CFILE_VERSION 1 +#define CFILE_MIN_VERSION 1 + +/* + * Format of a feeCipherFile header. + * Offsets and lengths refer to locations of components in cFileInst.dataRep. + * This struct appears at the start of a feeCipherFile data representation. + */ +typedef struct { + unsigned magic; + unsigned version; + unsigned minVersion; + unsigned totalLength; // equals dataRepLen + cipherFileEncrType encrType; + unsigned cipherTextOffset; // offset of ciphertext + unsigned cipherTextLen; // in bytes + unsigned sendPubKeyDataOffset; // optional + unsigned sendPubKeyDataLen; + unsigned otherKeyDataOffset; // optional + unsigned otherKeyDataLen; + unsigned sigDataOffset; // optional + unsigned sigDataLen; // 0 means no signature + unsigned userData; +} cFileHeader; + +/* + * Private data, represented by a feeCipherFile handle. + */ +typedef struct { + cFileHeader header; + unsigned char *dataRep; // raw data + unsigned dataRepLen; +} cFileInst; + +static unsigned lengthOfByteRepCfileHdr(void); +static unsigned cfileHdrToByteRep(cFileHeader *hdr, + unsigned char *s); +static void byteRepToCfileHdr(const unsigned char *s, + cFileHeader *hdr); + + +/* + * alloc, free cFileInst + */ +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); +} + +/* + * Alloc and return a new feeCipherFile object associated with the specified + * data. + */ +feeCipherFile feeCFileNewFromCipherText(cipherFileEncrType encrType, + const unsigned char *cipherText, + unsigned cipherTextLen, + const unsigned char *sendPubKeyData, // optional + unsigned sendPubKeyDataLen, // 0 if sendPubKeyData is NULL + const unsigned char *otherKeyData, // optional + unsigned otherKeyDataLen, // 0 if otherKeyData is NULL + const unsigned char *sigData, // optional; NULL means no signature + unsigned sigDataLen, // 0 if sigData is NULL + unsigned userData) // for caller's convenience +{ + cFileInst *cfinst; + cFileHeader *header; + unsigned char *data; + + if(cipherTextLen == 0) { + return NULL; + } + cfinst = cFileInstAlloc(); + header = &cfinst->header; + + /* + * Init the 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; + + /* + * Alloc a data representation, copy various components to it. + */ + 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; +} + +/* + * Obtain the contents of a feeCipherFile as a byte stream. + */ +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; +} + +/* + * Alloc and return a new feeCipherFile object, given a byte stream (originally + * obtained from feeCFDataRepresentation()). + */ +feeReturn feeCFileNewFromDataRep(const unsigned char *dataRep, + unsigned dataRepLen, + feeCipherFile *cipherFile) // RETURNED if sucessful +{ + 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); + + /* + * As much consistency checking as we can manage here. + */ + 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; + } + + /* + * OK, looks good. + */ + *cipherFile = (feeCipherFile)cfinst; + return FR_Success; +abort: + cFileInstFree(cfinst); + *cipherFile = NULL; + return FR_BadCipherFile; +} + +/* + * Free a feeCipherFile object. + */ +void feeCFileFree(feeCipherFile cipherFile) +{ + cFileInstFree((cFileInst *)cipherFile); +} + +/* + * Given a feeCipherFile object (typically obtained from + * feeCFileNewFromData()), obtain its constituent parts. + * + * Data returned must be freed by caller. + * feeCFileSigData() may return NULL, indicating no signature present. + */ +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 { + /* + * Not an error + */ + *sigDataLen = 0; + return NULL; + } +} + +unsigned feeCFileUserData(feeCipherFile cipherFile) +{ + cFileInst *cfinst = (cFileInst *)cipherFile; + + return cfinst->header.userData; +} + +/* + * Convert between cFileHeader and portable byte representation. + */ + +/* + * Return size of byte rep of cFileHeader. We just happen to know that + * this is the same size as the header.... + */ +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); +// DEC_INT(hdr->encrType, 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); +}