From 9fa468420373e9478b097a4d86ab9aeb96ab46f4 Mon Sep 17 00:00:00 2001
From: Francesco Ermini <francescoermini8@gmail.com>
Date: Thu, 14 May 2015 15:03:52 +0200
Subject: [PATCH] drivers/xbee: encryption support

add encryption to drivers

fix new line at the end of file

add shell command for enable encryption and set encryption key on a given device

modify _net_if_set_encrypt_key to support any key length

modify _net_if_set_encrypt_key to support any key length of the key

modify blank line

fix ace before tab in indent

fix ace before tab indent

fix ace before tab indent an error

fix trailing white space

drivers/xbee: encryption support

add encryption to drivers

fix new line at the end of file

add shell command for enable encryption and set encryption key on a given device

modify _net_if_set_encrypt_key to support any key length

modify _net_if_set_encrypt_key to support any key length of the key

modify blank line

fix ace before tab in indent

fix ace before tab indent

fix ace before tab indent an error

fix trailing white space

modify drivers/xbee/xbee.c

fix white spaces on xbee.c

Update xbee encryption driver

white line at end xbee.h

fix error

fix sc_netif.c

fix rebase master interactive

drivers/xbee: encryption support

add encryption to drivers

fix new line at the end of file

add shell command for enable encryption and set encryption key on a given device

modify _net_if_set_encrypt_key to support any key length

modify _net_if_set_encrypt_key to support any key length of the key

modify blank line

fix ace before tab in indent

fix ace before tab indent

fix ace before tab indent an error

fix trailing white space

drivers/xbee: encryption support

add encryption to drivers

fix new line at the end of file

add shell command for enable encryption and set encryption key on a given device

modify _net_if_set_encrypt_key to support any key length

modify _net_if_set_encrypt_key to support any key length of the key

modify blank line

fix ace before tab in indent

fix ace before tab indent

fix ace before tab indent an error

fix trailing white space

modify drivers/xbee/xbee.c

fix white spaces on xbee.c

Update xbee encryption driver

white line at end xbee.h

fix error

fix rebase  conflict 4

fix same missing in patches changes

fix ascii to hex index parser

fix syntax rules

fix syntax issue 2

add _netopt_strmap NETOPT_ENCRYPTION e NETOPT_ENCRYPTION_KEY

fix trailng white spaces
---
 drivers/include/xbee.h             |   4 +
 drivers/xbee/xbee.c                |  50 ++++++++++++
 sys/include/net/netopt.h           |   6 ++
 sys/net/crosslayer/netopt/netopt.c |   2 +
 sys/shell/commands/sc_netif.c      | 121 ++++++++++++++++++++++++++++-
 5 files changed, 182 insertions(+), 1 deletion(-)

diff --git a/drivers/include/xbee.h b/drivers/include/xbee.h
index 43c1c43754..f0ca8a2efd 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 ce90c8113b..993faa9eea 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 3c6ed8262d..778d1d8ff0 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 5d35bc9c31..c470a247c3 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 7c24ba2af3..f6d760e49e 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;
-- 
GitLab