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