ADD_SUBDIRECTORY(src/dcm-client)
ADD_SUBDIRECTORY(src/dcm-daemon)
ADD_SUBDIRECTORY(pkgconfig)
-ADD_SUBDIRECTORY(rpm)
ADD_SUBDIRECTORY(systemd)
ADD_SUBDIRECTORY(tests)
-#Device Certificate Manager
+# Device Certificate Manager
-##About
+## About
The Device Certificate Manager (DCM) provides cryptography services (digital certificates and keys) for authentication and secure communication with another system.
Please visit the following webpage for the details about the prerequsities and the usage: [https://docs.tizen.org/application/native/guides/security/device-certificate-manager](https://docs.tizen.org/application/native/guides/security/device-certificate-manager).
-##Architecture
+## Architecture
The DCM (tizen.org repository *platform/core/security/device-certificate-manager*) consists of two submodules: the client and the daemon.
The client provides the public DCM API, while the daemon its implementation.
-The implementation is realized with the internal backend API (see the *src/dcm-daemon/dcm-backend-api.h* header file).
-Example implementation of this backend API may be found in the tizen.org separate repository: *platform/core/security/device-certificate-manager-backend*.
-The DCM backend repository provides dummy implementation based on the OpenSSL and dedicated mainly for the testing purposes.
+The implementation is realized with the external backend HAL API (see the *platform/hal/api/security* security-certs header files, for existing functions).
+Example implementation of this backend API may be found in the tizen.org separate repository: *platform/hal/backend/emulator/security-certs*.
+The security-certs backend repository provides example implementation based on the OpenSSL and dedicated mainly for the testing purposes.
-Backend is packed to the rpm device-certificate-manager-backend-dummy package, that provide the *libdcm-backend-api.so* library with the DCM backend API implementation.
+Backend is packed to the hal-backend-security-certs rpm package, that provides the *libhal-backend-security-certs.so* library with the Security Certs backend API implementation.
The library is loaded dynamically by the DCM daemon at runtime.
-Although the DCM backend is not installed automatically with the DCM, it is required for proper work of the DCM and because of that it must be installed manually.
-Alternatively, the specific Tizen image may be configured to contain the chosen backend.
+It is required for proper work of the DCM.
-##Adding a new backend (a new SE device)
+## Adding a new backend (a new SE device)
-In order to support a new SE device in the DCM, a new backend API implementation must be developed, which means that the plugin developer must provide the implemenation of the plugin header (*src/dcm-daemon/dcm-backend-api.h*).
-Such an implementation may be based on the dummy implementation from the *platform/core/security/device-certificate-manager-backend* repository.
+In order to support a new SE device in the DCM, a new backend API implementation must be developed, which means that the plugin developer must provide the implemenation of the plugin header (*hal-security-certs.h* from *platform/hal/api/security* repository).
+Such an implementation may be based on the example implementation from the *platform/hal/backend/emulator/security-certs* repository.
The new implementation may be added to this public repository or provided in the separate git repository.
-The most important item is to implement the *libdcm-backend-api.so* library and to install it in the system.
+The most important item is to implement the *libhal-backend-security-certs.so* library and to install it in the system.
The DCM daemon does not need to be modified.
-##Testing
+## Testing
There is currently one general testing application:
- *device-certificate-manager-tests*
Testing application should be executed after implementing changes to the DCM or to the DCM backend repository.
BuildRequires: pkgconfig(cynara-creds-socket)
BuildRequires: pkgconfig(cynara-session)
BuildRequires: pkgconfig(capi-system-info)
+BuildRequires: pkgconfig(hal-api-security)
BuildRequires: boost-devel
%if "%{build_type}" == "COVERAGE"
BuildRequires: lcov
%description -n device-certificate-manager-ext-devel
Device Certificate Manager development headers and libraries only for extension of the API
-%package -n device-certificate-manager-backend-devel
-Summary: Device Certificate Manager backend (development)
-Group: Security/Development
-
-%description -n device-certificate-manager-backend-devel
-Device Certificate Manager backend development header
-
%package -n device-certificate-manager-tests
Summary: Internal tests for Device Certificate Manager
Group: Security/Testing
BuildRequires: pkgconfig(security-manager)
Requires: device-certificate-manager = %{version}-%{release}
Requires: boost-test
+Requires(post): /usr/bin/system-info-tool
+Requires(postun): /usr/bin/system-info-tool
%description -n device-certificate-manager-tests
Internal tests for Device Certificate Manager
-DUSER_NAME=%{user_name} \
-DGROUP_NAME=%{group_name} \
-DSMACK_DOMAIN_NAME=%{smack_domain_name} \
- -DRPM_DIR=%{_sysconfdir}/rpm \
-DCOVERAGE_DIR=%{coverage_dir}
make
systemctl daemon-reload
fi
+%post -n device-certificate-manager-tests
+
+/usr/bin/system-info-tool -s tizen.org/feature/security.device_certificate bool 1
+
+%postun -n device-certificate-manager-tests
+
+if [ $1 = 0 ]; then
+ /usr/bin/system-info-tool -s tizen.org/feature/security.device_certificate bool 0
+fi
+
%files
%manifest %{name}.manifest
%license LICENSE
%{_includedir}/device-certificate-manager/device_certificate_manager_ext_types.h
%{_libdir}/pkgconfig/device-certificate-manager-ext.pc
-%files backend-devel
-%manifest %{name}.manifest
-%license LICENSE
-%{_includedir}/device-certificate-manager-backend/dcm-backend-api.h
-%{_includedir}/device-certificate-manager-backend/dcm-ext-backend-api.h
-%{_includedir}/device-certificate-manager-backend/dcm_support.pb.h
-%{_libdir}/pkgconfig/device-certificate-manager-backend.pc
-%{_sysconfdir}/rpm/macros.dcm-backend-api
-
%files tests
%manifest %{name}.manifest
%license LICENSE
CONFIGURE_FILE(device-certificate-manager.pc.in device-certificate-manager.pc @ONLY)
CONFIGURE_FILE(device-certificate-manager-ext.pc.in device-certificate-manager-ext.pc @ONLY)
-CONFIGURE_FILE(device-certificate-manager-backend.pc.in device-certificate-manager-backend.pc @ONLY)
INSTALL(FILES
${CMAKE_CURRENT_BINARY_DIR}/device-certificate-manager.pc
${CMAKE_CURRENT_BINARY_DIR}/device-certificate-manager-ext.pc
- ${CMAKE_CURRENT_BINARY_DIR}/device-certificate-manager-backend.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
+++ /dev/null
-prefix=@CMAKE_INSTALL_PREFIX@
-exec_prefix=${prefix}
-libdir=@CMAKE_INSTALL_FULL_LIBDIR@
-includedir=${prefix}/include
-
-Name: device-certificate-manager-backend
-Description: Device Certificate Manager Backend Package
-Version: @PROJECT_VERSION@
-Requires: protobuf-lite
-Cflags: -I${includedir}/device-certificate-manager-backend
+++ /dev/null
-# Copyright (c) 2019 - 2020 Samsung Electronics Co., Ltd All Rights Reserved
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# @file rpm/CMakeLists.txt
-# @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
-#
-
-CONFIGURE_FILE(macros.dcm-backend-api.in macros.dcm-backend-api @ONLY)
-
-INSTALL(FILES
- ${CMAKE_CURRENT_BINARY_DIR}/macros.dcm-backend-api
- DESTINATION ${RPM_DIR})
+++ /dev/null
-# RPM macros for package device-certificate-manager
-
-%dcm_backend_api() %(echo dcm-backend-api)
INSTALL(TARGETS ${TARGET_CLIENT} ${TARGET_CLIENT_EXT}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
-
-INSTALL(FILES
- ${CMAKE_CURRENT_BINARY_DIR}/dcm_support.pb.h
- DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/device-certificate-manager-backend)
PKG_CHECK_MODULES(DAEMON_DEPS
REQUIRED
+ hal-api-security
libsystemd
cynara-client
cynara-creds-socket
dcm_session.cpp
../shared/protobuf_asio.cpp
../shared/log.cpp
- soresolver.cpp
${PROTO_SRCS}
${PROTO_HDRS})
INSTALL(TARGETS ${TARGET_DAEMON}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-
-INSTALL(FILES
- dcm-backend-api.h
- dcm-ext-backend-api.h
- DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/device-certificate-manager-backend)
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2019 - 2020 Samsung Electronics All Rights Reserved.
- *
- * Author: Pawel Kowalski <p.kowalski2@partner.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_BACKEND_API_H_
-#define DCM_BACKEND_API_H_
-
-#include "dcm_support.pb.h"
-
-#ifndef API_DCM_BACKEND_EXPORT
-#define API_DCM_BACKEND_EXPORT __attribute__((visibility("default")))
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct dcm_backend_context {
- void* backend;
-};
-
-API_DCM_BACKEND_EXPORT
-void dcm_backend_create_key_context(dcm_backend_context& ctx,
- const std::string& keyType);
-
-API_DCM_BACKEND_EXPORT
-void dcm_backend_free_key_context(dcm_backend_context& ctx);
-
-API_DCM_BACKEND_EXPORT
-int dcm_backend_request_certificate_chain(dcm_backend_context& ctx,
- std::string& chain);
-
-API_DCM_BACKEND_EXPORT
-int dcm_backend_sign_crypto_data(dcm_backend_context& ctx,
- MessageDigestType digestType,
- const std::string& dataToSign,
- std::string& digestResult);
-
-API_DCM_BACKEND_EXPORT
-CryptoKeyType dcm_backend_key_type(dcm_backend_context& ctx);
-
-API_DCM_BACKEND_EXPORT
-unsigned int dcm_backend_key_length(dcm_backend_context& ctx);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* DCM_BACKEND_API_H_ */
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2021 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 DCM_EXT_BACKEND_API_H_
-#define DCM_EXT_BACKEND_API_H_
-
-#ifndef API_DCM_EXT_BACKEND_EXPORT
-#define API_DCM_EXT_BACKEND_EXPORT __attribute__((visibility("default")))
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Calls relevant method/functionality in the backend.
- * Returns 0 in case of success or other code in case of error.
- *
- * If the backend developers wish to return backend-specific
- * error code to the caller that uses the DCM EXT client libary,
- * it should be implemented by returning 0 from function below
- * and returning custom information/data in output_data.
- *
- * This function should not throw exceptions.
- */
-API_DCM_EXT_BACKEND_EXPORT
-int dcm_ext_backend_call_api(const std::string& method_name,
- const std::string& input_data,
- std::string& output_data);
-
-/*
- * Returns the privilege that should be checked by Cynara in order for
- * DCM daemon to allow a client call to the method_name method/functionality.
- * Can return emtpy string in case no privilege guards access to the method.
- * Returns 0 in case of success or other code in case of error.
- *
- * This function should not throw exceptions.
- *
- * Nonzero error code returned by function will be treated as invalid
- * method name (and returned to DCM EXT client as invalid parameter error).
- */
-API_DCM_EXT_BACKEND_EXPORT
-int dcm_ext_backend_get_api_privilege(const std::string& method_name,
- std::string& privilege);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* DCM_EXT_BACKEND_API_H_ */
#include "dcm_session.h"
#include "log.h"
+#include <hal/hal-security-certs.h>
+
dcm_server::dcm_server(boost::asio::io_service& io_service,
boost::asio::local::stream_protocol::acceptor&& acceptor) :
fService(io_service),
fTimer(io_service),
- fAcceptor(std::move(acceptor)),
- fSoResolver(std::make_shared<so_resolver>())
+ fAcceptor(std::move(acceptor))
{
LOGD("Construct server object");
LOGE("Can't initialize Cynara instance: " << error);
throw std::runtime_error("Can't initialize Cynara instance");
}
+
+ error = hal_security_certs_get_backend();
+ if (error) {
+ LOGE("Can't get DCM backend: " << error);
+ throw std::runtime_error("Can't get DCM backend");
+ }
}
dcm_server::~dcm_server()
{
+ hal_security_certs_put_backend();
cynara_finish(fCynaraInstance);
LOGD("Destroy server object");
}
std::shared_ptr<dcm_session> session;
try {
- session = std::make_shared<dcm_session>(fService, shared_from_this(),
- fSoResolver, fCynaraInstance);
+ session = std::make_shared<dcm_session>(fService, shared_from_this(), fCynaraInstance);
} catch(std::bad_alloc& ex) {
LOGE("Out of memory when trying to allocate new session");
return;
#include <boost/noncopyable.hpp>
#include <cynara-client.h>
-#include "soresolver.h"
-
class dcm_server final : public boost::noncopyable, public std::enable_shared_from_this<dcm_server> {
public:
dcm_server(boost::asio::io_service& io_service,
boost::asio::io_service& fService;
boost::asio::deadline_timer fTimer;
boost::asio::local::stream_protocol::acceptor fAcceptor;
- std::shared_ptr<so_resolver> fSoResolver;
cynara* fCynaraInstance;
unsigned int fSessionCounter = 0;
};
#include "device_certificate_manager.h"
#include "log.h"
+#include <hal/hal-security-certs.h>
+
#define DCM_DEFAULT_PRIVILEGE "http://tizen.org/privilege/devicecertificate"
+struct string_free_deleter {
+ void operator()(char * p) const {
+ free(p);
+ }
+};
+
+struct data_free_deleter {
+ void operator()(hal_security_certs_data_s* p) const {
+ if (p->buffer)
+ free(p->buffer);
+ delete p;
+ }
+};
+
+using security_certs_data_ptr = std::unique_ptr<hal_security_certs_data_s, data_free_deleter>;
+
+dcm_error_e backend_to_dcm_error(int error) {
+ switch (error) {
+ case -EINVAL:
+ return DCM_ERROR_INVALID_PARAMETER;
+ case -ENOMEM:
+ return DCM_ERROR_OUT_OF_MEMORY;
+ case -EACCES:
+ return DCM_ERROR_PERMISSION_DENIED;
+ case -ENODATA:
+ return DCM_ERROR_NO_DATA;
+ default:
+ return DCM_ERROR_UNKNOWN;
+ }
+}
+
+dcm_ext_error_e backend_to_dcm_ext_error(int error) {
+ switch (error) {
+ case -EINVAL:
+ return DCM_EXT_ERROR_INVALID_PARAMETER;
+ case -ENOMEM:
+ return DCM_EXT_ERROR_OUT_OF_MEMORY;
+ case -EACCES:
+ return DCM_EXT_ERROR_PERMISSION_DENIED;
+ case -ENOTSUP:
+ return DCM_EXT_ERROR_NOT_SUPPORTED;
+ default:
+ return DCM_EXT_ERROR_UNKNOWN;
+ }
+}
+
dcm_session::dcm_session(boost::asio::io_service& io_service,
const std::shared_ptr<dcm_server>& server,
- std::shared_ptr<so_resolver> soResolver,
cynara* cynaraInstance) :
fSocket(io_service),
fServer(server),
- fSoResolver(soResolver),
fCynaraInstance(cynaraInstance)
{
LOGD("Create new session object " << this);
}
}
-struct string_free_deleter {
- void operator()(char * p) const {
- free(p);
- }
-};
+template <typename context, typename error>
+void dcm_session::reply_error(ResponseMessage& msg, context& ctx, error err, std::string error_msg) {
+ LOGE(error_msg);
+ ctx->set_result(err);
+ reply(msg);
+}
static inline std::string cynara_error_to_string(int error) {
char buffer[256];
{
LOGD("Associate context");
- if(!verify_privileges(fSocket.native_handle(), DCM_DEFAULT_PRIVILEGE)) {
+ if (!verify_privileges(fSocket.native_handle(), DCM_DEFAULT_PRIVILEGE)) {
LOGE("Client privilege check failure. Disconnect");
return;
}
+ int error;
ResponseMessage msg;
auto* contextResponse = msg.mutable_associate_context();
- if(fBackendContext) {
- contextResponse->set_result(EEXIST);
- reply(msg);
+ if (fBackendContext) {
+ reply_error(msg, contextResponse, EEXIST,
+ "Backend context already exists");
return;
}
" with usage " << message.usage() << " and key type " << message.key_type());
auto server = fServer.lock();
- if(!server) {
+ if (!server) {
LOGE("Server object gone while handling message");
return;
}
- int error = 0;
try {
- fBackendContext = std::unique_ptr<dcm_backend_context>(new dcm_backend_context);
-
- fSoResolver->invoke<void, dcm_backend_context&, const std::string&>(
- "dcm_backend_create_key_context", *fBackendContext, message.key_type());
+ fBackendContext = std::unique_ptr<hal_security_certs_context_s>(new hal_security_certs_context_s);
+ } catch (std::bad_alloc&) {
+ reply_error(msg, contextResponse, backend_to_dcm_error(-ENOMEM),
+ "Out of memory when allocating memory for backend context");
+ return;
+ }
- CryptoKeyType crypto_key_type = fSoResolver->invoke<CryptoKeyType, dcm_backend_context&>(
- "dcm_backend_key_type", *fBackendContext);
- contextResponse->set_key_type(crypto_key_type);
+ hal_security_certs_data_s key_type_data =
+ {(char*)message.key_type().c_str(), message.key_type().size()};
+ error = hal_security_certs_create_key_context(fBackendContext.get(), key_type_data);
+ if (error) {
+ reply_error(msg, contextResponse, backend_to_dcm_error(error),
+ "Creating key context failed");
+ return;
+ }
- unsigned int crypto_key_length = fSoResolver->invoke<unsigned int, dcm_backend_context&>(
- "dcm_backend_key_length", *fBackendContext);
- contextResponse->set_key_length(crypto_key_length);
+ hal_security_certs_crypto_key_type_e key_type;
+ error = hal_security_certs_get_key_type(fBackendContext.get(), &key_type);
+ if (error) {
+ reply_error(msg, contextResponse, backend_to_dcm_error(error),
+ "Can't get key type");
+ return;
+ }
+ contextResponse->set_key_type((CryptoKeyType)key_type);
- fCookie = (uintptr_t)fBackendContext.get();
- contextResponse->set_context_cookie(fCookie);
- } catch(std::bad_alloc&) {
- error = -ENOMEM;
- } catch(std::exception&) {
- error = -EINVAL;
- } catch(...) {
- error = -EFAULT;
+ unsigned int key_length;
+ error = hal_security_certs_get_key_bit_length(fBackendContext.get(), &key_length);
+ if (error) {
+ reply_error(msg, contextResponse, backend_to_dcm_error(error),
+ "Can't get key length");
+ return;
}
- contextResponse->set_result(error);
+ contextResponse->set_key_length(key_length);
+ fCookie = (uintptr_t)fBackendContext.get();
+ contextResponse->set_context_cookie(fCookie);
+ contextResponse->set_result(0);
reply(msg);
}
{
LOGD("Request certificate chain");
- if(!verify_privileges(fSocket.native_handle(), DCM_DEFAULT_PRIVILEGE)) {
+ if (!verify_privileges(fSocket.native_handle(), DCM_DEFAULT_PRIVILEGE)) {
LOGE("Client privilege check failure. Disconnect");
return;
}
+ int error;
ResponseMessage msg;
auto* certificateResponse = msg.mutable_request_chain();
- if(message.context_cookie() != fCookie) {
- LOGE("Received unknown context cookie");
- certificateResponse->set_result(-EINVAL);
- reply(msg);
+ if (message.context_cookie() != fCookie) {
+ reply_error(msg, certificateResponse, backend_to_dcm_error(-EINVAL),
+ "Received unknown context cookie");
return;
}
- if(!fBackendContext) {
- LOGE("Context not associated with connection");
- certificateResponse->set_result(-EINVAL);
- reply(msg);
+ if (!fBackendContext) {
+ reply_error(msg, certificateResponse, backend_to_dcm_error(-EINVAL),
+ "Context not associated with connection");
return;
}
- std::string cert_chain;
+ try {
+ security_certs_data_ptr cert_chain(new hal_security_certs_data_s);
+ error = hal_security_certs_request_certificate_chain(fBackendContext.get(), cert_chain.get());
+ if (error) {
+ reply_error(msg, certificateResponse, backend_to_dcm_error(error),
+ "Failed requesting certificate chain");
+ return;
+ }
+
+ if (cert_chain->buffer != NULL && cert_chain->length >= sPEMHeader.length() &&
+ !memcmp(sPEMHeader.c_str(), cert_chain->buffer, sPEMHeader.size()) &&
+ cert_chain->buffer[cert_chain->length - 1] != '\0')
+ {
+ // Add missing 0
+ char* new_buffer = static_cast<char*>(realloc(cert_chain->buffer, cert_chain->length + 1));
+ if (new_buffer == NULL) {
+ reply_error(msg, certificateResponse, backend_to_dcm_error(-ENOMEM),
+ "Failed reallocating memory for certificate chain");
+ return;
+ }
- int error = fSoResolver->invoke<int, dcm_backend_context&, std::string&>(
- "dcm_backend_request_certificate_chain", *fBackendContext, cert_chain);
+ cert_chain->buffer = new_buffer;
+ cert_chain->length = cert_chain->length + 1;
+ strncat(cert_chain->buffer, "\0", 1);
+ }
- if(error != 0) {
- certificateResponse->set_result(error);
+ *certificateResponse->mutable_cert_chain() = std::string(cert_chain->buffer, cert_chain->length);
+ certificateResponse->set_result(0);
reply(msg);
+ } catch (std::bad_alloc&) {
+ reply_error(msg, certificateResponse, backend_to_dcm_error(-ENOMEM),
+ "Out of memory when allocating memory for output certificate chain");
return;
}
-
- if(cert_chain.length() >= sPEMHeader.length() &&
- !memcmp(sPEMHeader.c_str(), cert_chain.c_str(), sPEMHeader.size()) &&
- cert_chain[cert_chain.size() - 1] != '\0')
- {
- // Add missing 0
- cert_chain.push_back(0);
- }
-
- *certificateResponse->mutable_cert_chain() = cert_chain;
- certificateResponse->set_result(0);
- reply(msg);
}
int dcm_session::sign_request_check(const SignRequest& message)
return true;
}
-int dcm_session::sign(
- MessageDigestType digest_type,
- const std::string& message,
- std::string& signature)
-{
- return fSoResolver->invoke<int, dcm_backend_context&, MessageDigestType, const std::string&, std::string&>(
- "dcm_backend_sign_crypto_data", *fBackendContext, digest_type, message, signature);
-}
-
void dcm_session::handle_sign_request(const SignRequest& message)
{
LOGD("Request data signing");
- if(!verify_privileges(fSocket.native_handle(), DCM_DEFAULT_PRIVILEGE)) {
+ if (!verify_privileges(fSocket.native_handle(), DCM_DEFAULT_PRIVILEGE)) {
LOGE("Client privilege check failure. Disconnect");
return;
}
- int ret;
+ int error;
ResponseMessage msg;
auto* signingResponse = msg.mutable_sign_data();
- if (!sign_request_check(message)) {
- ret = -EINVAL;
- } else {
- ret = sign(
- message.digest_type(), message.data_to_sign(), *signingResponse->mutable_signature());
- if (ret != 0)
- LOGE("Signing failed");
- }
- signingResponse->set_result(ret);
- reply(msg);
+
+ try {
+ security_certs_data_ptr signature(new hal_security_certs_data_s);
+ if (!sign_request_check(message)) {
+ reply_error(msg, signingResponse, backend_to_dcm_error(-EINVAL),
+ "Sign request check failed");
+ return;
+ } else {
+ hal_security_certs_data_s message_data =
+ {(char*)message.data_to_sign().c_str(), message.data_to_sign().size()};
+ error = hal_security_certs_sign_crypto_data(fBackendContext.get(),
+ (hal_security_certs_digest_type_e)message.digest_type(),
+ message_data, signature.get());
+ if (error) {
+ reply_error(msg, signingResponse, backend_to_dcm_error(error),
+ "Signing failed");
+ return;
+ }
+ }
+
+ *signingResponse->mutable_signature() = std::string(signature->buffer, signature->length);
+ signingResponse->set_result(0);
+ reply(msg);
+ } catch (std::bad_alloc&) {
+ reply_error(msg, signingResponse, backend_to_dcm_error(-ENOMEM),
+ "Out of memory when allocating memory for output signature");
+ return;
+ }
}
void dcm_session::handle_ext_call_request(const ExtCallRequest& message)
{
LOGD("Request EXT API call from backend");
+
+ int error;
ResponseMessage msg;
auto* extCallResponse = msg.mutable_ext_call();
- std::string privilege;
try {
- if(fSoResolver->invoke<int, const std::string&, std::string&>(
- "dcm_ext_backend_get_api_privilege", message.method_name(), privilege)) {
- LOGE("Invalid method name for EXT API call - method name: " << message.method_name());
- extCallResponse->set_result(DCM_EXT_ERROR_INVALID_PARAMETER);
- reply(msg);
+ hal_security_certs_data_s method_name =
+ {(char*)message.method_name().c_str(), message.method_name().size()};
+ security_certs_data_ptr privilege(new hal_security_certs_data_s{nullptr, 0});
+
+ error = hal_security_certs_ext_get_api_privilege(method_name, privilege.get());
+ if (error == -EINVAL) {
+ reply_error(msg, extCallResponse, backend_to_dcm_ext_error(error),
+ "Invalid method name for EXT API call - method name: " + message.method_name());
+ return;
+ } else if (error == -ENOTSUP) {
+ reply_error(msg, extCallResponse, backend_to_dcm_ext_error(error),
+ "Couldn't call backend EXT API - backend doesn't support this functionality");
return;
}
- } catch (std::runtime_error&) {
- LOGE("Couldn't call backend EXT API - backend doesn't support this functionality");
- extCallResponse->set_result(DCM_EXT_ERROR_NOT_SUPPORTED);
- reply(msg);
- return;
- }
- if(!privilege.empty()) {
- if(!verify_privileges(fSocket.native_handle(), privilege.c_str())) {
- LOGE("Client privilege check failure - access denied for method " << message.method_name()
- << " and privilege " << privilege);
- extCallResponse->set_result(DCM_EXT_ERROR_PERMISSION_DENIED);
- reply(msg);
- return;
+ if (privilege->buffer != NULL) {
+ std::string privilegeStr(privilege->buffer, privilege->length);
+ if (!verify_privileges(fSocket.native_handle(), privilegeStr.c_str())) {
+ reply_error(msg, extCallResponse, DCM_EXT_ERROR_PERMISSION_DENIED,
+ "Client privilege check failure - access denied for method " +
+ message.method_name() + " and privilege " + privilegeStr);
+ return;
+ }
+ } else {
+ LOGD("Access to method " << message.method_name() << " granted, no privilege check required");
}
- } else {
- LOGD("Access to method " << message.method_name() << " granted, no privilege check required");
- }
- try {
- int error = fSoResolver->invoke<int, const std::string&, const std::string&, std::string&>(
- "dcm_ext_backend_call_api", message.method_name(), message.input_data(), *extCallResponse->mutable_output_data());
+ hal_security_certs_data_s input_data =
+ {(char*)message.input_data().c_str(), message.input_data().size()};
+ security_certs_data_ptr output_data(new hal_security_certs_data_s{nullptr, 0});
- if(error) {
- LOGE("Error in dcm_ext_backend_call_api for method " << message.method_name() << " , error: " << error);
+ error = hal_security_certs_ext_call_api(method_name, input_data, output_data.get());
+ if (error == -EINVAL) {
+ reply_error(msg, extCallResponse, backend_to_dcm_ext_error(error),
+ "Error in hal_security_certs_ext_call_api for method " +
+ message.method_name() + " , error: " + std::to_string(error));
+ return;
+ } else if (error == -ENOTSUP) {
+ reply_error(msg, extCallResponse, backend_to_dcm_ext_error(error),
+ "Couldn't call backend EXT API - backend doesn't support this functionality");
+ return;
+ } else {
+ *extCallResponse->mutable_output_data() = std::string(output_data->buffer, output_data->length);
+ extCallResponse->set_result(0);
}
- extCallResponse->set_result(error ? DCM_EXT_ERROR_UNKNOWN : DCM_EXT_ERROR_NONE);
- } catch (std::runtime_error&) {
- LOGE("Couldn't call backend EXT API - backend doesn't support this functionality");
- extCallResponse->set_result(DCM_EXT_ERROR_NOT_SUPPORTED);
+
+ reply(msg);
+ } catch (std::bad_alloc&) {
+ reply_error(msg, extCallResponse, backend_to_dcm_ext_error(-ENOMEM),
+ "Out of memory when allocating memory for output data");
}
- reply(msg);
}
void dcm_session::handle_close_context(const CloseKeyContext& message)
auto* closeResponse = msg.mutable_close_context();
if(message.context_cookie() != fCookie) {
- LOGE("Received unknown context cookie");
- closeResponse->set_result(-EINVAL);
- reply(msg);
+ reply_error(msg, closeResponse, backend_to_dcm_error(-EINVAL),
+ "Received unknown context cookie");
return;
}
if(!fBackendContext) {
- LOGE("Context not associated with connection");
- closeResponse->set_result(-EINVAL);
- reply(msg);
+ reply_error(msg, closeResponse, backend_to_dcm_error(-EINVAL),
+ "Context not associated with connection");
return;
}
- int error = 0;
- try {
- fSoResolver->invoke<void, dcm_backend_context&>(
- "dcm_backend_free_key_context", *fBackendContext);
- } catch(std::bad_alloc&) {
- error = -ENOMEM;
- } catch(std::exception&) {
- error = -EINVAL;
- } catch(...) {
- error = -EFAULT;
- }
-
- closeResponse->set_result(error);
+ closeResponse->set_result(hal_security_certs_free_key_context(fBackendContext.get()));
reply(msg);
}
#include "dcm_support.pb.h"
#include "protobuf_asio.h"
-#include "dcm-backend-api.h"
-#include "soresolver.h"
+
+#include <hal/hal-security-certs-types.h>
class dcm_server;
public:
dcm_session(boost::asio::io_service& io_service,
const std::shared_ptr<dcm_server>& server,
- std::shared_ptr<so_resolver> soResolver,
cynara* cynaraInstance);
~dcm_session();
void handle_ext_call_request(const ExtCallRequest& message);
void handle_close_context(const CloseKeyContext& message);
- int sign(MessageDigestType digest_type, const std::string& message, std::string& signature);
int sign_request_check(const SignRequest& message);
+ template <typename context, typename error>
+ void reply_error(ResponseMessage& msg, context& ctx, error err, std::string error_msg);
+
private:
boost::asio::local::stream_protocol::socket fSocket;
protobuf_async_message_serialization fSerializer;
protobuf_async_message_deserialization fDeserializer;
std::weak_ptr<dcm_server> fServer;
- std::shared_ptr<dcm_backend_context> fBackendContext;
- std::shared_ptr<so_resolver> fSoResolver;
+ std::shared_ptr<hal_security_certs_context_s> fBackendContext;
uint64_t fCookie = 0;
cynara* fCynaraInstance;
};
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2017 - 2020 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 <dlfcn.h>
-
-#include "soresolver.h"
-#include "log.h"
-
-so_resolver::so_resolver()
-{
- LOGD("Loading library " << fLibraryName);
-
- fLibraryHandle = dlopen(fLibraryName.c_str(), RTLD_LAZY | RTLD_LOCAL);
- if(!fLibraryHandle) {
- LOGE("Unable to load library " << fLibraryName << ": " << dlerror());
- throw std::runtime_error("Unable to load backend");
- }
-
- LOGD("Library loaded " << fLibraryName);
-}
-
-so_resolver::~so_resolver()
-{
- LOGD("Unloading library " << fLibraryName);
- dlclose(fLibraryHandle);
- LOGD("Unloaded library " << fLibraryName);
-}
-
-void* so_resolver::resolve_function(const std::string& name) noexcept
-{
- LOGD("Resolving symbol " << name << " from " << fLibraryName);
- void* sym = dlsym(fLibraryHandle, name.c_str());
- if(!sym) {
- LOGE("Unable to resolve symbol " << name << " from " << fLibraryName << ": Error is " << dlerror());
- }
- return sym;
-}
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2017 - 2020 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_DAEMON_SORESOLVER_H_
-#define DCM_DAEMON_SORESOLVER_H_
-
-#include <string>
-#include <stdexcept>
-
-#include <boost/noncopyable.hpp>
-
-#define DCM_BACKEND "libdcm-backend-api.so"
-
-class so_resolver : public boost::noncopyable {
-public:
- so_resolver();
- ~so_resolver();
-
- void* resolve_function(const std::string& name) noexcept;
-
- template<typename ReturnValue, typename... Args> ReturnValue invoke(const std::string& name, Args... args) {
- typedef ReturnValue (* function_t)(Args...);
- function_t func = (function_t)resolve_function(name);
- if(!func) {
- throw std::runtime_error("Trying to call unresolved function");
- }
- return func(args...);
- }
-
-private:
- std::string fLibraryName = DCM_BACKEND;
- void* fLibraryHandle = nullptr;
-};
-
-#endif /* DCM_DAEMON_SORESOLVER_H_ */
/**
* @platform
- * @brief Calls dcm_ext_backend_call_api in the DCM backend with specified method name & arguments.
+ * @brief Calls hal_security_certs_ext_call_api in the DCM backend with specified method name & arguments.
* @since_tizen 6.5
* @privlevel platform
* @privilege custom one, defined by the backend for given method call