ea46dc3a8c2437239e4916408a2e5fdd89672759
[platform/core/security/device-certificate-manager.git] / src / dcm-client / device_certificate_manager.cpp
1 /******************************************************************
2  *
3  * Copyright 2017 - 2020 Samsung Electronics All Rights Reserved.
4  *
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  ******************************************************************/
18
19 #include <vector>
20 #include <cstring>
21 #include <cstdlib>
22 #include <cassert>
23
24 #include "device_certificate_manager.h"
25 #include "dcm_client.h"
26 #include "log.h"
27 #include "bundle.h"
28
29 #ifndef API_DEVICE_CERTIFICATE_MANAGER_EXPORT
30 #define API_DEVICE_CERTIFICATE_MANAGER_EXPORT __attribute__((visibility("default")))
31 #endif
32
33 struct dcm_key_context_internal {
34         std::shared_ptr<dcm_client_connection> connection;
35 };
36
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)
39 {
40         try {
41                 if(!key_ctx)
42                         return DCM_ERROR_INVALID_PARAMETER;
43
44                 std::unique_ptr<dcm_key_context_internal> context(new dcm_key_context_internal());
45
46                 std::string service_string(service ? service : "");
47                 std::string usage_string(usage ? usage : "");
48                 std::string keytype_string(key_type ? key_type : "");
49
50                 context->connection = dcm_client_connection::create();
51
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");
55                         return result;
56                 }
57
58                 *key_ctx = context.release();
59         } catch(std::exception& ex) {
60                 LOGE("Context creation failure: %s", ex.what());
61                 return DCM_ERROR_UNKNOWN;
62         } catch(...) {
63                 LOGE("Context creation failure");
64                 return DCM_ERROR_UNKNOWN;
65         }
66
67         return DCM_ERROR_NONE;
68 }
69
70 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
71 int dcm_free_key_context(void *key_ctx)
72 {
73         if(!key_ctx)
74                 return DCM_ERROR_NONE;
75
76         delete reinterpret_cast<dcm_key_context_internal *>(key_ctx);
77
78         return DCM_ERROR_NONE;
79 }
80
81 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
82 int dcm_get_certificate_chain(const void *key_ctx, char **cert_chain, size_t *cert_chain_len)
83 {
84         if(!key_ctx || !cert_chain || !cert_chain_len)
85                 return DCM_ERROR_INVALID_PARAMETER;
86
87         const dcm_key_context_internal *context =
88                 reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
89
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();
98         }
99
100         return result;
101 }
102
103 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
104 int dcm_get_key_bit_length(const void *key_ctx, size_t *key_bit_len)
105 {
106         if(!key_ctx || !key_bit_len)
107                 return DCM_ERROR_INVALID_PARAMETER;
108
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();
112
113         return DCM_ERROR_NONE;
114 }
115
116 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
117 int dcm_get_key_type(const void *key_ctx, char **key_type)
118 {
119         if(!key_ctx || !key_type)
120                 return DCM_ERROR_INVALID_PARAMETER;
121
122         const dcm_key_context_internal *context =
123                 reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
124
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);
130
131         return DCM_ERROR_NONE;
132 }
133
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)
138 {
139         if(!key_ctx || !signature || !signature_len)
140                 return DCM_ERROR_INVALID_PARAMETER;
141
142         const dcm_key_context_internal *context =
143                 reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
144
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();
153         }
154
155         return result;
156 }
157
158 /**
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.
161  * @since_tizen 6.5
162  */
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 */
168 };
169
170 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
171 int dcm_e2ee_create_bundle(unsigned char *message,
172         size_t message_len,
173         dcm_e2ee_bundle_h* bundle)
174 {
175         if (message == NULL || bundle == NULL)
176                 return DCM_ERROR_INVALID_PARAMETER;
177
178         struct dcm_e2ee_bundle_s *tmp = static_cast<struct dcm_e2ee_bundle_s*>(
179                 malloc(sizeof(struct dcm_e2ee_bundle_s)));
180
181         if (tmp == NULL)
182                 return DCM_ERROR_OUT_OF_MEMORY;
183
184         int ret = decompose_e2ee_message(message, message_len, tmp->pkg_id_offset, tmp->payload_offset);
185         if (ret != DCM_ERROR_NONE) {
186                 free(tmp);
187                 return ret;
188         }
189
190         tmp->message_len = message_len;
191         tmp->message = message;
192
193         *bundle = tmp;
194         return DCM_ERROR_NONE;
195 }
196
197 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
198 void dcm_e2ee_free_bundle(dcm_e2ee_bundle_h bundle)
199 {
200         if (bundle == NULL)
201                 return;
202
203         free(bundle->message);
204         free(bundle);
205 }
206
207 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
208 int dcm_e2ee_get_bundle_message(const dcm_e2ee_bundle_h bundle,
209         const unsigned char** message,
210         size_t* message_len)
211 {
212         if (bundle == NULL || message == NULL || message_len == NULL)
213                 return DCM_ERROR_INVALID_PARAMETER;
214
215         assert(bundle->message != NULL);
216
217         *message = bundle->message;
218         *message_len = bundle->message_len;
219         return DCM_ERROR_NONE;
220 }
221
222 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
223 int dcm_e2ee_get_bundle_platform(const dcm_e2ee_bundle_h bundle, const char** platform)
224 {
225         if (bundle == NULL || platform == NULL)
226                 return DCM_ERROR_INVALID_PARAMETER;
227
228         assert(bundle->message != NULL);
229
230         *platform = reinterpret_cast<const char*>(bundle->message);
231         return DCM_ERROR_NONE;
232 }
233
234 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
235 int dcm_e2ee_get_bundle_pkg_id(const dcm_e2ee_bundle_h bundle, const char** pkg_id)
236 {
237         if (bundle == NULL || pkg_id == NULL)
238                 return DCM_ERROR_INVALID_PARAMETER;
239
240         assert(bundle->message != NULL);
241
242         *pkg_id = reinterpret_cast<const char*>(&bundle->message[bundle->pkg_id_offset]);
243         return DCM_ERROR_NONE;
244 }
245
246 API_DEVICE_CERTIFICATE_MANAGER_EXPORT
247 int dcm_e2ee_get_bundle_payload(const dcm_e2ee_bundle_h bundle,
248         const unsigned char** payload,
249         size_t* payload_len)
250 {
251         if (bundle == NULL || payload == NULL || payload_len == NULL)
252                 return DCM_ERROR_INVALID_PARAMETER;
253
254         assert(bundle->message != NULL);
255
256         *payload = &bundle->message[bundle->payload_offset];
257         *payload_len = bundle->message_len - bundle->payload_offset;
258         return DCM_ERROR_NONE;
259 }
260
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,
265         size_t payload_len,
266         dcm_e2ee_bundle_h *bundle,
267         char **signature,
268         size_t *signature_len)
269 {
270         if (key_ctx == NULL || payload == NULL || bundle == NULL || signature == NULL ||
271                 signature_len == NULL)
272                 return DCM_ERROR_INVALID_PARAMETER;
273
274         const dcm_key_context_internal *context =
275                 reinterpret_cast<const dcm_key_context_internal *>(key_ctx);
276
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();
286
287                 auto message_dup = static_cast<unsigned char*>(malloc(sizeof(uint8_t)*message.size()));
288                 if(message_dup == NULL) {
289                         free(signature);
290                         return DCM_ERROR_OUT_OF_MEMORY;
291                 }
292                 memcpy(message_dup, message.data(), message.size());
293
294                 result = dcm_e2ee_create_bundle(message_dup, message.size(), bundle);
295                 assert(result == DCM_ERROR_NONE);
296         }
297
298         return result;
299 }