Example #1
0
  std::vector<byte> encode_signature(CryptoPP::Integer r, CryptoPP::Integer s) {
    std::vector<byte> signature;
    signature.resize(64);

    r.Encode(signature.data(), 32);
    s.Encode(signature.data() + 32, 32);

    return signature;
  }
SecureBinaryData CryptoECDSA::SerializePublicKey(BTC_PUBKEY const & pubKey)
{
   BTC_ECPOINT publicPoint = pubKey.GetPublicElement();
   CryptoPP::Integer pubX = publicPoint.x;
   CryptoPP::Integer pubY = publicPoint.y;
   SecureBinaryData pubData(65);
   pubData.fill(0x04);  // we fill just to set the first byte...

   pubX.Encode(pubData.getPtr()+1,  32, UNSIGNED);
   pubY.Encode(pubData.getPtr()+33, 32, UNSIGNED);
   return pubData;
}
SecureBinaryData CryptoECDSA::SerializePrivateKey(BTC_PRIVKEY const & privKey)
{
   CryptoPP::Integer privateExp = privKey.GetPrivateExponent();
   SecureBinaryData privKeyData(32);
   privateExp.Encode(privKeyData.getPtr(), privKeyData.getSize(), UNSIGNED);
   return privKeyData;
}
Example #4
0
 const vector<unsigned char> CryptoPpDlogZpSafePrime::decodeGroupElementToByteArray(GroupElement * groupElement) {
	 ZpSafePrimeElementCryptoPp * zp_element = dynamic_cast<ZpSafePrimeElementCryptoPp *>(groupElement);
	 if (!(zp_element))
		 throw invalid_argument("element type doesn't match the group type");

	 //Given a group element y, find the two inverses z,-z. Take z to be the value between 1 and (p-1)/2. Return s=z-1
	 biginteger y = zp_element->getElementValue();
	 biginteger p = ((ZpGroupParams * ) groupParams)->getP();

	 MathAlgorithms::SquareRootResults roots = MathAlgorithms::sqrtModP_3_4(y, p);

	 biginteger goodRoot;
	 biginteger halfP = (p - 1) / 2;
	 if (roots.getRoot1()>1 && roots.getRoot1() < halfP)
		 goodRoot = roots.getRoot1();
	 else
		 goodRoot = roots.getRoot2();
	 goodRoot -= 1;

	 CryptoPP::Integer cpi = biginteger_to_cryptoppint(goodRoot);
	 int len = ceil((cpi.BitCount() + 1) / 8.0); //ceil(find_log2_floor(goodRoot) / 8.0);
	 byte * output = new byte[len];
	 cpi.Encode(output, len);
	 vector<byte> res;
	 
	 // Remove the padding byte at the most significant position (that was added while encoding)
	 for (int i = 1; i < len; ++i)
		 res.push_back(output[i]);
	 return res;
 }
