Handling delete password entry from ipmi-pass

API to Handle the delete password entry from
ipmi-pass encrypted file when user gets deleted
by any interface

Change-Id: I692a81b166b53d6fc981fdb85ce5d6980887560b
Signed-off-by: AppaRao Puli <apparao.puli@intel.com>
Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
diff --git a/user_channel/file.hpp b/user_channel/file.hpp
new file mode 100644
index 0000000..2c537b1
--- /dev/null
+++ b/user_channel/file.hpp
@@ -0,0 +1,88 @@
+#pragma once
+
+#include <stdio.h>
+
+#include <experimental/filesystem>
+namespace phosphor
+{
+namespace user
+{
+
+namespace fs = std::experimental::filesystem;
+
+/** @class File
+ *  @brief Responsible for handling file pointer
+ *  Needed by putspent(3)
+ */
+class File
+{
+  private:
+    /** @brief handler for operating on file */
+    FILE* fp = NULL;
+
+    /** @brief File name. Needed in the case where the temp
+     *         needs to be removed
+     */
+    const std::string& name;
+
+    /** @brief Should the file be removed at exit */
+    bool removeOnExit = false;
+
+  public:
+    File() = delete;
+    File(const File&) = delete;
+    File& operator=(const File&) = delete;
+    File(File&&) = delete;
+    File& operator=(File&&) = delete;
+
+    /** @brief Opens file and uses it to do file operation
+     *
+     *  @param[in] name         - File name
+     *  @param[in] mode         - File open mode
+     *  @param[in] removeOnExit - File to be removed at exit or no
+     */
+    File(const std::string& name, const std::string& mode,
+         bool removeOnExit = false) :
+        name(name),
+        removeOnExit(removeOnExit)
+    {
+        fp = fopen(name.c_str(), mode.c_str());
+    }
+
+    /** @brief Opens file using provided file descriptor
+     *
+     *  @param[in] fd           - File descriptor
+     *  @param[in] name         - File name
+     *  @param[in] mode         - File open mode
+     *  @param[in] removeOnExit - File to be removed at exit or no
+     */
+    File(int fd, const std::string& name, const std::string& mode,
+         bool removeOnExit = false) :
+        name(name),
+        removeOnExit(removeOnExit)
+    {
+        fp = fdopen(fd, mode.c_str());
+    }
+
+    ~File()
+    {
+        if (fp)
+        {
+            fclose(fp);
+        }
+
+        // Needed for exception safety
+        if (removeOnExit && fs::exists(name))
+        {
+            fs::remove(name);
+        }
+    }
+
+    auto operator()()
+    {
+        return fp;
+    }
+};
+
+} // namespace user
+} // namespace phosphor
diff --git a/user_channel/passwd_mgr.cpp b/user_channel/passwd_mgr.cpp
index 1d8a1ce..15e6e34 100644
--- a/user_channel/passwd_mgr.cpp
+++ b/user_channel/passwd_mgr.cpp
@@ -16,15 +16,20 @@
 
 #include "passwd_mgr.hpp"
 
+#include "file.hpp"
 #include "shadowlock.hpp"
 
 #include <openssl/hmac.h>
+#include <openssl/rand.h>
 #include <openssl/sha.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <unistd.h>
 
+#include <cerrno>
 #include <cstring>
 #include <fstream>
+#include <iomanip>
 #include <phosphor-logging/log.hpp>
 
 namespace ipmi
@@ -34,7 +39,12 @@
 static const char* encryptKeyFileName = "/etc/key_file";
 static const size_t maxKeySize = 8;
 
