diff options
Diffstat (limited to 'src/libcharon/plugins/eap_tls/tls')
21 files changed, 0 insertions, 4522 deletions
diff --git a/src/libcharon/plugins/eap_tls/tls/tls.c b/src/libcharon/plugins/eap_tls/tls/tls.c deleted file mode 100644 index ab03037fa..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "tls.h" - -#include "tls_protection.h" -#include "tls_compression.h" -#include "tls_fragmentation.h" -#include "tls_crypto.h" -#include "tls_server.h" -#include "tls_peer.h" - -#include <daemon.h> - -ENUM_BEGIN(tls_version_names, SSL_2_0, SSL_2_0, - "SSLv2"); -ENUM_NEXT(tls_version_names, SSL_3_0, TLS_1_2, SSL_2_0, - "SSLv3", - "TLS 1.0", - "TLS 1.1", - "TLS 1.2"); -ENUM_END(tls_version_names, TLS_1_2); - -ENUM(tls_content_type_names, TLS_CHANGE_CIPHER_SPEC, TLS_APPLICATION_DATA, - "ChangeCipherSpec", - "Alert", - "Handshake", - "ApplicationData", -); - -ENUM_BEGIN(tls_handshake_type_names, TLS_HELLO_REQUEST, TLS_SERVER_HELLO, - "HelloRequest", - "ClientHello", - "ServerHello"); -ENUM_NEXT(tls_handshake_type_names, TLS_CERTIFICATE, TLS_CLIENT_KEY_EXCHANGE, TLS_SERVER_HELLO, - "Certificate", - "ServerKeyExchange", - "CertificateRequest", - "ServerHelloDone", - "CertificateVerify", - "ClientKeyExchange"); -ENUM_NEXT(tls_handshake_type_names, TLS_FINISHED, TLS_FINISHED, TLS_CLIENT_KEY_EXCHANGE, - "Finished"); -ENUM_END(tls_handshake_type_names, TLS_FINISHED); - - -typedef struct private_tls_t private_tls_t; - -/** - * Private data of an tls_protection_t object. - */ -struct private_tls_t { - - /** - * Public tls_t interface. - */ - tls_t public; - - /** - * Role this TLS stack acts as. - */ - bool is_server; - - /** - * Server identity - */ - identification_t *server; - - /** - * Peer identity - */ - identification_t *peer; - - /** - * Negotiated TLS version - */ - tls_version_t version; - - /** - * TLS record protection layer - */ - tls_protection_t *protection; - - /** - * TLS record compression layer - */ - tls_compression_t *compression; - - /** - * TLS record fragmentation layer - */ - tls_fragmentation_t *fragmentation; - - /** - * TLS crypto helper context - */ - tls_crypto_t *crypto; - - /** - * TLS handshake protocol handler - */ - tls_handshake_t *handshake; -}; - -METHOD(tls_t, process, status_t, - private_tls_t *this, tls_content_type_t type, chunk_t data) -{ - return this->protection->process(this->protection, type, data); -} - -METHOD(tls_t, build, status_t, - private_tls_t *this, tls_content_type_t *type, chunk_t *data) -{ - return this->protection->build(this->protection, type, data); -} - -METHOD(tls_t, is_server, bool, - private_tls_t *this) -{ - return this->is_server; -} - -METHOD(tls_t, get_version, tls_version_t, - private_tls_t *this) -{ - return this->version; -} - -METHOD(tls_t, set_version, void, - private_tls_t *this, tls_version_t version) -{ - this->version = version; -} - -METHOD(tls_t, is_complete, bool, - private_tls_t *this) -{ - return this->crypto->get_eap_msk(this->crypto).len != 0; -} - -METHOD(tls_t, get_eap_msk, chunk_t, - private_tls_t *this) -{ - return this->crypto->get_eap_msk(this->crypto); -} - -METHOD(tls_t, destroy, void, - private_tls_t *this) -{ - this->protection->destroy(this->protection); - this->compression->destroy(this->compression); - this->fragmentation->destroy(this->fragmentation); - this->crypto->destroy(this->crypto); - this->handshake->destroy(this->handshake); - this->peer->destroy(this->peer); - this->server->destroy(this->server); - - free(this); -} - -/** - * See header - */ -tls_t *tls_create(bool is_server, identification_t *server, - identification_t *peer) -{ - private_tls_t *this; - - INIT(this, - .public = { - .process = _process, - .build = _build, - .is_server = _is_server, - .get_version = _get_version, - .set_version = _set_version, - .is_complete = _is_complete, - .get_eap_msk = _get_eap_msk, - .destroy = _destroy, - }, - .is_server = is_server, - .version = TLS_1_2, - .server = server->clone(server), - .peer = peer->clone(peer), - ); - - this->crypto = tls_crypto_create(&this->public); - if (is_server) - { - this->handshake = &tls_server_create(&this->public, this->crypto, - this->server, this->peer)->handshake; - } - else - { - this->handshake = &tls_peer_create(&this->public, this->crypto, - this->peer, this->server)->handshake; - } - this->fragmentation = tls_fragmentation_create(this->handshake); - this->compression = tls_compression_create(this->fragmentation); - this->protection = tls_protection_create(&this->public, this->compression); - this->crypto->set_protection(this->crypto, this->protection); - - return &this->public; -} diff --git a/src/libcharon/plugins/eap_tls/tls/tls.h b/src/libcharon/plugins/eap_tls/tls/tls.h deleted file mode 100644 index 283f591e7..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup tlsgroup tls - * @{ @ingroup eap_tls - * - * @defgroup tls tls - * @{ @ingroup tls - */ - -#ifndef TLS_H_ -#define TLS_H_ - -typedef enum tls_version_t tls_version_t; -typedef enum tls_content_type_t tls_content_type_t; -typedef enum tls_handshake_type_t tls_handshake_type_t; -typedef struct tls_t tls_t; - -#include <library.h> - -/** - * TLS/SSL version numbers - */ -enum tls_version_t { - SSL_2_0 = 0x0200, - SSL_3_0 = 0x0300, - TLS_1_0 = 0x0301, - TLS_1_1 = 0x0302, - TLS_1_2 = 0x0303, -}; - -/** - * Enum names for tls_version_t - */ -extern enum_name_t *tls_version_names; - -/** - * TLS higher level content type - */ -enum tls_content_type_t { - TLS_CHANGE_CIPHER_SPEC = 20, - TLS_ALERT = 21, - TLS_HANDSHAKE = 22, - TLS_APPLICATION_DATA = 23, -}; - -/** - * Enum names for tls_content_type_t - */ -extern enum_name_t *tls_content_type_names; - -/** - * TLS handshake subtype - */ -enum tls_handshake_type_t { - TLS_HELLO_REQUEST = 0, - TLS_CLIENT_HELLO = 1, - TLS_SERVER_HELLO = 2, - TLS_CERTIFICATE = 11, - TLS_SERVER_KEY_EXCHANGE = 12, - TLS_CERTIFICATE_REQUEST = 13, - TLS_SERVER_HELLO_DONE = 14, - TLS_CERTIFICATE_VERIFY = 15, - TLS_CLIENT_KEY_EXCHANGE = 16, - TLS_FINISHED = 20, -}; - -/** - * Enum names for tls_handshake_type_t - */ -extern enum_name_t *tls_handshake_type_names; - -/** - * A bottom-up driven TLS stack, suitable for EAP implementations. - */ -struct tls_t { - - /** - * Process a TLS record, pass it to upper layers. - * - * @param type type of the TLS record to process - * @param data associated TLS record data - * @return - * - SUCCESS if TLS negotiation complete - * - FAILED if TLS handshake failed - * - NEED_MORE if more invocations to process/build needed - */ - status_t (*process)(tls_t *this, tls_content_type_t type, chunk_t data); - - /** - * Query upper layer for TLS record, build protected record. - * - * @param type type of the built TLS record - * @param data allocated data of the built TLS record - * @return - * - SUCCESS if TLS negotiation complete - * - FAILED if TLS handshake failed - * - NEED_MORE if upper layers have more records to send - * - INVALID_STATE if more input records required - */ - status_t (*build)(tls_t *this, tls_content_type_t *type, chunk_t *data); - - /** - * Check if TLS stack is acting as a server. - * - * @return TRUE if server, FALSE if peer - */ - bool (*is_server)(tls_t *this); - - /** - * Get the negotiated TLS/SSL version. - * - * @return negotiated TLS version - */ - tls_version_t (*get_version)(tls_t *this); - - /** - * Set the negotiated TLS/SSL version. - * - * @param version negotiated TLS version - */ - void (*set_version)(tls_t *this, tls_version_t version); - - /** - * Check if TLS negotiation completed successfully. - * - * @return TRUE if TLS negotation and authentication complete - */ - bool (*is_complete)(tls_t *this); - - /** - * Get the MSK for EAP-TLS. - * - * @return MSK, internal data - */ - chunk_t (*get_eap_msk)(tls_t *this); - - /** - * Destroy a tls_t. - */ - void (*destroy)(tls_t *this); -}; - -/** - * Create a tls instance. - * - * @param is_server TRUE to act as server, FALSE for client - * @param server server identity - * @param peer peer identity - * @return TLS stack - */ -tls_t *tls_create(bool is_server, identification_t *server, - identification_t *peer); - -#endif /** TLS_H_ @}*/ diff --git a/src/libcharon/plugins/eap_tls/tls/tls_compression.c b/src/libcharon/plugins/eap_tls/tls/tls_compression.c deleted file mode 100644 index 453558084..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_compression.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "tls_compression.h" - -#include <daemon.h> - -typedef struct private_tls_compression_t private_tls_compression_t; - -/** - * Private data of an tls_compression_t object. - */ -struct private_tls_compression_t { - - /** - * Public tls_compression_t interface. - */ - tls_compression_t public; - - /** - * Upper layer, TLS record fragmentation - */ - tls_fragmentation_t *fragmentation; -}; - -METHOD(tls_compression_t, process, status_t, - private_tls_compression_t *this, tls_content_type_t type, chunk_t data) -{ - return this->fragmentation->process(this->fragmentation, type, data); -} - -METHOD(tls_compression_t, build, status_t, - private_tls_compression_t *this, tls_content_type_t *type, chunk_t *data) -{ - return this->fragmentation->build(this->fragmentation, type, data); -} - -METHOD(tls_compression_t, destroy, void, - private_tls_compression_t *this) -{ - free(this); -} - -/** - * See header - */ -tls_compression_t *tls_compression_create(tls_fragmentation_t *fragmentation) -{ - private_tls_compression_t *this; - - INIT(this, - .public = { - .process = _process, - .build = _build, - .destroy = _destroy, - }, - .fragmentation = fragmentation, - ); - - return &this->public; -} diff --git a/src/libcharon/plugins/eap_tls/tls/tls_compression.h b/src/libcharon/plugins/eap_tls/tls/tls_compression.h deleted file mode 100644 index a61543004..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_compression.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup tls_compression tls_compression - * @{ @ingroup tls - */ - -#ifndef TLS_COMPRESSION_H_ -#define TLS_COMPRESSION_H_ - -typedef struct tls_compression_t tls_compression_t; - -#include <library.h> - -#include "tls.h" -#include "tls_fragmentation.h" - -/** - * TLS record protocol compression layer. - */ -struct tls_compression_t { - - /** - * Process a compressed TLS record, pass it to upper layers. - * - * @param type type of the TLS record to process - * @param data associated TLS record data - * @return - * - SUCCESS if TLS negotiation complete - * - FAILED if TLS handshake failed - * - NEED_MORE if more invocations to process/build needed - */ - status_t (*process)(tls_compression_t *this, - tls_content_type_t type, chunk_t data); - - /** - * Query upper layer for TLS record, build compressed record. - * - * @param type type of the built TLS record - * @param data allocated data of the built TLS record - * @return - * - SUCCESS if TLS negotiation complete - * - FAILED if TLS handshake failed - * - NEED_MORE if upper layers have more records to send - * - INVALID_STATE if more input records required - */ - status_t (*build)(tls_compression_t *this, - tls_content_type_t *type, chunk_t *data); - - /** - * Destroy a tls_compression_t. - */ - void (*destroy)(tls_compression_t *this); -}; - -/** - * Create a tls_compression instance. - * - * @param fragmentation fragmentation layer of TLS stack - * @return TLS compression layer. - */ -tls_compression_t *tls_compression_create(tls_fragmentation_t *fragmentation); - -#endif /** TLS_COMPRESSION_H_ @}*/ diff --git a/src/libcharon/plugins/eap_tls/tls/tls_crypto.c b/src/libcharon/plugins/eap_tls/tls/tls_crypto.c deleted file mode 100644 index f8894629f..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_crypto.c +++ /dev/null @@ -1,691 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "tls_crypto.h" - -#include <daemon.h> - -typedef struct private_tls_crypto_t private_tls_crypto_t; - -/** - * Private data of an tls_crypto_t object. - */ -struct private_tls_crypto_t { - - /** - * Public tls_crypto_t interface. - */ - tls_crypto_t public; - - /** - * Protection layer - */ - tls_protection_t *protection; - - /** - * List of supported/acceptable cipher suites - */ - tls_cipher_suite_t *suites; - - /** - * Number of supported suites - */ - int suite_count; - - /** - * Selected cipher suite - */ - tls_cipher_suite_t suite; - - /** - * TLS context - */ - tls_t *tls; - - /** - * All handshake data concatentated - */ - chunk_t handshake; - - /** - * Connection state TLS PRF - */ - tls_prf_t *prf; - - /** - * Signer instance for inbound traffic - */ - signer_t *signer_in; - - /** - * Signer instance for outbound traffic - */ - signer_t *signer_out; - - /** - * Crypter instance for inbound traffic - */ - crypter_t *crypter_in; - - /** - * Crypter instance for outbound traffic - */ - crypter_t *crypter_out; - - /** - * IV for input decryption, if < TLSv1.2 - */ - chunk_t iv_in; - - /** - * IV for output decryption, if < TLSv1.2 - */ - chunk_t iv_out; - - /** - * EAP-TLS MSK - */ - chunk_t msk; -}; - -typedef struct { - tls_cipher_suite_t suite; - hash_algorithm_t hash; - pseudo_random_function_t prf; - integrity_algorithm_t mac; - encryption_algorithm_t encr; - size_t encr_size; -} suite_algs_t; - -/** - * Mapping suites to a set of algorithms - */ -static suite_algs_t suite_algs[] = { - { TLS_RSA_WITH_NULL_MD5, - HASH_MD5, - PRF_HMAC_MD5, - AUTH_HMAC_MD5_128, - ENCR_NULL, 0 - }, - { TLS_RSA_WITH_NULL_SHA, - HASH_SHA1, - PRF_HMAC_SHA1, - AUTH_HMAC_SHA1_160, - ENCR_NULL, 0 - }, - { TLS_RSA_WITH_NULL_SHA256, - HASH_SHA256, - PRF_HMAC_SHA2_256, - AUTH_HMAC_SHA2_256_256, - ENCR_NULL, 0 - }, - { TLS_RSA_WITH_AES_128_CBC_SHA, - HASH_SHA1, - PRF_HMAC_SHA1, - AUTH_HMAC_SHA1_160, - ENCR_AES_CBC, 16 - }, - { TLS_RSA_WITH_AES_256_CBC_SHA, - HASH_SHA1, - PRF_HMAC_SHA1, - AUTH_HMAC_SHA1_160, - ENCR_AES_CBC, 32 - }, - { TLS_RSA_WITH_3DES_EDE_CBC_SHA, - HASH_SHA1, - PRF_HMAC_SHA1, - AUTH_HMAC_SHA1_160, - ENCR_3DES, 0 - }, - { TLS_RSA_WITH_AES_128_CBC_SHA256, - HASH_SHA256, - PRF_HMAC_SHA2_256, - AUTH_HMAC_SHA2_256_256, - ENCR_AES_CBC, 16 - }, -}; - -/** - * Look up algoritms by a suite - */ -static suite_algs_t *find_suite(tls_cipher_suite_t suite) -{ - int i; - - for (i = 0; i < countof(suite_algs); i++) - { - if (suite_algs[i].suite == suite) - { - return &suite_algs[i]; - } - } - return NULL; -} - -/** - * Initialize the cipher suite list - */ -static void build_cipher_suite_list(private_tls_crypto_t *this) -{ - encryption_algorithm_t encr; - integrity_algorithm_t mac; - enumerator_t *encrs, *macs; - tls_cipher_suite_t supported[64], unique[64]; - int count = 0, i, j; - - /* we assume that we support RSA, but no DHE yet */ - macs = lib->crypto->create_signer_enumerator(lib->crypto); - while (macs->enumerate(macs, &mac)) - { - switch (mac) - { - case AUTH_HMAC_SHA1_160: - supported[count++] = TLS_RSA_WITH_NULL_SHA; - break; - case AUTH_HMAC_SHA2_256_256: - supported[count++] = TLS_RSA_WITH_NULL_SHA256; - break; - case AUTH_HMAC_MD5_128: - supported[count++] = TLS_RSA_WITH_NULL_MD5; - break; - default: - break; - } - encrs = lib->crypto->create_crypter_enumerator(lib->crypto); - while (encrs->enumerate(encrs, &encr)) - { - switch (encr) - { - case ENCR_AES_CBC: - switch (mac) - { - case AUTH_HMAC_SHA1_160: - supported[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; - supported[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; - break; - case AUTH_HMAC_SHA2_256_256: - supported[count++] = TLS_RSA_WITH_AES_128_CBC_SHA256; - supported[count++] = TLS_RSA_WITH_AES_128_CBC_SHA256; - break; - default: - break; - } - break; - case ENCR_3DES: - switch (mac) - { - case AUTH_HMAC_SHA1_160: - supported[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; - break; - default: - break; - } - break; - default: - break; - } - } - encrs->destroy(encrs); - } - macs->destroy(macs); - - /* remove duplicates */ - this->suite_count = 0; - for (i = 0; i < count; i++) - { - bool match = FALSE; - - for (j = 0; j < this->suite_count; j++) - { - if (supported[i] == unique[j]) - { - match = TRUE; - break; - } - } - if (!match) - { - unique[this->suite_count++] = supported[i]; - } - } - free(this->suites); - this->suites = malloc(sizeof(tls_cipher_suite_t) * this->suite_count); - memcpy(this->suites, unique, sizeof(tls_cipher_suite_t) * this->suite_count); -} - -METHOD(tls_crypto_t, get_cipher_suites, int, - private_tls_crypto_t *this, tls_cipher_suite_t **suites) -{ - *suites = this->suites; - return this->suite_count; -} - -/** - * Create crypto primitives - */ -static bool create_ciphers(private_tls_crypto_t *this, tls_cipher_suite_t suite) -{ - suite_algs_t *algs; - - algs = find_suite(suite); - if (!algs) - { - DBG1(DBG_IKE, "selected TLS suite not supported"); - return FALSE; - } - - DESTROY_IF(this->prf); - if (this->tls->get_version(this->tls) < TLS_1_2) - { - this->prf = tls_prf_create_10(); - } - else - { - this->prf = tls_prf_create_12(algs->prf); - } - if (!this->prf) - { - DBG1(DBG_IKE, "selected TLS PRF not supported"); - return FALSE; - } - - DESTROY_IF(this->signer_in); - DESTROY_IF(this->signer_out); - this->signer_in = lib->crypto->create_signer(lib->crypto, algs->mac); - this->signer_out = lib->crypto->create_signer(lib->crypto, algs->mac); - if (!this->signer_in || !this->signer_out) - { - DBG1(DBG_IKE, "selected TLS MAC %N not supported", - integrity_algorithm_names, algs->mac); - return FALSE; - } - - DESTROY_IF(this->crypter_in); - DESTROY_IF(this->crypter_out); - if (algs->encr == ENCR_NULL) - { - this->crypter_in = this->crypter_out = NULL; - } - else - { - this->crypter_in = lib->crypto->create_crypter(lib->crypto, - algs->encr, algs->encr_size); - this->crypter_out = lib->crypto->create_crypter(lib->crypto, - algs->encr, algs->encr_size); - if (!this->crypter_in || !this->crypter_out) - { - DBG1(DBG_IKE, "selected TLS crypter %N not supported", - encryption_algorithm_names, algs->encr); - return FALSE; - } - } - return TRUE; -} - -METHOD(tls_crypto_t, select_cipher_suite, tls_cipher_suite_t, - private_tls_crypto_t *this, tls_cipher_suite_t *suites, int count) -{ - int i, j; - - for (i = 0; i < this->suite_count; i++) - { - for (j = 0; j < count; j++) - { - if (this->suites[i] == suites[j]) - { - if (create_ciphers(this, this->suites[i])) - { - this->suite = this->suites[i]; - return this->suite; - } - } - } - } - return 0; -} - -METHOD(tls_crypto_t, set_protection, void, - private_tls_crypto_t *this, tls_protection_t *protection) -{ - this->protection = protection; -} - -METHOD(tls_crypto_t, append_handshake, void, - private_tls_crypto_t *this, tls_handshake_type_t type, chunk_t data) -{ - u_int32_t header; - - /* reconstruct handshake header */ - header = htonl(data.len | (type << 24)); - this->handshake = chunk_cat("mcc", this->handshake, - chunk_from_thing(header), data); -} - -/** - * Create a hash of the stored handshake data - */ -static bool hash_handshake(private_tls_crypto_t *this, chunk_t *hash) -{ - if (this->tls->get_version(this->tls) >= TLS_1_2) - { - hasher_t *hasher; - suite_algs_t *alg; - - alg = find_suite(this->suite); - if (!alg) - { - return FALSE; - } - hasher = lib->crypto->create_hasher(lib->crypto, alg->hash); - if (!hasher) - { - DBG1(DBG_IKE, "%N not supported", hash_algorithm_names, alg->hash); - return FALSE; - } - hasher->allocate_hash(hasher, this->handshake, hash); - hasher->destroy(hasher); - } - else - { - hasher_t *md5, *sha1; - char buf[HASH_SIZE_MD5 + HASH_SIZE_SHA1]; - - md5 = lib->crypto->create_hasher(lib->crypto, HASH_MD5); - if (!md5) - { - DBG1(DBG_IKE, "%N not supported", hash_algorithm_names, HASH_MD5); - return FALSE; - } - md5->get_hash(md5, this->handshake, buf); - md5->destroy(md5); - sha1 = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); - if (!sha1) - { - DBG1(DBG_IKE, "%N not supported", hash_algorithm_names, HASH_SHA1); - return FALSE; - } - sha1->get_hash(sha1, this->handshake, buf + HASH_SIZE_MD5); - sha1->destroy(sha1); - - *hash = chunk_clone(chunk_from_thing(buf)); - } - return TRUE; -} - -METHOD(tls_crypto_t, sign_handshake, bool, - private_tls_crypto_t *this, private_key_t *key, tls_writer_t *writer) -{ - chunk_t sig, hash; - - if (this->tls->get_version(this->tls) >= TLS_1_2) - { - /* TODO: use supported algorithms instead of fixed SHA1/RSA */ - if (!key->sign(key, SIGN_RSA_EMSA_PKCS1_SHA1, this->handshake, &sig)) - { - return FALSE; - } - writer->write_uint8(writer, 2); - writer->write_uint8(writer, 1); - writer->write_data16(writer, sig); - free(sig.ptr); - } - else - { - if (!hash_handshake(this, &hash)) - { - return FALSE; - } - if (!key->sign(key, SIGN_RSA_EMSA_PKCS1_NULL, hash, &sig)) - { - free(hash.ptr); - return FALSE; - } - writer->write_data16(writer, sig); - free(hash.ptr); - free(sig.ptr); - } - return TRUE; -} - -METHOD(tls_crypto_t, verify_handshake, bool, - private_tls_crypto_t *this, public_key_t *key, tls_reader_t *reader) -{ - if (this->tls->get_version(this->tls) >= TLS_1_2) - { - u_int8_t hash, alg; - chunk_t sig; - - if (!reader->read_uint8(reader, &hash) || - !reader->read_uint8(reader, &alg) || - !reader->read_data16(reader, &sig)) - { - DBG1(DBG_IKE, "received invalid Certificate Verify"); - return FALSE; - } - /* TODO: map received hash/sig alg to signature scheme */ - if (hash != 2 || alg != 1 || - !key->verify(key, SIGN_RSA_EMSA_PKCS1_SHA1, this->handshake, sig)) - { - return FALSE; - } - } - else - { - chunk_t sig, hash; - - if (!reader->read_data16(reader, &sig)) - { - DBG1(DBG_IKE, "received invalid Certificate Verify"); - return FALSE; - } - if (!hash_handshake(this, &hash)) - { - return FALSE; - } - if (!key->verify(key, SIGN_RSA_EMSA_PKCS1_NULL, hash, sig)) - { - free(hash.ptr); - return FALSE; - } - free(hash.ptr); - } - return TRUE; -} - -METHOD(tls_crypto_t, calculate_finished, bool, - private_tls_crypto_t *this, char *label, char out[12]) -{ - chunk_t seed; - - if (!this->prf) - { - return FALSE; - } - if (!hash_handshake(this, &seed)) - { - return FALSE; - } - this->prf->get_bytes(this->prf, label, seed, 12, out); - free(seed.ptr); - return TRUE; -} - -METHOD(tls_crypto_t, derive_secrets, void, - private_tls_crypto_t *this, chunk_t premaster, - chunk_t client_random, chunk_t server_random) -{ - char master[48]; - chunk_t seed, block, client_write, server_write; - int mks, eks = 0, ivs = 0; - - /* derive master secret */ - seed = chunk_cata("cc", client_random, server_random); - this->prf->set_key(this->prf, premaster); - this->prf->get_bytes(this->prf, "master secret", seed, - sizeof(master), master); - - this->prf->set_key(this->prf, chunk_from_thing(master)); - memset(master, 0, sizeof(master)); - - /* derive key block for key expansion */ - mks = this->signer_out->get_key_size(this->signer_out); - if (this->crypter_out) - { - eks = this->crypter_out->get_key_size(this->crypter_out); - if (this->tls->get_version(this->tls) < TLS_1_1) - { - ivs = this->crypter_out->get_block_size(this->crypter_out); - } - } - seed = chunk_cata("cc", server_random, client_random); - block = chunk_alloca((mks + eks + ivs) * 2); - this->prf->get_bytes(this->prf, "key expansion", seed, block.len, block.ptr); - - /* signer keys */ - client_write = chunk_create(block.ptr, mks); - block = chunk_skip(block, mks); - server_write = chunk_create(block.ptr, mks); - block = chunk_skip(block, mks); - if (this->tls->is_server(this->tls)) - { - this->signer_in->set_key(this->signer_in, client_write); - this->signer_out->set_key(this->signer_out, server_write); - } - else - { - this->signer_out->set_key(this->signer_out, client_write); - this->signer_in->set_key(this->signer_in, server_write); - } - - /* crypter keys, and IVs if < TLSv1.2 */ - if (this->crypter_out && this->crypter_in) - { - client_write = chunk_create(block.ptr, eks); - block = chunk_skip(block, eks); - server_write = chunk_create(block.ptr, eks); - block = chunk_skip(block, eks); - - if (this->tls->is_server(this->tls)) - { - this->crypter_in->set_key(this->crypter_in, client_write); - this->crypter_out->set_key(this->crypter_out, server_write); - } - else - { - this->crypter_out->set_key(this->crypter_out, client_write); - this->crypter_in->set_key(this->crypter_in, server_write); - } - if (ivs) - { - client_write = chunk_create(block.ptr, ivs); - block = chunk_skip(block, ivs); - server_write = chunk_create(block.ptr, ivs); - block = chunk_skip(block, ivs); - - if (this->tls->is_server(this->tls)) - { - this->iv_in = chunk_clone(client_write); - this->iv_out = chunk_clone(server_write); - } - else - { - this->iv_out = chunk_clone(client_write); - this->iv_in = chunk_clone(server_write); - } - } - } -} - -METHOD(tls_crypto_t, change_cipher, void, - private_tls_crypto_t *this, bool inbound) -{ - if (this->protection) - { - if (inbound) - { - this->protection->set_cipher(this->protection, TRUE, - this->signer_in, this->crypter_in, this->iv_in); - } - else - { - this->protection->set_cipher(this->protection, FALSE, - this->signer_out, this->crypter_out, this->iv_out); - } - } -} - -METHOD(tls_crypto_t, derive_eap_msk, void, - private_tls_crypto_t *this, chunk_t client_random, chunk_t server_random) -{ - chunk_t seed; - - seed = chunk_cata("cc", client_random, server_random); - free(this->msk.ptr); - this->msk = chunk_alloc(64); - this->prf->get_bytes(this->prf, "client EAP encryption", seed, - this->msk.len, this->msk.ptr); -} - -METHOD(tls_crypto_t, get_eap_msk, chunk_t, - private_tls_crypto_t *this) -{ - return this->msk; -} - -METHOD(tls_crypto_t, destroy, void, - private_tls_crypto_t *this) -{ - DESTROY_IF(this->signer_in); - DESTROY_IF(this->signer_out); - DESTROY_IF(this->crypter_in); - DESTROY_IF(this->crypter_out); - free(this->iv_in.ptr); - free(this->iv_out.ptr); - free(this->handshake.ptr); - free(this->msk.ptr); - DESTROY_IF(this->prf); - free(this->suites); - free(this); -} - -/** - * See header - */ -tls_crypto_t *tls_crypto_create(tls_t *tls) -{ - private_tls_crypto_t *this; - - INIT(this, - .public = { - .get_cipher_suites = _get_cipher_suites, - .select_cipher_suite = _select_cipher_suite, - .set_protection = _set_protection, - .append_handshake = _append_handshake, - .sign_handshake = _sign_handshake, - .verify_handshake = _verify_handshake, - .calculate_finished = _calculate_finished, - .derive_secrets = _derive_secrets, - .change_cipher = _change_cipher, - .derive_eap_msk = _derive_eap_msk, - .get_eap_msk = _get_eap_msk, - .destroy = _destroy, - }, - .tls = tls, - ); - - build_cipher_suite_list(this); - - return &this->public; -} diff --git a/src/libcharon/plugins/eap_tls/tls/tls_crypto.h b/src/libcharon/plugins/eap_tls/tls/tls_crypto.h deleted file mode 100644 index 69b8da742..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_crypto.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup tls_crypto tls_crypto - * @{ @ingroup tls - */ - -#ifndef TLS_CRYPTO_H_ -#define TLS_CRYPTO_H_ - -typedef struct tls_crypto_t tls_crypto_t; -typedef enum tls_cipher_suite_t tls_cipher_suite_t; - -#include "tls.h" -#include "tls_prf.h" -#include "tls_protection.h" - -#include <credentials/keys/private_key.h> - -/** - * TLS cipher suites - */ -enum tls_cipher_suite_t { - TLS_NULL_WITH_NULL_NULL = 0x00, - TLS_RSA_WITH_NULL_MD5 = 0x01, - TLS_RSA_WITH_NULL_SHA = 0x02, - TLS_RSA_WITH_NULL_SHA256 = 0x3B, - TLS_RSA_WITH_RC4_128_MD5 = 0x04, - TLS_RSA_WITH_RC4_128_SHA = 0x05, - TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x0A, - TLS_RSA_WITH_AES_128_CBC_SHA = 0x2F, - TLS_RSA_WITH_AES_256_CBC_SHA = 0x35, - TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x3C, - TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x3D, - TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x0D, - TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x10, - TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x13, - TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x16, - TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x30, - TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x31, - TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x32, - TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x33, - TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x36, - TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x37, - TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x38, - TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x39, - TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x3E, - TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x3F, - TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x40, - TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x67, - TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x68, - TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x69, - TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x6A, - TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x6B, - TLS_DH_ANON_WITH_RC4_128_MD5 = 0x18, - TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA = 0x1B, - TLS_DH_ANON_WITH_AES_128_CBC_SHA = 0x34, - TLS_DH_ANON_WITH_AES_256_CBC_SHA = 0x3A, - TLS_DH_ANON_WITH_AES_128_CBC_SHA256 = 0x6C, - TLS_DH_ANON_WITH_AES_256_CBC_SHA256 = 0x6D, -}; - -/** - * TLS crypto helper functions. - */ -struct tls_crypto_t { - - /** - * Get a list of supported TLS cipher suites. - * - * @param suites list of suites, points to internal data - * @return number of suites returned - */ - int (*get_cipher_suites)(tls_crypto_t *this, tls_cipher_suite_t **suites); - - /** - * Select and store a cipher suite from a given list of candidates. - * - * @param suites list of candidates to select from - * @param count number of suites - * @return selected suite, 0 if none acceptable - */ - tls_cipher_suite_t (*select_cipher_suite)(tls_crypto_t *this, - tls_cipher_suite_t *suites, int count); - - /** - * Set the protection layer of the TLS stack to control it. - * - * @param protection protection layer to work on - */ - void (*set_protection)(tls_crypto_t *this, tls_protection_t *protection); - - /** - * Store exchanged handshake data, used for cryptographic operations. - * - * @param type handshake sub type - * @param data data to append to handshake buffer - */ - void (*append_handshake)(tls_crypto_t *this, - tls_handshake_type_t type, chunk_t data); - - /** - * Create a signature of the handshake data using a given private key. - * - * @param key private key to use for signature - * @param writer TLS writer to write signature to - * @return TRUE if signature create successfully - */ - bool (*sign_handshake)(tls_crypto_t *this, private_key_t *key, - tls_writer_t *writer); - - /** - * Verify the signature over handshake data using a given public key. - * - * @param key public key to verify signature with - * @param reader TLS reader to read signature from - * @return TRUE if signature valid - */ - bool (*verify_handshake)(tls_crypto_t *this, public_key_t *key, - tls_reader_t *reader); - - /** - * Calculate the data of a TLS finished message. - * - * @param label ASCII label to use for calculation - * @param out buffer to write finished data to - * @return TRUE if calculation successful - */ - bool (*calculate_finished)(tls_crypto_t *this, char *label, char out[12]); - - /** - * Derive the master secret, MAC and encryption keys. - * - * @param premaster premaster secret - * @param client_random random data from client hello - * @param server_random random data from server hello - */ - void (*derive_secrets)(tls_crypto_t *this, chunk_t premaster, - chunk_t client_random, chunk_t server_random); - - /** - * Change the cipher used at protection layer. - * - * @param inbound TRUE to change inbound cipher, FALSE for outbound - */ - void (*change_cipher)(tls_crypto_t *this, bool inbound); - - /** - * Derive the EAP-TLS MSK. - * - * @param client_random random data from client hello - * @param server_random random data from server hello - */ - void (*derive_eap_msk)(tls_crypto_t *this, - chunk_t client_random, chunk_t server_random); - - /** - * Get the MSK to use in EAP-TLS. - * - * @return MSK, points to internal data - */ - chunk_t (*get_eap_msk)(tls_crypto_t *this); - - /** - * Destroy a tls_crypto_t. - */ - void (*destroy)(tls_crypto_t *this); -}; - -/** - * Create a tls_crypto instance. - */ -tls_crypto_t *tls_crypto_create(tls_t *tls); - -#endif /** TLS_CRYPTO_H_ @}*/ diff --git a/src/libcharon/plugins/eap_tls/tls/tls_fragmentation.c b/src/libcharon/plugins/eap_tls/tls/tls_fragmentation.c deleted file mode 100644 index 7a99c9235..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_fragmentation.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "tls_fragmentation.h" - -#include "tls_reader.h" - -#include <daemon.h> - -typedef struct private_tls_fragmentation_t private_tls_fragmentation_t; - -/** - * Private data of an tls_fragmentation_t object. - */ -struct private_tls_fragmentation_t { - - /** - * Public tls_fragmentation_t interface. - */ - tls_fragmentation_t public; - - /** - * Upper layer handshake protocol - */ - tls_handshake_t *handshake; - - /** - * Handshake input buffer - */ - chunk_t input; - - /** - * Position in input buffer - */ - size_t inpos; - - /** - * Currently processed handshake message type - */ - tls_handshake_type_t type; - - /** - * Handshake output buffer - */ - chunk_t output; -}; - -/** - * Maximum size of a TLS fragment - */ -#define MAX_TLS_FRAGMENT_LEN 16384 - -/** - * Maximum size of a TLS handshake message we accept - */ -#define MAX_TLS_HANDSHAKE_LEN 65536 - -/** - * Process TLS handshake protocol data - */ -static status_t process_handshake(private_tls_fragmentation_t *this, - tls_reader_t *reader) -{ - while (reader->remaining(reader)) - { - tls_reader_t *msg; - u_int8_t type; - u_int32_t len; - status_t status; - chunk_t data; - - if (reader->remaining(reader) > MAX_TLS_FRAGMENT_LEN) - { - DBG1(DBG_IKE, "TLS fragment has invalid length"); - return FAILED; - } - - if (this->input.len == 0) - { /* new handshake message */ - if (!reader->read_uint8(reader, &type) || - !reader->read_uint24(reader, &len)) - { - return FAILED; - } - this->type = type; - if (len > MAX_TLS_HANDSHAKE_LEN) - { - DBG1(DBG_IKE, "TLS handshake message exceeds maximum length"); - return FAILED; - } - chunk_free(&this->input); - this->inpos = 0; - if (len) - { - this->input = chunk_alloc(len); - } - } - - len = min(this->input.len - this->inpos, reader->remaining(reader)); - if (!reader->read_data(reader, len, &data)) - { - return FAILED; - } - memcpy(this->input.ptr + this->inpos, data.ptr, len); - this->inpos += len; - - if (this->input.len == this->inpos) - { /* message completely defragmented, process */ - msg = tls_reader_create(this->input); - status = this->handshake->process(this->handshake, this->type, msg); - msg->destroy(msg); - chunk_free(&this->input); - if (status != NEED_MORE) - { - return status; - } - } - } - return NEED_MORE; -} - -METHOD(tls_fragmentation_t, process, status_t, - private_tls_fragmentation_t *this, tls_content_type_t type, chunk_t data) -{ - tls_reader_t *reader; - status_t status; - - reader = tls_reader_create(data); - switch (type) - { - case TLS_CHANGE_CIPHER_SPEC: - if (this->handshake->change_cipherspec(this->handshake)) - { - status = NEED_MORE; - break; - } - status = FAILED; - break; - case TLS_ALERT: - /* TODO: handle Alert */ - status = FAILED; - break; - case TLS_HANDSHAKE: - status = process_handshake(this, reader); - break; - case TLS_APPLICATION_DATA: - /* skip application data */ - status = NEED_MORE; - break; - default: - DBG1(DBG_IKE, "received unknown TLS content type %d, ignored", type); - status = NEED_MORE; - break; - } - reader->destroy(reader); - return status; -} - -METHOD(tls_fragmentation_t, build, status_t, - private_tls_fragmentation_t *this, tls_content_type_t *type, chunk_t *data) -{ - tls_handshake_type_t hs_type; - tls_writer_t *writer, *msg; - status_t status; - - if (this->handshake->cipherspec_changed(this->handshake)) - { - *type = TLS_CHANGE_CIPHER_SPEC; - *data = chunk_clone(chunk_from_chars(0x01)); - return NEED_MORE; - } - - if (!this->output.len) - { - msg = tls_writer_create(64); - do - { - writer = tls_writer_create(64); - status = this->handshake->build(this->handshake, &hs_type, writer); - switch (status) - { - case NEED_MORE: - msg->write_uint8(msg, hs_type); - msg->write_data24(msg, writer->get_buf(writer)); - break; - case INVALID_STATE: - this->output = chunk_clone(msg->get_buf(msg)); - break; - default: - break; - } - writer->destroy(writer); - } - while (status == NEED_MORE); - - msg->destroy(msg); - if (status != INVALID_STATE) - { - return status; - } - } - - if (this->output.len) - { - *type = TLS_HANDSHAKE; - if (this->output.len <= MAX_TLS_FRAGMENT_LEN) - { - *data = this->output; - this->output = chunk_empty; - return NEED_MORE; - } - *data = chunk_create(this->output.ptr, MAX_TLS_FRAGMENT_LEN); - this->output = chunk_clone(chunk_skip(this->output, MAX_TLS_FRAGMENT_LEN)); - return NEED_MORE; - } - return status; -} - -METHOD(tls_fragmentation_t, destroy, void, - private_tls_fragmentation_t *this) -{ - free(this->input.ptr); - free(this->output.ptr); - free(this); -} - -/** - * See header - */ -tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake) -{ - private_tls_fragmentation_t *this; - - INIT(this, - .public = { - .process = _process, - .build = _build, - .destroy = _destroy, - }, - .handshake = handshake, - ); - - return &this->public; -} diff --git a/src/libcharon/plugins/eap_tls/tls/tls_fragmentation.h b/src/libcharon/plugins/eap_tls/tls/tls_fragmentation.h deleted file mode 100644 index 61bf5488e..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_fragmentation.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup tls_fragmentation tls_fragmentation - * @{ @ingroup tls - */ - -#ifndef TLS_FRAGMENTATION_H_ -#define TLS_FRAGMENTATION_H_ - -typedef struct tls_fragmentation_t tls_fragmentation_t; - -#include <library.h> - -#include "tls.h" -#include "tls_handshake.h" - -/** - * TLS record protocol fragmentation layer. - */ -struct tls_fragmentation_t { - - /** - * Process a fragmented TLS record, pass it to upper layers. - * - * @param type type of the TLS record to process - * @param data associated TLS record data - * @return - * - SUCCESS if TLS negotiation complete - * - FAILED if TLS handshake failed - * - NEED_MORE if more invocations to process/build needed - */ - status_t (*process)(tls_fragmentation_t *this, - tls_content_type_t type, chunk_t data); - - /** - * Query upper layer for TLS messages, build fragmented records. - * - * @param type type of the built TLS record - * @param data allocated data of the built TLS record - * @return - * - SUCCESS if TLS negotiation complete - * - FAILED if TLS handshake failed - * - NEED_MORE if upper layers have more records to send - * - INVALID_STATE if more input records required - */ - status_t (*build)(tls_fragmentation_t *this, - tls_content_type_t *type, chunk_t *data); - - /** - * Destroy a tls_fragmentation_t. - */ - void (*destroy)(tls_fragmentation_t *this); -}; - -/** - * Create a tls_fragmentation instance. - * - * @param handshake upper layer handshake protocol - * @return TLS fragmentation layer. - */ -tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake); - -#endif /** TLS_FRAGMENTATION_H_ @}*/ diff --git a/src/libcharon/plugins/eap_tls/tls/tls_handshake.h b/src/libcharon/plugins/eap_tls/tls/tls_handshake.h deleted file mode 100644 index 113974042..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_handshake.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup tls_handshake tls_handshake - * @{ @ingroup tls - */ - -#ifndef TLS_HANDSHAKE_H_ -#define TLS_HANDSHAKE_H_ - -typedef struct tls_handshake_t tls_handshake_t; - -#include "tls.h" -#include "tls_reader.h" -#include "tls_writer.h" - -/** - * TLS handshake state machine interface. - */ -struct tls_handshake_t { - - /** - * Process received TLS handshake message. - * - * @param type TLS handshake message type - * @param reader TLS data buffer - * @return - * - SUCCESS if handshake complete - * - FAILED if handshake failed - * - NEED_MORE if another invocation of process/build needed - */ - status_t (*process)(tls_handshake_t *this, - tls_handshake_type_t type, tls_reader_t *reader); - - /** - * Build TLS handshake messages to send out. - * - * @param type type of created handshake message - * @param writer TLS data buffer to write to - * @return - * - SUCCESS if handshake complete - * - FAILED if handshake failed - * - NEED_MORE if more messages ready for delivery - * - INVALID_STATE if more input to process() required - */ - status_t (*build)(tls_handshake_t *this, - tls_handshake_type_t *type, tls_writer_t *writer); - - /** - * Check if the cipher spec for outgoing messages has changed. - * - * @return TRUE if cipher spec changed - */ - bool (*cipherspec_changed)(tls_handshake_t *this); - - /** - * Change the cipher spec for incoming messages. - * - * @return TRUE if cipher spec changed - */ - bool (*change_cipherspec)(tls_handshake_t *this); - - /** - * Destroy a tls_handshake_t. - */ - void (*destroy)(tls_handshake_t *this); -}; - -#endif /** TLS_HANDSHAKE_H_ @}*/ diff --git a/src/libcharon/plugins/eap_tls/tls/tls_peer.c b/src/libcharon/plugins/eap_tls/tls/tls_peer.c deleted file mode 100644 index 95973598b..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_peer.c +++ /dev/null @@ -1,625 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "tls_peer.h" - -#include <daemon.h> - -#include <time.h> - -typedef struct private_tls_peer_t private_tls_peer_t; - -typedef enum { - STATE_INIT, - STATE_HELLO_SENT, - STATE_HELLO_RECEIVED, - STATE_HELLO_DONE, - STATE_CERT_SENT, - STATE_CERT_RECEIVED, - STATE_CERTREQ_RECEIVED, - STATE_KEY_EXCHANGE_SENT, - STATE_VERIFY_SENT, - STATE_CIPHERSPEC_CHANGED_OUT, - STATE_FINISHED_SENT, - STATE_CIPHERSPEC_CHANGED_IN, - STATE_COMPLETE, -} peer_state_t; - -/** - * Private data of an tls_peer_t object. - */ -struct private_tls_peer_t { - - /** - * Public tls_peer_t interface. - */ - tls_peer_t public; - - /** - * TLS stack - */ - tls_t *tls; - - /** - * TLS crypto context - */ - tls_crypto_t *crypto; - - /** - * Peer identity - */ - identification_t *peer; - - /** - * Server identity - */ - identification_t *server; - - /** - * State we are in - */ - peer_state_t state; - - /** - * Hello random data selected by client - */ - char client_random[32]; - - /** - * Hello random data selected by server - */ - char server_random[32]; - - /** - * Auth helper for peer authentication - */ - auth_cfg_t *peer_auth; - - /** - * Auth helper for server authentication - */ - auth_cfg_t *server_auth; - - /** - * Peer private key - */ - private_key_t *private; -}; - -/** - * Process a server hello message - */ -static status_t process_server_hello(private_tls_peer_t *this, - tls_reader_t *reader) -{ - u_int8_t compression; - u_int16_t version, cipher; - chunk_t random, session, ext = chunk_empty; - tls_cipher_suite_t suite; - - this->crypto->append_handshake(this->crypto, - TLS_SERVER_HELLO, reader->peek(reader)); - - if (!reader->read_uint16(reader, &version) || - !reader->read_data(reader, sizeof(this->server_random), &random) || - !reader->read_data8(reader, &session) || - !reader->read_uint16(reader, &cipher) || - !reader->read_uint8(reader, &compression) || - (reader->remaining(reader) && !reader->read_data16(reader, &ext))) - { - DBG1(DBG_IKE, "received invalid ServerHello"); - return FAILED; - } - - memcpy(this->server_random, random.ptr, sizeof(this->server_random)); - - if (version < this->tls->get_version(this->tls)) - { - this->tls->set_version(this->tls, version); - } - suite = cipher; - if (!this->crypto->select_cipher_suite(this->crypto, &suite, 1)) - { - DBG1(DBG_IKE, "received cipher suite inacceptable"); - return FAILED; - } - this->state = STATE_HELLO_RECEIVED; - return NEED_MORE; -} - -/** - * Process a Certificate message - */ -static status_t process_certificate(private_tls_peer_t *this, - tls_reader_t *reader) -{ - certificate_t *cert; - tls_reader_t *certs; - chunk_t data; - bool first = TRUE; - - this->crypto->append_handshake(this->crypto, - TLS_CERTIFICATE, reader->peek(reader)); - - if (!reader->read_data24(reader, &data)) - { - return FAILED; - } - certs = tls_reader_create(data); - while (certs->remaining(certs)) - { - if (!certs->read_data24(certs, &data)) - { - certs->destroy(certs); - return FAILED; - } - cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, - BUILD_BLOB_ASN1_DER, data, BUILD_END); - if (cert) - { - if (first) - { - this->server_auth->add(this->server_auth, - AUTH_HELPER_SUBJECT_CERT, cert); - DBG1(DBG_IKE, "received TLS server certificate '%Y'", - cert->get_subject(cert)); - first = FALSE; - } - else - { - DBG1(DBG_IKE, "received TLS intermediate certificate '%Y'", - cert->get_subject(cert)); - this->server_auth->add(this->server_auth, - AUTH_HELPER_IM_CERT, cert); - } - } - else - { - DBG1(DBG_IKE, "parsing TLS certificate failed, skipped"); - } - } - certs->destroy(certs); - this->state = STATE_CERT_RECEIVED; - return NEED_MORE; -} - -/** - * Process a Certificate message - */ -static status_t process_certreq(private_tls_peer_t *this, tls_reader_t *reader) -{ - chunk_t types, hashsig, data; - tls_reader_t *authorities; - identification_t *id; - certificate_t *cert; - - this->crypto->append_handshake(this->crypto, - TLS_CERTIFICATE_REQUEST, reader->peek(reader)); - - if (!reader->read_data8(reader, &types)) - { - return FAILED; - } - if (this->tls->get_version(this->tls) >= TLS_1_2) - { - if (!reader->read_data16(reader, &hashsig)) - { - return FAILED; - } - /* TODO: store supported hashsig algorithms */ - } - if (!reader->read_data16(reader, &data)) - { - return FAILED; - } - authorities = tls_reader_create(data); - while (authorities->remaining(authorities)) - { - if (!authorities->read_data16(authorities, &data)) - { - authorities->destroy(authorities); - return FAILED; - } - id = identification_create_from_encoding(ID_DER_ASN1_DN, data); - cert = lib->credmgr->get_cert(lib->credmgr, - CERT_X509, KEY_ANY, id, TRUE); - if (cert) - { - DBG1(DBG_IKE, "received cert request for '%Y", id); - this->peer_auth->add(this->peer_auth, AUTH_RULE_CA_CERT, cert); - } - else - { - DBG1(DBG_IKE, "received cert request for unknown CA '%Y'", id); - } - id->destroy(id); - } - authorities->destroy(authorities); - this->state = STATE_CERTREQ_RECEIVED; - return NEED_MORE; -} - -/** - * Process Hello Done message - */ -static status_t process_hello_done(private_tls_peer_t *this, - tls_reader_t *reader) -{ - this->crypto->append_handshake(this->crypto, - TLS_SERVER_HELLO_DONE, reader->peek(reader)); - this->state = STATE_HELLO_DONE; - return NEED_MORE; -} - -/** - * Process finished message - */ -static status_t process_finished(private_tls_peer_t *this, tls_reader_t *reader) -{ - chunk_t received; - char buf[12]; - - if (!reader->read_data(reader, sizeof(buf), &received)) - { - DBG1(DBG_IKE, "received server finished too short"); - return FAILED; - } - if (!this->crypto->calculate_finished(this->crypto, "server finished", buf)) - { - DBG1(DBG_IKE, "calculating server finished failed"); - return FAILED; - } - if (!chunk_equals(received, chunk_from_thing(buf))) - { - DBG1(DBG_IKE, "received server finished invalid"); - return FAILED; - } - this->state = STATE_COMPLETE; - this->crypto->derive_eap_msk(this->crypto, - chunk_from_thing(this->client_random), - chunk_from_thing(this->server_random)); - return NEED_MORE; -} - -METHOD(tls_handshake_t, process, status_t, - private_tls_peer_t *this, tls_handshake_type_t type, tls_reader_t *reader) -{ - tls_handshake_type_t expected; - - switch (this->state) - { - case STATE_HELLO_SENT: - if (type == TLS_SERVER_HELLO) - { - return process_server_hello(this, reader); - } - expected = TLS_SERVER_HELLO; - break; - case STATE_HELLO_RECEIVED: - if (type == TLS_CERTIFICATE) - { - return process_certificate(this, reader); - } - expected = TLS_CERTIFICATE; - break; - case STATE_CERT_RECEIVED: - if (type == TLS_CERTIFICATE_REQUEST) - { - return process_certreq(this, reader); - } - expected = TLS_CERTIFICATE_REQUEST; - break; - case STATE_CERTREQ_RECEIVED: - if (type == TLS_SERVER_HELLO_DONE) - { - return process_hello_done(this, reader); - } - expected = TLS_SERVER_HELLO_DONE; - break; - case STATE_CIPHERSPEC_CHANGED_IN: - if (type == TLS_FINISHED) - { - return process_finished(this, reader); - } - expected = TLS_FINISHED; - break; - default: - DBG1(DBG_IKE, "TLS %N not expected in current state", - tls_handshake_type_names, type); - return FAILED; - } - DBG1(DBG_IKE, "TLS %N expected, but received %N", - tls_handshake_type_names, expected, tls_handshake_type_names, type); - return FAILED; -} - -/** - * Send a client hello - */ -static status_t send_client_hello(private_tls_peer_t *this, - tls_handshake_type_t *type, tls_writer_t *writer) -{ - tls_cipher_suite_t *suite; - int count, i; - rng_t *rng; - - htoun32(&this->client_random, time(NULL)); - rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); - if (!rng) - { - return FAILED; - } - rng->get_bytes(rng, sizeof(this->client_random) - 4, this->client_random + 4); - rng->destroy(rng); - - writer->write_uint16(writer, this->tls->get_version(this->tls)); - writer->write_data(writer, chunk_from_thing(this->client_random)); - /* session identifier => none */ - writer->write_data8(writer, chunk_empty); - - count = this->crypto->get_cipher_suites(this->crypto, &suite); - writer->write_uint16(writer, count * 2); - for (i = 0; i < count; i++) - { - writer->write_uint16(writer, suite[i]); - } - /* NULL compression only */ - writer->write_uint8(writer, 1); - writer->write_uint8(writer, 0); - - *type = TLS_CLIENT_HELLO; - this->state = STATE_HELLO_SENT; - this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); - return NEED_MORE; -} - -/** - * Send Certificate - */ -static status_t send_certificate(private_tls_peer_t *this, - tls_handshake_type_t *type, tls_writer_t *writer) -{ - enumerator_t *enumerator; - certificate_t *cert; - auth_rule_t rule; - tls_writer_t *certs; - chunk_t data; - - this->private = lib->credmgr->get_private(lib->credmgr, - KEY_ANY, this->peer, this->peer_auth); - if (!this->private) - { - DBG1(DBG_IKE, "no TLS peer certificate found for '%Y'", this->peer); - return FAILED; - } - - /* generate certificate payload */ - certs = tls_writer_create(256); - cert = this->peer_auth->get(this->peer_auth, AUTH_RULE_SUBJECT_CERT); - if (cert) - { - if (cert->get_encoding(cert, CERT_ASN1_DER, &data)) - { - DBG1(DBG_IKE, "sending TLS peer certificate '%Y'", - cert->get_subject(cert)); - certs->write_data24(certs, data); - free(data.ptr); - } - } - enumerator = this->peer_auth->create_enumerator(this->peer_auth); - while (enumerator->enumerate(enumerator, &rule, &cert)) - { - if (rule == AUTH_RULE_IM_CERT) - { - if (cert->get_encoding(cert, CERT_ASN1_DER, &data)) - { - DBG1(DBG_IKE, "sending TLS intermediate certificate '%Y'", - cert->get_subject(cert)); - certs->write_data24(certs, data); - free(data.ptr); - } - } - } - enumerator->destroy(enumerator); - - writer->write_data24(writer, certs->get_buf(certs)); - certs->destroy(certs); - - *type = TLS_CERTIFICATE; - this->state = STATE_CERT_SENT; - this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); - return NEED_MORE; -} - -/** - * Send client key exchange - */ -static status_t send_key_exchange(private_tls_peer_t *this, - tls_handshake_type_t *type, tls_writer_t *writer) -{ - public_key_t *public = NULL, *current; - enumerator_t *enumerator; - auth_cfg_t *auth; - rng_t *rng; - char premaster[48]; - chunk_t encrypted; - - rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); - if (!rng) - { - DBG1(DBG_IKE, "no suitable RNG found for TLS premaster secret"); - return FAILED; - } - rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2); - rng->destroy(rng); - htoun16(premaster, TLS_1_2); - - this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster), - chunk_from_thing(this->client_random), - chunk_from_thing(this->server_random)); - - enumerator = lib->credmgr->create_public_enumerator(lib->credmgr, - KEY_ANY, this->server, this->server_auth); - while (enumerator->enumerate(enumerator, ¤t, &auth)) - { - public = current->get_ref(current); - break; - } - enumerator->destroy(enumerator); - - if (!public) - { - DBG1(DBG_IKE, "no TLS public key found for server '%Y'", this->server); - return FAILED; - } - if (!public->encrypt(public, chunk_from_thing(premaster), &encrypted)) - { - public->destroy(public); - DBG1(DBG_IKE, "encrypting TLS premaster secret failed"); - return FAILED; - } - - public->destroy(public); - - writer->write_data16(writer, encrypted); - free(encrypted.ptr); - - *type = TLS_CLIENT_KEY_EXCHANGE; - this->state = STATE_KEY_EXCHANGE_SENT; - this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); - return NEED_MORE; -} - -/** - * Send certificate verify - */ -static status_t send_certificate_verify(private_tls_peer_t *this, - tls_handshake_type_t *type, tls_writer_t *writer) -{ - if (!this->private || - !this->crypto->sign_handshake(this->crypto, this->private, writer)) - { - DBG1(DBG_IKE, "creating TLS Certificate Verify signature failed"); - return FAILED; - } - - *type = TLS_CERTIFICATE_VERIFY; - this->state = STATE_VERIFY_SENT; - this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); - return NEED_MORE; -} - -/** - * Send Finished - */ -static status_t send_finished(private_tls_peer_t *this, - tls_handshake_type_t *type, tls_writer_t *writer) -{ - char buf[12]; - - if (!this->crypto->calculate_finished(this->crypto, "client finished", buf)) - { - DBG1(DBG_IKE, "calculating client finished data failed"); - return FAILED; - } - - writer->write_data(writer, chunk_from_thing(buf)); - - *type = TLS_FINISHED; - this->state = STATE_FINISHED_SENT; - this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); - return NEED_MORE; -} - -METHOD(tls_handshake_t, build, status_t, - private_tls_peer_t *this, tls_handshake_type_t *type, tls_writer_t *writer) -{ - switch (this->state) - { - case STATE_INIT: - return send_client_hello(this, type, writer); - case STATE_HELLO_DONE: - return send_certificate(this, type, writer); - case STATE_CERT_SENT: - return send_key_exchange(this, type, writer); - case STATE_KEY_EXCHANGE_SENT: - return send_certificate_verify(this, type, writer); - case STATE_CIPHERSPEC_CHANGED_OUT: - return send_finished(this, type, writer); - default: - return INVALID_STATE; - } -} - -METHOD(tls_handshake_t, cipherspec_changed, bool, - private_tls_peer_t *this) -{ - if (this->state == STATE_VERIFY_SENT) - { - this->crypto->change_cipher(this->crypto, FALSE); - this->state = STATE_CIPHERSPEC_CHANGED_OUT; - return TRUE; - } - return FALSE; -} - -METHOD(tls_handshake_t, change_cipherspec, bool, - private_tls_peer_t *this) -{ - if (this->state == STATE_FINISHED_SENT) - { - this->crypto->change_cipher(this->crypto, TRUE); - this->state = STATE_CIPHERSPEC_CHANGED_IN; - return TRUE; - } - return FALSE; -} - -METHOD(tls_handshake_t, destroy, void, - private_tls_peer_t *this) -{ - DESTROY_IF(this->private); - this->peer_auth->destroy(this->peer_auth); - this->server_auth->destroy(this->server_auth); - free(this); -} - -/** - * See header - */ -tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, - identification_t *peer, identification_t *server) -{ - private_tls_peer_t *this; - - INIT(this, - .public.handshake = { - .process = _process, - .build = _build, - .cipherspec_changed = _cipherspec_changed, - .change_cipherspec = _change_cipherspec, - .destroy = _destroy, - }, - .state = STATE_INIT, - .tls = tls, - .crypto = crypto, - .peer = peer, - .server = server, - .peer_auth = auth_cfg_create(), - .server_auth = auth_cfg_create(), - ); - - return &this->public; -} diff --git a/src/libcharon/plugins/eap_tls/tls/tls_peer.h b/src/libcharon/plugins/eap_tls/tls/tls_peer.h deleted file mode 100644 index 7857d3261..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_peer.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup tls_peer tls_peer - * @{ @ingroup tls - */ - -#ifndef TLS_PEER_H_ -#define TLS_PEER_H_ - -typedef struct tls_peer_t tls_peer_t; - -#include "tls_handshake.h" -#include "tls_crypto.h" - -#include <library.h> - -/** - * TLS handshake protocol handler as peer. - */ -struct tls_peer_t { - - /** - * Implements the TLS handshake protocol handler. - */ - tls_handshake_t handshake; -}; - -/** - * Create a tls_peer instance. - */ -tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, - identification_t *peer, identification_t *server); - -#endif /** TLS_PEER_H_ @}*/ diff --git a/src/libcharon/plugins/eap_tls/tls/tls_prf.c b/src/libcharon/plugins/eap_tls/tls/tls_prf.c deleted file mode 100644 index f181d01d3..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_prf.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "tls_prf.h" - -typedef struct private_tls_prf12_t private_tls_prf12_t; - -/** - * Private data of an tls_prf_t object. - */ -struct private_tls_prf12_t { - - /** - * Public tls_prf_t interface. - */ - tls_prf_t public; - - /** - * Underlying primitive PRF - */ - prf_t *prf; -}; - -METHOD(tls_prf_t, set_key12, void, - private_tls_prf12_t *this, chunk_t key) -{ - this->prf->set_key(this->prf, key); -} - -/** - * The P_hash function as in TLS 1.0/1.2 - */ -static void p_hash(prf_t *prf, char *label, chunk_t seed, size_t block_size, - size_t bytes, char *out) -{ - char buf[block_size], abuf[block_size]; - chunk_t a; - - /* seed = label + seed */ - seed = chunk_cata("cc", chunk_create(label, strlen(label)), seed); - /* A(0) = seed */ - a = seed; - - while (TRUE) - { - /* A(i) = HMAC_hash(secret, A(i-1)) */ - prf->get_bytes(prf, a, abuf); - a = chunk_from_thing(abuf); - /* HMAC_hash(secret, A(i) + seed) */ - prf->get_bytes(prf, a, NULL); - prf->get_bytes(prf, seed, buf); - - if (bytes <= block_size) - { - memcpy(out, buf, bytes); - break; - } - memcpy(out, buf, block_size); - out += block_size; - bytes -= block_size; - } -} - -METHOD(tls_prf_t, get_bytes12, void, - private_tls_prf12_t *this, char *label, chunk_t seed, - size_t bytes, char *out) -{ - p_hash(this->prf, label, seed, this->prf->get_block_size(this->prf), - bytes, out); -} - -METHOD(tls_prf_t, destroy12, void, - private_tls_prf12_t *this) -{ - this->prf->destroy(this->prf); - free(this); -} - -/** - * See header - */ -tls_prf_t *tls_prf_create_12(pseudo_random_function_t prf) -{ - private_tls_prf12_t *this; - - INIT(this, - .public = { - .set_key = _set_key12, - .get_bytes = _get_bytes12, - .destroy = _destroy12, - }, - .prf = lib->crypto->create_prf(lib->crypto, prf), - ); - if (!this->prf) - { - free(this); - return NULL; - } - return &this->public; -} - - -typedef struct private_tls_prf10_t private_tls_prf10_t; - -/** - * Private data of an tls_prf_t object. - */ -struct private_tls_prf10_t { - - /** - * Public tls_prf_t interface. - */ - tls_prf_t public; - - /** - * Underlying MD5 PRF - */ - prf_t *md5; - - /** - * Underlying SHA1 PRF - */ - prf_t *sha1; -}; - -METHOD(tls_prf_t, set_key10, void, - private_tls_prf10_t *this, chunk_t key) -{ - size_t len = key.len / 2 + key.len % 2; - - this->md5->set_key(this->md5, chunk_create(key.ptr, len)); - this->sha1->set_key(this->sha1, chunk_create(key.ptr + key.len - len, len)); -} - -METHOD(tls_prf_t, get_bytes10, void, - private_tls_prf10_t *this, char *label, chunk_t seed, - size_t bytes, char *out) -{ - char buf[bytes]; - - p_hash(this->md5, label, seed, this->md5->get_block_size(this->md5), - bytes, out); - p_hash(this->sha1, label, seed, this->sha1->get_block_size(this->sha1), - bytes, buf); - memxor(out, buf, bytes); -} - -METHOD(tls_prf_t, destroy10, void, - private_tls_prf10_t *this) -{ - DESTROY_IF(this->md5); - DESTROY_IF(this->sha1); - free(this); -} - -/** - * See header - */ -tls_prf_t *tls_prf_create_10(pseudo_random_function_t prf) -{ - private_tls_prf10_t *this; - - INIT(this, - .public = { - .set_key = _set_key10, - .get_bytes = _get_bytes10, - .destroy = _destroy10, - }, - .md5 = lib->crypto->create_prf(lib->crypto, PRF_HMAC_MD5), - .sha1 = lib->crypto->create_prf(lib->crypto, PRF_HMAC_SHA1), - ); - if (!this->md5 || !this->sha1) - { - destroy10(this); - return NULL; - } - return &this->public; -} diff --git a/src/libcharon/plugins/eap_tls/tls/tls_prf.h b/src/libcharon/plugins/eap_tls/tls/tls_prf.h deleted file mode 100644 index 7326be98c..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_prf.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup tls_prf tls_prf - * @{ @ingroup tls - */ - -#ifndef TLS_PRF_H_ -#define TLS_PRF_H_ - -typedef struct tls_prf_t tls_prf_t; - -#include <crypto/prfs/prf.h> - -/** - * The PRF function specified on TLS, based on HMAC. - */ -struct tls_prf_t { - - /** - * Set the key of the PRF function. - * - * @param key key to set - */ - void (*set_key)(tls_prf_t *this, chunk_t key); - - /** - * Generate a series of bytes using a label and a seed. - * - * @param label ASCII input label - * @param seed seed input value - * @param bytes number of bytes to get - * @param out buffer receiving bytes - */ - void (*get_bytes)(tls_prf_t *this, char *label, chunk_t seed, - size_t bytes, char *out); - - /** - * Destroy a tls_prf_t. - */ - void (*destroy)(tls_prf_t *this); -}; - -/** - * Create a tls_prf instance with specific algorithm as in TLS 1.2. - * - * @param hash underlying PRF function to use - * @return TLS PRF algorithm - */ -tls_prf_t *tls_prf_create_12(pseudo_random_function_t prf); - -/** - * Create a tls_prf instance with XOred SHA1/MD5 as in TLS 1.0/1.1. - * - * @return TLS PRF algorithm - */ -tls_prf_t *tls_prf_create_10(); - -#endif /** TLS_PRF_H_ @}*/ diff --git a/src/libcharon/plugins/eap_tls/tls/tls_protection.c b/src/libcharon/plugins/eap_tls/tls/tls_protection.c deleted file mode 100644 index 75fae0a71..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_protection.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "tls_protection.h" - -#include <daemon.h> - -typedef struct private_tls_protection_t private_tls_protection_t; - -/** - * Private data of an tls_protection_t object. - */ -struct private_tls_protection_t { - - /** - * Public tls_protection_t interface. - */ - tls_protection_t public; - - /** - * TLS context - */ - tls_t *tls; - - /** - * Upper layer, TLS record compression - */ - tls_compression_t *compression; - - /** - * RNG if we generate IVs ourself - */ - rng_t *rng; - - /** - * Sequence number of incoming records - */ - u_int32_t seq_in; - - /** - * Sequence number for outgoing records - */ - u_int32_t seq_out; - - /** - * Signer instance for inbound traffic - */ - signer_t *signer_in; - - /** - * Signer instance for outbound traffic - */ - signer_t *signer_out; - - /** - * Crypter instance for inbound traffic - */ - crypter_t *crypter_in; - - /** - * Crypter instance for outbound traffic - */ - crypter_t *crypter_out; - - /** - * Current IV for input decryption - */ - chunk_t iv_in; - - /** - * Current IV for output decryption - */ - chunk_t iv_out; -}; - -/** - * Create the header to append to the record data to create the MAC - */ -static chunk_t sigheader(u_int32_t seq, u_int8_t type, - u_int16_t version, u_int16_t length) -{ - /* we only support 32 bit sequence numbers, but TLS uses 64 bit */ - u_int32_t seq_high = 0; - - seq = htonl(seq); - version = htons(version); - length = htons(length); - - return chunk_cat("ccccc", chunk_from_thing(seq_high), - chunk_from_thing(seq), chunk_from_thing(type), - chunk_from_thing(version), chunk_from_thing(length)); -} - -METHOD(tls_protection_t, process, status_t, - private_tls_protection_t *this, tls_content_type_t type, chunk_t data) -{ - if (this->crypter_in) - { - chunk_t iv, next_iv = chunk_empty; - u_int8_t bs, padding_length; - - bs = this->crypter_in->get_block_size(this->crypter_in); - if (data.len < bs || data.len % bs) - { - DBG1(DBG_IKE, "encrypted TLS record not multiple of block size"); - return FAILED; - } - if (this->iv_in.len) - { /* < TLSv1.1 uses IV from key derivation/last block */ - iv = this->iv_in; - next_iv = chunk_clone(chunk_create(data.ptr + data.len - bs, bs)); - } - else - { /* TLSv1.1 uses random IVs, prepended to record */ - iv = chunk_create(data.ptr, bs); - data = chunk_skip(data, bs); - if (data.len < bs) - { - DBG1(DBG_IKE, "TLS record too short to decrypt"); - return FAILED; - } - } - this->crypter_in->decrypt(this->crypter_in, data, iv, NULL); - - if (next_iv.len) - { /* next record IV is last ciphertext block of this record */ - memcpy(this->iv_in.ptr, next_iv.ptr, next_iv.len); - free(next_iv.ptr); - } - - padding_length = data.ptr[data.len - 1]; - if (padding_length >= data.len) - { - DBG1(DBG_IKE, "invalid TLS record padding"); - return FAILED; - } - data.len -= padding_length + 1; - } - if (this->signer_in) - { - chunk_t mac, macdata, header; - u_int8_t bs; - - bs = this->signer_in->get_block_size(this->signer_in); - if (data.len <= bs) - { - DBG1(DBG_IKE, "TLS record too short to verify MAC"); - return FAILED; - } - mac = chunk_skip(data, data.len - bs); - data.len -= bs; - - header = sigheader(this->seq_in, type, - this->tls->get_version(this->tls), data.len); - macdata = chunk_cat("mc", header, data); - if (!this->signer_in->verify_signature(this->signer_in, macdata, mac)) - { - DBG1(DBG_IKE, "TLS record MAC verification failed"); - free(macdata.ptr); - return FAILED; - } - free(macdata.ptr); - } - - if (type == TLS_CHANGE_CIPHER_SPEC) - { - this->seq_in = 0; - } - else - { - this->seq_in++; - } - return this->compression->process(this->compression, type, data); -} - -METHOD(tls_protection_t, build, status_t, - private_tls_protection_t *this, tls_content_type_t *type, chunk_t *data) -{ - status_t status; - - status = this->compression->build(this->compression, type, data); - if (*type == TLS_CHANGE_CIPHER_SPEC) - { - this->seq_out = 0; - return status; - } - - if (status == NEED_MORE) - { - if (this->signer_out) - { - chunk_t mac, header; - - header = sigheader(this->seq_out, *type, - this->tls->get_version(this->tls), data->len); - this->signer_out->get_signature(this->signer_out, header, NULL); - free(header.ptr); - this->signer_out->allocate_signature(this->signer_out, *data, &mac); - if (this->crypter_out) - { - chunk_t padding, iv; - u_int8_t bs, padding_length; - - bs = this->crypter_out->get_block_size(this->crypter_out); - padding_length = bs - ((data->len + mac.len + 1) % bs); - - padding = chunk_alloca(padding_length); - memset(padding.ptr, padding_length, padding.len); - - if (this->iv_out.len) - { /* < TLSv1.1 uses IV from key derivation/last block */ - iv = this->iv_out; - } - else - { /* TLSv1.1 uses random IVs, prepended to record */ - if (!this->rng) - { - DBG1(DBG_IKE, "no RNG supported to generate TLS IV"); - free(data->ptr); - return FAILED; - } - this->rng->allocate_bytes(this->rng, bs, &iv); - } - - *data = chunk_cat("mmcc", *data, mac, padding, - chunk_from_thing(padding_length)); - /* encrypt inline */ - this->crypter_out->encrypt(this->crypter_out, *data, iv, NULL); - - if (this->iv_out.len) - { /* next record IV is last ciphertext block of this record */ - memcpy(this->iv_out.ptr, data->ptr - this->iv_out.len, - this->iv_out.len); - } - else - { /* prepend IV */ - *data = chunk_cat("mm", iv, *data); - } - } - else - { /* NULL encryption */ - *data = chunk_cat("mm", *data, mac); - } - } - } - this->seq_out++; - return status; -} - -METHOD(tls_protection_t, set_cipher, void, - private_tls_protection_t *this, bool inbound, signer_t *signer, - crypter_t *crypter, chunk_t iv) -{ - if (inbound) - { - this->signer_in = signer; - this->crypter_in = crypter; - this->iv_in = iv; - } - else - { - this->signer_out = signer; - this->crypter_out = crypter; - this->iv_out = iv; - if (!iv.len) - { /* generate IVs if none given */ - this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); - } - } -} - -METHOD(tls_protection_t, destroy, void, - private_tls_protection_t *this) -{ - DESTROY_IF(this->rng); - free(this); -} - -/** - * See header - */ -tls_protection_t *tls_protection_create(tls_t *tls, - tls_compression_t *compression) -{ - private_tls_protection_t *this; - - INIT(this, - .public = { - .process = _process, - .build = _build, - .set_cipher = _set_cipher, - .destroy = _destroy, - }, - .tls = tls, - .compression = compression, - ); - - return &this->public; -} diff --git a/src/libcharon/plugins/eap_tls/tls/tls_protection.h b/src/libcharon/plugins/eap_tls/tls/tls_protection.h deleted file mode 100644 index fab913788..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_protection.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup tls_protection tls_protection - * @{ @ingroup tls - */ - -#ifndef TLS_PROTECTION_H_ -#define TLS_PROTECTION_H_ - -typedef struct tls_protection_t tls_protection_t; - -#include <library.h> - -#include "tls.h" -#include "tls_compression.h" - -/** - * TLS record protocol protection layer. - */ -struct tls_protection_t { - - /** - * Process a protected TLS record, pass it to upper layers. - * - * @param type type of the TLS record to process - * @param data associated TLS record data - * @return - * - SUCCESS if TLS negotiation complete - * - FAILED if TLS handshake failed - * - NEED_MORE if more invocations to process/build needed - */ - status_t (*process)(tls_protection_t *this, - tls_content_type_t type, chunk_t data); - - /** - * Query upper layer for TLS record, build protected record. - * - * @param type type of the built TLS record - * @param data allocated data of the built TLS record - * @return - * - SUCCESS if TLS negotiation complete - * - FAILED if TLS handshake failed - * - NEED_MORE if upper layers have more records to send - * - INVALID_STATE if more input records required - */ - status_t (*build)(tls_protection_t *this, - tls_content_type_t *type, chunk_t *data); - - /** - * Set a new cipher, including encryption and integrity algorithms. - * - * @param inbound TRUE to use cipher for inbound data, FALSE for outbound - * @param signer new signer to use, gets owned by protection layer - * @param crypter new crypter to use, gets owned by protection layer - * @param iv initial IV for crypter, gets owned by protection layer - */ - void (*set_cipher)(tls_protection_t *this, bool inbound, signer_t *signer, - crypter_t *crypter, chunk_t iv); - - /** - * Destroy a tls_protection_t. - */ - void (*destroy)(tls_protection_t *this); -}; - -/** - * Create a tls_protection instance. - * - * @param tls TLS context - * @param compression compression layer of TLS stack - * @return TLS protection layer. - */ -tls_protection_t *tls_protection_create(tls_t *tls, - tls_compression_t *compression); - -#endif /** TLS_PROTECTION_H_ @}*/ diff --git a/src/libcharon/plugins/eap_tls/tls/tls_reader.c b/src/libcharon/plugins/eap_tls/tls/tls_reader.c deleted file mode 100644 index b21eb04f3..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_reader.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "tls_reader.h" - -#include <daemon.h> - -typedef struct private_tls_reader_t private_tls_reader_t; - -/** - * Private data of an tls_reader_t object. - */ -struct private_tls_reader_t { - - /** - * Public tls_reader_t interface. - */ - tls_reader_t public; - - /** - * Remaining data to process - */ - chunk_t buf; -}; - -METHOD(tls_reader_t, remaining, u_int32_t, - private_tls_reader_t *this) -{ - return this->buf.len; -} - -METHOD(tls_reader_t, peek, chunk_t, - private_tls_reader_t *this) -{ - return this->buf; -} - -METHOD(tls_reader_t, read_uint8, bool, - private_tls_reader_t *this, u_int8_t *res) -{ - if (this->buf.len < 1) - { - DBG1(DBG_IKE, "%d bytes insufficient to parse uint%d TLS data", - this->buf.len, 8); - return FALSE; - } - *res = this->buf.ptr[0]; - this->buf = chunk_skip(this->buf, 1); - return TRUE; -} - -METHOD(tls_reader_t, read_uint16, bool, - private_tls_reader_t *this, u_int16_t *res) -{ - if (this->buf.len < 2) - { - DBG1(DBG_IKE, "%d bytes insufficient to parse uint%d TLS data", - this->buf.len, 16); - return FALSE; - } - *res = untoh16(this->buf.ptr); - this->buf = chunk_skip(this->buf, 2); - return TRUE; -} - -METHOD(tls_reader_t, read_uint24, bool, - private_tls_reader_t *this, u_int32_t *res) -{ - if (this->buf.len < 3) - { - DBG1(DBG_IKE, "%d bytes insufficient to parse uint%d TLS data", - this->buf.len, 24); - return FALSE; - } - *res = untoh32(this->buf.ptr) >> 8; - this->buf = chunk_skip(this->buf, 3); - return TRUE; -} - -METHOD(tls_reader_t, read_uint32, bool, - private_tls_reader_t *this, u_int32_t *res) -{ - if (this->buf.len < 4) - { - DBG1(DBG_IKE, "%d bytes insufficient to parse uint%d TLS data", - this->buf.len, 32); - return FALSE; - } - *res = untoh32(this->buf.ptr); - this->buf = chunk_skip(this->buf, 4); - return TRUE; -} - -METHOD(tls_reader_t, read_data, bool, - private_tls_reader_t *this, u_int32_t len, chunk_t *res) -{ - if (this->buf.len < len) - { - DBG1(DBG_IKE, "%d bytes insufficient to parse %d bytes TLS data", - this->buf.len, len); - return FALSE; - } - *res = chunk_create(this->buf.ptr, len); - this->buf = chunk_skip(this->buf, len); - return TRUE; -} - -METHOD(tls_reader_t, read_data8, bool, - private_tls_reader_t *this, chunk_t *res) -{ - u_int8_t len; - - if (!read_uint8(this, &len)) - { - return FALSE; - } - return read_data(this, len, res); -} - -METHOD(tls_reader_t, read_data16, bool, - private_tls_reader_t *this, chunk_t *res) -{ - u_int16_t len; - - if (!read_uint16(this, &len)) - { - return FALSE; - } - return read_data(this, len, res); -} - -METHOD(tls_reader_t, read_data24, bool, - private_tls_reader_t *this, chunk_t *res) -{ - u_int32_t len; - - if (!read_uint24(this, &len)) - { - return FALSE; - } - return read_data(this, len, res); -} - -METHOD(tls_reader_t, read_data32, bool, - private_tls_reader_t *this, chunk_t *res) -{ - u_int32_t len; - - if (!read_uint32(this, &len)) - { - return FALSE; - } - return read_data(this, len, res); -} - -METHOD(tls_reader_t, destroy, void, - private_tls_reader_t *this) -{ - free(this); -} - -/** - * See header - */ -tls_reader_t *tls_reader_create(chunk_t data) -{ - private_tls_reader_t *this; - - INIT(this, - .public = { - .remaining = _remaining, - .peek = _peek, - .read_uint8 = _read_uint8, - .read_uint16 = _read_uint16, - .read_uint24 = _read_uint24, - .read_uint32 = _read_uint32, - .read_data = _read_data, - .read_data8 = _read_data8, - .read_data16 = _read_data16, - .read_data24 = _read_data24, - .read_data32 = _read_data32, - .destroy = _destroy, - }, - .buf = data, - ); - - return &this->public; -} diff --git a/src/libcharon/plugins/eap_tls/tls/tls_reader.h b/src/libcharon/plugins/eap_tls/tls/tls_reader.h deleted file mode 100644 index a8917dfb6..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_reader.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup tls_reader tls_reader - * @{ @ingroup tls - */ - -#ifndef TLS_READER_H_ -#define TLS_READER_H_ - -typedef struct tls_reader_t tls_reader_t; - -#include <library.h> - -/** - * TLS record parser. - */ -struct tls_reader_t { - - /** - * Get the number of remaining bytes. - * - * @return number of remaining bytes in buffer - */ - u_int32_t (*remaining)(tls_reader_t *this); - - /** - * Peek the remaining data, not consuming any bytes. - * - * @return remaining data - */ - chunk_t (*peek)(tls_reader_t *this); - - /** - * Read a 8-bit integer from the buffer, advance. - * - * @param res pointer to result - * @return TRUE if integer read successfully - */ - bool (*read_uint8)(tls_reader_t *this, u_int8_t *res); - - /** - * Read a 16-bit integer from the buffer, advance. - * - * @param res pointer to result - * @return TRUE if integer read successfully - */ - bool (*read_uint16)(tls_reader_t *this, u_int16_t *res); - - /** - * Read a 24-bit integer from the buffer, advance. - * - * @param res pointer to result - * @return TRUE if integer read successfully - */ - bool (*read_uint24)(tls_reader_t *this, u_int32_t *res); - - /** - * Read a 32-bit integer from the buffer, advance. - * - * @param res pointer to result - * @return TRUE if integer read successfully - */ - bool (*read_uint32)(tls_reader_t *this, u_int32_t *res); - - /** - * Read a chunk of len bytes, advance. - * - * @param len number of bytes to read - * @param res pointer to result, not cloned - * @return TRUE if data read successfully - */ - bool (*read_data)(tls_reader_t *this, u_int32_t len, chunk_t *res); - - /** - * Read a chunk of bytes with a 8-bit length header, advance. - * - * @param res pointer to result, not cloned - * @return TRUE if data read successfully - */ - bool (*read_data8)(tls_reader_t *this, chunk_t *res); - - /** - * Read a chunk of bytes with a 16-bit length header, advance. - * - * @param res pointer to result, not cloned - * @return TRUE if data read successfully - */ - bool (*read_data16)(tls_reader_t *this, chunk_t *res); - - /** - * Read a chunk of bytes with a 24-bit length header, advance. - * - * @param res pointer to result, not cloned - * @return TRUE if data read successfully - */ - bool (*read_data24)(tls_reader_t *this, chunk_t *res); - - /** - * Read a chunk of bytes with a 32-bit length header, advance. - * - * @param res pointer to result, not cloned - * @return TRUE if data read successfully - */ - bool (*read_data32)(tls_reader_t *this, chunk_t *res); - - /** - * Destroy a tls_reader_t. - */ - void (*destroy)(tls_reader_t *this); -}; - -/** - * Create a tls_reader instance. - */ -tls_reader_t *tls_reader_create(chunk_t data); - -#endif /** tls_reader_H_ @}*/ diff --git a/src/libcharon/plugins/eap_tls/tls/tls_server.c b/src/libcharon/plugins/eap_tls/tls/tls_server.c deleted file mode 100644 index 60c62684e..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_server.c +++ /dev/null @@ -1,607 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "tls_server.h" - -#include <time.h> - -#include <daemon.h> - -typedef struct private_tls_server_t private_tls_server_t; - - -typedef enum { - STATE_INIT, - STATE_HELLO_RECEIVED, - STATE_HELLO_SENT, - STATE_CERT_SENT, - STATE_CERTREQ_SENT, - STATE_HELLO_DONE, - STATE_CERT_RECEIVED, - STATE_KEY_EXCHANGE_RECEIVED, - STATE_CERT_VERIFY_RECEIVED, - STATE_CIPHERSPEC_CHANGED_IN, - STATE_FINISHED_RECEIVED, - STATE_CIPHERSPEC_CHANGED_OUT, - STATE_FINISHED_SENT, -} server_state_t; - -/** - * Private data of an tls_server_t object. - */ -struct private_tls_server_t { - - /** - * Public tls_server_t interface. - */ - tls_server_t public; - - /** - * TLS stack - */ - tls_t *tls; - - /** - * TLS crypto context - */ - tls_crypto_t *crypto; - - /** - * Server identity - */ - identification_t *server; - - /** - * Peer identity - */ - identification_t *peer; - - /** - * State we are in - */ - server_state_t state; - - /** - * Hello random data selected by client - */ - char client_random[32]; - - /** - * Hello random data selected by server - */ - char server_random[32]; - - /** - * Auth helper for peer authentication - */ - auth_cfg_t *peer_auth; - - /** - * Auth helper for server authentication - */ - auth_cfg_t *server_auth; - - /** - * Peer private key - */ - private_key_t *private; - - /** - * Selected TLS cipher suite - */ - tls_cipher_suite_t suite; -}; - -/** - * Process client hello message - */ -static status_t process_client_hello(private_tls_server_t *this, - tls_reader_t *reader) -{ - u_int16_t version; - chunk_t random, session, ciphers, compression, ext = chunk_empty; - tls_cipher_suite_t *suites; - int count, i; - - this->crypto->append_handshake(this->crypto, - TLS_CLIENT_HELLO, reader->peek(reader)); - - if (!reader->read_uint16(reader, &version) || - !reader->read_data(reader, sizeof(this->client_random), &random) || - !reader->read_data8(reader, &session) || - !reader->read_data16(reader, &ciphers) || - !reader->read_data8(reader, &compression) || - (reader->remaining(reader) && !reader->read_data16(reader, &ext))) - { - DBG1(DBG_IKE, "received invalid ClientHello"); - return FAILED; - } - - memcpy(this->client_random, random.ptr, sizeof(this->client_random)); - - if (version < this->tls->get_version(this->tls)) - { - this->tls->set_version(this->tls, version); - } - count = ciphers.len / sizeof(u_int16_t); - suites = alloca(count * sizeof(tls_cipher_suite_t)); - for (i = 0; i < count; i++) - { - suites[i] = untoh16(&ciphers.ptr[i * sizeof(u_int16_t)]); - } - this->suite = this->crypto->select_cipher_suite(this->crypto, suites, count); - if (!this->suite) - { - DBG1(DBG_IKE, "received cipher suite inacceptable"); - return FAILED; - } - this->state = STATE_HELLO_RECEIVED; - return NEED_MORE; -} - -/** - * Process certificate - */ -static status_t process_certificate(private_tls_server_t *this, - tls_reader_t *reader) -{ - certificate_t *cert; - tls_reader_t *certs; - chunk_t data; - bool first = TRUE; - - this->crypto->append_handshake(this->crypto, - TLS_CERTIFICATE, reader->peek(reader)); - - if (!reader->read_data24(reader, &data)) - { - return FAILED; - } - certs = tls_reader_create(data); - while (certs->remaining(certs)) - { - if (!certs->read_data24(certs, &data)) - { - certs->destroy(certs); - return FAILED; - } - cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, - BUILD_BLOB_ASN1_DER, data, BUILD_END); - if (cert) - { - if (first) - { - this->peer_auth->add(this->peer_auth, - AUTH_HELPER_SUBJECT_CERT, cert); - DBG1(DBG_IKE, "received TLS peer certificate '%Y'", - cert->get_subject(cert)); - first = FALSE; - } - else - { - DBG1(DBG_IKE, "received TLS intermediate certificate '%Y'", - cert->get_subject(cert)); - this->peer_auth->add(this->peer_auth, AUTH_HELPER_IM_CERT, cert); - } - } - else - { - DBG1(DBG_IKE, "parsing TLS certificate failed, skipped"); - } - } - certs->destroy(certs); - this->state = STATE_CERT_RECEIVED; - return NEED_MORE; -} - -/** - * Process Client Key Exchange - */ -static status_t process_key_exchange(private_tls_server_t *this, - tls_reader_t *reader) -{ - chunk_t encrypted, premaster; - - this->crypto->append_handshake(this->crypto, - TLS_CLIENT_KEY_EXCHANGE, reader->peek(reader)); - - if (!reader->read_data16(reader, &encrypted)) - { - DBG1(DBG_IKE, "received invalid Client Key Exchange"); - return FAILED; - } - - if (!this->private || - !this->private->decrypt(this->private, encrypted, &premaster)) - { - DBG1(DBG_IKE, "decrypting Client Key Exchange data failed"); - return FAILED; - } - this->crypto->derive_secrets(this->crypto, premaster, - chunk_from_thing(this->client_random), - chunk_from_thing(this->server_random)); - chunk_clear(&premaster); - - this->state = STATE_KEY_EXCHANGE_RECEIVED; - return NEED_MORE; -} - -/** - * Process Certificate verify - */ -static status_t process_cert_verify(private_tls_server_t *this, - tls_reader_t *reader) -{ - bool verified = FALSE; - enumerator_t *enumerator; - public_key_t *public; - auth_cfg_t *auth; - tls_reader_t *sig; - - enumerator = lib->credmgr->create_public_enumerator(lib->credmgr, - KEY_ANY, this->peer, this->peer_auth); - while (enumerator->enumerate(enumerator, &public, &auth)) - { - sig = tls_reader_create(reader->peek(reader)); - verified = this->crypto->verify_handshake(this->crypto, public, sig); - sig->destroy(sig); - if (verified) - { - break; - } - DBG1(DBG_IKE, "signature verification failed, trying another key"); - } - enumerator->destroy(enumerator); - - if (!verified) - { - DBG1(DBG_IKE, "no trusted certificate found for '%Y' to verify TLS peer", - this->peer); - return FAILED; - } - - this->crypto->append_handshake(this->crypto, - TLS_CERTIFICATE_VERIFY, reader->peek(reader)); - this->state = STATE_CERT_VERIFY_RECEIVED; - return NEED_MORE; -} - -/** - * Process finished message - */ -static status_t process_finished(private_tls_server_t *this, - tls_reader_t *reader) -{ - chunk_t received; - char buf[12]; - - if (!reader->read_data(reader, sizeof(buf), &received)) - { - DBG1(DBG_IKE, "received client finished too short"); - return FAILED; - } - if (!this->crypto->calculate_finished(this->crypto, "client finished", buf)) - { - DBG1(DBG_IKE, "calculating client finished failed"); - return FAILED; - } - if (!chunk_equals(received, chunk_from_thing(buf))) - { - DBG1(DBG_IKE, "received client finished invalid"); - return FAILED; - } - - this->crypto->append_handshake(this->crypto, TLS_FINISHED, received); - this->state = STATE_FINISHED_RECEIVED; - return NEED_MORE; -} - -METHOD(tls_handshake_t, process, status_t, - private_tls_server_t *this, tls_handshake_type_t type, tls_reader_t *reader) -{ - tls_handshake_type_t expected; - - switch (this->state) - { - case STATE_INIT: - if (type == TLS_CLIENT_HELLO) - { - return process_client_hello(this, reader); - } - expected = TLS_CLIENT_HELLO; - break; - case STATE_HELLO_DONE: - if (type == TLS_CERTIFICATE) - { - return process_certificate(this, reader); - } - expected = TLS_CERTIFICATE; - break; - case STATE_CERT_RECEIVED: - if (type == TLS_CLIENT_KEY_EXCHANGE) - { - return process_key_exchange(this, reader); - } - expected = TLS_CLIENT_KEY_EXCHANGE; - break; - case STATE_KEY_EXCHANGE_RECEIVED: - if (type == TLS_CERTIFICATE_VERIFY) - { - return process_cert_verify(this, reader); - } - expected = TLS_CERTIFICATE_VERIFY; - break; - case STATE_CIPHERSPEC_CHANGED_IN: - if (type == TLS_FINISHED) - { - return process_finished(this, reader); - } - expected = TLS_FINISHED; - break; - default: - DBG1(DBG_IKE, "TLS %N not expected in current state", - tls_handshake_type_names, type); - return FAILED; - } - DBG1(DBG_IKE, "TLS %N expected, but received %N", - tls_handshake_type_names, expected, tls_handshake_type_names, type); - return FAILED; -} - -/** - * Send ServerHello message - */ -static status_t send_server_hello(private_tls_server_t *this, - tls_handshake_type_t *type, tls_writer_t *writer) -{ - rng_t *rng; - - htoun32(&this->server_random, time(NULL)); - rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); - if (!rng) - { - return FAILED; - } - rng->get_bytes(rng, sizeof(this->server_random) - 4, this->server_random + 4); - rng->destroy(rng); - - writer->write_uint16(writer, this->tls->get_version(this->tls)); - writer->write_data(writer, chunk_from_thing(this->server_random)); - /* session identifier => none, we don't support session resumption */ - writer->write_data8(writer, chunk_empty); - /* add selected suite */ - writer->write_uint16(writer, this->suite); - /* NULL compression only */ - writer->write_uint8(writer, 0); - - *type = TLS_SERVER_HELLO; - this->state = STATE_HELLO_SENT; - this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); - return NEED_MORE; -} - -/** - * Send Certificate - */ -static status_t send_certificate(private_tls_server_t *this, - tls_handshake_type_t *type, tls_writer_t *writer) -{ - enumerator_t *enumerator; - certificate_t *cert; - auth_rule_t rule; - tls_writer_t *certs; - chunk_t data; - - this->private = lib->credmgr->get_private(lib->credmgr, - KEY_ANY, this->server, this->server_auth); - if (!this->private) - { - DBG1(DBG_IKE, "no TLS server certificate found for '%Y'", this->server); - return FAILED; - } - - /* generate certificate payload */ - certs = tls_writer_create(256); - cert = this->server_auth->get(this->server_auth, AUTH_RULE_SUBJECT_CERT); - if (cert) - { - if (cert->get_encoding(cert, CERT_ASN1_DER, &data)) - { - DBG1(DBG_IKE, "sending TLS server certificate '%Y'", - cert->get_subject(cert)); - certs->write_data24(certs, data); - free(data.ptr); - } - } - enumerator = this->server_auth->create_enumerator(this->server_auth); - while (enumerator->enumerate(enumerator, &rule, &cert)) - { - if (rule == AUTH_RULE_IM_CERT) - { - if (cert->get_encoding(cert, CERT_ASN1_DER, &data)) - { - DBG1(DBG_IKE, "sending TLS intermediate certificate '%Y'", - cert->get_subject(cert)); - certs->write_data24(certs, data); - free(data.ptr); - } - } - } - enumerator->destroy(enumerator); - - writer->write_data24(writer, certs->get_buf(certs)); - certs->destroy(certs); - - *type = TLS_CERTIFICATE; - this->state = STATE_CERT_SENT; - this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); - return NEED_MORE; -} - -/** - * Send Certificate Request - */ -static status_t send_certificate_request(private_tls_server_t *this, - tls_handshake_type_t *type, tls_writer_t *writer) -{ - tls_writer_t *authorities; - enumerator_t *enumerator; - certificate_t *cert; - identification_t *id; - - /* currently only RSA signatures are supported */ - writer->write_data8(writer, chunk_from_chars(1)); - if (this->tls->get_version(this->tls) >= TLS_1_2) - { - /* enforce RSA with SHA1 signatures */ - writer->write_data16(writer, chunk_from_chars(2, 1)); - } - - authorities = tls_writer_create(64); - enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, - CERT_X509, KEY_RSA, NULL, TRUE); - while (enumerator->enumerate(enumerator, &cert)) - { - id = cert->get_subject(cert); - authorities->write_data16(authorities, id->get_encoding(id)); - } - enumerator->destroy(enumerator); - writer->write_data16(writer, authorities->get_buf(authorities)); - authorities->destroy(authorities); - - *type = TLS_CERTIFICATE_REQUEST; - this->state = STATE_CERTREQ_SENT; - this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); - return NEED_MORE; -} - -/** - * Send Hello Done - */ -static status_t send_hello_done(private_tls_server_t *this, - tls_handshake_type_t *type, tls_writer_t *writer) -{ - *type = TLS_SERVER_HELLO_DONE; - this->state = STATE_HELLO_DONE; - this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); - return NEED_MORE; -} - -/** - * Send Finished - */ -static status_t send_finished(private_tls_server_t *this, - tls_handshake_type_t *type, tls_writer_t *writer) -{ - char buf[12]; - - if (!this->crypto->calculate_finished(this->crypto, "server finished", buf)) - { - DBG1(DBG_IKE, "calculating server finished data failed"); - return FAILED; - } - - writer->write_data(writer, chunk_from_thing(buf)); - - *type = TLS_FINISHED; - this->state = STATE_FINISHED_SENT; - this->crypto->derive_eap_msk(this->crypto, - chunk_from_thing(this->client_random), - chunk_from_thing(this->server_random)); - return NEED_MORE; -} - -METHOD(tls_handshake_t, build, status_t, - private_tls_server_t *this, tls_handshake_type_t *type, tls_writer_t *writer) -{ - switch (this->state) - { - case STATE_HELLO_RECEIVED: - return send_server_hello(this, type, writer); - case STATE_HELLO_SENT: - return send_certificate(this, type, writer); - case STATE_CERT_SENT: - return send_certificate_request(this, type, writer); - case STATE_CERTREQ_SENT: - return send_hello_done(this, type, writer); - case STATE_CIPHERSPEC_CHANGED_OUT: - return send_finished(this, type, writer); - case STATE_FINISHED_SENT: - return INVALID_STATE; - default: - return INVALID_STATE; - } -} - -METHOD(tls_handshake_t, cipherspec_changed, bool, - private_tls_server_t *this) -{ - if (this->state == STATE_FINISHED_RECEIVED) - { - this->crypto->change_cipher(this->crypto, FALSE); - this->state = STATE_CIPHERSPEC_CHANGED_OUT; - return TRUE; - } - return FALSE; -} - -METHOD(tls_handshake_t, change_cipherspec, bool, - private_tls_server_t *this) -{ - if (this->state == STATE_CERT_VERIFY_RECEIVED) - { - this->crypto->change_cipher(this->crypto, TRUE); - this->state = STATE_CIPHERSPEC_CHANGED_IN; - return TRUE; - } - return FALSE; -} - -METHOD(tls_handshake_t, destroy, void, - private_tls_server_t *this) -{ - DESTROY_IF(this->private); - this->peer_auth->destroy(this->peer_auth); - this->server_auth->destroy(this->server_auth); - free(this); -} - -/** - * See header - */ -tls_server_t *tls_server_create(tls_t *tls, tls_crypto_t *crypto, - identification_t *server, identification_t *peer) -{ - private_tls_server_t *this; - - INIT(this, - .public.handshake = { - .process = _process, - .build = _build, - .cipherspec_changed = _cipherspec_changed, - .change_cipherspec = _change_cipherspec, - .destroy = _destroy, - }, - .tls = tls, - .crypto = crypto, - .server = server, - .peer = peer, - .state = STATE_INIT, - .peer_auth = auth_cfg_create(), - .server_auth = auth_cfg_create(), - ); - - return &this->public; -} diff --git a/src/libcharon/plugins/eap_tls/tls/tls_server.h b/src/libcharon/plugins/eap_tls/tls/tls_server.h deleted file mode 100644 index 3fddea225..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_server.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup tls_server tls_server - * @{ @ingroup tls - */ - -#ifndef TLS_SERVER_H_ -#define TLS_SERVER_H_ - -typedef struct tls_server_t tls_server_t; - -#include "tls_handshake.h" -#include "tls_crypto.h" - -#include <library.h> - -/** - * TLS handshake protocol handler as peer. - */ -struct tls_server_t { - - /** - * Implements the TLS handshake protocol handler. - */ - tls_handshake_t handshake; -}; - -/** - * Create a tls_server instance. - */ -tls_server_t *tls_server_create(tls_t *tls, tls_crypto_t *crypto, - identification_t *server, identification_t *peer); - -#endif /** TLS_SERVER_H_ @}*/ diff --git a/src/libcharon/plugins/eap_tls/tls/tls_writer.c b/src/libcharon/plugins/eap_tls/tls/tls_writer.c deleted file mode 100644 index f1d9d790e..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_writer.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "tls_writer.h" - -typedef struct private_tls_writer_t private_tls_writer_t; - -/** - * Private data of an tls_writer_t object. - */ -struct private_tls_writer_t { - - /** - * Public tls_writer_t interface. - */ - tls_writer_t public; - - /** - * Allocated buffer - */ - chunk_t buf; - - /** - * Used bytes in buffer - */ - size_t used; - - /** - * Number of bytes to increase buffer size - */ - size_t increase; -}; - -/** - * Increase buffer size - */ -static void increase(private_tls_writer_t *this) -{ - this->buf.len += this->increase; - this->buf.ptr = realloc(this->buf.ptr, this->buf.len); -} - -METHOD(tls_writer_t, write_uint8, void, - private_tls_writer_t *this, u_int8_t value) -{ - if (this->used + 1 > this->buf.len) - { - increase(this); - } - this->buf.ptr[this->used] = value; - this->used += 1; -} - -METHOD(tls_writer_t, write_uint16, void, - private_tls_writer_t *this, u_int16_t value) -{ - if (this->used + 2 > this->buf.len) - { - increase(this); - } - htoun16(this->buf.ptr + this->used, value); - this->used += 2; -} - -METHOD(tls_writer_t, write_uint24, void, - private_tls_writer_t *this, u_int32_t value) -{ - if (this->used + 3 > this->buf.len) - { - increase(this); - } - value = htonl(value); - memcpy(this->buf.ptr + this->used, ((char*)&value) + 1, 3); - this->used += 3; -} - -METHOD(tls_writer_t, write_uint32, void, - private_tls_writer_t *this, u_int32_t value) -{ - if (this->used + 4 > this->buf.len) - { - increase(this); - } - htoun32(this->buf.ptr + this->used, value); - this->used += 4; -} - -METHOD(tls_writer_t, write_data, void, - private_tls_writer_t *this, chunk_t value) -{ - while (this->used + value.len > this->buf.len) - { - increase(this); - } - memcpy(this->buf.ptr + this->used, value.ptr, value.len); - this->used += value.len; -} - -METHOD(tls_writer_t, write_data8, void, - private_tls_writer_t *this, chunk_t value) -{ - write_uint8(this, value.len); - write_data(this, value); -} - -METHOD(tls_writer_t, write_data16, void, - private_tls_writer_t *this, chunk_t value) -{ - write_uint16(this, value.len); - write_data(this, value); -} - -METHOD(tls_writer_t, write_data24, void, - private_tls_writer_t *this, chunk_t value) -{ - write_uint24(this, value.len); - write_data(this, value); -} - -METHOD(tls_writer_t, write_data32, void, - private_tls_writer_t *this, chunk_t value) -{ - write_uint32(this, value.len); - write_data(this, value); -} - -METHOD(tls_writer_t, wrap8, void, - private_tls_writer_t *this) -{ - if (this->used + 1 > this->buf.len) - { - increase(this); - } - memmove(this->buf.ptr + 1, this->buf.ptr, 1); - this->buf.ptr[0] = this->used; - this->used += 1; -} - -METHOD(tls_writer_t, wrap16, void, - private_tls_writer_t *this) -{ - if (this->used + 2 > this->buf.len) - { - increase(this); - } - memmove(this->buf.ptr + 2, this->buf.ptr, 2); - htoun16(this->buf.ptr, this->used); - this->used += 2; -} - -METHOD(tls_writer_t, wrap24, void, - private_tls_writer_t *this) -{ - u_int32_t len; - - if (this->used + 3 > this->buf.len) - { - increase(this); - } - memmove(this->buf.ptr + 3, this->buf.ptr, 3); - - len = htonl(this->used); - memcpy(this->buf.ptr, ((char*)&len) + 1, 3); - this->used += 3; -} - -METHOD(tls_writer_t, wrap32, void, - private_tls_writer_t *this) -{ - if (this->used + 4 > this->buf.len) - { - increase(this); - } - memmove(this->buf.ptr + 4, this->buf.ptr, 4); - htoun32(this->buf.ptr, this->used); - this->used += 4; -} - -METHOD(tls_writer_t, get_buf, chunk_t, - private_tls_writer_t *this) -{ - return chunk_create(this->buf.ptr, this->used); -} - -METHOD(tls_writer_t, destroy, void, - private_tls_writer_t *this) -{ - free(this->buf.ptr); - free(this); -} - -/** - * See header - */ -tls_writer_t *tls_writer_create(u_int32_t bufsize) -{ - private_tls_writer_t *this; - - INIT(this, - .public = { - .write_uint8 = _write_uint8, - .write_uint16 = _write_uint16, - .write_uint24 = _write_uint24, - .write_uint32 = _write_uint32, - .write_data = _write_data, - .write_data8 = _write_data8, - .write_data16 = _write_data16, - .write_data24 = _write_data24, - .write_data32 = _write_data32, - .wrap8 = _wrap8, - .wrap16 = _wrap16, - .wrap24 = _wrap24, - .wrap32 = _wrap32, - .get_buf = _get_buf, - .destroy = _destroy, - }, - .increase = bufsize ?: 32, - ); - if (bufsize) - { - this->buf = chunk_alloc(bufsize); - } - - return &this->public; -} diff --git a/src/libcharon/plugins/eap_tls/tls/tls_writer.h b/src/libcharon/plugins/eap_tls/tls/tls_writer.h deleted file mode 100644 index ce8ba6a6e..000000000 --- a/src/libcharon/plugins/eap_tls/tls/tls_writer.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup tls_writer tls_writer - * @{ @ingroup tls - */ - -#ifndef TLS_WRITER_H_ -#define TLS_WRITER_H_ - -typedef struct tls_writer_t tls_writer_t; - -#include <library.h> - -/** - * TLS record generator. - */ -struct tls_writer_t { - - /** - * Append a 8-bit integer to the buffer. - * - * @param value value to append - */ - void (*write_uint8)(tls_writer_t *this, u_int8_t value); - - /** - * Append a 16-bit integer to the buffer. - * - * @param value value to append - */ - void (*write_uint16)(tls_writer_t *this, u_int16_t value); - - /** - * Append a 24-bit integer to the buffer. - * - * @param value value to append - */ - void (*write_uint24)(tls_writer_t *this, u_int32_t value); - - /** - * Append a 32-bit integer to the buffer. - * - * @param value value to append - */ - void (*write_uint32)(tls_writer_t *this, u_int32_t value); - - /** - * Append a chunk of data without a length header. - * - * @param value value to append - */ - void (*write_data)(tls_writer_t *this, chunk_t value); - - /** - * Append a chunk of data with a 16-bit length header. - * - * @param value value to append - */ - void (*write_data8)(tls_writer_t *this, chunk_t value); - - /** - * Append a chunk of data with a 8-bit length header. - * - * @param value value to append - */ - void (*write_data16)(tls_writer_t *this, chunk_t value); - - /** - * Append a chunk of data with a 24-bit length header. - * - * @param value value to append - */ - void (*write_data24)(tls_writer_t *this, chunk_t value); - - /** - * Append a chunk of data with a 32-bit length header. - * - * @param value value to append - */ - void (*write_data32)(tls_writer_t *this, chunk_t value); - - /** - * Prepend a 8-bit length header to existing data. - */ - void (*wrap8)(tls_writer_t *this); - - /** - * Prepend a 16-bit length header to existing data. - */ - void (*wrap16)(tls_writer_t *this); - - /** - * Prepend a 24-bit length header to existing data. - */ - void (*wrap24)(tls_writer_t *this); - - /** - * Prepend a 32-bit length header to existing data. - */ - void (*wrap32)(tls_writer_t *this); - - /** - * Get the encoded data buffer. - * - * @return chunk to internal buffer - */ - chunk_t (*get_buf)(tls_writer_t *this); - - /** - * Destroy a tls_writer_t. - */ - void (*destroy)(tls_writer_t *this); -}; - -/** - * Create a tls_writer instance. - * - * @param bufsize initially allocated buffer size - */ -tls_writer_t *tls_writer_create(u_int32_t bufsize); - -#endif /** TLS_WRITER_H_ @}*/ |