| 1 /* |
|
| 2 * Original des taken from gpg |
|
| 3 * |
|
| 4 * des.c - DES encryption/decryption Algorithm |
|
| 5 * Copyright (C) 1998 Free Software Foundation, Inc. |
|
| 6 * |
|
| 7 * Please see below for more legal information! |
|
| 8 * |
|
| 9 * According to the definition of DES in FIPS PUB 46-2 from December 1993. |
|
| 10 * For a description of triple encryption, see: |
|
| 11 * Bruce Schneier: Applied Cryptography. Second Edition. |
|
| 12 * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. |
|
| 13 * |
|
| 14 * Purple is the legal property of its developers, whose names are too numerous |
|
| 15 * to list here. Please refer to the COPYRIGHT file distributed with this |
|
| 16 * source distribution. |
|
| 17 * |
|
| 18 * This program is free software; you can redistribute it and/or modify |
|
| 19 * it under the terms of the GNU General Public License as published by |
|
| 20 * the Free Software Foundation; either version 2 of the License, or |
|
| 21 * (at your option) any later version. |
|
| 22 * |
|
| 23 * This program is distributed in the hope that it will be useful, |
|
| 24 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 26 * GNU General Public License for more details. |
|
| 27 * |
|
| 28 * You should have received a copy of the GNU General Public License |
|
| 29 * along with this program; if not, write to the Free Software |
|
| 30 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
|
| 31 */ |
|
| 32 #include "internal.h" |
|
| 33 #include "glibcompat.h" |
|
| 34 |
|
| 35 #include "descipher.h" |
|
| 36 #include "enums.h" |
|
| 37 |
|
| 38 #include <string.h> |
|
| 39 |
|
| 40 /****************************************************************************** |
|
| 41 * Structs |
|
| 42 *****************************************************************************/ |
|
| 43 #define PURPLE_DES_CIPHER_GET_PRIVATE(obj) \ |
|
| 44 (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_DES_CIPHER, PurpleDESCipherPrivate)) |
|
| 45 |
|
| 46 typedef struct { |
|
| 47 guint32 encrypt_subkeys[32]; |
|
| 48 guint32 decrypt_subkeys[32]; |
|
| 49 } PurpleDESCipherPrivate; |
|
| 50 |
|
| 51 /****************************************************************************** |
|
| 52 * Enums |
|
| 53 *****************************************************************************/ |
|
| 54 enum { |
|
| 55 PROP_NONE, |
|
| 56 PROP_KEY, |
|
| 57 PROP_LAST, |
|
| 58 }; |
|
| 59 |
|
| 60 /****************************************************************************** |
|
| 61 * Globals |
|
| 62 *****************************************************************************/ |
|
| 63 static GObjectClass *parent_class = NULL; |
|
| 64 static GParamSpec *properties[PROP_LAST]; |
|
| 65 |
|
| 66 /* |
|
| 67 * The s-box values are permuted according to the 'primitive function P' |
|
| 68 */ |
|
| 69 static guint32 sbox1[64] = { |
|
| 70 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, |
|
| 71 0x00000002, 0x00008000, 0x00000200, 0x00808200, 0x00808202, 0x00000200, |
|
| 72 0x00800202, 0x00808002, 0x00800000, 0x00000002, 0x00000202, 0x00800200, |
|
| 73 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, |
|
| 74 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, |
|
| 75 0x00008202, 0x00800000, 0x00008000, 0x00808202, 0x00000002, 0x00808000, |
|
| 76 0x00808200, 0x00800000, 0x00800000, 0x00000200, 0x00808002, 0x00008000, |
|
| 77 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, |
|
| 78 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, |
|
| 79 0x00008202, 0x00808200, 0x00000202, 0x00800200, 0x00800200, 0x00000000, |
|
| 80 0x00008002, 0x00008200, 0x00000000, 0x00808002 |
|
| 81 }; |
|
| 82 |
|
| 83 static guint32 sbox2[64] = { |
|
| 84 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, |
|
| 85 0x40080010, 0x40004010, 0x40000010, 0x40084010, 0x40084000, 0x40000000, |
|
| 86 0x40004000, 0x00080000, 0x00000010, 0x40080010, 0x00084000, 0x00080010, |
|
| 87 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, |
|
| 88 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, |
|
| 89 0x40080000, 0x00004010, 0x00000000, 0x00084010, 0x40080010, 0x00080000, |
|
| 90 0x40004010, 0x40080000, 0x40084000, 0x00004000, 0x40080000, 0x40004000, |
|
| 91 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, |
|
| 92 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, |
|
| 93 0x40000010, 0x00080010, 0x00084000, 0x00000000, 0x40004000, 0x00004010, |
|
| 94 0x40000000, 0x40080010, 0x40084010, 0x00084000 |
|
| 95 }; |
|
| 96 |
|
| 97 static guint32 sbox3[64] = { |
|
| 98 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, |
|
| 99 0x00010104, 0x04000100, 0x00010004, 0x04000004, 0x04000004, 0x00010000, |
|
| 100 0x04010104, 0x00010004, 0x04010000, 0x00000104, 0x04000000, 0x00000004, |
|
| 101 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, |
|
| 102 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, |
|
| 103 0x00000100, 0x04000000, 0x04010100, 0x04000000, 0x00010004, 0x00000104, |
|
| 104 0x00010000, 0x04010100, 0x04000100, 0x00000000, 0x00000100, 0x00010004, |
|
| 105 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, |
|
| 106 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, |
|
| 107 0x00010100, 0x04000004, 0x04010000, 0x04000104, 0x00000104, 0x04010000, |
|
| 108 0x00010104, 0x00000004, 0x04010004, 0x00010100 |
|
| 109 }; |
|
| 110 |
|
| 111 static guint32 sbox4[64] = { |
|
| 112 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, |
|
| 113 0x80400000, 0x80001000, 0x00000000, 0x00401000, 0x00401000, 0x80401040, |
|
| 114 0x80000040, 0x00000000, 0x00400040, 0x80400000, 0x80000000, 0x00001000, |
|
| 115 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, |
|
| 116 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, |
|
| 117 0x80401040, 0x80000040, 0x00400040, 0x80400000, 0x00401000, 0x80401040, |
|
| 118 0x80000040, 0x00000000, 0x00000000, 0x00401000, 0x00001040, 0x00400040, |
|
| 119 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, |
|
| 120 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, |
|
| 121 0x00401040, 0x80400040, 0x80001000, 0x00001040, 0x00400000, 0x80401000, |
|
| 122 0x00000040, 0x00400000, 0x00001000, 0x00401040 |
|
| 123 }; |
|
| 124 |
|
| 125 static guint32 sbox5[64] = { |
|
| 126 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, |
|
| 127 0x20000000, 0x01040000, 0x20040080, 0x00040000, 0x01000080, 0x20040080, |
|
| 128 0x21000080, 0x21040000, 0x00040080, 0x20000000, 0x01000000, 0x20040000, |
|
| 129 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, |
|
| 130 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, |
|
| 131 0x21000000, 0x00040080, 0x00040000, 0x21000080, 0x00000080, 0x01000000, |
|
| 132 0x20000000, 0x01040000, 0x21000080, 0x20040080, 0x01000080, 0x20000000, |
|
| 133 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, |
|
| 134 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, |
|
| 135 0x20040000, 0x21000000, 0x00040080, 0x01000080, 0x20000080, 0x00040000, |
|
| 136 0x00000000, 0x20040000, 0x01040080, 0x20000080 |
|
| 137 }; |
|
| 138 |
|
| 139 static guint32 sbox6[64] = { |
|
| 140 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, |
|
| 141 0x10202008, 0x00200000, 0x10002000, 0x00202008, 0x00200000, 0x10000008, |
|
| 142 0x00200008, 0x10002000, 0x10000000, 0x00002008, 0x00000000, 0x00200008, |
|
| 143 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, |
|
| 144 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, |
|
| 145 0x10202000, 0x10000000, 0x10002000, 0x00000008, 0x10200008, 0x00202000, |
|
| 146 0x10202008, 0x00200000, 0x00002008, 0x10000008, 0x00200000, 0x10002000, |
|
| 147 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, |
|
| 148 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, |
|
| 149 0x10200000, 0x00202008, 0x00002000, 0x00200008, 0x10002008, 0x00000000, |
|
| 150 0x10202000, 0x10000000, 0x00200008, 0x10002008 |
|
| 151 }; |
|
| 152 |
|
| 153 static guint32 sbox7[64] = { |
|
| 154 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, |
|
| 155 0x00100401, 0x02100400, 0x02100401, 0x00100000, 0x00000000, 0x02000001, |
|
| 156 0x00000001, 0x02000000, 0x02100001, 0x00000401, 0x02000400, 0x00100401, |
|
| 157 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, |
|
| 158 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, |
|
| 159 0x02000000, 0x00100400, 0x02000000, 0x00100400, 0x00100000, 0x02000401, |
|
| 160 0x02000401, 0x02100001, 0x02100001, 0x00000001, 0x00100001, 0x02000000, |
|
| 161 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, |
|
| 162 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, |
|
| 163 0x00000001, 0x02100401, 0x00000000, 0x00100401, 0x02100000, 0x00000400, |
|
| 164 0x02000001, 0x02000400, 0x00000400, 0x00100001 |
|
| 165 }; |
|
| 166 |
|
| 167 static guint32 sbox8[64] = { |
|
| 168 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, |
|
| 169 0x00000020, 0x08000000, 0x00020020, 0x08020000, 0x08020820, 0x00020800, |
|
| 170 0x08020800, 0x00020820, 0x00000800, 0x00000020, 0x08020000, 0x08000020, |
|
| 171 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, |
|
| 172 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, |
|
| 173 0x00020820, 0x00020000, 0x00020820, 0x00020000, 0x08020800, 0x00000800, |
|
| 174 0x00000020, 0x08020020, 0x00000800, 0x00020820, 0x08000800, 0x00000020, |
|
| 175 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, |
|
| 176 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, |
|
| 177 0x08000820, 0x00000000, 0x08020820, 0x00020800, 0x00020800, 0x00000820, |
|
| 178 0x00000820, 0x00020020, 0x08000000, 0x08020800 |
|
| 179 }; |
|
| 180 |
|
| 181 /* |
|
| 182 * These two tables are part of the 'permuted choice 1' function. |
|
| 183 * In this implementation several speed improvements are done. |
|
| 184 */ |
|
| 185 static guint32 leftkey_swap[16] = { |
|
| 186 0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00010000, 0x00010001, |
|
| 187 0x00010100, 0x00010101, 0x01000000, 0x01000001, 0x01000100, 0x01000101, |
|
| 188 0x01010000, 0x01010001, 0x01010100, 0x01010101 |
|
| 189 }; |
|
| 190 |
|
| 191 static guint32 rightkey_swap[16] = { |
|
| 192 0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00000100, 0x01000100, |
|
| 193 0x00010100, 0x01010100, 0x00000001, 0x01000001, 0x00010001, 0x01010001, |
|
| 194 0x00000101, 0x01000101, 0x00010101, 0x01010101, |
|
| 195 }; |
|
| 196 |
|
| 197 /* |
|
| 198 * Numbers of left shifts per round for encryption subkey schedule |
|
| 199 * To calculate the decryption key scheduling we just reverse the |
|
| 200 * ordering of the subkeys so we can omit the table for decryption |
|
| 201 * subkey schedule. |
|
| 202 */ |
|
| 203 static guint8 encrypt_rotate_tab[16] = { |
|
| 204 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 |
|
| 205 }; |
|
| 206 |
|
| 207 |
|
| 208 /****************************************************************************** |
|
| 209 * Helpers |
|
| 210 *****************************************************************************/ |
|
| 211 /* |
|
| 212 * Macro to swap bits across two words |
|
| 213 */ |
|
| 214 #define DO_PERMUTATION(a, temp, b, offset, mask) \ |
|
| 215 temp = ((a>>offset) ^ b) & mask; \ |
|
| 216 b ^= temp; \ |
|
| 217 a ^= temp<<offset; |
|
| 218 |
|
| 219 /* |
|
| 220 * This performs the 'initial permutation' for the data to be encrypted or |
|
| 221 * decrypted |
|
| 222 */ |
|
| 223 #define INITIAL_PERMUTATION(left, temp, right) \ |
|
| 224 DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \ |
|
| 225 DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ |
|
| 226 DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ |
|
| 227 DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ |
|
| 228 DO_PERMUTATION(left, temp, right, 1, 0x55555555) |
|
| 229 |
|
| 230 /* |
|
| 231 * The 'inverse initial permutation' |
|
| 232 */ |
|
| 233 #define FINAL_PERMUTATION(left, temp, right) \ |
|
| 234 DO_PERMUTATION(left, temp, right, 1, 0x55555555) \ |
|
| 235 DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ |
|
| 236 DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ |
|
| 237 DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ |
|
| 238 DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) |
|
| 239 |
|
| 240 /* |
|
| 241 * A full DES round including 'expansion function', 'sbox substitution' |
|
| 242 * and 'primitive function P' but without swapping the left and right word. |
|
| 243 */ |
|
| 244 #define DES_ROUND(from, to, work, subkey) \ |
|
| 245 work = ((from<<1) | (from>>31)) ^ *subkey++; \ |
|
| 246 to ^= sbox8[ work & 0x3f ]; \ |
|
| 247 to ^= sbox6[ (work>>8) & 0x3f ]; \ |
|
| 248 to ^= sbox4[ (work>>16) & 0x3f ]; \ |
|
| 249 to ^= sbox2[ (work>>24) & 0x3f ]; \ |
|
| 250 work = ((from>>3) | (from<<29)) ^ *subkey++; \ |
|
| 251 to ^= sbox7[ work & 0x3f ]; \ |
|
| 252 to ^= sbox5[ (work>>8) & 0x3f ]; \ |
|
| 253 to ^= sbox3[ (work>>16) & 0x3f ]; \ |
|
| 254 to ^= sbox1[ (work>>24) & 0x3f ]; |
|
| 255 |
|
| 256 |
|
| 257 /* |
|
| 258 * Macros to convert 8 bytes from/to 32bit words |
|
| 259 */ |
|
| 260 #define READ_64BIT_DATA(data, left, right) \ |
|
| 261 left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ |
|
| 262 right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; |
|
| 263 |
|
| 264 #define WRITE_64BIT_DATA(data, left, right) \ |
|
| 265 data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ |
|
| 266 data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ |
|
| 267 data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ |
|
| 268 data[6] = (right >> 8) &0xff; data[7] = right &0xff; |
|
| 269 |
|
| 270 /****************************************************************************** |
|
| 271 * Cipher Stuff |
|
| 272 *****************************************************************************/ |
|
| 273 /* |
|
| 274 * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for |
|
| 275 * 16 encryption rounds. |
|
| 276 * To calculate subkeys for decryption the caller |
|
| 277 * have to reorder the generated subkeys. |
|
| 278 * |
|
| 279 * rawkey: 8 Bytes of key data |
|
| 280 * subkey: Array of at least 32 guint32s. Will be filled |
|
| 281 * with calculated subkeys. |
|
| 282 * |
|
| 283 */ |
|
| 284 static void |
|
| 285 purple_des_cipher_key_schedule(const guint8 * rawkey, guint32 * subkey) { |
|
| 286 guint32 left, right, work; |
|
| 287 int round; |
|
| 288 |
|
| 289 READ_64BIT_DATA (rawkey, left, right) |
|
| 290 |
|
| 291 DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) |
|
| 292 DO_PERMUTATION (right, work, left, 0, 0x10101010) |
|
| 293 |
|
| 294 left = (leftkey_swap[(left >> 0) & 0xf] << 3) |
|
| 295 | (leftkey_swap[(left >> 8) & 0xf] << 2) |
|
| 296 | (leftkey_swap[(left >> 16) & 0xf] << 1) |
|
| 297 | (leftkey_swap[(left >> 24) & 0xf] ) |
|
| 298 | (leftkey_swap[(left >> 5) & 0xf] << 7) |
|
| 299 | (leftkey_swap[(left >> 13) & 0xf] << 6) |
|
| 300 | (leftkey_swap[(left >> 21) & 0xf] << 5) |
|
| 301 | (leftkey_swap[(left >> 29) & 0xf] << 4); |
|
| 302 |
|
| 303 left &= 0x0fffffff; |
|
| 304 |
|
| 305 right = (rightkey_swap[(right >> 1) & 0xf] << 3) |
|
| 306 | (rightkey_swap[(right >> 9) & 0xf] << 2) |
|
| 307 | (rightkey_swap[(right >> 17) & 0xf] << 1) |
|
| 308 | (rightkey_swap[(right >> 25) & 0xf] ) |
|
| 309 | (rightkey_swap[(right >> 4) & 0xf] << 7) |
|
| 310 | (rightkey_swap[(right >> 12) & 0xf] << 6) |
|
| 311 | (rightkey_swap[(right >> 20) & 0xf] << 5) |
|
| 312 | (rightkey_swap[(right >> 28) & 0xf] << 4); |
|
| 313 |
|
| 314 right &= 0x0fffffff; |
|
| 315 |
|
| 316 for (round = 0; round < 16; ++round) { |
|
| 317 left = ((left << encrypt_rotate_tab[round]) | |
|
| 318 (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; |
|
| 319 right = ((right << encrypt_rotate_tab[round]) | |
|
| 320 (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; |
|
| 321 |
|
| 322 *subkey++ = ((left << 4) & 0x24000000) |
|
| 323 | ((left << 28) & 0x10000000) |
|
| 324 | ((left << 14) & 0x08000000) |
|
| 325 | ((left << 18) & 0x02080000) |
|
| 326 | ((left << 6) & 0x01000000) |
|
| 327 | ((left << 9) & 0x00200000) |
|
| 328 | ((left >> 1) & 0x00100000) |
|
| 329 | ((left << 10) & 0x00040000) |
|
| 330 | ((left << 2) & 0x00020000) |
|
| 331 | ((left >> 10) & 0x00010000) |
|
| 332 | ((right >> 13) & 0x00002000) |
|
| 333 | ((right >> 4) & 0x00001000) |
|
| 334 | ((right << 6) & 0x00000800) |
|
| 335 | ((right >> 1) & 0x00000400) |
|
| 336 | ((right >> 14) & 0x00000200) |
|
| 337 | (right & 0x00000100) |
|
| 338 | ((right >> 5) & 0x00000020) |
|
| 339 | ((right >> 10) & 0x00000010) |
|
| 340 | ((right >> 3) & 0x00000008) |
|
| 341 | ((right >> 18) & 0x00000004) |
|
| 342 | ((right >> 26) & 0x00000002) |
|
| 343 | ((right >> 24) & 0x00000001); |
|
| 344 |
|
| 345 *subkey++ = ((left << 15) & 0x20000000) |
|
| 346 | ((left << 17) & 0x10000000) |
|
| 347 | ((left << 10) & 0x08000000) |
|
| 348 | ((left << 22) & 0x04000000) |
|
| 349 | ((left >> 2) & 0x02000000) |
|
| 350 | ((left << 1) & 0x01000000) |
|
| 351 | ((left << 16) & 0x00200000) |
|
| 352 | ((left << 11) & 0x00100000) |
|
| 353 | ((left << 3) & 0x00080000) |
|
| 354 | ((left >> 6) & 0x00040000) |
|
| 355 | ((left << 15) & 0x00020000) |
|
| 356 | ((left >> 4) & 0x00010000) |
|
| 357 | ((right >> 2) & 0x00002000) |
|
| 358 | ((right << 8) & 0x00001000) |
|
| 359 | ((right >> 14) & 0x00000808) |
|
| 360 | ((right >> 9) & 0x00000400) |
|
| 361 | ((right) & 0x00000200) |
|
| 362 | ((right << 7) & 0x00000100) |
|
| 363 | ((right >> 7) & 0x00000020) |
|
| 364 | ((right >> 3) & 0x00000011) |
|
| 365 | ((right << 2) & 0x00000004) |
|
| 366 | ((right >> 21) & 0x00000002); |
|
| 367 } |
|
| 368 } |
|
| 369 |
|
| 370 /* |
|
| 371 * Fill a DES context with subkeys calculated from a 64bit key. |
|
| 372 * Does not check parity bits, but simply ignore them. |
|
| 373 * Does not check for weak keys. |
|
| 374 */ |
|
| 375 static void |
|
| 376 purple_des_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) { |
|
| 377 PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher); |
|
| 378 PurpleDESCipherPrivate *priv = PURPLE_DES_CIPHER_GET_PRIVATE(des_cipher); |
|
| 379 int i; |
|
| 380 |
|
| 381 g_return_if_fail(len == 8); |
|
| 382 |
|
| 383 purple_des_cipher_key_schedule(key, priv->encrypt_subkeys); |
|
| 384 |
|
| 385 for(i = 0; i < 32; i += 2) { |
|
| 386 priv->decrypt_subkeys[i] = priv->encrypt_subkeys[30 - i]; |
|
| 387 priv->decrypt_subkeys[i + 1] = priv->encrypt_subkeys[31 - i]; |
|
| 388 } |
|
| 389 |
|
| 390 g_object_notify_by_pspec(G_OBJECT(cipher), properties[PROP_KEY]); |
|
| 391 } |
|
| 392 |
|
| 393 static size_t |
|
| 394 purple_des_cipher_get_key_size(PurpleCipher *cipher) |
|
| 395 { |
|
| 396 return 8; |
|
| 397 } |
|
| 398 |
|
| 399 /* |
|
| 400 * Electronic Codebook Mode DES encryption/decryption of data according to |
|
| 401 * 'mode'. |
|
| 402 */ |
|
| 403 int |
|
| 404 purple_des_cipher_ecb_crypt(PurpleDESCipher *des_cipher, const guint8 * from, guint8 * to, |
|
| 405 int mode) |
|
| 406 { |
|
| 407 guint32 left, right, work; |
|
| 408 guint32 *keys; |
|
| 409 PurpleDESCipherPrivate *priv = PURPLE_DES_CIPHER_GET_PRIVATE(des_cipher); |
|
| 410 |
|
| 411 keys = mode ? priv->decrypt_subkeys : |
|
| 412 priv->encrypt_subkeys; |
|
| 413 |
|
| 414 READ_64BIT_DATA (from, left, right) |
|
| 415 INITIAL_PERMUTATION (left, work, right) |
|
| 416 |
|
| 417 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
|
| 418 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
|
| 419 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
|
| 420 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
|
| 421 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
|
| 422 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
|
| 423 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
|
| 424 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) |
|
| 425 |
|
| 426 FINAL_PERMUTATION (right, work, left) |
|
| 427 WRITE_64BIT_DATA (to, right, left) |
|
| 428 |
|
| 429 return 0; |
|
| 430 } |
|
| 431 |
|
| 432 static ssize_t |
|
| 433 purple_des_cipher_encrypt(PurpleCipher *cipher, const guchar input[], |
|
| 434 size_t in_len, guchar output[], size_t out_size) |
|
| 435 { |
|
| 436 PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher); |
|
| 437 |
|
| 438 gsize offset = 0; |
|
| 439 int i = 0; |
|
| 440 gsize tmp; |
|
| 441 guint8 buf[8] = {0,0,0,0,0,0,0,0}; |
|
| 442 gsize out_len; |
|
| 443 |
|
| 444 g_return_val_if_fail(out_size >= in_len, -1); |
|
| 445 |
|
| 446 while(offset + 8 <= in_len) { |
|
| 447 purple_des_cipher_ecb_crypt(des_cipher, input + offset, output + offset, 0); |
|
| 448 offset += 8; |
|
| 449 } |
|
| 450 |
|
| 451 out_len = in_len; |
|
| 452 |
|
| 453 if(offset<in_len) { |
|
| 454 g_return_val_if_fail(in_len >= offset, -1); |
|
| 455 out_len += in_len - offset; |
|
| 456 g_return_val_if_fail(out_size >= out_len, -1); |
|
| 457 tmp = offset; |
|
| 458 while(tmp<in_len) { |
|
| 459 buf[i++] = input[tmp]; |
|
| 460 tmp++; |
|
| 461 } |
|
| 462 |
|
| 463 purple_des_cipher_ecb_crypt(des_cipher, buf, output + offset, 0); |
|
| 464 } |
|
| 465 |
|
| 466 return out_len; |
|
| 467 } |
|
| 468 |
|
| 469 static ssize_t |
|
| 470 purple_des_cipher_decrypt(PurpleCipher *cipher, const guchar input[], |
|
| 471 size_t in_len, guchar output[], size_t out_size) |
|
| 472 { |
|
| 473 PurpleDESCipher *des_cipher = PURPLE_DES_CIPHER(cipher); |
|
| 474 |
|
| 475 gsize offset = 0; |
|
| 476 int i = 0; |
|
| 477 gsize tmp; |
|
| 478 guint8 buf[8] = {0,0,0,0,0,0,0,0}; |
|
| 479 gsize out_len; |
|
| 480 |
|
| 481 g_return_val_if_fail(out_size >= in_len, -1); |
|
| 482 |
|
| 483 while(offset + 8 <= in_len) { |
|
| 484 purple_des_cipher_ecb_crypt(des_cipher, input + offset, output + offset, 1); |
|
| 485 offset += 8; |
|
| 486 } |
|
| 487 |
|
| 488 out_len = in_len; |
|
| 489 if(offset<in_len) { |
|
| 490 g_return_val_if_fail(in_len >= offset, -1); |
|
| 491 out_len += in_len - offset; |
|
| 492 g_return_val_if_fail(out_size >= out_len, -1); |
|
| 493 tmp = offset; |
|
| 494 while(tmp<in_len) { |
|
| 495 buf[i++] = input[tmp]; |
|
| 496 tmp++; |
|
| 497 } |
|
| 498 |
|
| 499 purple_des_cipher_ecb_crypt(des_cipher, buf, output + offset, 1); |
|
| 500 } |
|
| 501 |
|
| 502 return out_len; |
|
| 503 } |
|
| 504 |
|
| 505 /****************************************************************************** |
|
| 506 * Object Stuff |
|
| 507 *****************************************************************************/ |
|
| 508 static void |
|
| 509 purple_des_cipher_set_property(GObject *obj, guint param_id, |
|
| 510 const GValue *value, GParamSpec *pspec) |
|
| 511 { |
|
| 512 PurpleCipher *cipher = PURPLE_CIPHER(obj); |
|
| 513 |
|
| 514 switch(param_id) { |
|
| 515 case PROP_KEY: |
|
| 516 purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value), |
|
| 517 purple_des_cipher_get_key_size(cipher)); |
|
| 518 break; |
|
| 519 default: |
|
| 520 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); |
|
| 521 break; |
|
| 522 } |
|
| 523 } |
|
| 524 |
|
| 525 static void |
|
| 526 purple_des_cipher_class_init(PurpleDESCipherClass *klass) |
|
| 527 { |
|
| 528 GObjectClass *obj_class = G_OBJECT_CLASS(klass); |
|
| 529 PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); |
|
| 530 |
|
| 531 parent_class = g_type_class_peek_parent(klass); |
|
| 532 |
|
| 533 obj_class->set_property = purple_des_cipher_set_property; |
|
| 534 |
|
| 535 cipher_class->encrypt = purple_des_cipher_encrypt; |
|
| 536 cipher_class->decrypt = purple_des_cipher_decrypt; |
|
| 537 cipher_class->set_key = purple_des_cipher_set_key; |
|
| 538 cipher_class->get_key_size = purple_des_cipher_get_key_size; |
|
| 539 |
|
| 540 g_type_class_add_private(klass, sizeof(PurpleDESCipherPrivate)); |
|
| 541 |
|
| 542 properties[PROP_KEY] = g_param_spec_string("key", "key", "key", NULL, |
|
| 543 G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); |
|
| 544 |
|
| 545 g_object_class_install_properties(obj_class, PROP_LAST, properties); |
|
| 546 } |
|
| 547 |
|
| 548 /****************************************************************************** |
|
| 549 * API |
|
| 550 *****************************************************************************/ |
|
| 551 GType |
|
| 552 purple_des_cipher_get_type(void) { |
|
| 553 static GType type = 0; |
|
| 554 |
|
| 555 if(type == 0) { |
|
| 556 static const GTypeInfo info = { |
|
| 557 .class_size = sizeof(PurpleDESCipherClass), |
|
| 558 .class_init = (GClassInitFunc)purple_des_cipher_class_init, |
|
| 559 .instance_size = sizeof(PurpleDESCipher), |
|
| 560 .instance_init = (GInstanceInitFunc)purple_cipher_reset, |
|
| 561 }; |
|
| 562 |
|
| 563 type = g_type_register_static(PURPLE_TYPE_CIPHER, |
|
| 564 "PurpleDESCipher", |
|
| 565 &info, 0); |
|
| 566 } |
|
| 567 |
|
| 568 return type; |
|
| 569 } |
|
| 570 |
|
| 571 /** |
|
| 572 * purple_des_cipher_new: |
|
| 573 * |
|
| 574 * Creates a new #PurpleCipher instance which implements the DES block cipher. |
|
| 575 * |
|
| 576 * Return Value: The new DES implementation of #PurpleCipher. |
|
| 577 */ |
|
| 578 PurpleCipher * |
|
| 579 purple_des_cipher_new(void) { |
|
| 580 return g_object_new(PURPLE_TYPE_DES_CIPHER, NULL); |
|
| 581 } |
|