libpurple/ciphers/des.c

branch
soc.2013.gobjectification
changeset 34537
fb40b0460a36
parent 33944
1ca572ed7563
child 34547
45b72366ddde
--- a/libpurple/ciphers/des.c	Thu Jun 13 20:43:35 2013 +0530
+++ b/libpurple/ciphers/des.c	Thu Jun 13 22:59:58 2013 +0530
@@ -1,23 +1,19 @@
 /*
- * 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.
- *
  * Original des taken from gpg
  *
- * des.c - DES and Triple-DES encryption/decryption Algorithm
+ * des.c - DES encryption/decryption Algorithm
  *  Copyright (C) 1998 Free Software Foundation, Inc.
  *
  *  Please see below for more legal information!
- *
+ *  
  *   According to the definition of DES in FIPS PUB 46-2 from December 1993.
  *   For a description of triple encryption, see:
  *     Bruce Schneier: Applied Cryptography. Second Edition.
  *     John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff.
- *
- *   This file is part of GnuPG.
+ *  
+ * 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
@@ -33,228 +29,255 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
+#include "des.h"
 
-#include "internal.h"
-#include <cipher.h>
-#include "ciphers.h"
+#include <string.h>
 
 /******************************************************************************
- * DES
+ * Structs
  *****************************************************************************/
-typedef struct _des_ctx
-{
+#define PURPLE_DES_CIPHER_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_DES_CIPHER, PurpleDESCipherPrivate))
+
+typedef struct {
 	guint32 encrypt_subkeys[32];
 	guint32 decrypt_subkeys[32];
-} des_ctx[1];
+} PurpleDESCipherPrivate;
 
-/*
+/******************************************************************************
+ * Enums
+ *****************************************************************************/
+enum {
+	PROP_NONE,
+	PROP_KEY,
+	PROP_LAST,
+};
+
+/******************************************************************************
+ * Globals
+ *****************************************************************************/
+static GObjectClass *parent_class = NULL;
+
+/*  
  *  The s-box values are permuted according to the 'primitive function P'
  */
