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}
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2017 - 2020 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.
+ *
+ ******************************************************************/
+#define LOG_TAG "DCM_CLIENT"
+
+#include <cassert>
+#include <inttypes.h>
+
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <mbedtls/ssl.h>
+#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_assert(MD_MD5 == (unsigned int)MBEDTLS_MD_MD5, "MBEDTLS_MD_MD5 mismatch");
+static_assert(MD_SHA1 == (unsigned int)MBEDTLS_MD_SHA1, "MBEDTLS_MD_SHA1 mismatch");
+static_assert(MD_SHA224 == (unsigned int)MBEDTLS_MD_SHA224, "MBEDTLS_MD_SHA224 mismatch");
+static_assert(MD_SHA256 == (unsigned int)MBEDTLS_MD_SHA256, "MBEDTLS_MD_SHA256 mismatch");
+static_assert(MD_SHA384 == (unsigned int)MBEDTLS_MD_SHA384, "MBEDTLS_MD_SHA384 mismatch");
+static_assert(MD_SHA512 == (unsigned int)MBEDTLS_MD_SHA512, "MBEDTLS_MD_SHA512 mismatch");
+static_assert(MD_RIPEMD160 == (unsigned int)MBEDTLS_MD_RIPEMD160, "MBEDTLS_MD_RIPEMD160 mismatch");
+
+static std::string sKeyTypeUnknown("UNKNOWN");
+static std::string sKeyTypeRSA("RSA");
+static std::string sKeyTypeECDSA("ECDSA");
+
+std::shared_ptr<dcm_client_connection> dcm_client_connection::create()
+{
+ return std::make_shared<dcm_client_connection>();
+}
+
+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 DCM_ERROR_SOCKET;
+ }
+
+ if(!fSocket) {
+ try {
+ 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 DCM_ERROR_SOCKET;
+ } catch(...) {
+ LOGE("%s: Caught unknown exception when connecting socket for session %p", __FUNCTION__, this);
+ return DCM_ERROR_SOCKET;
+ }
+ }
+
+ try {
+ RequestMessage request;
+ ResponseMessage response;
+
+ 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);
+
+ send_receive(request, response);
+ if(!response.has_associate_context()) {
+ LOGE("%s: received response is not context association message in context %p", __FUNCTION__, this);
+ 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 DCM_ERROR_NO_DATA;
+ }
+
+ fCookie = assoc_message.context_cookie();
+ fKeyType = assoc_message.key_type();
+ fKeyLength = assoc_message.key_length();
+ } catch(std::exception& ex) {
+ LOGE("%s: Caught exception \"%s\" when establishing cookie for session %p", __FUNCTION__, ex.what(), this);
+ fSocket.reset();
+ return DCM_ERROR_SOCKET;
+ } catch(...) {
+ LOGE("%s: Caught unknown exception when establishing cookie for session %p", __FUNCTION__, this);
+ fSocket.reset();
+ return DCM_ERROR_SOCKET;
+ }
+
+ return DCM_ERROR_NONE;
+}
+
+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_SOCKET;
+ }
+
+ try {
+ RequestMessage request;
+ ResponseMessage response;
+
+ auto* cert_req = request.mutable_request_chain();
+ cert_req->set_context_cookie(fCookie);
+
+ 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);
+ return DCM_ERROR_NO_DATA;
+ }
+
+ if(cert_resp.cert_chain().size() == 0) {
+ LOGE("%s: Server can't respond with certificate chain: certificate empty", __FUNCTION__);
+ return DCM_ERROR_NO_DATA;
+ }
+
+ // Add space for last zero byte if needed
+ chain.reserve(cert_resp.cert_chain().size() + 1);
+ 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);
+ }
+ } catch(std::bad_alloc&) {
+ LOGE("%s: Out of memory when requesting certificate for session %p", __FUNCTION__, this);
+ return DCM_ERROR_OUT_OF_MEMORY;
+ } catch(std::invalid_argument&) {
+ LOGE("%s: Invalid argument passed for certificate request for session %p", __FUNCTION__, this);
+ return DCM_ERROR_INVALID_PARAMETER;
+ } catch(std::exception& ex) {
+ LOGE("%s: When requesting certificate for session %p received exception : %s", __FUNCTION__, this, ex.what());
+ return DCM_ERROR_UNKNOWN;
+ } catch(...) {
+ LOGE("%s: When requesting certificate for session %p received exception : %s", __FUNCTION__, this, "Unknown error");
+ return DCM_ERROR_UNKNOWN;
+ }
+
+ return DCM_ERROR_NONE;
+}
+
+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;
+ }
+}
+
+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);
+
+ if(!fCookie) {
+ LOGE("%s: Trying to request data signing in object %p but there is no connection", __FUNCTION__, this);
+ return DCM_ERROR_SOCKET;
+ }
+
+ // If hash_size == 0 then hash type must be known
+ if(hash_size == 0) {
+ 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(md);
+ if(!md_info) {
+ 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 && 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__, md);
+ return DCM_ERROR_INVALID_PARAMETER;
+ }
+
+ if(hash_size != mbedtls_md_get_size(md_info)) {
+ LOGE("%s: Hash size mismatch. Expected %zd but got %zd", __FUNCTION__, hash_size, (size_t)mbedtls_md_get_size(md_info));
+ return DCM_ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ try {
+ RequestMessage request;
+ ResponseMessage response;
+
+ 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>(md));
+
+ send_receive(request, response);
+ if(!response.has_sign_data()) {
+ LOGE("%s: Response for hash signature has no signature data", __FUNCTION__);
+ 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_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_NO_DATA;
+ }
+
+ digest.resize(signature.size());
+ memcpy(&digest[0], signature.c_str(), signature.size());
+ } catch(std::bad_alloc&) {
+ LOGE("%s: Out of memory when processing sign request for session %p", __FUNCTION__, this);
+ return DCM_ERROR_OUT_OF_MEMORY;
+ } catch(...) {
+ LOGE("%s: When processing signature for session %p got exception : %s", __FUNCTION__, this, "Unknown error");
+ return DCM_ERROR_UNKNOWN;
+ }
+
+ return DCM_ERROR_NONE;
+}
+
+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;
}
}
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2017 - 2020 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 "dcm_client_p.h"
-#include "dcm_support.pb.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>
-
-#define LOG_TAG "DCM_CLIENT"
-#include <dlog.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_assert(MD_MD5 == (unsigned int)MBEDTLS_MD_MD5, "MBEDTLS_MD_MD5 mismatch");
-static_assert(MD_SHA1 == (unsigned int)MBEDTLS_MD_SHA1, "MBEDTLS_MD_SHA1 mismatch");
-static_assert(MD_SHA224 == (unsigned int)MBEDTLS_MD_SHA224, "MBEDTLS_MD_SHA224 mismatch");
-static_assert(MD_SHA256 == (unsigned int)MBEDTLS_MD_SHA256, "MBEDTLS_MD_SHA256 mismatch");
-static_assert(MD_SHA384 == (unsigned int)MBEDTLS_MD_SHA384, "MBEDTLS_MD_SHA384 mismatch");
-static_assert(MD_SHA512 == (unsigned int)MBEDTLS_MD_SHA512, "MBEDTLS_MD_SHA512 mismatch");
-static_assert(MD_RIPEMD160 == (unsigned int)MBEDTLS_MD_RIPEMD160, "MBEDTLS_MD_RIPEMD160 mismatch");
-
-static std::string sKeyTypeUnknown("UNKNOWN");
-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>();
-}
-
-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
-{
- 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;
- }
-
- if(!fSocket) {
- try {
- ensureSocketConnected();
- } catch(std::exception& ex) {
- LOGE("%s: Caught exception \"%s\" when connecting socket for session %p", __FUNCTION__, ex.what(), this);
- return false;
- } catch(...) {
- LOGE("%s: Caught unknown exception when connecting socket for session %p", __FUNCTION__, this);
- return false;
- }
- }
-
- try {
- RequestMessage request;
- ResponseMessage response;
-
- auto * assoc_req = request.mutable_associate_context();
-
- assoc_req->set_service(serviceName);
- assoc_req->set_usage(usage);
- assoc_req->set_key_type(key_type);
-
- sendReceive(request, response);
-
- if(!response.has_associate_context()) {
- LOGE("%s: received response is not context association message in context %p", __FUNCTION__, this);
- return false;
- }
-
- 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;
- }
-
- fCookie = assoc_message.context_cookie();
- fKeyType = assoc_message.key_type();
- fKeyLength = assoc_message.key_length();
- } catch(std::exception& ex) {
- LOGE("%s: Caught exception \"%s\" when establishing cookie for session %p", __FUNCTION__, ex.what(), this);
- fSocket.reset();
- return false;
- } catch(...) {
- LOGE("%s: Caught unknown exception when establishing cookie for session %p", __FUNCTION__, this);
- fSocket.reset();
- return false;
- }
-
- 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);
-}
-
-int dcm_client_connection_impl::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;
- }
-
- try {
- RequestMessage request;
- ResponseMessage response;
-
- auto * cert_req = request.mutable_request_chain();
-
- cert_req->set_context_cookie(fCookie);
-
- sendReceive(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);
- return DCM_ERROR_NO_DATA;
- }
-
- if(cert_resp.cert_chain().size() == 0) {
- LOGE("%s: Server can't respond with certificate chain: certificate empty", __FUNCTION__);
- return DCM_ERROR_NO_DATA;
- }
-
- // Add space for last zero byte if needed
- chain.reserve(cert_resp.cert_chain().size() + 1);
- 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);
- }
- } catch(std::bad_alloc&) {
- LOGE("%s: Out of memory when requesting certificate for session %p", __FUNCTION__, this);
- return DCM_ERROR_OUT_OF_MEMORY;
- } catch(std::invalid_argument&) {
- LOGE("%s: Invalid argument passed for certificate request for session %p", __FUNCTION__, this);
- return DCM_ERROR_INVALID_PARAMETER;
- } catch(std::exception& ex) {
- LOGE("%s: When requesting certificate for session %p received exception : %s", __FUNCTION__, this, ex.what());
- return DCM_ERROR_UNKNOWN;
- } catch(...) {
- LOGE("%s: When requesting certificate for session %p received exception : %s", __FUNCTION__, this, "Unknown error");
- return DCM_ERROR_UNKNOWN;
- }
-
- return DCM_ERROR_NONE;
-}
-
-const std::string& dcm_client_connection_impl::key_type() const noexcept {
- switch(fKeyType) {
- 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
-{
- std::lock_guard<std::mutex> locker(fLock);
-
- if(!fCookie) {
- LOGE("%s: Trying to request data signing in object %p but there is no connection", __FUNCTION__, this);
- return DCM_ERROR_SOCKET;
- }
-
- /*
- * If hash_size == 0 then hash type must be known
- */
- if(hash_size == 0) {
- if(digestType == 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);
-
- if(!md_info) {
- LOGE("%s: Can't find hash data for digest type %d", __FUNCTION__, digestType);
- 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);
-
- if(!md_info) {
- LOGE("%s: Can't find hash data for digest type %d", __FUNCTION__, digestType);
- return DCM_ERROR_INVALID_PARAMETER;
- }
-
- if(hash_size != mbedtls_md_get_size(md_info)) {
- LOGE("%s: Hash size mismatch. Expected %zd but got %zd", __FUNCTION__, hash_size, (size_t)mbedtls_md_get_size(md_info));
- return DCM_ERROR_INVALID_PARAMETER;
- }
- }
-
- try {
- RequestMessage request;
- ResponseMessage response;
-
- 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);
-
- if(!response.has_sign_data()) {
- LOGE("%s: Response for hash signature has no signature data", __FUNCTION__);
- return DCM_ERROR_INVALID_PARAMETER;
- }
-
- 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;
- }
-
- 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;
- }
-
- digest.resize(signature.size());
- memcpy(&digest[0], signature.c_str(), signature.size());
- } catch(std::bad_alloc&) {
- LOGE("%s: Out of memory when processing sign request for session %p", __FUNCTION__, this);
- return DCM_ERROR_OUT_OF_MEMORY;
- } catch(...) {
- LOGE("%s: When processing signature for session %p got exception : %s", __FUNCTION__, this, "Unknown error");
- return DCM_ERROR_UNKNOWN;
- }
-
- return DCM_ERROR_NONE;
-}
-
-unsigned int dcm_client_connection_impl::key_length() const noexcept {
- return fKeyLength;
-}
* 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);