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

version» Context lines:

pike.git/src/post_modules/Nettle/nettle.cmod:1: + /* nettle.cmod -*- c -*- */    -  + #include "global.h" + RCSID("$Id: nettle.cmod,v 1.1 2003/03/12 17:07:10 nisse Exp $"); + #include "interpret.h" + #include "svalue.h" +  + /* For this_object() */ + #include "object.h" +  + #include "module_support.h" +  + #include "nettle.h" +  + #include <nettle/md5.h> + #include <nettle/aes.h> + #include <nettle/sha.h> + #include <nettle/nettle-meta.h> +  + #include <assert.h> + #include <stdio.h> + #include <stdarg.h> +  + /* #define sp Pike_sp */ +  + DECLARATIONS +  + #if 1 + void + werror(const char *format, ...) + { +  va_list args; +  +  va_start(args, format); +  vfprintf(stderr, format, args); +  va_end(args); + } + #endif +  + /*! @module Nettle +  */ +  + 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) +  +  + PIKECLASS hash_state + { +  INHERIT nettle_hash; +  +  /* FIXME: The ctx pointer isn't strictly needed, as the ctx is in +  * the storage area just after the poitner. But this seems like the +  * simplest and most portable way to get to it. */ +  CVAR void *ctx; +  +  PIKEFUN object update(string data) +  { +  const struct nettle_hash *meta; +  +  if (! THIS->ctx) +  Pike_error("hash_state not properly initialized."); +  +  meta = GET_META(this_object()); +  +  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; +  INT32 length; +  +  if (! THIS->ctx) +  Pike_error("hash_state not properly initialized."); +  +  meta = GET_META(this_object()); +  +  if (!arg) +  length = meta->digest_size; +  else +  { +  if (arg->type != PIKE_T_INT) +  Pike_error("Bad argument type"); +  length = arg->u.integer; +  if (length <= 0 || length > meta->digest_size) +  Pike_error("Unsupported digest length"); +  } +  +  digest = begin_shared_string(length); +  meta->digest(THIS->ctx, length, digest->str); +  push_string(end_shared_string(digest)); +  } +  INIT +  { +  /* werror("hash_state->INIT\n"); */ +  THIS->ctx = NULL; +  } + } +  + PIKECLASS sha1_state + { +  INHERIT hash_state; +  CVAR struct sha1_ctx ctx; +  +  /* FIXME: Move this to the generic hash_state class. */ +  PIKEFUN void create(void|object arg) +  { +  struct sha1_state_struct *other; +  +  if (!arg) +  return; +  +  if ( (arg->type == PIKE_T_OBJECT) +  && ((other = (struct sha1_state_struct *) +  get_storage(arg->u.object, sha1_state_program))) ) +  { +  memcpy(&THIS->ctx, &other->ctx, sizeof(THIS->ctx)); +  return; +  } +  else +  Pike_error("Can't copy an incompatible hash state."); +  } +  +  INIT +  { +  struct hash_state_struct *hash_state; +  struct nettle_hash_struct *nettle_hash; +  +  /* werror("sha1_state->INIT\n"); */ +  +  hash_state = (struct hash_state_struct *) +  get_storage(this_object(), hash_state_program); +  nettle_hash = (struct nettle_hash_struct *) +  get_storage(this_object(), nettle_hash_program); +  +  assert(hash_state); +  assert(nettle_hash); +  +  nettle_hash->meta = &nettle_sha1; +  hash_state->ctx = &THIS->ctx; +  +  sha1_init(&THIS->ctx); +  } + } +  + PIKECLASS md5 + { +  CVAR struct md5_ctx ctx; +  +  PIKEFUN string name() +  { +  push_string(make_shared_string("md5")); +  } +  +  PIKEFUN int digest_size() +  { +  push_int(MD5_DIGEST_SIZE); +  } +  +  PIKEFUN int block_size() +  { +  push_int(MD5_DATA_SIZE); +  } +  +  PIKEFUN object update(string data) +  { +  /* FIXME: What about multibyte strings? */ +  md5_update(&THIS->ctx, data->len, data->str); +  +  push_object(this_object()); +  } +  +  PIKEFUN string digest(int|void arg) +  { +  struct pike_string *digest; +  INT32 length; +  +  if (!arg) +  length = MD5_DIGEST_SIZE; +  else +  { +  if (arg->type != PIKE_T_INT) +  Pike_error("Bad argument type"); +  length = arg->u.integer; +  if (length <= 0 || length > MD5_DIGEST_SIZE) +  Pike_error("Unsupported digest length"); +  } +  +  digest = begin_shared_string(length); +  md5_digest(&THIS->ctx, length, digest->str); +  push_string(end_shared_string(digest)); +  } +  +  INIT +  { +  /* werror("md5->INIT\n"); */ +  md5_init(&THIS->ctx); +  } +  +  EXIT +  { +  memset(&THIS->ctx, 0, sizeof(THIS->ctx)); +  } + } +  + PIKECLASS aes + { +  CVAR struct aes_ctx ctx; +  CVAR void (*f)(struct aes_ctx *, unsigned length, +  uint8_t *dst, const uint8_t *src); +  +  PIKEFUN string name() +  { +  push_string(make_shared_string("aes")); +  } +  +  PIKEFUN int key_size() +  { +  /* Recommended key size. */ +  push_int(AES_KEY_SIZE); +  } +  +  PIKEFUN int block_size() +  { +  push_int(AES_BLOCK_SIZE); +  } +  +  PIKEFUN object set_encrypt_key(string key) +  { +  NO_WIDE_STRING(key); +  +  if ( (key->len < AES_MIN_KEY_SIZE) +  || (key->len > AES_MAX_KEY_SIZE) ) +  Pike_error("Invalid key size for aes."); +  +  aes_set_encrypt_key(&THIS->ctx, key->len, key->str); +  +  THIS->f = aes_encrypt; +  +  push_object(this_object()); +  } +  +  PIKEFUN object set_decrypt_key(string key) +  { +  NO_WIDE_STRING(key); +  +  if ( (key->len < AES_MIN_KEY_SIZE) +  || (key->len > AES_MAX_KEY_SIZE) ) +  Pike_error("Invalid key size for aes."); +  aes_set_decrypt_key(&THIS->ctx, key->len, key->str); +  +  THIS->f = aes_decrypt; +  +  push_object(this_object()); +  } +  +  PIKEFUN string crypt(string data) +  { +  struct pike_string *s; +  /* werror("aes->encrypt\n"); */ +  + #if 0 +  { +  struct aes_ctx test_ctx; +  const uint8_t clear[16] = "aaaaaaaaaaaaaaaa"; +  uint8_t cipher[16]; +  +  werror("tfoo\n"); +  +  aes_set_encrypt_key(&test_ctx, 16, "0123456789abcdef"); +  werror("tbar\n"); +  +  aes_encrypt(&test_ctx, 16, cipher, clear); +  +  werror("tbaz\n"); +  } + #endif +  +  if (!THIS->f) +  Pike_error("Must install an encrypt or decrypt key first."); +  +  // werror("foo\n"); +  +  NO_WIDE_STRING(data); +  +  // werror("bar\n"); +  +  if (data->len % AES_BLOCK_SIZE) +  Pike_error("Data must be an integer number of blocks."); +  +  // werror("baz\n"); +  +  s = begin_shared_string(data->len); +  +  // werror("bazz\n"); +  + // werror("ctx = %p, len = %d, dst = %p, src = %p\n", + // &THIS->ctx, data->len, s->str, data->str); +  +  THIS->f(&THIS->ctx, data->len, s->str, data->str); +  /* aes_encrypt(&THIS->ctx, data->len, s->str, data->str); */ +  +  // werror("bazzz\n"); +  +  push_string(end_shared_string(s)); +  +  // werror("bazzzz\n"); +  } +  +  INIT +  { +  /* werror("aes->INIT\n"); */ +  THIS->f = NULL; +  } +  +  EXIT +  { +  /* werror("aes->EXIT\n"); */ +  memset(&THIS->ctx, 0, sizeof(THIS->ctx)); +  } + }   Newline at end of file added.