* move db-module from common lib to service executeble.
* add function removeUserData.
* add function getKeyAliases.
* move DBRow struct to new file.
Change-Id: I70bbcd4672014c341f8a0bb476b5bde5f8a56ba5
${KEY_MANAGER_PATH}/service/DBCryptoModule.cpp
${KEY_MANAGER_PATH}/service/CryptoService.cpp
${KEY_MANAGER_PATH}/service/file-system.cpp
+ ${KEY_MANAGER_PATH}/service/db-crypto.cpp
)
SET_SOURCE_FILES_PROPERTIES(
${KEY_MANAGER_CLIENT_SRC_PATH}/client-control.cpp
${KEY_MANAGER_CLIENT_SRC_PATH}/client-common.cpp
${KEY_MANAGER_CLIENT_SRC_PATH}/client-echo.cpp
+ ${KEY_MANAGER_CLIENT_SRC_PATH}/client-error.cpp
${KEY_MANAGER_CLIENT_SRC_PATH}/client-key.cpp
${KEY_MANAGER_CLIENT_SRC_PATH}/client-manager.cpp
${KEY_MANAGER_CLIENT_SRC_PATH}/client-manager-impl.cpp
${COMMON_PATH}/common/smack-check.cpp
${COMMON_PATH}/common/certificate-impl.cpp
${COMMON_PATH}/common/key-impl.cpp
- ${COMMON_PATH}/common/db-crypto.cpp
${COMMON_PATH}/dpl/log/src/abstract_log_provider.cpp
${COMMON_PATH}/dpl/log/src/dlog_log_provider.cpp
${COMMON_PATH}/dpl/log/src/log.cpp
* @version 1.0
* @brief This file contains example of key-manager client implementation
*/
-#include <protocol.h>
-
#include <ckm/ckm-error.h>
#define ERRORDESCRIBE(name) case name: return #name
namespace CKM {
-
-KEY_MANAGER_API
+__attribute__ ((visibility ("default")))
const char * ErrorToString(int error) {
switch(error) {
ERRORDESCRIBE(KEY_MANAGER_API_SUCCESS);
}
}
-}
+} // namespace CKM
int retCode = getBinaryData(
alias,
- DBDataType::CERTIFICATE,
+ DBDataType::BINARY_DATA,
password,
recvDataType,
rawData);
BIO_write(bio.get(), data.data(), data.size());
rsa = PEM_read_bio_RSAPrivateKey(bio.get(), NULL, NULL, pass);
} else if (type == KeyType::KEY_RSA_PUBLIC) {
+ // First we will try to read der file
const unsigned char *p = static_cast<const unsigned char*>(data.data());
rsa = d2i_RSA_PUBKEY(NULL, &p, data.size());
+ if (rsa == NULL) {
+ // This is internal der format used by openssl?
+ BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
+ BIO_write(bio.get(), data.data(), data.size());
+ rsa = d2i_RSAPublicKey_bio(bio.get(), NULL);
+ }
} else if (type == KeyType::KEY_RSA_PRIVATE) {
BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
if (NULL == bio.get())
DBDataType toDBDataType(KeyType key) {
switch(key) {
- case KeyType::KEY_RSA_PUBLIC: return DBDataType::KEY_RSA_PRIVATE;
- case KeyType::KEY_RSA_PRIVATE: return DBDataType::KEY_RSA_PUBLIC;
+ case KeyType::KEY_RSA_PUBLIC: return DBDataType::KEY_RSA_PUBLIC;
+ case KeyType::KEY_RSA_PRIVATE: return DBDataType::KEY_RSA_PRIVATE;
default:
// TODO
throw 1;
CREATE_KEY_PAIR_ECDSA
};
+// Do not use DB_KEY_FIRST and DB_KEY_LAST in the code.
+// This values are only for db module!
enum class DBDataType : int {
KEY_RSA_PUBLIC,
+ DB_KEY_FIRST = KEY_RSA_PUBLIC,
KEY_RSA_PRIVATE,
KEY_ECDSA_PUBLIC,
KEY_ECDSA_PRIVATE,
KEY_AES,
+ DB_KEY_LAST = KEY_AES,
CERTIFICATE,
BINARY_DATA
};
-enum class DBQueryType : int {
- KEY_QUERY,
- CERTIFICATE_QUERY,
- BINARY_DATA_QUERY
-};
-
DBDataType toDBDataType(KeyType key);
KeyType toKeyType(DBDataType dbDataType);
LogPedantic("Cannot set key. No connection to DB!");
return;
}
- if (rawPass.size() == SQLCIPHER_RAW_DATA_SIZE)
+ if (rawPass.size() != SQLCIPHER_RAW_DATA_SIZE)
ThrowMsg(Exception::InvalidArguments,
"Binary data for raw password should be 32 bytes long.");
TransitoryString pass = createHexPass(rawPass);
}
handle.keyProvider = KeyProvider(wrappedDomainKEK, password);
-
- // TODO Now create database!
+ handle.database = DBCrypto(fs.getDBPath(), handle.keyProvider.getDomainKEK());
}
MessageBuffer response;
}
RawBuffer CKMLogic::lockUserKey(uid_t user) {
+ int retCode = KEY_MANAGER_API_SUCCESS;
// TODO try catch for all errors that should be supported by error code
m_userDataMap.erase(user);
MessageBuffer response;
- Serialization::Serialize(response, static_cast<int>(KEY_MANAGER_API_SUCCESS));
+ Serialization::Serialize(response, retCode);
return response.Pop();
}
RawBuffer CKMLogic::removeUserData(uid_t user) {
+ int retCode = KEY_MANAGER_API_SUCCESS;
// TODO try catch for all errors that should be supported by error code
m_userDataMap.erase(user);
FileSystem fs(user);
-// fs.removeUserData(); // remove DB also
+ fs.removeUserData();
MessageBuffer response;
- Serialization::Serialize(response, static_cast<int>(KEY_MANAGER_API_SUCCESS));
+ Serialization::Serialize(response, retCode);
return response.Pop();
}
{
int retCode = KEY_MANAGER_API_SUCCESS;
// TODO try-catch
- if (m_userDataMap.count(user) <= 0) {
+ if (0 == m_userDataMap.count(user)) {
retCode = KEY_MANAGER_API_ERROR_BAD_REQUEST;
} else {
auto &handler = m_userDataMap[user];
const RawBuffer &key,
const PolicySerializable &policy)
{
- (void)cred;
- (void)alias;
- (void)key;
- (void)policy;
+ int retCode = KEY_MANAGER_API_SUCCESS;
+
+ if (0 == m_userDataMap.count(cred.uid)) {
+ retCode = KEY_MANAGER_API_ERROR_DB_LOCKED;
+ } else {
+ RawBuffer iv(10,'c');
+
+ DBRow row = {
+ alias,
+ cred.smackLabel,
+ policy.restricted,
+ policy.extractable,
+ dataType,
+ 0,
+ 0,
+ iv,
+ key.size(),
+ key };
+
+ auto &handler = m_userDataMap[cred.uid];
+ retCode = handler.database.saveDBRow(row);
+ }
MessageBuffer response;
Serialization::Serialize(response, static_cast<int>(LogicCommand::SAVE));
Serialization::Serialize(response, commandId);
- Serialization::Serialize(response, static_cast<int>(KEY_MANAGER_API_SUCCESS));
+ Serialization::Serialize(response, retCode);
Serialization::Serialize(response, static_cast<int>(dataType));
return response.Pop();
(void)cred;
(void)alias;
+ int retCode = KEY_MANAGER_API_SUCCESS;
+
+ if (0 == m_userDataMap.count(cred.uid)) {
+ retCode = KEY_MANAGER_API_ERROR_DB_LOCKED;
+ } else {
+ // TODO
+ auto &handler = m_userDataMap[cred.uid];
+ (void)handler;
+ }
+
MessageBuffer response;
Serialization::Serialize(response, static_cast<int>(LogicCommand::REMOVE));
Serialization::Serialize(response, commandId);
- Serialization::Serialize(response, static_cast<int>(KEY_MANAGER_API_SUCCESS));
+ Serialization::Serialize(response, retCode);
Serialization::Serialize(response, static_cast<int>(dataType));
return response.Pop();
const Alias &alias,
const std::string &password)
{
- (void)cred;
- (void)alias;
+ (void)dataType;
(void)password;
+ int retCode = KEY_MANAGER_API_SUCCESS;
+ DBRow row;
+
+ if (0 == m_userDataMap.count(cred.uid)) {
+ retCode = KEY_MANAGER_API_ERROR_DB_LOCKED;
+ } else {
+ auto &handler = m_userDataMap[cred.uid];
+ retCode = handler.database.getDBRow(alias, cred.smackLabel, row);
+ }
+
MessageBuffer response;
Serialization::Serialize(response, static_cast<int>(LogicCommand::GET));
Serialization::Serialize(response, commandId);
- Serialization::Serialize(response, static_cast<int>(KEY_MANAGER_API_SUCCESS));
- Serialization::Serialize(response, static_cast<int>(dataType));
- Serialization::Serialize(response, RawBuffer());
+ Serialization::Serialize(response, retCode);
+ Serialization::Serialize(response, static_cast<int>(row.dataType));
+ Serialization::Serialize(response, row.data);
return response.Pop();
}
int commandId,
DBDataType dataType)
{
- (void)cred;
+ int retCode = KEY_MANAGER_API_SUCCESS;
+
+ if (0 == m_userDataMap.count(cred.uid)) {
+ retCode = KEY_MANAGER_API_ERROR_DB_LOCKED;
+ } else {
+ auto &handler = m_userDataMap[cred.uid];
+ // TODO
+ (void)handler;
+ }
MessageBuffer response;
Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_LIST));
Serialization::Serialize(response, commandId);
- Serialization::Serialize(response, static_cast<int>(KEY_MANAGER_API_SUCCESS));
+ Serialization::Serialize(response, retCode);
Serialization::Serialize(response, static_cast<int>(dataType));
Serialization::Serialize(response, AliasVector());
return response.Pop();
#include <protocols.h>
#include <ckm/ckm-type.h>
#include <connection-info.h>
+#include <db-crypto.h>
#include <key-provider.h>
namespace CKM {
struct UserData {
KeyProvider keyProvider;
+ DBCrypto database;
};
class CKMLogic {
// 1 2
"SELECT * FROM CKM_TABLE WHERE alias=? AND label=?;";
+ const char *select_key_alias_cmd =
+ "SELECT * FROM CKM_TABLE WHERE "
+ " dataType >= ? AND "
+ " dataType <= ? AND "
+ " (restricted=0 OR label=?)";
+
+
const char *select_type_cmd =
// 1
"SELECT alias FROM CKM_TABLE WHERE dataType=? AND restricted=0 "
return KEY_MANAGER_API_SUCCESS;
}
- int DBCrypto::getDBRow(const Alias &alias, const std::string &label,
- DBRow &row) {
-
+ int DBCrypto::getDBRow(
+ const Alias &alias,
+ const std::string &label,
+ DBRow &row)
+ {
if(!m_init)
return KEY_MANAGER_API_ERROR_DB_ERROR;
Try {
selectCommand->BindString(2, label.c_str());
if(selectCommand->Step()) {
- row.alias = selectCommand->GetColumnString(1);
- row.smackLabel = selectCommand->GetColumnString(2);
- row.restricted = selectCommand->GetColumnInteger(3);
- row.exportable = selectCommand->GetColumnInteger(4);
- row.dataType = static_cast<DBDataType>(selectCommand->GetColumnInteger(5));
- row.algorithmType = selectCommand->GetColumnInteger(6);
- row.encryptionScheme = selectCommand->GetColumnInteger(7);
- row.iv = selectCommand->GetColumnBlob(8);
- row.dataSize = selectCommand->GetColumnInteger(9);
- row.data = selectCommand->GetColumnBlob(10);
+ row.alias = selectCommand->GetColumnString(0);
+ row.smackLabel = selectCommand->GetColumnString(1);
+ row.restricted = selectCommand->GetColumnInteger(2);
+ row.exportable = selectCommand->GetColumnInteger(3);
+ row.dataType = static_cast<DBDataType>(selectCommand->GetColumnInteger(4));
+ row.algorithmType = selectCommand->GetColumnInteger(5);
+ row.encryptionScheme = selectCommand->GetColumnInteger(6);
+ row.iv = selectCommand->GetColumnBlob(7);
+ row.dataSize = selectCommand->GetColumnInteger(8);
+ row.data = selectCommand->GetColumnBlob(9);
} else {
return KEY_MANAGER_API_ERROR_BAD_REQUEST;
}
while(selectCommand->Step()) {
Alias alias;
- alias = selectCommand->GetColumnString(1);
+ alias = selectCommand->GetColumnString(0);
aliases.push_back(alias);
}
} Catch (SqlConnection::Exception::InvalidColumn) {
return KEY_MANAGER_API_SUCCESS;
}
- int DBCrypto::getAliases(DBQueryType type, const std::string& label,
- AliasVector& aliases) {
-
+ int DBCrypto::getAliases(
+ DBDataType type,
+ const std::string& label,
+ AliasVector& aliases)
+ {
if(!m_init)
return KEY_MANAGER_API_ERROR_DB_ERROR;
- int ret;
- switch(type) {
- case DBQueryType::KEY_QUERY:
- ret = getSingleType(DBDataType::KEY_AES, label, aliases);
- if(ret != KEY_MANAGER_API_SUCCESS)
- return ret;
- ret = getSingleType(DBDataType::KEY_ECDSA_PRIVATE, label, aliases);
- if(ret != KEY_MANAGER_API_SUCCESS)
- return ret;
- ret = getSingleType(DBDataType::KEY_ECDSA_PUBLIC, label, aliases);
- if(ret != KEY_MANAGER_API_SUCCESS)
- return ret;
- ret = getSingleType(DBDataType::KEY_RSA_PRIVATE, label, aliases);
- if(ret != KEY_MANAGER_API_SUCCESS)
- return ret;
- return(getSingleType(DBDataType::KEY_RSA_PUBLIC, label, aliases));
- case DBQueryType::CERTIFICATE_QUERY:
- return getSingleType(DBDataType::CERTIFICATE, label, aliases);
- case DBQueryType::BINARY_DATA_QUERY:
- return getSingleType(DBDataType::BINARY_DATA, label, aliases);
+
+ return getSingleType(type, label, aliases);
+ }
+
+ int DBCrypto::getKeyAliases(
+ const std::string &label,
+ AliasVector &aliases)
+ {
+ if (!m_init)
+ return KEY_MANAGER_API_ERROR_DB_ERROR;
+
+ Try{
+ SqlConnection::DataCommandAutoPtr selectCommand =
+ m_connection->PrepareDataCommand(select_key_alias_cmd);
+ selectCommand->BindInteger(1, static_cast<int>(DBDataType::DB_KEY_FIRST));
+ selectCommand->BindInteger(2, static_cast<int>(DBDataType::DB_KEY_LAST));
+ selectCommand->BindString(3, label.c_str());
+
+ while(selectCommand->Step()) {
+ Alias alias;
+ alias = selectCommand->GetColumnString(1);
+ aliases.push_back(alias);
+ }
+ } Catch (SqlConnection::Exception::InvalidColumn) {
+ LogError("Select statement invalid column error");
+ return KEY_MANAGER_API_ERROR_DB_ERROR;
+ } Catch (SqlConnection::Exception::SyntaxError) {
+ LogError("Couldn't prepare select statement");
+ return KEY_MANAGER_API_ERROR_DB_ERROR;
+ } Catch (SqlConnection::Exception::InternalError) {
+ LogError("Couldn't execute select statement");
+ return KEY_MANAGER_API_ERROR_DB_ERROR;
}
return KEY_MANAGER_API_SUCCESS;
}
#include <vector>
#include <string>
-#include <ckm/ckm-type.h>
+
#include <dpl/db/sql_connection.h>
+
+#include <ckm/ckm-type.h>
+#include <db-row.h>
#include <protocols.h>
-namespace CKM {
- struct DBRow {
- std::string alias;
- std::string smackLabel;
- int restricted;
- int exportable;
- DBDataType dataType; // cert/key/data
- int algorithmType; // AES mode ?
- int encryptionScheme; // for example: (ENCR_BASE64 | ENCR_PASSWORD)
- RawBuffer iv; // encoded in base64
- int dataSize; // size of information without hash and padding
- RawBuffer data;
- };
+namespace CKM {
class DBCrypto {
public:
DBCrypto() : m_connection(NULL), m_init(false) {};
DBCrypto& operator=(const DBCrypto& ) = delete;
DBCrypto& operator=(DBCrypto&& other);
- ~DBCrypto();
+ virtual ~DBCrypto();
bool isInit() {return m_init;};
int saveDBRow(const DBRow &row);
int getDBRow(const Alias &alias, const std::string &label, DBRow &row);
- int getAliases(DBQueryType dataType, const std::string &label,
+ int getAliases(
+ DBDataType dataType,
+ const std::string &label,
+ AliasVector &aliases);
+ int getKeyAliases(
+ const std::string &label,
AliasVector &aliases);
int deleteDBRow(const Alias& alias, const std::string &label);
AliasVector& aliases);
};
-}
+} // namespace CKM
+
#endif //DB_CRYPTO_H
--- /dev/null
+#pragma once
+
+#include <string>
+
+#include <ckm/ckm-type.h>
+#include <protocols.h>
+
+namespace CKM {
+ struct DBRow {
+ std::string alias;
+ std::string smackLabel;
+ int restricted;
+ int exportable;
+ DBDataType dataType; // cert/key/data
+ int algorithmType; // AES mode ?
+ int encryptionScheme; // for example: (ENCR_BASE64 | ENCR_PASSWORD)
+ RawBuffer iv; // encoded in base64
+ int dataSize; // size of information without hash and padding
+ RawBuffer data;
+ };
+} // namespace CKM
+
+
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <unistd.h>
#include <string>
#include <sstream>
return ss.str();
}
-RawBuffer FileSystem::getDomainKEK() const
-{
+std::string FileSystem::getDKEKPath() const {
std::stringstream ss;
ss << CKM_DATA_PATH << CKM_KEY_PREFIX << m_uid;
+ return ss.str();
+}
- std::ifstream is(ss.str());
+RawBuffer FileSystem::getDomainKEK() const
+{
+ std::ifstream is(getDKEKPath());
std::istreambuf_iterator<char> begin(is),end;
RawBuffer buffer(begin, end);
return buffer;
bool FileSystem::saveDomainKEK(const RawBuffer &buffer) const
{
- std::stringstream ss;
- ss << CKM_DATA_PATH << CKM_KEY_PREFIX << m_uid;
-
- std::ofstream os(ss.str(), std::ios::out | std::ofstream::binary);
+ std::ofstream os(getDKEKPath(), std::ios::out | std::ofstream::binary);
std::copy(buffer.begin(), buffer.end(), std::ostreambuf_iterator<char>(os));
return !os.fail();
}
return 0;
}
+int FileSystem::removeUserData() const {
+ int err, retCode = 0;
+ if (unlink(getDBPath().c_str())) {
+ retCode = -1;
+ err = errno;
+ LogError("Error in unlink user database: " << getDBPath()
+ << "Errno: " << errno << " " << strerror(err));
+ }
+ if (unlink(getDKEKPath().c_str())) {
+ retCode = -1;
+ err = errno;
+ LogError("Error in unlink user DKEK: " << getDKEKPath()
+ << "Errno: " << errno << " " << strerror(err));
+ }
+ return retCode;
+}
+
} // namespace CKM
std::string getDBPath() const;
RawBuffer getDomainKEK() const;
bool saveDomainKEK(const RawBuffer &buffer) const;
+ int removeUserData() const;
static int init();
virtual ~FileSystem(){}
protected:
+ std::string getDKEKPath() const;
+
uid_t m_uid;
};
bool isInitialized();
// Returns Key used to decrypt database.
- KeyAES getDomainKEK();
+ RawBuffer getDomainKEK();
// Returns Key in form used to store key in file
// Requied by Control::resetPassword(const RawBuffer &newPassword);