01e115 | 2003-03-12 | Niels Möller | | /* nettle.cmod -*- c -*- */
#include "global.h"
|
12beec | 2004-03-24 | Martin Nilsson | | RCSID("$Id: nettle.cmod,v 1.36 2004/03/24 00:08:30 nilsson Exp $");
|
01e115 | 2003-03-12 | Niels Möller | | #include "interpret.h"
#include "svalue.h"
/* For this_object() */
#include "object.h"
|
7d54f4 | 2004-01-23 | Martin Nilsson | | #include "operators.h"
|
01e115 | 2003-03-12 | Niels Möller | | #include "module_support.h"
|
d7f88a | 2004-02-14 | Martin Nilsson | | #include "threads.h"
|
01e115 | 2003-03-12 | Niels Möller | |
|
4e1f62 | 2003-03-13 | Niels Möller | | #include "nettle_config.h"
|
770fee | 2003-03-12 | Henrik Grubbström (Grubba) | | #ifdef HAVE_LIBNETTLE
|
efb89c | 2003-08-06 | Henrik Grubbström (Grubba) | | #include "nettle.h"
|
01e115 | 2003-03-12 | Niels Möller | |
|
318417 | 2003-08-06 | Henrik Grubbström (Grubba) | | #include <nettle/yarrow.h>
|
329a6f | 2004-02-21 | Martin Nilsson | | #include <nettle/knuth-lfib.h>
|
318417 | 2003-08-06 | Henrik Grubbström (Grubba) | |
|
01e115 | 2003-03-12 | Niels Möller | | #include <assert.h>
#include <stdio.h>
#include <stdarg.h>
DECLARATIONS
/*! @module Nettle
|
d74599 | 2003-08-05 | Martin Nilsson | | *! Low level crypto functions used by the @[Crypto] module. Unless
*! you are doing something very special, you would want to use the
*! Crypto module instead.
*/
/*! @class Yarrow
*!
*! Yarrow is a family of pseudo-randomness generators, designed for
*! cryptographic use, by John Kelsey, Bruce Schneier and Niels Ferguson.
*! Yarrow-160 is described in a paper at
*! @url{http://www.counterpane.com/yarrow.html@}, and it uses SHA1 and
*! triple-DES, and has a 160-bit internal state. Nettle implements
*! Yarrow-256, which is similar, but uses SHA256 and AES to get an
*! internal state of 256 bits.
*/
PIKECLASS Yarrow
{
|
49acab | 2003-11-09 | Niels Möller | | CVAR struct yarrow256_ctx ctx;
|
25f543 | 2003-08-06 | Martin Nilsson | | CVAR struct yarrow_source *sources;
|
910947 | 2003-08-07 | Martin Nilsson | | /*! @decl void create(void|int sources)
*! The number of entropy sources that will feed entropy to the
*! random number generator is given as an argument to Yarrow
*! during instantiation.
*! @seealso
*! @[update]
*/
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN void create(void|int arg)
{
|
25f543 | 2003-08-06 | Martin Nilsson | | INT32 num = 0;
if(arg) {
if (arg->type != PIKE_T_INT)
Pike_error("Bad argument type.\n");
num = arg->u.integer;
if(num < 0)
Pike_error("Invalid number of sources.\n");
|
49acab | 2003-11-09 | Niels Möller | | free (THIS->sources);
|
25f543 | 2003-08-06 | Martin Nilsson | | THIS->sources = xalloc(sizeof(struct yarrow_source)*num);
}
|
49acab | 2003-11-09 | Niels Möller | | else
{
free (THIS->sources);
THIS->sources = NULL;
}
yarrow256_init(&THIS->ctx, num, THIS->sources);
|
d74599 | 2003-08-05 | Martin Nilsson | | }
/*! @decl Yarrow seed(string data)
*! The random generator needs to be seeded before
*! it can be used. The seed must be at least 32
*! characters long. The seed could be stored from
*! a previous run by inserting the value returned
*! from @[get_seed].
*! @returns
*! Returns the called object.
|
910947 | 2003-08-07 | Martin Nilsson | | *! @seealso
*! @[min_seed_size], @[get_seed], @[is_seeded]
|
d74599 | 2003-08-05 | Martin Nilsson | | */
PIKEFUN object seed(string data)
|
d7f88a | 2004-02-14 | Martin Nilsson | | optflags OPT_SIDE_EFFECT;
|
d74599 | 2003-08-05 | Martin Nilsson | | {
if(data->len < YARROW256_SEED_FILE_SIZE)
Pike_error( "Seed must be at least 32 characters.\n" );
NO_WIDE_STRING(data);
|
49acab | 2003-11-09 | Niels Möller | | yarrow256_seed(&THIS->ctx, data->len, data->str);
|
d74599 | 2003-08-05 | Martin Nilsson | | RETURN this_object();
}
|
910947 | 2003-08-07 | Martin Nilsson | | /*! @decl int(0..) min_seed_size()
*! Returns the minimal number of characters that the @[seed]
*! needs to properly seed the random number generator.
*! @seealso
*! @[seed]
*/
PIKEFUN int(0..) min_seed_size()
|
d7f88a | 2004-02-14 | Martin Nilsson | | optflags OPT_TRY_OPTIMIZE;
|
910947 | 2003-08-07 | Martin Nilsson | | {
RETURN YARROW256_SEED_FILE_SIZE;
}
|
d74599 | 2003-08-05 | Martin Nilsson | | /*! @decl string get_seed()
*! Returns part of the internal state so that it can
*! be saved for later seeding.
|
910947 | 2003-08-07 | Martin Nilsson | | *! @seealso
*! @[seed]
|
d74599 | 2003-08-05 | Martin Nilsson | | */
PIKEFUN string get_seed()
|
d7f88a | 2004-02-14 | Martin Nilsson | | optflags OPT_EXTERNAL_DEPEND;
|
d74599 | 2003-08-05 | Martin Nilsson | | {
|
324ca8 | 2003-11-10 | Niels Möller | | if( !yarrow256_is_seeded(&THIS->ctx) )
Pike_error("Random generator not seeded.\n");
|
d7f88a | 2004-02-14 | Martin Nilsson | | RETURN make_shared_binary_string(THIS->ctx.seed_file,
YARROW256_SEED_FILE_SIZE);
|
d74599 | 2003-08-05 | Martin Nilsson | | }
/*! @decl int(0..1) is_seeded()
*! Returns 1 if the random generator is seeded and ready
*! to generator output. 0 otherwise.
|
910947 | 2003-08-07 | Martin Nilsson | | *! @seealso
*! @[seed]
|
d74599 | 2003-08-05 | Martin Nilsson | | */
PIKEFUN int(0..1) is_seeded()
|
d7f88a | 2004-02-14 | Martin Nilsson | | optflags OPT_EXTERNAL_DEPEND;
|
d74599 | 2003-08-05 | Martin Nilsson | | {
|
49acab | 2003-11-09 | Niels Möller | | RETURN yarrow256_is_seeded(&THIS->ctx);
|
d74599 | 2003-08-05 | Martin Nilsson | | }
|
910947 | 2003-08-07 | Martin Nilsson | | /*! @decl void force_reseed()
*! By calling this function entropy is moved from the slow
*! pool to the fast pool. Read more about Yarrow before using
*! this.
*/
|
d74599 | 2003-08-05 | Martin Nilsson | | PIKEFUN void force_reseed()
|
d7f88a | 2004-02-14 | Martin Nilsson | | optflags OPT_SIDE_EFFECT;
|
d74599 | 2003-08-05 | Martin Nilsson | | {
|
49acab | 2003-11-09 | Niels Möller | | yarrow256_force_reseed(&THIS->ctx);
|
d74599 | 2003-08-05 | Martin Nilsson | | }
|
910947 | 2003-08-07 | Martin Nilsson | | /*! @decl int(0..1) update(string data, int source, int entropy)
*! Inject additional entropy into the random number generator.
*!
*! @seealso
*! @[create]
*/
|
f1d891 | 2003-08-06 | Martin Nilsson | | PIKEFUN int(0..1) update(string data, int source, int entropy)
|
d7f88a | 2004-02-14 | Martin Nilsson | | optflags OPT_SIDE_EFFECT;
|
f1d891 | 2003-08-06 | Martin Nilsson | | {
|
49acab | 2003-11-09 | Niels Möller | | /* FIXME: Wide strings could actually be supported here */
|
f1d891 | 2003-08-06 | Martin Nilsson | | NO_WIDE_STRING(data);
|
49acab | 2003-11-09 | Niels Möller | | if( !THIS->sources )
|
f1d891 | 2003-08-06 | Martin Nilsson | | Pike_error("This random generator has no sources.\n");
|
61e14b | 2004-01-23 | Martin Nilsson | | if( source<0 || (unsigned)source>=THIS->ctx.nsources )
|
f1d891 | 2003-08-06 | Martin Nilsson | | Pike_error("Invalid random source.\n");
if( entropy<0 )
Pike_error("Entropy must be positive.\n");
|
910947 | 2003-08-07 | Martin Nilsson | | if( entropy>(data->len*8) )
Pike_error("Impossibly large entropy value.\n");
|
49acab | 2003-11-09 | Niels Möller | | RETURN yarrow256_update(&THIS->ctx, source, entropy, data->len, data->str);
|
f1d891 | 2003-08-06 | Martin Nilsson | | }
|
01a1ba | 2003-12-14 | Martin Nilsson | | /*! @decl int(0..) needed_sources()
*! The number of sources that must reach the threshold before a
*! slow reseed will happen.
*/
|
d74599 | 2003-08-05 | Martin Nilsson | | PIKEFUN int(0..) needed_sources()
|
d7f88a | 2004-02-14 | Martin Nilsson | | optflags OPT_EXTERNAL_DEPEND;
|
d74599 | 2003-08-05 | Martin Nilsson | | {
|
49acab | 2003-11-09 | Niels Möller | | RETURN yarrow256_needed_sources(&THIS->ctx);
|
d74599 | 2003-08-05 | Martin Nilsson | | }
/*! @decl string random_string(int length)
*! Returns a pseudo-random string of the requested @[length].
*/
PIKEFUN string random_string(int length)
|
d7f88a | 2004-02-14 | Martin Nilsson | | optflags OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT;
|
d74599 | 2003-08-05 | Martin Nilsson | | {
struct pike_string *rnd;
if(length < 0)
Pike_error("Invalid length, must be positive.\n");
|
49acab | 2003-11-09 | Niels Möller | | if( !yarrow256_is_seeded(&THIS->ctx) )
|
d74599 | 2003-08-05 | Martin Nilsson | | Pike_error("Random generator not seeded.\n");
rnd = begin_shared_string(length);
|
49acab | 2003-11-09 | Niels Möller | | yarrow256_random(&THIS->ctx, length, rnd->str);
|
d74599 | 2003-08-05 | Martin Nilsson | | RETURN end_shared_string(rnd);
}
INIT
{
|
49acab | 2003-11-09 | Niels Möller | | THIS->sources = NULL;
yarrow256_init(&THIS->ctx, 0, NULL);
|
d74599 | 2003-08-05 | Martin Nilsson | | }
EXIT
{
|
49acab | 2003-11-09 | Niels Möller | | /* It's ok to call free(NULL); */
free(THIS->sources);
|
d74599 | 2003-08-05 | Martin Nilsson | | }
}
/*! @endclass
|
01e115 | 2003-03-12 | Niels Möller | | */
|
9d4fc8 | 2003-08-25 | Martin Nilsson | | /*! @decl string crypt_md5(string password, string salt)
*! Does the crypt_md5 abrakadabra (MD5 + snakeoil).
|
3955a9 | 2003-08-24 | Martin Nilsson | | *! It is assumed that @[salt] does not contain "$".
*/
PIKEFUN string crypt_md5(string pw, string salt)
|
d7f88a | 2004-02-14 | Martin Nilsson | | optflags OPT_TRY_OPTIMIZE;
|
3955a9 | 2003-08-24 | Martin Nilsson | | {
|
329a6f | 2004-02-21 | Martin Nilsson | | char *hash;
|
3955a9 | 2003-08-24 | Martin Nilsson | | NO_WIDE_STRING(pw);
NO_WIDE_STRING(salt);
|
d7f88a | 2004-02-14 | Martin Nilsson | | THREADS_ALLOW();
|
a467f9 | 2004-03-20 | Henrik Grubbström (Grubba) | | hash = pike_crypt_md5(pw->len, pw->str,salt->len, salt->str);
|
d7f88a | 2004-02-14 | Martin Nilsson | | THREADS_DISALLOW();
|
329a6f | 2004-02-21 | Martin Nilsson | | push_text(hash);
|
3955a9 | 2003-08-24 | Martin Nilsson | | }
|
221ebe | 2003-12-06 | Martin Nilsson | |
static const char *crypto_functions[] = {
"block_size",
"key_size",
"set_encrypt_key",
"set_decrypt_key",
"crypt",
0
};
|
61e14b | 2004-01-23 | Martin Nilsson | | static const char * assert_is_crypto_object(struct program *p,
|
221ebe | 2003-12-06 | Martin Nilsson | | const char **required) {
while (*required) {
if (find_identifier( (char *) *required, p) < 0)
return *required;
required++;
}
return 0;
}
|
44ee95 | 2003-12-06 | Martin Nilsson | | static struct object *make_cipher_object(INT32 args) {
ptrdiff_t fun;
|
61e14b | 2004-01-23 | Martin Nilsson | | const char *missing;
|
44ee95 | 2003-12-06 | Martin Nilsson | | struct svalue *top = Pike_sp-args;
struct object *obj;
switch(top->type)
{
case T_PROGRAM:
obj = clone_object(top->u.program, args-1);
break;
case T_FUNCTION:
apply_svalue(Pike_sp - args, args-1);
/* Check return value */
if(Pike_sp[-1].type != T_OBJECT)
Pike_error("Returned value is not an object.\n");
add_ref(obj = Pike_sp[-1].u.object);
break;
case T_OBJECT:
fun = -1;
missing = assert_is_crypto_object(top->u.object->prog,
crypto_functions);
if(missing)
fun = FIND_LFUN(top->u.object->prog, LFUN_CALL);
if(fun!=-1) {
apply_low(top->u.object, fun, args-1);
stack_swap();
pop_stack();
}
else
if(args!=1) Pike_error("Too many arguments.\n");
add_ref(obj = top->u.object);
break;
default:
SIMPLE_BAD_ARG_ERROR("create", 1, "program|object|function");
}
pop_stack();
missing = assert_is_crypto_object(obj->prog, crypto_functions);
if(missing) {
free_object(obj);
Pike_error("Object is missing identifier \"%s\"\n", missing);
}
return obj;
}
|
221ebe | 2003-12-06 | Martin Nilsson | |
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | /*! @class CBC
|
12beec | 2004-03-24 | Martin Nilsson | | *! @belongs Crypto
|
01a1ba | 2003-12-14 | Martin Nilsson | | *! Implementation of the cipher block chaining mode (CBC). Works as
*! a wrapper for the cipher algorithm put in create.
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | */
PIKECLASS CBC
{
CVAR struct object *object;
CVAR unsigned INT8 *iv;
CVAR INT32 block_size;
CVAR INT32 mode;
INIT
{
THIS->object = 0;
THIS->iv = 0;
THIS->block_size = 0;
THIS->mode = 0;
}
EXIT
{
if(THIS->object) free_object(THIS->object);
if(THIS->iv) {
|
44ee95 | 2003-12-06 | Martin Nilsson | | MEMSET(THIS->iv, 0, THIS->block_size);
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | free(THIS->iv);
}
THIS->iv = 0;
}
INLINE static void cbc_encrypt_step(const unsigned INT8 *source,
unsigned INT8 *dest)
{
INT32 block_size = THIS->block_size;
INT32 i;
for(i=0; i < block_size; i++)
THIS->iv[i] ^= source[i];
push_string(make_shared_binary_string((INT8 *)THIS->iv, block_size));
safe_apply(THIS->object, "crypt", 1);
if(Pike_sp[-1].type != T_STRING)
Pike_error("Expected string from crypt()\n");
if(Pike_sp[-1].u.string->len != block_size) {
Pike_error("Bad string length %ld returned from crypt()\n",
DO_NOT_WARN((long)Pike_sp[-1].u.string->len));
}
MEMCPY(THIS->iv, Pike_sp[-1].u.string->str, block_size);
MEMCPY(dest, Pike_sp[-1].u.string->str, block_size);
pop_stack();
}
INLINE static void cbc_decrypt_step(const unsigned INT8 *source,
unsigned INT8 *dest)
{
INT32 block_size = THIS->block_size;
INT32 i;
push_string(make_shared_binary_string((const INT8 *)source, block_size));
safe_apply(THIS->object, "crypt", 1);
if(Pike_sp[-1].type != T_STRING)
Pike_error("Expected string from crypt()\n");
if(Pike_sp[-1].u.string->len != block_size) {
Pike_error("Bad string length %ld returned from crypt()\n",
DO_NOT_WARN((long)Pike_sp[-1].u.string->len));
}
for(i=0; i < block_size; i++)
dest[i] = THIS->iv[i] ^ Pike_sp[-1].u.string->str[i];
pop_stack();
MEMCPY(THIS->iv, source, block_size);
}
|
44ee95 | 2003-12-06 | Martin Nilsson | | /*! @decl void create(program|object|function cipher, mixed ... args)
|
01a1ba | 2003-12-14 | Martin Nilsson | | *! Initialize the CBC wrapper with a cipher algorithm. If it is a
*! program, an object will be instantiated with @[args] as arguments.
*! If it is an object that doesn't conform to the cipher API, but has
*! an @[LFUN::`()], that LFUN will be called. If it is a function,
*! that function will be called with @[args] as arguments.
|
44ee95 | 2003-12-06 | Martin Nilsson | | */
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN void create(program|object|function cipher, mixed ... more)
flags ID_STATIC;
{
|
99ac11 | 2004-02-04 | Martin Nilsson | | int old_block_size = THIS->block_size;
|
44ee95 | 2003-12-06 | Martin Nilsson | | THIS->object = make_cipher_object(args);
|
a5a7b8 | 2003-11-26 | Martin Nilsson | |
safe_apply(THIS->object, "block_size", 0);
if(Pike_sp[-1].type != T_INT)
Pike_error("block_size() didn't return an int.\n");
|
99ac11 | 2004-02-04 | Martin Nilsson | |
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | THIS->block_size = Pike_sp[-1].u.integer;
pop_stack();
if ((!THIS->block_size) ||
(THIS->block_size > 4096))
Pike_error("Bad block size %d.\n", THIS->block_size);
|
99ac11 | 2004-02-04 | Martin Nilsson | | if(THIS->iv) {
MEMSET(THIS->iv, 0, old_block_size);
free(THIS->iv);
}
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | THIS->iv = (unsigned INT8 *)xalloc(THIS->block_size);
MEMSET(THIS->iv, 0, THIS->block_size);
}
|
4922e9 | 2003-12-12 | Martin Nilsson | | /*! @decl string name()
|
a9981a | 2003-12-15 | Martin Nilsson | | *! Returns the string @expr{"CBC(x)"@} where x is the
*! encapsulated algorithm.
|
4922e9 | 2003-12-12 | Martin Nilsson | | */
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN string name()
optflags OPT_TRY_OPTIMIZE;
{
|
a9981a | 2003-12-15 | Martin Nilsson | | push_constant_text("CBC(");
safe_apply(THIS->object, "name", 0);
push_constant_text(")");
f_add(3);
|
4922e9 | 2003-12-12 | Martin Nilsson | | }
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | /*! @decl int block_size()
|
01a1ba | 2003-12-14 | Martin Nilsson | | *! Reurns the block size of the encapsulated cipher.
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | */
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN int block_size()
optflags OPT_TRY_OPTIMIZE;
{
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | RETURN THIS->block_size;
}
/*! @decl int key_size()
|
01a1ba | 2003-12-14 | Martin Nilsson | | *! Returns the key size of the encapsulated cipher.
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | */
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN int key_size()
optflags OPT_EXTERNAL_DEPEND;
{
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | safe_apply(THIS->object, "key_size", args);
}
|
01a1ba | 2003-12-14 | Martin Nilsson | | /*! @decl this_program set_encrypt_key(string key)
*! Prepare the cipher and the wrapper for encrypting
*! with the given @[key].
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | */
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN object set_encrypt_key(string key)
optflags OPT_SIDE_EFFECT;
{
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | assert(THIS->block_size);
THIS->mode = 0;
safe_apply(THIS->object, "set_encrypt_key", args);
pop_stack();
RETURN this_object();
}
|
01a1ba | 2003-12-14 | Martin Nilsson | | /*! @decl this_program set_decrypt_key(string key)
*! Prepare the cipher and the wrapper for decrypting
*! with the given @[key].
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | */
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN object set_decrypt_key(string key)
optflags OPT_SIDE_EFFECT;
{
|
99ac11 | 2004-02-04 | Martin Nilsson | | assert(THIS->block_size);
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | THIS->mode = 1;
|
99ac11 | 2004-02-04 | Martin Nilsson | | safe_apply(THIS->object, "set_decrypt_key", args);
pop_stack();
RETURN this_object();
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | }
|
01a1ba | 2003-12-14 | Martin Nilsson | | /*! @decl this_program set_iv(string iv)
*! Set the initialization vector to @[iv].
*/
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN object set_iv(string iv)
optflags OPT_SIDE_EFFECT;
{
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | assert(THIS->iv);
NO_WIDE_STRING(iv);
if(iv->len != THIS->block_size)
Pike_error("Argument incompatible with cipher block size.\n");
MEMCPY(THIS->iv, iv->str, THIS->block_size);
RETURN this_object();
}
|
01a1ba | 2003-12-14 | Martin Nilsson | | /*! @decl string crypt(string data)
*! Encrypt/decrypt @[data] and return the result. @[data] must
*! be an integral number of blocks.
*/
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | PIKEFUN string crypt(string data) {
unsigned INT8 *result;
INT32 offset = 0;
NO_WIDE_STRING(data);
if(data->len % THIS->block_size)
Pike_error("Data length not multiple of block size.\n");
if(!(result = alloca(data->len)))
Pike_error("Out of memory.\n");
if(THIS->mode == 0) {
while (offset < data->len) {
cbc_encrypt_step((const unsigned INT8 *)data->str + offset,
result + offset);
offset += THIS->block_size;
}
}
else {
while (offset < data->len) {
|
99ac11 | 2004-02-04 | Martin Nilsson | | cbc_decrypt_step((const unsigned INT8 *)data->str + offset,
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | result + offset);
offset += THIS->block_size;
}
}
pop_n_elems(args);
push_string(make_shared_binary_string((INT8 *)result, offset));
MEMSET(result, 0, offset);
}
}
|
44ee95 | 2003-12-06 | Martin Nilsson | | /*! @endclass
*/
|
f34dec | 2004-02-04 | Martin Nilsson | | /*! @class Buffer
|
12beec | 2004-03-24 | Martin Nilsson | | *! @belongs Crypto
|
44ee95 | 2003-12-06 | Martin Nilsson | | *! Acts as a buffer so that data can be fed to a cipher in blocks
*! that doesn't correspond to cipher block sizes.
*/
PIKECLASS Proxy {
CVAR struct object *object;
CVAR int block_size;
CVAR unsigned char *backlog;
CVAR int backlog_len;
INIT {
THIS->object = 0;
THIS->block_size = 0;
THIS->backlog = 0;
THIS->backlog_len = 0;
}
EXIT {
if(THIS->backlog) {
MEMSET(THIS->backlog, 0, THIS->block_size);
free(THIS->backlog);
}
if(THIS->object)
free_object(THIS->object);
}
/*! @decl void create(program|object|function cipher, mixed ... args)
|
a9981a | 2003-12-15 | Martin Nilsson | | *! Initialize the Proxy wrapper with a cipher algorithm. If it is a
*! program, an object will be instantiated with @[args] as arguments.
*! If it is an object that doesn't conform to the cipher API, but has
*! an @[LFUN::`()], that LFUN will be called. If it is a function,
*! that function will be called with @[args] as arguments.
|
44ee95 | 2003-12-06 | Martin Nilsson | | */
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN void create(program|object|function cipher, mixed ... more)
flags ID_STATIC;
{
|
44ee95 | 2003-12-06 | Martin Nilsson | | THIS->object = make_cipher_object(args);
safe_apply(THIS->object, "block_size", 0);
if (Pike_sp[-1].type != T_INT)
Pike_error("block_size() didn't return an int\n");
THIS->block_size = Pike_sp[-1].u.integer;
pop_stack();
if ((!THIS->block_size) ||
(THIS->block_size > 4096))
Pike_error("Bad block size %ld\n", DO_NOT_WARN((long)THIS->block_size));
THIS->backlog = (unsigned char *)xalloc(THIS->block_size);
THIS->backlog_len = 0;
MEMSET(THIS->backlog, 0, THIS->block_size);
}
|
4922e9 | 2003-12-12 | Martin Nilsson | | /*! @decl string name()
|
a9981a | 2003-12-15 | Martin Nilsson | | *! Returns the string @expr{"CBC(x)"@} where x is the
*! encapsulated algorithm.
|
4922e9 | 2003-12-12 | Martin Nilsson | | */
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN string name()
optflags OPT_TRY_OPTIMIZE;
{
|
a9981a | 2003-12-15 | Martin Nilsson | | push_constant_text("Proxy(");
safe_apply(THIS->object, "name", 0);
push_constant_text(")");
f_add(3);
|
4922e9 | 2003-12-12 | Martin Nilsson | | }
|
44ee95 | 2003-12-06 | Martin Nilsson | | /*! @decl int block_size()
*!
*! Get the block size of the contained block crypto.
*/
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN int block_size()
optflags OPT_TRY_OPTIMIZE;
{
|
44ee95 | 2003-12-06 | Martin Nilsson | | RETURN THIS->block_size;
}
/*! @decl int key_size()
*!
*! Get the key size of the contained block crypto.
*/
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN int key_size()
optflags OPT_EXTERNAL_DEPEND;
{
|
44ee95 | 2003-12-06 | Martin Nilsson | | safe_apply(THIS->object, "key_size", args);
}
/*! @decl this_program set_encrypt_key(string key)
*!
*! Set the encryption key.
*!
*! @note
*! As a side-effect any buffered data will be cleared.
*/
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN object set_encrypt_key(string key)
optflags OPT_SIDE_EFFECT;
{
|
44ee95 | 2003-12-06 | Martin Nilsson | | MEMSET(THIS->backlog, 0, THIS->block_size);
THIS->backlog_len = 0;
safe_apply(THIS->object, "set_encrypt_key", args);
pop_stack();
RETURN this_object();
}
/*! @decl this_program set_decrypt_key(string key)
*!
*! Set the decryption key.
*!
*! @note
*! As a side-effect any buffered data will be cleared.
*/
|
d7f88a | 2004-02-14 | Martin Nilsson | | PIKEFUN object set_decrypt_key(string key)
optflags OPT_SIDE_EFFECT;
{
|
44ee95 | 2003-12-06 | Martin Nilsson | | MEMSET(THIS->backlog, 0, THIS->block_size);
THIS->backlog_len = 0;
safe_apply(THIS->object, "set_decrypt_key", args);
pop_stack();
RETURN this_object();
}
/*! @decl string crypt(string data)
*!
*! Encrypt some data.
*!
*! Adds data to be encrypted to the buffer. If there's enough
*! data to en/decrypt a block, that will be done, and the result
*! returned. Any uncrypted data will be left in the buffer.
*/
PIKEFUN string crypt(string data) {
unsigned char *result;
ptrdiff_t roffset = 0;
ptrdiff_t soffset = 0;
ptrdiff_t len;
if (!(result = alloca(data->len + THIS->block_size)))
Pike_error("Out of memory\n");
if (THIS->backlog_len) {
if (data->len >= (THIS->block_size - THIS->backlog_len)) {
MEMCPY(THIS->backlog + THIS->backlog_len, data->str,
(THIS->block_size - THIS->backlog_len));
soffset += (THIS->block_size - THIS->backlog_len);
THIS->backlog_len = 0;
push_string(make_shared_binary_string((char *)THIS->backlog,
THIS->block_size));
safe_apply(THIS->object, "crypt", 1);
if (Pike_sp[-1].type != T_STRING)
Pike_error("crypt() did not return string\n");
if (Pike_sp[-1].u.string->len != THIS->block_size)
Pike_error("Unexpected string length %ld\n",
DO_NOT_WARN((long)Pike_sp[-1].u.string->len));
MEMCPY(result, Pike_sp[-1].u.string->str, THIS->block_size);
roffset = THIS->block_size;
pop_stack();
MEMSET(THIS->backlog, 0, THIS->block_size);
} else {
MEMCPY(THIS->backlog + THIS->backlog_len,
data->str, data->len);
THIS->backlog_len += data->len;
pop_n_elems(args);
push_constant_text("");
return;
}
}
len = (Pike_sp[-1].u.string->len - soffset);
len -= len % THIS->block_size;
if (len) {
push_string(make_shared_binary_string(Pike_sp[-1].u.string->str +
soffset, len));
soffset += len;
safe_apply(THIS->object, "crypt", 1);
if (Pike_sp[-1].type != T_STRING)
|
f34dec | 2004-02-04 | Martin Nilsson | | Pike_error("crypt() did not return string.\n");
|
44ee95 | 2003-12-06 | Martin Nilsson | | if (Pike_sp[-1].u.string->len != len)
|
f34dec | 2004-02-04 | Martin Nilsson | | Pike_error("crypt() Unexpected string length %ld.\n",
DO_NOT_WARN((long)Pike_sp[-1].u.string->len));
|
44ee95 | 2003-12-06 | Martin Nilsson | |
MEMCPY(result + roffset, Pike_sp[-1].u.string->str, len);
pop_stack();
}
if (soffset < Pike_sp[-1].u.string->len) {
MEMCPY(THIS->backlog, Pike_sp[-1].u.string->str + soffset,
Pike_sp[-1].u.string->len - soffset);
THIS->backlog_len = Pike_sp[-1].u.string->len - soffset;
}
pop_n_elems(args);
push_string(make_shared_binary_string((char *)result, roffset + len));
MEMSET(result, 0, roffset + len);
}
/*! @decl string pad()
*!
*! Pad and de/encrypt any data left in the buffer.
*!
*! @seealso
*! @[unpad()]
*/
PIKEFUN string pad() {
ptrdiff_t i;
for (i = THIS->backlog_len; i < THIS->block_size - 1; i++)
THIS->backlog[i] = DO_NOT_WARN((unsigned char)(my_rand() & 0xff));
THIS->backlog[THIS->block_size - 1] =
|
f34dec | 2004-02-04 | Martin Nilsson | | DO_NOT_WARN((unsigned char)(THIS->block_size - THIS->backlog_len - 1));
|
44ee95 | 2003-12-06 | Martin Nilsson | |
push_string(make_shared_binary_string((const char *)THIS->backlog,
THIS->block_size));
MEMSET(THIS->backlog, 0, THIS->block_size);
THIS->backlog_len = 0;
safe_apply(THIS->object, "crypt", 1);
}
/*! @decl string unpad(string data)
*!
*! De/encrypt and unpad a block of data.
*!
*! This performs the reverse operation of @[pad()].
*!
*! @seealso
*! @[pad()]
*/
|
f34dec | 2004-02-04 | Martin Nilsson | | PIKEFUN string unpad(string str) {
|
44ee95 | 2003-12-06 | Martin Nilsson | | ptrdiff_t len;
len = str->len;
|
f34dec | 2004-02-04 | Martin Nilsson | | if( len % THIS->block_size)
Pike_error("String must be integral numbers of blocks.\n");
safe_apply(THIS->object, "crypt", 1);
if (Pike_sp[-1].type != T_STRING)
Pike_error("crypt() did not return string.\n");
if (Pike_sp[-1].u.string->len != len)
Pike_error("crypt() Unexpected string length %ld.\n",
DO_NOT_WARN((long)Pike_sp[-1].u.string->len));
str = Pike_sp[-1].u.string;
|
44ee95 | 2003-12-06 | Martin Nilsson | | if (str->str[len - 1] > (THIS->block_size - 1))
|
f34dec | 2004-02-04 | Martin Nilsson | | Pike_error("Invalid padding (%d > %d)\n",
str->str[len-1], THIS->block_size-1);
|
44ee95 | 2003-12-06 | Martin Nilsson | |
len -= (str->str[len - 1] + 1);
if (len < 0)
Pike_error("String to short to unpad\n");
add_ref(str);
pop_stack();
push_string(make_shared_binary_string(str->str, len));
free_string(str);
}
}
|
a5a7b8 | 2003-11-26 | Martin Nilsson | | /*! @endclass
*/
|
329a6f | 2004-02-21 | Martin Nilsson | | #if 0
/* @class LFib
* The Donald Knuth Lagged Fibonacci pseudo random number generator.
* This is @b{not@} a source for cryptographic randomness. Use
* @[Crypto.Yarrow] instead.
*/
PIKECLASS LFib
{
CVAR struct knuth_lfib_ctx *ctx;
INIT {
THIS->ctx = xalloc(sizeof(struct knuth_lfib_ctx));
}
EXIT {
free(THIS->ctx);
}
/* @decl void create(int seed)
* The Lfib generator must be seeded with a number.
*/
PIKEFUN void create(int seed) {
knuth_lfib_init(THIS->ctx, seed);
}
/* @decl this_program reseed(int s)
* Reseed this object with seed @[s].
* @return
* Returns the current object.
*/
PIKEFUN object reseed(int s) {
knuth_lfib_init(THIS->ctx, s);
RETURN this_object();
}
/* Get one 32bit pseudorandom integer.
*/
PIKEFUN int get() {
RETURN knuth_lfib_get(THIS->ctx);
}
/* Get a pseudorandom string of length @[len].
*/
PIKEFUN string get_string(int len) {
struct pike_string *s = begin_shared_string(len);
knuth_lfib_random(THIS->ctx, len, s->str);
push_string(end_shared_string(s));
}
}
/* @endclass
*/
#endif
|
1ab4b1 | 2003-03-18 | Niels Möller | | /*! @endmodule
*/
|
770fee | 2003-03-12 | Henrik Grubbström (Grubba) | |
|
099d68 | 2004-01-30 | Martin Nilsson | |
|
654f15 | 2003-03-14 | Marcus Comstedt | | #endif /* HAVE_LIBNETTLE */
|
4e1f62 | 2003-03-13 | Niels Möller | | PIKE_MODULE_INIT
{
|
099d68 | 2004-01-30 | Martin Nilsson | | #ifdef __NT__
struct program *nt_program = NULL;
struct object *nt_object = NULL;
#endif /* __NT__ */
|
4e1f62 | 2003-03-13 | Niels Möller | | INIT;
|
654f15 | 2003-03-14 | Marcus Comstedt | | #ifdef HAVE_LIBNETTLE
|
4e1f62 | 2003-03-13 | Niels Möller | | hash_init();
|
636c42 | 2003-03-18 | Niels Möller | | cipher_init();
|
654f15 | 2003-03-14 | Marcus Comstedt | | #endif /* HAVE_LIBNETTLE */
|
099d68 | 2004-01-30 | Martin Nilsson | | #ifdef __NT__
start_new_program();
nt_init();
nt_program = end_program();
add_object_constant("NT", nt_object=clone_object(nt_program,0), 0);
free_object(nt_object);
free_program(nt_program);
#endif /* __NT__ */
|
4e1f62 | 2003-03-13 | Niels Möller | | }
PIKE_MODULE_EXIT
{
|
654f15 | 2003-03-14 | Marcus Comstedt | | #ifdef HAVE_LIBNETTLE
|
636c42 | 2003-03-18 | Niels Möller | | cipher_exit();
|
4e1f62 | 2003-03-13 | Niels Möller | | hash_exit();
|
654f15 | 2003-03-14 | Marcus Comstedt | | #endif /* HAVE_LIBNETTLE */
|
099d68 | 2004-01-30 | Martin Nilsson | | #ifdef __NT__
nt_exit();
#endif /* __NT__ */
|
4e1f62 | 2003-03-13 | Niels Möller | | EXIT;
}
|