xref: /freebsd/contrib/wpa/src/tls/tlsv1_common.c (revision 39beb93c3f8bdbf72a61fda42300b5ebed7390c8)
139beb93cSSam Leffler /*
239beb93cSSam Leffler  * TLSv1 common routines
339beb93cSSam Leffler  * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
539beb93cSSam Leffler  * This program is free software; you can redistribute it and/or modify
639beb93cSSam Leffler  * it under the terms of the GNU General Public License version 2 as
739beb93cSSam Leffler  * published by the Free Software Foundation.
839beb93cSSam Leffler  *
939beb93cSSam Leffler  * Alternatively, this software may be distributed under the terms of BSD
1039beb93cSSam Leffler  * license.
1139beb93cSSam Leffler  *
1239beb93cSSam Leffler  * See README and COPYING for more details.
1339beb93cSSam Leffler  */
1439beb93cSSam Leffler 
1539beb93cSSam Leffler #include "includes.h"
1639beb93cSSam Leffler 
1739beb93cSSam Leffler #include "common.h"
1839beb93cSSam Leffler #include "x509v3.h"
1939beb93cSSam Leffler #include "tlsv1_common.h"
2039beb93cSSam Leffler 
2139beb93cSSam Leffler 
2239beb93cSSam Leffler /*
2339beb93cSSam Leffler  * TODO:
2439beb93cSSam Leffler  * RFC 2246 Section 9: Mandatory to implement TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
2539beb93cSSam Leffler  * Add support for commonly used cipher suites; don't bother with exportable
2639beb93cSSam Leffler  * suites.
2739beb93cSSam Leffler  */
2839beb93cSSam Leffler 
2939beb93cSSam Leffler static const struct tls_cipher_suite tls_cipher_suites[] = {
3039beb93cSSam Leffler 	{ TLS_NULL_WITH_NULL_NULL, TLS_KEY_X_NULL, TLS_CIPHER_NULL,
3139beb93cSSam Leffler 	  TLS_HASH_NULL },
3239beb93cSSam Leffler 	{ TLS_RSA_WITH_RC4_128_MD5, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128,
3339beb93cSSam Leffler 	  TLS_HASH_MD5 },
3439beb93cSSam Leffler 	{ TLS_RSA_WITH_RC4_128_SHA, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128,
3539beb93cSSam Leffler 	  TLS_HASH_SHA },
3639beb93cSSam Leffler 	{ TLS_RSA_WITH_DES_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_DES_CBC,
3739beb93cSSam Leffler 	  TLS_HASH_SHA },
3839beb93cSSam Leffler 	{ TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_RSA,
3939beb93cSSam Leffler 	  TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA },
4039beb93cSSam Leffler  	{ TLS_DH_anon_WITH_RC4_128_MD5, TLS_KEY_X_DH_anon,
4139beb93cSSam Leffler 	  TLS_CIPHER_RC4_128, TLS_HASH_MD5 },
4239beb93cSSam Leffler  	{ TLS_DH_anon_WITH_DES_CBC_SHA, TLS_KEY_X_DH_anon,
4339beb93cSSam Leffler 	  TLS_CIPHER_DES_CBC, TLS_HASH_SHA },
4439beb93cSSam Leffler  	{ TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_DH_anon,
4539beb93cSSam Leffler 	  TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA },
4639beb93cSSam Leffler 	{ TLS_RSA_WITH_AES_128_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_128_CBC,
4739beb93cSSam Leffler 	  TLS_HASH_SHA },
4839beb93cSSam Leffler 	{ TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_KEY_X_DH_anon,
4939beb93cSSam Leffler 	  TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA },
5039beb93cSSam Leffler 	{ TLS_RSA_WITH_AES_256_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_256_CBC,
5139beb93cSSam Leffler 	  TLS_HASH_SHA },
5239beb93cSSam Leffler 	{ TLS_DH_anon_WITH_AES_256_CBC_SHA, TLS_KEY_X_DH_anon,
5339beb93cSSam Leffler 	  TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA }
5439beb93cSSam Leffler };
5539beb93cSSam Leffler 
5639beb93cSSam Leffler #define NUM_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
5739beb93cSSam Leffler #define NUM_TLS_CIPHER_SUITES NUM_ELEMS(tls_cipher_suites)
5839beb93cSSam Leffler 
5939beb93cSSam Leffler 
6039beb93cSSam Leffler static const struct tls_cipher_data tls_ciphers[] = {
6139beb93cSSam Leffler 	{ TLS_CIPHER_NULL,         TLS_CIPHER_STREAM,  0,  0,  0,
6239beb93cSSam Leffler 	  CRYPTO_CIPHER_NULL },
6339beb93cSSam Leffler 	{ TLS_CIPHER_IDEA_CBC,     TLS_CIPHER_BLOCK,  16, 16,  8,
6439beb93cSSam Leffler 	  CRYPTO_CIPHER_NULL },
6539beb93cSSam Leffler 	{ TLS_CIPHER_RC2_CBC_40,   TLS_CIPHER_BLOCK,   5, 16,  0,
6639beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_RC2 },
6739beb93cSSam Leffler 	{ TLS_CIPHER_RC4_40,       TLS_CIPHER_STREAM,  5, 16,  0,
6839beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_RC4 },
6939beb93cSSam Leffler 	{ TLS_CIPHER_RC4_128,      TLS_CIPHER_STREAM, 16, 16,  0,
7039beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_RC4 },
7139beb93cSSam Leffler 	{ TLS_CIPHER_DES40_CBC,    TLS_CIPHER_BLOCK,   5,  8,  8,
7239beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_DES },
7339beb93cSSam Leffler 	{ TLS_CIPHER_DES_CBC,      TLS_CIPHER_BLOCK,   8,  8,  8,
7439beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_DES },
7539beb93cSSam Leffler 	{ TLS_CIPHER_3DES_EDE_CBC, TLS_CIPHER_BLOCK,  24, 24,  8,
7639beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_3DES },
7739beb93cSSam Leffler 	{ TLS_CIPHER_AES_128_CBC,  TLS_CIPHER_BLOCK,  16, 16, 16,
7839beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_AES },
7939beb93cSSam Leffler 	{ TLS_CIPHER_AES_256_CBC,  TLS_CIPHER_BLOCK,  32, 32, 16,
8039beb93cSSam Leffler 	  CRYPTO_CIPHER_ALG_AES }
8139beb93cSSam Leffler };
8239beb93cSSam Leffler 
8339beb93cSSam Leffler #define NUM_TLS_CIPHER_DATA NUM_ELEMS(tls_ciphers)
8439beb93cSSam Leffler 
8539beb93cSSam Leffler 
8639beb93cSSam Leffler /**
8739beb93cSSam Leffler  * tls_get_cipher_suite - Get TLS cipher suite
8839beb93cSSam Leffler  * @suite: Cipher suite identifier
8939beb93cSSam Leffler  * Returns: Pointer to the cipher data or %NULL if not found
9039beb93cSSam Leffler  */
9139beb93cSSam Leffler const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite)
9239beb93cSSam Leffler {
9339beb93cSSam Leffler 	size_t i;
9439beb93cSSam Leffler 	for (i = 0; i < NUM_TLS_CIPHER_SUITES; i++)
9539beb93cSSam Leffler 		if (tls_cipher_suites[i].suite == suite)
9639beb93cSSam Leffler 			return &tls_cipher_suites[i];
9739beb93cSSam Leffler 	return NULL;
9839beb93cSSam Leffler }
9939beb93cSSam Leffler 
10039beb93cSSam Leffler 
10139beb93cSSam Leffler const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher)
10239beb93cSSam Leffler {
10339beb93cSSam Leffler 	size_t i;
10439beb93cSSam Leffler 	for (i = 0; i < NUM_TLS_CIPHER_DATA; i++)
10539beb93cSSam Leffler 		if (tls_ciphers[i].cipher == cipher)
10639beb93cSSam Leffler 			return &tls_ciphers[i];
10739beb93cSSam Leffler 	return NULL;
10839beb93cSSam Leffler }
10939beb93cSSam Leffler 
11039beb93cSSam Leffler 
11139beb93cSSam Leffler int tls_server_key_exchange_allowed(tls_cipher cipher)
11239beb93cSSam Leffler {
11339beb93cSSam Leffler 	const struct tls_cipher_suite *suite;
11439beb93cSSam Leffler 
11539beb93cSSam Leffler 	/* RFC 2246, Section 7.4.3 */
11639beb93cSSam Leffler 	suite = tls_get_cipher_suite(cipher);
11739beb93cSSam Leffler 	if (suite == NULL)
11839beb93cSSam Leffler 		return 0;
11939beb93cSSam Leffler 
12039beb93cSSam Leffler 	switch (suite->key_exchange) {
12139beb93cSSam Leffler 	case TLS_KEY_X_DHE_DSS:
12239beb93cSSam Leffler 	case TLS_KEY_X_DHE_DSS_EXPORT:
12339beb93cSSam Leffler 	case TLS_KEY_X_DHE_RSA:
12439beb93cSSam Leffler 	case TLS_KEY_X_DHE_RSA_EXPORT:
12539beb93cSSam Leffler 	case TLS_KEY_X_DH_anon_EXPORT:
12639beb93cSSam Leffler 	case TLS_KEY_X_DH_anon:
12739beb93cSSam Leffler 		return 1;
12839beb93cSSam Leffler 	case TLS_KEY_X_RSA_EXPORT:
12939beb93cSSam Leffler 		return 1 /* FIX: public key len > 512 bits */;
13039beb93cSSam Leffler 	default:
13139beb93cSSam Leffler 		return 0;
13239beb93cSSam Leffler 	}
13339beb93cSSam Leffler }
13439beb93cSSam Leffler 
13539beb93cSSam Leffler 
13639beb93cSSam Leffler /**
13739beb93cSSam Leffler  * tls_parse_cert - Parse DER encoded X.509 certificate and get public key
13839beb93cSSam Leffler  * @buf: ASN.1 DER encoded certificate
13939beb93cSSam Leffler  * @len: Length of the buffer
14039beb93cSSam Leffler  * @pk: Buffer for returning the allocated public key
14139beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
14239beb93cSSam Leffler  *
14339beb93cSSam Leffler  * This functions parses an ASN.1 DER encoded X.509 certificate and retrieves
14439beb93cSSam Leffler  * the public key from it. The caller is responsible for freeing the public key
14539beb93cSSam Leffler  * by calling crypto_public_key_free().
14639beb93cSSam Leffler  */
14739beb93cSSam Leffler int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk)
14839beb93cSSam Leffler {
14939beb93cSSam Leffler 	struct x509_certificate *cert;
15039beb93cSSam Leffler 
15139beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: Parse ASN.1 DER certificate",
15239beb93cSSam Leffler 		    buf, len);
15339beb93cSSam Leffler 
15439beb93cSSam Leffler 	*pk = crypto_public_key_from_cert(buf, len);
15539beb93cSSam Leffler 	if (*pk)
15639beb93cSSam Leffler 		return 0;
15739beb93cSSam Leffler 
15839beb93cSSam Leffler 	cert = x509_certificate_parse(buf, len);
15939beb93cSSam Leffler 	if (cert == NULL) {
16039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse X.509 "
16139beb93cSSam Leffler 			   "certificate");
16239beb93cSSam Leffler 		return -1;
16339beb93cSSam Leffler 	}
16439beb93cSSam Leffler 
16539beb93cSSam Leffler 	/* TODO
16639beb93cSSam Leffler 	 * verify key usage (must allow encryption)
16739beb93cSSam Leffler 	 *
16839beb93cSSam Leffler 	 * All certificate profiles, key and cryptographic formats are
16939beb93cSSam Leffler 	 * defined by the IETF PKIX working group [PKIX]. When a key
17039beb93cSSam Leffler 	 * usage extension is present, the digitalSignature bit must be
17139beb93cSSam Leffler 	 * set for the key to be eligible for signing, as described
17239beb93cSSam Leffler 	 * above, and the keyEncipherment bit must be present to allow
17339beb93cSSam Leffler 	 * encryption, as described above. The keyAgreement bit must be
17439beb93cSSam Leffler 	 * set on Diffie-Hellman certificates. (PKIX: RFC 3280)
17539beb93cSSam Leffler 	 */
17639beb93cSSam Leffler 
17739beb93cSSam Leffler 	*pk = crypto_public_key_import(cert->public_key, cert->public_key_len);
17839beb93cSSam Leffler 	x509_certificate_free(cert);
17939beb93cSSam Leffler 
18039beb93cSSam Leffler 	if (*pk == NULL) {
18139beb93cSSam Leffler 		wpa_printf(MSG_ERROR, "TLSv1: Failed to import "
18239beb93cSSam Leffler 			   "server public key");
18339beb93cSSam Leffler 		return -1;
18439beb93cSSam Leffler 	}
18539beb93cSSam Leffler 
18639beb93cSSam Leffler 	return 0;
18739beb93cSSam Leffler }
18839beb93cSSam Leffler 
18939beb93cSSam Leffler 
19039beb93cSSam Leffler int tls_verify_hash_init(struct tls_verify_hash *verify)
19139beb93cSSam Leffler {
19239beb93cSSam Leffler 	tls_verify_hash_free(verify);
19339beb93cSSam Leffler 	verify->md5_client = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
19439beb93cSSam Leffler 	verify->md5_server = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
19539beb93cSSam Leffler 	verify->md5_cert = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
19639beb93cSSam Leffler 	verify->sha1_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
19739beb93cSSam Leffler 	verify->sha1_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
19839beb93cSSam Leffler 	verify->sha1_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
19939beb93cSSam Leffler 	if (verify->md5_client == NULL || verify->md5_server == NULL ||
20039beb93cSSam Leffler 	    verify->md5_cert == NULL || verify->sha1_client == NULL ||
20139beb93cSSam Leffler 	    verify->sha1_server == NULL || verify->sha1_cert == NULL) {
20239beb93cSSam Leffler 		tls_verify_hash_free(verify);
20339beb93cSSam Leffler 		return -1;
20439beb93cSSam Leffler 	}
20539beb93cSSam Leffler 	return 0;
20639beb93cSSam Leffler }
20739beb93cSSam Leffler 
20839beb93cSSam Leffler 
20939beb93cSSam Leffler void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf,
21039beb93cSSam Leffler 			 size_t len)
21139beb93cSSam Leffler {
21239beb93cSSam Leffler 	if (verify->md5_client && verify->sha1_client) {
21339beb93cSSam Leffler 		crypto_hash_update(verify->md5_client, buf, len);
21439beb93cSSam Leffler 		crypto_hash_update(verify->sha1_client, buf, len);
21539beb93cSSam Leffler 	}
21639beb93cSSam Leffler 	if (verify->md5_server && verify->sha1_server) {
21739beb93cSSam Leffler 		crypto_hash_update(verify->md5_server, buf, len);
21839beb93cSSam Leffler 		crypto_hash_update(verify->sha1_server, buf, len);
21939beb93cSSam Leffler 	}
22039beb93cSSam Leffler 	if (verify->md5_cert && verify->sha1_cert) {
22139beb93cSSam Leffler 		crypto_hash_update(verify->md5_cert, buf, len);
22239beb93cSSam Leffler 		crypto_hash_update(verify->sha1_cert, buf, len);
22339beb93cSSam Leffler 	}
22439beb93cSSam Leffler }
22539beb93cSSam Leffler 
22639beb93cSSam Leffler 
22739beb93cSSam Leffler void tls_verify_hash_free(struct tls_verify_hash *verify)
22839beb93cSSam Leffler {
22939beb93cSSam Leffler 	crypto_hash_finish(verify->md5_client, NULL, NULL);
23039beb93cSSam Leffler 	crypto_hash_finish(verify->md5_server, NULL, NULL);
23139beb93cSSam Leffler 	crypto_hash_finish(verify->md5_cert, NULL, NULL);
23239beb93cSSam Leffler 	crypto_hash_finish(verify->sha1_client, NULL, NULL);
23339beb93cSSam Leffler 	crypto_hash_finish(verify->sha1_server, NULL, NULL);
23439beb93cSSam Leffler 	crypto_hash_finish(verify->sha1_cert, NULL, NULL);
23539beb93cSSam Leffler 	verify->md5_client = NULL;
23639beb93cSSam Leffler 	verify->md5_server = NULL;
23739beb93cSSam Leffler 	verify->md5_cert = NULL;
23839beb93cSSam Leffler 	verify->sha1_client = NULL;
23939beb93cSSam Leffler 	verify->sha1_server = NULL;
24039beb93cSSam Leffler 	verify->sha1_cert = NULL;
24139beb93cSSam Leffler }
242