diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index c26090a7..590fec57 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -5764,6 +5764,10 @@ We recommend you use the AppImage available on our downloads page. Unexpected EOF when writing private key + + AES-256/GCM is currently not supported + + PasswordEditWidget diff --git a/src/crypto/SymmetricCipher.cpp b/src/crypto/SymmetricCipher.cpp index 4d3a7bdf..1ed05bb3 100644 --- a/src/crypto/SymmetricCipher.cpp +++ b/src/crypto/SymmetricCipher.cpp @@ -267,3 +267,22 @@ int SymmetricCipher::blockSize(Mode mode) return 0; } } + +int SymmetricCipher::ivSize(Mode mode) +{ + switch (mode) { + case Aes128_CBC: + case Aes256_CBC: + case Aes128_CTR: + case Aes256_CTR: + case Twofish_CBC: + return 16; + case Aes256_GCM: + return 12; + case Salsa20: + case ChaCha20: + return 8; + default: + return 0; + } +} diff --git a/src/crypto/SymmetricCipher.h b/src/crypto/SymmetricCipher.h index 83b54658..e18f623f 100644 --- a/src/crypto/SymmetricCipher.h +++ b/src/crypto/SymmetricCipher.h @@ -70,6 +70,7 @@ public: static int defaultIvSize(Mode mode); static int keySize(Mode mode); static int blockSize(Mode mode); + static int ivSize(Mode mode); private: static QString modeToString(const Mode mode); diff --git a/src/sshagent/OpenSSHKey.cpp b/src/sshagent/OpenSSHKey.cpp index e7a2a9b8..e6b21c86 100644 --- a/src/sshagent/OpenSSHKey.cpp +++ b/src/sshagent/OpenSSHKey.cpp @@ -30,6 +30,7 @@ const QString OpenSSHKey::TYPE_DSA_PRIVATE = "DSA PRIVATE KEY"; const QString OpenSSHKey::TYPE_RSA_PRIVATE = "RSA PRIVATE KEY"; const QString OpenSSHKey::TYPE_OPENSSH_PRIVATE = "OPENSSH PRIVATE KEY"; +const QString OpenSSHKey::OPENSSH_CIPHER_SUFFIX = "@openssh.com"; OpenSSHKey::OpenSSHKey(QObject* parent) : QObject(parent) @@ -310,9 +311,16 @@ bool OpenSSHKey::openKey(const QString& passphrase) QByteArray rawData = m_rawData; if (m_cipherName != "none") { - auto cipherMode = SymmetricCipher::stringToMode(m_cipherName); + QString l_cipherName(m_cipherName); + if (l_cipherName.endsWith(OPENSSH_CIPHER_SUFFIX)) { + l_cipherName.remove(OPENSSH_CIPHER_SUFFIX); + } + auto cipherMode = SymmetricCipher::stringToMode(l_cipherName); if (cipherMode == SymmetricCipher::InvalidMode) { - m_error = tr("Unknown cipher: %1").arg(m_cipherName); + m_error = tr("Unknown cipher: %1").arg(l_cipherName); + return false; + } else if (cipherMode == SymmetricCipher::Aes256_GCM) { + m_error = tr("AES-256/GCM is currently not supported"); return false; } @@ -325,7 +333,7 @@ bool OpenSSHKey::openKey(const QString& passphrase) } int keySize = cipher->keySize(cipherMode); - int blockSize = 16; + int ivSize = cipher->ivSize(cipherMode); BinaryStream optionStream(&m_kdfOptions); @@ -335,7 +343,7 @@ bool OpenSSHKey::openKey(const QString& passphrase) optionStream.readString(salt); optionStream.read(rounds); - QByteArray decryptKey(keySize + blockSize, '\0'); + QByteArray decryptKey(keySize + ivSize, '\0'); try { auto baPass = passphrase.toUtf8(); auto pwhash = Botan::PasswordHashFamily::create_or_throw("Bcrypt-PBKDF")->from_iterations(rounds); @@ -351,7 +359,7 @@ bool OpenSSHKey::openKey(const QString& passphrase) } keyData = decryptKey.left(keySize); - ivData = decryptKey.right(blockSize); + ivData = decryptKey.right(ivSize); } else if (m_kdfName == "md5") { if (m_cipherIV.length() < 8) { m_error = tr("Cipher IV is too short for MD5 kdf"); diff --git a/src/sshagent/OpenSSHKey.h b/src/sshagent/OpenSSHKey.h index 78ccf719..a42e433d 100644 --- a/src/sshagent/OpenSSHKey.h +++ b/src/sshagent/OpenSSHKey.h @@ -58,6 +58,7 @@ public: static const QString TYPE_DSA_PRIVATE; static const QString TYPE_RSA_PRIVATE; static const QString TYPE_OPENSSH_PRIVATE; + static const QString OPENSSH_CIPHER_SUFFIX; private: enum KeyPart