From 40e2e3e7656636f9a5db317fed1923ed84fffd64 Mon Sep 17 00:00:00 2001 From: sairoop-elear Date: Thu, 25 Apr 2019 09:08:31 +0530 Subject: [PATCH] Add encrypted key rotation feature api --- src/conf.c | 49 ++++------- src/meshlink.c | 81 ++++++++++++++++--- .../test_cases_key_rotation.c | 8 +- 3 files changed, 88 insertions(+), 50 deletions(-) diff --git a/src/conf.c b/src/conf.c index 5db2c016..a9e3e4d6 100644 --- a/src/conf.c +++ b/src/conf.c @@ -206,6 +206,10 @@ static bool copytree(const char *src_dir_name, const void *src_key, const char * return false; } + char src_filename[PATH_MAX]; + char dst_filename[PATH_MAX]; + struct dirent *ent; + DIR *src_dir = opendir(src_dir_name); if(!src_dir) { @@ -213,29 +217,23 @@ static bool copytree(const char *src_dir_name, const void *src_key, const char * return false; } - struct dirent *ent; + // Delete if already exists and create a new destination directory + deltree(dst_dir_name); + + if(mkdir(dst_dir_name, 0700)) { + logger(NULL, MESHLINK_ERROR, "Could not create directory %s\n", dst_filename); + return false; + } while((ent = readdir(src_dir))) { if(ent->d_name[0] == '.') { continue; } - char src_filename[PATH_MAX]; - char dst_filename[PATH_MAX]; - snprintf(dst_filename, sizeof(dst_filename), "%s" SLASH "%s", dst_dir_name, ent->d_name); snprintf(src_filename, sizeof(src_filename), "%s" SLASH "%s", src_dir_name, ent->d_name); if(ent->d_type == DT_DIR) { - - // Delete if already exists and create a new destination directory - deltree(dst_filename); - - if(mkdir(dst_filename, 0700)) { - logger(NULL, MESHLINK_ERROR, "Could create directory %s\n", dst_filename); - return false; - } - if(!copytree(src_filename, src_key, dst_filename, dst_key)) { logger(NULL, MESHLINK_ERROR, "Copying %s to %s failed\n", src_filename, dst_filename); return false; @@ -244,7 +242,6 @@ static bool copytree(const char *src_dir_name, const void *src_key, const char * if(!sync_path(dst_filename)) { return false; } - } else if(ent->d_type == DT_REG) { struct stat st; config_t config; @@ -318,15 +315,6 @@ bool config_copy(meshlink_handle_t *mesh, const char *src_dir_name, const void * snprintf(dst_filename, sizeof(dst_filename), "%s" SLASH "%s", mesh->confbase, dst_dir_name); snprintf(src_filename, sizeof(src_filename), "%s" SLASH "%s", mesh->confbase, src_dir_name); - if(main_config_exists(mesh, dst_dir_name)) { - deltree(dst_dir_name); - } - - if(mkdir(dst_filename, 0700)) { - logger(NULL, MESHLINK_ERROR, "Could create directory %s\n", dst_filename); - return false; - } - return copytree(src_filename, src_key, dst_filename, dst_key); } @@ -583,10 +571,7 @@ bool config_read(meshlink_handle_t *mesh, const char *conf_subdir, const char *n return false; } - if(fclose(f)) { - logger(mesh, MESHLINK_ERROR, "Failed to close `%s': %s", path, strerror(errno)); - return false; - } + fclose(f); return true; } @@ -676,10 +661,7 @@ bool main_config_read(meshlink_handle_t *mesh, const char *conf_subdir, config_t return false; } - if(fclose(f)) { - logger(mesh, MESHLINK_ERROR, "Failed to close `%s': %s", path, strerror(errno)); - return false; - } + fclose(f); return true; } @@ -767,10 +749,7 @@ bool invitation_read(meshlink_handle_t *mesh, const char *conf_subdir, const cha return false; } - if(fclose(f)) { - logger(mesh, MESHLINK_ERROR, "Failed to close `%s': %s", path, strerror(errno)); - return false; - } + fclose(f); unlink(used_path); return true; diff --git a/src/meshlink.c b/src/meshlink.c index 185f6689..c5dc33ac 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -1057,20 +1057,83 @@ bool meshlink_open_params_set_storage_key(meshlink_open_params_t *params, const return true; } -bool meshlink_encrypted_key_rotate(meshlink_handle_t *mesh, const void *new_key, size_t new_keylen) { +bool meshlink_encrypted_key_rotate(meshlink_handle_t *mesh, const char *new_key, size_t new_keylen) { + if(!mesh || !new_key || !new_keylen || !*new_key) { + logger(mesh, MESHLINK_ERROR, "Invalid arguments given!\n"); + meshlink_errno = MESHLINK_EINVAL; + return false; + } + + pthread_mutex_lock(&(mesh->mesh_mutex)); + + // Create hash for the new key + void *new_config_key; + new_config_key = xmalloc(CHACHA_POLY1305_KEYLEN); + + if(!prf(new_key, new_keylen, "MeshLink configuration key", 26, new_config_key, CHACHA_POLY1305_KEYLEN)) { + logger(mesh, MESHLINK_ERROR, "Error creating new configuration key!\n"); + meshlink_errno = MESHLINK_EINTERNAL; + pthread_mutex_unlock(&(mesh->mesh_mutex)); + return false; + } + + // Copy contents of the "current" confbase sub-directory to "new" confbase sub-directory with the new key + + if(!config_copy(mesh, "current", mesh->config_key, "new", new_config_key)) { + logger(mesh, MESHLINK_ERROR, "Could not set up configuration in %s/old: %s\n", mesh->confbase, strerror(errno)); + meshlink_errno = MESHLINK_ESTORAGE; + pthread_mutex_unlock(&(mesh->mesh_mutex)); + return false; + } - // While copying old config files to new config files devtool_keyrotate_probe(1); - // After completed creating new config files in confbase/new/ + + main_config_unlock(mesh); + + // Rename confbase/current/ to confbase/old + + if(!config_rename(mesh, "current", "old")) { + logger(mesh, MESHLINK_ERROR, "Cannot rename %s/current to %s/old\n", mesh->confbase, mesh->confbase); + meshlink_errno = MESHLINK_ESTORAGE; + main_config_lock(mesh); + pthread_mutex_unlock(&(mesh->mesh_mutex)); + return false; + } + devtool_keyrotate_probe(2); - // Rename confbase/current to confbase/old/ - devtool_keyrotate_probe(3); + // Rename confbase/new/ to confbase/current - devtool_keyrotate_probe(4); - // Before deleting old sub-directory - devtool_keyrotate_probe(5); - return false; + if(!config_rename(mesh, "new", "current")) { + logger(mesh, MESHLINK_ERROR, "Cannot rename %s/new to %s/current\n", mesh->confbase, mesh->confbase); + meshlink_errno = MESHLINK_ESTORAGE; + main_config_lock(mesh); + pthread_mutex_unlock(&(mesh->mesh_mutex)); + return false; + } + + devtool_keyrotate_probe(3); + + if(!main_config_lock(mesh)) { + pthread_mutex_unlock(&(mesh->mesh_mutex)); + return false; + } + + // Cleanup the "old" confbase sub-directory + + if(!config_destroy(mesh->confbase, "old")) { + pthread_mutex_unlock(&(mesh->mesh_mutex)); + return false; + } + + // Change the mesh handle key with new key + + free(mesh->config_key); + mesh->config_key = new_config_key; + + pthread_mutex_unlock(&(mesh->mesh_mutex)); + + return true; } void meshlink_open_params_free(meshlink_open_params_t *params) { diff --git a/test/blackbox/run_blackbox_tests/test_cases_key_rotation.c b/test/blackbox/run_blackbox_tests/test_cases_key_rotation.c index 2768c80c..a42a54d5 100644 --- a/test/blackbox/run_blackbox_tests/test_cases_key_rotation.c +++ b/test/blackbox/run_blackbox_tests/test_cases_key_rotation.c @@ -342,7 +342,7 @@ static void debug_probe(int stage) { // Terminate the node at the specified stage (by @ break_stage @ ) if(stage == break_stage) { raise(SIGINT); - } else if((break_stage < 1) || (break_stage > 11)) { + } else if((break_stage < 1) || (break_stage > 3)) { fprintf(stderr, "INVALID stage break\n"); raise(SIGABRT); } @@ -381,7 +381,7 @@ static bool test_key_rotation_05(void) { // incrementally debug meshlink_encrypted_key_rotate API atomicity - for(break_stage = 1; break_stage <= 10; break_stage += 1) { + for(break_stage = 1; break_stage <= 3; break_stage += 1) { fprintf(stderr, "Debugging stage %d\n", break_stage); meshlink_destroy("encrypted_conf"); @@ -450,13 +450,9 @@ static bool test_key_rotation_05(void) { meshlink_destroy("encrypted_conf.1"); - set_sync_flag(&status_changed_cond, false); - bar_reachable = false; - meshlink_handle_t *mesh2 = meshlink_open("encrypted_conf.1", "bar", "bar", DEV_CLASS_BACKBONE); assert(mesh2); - meshlink_set_node_status_cb(mesh2, node_status_cb); meshlink_set_log_cb(mesh2, MESHLINK_DEBUG, log_cb); meshlink_enable_discovery(mesh2, false); -- 2.39.5