예제 #1
0
파일: Crypto.hpp 프로젝트: wumch/pvdesktop
    std::size_t genKeyIv(char* _chunk)
    {
        char* chunk = _chunk;
        CryptoPP::AutoSeededRandomPool rnd;

        {
            CryptoPP::SecByteBlock key(0x00, CryptoPP::AES::DEFAULT_KEYLENGTH);
            rnd.GenerateBlock(key, key.size());

            byte iv[CryptoPP::AES::BLOCKSIZE];
            rnd.GenerateBlock(iv, sizeof(iv));
            setEncKeyWithIv(key.data(), key.SizeInBytes(), iv, sizeof(iv));

            std::memcpy(chunk, key.data(), key.SizeInBytes());
            chunk += key.SizeInBytes();
            std::memcpy(chunk, iv, sizeof(iv));
            chunk += sizeof(iv);
        }

        {
            CryptoPP::SecByteBlock key(0x00, CryptoPP::AES::DEFAULT_KEYLENGTH);
            rnd.GenerateBlock(key, key.size());

            byte iv[CryptoPP::AES::BLOCKSIZE];
            rnd.GenerateBlock(iv, sizeof(iv));
            setDecKeyWithIv(key.data(), key.SizeInBytes(), iv, sizeof(iv));

            std::memcpy(chunk, key.data(), key.SizeInBytes());
            chunk += key.SizeInBytes();
            std::memcpy(chunk, iv, sizeof(iv));
            chunk += sizeof(iv);
        }
        return chunk - _chunk;
    }
예제 #2
0
uint32_t
generateWord32()
{
  static CryptoPP::AutoSeededRandomPool rng;

  return rng.GenerateWord32();
}
예제 #3
0
void VhsmTest::testMac() {
    VHSM vhsm;
    ClientId cid;
    cid.pid = 0; cid.veid = 0;
    std::string user = "******";
    std::string password = "******";

    unsigned int mdsize;

    char msg[BUF_SIZE];
    std::vector<char> md;

    CryptoPP::AutoSeededRandomPool rnd;
    rnd.GenerateBlock((byte*)msg, BUF_SIZE);

    byte realmd[CryptoPP::HMAC<CryptoPP::SHA1>::DIGESTSIZE];
    CryptoPP::HMAC<CryptoPP::SHA1>((byte*)"", 0).CalculateDigest(realmd, (byte*)msg, BUF_SIZE);

    VhsmSession s = vhsm.openSession(cid);
    CPPUNIT_ASSERT_MESSAGE("login user failed", vhsm.loginUser(user, password, s.sid()));
    CPPUNIT_ASSERT_MESSAGE("macInit failed", vhsm.macInit(HMAC, SHA1, s.sid(), "") == ERR_NO_ERROR);
    CPPUNIT_ASSERT_MESSAGE("unsupported method accepted", vhsm.macInit((VhsmMacMechanismId)0, (VhsmDigestMechanismId)0, s.sid(), "") == ERR_BAD_MAC_METHOD);
    CPPUNIT_ASSERT_MESSAGE("macUpdate failed", vhsm.macUpdate(s.sid(), std::string(msg, BUF_SIZE)) == ERR_NO_ERROR);
    CPPUNIT_ASSERT_MESSAGE("invalid session id accepted", vhsm.macUpdate(s.sid() + 1, std::string(msg, BUF_SIZE)) == ERR_MAC_NOT_INITIALIZED);
    CPPUNIT_ASSERT_MESSAGE("macGetSize failed", vhsm.macGetSize(s.sid(), &mdsize) == ERR_NO_ERROR);
    CPPUNIT_ASSERT_MESSAGE("wrong size returned", mdsize == CryptoPP::HMAC<CryptoPP::SHA1>::DIGESTSIZE);
    CPPUNIT_ASSERT_MESSAGE("invalid session id accepted", vhsm.macGetSize(s.sid() + 1, &mdsize) == ERR_MAC_NOT_INITIALIZED);
    CPPUNIT_ASSERT_MESSAGE("macFinal failed", vhsm.macFinal(s.sid(), md) == ERR_NO_ERROR);
    CPPUNIT_ASSERT_MESSAGE("double digest finalization", vhsm.macFinal(s.sid(), md) == ERR_MAC_NOT_INITIALIZED);
    CPPUNIT_ASSERT_MESSAGE("wrong digest", memcmp(realmd, md.data(), CryptoPP::HMAC<CryptoPP::SHA1>::DIGESTSIZE) == 0);
    CPPUNIT_ASSERT_MESSAGE("close session failed", vhsm.closeSession(cid, s));
}
예제 #4
0
SecureBinaryData SecureBinaryData::GenerateRandom(uint32_t numBytes)
{
   static CryptoPP::AutoSeededRandomPool prng;
   SecureBinaryData randData(numBytes);
   prng.GenerateBlock(randData.getPtr(), numBytes);
   return randData;  
}
예제 #5
0
파일: Reseed.cpp 프로젝트: hagen-i2p/i2pd
	int Reseeder::ReseedNowSU3 ()
	{
		CryptoPP::AutoSeededRandomPool rnd;
		auto ind = rnd.GenerateWord32 (0, httpReseedHostList.size() - 1);
		std::string reseedHost = httpReseedHostList[ind];
		return ReseedFromSU3 (reseedHost);
	}
예제 #6
0
void generateRandomKey(std::string name, byte* key, long unsigned int length)
{
	CryptoPP::AutoSeededRandomPool prng;

	//byte key[CryptoPP::AES::DEFAULT_KEYLENGTH];
	prng.GenerateBlock(key, length);

	std::string encoded;

	CryptoPP::StringSource(key, length, true,
		new CryptoPP::HexEncoder(
			new CryptoPP::StringSink(encoded)
		) // HexEncoder
	); // StringSource

		std::ofstream outfile;

	std::string keyFile = "keys/" + name + ".key";

	std::ofstream file_out(keyFile.c_str());
	if(file_out.is_open())
	{
		file_out << encoded;
	} //end if valid outfstream
	file_out.close();
}
예제 #7
0
 void AddressBook::HandleSubscriptionsUpdateTimer (const boost::system::error_code& ecode)
 {
     if (ecode != boost::asio::error::operation_aborted)
     {
         if (!m_SharedLocalDestination)
             return; // TODO: error handling
         if (m_IsLoaded && !m_IsDownloading && m_SharedLocalDestination->IsReady ())
         {
             // pick random subscription
             CryptoPP::AutoSeededRandomPool rnd;
             auto ind = rnd.GenerateWord32 (0, m_Subscriptions.size() - 1);  
             m_IsDownloading = true; 
             m_Subscriptions[ind]->CheckSubscription ();     
         }
         else
         {
             if (!m_IsLoaded)
                 LoadHosts ();
             // try it again later
             m_SubscriptionsUpdateTimer->expires_from_now (boost::posix_time::minutes(INITIAL_SUBSCRIPTION_RETRY_TIMEOUT));
             m_SubscriptionsUpdateTimer->async_wait (std::bind (&AddressBook::HandleSubscriptionsUpdateTimer,
                 this, std::placeholders::_1));
         }
     }
 }
