--- /dev/null
+/*
+ * crypto - Tcl bindings for parts of the `nettle' crypto library
+ * Copyright 2006 Ian Jackson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+
+#include "chiark_tcl_crypto.h"
+
+typedef struct {
+ int ix;
+ const HashAlgInfo *alg;
+ Byte d[1];
+} HashState;
+
+int cht_do_hbcrypto_hash(ClientData cd, Tcl_Interp *ip, const HashAlgInfo *alg,
+ HBytes_Value message, HBytes_Value *result) {
+ Byte *dest;
+
+ dest= cht_hb_arrayspace(result,alg->hashsize);
+ alg->oneshot(dest, cht_hb_data(&message), cht_hb_len(&message));
+ return TCL_OK;
+}
+
+int cht_do_hbcrypto_hash_init(ClientData cd, Tcl_Interp *ip,
+ const HashAlgInfo *alg, void **state_r) {
+ HashState *state= TALLOC(sizeof(*state) + alg->statesize - 1);
+ state->ix= -1;
+ state->alg= alg;
+ alg->init(state->d);
+ *state_r= state;
+ return TCL_OK;
+}
+
+int cht_do_hbcrypto_hash_update(ClientData cd, Tcl_Interp *ip,
+ void *state_v, HBytes_Value data) {
+ HashState *state= state_v;
+ state->alg->update(&state->d, cht_hb_data(&data), cht_hb_len(&data));
+ return TCL_OK;
+}
+
+int cht_do_hbcrypto_hash_final(ClientData cd, Tcl_Interp *ip,
+ void *state_v, HBytes_Value *result) {
+ HashState *state= state_v;
+ Byte *digest;
+
+ digest= cht_hb_arrayspace(result,state->alg->hashsize);
+ state->alg->final(&state->d, digest);
+ return cht_do_hbcrypto_hash_discard(cd,ip,state_v);
+}
+
+int cht_do_hbcrypto_hash_discard(ClientData cd, Tcl_Interp *ip,
+ void *state_v) {
+ cht_tabledataid_disposing(ip,state_v,&cht_hash_states);
+ free(state_v);
+ return TCL_OK;
+}
+
+int cht_do_hbcrypto_hash_clonestate(ClientData cd, Tcl_Interp *ip,
+ void *old_v, void **new_r) {
+ HashState *old= old_v;
+ int len= sizeof(*old) + old->alg->statesize - 1;
+ void *new_v= TALLOC(len);
+ memcpy(new_v, old, len);
+ ((HashState*)new_v)->ix= -1;
+ *new_r= new_v;
+ return TCL_OK;
+}
+
+
+static void destroy_idtabcb(Tcl_Interp *ip, void *state_v) {
+ free(state_v);
+}
+
+const IdDataSpec cht_hash_states= {
+ "hashstate", "hashstate-table", destroy_idtabcb
+};