-static const char* META_PASSWD_SIG = "=OPENBMC=";
+#define META_PASSWD_SIG "=OPENBMC="
+
+static inline size_t blockRound(size_t odd, size_t blk)
+{
+    return ((odd) + (((blk) - ((odd) & ((blk)-1))) & ((blk)-1)));
+}
 
 /*
  * Meta data struct for encrypted password file
@@ -68,16 +78,36 @@
     return iter->second;
 }
 
+int PasswdMgr::clearUserEntry(const std::string& userName)
+{
+    std::time_t updatedTime = getUpdatedFileTime();
+    // Check file time stamp to know passwdMapList is up-to-date.
+    // If not up-to-date, then updatePasswdSpecialFile will read and
+    // check the user entry existance.
+    if (fileLastUpdatedTime == updatedTime && updatedTime != -EIO)
+    {
+        if (passwdMapList.find(userName) == passwdMapList.end())
+        {
+            log<level::DEBUG>("User not found");
+            return 0;
+        }
+    }
+
+    // Write passwdMap to Encryted file
+    if (updatePasswdSpecialFile(userName) != 0)
+    {
+        log<level::DEBUG>("Passwd file update failed");
+        return -EIO;
+    }
+
+    log<level::DEBUG>("Passwd file updated successfully");
+    return 0;
+}
+
 void PasswdMgr::checkAndReload(void)
 {
-    struct stat fileStat = {};
-    if (stat(passwdFileName, &fileStat) != 0)
-    {
-        log<level::DEBUG>("Error in getting last updated time stamp");
-        return;
-    }
-    std::time_t updatedTime = fileStat.st_mtime;
-    if (fileLastUpdatedTime != updatedTime)
+    std::time_t updatedTime = getUpdatedFileTime();
+    if (fileLastUpdatedTime != updatedTime && updatedTime != -1)
     {
         log<level::DEBUG>("Reloading password map list");
         passwdMapList.clear();
@@ -85,49 +115,55 @@
     }
 }
 
-int PasswdMgr::decrypt(const EVP_CIPHER* cipher, uint8_t* key, size_t keyLen,
-                       uint8_t* iv, size_t ivLen, uint8_t* inBytes,
-                       size_t inBytesLen, uint8_t* mac, size_t macLen,
-                       uint8_t* outBytes, size_t* outBytesLen)
+int PasswdMgr::encryptDecryptData(bool doEncrypt, const EVP_CIPHER* cipher,
+                                  uint8_t* key, size_t keyLen, uint8_t* iv,
+                                  size_t ivLen, uint8_t* inBytes,
+                                  size_t inBytesLen, uint8_t* mac,
+                                  size_t* macLen, unsigned char* outBytes,
+                                  size_t* outBytesLen)
 {
-
     if (cipher == NULL || key == NULL || iv == NULL || inBytes == NULL ||
         outBytes == NULL || mac == NULL || inBytesLen == 0 ||
         (size_t)EVP_CIPHER_key_length(cipher) > keyLen ||
         (size_t)EVP_CIPHER_iv_length(cipher) > ivLen)
     {
         log<level::DEBUG>("Error Invalid Inputs");
-        return -1;
+        return -EINVAL;
     }
 
-    std::array<uint8_t, EVP_MAX_MD_SIZE> calMac;
-    size_t calMacLen = calMac.size();
-    // calculate MAC for the encrypted message.
-    if (NULL == HMAC(EVP_sha256(), key, keyLen, inBytes, inBytesLen,
-                     calMac.data(),
-                     reinterpret_cast<unsigned int*>(&calMacLen)))
+    if (!doEncrypt)
     {
-        log<level::DEBUG>("Error: Failed to calculate MAC");
-        return -1;
-    }
-    if (!((calMacLen == macLen) &&
-          (std::memcmp(calMac.data(), mac, calMacLen) == 0)))
-    {
-        log<level::DEBUG>("Authenticated message doesn't match");
-        return -1;
+        // verify MAC before decrypting the data.
+        std::array<uint8_t, EVP_MAX_MD_SIZE> calMac;
+        size_t calMacLen = calMac.size();
+        // calculate MAC for the encrypted message.
+        if (NULL == HMAC(EVP_sha256(), key, keyLen, inBytes, inBytesLen,
+                         calMac.data(),
+                         reinterpret_cast<unsigned int*>(&calMacLen)))
+        {
+            log<level::DEBUG>("Error: Failed to calculate MAC");
+            return -EIO;
+        }
+        if (!((calMacLen == *macLen) &&
+              (std::memcmp(calMac.data(), mac, calMacLen) == 0)))
+        {
+            log<level::DEBUG>("Authenticated message doesn't match");
+            return -EBADMSG;
+        }
     }
 
     std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)> ctx(
         EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);
     EVP_CIPHER_CTX_set_padding(ctx.get(), 1);
 
-    // Set key & IV to decrypt
-    int retval = EVP_CipherInit_ex(ctx.get(), cipher, NULL, key, iv, 0);
+    // Set key & IV
+    int retval = EVP_CipherInit_ex(ctx.get(), cipher, NULL, key, iv,
+                                   static_cast<int>(doEncrypt));
     if (!retval)
     {
         log<level::DEBUG>("EVP_CipherInit_ex failed",
                           entry("RET_VAL=%d", retval));
-        return -1;
+        return -EIO;
     }
 
     int outLen = 0, outEVPLen = 0;
@@ -145,14 +181,25 @@
         {
             log<level::DEBUG>("EVP_CipherFinal fails",
                               entry("RET_VAL=%d", retval));
-            return -1;
+            return -EIO;
         }
     }
     else
     {
         log<level::DEBUG>("EVP_CipherUpdate fails",
                           entry("RET_VAL=%d", retval));
-        return -1;
+        return -EIO;
+    }
+
+    if (doEncrypt)
+    {
+        // Create MAC for the encrypted message
+        if (NULL == HMAC(EVP_sha256(), key, keyLen, outBytes, *outBytesLen, mac,
+                         reinterpret_cast<unsigned int*>(macLen)))
+        {
+            log<level::DEBUG>("Failed to create authentication");
+            return -EIO;
+        }
     }
     return 0;
 }
@@ -160,39 +207,73 @@
 void PasswdMgr::initPasswordMap(void)
 {
     phosphor::user::shadow::Lock lock();
+    std::vector<uint8_t> dataBuf;
 
+    if (readPasswdFileData(dataBuf) != 0)
+    {
+        log<level::DEBUG>("Error in reading the encrypted pass file");
+        return;
+    }
+
+    if (dataBuf.size() != 0)
+    {
+        // populate the user list with password
+        char* outPtr = reinterpret_cast<char*>(dataBuf.data());
+        char* nToken = NULL;
+        char* linePtr = strtok_r(outPtr, "\n", &nToken);
+        size_t userEPos = 0, lineSize = 0;
+        while (linePtr != NULL)
+        {
+            std::string lineStr(linePtr);
+            if ((userEPos = lineStr.find(":")) != std::string::npos)
+            {
+                lineSize = lineStr.size();
+                passwdMapList.emplace(
+                    lineStr.substr(0, userEPos),
+                    lineStr.substr(userEPos + 1, lineSize - (userEPos + 1)));
+            }
+            linePtr = strtok_r(NULL, "\n", &nToken);
+        }
+    }
+
+    // Update the timestamp
+    fileLastUpdatedTime = getUpdatedFileTime();
+    return;
+}
+
+int PasswdMgr::readPasswdFileData(std::vector<uint8_t>& outBytes)
+{
     std::array<uint8_t, maxKeySize> keyBuff;
     std::ifstream keyFile(encryptKeyFileName, std::ios::in | std::ios::binary);
     if (!keyFile.is_open())
     {
         log<level::DEBUG>("Error in opening encryption key file");
-        return;
+        return -EIO;
     }
-    keyFile.read((char*)keyBuff.data(), keyBuff.size());
+    keyFile.read(reinterpret_cast<char*>(keyBuff.data()), keyBuff.size());
     if (keyFile.fail())
     {
         log<level::DEBUG>("Error in reading encryption key file");
-        return;
+        return -EIO;
     }
 
     std::ifstream passwdFile(passwdFileName, std::ios::in | std::ios::binary);
     if (!passwdFile.is_open())
     {
         log<level::DEBUG>("Error in opening ipmi password file");
-        return;
+        return -EIO;
     }
 
     // calculate file size and read the data
-    std::vector<uint8_t> input;
     passwdFile.seekg(0, std::ios::end);
     ssize_t fileSize = passwdFile.tellg();
     passwdFile.seekg(0, std::ios::beg);
-    input.resize(fileSize);
-    passwdFile.read((char*)input.data(), fileSize);
+    std::vector<uint8_t> input(fileSize);
+    passwdFile.read(reinterpret_cast<char*>(input.data()), fileSize);
     if (passwdFile.fail())
     {
         log<level::DEBUG>("Error in reading encryption key file");
-        return;
+        return -EIO;
     }
 
     // verify the signature first
@@ -201,61 +282,286 @@
                      sizeof(metaData->signature)))
     {
         log<level::DEBUG>("Error signature mismatch in password file");
-        return;
+        return -EBADMSG;
+    }
+
+    size_t inBytesLen = metaData->dataSize + metaData->padSize;
+    // If data is empty i.e no password map then return success
+    if (inBytesLen == 0)
+    {
+        log<level::DEBUG>("Empty password file");
+        return 0;
     }
 
     // compute the key needed to decrypt
     std::array<uint8_t, EVP_MAX_KEY_LENGTH> key;
     auto keyLen = key.size();
-    HMAC(EVP_sha256(), keyBuff.data(), keyBuff.size(),
-         input.data() + sizeof(*metaData), metaData->hashSize, key.data(),
-         reinterpret_cast<unsigned int*>(&keyLen));
+    if (NULL == HMAC(EVP_sha256(), keyBuff.data(), keyBuff.size(),
+                     input.data() + sizeof(*metaData), metaData->hashSize,
+                     key.data(), reinterpret_cast<unsigned int*>(&keyLen)))
+    {
+        log<level::DEBUG>("Failed to create MAC for authentication");
+        return -EIO;
+    }
 
     // decrypt the data
     uint8_t* iv = input.data() + sizeof(*metaData) + metaData->hashSize;
     size_t ivLen = metaData->ivSize;
     uint8_t* inBytes = iv + ivLen;
-    size_t inBytesLen = metaData->dataSize + metaData->padSize;
     uint8_t* mac = inBytes + inBytesLen;
     size_t macLen = metaData->macSize;
-    std::vector<uint8_t> outBytes(inBytesLen + EVP_MAX_BLOCK_LENGTH);
-    size_t outBytesLen = outBytes.size();
-    if (decrypt(EVP_aes_128_cbc(), key.data(), keyLen, iv, ivLen, inBytes,
-                inBytesLen, mac, macLen, outBytes.data(), &outBytesLen) != 0)
+
+    size_t outBytesLen = 0;
+    // Resize to actual data size
+    outBytes.resize(inBytesLen + EVP_MAX_BLOCK_LENGTH);
+    if (encryptDecryptData(false, EVP_aes_128_cbc(), key.data(), keyLen, iv,
+                           ivLen, inBytes, inBytesLen, mac, &macLen,
+                           outBytes.data(), &outBytesLen) != 0)
     {
         log<level::DEBUG>("Error in decryption");
-        return;
+        return -EIO;
     }
-    outBytes[outBytesLen] = 0;
+    // Resize the vector to outBytesLen
+    outBytes.resize(outBytesLen);
+
     OPENSSL_cleanse(key.data(), keyLen);
     OPENSSL_cleanse(iv, ivLen);
 
-    // populate the user list with password
-    char* outPtr = reinterpret_cast<char*>(outBytes.data());
-    char* nToken = NULL;
-    char* linePtr = strtok_r(outPtr, "\n", &nToken);
-    size_t userEPos = 0, lineSize = 0;
-    while (linePtr != NULL)
+    return 0;
+}
+
+int PasswdMgr::updatePasswdSpecialFile(const std::string& userName)
+{
+    phosphor::user::shadow::Lock lock();
+
+    size_t bytesWritten = 0;
+    size_t inBytesLen = 0;
+    size_t isUsrFound = false;
+    const EVP_CIPHER* cipher = EVP_aes_128_cbc();
+    std::vector<uint8_t> dataBuf;
+
+    // Read the encrypted file and get the file data
+    // Check user existance and return if not exist.
+    if (readPasswdFileData(dataBuf) != 0)
     {
-        std::string lineStr(linePtr);
-        if ((userEPos = lineStr.find(":")) != std::string::npos)
-        {
-            lineSize = lineStr.size();
-            passwdMapList.emplace(
-                lineStr.substr(0, userEPos),
-                lineStr.substr(userEPos + 1, lineSize - (userEPos + 1)));
-        }
-        linePtr = strtok_r(NULL, "\n", &nToken);
+        log<level::DEBUG>("Error in reading the encrypted pass file");
+        return -EIO;
     }
-    // Update the timestamp
+
+    if (dataBuf.size() != 0)
+    {
+        inBytesLen = dataBuf.size() + EVP_CIPHER_block_size(cipher);
+    }
+
+    std::vector<uint8_t> inBytes(inBytesLen);
+    if (inBytesLen != 0)
+    {
+        char* outPtr = reinterpret_cast<char*>(dataBuf.data());
+        size_t userEPos = 0;
+        char* nToken = NULL;
+        char* linePtr = strtok_r(outPtr, "\n", &nToken);
+        while (linePtr != NULL)
+        {
+            std::string lineStr(linePtr);
+            if ((userEPos = lineStr.find(":")) != std::string::npos)
+            {
+                if (userName.compare(lineStr.substr(0, userEPos)) == 0)
+                {
+                    isUsrFound = true;
+                }
+                else
+                {
+                    bytesWritten += std::snprintf(
+                        reinterpret_cast<char*>(&inBytes[0]) + bytesWritten,
+                        inBytesLen, "%s\n", lineStr.data());
+                }
+            }
+            linePtr = strtok_r(NULL, "\n", &nToken);
+        }
+
+        // Round of to block size and padding remaing bytes with zero.
+        inBytesLen = blockRound(bytesWritten, EVP_CIPHER_block_size(cipher));
+        std::memset(&inBytes[0] + bytesWritten, 0, inBytesLen - bytesWritten);
+    }
+    if (!isUsrFound)
+    {
+        log<level::DEBUG>("User doesn't exist");
+        return 0;
+    }
+
+    // Read the key buff from key file
+    std::array<uint8_t, maxKeySize> keyBuff;
+    std::ifstream keyFile(encryptKeyFileName, std::ios::in | std::ios::binary);
+    if (!keyFile.good())
+    {
+        log<level::DEBUG>("Error in opening encryption key file");
+        return -EIO;
+    }
+    keyFile.read(reinterpret_cast<char*>(keyBuff.data()), keyBuff.size());
+    if (keyFile.fail())
+    {
+        log<level::DEBUG>("Error in reading encryption key file");
+        return -EIO;
+    }
+    keyFile.close();
+
+    // Read the original passwd file mode
+    struct stat st = {};
+    if (stat(passwdFileName, &st) != 0)
+    {
+        log<level::DEBUG>("Error in getting password file fstat()");
+        return -EIO;
+    }
+
+    // Create temporary file for write
+    std::string pwdFile(passwdFileName);
+    std::vector<char> tempFileName(pwdFile.begin(), pwdFile.end());
+    std::vector<char> fileTemplate = {'_', '_', 'X', 'X', 'X',
+                                      'X', 'X', 'X', '\0'};
+    tempFileName.insert(tempFileName.end(), fileTemplate.begin(),
+                        fileTemplate.end());
+    int fd = mkstemp((char*)tempFileName.data());
+    if (fd == -1)
+    {
+        log<level::DEBUG>("Error creating temp file");
+        return -EIO;
+    }
+
+    std::string strTempFileName(tempFileName.data());
+    // Open the temp file for writing from provided fd
+    // By "true", remove it at exit if still there.
+    // This is needed to cleanup the temp file at exception
+    phosphor::user::File temp(fd, strTempFileName, "w", true);
+    if ((temp)() == NULL)
+    {
+        close(fd);
+        log<level::DEBUG>("Error creating temp file");
+        return -EIO;
+    }
+    fd = -1; // don't use fd anymore, as the File object owns it
+
+    // Set the file mode as of actual ipmi-pass file.
+    if (fchmod(fileno((temp)()), st.st_mode) < 0)
+    {
+        log<level::DEBUG>("Error setting fchmod for temp file");
+        return -EIO;
+    }
+
+    const EVP_MD* digest = EVP_sha256();
+    size_t hashLen = EVP_MD_block_size(digest);
+    std::vector<uint8_t> hash(hashLen);
+    size_t ivLen = EVP_CIPHER_iv_length(cipher);
+    std::vector<uint8_t> iv(ivLen);
+    std::array<uint8_t, EVP_MAX_KEY_LENGTH> key;
+    size_t keyLen = key.size();
+    std::array<uint8_t, EVP_MAX_MD_SIZE> mac;
+    size_t macLen = mac.size();
+
+    // Create random hash and generate hash key which will be used for
+    // encryption.
+    if (RAND_bytes(hash.data(), hashLen) != 1)
+    {
+        log<level::DEBUG>("Hash genertion failed, bailing out");
+        return -EIO;
+    }
+    if (NULL == HMAC(digest, keyBuff.data(), keyBuff.size(), hash.data(),
+                     hashLen, key.data(),
+                     reinterpret_cast<unsigned int*>(&keyLen)))
+    {
+        log<level::DEBUG>("Failed to create MAC for authentication");
+        return -EIO;
+    }
+
+    // Generate IV values
+    if (RAND_bytes(iv.data(), ivLen) != 1)
+    {
+        log<level::DEBUG>("UV genertion failed, bailing out");
+        return -EIO;
+    }
+
+    // Encrypt the input data
+    std::vector<uint8_t> outBytes(inBytesLen + EVP_MAX_BLOCK_LENGTH);
+    size_t outBytesLen = 0;
+    if (inBytesLen != 0)
+    {
+        if (encryptDecryptData(true, EVP_aes_128_cbc(), key.data(), keyLen,
+                               iv.data(), ivLen, inBytes.data(), inBytesLen,
+                               mac.data(), &macLen, outBytes.data(),
+                               &outBytesLen) != 0)
+        {
+            log<level::DEBUG>("Error while encrypting the data");
+            return -EIO;
+        }
+        outBytes[outBytesLen] = 0;
+    }
+    OPENSSL_cleanse(key.data(), keyLen);
+
+    // Update the meta password structure.
+    metaPassStruct metaData = {META_PASSWD_SIG, {0, 0}, 0, 0, 0, 0, 0};
+    metaData.hashSize = hashLen;
+    metaData.ivSize = ivLen;
+    metaData.dataSize = bytesWritten;
+    metaData.padSize = outBytesLen - bytesWritten;
+    metaData.macSize = macLen;
+
+    if (fwrite(&metaData, 1, sizeof(metaData), (temp)()) != sizeof(metaData))
+    {
+        log<level::DEBUG>("Error in writing meta data");
+        return -EIO;
+    }
+
+    if (fwrite(&hash[0], 1, hashLen, (temp)()) != hashLen)
+    {
+        log<level::DEBUG>("Error in writing hash data");
+        return -EIO;
+    }
+
+    if (fwrite(&iv[0], 1, ivLen, (temp)()) != ivLen)
+    {
+        log<level::DEBUG>("Error in writing IV data");
+        return -EIO;
+    }
+
+    if (fwrite(&outBytes[0], 1, outBytesLen, (temp)()) != outBytesLen)
+    {
+        log<level::DEBUG>("Error in writing encrypted data");
+        return -EIO;
+    }
+
+    if (fwrite(&mac[0], 1, macLen, (temp)()) != macLen)
+    {
+        log<level::DEBUG>("Error in writing MAC data");
+        return -EIO;
+    }
+
+    if (fflush((temp)()))
+    {
+        log<level::DEBUG>(
+            "File fflush error while writing entries to special file");
+        return -EIO;
+    }
+
+    OPENSSL_cleanse(iv.data(), ivLen);
+
+    // Rename the tmp  file to actual file
+    if (std::rename(strTempFileName.data(), passwdFileName) != 0)
+    {
+        log<level::DEBUG>("Failed to rename tmp file to ipmi-pass");
+        return -EIO;
+    }
+
+    return 0;
+}
+
+std::time_t PasswdMgr::getUpdatedFileTime()
+{
     struct stat fileStat = {};
     if (stat(passwdFileName, &fileStat) != 0)
     {
-        log<level::DEBUG>("Error in getting last updated time stamp");
-        return;
+        log<level::DEBUG>("Error - Getting passwd file time stamp");
+        return -EIO;
     }
-    fileLastUpdatedTime = fileStat.st_mtime;
-    return;
+    return fileStat.st_mtime;
 }
 
 } // namespace ipmi
diff --git a/user_channel/passwd_mgr.hpp b/user_channel/passwd_mgr.hpp
index 3078e21..e5625bc 100644
--- a/user_channel/passwd_mgr.hpp
+++ b/user_channel/passwd_mgr.hpp
@@ -18,6 +18,7 @@
 
 #include <ctime>
 #include <unordered_map>
+#include <vector>
 
 namespace ipmi
 {
@@ -45,6 +46,14 @@
      */
     std::string getPasswdByUserName(const std::string& userName);
 
