From 30004498c5520a47e42323a8088b5e23bc8c9283 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 6 Feb 2013 13:08:28 -0800 Subject: [PATCH 1/7] For TLSv1.2, cert and key messages use SHA-256 or SHA-384 as expected. --- cyassl/internal.h | 13 +- src/internal.c | 338 +++++++++++++++++++++++++++++++++++++--------- src/tls.c | 6 - 3 files changed, 282 insertions(+), 75 deletions(-) diff --git a/cyassl/internal.h b/cyassl/internal.h index 4d3f0b583..2d426a890 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1164,14 +1164,15 @@ CYASSL_LOCAL void InitCiphers(CYASSL* ssl); CYASSL_LOCAL void FreeCiphers(CYASSL* ssl); +#ifdef CYASSL_SHA384 + #define HASHES_SZ SHA384_DIGEST_SIZE +#else + #define HASHES_SZ FINISHED_SZ +#endif + /* hashes type */ typedef struct Hashes { - #ifndef NO_MD5 - byte md5[MD5_DIGEST_SIZE]; - byte sha[SHA_DIGEST_SIZE]; - #else - byte hash[FINISHED_SZ]; - #endif + byte hash[HASHES_SZ]; } Hashes; diff --git a/src/internal.c b/src/internal.c index 6158c4d0c..df6a03781 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2270,7 +2270,7 @@ static void BuildMD5(CYASSL* ssl, Hashes* hashes, const byte* sender) Md5Update(&ssl->hashMd5, PAD2, PAD_MD5); Md5Update(&ssl->hashMd5, md5_result, MD5_DIGEST_SIZE); - Md5Final(&ssl->hashMd5, hashes->md5); + Md5Final(&ssl->hashMd5, &hashes->hash[0]); } @@ -2290,7 +2290,7 @@ static void BuildSHA(CYASSL* ssl, Hashes* hashes, const byte* sender) ShaUpdate(&ssl->hashSha, PAD2, PAD_SHA); ShaUpdate(&ssl->hashSha, sha_result, SHA_DIGEST_SIZE); - ShaFinal(&ssl->hashSha, hashes->sha); + ShaFinal(&ssl->hashSha, &hashes->hash[MD5_DIGEST_SIZE]); } #endif @@ -4322,29 +4322,58 @@ static void BuildCertHashes(CYASSL* 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; - InitSha256(&sha256); - if (IsAtLeastTLSv1_2(ssl)) - sha256 = ssl->hashSha256; -#endif + #ifndef NO_SHA256 + Sha256 sha256; + #endif + #ifdef CYASSL_SHA384 + Sha384 sha384; + #endif + + #ifndef NO_SHA256 + InitSha256(&sha256); + if (IsAtLeastTLSv1_2(ssl)) + sha256 = ssl->hashSha256; + #endif + #ifdef CYASSL_SHA384 + InitSha384(&sha384); + if (IsAtLeastTLSv1_2(ssl)) + sha384 = ssl->hashSha384; + #endif if (ssl->options.tls) { - Md5Final(&ssl->hashMd5, hashes->md5); - ShaFinal(&ssl->hashSha, hashes->sha); + if (IsAtLeastTLSv1_2(ssl)) { + if (ssl->specs.mac_algorithm <= sha256_mac) { + #ifndef NO_SHA256 + Sha256Final(&ssl->hashSha256, hashes->hash); + #endif + } + else if (ssl->specs.mac_algorithm == sha384_mac) { + #ifdef CYASSL_SHA384 + Sha384Final(&ssl->hashSha384, hashes->hash); + #endif + } + } + else { + Md5Final(&ssl->hashMd5, &hashes->hash[0]); + ShaFinal(&ssl->hashSha, &hashes->hash[MD5_DIGEST_SIZE]); + } } else { - BuildMD5_CertVerify(ssl, hashes->md5); - BuildSHA_CertVerify(ssl, hashes->sha); + BuildMD5_CertVerify(ssl, &hashes->hash[0]); + BuildSHA_CertVerify(ssl, &hashes->hash[MD5_DIGEST_SIZE]); } /* restore */ ssl->hashMd5 = md5; ssl->hashSha = sha; -#ifndef NO_SHA256 - if (IsAtLeastTLSv1_2(ssl)) - ssl->hashSha256 = sha256; -#endif + #ifndef NO_SHA256 + if (IsAtLeastTLSv1_2(ssl)) + ssl->hashSha256 = sha256; + #endif + #ifdef CYASSL_SHA384 + if (IsAtLeastTLSv1_2(ssl)) + ssl->hashSha384 = sha384; + #endif } #endif @@ -6403,6 +6432,14 @@ int SetCipherList(Suites* s, const char* list) Md5 md5; Sha sha; byte hash[FINISHED_SZ]; + #ifndef NO_SHA256 + Sha256 sha256; + byte hash256[SHA256_DIGEST_SIZE]; + #endif + #ifdef CYASSL_SHA384 + Sha384 sha384; + byte hash384[SHA384_DIGEST_SIZE]; + #endif byte messageVerify[MAX_DH_SZ]; /* adjust from start idx */ @@ -6442,6 +6479,22 @@ int SetCipherList(Suites* s, const char* list) ShaUpdate(&sha, messageVerify, verifySz); ShaFinal(&sha, &hash[MD5_DIGEST_SIZE]); + #ifndef NO_SHA256 + InitSha256(&sha256); + Sha256Update(&sha256, ssl->arrays->clientRandom, RAN_LEN); + Sha256Update(&sha256, ssl->arrays->serverRandom, RAN_LEN); + Sha256Update(&sha256, messageVerify, verifySz); + Sha256Final(&sha256, hash256); + #endif + + #ifdef CYASSL_SHA384 + InitSha384(&sha384); + Sha384Update(&sha384, ssl->arrays->clientRandom, RAN_LEN); + Sha384Update(&sha384, ssl->arrays->serverRandom, RAN_LEN); + Sha384Update(&sha384, messageVerify, verifySz); + Sha384Final(&sha384, hash384); + #endif + /* rsa */ if (ssl->specs.sig_algo == rsa_sa_algo) { @@ -6456,14 +6509,24 @@ int SetCipherList(Suites* s, const char* list) if (IsAtLeastTLSv1_2(ssl)) { byte encodedSig[MAX_ENCODED_SIG_SZ]; word32 encSigSz; - byte* digest; - int typeH; - int digestSz; + byte* digest = &hash[MD5_DIGEST_SIZE]; + int typeH = SHAh; + int digestSz = SHA_DIGEST_SIZE; - /* sha1 for now */ - digest = &hash[MD5_DIGEST_SIZE]; - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; + if (ssl->specs.mac_algorithm <= sha256_mac) { + #ifndef NO_SHA256 + digest = hash256; + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (ssl->specs.mac_algorithm == sha384_mac) { + #ifdef CYASSL_SHA384 + digest = hash384; + typeH = SHA384h; + digestSz = SHA384_DIGEST_SIZE; + #endif + } encSigSz = EncodeSignature(encodedSig, digest, digestSz, typeH); @@ -6480,11 +6543,28 @@ int SetCipherList(Suites* s, const char* list) /* ecdsa */ else if (ssl->specs.sig_algo == ecc_dsa_sa_algo) { int verify = 0, ret; + byte* digest = &hash[MD5_DIGEST_SIZE]; + word32 digestSz = SHA_DIGEST_SIZE; if (!ssl->peerEccDsaKeyPresent) return NO_PEER_KEY; - ret = ecc_verify_hash(signature, sigLen, &hash[MD5_DIGEST_SIZE], - SHA_DIGEST_SIZE, &verify, ssl->peerEccDsaKey); + if (IsAtLeastTLSv1_2(ssl)) { + if (ssl->specs.mac_algorithm <= sha256_mac) { + #ifndef NO_SHA256 + digest = hash256; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (ssl->specs.mac_algorithm == sha384_mac) { + #ifdef CYASSL_SHA384 + digest = hash384; + digestSz = SHA384_DIGEST_SIZE; + #endif + } + } + + ret = ecc_verify_hash(signature, sigLen, digest, digestSz, + &verify, ssl->peerEccDsaKey); if (ret != 0 || verify == 0) return VERIFY_SIGN_ERROR; } @@ -6799,8 +6879,8 @@ int SetCipherList(Suites* s, const char* list) if (ret == 0) { byte* verify = (byte*)&output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ]; - byte* signBuffer = ssl->certHashes.md5; - word32 signSz = sizeof(Hashes); + byte* signBuffer = ssl->certHashes.hash; + word32 signSz = FINISHED_SZ; byte encodedSig[MAX_ENCODED_SIG_SZ]; word32 extraSz = 0; /* tls 1.2 hash/sig */ @@ -6810,7 +6890,7 @@ int SetCipherList(Suites* s, const char* list) #endif length = sigOutSz; if (IsAtLeastTLSv1_2(ssl)) { - verify[0] = sha_mac; + verify[0] = ssl->specs.mac_algorithm; verify[1] = usingEcc ? ecc_dsa_sa_algo : rsa_sa_algo; extraSz = HASH_SIG_SIZE; } @@ -6819,21 +6899,46 @@ int SetCipherList(Suites* s, const char* list) if (usingEcc) { #ifdef HAVE_ECC word32 localSz = sigOutSz; - ret = ecc_sign_hash(signBuffer + MD5_DIGEST_SIZE, - SHA_DIGEST_SIZE, verify + extraSz + VERIFY_HEADER, + word32 digestSz = SHA_DIGEST_SIZE; + byte* digest = signBuffer + MD5_DIGEST_SIZE; + + if (IsAtLeastTLSv1_2(ssl)) { + digest = ssl->certHashes.hash; + if (ssl->specs.mac_algorithm <= sha256_mac) { + #ifndef NO_SHA256 + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (ssl->specs.mac_algorithm == sha384_mac) { + #ifdef CYASSL_SHA384 + digestSz = SHA384_DIGEST_SIZE; + #endif + } + } + + ret = ecc_sign_hash(digest, digestSz, + verify + extraSz + VERIFY_HEADER, &localSz, ssl->rng, &eccKey); #endif } else { if (IsAtLeastTLSv1_2(ssl)) { - byte* digest; - int typeH; - int digestSz; + byte* digest = ssl->certHashes.hash; + int digestSz = SHA_DIGEST_SIZE; + int typeH = SHAh; - /* sha1 for now */ - digest = ssl->certHashes.sha; - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; + if (ssl->specs.mac_algorithm <= sha256_mac) { + #ifndef NO_SHA256 + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (ssl->specs.mac_algorithm == sha384_mac) { + #ifdef CYASSL_SHA384 + typeH = SHA384h; + digestSz = SHA384_DIGEST_SIZE; + #endif + } signSz = EncodeSignature(encodedSig, digest,digestSz,typeH); signBuffer = encodedSig; @@ -7183,6 +7288,14 @@ int SetCipherList(Suites* s, const char* list) Md5 md5; Sha sha; byte hash[FINISHED_SZ]; + #ifndef NO_SHA256 + Sha256 sha256; + byte hash256[SHA256_DIGEST_SIZE]; + #endif + #ifdef CYASSL_SHA384 + Sha384 sha384; + byte hash384[SHA384_DIGEST_SIZE]; + #endif /* md5 */ InitMd5(&md5); @@ -7198,22 +7311,48 @@ int SetCipherList(Suites* s, const char* list) ShaUpdate(&sha, output + preSigIdx, preSigSz); ShaFinal(&sha, &hash[MD5_DIGEST_SIZE]); + #ifndef NO_SHA256 + InitSha256(&sha256); + Sha256Update(&sha256, ssl->arrays->clientRandom, RAN_LEN); + Sha256Update(&sha256, ssl->arrays->serverRandom, RAN_LEN); + Sha256Update(&sha256, output + preSigIdx, preSigSz); + Sha256Final(&sha256, hash256); + #endif + + #ifdef CYASSL_SHA384 + InitSha384(&sha384); + Sha384Update(&sha384, ssl->arrays->clientRandom, RAN_LEN); + Sha384Update(&sha384, ssl->arrays->serverRandom, RAN_LEN); + Sha384Update(&sha384, output + preSigIdx, preSigSz); + Sha384Final(&sha384, hash384); + #endif + if (ssl->specs.sig_algo == rsa_sa_algo) { byte* signBuffer = hash; word32 signSz = sizeof(hash); byte encodedSig[MAX_ENCODED_SIG_SZ]; if (IsAtLeastTLSv1_2(ssl)) { - byte* digest; - int hType; - int digestSz; + byte* digest = &hash[MD5_DIGEST_SIZE]; + int typeH = SHAh; + int digestSz = SHA_DIGEST_SIZE; - /* sha1 for now */ - digest = &hash[MD5_DIGEST_SIZE]; - hType = SHAh; - digestSz = SHA_DIGEST_SIZE; + if (ssl->specs.mac_algorithm <= sha256_mac) { + #ifndef NO_SHA256 + digest = hash256; + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (ssl->specs.mac_algorithm == sha384_mac) { + #ifdef CYASSL_SHA384 + digest = hash384; + typeH = SHA384h; + digestSz = SHA384_DIGEST_SIZE; + #endif + } signSz = EncodeSignature(encodedSig, digest, digestSz, - hType); + typeH); signBuffer = encodedSig; } ret = RsaSSL_Sign(signBuffer, signSz, output + idx, sigSz, @@ -7226,9 +7365,26 @@ int SetCipherList(Suites* s, const char* list) return ret; } else if (ssl->specs.sig_algo == ecc_dsa_sa_algo) { + byte* digest = &hash[MD5_DIGEST_SIZE]; + word32 digestSz = SHA_DIGEST_SIZE; word32 sz = sigSz; - ret = ecc_sign_hash(&hash[MD5_DIGEST_SIZE], SHA_DIGEST_SIZE, + if (IsAtLeastTLSv1_2(ssl)) { + if (ssl->specs.mac_algorithm <= sha256_mac) { + #ifndef NO_SHA256 + digest = hash256; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (ssl->specs.mac_algorithm == sha384_mac) { + #ifdef CYASSL_SHA384 + digest = hash384; + digestSz = SHA384_DIGEST_SIZE; + #endif + } + } + + ret = ecc_sign_hash(digest, digestSz, output + idx, &sz, ssl->rng, &dsaKey); FreeRsaKey(&rsaKey); ecc_free(&dsaKey); @@ -7385,6 +7541,14 @@ int SetCipherList(Suites* s, const char* list) Md5 md5; Sha sha; byte hash[FINISHED_SZ]; + #ifndef NO_SHA256 + Sha256 sha256; + byte hash256[SHA256_DIGEST_SIZE]; + #endif + #ifdef CYASSL_SHA384 + Sha384 sha384; + byte hash384[SHA384_DIGEST_SIZE]; + #endif /* md5 */ InitMd5(&md5); @@ -7400,19 +7564,45 @@ int SetCipherList(Suites* s, const char* list) ShaUpdate(&sha, output + preSigIdx, preSigSz); ShaFinal(&sha, &hash[MD5_DIGEST_SIZE]); + #ifndef NO_SHA256 + InitSha256(&sha256); + Sha256Update(&sha256, ssl->arrays->clientRandom, RAN_LEN); + Sha256Update(&sha256, ssl->arrays->serverRandom, RAN_LEN); + Sha256Update(&sha256, output + preSigIdx, preSigSz); + Sha256Final(&sha256, hash256); + #endif + + #ifdef CYASSL_SHA384 + InitSha384(&sha384); + Sha384Update(&sha384, ssl->arrays->clientRandom, RAN_LEN); + Sha384Update(&sha384, ssl->arrays->serverRandom, RAN_LEN); + Sha384Update(&sha384, output + preSigIdx, preSigSz); + Sha384Final(&sha384, hash384); + #endif + if (ssl->specs.sig_algo == rsa_sa_algo) { byte* signBuffer = hash; word32 signSz = sizeof(hash); byte encodedSig[MAX_ENCODED_SIG_SZ]; if (IsAtLeastTLSv1_2(ssl)) { - byte* digest; - int typeH; - int digestSz; + byte* digest = &hash[MD5_DIGEST_SIZE]; + int typeH = SHAh; + int digestSz = SHA_DIGEST_SIZE; - /* sha1 for now */ - digest = &hash[MD5_DIGEST_SIZE]; - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; + if (ssl->specs.mac_algorithm <= sha256_mac) { + #ifndef NO_SHA256 + digest = hash256; + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (ssl->specs.mac_algorithm == sha384_mac) { + #ifdef CYASSL_SHA384 + digest = hash384; + typeH = SHA384h; + digestSz = SHA384_DIGEST_SIZE; + #endif + } signSz = EncodeSignature(encodedSig, digest, digestSz, typeH); @@ -8304,14 +8494,22 @@ int SetCipherList(Suites* s, const char* list) if (IsAtLeastTLSv1_2(ssl)) { byte encodedSig[MAX_ENCODED_SIG_SZ]; word32 sigSz; - byte* digest; - int typeH; - int digestSz; + byte* digest = ssl->certHashes.hash; + int typeH = SHAh; + int digestSz = SHA_DIGEST_SIZE; - /* sha1 for now */ - digest = ssl->certHashes.sha; - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; + if (ssl->specs.mac_algorithm <= sha256_mac) { + #ifndef NO_SHA256 + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (ssl->specs.mac_algorithm == sha384_mac) { + #ifdef CYASSL_SHA384 + typeH = SHA384h; + digestSz = SHA384_DIGEST_SIZE; + #endif + } sigSz = EncodeSignature(encodedSig, digest, digestSz, typeH); @@ -8320,8 +8518,8 @@ int SetCipherList(Suites* s, const char* list) ret = 0; /* verified */ } else { - if (outLen == sizeof(ssl->certHashes) && XMEMCMP(out, - &ssl->certHashes, sizeof(ssl->certHashes)) == 0) + if (outLen == FINISHED_SZ && XMEMCMP(out, + &ssl->certHashes, FINISHED_SZ) == 0) ret = 0; /* verified */ } } @@ -8330,10 +8528,24 @@ int SetCipherList(Suites* s, const char* list) if (ssl->peerEccDsaKeyPresent) { int verify = 0; int err = -1; + byte* digest = ssl->certHashes.hash; + word32 digestSz = SHA_DIGEST_SIZE; CYASSL_MSG("Doing ECC peer cert verify"); - err = ecc_verify_hash(sig, sz, ssl->certHashes.sha, SHA_DIGEST_SIZE, + if (IsAtLeastTLSv1_2(ssl)) { + if (ssl->specs.mac_algorithm <= sha256_mac) { + #ifndef NO_SHA256 + digestSz = SHA256_DIGEST_SIZE; + #endif + } + else if (ssl->specs.mac_algorithm == sha384_mac) { + #ifdef CYASSL_SHA384 + digestSz = SHA384_DIGEST_SIZE; + #endif + } + } + err = ecc_verify_hash(sig, sz, digest, digestSz, &verify, ssl->peerEccDsaKey); if (err == 0 && verify == 1) diff --git a/src/tls.c b/src/tls.c index db19785f6..b3e67c27d 100644 --- a/src/tls.c +++ b/src/tls.c @@ -239,15 +239,9 @@ void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) else side = tls_server; -#ifndef NO_MD5 - PRF(hashes->md5, TLS_FINISHED_SZ, ssl->arrays->masterSecret, SECRET_LEN, - side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl), - ssl->specs.mac_algorithm); -#else PRF(hashes->hash, TLS_FINISHED_SZ, ssl->arrays->masterSecret, SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); -#endif } From 5f7359be7ebdf2f634e9e577109029f988278792 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 12 Feb 2013 13:47:13 -0800 Subject: [PATCH 2/7] Builds the hash/sig algorithm extension list based on the available cipher suites and hashes --- cyassl/internal.h | 12 ++++-- src/internal.c | 101 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 18 deletions(-) diff --git a/cyassl/internal.h b/cyassl/internal.h index 2d426a890..c2c735289 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -480,10 +480,10 @@ enum Misc { CERT_HEADER_SZ = 3, /* always 3 bytes */ REQ_HEADER_SZ = 2, /* cert request header sz */ HINT_LEN_SZ = 2, /* length of hint size field */ - HELLO_EXT_SZ = 14, /* total length of the lazy hello extensions */ - HELLO_EXT_LEN = 12, /* length of the lazy hello extensions */ - HELLO_EXT_SIGALGO_SZ = 8, /* length of signature algo extension */ - HELLO_EXT_SIGALGO_LEN = 6, /* number of items in the signature algo list */ + HELLO_EXT_SZ = 8, /* total length of the lazy hello extensions */ + HELLO_EXT_LEN = 6, /* length of the lazy hello extensions */ + HELLO_EXT_SIGALGO_SZ = 2, /* length of signature algo extension */ + HELLO_EXT_SIGALGO_MAX = 32, /* number of items in the signature algo list */ DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */ DTLS_RECORD_HEADER_SZ = 13, /* normal + epoch(2) + seq_num(6) */ @@ -749,6 +749,10 @@ typedef struct Suites { int setSuites; /* user set suites from default */ byte suites[MAX_SUITE_SZ]; word16 suiteSz; /* suite length in bytes */ + byte hashSigAlgo[HELLO_EXT_SIGALGO_MAX]; + word16 hashSigAlgoSz; /* SigAlgo extension length in bytes */ + byte hashAlgo; /* selected hash algorithm */ + byte signAlgo; /* selected sig algorithm */ } Suites; diff --git a/src/internal.c b/src/internal.c index df6a03781..a64d7fce4 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1049,6 +1049,38 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveRSA, byte havePSK, #endif suites->suiteSz = idx; + + { + idx = 0; + + if (haveECDSAsig) { + #ifdef CYASSL_SHA384 + suites->hashSigAlgo[idx++] = sha384_mac; + suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; + #endif + #ifndef NO_SHA256 + suites->hashSigAlgo[idx++] = sha256_mac; + suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; + #endif + suites->hashSigAlgo[idx++] = sha_mac; + suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; + } + + if (haveRSAsig) { + #ifdef CYASSL_SHA384 + suites->hashSigAlgo[idx++] = sha384_mac; + suites->hashSigAlgo[idx++] = rsa_sa_algo; + #endif + #ifndef NO_SHA256 + suites->hashSigAlgo[idx++] = sha256_mac; + suites->hashSigAlgo[idx++] = rsa_sa_algo; + #endif + suites->hashSigAlgo[idx++] = sha_mac; + suites->hashSigAlgo[idx++] = rsa_sa_algo; + } + + suites->hashSigAlgoSz = idx; + } } @@ -5794,6 +5826,7 @@ int SetCipherList(Suites* s, const char* list) const int suiteSz = sizeof(cipher_names) / sizeof(cipher_names[0]); int idx = 0; + int haveRSA = 0, haveECDSA = 0; if (s == NULL) { CYASSL_MSG("SetCipherList suite pointer error"); @@ -5805,7 +5838,7 @@ int SetCipherList(Suites* s, const char* list) if (*list == 0) return 1; /* CyaSSL default */ - if (XSTRNCMP(haystack, "ALL", 3) == 0) return 1; /* CyaSSL defualt */ + if (XSTRNCMP(haystack, "ALL", 3) == 0) return 1; /* CyaSSL default */ for(;;) { word32 len; @@ -5828,6 +5861,15 @@ int SetCipherList(Suites* s, const char* list) s->suites[idx++] = 0x00; /* normal */ s->suites[idx++] = (byte)cipher_name_idx[i]; + /* The suites are either ECDSA, RSA, or PSK. The RSA suites + * don't necessarily have RSA in the name. */ + if ((haveECDSA == 0) && XSTRSTR(name, "ECDSA")) { + haveECDSA = 1; + } + else if ((haveRSA == 0) && (XSTRSTR(name, "PSK") == NULL)) { + haveRSA = 1; + } + if (!ret) ret = 1; /* found at least one */ break; } @@ -5838,6 +5880,36 @@ int SetCipherList(Suites* s, const char* list) if (ret) { s->setSuites = 1; s->suiteSz = (word16)idx; + + idx = 0; + + if (haveECDSA) { + #ifdef CYASSL_SHA384 + s->hashSigAlgo[idx++] = sha384_mac; + s->hashSigAlgo[idx++] = ecc_dsa_sa_algo; + #endif + #ifndef NO_SHA256 + s->hashSigAlgo[idx++] = sha256_mac; + s->hashSigAlgo[idx++] = ecc_dsa_sa_algo; + #endif + s->hashSigAlgo[idx++] = sha_mac; + s->hashSigAlgo[idx++] = ecc_dsa_sa_algo; + } + + if (haveRSA) { + #ifdef CYASSL_SHA384 + s->hashSigAlgo[idx++] = sha384_mac; + s->hashSigAlgo[idx++] = rsa_sa_algo; + #endif + #ifndef NO_SHA256 + s->hashSigAlgo[idx++] = sha256_mac; + s->hashSigAlgo[idx++] = rsa_sa_algo; + #endif + s->hashSigAlgo[idx++] = sha_mac; + s->hashSigAlgo[idx++] = rsa_sa_algo; + } + + s->hashSigAlgoSz = idx; } return ret; @@ -6009,9 +6081,11 @@ int SetCipherList(Suites* s, const char* list) + ssl->suites->suiteSz + SUITE_LEN + COMP_LEN + ENUM_LEN; - if (IsAtLeastTLSv1_2(ssl)) - length += HELLO_EXT_SZ; - + if (IsAtLeastTLSv1_2(ssl)) { + if (ssl->suites->hashSigAlgoSz) { + length += ssl->suites->hashSigAlgoSz + HELLO_EXT_SZ; + } + } sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; #ifdef CYASSL_DTLS @@ -6084,26 +6158,25 @@ int SetCipherList(Suites* s, const char* list) else output[idx++] = NO_COMPRESSION; - if (IsAtLeastTLSv1_2(ssl)) + if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) { + int i; /* add in the extensions length */ - c16toa(HELLO_EXT_LEN, output + idx); + c16toa(HELLO_EXT_LEN + ssl->suites->hashSigAlgoSz, output + idx); idx += 2; c16toa(HELLO_EXT_SIG_ALGO, output + idx); idx += 2; - c16toa(HELLO_EXT_SIGALGO_SZ, output + idx); + c16toa(HELLO_EXT_SIGALGO_SZ+ssl->suites->hashSigAlgoSz, output+idx); idx += 2; /* This is a lazy list setup. Eventually, we'll need to support * using other hash types or even other extensions. */ - c16toa(HELLO_EXT_SIGALGO_LEN, output + idx); + c16toa(ssl->suites->hashSigAlgoSz, output + idx); idx += 2; - output[idx++] = sha_mac; - output[idx++] = rsa_sa_algo; - output[idx++] = sha_mac; - output[idx++] = dsa_sa_algo; - output[idx++] = sha_mac; - output[idx++] = ecc_dsa_sa_algo; + for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, idx++) { + output[idx] = ssl->suites->hashSigAlgo[i]; + } + idx += i; } #ifdef CYASSL_DTLS From afb0cb3e2070cb559f85962548c01a54865750bb Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 12 Feb 2013 14:57:39 -0800 Subject: [PATCH 3/7] Fixed merge conflict with stashed code --- src/internal.c | 86 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 25 deletions(-) diff --git a/src/internal.c b/src/internal.c index a64d7fce4..ba758c2e4 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4374,7 +4374,10 @@ static void BuildCertHashes(CYASSL* ssl, Hashes* hashes) if (ssl->options.tls) { if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->specs.mac_algorithm <= sha256_mac) { + if (ssl->specs.mac_algorithm == sha_mac) { + ShaFinal(&ssl->hashSha, hashes->hash); + } + else if (ssl->specs.mac_algorithm == sha256_mac) { #ifndef NO_SHA256 Sha256Final(&ssl->hashSha256, hashes->hash); #endif @@ -6081,10 +6084,8 @@ int SetCipherList(Suites* s, const char* list) + ssl->suites->suiteSz + SUITE_LEN + COMP_LEN + ENUM_LEN; - if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->suites->hashSigAlgoSz) { - length += ssl->suites->hashSigAlgoSz + HELLO_EXT_SZ; - } + if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) { + length += ssl->suites->hashSigAlgoSz + HELLO_EXT_SZ; } sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; @@ -6169,14 +6170,11 @@ int SetCipherList(Suites* s, const char* list) idx += 2; c16toa(HELLO_EXT_SIGALGO_SZ+ssl->suites->hashSigAlgoSz, output+idx); idx += 2; - /* This is a lazy list setup. Eventually, we'll need to support - * using other hash types or even other extensions. */ c16toa(ssl->suites->hashSigAlgoSz, output + idx); idx += 2; for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, idx++) { output[idx] = ssl->suites->hashSigAlgo[i]; } - idx += i; } #ifdef CYASSL_DTLS @@ -6514,6 +6512,8 @@ int SetCipherList(Suites* s, const char* list) byte hash384[SHA384_DIGEST_SIZE]; #endif byte messageVerify[MAX_DH_SZ]; + byte sigAlgo = ssl->specs.sig_algo; + byte hashAlgo = ssl->specs.mac_algorithm; /* adjust from start idx */ verifySz = (word16)(*inOutIdx - verifySz); @@ -6525,7 +6525,14 @@ int SetCipherList(Suites* s, const char* list) if (IsAtLeastTLSv1_2(ssl)) { /* just advance for now TODO: validate hash algo params */ - *inOutIdx += LENGTH_SZ; + /* XXX This is where we look at the signature algorithm, + * which should match what is in ssl->specs.sig_algo. We + * check that the hash is in our list of available hashes, + * and just use it and only it. */ + hashAlgo = input[*inOutIdx]; + *inOutIdx += 1; + sigAlgo = input[*inOutIdx]; + *inOutIdx += 1; } /* signature */ @@ -6569,7 +6576,7 @@ int SetCipherList(Suites* s, const char* list) #endif /* rsa */ - if (ssl->specs.sig_algo == rsa_sa_algo) + if (sigAlgo == rsa_sa_algo) { int ret; byte* out; @@ -6586,14 +6593,14 @@ int SetCipherList(Suites* s, const char* list) int typeH = SHAh; int digestSz = SHA_DIGEST_SIZE; - if (ssl->specs.mac_algorithm <= sha256_mac) { + if (hashAlgo == sha256_mac) { #ifndef NO_SHA256 digest = hash256; typeH = SHA256h; digestSz = SHA256_DIGEST_SIZE; #endif } - else if (ssl->specs.mac_algorithm == sha384_mac) { + else if (hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 digest = hash384; typeH = SHA384h; @@ -6614,7 +6621,7 @@ int SetCipherList(Suites* s, const char* list) } #ifdef HAVE_ECC /* ecdsa */ - else if (ssl->specs.sig_algo == ecc_dsa_sa_algo) { + else if (sigAlgo == ecc_dsa_sa_algo) { int verify = 0, ret; byte* digest = &hash[MD5_DIGEST_SIZE]; word32 digestSz = SHA_DIGEST_SIZE; @@ -6622,13 +6629,13 @@ int SetCipherList(Suites* s, const char* list) return NO_PEER_KEY; if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->specs.mac_algorithm <= sha256_mac) { + if (hashAlgo == sha256_mac) { #ifndef NO_SHA256 digest = hash256; digestSz = SHA256_DIGEST_SIZE; #endif } - else if (ssl->specs.mac_algorithm == sha384_mac) { + else if (hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 digest = hash384; digestSz = SHA384_DIGEST_SIZE; @@ -6964,7 +6971,7 @@ int SetCipherList(Suites* s, const char* list) length = sigOutSz; if (IsAtLeastTLSv1_2(ssl)) { verify[0] = ssl->specs.mac_algorithm; - verify[1] = usingEcc ? ecc_dsa_sa_algo : rsa_sa_algo; + verify[1] = ssl->specs.sig_algo; extraSz = HASH_SIG_SIZE; } c16toa((word16)length, verify + extraSz); /* prepend verify header*/ @@ -6977,7 +6984,7 @@ int SetCipherList(Suites* s, const char* list) if (IsAtLeastTLSv1_2(ssl)) { digest = ssl->certHashes.hash; - if (ssl->specs.mac_algorithm <= sha256_mac) { + if (ssl->specs.mac_algorithm == sha256_mac) { #ifndef NO_SHA256 digestSz = SHA256_DIGEST_SIZE; #endif @@ -7000,7 +7007,7 @@ int SetCipherList(Suites* s, const char* list) int digestSz = SHA_DIGEST_SIZE; int typeH = SHAh; - if (ssl->specs.mac_algorithm <= sha256_mac) { + if (ssl->specs.mac_algorithm == sha256_mac) { #ifndef NO_SHA256 typeH = SHA256h; digestSz = SHA256_DIGEST_SIZE; @@ -7409,7 +7416,7 @@ int SetCipherList(Suites* s, const char* list) int typeH = SHAh; int digestSz = SHA_DIGEST_SIZE; - if (ssl->specs.mac_algorithm <= sha256_mac) { + if (ssl->specs.mac_algorithm == sha256_mac) { #ifndef NO_SHA256 digest = hash256; typeH = SHA256h; @@ -7443,7 +7450,7 @@ int SetCipherList(Suites* s, const char* list) word32 sz = sigSz; if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->specs.mac_algorithm <= sha256_mac) { + if (ssl->specs.mac_algorithm == sha256_mac) { #ifndef NO_SHA256 digest = hash256; digestSz = SHA256_DIGEST_SIZE; @@ -7662,7 +7669,7 @@ int SetCipherList(Suites* s, const char* list) int typeH = SHAh; int digestSz = SHA_DIGEST_SIZE; - if (ssl->specs.mac_algorithm <= sha256_mac) { + if (ssl->specs.mac_algorithm == sha256_mac) { #ifndef NO_SHA256 digest = hash256; typeH = SHA256h; @@ -8489,8 +8496,37 @@ int SetCipherList(Suites* s, const char* list) ssl->options.clientState = CLIENT_HELLO_COMPLETE; *inOutIdx = i; - if ( (i - begin) < helloSz) - *inOutIdx = begin + helloSz; /* skip extensions */ + if ( (i - begin) < helloSz) { + if (IsAtLeastTLSv1_2(ssl)) { + word16 totalExtSz, extId, extSz; + + ato16(&input[i], &totalExtSz); + i += 2; + ato16(&input[i], &extId); + i += 2; + ato16(&input[i], &extSz); + i += 2; + ato16(&input[i], &clSuites.hashSigAlgoSz); + i += 2; + + if (i + clSuites.hashSigAlgoSz > totalSz) + return INCOMPLETE_DATA; + if (clSuites.hashSigAlgoSz > HELLO_EXT_SIGALGO_MAX) + return BUFFER_ERROR; + + XMEMCPY(clSuites.hashSigAlgo, input+i, clSuites.hashSigAlgoSz); + i += clSuites.hashSigAlgoSz; + + *inOutIdx = i; + } + else + *inOutIdx = begin + helloSz; /* skip extensions */ + } + else { + if (IsAtLeastTLSv1_2(ssl)) { + clSuites.hashSigAlgoSz = 0; + } + } ssl->options.haveSessionId = 1; /* ProcessOld uses same resume code */ @@ -8571,7 +8607,7 @@ int SetCipherList(Suites* s, const char* list) int typeH = SHAh; int digestSz = SHA_DIGEST_SIZE; - if (ssl->specs.mac_algorithm <= sha256_mac) { + if (ssl->specs.mac_algorithm == sha256_mac) { #ifndef NO_SHA256 typeH = SHA256h; digestSz = SHA256_DIGEST_SIZE; @@ -8607,7 +8643,7 @@ int SetCipherList(Suites* s, const char* list) CYASSL_MSG("Doing ECC peer cert verify"); if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->specs.mac_algorithm <= sha256_mac) { + if (ssl->specs.mac_algorithm == sha256_mac) { #ifndef NO_SHA256 digestSz = SHA256_DIGEST_SIZE; #endif From d65e5ef3e4d9fac98bf188a728038370ec95992f Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 13 Feb 2013 12:05:56 -0800 Subject: [PATCH 4/7] bug fix --- src/internal.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/internal.c b/src/internal.c index ba758c2e4..048ee9eee 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4374,8 +4374,8 @@ static void BuildCertHashes(CYASSL* ssl, Hashes* hashes) if (ssl->options.tls) { if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->specs.mac_algorithm == sha_mac) { - ShaFinal(&ssl->hashSha, hashes->hash); + if (ssl->specs.mac_algorithm <= sha_mac) { + ShaFinal(&ssl->hashSha, &hashes->hash[MD5_DIGEST_SIZE]); } else if (ssl->specs.mac_algorithm == sha256_mac) { #ifndef NO_SHA256 @@ -7003,18 +7003,20 @@ int SetCipherList(Suites* s, const char* list) } else { if (IsAtLeastTLSv1_2(ssl)) { - byte* digest = ssl->certHashes.hash; + byte* digest = &ssl->certHashes.hash[MD5_DIGEST_SIZE]; int digestSz = SHA_DIGEST_SIZE; int typeH = SHAh; if (ssl->specs.mac_algorithm == sha256_mac) { #ifndef NO_SHA256 + digest = ssl->certHashes.hash; typeH = SHA256h; digestSz = SHA256_DIGEST_SIZE; #endif } else if (ssl->specs.mac_algorithm == sha384_mac) { #ifdef CYASSL_SHA384 + digest = ssl->certHashes.hash; typeH = SHA384h; digestSz = SHA384_DIGEST_SIZE; #endif @@ -7357,7 +7359,7 @@ int SetCipherList(Suites* s, const char* list) XMEMCPY(output + idx, exportBuf, expSz); idx += expSz; if (IsAtLeastTLSv1_2(ssl)) { - output[idx++] = sha_mac; + output[idx++] = ssl->specs.mac_algorithm; output[idx++] = ssl->specs.sig_algo; } c16toa((word16)sigSz, output + idx); @@ -7609,7 +7611,7 @@ int SetCipherList(Suites* s, const char* list) /* Add signature */ if (IsAtLeastTLSv1_2(ssl)) { - output[idx++] = sha_mac; + output[idx++] = ssl->specs.mac_algorithm; output[idx++] = ssl->specs.sig_algo; } /* size */ @@ -8603,18 +8605,20 @@ int SetCipherList(Suites* s, const char* list) if (IsAtLeastTLSv1_2(ssl)) { byte encodedSig[MAX_ENCODED_SIG_SZ]; word32 sigSz; - byte* digest = ssl->certHashes.hash; + byte* digest = &ssl->certHashes.hash[MD5_DIGEST_SIZE]; int typeH = SHAh; int digestSz = SHA_DIGEST_SIZE; if (ssl->specs.mac_algorithm == sha256_mac) { #ifndef NO_SHA256 + digest = ssl->certHashes.hash; typeH = SHA256h; digestSz = SHA256_DIGEST_SIZE; #endif } else if (ssl->specs.mac_algorithm == sha384_mac) { #ifdef CYASSL_SHA384 + digest = ssl->certHashes.hash; typeH = SHA384h; digestSz = SHA384_DIGEST_SIZE; #endif From 657b10c8b24b13adc1a735afd4f129896c059eb3 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 13 Feb 2013 15:30:46 -0800 Subject: [PATCH 5/7] client sends sig/hash hello extension to server, server sends a selection (hardcoded) back, and both use the selection --- src/internal.c | 88 +++++++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/src/internal.c b/src/internal.c index 048ee9eee..da86979e2 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4374,15 +4374,15 @@ static void BuildCertHashes(CYASSL* ssl, Hashes* hashes) if (ssl->options.tls) { if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->specs.mac_algorithm <= sha_mac) { + if (ssl->suites->hashAlgo <= sha_mac) { ShaFinal(&ssl->hashSha, &hashes->hash[MD5_DIGEST_SIZE]); } - else if (ssl->specs.mac_algorithm == sha256_mac) { + else if (ssl->suites->hashAlgo == sha256_mac) { #ifndef NO_SHA256 Sha256Final(&ssl->hashSha256, hashes->hash); #endif } - else if (ssl->specs.mac_algorithm == sha384_mac) { + else if (ssl->suites->hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 Sha384Final(&ssl->hashSha384, hashes->hash); #endif @@ -4695,8 +4695,8 @@ int SendCertificateRequest(CYASSL* ssl) c16toa(HASH_SIG_SIZE, &output[i]); i += LENGTH_SZ; - output[i++] = sha_mac; /* hash */ - output[i++] = rsa_sa_algo; /* sig */ + output[i++] = ssl->suites->hashAlgo; /* hash */ + output[i++] = ssl->specs.sig_algo; /* sig */ } c16toa(0, &output[i]); /* auth's */ @@ -6358,17 +6358,20 @@ int SetCipherList(Suites* s, const char* list) /* types, read in here */ *inOutIdx += len; - ato16(&input[*inOutIdx], &len); - *inOutIdx += LENGTH_SZ; if (IsAtLeastTLSv1_2(ssl)) { /* hash sig format */ - *inOutIdx += len; ato16(&input[*inOutIdx], &len); *inOutIdx += LENGTH_SZ; + /* XXX Read the hash sig format, can be more than one pair. */ + ssl->suites->hashAlgo = input[(*inOutIdx)++]; + ssl->suites->signAlgo = input[(*inOutIdx)++]; + /**inOutIdx += len;*/ } /* authorities */ + ato16(&input[*inOutIdx], &len); + *inOutIdx += LENGTH_SZ; while (len) { word16 dnSz; @@ -6970,7 +6973,7 @@ int SetCipherList(Suites* s, const char* list) #endif length = sigOutSz; if (IsAtLeastTLSv1_2(ssl)) { - verify[0] = ssl->specs.mac_algorithm; + verify[0] = ssl->suites->hashAlgo; verify[1] = ssl->specs.sig_algo; extraSz = HASH_SIG_SIZE; } @@ -6984,12 +6987,12 @@ int SetCipherList(Suites* s, const char* list) if (IsAtLeastTLSv1_2(ssl)) { digest = ssl->certHashes.hash; - if (ssl->specs.mac_algorithm == sha256_mac) { + if (ssl->suites->hashAlgo == sha256_mac) { #ifndef NO_SHA256 digestSz = SHA256_DIGEST_SIZE; #endif } - else if (ssl->specs.mac_algorithm == sha384_mac) { + else if (ssl->suites->hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 digestSz = SHA384_DIGEST_SIZE; #endif @@ -7007,14 +7010,14 @@ int SetCipherList(Suites* s, const char* list) int digestSz = SHA_DIGEST_SIZE; int typeH = SHAh; - if (ssl->specs.mac_algorithm == sha256_mac) { + if (ssl->suites->hashAlgo == sha256_mac) { #ifndef NO_SHA256 digest = ssl->certHashes.hash; typeH = SHA256h; digestSz = SHA256_DIGEST_SIZE; #endif } - else if (ssl->specs.mac_algorithm == sha384_mac) { + else if (ssl->suites->hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 digest = ssl->certHashes.hash; typeH = SHA384h; @@ -7359,7 +7362,7 @@ int SetCipherList(Suites* s, const char* list) XMEMCPY(output + idx, exportBuf, expSz); idx += expSz; if (IsAtLeastTLSv1_2(ssl)) { - output[idx++] = ssl->specs.mac_algorithm; + output[idx++] = ssl->suites->hashAlgo; output[idx++] = ssl->specs.sig_algo; } c16toa((word16)sigSz, output + idx); @@ -7418,14 +7421,14 @@ int SetCipherList(Suites* s, const char* list) int typeH = SHAh; int digestSz = SHA_DIGEST_SIZE; - if (ssl->specs.mac_algorithm == sha256_mac) { + if (ssl->suites->hashAlgo == sha256_mac) { #ifndef NO_SHA256 digest = hash256; typeH = SHA256h; digestSz = SHA256_DIGEST_SIZE; #endif } - else if (ssl->specs.mac_algorithm == sha384_mac) { + else if (ssl->suites->hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 digest = hash384; typeH = SHA384h; @@ -7452,13 +7455,13 @@ int SetCipherList(Suites* s, const char* list) word32 sz = sigSz; if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->specs.mac_algorithm == sha256_mac) { + if (ssl->suites->hashAlgo == sha256_mac) { #ifndef NO_SHA256 digest = hash256; digestSz = SHA256_DIGEST_SIZE; #endif } - else if (ssl->specs.mac_algorithm == sha384_mac) { + else if (ssl->suites->hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 digest = hash384; digestSz = SHA384_DIGEST_SIZE; @@ -7611,7 +7614,7 @@ int SetCipherList(Suites* s, const char* list) /* Add signature */ if (IsAtLeastTLSv1_2(ssl)) { - output[idx++] = ssl->specs.mac_algorithm; + output[idx++] = ssl->suites->hashAlgo; output[idx++] = ssl->specs.sig_algo; } /* size */ @@ -7671,14 +7674,14 @@ int SetCipherList(Suites* s, const char* list) int typeH = SHAh; int digestSz = SHA_DIGEST_SIZE; - if (ssl->specs.mac_algorithm == sha256_mac) { + if (ssl->suites->hashAlgo == sha256_mac) { #ifndef NO_SHA256 digest = hash256; typeH = SHA256h; digestSz = SHA256_DIGEST_SIZE; #endif } - else if (ssl->specs.mac_algorithm == sha384_mac) { + else if (ssl->suites->hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 digest = hash384; typeH = SHA384h; @@ -8179,7 +8182,6 @@ int SetCipherList(Suites* s, const char* list) if (ssl->suites == NULL) return SUITES_ERROR; - /* start with best, if a match we are good */ for (i = 0; i < ssl->suites->suiteSz; i += 2) for (j = 0; j < peerSuites->suiteSz; j += 2) @@ -8187,10 +8189,17 @@ int SetCipherList(Suites* s, const char* list) ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) { if (VerifySuite(ssl, i)) { + int result; CYASSL_MSG("Verified suite validity"); ssl->options.cipherSuite0 = ssl->suites->suites[i]; ssl->options.cipherSuite = ssl->suites->suites[i+1]; - return SetCipherSpecs(ssl); + result = SetCipherSpecs(ssl); + if (result == 0) { + /* XXX */ + ssl->suites->hashAlgo = sha256_mac; + ssl->suites->signAlgo = ssl->specs.sig_algo; + } + return result; } else { CYASSL_MSG("Could not verify suite validity, continue"); @@ -8508,16 +8517,21 @@ int SetCipherList(Suites* s, const char* list) i += 2; ato16(&input[i], &extSz); i += 2; - ato16(&input[i], &clSuites.hashSigAlgoSz); - i += 2; - - if (i + clSuites.hashSigAlgoSz > totalSz) - return INCOMPLETE_DATA; - if (clSuites.hashSigAlgoSz > HELLO_EXT_SIGALGO_MAX) - return BUFFER_ERROR; - - XMEMCPY(clSuites.hashSigAlgo, input+i, clSuites.hashSigAlgoSz); - i += clSuites.hashSigAlgoSz; + if (extId == HELLO_EXT_SIG_ALGO) { + ato16(&input[i], &clSuites.hashSigAlgoSz); + i += 2; + + if (i + clSuites.hashSigAlgoSz > totalSz) + return INCOMPLETE_DATA; + if (clSuites.hashSigAlgoSz > HELLO_EXT_SIGALGO_MAX) + return BUFFER_ERROR; + + XMEMCPY(clSuites.hashSigAlgo, + input+i, clSuites.hashSigAlgoSz); + i += clSuites.hashSigAlgoSz; + } + else + i += extSz; *inOutIdx = i; } @@ -8609,14 +8623,14 @@ int SetCipherList(Suites* s, const char* list) int typeH = SHAh; int digestSz = SHA_DIGEST_SIZE; - if (ssl->specs.mac_algorithm == sha256_mac) { + if (ssl->suites->hashAlgo == sha256_mac) { #ifndef NO_SHA256 digest = ssl->certHashes.hash; typeH = SHA256h; digestSz = SHA256_DIGEST_SIZE; #endif } - else if (ssl->specs.mac_algorithm == sha384_mac) { + else if (ssl->suites->hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 digest = ssl->certHashes.hash; typeH = SHA384h; @@ -8647,12 +8661,12 @@ int SetCipherList(Suites* s, const char* list) CYASSL_MSG("Doing ECC peer cert verify"); if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->specs.mac_algorithm == sha256_mac) { + if (ssl->suites->hashAlgo == sha256_mac) { #ifndef NO_SHA256 digestSz = SHA256_DIGEST_SIZE; #endif } - else if (ssl->specs.mac_algorithm == sha384_mac) { + else if (ssl->suites->hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 digestSz = SHA384_DIGEST_SIZE; #endif From df011b2e40f70e49ca027f5524afea5298f807a2 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 18 Feb 2013 11:54:23 -0800 Subject: [PATCH 6/7] Server and client tell each other which sig/hash algos they support, peers pick from the list and use it indicating which one they used as appropriate. --- cyassl/internal.h | 21 ++-- src/internal.c | 260 +++++++++++++++++++++++++--------------------- src/tls.c | 2 +- 3 files changed, 156 insertions(+), 127 deletions(-) diff --git a/cyassl/internal.h b/cyassl/internal.h index c2c735289..c6228b8ca 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -749,10 +749,10 @@ typedef struct Suites { int setSuites; /* user set suites from default */ byte suites[MAX_SUITE_SZ]; word16 suiteSz; /* suite length in bytes */ - byte hashSigAlgo[HELLO_EXT_SIGALGO_MAX]; + byte hashSigAlgo[HELLO_EXT_SIGALGO_MAX]; /* sig/algo to offer */ word16 hashSigAlgoSz; /* SigAlgo extension length in bytes */ byte hashAlgo; /* selected hash algorithm */ - byte signAlgo; /* selected sig algorithm */ + byte sigAlgo; /* selected sig algorithm */ } Suites; @@ -1168,15 +1168,18 @@ CYASSL_LOCAL void InitCiphers(CYASSL* ssl); CYASSL_LOCAL void FreeCiphers(CYASSL* ssl); -#ifdef CYASSL_SHA384 - #define HASHES_SZ SHA384_DIGEST_SIZE -#else - #define HASHES_SZ FINISHED_SZ -#endif - /* hashes type */ typedef struct Hashes { - byte hash[HASHES_SZ]; + #ifndef NO_MD5 + byte md5[MD5_DIGEST_SIZE]; + #endif + byte sha[SHA_DIGEST_SIZE]; + #ifndef NO_SHA256 + byte sha256[SHA256_DIGEST_SIZE]; + #endif + #ifdef CYASSL_SHA384 + byte sha384[SHA384_DIGEST_SIZE]; + #endif } Hashes; diff --git a/src/internal.c b/src/internal.c index da86979e2..9e421b5bc 100644 --- a/src/internal.c +++ b/src/internal.c @@ -97,6 +97,8 @@ static void Hmac(CYASSL* ssl, byte* digest, const byte* buffer, word32 sz, static void BuildCertHashes(CYASSL* ssl, Hashes* hashes); #endif +static void PickHashSigAlgo(CYASSL* ssl, + const byte* hashSigAlgo, word32 hashSigAlgoSz); #ifndef min @@ -2302,7 +2304,7 @@ static void BuildMD5(CYASSL* ssl, Hashes* hashes, const byte* sender) Md5Update(&ssl->hashMd5, PAD2, PAD_MD5); Md5Update(&ssl->hashMd5, md5_result, MD5_DIGEST_SIZE); - Md5Final(&ssl->hashMd5, &hashes->hash[0]); + Md5Final(&ssl->hashMd5, hashes->md5); } @@ -2322,7 +2324,7 @@ static void BuildSHA(CYASSL* ssl, Hashes* hashes, const byte* sender) ShaUpdate(&ssl->hashSha, PAD2, PAD_SHA); ShaUpdate(&ssl->hashSha, sha_result, SHA_DIGEST_SIZE); - ShaFinal(&ssl->hashSha, &hashes->hash[MD5_DIGEST_SIZE]); + ShaFinal(&ssl->hashSha, hashes->sha); } #endif @@ -2341,16 +2343,16 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) Sha384 sha384; #endif -#ifndef NO_SHA256 - InitSha256(&sha256); - if (IsAtLeastTLSv1_2(ssl)) - sha256 = ssl->hashSha256; -#endif -#ifdef CYASSL_SHA384 - InitSha384(&sha384); - if (IsAtLeastTLSv1_2(ssl)) - sha384 = ssl->hashSha384; -#endif + if (IsAtLeastTLSv1_2(ssl)) { + #ifndef NO_SHA256 + InitSha256(&sha256); + sha256 = ssl->hashSha256; + #endif + #ifdef CYASSL_SHA384 + InitSha384(&sha384); + sha384 = ssl->hashSha384; + #endif + } if (ssl->options.tls) BuildTlsFinished(ssl, hashes, sender); @@ -2362,17 +2364,17 @@ static void BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) #endif /* restore */ -#ifndef NO_MD5 - ssl->hashMd5 = md5; -#endif + #ifndef NO_MD5 + ssl->hashMd5 = md5; + #endif ssl->hashSha = sha; if (IsAtLeastTLSv1_2(ssl)) { -#ifndef NO_SHA256 - ssl->hashSha256 = sha256; -#endif -#ifdef CYASSL_SHA384 - ssl->hashSha384 = sha384; -#endif + #ifndef NO_SHA256 + ssl->hashSha256 = sha256; + #endif + #ifdef CYASSL_SHA384 + ssl->hashSha384 = sha384; + #endif } } @@ -4361,54 +4363,45 @@ static void BuildCertHashes(CYASSL* ssl, Hashes* hashes) Sha384 sha384; #endif - #ifndef NO_SHA256 - InitSha256(&sha256); - if (IsAtLeastTLSv1_2(ssl)) + if (IsAtLeastTLSv1_2(ssl)) { + #ifndef NO_SHA256 + InitSha256(&sha256); sha256 = ssl->hashSha256; - #endif - #ifdef CYASSL_SHA384 - InitSha384(&sha384); - if (IsAtLeastTLSv1_2(ssl)) + #endif + #ifdef CYASSL_SHA384 + InitSha384(&sha384); sha384 = ssl->hashSha384; - #endif + #endif + } if (ssl->options.tls) { + Md5Final(&ssl->hashMd5, hashes->md5); + ShaFinal(&ssl->hashSha, hashes->sha); if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->suites->hashAlgo <= sha_mac) { - ShaFinal(&ssl->hashSha, &hashes->hash[MD5_DIGEST_SIZE]); - } - else if (ssl->suites->hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - Sha256Final(&ssl->hashSha256, hashes->hash); - #endif - } - else if (ssl->suites->hashAlgo == sha384_mac) { - #ifdef CYASSL_SHA384 - Sha384Final(&ssl->hashSha384, hashes->hash); - #endif - } - } - else { - Md5Final(&ssl->hashMd5, &hashes->hash[0]); - ShaFinal(&ssl->hashSha, &hashes->hash[MD5_DIGEST_SIZE]); + #ifndef NO_SHA256 + Sha256Final(&ssl->hashSha256, hashes->sha256); + #endif + #ifdef CYASSL_SHA384 + Sha384Final(&ssl->hashSha384, hashes->sha384); + #endif } } else { - BuildMD5_CertVerify(ssl, &hashes->hash[0]); - BuildSHA_CertVerify(ssl, &hashes->hash[MD5_DIGEST_SIZE]); + BuildMD5_CertVerify(ssl, hashes->md5); + BuildSHA_CertVerify(ssl, hashes->sha); } /* restore */ ssl->hashMd5 = md5; ssl->hashSha = sha; - #ifndef NO_SHA256 - if (IsAtLeastTLSv1_2(ssl)) + if (IsAtLeastTLSv1_2(ssl)) { + #ifndef NO_SHA256 ssl->hashSha256 = sha256; - #endif - #ifdef CYASSL_SHA384 - if (IsAtLeastTLSv1_2(ssl)) + #endif + #ifdef CYASSL_SHA384 ssl->hashSha384 = sha384; - #endif + #endif + } } #endif @@ -4664,7 +4657,7 @@ int SendCertificateRequest(CYASSL* ssl) int reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ; /* add auth later */ if (IsAtLeastTLSv1_2(ssl)) - reqSz += LENGTH_SZ + HASH_SIG_SIZE; + reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz; if (ssl->options.usingPSK_cipher) return 0; /* not needed */ @@ -4692,11 +4685,12 @@ int SendCertificateRequest(CYASSL* ssl) /* supported hash/sig */ if (IsAtLeastTLSv1_2(ssl)) { - c16toa(HASH_SIG_SIZE, &output[i]); + c16toa(ssl->suites->hashSigAlgoSz, &output[i]); i += LENGTH_SZ; - output[i++] = ssl->suites->hashAlgo; /* hash */ - output[i++] = ssl->specs.sig_algo; /* sig */ + XMEMCPY(&output[i], + ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz); + i += ssl->suites->hashSigAlgoSz; } c16toa(0, &output[i]); /* auth's */ @@ -5841,7 +5835,7 @@ int SetCipherList(Suites* s, const char* list) if (*list == 0) return 1; /* CyaSSL default */ - if (XSTRNCMP(haystack, "ALL", 3) == 0) return 1; /* CyaSSL default */ + if (XSTRNCMP(haystack, "ALL", 3) == 0) return 1; /* CyaSSL defualt */ for(;;) { word32 len; @@ -6363,10 +6357,8 @@ int SetCipherList(Suites* s, const char* list) /* hash sig format */ ato16(&input[*inOutIdx], &len); *inOutIdx += LENGTH_SZ; - /* XXX Read the hash sig format, can be more than one pair. */ - ssl->suites->hashAlgo = input[(*inOutIdx)++]; - ssl->suites->signAlgo = input[(*inOutIdx)++]; - /**inOutIdx += len;*/ + PickHashSigAlgo(ssl, &input[*inOutIdx], len); + *inOutIdx += len; } /* authorities */ @@ -6515,8 +6507,8 @@ int SetCipherList(Suites* s, const char* list) byte hash384[SHA384_DIGEST_SIZE]; #endif byte messageVerify[MAX_DH_SZ]; + byte hashAlgo = sha_mac; byte sigAlgo = ssl->specs.sig_algo; - byte hashAlgo = ssl->specs.mac_algorithm; /* adjust from start idx */ verifySz = (word16)(*inOutIdx - verifySz); @@ -6527,11 +6519,6 @@ int SetCipherList(Suites* s, const char* list) XMEMCPY(messageVerify, &input[*inOutIdx - verifySz], verifySz); if (IsAtLeastTLSv1_2(ssl)) { - /* just advance for now TODO: validate hash algo params */ - /* XXX This is where we look at the signature algorithm, - * which should match what is in ssl->specs.sig_algo. We - * check that the hash is in our list of available hashes, - * and just use it and only it. */ hashAlgo = input[*inOutIdx]; *inOutIdx += 1; sigAlgo = input[*inOutIdx]; @@ -6962,7 +6949,7 @@ int SetCipherList(Suites* s, const char* list) if (ret == 0) { byte* verify = (byte*)&output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ]; - byte* signBuffer = ssl->certHashes.hash; + byte* signBuffer = ssl->certHashes.md5; word32 signSz = FINISHED_SZ; byte encodedSig[MAX_ENCODED_SIG_SZ]; word32 extraSz = 0; /* tls 1.2 hash/sig */ @@ -6974,7 +6961,7 @@ int SetCipherList(Suites* s, const char* list) length = sigOutSz; if (IsAtLeastTLSv1_2(ssl)) { verify[0] = ssl->suites->hashAlgo; - verify[1] = ssl->specs.sig_algo; + verify[1] = usingEcc ? ecc_dsa_sa_algo : rsa_sa_algo; extraSz = HASH_SIG_SIZE; } c16toa((word16)length, verify + extraSz); /* prepend verify header*/ @@ -6983,17 +6970,18 @@ int SetCipherList(Suites* s, const char* list) #ifdef HAVE_ECC word32 localSz = sigOutSz; word32 digestSz = SHA_DIGEST_SIZE; - byte* digest = signBuffer + MD5_DIGEST_SIZE; + byte* digest = ssl->certHashes.sha; if (IsAtLeastTLSv1_2(ssl)) { - digest = ssl->certHashes.hash; if (ssl->suites->hashAlgo == sha256_mac) { #ifndef NO_SHA256 + digest = ssl->certHashes.sha256; digestSz = SHA256_DIGEST_SIZE; #endif } else if (ssl->suites->hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 + digest = ssl->certHashes.sha384; digestSz = SHA384_DIGEST_SIZE; #endif } @@ -7006,20 +6994,20 @@ int SetCipherList(Suites* s, const char* list) } else { if (IsAtLeastTLSv1_2(ssl)) { - byte* digest = &ssl->certHashes.hash[MD5_DIGEST_SIZE]; + byte* digest = ssl->certHashes.sha; int digestSz = SHA_DIGEST_SIZE; int typeH = SHAh; if (ssl->suites->hashAlgo == sha256_mac) { #ifndef NO_SHA256 - digest = ssl->certHashes.hash; + digest = ssl->certHashes.sha256; typeH = SHA256h; digestSz = SHA256_DIGEST_SIZE; #endif } else if (ssl->suites->hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 - digest = ssl->certHashes.hash; + digest = ssl->certHashes.sha384; typeH = SHA384h; digestSz = SHA384_DIGEST_SIZE; #endif @@ -7363,7 +7351,7 @@ int SetCipherList(Suites* s, const char* list) idx += expSz; if (IsAtLeastTLSv1_2(ssl)) { output[idx++] = ssl->suites->hashAlgo; - output[idx++] = ssl->specs.sig_algo; + output[idx++] = ssl->suites->sigAlgo; } c16toa((word16)sigSz, output + idx); idx += LENGTH_SZ; @@ -7412,7 +7400,7 @@ int SetCipherList(Suites* s, const char* list) Sha384Final(&sha384, hash384); #endif - if (ssl->specs.sig_algo == rsa_sa_algo) { + if (ssl->suites->sigAlgo == rsa_sa_algo) { byte* signBuffer = hash; word32 signSz = sizeof(hash); byte encodedSig[MAX_ENCODED_SIG_SZ]; @@ -7449,7 +7437,7 @@ int SetCipherList(Suites* s, const char* list) else return ret; } - else if (ssl->specs.sig_algo == ecc_dsa_sa_algo) { + else if (ssl->suites->sigAlgo == ecc_dsa_sa_algo) { byte* digest = &hash[MD5_DIGEST_SIZE]; word32 digestSz = SHA_DIGEST_SIZE; word32 sz = sigSz; @@ -7615,7 +7603,7 @@ int SetCipherList(Suites* s, const char* list) /* Add signature */ if (IsAtLeastTLSv1_2(ssl)) { output[idx++] = ssl->suites->hashAlgo; - output[idx++] = ssl->specs.sig_algo; + output[idx++] = ssl->suites->sigAlgo; } /* size */ c16toa((word16)sigSz, output + idx); @@ -7665,7 +7653,7 @@ int SetCipherList(Suites* s, const char* list) Sha384Final(&sha384, hash384); #endif - if (ssl->specs.sig_algo == rsa_sa_algo) { + if (ssl->suites->sigAlgo == rsa_sa_algo) { byte* signBuffer = hash; word32 signSz = sizeof(hash); byte encodedSig[MAX_ENCODED_SIG_SZ]; @@ -8170,6 +8158,36 @@ int SetCipherList(Suites* s, const char* list) } + static void PickHashSigAlgo(CYASSL* ssl, + const byte* hashSigAlgo, word32 hashSigAlgoSz) + { + word32 i; + + ssl->suites->sigAlgo = ssl->specs.sig_algo; + ssl->suites->hashAlgo = sha_mac; + + for (i = 0; i < hashSigAlgoSz; i += 2) { + if (hashSigAlgo[i+1] == ssl->specs.sig_algo) { + if (hashSigAlgo[i] == sha_mac) { + break; + } + #ifndef NO_SHA256 + else if (hashSigAlgo[i] == sha256_mac) { + ssl->suites->hashAlgo = sha256_mac; + break; + } + #endif + #ifdef CYASSL_SHA384 + else if (hashSigAlgo[i] == sha384_mac) { + ssl->suites->hashAlgo = sha384_mac; + break; + } + #endif + } + } + } + + static int MatchSuite(CYASSL* ssl, Suites* peerSuites) { word16 i, j; @@ -8194,11 +8212,9 @@ int SetCipherList(Suites* s, const char* list) ssl->options.cipherSuite0 = ssl->suites->suites[i]; ssl->options.cipherSuite = ssl->suites->suites[i+1]; result = SetCipherSpecs(ssl); - if (result == 0) { - /* XXX */ - ssl->suites->hashAlgo = sha256_mac; - ssl->suites->signAlgo = ssl->specs.sig_algo; - } + if (result == 0) + PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, + peerSuites->hashSigAlgoSz); return result; } else { @@ -8507,41 +8523,45 @@ int SetCipherList(Suites* s, const char* list) ssl->options.clientState = CLIENT_HELLO_COMPLETE; *inOutIdx = i; + clSuites.hashSigAlgoSz = 0; if ( (i - begin) < helloSz) { if (IsAtLeastTLSv1_2(ssl)) { + /* Need to process all extensions, i.e. skip the ones we don't + * support. */ word16 totalExtSz, extId, extSz; ato16(&input[i], &totalExtSz); i += 2; - ato16(&input[i], &extId); - i += 2; - ato16(&input[i], &extSz); - i += 2; - if (extId == HELLO_EXT_SIG_ALGO) { - ato16(&input[i], &clSuites.hashSigAlgoSz); + while (totalExtSz) { + ato16(&input[i], &extId); i += 2; - - if (i + clSuites.hashSigAlgoSz > totalSz) - return INCOMPLETE_DATA; - if (clSuites.hashSigAlgoSz > HELLO_EXT_SIGALGO_MAX) - return BUFFER_ERROR; - - XMEMCPY(clSuites.hashSigAlgo, - input+i, clSuites.hashSigAlgoSz); - i += clSuites.hashSigAlgoSz; + ato16(&input[i], &extSz); + i += 2; + totalExtSz -= 4 + extSz; + if (extId == HELLO_EXT_SIG_ALGO) { + ato16(&input[i], &clSuites.hashSigAlgoSz); + i += 2; + + if (i + clSuites.hashSigAlgoSz > totalSz) + return INCOMPLETE_DATA; + if (clSuites.hashSigAlgoSz > HELLO_EXT_SIGALGO_MAX) + return BUFFER_ERROR; + + XMEMCPY(clSuites.hashSigAlgo, + input+i, clSuites.hashSigAlgoSz); + i += clSuites.hashSigAlgoSz; + } + else + i += extSz; + } - else - i += extSz; - *inOutIdx = i; } else *inOutIdx = begin + helloSz; /* skip extensions */ } else { - if (IsAtLeastTLSv1_2(ssl)) { - clSuites.hashSigAlgoSz = 0; - } + clSuites.hashSigAlgoSz = 0; } ssl->options.haveSessionId = 1; @@ -8585,6 +8605,8 @@ int SetCipherList(Suites* s, const char* list) byte* sig; byte* out; int outLen; + byte hashAlgo = sha_mac; + byte sigAlgo; #ifdef CYASSL_CALLBACKS if (ssl->hsInfoOn) @@ -8595,8 +8617,10 @@ int SetCipherList(Suites* s, const char* list) if ( (i + VERIFY_HEADER) > totalSz) return INCOMPLETE_DATA; - if (IsAtLeastTLSv1_2(ssl)) - i += HASH_SIG_SIZE; + if (IsAtLeastTLSv1_2(ssl)) { + hashAlgo = input[i++]; + sigAlgo = input[i++]; + } ato16(&input[i], &sz); i += VERIFY_HEADER; @@ -8619,20 +8643,20 @@ int SetCipherList(Suites* s, const char* list) if (IsAtLeastTLSv1_2(ssl)) { byte encodedSig[MAX_ENCODED_SIG_SZ]; word32 sigSz; - byte* digest = &ssl->certHashes.hash[MD5_DIGEST_SIZE]; + byte* digest = ssl->certHashes.sha; int typeH = SHAh; int digestSz = SHA_DIGEST_SIZE; - if (ssl->suites->hashAlgo == sha256_mac) { + if (hashAlgo == sha256_mac) { #ifndef NO_SHA256 - digest = ssl->certHashes.hash; + digest = ssl->certHashes.sha256; typeH = SHA256h; digestSz = SHA256_DIGEST_SIZE; #endif } - else if (ssl->suites->hashAlgo == sha384_mac) { + else if (hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 - digest = ssl->certHashes.hash; + digest = ssl->certHashes.sha384; typeH = SHA384h; digestSz = SHA384_DIGEST_SIZE; #endif @@ -8655,19 +8679,21 @@ int SetCipherList(Suites* s, const char* list) if (ssl->peerEccDsaKeyPresent) { int verify = 0; int err = -1; - byte* digest = ssl->certHashes.hash; + byte* digest = ssl->certHashes.sha; word32 digestSz = SHA_DIGEST_SIZE; CYASSL_MSG("Doing ECC peer cert verify"); if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->suites->hashAlgo == sha256_mac) { + if (hashAlgo == sha256_mac) { #ifndef NO_SHA256 + digest = ssl->certHashes.sha256; digestSz = SHA256_DIGEST_SIZE; #endif } - else if (ssl->suites->hashAlgo == sha384_mac) { + else if (hashAlgo == sha384_mac) { #ifdef CYASSL_SHA384 + digest = ssl->certHashes.sha384; digestSz = SHA384_DIGEST_SIZE; #endif } diff --git a/src/tls.c b/src/tls.c index b3e67c27d..838bb1a0c 100644 --- a/src/tls.c +++ b/src/tls.c @@ -239,7 +239,7 @@ void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) else side = tls_server; - PRF(hashes->hash, TLS_FINISHED_SZ, ssl->arrays->masterSecret, SECRET_LEN, + PRF((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); } From d9a9982bc8416b8bbdea1dae2d92b66e6e44b01a Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 18 Feb 2013 12:52:08 -0800 Subject: [PATCH 7/7] length check the hello extensions --- cyassl/internal.h | 1 + src/internal.c | 40 ++++++++++++++++++++-------------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/cyassl/internal.h b/cyassl/internal.h index c6228b8ca..2ea1e5a02 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -462,6 +462,7 @@ enum Misc { ALERT_SIZE = 2, /* level + description */ REQUEST_HEADER = 2, /* always use 2 bytes */ VERIFY_HEADER = 2, /* always use 2 bytes */ + EXT_ID_SZ = 2, /* always use 2 bytes */ MAX_DH_SIZE = 513, /* 4096 bit plus possible leading 0 */ MAX_SUITE_SZ = 200, /* 100 suites for now! */ diff --git a/src/internal.c b/src/internal.c index 9e421b5bc..a25cd163c 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8500,6 +8500,7 @@ int SetCipherList(Suites* s, const char* list) return BUFFER_ERROR; XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz); i += clSuites.suiteSz; + clSuites.hashSigAlgoSz = 0; b = input[i++]; /* comp len */ if (i + b > totalSz) @@ -8523,46 +8524,45 @@ int SetCipherList(Suites* s, const char* list) ssl->options.clientState = CLIENT_HELLO_COMPLETE; *inOutIdx = i; - clSuites.hashSigAlgoSz = 0; if ( (i - begin) < helloSz) { if (IsAtLeastTLSv1_2(ssl)) { - /* Need to process all extensions, i.e. skip the ones we don't - * support. */ - word16 totalExtSz, extId, extSz; + /* Process the hello extension. Skip unsupported. */ + word16 totalExtSz; ato16(&input[i], &totalExtSz); - i += 2; + i += LENGTH_SZ; + if (totalExtSz > helloSz + begin - i) + return INCOMPLETE_DATA; while (totalExtSz) { + word16 extId, extSz; + ato16(&input[i], &extId); - i += 2; + i += LENGTH_SZ; ato16(&input[i], &extSz); - i += 2; - totalExtSz -= 4 + extSz; + i += EXT_ID_SZ; + if (extSz > totalExtSz - LENGTH_SZ - EXT_ID_SZ) + return INCOMPLETE_DATA; + if (extId == HELLO_EXT_SIG_ALGO) { ato16(&input[i], &clSuites.hashSigAlgoSz); - i += 2; - - if (i + clSuites.hashSigAlgoSz > totalSz) + i += LENGTH_SZ; + if (clSuites.hashSigAlgoSz > extSz - LENGTH_SZ) return INCOMPLETE_DATA; - if (clSuites.hashSigAlgoSz > HELLO_EXT_SIGALGO_MAX) - return BUFFER_ERROR; - - XMEMCPY(clSuites.hashSigAlgo, - input+i, clSuites.hashSigAlgoSz); + + XMEMCPY(clSuites.hashSigAlgo, &input[i], + min(clSuites.hashSigAlgoSz, HELLO_EXT_SIGALGO_MAX)); i += clSuites.hashSigAlgoSz; } else i += extSz; - + + totalExtSz -= LENGTH_SZ + EXT_ID_SZ + extSz; } *inOutIdx = i; } else *inOutIdx = begin + helloSz; /* skip extensions */ } - else { - clSuites.hashSigAlgoSz = 0; - } ssl->options.haveSessionId = 1; /* ProcessOld uses same resume code */