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 * NSCipherFile.m - ObjC wrapper for feeCipherFile
12 *
13 * Revision History
14 * ----------------
15 * 28 Oct 96	Doug Mitchell at NeXT
16 *	Created.
17 */
18
19#import "NSCipherFile.h"
20#import "feeCipherFile.h"
21#import "falloc.h"
22#import "NSFEEPublicKeyPrivate.h"	/* for -feePubKey */
23
24/*
25 * Private instance data.
26 */
27typedef struct {
28	feeCipherFile	cfile;
29} _cfPriv;
30
31@implementation NSCipherFile
32
33- (void)dealloc
34{
35	if(_priv) {
36		_cfPriv *cfPriv = _priv;
37		if(cfPriv->cfile) {
38		    feeCFileFree(cfPriv->cfile);
39		}
40	}
41	[super dealloc];
42}
43
44/*
45 * Alloc and return an autoreleased NSCipherFile object associated with
46 * the specified data.
47 */
48+ newFromCipherText : (NSData *)cipherText
49	encrType : (cipherFileEncrType)encrType
50	sendPubKeyData : (NSData *)sendPubKeyData
51	otherKeyData : (NSData *)otherKeyData
52	sigData : (NSData *)sigData	// optional; nil means no signature
53	userData : (unsigned)userData	// for caller's convenience
54{
55	NSCipherFile *result;
56	_cfPriv *cfPriv;
57
58	result = [[self alloc] autorelease];
59	result->_priv = cfPriv = fmalloc(sizeof(_cfPriv));
60	cfPriv->cfile = feeCFileNewFromCipherText(encrType,
61		[cipherText bytes],
62		[cipherText length],
63		[sendPubKeyData bytes],
64		[sendPubKeyData length],
65		[otherKeyData bytes],
66		[otherKeyData length],
67		[sigData bytes],
68		[sigData length],
69		userData);
70	if(cfPriv->cfile) {
71		return result;
72	}
73	else {
74		return nil;
75	}
76}
77
78/*
79 * Obtain the contents of a feeCipherFile as NSData.
80 */
81- (NSData *)dataRepresentation
82{
83	_cfPriv 		*cfPriv = _priv;
84	NSData 			*result;
85	const unsigned char 	*rep;
86	unsigned 		repLen;
87	feeReturn 		frtn;
88
89	if(cfPriv == NULL) {
90		return nil;
91	}
92	frtn = feeCFileDataRepresentation(cfPriv->cfile,
93		&rep,
94		&repLen);
95	if(frtn) {
96		return nil;
97	}
98	result = [NSData dataWithBytesNoCopy:(unsigned char *)rep
99		length:repLen];
100	return result;
101}
102
103/*
104 * Alloc and return an autoreleased NSCipherFile object given a data
105 * representation.
106 */
107+ newFromDataRepresentation : (NSData *)dataRep
108{
109	NSCipherFile *result;
110	_cfPriv *cfPriv;
111	feeReturn frtn;
112
113	result = [[self alloc] autorelease];
114	result->_priv = cfPriv = fmalloc(sizeof(_cfPriv));
115	frtn = feeCFileNewFromDataRep([dataRep bytes],
116		[dataRep length],
117		&cfPriv->cfile);
118	if(frtn) {
119		return nil;
120	}
121	else {
122		return result;
123	}
124}
125
126/*
127 * Given an NSCipherFile object, obtain its constituent parts.
128 */
129- (cipherFileEncrType)encryptionType
130{
131	_cfPriv 		*cfPriv = _priv;
132
133	if(cfPriv == NULL) {
134		return CFE_Other;
135	}
136	return feeCFileEncrType(cfPriv->cfile);
137}
138
139- (NSData *)cipherText
140{
141	_cfPriv 		*cfPriv = _priv;
142	const unsigned char 	*ctext;
143	unsigned 		ctextLen;
144
145	if(cfPriv == NULL) {
146		return nil;
147	}
148	ctext = feeCFileCipherText(cfPriv->cfile, &ctextLen);
149	return [NSData dataWithBytesNoCopy:(unsigned char *)ctext
150		length:ctextLen];
151}
152
153- (NSData *)sendPubKeyData
154{
155	_cfPriv 		*cfPriv = _priv;
156	const unsigned char 	*key;
157	unsigned 		keyLen;
158
159	if(cfPriv == NULL) {
160		return nil;
161	}
162	key = feeCFileSendPubKeyData(cfPriv->cfile, &keyLen);
163	if(key) {
164	    return [NSData dataWithBytesNoCopy:(unsigned char *)key
165		length:keyLen];
166	}
167	else {
168	    return nil;
169	}
170}
171
172- (NSData *)otherKeyData
173{
174	_cfPriv 		*cfPriv = _priv;
175	const unsigned char 	*key;
176	unsigned 		keyLen;
177
178	if(cfPriv == NULL) {
179		return nil;
180	}
181	key = feeCFileOtherKeyData(cfPriv->cfile, &keyLen);
182	if(key) {
183	    return [NSData dataWithBytesNoCopy:(unsigned char *)key
184		length:keyLen];
185	}
186	else {
187	    return nil;
188	}
189}
190
191- (NSData *)sigData
192{
193	_cfPriv 		*cfPriv = _priv;
194	const unsigned char 	*sig;
195	unsigned 		sigLen;
196
197	if(cfPriv == NULL) {
198		return nil;
199	}
200	sig = feeCFileSigData(cfPriv->cfile, &sigLen);
201	if(sig) {
202	    return [NSData dataWithBytesNoCopy:(unsigned char *)sig
203	    	length:sigLen];
204	}
205	else {
206	    return nil;
207	}
208}
209
210- (unsigned)userData
211{
212	_cfPriv 		*cfPriv = _priv;
213
214	if(cfPriv == NULL) {
215		return 0;
216	}
217	return feeCFileUserData(cfPriv->cfile);
218}
219
220/*
221 * High-level cipherFile support.
222 */
223
224/*
225 * Create a cipherfile of specified cipherFileEncrType for given plaintext.
226 */
227+(feeReturn)createCipherFileForPrivKey : (NSFEEPublicKey *)sendPrivKey
228	recvPubKey : (NSFEEPublicKey *)recvPubKey
229	encrType : (cipherFileEncrType)encrType
230	plainText : (NSData *)plainText
231	genSig : (BOOL)genSig
232	doEnc64 : (BOOL)doEnc64			// YES ==> perform enc64
233	userData : (unsigned)userData		// for caller's convenience
234	cipherFileData : (NSData **)cipherFileData	// RETURNED
235{
236	feeReturn frtn;
237	unsigned char *cfileData;
238	unsigned cfileDataLen;
239	feePubKey privKey = NULL;
240
241	if(sendPrivKey) {
242		privKey = [sendPrivKey feePubKey];
243	}
244	frtn = createCipherFile(privKey,
245		[recvPubKey feePubKey],
246		encrType,
247		[plainText bytes],
248		[plainText length],
249		genSig,
250		doEnc64,
251		userData,
252		&cfileData,
253		&cfileDataLen);
254	if(frtn) {
255		return frtn;
256	}
257	*cipherFileData =
258		[NSData dataWithBytesNoCopy:(unsigned char *)cfileData
259			length:cfileDataLen];
260	return frtn;
261}
262
263/*
264 * Parse and decrypt a data representation of an NSCipherFile object.
265 */
266+ (feeReturn)parseCipherFileData : (NSFEEPublicKey *)recvPrivKey
267	sendPubKey : (NSFEEPublicKey *)sendPubKey
268	cipherFileData : (NSData *)cipherFileData
269	doDec64 : (BOOL)doDec64
270	encrType : (cipherFileEncrType *)encrType	// RETURNED
271	plainText : (NSData **)plainText		// RETURNED
272	sigStatus : (feeSigStatus *)sigStatus		// RETURNED
273	sigSigner : (NSString **)sigSigner		// RETURNED
274	userData : (unsigned *)userData			// RETURNED
275{
276	feeReturn 	frtn;
277	unsigned char 	*ptext;
278	unsigned 	ptextLen;
279	feeUnichar 	*signer;
280	unsigned 	signerLen;
281	feePubKey 	_pubKey = NULL;
282
283	if(recvPrivKey == nil) {
284		return FR_IllegalArg;			// always required
285	}
286	if(sendPubKey) {
287		_pubKey = [sendPubKey feePubKey];
288	}
289
290	frtn = parseCipherFile([recvPrivKey feePubKey],
291		_pubKey,
292		[cipherFileData bytes],
293		[cipherFileData length],
294		doDec64,
295		encrType,
296		&ptext,
297		&ptextLen,
298		sigStatus,
299		&signer,
300		&signerLen,
301		userData);
302	if(frtn) {
303		return frtn;
304	}
305	*plainText = [NSData dataWithBytesNoCopy:ptext length:ptextLen];
306	*sigSigner = [NSString stringWithCharacters:signer length:signerLen];
307	ffree(signer);
308	return frtn;
309}
310
311/*
312 * Parse and decrypt an NSCipherFile object obtained via
313 * +newFromDataRepresentation.
314 *
315 * recvPrivKey is required in all cases. If sendPubKey is present,
316 * sendPubKey - rather than the embedded sender's public key - will be
317 * used for signature validation.
318 */
319- (feeReturn)decryptCipherFileData : (NSFEEPublicKey *)recvPrivKey
320	sendPubKey : (NSFEEPublicKey *)sendPubKey
321	plainText : (NSData **)plainText		// RETURNED
322	sigStatus : (feeSigStatus *)sigStatus		// RETURNED
323	sigSigner : (NSString **)sigSigner		// RETURNED
324{
325	_cfPriv 	*cfPriv = _priv;
326	feeReturn 	frtn;
327	unsigned char 	*ptext;
328	unsigned 	ptextLen;
329	feeUnichar 	*signer;
330	unsigned 	signerLen;
331	feePubKey 	_pubKey = NULL;
332
333	if(cfPriv == NULL) {
334		return FR_IllegalArg;
335	}
336	if(recvPrivKey == nil) {
337		return FR_IllegalArg;			// always required
338	}
339	if(sendPubKey) {
340		_pubKey = [sendPubKey feePubKey];
341	}
342
343	frtn = decryptCipherFile(cfPriv->cfile,
344		[recvPrivKey feePubKey],
345		_pubKey,
346		&ptext,
347		&ptextLen,
348		sigStatus,
349		&signer,
350		&signerLen);
351	if(frtn) {
352		return frtn;
353	}
354	*plainText = [NSData dataWithBytesNoCopy:ptext length:ptextLen];
355	*sigSigner = [NSString stringWithCharacters:signer length:signerLen];
356	ffree(signer);
357	return frtn;
358
359}
360@end
361