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;
|
server_params_end = pos;
|
||||||
|
|
||||||
if (key_exchange == TLS_KEY_X_DHE_RSA) {
|
if (key_exchange == TLS_KEY_X_DHE_RSA) {
|
||||||
u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos, *sbuf;
|
u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *sbuf;
|
||||||
size_t hlen, buflen;
|
size_t buflen;
|
||||||
enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
|
int hlen;
|
||||||
u16 slen;
|
u16 slen;
|
||||||
struct crypto_hash *ctx;
|
|
||||||
|
|
||||||
hpos = hash;
|
|
||||||
|
|
||||||
#ifdef CONFIG_TLSV12
|
|
||||||
if (conn->rl.tls_version == TLS_VERSION_1_2) {
|
if (conn->rl.tls_version == TLS_VERSION_1_2) {
|
||||||
|
#ifdef CONFIG_TLSV12
|
||||||
/*
|
/*
|
||||||
* RFC 5246, 4.7:
|
* RFC 5246, 4.7:
|
||||||
* TLS v1.2 adds explicit indication of the used
|
* 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;
|
pos += 2;
|
||||||
|
|
||||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, 0);
|
hlen = tlsv12_key_x_server_params_hash(
|
||||||
if (ctx == NULL)
|
conn->rl.tls_version, conn->client_random,
|
||||||
goto fail;
|
conn->server_random, server_params,
|
||||||
crypto_hash_update(ctx, conn->client_random,
|
server_params_end - server_params, hash);
|
||||||
TLS_RANDOM_LEN);
|
#else /* CONFIG_TLSV12 */
|
||||||
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;
|
goto fail;
|
||||||
|
#endif /* CONFIG_TLSV12 */
|
||||||
} else {
|
} else {
|
||||||
#endif /* CONFIG_TLSV12 */
|
hlen = tls_key_x_server_params_hash(
|
||||||
if (alg == SIGN_ALG_RSA) {
|
conn->rl.tls_version, conn->client_random,
|
||||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
|
conn->server_random, server_params,
|
||||||
if (ctx == NULL)
|
server_params_end - server_params, hash);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
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",
|
wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerKeyExchange hash",
|
||||||
hash, hlen);
|
hash, hlen);
|
||||||
|
|
||||||
|
@ -606,7 +574,8 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_TLSV12 */
|
#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");
|
wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in ServerKeyExchange - did not match calculated hash");
|
||||||
os_free(sbuf);
|
os_free(sbuf);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "crypto/md5.h"
|
||||||
#include "crypto/sha1.h"
|
#include "crypto/sha1.h"
|
||||||
#include "crypto/sha256.h"
|
#include "crypto/sha256.h"
|
||||||
#include "x509v3.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,
|
return tls_prf_sha1_md5(secret, secret_len, label, seed, seed_len, out,
|
||||||
outlen);
|
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
|
* 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.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -257,5 +257,13 @@ int tls_version_ok(u16 ver);
|
||||||
const char * tls_version_str(u16 ver);
|
const char * tls_version_str(u16 ver);
|
||||||
int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label,
|
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);
|
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 */
|
#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) {
|
if (keyx == TLS_KEY_X_DHE_RSA) {
|
||||||
u8 hash[100], *hpos;
|
u8 hash[100];
|
||||||
u8 *signed_start;
|
u8 *signed_start;
|
||||||
size_t hlen, clen;
|
size_t clen;
|
||||||
enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
|
int hlen;
|
||||||
struct crypto_hash *ctx;
|
|
||||||
|
|
||||||
|
if (conn->rl.tls_version >= TLS_VERSION_1_2) {
|
||||||
#ifdef CONFIG_TLSV12
|
#ifdef CONFIG_TLSV12
|
||||||
if (conn->rl.tls_version == TLS_VERSION_1_2) {
|
hlen = tlsv12_key_x_server_params_hash(
|
||||||
ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, 0);
|
conn->rl.tls_version, conn->client_random,
|
||||||
if (ctx == NULL) {
|
conn->server_random, server_params,
|
||||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
pos - server_params, hash + 19);
|
||||||
TLS_ALERT_INTERNAL_ERROR);
|
|
||||||
return -1;
|
/*
|
||||||
}
|
* RFC 5246, 4.7:
|
||||||
crypto_hash_update(ctx, conn->client_random,
|
* TLS v1.2 adds explicit indication of the used
|
||||||
TLS_RANDOM_LEN);
|
* signature and hash algorithms.
|
||||||
crypto_hash_update(ctx, conn->server_random,
|
*
|
||||||
TLS_RANDOM_LEN);
|
* struct {
|
||||||
crypto_hash_update(ctx, server_params,
|
* HashAlgorithm hash;
|
||||||
pos - server_params);
|
* SignatureAlgorithm signature;
|
||||||
hlen = sizeof(hash) - 19;
|
* } SignatureAndHashAlgorithm;
|
||||||
if (crypto_hash_finish(ctx, hash + 19, &hlen) < 0) {
|
*/
|
||||||
|
if (hlen < 0 || pos + 2 > end) {
|
||||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
TLS_ALERT_INTERNAL_ERROR);
|
TLS_ALERT_INTERNAL_ERROR);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
*pos++ = TLS_HASH_ALG_SHA256;
|
||||||
|
*pos++ = TLS_SIGN_ALG_RSA;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RFC 3447, A.2.4 RSASSA-PKCS1-v1_5
|
* 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,
|
os_memcpy(hash,
|
||||||
"\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65"
|
"\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65"
|
||||||
"\x03\x04\x02\x01\x05\x00\x04\x20", 19);
|
"\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 {
|
} else {
|
||||||
#endif /* CONFIG_TLSV12 */
|
hlen = tls_key_x_server_params_hash(
|
||||||
hpos = hash;
|
conn->rl.tls_version, conn->client_random,
|
||||||
|
conn->server_random, server_params,
|
||||||
if (alg == SIGN_ALG_RSA) {
|
pos - server_params, hash);
|
||||||
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 (hlen < 0) {
|
||||||
if (ctx == NULL) {
|
|
||||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
TLS_ALERT_INTERNAL_ERROR);
|
TLS_ALERT_INTERNAL_ERROR);
|
||||||
return -1;
|
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
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_TLSV12 */
|
|
||||||
|
|
||||||
wpa_hexdump(MSG_MSGDUMP,
|
wpa_hexdump(MSG_MSGDUMP, "TLS: ServerKeyExchange signed_params hash",
|
||||||
"TLSv1: ServerKeyExchange signed_params hash",
|
|
||||||
hash, hlen);
|
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:
|
* RFC 2246, 4.7:
|
||||||
* In digital signing, one-way hash functions are used as input
|
* In digital signing, one-way hash functions are used as input
|
||||||
|
|
Loading…
Reference in a new issue