+    /** @brief Clear username and password entry for the specified user
+     *
+     *  @param[in] userName - username
+     *
+     * @return error response
+     */
+    int clearUserEntry(const std::string& userName);
+
   private:
     using UserName = std::string;
     using Password = std::string;
@@ -61,15 +70,32 @@
      * authentication.
      */
     void initPasswordMap(void);
-    /** @brief decrypts the data provided
+
+    /** @brief Function to read the encrypted password file data
      *
+     *  @param[out] outBytes - vector to hold decrypted password file data
+     *
+     * @return error response
+     */
+    int readPasswdFileData(std::vector<uint8_t>& outBytes);
+    /** @brief  Updates special password file by clearing the password entry
+     *  for the user specified.
+     *
+     *  @param[in] userName - user name entry that has to be removed.
+     *
+     * @return error response
+     */
+    int updatePasswdSpecialFile(const std::string& userName);
+    /** @brief encrypts or decrypt the data provided
+     *
+     *  @param[in] doEncrypt - do encrypt if set to true, else do decrypt.
      *  @param[in] cipher - cipher to be used
      *  @param[in] key - pointer to the key
      *  @param[in] keyLen - Length of the key to be used
      *  @param[in] iv - pointer to initialization vector
      *  @param[in] ivLen - Length of the iv
      *  @param[in] inBytes - input data to be encrypted / decrypted
-     *  @param[in] inBytesLen - input size to be decrypted
+     *  @param[in] inBytesLen - input size to be encrypted / decrypted
      *  @param[in] mac - message authentication code - to figure out corruption
      *  @param[in] macLen - size of MAC
      *  @param[in] outBytes - ptr to store output bytes
@@ -77,10 +103,17 @@
      *
      * @return error response
      */
