Encrypted Initial Values: parsing key values. 73/44273/23
authorMaciej J. Karpiuk <m.karpiuk2@samsung.com>
Mon, 20 Jul 2015 09:31:29 +0000 (11:31 +0200)
committerBartlomiej Grzelewski <b.grzelewski@samsung.com>
Tue, 24 Nov 2015 17:38:34 +0000 (09:38 -0800)
Change-Id: Iecebe5cba1ce716e43fff09ddc442a57dcfdf976

src/CMakeLists.txt
src/manager/crypto/sw-backend/store.cpp
src/manager/crypto/sw-backend/store.h
src/manager/initial-values/InitialValuesFile.cpp
src/manager/initial-values/InitialValuesFile.h
src/manager/initial-values/SWKeyFile.cpp [new file with mode: 0644]
src/manager/initial-values/SWKeyFile.h [new file with mode: 0644]
src/manager/initial-values/xml-utils.cpp
src/manager/initial-values/xml-utils.h
tools/ckm_db_tool/CMakeLists.txt

index fa31106..ceb976e 100644 (file)
@@ -61,6 +61,7 @@ SET(KEY_MANAGER_SOURCES
     ${KEY_MANAGER_PATH}/initial-values/InitialValueHandler.cpp
     ${KEY_MANAGER_PATH}/initial-values/InitialValuesFile.cpp
     ${KEY_MANAGER_PATH}/initial-values/NoCharactersHandler.cpp
+    ${KEY_MANAGER_PATH}/initial-values/SWKeyFile.cpp
     ${KEY_MANAGER_PATH}/initial-values/xml-utils.cpp
     ${KEY_MANAGER_PATH}/initial-values/initial-value-loader.cpp
     ${KEY_MANAGER_PATH}/dpl/core/src/assert.cpp
index e1ca362..d59cea1 100644 (file)
@@ -27,6 +27,8 @@
 #include <sw-backend/obj.h>
 #include <sw-backend/store.h>
 #include <sw-backend/internals.h>
+#include <SWKeyFile.h>
+#include <dpl/log/log.h>
 
 #include <message-buffer.h>
 
@@ -142,9 +144,31 @@ RawBuffer pack(const RawBuffer& data, const Password& pass)
 
 } // namespace anonymous
 
+namespace
+{
+const char * const DEVICE_KEY_XSD       = "/usr/share/ckm/sw_key.xsd";
+const char * const DEVICE_KEY_SW_FILE   = "/opt/data/ckm/device_key.xml";
+}
+
 Store::Store(CryptoBackend backendId)
   : GStore(backendId)
 {
+    // get the device key if present
+    InitialValues::SWKeyFile keyFile(DEVICE_KEY_SW_FILE);
+    int rc = keyFile.Validate(DEVICE_KEY_XSD);
+    if(rc == XML::Parser::PARSE_SUCCESS)
+    {
+        rc = keyFile.Parse();
+        if(rc == XML::Parser::PARSE_SUCCESS)
+            m_deviceKey = keyFile.getPrivKey();
+        else
+        {
+            // do nothing, bypass encrypted elements
+            LogWarning("invalid SW key file: " << DEVICE_KEY_SW_FILE << ", parsing code: " << rc);
+        }
+    }
+    else
+        LogWarning("invalid SW key file: " << DEVICE_KEY_SW_FILE << ", validation code: " << rc);
 }
 
 GObjUPtr Store::getObject(const Token &token, const Password &pass) {
@@ -194,8 +218,21 @@ Token Store::import(const Data &data, const Password &pass) {
     return Token(m_backendId, data.type, pack(data.data, pass));
 }
 
-Token Store::importEncrypted(const Data &, const Password &, const DataEncryption &) {
-    ThrowErr(Exc::Crypto::OperationNotSupported, "Importing encrypted data not yet implemented!");
+Token Store::importEncrypted(const Data &data, const Password &pass, const DataEncryption &enc) {
+    if(!m_deviceKey)
+        ThrowErr(Exc::Crypto::InternalError, "No device key present");
+
+    // decrypt the AES key using device key
+    CryptoAlgorithm algorithmRSAOAEP;
+    algorithmRSAOAEP.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_OAEP);
+    Crypto::SW::SKey aesKey(m_deviceKey->decrypt(algorithmRSAOAEP, enc.encryptedKey), DataType::KEY_AES);
+
+    // decrypt the buffer using AES key
+    CryptoAlgorithm algorithmAESCBC;
+    algorithmAESCBC.setParam(ParamName::ALGO_TYPE, AlgoType::AES_CBC);
+    algorithmAESCBC.setParam(ParamName::ED_IV, enc.iv);
+    RawBuffer rawData = aesKey.decrypt(algorithmAESCBC, data.data);
+    return Token(m_backendId, data.type, pack(rawData, pass));
 }
 
 } // namespace SW
