I think you use this to validate the password, not to check the integrity of the message. And an attacker gets a password as a result of brute-forcing, not a hash. Look at this snippet in pseudocode:
// Get the hash and the encrypted text from the encrypted data
hash = substing(encryptedData, 0, 64);
encryptedText = substing(encryptedData, 64);
foreach password in PasswordDictionary {
if hash == HMAC(encryptedText, SHA256(password)) {
print "Password found: " + password;
// Decrypt the message
print "Message: " + AESDecrypt(encryptedText, password);
}
}
The loop will run fast, and you get a clear-text password as a result, which can decrypt the message. If you replace SHA256(password) with PBKDF2(password, 20000) the loop becomes insanely slower.