]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
TLS: Share a helper function for verifying Signature
authorJouni Malinen <j@w1.fi>
Sun, 9 Mar 2014 15:11:58 +0000 (17:11 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 9 Mar 2014 15:11:58 +0000 (17:11 +0200)
This same design is used in both the server and the client roles in the
internal TLS implementation. Instead of duplicated implementation, use a
helper function.

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_read.c

index 7b79da36dfe63670f2253a67cb9b6f5d2048a953..475a6e90334e38ba951ecc7a5838b1652aeb9dbe 100644 (file)
@@ -414,6 +414,7 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
                                        tls_key_exchange key_exchange)
 {
        const u8 *pos, *end, *server_params, *server_params_end;
+       u8 alert;
 
        tlsv1_client_free_dh(conn);
 
@@ -470,10 +471,8 @@ 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], *sbuf;
-               size_t buflen;
+               u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
                int hlen;
-               u16 slen;
 
                if (conn->rl.tls_version == TLS_VERSION_1_2) {
 #ifdef CONFIG_TLSV12
@@ -516,72 +515,11 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
                wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerKeyExchange hash",
                            hash, hlen);
 
-               if (end - pos < 2)
+               if (tls_verify_signature(conn->rl.tls_version,
+                                        conn->server_rsa_key,
+                                        hash, hlen, pos, end - pos,
+                                        &alert) < 0)
                        goto fail;
-               slen = WPA_GET_BE16(pos);
-               pos += 2;
-               if (end - pos < slen)
-                       goto fail;
-
-               wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos);
-               if (conn->server_rsa_key == NULL) {
-                       wpa_printf(MSG_DEBUG, "TLSv1: No server public key to verify signature");
-                       goto fail;
-               }
-
-               buflen = end - pos;
-               sbuf = os_malloc(end - pos);
-               if (crypto_public_key_decrypt_pkcs1(conn->server_rsa_key,
-                                                   pos, end - pos, sbuf,
-                                                   &buflen) < 0) {
-                       wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature");
-                       os_free(sbuf);
-                       goto fail;
-               }
-
-               wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature",
-                               sbuf, buflen);
-
-#ifdef CONFIG_TLSV12
-               if (conn->rl.tls_version >= TLS_VERSION_1_2) {
-                       /*
-                        * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5
-                        *
-                        * DigestInfo ::= SEQUENCE {
-                        *   digestAlgorithm DigestAlgorithm,
-                        *   digest OCTET STRING
-                        * }
-                        *
-                        * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11}
-                        *
-                        * DER encoded DigestInfo for SHA256 per RFC 3447:
-                        * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00
-                        * 04 20 || H
-                        */
-                       if (buflen >= 19 + 32 &&
-                           os_memcmp(sbuf,
-                                     "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01"
-                                     "\x65\x03\x04\x02\x01\x05\x00\x04\x20",
-                                     19) == 0) {
-                               wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = SHA-256");
-                               os_memmove(sbuf, sbuf + 19, buflen - 19);
-                               buflen -= 19;
-                       } else {
-                               wpa_printf(MSG_DEBUG, "TLSv1.2: Unrecognized DigestInfo");
-                               os_free(sbuf);
-                               goto fail;
-                       }
-               }
-#endif /* CONFIG_TLSV12 */
-
-               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;
-               }
-
-               os_free(sbuf);
        }
 
        return 0;
index dd67d28e01e151231e2091f5b0d1904e5740f825..8a4645bf2b2d1779e04752b554289332f3b08cc0 100644 (file)
@@ -396,3 +396,99 @@ int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
        hpos += hlen;
        return hpos - hash;
 }
