]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
TLS: Add TLS v1.2 signature algorithm support for SHA384 and SHA512
authorJouni Malinen <j@w1.fi>
Sun, 29 Nov 2015 16:16:07 +0000 (18:16 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 29 Nov 2015 16:21:08 +0000 (18:21 +0200)
This extends the internal TLS client implementation to support signature
algorithms SHA384 and SHA512 in addition to the previously supported
SHA256.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/tls/tlsv1_client_read.c
src/tls/tlsv1_client_write.c
src/tls/tlsv1_common.c
src/tls/tlsv1_common.h
src/tls/tlsv1_server_write.c

index 48120b683030529ac5e89592235717ffd655cb1c..294ae008194ea2d917f143080e9491a5f4b33ac1 100644 (file)
@@ -529,7 +529,7 @@ 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];
+               u8 hash[64];
                int hlen;
 
                if (conn->rl.tls_version == TLS_VERSION_1_2) {
@@ -546,18 +546,21 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
                         */
                        if (end - pos < 2)
                                goto fail;
-                       if (pos[0] != TLS_HASH_ALG_SHA256 ||
+                       if ((pos[0] != TLS_HASH_ALG_SHA256 &&
+                            pos[0] != TLS_HASH_ALG_SHA384 &&
+                            pos[0] != TLS_HASH_ALG_SHA512) ||
                            pos[1] != TLS_SIGN_ALG_RSA) {
                                wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/signature(%u) algorithm",
                                           pos[0], pos[1]);
                                goto fail;
                        }
-                       pos += 2;
 
                        hlen = tlsv12_key_x_server_params_hash(
-                               conn->rl.tls_version, conn->client_random,
+                               conn->rl.tls_version, pos[0],
+                               conn->client_random,
                                conn->server_random, server_params,
                                server_params_end - server_params, hash);
+                       pos += 2;
 #else /* CONFIG_TLSV12 */
                        goto fail;
 #endif /* CONFIG_TLSV12 */
index e02437172a16d56b15fe8551fae03f3703508f5c..6f1e0522b36691e4051a159c377e642bdfeb6a7a 100644 (file)
@@ -116,12 +116,16 @@ u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len)
                WPA_PUT_BE16(pos, TLS_EXT_SIGNATURE_ALGORITHMS);
                pos += 2;
                /* opaque extension_data<0..2^16-1> length */
-               WPA_PUT_BE16(pos, 4);
+               WPA_PUT_BE16(pos, 8);
                pos += 2;
                /* supported_signature_algorithms<2..2^16-2> length */
-               WPA_PUT_BE16(pos, 2);
+               WPA_PUT_BE16(pos, 6);
                pos += 2;
                /* supported_signature_algorithms */
+               *pos++ = TLS_HASH_ALG_SHA512;
+               *pos++ = TLS_SIGN_ALG_RSA;
+               *pos++ = TLS_HASH_ALG_SHA384;
+               *pos++ = TLS_SIGN_ALG_RSA;
                *pos++ = TLS_HASH_ALG_SHA256;
                *pos++ = TLS_SIGN_ALG_RSA;
        }
index dabc12a12978891a204dd5e2e435e343720bee73..6b28417e499c70680d7b64312c955ec12b202090 100644 (file)
@@ -335,7 +335,7 @@ int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label,
 
 
 #ifdef CONFIG_TLSV12
-int tlsv12_key_x_server_params_hash(u16 tls_version,
+int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_alg,
                                    const u8 *client_random,
                                    const u8 *server_random,
                                    const u8 *server_params,
@@ -343,14 +343,30 @@ int tlsv12_key_x_server_params_hash(u16 tls_version,
 {
        size_t hlen;
        struct crypto_hash *ctx;
-
-       ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, 0);
+       enum crypto_hash_alg alg;
+
+       switch (hash_alg) {
+       case TLS_HASH_ALG_SHA256:
+               alg = CRYPTO_HASH_ALG_SHA256;
+               hlen = SHA256_MAC_LEN;
+               break;
+       case TLS_HASH_ALG_SHA384:
+               alg = CRYPTO_HASH_ALG_SHA384;
+               hlen = 48;
+               break;
+       case TLS_HASH_ALG_SHA512:
+               alg = CRYPTO_HASH_ALG_SHA512;
+               hlen = 64;
+               break;
+       default:
+               return -1;
+       }
+       ctx = crypto_hash_init(alg, 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;
 
@@ -469,6 +485,21 @@ int tls_verify_signature(u16 tls_version, struct crypto_public_key *pk,
                        wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = SHA-256");
                        decrypted = buf + 19;
                        buflen -= 19;
+               } else if (buflen >= 19 + 48 &&
+                   os_memcmp(buf, "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01"
+                             "\x65\x03\x04\x02\x02\x05\x00\x04\x30", 19) == 0)
+               {
+                       wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = SHA-384");
+                       decrypted = buf + 19;
+                       buflen -= 19;
+               } else if (buflen >= 19 + 64 &&
+                   os_memcmp(buf, "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01"
+                             "\x65\x03\x04\x02\x03\x05\x00\x04\x40", 19) == 0)
+               {
+                       wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = SHA-512");
+                       decrypted = buf + 19;
+                       buflen -= 19;
+
                } else {
                        wpa_printf(MSG_DEBUG, "TLSv1.2: Unrecognized DigestInfo");
                        os_free(buf);
index e2a5d4ce239b0fc3a7d32b4130ec6a3e1dc2d731..7a252feec8aec04ea88040bd399eeb0b68f1df0b 100644 (file)
@@ -258,7 +258,8 @@ 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,
+int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_Alg,
+                                   const u8 *client_random,
                                    const u8 *server_random,
                                    const u8 *server_params,
                                    size_t server_params_len, u8 *hash);
index 65cda3c24c5400e49fa435e921e5b84ded24c4be..e7c5e2254e6d2c0e04df2573b4e80ff6a046498e 100644 (file)
@@ -448,7 +448,8 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
                if (conn->rl.tls_version >= TLS_VERSION_1_2) {
 #ifdef CONFIG_TLSV12
                        hlen = tlsv12_key_x_server_params_hash(
-                               conn->rl.tls_version, conn->client_random,
+                               conn->rl.tls_version, TLS_HASH_ALG_SHA256,
+                               conn->client_random,
                                conn->server_random, server_params,
                                pos - server_params, hash + 19);