Add KONAI SE plugin 43/204243/5 accepted/tizen/unified/20190426.110502 submit/tizen/20190425.235759
authorDongsun Lee <ds73.lee@samsung.com>
Mon, 22 Apr 2019 08:34:53 +0000 (17:34 +0900)
committerDongsun Lee <ds73.lee@samsung.com>
Tue, 23 Apr 2019 23:37:29 +0000 (08:37 +0900)
Change-Id: I1fb423ae44f5df1dad3bf3fadfd7e8e6fd308875
Signed-off-by: Dongsun Lee <ds73.lee@samsung.com>
dcm-daemon/CMakeLists.txt
dcm-daemon/konaise-backend/CMakeLists.txt [new file with mode: 0644]
dcm-daemon/konaise-backend/konaise.h [new file with mode: 0644]
dcm-daemon/konaise-backend/ksebackend.cpp [new file with mode: 0644]
dcm-daemon/konaise-backend/ksebackend.h [new file with mode: 0644]
dcm-daemon/konaise-backend/ksebackendcontext.cpp [new file with mode: 0644]
dcm-daemon/konaise-backend/ksebackendcontext.h [new file with mode: 0644]
packaging/device-certificate-manager.spec
tools/CMakeLists.txt
tools/konaise_tool.cpp [new file with mode: 0644]

index 2d8a157..b1089c2 100644 (file)
@@ -50,6 +50,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
 
 add_subdirectory(dummy-backend)
 add_subdirectory(see-backend)
+add_subdirectory(konaise-backend)
 
 IF(ENABLE_DUMMY_BACKEND)
        SET(DUMMY_BACKEND_OBJECTS $<TARGET_OBJECTS:dummy_backend_objects>)
@@ -57,6 +58,7 @@ IF(ENABLE_DUMMY_BACKEND)
 ENDIF(ENABLE_DUMMY_BACKEND)
 
 SET(SEE_BACKEND_OBJECTS $<TARGET_OBJECTS:see-backend>)
+SET(KSE_BACKEND_OBJECTS $<TARGET_OBJECTS:kse-backend>)
 
 ###### Main executable #######
 
@@ -75,20 +77,21 @@ add_executable(device-certificate-managerd
        ${PROTO_HDRS}
        ${DUMMY_BACKEND_OBJECTS}
        ${SEE_BACKEND_OBJECTS}
+       ${KSE_BACKEND_OBJECTS}
        )
-       
+
 add_dependencies(device-certificate-managerd protobuf_generated)
 
 ApplyCxx11Standard(device-certificate-managerd)
 
 ###### Framework linking #######
 
