]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
TLS: Use a helper function for calculating ServerKeyExchange hash
authorJouni Malinen <j@w1.fi>
Sun, 9 Mar 2014 14:26:27 +0000 (16:26 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 9 Mar 2014 14:26:27 +0000 (16:26 +0200)
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>
src/tls/tlsv1_client_read.c
src/tls/tlsv1_common.c
src/tls/tlsv1_common.h
src/tls/tlsv1_server_write.c

index 8313efbe2d28d6dd17fa1d5eca3dcd27ad8a0c1c..7b79da36dfe63670f2253a67cb9b6f5d2048a953 100644 (file)
@@ -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;
index d05df856d8c8129201c2295cb0a02de66c0d187b..dd67d28e01e151231e2091f5b0d1904e5740f825 100644 (file)
@@ -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;
+}
index f28c0cdc4790690cd961a0f7778eef6392f2a8b1..4251d393643e807c681a85b7a5389fb59af8bbfa 100644 (file)
@@ -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 */
index 39dbad4fe21082af02c4f23e7f3387ef4b9918df..b4eadca27847b65693789f5a45a9bdbb36b6e90f 100644 (file)
@@ -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