From b51ac45c484b4fb08153fe2075b8899d48d36862 Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Sun, 15 Aug 2010 13:02:57 +0200 Subject: [PATCH] optional certificate-based peer authentication on TLS server side --- src/libcharon/plugins/eap_tls/eap_tls.c | 4 +-- src/libcharon/plugins/eap_ttls/eap_ttls.c | 4 +-- src/libtls/tls.c | 7 +++-- src/libtls/tls.h | 17 ++++++----- src/libtls/tls_server.c | 37 ++++++++++++++++++----- src/libtls/tls_server.h | 3 +- 6 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/libcharon/plugins/eap_tls/eap_tls.c b/src/libcharon/plugins/eap_tls/eap_tls.c index e4f12d7f6..849f03875 100644 --- a/src/libcharon/plugins/eap_tls/eap_tls.c +++ b/src/libcharon/plugins/eap_tls/eap_tls.c @@ -433,8 +433,8 @@ static eap_tls_t *eap_tls_create(identification_t *server, .is_server = is_server, ); /* MSK PRF ASCII constant label according to EAP-TLS RFC 5216 */ - this->tls = tls_create(is_server, server, peer, "client EAP encryption", - NULL); + this->tls = tls_create(is_server, server, peer, TRUE, + "client EAP encryption", NULL); return &this->public; } diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls.c b/src/libcharon/plugins/eap_ttls/eap_ttls.c index 56713c302..dd24f401a 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls.c @@ -441,8 +441,8 @@ static eap_ttls_t *eap_ttls_create(identification_t *server, .is_server = is_server, ); /* MSK PRF ASCII constant label according to EAP-TTLS RFC 5281 */ - this->tls = tls_create(is_server, server, peer, "ttls keying material", - application); + this->tls = tls_create(is_server, server, peer, FALSE, + "ttls keying material", application); return &this->public; } diff --git a/src/libtls/tls.c b/src/libtls/tls.c index 24f442ca9..e3be79dda 100644 --- a/src/libtls/tls.c +++ b/src/libtls/tls.c @@ -178,8 +178,8 @@ METHOD(tls_t, destroy, void, * See header */ tls_t *tls_create(bool is_server, identification_t *server, - identification_t *peer, char *msk_label, - tls_application_t *application) + identification_t *peer, bool request_peer_auth, + char *msk_label, tls_application_t *application) { private_tls_t *this; @@ -205,7 +205,8 @@ tls_t *tls_create(bool is_server, identification_t *server, if (is_server) { this->handshake = &tls_server_create(&this->public, this->crypto, - this->server, this->peer)->handshake; + this->server, this->peer, + request_peer_auth)->handshake; } else { diff --git a/src/libtls/tls.h b/src/libtls/tls.h index ea66b7661..95ec6011c 100644 --- a/src/libtls/tls.h +++ b/src/libtls/tls.h @@ -161,15 +161,16 @@ struct tls_t { /** * Create a tls instance. * - * @param is_server TRUE to act as server, FALSE for client - * @param server server identity - * @param peer peer identity - * @param msk_label ASCII string constant used as seed for MSK PRF - * @param application higher layer application or NULL if none - * @return TLS stack + * @param is_server TRUE to act as server, FALSE for client + * @param server server identity + * @param peer peer identity + * @param request_peer_auth TRUE to request certificate-based peer authentication + * @param msk_label ASCII string constant used as seed for MSK PRF + * @param application higher layer application or NULL if none + * @return TLS stack */ tls_t *tls_create(bool is_server, identification_t *server, - identification_t *peer, char *msk_label, - tls_application_t *application); + identification_t *peer, bool request_peer_auth, + char *msk_label, tls_application_t *application); #endif /** TLS_H_ @}*/ diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c index 673b20145..2b2845ea1 100644 --- a/src/libtls/tls_server.c +++ b/src/libtls/tls_server.c @@ -83,6 +83,11 @@ struct private_tls_server_t { */ char server_random[32]; + /** + * Does the server request a peer authentication? + */ + bool request_peer_auth; + /** * Auth helper for peer authentication */ @@ -332,8 +337,12 @@ METHOD(tls_handshake_t, process, status_t, { return process_certificate(this, reader); } - expected = TLS_CERTIFICATE; - break; + if (this->request_peer_auth) + { + expected = TLS_CERTIFICATE; + break; + } + /* otherwise fall through to next state */ case STATE_CERT_RECEIVED: if (type == TLS_CLIENT_KEY_EXCHANGE) { @@ -346,8 +355,15 @@ METHOD(tls_handshake_t, process, status_t, { return process_cert_verify(this, reader); } - expected = TLS_CERTIFICATE_VERIFY; - break; + if (this->request_peer_auth) + { + expected = TLS_CERTIFICATE_VERIFY; + break; + } + else + { + return INVALID_STATE; + } case STATE_CIPHERSPEC_CHANGED_IN: if (type == TLS_FINISHED) { @@ -547,7 +563,11 @@ METHOD(tls_handshake_t, build, status_t, case STATE_HELLO_SENT: return send_certificate(this, type, writer); case STATE_CERT_SENT: - return send_certificate_request(this, type, writer); + if (this->request_peer_auth) + { + return send_certificate_request(this, type, writer); + } + /* otherwise fall through to next state */ case STATE_CERTREQ_SENT: return send_hello_done(this, type, writer); case STATE_CIPHERSPEC_CHANGED_OUT: @@ -574,7 +594,8 @@ METHOD(tls_handshake_t, cipherspec_changed, bool, METHOD(tls_handshake_t, change_cipherspec, bool, private_tls_server_t *this) { - if (this->state == STATE_CERT_VERIFY_RECEIVED) + if ((this->request_peer_auth && this->state == STATE_CERT_VERIFY_RECEIVED) || + (!this->request_peer_auth && this->state == STATE_KEY_EXCHANGE_RECEIVED)) { this->crypto->change_cipher(this->crypto, TRUE); this->state = STATE_CIPHERSPEC_CHANGED_IN; @@ -602,7 +623,8 @@ METHOD(tls_handshake_t, destroy, void, * See header */ tls_server_t *tls_server_create(tls_t *tls, tls_crypto_t *crypto, - identification_t *server, identification_t *peer) + identification_t *server, identification_t *peer, + bool request_peer_auth) { private_tls_server_t *this; @@ -620,6 +642,7 @@ tls_server_t *tls_server_create(tls_t *tls, tls_crypto_t *crypto, .server = server, .peer = peer, .state = STATE_INIT, + .request_peer_auth = request_peer_auth, .peer_auth = auth_cfg_create(), .server_auth = auth_cfg_create(), ); diff --git a/src/libtls/tls_server.h b/src/libtls/tls_server.h index 6dc26cd3f..a15d54f02 100644 --- a/src/libtls/tls_server.h +++ b/src/libtls/tls_server.h @@ -43,6 +43,7 @@ struct tls_server_t { * Create a tls_server instance. */ tls_server_t *tls_server_create(tls_t *tls, tls_crypto_t *crypto, - identification_t *server, identification_t *peer); + identification_t *server, identification_t *peer, + bool request_peer_auth); #endif /** TLS_SERVER_H_ @}*/