18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLSv1 common routines
31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "crypto/sha1.h"
131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "crypto/sha256.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "x509v3.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_common.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO:
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 2246 Section 9: Mandatory to implement TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Add support for commonly used cipher suites; don't bother with exportable
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * suites.
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const struct tls_cipher_suite tls_cipher_suites[] = {
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_NULL_WITH_NULL_NULL, TLS_KEY_X_NULL, TLS_CIPHER_NULL,
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  TLS_HASH_NULL },
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_RSA_WITH_RC4_128_MD5, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128,
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  TLS_HASH_MD5 },
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_RSA_WITH_RC4_128_SHA, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128,
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  TLS_HASH_SHA },
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_RSA_WITH_DES_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_DES_CBC,
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  TLS_HASH_SHA },
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_RSA,
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA },
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 	{ TLS_DH_anon_WITH_RC4_128_MD5, TLS_KEY_X_DH_anon,
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  TLS_CIPHER_RC4_128, TLS_HASH_MD5 },
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 	{ TLS_DH_anon_WITH_DES_CBC_SHA, TLS_KEY_X_DH_anon,
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  TLS_CIPHER_DES_CBC, TLS_HASH_SHA },
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 	{ TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_DH_anon,
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA },
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_RSA_WITH_AES_128_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_128_CBC,
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  TLS_HASH_SHA },
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_KEY_X_DH_anon,
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA },
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_RSA_WITH_AES_256_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_256_CBC,
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  TLS_HASH_SHA },
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_DH_anon_WITH_AES_256_CBC_SHA, TLS_KEY_X_DH_anon,
491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	  TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA },
501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_KEY_X_RSA,
511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	  TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA256 },
521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_KEY_X_RSA,
531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	  TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA256 },
541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ TLS_DH_anon_WITH_AES_128_CBC_SHA256, TLS_KEY_X_DH_anon,
551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	  TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA256 },
561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ TLS_DH_anon_WITH_AES_256_CBC_SHA256, TLS_KEY_X_DH_anon,
571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	  TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA256 }
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NUM_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NUM_TLS_CIPHER_SUITES NUM_ELEMS(tls_cipher_suites)
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const struct tls_cipher_data tls_ciphers[] = {
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_CIPHER_NULL,         TLS_CIPHER_STREAM,  0,  0,  0,
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  CRYPTO_CIPHER_NULL },
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_CIPHER_IDEA_CBC,     TLS_CIPHER_BLOCK,  16, 16,  8,
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  CRYPTO_CIPHER_NULL },
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_CIPHER_RC2_CBC_40,   TLS_CIPHER_BLOCK,   5, 16,  0,
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  CRYPTO_CIPHER_ALG_RC2 },
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_CIPHER_RC4_40,       TLS_CIPHER_STREAM,  5, 16,  0,
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  CRYPTO_CIPHER_ALG_RC4 },
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_CIPHER_RC4_128,      TLS_CIPHER_STREAM, 16, 16,  0,
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  CRYPTO_CIPHER_ALG_RC4 },
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_CIPHER_DES40_CBC,    TLS_CIPHER_BLOCK,   5,  8,  8,
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  CRYPTO_CIPHER_ALG_DES },
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_CIPHER_DES_CBC,      TLS_CIPHER_BLOCK,   8,  8,  8,
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  CRYPTO_CIPHER_ALG_DES },
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_CIPHER_3DES_EDE_CBC, TLS_CIPHER_BLOCK,  24, 24,  8,
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  CRYPTO_CIPHER_ALG_3DES },
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_CIPHER_AES_128_CBC,  TLS_CIPHER_BLOCK,  16, 16, 16,
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  CRYPTO_CIPHER_ALG_AES },
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ TLS_CIPHER_AES_256_CBC,  TLS_CIPHER_BLOCK,  32, 32, 16,
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	  CRYPTO_CIPHER_ALG_AES }
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define NUM_TLS_CIPHER_DATA NUM_ELEMS(tls_ciphers)
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tls_get_cipher_suite - Get TLS cipher suite
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @suite: Cipher suite identifier
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the cipher data or %NULL if not found
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct tls_cipher_suite * tls_get_cipher_suite(u16 suite)
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < NUM_TLS_CIPHER_SUITES; i++)
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_cipher_suites[i].suite == suite)
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return &tls_cipher_suites[i];
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher)
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < NUM_TLS_CIPHER_DATA; i++)
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_ciphers[i].cipher == cipher)
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return &tls_ciphers[i];
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_server_key_exchange_allowed(tls_cipher cipher)
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct tls_cipher_suite *suite;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* RFC 2246, Section 7.4.3 */
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	suite = tls_get_cipher_suite(cipher);
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (suite == NULL)
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (suite->key_exchange) {
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case TLS_KEY_X_DHE_DSS:
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case TLS_KEY_X_DHE_DSS_EXPORT:
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case TLS_KEY_X_DHE_RSA:
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case TLS_KEY_X_DHE_RSA_EXPORT:
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case TLS_KEY_X_DH_anon_EXPORT:
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case TLS_KEY_X_DH_anon:
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case TLS_KEY_X_RSA_EXPORT:
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1 /* FIX: public key len > 512 bits */;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tls_parse_cert - Parse DER encoded X.509 certificate and get public key
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: ASN.1 DER encoded certificate
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the buffer
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pk: Buffer for returning the allocated public key
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This functions parses an ASN.1 DER encoded X.509 certificate and retrieves
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the public key from it. The caller is responsible for freeing the public key
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * by calling crypto_public_key_free().
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk)
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct x509_certificate *cert;
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: Parse ASN.1 DER certificate",
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    buf, len);
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pk = crypto_public_key_from_cert(buf, len);
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*pk)
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cert = x509_certificate_parse(buf, len);
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert == NULL) {
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse X.509 "
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "certificate");
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * verify key usage (must allow encryption)
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * All certificate profiles, key and cryptographic formats are
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * defined by the IETF PKIX working group [PKIX]. When a key
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * usage extension is present, the digitalSignature bit must be
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * set for the key to be eligible for signing, as described
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * above, and the keyEncipherment bit must be present to allow
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * encryption, as described above. The keyAgreement bit must be
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * set on Diffie-Hellman certificates. (PKIX: RFC 3280)
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pk = crypto_public_key_import(cert->public_key, cert->public_key_len);
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	x509_certificate_free(cert);
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*pk == NULL) {
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "TLSv1: Failed to import "
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "server public key");
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_verify_hash_init(struct tls_verify_hash *verify)
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_verify_hash_free(verify);
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	verify->md5_client = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	verify->md5_server = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	verify->md5_cert = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	verify->sha1_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	verify->sha1_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	verify->sha1_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (verify->md5_client == NULL || verify->md5_server == NULL ||
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    verify->md5_cert == NULL || verify->sha1_client == NULL ||
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    verify->sha1_server == NULL || verify->sha1_cert == NULL) {
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_verify_hash_free(verify);
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
2101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	verify->sha256_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL,
2111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt						 0);
2121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	verify->sha256_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL,
2131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt						 0);
2141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	verify->sha256_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL,
2151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					       0);
2161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (verify->sha256_client == NULL || verify->sha256_server == NULL ||
2171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    verify->sha256_cert == NULL) {
2181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		tls_verify_hash_free(verify);
2191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
2201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
2211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf,
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 size_t len)
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (verify->md5_client && verify->sha1_client) {
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_update(verify->md5_client, buf, len);
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_update(verify->sha1_client, buf, len);
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (verify->md5_server && verify->sha1_server) {
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_update(verify->md5_server, buf, len);
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_update(verify->sha1_server, buf, len);
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (verify->md5_cert && verify->sha1_cert) {
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_update(verify->md5_cert, buf, len);
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_update(verify->sha1_cert, buf, len);
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
2421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (verify->sha256_client)
2431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		crypto_hash_update(verify->sha256_client, buf, len);
2441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (verify->sha256_server)
2451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		crypto_hash_update(verify->sha256_server, buf, len);
2461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (verify->sha256_cert)
2471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		crypto_hash_update(verify->sha256_cert, buf, len);
2481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_verify_hash_free(struct tls_verify_hash *verify)
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	crypto_hash_finish(verify->md5_client, NULL, NULL);
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	crypto_hash_finish(verify->md5_server, NULL, NULL);
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	crypto_hash_finish(verify->md5_cert, NULL, NULL);
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	crypto_hash_finish(verify->sha1_client, NULL, NULL);
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	crypto_hash_finish(verify->sha1_server, NULL, NULL);
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	crypto_hash_finish(verify->sha1_cert, NULL, NULL);
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	verify->md5_client = NULL;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	verify->md5_server = NULL;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	verify->md5_cert = NULL;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	verify->sha1_client = NULL;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	verify->sha1_server = NULL;
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	verify->sha1_cert = NULL;
2661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
2671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	crypto_hash_finish(verify->sha256_client, NULL, NULL);
2681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	crypto_hash_finish(verify->sha256_server, NULL, NULL);
2691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	crypto_hash_finish(verify->sha256_cert, NULL, NULL);
2701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	verify->sha256_client = NULL;
2711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	verify->sha256_server = NULL;
2721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	verify->sha256_cert = NULL;
2731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
2741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
2751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint tls_version_ok(u16 ver)
2781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
2791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (ver == TLS_VERSION_1)
2801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 1;
2811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV11
2821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (ver == TLS_VERSION_1_1)
2831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 1;
2841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV11 */
2851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
2861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (ver == TLS_VERSION_1_2)
2871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 1;
2881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
2891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 0;
2911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
2921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtconst char * tls_version_str(u16 ver)
2951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
2961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (ver) {
2971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case TLS_VERSION_1:
2981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return "1.0";
2991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case TLS_VERSION_1_1:
3001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return "1.1";
3011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case TLS_VERSION_1_2:
3021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return "1.2";
3031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
3041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return "?";
3061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
3071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label,
3101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
3111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
3121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
3131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (ver >= TLS_VERSION_1_2) {
3141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		tls_prf_sha256(secret, secret_len, label, seed, seed_len,
3151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			       out, outlen);
3161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
3171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
3181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
3191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return tls_prf_sha1_md5(secret, secret_len, label, seed, seed_len, out,
3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				outlen);
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
323