TLS 1.2 updates for hash/sig id

This commit is contained in:
Todd A Ouska 2011-02-28 12:21:06 -08:00
parent 09eda62f99
commit 4dd9f290e5
6 changed files with 119 additions and 22 deletions

5
.gitignore vendored
View File

@ -13,6 +13,7 @@ Makefile
depcomp
missing
libtool
tags
benchmark
test
client
@ -22,3 +23,7 @@ server
snifftest
output
testsuite
diff
*.gz
*.zip
*.bak

View File

@ -36,6 +36,9 @@
#ifdef HAVE_ECC
#include "ctc_ecc.h"
#endif
#ifndef NO_SHA256
#include "sha256.h"
#endif
#ifdef CYASSL_CALLBACKS
#include "cyassl_callbacks.h"
@ -333,6 +336,10 @@ enum Misc {
NO_SNIFF = 0, /* not sniffing */
SNIFF = 1, /* currently sniffing */
HASH_SIG_SIZE = 2, /* default SHA1 RSA */
SHA1_ID = 2, /* hash id */
RSA_ID = 1, /* sig id */
NO_COPY = 0, /* should we copy static buffer for write */
COPY = 1 /* should we copy static buffer for write */
};
@ -949,6 +956,9 @@ struct SSL {
RNG rng;
Md5 hashMd5; /* md5 hash of handshake msgs */
Sha hashSha; /* sha hash of handshake msgs */
#ifndef NO_SHA256
Sha256 hashSha256; /* sha256 hash of handshake msgs */
#endif
Hashes verifyHashes;
Hashes certHashes; /* for cert verify */
Signer* caList; /* SSL_CTX owns */

View File

@ -621,6 +621,9 @@ int InitSSL(SSL* ssl, SSL_CTX* ctx)
InitMd5(&ssl->hashMd5);
InitSha(&ssl->hashSha);
#ifndef NO_SHA256
InitSha256(&ssl->hashSha256);
#endif
InitRsaKey(&ssl->peerRsaKey, ctx->heap);
ssl->peerRsaKeyPresent = 0;
@ -904,6 +907,10 @@ static void HashOutput(SSL* ssl, const byte* output, int sz, int ivSz)
Md5Update(&ssl->hashMd5, buffer, sz);
ShaUpdate(&ssl->hashSha, buffer, sz);
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl))
Sha256Update(&ssl->hashSha256, buffer, sz);
#endif
}
@ -922,6 +929,10 @@ static void HashInput(SSL* ssl, const byte* input, int sz)
Md5Update(&ssl->hashMd5, buffer, sz);
ShaUpdate(&ssl->hashSha, buffer, sz);
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl))
Sha256Update(&ssl->hashSha256, buffer, sz);
#endif
}
@ -1322,6 +1333,11 @@ static void BuildFinished(SSL* ssl, Hashes* hashes, const byte* sender)
/* store current states, building requires get_digest which resets state */
Md5 md5 = ssl->hashMd5;
Sha sha = ssl->hashSha;
#ifndef NO_SHA256
Sha256 sha256;
if (IsAtLeastTLSv1_2(ssl))
sha256 = ssl->hashSha256;
#endif
if (ssl->options.tls)
BuildTlsFinished(ssl, hashes, sender);
@ -1333,6 +1349,10 @@ static void BuildFinished(SSL* ssl, Hashes* hashes, const byte* sender)
/* restore */
ssl->hashMd5 = md5;
ssl->hashSha = sha;
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl))
ssl->hashSha256 = sha256;
#endif
}
@ -2311,6 +2331,11 @@ static void BuildCertHashes(SSL* ssl, Hashes* hashes)
/* store current states, building requires get_digest which resets state */
Md5 md5 = ssl->hashMd5;
Sha sha = ssl->hashSha;
#ifndef NO_SHA256 /* for possible future changes */
Sha256 sha256;
if (IsAtLeastTLSv1_2(ssl))
sha256 = ssl->hashSha256;
#endif
if (ssl->options.tls) {
Md5Final(&ssl->hashMd5, hashes->md5);
@ -2324,6 +2349,10 @@ static void BuildCertHashes(SSL* ssl, Hashes* hashes)
/* restore */
ssl->hashMd5 = md5;
ssl->hashSha = sha;
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl))
ssl->hashSha256 = sha256;
#endif
}
@ -2528,6 +2557,9 @@ int SendCertificateRequest(SSL* ssl)
int typeTotal = 1; /* only rsa for now */
int reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ; /* add auth later */
if (IsAtLeastTLSv1_2(ssl))
reqSz += LENGTH_SZ + HASH_SIG_SIZE;
if (ssl->options.usingPSK_cipher) return 0; /* not needed */
sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
@ -2551,6 +2583,15 @@ int SendCertificateRequest(SSL* ssl)
output[i++] = typeTotal; /* # of types */
output[i++] = rsa_sign;
/* supported hash/sig */
if (IsAtLeastTLSv1_2(ssl)) {
c16toa(HASH_SIG_SIZE, &output[i]);
i += LENGTH_SZ;
output[i++] = SHA1_ID; /* hash */
output[i++] = RSA_ID; /* sig */
}
c16toa(0, &output[i]); /* auth's */
i += REQ_HEADER_SZ;
@ -3573,14 +3614,15 @@ int SetCipherList(SSL_CTX* ctx, const char* list)
if (XMEMCMP(ssl->arrays.sessionID, ssl->session.sessionID, ID_LEN)
== 0) {
if (SetCipherSpecs(ssl) == 0) {
int ret;
XMEMCPY(ssl->arrays.masterSecret, ssl->session.masterSecret,
SECRET_LEN);
if (ssl->options.tls)
DeriveTlsKeys(ssl);
ret = DeriveTlsKeys(ssl);
else
DeriveKeys(ssl);
ret = DeriveKeys(ssl);
ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
return 0;
return ret;
}
else
return UNSUPPORTED_SUITE;
@ -3612,6 +3654,13 @@ int SetCipherList(SSL_CTX* ctx, const char* list)
ato16(&input[*inOutIdx], &len);
*inOutIdx += LENGTH_SZ;
if (IsAtLeastTLSv1_2(ssl)) {
/* hash sig format */
*inOutIdx += len;
ato16(&input[*inOutIdx], &len);
*inOutIdx += LENGTH_SZ;
}
/* authorities */
while (len) {
word16 dnSz;
@ -3755,6 +3804,11 @@ int SetCipherList(SSL_CTX* ctx, const char* list)
return BUFFER_ERROR;
XMEMCPY(messageVerify, &input[*inOutIdx - verifySz], verifySz);
if (IsAtLeastTLSv1_2(ssl)) {
/* just advance for now TODO: validate hash algo params */
*inOutIdx += LENGTH_SZ;
}
/* signature */
ato16(&input[*inOutIdx], &length);
*inOutIdx += LENGTH_SZ;
@ -4071,14 +4125,20 @@ int SetCipherList(SSL_CTX* ctx, const char* list)
HANDSHAKE_HEADER_SZ];
byte* signBuffer = ssl->certHashes.md5;
word32 signSz = sizeof(Hashes);
byte encodedSig[MAX_ENCODED_SIG_SZ];
byte encodedSig[MAX_ENCODED_SIG_SZ];
word32 extraSz = 0; /* tls 1.2 hash/sig */
#ifdef CYASSL_DTLS
if (ssl->options.dtls)
verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
#endif
length = RsaEncryptSize(&key);
c16toa((word16)length, verify); /* prepend verify header */
if (IsAtLeastTLSv1_2(ssl)) {
verify[0] = SHA1_ID;
verify[1] = RSA_ID;
extraSz = HASH_SIG_SIZE;
}
c16toa((word16)length, verify + extraSz); /* prepend verify header*/
if (IsAtLeastTLSv1_2(ssl)) {
byte* digest;
@ -4094,17 +4154,17 @@ int SetCipherList(SSL_CTX* ctx, const char* list)
signBuffer = encodedSig;
}
ret = RsaSSL_Sign(signBuffer, signSz, verify +
ret = RsaSSL_Sign(signBuffer, signSz, verify + extraSz +
VERIFY_HEADER, ENCRYPT_LEN, &key, &ssl->rng);
if (ret > 0) {
ret = 0; /* reset */
AddHeaders(output, length + VERIFY_HEADER, certificate_verify,
ssl);
AddHeaders(output, length + extraSz + VERIFY_HEADER,
certificate_verify, ssl);
sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length +
VERIFY_HEADER;
extraSz + VERIFY_HEADER;
#ifdef CYASSL_DTLS
if (ssl->options.dtls)
sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
@ -4514,6 +4574,10 @@ int SetCipherList(SSL_CTX* ctx, const char* list)
/* manually hash input since different format */
Md5Update(&ssl->hashMd5, input + idx, sz);
ShaUpdate(&ssl->hashSha, input + idx, sz);
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl))
Sha256Update(&ssl->hashSha256, input + idx, sz);
#endif
/* does this value mean client_hello? */
idx++;
@ -4589,6 +4653,7 @@ int SetCipherList(SSL_CTX* ctx, const char* list)
/* DoClientHello uses same resume code */
while (ssl->options.resuming) { /* let's try */
int ret;
SSL_SESSION* session = GetSession(ssl, ssl->arrays.masterSecret);
if (!session) {
ssl->options.resuming = 0;
@ -4599,12 +4664,12 @@ int SetCipherList(SSL_CTX* ctx, const char* list)
RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
if (ssl->options.tls)
DeriveTlsKeys(ssl);
ret = DeriveTlsKeys(ssl);
else
DeriveKeys(ssl);
ret = DeriveKeys(ssl);
ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
return 0;
return ret;
}
return MatchSuite(ssl, &clSuites);
@ -4719,6 +4784,7 @@ int SetCipherList(SSL_CTX* ctx, const char* list)
/* ProcessOld uses same resume code */
while (ssl->options.resuming) { /* let's try */
int ret;
SSL_SESSION* session = GetSession(ssl, ssl->arrays.masterSecret);
if (!session) {
ssl->options.resuming = 0;
@ -4729,12 +4795,12 @@ int SetCipherList(SSL_CTX* ctx, const char* list)
RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
if (ssl->options.tls)
DeriveTlsKeys(ssl);
ret = DeriveTlsKeys(ssl);
else
DeriveKeys(ssl);
ret = DeriveKeys(ssl);
ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
return 0;
return ret;
}
return MatchSuite(ssl, &clSuites);
}
@ -4759,6 +4825,8 @@ int SetCipherList(SSL_CTX* ctx, const char* list)
if ( (i + VERIFY_HEADER) > totalSz)
return INCOMPLETE_DATA;
if (IsAtLeastTLSv1_2(ssl))
i += HASH_SIG_SIZE;
ato16(&input[i], &sz);
i += VERIFY_HEADER;

View File

@ -431,7 +431,7 @@ int SetCipherSpecs(SSL* ssl)
#ifndef NO_TLS
ssl->options.tls = 1;
ssl->hmac = TLS_hmac;
if (ssl->version.minor == 2)
if (ssl->version.minor >= 2)
ssl->options.tls1_1 = 1;
#endif
}
@ -678,7 +678,7 @@ int MakeMasterSecret(SSL* ssl)
byte shaOutput[SHA_DIGEST_SIZE];
byte md5Input[ENCRYPT_LEN + SHA_DIGEST_SIZE];
byte shaInput[PREFIX + ENCRYPT_LEN + 2 * RAN_LEN];
int i;
int i, ret;
word32 idx;
word32 pmsSz = ssl->arrays.preMasterSz;
@ -740,10 +740,10 @@ int MakeMasterSecret(SSL* ssl)
}
#endif
DeriveKeys(ssl);
ret = DeriveKeys(ssl);
CleanPreMaster(ssl);
return 0;
return ret;
}

