summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>2015-09-07 13:19:54 +0200
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>2015-10-26 12:34:39 +0100
commit51a5e9cfe81d0374a02c1e28375a482b68afd879 (patch)
tree3284ad46a180e1c9cf31f947ad63054eccf5c1e1
parentb2d277acd0398562a7e9968c1d6c59517178c0f8 (diff)
downloadkey-manager-51a5e9cfe81d0374a02c1e28375a482b68afd879.tar.gz
key-manager-51a5e9cfe81d0374a02c1e28375a482b68afd879.tar.bz2
key-manager-51a5e9cfe81d0374a02c1e28375a482b68afd879.zip
Modify encryption scheme
[Problem] Current encryption scheme makes it impossible to remove an entry protected with custom user password from database. [Solution] Encryption scheme modified. Store is responsible for encrypting data with user password. Service encrypts it with app key. Data encrypted with old scheme that is being read will be automatically reencrypted with new scheme. [Verification] Run tests from upcoming commit: ckm-tests-internal -t ENCRYPTION_SCHEME_TEST Change-Id: I8ed514290d9e75bbc89d74b006939e3cbb0b8bd2
-rw-r--r--src/manager/crypto/generic-backend/gobj.h2
-rw-r--r--src/manager/crypto/generic-backend/gstore.h20
-rw-r--r--src/manager/crypto/sw-backend/internals.cpp37
-rw-r--r--src/manager/crypto/sw-backend/internals.h21
-rw-r--r--src/manager/crypto/sw-backend/obj.cpp4
-rw-r--r--src/manager/crypto/sw-backend/obj.h2
-rw-r--r--src/manager/crypto/sw-backend/store.cpp146
-rw-r--r--src/manager/crypto/sw-backend/store.h8
-rw-r--r--src/manager/crypto/tz-backend/store.cpp6
-rw-r--r--src/manager/crypto/tz-backend/store.h6
-rw-r--r--src/manager/service/ckm-logic.cpp221
-rw-r--r--src/manager/service/ckm-logic.h19
-rw-r--r--src/manager/service/crypto-logic.cpp66
-rw-r--r--src/manager/service/crypto-logic.h22
-rw-r--r--src/manager/service/db-crypto.cpp45
-rw-r--r--src/manager/service/db-crypto.h5
16 files changed, 480 insertions, 150 deletions
diff --git a/src/manager/crypto/generic-backend/gobj.h b/src/manager/crypto/generic-backend/gobj.h
index 0857a0e5..1e6598f0 100644
--- a/src/manager/crypto/generic-backend/gobj.h
+++ b/src/manager/crypto/generic-backend/gobj.h
@@ -20,6 +20,7 @@
*/
#pragma once
#include <memory>
+#include <vector>
#include <ckm/ckm-raw-buffer.h>
#include <ckm/ckm-type.h>
@@ -58,6 +59,7 @@ public:
typedef std::unique_ptr<GObj> GObjUPtr;
typedef std::shared_ptr<GObj> GObjShPtr;
+typedef std::vector<GObjUPtr> GObjUPtrVector;
} // namespace Crypto
} // namespace CKM
diff --git a/src/manager/crypto/generic-backend/gstore.h b/src/manager/crypto/generic-backend/gstore.h
index 30e177d2..bcb3a57d 100644
--- a/src/manager/crypto/generic-backend/gstore.h
+++ b/src/manager/crypto/generic-backend/gstore.h
@@ -33,11 +33,21 @@ namespace Crypto {
class GStore {
public:
- virtual GObjUPtr getObject(const Token &) { ThrowErr(Exc::Crypto::OperationNotSupported); }
- virtual TokenPair generateAKey(const CryptoAlgorithm &) { ThrowErr(Exc::Crypto::OperationNotSupported); }
- virtual Token generateSKey(const CryptoAlgorithm &) { ThrowErr(Exc::Crypto::OperationNotSupported); }
- virtual Token import(DataType, const RawBuffer &) { ThrowErr(Exc::Crypto::OperationNotSupported); }
- virtual void destroy(const Token &) { ThrowErr(Exc::Crypto::OperationNotSupported); }
+ virtual GObjUPtr getObject(const Token &, const Password &) {
+ ThrowErr(Exc::Crypto::OperationNotSupported);
+ }
+ virtual TokenPair generateAKey(const CryptoAlgorithm &, const Password &, const Password &) {
+ ThrowErr(Exc::Crypto::OperationNotSupported);
+ }
+ virtual Token generateSKey(const CryptoAlgorithm &, const Password &) {
+ ThrowErr(Exc::Crypto::OperationNotSupported);
+ }
+ virtual Token import(DataType, const RawBuffer &, const Password &) {
+ ThrowErr(Exc::Crypto::OperationNotSupported);
+ }
+ virtual void destroy(const Token &) {
+ ThrowErr(Exc::Crypto::OperationNotSupported);
+ }
virtual ~GStore() {}
protected:
diff --git a/src/manager/crypto/sw-backend/internals.cpp b/src/manager/crypto/sw-backend/internals.cpp
index d5dfa236..6239c668 100644
--- a/src/manager/crypto/sw-backend/internals.cpp
+++ b/src/manager/crypto/sw-backend/internals.cpp
@@ -368,7 +368,7 @@ int getRsaPadding(const RSAPaddingAlgorithm padAlgo) {
return rsa_padding;
}
-TokenPair createKeyPairRSA(CryptoBackend backendId, const int size)
+DataPair createKeyPairRSA(const int size)
{
EvpPkeyUPtr pkey;
@@ -396,12 +396,13 @@ TokenPair createKeyPairRSA(CryptoBackend backendId, const int size)
}
pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
- return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_RSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
- Token(backendId, DataType(KeyType::KEY_RSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
+ return std::make_pair<Data, Data>(
+ {DataType(KeyType::KEY_RSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())},
+ {DataType(KeyType::KEY_RSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())});
}
-TokenPair createKeyPairDSA(CryptoBackend backendId, const int size)
+DataPair createKeyPairDSA(const int size)
{
EvpPkeyUPtr pkey;
EvpPkeyUPtr pparam;
@@ -449,11 +450,12 @@ TokenPair createKeyPairDSA(CryptoBackend backendId, const int size)
}
pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
- return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_DSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
- Token(backendId, DataType(KeyType::KEY_DSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
+ return std::make_pair<Data, Data>(
+ {DataType(KeyType::KEY_DSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())},
+ {DataType(KeyType::KEY_DSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())});
}
-TokenPair createKeyPairECDSA(CryptoBackend backendId, ElipticCurve type)
+DataPair createKeyPairECDSA(ElipticCurve type)
{
int ecCurve = NOT_DEFINED;
EvpPkeyUPtr pkey;
@@ -511,11 +513,12 @@ TokenPair createKeyPairECDSA(CryptoBackend backendId, ElipticCurve type)
}
pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
- return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_ECDSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
- Token(backendId, DataType(KeyType::KEY_ECDSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
+ return std::make_pair<Data, Data>(
+ {DataType(KeyType::KEY_ECDSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())},
+ {DataType(KeyType::KEY_ECDSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())});
}
-Token createKeyAES(CryptoBackend backendId, const int sizeBits)
+Data createKeyAES(const int sizeBits)
{
// check the parameters of functions
if(sizeBits!=128 && sizeBits!=192 && sizeBits!=256) {
@@ -530,10 +533,10 @@ Token createKeyAES(CryptoBackend backendId, const int sizeBits)
ThrowMsg(Exc::Crypto::InternalError, "Error in AES key generation");
}
- return Token(backendId, DataType(KeyType::KEY_AES), CKM::RawBuffer(key, key+sizeBytes));
+ return { DataType(KeyType::KEY_AES), CKM::RawBuffer(key, key+sizeBytes)};
}
-TokenPair generateAKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm)
+DataPair generateAKey(const CryptoAlgorithm &algorithm)
{
validateParams<IsAsymGeneration>(algorithm);
@@ -542,23 +545,23 @@ TokenPair generateAKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm
{
int keyLength = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
if(keyType == AlgoType::RSA_GEN)
- return createKeyPairRSA(backendId, keyLength);
+ return createKeyPairRSA(keyLength);
else
- return createKeyPairDSA(backendId, keyLength);
+ return createKeyPairDSA(keyLength);
}
else // AlgoType::ECDSA_GEN
{
ElipticCurve ecType = unpack<ElipticCurve>(algorithm, ParamName::GEN_EC);
- return createKeyPairECDSA(backendId, ecType);
+ return createKeyPairECDSA(ecType);
}
}
-Token generateSKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm)
+Data generateSKey(const CryptoAlgorithm &algorithm)
{
validateParams<IsSymGeneration>(algorithm);
int keySizeBits = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
- return createKeyAES(backendId, keySizeBits);
+ return createKeyAES(keySizeBits);
}
RawBuffer encryptDataAes(
diff --git a/src/manager/crypto/sw-backend/internals.h b/src/manager/crypto/sw-backend/internals.h
index 3b543942..ecf52d47 100644
--- a/src/manager/crypto/sw-backend/internals.h
+++ b/src/manager/crypto/sw-backend/internals.h
@@ -24,7 +24,6 @@
#include <certificate-impl.h>
#include <ckm/ckm-type.h>
#include <openssl/evp.h>
-#include <token.h>
#include <sw-backend/obj.h>
#define EVP_SUCCESS 1 // DO NOTCHANGE THIS VALUE
@@ -40,13 +39,21 @@ namespace Crypto {
namespace SW {
namespace Internals {
-TokenPair createKeyPairRSA(CryptoBackend backendId, const int size);
-TokenPair createKeyPairDSA(CryptoBackend backendId, const int size);
-TokenPair createKeyPairECDSA(CryptoBackend backendId, ElipticCurve type1);
-Token createKeyAES(CryptoBackend backendId, const int sizeBits);
+// TODO replace it with DataContainer
+struct Data {
+ DataType type;
+ RawBuffer buffer;
+};
-TokenPair generateAKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm);
-Token generateSKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm);
+typedef std::pair<Data,Data> DataPair;
+
+DataPair createKeyPairRSA(const int size);
+DataPair createKeyPairDSA(const int size);
+DataPair createKeyPairECDSA(ElipticCurve type1);
+Data createKeyAES(const int sizeBits);
+
+DataPair generateAKey(const CryptoAlgorithm &algorithm);
+Data generateSKey(const CryptoAlgorithm &algorithm);
RawBuffer symmetricEncrypt(const RawBuffer &key,
const CryptoAlgorithm &alg,
diff --git a/src/manager/crypto/sw-backend/obj.cpp b/src/manager/crypto/sw-backend/obj.cpp
index 0b602a3a..2a70736e 100644
--- a/src/manager/crypto/sw-backend/obj.cpp
+++ b/src/manager/crypto/sw-backend/obj.cpp
@@ -59,10 +59,6 @@ AlgoType key2algo(DataType type) {
typedef std::unique_ptr<BIO, std::function<void(BIO*)>> BioUniquePtr;
-RawBuffer BData::getBinary() const {
- return m_raw;
-}
-
RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
{
return Internals::symmetricEncrypt(getBinary(), alg, data);
diff --git a/src/manager/crypto/sw-backend/obj.h b/src/manager/crypto/sw-backend/obj.h
index c56354f3..f8c3cfee 100644
--- a/src/manager/crypto/sw-backend/obj.h
+++ b/src/manager/crypto/sw-backend/obj.h
@@ -40,7 +40,7 @@ public:
, m_type(keyType)
{}
- virtual RawBuffer getBinary() const;
+ virtual RawBuffer getBinary() const { return m_raw; }
protected:
RawBuffer m_raw;
DataType m_type;
diff --git a/src/manager/crypto/sw-backend/store.cpp b/src/manager/crypto/sw-backend/store.cpp
index 0c6669a9..4e944adb 100644
--- a/src/manager/crypto/sw-backend/store.cpp
+++ b/src/manager/crypto/sw-backend/store.cpp
@@ -20,66 +20,180 @@
*/
#include <memory>
+#include <openssl/rand.h>
+#include <openssl/evp.h>
+
#include <generic-backend/exception.h>
#include <sw-backend/obj.h>
#include <sw-backend/store.h>
#include <sw-backend/internals.h>
+#include <message-buffer.h>
+
+namespace CKM {
+namespace Crypto {
+namespace SW {
+
namespace {
+const int ITERATIONS = 1024;
+const int KEY_LENGTH = 16; // length of AES key derived from password
+const int STORE_AES_GCM_TAG_SIZE = 16; // length of AES GCM tag
+
+// internal SW encryption scheme flags
+enum EncryptionScheme {
+ NONE = 0,
+ PASSWORD = 1 << 0
+};
+
template <typename T, typename ...Args>
std::unique_ptr<T> make_unique(Args&& ...args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
-} // namespace anonymous
+RawBuffer generateRandIV() {
+ RawBuffer civ(EVP_MAX_IV_LENGTH);
-namespace CKM {
-namespace Crypto {
-namespace SW {
+ if (1 != RAND_bytes(civ.data(), civ.size()))
+ ThrowErr(Exc::Crypto::InternalError, "RAND_bytes failed to generate IV.");
+ return civ;
+}
+
+RawBuffer passwordToKey(const Password &password, const RawBuffer &salt, size_t keySize)
+{
+ RawBuffer result(keySize);
+
+ if (1 != PKCS5_PBKDF2_HMAC_SHA1(
+ password.c_str(),
+ password.size(),
+ salt.data(),
+ salt.size(),
+ ITERATIONS,
+ result.size(),
+ result.data()))
+ {
+ ThrowErr(Exc::InternalError, "PCKS5_PKKDF2_HMAC_SHA1 failed.");
+ }
+
+ return result;
+}
+
+RawBuffer unpack(const RawBuffer& packed, const Password& pass)
+{
+ MessageBuffer buffer;
+ buffer.Push(packed);
+ int encryptionScheme = 0;
+ RawBuffer data;
+ buffer.Deserialize(encryptionScheme, data);
+
+ if (encryptionScheme == 0)
+ return data;
+
+ MessageBuffer internalBuffer;
+ internalBuffer.Push(data);
+ RawBuffer encrypted;
+ RawBuffer iv;
+ RawBuffer tag;
+
+ // serialization exceptions will be catched as CKM::Exception and will cause
+ // CKM_API_ERROR_SERVER_ERROR
+ internalBuffer.Deserialize(encrypted, iv, tag);
+
+ /*
+ * AES GCM will check data integrity and handle cases where:
+ * - wrong password is used
+ * - password is empty when it shouldn't be
+ * - password is not empty when it should be
+ */
+ RawBuffer key = passwordToKey(pass, iv, KEY_LENGTH);
+
+ RawBuffer ret;
+ try {
+ ret = Crypto::SW::Internals::decryptDataAesGcm(key, encrypted, iv, tag);
+ } catch( const Exc::Crypto::InternalError& e) {
+ ThrowErr(Exc::AuthenticationFailed, "Decryption with custom password failed");
+ }
+ return ret;
+}
+
+RawBuffer pack(const RawBuffer& data, const Password& pass)
+{
+ int scheme = EncryptionScheme::NONE;
+ RawBuffer packed = data;
+ if (!pass.empty()) {
+ RawBuffer iv = generateRandIV();
+ RawBuffer key = passwordToKey(pass, iv, KEY_LENGTH);
+
+ std::pair<RawBuffer, RawBuffer> ret;
+ try {
+ ret = Crypto::SW::Internals::encryptDataAesGcm(key, data, iv, STORE_AES_GCM_TAG_SIZE);
+ } catch( const Exc::Crypto::InternalError& e) {
+ ThrowErr(Exc::AuthenticationFailed, "Encryption with custom password failed");
+ }
+ scheme |= EncryptionScheme::PASSWORD;
+
+ // serialization exceptions will be catched as CKM::Exception and will cause
+ // CKM_API_ERROR_SERVER_ERROR
+ packed = MessageBuffer::Serialize(ret.first, iv, ret.second).Pop();
+ }
+ // encryption scheme + internal buffer
+ return MessageBuffer::Serialize(scheme, packed).Pop();
+}
+
+} // namespace anonymous
Store::Store(CryptoBackend backendId)
: GStore(backendId)
{
}
-GObjUPtr Store::getObject(const Token &token) {
+GObjUPtr Store::getObject(const Token &token, const Password &pass) {
if (token.backendId != m_backendId) {
ThrowErr(Exc::Crypto::WrongBackend, "Decider choose wrong backend!");
}
+ RawBuffer data = unpack(token.data, pass);
+
if (token.dataType.isKeyPrivate() || token.dataType.isKeyPublic()) {
- return make_unique<AKey>(token.data, token.dataType);
+ return make_unique<AKey>(data, token.dataType);
}
if (token.dataType == DataType(DataType::KEY_AES)) {
- return make_unique<SKey>(token.data, token.dataType);
+ return make_unique<SKey>(data, token.dataType);
}
- if (token.dataType.isCertificate()) {
- return make_unique<Cert>(token.data, token.dataType);
+ if (token.dataType.isCertificate() || token.dataType.isChainCert()) {
+ return make_unique<Cert>(data, token.dataType);
}
if (token.dataType.isBinaryData()) {
- return make_unique<BData>(token.data, token.dataType);
+ return make_unique<BData>(data, token.dataType);
}
ThrowErr(Exc::Crypto::DataTypeNotSupported,
"This type of data is not supported by openssl backend: ", (int)token.dataType);
}
-TokenPair Store::generateAKey(const CryptoAlgorithm &algorithm)
+TokenPair Store::generateAKey(const CryptoAlgorithm &algorithm,
+ const Password &prvPass,
+ const Password &pubPass)
{
- return Internals::generateAKey(m_backendId, algorithm);
+ Internals::DataPair ret = Internals::generateAKey(algorithm);
+ return std::make_pair<Token,Token>(
+ Token(m_backendId, ret.first.type, pack(ret.first.buffer, prvPass)),
+ Token(m_backendId, ret.second.type, pack(ret.second.buffer, pubPass)));
}
-Token Store::generateSKey(const CryptoAlgorithm &algorithm)
+Token Store::generateSKey(const CryptoAlgorithm &algorithm, const Password &pass)
{
- return Internals::generateSKey(m_backendId, algorithm);
+ Internals::Data ret = Internals::generateSKey(algorithm);
+ return Token(m_backendId, ret.type, pack(ret.buffer, pass));
}
-Token Store::import(DataType dataType, const RawBuffer &buffer) {
- return Token(m_backendId, dataType, buffer);
+Token Store::import(DataType dataType, const RawBuffer &input, const Password &pass) {
+
+ RawBuffer data = pack(input, pass);
+ return Token(m_backendId, dataType, std::move(data));
}
} // namespace SW
diff --git a/src/manager/crypto/sw-backend/store.h b/src/manager/crypto/sw-backend/store.h
index 552f5bc0..f39d0c51 100644
--- a/src/manager/crypto/sw-backend/store.h
+++ b/src/manager/crypto/sw-backend/store.h
@@ -31,10 +31,10 @@ class Store : public GStore {
public:
explicit Store(CryptoBackend backendId);
- virtual GObjUPtr getObject(const Token &token);
- virtual TokenPair generateAKey(const CryptoAlgorithm &);
- virtual Token generateSKey(const CryptoAlgorithm &);
- virtual Token import(DataType dataType, const RawBuffer &buffer);
+ virtual GObjUPtr getObject(const Token &, const Password &);
+ virtual TokenPair generateAKey(const CryptoAlgorithm &, const Password &, const Password &);
+ virtual Token generateSKey(const CryptoAlgorithm &, const Password &);
+ virtual Token import(DataType, const RawBuffer &, const Password &);
virtual void destroy(const Token &){}
};
diff --git a/src/manager/crypto/tz-backend/store.cpp b/src/manager/crypto/tz-backend/store.cpp
index fe3fae70..1c5d58a6 100644
--- a/src/manager/crypto/tz-backend/store.cpp
+++ b/src/manager/crypto/tz-backend/store.cpp
@@ -30,15 +30,15 @@ Store::Store(CryptoBackend backendId)
: GStore(backendId)
{}
-GObjUPtr Store::getObject(const Token &) {
+GObjUPtr Store::getObject(const Token &, const Password &) {
ThrowErr(Exc::Crypto::OperationNotSupported, "Trust zone backend is not implemented!");
}
-TokenPair Store::generateAKey(const CryptoAlgorithm &) {
+TokenPair Store::generateAKey(const CryptoAlgorithm &, const Password &, const Password &) {
ThrowErr(Exc::Crypto::OperationNotSupported, "Trust zone backend is not implemented!");
}
-Token Store::import(DataType, const RawBuffer &) {
+Token Store::import(DataType, const RawBuffer &, const Password &) {
ThrowErr(Exc::Crypto::OperationNotSupported, "Trust zone backend is not implemented!");
}
diff --git a/src/manager/crypto/tz-backend/store.h b/src/manager/crypto/tz-backend/store.h
index be3595cf..85e193df 100644
--- a/src/manager/crypto/tz-backend/store.h
+++ b/src/manager/crypto/tz-backend/store.h
@@ -31,9 +31,9 @@ class Store : public GStore {
public:
explicit Store(CryptoBackend backendId);
- virtual GObjUPtr getObject(const Token &token);
- virtual TokenPair generateAKey(const CryptoAlgorithm &);
- virtual Token import(DataType dataType, const RawBuffer &buffer);
+ virtual GObjUPtr getObject(const Token &, const Password &);
+ virtual TokenPair generateAKey(const CryptoAlgorithm &, const Password &, const Password &);
+ virtual Token import(DataType dataType, const RawBuffer &buffer, const Password &);
virtual void destroy(const Token &){}
};
diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp
index 728bfc5e..8736fd50 100644
--- a/src/manager/service/ckm-logic.cpp
+++ b/src/manager/service/ckm-logic.cpp
@@ -418,16 +418,11 @@ DB::Row CKMLogic::createEncryptedRow(
const Policy &policy) const
{
Crypto::GStore& store = m_decider.getStore(dataType, policy.extractable);
- Token token = store.import(dataType, data);
-
- DB::Row row(std::move(token), name, label, static_cast<int>(policy.extractable));
// do not encrypt data with password during cc_mode on
- if(m_accessControl.isCCMode()) {
- crypto.encryptRow("", row);
- } else {
- crypto.encryptRow(policy.password, row);
- }
+ Token token = store.import(dataType, data, m_accessControl.isCCMode() ? "" : policy.password);
+ DB::Row row(std::move(token), name, label, static_cast<int>(policy.extractable));
+ crypto.encryptRow(row);
return row;
}
@@ -515,9 +510,10 @@ int CKMLogic::getKeyForService(
DB::Row row;
try {
// Key is for internal service use. It won't be exported to the client
- int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, label, pass, row);
+ Crypto::GObjUPtr obj;
+ int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, label, pass, obj);
if (retCode == CKM_API_SUCCESS)
- key = m_decider.getStore(row).getObject(row);
+ key = std::move(obj);
return retCode;
} catch (const DB::Crypto::Exception::Base &e) {
LogError("DB::Crypto failed with message: " << e.GetMessage());
@@ -666,17 +662,12 @@ int CKMLogic::removeDataHelper(
// destroy it in store
for(auto& r : rows) {
- /*
- * TODO: If row is encrypted with user password we won't be able to decrypt it (tz id).
- * Encryption/decryption with user password and with app key should both be done inside the
- * store (import, getKey and generateXKey).
- */
try {
handler.crypto.decryptRow(Password(), r);
+ m_decider.getStore(r).destroy(r);
} catch (const Exc::AuthenticationFailed&) {
LogDebug("Authentication failed when removing data. Ignored.");
}
- m_decider.getStore(r.dataType, r.exportable).destroy(r);
}
// delete row in db
@@ -803,6 +794,45 @@ int CKMLogic::checkDataPermissionsHelper(const Credentials &cred,
return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt));
}
+Crypto::GObjUPtr CKMLogic::rowToObject(
+ UserData& handler,
+ DB::Row row,
+ const Password& password)
+{
+ Crypto::GStore& store = m_decider.getStore(row);
+
+ Password pass = m_accessControl.isCCMode() ? "" : password;
+
+ // decrypt row
+ Crypto::GObjUPtr obj;
+ if(CryptoLogic::getSchemeVersion(row.encryptionScheme) == CryptoLogic::ENCRYPTION_V2) {
+ handler.crypto.decryptRow(Password(), row);
+
+ obj = store.getObject(row, pass);
+ } else {
+ // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
+ handler.crypto.decryptRow(pass, row);
+ // destroy it in store
+ store.destroy(row);
+
+ // import it to store with new scheme: data -> pass(data)
+ Token token = store.import(row.dataType,row.data, pass);
+
+ // get it from the store (it can be different than the data we imported into store)
+ obj = store.getObject(token, pass);
+
+ // update row with new token
+ *static_cast<Token*>(&row) = std::move(token);
+
+ // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
+ handler.crypto.encryptRow(row);
+
+ // update it in db
+ handler.database.updateRow(row);
+ }
+ return obj;
+}
+
int CKMLogic::readDataHelper(
bool exportFlag,
const Credentials &cred,
@@ -810,7 +840,7 @@ int CKMLogic::readDataHelper(
const Name &name,
const Label &label,
const Password &password,
- DB::RowVector &rows)
+ Crypto::GObjUPtrVector &objs)
{
auto &handler = selectDatabase(cred, label);
@@ -822,6 +852,7 @@ int CKMLogic::readDataHelper(
// read rows
DB::Crypto::Transaction transaction(&handler.database);
+ DB::RowVector rows;
int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows);
if(CKM_API_SUCCESS != retCode)
return retCode;
@@ -841,7 +872,9 @@ int CKMLogic::readDataHelper(
// decrypt row
for(auto &row : rows)
- handler.crypto.decryptRow(password, row);
+ objs.push_back(rowToObject(handler, std::move(row), password));
+ // rowToObject may modify db
+ transaction.commit();
return CKM_API_SUCCESS;
}
@@ -853,7 +886,21 @@ int CKMLogic::readDataHelper(
const Name &name,
const Label &label,
const Password &password,
- DB::Row &row)
+ Crypto::GObjUPtr &obj)
+{
+ DataType objDataType;
+ return readDataHelper(exportFlag, cred, dataType, name, label, password, obj, objDataType);
+}
+
+int CKMLogic::readDataHelper(
+ bool exportFlag,
+ const Credentials &cred,
+ DataType dataType,
+ const Name &name,
+ const Label &label,
+ const Password &password,
+ Crypto::GObjUPtr &obj,
+ DataType& objDataType)
{
auto &handler = selectDatabase(cred, label);
@@ -865,10 +912,13 @@ int CKMLogic::readDataHelper(
// read row
DB::Crypto::Transaction transaction(&handler.database);
+ DB::Row row;
int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row);
if(CKM_API_SUCCESS != retCode)
return retCode;
+ objDataType = row.dataType;
+
// check access rights
retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
if(CKM_API_SUCCESS != retCode)
@@ -879,8 +929,9 @@ int CKMLogic::readDataHelper(
if(CKM_API_SUCCESS != retCode)
return retCode;
- // decrypt row
- handler.crypto.decryptRow(password, row);
+ obj = rowToObject(handler, std::move(row), password);
+ // rowToObject may modify db
+ transaction.commit();
return CKM_API_SUCCESS;
}
@@ -895,9 +946,13 @@ RawBuffer CKMLogic::getData(
{
int retCode = CKM_API_SUCCESS;
DB::Row row;
+ DataType objDataType;
try {
- retCode = readDataHelper(true, cred, dataType, name, label, password, row);
+ Crypto::GObjUPtr obj;
+ retCode = readDataHelper(true, cred, dataType, name, label, password, obj, objDataType);
+ if(retCode == CKM_API_SUCCESS)
+ row.data = std::move(obj->getBinary());
} catch (const DB::Crypto::Exception::Base &e) {
LogError("DB::Crypto failed with message: " << e.GetMessage());
retCode = CKM_API_ERROR_DB_ERROR;
@@ -916,7 +971,7 @@ RawBuffer CKMLogic::getData(
auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
commandId,
retCode,
- static_cast<int>(row.dataType),
+ static_cast<int>(objDataType),
row.data);
return response.Pop();
}
@@ -934,27 +989,27 @@ int CKMLogic::getPKCS12Helper(
int retCode;
// read private key (mandatory)
- DB::Row privKeyRow;
- retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, privKeyRow);
+ Crypto::GObjUPtr keyObj;
+ retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, keyObj);
if(retCode != CKM_API_SUCCESS)
return retCode;
- privKey = CKM::Key::create(privKeyRow.data);
+ privKey = CKM::Key::create(keyObj->getBinary());
// read certificate (mandatory)
- DB::Row certRow;
- retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certRow);
+ Crypto::GObjUPtr certObj;
+ retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certObj);
if(retCode != CKM_API_SUCCESS)
return retCode;
- cert = CKM::Certificate::create(certRow.data, DataFormat::FORM_DER);
+ cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
// read CA cert chain (optional)
- DB::RowVector rawCaChain;
- retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, rawCaChain);
+ Crypto::GObjUPtrVector caChainObjs;
+ retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, caChainObjs);
if(retCode != CKM_API_SUCCESS &&
retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
return retCode;
- for(auto &rawCaCert : rawCaChain)
- caChain.push_back(CKM::Certificate::create(rawCaCert.data, DataFormat::FORM_DER));
+ for(auto &caCertObj : caChainObjs)
+ caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(), DataFormat::FORM_DER));
// if anything found, return it
if(privKey || cert || caChain.size()>0)
@@ -1157,17 +1212,33 @@ int CKMLogic::createKeyAESHelper(
const Label &label,
const PolicySerializable &policy)
{
+ auto &handler = selectDatabase(cred, label);
+
+ // use client label if not explicitly provided
+ const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
+ if( m_accessControl.isSystemService(cred) && ownerLabel.compare(OWNER_ID_SYSTEM)!=0)
+ return CKM_API_ERROR_INPUT_PARAM;
+
+ // check if save is possible
+ DB::Crypto::Transaction transaction(&handler.database);
+ int retCode = checkSaveConditions(cred, handler, name, ownerLabel);
+ if(retCode != CKM_API_SUCCESS)
+ return retCode;
+
+ // create key in store
CryptoAlgorithm keyGenAlgorithm;
keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
- Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm);
-
- return saveDataHelper(cred,
- name,
- label,
- DataType::KEY_AES,
- key.data,
- policy);
+ Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm, policy.password);
+
+ // save the data
+ DB::Row row(std::move(key), name, ownerLabel, static_cast<int>(policy.extractable));
+ handler.crypto.encryptRow(row);
+
+ handler.database.saveRow(row);
+
+ transaction.commit();
+ return CKM_API_SUCCESS;
}
@@ -1191,32 +1262,41 @@ int CKMLogic::createKeyPairHelper(
if(!dt.isKey())
ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
+ // use client label if not explicitly provided
+ const Label &ownerLabelPrv = labelPrivate.empty() ? cred.smackLabel : labelPrivate;
+ if( m_accessControl.isSystemService(cred) && ownerLabelPrv.compare(OWNER_ID_SYSTEM)!=0)
+ return CKM_API_ERROR_INPUT_PARAM;
+ const Label &ownerLabelPub = labelPublic.empty() ? cred.smackLabel : labelPublic;
+ if( m_accessControl.isSystemService(cred) && ownerLabelPub.compare(OWNER_ID_SYSTEM)!=0)
+ return CKM_API_ERROR_INPUT_PARAM;
+
bool exportable = policyPrivate.extractable || policyPublic.extractable;
- TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams);
+ TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams,
+ policyPrivate.password,
+ policyPublic.password);
DB::Crypto::Transaction transactionPriv(&handlerPriv.database);
// in case the same database is used for private and public - the second
// transaction will not be executed
DB::Crypto::Transaction transactionPub(&handlerPub.database);
- int retCode = saveDataHelper(cred,
- namePrivate,
- labelPrivate,
- keys.first.dataType,
- keys.first.data,
- policyPrivate);
- if (CKM_API_SUCCESS != retCode)
+ int retCode;
+ retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerLabelPrv);
+ if(retCode != CKM_API_SUCCESS)
return retCode;
-
- retCode = saveDataHelper(cred,
- namePublic,
- labelPublic,
- keys.second.dataType,
- keys.second.data,
- policyPublic);
- if (CKM_API_SUCCESS != retCode)
+ retCode = checkSaveConditions(cred, handlerPub, namePrivate, ownerLabelPub);
+ if(retCode != CKM_API_SUCCESS)
return retCode;
+ // save the data
+ DB::Row rowPrv(std::move(keys.first), namePrivate, ownerLabelPrv, static_cast<int>(policyPrivate.extractable));
+ handlerPriv.crypto.encryptRow(rowPrv);
+ handlerPriv.database.saveRow(rowPrv);
+
+ DB::Row rowPub(std::move(keys.second), namePublic, ownerLabelPub, static_cast<int>(policyPublic.extractable));
+ handlerPub.crypto.encryptRow(rowPub);
+ handlerPub.database.saveRow(rowPub);
+
transactionPub.commit();
transactionPriv.commit();
return CKM_API_SUCCESS;
@@ -1301,18 +1381,21 @@ int CKMLogic::readCertificateHelper(
{
DB::Row row;
for (auto &i: labelNameVector) {
- int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), row);
+ // certificates can't be protected with custom user password
+ Crypto::GObjUPtr obj;
+ int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), obj);
if (ec != CKM_API_SUCCESS)
return ec;
- certVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
+
+ certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER);
// try to read chain certificates (if present)
- DB::RowVector rawCaChain;
- ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), rawCaChain);
+ Crypto::GObjUPtrVector caChainObjs;
+ ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), caChainObjs);
if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
return ec;
- for(auto &rawCaCert : rawCaChain)
- certVector.push_back(CertificateImpl(rawCaCert.data, DataFormat::FORM_DER));
+ for(auto &caCertObj : caChainObjs)
+ certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER);
}
return CKM_API_SUCCESS;
}
@@ -1490,9 +1573,10 @@ RawBuffer CKMLogic::createSignature(
int retCode = CKM_API_SUCCESS;
try {
- retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
+ Crypto::GObjUPtr obj;
+ retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, obj);
if(retCode == CKM_API_SUCCESS) {
- signature = m_decider.getStore(row).getObject(row)->sign(cryptoAlg, message);
+ signature = obj->sign(cryptoAlg, message);
}
} catch (const DB::Crypto::Exception::Base &e) {
LogError("DB::Crypto failed with message: " << e.GetMessage());
@@ -1534,13 +1618,14 @@ RawBuffer CKMLogic::verifySignature(
// try certificate first - looking for a public key.
// in case of PKCS, pub key from certificate will be found first
// rather than private key from the same PKCS.
- retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
+ Crypto::GObjUPtr obj;
+ retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, obj);
if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
- retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
+ retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, obj);
}
if (retCode == CKM_API_SUCCESS) {
- retCode = m_decider.getStore(row).getObject(row)->verify(params, message, signature);
+ retCode = obj->verify(params, message, signature);
}
} catch (const Exc::Exception &e) {
retCode = e.error();
diff --git a/src/manager/service/ckm-logic.h b/src/manager/service/ckm-logic.h
index c07225bd..d3f0c402 100644
--- a/src/manager/service/ckm-logic.h
+++ b/src/manager/service/ckm-logic.h
@@ -314,6 +314,11 @@ private:
bool exportFlag,
DB::Crypto & database);
+ Crypto::GObjUPtr rowToObject(
+ UserData& handler,
+ DB::Row row,
+ const Password& password);
+
int readDataHelper(
bool exportFlag,
const Credentials &cred,
@@ -321,7 +326,17 @@ private:
const Name &name,
const Label &label,
const Password &password,
- DB::Row &row);
+ Crypto::GObjUPtr &obj);
+
+ int readDataHelper(
+ bool exportFlag,
+ const Credentials &cred,
+ DataType dataType,
+ const Name &name,
+ const Label &label,
+ const Password &password,
+ Crypto::GObjUPtr &obj,
+ DataType& objDataType);
int readDataHelper(
bool exportFlag,
@@ -330,7 +345,7 @@ private:
const Name &name,
const Label &label,
const Password &password,
- DB::RowVector &rows);
+ Crypto::GObjUPtrVector &objs);
int createKeyAESHelper(
const Credentials &cred,
diff --git a/src/manager/service/crypto-logic.cpp b/src/manager/service/crypto-logic.cpp
index 9f663c88..c7b8786c 100644
--- a/src/manager/service/crypto-logic.cpp
+++ b/src/manager/service/crypto-logic.cpp
@@ -23,6 +23,7 @@
#include <iostream>
#include <fstream>
#include <utility>
+#include <climits>
#include <stdio.h>
#include <string.h>
@@ -41,14 +42,34 @@
#include <generic-backend/exception.h>
#include <sw-backend/internals.h>
+namespace CKM {
+
namespace {
const static int AES_CBC_KEY_SIZE = 32;
const static int AES_GCM_TAG_SIZE = 16;
-} // anonymous namespace
+// Encryption scheme flags (enable/disable specific encryption type, multiple choice)
+const int ENCR_BASE64 = 1 << 0;
+const int ENCR_APPKEY = 1 << 1;
+const int ENCR_PASSWORD = 1 << 2;
-namespace CKM {
+// Encryption order flags (single choice)
+const int ENCR_ORDER_OFFSET = 24;
+const int ENCR_ORDER_FILTER = INT_MAX << ENCR_ORDER_OFFSET; // 0xff000000
+const int ENCR_ORDER_CLEAR = ~ENCR_ORDER_FILTER; // 0x00ffffff
+/*
+ * ENCR_ORDER_V1 - v1 encryption order. Token returned from store is encrypted with app key and
+ * optionally by custom user password. In such form it is stored in db.
+ */
+const int ENCR_ORDER_V1 = CryptoLogic::ENCRYPTION_V1 << ENCR_ORDER_OFFSET;
+/*
+ * ENCR_ORDER_V2 - v2 encryption order. Stored data is optionally encrypted by store with
+ * user password. Returned token is encrypted with app key and stored in db.
+ */
+const int ENCR_ORDER_V2 = CryptoLogic::ENCRYPTION_V2 << ENCR_ORDER_OFFSET;
+
+} // anonymous namespace
CryptoLogic::CryptoLogic() {}
@@ -122,7 +143,7 @@ RawBuffer CryptoLogic::generateRandIV() const {
return civ;
}
-void CryptoLogic::encryptRow(const Password &password, DB::Row &row)
+void CryptoLogic::encryptRow(DB::Row &row)
{
try {
DB::Row crow = row;
@@ -154,17 +175,13 @@ void CryptoLogic::encryptRow(const Password &password, DB::Row &row)
crow.tag = dataPair.second;
- if (!password.empty()) {
- key = passwordToKey(password, crow.iv, AES_CBC_KEY_SIZE);
-
- crow.data = Crypto::SW::Internals::encryptDataAes(AlgoType::AES_CBC, key, crow.data, crow.iv);
- crow.encryptionScheme |= ENCR_PASSWORD;
- }
-
encBase64(crow.data);
crow.encryptionScheme |= ENCR_BASE64;
encBase64(crow.iv);
+ crow.encryptionScheme &= ENCR_ORDER_CLEAR;
+ crow.encryptionScheme |= ENCR_ORDER_V2;
+
row = std::move(crow);
} catch(const CKM::Base64Encoder::Exception::Base &e) {
ThrowErr(Exc::InternalError, e.GetMessage());
@@ -173,6 +190,11 @@ void CryptoLogic::encryptRow(const Password &password, DB::Row &row)
}
}
+int CryptoLogic::getSchemeVersion(int encryptionScheme)
+{
+ return encryptionScheme >> ENCR_ORDER_OFFSET;
+}
+
void CryptoLogic::decryptRow(const Password &password, DB::Row &row)
{
try {
@@ -200,16 +222,22 @@ void CryptoLogic::decryptRow(const Password &password, DB::Row &row)
decBase64(crow.data);
}
- if (crow.encryptionScheme & ENCR_PASSWORD) {
- key = passwordToKey(password, crow.iv, AES_CBC_KEY_SIZE);
- crow.data = Crypto::SW::Internals::decryptDataAes(AlgoType::AES_CBC, key, crow.data, crow.iv);
+ if((crow.encryptionScheme >> ENCR_ORDER_OFFSET) == ENCR_ORDER_V2) {
+ if (crow.encryptionScheme & ENCR_APPKEY) {
+ key = m_keyMap[crow.ownerLabel];
+ crow.data = Crypto::SW::Internals::decryptDataAesGcm(key, crow.data, crow.iv, crow.tag);
+ }
+ } else {
+ if (crow.encryptionScheme & ENCR_PASSWORD) {
+ key = passwordToKey(password, crow.iv, AES_CBC_KEY_SIZE);
+ crow.data = Crypto::SW::Internals::decryptDataAes(AlgoType::AES_CBC, key, crow.data, crow.iv);
+ }
+
+ if (crow.encryptionScheme & ENCR_APPKEY) {
+ key = m_keyMap[crow.ownerLabel];
+ crow.data = Crypto::SW::Internals::decryptDataAesGcm(key, crow.data, crow.iv, crow.tag);
+ }
}
-
- if (crow.encryptionScheme & ENCR_APPKEY) {
- key = m_keyMap[crow.ownerLabel];
- crow.data = Crypto::SW::Internals::decryptDataAesGcm(key, crow.data, crow.iv, crow.tag);
- }
-
if (static_cast<int>(crow.data.size()) < crow.dataSize) {
ThrowErr(Exc::AuthenticationFailed, "Decrypted row size mismatch");
}
diff --git a/src/manager/service/crypto-logic.h b/src/manager/service/crypto-logic.h
index b734bb4a..61c582e4 100644
--- a/src/manager/service/crypto-logic.h
+++ b/src/manager/service/crypto-logic.h
@@ -38,18 +38,38 @@ public:
virtual ~CryptoLogic(){}
void decryptRow(const Password &password, DB::Row &row);
- void encryptRow(const Password &password, DB::Row &row);
+ void encryptRow(DB::Row &row);
+
+ static int getSchemeVersion(int encryptionScheme);
bool haveKey(const Label &smackLabel);
void pushKey(const Label &smackLabel,
const RawBuffer &applicationKey);
void removeKey(const Label &smackLabel);
+ static const int ENCRYPTION_V1 = 0;
+ static const int ENCRYPTION_V2 = 1;
+
private:
+ // Encryption scheme flags (enable/disable specific encryption type, multiple choice)
static const int ENCR_BASE64 = 1 << 0;
static const int ENCR_APPKEY = 1 << 1;
static const int ENCR_PASSWORD = 1 << 2;
+ // Encryption order flags (single choice)
+ static const int ENCR_ORDER_CLEAR = 0x00ffffff;
+ static const int ENCR_ORDER_FILTER = ~ENCR_ORDER_CLEAR;
+ /*
+ * ENCR_ORDER_V1 - v1 encryption order. Token returned from store is encrypted with app key and
+ * optionally by custom user password. Is such form it is stored in db.
+ */
+ static const int ENCR_ORDER_V1 = ENCR_ORDER_CLEAR + 0;
+ /*
+ * ENCR_ORDER_V2 - v2 encryption order. Stored data is optionally encrypted by store with
+ * user password. Returned token is encrypted with app key and stored in db.
+ */
+ static const int ENCR_ORDER_V2 = ENCR_ORDER_CLEAR + 1;
+
std::map<Label, RawBuffer> m_keyMap;
RawBuffer generateRandIV() const;
diff --git a/src/manager/service/db-crypto.cpp b/src/manager/service/db-crypto.cpp
index 8a5b57b4..99c01552 100644
--- a/src/manager/service/db-crypto.cpp
+++ b/src/manager/service/db-crypto.cpp
@@ -94,6 +94,17 @@ namespace {
" ?009"
" );";
+ const char *DB_CMD_OBJECT_UPDATE =
+ "UPDATE OR FAIL OBJECTS SET"
+ " algorithmType = ?003,"
+ " encryptionScheme = ?004,"
+ " iv = ?005,"
+ " dataSize = ?006,"
+ " data = ?007,"
+ " tag = ?008"
+ " WHERE idx IN (SELECT idx FROM NAMES WHERE name=?101 and label=?102)"
+ " AND dataType = ?002;";
+
const char *DB_CMD_OBJECT_SELECT_BY_NAME_AND_LABEL =
"SELECT * FROM [join_name_object_tables] "
" WHERE (dataType BETWEEN ?001 AND ?002) "
@@ -388,6 +399,21 @@ namespace DB {
"Couldn't save Row");
}
+ void Crypto::updateRow(const Row &row) {
+ Try {
+ // transaction is present in the layer above
+ ObjectTable objectTable(this->m_connection);
+ objectTable.updateRow(row);
+ return;
+ } Catch(SqlConnection::Exception::SyntaxError) {
+ LogError("Couldn't prepare update statement");
+ } Catch(SqlConnection::Exception::InternalError) {
+ LogError("Couldn't execute update statement");
+ }
+ ThrowMsg(Crypto::Exception::InternalError,
+ "Couldn't update Row");
+ }
+
bool Crypto::deleteRow(
const Name &name,
const Label &ownerLabel)
@@ -826,6 +852,25 @@ namespace DB {
insertObjectCommand->Step();
}
+
+ void Crypto::ObjectTable::updateRow(const Row &row)
+ {
+ SqlConnection::DataCommandUniquePtr updateObjectCommand =
+ m_connection->PrepareDataCommand(DB_CMD_OBJECT_UPDATE);
+ updateObjectCommand->BindInteger(2, static_cast<int>(row.dataType));
+ updateObjectCommand->BindInteger(3, static_cast<int>(row.algorithmType));
+ updateObjectCommand->BindInteger(4, row.encryptionScheme);
+ updateObjectCommand->BindBlob (5, row.iv);
+ updateObjectCommand->BindInteger(6, row.dataSize);
+ updateObjectCommand->BindBlob (7, row.data);
+ updateObjectCommand->BindBlob (8, row.tag);
+
+ // name table reference
+ updateObjectCommand->BindString (101, row.name.c_str());
+ updateObjectCommand->BindString (102, row.ownerLabel.c_str());
+
+ updateObjectCommand->Step();
+ }
} // namespace DB
} // namespace CKM
diff --git a/src/manager/service/db-crypto.h b/src/manager/service/db-crypto.h
index c83b1e1b..dae00317 100644
--- a/src/manager/service/db-crypto.h
+++ b/src/manager/service/db-crypto.h
@@ -72,6 +72,9 @@ namespace DB {
const Label &owner,
const RowVector &rows);
+ void updateRow(
+ const Row &row);
+
bool isNameLabelPresent(
const Name &name,
const Label &owner) const;
@@ -277,6 +280,8 @@ namespace DB {
void addRow(
const Row &row);
+ void updateRow(
+ const Row &row);
private:
SqlConnection* m_connection;