libpurple/protocols/mxit/cipher.c

branch
mxit
changeset 32180
766c92a94b04
parent 32177
b4729e4322f3
child 32182
fdf3af8def04
equal deleted inserted replaced
31999:8654d04cb094 32180:766c92a94b04
1 /* 1 /*
2 * MXit Protocol libPurple Plugin 2 * MXit Protocol libPurple Plugin
3 * 3 *
4 * -- user password encryption -- 4 * -- encryption --
5 * 5 *
6 * Pieter Loubser <libpurple@mxit.com> 6 * Pieter Loubser <libpurple@mxit.com>
7 * 7 *
8 * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. 8 * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
9 * <http://www.mxitlifestyle.com> 9 * <http://www.mxitlifestyle.com>
29 #include "mxit.h" 29 #include "mxit.h"
30 #include "cipher.h" 30 #include "cipher.h"
31 #include "aes.h" 31 #include "aes.h"
32 32
33 33
34 /* password encryption */ 34 /* encryption */
35 #define INITIAL_KEY "6170383452343567" 35 #define INITIAL_KEY "6170383452343567"
36 #define SECRET_HEADER "<mxit/>" 36 #define SECRET_HEADER "<mxit/>"
37 #define ENCRYPT_HEADER "<mxitencrypted ver=\"5.2\"/>" 37 #define ENCRYPT_HEADER "<mxitencrypted ver=\"5.2\"/>"
38 38
39 39
40 /*------------------------------------------------------------------------ 40 /*------------------------------------------------------------------------
41 * Pad the secret data using ISO10126 Padding. 41 * Add ISO10126 Padding to the data.
42 * 42 *
43 * @param secret The data to pad (caller must ensure buffer has enough space for padding) 43 * @param data The data to pad.
44 * @return The total number of 128-bit blocks used 44 */
45 */ 45 static void padding_add( GString* data )
46 static int pad_secret_data( char* secret ) 46 {
47 { 47 unsigned int blocks = ( data->len / 16 ) + 1;
48 int blocks = 0; 48 unsigned int padding = ( blocks * 16 ) - data->len;
49 int passlen; 49
50 int padding; 50 g_string_set_size( data, blocks * 16 );
51 51 data->str[data->len - 1] = padding;
52 passlen = strlen( secret ); 52 }
53 blocks = ( passlen / 16 ) + 1; 53
54 padding = ( blocks * 16 ) - passlen; 54
55 secret[passlen] = 0x50; 55 /*------------------------------------------------------------------------
56 secret[(blocks * 16) - 1] = padding; 56 * Remove ISO10126 Padding from the data.
57 57 *
58 return blocks; 58 * @param data The data from which to remove padding.
59 */
60 static void padding_remove( GString* data )
61 {
62 unsigned int padding;
63
64 if ( data->len == 0 )
65 return;
66
67 padding = data->str[data->len - 1];
68 g_string_truncate( data, data->len - padding );
69 }
70
71
72 /*------------------------------------------------------------------------
73 * Generate the Transport-Layer crypto key.
74 * (Note: this function is not-thread safe)
75 *
76 * @param session The MXit Session object
77 * @return The transport-layer crypto key.
78 */
79 static char* transport_layer_key( struct MXitSession* session )
80 {
81 static char key[16 + 1];
82 int passlen = strlen( session->acc->password );
83
84 /* initialize with initial key */
85 g_strlcpy( key, INITIAL_KEY, sizeof( key ) );
86
87 /* client key (8 bytes) */
88 memcpy( key, session->clientkey, strlen( session->clientkey ) );
89
90 /* add last 8 characters of the PIN (no padding if less characters) */
91 if ( passlen <= 8 )
92 memcpy( key + 8, session->acc->password, passlen );
93 else
94 memcpy( key + 8, session->acc->password + ( passlen - 8 ), 8 );
95
96 return key;
59 } 97 }
60 98
61 99
62 /*------------------------------------------------------------------------ 100 /*------------------------------------------------------------------------
63 * Encrypt the user's cleartext password using the AES 128-bit (ECB) 101 * Encrypt the user's cleartext password using the AES 128-bit (ECB)
66 * @param session The MXit session object 104 * @param session The MXit session object
67 * @return The encrypted & encoded password. Must be g_free'd when no longer needed. 105 * @return The encrypted & encoded password. Must be g_free'd when no longer needed.
68 */ 106 */
69 char* mxit_encrypt_password( struct MXitSession* session ) 107 char* mxit_encrypt_password( struct MXitSession* session )
70 { 108 {
71 char key[64]; 109 char key[16 + 1];
72 char exkey[512]; 110 char exkey[512];
73 char pass[64]; 111 GString* pass = NULL;
74 char encrypted[64]; 112 char encrypted[64];
75 char* base64; 113 char* base64;
76 int blocks;
77 int size;
78 int i; 114 int i;
79 115
80 purple_debug_info( MXIT_PLUGIN_ID, "mxit_encrypt_password\n" ); 116 purple_debug_info( MXIT_PLUGIN_ID, "mxit_encrypt_password\n" );
81 117
82 memset( encrypted, 0x00, sizeof( encrypted ) ); 118 memset( encrypted, 0x00, sizeof( encrypted ) );
83 memset( exkey, 0x00, sizeof( exkey ) );
84 memset( pass, 0x58, sizeof( pass ) );
85 pass[sizeof( pass ) - 1] = '\0';
86 119
87 /* build the custom AES encryption key */ 120 /* build the custom AES encryption key */
88 g_strlcpy( key, INITIAL_KEY, sizeof( key ) ); 121 g_strlcpy( key, INITIAL_KEY, sizeof( key ) );
89 memcpy( key, session->clientkey, strlen( session->clientkey ) ); 122 memcpy( key, session->clientkey, strlen( session->clientkey ) );
90 ExpandKey( (unsigned char*) key, (unsigned char*) exkey ); 123 ExpandKey( (unsigned char*) key, (unsigned char*) exkey );
100 /* now encrypt the password. we encrypt each block separately (ECB mode) */ 133 /* now encrypt the password. we encrypt each block separately (ECB mode) */
101 for ( i = 0; i < size; i += 16 ) 134 for ( i = 0; i < size; i += 16 )
102 Encrypt( (unsigned char*) pass + i, (unsigned char*) exkey, (unsigned char*) encrypted + i ); 135 Encrypt( (unsigned char*) pass + i, (unsigned char*) exkey, (unsigned char*) encrypted + i );
103 136
104 /* now base64 encode the encrypted password */ 137 /* now base64 encode the encrypted password */
105 base64 = purple_base64_encode( (unsigned char*) encrypted, size ); 138 base64 = purple_base64_encode( (unsigned char*) encrypted, pass->len );
139
140 g_string_free( pass, TRUE );
106 141
107 return base64; 142 return base64;
108 } 143 }
109 144
110 145

mercurial