Added encryption callbacks for file upload in im encryption engine

This commit is contained in:
Sylvain Berfini 2016-11-10 15:44:32 +01:00
parent 3214b4371a
commit 395c81f69a
7 changed files with 153 additions and 65 deletions

View file

@ -578,18 +578,16 @@ LinphoneReason linphone_core_message_received(LinphoneCore *lc, SalOp *op, const
file_url = xmlGetProp(cur, (const xmlChar *)"url");
}
if (!xmlStrcmp(cur->name,
(const xmlChar *)"file-key")) { /* there is a key in the msg: file has
been encrypted */
if (!xmlStrcmp(cur->name, (const xmlChar *)"file-key")) {
/* there is a key in the msg: file has been encrypted */
/* convert the key from base 64 */
xmlChar *keyb64 = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1);
size_t keyLength = b64_decode((char *)keyb64, strlen((char *)keyb64), NULL, 0);
uint8_t *keyBuffer = (uint8_t *)malloc(keyLength);
/* decode the key into local key buffer */
b64_decode((char *)keyb64, strlen((char *)keyb64), keyBuffer, keyLength);
linphone_content_set_key(
msg->file_transfer_information, (char *)keyBuffer,
strlen((char *)keyBuffer)); /* duplicate key value into the linphone content private structure */
linphone_content_set_key(msg->file_transfer_information, (char *)keyBuffer, strlen((char *)keyBuffer));
/* duplicate key value into the linphone content private structure */
xmlFree(keyb64);
free(keyBuffer);
}

View file