-    int decrypt(const EVP_CIPHER* cipher, uint8_t* key, size_t keyLen,
-                uint8_t* iv, size_t ivLen, uint8_t* inBytes, size_t inBytesLen,
-                uint8_t* mac, size_t macLen, uint8_t* outBytes,
-                size_t* outBytesLen);
+    int encryptDecryptData(bool doEncrypt, const EVP_CIPHER* cipher,
+                           uint8_t* key, size_t keyLen, uint8_t* iv,
+                           size_t ivLen, uint8_t* inBytes, size_t inBytesLen,
+                           uint8_t* mac, size_t* macLen, uint8_t* outBytes,
+                           size_t* outBytesLen);
+
+    /** @brief  returns updated file time of passwd file entry.
+     *
+     * @return timestamp or -1 for error.
+     */
+    std::time_t getUpdatedFileTime();
 };
 
 } // namespace ipmi
diff --git a/user_channel/user_layer.cpp b/user_channel/user_layer.cpp
index dce33d9..ed99137 100644
--- a/user_channel/user_layer.cpp
+++ b/user_channel/user_layer.cpp
@@ -29,4 +29,10 @@
     return passwdMgr.getPasswdByUserName(userName);
 }
 
+ipmi_ret_t ipmiUserClearPassword(const std::string& userName)
+{
+    passwdMgr.clearUserEntry(userName);
+    return IPMI_CC_OK;
+}
+
 } // namespace ipmi
diff --git a/user_channel/user_layer.hpp b/user_channel/user_layer.hpp
index b797007..4040102 100644
--- a/user_channel/user_layer.hpp
+++ b/user_channel/user_layer.hpp
@@ -28,6 +28,15 @@
  */
 std::string ipmiUserGetPassword(const std::string& userName);
 
+/** @brief The IPMI call to clear password entry associated with specified
+ * username
+ *
+ *  @param[in] userName
+ *
+ *  @return 0 on success, non-zero otherwise.
+ */
+ipmi_ret_t ipmiUserClearPassword(const std::string& userName);
+
 // TODO: Define required user layer API Call's which user layer shared library
 // must implement.
 } // namespace ipmi