summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt13
-rw-r--r--lib/crypto.c138
2 files changed, 151 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4564818..b6bcf62 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,6 +28,7 @@ find_library(libuci NAMES uci)
find_library(libubox NAMES ubox)
find_library(libubus NAMES ubus)
find_library(libblobmsg_json NAMES blobmsg_json)
+find_library(libmbedtls NAMES mbedtls)
find_package(ZLIB)
if(LINUX)
@@ -54,6 +55,10 @@ if(ZLIB_FOUND)
set(DEFAULT_ZLIB_SUPPORT ON)
endif()
+if(libmbedtls)
+ set(DEFAULT_CRYPTO_SUPPORT ON)
+endif()
+
option(DEBUG_SUPPORT "Debug plugin support" ON)
option(FS_SUPPORT "Filesystem plugin support" ON)
option(MATH_SUPPORT "Math plugin support" ON)
@@ -67,6 +72,7 @@ option(ULOOP_SUPPORT "Uloop plugin support" ${DEFAULT_ULOOP_SUPPORT})
option(LOG_SUPPORT "Log plugin support" ON)
option(SOCKET_SUPPORT "Socket plugin support" ON)
option(ZLIB_SUPPORT "Zlib plugin support" ${DEFAULT_ZLIB_SUPPORT})
+option(CRYPTO_SUPPORT "Crypto Mbed-TLS plugin support" ${DEFAULT_CRYPTO_SUPPORT})
set(LIB_SEARCH_PATH "${CMAKE_INSTALL_PREFIX}/lib/ucode/*.so:${CMAKE_INSTALL_PREFIX}/share/ucode/*.uc:./*.so:./*.uc" CACHE STRING "Default library search path")
string(REPLACE ":" "\", \"" LIB_SEARCH_DEFINE "${LIB_SEARCH_PATH}")
@@ -290,6 +296,13 @@ if(ZLIB_SUPPORT)
target_link_libraries(zlib_lib ZLIB::ZLIB)
endif()
+if(CRYPTO_SUPPORT)
+ set(LIBRARIES ${LIBRARIES} crypto_lib)
+ add_library(crypto_lib MODULE lib/crypto.c)
+ set_target_properties(crypto_lib PROPERTIES OUTPUT_NAME crypto PREFIX "")
+ target_link_options(crypto_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
+endif()
+
if(UNIT_TESTING)
enable_testing()
add_definitions(-DUNIT_TESTING)
diff --git a/lib/crypto.c b/lib/crypto.c
new file mode 100644
index 0000000..1cc9a99
--- /dev/null
+++ b/lib/crypto.c
@@ -0,0 +1,138 @@
+#include <stdint.h>
+//#include <stdio.h>
+//#include <unistd.h>
+#include <errno.h>
+#include <alloca.h>
+
+#include <ucode/module.h>
+
+#include <mbedtls/error.h>
+#include <mbedtls/md.h>
+#include <mbedtls/pk.h>
+
+#define TRUE ucv_boolean_new(true)
+#define FALSE ucv_boolean_new(false)
+
+static uc_resource_type_t *pk_type;
+
+static uc_value_t *
+md_digest(uc_vm_t *vm, size_t nargs)
+{
+ uc_value_t *alg = uc_fn_arg(0);
+ uc_value_t *input = uc_fn_arg(1);
+
+ if (ucv_type(alg) != UC_STRING)
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "alg not a string");
+
+ if (ucv_type(input) != UC_STRING)
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "input not a string");
+
+ const mbedtls_md_info_t *info = mbedtls_md_info_from_string(ucv_string_get(alg));
+
+ if (!info)
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "unknown MD algorithm");
+
+ unsigned char size = mbedtls_md_get_size(info);
+ char *output = alloca(size);
+
+ if (mbedtls_md(info, (const unsigned char*)ucv_string_get(input), ucv_string_length(input), (unsigned char*)output))
+ uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "bad input data");
+
+ uc_value_t *rv = ucv_string_new_length(output, size);
+ return rv;
+}
+
+static uc_value_t *
+pk_init(uc_vm_t *vm, size_t nargs)
+{
+ mbedtls_pk_context *ctx = malloc(sizeof(mbedtls_pk_context));
+
+ mbedtls_pk_init(ctx);
+ return uc_resource_new(pk_type, ctx);
+}
+
+static void
+pk_free(void *ptr)
+{
+ mbedtls_pk_context *ctx = ptr;
+
+ mbedtls_pk_free(ctx);
+ free(ctx);
+}
+
+static uc_value_t *
+pk_set_public_key(uc_vm_t *vm, size_t nargs)
+{
+ mbedtls_pk_context *ctx = uc_fn_thisval("mbedtls.pk");
+
+ if (!ctx)
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "invalid mbedtls.pk object");
+
+ uc_value_t *key = uc_fn_arg(0);
+
+ if (ucv_type(key) != UC_STRING)
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "key is not a string");
+
+ int err = mbedtls_pk_parse_public_key(ctx, (const unsigned char*)ucv_string_get(key), ucv_string_length(key));
+ if (err)
+ uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "not a valid PEM/DER key %s: %s",
+ mbedtls_high_level_strerr(err),
+ mbedtls_low_level_strerr(err));
+ return NULL;
+}
+
+static uc_value_t *
+pk_verify(uc_vm_t *vm, size_t nargs)
+{
+ mbedtls_pk_context *ctx = uc_fn_thisval("mbedtls.pk");
+
+ if (!ctx)
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "invalid mbedtls.pk object");
+
+ uc_value_t *md_alg = uc_fn_arg(0);
+ uc_value_t *hash = uc_fn_arg(1);
+ uc_value_t *sig = uc_fn_arg(2);
+
+ if (ucv_type(md_alg) != UC_STRING)
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "md_alg is not a string");
+
+ if (ucv_type(hash) != UC_STRING)
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "hash is not a string");
+
+ if (ucv_type(sig) != UC_STRING)
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "sig is not a string");
+
+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_string(ucv_string_get(md_alg));
+
+ if (!md_info)
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "unknown MD algorithm");
+
+ const mbedtls_md_type_t md_type = mbedtls_md_get_type(md_info);
+
+ int err = mbedtls_pk_verify(ctx, md_type,
+ (const unsigned char*)ucv_string_get(hash), ucv_string_length(hash),
+ (const unsigned char*)ucv_string_get(sig), ucv_string_length(sig));
+ if (err)
+ uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "validation failed: %s: %s",
+ mbedtls_high_level_strerr(err),
+ mbedtls_low_level_strerr(err));
+
+ return TRUE;
+}
+
+static const uc_function_list_t global_fns[] = {
+ { "md_digest", md_digest },
+ { "pk", pk_init },
+};
+
+static const uc_function_list_t pk_fns[] = {
+ { "set_public_key", pk_set_public_key },
+ { "verify", pk_verify },
+};
+
+void uc_module_init(uc_vm_t *vm, uc_value_t *scope)
+{
+ uc_function_list_register(scope, global_fns);
+
+ pk_type = uc_type_declare(vm, "mbedtls.pk", pk_fns, pk_free);
+}