Skip to content
Snippets Groups Projects
Verified Commit 8de4df36 authored by Nicolas Werner's avatar Nicolas Werner
Browse files

Implement online keybackup session encryption

parent f664dbbd
No related branches found
No related tags found
No related merge requests found
Pipeline #1654 failed
......@@ -73,6 +73,10 @@ public:
: olm_exception(std::move(func), std::string(olm_pk_decryption_last_error(s)))
{}
olm_exception(std::string func, OlmPkEncryption *s)
: olm_exception(std::move(func), std::string(olm_pk_encryption_last_error(s)))
{}
olm_exception(std::string func, OlmPkSigning *s)
: olm_exception(std::move(func), std::string(olm_pk_signing_last_error(s)))
{}
......
......@@ -44,6 +44,11 @@ struct OlmDeleter
olm_clear_pk_decryption(ptr);
delete[](reinterpret_cast<uint8_t *>(ptr));
}
void operator()(OlmPkEncryption *ptr)
{
olm_clear_pk_encryption(ptr);
delete[](reinterpret_cast<uint8_t *>(ptr));
}
void operator()(OlmPkSigning *ptr)
{
olm_clear_pk_signing(ptr);
......@@ -99,6 +104,17 @@ struct PkDecryptionObject
}
};
//! Wrapper for the olm object to do Private Key Decryption.
struct PkEncryptionObject
{
using olm_type = OlmPkEncryption;
static olm_type *allocate()
{
return olm_pk_encryption(new uint8_t[olm_pk_encryption_size()]);
}
};
//! Wrapper for the olm object to do Private Key Signing.
struct PkSigningObject
{
......
......@@ -91,6 +91,17 @@ AES_CTR_256_Encrypt(const std::string plaintext, const BinaryBuf aes256Key, Bina
BinaryBuf
AES_CTR_256_Decrypt(const std::string ciphertext, const BinaryBuf aes256Key, BinaryBuf iv);
//! Base64 encoded CURVE25519_AES_SHA2 encrypted text, including the mac and ephemeral key
struct CURVE25519_AES_SHA2_Encrypted
{
//! base64 encoded
std::string ciphertext, mac, ephemeral;
};
//! encypts a plaintext payload using CURVE25519_AES_SHA2
CURVE25519_AES_SHA2_Encrypted
CURVE25519_AES_SHA2_Encrypt(const std::string &plaintext, const std::string &base64_publicKey);
//! returns base64 encoded pubkey
std::string
CURVE25519_public_key_from_private(const BinaryBuf &privateKey);
......@@ -102,6 +113,10 @@ CURVE25519_AES_SHA2_Decrypt(std::string base64_ciphertext,
const std::string &ephemeral,
const std::string &mac);
//! encrypt a session for online key backup
mtx::responses::backup::EncryptedSessionData
encrypt_session(const mtx::responses::backup::SessionData &data, const std::string publicKey);
//! Decrypt a session retrieved from online key backup.
mtx::responses::backup::SessionData
decrypt_session(const mtx::responses::backup::EncryptedSessionData &data,
......
......@@ -608,6 +608,18 @@ public:
const std::string &room_id,
const std::string &session_id,
Callback<mtx::responses::backup::SessionBackup> cb);
void put_room_keys(const std::string &version,
const mtx::responses::backup::KeysBackup &keys,
ErrCallback cb);
void put_room_keys(const std::string &version,
const std::string &room_id,
const mtx::responses::backup::RoomKeysBackup &keys,
ErrCallback cb);
void put_room_keys(const std::string &version,
const std::string &room_id,
const std::string &session_id,
const mtx::responses::backup::SessionBackup &keys,
ErrCallback cb);
//
// Secret storage endpoints
......
......@@ -9,6 +9,8 @@
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <olm/pk.h>
#include <algorithm>
#include <iomanip>
#include <iostream>
......@@ -291,6 +293,40 @@ CURVE25519_public_key_from_private(const BinaryBuf &privateKey)
return to_string(pubkey);
}
CURVE25519_AES_SHA2_Encrypted
CURVE25519_AES_SHA2_Encrypt(const std::string &plaintext, const std::string &base64_publicKey)
{
auto ctx = create_olm_object<PkEncryptionObject>();
::olm_pk_encryption_set_recipient_key(
ctx.get(), base64_publicKey.data(), base64_publicKey.size());
BinaryBuf ephemeral(::olm_pk_key_length());
BinaryBuf mac(::olm_pk_mac_length(ctx.get()));
BinaryBuf ciphertext(::olm_pk_ciphertext_length(ctx.get(), plaintext.size()));
BinaryBuf randomBuf = create_buffer(::olm_pk_encrypt_random_length(ctx.get()));
auto encrypted_size = ::olm_pk_encrypt(ctx.get(),
plaintext.data(),
plaintext.size(),
ciphertext.data(),
ciphertext.size(),
mac.data(),
mac.size(),
ephemeral.data(),
ephemeral.size(),
randomBuf.data(),
randomBuf.size());
if (encrypted_size != olm_error()) {
CURVE25519_AES_SHA2_Encrypted val;
val.ciphertext = to_string(ciphertext);
val.mac = to_string(mac);
val.ephemeral = to_string(ephemeral);
return val;
} else
throw olm_exception(__func__, ctx.get());
}
std::string
CURVE25519_AES_SHA2_Decrypt(std::string base64_ciphertext,
const BinaryBuf &privateKey,
......@@ -323,6 +359,19 @@ CURVE25519_AES_SHA2_Decrypt(std::string base64_ciphertext,
throw olm_exception(__func__, ctx.get());
}
mtx::responses::backup::EncryptedSessionData
encrypt_session(const mtx::responses::backup::SessionData &data, const std::string publicKey)
{
mtx::responses::backup::EncryptedSessionData d;
auto temp = CURVE25519_AES_SHA2_Encrypt(nlohmann::json(data).dump(), publicKey);
d.ciphertext = std::move(temp.ciphertext);
d.mac = std::move(temp.mac);
d.ephemeral = std::move(temp.ephemeral);
return d;
}
mtx::responses::backup::SessionData
decrypt_session(const mtx::responses::backup::EncryptedSessionData &data,
const BinaryBuf &privateKey)
......
......@@ -1193,6 +1193,40 @@ Client::room_keys(const std::string &version,
});
}
void
Client::put_room_keys(const std::string &version,
const mtx::responses::backup::KeysBackup &keys,
ErrCallback cb)
{
put("/client/r0/room_keys/keys?" + mtx::client::utils::query_params({{"version", version}}),
keys,
cb);
}
void
Client::put_room_keys(const std::string &version,
const std::string &room_id,
const mtx::responses::backup::RoomKeysBackup &keys,
ErrCallback cb)
{
put("/client/r0/room_keys/keys/" + mtx::client::utils::url_encode(room_id) + "?" +
mtx::client::utils::query_params({{"version", version}}),
keys,
cb);
}
void
Client::put_room_keys(const std::string &version,
const std::string &room_id,
const std::string &session_id,
const mtx::responses::backup::SessionBackup &keys,
ErrCallback cb)
{
put("/client/r0/room_keys/keys/" + mtx::client::utils::url_encode(room_id) + "/" +
mtx::client::utils::url_encode(session_id) + "?" +
mtx::client::utils::query_params({{"version", version}}),
keys,
cb);
}
//! Retrieve a specific secret
void
Client::secret_storage_secret(const std::string &secret_id,
......
......@@ -282,6 +282,26 @@ TEST(Encryption, EncryptedFile)
ev.content.file.value())));
}
TEST(Encryption, PkEncryptionDecryption)
{
mtx::responses::backup::SessionData d;
d.algorithm = "m.megolm.v1.aes-sha2";
d.sender_key = "sender_key";
d.session_key = "session_key";
auto privKey = mtx::crypto::create_buffer(256 / 8);
auto publicKey = mtx::crypto::CURVE25519_public_key_from_private(privKey);
auto encrypted = mtx::crypto::encrypt_session(d, publicKey);
auto decrypted = mtx::crypto::decrypt_session(encrypted, privKey);
EXPECT_EQ(d.algorithm, decrypted.algorithm);
EXPECT_EQ(d.forwarding_curve25519_key_chain, decrypted.forwarding_curve25519_key_chain);
EXPECT_EQ(d.sender_claimed_keys, decrypted.sender_claimed_keys);
EXPECT_EQ(d.sender_key, decrypted.sender_key);
EXPECT_EQ(d.session_key, decrypted.session_key);
}
TEST(SecretStorage, Secret)
{
json j = R"({
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment