+ /* TLS1.3 specific extensions */
+ if (SSL_IS_TLS13(s)) {
+ int min_version, max_version, reason, currv;
+ size_t i, sharessent = 0;
+
+ /* TODO(TLS1.3): Should we add this extension for versions < TLS1.3? */
+ /* supported_versions extension */
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_start_sub_packet_u8(pkt)) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ reason = ssl_get_client_min_max_version(s, &min_version, &max_version);
+ if (reason != 0) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, reason);
+ return 0;
+ }
+ /*
+ * TODO(TLS1.3): There is some discussion on the TLS list as to wheter
+ * we should include versions <TLS1.2. For the moment we do. To be
+ * reviewed later.
+ */
+ for (currv = max_version; currv >= min_version; currv--) {
+ /* TODO(TLS1.3): Remove this first if clause prior to release!! */
+ if (currv == TLS1_3_VERSION) {
+ if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ } else if (!WPACKET_put_bytes_u16(pkt, currv)) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+
+ /* key_share extension */
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
+ /* Extension data sub-packet */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ /* KeyShare list sub-packet */
+ || !WPACKET_start_sub_packet_u16(pkt)) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /*
+ * TODO(TLS1.3): Make the number of key_shares sent configurable. For
+ * now, just send one
+ */
+ for (i = 0; i < num_curves && sharessent < 1; i++, pcurves += 2) {
+ if (tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) {
+ unsigned char *encodedPoint = NULL;
+ unsigned int curve_id = 0;
+ EVP_PKEY *key_share_key = NULL;
+ size_t encodedlen;
+
+ if (s->s3->tmp.pkey != NULL) {
+ /* Shouldn't happen! */
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* Generate a key for this key_share */
+ curve_id = (pcurves[0] << 8) | pcurves[1];
+ key_share_key = ssl_generate_pkey_curve(curve_id);
+ if (key_share_key == NULL) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_EVP_LIB);
+ return 0;
+ }
+
+ /* Encode the public key. */
+ encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key,
+ &encodedPoint);
+ if (encodedlen == 0) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_EC_LIB);
+ EVP_PKEY_free(key_share_key);
+ return 0;
+ }
+
+ /* Create KeyShareEntry */
+ if (!WPACKET_put_bytes_u16(pkt, curve_id)
+ || !WPACKET_sub_memcpy_u16(pkt, encodedPoint,
+ encodedlen)) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
+ ERR_R_INTERNAL_ERROR);
+ EVP_PKEY_free(key_share_key);
+ OPENSSL_free(encodedPoint);
+ return 0;
+ }
+
+ /*
+ * TODO(TLS1.3): When changing to send more than one key_share
+ * we're going to need to be able to save more than one EVP_PKEY
+ * For now we reuse the existing tmp.pkey
+ */
+ s->s3->group_id = curve_id;
+ s->s3->tmp.pkey = key_share_key;
+ sharessent++;
+ OPENSSL_free(encodedPoint);
+ }
+ }
+ if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+