]>
Commit | Line | Data |
---|---|---|
d8f41ccd | 1 | /* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
2 | * |
3 | * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT | |
4 | * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE | |
d8f41ccd A |
5 | * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE |
6 | * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, | |
b1ab9ed8 A |
7 | * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL |
8 | * EXPOSE YOU TO LIABILITY. | |
9 | *************************************************************************** | |
10 | * | |
11 | * feeCipherFile.c | |
12 | * | |
13 | * Revision History | |
14 | * ---------------- | |
15 | * 10/06/98 ap | |
16 | * Changed to compile with C++. | |
d8f41ccd | 17 | * 05 Feb 97 at Apple |
b1ab9ed8 | 18 | * Modified to use portable byte representation. |
d8f41ccd | 19 | * 23 Oct 96 at NeXT |
b1ab9ed8 A |
20 | * Created. |
21 | */ | |
22 | ||
23 | #include "feeCipherFile.h" | |
24 | #include "falloc.h" | |
25 | #include "platform.h" | |
26 | #include "feeDebug.h" | |
27 | #include "byteRep.h" | |
28 | ||
29 | #ifndef NULL | |
30 | #define NULL ((void *)0) | |
31 | #endif /* NULL */ | |
32 | ||
33 | /* | |
34 | * These must match constants of same name in CipherFileAtom.java. | |
35 | */ | |
36 | #define CFILE_MAGIC 0xfeecf111 | |
37 | #define CFILE_VERSION 1 | |
38 | #define CFILE_MIN_VERSION 1 | |
39 | ||
40 | /* | |
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. | |
44 | */ | |
45 | typedef struct { | |
46 | unsigned magic; | |
47 | unsigned version; | |
48 | unsigned minVersion; | |
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 | |
59 | unsigned userData; | |
60 | } cFileHeader; | |
61 | ||
62 | /* | |
63 | * Private data, represented by a feeCipherFile handle. | |
64 | */ | |
65 | typedef struct { | |
66 | cFileHeader header; | |
67 | unsigned char *dataRep; // raw data | |
68 | unsigned dataRepLen; | |
69 | } cFileInst; | |
70 | ||
71 | static unsigned lengthOfByteRepCfileHdr(void); | |
72 | static unsigned cfileHdrToByteRep(cFileHeader *hdr, | |
73 | unsigned char *s); | |
74 | static void byteRepToCfileHdr(const unsigned char *s, | |
75 | cFileHeader *hdr); | |
76 | ||
77 | ||
78 | /* | |
79 | * alloc, free cFileInst | |
80 | */ | |
81 | static cFileInst *cFileInstAlloc() | |
82 | { | |
83 | cFileInst *cfinst = (cFileInst *) fmalloc(sizeof(cFileInst)); | |
84 | ||
85 | bzero(cfinst, sizeof(cFileInst)); | |
86 | return cfinst; | |
87 | } | |
88 | ||
89 | static void cFileInstFree(cFileInst *cfinst) | |
90 | { | |
91 | if(cfinst->dataRep) { | |
92 | ffree(cfinst->dataRep); | |
93 | } | |
94 | ffree(cfinst); | |
95 | } | |
96 | ||
97 | /* | |
98 | * Alloc and return a new feeCipherFile object associated with the specified | |
99 | * data. | |
100 | */ | |
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 | |
111 | { | |
112 | cFileInst *cfinst; | |
113 | cFileHeader *header; | |
114 | unsigned char *data; | |
115 | ||
116 | if(cipherTextLen == 0) { | |
117 | return NULL; | |
118 | } | |
119 | cfinst = cFileInstAlloc(); | |
120 | header = &cfinst->header; | |
121 | ||
122 | /* | |
123 | * Init the header. | |
124 | */ | |
125 | header->magic = CFILE_MAGIC; | |
126 | header->version = CFILE_VERSION; | |
127 | header->minVersion = CFILE_MIN_VERSION; | |
128 | header->totalLength = lengthOfByteRepCfileHdr() + cipherTextLen + | |
129 | sendPubKeyDataLen + otherKeyDataLen + | |
130 | sigDataLen; | |
131 | header->encrType = encrType; | |
132 | header->cipherTextOffset = lengthOfByteRepCfileHdr(); | |
133 | header->cipherTextLen = cipherTextLen; | |
134 | header->sendPubKeyDataOffset = header->cipherTextOffset + | |
135 | cipherTextLen; | |
136 | header->sendPubKeyDataLen = sendPubKeyDataLen; | |
137 | header->otherKeyDataOffset = header->sendPubKeyDataOffset + | |
138 | sendPubKeyDataLen; | |
139 | header->otherKeyDataLen = otherKeyDataLen; | |
140 | header->sigDataOffset = header->otherKeyDataOffset + | |
141 | otherKeyDataLen; | |
142 | header->sigDataLen = sigDataLen; | |
143 | header->userData = userData; | |
144 | ||
145 | /* | |
146 | * Alloc a data representation, copy various components to it. | |
147 | */ | |
148 | cfinst->dataRepLen = header->totalLength; | |
149 | data = cfinst->dataRep = (unsigned char*) fmalloc(cfinst->dataRepLen); | |
150 | cfileHdrToByteRep(header, data); | |
151 | ||
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); | |
157 | } | |
158 | if(otherKeyDataLen) { | |
159 | data = cfinst->dataRep + header->otherKeyDataOffset; | |
160 | bcopy(otherKeyData, data, otherKeyDataLen); | |
161 | } | |
162 | if(sigDataLen) { | |
163 | data = cfinst->dataRep + header->sigDataOffset; | |
164 | bcopy(sigData, data, sigDataLen); | |
165 | } | |
166 | return (feeCipherFile)cfinst; | |
167 | } | |
168 | ||
169 | /* | |
170 | * Obtain the contents of a feeCipherFile as a byte stream. | |
171 | */ | |
172 | feeReturn feeCFileDataRepresentation(feeCipherFile cipherFile, | |
173 | const unsigned char **dataRep, | |
174 | unsigned *dataRepLen) | |
175 | { | |
176 | cFileInst *cfinst = (cFileInst *)cipherFile; | |
177 | ||
178 | if(cfinst->dataRepLen == 0) { | |
179 | *dataRep = NULL; | |
180 | *dataRepLen = 0; | |
181 | return FR_BadCipherFile; | |
182 | } | |
183 | *dataRep = (unsigned char*) fmallocWithData(cfinst->dataRep, cfinst->dataRepLen); | |
184 | *dataRepLen = cfinst->dataRepLen; | |
185 | return FR_Success; | |
186 | } | |
187 | ||
188 | /* | |
189 | * Alloc and return a new feeCipherFile object, given a byte stream (originally | |
190 | * obtained from feeCFDataRepresentation()). | |
191 | */ | |
192 | feeReturn feeCFileNewFromDataRep(const unsigned char *dataRep, | |
193 | unsigned dataRepLen, | |
194 | feeCipherFile *cipherFile) // RETURNED if sucessful | |
195 | { | |
196 | cFileInst *cfinst = cFileInstAlloc(); | |
197 | cFileHeader *header; | |
198 | ||
199 | if(dataRepLen < lengthOfByteRepCfileHdr()) { | |
200 | dbgLog(("datRep too short\n")); | |
201 | goto abort; | |
202 | } | |
203 | cfinst->dataRep = (unsigned char*) fmallocWithData(dataRep, dataRepLen); | |
204 | cfinst->dataRepLen = dataRepLen; | |
205 | header = &cfinst->header; | |
206 | byteRepToCfileHdr(dataRep, header); | |
207 | ||
208 | /* | |
209 | * As much consistency checking as we can manage here. | |
210 | */ | |
211 | if(header->magic != CFILE_MAGIC) { | |
212 | dbgLog(("Bad cipherFile magic number\n")); | |
213 | goto abort; | |
214 | } | |
215 | if(header->minVersion > CFILE_VERSION) { | |
216 | dbgLog(("Incompatible cipherFile version\n")); | |
217 | goto abort; | |
218 | } | |
219 | if(header->totalLength != dataRepLen) { | |
220 | dbgLog(("Bad totalLength in cipherFile header\n")); | |
221 | goto abort; | |
222 | } | |
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")); | |
232 | goto abort; | |
233 | } | |
234 | ||
235 | /* | |
236 | * OK, looks good. | |
237 | */ | |
238 | *cipherFile = (feeCipherFile)cfinst; | |
239 | return FR_Success; | |
240 | abort: | |
241 | cFileInstFree(cfinst); | |
242 | *cipherFile = NULL; | |
243 | return FR_BadCipherFile; | |
244 | } | |
245 | ||
246 | /* | |
247 | * Free a feeCipherFile object. | |
248 | */ | |
249 | void feeCFileFree(feeCipherFile cipherFile) | |
250 | { | |
251 | cFileInstFree((cFileInst *)cipherFile); | |
252 | } | |
253 | ||
254 | /* | |
255 | * Given a feeCipherFile object (typically obtained from | |
256 | * feeCFileNewFromData()), obtain its constituent parts. | |
257 | * | |
258 | * Data returned must be freed by caller. | |
259 | * feeCFileSigData() may return NULL, indicating no signature present. | |
260 | */ | |
261 | cipherFileEncrType feeCFileEncrType(feeCipherFile cipherFile) | |
262 | { | |
263 | cFileInst *cfinst = (cFileInst *)cipherFile; | |
264 | ||
265 | return cfinst->header.encrType; | |
266 | } | |
267 | ||
268 | unsigned char *feeCFileCipherText(feeCipherFile cipherFile, | |
269 | unsigned *cipherTextLen) | |
270 | { | |
271 | cFileInst *cfinst = (cFileInst *)cipherFile; | |
272 | ||
273 | if(cfinst->header.cipherTextLen) { | |
274 | *cipherTextLen = cfinst->header.cipherTextLen; | |
275 | return (unsigned char*) fmallocWithData(cfinst->dataRep + | |
276 | cfinst->header.cipherTextOffset, *cipherTextLen); | |
277 | } | |
278 | else { | |
279 | dbgLog(("feeCFileCipherText: no cipherText\n")); | |
280 | *cipherTextLen = 0; | |
281 | return NULL; | |
282 | } | |
283 | } | |
284 | ||
285 | unsigned char *feeCFileSendPubKeyData(feeCipherFile cipherFile, | |
286 | unsigned *sendPubKeyDataLen) | |
287 | { | |
288 | cFileInst *cfinst = (cFileInst *)cipherFile; | |
289 | ||
290 | if(cfinst->header.sendPubKeyDataLen) { | |
291 | *sendPubKeyDataLen = cfinst->header.sendPubKeyDataLen; | |
292 | return (unsigned char*) fmallocWithData(cfinst->dataRep + | |
293 | cfinst->header.sendPubKeyDataOffset, | |
294 | *sendPubKeyDataLen); | |
295 | } | |
296 | else { | |
297 | *sendPubKeyDataLen = 0; | |
298 | return NULL; | |
299 | } | |
300 | } | |
301 | ||
302 | unsigned char *feeCFileOtherKeyData(feeCipherFile cipherFile, | |
303 | unsigned *otherKeyDataLen) | |
304 | { | |
305 | cFileInst *cfinst = (cFileInst *)cipherFile; | |
306 | ||
307 | if(cfinst->header.otherKeyDataLen) { | |
308 | *otherKeyDataLen = cfinst->header.otherKeyDataLen; | |
309 | return (unsigned char*) fmallocWithData(cfinst->dataRep + | |
310 | cfinst->header.otherKeyDataOffset, *otherKeyDataLen); | |
311 | } | |
312 | else { | |
313 | *otherKeyDataLen = 0; | |
314 | return NULL; | |
315 | } | |
316 | } | |
317 | ||
318 | unsigned char *feeCFileSigData(feeCipherFile cipherFile, | |
319 | unsigned *sigDataLen) | |
320 | { | |
321 | cFileInst *cfinst = (cFileInst *)cipherFile; | |
322 | ||
323 | if(cfinst->header.sigDataLen) { | |
324 | *sigDataLen = cfinst->header.sigDataLen; | |
325 | return (unsigned char*) fmallocWithData(cfinst->dataRep + | |
326 | cfinst->header.sigDataOffset, *sigDataLen); | |
327 | } | |
328 | else { | |
329 | /* | |
330 | * Not an error | |
331 | */ | |
332 | *sigDataLen = 0; | |
333 | return NULL; | |
334 | } | |
335 | } | |
336 | ||
337 | unsigned feeCFileUserData(feeCipherFile cipherFile) | |
338 | { | |
339 | cFileInst *cfinst = (cFileInst *)cipherFile; | |
340 | ||
341 | return cfinst->header.userData; | |
342 | } | |
343 | ||
344 | /* | |
345 | * Convert between cFileHeader and portable byte representation. | |
346 | */ | |
347 | ||
348 | /* | |
349 | * Return size of byte rep of cFileHeader. We just happen to know that | |
350 | * this is the same size as the header.... | |
351 | */ | |
352 | static unsigned lengthOfByteRepCfileHdr(void) | |
353 | { | |
354 | return sizeof(cFileHeader); | |
355 | } | |
356 | ||
357 | static unsigned cfileHdrToByteRep(cFileHeader *hdr, | |
358 | unsigned char *s) | |
359 | { | |
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); | |
375 | } | |
376 | ||
377 | #define DEC_INT(n, b) \ | |
378 | n = byteRepToInt(b); \ | |
379 | b += sizeof(int); | |
380 | ||
381 | static void byteRepToCfileHdr(const unsigned char *s, | |
382 | cFileHeader *hdr) | |
383 | { | |
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); | |
390 | s += sizeof(int); | |
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); | |
400 | } |