#include "encryption.h" #include #include #include #include #include #include void Encryption::createNewDeviceKeys() { initAccount(); // create account auto length = olm_create_account_random_length(account); void* memory = malloc(length); int fd = open("/dev/random", O_RDONLY); read(fd, memory, length); olm_create_account(account, memory, length); qDebug() << olm_account_last_error(account); qDebug() << "Created new device keys!"; // retrieve identity keys length = olm_account_identity_keys_length(account); char* identity_memory = (char*)malloc(length + 1); identity_memory[length] = '\0'; olm_account_identity_keys(account, identity_memory, length); QJsonDocument doc = QJsonDocument::fromJson((char*)identity_memory); identityKey = doc.object(); qDebug() << "identity keys: " << (char*)identity_memory; qDebug() << "identity keys (parsed): " << identityKey; } QString Encryption::saveDeviceKeys() { auto length = olm_pickle_account_length(account); char* identity_memory = (char*)malloc(length + 1); identity_memory[length] = '\0'; auto err = olm_pickle_account(account, "secret_key", 10, identity_memory, length); qDebug() << olm_account_last_error(account); qDebug() << err << " = " << olm_error(); qDebug() << "Save: " << identity_memory; return identity_memory; } void Encryption::loadDeviceKeys(QString bytes) { initAccount(); qDebug() << "load: " << bytes; auto length = bytes.length(); std::string key = bytes.toStdString(); olm_unpickle_account(account, "secret_key", 10, key.data(), key.length()); qDebug() << olm_account_last_error(account); length = olm_account_identity_keys_length(account); char* identity_memory = (char*)malloc(length + 1); identity_memory[length] = '\0'; olm_account_identity_keys(account, identity_memory, length); qDebug() << identity_memory; QJsonDocument doc = QJsonDocument::fromJson(identity_memory); qDebug() << doc; identityKey = doc.object(); } QJsonObject Encryption::generateOneTimeKeys(int number_of_keys) { int fd = open("/dev/random", O_RDONLY); // generate random data auto length = olm_account_generate_one_time_keys_random_length(account, number_of_keys); auto memory = malloc(length); read(fd, memory, length); olm_account_generate_one_time_keys(account, number_of_keys, memory, length); // retrieve one time keys length = olm_account_one_time_keys_length(account); memory = malloc(length); olm_account_one_time_keys(account, memory, length); olm_account_mark_keys_as_published(account); QJsonDocument doc = QJsonDocument::fromJson((char*)memory); return doc.object(); } int Encryption::getRecommendedNumberOfOneTimeKeys() { return olm_account_max_number_of_one_time_keys(account) / 2; } QString Encryption::signMessage(QString message) { auto length = olm_account_signature_length(account); void* memory = malloc(length); olm_account_sign( account, message.data(), message.length(), memory, length ); qDebug() << "Signed: " << (char*)memory; return (char*)memory; } void Encryption::initAccount() { void* memory = malloc(olm_account_size()); account = olm_account(memory); } OlmOutboundGroupSession* Encryption::beginOutboundSession() { void* outboundMemory = malloc(olm_outbound_group_session_size()); auto outboundSession = olm_outbound_group_session(outboundMemory); auto length = olm_init_outbound_group_session_random_length(outboundSession); void* memory = malloc(length); int fd = open("/dev/random", O_RDONLY); read(fd, memory, length); olm_init_outbound_group_session(outboundSession, (uint8_t*)memory, length); return outboundSession; } std::string Encryption::getGroupSessionId(OlmOutboundGroupSession* session) { auto encryptedLength = olm_outbound_group_session_id_length(session); char* encryptedMemory = (char*)malloc(encryptedLength + 1); olm_outbound_group_session_id(session, (uint8_t*)encryptedMemory, encryptedLength); return encryptedMemory; } std::string Encryption::getGroupSessionKey(OlmOutboundGroupSession* session) { auto encryptedLength = olm_outbound_group_session_key_length(session); char* encryptedMemory = (char*)malloc(encryptedLength + 1); olm_outbound_group_session_key(session, (uint8_t*)encryptedMemory, encryptedLength); return encryptedMemory; } OlmSession* Encryption::beginOutboundOlmSession(std::string identityKey, std::string oneTimeKey) { void* outboundMemory = malloc(olm_session_size()); auto outboundSession = olm_session(outboundMemory); auto length = olm_create_outbound_session_random_length(outboundSession); void* memory = malloc(length); int fd = open("/dev/random", O_RDONLY); read(fd, memory, length); olm_create_outbound_session(outboundSession, account, identityKey.data(), identityKey.length(), oneTimeKey.data(), oneTimeKey.length(), (uint8_t*)memory, length); //qDebug() << "ERR: " << olm_session_last_error(outboundSession); return outboundSession; /*size_t olm_create_outbound_session( OlmSession * session, OlmAccount * account, void const * their_identity_key, size_t their_identity_key_length, void const * their_one_time_key, size_t their_one_time_key_length, void * random, size_t random_length );*/ } std::string Encryption::getSessionId(OlmSession* session) { auto length = olm_session_id_length(session); char* memory = (char*)malloc(length + 1); memory[length] = '\0'; /** An identifier for this session. Will be the same for both ends of the * conversation. If the id buffer is too small then olm_session_last_error() * will be "OUTPUT_BUFFER_TOO_SMALL". */ olm_session_id( session, memory, length ); return memory; } std::string Encryption::encrypt(OlmSession* session, std::string message) { auto length = olm_encrypt_random_length(session); void* memory = malloc(length); int fd = open("/dev/random", O_RDONLY); read(fd, memory, length); auto encryptedLength = olm_encrypt_message_length(session, message.length()); char* encryptedMemory = (char*)malloc(encryptedLength + 1); olm_encrypt(session, message.data(), message.length(), memory, length, encryptedMemory, encryptedLength); return encryptedMemory; } std::string Encryption::encryptGroup(OlmOutboundGroupSession* session, std::string message) { auto encryptedLength = olm_group_encrypt_message_length(session, message.length()); char* encryptedMemory = (char*)malloc(encryptedLength + 1); olm_group_encrypt(session, (uint8_t*)message.data(), message.length(), (uint8_t*)encryptedMemory, encryptedLength); return encryptedMemory; } OlmSession* Encryption::createInboundSession(std::string senderKey, std::string body) { void* inboundMemory = malloc(olm_session_size()); auto inboundSession = olm_session(inboundMemory); olm_create_inbound_session_from(inboundSession, account, (void*)senderKey.c_str(), senderKey.length(), (void*)body.c_str(), body.length()); return inboundSession; } std::vector Encryption::decrypt(OlmSession* session, int msgType, std::string cipherText) { /*std::string maxPlaintextLengthBuffer = cipherText; size_t maxPlaintextLength = olm_decrypt_max_plaintext_length(session, msgType, (void*)maxPlaintextLengthBuffer.data(), maxPlaintextLengthBuffer.length());; qDebug() << "THE ERROR YOU ARE LOOKING FOR " << olm_session_last_error(session); if(maxPlaintextLength == olm_error()) return ""; char* plaintext = new char[maxPlaintextLength]; //plaintext[maxPlaintextLength] = '\0'; memset(plaintext, '\0', maxPlaintextLength); int size = olm_decrypt(session, msgType, (void*)cipherText.data(), cipherText.length(), (void*)plaintext, maxPlaintextLength); //plaintext[size] = '\0'; plaintext[size + 1] = '\0'; return plaintext;*/ // because olm_group_decrypt_max_plaintext_length DESTROYS the buffer, why? auto tmp_plaintext_buffer = std::vector(cipherText.size()); std::copy(cipherText.begin(), cipherText.end(), tmp_plaintext_buffer.begin()); // create the result buffer size_t length = olm_decrypt_max_plaintext_length(session, msgType, tmp_plaintext_buffer.data(), tmp_plaintext_buffer.size()); if(length == olm_error()) return {}; auto result_buffer = std::vector(length); // now create another buffer for olm_group_decrypt auto tmp_buffer = std::vector(cipherText.size()); std::copy(cipherText.begin(), cipherText.end(), tmp_buffer.begin()); auto size = olm_decrypt(session, msgType, tmp_buffer.data(), tmp_buffer.size(), result_buffer.data(), result_buffer.size()); if(size == olm_error()) return {}; auto output = std::vector(size); std::memcpy(output.data(), result_buffer.data(), size); return output; } QString Encryption::saveSession(OlmOutboundGroupSession* session) { auto length = olm_pickle_outbound_group_session_length(session); char* identity_memory = (char*)malloc(length + 1); identity_memory[length] = '\0'; auto err = olm_pickle_outbound_group_session(session, "secret_key", 10, identity_memory, length); return identity_memory; } OlmOutboundGroupSession* Encryption::loadSession(QString bytes) { void* outboundMemory = malloc(olm_outbound_group_session_size()); auto outboundSession = olm_outbound_group_session(outboundMemory); auto length = bytes.length(); std::string key = bytes.toStdString(); olm_unpickle_outbound_group_session(outboundSession, "secret_key", 10, (void*)key.data(), key.length()); return outboundSession; } OlmInboundGroupSession* Encryption::beginInboundSession(std::string sessionKey) { void* inboundMemory = malloc(olm_inbound_group_session_size()); auto inboundSession = olm_inbound_group_session(inboundMemory); olm_init_inbound_group_session(inboundSession, (uint8_t*)sessionKey.data(), sessionKey.size()); return inboundSession; } std::vector Encryption::decrypt(OlmInboundGroupSession* session, std::string cipherText) { // because olm_group_decrypt_max_plaintext_length DESTROYS the buffer, why? auto tmp_plaintext_buffer = std::vector(cipherText.size()); std::copy(cipherText.begin(), cipherText.end(), tmp_plaintext_buffer.begin()); // create the result buffer size_t length = olm_group_decrypt_max_plaintext_length(session, tmp_plaintext_buffer.data(), tmp_plaintext_buffer.size()); if(length == olm_error()) return {}; auto result_buffer = std::vector(length); // now create another buffer for olm_group_decrypt auto tmp_buffer = std::vector(cipherText.size()); std::copy(cipherText.begin(), cipherText.end(), tmp_buffer.begin()); uint32_t msgIndex; auto size = olm_group_decrypt(session, tmp_buffer.data(), tmp_buffer.size(), result_buffer.data(), result_buffer.size(), &msgIndex); if(size == olm_error()) return {}; auto output = std::vector(size); std::memcpy(output.data(), result_buffer.data(), size); return output; }