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 * CipherFileDES.c - DES-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 "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 */ 34feeReturn 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 154out: 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 184feeReturn 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 } 308out: 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 337feeReturn 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 433out: 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 459feeReturn 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 } 563out: 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 587