Refactor dcm-client code 12/235012/11
authorDariusz Michaluk <d.michaluk@samsung.com>
Mon, 1 Jun 2020 08:39:26 +0000 (10:39 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Mon, 6 Jul 2020 09:59:38 +0000 (11:59 +0200)
- remove dcm_client_connection_impl class
- code formatting changes
- added new error return values in some functions

Change-Id: I1db0ab5645d8c10e281e727f4c0c4a5530da0802

src/dcm-client/CMakeLists.txt
src/dcm-client/dcm_client.cpp [new file with mode: 0644]
src/dcm-client/dcm_client.h
src/dcm-client/dcm_client_p.h [deleted file]
src/dcm-client/dcm_support.proto
src/dcm-client/dcmclient.cpp [deleted file]
src/dcm-client/device_certificate_manager.cpp
tests/api_test.cpp

index ac78ed78e4ea79fc6840df73bd6bbd4cc8601a26..bc4c2c3585bcce9bc69c0ec7014bbb46b35c4b0b 100644 (file)
@@ -36,7 +36,7 @@ PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS dcm_support.proto)
 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}
diff --git a/src/dcm-client/dcm_client.cpp b/src/dcm-client/dcm_client.cpp
new file mode 100644 (file)
index 0000000..cc9d9e3
--- /dev/null
@@ -0,0 +1,274 @@
+/******************************************************************
+ *
+ * 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);
+}
index bd6ce70b2c23e1c72604994fa7eb7d7de30bd925..2748e460a6d8ae399eb33194e6f73fb3feb73332 100644 (file)
 #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_ */
diff --git a/src/dcm-client/dcm_client_p.h b/src/dcm-client/dcm_client_p.h
deleted file mode 100644 (file)
index 9fe1749..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/******************************************************************
- *
- * 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_ */
index 4adc4cf49ab4320736cff834242a6b2995fad362..6a7e96d8e4690742c092c77b9c92f2d89e01772f 100644 (file)
@@ -1,82 +1,76 @@
 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;
        }
 }
diff --git a/src/dcm-client/dcmclient.cpp b/src/dcm-client/dcmclient.cpp
deleted file mode 100644 (file)
index 322420b..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/******************************************************************
- *
- * 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;
-}
index bef03c8ed0b88de57b07da0cc3cca6001f15ad99..c57d96b54a9a4806fdd61399b1f014f30c80785a 100644 (file)
  * 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 {
@@ -79,13 +78,13 @@ int dcm_create_key_context(const char *service, const char *usage, const char *k
 
                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;
@@ -93,6 +92,8 @@ int dcm_create_key_context(const char *service, const char *usage, const char *k
                LOGE("Context creation failure");
                return DCM_ERROR_UNKNOWN;
        }
+
+       return DCM_ERROR_NONE;
 }
 
 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
@@ -161,8 +162,8 @@ int dcm_get_key_type(const void *key_ctx, char **key_type)
 
 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;
index 2cd611bdb90fb5a163ae0205d4dce2897a380f9f..65aa90cdc241985b342e57cf03591129fd1753f3 100644 (file)
@@ -66,7 +66,7 @@ POSITIVE_TEST_CASE(test01_dcm_create_key_context)
 
     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);