--- a/src/protocols/msn/msn-utils.c Sun Jul 09 16:48:25 2006 +0000 +++ b/src/protocols/msn/msn-utils.c Mon Jul 17 12:22:37 2006 +0000 @@ -23,6 +23,7 @@ */ #include "msn.h" #include "msn-utils.h" +//#include <openssl/md5.h> void msn_parse_format(const char *mime, char **pre_ret, char **post_ret) @@ -362,3 +363,122 @@ *ret_port = port; } +/*check the edian of system*/ +int +isBigEndian(void) +{ + short int word = 0x0100; + char *byte = (char *)&word; + + return(byte[0]); +} + +/*swap utility*/ +unsigned int +swapInt(unsigned int dw) +{ + unsigned int tmp; + tmp = (dw & 0x000000FF); + tmp = ((dw & 0x0000FF00) >> 0x08) | (tmp << 0x08); + tmp = ((dw & 0x00FF0000) >> 0x10) | (tmp << 0x08); + tmp = ((dw & 0xFF000000) >> 0x18) | (tmp << 0x08); + return(tmp); +} + +/* + * handle MSN Chanllege computation + *This algorithm reference with http://msnpiki.msnfanatic.com/index.php/MSNP11:Challenges + */ +#define BUFSIZE 256 +void +msn_handle_chl(char *input, char *output) +{ + GaimCipher *cipher; + GaimCipherContext *context; + char *productKey = MSNP13_WLM_PRODUCT_KEY, + *productID = MSNP13_WLM_PRODUCT_ID, + *hexChars = "0123456789abcdef", + buf[BUFSIZE]; + unsigned char md5Hash[16], *newHash; + unsigned int *md5Parts, *chlStringParts, newHashParts[5]; + + long long nHigh=0, nLow=0; + + int i, bigEndian; + + /* Determine our endianess */ + bigEndian = isBigEndian(); + + /* Create the MD5 hash by using Gaim MD5 algorithm*/ + cipher = gaim_ciphers_find_cipher("md5"); + context = gaim_cipher_context_new(cipher, NULL); + + gaim_cipher_context_append(context, (const guchar *)input, + strlen(input)); + gaim_cipher_context_append(context, (const guchar *)productKey, + strlen(productKey)); + gaim_cipher_context_digest(context, sizeof(md5Hash), md5Hash, NULL); + gaim_cipher_context_destroy(context); + + /* Split it into four integers */ + md5Parts = (unsigned int *)md5Hash; + for(i=0; i<4; i++){ + /* check for endianess */ + if(bigEndian) + md5Parts[i] = swapInt(md5Parts[i]); + + /* & each integer with 0x7FFFFFFF */ + /* and save one unmodified array for later */ + newHashParts[i] = md5Parts[i]; + md5Parts[i] &= 0x7FFFFFFF; + } + + /* make a new string and pad with '0' */ + snprintf(buf, BUFSIZE-5, "%s%s", input, productID); + i = strlen(buf); + memset(&buf[i], '0', 8 - (i % 8)); + buf[i + (8 - (i % 8))]='\0'; + + /* split into integers */ + chlStringParts = (unsigned int *)buf; + + /* this is magic */ + for (i=0; i<(strlen(buf)/4)-1; i+=2){ + long long temp; + + if(bigEndian){ + chlStringParts[i] = swapInt(chlStringParts[i]); + chlStringParts[i+1] = swapInt(chlStringParts[i+1]); + } + + temp=(md5Parts[0] * (((0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF)+nHigh) + md5Parts[1])%0x7FFFFFFF; + nHigh=(md5Parts[2] * (((long long)chlStringParts[i+1]+temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF; + nLow=nLow + nHigh + temp; + } + nHigh=(nHigh+md5Parts[1]) % 0x7FFFFFFF; + nLow=(nLow+md5Parts[3]) % 0x7FFFFFFF; + + newHashParts[0]^=nHigh; + newHashParts[1]^=nLow; + newHashParts[2]^=nHigh; + newHashParts[3]^=nLow; + + /* swap more bytes if big endian */ + for(i=0; i<4 && bigEndian; i++) + newHashParts[i] = swapInt(newHashParts[i]); + + /* make a string of the parts */ + newHash = (unsigned char *)newHashParts; + + /* convert to hexadecimal */ + for (i=0; i<16; i++) + { + output[i*2]=hexChars[(newHash[i]>>4)&0xF]; + output[(i*2)+1]=hexChars[newHash[i]&0xF]; + } + + output[32]='\0'; + +// gaim_debug_info("MaYuan","chl output{%s}\n",output); +} +