diff --git a/endpoint/endpoint.adef b/endpoint/endpoint.adef index 819e680e..08de64fc 100644 --- a/endpoint/endpoint.adef +++ b/endpoint/endpoint.adef @@ -11,6 +11,27 @@ processes: } } +requires: +{ + file: + { + // needed for networking: + /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + /etc/nsswitch.conf /etc/ + /etc/hosts /etc/ + /etc/resolv.conf /etc/ + + /bin/sh /bin/sh + /bin/date /bin/date + } + device: + { + [rw] /dev/null /dev/null + [r] /dev/urandom /dev/urandom + [r] /dev/random /dev/random + } +} + #if ${LEGATO_TARGET} = localhost #else bindings: diff --git a/endpoint/endpointComp/endpoint.c b/endpoint/endpointComp/endpoint.c index 3e90ce3f..7f81f095 100644 --- a/endpoint/endpointComp/endpoint.c +++ b/endpoint/endpointComp/endpoint.c @@ -133,7 +133,7 @@ COMPONENT_INIT { device->op->get_device_id(device_id); #ifdef ENABLE_ENDPOINT_TEST LE_TEST_INIT; - LE_TEST_INFO("=== ENDPOINT TEST BEGIN ==="); + LE_INFO("=== ENDPOINT TEST BEGIN ==="); LE_TEST(SC_OK == send_transaction_information(host, port, ssl_seed, value, message, message_fmt, tag, address, next_address, private_key, device_id_ptr, iv)); LE_TEST_EXIT; diff --git a/endpoint/platform/wp76xx/build.mk b/endpoint/platform/wp76xx/build.mk new file mode 100644 index 00000000..627d8c7e --- /dev/null +++ b/endpoint/platform/wp76xx/build.mk @@ -0,0 +1,9 @@ +# 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. + +platform-build-command = \ + cd endpoint && \ + leaf shell -c "mkapp -v -t wp76xx $(LEGATO_FLAGS) endpoint.adef" diff --git a/endpoint/platform/wp76xx/impl.c b/endpoint/platform/wp76xx/impl.c new file mode 100644 index 00000000..a76107a2 --- /dev/null +++ b/endpoint/platform/wp76xx/impl.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "endpoint/hal/device.h" + +#include "legato.h" + +#include "interfaces.h" +#include "le_log.h" +#include "le_mdmDefs_interface.h" +#include "le_secStore_interface.h" +#include "le_sim_interface.h" + +#define MAXLINE 1024 + +#define CBC_IV_SIZE 16 +#define IMSI_LEN 15 +#define READ_BUFFER_SIZE 32 +#define DEFAULT_PORT "/dev/ttyHS0" + +extern struct device_type wp76xx_device_type; + +static le_sim_Id_t SimId; +/* UART file descriptor */ +static int uart_fd; + +static status_t wp76xx_init(void) { + status_t err = register_device(&wp76xx_device_type); + LE_ERROR_IF(err != SC_OK, "register wp76xx device error: %d", err); + return err; +} + +static void wp76xx_release(void) { LE_INFO("Finalize the device success"); } + +static status_t wp76xx_get_key(uint8_t *key) { + // FIXME:Need to implement the private key generate algorithm + if (key == NULL) { + LE_ERROR("Failed to get key"); + return SC_ENDPOINT_GET_KEY_ERROR; + } + + char *private_key = "AAAAAAAAAAAAAAAA"; + memcpy(key, private_key, CBC_IV_SIZE); + + return SC_OK; +} + +static status_t cm_sim_GetSimImsi(char *sim_id) { + char *imsi = sim_id; + status_t ret = SC_OK; + + if (le_sim_GetIMSI(SimId, imsi, LE_SIM_IMSI_BYTES) != LE_OK) { + imsi[0] = '\0'; + ret = SC_ENDPOINT_GET_DEVICE_ID_ERROR; + } + + return ret; +} + +static status_t wp76xx_get_device_id(char *device_id) { + if (cm_sim_GetSimImsi(device_id) != SC_OK) { + return SC_ENDPOINT_GET_DEVICE_ID_ERROR; + } + return SC_OK; +} + +static status_t set_interface_attribs(int fd, int speed) { + struct termios tty; + + if (tcgetattr(fd, &tty) < 0) { + LE_ERROR("Error from tcgetattr: %s\n", strerror(errno)); + return SC_ENDPOINT_UART_SET_ATTR; + } + + cfsetospeed(&tty, (speed_t)speed); + cfsetispeed(&tty, (speed_t)speed); + + tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */ + tty.c_cflag &= ~CSIZE; + tty.c_cflag |= CS8; /* 8-bit characters */ + tty.c_cflag &= ~PARENB; /* no parity bit */ + tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */ + tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */ + + /* setup for non-canonical mode */ + tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); + tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + tty.c_oflag &= ~OPOST; + + /* fetch bytes as they become available */ + tty.c_cc[VMIN] = 1; + tty.c_cc[VTIME] = 1; + + if (tcsetattr(fd, TCSANOW, &tty) != 0) { + LE_ERROR("Error from tcsetattr: %s\n", strerror(errno)); + return SC_ENDPOINT_UART_SET_ATTR; + } + return SC_OK; +} + +static status_t uart_init(const char *device) { + if (device == NULL) device = DEFAULT_PORT; + int fd; + + fd = open(device, O_RDWR | O_NOCTTY | O_SYNC); + if (fd < 0) { + LE_ERROR("Error opening %s: %s\n", device, strerror(errno)); + return SC_ENDPOINT_UART; + } + /*baudrate 115200, 8 bits, no parity, 1 stop bit */ + set_interface_attribs(fd, B115200); + uart_fd = fd; + + return SC_OK; +} + +static void uart_write(const int fd, const char *cmd) { + /* simple output */ + ssize_t cmd_len = strlen(cmd); + ssize_t wlen = write(fd, cmd, cmd_len); + if (wlen != cmd_len) { + LE_ERROR("Error from write: %zd, %s\n", wlen, strerror(errno)); + } + tcdrain(fd); /* delay for output */ +} + +static char *uart_read(const int fd) { + unsigned char buf[READ_BUFFER_SIZE]; + char *response = NULL; + + ssize_t rdlen = read(fd, buf, sizeof(buf) - 1); + if (rdlen > 0) { + LE_DEBUG("uart read: %s", buf); + response = (char *)malloc(sizeof(char) * rdlen); + strncpy(response, (char *)buf, READ_BUFFER_SIZE); + } else if (rdlen < 0) { + LE_ERROR("Error from read: %zd: %s\n", rdlen, strerror(errno)); + } + + return response; +} + +static void uart_clean(const int fd) { + if (tcflush(fd, TCIOFLUSH) != 0) { + LE_ERROR("tcflush error"); + } +} + +status_t sec_init(void) { + LE_INFO("Initialize secure storage success"); + return SC_OK; +} + +status_t sec_write(const char *name, const uint8_t *buf, size_t buf_size) { + le_result_t result = le_secStore_Write(name, buf, buf_size); + + switch (result) { + case LE_UNAVAILABLE: + return SC_ENDPOINT_SEC_UNAVAILABLE; + case LE_OK: + return SC_OK; + default: + return SC_ENDPOINT_SEC_FAULT; + } +} + +status_t sec_read(const char *name, uint8_t *buf, size_t *buf_size) { + le_result_t result = le_secStore_Read(name, buf, buf_size); + + switch (result) { + case LE_NOT_FOUND: + return SC_ENDPOINT_SEC_ITEM_NOT_FOUND; + case LE_UNAVAILABLE: + return SC_ENDPOINT_SEC_UNAVAILABLE; + case LE_OK: + return SC_OK; + default: + return SC_ENDPOINT_SEC_FAULT; + } +} + +status_t sec_delete(const char *name) { + le_result_t result = le_secStore_Delete(name); + + switch (result) { + case LE_NOT_FOUND: + return SC_ENDPOINT_SEC_ITEM_NOT_FOUND; + case LE_UNAVAILABLE: + return SC_ENDPOINT_SEC_UNAVAILABLE; + case LE_OK: + return SC_OK; + default: + return SC_ENDPOINT_SEC_FAULT; + } +} + +static const struct device_operations wp76xx_ops = { + .init = wp76xx_init, + .fini = wp76xx_release, + .get_key = wp76xx_get_key, + .get_device_id = wp76xx_get_device_id, +}; + +static const struct uart_operations wp76xx_uart = { + .init = uart_init, + .write = uart_write, + .read = uart_read, + .clean = uart_clean, +}; + +static const struct secure_store_operations wp76xx_sec_ops = { + .init = sec_init, + .write = sec_write, + .read = sec_read, + .delete = sec_delete, +}; + +struct device_type wp76xx_device_type = { + .name = "wp76xx", + .op = &wp76xx_ops, + .uart = &wp76xx_uart, + .sec_ops = &wp76xx_sec_ops, +}; + +DECLARE_DEVICE(wp76xx); diff --git a/tests/endpoint/common.sh b/tests/endpoint/common.sh index 29925668..ed545893 100644 --- a/tests/endpoint/common.sh +++ b/tests/endpoint/common.sh @@ -22,10 +22,17 @@ function build_legato_repo() { make -C legato localhost } -function setup_leaf() { - if ! which "leaf"; then - echo "Please install Legato leaf first" - exit 1 - fi - leaf --non-interactive setup legato-latest -p "$1" +function setup_leaf(){ + if ! which "leaf"; + then + echo "Please install Legato leaf first" + exit 1 + fi + + error_message=$(leaf --non-interactive setup "$1" -p "$2" 2>&1) + if ! echo "$error_message" | grep "Profile name "$1" already exists in current workspace"; + then + echo "Error occurred when setup leaf profile" + exit 1 + fi } diff --git a/tests/endpoint/test-WP76.sh b/tests/endpoint/test-WP76.sh new file mode 100755 index 00000000..72497ebd --- /dev/null +++ b/tests/endpoint/test-WP76.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + + +COMMON_FILE="tests/endpoint/common.sh" + +if [ ! -f "$COMMON_FILE" ] +then + echo "$COMMON_FILE is not exists." + exit 1 +fi +source $COMMON_FILE + +# setup FX30(WP7607-1) leaf shell +setup_leaf "fx30-stable" "swi-fx30-cat1_1.0.0" + +set -euo pipefail + +make TESTS=true EP_TARGET=wp76xx EP_TA_HOST=node.deviceproof.org EP_TA_PORT=5566 legato && \ +tar zcf endpoint-wp76xx.tgz endpoint/_build_endpoint/wp76xx/app/endpoint/staging/read-only/ diff --git a/tests/endpoint/test-WP77.sh b/tests/endpoint/test-WP77.sh index 8145e6af..7f57136d 100755 --- a/tests/endpoint/test-WP77.sh +++ b/tests/endpoint/test-WP77.sh @@ -1,6 +1,5 @@ #!/usr/bin/env bash -set -uo pipefail COMMON_FILE="tests/endpoint/common.sh" @@ -11,7 +10,9 @@ fi source $COMMON_FILE # setup WP77 leaf shell -setup_leaf "swi-wp77_3.4.0" +setup_leaf "wp77-latest" "swi-wp77_3.4.0" -make TESTS=true EP_TARGET=wp77xx EP_TA_HOST=node.deviceproof.org EP_TA_PORT=5566 legato && - tar zcf endpoint.tgz endpoint/_build_endpoint/wp77xx/app/endpoint/staging/read-only/ +set -euo pipefail + +make TESTS=true EP_TARGET=wp77xx EP_TA_HOST=node.deviceproof.org EP_TA_PORT=5566 legato && \ +tar zcf endpoint-wp77xx.tgz endpoint/_build_endpoint/wp77xx/app/endpoint/staging/read-only/