TLS: Use a helper function for calculating ServerKeyExchange hash
Instead of separate server and client side implementations, use a common set of helper functions for calculating the ServerParams hash for ServerKeyExchange. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
65074a2a7c
commit
6531963584
4 changed files with 132 additions and 144 deletions
|
@ -470,16 +470,13 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
|
|||
server_params_end = pos;
|
||||
|
||||
if (key_exchange == TLS_KEY_X_DHE_RSA) {
|
||||
u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos, *sbuf;
|
||||
size_t hlen, buflen;
|
||||
enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
|
||||
u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *sbuf;
|
||||
size_t buflen;
|
||||
int hlen;
|
||||
u16 slen;
|
||||
struct crypto_hash *ctx;
|
||||
|
||||
hpos = hash;
|
||||
|
||||
#ifdef CONFIG_TLSV12
|
||||
if (conn->rl.tls_version == TLS_VERSION_1_2) {
|
||||
#ifdef CONFIG_TLSV12
|
||||
/*
|
||||
* RFC 5246, 4.7:
|
||||
* TLS v1.2 adds explicit indication of the used
|
||||
|
@ -500,51 +497,22 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
|
|||
}
|
||||
pos += 2;
|
||||
|
||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, 0);
|
||||
if (ctx == NULL)
|
||||
goto fail;
|
||||
crypto_hash_update(ctx, conn->client_random,
|
||||
TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, conn->server_random,
|
||||
TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params,
|
||||
server_params_end - server_params);
|
||||
hlen = SHA256_MAC_LEN;
|
||||
if (crypto_hash_finish(ctx, hpos, &hlen) < 0)
|
||||
goto fail;
|
||||
hlen = tlsv12_key_x_server_params_hash(
|
||||
conn->rl.tls_version, conn->client_random,
|
||||
conn->server_random, server_params,
|
||||
server_params_end - server_params, hash);
|
||||
#else /* CONFIG_TLSV12 */
|
||||
goto fail;
|
||||
#endif /* CONFIG_TLSV12 */
|
||||
} else {
|
||||
#endif /* CONFIG_TLSV12 */
|
||||
if (alg == SIGN_ALG_RSA) {
|
||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
|
||||
if (ctx == NULL)
|
||||
goto fail;
|
||||
crypto_hash_update(ctx, conn->client_random,
|
||||
TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, conn->server_random,
|
||||
TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params,
|
||||
server_params_end - server_params);
|
||||
hlen = sizeof(hash);
|
||||
if (crypto_hash_finish(ctx, hash, &hlen) < 0)
|
||||
goto fail;
|
||||
hpos += hlen;
|
||||
hlen = tls_key_x_server_params_hash(
|
||||
conn->rl.tls_version, conn->client_random,
|
||||
conn->server_random, server_params,
|
||||
server_params_end - server_params, hash);
|
||||
}
|
||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
|
||||
if (ctx == NULL)
|
||||
goto fail;
|
||||
crypto_hash_update(ctx, conn->client_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, conn->server_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params,
|
||||
server_params_end - server_params);
|
||||
hlen = hash + sizeof(hash) - hpos;
|
||||
if (crypto_hash_finish(ctx, hpos, &hlen) < 0)
|
||||
goto fail;
|
||||
hpos += hlen;
|
||||
hlen = hpos - hash;
|
||||
#ifdef CONFIG_TLSV12
|
||||
}
|
||||
#endif /* CONFIG_TLSV12 */
|
||||
|
||||
if (hlen < 0)
|
||||
goto fail;
|
||||
wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerKeyExchange hash",
|
||||
hash, hlen);
|
||||
|
||||
|
@ -606,7 +574,8 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
|
|||
}
|
||||
#endif /* CONFIG_TLSV12 */
|
||||
|
||||
if (buflen != hlen || os_memcmp(sbuf, hash, buflen) != 0) {
|
||||
if (buflen != (unsigned int) hlen ||
|
||||
os_memcmp(sbuf, hash, buflen) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in ServerKeyExchange - did not match calculated hash");
|
||||
os_free(sbuf);
|
||||
goto fail;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "crypto/md5.h"
|
||||
#include "crypto/sha1.h"
|
||||
#include "crypto/sha256.h"
|
||||
#include "x509v3.h"
|
||||
|
@ -331,3 +332,67 @@ int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label,
|
|||
return tls_prf_sha1_md5(secret, secret_len, label, seed, seed_len, out,
|
||||
outlen);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_TLSV12
|
||||
int tlsv12_key_x_server_params_hash(u16 tls_version,
|
||||
const u8 *client_random,
|
||||
const u8 *server_random,
|
||||
const u8 *server_params,
|
||||
size_t server_params_len, u8 *hash)
|
||||
{
|
||||
size_t hlen;
|
||||
struct crypto_hash *ctx;
|
||||
|
||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, 0);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params, server_params_len);
|
||||
hlen = SHA256_MAC_LEN;
|
||||
if (crypto_hash_finish(ctx, hash, &hlen) < 0)
|
||||
return -1;
|
||||
|
||||
return hlen;
|
||||
}
|
||||
#endif /* CONFIG_TLSV12 */
|
||||
|
||||
|
||||
int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
|
||||
const u8 *server_random,
|
||||
const u8 *server_params,
|
||||
size_t server_params_len, u8 *hash)
|
||||
{
|
||||
u8 *hpos;
|
||||
size_t hlen;
|
||||
enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
|
||||
struct crypto_hash *ctx;
|
||||
|
||||
hpos = hash;
|
||||
|
||||
if (alg == SIGN_ALG_RSA) {
|
||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params, server_params_len);
|
||||
hlen = MD5_MAC_LEN;
|
||||
if (crypto_hash_finish(ctx, hash, &hlen) < 0)
|
||||
return -1;
|
||||
hpos += hlen;
|
||||
}
|
||||
|
||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params, server_params_len);
|
||||
hlen = hash + sizeof(hash) - hpos;
|
||||
if (crypto_hash_finish(ctx, hpos, &hlen) < 0)
|
||||
return -1;
|
||||
hpos += hlen;
|
||||
return hpos - hash;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* TLSv1 common definitions
|
||||
* Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -257,5 +257,13 @@ int tls_version_ok(u16 ver);
|
|||
const char * tls_version_str(u16 ver);
|
||||
int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label,
|
||||
const u8 *seed, size_t seed_len, u8 *out, size_t outlen);
|
||||
int tlsv12_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
|
||||
const u8 *server_random,
|
||||
const u8 *server_params,
|
||||
size_t server_params_len, u8 *hash);
|
||||
int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
|
||||
const u8 *server_random,
|
||||
const u8 *server_params,
|
||||
size_t server_params_len, u8 *hash);
|
||||
|
||||
#endif /* TLSV1_COMMON_H */
|
||||
|
|
|
@ -434,32 +434,35 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
|
|||
*/
|
||||
|
||||
if (keyx == TLS_KEY_X_DHE_RSA) {
|
||||
u8 hash[100], *hpos;
|
||||
u8 hash[100];
|
||||
u8 *signed_start;
|
||||
size_t hlen, clen;
|
||||
enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
|
||||
struct crypto_hash *ctx;
|
||||
size_t clen;
|
||||
int hlen;
|
||||
|
||||
if (conn->rl.tls_version >= TLS_VERSION_1_2) {
|
||||
#ifdef CONFIG_TLSV12
|
||||
if (conn->rl.tls_version == TLS_VERSION_1_2) {
|
||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, 0);
|
||||
if (ctx == NULL) {
|
||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||
TLS_ALERT_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
crypto_hash_update(ctx, conn->client_random,
|
||||
TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, conn->server_random,
|
||||
TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params,
|
||||
pos - server_params);
|
||||
hlen = sizeof(hash) - 19;
|
||||
if (crypto_hash_finish(ctx, hash + 19, &hlen) < 0) {
|
||||
hlen = tlsv12_key_x_server_params_hash(
|
||||
conn->rl.tls_version, conn->client_random,
|
||||
conn->server_random, server_params,
|
||||
pos - server_params, hash + 19);
|
||||
|
||||
/*
|
||||
* RFC 5246, 4.7:
|
||||
* TLS v1.2 adds explicit indication of the used
|
||||
* signature and hash algorithms.
|
||||
*
|
||||
* struct {
|
||||
* HashAlgorithm hash;
|
||||
* SignatureAlgorithm signature;
|
||||
* } SignatureAndHashAlgorithm;
|
||||
*/
|
||||
if (hlen < 0 || pos + 2 > end) {
|
||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||
TLS_ALERT_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
*pos++ = TLS_HASH_ALG_SHA256;
|
||||
*pos++ = TLS_SIGN_ALG_RSA;
|
||||
|
||||
/*
|
||||
* RFC 3447, A.2.4 RSASSA-PKCS1-v1_5
|
||||
|
@ -479,85 +482,28 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
|
|||
os_memcpy(hash,
|
||||
"\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65"
|
||||
"\x03\x04\x02\x01\x05\x00\x04\x20", 19);
|
||||
|
||||
#else /* CONFIG_TLSV12 */
|
||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||
TLS_ALERT_INTERNAL_ERROR);
|
||||
return -1;
|
||||
#endif /* CONFIG_TLSV12 */
|
||||
} else {
|
||||
#endif /* CONFIG_TLSV12 */
|
||||
hpos = hash;
|
||||
|
||||
if (alg == SIGN_ALG_RSA) {
|
||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_MD5,
|
||||
NULL, 0);
|
||||
if (ctx == NULL) {
|
||||
tlsv1_server_alert(
|
||||
conn, TLS_ALERT_LEVEL_FATAL,
|
||||
TLS_ALERT_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
crypto_hash_update(ctx, conn->client_random,
|
||||
TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, conn->server_random,
|
||||
TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params,
|
||||
pos - server_params);
|
||||
hlen = sizeof(hash);
|
||||
if (crypto_hash_finish(ctx, hash, &hlen) < 0) {
|
||||
tlsv1_server_alert(
|
||||
conn, TLS_ALERT_LEVEL_FATAL,
|
||||
TLS_ALERT_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
hpos += hlen;
|
||||
}
|
||||
|
||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
|
||||
if (ctx == NULL) {
|
||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||
TLS_ALERT_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
crypto_hash_update(ctx, conn->client_random,
|
||||
TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, conn->server_random,
|
||||
TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params,
|
||||
pos - server_params);
|
||||
hlen = hash + sizeof(hash) - hpos;
|
||||
if (crypto_hash_finish(ctx, hpos, &hlen) < 0) {
|
||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||
TLS_ALERT_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
hpos += hlen;
|
||||
hlen = hpos - hash;
|
||||
#ifdef CONFIG_TLSV12
|
||||
hlen = tls_key_x_server_params_hash(
|
||||
conn->rl.tls_version, conn->client_random,
|
||||
conn->server_random, server_params,
|
||||
pos - server_params, hash);
|
||||
}
|
||||
#endif /* CONFIG_TLSV12 */
|
||||
|
||||
wpa_hexdump(MSG_MSGDUMP,
|
||||
"TLSv1: ServerKeyExchange signed_params hash",
|
||||
if (hlen < 0) {
|
||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||
TLS_ALERT_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_hexdump(MSG_MSGDUMP, "TLS: ServerKeyExchange signed_params hash",
|
||||
hash, hlen);
|
||||
|
||||
#ifdef CONFIG_TLSV12
|
||||
if (conn->rl.tls_version >= TLS_VERSION_1_2) {
|
||||
/*
|
||||
* RFC 5246, 4.7:
|
||||
* TLS v1.2 adds explicit indication of the used
|
||||
* signature and hash algorithms.
|
||||
*
|
||||
* struct {
|
||||
* HashAlgorithm hash;
|
||||
* SignatureAlgorithm signature;
|
||||
* } SignatureAndHashAlgorithm;
|
||||
*/
|
||||
if (pos + 2 > end) {
|
||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||
TLS_ALERT_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
*pos++ = TLS_HASH_ALG_SHA256;
|
||||
*pos++ = TLS_SIGN_ALG_RSA;
|
||||
}
|
||||
#endif /* CONFIG_TLSV12 */
|
||||
|
||||
/*
|
||||
* RFC 2246, 4.7:
|
||||
* In digital signing, one-way hash functions are used as input
|
||||
|
|
Loading…
Reference in a new issue