2 * Network Configuration Module
4 * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 #include <sys/types.h>
25 #include <ckmc/ckmc-type.h>
26 #include <ckmc/ckmc-manager.h>
31 #include "wifi-key-encryption.h"
33 #define KEY_ALIAS "connman_wifi_passphrase"
34 #define IV_ALIAS "connman_wifi_enciv"
35 #define AAD_ALIAS "connman_wifi_gcmaad"
36 #define URANDOM "/dev/urandom"
38 #define PASSPHRASE "Passphrase"
40 #define AES_KEY_SIZE 256
41 #define CKMC_ERROR_HANDLING(expression, release) err = expression; \
42 if (CKMC_ERROR_NONE != err) { \
43 err_str = get_error_message(err); \
44 ERR(#expression " : %s", err_str); \
48 DBG(#expression " success");
54 static int __netconfig_generate_random_bytes(unsigned char* bytes, int len)
62 urfd = open(URANDOM, O_RDONLY);
64 ERR("Could not open "URANDOM);
67 r = read(urfd, bytes, len);
69 ERR("Could not read from "URANDOM);
72 } else if (r != len) {
73 ERR("Short read from "URANDOM);
83 static void __netconfig_convert_hexstr_to_bytes(gchar* hexstr, int hlen, gchar* bin)
88 if (*hexstr >= '0' && *hexstr <= '9')
89 *bin = (*hexstr - '0') << 4;
90 else if (*hexstr >= 'a' && *hexstr <= 'f')
91 *bin = (*hexstr - 'a' + 10) << 4;
95 if (*hexstr >= '0' && *hexstr <= '9')
96 *bin |= (*hexstr - '0') & 0x0f;
97 else if (*hexstr >= 'a' && *hexstr <= 'f')
98 *bin |= (*hexstr - 'a' + 10) & 0x0f;
106 static int __netconfig_generate_aes_key()
109 pol.extractable = false;
113 err = ckmc_create_key_aes(AES_KEY_SIZE, KEY_ALIAS, pol);
115 if (err != CKMC_ERROR_NONE && err != CKMC_ERROR_DB_ALIAS_EXISTS)
118 return CKMC_ERROR_NONE;
121 static void* __netconfig_set_param_list_aes_gcm(ckmc_param_list_h param)
123 ckmc_raw_buffer_s *iv_buf = NULL;
124 unsigned char rnd[RND_LENGTH];
125 ckmc_raw_buffer_s *aad_buf = NULL;
126 unsigned char aad[RND_LENGTH];
128 err = ckmc_get_data(IV_ALIAS, NULL, &iv_buf);
130 if (err == CKMC_ERROR_DB_ALIAS_UNKNOWN) {
131 ckmc_policy_s policy;
132 policy.extractable = true;
133 policy.password = NULL;
135 if (!__netconfig_generate_random_bytes(rnd, RND_LENGTH))
139 ckmc_buffer_new(rnd, RND_LENGTH, &iv_buf),
143 ckmc_save_data(IV_ALIAS, *iv_buf, policy),
144 ckmc_buffer_free(iv_buf));
147 err = ckmc_get_data(AAD_ALIAS, NULL, &aad_buf);
149 if (err == CKMC_ERROR_DB_ALIAS_UNKNOWN) {
150 ckmc_policy_s policy;
151 policy.extractable = true;
152 policy.password = NULL;
154 if (!__netconfig_generate_random_bytes(aad, RND_LENGTH)) {
155 ckmc_buffer_free(iv_buf);
160 ckmc_buffer_new(aad, RND_LENGTH, &aad_buf),
161 ckmc_buffer_free(iv_buf));
164 ckmc_save_data(AAD_ALIAS, *aad_buf, policy),
165 ckmc_buffer_free(iv_buf);\
166 ckmc_buffer_free(aad_buf));
170 ckmc_param_list_set_buffer(param, CKMC_PARAM_ED_IV, iv_buf),
171 ckmc_buffer_free(iv_buf);\
172 ckmc_buffer_free(aad_buf));
175 ckmc_param_list_set_buffer(param, CKMC_PARAM_ED_AAD, aad_buf),
176 ckmc_buffer_free(iv_buf);\
177 ckmc_buffer_free(aad_buf));
179 return GINT_TO_POINTER(1);
182 gchar* _netconfig_encrypt_passphrase(const gchar *passphrase)
184 gchar* origin_value = NULL;
185 gchar* encrypted_value = NULL;
187 ckmc_param_list_h param = NULL;
188 ckmc_raw_buffer_s *ptext = NULL;
189 ckmc_raw_buffer_s *ctext = NULL;
194 origin_value = g_strdup(passphrase);
197 __netconfig_generate_aes_key(),
198 g_free(origin_value));
201 ckmc_generate_new_params(CKMC_ALGO_AES_GCM, ¶m),
202 g_free(origin_value));
204 if (__netconfig_set_param_list_aes_gcm(param) == NULL) {
205 ckmc_param_list_free(param);
206 g_free(origin_value);
211 ckmc_buffer_new((unsigned char*)origin_value,
212 strlen((char*)origin_value) + 1, &ptext),
213 ckmc_param_list_free(param);\
214 g_free(origin_value));
217 ckmc_encrypt_data(param, KEY_ALIAS, NULL, *ptext, &ctext),
218 ckmc_param_list_free(param);\
219 ckmc_buffer_free(ptext);\
220 g_free(origin_value));
223 (encrypted_value = g_try_malloc0(ctext->size * 2 + 1)) == NULL) {
224 DBG(" encrypted_value allocation failed");
225 ckmc_param_list_free(param);
226 ckmc_buffer_free(ptext);
227 ckmc_buffer_free(ctext);
228 g_free(origin_value);
232 netconfig_convert_bytes_to_hexstr((const char *)ctext->data, ctext->size, encrypted_value);
234 g_free(origin_value);
236 ckmc_param_list_free(param);
237 ckmc_buffer_free(ptext);
238 ckmc_buffer_free(ctext);
240 return encrypted_value;
243 static gchar* _netconfig_decrypt_passphrase(const gchar *enc_data)
245 gchar *ehexstr = NULL;
246 gchar *encrypted_value = NULL;
247 gchar *passphrase = NULL;
249 ckmc_param_list_h param = NULL;
250 ckmc_raw_buffer_s *ptext = NULL;
251 ckmc_raw_buffer_s *ctext = NULL;
256 ehexstr = g_strdup(enc_data);
259 ckmc_generate_new_params(CKMC_ALGO_AES_GCM, ¶m),
262 if (__netconfig_set_param_list_aes_gcm(param) == NULL) {
263 ckmc_param_list_free(param);
268 if ((encrypted_value = g_try_malloc0(strlen((char*)ehexstr)/2)) == NULL) {
269 DBG(" encrypted_value allocation failed");
270 ckmc_param_list_free(param);
275 __netconfig_convert_hexstr_to_bytes(ehexstr, strlen((char*)ehexstr), encrypted_value);
278 ckmc_buffer_new((unsigned char*)encrypted_value,
279 strlen((char*)ehexstr)/2, &ctext),
280 ckmc_param_list_free(param);\
281 g_free(encrypted_value);\
287 ckmc_decrypt_data(param, KEY_ALIAS, NULL, *ctext, &ptext),
288 ckmc_param_list_free(param);\
289 ckmc_buffer_free(ctext);\
290 g_free(encrypted_value));
293 passphrase = g_strdup((const gchar*)ptext->data);
295 ckmc_param_list_free(param);
296 ckmc_buffer_free(ctext);
297 ckmc_buffer_free(ptext);
298 g_free(encrypted_value);
303 gboolean handle_encrypt_passphrase(Wifi *wifi, GDBusMethodInvocation *context, const gchar *passphrase)
305 gchar *enc_data = NULL;
307 if ((wifi == NULL) || (passphrase == NULL)) {
308 ERR("Invalid parameter");
309 netconfig_error_invalid_parameter(context);
313 enc_data = _netconfig_encrypt_passphrase(passphrase);
316 ERR("Failed to encrypt the passphrase");
317 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed");
321 wifi_complete_encrypt_passphrase(wifi, context, enc_data);
327 gboolean handle_decrypt_passphrase(Wifi *wifi, GDBusMethodInvocation *context, const gchar *enc_data)
329 gchar *passphrase = NULL;
331 if ((wifi == NULL) || (enc_data == NULL)) {
332 ERR("Invalid parameter");
333 netconfig_error_invalid_parameter(context);
337 passphrase = _netconfig_decrypt_passphrase(enc_data);
340 ERR("Failed to decrypt the passphrase");
341 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed");
345 wifi_complete_decrypt_passphrase(wifi, context, passphrase);
351 gboolean handle_decrypt_conf_obj(Wifi *wifi, GDBusMethodInvocation *context,
352 const gchar *enc_connector,
353 const gchar *enc_c_sign_key,
354 const gchar *enc_net_access_key)
356 GVariantBuilder *builder = NULL;
357 gchar *connector = NULL;
358 gchar *c_sign_key = NULL;
359 gchar *net_access_key = NULL;
362 if (!wifi || !enc_connector || !enc_c_sign_key || !enc_net_access_key) {
363 ERR("Invalid parameter");
364 netconfig_error_invalid_parameter(context);
368 connector = _netconfig_decrypt_passphrase(enc_connector);
369 c_sign_key = _netconfig_decrypt_passphrase(enc_c_sign_key);
370 net_access_key = _netconfig_decrypt_passphrase(enc_net_access_key);
372 if (!connector || !c_sign_key || !net_access_key) {
373 ERR("Failed to decrypt the configuration object");
374 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed");
377 g_free(net_access_key);
381 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
382 g_variant_builder_add(builder, "{sv}", "connector",
383 g_variant_new_string(connector));
384 g_variant_builder_add(builder, "{sv}", "c_sign_key",
385 g_variant_new_string(c_sign_key));
386 g_variant_builder_add(builder, "{sv}", "net_access_key",
387 g_variant_new_string(net_access_key));
389 wifi_complete_decrypt_conf_obj(wifi, context, g_variant_builder_end(builder));
390 g_variant_builder_unref(builder);
393 g_free(net_access_key);