Commit 77aa5844 authored by Matthieu Tanon's avatar Matthieu Tanon
Browse files

Implement encrypted file transfer for LIMEv2

parent a84e8227
......@@ -51,10 +51,10 @@ public:
virtual ChatMessageModifier::Result processOutgoingMessage (const std::shared_ptr<ChatMessage> &message, int &errorCode) { return ChatMessageModifier::Result::Skipped; }
virtual ChatMessageModifier::Result processIncomingMessage (const std::shared_ptr<ChatMessage> &message, int &errorCode) { return ChatMessageModifier::Result::Skipped; }
virtual void update (LinphoneConfig *lpconfig) {};
virtual bool encryptionEnabledForFileTransferCb (const std::shared_ptr<AbstractChatRoom> &ChatRoom) { return false; }
virtual void generateFileTransferKeyCb (const std::shared_ptr<AbstractChatRoom> &ChatRoom, const std::shared_ptr<ChatMessage> &message) {}
virtual int downloadingFileCb (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decryptedBuffer) { return 0; }
virtual int uploadingFileCb (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *encryptedBuffer) { return 0; }
virtual bool encryptionEnabledForFileTransfer (const std::shared_ptr<AbstractChatRoom> &ChatRoom) { return false; }
virtual void generateFileTransferKey (const std::shared_ptr<AbstractChatRoom> &ChatRoom, const std::shared_ptr<ChatMessage> &message) {}
virtual int downloadingFile (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decryptedBuffer) { return 0; }
virtual int uploadingFile (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t *size, uint8_t *encryptedBuffer) { return 0; }
virtual EncryptionEngineListener::EngineType getEngineType () { return EngineType::Undefined; }
virtual AbstractChatRoom::SecurityLevel getSecurityLevel (std::string deviceId) const { return AbstractChatRoom::SecurityLevel::Unsafe; }
......
......@@ -31,10 +31,7 @@ using namespace std;
LINPHONE_BEGIN_NAMESPACE
ChatMessageModifier::Result LimeBackwardsCompatible::processOutgoingMessage(
const shared_ptr<ChatMessage> &message,
int &errorCode
) {
ChatMessageModifier::Result LimeBackwardsCompatible::processOutgoingMessage (const shared_ptr<ChatMessage> &message, int &errorCode) {
shared_ptr<AbstractChatRoom> chatRoom = message->getChatRoom();
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(chatRoom->getCore()->getCCore());
if (!imee)
......@@ -62,10 +59,7 @@ ChatMessageModifier::Result LimeBackwardsCompatible::processOutgoingMessage(
return ChatMessageModifier::Result::Done;
}
ChatMessageModifier::Result LimeBackwardsCompatible::processIncomingMessage(
const shared_ptr<ChatMessage> &message,
int &errorCode
) {
ChatMessageModifier::Result LimeBackwardsCompatible::processIncomingMessage (const shared_ptr<ChatMessage> &message, int &errorCode) {
shared_ptr<AbstractChatRoom> chatRoom = message->getChatRoom();
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(chatRoom->getCore()->getCCore());
if (!imee)
......@@ -93,9 +87,7 @@ ChatMessageModifier::Result LimeBackwardsCompatible::processIncomingMessage(
return ChatMessageModifier::Result::Done;
}
bool LimeBackwardsCompatible::encryptionEnabledForFileTransferCb(
const shared_ptr<AbstractChatRoom> &chatRoom
) {
bool LimeBackwardsCompatible::encryptionEnabledForFileTransfer (const shared_ptr<AbstractChatRoom> &chatRoom) {
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(chatRoom->getCore()->getCCore());
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb is_encryption_enabled_for_file_transfer_cb =
......@@ -106,10 +98,7 @@ bool LimeBackwardsCompatible::encryptionEnabledForFileTransferCb(
return false;
}
void LimeBackwardsCompatible::generateFileTransferKeyCb(
const shared_ptr<AbstractChatRoom> &chatRoom,
const shared_ptr<ChatMessage> &message
) {
void LimeBackwardsCompatible::generateFileTransferKey (const shared_ptr<AbstractChatRoom> &chatRoom, const shared_ptr<ChatMessage> &message) {
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(chatRoom->getCore()->getCCore());
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb generate_file_transfer_key_cb =
......@@ -119,13 +108,7 @@ void LimeBackwardsCompatible::generateFileTransferKeyCb(
}
}
int LimeBackwardsCompatible::downloadingFileCb(
const shared_ptr<ChatMessage> &message,
size_t offset,
const uint8_t *buffer,
size_t size,
uint8_t *decryptedBuffer
) {
int LimeBackwardsCompatible::downloadingFile (const shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decryptedBuffer) {
shared_ptr<AbstractChatRoom> chatRoom = message->getChatRoom();
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(chatRoom->getCore()->getCCore());
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
......@@ -136,19 +119,13 @@ int LimeBackwardsCompatible::downloadingFileCb(
return -1;
}
int LimeBackwardsCompatible::uploadingFileCb(
const shared_ptr<ChatMessage> &message,
size_t offset,
const uint8_t *buffer,
size_t size,
uint8_t *encryptedBuffer
) {
int LimeBackwardsCompatible::uploadingFile (const shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t *size, uint8_t *encryptedBuffer) {
shared_ptr<AbstractChatRoom> chatRoom = message->getChatRoom();
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(chatRoom->getCore()->getCCore());
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineCbsUploadingFileCb cb_process_uploading_file = linphone_im_encryption_engine_cbs_get_process_uploading_file(imee_cbs);
if (cb_process_uploading_file) {
return cb_process_uploading_file(imee, L_GET_C_BACK_PTR(message), offset, buffer, &size, encryptedBuffer);
return cb_process_uploading_file(imee, L_GET_C_BACK_PTR(message), offset, buffer, size, encryptedBuffer);
}
return -1;
}
......
......@@ -30,10 +30,10 @@ class LimeBackwardsCompatible : public EncryptionEngineListener {
public:
ChatMessageModifier::Result processIncomingMessage (const std::shared_ptr<ChatMessage> &message, int &errorCode) override;
ChatMessageModifier::Result processOutgoingMessage (const std::shared_ptr<ChatMessage> &message, int &errorCode) override;
bool encryptionEnabledForFileTransferCb (const std::shared_ptr<AbstractChatRoom> &ChatRoom) override;
void generateFileTransferKeyCb (const std::shared_ptr<AbstractChatRoom> &ChatRoom, const std::shared_ptr<ChatMessage> &message) override;
int downloadingFileCb (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decrypted_buffer) override;
int uploadingFileCb (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *encrypted_buffer) override;
bool encryptionEnabledForFileTransfer (const std::shared_ptr<AbstractChatRoom> &ChatRoom) override;
void generateFileTransferKey (const std::shared_ptr<AbstractChatRoom> &ChatRoom, const std::shared_ptr<ChatMessage> &message) override;
int downloadingFile (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decrypted_buffer) override;
int uploadingFile (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t *size, uint8_t *encrypted_buffer) override;
};
LINPHONE_END_NAMESPACE
......
......@@ -23,9 +23,13 @@
#include "content/header/header-param.h"
#include "conference/participant-p.h"
#include "conference/participant-device.h"
#include "c-wrapper/c-wrapper.h"
#include "lime-v2.h"
#include "private.h"
// TODO remove me
#include "lime.h"
using namespace std;
LINPHONE_BEGIN_NAMESPACE
......@@ -341,22 +345,81 @@ void LimeV2::update (LinphoneConfig *lpconfig) {
lp_config_set_int(lpconfig, "misc", "last_lime_update_time", (int)lastLimeUpdate);
}
bool LimeV2::encryptionEnabledForFileTransferCb (const shared_ptr<AbstractChatRoom> &chatRoom) {
// TODO Work in progress
return false;
bool LimeV2::encryptionEnabledForFileTransfer (const shared_ptr<AbstractChatRoom> &chatRoom) {
return true;
}
void LimeV2::generateFileTransferKeyCb (const shared_ptr<AbstractChatRoom> &chatRoom, const shared_ptr<ChatMessage> &message) {
// TODO Work in progress
void LimeV2::generateFileTransferKey (const shared_ptr<AbstractChatRoom> &chatRoom, const shared_ptr<ChatMessage> &message) {
int FILE_TRANSFER_KEY_SIZE = 32; // TODO #define or get it from a config
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);
for (Content *content : message->getContents()) {
if (content->isFileTransfer()) {
FileTransferContent *fileTransferContent = dynamic_cast<FileTransferContent *>(content); // TODO could static_cast
fileTransferContent->setFileKey(keyBuffer, FILE_TRANSFER_KEY_SIZE);
return;
}
}
}
int LimeV2::downloadingFileCb (const shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decrypted_buffer) {
// TODO Work in progress
int LimeV2::downloadingFile (const shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decrypted_buffer) {
const Content *content = message->getPrivate()->getFileTransferContent();
if (!content)
return -1;
const FileTransferContent *fileTransferContent = dynamic_cast<const FileTransferContent *>(content); // TODO could static_cast
const char *fileKey = fileTransferContent->getFileKey().data();
if (!fileKey)
return -1;
if (!buffer || size == 0)
return lime_decryptFile(linphone_content_get_cryptoContext_address(L_GET_C_BACK_PTR(content)), NULL, 0, NULL, NULL);
return lime_decryptFile(
linphone_content_get_cryptoContext_address(L_GET_C_BACK_PTR(content)),
(unsigned char *)fileKey,
size,
(char *)decrypted_buffer,
(char *)buffer
);
return 0;
}
int LimeV2::uploadingFileCb (const shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *encrypted_buffer) {
// TODO Work in progress
int LimeV2::uploadingFile (const shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t *size, uint8_t *encrypted_buffer) {
const Content *content = message->getPrivate()->getFileTransferContent();
if (!content)
return -1;
const FileTransferContent *fileTransferContent = dynamic_cast<const FileTransferContent *>(content);
const char *fileKey = fileTransferContent->getFileKey().data();
if (!fileKey)
return -1;
if (!buffer || *size == 0)
return lime_encryptFile(linphone_content_get_cryptoContext_address(L_GET_C_BACK_PTR(content)), NULL, 0, NULL, NULL);
size_t file_size = fileTransferContent->getFileSize();
if (file_size == 0) {
ms_warning("File size has not been set, encryption will fail if not done in one step (if file is larger than 16K)");
} else if (offset + *size < file_size) {
*size -= (*size % 16);
}
lInfo() << "Uploading encrypted file " << fileTransferContent->getFileName() << " " << *size << " out of " << file_size;
return lime_encryptFile(
linphone_content_get_cryptoContext_address(L_GET_C_BACK_PTR(content)),
(unsigned char *)fileKey,
*size,
(char *)buffer,
(char *)encrypted_buffer
);
return 0;
}
......
......@@ -77,10 +77,10 @@ public:
ChatMessageModifier::Result processIncomingMessage (const std::shared_ptr<ChatMessage> &message, int &errorCode) override;
ChatMessageModifier::Result processOutgoingMessage (const std::shared_ptr<ChatMessage> &message, int &errorCode) override;
void update (LinphoneConfig *lpconfig) override;
bool encryptionEnabledForFileTransferCb (const std::shared_ptr<AbstractChatRoom> &ChatRoom) override;
void generateFileTransferKeyCb (const std::shared_ptr<AbstractChatRoom> &ChatRoom, const std::shared_ptr<ChatMessage> &message) override;
int downloadingFileCb (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decrypted_buffer) override;
int uploadingFileCb (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *encrypted_buffer) override;
bool encryptionEnabledForFileTransfer (const std::shared_ptr<AbstractChatRoom> &ChatRoom) override;
void generateFileTransferKey (const std::shared_ptr<AbstractChatRoom> &ChatRoom, const std::shared_ptr<ChatMessage> &message) override;
int downloadingFile (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decrypted_buffer) override;
int uploadingFile (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t *size, uint8_t *encrypted_buffer) override;
EncryptionEngineListener::EngineType getEngineType () override;
AbstractChatRoom::SecurityLevel getSecurityLevel (std::string deviceId) const override;
......
......@@ -175,11 +175,11 @@ int FileTransferChatMessageModifier::onSendBody (
}
}
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(message->getCore()->getCCore());
EncryptionEngineListener *imee = message->getCore()->getEncryptionEngine();
if (imee) {
size_t max_size = *size;
uint8_t *encrypted_buffer = (uint8_t *)ms_malloc0(max_size);
retval = message->getCore()->getEncryptionEngine()->uploadingFileCb(L_GET_CPP_PTR_FROM_C_OBJECT(msg), offset, buffer, *size, encrypted_buffer);
retval = imee->uploadingFile(L_GET_CPP_PTR_FROM_C_OBJECT(msg), offset, buffer, size, encrypted_buffer);
if (retval == 0) {
if (*size > max_size) {
lError() << "IM encryption engine process upload file callback returned a size bigger than the size of the buffer, so it will be truncated !";
......@@ -203,9 +203,9 @@ void FileTransferChatMessageModifier::onSendEnd (belle_sip_user_body_handler_t *
if (!message)
return;
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(message->getCore()->getCCore());
EncryptionEngineListener *imee = message->getCore()->getEncryptionEngine();
if (imee) {
message->getCore()->getEncryptionEngine()->uploadingFileCb(message, 0, nullptr, 0, nullptr);
imee->uploadingFile(message, 0, nullptr, 0, nullptr);
}
}
......@@ -233,16 +233,10 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h
string first_part_header;
belle_sip_body_handler_t *first_part_bh;
bool is_file_encryption_enabled = false;
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(message->getCore()->getCCore());
if (imee && message->getChatRoom()) {
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb 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(imee, L_GET_C_BACK_PTR(message->getChatRoom()));
}
}
bool isFileEncryptionEnabled = false;
EncryptionEngineListener *imee = message->getCore()->getEncryptionEngine();
if (imee)
isFileEncryptionEnabled = imee->encryptionEnabledForFileTransfer(message->getChatRoom());
FileTransferContent *fileTransferContent = new FileTransferContent();
fileTransferContent->setContentType(ContentType::FileTransfer);
......@@ -250,18 +244,12 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h
message->getPrivate()->addContent(fileTransferContent);
// shall we encrypt the file
if (is_file_encryption_enabled && message->getChatRoom()) {
if (isFileEncryptionEnabled && message->getChatRoom()) {
// 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
first_part_header = "form-data; name=\"File\"; filename=\"filename.txt\"";
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb 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(imee, L_GET_C_BACK_PTR(message->getChatRoom()), L_GET_C_BACK_PTR(message));
}
imee->generateFileTransferKey(message->getChatRoom(), message);
} else {
first_part_header = "form-data; name=\"File\"; filename=\"" + currentFileContentToTransfer->getFileName() + "\"";
}
......@@ -730,10 +718,10 @@ void FileTransferChatMessageModifier::onRecvBody (belle_sip_user_body_handler_t
return;
int retval = -1;
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(message->getCore()->getCCore());
EncryptionEngineListener *imee = message->getCore()->getEncryptionEngine();
if (imee) {
uint8_t *decrypted_buffer = (uint8_t *)ms_malloc0(size);
retval = message->getCore()->getEncryptionEngine()->downloadingFileCb(message, offset, buffer, size, decrypted_buffer);
retval = imee->downloadingFile(message, offset, buffer, size, decrypted_buffer);
if (retval == 0) {
memcpy(buffer, decrypted_buffer, size);
}
......@@ -773,9 +761,9 @@ void FileTransferChatMessageModifier::onRecvEnd (belle_sip_user_body_handler_t *
shared_ptr<Core> core = message->getCore();
int retval = -1;
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(core->getCCore());
EncryptionEngineListener *imee = message->getCore()->getEncryptionEngine();
if (imee) {
retval = core->getEncryptionEngine()->downloadingFileCb(message, 0, nullptr, 0, nullptr);
retval = imee->downloadingFile(message, 0, nullptr, 0, nullptr);
}
if (retval <= 0) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment