]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cryptkit/lib/CipherFileDES.c
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurity_cryptkit / lib / CipherFileDES.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 * CipherFileDES.c - DES-related cipherfile support
12 *
13 * Revision History
14 * ----------------
15 * 24 Jun 97 at Apple
16 * Fixed memory leaks via sigData
17 * 18 Feb 97 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 "CipherFileDES.h"
27 #include "falloc.h"
28 #include "feeDebug.h"
29 #include <string.h>
30
31 /*
32 * These functions are only called from feeCipherFile.c.
33 */
34 feeReturn createRandDES(feePubKey sendPrivKey, // for sig only
35 feePubKey recvPubKey,
36 const unsigned char *plainText,
37 unsigned plainTextLen,
38 int genSig, // 1 ==> generate signature
39 unsigned userData, // for caller's convenience
40 feeCipherFile *cipherFile) // RETURNED if successful
41 {
42 feeRand frand = NULL;
43 feeReturn frtn;
44 unsigned char desKey[FEE_DES_MIN_STATE_SIZE];
45 unsigned char *encrDesKey = NULL; // FEED encrypted desKey
46 unsigned encrDesKeyLen;
47 feeDES des = NULL;
48 feeFEEDExp feed = NULL;
49 unsigned char *cipherText = NULL;
50 unsigned cipherTextLen;
51 unsigned char *sigData = NULL;
52 unsigned sigDataLen = 0;
53 feeCipherFile cfile = NULL;
54 unsigned char *pubKeyString = NULL; // of sendPrivKey
55 unsigned pubKeyStringLen = 0;
56
57 if(recvPubKey == NULL) {
58 return FR_BadPubKey;
59 }
60
61 /*
62 * Cons up random DES key and a feeDES object with it
63 */
64 frand = feeRandAlloc();
65 if(frand == NULL) {
66 frtn = FR_Internal;
67 goto out;
68 }
69 feeRandBytes(frand, desKey, FEE_DES_MIN_STATE_SIZE);
70 des = feeDESNewWithState(desKey, FEE_DES_MIN_STATE_SIZE);
71 if(des == NULL) {
72 frtn = FR_Internal;
73 goto out;
74 }
75
76 /*
77 * Encrypt the DES key via FEEDExp
78 */
79 feed = feeFEEDExpNewWithPubKey(recvPubKey, NULL, NULL);
80 if(feed == NULL) {
81 frtn = FR_BadPubKey;
82 goto out;
83 }
84 frtn = feeFEEDExpEncrypt(feed,
85 desKey,
86 FEE_DES_MIN_STATE_SIZE,
87 &encrDesKey,
88 &encrDesKeyLen);
89 if(frtn) {
90 goto out;
91 }
92
93 /*
94 * Encrypt the plaintext via DES
95 */
96 frtn = feeDESEncrypt(des,
97 plainText,
98 plainTextLen,
99 &cipherText,
100 &cipherTextLen);
101 if(frtn) {
102 goto out;
103 }
104
105 if(genSig) {
106 /*
107 * We generate signature on ciphertext by convention.
108 */
109 if(sendPrivKey == NULL) {
110 frtn = FR_BadPubKey;
111 goto out;
112 }
113 frtn = feePubKeyCreateSignature(sendPrivKey,
114 cipherText,
115 cipherTextLen,
116 &sigData,
117 &sigDataLen);
118 if(frtn) {
119 goto out;
120 }
121 /*
122 * Sender's public key string
123 */
124 frtn = feePubKeyCreateKeyString(sendPrivKey,
125 (char **)&pubKeyString,
126 &pubKeyStringLen);
127 if(frtn) {
128 /*
129 * Huh?
130 */
131 frtn = FR_BadPubKey;
132 goto out;
133 }
134 }
135
136 /*
137 * Cons up a cipherfile
138 */
139 cfile = feeCFileNewFromCipherText(CFE_RandDES,
140 cipherText,
141 cipherTextLen,
142 pubKeyString,
143 pubKeyStringLen,
144 encrDesKey,
145 encrDesKeyLen,
146 sigData,
147 sigDataLen,
148 userData);
149 if(cfile == NULL) {
150 frtn = FR_Internal;
151 goto out;
152 }
153
154 out:
155 /* free alloc'd stuff */
156
157 if(cipherText) {
158 ffree(cipherText);
159 }
160 if(feed) {
161 feeFEEDExpFree(feed);
162 }
163 if(frand) {
164 feeRandFree(frand);
165 }
166 if(des) {
167 feeDESFree(des);
168 }
169 if(sigData) {
170 ffree(sigData);
171 }
172 if(encrDesKey) {
173 ffree(encrDesKey);
174 }
175 if(pubKeyString) {
176 ffree(pubKeyString);
177 }
178 memset(desKey, 0, FEE_DES_MIN_STATE_SIZE);
179 *cipherFile = cfile;
180 return frtn;
181
182 }
183
184 feeReturn decryptRandDES(feeCipherFile cipherFile,
185 feePubKey recvPrivKey,
186 feePubKey sendPubKey, // optional
187 unsigned char **plainText, // RETURNED
188 unsigned *plainTextLen, // RETURNED
189 feeSigStatus *sigStatus) // RETURNED
190 {
191 feeReturn frtn = FR_Success;
192 unsigned char *cipherText = NULL;
193 unsigned cipherTextLen;
194 feeFEEDExp feed = NULL; // to decrypt desKey
195 feeDES des = NULL; // to decrypt cipherText
196 unsigned char *desKey;
197 unsigned desKeyLen;
198 unsigned char *encrDesKey = NULL; // FEED encrypted desKey
199 unsigned encrDesKeyLen;
200 unsigned char *sigData = NULL;
201 unsigned sigDataLen;
202 unsigned char *sendPubKeyStr = NULL;
203 unsigned sendPubKeyStrLen = 0;
204 feePubKey parsedSendPubKey = NULL;
205
206 if(feeCFileEncrType(cipherFile) != CFE_RandDES) {
207 frtn = FR_Internal;
208 goto out;
209 }
210
211 /*
212 * Get ciphertext and encrypted DES key from cipherFile
213 */
214 cipherText = feeCFileCipherText(cipherFile, &cipherTextLen);
215 if(cipherText == NULL) {
216 frtn = FR_BadCipherFile;
217 goto out;
218 }
219 encrDesKey = feeCFileOtherKeyData(cipherFile, &encrDesKeyLen);
220 if(encrDesKey == NULL) {
221 frtn = FR_BadCipherFile;
222 goto out;
223 }
224
225 /*
226 * FEED decrypt to get DES key
227 */
228 feed = feeFEEDExpNewWithPubKey(recvPrivKey, NULL, NULL);
229 if(feed == NULL) {
230 frtn = FR_BadPubKey;
231 goto out;
232 }
233 frtn = feeFEEDExpDecrypt(feed,
234 encrDesKey,
235 encrDesKeyLen,
236 &desKey,
237 &desKeyLen);
238 if(frtn) {
239 goto out;
240 }
241
242 /*
243 * Now DES decrypt the ciphertext
244 */
245 if(desKeyLen != FEE_DES_MIN_STATE_SIZE) {
246 frtn = FR_BadCipherFile;
247 goto out;
248 }
249 des = feeDESNewWithState(desKey, desKeyLen);
250 if(des == NULL) {
251 frtn = FR_Internal;
252 goto out;
253 }
254 frtn = feeDESDecrypt(des,
255 cipherText,
256 cipherTextLen,
257 plainText,
258 plainTextLen);
259 if(frtn) {
260 goto out;
261 }
262
263 sigData = feeCFileSigData(cipherFile, &sigDataLen);
264 if(sigData) {
265 feeReturn sigFrtn;
266
267 if(sendPubKey == NULL) {
268 /*
269 * Obtain sender's public key from cipherfile
270 */
271 sendPubKeyStr = feeCFileSendPubKeyData(cipherFile,
272 &sendPubKeyStrLen);
273 if(sendPubKeyStr == NULL) {
274 /*
275 * Hmm..shouldn't really happen, but let's
276 * press on.
277 */
278 *sigStatus = SS_PresentNoKey;
279 goto out;
280 }
281 parsedSendPubKey = feePubKeyAlloc();
282 frtn = feePubKeyInitFromKeyString(parsedSendPubKey,
283 (char *)sendPubKeyStr, sendPubKeyStrLen);
284 if(frtn) {
285 dbgLog(("parseRandDES: bad sendPubKeyStr\n"));
286 *sigStatus = SS_PresentNoKey;
287 goto out;
288 }
289 sendPubKey = parsedSendPubKey;
290 }
291 sigFrtn = feePubKeyVerifySignature(sendPubKey,
292 cipherText,
293 cipherTextLen,
294 sigData,
295 sigDataLen);
296 switch(sigFrtn) {
297 case FR_Success:
298 *sigStatus = SS_PresentValid;
299 break;
300 default:
301 *sigStatus = SS_PresentInvalid;
302 break;
303 }
304 }
305 else {
306 *sigStatus = SS_NotPresent;
307 }
308 out:
309 if(cipherText) {
310 ffree(cipherText);
311 }
312 if(feed) {
313 feeFEEDExpFree(feed);
314 }
315 if(des) {
316 feeDESFree(des);
317 }
318 if(desKey) {
319 memset(desKey, 0, desKeyLen);
320 ffree(desKey);
321 }
322 if(encrDesKey) {
323 ffree(encrDesKey);
324 }
325 if(sigData) {
326 ffree(sigData);
327 }
328 if(parsedSendPubKey) {
329 feePubKeyFree(parsedSendPubKey);
330 }
331 if(sendPubKeyStr) {
332 ffree(sendPubKeyStr);
333 }
334 return frtn;
335 }
336
337 feeReturn createPubDES(feePubKey sendPrivKey, // required
338 feePubKey recvPubKey,
339 const unsigned char *plainText,
340 unsigned plainTextLen,
341 int genSig, // 1 ==> generate signature
342 unsigned userData, // for caller's convenience
343 feeCipherFile *cipherFile) // RETURNED if successful
344 {
345 feeRand frand = NULL;
346 feeReturn frtn;
347 unsigned char *desKey;
348 unsigned desKeyLen;
349 feeDES des = NULL;
350 unsigned char *cipherText = NULL;
351 unsigned cipherTextLen;
352 unsigned char *sigData = NULL;
353 unsigned sigDataLen = 0;
354 feeCipherFile cfile = NULL;
355 unsigned char *pubKeyString = NULL;
356 unsigned pubKeyStringLen;
357
358 if((sendPrivKey == NULL) || (recvPubKey == NULL)) {
359 return FR_BadPubKey;
360 }
361
362 /*
363 * Get the public string version of sendPrivKey for embedding in
364 * cipherfile
365 */
366 frtn = feePubKeyCreateKeyString(sendPrivKey,
367 (char **)&pubKeyString,
368 &pubKeyStringLen);
369 if(frtn) {
370 goto out;
371 }
372
373 /*
374 * Obtain DES key via key exchange and get a feeDES object with it
375 */
376 frtn = feePubKeyCreatePad(sendPrivKey,
377 recvPubKey,
378 &desKey,
379 &desKeyLen);
380 if(frtn) {
381 goto out;
382 }
383 des = feeDESNewWithState(desKey, desKeyLen);
384 if(des == NULL) {
385 frtn = FR_Internal;
386 goto out;
387 }
388
389 /*
390 * Encrypt the plaintext via DES
391 */
392 frtn = feeDESEncrypt(des,
393 plainText,
394 plainTextLen,
395 &cipherText,
396 &cipherTextLen);
397 if(frtn) {
398 goto out;
399 }
400
401 if(genSig) {
402 /*
403 * We generate signature on ciphertext by convention.
404 */
405 frtn = feePubKeyCreateSignature(sendPrivKey,
406 cipherText,
407 cipherTextLen,
408 &sigData,
409 &sigDataLen);
410 if(frtn) {
411 goto out;
412 }
413 }
414
415 /*
416 * Cons up a cipherfile
417 */
418 cfile = feeCFileNewFromCipherText(CFE_PublicDES,
419 cipherText,
420 cipherTextLen,
421 pubKeyString,
422 pubKeyStringLen,
423 NULL, // otherKey
424 0,
425 sigData,
426 sigDataLen,
427 userData);
428 if(cfile == NULL) {
429 frtn = FR_Internal;
430 goto out;
431 }
432
433 out:
434 /* free alloc'd stuff */
435
436 if(cipherText) {
437 ffree(cipherText);
438 }
439 if(frand) {
440 feeRandFree(frand);
441 }
442 if(des) {
443 feeDESFree(des);
444 }
445 if(desKey) {
446 ffree(desKey);
447 }
448 if(sigData) {
449 ffree(sigData);
450 }
451 if(pubKeyString) {
452 ffree(pubKeyString);
453 }
454 *cipherFile = cfile;
455 return frtn;
456
457 }
458
459 feeReturn decryptPubDES(feeCipherFile cipherFile,
460 feePubKey recvPrivKey,
461 feePubKey sendPubKey,
462 unsigned char **plainText, // RETURNED
463 unsigned *plainTextLen, // RETURNED
464 feeSigStatus *sigStatus) // RETURNED
465 {
466 feeReturn frtn = FR_Success;
467 unsigned char *cipherText = NULL;
468 unsigned cipherTextLen;
469 feeDES des = NULL; // to decrypt cipherText
470 unsigned char *desKey;
471 unsigned desKeyLen;
472 unsigned char *sigData = NULL;
473 unsigned sigDataLen;
474 unsigned char *pubKeyString = NULL;
475 unsigned pubKeyStringLen;
476 feePubKey decryptPubKey = NULL; // from cipherfile
477
478 if(feeCFileEncrType(cipherFile) != CFE_PublicDES) {
479 frtn = FR_Internal;
480 goto out;
481 }
482
483 /*
484 * Get ciphertext and sender's public key from cipherFile
485 */
486 cipherText = feeCFileCipherText(cipherFile, &cipherTextLen);
487 if(cipherText == NULL) {
488 frtn = FR_BadCipherFile;
489 goto out;
490 }
491 pubKeyString = feeCFileSendPubKeyData(cipherFile, &pubKeyStringLen);
492 if(pubKeyString == NULL) {
493 frtn = FR_BadCipherFile;
494 goto out;
495 }
496 decryptPubKey = feePubKeyAlloc();
497 frtn = feePubKeyInitFromKeyString(decryptPubKey,
498 (char *)pubKeyString,
499 pubKeyStringLen);
500 if(frtn) {
501 goto out;
502 }
503
504 /*
505 * key exchange to get DES key
506 */
507 frtn = feePubKeyCreatePad(recvPrivKey,
508 decryptPubKey,
509 &desKey,
510 &desKeyLen);
511 if(frtn) {
512 goto out;
513 }
514
515 /*
516 * Now DES decrypt the ciphertext
517 */
518 if(desKeyLen < FEE_DES_MIN_STATE_SIZE) {
519 frtn = FR_BadCipherFile;
520 goto out;
521 }
522 des = feeDESNewWithState(desKey, desKeyLen);
523 if(des == NULL) {
524 frtn = FR_Internal;
525 goto out;
526 }
527 frtn = feeDESDecrypt(des,
528 cipherText,
529 cipherTextLen,
530 plainText,
531 plainTextLen);
532 if(frtn) {
533 goto out;
534 }
535
536 sigData = feeCFileSigData(cipherFile, &sigDataLen);
537 if(sigData) {
538 feeReturn sigFrtn;
539
540 if(sendPubKey == NULL) {
541 /*
542 * Use key embedded in cipherfile
543 */
544 sendPubKey = decryptPubKey;
545 }
546 sigFrtn = feePubKeyVerifySignature(sendPubKey,
547 cipherText,
548 cipherTextLen,
549 sigData,
550 sigDataLen);
551 switch(sigFrtn) {
552 case FR_Success:
553 *sigStatus = SS_PresentValid;
554 break;
555 default:
556 *sigStatus = SS_PresentInvalid;
557 break;
558 }
559 }
560 else {
561 *sigStatus = SS_NotPresent;
562 }
563 out:
564 if(cipherText) {
565 ffree(cipherText);
566 }
567 if(des) {
568 feeDESFree(des);
569 }
570 if(desKey) {
571 ffree(desKey);
572 }
573 if(pubKeyString) {
574 ffree(pubKeyString);
575 }
576 if(sigData) {
577 ffree(sigData);
578 }
579 if(decryptPubKey) {
580 feePubKeyFree(decryptPubKey);
581 }
582 return frtn;
583 }
584
585 #endif /* CRYPTKIT_CIPHERFILE_ENABLE */
586