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 - general cipherfile support
12 *
13 * Revision History
14 * ----------------
15 * 05 Feb 97 at Apple
16 *	Added CFE_FEED and CFE_FEEDExp types.
17 * 24 Oct 96 at NeXT
18 *	Created.
19 */
20
21#include "feeCipherFile.h"
22#include "falloc.h"
23#include "feeFEEDExp.h"
24#include "feeFEED.h"
25#include "feeDebug.h"
26#include "CipherFileFEED.h"
27#include "CipherFileDES.h"
28
29
30/*
31 * Create a cipherfile of specified cipherFileEncrType.
32 */
33feeReturn createCipherFile(feePubKey sendPrivKey,
34	feePubKey recvPubKey,
35	cipherFileEncrType encrType,
36	const unsigned char *plainText,
37	unsigned plainTextLen,
38	int genSig,				// 1 ==> generate signature
39	int doEnc64,				// 1 ==> perform enc64
40	unsigned userData,			// for caller's convenience
41	unsigned char **cipherFileData,		// RETURNED
42	unsigned *cipherFileDataLen)		// RETURNED
43{
44	feeReturn 		frtn = FR_Success;
45	feeCipherFile		cipherFile = NULL;
46	unsigned char 		*cipherData = NULL;
47	unsigned 		cipherDataLen;
48
49	/*
50	 * Dispatch to encrType-specific code.
51	 */
52	switch(encrType) {
53	    case CFE_RandDES:
54	    	frtn = createRandDES(sendPrivKey,
55			recvPubKey,
56			plainText,
57			plainTextLen,
58			genSig,
59			userData,
60			&cipherFile);
61		break;
62	    case CFE_PublicDES:
63	    	frtn = createPubDES(sendPrivKey,
64			recvPubKey,
65			plainText,
66			plainTextLen,
67			genSig,
68			userData,
69			&cipherFile);
70		break;
71	    case CFE_FEED:
72	    	frtn = createFEED(sendPrivKey,
73			recvPubKey,
74			plainText,
75			plainTextLen,
76			genSig,
77			userData,
78			&cipherFile);
79		break;
80	    case CFE_FEEDExp:
81	    	frtn = createFEEDExp(sendPrivKey,
82			recvPubKey,
83			plainText,
84			plainTextLen,
85			genSig,
86			userData,
87			&cipherFile);
88		break;
89	    default:
90	    	frtn = FR_Unimplemented;
91		break;
92	}
93
94	if(frtn) {
95		goto out;
96	}
97
98	/*
99	 * Common logic for all encrTypes
100	 */
101
102	/*
103	 * Get the cipherfile's raw data
104	 */
105	frtn = feeCFileDataRepresentation(cipherFile,
106		(const unsigned char **)&cipherData,
107		&cipherDataLen);
108	if(frtn) {
109		goto out;
110	}
111
112	/*
113	 * Optionally encode in 64-char ASCII
114	 */
115	if(doEnc64) {
116		*cipherFileData = enc64(cipherData,
117			cipherDataLen,
118			cipherFileDataLen);
119		ffree(cipherData);
120		if(*cipherFileData == NULL) {
121			frtn = FR_Internal;
122			ffree(cipherData);
123			goto out;
124		}
125	}
126	else {
127		*cipherFileData = cipherData;
128		*cipherFileDataLen = cipherDataLen;
129	}
130out:
131	/* free stuff */
132	if(cipherFile) {
133		feeCFileFree(cipherFile);
134	}
135	return frtn;
136}
137
138/*
139 * Parse a cipherfile.
140 *
141 * sendPubKey only needed for cipherFileEncrType CFE_RandDES if signature
142 * is present. If sendPubKey is present, it will be used for signature
143 * validation rather than the embedded sender's public key.
144 */
145feeReturn parseCipherFile(feePubKey recvPrivKey,
146	feePubKey sendPubKey,
147	const unsigned char *cipherFileData,
148	unsigned cipherFileDataLen,
149	int doDec64,					// 1 ==> perform dec64
150	cipherFileEncrType *encrType,	// RETURNED
151	unsigned char **plainText,		// RETURNED
152	unsigned *plainTextLen,			// RETURNED
153	feeSigStatus *sigStatus,		// RETURNED
154	unsigned *userData)				// RETURNED
155{
156	feeReturn 		frtn;
157	unsigned char		*cipherData = NULL;
158	unsigned		cipherDataLen;
159	int			freeCipherData = 0;
160	feeCipherFile		cipherFile = NULL;
161
162	*plainText = NULL;
163	*plainTextLen = 0;
164
165	if(recvPrivKey == NULL) {	// always required
166		frtn = FR_BadPubKey;
167		goto out;
168	}
169
170	/*
171	 * First, optional dec64()
172	 */
173	if(doDec64) {
174		cipherData = dec64(cipherFileData,
175			cipherFileDataLen,
176			&cipherDataLen);
177		if(cipherData == NULL) {
178			frtn = FR_BadEnc64;
179			goto out;
180		}
181		else {
182			freeCipherData = 1;
183		}
184	}
185	else {
186		cipherData = (unsigned char *)cipherFileData;
187		cipherDataLen = cipherFileDataLen;
188	}
189
190	/*
191	 * Cons up a feeCipherFile object.
192	 */
193	frtn = feeCFileNewFromDataRep(cipherData,
194		cipherDataLen,
195		&cipherFile);
196	if(frtn) {
197		goto out;
198	}
199	*encrType = feeCFileEncrType(cipherFile);
200	*userData = feeCFileUserData(cipherFile);
201	frtn = decryptCipherFile(cipherFile,
202		recvPrivKey,
203		sendPubKey,
204		plainText,
205		plainTextLen,
206		sigStatus);
207
208out:
209	/* free stuff */
210
211	if(cipherData && freeCipherData) {
212		ffree(cipherData);
213	}
214	if(cipherFile) {
215		feeCFileFree(cipherFile);
216	}
217	return frtn;
218}
219
220/*
221 * Decrypt a feeCipherFile obtained via feeCFileNewFromDataRep().
222 * recvPrivKey is required in all cases. If sendPubKey is present,
223 * sendPubKey - rather than the embedded sender's public key - will be
224 * used for signature validation.
225 */
226feeReturn decryptCipherFile(feeCipherFile cipherFile,
227	feePubKey recvPrivKey,			// required
228	feePubKey sendPubKey,			// optional, for signature
229	unsigned char **plainText,		// malloc'd & RETURNED
230	unsigned *plainTextLen,			// RETURNED
231	feeSigStatus *sigStatus)		// RETURNED
232{
233	cipherFileEncrType 	encrType = feeCFileEncrType(cipherFile);
234	feeReturn 		frtn;
235
236	*plainText = NULL;
237	*plainTextLen = 0;
238
239	/*
240	 * Dispatch to encrType-specific code.
241	 */
242	switch(encrType) {
243	    case CFE_RandDES:
244	    	frtn = decryptRandDES(cipherFile,
245			recvPrivKey,
246			sendPubKey,
247			plainText,
248			plainTextLen,
249			sigStatus);
250		break;
251	    case CFE_PublicDES:
252	    	frtn = decryptPubDES(cipherFile,
253			recvPrivKey,
254			sendPubKey,
255			plainText,
256			plainTextLen,
257			sigStatus);
258		break;
259	    case CFE_FEED:
260	    	frtn = decryptFEED(cipherFile,
261			recvPrivKey,
262			sendPubKey,
263			plainText,
264			plainTextLen,
265			sigStatus);
266		break;
267	    case CFE_FEEDExp:
268	    	frtn = decryptFEEDExp(cipherFile,
269			recvPrivKey,
270			sendPubKey,
271			plainText,
272			plainTextLen,
273			sigStatus);
274		break;
275	    default:
276	    	frtn = FR_Unimplemented;
277		break;
278	}
279	return frtn;
280}
281