-static const guint32 sbox1[64] =
-{
-	0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000,
-	0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002,
-	0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202,
-	0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000,
-	0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200,
-	0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202,
-	0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200,
-	0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002
+static guint32 sbox1[64] = {
+	0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202,
+	0x00000002, 0x00008000, 0x00000200, 0x00808200, 0x00808202, 0x00000200,
+	0x00800202, 0x00808002, 0x00800000, 0x00000002, 0x00000202, 0x00800200,
+	0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202,
+	0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202,
+	0x00008202, 0x00800000, 0x00008000, 0x00808202, 0x00000002, 0x00808000,
+	0x00808200, 0x00800000, 0x00800000, 0x00000200, 0x00808002, 0x00008000,
+	0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202,
+	0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202,
+	0x00008202, 0x00808200, 0x00000202, 0x00800200, 0x00800200, 0x00000000,
+	0x00008002, 0x00008200, 0x00000000, 0x00808002
 };
 
-static const guint32 sbox2[64] =
-{
-	0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010,
-	0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010,
-	0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000,
-	0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010,
-	0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000,
-	0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000,
-	0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010,
-	0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000
+static guint32 sbox2[64] = {
+	0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010,
+	0x40080010, 0x40004010, 0x40000010, 0x40084010, 0x40084000, 0x40000000,
+	0x40004000, 0x00080000, 0x00000010, 0x40080010, 0x00084000, 0x00080010,
+	0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000,
+	0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000,
+	0x40080000, 0x00004010, 0x00000000, 0x00084010, 0x40080010, 0x00080000,
+	0x40004010, 0x40080000, 0x40084000, 0x00004000, 0x40080000, 0x40004000,
+	0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000,
+	0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010,
+	0x40000010, 0x00080010, 0x00084000, 0x00000000, 0x40004000, 0x00004010,
+	0x40000000, 0x40080010, 0x40084010, 0x00084000
 };
 
-static const guint32 sbox3[64] =
-{
-	0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100,
-	0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104,
-	0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104,
-	0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000,
-	0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000,
-	0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004,
-	0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004,
-	0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100
+static guint32 sbox3[64] = {
+	0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000,
+	0x00010104, 0x04000100, 0x00010004, 0x04000004, 0x04000004, 0x00010000,
+	0x04010104, 0x00010004, 0x04010000, 0x00000104, 0x04000000, 0x00000004,
+	0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104,
+	0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104,
+	0x00000100, 0x04000000, 0x04010100, 0x04000000, 0x00010004, 0x00000104,
+	0x00010000, 0x04010100, 0x04000100, 0x00000000, 0x00000100, 0x00010004,
+	0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004,
+	0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104,
+	0x00010100, 0x04000004, 0x04010000, 0x04000104, 0x00000104, 0x04010000,
+	0x00010104, 0x00000004, 0x04010004, 0x00010100
 };
 
-static const guint32 sbox4[64] =
-{
-	0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000,
-	0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000,
-	0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040,
-	0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040,
-	0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000,
-	0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040,
-	0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040,
-	0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040
+static guint32 sbox4[64] = {
+	0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040,
+	0x80400000, 0x80001000, 0x00000000, 0x00401000, 0x00401000, 0x80401040,
+	0x80000040, 0x00000000, 0x00400040, 0x80400000, 0x80000000, 0x00001000,
+	0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040,
+	0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040,
+	0x80401040, 0x80000040, 0x00400040, 0x80400000, 0x00401000, 0x80401040,
+	0x80000040, 0x00000000, 0x00000000, 0x00401000, 0x00001040, 0x00400040,
+	0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040,
+	0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000,
+	0x00401040, 0x80400040, 0x80001000, 0x00001040, 0x00400000, 0x80401000,
+	0x00000040, 0x00400000, 0x00001000, 0x00401040
 };
 
-static const guint32 sbox5[64] =
-{
-	0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000,
-	0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000,
-	0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080,
-	0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080,
-	0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080,
-	0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000,
-	0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000,
-	0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080
+static guint32 sbox5[64] = {
+	0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080,
+	0x20000000, 0x01040000, 0x20040080, 0x00040000, 0x01000080, 0x20040080,
+	0x21000080, 0x21040000, 0x00040080, 0x20000000, 0x01000000, 0x20040000,
+	0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080,
+	0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000,
+	0x21000000, 0x00040080, 0x00040000, 0x21000080, 0x00000080, 0x01000000,
+	0x20000000, 0x01040000, 0x21000080, 0x20040080, 0x01000080, 0x20000000,
+	0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000,
+	0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000,
+	0x20040000, 0x21000000, 0x00040080, 0x01000080, 0x20000080, 0x00040000,
+	0x00000000, 0x20040000, 0x01040080, 0x20000080
 };
 
-static const guint32 sbox6[64] =
-{
-	0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000,
-	0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008,
-	0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008,
-	0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000,
-	0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008,
-	0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000,
-	0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008,
-	0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008
+static guint32 sbox6[64] = {
+	0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008,
+	0x10202008, 0x00200000, 0x10002000, 0x00202008, 0x00200000, 0x10000008,
+	0x00200008, 0x10002000, 0x10000000, 0x00002008, 0x00000000, 0x00200008,
+	0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008,
+	0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000,
+	0x10202000, 0x10000000, 0x10002000, 0x00000008, 0x10200008, 0x00202000,
+	0x10202008, 0x00200000, 0x00002008, 0x10000008, 0x00200000, 0x10002000,
+	0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000,
+	0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000,
+	0x10200000, 0x00202008, 0x00002000, 0x00200008, 0x10002008, 0x00000000,
+	0x10202000, 0x10000000, 0x00200008, 0x10002008
 };
 
-static const guint32 sbox7[64] =
-{
-	0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400,
-	0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401,
-	0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001,
-	0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400,
-	0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001,
-	0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400,
-	0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401,
-	0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001
+static guint32 sbox7[64] = {
+	0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401,
+	0x00100401, 0x02100400, 0x02100401, 0x00100000, 0x00000000, 0x02000001,
+	0x00000001, 0x02000000, 0x02100001, 0x00000401, 0x02000400, 0x00100401,
+	0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001,
+	0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001,
+	0x02000000, 0x00100400, 0x02000000, 0x00100400, 0x00100000, 0x02000401,
+	0x02000401, 0x02100001, 0x02100001, 0x00000001, 0x00100001, 0x02000000,
+	0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400,
+	0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000,
+	0x00000001, 0x02100401, 0x00000000, 0x00100401, 0x02100000, 0x00000400,
+	0x02000001, 0x02000400, 0x00000400, 0x00100001
 };
 
-static const guint32 sbox8[64] =
-{
-	0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000,
-	0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020,
-	0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800,
-	0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000,
-	0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820,
-	0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820,
-	0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000,
-	0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800
+static guint32 sbox8[64] = {
+	0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820,
+	0x00000020, 0x08000000, 0x00020020, 0x08020000, 0x08020820, 0x00020800,
+	0x08020800, 0x00020820, 0x00000800, 0x00000020, 0x08020000, 0x08000020,
+	0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800,
+	0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800,
+	0x00020820, 0x00020000, 0x00020820, 0x00020000, 0x08020800, 0x00000800,
+	0x00000020, 0x08020020, 0x00000800, 0x00020820, 0x08000800, 0x00000020,
+	0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820,
+	0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800,
+	0x08000820, 0x00000000, 0x08020820, 0x00020800, 0x00020800, 0x00000820,
+	0x00000820, 0x00020020, 0x08000000, 0x08020800
 };
 
-
 /*
- *  * These two tables are part of the 'permuted choice 1' function.
- *   * In this implementation several speed improvements are done.
- *    */
-static const guint32 leftkey_swap[16] =
-{
-	0x00000000, 0x00000001, 0x00000100, 0x00000101,
-	0x00010000, 0x00010001, 0x00010100, 0x00010101,
-	0x01000000, 0x01000001, 0x01000100, 0x01000101,
+ * These two tables are part of the 'permuted choice 1' function.
+ * In this implementation several speed improvements are done.
+ */
+static guint32 leftkey_swap[16] = {
+	0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00010000, 0x00010001,
+	0x00010100, 0x00010101, 0x01000000, 0x01000001, 0x01000100, 0x01000101,
 	0x01010000, 0x01010001, 0x01010100, 0x01010101
 };
 
-static const guint32 rightkey_swap[16] =
-{
-	0x00000000, 0x01000000, 0x00010000, 0x01010000,
-	0x00000100, 0x01000100, 0x00010100, 0x01010100,
-	0x00000001, 0x01000001, 0x00010001, 0x01010001,
+static guint32 rightkey_swap[16] = {
+	0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00000100, 0x01000100,
+	0x00010100, 0x01010100, 0x00000001, 0x01000001, 0x00010001, 0x01010001,
 	0x00000101, 0x01000101, 0x00010101, 0x01010101,
 };
 
-
 /*
  *  Numbers of left shifts per round for encryption subkey schedule
  *  To calculate the decryption key scheduling we just reverse the
  *  ordering of the subkeys so we can omit the table for decryption
  *  subkey schedule.
  */
-static const guint8 encrypt_rotate_tab[16] =
-{
+static guint8 encrypt_rotate_tab[16] = {
 	1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
 };
 
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
 /*
- *  Macro to swap bits across two words
- **/
-#define DO_PERMUTATION(a, temp, b, offset, mask)    \
-	temp = ((a>>offset) ^ b) & mask;            \
-	b ^= temp;                      \
+ * Macro to swap bits across two words
+ */
+#define DO_PERMUTATION(a, temp, b, offset, mask)	\
+	temp = ((a>>offset) ^ b) & mask;				\
+	b ^= temp;										\
 	a ^= temp<<offset;
 
-
 /*
- *  This performs the 'initial permutation' for the data to be encrypted or decrypted
- **/
-#define INITIAL_PERMUTATION(left, temp, right)      \
-	DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f)    \
-	DO_PERMUTATION(left, temp, right, 16, 0x0000ffff)   \
-	DO_PERMUTATION(right, temp, left, 2, 0x33333333)    \
-	DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff)    \
+ * This performs the 'initial permutation' for the data to be encrypted or
+ * decrypted
+ */
+#define INITIAL_PERMUTATION(left, temp, right)			\
+	DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f)	\
+	DO_PERMUTATION(left, temp, right, 16, 0x0000ffff)	\
+	DO_PERMUTATION(right, temp, left, 2, 0x33333333)	\
+	DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff)	\
 	DO_PERMUTATION(left, temp, right, 1, 0x55555555)
 
-
 /*
  * The 'inverse initial permutation'
- **/
-#define FINAL_PERMUTATION(left, temp, right)        \
-	DO_PERMUTATION(left, temp, right, 1, 0x55555555)    \
-	DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff)    \
-	DO_PERMUTATION(right, temp, left, 2, 0x33333333)    \
-	DO_PERMUTATION(left, temp, right, 16, 0x0000ffff)   \
+ */
+#define FINAL_PERMUTATION(left, temp, right)			\
+    DO_PERMUTATION(left, temp, right, 1, 0x55555555)	\
+	DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff)	\
+	DO_PERMUTATION(right, temp, left, 2, 0x33333333)	\
+	DO_PERMUTATION(left, temp, right, 16, 0x0000ffff)	\
 	DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f)
 
-
 /*
  * A full DES round including 'expansion function', 'sbox substitution'
  * and 'primitive function P' but without swapping the left and right word.
- **/
-#define DES_ROUND(from, to, work, subkey)       \
-	work = ((from<<1) | (from>>31)) ^ *subkey++;    \
-	to ^= sbox8[  work      & 0x3f ];           \
-	to ^= sbox6[ (work>>8)  & 0x3f ];           \
-	to ^= sbox4[ (work>>16) & 0x3f ];           \
-	to ^= sbox2[ (work>>24) & 0x3f ];           \
-	work = ((from>>3) | (from<<29)) ^ *subkey++;    \
-	to ^= sbox7[  work      & 0x3f ];           \
-	to ^= sbox5[ (work>>8)  & 0x3f ];           \
-	to ^= sbox3[ (work>>16) & 0x3f ];           \
+ */
+#define DES_ROUND(from, to, work, subkey)			\
+	work = ((from<<1) | (from>>31)) ^ *subkey++;	\
+	to ^= sbox8[  work      & 0x3f ];				\
+	to ^= sbox6[ (work>>8)  & 0x3f ];				\
+	to ^= sbox4[ (work>>16) & 0x3f ];				\
+	to ^= sbox2[ (work>>24) & 0x3f ];				\
+	work = ((from>>3) | (from<<29)) ^ *subkey++;	\
+	to ^= sbox7[  work      & 0x3f ];				\
+	to ^= sbox5[ (work>>8)  & 0x3f ];				\
+	to ^= sbox3[ (work>>16) & 0x3f ];				\
 	to ^= sbox1[ (work>>24) & 0x3f ];
 
 
 /*
  * Macros to convert 8 bytes from/to 32bit words
- **/
-#define READ_64BIT_DATA(data, left, right)                  \
-	left  = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];   \
+ */
+#define READ_64BIT_DATA(data, left, right)									\
+	left  = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];	\
 	right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7];
 
-#define WRITE_64BIT_DATA(data, left, right)                 \
-	data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff;         \
-	data[2] = (left >> 8) &0xff; data[3] = left &0xff;              \
-	data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff;       \
+#define WRITE_64BIT_DATA(data, left, right)							\
+	data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff;		\
+	data[2] = (left >> 8) &0xff; data[3] = left &0xff;				\
+	data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff;	\
 	data[6] = (right >> 8) &0xff; data[7] = right &0xff;
 
-
+/******************************************************************************
+ * Cipher Stuff
+ *****************************************************************************/
 /*
  * des_key_schedule():    Calculate 16 subkeys pairs (even/odd) for
  *            16 encryption rounds.
  *            To calculate subkeys for decryption the caller
  *                have to reorder the generated subkeys.
- *
+ *     
  *        rawkey:       8 Bytes of key data
  *        subkey:       Array of at least 32 guint32s. Will be filled
  *              with calculated subkeys.
- *
- **/
+ *     
+ */
 static void
-des_key_schedule (const guint8 * rawkey, guint32 * subkey)
-{
+purple_des_cipher_key_schedule(const guint8 * rawkey, guint32 * subkey) {
 	guint32 left, right, work;
 	int round;
 
@@ -263,113 +286,123 @@
 	DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f)
 	DO_PERMUTATION (right, work, left, 0, 0x10101010)
 
-	left = (leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2)
-	| (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf])
-	| (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6)
-	| (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4);
+	left = (leftkey_swap[(left >>  0) & 0xf] << 3)
+		 | (leftkey_swap[(left >>  8) & 0xf] << 2)
+		 | (leftkey_swap[(left >> 16) & 0xf] << 1)
+		 | (leftkey_swap[(left >> 24) & 0xf]     )
+		 | (leftkey_swap[(left >>  5) & 0xf] << 7)
+		 | (leftkey_swap[(left >> 13) & 0xf] << 6)
+		 | (leftkey_swap[(left >> 21) & 0xf] << 5)
+		 | (leftkey_swap[(left >> 29) & 0xf] << 4);
 
 	left &= 0x0fffffff;
 
-	right = (rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2)
-		| (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf])
-		| (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6)
-		| (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4);
+	right = (rightkey_swap[(right >>  1) & 0xf] << 3)
+		  | (rightkey_swap[(right >>  9) & 0xf] << 2)
+		  | (rightkey_swap[(right >> 17) & 0xf] << 1)
+		  | (rightkey_swap[(right >> 25) & 0xf]     )
+		  | (rightkey_swap[(right >>  4) & 0xf] << 7)
+		  | (rightkey_swap[(right >> 12) & 0xf] << 6)
+		  | (rightkey_swap[(right >> 20) & 0xf] << 5)
+		  | (rightkey_swap[(right >> 28) & 0xf] << 4);
 
 	right &= 0x0fffffff;
 
