[#52] Make TPM2 Provisioner check for a running Resource Manager (#53)

[#52] Make TPM2 Provisioner check for a running Resource Manager
This commit is contained in:
apldev3 2018-11-26 16:45:22 -05:00 committed by GitHub
parent c12cb135f1
commit c4bc52bd42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 814 additions and 600 deletions

View File

@ -234,7 +234,7 @@ if(STATIC_ANALYSIS)
--library=posix.cfg
--error-exitcode=1
--verbose
-i src/ProvisionerTpm2.pb.cc
--suppress=readdirCalled
-I include/
src/
)
@ -257,7 +257,7 @@ if (${DISTRIBUTION} STREQUAL "Ubuntu")
set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_NAME "HIRSProvisionerTPM2.0")
set(CPACK_DEBIAN_PACKAGE_SECTION "admin")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "liblog4cplus-1.1-9(>=1.1.2), libcurlpp0(>=0.7), paccor")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "liblog4cplus-1.1-9(>=1.1.2), libcurlpp0(>=0.7), paccor, procps(>=3.3.0)")
# Set variables specific to Ubuntu release version
if (${DISTRIBUTION_VERSION} STREQUAL "16.04")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libre2-1v5(>=20160201), libprotobuf9v5(>=2.4.1)")
@ -279,7 +279,7 @@ elseif (${DISTRIBUTION} STREQUAL "CentOS Linux")
set(CPACK_RPM_PACKAGE_RELEASE_DIST "el7")
set(CPACK_RPM_PACKAGE_LICENSE "Apache License, Version 2.0")
set(CPACK_RPM_PACKAGE_GROUP "System Environment/Base")
set(CPACK_RPM_PACKAGE_REQUIRES "log4cplus >= 1.1.2, tpm2-tss >= 1.0, tpm2-tools >= 1.1.0, protobuf >= 2.4.1, re2 >= 20160401, libcurl >= 7.0.0, paccor")
set(CPACK_RPM_PACKAGE_REQUIRES "log4cplus >= 1.1.2, tpm2-tss >= 1.0, tpm2-tools >= 1.1.0, protobuf >= 2.4.1, re2 >= 20160401, libcurl >= 7.0.0, paccor, procps-ng >= 3.3.0")
set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/package/rpm-post-install.sh)
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /usr/local /usr/local/bin /usr/local/include /usr/local/lib)
set(CPACK_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_RELEASE}.${CPACK_RPM_PACKAGE_RELEASE_DIST}.${CMAKE_SYSTEM_PROCESSOR}")

View File

@ -14,4 +14,5 @@ Please look up their respective names in the CentOS repositories.
| re2 | 20160401 | 20160201 | CentOS 7 epel-release | https://github.com/google/re2 |
| tpm2-tss | 1.2.0 | 1.0.0 | CentOS 7 base | https://github.com/intel/tpm2-tss |
| tpm2-tools | 1.1.0 | 1.1.0 | CentOS 7 base | https://github.com/tpm2-software/tpm2-tools |
| paccor | 1.0.6 | none | | https://github.com/nsacyber/paccor |
| paccor | 1.0.6 | none | N/A | https://github.com/nsacyber/paccor |
| procps-ng | 3.3.10 | 3.3.0 | CentOS 7 base | https://gitlab.com/procps-ng/procps |

View File

@ -6,7 +6,7 @@
#include <Logger.h>
#include <ProvisionerTpm2.pb.h>
#include <Utils.h>
#include <Tpm2ToolsUtils.h>
#include <Tss.h>

View File

@ -20,6 +20,9 @@ class Process {
private:
static const hirs::log::Logger LOGGER;
static const char* const kPgrepCommand;
static const int kMaxStatFileProcessNameLength;
std::string executable;
std::string arguments;
@ -40,6 +43,8 @@ class Process {
std::string sourceFileName,
int sourceLineNumber,
const std::string& arguments = "");
static bool isRunning(const std::string& executable);
};
} // namespace utils

View File

@ -0,0 +1,112 @@
/**
* Copyright (C) 2017-2018, U.S. Government
*/
#ifndef HIRS_PROVISIONERTPM2_INCLUDE_TPM2TOOLSUTILS_H_
#define HIRS_PROVISIONERTPM2_INCLUDE_TPM2TOOLSUTILS_H_
#include <string>
#include <unordered_map>
namespace hirs {
namespace tpm2_tools_utils {
/**
* Enum class that provides list of supported tpm2_tools versions
*/
enum class Tpm2ToolsVersion {
VERSION_1_1_0,
VERSION_2_1_0,
VERSION_3
};
/**
* Utility class that determines the version of tpm2_tools present on the
* system.
*/
class Tpm2ToolsVersionChecker {
private:
static const std::unordered_map<std::string, Tpm2ToolsVersion> kVersionMap;
static const std::unordered_map<std::string,
Tpm2ToolsVersion> kMaxSupportedVersionMap;
static std::string getDistribution();
public:
/**
* Makes a simple tpm2-tools call to determine the version available on the
* current system.
*
* @return enum specifying the version of tpm2-tools available locally
*/
static Tpm2ToolsVersion findTpm2ToolsVersion();
};
/**
* Utility class that provides functions to parse information from tpm2_tools
* output.
*/
class Tpm2ToolsOutputParser {
public:
/**
* Parses the provided Non-volatile (NV) Index List for the data size of
* the index at the prescribed NV handle. Expects output from tpm2_nvlist.
*
* @param nvHandle memory address to search the nvListOutput for
* @param nvListOutput the NV Index List to search for the data size
* @return the size of the desired NV index or 0 if the index isn't found
*/
static uint16_t parseNvDataSize(const std::string& nvHandle,
const std::string& nvListOutput);
/**
* Pulls the data out of the output from a tpm2_nvread command.
*
* @param nvReadOutput the output from a call to tpm2_nvread
* @return the data serialized as bytes, or an empty string if
* nvReadOutput improperly formatted
*/
static std::string parseNvReadOutput(const std::string& nvReadOutput);
/**
* Parses the provided Persistent Object List for the provided handle.
*
* @param handle memory address to search the nvListPersistentOutput for
* @param listPersistentOutput the Persistent Object list to search
* @return true, if handle is found / false, otherwise
*/
static bool parsePersistentObjectExists(const std::string& handle,
const std::string& listPersistentOutput);
/**
* Parses the provided tpm2-tool output for a TPM Error Code.
*
* @param toolOutput the output from a call to any of the tpm2-tools
* @return a TPM error code if found, or an empty string, otherwise
*/
static std::string parseTpmErrorCode(const std::string& toolOutput);
/**
* Parses the provided tpm2-tool output for a tpm2_tools version.
*
* @param toolOutput the output from a call to any of the tpm2-tools
* @return a tpm2_tools version if found, or an empty string, otherwise
*/
static std::string parseTpm2ToolsVersion(const std::string& toolOutput);
/**
* Parses the provided tpm2-tool version for the major version.
*
* @param toolVersion the output from a call to parseTpm2ToolsVersion
* @return tpm2_tools major version if found, or an empty string, otherwise
*/
static std::string parseTpm2ToolsMajorVersion(
const std::string& toolVersion);
};
} // namespace tpm2_tools_utils
} // namespace hirs
#endif // HIRS_PROVISIONERTPM2_INCLUDE_TPM2TOOLSUTILS_H_

