📄 sec_de3s.cpp
字号:
// sec_de3s.cpp// code for sec_de3s.h// copyright SafeTP Development Group, Inc., 2000 Terms of use are as specified in license.txt#include <stdio.h> // printf#include <string.h> // strlen#include "sec_de3s.h" // this module#include "keyutils.h" // LoadKey#include "globrand.h" // getRandomBytes#include "exc.h" // xsecurity#include "warn.h" // warning#include "blokutil.h" // Left, Right, ||, etc.#include "sdsa.h" // DSA*#include "keydb.h" // handleServerKey#include "sockutil.h" // formatAddress// logging levels:// 0 no logging// 1 diagDataBlock1: keys and challenges// 2 everything#ifndef PROTOCOL_LOGGING# define PROTOCOL_LOGGING 0#endif#if PROTOCOL_LOGGING >= 1# define diagDataBlock1(block, label) block.print(label)#else# define diagDataBlock1(block, label)#endif#if PROTOCOL_LOGGING >= 2# define diagnostic printf# define diagDataBlock(block, label) diagDataBlock1(block, label)# define diagDataBlock2(block) diagDataBlock1(block, #block)#else static int dummyPrintf(char const *, ...) { return 0; }# define diagnostic dummyPrintf# define diagDataBlock(block, label)# define diagDataBlock2(block)#endif// temp#if 0# define tdiagnostic printf# define tdiagDataBlock(block, label) block.print(label)#else# define tdiagnostic dummyPrintf# define tdiagDataBlock(block, label)#endifstatic void loadKey(char const *name, DataBlock &block, bool forceprotected=false){ string s(name); if (!LoadKey(s, block, forceprotected)) { xfailure(stringb("LoadKey for " << name << " failed")); }}// ------------------ DE3S_Shared ---------------------------------DE3S_Shared::DE3S_Shared(bool ac) : sha1HMacSigner(NULL), sha1HMacVerifier(NULL), amClient(ac){}DE3S_Shared::~DE3S_Shared(){ delete sha1HMacSigner; delete sha1HMacVerifier;}// =================== DE3S_Control ==========================DE3S_Control::DE3S_Control(KeyEnvironment *env, IPAddress ma, IPAddress pa) : DE3S_Shared(env != NULL /*amClient*/), controlTripleDesEnc(NULL), controlTripleDesDec(NULL), myAddress(ma), peerAddress(pa), keyEnvironment(env){ if (amClient()) { // load client keys loadKey("ElGamal/public.key", clientElGamalPublicKey); diagDataBlock1(clientElGamalPublicKey, "ElGamal public key"); loadKey("ElGamal/private.key", clientElGamalPrivateKey); diagDataBlock1(clientElGamalPrivateKey, "ElGamal private key"); } else { // load server keys loadKey("DSA/public.key", brandedServerDSAPublicKey, true); // need to forceProtected, in case we're using KEYS_IN_REGISTRY diagDataBlock1(brandedServerDSAPublicKey, "branded DSA public key"); loadKey("DSA/private.key", serverDSAPrivateKey, true); // need to forceProtected, in case we're using KEYS_IN_REGISTRY diagDataBlock1(serverDSAPrivateKey, "DSA private key"); // de-brand public key (also verifies the brand) DSABrandedPublicKey branded(brandedServerDSAPublicKey); branded.DSAPublicKey::encode(serverDSAPublicKey); diagDataBlock1(serverDSAPublicKey, "DSA public key"); } state = S_SERVER_PUBLIC_KEY; sendSequenceNumber = INITIAL_SEQUENCE_NUMBER; receiveSequenceNumber = INITIAL_SEQUENCE_NUMBER;}DE3S_Control::~DE3S_Control(){ delete controlTripleDesEnc; delete controlTripleDesDec;}// ------------------- ADAT negotiation ----------------------// this returns true if the (client? "client" : "server")// is sending data in this statebool DE3S_Control::isSending(bool client) const{ if (client == true) { // client return state==S_CLIENT_PUBLIC_KEY || state==S_SERVER_CHALLENGE; } else { // server return state==S_SERVER_PUBLIC_KEY || state==S_MASTER_KEY; }}bool DE3S_Control::hasOutgoingAdat() const{ return isSending(amClient());}STATICDEF DataBlock DE3S_Control::makeUpChallenge(){ return getRandomBytes(CHALLENGE_LENGTH);}// return a datablock containing a string, *without* the null terminatorstatic DataBlock tagBlock(char const *tag){ return DataBlock(tag, strlen(tag));}DataBlock DE3S_Control::make3DESKey( char const *leftTag, char const *rightTag) const{ return Sha1(masterKey || tagBlock(leftTag)) || Left(4, Sha1(masterKey || tagBlock(rightTag)));}DataBlock DE3S_Control::makeShaHMacKey(char const *tag) const{ return Sha1(masterKey || tagBlock(tag));}DataBlock DE3S_Control::make3DESIV(char const *tag) const{ return Left(8, Sha1(masterKey || tagBlock(tag)));}void DE3S_Control::makeExtraKeys(){ // compute new keys clientControl3DesKey = make3DESKey("client 3des control left", "client 3des control right"); serverControl3DesKey = make3DESKey("server 3des control left", "server 3des control right"); clientControl3DesIV = make3DESIV("client control 3des iv"); serverControl3DesIV = make3DESIV("server control 3des iv"); clientData3DesKey = make3DESKey("client 3des data left", "client 3des data right"); serverData3DesKey = make3DESKey("server 3des data left", "server 3des data right"); clientSha1HMacKey = makeShaHMacKey("client shahmac"); serverSha1HMacKey = makeShaHMacKey("server shahmac"); // display them for diagnostic purposes diagDataBlock1(clientControl3DesKey, "client control 3DES key"); diagDataBlock1(serverControl3DesKey, "server control 3DES key"); diagDataBlock1(clientData3DesKey, "client data 3DES key"); diagDataBlock1(serverData3DesKey, "server data 3DES key"); diagDataBlock1(clientSha1HMacKey, "client SHA1HMAC key"); diagDataBlock1(serverSha1HMacKey, "server SHA1HMAC key"); // make 3des objects controlTripleDesEnc = new CBC3DESEncTrans( amClient()? clientControl3DesKey : serverControl3DesKey, amClient()? clientControl3DesIV : serverControl3DesIV); controlTripleDesDec = new CBC3DESDecTrans( amClient()? serverControl3DesKey : clientControl3DesKey, amClient()? serverControl3DesIV : clientControl3DesIV); // make sha1hmac objects sha1HMacSigner = new SHA1HMAC( amClient()? clientSha1HMacKey : serverSha1HMacKey); sha1HMacVerifier = new SHA1HMAC( amClient()? serverSha1HMacKey : clientSha1HMacKey);}void DE3S_Control::getNextOutgoingAdat(DataBlock &block){ if (amClient() == false) { // server if (state == S_SERVER_PUBLIC_KEY) { block = brandedServerDSAPublicKey; } else { xassert(state == S_MASTER_KEY); // compute challenge serverChallenge = makeUpChallenge(); diagDataBlock1(serverChallenge, "server challenge"); // compute master key masterKey = getRandomBytes(MASTER_KEY_LENGTH); diagDataBlock1(masterKey, "master key"); // compute final message block = elGamalEncrypt(clientElGamalPublicKey, masterKey) || clientChallenge || serverChallenge; appendIPAddress(block, myAddress); dsaSign(serverDSAPrivateKey, block); // compute the extra keys makeExtraKeys(); } } else { // client if (state == S_CLIENT_PUBLIC_KEY) { // compute challenge clientChallenge = makeUpChallenge(); diagDataBlock1(clientChallenge, "client challenge"); // compute final message block = clientElGamalPublicKey || clientChallenge; } else { xassert(state == S_SERVER_CHALLENGE); // compute the main keys makeExtraKeys(); // compute block to send block = serverChallenge; controlTripleDesEnc->trans(block); } } state = (State)(state + 1);}bool DE3S_Control::expectingIncomingAdat() const{ // I'm expecting data during precisely those states // where the other guy is sending data return isSending(!amClient());}void DE3S_Control::incomingAdat(DataBlock &block){ if (amClient() == false) { // server if (state == S_CLIENT_PUBLIC_KEY) { // pull apart client challenge and client ElGamal public key clientChallenge = removeBlock(block, CHALLENGE_LENGTH); diagDataBlock1(clientChallenge, "client challenge"); clientElGamalPublicKey = block; diagDataBlock1(clientElGamalPublicKey, "ElGamal public key"); } else { xassert(state == S_SERVER_CHALLENGE); // un-3des controlTripleDesDec->trans(block); diagDataBlock1(block, "client's challenge response"); // compare to serverChallenge if (block != serverChallenge) { xsecurity("Client failed server's challenge."); } else { diagnostic("client passed server's challenge\n"); } } } else { // client if (state == S_SERVER_PUBLIC_KEY) { // extract key brandedServerDSAPublicKey = block; diagDataBlock1(brandedServerDSAPublicKey, "branded DSA public key"); // de-brand key (and verify brand) DSABrandedPublicKey branded(brandedServerDSAPublicKey); branded.DSAPublicKey::encode(serverDSAPublicKey); diagDataBlock1(serverDSAPublicKey, "DSA public key"); // consult public-key database xassert(keyEnvironment != NULL); handleServerKey(brandedServerDSAPublicKey, peerAddress /*host ip*/, *keyEnvironment); } else { xassert(state == S_MASTER_KEY); // check the DSA signature dsaVerify(serverDSAPublicKey, block, "Server's signature is invalid."); // pull apart concatenated pieces IPAddress serverIP = removeIPAddress(block); if (serverIP != peerAddress) { // have to make a policy decision; the called code can // throw xsecurity if it doesn't want to allow it keyEnvironment->policy. serverIPMismatch(serverIP, peerAddress, serverDSAPublicKey); } serverChallenge = removeBlock(block, CHALLENGE_LENGTH); diagDataBlock1(serverChallenge, "server challenge"); DataBlock clientChallengeTry = removeBlock(block, CHALLENGE_LENGTH); diagDataBlock1(clientChallengeTry, "server's challenge response"); if (clientChallengeTry != clientChallenge) { xsecurity("Server failed client's challenge."); } else { diagnostic("server passed client's challenge\n"); } // what remains is the encrypted master key diagDataBlock1(block, "encrypted master key"); masterKey = elGamalDecrypt(clientElGamalPrivateKey, block); diagDataBlock1(masterKey, "master key"); } } state = (State)(state + 1);}// ---------------- Steady-state encoding --------------------------void DE3S_Control::encode(DataBlock &data){ int srclen = data.getDataLen(); xassert(state == S_AUTHENTICATED); tdiagDataBlock(data, "plaintext"); // append flag byte appendNBO32(data, FLAG_CONTROL | (amClient()? FLAG_CLIENT : FLAG_SERVER)); tdiagDataBlock(data, "with flags"); // append sequence number appendNBO32(data, sendSequenceNumber++); tdiagDataBlock(data, "with seqnum"); // append SHA1HMac code appendDigest(data, *sha1HMacSigner); tdiagDataBlock(data, "with signature"); // triple-des the thing controlTripleDesEnc->trans(data); tdiagDataBlock(data, "ciphertext"); xassert(data.getDataLen() <= maximumEncodedSize(srclen));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -