+/**
+ * Generate ephemeral secret
+ *
+ * @v tls TLS connection
+ * @v info Additional information (or NULL)
+ * @v info_len Length of additional information
+ * @v out Ephemeral secret to fill in
+ * @v len Length of ephemeral secret
+ */
+static void tls_ephemeral ( struct tls_connection *tls, const void *info,
+ size_t info_len, void *out, size_t len ) {
+ struct tls_key_schedule *key = &tls->key;
+ struct digest_algorithm *digest = &tls_ephemeral_algorithm;
+
+ /* Generate from ephemeral master secret and additional information */
+ hkdf_expand ( digest, key->ephemeral, info, info_len, out, len );
+}
+
+/**
+ * Generate ephemeral secret from label
+ *
+ * @v tls TLS connection
+ * @v label Secret label
+ * @v out Ephemeral secret to fill in
+ * @v len Length of ephemeral secret
+ */
+static void tls_ephemeral_label ( struct tls_connection *tls,
+ const char *label, void *out, size_t len ) {
+
+ /* Generate from ephemeral master secret and label */
+ tls_ephemeral ( tls, label, strlen ( label ), out, len );
+ DBGC2 ( tls, "TLS %p ephemeral %s:\n", tls, label );
+ DBGC2_HDA ( tls, 0, out, len );
+}
+
+/**
+ * Reset key schedule
+ *
+ * @v tls TLS connection
+ */
+static void tls_key_reset ( struct tls_connection *tls ) {
+ struct tls_key_schedule *key = &tls->key;
+
+ /* Derive a new ephemeral master secret */
+ tls_ephemeral_label ( tls, "key reset", key->ephemeral,
+ sizeof ( key->ephemeral ) );
+
+ /* (Re)generate client random bytes */
+ tls_ephemeral_label ( tls, "client random", &tls->client.random.random,
+ sizeof ( tls->client.random.random ) );
+}
+