+/*
+ * Perform full static ECDH. This occurs only in the context of client
+ * authentication with certificates: the server uses an EC public key,
+ * the cipher suite is of type ECDH (not ECDHE), the server requested a
+ * client certificate and accepts static ECDH, the client has a
+ * certificate with an EC public key in the same curve, and accepts
+ * static ECDH as well.
+ *
+ * Returned value is 0 on success, -1 on error.
+ */
+static int
+make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id)
+{
+ unsigned char point[133];
+ size_t point_len;
+ const br_x509_class **xc;
+ const br_x509_pkey *pk;
+
+ xc = ctx->eng.x509ctx;
+ pk = (*xc)->get_pkey(xc, NULL);
+ point_len = pk->key.ec.qlen;
+ if (point_len > sizeof point) {
+ return -1;
+ }
+ memcpy(point, pk->key.ec.q, point_len);
+ if (!(*ctx->client_auth_vtable)->do_keyx(
+ ctx->client_auth_vtable, point, point_len))
+ {
+ return -1;
+ }
+ br_ssl_engine_compute_master(&ctx->eng,
+ prf_id, point + 1, point_len >> 1);
+ return 0;
+}
+
+/*
+ * Compute the client-side signature. This is invoked only when a
+ * signature-based client authentication was selected. The computed
+ * signature is in the pad; its length (in bytes) is returned. On
+ * error, 0 is returned.
+ */
+static size_t
+make_client_sign(br_ssl_client_context *ctx)
+{
+ size_t hv_len;
+
+ /*
+ * Compute hash of handshake messages so far. This "cannot" fail
+ * because the list of supported hash functions provided to the
+ * client certificate handler was trimmed to include only the
+ * hash functions that the multi-hasher supports.
+ */
+ if (ctx->hash_id) {
+ hv_len = br_multihash_out(&ctx->eng.mhash,
+ ctx->hash_id, ctx->eng.pad);
+ } else {
+ br_multihash_out(&ctx->eng.mhash,
+ br_md5_ID, ctx->eng.pad);
+ br_multihash_out(&ctx->eng.mhash,
+ br_sha1_ID, ctx->eng.pad + 16);
+ hv_len = 36;
+ }
+ return (*ctx->client_auth_vtable)->do_sign(
+ ctx->client_auth_vtable, ctx->hash_id, hv_len,
+ ctx->eng.pad, sizeof ctx->eng.pad);
+}
+