1/* Copyright (c) 1998 Apple Computer, 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 COMPUTER, INC. AND THE
6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER,
7 * INC.  ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
8 * EXPOSE YOU TO LIABILITY.
9 ***************************************************************************
10 *
11 * CipherFileFEED.c - FEED and FEEDExp related cipherfile support
12 *
13 * Revision History
14 * ----------------
15 * 24 Jun 97	Doug Mitchell at Apple
16 *	Fixed memory leaks via sigData
17 * 18 Feb 97	Doug Mitchell at Apple
18 *	Split off from feeCipherFile.c
19 */
20
21#include "ckconfig.h"
22
23#if	CRYPTKIT_CIPHERFILE_ENABLE
24
25#include "Crypt.h"
26#include "CipherFileFEED.h"
27#include "falloc.h"
28#include "feeDebug.h"
29
30feeReturn createFEED(feePubKey sendPrivKey,	// required
31	feePubKey recvPubKey,
32	const unsigned char *plainText,
33	unsigned plainTextLen,
34	int genSig,				// 1 ==> generate signature
35	unsigned userData,			// for caller's convenience
36	feeCipherFile *cipherFile)		// RETURNED if successful
37{
38	feeReturn	frtn;
39	feeFEED		feed = NULL;
40	unsigned char	*cipherText = NULL;
41	unsigned	cipherTextLen;
42	unsigned char	*sigData = NULL;
43	unsigned	sigDataLen = 0;
44	feeCipherFile	cfile = NULL;
45	unsigned char	*pubKeyString = NULL;	// of sendPrivKey
46	unsigned	pubKeyStringLen = 0;
47
48	if((sendPrivKey == NULL) || (recvPubKey == NULL)) {
49		return FR_BadPubKey;
50	}
51
52	/*
53	 * FEED encrypt plaintext
54	 */
55	feed = feeFEEDNewWithPubKey(sendPrivKey, recvPubKey, FF_ENCRYPT, NULL, NULL);
56	if(feed == NULL) {
57		frtn = FR_BadPubKey;
58		goto out;
59	}
60	frtn = feeFEEDEncrypt(feed,
61		plainText,
62		plainTextLen,
63		&cipherText,
64		&cipherTextLen);
65	if(frtn) {
66		goto out;
67	}
68
69	/*
70	 * Sender's public key string
71	 */
72	frtn = feePubKeyCreateKeyString(sendPrivKey,
73		(char **)&pubKeyString,
74		&pubKeyStringLen);
75	if(frtn) {
76		/*
77		 * Huh?
78		 */
79		frtn = FR_BadPubKey;
80		goto out;
81	}
82
83	if(genSig) {
84		/*
85		 * We generate signature on ciphertext by convention.
86		 */
87		frtn = feePubKeyCreateSignature(sendPrivKey,
88			cipherText,
89			cipherTextLen,
90			&sigData,
91			&sigDataLen);
92		if(frtn) {
93			goto out;
94		}
95	}
96
97	/*
98	 * Cons up a cipherfile
99	 */
100	cfile = feeCFileNewFromCipherText(CFE_FEED,
101		cipherText,
102		cipherTextLen,
103		pubKeyString,
104		pubKeyStringLen,
105		NULL,
106		0,
107		sigData,
108		sigDataLen,
109		userData);
110	if(cfile == NULL) {
111		frtn = FR_Internal;
112		goto out;
113	}
114
115out:
116	/* free alloc'd stuff */
117
118	if(cipherText) {
119		ffree(cipherText);
120	}
121	if(feed) {
122		feeFEEDFree(feed);
123	}
124	if(pubKeyString) {
125		ffree(pubKeyString);
126	}
127	if(sigData) {
128		ffree(sigData);
129	}
130	*cipherFile = cfile;
131	return frtn;
132
133}
134
135feeReturn decryptFEED(feeCipherFile cipherFile,
136	feePubKey recvPrivKey,
137	feePubKey sendPubKey,				// optional
138	unsigned char **plainText,			// RETURNED
139	unsigned *plainTextLen,				// RETURNED
140	feeSigStatus *sigStatus)			// RETURNED
141{
142	feeReturn 	frtn = FR_Success;
143	unsigned char	*cipherText = NULL;
144	unsigned	cipherTextLen;
145	feeFEED		feed = NULL;
146	unsigned char	*sigData = NULL;
147	unsigned	sigDataLen;
148	unsigned char	*sendPubKeyStr = NULL;
149	unsigned	sendPubKeyStrLen = 0;
150	feePubKey 	parsedSendPubKey = NULL;
151
152	if(feeCFileEncrType(cipherFile) != CFE_FEED) {
153		frtn = FR_Internal;
154		goto out;
155	}
156//printf("decryptFEED\n");
157//printf("privKey:\n"); printPubKey(recvPrivKey);
158//printf("pubKey:\n");  printPubKey(sendPubKey);
159	/*
160	 * Get ciphertext and sender's public key from cipherFile
161	 */
162	cipherText = feeCFileCipherText(cipherFile, &cipherTextLen);
163	if(cipherText == NULL) {
164		frtn = FR_BadCipherFile;
165		goto out;
166	}
167	sendPubKeyStr = feeCFileSendPubKeyData(cipherFile, &sendPubKeyStrLen);
168	if(sendPubKeyStr == NULL) {
169		frtn = FR_BadCipherFile;
170		goto out;
171	}
172	parsedSendPubKey = feePubKeyAlloc();
173	frtn = feePubKeyInitFromKeyString(parsedSendPubKey,
174		(char *)sendPubKeyStr,
175		sendPubKeyStrLen);
176	if(frtn) {
177		frtn = FR_BadCipherFile;
178		goto out;
179	}
180//printf("parsedSendPubKey:\n");  printPubKey(parsedSendPubKey);
181
182	/*
183	 * FEED decrypt
184	 */
185	feed = feeFEEDNewWithPubKey(recvPrivKey, parsedSendPubKey, FF_DECRYPT, NULL, NULL);
186	if(feed == NULL) {
187		frtn = FR_BadPubKey;
188		goto out;
189	}
190	frtn = feeFEEDDecrypt(feed,
191		cipherText,
192		cipherTextLen,
193		plainText,
194		plainTextLen);
195	if(frtn) {
196		goto out;
197	}
198
199	sigData = feeCFileSigData(cipherFile, &sigDataLen);
200	if(sigData) {
201		feeReturn sigFrtn;
202
203		if(sendPubKey == NULL) {
204			/*
205			 * use embedded sender's public key
206			 */
207			sendPubKey = parsedSendPubKey;
208		}
209		sigFrtn = feePubKeyVerifySignature(sendPubKey,
210			cipherText,
211			cipherTextLen,
212			sigData,
213			sigDataLen);
214		switch(sigFrtn) {
215		    case FR_Success:
216		    	*sigStatus = SS_PresentValid;
217			break;
218		    default:
219		    	*sigStatus = SS_PresentInvalid;
220			break;
221		}
222	}
223	else {
224		*sigStatus = SS_NotPresent;
225	}
226out:
227	if(cipherText) {
228		ffree(cipherText);
229	}
230	if(feed) {
231		feeFEEDFree(feed);
232	}
233	if(sigData) {
234		ffree(sigData);
235	}
236	if(parsedSendPubKey) {
237		feePubKeyFree(parsedSendPubKey);
238	}
239	if(sendPubKeyStr) {
240		ffree(sendPubKeyStr);
241	}
242	return frtn;
243}
244
245feeReturn createFEEDExp(feePubKey sendPrivKey,	// for sig only
246	feePubKey recvPubKey,
247	const unsigned char *plainText,
248	unsigned plainTextLen,
249	int genSig,				// 1 ==> generate signature
250	unsigned userData,			// for caller's convenience
251	feeCipherFile *cipherFile)		// RETURNED if successful
252{
253	feeReturn	frtn;
254	feeFEEDExp	feed = NULL;
255	unsigned char	*cipherText = NULL;
256	unsigned	cipherTextLen;
257	unsigned char	*sigData = NULL;
258	unsigned	sigDataLen = 0;
259	feeCipherFile	cfile = NULL;
260	unsigned char	*pubKeyString = NULL;	// of sendPrivKey, for sig
261	unsigned	pubKeyStringLen = 0;
262
263	if(recvPubKey == NULL) {
264		return FR_BadPubKey;
265	}
266
267	/*
268	 * FEEDExp encrypt plaintext
269	 */
270	feed = feeFEEDExpNewWithPubKey(recvPubKey, NULL, NULL);
271	if(feed == NULL) {
272		frtn = FR_BadPubKey;
273		goto out;
274	}
275	frtn = feeFEEDExpEncrypt(feed,
276		plainText,
277		plainTextLen,
278		&cipherText,
279		&cipherTextLen);
280	if(frtn) {
281		goto out;
282	}
283
284	if(genSig) {
285		if(sendPrivKey == NULL) {
286			frtn = FR_IllegalArg;
287			goto out;
288		}
289		/*
290		 * We generate signature on ciphertext by convention.
291		 */
292		frtn = feePubKeyCreateSignature(sendPrivKey,
293			cipherText,
294			cipherTextLen,
295			&sigData,
296			&sigDataLen);
297		if(frtn) {
298			goto out;
299		}
300		/*
301		 * Sender's public key string
302		 */
303		frtn = feePubKeyCreateKeyString(sendPrivKey,
304			(char **)&pubKeyString,
305			&pubKeyStringLen);
306		if(frtn) {
307			/*
308			 * Huh?
309			 */
310			frtn = FR_BadPubKey;
311			goto out;
312		}
313	}
314
315	/*
316	 * Cons up a cipherfile
317	 */
318	cfile = feeCFileNewFromCipherText(CFE_FEEDExp,
319		cipherText,
320		cipherTextLen,
321		pubKeyString,
322		pubKeyStringLen,
323		NULL,
324		0,
325		sigData,
326		sigDataLen,
327		userData);
328	if(cfile == NULL) {
329		frtn = FR_Internal;
330		goto out;
331	}
332
333out:
334	/* free alloc'd stuff */
335
336	if(cipherText) {
337		ffree(cipherText);
338	}
339	if(feed) {
340		feeFEEDExpFree(feed);
341	}
342	if(sigData) {
343		ffree(sigData);
344	}
345	if(pubKeyString) {
346		ffree(pubKeyString);
347	}
348	*cipherFile = cfile;
349	return frtn;
350
351}
352
353feeReturn decryptFEEDExp(feeCipherFile cipherFile,
354	feePubKey recvPrivKey,
355	feePubKey sendPubKey,				// optional
356	unsigned char **plainText,			// RETURNED
357	unsigned *plainTextLen,				// RETURNED
358	feeSigStatus *sigStatus)			// RETURNED
359{
360	feeReturn 	frtn = FR_Success;
361	unsigned char	*cipherText = NULL;
362	unsigned	cipherTextLen;
363	feeFEEDExp	feed = NULL;
364	unsigned char	*sigData = NULL;
365	unsigned	sigDataLen;
366	unsigned char	*sendPubKeyStr = NULL;
367	unsigned	sendPubKeyStrLen = 0;
368	feePubKey 	parsedSendPubKey = NULL;
369
370	if(feeCFileEncrType(cipherFile) != CFE_FEEDExp) {
371		frtn = FR_Internal;
372		goto out;
373	}
374
375	/*
376	 * Get ciphertext from cipherFile
377	 */
378	cipherText = feeCFileCipherText(cipherFile, &cipherTextLen);
379	if(cipherText == NULL) {
380		frtn = FR_BadCipherFile;
381		goto out;
382	}
383
384	/*
385	 * FEEDExp decrypt
386	 */
387	feed = feeFEEDExpNewWithPubKey(recvPrivKey, NULL, NULL);
388	if(feed == NULL) {
389		frtn = FR_BadPubKey;
390		goto out;
391	}
392	frtn = feeFEEDExpDecrypt(feed,
393		cipherText,
394		cipherTextLen,
395		plainText,
396		plainTextLen);
397	if(frtn) {
398		goto out;
399	}
400
401	sigData = feeCFileSigData(cipherFile, &sigDataLen);
402	if(sigData) {
403		feeReturn sigFrtn;
404
405		if(sendPubKey == NULL) {
406			/*
407			 * use embedded sender's public key
408			 */
409			sendPubKeyStr = feeCFileSendPubKeyData(cipherFile,
410				&sendPubKeyStrLen);
411			if(sendPubKeyStr == NULL) {
412				frtn = FR_BadCipherFile;
413				goto out;
414			}
415			parsedSendPubKey = feePubKeyAlloc();
416			frtn = feePubKeyInitFromKeyString(parsedSendPubKey,
417				(char *)sendPubKeyStr, sendPubKeyStrLen);
418			if(frtn) {
419				frtn = FR_BadCipherFile;
420				goto out;
421			}
422			sendPubKey = parsedSendPubKey;
423		}
424		sigFrtn = feePubKeyVerifySignature(sendPubKey,
425			cipherText,
426			cipherTextLen,
427			sigData,
428			sigDataLen);
429		switch(sigFrtn) {
430		    case FR_Success:
431		    	*sigStatus = SS_PresentValid;
432			break;
433		    default:
434		    	*sigStatus = SS_PresentInvalid;
435			break;
436		}
437	}
438	else {
439		*sigStatus = SS_NotPresent;
440	}
441out:
442	if(cipherText) {
443		ffree(cipherText);
444	}
445	if(feed) {
446		feeFEEDExpFree(feed);
447	}
448	if(sigData) {
449		ffree(sigData);
450	}
451	if(parsedSendPubKey) {
452		feePubKeyFree(parsedSendPubKey);
453	}
454	if(sendPubKeyStr) {
455		ffree(sendPubKeyStr);
456	}
457	return frtn;
458}
459
460#endif	/* CRYPTKIT_CIPHERFILE_ENABLE */
461