| 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 |