pike.git / src / post_modules / Nettle / hash.cmod

version» Context lines:

pike.git/src/post_modules/Nettle/hash.cmod:1:   /* -*- c -*-   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. - || $Id$ +    */      #include "global.h"   #include "interpret.h"   #include "svalue.h"   #include "threads.h"      /* For this_object() */   #include "object.h"   #include "module_support.h" -  + #include "pike_memory.h"      #include "nettle_config.h"      #ifdef HAVE_LIBNETTLE      DECLARATIONS      #include "nettle.h"      #include <nettle/md5.h> - #ifdef HAVE_NETTLE_MD4_INIT +    #include <nettle/md4.h>   #include <nettle/md2.h> - #endif +    #include <nettle/sha.h> - #include <nettle/nettle-meta.h> + #ifdef HAVE_NETTLE_SHA3_H + #include <nettle/sha3.h> + #endif + #ifdef HAVE_NETTLE_RIPEMD160_H + #include <nettle/ripemd160.h> + #endif + #ifdef HAVE_NETTLE_GOSTHASH94_H + #include <nettle/gosthash94.h> + #endif    - #include <stdio.h> - #include <stdarg.h> +    #include "fdlib.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 -  - static struct program *Fd_ref_program = NULL; - static struct program *Fd_program = NULL; -  +    /*! @module Nettle */    - /*! @class HashInfo + /*! @class Hash    *!    *! Represents information about a hash algorithm, such as    *! name, digest size, and internal block size.    */ - PIKECLASS HashInfo + PIKECLASS Hash   { -  +  /*! @decl inherit __builtin.Nettle.Hash +  */ +  INHERIT "__builtin.Nettle.Hash"; +     CVAR const struct nettle_hash *meta;    -  /*! @decl string name(void) +  /*! @decl string(0..255) name(void)    *!    *! Returns a human readable name for the algorithm.    */ -  PIKEFUN string name() +  PIKEFUN string(0..255) name()    optflags OPT_TRY_OPTIMIZE;    {    if (!THIS->meta) -  Pike_error("HashInfo not properly initialized.\n"); +  Pike_error("Hash not properly initialized.\n");       push_text(THIS->meta->name);    }    -  /*! @decl string digest_size(void) +  /*! @decl int(0..) digest_size(void)    *! -  *! Returns the size of a hash digests. +  *! Returns the size of a hash digest.    */ -  PIKEFUN int digest_size() +  PIKEFUN int(0..) digest_size()    optflags OPT_TRY_OPTIMIZE;    {    if (!THIS->meta) -  Pike_error("HashInfo not properly initialized.\n"); +  Pike_error("Hash not properly initialized.\n");       push_int(THIS->meta->digest_size);    }    -  /*! @decl string block_size(void) +  /*! @decl int(0..) block_size(void)    *!    *! Returns the internal block size of the hash algorithm.    */ -  PIKEFUN int block_size() +  PIKEFUN int(0..) block_size()    optflags OPT_TRY_OPTIMIZE;    {    if (!THIS->meta) -  Pike_error("HashInfo not properly initialized.\n"); +  Pike_error("Hash not properly initialized.\n");       push_int(THIS->meta->block_size);    }       -  /*! @decl string hash(string data) +  /*! @decl string(0..255) hash(string(0..255) data)    *!    *! Works as a (faster) shortcut for -  *! @expr{HashState()->update(data)->digest()@}, where HashState is -  *! the hash state class corresponding to this HashInfo. +  *! @expr{State()->update(data)->digest()@}, where State is +  *! the hash state class corresponding to this Hash.    *!    *! @seealso -  *! @[HashState()->update()] and @[HashState()->digest()]. +  *! @[State()->update()] and @[State()->digest()].    */ -  PIKEFUN string hash(string in) +  PIKEFUN string(0..255) hash(string(0..255) in)    optflags OPT_TRY_OPTIMIZE;    {    void *ctx;    struct pike_string *out;    unsigned digest_length;    const struct nettle_hash *meta = THIS->meta;       if (!meta) -  Pike_error("HashInfo not properly initialized.\n"); +  Pike_error("Hash not properly initialized.\n");    NO_WIDE_STRING(in);    -  ctx = (void *)alloca(meta->context_size); +  ctx = alloca(meta->context_size);    if(!ctx)    SIMPLE_OUT_OF_MEMORY_ERROR("hash", meta->context_size);       /* Only thread this block for significant data size */ -  if (in->len > THREADS_ALLOW_THRESHOLD) { +  if (in->len > HASH_THREADS_ALLOW_THRESHOLD) {    THREADS_ALLOW();    meta->init(ctx);    meta->update(ctx, in->len, (const uint8_t *)in->str);    THREADS_DISALLOW();    } else {    meta->init(ctx);    meta->update(ctx, in->len, (const uint8_t *)in->str);    }       digest_length = meta->digest_size;    out = begin_shared_string(digest_length);    meta->digest(ctx, digest_length, (uint8_t *)out->str);       pop_n_elems(args);    push_string(end_shared_string(out));    }    -  /*! @decl string hash(Stdio.File file, void|int bytes) +  int is_stdio_file(struct object *o) +  { +  struct program *p = o->prog; +  INT32 i = p->num_inherits; +  while( i-- ) +  { +  if( p->inherits[i].prog->id == PROG_STDIO_FD_ID || +  p->inherits[i].prog->id == PROG_STDIO_FD_REF_ID ) +  return 1; +  } +  return 0; +  } +  +  /*! @decl string(0..255) hash(Stdio.File|Stdio.Buffer|String.Buffer|System.Memory source, void|int bytes)    *! -  *! Works as a (faster) shortcut for -  *! @expr{HashState()->update(Stdio.read_file(file))->digest()@}, -  *! where HashState is the hash state class corresponding to this -  *! HashInfo. +  *! Works as a (faster) shortcut for e.g. +  *! @expr{State()->update(Stdio.read_file(file))->digest()@}, +  *! where State is the hash state class corresponding to this +  *! Hash.    *!    *! @param bytes    *! The number of bytes of the file object @[file] that should be    *! hashed. Negative numbers are ignored and the whole file is    *! hashed.    *!    *! @seealso -  *! @[Stdio.File], @[HashState()->update()] and -  *! @[HashState()->digest()]. +  *! @[Stdio.File], @[State()->update()] and +  *! @[State()->digest()].    */ -  PIKEFUN string hash(object in, void|int bytes) +  PIKEFUN string(0..255) hash(object in, void|int bytes)    optflags OPT_EXTERNAL_DEPEND;    {    void *ctx; -  int len, fd; +  size_t len; +  int fd;    char *read_buffer;    PIKE_STAT_T st;    struct pike_string *out;    const struct nettle_hash *meta = THIS->meta;       if (!meta)    Pike_error("HashInfo not properly initialized.\n");    -  /* Verify that the input is a Stdio.Fd or Stdio.Fd_ref */ -  if (!Fd_program) -  { -  push_text("files.Fd"); -  SAFE_APPLY_MASTER("resolv",1); -  Fd_program = program_from_svalue(Pike_sp-1); -  if (!Fd_program) { -  pop_stack(); -  Pike_error("Unable to resolv files.Fd.\n"); -  } -  add_ref(Fd_program); -  pop_stack( ); -  } +  ctx = alloca(meta->context_size); +  if (!ctx) +  SIMPLE_OUT_OF_MEMORY_ERROR("hash", meta->context_size); +  meta->init(ctx);    -  if (!Fd_ref_program) +  if( get_memory_object_memory(in, (void **)&read_buffer, &len, NULL) )    { -  push_text("files.Fd_ref"); -  SAFE_APPLY_MASTER("resolv",1); -  Fd_ref_program = program_from_svalue(Pike_sp-1); -  if (!Fd_ref_program) { -  pop_stack(); -  Pike_error("Unable to resolv files.Fd_ref.\n"); +  if( bytes ) +  len = MINIMUM(len, MAXIMUM(bytes->u.integer,0) ); +  meta->update( ctx, len, (const uint8_t*)read_buffer); +  goto ret_meta;    } -  add_ref(Fd_ref_program); -  pop_stack( ); -  } +     -  if (!get_storage(in, Fd_program) && !get_storage(in, Fd_ref_program) ) -  Pike_error("Object not Fd or Fd_ref or subclass.\n"); +  if (!is_stdio_file(in)) +  Pike_error("Object not Fd or Fd_ref, or subclass or 8bit buffer.\n");    -  safe_apply(in, "query_fd", 0); +  apply(in, "query_fd", 0);    fd = Pike_sp[-1].u.integer;    pop_stack();       if (fd_fstat(fd, &st)<0)    Pike_error("File not found!\n");       if (!S_ISREG(st.st_mode))    Pike_error("Non-regular file.\n");    -  ctx = (void *)alloca(meta->context_size); -  if (!ctx) -  SIMPLE_OUT_OF_MEMORY_ERROR("hash", meta->context_size); +  read_buffer=xalloc(8192);    -  read_buffer=(char *)malloc(8192); -  if (!read_buffer) -  SIMPLE_OUT_OF_MEMORY_ERROR("hash", 8192); -  +     THREADS_ALLOW(); -  meta->init(ctx); -  if(args==2 && bytes->u.integer>-1) { +  if(bytes && bytes->u.integer>-1) {    int bytes_left = bytes->u.integer;    int read_bytes = MINIMUM(8192, bytes_left);    while(read_bytes>0 && (len=fd_read(fd, read_buffer, read_bytes))>0) {    meta->update(ctx, len, (const uint8_t *)read_buffer);    bytes_left -= read_bytes;    read_bytes = MINIMUM(8192, bytes_left);    }    }    else    while((len=fd_read(fd, read_buffer, 8192))>0)    meta->update(ctx, len, (const uint8_t *)read_buffer);       free(read_buffer);       THREADS_DISALLOW(); -  +  ret_meta:    out = begin_shared_string(meta->digest_size);    meta->digest(ctx, meta->digest_size, (uint8_t *)out->str);       pop_n_elems(args);    push_string(end_shared_string(out));    }    -  INIT +  /* NOTE: This is NOT the MIME base64 table! */ +  static const char b64tab[64] = +  "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +  +  static inline void b64enc(char *dest, int a, int b, int c, int sz)    { -  werror("HashInfo->INIT\n"); -  THIS->meta = NULL; +  unsigned int bitbuf = a | (b << 8) | (c << 16); +  while (sz--) { +  *(dest++) = b64tab[bitbuf & 63]; +  bitbuf >>= 6;    }    }    - /*! @endclass HashInfo */ +  /*! @decl string(0..127) crypt_hash(string(0..255) password, @ +  *! string(0..255) salt, int rounds) +  *! +  *! Password hashing function in @[crypt_md5()]-style. +  *! +  *! Implements the algorithm described in +  *! @url{http://www.akkadia.org/drepper/SHA-crypt.txt@}. +  *! +  *! This is the algorithm used by @tt{crypt(2)@} in +  *! methods @tt{$5$@} (SHA256) and @tt{$6$@} (SHA512). +  *! +  *! The @[password] memory will be cleared before released. +  *! +  *! @seealso +  *! @[crypt_md5()] +  */ +  PIKEFUN string(0..127) crypt_hash(string(0..255) password, +  string(0..255) salt, int rounds) +  { +  struct pike_string *res; +  const struct nettle_hash *meta = THIS->meta; +  void *ctx; +  uint8_t *abcbuf; +  uint8_t *dpbuf; +  uint8_t *dsbuf;    - #define GET_META(o) \ - ( ((struct HashInfo_struct *) get_storage((o), HashInfo_program)) \ -  ->meta) +  unsigned char *p; +  unsigned char *s; +  int plen; +  int slen; +  int dsz = meta->digest_size;    - /* The algorithm objects have to be implemented in pike. */ +  int i; +  int r;    - /*! @class HashState +  int a, b, c; +  +  if (!rounds) rounds = 5000; +  if (rounds < 1000) rounds = 1000; +  if (rounds > 999999999) rounds = 999999999; +  +  NO_WIDE_STRING(password); +  NO_WIDE_STRING(salt); +  +  password->flags |= STRING_CLEAR_ON_EXIT; +  +  ctx = alloca(meta->context_size); +  if (!ctx) +  SIMPLE_OUT_OF_MEMORY_ERROR("crypt_hash", meta->context_size); +  +  abcbuf = alloca(meta->digest_size * 3); +  if (!abcbuf) +  SIMPLE_OUT_OF_MEMORY_ERROR("crypt_hash", meta->digest_size * 3); +  +  dpbuf = abcbuf + meta->digest_size; +  dsbuf = dpbuf + meta->digest_size; +  +  /* NB: We use these to allow the compiler to +  * avoid dereferencing at every step. +  */ +  p = (unsigned char*)password->str; +  plen = password->len; +  s = (unsigned char*)salt->str; +  slen = salt->len; +  if (slen > 16) slen = 16; +  dsz = meta->digest_size; +  +  /* NB: We allocate the result here to avoid throwing away all the work +  * on out of memory at the end. +  */ +  if (dsz == 32) { +  /* 4 * (30/3) + 3 */ +  res = begin_shared_string(43); +  } else if (dsz == 64) { +  /* 4 * (63/3) + 2 */ +  res = begin_shared_string(86); +  } else { +  Pike_error("crypt_hash() not supported for this digest size yet (%d).\n", +  dsz); +  } +  +  THREADS_ALLOW(); +  +  /* NB: Comments refer to http://www.akkadia.org/drepper/SHA-crypt.txt */ +  meta->init(ctx); /* 4 */ +  meta->update(ctx, plen, p); /* 5 */ +  meta->update(ctx, slen, s); /* 6 */ +  meta->update(ctx, plen, p); /* 7 */ +  meta->digest(ctx, dsz, abcbuf); /* 8 */ +  +  /* 1 */ +  meta->update(ctx, plen, p); /* 2 */ +  meta->update(ctx, slen, s); /* 3 */ +  +  for (i = 0; i + dsz < plen; i += dsz) { /* 9 */ +  meta->update(ctx, dsz, abcbuf); +  } +  +  meta->update(ctx, plen - i, abcbuf); /* 10 */ +  +  for (i = 1; i < plen; i <<= 1) { /* 11 */ +  if (plen & i) { +  meta->update(ctx, dsz, abcbuf); +  } else { +  meta->update(ctx, plen, p); +  } +  } +  +  meta->digest(ctx, dsz, abcbuf); /* 12 */ +  +  /* 13 */ +  for (i = 0; i < plen; i++) { /* 14 */ +  meta->update(ctx, plen, p); +  } +  meta->digest(ctx, dsz, dpbuf); /* 15 */ +  +  /* Sequence P is implicit. */ /* 16 */ +  +  /* 17 */ +  for(i = 0; i < 16 + abcbuf[0]; i++) { /* 18 */ +  meta->update(ctx, slen, s); +  } +  meta->digest(ctx, dsz, dsbuf); /* 19 */ +  +  /* Sequence S is implicit. */ /* 20 */ +  +  for (r = 0; r < rounds; r++) { /* 21 */ +  /* a */ +  if (r & 1) { /* b */ +  for (i = 0; i + dsz < plen; i += dsz) { +  meta->update(ctx, dsz, dpbuf); +  } +  meta->update(ctx, plen - i, dpbuf); +  } else { +  meta->update(ctx, dsz, abcbuf); /* c */ +  } +  if (r % 3) /* d */ +  meta->update(ctx, slen, dsbuf); +  if (r % 7) { /* e */ +  for (i = 0; i + dsz < plen; i += dsz) { +  meta->update(ctx, dsz, dpbuf); +  } +  meta->update(ctx, plen - i, dpbuf); +  } +  if (r & 1) { /* f */ +  meta->update(ctx, dsz, abcbuf); +  } else { /* g */ +  for (i = 0; i + dsz < plen; i += dsz) { +  meta->update(ctx, dsz, dpbuf); +  } +  meta->update(ctx, plen - i, dpbuf); +  } +  meta->digest(ctx, dsz, abcbuf); /* h */ +  } +  THREADS_DISALLOW(); +  +  /* And now time for some pointless shuffling of the result. +  * Note that the shuffling is slightly different between +  * the two cases. +  * +  * This is followed by a custom base64-style encoding. +  */ +  c = 0; +  b = dsz/3; +  a = 2*b; +  if (dsz == 32) { +  for (i = 0, r = 0; i + 3 < dsz; i+=3, r+=4) { +  int t; +  b64enc(res->str + r, abcbuf[a], abcbuf[b], abcbuf[c], 4); +  +  t = a+1; +  a = b+1; +  b = c+1; +  c = t; +  } +  b64enc(res->str + r, abcbuf[30], abcbuf[31], 0, 3); +  } else { +  for (i = 0, r = 0; i + 3 < dsz; i+=3, r+=4) { +  int t; +  b64enc(res->str + r, abcbuf[a], abcbuf[b], abcbuf[c], 4); +  +  t = a+1; +  a = c+1; +  c = b+1; +  b = t; +  } +  b64enc(res->str + r, abcbuf[63], 0, 0, 2); +  } +  +  push_string(end_shared_string(res)); /* 22e */ +  +  /* Clean intermediate values. */ +  memset(ctx, 0, meta->context_size); +  memset(abcbuf, 0, 3*dsz); +  } +  +  INIT +  { +  werror("Hash->INIT\n"); +  THIS->meta = NULL; +  } +  +  /*! @class State    *!    *! Base class for hashing contexts.    */ - PIKECLASS HashState +  PIKECLASS State +  program_flags PROGRAM_USES_PARENT|PROGRAM_NEEDS_PARENT|PROGRAM_CLEAR_STORAGE;    { -  INHERIT HashInfo; +  DOCSTART() @decl inherit Hash::State +  DOCEND() +  +  EXTRA +  { +  /* Perform an inherit of the State class (if any) that our parent +  * may contain via its inherit of __builtin.Nettle.Hash. +  */ +  struct program *parent_prog = Pike_compiler->previous->new_program; +  struct object *parent_obj = Pike_compiler->previous->fake_object; +  int parent_State_fun_num = +  really_low_find_shared_string_identifier(MK_STRING("State"), +  parent_prog, +  SEE_PROTECTED|SEE_PRIVATE); +  if (parent_State_fun_num >= 0) { +  struct program *parent_State_prog = +  low_program_from_function(parent_obj, parent_State_fun_num); +  if (parent_State_prog) { +  parent_State_fun_num = +  really_low_reference_inherited_identifier(Pike_compiler->previous, +  0, parent_State_fun_num); +  low_inherit(parent_State_prog, 0, +  parent_State_fun_num, +  1 + 42, 0, NULL); +  } +  } +  } +  + #define GET_META(o) \ +  ( ((struct Nettle_Hash_struct *)parent_storage(1, Nettle_Hash_program))->meta ) +     CVAR void *ctx;       /* FIXME: Create should copy state from the other object, if    * provided. */    -  /*! @decl HashState update(string data) +  /*! @decl State update(string(0..255) data)    *!    *! Hashes more data. -  +  *! +  *! @returns +  *! Returns @expr{this@} in order to simplify chaining +  *! of function calls.    */ -  PIKEFUN object update(string data) +  PIKEFUN object update(string(0..255) data)    optflags OPT_SIDE_EFFECT; -  +  rawtype tFunc(tStr8, tObjImpl_NETTLE_HASH_STATE);    {    void *ctx = THIS->ctx;    const struct nettle_hash *meta =    GET_META(Pike_fp->current_object);       if (!ctx || !meta) -  Pike_error("HashState not properly initialized.\n"); +  Pike_error("State not properly initialized.\n");       NO_WIDE_STRING(data);       /* Only thread this block for significant data size */ -  if (data->len > THREADS_ALLOW_THRESHOLD) { +  if (data->len > HASH_THREADS_ALLOW_THRESHOLD) {    THREADS_ALLOW();    meta->update(ctx, data->len, (const uint8_t *)data->str);    THREADS_DISALLOW();    } else {    meta->update(ctx, data->len, (const uint8_t *)data->str);    }       push_object(this_object());    }    -  /*! @decl string digest(int|void length) +  /*! @decl string(0..255) digest(int|void length)    *! -  *! Generates a digests, and resets the hashing contents. +  *! Generates a digest, and resets the hashing contents.    *!    *! @param length    *! If the length argument is provided, the digest is truncated    *! to the given length.    *!    *! @returns    *! The digest.    */ -  PIKEFUN string digest(int|void arg) +  PIKEFUN string(0..255) digest(int|void arg)    {    const struct nettle_hash *meta;    struct pike_string *digest;    unsigned length;    -  if (! THIS->ctx) -  Pike_error("HashState not properly initialized.\n"); -  +     meta = GET_META(Pike_fp->current_object); -  assert(meta); +     -  +  if (!THIS->ctx || !meta) +  Pike_error("State not properly initialized.\n"); +     if (!arg)    length = meta->digest_size;    else    {    if (TYPEOF(*arg) != PIKE_T_INT)    Pike_error("Bad argument type.\n");    if (arg->u.integer < 0)    Pike_error("Invalid length, must be positive.\n");    if ((unsigned)arg->u.integer > meta->digest_size)    Pike_error("Unsupported digest length.\n");
pike.git/src/post_modules/Nettle/hash.cmod:340:    length = arg->u.integer;    }       digest = begin_shared_string(length);    meta->digest(THIS->ctx, length, (uint8_t *)digest->str);    push_string(end_shared_string(digest));    }       INIT    { -  werror("HashState->INIT\n"); +  werror("State->INIT\n");    THIS->ctx = NULL;    }       EXIT -  gc_trivial; +     { -  werror("HashState->EXIT\n"); -  if (THIS->ctx && Pike_fp->current_object->prog) +  werror("State->EXIT\n"); +  if (THIS->ctx)    {    const struct nettle_hash *meta =    GET_META(Pike_fp->current_object); -  assert(meta); +  if (meta) {    memset(THIS->ctx, 0, meta->context_size);    }    }    } -  - /*! @endclass HashState */ -  - /*! @class MD5_Info -  *! -  *! Internal mixin class, intended to be multiply inherited -  *! together with HashInfo. */ -  - PIKECLASS MD5_Info - { -  INIT -  { -  struct HashInfo_struct *HashInfo -  = (struct HashInfo_struct *) get_storage(Pike_fp->current_object, -  HashInfo_program); -  -  werror("MD5_Info->INIT\n"); -  -  if (HashInfo && !HashInfo->meta) -  HashInfo->meta = &nettle_md5; -  else { -  /* Can't call Pike_error here. -  * Pike_error("Can't initialize this object.\n"); */ -  werror("MD5_Info->INIT failed\n"); +     } -  } - } +     - /*! @endclass MD5_Info */ +  /*! @endclass State */    - /*! @class MD5_State -  *! -  *! State for MD5 hashing. -  */ - PIKECLASS MD5_State - { -  INHERIT MD5_Info; -  INHERIT HashState; -  CVAR struct md5_ctx md5; -  -  INIT -  { -  struct HashState_struct *instance -  = (struct HashState_struct *) get_storage(Pike_fp->current_object, -  HashState_program); -  werror("MD5_State->INIT\n"); -  -  assert(instance); -  -  md5_init(&THIS->md5); -  instance->ctx = &THIS->md5; +    } - } - /*! @endclass MD5_State */ +     - #ifdef HAVE_NETTLE_MD4_INIT + /*! @endclass Hash */    - /*! @class MD4_Info -  *! -  *! Internal mixin class, intended to be multiply inherited -  *! together with HashInfo. */ + /* The algorithm objects can be overloaded in pike. */    - PIKECLASS MD4_Info - { -  INIT -  { -  struct HashInfo_struct *HashInfo -  = (struct HashInfo_struct *) get_storage(Pike_fp->current_object, -  HashInfo_program); + #cmod_define TOSTR(DEF) #DEF    -  werror("MD4_Info->INIT\n"); + #cmod_define PIKE_NAME MD5 + #cmod_define NETTLE_NAME md5 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    -  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"); -  } -  } - } + #cmod_define PIKE_NAME MD4 + #cmod_define NETTLE_NAME md4 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    - /*! @endclass MD4_Info */ + #cmod_define PIKE_NAME MD2 + #cmod_define NETTLE_NAME md2 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    - /*! @class MD4_State -  *! -  *! State for MD4 hashing. -  */ - PIKECLASS MD4_State - { -  INHERIT MD4_Info; -  INHERIT HashState; -  CVAR struct md4_ctx md4; + #cmod_define PIKE_NAME SHA1 + #cmod_define NETTLE_NAME sha1 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    -  INIT -  { -  struct HashState_struct *instance -  = (struct HashState_struct *) get_storage(Pike_fp->current_object, -  HashState_program); -  werror("MD4_State->INIT\n"); + #ifdef HAVE_NETTLE_SHA224_INIT    -  assert(instance); + #cmod_define PIKE_NAME SHA224 + #cmod_define NETTLE_NAME sha224 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    -  md4_init(&THIS->md4); -  instance->ctx = &THIS->md4; -  } - } - /*! @endclass MD4_State */ + #endif    - /*! @class MD2_Info -  *! -  *! Internal mixin class, intended to be multiply inherited -  *! together with HashInfo. */ + #cmod_define PIKE_NAME SHA256 + #cmod_define NETTLE_NAME sha256 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    - PIKECLASS MD2_Info - { -  INIT -  { -  struct HashInfo_struct *HashInfo -  = (struct HashInfo_struct *) get_storage(Pike_fp->current_object, -  HashInfo_program); + #ifdef SHA384_DIGEST_SIZE    -  werror("MD2_Info->INIT\n"); + #cmod_define PIKE_NAME SHA384 + #cmod_define NETTLE_NAME sha384 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    -  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"); -  } -  } - } + #endif /* SHA384_DIGEST_SIZE */    - /*! @endclass MD2_Info */ + #ifdef SHA512_DIGEST_SIZE    - /*! @class MD2_State -  *! -  *! State for MD2 hashing. -  */ - PIKECLASS MD2_State - { -  INHERIT MD2_Info; -  INHERIT HashState; -  CVAR struct md2_ctx md2; + #cmod_define PIKE_NAME SHA512 + #cmod_define NETTLE_NAME sha512 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    -  INIT -  { -  struct HashState_struct *instance -  = (struct HashState_struct *) get_storage(Pike_fp->current_object, -  HashState_program); -  werror("MD2_State->INIT\n"); + #endif /* SHA512_DIGEST_SIZE */    -  assert(instance); + #ifdef SHA512_224_DIGEST_SIZE    -  md2_init(&THIS->md2); -  instance->ctx = &THIS->md2; -  } - } - /*! @endclass MD2_State */ + #cmod_define PIKE_NAME SHA512_224 + #cmod_define NETTLE_NAME sha512_224 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    - #endif /* HAVE_NETTLE_MD4_INIT */ + #endif /* SHA512_224_DIGEST_SIZE */    - /*! @class SHA1_Info -  *! -  *! Internal mixin class, intended to be multiply inherited -  *! together with HashInfo. */ + #ifdef SHA512_256_DIGEST_SIZE    - PIKECLASS SHA1_Info - { -  INIT -  { -  struct HashInfo_struct *HashInfo -  = (struct HashInfo_struct *) get_storage(Pike_fp->current_object, -  HashInfo_program); + #cmod_define PIKE_NAME SHA512_256 + #cmod_define NETTLE_NAME sha512_256 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    -  werror("SHA1_Info->INIT\n"); + #endif /* SHA512_256_DIGEST_SIZE */    -  if (HashInfo && !HashInfo->meta) -  HashInfo->meta = &nettle_sha1; -  else { -  /* Can't call Pike_error here. -  * Pike_error("Can't initialize this object.\n"); */ -  werror("SHA1_Info->INIT failed\n"); -  } -  } - } + #ifdef HAVE_NETTLE_SHA3_H    - /*! @endclass SHA1_Info */ + #cmod_define PIKE_NAME SHA3_224 + #cmod_define NETTLE_NAME sha3_224 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    - /*! @class SHA1_State -  *! -  *! State for SHA1 hashing. -  */ + #cmod_define PIKE_NAME SHA3_256 + #cmod_define NETTLE_NAME sha3_256 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    - PIKECLASS SHA1_State - { -  INHERIT SHA1_Info; -  INHERIT HashState; -  CVAR struct sha1_ctx sha1; + #cmod_define PIKE_NAME SHA3_384 + #cmod_define NETTLE_NAME sha3_384 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    -  INIT -  { -  struct HashState_struct *instance -  = (struct HashState_struct *) get_storage(Pike_fp->current_object, -  HashState_program); -  werror("SHA1_State->INIT\n"); + #cmod_define PIKE_NAME SHA3_512 + #cmod_define NETTLE_NAME sha3_512 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    -  assert(instance); + #endif /* HAVE_NETTLE_SHA3_H */    -  sha1_init(&THIS->sha1); -  instance->ctx = &THIS->sha1; -  } - } - /*! @endclass SHA1_State */ + #ifdef HAVE_NETTLE_RIPEMD160_H    - /*! @class SHA256_Info -  *! -  *! Internal mixin class, intended to be multiply inherited -  *! together with HashInfo. */ + #cmod_define PIKE_NAME RIPEMD160 + #cmod_define NETTLE_NAME ripemd160 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    - PIKECLASS SHA256_Info - { -  INIT -  { -  struct HashInfo_struct *HashInfo -  = (struct HashInfo_struct *) get_storage(Pike_fp->current_object, -  HashInfo_program); + #endif    -  werror("SHA256_Info->INIT\n"); + #ifdef HAVE_NETTLE_GOSTHASH94_H    -  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"); -  } -  } - } + #cmod_define PIKE_NAME GOST94 + #cmod_define NETTLE_NAME gosthash94 + #cmod_include "hash.H" + #cmod_undef PIKE_NAME + #cmod_undef NETTLE_NAME    - /*! @endclass SHA256_Info */ + #endif    - /*! @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 */ -  +    /*! @endmodule Nettle */      void   hash_init(void)   {    werror("Nettle, hash init\n");    INIT;   }      void   hash_exit(void)   {    werror("Nettle, hash exit\n"); -  if (Fd_program) { -  free_program( Fd_program ); -  } -  if (Fd_ref_program) { -  free_program( Fd_ref_program ); -  } +     EXIT;   }      #endif /* HAVE_LIBNETTLE */