Make dcm APIs as public API 83/173783/10
authorDongsun Lee <ds73.lee@samsung.com>
Mon, 26 Mar 2018 02:16:57 +0000 (11:16 +0900)
committerDariusz Michaluk <d.michaluk@samsung.com>
Wed, 25 Apr 2018 13:53:59 +0000 (15:53 +0200)
Change-Id: I12dc1e3961f3842275c6cdcf54c0396bcec35a21
Signed-off-by: Dongsun Lee <ds73.lee@samsung.com>
Signed-off-by: Dariusz Michaluk <d.michaluk@samsung.com>
15 files changed:
CMakeLists.txt
dcm-client/CMakeLists.txt
dcm-client/dcm_client.h
dcm-client/dcm_hw_interface.cpp [deleted file]
dcm-client/dcm_hw_interface.h [deleted file]
dcm-client/dcmclient.cpp
dcm-client/device_certificate_manager.cpp [new file with mode: 0644]
dcm-client/device_certificate_manager.h [new file with mode: 0644]
dcm-client/version_script.lds
dcm-daemon/logging.h
doc/device_certificate_manager_doc.h [new file with mode: 0644]
packaging/device-certificate-manager.spec
tests/CMakeLists.txt
tests/example_capi.c [new file with mode: 0644]
tests/hw_api_test.cpp

index 68f1c4f5223d2e3b7de2a9d2bad7e48b764b0eac..fda93fb84b1349e9c82182b64921b11f139a6aae 100644 (file)
@@ -37,14 +37,14 @@ option(ENABLE_SYSTEMD_SUPPORT "Enable support for systemd" ON)
 
 IF(ENABLE_SYSTEMD_SUPPORT AND NOT SYSTEMD_FOUND)
        message(FATAL_ERROR "systemd support required but systemd not found")
-ENDIF() 
+ENDIF()
 
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/dcm_build_config.h.in
        ${CMAKE_CURRENT_BINARY_DIR}/dcm_build_config.h)
-       
+
 configure_file(packaging/device-certificate-manager-tests.manifest.in
        ${CMAKE_CURRENT_BINARY_DIR}/device-certificate-manager-tests.manifest)
-       
+
 include_directories(${CMAKE_CURRENT_BINARY_DIR})
 include_directories(shared)
 
index b318c0081a2213f0f76744b0d405f1c4091af521..fb012c1c577b0da80523b8254de546d6893e88f8 100644 (file)
@@ -34,13 +34,13 @@ PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS dcm_support.proto)
 add_library(device-certificate-manager
        SHARED
        dcmclient.cpp
-       dcm_hw_interface.cpp
+       device_certificate_manager.cpp
        ../shared/protobuf_asio.cpp
        ${PROTO_SRCS}
        ${PROTO_HDRS})
 
 ###### Export header generation ######