-target_link_libraries(device-certificate-managerd 
+target_link_libraries(device-certificate-managerd
        ${Boost_LOG_LIBRARY}
        ${Boost_THREAD_LIBRARY}
        ${Boost_FILESYSTEM_LIBRARY}
        ${Boost_PROGRAM_OPTIONS_LIBRARY}
-       ${Boost_SYSTEM_LIBRARY} 
+       ${Boost_SYSTEM_LIBRARY}
        ${CMAKE_THREAD_LIBS_INIT}
        ${MBEDTLS_LIB}
        ${MBEDCRYPTO_LIB}
@@ -102,7 +105,7 @@ ENDIF(DLOG_FOUND)
 
 IF(ENABLE_SYSTEMD_SUPPORT)
        target_link_libraries(device-certificate-managerd ${SYSTEMD_LIBRARIES})
-ENDIF(ENABLE_SYSTEMD_SUPPORT)  
+ENDIF(ENABLE_SYSTEMD_SUPPORT)
 
 IF(CYNARA_FOUND)
        target_link_libraries(device-certificate-managerd ${CYNARA_LIBRARIES})
@@ -110,5 +113,5 @@ ENDIF(CYNARA_FOUND)
 
 ###### Installation #######
 
-install(TARGETS device-certificate-managerd 
+install(TARGETS device-certificate-managerd
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/dcm-daemon/konaise-backend/CMakeLists.txt b/dcm-daemon/konaise-backend/CMakeLists.txt
new file mode 100644 (file)
index 0000000..43ff818
--- /dev/null
@@ -0,0 +1,5 @@
+add_library(kse-backend
+       OBJECT
+       ksebackend.cpp
+       ksebackendcontext.cpp)
+add_dependencies(kse-backend protobuf_generated)
diff --git a/dcm-daemon/konaise-backend/konaise.h b/dcm-daemon/konaise-backend/konaise.h
new file mode 100644 (file)
index 0000000..1b3f908
--- /dev/null
@@ -0,0 +1,65 @@
+/******************************************************************
+ *
+ * Copyright 2019 Samsung Electronics 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.
+ *
+ ******************************************************************/
+
+#ifdef USE_KONAISE_HEADERS
+#include <konaise.h>
+#else
+
+#ifndef _KONAISE_SECURITY_H_
+#define _KONAISE_SECURITY_H_
+
+typedef struct _hal_init_param {
+       uint32_t i2c_port;
+       uint32_t gpio;
+} hal_init_param;
+
+
+typedef struct _hal_data {
+       void *data;
+       uint32_t data_len;
+       void *priv;
+} hal_data;
+
+typedef enum {
+       HAL_HASH_MD5,
+       HAL_HASH_SHA1,
+       HAL_HASH_SHA224,
+       HAL_HASH_SHA256,
+       HAL_HASH_SHA384,
+       HAL_HASH_SHA512,
+       HAL_HASH_UNKNOWN,
+} hal_hash_type;
+
+typedef enum {
+       HAL_ECDSA_BRAINPOOL_P256R1,
+       HAL_ECDSA_BRAINPOOL_P384R1,
+       HAL_ECDSA_BRAINPOOL_P512R1,
+       HAL_ECDSA_SEC_P256R1,
+       HAL_ECDSA_SEC_P384R1,
+       HAL_ECDSA_SEC_P512R1,
+} hal_ecdsa_curve;
+
+typedef struct _hal_ecdsa_mode {
+       hal_ecdsa_curve curve;
+       hal_hash_type hash_t;
+} hal_ecdsa_mode;
+
+
+#endif
+
+#endif
diff --git a/dcm-daemon/konaise-backend/ksebackend.cpp b/dcm-daemon/konaise-backend/ksebackend.cpp
new file mode 100644 (file)
index 0000000..98f7168
--- /dev/null
@@ -0,0 +1,106 @@
+/******************************************************************
+ *
+ * Copyright 2019 Samsung Electronics All Rights Reserved.
+ *
+ * Author: Dongsun Lee <ds73.lee@samsung.com>
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+#include "ksebackend.h"
+#include "ksebackendcontext.h"
+#include "logging.h"
+#include <mutex>
+
+#include "konaise.h"
+
+#define KSE_LIB_NAME "libkonaise.so"
+
+crypto_backend_registration<kse_backend> kse_backend::kse_crypto_backend_registration;
+
+kse_backend::kse_backend() :
+       fKseInitOK(false),
+       fDllResolver(std::string(KSE_LIB_NAME))
+{
+       BOOST_LOG_FUNCTION();
+       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Constructed KSE backend";
+}
+
+kse_backend::~kse_backend() {
+       BOOST_LOG_FUNCTION();
+       if(fKseInitOK) {
+               try {
+                       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Deinitializing KSE backend";
+                       fDllResolver.invoke<void>(nullptr, "hal_deinit");
+                       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Deinitialized KSE backend";
+               } catch(...) {
+                       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Exception caught when deinitializing KSE backend";
+               }
+       }
+}
+
+void kse_backend::initialize_kse() {
+       if(fKseInitOK)
+               return;
+
+       BOOST_LOG_FUNCTION();
+       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Initializing KSE backend";
+
+       std::unique_lock<std::mutex> locker(fKSEMutex);
+
+       try {
+               hal_init_param init_parm = {};
+               int error = fDllResolver.invoke<int>(nullptr, "hal_init", &init_parm);
+
+               if(error != 0) {
+                       BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "KSE framework init failure: " << error;
+                       fKseInitOK = false;
+               } else {
+                       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "KSE framework initialized";
+                       fKseInitOK = true;
+               }
+       } catch(...) {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "Caught exception when initializing KSE backend";
+               fKseInitOK = false;
+       }
+}
+
+std::shared_ptr<abstract_crypto_backend_context> kse_backend::create_client_context(
+               const std::string& serviceName,
+               const std::string& usage,
+               const std::string& key_type)
+{
+       BOOST_LOG_FUNCTION();
+       initialize_kse();
+
+       if(!fKseInitOK)
+               throw std::runtime_error("KSE not initialized");
+
+       return std::make_shared<kse_backend_context>(std::static_pointer_cast<kse_backend>(shared_from_this()), key_type);
+}
+
+float kse_backend::will_handle_service(const std::string&,
+                       const std::string&)
+{
+       BOOST_LOG_FUNCTION();
+       if(!fDllResolver.ensure_loaded())
+               return -1.0f;
+
+       initialize_kse();
+
+       if(!fKseInitOK)
+               return -1.0f;
+
+       return 1.0f;
+}
diff --git a/dcm-daemon/konaise-backend/ksebackend.h b/dcm-daemon/konaise-backend/ksebackend.h
new file mode 100644 (file)
index 0000000..484897f
--- /dev/null
@@ -0,0 +1,59 @@
+/******************************************************************
+ *
+ * Copyright 2019 Samsung Electronics All Rights Reserved.
+ *
+ * Author: Dongsun Lee <ds73.lee@samsung.com>
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+
+#ifndef DCM_DAEMON_KSE_BACKEND_KSEBACKEND_H_
+#define DCM_DAEMON_KSE_BACKEND_KSEBACKEND_H_
+
+#include "abstractcryptobackend.h"
+#include "cryptobackendroster.h"
+#include <dllresolver.h>
+#include <mutex>
+
+class kse_backend: public asbtract_crypto_backend
+{
+public:
+       kse_backend();
+       virtual ~kse_backend();
+
+       virtual std::shared_ptr<abstract_crypto_backend_context> create_client_context(
+                       const std::string& serviceName,
+                       const std::string& usage,
+                       const std::string& key_type) override;
+
+       virtual float will_handle_service(const std::string& serviceName,
+                               const std::string& usage);
+
+       inline dll_resolver& get_dll_resolver() {
+               return fDllResolver;
+       }
+
+       static crypto_backend_registration<kse_backend> kse_crypto_backend_registration;
+
+private:
+       void initialize_kse();
+
+private:
+       bool                            fKseInitOK = false;
+       std::mutex                      fKSEMutex;
+       dll_resolver            fDllResolver;
+};
+
+#endif /* DCM_DAEMON_KSE_BACKEND_KSEBACKEND_H_ */
diff --git a/dcm-daemon/konaise-backend/ksebackendcontext.cpp b/dcm-daemon/konaise-backend/ksebackendcontext.cpp
new file mode 100644 (file)
index 0000000..f931f1e
--- /dev/null
@@ -0,0 +1,217 @@
+/******************************************************************
+ *
+ * Copyright 2019 Samsung Electronics All Rights Reserved.
+ *
+ * Author: Dongsun Lee <ds73.lee@samsung.com>
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+#include "ksebackendcontext.h"
+#include "logging.h"
+#include "konaise.h"
+#include "mbedtls_wrapper.h"
+#include "cert_utils.h"
+
+#include <mbedtls/pk.h>
+
+#include <mbedtls/asn1write.h>
+#include <boost/algorithm/hex.hpp>
+
+#define PRIVATE_KEY_INDEX 1
+#define SUBCA_CERT_INDEX 2
+#define LEAF_CERT_INDEX 3
+
+static int kse_get_certificate_key = 0;
+static int kse_get_ecdsa_signature_key = 1;
+
+kse_backend_context::kse_backend_context(std::shared_ptr<kse_backend> backend, const std::string& keyType) :
+       fBackendPtr(backend)
+{
+       BOOST_LOG_FUNCTION();
+       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug)
+                                       << "Created new KSE with key " << keyType;
+
+       if(keyType.empty() || keyType == "ECDSA") {
+               fKeyType = CRYPTO_KEY_TYPE_ECDSA;
+       } else {
+               throw std::invalid_argument("Unsupported key type");
+       }
+
+       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug)
+                                       << "Created new KSE context at " << this;
+}
+
+kse_backend_context::~kse_backend_context()
+{
+       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug)
+                                       << "Deleting KSE context " << this;
+}
+
+int kse_backend_context::get_certificate(unsigned int index, std::string& outcert)
+{
+       hal_data cert = {0};
+       const char *method_name = "hal_get_certificate";
+
+       auto backend = fBackendPtr.lock();
+       if(!backend) {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error)
+                                       << "Unable to acquire backend pointer";
+               return -EINVAL;
+       }
+
+       auto& resolver(backend->get_dll_resolver());
+       int error = resolver.invoke<int, unsigned int, hal_data *>(&kse_get_certificate_key,
+                                       method_name, index, &cert);
+       if(error != 0) {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error)
+                                       << "Failed to get certificate. error=" << error;
+               return -EINVAL;
+       }
+
+#ifdef ENABLE_DEBUG_LODDING
+       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug)
+                                       << "KSE: Got certificate with " << cert.data_len
+                                       << " bytes and index " << index;
+#endif
+       try {
+               outcert.assign((const char *)cert.data, cert.data_len);
+       } catch(...) {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error)
+                                       << "KSE: Got exception when assigning data";
+               free(cert.data);
+               throw;
+       }
+       free(cert.data);
+
+       return 0;
+}
+
+int kse_backend_context::request_certificate_chain(std::string& mutable_chain)
+{
+       BOOST_LOG_FUNCTION();
+#ifdef ENABLE_DEBUG_LODDING
+       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug)
+                                       << "KSE : Request certificate chain";
+#endif
+
+       std::string leaf_cert;
+       std::string subca_cert;
+
+       int error = 0;
+
+       if(error = get_certificate(LEAF_CERT_INDEX, leaf_cert))
+               return error;
+       if(error = get_certificate(SUBCA_CERT_INDEX, subca_cert))
+               return error;
+
+       x509_crt_rewriter cert_writer;
+       if(error = cert_writer.parse(reinterpret_cast<const unsigned char *>(leaf_cert.c_str()),
+                       leaf_cert.length()+1)) {
+               return error;
+       }
+       if(error = cert_writer.parse(reinterpret_cast<const unsigned char *>(subca_cert.c_str()),
+                       subca_cert.length()+1)) {
+               return error;
+       }
+       cert_writer.sort_chain();
+
+       mutable_chain.append(cert_writer.emit_pem());
+
+#ifdef ENABLE_DEBUG_LODDING
+       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug)
+                                       << "Requested certificate in " << this;
+#endif
+
+       return 0;
+}
+
+int kse_backend_context::sign_crypto_data(MessageDigestType digestType, const std::string& dataToSign,
+               std::string& digestResult)
+{
+       BOOST_LOG_FUNCTION();
+       hal_data hashed_data = { };
+       hal_data signed_data = { };
+
+       hashed_data.data = (void *)dataToSign.c_str();
+       hashed_data.data_len = dataToSign.size();
+
+       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "KSE: Sign " << hashed_data.data_len << " bytes";
+
+       auto backend = fBackendPtr.lock();
+
+       if(!backend) {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "Unable to acquire backend pointer";
+               return -EINVAL;
+       }
+
+       auto& resolver(backend->get_dll_resolver());
+
+#ifdef ENABLE_DEBUG_LODDING
+       try {
+               std::string hex;
+               boost::algorithm::hex((const unsigned char *)hashed_data.data,
+                               (const unsigned char *)hashed_data.data + hashed_data.data_len,
+                               std::back_inserter(hex));
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Hashed data is " << hex;
+       } catch(...) {
+       }
+#endif
+
+       const char *method_name = "hal_ecdsa_sign_md";
+       hal_ecdsa_mode mode = {HAL_ECDSA_SEC_P256R1, HAL_HASH_UNKNOWN};
+
+       int error = resolver.invoke<int, hal_data *, unsigned int, hal_ecdsa_mode *, hal_data *>(
+               &kse_get_ecdsa_signature_key, method_name,
+               &hashed_data, PRIVATE_KEY_INDEX, &mode, &signed_data);
+
+       if(error != 0) {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) <<
+                               "Unable to generate ECDSA signature in " <<
+                               this <<
+                               " (" << error << ") : " <<
+                               mbedtls_error_to_string(error);
+
+               return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+       }
+
+#ifdef ENABLE_DEBUG_LODDING
+       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Signature length is " << signed_data.data_len;
+
+       try {
+               std::string hex;
+               boost::algorithm::hex((const unsigned char *)signed_data.data,
+                               (const unsigned char *)signed_data.data + signed_data.data_len,
+                               std::back_inserter(hex));
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Hex signature is " << hex;
+       } catch(...) {
+       }
+       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "KSE: Generated ECDSA signature";
+#endif
+
+       digestResult.assign((const char *)signed_data.data, signed_data.data_len);
+
+       free(signed_data.data);
+       return 0;
+}
+
+CryptoKeyType kse_backend_context::key_type()
+{
+       return fKeyType;
+}
+
+unsigned int kse_backend_context::key_length()
+{
+       return 256;
+}
diff --git a/dcm-daemon/konaise-backend/ksebackendcontext.h b/dcm-daemon/konaise-backend/ksebackendcontext.h
new file mode 100644 (file)
index 0000000..5253119
--- /dev/null
@@ -0,0 +1,49 @@
+/******************************************************************
+ *
+ * Copyright 2019 Samsung Electronics All Rights Reserved.
+ *
+ * Author: Dongsun Lee <ds73.lee@samsung.com>
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+#ifndef DCM_DAEMON_KSE_BACKEND_KSEBACKENDCONTEXT_H_
+#define DCM_DAEMON_KSE_BACKEND_KSEBACKENDCONTEXT_H_
+
+#include "abstractcryptobackendcontext.h"
+#include "ksebackend.h"
+
+class kse_backend_context final : public abstract_crypto_backend_context {
+public:
+       kse_backend_context(std::shared_ptr<kse_backend> backend, const std::string& keyType);
+       virtual ~kse_backend_context();
+
+       virtual int request_certificate_chain(std::string& mutable_chain) override;
+
+       virtual int sign_crypto_data(MessageDigestType digestType, const std::string& dataToSign,
+                       std::string& digestResult) override;
+
+       virtual CryptoKeyType key_type() override;
+
+       virtual unsigned int key_length() override;
+
+private:
+       int get_certificate(unsigned int index, std::string& cert);
+
+private:
+       CryptoKeyType                                   fKeyType;
+       std::weak_ptr<kse_backend>              fBackendPtr;
+};
+
+#endif /* DCM_DAEMON_KSE_BACKEND_KSEBACKENDCONTEXT_H_ */
index ef19f83..bf5e107 100644 (file)
@@ -115,3 +115,4 @@ fi
 %{_bindir}/dcm_example_capi
 %{_bindir}/dcm_api_test
 %{_bindir}/dcm_test_cert_rewriter
+%{_bindir}/dcm_konaise_tool
index 064d1a4..bb06898 100644 (file)
@@ -1,3 +1,21 @@
 add_executable(helper_bin2c
        bin2c.c)
-       
\ No newline at end of file
+
+#######################################################################################
+# For SE_KONAI
+ADD_DEFINITIONS(-DBOOST_LOG_DYN_LINK)
+include_directories(${Boost_INCLUDE_DIRS})
+link_directories(${Boost_LIBRARY_DIRS})
+
+include_directories(../dcm-daemon ../dcm-daemon/konaise-backend)
+
+add_executable(dcm_konaise_tool
+       ../dcm-daemon/dllresolver.cpp
+       konaise_tool.cpp)
+target_link_libraries(dcm_konaise_tool
+       ${Boost_LOG_LIBRARY}
+       device-certificate-manager
+       dl)
+install(TARGETS dcm_konaise_tool RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+#######################################################################################
+
diff --git a/tools/konaise_tool.cpp b/tools/konaise_tool.cpp
new file mode 100644 (file)
index 0000000..225dd24
--- /dev/null
@@ -0,0 +1,346 @@
+/******************************************************************
+ *
+ * Copyright 2019 Samsung Electronics All Rights Reserved.
+ *
+ * Author: Dongsun Lee <ds73.lee@samsung.com>
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <dllresolver.h>
+#include "konaise.h"
+
+#define KSE_LIB_NAME "libkonaise.so"
+
+static int kse_cert_get = 0x00;
+static int kse_cert_add = 0x01;
+static int kse_cert_del = 0x02;
+static int kse_key_get  = 0x10;
+static int kse_key_add  = 0x11;
+static int kse_key_del  = 0x12;
+static int kse_ec_sign  = 0x21;
+static int kse_ec_verify= 0x22;
+
+
+typedef enum {
+    /*  AES */
+    HAL_KEY_AES_128,// 128 bits aes algorithm
+    HAL_KEY_AES_192, // 192 bits aes algorithm
+    HAL_KEY_AES_256, // 256 bits aes algorithm
+    /*  RSA */
+    HAL_KEY_RSA_1024, // 1024 bits rsa algorithm
+    HAL_KEY_RSA_2048, // 2048 bits rsa algorithm
+    HAL_KEY_RSA_3072, // 3072 bits rsa algorithm
+    HAL_KEY_RSA_4096,
+    /*  ECC: it doesn't support whole algorithm that mbedTLS support. it's have to be added*/
+    HAL_KEY_ECC_BRAINPOOL_P256R1, // ecc brainpool curve for p256r1
+    HAL_KEY_ECC_BRAINPOOL_P384R1, // ecc brainpool curve for p384r1
+    HAL_KEY_ECC_BRAINPOOL_P512R1, // ecc brainpool curve for p512r1
+    HAL_KEY_ECC_SEC_P256R1, // nist curve for p256r1
+    HAL_KEY_ECC_SEC_P384R1, // nist curve for p384r1
+    HAL_KEY_ECC_SEC_P512R1, // nist curve for p512r1
+    /*  Hmac */
+    HAL_KEY_HMAC_MD5, // hmac with md5
+    HAL_KEY_HMAC_SHA1, // hmac with sha1
+    HAL_KEY_HMAC_SHA224, // hmac with sha224
+    HAL_KEY_HMAC_SHA256, // hmac with sha256
+    HAL_KEY_HMAC_SHA384, // hmac with sha384
+    HAL_KEY_HMAC_SHA512, // hmac with sha512
+    /* DH */
+    HAL_KEY_DH_1024,
+    HAL_KEY_DH_2048,
+    HAL_KEY_UNKNOWN,
+} hal_key_type;
+
+
+class SEKonai {
+public:
+       SEKonai(const std::string& libraryName) :
+               fDllResolver(libraryName)
+       {
+               loaded = fDllResolver.ensure_loaded();
+       }
+
+       ~SEKonai(){
+       }
+
+       bool is_loaded() {
+               return loaded;
+       }
+
+       void get_cert(int idx, const std::string& fileName){
+               hal_data cert = {0};
+
+               const char *method_name = "hal_get_certificate";
+               int error = fDllResolver.invoke<int, unsigned int, hal_data *>(&kse_cert_get,
+                                                               method_name, idx, &cert);
+               if(error == 0) {
+                       write_file(fileName, cert);
+                       std::cout << "SUCCEEDED in " << method_name << "." << std::endl;
+               } else {
+                       std::cout << "FAILED in " << method_name << ". ERROR=" << error << std::endl;
+               }
+       }
+
+       void get_key(hal_key_type key_type, int idx, const std::string& fileName) {
+               hal_data data = {0};
+               const char *method_name = "hal_get_key";
+               int error = fDllResolver.invoke<int, hal_key_type, unsigned int, hal_data *>(&kse_key_get,
+                                                               method_name, key_type, idx, &data);
+               if(error == 0) {
+                       write_file(fileName, data);
+                       std::cout << "SUCCEEDED in " << method_name << "." << std::endl;
+               } else {
+                       std::cout << "FAILED in " << method_name << ". ERROR=" << error << std::endl;
+               }
+       }
+
+       void add_cert(const std::string& fileName, int idx) {
+               hal_data *data = read_file(fileName);
+               const char *method_name = "hal_set_certificate";
+               int error = fDllResolver.invoke<int, unsigned int, hal_data *>(&kse_cert_add,
+                                                                       method_name, idx, data);
+               if(error == 0) {
+                       std::cout << "SUCCEEDED in " << method_name << "." << std::endl;
+               } else {
+                       std::cout << "FAILED in " << method_name << ". ERROR=" << error << std::endl;
+               }
+               free_hal_data(data);
+       }
+
+       void add_key(const std::string& fileName, hal_key_type key_type, int idx,
+                               const std::string& privFileName) {
+               hal_data *key = read_file(fileName);
+               hal_data *priKey = {0};
+               if(privFileName.size() != 0)
+                       priKey = read_file(privFileName);
+               const char *method_name = "hal_set_key";
+               int error = fDllResolver.invoke<int, hal_key_type, unsigned int, hal_data *, hal_data *>(
+                                               &kse_key_add, method_name, key_type, idx, key, priKey);
+               if(error == 0) {
+                       std::cout << "SUCCEEDED in " << method_name << "." << std::endl;
+               } else {
+                       std::cout << "FAILED in " << method_name << ". ERROR=" << error << std::endl;
+               }
+               free_hal_data(key);
+               free_hal_data(priKey);
+       }
+
+       void del_cert(int idx) {
+               const char *method_name = "hal_remove_certificate";
+               int error = fDllResolver.invoke<int, unsigned int>(&kse_key_del, method_name, idx);
+               if(error == 0) {
+                       std::cout << "SUCCEEDED in " << method_name << "." << std::endl;
+               } else {
+                       std::cout << "FAILED in " << method_name << ". ERROR=" << error << std::endl;
+               }
+       }
+
+       void del_key(hal_key_type key_type, int idx) {
+               const char *method_name = "hal_remove_key";
+               int error = fDllResolver.invoke<int, hal_key_type, unsigned int>(&kse_key_del, method_name,
+                                                                                                                                                       key_type, idx);
+               if(error == 0) {
+                       std::cout << "SUCCEEDED in " << method_name << "." << std::endl;
+               } else {
+                       std::cout << "FAILED in " << method_name << ". ERROR=" << error << std::endl;
+               }
+       }
+
+       void ec_sec_p256r1_sign(std::string hash_file, int key_idx, std::string sig_file) {
+               hal_data *hashed_data = read_file(hash_file);
+               hal_data signed_data = {0};
+
+               const char *method_name = "hal_ecdsa_sign_md";
+               hal_ecdsa_mode mode = {HAL_ECDSA_SEC_P256R1, HAL_HASH_UNKNOWN};
+               int error = fDllResolver.invoke<int, hal_data *,
+                                               unsigned int, hal_ecdsa_mode *, hal_data *>(
+                                       &kse_ec_sign, method_name,
+                                       hashed_data, key_idx, &mode, &signed_data);
+               if(error == 0) {
+                       write_file(sig_file, signed_data);
+                       std::cout << "SUCCEEDED in " << method_name << "." << std::endl;
+               } else {
+                       std::cout << "FAILED in " << method_name << ". ERROR=" << error << std::endl;
+               }
+               free_hal_data(hashed_data);
+               free(signed_data.data);
+       }
+
+       void ec_sec_p256r1_verify(std::string hash_file, int key_idx, std::string sig_file) {
+               // ec_sign hash_file key_index key_type sigfile(out)
+               hal_data *hashed_data = read_file(hash_file);
+               hal_data *signed_data = read_file(sig_file);
+
+               const char *method_name = "hal_ecdsa_verify_md";
+               hal_ecdsa_mode mode = {HAL_ECDSA_SEC_P256R1, HAL_HASH_UNKNOWN};
+               int error = fDllResolver.invoke<int, hal_ecdsa_mode, hal_data *, hal_data *,
+                                               unsigned int>(
+                                       &kse_ec_verify, method_name,
+                                       mode, hashed_data, signed_data, key_idx);
+               if(error == 0) {
+                       std::cout << "SUCCEEDED in " << method_name << "." << std::endl;
+               } else {
+                       std::cout << "FAILED in " << method_name << ". ERROR=" << error << std::endl;
+               }
+               free_hal_data(hashed_data);
+               free_hal_data(signed_data);
+       }
+
+       hal_key_type get_key_type(const std::string& keyType) {
+               if(keyType.compare("HAL_KEY_AES_128") == 0) return HAL_KEY_AES_128;
+               if(keyType.compare("HAL_KEY_AES_192") == 0) return HAL_KEY_AES_192;
+               if(keyType.compare("HAL_KEY_AES_256") == 0) return HAL_KEY_AES_256;
+               if(keyType.compare("HAL_KEY_RSA_1024") == 0) return HAL_KEY_RSA_1024;
+               if(keyType.compare("HAL_KEY_RSA_2048") == 0) return HAL_KEY_RSA_2048;
+               if(keyType.compare("HAL_KEY_RSA_3072") == 0) return HAL_KEY_RSA_3072;
+               if(keyType.compare("HAL_KEY_RSA_4096") == 0) return HAL_KEY_RSA_4096;
+               if(keyType.compare("HAL_KEY_ECC_BRAINPOOL_P256R1") == 0) return HAL_KEY_ECC_BRAINPOOL_P256R1;
+               if(keyType.compare("HAL_KEY_ECC_BRAINPOOL_P384R1") == 0) return HAL_KEY_ECC_BRAINPOOL_P384R1;
+               if(keyType.compare("HAL_KEY_ECC_BRAINPOOL_P512R1") == 0) return HAL_KEY_ECC_BRAINPOOL_P512R1;
+               if(keyType.compare("HAL_KEY_ECC_SEC_P256R1") == 0) return HAL_KEY_ECC_SEC_P256R1;
+               if(keyType.compare("HAL_KEY_ECC_SEC_P384R1") == 0) return HAL_KEY_ECC_SEC_P384R1;
+               if(keyType.compare("HAL_KEY_ECC_SEC_P512R1") == 0) return HAL_KEY_ECC_SEC_P512R1;
+               if(keyType.compare("HAL_KEY_HMAC_MD5") == 0) return HAL_KEY_HMAC_MD5;
+               if(keyType.compare("HAL_KEY_HMAC_SHA1") == 0) return HAL_KEY_HMAC_SHA1;
+               if(keyType.compare("HAL_KEY_HMAC_SHA224") == 0) return HAL_KEY_HMAC_SHA224;
+               if(keyType.compare("HAL_KEY_HMAC_SHA256") == 0) return HAL_KEY_HMAC_SHA256;
+               if(keyType.compare("HAL_KEY_HMAC_SHA384") == 0) return HAL_KEY_HMAC_SHA384;
+               if(keyType.compare("HAL_KEY_HMAC_SHA512") == 0) return HAL_KEY_HMAC_SHA512;
+               if(keyType.compare("HAL_KEY_DH_1024") == 0) return HAL_KEY_DH_1024;
+               if(keyType.compare("HAL_KEY_DH_2048") == 0) return HAL_KEY_DH_2048;
+               return HAL_KEY_UNKNOWN;
+       }
+
+       std::string get_key_type_str(hal_key_type keyType) {
+               switch(keyType) {
+               case HAL_KEY_AES_128: return std::string("HAL_KEY_AES_128");
+               case HAL_KEY_AES_192: return std::string("HAL_KEY_AES_192");
+               case HAL_KEY_AES_256: return std::string("HAL_KEY_AES_256");
+               case HAL_KEY_RSA_1024: return std::string("HAL_KEY_RSA_1024");
+               case HAL_KEY_RSA_2048: return std::string("HAL_KEY_RSA_2048");
+               case HAL_KEY_RSA_3072: return std::string("HAL_KEY_RSA_3072");
+               case HAL_KEY_RSA_4096: return std::string("HAL_KEY_RSA_4096");
+               case HAL_KEY_ECC_BRAINPOOL_P256R1: return std::string("HAL_KEY_ECC_BRAINPOOL_P256R1");
+               case HAL_KEY_ECC_BRAINPOOL_P384R1: return std::string("HAL_KEY_ECC_BRAINPOOL_P384R1");
+               case HAL_KEY_ECC_BRAINPOOL_P512R1: return std::string("HAL_KEY_ECC_BRAINPOOL_P512R1");
+               case HAL_KEY_ECC_SEC_P256R1: return std::string("HAL_KEY_ECC_SEC_P256R1");
+               case HAL_KEY_ECC_SEC_P384R1: return std::string("HAL_KEY_ECC_SEC_P384R1");
+               case HAL_KEY_ECC_SEC_P512R1: return std::string("HAL_KEY_ECC_SEC_P512R1");
+               case HAL_KEY_HMAC_MD5: return std::string("HAL_KEY_HMAC_MD5");
+               case HAL_KEY_HMAC_SHA1: return std::string("HAL_KEY_HMAC_SHA1");
+               case HAL_KEY_HMAC_SHA224: return std::string("HAL_KEY_HMAC_SHA224");
+               case HAL_KEY_HMAC_SHA256: return std::string("HAL_KEY_HMAC_SHA256");
+               case HAL_KEY_HMAC_SHA384: return std::string("HAL_KEY_HMAC_SHA384");
+               case HAL_KEY_HMAC_SHA512: return std::string("HAL_KEY_HMAC_SHA512");
+               case HAL_KEY_DH_1024: return std::string("HAL_KEY_DH_1024");
+               case HAL_KEY_DH_2048: return std::string("HAL_KEY_DH_2048");
+               default: return std::string("HAL_KEY_UNKNOWN");
+               }
+       }
+
+private:
+       dll_resolver fDllResolver;
+       bool loaded;
+
+       void free_hal_data(hal_data *data) {
+               if(data == NULL)
+                       return;
+               if(data->data != NULL)
+                       free(data->data);
+               free(data);
+       }
+
+       void write_file(const std::string& fileName, hal_data in) {
+               std::fstream outfile;
+               outfile = std::fstream(fileName, std::ios::out | std::ios::binary);
+               outfile.write((char*)in.data, in.data_len);
+               outfile.close();
+       }
+
+       hal_data* read_file(const std::string& fileName) {
+               if(fileName.size() == 0)
+                       return NULL;
+               std::ifstream input(fileName, std::ios::binary);
+               std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(input), {});
+               unsigned char* data = (unsigned char*) malloc(buffer.size());
+               for(int i = 0; i < buffer.size(); i++)
+                       data[i] = buffer[i];
+               hal_data *ret = (hal_data *) malloc(sizeof(hal_data));
+               ret->data = data;
+               ret->data_len = buffer.size();
+               ret->priv = NULL;
+               return ret;
+       }
+};
+
+void print_usage(char *prog_name) {
+       std::cout << prog_name << " command  opt1 opt2 . . . " << std::endl;
+       std::cout << "  example: " << prog_name << " get_cert index outfile" << std::endl;
+       std::cout << "  example: " << prog_name << " add_cert infile index" << std::endl;
+       std::cout << "  example: " << prog_name << " del_cert index" << std::endl;
+       std::cout << "  example: " << prog_name << " get_key key_type index outfile" << std::endl;
+       std::cout << "  example: " << prog_name << " add_key infile key_type index in_privfile"<<std::endl;
+       std::cout << "  example: " << prog_name << " del_key key_type index" << std::endl;
+       std::cout << "  example: " << prog_name << " ec_sec_p256r1_sign hash_file key_idx sigfile(out)" << std::endl;
+       std::cout << "  example: " << prog_name << " ec_sec_p256r1_verify hash_file key_idx sigfile(in)" << std::endl;
+}
+
+int main(int argc, char ** argv)
+{
+       if(argc < 2) {
+               print_usage(argv[0]);
+               return -1;
+       }
+
+       SEKonai se(KSE_LIB_NAME);
+       if(!se.is_loaded()) {
+               std::cout << "LIBRARY WAS NOT LOADED!!" << std::endl;
+               return -1;
+       }
+       std::string cmd(argv[1]);
+
+       if((cmd.compare("get_cert") == 0) && argc > 3) {
+               se.get_cert(std::stoi(argv[2]), std::string(argv[3]));
+       }else if((cmd.compare("add_cert") == 0) && argc > 3) {
+               se.add_cert(std::string(argv[2]), std::stoi(argv[3]));
+       }else if((cmd.compare("del_cert") == 0) && argc > 2) {
+               se.del_cert(std::stoi(argv[2]));
+       }else if((cmd.compare("get_key") == 0) && argc > 4) {
+               se.get_key(se.get_key_type(std::string(argv[2])),
+                               std::stoi(argv[3]), std::string(argv[4]));
+       }else if((cmd.compare("add_key") == 0) && argc >= 5) {
+               char * priv_file = nullptr;
+               if(argc > 5)
+                       priv_file = argv[5];
+               se.add_key(std::string(argv[2]), se.get_key_type(std::string(argv[3])),
+                               std::stoi(argv[4]), std::string(priv_file));
+       }else if((cmd.compare("del_key") == 0) && argc > 3) {
+               se.del_key(se.get_key_type(std::string(argv[2])), std::stoi(argv[3]));
+       }else if((cmd.compare("ec_sec_p256r1_sign") == 0) && argc > 4) {
+               se.ec_sec_p256r1_sign(std::string(argv[2]), std::stoi(argv[3]),
+                               std::string(argv[4]));
+       }else if((cmd.compare("ec_sec_p256r1_verify") == 0) && argc > 4) {
+               se.ec_sec_p256r1_verify(std::string(argv[2]), std::stoi(argv[3]),
+                               std::string(argv[4]));
+       }else {
+               print_usage(argv[0]);
+               return -1;
+       }
+
+       return 0;
+}