--- /dev/null
+#define _POSIX_C_SOURCE 200809L
+
+#include "tlse.h"
+
+void tls_destroy_hash(struct TLSContext *context) {
+ if (context) {
+ context->hs_index = -1;
+ }
+ return;
+}
+
+static void create_hash(struct TLSContext *context) {
+ int index;
+
+ if (!context) {
+ return;
+ }
+
+ int hash_size = tls_mac_length(context);
+
+ if (hash_size == TLS_SHA384_MAC_SIZE) {
+ index = find_hash("sha384");
+ } else {
+ index = find_hash("sha256");
+ }
+ context->hs_index = index;
+ context->handshake_init = hash_descriptor[index].init;
+ context->handshake_process = hash_descriptor[index].process;
+ context->handshake_done = hash_descriptor[index].done;
+
+ context->handshake_init(&context->hs_hash);
+ context->hs_created = 1;
+}
+
+int tls_update_hash(struct TLSContext *context, const unsigned char *in,
+ unsigned int len) {
+ if (!context) {
+ return 0;
+ }
+
+ if (!len) {
+ return 0;
+ }
+
+ if (!context->hs_created) {
+ create_hash(context);
+ }
+
+ context->handshake_process(&context->hs_hash, in, len);
+
+ if (context->request_client_certificate) {
+ tls_buffer_append(&context->cached_handshake, in, len);
+ }
+ return 0;
+}
+
+int tls_done_hash(struct TLSContext *context, unsigned char *hout) {
+ if (!context) {
+ return 0;
+ }
+
+ if (!context->hs_created) {
+ return 0;
+ }
+
+ if (hout) {
+ context->handshake_done(&context->hs_hash, hout);
+ }
+ /* TODO zero memory? */
+ context->hs_created = 0;
+
+ tls_buffer_free(&context->cached_handshake);
+ return tls_mac_length(context);
+}
+
+int tls_get_hash_idx(struct TLSContext *context) {
+ if (!context) {
+ return -1;
+ }
+
+ switch (tls_mac_length(context)) {
+ case TLS_SHA256_MAC_SIZE:
+ return find_hash("sha256");
+ case TLS_SHA384_MAC_SIZE:
+ return find_hash("sha384");
+ case TLS_SHA1_MAC_SIZE:
+ return find_hash("sha1");
+ }
+ return -1;
+}
+
+int tls_get_hash(struct TLSContext *context, unsigned char *hout) {
+ hash_state prec;
+
+ if (!context) {
+ return 0;
+ }
+
+ if (!context->hs_created) {
+ return 0;
+ }
+
+ prec = context->hs_hash;
+
+ context->handshake_done(&prec, hout);
+
+ return tls_mac_length(context);
+}