pike.git
/
src
/
post_modules
/
Nettle
/
nettle.cmod
version
»
Context lines:
10
20
40
80
file
none
3
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.