6d1a542003-03-13Niels Möller /* hash.cmod -*- c -*- */ #include "global.h"
3f286d2003-11-29Martin Nilsson RCSID("$Id: hash.cmod,v 1.14 2003/11/29 00:11:39 nilsson 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>
5c36c82003-08-26Martin Nilsson #ifdef HAVE_NETTLE_MD4_INIT
40f88a2003-08-01Martin Nilsson #include <nettle/md4.h>
5c36c82003-08-26Martin Nilsson #include <nettle/md2.h>
40f88a2003-08-01Martin Nilsson #endif
6d1a542003-03-13Niels Möller #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
411a282003-03-18Niels Möller /*! @module Nettle */
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)
f1c9f42003-08-05Martin Nilsson  Pike_error("HashInfo not properly initialized.\n");
6d1a542003-03-13Niels Möller 
3f286d2003-11-29Martin Nilsson  push_text(THIS->meta->name);
6d1a542003-03-13Niels Möller  }
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)
f1c9f42003-08-05Martin Nilsson  Pike_error("HashInfo not properly initialized.\n");
6d1a542003-03-13Niels Möller  push_int(THIS->meta->digest_size); }
cd26482003-03-18Niels Möller  /*! @decl string block_size(void) *!
f1c9f42003-08-05Martin Nilsson  *! Returns the internal block size of the hash algorithm.
cd26482003-03-18Niels Möller  */
6d1a542003-03-13Niels Möller  PIKEFUN int block_size() { if (!THIS->meta)
f1c9f42003-08-05Martin Nilsson  Pike_error("HashInfo not properly initialized.\n");
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; } }
411a282003-03-18Niels Möller /*! @endclass HashInfo */
6d1a542003-03-13Niels Möller #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. */
4a63d42003-03-18Martin Nilsson  /*! @decl HashState update(string data)
cd26482003-03-18Niels Möller  *! *! Hashes more data. */
6d1a542003-03-13Niels Möller  PIKEFUN object update(string data) {
9119632003-05-07Henrik Grubbström (Grubba)  const struct nettle_hash *meta = GET_META(Pike_fp->current_object);
6d1a542003-03-13Niels Möller  if (!THIS->ctx || !meta)
f1c9f42003-08-05Martin Nilsson  Pike_error("HashState not properly initialized.\n");
6d1a542003-03-13Niels Möller  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. *!
4a63d42003-03-18Martin Nilsson  *! @returns *! The digest.
cd26482003-03-18Niels Möller  */
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)
f1c9f42003-08-05Martin Nilsson  Pike_error("HashState not properly initialized.\n");
6d1a542003-03-13Niels Möller 
9119632003-05-07Henrik Grubbström (Grubba)  meta = GET_META(Pike_fp->current_object);
6d1a542003-03-13Niels Möller  assert(meta); if (!arg) length = meta->digest_size; else { if (arg->type != PIKE_T_INT)
f1c9f42003-08-05Martin Nilsson  Pike_error("Bad argument type.\n"); if (arg->u.integer < 0) Pike_error("Invalid length, must be positive.\n");
6d1a542003-03-13Niels Möller  if (arg->u.integer > meta->digest_size)
f1c9f42003-08-05Martin Nilsson  Pike_error("Unsupported digest length.\n");
6d1a542003-03-13Niels Möller  length = arg->u.integer; } digest = begin_shared_string(length); meta->digest(THIS->ctx, length, digest->str); push_string(end_shared_string(digest)); }
ac14652003-07-29Martin Nilsson 
6d1a542003-03-13Niels Möller  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");
983e2d2003-05-08Henrik Grubbström (Grubba)  if (THIS->ctx && Pike_fp->current_object->prog)
6d1a542003-03-13Niels Möller  {
9119632003-05-07Henrik Grubbström (Grubba)  const struct nettle_hash *meta = GET_META(Pike_fp->current_object);
6d1a542003-03-13Niels Möller  assert(meta); memset(THIS->ctx, 0, meta->context_size); } } }
411a282003-03-18Niels Möller /*! @endclass HashState */
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
9119632003-05-07Henrik Grubbström (Grubba)  = (struct HashInfo_struct *) get_storage(Pike_fp->current_object, HashInfo_program);
6d1a542003-03-13Niels Möller 
cd26482003-03-18Niels Möller  werror("MD5_Info->INIT\n");
6d1a542003-03-13Niels Möller 
411a282003-03-18Niels Möller  if (HashInfo && !HashInfo->meta)
cd26482003-03-18Niels Möller  HashInfo->meta = &nettle_md5;
ac14652003-07-29Martin Nilsson  else {
6d1a542003-03-13Niels Möller  /* 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");
ac14652003-07-29Martin Nilsson  }
6d1a542003-03-13Niels Möller  } }
411a282003-03-18Niels Möller /*! @endclass MD5_Info */
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
9119632003-05-07Henrik Grubbström (Grubba)  = (struct HashState_struct *) get_storage(Pike_fp->current_object, HashState_program);
cd26482003-03-18Niels Möller  werror("MD5_State->INIT\n");
6d1a542003-03-13Niels Möller  assert(instance); md5_init(&THIS->md5); instance->ctx = &THIS->md5; } }
411a282003-03-18Niels Möller /*! @endclass MD5_State */
6d1a542003-03-13Niels Möller 
5c36c82003-08-26Martin Nilsson #ifdef HAVE_NETTLE_MD4_INIT
40f88a2003-08-01Martin Nilsson  /*! @class MD4_Info *! *! Internal mixin class, intended to be multiply inherited *! together with HashInfo. */ PIKECLASS MD4_Info { INIT { struct HashInfo_struct *HashInfo = (struct HashInfo_struct *) get_storage(Pike_fp->current_object, HashInfo_program); werror("MD4_Info->INIT\n"); if (HashInfo && !HashInfo->meta) HashInfo->meta = &nettle_md4; else { /* Can't call Pike_error here. * Pike_error("Can't initialize this object.\n"); */ werror("MD4_Info->INIT failed\n"); } } } /*! @endclass MD4_Info */ /*! @class MD4_State *! *! State for MD4 hashing. */ PIKECLASS MD4_State { INHERIT MD4_Info; INHERIT HashState; CVAR struct md4_ctx md4; INIT { struct HashState_struct *instance = (struct HashState_struct *) get_storage(Pike_fp->current_object, HashState_program); werror("MD4_State->INIT\n"); assert(instance);
5c36c82003-08-26Martin Nilsson  md4_init(&THIS->md4);
40f88a2003-08-01Martin Nilsson  instance->ctx = &THIS->md4; } } /*! @endclass MD4_State */
5c36c82003-08-26Martin Nilsson /*! @class MD2_Info *! *! Internal mixin class, intended to be multiply inherited *! together with HashInfo. */ PIKECLASS MD2_Info { INIT { struct HashInfo_struct *HashInfo = (struct HashInfo_struct *) get_storage(Pike_fp->current_object, HashInfo_program); werror("MD2_Info->INIT\n"); if (HashInfo && !HashInfo->meta) HashInfo->meta = &nettle_md2; else { /* Can't call Pike_error here. * Pike_error("Can't initialize this object.\n"); */ werror("MD2_Info->INIT failed\n"); } } } /*! @endclass MD2_Info */ /*! @class MD2_State *! *! State for MD2 hashing. */ PIKECLASS MD2_State { INHERIT MD2_Info; INHERIT HashState; CVAR struct md2_ctx md2; INIT { struct HashState_struct *instance = (struct HashState_struct *) get_storage(Pike_fp->current_object, HashState_program); werror("MD2_State->INIT\n"); assert(instance); md2_init(&THIS->md2); instance->ctx = &THIS->md2; } } /*! @endclass MD2_State */ #endif /* HAVE_NETTLE_MD4_INIT */
40f88a2003-08-01Martin Nilsson 
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
9119632003-05-07Henrik Grubbström (Grubba)  = (struct HashInfo_struct *) get_storage(Pike_fp->current_object, HashInfo_program);
6d1a542003-03-13Niels Möller 
cd26482003-03-18Niels Möller  werror("SHA1_Info->INIT\n");
6d1a542003-03-13Niels Möller 
411a282003-03-18Niels Möller  if (HashInfo && !HashInfo->meta)
cd26482003-03-18Niels Möller  HashInfo->meta = &nettle_sha1;
ac14652003-07-29Martin Nilsson  else {
6d1a542003-03-13Niels Möller  /* 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");
ac14652003-07-29Martin Nilsson  }
6d1a542003-03-13Niels Möller  } }
411a282003-03-18Niels Möller /*! @endclass SHA1_Info */
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
9119632003-05-07Henrik Grubbström (Grubba)  = (struct HashState_struct *) get_storage(Pike_fp->current_object, HashState_program);
cd26482003-03-18Niels Möller  werror("SHA1_State->INIT\n");
6d1a542003-03-13Niels Möller  assert(instance); sha1_init(&THIS->sha1); instance->ctx = &THIS->sha1; } }
411a282003-03-18Niels Möller /*! @endclass SHA1_State */
6d1a542003-03-13Niels Möller 
0980772003-07-29Martin Nilsson /*! @class SHA256_Info *! *! Internal mixin class, intended to be multiply inherited *! together with HashInfo. */ PIKECLASS SHA256_Info { INIT { struct HashInfo_struct *HashInfo = (struct HashInfo_struct *) get_storage(Pike_fp->current_object, HashInfo_program); werror("SHA256_Info->INIT\n"); if (HashInfo && !HashInfo->meta) HashInfo->meta = &nettle_sha256; else { /* Can't call Pike_error here. * Pike_error("Can't initialize this object.\n"); */ werror("SHA256_Info->INIT failed\n"); } } } /*! @endclass SHA256_Info */ /*! @class SHA256_State *! *! State for SHA256 hashing. */ PIKECLASS SHA256_State { INHERIT SHA256_Info; INHERIT HashState; CVAR struct sha256_ctx sha256; INIT { struct HashState_struct *instance = (struct HashState_struct *) get_storage(Pike_fp->current_object, HashState_program); werror("SHA256_State->INIT\n"); assert(instance); sha256_init(&THIS->sha256); instance->ctx = &THIS->sha256; } } /*! @endclass SHA256_State */
411a282003-03-18Niels Möller /*! @endmodule Nettle */
6d1a542003-03-13Niels Möller  void hash_init(void) { werror("Nettle, hash init\n"); INIT; } void hash_exit(void) { werror("Nettle, hash exit\n"); EXIT; } #endif /* HAVE_LIBNETTLE */