xref: /freebsd/contrib/wpa/src/tls/tlsv1_common.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
139beb93cSSam Leffler /*
239beb93cSSam Leffler  * TLSv1 common routines
35b9c547cSRui Paulo  * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
739beb93cSSam Leffler  */
839beb93cSSam Leffler 
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler 
1139beb93cSSam Leffler #include "common.h"
125b9c547cSRui Paulo #include "crypto/md5.h"
13f05cddf9SRui Paulo #include "crypto/sha1.h"
14f05cddf9SRui Paulo #include "crypto/sha256.h"
1539beb93cSSam Leffler #include "x509v3.h"
1639beb93cSSam Leffler #include "tlsv1_common.h"
1739beb93cSSam Leffler 
1839beb93cSSam Leffler 
1939beb93cSSam Leffler /*
2039beb93cSSam Leffler  * TODO:
2139beb93cSSam Leffler  * RFC 2246 Section 9: Mandatory to implement TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
2239beb93cSSam Leffler  * Add support for commonly used cipher suites; don't bother with exportable
2339beb93cSSam Leffler  * suites.
2439beb93cSSam Leffler  */
2539beb93cSSam Leffler 
2639beb93cSSam Leffler static const struct tls_cipher_suite tls_cipher_suites[] = {
2739beb93cSSam Leffler 	{ TLS_NULL_WITH_NULL_NULL, TLS_KEY_X_NULL, TLS_CIPHER_NULL,
2839beb93cSSam Leffler 	  TLS_HASH_NULL },
2939beb93cSSam Leffler 	{ TLS_RSA_WITH_RC4_128_MD5, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128,
3039beb93cSSam Leffler 	  TLS_HASH_MD5 },
3139beb93cSSam Leffler 	{ TLS_RSA_WITH_RC4_128_SHA, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128,
3239beb93cSSam Leffler 	  TLS_HASH_SHA },
3339beb93cSSam Leffler 	{ TLS_RSA_WITH_DES_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_DES_CBC,
3439beb93cSSam Leffler 	  TLS_HASH_SHA },
3539beb93cSSam Leffler 	{ TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_RSA,
3639beb93cSSam Leffler 	  TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA },
375b9c547cSRui Paulo 	{ TLS_DHE_RSA_WITH_DES_CBC_SHA, TLS_KEY_X_DHE_RSA, TLS_CIPHER_DES_CBC,
385b9c547cSRui Paulo 	  TLS_HASH_SHA},
395b9c547cSRui Paulo 	{ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_DHE_RSA,
405b9c547cSRui Paulo 	  TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA },
4139beb93cSSam Leffler  	{ TLS_DH_anon_WITH_RC4_128_MD5, TLS_KEY_X_DH_anon,
4239beb93cSSam Leffler 	  TLS_CIPHER_RC4_128, TLS_HASH_MD5 },
4339beb93cSSam Leffler  	{ TLS_DH_anon_WITH_DES_CBC_SHA, TLS_KEY_X_DH_anon,
4439beb93cSSam Leffler 	  TLS_CIPHER_DES_CBC, TLS_HASH_SHA },
4539beb93cSSam Leffler  	{ TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_DH_anon,
4639beb93cSSam Leffler 	  TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA },
4739beb93cSSam Leffler 	{ TLS_RSA_WITH_AES_128_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_128_CBC,
4839beb93cSSam Leffler 	  TLS_HASH_SHA },
495b9c547cSRui Paulo 	{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_KEY_X_DHE_RSA,
505b9c547cSRui Paulo 	  TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA },
5139beb93cSSam Leffler 	{ TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_KEY_X_DH_anon,
5239beb93cSSam Leffler 	  TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA },
5339beb93cSSam Leffler 	{ TLS_RSA_WITH_AES_256_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_256_CBC,
5439beb93cSSam Leffler 	  TLS_HASH_SHA },
555b9c547cSRui Paulo 	{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_KEY_X_DHE_RSA,
565b9c547cSRui Paulo 	  TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA },
5739beb93cSSam Leffler 	{ TLS_DH_anon_WITH_AES_256_CBC_SHA, TLS_KEY_X_DH_anon,
58f05cddf9SRui Paulo 	  TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA },
59f05cddf9SRui Paulo 	{ TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_KEY_X_RSA,
60f05cddf9SRui Paulo 	  TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA256 },
61f05cddf9SRui Paulo 	{ TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_KEY_X_RSA,
62f05cddf9SRui Paulo 	  TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA256 },
635b9c547cSRui Paulo 	{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_KEY_X_DHE_RSA,
645b9c547cSRui Paulo 	  TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA256 },
655b9c547cSRui Paulo 	{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_KEY_X_DHE_RSA,
665b9c547cSRui Paulo 	  TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA256 },
67f05cddf9SRui Paulo 	{ TLS_DH_anon_WITH_AES_128_CBC_SHA256, TLS_KEY_X_DH_anon,
68f05cddf9SRui Paulo 	  TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA256 },
69f05cddf9SRui Paulo 	{ TLS_DH_anon_WITH_AES_256_CBC_SHA256, TLS_KEY_X_DH_anon,
70f05cddf9SRui Paulo 	  TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA256 }
7139beb93cSSam Leffler };
7239beb93cSSam Leffler 
735b9c547cSRui Paulo #define NUM_TLS_CIPHER_SUITES ARRAY_SIZE(tls_cipher_suites)
7439beb93cSSam Leffler 
7539beb93cSSam Leffler 
7639beb93cSSam Leffler static const struct tls_cipher_data tls_ciphers[] = {
7739beb93cSSam Leffler 	{ TLS_CIPHER_NULL,         TLS_CIPHER_STREAM,  0,  0,  0,
7839beb93cSSam Leffler 	  CRYPTO_CIPHER_NULL },
7939beb93cSSam Leffler 	{ TLS_CIPHER_IDEA_CBC,     TLS_CIPHER_BLOCK,  16, 16,  8,
8039beb93cSSam Leffler 	  CRYPTO_CIPHER_NULL },
8139beb93cSSam Leffler 	{ TLS_CIPHER_RC2_CBC_40,   TLS_CIPHER_BLOCK,   5, 16,  0,
8239beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_RC2 },
8339beb93cSSam Leffler 	{ TLS_CIPHER_RC4_40,       TLS_CIPHER_STREAM,  5, 16,  0,
8439beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_RC4 },
8539beb93cSSam Leffler 	{ TLS_CIPHER_RC4_128,      TLS_CIPHER_STREAM, 16, 16,  0,
8639beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_RC4 },
8739beb93cSSam Leffler 	{ TLS_CIPHER_DES40_CBC,    TLS_CIPHER_BLOCK,   5,  8,  8,
8839beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_DES },
8939beb93cSSam Leffler 	{ TLS_CIPHER_DES_CBC,      TLS_CIPHER_BLOCK,   8,  8,  8,
9039beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_DES },
9139beb93cSSam Leffler 	{ TLS_CIPHER_3DES_EDE_CBC, TLS_CIPHER_BLOCK,  24, 24,  8,
9239beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_3DES },
9339beb93cSSam Leffler 	{ TLS_CIPHER_AES_128_CBC,  TLS_CIPHER_BLOCK,  16, 16, 16,
9439beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_AES },
9539beb93cSSam Leffler 	{ TLS_CIPHER_AES_256_CBC,  TLS_CIPHER_BLOCK,  32, 32, 16,
9639beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_AES }
9739beb93cSSam Leffler };
9839beb93cSSam Leffler 
995b9c547cSRui Paulo #define NUM_TLS_CIPHER_DATA ARRAY_SIZE(tls_ciphers)
10039beb93cSSam Leffler 
10139beb93cSSam Leffler 
10239beb93cSSam Leffler /**
10339beb93cSSam Leffler  * tls_get_cipher_suite - Get TLS cipher suite
10439beb93cSSam Leffler  * @suite: Cipher suite identifier
10539beb93cSSam Leffler  * Returns: Pointer to the cipher data or %NULL if not found
10639beb93cSSam Leffler  */
tls_get_cipher_suite(u16 suite)10739beb93cSSam Leffler const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite)
10839beb93cSSam Leffler {
10939beb93cSSam Leffler 	size_t i;
11039beb93cSSam Leffler 	for (i = 0; i < NUM_TLS_CIPHER_SUITES; i++)
11139beb93cSSam Leffler 		if (tls_cipher_suites[i].suite == suite)
11239beb93cSSam Leffler 			return &tls_cipher_suites[i];
11339beb93cSSam Leffler 	return NULL;
11439beb93cSSam Leffler }
11539beb93cSSam Leffler 
11639beb93cSSam Leffler 
tls_get_cipher_data(tls_cipher cipher)11739beb93cSSam Leffler const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher)
11839beb93cSSam Leffler {
11939beb93cSSam Leffler 	size_t i;
12039beb93cSSam Leffler 	for (i = 0; i < NUM_TLS_CIPHER_DATA; i++)
12139beb93cSSam Leffler 		if (tls_ciphers[i].cipher == cipher)
12239beb93cSSam Leffler 			return &tls_ciphers[i];
12339beb93cSSam Leffler 	return NULL;
12439beb93cSSam Leffler }
12539beb93cSSam Leffler 
12639beb93cSSam Leffler 
tls_server_key_exchange_allowed(tls_cipher cipher)12739beb93cSSam Leffler int tls_server_key_exchange_allowed(tls_cipher cipher)
12839beb93cSSam Leffler {
12939beb93cSSam Leffler 	const struct tls_cipher_suite *suite;
13039beb93cSSam Leffler 
13139beb93cSSam Leffler 	/* RFC 2246, Section 7.4.3 */
13239beb93cSSam Leffler 	suite = tls_get_cipher_suite(cipher);
13339beb93cSSam Leffler 	if (suite == NULL)
13439beb93cSSam Leffler 		return 0;
13539beb93cSSam Leffler 
13639beb93cSSam Leffler 	switch (suite->key_exchange) {
13739beb93cSSam Leffler 	case TLS_KEY_X_DHE_DSS:
13839beb93cSSam Leffler 	case TLS_KEY_X_DHE_DSS_EXPORT:
13939beb93cSSam Leffler 	case TLS_KEY_X_DHE_RSA:
14039beb93cSSam Leffler 	case TLS_KEY_X_DHE_RSA_EXPORT:
14139beb93cSSam Leffler 	case TLS_KEY_X_DH_anon_EXPORT:
14239beb93cSSam Leffler 	case TLS_KEY_X_DH_anon:
14339beb93cSSam Leffler 		return 1;
14439beb93cSSam Leffler 	case TLS_KEY_X_RSA_EXPORT:
14539beb93cSSam Leffler 		return 1 /* FIX: public key len > 512 bits */;
14639beb93cSSam Leffler 	default:
14739beb93cSSam Leffler 		return 0;
14839beb93cSSam Leffler 	}
14939beb93cSSam Leffler }
15039beb93cSSam Leffler 
15139beb93cSSam Leffler 
15239beb93cSSam Leffler /**
15339beb93cSSam Leffler  * tls_parse_cert - Parse DER encoded X.509 certificate and get public key
15439beb93cSSam Leffler  * @buf: ASN.1 DER encoded certificate
15539beb93cSSam Leffler  * @len: Length of the buffer
15639beb93cSSam Leffler  * @pk: Buffer for returning the allocated public key
15739beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
15839beb93cSSam Leffler  *
15939beb93cSSam Leffler  * This functions parses an ASN.1 DER encoded X.509 certificate and retrieves
16039beb93cSSam Leffler  * the public key from it. The caller is responsible for freeing the public key
16139beb93cSSam Leffler  * by calling crypto_public_key_free().
16239beb93cSSam Leffler  */
tls_parse_cert(const u8 * buf,size_t len,struct crypto_public_key ** pk)16339beb93cSSam Leffler int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk)
16439beb93cSSam Leffler {
16539beb93cSSam Leffler 	struct x509_certificate *cert;
16639beb93cSSam Leffler 
16739beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: Parse ASN.1 DER certificate",
16839beb93cSSam Leffler 		    buf, len);
16939beb93cSSam Leffler 
17039beb93cSSam Leffler 	*pk = crypto_public_key_from_cert(buf, len);
17139beb93cSSam Leffler 	if (*pk)
17239beb93cSSam Leffler 		return 0;
17339beb93cSSam Leffler 
17439beb93cSSam Leffler 	cert = x509_certificate_parse(buf, len);
17539beb93cSSam Leffler 	if (cert == NULL) {
17639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse X.509 "
17739beb93cSSam Leffler 			   "certificate");
17839beb93cSSam Leffler 		return -1;
17939beb93cSSam Leffler 	}
18039beb93cSSam Leffler 
18139beb93cSSam Leffler 	/* TODO
18239beb93cSSam Leffler 	 * verify key usage (must allow encryption)
18339beb93cSSam Leffler 	 *
18439beb93cSSam Leffler 	 * All certificate profiles, key and cryptographic formats are
18539beb93cSSam Leffler 	 * defined by the IETF PKIX working group [PKIX]. When a key
18639beb93cSSam Leffler 	 * usage extension is present, the digitalSignature bit must be
18739beb93cSSam Leffler 	 * set for the key to be eligible for signing, as described
18839beb93cSSam Leffler 	 * above, and the keyEncipherment bit must be present to allow
18939beb93cSSam Leffler 	 * encryption, as described above. The keyAgreement bit must be
19039beb93cSSam Leffler 	 * set on Diffie-Hellman certificates. (PKIX: RFC 3280)
19139beb93cSSam Leffler 	 */
19239beb93cSSam Leffler 
19339beb93cSSam Leffler 	*pk = crypto_public_key_import(cert->public_key, cert->public_key_len);
19439beb93cSSam Leffler 	x509_certificate_free(cert);
19539beb93cSSam Leffler 
19639beb93cSSam Leffler 	if (*pk == NULL) {
19739beb93cSSam Leffler 		wpa_printf(MSG_ERROR, "TLSv1: Failed to import "
19839beb93cSSam Leffler 			   "server public key");
19939beb93cSSam Leffler 		return -1;
20039beb93cSSam Leffler 	}
20139beb93cSSam Leffler 
20239beb93cSSam Leffler 	return 0;
20339beb93cSSam Leffler }
20439beb93cSSam Leffler 
20539beb93cSSam Leffler 
tls_verify_hash_init(struct tls_verify_hash * verify)20639beb93cSSam Leffler int tls_verify_hash_init(struct tls_verify_hash *verify)
20739beb93cSSam Leffler {
20839beb93cSSam Leffler 	tls_verify_hash_free(verify);
20939beb93cSSam Leffler 	verify->md5_client = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
21039beb93cSSam Leffler 	verify->md5_server = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
21139beb93cSSam Leffler 	verify->md5_cert = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
21239beb93cSSam Leffler 	verify->sha1_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
21339beb93cSSam Leffler 	verify->sha1_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
21439beb93cSSam Leffler 	verify->sha1_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
21539beb93cSSam Leffler 	if (verify->md5_client == NULL || verify->md5_server == NULL ||
21639beb93cSSam Leffler 	    verify->md5_cert == NULL || verify->sha1_client == NULL ||
21739beb93cSSam Leffler 	    verify->sha1_server == NULL || verify->sha1_cert == NULL) {
21839beb93cSSam Leffler 		tls_verify_hash_free(verify);
21939beb93cSSam Leffler 		return -1;
22039beb93cSSam Leffler 	}
221f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
222f05cddf9SRui Paulo 	verify->sha256_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL,
223f05cddf9SRui Paulo 						 0);
224f05cddf9SRui Paulo 	verify->sha256_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL,
225f05cddf9SRui Paulo 						 0);
226f05cddf9SRui Paulo 	verify->sha256_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL,
227f05cddf9SRui Paulo 					       0);
228f05cddf9SRui Paulo 	if (verify->sha256_client == NULL || verify->sha256_server == NULL ||
229f05cddf9SRui Paulo 	    verify->sha256_cert == NULL) {
230f05cddf9SRui Paulo 		tls_verify_hash_free(verify);
231f05cddf9SRui Paulo 		return -1;
232f05cddf9SRui Paulo 	}
233f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
23439beb93cSSam Leffler 	return 0;
23539beb93cSSam Leffler }
23639beb93cSSam Leffler 
23739beb93cSSam Leffler 
tls_verify_hash_add(struct tls_verify_hash * verify,const u8 * buf,size_t len)23839beb93cSSam Leffler void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf,
23939beb93cSSam Leffler 			 size_t len)
24039beb93cSSam Leffler {
24139beb93cSSam Leffler 	if (verify->md5_client && verify->sha1_client) {
24239beb93cSSam Leffler 		crypto_hash_update(verify->md5_client, buf, len);
24339beb93cSSam Leffler 		crypto_hash_update(verify->sha1_client, buf, len);
24439beb93cSSam Leffler 	}
24539beb93cSSam Leffler 	if (verify->md5_server && verify->sha1_server) {
24639beb93cSSam Leffler 		crypto_hash_update(verify->md5_server, buf, len);
24739beb93cSSam Leffler 		crypto_hash_update(verify->sha1_server, buf, len);
24839beb93cSSam Leffler 	}
24939beb93cSSam Leffler 	if (verify->md5_cert && verify->sha1_cert) {
25039beb93cSSam Leffler 		crypto_hash_update(verify->md5_cert, buf, len);
25139beb93cSSam Leffler 		crypto_hash_update(verify->sha1_cert, buf, len);
25239beb93cSSam Leffler 	}
253f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
254f05cddf9SRui Paulo 	if (verify->sha256_client)
255f05cddf9SRui Paulo 		crypto_hash_update(verify->sha256_client, buf, len);
256f05cddf9SRui Paulo 	if (verify->sha256_server)
257f05cddf9SRui Paulo 		crypto_hash_update(verify->sha256_server, buf, len);
258f05cddf9SRui Paulo 	if (verify->sha256_cert)
259f05cddf9SRui Paulo 		crypto_hash_update(verify->sha256_cert, buf, len);
260f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
26139beb93cSSam Leffler }
26239beb93cSSam Leffler 
26339beb93cSSam Leffler 
tls_verify_hash_free(struct tls_verify_hash * verify)26439beb93cSSam Leffler void tls_verify_hash_free(struct tls_verify_hash *verify)
26539beb93cSSam Leffler {
26639beb93cSSam Leffler 	crypto_hash_finish(verify->md5_client, NULL, NULL);
26739beb93cSSam Leffler 	crypto_hash_finish(verify->md5_server, NULL, NULL);
26839beb93cSSam Leffler 	crypto_hash_finish(verify->md5_cert, NULL, NULL);
26939beb93cSSam Leffler 	crypto_hash_finish(verify->sha1_client, NULL, NULL);
27039beb93cSSam Leffler 	crypto_hash_finish(verify->sha1_server, NULL, NULL);
27139beb93cSSam Leffler 	crypto_hash_finish(verify->sha1_cert, NULL, NULL);
27239beb93cSSam Leffler 	verify->md5_client = NULL;
27339beb93cSSam Leffler 	verify->md5_server = NULL;
27439beb93cSSam Leffler 	verify->md5_cert = NULL;
27539beb93cSSam Leffler 	verify->sha1_client = NULL;
27639beb93cSSam Leffler 	verify->sha1_server = NULL;
27739beb93cSSam Leffler 	verify->sha1_cert = NULL;
278f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
279f05cddf9SRui Paulo 	crypto_hash_finish(verify->sha256_client, NULL, NULL);
280f05cddf9SRui Paulo 	crypto_hash_finish(verify->sha256_server, NULL, NULL);
281f05cddf9SRui Paulo 	crypto_hash_finish(verify->sha256_cert, NULL, NULL);
282f05cddf9SRui Paulo 	verify->sha256_client = NULL;
283f05cddf9SRui Paulo 	verify->sha256_server = NULL;
284f05cddf9SRui Paulo 	verify->sha256_cert = NULL;
285f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
286f05cddf9SRui Paulo }
287f05cddf9SRui Paulo 
288f05cddf9SRui Paulo 
tls_version_ok(u16 ver)289f05cddf9SRui Paulo int tls_version_ok(u16 ver)
290f05cddf9SRui Paulo {
291f05cddf9SRui Paulo 	if (ver == TLS_VERSION_1)
292f05cddf9SRui Paulo 		return 1;
293f05cddf9SRui Paulo #ifdef CONFIG_TLSV11
294f05cddf9SRui Paulo 	if (ver == TLS_VERSION_1_1)
295f05cddf9SRui Paulo 		return 1;
296f05cddf9SRui Paulo #endif /* CONFIG_TLSV11 */
297f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
298f05cddf9SRui Paulo 	if (ver == TLS_VERSION_1_2)
299f05cddf9SRui Paulo 		return 1;
300f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
301f05cddf9SRui Paulo 
302f05cddf9SRui Paulo 	return 0;
303f05cddf9SRui Paulo }
304f05cddf9SRui Paulo 
305f05cddf9SRui Paulo 
tls_version_str(u16 ver)306f05cddf9SRui Paulo const char * tls_version_str(u16 ver)
307f05cddf9SRui Paulo {
308f05cddf9SRui Paulo 	switch (ver) {
309f05cddf9SRui Paulo 	case TLS_VERSION_1:
310f05cddf9SRui Paulo 		return "1.0";
311f05cddf9SRui Paulo 	case TLS_VERSION_1_1:
312f05cddf9SRui Paulo 		return "1.1";
313f05cddf9SRui Paulo 	case TLS_VERSION_1_2:
314f05cddf9SRui Paulo 		return "1.2";
315f05cddf9SRui Paulo 	}
316f05cddf9SRui Paulo 
317f05cddf9SRui Paulo 	return "?";
318f05cddf9SRui Paulo }
319f05cddf9SRui Paulo 
320f05cddf9SRui Paulo 
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)321f05cddf9SRui Paulo int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label,
322f05cddf9SRui Paulo 	    const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
323f05cddf9SRui Paulo {
324f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
325f05cddf9SRui Paulo 	if (ver >= TLS_VERSION_1_2) {
326f05cddf9SRui Paulo 		tls_prf_sha256(secret, secret_len, label, seed, seed_len,
327f05cddf9SRui Paulo 			       out, outlen);
328f05cddf9SRui Paulo 		return 0;
329f05cddf9SRui Paulo 	}
330f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
331f05cddf9SRui Paulo 
332f05cddf9SRui Paulo 	return tls_prf_sha1_md5(secret, secret_len, label, seed, seed_len, out,
333f05cddf9SRui Paulo 				outlen);
33439beb93cSSam Leffler }
3355b9c547cSRui Paulo 
3365b9c547cSRui Paulo 
3375b9c547cSRui Paulo #ifdef CONFIG_TLSV12
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)338780fb4a2SCy Schubert int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_alg,
3395b9c547cSRui Paulo 				    const u8 *client_random,
3405b9c547cSRui Paulo 				    const u8 *server_random,
3415b9c547cSRui Paulo 				    const u8 *server_params,
3425b9c547cSRui Paulo 				    size_t server_params_len, u8 *hash)
3435b9c547cSRui Paulo {
3445b9c547cSRui Paulo 	size_t hlen;
3455b9c547cSRui Paulo 	struct crypto_hash *ctx;
346780fb4a2SCy Schubert 	enum crypto_hash_alg alg;
3475b9c547cSRui Paulo 
348780fb4a2SCy Schubert 	switch (hash_alg) {
349780fb4a2SCy Schubert 	case TLS_HASH_ALG_SHA256:
350780fb4a2SCy Schubert 		alg = CRYPTO_HASH_ALG_SHA256;
351780fb4a2SCy Schubert 		hlen = SHA256_MAC_LEN;
352780fb4a2SCy Schubert 		break;
353780fb4a2SCy Schubert 	case TLS_HASH_ALG_SHA384:
354780fb4a2SCy Schubert 		alg = CRYPTO_HASH_ALG_SHA384;
355780fb4a2SCy Schubert 		hlen = 48;
356780fb4a2SCy Schubert 		break;
357780fb4a2SCy Schubert 	case TLS_HASH_ALG_SHA512:
358780fb4a2SCy Schubert 		alg = CRYPTO_HASH_ALG_SHA512;
359780fb4a2SCy Schubert 		hlen = 64;
360780fb4a2SCy Schubert 		break;
361780fb4a2SCy Schubert 	default:
362780fb4a2SCy Schubert 		return -1;
363780fb4a2SCy Schubert 	}
364780fb4a2SCy Schubert 	ctx = crypto_hash_init(alg, NULL, 0);
3655b9c547cSRui Paulo 	if (ctx == NULL)
3665b9c547cSRui Paulo 		return -1;
3675b9c547cSRui Paulo 	crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
3685b9c547cSRui Paulo 	crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
3695b9c547cSRui Paulo 	crypto_hash_update(ctx, server_params, server_params_len);
3705b9c547cSRui Paulo 	if (crypto_hash_finish(ctx, hash, &hlen) < 0)
3715b9c547cSRui Paulo 		return -1;
3725b9c547cSRui Paulo 
3735b9c547cSRui Paulo 	return hlen;
3745b9c547cSRui Paulo }
3755b9c547cSRui Paulo #endif /* CONFIG_TLSV12 */
3765b9c547cSRui Paulo 
3775b9c547cSRui Paulo 
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,size_t hsz)3785b9c547cSRui Paulo int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
3795b9c547cSRui Paulo 				 const u8 *server_random,
3805b9c547cSRui Paulo 				 const u8 *server_params,
381*a90b9d01SCy Schubert 				 size_t server_params_len, u8 *hash, size_t hsz)
3825b9c547cSRui Paulo {
3835b9c547cSRui Paulo 	u8 *hpos;
3845b9c547cSRui Paulo 	size_t hlen;
3855b9c547cSRui Paulo 	struct crypto_hash *ctx;
3865b9c547cSRui Paulo 
3875b9c547cSRui Paulo 	hpos = hash;
3885b9c547cSRui Paulo 
3895b9c547cSRui Paulo 	ctx = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
3905b9c547cSRui Paulo 	if (ctx == NULL)
3915b9c547cSRui Paulo 		return -1;
3925b9c547cSRui Paulo 	crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
3935b9c547cSRui Paulo 	crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
3945b9c547cSRui Paulo 	crypto_hash_update(ctx, server_params, server_params_len);
3955b9c547cSRui Paulo 	hlen = MD5_MAC_LEN;
396*a90b9d01SCy Schubert 	if (hsz < hlen)
397*a90b9d01SCy Schubert 		return -1;
3985b9c547cSRui Paulo 	if (crypto_hash_finish(ctx, hash, &hlen) < 0)
3995b9c547cSRui Paulo 		return -1;
4005b9c547cSRui Paulo 	hpos += hlen;
4015b9c547cSRui Paulo 
4025b9c547cSRui Paulo 	ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
4035b9c547cSRui Paulo 	if (ctx == NULL)
4045b9c547cSRui Paulo 		return -1;
4055b9c547cSRui Paulo 	crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
4065b9c547cSRui Paulo 	crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
4075b9c547cSRui Paulo 	crypto_hash_update(ctx, server_params, server_params_len);
408*a90b9d01SCy Schubert 	hlen = hsz - hlen;
4095b9c547cSRui Paulo 	if (crypto_hash_finish(ctx, hpos, &hlen) < 0)
4105b9c547cSRui Paulo 		return -1;
4115b9c547cSRui Paulo 	hpos += hlen;
4125b9c547cSRui Paulo 	return hpos - hash;
4135b9c547cSRui Paulo }
4145b9c547cSRui Paulo 
4155b9c547cSRui Paulo 
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)4165b9c547cSRui Paulo int tls_verify_signature(u16 tls_version, struct crypto_public_key *pk,
4175b9c547cSRui Paulo 			 const u8 *data, size_t data_len,
4185b9c547cSRui Paulo 			 const u8 *pos, size_t len, u8 *alert)
4195b9c547cSRui Paulo {
4205b9c547cSRui Paulo 	u8 *buf;
4215b9c547cSRui Paulo 	const u8 *end = pos + len;
4225b9c547cSRui Paulo 	const u8 *decrypted;
4235b9c547cSRui Paulo 	u16 slen;
4245b9c547cSRui Paulo 	size_t buflen;
4255b9c547cSRui Paulo 
4265b9c547cSRui Paulo 	if (end - pos < 2) {
4275b9c547cSRui Paulo 		*alert = TLS_ALERT_DECODE_ERROR;
4285b9c547cSRui Paulo 		return -1;
4295b9c547cSRui Paulo 	}
4305b9c547cSRui Paulo 	slen = WPA_GET_BE16(pos);
4315b9c547cSRui Paulo 	pos += 2;
4325b9c547cSRui Paulo 	if (end - pos < slen) {
4335b9c547cSRui Paulo 		*alert = TLS_ALERT_DECODE_ERROR;
4345b9c547cSRui Paulo 		return -1;
4355b9c547cSRui Paulo 	}
4365b9c547cSRui Paulo 	if (end - pos > slen) {
4375b9c547cSRui Paulo 		wpa_hexdump(MSG_MSGDUMP, "Additional data after Signature",
4385b9c547cSRui Paulo 			    pos + slen, end - pos - slen);
4395b9c547cSRui Paulo 		end = pos + slen;
4405b9c547cSRui Paulo 	}
4415b9c547cSRui Paulo 
4425b9c547cSRui Paulo 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos);
4435b9c547cSRui Paulo 	if (pk == NULL) {
4445b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "TLSv1: No public key to verify signature");
4455b9c547cSRui Paulo 		*alert = TLS_ALERT_INTERNAL_ERROR;
4465b9c547cSRui Paulo 		return -1;
4475b9c547cSRui Paulo 	}
4485b9c547cSRui Paulo 
4495b9c547cSRui Paulo 	buflen = end - pos;
4505b9c547cSRui Paulo 	buf = os_malloc(end - pos);
4515b9c547cSRui Paulo 	if (buf == NULL) {
4525b9c547cSRui Paulo 		*alert = TLS_ALERT_INTERNAL_ERROR;
4535b9c547cSRui Paulo 		return -1;
4545b9c547cSRui Paulo 	}
4555b9c547cSRui Paulo 	if (crypto_public_key_decrypt_pkcs1(pk, pos, end - pos, buf, &buflen) <
4565b9c547cSRui Paulo 	    0) {
4575b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature");
4585b9c547cSRui Paulo 		os_free(buf);
4595b9c547cSRui Paulo 		*alert = TLS_ALERT_DECRYPT_ERROR;
4605b9c547cSRui Paulo 		return -1;
4615b9c547cSRui Paulo 	}
4625b9c547cSRui Paulo 	decrypted = buf;
4635b9c547cSRui Paulo 
4645b9c547cSRui Paulo 	wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature",
4655b9c547cSRui Paulo 			decrypted, buflen);
4665b9c547cSRui Paulo 
4675b9c547cSRui Paulo #ifdef CONFIG_TLSV12
4685b9c547cSRui Paulo 	if (tls_version >= TLS_VERSION_1_2) {
4695b9c547cSRui Paulo 		/*
4705b9c547cSRui Paulo 		 * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5
4715b9c547cSRui Paulo 		 *
4725b9c547cSRui Paulo 		 * DigestInfo ::= SEQUENCE {
4735b9c547cSRui Paulo 		 *   digestAlgorithm DigestAlgorithm,
4745b9c547cSRui Paulo 		 *   digest OCTET STRING
4755b9c547cSRui Paulo 		 * }
4765b9c547cSRui Paulo 		 *
4775b9c547cSRui Paulo 		 * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11}
4785b9c547cSRui Paulo 		 *
4795b9c547cSRui Paulo 		 * DER encoded DigestInfo for SHA256 per RFC 3447:
4805b9c547cSRui Paulo 		 * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 ||
4815b9c547cSRui Paulo 		 * H
4825b9c547cSRui Paulo 		 */
4835b9c547cSRui Paulo 		if (buflen >= 19 + 32 &&
4845b9c547cSRui Paulo 		    os_memcmp(buf, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01"
4855b9c547cSRui Paulo 			      "\x65\x03\x04\x02\x01\x05\x00\x04\x20", 19) == 0)
4865b9c547cSRui Paulo 		{
48785732ac8SCy Schubert 			wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithm = SHA-256");
4885b9c547cSRui Paulo 			decrypted = buf + 19;
4895b9c547cSRui Paulo 			buflen -= 19;
490780fb4a2SCy Schubert 		} else if (buflen >= 19 + 48 &&
491780fb4a2SCy Schubert 		    os_memcmp(buf, "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01"
492780fb4a2SCy Schubert 			      "\x65\x03\x04\x02\x02\x05\x00\x04\x30", 19) == 0)
493780fb4a2SCy Schubert 		{
49485732ac8SCy Schubert 			wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithm = SHA-384");
495780fb4a2SCy Schubert 			decrypted = buf + 19;
496780fb4a2SCy Schubert 			buflen -= 19;
497780fb4a2SCy Schubert 		} else if (buflen >= 19 + 64 &&
498780fb4a2SCy Schubert 		    os_memcmp(buf, "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01"
499780fb4a2SCy Schubert 			      "\x65\x03\x04\x02\x03\x05\x00\x04\x40", 19) == 0)
500780fb4a2SCy Schubert 		{
50185732ac8SCy Schubert 			wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithm = SHA-512");
502780fb4a2SCy Schubert 			decrypted = buf + 19;
503780fb4a2SCy Schubert 			buflen -= 19;
504780fb4a2SCy Schubert 
5055b9c547cSRui Paulo 		} else {
5065b9c547cSRui Paulo 			wpa_printf(MSG_DEBUG, "TLSv1.2: Unrecognized DigestInfo");
5075b9c547cSRui Paulo 			os_free(buf);
5085b9c547cSRui Paulo 			*alert = TLS_ALERT_DECRYPT_ERROR;
5095b9c547cSRui Paulo 			return -1;
5105b9c547cSRui Paulo 		}
5115b9c547cSRui Paulo 	}
5125b9c547cSRui Paulo #endif /* CONFIG_TLSV12 */
5135b9c547cSRui Paulo 
5145b9c547cSRui Paulo 	if (buflen != data_len ||
5155b9c547cSRui Paulo 	    os_memcmp_const(decrypted, data, data_len) != 0) {
5165b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in CertificateVerify - did not match calculated hash");
5175b9c547cSRui Paulo 		os_free(buf);
5185b9c547cSRui Paulo 		*alert = TLS_ALERT_DECRYPT_ERROR;
5195b9c547cSRui Paulo 		return -1;
5205b9c547cSRui Paulo 	}
5215b9c547cSRui Paulo 
5225b9c547cSRui Paulo 	os_free(buf);
5235b9c547cSRui Paulo 
5245b9c547cSRui Paulo 	return 0;
5255b9c547cSRui Paulo }
526