SecureBinaryData CryptoECDSA::InvMod(const SecureBinaryData& m)
{
   static BinaryData N = BinaryData::CreateFromHex(
           "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
   CryptoPP::Integer cppM;
   CryptoPP::Integer cppModulo;
   cppM.Decode(m.getPtr(), m.getSize(), UNSIGNED);
   cppModulo.Decode(N.getPtr(), N.getSize(), UNSIGNED);
   CryptoPP::Integer cppResult = cppM.InverseMod(cppModulo);
   SecureBinaryData result(32);
   cppResult.Encode(result.getPtr(), result.getSize(), UNSIGNED);
   return result;
}
Example #6
0
	std::string security::str(const CryptoPP::Integer& input)
	{
		const auto input_size = input.MinEncodedSize();
		CryptoPP::SecByteBlock block(input_size);
		input.Encode(block.BytePtr(), input_size);

		return str(block);
		
		// NOTE: CryptoPP::Integer has a weird ostream format (uses prefixes to specify numeric base)
		//
		/*std::ostringstream oss;
		oss << std::hex << input;
		return oss.str();*/
	}
Example #7
0
CK_RV CKKeyObject::CopyInteger(CK_ATTRIBUTE& attribute,
							   const CryptoPP::Integer& intValue) const
{
	CK_ULONG intSize = intValue.MinEncodedSize();
	if (attribute.pValue == NULL_PTR)
	{
		attribute.ulValueLen = intSize;
	}
	else if (attribute.ulValueLen < intSize)
	{
		attribute.ulValueLen = (CK_ULONG)-1;
		return CKR_BUFFER_TOO_SMALL;
	}
	else
	{
		attribute.ulValueLen = intSize;
		intValue.Encode((byte*)attribute.pValue, attribute.ulValueLen);
	}
	return CKR_OK;
}
/////////////////////////////////////////////////////////////////////////////
// Deterministically generate new private key using a chaincode
// Changed:  added using the hash of the public key to the mix
//           b/c multiplying by the chaincode alone is too "linear"
//           (there's no reason to believe it's insecure, but it doesn't
//           hurt to add some extra entropy/non-linearity to the chain
//           generation process)
SecureBinaryData CryptoECDSA::ComputeChainedPrivateKey(
                                 SecureBinaryData const & binPrivKey,
                                 SecureBinaryData const & chainCode,
                                 SecureBinaryData binPubKey,
                                 SecureBinaryData* multiplierOut)
{
   if(CRYPTO_DEBUG)
   {
      cout << "ComputeChainedPrivateKey:" << endl;
      cout << "   BinPrv: " << binPrivKey.toHexStr() << endl;
      cout << "   BinChn: " << chainCode.toHexStr() << endl;
      cout << "   BinPub: " << binPubKey.toHexStr() << endl;
   }


   if( binPubKey.getSize()==0 )
      binPubKey = ComputePublicKey(binPrivKey);

   if( binPrivKey.getSize() != 32 || chainCode.getSize() != 32)
   {
      LOGERR << "***ERROR:  Invalid private key or chaincode (both must be 32B)";
      LOGERR << "BinPrivKey: " << binPrivKey.getSize();
      LOGERR << "BinPrivKey: (not logged for security)";
      //LOGERR << "BinPrivKey: " << binPrivKey.toHexStr();
      LOGERR << "BinChain  : " << chainCode.getSize();
      LOGERR << "BinChain  : " << chainCode.toHexStr();
   }

   // Adding extra entropy to chaincode by xor'ing with hash256 of pubkey
   BinaryData chainMod  = binPubKey.getHash256();
   BinaryData chainOrig = chainCode.getRawCopy();
   BinaryData chainXor(32);
      
   for(uint8_t i=0; i<8; i++)
   {
      uint8_t offset = 4*i;
      *(uint32_t*)(chainXor.getPtr()+offset) =
                           *(uint32_t*)( chainMod.getPtr()+offset) ^ 
                           *(uint32_t*)(chainOrig.getPtr()+offset);
   }


   // Hard-code the order of the group
   static SecureBinaryData SECP256K1_ORDER_BE = SecureBinaryData().CreateFromHex(
           "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
   
   CryptoPP::Integer mult, origPrivExp, ecOrder;
   // A 
   mult.Decode(chainXor.getPtr(), chainXor.getSize(), UNSIGNED);
   // B 
   origPrivExp.Decode(binPrivKey.getPtr(), binPrivKey.getSize(), UNSIGNED);
   // C
   ecOrder.Decode(SECP256K1_ORDER_BE.getPtr(), SECP256K1_ORDER_BE.getSize(), UNSIGNED);

   // A*B mod C will get us a new private key exponent
   CryptoPP::Integer newPrivExponent = 
                  a_times_b_mod_c(mult, origPrivExp, ecOrder);

   // Convert new private exponent to big-endian binary string 
   SecureBinaryData newPrivData(32);
   newPrivExponent.Encode(newPrivData.getPtr(), newPrivData.getSize(), UNSIGNED);

   if(multiplierOut != NULL)
      (*multiplierOut) = SecureBinaryData(chainXor);

   //LOGINFO << "Computed new chained private key using:";
   //LOGINFO << "   Public key: " << binPubKey.toHexStr().c_str();
   //LOGINFO << "   PubKeyHash: " << chainMod.toHexStr().c_str();
   //LOGINFO << "   Chaincode:  " << chainOrig.toHexStr().c_str();
   //LOGINFO << "   Multiplier: " << chainXor.toHexStr().c_str();

   return newPrivData;
}
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;
	}
}
Example #11
0
void Send(SOCKET s, CryptoPP::Integer item){
	byte output[128];
	item.Encode(output, 128);
	send(s, (char *)output, 128, 0);
}
Example #12
0
int CEncryptedStreamSocket::Negotiate(const uint8* pBuffer, uint32 nLen)
{
	uint32_t nRead = 0;
	wxASSERT( m_nReceiveBytesWanted > 0 );

	//DumpMem(pBuffer, nLen, wxT("Negotiate buffer: "));

	try {
		while (m_NegotiatingState != ONS_COMPLETE && m_nReceiveBytesWanted > 0) {
			if (m_nReceiveBytesWanted > 512) {
				wxFAIL;
				return 0;
			}

			const uint32_t nToRead =  std::min(nLen - nRead, m_nReceiveBytesWanted);
			//printf("Reading %i bytes, add from %i position on %i position\n",nToRead, nRead, (int)m_pfiReceiveBuffer.GetPosition());
			//DumpMem(pBuffer + nRead, nToRead, wxT("Recv Buffer: "));
			m_pfiReceiveBuffer.Write(pBuffer + nRead, nToRead);
			nRead += nToRead;
			m_nReceiveBytesWanted -= nToRead;
			if (m_nReceiveBytesWanted > 0)  {
				return nRead;
			}

			if (m_NegotiatingState != ONS_BASIC_CLIENTA_RANDOMPART && m_NegotiatingState != ONS_BASIC_SERVER_DHANSWER) {
				// We have the keys, decrypt
				//printf("We have the keys, so decrypt away on %s\n", (const char*) unicode2char(DbgGetIPString()));
				m_pfiReceiveBuffer.Encrypt();
			}

			m_pfiReceiveBuffer.Seek(0);

			switch (m_NegotiatingState) {
				case ONS_NONE: // would be a bug
					wxFAIL;
					return 0;
				case ONS_BASIC_CLIENTA_RANDOMPART: {
					//printf("We are on ONS_BASIC_CLIENTA_RANDOMPART, create the keys on %s\n", (const char*) unicode2char(DbgGetIPString()));
					// This creates the send/receive keys.

					uint8_t achKeyData[21];
					md4cpy(achKeyData, thePrefs::GetUserHash().GetHash());
					m_pfiReceiveBuffer.Read(achKeyData + 17, 4);

					achKeyData[16] = MAGICVALUE_REQUESTER;

					//DumpMem(achKeyData, sizeof(achKeyData), wxT("ach:"));

					MD5Sum md5(achKeyData, sizeof(achKeyData));
					//DumpMem(md5.GetRawHash(), 16, wxT("Md5:"));
					m_pfiReceiveBuffer.SetKey(md5);

					achKeyData[16] = MAGICVALUE_SERVER;
					md5.Calculate(achKeyData, sizeof(achKeyData));
					m_pfiSendBuffer.SetKey(md5);

					m_NegotiatingState = ONS_BASIC_CLIENTA_MAGICVALUE;
					m_nReceiveBytesWanted = 4;
					break;
				}
				case ONS_BASIC_CLIENTA_MAGICVALUE: {
					// Check the magic value to confirm encryption works.
					//printf("Creating magic value on negotiate on %s\n", (const char*) unicode2char(DbgGetIPString()));

					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
						//printf("Magic value works on %s\n", (const char*) unicode2char(DbgGetIPString()));
						m_NegotiatingState = ONS_BASIC_CLIENTA_METHODTAGSPADLEN;
						m_nReceiveBytesWanted = 3;
					} else {
						//printf("Wrong magic value: 0x%x != 0x%x on %s\n",dwValue, MAGICVALUE_SYNC, (const char*)unicode2char(DbgGetIPString()));
						//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: {
					// Get encryption method and padding.
					// Might fall back to padding process, but the bytes will be ignored.
					//printf("Getting encryption method on negotiation\n");

					m_dbgbyEncryptionSupported = m_pfiReceiveBuffer.ReadUInt8();
					m_dbgbyEncryptionRequested = m_pfiReceiveBuffer.ReadUInt8();

					if (m_dbgbyEncryptionRequested != ENM_OBFUSCATION) {
						//printf("Unsupported encryption method!\n");
//						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 > 0) {
						// No padding
						break;
					}
				}
				case ONS_BASIC_CLIENTA_PADDING: {
					//printf("Negotiating on padding, completing\n");
					// ignore the random bytes, send the response, set status complete
					CMemFile 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);

					amuleIPV4Address address;
					GetPeer(address);
					const uint8_t byPaddingLen = theApp->serverconnect->AwaitingTestFromIP(StringIPtoUint32(address.IPAddress())) ? 16 : (thePrefs::GetCryptTCPPaddingLength() + 1);
					uint8_t byPadding = (uint8_t)(GetRandomUint8() % byPaddingLen);

					fileResponse.WriteUInt8(byPadding);
					for (int i = 0; i < byPadding; i++) {
						fileResponse.WriteUInt8((uint8_t)rand());
					}
					SendNegotiatingData(fileResponse.GetRawBuffer(), (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: {
					//printf("Negotiating on magic value\n");
					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: {
					//printf("Negotiating on client B pad length\n");
					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:
					//printf("Negotiating on client B padding, handshake complete\n");
					// 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: {
					wxASSERT( !m_cryptDHA.IsZero() );
					uint8_t 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 = a_exp_b_mod_c(cryptDHAnswer, m_cryptDHA, cryptDHPrime);

					m_cryptDHA = 0;
					//DEBUG_ONLY( ZeroMemory(aBuffer, sizeof(aBuffer)) );
					wxASSERT( cryptResult.MinEncodedSize() <= PRIMESIZE_BYTES );

					// create the keys
					cryptResult.Encode(aBuffer, PRIMESIZE_BYTES);
					aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_REQUESTER;
					MD5Sum md5(aBuffer, sizeof(aBuffer));
					m_pfiSendBuffer.SetKey(md5);
					aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_SERVER;
					md5.Calculate(aBuffer, sizeof(aBuffer));
					m_pfiReceiveBuffer.SetKey(md5);

					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 > 0) {
						break;
					}
				case ONS_BASIC_SERVER_PADDING: {
					// ignore the random bytes (they are decrypted already), send the response, set status complete
					CMemFile 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);

					// Server callback connection only allows 16 bytes of padding.
					uint8_t byPadding = (uint8_t)(GetRandomUint8() % 16);
					fileResponse.WriteUInt8(byPadding);

					for (int i = 0; i < byPadding; i++) {
						fileResponse.WriteUInt8((uint8_t)rand());
					}

					m_NegotiatingState = ONS_BASIC_SERVER_DELAYEDSENDING;
					SendNegotiatingData(fileResponse.GetRawBuffer(), (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:
					wxFAIL;
			}
			m_pfiReceiveBuffer.ResetData();
		}
		return nRead;
	} catch(...) {
		// can only be caused by a bug in negationhandling, not by the datastream
		//error->Delete();
		//printf("Bug on negotiation?\n");
		wxFAIL;
		OnError(ERR_ENCRYPTION);
		m_pfiReceiveBuffer.ResetData();
		return (-1);
	}
}
Example #13
0
void CEncryptedStreamSocket::StartNegotiation(bool bOutgoing)
{
	//printf("Starting socket negotiation\n");
	if (!bOutgoing) {
		//printf("Incoming connection negotiation on %s\n", (const char*) unicode2char(DbgGetIPString()));
		m_NegotiatingState = ONS_BASIC_CLIENTA_RANDOMPART;
		m_StreamCryptState = ECS_NEGOTIATING;
		m_nReceiveBytesWanted = 4;
	} else if (m_StreamCryptState == ECS_PENDING) {
		//printf("Socket is client.pending on negotiation\n");
		CMemFile 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)(GetRandomUint8() % (thePrefs::GetCryptTCPPaddingLength() + 1));
		fileRequest.WriteUInt8(byPadding);
		for (int i = 0; i < byPadding; i++) {
			fileRequest.WriteUInt8(GetRandomUint8());
		}

		m_NegotiatingState = ONS_BASIC_CLIENTB_MAGICVALUE;
		m_StreamCryptState = ECS_NEGOTIATING;
		m_nReceiveBytesWanted = 4;

		SendNegotiatingData(fileRequest.GetRawBuffer(), (uint32_t)fileRequest.GetLength(), 5);
	} else if (m_StreamCryptState == ECS_PENDING_SERVER) {
		//printf("Socket is server.pending on negotiation\n");
		CMemFile fileRequest(113);
		const uint8_t bySemiRandomNotProtocolMarker = GetSemiRandomNotProtocolMarker();
		fileRequest.WriteUInt8(bySemiRandomNotProtocolMarker);

		m_cryptDHA.Randomize((CryptoPP::AutoSeededRandomPool&)GetRandomPool(), DHAGREEMENT_A_BITS); // our random a
		wxASSERT( 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 = a_exp_b_mod_c(CryptoPP::Integer(2), m_cryptDHA, cryptDHPrime);
		wxASSERT( m_cryptDHA.MinEncodedSize() <= PRIMESIZE_BYTES );
		// put the result into a buffer
		uint8_t aBuffer[PRIMESIZE_BYTES];
		cryptDHGexpAmodP.Encode(aBuffer, PRIMESIZE_BYTES);

		fileRequest.Write(aBuffer, PRIMESIZE_BYTES);
		uint8 byPadding = (uint8)(GetRandomUint8() % 16); // add random padding
		fileRequest.WriteUInt8(byPadding);

		for (int i = 0; i < byPadding; i++) {
			fileRequest.WriteUInt8(GetRandomUint8());
		}

		m_NegotiatingState = ONS_BASIC_SERVER_DHANSWER;
		m_StreamCryptState = ECS_NEGOTIATING;
		m_nReceiveBytesWanted = 96;

		SendNegotiatingData(fileRequest.GetRawBuffer(), (uint32_t)fileRequest.GetLength(), (uint32_t)fileRequest.GetLength());
	} else {
		wxFAIL;
		m_StreamCryptState = ECS_NONE;
		return;
	}
}