View File

@ -4,11 +4,7 @@
#ifndef HIRS_PROVISIONERTPM2_INCLUDE_UTILS_H_
#define HIRS_PROVISIONERTPM2_INCLUDE_UTILS_H_
#include <re2/re2.h>
#include <string>
#include <unordered_map>
#include <vector>
namespace hirs {
@ -45,6 +41,8 @@ namespace file_utils {
const std::string& outFilename,
int startPos,
int readSize);
std::string trimFilenameFromPath(const std::string& path);
} // namespace file_utils
namespace json_utils {
@ -152,104 +150,6 @@ namespace string_utils {
std::string trimWhitespaceFromBothEnds(std::string str);
} // namespace string_utils
namespace tpm2_tools_utils {
/**
* Enum class that provides list of supported tpm2_tools versions
*/
enum class Tpm2ToolsVersion {
VERSION_1_1_0,
VERSION_2_1_0,
VERSION_3
};
/**
* Utility class that determines the version of tpm2_tools present on the
* system.
*/
class Tpm2ToolsVersionChecker {
private:
static const std::unordered_map<std::string, Tpm2ToolsVersion> kVersionMap;
static const std::unordered_map<std::string,
Tpm2ToolsVersion> kMaxSupportedVersionMap;
static std::string getDistribution();
public:
/**
* Makes a simple tpm2-tools call to determine the version available on the
* current system.
*
* @return enum specifying the version of tpm2-tools available locally
*/
static Tpm2ToolsVersion findTpm2ToolsVersion();
};
/**
* Utility class that provides functions to parse information from tpm2_tools
* output.
*/
class Tpm2ToolsOutputParser {
public:
/**
* Parses the provided Non-volatile (NV) Index List for the data size of
* the index at the prescribed NV handle. Expects output from tpm2_nvlist.
*
* @param nvHandle memory address to search the nvListOutput for
* @param nvListOutput the NV Index List to search for the data size
* @return the size of the desired NV index or 0 if the index isn't found
*/
static uint16_t parseNvDataSize(const std::string& nvHandle,
const std::string& nvListOutput);
/**
* Pulls the data out of the output from a tpm2_nvread command.
*
* @param nvReadOutput the output from a call to tpm2_nvread
* @return the data serialized as bytes, or an empty string if
* nvReadOutput improperly formatted
*/
static std::string parseNvReadOutput(const std::string& nvReadOutput);
/**
* Parses the provided Persistent Object List for the provided handle.
*
* @param handle memory address to search the nvListPersistentOutput for
* @param listPersistentOutput the Persistent Object list to search
* @return true, if handle is found / false, otherwise
*/
static bool parsePersistentObjectExists(const std::string& handle,
const std::string& listPersistentOutput);
/**
* Parses the provided tpm2-tool output for a TPM Error Code.
*
* @param toolOutput the output from a call to any of the tpm2-tools
* @return a TPM error code if found, or an empty string, otherwise
*/
static std::string parseTpmErrorCode(const std::string& toolOutput);
/**
* Parses the provided tpm2-tool output for a tpm2_tools version.
*
* @param toolOutput the output from a call to any of the tpm2-tools
* @return a tpm2_tools version if found, or an empty string, otherwise
*/
static std::string parseTpm2ToolsVersion(const std::string& toolOutput);
/**
* Parses the provided tpm2-tool version for the major version.
*
* @param toolVersion the output from a call to parseTpm2ToolsVersion
* @return tpm2_tools major version if found, or an empty string, otherwise
*/
static std::string parseTpm2ToolsMajorVersion(
const std::string& toolVersion);
};
} // namespace tpm2_tools_utils
} // namespace hirs
#endif // HIRS_PROVISIONERTPM2_INCLUDE_UTILS_H_

View File

