1 /******************************************************************
3 * Copyright 2017 - 2020 Samsung Electronics All Rights Reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 ******************************************************************/
25 #include <system_info.h>
27 #include "device_certificate_manager.h"
28 #include "dcm_client.h"
32 #ifndef API_DEVICE_CERTIFICATE_MANAGER_EXPORT
33 #define API_DEVICE_CERTIFICATE_MANAGER_EXPORT __attribute__((visibility("default")))
36 std::once_flag check_flag;
37 static int check_result;
39 void check_feature(void)
42 if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_bool(
43 "http://tizen.org/feature/security.device_certificate", &is_supported))
44 check_result = DCM_ERROR_UNKNOWN;
45 else if (!is_supported)
46 check_result = DCM_ERROR_NOT_SUPPORTED;
48 check_result = DCM_ERROR_NONE;
51 #define CHECK_FEATURE_SUPPORTED \
54 std::call_once(check_flag, check_feature); \
55 if (check_result != DCM_ERROR_NONE) \
56 return check_result; \
58 return DCM_ERROR_UNKNOWN; \
62 struct dcm_key_context_internal {
63 std::shared_ptr<dcm_client_connection> connection;
66 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
67 int dcm_create_key_context(const char *service, const char *usage, const char *key_type, void **key_ctx)
69 CHECK_FEATURE_SUPPORTED;
73 return DCM_ERROR_INVALID_PARAMETER;
75 std::unique_ptr<dcm_key_context_internal> context(new dcm_key_context_internal());
77 std::string service_string(service ? service : "");
78 std::string usage_string(usage ? usage : "");
79 std::string keytype_string(key_type ? key_type : "");
81 context->connection = dcm_client_connection::create();
83 int result = context->connection->create_context(service_string, usage_string, keytype_string);
84 if(result != DCM_ERROR_NONE) {
85 LOGE("Can't create connection context");
89 *key_ctx = context.release();
90 } catch(std::exception& ex) {
91 LOGE("Context creation failure: %s", ex.what());
92 return DCM_ERROR_UNKNOWN;
94 LOGE("Context creation failure");
95 return DCM_ERROR_UNKNOWN;
98 return DCM_ERROR_NONE;
101 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
102 int dcm_free_key_context(void *key_ctx)
104 CHECK_FEATURE_SUPPORTED;
107 return DCM_ERROR_NONE;
109 delete reinterpret_cast<dcm_key_context_internal *>(key_ctx);
111 return DCM_ERROR_NONE;
114 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
115 int dcm_get_certificate_chain(const void *key_ctx, char **cert_chain, size_t *cert_chain_len)
117 CHECK_FEATURE_SUPPORTED;
119 if(!key_ctx || !cert_chain || !cert_chain_len)
120 return DCM_ERROR_INVALID_PARAMETER;
122 const dcm_key_context_internal *context =
123 reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
125 std::vector<uint8_t> cert;
126 int result = context->connection->get_certificate_chain(cert);
127 if(result == DCM_ERROR_NONE) {
128 *cert_chain = (char*)malloc(sizeof(uint8_t) * cert.size());
129 if(*cert_chain == NULL)
130 return DCM_ERROR_OUT_OF_MEMORY;
131 memcpy(*cert_chain, cert.data(), cert.size());
132 *cert_chain_len = cert.size();
138 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
139 int dcm_get_key_bit_length(const void *key_ctx, size_t *key_bit_len)
141 CHECK_FEATURE_SUPPORTED;
143 if(!key_ctx || !key_bit_len)
144 return DCM_ERROR_INVALID_PARAMETER;
146 const dcm_key_context_internal *context =
147 reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
148 *key_bit_len = context->connection->key_length();
150 return DCM_ERROR_NONE;
153 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
154 int dcm_get_key_type(const void *key_ctx, char **key_type)
156 CHECK_FEATURE_SUPPORTED;
158 if(!key_ctx || !key_type)
159 return DCM_ERROR_INVALID_PARAMETER;
161 const dcm_key_context_internal *context =
162 reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
164 std::string type = context->connection->key_type();
165 *key_type = (char*)malloc(sizeof(char) * (type.length() + 1));
166 if(*key_type == NULL)
167 return DCM_ERROR_OUT_OF_MEMORY;
168 memcpy(*key_type, type.c_str(), type.length() + 1);
170 return DCM_ERROR_NONE;
173 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
174 int dcm_create_signature(const void *key_ctx, dcm_digest_algorithm_e md,
175 const char *message, size_t message_len,
176 char **signature, size_t *signature_len)
178 CHECK_FEATURE_SUPPORTED;
180 if(!key_ctx || !signature || !signature_len)
181 return DCM_ERROR_INVALID_PARAMETER;
183 const dcm_key_context_internal *context =
184 reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
186 std::vector<uint8_t> digest;
187 int result = context->connection->sign_data(md, message, message_len, digest);
188 if(result == DCM_ERROR_NONE) {
189 *signature = (char*)malloc(sizeof(uint8_t) * digest.size());
190 if(*signature == NULL)
191 return DCM_ERROR_OUT_OF_MEMORY;
192 memcpy(*signature, digest.data(), digest.size());
193 *signature_len = digest.size();
200 * @brief Struct containing E2EE message bundle. Message = platform | pkg_id | payload.
201 * @remarks The platform and pkg_id are NULL terminated strings. The payload is a sequence of bytes.
204 struct dcm_e2ee_bundle_s {
205 unsigned char *message; /**< Byte array containing whole message */
206 size_t message_len; /**< The size of the message */
207 size_t pkg_id_offset; /**< Package id offset */
208 size_t payload_offset; /**< Payload offset */
211 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
212 int dcm_e2ee_create_bundle(unsigned char *message,
214 dcm_e2ee_bundle_h* bundle)
216 CHECK_FEATURE_SUPPORTED;
218 if (message == NULL || bundle == NULL)
219 return DCM_ERROR_INVALID_PARAMETER;
221 struct dcm_e2ee_bundle_s *tmp = static_cast<struct dcm_e2ee_bundle_s*>(
222 malloc(sizeof(struct dcm_e2ee_bundle_s)));
225 return DCM_ERROR_OUT_OF_MEMORY;
227 int ret = decompose_e2ee_message(message, message_len, tmp->pkg_id_offset, tmp->payload_offset);
228 if (ret != DCM_ERROR_NONE) {
233 tmp->message_len = message_len;
234 tmp->message = message;
237 return DCM_ERROR_NONE;
240 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
241 void dcm_e2ee_free_bundle(dcm_e2ee_bundle_h bundle)
246 free(bundle->message);
250 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
251 int dcm_e2ee_get_bundle_message(const dcm_e2ee_bundle_h bundle,
252 const unsigned char** message,
255 CHECK_FEATURE_SUPPORTED;
257 if (bundle == NULL || message == NULL || message_len == NULL)
258 return DCM_ERROR_INVALID_PARAMETER;
260 assert(bundle->message != NULL);
262 *message = bundle->message;
263 *message_len = bundle->message_len;
264 return DCM_ERROR_NONE;
267 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
268 int dcm_e2ee_get_bundle_platform(const dcm_e2ee_bundle_h bundle, const char** platform)
270 CHECK_FEATURE_SUPPORTED;
272 if (bundle == NULL || platform == NULL)
273 return DCM_ERROR_INVALID_PARAMETER;
275 assert(bundle->message != NULL);
277 *platform = reinterpret_cast<const char*>(bundle->message);
278 return DCM_ERROR_NONE;
281 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
282 int dcm_e2ee_get_bundle_pkg_id(const dcm_e2ee_bundle_h bundle, const char** pkg_id)
284 CHECK_FEATURE_SUPPORTED;
286 if (bundle == NULL || pkg_id == NULL)
287 return DCM_ERROR_INVALID_PARAMETER;
289 assert(bundle->message != NULL);
291 *pkg_id = reinterpret_cast<const char*>(&bundle->message[bundle->pkg_id_offset]);
292 return DCM_ERROR_NONE;
295 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
296 int dcm_e2ee_get_bundle_payload(const dcm_e2ee_bundle_h bundle,
297 const unsigned char** payload,
300 CHECK_FEATURE_SUPPORTED;
302 if (bundle == NULL || payload == NULL || payload_len == NULL)
303 return DCM_ERROR_INVALID_PARAMETER;
305 assert(bundle->message != NULL);
307 *payload = &bundle->message[bundle->payload_offset];
308 *payload_len = bundle->message_len - bundle->payload_offset;
309 return DCM_ERROR_NONE;
312 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
313 int dcm_e2ee_create_signed_bundle(const void *key_ctx,
314 dcm_digest_algorithm_e md,
315 const unsigned char *payload,
317 dcm_e2ee_bundle_h *bundle,
319 size_t *signature_len)
321 CHECK_FEATURE_SUPPORTED;
323 if (key_ctx == NULL || payload == NULL || bundle == NULL || signature == NULL ||
324 signature_len == NULL)
325 return DCM_ERROR_INVALID_PARAMETER;
327 const dcm_key_context_internal *context =
328 reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
330 std::vector<uint8_t> digest;
331 std::vector<uint8_t> message;
332 int result = context->connection->e2ee_sign_data(md, payload, payload_len, message, digest);
333 if(result == DCM_ERROR_NONE) {
334 *signature = static_cast<char*>(malloc(sizeof(uint8_t) * digest.size()));
335 if(*signature == NULL)
336 return DCM_ERROR_OUT_OF_MEMORY;
337 memcpy(*signature, digest.data(), digest.size());
338 *signature_len = digest.size();
340 auto message_dup = static_cast<unsigned char*>(malloc(sizeof(uint8_t)*message.size()));
341 if(message_dup == NULL) {
343 return DCM_ERROR_OUT_OF_MEMORY;
345 memcpy(message_dup, message.data(), message.size());
347 result = dcm_e2ee_create_bundle(message_dup, message.size(), bundle);
348 assert(result == DCM_ERROR_NONE);