aboutsummaryrefslogtreecommitdiffstats
path: root/src/libtls/tls_peer.c
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2010-09-03 11:00:07 +0200
committerMartin Willi <martin@revosec.ch>2010-09-03 14:54:43 +0200
commit5fc7297e38d86e3e8994d4b6a737bcdb62343043 (patch)
tree00034e10211c3cc00a53899c3e399c651539b62e /src/libtls/tls_peer.c
parent691ca54db501b8e1ad038cadef02bbdb20688767 (diff)
downloadstrongswan-5fc7297e38d86e3e8994d4b6a737bcdb62343043.tar.bz2
strongswan-5fc7297e38d86e3e8994d4b6a737bcdb62343043.tar.xz
Added client support for ECDHE key exchange
Diffstat (limited to 'src/libtls/tls_peer.c')
-rw-r--r--src/libtls/tls_peer.c105
1 files changed, 103 insertions, 2 deletions
diff --git a/src/libtls/tls_peer.c b/src/libtls/tls_peer.c
index f3476494d..b31b41188 100644
--- a/src/libtls/tls_peer.c
+++ b/src/libtls/tls_peer.c
@@ -352,6 +352,100 @@ static status_t process_modp_key_exchange(private_tls_peer_t *this,
return NEED_MORE;
}
+
+/**
+ * Process a Key Exchange message using EC Diffie Hellman
+ */
+static status_t process_ec_key_exchange(private_tls_peer_t *this,
+ tls_reader_t *reader)
+{
+ diffie_hellman_group_t group;
+ public_key_t *public;
+ u_int8_t type;
+ u_int16_t curve;
+ chunk_t pub, chunk;
+
+ chunk = reader->peek(reader);
+ if (!reader->read_uint8(reader, &type))
+ {
+ DBG1(DBG_TLS, "received invalid Server Key Exchange");
+ this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
+ return NEED_MORE;
+ }
+ if (type != TLS_ECC_NAMED_CURVE)
+ {
+ DBG1(DBG_TLS, "ECDH curve type %N not supported",
+ tls_ecc_curve_type_names, type);
+ this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
+ return NEED_MORE;
+ }
+ if (!reader->read_uint16(reader, &curve) ||
+ !reader->read_data8(reader, &pub))
+ {
+ DBG1(DBG_TLS, "received invalid Server Key Exchange");
+ this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
+ return NEED_MORE;
+ }
+ switch (curve)
+ {
+ case TLS_SECP256R1:
+ group = ECP_256_BIT;
+ break;
+ case TLS_SECP384R1:
+ group = ECP_384_BIT;
+ break;
+ case TLS_SECP521R1:
+ group = ECP_521_BIT;
+ break;
+ case TLS_SECP192R1:
+ group = ECP_192_BIT;
+ break;
+ case TLS_SECP224R1:
+ group = ECP_224_BIT;
+ break;
+ default:
+ DBG1(DBG_TLS, "ECDH curve %N not supported",
+ tls_named_curve_names, curve);
+ this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
+ return NEED_MORE;
+ }
+
+ public = find_public_key(this);
+ if (!public)
+ {
+ DBG1(DBG_TLS, "no TLS public key found for server '%Y'", this->server);
+ this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN);
+ return NEED_MORE;
+ }
+
+ chunk.len = 4 + pub.len;
+ chunk = chunk_cat("ccc", chunk_from_thing(this->client_random),
+ chunk_from_thing(this->server_random), chunk);
+ if (!this->crypto->verify(this->crypto, public, reader, chunk))
+ {
+ public->destroy(public);
+ free(chunk.ptr);
+ DBG1(DBG_TLS, "verifying DH parameters failed");
+ this->alert->add(this->alert, TLS_FATAL, TLS_BAD_CERTIFICATE);
+ return NEED_MORE;
+ }
+ public->destroy(public);
+ free(chunk.ptr);
+
+ this->dh = lib->crypto->create_dh(lib->crypto, group);
+ if (!this->dh)
+ {
+ DBG1(DBG_TLS, "DH group %N not supported",
+ diffie_hellman_group_names, group);
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
+ }
+ this->dh->set_other_public_value(this->dh, pub);
+
+ this->state = STATE_KEY_EXCHANGE_RECEIVED;
+ return NEED_MORE;
+}
+
/**
* Process a Server Key Exchange
*/
@@ -389,7 +483,7 @@ static status_t process_key_exchange(private_tls_peer_t *this,
case ECP_521_BIT:
case ECP_192_BIT:
case ECP_224_BIT:
- /* TODO */
+ return process_ec_key_exchange(this, reader);
default:
return FAILED;
}
@@ -797,7 +891,14 @@ static status_t send_key_exchange_dhe(private_tls_peer_t *this,
chunk_clear(&premaster);
this->dh->get_my_public_value(this->dh, &pub);
- writer->write_data16(writer, pub);
+ if (this->dh->get_dh_group(this->dh) == MODP_CUSTOM)
+ {
+ writer->write_data16(writer, pub);
+ }
+ else
+ { /* ECP uses 8bit length header only */
+ writer->write_data8(writer, pub);
+ }
free(pub.ptr);
*type = TLS_CLIENT_KEY_EXCHANGE;