01e115 | 2003-03-12 | Niels Möller | | #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
|
01e115 | 2003-03-12 | Niels Möller | | * 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));
}
}
|