@ -27,8 +27,6 @@
#include "lime.h"
#include "ortp/b64.h"
#define FILE_TRANSFER_KEY_SIZE 32
static bool_t file_transfer_in_progress_and_valid(LinphoneChatMessage* msg) {
return (msg->chat_room && msg->chat_room->lc && msg->http_request && !belle_http_request_is_cancelled(msg->http_request));
}
@ -98,7 +96,8 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_
void *data, size_t offset, uint8_t *buffer, size_t *size) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
LinphoneCore *lc = NULL;
char *buf = (char *)buffer;
LinphoneImEncryptionEngine *imee = NULL;
int retval = -1;
if (!file_transfer_in_progress_and_valid(msg)) {
if (msg->http_request) {
@ -111,50 +110,43 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_
lc = msg->chat_room->lc;
/* if we've not reach the end of file yet, ask for more data*/
if (offset < linphone_content_get_size(msg->file_transfer_information)) {
char *plainBuffer = NULL;
if (linphone_content_get_key(msg->file_transfer_information) !=
NULL) { /* if we have a key to cipher the msg, use it! */
/* if this chunk is not the last one, the lenght must be a multiple of block cipher size(16 bytes)*/
if (offset + *size < linphone_content_get_size(msg->file_transfer_information)) {
*size -= (*size % 16);
}
plainBuffer = (char *)ms_malloc0(*size);
}
char *plainBuffer = (char *)ms_malloc0(*size);
/* get data from call back */
if (linphone_chat_message_cbs_get_file_transfer_send(msg->callbacks)) {
LinphoneBuffer *lb = linphone_chat_message_cbs_get_file_transfer_send(msg->callbacks)(
msg, msg->file_transfer_information, offset, *size);
LinphoneChatMessageCbsFileTransferSendCb file_transfer_send_cb = linphone_chat_message_cbs_get_file_transfer_send(msg->callbacks);
if (file_transfer_send_cb) {
LinphoneBuffer *lb = file_transfer_send_cb(msg, msg->file_transfer_information, offset, *size);
if (lb == NULL) {
*size = 0;
} else {
*size = linphone_buffer_get_size(lb);
memcpy(plainBuffer ? plainBuffer : buf, linphone_buffer_get_content(lb), *size);
memcpy(plainBuffer, linphone_buffer_get_content(lb), *size);
linphone_buffer_unref(lb);
}
} else {
/* Legacy */
linphone_core_notify_file_transfer_send(lc, msg, msg->file_transfer_information,
plainBuffer ? plainBuffer : buf, size);
linphone_core_notify_file_transfer_send(lc, msg, msg->file_transfer_information, plainBuffer, size);
}
if (linphone_content_get_key(msg->file_transfer_information) !=
NULL) { /* if we have a key to cipher the msg, use it! */
lime_encryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information),
(unsigned char *)linphone_content_get_key(msg->file_transfer_information), *size,
plainBuffer, (char *)buffer);
ms_free(plainBuffer);
/* check if we reach the end of file */
if (offset + *size >= linphone_content_get_size(msg->file_transfer_information)) {
/* conclude file ciphering by calling it context with a zero size */
lime_encryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), NULL, 0,
NULL, NULL);
imee = linphone_core_get_im_encryption_engine(lc);
if (imee) {
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineUploadingFileCb cb_process_uploading_file = linphone_im_encryption_engine_cbs_get_process_uploading_file(imee_cbs);
if (cb_process_uploading_file) {
retval = cb_process_uploading_file(lc, msg, offset, plainBuffer, size, (char *)buffer);
if (offset + *size >= linphone_content_get_size(msg->file_transfer_information)) {
/* conclude file ciphering by calling it context with a zero size */
cb_process_uploading_file(lc, msg, 0, NULL, NULL, NULL);
}
}
}
if (retval < 0) {
memcpy(buffer, plainBuffer, *size);
}
ms_free(plainBuffer);
}
return BELLE_SIP_CONTINUE;
return retval <= 0 ? BELLE_SIP_CONTINUE : BELLE_SIP_STOP;
}
static void linphone_chat_message_process_response_from_post_file(void *data,
@ -176,21 +168,27 @@ static void linphone_chat_message_process_response_from_post_file(void *data,
char *first_part_header;
belle_sip_body_handler_t *first_part_bh;
bool_t is_file_encryption_enabled = FALSE;
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(msg->chat_room->lc);
if (imee) {
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineIsEncryptionEnabledForFileTransferCb is_encryption_enabled_for_file_transfer_cb =
linphone_im_encryption_engine_cbs_get_is_encryption_enabled_for_file_transfer(imee_cbs);
if (is_encryption_enabled_for_file_transfer_cb) {
is_file_encryption_enabled = is_encryption_enabled_for_file_transfer_cb(msg->chat_room->lc, msg->chat_room);
}
}
/* shall we encrypt the file */
if (linphone_chat_room_lime_available(msg->chat_room) &&
linphone_core_lime_for_file_sharing_enabled(msg->chat_room->lc)) {
char keyBuffer
[FILE_TRANSFER_KEY_SIZE]; /* temporary storage of generated key: 192 bits of key + 64 bits of
initial vector */
/* generate a random 192 bits key + 64 bits of initial vector and store it into the
* file_transfer_information->key field of the msg */
sal_get_random_bytes((unsigned char *)keyBuffer, FILE_TRANSFER_KEY_SIZE);
linphone_content_set_key(
msg->file_transfer_information, keyBuffer,
FILE_TRANSFER_KEY_SIZE); /* key is duplicated in the content private structure */
if (is_file_encryption_enabled) {
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineGenerateFileTransferKeyCb generate_file_transfer_key_cb =
linphone_im_encryption_engine_cbs_get_generate_file_transfer_key(imee_cbs);
if (generate_file_transfer_key_cb) {
generate_file_transfer_key_cb(msg->chat_room->lc, msg->chat_room, msg);
}
/* temporary storage for the Content-disposition header value : use a generic filename to not leak it
* Actual filename stored in msg->file_transfer_information->name will be set in encrypted msg
* sended to the */
* Actual filename stored in msg->file_transfer_information->name will be set in encrypted msg
* sended to the */
first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"filename.txt\"");
} else {
/* temporary storage for the Content-disposition header value */
@ -201,8 +199,7 @@ static void linphone_chat_message_process_response_from_post_file(void *data,
/* create a user body handler to take care of the file and add the content disposition and content-type
* headers */
if (msg->file_transfer_filepath != NULL) {
first_part_bh =
(belle_sip_body_handler_t *)belle_sip_file_body_handler_new(msg->file_transfer_filepath, NULL, msg);
first_part_bh = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(msg->file_transfer_filepath, NULL, msg);
} else if (linphone_content_get_buffer(msg->file_transfer_information) != NULL) {
first_part_bh = (belle_sip_body_handler_t *)belle_sip_memory_body_handler_new_from_buffer(
linphone_content_get_buffer(msg->file_transfer_information),
@ -233,7 +230,8 @@ static void linphone_chat_message_process_response_from_post_file(void *data,
if (body && strlen(body) > 0) {
/* if we have an encryption key for the file, we must insert it into the msg and restore the correct
* filename */
if (linphone_content_get_key(msg->file_transfer_information) != NULL) {
const char *content_key = linphone_content_get_key(msg->file_transfer_information);
if (content_key != NULL) {
/* parse the msg body */
xmlDocPtr xmlMessageBody = xmlParseDoc((const xmlChar *)body);
@ -252,12 +250,11 @@ static void linphone_chat_message_process_response_from_post_file(void *data,
->xmlChildrenNode; /* need to parse the children node to update the file-name
one */
/* convert key to base64 */
size_t b64Size = b64_encode(NULL, FILE_TRANSFER_KEY_SIZE, NULL, 0);
size_t b64Size = b64_encode(NULL, strlen(content_key), NULL, 0);
char *keyb64 = (char *)ms_malloc0(b64Size + 1);
int xmlStringLength;
b64Size = b64_encode(linphone_content_get_key(msg->file_transfer_information),
FILE_TRANSFER_KEY_SIZE, keyb64, b64Size);
b64Size = b64_encode(content_key, strlen(content_key), keyb64, b64Size);
keyb64[b64Size] = '\0'; /* libxml need a null terminated string */
/* add the node containing the key to the file-info node */
@ -354,7 +351,7 @@ static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineDownloadingFileCb cb_process_downloading_file = linphone_im_encryption_engine_cbs_get_process_downloading_file(imee_cbs);
if (cb_process_downloading_file) {
retval = cb_process_downloading_file(lc, msg, (const char *)buffer, size, &decrypted_buffer);
retval = cb_process_downloading_file(lc, msg, (const char *)buffer, size, decrypted_buffer);
}
}
@ -467,7 +464,7 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle
retval = (int)bctbx_file_read(encrypted_file, encrypted_content, encrypted_file_size, 0);
bctbx_file_close(encrypted_file);
if (retval != BCTBX_VFS_ERROR && retval == (int)encrypted_file_size) {
retval = cb_process_downloading_file(lc, msg, encrypted_content, encrypted_file_size, &decrypted_content);
retval = cb_process_downloading_file(lc, msg, encrypted_content, encrypted_file_size, decrypted_content);
cb_process_downloading_file(lc, msg, NULL, 0, NULL);
decrypted_file = bctbx_file_open(vfs, msg->file_transfer_filepath, "w");
bctbx_file_write(decrypted_file, decrypted_content, encrypted_file_size, 0);

View file

@ -23,8 +23,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
struct _LinphoneImEncryptionEngineCbs {
void *user_data;
LinphoneImEncryptionEngineIncomingMessageCb process_incoming_message;
LinphoneImEncryptionEngineDownloadingFileCb process_downlading_file;
LinphoneImEncryptionEngineOutgoingMessageCb process_outgoing_message;
LinphoneImEncryptionEngineIsEncryptionEnabledForFileTransferCb is_encryption_enabled_for_file_transfer;
LinphoneImEncryptionEngineGenerateFileTransferKeyCb generate_file_transfer_key;
LinphoneImEncryptionEngineDownloadingFileCb process_downlading_file;
LinphoneImEncryptionEngineUploadingFileCb process_uploading_file;
};
struct _LinphoneImEncryptionEngine {
@ -94,4 +97,28 @@ LinphoneImEncryptionEngineDownloadingFileCb linphone_im_encryption_engine_cbs_ge
void linphone_im_encryption_engine_cbs_set_process_downloading_file(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineDownloadingFileCb cb) {
cbs->process_downlading_file = cb;
}
LinphoneImEncryptionEngineUploadingFileCb linphone_im_encryption_engine_cbs_get_process_uploading_file(LinphoneImEncryptionEngineCbs *cbs) {
return cbs->process_uploading_file;
}
void linphone_im_encryption_engine_cbs_set_process_uploading_file(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineUploadingFileCb cb) {
cbs->process_uploading_file = cb;
}
LinphoneImEncryptionEngineIsEncryptionEnabledForFileTransferCb linphone_im_encryption_engine_cbs_get_is_encryption_enabled_for_file_transfer(LinphoneImEncryptionEngineCbs *cbs) {
return cbs->is_encryption_enabled_for_file_transfer;
}
void linphone_im_encryption_engine_cbs_set_is_encryption_enabled_for_file_transfer(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineIsEncryptionEnabledForFileTransferCb cb) {
cbs->is_encryption_enabled_for_file_transfer = cb;
}
LinphoneImEncryptionEngineGenerateFileTransferKeyCb linphone_im_encryption_engine_cbs_get_generate_file_transfer_key(LinphoneImEncryptionEngineCbs *cbs) {
return cbs->generate_file_transfer_key;
}
void linphone_im_encryption_engine_cbs_set_generate_file_transfer_key(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineGenerateFileTransferKeyCb cb) {
cbs->generate_file_transfer_key = cb;
}

View file

@ -30,7 +30,13 @@ typedef int (*LinphoneImEncryptionEngineIncomingMessageCb)(LinphoneCore* lc, Lin
typedef int (*LinphoneImEncryptionEngineOutgoingMessageCb)(LinphoneCore* lc, LinphoneChatRoom *room, LinphoneChatMessage *msg);
typedef int (*LinphoneImEncryptionEngineDownloadingFileCb)(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char **decrypted_buffer);
typedef bool_t (*LinphoneImEncryptionEngineIsEncryptionEnabledForFileTransferCb)(LinphoneCore *lc, LinphoneChatRoom *room);
typedef void (*LinphoneImEncryptionEngineGenerateFileTransferKeyCb)(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg);
typedef int (*LinphoneImEncryptionEngineDownloadingFileCb)(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char *decrypted_buffer);
typedef int (*LinphoneImEncryptionEngineUploadingFileCb)(LinphoneCore *lc, LinphoneChatMessage *msg, size_t offset, const char *buffer, size_t *size, char *encrypted_buffer);
typedef struct _LinphoneImEncryptionEngineCbs LinphoneImEncryptionEngineCbs;
@ -66,4 +72,16 @@ LINPHONE_PUBLIC LinphoneImEncryptionEngineDownloadingFileCb linphone_im_encrypti
LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_process_downloading_file(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineDownloadingFileCb cb);
LINPHONE_PUBLIC LinphoneImEncryptionEngineUploadingFileCb linphone_im_encryption_engine_cbs_get_process_uploading_file(LinphoneImEncryptionEngineCbs *cbs);
LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_process_uploading_file(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineUploadingFileCb cb);
LINPHONE_PUBLIC LinphoneImEncryptionEngineIsEncryptionEnabledForFileTransferCb linphone_im_encryption_engine_cbs_get_is_encryption_enabled_for_file_transfer(LinphoneImEncryptionEngineCbs *cbs);
LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_is_encryption_enabled_for_file_transfer(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineIsEncryptionEnabledForFileTransferCb cb);
LINPHONE_PUBLIC LinphoneImEncryptionEngineGenerateFileTransferKeyCb linphone_im_encryption_engine_cbs_get_generate_file_transfer_key(LinphoneImEncryptionEngineCbs *cbs);
LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_generate_file_transfer_key(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineGenerateFileTransferKeyCb cb);
#endif /* IM_ENCRYPTION_ENGINE_H */

View file

@ -26,6 +26,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "private.h"
#include "bctoolbox/crypto.h"
#define FILE_TRANSFER_KEY_SIZE 32
/**
* @brief check at runtime if LIME is available
*
@ -996,7 +998,7 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneCore* lc, Linp
return errcode;
}
int lime_im_encryption_engine_process_downloading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char **decrypted_buffer) {
int lime_im_encryption_engine_process_downloading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char *decrypted_buffer) {
if (linphone_content_get_key(msg->file_transfer_information) == NULL) return -1;
if (buffer == NULL || size == 0) {
@ -1004,10 +1006,38 @@ int lime_im_encryption_engine_process_downloading_file_cb(LinphoneCore *lc, Linp
}
return lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information),
(unsigned char *)linphone_content_get_key(msg->file_transfer_information), size, *decrypted_buffer,
(unsigned char *)linphone_content_get_key(msg->file_transfer_information), size, decrypted_buffer,
(char *)buffer);
}
int lime_im_encryption_engine_process_uploading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, size_t offset, const char *buffer, size_t *size, char *encrypted_buffer) {
if (linphone_content_get_key(msg->file_transfer_information) == NULL) return -1;
if (buffer == NULL || *size == 0) {
return lime_encryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), NULL, 0, NULL, NULL);
}
if (offset + *size < linphone_content_get_size(msg->file_transfer_information)) {
*size -= (*size % 16);
}
return lime_encryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information),
(unsigned char *)linphone_content_get_key(msg->file_transfer_information), *size,
(char *)buffer, encrypted_buffer);
}
bool_t lime_im_encryption_engine_is_file_encryption_enabled_cb(LinphoneCore *lc, LinphoneChatRoom *room) {
return linphone_chat_room_lime_available(room) && linphone_core_lime_for_file_sharing_enabled(lc);
}
void lime_im_encryption_engine_generate_file_transfer_key_cb(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg) {
char keyBuffer [FILE_TRANSFER_KEY_SIZE]; /* temporary storage of generated key: 192 bits of key + 64 bits of initial vector */
/* generate a random 192 bits key + 64 bits of initial vector and store it into the
* file_transfer_information->key field of the msg */
sal_get_random_bytes((unsigned char *)keyBuffer, FILE_TRANSFER_KEY_SIZE);
linphone_content_set_key(msg->file_transfer_information, keyBuffer, FILE_TRANSFER_KEY_SIZE); /* key is duplicated in the content private structure */
}
#else /* HAVE_LIME */
bool_t lime_is_available() { return FALSE; }
@ -1041,8 +1071,17 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, Linp
int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneCore* lc, LinphoneChatRoom *room, LinphoneChatMessage *msg) {
return 500;
}
int lime_im_encryption_engine_process_downloading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char **decrypted_buffer) {
int lime_im_encryption_engine_process_downloading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char *decrypted_buffer) {
return 500;
}
int lime_im_encryption_engine_process_uploading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, size_t offset, const char *buffer, size_t *size, char *encrypted_buffer) {
return 500;
}
bool_t lime_im_encryption_engine_is_file_encryption_enabled_cb(LinphoneCore *lc, LinphoneChatRoom *room) {
return FALSE;
}
void lime_im_encryption_engine_generate_file_transfer_key_cb(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg) {
}
#endif /* HAVE_LIME */

View file

@ -209,6 +209,12 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, Linp
int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneCore* lc, LinphoneChatRoom *room, LinphoneChatMessage *msg);
int lime_im_encryption_engine_process_downloading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char **decrypted_buffer);
int lime_im_encryption_engine_process_downloading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char *decrypted_buffer);
int lime_im_encryption_engine_process_uploading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, size_t offset, const char *buffer, size_t *size, char *encrypted_buffer);
bool_t lime_im_encryption_engine_is_file_encryption_enabled_cb(LinphoneCore *lc, LinphoneChatRoom *room);
void lime_im_encryption_engine_generate_file_transfer_key_cb(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg);
#endif /* LIME_H */

View file

@ -1957,6 +1957,9 @@ void linphone_core_enable_lime(LinphoneCore *lc, LinphoneLimeState val){
linphone_im_encryption_engine_cbs_set_process_incoming_message(cbs, lime_im_encryption_engine_process_incoming_message_cb);
linphone_im_encryption_engine_cbs_set_process_outgoing_message(cbs, lime_im_encryption_engine_process_outgoing_message_cb);
linphone_im_encryption_engine_cbs_set_process_downloading_file(cbs, lime_im_encryption_engine_process_downloading_file_cb);
linphone_im_encryption_engine_cbs_set_process_uploading_file(cbs, lime_im_encryption_engine_process_uploading_file_cb);
linphone_im_encryption_engine_cbs_set_is_encryption_enabled_for_file_transfer(cbs, lime_im_encryption_engine_is_file_encryption_enabled_cb);
linphone_im_encryption_engine_cbs_set_generate_file_transfer_key(cbs, lime_im_encryption_engine_generate_file_transfer_key_cb);
lc->im_encryption_engine = imee;
} else {
if (lc->im_encryption_engine) {