6d1a542003-03-13Niels Möller /* hash.cmod -*- c -*- */ #include "global.h" RCSID("$Id: hash.cmod,v 1.1 2003/03/13 14:55:22 nisse Exp $"); #include "interpret.h" #include "svalue.h" /* For this_object() */ #include "object.h" #include "module_support.h" #include "nettle_config.h" #ifdef HAVE_LIBNETTLE #include "nettle.h" #include <nettle/md5.h> #include <nettle/sha.h> #include <nettle/nettle-meta.h> #include <assert.h> #include <stdio.h> #include <stdarg.h> #if 0 static void werror(const char *format, ...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); } #else #define werror(x) #endif PIKECLASS nettle_hash { CVAR const struct nettle_hash *meta; PIKEFUN string name() { if (!THIS->meta) Pike_error("nettle_hash not properly initialized."); push_string(make_shared_string(THIS->meta->name)); } PIKEFUN int digest_size() { if (!THIS->meta) Pike_error("nettle_hash not properly initialized."); push_int(THIS->meta->digest_size); } PIKEFUN int block_size() { if (!THIS->meta) Pike_error("nettle_hash not properly initialized."); push_int(THIS->meta->block_size); } INIT { werror("nettle_hash->INIT\n"); THIS->meta = NULL; } } #define GET_META(o) \ ( ((struct nettle_hash_struct *) get_storage((o), nettle_hash_program)) \ ->meta) /* The algorithm objects have to be implemented in pike. */ PIKECLASS hash_instance { INHERIT nettle_hash; CVAR void *ctx; /* FIXME: Create should copy state from the other object, if * provided. */ PIKEFUN object update(string data) { const struct nettle_hash *meta = GET_META(this_object()); if (!THIS->ctx || !meta) Pike_error("hash_state not properly initialized."); NO_WIDE_STRING(data); meta->update(THIS->ctx, data->len, data->str); push_object(this_object()); } PIKEFUN string digest(int|void arg) { const struct nettle_hash *meta; struct pike_string *digest; unsigned length; if (! THIS->ctx) Pike_error("hash_state not properly initialized."); meta = GET_META(this_object()); assert(meta); if (!arg) length = meta->digest_size; else { if (arg->type != PIKE_T_INT) Pike_error("Bad argument type"); if (arg->u.integer <= 0) Pike_error("Invalid argument, must be positive.\n"); if (arg->u.integer > meta->digest_size) Pike_error("Unsupported digest length"); length = arg->u.integer; } digest = begin_shared_string(length); meta->digest(THIS->ctx, length, digest->str); push_string(end_shared_string(digest)); } INIT { werror("hash_instance->INIT\n"); THIS->ctx = NULL; } EXIT { werror("hash_instance->EXIT\n"); if (THIS->ctx) { const struct nettle_hash *meta = GET_META(this_object()); assert(meta); memset(THIS->ctx, 0, meta->context_size); } } } /*! @class nettle_md5 *! Internal mixin class, intended to be multiply inherited *! together with nettle_hash. */ PIKECLASS nettle_md5 { INIT { struct nettle_hash_struct *nettle_hash = (struct nettle_hash_struct *) get_storage(this_object(), nettle_hash_program); werror("nettle_md5->INIT\n"); if (nettle_hash || !nettle_hash->meta) nettle_hash->meta = &nettle_md5; else /* Can't call Pike_error here. * Pike_error("Can't initialize this object.\n"); */ werror("nettle_md5->INIT failed\n"); } } PIKECLASS md5_state { INHERIT nettle_md5; INHERIT hash_instance; CVAR struct md5_ctx md5; INIT { struct hash_instance_struct *instance = (struct hash_instance_struct *) get_storage(this_object(), hash_instance_program); werror("md5_state->INIT\n"); assert(instance); md5_init(&THIS->md5); instance->ctx = &THIS->md5; } } /*! @class nettle_sha1 *! Internal mixin class, intended to be multiply inherited *! together with nettle_hash. */ PIKECLASS nettle_sha1 { INIT { struct nettle_hash_struct *nettle_hash = (struct nettle_hash_struct *) get_storage(this_object(), nettle_hash_program); werror("nettle_sha1->INIT\n"); if (nettle_hash || !nettle_hash->meta) nettle_hash->meta = &nettle_sha1; else /* Can't call Pike_error here. * Pike_error("Can't initialize this object.\n"); */ werror("nettle_sha1->INIT failed\n"); } } PIKECLASS sha1_state { INHERIT nettle_sha1; INHERIT hash_instance; CVAR struct sha1_ctx sha1; INIT { struct hash_instance_struct *instance = (struct hash_instance_struct *) get_storage(this_object(), hash_instance_program); werror("sha1_state->INIT\n"); assert(instance); sha1_init(&THIS->sha1); instance->ctx = &THIS->sha1; } } void hash_init(void) { werror("Nettle, hash init\n"); INIT; } void hash_exit(void) { werror("Nettle, hash exit\n"); EXIT; } #endif /* HAVE_LIBNETTLE */