mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2025-01-30 08:44:03 -05:00
TLS: Add TLS v1.2 style CertificateVerify functionality
Add support for generating and verifying RFC 3447 RSASSA-PKCS1-v1_5 style DigestInfo for TLS v1.2 CertificateVerify. For now, this is hardcoded to only support SHA256-based digest. Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
949b2e1f61
commit
f0b1c5f7b3
@ -437,7 +437,7 @@ static int tls_write_client_certificate_verify(struct tlsv1_client *conn,
|
|||||||
{
|
{
|
||||||
u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start;
|
u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start;
|
||||||
size_t rlen, hlen, clen;
|
size_t rlen, hlen, clen;
|
||||||
u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos;
|
u8 hash[100], *hpos;
|
||||||
enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
|
enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
|
||||||
|
|
||||||
pos = *msgpos;
|
pos = *msgpos;
|
||||||
@ -477,6 +477,40 @@ static int tls_write_client_certificate_verify(struct tlsv1_client *conn,
|
|||||||
|
|
||||||
hpos = hash;
|
hpos = hash;
|
||||||
|
|
||||||
|
#ifdef CONFIG_TLSV12
|
||||||
|
if (conn->rl.tls_version == TLS_VERSION_1_2) {
|
||||||
|
hlen = SHA256_MAC_LEN;
|
||||||
|
if (conn->verify.sha256_cert == NULL ||
|
||||||
|
crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) <
|
||||||
|
0) {
|
||||||
|
conn->verify.sha256_cert = NULL;
|
||||||
|
tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
|
TLS_ALERT_INTERNAL_ERROR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
conn->verify.sha256_cert = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
os_memmove(hash + 19, hash, hlen);
|
||||||
|
hlen += 19;
|
||||||
|
os_memcpy(hash, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65"
|
||||||
|
"\x03\x04\x02\x01\x05\x00\x04\x20", 19);
|
||||||
|
} else {
|
||||||
|
#endif /* CONFIG_TLSV12 */
|
||||||
|
|
||||||
if (alg == SIGN_ALG_RSA) {
|
if (alg == SIGN_ALG_RSA) {
|
||||||
hlen = MD5_MAC_LEN;
|
hlen = MD5_MAC_LEN;
|
||||||
if (conn->verify.md5_cert == NULL ||
|
if (conn->verify.md5_cert == NULL ||
|
||||||
@ -507,8 +541,29 @@ static int tls_write_client_certificate_verify(struct tlsv1_client *conn,
|
|||||||
if (alg == SIGN_ALG_RSA)
|
if (alg == SIGN_ALG_RSA)
|
||||||
hlen += MD5_MAC_LEN;
|
hlen += MD5_MAC_LEN;
|
||||||
|
|
||||||
|
#ifdef CONFIG_TLSV12
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TLSV12 */
|
||||||
|
|
||||||
wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen);
|
wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify 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;
|
||||||
|
*/
|
||||||
|
*pos++ = TLS_HASH_ALG_SHA256;
|
||||||
|
*pos++ = TLS_SIGN_ALG_RSA;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TLSV12 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RFC 2246, 4.7:
|
* RFC 2246, 4.7:
|
||||||
* In digital signing, one-way hash functions are used as input for a
|
* In digital signing, one-way hash functions are used as input for a
|
||||||
|
@ -97,6 +97,25 @@ enum {
|
|||||||
/* CompressionMethod */
|
/* CompressionMethod */
|
||||||
#define TLS_COMPRESSION_NULL 0
|
#define TLS_COMPRESSION_NULL 0
|
||||||
|
|
||||||
|
/* HashAlgorithm */
|
||||||
|
enum {
|
||||||
|
TLS_HASH_ALG_NONE = 0,
|
||||||
|
TLS_HASH_ALG_MD5 = 1,
|
||||||
|
TLS_HASH_ALG_SHA1 = 2,
|
||||||
|
TLS_HASH_ALG_SHA224 = 3,
|
||||||
|
TLS_HASH_ALG_SHA256 = 4,
|
||||||
|
TLS_HASH_ALG_SHA384 = 5,
|
||||||
|
TLS_HASH_ALG_SHA512 = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SignatureAlgorithm */
|
||||||
|
enum {
|
||||||
|
TLS_SIGN_ALG_ANONYMOUS = 0,
|
||||||
|
TLS_SIGN_ALG_RSA = 1,
|
||||||
|
TLS_SIGN_ALG_DSA = 2,
|
||||||
|
TLS_SIGN_ALG_ECDSA = 3,
|
||||||
|
};
|
||||||
|
|
||||||
/* AlertLevel */
|
/* AlertLevel */
|
||||||
#define TLS_ALERT_LEVEL_WARNING 1
|
#define TLS_ALERT_LEVEL_WARNING 1
|
||||||
#define TLS_ALERT_LEVEL_FATAL 2
|
#define TLS_ALERT_LEVEL_FATAL 2
|
||||||
|
@ -842,6 +842,47 @@ static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct,
|
|||||||
|
|
||||||
hpos = hash;
|
hpos = hash;
|
||||||
|
|
||||||
|
#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 (end - pos < 2) {
|
||||||
|
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
|
TLS_ALERT_DECODE_ERROR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (pos[0] != TLS_HASH_ALG_SHA256 ||
|
||||||
|
pos[1] != TLS_SIGN_ALG_RSA) {
|
||||||
|
wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/"
|
||||||
|
"signature(%u) algorithm",
|
||||||
|
pos[0], pos[1]);
|
||||||
|
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
|
TLS_ALERT_INTERNAL_ERROR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos += 2;
|
||||||
|
|
||||||
|
hlen = SHA256_MAC_LEN;
|
||||||
|
if (conn->verify.sha256_cert == NULL ||
|
||||||
|
crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) <
|
||||||
|
0) {
|
||||||
|
conn->verify.sha256_cert = NULL;
|
||||||
|
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
|
TLS_ALERT_INTERNAL_ERROR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
conn->verify.sha256_cert = NULL;
|
||||||
|
} else {
|
||||||
|
#endif /* CONFIG_TLSV12 */
|
||||||
|
|
||||||
if (alg == SIGN_ALG_RSA) {
|
if (alg == SIGN_ALG_RSA) {
|
||||||
hlen = MD5_MAC_LEN;
|
hlen = MD5_MAC_LEN;
|
||||||
if (conn->verify.md5_cert == NULL ||
|
if (conn->verify.md5_cert == NULL ||
|
||||||
@ -872,6 +913,10 @@ static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct,
|
|||||||
if (alg == SIGN_ALG_RSA)
|
if (alg == SIGN_ALG_RSA)
|
||||||
hlen += MD5_MAC_LEN;
|
hlen += MD5_MAC_LEN;
|
||||||
|
|
||||||
|
#ifdef CONFIG_TLSV12
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TLSV12 */
|
||||||
|
|
||||||
wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen);
|
wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen);
|
||||||
|
|
||||||
if (end - pos < 2) {
|
if (end - pos < 2) {
|
||||||
@ -911,6 +956,41 @@ static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct,
|
|||||||
wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature",
|
wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature",
|
||||||
buf, buflen);
|
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) {
|
if (buflen != hlen || os_memcmp(buf, hash, buflen) != 0) {
|
||||||
wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in "
|
wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in "
|
||||||
"CertificateVerify - did not match with calculated "
|
"CertificateVerify - did not match with calculated "
|
||||||
|
Loading…
Reference in New Issue
Block a user