1 /* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved.
3 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
4 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
5 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE
6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE,
7 * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
8 * EXPOSE YOU TO LIABILITY.
9 ***************************************************************************
16 * Changed to compile with C++.
18 * Modified to use portable byte representation.
23 #include "feeCipherFile.h"
30 #define NULL ((void *)0)
34 * These must match constants of same name in CipherFileAtom.java.
36 #define CFILE_MAGIC 0xfeecf111
37 #define CFILE_VERSION 1
38 #define CFILE_MIN_VERSION 1
41 * Format of a feeCipherFile header.
42 * Offsets and lengths refer to locations of components in cFileInst.dataRep.
43 * This struct appears at the start of a feeCipherFile data representation.
49 unsigned totalLength
; // equals dataRepLen
50 cipherFileEncrType encrType
;
51 unsigned cipherTextOffset
; // offset of ciphertext
52 unsigned cipherTextLen
; // in bytes
53 unsigned sendPubKeyDataOffset
; // optional
54 unsigned sendPubKeyDataLen
;
55 unsigned otherKeyDataOffset
; // optional
56 unsigned otherKeyDataLen
;
57 unsigned sigDataOffset
; // optional
58 unsigned sigDataLen
; // 0 means no signature
63 * Private data, represented by a feeCipherFile handle.
67 unsigned char *dataRep
; // raw data
71 static unsigned lengthOfByteRepCfileHdr(void);
72 static unsigned cfileHdrToByteRep(cFileHeader
*hdr
,
74 static void byteRepToCfileHdr(const unsigned char *s
,
79 * alloc, free cFileInst
81 static cFileInst
*cFileInstAlloc()
83 cFileInst
*cfinst
= (cFileInst
*) fmalloc(sizeof(cFileInst
));
85 bzero(cfinst
, sizeof(cFileInst
));
89 static void cFileInstFree(cFileInst
*cfinst
)
92 ffree(cfinst
->dataRep
);
98 * Alloc and return a new feeCipherFile object associated with the specified
101 feeCipherFile
feeCFileNewFromCipherText(cipherFileEncrType encrType
,
102 const unsigned char *cipherText
,
103 unsigned cipherTextLen
,
104 const unsigned char *sendPubKeyData
, // optional
105 unsigned sendPubKeyDataLen
, // 0 if sendPubKeyData is NULL
106 const unsigned char *otherKeyData
, // optional
107 unsigned otherKeyDataLen
, // 0 if otherKeyData is NULL
108 const unsigned char *sigData
, // optional; NULL means no signature
109 unsigned sigDataLen
, // 0 if sigData is NULL
110 unsigned userData
) // for caller's convenience
116 if(cipherTextLen
== 0) {
119 cfinst
= cFileInstAlloc();
120 header
= &cfinst
->header
;
125 header
->magic
= CFILE_MAGIC
;
126 header
->version
= CFILE_VERSION
;
127 header
->minVersion
= CFILE_MIN_VERSION
;
128 header
->totalLength
= lengthOfByteRepCfileHdr() + cipherTextLen
+
129 sendPubKeyDataLen
+ otherKeyDataLen
+
131 header
->encrType
= encrType
;
132 header
->cipherTextOffset
= lengthOfByteRepCfileHdr();
133 header
->cipherTextLen
= cipherTextLen
;
134 header
->sendPubKeyDataOffset
= header
->cipherTextOffset
+
136 header
->sendPubKeyDataLen
= sendPubKeyDataLen
;
137 header
->otherKeyDataOffset
= header
->sendPubKeyDataOffset
+
139 header
->otherKeyDataLen
= otherKeyDataLen
;
140 header
->sigDataOffset
= header
->otherKeyDataOffset
+
142 header
->sigDataLen
= sigDataLen
;
143 header
->userData
= userData
;
146 * Alloc a data representation, copy various components to it.
148 cfinst
->dataRepLen
= header
->totalLength
;
149 data
= cfinst
->dataRep
= (unsigned char*) fmalloc(cfinst
->dataRepLen
);
150 cfileHdrToByteRep(header
, data
);
152 data
= cfinst
->dataRep
+ header
->cipherTextOffset
;
153 bcopy(cipherText
, data
, cipherTextLen
);
154 if(sendPubKeyDataLen
) {
155 data
= cfinst
->dataRep
+ header
->sendPubKeyDataOffset
;
156 bcopy(sendPubKeyData
, data
, sendPubKeyDataLen
);
158 if(otherKeyDataLen
) {
159 data
= cfinst
->dataRep
+ header
->otherKeyDataOffset
;
160 bcopy(otherKeyData
, data
, otherKeyDataLen
);
163 data
= cfinst
->dataRep
+ header
->sigDataOffset
;
164 bcopy(sigData
, data
, sigDataLen
);
166 return (feeCipherFile
)cfinst
;
170 * Obtain the contents of a feeCipherFile as a byte stream.
172 feeReturn
feeCFileDataRepresentation(feeCipherFile cipherFile
,
173 const unsigned char **dataRep
,
174 unsigned *dataRepLen
)
176 cFileInst
*cfinst
= (cFileInst
*)cipherFile
;
178 if(cfinst
->dataRepLen
== 0) {
181 return FR_BadCipherFile
;
183 *dataRep
= (unsigned char*) fmallocWithData(cfinst
->dataRep
, cfinst
->dataRepLen
);
184 *dataRepLen
= cfinst
->dataRepLen
;
189 * Alloc and return a new feeCipherFile object, given a byte stream (originally
190 * obtained from feeCFDataRepresentation()).
192 feeReturn
feeCFileNewFromDataRep(const unsigned char *dataRep
,
194 feeCipherFile
*cipherFile
) // RETURNED if sucessful
196 cFileInst
*cfinst
= cFileInstAlloc();
199 if(dataRepLen
< lengthOfByteRepCfileHdr()) {
200 dbgLog(("datRep too short\n"));
203 cfinst
->dataRep
= (unsigned char*) fmallocWithData(dataRep
, dataRepLen
);
204 cfinst
->dataRepLen
= dataRepLen
;
205 header
= &cfinst
->header
;
206 byteRepToCfileHdr(dataRep
, header
);
209 * As much consistency checking as we can manage here.
211 if(header
->magic
!= CFILE_MAGIC
) {
212 dbgLog(("Bad cipherFile magic number\n"));
215 if(header
->minVersion
> CFILE_VERSION
) {
216 dbgLog(("Incompatible cipherFile version\n"));
219 if(header
->totalLength
!= dataRepLen
) {
220 dbgLog(("Bad totalLength in cipherFile header\n"));
223 if(((header
->cipherTextOffset
+ header
->cipherTextLen
) >
224 header
->totalLength
) ||
225 ((header
->sendPubKeyDataOffset
+ header
->sendPubKeyDataLen
) >
226 header
->totalLength
) ||
227 ((header
->otherKeyDataOffset
+ header
->otherKeyDataLen
) >
228 header
->totalLength
) ||
229 ((header
->sigDataOffset
+ header
->sigDataLen
) >
230 header
->totalLength
)) {
231 dbgLog(("Bad element lengths in cipherFile header\n"));
238 *cipherFile
= (feeCipherFile
)cfinst
;
241 cFileInstFree(cfinst
);
243 return FR_BadCipherFile
;
247 * Free a feeCipherFile object.
249 void feeCFileFree(feeCipherFile cipherFile
)
251 cFileInstFree((cFileInst
*)cipherFile
);
255 * Given a feeCipherFile object (typically obtained from
256 * feeCFileNewFromData()), obtain its constituent parts.
258 * Data returned must be freed by caller.
259 * feeCFileSigData() may return NULL, indicating no signature present.
261 cipherFileEncrType
feeCFileEncrType(feeCipherFile cipherFile
)
263 cFileInst
*cfinst
= (cFileInst
*)cipherFile
;
265 return cfinst
->header
.encrType
;
268 unsigned char *feeCFileCipherText(feeCipherFile cipherFile
,
269 unsigned *cipherTextLen
)
271 cFileInst
*cfinst
= (cFileInst
*)cipherFile
;
273 if(cfinst
->header
.cipherTextLen
) {
274 *cipherTextLen
= cfinst
->header
.cipherTextLen
;
275 return (unsigned char*) fmallocWithData(cfinst
->dataRep
+
276 cfinst
->header
.cipherTextOffset
, *cipherTextLen
);
279 dbgLog(("feeCFileCipherText: no cipherText\n"));
285 unsigned char *feeCFileSendPubKeyData(feeCipherFile cipherFile
,
286 unsigned *sendPubKeyDataLen
)
288 cFileInst
*cfinst
= (cFileInst
*)cipherFile
;
290 if(cfinst
->header
.sendPubKeyDataLen
) {
291 *sendPubKeyDataLen
= cfinst
->header
.sendPubKeyDataLen
;
292 return (unsigned char*) fmallocWithData(cfinst
->dataRep
+
293 cfinst
->header
.sendPubKeyDataOffset
,
297 *sendPubKeyDataLen
= 0;
302 unsigned char *feeCFileOtherKeyData(feeCipherFile cipherFile
,
303 unsigned *otherKeyDataLen
)
305 cFileInst
*cfinst
= (cFileInst
*)cipherFile
;
307 if(cfinst
->header
.otherKeyDataLen
) {
308 *otherKeyDataLen
= cfinst
->header
.otherKeyDataLen
;
309 return (unsigned char*) fmallocWithData(cfinst
->dataRep
+
310 cfinst
->header
.otherKeyDataOffset
, *otherKeyDataLen
);
313 *otherKeyDataLen
= 0;
318 unsigned char *feeCFileSigData(feeCipherFile cipherFile
,
319 unsigned *sigDataLen
)
321 cFileInst
*cfinst
= (cFileInst
*)cipherFile
;
323 if(cfinst
->header
.sigDataLen
) {
324 *sigDataLen
= cfinst
->header
.sigDataLen
;
325 return (unsigned char*) fmallocWithData(cfinst
->dataRep
+
326 cfinst
->header
.sigDataOffset
, *sigDataLen
);
337 unsigned feeCFileUserData(feeCipherFile cipherFile
)
339 cFileInst
*cfinst
= (cFileInst
*)cipherFile
;
341 return cfinst
->header
.userData
;
345 * Convert between cFileHeader and portable byte representation.
349 * Return size of byte rep of cFileHeader. We just happen to know that
350 * this is the same size as the header....
352 static unsigned lengthOfByteRepCfileHdr(void)
354 return sizeof(cFileHeader
);
357 static unsigned cfileHdrToByteRep(cFileHeader
*hdr
,
360 s
+= intToByteRep(hdr
->magic
, s
);
361 s
+= intToByteRep(hdr
->version
, s
);
362 s
+= intToByteRep(hdr
->minVersion
, s
);
363 s
+= intToByteRep(hdr
->totalLength
, s
);
364 s
+= intToByteRep(hdr
->encrType
, s
);
365 s
+= intToByteRep(hdr
->cipherTextOffset
, s
);
366 s
+= intToByteRep(hdr
->cipherTextLen
, s
);
367 s
+= intToByteRep(hdr
->sendPubKeyDataOffset
, s
);
368 s
+= intToByteRep(hdr
->sendPubKeyDataLen
, s
);
369 s
+= intToByteRep(hdr
->otherKeyDataOffset
, s
);
370 s
+= intToByteRep(hdr
->otherKeyDataLen
, s
);
371 s
+= intToByteRep(hdr
->sigDataOffset
, s
);
372 s
+= intToByteRep(hdr
->sigDataLen
, s
);
373 s
+= intToByteRep(hdr
->userData
, s
);
374 return sizeof(cFileHeader
);
377 #define DEC_INT(n, b) \
378 n = byteRepToInt(b); \
381 static void byteRepToCfileHdr(const unsigned char *s
,
384 DEC_INT(hdr
->magic
, s
);
385 DEC_INT(hdr
->version
, s
);
386 DEC_INT(hdr
->minVersion
, s
);
387 DEC_INT(hdr
->totalLength
, s
);
388 // DEC_INT(hdr->encrType, s);
389 hdr
->encrType
= (cipherFileEncrType
) byteRepToInt(s
);
391 DEC_INT(hdr
->cipherTextOffset
, s
);
392 DEC_INT(hdr
->cipherTextLen
, s
);
393 DEC_INT(hdr
->sendPubKeyDataOffset
, s
);
394 DEC_INT(hdr
->sendPubKeyDataLen
, s
);
395 DEC_INT(hdr
->otherKeyDataOffset
, s
);
396 DEC_INT(hdr
->otherKeyDataLen
, s
);
397 DEC_INT(hdr
->sigDataOffset
, s
);
398 DEC_INT(hdr
->sigDataLen
, s
);
399 DEC_INT(hdr
->userData
, s
);