-       
+
 GENERATE_EXPORT_HEADER(device-certificate-manager
        BASE_NAME DEVICE_CERTIFICATE_MANAGER
        PREFIX_NAME API_
@@ -50,9 +50,9 @@ GENERATE_EXPORT_HEADER(device-certificate-manager
 
 ApplyCxx11Standard(device-certificate-manager)
 
-target_link_libraries(device-certificate-manager 
-       ${Boost_SYSTEM_LIBRARY} 
-       ${CMAKE_THREAD_LIBS_INIT} 
+target_link_libraries(device-certificate-manager
+       ${Boost_SYSTEM_LIBRARY}
+       ${CMAKE_THREAD_LIBS_INIT}
        ${PROTOBUF_LIBRARIES}
        ${MBEDTLS_LIB}
        ${MBEDCRYPTO_LIB})
@@ -66,19 +66,19 @@ ENDIF()
 ###### Properties of library ######
 
 set_property(TARGET device-certificate-manager PROPERTY DEFINE_SYMBOL DEVICE_CERTIFICATE_MANAGER_EXPORT)
-set_property(TARGET device-certificate-manager PROPERTY VISIBILITY_INLINES_HIDDEN TRUE) 
+set_property(TARGET device-certificate-manager PROPERTY VISIBILITY_INLINES_HIDDEN TRUE)
 set_property(TARGET device-certificate-manager PROPERTY VERSION 1.0)
 set_property(TARGET device-certificate-manager PROPERTY C_VISIBILITY_PRESET hidden)
 set_property(TARGET device-certificate-manager PROPERTY CXX_VISIBILITY_PRESET hidden)
 
 ###### Installation ######
 
-install(TARGETS device-certificate-manager 
+install(TARGETS device-certificate-manager
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
 
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/device_certificate_manager_export.h
        dcm_client.h
-       dcm_hw_interface.h
+       device_certificate_manager.h
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/device-certificate-manager)
 
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/device-certificate-manager.pc
index 1531f81244ec8f274122ddd2a3cb999abfcea022..bc544e46559e36f34f82317244a6946063778b41 100644 (file)
@@ -71,8 +71,6 @@ public:
 
        /*!
         * Sign data with context certificate
-        *
-        * This function returns error codes from the mbedtls error value space
         */
        virtual int sign_data(mbedtls_md_type_t digestType,
                                const void * hash_data, size_t hash_size,
diff --git a/dcm-client/dcm_hw_interface.cpp b/dcm-client/dcm_hw_interface.cpp
deleted file mode 100644 (file)
index 332141a..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-/******************************************************************
- *
- * Copyright 2017 Samsung Electronics All Rights Reserved.
- *
- * Author: Jaroslaw Pelczar <j.pelczar@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 "dcm_hw_interface.h"
-#include "dcm_client.h"
-#include <mbedtls/pk_internal.h>
-#include <mbedtls/rsa.h>
-#include <mbedtls/pk.h>
-#include <vector>
-#include <cstring>
-#include <map>
-#include <mutex>
-
-#ifdef USE_DLOG_LOGGING
-#define LOG_TAG                "dcm-client"
-#include <dlog.h>
-#endif
-
-struct dcm_key_context_internal {
-       std::shared_ptr<dcm_client_connection> connection;
-       std::vector<uint8_t> cached_cert_chain;
-       mbedtls_pk_info_t ec_info;
-};
-
-static std::map<const void *, std::weak_ptr<dcm_client_connection>> sEDCSAContexts;
-static std::mutex sEDCSAContextsMutex;
-
-void* DCM_HWGetKeyContext(const char* service, const char* usage, const char* keytype) {
-       try {
-               std::unique_ptr<dcm_key_context_internal> context(new dcm_key_context_internal());
-
-               std::string service_string(service ? service : "");
-               std::string usage_string(usage ? usage : "");
-               std::string keytype_string(keytype ? keytype : "");
-
-               context->connection = dcm_client_connection::create();
-
-               if(!context->connection->create_context(service_string,
-                               usage_string,
-                               keytype_string))
-               {
-#ifdef USE_DLOG_LOGGING
-                       LOGE("Can't create connection context");
-#endif
-                       return nullptr;
-               }
-
-               return context.release();
-       } catch(std::exception& ex) {
-#ifdef USE_DLOG_LOGGING
-               LOGE("Context creation failure: %s", ex.what());
-#endif
-               return nullptr;
-       } catch(...) {
-#ifdef USE_DLOG_LOGGING
-               LOGE("Context creation failure");
-#endif
-               return nullptr;
-       }
-}
-
-int DCM_HWFreeKeyContext(void* keyContext)
-{
-       if(!keyContext) {
-               return HWIF_ERR_INVALID_PARAM;
-       }
-
-       delete reinterpret_cast<dcm_key_context_internal *>(keyContext);
-
-       return HWIF_SUCCESS;
-}
-
-int DCM_HWGetOwnCertificateChain(const void* keyContext,
-                    unsigned char** cert_chain, size_t* cert_chain_len)
-{
-       dcm_key_context_internal * context = reinterpret_cast<dcm_key_context_internal *>(
-               const_cast<void *>(keyContext));
-
-       if(!keyContext || !cert_chain || !cert_chain_len) {
-               return HWIF_ERR_INVALID_PARAM;
-       }
-
-       if(!context->cached_cert_chain.empty()) {
-               *cert_chain = &context->cached_cert_chain[0];
-               *cert_chain_len = context->cached_cert_chain.size();
-               return HWIF_SUCCESS;
-       }
-
-       int result;
-
-       if((result = context->connection->get_certificate_chain(context->cached_cert_chain)) == 0) {
-               *cert_chain = &context->cached_cert_chain[0];
-               *cert_chain_len = context->cached_cert_chain.size();
-       }
-
-       return result;
-}
-
-static int pk_rsa_alt_decrypt_func( void *ctx, int mode, size_t *olen,
-                    const unsigned char *input, unsigned char *output,
-                    size_t output_max_len )
-{
-#ifdef USE_DLOG_LOGGING
-       LOGE("Can't use this API to decrypt RSA data");
-#endif
-
-       return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-}
-
-static int pk_rsa_alt_sign_func( void *ctx,
-                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
-                    int mode, mbedtls_md_type_t md_alg, unsigned int hashlen,
-                    const unsigned char *hash, unsigned char *sig )
-{
-       if(!ctx) {
-               return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-       }
-
-       if(mode != MBEDTLS_RSA_PRIVATE) {
-#ifdef USE_DLOG_LOGGING
-               LOGE("Signing mode must be RSA_PRIVATE");
-#endif
-               return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-       }
-
-       dcm_key_context_internal * context = reinterpret_cast<dcm_key_context_internal *>(ctx);
-
-       try {
-               std::vector<uint8_t> digest;
-
-               int error = context->connection->sign_data(md_alg,
-                               hash,
-                               hashlen,
-                               digest);
-
-               if(error == 0) {
-                       if(digest.size() > MBEDTLS_MPI_MAX_SIZE) {
-                               return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-                       }
-
-                       memcpy(sig, &digest[0], digest.size());
-               }
-
-               return error;
-       } catch(...) {
-               return MBEDTLS_ERR_PK_ALLOC_FAILED;
-       }
-}
-
-
-static size_t pk_rsa_alt_key_len_func( void *ctx )
-{
-       if(!ctx) {
-               return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-       }
-
-       dcm_key_context_internal * context = reinterpret_cast<dcm_key_context_internal *>(ctx);
-
-       return (context->connection->key_length() + 7) / 8;
-}
-
-static int SetupRSAContext(mbedtls_pk_context* ctx, void* key_context) {
-       return mbedtls_pk_setup_rsa_alt(ctx,
-                       key_context,
-                       pk_rsa_alt_decrypt_func,
-                       pk_rsa_alt_sign_func,
-                       pk_rsa_alt_key_len_func) ? HWIF_ERROR : HWIF_SUCCESS;
-}
-
-static int ecdsa_sign_alt( void *ctx, mbedtls_md_type_t md_alg,
-                   const unsigned char *hash, size_t hash_len,
-                   unsigned char *sig, size_t *sig_len,
-                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
-{
-       if(!ctx) {
-               return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-       }
-
-       std::unique_lock<std::mutex> locker(sEDCSAContextsMutex);
-       auto context = sEDCSAContexts[ctx].lock();
-
-       if(!context) {
-#ifdef USE_DLOG_LOGGING
-               LOGE("Trying to sign ECDSA data on deleted context");
-#endif
-               return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-       }
-
-       locker.unlock();
-
-       try {
-               std::vector<uint8_t> digest;
-
-               int error = context->sign_data(md_alg,
-                               hash,
-                               hash_len,
-                               digest);
-
-               if(error == 0) {
-                       if(digest.size() > MBEDTLS_MPI_MAX_SIZE) {
-                               return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-                       }
-
-                       memcpy(sig, &digest[0], digest.size());
-                       *sig_len = digest.size();
-               }
-
-               return error;
-       } catch(...) {
-               return MBEDTLS_ERR_PK_ALLOC_FAILED;
-       }
-}
-
-static void eckey_free_wrap_alt( void *ctx )
-{
-    const mbedtls_pk_info_t *mbedtls_ec_info;
-    mbedtls_ec_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
-    mbedtls_ec_info->ctx_free_func(ctx);
-       std::unique_lock<std::mutex> locker(sEDCSAContextsMutex);
-       sEDCSAContexts.erase(ctx);
-}
-
-static size_t eckey_get_bitlen_alt( const void *ctx )
-{
-       std::unique_lock<std::mutex> locker(sEDCSAContextsMutex);
-       auto context = sEDCSAContexts[ctx].lock();
-
-       if(!context) {
-#ifdef USE_DLOG_LOGGING
-               LOGE("Trying to sign ECDSA data on deleted context");
-#endif
-               return 0;
-       }
-
-    return context->key_length();
-}
-
-static int SetupECDSAContext(mbedtls_pk_context* ctx, void* key_context) {
-    const mbedtls_pk_info_t *mbedtls_ec_info;
-       dcm_key_context_internal * context = reinterpret_cast<dcm_key_context_internal *>(key_context);
-
-    mbedtls_ec_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
-
-    if(!mbedtls_ec_info) {
-       return HWIF_ERROR;
-    }
-
-    context->ec_info = *mbedtls_ec_info;
-    context->ec_info.sign_func = ecdsa_sign_alt;
-    context->ec_info.ctx_free_func = eckey_free_wrap_alt;
-    context->ec_info.get_bitlen = eckey_get_bitlen_alt;
-
-    if(mbedtls_pk_setup(ctx, &context->ec_info)) {
-       return HWIF_ERROR;
-    }
-
-    try {
-       std::unique_lock<std::mutex> locker(sEDCSAContextsMutex);
-       sEDCSAContexts.emplace(ctx->pk_ctx, context->connection);
-    } catch(...) {
-#ifdef USE_DLOG_LOGGING
-       LOGE("Got exception when inserting to map");
-#endif
-       mbedtls_pk_free(ctx);
-       return HWIF_ERR_OUT_OF_MEMORY;
-    }
-
-    return HWIF_SUCCESS;
-}
-
-int DCM_HWSetupPkContext(mbedtls_pk_context* ctx, void* key_context)
-{
-       dcm_key_context_internal * context = reinterpret_cast<dcm_key_context_internal *>(key_context);
-
-       if(!context || !ctx) {
-               return HWIF_ERR_INVALID_PARAM;
-       }
-
-       const auto& key_type(context->connection->key_type());
-
-       if(key_type == "RSA") {
-               return SetupRSAContext(ctx, key_context);
-       } else if(key_type == "ECDSA") {
-               return SetupECDSAContext(ctx, key_context);
-       } else {
-#ifdef USE_DLOG_LOGGING
-               LOGE("Unsupported key type received from server");
-#endif
-       }
-
-       return HWIF_ERR_INVALID_PARAM;
-}
diff --git a/dcm-client/dcm_hw_interface.h b/dcm-client/dcm_hw_interface.h
deleted file mode 100644 (file)
index 55239a0..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/******************************************************************
- *
- * Copyright 2017 Samsung Electronics All Rights Reserved.
- *
- * Author: Jaroslaw Pelczar <j.pelczar@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_CLIENT_DCM_HW_INTERFACE_H_
-#define DCM_CLIENT_DCM_HW_INTERFACE_H_
-
-#include "device_certificate_manager_export.h"
-#include <mbedtls/ssl.h>
-#include <errno.h>
-
-/**
- * Error-definition for hw interface
- */
-
-typedef enum HwifResult {
-       HWIF_ERR_INVALID_PARAM = -EINVAL, /**< Invalid Paramter */
-       HWIF_ERR_OUT_OF_MEMORY = -ENOMEM, /**< Out of memory */
-       HWIF_ERR_NO_DATA = -ENODATA, /**< No data found */
-       HWIF_ERROR = -EFAULT, /**< Internal Error */
-       HWIF_SUCCESS = 0, /**< No Error */
-} HwifResult_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * This callback will be invoked to get a key context based on specific name indication
- * (service name, key usage, key type). The key context may be same with the alias name.
- *
- * @param[in] service  service name indicates first category name
- * @param[in] usage  usage name indicates sub-category name
- * @param[in] keytype  (optional) key type name indication if any, otherwise it usually will be NULL
- * @return  void type pointer value on success, otherwise NULL
- */
-API_DEVICE_CERTIFICATE_MANAGER_EXPORT void* DCM_HWGetKeyContext(const char* service, const char* usage, const char* keytype);
-
-/**
- * This callback will deallocate the key context that was retrieved from TZ
- * by calling GetHwKeyContext callback.
- *
- * @param[in] keyContext  key context object to be deallocated,
- *                   which was obtained from GetHwKeyContext callback function
- * @return  0 on success, otherwise a negative value
- */
-API_DEVICE_CERTIFICATE_MANAGER_EXPORT int DCM_HWFreeKeyContext(void* keyContext);
-
-/**
- * This callback will be invoked to load own(i.e., pre-injected) certificate from HW(e.g., TZ, eSE)
- *
- * @param[in] keyContext  key context object that identifies proper certificate chain
- * @param[out] cert_chain  certificate chain in binary
- * @param[out] cert_chain_len  total length of certificate chain
- * @return  0 on success, otherwise a negative value
- */
-API_DEVICE_CERTIFICATE_MANAGER_EXPORT int DCM_HWGetOwnCertificateChain(const void* keyContext,
-                    unsigned char** cert_chain, size_t* cert_chain_len);
-
-/**
- * This callback should provide setting up alternative functions (e.g., rsa_sign, key_len, etc)
- * of which HW(e.g., TZ, eSE) management library to the specified mbedtls context
- * that will be used during handshake.
- *
- * @param[in] ctx  pointer of pk context of mbedtls
- * @param[in] keyContext  key context object that identifies proper public/private key
- * @return  0 on success, otherwise a negative value
- */
-API_DEVICE_CERTIFICATE_MANAGER_EXPORT int DCM_HWSetupPkContext(mbedtls_pk_context* ctx, void* key_context);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* DCM_CLIENT_DCM_HW_INTERFACE_H_ */
index 82acda3d54d820a3daf46dad7367d0864e11af1d..c8de053c708549d90e326624efe2de5301b58944 100644 (file)
@@ -1,8 +1,6 @@
 /******************************************************************
  *
- * Copyright 2017 Samsung Electronics All Rights Reserved.
- *
- * Author: Jaroslaw Pelczar <j.pelczar@samsung.com>
+ * Copyright 2017 - 2018 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.
 
 #include "dcm_client_p.h"
 #include "dcm_support.pb.h"
-#include "dcm_hw_interface.h"
+#include "device_certificate_manager.h"
 #include <cassert>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <protobuf_asio.h>
 #include <inttypes.h>
+#include <mbedtls/ssl.h>
 
 #ifdef USE_DLOG_LOGGING
-#define LOG_TAG                "dcm-client"
+#define LOG_TAG                "DEVICE_CERTIFICATE_MANAGER_CLIENT"
 #include <dlog.h>
 #endif
 
@@ -167,7 +166,7 @@ int dcm_client_connection_impl::get_certificate_chain(std::vector<uint8_t>& chai
 #ifdef USE_DLOG_LOGGING
                LOGE("%s: Trying to request certificate in session %p without connection", __FUNCTION__, this);
 #endif
-               return HWIF_ERR_INVALID_PARAM;
+               return DCM_ERROR_INVALID_PARAMETER;
        }
 
        try {
@@ -184,7 +183,7 @@ int dcm_client_connection_impl::get_certificate_chain(std::vector<uint8_t>& chai
 #ifdef USE_DLOG_LOGGING
                        LOGE("%s: Response from server is not certificate chain response on session %p", __FUNCTION__, this);
 #endif
-                       return HWIF_ERR_NO_DATA;
+                       return DCM_ERROR_NO_DATA;
                }
 
                auto& cert_resp(response.request_chain());
@@ -194,14 +193,14 @@ int dcm_client_connection_impl::get_certificate_chain(std::vector<uint8_t>& chai
                        LOGE("%s: Server can't respond with certificate chain: error %d in session %p", __FUNCTION__,
                                        cert_resp.result(), this);
 #endif
-                       return HWIF_ERR_NO_DATA;
+                       return DCM_ERROR_NO_DATA;
                }
 
                if(cert_resp.cert_chain().size() == 0) {
 #ifdef USE_DLOG_LOGGING
                        LOGE("%s: Server can't respond with certificate chain: certificate empty", __FUNCTION__);
 #endif
-                       return HWIF_ERR_NO_DATA;
+                       return DCM_ERROR_NO_DATA;
                }
 
                // Add space for last zero byte if needed
@@ -218,25 +217,25 @@ int dcm_client_connection_impl::get_certificate_chain(std::vector<uint8_t>& chai
 #ifdef USE_DLOG_LOGGING
                LOGE("%s: Out of memory when requesting certificate for session %p", __FUNCTION__, this);
 #endif
-               return HWIF_ERR_OUT_OF_MEMORY;
+               return DCM_ERROR_OUT_OF_MEMORY;
        } catch(std::invalid_argument&) {
 #ifdef USE_DLOG_LOGGING
                LOGE("%s: Invalid argument passed for certificate request for session %p", __FUNCTION__, this);
 #endif
-               return HWIF_ERR_INVALID_PARAM;
+               return DCM_ERROR_INVALID_PARAMETER;
        } catch(std::exception& ex) {
 #ifdef USE_DLOG_LOGGING
                LOGE("%s: When requesting certificate for session %p received exception : %s", __FUNCTION__, this, ex.what());
 #endif
-               return HWIF_ERROR;
+               return DCM_ERROR_UNKNOWN;
        } catch(...) {
 #ifdef USE_DLOG_LOGGING
                LOGE("%s: When requesting certificate for session %p received exception : %s", __FUNCTION__, this, "Unknown error");
 #endif
-               return HWIF_ERROR;
+               return DCM_ERROR_UNKNOWN;
        }
 
-       return HWIF_SUCCESS;
+       return DCM_ERROR_NONE;
 }
 
 const std::string& dcm_client_connection_impl::key_type() const noexcept {
@@ -256,7 +255,7 @@ int dcm_client_connection_impl::sign_data(mbedtls_md_type_t digestType, const vo
 #ifdef USE_DLOG_LOGGING
                LOGE("%s: Trying to request data signing in object %p but there is no connection", __FUNCTION__);
 #endif
-               return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+               return DCM_ERROR_SOCKET;
        }
 
        /*
@@ -267,7 +266,7 @@ int dcm_client_connection_impl::sign_data(mbedtls_md_type_t digestType, const vo
 #ifdef USE_DLOG_LOGGING
                        LOGE("%s: Digest type is NONE and hash size is 0", __FUNCTION__);
 #endif
-                       return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+                       return DCM_ERROR_INVALID_PARAMETER;
                }
 
                const mbedtls_md_info_t * md_info = mbedtls_md_info_from_type(digestType);
@@ -276,7 +275,7 @@ int dcm_client_connection_impl::sign_data(mbedtls_md_type_t digestType, const vo
 #ifdef USE_DLOG_LOGGING
                        LOGE("%s: Can't find hash data for digest type %d", __FUNCTION__, digestType);
 #endif
-                       return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+                       return DCM_ERROR_INVALID_PARAMETER;
                }
 
                hash_size = mbedtls_md_get_size(md_info);
@@ -290,14 +289,14 @@ int dcm_client_connection_impl::sign_data(mbedtls_md_type_t digestType, const vo
 #ifdef USE_DLOG_LOGGING
                        LOGE("%s: Can't find hash data for digest type %d", __FUNCTION__, digestType);
 #endif
-                       return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+                       return DCM_ERROR_INVALID_PARAMETER;
                }
 
                if(hash_size != mbedtls_md_get_size(md_info)) {
 #ifdef USE_DLOG_LOGGING
                        LOGE("%s: Hash size mismatch. Expected %zd but got %zd", __FUNCTION__, hash_size, (size_t)mbedtls_md_get_size(md_info));
 #endif
-                       return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+                       return DCM_ERROR_INVALID_PARAMETER;
                }
        }
 
@@ -317,7 +316,7 @@ int dcm_client_connection_impl::sign_data(mbedtls_md_type_t digestType, const vo
 #ifdef USE_DLOG_LOGGING
                        LOGE("%s: Response for hash signature has no signature data", __FUNCTION__);
 #endif
-                       return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+                       return DCM_ERROR_INVALID_PARAMETER;
                }
 
                auto& sign_resp(response.sign_data());
@@ -326,7 +325,7 @@ int dcm_client_connection_impl::sign_data(mbedtls_md_type_t digestType, const vo
 #ifdef USE_DLOG_LOGGING
                        LOGE("%s: Signature request for session %p received error %d", __FUNCTION__, this, sign_resp.result());
 #endif
-                       return sign_resp.result();
+                       return DCM_ERROR_INVALID_PARAMETER;
                }
 
                const auto& signature = sign_resp.signature();
@@ -335,7 +334,7 @@ int dcm_client_connection_impl::sign_data(mbedtls_md_type_t digestType, const vo
 #ifdef USE_DLOG_LOGGING
                        LOGE("%s: Received signature object is empty for session %p", __FUNCTION__, this);
 #endif
-                       return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+                       return DCM_ERROR_INVALID_PARAMETER;
                }
 
                digest.resize(signature.size());
@@ -344,19 +343,15 @@ int dcm_client_connection_impl::sign_data(mbedtls_md_type_t digestType, const vo
 #ifdef USE_DLOG_LOGGING
                LOGE("%s: Out of memory when processing sign request for session %p", __FUNCTION__, this);
 #endif
-               return MBEDTLS_ERR_PK_ALLOC_FAILED;
-       } catch(std::exception& ex) {
-#ifdef USE_DLOG_LOGGING
-               LOGE("%s: When processing signature for session %p got exception : %s", __FUNCTION__, this, ex.what());
-#endif
+               return DCM_ERROR_OUT_OF_MEMORY;
        } catch(...) {
 #ifdef USE_DLOG_LOGGING
                LOGE("%s: When processing signature for session %p got exception : %s", __FUNCTION__, this, "Unknown error");
 #endif
-               return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+               return DCM_ERROR_UNKNOWN;
        }
 
-       return 0;
+       return DCM_ERROR_NONE;
 }
 
 unsigned int dcm_client_connection_impl::key_length() const noexcept {
diff --git a/dcm-client/device_certificate_manager.cpp b/dcm-client/device_certificate_manager.cpp
new file mode 100644 (file)
index 0000000..1ee2896
--- /dev/null
@@ -0,0 +1,185 @@
+/******************************************************************
+ *
+ * Copyright 2017 - 2018 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.
+ *
+ ******************************************************************/
+
+#include "device_certificate_manager.h"
+#include "dcm_client.h"
+#include <mbedtls/pk_internal.h>
+#include <mbedtls/md.h>
+#include <vector>
+#include <cstring>
+
+#ifdef USE_DLOG_LOGGING
+#define LOG_TAG                "DEVICE_CERTIFICATE_MANAGER_CLIENT"
+#include <dlog.h>
+#endif
+
+#define API_DEVICE_CERTIFICATE_MANAGER_EXPORT __attribute__((visibility("default")))
+
+static mbedtls_md_type_t to_mbedtls_md_type(dcm_digest_algorithm_e md)
+{
+  switch(md) {
+    case DCM_DIGEST_NONE:
+      return MBEDTLS_MD_NONE;
+    case DCM_DIGEST_MD2:
+      return MBEDTLS_MD_MD2;
+    case DCM_DIGEST_MD4:
+      return MBEDTLS_MD_MD4;
+    case DCM_DIGEST_MD5:
+      return MBEDTLS_MD_MD5;
+    case DCM_DIGEST_SHA1:
+      return MBEDTLS_MD_SHA1;
+    case DCM_DIGEST_SHA224:
+      return MBEDTLS_MD_SHA224;
+    case DCM_DIGEST_SHA256:
+      return MBEDTLS_MD_SHA256;
+    case DCM_DIGEST_SHA384:
+      return MBEDTLS_MD_SHA384;
+    case DCM_DIGEST_SHA512:
+      return MBEDTLS_MD_SHA512;
+    case DCM_DIGEST_RIPEMD160:
+      return MBEDTLS_MD_RIPEMD160;
+    default:
+      return MBEDTLS_MD_NONE;
+  };
+}
+
+struct dcm_key_context_internal {
+       std::shared_ptr<dcm_client_connection> connection;
+};
+
+API_DEVICE_CERTIFICATE_MANAGER_EXPORT
+int dcm_create_key_context(const char *service, const char *usage, const char *key_type, void **key_ctx)
+{
+       try {
+               if(!key_ctx)
+                       return DCM_ERROR_INVALID_PARAMETER;
+
+               std::unique_ptr<dcm_key_context_internal> context(new dcm_key_context_internal());
+
+               std::string service_string(service ? service : "");
+               std::string usage_string(usage ? usage : "");
+               std::string keytype_string(key_type ? key_type : "");
+
+               context->connection = dcm_client_connection::create();
+
+               if(!context->connection->create_context(service_string, usage_string, keytype_string)) {
+#ifdef USE_DLOG_LOGGING
+                       LOGE("Can't create connection context");
+#endif
+                       return DCM_ERROR_SOCKET;
+               }
+
+               *key_ctx = context.release();
+               return DCM_ERROR_NONE;
+       } catch(std::exception& ex) {
+#ifdef USE_DLOG_LOGGING
+               LOGE("Context creation failure: %s", ex.what());
+#endif
+               return DCM_ERROR_UNKNOWN;
+       } catch(...) {
+#ifdef USE_DLOG_LOGGING
+               LOGE("Context creation failure");
+#endif
+               return DCM_ERROR_UNKNOWN;
+       }
+}
+
+API_DEVICE_CERTIFICATE_MANAGER_EXPORT
+int dcm_free_key_context(void *key_ctx)
+{
+       if(!key_ctx)
+               return DCM_ERROR_NONE;
+
+       delete reinterpret_cast<dcm_key_context_internal *>(key_ctx);
+
+       return DCM_ERROR_NONE;
+}
+
+API_DEVICE_CERTIFICATE_MANAGER_EXPORT
+int dcm_get_certificate_chain(const void *key_ctx, char **cert_chain, size_t *cert_chain_len)
+{
+       if(!key_ctx || !cert_chain || !cert_chain_len)
+               return DCM_ERROR_INVALID_PARAMETER;
+
+       const dcm_key_context_internal *context =
+               reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
+
+       std::vector<uint8_t> cert;
+       int result = context->connection->get_certificate_chain(cert);
+       if(result == DCM_ERROR_NONE) {
+               if(!(*cert_chain = strdup(reinterpret_cast<const char*>(cert.data()))))
+                       return DCM_ERROR_OUT_OF_MEMORY;
+               *cert_chain_len = cert.size();
+       }
+
+       return result;
+}
+
+API_DEVICE_CERTIFICATE_MANAGER_EXPORT
+int dcm_get_key_bit_length(const void *key_ctx, size_t *key_bit_len)
+{
+       if(!key_ctx || !key_bit_len)
+               return DCM_ERROR_INVALID_PARAMETER;
+
+       const dcm_key_context_internal *context =
+               reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
+       *key_bit_len = context->connection->key_length();
+
+       return DCM_ERROR_NONE;
+}
+
+API_DEVICE_CERTIFICATE_MANAGER_EXPORT
+int dcm_get_key_type(const void *key_ctx, char **key_type)
+{
+       if(!key_ctx || !key_type)
+               return DCM_ERROR_INVALID_PARAMETER;
+
+       const dcm_key_context_internal *context =
+               reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
+
+       std::string type = context->connection->key_type();
+       if(!(*key_type = strdup(type.c_str())))
+               return DCM_ERROR_OUT_OF_MEMORY;
+
+       return DCM_ERROR_NONE;
+}
+
+API_DEVICE_CERTIFICATE_MANAGER_EXPORT
+int dcm_create_signature(const void *key_ctx, dcm_digest_algorithm_e md,
+                        const char *message, size_t message_len,
+                        char **signature, size_t *signature_len)
+{
+       if(!key_ctx || !signature || !signature_len)
+               return DCM_ERROR_INVALID_PARAMETER;
+
+       const dcm_key_context_internal *context =
+               reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
+
+       std::vector<uint8_t> digest;
+       int result = context->connection->sign_data(to_mbedtls_md_type(md), message, message_len, digest);
+       if(result == DCM_ERROR_NONE) {
+               if(digest.size() > MBEDTLS_MPI_MAX_SIZE)
+                       return DCM_ERROR_INVALID_PARAMETER;
+
+               if(!(*signature = strdup(reinterpret_cast<const char*>(digest.data()))))
+                       return DCM_ERROR_OUT_OF_MEMORY;
+               *signature_len = digest.size();
+       }
+
+       return result;
+}
diff --git a/dcm-client/device_certificate_manager.h b/dcm-client/device_certificate_manager.h
new file mode 100644 (file)
index 0000000..9e53a83
--- /dev/null
@@ -0,0 +1,240 @@
+/******************************************************************
+ *
+ * Copyright 2017 - 2018 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.
+ *
+ ******************************************************************/
+
+#ifndef __DEVICE_CERTIFICATE_MANAGER_H__
+#define __DEVICE_CERTIFICATE_MANAGER_H__
+
+#include <stddef.h>
+#include <tizen.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup CAPI_DEVICE_CERTIFICATE_MANAGER_MODULE
+ * @{
+ */
+
+
+/**
+ * @brief Enumeration for DCM error values.
+ * @since_tizen 5.0
+ */
+typedef enum {
+    DCM_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
+    DCM_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid function parameter */
+    DCM_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
+    DCM_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
+    DCM_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Feature needed to run API is not supported */
+    DCM_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA, /**< No data available */
+    DCM_ERROR_UNKNOWN = TIZEN_ERROR_UNKNOWN, /**< Unknown error */
+
+    DCM_ERROR_SOCKET = TIZEN_ERROR_DEVICE_CERTIFICATE_MANAGER | 0x01, /**< Socket error between client and server */
+} dcm_error_e;
+
+
+/**
+ * @brief Enumeration for DCM message digest algorithms.
+ * @since_tizen 5.0
+ */
+typedef enum {
+    DCM_DIGEST_NONE=0, /**< No message digest algorithm */
+    DCM_DIGEST_MD2, /**< Message digest algorithm MD2 */
+    DCM_DIGEST_MD4, /**< Message digest algorithm MD4 */
+    DCM_DIGEST_MD5, /**< Message digest algorithm MD5 */
+    DCM_DIGEST_SHA1, /**< Message digest algorithm SHA1 */
+    DCM_DIGEST_SHA224, /**< Message digest algorithm SHA224 */
+    DCM_DIGEST_SHA256, /**< Message digest algorithm SHA256 */
+    DCM_DIGEST_SHA384, /**< Message digest algorithm SHA384 */
+    DCM_DIGEST_SHA512, /**< Message digest algorithm SHA512 */
+    DCM_DIGEST_RIPEMD160, /**< Message digest algorithm RIPEMD160 */
+} dcm_digest_algorithm_e;
+
+
+/**
+ * @platform
+ * @brief Creates a new key context based on specific name indication (service name, key usage, key type).
+ * @since_tizen 5.0
+ * @privlevel platform
+ * @privilege %http://tizen.org/privilege/devicecertificate
+ *
+ * @remarks The @a key_ctx should be freed with dcm_free_key_context() after use.
+ *
+ * @param[in] service  Service name indicates first category name (if null, default value is used)
+ * @param[in] usage  Usage name indicates sub-category name (if null, default value is used)
+ * @param[in] key_type  Key type name indication (if null, default value is used)
+ * @param[out] key_ctx  Newly created key context
+ * @return #DCM_ERROR_NONE on success,
+ *         otherwise a negative error value
+ *
+ * @retval #DCM_ERROR_NONE Successful
+ * @retval #DCM_ERROR_INVALID_PARAMETER Input parameter is invalid
+ * @retval #DCM_ERROR_OUT_OF_MEMORY Out of memory during processing
+ * @retval #DCM_ERROR_PERMISSION_DENIED Failed to access device certificate manager
+ * @retval #DCM_ERROR_NOT_SUPPORTED Feature needed to run API is not supported
+ * @retval #DCM_ERROR_SOCKET Socket error between client and server
+ * @retval #DCM_ERROR_UNKNOWN Unknown error
+ *
+ * @see dcm_free_key_context()
+ */
+int dcm_create_key_context(const char *service, const char *usage, const char *key_type, void **key_ctx);
+
+
+/**
+ * @platform
+ * @brief Destroys the key context that was created by calling dcm_create_key_context().
+ * @since_tizen 5.0
+ * @privlevel platform
+ * @privilege %http://tizen.org/privilege/devicecertificate
+ *
+ * @param[in] key_ctx  Key context object to be deallocated
+ * @return #DCM_ERROR_NONE on success,
+ *         otherwise a negative error value
+ *
+ * @retval #DCM_ERROR_NONE Successful
+ * @retval #DCM_ERROR_INVALID_PARAMETER Input parameter is invalid
+ * @retval #DCM_ERROR_OUT_OF_MEMORY Out of memory during processing
+ * @retval #DCM_ERROR_PERMISSION_DENIED Failed to access device certificate manager
+ * @retval #DCM_ERROR_NOT_SUPPORTED Feature needed to run API is not supported
+ * @retval #DCM_ERROR_SOCKET Socket error between client and server
+ * @retval #DCM_ERROR_NO_DATA No such key context object
+ * @retval #DCM_ERROR_UNKNOWN Unknown error
+ *
+ * @see dcm_create_key_context()
+ */
+int dcm_free_key_context(void *key_ctx);
+
+
+/**
+ * @platform
+ * @brief Returns a certificate chain which was pre-injected in device.
+ * @since_tizen 5.0
+ * @privlevel platform
+ * @privilege %http://tizen.org/privilege/devicecertificate
+ *
+ * @remarks The @a cert_chain should be freed using free().
+ *
+ * @param[in] key_ctx  Key context object that identifies proper certificate chain
+ * @param[out] cert_chain  Certificate chain in binary, will be allocated by the library
+ * @param[out] cert_chain_len  The total length of certificate chain
+ * @return #DCM_ERROR_NONE on success,
+ *         otherwise a negative error value
+ *
+ * @retval #DCM_ERROR_NONE Successful
+ * @retval #DCM_ERROR_INVALID_PARAMETER Input parameter is invalid
+ * @retval #DCM_ERROR_OUT_OF_MEMORY Out of memory during processing
+ * @retval #DCM_ERROR_PERMISSION_DENIED Failed to access device certificate manager
+ * @retval #DCM_ERROR_NOT_SUPPORTED Feature needed to run API is not supported
+ * @retval #DCM_ERROR_SOCKET Socket error between client and server
+ * @retval #DCM_ERROR_NO_DATA No certificate chain available
+ * @retval #DCM_ERROR_UNKNOWN Unknown error
+ */
+int dcm_get_certificate_chain(const void *key_ctx, char **cert_chain, size_t *cert_chain_len);
+
+
+/**
+ * @platform
+ * @brief Returns the key size in bits for a given key context.
+ * @since_tizen 5.0
+ * @privlevel platform
+ * @privilege %http://tizen.org/privilege/devicecertificate
+ *
+ * @param[in] key_ctx  Key context object that identifies proper certificate chain
+ * @param[out] key_bit_len  Key length in bits
+ * @return #DCM_ERROR_NONE on success,
+ *         otherwise a negative error value
+ *
+ * @retval #DCM_ERROR_NONE Successful
+ * @retval #DCM_ERROR_INVALID_PARAMETER Input parameter is invalid
+ * @retval #DCM_ERROR_OUT_OF_MEMORY Out of memory during processing
+ * @retval #DCM_ERROR_PERMISSION_DENIED Failed to access device certificate manager
+ * @retval #DCM_ERROR_NOT_SUPPORTED Feature needed to run API is not supported
+ * @retval #DCM_ERROR_SOCKET Socket error between client and server
+ * @retval #DCM_ERROR_NO_DATA No certificate chain available
+ * @retval #DCM_ERROR_UNKNOWN Unknown error
+ */
+int dcm_get_key_bit_length(const void *key_ctx, size_t *key_bit_len);
+
+
+/**
+ * @platform
+ * @brief Returns the key type name for a given key context.
+ * @since_tizen 5.0
+ * @privlevel platform
+ * @privilege %http://tizen.org/privilege/devicecertificate
+ *
+ * @remarks The @a key_type should be freed using free().
+ *
+ * @param[in] key_ctx  Key context object that identifies proper certificate chain
+ * @param[out] key_type  Key type name (UNKNOWN, RSA or ECDSA), will be allocated by the library
+ * @return #DCM_ERROR_NONE on success,
+ *         otherwise a negative error value
+ *
+ * @retval #DCM_ERROR_NONE Successful
+ * @retval #DCM_ERROR_INVALID_PARAMETER Input parameter is invalid
+ * @retval #DCM_ERROR_OUT_OF_MEMORY Out of memory during processing
+ * @retval #DCM_ERROR_PERMISSION_DENIED Failed to access device certificate manager
+ * @retval #DCM_ERROR_NOT_SUPPORTED Feature needed to run API is not supported
+ * @retval #DCM_ERROR_SOCKET Socket error between client and server
+ * @retval #DCM_ERROR_NO_DATA No certificate chain available
+ * @retval #DCM_ERROR_UNKNOWN Unknown error
+ */
+int dcm_get_key_type(const void *key_ctx, char **key_type);
+
+/**
+ * @platform
+ * @brief Creates a signature on a given data using a private key and returns the signature.
+ * @since_tizen 5.0
+ * @privlevel platform
+ * @privilege %http://tizen.org/privilege/devicecertificate
+ *
+ * @remarks The private key is identified by @a key_ctx.
+ * @remarks The @a message can be NULL but then @a message_len must be 0.
+ * @remarks The @a signature should be freed using free().
+ *
+ * @param[in] key_ctx  Key context object that identifies a proper private key for signing
+ * @param[in] md  Message digest algorithm used in creating signature
+ * @param[in] message  Message that is signed with a key
+ * @param[in] message_len  Length of the message
+ * @param[out] signature  Newly created signature, will be allocated by the library
+ * @param[out] signature_len  Length of a newly created signature
+ * @return #DCM_ERROR_NONE on success,
+ *         otherwise a negative error value
+ *
+ * @retval #DCM_ERROR_NONE Successful
+ * @retval #DCM_ERROR_INVALID_PARAMETER Input parameter is invalid
+ * @retval #DCM_ERROR_OUT_OF_MEMORY Out of memory during processing
+ * @retval #DCM_ERROR_PERMISSION_DENIED Failed to access device certificate manager
+ * @retval #DCM_ERROR_NOT_SUPPORTED Feature needed to run API is not supported
+ * @retval #DCM_ERROR_SOCKET Socket error between client and server
+ * @retval #DCM_ERROR_UNKNOWN Unknown error
+ */
+int dcm_create_signature(const void *key_ctx, dcm_digest_algorithm_e md,
+                         const char *message, size_t message_len,
+                         char **signature, size_t *signature_len);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DEVICE_CERTIFICATE_MANAGER_H__ */
index 854fe235d31ae6a5526339c3f82ab55e5ee91dc4..88ea94d015ae966ba96449b5af9f9c01b17fea7b 100644 (file)
@@ -1,13 +1,15 @@
-DCMCLIENT_1.0 {
+DCMCLIENT_2.0 {
        global:
-               DCM_HWGetKeyContext;
-               DCM_HWFreeKeyContext;
-               DCM_HWGetOwnCertificateChain;
-               DCM_HWSetupPkContext;
+               dcm_create_key_context;
+               dcm_free_key_context;
+               dcm_get_certificate_chain;
+               dcm_get_key_bit_length;
+               dcm_get_key_type;
+               dcm_create_signature;
                extern "C++" {
                        dcm_client_connection::*;
                };
-               
+
        local:
                *;
 };
index 1ccf0a10653d70dc5958a79bc2af2a836a73782f..3564e3c40571f00e4f785b197c39ccbed3bc7e11 100644 (file)
@@ -33,7 +33,7 @@
 #include <boost/log/attributes/named_scope.hpp>
 
 #ifdef USE_DLOG_LOGGING
-#define LOG_TAG                "dcm-server"
+#define LOG_TAG                "DEVICE_CERTIFICATE_MANAGER_SERVER"
 #include <dlog.h>
 #endif
 
diff --git a/doc/device_certificate_manager_doc.h b/doc/device_certificate_manager_doc.h
new file mode 100644 (file)
index 0000000..e14a4ac
--- /dev/null
@@ -0,0 +1,48 @@
+/******************************************************************
+ *
+ * Copyright 2018 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.
+ *
+ ******************************************************************/
+
+#ifndef __TIZEN_CORE_DEVICE_CERTIFICATE_MANAGER_DOC_H__
+#define __TIZEN_CORE_DEVICE_CERTIFICATE_MANAGER_DOC_H__
+
+/**
+  * @ingroup CAPI_SECURITY_FRAMEWORK
+  * @defgroup CAPI_DEVICE_CERTIFICATE_MANAGER_MODULE Device Certificate Manager
+  *
+  * @brief  Device Certificate Manager provides cryptography services (digital certificates and keys)
+  *         for authentication and secure communication with another system.
+  *         Device certificate and key was embedded in device storage.
+  *
+  * @section CAPI_DEVICE_CERTIFICATE_MANAGER_MODULE_HEADER Required Header
+  *   \#include <device_certificate_manager.h>
+  *
+  * @section CAPI_DEVICE_CERTIFICATE_MANAGER_MODULE_FEATURE Related Features
+  * This module is related with the following features:\n
+  * - http://tizen.org/feature/security.device_certificate\n
+  * It is recommended to use features in your application for reliability.\n
+  * You can check if the device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, and control your application's actions accordingly.\n
+  * To ensure your application is running only on devices with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n
+  * More details on using features in your application can be found in the <a href="https://developer.tizen.org/development/tizen-studio/native-tools/configuring-your-app/manifest-text-editor#feature"><b>feature element description</b></a>.
+  *
+  * @section CAPI_PRIVACY_PRIVILEGE_MANAGER_MODULE_OVERVIEW Overview
+  * Device Certificate Manager provides cryptography services (digital certificates and keys)
+  * for authentication and secure communication with another system.
+  * Device certificate and key was embedded in device storage.
+  *
+  */
+
+#endif /* __TIZEN_CORE_DEVICE_CERTIFICATE_MANAGER_DOC_H__ */
index c22f0450365065f60cd48fc38ea04597f1fd6579..98877a9181146274d13da7f0600fdbdb2de44fd7 100644 (file)
@@ -119,5 +119,6 @@ fi
 %manifest device-certificate-manager-tests.manifest
 %license LICENSE
 %{_bindir}/dcm_example_client
+%{_bindir}/dcm_example_capi
 %{_bindir}/dcm_hw_api_test
 %{_bindir}/dcm_test_cert_rewriter
index 68742eb888169d4dfa9f2122c9c370cf47ebecf1..a4fa1d67a5d9109ff75e1fcda3b8d45a39111be0 100644 (file)
@@ -10,42 +10,47 @@ ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK)
 add_executable(dcm_example_client example_client.cpp)
 target_link_libraries(dcm_example_client device-certificate-manager)
 
-add_executable(dcm_hw_api_test hw_api_test.cpp)
-target_link_libraries(dcm_hw_api_test device-certificate-manager ${MBEDTLS_LIB} ${MBEDCRYPTO_LIB} ${MBEDX509_LIB})
+add_executable(dcm_example_capi example_capi.c)
+target_link_libraries(dcm_example_capi device-certificate-manager)
 
-install(TARGETS dcm_example_client dcm_hw_api_test
+install(TARGETS dcm_example_client dcm_example_capi
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
 
 IF(Boost_UNIT_TEST_FRAMEWORK_FOUND)
        add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cert_pem.c
                COMMAND $<TARGET_FILE:helper_bin2c> ${CMAKE_CURRENT_SOURCE_DIR}/test_data/cert.pem ${CMAKE_CURRENT_BINARY_DIR}/cert_pem.c test_data_cert_pem
                DEPENDS helper_bin2c ${CMAKE_CURRENT_SOURCE_DIR}/test_data/cert.pem)
-       
+
        add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cert_pem2.c
                COMMAND $<TARGET_FILE:helper_bin2c> ${CMAKE_CURRENT_SOURCE_DIR}/test_data/cert2.pem ${CMAKE_CURRENT_BINARY_DIR}/cert_pem2.c test_data_cert_pem2
                DEPENDS helper_bin2c ${CMAKE_CURRENT_SOURCE_DIR}/test_data/cert2.pem)
-       
+
        add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/tizen_org_pem.c
                COMMAND $<TARGET_FILE:helper_bin2c> ${CMAKE_CURRENT_SOURCE_DIR}/test_data/tizen.org.pem ${CMAKE_CURRENT_BINARY_DIR}/tizen_org_pem.c tizen_org_pem
                DEPENDS helper_bin2c ${CMAKE_CURRENT_SOURCE_DIR}/test_data/tizen.org.pem)
-       
+
        add_executable(dcm_test_cert_rewriter
                test_cert_rewriter.cpp
                ../dcm-daemon/cert_utils.cpp
                ${CMAKE_CURRENT_BINARY_DIR}/cert_pem.c
                ${CMAKE_CURRENT_BINARY_DIR}/cert_pem2.c
                ${CMAKE_CURRENT_BINARY_DIR}/tizen_org_pem.c)
-               
-       target_link_libraries(dcm_test_cert_rewriter 
+
+       target_link_libraries(dcm_test_cert_rewriter
                        ${Boost_LOG_LIBRARY}
                        ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}
-                       ${Boost_SYSTEM_LIBRARY}  
+                       ${Boost_SYSTEM_LIBRARY}
                        ${CMAKE_THREAD_LIBS_INIT}
                        ${MBEDTLS_LIB}
                        ${MBEDCRYPTO_LIB}
                        ${MBEDX509_LIB})
 
-       install(TARGETS dcm_test_cert_rewriter
+       add_executable(dcm_hw_api_test hw_api_test.cpp)
+       target_link_libraries(dcm_hw_api_test
+                       device-certificate-manager
+                       ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
+
+       install(TARGETS dcm_test_cert_rewriter dcm_hw_api_test
                RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
 ELSE()
        message(STATUS "Boost::test library not found. Disabling unit test build")
diff --git a/tests/example_capi.c b/tests/example_capi.c
new file mode 100644 (file)
index 0000000..10a1317
--- /dev/null
@@ -0,0 +1,63 @@
+#include "device_certificate_manager.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char ** argv)
+{
+       int result;
+       void *key_ctx = NULL;
+       char *key_type = NULL;
+       size_t key_len;
+       char *cert_chain = NULL;
+       size_t cert_chain_len;
+       char *signature = NULL;
+       size_t signature_len;
+
+       result = dcm_create_key_context("example_client", "test_usage", "", &key_ctx);
+       if(result != DCM_ERROR_NONE) {
+               printf("Can't create context\n");
+               goto exit;
+       }
+
+       result = dcm_get_key_type(key_ctx, &key_type);
+       if(result != DCM_ERROR_NONE) {
+               printf("Can't get key type\n");
+               goto exit;
+       }
+       printf("Using key type %s\n", key_type);
+
+       result = dcm_get_certificate_chain(key_ctx, &cert_chain, &cert_chain_len);
+       if(result != DCM_ERROR_NONE) {
+               printf("Can't get cert chain\n");
+               goto exit;
+       }
+       printf("Cert is %d bytes\n", cert_chain_len);
+       printf("Received cert %s\n", cert_chain);
+
+       result = dcm_get_key_bit_length(key_ctx, &key_len);
+       if(result != DCM_ERROR_NONE) {
+               printf("Can't get key length\n");
+               goto exit;
+       }
+       printf("Private key is %d bits\n", key_len);
+       printf("Private key is %s\n", key_type);
+
+       result = dcm_create_signature(key_ctx, DCM_DIGEST_SHA256, "12345678901234567890123456789012", 32, &signature, &signature_len);
+       if(result != DCM_ERROR_NONE) {
+               printf("Can't create signature\n");
+               goto exit;
+       }
+
+       for(int i = 0; i < signature_len; i++) {
+               printf("%x ", (int)(*(unsigned char*)(&signature[i])));
+       }
+       printf("\n");
+
+exit:
+       free(signature);
+       free(cert_chain);
+       free(key_type);
+       dcm_free_key_context(key_ctx);
+
+       return result;
+}
index 7c76a345dc945633f53727e2194a60a964ea0ee8..2be7bd4f1ee0331a6c5a58cf985abb88a31efcb0 100644 (file)
-#include "dcm_hw_interface.h"
+#define BOOST_TEST_MODULE HW API test
+
+#include "device_certificate_manager.h"
 #include <iostream>
 #include <iomanip>
 #include <cstring>
 
-#include <mbedtls/debug.h>
-#include <mbedtls/ssl.h>
-#include <mbedtls/entropy.h>
-#include <mbedtls/ctr_drbg.h>
-#include <mbedtls/error.h>
-#include <mbedtls/certs.h>
-#include <mbedtls/x509_crt.h>
-
-#include <mbedtls_wrapper.h>
-
-#include <cassert>
-
 #include <boost/algorithm/hex.hpp>
+#include <boost/test/unit_test.hpp>
 
-
-static void test_key_context_creation() {
-
-    void* res = DCM_HWGetKeyContext(NULL, NULL, NULL);
-    assert(res != NULL);
-    int ret = DCM_HWFreeKeyContext(res);
-    assert(ret == 0);
-
-    res = DCM_HWGetKeyContext("", "", NULL);
-    assert(res != NULL);
-    ret = DCM_HWFreeKeyContext(res);
-    assert(ret == 0);
-
-    res = DCM_HWGetKeyContext("a", NULL, NULL);
-    assert(res != NULL);
-    ret = DCM_HWFreeKeyContext(res);
-    assert(ret == 0);
-
-    res = DCM_HWGetKeyContext(NULL, "a", NULL);
-    assert(res != NULL);
-    ret = DCM_HWFreeKeyContext(res);
-    assert(ret == 0);
-
-    res = DCM_HWGetKeyContext("a", "a", NULL);
-    assert(res != NULL);
-    ret = DCM_HWFreeKeyContext(res);
-    assert(ret == 0);
-
-    res = DCM_HWGetKeyContext("a", "b", "UNEXISTING");
-    assert(res == NULL);
-    ret = DCM_HWFreeKeyContext(res);
-    assert(ret == 0);
-
-    std::cout << "DCM_HWGetKeyContext/DCM_HWFreeKeyContext ... OK\n";
-}
-
-static void test_get_own_cert_chain() {
-    void *ctx = DCM_HWGetKeyContext("a", "b", NULL);
-    size_t size;
-    unsigned char *cert;
-
-    int res = DCM_HWGetOwnCertificateChain(ctx, NULL, &size);
-    assert(res < 0);
-
-    res = DCM_HWGetOwnCertificateChain(ctx, &cert, NULL);
-    assert(res < 0);
-
-    res = DCM_HWGetOwnCertificateChain(NULL, &cert, &size);
-    assert(res < 0);
-
-    res = DCM_HWGetOwnCertificateChain(ctx, &cert, &size);
-    assert(res == 0);
-
-    DCM_HWFreeKeyContext(ctx);
-
-    std::cout << "DCM_HWGetOwnCertificateChain ... OK\n";
+BOOST_AUTO_TEST_CASE(test01_dcm_create_key_context)
+{
+    void *ctx;
+    int ret = dcm_create_key_context(NULL, NULL, NULL, &ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(ctx);
+    ret = dcm_free_key_context(ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+
+    ctx = NULL;
+    ret = dcm_create_key_context("", "", NULL, &ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(ctx);
+    ret = dcm_free_key_context(ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+
+    ctx = NULL;
+    ret = dcm_create_key_context("a", NULL, NULL, &ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(ctx);
+    ret = dcm_free_key_context(ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+
+    ctx = NULL;
+    ret = dcm_create_key_context(NULL, "a", NULL, &ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(ctx);
+    ret = dcm_free_key_context(ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+
+    ctx = NULL;
+    ret = dcm_create_key_context("a", "a", NULL, &ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(ctx);
+    ret = dcm_free_key_context(ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+
+    ctx = NULL;
+    ret = dcm_create_key_context("a", "b", "UNEXISTING", &ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_SOCKET);
+    BOOST_CHECK(!ctx);
+    ret = dcm_free_key_context(ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
 }
 
-static void test_setup_pk_ctx() {
-    void *ctx = DCM_HWGetKeyContext("a", "b", NULL);
+BOOST_AUTO_TEST_CASE(test02_dcm_get_certificate_chain)
+{
+    void *ctx;
+    char *cert;
+    size_t cert_len;
 
-    int ret = DCM_HWSetupPkContext(NULL, ctx);
-    assert(ret < 0);
+    int ret = dcm_create_key_context("a", "b", NULL, &ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(ctx);
 
-    ret = DCM_HWSetupPkContext(NULL, ctx);
-    assert(ret < 0);
+    ret = dcm_get_certificate_chain(ctx, NULL, &cert_len);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
 
-    mbedtls_pk_context_wrapper pkey;
+    ret = dcm_get_certificate_chain(ctx, &cert, NULL);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
 
-    ret = DCM_HWSetupPkContext(&pkey, NULL);
-    assert(ret < 0);
+    ret = dcm_get_certificate_chain(NULL, &cert, &cert_len);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
 
-    ret = DCM_HWSetupPkContext(&pkey, ctx);
-    assert(ret == 0);
+    ret = dcm_get_certificate_chain(ctx, &cert, &cert_len);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(cert);
+    BOOST_REQUIRE(cert_len > 0);
 
-    DCM_HWFreeKeyContext(ctx);
+    ret = dcm_free_key_context(ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
 
-    std::cout << "DCM_HWSetupPkContext ... OK\n";
+    free(cert);
 }
 
-static int test_general_case() {
-       const char *pers = "hw_api_test";
-
-       mbedtls_entropy_context_wrapper entropy;
-       mbedtls_ctr_drbg_context_wrapper ctr_drbg;
-
-    int error;
-       unsigned char result_sig[MBEDTLS_MPI_MAX_SIZE];
-       size_t result_sig_len;
-
-    if( (error = ctr_drbg.seed(mbedtls_entropy_func, &entropy,
-                               (const unsigned char *) pers,
-                               strlen( pers ))) != 0 )
-    {
-       std::cerr << "Can't seed RNG: " << mbedtls_error_to_string(error) << std::endl;
-               return -1;
-    }
-
-       std::cout << "Create new DCM key context" << std::endl;
-
-       void * keyContext = DCM_HWGetKeyContext("a", "b", "ECDSA");
-
-       if(!keyContext) {
-               std::cerr << "Can't create DCM key context" << std::endl;
-               return -1;
-       }
+BOOST_AUTO_TEST_CASE(test03_dcm_get_key_bit_length)
+{
+    int ret;
+    void *ctx;
+    size_t key_len = 0;
 
-    std::cout << "Initialize PK context" << std::endl;
+    ret = dcm_get_key_bit_length(NULL, &key_len);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
 
-       mbedtls_pk_context_wrapper pkey;
+    ret = dcm_create_key_context("a", "b", "RSA", &ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(ctx);
 
-    if(DCM_HWSetupPkContext(&pkey, keyContext) != 0) {
-       std::cerr << "Can't setup key context" << std::endl;
-        DCM_HWFreeKeyContext(keyContext);
-        return -1;
-    } else {
-       std::cout << "Key context setup OK" << std::endl;
-       std::cout << "Key has " << mbedtls_pk_get_bitlen(&pkey) << " bits" << std::endl;
-    }
+    ret = dcm_get_key_bit_length(ctx, NULL);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
 
-    unsigned char * certChain = nullptr;
-    size_t certChainLen = 0;
+    ret = dcm_get_key_bit_length(ctx, &key_len);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_REQUIRE(key_len > 0);
 
-    mbedtls_x509_crt_wrapper chain;
+    ret = dcm_free_key_context(ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
 
-    if(DCM_HWGetOwnCertificateChain(keyContext, &certChain, &certChainLen)) {
-       std::cerr << "Can't request certificate chain" << std::endl;
-    } else {
-       std::cout << "Certificate received" << std::endl;
+    ctx = NULL;
+    key_len = 0;
+    ret = dcm_create_key_context("a", "b", "ECDSA", &ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(ctx);
 
-       error = chain.parse(certChain, certChainLen);
+    ret = dcm_get_key_bit_length(ctx, &key_len);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_REQUIRE(key_len > 0);
 
-       if(error != 0) {
-               std::cerr << "Can't parse certificate chain: " << mbedtls_error_to_string(error) << std::endl;
-               DCM_HWFreeKeyContext(keyContext);
-               return -1;
-       }
+    ret = dcm_free_key_context(ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+}
 
-       std::cout << "Certificate chain parsed successfuly" << std::endl;
-    }
+BOOST_AUTO_TEST_CASE(test04_dcm_get_key_type)
+{
+    int ret;
+    void *ctx;
+    char *key_type;
+
+    ret = dcm_get_key_type(NULL, &key_type);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
+
+    ret = dcm_create_key_context("a", "b", "RSA", &ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(ctx);
+
+    ret = dcm_get_key_type(ctx, NULL);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
+
+    ret = dcm_get_key_type(ctx, &key_type);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(key_type);
+    BOOST_CHECK(strcmp(key_type, "RSA") == 0);
+
+    ret = dcm_free_key_context(ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    free(key_type);
+
+    ctx = NULL;
+    ret = dcm_create_key_context("a", "b", "ECDSA", &ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(ctx);
+
+    ret = dcm_get_key_type(ctx, &key_type);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(key_type);
+    BOOST_CHECK(strcmp(key_type, "ECDSA") == 0);
+
+    ret = dcm_free_key_context(ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    free(key_type);
+}
 
-       unsigned char to_sign[32];
+BOOST_AUTO_TEST_CASE(test05_dcm_create_signature)
+{
+    int ret;
+    void *ctx;
+    char *signature;
+    size_t signature_len;
+    char data[32];
 
-       mbedtls_ctr_drbg_random(&ctr_drbg, to_sign, sizeof(to_sign));
+    ret = dcm_create_signature(NULL, DCM_DIGEST_SHA256, data, sizeof(data), &signature, &signature_len);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
 
-       std::cout << "Data to sign = ";
-       boost::algorithm::hex(std::begin(to_sign), std::end(to_sign), std::ostream_iterator<char>(std::cout));
-       std::cout << std::endl;
+    ret = dcm_create_key_context("a", "b", "RSA", &ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(ctx);
 
-       if((error = mbedtls_pk_sign(&pkey,
-                       MBEDTLS_MD_SHA256,
-                       to_sign,
-                       sizeof(to_sign),
-                       result_sig,
-                       &result_sig_len,
-                       mbedtls_ctr_drbg_random, &ctr_drbg)) != 0)
-       {
-               std::cerr << "Can't sign data with key: " << mbedtls_error_to_string(error) << std::endl;
-           DCM_HWFreeKeyContext(keyContext);
-           return -1;
-       }
+    ret = dcm_create_signature(ctx, DCM_DIGEST_SHA256, data, sizeof(data), NULL, &signature_len);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
 
-       std::cout << "Signature = ";
+    ret = dcm_create_signature(ctx, DCM_DIGEST_SHA256, data, sizeof(data), &signature, NULL);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
 
-       boost::algorithm::hex(result_sig, result_sig + result_sig_len, std::ostream_iterator<char>(std::cout));
+    std::cout << "Data to sign = ";
+    boost::algorithm::hex(std::begin(data), std::end(data), std::ostream_iterator<char>(std::cout));
+    std::cout << std::endl;
 
-       std::cout << std::endl;
+    ret = dcm_create_signature(ctx, DCM_DIGEST_SHA256, data, sizeof(data), &signature, &signature_len);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
+    BOOST_CHECK(signature);
+    BOOST_REQUIRE(signature_len > 0);
 
-       // Verify signature
-       std::cout << "Verifying signature ..." << std::endl;
+    std::cout << "Signature = ";
+    boost::algorithm::hex(signature, signature + signature_len, std::ostream_iterator<char>(std::cout));
+    std::cout << std::endl;
 
-       if((error = mbedtls_pk_verify_ext(chain.sig_pk,
-                       chain.sig_opts,
-                       &chain.pk,
-                       MBEDTLS_MD_SHA256,
-                       to_sign,
-                       sizeof(to_sign),
-                       result_sig,
-                       result_sig_len)) != 0)
-       {
-               std::cout << "Signature verification failure : " << mbedtls_error_to_string(error) << std::endl;
-       } else {
-               std::cout << "Signature verification succeeded" << std::endl;
-       }
-
-    std::cout << "Deleting HW context" << std::endl;
-    DCM_HWFreeKeyContext(keyContext);
-
-    std::cout << "Testing general usecase ... OK" << std::endl;
-    return 0;
-}
+    ret = dcm_free_key_context(ctx);
+    BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
 
-int main()
-{
-    test_key_context_creation();
-    test_get_own_cert_chain();
-    test_setup_pk_ctx();
-    return test_general_case();
+    free(signature);
 }