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)
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_
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})
###### 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
/*!
* 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,
+++ /dev/null
-/******************************************************************
- *
- * 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;
-}
+++ /dev/null
-/******************************************************************
- *
- * 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_ */
/******************************************************************
*
- * 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
#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 {
#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());
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
#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 {
#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;
}
/*
#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);
#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);
#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;
}
}
#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());
#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();
#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());
#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 {
--- /dev/null
+/******************************************************************
+ *
+ * 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;
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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__ */
-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:
*;
};
#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
--- /dev/null
+/******************************************************************
+ *
+ * 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__ */
%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
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")
--- /dev/null
+#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;
+}
-#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);
}