View File

@ -999,6 +999,10 @@ int SSL_CTX_set_cipher_list(SSL_CTX* ctx, const char* list)
/* re-init hashes, exclude first hello and verify request */
InitMd5(&ssl->hashMd5);
InitSha(&ssl->hashSha);
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl))
InitSha256(&ssl->hashSha256);
#endif
if ( (ssl->error = SendClientHello(ssl)) != 0) {
CYASSL_ERROR(ssl->error);
return SSL_FATAL_ERROR;
@ -1196,6 +1200,10 @@ int SSL_CTX_set_cipher_list(SSL_CTX* ctx, const char* list)
/* re-init hashes, exclude first hello and verify request */
InitMd5(&ssl->hashMd5);
InitSha(&ssl->hashSha);
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl))
InitSha256(&ssl->hashSha256);
#endif
while (ssl->options.clientState < CLIENT_HELLO_COMPLETE)
if ( (ssl->error = ProcessReply(ssl)) < 0) {

View File

@ -136,10 +136,17 @@ static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
void BuildTlsFinished(SSL* ssl, Hashes* hashes, const byte* sender)
{
const byte* side;
byte handshake_hash[FINISHED_SZ];
byte handshake_hash[FINISHED_SZ];
word32 hashSz = FINISHED_SZ;
Md5Final(&ssl->hashMd5, handshake_hash);
ShaFinal(&ssl->hashSha, &handshake_hash[MD5_DIGEST_SIZE]);
#ifndef NO_SHA256
if (IsAtLeastTLSv1_2(ssl)) {
Sha256Final(&ssl->hashSha256, handshake_hash);
hashSz = SHA256_DIGEST_SIZE;
}
#endif
if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
side = tls_client;
@ -147,8 +154,7 @@ void BuildTlsFinished(SSL* ssl, Hashes* hashes, const byte* sender)
side = tls_server;
PRF(hashes->md5, TLS_FINISHED_SZ, ssl->arrays.masterSecret, SECRET_LEN,
side, FINISHED_LABEL_SZ, handshake_hash, FINISHED_SZ,
IsAtLeastTLSv1_2(ssl));
side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl));
}