@@ -63,43 +63,57 @@ QByteArray EncryptionEngine::performKeyDerivation(const QByteArray& passwordWith
6363 // Initialize a QByteArray to hold the derived key
6464 QByteArray key (keySize, 0 );
6565
66+ // Attempt to lock the key memory to prevent it from being swapped to disk
67+ if (sodium_mlock (key.data (), key.size ()) != 0 ) {
68+ qDebug () << " Failed to lock key in memory" ;
69+ return QByteArray (); // Return an empty QByteArray on failure
70+ }
71+
72+ bool success = false ;
73+
6674 // Perform key derivation based on the selected KDF
6775 if (kdf == " PBKDF2" ) {
6876 // PBKDF2 key derivation using SHA-256
69- if (!PKCS5_PBKDF2_HMAC (passwordWithKeyfile.data (), passwordWithKeyfile.size (),
70- reinterpret_cast <const unsigned char *>(salt.data ()), salt.size (),
71- iterations, EVP_sha256 (), key.size (),
72- reinterpret_cast <unsigned char *>(key.data ()))) {
73- qDebug () << " PBKDF2 key derivation failed" ;
74- return QByteArray (); // Return an empty QByteArray on failure
75- }
77+ success = PKCS5_PBKDF2_HMAC (passwordWithKeyfile.data (), passwordWithKeyfile.size (),
78+ reinterpret_cast <const unsigned char *>(salt.data ()), salt.size (),
79+ iterations, EVP_sha256 (), key.size (),
80+ reinterpret_cast <unsigned char *>(key.data ())) != 0 ;
7681 } else if (kdf == " Argon2" ) {
7782 // Argon2i key derivation
78- if (argon2i_hash_raw (iterations, 1 << 16 , 1 ,
79- passwordWithKeyfile.data (), passwordWithKeyfile.size (),
80- reinterpret_cast <const unsigned char *>(salt.data ()), salt.size (),
81- reinterpret_cast <unsigned char *>(key.data ()), key.size ()) != ARGON2_OK) {
82- qDebug () << " Argon2 key derivation failed" ;
83- return QByteArray (); // Return an empty QByteArray on failure
84- }
83+ success = argon2i_hash_raw (iterations, 1 << 16 , 1 ,
84+ passwordWithKeyfile.data (), passwordWithKeyfile.size (),
85+ reinterpret_cast <const unsigned char *>(salt.data ()), salt.size (),
86+ reinterpret_cast <unsigned char *>(key.data ()), key.size ()) == ARGON2_OK;
8587 } else if (kdf == " Scrypt" ) {
8688 // Scrypt key derivation
8789 unsigned long long opslimit = iterations;
88- if (crypto_pwhash_scryptsalsa208sha256 (reinterpret_cast <unsigned char *>(key.data ()),
89- static_cast <unsigned long long >(key.size ()),
90- passwordWithKeyfile.constData (),
91- static_cast <unsigned long long >(passwordWithKeyfile.size ()),
92- reinterpret_cast <const unsigned char *>(salt.data ()),
93- opslimit,
94- crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0 ) {
95- qDebug () << " Scrypt key derivation failed" ;
96- return QByteArray (); // Return an empty QByteArray on failure
97- }
90+ success = crypto_pwhash_scryptsalsa208sha256 (reinterpret_cast <unsigned char *>(key.data ()),
91+ static_cast <unsigned long long >(key.size ()),
92+ passwordWithKeyfile.constData (),
93+ static_cast <unsigned long long >(passwordWithKeyfile.size ()),
94+ reinterpret_cast <const unsigned char *>(salt.data ()),
95+ opslimit,
96+ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) == 0 ;
9897 } else {
9998 // If an unknown KDF is provided, log an error
10099 qDebug () << " Unknown KDF specified:" << kdf;
100+ }
101+
102+ if (!success) {
103+ qDebug () << kdf << " key derivation failed" ;
104+
105+ // Unlock and cleanse key before returning
106+ sodium_munlock (key.data (), key.size ());
107+ OPENSSL_cleanse (key.data (), key.size ());
108+
101109 return QByteArray (); // Return an empty QByteArray on failure
102110 }
103111
112+ // Clear sensitive data in passwordWithKeyfile
113+ OPENSSL_cleanse (const_cast <char *>(passwordWithKeyfile.constData ()), passwordWithKeyfile.size ());
114+
115+ // Unlock the key memory before returning it
116+ sodium_munlock (key.data (), key.size ());
117+
104118 return key;
105- }
119+ }
0 commit comments