aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls/tlsv1_common.c
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 /src/tls/tlsv1_common.c
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>
Diffstat (limited to 'src/tls/tlsv1_common.c')
-rw-r--r--src/tls/tlsv1_common.c96
1 files changed, 96 insertions, 0 deletions
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;
+}