"SECP521R1",
);
+ENUM(tls_ecp_format_names, TLS_ECP_COMPRESSED, TLS_ECP_HYBRID_Y,
+ "compressed",
+ "compressed y",
+ "uncompressed",
+ "uncompressed y",
+ "hybrid",
+ "hybrid y",
+);
typedef struct private_tls_crypto_t private_tls_crypto_t;
*/
extern enum_name_t *tls_named_curve_names;
+/**
+ * EC Point format, ANSI X9.62.
+ */
+enum tls_ecp_format_t {
+ TLS_ECP_COMPRESSED = 2,
+ TLS_ECP_COMPRESSED_Y = 3,
+ TLS_ECP_UNCOMPRESSED = 4,
+ TLS_ECP_HYBRID = 6,
+ TLS_ECP_HYBRID_Y = 7,
+};
+
+/**
+ * Enum names for tls_ecp_format_t.
+ */
+extern enum_name_t *tls_ecp_format_names;
+
/**
* TLS crypto helper functions.
*/
return NEED_MORE;
}
if (!reader->read_uint16(reader, &curve) ||
- !reader->read_data8(reader, &pub))
+ !reader->read_data8(reader, &pub) || pub.len == 0)
{
DBG1(DBG_TLS, "received invalid Server Key Exchange");
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
return NEED_MORE;
}
- this->dh->set_other_public_value(this->dh, pub);
+
+ if (pub.ptr[0] != TLS_ECP_UNCOMPRESSED)
+ {
+ DBG1(DBG_TLS, "DH point format '%N' not supported",
+ tls_ecp_format_names, pub.ptr[0]);
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
+ }
+ this->dh->set_other_public_value(this->dh, chunk_skip(pub, 1));
this->state = STATE_KEY_EXCHANGE_RECEIVED;
return NEED_MORE;
writer->write_data16(writer, pub);
}
else
- { /* ECP uses 8bit length header only */
- writer->write_data8(writer, pub);
+ { /* ECP uses 8bit length header only, but a point format */
+ writer->write_uint8(writer, pub.len + 1);
+ writer->write_uint8(writer, TLS_ECP_UNCOMPRESSED);
+ writer->write_data(writer, pub);
}
free(pub.ptr);
ec = diffie_hellman_group_is_ec(this->dh->get_dh_group(this->dh));
if ((ec && !reader->read_data8(reader, &pub)) ||
- (!ec && !reader->read_data16(reader, &pub)))
+ (!ec && (!reader->read_data16(reader, &pub) || pub.len == 0)))
{
DBG1(DBG_TLS, "received invalid Client Key Exchange");
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
return NEED_MORE;
}
- this->dh->set_other_public_value(this->dh, pub);
+
+ if (pub.ptr[0] != TLS_ECP_UNCOMPRESSED)
+ {
+ DBG1(DBG_TLS, "DH point format '%N' not supported",
+ tls_ecp_format_names, pub.ptr[0]);
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
+ }
+ this->dh->set_other_public_value(this->dh, chunk_skip(pub, 1));
if (this->dh->get_shared_secret(this->dh, &premaster) != SUCCESS)
{
DBG1(DBG_TLS, "calculating premaster from DH failed");
writer->write_data16(writer, chunk);
}
else
- { /* 8bit header for EC groups */
- writer->write_data8(writer, chunk);
+ { /* ECP uses 8bit length header only, but a point format */
+ writer->write_uint8(writer, chunk.len + 1);
+ writer->write_uint8(writer, TLS_ECP_UNCOMPRESSED);
+ writer->write_data(writer, chunk);
}
free(chunk.ptr);