SET(TARGET_CLIENT "device-certificate-manager")
ADD_LIBRARY(${TARGET_CLIENT}
SHARED
- dcmclient.cpp
+ dcm_client.cpp
device_certificate_manager.cpp
../shared/protobuf_asio.cpp
${PROTO_SRCS}
* limitations under the License.
*
******************************************************************/
+#define LOG_TAG "DCM_CLIENT"
-#include "dcm_client_p.h"
-#include "dcm_support.pb.h"
-#include "device_certificate_manager.h"
#include <cassert>
+#include <inttypes.h>
+
#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>
-
-#define LOG_TAG "DCM_CLIENT"
#include <dlog.h>
+#include "dcm_client.h"
+#include "dcm_support.pb.h"
+#include "device_certificate_manager.h"
+#include "protobuf_asio.h"
+
static_assert(MD_NONE == (unsigned int)MBEDTLS_MD_NONE, "MBEDTLS_MD_NONE mismatch");
static_assert(MD_MD2 == (unsigned int)MBEDTLS_MD_MD2, "MBEDTLS_MD_MD2 mismatch");
static_assert(MD_MD4 == (unsigned int)MBEDTLS_MD_MD4, "MBEDTLS_MD_MD4 mismatch");
static std::string sKeyTypeRSA("RSA");
static std::string sKeyTypeECDSA("ECDSA");
-dcm_client_connection_impl::dcm_client_connection_impl()
-{
-}
-
-dcm_client_connection_impl::~dcm_client_connection_impl()
-{
-}
-
-dcm_client_connection::dcm_client_connection()
-{
-}
-
-dcm_client_connection::~dcm_client_connection()
-{
-}
-
std::shared_ptr<dcm_client_connection> dcm_client_connection::create()
{
- return std::make_shared<dcm_client_connection_impl>();
+ return std::make_shared<dcm_client_connection>();
}
-void dcm_client_connection_impl::sendReceive(RequestMessage& request, ResponseMessage& response)
-{
- protobuf_sync_message_serialization(*fSocket).encodeMessage(request);
- protobuf_sync_message_deserialization(*fSocket).decodeMessage(response);
-}
-
-bool dcm_client_connection_impl::create_context(const std::string& serviceName,
- const std::string& usage,
- const std::string& key_type) noexcept
+int dcm_client_connection::create_context(
+ const std::string& service_name,
+ const std::string& usage,
+ const std::string& key_type) noexcept
{
std::lock_guard<std::mutex> locker(fLock);
if(fCookie) {
LOGE("%s: Cookie has already been requested for session %p", __FUNCTION__, this);
// Already created
- return false;
+ return DCM_ERROR_SOCKET;
}
if(!fSocket) {
try {
- ensureSocketConnected();
+ fSocket.reset(new boost::asio::local::stream_protocol::socket(fIOService));
+ boost::asio::local::stream_protocol::endpoint endpoint(DCM_UNIX_SOCKET_PATH);
+ fSocket->connect(endpoint);
} catch(std::exception& ex) {
LOGE("%s: Caught exception \"%s\" when connecting socket for session %p", __FUNCTION__, ex.what(), this);
- return false;
+ return DCM_ERROR_SOCKET;
} catch(...) {
LOGE("%s: Caught unknown exception when connecting socket for session %p", __FUNCTION__, this);
- return false;
+ return DCM_ERROR_SOCKET;
}
}
RequestMessage request;
ResponseMessage response;
- auto * assoc_req = request.mutable_associate_context();
-
- assoc_req->set_service(serviceName);
+ auto* assoc_req = request.mutable_associate_context();
+ assoc_req->set_service(service_name);
assoc_req->set_usage(usage);
assoc_req->set_key_type(key_type);
- sendReceive(request, response);
-
+ send_receive(request, response);
if(!response.has_associate_context()) {
LOGE("%s: received response is not context association message in context %p", __FUNCTION__, this);
- return false;
+ return DCM_ERROR_NO_DATA;
}
auto& assoc_message(response.associate_context());
-
if(assoc_message.result() != 0) {
LOGE("%s: Received context association message with error %d in %p", __FUNCTION__, assoc_message.result(), this);
- return false;
+ return DCM_ERROR_NO_DATA;
}
fCookie = assoc_message.context_cookie();
} catch(std::exception& ex) {
LOGE("%s: Caught exception \"%s\" when establishing cookie for session %p", __FUNCTION__, ex.what(), this);
fSocket.reset();
- return false;
+ return DCM_ERROR_SOCKET;
} catch(...) {
LOGE("%s: Caught unknown exception when establishing cookie for session %p", __FUNCTION__, this);
fSocket.reset();
- return false;
+ return DCM_ERROR_SOCKET;
}
- return true;
-}
-
-void dcm_client_connection_impl::ensureSocketConnected()
-{
- fSocket.reset(new boost::asio::local::stream_protocol::socket(fIOService));
- boost::asio::local::stream_protocol::endpoint endpoint(DCM_UNIX_SOCKET_PATH);
- fSocket->connect(endpoint);
+ return DCM_ERROR_NONE;
}
-int dcm_client_connection_impl::get_certificate_chain(std::vector<uint8_t>& chain) noexcept
+int dcm_client_connection::get_certificate_chain(std::vector<uint8_t>& chain) noexcept
{
std::lock_guard<std::mutex> locker(fLock);
if(!fCookie) {
LOGE("%s: Trying to request certificate in session %p without connection", __FUNCTION__, this);
- return DCM_ERROR_INVALID_PARAMETER;
+ return DCM_ERROR_SOCKET;
}
try {
RequestMessage request;
ResponseMessage response;
- auto * cert_req = request.mutable_request_chain();
-
+ auto* cert_req = request.mutable_request_chain();
cert_req->set_context_cookie(fCookie);
- sendReceive(request, response);
-
+ send_receive(request, response);
if(!response.has_request_chain()) {
LOGE("%s: Response from server is not certificate chain response on session %p", __FUNCTION__, this);
return DCM_ERROR_NO_DATA;
}
auto& cert_resp(response.request_chain());
-
if(cert_resp.result() != 0) {
- LOGE("%s: Server can't respond with certificate chain: error %d in session %p", __FUNCTION__,
- cert_resp.result(), this);
+ LOGE("%s: Server can't respond with certificate chain: error %d in session %p", __FUNCTION__, cert_resp.result(), this);
return DCM_ERROR_NO_DATA;
}
chain.resize(cert_resp.cert_chain().size());
memcpy(&chain[0], cert_resp.cert_chain().c_str(), cert_resp.cert_chain().size());
-
if(chain[chain.size() - 1] != 0) {
// Pad with zero
chain.push_back(0);
return DCM_ERROR_NONE;
}
-const std::string& dcm_client_connection_impl::key_type() const noexcept {
+const std::string& dcm_client_connection::key_type() const noexcept
+{
switch(fKeyType) {
- case CRYPTO_KEY_TYPE_RSA: return sKeyTypeRSA;
- case CRYPTO_KEY_TYPE_ECDSA: return sKeyTypeECDSA;
- default: return sKeyTypeUnknown;
+ case CRYPTO_KEY_TYPE_RSA: return sKeyTypeRSA;
+ case CRYPTO_KEY_TYPE_ECDSA: return sKeyTypeECDSA;
+ default: return sKeyTypeUnknown;
}
}
-int dcm_client_connection_impl::sign_data(mbedtls_md_type_t digestType, const void * hash_data,
- size_t hash_size, std::vector<uint8_t>& digest) noexcept
+unsigned int dcm_client_connection::key_length() const noexcept
+{
+ return fKeyLength;
+}
+
+int dcm_client_connection::sign_data(
+ mbedtls_md_type_t md,
+ const void* hash_data, size_t hash_size,
+ std::vector<uint8_t>& digest) noexcept
{
std::lock_guard<std::mutex> locker(fLock);
return DCM_ERROR_SOCKET;
}
- /*
- * If hash_size == 0 then hash type must be known
- */
+ // If hash_size == 0 then hash type must be known
if(hash_size == 0) {
- if(digestType == MBEDTLS_MD_NONE) {
+ if(md == MBEDTLS_MD_NONE) {
LOGE("%s: Digest type is NONE and hash size is 0", __FUNCTION__);
return DCM_ERROR_INVALID_PARAMETER;
}
- const mbedtls_md_info_t * md_info = mbedtls_md_info_from_type(digestType);
-
+ const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md);
if(!md_info) {
- LOGE("%s: Can't find hash data for digest type %d", __FUNCTION__, digestType);
+ LOGE("%s: Can't find hash data for digest type %d", __FUNCTION__, md);
return DCM_ERROR_INVALID_PARAMETER;
}
hash_size = mbedtls_md_get_size(md_info);
- } else if(hash_size != 0 && digestType != MBEDTLS_MD_NONE) {
- /*
- * If hash_size != 0 then hash type can be specified
- */
- const mbedtls_md_info_t * md_info = mbedtls_md_info_from_type(digestType);
-
+ } else if(hash_size != 0 && md != MBEDTLS_MD_NONE) {
+ // If hash_size != 0 then hash type can be specified
+ const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md);
if(!md_info) {
- LOGE("%s: Can't find hash data for digest type %d", __FUNCTION__, digestType);
+ LOGE("%s: Can't find hash data for digest type %d", __FUNCTION__, md);
return DCM_ERROR_INVALID_PARAMETER;
}
RequestMessage request;
ResponseMessage response;
- auto * sign_req = request.mutable_sign_data();
-
+ auto* sign_req = request.mutable_sign_data();
sign_req->set_context_cookie(fCookie);
sign_req->set_data_to_sign(hash_data, hash_size);
- sign_req->set_digest_type(static_cast<MessageDigestType>(digestType));
-
- sendReceive(request, response);
+ sign_req->set_digest_type(static_cast<MessageDigestType>(md));
+ send_receive(request, response);
if(!response.has_sign_data()) {
LOGE("%s: Response for hash signature has no signature data", __FUNCTION__);
- return DCM_ERROR_INVALID_PARAMETER;
+ return DCM_ERROR_NO_DATA;
}
auto& sign_resp(response.sign_data());
-
if(sign_resp.result() != 0) {
LOGE("%s: Signature request for session %p received error %d", __FUNCTION__, this, sign_resp.result());
- return DCM_ERROR_INVALID_PARAMETER;
+ return DCM_ERROR_NO_DATA;
}
const auto& signature = sign_resp.signature();
-
if(signature.empty()) {
LOGE("%s: Received signature object is empty for session %p", __FUNCTION__, this);
- return DCM_ERROR_INVALID_PARAMETER;
+ return DCM_ERROR_NO_DATA;
}
digest.resize(signature.size());
return DCM_ERROR_NONE;
}
-unsigned int dcm_client_connection_impl::key_length() const noexcept {
- return fKeyLength;
+void dcm_client_connection::send_receive(RequestMessage& request, ResponseMessage& response)
+{
+ protobuf_sync_message_serialization(*fSocket).encodeMessage(request);
+ protobuf_sync_message_deserialization(*fSocket).decodeMessage(response);
}
#ifndef DCM_CLIENT_DCM_CLIENT_H_
#define DCM_CLIENT_DCM_CLIENT_H_
-#include <mbedtls/md.h>
-
#include <memory>
+#include <mutex>
#include <vector>
-class dcm_client_connection :
- public std::enable_shared_from_this<dcm_client_connection>
+#include <boost/asio.hpp>
+#include <mbedtls/md.h>
+
+#include "dcm_support.pb.h"
+
+class dcm_client_connection
{
-private:
+public:
+ dcm_client_connection() {};
+ ~dcm_client_connection() {};
dcm_client_connection(const dcm_client_connection&) = delete;
dcm_client_connection& operator = (const dcm_client_connection&) = delete;
-protected:
- dcm_client_connection();
- ~dcm_client_connection();
-
-public:
- /*!
- * Initialize default instance of the client connection.
- *
- * Standard C++ exceptions may be thrown in case of error
- */
static std::shared_ptr<dcm_client_connection> create();
- /*!
- * Associate key context with this object. This function can be called
- * only once. This function doesn't throw any exceptions.
- */
- virtual bool create_context(const std::string& serviceName,
- const std::string& usage,
- const std::string& key_type) noexcept = 0;
+ int create_context(
+ const std::string& service_name,
+ const std::string& usage,
+ const std::string& key_type) noexcept;
+ int get_certificate_chain(std::vector<uint8_t>& chain) noexcept;
- /*!
- * Request certificate chain associated with this context
- */
- virtual int get_certificate_chain(std::vector<uint8_t>& chain) noexcept = 0;
+ const std::string& key_type() const noexcept;
- /*!
- * Return name of key type (UNKNOWN, RSA or ECDSA for now)
- */
- virtual const std::string& key_type() const noexcept = 0;
+ unsigned int key_length() const noexcept;
- /*!
- * Return length of the crypto key in bits
- */
- virtual unsigned int key_length() const noexcept = 0;
+ int sign_data(
+ mbedtls_md_type_t md,
+ const void* hash_data, size_t hash_size,
+ std::vector<uint8_t>& digest) noexcept;
- /*!
- * Sign data with context certificate
- */
- virtual int sign_data(mbedtls_md_type_t digestType,
- const void * hash_data, size_t hash_size,
- std::vector<uint8_t>& digest) noexcept = 0;
+private:
+ void send_receive(RequestMessage& request, ResponseMessage& response);
+
+private:
+ boost::asio::io_service fIOService;
+ std::mutex fLock;
+ uint64_t fCookie = 0;
+ std::unique_ptr<boost::asio::local::stream_protocol::socket> fSocket;
+ CryptoKeyType fKeyType = CRYPTO_KEY_TYPE_INVALID;
+ unsigned int fKeyLength = 0;
};
#endif /* DCM_CLIENT_DCM_CLIENT_H_ */
+++ /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_CLIENT_DCM_CLIENT_P_H_
-#define DCM_CLIENT_DCM_CLIENT_P_H_
-
-#include "dcm_client.h"
-#include "dcm_support.pb.h"
-#include <memory>
-#include <mutex>
-#include <array>
-#include <boost/asio.hpp>
-
-class dcm_client_connection_impl final : public dcm_client_connection
-{
-public:
- dcm_client_connection_impl();
- dcm_client_connection_impl(boost::asio::io_service& ioService);
- virtual ~dcm_client_connection_impl();
-
- bool create_context(const std::string& serviceName,
- const std::string& usage,
- const std::string& key_type) noexcept override;
-
- int get_certificate_chain(std::vector<uint8_t>& chain) noexcept override;
-
- const std::string& key_type() const noexcept override;
-
- unsigned int key_length() const noexcept override;
-
- int sign_data(mbedtls_md_type_t digestType,
- const void * hash_data, size_t hash_size,
- std::vector<uint8_t>& digest) noexcept override;
-
- void sendReceive(RequestMessage& request, ResponseMessage& response);
-
-private:
- void ensureSocketConnected();
-
-
-private:
- boost::asio::io_service fIOService;
- std::mutex fLock;
- uint64_t fCookie = 0;
- std::unique_ptr<boost::asio::local::stream_protocol::socket> fSocket;
- CryptoKeyType fKeyType = CRYPTO_KEY_TYPE_INVALID;
- unsigned int fKeyLength = 0;
-};
-
-#endif /* DCM_CLIENT_DCM_CLIENT_P_H_ */
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
-/*
- * Type of the crypto key
- */
enum CryptoKeyType {
CRYPTO_KEY_TYPE_INVALID = 0;
CRYPTO_KEY_TYPE_ECDSA = 1;
CRYPTO_KEY_TYPE_RSA = 2;
}
-/*
- * These values match the mbedtls ones
- */
enum MessageDigestType {
- MD_NONE = 0;
- MD_MD2 = 1;
- MD_MD4 = 2;
- MD_MD5 = 3;
- MD_SHA1 = 4;
- MD_SHA224 = 5;
- MD_SHA256 = 6;
- MD_SHA384 = 7;
- MD_SHA512 = 8;
- MD_RIPEMD160 = 9;
+ MD_NONE = 0;
+ MD_MD2 = 1;
+ MD_MD4 = 2;
+ MD_MD5 = 3;
+ MD_SHA1 = 4;
+ MD_SHA224 = 5;
+ MD_SHA256 = 6;
+ MD_SHA384 = 7;
+ MD_SHA512 = 8;
+ MD_RIPEMD160 = 9;
}
message AssociateKeyContext
{
- required string service = 1;
- required string usage = 2;
- required string key_type = 3;
+ required string service = 1;
+ required string usage = 2;
+ required string key_type = 3;
}
message AssociateKeyContextResponse
{
- required int32 result = 1;
- optional uint64 context_cookie = 2;
- optional CryptoKeyType key_type = 3;
- optional uint32 key_length = 4;
+ required int32 result = 1;
+ optional uint64 context_cookie = 2;
+ optional CryptoKeyType key_type = 3;
+ optional uint32 key_length = 4;
}
message RequestCertificateChain
{
- required uint64 context_cookie = 1;
+ required uint64 context_cookie = 1;
}
message RequestCertificateChainResponse
{
- required int32 result = 1;
- optional bytes cert_chain = 2;
+ required int32 result = 1;
+ optional bytes cert_chain = 2;
}
message SignRequest
{
- required uint64 context_cookie = 1;
- required bytes data_to_sign = 2;
- required MessageDigestType digest_type = 3;
+ required uint64 context_cookie = 1;
+ required bytes data_to_sign = 2;
+ required MessageDigestType digest_type = 3;
}
message SignResponse
{
- required int32 result = 1;
- optional bytes signature = 2;
+ required int32 result = 1;
+ optional bytes signature = 2;
}
message RequestMessage {
oneof request_oneof {
- AssociateKeyContext associate_context = 1;
- RequestCertificateChain request_chain = 2;
- SignRequest sign_data = 3;
+ AssociateKeyContext associate_context = 1;
+ RequestCertificateChain request_chain = 2;
+ SignRequest sign_data = 3;
}
}
message ResponseMessage {
oneof reply_oneof {
- AssociateKeyContextResponse associate_context = 1;
- RequestCertificateChainResponse request_chain = 2;
- SignResponse sign_data = 3;
+ AssociateKeyContextResponse associate_context = 1;
+ RequestCertificateChainResponse request_chain = 2;
+ SignResponse sign_data = 3;
}
}
* limitations under the License.
*
******************************************************************/
+#define LOG_TAG "DCM_CLIENT"
-#include "device_certificate_manager.h"
-#include "dcm_client.h"
+#include <vector>
+#include <cstring>
#include <mbedtls/pk_internal.h>
#include <mbedtls/md.h>
+#include <dlog.h>
-#include <vector>
-#include <cstring>
+#include "device_certificate_manager.h"
+#include "dcm_client.h"
#ifndef API_DEVICE_CERTIFICATE_MANAGER_EXPORT
#define API_DEVICE_CERTIFICATE_MANAGER_EXPORT __attribute__((visibility("default")))
#endif
-#define LOG_TAG "DCM_CLIENT"
-#include <dlog.h>
-
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;
- }
+ 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 {
context->connection = dcm_client_connection::create();
- if(!context->connection->create_context(service_string, usage_string, keytype_string)) {
+ int result = context->connection->create_context(service_string, usage_string, keytype_string);
+ if(result != DCM_ERROR_NONE) {
LOGE("Can't create connection context");
- return DCM_ERROR_SOCKET;
+ return result;
}
*key_ctx = context.release();
- return DCM_ERROR_NONE;
} catch(std::exception& ex) {
LOGE("Context creation failure: %s", ex.what());
return DCM_ERROR_UNKNOWN;
LOGE("Context creation failure");
return DCM_ERROR_UNKNOWN;
}
+
+ return DCM_ERROR_NONE;
}
API_DEVICE_CERTIFICATE_MANAGER_EXPORT
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)
+ const char *message, size_t message_len,
+ char **signature, size_t *signature_len)
{
if(!key_ctx || !signature || !signature_len)
return DCM_ERROR_INVALID_PARAMETER;
ctx = NULL;
ret = dcm_create_key_context("a", "b", "UNEXISTING", &ctx);
- BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_SOCKET);
+ BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NO_DATA);
BOOST_CHECK(!ctx);
ret = dcm_free_key_context(ctx);
BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);