X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_cryptkit/lib/CipherFileDES.c diff --git a/Security/libsecurity_cryptkit/lib/CipherFileDES.c b/Security/libsecurity_cryptkit/lib/CipherFileDES.c new file mode 100644 index 00000000..f4554ea9 --- /dev/null +++ b/Security/libsecurity_cryptkit/lib/CipherFileDES.c @@ -0,0 +1,586 @@ +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * CipherFileDES.c - DES-related cipherfile support + * + * Revision History + * ---------------- + * 24 Jun 97 at Apple + * Fixed memory leaks via sigData + * 18 Feb 97 at Apple + * Split off from feeCipherFile.c + */ + +#include "ckconfig.h" + +#if CRYPTKIT_CIPHERFILE_ENABLE + +#include "Crypt.h" +#include "CipherFileDES.h" +#include "falloc.h" +#include "feeDebug.h" +#include + +/* + * These functions are only called from feeCipherFile.c. + */ +feeReturn createRandDES(feePubKey sendPrivKey, // for sig only + feePubKey recvPubKey, + const unsigned char *plainText, + unsigned plainTextLen, + int genSig, // 1 ==> generate signature + unsigned userData, // for caller's convenience + feeCipherFile *cipherFile) // RETURNED if successful +{ + feeRand frand = NULL; + feeReturn frtn; + unsigned char desKey[FEE_DES_MIN_STATE_SIZE]; + unsigned char *encrDesKey = NULL; // FEED encrypted desKey + unsigned encrDesKeyLen; + feeDES des = NULL; + feeFEEDExp feed = NULL; + unsigned char *cipherText = NULL; + unsigned cipherTextLen; + unsigned char *sigData = NULL; + unsigned sigDataLen = 0; + feeCipherFile cfile = NULL; + unsigned char *pubKeyString = NULL; // of sendPrivKey + unsigned pubKeyStringLen = 0; + + if(recvPubKey == NULL) { + return FR_BadPubKey; + } + + /* + * Cons up random DES key and a feeDES object with it + */ + frand = feeRandAlloc(); + if(frand == NULL) { + frtn = FR_Internal; + goto out; + } + feeRandBytes(frand, desKey, FEE_DES_MIN_STATE_SIZE); + des = feeDESNewWithState(desKey, FEE_DES_MIN_STATE_SIZE); + if(des == NULL) { + frtn = FR_Internal; + goto out; + } + + /* + * Encrypt the DES key via FEEDExp + */ + feed = feeFEEDExpNewWithPubKey(recvPubKey, NULL, NULL); + if(feed == NULL) { + frtn = FR_BadPubKey; + goto out; + } + frtn = feeFEEDExpEncrypt(feed, + desKey, + FEE_DES_MIN_STATE_SIZE, + &encrDesKey, + &encrDesKeyLen); + if(frtn) { + goto out; + } + + /* + * Encrypt the plaintext via DES + */ + frtn = feeDESEncrypt(des, + plainText, + plainTextLen, + &cipherText, + &cipherTextLen); + if(frtn) { + goto out; + } + + if(genSig) { + /* + * We generate signature on ciphertext by convention. + */ + if(sendPrivKey == NULL) { + frtn = FR_BadPubKey; + goto out; + } + frtn = feePubKeyCreateSignature(sendPrivKey, + cipherText, + cipherTextLen, + &sigData, + &sigDataLen); + if(frtn) { + goto out; + } + /* + * Sender's public key string + */ + frtn = feePubKeyCreateKeyString(sendPrivKey, + (char **)&pubKeyString, + &pubKeyStringLen); + if(frtn) { + /* + * Huh? + */ + frtn = FR_BadPubKey; + goto out; + } + } + + /* + * Cons up a cipherfile + */ + cfile = feeCFileNewFromCipherText(CFE_RandDES, + cipherText, + cipherTextLen, + pubKeyString, + pubKeyStringLen, + encrDesKey, + encrDesKeyLen, + sigData, + sigDataLen, + userData); + if(cfile == NULL) { + frtn = FR_Internal; + goto out; + } + +out: + /* free alloc'd stuff */ + + if(cipherText) { + ffree(cipherText); + } + if(feed) { + feeFEEDExpFree(feed); + } + if(frand) { + feeRandFree(frand); + } + if(des) { + feeDESFree(des); + } + if(sigData) { + ffree(sigData); + } + if(encrDesKey) { + ffree(encrDesKey); + } + if(pubKeyString) { + ffree(pubKeyString); + } + memset(desKey, 0, FEE_DES_MIN_STATE_SIZE); + *cipherFile = cfile; + return frtn; + +} + +feeReturn decryptRandDES(feeCipherFile cipherFile, + feePubKey recvPrivKey, + feePubKey sendPubKey, // optional + unsigned char **plainText, // RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus) // RETURNED +{ + feeReturn frtn = FR_Success; + unsigned char *cipherText = NULL; + unsigned cipherTextLen; + feeFEEDExp feed = NULL; // to decrypt desKey + feeDES des = NULL; // to decrypt cipherText + unsigned char *desKey; + unsigned desKeyLen; + unsigned char *encrDesKey = NULL; // FEED encrypted desKey + unsigned encrDesKeyLen; + unsigned char *sigData = NULL; + unsigned sigDataLen; + unsigned char *sendPubKeyStr = NULL; + unsigned sendPubKeyStrLen = 0; + feePubKey parsedSendPubKey = NULL; + + if(feeCFileEncrType(cipherFile) != CFE_RandDES) { + frtn = FR_Internal; + goto out; + } + + /* + * Get ciphertext and encrypted DES key from cipherFile + */ + cipherText = feeCFileCipherText(cipherFile, &cipherTextLen); + if(cipherText == NULL) { + frtn = FR_BadCipherFile; + goto out; + } + encrDesKey = feeCFileOtherKeyData(cipherFile, &encrDesKeyLen); + if(encrDesKey == NULL) { + frtn = FR_BadCipherFile; + goto out; + } + + /* + * FEED decrypt to get DES key + */ + feed = feeFEEDExpNewWithPubKey(recvPrivKey, NULL, NULL); + if(feed == NULL) { + frtn = FR_BadPubKey; + goto out; + } + frtn = feeFEEDExpDecrypt(feed, + encrDesKey, + encrDesKeyLen, + &desKey, + &desKeyLen); + if(frtn) { + goto out; + } + + /* + * Now DES decrypt the ciphertext + */ + if(desKeyLen != FEE_DES_MIN_STATE_SIZE) { + frtn = FR_BadCipherFile; + goto out; + } + des = feeDESNewWithState(desKey, desKeyLen); + if(des == NULL) { + frtn = FR_Internal; + goto out; + } + frtn = feeDESDecrypt(des, + cipherText, + cipherTextLen, + plainText, + plainTextLen); + if(frtn) { + goto out; + } + + sigData = feeCFileSigData(cipherFile, &sigDataLen); + if(sigData) { + feeReturn sigFrtn; + + if(sendPubKey == NULL) { + /* + * Obtain sender's public key from cipherfile + */ + sendPubKeyStr = feeCFileSendPubKeyData(cipherFile, + &sendPubKeyStrLen); + if(sendPubKeyStr == NULL) { + /* + * Hmm..shouldn't really happen, but let's + * press on. + */ + *sigStatus = SS_PresentNoKey; + goto out; + } + parsedSendPubKey = feePubKeyAlloc(); + frtn = feePubKeyInitFromKeyString(parsedSendPubKey, + (char *)sendPubKeyStr, sendPubKeyStrLen); + if(frtn) { + dbgLog(("parseRandDES: bad sendPubKeyStr\n")); + *sigStatus = SS_PresentNoKey; + goto out; + } + sendPubKey = parsedSendPubKey; + } + sigFrtn = feePubKeyVerifySignature(sendPubKey, + cipherText, + cipherTextLen, + sigData, + sigDataLen); + switch(sigFrtn) { + case FR_Success: + *sigStatus = SS_PresentValid; + break; + default: + *sigStatus = SS_PresentInvalid; + break; + } + } + else { + *sigStatus = SS_NotPresent; + } +out: + if(cipherText) { + ffree(cipherText); + } + if(feed) { + feeFEEDExpFree(feed); + } + if(des) { + feeDESFree(des); + } + if(desKey) { + memset(desKey, 0, desKeyLen); + ffree(desKey); + } + if(encrDesKey) { + ffree(encrDesKey); + } + if(sigData) { + ffree(sigData); + } + if(parsedSendPubKey) { + feePubKeyFree(parsedSendPubKey); + } + if(sendPubKeyStr) { + ffree(sendPubKeyStr); + } + return frtn; +} + +feeReturn createPubDES(feePubKey sendPrivKey, // required + feePubKey recvPubKey, + const unsigned char *plainText, + unsigned plainTextLen, + int genSig, // 1 ==> generate signature + unsigned userData, // for caller's convenience + feeCipherFile *cipherFile) // RETURNED if successful +{ + feeRand frand = NULL; + feeReturn frtn; + unsigned char *desKey; + unsigned desKeyLen; + feeDES des = NULL; + unsigned char *cipherText = NULL; + unsigned cipherTextLen; + unsigned char *sigData = NULL; + unsigned sigDataLen = 0; + feeCipherFile cfile = NULL; + unsigned char *pubKeyString = NULL; + unsigned pubKeyStringLen; + + if((sendPrivKey == NULL) || (recvPubKey == NULL)) { + return FR_BadPubKey; + } + + /* + * Get the public string version of sendPrivKey for embedding in + * cipherfile + */ + frtn = feePubKeyCreateKeyString(sendPrivKey, + (char **)&pubKeyString, + &pubKeyStringLen); + if(frtn) { + goto out; + } + + /* + * Obtain DES key via key exchange and get a feeDES object with it + */ + frtn = feePubKeyCreatePad(sendPrivKey, + recvPubKey, + &desKey, + &desKeyLen); + if(frtn) { + goto out; + } + des = feeDESNewWithState(desKey, desKeyLen); + if(des == NULL) { + frtn = FR_Internal; + goto out; + } + + /* + * Encrypt the plaintext via DES + */ + frtn = feeDESEncrypt(des, + plainText, + plainTextLen, + &cipherText, + &cipherTextLen); + if(frtn) { + goto out; + } + + if(genSig) { + /* + * We generate signature on ciphertext by convention. + */ + frtn = feePubKeyCreateSignature(sendPrivKey, + cipherText, + cipherTextLen, + &sigData, + &sigDataLen); + if(frtn) { + goto out; + } + } + + /* + * Cons up a cipherfile + */ + cfile = feeCFileNewFromCipherText(CFE_PublicDES, + cipherText, + cipherTextLen, + pubKeyString, + pubKeyStringLen, + NULL, // otherKey + 0, + sigData, + sigDataLen, + userData); + if(cfile == NULL) { + frtn = FR_Internal; + goto out; + } + +out: + /* free alloc'd stuff */ + + if(cipherText) { + ffree(cipherText); + } + if(frand) { + feeRandFree(frand); + } + if(des) { + feeDESFree(des); + } + if(desKey) { + ffree(desKey); + } + if(sigData) { + ffree(sigData); + } + if(pubKeyString) { + ffree(pubKeyString); + } + *cipherFile = cfile; + return frtn; + +} + +feeReturn decryptPubDES(feeCipherFile cipherFile, + feePubKey recvPrivKey, + feePubKey sendPubKey, + unsigned char **plainText, // RETURNED + unsigned *plainTextLen, // RETURNED + feeSigStatus *sigStatus) // RETURNED +{ + feeReturn frtn = FR_Success; + unsigned char *cipherText = NULL; + unsigned cipherTextLen; + feeDES des = NULL; // to decrypt cipherText + unsigned char *desKey; + unsigned desKeyLen; + unsigned char *sigData = NULL; + unsigned sigDataLen; + unsigned char *pubKeyString = NULL; + unsigned pubKeyStringLen; + feePubKey decryptPubKey = NULL; // from cipherfile + + if(feeCFileEncrType(cipherFile) != CFE_PublicDES) { + frtn = FR_Internal; + goto out; + } + + /* + * Get ciphertext and sender's public key from cipherFile + */ + cipherText = feeCFileCipherText(cipherFile, &cipherTextLen); + if(cipherText == NULL) { + frtn = FR_BadCipherFile; + goto out; + } + pubKeyString = feeCFileSendPubKeyData(cipherFile, &pubKeyStringLen); + if(pubKeyString == NULL) { + frtn = FR_BadCipherFile; + goto out; + } + decryptPubKey = feePubKeyAlloc(); + frtn = feePubKeyInitFromKeyString(decryptPubKey, + (char *)pubKeyString, + pubKeyStringLen); + if(frtn) { + goto out; + } + + /* + * key exchange to get DES key + */ + frtn = feePubKeyCreatePad(recvPrivKey, + decryptPubKey, + &desKey, + &desKeyLen); + if(frtn) { + goto out; + } + + /* + * Now DES decrypt the ciphertext + */ + if(desKeyLen < FEE_DES_MIN_STATE_SIZE) { + frtn = FR_BadCipherFile; + goto out; + } + des = feeDESNewWithState(desKey, desKeyLen); + if(des == NULL) { + frtn = FR_Internal; + goto out; + } + frtn = feeDESDecrypt(des, + cipherText, + cipherTextLen, + plainText, + plainTextLen); + if(frtn) { + goto out; + } + + sigData = feeCFileSigData(cipherFile, &sigDataLen); + if(sigData) { + feeReturn sigFrtn; + + if(sendPubKey == NULL) { + /* + * Use key embedded in cipherfile + */ + sendPubKey = decryptPubKey; + } + sigFrtn = feePubKeyVerifySignature(sendPubKey, + cipherText, + cipherTextLen, + sigData, + sigDataLen); + switch(sigFrtn) { + case FR_Success: + *sigStatus = SS_PresentValid; + break; + default: + *sigStatus = SS_PresentInvalid; + break; + } + } + else { + *sigStatus = SS_NotPresent; + } +out: + if(cipherText) { + ffree(cipherText); + } + if(des) { + feeDESFree(des); + } + if(desKey) { + ffree(desKey); + } + if(pubKeyString) { + ffree(pubKeyString); + } + if(sigData) { + ffree(sigData); + } + if(decryptPubKey) { + feePubKeyFree(decryptPubKey); + } + return frtn; +} + +#endif /* CRYPTKIT_CIPHERFILE_ENABLE */ +