]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_cryptkit/lib/feeCipherFileAtom.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / libsecurity_cryptkit / lib / feeCipherFileAtom.c
diff --git a/OSX/libsecurity_cryptkit/lib/feeCipherFileAtom.c b/OSX/libsecurity_cryptkit/lib/feeCipherFileAtom.c
new file mode 100644 (file)
index 0000000..3576551
--- /dev/null
@@ -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);
+}