예제 #8
0
void securityInfo::setPassword(const std::string &pw){ 
	password=pw;

	


  CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::SHA1> pbkdf;





  CryptoPP::AutoSeededRandomPool rng;

  rng.GenerateBlock(pwsalt,pwsalt.size());

 



  icpw=pbkdf.DeriveKey( key, key.size(), 0x00, (byte *) password.data(), password.size(),
	pwsalt, pwsalt.size(), 0,0.5);

  iciv=pbkdf.DeriveKey(iv, iv.size(), 0x00,(byte *) password.data(), password.size(), pwsalt, pwsalt.size(),
	0,0.5);
}
예제 #9
0
// --------------------------------------------------------------------------
document::document () :
 node(std::shared_ptr<document>(this, [](document*){})),
 m_implementation(m_document)
// --------------------------------------------------------------------------
{
  m_html = false;
  m_mode = no_quirks_mode;
  m_content_type = "application/xml";
  m_encoding = "utf-8";
  m_url = "about:blank";

  if (global_object)
  {
    m_origin = global_object->m_document->m_origin;
    m_script_origin = global_object->m_document->m_script_origin;
  }
  else
  {
    // Default is a globally unique identifier.
    // We'll just generate 32 random bytes as the ID.
    
    CryptoPP::AutoSeededRandomPool rng;
    CryptoPP::HexEncoder enc;
    byte bin[32];
    char hex[64];

    rng.GenerateBlock(bin, 32);
    enc.PutMessageEnd(bin, 32);
    enc.Get(reinterpret_cast<byte*>(hex), 64);
    
    m_origin = hex;
    m_script_origin = m_origin;
  }
}
예제 #10
0
static std::string generateChallenge()
{
    CryptoPP::AutoSeededRandomPool prng;
    CryptoPP::SecByteBlock seed(16);
    prng.GenerateBlock(seed, seed.size());
    std::string challenge;
    CryptoPP::ArraySource(seed, seed.size(), true, new CryptoPP::HexEncoder(new CryptoPP::StringSink(challenge)));
    return challenge;
}
예제 #11
0
int CEncryptedDatagramSocket::EncryptSendServer(uchar** ppbyBuf, int nBufLen, uint32 dwBaseKey) const{
	ASSERT( thePrefs.IsServerCryptLayerUDPEnabled() );
	ASSERT( dwBaseKey != 0 );
	
	uint8 byPadLen = 0;			// padding disabled for UDP currently
	uint32 nCryptedLen = nBufLen + byPadLen + CRYPT_HEADER_WITHOUTPADDING;
	uchar* pachCryptedBuffer = new uchar[nCryptedLen];
	
	uint16 nRandomKeyPart = (uint16)cryptRandomGen.GenerateWord32(0x0000, 0xFFFF);

	uchar achKeyData[7];
	memcpy(achKeyData, &dwBaseKey, 4);
	achKeyData[4] = MAGICVALUE_UDP_CLIENTSERVER;
	memcpy(achKeyData + 5, &nRandomKeyPart, 2);
	MD5Sum md5(achKeyData, sizeof(achKeyData));
	RC4_Key_Struct keySendKey;
	RC4CreateKey(md5.GetRawHash(), 16, &keySendKey, true);

	// create the semi random byte encryption header
	uint8 bySemiRandomNotProtocolMarker = 0;
	int i;
	for (i = 0; i < 128; i++){
		bySemiRandomNotProtocolMarker = cryptRandomGen.GenerateByte();
		if (bySemiRandomNotProtocolMarker != OP_EDONKEYPROT) // not allowed values
			break;
	}
	if (i >= 128){
		// either we have _real_ bad luck or the randomgenerator is a bit messed up
		ASSERT( false );
		bySemiRandomNotProtocolMarker = 0x01;
	}

	uint32 dwMagicValue = MAGICVALUE_UDP_SYNC_SERVER;
	pachCryptedBuffer[0] = bySemiRandomNotProtocolMarker;
	memcpy(pachCryptedBuffer + 1, &nRandomKeyPart, 2);
	RC4Crypt((uchar*)&dwMagicValue, pachCryptedBuffer + 3, 4, &keySendKey);
	RC4Crypt((uchar*)&byPadLen, pachCryptedBuffer + 7, 1, &keySendKey);

	for (int j = 0; j < byPadLen; j++){
		uint8 byRand = (uint8)rand();	// they actually dont really need to be random, but it doesn't hurts either
		RC4Crypt((uchar*)&byRand, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + j, 1, &keySendKey);
	}
	RC4Crypt(*ppbyBuf, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen, nBufLen, &keySendKey);
	delete[] *ppbyBuf;
	*ppbyBuf = pachCryptedBuffer;

	//Xman
	// Maella -Accurate measure of bandwidth: eDonkey data + control, network adapter-
	/*
	theStats.AddUpDataOverheadCrypt(nCryptedLen - nBufLen);
	*/
	theApp.pBandWidthControl->AddeMuleOutObfuscationUDP(nCryptedLen - nBufLen);
	//Xman end
	return nCryptedLen;
}
예제 #12
0
uint64_t
generateWord64()
{
  static CryptoPP::AutoSeededRandomPool rng;

  uint64_t random;

  rng.GenerateBlock(reinterpret_cast<unsigned char*>(&random), 8);

  return random;
}
예제 #13
0
bool encryptPacket(char* packet, byte* aes_key)
{
	try
	{
		std::string plaintext(packet);

		//Decode the key from the file
		GCM< AES >::Encryption p;
		//iv will help us with keying out cipher
		//it is also randomly generated
		byte iv[ AES::BLOCKSIZE ];
		CryptoPP::AutoSeededRandomPool prng;
		prng.GenerateBlock( iv, sizeof(iv) );

		//Merge the iv and key
		p.SetKeyWithIV( aes_key, CryptoPP::AES::DEFAULT_KEYLENGTH, iv, sizeof(iv) );

		//Encode the IV
		std::string encoded_iv;
		CryptoPP::StringSource(iv, sizeof(iv), true,
			new CryptoPP::HexEncoder(
				new CryptoPP::StringSink(encoded_iv)
			) // HexEncoder
		);

		//Create the ciphertext from the plaintext
		std::string ciphertext;
		CryptoPP::StringSource(plaintext, true,
			new CryptoPP::AuthenticatedEncryptionFilter(p,
				new CryptoPP::StringSink(ciphertext)
			)
		);

		//Encode the cipher to be sent
		std::string encodedCipher;
		CryptoPP::StringSource(ciphertext, true,
			new CryptoPP::HexEncoder(
				new CryptoPP::StringSink(encodedCipher)
			) // HexEncoder
		);

		//replace the packet with the econded ciphertext
		strcpy(packet, (encoded_iv+encodedCipher).c_str());
		packet[(encoded_iv+encodedCipher).size()] = '\0';
		//printf("Encrypted packet size: %d\n", (int)strlen(packet));
	}
	catch(std::exception e)
	{
		return false;
	}
	
	return true;
} //end encryptPacket function
예제 #14
0
파일: I2PControl.cpp 프로젝트: 01BTC10/i2pd
std::string I2PControlSession::generateToken() const
{
    byte random_data[I2P_CONTROL_TOKEN_SIZE] = {};
    CryptoPP::AutoSeededRandomPool rng;
    rng.GenerateBlock(random_data, I2P_CONTROL_TOKEN_SIZE);
    std::string token;
    CryptoPP::StringSource ss(
        random_data, I2P_CONTROL_TOKEN_SIZE, true,
        new CryptoPP::HexEncoder(new CryptoPP::StringSink(token))
    );
    return token;
}
예제 #15
0
bool
SecTpmFile::generateRandomBlock(uint8_t* res, size_t size)
{
  try {
    CryptoPP::AutoSeededRandomPool rng;
    rng.GenerateBlock(res, size);
    return true;
  }
  catch (const CryptoPP::Exception& e) {
    return false;
  }
}
예제 #16
0
bool Session::do_key_exchange()
{
   aes_buffer aes_tmp;

   CryptoPP::AutoSeededRandomPool prng;
   prng.GenerateBlock(this->aes.key, sizeof(aes_key));
   prng.GenerateBlock(this->aes.iv, sizeof(aes_iv));

   std::memcpy(&aes_tmp, &this->aes, sizeof(aes_buffer));

   CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption encryptor(aes_hard_key, sizeof(aes_key),
      aes_hard_iv);
   encryptor.ProcessData((uint8_t*)&aes_tmp, (uint8_t const*)&this->aes, sizeof(aes_buffer));

   return (write(this->fd, &aes_tmp, sizeof(aes_buffer)) > 0);
}
예제 #17
0
void Container::set_seed(CryptoPP::SecByteBlock seed)
{
	seed_ = seed;
	CryptoPP::AutoSeededRandomPool prng;
	CryptoPP::SecByteBlock t(seed.size());
	prng.GenerateBlock(t, t.size());
	for (auto p : mtl::count_until(t.size()))
	{
		seed_[p] ^= t[p];
	}
	prng_.IncorporateEntropy(seed_, seed_.size());

	//enhance pw
	for (auto b : seed)
	{
		enhanced_passphrase_.push_back(b);
	}
}
예제 #18
0
int s3fs_encrypt(int fd, byte *key)
{
  //randomly generate iv
  CryptoPP::AutoSeededRandomPool prng;
  byte iv[CryptoPP::AES::BLOCKSIZE];
  prng.GenerateBlock(iv, sizeof(iv));
  string rawiv(reinterpret_cast<char*>(iv), CryptoPP::AES::BLOCKSIZE), striv;
  CryptoPP::StringSource s2(rawiv, true,
    new CryptoPP::HexEncoder(
      new CryptoPP::StringSink(striv)
    )
  );

  //read file into char array
  int flength = lseek(fd, 0, SEEK_END);
  unsigned char* fcontents;
  fcontents = (unsigned char*) calloc(flength, sizeof(char));
  pread(fd, fcontents, flength, 0);
  string plain(reinterpret_cast<char*>(fcontents), flength);

  //encrypt plaintext into ciphertext
  string cipher;
  CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption e;
  e.SetKeyWithIV(key, CryptoPP::AES::DEFAULT_KEYLENGTH, iv);
  CryptoPP::StringSource ss(plain, true,
    new CryptoPP::StreamTransformationFilter(e,
      new CryptoPP::HexEncoder(
        new CryptoPP::StringSink(cipher)
      )
    )
  );

  //write iv and encrypted data to file
  string output = striv+cipher;
  const char *buf = output.c_str();
  pwrite(fd, buf, output.length(), 0);
  ftruncate(fd, output.length());

  return 0;
}
예제 #19
0
//Takes the socket and packet and sends the packet
bool sendPacket(long int &csock, void* packet)
{
	CryptoPP::AutoSeededRandomPool prng;
	sleepTime(prng.GenerateWord32()); //wait for random amount of time

	int length = 0;

	length = strlen((char*)packet);
	//printf("Packet size: %d\n", length);
	if(sizeof(int) != send(csock, &length, sizeof(int), 0))
	{
	    printf("[error] fail to send packet length\n");
	   	return false;
	}
	if(length != send(csock, packet, length, 0))
	{
	    printf("[error] fail to send packet\n");
	    return false;
	}

	return true;
}
예제 #20
0
void Pbkdf2::Work()
{
	static const unsigned _PBKDF2_BYTE_ = 512 / 8;

	boost::chrono::steady_clock::time_point start = boost::chrono::steady_clock::now();
	
	CryptoPP::SecByteBlock byte_Derived(_PBKDF2_BYTE_);
	CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::Whirlpool> pbkdf2;

	if(h_Worker == PBKDF2_GENERATE)
	{
		CryptoPP::SecByteBlock byte_Salt(_PBKDF2_BYTE_);
		CryptoPP::AutoSeededRandomPool RNG;
		RNG.GenerateBlock(byte_Salt, byte_Salt.size());
		CryptoPP::ArraySource(byte_Salt, byte_Salt.size(), true, new CryptoPP::HexEncoder(new CryptoPP::StringSink(h_Salt)));

		pbkdf2.DeriveKey(byte_Derived, byte_Derived.size(), 0x0, reinterpret_cast<const byte *>(h_Key.data()), h_Key.size(), reinterpret_cast<const byte *>(h_Salt.data()), h_Salt.size(), h_Iterations, 0);
		CryptoPP::ArraySource(byte_Derived, byte_Derived.size(), true, new CryptoPP::HexEncoder(new CryptoPP::StringSink(h_Hash)));
	}
	else if(h_Worker == PBKDF2_VALIDATE)
	{
		pbkdf2.DeriveKey(byte_Derived, byte_Derived.size(), 0x0, reinterpret_cast<const byte *>(h_Key.data()), h_Key.size(), reinterpret_cast<const byte *>(h_Salt.data()), h_Salt.size(), h_Iterations, 0);

		CryptoPP::SecByteBlock byte_Validate(_PBKDF2_BYTE_);
		CryptoPP::StringSource(h_Hash, true, new CryptoPP::HexDecoder(new CryptoPP::ArraySink(byte_Validate, byte_Validate.size())));

		// Length-constant comparison.
		unsigned diff = _PBKDF2_BYTE_ ^ _PBKDF2_BYTE_;
		for(unsigned i = 0; i < _PBKDF2_BYTE_; ++i)
		{
			diff |= byte_Derived[i] ^ byte_Validate[i];
		}
		h_Equal = diff == 0;
	}

	boost::chrono::steady_clock::duration duration = boost::chrono::steady_clock::now() - start;
	h_ExecTime = static_cast<unsigned>(boost::chrono::duration_cast<boost::chrono::milliseconds>(duration).count());
}
    QByteArray encrypt(QByteArray in) {
        byte iv[CryptoPP::AES::BLOCKSIZE];
        rnd.GenerateBlock(iv, CryptoPP::AES::BLOCKSIZE);
        QByteArray out = QByteArray((char*)iv, CryptoPP::AES::BLOCKSIZE);
        int inputSize = in.size();
        string cipher;

        CBC_Mode<AES>::Encryption aes(keyByte(), keySize(), iv);
        ArraySource((byte *)in.data(), inputSize, true, new StreamTransformationFilter(aes, new StringSink(cipher)));

        QByteArray encryptedBytes = QByteArray(cipher.c_str(), cipher.size());
        out.append(encryptedBytes);
        return out;
    }