index 03d69ff..860e393 100644 (file)
@@ -37,6 +37,9 @@ public:
     virtual Token import(const Data &data, const Password &);
     virtual Token importEncrypted(const Data &, const Password &, const DataEncryption &);
     virtual void destroy(const Token &){}
+
+private:
+    Crypto::GObjShPtr m_deviceKey;
 };
 
 } // namespace SW
index bc5fbec..166f158 100644 (file)
 #include <CertHandler.h>
 #include <DataHandler.h>
 #include <EncodingType.h>
+#include <sw-backend/obj.h>
 #include <dpl/log/log.h>
 
 namespace {
 const int          XML_CURRENT_VERSION      = 1;
 const char * const XML_TAG_INITIAL_VALUES   = "InitialValues";
+const char * const XML_TAG_ENCRYPTION_KEY   = "EncryptionKey";
 const char * const XML_TAG_KEY              = "Key";
 const char * const XML_TAG_DATA             = "Data";
 const char * const XML_TAG_CERT             = "Cert";
@@ -48,9 +50,11 @@ const char * const XML_ATTR_VERSION         = "version";
 namespace CKM {
 namespace InitialValues {
 
-InitialValuesFile::InitialValuesFile(const std::string &XML_filename, CKMLogic & db_logic)
+InitialValuesFile::InitialValuesFile(const std::string &XML_filename,
+                                     CKMLogic & db_logic)
         : m_parser(XML_filename), m_db_logic(db_logic),
-          m_header(std::make_shared<HeaderHandler>(*this))
+          m_header(std::make_shared<HeaderHandler>(*this)),
+          m_encryptionKeyHandler(std::make_shared<EncryptionKeyHandler>(*this))
 {
     m_parser.RegisterErrorCb(InitialValuesFile::Error);
     m_parser.RegisterElementCb(XML_TAG_INITIAL_VALUES,
@@ -59,6 +63,15 @@ InitialValuesFile::InitialValuesFile(const std::string &XML_filename, CKMLogic &
                 return m_header;
             },
             [this](const XML::Parser::ElementHandlerPtr &) {});
+    m_parser.RegisterElementCb(XML_TAG_ENCRYPTION_KEY,
+            [this]() -> XML::Parser::ElementHandlerPtr
+            {
+                return m_encryptionKeyHandler;
+            },
+            [this](const XML::Parser::ElementHandlerPtr &)
+            {
+                m_encryptedAESkey = m_encryptionKeyHandler->getEncryptedKey();
+            });
 }
 
 void InitialValuesFile::registerElementListeners()
@@ -226,6 +239,24 @@ void InitialValuesFile::ReleasePermissionHandler()
 }
 
 
+InitialValuesFile::EncryptionKeyHandler::EncryptionKeyHandler(InitialValuesFile & parent) : m_parent(parent) {}
+void InitialValuesFile::EncryptionKeyHandler::Characters(const std::string &data) {
+    m_encryptedKey.reserve(m_encryptedKey.size() + data.size());
+    m_encryptedKey.insert(m_encryptedKey.end(), data.begin(), data.end());
+};
+void InitialValuesFile::EncryptionKeyHandler::End() {
+    std::string trimmed = XML::trimEachLine(std::string(m_encryptedKey.begin(), m_encryptedKey.end()));
+    Base64Decoder base64;
+    base64.reset();
+    base64.append(RawBuffer(trimmed.begin(), trimmed.end()));
+    base64.finalize();
+    m_encryptedKey = base64.get();
+};
+
+CKM::RawBuffer InitialValuesFile::EncryptionKeyHandler::getEncryptedKey() const {
+    return m_encryptedKey;
+}
+
 InitialValuesFile::HeaderHandler::HeaderHandler(InitialValuesFile & parent)
     : m_version(-1), m_parent(parent) {}
 void InitialValuesFile::HeaderHandler::Start(const XML::Parser::Attributes & attr)
index 8226822..1572e2f 100644 (file)
 #include <parser.h>
 #include <InitialValueHandler.h>
 #include <ckm-logic.h>
+#include <string>
+#include <algorithm>
+#include <cctype>
+#include <xml-utils.h>
+#include <base64.h>
 
 namespace CKM {
 namespace InitialValues {
 
+
 class InitialValuesFile
 {
 public:
@@ -74,8 +80,26 @@ private:
         int m_version;
         InitialValuesFile & m_parent;
     };
+
+    class EncryptionKeyHandler : public XML::Parser::ElementHandler
+    {
+    public:
+        explicit EncryptionKeyHandler(InitialValuesFile & parent);
+        virtual void Start(const XML::Parser::Attributes &) {};
+        virtual void Characters(const std::string &data);
+        virtual void End();
+
+        CKM::RawBuffer getEncryptedKey() const;
+    private:
+        CKM::RawBuffer m_encryptedKey;
+        InitialValuesFile & m_parent;
+    };
+
     typedef std::shared_ptr<HeaderHandler> HeaderHandlerPtr;
+    typedef std::shared_ptr<EncryptionKeyHandler> EncryptionKeyHandlerPtr;
     HeaderHandlerPtr m_header;
+    EncryptionKeyHandlerPtr m_encryptionKeyHandler;
+    CKM::RawBuffer m_encryptedAESkey;
 
     void registerElementListeners();
     static void Error(const XML::Parser::ErrorType errorType,
diff --git a/src/manager/initial-values/SWKeyFile.cpp b/src/manager/initial-values/SWKeyFile.cpp
new file mode 100644 (file)
index 0000000..f614185
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ *
+ * @file        SWKeyFile.cpp
+ * @author      Maciej Karpiuk (m.karpiuk2@samsung.com)
+ * @version     1.0
+ * @brief       SWKeyFile class implementation.
+ */
+
+#include <iostream>
+#include <SWKeyFile.h>
+#include <BufferHandler.h>
+#include <EncodingType.h>
+#include <sw-backend/obj.h>
+#include <dpl/log/log.h>
+
+namespace {
+const int          XML_SW_KEY_CURRENT_VERSION   = 1;
+const char * const XML_TAG_DEVICE_KEY           = "DeviceKey";
+const char * const XML_TAG_RSA_KEY              = "RSAPrivateKey";
+const char * const XML_TAG_PEM                  = "PEM";
+const char * const XML_TAG_DER                  = "DERBase64";
+const char * const XML_TAG_BASE64               = "Base64";
+const char * const XML_ATTR_VERSION             = "version";
+}
+
+namespace CKM {
+namespace InitialValues {
+
+SWKeyFile::SWKeyFile(const std::string &XML_filename)
+        : m_parser(XML_filename),
+          m_header(std::make_shared<HeaderHandler>(*this)),
+          m_RSAKeyHandler(std::make_shared<RSAKeyHandler>(*this))
+{
+    m_parser.RegisterErrorCb(SWKeyFile::Error);
+    m_parser.RegisterElementCb(XML_TAG_DEVICE_KEY,
+            [this]() -> XML::Parser::ElementHandlerPtr
+            {
+                return m_header;
+            },
+            [this](const XML::Parser::ElementHandlerPtr &) {});
+}
+
+void SWKeyFile::registerElementListeners()
+{
+    m_parser.RegisterElementCb(XML_TAG_RSA_KEY,
+            [this]() -> XML::Parser::ElementHandlerPtr
+            {
+                return m_RSAKeyHandler;
+            },
+            [this](const XML::Parser::ElementHandlerPtr &)
+            {
+                m_deviceKey = m_RSAKeyHandler->getPrivKey();
+            });
+}
+
+void SWKeyFile::Error(const XML::Parser::ErrorType errorType,
+                      const std::string & log_msg)
+{
+    switch(errorType)
+    {
+        case XML::Parser::VALIDATION_ERROR:
+            LogWarning("validating error: " << log_msg);
+            break;
+        case XML::Parser::PARSE_WARNING:
+            LogWarning("parsing warning: " << log_msg);
+            break;
+        case XML::Parser::PARSE_ERROR:
+            LogWarning("parsing error: " << log_msg);
+            break;
+    }
+}
+
+int SWKeyFile::Validate(const std::string &XSD_file)
+{
+    return m_parser.Validate(XSD_file);
+}
+
+int SWKeyFile::Parse()
+{
+    int ec = m_parser.Parse();
+    if(!m_header || !m_header->isCorrectVersion()) {
+        LogError("bypassing XML file: " << m_filename << " - wrong file version!");
+        ec = XML::Parser::ERROR_INVALID_VERSION;
+    }
+    return ec;
+}
+
+
+
+SWKeyFile::RSAKeyHandler::RSAKeyHandler(SWKeyFile & parent)
+  : m_parent(parent)
+{}
+
+void SWKeyFile::RSAKeyHandler::Characters(const std::string &data) {
+    //m_encryptedKey.reserve(m_encryptedKey.size() + data.size());
+    //m_encryptedKey.insert(m_encryptedKey.end(), data.begin(), data.end());
+    std::copy(data.begin(), data.end(), std::back_inserter(m_encryptedKey));
+}
+
+void SWKeyFile::RSAKeyHandler::End() {
+//    std::string trimmed = XML::trimEachLine(std::string(m_encryptedKey.begin(), m_encryptedKey.end()));
+
+    Base64Decoder base64;
+    base64.reset();
+    base64.append(XML::removeWhiteChars(m_encryptedKey));
+    base64.finalize();
+    m_encryptedKey = base64.get();
+};
+
+Crypto::GObjShPtr SWKeyFile::RSAKeyHandler::getPrivKey() {
+    return std::make_shared<Crypto::SW::AKey>(m_encryptedKey, DataType::KEY_RSA_PRIVATE);
+}
+
+SWKeyFile::HeaderHandler::HeaderHandler(SWKeyFile & parent)
+    : m_version(-1), m_parent(parent) {}
+void SWKeyFile::HeaderHandler::Start(const XML::Parser::Attributes & attr)
+{
+    // get key type
+    if(attr.find(XML_ATTR_VERSION) != attr.end())
+    {
+        m_version = atoi(attr.at(XML_ATTR_VERSION).c_str());
+
+        if(isCorrectVersion())
+            m_parent.registerElementListeners();
+    }
+}
+bool SWKeyFile::HeaderHandler::isCorrectVersion() const {
+    return m_version == XML_SW_KEY_CURRENT_VERSION;
+}
+
+}
+}
diff --git a/src/manager/initial-values/SWKeyFile.h b/src/manager/initial-values/SWKeyFile.h
new file mode 100644 (file)
index 0000000..887c0a9
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ *
+ * @file        SWKeyFile.h
+ * @author      Maciej Karpiuk (m.karpiuk2@samsung.com)
+ * @version     1.0
+ * @brief       SWKeyFile class.
+ */
+
+#ifndef SWKEYFILE_H_
+#define SWKEYFILE_H_
+
+#include <parser.h>
+#include <InitialValueHandler.h>
+#include <ckm-logic.h>
+#include <string>
+#include <algorithm>
+#include <cctype>
+#include <xml-utils.h>
+#include <base64.h>
+#include <generic-backend/gobj.h>
+#include <dpl/log/log.h>
+namespace CKM {
+namespace InitialValues {
+
+
+class SWKeyFile
+{
+public:
+    explicit SWKeyFile(const std::string &XML_filename);
+
+    int Validate(const std::string &XSD_file);
+    int Parse();
+
+    Crypto::GObjShPtr getPrivKey() {
+        return m_deviceKey;
+    }
+
+private:
+    class HeaderHandler : public XML::Parser::ElementHandler
+    {
+    public:
+        explicit HeaderHandler(SWKeyFile & parent);
+        virtual void Start(const XML::Parser::Attributes & attr);
+        virtual void Characters(const std::string &) {};
+        virtual void End() {};
+
+        bool isCorrectVersion() const;
+
+    private:
+        int m_version;
+        SWKeyFile & m_parent;
+    };
+
+    class RSAKeyHandler : public XML::Parser::ElementHandler
+    {
+    public:
+        explicit RSAKeyHandler(SWKeyFile & parent);
+        virtual void Start(const XML::Parser::Attributes &) {};
+        virtual void Characters(const std::string &data);
+        virtual void End();
+
+        Crypto::GObjShPtr getPrivKey();
+    private:
+        CKM::RawBuffer m_encryptedKey;
+        SWKeyFile & m_parent;
+    };
+
+    std::string m_filename;
+    XML::Parser m_parser;
+    typedef std::shared_ptr<HeaderHandler> HeaderHandlerPtr;
+    typedef std::shared_ptr<RSAKeyHandler> RSAKeyHandlerPtr;
+    HeaderHandlerPtr m_header;
+    RSAKeyHandlerPtr m_RSAKeyHandler;
+    Crypto::GObjShPtr m_deviceKey;
+
+    void registerElementListeners();
+    static void Error(const XML::Parser::ErrorType errorType,
+                      const std::string & logMsg);
+
+};
+
+}
+}
+#endif /* SWKEYFILE_H_ */
index 8b1abdb..0553c01 100644 (file)
@@ -28,7 +28,7 @@
 namespace
 {
 const char * const WHITESPACE       = " \n\r\t\v";
-const char * const LINE_WHITESPACE  = " \t";
+const char * const LINE_WHITESPACE  = " \r\t\v";
 
 std::string trim_left(const std::string& s, const char *whitespaces)
 {
@@ -46,27 +46,51 @@ std::string trim(const std::string& s, const char *whitespaces)
 {
     return trim_right(trim_left(s, whitespaces), whitespaces);
 }
+
 }
 
 namespace CKM {
 namespace XML {
-std::string trim(const std::string& s)
+
+template <typename T>
+T removeChars(const T& input, const char *what)
 {
-    return ::trim(s, WHITESPACE);
+    T out(input);
+    auto endit = std::remove_if(out.begin(), out.end(),
+        [what](char c)
+        {
+            for (const char *ptr = what; *ptr; ++ptr)
+                if (*ptr == c)
+                    return true;
+            return false;
+        });
+
+    out.erase(endit, out.end());
+    return out;
 }
 
-std::string trimEachLine(const std::string& s)
-{
-    std::istringstream stream(s);
-    size_t line_cnt = 0;
-    std::string line, output;
-    while(std::getline(stream, line)) {
-        if(line_cnt>0)
-            output += "\n";
-        output += ::trim(line, LINE_WHITESPACE);
-        line_cnt ++;
-    }
-    return output;
+RawBuffer removeWhiteChars(const RawBuffer &buffer) {
+    return removeChars(buffer, WHITESPACE);
 }
+
+std::string trimEachLine(const std::string& input) {
+    std::stringstream ss(input);
+    std::stringstream output;
+    std::string line;
+
+    while(std::getline(ss, line, '\n')) {
+        auto afterTrim = ::trim(line, LINE_WHITESPACE);
+        if (!afterTrim.empty())
+            output << afterTrim << std::endl;
+    }
+
+    return output.str();
 }
+
+std::string trim(const std::string &s) {
+    return removeChars(s, WHITESPACE);
 }
+
+} // namespace XML
+} // namespace CKM
+
index c385598..8ef94fd 100644 (file)
 #define XML_UTILS_H_
 
 #include <string>
+#include <ckm/ckm-raw-buffer.h>
 namespace CKM {
 namespace XML
 {
 
+RawBuffer removeWhiteChars(const RawBuffer &buffer);
 std::string trim(const std::string& s);
 std::string trimEachLine(const std::string &s);
 
index c040cad..9513b80 100644 (file)
@@ -33,6 +33,7 @@ SET(CKM_DB_TOOL_SOURCES
     ${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/ckm_db_tool.cpp
     ${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/db-crypto-ext.cpp
     ${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/ckm-logic-ext.cpp
+    ${KEY_MANAGER_PATH}/initial-values/SWKeyFile.cpp
 
     ${KEY_MANAGER_PATH}/main/cynara.cpp
     ${KEY_MANAGER_PATH}/main/generic-socket-manager.cpp