-	for (round = 0; round < 16; ++round)
-	{
-        left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
-        right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
+	for (round = 0; round < 16; ++round) {
+		left = ((left << encrypt_rotate_tab[round]) |
+			    (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
+		right = ((right << encrypt_rotate_tab[round]) |
+				 (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
 
-		*subkey++ = ((left << 4) & 0x24000000)
-			| ((left << 28) & 0x10000000)
-			| ((left << 14) & 0x08000000)
-			| ((left << 18) & 0x02080000)
-			| ((left << 6) & 0x01000000)
-			| ((left << 9) & 0x00200000)
-			| ((left >> 1) & 0x00100000)
-			| ((left << 10) & 0x00040000)
-			| ((left << 2) & 0x00020000)
-			| ((left >> 10) & 0x00010000)
-			| ((right >> 13) & 0x00002000)
-			| ((right >> 4) & 0x00001000)
-			| ((right << 6) & 0x00000800)
-			| ((right >> 1) & 0x00000400)
-			| ((right >> 14) & 0x00000200)
-			| (right & 0x00000100)
-			| ((right >> 5) & 0x00000020)
-			| ((right >> 10) & 0x00000010)
-			| ((right >> 3) & 0x00000008)
-			| ((right >> 18) & 0x00000004)
-			| ((right >> 26) & 0x00000002)
-			| ((right >> 24) & 0x00000001);
+		*subkey++ = ((left  <<  4) & 0x24000000)
+				  | ((left  << 28) & 0x10000000)
+				  | ((left  << 14) & 0x08000000)
+				  | ((left  << 18) & 0x02080000)
+				  | ((left  <<  6) & 0x01000000)
+				  | ((left  <<  9) & 0x00200000)
+				  | ((left  >>  1) & 0x00100000)
+				  | ((left  << 10) & 0x00040000)
+				  | ((left  <<  2) & 0x00020000)
+				  | ((left  >> 10) & 0x00010000)
+				  | ((right >> 13) & 0x00002000)
+				  | ((right >>  4) & 0x00001000)
+				  | ((right <<  6) & 0x00000800)
+				  | ((right >>  1) & 0x00000400)
+				  | ((right >> 14) & 0x00000200)
+				  | (right         & 0x00000100)
+				  | ((right >>  5) & 0x00000020)
+				  | ((right >> 10) & 0x00000010)
+				  | ((right >>  3) & 0x00000008)
+				  | ((right >> 18) & 0x00000004)
+				  | ((right >> 26) & 0x00000002)
+				  | ((right >> 24) & 0x00000001);
 
-		*subkey++ = ((left << 15) & 0x20000000)
-			| ((left << 17) & 0x10000000)
-			| ((left << 10) & 0x08000000)
-			| ((left << 22) & 0x04000000)
-			| ((left >> 2) & 0x02000000)
-			| ((left << 1) & 0x01000000)
-			| ((left << 16) & 0x00200000)
-			| ((left << 11) & 0x00100000)
-			| ((left << 3) & 0x00080000)
-			| ((left >> 6) & 0x00040000)
-			| ((left << 15) & 0x00020000)
-			| ((left >> 4) & 0x00010000)
-			| ((right >> 2) & 0x00002000)
-			| ((right << 8) & 0x00001000)
-			| ((right >> 14) & 0x00000808)
-			| ((right >> 9) & 0x00000400)
-			| ((right) & 0x00000200)
-			| ((right << 7) & 0x00000100)
-			| ((right >> 7) & 0x00000020)
-			| ((right >> 3) & 0x00000011)
-			| ((right << 2) & 0x00000004)
-			| ((right >> 21) & 0x00000002);
+		*subkey++ = ((left  << 15) & 0x20000000)
+				  | ((left  << 17) & 0x10000000)
+				  | ((left  << 10) & 0x08000000)
+				  | ((left  << 22) & 0x04000000)
+				  | ((left  >>  2) & 0x02000000)
+				  | ((left  <<  1) & 0x01000000)
+				  | ((left  << 16) & 0x00200000)
+				  | ((left  << 11) & 0x00100000)
+				  | ((left  <<  3) & 0x00080000)
+				  | ((left  >>  6) & 0x00040000)
+				  | ((left  << 15) & 0x00020000)
+				  | ((left  >>  4) & 0x00010000)
+				  | ((right >>  2) & 0x00002000)
+				  | ((right <<  8) & 0x00001000)
+				  | ((right >> 14) & 0x00000808)
+				  | ((right >>  9) & 0x00000400)
+				  | ((right)       & 0x00000200)
+				  | ((right <<  7) & 0x00000100)
+				  | ((right >>  7) & 0x00000020)
+				  | ((right >>  3) & 0x00000011)
+				  | ((right <<  2) & 0x00000004)
+				  | ((right >> 21) & 0x00000002);
 	}
 }
 
-
 /*
- *  Fill a DES context with subkeys calculated from a 64bit key.
- *  Does not check parity bits, but simply ignore them.
- *  Does not check for weak keys.
- **/
+ * Fill a DES context with subkeys calculated from a 64bit key.
+ * Does not check parity bits, but simply ignore them.
+ * Does not check for weak keys.
+ */
 static void
-des_set_key (PurpleCipherContext *context, const guchar * key, size_t len)
-{
-	struct _des_ctx *ctx = purple_cipher_context_get_data(context);
+purple_des_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) {
+	PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher);
+	PurpleDESCipherPrivate *priv = PURPLE_DES_CIPHER_GET_PRIVATE(des_cipher);
 	int i;
 
-	g_return_if_fail(len != 8);
+	g_return_if_fail(len == 8);
 
-	des_key_schedule (key, ctx->encrypt_subkeys);
+	purple_des_cipher_key_schedule(key, priv->encrypt_subkeys);
 
-	for(i=0; i<32; i+=2)
-	{
-		ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i];
-		ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i];
+	for(i = 0; i < 32; i += 2) {
+		priv->decrypt_subkeys[i] = priv->encrypt_subkeys[30 - i];
+		priv->decrypt_subkeys[i + 1] = priv->encrypt_subkeys[31 - i];
 	}
 }
 
 static size_t
-des_get_key_size(PurpleCipherContext *context)
+purple_des_cipher_get_key_size(PurpleCipher *cipher)
 {
 	return 8;
 }
 
 /*
- *  Electronic Codebook Mode DES encryption/decryption of data according
- *  to 'mode'.
- **/
-static int
-des_ecb_crypt (struct _des_ctx *ctx, const guint8 * from, guint8 * to, int mode)
+ * Electronic Codebook Mode DES encryption/decryption of data according to
+ * 'mode'.
+ */
+int
+purple_des_cipher_ecb_crypt(PurpleDESCipher *des_cipher, const guint8 * from, guint8 * to,
+			  int mode)
 {
 	guint32 left, right, work;
 	guint32 *keys;
+	PurpleDESCipherPrivate *priv = PURPLE_DES_CIPHER_GET_PRIVATE(des_cipher);
 
-	keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys;
+	keys = mode ? priv->decrypt_subkeys :
+				  priv->encrypt_subkeys;
 
 	READ_64BIT_DATA (from, left, right)
 	INITIAL_PERMUTATION (left, work, right)
@@ -390,60 +423,53 @@
 }
 
 static ssize_t
-des_encrypt(PurpleCipherContext *context, const guchar input[], size_t in_len,
-	guchar output[], size_t out_size)
+purple_des_cipher_encrypt(PurpleCipher *cipher, const guchar input[],
+							size_t in_len, guchar output[], size_t out_size)
 {
-	int offset = 0;
-	int i = 0;
-	int tmp;
-	guint8 buf[8] = {0,0,0,0,0,0,0,0};
+	PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher);
+	gint offset = 0, i = 0, tmp;
+	guint8 buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 	ssize_t out_len;
 
 	g_return_val_if_fail(out_size < in_len, -1);
 
-	while(offset+8<=in_len) {
-		des_ecb_crypt(purple_cipher_context_get_data(context),
-		              input+offset,
-		              output+offset,
-		              0);
-		offset+=8;
+	while(offset + 8 <= in_len) {
+		purple_des_cipher_ecb_crypt(des_cipher, input + offset, output + offset, 0);
+		offset += 8;
 	}
+
 	out_len = in_len;
+
 	if(offset<in_len) {
 		out_len += in_len - offset;
-		g_return_val_if_fail(out_size < out_len, -1);
 		tmp = offset;
 		while(tmp<in_len) {
 			buf[i++] = input[tmp];
 			tmp++;
 		}
-		des_ecb_crypt(purple_cipher_context_get_data(context),
-		              buf,
-		              output+offset,
-		              0);
+
+		purple_des_cipher_ecb_crypt(des_cipher, buf, output + offset, 0);
 	}
+
 	return out_len;
 }
 
 static ssize_t
-des_decrypt(PurpleCipherContext *context, const guchar input[], size_t in_len,
-	guchar output[], size_t out_size)
+purple_des_cipher_decrypt(PurpleCipher *cipher, const guchar input[],
+							size_t in_len, guchar output[], size_t out_size)
 {
-	int offset = 0;
-	int i = 0;
-	int tmp;
+	PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher);
+	int offset = 0, i = 0, tmp;
 	guint8 buf[8] = {0,0,0,0,0,0,0,0};
 	ssize_t out_len;
 
 	g_return_val_if_fail(out_size < in_len, -1);
 
-	while(offset+8<=in_len) {
-		des_ecb_crypt(purple_cipher_context_get_data(context),
-		              input+offset,
-		              output+offset,
-		              1);
-		offset+=8;
+	while(offset + 8 <= in_len) {
+		purple_des_cipher_ecb_crypt(des_cipher, input + offset, output + offset, 1);
+		offset += 8;
 	}
+
 	out_len = in_len;
 	if(offset<in_len) {
 		out_len += in_len - offset;
@@ -453,445 +479,100 @@
 			buf[i++] = input[tmp];
 			tmp++;
 		}
-		des_ecb_crypt(purple_cipher_context_get_data(context),
-		              buf,
-		              output+offset,
-		              1);
-	}
-	return out_len;
-}
-
-static void
-des_init(PurpleCipherContext *context, gpointer extra) {
-	struct _des_ctx *mctx;
-	mctx = g_new0(struct _des_ctx, 1);
-	purple_cipher_context_set_data(context, mctx);
-}
-
-static void
-des_uninit(PurpleCipherContext *context) {
-	struct _des_ctx *des_context;
-
-	des_context = purple_cipher_context_get_data(context);
-	memset(des_context, 0, sizeof(*des_context));
-
-	g_free(des_context);
-	des_context = NULL;
-}
-
-static PurpleCipherOps DESOps = {
-	NULL,              /* Set option */
-	NULL,              /* Get option */
-	des_init,          /* init */
- 	NULL,              /* reset */
- 	NULL,              /* reset state */
-	des_uninit,        /* uninit */
-	NULL,              /* set iv */
-	NULL,              /* append */
-	NULL,              /* digest */
-	NULL,              /* get_digest_size */
-	des_encrypt,       /* encrypt */
-	des_decrypt,       /* decrypt */
-	NULL,              /* set salt */
-	NULL,              /* get salt size */
-	des_set_key,       /* set key */
-	des_get_key_size,  /* get key size */
-	NULL,              /* set batch mode */
-	NULL,              /* get batch mode */
-	NULL,              /* get block size */
-	NULL, NULL, NULL, NULL /* reserved */
-};
-
-/******************************************************************************
- * Triple-DES
- *****************************************************************************/
-
-typedef struct _des3_ctx
-{
-	PurpleCipherBatchMode mode;
-	guchar iv[8];
-	/* First key for encryption */
-	struct _des_ctx key1;
-	/* Second key for decryption */
-	struct _des_ctx key2;
-	/* Third key for encryption */
-	struct _des_ctx key3;
-} des3_ctx[1];
-
-/*
- *  Fill a DES3 context with subkeys calculated from 3 64bit key.
- *  Does not check parity bits, but simply ignore them.
- *  Does not check for weak keys.
- **/
-static void
-des3_set_key(PurpleCipherContext *context, const guchar * key, size_t len)
-{
-	struct _des3_ctx *ctx = purple_cipher_context_get_data(context);
-	int i;
-
-	g_return_if_fail(len != 24);
-
-	des_key_schedule (key +  0, ctx->key1.encrypt_subkeys);
-	des_key_schedule (key +  8, ctx->key2.encrypt_subkeys);
-	des_key_schedule (key + 16, ctx->key3.encrypt_subkeys);
-
-	for (i = 0; i < 32; i += 2)
-	{
-		ctx->key1.decrypt_subkeys[i]    = ctx->key1.encrypt_subkeys[30-i];
-		ctx->key1.decrypt_subkeys[i+1]  = ctx->key1.encrypt_subkeys[31-i];
-		ctx->key2.decrypt_subkeys[i]    = ctx->key2.encrypt_subkeys[30-i];
-		ctx->key2.decrypt_subkeys[i+1]  = ctx->key2.encrypt_subkeys[31-i];
-		ctx->key3.decrypt_subkeys[i]    = ctx->key3.encrypt_subkeys[30-i];
-		ctx->key3.decrypt_subkeys[i+1]  = ctx->key3.encrypt_subkeys[31-i];
-	}
-}
-
-static size_t
-des3_get_key_size(PurpleCipherContext *context)
-{
-	return 24;
-}
 
-static ssize_t
-des3_ecb_encrypt(struct _des3_ctx *ctx, const guchar input[], size_t in_len,
-	guchar output[], size_t out_size)
-{
-	int offset = 0;
-	int i = 0;
-	int tmp;
-	guint8 buf[8] = {0,0,0,0,0,0,0,0};
-	ssize_t out_len;
-
-	g_return_val_if_fail(out_size < in_len, -1);
-
-	while (offset + 8 <= in_len) {
-		des_ecb_crypt(&ctx->key1,
-		              input+offset,
-		              output+offset,
-		              0);
-		des_ecb_crypt(&ctx->key2,
-		              output+offset,
-		              buf,
-		              1);
-		des_ecb_crypt(&ctx->key3,
-		              buf,
-		              output+offset,
-		              0);
-		offset += 8;
+		purple_des_cipher_ecb_crypt(des_cipher, buf, output + offset, 1);
 	}
-	out_len = in_len;
-	if (offset < in_len) {
-		out_len += in_len - offset;
-		g_return_val_if_fail(out_size < out_len, -1);
-		tmp = offset;
-		memset(buf, 0, 8);
-		while (tmp < in_len) {
-			buf[i++] = input[tmp];
-			tmp++;
-		}
-		des_ecb_crypt(&ctx->key1,
-		              buf,
-		              output+offset,
-		              0);
-		des_ecb_crypt(&ctx->key2,
-		              output+offset,
-		              buf,
-		              1);
-		des_ecb_crypt(&ctx->key3,
-		              buf,
-		              output+offset,
-		              0);
-	}
-	return out_len;
-}
 
-static ssize_t
-des3_cbc_encrypt(struct _des3_ctx *ctx, const guchar input[], size_t in_len,
-	guchar output[], size_t out_size)
-{
-	int offset = 0;
-	int i = 0;
-	int tmp;
-	guint8 buf[8];
-	ssize_t out_len;
-	memcpy(buf, ctx->iv, 8);
-
-	g_return_val_if_fail(out_size < in_len, -1);
-
-	while (offset + 8 <= in_len) {
-		for (i = 0; i < 8; i++)
-			buf[i] ^= input[offset + i];
-
-		des_ecb_crypt(&ctx->key1,
-		              buf,
-		              output+offset,
-		              0);
-		des_ecb_crypt(&ctx->key2,
-		              output+offset,
-		              buf,
-		              1);
-		des_ecb_crypt(&ctx->key3,
-		              buf,
-		              output+offset,
-		              0);
-		memcpy(buf, output+offset, 8);
-		offset += 8;
-	}
-	out_len = in_len;
-	if (offset < in_len) {
-		out_len += in_len - offset;
-		g_return_val_if_fail(out_size < out_len, -1);
-		tmp = offset;
-		i = 0;
-		while (tmp < in_len) {
-			buf[i++] ^= input[tmp];
-			tmp++;
-		}
-		des_ecb_crypt(&ctx->key1,
-		              buf,
-		              output+offset,
-		              0);
-		des_ecb_crypt(&ctx->key2,
-		              output+offset,
-		              buf,
-		              1);
-		des_ecb_crypt(&ctx->key3,
-		              buf,
-		              output+offset,
-		              0);
-	}
 	return out_len;
 }
 
-static ssize_t
-des3_encrypt(PurpleCipherContext *context, const guchar input[], size_t in_len,
-	guchar output[], size_t out_size)
+/******************************************************************************
+ * Object Stuff
+ *****************************************************************************/
+static void
+purple_des_cipher_set_property(GObject *obj, guint param_id,
+							   const GValue *value, GParamSpec *pspec)
 {
-	struct _des3_ctx *ctx = purple_cipher_context_get_data(context);
-
-	if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) {
-		return des3_ecb_encrypt(ctx, input, in_len, output, out_size);
-	} else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) {
-		return des3_cbc_encrypt(ctx, input, in_len, output, out_size);
-	} else {
-		g_return_val_if_reached(0);
-	}
-
-	return 0;
-}
-
-static ssize_t
-des3_ecb_decrypt(struct _des3_ctx *ctx, const guchar input[], size_t in_len,
-	guchar output[], size_t out_size)
-{
-	int offset = 0;
-	int i = 0;
-	int tmp;
-	guint8 buf[8] = {0,0,0,0,0,0,0,0};
-	ssize_t out_len;
-
-	g_return_val_if_fail(out_size < in_len, -1);
+	PurpleCipher *cipher = PURPLE_CIPHER(obj);
 
-	while (offset + 8 <= in_len) {
-		/* NOTE: Apply key in reverse */
-		des_ecb_crypt(&ctx->key3,
-		              input+offset,
-		              output+offset,
-		              1);
-		des_ecb_crypt(&ctx->key2,
-		              output+offset,
-		              buf,
-		              0);
-		des_ecb_crypt(&ctx->key1,
-		              buf,
-		              output+offset,
-		              1);
-		offset+=8;
+	switch(param_id) {
+		case PROP_KEY:
+			purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value),
+										purple_des_cipher_get_key_size(cipher));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
 	}
