From f1f0f593374ab3169bbd353c7696d8414fbd0686 Mon Sep 17 00:00:00 2001 From: HYChang Date: Thu, 26 Mar 2020 14:39:26 +0800 Subject: [PATCH] feat: Add HAL support Add hardware abstraction layer for create unify device operators. Closes #31 --- Makefile | 23 +++---- hal/Makefile | 12 ++++ hal/device.c | 49 +++++++++++++++ hal/device.h | 135 ++++++++++++++++++++++++++++++++++++++++++ utils/crypto_utils.c | 58 ------------------ utils/crypto_utils.h | 22 ------- utils/defined_error.h | 8 +++ 7 files changed, 217 insertions(+), 90 deletions(-) create mode 100644 hal/Makefile create mode 100644 hal/device.c create mode 100644 hal/device.h diff --git a/Makefile b/Makefile index bc7c641..8f118f7 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,8 @@ UNITY_PATH = $(THIRD_PARTY_PATH)/Unity TEST_PATH = $(ROOT_DIR)/tests UTILS_PATH = $(ROOT_DIR)/utils CONNECTIVITY_PATH = $(ROOT_DIR)/connectivity -export THIRD_PARTY_PATH ROOT_DIR UTILS_PATH MBEDTLS_PATH UNITY_PATH +HAL_PATH = $(ROOT_DIR)/hal +export THIRD_PARTY_PATH ROOT_DIR UTILS_PATH MBEDTLS_PATH UNITY_PATH HAL_PATH ifeq ($(DEBUG), n) CFLAGS = -Wall -Werror -fPIC -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -O2 @@ -26,7 +27,7 @@ CFLAGS = -Wall -fPIC -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -g3 -DDEBUG endif export CFLAGS -INCLUDES = -I$(THIRD_PARTY_PATH)/http-parser -I$(MBEDTLS_PATH)/include -I$(ROOT_DIR)/connectivity -I$(ROOT_DIR)/utils +INCLUDES = -I$(THIRD_PARTY_PATH)/http-parser -I$(MBEDTLS_PATH)/include -I$(ROOT_DIR)/connectivity -I$(ROOT_DIR)/utils -I$(HAL_PATH) LIBS = $(MBEDTLS_PATH)/library/libmbedx509.a $(MBEDTLS_PATH)/library/libmbedtls.a $(MBEDTLS_PATH)/library/libmbedcrypto.a export INCLUDES @@ -38,13 +39,9 @@ CONNECTIVITY_OBJS = conn_http.o OBJS = main.o $(HTTP_PARSER_PATH)/http_parser.o $(UTILS_OBJS) $(CONNECTIVITY_OBJS) .SUFFIXES:.c .o -.PHONY: all clean test pre-build +.PHONY: all clean test pre-build hal -all: pre-build ta_client mbedtls_make - -ta_client: mbedtls_make $(OBJS) - @echo Linking: $@ .... - $(CC) -o $@ $(OBJS) $(LIBS) +all: pre-build mbedtls_make hal mbedtls_make: @for dir in $(MBEDTLS_PATH); do \ @@ -64,7 +61,10 @@ $(UTILS_OBJS): test: $(TEST_PATH) $(UTILS_OBJS) $(MAKE) -C $(TEST_PATH) -clean: clean_client clean_third_party clean_test +hal: + $(MAKE) -C $(HAL_PATH) + +clean: clean_client clean_third_party clean_test clean_devices clean_test: $(MAKE) -C $(TEST_PATH) clean @@ -72,7 +72,10 @@ clean_test: clean_client: $(MAKE) -C $(UTILS_PATH) clean $(MAKE) -C $(CONNECTIVITY_PATH) clean - rm -f ta_client *.o *.c.d + rm -f *.o *.c.d + +clean_devices: + $(MAKE) -C $(HAL_PATH) clean clean_third_party: clean_mbedtls clean_http_parser diff --git a/hal/Makefile b/hal/Makefile new file mode 100644 index 0000000..7c7da60 --- /dev/null +++ b/hal/Makefile @@ -0,0 +1,12 @@ +DEVICES_OBJ = device.o +INCLUDES += -I/$(CURDIR) +export DEVICES_OBJ + +all: $(DEVICES_OBJ) + +device.o: device.c + $(CC) $(CFLAGS) $(INCLUDES) -c $^ + +clean: + find $(DEVICES_PATH) -name "*.o" -exec rm -f {} \; + rm *.o diff --git a/hal/device.c b/hal/device.c new file mode 100644 index 0000000..c7b2f3c --- /dev/null +++ b/hal/device.c @@ -0,0 +1,49 @@ +#include "device.h" + +static struct device_type *devices; + +static struct device_type **find_device(const char *name, unsigned len) { + struct device_type **p; + for (p = &devices; *p; p = &(*p)->next) + if (strlen((*p)->name) == len && strncmp((*p)->name, name, len) == 0) break; + return p; +} + +device_t *device(const char *type) { + struct device_type **p; + if (devices->next) { + fprintf(stderr, "No device type registered!"); + return NULL; + } + p = find_device(type, strlen(type)); + if (*p) { + fprintf(stderr, "Device type %s not found", type); + } + return *p; +} + +retcode_t register_device(struct device_type *dv) { + retcode_t res = RET_OK; + struct device_type **p; + if (dv->next) { + return -DEVICE_REG; + } + p = find_device(dv->name, strlen(dv->name)); + if (*p) { + res = -DEVICE_REG; + } else { + *p = dv; + } + return res; +} + +retcode_t unregister_device(struct device_type *dv) { + for (struct device_type **tmp = &devices; *tmp != NULL; tmp = &(*tmp)->next) { + if (dv == *tmp) { + *tmp = dv->next; + dv->next = NULL; + return RET_OK; + } + } + return -DEVICE_UNREG; +} diff --git a/hal/device.h b/hal/device.h new file mode 100644 index 0000000..fea7777 --- /dev/null +++ b/hal/device.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2019-2020 BiiLabs Co., Ltd. and Contributors + * All Rights Reserved. + * This is free software; you can redistribute it and/or modify it under the + * terms of the MIT license. A copy of the license can be found in the file + * "LICENSE" at the root of this distribution. + */ + +#ifndef HAL_DEVICE_H +#define HAL_DEVICE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include "defined_error.h" + +/*! device initialization entry point */ +#define DECLARE_DEVICE(name) \ + void init_##name##_init(void) __attribute__((constructor)); \ + void init_##name##_init(void) { name##_device_type.op->init(); } + +typedef struct device_type device_t; + +struct device_operations { + retcode_t (*init)(void); /**< initialize for device */ + void (*fini)(void); /**< destructor for device */ + retcode_t (*get_key)(uint8_t *); /**< get device private key */ + retcode_t (*get_device_id)(char *); /**< get device id */ +}; + +struct uart_operations { + retcode_t (*init)(const char *device); /**< init uart */ + void (*write)(const int fd, const char *cmd); /**< write command to uart */ + char *(*read)(const int fd); /**< read from uart */ + void (*clean)(const int fd); /**< flush uart buffer */ +}; + +struct secure_store_operations { + retcode_t (*init)(void); /**< init secure storage */ + /** + * @brief Write an item to secure storage + * + * @param[in] name Name of item + * @param[in] bufPtr Pointer to data + * @param[in] bufSize Length of data + * + * @return + * - #RET_OK on success + * - #NO_MEMORY on no memory error + * - #UNAVAILABLE on secure storage is currently unavailable + * - #FAULT on some other error + */ + retcode_t (*write)(const char *name, const uint8_t *bufPtr, size_t bufSize); + /** + * @brief Read an item from secure storage + * + * @param[in] name Name of item + * @param[out] bufPtr Buffer to store the data in + * @param[out] bufSizePtr Pointer to length of data + * + * @return + * - #RET_OK on success + * - #OVERFLOW error on the buffer is too small + * - #NOT_FOUND error on the item not found inside secure storage + * - #UNAVAILABLE error if the storage is currently unavailable + * - #FAULT if there was some other error + */ + retcode_t (*read)(const char *name, uint8_t *bufPtr, size_t *bufSizePtr); + /** + * @brief Delete item in secure storage + * + * @param[in] name Name of item + * + * @return + * - #RET_OK on success + * - #NOT_FOUND error on the item not found inside secure storage + * - #UNAVAILABLE error if the storage is currently unavailable + * - #FAULT if there was some other error + */ + retcode_t (*delete)(const char *name); +}; + +struct device_type { + const char *name; /**< device type, a string */ + int uart_fd; /**< uart file descriptor */ + const struct device_operations *op; /**< device operations handler */ + const struct uart_operations *uart; /**< uart operations handler */ + const struct secure_store_operations *sec_ops; /**< secure storage operations handler */ + device_t *next; /**< Pointer to next device type, don't use this directly */ +}; + +/** + * @brief Obtain specific device handler + * + * @param[in] device Device type + * + * @return + * - device handler on success + * - NULL on failed + * @see #device_type + */ +device_t *device(const char *device); + +/** + * @brief Register device + * + * @param[in] dv Device to register + * + * @return + * - #RET_OK on success + * - #DEVICE_REG on failed + */ +retcode_t register_device(struct device_type *dv); + +/** + * @brief Unregister device + * + * @param[in] dv Device to unregister + * + * @return + * - #RET_OK on success + * - #DEVICE_UNREG on failed + */ +retcode_t unregister_device(struct device_type *dv); + +#ifdef __cplusplus +} +#endif + +#endif // HAL_DEVICE_H diff --git a/utils/crypto_utils.c b/utils/crypto_utils.c index 5ef57d5..4982d0b 100644 --- a/utils/crypto_utils.c +++ b/utils/crypto_utils.c @@ -16,64 +16,6 @@ #define MAX_TIMESTAMP_LEN 20 -// The device ID we are used here is IMSI. We could use other physical ID in the -// future. -int get_device_id(const char *device_id) { - // TODO: replace cm command - char result_buf[MAXLINE], *imsi; - char cmd[] = "cm sim info"; - FILE *fp; - - fp = popen(cmd, "r"); - if (NULL == fp) { - perror("popen open error"); - return -1; - } - - while (fgets(result_buf, sizeof(result_buf), fp) != NULL) { - if (strstr(result_buf, "IMSI")) { - result_buf[strlen(result_buf) - 1] = '\0'; - imsi = strtok(result_buf + 5, " "); - } - } - - strncpy((char *)device_id, imsi, IMSI_LEN); - - if (pclose(fp) == -1) { - perror("close FILE pointer"); - return -1; - } - return 0; -} - -// Get AES key with hashchain in legato originated app form. -int get_aes_key(const uint8_t *key) { - // TODO: replace cm command - char hash_chain_res[MAXLINE]; - char cmd[] = "cm sim info"; - FILE *fp; - - fp = popen(cmd, "r"); - - if (NULL == fp) { - perror("popen open error"); - return -1; - } - - if (fgets(hash_chain_res, sizeof(hash_chain_res), fp) != NULL) { - hash_chain_res[strlen(hash_chain_res) - 2] = '\0'; - } - - strncpy((char *)key, hash_chain_res, AES_BLOCK_SIZE); - - if (pclose(fp) == -1) { - perror("close FILE pointer"); - return -1; - } - - return 0; -} - int aes_encrypt(const char *plaintext, int plaintext_len, const unsigned char *key, unsigned int keybits, unsigned char iv[AES_BLOCK_SIZE], char *ciphertext, int ciphertext_len) { mbedtls_aes_context ctx; diff --git a/utils/crypto_utils.h b/utils/crypto_utils.h index 8c39c19..a6b5a0b 100644 --- a/utils/crypto_utils.h +++ b/utils/crypto_utils.h @@ -20,28 +20,6 @@ extern "C" { #define MAXLINE 1024 #define IMSI_LEN 15 -/** - * @brief Obtain device IMSI or physical ID - * - * @param[out] device_id Device id output - * - * @return - * - 0 on success - * - -1 on failed - */ -int get_device_id(const char *device_id); - -/** - * @brief Obtain aes key from hashchain - * - * @param[out] key Device key output - * - * @return - * - 0 on success - * - -1 on failed - */ -int get_aes_key(const uint8_t *key); - /** * @brief Encrypt plaintext * diff --git a/utils/defined_error.h b/utils/defined_error.h index 07b59cd..7638b95 100644 --- a/utils/defined_error.h +++ b/utils/defined_error.h @@ -24,6 +24,14 @@ typedef enum { RET_HTTP_CERT, /**< failed on x509 cert parse */ RET_HTTP_CONNECT, /**< failed on HTTP initial connection */ RET_HTTP_SSL, /**< failed on setting ssl config */ + DEVICE_REG, /**< register device error */ + DEVICE_UNREG, /**< unregister device error */ + UART_INIT, /**< initialize uart error */ + NO_MEMORY, /**< no enough memory error */ + OVERFLOW, /**< overflow error */ + NOT_FOUND, /**< item not found error */ + UNAVAILABLE, /**< item not available */ + FAULT /** some other fault */ } retcode_t; #ifdef __cplusplus