aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2014-03-09 14:26:27 (GMT)
committerJouni Malinen <j@w1.fi>2014-03-09 14:26:27 (GMT)
commit6531963584758971dfcebd663ea601d43adf9dbe (patch)
tree665e3d0dd613a58dc963c954a832dbabf381cb89
parent65074a2a7ca5c9d0d1fc8a72da2176ac0e81a246 (diff)
downloadhostap-6531963584758971dfcebd663ea601d43adf9dbe.zip
hostap-6531963584758971dfcebd663ea601d43adf9dbe.tar.gz
hostap-6531963584758971dfcebd663ea601d43adf9dbe.tar.bz2
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>
-rw-r--r--src/tls/tlsv1_client_read.c69
-rw-r--r--src/tls/tlsv1_common.c65
-rw-r--r--src/tls/tlsv1_common.h10
-rw-r--r--src/tls/tlsv1_server_write.c130
4 files changed, 131 insertions, 143 deletions
diff --git a/src/tls/tlsv1_client_read.c b/src/tls/tlsv1_client_read.c
index 8313efb..7b79da3 100644
--- a/src/tls/tlsv1_client_read.c
+++ b/src/tls/tlsv1_client_read.c
@@ -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;
- } 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;
- }
- ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
- if (ctx == NULL)
+ 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;
- 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 */
+ } else {
+ 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);
+ }
+ 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;
diff --git a/src/tls/tlsv1_common.c b/src/tls/tlsv1_common.c
index d05df85..dd67d28 100644
--- a/src/tls/tlsv1_common.c
+++ b/src/tls/tlsv1_common.c
@@ -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;
+}
diff --git a/src/tls/tlsv1_common.h b/src/tls/tlsv1_common.h
index f28c0cd..4251d39 100644
--- a/src/tls/tlsv1_common.h
+++ b/src/tls/tlsv1_common.h
@@ -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 */
diff --git a/src/tls/tlsv1_server_write.c b/src/tls/tlsv1_server_write.c
index 39dbad4..b4eadca 100644
--- a/src/tls/tlsv1_server_write.c
+++ b/src/tls/tlsv1_server_write.c
@@ -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 {
+
+#else /* CONFIG_TLSV12 */
+ tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ return -1;
#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;
- }
+ } else {
+ hlen = tls_key_x_server_params_hash(
+ conn->rl.tls_version, conn->client_random,
+ conn->server_random, server_params,
+ pos - server_params, hash);
+ }
- 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
+ if (hlen < 0) {
+ tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ return -1;
}
-#endif /* CONFIG_TLSV12 */
- wpa_hexdump(MSG_MSGDUMP,
- "TLSv1: ServerKeyExchange signed_params hash",
+ 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