# HG changeset patch # User andrew.victor@mxit.com # Date 1309122202 0 # Node ID 3951afa56940a87baf32bc909acdad30eb597963 # Parent d872652ae4e42db725481c130c2fc9f21827325d Start implementing MXit secure messaging. * Decoding of transport-layer encrypted MXit messages. diff -r d872652ae4e4 -r 3951afa56940 libpurple/protocols/mxit/cipher.c --- a/libpurple/protocols/mxit/cipher.c Mon Jun 20 21:36:22 2011 +0000 +++ b/libpurple/protocols/mxit/cipher.c Sun Jun 26 21:03:22 2011 +0000 @@ -34,6 +34,7 @@ /* password encryption */ #define INITIAL_KEY "6170383452343567" #define SECRET_HEADER "" +#define ENCRYPT_HEADER "" /*------------------------------------------------------------------------ @@ -106,3 +107,62 @@ return base64; } + +/*------------------------------------------------------------------------ + * Decrypt a transport-layer encryptede message. + * + * @param session The MXit session object + * @param message The encrypted message data. + * @return The decrypted message. Must be g_free'd when no longer needed. + */ +char* mxit_decrypt_message( struct MXitSession* session, char* message ) +{ + gsize raw_len; + guchar* raw_message; + char key[64]; + int pwdlen = strlen( session->acc->password ); + char exkey[512]; + int i; + GString* decoded = NULL; + + /* remove optional header: */ + if ( strncmp( message, ENCRYPT_HEADER, strlen( ENCRYPT_HEADER ) ) == 0 ) + message += strlen( ENCRYPT_HEADER ); + + /* base64 decode the message */ + raw_message = purple_base64_decode( message, &raw_len ); + + /* build the key - Client key, appended with last 8 characters of the PIN. (no padding) */ + memset( key, 0x00, sizeof( key ) ); + memcpy( key, session->clientkey, strlen( session->clientkey ) ); + if ( pwdlen <= 8 ) + strcat( key, session->acc->password ); + else + strncat( key, session->acc->password + ( pwdlen - 8 ), 8 ); + ExpandKey( (unsigned char*) key, (unsigned char*) exkey ); + + /* decode each block */ + decoded = g_string_sized_new( raw_len ); + for ( i = 0; i < raw_len; i += 16 ) { + char block[16]; + + Decrypt( (unsigned char*) raw_message + i, (unsigned char*) exkey, (unsigned char*) block ); + g_string_append_len( decoded, block, 16 ); + } + + g_free( raw_message ); + + purple_debug_info( MXIT_PLUGIN_ID, "decrypted: '%s'\n", decoded->str ); + + /* check that the decrypted message starts with header: */ + if ( strncmp( decoded->str, SECRET_HEADER, strlen( SECRET_HEADER ) != 0 ) ) { + g_string_free( decoded, TRUE ); + return NULL; /* message could not be decoded */ + } + g_string_erase( decoded, 0, strlen( SECRET_HEADER ) ); /* remove header */ + + /* remove ISO10126 padding */ +// TODO + + return g_string_free( decoded, FALSE ); +} diff -r d872652ae4e4 -r 3951afa56940 libpurple/protocols/mxit/cipher.h --- a/libpurple/protocols/mxit/cipher.h Mon Jun 20 21:36:22 2011 +0000 +++ b/libpurple/protocols/mxit/cipher.h Sun Jun 26 21:03:22 2011 +0000 @@ -32,5 +32,7 @@ char* mxit_encrypt_password( struct MXitSession* session ); +char* mxit_decrypt_message( struct MXitSession* session, char* message ); + #endif /* _MXIT_CIPHER_H_ */ diff -r d872652ae4e4 -r 3951afa56940 libpurple/protocols/mxit/protocol.c --- a/libpurple/protocols/mxit/protocol.c Mon Jun 20 21:36:22 2011 +0000 +++ b/libpurple/protocols/mxit/protocol.c Sun Jun 26 21:03:22 2011 +0000 @@ -1516,6 +1516,7 @@ { struct RXMsgData* mx = NULL; char* message = NULL; + char* sender = NULL; int msglen = 0; int msgflags = 0; int msgtype = 0; @@ -1529,10 +1530,11 @@ msglen = strlen( message ); /* strip off dummy domain */ - mxit_strip_domain( records[0]->fields[0]->data ); + sender = records[0]->fields[0]->data; + mxit_strip_domain( sender ); #ifdef DEBUG_PROTOCOL - purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", records[0]->fields[0]->data ); + purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender ); #endif /* decode message flags (if any) */ @@ -1540,33 +1542,42 @@ msgflags = atoi( records[0]->fields[4]->data ); msgtype = atoi( records[0]->fields[2]->data ); - if ( msgflags & CP_MSG_ENCRYPTED ) { - /* this is an encrypted message. we do not currently support those so ignore it */ + if ( msgflags & CP_MSG_PWD_ENCRYPTED ) { + /* this is a password encrypted message. we do not currently support those so ignore it */ PurpleBuddy* buddy; const char* name; char msg[128]; - buddy = purple_find_buddy( session->acc, records[0]->fields[0]->data ); + buddy = purple_find_buddy( session->acc, sender ); if ( buddy ) name = purple_buddy_get_alias( buddy ); else - name = records[0]->fields[0]->data; + name = sender; g_snprintf( msg, sizeof( msg ), _( "%s sent you an encrypted message, but it is not supported on this client." ), name ); mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), msg ); return; } + else if ( msgflags & CP_MSG_TL_ENCRYPTED ) { + /* this is a transport-layer encrypted message. */ + message = mxit_decrypt_message( session, message ); + if ( !message ) { + /* could not be decrypted */ + serv_got_im( session->con, sender, _( "An encrypted message was received which could not be decrypted." ), PURPLE_MESSAGE_ERROR, time( NULL ) ); + return; + } + } if ( msgflags & CP_MSG_NOTIFY_DELIVERY ) { /* delivery notification is requested */ if ( records[0]->fcount >= 4 ) - mxit_send_msgevent( session, records[0]->fields[0]->data, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED ); + mxit_send_msgevent( session, sender, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED ); } /* create and initialise new markup struct */ mx = g_new0( struct RXMsgData, 1 ); mx->msg = g_string_sized_new( msglen ); mx->session = session; - mx->from = g_strdup( records[0]->fields[0]->data ); + mx->from = g_strdup( sender ); mx->timestamp = atoi( records[0]->fields[1]->data ); mx->got_img = FALSE; mx->chatid = -1; @@ -1597,6 +1608,10 @@ * so the image received callback function will eventually display * the message. */ } + + /* cleanup */ + if ( msgflags & CP_MSG_TL_ENCRYPTED ) + g_free( message ); } diff -r d872652ae4e4 -r 3951afa56940 libpurple/protocols/mxit/protocol.h --- a/libpurple/protocols/mxit/protocol.h Mon Jun 20 21:36:22 2011 +0000 +++ b/libpurple/protocols/mxit/protocol.h Sun Jun 26 21:03:22 2011 +0000 @@ -155,7 +155,10 @@ /* message flags */ #define CP_MSG_NOTIFY_DELIVERY 0x0002 /* request delivery notification */ #define CP_MSG_NOTIFY_READ 0x0004 /* request read notification */ -#define CP_MSG_ENCRYPTED 0x0010 /* message is encrypted */ +#define CP_MSG_PWD_ENCRYPTED 0x0010 /* message is password encrypted */ +#define CP_MSG_TL_ENCRYPTED 0x0020 /* message is transport encrypted */ +#define CP_MSG_RPLY_PWD_ENCRYPT 0x0040 /* reply should be password encrypted */ +#define CP_MSG_RPLY_TL_ENCRYPT 0x0080 /* reply should be transport encrypted */ #define CP_MSG_MARKUP 0x0200 /* message may contain markup */ #define CP_MSG_EMOTICON 0x0400 /* message may contain custom emoticons */