6d1a542003-03-13Niels Möller /* hash.cmod -*- c -*- */ #include "global.h"
cd26482003-03-18Niels Möller RCSID("$Id: hash.cmod,v 1.2 2003/03/18 13:35:31 nisse Exp $");
6d1a542003-03-13Niels Möller #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
cd26482003-03-18Niels Möller /*! @class HashInfo *! *! Represents information about a hash algorithm, such as *! name, digest size, and internal block size. */ PIKECLASS HashInfo
6d1a542003-03-13Niels Möller { CVAR const struct nettle_hash *meta;
cd26482003-03-18Niels Möller  /*! @decl string name(void) *! *! Returns a human readable name for the algorithm. */
6d1a542003-03-13Niels Möller  PIKEFUN string name() { if (!THIS->meta)
cd26482003-03-18Niels Möller  Pike_error("HashInfo not properly initialized.");
6d1a542003-03-13Niels Möller  push_string(make_shared_string(THIS->meta->name)); }
cd26482003-03-18Niels Möller  /*! @decl string digest_size(void) *! *! Returns the size of a hash digests. */
6d1a542003-03-13Niels Möller  PIKEFUN int digest_size() { if (!THIS->meta)
cd26482003-03-18Niels Möller  Pike_error("HashInfo not properly initialized.");
6d1a542003-03-13Niels Möller  push_int(THIS->meta->digest_size); }
cd26482003-03-18Niels Möller  /*! @decl string block_size(void) *! *! REturns the internal block size of the hash algorithm. */
6d1a542003-03-13Niels Möller  PIKEFUN int block_size() { if (!THIS->meta)
cd26482003-03-18Niels Möller  Pike_error("HashInfo not properly initialized.");
6d1a542003-03-13Niels Möller  push_int(THIS->meta->block_size); } INIT {
cd26482003-03-18Niels Möller  werror("HashInfo->INIT\n");
6d1a542003-03-13Niels Möller  THIS->meta = NULL; } } #define GET_META(o) \
cd26482003-03-18Niels Möller ( ((struct HashInfo_struct *) get_storage((o), HashInfo_program)) \
6d1a542003-03-13Niels Möller  ->meta) /* The algorithm objects have to be implemented in pike. */
cd26482003-03-18Niels Möller /*! @class HashState *! *! Base class for hashing contexts. */ PIKECLASS HashState
6d1a542003-03-13Niels Möller {
cd26482003-03-18Niels Möller  INHERIT HashInfo;
6d1a542003-03-13Niels Möller  CVAR void *ctx; /* FIXME: Create should copy state from the other object, if * provided. */
cd26482003-03-18Niels Möller  /*! @decl object update(string data) *! *! Hashes more data. *! @returns this_object(). */
6d1a542003-03-13Niels Möller  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()); }
cd26482003-03-18Niels Möller  /*! @decl string digest(int|void length) *! *! Generates a digests, and resets the hashing contents. *! *! @param length *! If the length argument is provided, the digest is truncated *! to the given length. *! *! @returns the digest. */
6d1a542003-03-13Niels Möller  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 {
cd26482003-03-18Niels Möller  werror("HashState->INIT\n");
6d1a542003-03-13Niels Möller  THIS->ctx = NULL; } EXIT {
cd26482003-03-18Niels Möller  werror("HashState->EXIT\n");
6d1a542003-03-13Niels Möller  if (THIS->ctx) { const struct nettle_hash *meta = GET_META(this_object()); assert(meta); memset(THIS->ctx, 0, meta->context_size); } } }
cd26482003-03-18Niels Möller /*! @class MD5_Info *!
6d1a542003-03-13Niels Möller  *! Internal mixin class, intended to be multiply inherited
cd26482003-03-18Niels Möller  *! together with HashInfo. */
6d1a542003-03-13Niels Möller 
cd26482003-03-18Niels Möller PIKECLASS MD5_Info
6d1a542003-03-13Niels Möller { INIT {
cd26482003-03-18Niels Möller  struct HashInfo_struct *HashInfo = (struct HashInfo_struct *) get_storage(this_object(), HashInfo_program);
6d1a542003-03-13Niels Möller 
cd26482003-03-18Niels Möller  werror("MD5_Info->INIT\n");
6d1a542003-03-13Niels Möller 
cd26482003-03-18Niels Möller  if (HashInfo || !HashInfo->meta) HashInfo->meta = &nettle_md5;
6d1a542003-03-13Niels Möller  else /* Can't call Pike_error here. * Pike_error("Can't initialize this object.\n"); */
cd26482003-03-18Niels Möller  werror("MD5_Info->INIT failed\n");
6d1a542003-03-13Niels Möller  } }
cd26482003-03-18Niels Möller /*! @class MD5_State *! *! State for MD5 hashing. */ PIKECLASS MD5_State
6d1a542003-03-13Niels Möller {
cd26482003-03-18Niels Möller  INHERIT MD5_Info; INHERIT HashState;
6d1a542003-03-13Niels Möller  CVAR struct md5_ctx md5; INIT {
cd26482003-03-18Niels Möller  struct HashState_struct *instance = (struct HashState_struct *) get_storage(this_object(), HashState_program); werror("MD5_State->INIT\n");
6d1a542003-03-13Niels Möller  assert(instance); md5_init(&THIS->md5); instance->ctx = &THIS->md5; } }
cd26482003-03-18Niels Möller /*! @class SHA1_Info *!
6d1a542003-03-13Niels Möller  *! Internal mixin class, intended to be multiply inherited
cd26482003-03-18Niels Möller  *! together with HashInfo. */
6d1a542003-03-13Niels Möller 
cd26482003-03-18Niels Möller PIKECLASS SHA1_Info
6d1a542003-03-13Niels Möller { INIT {
cd26482003-03-18Niels Möller  struct HashInfo_struct *HashInfo = (struct HashInfo_struct *) get_storage(this_object(), HashInfo_program);
6d1a542003-03-13Niels Möller 
cd26482003-03-18Niels Möller  werror("SHA1_Info->INIT\n");
6d1a542003-03-13Niels Möller 
cd26482003-03-18Niels Möller  if (HashInfo || !HashInfo->meta) HashInfo->meta = &nettle_sha1;
6d1a542003-03-13Niels Möller  else /* Can't call Pike_error here. * Pike_error("Can't initialize this object.\n"); */
cd26482003-03-18Niels Möller  werror("SHA1_Info->INIT failed\n");
6d1a542003-03-13Niels Möller  } }
cd26482003-03-18Niels Möller /*! @class SHA1_State *! *! State for SHA1 hashing. */ PIKECLASS SHA1_State
6d1a542003-03-13Niels Möller {
cd26482003-03-18Niels Möller  INHERIT SHA1_Info; INHERIT HashState;
6d1a542003-03-13Niels Möller  CVAR struct sha1_ctx sha1; INIT {
cd26482003-03-18Niels Möller  struct HashState_struct *instance = (struct HashState_struct *) get_storage(this_object(), HashState_program); werror("SHA1_State->INIT\n");
6d1a542003-03-13Niels Möller  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 */