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

Fix session decryption

parent 16bc612c
No related branches found
No related tags found
No related merge requests found
......@@ -115,58 +115,42 @@ login_handler(const mtx::responses::Login &res, RequestErr err)
mtx::crypto::BinaryBuf decryptionKey;
if (keyDesc.passphrase) {
auto password =
getpass("Enter Key Backup Password: ");
decryptionKey = mtx::crypto::derive_key(
password, keyDesc.passphrase.value());
std::optional<mtx::crypto::BinaryBuf> temp;
do {
auto password = getpass(
"Enter Key Backup Password: ");
temp =
mtx::crypto::key_from_passphrase(
password, keyDesc);
} while (!temp);
decryptionKey = temp.value();
} else {
auto recoveryKey =
getpass("Enter Key Backup Recovery Key: ");
decryptionKey =
mtx::crypto::to_binary_buf(recoveryKey);
std::optional<mtx::crypto::BinaryBuf> temp;
do {
auto recoveryKey = getpass(
"Enter Key Backup Recovery Key: ");
temp =
mtx::crypto::key_from_recoverykey(
recoveryKey, keyDesc);
} while (!temp);
decryptionKey = temp.value();
}
// BinaryBuf
// AES_CTR_256_Encrypt(const std::string plaintext,
// const BinaryBuf aes256Key, BinaryBuf iv);
// verify key
using namespace mtx::crypto;
auto testKeys = HKDF_SHA256(
decryptionKey, BinaryBuf(32, 0), BinaryBuf{});
auto encrypted = AES_CTR_256_Encrypt(
std::string(32, '\0'),
testKeys.aes,
to_binary_buf(base642bin(keyDesc.iv)));
auto mac = HMAC_SHA256(testKeys.mac, encrypted);
if (bin2base64(to_string(mac)) != keyDesc.mac) {
cerr
<< "mac failed, key or password wrong!\n";
return;
}
auto keys = HKDF_SHA256(
auto decryptedSecret = decrypt(
secretData,
decryptionKey,
BinaryBuf(32, 0),
to_binary_buf(
mtx::secret_storage::secrets::megolm_backup_v1));
auto keyMac = HMAC_SHA256(
keys.mac,
to_binary_buf(base642bin(secretData.ciphertext)));
if (bin2base64(to_string(keyMac)) != secretData.mac) {
mtx::secret_storage::secrets::megolm_backup_v1);
if (decryptedSecret.empty()) {
cerr
<< bin2base64(to_string(keyMac)) << " and "
<< secretData.mac
<< " don't match, can't decrypt ecdh key!";
<< "Failed to get backup key from secret";
return;
}
auto decryptedSecret = AES_CTR_256_Decrypt(
secretData.ciphertext,
keys.aes,
to_binary_buf(base642bin(secretData.iv)));
auto sessionDecryptionKey =
to_binary_buf(base642bin(decryptedSecret));
for (const auto &[room_id, backup_sessions] :
backup.rooms) {
......@@ -181,7 +165,7 @@ login_handler(const mtx::responses::Login &res, RequestErr err)
<< CURVE25519_AES_SHA2_Decrypt(
s.session_data
.ciphertext,
decryptedSecret,
sessionDecryptionKey,
s.session_data
.ephemeral,
s.session_data.mac)
......@@ -189,6 +173,7 @@ login_handler(const mtx::responses::Login &res, RequestErr err)
} catch (
mtx::crypto::olm_exception &e) {
cerr << e.what() << "\n";
return;
}
}
}
......
......@@ -51,8 +51,18 @@ PBKDF2_HMAC_SHA_512(const std::string pass,
uint32_t iterations,
uint32_t keylen = 64);
BinaryBuf
derive_key(const std::string &password, const mtx::secret_storage::PBKDF2 &parameters);
std::optional<BinaryBuf>
key_from_passphrase(const std::string &password,
const mtx::secret_storage::AesHmacSha2KeyDescription &parameters);
std::optional<BinaryBuf>
key_from_recoverykey(const std::string &recoverkey,
const mtx::secret_storage::AesHmacSha2KeyDescription &parameters);
std::string
decrypt(const mtx::secret_storage::AesHmacSha2EncryptedData &data,
BinaryBuf decryptionKey,
const std::string key_name);
//! HKDF key derivation with SHA256 digest
struct HkdfKeys
......
......@@ -43,13 +43,83 @@ PBKDF2_HMAC_SHA_512(const std::string pass,
return out;
}
BinaryBuf
derive_key(const std::string &password, const mtx::secret_storage::PBKDF2 &parameters)
std::optional<BinaryBuf>
key_from_passphrase(const std::string &password,
const mtx::secret_storage::AesHmacSha2KeyDescription &parameters)
{
if (parameters.algorithm != "m.pbkdf2")
if (!parameters.passphrase)
throw std::invalid_argument("no passphrase to derive key from");
if (parameters.passphrase->algorithm != "m.pbkdf2")
throw std::invalid_argument("invalid pbkdf algorithm");
return PBKDF2_HMAC_SHA_512(
password, to_binary_buf(parameters.salt), parameters.iterations, parameters.bits / 8);
auto decryptionKey = PBKDF2_HMAC_SHA_512(password,
to_binary_buf(parameters.passphrase->salt),
parameters.passphrase->iterations,
parameters.passphrase->bits / 8);
// verify key
using namespace mtx::crypto;
auto testKeys = HKDF_SHA256(decryptionKey, BinaryBuf(32, 0), BinaryBuf{});
auto encrypted = AES_CTR_256_Encrypt(
std::string(32, '\0'), testKeys.aes, to_binary_buf(base642bin(parameters.iv)));
auto mac = HMAC_SHA256(testKeys.mac, encrypted);
if (bin2base64(to_string(mac)) != parameters.mac) {
return std::nullopt;
}
return decryptionKey;
}
std::optional<BinaryBuf>
key_from_recoverykey(const std::string &recoverykey,
const mtx::secret_storage::AesHmacSha2KeyDescription &parameters)
{
auto tempKey = to_binary_buf(base582bin(recoverykey));
if (tempKey.size() < 3 || tempKey[0] != 0x8b || tempKey[1] != 0x01)
return std::nullopt;
uint8_t parity = 0;
for (auto byte = tempKey.begin(); byte != tempKey.end() - 1; ++byte)
parity ^= *byte;
if (parity != tempKey.back())
return std::nullopt;
auto decryptionKey = BinaryBuf(tempKey.begin() + 2, tempKey.end() - 1);
// verify key
using namespace mtx::crypto;
auto testKeys = HKDF_SHA256(decryptionKey, BinaryBuf(32, 0), BinaryBuf{});
auto encrypted = AES_CTR_256_Encrypt(
std::string(32, '\0'), testKeys.aes, to_binary_buf(base642bin(parameters.iv)));
auto mac = HMAC_SHA256(testKeys.mac, encrypted);
if (bin2base64(to_string(mac)) != parameters.mac) {
return std::nullopt;
}
return decryptionKey;
}
std::string
decrypt(const mtx::secret_storage::AesHmacSha2EncryptedData &data,
BinaryBuf decryptionKey,
const std::string key_name)
{
auto keys = HKDF_SHA256(decryptionKey, BinaryBuf(32, 0), to_binary_buf(key_name));
auto keyMac = HMAC_SHA256(keys.mac, to_binary_buf(base642bin(data.ciphertext)));
if (bin2base64(to_string(keyMac)) != data.mac) {
return "";
}
auto decryptedSecret = AES_CTR_256_Decrypt(
base642bin(data.ciphertext), keys.aes, to_binary_buf(base642bin(data.iv)));
return to_string(decryptedSecret);
}
HkdfKeys
......@@ -214,7 +284,8 @@ CURVE25519_AES_SHA2_Decrypt(std::string base64_ciphertext,
::olm_pk_key_from_private(
ctx.get(), pubkey.data(), pubkey.size(), privateKey.data(), privateKey.size());
std::string plaintext(base64_ciphertext.size(), '\0');
std::string plaintext(olm_pk_max_plaintext_length(ctx.get(), base64_ciphertext.size()),
'\0');
std::size_t decrypted_size = ::olm_pk_decrypt(ctx.get(),
ephemeral.data(),
ephemeral.size(),
......
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