-	out_len = in_len;
-	if (offset < in_len) {
-		out_len += in_len - offset;
-		g_return_val_if_fail(out_size < out_len, -1);
-		tmp = offset;
-		memset(buf, 0, 8);
-		while (tmp < in_len) {
-			buf[i++] = input[tmp];
-			tmp++;
-		}
-		des_ecb_crypt(&ctx->key3,
-		              buf,
-		              output+offset,
-		              1);
-		des_ecb_crypt(&ctx->key2,
-		              output+offset,
-		              buf,
-		              0);
-		des_ecb_crypt(&ctx->key1,
-		              buf,
-		              output+offset,
-		              1);
-	}
-	return out_len;
 }
 
-static ssize_t
-des3_cbc_decrypt(struct _des3_ctx *ctx, const guchar input[], size_t in_len,
-	guchar output[], size_t out_size)
+static void
+purple_des_cipher_finalize(GObject *obj)
 {
-	int offset = 0;
-	int i = 0;
-	int tmp;
-	guint8 buf[8] = {0,0,0,0,0,0,0,0};
-	guint8 link[8];
-	ssize_t out_len;
-
-	g_return_val_if_fail(out_size < in_len, -1);
-
-	memcpy(link, ctx->iv, 8);
-	while (offset + 8 <= in_len) {
-		des_ecb_crypt(&ctx->key3,
-		              input+offset,
-		              output+offset,
-		              1);
-		des_ecb_crypt(&ctx->key2,
-		              output+offset,
-		              buf,
-		              0);
-		des_ecb_crypt(&ctx->key1,
-		              buf,
-		              output+offset,
-		              1);
-		for (i = 0; i < 8; i++)
-			output[offset + i] ^= link[i];
-		memcpy(link, input + offset, 8);
-		offset+=8;
-	}
-	out_len = in_len;
-	if(offset<in_len) {
-		out_len += in_len - offset;
-		g_return_val_if_fail(out_size < out_len, -1);
-		tmp = offset;
-		memset(buf, 0, 8);
-		i = 0;
-		while(tmp<in_len) {
-			buf[i++] = input[tmp];
-			tmp++;
-		}
-		des_ecb_crypt(&ctx->key3,
-		              buf,
-		              output+offset,
-		              1);
-		des_ecb_crypt(&ctx->key2,
-		              output+offset,
-		              buf,
-		              0);
-		des_ecb_crypt(&ctx->key1,
-		              buf,
-		              output+offset,
-		              1);
-		for (i = 0; i < 8; i++)
-			output[offset + i] ^= link[i];
-	}
-	return out_len;
-}
-
-static ssize_t
-des3_decrypt(PurpleCipherContext *context, const guchar input[], size_t in_len,
-	guchar output[], size_t out_size)
-{
-	struct _des3_ctx *ctx = purple_cipher_context_get_data(context);
-
-	if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) {
-		return des3_ecb_decrypt(ctx, input, in_len, output, out_size);
-	} else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) {
-		return des3_cbc_decrypt(ctx, input, in_len, output, out_size);
-	} else {
-		g_return_val_if_reached(0);
-	}
-
-	return 0;
+	parent_class->finalize(obj);
 }
 
 static void
-des3_set_batch(PurpleCipherContext *context, PurpleCipherBatchMode mode)
+purple_des_cipher_class_init(PurpleDESCipherClass *klass)
 {
-	struct _des3_ctx *ctx = purple_cipher_context_get_data(context);
-
-	ctx->mode = mode;
-}
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass);
+	GParamSpec *pspec;
 
-static PurpleCipherBatchMode
-des3_get_batch(PurpleCipherContext *context)
-{
-	struct _des3_ctx *ctx = purple_cipher_context_get_data(context);
+	parent_class = g_type_class_peek_parent(klass);
 
-	return ctx->mode;
-}
+	obj_class->finalize = purple_des_cipher_finalize;
+	obj_class->set_property = purple_des_cipher_set_property;
 
-static void
-des3_set_iv(PurpleCipherContext *context, guchar *iv, size_t len)
-{
-	struct _des3_ctx *ctx;
-
-	g_return_if_fail(len == 8);
-
-	ctx = purple_cipher_context_get_data(context);
+	cipher_class->encrypt = purple_des_cipher_encrypt;
+	cipher_class->decrypt = purple_des_cipher_decrypt;
+	cipher_class->set_key = purple_des_cipher_set_key;
+	cipher_class->get_key_size = purple_des_cipher_get_key_size;
 
-	memcpy(ctx->iv, iv, len);
-}
+	pspec = g_param_spec_string("key", "key", "key", NULL,
+								G_PARAM_WRITABLE);
+	g_object_class_install_property(obj_class, PROP_KEY, pspec);
 
