aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2014-03-09 15:11:58 (GMT)
committerJouni Malinen <j@w1.fi>2014-03-09 15:11:58 (GMT)
commit129b9b991ad9879768bfe7c8c7b4f61bc6807079 (patch)
treea837dc06db297a1b3ee2c1da440a551df1363b0b
parent6531963584758971dfcebd663ea601d43adf9dbe (diff)
downloadhostap-129b9b991ad9879768bfe7c8c7b4f61bc6807079.zip
hostap-129b9b991ad9879768bfe7c8c7b4f61bc6807079.tar.gz
hostap-129b9b991ad9879768bfe7c8c7b4f61bc6807079.tar.bz2
TLS: Share a helper function for verifying Signature
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>
-rw-r--r--src/tls/tlsv1_client_read.c74
-rw-r--r--src/tls/tlsv1_common.c96
-rw-r--r--src/tls/tlsv1_common.h3
-rw-r--r--src/tls/tlsv1_server_read.c90
4 files changed, 111 insertions, 152 deletions
diff --git a/src/tls/tlsv1_client_read.c b/src/tls/tlsv1_client_read.c
index 7b79da3..475a6e9 100644
--- a/src/tls/tlsv1_client_read.c
+++ b/src/tls/tlsv1_client_read.c
@@ -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;
diff --git a/src/tls/tlsv1_common.c b/src/tls/tlsv1_common.c
index dd67d28..8a4645b 100644
--- a/src/tls/tlsv1_common.c
+++ b/src/tls/tlsv1_common.c
@@ -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;
+}
diff --git a/src/tls/tlsv1_common.h b/src/tls/tlsv1_common.h
index 4251d39..26e68af 100644
--- a/src/tls/tlsv1_common.h
+++ b/src/tls/tlsv1_common.h
@@ -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 */
diff --git a/src/tls/tlsv1_server_read.c b/src/tls/tlsv1_server_read.c
index 137fd3a..a5b7328 100644
--- a/src/tls/tlsv1_server_read.c
+++ b/src/tls/tlsv1_server_read.c
@@ -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;