diff --git a/drivers/include/xbee.h b/drivers/include/xbee.h index 43c1c437544aca4c9ca7a41794a54efa1e1aa77b..f0ca8a2efd61c6864b0d8c0ef48642f1f8fb1ad4 100644 --- a/drivers/include/xbee.h +++ b/drivers/include/xbee.h @@ -39,7 +39,11 @@ extern "C" { /** * @brief Maximum payload length that can be send */ +#ifdef MODULE_XBEE_ENCRYPTION +#define XBEE_MAX_PAYLOAD_LENGTH (95U) +#else #define XBEE_MAX_PAYLOAD_LENGTH (100U) +#endif /** * @brief Maximum packet length, including XBee API frame overhead diff --git a/drivers/xbee/xbee.c b/drivers/xbee/xbee.c index ce90c8113ba2f820f8bd3204b08d7c73fda21b0f..993faa9eeaf0571e5b72566a07832c35dae83b5c 100644 --- a/drivers/xbee/xbee.c +++ b/drivers/xbee/xbee.c @@ -456,6 +456,50 @@ static int _set_proto(xbee_t *dev, uint8_t *val, size_t len) return sizeof(gnrc_nettype_t); } +#ifdef MODULE_XBEE_ENCRYPTION +static int _set_encryption(xbee_t *dev, uint8_t *val) +{ + uint8_t cmd[3]; + resp_t resp; + /* get the current state of Encryption */ + cmd[0] = 'E'; + cmd[1] = 'E'; + _api_at_cmd(dev, cmd, 2, &resp); + + /* Prevent writing the same value in EE. */ + if (val[0] != resp.data[0] ){ + cmd[0] = 'E'; + cmd[1] = 'E'; + cmd[2] = val[0]; + _api_at_cmd(dev, cmd, 3, &resp); + } + if (resp.status == 0) { + return 2; + } + return -ECANCELED; +} + +static int _set_encryption_key(xbee_t *dev, uint8_t *val, size_t len) +{ + uint8_t cmd[18]; + resp_t resp; + if (len != 16) { /* the AES key is 128bit, 16 byte */ + return -EINVAL; + } + cmd[0] = 'K'; + cmd[1] = 'Y'; + + for (int i = 0; i < 16; i++) { /* Append the key to the KY API AT command */ + cmd[i + 2] = val[i]; + } + _api_at_cmd(dev, cmd, 18, &resp); + if (resp.status == 0) { + return 2; + } + return -ECANCELED; +} +#endif + /* * Driver's "public" functions */ @@ -758,6 +802,12 @@ static int _set(gnrc_netdev_t *netdev, netopt_t opt, void *value, size_t value_l return _set_panid(dev, (uint8_t *)value, value_len); case NETOPT_PROTO: return _set_proto(dev, (uint8_t *)value, value_len); +#ifdef MODULE_XBEE_ENCRYPTION + case NETOPT_ENCRYPTION: + return _set_encryption(dev, (uint8_t *)value); + case NETOPT_ENCRYPTION_KEY: + return _set_encryption_key(dev, (uint8_t *)value, value_len); +#endif default: return -ENOTSUP; } diff --git a/sys/include/net/netopt.h b/sys/include/net/netopt.h index 3c6ed8262de45cfe1e6822e84891581eb7348e47..778d1d8ff0e3bb390e590cd7493160e035e3ec06 100644 --- a/sys/include/net/netopt.h +++ b/sys/include/net/netopt.h @@ -207,6 +207,12 @@ typedef enum { */ NETOPT_STATS, + /** + * @brief en/disable encryption. + */ + NETOPT_ENCRYPTION, /**< en/disable encryption */ + NETOPT_ENCRYPTION_KEY, /**< set encryption key */ + /* add more options if needed */ /** diff --git a/sys/net/crosslayer/netopt/netopt.c b/sys/net/crosslayer/netopt/netopt.c index 5d35bc9c31805b119106d81acb7b580f860c9970..c470a247c319fb4afa9e55a7655ceebe239106f0 100644 --- a/sys/net/crosslayer/netopt/netopt.c +++ b/sys/net/crosslayer/netopt/netopt.c @@ -53,6 +53,8 @@ static const char *_netopt_strmap[] = { [NETOPT_CHANNEL_PAGE] = "NETOPT_CHANNEL_PAGE", [NETOPT_CCA_THRESHOLD] = "NETOPT_CCA_THRESHOLD", [NETOPT_STATS] = "NETOPT_STATS", + [NETOPT_ENCRYPTION] = "NETOPT_ENCRYPTION", + [NETOPT_ENCRYPTION_KEY] = "NETOPT_ENCRYPTION_KEY", [NETOPT_NUMOF] = "NETOPT_NUMOF", }; diff --git a/sys/shell/commands/sc_netif.c b/sys/shell/commands/sc_netif.c index 7c24ba2af3b70ecac1687cf9ac774db9b8f5ec6a..f6d760e49e9a1cc912c8765048a3f95ecf9b57a8 100644 --- a/sys/shell/commands/sc_netif.c +++ b/sys/shell/commands/sc_netif.c @@ -121,7 +121,9 @@ static void _set_usage(char *cmd_name) " * \"power\" - TX power in dBm\n" " * \"retrans\" - max. number of retransmissions\n" " * \"src_len\" - sets the source address length in byte\n" - " * \"state\" - set the device state\n"); + " * \"state\" - set the device state\n" + " * \"encrypt\" - set the encryption on-off\n" + " * \"key\" - set the encryption key in hexadecimal format\n"); } static void _mtu_usage(char *cmd_name) @@ -199,6 +201,14 @@ static void _print_netopt(netopt_t opt) printf("CCA threshold [in dBm]"); break; + case NETOPT_ENCRYPTION: + printf("encryption"); + break; + + case NETOPT_ENCRYPTION_KEY: + printf("encryption key"); + break; + default: /* we don't serve these options here */ break; @@ -614,6 +624,109 @@ static int _netif_set_state(kernel_pid_t dev, char *state_str) return 0; } +static int _netif_set_encrypt(kernel_pid_t dev, netopt_t opt, char *encrypt_str) +{ + netopt_enable_t set; + size_t size = 1; + if ((strcmp("on", encrypt_str) == 0) || (strcmp("ON", encrypt_str) == 0)) { + set = NETOPT_ENABLE; + } + else if ((strcmp("off", encrypt_str) == 0) || (strcmp("OFF", encrypt_str) == 0)) { + set = NETOPT_DISABLE; + } + else { + puts("usage: ifconfig <if_id> set encryption [on|off]"); + return 1; + } + + if (gnrc_netapi_set(dev, opt, 0, &set, size) < 0) { + printf("error: unable to set "); + _print_netopt(opt); + puts(""); + return 1; + } + + printf("success: set "); + _print_netopt(opt); + printf(" on interface %" PRIkernel_pid " to %s\n", dev, encrypt_str); + + return 0; +} + +static int _hex_to_int(char c) { + if ('0' <= c && c <= '9') { + return c - '0'; + } + else if ('a' <= c && c <= 'f') { + return c - 'a'; + } + else if ('A' <= c && c <= 'F') { + return c - 'A'; + } + else { + return -1; + } +} + +static int _netif_set_encrypt_key(kernel_pid_t dev, netopt_t opt, char *key_str) +{ + size_t str_len = strlen(key_str); + size_t key_len = str_len / 2; + uint8_t key[key_len]; + + if (str_len == 14U) { + printf("\nNotice: setting 56 bit key."); + } + else if (str_len == 16U) { + printf("\nNotice: setting 64 bit key."); + } + else if (str_len == 32U) { + printf("\nNotice: setting 128 bit key."); + } + else if (str_len == 48U) { + printf("\nNotice: setting 192 bit key."); + } + else if (str_len == 64U) { + printf("\nNotice: setting 256 bit key."); + } + else if (str_len == 128U) { + printf("\nNotice: setting 512 bit key."); + } + else { + printf("error: invalid key size.\n"); + return 1; + } + /* Convert any char from ASCII table in hex format */ + for (size_t i = 0; i < str_len; i += 2) { + int i1 = _hex_to_int(key_str[i]); + int i2 = _hex_to_int(key_str[i + 1]); + + if (i1 == -1 || i2 == -1) { + puts("error: unable to parse key"); + return 1; + } + + key[i / 2] = (uint8_t)((i1 << 4) + i2); + } + + if (gnrc_netapi_set(dev, opt, 0, key, key_len) < 0) { + printf("error: unable to set "); + _print_netopt(opt); + puts(""); + return 1; + } + + printf("success: set "); + _print_netopt(opt); + printf(" on interface %" PRIkernel_pid " to \n", dev); + for (size_t i = 0; i < key_len; i++) { + /* print the hex value of the key */ + printf("%02x", key[i]); + } + puts(""); + return 0; +} + static int _netif_set(char *cmd_name, kernel_pid_t dev, char *key, char *value) { if ((strcmp("addr", key) == 0) || (strcmp("addr_short", key) == 0)) { @@ -650,6 +763,12 @@ static int _netif_set(char *cmd_name, kernel_pid_t dev, char *key, char *value) else if (strcmp("cca_threshold", key) == 0) { return _netif_set_u8(dev, NETOPT_CCA_THRESHOLD, value); } + else if (strcmp("encrypt", key) == 0) { + return _netif_set_encrypt(dev, NETOPT_ENCRYPTION, value); + } + else if (strcmp("key", key) == 0) { + return _netif_set_encrypt_key(dev, NETOPT_ENCRYPTION_KEY, value); + } _set_usage(cmd_name); return 1;