diff options
Diffstat (limited to 'libpurple/protocols/qq/crypt.c')
-rw-r--r-- | libpurple/protocols/qq/crypt.c | 393 |
1 files changed, 0 insertions, 393 deletions
diff --git a/libpurple/protocols/qq/crypt.c b/libpurple/protocols/qq/crypt.c deleted file mode 100644 index f2a1df5e0e..0000000000 --- a/libpurple/protocols/qq/crypt.c +++ /dev/null @@ -1,393 +0,0 @@ -/** - * @file crypt.c - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * QQ encryption algorithm - * Convert from ASM code provided by PerlOICQ - * - * Puzzlebird, Nov-Dec 2002 - */ - -/* Notes: (QQ uses 16 rounds, and modified something...) - -IN : 64 bits of data in v[0] - v[1]. -OUT: 64 bits of data in w[0] - w[1]. -KEY: 128 bits of key in k[0] - k[3]. - -delta is chosen to be the real part of -the golden ratio: Sqrt(5/4) - 1/2 ~ 0.618034 multiplied by 2^32. - -0x61C88647 is what we can track on the ASM codes.!! -*/ - -#include <string.h> - -#include "crypt.h" -#include "debug.h" - -/* 1, fixed alignment problem, when compiled on different platform - * 2, whether we need core debug - * 20070717, s3e */ -#if 0 -#define CORE_DEBUG -#endif - -/******************************************************************** - * encryption - *******************************************************************/ - -/* Tiny Encryption Algorithm (TEA) */ -static void qq_encipher(guint32 *const v, const guint32 *const k, guint32 *const w) -{ - register guint32 - y = g_ntohl(v[0]), - z = g_ntohl(v[1]), - a = g_ntohl(k[0]), - b = g_ntohl(k[1]), - c = g_ntohl(k[2]), - d = g_ntohl(k[3]), - n = 0x10, - sum = 0, - delta = 0x9E3779B9; /* 0x9E3779B9 - 0x100000000 = -0x61C88647 */ - - while (n-- > 0) { - sum += delta; - y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); - z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); - } - - w[0] = g_htonl(y); - w[1] = g_htonl(z); -} - -/* it can be the real random seed function */ -/* override with number, convenient for debug */ -#ifdef DEBUG -static gint rand(void) { - return 0xdead; -} -#else -#include <stdlib.h> -#endif - -/* 64-bit blocks and some kind of feedback mode of operation */ -static inline void encrypt_block(guint8 *plain, guint8 *plain_pre_8, guint8 **crypted, - guint8 **crypted_pre_8, const guint8 *const key, gint *count, - gint *pos_in_block, gint *is_header) -{ - /* loop it */ - int j; - /* ships in encipher */ - guint32 ptr_p[2]; /* 64 bits, guint32[2] */ - guint32 ptr_k[4]; /* 128 bits, guint32[4] */ - guint32 ptr_c[2]; /* 64 bits, guint32[2] */ - - /* prepare input text */ -#ifdef CORE_DEBUG - purple_debug(PURPLE_DEBUG_ERROR, "QQ_CORE_DEBUG", - "!we are in encrypt_block! *pos_in_block comes: %d, *is_header comes: %d\n", - *pos_in_block, *is_header); -#endif - for(j = 0; j < 8; j++) { -#ifdef CORE_DEBUG - purple_debug(PURPLE_DEBUG_INFO, "QQ_CORE_DEBUG", - "plain[%d]: 0x%02x, plain_pre_8[%d]: 0x%02x\n", - j, plain[j], j, plain_pre_8[j]); -#endif - if (!*is_header) { -#ifdef CORE_DEBUG - purple_debug(PURPLE_DEBUG_INFO, "QQ_CORE_DEBUG", - "(*crypted_pre_8 + %d): 0x%02x\n", - j, *(*crypted_pre_8 + j)); -#endif - plain[j] ^= (*(*crypted_pre_8 + j)); -#ifdef CORE_DEBUG - purple_debug(PURPLE_DEBUG_INFO, "QQ_CORE_DEBUG", - "NOW plain[%d]: 0x%02x\n", - j, plain[j]); -#endif - } else { - plain[j] ^= plain_pre_8[j]; -#ifdef CORE_DEBUG - purple_debug(PURPLE_DEBUG_INFO, "QQ_CORE_DEBUG", - "NOW plain[%d]: 0x%02x\n", - j, plain[j]); -#endif - } - } - - g_memmove(ptr_p, plain, 8); - g_memmove(ptr_k, key, 16); - g_memmove(ptr_c, *crypted, 8); - - /* encrypt it */ - qq_encipher(ptr_p, ptr_k, ptr_c); - - g_memmove(plain, ptr_p, 8); - g_memmove(*crypted, ptr_c, 8); - - for(j = 0; j < 8; j++) { -#ifdef CORE_DEBUG - purple_debug(PURPLE_DEBUG_INFO, "QQ_CORE_DEBUG", - "j: %d, *(*crypted + %d): 0x%02x, plain_pre_8[%d]: 0x%02x\n", - j, j, *(*crypted + j), j, plain_pre_8[j]); -#endif - (*(*crypted + j)) ^= plain_pre_8[j]; -#ifdef CORE_DEBUG - purple_debug(PURPLE_DEBUG_INFO, "QQ_CORE_DEBUG", - "NOW *(*crypted + [%d]): 0x%02x\n", - j, *(*crypted + j)); -#endif - } - - memcpy(plain_pre_8, plain, 8); /* prepare next */ - - *crypted_pre_8 = *crypted; /* store position of previous 8 byte */ - *crypted += 8; /* prepare next output */ - *count += 8; /* outstrlen increase by 8 */ - *pos_in_block = 0; /* back to start */ - *is_header = 0; /* and exit header */ -} /* encrypt_block */ - -void qq_encrypt(const guint8 *const instr, gint instrlen, - const guint8 *const key, - guint8 *outstr, gint *outstrlen_ptr) -{ - guint8 plain[8], /* plain text buffer */ - plain_pre_8[8], /* plain text buffer, previous 8 bytes */ - *crypted, /* crypted text */ - *crypted_pre_8; /* crypted text, previous 8 bytes */ - const guint8 *inp; /* current position in instr */ - gint pos_in_block = 1, /* loop in the byte */ - is_header = 1, /* header is one byte */ - count = 0, /* number of bytes being crypted */ - padding = 0; /* number of padding stuff */ - - pos_in_block = (instrlen + 0x0a) % 8; /* header padding decided by instrlen */ - if (pos_in_block) - pos_in_block = 8 - pos_in_block; - - /* initialization vector */ - plain[0] = (rand() & 0xf8) | pos_in_block; - memset(plain + 1, rand() & 0xff, pos_in_block++); - - memset(plain_pre_8, 0x00, sizeof(plain_pre_8)); - - crypted = crypted_pre_8 = outstr; - - padding = 1; /* pad some stuff in header */ - while (padding <= 2) { /* at most two bytes */ - if (pos_in_block < 8) { - plain[pos_in_block++] = rand() & 0xff; - padding++; - } - if (pos_in_block == 8) { - encrypt_block(plain, plain_pre_8, &crypted, &crypted_pre_8, - key, &count, &pos_in_block, &is_header); - } - } - - inp = instr; - while (instrlen > 0) { - if (pos_in_block < 8) { - plain[pos_in_block++] = *(inp++); - instrlen--; - } - if (pos_in_block == 8) { - encrypt_block(plain, plain_pre_8, &crypted, &crypted_pre_8, - key, &count, &pos_in_block, &is_header); - } - } - - padding = 1; /* pad some stuff in tail */ - while (padding <= 7) { /* at most seven bytes */ - if (pos_in_block < 8) { - plain[pos_in_block++] = 0x00; - padding++; - } - if (pos_in_block == 8) { - encrypt_block(plain, plain_pre_8, &crypted, &crypted_pre_8, - key, &count, &pos_in_block, &is_header); - } - } - - *outstrlen_ptr = count; -} - - -/******************************************************************** - * decryption - ********************************************************************/ - -static void qq_decipher(guint32 *const v, const guint32 *const k, guint32 *const w) -{ - register guint32 - y = g_ntohl(v[0]), - z = g_ntohl(v[1]), - a = g_ntohl(k[0]), - b = g_ntohl(k[1]), - c = g_ntohl(k[2]), - d = g_ntohl(k[3]), - n = 0x10, - sum = 0xE3779B90, /* why this ? must be related with n value */ - delta = 0x9E3779B9; - - /* sum = delta<<5, in general sum = delta * n */ - while (n-- > 0) { - z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); - y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); - sum -= delta; - } - - w[0] = g_htonl(y); - w[1] = g_htonl(z); -} - -static gint decrypt_block(const guint8 **crypt_buff, const gint instrlen, - const guint8 *const key, gint *context_start, - guint8 *decrypted, gint *pos_in_block) -{ - /* loop */ - int i; - /* ships in decipher */ - guint32 ptr_v[2]; - guint32 ptr_k[4]; - - if (*context_start == instrlen) - return 1; - - for(i = 0; i < 8; i++) { - decrypted[i] ^= (*(*crypt_buff + i)); - } - - g_memmove(ptr_v, decrypted, 8); - g_memmove(ptr_k, key, 16); - - qq_decipher(ptr_v, ptr_k, ptr_v); - - g_memmove(decrypted, ptr_v, 8); - - *context_start += 8; - *crypt_buff += 8; - *pos_in_block = 0; - - return 1; -} - -/* return 0 if failed, 1 otherwise */ -gint qq_decrypt(const guint8 *const instr, gint instrlen, - const guint8 *const key, - guint8 *outstr, gint *outstrlen_ptr) -{ - guint8 decrypted[8], m[8], *outp; - const guint8 *crypt_buff, *crypt_buff_pre_8; - gint count, context_start, pos_in_block, padding; - /* ships */ - guint32 ptr_instr[2]; - guint32 ptr_key[4]; - guint32 ptr_decr[2]; - - /* at least 16 bytes and %8 == 0 */ - if ((instrlen % 8) || (instrlen < 16)) { - purple_debug(PURPLE_DEBUG_ERROR, "QQ", - "Ciphertext len is either too short or not a multiple of 8 bytes, read %d bytes\n", - instrlen); - return 0; - } - g_memmove(ptr_instr, instr, 8); - g_memmove(ptr_key, key, 16); - g_memmove(ptr_decr, decrypted, 8); - - qq_decipher(ptr_instr, ptr_key, ptr_decr); - - g_memmove(decrypted, ptr_decr, 8); - - pos_in_block = decrypted[0] & 0x7; - count = instrlen - pos_in_block - 10; /* this is the plaintext length */ - /* return if outstr buffer is not large enough or error plaintext length */ - if (*outstrlen_ptr < count || count < 0) { - purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Buffer len %d is less than real len %d", - *outstrlen_ptr, count); - return 0; - } - - memset(m, 0, 8); - crypt_buff_pre_8 = m; - *outstrlen_ptr = count; /* everything is ok! set return string length */ - - crypt_buff = instr + 8; /* address of real data start */ - context_start = 8; /* context is at the second block of 8 bytes */ - pos_in_block++; /* start of paddng stuff */ - - padding = 1; /* at least one in header */ - while (padding <= 2) { /* there are 2 byte padding stuff in header */ - if (pos_in_block < 8) { /* bypass the padding stuff, it's nonsense data */ - pos_in_block++; - padding++; - } - if (pos_in_block == 8) { - crypt_buff_pre_8 = instr; - if (!decrypt_block(&crypt_buff, instrlen, key, - &context_start, decrypted, &pos_in_block)) { - purple_debug(PURPLE_DEBUG_ERROR, "QQ", "decrypt every 8 bytes error A"); - return 0; - } - } - } - - outp = outstr; - while (count != 0) { - if (pos_in_block < 8) { - *outp = crypt_buff_pre_8[pos_in_block] ^ decrypted[pos_in_block]; - outp++; - count--; - pos_in_block++; - } - if (pos_in_block == 8) { - crypt_buff_pre_8 = crypt_buff - 8; - if (!decrypt_block(&crypt_buff, instrlen, key, - &context_start, decrypted, &pos_in_block)) { - purple_debug(PURPLE_DEBUG_ERROR, "QQ", "decrypt every 8 bytes error B"); - return 0; - } - } - } - - for (padding = 1; padding < 8; padding++) { - if (pos_in_block < 8) { - if (crypt_buff_pre_8[pos_in_block] ^ decrypted[pos_in_block]) - return 0; - pos_in_block++; - } - if (pos_in_block == 8) { - crypt_buff_pre_8 = crypt_buff; - if (!decrypt_block(&crypt_buff, instrlen, key, - &context_start, decrypted, &pos_in_block)) { - purple_debug(PURPLE_DEBUG_ERROR, "QQ", "decrypt every 8 bytes error C"); - return 0; - } - } - } - - return 1; -} |