Tests updated.
Change-Id: I61790de9a3914c3bea846e9060360c16969e65c6
BuildRequires: pkgconfig(cynara-client)
BuildRequires: pkgconfig(cynara-creds-socket)
BuildRequires: pkgconfig(cynara-session)
+BuildRequires: pkgconfig(openssl1.1)
BuildRequires: boost-devel
%if "%{build_type}" == "COVERAGE"
BuildRequires: lcov
device_certificate_manager.cpp
../shared/protobuf_asio.cpp
../shared/log.cpp
+ ../shared/bundle.cpp
${PROTO_SRCS}
${PROTO_HDRS})
return DCM_ERROR_NONE;
}
+int dcm_client_connection::e2ee_sign_data(
+ dcm_digest_algorithm_e md,
+ const void* payload, size_t payload_size,
+ std::vector<uint8_t>& signed_message,
+ std::vector<uint8_t>& digest) noexcept
+{
+ std::lock_guard<std::mutex> locker(fLock);
+
+ if(!fCookie) {
+ LOGE("Trying to request E2EE data signing in object %p but there is no connection", this);
+ return DCM_ERROR_SOCKET;
+ }
+
+ try {
+ RequestMessage request;
+ ResponseMessage response;
+
+ auto* sign_req = request.mutable_e2ee_sign_data();
+ sign_req->set_context_cookie(fCookie);
+ sign_req->set_data_to_sign(payload, payload_size);
+ sign_req->set_digest_type(static_cast<MessageDigestType>(md));
+
+ send_receive(request, response);
+ if(!response.has_sign_data()) {
+ LOGE("Response for E2EE signature has no signature data");
+ return DCM_ERROR_NO_DATA;
+ }
+
+ auto& sign_resp(response.sign_data());
+ if(sign_resp.result() != 0) {
+ LOGE("E2EE signature request for session %p received error %d", this, sign_resp.result());
+ return DCM_ERROR_NO_DATA;
+ }
+
+ const auto& signature = sign_resp.signature();
+ if(signature.empty()) {
+ LOGE("Received E2EE signature object is empty for session %p", this);
+ return DCM_ERROR_NO_DATA;
+ }
+
+ digest.resize(signature.size());
+ memcpy(&digest[0], signature.c_str(), signature.size());
+
+ const auto& message = sign_resp.message();
+ if(message.empty()) {
+ LOGE("Received E2EE message object is empty for session %p", this);
+ return DCM_ERROR_NO_DATA;
+ }
+ signed_message.resize(message.size());
+ memcpy(&signed_message[0], message.c_str(), message.size());
+ } catch(std::bad_alloc&) {
+ LOGE("Out of memory when processing E2EE sign request for session %p", this);
+ return DCM_ERROR_OUT_OF_MEMORY;
+ } catch(...) {
+ LOGE("When processing E2EE signature for session %p got exception : %s", 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);
const void* hash_data, size_t hash_size,
std::vector<uint8_t>& digest) noexcept;
+ int e2ee_sign_data(
+ dcm_digest_algorithm_e md,
+ const void* hash_data, size_t hash_size,
+ std::vector<uint8_t>& message,
+ std::vector<uint8_t>& digest) noexcept;
+
private:
void send_receive(RequestMessage& request, ResponseMessage& response);
{
required int32 result = 1;
optional bytes signature = 2;
+ optional bytes message = 3;
}
message ExtCallRequest
RequestCertificateChain request_chain = 2;
SignRequest sign_data = 3;
ExtCallRequest ext_call = 4;
+ SignRequest e2ee_sign_data = 5;
}
}
RequestCertificateChainResponse request_chain = 2;
SignResponse sign_data = 3;
ExtCallResponse ext_call = 4;
+
}
}
#include "device_certificate_manager.h"
#include "dcm_client.h"
#include "log.h"
+#include "bundle.h"
#ifndef API_DEVICE_CERTIFICATE_MANAGER_EXPORT
#define API_DEVICE_CERTIFICATE_MANAGER_EXPORT __attribute__((visibility("default")))
if (message == NULL || bundle == NULL)
return DCM_ERROR_INVALID_PARAMETER;
- const char* message_str = reinterpret_cast<const char*>(message);
+ struct dcm_e2ee_bundle_s *tmp = static_cast<struct dcm_e2ee_bundle_s*>(
+ malloc(sizeof(struct dcm_e2ee_bundle_s)));
- struct dcm_e2ee_bundle_s *tmp = new dcm_e2ee_bundle_s;
-
- tmp->message_len = message_len;
- tmp->pkg_id_offset = strnlen(message_str, message_len);
- if (tmp->pkg_id_offset == message_len) {
- delete tmp;
- return DCM_ERROR_INVALID_PARAMETER; // wrong format
- }
-
- if (strcmp(message_str, "Tizen") != 0) { // TODO specify platform format
- delete tmp;
- return DCM_ERROR_NOT_SUPPORTED; // not a Tizen bundle
- }
-
- tmp->pkg_id_offset++; // skip \0
- message_str += tmp->pkg_id_offset;
- message_len -= tmp->pkg_id_offset;
+ if (tmp == NULL)
+ return DCM_ERROR_OUT_OF_MEMORY;
- tmp->payload_offset = strnlen(message_str, message_len);
- if (tmp->payload_offset == message_len) {
- delete tmp;
- return DCM_ERROR_INVALID_PARAMETER; // wrong format
+ int ret = decompose_e2ee_message(message, message_len, tmp->pkg_id_offset, tmp->payload_offset);
+ if (ret != DCM_ERROR_NONE) {
+ free(tmp);
+ return ret;
}
- tmp->payload_offset += tmp->pkg_id_offset; // skip pkg_id
- tmp->payload_offset++; // skip \0
+ tmp->message_len = message_len;
tmp->message = message;
*bundle = tmp;
return;
free(bundle->message);
- delete bundle;
+ free(bundle);
}
API_DEVICE_CERTIFICATE_MANAGER_EXPORT
API_DEVICE_CERTIFICATE_MANAGER_EXPORT
int dcm_e2ee_create_signed_bundle(const void *key_ctx,
- dcm_digest_algorithm_e /*md*/,
+ dcm_digest_algorithm_e md,
const unsigned char *payload,
- size_t /*payload_len*/,
+ size_t payload_len,
dcm_e2ee_bundle_h *bundle,
char **signature,
size_t *signature_len)
signature_len == NULL)
return DCM_ERROR_INVALID_PARAMETER;
- /* TODO:
- * 1. Get client pkg_id from socket
- * 2. Construct a message (platform="Tizen" + pkg_id + payload) and put it into bundle
- * 3. Sign the message with OCF
- * 4. Return bundle and signature
- */
+ const dcm_key_context_internal *context =
+ reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
- return DCM_ERROR_NONE;
+ std::vector<uint8_t> digest;
+ std::vector<uint8_t> message;
+ int result = context->connection->e2ee_sign_data(md, payload, payload_len, message, digest);
+ if(result == DCM_ERROR_NONE) {
+ *signature = static_cast<char*>(malloc(sizeof(uint8_t) * digest.size()));
+ if(*signature == NULL)
+ return DCM_ERROR_OUT_OF_MEMORY;
+ memcpy(*signature, digest.data(), digest.size());
+ *signature_len = digest.size();
+
+ auto message_dup = static_cast<unsigned char*>(malloc(sizeof(uint8_t)*message.size()));
+ if(message_dup == NULL) {
+ free(signature);
+ return DCM_ERROR_OUT_OF_MEMORY;
+ }
+ memcpy(message_dup, message.data(), message.size());
+
+ result = dcm_e2ee_create_bundle(message_dup, message.size(), bundle);
+ assert(result == DCM_ERROR_NONE);
+ }
+
+ return result;
}
PKG_CHECK_MODULES(DAEMON_DEPS
REQUIRED
libsystemd
+ openssl1.1
cynara-client
cynara-creds-socket
cynara-session
dcm_session.cpp
../shared/protobuf_asio.cpp
../shared/log.cpp
+ ../shared/bundle.cpp
soresolver.cpp
${PROTO_SRCS}
${PROTO_HDRS})
#include <iostream>
#include <cassert>
+#include <openssl/evp.h>
#include <cynara-client.h>
#include <cynara-creds-socket.h>
#include "dcm_session.h"
#include "dcm_server.h"
#include "../dcm-client/device_certificate_manager_ext_types.h"
+#include "../dcm-client/device_certificate_manager.h"
#include "log.h"
+#include "bundle.h"
+
+namespace {
+const EVP_MD* get_md(MessageDigestType digest_type)
+{
+ switch(digest_type) {
+ case MD_MD2:
+ return EVP_md2();
+ case MD_MD4:
+ return EVP_md4();
+ case MD_MD5:
+ return EVP_md5();
+ case MD_SHA1:
+ return EVP_sha1();
+ case MD_SHA224:
+ return EVP_sha224();
+ case MD_SHA256:
+ return EVP_sha256();
+ case MD_SHA384:
+ return EVP_sha384();
+ case MD_SHA512:
+ return EVP_sha512();
+ case MD_RIPEMD160:
+ return EVP_ripemd160();
+ default:
+ LOGE("Unknown message digest type: " << static_cast<unsigned>(digest_type));
+ return nullptr;
+ }
+}
+
+std::string digest_message(const std::string& message, MessageDigestType digest_type)
+{
+ if (digest_type == MD_NONE)
+ return message;
+
+ EVP_MD_CTX* mdctx = nullptr;
+ if((mdctx = EVP_MD_CTX_new()) == nullptr)
+ return std::string();
+
+ std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> mdctxPtr(mdctx, EVP_MD_CTX_free);
+
+ auto md = get_md(digest_type);
+ if (md == nullptr)
+ return std::string();
+
+ if(1 != EVP_DigestInit_ex(mdctx, md, nullptr))
+ return std::string();
+
+ if(1 != EVP_DigestUpdate(
+ mdctx,
+ reinterpret_cast<const unsigned char*>(message.c_str()),
+ message.size()))
+ return std::string();
+
+ std::string digest(EVP_MD_size(md), '\0');
+ size_t digest_size;
+ if(1 != EVP_DigestFinal_ex(
+ mdctx,
+ reinterpret_cast<unsigned char*>(digest.data()),
+ &digest_size))
+ return std::string();
+
+ digest.resize(digest_size);
+ return digest;
+}
+} // namespace
#define DCM_DEFAULT_PRIVILEGE "http://tizen.org/privilege/devicecertificate"
case RequestMessage::kExtCall:
handle_ext_call_request(requestMessage.ext_call());
break;
+ case RequestMessage::kE2EeSignData:
+ handle_e2ee_sign_request(requestMessage.e2ee_sign_data());
+ break;
default:
LOGE("Incorrect request message type");
// This will terminate connection
reply(msg);
}
+int dcm_session::sign_request_check(const SignRequest& message)
+{
+ if(message.context_cookie() != fCookie) {
+ LOGE("Received unknown context cookie");
+ return false;
+ }
+
+ if(!fBackendContext) {
+ LOGE("Context not associated with connection");
+ return false;
+ }
+
+ if(message.data_to_sign().size() == 0) {
+ LOGE("Data to sign is empty");
+ return false;
+ }
+
+ 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");
return;
}
+ int ret;
ResponseMessage msg;
auto* signingResponse = msg.mutable_sign_data();
-
- if(message.context_cookie() != fCookie) {
- LOGE("Received unknown context cookie");
- signingResponse->set_result(-EINVAL);
- reply(msg);
- return;
+ if (!sign_request_check(message)) {
+ ret = -EINVAL;
+ } else {
+ ret = sign(
+ message.digest_type(), message.data_to_sign(), *signingResponse->mutable_signature());
}
+ signingResponse->set_result(ret);
+ reply(msg);
+}
- if(!fBackendContext) {
- LOGE("Context not associated with connection");
- signingResponse->set_result(-EINVAL);
- reply(msg);
- return;
- }
+void dcm_session::handle_e2ee_sign_request(const SignRequest& message)
+{
+ LOGD("Request E2EE data signing");
- if(message.data_to_sign().size() == 0) {
- LOGE("Data to sign is empty");
- signingResponse->set_result(-EINVAL);
+ if(!verify_privileges(fSocket.native_handle(), DCM_DEFAULT_PRIVILEGE)) {
+ LOGE("Client privilege check failure. Disconnect");
return;
}
- int error = fSoResolver->invoke<int, dcm_backend_context&, MessageDigestType, const std::string&, std::string&>(
- "dcm_backend_sign_crypto_data", *fBackendContext, message.digest_type(), message.data_to_sign(), *signingResponse->mutable_signature());
+ int ret;
+ ResponseMessage msg;
+ auto* signingResponse = msg.mutable_sign_data();
- signingResponse->set_result(error);
+ if (!sign_request_check(message)) {
+ ret = -EINVAL;
+ } else {
+ std::unique_ptr<char, string_free_deleter> client;
+ char* tmp_str = nullptr;
+ ret = cynara_creds_socket_get_client(
+ fSocket.native_handle(), CLIENT_METHOD_DEFAULT, &tmp_str);
+ assert(ret == CYNARA_API_SUCCESS); // it was checked in verify_privileges already
+ client.reset(tmp_str);
+
+ std::string composed = compose_e2ee_message(client.get(), message.data_to_sign());
+ auto digest = digest_message(composed, message.digest_type());
+ if (digest.empty()) {
+ LOGE("Digest calculation failed");
+ ret = -EINVAL; // TODO validate digest algorithms and return proper error to client
+ } else {
+ ret = sign(message.digest_type(), digest, *signingResponse->mutable_signature());
+ signingResponse->set_message(composed);
+ }
+ }
+ signingResponse->set_result(ret);
reply(msg);
}
void handle_context_association(const AssociateKeyContext& message);
void handle_cert_chain(const RequestCertificateChain& message);
void handle_sign_request(const SignRequest& message);
+ void handle_e2ee_sign_request(const SignRequest& message);
void handle_ext_call_request(const ExtCallRequest& message);
+ int sign(MessageDigestType digest_type, const std::string& message, std::string& signature);
+ int sign_request_check(const SignRequest& message);
+
private:
boost::asio::local::stream_protocol::socket fSocket;
protobuf_async_message_serialization fSerializer;
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2023 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 <cerrno>
+#include <cassert>
+#include <cstring>
+
+#include "bundle.h"
+#include "../dcm-client/device_certificate_manager.h"
+
+namespace {
+constexpr char PLATFORM[] = "Tizen";
+}
+
+std::string compose_e2ee_message(const char* pkg_id, const std::string& payload)
+{
+ assert(pkg_id);
+
+ size_t platform_len = strlen(PLATFORM) + 1;
+ size_t pkg_id_len = strlen(pkg_id) + 1;
+ size_t size = platform_len + pkg_id_len + payload.size();
+
+ std::string message(size, ' ');
+
+ auto tmp = message.data();
+
+ memcpy(tmp, PLATFORM, platform_len);
+ tmp += platform_len;
+ memcpy(tmp, pkg_id, pkg_id_len);
+ tmp += pkg_id_len;
+ memcpy(tmp, payload.c_str(), payload.size());
+
+ return message;
+}
+
+int decompose_e2ee_message(
+ const unsigned char* message,
+ size_t message_len,
+ size_t& pkg_id_offset,
+ size_t& payload_offset)
+{
+ if (message == NULL)
+ return DCM_ERROR_INVALID_PARAMETER;
+
+ const char* message_str = reinterpret_cast<const char*>(message);
+ pkg_id_offset = strnlen(message_str, message_len);
+ if (pkg_id_offset == message_len)
+ return DCM_ERROR_INVALID_PARAMETER; // wrong format
+
+ if (strcmp(message_str, PLATFORM) != 0)
+ return DCM_ERROR_NOT_SUPPORTED; // not a Tizen bundle
+
+ pkg_id_offset++; // skip \0
+ message_str += pkg_id_offset;
+ message_len -= pkg_id_offset;
+
+ payload_offset = strnlen(message_str, message_len);
+ if (payload_offset == message_len)
+ return DCM_ERROR_INVALID_PARAMETER; // wrong format
+
+ payload_offset += pkg_id_offset; // skip pkg_id
+ payload_offset++; // skip \0
+
+ return DCM_ERROR_NONE;
+}
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2023 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.
+ *
+ ******************************************************************/
+#pragma once
+
+#include <cstddef>
+#include <string>
+
+std::string compose_e2ee_message(const char* pkg_id, const std::string& payload);
+int decompose_e2ee_message(
+ const unsigned char* message,
+ size_t message_len,
+ size_t& pkg_id_offset,
+ size_t& payload_offset);
COMPONENTS
unit_test_framework)
-PKG_CHECK_MODULES(TEST_DEPS REQUIRED dlog)
+PKG_CHECK_MODULES(TEST_DEPS REQUIRED dlog libsmack)
INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS} ${TEST_DEPS_INCLUDE_DIRS})
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS} ${TEST_DEPS_LIBRARY_DIRS})
../src/dcm-client/device_certificate_manager_ext.cpp
../src/shared/log.cpp
../src/shared/protobuf_asio.cpp
+ ../src/shared/bundle.cpp
${PROTO_SRCS}
${PROTO_HDRS})
typedef Free<dcm_e2ee_bundle_s, dcm_e2ee_free_bundle> FreeBundle;
typedef Free<void, freeKey> FreeKey;
typedef std::unique_ptr<unsigned char, decltype(&free)> BytesPtr;
+typedef std::unique_ptr<char, decltype(&free)> CharPtr;
} // namespace
nullptr, nullptr, nullptr, &ctx) == DCM_ERROR_UNKNOWN);
}
-POSITIVE_TEST_CASE(test20_dcm_api_bundle) {
+POSITIVE_TEST_CASE(test20_dcm_e2ee_bundle_api) {
BOOST_REQUIRE_NO_THROW(dcm_e2ee_free_bundle(NULL));
unsigned char payload[] = {1,2,3,4};
assert_positive(dcm_e2ee_get_bundle_payload, bundle, &cPayload, &cPayloadSize);
BOOST_REQUIRE_EQUAL(cPayloadSize, sizeof(payload));
BOOST_REQUIRE_EQUAL(memcmp(payload, cPayload, cPayloadSize), 0);
-
- // TODO create signed bundle
}
-NEGATIVE_TEST_CASE(test21_dcm_api_bundle) {
+NEGATIVE_TEST_CASE(test21_dcm_e2ee_bundle_api) {
unsigned char payload[] = {1,2,3,4};
unsigned char payload2[] = {'T', 'i', 'z', 'e', 'n', 0, 1, 2, 3, 4};
auto [msg, size] = makeMessage("Tizen", "User::Pkg::test", payload);
assert_positive(dcm_e2ee_create_bundle, msg, size, &bundle);
msgPtr.release();
- {
- FreeBundle freeBundle(bundle);
-
- const unsigned char* cMsg;
- size_t cMsgSize;
- assert_invalid_param(dcm_e2ee_get_bundle_message, nullptr, &cMsg, &cMsgSize);
- assert_invalid_param(dcm_e2ee_get_bundle_message, bundle, nullptr, &cMsgSize);
- assert_invalid_param(dcm_e2ee_get_bundle_message, bundle, &cMsg, nullptr);
-
- const char* cPlatform;
- assert_invalid_param(dcm_e2ee_get_bundle_platform, nullptr, &cPlatform);
- assert_invalid_param(dcm_e2ee_get_bundle_platform, bundle, nullptr);
-
- const char* cPkgId;
- assert_invalid_param(dcm_e2ee_get_bundle_pkg_id, nullptr, &cPkgId);
- assert_invalid_param(dcm_e2ee_get_bundle_pkg_id, bundle, nullptr);
-
- const unsigned char* cPayload;
- size_t cPayloadSize;
- assert_invalid_param(dcm_e2ee_get_bundle_payload, nullptr, &cPayload, &cPayloadSize);
- assert_invalid_param(dcm_e2ee_get_bundle_payload, bundle, nullptr, &cPayloadSize);
- assert_invalid_param(dcm_e2ee_get_bundle_payload, bundle, &cPayload, nullptr);
- }
- bundle = nullptr;
+ FreeBundle freeBundle(bundle);
+
+ const unsigned char* cMsg;
+ size_t cMsgSize;
+ assert_invalid_param(dcm_e2ee_get_bundle_message, nullptr, &cMsg, &cMsgSize);
+ assert_invalid_param(dcm_e2ee_get_bundle_message, bundle, nullptr, &cMsgSize);
+ assert_invalid_param(dcm_e2ee_get_bundle_message, bundle, &cMsg, nullptr);
+ const char* cPlatform;
+ assert_invalid_param(dcm_e2ee_get_bundle_platform, nullptr, &cPlatform);
+ assert_invalid_param(dcm_e2ee_get_bundle_platform, bundle, nullptr);
+
+ const char* cPkgId;
+ assert_invalid_param(dcm_e2ee_get_bundle_pkg_id, nullptr, &cPkgId);
+ assert_invalid_param(dcm_e2ee_get_bundle_pkg_id, bundle, nullptr);
+
+ const unsigned char* cPayload;
+ size_t cPayloadSize;
+ assert_invalid_param(dcm_e2ee_get_bundle_payload, nullptr, &cPayload, &cPayloadSize);
+ assert_invalid_param(dcm_e2ee_get_bundle_payload, bundle, nullptr, &cPayloadSize);
+ assert_invalid_param(dcm_e2ee_get_bundle_payload, bundle, &cPayload, nullptr);
+}
+
+POSITIVE_TEST_CASE(test22_dcm_e2ee_sign_api) {
+ unsigned char payload[] = {1,2,3,4};
void* ocfCtx = nullptr;
+
assert_positive(dcm_create_key_context, nullptr, nullptr, "ECDSA", &ocfCtx);
FreeKey freeOcfCtx(ocfCtx);
- char* signature;
- size_t signatureSize;
- assert_invalid_param(dcm_e2ee_create_signed_bundle,
- nullptr,
- DCM_DIGEST_SHA256,
- payload,
- sizeof(payload),
- &bundle,
- &signature,
- &signatureSize);
-
- assert_invalid_param(dcm_e2ee_create_signed_bundle,
- ocfCtx,
- DCM_DIGEST_SHA256,
- nullptr,
- sizeof(payload),
- &bundle,
- &signature,
- &signatureSize);
-
- assert_invalid_param(dcm_e2ee_create_signed_bundle,
- ocfCtx,
- DCM_DIGEST_SHA256,
- payload,
- sizeof(payload),
- nullptr,
- &signature,
- &signatureSize);
-
- assert_invalid_param(dcm_e2ee_create_signed_bundle,
- ocfCtx,
- DCM_DIGEST_SHA256,
- payload,
- sizeof(payload),
- &bundle,
- nullptr,
- &signatureSize);
-
- assert_invalid_param(dcm_e2ee_create_signed_bundle,
- ocfCtx,
- DCM_DIGEST_SHA256,
- payload,
- sizeof(payload),
- &bundle,
- &signature,
- nullptr);
+ dcm_e2ee_bundle_h bundle = nullptr;
+ char* sig = nullptr;
+ size_t sigSize;
+ assert_positive(dcm_e2ee_create_signed_bundle,
+ ocfCtx,
+ DCM_DIGEST_SHA256,
+ payload,
+ sizeof(payload),
+ &bundle,
+ &sig,
+ &sigSize);
+ FreeBundle freeBundle(bundle);
+ CharPtr signaturePtr(sig, free);
+ BOOST_REQUIRE(sig != nullptr);
+ BOOST_REQUIRE(sigSize > 0);
+ BOOST_REQUIRE(bundle != nullptr);
+
+ const unsigned char* cMsg;
+ size_t cMsgSize;
+ const char* cPlatform;
+ const char* cPkgId;
+ const unsigned char* cPayload;
+ size_t cPayloadSize;
+ assert_positive(dcm_e2ee_get_bundle_message, bundle, &cMsg, &cMsgSize);
+ assert_positive(dcm_e2ee_get_bundle_platform, bundle, &cPlatform);
+ assert_positive(dcm_e2ee_get_bundle_pkg_id, bundle, &cPkgId);
+ assert_positive(dcm_e2ee_get_bundle_payload, bundle, &cPayload, &cPayloadSize);
+
+ BOOST_REQUIRE(cPlatform != nullptr);
+ BOOST_REQUIRE(cPkgId != nullptr);
+
+ size_t cPlatformSize = strlen(cPlatform) + 1;
+ size_t cPkgIdSize = strlen(cPkgId) + 1;
+
+ BOOST_REQUIRE(cMsgSize > 0);
+ BOOST_REQUIRE(cPayloadSize > 0);
+ BOOST_REQUIRE(cPlatformSize + cPkgIdSize + cPayloadSize == cMsgSize);
+
+ char* label = nullptr;
+ BOOST_REQUIRE(smack_new_label_from_self(&label) >= 0);
+ BOOST_REQUIRE(label != nullptr);
+ std::string labelStr(label);
+ free(label);
+
+ BOOST_REQUIRE(strcmp(cPlatform, "Tizen") == 0);
+ BOOST_REQUIRE(labelStr == cPkgId);
+ BOOST_REQUIRE(memcmp(payload, cPayload, cPayloadSize) == 0);
+}
+
+NEGATIVE_TEST_CASE(test23_dcm_e2ee_sign_api) {
+ unsigned char payload[] = {1,2,3,4};
+ void* ocfCtx = nullptr;
+ assert_positive(dcm_create_key_context, nullptr, nullptr, "ECDSA", &ocfCtx);
+ FreeKey freeOcfCtx(ocfCtx);
+ dcm_e2ee_bundle_h bundle;
+
+ char* sig;
+ size_t sigSize;
+
+ auto invalid = [](const void *key_ctx,
+ dcm_digest_algorithm_e md,
+ const unsigned char *payload,
+ size_t payload_len,
+ dcm_e2ee_bundle_h *bundle,
+ char **signature,
+ size_t *signature_len){
+ assert_invalid_param(dcm_e2ee_create_signed_bundle,
+ key_ctx,
+ md,
+ payload,
+ payload_len,
+ bundle,
+ signature,
+ signature_len);
+ };
+
+ invalid(nullptr, DCM_DIGEST_SHA256, payload, sizeof(payload), &bundle, &sig, &sigSize);
+
+ // unsupported md
+ invalid(ocfCtx, DCM_DIGEST_NONE, payload, sizeof(payload), &bundle, &sig, &sigSize);
+ invalid(ocfCtx, DCM_DIGEST_MD2, payload, sizeof(payload), &bundle, &sig, &sigSize);
+ invalid(ocfCtx, DCM_DIGEST_MD4, payload, sizeof(payload), &bundle, &sig, &sigSize);
+ invalid(ocfCtx, DCM_DIGEST_MD5, payload, sizeof(payload), &bundle, &sig, &sigSize);
+ invalid(ocfCtx, DCM_DIGEST_RIPEMD160, payload, sizeof(payload), &bundle, &sig, &sigSize);
+
+ // dcm client will abort for values outside dcm_digest_algorithm_e range
+
+ invalid(ocfCtx, DCM_DIGEST_SHA256, nullptr, sizeof(payload), &bundle, &sig, &sigSize);
+ invalid(ocfCtx, DCM_DIGEST_SHA256, payload, sizeof(payload), nullptr, &sig, &sigSize);
+ invalid(ocfCtx, DCM_DIGEST_SHA256, payload, sizeof(payload), &bundle, nullptr, &sigSize);
+ invalid(ocfCtx, DCM_DIGEST_SHA256, payload, sizeof(payload), &bundle, &sig, nullptr);
}
BOOST_AUTO_TEST_SUITE_END()