]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cryptkit/lib/feeCipherFileAtom.c
Security-57740.51.3.tar.gz
[apple/security.git] / OSX / libsecurity_cryptkit / lib / feeCipherFileAtom.c
1 /* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved.
2 *
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 ***************************************************************************
10 *
11 * feeCipherFile.c
12 *
13 * Revision History
14 * ----------------
15 * 10/06/98 ap
16 * Changed to compile with C++.
17 * 05 Feb 97 at Apple
18 * Modified to use portable byte representation.
19 * 23 Oct 96 at NeXT
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 }