summaryrefslogtreecommitdiff
path: root/libpurple/cipher.c
diff options
context:
space:
mode:
authorPaul Aurich <darkrain42@pidgin.im>2009-07-04 23:13:23 +0000
committerPaul Aurich <darkrain42@pidgin.im>2009-07-04 23:13:23 +0000
commit003b0f0506abcb025de0d6366659bf1da0f21008 (patch)
tree33bdefac58f850e64173e0fbfb59b7d60582fc97 /libpurple/cipher.c
parent5b3275b1bd6c93ddcf3ed666570f3e5a288f2397 (diff)
downloadpidgin-003b0f0506abcb025de0d6366659bf1da0f21008.tar.gz
Use glib's SHA1, SHA256, and MD5 implementations when available (glib 2.16)
These SHA1 and SHA256 implementations do not expose any options, which the built-in ones do (for getting/setting sizeHi, sizeLo, and lenW). Nothing in Pidgin uses those (and I can't think of a decent use case), so I think this is OK. Feel free to disagree. As I mentioned on the mailing list, glib's SHA1 implementation was just under 3x as fast on my system.
Diffstat (limited to 'libpurple/cipher.c')
-rw-r--r--libpurple/cipher.c276
1 files changed, 255 insertions, 21 deletions
diff --git a/libpurple/cipher.c b/libpurple/cipher.c
index 15def7c393..890572b3f6 100644
--- a/libpurple/cipher.c
+++ b/libpurple/cipher.c
@@ -61,11 +61,152 @@
#include "signals.h"
#include "value.h"
+#if GLIB_CHECK_VERSION(2,16,0)
+static void
+purple_g_checksum_init(PurpleCipherContext *context, GChecksumType type)
+{
+ GChecksum *checksum;
+
+ checksum = g_checksum_new(type);
+ purple_cipher_context_set_data(context, checksum);
+}
+
+static void
+purple_g_checksum_reset(PurpleCipherContext *context, GChecksumType type)
+{
+ GChecksum *checksum;
+
+ checksum = purple_cipher_context_get_data(context);
+ g_return_if_fail(checksum != NULL);
+
+#if GLIB_CHECK_VERSION(2,18,0)
+ g_checksum_reset(checksum);
+#else
+ g_checksum_free(checksum);
+ checksum = g_checksum_new(type);
+ purple_cipher_context_set_data(context, checksum);
+#endif
+}
+
+static void
+purple_g_checksum_uninit(PurpleCipherContext *context)
+{
+ GChecksum *checksum;
+
+ checksum = purple_cipher_context_get_data(context);
+ g_return_if_fail(checksum != NULL);
+
+ g_checksum_free(checksum);
+}
+
+static void
+purple_g_checksum_append(PurpleCipherContext *context, const guchar *data,
+ gsize len)
+{
+ GChecksum *checksum;
+
+ checksum = purple_cipher_context_get_data(context);
+ g_return_if_fail(checksum != NULL);
+
+ if (len > (gsize)G_MAXSSIZE) {
+ /*
+ * g_checksum_update takes a gssize, whereas we handle gsizes. To
+ * be pedantically correct, we need to handle this case. In real life,
+ * I think this couldn't actually occur.
+ */
+ const guchar *buf = data;
+ gssize chunk_size;
+ while (len > 0) {
+ chunk_size = MIN(G_MAXSSIZE, len);
+ g_checksum_update(checksum, buf, chunk_size);
+ len -= chunk_size;
+ buf += chunk_size;
+ }
+ } else
+ g_checksum_update(checksum, data, len);
+}
+
+static gboolean
+purple_g_checksum_digest(PurpleCipherContext *context, GChecksumType type,
+ gsize len, guchar *digest, gsize *out_len)
+{
+ GChecksum *checksum;
+ const gssize required_length = g_checksum_type_get_length(type);
+
+ checksum = purple_cipher_context_get_data(context);
+
+ g_return_val_if_fail(len >= required_length, FALSE);
+ g_return_val_if_fail(checksum != NULL, FALSE);
+
+ g_checksum_get_digest(checksum, digest, &len);
+
+ purple_cipher_context_reset(context, NULL);
+
+ if (out_len)
+ *out_len = len;
+
+ return TRUE;
+}
+#endif
+
+
/*******************************************************************************
* MD5
******************************************************************************/
#define MD5_HMAC_BLOCK_SIZE 64
+static size_t
+md5_get_block_size(PurpleCipherContext *context)
+{
+ /* This does not change (in this case) */
+ return MD5_HMAC_BLOCK_SIZE;
+}
+
+#if GLIB_CHECK_VERSION(2,16,0)
+
+static void
+md5_init(PurpleCipherContext *context, void *extra)
+{
+ purple_g_checksum_init(context, G_CHECKSUM_MD5);
+}
+
+static void
+md5_reset(PurpleCipherContext *context, void *extra)
+{
+ purple_g_checksum_reset(context, G_CHECKSUM_MD5);
+}
+
+static gboolean
+md5_digest(PurpleCipherContext *context, gsize in_len, guchar digest[16],
+ size_t *out_len)
+{
+ return purple_g_checksum_digest(context, G_CHECKSUM_MD5, in_len,
+ digest, out_len);
+}
+
+static PurpleCipherOps MD5Ops = {
+ NULL, /* Set Option */
+ NULL, /* Get Option */
+ md5_init, /* init */
+ md5_reset, /* reset */
+ purple_g_checksum_uninit, /* uninit */
+ NULL, /* set iv */
+ purple_g_checksum_append, /* append */
+ md5_digest, /* digest */
+ NULL, /* encrypt */
+ NULL, /* decrypt */
+ NULL, /* set salt */
+ NULL, /* get salt size */
+ NULL, /* set key */
+ NULL, /* get key size */
+ NULL, /* set batch mode */
+ NULL, /* get batch mode */
+ md5_get_block_size, /* get block size */
+ NULL /* set key with len */
+};
+
+#else /* GLIB_CHECK_VERSION(2,16,0) */
+
struct MD5Context {
guint32 total[2];
guint32 state[4];
@@ -327,13 +468,6 @@ md5_digest(PurpleCipherContext *context, size_t in_len, guchar digest[16],
return TRUE;
}
-static size_t
-md5_get_block_size(PurpleCipherContext *context)
-{
- /* This does not change (in this case) */
- return MD5_HMAC_BLOCK_SIZE;
-}
-
static PurpleCipherOps MD5Ops = {
NULL, /* Set option */
NULL, /* Get option */
@@ -355,6 +489,8 @@ static PurpleCipherOps MD5Ops = {
NULL /* set key with len */
};
+#endif /* GLIB_CHECK_VERSION(2,16,0) */
+
/*******************************************************************************
* MD4
******************************************************************************/
@@ -1613,6 +1749,61 @@ static PurpleCipherOps DES3Ops = {
* SHA-1
******************************************************************************/
#define SHA1_HMAC_BLOCK_SIZE 64
+
+static size_t
+sha1_get_block_size(PurpleCipherContext *context)
+{
+ /* This does not change (in this case) */
+ return SHA1_HMAC_BLOCK_SIZE;
+}
+
+
+#if GLIB_CHECK_VERSION(2,16,0)
+
+static void
+sha1_init(PurpleCipherContext *context, void *extra)
+{
+ purple_g_checksum_init(context, G_CHECKSUM_SHA1);
+}
+
+static void
+sha1_reset(PurpleCipherContext *context, void *extra)
+{
+ purple_g_checksum_reset(context, G_CHECKSUM_SHA1);
+}
+
+static gboolean
+sha1_digest(PurpleCipherContext *context, gsize in_len, guchar digest[20],
+ gsize *out_len)
+{
+ return purple_g_checksum_digest(context, G_CHECKSUM_SHA1, in_len,
+ digest, out_len);
+}
+
+static PurpleCipherOps SHA1Ops = {
+ NULL, /* Set Option */
+ NULL, /* Get Option */
+ sha1_init, /* init */
+ sha1_reset, /* reset */
+ purple_g_checksum_uninit, /* uninit */
+ NULL, /* set iv */
+ purple_g_checksum_append, /* append */
+ sha1_digest, /* digest */
+ NULL, /* encrypt */
+ NULL, /* decrypt */
+ NULL, /* set salt */
+ NULL, /* get salt size */
+ NULL, /* set key */
+ NULL, /* get key size */
+ NULL, /* set batch mode */
+ NULL, /* get batch mode */
+ sha1_get_block_size, /* get block size */
+ NULL /* set key with len */
+};
+
+#else /* GLIB_CHECK_VERSION(2,16,0) */
+
+#define SHA1_HMAC_BLOCK_SIZE 64
#define SHA1_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xFFFFFFFF)
struct SHA1Context {
@@ -1833,13 +2024,6 @@ sha1_digest(PurpleCipherContext *context, size_t in_len, guchar digest[20],
return TRUE;
}
-static size_t
-sha1_get_block_size(PurpleCipherContext *context)
-{
- /* This does not change (in this case) */
- return SHA1_HMAC_BLOCK_SIZE;
-}
-
static PurpleCipherOps SHA1Ops = {
sha1_set_opt, /* Set Option */
sha1_get_opt, /* Get Option */
@@ -1861,10 +2045,65 @@ static PurpleCipherOps SHA1Ops = {
NULL /* set key with len */
};
+#endif /* GLIB_CHECK_VERSION(2,16,0) */
+
/*******************************************************************************
* SHA-256
******************************************************************************/
#define SHA256_HMAC_BLOCK_SIZE 64
+
+static size_t
+sha256_get_block_size(PurpleCipherContext *context)
+{
+ /* This does not change (in this case) */
+ return SHA256_HMAC_BLOCK_SIZE;
+}
+
+#if GLIB_CHECK_VERSION(2,16,0)
+
+static void
+sha256_init(PurpleCipherContext *context, void *extra)
+{
+ purple_g_checksum_init(context, G_CHECKSUM_SHA256);
+}
+
+static void
+sha256_reset(PurpleCipherContext *context, void *extra)
+{
+ purple_g_checksum_reset(context, G_CHECKSUM_SHA256);
+}
+
+static gboolean
+sha256_digest(PurpleCipherContext *context, gsize in_len, guchar digest[20],
+ gsize *out_len)
+{
+ return purple_g_checksum_digest(context, G_CHECKSUM_SHA256, in_len,
+ digest, out_len);
+}
+
+static PurpleCipherOps SHA256Ops = {
+ NULL, /* Set Option */
+ NULL, /* Get Option */
+ sha256_init, /* init */
+ sha256_reset, /* reset */
+ purple_g_checksum_uninit, /* uninit */
+ NULL, /* set iv */
+ purple_g_checksum_append, /* append */
+ sha256_digest, /* digest */
+ NULL, /* encrypt */
+ NULL, /* decrypt */
+ NULL, /* set salt */
+ NULL, /* get salt size */
+ NULL, /* set key */
+ NULL, /* get key size */
+ NULL, /* set batch mode */
+ NULL, /* get batch mode */
+ sha256_get_block_size, /* get block size */
+ NULL /* set key with len */
+};
+
+#else /* GLIB_CHECK_VERSION(2,16,0) */
+
#define SHA256_ROTR(X,n) ((((X) >> (n)) | ((X) << (32-(n)))) & 0xFFFFFFFF)
static const guint32 sha256_K[64] =
@@ -2088,13 +2327,6 @@ sha256_digest(PurpleCipherContext *context, size_t in_len, guchar digest[32],
return TRUE;
}
-static size_t
-sha256_get_block_size(PurpleCipherContext *context)
-{
- /* This does not change (in this case) */
- return SHA256_HMAC_BLOCK_SIZE;
-}
-
static PurpleCipherOps SHA256Ops = {
sha256_set_opt, /* Set Option */
sha256_get_opt, /* Get Option */
@@ -2116,6 +2348,8 @@ static PurpleCipherOps SHA256Ops = {
NULL /* set key with len */
};
+#endif /* GLIB_CHECK_VERSION(2,16,0) */
+
/*******************************************************************************
* RC4
******************************************************************************/