Use SecureString where there is data to be cleansed
SecureString has quite a few places it should be used in the user
management code.
Tested: ran set password, test password, and other commands
Change-Id: Ia53bc914d25f7965c3e72d5cf18346e0fa9339b9
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/user_channel/usercommands.cpp b/user_channel/usercommands.cpp
index c48c476..f6190d7 100644
--- a/user_channel/usercommands.cpp
+++ b/user_channel/usercommands.cpp
@@ -358,28 +358,33 @@
}
else if (req->operation == testPassword)
{
- auto password = ipmiUserGetPassword(userName);
- std::string testPassword(
- reinterpret_cast<const char*>(req->userPassword), 0,
- passwordLength);
- // Note: For security reasons password size won't be compared and
- // wrong password size completion code will not be returned if size
- // doesn't match as specified in IPMI specification.
- if (password != testPassword)
+ SecureString password = ipmiUserGetPassword(userName);
+ SecureString testPassword(
+ reinterpret_cast<const char*>(req->userPassword), passwordLength);
+ // constant time string compare: always compare exactly as many bytes
+ // as the length of the input, resizing the actual password to match,
+ // maintaining a knowledge if the sizes differed originally
+ static const std::array<char, maxIpmi20PasswordSize> empty = {'\0'};
+ size_t cmpLen = testPassword.size();
+ bool pwLenDiffers = password.size() != cmpLen;
+ const char* cmpPassword = nullptr;
+ if (pwLenDiffers)
+ {
+ cmpPassword = empty.data();
+ }
+ else
+ {
+ cmpPassword = password.data();
+ }
+ bool pwBad = CRYPTO_memcmp(cmpPassword, testPassword.data(), cmpLen);
+ pwBad |= pwLenDiffers;
+ if (pwBad)
{
log<level::DEBUG>("Test password failed",
entry("USER-ID=%d", (uint8_t)req->userId));
- // Clear sensitive data
- OPENSSL_cleanse(testPassword.data(), testPassword.length());
- OPENSSL_cleanse(password.data(), password.length());
-
return static_cast<Cc>(
IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch);
}
- // Clear sensitive data
- OPENSSL_cleanse(testPassword.data(), testPassword.length());
- OPENSSL_cleanse(password.data(), password.length());
-
return ccSuccess;
}
return ccInvalidFieldRequest;