MEDIUM: h1: generate WebSocket key on response if needed

Add the Sec-Websocket-Accept header on a websocket handshake response.
This header may be missing if a h2 server is used with a h1 client.

The response key is calculated following the rfc6455. For this, the
handshake request key must be stored in the h1 session, as a new field
name ws_key. Note that this is only done if the message has been
prealably identified as a Websocket handshake request.
diff --git a/src/h1.c b/src/h1.c
index ca39d97..95bcc1f 100644
--- a/src/h1.c
+++ b/src/h1.c
@@ -11,7 +11,11 @@
  */
 
 #include <ctype.h>
+
+#include <import/sha1.h>
+
 #include <haproxy/api.h>
+#include <haproxy/base64.h>
 #include <haproxy/h1.h>
 #include <haproxy/http-hdr.h>
 
@@ -1051,3 +1055,28 @@
 	}
 	return count - ofs;
 }
+
+#define H1_WS_KEY_SUFFIX_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
+
+/*
+ * Calculate the WebSocket handshake response key from <key_in>. Following the
+ * rfc6455, <key_in> must be 24 bytes longs. The result is  stored in <key_out>
+ * as a 29 bytes long string.
+ */
+void h1_calculate_ws_output_key(const char *key, char *result)
+{
+	blk_SHA_CTX sha1_ctx;
+	char hash_in[60], hash_out[20];
+
+	/* concatenate the key with a fixed suffix */
+	memcpy(hash_in, key, 24);
+	memcpy(&hash_in[24], H1_WS_KEY_SUFFIX_GUID, 36);
+
+	/* sha1 the result */
+	blk_SHA1_Init(&sha1_ctx);
+	blk_SHA1_Update(&sha1_ctx, hash_in, 60);
+	blk_SHA1_Final((unsigned char *)hash_out, &sha1_ctx);
+
+	/* encode in base64 the hash */
+	a2base64(hash_out, 20, result, 29);
+}