+
+
+int tls_verify_signature(u16 tls_version, struct crypto_public_key *pk,
+                        const u8 *data, size_t data_len,
+                        const u8 *pos, size_t len, u8 *alert)
+{
+       u8 *buf;
+       const u8 *end = pos + len;
+       const u8 *decrypted;
+       u16 slen;
+       size_t buflen;
+
+       if (end - pos < 2) {
+               *alert = TLS_ALERT_DECODE_ERROR;
+               return -1;
+       }
+       slen = WPA_GET_BE16(pos);
+       pos += 2;
+       if (end - pos < slen) {
+               *alert = TLS_ALERT_DECODE_ERROR;
+               return -1;
+       }
+       if (end - pos > slen) {
+               wpa_hexdump(MSG_MSGDUMP, "Additional data after Signature",
+                           pos + slen, end - pos - slen);
+               end = pos + slen;
+       }
+
+       wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos);
+       if (pk == NULL) {
+               wpa_printf(MSG_DEBUG, "TLSv1: No public key to verify signature");
+               *alert = TLS_ALERT_INTERNAL_ERROR;
+               return -1;
+       }
+
+       buflen = end - pos;
+       buf = os_malloc(end - pos);
+       if (buf == NULL) {
+               *alert = TLS_ALERT_INTERNAL_ERROR;
+               return -1;
+       }
+       if (crypto_public_key_decrypt_pkcs1(pk, pos, end - pos, buf, &buflen) <
+           0) {
+               wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature");
+               os_free(buf);
+               *alert = TLS_ALERT_DECRYPT_ERROR;
+               return -1;
+       }
+       decrypted = buf;
+
+       wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature",
+                       decrypted, buflen);
+
+#ifdef CONFIG_TLSV12
+       if (tls_version >= TLS_VERSION_1_2) {
+               /*
+                * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5
+                *
+                * DigestInfo ::= SEQUENCE {
+                *   digestAlgorithm DigestAlgorithm,
+                *   digest OCTET STRING
+                * }
+                *
+                * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11}
+                *
+                * DER encoded DigestInfo for SHA256 per RFC 3447:
+                * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 ||
+                * H
+                */
+               if (buflen >= 19 + 32 &&
+                   os_memcmp(buf, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01"
+                             "\x65\x03\x04\x02\x01\x05\x00\x04\x20", 19) == 0)
+               {
+                       wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = SHA-256");
+                       decrypted = buf + 19;
+                       buflen -= 19;
+               } else {
+                       wpa_printf(MSG_DEBUG, "TLSv1.2: Unrecognized DigestInfo");
+                       os_free(buf);
+                       *alert = TLS_ALERT_DECRYPT_ERROR;
+                       return -1;
+               }
+       }
+#endif /* CONFIG_TLSV12 */
+
+       if (buflen != data_len || os_memcmp(decrypted, data, data_len) != 0) {
+               wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in CertificateVerify - did not match calculated hash");
+               os_free(buf);
+               *alert = TLS_ALERT_DECRYPT_ERROR;
+               return -1;
+       }
+
+       os_free(buf);
+
+       return 0;
+}
index 4251d393643e807c681a85b7a5389fb59af8bbfa..26e68af166069c6fde1e1217eb65c629430de9c5 100644 (file)
@@ -265,5 +265,8 @@ 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);
+int tls_verify_signature(u16 tls_version, struct crypto_public_key *pk,
+                        const u8 *data, size_t data_len,
+                        const u8 *pos, size_t len, u8 *alert);
 
 #endif /* TLSV1_COMMON_H */
index 137fd3abddc0e8e56521ed50c24245c1c2b37801..a5b732850e91d7257a9645ac83477bd5d6fff713 100644 (file)
@@ -769,10 +769,10 @@ static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct,
        const u8 *pos, *end;
        size_t left, len;
        u8 type;
-       size_t hlen, buflen;
-       u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos, *buf;
+       size_t hlen;
+       u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos;
        enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
-       u16 slen;
+       u8 alert;
 
        if (ct == TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
                if (conn->verify_peer) {
@@ -917,90 +917,12 @@ static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct,
 
        wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen);
 
-       if (end - pos < 2) {
-               tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
-                                  TLS_ALERT_DECODE_ERROR);
-               return -1;
-       }
-       slen = WPA_GET_BE16(pos);
-       pos += 2;
-       if (end - pos < slen) {
-               tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
-                                  TLS_ALERT_DECODE_ERROR);
-               return -1;
-       }
-
-       wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos);
-       if (conn->client_rsa_key == NULL) {
-               wpa_printf(MSG_DEBUG, "TLSv1: No client public key to verify "
-                          "signature");
-               tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
-                                  TLS_ALERT_INTERNAL_ERROR);
-               return -1;
-       }
-
-       buflen = end - pos;
-       buf = os_malloc(end - pos);
-       if (crypto_public_key_decrypt_pkcs1(conn->client_rsa_key,
-                                           pos, end - pos, buf, &buflen) < 0)
-       {
-               wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature");
-               os_free(buf);
-               tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
-                                  TLS_ALERT_DECRYPT_ERROR);
+       if (tls_verify_signature(conn->rl.tls_version, conn->client_rsa_key,
+                                hash, hlen, pos, end - pos, &alert) < 0) {
+               tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
                return -1;
        }
 
-       wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature",
-                       buf, buflen);
-
-#ifdef CONFIG_TLSV12
-       if (conn->rl.tls_version >= TLS_VERSION_1_2) {
-               /*
-                * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5
-                *
-                * DigestInfo ::= SEQUENCE {
-                *   digestAlgorithm DigestAlgorithm,
-                *   digest OCTET STRING
-                * }
-                *
-                * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11}
-                *
-                * DER encoded DigestInfo for SHA256 per RFC 3447:
-                * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 ||
-                * H
-                */
-               if (buflen >= 19 + 32 &&
-                   os_memcmp(buf, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01"
-                             "\x65\x03\x04\x02\x01\x05\x00\x04\x20", 19) == 0)
-               {
-                       wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = "
-                                  "SHA-256");
-                       os_memmove(buf, buf + 19, buflen - 19);
-                       buflen -= 19;
-               } else {
-                       wpa_printf(MSG_DEBUG, "TLSv1.2: Unrecognized "
-                                  "DigestInfo");
-                       os_free(buf);
-                       tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
-                                          TLS_ALERT_DECRYPT_ERROR);
-                       return -1;
-               }
-       }
-#endif /* CONFIG_TLSV12 */
-
-       if (buflen != hlen || os_memcmp(buf, hash, buflen) != 0) {
-               wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in "
-                          "CertificateVerify - did not match with calculated "
-                          "hash");
-               os_free(buf);
-               tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
-                                  TLS_ALERT_DECRYPT_ERROR);
-               return -1;
-       }
-
-       os_free(buf);
-
        *in_len = end - in_data;
 
        conn->state = CHANGE_CIPHER_SPEC;