/cpw/tomkiewicz/masterpassword: 087c0fbac984: AES support
Tomasz Wasilczyk
tomkiewicz at cpw.pidgin.im
Thu May 9 14:24:37 EDT 2013
Changeset: 087c0fbac9847c30af5f0804e63a09dfaada3d00
Author: Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date: 2013-05-09 20:24 +0200
Branch: soc.2008.masterpassword
URL: https://hg.pidgin.im/cpw/tomkiewicz/masterpassword/rev/087c0fbac984
Description:
AES support
diffstat:
libpurple/Makefile.am | 2 +
libpurple/Makefile.mingw | 1 +
libpurple/cipher.c | 10 +-
libpurple/ciphers/Makefile.am | 12 +-
libpurple/ciphers/aes.c | 566 +++++++++++++++++++++++++++++++++++++++++
libpurple/ciphers/ciphers.h | 25 +
libpurple/plugins/ciphertest.c | 159 ++++++++++-
7 files changed, 754 insertions(+), 21 deletions(-)
diffs (truncated from 908 to 300 lines):
diff --git a/libpurple/Makefile.am b/libpurple/Makefile.am
--- a/libpurple/Makefile.am
+++ b/libpurple/Makefile.am
@@ -317,6 +317,8 @@ libpurple_la_LIBADD = \
$(GSTINTERFACES_LIBS) \
$(IDN_LIBS) \
$(JSON_LIBS) \
+ $(GNUTLS_LIBS) \
+ $(NSS_LIBS) \
ciphers/libpurple-ciphers.la \
-lm
diff --git a/libpurple/Makefile.mingw b/libpurple/Makefile.mingw
--- a/libpurple/Makefile.mingw
+++ b/libpurple/Makefile.mingw
@@ -49,6 +49,7 @@ C_SRC = \
buddyicon.c \
certificate.c \
cipher.c \
+ ciphers/aes.c \
ciphers/des.c \
ciphers/gchecksum.c \
ciphers/hmac.c \
diff --git a/libpurple/cipher.c b/libpurple/cipher.c
--- a/libpurple/cipher.c
+++ b/libpurple/cipher.c
@@ -248,15 +248,7 @@ purple_ciphers_init() {
purple_value_new(PURPLE_TYPE_SUBTYPE,
PURPLE_SUBTYPE_CIPHER));
- purple_ciphers_register_cipher("md5", purple_md5_cipher_get_ops());
- purple_ciphers_register_cipher("sha1", purple_sha1_cipher_get_ops());
- purple_ciphers_register_cipher("sha256", purple_sha256_cipher_get_ops());
- purple_ciphers_register_cipher("md4", purple_md4_cipher_get_ops());
- purple_ciphers_register_cipher("hmac", purple_hmac_cipher_get_ops());
- purple_ciphers_register_cipher("des", purple_des_cipher_get_ops());
- purple_ciphers_register_cipher("des3", purple_des3_cipher_get_ops());
- purple_ciphers_register_cipher("pbkdf2", purple_pbkdf2_cipher_get_ops());
- purple_ciphers_register_cipher("rc4", purple_rc4_cipher_get_ops());
+ purple_ciphers_register_all();
}
void
diff --git a/libpurple/ciphers/Makefile.am b/libpurple/ciphers/Makefile.am
--- a/libpurple/ciphers/Makefile.am
+++ b/libpurple/ciphers/Makefile.am
@@ -1,7 +1,15 @@
noinst_LTLIBRARIES=libpurple-ciphers.la
# XXX: cipher.lo won't be updated after a change in cipher files
+if USE_NSS
+AES_SOURCE = aes.c
+endif
+if USE_GNUTLS
+AES_SOURCE = aes.c
+endif
+
libpurple_ciphers_la_SOURCES=\
+ $(AES_SOURCE) \
des.c \
gchecksum.c \
hmac.c \
@@ -18,4 +26,6 @@ AM_CPPFLAGS = \
$(INTGG_CFLAGS) \
$(AM_CFLAGS) \
$(GLIB_CFLAGS) \
- $(DEBUG_CFLAGS)
+ $(DEBUG_CFLAGS) \
+ $(GNUTLS_CFLAGS) \
+ $(NSS_CFLAGS)
diff --git a/libpurple/ciphers/aes.c b/libpurple/ciphers/aes.c
new file mode 100644
--- /dev/null
+++ b/libpurple/ciphers/aes.c
@@ -0,0 +1,566 @@
+/*
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ * Written by Tomek Wasilczyk <tomkiewicz at cpw.pidgin.im>
+ */
+
+#include "internal.h"
+#include "cipher.h"
+#include "ciphers.h"
+#include "debug.h"
+
+#if defined(HAVE_GNUTLS)
+# define PURPLE_AES_USE_GNUTLS 1
+# include <gnutls/gnutls.h>
+# include <gnutls/crypto.h>
+#elif defined(HAVE_NSS)
+# define PURPLE_AES_USE_NSS 1
+# include <nss.h>
+# include <pk11pub.h>
+# include <prerror.h>
+#else
+# error "No GnuTLS or NSS support"
+#endif
+
+/* 128bit */
+#define PURPLE_AES_BLOCK_SIZE 16
+
+typedef struct
+{
+ guchar iv[PURPLE_AES_BLOCK_SIZE];
+ guchar key[32];
+ guint key_size;
+ gboolean failure;
+} AESContext;
+
+typedef gboolean (*purple_aes_crypt_func)(
+ const guchar *input, guchar *output, size_t len,
+ guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size);
+
+static void
+purple_aes_init(PurpleCipherContext *context, void *extra)
+{
+ AESContext *ctx_data;
+
+ ctx_data = g_new0(AESContext, 1);
+ purple_cipher_context_set_data(context, ctx_data);
+
+ purple_cipher_context_reset(context, extra);
+}
+
+static void
+purple_aes_uninit(PurpleCipherContext *context)
+{
+ AESContext *ctx_data;
+
+ purple_cipher_context_reset(context, NULL);
+
+ ctx_data = purple_cipher_context_get_data(context);
+ g_free(ctx_data);
+ purple_cipher_context_set_data(context, NULL);
+}
+
+static void
+purple_aes_reset(PurpleCipherContext *context, void *extra)
+{
+ AESContext *ctx_data = purple_cipher_context_get_data(context);
+
+ g_return_if_fail(ctx_data != NULL);
+
+ memset(ctx_data->iv, 0, sizeof(ctx_data->iv));
+ memset(ctx_data->key, 0, sizeof(ctx_data->key));
+ ctx_data->key_size = 32; /* 256bit */
+ ctx_data->failure = FALSE;
+}
+
+static void
+purple_aes_set_option(PurpleCipherContext *context, const gchar *name,
+ void *value)
+{
+ AESContext *ctx_data = purple_cipher_context_get_data(context);
+
+ purple_debug_error("cipher-aes", "set_option not supported\n");
+ ctx_data->failure = TRUE;
+}
+
+static void
+purple_aes_set_iv(PurpleCipherContext *context, guchar *iv, size_t len)
+{
+ AESContext *ctx_data = purple_cipher_context_get_data(context);
+
+ if ((len > 0 && iv == NULL) ||
+ (len != 0 && len != sizeof(ctx_data->iv))) {
+ purple_debug_error("cipher-aes", "invalid IV length\n");
+ ctx_data->failure = TRUE;
+ return;
+ }
+
+ if (len == 0)
+ memset(ctx_data->iv, 0, sizeof(ctx_data->iv));
+ else
+ memcpy(ctx_data->iv, iv, len);
+}
+
+static void
+purple_aes_set_key(PurpleCipherContext *context, const guchar *key, size_t len)
+{
+ AESContext *ctx_data = purple_cipher_context_get_data(context);
+
+ if ((len > 0 && key == NULL) ||
+ (len != 0 && len != 16 && len != 24 && len != 32)) {
+ purple_debug_error("cipher-aes", "invalid key length\n");
+ ctx_data->failure = TRUE;
+ return;
+ }
+
+ ctx_data->key_size = len;
+ memset(ctx_data->key, 0, sizeof(ctx_data->key));
+ if (len > 0)
+ memcpy(ctx_data->key, key, len);
+}
+
+static guchar *
+purple_aes_pad_pkcs7(const guchar input[], size_t in_len, size_t *out_len)
+{
+ int padding_len, total_len;
+ guchar *padded;
+
+ g_return_val_if_fail(input != NULL, NULL);
+ g_return_val_if_fail(out_len != NULL, NULL);
+
+ padding_len = PURPLE_AES_BLOCK_SIZE - (in_len % PURPLE_AES_BLOCK_SIZE);
+ total_len = in_len + padding_len;
+ g_assert((total_len % PURPLE_AES_BLOCK_SIZE) == 0);
+
+ padded = g_new(guchar, total_len);
+ *out_len = total_len;
+
+ memcpy(padded, input, in_len);
+ memset(padded + in_len, padding_len, padding_len);
+
+ return padded;
+}
+
+static ssize_t
+purple_aes_unpad_pkcs7(guchar input[], size_t in_len)
+{
+ int padding_len, i;
+ size_t out_len;
+
+ g_return_val_if_fail(input != NULL, -1);
+ g_return_val_if_fail(in_len > 0, -1);
+
+ padding_len = input[in_len - 1];
+ if (padding_len <= 0 || padding_len > PURPLE_AES_BLOCK_SIZE ||
+ padding_len > in_len) {
+ purple_debug_warning("cipher-aes",
+ "Invalid padding length: %d (total %d) - "
+ "most probably, the key was invalid\n",
+ padding_len, in_len);
+ return -1;
+ }
+
+ out_len = in_len - padding_len;
+ for (i = 0; i < padding_len; i++) {
+ if (input[out_len + i] != padding_len) {
+ purple_debug_warning("cipher-aes",
+ "Padding doesn't match at pos %d (found %02x, "
+ "expected %02x) - "
+ "most probably, the key was invalid\n",
+ i, input[out_len + i], padding_len);
+ return -1;
+ }
+ }
+
+ memset(input + out_len, 0, padding_len);
+ return out_len;
+}
+
+#ifdef PURPLE_AES_USE_GNUTLS
+
+static gnutls_cipher_hd_t
+purple_aes_crypt_gnutls_init(guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32],
+ guint key_size)
+{
+ gnutls_cipher_hd_t handle;
+ gnutls_cipher_algorithm_t algorithm;
+ gnutls_datum_t key_info, iv_info;
+ int ret;
+
+ if (key_size == 16)
+ algorithm = GNUTLS_CIPHER_AES_128_CBC;
+ else if (key_size == 24)
+ algorithm = GNUTLS_CIPHER_AES_192_CBC;
+ else if (key_size == 32)
+ algorithm = GNUTLS_CIPHER_AES_256_CBC;
+ else
+ g_return_val_if_reached(NULL);
+
+ key_info.data = key;
+ key_info.size = key_size;
+
+ iv_info.data = iv;
+ iv_info.size = PURPLE_AES_BLOCK_SIZE;
+
+ ret = gnutls_cipher_init(&handle, algorithm, &key_info, &iv_info);
+ if (ret != 0) {
+ purple_debug_error("cipher-aes",
More information about the Commits
mailing list