Commit 041f01da authored by Niels Möller's avatar Niels Möller
Browse files

Moved most crypto algorithms into separate files.

Rev: src/Makefile.am.in:1.12
Rev: src/abstract_crypto.c:1.4
Rev: src/crypto.c:1.20
parent fb58f63e
......@@ -29,13 +29,15 @@ noinst_LIBRARIES = liblsh.a
generated_sources = atoms_defines.h atoms_gperf.c atoms_table.c prime_table.h
liblsh_a_SOURCES = abstract_io.c abstract_crypto.c alist.c atoms.c \
bignum.c channel.c charset.c connection.c crypto.c \
debug.c disconnect.c dss_keygen.c encrypt.c \
format.c gc.c getopt.c io.c keyexchange.c \
list.c packet_ignore.c pad.c parse.c password.c publickey_crypto.c \
liblsh_a_SOURCES = abstract_io.c abstract_crypto.c alist.c arcfour.c atoms.c \
bignum.c blowfish.c \
cascade.c cbc.c channel.c charset.c connection.c crypto.c \
debug.c des.c disconnect.c dss_keygen.c encrypt.c \
format.c gc.c getopt.c hmac.c io.c keyexchange.c \
list.c md5.c packet_ignore.c pad.c parse.c password.c publickey_crypto.c \
randomness.c \
read_data.c read_line.c read_packet.c resource.c service.c \
read_data.c read_line.c read_packet.c resource.c \
sha.c service.c \
translate_signal.c unpad.c userauth.c \
werror.c write_buffer.c xalloc.c
......
......@@ -38,105 +38,8 @@
/* Combining block cryptos */
/* CLASS:
(class
(name cbc_algorithm)
(super crypto_algorithm)
(vars
(inner object crypto_algorithm)))
*/
/* CLASS:
(class
(name cbc_instance)
(super crypto_instance)
(vars
(inner object crypto_instance)
(iv space UINT8)))
*/
static void do_cbc_encrypt(struct crypto_instance *s,
UINT32 length, const UINT8 *src, UINT8 *dst)
{
CAST(cbc_instance, self, s);
FOR_BLOCKS(length, src, dst, self->super.block_size)
{
memxor(self->iv, src, self->super.block_size);
CRYPT(self->inner, self->super.block_size, src, self->iv);
memcpy(dst, self->iv, self->super.block_size);
}
}
static void do_cbc_decrypt(struct crypto_instance *s,
UINT32 length, const UINT8 *src, UINT8 *dst)
{
CAST(cbc_instance, self, s);
if (length % self->super.block_size)
fatal("Internal error\n");
if (!length)
return;
/* Decrypt in ECB mode */
CRYPT(self->inner, length, src, dst);
/* XOR the cryptotext, shifted one block */
memxor(dst,
self->iv, self->super.block_size);
memxor(dst + self->super.block_size,
src, length - self->super.block_size);
memcpy(self->iv,
src + length - self->super.block_size, self->super.block_size);
}
static struct crypto_instance *
do_make_cbc_instance(struct crypto_algorithm *s,
int mode, const UINT8 *key, const UINT8 *iv)
{
CAST(cbc_algorithm, algorithm, s);
NEW(cbc_instance, instance);
instance->super.block_size = algorithm->super.block_size;
/* NOTE: We use a prefix of the iv, and pass the tail on to the
* inner block crypto. This allows nested chaining, although the
* semantics may be a little obscure.. */
instance->inner = MAKE_CRYPT(algorithm->inner, mode, key,
iv + algorithm->super.block_size);
if (!instance->inner)
{
/* Weak key */
KILL(instance);
return NULL;
}
instance->iv = lsh_space_alloc(algorithm->super.block_size);
memcpy(instance->iv, iv, algorithm->super.block_size);
instance->super.crypt = ( (mode == CRYPTO_ENCRYPT)
? do_cbc_encrypt
: do_cbc_decrypt);
return &instance->super;
}
struct crypto_algorithm *crypto_cbc(struct crypto_algorithm *inner)
{
NEW(cbc_algorithm, algorithm);
algorithm->super.block_size = inner->block_size;
algorithm->super.key_size = inner->key_size;
algorithm->super.iv_size = inner->iv_size + inner->block_size;
algorithm->inner = inner;
algorithm->super.make_crypt = do_make_cbc_instance;
return &algorithm->super;
}
/* Inverts the encryption mode (needed for the EDE-operation of
* tripple DES). */
* triple DES). */
/* CLASS:
(class
(name crypto_inverted)
......@@ -171,220 +74,11 @@ struct crypto_algorithm *crypto_invert(struct crypto_algorithm *inner)
return &algorithm->super;
}
/* CLASS:
(class
(name crypto_cascade_algorithm)
(super crypto_algorithm)
(vars
(cascade object object_list)))
*/
/* CLASS:
(class
(name crypto_cascade_instance)
(super crypto_instance)
(vars
(cascade object object_list)))
*/
static void do_cascade_crypt(struct crypto_instance *s,
UINT32 length, const UINT8 *src, UINT8 *dst)
{
CAST(crypto_cascade_instance, self, s);
unsigned i;
if (length % self->super.block_size)
fatal("Internal error!\n");
assert(LIST_LENGTH(self->cascade));
{
CAST_SUBTYPE(crypto_instance, o, LIST(self->cascade)[0]);
CRYPT(o, length, src, dst);
}
for (i = 1; i<LIST_LENGTH(self->cascade); i++)
{
CAST_SUBTYPE(crypto_instance, o, LIST(self->cascade)[i]);
CRYPT(o, length, dst, dst);
}
}
static struct crypto_instance *
do_make_cascade(struct crypto_algorithm *s,
int mode, const UINT8 *key, const UINT8 *iv)
{
CAST(crypto_cascade_algorithm, algorithm, s);
NEW(crypto_cascade_instance, instance);
unsigned i;
instance->super.block_size = algorithm->super.block_size;
instance->cascade = alloc_object_list(LIST_LENGTH(algorithm->cascade));
/* FIXME: When decrypting, the crypto algorithm should be used in
* reverse order! */
for (i = 0; i<LIST_LENGTH(algorithm->cascade); i++)
{
CAST_SUBTYPE(crypto_algorithm, a, LIST(algorithm->cascade)[i]);
struct crypto_instance *o = MAKE_CRYPT(a, mode, key, iv);
if (!o)
{
KILL(instance);
return NULL;
}
LIST(instance->cascade)[i] = (struct lsh_object *) o;
key += a->key_size;
iv += a->iv_size;
}
instance->super.crypt = do_cascade_crypt;
return &instance->super;
}
struct crypto_algorithm *crypto_cascadel(struct object_list *cascade)
{
NEW(crypto_cascade_algorithm, self);
unsigned i;
self->cascade = cascade;
self->super.key_size = self->super.iv_size = 0;
self->super.block_size = 1;
for (i = 0; i<LIST_LENGTH(self->cascade); i++)
{
CAST_SUBTYPE(crypto_algorithm, a, LIST(self->cascade)[i]);
self->super.key_size += a->key_size;
self->super.iv_size += a->iv_size;
self->super.block_size = lcm(self->super.block_size, a->block_size);
}
self->super.make_crypt = do_make_cascade;
return &self->super;
}
struct crypto_algorithm *crypto_cascade(unsigned n, ...)
{
va_list args;
struct object_list *l;
va_start(args, n);
l = make_object_listv(n, args);
va_end(args);
return crypto_cascadel(l);
}
/* The HMAC (rfc-2104) construction */
/* CLASS:
(class
(name hmac_algorithm)
(super mac_algorithm)
(vars
(hash object hash_algorithm)))
*/
/* CLASS:
(class
(name hmac_instance)
(super mac_instance)
(vars
; Initialized hash objects
(hinner object hash_instance)
(houter object hash_instance)
; Modified by update
(state object hash_instance)))
*/
static void do_hmac_update(struct mac_instance *s,
UINT32 length, UINT8 *data)
{
CAST(hmac_instance, self, s);
HASH_UPDATE(self->state, length, data);
}
static void do_hmac_digest(struct mac_instance *s,
UINT8 *data)
{
CAST(hmac_instance, self, s);
struct hash_instance *h = self->state;
HASH_DIGEST(h, data); /* Inner hash */
KILL(h);
h = HASH_COPY(self->houter);
HASH_UPDATE(h, self->super.mac_size, data);
HASH_DIGEST(h, data);
KILL(h);
self->state = HASH_COPY(self->hinner);
}
static struct mac_instance *do_hmac_copy(struct mac_instance *s)
{
CAST(hmac_instance, self, s);
CLONED(hmac_instance, new, self);
new->state = HASH_COPY(self->state);
return &new->super;
}
#define IPAD 0x36
#define OPAD 0x5c
static struct mac_instance *make_hmac_instance(struct mac_algorithm *s,
const UINT8 *key)
{
CAST(hmac_algorithm, self, s);
NEW(hmac_instance, instance);
UINT8 *pad = alloca(self->hash->block_size);
instance->super.hash_size = self->super.hash_size;
instance->super.update = do_hmac_update;
instance->super.digest = do_hmac_digest;
instance->super.copy = do_hmac_copy;
instance->hinner = MAKE_HASH(self->hash);
memset(pad, IPAD, self->hash->block_size);
memxor(pad, key, self->hash->hash_size);
HASH_UPDATE(instance->hinner, self->hash->block_size, pad);
instance->houter = MAKE_HASH(self->hash);
memset(pad, OPAD, self->hash->block_size);
memxor(pad, key, self->hash->block_size);
HASH_UPDATE(instance->houter, self->hash->block_size, pad);
instance->state = HASH_COPY(instance->hinner);
return &instance->super;
}
struct mac_algorithm *make_hmac_algorithm(struct hash_algorithm *h)
{
NEW(hmac_algorithm, self);
self->super.hash_size = h->hash_size;
/* Recommended in RFC-2104 */
self->super.key_size = h->hash_size;
self->super.make_mac = make_hmac_instance;
self->hash = h;
return &self->super;
}
/* FIXME: These functions don't really belong here. */
/* XOR:s src onto dst */
/* FIXME: Perhaps it would make sense to optimize this function. */
/* NOTE: Perhaps it would make sense to optimize this function. */
void memxor(UINT8 *dst, const UINT8 *src, size_t n)
{
size_t i;
......
......@@ -24,12 +24,12 @@
*/
#include "crypto.h"
#include "werror.h"
#include "xalloc.h"
#include "blowfish.h"
#include "des.h"
#include "rc4.h"
#include "sha.h"
#include "md5.h"
......@@ -38,292 +38,7 @@
#include <sys/types.h>
#include <time.h>
#include "crypto.c.x"
/* CLASS:
(class
(name rc4_instance)
(super crypto_instance)
(vars
(ctx simple "struct rc4_ctx")))
*/
static void do_crypt_rc4(struct crypto_instance *s,
UINT32 length, const UINT8 *src, UINT8 *dst)
{
CAST(rc4_instance, self, s);
if (length % 8)
fatal("Internal error\n");
rc4_crypt(&self->ctx, dst, src, length);
}
static struct crypto_instance *
make_rc4_instance(struct crypto_algorithm *ignored UNUSED, int mode,
const UINT8 *key, const UINT8 *iv UNUSED)
{
NEW(rc4_instance, self);
self->super.block_size = 8;
self->super.crypt = do_crypt_rc4;
rc4_set_key(&self->ctx, key, 16);
return &self->super;
}
struct crypto_algorithm crypto_rc4_algorithm =
{ STATIC_HEADER,
8, 16, 0, make_rc4_instance };
/* Blowfish */
/* CLASS:
(class
(name blowfish_instance)
(super crypto_instance)
(vars
(ctx simple "BLOWFISH_context")))
*/
static void do_blowfish_encrypt(struct crypto_instance *s,
UINT32 length, const UINT8 *src, UINT8 *dst)
{
CAST(blowfish_instance, self, s);
FOR_BLOCKS(length, src, dst, BLOWFISH_BLOCKSIZE)
bf_encrypt_block(&self->ctx, dst, src);
}
static void do_blowfish_decrypt(struct crypto_instance *s,
UINT32 length, const UINT8 *src, UINT8 *dst)
{
CAST(blowfish_instance, self, s);
FOR_BLOCKS(length, src, dst, BLOWFISH_BLOCKSIZE)
bf_decrypt_block(&self->ctx, dst, src);
}
static struct crypto_instance *
make_blowfish_instance(struct crypto_algorithm *algorithm, int mode,
const UINT8 *key, const UINT8 *iv UNUSED)
{
NEW(blowfish_instance, self);
self->super.block_size = BLOWFISH_BLOCKSIZE;
self->super.crypt = ( (mode == CRYPTO_ENCRYPT)
? do_blowfish_encrypt
: do_blowfish_decrypt);
switch (bf_set_key(&self->ctx, key, algorithm->key_size))
{
case 0:
return &self->super;
default:
werror("Detected a weak blowfish key!\n");
KILL(self);
return NULL;
}
}
struct crypto_algorithm *make_blowfish_algorithm(UINT32 key_size)
{
NEW(crypto_algorithm, algorithm);
assert(key_size <= BLOWFISH_MAX_KEYSIZE);
assert(key_size >= BLOWFISH_MIN_KEYSIZE);
algorithm->block_size = BLOWFISH_BLOCKSIZE;
algorithm->key_size = key_size;
algorithm->iv_size = 0;
algorithm->make_crypt = make_blowfish_instance;
return algorithm;
}
struct crypto_algorithm *make_blowfish(void)
{
return make_blowfish_algorithm(BLOWFISH_KEYSIZE);
}
/* CLASS:
(class
(name des_instance)
(super crypto_instance)
(vars
(ctx array (simple UINT32) DES_EXPANDED_KEYLEN)))
*/
static void do_des_encrypt(struct crypto_instance *s,
UINT32 length, const UINT8 *src, UINT8 *dst)
{
CAST(des_instance, self, s);
FOR_BLOCKS(length, src, dst, DES_BLOCKSIZE)
DesSmallFipsEncrypt(dst, self->ctx, src);
}
static void do_des_decrypt(struct crypto_instance *s,
UINT32 length, const UINT8 *src, UINT8 *dst)
{
CAST(des_instance, self, s);
FOR_BLOCKS(length, src, dst, DES_BLOCKSIZE)
DesSmallFipsDecrypt(dst, self->ctx, src);
}
static struct crypto_instance *
make_des_instance(struct crypto_algorithm *algorithm, int mode,
const UINT8 *key, const UINT8 *iv UNUSED)
{
NEW(des_instance, self);
UINT8 pkey[DES_KEYSIZE];
unsigned i;
/* Fix parity */
for (i=0; i<DES_KEYSIZE; i++)
{
UINT8 p = key[i];
p ^= (p >> 4);
p ^= (p >> 2);
p ^= (p >> 1);
pkey[i] = key[i] ^ (p & 1);
}
self->super.block_size = DES_BLOCKSIZE;
self->super.crypt = ( (mode == CRYPTO_ENCRYPT)
? do_des_encrypt
: do_des_decrypt);
switch (DesMethod(self->ctx, pkey))
{
case 0:
return &self->super;
case -1:
fatal("Internal error! Bad parity in make_des_instance.\n");
case -2:
werror("Detected weak DES key.\n");
KILL(self);
return NULL;
default:
fatal("Internal error!\n");
}
}
struct crypto_algorithm crypto_des_algorithm =
{ STATIC_HEADER,
DES_BLOCKSIZE, DES_KEYSIZE, 0, make_des_instance };
struct crypto_algorithm *make_des3(void)
{
return crypto_cascade(3,
&crypto_des_algorithm,
crypto_invert(&crypto_des_algorithm),
&crypto_des_algorithm,
-1);
}
/* SHA1 hash */
/* CLASS:
(class
(name sha_instance)
(super hash_instance)
(vars
(ctx simple "struct sha_ctx")))
*/
static void do_sha_update(struct hash_instance *s,
UINT32 length, UINT8 *data)
{
CAST(sha_instance, self, s);
sha_update(&self->ctx, data, length);
}
static void do_sha_digest(struct hash_instance *s,
UINT8 *dst)
{
CAST(sha_instance, self, s);
sha_final(&self->ctx);
sha_digest(&self->ctx, dst);
sha_init(&self->ctx);
}
static struct hash_instance *do_sha_copy(struct hash_instance *s)
{
return &CLONE(sha_instance, s)->super;
}
static struct hash_instance *
make_sha_instance(struct hash_algorithm *ignored UNUSED)
{
NEW(sha_instance, res);
res->super.hash_size = 20;
res->super.update = do_sha_update;
res->super.digest = do_sha_digest;
res->super.copy = do_sha_copy;
sha_init(&res->ctx);
return &res->super;
}
struct hash_algorithm sha_algorithm =
{ STATIC_HEADER,
SHA_DATASIZE, SHA_DIGESTSIZE, make_sha_instance };
/* MD5 hash */
/* CLASS:
(class
(name md5_instance)
(super hash_instance)
(vars
(ctx simple "struct md5_ctx")))
*/
static void do_md5_update(struct hash_instance *s,
UINT32 length, UINT8 *data)
{
CAST(md5_instance, self, s);
md5_update(&self->ctx, data, length);
}
static void do_md5_digest(struct hash_instance *s,
UINT8 *dst)
{
CAST(md5_instance, self, s);
md5_final(&self->ctx);
md5_digest(&self->ctx, dst);