Blame src/cipher.c

Packit 16808d
Packit 16808d
/*
Packit 16808d
  Meanwhile - Unofficial Lotus Sametime Community Client Library
Packit 16808d
  Copyright (C) 2004  Christopher (siege) O'Brien
Packit 16808d
  
Packit 16808d
  This library is free software; you can redistribute it and/or
Packit 16808d
  modify it under the terms of the GNU Library General Public
Packit 16808d
  License as published by the Free Software Foundation; either
Packit 16808d
  version 2 of the License, or (at your option) any later version.
Packit 16808d
  
Packit 16808d
  This library is distributed in the hope that it will be useful,
Packit 16808d
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 16808d
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 16808d
  Library General Public License for more details.
Packit 16808d
  
Packit 16808d
  You should have received a copy of the GNU Library General Public
Packit 16808d
  License along with this library; if not, write to the Free
Packit 16808d
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Packit 16808d
*/
Packit 16808d
Packit 16808d
#include <stdlib.h>
Packit 16808d
#include <time.h>
Packit 16808d
Packit 16808d
#include "mpi/mpi.h"
Packit 16808d
Packit 16808d
#include "mw_channel.h"
Packit 16808d
#include "mw_cipher.h"
Packit 16808d
#include "mw_debug.h"
Packit 16808d
#include "mw_session.h"
Packit 16808d
Packit 16808d
Packit 16808d
struct mwMpi {
Packit 16808d
  mw_mp_int i;
Packit 16808d
};
Packit 16808d
Packit 16808d
Packit 16808d
/** From RFC2268 */
Packit 16808d
static guchar PT[] = {
Packit 16808d
  0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
Packit 16808d
  0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
Packit 16808d
  0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
Packit 16808d
  0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
Packit 16808d
  0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
Packit 16808d
  0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
Packit 16808d
  0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
Packit 16808d
  0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
Packit 16808d
  0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
Packit 16808d
  0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
Packit 16808d
  0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
Packit 16808d
  0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
Packit 16808d
  0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
Packit 16808d
  0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
Packit 16808d
  0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
Packit 16808d
  0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
Packit 16808d
  0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
Packit 16808d
  0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
Packit 16808d
  0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
Packit 16808d
  0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
Packit 16808d
  0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
Packit 16808d
  0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
Packit 16808d
  0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
Packit 16808d
  0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
Packit 16808d
  0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
Packit 16808d
  0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
Packit 16808d
  0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
Packit 16808d
  0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
Packit 16808d
  0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
Packit 16808d
  0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
Packit 16808d
  0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
Packit 16808d
  0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD
Packit 16808d
};
Packit 16808d
Packit 16808d
Packit 16808d
/** prime number used in DH exchange */
Packit 16808d
static guchar dh_prime[] = {
Packit 16808d
  0xCF, 0x84, 0xAF, 0xCE, 0x86, 0xDD, 0xFA, 0x52,
Packit 16808d
  0x7F, 0x13, 0x6D, 0x10, 0x35, 0x75, 0x28, 0xEE,
Packit 16808d
  0xFB, 0xA0, 0xAF, 0xEF, 0x80, 0x8F, 0x29, 0x17,
Packit 16808d
  0x4E, 0x3B, 0x6A, 0x9E, 0x97, 0x00, 0x01, 0x71,
Packit 16808d
  0x7C, 0x8F, 0x10, 0x6C, 0x41, 0xC1, 0x61, 0xA6,
Packit 16808d
  0xCE, 0x91, 0x05, 0x7B, 0x34, 0xDA, 0x62, 0xCB,
Packit 16808d
  0xB8, 0x7B, 0xFD, 0xC1, 0xB3, 0x5C, 0x1B, 0x91,
Packit 16808d
  0x0F, 0xEA, 0x72, 0x24, 0x9D, 0x56, 0x6B, 0x9F
Packit 16808d
};
Packit 16808d
Packit 16808d
Packit 16808d
/** base used in DH exchange */
Packit 16808d
#define DH_BASE  3
Packit 16808d
Packit 16808d
Packit 16808d
struct mwMpi *mwMpi_new() {
Packit 16808d
  struct mwMpi *i;
Packit 16808d
  i = g_new0(struct mwMpi, 1);
Packit 16808d
  mw_mp_init(&i->i);
Packit 16808d
  return i;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwMpi_free(struct mwMpi *i) {
Packit 16808d
  if(! i) return;
Packit 16808d
  mw_mp_clear(&i->i);
Packit 16808d
  g_free(i);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void mwInitDHPrime(mw_mp_int *i) {
Packit 16808d
  mw_mp_init(i);
Packit 16808d
  mw_mp_read_unsigned_bin(i, dh_prime, 64);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwMpi_setDHPrime(struct mwMpi *i) {
Packit 16808d
  g_return_if_fail(i != NULL);
Packit 16808d
  mw_mp_read_unsigned_bin(&i->i, dh_prime, 64);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void mwInitDHBase(mw_mp_int *i) {
Packit 16808d
  mw_mp_init(i);
Packit 16808d
  mw_mp_set_int(i, DH_BASE);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwMpi_setDHBase(struct mwMpi *i) {
Packit 16808d
  g_return_if_fail(i != NULL);
Packit 16808d
  mw_mp_set_int(&i->i, DH_BASE);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void mw_mp_set_rand(mw_mp_int *i, guint bits) {
Packit 16808d
  size_t len, l;
Packit 16808d
  guchar *buf;
Packit 16808d
Packit 16808d
  l = len = (bits / 8) + 1;
Packit 16808d
  buf = g_malloc(len);
Packit 16808d
Packit 16808d
  srand(time(NULL));
Packit 16808d
  while(l--) buf[l] = rand() & 0xff;
Packit 16808d
Packit 16808d
  buf[0] &= (0xff >> (8 - (bits % 8)));
Packit 16808d
Packit 16808d
  mw_mp_read_unsigned_bin(i, buf, len);
Packit 16808d
  g_free(buf);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void mwDHRandKeypair(mw_mp_int *private_key, mw_mp_int *public_key) {
Packit 16808d
  mw_mp_int prime, base;
Packit 16808d
 
Packit 16808d
  mwInitDHPrime(&prime);
Packit 16808d
  mwInitDHBase(&base);
Packit 16808d
Packit 16808d
  mw_mp_set_rand(private_key, 512);
Packit 16808d
  mw_mp_exptmod(&base, private_key, &prime, public_key);
Packit 16808d
Packit 16808d
  mw_mp_clear(&prime);
Packit 16808d
  mw_mp_clear(&base);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwMpi_randDHKeypair(struct mwMpi *private_key, struct mwMpi *public_key) {
Packit 16808d
  g_return_if_fail(private_key != NULL);
Packit 16808d
  g_return_if_fail(public_key != NULL);
Packit 16808d
Packit 16808d
  mwDHRandKeypair(&private_key->i, &public_key->i);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void mwDHCalculateShared(mw_mp_int *shared_key, mw_mp_int *remote_key,
Packit 16808d
				mw_mp_int *private_key) {
Packit 16808d
  mw_mp_int prime;
Packit 16808d
 
Packit 16808d
  mwInitDHPrime(&prime);
Packit 16808d
  mw_mp_exptmod(remote_key, private_key, &prime, shared_key);
Packit 16808d
  mw_mp_clear(&prime);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwMpi_calculateDHShared(struct mwMpi *shared_key, struct mwMpi *remote_key,
Packit 16808d
			     struct mwMpi *private_key) {
Packit 16808d
Packit 16808d
  g_return_if_fail(shared_key != NULL);
Packit 16808d
  g_return_if_fail(remote_key != NULL);
Packit 16808d
  g_return_if_fail(private_key != NULL);
Packit 16808d
Packit 16808d
  mwDHCalculateShared(&shared_key->i, &remote_key->i, &private_key->i);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void mwDHImportKey(mw_mp_int *key, struct mwOpaque *o) {
Packit 16808d
  mw_mp_read_unsigned_bin(key, o->data, o->len);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwMpi_import(struct mwMpi *i, struct mwOpaque *o) {
Packit 16808d
  g_return_if_fail(i != NULL);
Packit 16808d
  g_return_if_fail(o != NULL);
Packit 16808d
Packit 16808d
  mwDHImportKey(&i->i, o);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void mwDHExportKey(mw_mp_int *key, struct mwOpaque *o) {
Packit 16808d
  o->len = mw_mp_unsigned_bin_size(key);
Packit 16808d
  o->data = g_malloc0(o->len);
Packit 16808d
  mw_mp_to_unsigned_bin(key, o->data);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwMpi_export(struct mwMpi *i, struct mwOpaque *o) {
Packit 16808d
  g_return_if_fail(i != NULL);
Packit 16808d
  g_return_if_fail(o != NULL);
Packit 16808d
  
Packit 16808d
  mwDHExportKey(&i->i, o);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwKeyRandom(guchar *key, gsize keylen) {
Packit 16808d
  g_return_if_fail(key != NULL);
Packit 16808d
Packit 16808d
  srand(time(NULL));
Packit 16808d
  while(keylen--) key[keylen] = rand() & 0xff;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwIV_init(guchar *iv) {
Packit 16808d
  iv[0] = 0x01;
Packit 16808d
  iv[1] = 0x23;
Packit 16808d
  iv[2] = 0x45;
Packit 16808d
  iv[3] = 0x67;
Packit 16808d
  iv[4] = 0x89;
Packit 16808d
  iv[5] = 0xab;
Packit 16808d
  iv[6] = 0xcd;
Packit 16808d
  iv[7] = 0xef;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* This does not seem to produce the same results as normal RC2 key
Packit 16808d
   expansion would, but it works, so eh. It might be smart to farm
Packit 16808d
   this out to mozilla or openssl */
Packit 16808d
void mwKeyExpand(int *ekey, const guchar *key, gsize keylen) {
Packit 16808d
  guchar tmp[128];
Packit 16808d
  int i, j;
Packit 16808d
Packit 16808d
  g_return_if_fail(keylen > 0);
Packit 16808d
  g_return_if_fail(key != NULL);
Packit 16808d
Packit 16808d
  if(keylen > 128) keylen = 128;
Packit 16808d
Packit 16808d
  /* fill the first chunk with what key bytes we have */
Packit 16808d
  for(i = keylen; i--; tmp[i] = key[i]);
Packit 16808d
  /* memcpy(tmp, key, keylen); */
Packit 16808d
Packit 16808d
  /* build the remaining key from the given data */
Packit 16808d
  for(i = 0; keylen < 128; i++) {
Packit 16808d
    tmp[keylen] = PT[ (tmp[keylen - 1] + tmp[i]) & 0xff ];
Packit 16808d
    keylen++;
Packit 16808d
  }
Packit 16808d
Packit 16808d
  tmp[0] = PT[ tmp[0] & 0xff ];
Packit 16808d
Packit 16808d
  for(i = 0, j = 0; i < 64; i++) {
Packit 16808d
    ekey[i] = (tmp[j] & 0xff) | (tmp[j+1] << 8);
Packit 16808d
    j += 2;
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
/* normal RC2 encryption given a full 128-byte (as 64 ints) key */
Packit 16808d
static void mwEncryptBlock(const int *ekey, guchar *out) {
Packit 16808d
Packit 16808d
  int a, b, c, d;
Packit 16808d
  int i, j;
Packit 16808d
Packit 16808d
  a = (out[7] << 8) | (out[6] & 0xff);
Packit 16808d
  b = (out[5] << 8) | (out[4] & 0xff);
Packit 16808d
  c = (out[3] << 8) | (out[2] & 0xff);
Packit 16808d
  d = (out[1] << 8) | (out[0] & 0xff);
Packit 16808d
Packit 16808d
  for(i = 0; i < 16; i++) {
Packit 16808d
    j = i * 4;
Packit 16808d
Packit 16808d
    d += ((c & (a ^ 0xffff)) + (b & a) + ekey[j++]);
Packit 16808d
    d = (d << 1) | (d >> 15 & 0x0001);
Packit 16808d
Packit 16808d
    c += ((b & (d ^ 0xffff)) + (a & d) + ekey[j++]);
Packit 16808d
    c = (c << 2) | (c >> 14 & 0x0003);
Packit 16808d
Packit 16808d
    b += ((a & (c ^ 0xffff)) + (d & c) + ekey[j++]);
Packit 16808d
    b = (b << 3) | (b >> 13 & 0x0007);
Packit 16808d
    
Packit 16808d
    a += ((d & (b ^ 0xffff)) + (c & b) + ekey[j++]);
Packit 16808d
    a = (a << 5) | (a >> 11 & 0x001f);
Packit 16808d
Packit 16808d
    if(i == 4 || i == 10) {
Packit 16808d
      d += ekey[a & 0x003f];
Packit 16808d
      c += ekey[d & 0x003f];
Packit 16808d
      b += ekey[c & 0x003f];
Packit 16808d
      a += ekey[b & 0x003f];
Packit 16808d
    }    
Packit 16808d
  }
Packit 16808d
Packit 16808d
  *out++ = d & 0xff;
Packit 16808d
  *out++ = (d >> 8) & 0xff;
Packit 16808d
  *out++ = c & 0xff;
Packit 16808d
  *out++ = (c >> 8) & 0xff;
Packit 16808d
  *out++ = b & 0xff;
Packit 16808d
  *out++ = (b >> 8) & 0xff;
Packit 16808d
  *out++ = a & 0xff;
Packit 16808d
  *out++ = (a >> 8) & 0xff;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwEncryptExpanded(const int *ekey, guchar *iv,
Packit 16808d
		       struct mwOpaque *in_data,
Packit 16808d
		       struct mwOpaque *out_data) {
Packit 16808d
Packit 16808d
  guchar *i = in_data->data;
Packit 16808d
  gsize i_len = in_data->len;
Packit 16808d
Packit 16808d
  guchar *o;
Packit 16808d
  gsize o_len;
Packit 16808d
Packit 16808d
  int x, y;
Packit 16808d
Packit 16808d
  /* pad upwards to a multiple of 8 */
Packit 16808d
  /* o_len = (i_len & -8) + 8; */
Packit 16808d
  o_len = i_len + (8 - (i_len % 8));
Packit 16808d
  o = g_malloc(o_len);
Packit 16808d
Packit 16808d
  out_data->data = o;
Packit 16808d
  out_data->len = o_len;
Packit 16808d
Packit 16808d
  /* figure out the amount of padding */
Packit 16808d
  y = o_len - i_len;
Packit 16808d
Packit 16808d
  /* copy in to out, and write padding bytes */
Packit 16808d
  for(x = i_len; x--; o[x] = i[x]);
Packit 16808d
  for(x = i_len; x < o_len; o[x++] = y);
Packit 16808d
  /* memcpy(o, i, i_len);
Packit 16808d
     memset(o + i_len, y, y); */
Packit 16808d
Packit 16808d
  /* encrypt in blocks */
Packit 16808d
  for(x = o_len; x > 0; x -= 8) {
Packit 16808d
    for(y = 8; y--; o[y] ^= iv[y]);
Packit 16808d
    mwEncryptBlock(ekey, o);
Packit 16808d
    for(y = 8; y--; iv[y] = o[y]);
Packit 16808d
    /* memcpy(iv, o, 8); */
Packit 16808d
    o += 8;
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwEncrypt(const guchar *key, gsize keylen, guchar *iv,
Packit 16808d
	       struct mwOpaque *in, struct mwOpaque *out) {
Packit 16808d
Packit 16808d
  int ekey[64];
Packit 16808d
  mwKeyExpand(ekey, key, keylen);
Packit 16808d
  mwEncryptExpanded(ekey, iv, in, out);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void mwDecryptBlock(const int *ekey, guchar *out) {
Packit 16808d
Packit 16808d
  int a, b, c, d;
Packit 16808d
  int i, j;
Packit 16808d
Packit 16808d
  a = (out[7] << 8) | (out[6] & 0xff);
Packit 16808d
  b = (out[5] << 8) | (out[4] & 0xff);
Packit 16808d
  c = (out[3] << 8) | (out[2] & 0xff);
Packit 16808d
  d = (out[1] << 8) | (out[0] & 0xff);
Packit 16808d
Packit 16808d
  for(i = 16; i--; ) {
Packit 16808d
    j = i * 4 + 3;
Packit 16808d
Packit 16808d
    a = (a << 11) | (a >> 5 & 0x07ff);
Packit 16808d
    a -= ((d & (b ^ 0xffff)) + (c & b) + ekey[j--]);
Packit 16808d
Packit 16808d
    b = (b << 13) | (b >> 3 & 0x1fff);
Packit 16808d
    b -= ((a & (c ^ 0xffff)) + (d & c) + ekey[j--]);
Packit 16808d
Packit 16808d
    c = (c << 14) | (c >> 2 & 0x3fff);
Packit 16808d
    c -= ((b & (d ^ 0xffff)) + (a & d) + ekey[j--]);
Packit 16808d
Packit 16808d
    d = (d << 15) | (d >> 1 & 0x7fff);
Packit 16808d
    d -= ((c & (a ^ 0xffff)) + (b & a) + ekey[j--]);
Packit 16808d
Packit 16808d
    if(i == 5 || i == 11) {
Packit 16808d
      a -= ekey[b & 0x003f];
Packit 16808d
      b -= ekey[c & 0x003f];
Packit 16808d
      c -= ekey[d & 0x003f];
Packit 16808d
      d -= ekey[a & 0x003f];
Packit 16808d
    }
Packit 16808d
  }
Packit 16808d
Packit 16808d
  *out++ = d & 0xff;
Packit 16808d
  *out++ = (d >> 8) & 0xff;
Packit 16808d
  *out++ = c & 0xff;
Packit 16808d
  *out++ = (c >> 8) & 0xff;
Packit 16808d
  *out++ = b & 0xff;
Packit 16808d
  *out++ = (b >> 8) & 0xff;
Packit 16808d
  *out++ = a & 0xff;
Packit 16808d
  *out++ = (a >> 8) & 0xff;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwDecryptExpanded(const int *ekey, guchar *iv,
Packit 16808d
		       struct mwOpaque *in_data,
Packit 16808d
		       struct mwOpaque *out_data) {
Packit 16808d
Packit 16808d
  guchar *i = in_data->data;
Packit 16808d
  gsize i_len = in_data->len;
Packit 16808d
Packit 16808d
  guchar *o;
Packit 16808d
  gsize o_len;
Packit 16808d
Packit 16808d
  int x, y;
Packit 16808d
Packit 16808d
  if(i_len % 8) {
Packit 16808d
    /* this doesn't check to ensure that in_data->len is a multiple of
Packit 16808d
       8, which is damn well ought to be. */
Packit 16808d
    g_warning("attempting decryption of mis-sized data, %u bytes",
Packit 16808d
	      (guint) i_len);
Packit 16808d
  }
Packit 16808d
Packit 16808d
  o = g_malloc(i_len);
Packit 16808d
  o_len = i_len;
Packit 16808d
  for(x = i_len; x--; o[x] = i[x]);
Packit 16808d
  /* memcpy(o, i, i_len); */
Packit 16808d
Packit 16808d
  out_data->data = o;
Packit 16808d
  out_data->len = o_len;
Packit 16808d
Packit 16808d
  for(x = o_len; x > 0; x -= 8) {
Packit 16808d
    /* decrypt a block */
Packit 16808d
    mwDecryptBlock(ekey, o);
Packit 16808d
Packit 16808d
    /* modify the initialization vector */
Packit 16808d
    for(y = 8; y--; o[y] ^= iv[y]);
Packit 16808d
    for(y = 8; y--; iv[y] = i[y]);
Packit 16808d
    /* memcpy(iv, i, 8); */
Packit 16808d
    i += 8;
Packit 16808d
    o += 8;
Packit 16808d
  }
Packit 16808d
Packit 16808d
  /* shorten the length by the value of the filler in the padding
Packit 16808d
     bytes */
Packit 16808d
  out_data->len -= *(o - 1);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwDecrypt(const guchar *key, gsize keylen, guchar *iv,
Packit 16808d
	       struct mwOpaque *in, struct mwOpaque *out) {
Packit 16808d
Packit 16808d
  int ekey[64];
Packit 16808d
  mwKeyExpand(ekey, key, keylen);
Packit 16808d
  mwDecryptExpanded(ekey, iv, in, out);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
Packit 16808d
struct mwCipher_RC2_40 {
Packit 16808d
  struct mwCipher cipher;
Packit 16808d
  int session_key[64];
Packit 16808d
  gboolean ready;
Packit 16808d
};
Packit 16808d
Packit 16808d
Packit 16808d
struct mwCipherInstance_RC2_40 {
Packit 16808d
  struct mwCipherInstance instance;
Packit 16808d
  int incoming_key[64];
Packit 16808d
  guchar outgoing_iv[8];
Packit 16808d
  guchar incoming_iv[8];
Packit 16808d
};
Packit 16808d
Packit 16808d
Packit 16808d
static const char *get_name_RC2_40() {
Packit 16808d
  return "RC2/40 Cipher";
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static const char *get_desc_RC2_40() {
Packit 16808d
  return "RC2, 40-bit effective key";
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static int encrypt_RC2_40(struct mwCipherInstance *ci,
Packit 16808d
			  struct mwOpaque *data) {
Packit 16808d
Packit 16808d
  struct mwCipherInstance_RC2_40 *cir;
Packit 16808d
  struct mwCipher_RC2_40 *cr;
Packit 16808d
  struct mwOpaque o = { 0, 0 };
Packit 16808d
Packit 16808d
  cir = (struct mwCipherInstance_RC2_40 *) ci;
Packit 16808d
  cr = (struct mwCipher_RC2_40 *) ci->cipher;
Packit 16808d
Packit 16808d
  mwEncryptExpanded(cr->session_key, cir->outgoing_iv, data, &o);
Packit 16808d
Packit 16808d
  mwOpaque_clear(data);
Packit 16808d
  data->data = o.data;
Packit 16808d
  data->len = o.len;
Packit 16808d
Packit 16808d
  return 0;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static int decrypt_RC2_40(struct mwCipherInstance *ci,
Packit 16808d
			  struct mwOpaque *data) {
Packit 16808d
  
Packit 16808d
  struct mwCipherInstance_RC2_40 *cir;
Packit 16808d
  struct mwCipher_RC2_40 *cr;
Packit 16808d
  struct mwOpaque o = { 0, 0 };
Packit 16808d
Packit 16808d
  cir = (struct mwCipherInstance_RC2_40 *) ci;
Packit 16808d
  cr = (struct mwCipher_RC2_40 *) ci->cipher;
Packit 16808d
Packit 16808d
  mwDecryptExpanded(cir->incoming_key, cir->incoming_iv, data, &o);
Packit 16808d
Packit 16808d
  mwOpaque_clear(data);
Packit 16808d
  data->data = o.data;
Packit 16808d
  data->len = o.len;
Packit 16808d
Packit 16808d
  return 0;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static struct mwCipherInstance *
Packit 16808d
new_instance_RC2_40(struct mwCipher *cipher,
Packit 16808d
		    struct mwChannel *chan) {
Packit 16808d
Packit 16808d
  struct mwCipher_RC2_40 *cr;
Packit 16808d
  struct mwCipherInstance_RC2_40 *cir;
Packit 16808d
  struct mwCipherInstance *ci;
Packit 16808d
Packit 16808d
  cr = (struct mwCipher_RC2_40 *) cipher;
Packit 16808d
Packit 16808d
  /* a bit of lazy initialization here */
Packit 16808d
  if(! cr->ready) {
Packit 16808d
    struct mwLoginInfo *info = mwSession_getLoginInfo(cipher->session);
Packit 16808d
    mwKeyExpand(cr->session_key, (guchar *) info->login_id, 5);
Packit 16808d
    cr->ready = TRUE;
Packit 16808d
  }
Packit 16808d
Packit 16808d
  cir = g_new0(struct mwCipherInstance_RC2_40, 1);
Packit 16808d
  ci = &cir->instance;
Packit 16808d
Packit 16808d
  ci->cipher = cipher;
Packit 16808d
  ci->channel = chan;
Packit 16808d
Packit 16808d
  mwIV_init(cir->incoming_iv);
Packit 16808d
  mwIV_init(cir->outgoing_iv);
Packit 16808d
Packit 16808d
  return ci;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static struct mwEncryptItem *new_item_RC2_40(struct mwCipherInstance *ci) {
Packit 16808d
  struct mwEncryptItem *e;
Packit 16808d
Packit 16808d
  e = g_new0(struct mwEncryptItem, 1);
Packit 16808d
  e->id = mwCipher_RC2_40;
Packit 16808d
  return e;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static struct mwEncryptItem *
Packit 16808d
offer_RC2_40(struct mwCipherInstance *ci) {
Packit 16808d
  return new_item_RC2_40(ci);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void accepted_RC2_40(struct mwCipherInstance *ci,
Packit 16808d
			    struct mwEncryptItem *item) {
Packit 16808d
Packit 16808d
  struct mwCipherInstance_RC2_40 *cir;
Packit 16808d
  struct mwLoginInfo *info;
Packit 16808d
Packit 16808d
  cir = (struct mwCipherInstance_RC2_40 *) ci;
Packit 16808d
  info = mwChannel_getUser(ci->channel);
Packit 16808d
Packit 16808d
  if(info->login_id) {
Packit 16808d
    mwKeyExpand(cir->incoming_key, (guchar *) info->login_id, 5);
Packit 16808d
  }
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static struct mwEncryptItem *
Packit 16808d
accept_RC2_40(struct mwCipherInstance *ci) {
Packit 16808d
Packit 16808d
  accepted_RC2_40(ci, NULL);
Packit 16808d
  return new_item_RC2_40(ci);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwCipher *mwCipher_new_RC2_40(struct mwSession *s) {
Packit 16808d
  struct mwCipher_RC2_40 *cr = g_new0(struct mwCipher_RC2_40, 1);
Packit 16808d
  struct mwCipher *c = &cr->cipher;
Packit 16808d
Packit 16808d
  c->session = s;
Packit 16808d
  c->type = mwCipher_RC2_40;
Packit 16808d
  c->get_name = get_name_RC2_40;
Packit 16808d
  c->get_desc = get_desc_RC2_40;
Packit 16808d
  c->new_instance = new_instance_RC2_40;
Packit 16808d
Packit 16808d
  c->offer = offer_RC2_40;
Packit 16808d
Packit 16808d
  c->accepted = accepted_RC2_40;
Packit 16808d
  c->accept = accept_RC2_40;
Packit 16808d
Packit 16808d
  c->encrypt = encrypt_RC2_40;
Packit 16808d
  c->decrypt = decrypt_RC2_40;
Packit 16808d
Packit 16808d
  return c;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwCipher_RC2_128 {
Packit 16808d
  struct mwCipher cipher;
Packit 16808d
  mw_mp_int private_key;
Packit 16808d
  struct mwOpaque public_key;
Packit 16808d
};
Packit 16808d
Packit 16808d
Packit 16808d
struct mwCipherInstance_RC2_128 {
Packit 16808d
  struct mwCipherInstance instance;
Packit 16808d
  int shared[64];      /* shared secret determined via DH exchange */
Packit 16808d
  guchar outgoing_iv[8];
Packit 16808d
  guchar incoming_iv[8];
Packit 16808d
};
Packit 16808d
Packit 16808d
Packit 16808d
static const char *get_name_RC2_128() {
Packit 16808d
  return "RC2/128 Cipher";
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static const char *get_desc_RC2_128() {
Packit 16808d
  return "RC2, DH shared secret key";
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static struct mwCipherInstance *
Packit 16808d
new_instance_RC2_128(struct mwCipher *cipher,
Packit 16808d
		     struct mwChannel *chan) {
Packit 16808d
Packit 16808d
  struct mwCipher_RC2_128 *cr;
Packit 16808d
  struct mwCipherInstance_RC2_128 *cir;
Packit 16808d
  struct mwCipherInstance *ci;
Packit 16808d
Packit 16808d
  cr = (struct mwCipher_RC2_128 *) cipher;
Packit 16808d
Packit 16808d
  cir = g_new0(struct mwCipherInstance_RC2_128, 1);
Packit 16808d
  ci = &cir->instance;
Packit 16808d
  
Packit 16808d
  ci->cipher = cipher;
Packit 16808d
  ci->channel = chan;
Packit 16808d
Packit 16808d
  mwIV_init(cir->incoming_iv);
Packit 16808d
  mwIV_init(cir->outgoing_iv);
Packit 16808d
Packit 16808d
  return ci;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void offered_RC2_128(struct mwCipherInstance *ci,
Packit 16808d
			    struct mwEncryptItem *item) {
Packit 16808d
  
Packit 16808d
  mw_mp_int remote_key;
Packit 16808d
  mw_mp_int shared;
Packit 16808d
  struct mwOpaque sho = { 0, 0 };
Packit 16808d
Packit 16808d
  struct mwCipher *c;
Packit 16808d
  struct mwCipher_RC2_128 *cr;
Packit 16808d
  struct mwCipherInstance_RC2_128 *cir;
Packit 16808d
Packit 16808d
  c = ci->cipher;
Packit 16808d
  cr = (struct mwCipher_RC2_128 *) c;
Packit 16808d
  cir = (struct mwCipherInstance_RC2_128 *) ci;
Packit 16808d
Packit 16808d
  mw_mp_init(&remote_key);
Packit 16808d
  mw_mp_init(&shared);
Packit 16808d
Packit 16808d
  mwDHImportKey(&remote_key, &item->info);
Packit 16808d
  mwDHCalculateShared(&shared, &remote_key, &cr->private_key);
Packit 16808d
  mwDHExportKey(&shared, &sho);
Packit 16808d
Packit 16808d
  /* key expanded from the last 16 bytes of the DH shared secret. This
Packit 16808d
     took me forever to figure out. 16 bytes is 128 bit. */
Packit 16808d
  /* the sh_len-16 is important, because the key len could
Packit 16808d
     hypothetically start with 8bits or more unset, meaning the
Packit 16808d
     exported key might be less than 64 bytes in length */
Packit 16808d
  mwKeyExpand(cir->shared, sho.data+(sho.len-16), 16);
Packit 16808d
  
Packit 16808d
  mw_mp_clear(&remote_key);
Packit 16808d
  mw_mp_clear(&shared);
Packit 16808d
  mwOpaque_clear(&sho);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static struct mwEncryptItem *
Packit 16808d
offer_RC2_128(struct mwCipherInstance *ci) {
Packit 16808d
Packit 16808d
  struct mwCipher *c;
Packit 16808d
  struct mwCipher_RC2_128 *cr;
Packit 16808d
  struct mwEncryptItem *ei;
Packit 16808d
Packit 16808d
  c = ci->cipher;
Packit 16808d
  cr = (struct mwCipher_RC2_128 *) c;
Packit 16808d
Packit 16808d
  ei = g_new0(struct mwEncryptItem, 1);
Packit 16808d
  ei->id = mwCipher_RC2_128;
Packit 16808d
  mwOpaque_clone(&ei->info, &cr->public_key);
Packit 16808d
Packit 16808d
  return ei;
Packit 16808d
}			  
Packit 16808d
Packit 16808d
Packit 16808d
static void accepted_RC2_128(struct mwCipherInstance *ci,
Packit 16808d
			     struct mwEncryptItem *item) {
Packit 16808d
Packit 16808d
  offered_RC2_128(ci, item);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static struct mwEncryptItem *
Packit 16808d
accept_RC2_128(struct mwCipherInstance *ci) {
Packit 16808d
Packit 16808d
  return offer_RC2_128(ci);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static int encrypt_RC2_128(struct mwCipherInstance *ci,
Packit 16808d
			   struct mwOpaque *data) {
Packit 16808d
Packit 16808d
  struct mwCipherInstance_RC2_128 *cir;
Packit 16808d
  struct mwOpaque o = { 0, 0 };
Packit 16808d
Packit 16808d
  cir = (struct mwCipherInstance_RC2_128 *) ci;
Packit 16808d
Packit 16808d
  mwEncryptExpanded(cir->shared, cir->outgoing_iv, data, &o);
Packit 16808d
Packit 16808d
  mwOpaque_clear(data);
Packit 16808d
  data->data = o.data;
Packit 16808d
  data->len = o.len;
Packit 16808d
Packit 16808d
  return 0;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static int decrypt_RC2_128(struct mwCipherInstance *ci,
Packit 16808d
			   struct mwOpaque *data) {
Packit 16808d
Packit 16808d
  struct mwCipherInstance_RC2_128 *cir;
Packit 16808d
  struct mwOpaque o = { 0, 0 };
Packit 16808d
Packit 16808d
  cir = (struct mwCipherInstance_RC2_128 *) ci;
Packit 16808d
Packit 16808d
  mwDecryptExpanded(cir->shared, cir->incoming_iv, data, &o);
Packit 16808d
Packit 16808d
  mwOpaque_clear(data);
Packit 16808d
  data->data = o.data;
Packit 16808d
  data->len = o.len;
Packit 16808d
Packit 16808d
  return 0;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
static void clear_RC2_128(struct mwCipher *c) {
Packit 16808d
  struct mwCipher_RC2_128 *cr;
Packit 16808d
  cr = (struct mwCipher_RC2_128 *) c;
Packit 16808d
Packit 16808d
  mw_mp_clear(&cr->private_key);
Packit 16808d
  mwOpaque_clear(&cr->public_key);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwCipher *mwCipher_new_RC2_128(struct mwSession *s) {
Packit 16808d
  struct mwCipher_RC2_128 *cr;
Packit 16808d
  struct mwCipher *c;
Packit 16808d
Packit 16808d
  mw_mp_int pubkey;
Packit 16808d
Packit 16808d
  cr = g_new0(struct mwCipher_RC2_128, 1);
Packit 16808d
  c = &cr->cipher;
Packit 16808d
Packit 16808d
  c->session = s;
Packit 16808d
  c->type = mwCipher_RC2_128;
Packit 16808d
  c->get_name = get_name_RC2_128;
Packit 16808d
  c->get_desc = get_desc_RC2_128;
Packit 16808d
  c->new_instance = new_instance_RC2_128;
Packit 16808d
Packit 16808d
  c->offered = offered_RC2_128;
Packit 16808d
  c->offer = offer_RC2_128;
Packit 16808d
Packit 16808d
  c->accepted = accepted_RC2_128;
Packit 16808d
  c->accept = accept_RC2_128;
Packit 16808d
Packit 16808d
  c->encrypt = encrypt_RC2_128;
Packit 16808d
  c->decrypt = decrypt_RC2_128;
Packit 16808d
Packit 16808d
  c->clear = clear_RC2_128;
Packit 16808d
  
Packit 16808d
  mw_mp_init(&cr->private_key);
Packit 16808d
  mw_mp_init(&pubkey);
Packit 16808d
  mwDHRandKeypair(&cr->private_key, &pubkey);
Packit 16808d
  mwDHExportKey(&pubkey, &cr->public_key);
Packit 16808d
  mw_mp_clear(&pubkey);
Packit 16808d
Packit 16808d
  return c;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwSession *mwCipher_getSession(struct mwCipher *cipher) {
Packit 16808d
  g_return_val_if_fail(cipher != NULL, NULL);
Packit 16808d
  return cipher->session;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
guint16 mwCipher_getType(struct mwCipher *cipher) {
Packit 16808d
  /* oh man, this is a bad failover... who the hell decided to make
Packit 16808d
     zero a real cipher id? */
Packit 16808d
  g_return_val_if_fail(cipher != NULL, 0xffff);
Packit 16808d
  return cipher->type;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
const char *mwCipher_getName(struct mwCipher *cipher) {
Packit 16808d
  g_return_val_if_fail(cipher != NULL, NULL);
Packit 16808d
  g_return_val_if_fail(cipher->get_name != NULL, NULL);
Packit 16808d
  return cipher->get_name();
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
const char *mwCipher_getDesc(struct mwCipher *cipher) {
Packit 16808d
  g_return_val_if_fail(cipher != NULL, NULL);
Packit 16808d
  g_return_val_if_fail(cipher->get_desc != NULL, NULL);
Packit 16808d
  return cipher->get_desc();
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwCipher_free(struct mwCipher *cipher) {
Packit 16808d
  if(! cipher) return;
Packit 16808d
Packit 16808d
  if(cipher->clear)
Packit 16808d
    cipher->clear(cipher);
Packit 16808d
Packit 16808d
  g_free(cipher);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwCipherInstance *mwCipher_newInstance(struct mwCipher *cipher,
Packit 16808d
					      struct mwChannel *chan) {
Packit 16808d
  g_return_val_if_fail(cipher != NULL, NULL);
Packit 16808d
  g_return_val_if_fail(chan != NULL, NULL);
Packit 16808d
  g_return_val_if_fail(cipher->new_instance != NULL, NULL);
Packit 16808d
  return cipher->new_instance(cipher, chan);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwCipher *mwCipherInstance_getCipher(struct mwCipherInstance *ci) {
Packit 16808d
  g_return_val_if_fail(ci != NULL, NULL);
Packit 16808d
  return ci->cipher;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwChannel *mwCipherInstance_getChannel(struct mwCipherInstance *ci) {
Packit 16808d
  g_return_val_if_fail(ci != NULL, NULL);
Packit 16808d
  return ci->channel;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwCipherInstance_offered(struct mwCipherInstance *ci,
Packit 16808d
			      struct mwEncryptItem *item) {
Packit 16808d
  struct mwCipher *cipher;
Packit 16808d
Packit 16808d
  g_return_if_fail(ci != NULL);
Packit 16808d
Packit 16808d
  cipher = ci->cipher;
Packit 16808d
  g_return_if_fail(cipher != NULL);
Packit 16808d
Packit 16808d
  if(cipher->offered) cipher->offered(ci, item);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwEncryptItem *
Packit 16808d
mwCipherInstance_offer(struct mwCipherInstance *ci) {
Packit 16808d
  struct mwCipher *cipher;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(ci != NULL, NULL);
Packit 16808d
Packit 16808d
  cipher = ci->cipher;
Packit 16808d
  g_return_val_if_fail(cipher != NULL, NULL);
Packit 16808d
Packit 16808d
  return cipher->offer(ci);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwCipherInstance_accepted(struct mwCipherInstance *ci,
Packit 16808d
			       struct mwEncryptItem *item) {
Packit 16808d
  struct mwCipher *cipher;
Packit 16808d
Packit 16808d
  g_return_if_fail(ci != NULL);
Packit 16808d
Packit 16808d
  cipher = ci->cipher;
Packit 16808d
  g_return_if_fail(cipher != NULL);
Packit 16808d
Packit 16808d
  if(cipher->accepted) cipher->accepted(ci, item);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
struct mwEncryptItem *
Packit 16808d
mwCipherInstance_accept(struct mwCipherInstance *ci) {
Packit 16808d
  struct mwCipher *cipher;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(ci != NULL, NULL);
Packit 16808d
Packit 16808d
  cipher = ci->cipher;
Packit 16808d
  g_return_val_if_fail(cipher != NULL, NULL);
Packit 16808d
Packit 16808d
  return cipher->accept(ci);
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
int mwCipherInstance_encrypt(struct mwCipherInstance *ci,
Packit 16808d
			     struct mwOpaque *data) {
Packit 16808d
  struct mwCipher *cipher;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(data != NULL, 0);
Packit 16808d
Packit 16808d
  if(! ci) return 0;
Packit 16808d
  cipher = ci->cipher;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(cipher != NULL, -1);
Packit 16808d
Packit 16808d
  return (cipher->encrypt)?
Packit 16808d
    cipher->encrypt(ci, data): 0;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
int mwCipherInstance_decrypt(struct mwCipherInstance *ci,
Packit 16808d
			     struct mwOpaque *data) {
Packit 16808d
  struct mwCipher *cipher;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(data != NULL, 0);
Packit 16808d
Packit 16808d
  if(! ci) return 0;
Packit 16808d
  cipher = ci->cipher;
Packit 16808d
Packit 16808d
  g_return_val_if_fail(cipher != NULL, -1);
Packit 16808d
Packit 16808d
  return (cipher->decrypt)?
Packit 16808d
    cipher->decrypt(ci, data): 0;
Packit 16808d
}
Packit 16808d
Packit 16808d
Packit 16808d
void mwCipherInstance_free(struct mwCipherInstance *ci) {
Packit 16808d
  struct mwCipher *cipher;
Packit 16808d
Packit 16808d
  if(! ci) return;
Packit 16808d
Packit 16808d
  cipher = ci->cipher;
Packit 16808d
Packit 16808d
  if(cipher && cipher->clear_instance)
Packit 16808d
    cipher->clear_instance(ci);
Packit 16808d
Packit 16808d
  g_free(ci);
Packit 16808d
}
Packit 16808d