123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492 |
- /*
- * TLSv1 common routines
- * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
- #include "includes.h"
- #include "common.h"
- #include "crypto/md5.h"
- #include "crypto/sha1.h"
- #include "crypto/sha256.h"
- #include "x509v3.h"
- #include "tlsv1_common.h"
- /*
- * TODO:
- * RFC 2246 Section 9: Mandatory to implement TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
- * Add support for commonly used cipher suites; don't bother with exportable
- * suites.
- */
- static const struct tls_cipher_suite tls_cipher_suites[] = {
- { TLS_NULL_WITH_NULL_NULL, TLS_KEY_X_NULL, TLS_CIPHER_NULL,
- TLS_HASH_NULL },
- { TLS_RSA_WITH_RC4_128_MD5, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128,
- TLS_HASH_MD5 },
- { TLS_RSA_WITH_RC4_128_SHA, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128,
- TLS_HASH_SHA },
- { TLS_RSA_WITH_DES_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_DES_CBC,
- TLS_HASH_SHA },
- { TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_RSA,
- TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA },
- { TLS_DHE_RSA_WITH_DES_CBC_SHA, TLS_KEY_X_DHE_RSA, TLS_CIPHER_DES_CBC,
- TLS_HASH_SHA},
- { TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_DHE_RSA,
- TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA },
- { TLS_DH_anon_WITH_RC4_128_MD5, TLS_KEY_X_DH_anon,
- TLS_CIPHER_RC4_128, TLS_HASH_MD5 },
- { TLS_DH_anon_WITH_DES_CBC_SHA, TLS_KEY_X_DH_anon,
- TLS_CIPHER_DES_CBC, TLS_HASH_SHA },
- { TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_DH_anon,
- TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA },
- { TLS_RSA_WITH_AES_128_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_128_CBC,
- TLS_HASH_SHA },
- { TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_KEY_X_DHE_RSA,
- TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA },
- { TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_KEY_X_DH_anon,
- TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA },
- { TLS_RSA_WITH_AES_256_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_256_CBC,
- TLS_HASH_SHA },
- { TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_KEY_X_DHE_RSA,
- TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA },
- { TLS_DH_anon_WITH_AES_256_CBC_SHA, TLS_KEY_X_DH_anon,
- TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA },
- { TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_KEY_X_RSA,
- TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA256 },
- { TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_KEY_X_RSA,
- TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA256 },
- { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_KEY_X_DHE_RSA,
- TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA256 },
- { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_KEY_X_DHE_RSA,
- TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA256 },
- { TLS_DH_anon_WITH_AES_128_CBC_SHA256, TLS_KEY_X_DH_anon,
- TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA256 },
- { TLS_DH_anon_WITH_AES_256_CBC_SHA256, TLS_KEY_X_DH_anon,
- TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA256 }
- };
- #define NUM_TLS_CIPHER_SUITES ARRAY_SIZE(tls_cipher_suites)
- static const struct tls_cipher_data tls_ciphers[] = {
- { TLS_CIPHER_NULL, TLS_CIPHER_STREAM, 0, 0, 0,
- CRYPTO_CIPHER_NULL },
- { TLS_CIPHER_IDEA_CBC, TLS_CIPHER_BLOCK, 16, 16, 8,
- CRYPTO_CIPHER_NULL },
- { TLS_CIPHER_RC2_CBC_40, TLS_CIPHER_BLOCK, 5, 16, 0,
- CRYPTO_CIPHER_ALG_RC2 },
- { TLS_CIPHER_RC4_40, TLS_CIPHER_STREAM, 5, 16, 0,
- CRYPTO_CIPHER_ALG_RC4 },
- { TLS_CIPHER_RC4_128, TLS_CIPHER_STREAM, 16, 16, 0,
- CRYPTO_CIPHER_ALG_RC4 },
- { TLS_CIPHER_DES40_CBC, TLS_CIPHER_BLOCK, 5, 8, 8,
- CRYPTO_CIPHER_ALG_DES },
- { TLS_CIPHER_DES_CBC, TLS_CIPHER_BLOCK, 8, 8, 8,
- CRYPTO_CIPHER_ALG_DES },
- { TLS_CIPHER_3DES_EDE_CBC, TLS_CIPHER_BLOCK, 24, 24, 8,
- CRYPTO_CIPHER_ALG_3DES },
- { TLS_CIPHER_AES_128_CBC, TLS_CIPHER_BLOCK, 16, 16, 16,
- CRYPTO_CIPHER_ALG_AES },
- { TLS_CIPHER_AES_256_CBC, TLS_CIPHER_BLOCK, 32, 32, 16,
- CRYPTO_CIPHER_ALG_AES }
- };
- #define NUM_TLS_CIPHER_DATA ARRAY_SIZE(tls_ciphers)
- /**
- * tls_get_cipher_suite - Get TLS cipher suite
- * @suite: Cipher suite identifier
- * Returns: Pointer to the cipher data or %NULL if not found
- */
- const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite)
- {
- size_t i;
- for (i = 0; i < NUM_TLS_CIPHER_SUITES; i++)
- if (tls_cipher_suites[i].suite == suite)
- return &tls_cipher_suites[i];
- return NULL;
- }
- const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher)
- {
- size_t i;
- for (i = 0; i < NUM_TLS_CIPHER_DATA; i++)
- if (tls_ciphers[i].cipher == cipher)
- return &tls_ciphers[i];
- return NULL;
- }
- int tls_server_key_exchange_allowed(tls_cipher cipher)
- {
- const struct tls_cipher_suite *suite;
- /* RFC 2246, Section 7.4.3 */
- suite = tls_get_cipher_suite(cipher);
- if (suite == NULL)
- return 0;
- switch (suite->key_exchange) {
- case TLS_KEY_X_DHE_DSS:
- case TLS_KEY_X_DHE_DSS_EXPORT:
- case TLS_KEY_X_DHE_RSA:
- case TLS_KEY_X_DHE_RSA_EXPORT:
- case TLS_KEY_X_DH_anon_EXPORT:
- case TLS_KEY_X_DH_anon:
- return 1;
- case TLS_KEY_X_RSA_EXPORT:
- return 1 /* FIX: public key len > 512 bits */;
- default:
- return 0;
- }
- }
- /**
- * tls_parse_cert - Parse DER encoded X.509 certificate and get public key
- * @buf: ASN.1 DER encoded certificate
- * @len: Length of the buffer
- * @pk: Buffer for returning the allocated public key
- * Returns: 0 on success, -1 on failure
- *
- * This functions parses an ASN.1 DER encoded X.509 certificate and retrieves
- * the public key from it. The caller is responsible for freeing the public key
- * by calling crypto_public_key_free().
- */
- int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk)
- {
- struct x509_certificate *cert;
- wpa_hexdump(MSG_MSGDUMP, "TLSv1: Parse ASN.1 DER certificate",
- buf, len);
- *pk = crypto_public_key_from_cert(buf, len);
- if (*pk)
- return 0;
- cert = x509_certificate_parse(buf, len);
- if (cert == NULL) {
- wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse X.509 "
- "certificate");
- return -1;
- }
- /* TODO
- * verify key usage (must allow encryption)
- *
- * All certificate profiles, key and cryptographic formats are
- * defined by the IETF PKIX working group [PKIX]. When a key
- * usage extension is present, the digitalSignature bit must be
- * set for the key to be eligible for signing, as described
- * above, and the keyEncipherment bit must be present to allow
- * encryption, as described above. The keyAgreement bit must be
- * set on Diffie-Hellman certificates. (PKIX: RFC 3280)
- */
- *pk = crypto_public_key_import(cert->public_key, cert->public_key_len);
- x509_certificate_free(cert);
- if (*pk == NULL) {
- wpa_printf(MSG_ERROR, "TLSv1: Failed to import "
- "server public key");
- return -1;
- }
- return 0;
- }
- int tls_verify_hash_init(struct tls_verify_hash *verify)
- {
- tls_verify_hash_free(verify);
- verify->md5_client = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
- verify->md5_server = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
- verify->md5_cert = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
- verify->sha1_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
- verify->sha1_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
- verify->sha1_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
- if (verify->md5_client == NULL || verify->md5_server == NULL ||
- verify->md5_cert == NULL || verify->sha1_client == NULL ||
- verify->sha1_server == NULL || verify->sha1_cert == NULL) {
- tls_verify_hash_free(verify);
- return -1;
- }
- #ifdef CONFIG_TLSV12
- verify->sha256_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL,
- 0);
- verify->sha256_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL,
- 0);
- verify->sha256_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL,
- 0);
- if (verify->sha256_client == NULL || verify->sha256_server == NULL ||
- verify->sha256_cert == NULL) {
- tls_verify_hash_free(verify);
- return -1;
- }
- #endif /* CONFIG_TLSV12 */
- return 0;
- }
- void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf,
- size_t len)
- {
- if (verify->md5_client && verify->sha1_client) {
- crypto_hash_update(verify->md5_client, buf, len);
- crypto_hash_update(verify->sha1_client, buf, len);
- }
- if (verify->md5_server && verify->sha1_server) {
- crypto_hash_update(verify->md5_server, buf, len);
- crypto_hash_update(verify->sha1_server, buf, len);
- }
- if (verify->md5_cert && verify->sha1_cert) {
- crypto_hash_update(verify->md5_cert, buf, len);
- crypto_hash_update(verify->sha1_cert, buf, len);
- }
- #ifdef CONFIG_TLSV12
- if (verify->sha256_client)
- crypto_hash_update(verify->sha256_client, buf, len);
- if (verify->sha256_server)
- crypto_hash_update(verify->sha256_server, buf, len);
- if (verify->sha256_cert)
- crypto_hash_update(verify->sha256_cert, buf, len);
- #endif /* CONFIG_TLSV12 */
- }
- void tls_verify_hash_free(struct tls_verify_hash *verify)
- {
- crypto_hash_finish(verify->md5_client, NULL, NULL);
- crypto_hash_finish(verify->md5_server, NULL, NULL);
- crypto_hash_finish(verify->md5_cert, NULL, NULL);
- crypto_hash_finish(verify->sha1_client, NULL, NULL);
- crypto_hash_finish(verify->sha1_server, NULL, NULL);
- crypto_hash_finish(verify->sha1_cert, NULL, NULL);
- verify->md5_client = NULL;
- verify->md5_server = NULL;
- verify->md5_cert = NULL;
- verify->sha1_client = NULL;
- verify->sha1_server = NULL;
- verify->sha1_cert = NULL;
- #ifdef CONFIG_TLSV12
- crypto_hash_finish(verify->sha256_client, NULL, NULL);
- crypto_hash_finish(verify->sha256_server, NULL, NULL);
- crypto_hash_finish(verify->sha256_cert, NULL, NULL);
- verify->sha256_client = NULL;
- verify->sha256_server = NULL;
- verify->sha256_cert = NULL;
- #endif /* CONFIG_TLSV12 */
- }
- int tls_version_ok(u16 ver)
- {
- if (ver == TLS_VERSION_1)
- return 1;
- #ifdef CONFIG_TLSV11
- if (ver == TLS_VERSION_1_1)
- return 1;
- #endif /* CONFIG_TLSV11 */
- #ifdef CONFIG_TLSV12
- if (ver == TLS_VERSION_1_2)
- return 1;
- #endif /* CONFIG_TLSV12 */
- return 0;
- }
- const char * tls_version_str(u16 ver)
- {
- switch (ver) {
- case TLS_VERSION_1:
- return "1.0";
- case TLS_VERSION_1_1:
- return "1.1";
- case TLS_VERSION_1_2:
- return "1.2";
- }
- return "?";
- }
- int 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)
- {
- #ifdef CONFIG_TLSV12
- if (ver >= TLS_VERSION_1_2) {
- tls_prf_sha256(secret, secret_len, label, seed, seed_len,
- out, outlen);
- return 0;
- }
- #endif /* CONFIG_TLSV12 */
- return tls_prf_sha1_md5(secret, secret_len, label, seed, seed_len, out,
- outlen);
- }
- #ifdef CONFIG_TLSV12
- int tlsv12_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 hlen;
- struct crypto_hash *ctx;
- ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, 0);
- if (ctx == NULL)
- return -1;
- crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
- crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
- crypto_hash_update(ctx, server_params, server_params_len);
- hlen = SHA256_MAC_LEN;
- if (crypto_hash_finish(ctx, hash, &hlen) < 0)
- return -1;
- return hlen;
- }
- #endif /* CONFIG_TLSV12 */
- int 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)
- {
- u8 *hpos;
- size_t hlen;
- struct crypto_hash *ctx;
- hpos = hash;
- ctx = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
- if (ctx == NULL)
- return -1;
- crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
- crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
- crypto_hash_update(ctx, server_params, server_params_len);
- hlen = MD5_MAC_LEN;
- if (crypto_hash_finish(ctx, hash, &hlen) < 0)
- return -1;
- hpos += hlen;
- ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
- if (ctx == NULL)
- return -1;
- crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
- crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
- crypto_hash_update(ctx, server_params, server_params_len);
- hlen = hash + sizeof(hash) - hpos;
- if (crypto_hash_finish(ctx, hpos, &hlen) < 0)
- return -1;
- hpos += hlen;
- return hpos - hash;
- }
- int 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)
- {
- u8 *buf;
- const u8 *end = pos + len;
- const u8 *decrypted;
- u16 slen;
- size_t buflen;
- if (end - pos < 2) {
- *alert = TLS_ALERT_DECODE_ERROR;
- return -1;
- }
- slen = WPA_GET_BE16(pos);
- pos += 2;
- if (end - pos < slen) {
- *alert = TLS_ALERT_DECODE_ERROR;
- return -1;
- }
- if (end - pos > slen) {
- wpa_hexdump(MSG_MSGDUMP, "Additional data after Signature",
- pos + slen, end - pos - slen);
- end = pos + slen;
- }
- wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos);
- if (pk == NULL) {
- wpa_printf(MSG_DEBUG, "TLSv1: No public key to verify signature");
- *alert = TLS_ALERT_INTERNAL_ERROR;
- return -1;
- }
- buflen = end - pos;
- buf = os_malloc(end - pos);
- if (buf == NULL) {
- *alert = TLS_ALERT_INTERNAL_ERROR;
- return -1;
- }
- if (crypto_public_key_decrypt_pkcs1(pk, pos, end - pos, buf, &buflen) <
- 0) {
- wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature");
- os_free(buf);
- *alert = TLS_ALERT_DECRYPT_ERROR;
- return -1;
- }
- decrypted = buf;
- wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature",
- decrypted, buflen);
- #ifdef CONFIG_TLSV12
- if (tls_version >= TLS_VERSION_1_2) {
- /*
- * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5
- *
- * DigestInfo ::= SEQUENCE {
- * digestAlgorithm DigestAlgorithm,
- * digest OCTET STRING
- * }
- *
- * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11}
- *
- * DER encoded DigestInfo for SHA256 per RFC 3447:
- * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 ||
- * H
- */
- if (buflen >= 19 + 32 &&
- os_memcmp(buf, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01"
- "\x65\x03\x04\x02\x01\x05\x00\x04\x20", 19) == 0)
- {
- wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = SHA-256");
- decrypted = buf + 19;
- buflen -= 19;
- } else {
- wpa_printf(MSG_DEBUG, "TLSv1.2: Unrecognized DigestInfo");
- os_free(buf);
- *alert = TLS_ALERT_DECRYPT_ERROR;
- return -1;
- }
- }
- #endif /* CONFIG_TLSV12 */
- if (buflen != data_len ||
- os_memcmp_const(decrypted, data, data_len) != 0) {
- wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in CertificateVerify - did not match calculated hash");
- os_free(buf);
- *alert = TLS_ALERT_DECRYPT_ERROR;
- return -1;
- }
- os_free(buf);
- return 0;
- }
|