Mercurial > pidgin.yaz
comparison src/protocols/qq/crypt.c @ 13977:96947ec79828
[gaim-migrate @ 16536]
Eliminated some nested function declarations.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Huetsch <markhuetsch> |
---|---|
date | Sat, 22 Jul 2006 11:44:46 +0000 |
parents | 983fd420e86b |
children | ef8490f9e823 |
comparison
equal
deleted
inserted
replaced
13976:6a5aaf46bd52 | 13977:96947ec79828 |
---|---|
38 the golden ratio: Sqrt(5/4) - 1/2 ~ 0.618034 multiplied by 2^32. | 38 the golden ratio: Sqrt(5/4) - 1/2 ~ 0.618034 multiplied by 2^32. |
39 | 39 |
40 0x61C88647 is what we can track on the ASM codes.!! | 40 0x61C88647 is what we can track on the ASM codes.!! |
41 */ | 41 */ |
42 | 42 |
43 #ifndef _WIN32 | |
44 #include <arpa/inet.h> | 43 #include <arpa/inet.h> |
45 #else | |
46 #include "win32dep.h" | |
47 #endif | |
48 | 44 |
49 #include <string.h> | 45 #include <string.h> |
50 | 46 |
51 #include "crypt.h" | 47 #include "crypt.h" |
52 #include "debug.h" // gaim_debug, by gfhuang | 48 #include "debug.h" // gaim_debug |
53 | 49 |
54 /*****************************************************************************/ | 50 /******************************************************************** |
51 * encryption | |
52 *******************************************************************/ | |
53 | |
55 static void qq_encipher(unsigned long *const v, const unsigned long *const k, unsigned long *const w) | 54 static void qq_encipher(unsigned long *const v, const unsigned long *const k, unsigned long *const w) |
56 { | 55 { |
57 register unsigned long y = ntohl(v[0]), z = ntohl(v[1]), a = ntohl(k[0]), b = ntohl(k[1]), c = ntohl(k[2]), d = ntohl(k[3]), n = 0x10, sum = 0, delta = 0x9E3779B9; /* 0x9E3779B9 - 0x100000000 = -0x61C88647 */ | 56 register unsigned long y = ntohl(v[0]), |
57 z = ntohl(v[1]), | |
58 a = ntohl(k[0]), | |
59 b = ntohl(k[1]), | |
60 c = ntohl(k[2]), | |
61 d = ntohl(k[3]), | |
62 n = 0x10, | |
63 sum = 0, | |
64 delta = 0x9E3779B9; /* 0x9E3779B9 - 0x100000000 = -0x61C88647 */ | |
58 | 65 |
59 while (n-- > 0) { | 66 while (n-- > 0) { |
60 sum += delta; | 67 sum += delta; |
61 y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); | 68 y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); |
62 z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); | 69 z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); |
63 } // while | 70 } |
64 | 71 |
65 w[0] = htonl(y); | 72 w[0] = htonl(y); |
66 w[1] = htonl(z); | 73 w[1] = htonl(z); |
67 } // qq_enciper | 74 } |
68 | 75 |
69 /*****************************************************************************/ | 76 static int rand(void) { // it can be the real random seed function |
77 return 0xdead; | |
78 } // override with number, convenient for debug | |
79 | |
80 // we encrypt every eight byte chunk | |
81 static void encrypt_every_8_byte(unsigned char *plain, unsigned char *plain_pre_8, unsigned char **crypted, | |
82 unsigned char **crypted_pre_8, unsigned char *key, int *count, int *pos_in_byte, int *is_header) | |
83 { | |
84 // prepare plain text | |
85 for (*pos_in_byte = 0; *pos_in_byte < 8; (*pos_in_byte)++) { | |
86 if (*is_header) { | |
87 plain[*pos_in_byte] ^= plain_pre_8[*pos_in_byte]; | |
88 } else { | |
89 plain[*pos_in_byte] ^= (*crypted_pre_8)[*pos_in_byte]; | |
90 } | |
91 } | |
92 qq_encipher((unsigned long *) plain, (unsigned long *) key, (unsigned long *) *crypted); // encrypt it | |
93 | |
94 for (*pos_in_byte = 0; *pos_in_byte < 8; (*pos_in_byte)++) { | |
95 (*crypted)[*pos_in_byte] ^= plain_pre_8[*pos_in_byte]; | |
96 } | |
97 memcpy(plain_pre_8, plain, 8); // prepare next | |
98 | |
99 *crypted_pre_8 = *crypted; // store position of previous 8 byte | |
100 *crypted += 8; // prepare next output | |
101 *count += 8; // outstrlen increase by 8 | |
102 *pos_in_byte = 0; // back to start | |
103 *is_header = 0; // and exit header | |
104 } // encrypt_every_8_byte | |
105 | |
106 | |
107 static void qq_encrypt(unsigned char *instr, int instrlen, unsigned char *key, unsigned char *outstr, int *outstrlen_prt) | |
108 { | |
109 unsigned char plain[8], // plain text buffer | |
110 plain_pre_8[8], // plain text buffer, previous 8 bytes | |
111 *crypted, // crypted text | |
112 *crypted_pre_8, // crypted test, previous 8 bytes | |
113 *inp; // current position in instr | |
114 int pos_in_byte = 1, // loop in the byte | |
115 is_header = 1, // header is one byte | |
116 count = 0, // number of bytes being crypted | |
117 padding = 0; // number of padding stuff | |
118 | |
119 pos_in_byte = (instrlen + 0x0a) % 8; // header padding decided by instrlen | |
120 if (pos_in_byte) { | |
121 pos_in_byte = 8 - pos_in_byte; | |
122 } | |
123 plain[0] = (rand() & 0xf8) | pos_in_byte; | |
124 | |
125 memset(plain + 1, rand() & 0xff, pos_in_byte++); | |
126 memset(plain_pre_8, 0x00, sizeof(plain_pre_8)); | |
127 | |
128 crypted = crypted_pre_8 = outstr; | |
129 | |
130 padding = 1; // pad some stuff in header | |
131 while (padding <= 2) { // at most two bytes | |
132 if (pos_in_byte < 8) { | |
133 plain[pos_in_byte++] = rand() & 0xff; | |
134 padding++; | |
135 } | |
136 if (pos_in_byte == 8) { | |
137 encrypt_every_8_byte(plain, plain_pre_8, &crypted, &crypted_pre_8, key, &count, &pos_in_byte, &is_header); | |
138 } | |
139 } | |
140 | |
141 inp = instr; | |
142 while (instrlen > 0) { | |
143 if (pos_in_byte < 8) { | |
144 plain[pos_in_byte++] = *(inp++); | |
145 instrlen--; | |
146 } | |
147 if (pos_in_byte == 8) { | |
148 encrypt_every_8_byte(plain, plain_pre_8, &crypted, &crypted_pre_8, key, &count, &pos_in_byte, &is_header); | |
149 } | |
150 } | |
151 | |
152 padding = 1; // pad some stuff in tail | |
153 while (padding <= 7) { // at most seven bytes | |
154 if (pos_in_byte < 8) { | |
155 plain[pos_in_byte++] = 0x00; | |
156 padding++; | |
157 } | |
158 if (pos_in_byte == 8) { | |
159 encrypt_every_8_byte(plain, plain_pre_8, &crypted, &crypted_pre_8, key, &count, &pos_in_byte, &is_header); | |
160 } | |
161 } | |
162 | |
163 *outstrlen_prt = count; | |
164 } | |
165 | |
166 | |
167 /******************************************************************** | |
168 * decryption | |
169 ********************************************************************/ | |
170 | |
70 static void qq_decipher(unsigned long *const v, const unsigned long *const k, unsigned long *const w) | 171 static void qq_decipher(unsigned long *const v, const unsigned long *const k, unsigned long *const w) |
71 { | 172 { |
72 register unsigned long y = ntohl(v[0]), z = ntohl(v[1]), a = ntohl(k[0]), b = ntohl(k[1]), c = ntohl(k[2]), d = ntohl(k[3]), n = 0x10, sum = 0xE3779B90, // why this ? must be related with n value | 173 register unsigned long y = ntohl(v[0]), |
73 delta = 0x9E3779B9; | 174 z = ntohl(v[1]), |
175 a = ntohl(k[0]), | |
176 b = ntohl(k[1]), | |
177 c = ntohl(k[2]), | |
178 d = ntohl(k[3]), | |
179 n = 0x10, | |
180 sum = 0xE3779B90, // why this ? must be related with n value | |
181 delta = 0x9E3779B9; | |
74 | 182 |
75 /* sum = delta<<5, in general sum = delta * n */ | 183 /* sum = delta<<5, in general sum = delta * n */ |
76 while (n-- > 0) { | 184 while (n-- > 0) { |
77 z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); | 185 z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); |
78 y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); | 186 y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); |
79 sum -= delta; | 187 sum -= delta; |
80 } | 188 } |
81 | 189 |
82 w[0] = htonl(y); | 190 w[0] = htonl(y); |
83 w[1] = htonl(z); | 191 w[1] = htonl(z); |
84 } // qq_decipher | 192 } |
85 | 193 |
86 /******************************************************************** | 194 static int decrypt_every_8_byte(unsigned char **crypt_buff, const int instrlen, const unsigned char * const key, |
87 * encrypt part | 195 int *context_start, unsigned char *decrypted, int *pos_in_byte) |
88 *******************************************************************/ | 196 { |
89 | 197 for (*pos_in_byte = 0; *pos_in_byte < 8; (*pos_in_byte)++) { |
90 static void qq_encrypt(unsigned char *instr, int instrlen, unsigned char *key, unsigned char *outstr, int *outstrlen_prt) | 198 if (*context_start + *pos_in_byte >= instrlen) |
91 { | 199 return 1; |
92 unsigned char plain[8], // plain text buffer | 200 decrypted[*pos_in_byte] ^= (*crypt_buff)[*pos_in_byte]; |
93 plain_pre_8[8], // plain text buffer, previous 8 bytes | 201 } |
94 *crypted, // crypted text | 202 qq_decipher((unsigned long *) decrypted, (unsigned long *) key, (unsigned long *) decrypted); |
95 *crypted_pre_8, // crypted test, previous 8 bytes | 203 |
96 *inp; // current position in instr | 204 *context_start += 8; |
97 int pos_in_byte = 1, // loop in the byte | 205 *crypt_buff += 8; |
98 is_header = 1, // header is one byte | 206 *pos_in_byte = 0; |
99 count = 0, // number of bytes being crypted | 207 |
100 padding = 0; // number of padding stuff | 208 return 1; |
101 | 209 } |
102 int rand(void) { // it can be the real random seed function | 210 |
103 return 0xdead; | 211 // return 0 if failed, 1 otherwise |
104 } // override with number, convenient for debug | |
105 | |
106 /*** we encrypt every eight byte ***/ | |
107 void encrypt_every_8_byte(void) { | |
108 for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) { | |
109 if (is_header) { | |
110 plain[pos_in_byte] ^= plain_pre_8[pos_in_byte]; | |
111 } else { | |
112 plain[pos_in_byte] ^= crypted_pre_8[pos_in_byte]; | |
113 } | |
114 } // prepare plain text | |
115 qq_encipher((unsigned long *) plain, (unsigned long *) key, (unsigned long *) crypted); // encrypt it | |
116 | |
117 for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) { | |
118 crypted[pos_in_byte] ^= plain_pre_8[pos_in_byte]; | |
119 } | |
120 memcpy(plain_pre_8, plain, 8); // prepare next | |
121 | |
122 crypted_pre_8 = crypted; // store position of previous 8 byte | |
123 crypted += 8; // prepare next output | |
124 count += 8; // outstrlen increase by 8 | |
125 pos_in_byte = 0; // back to start | |
126 is_header = 0; // and exit header | |
127 } // encrypt_every_8_byte | |
128 | |
129 pos_in_byte = (instrlen + 0x0a) % 8; // header padding decided by instrlen | |
130 if (pos_in_byte) { | |
131 pos_in_byte = 8 - pos_in_byte; | |
132 } | |
133 plain[0] = (rand() & 0xf8) | pos_in_byte; | |
134 | |
135 memset(plain + 1, rand() & 0xff, pos_in_byte++); | |
136 memset(plain_pre_8, 0x00, sizeof(plain_pre_8)); | |
137 | |
138 crypted = crypted_pre_8 = outstr; | |
139 | |
140 padding = 1; // pad some stuff in header | |
141 while (padding <= 2) { // at most two byte | |
142 if (pos_in_byte < 8) { | |
143 plain[pos_in_byte++] = rand() & 0xff; | |
144 padding++; | |
145 } | |
146 if (pos_in_byte == 8) { | |
147 encrypt_every_8_byte(); | |
148 } | |
149 } | |
150 | |
151 inp = instr; | |
152 while (instrlen > 0) { | |
153 if (pos_in_byte < 8) { | |
154 plain[pos_in_byte++] = *(inp++); | |
155 instrlen--; | |
156 } | |
157 if (pos_in_byte == 8) { | |
158 encrypt_every_8_byte(); | |
159 } | |
160 } | |
161 | |
162 padding = 1; // pad some stuff in tailer | |
163 while (padding <= 7) { // at most sever byte | |
164 if (pos_in_byte < 8) { | |
165 plain[pos_in_byte++] = 0x00; | |
166 padding++; | |
167 } | |
168 if (pos_in_byte == 8) { | |
169 encrypt_every_8_byte(); | |
170 } | |
171 } | |
172 | |
173 *outstrlen_prt = count; | |
174 } // qq_encrypt | |
175 | |
176 | |
177 /******************************************************************** | |
178 * [decrypt part] | |
179 * return 0 if failed, otherwise return 1 | |
180 ********************************************************************/ | |
181 | |
182 static int qq_decrypt(unsigned char *instr, int instrlen, unsigned char *key, unsigned char *outstr, int *outstrlen_ptr) | 212 static int qq_decrypt(unsigned char *instr, int instrlen, unsigned char *key, unsigned char *outstr, int *outstrlen_ptr) |
183 { | 213 { |
184 unsigned char decrypted[8], m[8], *crypt_buff, *crypt_buff_pre_8, *outp; | 214 unsigned char decrypted[8], m[8], *crypt_buff, *crypt_buff_pre_8, *outp; |
185 int count, context_start, pos_in_byte, padding; | 215 int count, context_start, pos_in_byte, padding; |
186 | 216 |
187 int decrypt_every_8_byte(void) { | |
188 for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) { | |
189 if (context_start + pos_in_byte >= instrlen) | |
190 return 1; | |
191 decrypted[pos_in_byte] ^= crypt_buff[pos_in_byte]; | |
192 } | |
193 qq_decipher((unsigned long *) decrypted, (unsigned long *) key, (unsigned long *) decrypted); | |
194 | |
195 context_start += 8; | |
196 crypt_buff += 8; | |
197 pos_in_byte = 0; | |
198 return 1; | |
199 } // decrypt_every_8_byte | |
200 | |
201 // at least 16 bytes and %8 == 0 | 217 // at least 16 bytes and %8 == 0 |
202 if ((instrlen % 8) || (instrlen < 16)) { | 218 if ((instrlen % 8) || (instrlen < 16)) { |
203 //debug info by gfhuang | 219 gaim_debug(GAIM_DEBUG_ERROR, "QQ", |
204 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Packet len is not times of 8 bytes, read %d bytes\n", instrlen); | 220 "Packet len is either too short or not a multiple of 8 bytes, read %d bytes\n", instrlen); |
205 return 0; | 221 return 0; |
206 } | 222 } |
207 // get information from header | 223 // get information from header |
208 qq_decipher((unsigned long *) instr, (unsigned long *) key, (unsigned long *) decrypted); | 224 qq_decipher((unsigned long *) instr, (unsigned long *) key, (unsigned long *) decrypted); |
209 pos_in_byte = decrypted[0] & 0x7; | 225 pos_in_byte = decrypted[0] & 0x7; |
210 count = instrlen - pos_in_byte - 10; // this is the plaintext length | 226 count = instrlen - pos_in_byte - 10; // this is the plaintext length |
211 // return if outstr buffer is not large enought or error plaintext length | 227 // return if outstr buffer is not large enough or error plaintext length |
212 if (*outstrlen_ptr < count || count < 0) { | 228 if (*outstrlen_ptr < count || count < 0) { |
213 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Buffer len %d is less than real len %d", *outstrlen_ptr, count); | 229 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Buffer len %d is less than real len %d", *outstrlen_ptr, count); |
214 return 0; | 230 return 0; |
215 } | 231 } |
216 | 232 |
217 memset(m, 0, 8); | 233 memset(m, 0, 8); |
218 crypt_buff_pre_8 = m; | 234 crypt_buff_pre_8 = m; |
219 *outstrlen_ptr = count; // everything is ok! set return string length | 235 *outstrlen_ptr = count; // everything is ok! set return string length |
220 | 236 |
221 crypt_buff = instr + 8; // address of real data start | 237 crypt_buff = instr + 8; // address of real data start |
222 context_start = 8; // context is at the second 8 byte | 238 context_start = 8; // context is at the second chunk of 8 bytes |
223 pos_in_byte++; // start of paddng stuff | 239 pos_in_byte++; // start of paddng stuff |
224 | 240 |
225 padding = 1; // at least one in header | 241 padding = 1; // at least one in header |
226 while (padding <= 2) { // there are 2 byte padding stuff in header | 242 while (padding <= 2) { // there are 2 byte padding stuff in header |
227 if (pos_in_byte < 8) { // bypass the padding stuff, none sense data | 243 if (pos_in_byte < 8) { // bypass the padding stuff, it's nonsense data |
228 pos_in_byte++; | 244 pos_in_byte++; |
229 padding++; | 245 padding++; |
230 } | 246 } |
231 if (pos_in_byte == 8) { | 247 if (pos_in_byte == 8) { |
232 crypt_buff_pre_8 = instr; | 248 crypt_buff_pre_8 = instr; |
233 if (!decrypt_every_8_byte()) { | 249 if (!decrypt_every_8_byte(&crypt_buff, instrlen, key, &context_start, decrypted, &pos_in_byte)) { |
234 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "decrypt every 8 bytes error A"); | 250 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "decrypt every 8 bytes error A"); |
235 return 0; | 251 return 0; |
236 } | 252 } |
237 } | 253 } |
238 } // while | 254 } |
239 | 255 |
240 outp = outstr; | 256 outp = outstr; |
241 while (count != 0) { | 257 while (count != 0) { |
242 if (pos_in_byte < 8) { | 258 if (pos_in_byte < 8) { |
243 *outp = crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte]; | 259 *outp = crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte]; |
245 count--; | 261 count--; |
246 pos_in_byte++; | 262 pos_in_byte++; |
247 } | 263 } |
248 if (pos_in_byte == 8) { | 264 if (pos_in_byte == 8) { |
249 crypt_buff_pre_8 = crypt_buff - 8; | 265 crypt_buff_pre_8 = crypt_buff - 8; |
250 if (!decrypt_every_8_byte()) { | 266 if (!decrypt_every_8_byte(&crypt_buff, instrlen, key, &context_start, decrypted, &pos_in_byte)) { |
251 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "decrypt every 8 bytes error B"); | 267 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "decrypt every 8 bytes error B"); |
252 return 0; | 268 return 0; |
253 } | 269 } |
254 } | 270 } |
255 } // while | 271 } |
256 | 272 |
257 for (padding = 1; padding < 8; padding++) { | 273 for (padding = 1; padding < 8; padding++) { |
258 if (pos_in_byte < 8) { | 274 if (pos_in_byte < 8) { |
259 if (crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte]) | 275 if (crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte]) |
260 return 0; | 276 return 0; |
261 pos_in_byte++; | 277 pos_in_byte++; |
262 } | 278 } |
263 if (pos_in_byte == 8) { | 279 if (pos_in_byte == 8) { |
264 crypt_buff_pre_8 = crypt_buff; | 280 crypt_buff_pre_8 = crypt_buff; |
265 if (!decrypt_every_8_byte()) { | 281 if (!decrypt_every_8_byte(&crypt_buff, instrlen, key, &context_start, decrypted, &pos_in_byte)) { |
266 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "decrypt every 8 bytes error C"); | 282 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "decrypt every 8 bytes error C"); |
267 return 0; | 283 return 0; |
268 } | 284 } |
269 } | 285 } |
270 } // for | 286 } |
271 return 1; | 287 return 1; |
272 } // qq_decrypt | 288 } |
273 | 289 |
274 /*****************************************************************************/ | 290 /*****************************************************************************/ |
275 /* This is the Public Function */ | 291 /* This is the Public Function */ |
276 // return 1 is succeed, otherwise return 0 | 292 // return 1 is succeed, otherwise return 0 |
277 int qq_crypt(unsigned char flag, | 293 int qq_crypt(unsigned char flag, |
281 return qq_decrypt(instr, instrlen, key, outstr, outstrlen_ptr); | 297 return qq_decrypt(instr, instrlen, key, outstr, outstrlen_ptr); |
282 else if (flag == ENCRYPT) | 298 else if (flag == ENCRYPT) |
283 qq_encrypt(instr, instrlen, key, outstr, outstrlen_ptr); | 299 qq_encrypt(instr, instrlen, key, outstr, outstrlen_ptr); |
284 | 300 |
285 return 1; // flag must be DECRYPT or ENCRYPT | 301 return 1; // flag must be DECRYPT or ENCRYPT |
286 } // qq_crypt | 302 } |
287 | 303 |
288 /*****************************************************************************/ | 304 /*****************************************************************************/ |
289 // END OF FILE | 305 // END OF FILE |