예제 #22
0
//Function generates a random alphanumeric string of length len
std::string randomString(const unsigned int len)
{
    static const char alphanum[] =
        "0123456789"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";

	CryptoPP::AutoSeededRandomPool prng;
	std::string s = "";

	//When adding each letter, generate a new word32, 
	//then compute it modulo alphanum's size - 1
	for(unsigned int i = 0; i < len; ++i)
	{
		s += alphanum[prng.GenerateWord32() % (sizeof(alphanum) - 1)];
	} //end for generate random string

    /*std::string s = "";
    for (int i = 0; i < len; ++i) {
        s += alphanum[rand() % (sizeof(alphanum) - 1)];
    }
	*/
    return s;
}
예제 #23
0
void KadFileDownloader::Init()
{
	uchar achKeyData[21];
	uint32 m_nRandomKeyPart = cryptRandomGen.GenerateWord32();
	md4cpy(achKeyData,&KadUtil::client_hash);
	memcpy(achKeyData+17,&m_nRandomKeyPart,4);

	uchar md5sum[16]={0};
	MD5 md5;
	md5.Update(achKeyData,sizeof(achKeyData));
	md5.Final(md5sum);

	achKeyData[16] = MAGICVALUE_REQUESTER;
	m_pRC4SendKey= RC4CreateKey(md5sum,16,NULL);
	achKeyData[16] = MAGICVALUE_SERVER;
	md5.Update(achKeyData,sizeof(achKeyData));
	md5.Final(md5sum);
	m_pRC4ReceiveKey = RC4CreateKey(md5sum,16,NULL);

	creditsPool.InitalizeCrypting();
}
void CEncryptedStreamSocket::SetConnectionEncryption(bool bEnabled, const uchar* pTargetClientHash, bool bServerConnection){
	if (m_StreamCryptState != ECS_UNKNOWN && m_StreamCryptState != ECS_NONE){
		if (!m_StreamCryptState == ECS_NONE || bEnabled)
			ASSERT( false );
		return;
	}
	ASSERT( m_pRC4SendKey == NULL );
	ASSERT( m_pRC4ReceiveKey == NULL );

	if (bEnabled && pTargetClientHash != NULL && !bServerConnection){
		m_StreamCryptState = ECS_PENDING;
		// create obfuscation keys, see on top for key format

		// use the crypt random generator
		m_nRandomKeyPart = cryptRandomGen.GenerateWord32();

		uchar achKeyData[21];
		md4cpy(achKeyData, pTargetClientHash);
		memcpy(achKeyData + 17, &m_nRandomKeyPart, 4);
		
		achKeyData[16] = MAGICVALUE_REQUESTER;
		MD5Sum md5(achKeyData, sizeof(achKeyData));
		m_pRC4SendKey = RC4CreateKey(md5.GetRawHash(), 16, NULL);

		achKeyData[16] = MAGICVALUE_SERVER;
		md5.Calculate(achKeyData, sizeof(achKeyData));
		m_pRC4ReceiveKey = RC4CreateKey(md5.GetRawHash(), 16, NULL);
	}
	else if (bServerConnection && bEnabled){
		m_bServerCrypt = true;
		m_StreamCryptState = ECS_PENDING_SERVER;
	}
	else{
		ASSERT( !bEnabled );
		m_StreamCryptState = ECS_NONE;
	}
}
uint8_t CEncryptedStreamSocket::GetSemiRandomNotProtocolMarker() const{
	uint8_t bySemiRandomNotProtocolMarker = 0;
	int i;
	for (i = 0; i < 128; i++){
		bySemiRandomNotProtocolMarker = cryptRandomGen.GenerateByte();
		bool bOk = false;
		switch (bySemiRandomNotProtocolMarker){ // not allowed values
				case OP_EDONKEYPROT:
				case OP_PACKEDPROT:
				case OP_EMULEPROT:
					break;
				default:
					bOk = true;
		}
		if (bOk)
			break;
	}
	if (i >= 128){
		// either we have _real_ bad luck or the randomgenerator is a bit messed up
		ASSERT( false );
		bySemiRandomNotProtocolMarker = 0x01;
	}
	return bySemiRandomNotProtocolMarker;
}
예제 #26
0
void CUTPSocketListner::Send(const byte* Buff, size_t uSize, const struct sockaddr* sa, socklen_t sa_len, uint8 Type)
{
	TKeyMap::iterator I = m_SendKeys.find((struct sockaddr*)sa);
	if(I == m_SendKeys.end())
		return;
	I->second->LastActivity = GetCurTick();
	ASSERT(I->second->PassKey);

	if(uSize > 0xFFFF - 0x80)
	{
		ASSERT(0);
		return;
	}

	bool SendKey = false;
	int PadLen = 16;
	if(Type == 1) // if its a UTP packet lets be a bit smart
	{
		ASSERT(uSize >= 4);
		UUtpHdr UtpHdr;
		UtpHdr.Bits = *((uint32*)Buff);
		
		if(UtpHdr.Fields.type == 4) // ST_SYN
			SendKey = true; // we always send the passked on y UTP Sync packet

		if(UtpHdr.Fields.type == 0) // ST_DATA
			PadLen = 0; // we dont needto padd data frames as tahy may already on thair own have a random size
	}
	else //if(!I->second->bAck) // if we are not talking UDT lets always send the key just to be sure
		SendKey = true;


	char Buffer[0xFFFF];
	byte* pBuffer = (byte*)Buffer;
	size_t uLength = 0;

	CryptoPP::AutoSeededRandomPool rng;
	uint32 Rand = 0;
	rng.GenerateBlock((byte*)&Rand, sizeof(uint32));
	UHdr Hdr;
	Hdr.Fields.Type = Type;
	Hdr.Fields.Reserved = 0;
	Hdr.Fields.Discard = 0; // total drop ist (n+1)*256
	if(uSize >= 10 * 1024)
	   Hdr.Fields.Discard = 3; // discard only 1024 key bytes in total for large packets
	Hdr.Fields.HasKey = SendKey;
	if(PadLen)
		PadLen = (rand() % (PadLen + 1)) & 0x3F; // ensure 64 bytes are available for optional footer entries
	Hdr.Fields.PadLen = PadLen;
	//if(Hdr.Fields.Reserved != 0)
	//	Hdr.Fields.PadLen += 4;


	memcpy(pBuffer + uLength, &Rand, sizeof(uint32));			uLength += 4;
	memcpy(pBuffer + uLength, &Hdr.Bits, sizeof(uint32));		uLength += 4;
	if(Hdr.Fields.HasKey) {
		memcpy(pBuffer + uLength, &m_RecvKey, sizeof(uint64));	uLength += 8; }
	
	memcpy(pBuffer + uLength, Buff, uSize);						uLength += uSize;

	//if(Hdr.Fields.Reserved != 0) {
	//	memcpy(pBuffer + uLength, NEO_MAGIC, 4);				uLength += 4; }
	if(PadLen > 0) {
		rng.GenerateBlock(pBuffer + uLength, PadLen);			uLength += PadLen; }

	CryptoPP::Weak1::MD5 md5;
	md5.Update((byte*)&Rand, sizeof(Rand));
	md5.Update((byte*)&I->second->PassKey, sizeof(uint64));
	byte Hash[16];
	md5.Final(Hash);

//#ifdef _DEBUG
//	LogLine(LOG_INFO | LOG_DEBUG, L"Send to %s PassKey %I64u -> %s", 
//		CSafeAddress(sa, sa_len, sa_len == sizeof(sockaddr_in) ? CSafeAddress::eUTP_IP4 : CSafeAddress::eUTP_IP6).ToString().c_str(),
//		I->second->PassKey, ToHex(Hash, 16).c_str());
//#endif

	CryptoPP::Weak::ARC4::Encryption RC4;
	RC4.SetKey(Hash, 16);
	RC4.DiscardBytes(256);

	RC4.ProcessData(pBuffer + 4, pBuffer + 4, 4);
	if(Hdr.Fields.Discard)
		RC4.DiscardBytes(Hdr.Fields.Discard * 256);

	RC4.ProcessData(pBuffer + 8, pBuffer + 8, uLength - 8);

	sendto(m_Socket, Buffer, (int)uLength, 0, (struct sockaddr*)sa, sa_len);
}
예제 #27
0
// Encrypt packet. Key used:
// pachClientHashOrKadID != NULL									-> pachClientHashOrKadID
// pachClientHashOrKadID == NULL && bKad && nReceiverVerifyKey != 0 -> nReceiverVerifyKey
// else																-> ASSERT
int CEncryptedDatagramSocket::EncryptSendClient(uchar** ppbyBuf, int nBufLen, const uchar* pachClientHashOrKadID, bool bKad, uint32 nReceiverVerifyKey, uint32 nSenderVerifyKey) const{
	ASSERT( theApp.GetPublicIP() != 0 || bKad );
	ASSERT( thePrefs.IsClientCryptLayerSupported() );
	ASSERT( pachClientHashOrKadID != NULL || nReceiverVerifyKey != 0 );
	ASSERT( (nReceiverVerifyKey == 0 && nSenderVerifyKey == 0) || bKad );

	uint8 byPadLen = 0;			// padding disabled for UDP currently
	const uint32 nCryptHeaderLen = byPadLen + CRYPT_HEADER_WITHOUTPADDING + (bKad ? 8 : 0);
	
	uint32 nCryptedLen = nBufLen + nCryptHeaderLen;
	uchar* pachCryptedBuffer = new uchar[nCryptedLen];
	bool bKadRecKeyUsed = false;
	
	uint16 nRandomKeyPart = (uint16)cryptRandomGen.GenerateWord32(0x0000, 0xFFFF);
	MD5Sum md5;
	if (bKad){
		if ((pachClientHashOrKadID == NULL || isnulmd4(pachClientHashOrKadID)) && nReceiverVerifyKey != 0) {
			bKadRecKeyUsed = true;
			uchar achKeyData[6];
			PokeUInt32(achKeyData, nReceiverVerifyKey);
			PokeUInt16(achKeyData+4, nRandomKeyPart);
			md5.Calculate(achKeyData, sizeof(achKeyData));
			//DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by ReceiverKey (%u)"), nReceiverVerifyKey) );  
		}
		else if (pachClientHashOrKadID != NULL && !isnulmd4(pachClientHashOrKadID)) {
			uchar achKeyData[18];
			md4cpy(achKeyData, pachClientHashOrKadID);
			PokeUInt16(achKeyData+16, nRandomKeyPart);
			md5.Calculate(achKeyData, sizeof(achKeyData));
			//DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by Hash/NodeID %s"), md4str(pachClientHashOrKadID)) );  
		}
		else {
			ASSERT( false );
			delete[] pachCryptedBuffer;
			return nBufLen;
		}
	}
	else{
		uchar achKeyData[23];
		md4cpy(achKeyData, pachClientHashOrKadID);
		uint32 dwIP = theApp.GetPublicIP();
		memcpy(achKeyData+16, &dwIP, 4);
		memcpy(achKeyData+21, &nRandomKeyPart, 2);
		achKeyData[20] = MAGICVALUE_UDP;
		md5.Calculate(achKeyData, sizeof(achKeyData));
	}
	RC4_Key_Struct keySendKey;
	RC4CreateKey(md5.GetRawHash(), 16, &keySendKey, true);

	// create the semi random byte encryption header
	uint8 bySemiRandomNotProtocolMarker = 0;
	int i;
	for (i = 0; i < 128; i++){
		bySemiRandomNotProtocolMarker = cryptRandomGen.GenerateByte();
		bySemiRandomNotProtocolMarker = bKad ? (bySemiRandomNotProtocolMarker & 0xFE) : (bySemiRandomNotProtocolMarker | 0x01); // set the ed2k/kad marker bit
		if (bKad)
			bySemiRandomNotProtocolMarker = bKadRecKeyUsed ? ((bySemiRandomNotProtocolMarker & 0xFE) | 0x02) : (bySemiRandomNotProtocolMarker & 0xFC); // set the ed2k/kad and nodeid/reckey markerbit
		else
			bySemiRandomNotProtocolMarker = (bySemiRandomNotProtocolMarker | 0x01); // set the ed2k/kad marker bit
		
		bool bOk = false;
		switch (bySemiRandomNotProtocolMarker){ // not allowed values
			case OP_EMULEPROT:
			case OP_KADEMLIAPACKEDPROT:
			case OP_KADEMLIAHEADER:
			case OP_UDPRESERVEDPROT1:
			case OP_UDPRESERVEDPROT2:
			case OP_PACKEDPROT:
				break;
			default:
				bOk = true;
		}
		if (bOk)
			break;
	}
	if (i >= 128){
		// either we have _really_ bad luck or the randomgenerator is a bit messed up
		ASSERT( false );
		bySemiRandomNotProtocolMarker = 0x01;
	}

	uint32 dwMagicValue = MAGICVALUE_UDP_SYNC_CLIENT;
	pachCryptedBuffer[0] = bySemiRandomNotProtocolMarker;
	memcpy(pachCryptedBuffer + 1, &nRandomKeyPart, 2);
	RC4Crypt((uchar*)&dwMagicValue, pachCryptedBuffer + 3, 4, &keySendKey);
	RC4Crypt((uchar*)&byPadLen, pachCryptedBuffer + 7, 1, &keySendKey);

	for (int j = 0; j < byPadLen; j++){
		uint8 byRand = (uint8)rand();	// they actually dont really need to be random, but it doesn't hurts either
		RC4Crypt((uchar*)&byRand, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + j, 1, &keySendKey);
	}

	if (bKad){
		RC4Crypt((uchar*)&nReceiverVerifyKey, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen, 4, &keySendKey);
		RC4Crypt((uchar*)&nSenderVerifyKey, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen + 4, 4, &keySendKey);
	}

	RC4Crypt(*ppbyBuf, pachCryptedBuffer + nCryptHeaderLen, nBufLen, &keySendKey);
	delete[] *ppbyBuf;
	*ppbyBuf = pachCryptedBuffer;

	//Xman
	// Maella -Accurate measure of bandwidth: eDonkey data + control, network adapter-
	/*
	theStats.AddUpDataOverheadCrypt(nCryptedLen - nBufLen);
	*/
	theApp.pBandWidthControl->AddeMuleOutObfuscationUDP(nCryptedLen - nBufLen);
	//Xman end

	return nCryptedLen;
}
int CEncryptedStreamSocket::Negotiate(const uchar* pBuffer, uint32_t nLen){
	uint32_t nRead = 0;
	ASSERT( m_nReceiveBytesWanted > 0 );
	try{
		while (m_NegotiatingState != ONS_COMPLETE && m_nReceiveBytesWanted > 0){		
			if (m_nReceiveBytesWanted > 512){
				ASSERT( false );
				return 0;
			}
			
			if (m_pfiReceiveBuffer == NULL){
				BYTE* pReceiveBuffer = (BYTE*)malloc(512); // use a fixed size buffer
				if (pReceiveBuffer == NULL)
					AfxThrowMemoryException();
				m_pfiReceiveBuffer = new CSafeMemFile(pReceiveBuffer, 512);
			}
			const uint32_t nToRead =  min(nLen - nRead, m_nReceiveBytesWanted);
			m_pfiReceiveBuffer->Write(pBuffer + nRead, nToRead);
			nRead += nToRead;
			m_nReceiveBytesWanted -= nToRead;
			if (m_nReceiveBytesWanted > 0)
				return nRead;
			const uint32_t nCurrentBytesLen = (uint32_t)m_pfiReceiveBuffer->GetPosition();

			if (m_NegotiatingState != ONS_BASIC_CLIENTA_RANDOMPART && m_NegotiatingState != ONS_BASIC_SERVER_DHANSWER){ // don't have the keys yet
				BYTE* pCryptBuffer = m_pfiReceiveBuffer->Detach();
				RC4Crypt(pCryptBuffer, pCryptBuffer, nCurrentBytesLen, m_pRC4ReceiveKey);
				m_pfiReceiveBuffer->Attach(pCryptBuffer, 512);
			}
			m_pfiReceiveBuffer->SeekToBegin();

			switch (m_NegotiatingState){
				case ONS_NONE: // would be a bug
					ASSERT( false ); 
					return 0;
				case ONS_BASIC_CLIENTA_RANDOMPART:{
					ASSERT( m_pRC4ReceiveKey == NULL );

					uchar achKeyData[21];
					md4cpy(achKeyData, thePrefs.GetUserHash());
					achKeyData[16] = MAGICVALUE_REQUESTER;
					m_pfiReceiveBuffer->Read(achKeyData + 17, 4); // random key part sent from remote client

					MD5Sum md5(achKeyData, sizeof(achKeyData));
					m_pRC4ReceiveKey = RC4CreateKey(md5.GetRawHash(), 16, NULL);
					achKeyData[16] = MAGICVALUE_SERVER;
					md5.Calculate(achKeyData, sizeof(achKeyData));
					m_pRC4SendKey = RC4CreateKey(md5.GetRawHash(), 16, NULL);
						
					m_NegotiatingState = ONS_BASIC_CLIENTA_MAGICVALUE;
					m_nReceiveBytesWanted = 4;
					break;
				}
				case ONS_BASIC_CLIENTA_MAGICVALUE:{
					uint32_t dwValue = m_pfiReceiveBuffer->ReadUInt32();
					if (dwValue == MAGICVALUE_SYNC){
						// yup, the one or the other way it worked, this is an encrypted stream
						//DEBUG_ONLY( DebugLog(_T("Received proper magic value, clientIP: %s"), DbgGetIPString()) );
						// set the receiver key
						m_NegotiatingState = ONS_BASIC_CLIENTA_METHODTAGSPADLEN;
						m_nReceiveBytesWanted = 3;	
					}
					else{
						DebugLogError(_T("CEncryptedStreamSocket: Received wrong magic value from clientIP %s on a supposly encrytped stream / Wrong Header"), DbgGetIPString());
						OnError(ERR_ENCRYPTION);
						return (-1);
					}
					break;
			    }
				case ONS_BASIC_CLIENTA_METHODTAGSPADLEN:
					m_dbgbyEncryptionSupported = m_pfiReceiveBuffer->ReadUInt8();
					m_dbgbyEncryptionRequested = m_pfiReceiveBuffer->ReadUInt8();
					if (m_dbgbyEncryptionRequested != ENM_OBFUSCATION)
						AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Client %s preffered unsupported encryption method (%i)"), DbgGetIPString(), m_dbgbyEncryptionRequested);
					m_nReceiveBytesWanted = m_pfiReceiveBuffer->ReadUInt8();
					m_NegotiatingState = ONS_BASIC_CLIENTA_PADDING;
					//if (m_nReceiveBytesWanted > 16)
					//	AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Client %s sent more than 16 (%i) padding bytes"), DbgGetIPString(), m_nReceiveBytesWanted);
					if (m_nReceiveBytesWanted > 0)
						break;
				case ONS_BASIC_CLIENTA_PADDING:{
					// ignore the random bytes, send the response, set status complete
					CSafeMemFile fileResponse(26);
					fileResponse.WriteUInt32(MAGICVALUE_SYNC);
					const uint8_t bySelectedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version, so no need to look which the other client preferred
					fileResponse.WriteUInt8(bySelectedEncryptionMethod);
					
					SOCKADDR_IN sockAddr = {0};
					int nSockAddrLen = sizeof(sockAddr);
					GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);	
					const uint8_t byPaddingLen = theApp.serverconnect->AwaitingTestFromIP(sockAddr.sin_addr.S_un.S_addr) ? 16 : (thePrefs.GetCryptTCPPaddingLength() + 1);
					uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % byPaddingLen);
					
					fileResponse.WriteUInt8(byPadding);
					for (int i = 0; i < byPadding; i++)
						fileResponse.WriteUInt8(static_cast<uint8_t>(rand() & 0xFF));
					SendNegotiatingData(fileResponse.GetBuffer(), (uint32_t)fileResponse.GetLength());
					m_NegotiatingState = ONS_COMPLETE;
					m_StreamCryptState = ECS_ENCRYPTING;
					//DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (incoming)"), DbgGetIPString()) );
					break;
				}
				case ONS_BASIC_CLIENTB_MAGICVALUE:{
					if (m_pfiReceiveBuffer->ReadUInt32() != MAGICVALUE_SYNC){
						DebugLogError(_T("CEncryptedStreamSocket: EncryptedstreamSyncError: Client sent wrong Magic Value as answer, cannot complete handshake (%s)"), DbgGetIPString());
						OnError(ERR_ENCRYPTION);
						return (-1);
					}
					m_NegotiatingState = ONS_BASIC_CLIENTB_METHODTAGSPADLEN;
					m_nReceiveBytesWanted = 2;
					break;
				}
				case ONS_BASIC_CLIENTB_METHODTAGSPADLEN:{
					m_dbgbyEncryptionMethodSet = m_pfiReceiveBuffer->ReadUInt8();
					if (m_dbgbyEncryptionMethodSet != ENM_OBFUSCATION){
						DebugLogError( _T("CEncryptedStreamSocket: Client %s set unsupported encryption method (%i), handshake failed"), DbgGetIPString(), m_dbgbyEncryptionMethodSet);
						OnError(ERR_ENCRYPTION);
						return (-1);						
					}
					m_nReceiveBytesWanted = m_pfiReceiveBuffer->ReadUInt8();
					m_NegotiatingState = ONS_BASIC_CLIENTB_PADDING;
					if (m_nReceiveBytesWanted > 0)
						break;
				}
				case ONS_BASIC_CLIENTB_PADDING:
					// ignore the random bytes, the handshake is complete
					m_NegotiatingState = ONS_COMPLETE;
					m_StreamCryptState = ECS_ENCRYPTING;
					//DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (outgoing)"), DbgGetIPString()) );
					break;
				case ONS_BASIC_SERVER_DHANSWER:{
					ASSERT( !m_cryptDHA.IsZero() );
					uchar aBuffer[PRIMESIZE_BYTES + 1];
					m_pfiReceiveBuffer->Read(aBuffer, PRIMESIZE_BYTES);
					CryptoPP::Integer cryptDHAnswer((byte*)aBuffer, PRIMESIZE_BYTES);
					CryptoPP::Integer cryptDHPrime((byte*)dh768_p, PRIMESIZE_BYTES);  // our fixed prime
					CryptoPP::Integer cryptResult = CryptoPP::a_exp_b_mod_c(cryptDHAnswer, m_cryptDHA, cryptDHPrime);
					
					m_cryptDHA = 0;
					DEBUG_ONLY( ZeroMemory(aBuffer, sizeof(aBuffer)) );
					ASSERT( cryptResult.MinEncodedSize() <= PRIMESIZE_BYTES );
					
					// create the keys
					cryptResult.Encode(aBuffer, PRIMESIZE_BYTES);					
					aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_REQUESTER;
					MD5Sum md5(aBuffer, sizeof(aBuffer));
					m_pRC4SendKey = RC4CreateKey(md5.GetRawHash(), 16, NULL);
					aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_SERVER;
					md5.Calculate(aBuffer, sizeof(aBuffer));
					m_pRC4ReceiveKey = RC4CreateKey(md5.GetRawHash(), 16, NULL);

					m_NegotiatingState = ONS_BASIC_SERVER_MAGICVALUE;
					m_nReceiveBytesWanted = 4;
					break;
				}
				case ONS_BASIC_SERVER_MAGICVALUE:{
					uint32_t dwValue = m_pfiReceiveBuffer->ReadUInt32();
					if (dwValue == MAGICVALUE_SYNC){
						// yup, the one or the other way it worked, this is an encrypted stream
						DebugLog(_T("Received proper magic value after DH-Agreement from Serverconnection IP: %s"), DbgGetIPString());
						// set the receiver key
						m_NegotiatingState = ONS_BASIC_SERVER_METHODTAGSPADLEN;
						m_nReceiveBytesWanted = 3;	
					}
					else{
						DebugLogError(_T("CEncryptedStreamSocket: Received wrong magic value after DH-Agreement from Serverconnection"), DbgGetIPString());
						OnError(ERR_ENCRYPTION);
						return (-1);
					}
					break;
			    }
				case ONS_BASIC_SERVER_METHODTAGSPADLEN:
					m_dbgbyEncryptionSupported = m_pfiReceiveBuffer->ReadUInt8();
					m_dbgbyEncryptionRequested = m_pfiReceiveBuffer->ReadUInt8();
					if (m_dbgbyEncryptionRequested != ENM_OBFUSCATION)
						AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Server %s preffered unsupported encryption method (%i)"), DbgGetIPString(), m_dbgbyEncryptionRequested);
					m_nReceiveBytesWanted = m_pfiReceiveBuffer->ReadUInt8();
					m_NegotiatingState = ONS_BASIC_SERVER_PADDING;
					if (m_nReceiveBytesWanted > 16)
						AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Server %s sent more than 16 (%i) padding bytes"), DbgGetIPString(), m_nReceiveBytesWanted);
					if (m_nReceiveBytesWanted > 0)
						break;
				case ONS_BASIC_SERVER_PADDING:{
					// ignore the random bytes (they are decrypted already), send the response, set status complete
					CSafeMemFile fileResponse(26);
					fileResponse.WriteUInt32(MAGICVALUE_SYNC);
					const uint8_t bySelectedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version, so no need to look which the other client preferred
					fileResponse.WriteUInt8(bySelectedEncryptionMethod);
					uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % 16);
					fileResponse.WriteUInt8(byPadding);
					for (int i = 0; i < byPadding; i++)
						fileResponse.WriteUInt8(static_cast<uint8_t>(rand() & 0xFF));
					
					m_NegotiatingState = ONS_BASIC_SERVER_DELAYEDSENDING;
					SendNegotiatingData(fileResponse.GetBuffer(), (uint32_t)fileResponse.GetLength(), 0, true); // don't actually send it right now, store it in our sendbuffer
					m_StreamCryptState = ECS_ENCRYPTING;
					DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished DH Obufscation handshake with Server %s"), DbgGetIPString()) );
					break;
				}
				default:
					ASSERT( false );
			}
			m_pfiReceiveBuffer->SeekToBegin();
		}
		if (m_pfiReceiveBuffer != NULL)
			free(m_pfiReceiveBuffer->Detach());
		delete m_pfiReceiveBuffer;
		m_pfiReceiveBuffer = NULL;
		return nRead;
	}
	catch(CFileException* error){
		// can only be caused by a bug in negationhandling, not by the datastream
		error->Delete();
		ASSERT( false );
		OnError(ERR_ENCRYPTION);
		if (m_pfiReceiveBuffer != NULL)
			free(m_pfiReceiveBuffer->Detach());
		delete m_pfiReceiveBuffer;
		m_pfiReceiveBuffer = NULL;
		return (-1);
	}

}
void CEncryptedStreamSocket::StartNegotiation(bool bOutgoing){

	if (!bOutgoing){
		m_NegotiatingState = ONS_BASIC_CLIENTA_RANDOMPART;
		m_StreamCryptState = ECS_NEGOTIATING;
		m_nReceiveBytesWanted = 4;
	}
	else if (m_StreamCryptState == ECS_PENDING){
		
		CSafeMemFile fileRequest(29);
		const uint8_t bySemiRandomNotProtocolMarker = GetSemiRandomNotProtocolMarker();	
		fileRequest.WriteUInt8(bySemiRandomNotProtocolMarker);
		fileRequest.WriteUInt32(m_nRandomKeyPart);
		fileRequest.WriteUInt32(MAGICVALUE_SYNC);
		const uint8_t bySupportedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version
		fileRequest.WriteUInt8(bySupportedEncryptionMethod);
		fileRequest.WriteUInt8(bySupportedEncryptionMethod); // so we also prefer this one
		uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % (thePrefs.GetCryptTCPPaddingLength() + 1));
		fileRequest.WriteUInt8(byPadding);
		for (int i = 0; i < byPadding; i++)
			fileRequest.WriteUInt8(cryptRandomGen.GenerateByte());
		
		m_NegotiatingState = ONS_BASIC_CLIENTB_MAGICVALUE;
		m_StreamCryptState = ECS_NEGOTIATING;
		m_nReceiveBytesWanted = 4;
		
		SendNegotiatingData(fileRequest.GetBuffer(), (uint32_t)fileRequest.GetLength(), 5);
	}
	else if (m_StreamCryptState == ECS_PENDING_SERVER){
		CSafeMemFile fileRequest(113);
		const uint8_t bySemiRandomNotProtocolMarker = GetSemiRandomNotProtocolMarker();	
		fileRequest.WriteUInt8(bySemiRandomNotProtocolMarker);
		
		m_cryptDHA.Randomize(cryptRandomGen, DHAGREEMENT_A_BITS); // our random a
		ASSERT( m_cryptDHA.MinEncodedSize() <= DHAGREEMENT_A_BITS / 8 );
		CryptoPP::Integer cryptDHPrime((byte*)dh768_p, PRIMESIZE_BYTES);  // our fixed prime
		// calculate g^a % p
		CryptoPP::Integer cryptDHGexpAmodP = CryptoPP::a_exp_b_mod_c(CryptoPP::Integer(2), m_cryptDHA, cryptDHPrime);  
		ASSERT( m_cryptDHA.MinEncodedSize() <= PRIMESIZE_BYTES );
		// put the result into a buffer
		uchar aBuffer[PRIMESIZE_BYTES];
		cryptDHGexpAmodP.Encode(aBuffer, PRIMESIZE_BYTES);

		fileRequest.Write(aBuffer, PRIMESIZE_BYTES);
		uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % 16); // add random padding
		fileRequest.WriteUInt8(byPadding);
		for (int i = 0; i < byPadding; i++)
			fileRequest.WriteUInt8(cryptRandomGen.GenerateByte());
		
		m_NegotiatingState = ONS_BASIC_SERVER_DHANSWER;
		m_StreamCryptState = ECS_NEGOTIATING;
		m_nReceiveBytesWanted = 96;
		
		SendNegotiatingData(fileRequest.GetBuffer(), (uint32_t)fileRequest.GetLength(), (uint32_t)fileRequest.GetLength());
	}
	else{
		ASSERT( false );
		m_StreamCryptState = ECS_NONE;
		return;
	}
}
예제 #30
0
int CEncryptedDatagramSocket::EncryptSendClient(uchar** ppbyBuf, int nBufLen, const uchar* pachClientHashOrKadID, bool bKad, uint16 nReceiverVerifyKey, uint16 nSenderVerifyKey) const{
	ASSERT( theApp.GetPublicIP() != 0 || bKad );
	ASSERT( thePrefs.IsClientCryptLayerSupported() );

	uint8 byPadLen = 0;			// padding disabled for UDP currently
	const uint32 nCryptHeaderLen = byPadLen + CRYPT_HEADER_WITHOUTPADDING + (bKad ? 4 : 0);
	uint32 nCryptedLen = nBufLen + nCryptHeaderLen;
	uchar* pachCryptedBuffer = new uchar[nCryptedLen];
	
	uint16 nRandomKeyPart = (uint16)cryptRandomGen.GenerateWord32(0x0000, 0xFFFF);
	MD5Sum md5;
	if (bKad){
		uchar achKeyData[18];
		md4cpy(achKeyData, pachClientHashOrKadID);
		memcpy(achKeyData+16, &nRandomKeyPart, 2);
		md5.Calculate(achKeyData, sizeof(achKeyData));
	}
	else{
		uchar achKeyData[23];
		md4cpy(achKeyData, pachClientHashOrKadID);
		uint32 dwIP = theApp.GetPublicIP();
		memcpy(achKeyData+16, &dwIP, 4);
		memcpy(achKeyData+21, &nRandomKeyPart, 2);
		achKeyData[20] = MAGICVALUE_UDP;
		md5.Calculate(achKeyData, sizeof(achKeyData));
	}
	RC4_Key_Struct keySendKey;
	RC4CreateKey(md5.GetRawHash(), 16, &keySendKey, true);

	// create the semi random byte encryption header
	uint8 bySemiRandomNotProtocolMarker = 0;
	int i;
	for (i = 0; i < 128; i++){
		bySemiRandomNotProtocolMarker = cryptRandomGen.GenerateByte();
		bySemiRandomNotProtocolMarker = bKad ? (bySemiRandomNotProtocolMarker & 0xFE) : (bySemiRandomNotProtocolMarker | 0x01); // set the ed2k/kad marker bit

		bool bOk = false;
		switch (bySemiRandomNotProtocolMarker){ // not allowed values
			case OP_EMULEPROT:
			case OP_KADEMLIAPACKEDPROT:
			case OP_KADEMLIAHEADER:
			case OP_UDPRESERVEDPROT1:
			case OP_UDPRESERVEDPROT2:
			case OP_PACKEDPROT:
				break;
			default:
				bOk = true;
		}
		if (bOk)
			break;
	}
	if (i >= 128){
		// either we have _real_ bad luck or the randomgenerator is a bit messed up
		ASSERT( false );
		bySemiRandomNotProtocolMarker = 0x01;
	}

	uint32 dwMagicValue = MAGICVALUE_UDP_SYNC_CLIENT;
	pachCryptedBuffer[0] = bySemiRandomNotProtocolMarker;
	memcpy(pachCryptedBuffer + 1, &nRandomKeyPart, 2);
	RC4Crypt((uchar*)&dwMagicValue, pachCryptedBuffer + 3, 4, &keySendKey);
	RC4Crypt((uchar*)&byPadLen, pachCryptedBuffer + 7, 1, &keySendKey);

	for (int j = 0; j < byPadLen; j++){
		uint8 byRand = (uint8)rand();	// they actually dont really need to be random, but it doesn't hurts either
		RC4Crypt((uchar*)&byRand, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + j, 1, &keySendKey);
	}

	if (bKad){
		RC4Crypt((uchar*)&nReceiverVerifyKey, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen, 2, &keySendKey);
		RC4Crypt((uchar*)&nSenderVerifyKey, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen + 2, 2, &keySendKey);
	}

	RC4Crypt(*ppbyBuf, pachCryptedBuffer + nCryptHeaderLen, nBufLen, &keySendKey);
	delete[] *ppbyBuf;
	*ppbyBuf = pachCryptedBuffer;

	theStats.AddUpDataOverheadCrypt(nCryptedLen - nBufLen);
	return nCryptedLen;
}