diff --git a/src/api/encryption.c b/src/api/encryption.c deleted file mode 100644 index e576c3deceb48079aff4db30c1bf8a0a77404e1e..0000000000000000000000000000000000000000 --- a/src/api/encryption.c +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Callback function that shows the current encryption status (encrypted or - * unencrypted). - * - * Example output: - * {"encryption-status":"encrypted"} - * - * @param[in] request incoming HTTP request - * @param[out] response HTTP response to the request - * @param[in] user_data extra data to pass between main thread and callbacks - * @return internal status code - */ -int callback_encryption(const struct _u_request * request, - struct _u_response * response, void * user_data) -{ - char * encryption_status; - if (path_exists(DATA_PARTITION_DEVICE) && - is_encrypted_device(DATA_PARTITION_DEVICE)) - { - encryption_status = "encrypted"; - } - else - { - encryption_status = "unencrypted"; - } - return send_simple_response(response, 200, - "encryption-status", encryption_status); -} diff --git a/src/api/encryption_get.c b/src/api/encryption_get.c new file mode 100644 index 0000000000000000000000000000000000000000..4f02c0685b95096f8bbf98b0864d39b1d956dab8 --- /dev/null +++ b/src/api/encryption_get.c @@ -0,0 +1,65 @@ +/** + * Callback function that shows the current encryption status (encrypted or + * unencrypted). + * + * Example output: + * {"encryption-status":"encrypted"} + * + * @param[in] request incoming HTTP request + * @param[out] response HTTP response to the request + * @param[in] user_data extra data to pass between main thread and callbacks + * @return internal status code + */ +int callback_encryption_get(const struct _u_request * request, + struct _u_response * response, void * user_data) +{ + bool encrypted; + bool * can_encrypt_nullable = NULL; + bool can_encrypt = true; + json_t * messages = json_array(); + + if (path_exists(DATA_PARTITION_DEVICE) && + is_encrypted_device(DATA_PARTITION_DEVICE)) + { + encrypted = true; + } + else + { + encrypted = false; + can_encrypt_nullable = &can_encrypt; + + // Mount the filesystem on the unencrypted device. + int r = temporary_mount(ROOT_DEVICE, UNENCRYPTED_TMP_MOUNTPOINT, + FILESYSTEM_TYPE); + if (r != 0) + { + printf("mounting root device failed: return code %d\n", r); + return send_simple_response(response, 500, "error", + "mounting root device failed"); + } + bool fits = filesystem_fits_in_memory(UNENCRYPTED_TMP_MOUNTPOINT, + MEMORY_USAGE, true); + umount(UNENCRYPTED_TMP_MOUNTPOINT); + if (! fits) + { + can_encrypt = false; + json_array_append_new(messages, json_string( + "existing files do not fit in memory")); + } + } + + json_t * json_body = NULL; + json_body = json_object(); + + json_object_set_new(json_body, "encrypted", + encrypted ? json_true() : json_false()); + + json_object_set_new(json_body, "can-encrypt", + can_encrypt_nullable == NULL ? json_null() : + (can_encrypt ? json_true() : json_false())); + json_object_set_new(json_body, "messages", messages); + + ulfius_set_json_body_response(response, 200, json_body); + json_decref(json_body); + return U_CALLBACK_CONTINUE; +} diff --git a/src/api/encryption_init.c b/src/api/encryption_init_post.c similarity index 93% rename from src/api/encryption_init.c rename to src/api/encryption_init_post.c index 5f2880be01f23dd315022b82244b1fa6ca00578f..fc9e797386a944027fb8589fd99bbb3552096a37 100644 --- a/src/api/encryption_init.c +++ b/src/api/encryption_init_post.c @@ -27,7 +27,7 @@ * @param[in] user_data extra data to pass between handler and main thread * @return internal status code */ -int callback_encryption_init(const struct _u_request * request, +int callback_encryption_init_post(const struct _u_request * request, struct _u_response * response, void * user_data) { bool * reboot = (bool *)user_data; @@ -62,23 +62,10 @@ int callback_encryption_init(const struct _u_request * request, "mounting root device failed"); } - // Determine the filesystem usage of the device to be encrypted. - unsigned long size = filesystem_usage(UNENCRYPTED_TMP_MOUNTPOINT); - if (size < 0) - { - // Something went wrong in determining the filesystem usage. - printf("determining filesystem usage failed: return code %lu\n", size); - return send_simple_response(response, 500, "error", - "determining filesystem usage failed"); - } - printf("root device usage: %lu bytes\n", size); - - // Determine the available memory. - unsigned long memory = available_memory(); - - double projected_usage = (double)size / (double)memory; - printf("projected memory usage: %.3f\n", projected_usage); - if (projected_usage > MEMORY_USAGE) + // Determine if the files on the unencrypted device would fit in memory. + bool fits = filesystem_fits_in_memory(UNENCRYPTED_TMP_MOUNTPOINT, + MEMORY_USAGE, true); + if (! fits) { // Projected memory usage is really high, so abort. return send_simple_response(response, 500, "error", diff --git a/src/api/encryption_remove.c b/src/api/encryption_remove_post.c similarity index 99% rename from src/api/encryption_remove.c rename to src/api/encryption_remove_post.c index f49529aa444f7f0fe0c72518d075ac01329deee4..e76e357bff5302490fa13f05e660f32dc432930f 100644 --- a/src/api/encryption_remove.c +++ b/src/api/encryption_remove_post.c @@ -22,7 +22,7 @@ * @param[in] user_data extra data to pass between handler and main thread * @return internal status code */ -int callback_encryption_remove(const struct _u_request * request, +int callback_encryption_remove_post(const struct _u_request * request, struct _u_response * response, void * user_data) { bool * reboot = (bool *)user_data; diff --git a/src/api/encryption_unlock.c b/src/api/encryption_unlock_post.c similarity index 95% rename from src/api/encryption_unlock.c rename to src/api/encryption_unlock_post.c index fd20287806e66b2579528fae256760feaf02681d..83340837691ef09686d9929c74e996571247b5b9 100644 --- a/src/api/encryption_unlock.c +++ b/src/api/encryption_unlock_post.c @@ -6,7 +6,7 @@ * @param[in] user_data extra data to pass between main thread and callbacks * @return internal status code */ -int callback_encryption_unlock(const struct _u_request * request, +int callback_encryption_unlock_post(const struct _u_request * request, struct _u_response * response, void * user_data) { json_t * json_input = ulfius_get_json_body_request(request, NULL); diff --git a/src/auxiliary.c b/src/auxiliary.c index 6b833d80adc22a36440437496bb7fc0936e4ebb1..9773c09528bd10ef5120a9bb745b9fc733a5981e 100644 --- a/src/auxiliary.c +++ b/src/auxiliary.c @@ -111,6 +111,45 @@ unsigned long filesystem_usage(const char * path) return (s.f_blocks - s.f_bfree) * s.f_bsize; } +/** + * Check if the files on the given filesystem would fit into memory. + * @param path Path of the mounted filesystem. + * @param safety_margin Fraction (between zero and one) of free memory to + deem available for containing the files. + * @param debug Whether to print debug messages. + * @return Whether the filesystem seems to fit into memory. + */ +bool filesystem_fits_in_memory(const char * path, double safety_margin, + bool debug) +{ + // Determine the filesystem usage of the device to be encrypted. + unsigned long size = filesystem_usage(path); + if (size < 0) + { + // Something went wrong in determining the filesystem usage. + // Return false as a precaution. + if (debug) + { + printf("Determining file system usage failed (size: %lu)\n", size); + } + return false; + } + if (debug) + { + printf("file system usage: %lu bytes\n", size); + } + + // Determine the available memory. + unsigned long memory = available_memory(); + + double projected_usage = (double)size / (double)memory; + if (debug) + { + printf("projected memory usage: %.3f\n", projected_usage); + } + return (projected_usage <= safety_margin); +} + /** * Mount a filesystem; create the mount target if it doesn't exist. * @param device_path Path to the device to mount. diff --git a/src/cryptops-api.c b/src/cryptops-api.c index 6b1e6d263828573c9e4c970327c40145c0b51e2d..114850423a3f74cb710a1a3edb661e0f6160b9d7 100644 --- a/src/cryptops-api.c +++ b/src/cryptops-api.c @@ -6,10 +6,10 @@ #include <auxiliary.c> #include <encryption_functions.c> #include <api/default.c> -#include <api/encryption.c> -#include <api/encryption_init.c> -#include <api/encryption_remove.c> -#include <api/encryption_unlock.c> +#include <api/encryption_get.c> +#include <api/encryption_init_post.c> +#include <api/encryption_remove_post.c> +#include <api/encryption_unlock_post.c> #include <api/encryption_keys_put.c> #include <api/ssh_keys_get.c> @@ -41,16 +41,16 @@ int main(int argc, char ** argv) bool reboot = false; ulfius_add_endpoint_by_val(&instance, "GET" , PREFIX, "/encryption", - 0, &callback_encryption, NULL); + 0, &callback_encryption_get, NULL); ulfius_add_endpoint_by_val(&instance, "POST", PREFIX, "/encryption/init", - 0, &callback_encryption_init, &reboot); + 0, &callback_encryption_init_post, &reboot); ulfius_add_endpoint_by_val(&instance, "POST", PREFIX, "/encryption/remove", - 0, &callback_encryption_remove, &reboot); + 0, &callback_encryption_remove_post, &reboot); ulfius_add_endpoint_by_val(&instance, "POST", PREFIX, "/encryption/unlock", - 0, &callback_encryption_unlock, NULL); + 0, &callback_encryption_unlock_post, NULL); ulfius_add_endpoint_by_val(&instance, "PUT" , PREFIX, "/encryption/keys/:slot", 0, &callback_encryption_keys_put, NULL);