diff src/protocols/sametime/meanwhile/cipher.c @ 12261:2edf5dc1b2ea

[gaim-migrate @ 14563] Removed the dependancy on libgmp, opting to use the public domain libmpi code instead. Bringing over updates to the places service which should fix some crash bugs. committer: Tailor Script <tailor@pidgin.im>
author Christopher O'Brien <siege@pidgin.im>
date Tue, 29 Nov 2005 23:31:40 +0000
parents 0110fc7c6a8a
children a2ebf585d8c6
line wrap: on
line diff
--- a/src/protocols/sametime/meanwhile/cipher.c	Tue Nov 29 22:59:30 2005 +0000
+++ b/src/protocols/sametime/meanwhile/cipher.c	Tue Nov 29 23:31:40 2005 +0000
@@ -19,11 +19,9 @@
 */
 
 #include <stdlib.h>
-#include <string.h>
 #include <time.h>
 
-#include <gmp.h>
-
+#include "mpi/mpi.h"
 
 #include "mw_channel.h"
 #include "mw_cipher.h"
@@ -31,6 +29,11 @@
 #include "mw_session.h"
 
 
+struct mwMpi {
+  mp_int i;
+};
+
+
 /** From RFC2268 */
 static unsigned char PT[] = {
   0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
@@ -85,63 +88,140 @@
 #define DH_BASE  3
 
 
-void mwInitDHPrime(mpz_t z) {
-  mpz_init(z);
-  mpz_import(z, 64, 1, 1, 0, 0, dh_prime);
+struct mwMpi *mwMpi_new() {
+  struct mwMpi *i;
+  i = g_new0(struct mwMpi, 1);
+  mp_init(&i->i);
+  return i;
 }
 
 
-void mwInitDHBase(mpz_t z) {
-  mpz_init_set_ui(z, DH_BASE);
+void mwMpi_free(struct mwMpi *i) {
+  if(! i) return;
+  mp_clear(&i->i);
+  g_free(i);
+}
+
+
+static void mwInitDHPrime(mp_int *i) {
+  mp_init(i);
+  mp_read_unsigned_bin(i, dh_prime, 64);
+}
+
+
+void mwMpi_setDHPrime(struct mwMpi *i) {
+  g_return_if_fail(i != NULL);
+  mp_read_unsigned_bin(&i->i, dh_prime, 64);
 }
 
 
-void mwDHRandKeypair(mpz_t private, mpz_t public) {
-  gmp_randstate_t rstate;
-  mpz_t prime, base;
- 
-  mwInitDHPrime(prime);
-  mwInitDHBase(base);
+static void mwInitDHBase(mp_int *i) {
+  mp_init(i);
+  mp_set_int(i, DH_BASE);
+}
+
+
+void mwMpi_setDHBase(struct mwMpi *i) {
+  g_return_if_fail(i != NULL);
+  mp_set_int(&i->i, DH_BASE);
+}
+
+
+static void mp_set_rand(mp_int *i, guint bits) {
+  size_t len, l;
+  unsigned char *buf;
 
-  gmp_randinit_default(rstate);
-  mpz_urandomb(private, rstate, 512);
-  mpz_powm(public, base, private, prime);
+  l = len = (bits / 8) + 1;
+  buf = g_malloc(len);
+
+  srand(clock());
+  while(l--) buf[l] = rand() & 0xff;
+
+  buf[0] &= (0xff >> (8 - (bits % 8)));
 
-  mpz_clear(prime);
-  mpz_clear(base);
-  gmp_randclear(rstate);
+  mp_read_unsigned_bin(i, buf, len);
+  g_free(buf);
+}
+
+
+void mwMpi_rand(struct mwMpi *i, guint bits) {
+  g_return_if_fail(i != NULL);
+  mp_set_rand(&i->i, bits);
 }
 
 
-void mwDHCalculateShared(mpz_t shared, mpz_t remote, mpz_t private) {
-  mpz_t prime;
+static void mwDHRandKeypair(mp_int *private, mp_int *public) {
+  mp_int prime, base;
  
-  mwInitDHPrime(prime);
-  mpz_powm(shared, remote, private, prime);
-  mpz_clear(prime);
+  mwInitDHPrime(&prime);
+  mwInitDHBase(&base);
+
+  mp_set_rand(private, 512);
+  mp_exptmod(&base, private, &prime, public);
+
+  mp_clear(&prime);
+  mp_clear(&base);
 }
 
 
-void mwDHImportKey(mpz_t key, struct mwOpaque *o) {
-  g_return_if_fail(o != NULL);
-  mpz_import(key, o->len, 1, 1, 1, 0, o->data);
+void mwMpi_randDHKeypair(struct mwMpi *private, struct mwMpi *public) {
+  g_return_if_fail(private != NULL);
+  g_return_if_fail(public != NULL);
+
+  mwDHRandKeypair(&private->i, &public->i);
+}
+
+
+static void mwDHCalculateShared(mp_int *shared, mp_int *remote,
+				mp_int *private) {
+  mp_int prime;
+ 
+  mwInitDHPrime(&prime);
+  mp_exptmod(remote, private, &prime, shared);
+  mp_clear(&prime);
 }
 
 
-void mwDHExportKey(mpz_t key, struct mwOpaque *o) {
-  gsize needed;
+void mwMpi_calculateDHShared(struct mwMpi *shared, struct mwMpi *remote,
+			     struct mwMpi *private) {
 
-  g_return_if_fail(o != NULL);
+  g_return_if_fail(shared != NULL);
+  g_return_if_fail(remote != NULL);
+  g_return_if_fail(private != NULL);
 
-  needed = (mpz_sizeinbase(key,2) + 7) / 8;
-  o->len = 65;
-  o->data = g_malloc0(o->len);
+  mwDHCalculateShared(&shared->i, &remote->i, &private->i);
+}
 
-  mpz_export(o->data+(o->len-needed), NULL, 1, 1, 1, 0, key);
+
+static void mwDHImportKey(mp_int *key, struct mwOpaque *o) {
+  mp_read_unsigned_bin(key, o->data, o->len);
 }
 
 
-void mwKeyRandom(char *key, gsize keylen) {
+void mwMpi_import(struct mwMpi *i, struct mwOpaque *o) {
+  g_return_if_fail(i != NULL);
+  g_return_if_fail(o != NULL);
+
+  mwDHImportKey(&i->i, o);
+}
+
+
+static void mwDHExportKey(mp_int *key, struct mwOpaque *o) {
+  o->len = mp_unsigned_bin_size(key);
+  o->data = g_malloc0(o->len);
+  mp_to_unsigned_bin(key, o->data);
+}
+
+
+void mwMpi_export(struct mwMpi *i, struct mwOpaque *o) {
+  g_return_if_fail(i != NULL);
+  g_return_if_fail(o != NULL);
+  
+  mwDHExportKey(&i->i, o);
+}
+
+
+void mwKeyRandom(unsigned char *key, gsize keylen) {
   g_return_if_fail(key != NULL);
 
   srand(clock());
@@ -149,11 +229,13 @@
 }
 
 
-void mwIV_init(char *iv) {
+void mwIV_init(unsigned char *iv) {
+  int i;
   static unsigned char normal_iv[] = {
     0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
   };
-  memcpy(iv, normal_iv, 8);
+  for(i = 8; i--; iv[i] = normal_iv[i]);
+  /* memcpy(iv, normal_iv, 8); */
 }
 
 
@@ -161,7 +243,7 @@
    expansion would, but it works, so eh. It might be smart to farm
    this out to mozilla or openssl */
 void mwKeyExpand(int *ekey, const char *key, gsize keylen) {
-  char tmp[128];
+  unsigned char tmp[128];
   int i, j;
 
   g_return_if_fail(keylen > 0);
@@ -170,7 +252,8 @@
   if(keylen > 128) keylen = 128;
 
   /* fill the first chunk with what key bytes we have */
-  memcpy(tmp, key, keylen);
+  for(i = keylen; i--; tmp[i] = key[i]);
+  /* memcpy(tmp, key, keylen); */
 
   /* build the remaining key from the given data */
   for(i = 0; keylen < 128; i++) {
@@ -232,14 +315,14 @@
 }
 
 
-void mwEncryptExpanded(const int *ekey, char *iv,
+void mwEncryptExpanded(const int *ekey, unsigned char *iv,
 		       struct mwOpaque *in_data,
 		       struct mwOpaque *out_data) {
 
-  char *i = in_data->data;
+  unsigned char *i = in_data->data;
   gsize i_len = in_data->len;
 
-  char *o;
+  unsigned char *o;
   gsize o_len;
 
   int x, y;
@@ -255,20 +338,23 @@
   y = o_len - i_len;
 
   /* copy in to out, and write padding bytes */
-  memcpy(o, i, i_len);
-  memset(o + i_len, y, y);
+  for(x = i_len; x--; o[x] = i[x]);
+  for(x = i_len; x < o_len; o[x++] = y);
+  /* memcpy(o, i, i_len);
+     memset(o + i_len, y, y); */
 
   /* encrypt in blocks */
   for(x = o_len; x > 0; x -= 8) {
     for(y = 8; y--; o[y] ^= iv[y]);
     mwEncryptBlock(ekey, o);
-    memcpy(iv, o, 8);
+    for(y = 8; y--; iv[y] = o[y]);
+    /* memcpy(iv, o, 8); */
     o += 8;
   }
 }
 
 
-void mwEncrypt(const char *key, gsize keylen, char *iv,
+void mwEncrypt(const char *key, gsize keylen, unsigned char *iv,
 	       struct mwOpaque *in, struct mwOpaque *out) {
 
   int ekey[64];
@@ -277,7 +363,7 @@
 }
 
 
-static void mwDecryptBlock(const int *ekey, char *out) {
+static void mwDecryptBlock(const int *ekey, unsigned char *out) {
 
   int a, b, c, d;
   int i, j;
@@ -321,14 +407,14 @@
 }
 
 
-void mwDecryptExpanded(const int *ekey, char *iv,
+void mwDecryptExpanded(const int *ekey, unsigned char *iv,
 		       struct mwOpaque *in_data,
 		       struct mwOpaque *out_data) {
 
-  char *i = in_data->data;
+  unsigned char *i = in_data->data;
   gsize i_len = in_data->len;
 
-  char *o;
+  unsigned char *o;
   gsize o_len;
 
   int x, y;
@@ -338,7 +424,8 @@
 
   o = g_malloc(i_len);
   o_len = i_len;
-  memcpy(o, i, i_len);
+  for(x = i_len; x--; o[x] = i[x]);
+  /* memcpy(o, i, i_len); */
 
   out_data->data = o;
   out_data->len = o_len;
@@ -349,7 +436,8 @@
 
     /* modify the initialization vector */
     for(y = 8; y--; o[y] ^= iv[y]);
-    memcpy(iv, i, 8);
+    for(y = 8; y--; iv[y] = i[y]);
+    /* memcpy(iv, i, 8); */
     i += 8;
     o += 8;
   }
@@ -360,7 +448,7 @@
 }
 
 
-void mwDecrypt(const char *key, gsize keylen, char *iv,
+void mwDecrypt(const char *key, gsize keylen, unsigned char *iv,
 	       struct mwOpaque *in, struct mwOpaque *out) {
 
   int ekey[64];
@@ -380,8 +468,8 @@
 struct mwCipherInstance_RC2_40 {
   struct mwCipherInstance instance;
   int incoming_key[64];
-  char outgoing_iv[8];
-  char incoming_iv[8];
+  unsigned char outgoing_iv[8];
+  unsigned char incoming_iv[8];
 };
 
 
@@ -527,7 +615,7 @@
 
 struct mwCipher_RC2_128 {
   struct mwCipher cipher;
-  mpz_t private_key;
+  mp_int private_key;
   struct mwOpaque public_key;
 };
 
@@ -535,8 +623,8 @@
 struct mwCipherInstance_RC2_128 {
   struct mwCipherInstance instance;
   int shared[64];      /* shared secret determined via DH exchange */
-  char outgoing_iv[8];
-  char incoming_iv[8];
+  unsigned char outgoing_iv[8];
+  unsigned char incoming_iv[8];
 };
 
 
@@ -576,8 +664,8 @@
 static void offered_RC2_128(struct mwCipherInstance *ci,
 			    struct mwEncryptItem *item) {
   
-  mpz_t remote_key;
-  mpz_t shared;
+  mp_int remote_key;
+  mp_int shared;
   struct mwOpaque sho = { 0, 0 };
 
   struct mwCipher *c;
@@ -588,12 +676,12 @@
   cr = (struct mwCipher_RC2_128 *) c;
   cir = (struct mwCipherInstance_RC2_128 *) ci;
 
-  mpz_init(remote_key);
-  mpz_init(shared);
+  mp_init(&remote_key);
+  mp_init(&shared);
 
-  mwDHImportKey(remote_key, &item->info);
-  mwDHCalculateShared(shared, remote_key, cr->private_key);
-  mwDHExportKey(shared, &sho);
+  mwDHImportKey(&remote_key, &item->info);
+  mwDHCalculateShared(&shared, &remote_key, &cr->private_key);
+  mwDHExportKey(&shared, &sho);
 
   /* key expanded from the last 16 bytes of the DH shared secret. This
      took me forever to figure out. 16 bytes is 128 bit. */
@@ -602,8 +690,8 @@
      exported key might be less than 64 bytes in length */
   mwKeyExpand(cir->shared, sho.data+(sho.len-16), 16);
   
-  mpz_clear(remote_key);
-  mpz_clear(shared);
+  mp_clear(&remote_key);
+  mp_clear(&shared);
   mwOpaque_clear(&sho);
 }
 
@@ -680,7 +768,7 @@
   struct mwCipher_RC2_128 *cr;
   cr = (struct mwCipher_RC2_128 *) c;
 
-  mpz_clear(cr->private_key);
+  mp_clear(&cr->private_key);
   mwOpaque_clear(&cr->public_key);
 }
 
@@ -689,7 +777,7 @@
   struct mwCipher_RC2_128 *cr;
   struct mwCipher *c;
 
-  mpz_t pubkey;
+  mp_int pubkey;
 
   cr = g_new0(struct mwCipher_RC2_128, 1);
   c = &cr->cipher;
@@ -711,11 +799,11 @@
 
   c->clear = clear_RC2_128;
   
-  mpz_init(cr->private_key);
-  mpz_init(pubkey);
-  mwDHRandKeypair(cr->private_key, pubkey);
-  mwDHExportKey(pubkey, &cr->public_key);
-  mpz_clear(pubkey);
+  mp_init(&cr->private_key);
+  mp_init(&pubkey);
+  mwDHRandKeypair(&cr->private_key, &pubkey);
+  mwDHExportKey(&pubkey, &cr->public_key);
+  mp_clear(&pubkey);
 
   return c;
 }
@@ -780,19 +868,6 @@
 }
 
 
-struct mwEncryptItem *mwCipherInstance_newItem(struct mwCipherInstance *ci) {
-  struct mwCipher *cipher;
-
-  g_return_val_if_fail(ci != NULL, NULL);
-  cipher = ci->cipher;
-
-  g_return_val_if_fail(cipher != NULL, NULL);
-  g_return_val_if_fail(cipher->new_item != NULL, NULL);
-
-  return cipher->new_item(ci);
-}
-
-
 void mwCipherInstance_offered(struct mwCipherInstance *ci,
 			      struct mwEncryptItem *item) {
   struct mwCipher *cipher;