-static void
-des3_init(PurpleCipherContext *context, gpointer extra)
-{
-	struct _des3_ctx *mctx;
-	mctx = g_new0(struct _des3_ctx, 1);
-	purple_cipher_context_set_data(context, mctx);
+	g_type_class_add_private(klass, sizeof(PurpleDESCipherPrivate));
 }
 
 static void
-des3_uninit(PurpleCipherContext *context)
+purple_des_cipher_init(PurpleCipher *cipher)
 {
-	struct _des3_ctx *des3_context;
-
-	des3_context = purple_cipher_context_get_data(context);
-	memset(des3_context, 0, sizeof(*des3_context));
-
-	g_free(des3_context);
-	des3_context = NULL;
 }
 
-static PurpleCipherOps DES3Ops = {
-	NULL,              /* Set option */
-	NULL,              /* Get option */
-	des3_init,         /* init */
-	NULL,              /* reset */
-	NULL,              /* reset state */
-	des3_uninit,       /* uninit */
-	des3_set_iv,       /* set iv */
-	NULL,              /* append */
-	NULL,              /* digest */
-	NULL,              /* get_digest_size */
-	des3_encrypt,      /* encrypt */
-	des3_decrypt,      /* decrypt */
-	NULL,              /* set salt */
-	NULL,              /* get salt size */
-	des3_set_key,      /* set key */
-	des3_get_key_size, /* get_key_size */
-	des3_set_batch,    /* set batch mode */
-	des3_get_batch,    /* get batch mode */
-	NULL,              /* get block size */
-	NULL, NULL, NULL, NULL /* reserved */
-};
+/******************************************************************************
+ * API
+ *****************************************************************************/
+GType
+purple_des_cipher_get_type(void) {
+	static GType type = 0;
 
-/******************************************************************************
- * Registration
- *****************************************************************************/
-PurpleCipherOps *
-purple_des_cipher_get_ops(void) {
-	return &DESOps;
+	if(type == 0) {
+		static const GTypeInfo info = {
+			.class_size = sizeof(PurpleDESCipherClass),
+			.class_init = (GClassInitFunc)purple_des_cipher_class_init,
+			.instance_size = sizeof(PurpleDESCipher),
+			.instance_init = (GInstanceInitFunc)purple_des_cipher_init,
+		};
+
+		type = g_type_register_static(PURPLE_TYPE_CIPHER,
+									  "PurpleDESCipher",
+									  &info, 0);
+	}
+
+	return type;
 }
 
-PurpleCipherOps *
-purple_des3_cipher_get_ops(void) {
-	return &DES3Ops;
+/**
+ * purple_des_cipher_new:
+ *
+ * Creates a new #PurpleCipher instance which implements the DES block cipher.
+ *
+ * Return Value: The new DES implementation of #PurpleCipher.
+ */
+PurpleCipher *
+purple_des_cipher_new(void) {
+	return g_object_new(PURPLE_TYPE_DES_CIPHER, NULL);
 }
+

mercurial