Browse Source

hanshakes hash and finishes message

pull/163/head
orignal 10 years ago
parent
commit
29d118a19a
  1. 73
      Reseed.cpp
  2. 3
      Reseed.h

73
Reseed.cpp

@ -517,7 +517,7 @@ namespace data
0x00, // session id length 0x00, // session id length
0x00, 0x04, // chiper suites length 0x00, 0x04, // chiper suites length
0x00, 0x00, // NULL_WITH_NULL_NULL 0x00, 0x00, // NULL_WITH_NULL_NULL
0x00, 0x3D, // RSA_WITH_AES_256_CBC_SHA256 0x00, 0x35, // RSA_WITH_AES_256_CBC_SHA
0x01, // compression methods length 0x01, // compression methods length
0x00 // no compression 0x00 // no compression
}; };
@ -533,24 +533,38 @@ namespace data
// client key exchange RSA // client key exchange RSA
// 512 RSA encrypted 48 bytes ( 2 bytes version + 46 random bytes) // 512 RSA encrypted 48 bytes ( 2 bytes version + 46 random bytes)
}; };
static uint8_t finished[] =
{
0x16, // handshake
0x03, 0x02, // version (TSL 1.2)
0x00, 0x10, // length of handshake
// handshake
0x14, // handshake type (finished)
0x00, 0x00, 0x0C, // length of handshake payload
// 12 bytes of verified data
};
i2p::util::http::url u(address); i2p::util::http::url u(address);
boost::asio::ip::tcp::iostream site; boost::asio::ip::tcp::iostream site;
site.connect(u.host_, "443"); site.connect(u.host_, "443");
if (site.good ()) if (site.good ())
{ {
CryptoPP::SHA256 finishedHash;
// send ClientHello // send ClientHello
site.write ((char *)clientHello, sizeof (clientHello)); site.write ((char *)clientHello, sizeof (clientHello));
finishedHash.Update (clientHello, sizeof (clientHello));
// read ServerHello // read ServerHello
uint8_t type; uint8_t type;
site.read ((char *)&type, 1); site.read ((char *)&type, 1); finishedHash.Update ((uint8_t *)&type, 1);
uint16_t version; uint16_t version;
site.read ((char *)&version, 2); site.read ((char *)&version, 2); finishedHash.Update ((uint8_t *)&version, 2);
uint16_t length; uint16_t length;
site.read ((char *)&length, 2); site.read ((char *)&length, 2); finishedHash.Update ((uint8_t *)&length, 2);
length = be16toh (length); length = be16toh (length);
char * serverHello = new char[length]; char * serverHello = new char[length];
site.read (serverHello, length); site.read (serverHello, length);
finishedHash.Update ((uint8_t *)serverHello, length);
uint8_t serverRandom[32]; uint8_t serverRandom[32];
if (serverHello[0] == 0x02) // handshake type server hello if (serverHello[0] == 0x02) // handshake type server hello
memcpy (serverRandom, serverHello + 6, 32); memcpy (serverRandom, serverHello + 6, 32);
@ -558,12 +572,13 @@ namespace data
LogPrint (eLogError, "Unexpected handshake type ", (int)serverHello[0]); LogPrint (eLogError, "Unexpected handshake type ", (int)serverHello[0]);
delete[] serverHello; delete[] serverHello;
// read Certificate // read Certificate
site.read ((char *)&type, 1); site.read ((char *)&type, 1); finishedHash.Update ((uint8_t *)&type, 1);
site.read ((char *)&version, 2); site.read ((char *)&version, 2); finishedHash.Update ((uint8_t *)&version, 2);
site.read ((char *)&length, 2); site.read ((char *)&length, 2); finishedHash.Update ((uint8_t *)&length, 2);
length = be16toh (length); length = be16toh (length);
char * certificate = new char[length]; char * certificate = new char[length];
site.read (certificate, length); site.read (certificate, length);
finishedHash.Update ((uint8_t *)certificate, length);
CryptoPP::RSA::PublicKey publicKey; CryptoPP::RSA::PublicKey publicKey;
// 0 - handshake type // 0 - handshake type
// 1 - 3 - handshake payload length // 1 - 3 - handshake payload length
@ -585,12 +600,13 @@ namespace data
LogPrint (eLogError, "Unexpected handshake type ", (int)certificate[0]); LogPrint (eLogError, "Unexpected handshake type ", (int)certificate[0]);
delete[] certificate; delete[] certificate;
// read ServerHelloDone // read ServerHelloDone
site.read ((char *)&type, 1); site.read ((char *)&type, 1); finishedHash.Update ((uint8_t *)&type, 1);
site.read ((char *)&version, 2); site.read ((char *)&version, 2); finishedHash.Update ((uint8_t *)&version, 2);
site.read ((char *)&length, 2); site.read ((char *)&length, 2); finishedHash.Update ((uint8_t *)&length, 2);
length = be16toh (length); length = be16toh (length);
char * serverHelloDone = new char[length]; char * serverHelloDone = new char[length];
site.read (serverHelloDone, length); site.read (serverHelloDone, length);
finishedHash.Update ((uint8_t *)serverHelloDone, length);
if (serverHelloDone[0] != 0x0E) // handshake type hello done if (serverHelloDone[0] != 0x0E) // handshake type hello done
LogPrint (eLogError, "Unexpected handshake type ", (int)serverHelloDone[0]); LogPrint (eLogError, "Unexpected handshake type ", (int)serverHelloDone[0]);
delete[] serverHelloDone; delete[] serverHelloDone;
@ -606,37 +622,56 @@ namespace data
// send ClientKeyExchange // send ClientKeyExchange
site.write ((char *)clientKeyExchange, sizeof (clientKeyExchange)); site.write ((char *)clientKeyExchange, sizeof (clientKeyExchange));
site.write ((char *)encrypted, 512); site.write ((char *)encrypted, 512);
finishedHash.Update (clientKeyExchange, sizeof (clientKeyExchange));
finishedHash.Update (encrypted, 512);
uint8_t masterSecret[48], random[64]; uint8_t masterSecret[48], random[64];
memcpy (random, clientHello + 11, 32); memcpy (random, clientHello + 11, 32);
memcpy (random + 32, serverRandom, 32); memcpy (random + 32, serverRandom, 32);
PRF (secret, "master secret", random, 48, masterSecret);
// calculate master secret
PRF (secret, "master secret", random, 64, 48, masterSecret);
// send finished
uint8_t finishedHashDigest[32], verifyData[32];
finishedHash.Final (finishedHashDigest);
PRF (masterSecret, "client finished", finishedHashDigest, 32, 12, verifyData);
site.write ((char *)finished, sizeof (finished));
site.write ((char *)finishedHashDigest, 12);
// read finished
site.read ((char *)&type, 1);
site.read ((char *)&version, 2);
site.read ((char *)&length, 2);
length = be16toh (length);
char * finished1 = new char[length];
site.read (finished1, length);
delete[] finished1;
struct struct
{ {
uint8_t clientMACKey[32]; uint8_t clientMACKey[20];
uint8_t serverMACKey[32]; uint8_t serverMACKey[20];
uint8_t clientKey[32]; uint8_t clientKey[32];
uint8_t serverKey[32]; uint8_t serverKey[32];
} keys; } keys;
memcpy (random, serverRandom, 32); memcpy (random, serverRandom, 32);
memcpy (random + 32, clientHello + 11, 32); memcpy (random + 32, clientHello + 11, 32);
PRF (masterSecret, "key expansion", random, 128, (uint8_t *)&keys); PRF (masterSecret, "key expansion", random, 64, sizeof (keys), (uint8_t *)&keys);
} }
else else
LogPrint (eLogError, "Can't connect to ", address); LogPrint (eLogError, "Can't connect to ", address);
return ""; return "";
} }
void Reseeder::PRF (const uint8_t * secret, const char * label, const uint8_t * random, size_t len, uint8_t * buf) void Reseeder::PRF (const uint8_t * secret, const char * label, const uint8_t * random, size_t randomLen,
size_t len, uint8_t * buf)
{ {
// secret is assumed 48 bytes // secret is assumed 48 bytes
// random is 64 bytes // random is not more than 64 bytes
// output is 48 bytes (buffer size should be 64)
CryptoPP::HMAC<CryptoPP::SHA256> hmac (secret, 48); CryptoPP::HMAC<CryptoPP::SHA256> hmac (secret, 48);
uint8_t seed[96]; size_t seedLen; uint8_t seed[96]; size_t seedLen;
seedLen = strlen (label); seedLen = strlen (label);
memcpy (seed, label, seedLen); memcpy (seed, label, seedLen);
memcpy (seed + seedLen, random, 64); memcpy (seed + seedLen, random, randomLen);
seedLen += 64; seedLen += randomLen;
size_t offset = 0; size_t offset = 0;
uint8_t a[128]; uint8_t a[128];

3
Reseed.h

@ -39,7 +39,8 @@ namespace data
bool FindZipDataDescriptor (std::istream& s); bool FindZipDataDescriptor (std::istream& s);
// for HTTPS // for HTTPS
void PRF (const uint8_t * secret, const char * label, const uint8_t * random, size_t len, uint8_t * buf); void PRF (const uint8_t * secret, const char * label, const uint8_t * random, size_t randomLen,
size_t len, uint8_t * buf);
private: private:

Loading…
Cancel
Save