@ -11,6 +11,7 @@ add_library(TPM2_PROVISIONER_LIBRARY
Process.cpp
Properties.cpp
RestfulClientProvisioner.cpp
Tpm2ToolsUtils.cpp
Utils.cpp
# Header Files
@ -21,6 +22,7 @@ add_library(TPM2_PROVISIONER_LIBRARY
${CMAKE_SOURCE_DIR}/include/Process.h
${CMAKE_SOURCE_DIR}/include/Properties.h
${CMAKE_SOURCE_DIR}/include/RestfulClientProvisioner.h
${CMAKE_SOURCE_DIR}/include/Tpm2ToolsUtils.h
${CMAKE_SOURCE_DIR}/include/Tss.h
${CMAKE_SOURCE_DIR}/include/Utils.h
${CMAKE_SOURCE_DIR}/include/Version.h

View File

@ -3,8 +3,11 @@
*/
#include <Process.h>
#include <Logger.h>
#include <HirsRuntimeException.h>
#include <Utils.h>
#include <arpa/inet.h>
#include <dirent.h>
#include <cstdio>
#include <cerrno>
@ -14,18 +17,27 @@
#include <iostream>
#include <string>
#include <utility>
#include <HirsRuntimeException.h>
using hirs::exception::HirsRuntimeException;
using hirs::log::Logger;
using hirs::utils::Process;
using hirs::file_utils::dirExists;
using hirs::file_utils::fileExists;
using hirs::file_utils::fileToString;
using hirs::file_utils::trimFilenameFromPath;
using hirs::string_utils::trimChar;
using std::cerr;
using std::endl;
using std::ostream;
using std::stringstream;
using std::string;
using std::to_string;
const Logger Process::LOGGER = Logger::getDefaultLogger();
const char* const Process::kPgrepCommand = "pgrep";
const int Process::kMaxStatFileProcessNameLength = 15;
/**
* Constructor.
* @param executable the executable to be run
@ -76,7 +88,7 @@ int Process::run() {
* @param osForErrorLogging ostream to collect error message on failure
* @return the return value of the Linux process (between 0-255)
*/
int Process::run(std::ostream& osForErrorLogging) {
int Process::run(ostream& osForErrorLogging) {
int processReturnValue = run();
if (processReturnValue != 0) {
osForErrorLogging << "Call to " << executable
@ -111,7 +123,7 @@ string Process::getOutputString() const {
* executable (defaults to empty string)
*/
string Process::run(const string& executable,
std::string sourceFileName,
string sourceFileName,
int sourceLineNumber,
const string& arguments) {
stringstream errorStream;
@ -121,7 +133,7 @@ string Process::run(const string& executable,
<< "Process Output: "
<< p.getOutputString();
throw HirsRuntimeException(errorStream.str(),
sourceFileName + ": " + std::to_string(sourceLineNumber));
sourceFileName + ": " + to_string(sourceLineNumber));
}
// Remove trailing newline if one exists
@ -131,3 +143,37 @@ string Process::run(const string& executable,
}
return str;
}
/**
* Static function to check if a specified process is currently running in the
* local environment.
*
* @param executable the executable to check is running
* @return true, if executable is found to be running / false, otherwise
*/
bool Process::isRunning(const string& executable) {
// Check if executable includes path and trim to just process name if so
string processName = trimFilenameFromPath(executable);
// Log warning about including path to executable
if (processName.length() < executable.length()) {
stringstream warnStream;
warnStream << "Including the path to an executable isn't recommended "
<< "as this has no bearing on whether it's determined to "
<< "be running in the local environment.";
LOGGER.warn(warnStream.str());
}
// Sanitize any attempts to hijack the process
processName = trimChar(processName, ';');
// If the process name is longer than 15 characters log a warning
if (processName.length() > kMaxStatFileProcessNameLength) {
stringstream warnStream;
warnStream << "A process name with length greater than "
<< to_string(kMaxStatFileProcessNameLength)
<< " may result in a false negative depending on the"
<< " current runtime environment.";
LOGGER.warn(warnStream.str());
}
return Process(kPgrepCommand, "-c " + processName).run() == 0;
}

View File

@ -30,6 +30,7 @@ using hirs::log::Logger;
using hirs::tpm2::AsymmetricKeyType;
using hirs::tpm2::CommandTpm2;
using hirs::tpm2_tools_utils::Tpm2ToolsVersion;
using hirs::utils::Process;
using std::cout;
using std::cerr;
using std::endl;
@ -138,8 +139,21 @@ int main(int argc, char** argv) {
if (argument == "provision") {
// Ensure we're running as root
if (getuid() != 0) {
cerr << ("Program must be run as root. Exiting");
mainLogger.error("Program must be run as root. Exiting");
string error = "Program must be run as root. Exiting";
cerr << (error);
mainLogger.error(error);
return 1;
}
// Ensure either tpm2-abrmd or the old resourcemgr is running
if (!Process::isRunning("tpm2-abrmd")
&& !Process::isRunning("resourcemgr")) {
stringstream errorStream;
errorStream << R"(Neither "tpm2-abmrd" nor the older )"
<< R"("resourcemgr" daemon is currently running. )"
<< "\nPlease ensure either is running before "
<< "attempting provisioning.\n";
cerr << (errorStream.str());
mainLogger.error(errorStream.str());
return 1;
}
cout << "--> Provisioning" << endl;

View File

@ -0,0 +1,197 @@
/**
* Copyright (C) 2017-2018, U.S. Government
*/
#include <Tpm2ToolsUtils.h>
#include <HirsRuntimeException.h>
#include <Process.h>
#include <Utils.h>
#include <re2/re2.h>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <vector>
using std::ifstream;
using std::out_of_range;
using std::string;
using std::stringstream;
using std::unordered_map;
using std::vector;
using hirs::exception::HirsRuntimeException;
namespace hirs {
namespace tpm2_tools_utils {
const unordered_map<string, Tpm2ToolsVersion>
Tpm2ToolsVersionChecker::kVersionMap = {
{"1.1.0", Tpm2ToolsVersion::VERSION_1_1_0 },
{"2.1.0", Tpm2ToolsVersion::VERSION_2_1_0 },
{"3", Tpm2ToolsVersion::VERSION_3 }
};
const unordered_map<string, Tpm2ToolsVersion>
Tpm2ToolsVersionChecker::kMaxSupportedVersionMap = {
{"Ubuntu 17.10", Tpm2ToolsVersion::VERSION_1_1_0 },
{"Ubuntu 18.04", Tpm2ToolsVersion::VERSION_2_1_0 },
{"Ubuntu 18.10", Tpm2ToolsVersion::VERSION_2_1_0 },
{"CentOS Linux 7", Tpm2ToolsVersion::VERSION_3 }
};
Tpm2ToolsVersion Tpm2ToolsVersionChecker::findTpm2ToolsVersion() {
string versionOutput = RUN_PROCESS_OR_THROW("tpm2_nvlist", "-v");
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput);
string majorVersion = Tpm2ToolsOutputParser::parseTpm2ToolsMajorVersion(
version);
if (!version.empty()) {
try {
// Look to see if tpm2-tools major version is supported
return kVersionMap.at(majorVersion);
}
catch (const out_of_range& oor) {
// If major version not supported, then look for specific version
try {
return kVersionMap.at(version);
}
catch (const out_of_range& oor) {
// If no version found, version is unsupported, throw exception
stringstream ss;
ss << "Unsupported Tpm2 Tools Version Detected: " << version;
throw HirsRuntimeException(ss.str(),
"Tpm2ToolsVersionChecker::findTpm2ToolsVersion");
}
}
} else {
// If version check returns empty, instead of throwing exception,
// then tpm2-tools is installed but version lookup is faulty.
// Get current runtime environment distribution.
string currentDistribution = getDistribution();
try {
// Look to see if current distribution has a supported version
// and use that as best guess at version number
return kMaxSupportedVersionMap.at(currentDistribution);
} catch (const out_of_range& oor) {
stringstream ss;
ss << "Unsupported Distribution Detected: " << currentDistribution;
throw HirsRuntimeException(ss.str(),
"Tpm2ToolsVersionChecker::findTpm2ToolsVersion");
}
}
}
string Tpm2ToolsVersionChecker::getDistribution() {
stringstream completeDistro;
string distribution;
string distributionRelease;
ifstream releaseFile;
string line;
releaseFile.open("/etc/os-release");
if (releaseFile.is_open()) {
while (getline(releaseFile, line)) {
stringstream ss(line);
string item;
vector<string> tokens;
while (getline(ss, item, '=')) {
tokens.push_back(item);
}
if (!tokens.empty() && tokens.at(0) == "NAME") {
distribution = string_utils::trimQuotes(tokens.at(1));
} else if (!tokens.empty() && tokens.at(0) == "VERSION_ID") {
distributionRelease = string_utils::trimQuotes(tokens.at(1));
}
}
completeDistro << distribution << " " << distributionRelease;
releaseFile.close();
}
return completeDistro.str();
}
uint16_t Tpm2ToolsOutputParser::parseNvDataSize(const string &nvHandle,
const string &nvListOutput) {
stringstream regexPatternStream;
regexPatternStream << nvHandle
<< "(?:.*\\n)+?"
<< "(?i).*size\\S*:\\s*([0-9]+)";
uint16_t dataSize;
if (RE2::PartialMatch(nvListOutput, regexPatternStream.str(), &dataSize)) {
return dataSize;
} else {
return 0;
}
}
string Tpm2ToolsOutputParser::parseNvReadOutput(const string &nvReadOutput) {
stringstream regexPatternStream;
regexPatternStream << ".*\\n*The size of data:[0-9]+";
string byteString = nvReadOutput;
// Remove tpm2_nvlist header
int numReplacements = RE2::GlobalReplace(&byteString,
regexPatternStream.str(), "");
if (numReplacements != 0) {
// Remove any non-hexadecimal characters
RE2::GlobalReplace(&byteString, "[^0-9A-Fa-f]+", "");
return string_utils::hexToBytes(byteString);
} else {
return "";
}
}
bool Tpm2ToolsOutputParser::parsePersistentObjectExists(
const std::string &handle,
const std::string &listPersistentOutput) {
stringstream regexPatternStream;
regexPatternStream << "(?i)Persistent.*handle.*:\\s*"
<< handle;
return RE2::PartialMatch(listPersistentOutput, regexPatternStream.str());
}
string Tpm2ToolsOutputParser::parseTpmErrorCode(const string& toolOutput) {
stringstream regexPatternStream;
regexPatternStream << "(?i)Error.*:\\s*(0x[0-9a-fA-F]{3})";
string errorCode;
if (RE2::PartialMatch(toolOutput, regexPatternStream.str(), &errorCode)) {
return errorCode;
} else {
return "";
}
}
string Tpm2ToolsOutputParser::parseTpm2ToolsVersion(const string& toolOutput) {
stringstream regexPatternStream;
regexPatternStream << "(?i)version[^0-9]*([0-9]+\\.[0-9]+\\.[0-9]+).*";
string version;
if (RE2::PartialMatch(toolOutput, regexPatternStream.str(), &version)) {
return version;
} else {
return "";
}
}
string Tpm2ToolsOutputParser::parseTpm2ToolsMajorVersion(
const string& toolVersion) {
stringstream regexPatternStream;
regexPatternStream << "^([0-9]+)\\.[0-9]+\\.[0-9]+$";
string majorVersion;
if (RE2::PartialMatch(toolVersion, regexPatternStream.str(),
&majorVersion)) {
return majorVersion;
} else {
return "";
}
}
} // namespace tpm2_tools_utils
} // namespace hirs

View File

@ -3,7 +3,8 @@
*/
#include <Utils.h>
#include <HirsRuntimeException.h>
#include <Process.h>
#include <re2/re2.h>
#include <sys/stat.h>
#include <sstream>
@ -13,21 +14,17 @@
#include <algorithm>
#include <cctype>
#include <string>
#include <stdexcept>
#include <unordered_map>
#include <vector>
using std::hex;
using std::ifstream;
using std::ios;
using std::ofstream;
using std::out_of_range;
using std::remove;
using std::setfill;
using std::setw;
using std::string;
using std::stringstream;
using std::unordered_map;
using std::vector;
using hirs::exception::HirsRuntimeException;
@ -159,6 +156,21 @@ namespace file_utils {
delete[] fileBlock;
}
/**
* Returns the filename from the end of a filesystem path
* @param path the filesystem path
* @return the filename from the path
*/
string trimFilenameFromPath(const string& path) {
auto lastPathSeparatorIndex = path.find_last_of('/');
// Return path if it wasn't actually a path
if (lastPathSeparatorIndex == string::npos) {
return path;
}
return path.substr(lastPathSeparatorIndex + 1);
}
} // namespace file_utils
namespace string_utils {
@ -259,172 +271,4 @@ namespace string_utils {
} // namespace string_utils
namespace tpm2_tools_utils {
const unordered_map<string, Tpm2ToolsVersion>
Tpm2ToolsVersionChecker::kVersionMap = {
{"1.1.0", Tpm2ToolsVersion::VERSION_1_1_0 },
{"2.1.0", Tpm2ToolsVersion::VERSION_2_1_0 },
{"3", Tpm2ToolsVersion::VERSION_3 }
};
const unordered_map<string, Tpm2ToolsVersion>
Tpm2ToolsVersionChecker::kMaxSupportedVersionMap = {
{"Ubuntu 17.10", Tpm2ToolsVersion::VERSION_1_1_0 },
{"Ubuntu 18.04", Tpm2ToolsVersion::VERSION_2_1_0 },
{"Ubuntu 18.10", Tpm2ToolsVersion::VERSION_2_1_0 },
{"CentOS Linux 7", Tpm2ToolsVersion::VERSION_3 }
};
Tpm2ToolsVersion Tpm2ToolsVersionChecker::findTpm2ToolsVersion() {
string versionOutput = RUN_PROCESS_OR_THROW("tpm2_nvlist", "-v");
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput);
string majorVersion = Tpm2ToolsOutputParser::parseTpm2ToolsMajorVersion(
version);
if (!version.empty()) {
try {
// Look to see if tpm2-tools major version is supported
return kVersionMap.at(majorVersion);
}
catch (const out_of_range& oor) {
// If major version not supported, then look for specific version
try {
return kVersionMap.at(version);
}
catch (const out_of_range& oor) {
// If no version found, version is unsupported, throw exception
stringstream ss;
ss << "Unsupported Tpm2 Tools Version Detected: " << version;
throw HirsRuntimeException(ss.str(),
"Tpm2ToolsVersionChecker::findTpm2ToolsVersion");
}
}
} else {
// If version check returns empty, instead of throwing exception,
// then tpm2-tools is installed but version lookup is faulty.
// Get current runtime environment distribution.
string currentDistribution = getDistribution();
try {
// Look to see if current distribution has a supported version
// and use that as best guess at version number
return kMaxSupportedVersionMap.at(currentDistribution);
} catch (const out_of_range& oor) {
stringstream ss;
ss << "Unsupported Distribution Detected: " << currentDistribution;
throw HirsRuntimeException(ss.str(),
"Tpm2ToolsVersionChecker::findTpm2ToolsVersion");
}
}
}
string Tpm2ToolsVersionChecker::getDistribution() {
stringstream completeDistro;
string distribution;
string distributionRelease;
ifstream releaseFile;
string line;
releaseFile.open("/etc/os-release");
if (releaseFile.is_open()) {
while (getline(releaseFile, line)) {
stringstream ss(line);
string item;
vector<string> tokens;
while (getline(ss, item, '=')) {
tokens.push_back(item);
}
if (!tokens.empty() && tokens.at(0) == "NAME") {
distribution = string_utils::trimQuotes(tokens.at(1));
} else if (!tokens.empty() && tokens.at(0) == "VERSION_ID") {
distributionRelease = string_utils::trimQuotes(tokens.at(1));
}
}
completeDistro << distribution << " " << distributionRelease;
releaseFile.close();
}
return completeDistro.str();
}
uint16_t Tpm2ToolsOutputParser::parseNvDataSize(const string &nvHandle,
const string &nvListOutput) {
stringstream regexPatternStream;
regexPatternStream << nvHandle
<< "(?:.*\\n)+?"
<< "(?i).*size\\S*:\\s*([0-9]+)";
uint16_t dataSize;
if (RE2::PartialMatch(nvListOutput, regexPatternStream.str(), &dataSize)) {
return dataSize;
} else {
return 0;
}
}
string Tpm2ToolsOutputParser::parseNvReadOutput(const string &nvReadOutput) {
stringstream regexPatternStream;
regexPatternStream << ".*\\n*The size of data:[0-9]+";
string byteString = nvReadOutput;
// Remove tpm2_nvlist header
int numReplacements = RE2::GlobalReplace(&byteString,
regexPatternStream.str(), "");
if (numReplacements != 0) {
// Remove any non-hexadecimal characters
RE2::GlobalReplace(&byteString, "[^0-9A-Fa-f]+", "");
return string_utils::hexToBytes(byteString);
} else {
return "";
}
}
bool Tpm2ToolsOutputParser::parsePersistentObjectExists(
const std::string &handle,
const std::string &listPersistentOutput) {
stringstream regexPatternStream;
regexPatternStream << "(?i)Persistent.*handle.*:\\s*"
<< handle;
return RE2::PartialMatch(listPersistentOutput, regexPatternStream.str());
}
string Tpm2ToolsOutputParser::parseTpmErrorCode(const string& toolOutput) {
stringstream regexPatternStream;
regexPatternStream << "(?i)Error.*:\\s*(0x[0-9a-fA-F]{3})";
string errorCode;
if (RE2::PartialMatch(toolOutput, regexPatternStream.str(), &errorCode)) {
return errorCode;
} else {
return "";
}
}
string Tpm2ToolsOutputParser::parseTpm2ToolsVersion(const string& toolOutput) {
stringstream regexPatternStream;
regexPatternStream << "(?i)version[^0-9]*([0-9]+\\.[0-9]+\\.[0-9]+).*";
string version;
if (RE2::PartialMatch(toolOutput, regexPatternStream.str(), &version)) {
return version;
} else {
return "";
}
}
string Tpm2ToolsOutputParser::parseTpm2ToolsMajorVersion(
const string& toolVersion) {
stringstream regexPatternStream;
regexPatternStream << "^([0-9]+)\\.[0-9]+\\.[0-9]+$";
string majorVersion;
if (RE2::PartialMatch(toolVersion, regexPatternStream.str(),
&majorVersion)) {
return majorVersion;
} else {
return "";
}
}
} // namespace tpm2_tools_utils
} // namespace hirs

View File

@ -45,6 +45,7 @@ macro(register_test TEST_TARGET_NAME)
endmacro()
register_test(Process)
register_test(RestfulClientProvisioner)
register_test(Properties)
register_test(RestfulClientProvisioner)
register_test(Tpm2ToolsUtils)
register_test(Utils)

View File

@ -10,6 +10,10 @@
#include "log4cplus/configurator.h"
#include "gtest/gtest.h"
using hirs::utils::Process;
using std::string;
using std::stringstream;
namespace {
class ProcessTest : public :: testing::Test {
@ -36,55 +40,75 @@ class ProcessTest : public :: testing::Test {
};
TEST_F(ProcessTest, ProcessWorks) {
hirs::utils::Process p("echo \"Hello World\"");
Process p("echo \"Hello World\"");
int retVal = p.run();
ASSERT_EQ(retVal, 0);
ASSERT_EQ("Hello World\n", p.getOutputString());
}
TEST_F(ProcessTest, ProcessTwoArgConstructorWorks) {
hirs::utils::Process p("echo", "\"Hello World\"");
Process p("echo", "\"Hello World\"");
int retVal = p.run();
ASSERT_EQ(retVal, 0);
ASSERT_EQ("Hello World\n", p.getOutputString());
}
TEST_F(ProcessTest, ProcessFailsWithNonZeroReturnValue) {
hirs::utils::Process p("ls", "isjlfidjsaij");
Process p("ls", "isjlfidjsaij");
int retVal = p.run();
ASSERT_EQ(retVal, 2);
}
TEST_F(ProcessTest, NonExistentProcessFailsWithNonZeroReturnValue) {
hirs::utils::Process p("isjlfidjsaij");
Process p("isjlfidjsaij");
int retVal = p.run();
ASSERT_EQ(retVal, 127);
}
TEST_F(ProcessTest, NonExistentProcessFailsAndGivesErrorMessage) {
hirs::utils::Process p("isjlfidjsaij", "ijijdfi");
std::stringstream expectedError;
Process p("isjlfidjsaij", "ijijdfi");
stringstream expectedError;
expectedError << "Call to isjlfidjsaij returned 127" << std::endl
<< "Is isjlfidjsaij in your path?" << std::endl;
std::string expectedErrorString(expectedError.str());
string expectedErrorString(expectedError.str());
std::stringstream errorStream;
stringstream errorStream;
int retVal = p.run(errorStream);
ASSERT_EQ(retVal, 127);
std::string receivedErrorString(errorStream.str());
string receivedErrorString(errorStream.str());
ASSERT_EQ(receivedErrorString, expectedErrorString);
}
TEST_F(ProcessTest, SuccessfulProcessDoesNotProduceErrorMessage) {
hirs::utils::Process p("echo", "\"Hello World\"");
Process p("echo", "\"Hello World\"");
std::stringstream errorStream;
stringstream errorStream;
int retVal = p.run(errorStream);
ASSERT_EQ(retVal, 0);
std::string receivedErrorString(errorStream.str());
string receivedErrorString(errorStream.str());
ASSERT_TRUE(receivedErrorString.empty());
}
TEST_F(ProcessTest, ProcessIsRunningSuccessful) {
ASSERT_TRUE(Process::isRunning("Process"));
}
TEST_F(ProcessTest, ProcessIsRunningSuccessfulPathBased) {
ASSERT_TRUE(Process::isRunning("/opt/Process"));
}
TEST_F(ProcessTest, ProcessIsRunningFalse) {
ASSERT_FALSE(Process::isRunning("foobar"));
}
TEST_F(ProcessTest, ProcessIsRunningEmptyStringReturnsFalse) {
ASSERT_FALSE(Process::isRunning(""));
}
TEST_F(ProcessTest, ProcessIsRunningPreventCommandHijack) {
ASSERT_FALSE(Process::isRunning("foobar; echo blarg"));
}
} // namespace
int main(int argc, char **argv) {

View File

@ -0,0 +1,348 @@
/**
* Copyright (C) 2017-2018, U.S. Government
*/
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include "gtest/gtest.h"
#include "Tpm2ToolsUtils.h"
using std::string;
using std::stringstream;
using hirs::tpm2_tools_utils::Tpm2ToolsOutputParser;
namespace {
class Tpm2ToolsUtilsTest : public :: testing::Test {
protected:
Tpm2ToolsUtilsTest() {
// You can do set-up work for each test here.
}
virtual ~Tpm2ToolsUtilsTest() {
// You can do clean-up work that doesn't throw exceptions here.
}
virtual void SetUp() {
// Code here will be called immediately after the constructor (right
// before each test).
}
virtual void TearDown() {
// Code here will be called immediately after each test (right
// before the destructor).
}
};
TEST_F(Tpm2ToolsUtilsTest, ParseNvDataSizeSuccess) {
stringstream nvListOutput;
nvListOutput << "2 NV indexes defined.\n"
<< "\n"
<< " 0. NV Index: 0x1800001\n"
<< " {\n"
<< "\tHash algorithm(nameAlg):11\n"
<< "\tThe Index attributes(attributes):0x62042c04\n"
<< "\tThe size of the data area(dataSize):70\n"
<< " }\n"
<< "\n"
<< " 1. NV Index: 0x1c00002\n"
<< " {\n"
<< "\tHash algorithm(nameAlg):11\n"
<< "\tThe Index attributes(attributes):0x620f1001\n"
<< "\tThe size of the data area(dataSize):991\n"
<< " }\n";
uint16_t addressSize = Tpm2ToolsOutputParser::parseNvDataSize(
"0x1c00002", nvListOutput.str());
ASSERT_EQ(991, addressSize);
}
TEST_F(Tpm2ToolsUtilsTest, ParseNvDataSizeSuccessTpm2ToolsV3) {
stringstream nvListOutput;
nvListOutput << "0x1c00002\n"
<< "\thash algorithm:\n"
<< "\t\tfriendly: sha256\n"
<< "\t\tvalue: 0xB\n"
<< "\tattributes:\n"
<< "\t\tfriendly: ownerwrite|policywrite\n"
<< "\t\tvalue: 0xA000220\n"
<< "\tsize: 991\n\n"
<< "0x1c00003\n"
<< "\thash algorithm:\n"
<< "\t\tfriendly: sha256\n"
<< "\t\tvalue: 0xB\n"
<< "\tattributes:\n"
<< "\t\tfriendly: ownerwrite|policywrite\n"
<< "\t\tvalue: 0xA000220\n"
<< "\tsize: 1722\n\n";
uint16_t addressSize = Tpm2ToolsOutputParser::parseNvDataSize(
"0x1c00002", nvListOutput.str());
ASSERT_EQ(991, addressSize);
}
TEST_F(Tpm2ToolsUtilsTest, ParseNvDataSizeFailure) {
stringstream nvListOutput;
nvListOutput << "0 NV indexes defined.\n";
uint16_t addressSize = Tpm2ToolsOutputParser::parseNvDataSize(
"0x1c00002", nvListOutput.str());
ASSERT_EQ(0, addressSize);
}
TEST_F(Tpm2ToolsUtilsTest, ParseNvReadSuccess) {
stringstream nvReadOutput;
nvReadOutput << "The size of data:10\n"
<< " 30 7f 03 6d 30 7f 03 7e 3c 03";
string nvReadData = Tpm2ToolsOutputParser::parseNvReadOutput(
nvReadOutput.str());
string expectedOutput = {48, 127, 3, 109, 48, 127, 3, 126, 60, 3};
ASSERT_EQ(expectedOutput, nvReadData);
}
TEST_F(Tpm2ToolsUtilsTest, ParseNvReadFailure) {
stringstream nvReadOutput;
nvReadOutput << "Failed to read NVRAM area at index 0x1c00001 "
<< "(29360129).Error:0x28b\n";
string nvReadData = Tpm2ToolsOutputParser::parseNvReadOutput(
nvReadOutput.str());
ASSERT_EQ("", nvReadData);
}
TEST_F(Tpm2ToolsUtilsTest, ParsePersistentObjectExistsSuccess) {
stringstream listPersistentOutput;
listPersistentOutput << "1 persistent objects defined.\n"
<< "\n"
<< " 0. Persistent handle: 0x81010001\n"
<< " {\n"
<< "\tType: 0x1\n"
<< "\tHash algorithm(nameAlg): 0xb\n"
<< "\tAttributes: 0x300b2\n"
<< " }\n";
ASSERT_TRUE(Tpm2ToolsOutputParser::parsePersistentObjectExists(
"0x81010001", listPersistentOutput.str()));
}
TEST_F(Tpm2ToolsUtilsTest, ParsePersistentObjectExistsSuccessTpm2ToolsV3) {
stringstream listPersistentOutput;
listPersistentOutput << "persistent-handle[0]:0x81010001 "
<< "key-alg:rsa hash-alg:sha256 "
<< "object-attr:fixedtpm|fixedparent";
ASSERT_TRUE(Tpm2ToolsOutputParser::parsePersistentObjectExists(
"0x81010001", listPersistentOutput.str()));
}
TEST_F(Tpm2ToolsUtilsTest, ParsePersistentObjectExistsFailure) {
stringstream listPersistentOutput;
listPersistentOutput << "0 persistent objects defined.\n";
ASSERT_FALSE(Tpm2ToolsOutputParser::parsePersistentObjectExists(
"0x81010001", listPersistentOutput.str()));
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpmErrorCodeSuccessAnyCharBetweenErrorAndCode) {
stringstream errorOutput;
errorOutput << "Create Object Failed ! ErrorCode: 0x922";
string expectedOutput = "0x922";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpmErrorCodeSuccessHexChars) {
stringstream errorOutput;
errorOutput << "Failed to read NVRAM area at index 0x1c00003"
<< " (29360131).Error:0x28b";
string expectedOutput = "0x28b";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpmErrorCodeSuccessFirstThreeHex) {
stringstream errorOutput;
errorOutput << "Failed to read NVRAM area at index 0x1c00003"
<< " (29360131).Error:0x28b90210";
string expectedOutput = "0x28b";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpmErrorCodeSuccessMultiline) {
stringstream errorOutput;
errorOutput << "Failed to read NVRAM area at index 0x1c00003"
<< " (29360131).Error:\n\n0x28b";
string expectedOutput = "0x28b";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpmErrorCodeSuccessCapitalHex) {
stringstream errorOutput;
errorOutput << "Failed to read NVRAM area at index 0x1c00003"
<< " (29360131).Error:\n\n0x28B";
string expectedOutput = "0x28B";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpmErrorCodeFailNonHex) {
stringstream errorOutput;
errorOutput << "Failed to read NVRAM area at index 0x1c00003"
<< " (29360131).Error:0x28g";
string expectedOutput = "";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpmErrorCodeFailNonHexFormatted) {
stringstream errorOutput;
errorOutput << "Failed to read NVRAM area at index 0x1c00003"
<< " (29360131).Error:28b";
string expectedOutput = "";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpmErrorCodeFailNotErrorCode) {
stringstream errorOutput;
errorOutput << "Easter Egg to be found at memory address: 0x042";
string expectedOutput = "";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpm2ToolsVersionSuccess) {
stringstream versionOutput;
versionOutput << R"(tool="tpm2_rc_decode" version="3.0.1")"
<< R"(tctis="tabrmd,socket,device,")";
string expectedOutput = "3.0.1";
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, version);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpm2ToolsVersionSuccessCaseInsensitive) {
stringstream versionOutput;
versionOutput << R"(tool="tpm2_rc_decode" VeRSion="3.0.1")"
<< R"(tctis="tabrmd,socket,device,")";
string expectedOutput = "3.0.1";
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, version);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpm2ToolsVersionSuccessWhitespace) {
stringstream versionOutput;
versionOutput << "tpm2_rc_decode, version 1.1.0";
string expectedOutput = "1.1.0";
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, version);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpm2ToolsVersionSuccessMultiNumeralVersion) {
stringstream versionOutput;
versionOutput << "tpm2_rc_decode, version 10.29.970";
string expectedOutput = "10.29.970";
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, version);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpm2ToolsVersionSuccessAnyCharsBeforeVersion) {
stringstream versionOutput;
versionOutput << "tpm2_rc_decode, version!@#$%^&*()+=-_|1.2.9";
string expectedOutput = "1.2.9";
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, version);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpm2ToolsVersionFailNonSemanticVersion) {
stringstream versionOutput;
versionOutput << "tpm2_rc_decode, version 1.2";
string expectedOutput = "";
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, version);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpm2ToolsMajorVersionSuccess) {
stringstream versionOutput;
versionOutput << "3.0.1";
string expectedOutput = "3";
string majorVersion = Tpm2ToolsOutputParser::parseTpm2ToolsMajorVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, majorVersion);
}
TEST_F(Tpm2ToolsUtilsTest,
ParseTpm2ToolsMajorVersionSuccessMultiNumeralVersion) {
stringstream versionOutput;
versionOutput << "10.29.970";
string expectedOutput = "10";
string majorVersion = Tpm2ToolsOutputParser::parseTpm2ToolsMajorVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, majorVersion);
}
TEST_F(Tpm2ToolsUtilsTest, ParseTpm2ToolsMajorVersionFailNonSemanticVersion) {
stringstream versionOutput;
versionOutput << "3.0";
string expectedOutput = "";
string majorVersion = Tpm2ToolsOutputParser::parseTpm2ToolsMajorVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, majorVersion);
}
TEST_F(Tpm2ToolsUtilsTest,
ParseTpm2ToolsMajorVersionFailLongNonSemanticVersion) {
stringstream versionOutput;
versionOutput << "3.0.1.27";
string expectedOutput = "";
string majorVersion = Tpm2ToolsOutputParser::parseTpm2ToolsMajorVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, majorVersion);
}
} // namespace
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -12,6 +12,7 @@
using hirs::file_utils::dirExists;
using hirs::file_utils::fileExists;
using hirs::file_utils::trimFilenameFromPath;
using hirs::json_utils::JSONFieldParser;
using hirs::string_utils::binaryToHex;
using hirs::string_utils::contains;
@ -25,7 +26,6 @@ using hirs::string_utils::trimChar;
using hirs::string_utils::trimWhitespaceFromLeft;
using hirs::string_utils::trimWhitespaceFromRight;
using hirs::string_utils::trimWhitespaceFromBothEnds;
using hirs::tpm2_tools_utils::Tpm2ToolsOutputParser;
using std::ofstream;
using std::string;
using std::stringstream;
@ -155,6 +155,26 @@ TEST_F(UtilsTest, SplitFile) {
ASSERT_EQ(s, "d");
}
TEST_F(UtilsTest, TrimFilenameFromAbsolutePathSuccess) {
string test = "/usr/bin/echo";
ASSERT_EQ("echo", trimFilenameFromPath(test));
}
TEST_F(UtilsTest, TrimFilenameFromRelativePathSuccess) {
string test = "usr/bin/echo";
ASSERT_EQ("echo", trimFilenameFromPath(test));
}
TEST_F(UtilsTest, TrimFilenameFromPathSuccessWhenJustFilename) {
string test = "echo";
ASSERT_EQ("echo", trimFilenameFromPath(test));
}
TEST_F(UtilsTest, TrimEmptyFilenameFromPathSuccess) {
string test = "/usr/bin/";
ASSERT_EQ("", trimFilenameFromPath(test));
}
TEST_F(UtilsTest, BinToHex) {
const char* testBin = "j\223\255x\216=\330c\aaj\262@\343i\246?\204T5";
ASSERT_EQ(binaryToHex(testBin),
@ -328,306 +348,6 @@ TEST_F(UtilsTest, trimWhitespaceFromBoth) {
ASSERT_EQ(trimWhitespaceFromBothEnds("\t\ras\rdf"), "as\rdf");
}
TEST_F(UtilsTest, ParseNvDataSizeSuccess) {
stringstream nvListOutput;
nvListOutput << "2 NV indexes defined.\n"
<< "\n"
<< " 0. NV Index: 0x1800001\n"
<< " {\n"
<< "\tHash algorithm(nameAlg):11\n"
<< "\tThe Index attributes(attributes):0x62042c04\n"
<< "\tThe size of the data area(dataSize):70\n"
<< " }\n"
<< "\n"
<< " 1. NV Index: 0x1c00002\n"
<< " {\n"
<< "\tHash algorithm(nameAlg):11\n"
<< "\tThe Index attributes(attributes):0x620f1001\n"
<< "\tThe size of the data area(dataSize):991\n"
<< " }\n";
uint16_t addressSize = Tpm2ToolsOutputParser::parseNvDataSize(
"0x1c00002", nvListOutput.str());
ASSERT_EQ(991, addressSize);
}
TEST_F(UtilsTest, ParseNvDataSizeSuccessTpm2ToolsV3) {
stringstream nvListOutput;
nvListOutput << "0x1c00002\n"
<< "\thash algorithm:\n"
<< "\t\tfriendly: sha256\n"
<< "\t\tvalue: 0xB\n"
<< "\tattributes:\n"
<< "\t\tfriendly: ownerwrite|policywrite\n"
<< "\t\tvalue: 0xA000220\n"
<< "\tsize: 991\n\n"
<< "0x1c00003\n"
<< "\thash algorithm:\n"
<< "\t\tfriendly: sha256\n"
<< "\t\tvalue: 0xB\n"
<< "\tattributes:\n"
<< "\t\tfriendly: ownerwrite|policywrite\n"
<< "\t\tvalue: 0xA000220\n"
<< "\tsize: 1722\n\n";
uint16_t addressSize = Tpm2ToolsOutputParser::parseNvDataSize(
"0x1c00002", nvListOutput.str());
ASSERT_EQ(991, addressSize);
}
TEST_F(UtilsTest, ParseNvDataSizeFailure) {
stringstream nvListOutput;
nvListOutput << "0 NV indexes defined.\n";
uint16_t addressSize = Tpm2ToolsOutputParser::parseNvDataSize(
"0x1c00002", nvListOutput.str());
ASSERT_EQ(0, addressSize);
}
TEST_F(UtilsTest, ParseNvReadSuccess) {
stringstream nvReadOutput;
nvReadOutput << "The size of data:10\n"
<< " 30 7f 03 6d 30 7f 03 7e 3c 03";
string nvReadData = Tpm2ToolsOutputParser::parseNvReadOutput(
nvReadOutput.str());
string expectedOutput = {48, 127, 3, 109, 48, 127, 3, 126, 60, 3};
ASSERT_EQ(expectedOutput, nvReadData);
}
TEST_F(UtilsTest, ParseNvReadFailure) {
stringstream nvReadOutput;
nvReadOutput << "Failed to read NVRAM area at index 0x1c00001 "
<< "(29360129).Error:0x28b\n";
string nvReadData = Tpm2ToolsOutputParser::parseNvReadOutput(
nvReadOutput.str());
ASSERT_EQ("", nvReadData);
}
TEST_F(UtilsTest, ParsePersistentObjectExistsSuccess) {
stringstream listPersistentOutput;
listPersistentOutput << "1 persistent objects defined.\n"
<< "\n"
<< " 0. Persistent handle: 0x81010001\n"
<< " {\n"
<< "\tType: 0x1\n"
<< "\tHash algorithm(nameAlg): 0xb\n"
<< "\tAttributes: 0x300b2\n"
<< " }\n";
ASSERT_TRUE(Tpm2ToolsOutputParser::parsePersistentObjectExists(
"0x81010001", listPersistentOutput.str()));
}
TEST_F(UtilsTest, ParsePersistentObjectExistsSuccessTpm2ToolsV3) {
stringstream listPersistentOutput;
listPersistentOutput << "persistent-handle[0]:0x81010001 "
<< "key-alg:rsa hash-alg:sha256 "
<< "object-attr:fixedtpm|fixedparent";
ASSERT_TRUE(Tpm2ToolsOutputParser::parsePersistentObjectExists(
"0x81010001", listPersistentOutput.str()));
}
TEST_F(UtilsTest, ParsePersistentObjectExistsFailure) {
stringstream listPersistentOutput;
listPersistentOutput << "0 persistent objects defined.\n";
ASSERT_FALSE(Tpm2ToolsOutputParser::parsePersistentObjectExists(
"0x81010001", listPersistentOutput.str()));
}
TEST_F(UtilsTest, ParseTpmErrorCodeSuccessAnyCharBetweenErrorAndCode) {
stringstream errorOutput;
errorOutput << "Create Object Failed ! ErrorCode: 0x922";
string expectedOutput = "0x922";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(UtilsTest, ParseTpmErrorCodeSuccessHexChars) {
stringstream errorOutput;
errorOutput << "Failed to read NVRAM area at index 0x1c00003"
<< " (29360131).Error:0x28b";
string expectedOutput = "0x28b";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(UtilsTest, ParseTpmErrorCodeSuccessFirstThreeHex) {
stringstream errorOutput;
errorOutput << "Failed to read NVRAM area at index 0x1c00003"
<< " (29360131).Error:0x28b90210";
string expectedOutput = "0x28b";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(UtilsTest, ParseTpmErrorCodeSuccessMultiline) {
stringstream errorOutput;
errorOutput << "Failed to read NVRAM area at index 0x1c00003"
<< " (29360131).Error:\n\n0x28b";
string expectedOutput = "0x28b";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(UtilsTest, ParseTpmErrorCodeSuccessCapitalHex) {
stringstream errorOutput;
errorOutput << "Failed to read NVRAM area at index 0x1c00003"
<< " (29360131).Error:\n\n0x28B";
string expectedOutput = "0x28B";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(UtilsTest, ParseTpmErrorCodeFailNonHex) {
stringstream errorOutput;
errorOutput << "Failed to read NVRAM area at index 0x1c00003"
<< " (29360131).Error:0x28g";
string expectedOutput = "";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(UtilsTest, ParseTpmErrorCodeFailNonHexFormatted) {
stringstream errorOutput;
errorOutput << "Failed to read NVRAM area at index 0x1c00003"
<< " (29360131).Error:28b";
string expectedOutput = "";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(UtilsTest, ParseTpmErrorCodeFailNotErrorCode) {
stringstream errorOutput;
errorOutput << "Easter Egg to be found at memory address: 0x042";
string expectedOutput = "";
string errorCode = Tpm2ToolsOutputParser::parseTpmErrorCode(
errorOutput.str());
ASSERT_EQ(expectedOutput, errorCode);
}
TEST_F(UtilsTest, ParseTpm2ToolsVersionSuccess) {
stringstream versionOutput;
versionOutput << R"(tool="tpm2_rc_decode" version="3.0.1")"
<< R"(tctis="tabrmd,socket,device,")";
string expectedOutput = "3.0.1";
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, version);
}
TEST_F(UtilsTest, ParseTpm2ToolsVersionSuccessCaseInsensitive) {
stringstream versionOutput;
versionOutput << R"(tool="tpm2_rc_decode" VeRSion="3.0.1")"
<< R"(tctis="tabrmd,socket,device,")";
string expectedOutput = "3.0.1";
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, version);
}
TEST_F(UtilsTest, ParseTpm2ToolsVersionSuccessWhitespace) {
stringstream versionOutput;
versionOutput << "tpm2_rc_decode, version 1.1.0";
string expectedOutput = "1.1.0";
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, version);
}
TEST_F(UtilsTest, ParseTpm2ToolsVersionSuccessMultiNumeralVersion) {
stringstream versionOutput;
versionOutput << "tpm2_rc_decode, version 10.29.970";
string expectedOutput = "10.29.970";
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, version);
}
TEST_F(UtilsTest, ParseTpm2ToolsVersionSuccessAnyCharsBeforeVersion) {
stringstream versionOutput;
versionOutput << "tpm2_rc_decode, version!@#$%^&*()+=-_|1.2.9";
string expectedOutput = "1.2.9";
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, version);
}
TEST_F(UtilsTest, ParseTpm2ToolsVersionFailNonSemanticVersion) {
stringstream versionOutput;
versionOutput << "tpm2_rc_decode, version 1.2";
string expectedOutput = "";
string version = Tpm2ToolsOutputParser::parseTpm2ToolsVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, version);
}
TEST_F(UtilsTest, ParseTpm2ToolsMajorVersionSuccess) {
stringstream versionOutput;
versionOutput << "3.0.1";
string expectedOutput = "3";
string majorVersion = Tpm2ToolsOutputParser::parseTpm2ToolsMajorVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, majorVersion);
}
TEST_F(UtilsTest, ParseTpm2ToolsMajorVersionSuccessMultiNumeralVersion) {
stringstream versionOutput;
versionOutput << "10.29.970";
string expectedOutput = "10";
string majorVersion = Tpm2ToolsOutputParser::parseTpm2ToolsMajorVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, majorVersion);
}
TEST_F(UtilsTest, ParseTpm2ToolsMajorVersionFailNonSemanticVersion) {
stringstream versionOutput;
versionOutput << "3.0";
string expectedOutput = "";
string majorVersion = Tpm2ToolsOutputParser::parseTpm2ToolsMajorVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, majorVersion);
}
TEST_F(UtilsTest, ParseTpm2ToolsMajorVersionFailLongNonSemanticVersion) {
stringstream versionOutput;
versionOutput << "3.0.1.27";
string expectedOutput = "";
string majorVersion = Tpm2ToolsOutputParser::parseTpm2ToolsMajorVersion(
versionOutput.str());
ASSERT_EQ(expectedOutput, majorVersion);
}
} // namespace
int main(int argc, char **argv) {