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 ******************************************************************/
24 #include "device_certificate_manager.h"
25 #include "dcm_client.h"
29 #ifndef API_DEVICE_CERTIFICATE_MANAGER_EXPORT
30 #define API_DEVICE_CERTIFICATE_MANAGER_EXPORT __attribute__((visibility("default")))
33 struct dcm_key_context_internal {
34 std::shared_ptr<dcm_client_connection> connection;
37 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
38 int dcm_create_key_context(const char *service, const char *usage, const char *key_type, void **key_ctx)
42 return DCM_ERROR_INVALID_PARAMETER;
44 std::unique_ptr<dcm_key_context_internal> context(new dcm_key_context_internal());
46 std::string service_string(service ? service : "");
47 std::string usage_string(usage ? usage : "");
48 std::string keytype_string(key_type ? key_type : "");
50 context->connection = dcm_client_connection::create();
52 int result = context->connection->create_context(service_string, usage_string, keytype_string);
53 if(result != DCM_ERROR_NONE) {
54 LOGE("Can't create connection context");
58 *key_ctx = context.release();
59 } catch(std::exception& ex) {
60 LOGE("Context creation failure: %s", ex.what());
61 return DCM_ERROR_UNKNOWN;
63 LOGE("Context creation failure");
64 return DCM_ERROR_UNKNOWN;
67 return DCM_ERROR_NONE;
70 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
71 int dcm_free_key_context(void *key_ctx)
74 return DCM_ERROR_NONE;
76 delete reinterpret_cast<dcm_key_context_internal *>(key_ctx);
78 return DCM_ERROR_NONE;
81 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
82 int dcm_get_certificate_chain(const void *key_ctx, char **cert_chain, size_t *cert_chain_len)
84 if(!key_ctx || !cert_chain || !cert_chain_len)
85 return DCM_ERROR_INVALID_PARAMETER;
87 const dcm_key_context_internal *context =
88 reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
90 std::vector<uint8_t> cert;
91 int result = context->connection->get_certificate_chain(cert);
92 if(result == DCM_ERROR_NONE) {
93 *cert_chain = (char*)malloc(sizeof(uint8_t) * cert.size());
94 if(*cert_chain == NULL)
95 return DCM_ERROR_OUT_OF_MEMORY;
96 memcpy(*cert_chain, cert.data(), cert.size());
97 *cert_chain_len = cert.size();
103 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
104 int dcm_get_key_bit_length(const void *key_ctx, size_t *key_bit_len)
106 if(!key_ctx || !key_bit_len)
107 return DCM_ERROR_INVALID_PARAMETER;
109 const dcm_key_context_internal *context =
110 reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
111 *key_bit_len = context->connection->key_length();
113 return DCM_ERROR_NONE;
116 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
117 int dcm_get_key_type(const void *key_ctx, char **key_type)
119 if(!key_ctx || !key_type)
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::string type = context->connection->key_type();
126 *key_type = (char*)malloc(sizeof(char) * (type.length() + 1));
127 if(*key_type == NULL)
128 return DCM_ERROR_OUT_OF_MEMORY;
129 memcpy(*key_type, type.c_str(), type.length() + 1);
131 return DCM_ERROR_NONE;
134 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
135 int dcm_create_signature(const void *key_ctx, dcm_digest_algorithm_e md,
136 const char *message, size_t message_len,
137 char **signature, size_t *signature_len)
139 if(!key_ctx || !signature || !signature_len)
140 return DCM_ERROR_INVALID_PARAMETER;
142 const dcm_key_context_internal *context =
143 reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
145 std::vector<uint8_t> digest;
146 int result = context->connection->sign_data(md, message, message_len, digest);
147 if(result == DCM_ERROR_NONE) {
148 *signature = (char*)malloc(sizeof(uint8_t) * digest.size());
149 if(*signature == NULL)
150 return DCM_ERROR_OUT_OF_MEMORY;
151 memcpy(*signature, digest.data(), digest.size());
152 *signature_len = digest.size();
159 * @brief Struct containing E2EE message bundle. Message = platform | pkg_id | payload.
160 * @remarks The platform and pkg_id are NULL terminated strings. The payload is a sequence of bytes.
163 struct dcm_e2ee_bundle_s {
164 unsigned char *message; /**< Byte array containing whole message */
165 size_t message_len; /**< The size of the message */
166 size_t pkg_id_offset; /**< Package id offset */
167 size_t payload_offset; /**< Payload offset */
170 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
171 int dcm_e2ee_create_bundle(unsigned char *message,
173 dcm_e2ee_bundle_h* bundle)
175 if (message == NULL || bundle == NULL)
176 return DCM_ERROR_INVALID_PARAMETER;
178 struct dcm_e2ee_bundle_s *tmp = static_cast<struct dcm_e2ee_bundle_s*>(
179 malloc(sizeof(struct dcm_e2ee_bundle_s)));
182 return DCM_ERROR_OUT_OF_MEMORY;
184 int ret = decompose_e2ee_message(message, message_len, tmp->pkg_id_offset, tmp->payload_offset);
185 if (ret != DCM_ERROR_NONE) {
190 tmp->message_len = message_len;
191 tmp->message = message;
194 return DCM_ERROR_NONE;
197 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
198 void dcm_e2ee_free_bundle(dcm_e2ee_bundle_h bundle)
203 free(bundle->message);
207 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
208 int dcm_e2ee_get_bundle_message(const dcm_e2ee_bundle_h bundle,
209 const unsigned char** message,
212 if (bundle == NULL || message == NULL || message_len == NULL)
213 return DCM_ERROR_INVALID_PARAMETER;
215 assert(bundle->message != NULL);
217 *message = bundle->message;
218 *message_len = bundle->message_len;
219 return DCM_ERROR_NONE;
222 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
223 int dcm_e2ee_get_bundle_platform(const dcm_e2ee_bundle_h bundle, const char** platform)
225 if (bundle == NULL || platform == NULL)
226 return DCM_ERROR_INVALID_PARAMETER;
228 assert(bundle->message != NULL);
230 *platform = reinterpret_cast<const char*>(bundle->message);
231 return DCM_ERROR_NONE;
234 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
235 int dcm_e2ee_get_bundle_pkg_id(const dcm_e2ee_bundle_h bundle, const char** pkg_id)
237 if (bundle == NULL || pkg_id == NULL)
238 return DCM_ERROR_INVALID_PARAMETER;
240 assert(bundle->message != NULL);
242 *pkg_id = reinterpret_cast<const char*>(&bundle->message[bundle->pkg_id_offset]);
243 return DCM_ERROR_NONE;
246 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
247 int dcm_e2ee_get_bundle_payload(const dcm_e2ee_bundle_h bundle,
248 const unsigned char** payload,
251 if (bundle == NULL || payload == NULL || payload_len == NULL)
252 return DCM_ERROR_INVALID_PARAMETER;
254 assert(bundle->message != NULL);
256 *payload = &bundle->message[bundle->payload_offset];
257 *payload_len = bundle->message_len - bundle->payload_offset;
258 return DCM_ERROR_NONE;
261 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
262 int dcm_e2ee_create_signed_bundle(const void *key_ctx,
263 dcm_digest_algorithm_e md,
264 const unsigned char *payload,
266 dcm_e2ee_bundle_h *bundle,
268 size_t *signature_len)
270 if (key_ctx == NULL || payload == NULL || bundle == NULL || signature == NULL ||
271 signature_len == NULL)
272 return DCM_ERROR_INVALID_PARAMETER;
274 const dcm_key_context_internal *context =
275 reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
277 std::vector<uint8_t> digest;
278 std::vector<uint8_t> message;
279 int result = context->connection->e2ee_sign_data(md, payload, payload_len, message, digest);
280 if(result == DCM_ERROR_NONE) {
281 *signature = static_cast<char*>(malloc(sizeof(uint8_t) * digest.size()));
282 if(*signature == NULL)
283 return DCM_ERROR_OUT_OF_MEMORY;
284 memcpy(*signature, digest.data(), digest.size());
285 *signature_len = digest.size();
287 auto message_dup = static_cast<unsigned char*>(malloc(sizeof(uint8_t)*message.size()));
288 if(message_dup == NULL) {
290 return DCM_ERROR_OUT_OF_MEMORY;
292 memcpy(message_dup, message.data(), message.size());
294 result = dcm_e2ee_create_bundle(message_dup, message.size(), bundle);
295 assert(result == DCM_ERROR_NONE);