[PATCHv2] gpio: add simple get/set helpers for GPIO lines
by Martin Hundebøll
The Linux kernel GPIO api operates with chips, lines, handles, and
events.
The chip and line structures represent info about gpio chips, and
gpio lines, respectively. They are used to e.g. lookup a line with a
certain name, and/or line flags.
The handle structure is used to "obtain" a handle to one or more gpio
lines on a chip. Until the file descriptor in this handle is closed, the
gpio lines cannot be used by others. The same file descriptor is used
when setting or getting the line values (one can also set the initial
value when obtaining handles for output lines).
The event structure is used to get a file descriptor that can be used
with select/poll to wait for changes in line levels.
This commit add simple support for setting and getting the value for a
single gpio line. It does so by obtaining a line handle to get/set the
value, and then release the handle immediately again.
Functionality that could be implemented, but is postponed until the need
arises includes:
* looking up a gpio line by its name
* setting/getting multiple gpio lines with a single function
* waiting for events
* holding on to handles
Some of the above probably require adding structures to represent gpio
lines and events, while handles should be private to the class.
---
Changes since v1:
* added gpiochip info and corresponding getters
* changed "line" to "line_num" a few places
Changes since RFC:
* added gpio.h to ell.h
* changed copyright to Geanix
* open gpiochip in l_gpio_chip_new()
* open gpiochip read-only
* added input checks
* clear ioctl structs with memset instead of = {0}
* reorder error-paths
Makefile.am | 6 +-
ell/ell.h | 1 +
ell/ell.sym | 7 +++
ell/gpio.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/gpio.h | 49 +++++++++++++++
5 files changed, 236 insertions(+), 2 deletions(-)
create mode 100644 ell/gpio.c
create mode 100644 ell/gpio.h
diff --git a/Makefile.am b/Makefile.am
index 8401972..0ecb9a1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,7 +51,8 @@ pkginclude_HEADERS = ell/ell.h \
ell/dhcp.h \
ell/cert.h \
ell/ecc.h \
- ell/ecdh.h
+ ell/ecdh.h \
+ ell/gpio.h
lib_LTLIBRARIES = ell/libell.la
@@ -119,7 +120,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/ecc.h \
ell/ecc-external.c \
ell/ecc.c \
- ell/ecdh.c
+ ell/ecdh.c \
+ ell/gpio.c
ell_libell_la_LDFLAGS = -no-undefined \
-Wl,--version-script=$(top_srcdir)/ell/ell.sym \
diff --git a/ell/ell.h b/ell/ell.h
index aab6417..fb1dd79 100644
--- a/ell/ell.h
+++ b/ell/ell.h
@@ -59,3 +59,4 @@
#include <ell/cert.h>
#include <ell/ecc.h>
#include <ell/ecdh.h>
+#include <ell/gpio.h>
diff --git a/ell/ell.sym b/ell/ell.sym
index 841bc49..793e4c3 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -463,6 +463,13 @@ global:
/* ecdh */
l_ecdh_generate_key_pair;
l_ecdh_generate_shared_secret;
+ /* gpio */
+ l_gpio_chip_new;
+ l_gpio_chip_free;
+ l_gpio_chip_get_label;
+ l_gpio_chip_get_num_lines;
+ l_gpio_chip_get_line_value;
+ l_gpio_chip_set_line_value;
local:
*;
};
diff --git a/ell/gpio.c b/ell/gpio.c
new file mode 100644
index 0000000..83032f9
--- /dev/null
+++ b/ell/gpio.c
@@ -0,0 +1,175 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2018 Geanix. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <linux/gpio.h>
+
+#include "util.h"
+#include "gpio.h"
+#include "private.h"
+
+struct l_gpio_chip {
+ int fd;
+ char *label;
+ uint32_t num_lines;
+};
+
+LIB_EXPORT struct l_gpio_chip *l_gpio_chip_new(const char *chip_name)
+{
+ struct l_gpio_chip *chip;
+ struct gpiochip_info info;
+ char *path;
+ int ret;
+
+ if (!chip_name)
+ return NULL;
+
+ chip = l_new(struct l_gpio_chip, 1);
+
+ path = l_strdup_printf("/dev/%s", chip_name);
+ chip->fd = open(path, O_RDONLY | O_CLOEXEC);
+ l_free(path);
+
+ if (chip->fd < 0) {
+ l_free(chip);
+ return NULL;
+ }
+
+ memset(&info, 0, sizeof(info));
+
+ ret = ioctl(chip->fd, GPIO_GET_CHIPINFO_IOCTL, &info);
+ if (ret < 0) {
+ l_free(chip);
+ return NULL;
+ }
+
+ if (info.label)
+ chip->label = l_strndup(info.label, sizeof(info.label));
+
+ chip->num_lines = info.lines;
+
+ return chip;
+}
+
+LIB_EXPORT void l_gpio_chip_free(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return;
+
+ if (chip->fd >= 0)
+ close(chip->fd);
+
+ l_free(chip->label);
+ l_free(chip);
+}
+
+LIB_EXPORT const char *l_gpio_chip_get_label(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return NULL;
+
+ return chip->label;
+}
+
+LIB_EXPORT uint32_t l_gpio_chip_get_num_lines(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return 0;
+
+ return chip->num_lines;
+}
+
+LIB_EXPORT bool l_gpio_chip_get_line_value(struct l_gpio_chip *chip,
+ uint32_t line_num, bool *value)
+{
+ struct gpiohandle_request req;
+ struct gpiohandle_data data;
+ int ret;
+
+ if (!chip)
+ return false;
+
+ if (line_num >= chip->num_lines)
+ return false;
+
+ if (chip->fd < 0)
+ return false;
+
+ memset(&req, 0, sizeof(req));
+ req.lineoffsets[0] = line_num;
+ req.lines = 1;
+ req.flags = GPIOHANDLE_REQUEST_INPUT;
+
+ ret = ioctl(chip->fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
+ if (ret < 0 || req.fd <= 0)
+ return false;
+
+ memset(&data, 0, sizeof(data));
+
+ ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
+
+ close(req.fd);
+
+ if (ret < 0)
+ return false;
+
+ if (value)
+ *value = !!data.values[0];
+
+ return true;
+}
+
+LIB_EXPORT bool l_gpio_chip_set_line_value(struct l_gpio_chip *chip,
+ uint32_t line_num, bool value)
+{
+ struct gpiohandle_request req;
+ int ret;
+
+ if (!chip)
+ return false;
+
+ if (line_num >= chip->num_lines)
+ return false;
+
+ if (chip->fd < 0)
+ return false;
+
+ memset(&req, 0, sizeof(req));
+ req.lineoffsets[0] = line_num;
+ req.lines = 1;
+ req.flags = GPIOHANDLE_REQUEST_OUTPUT;
+ req.default_values[0] = value;
+
+ ret = ioctl(chip->fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
+ if (ret < 0 || req.fd <= 0)
+ return false;
+
+ close(req.fd);
+
+ return true;
+}
diff --git a/ell/gpio.h b/ell/gpio.h
new file mode 100644
index 0000000..9f4ae6a
--- /dev/null
+++ b/ell/gpio.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2011-2018 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ELL_GPIO_H
+#define __ELL_GPIO_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_gpio_chip;
+
+struct l_gpio_chip *l_gpio_chip_new(const char *chip_name);
+void l_gpio_chip_free(struct l_gpio_chip *chip);
+
+const char *l_gpio_chip_get_label(struct l_gpio_chip *chip);
+uint32_t l_gpio_chip_get_num_lines(struct l_gpio_chip *chip);
+bool l_gpio_chip_get_line_value(struct l_gpio_chip *chip, uint32_t line_num,
+ bool *value);
+bool l_gpio_chip_set_line_value(struct l_gpio_chip *chip, uint32_t line_num,
+ bool value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_GPIO_H */
--
2.20.0
2 years, 11 months
[PATCH 1/7] ecdh: Erase local copy of shared-secret after use
by Andrew Zaborowski
---
ell/ecdh.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ell/ecdh.c b/ell/ecdh.c
index 0b8c347..2c162e9 100644
--- a/ell/ecdh.c
+++ b/ell/ecdh.c
@@ -102,6 +102,8 @@ LIB_EXPORT bool l_ecdh_generate_shared_secret(const struct l_ecc_curve *curve,
*secret = _ecc_constant_new(curve, product->x, curve->ndigits * 8);
+ memset(product->x, 0, curve->ndigits * 8);
+ memset(product->y, 0, curve->ndigits * 8);
l_ecc_point_free(product);
l_ecc_scalar_free(z);
--
2.19.1
3 years, 4 months
[PATCH 01/11] tls: Only accept the Certificate Request in client mode
by Andrew Zaborowski
---
ell/tls.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/ell/tls.c b/ell/tls.c
index eab9cc2..f4cd94c 100644
--- a/ell/tls.c
+++ b/ell/tls.c
@@ -2312,6 +2312,12 @@ static void tls_handle_handshake(struct l_tls *tls, int type,
break;
case TLS_CERTIFICATE_REQUEST:
+ if (tls->server) {
+ TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+ "Message invalid in server mode");
+ break;
+ }
+
/*
* Server sends this optionally so in the WAIT_HELLO_DONE
* state we accept either this or a Server Hello Done (below).
--
2.19.1
3 years, 5 months
[PATCH 1/9] tls: Don't send Client Hello in l_tls_new
by Andrew Zaborowski
Give the user time to set up the tls instance's optional parameters --
those that can not be passed as parameters of l_tls_new, before sending
the Client Hello message in client mode. We now send the message from
l_tls_start which has to be called after the optional setup is done,
e.g. set_cacert, set_auth_data, set_debug are called. This way Client
Hello can avoid proposing cipher suites that would not have worked if
they were negotiated, due to bad certificate type. It also allows us to
output debug messages in the Client Hello sending code, and will allow
to add methods to define security profiles.
---
ell/ell.sym | 1 +
ell/tls-private.h | 1 +
ell/tls.c | 48 ++++++++++++++++++++++++++++-------------------
ell/tls.h | 3 +++
4 files changed, 34 insertions(+), 19 deletions(-)
diff --git a/ell/ell.sym b/ell/ell.sym
index a56433d..764cfd1 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -412,6 +412,7 @@ global:
l_tls_new;
l_tls_free;
l_tls_write;
+ l_tls_start;
l_tls_close;
l_tls_set_cacert;
l_tls_set_auth_data;
diff --git a/ell/tls-private.h b/ell/tls-private.h
index f3601e7..16f142b 100644
--- a/ell/tls-private.h
+++ b/ell/tls-private.h
@@ -98,6 +98,7 @@ struct tls_compression_method {
};
enum tls_handshake_state {
+ TLS_HANDSHAKE_WAIT_START,
TLS_HANDSHAKE_WAIT_HELLO,
TLS_HANDSHAKE_WAIT_CERTIFICATE,
TLS_HANDSHAKE_WAIT_KEY_EXCHANGE,
diff --git a/ell/tls.c b/ell/tls.c
index 9945586..e913642 100644
--- a/ell/tls.c
+++ b/ell/tls.c
@@ -195,7 +195,7 @@ static void tls_reset_handshake(struct l_tls *tls)
for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++)
tls_drop_handshake_hash(tls, hash);
- TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO);
+ TLS_SET_STATE(TLS_HANDSHAKE_WAIT_START);
tls->cert_requested = 0;
tls->cert_sent = 0;
}
@@ -826,13 +826,6 @@ static bool tls_send_client_hello(struct l_tls *tls)
*ptr++ = 0; /* No SessionID */
- /*
- * FIXME: We do need to filter the cipher suites by key exchange
- * mechanism compatibility with the certificate but we don't normally
- * have the certificate at this point because we're called from
- * l_tls_new. We also don't know the TLS version that's going to
- * be negotiated yet.
- */
len_ptr = ptr;
ptr += 2;
@@ -2463,17 +2456,11 @@ LIB_EXPORT struct l_tls *l_tls_new(bool server,
tls->signature_hash = HANDSHAKE_HASH_SHA256;
- /* If we're the client, start the handshake right away */
- if (!tls->server) {
- if (!tls_init_handshake_hash(tls) ||
- !tls_send_client_hello(tls)) {
- l_free(tls);
-
- return NULL;
- }
- }
-
- TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO);
+ /* If we're the server wait for the Client Hello already */
+ if (tls->server)
+ TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO);
+ else
+ TLS_SET_STATE(TLS_HANDSHAKE_WAIT_START);
return tls;
}
@@ -2652,6 +2639,28 @@ bool tls_handle_message(struct l_tls *tls, const uint8_t *message,
return false;
}
+LIB_EXPORT bool l_tls_start(struct l_tls *tls)
+{
+ /* This is a nop in server mode */
+ if (tls->server)
+ return true;
+
+ if (tls->state != TLS_HANDSHAKE_WAIT_START) {
+ TLS_DEBUG("Call invalid in state %s",
+ tls_handshake_state_to_str(tls->state));
+ return false;
+ }
+
+ if (!tls_init_handshake_hash(tls))
+ return false;
+
+ if (!tls_send_client_hello(tls))
+ return false;
+
+ TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO);
+ return true;
+}
+
LIB_EXPORT void l_tls_close(struct l_tls *tls)
{
TLS_DISCONNECT(TLS_ALERT_CLOSE_NOTIFY, 0, "Closing session");
@@ -2800,6 +2809,7 @@ const char *tls_handshake_state_to_str(enum tls_handshake_state state)
static char buf[100];
switch (state) {
+ SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_START)
SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_HELLO)
SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_CERTIFICATE)
SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_KEY_EXCHANGE)
diff --git a/ell/tls.h b/ell/tls.h
index 505f0e0..fb33404 100644
--- a/ell/tls.h
+++ b/ell/tls.h
@@ -77,6 +77,9 @@ struct l_tls *l_tls_new(bool server, l_tls_write_cb_t app_data_handler,
void l_tls_free(struct l_tls *tls);
+/* Begin sending connection setup messages to the server */
+bool l_tls_start(struct l_tls *tls);
+
/* Properly disconnect a connected session */
void l_tls_close(struct l_tls *tls);
--
2.19.1
3 years, 5 months
[PATCHv3] gpio: add simple get/set helpers for GPIO lines
by Martin Hundebøll
The Linux kernel GPIO api operates with chips, lines, handles, and
events.
The chip and line structures represent info about gpio chips, and
gpio lines, respectively. They are used to e.g. lookup a line with a
certain name, and/or line flags.
The handle structure is used to "obtain" a handle to one or more gpio
lines on a chip. Until the file descriptor in this handle is closed, the
gpio lines cannot be used by others. The same file descriptor is used
when setting or getting the line values (one can also set the initial
value when obtaining handles for output lines).
The event structure is used to get a file descriptor that can be used
with select/poll to wait for changes in line levels.
This commit adds simple support for setting and getting the value for a
single gpio line. It does so by obtaining a line handle to get/set the
value, and then release the handle immediately again.
Both the l_gpio_chip and l_gpio_line structures reference an internal
gpio structure that holds the file descriptor to the open
/dev/gpiochipX character device. This file descriptor is used by
l_gpio_chip to lookup line info, and by l_gpio_line to request a virtual
file descriptor used to get and set line values.
Functionality that could be implemented, but is postponed until the need
arises includes:
* setting/getting multiple gpio lines with a single function
* waiting for events
* holding on to handles
Some of the above probably require adding structures to represent
multiple gpio lines and events, while handles should be private to the
class.
---
Changes since v2:
* added internal reference counted structure to hold primary fd
* added l_gpio_line structure to represent a single line
* added function to lookup gpio line by label
Changes since v1:
* added gpiochip info and corresponding getters
* changed "line" to "line_num" a few places
Changes since RFC:
* added gpio.h to ell.h
* changed copyright to Geanix
* open gpiochip in l_gpio_chip_new()
* open gpiochip read-only
* added input checks
* clear ioctl structs with memset instead of = {0}
* reorder error-paths
Makefile.am | 6 +-
ell/ell.h | 1 +
ell/ell.sym | 15 +++
ell/gpio.c | 360 ++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/gpio.h | 59 +++++++++
5 files changed, 439 insertions(+), 2 deletions(-)
create mode 100644 ell/gpio.c
create mode 100644 ell/gpio.h
diff --git a/Makefile.am b/Makefile.am
index 8401972..0ecb9a1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,7 +51,8 @@ pkginclude_HEADERS = ell/ell.h \
ell/dhcp.h \
ell/cert.h \
ell/ecc.h \
- ell/ecdh.h
+ ell/ecdh.h \
+ ell/gpio.h
lib_LTLIBRARIES = ell/libell.la
@@ -119,7 +120,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/ecc.h \
ell/ecc-external.c \
ell/ecc.c \
- ell/ecdh.c
+ ell/ecdh.c \
+ ell/gpio.c
ell_libell_la_LDFLAGS = -no-undefined \
-Wl,--version-script=$(top_srcdir)/ell/ell.sym \
diff --git a/ell/ell.h b/ell/ell.h
index aab6417..fb1dd79 100644
--- a/ell/ell.h
+++ b/ell/ell.h
@@ -59,3 +59,4 @@
#include <ell/cert.h>
#include <ell/ecc.h>
#include <ell/ecdh.h>
+#include <ell/gpio.h>
diff --git a/ell/ell.sym b/ell/ell.sym
index 841bc49..057626c 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -463,6 +463,21 @@ global:
/* ecdh */
l_ecdh_generate_key_pair;
l_ecdh_generate_shared_secret;
+ /* gpio */
+ l_gpio_chip_new;
+ l_gpio_chip_free;
+ l_gpio_chip_get_name;
+ l_gpio_chip_get_label;
+ l_gpio_chip_get_num_lines;
+ l_gpio_chip_get_line;
+ l_gpio_chip_find_line;
+ l_gpio_line_free;
+ l_gpio_line_get_label;
+ l_gpio_line_get_num;
+ l_gpio_line_get_chip;
+ l_gpio_line_set_value;
+ l_gpio_line_get_value;
+ l_gpio_find_line;
local:
*;
};
diff --git a/ell/gpio.c b/ell/gpio.c
new file mode 100644
index 0000000..b1a6548
--- /dev/null
+++ b/ell/gpio.c
@@ -0,0 +1,360 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2018 Geanix. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <linux/gpio.h>
+
+#include "util.h"
+#include "gpio.h"
+#include "private.h"
+
+struct gpio_priv {
+ int fd;
+ size_t refcount;
+};
+
+struct l_gpio_chip {
+ struct gpio_priv *priv;
+ char *name;
+ char *label;
+ uint32_t num_lines;
+};
+
+struct l_gpio_line {
+ struct gpio_priv *priv;
+ char *label;
+ uint32_t num;
+};
+
+static struct gpio_priv *gpio_get(struct gpio_priv *priv)
+{
+ priv->refcount++;
+
+ return priv;
+}
+
+static void gpio_put(struct gpio_priv *priv)
+{
+ if (!priv)
+ return;
+
+ if (--priv->refcount > 0)
+ return;
+
+ if (priv->fd >= 0)
+ close(priv->fd);
+
+ l_free(priv);
+}
+
+static struct l_gpio_chip *gpio_get_chip(struct gpio_priv *priv)
+{
+ struct l_gpio_chip *chip;
+ struct gpiochip_info info;
+
+ if (!priv)
+ return NULL;
+
+ memset(&info, 0, sizeof(info));
+
+ if(ioctl(priv->fd, GPIO_GET_CHIPINFO_IOCTL, &info) < 0)
+ return NULL;
+
+ chip = l_new(struct l_gpio_chip, 1);
+ chip->priv = gpio_get(priv);
+ chip->num_lines = info.lines;
+
+ if (info.label)
+ chip->label = l_strndup(info.label, sizeof(info.label));
+
+ if (info.name)
+ chip->name = l_strndup(info.name, sizeof(info.name));
+
+ return chip;
+}
+
+LIB_EXPORT struct l_gpio_chip *l_gpio_chip_new(const char *chip_name)
+{
+ struct gpio_priv *priv;
+ char *path;
+ int fd;
+
+ if (!chip_name)
+ return NULL;
+
+ path = l_strdup_printf("/dev/%s", chip_name);
+ fd = open(path, O_RDONLY | O_CLOEXEC);
+ l_free(path);
+
+ if (fd < 0)
+ return NULL;
+
+ priv = l_new(struct gpio_priv, 1);
+ priv->fd = fd;
+
+ return gpio_get_chip(priv);
+}
+
+LIB_EXPORT void l_gpio_chip_free(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return;
+
+ gpio_put(chip->priv);
+ l_free(chip->name);
+ l_free(chip->label);
+ l_free(chip);
+}
+
+LIB_EXPORT const char *l_gpio_chip_get_name(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return NULL;
+
+ return chip->name;
+}
+
+LIB_EXPORT const char *l_gpio_chip_get_label(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return NULL;
+
+ return chip->label;
+}
+
+LIB_EXPORT uint32_t l_gpio_chip_get_num_lines(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return 0;
+
+ return chip->num_lines;
+}
+
+LIB_EXPORT struct l_gpio_line *l_gpio_chip_get_line(struct l_gpio_chip *chip,
+ uint32_t line_num)
+{
+ struct l_gpio_line *line;
+ struct gpioline_info info;
+
+ if (!chip)
+ return NULL;
+
+ if (line_num >= chip->num_lines)
+ return NULL;
+
+ memset(&info, 0, sizeof(info));
+ info.line_offset = line_num;
+
+ if (ioctl(chip->priv->fd, GPIO_GET_LINEINFO_IOCTL, &info) < 0)
+ return NULL;
+
+ line = l_new(struct l_gpio_line, 1);
+ line->num = line_num;
+ line->priv = gpio_get(chip->priv);
+
+ if (info.name)
+ line->label = l_strndup(info.name, sizeof(info.name));
+
+ return line;
+}
+
+LIB_EXPORT struct l_gpio_line *l_gpio_chip_find_line(struct l_gpio_chip *chip,
+ const char *line_label)
+{
+ struct l_gpio_line *line;
+ uint32_t i;
+
+ if (!chip)
+ return NULL;
+
+ if (!line_label)
+ return NULL;
+
+ for (i = 0; i < chip->num_lines; i++) {
+ line = l_gpio_chip_get_line(chip, i);
+ if (!line)
+ return NULL;
+
+ if (!line->label && strcmp(line->label, line_label) == 0)
+ return line;
+
+ l_gpio_line_free(line);
+ }
+
+ return NULL;
+}
+
+LIB_EXPORT void l_gpio_line_free(struct l_gpio_line *line)
+{
+ if (!line)
+ return;
+
+ gpio_put(line->priv);
+ l_free(line->label);
+ l_free(line);
+}
+
+LIB_EXPORT const char *l_gpio_line_get_label(struct l_gpio_line *line)
+{
+ if (!line)
+ return NULL;
+
+ return line->label;
+}
+
+LIB_EXPORT uint32_t l_gpio_line_get_num(struct l_gpio_line *line)
+{
+ if (!line)
+ return -1;
+
+ return line->num;
+}
+
+LIB_EXPORT struct l_gpio_chip *l_gpio_line_get_chip(struct l_gpio_line *line)
+{
+ if (!line)
+ return NULL;
+
+ return gpio_get_chip(line->priv);
+}
+
+LIB_EXPORT bool l_gpio_line_set_value(struct l_gpio_line *line, bool value)
+{
+ struct gpiohandle_request handle_req;
+
+ if (!line)
+ return false;
+
+ memset(&handle_req, 0, sizeof(handle_req));
+
+ handle_req.lineoffsets[0] = line->num;
+ handle_req.lines = 1;
+ handle_req.flags = GPIOHANDLE_REQUEST_OUTPUT;
+ handle_req.default_values[0] = value;
+
+ if (ioctl(line->priv->fd, GPIO_GET_LINEHANDLE_IOCTL, &handle_req) < 0)
+ return false;
+
+ if (handle_req.fd <= 0)
+ return false;
+
+ close(handle_req.fd);
+
+ return true;
+}
+
+LIB_EXPORT bool l_gpio_line_get_value(struct l_gpio_line *line, bool *value)
+{
+ struct gpiohandle_request handle_req;
+ struct gpiohandle_data handle_data;
+
+ if (!line)
+ return false;
+
+ memset(&handle_req, 9, sizeof(handle_req));
+
+ handle_req.lineoffsets[0] = line->num;
+ handle_req.lines = 1;
+ handle_req.flags = GPIOHANDLE_REQUEST_INPUT;
+
+ if (ioctl(line->priv->fd, GPIO_GET_LINEHANDLE_IOCTL, &handle_req) < 0)
+ return false;
+
+ if (handle_req.fd <= 0)
+ return false;
+
+ memset(&handle_data, 0, sizeof(handle_data));
+
+ if (ioctl(handle_req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL,
+ &handle_data) < 0) {
+ close(handle_req.fd);
+ return false;
+ }
+
+ close(handle_req.fd);
+
+ if (value)
+ *value = !!handle_data.values[0];
+
+ return true;
+}
+
+static int dir_filter(const struct dirent *dir)
+{
+ return !strncmp(dir->d_name, "gpiochip", 8);
+}
+
+static void free_dirs(struct dirent ***dirs, unsigned int num_dirs)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_dirs; i++)
+ l_free((*dirs)[i]);
+ l_free(*dirs);
+}
+
+LIB_EXPORT struct l_gpio_line *l_gpio_find_line(const char *line_label)
+{
+ struct l_gpio_chip *chip;
+ struct l_gpio_line *line;
+ struct dirent **dirs;
+ int i, num_chips;
+
+ if (!line_label)
+ return NULL;
+
+ num_chips = scandir("/dev", &dirs, dir_filter, alphasort);
+ if (num_chips < 0)
+ return NULL;
+
+ for (i = 0; i < num_chips; i++) {
+ chip = l_gpio_chip_new(dirs[i]->d_name);
+ if (!chip) {
+ free_dirs(&dirs, num_chips);
+ return NULL;
+ }
+
+ line = l_gpio_chip_find_line(chip, line_label);
+ if (line) {
+ l_gpio_chip_free(chip);
+ free_dirs(&dirs, num_chips);
+
+ return line;
+ }
+
+ l_gpio_chip_free(chip);
+ }
+
+ free_dirs(&dirs, num_chips);
+
+ return NULL;
+}
diff --git a/ell/gpio.h b/ell/gpio.h
new file mode 100644
index 0000000..ddbd109
--- /dev/null
+++ b/ell/gpio.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2018 Geanix. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ELL_GPIO_H
+#define __ELL_GPIO_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_gpio_chip;
+struct l_gpio_line;
+
+struct l_gpio_chip *l_gpio_chip_new(const char *chip_name);
+void l_gpio_chip_free(struct l_gpio_chip *chip);
+
+const char *l_gpio_chip_get_name(struct l_gpio_chip *name);
+const char *l_gpio_chip_get_label(struct l_gpio_chip *chip);
+uint32_t l_gpio_chip_get_num_lines(struct l_gpio_chip *chip);
+struct l_gpio_line *l_gpio_chip_get_line(struct l_gpio_chip *chip,
+ uint32_t line_num);
+struct l_gpio_line *l_gpio_chip_find_line(struct l_gpio_chip *chip,
+ const char *line_label);
+
+void l_gpio_line_free(struct l_gpio_line *line);
+const char *l_gpio_line_get_label(struct l_gpio_line *line);
+uint32_t l_gpio_line_get_num(struct l_gpio_line *line);
+struct l_gpio_chip *l_gpio_line_get_chip(struct l_gpio_line *line);
+bool l_gpio_line_set_value(struct l_gpio_line *line, bool value);
+bool l_gpio_line_get_value(struct l_gpio_line *line, bool *value);
+struct l_gpio_line *l_gpio_find_line(const char *line_label);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_GPIO_H */
--
2.20.1
3 years, 5 months
[PATCH 1/9] tls: Don't send Client Hello in l_tls_new
by Andrew Zaborowski
Give the user time to set up the tls instance's optional parameters --
those that can not be passed as parameters of l_tls_new, before sending
the Client Hello message in client mode. We now send the message from
l_tls_start which has to be called after the optional setup is done,
e.g. set_cacert, set_auth_data, set_debug are called. This way Client
Hello can avoid proposing cipher suites that would not have worked if
they were negotiated, due to bad certificate type. It also allows us to
output debug messages in the Client Hello sending code, and will allow
to add methods to define security profiles.
---
ell/ell.sym | 1 +
ell/tls-private.h | 1 +
ell/tls.c | 48 ++++++++++++++++++++++++++++-------------------
ell/tls.h | 3 +++
4 files changed, 34 insertions(+), 19 deletions(-)
diff --git a/ell/ell.sym b/ell/ell.sym
index 841bc49..7d7a5e4 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -413,6 +413,7 @@ global:
l_tls_new;
l_tls_free;
l_tls_write;
+ l_tls_start;
l_tls_close;
l_tls_set_cacert;
l_tls_set_auth_data;
diff --git a/ell/tls-private.h b/ell/tls-private.h
index f2b6b14..b6d1461 100644
--- a/ell/tls-private.h
+++ b/ell/tls-private.h
@@ -98,6 +98,7 @@ struct tls_compression_method {
};
enum tls_handshake_state {
+ TLS_HANDSHAKE_WAIT_START,
TLS_HANDSHAKE_WAIT_HELLO,
TLS_HANDSHAKE_WAIT_CERTIFICATE,
TLS_HANDSHAKE_WAIT_KEY_EXCHANGE,
diff --git a/ell/tls.c b/ell/tls.c
index f27f35c..d05ae8d 100644
--- a/ell/tls.c
+++ b/ell/tls.c
@@ -195,7 +195,7 @@ static void tls_reset_handshake(struct l_tls *tls)
for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++)
tls_drop_handshake_hash(tls, hash);
- TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO);
+ TLS_SET_STATE(TLS_HANDSHAKE_WAIT_START);
tls->cert_requested = 0;
tls->cert_sent = 0;
}
@@ -826,13 +826,6 @@ static bool tls_send_client_hello(struct l_tls *tls)
*ptr++ = 0; /* No SessionID */
- /*
- * FIXME: We do need to filter the cipher suites by key exchange
- * mechanism compatibility with the certificate but we don't normally
- * have the certificate at this point because we're called from
- * l_tls_new. We also don't know the TLS version that's going to
- * be negotiated yet.
- */
len_ptr = ptr;
ptr += 2;
@@ -2463,17 +2456,11 @@ LIB_EXPORT struct l_tls *l_tls_new(bool server,
tls->signature_hash = HANDSHAKE_HASH_SHA256;
- /* If we're the client, start the handshake right away */
- if (!tls->server) {
- if (!tls_init_handshake_hash(tls) ||
- !tls_send_client_hello(tls)) {
- l_free(tls);
-
- return NULL;
- }
- }
-
- TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO);
+ /* If we're the server wait for the Client Hello already */
+ if (tls->server)
+ TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO);
+ else
+ TLS_SET_STATE(TLS_HANDSHAKE_WAIT_START);
return tls;
}
@@ -2652,6 +2639,28 @@ bool tls_handle_message(struct l_tls *tls, const uint8_t *message,
return false;
}
+LIB_EXPORT bool l_tls_start(struct l_tls *tls)
+{
+ /* This is a nop in server mode */
+ if (tls->server)
+ return true;
+
+ if (tls->state != TLS_HANDSHAKE_WAIT_START) {
+ TLS_DEBUG("Call invalid in state %s",
+ tls_handshake_state_to_str(tls->state));
+ return false;
+ }
+
+ if (!tls_init_handshake_hash(tls))
+ return false;
+
+ if (!tls_send_client_hello(tls))
+ return false;
+
+ TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO);
+ return true;
+}
+
LIB_EXPORT void l_tls_close(struct l_tls *tls)
{
TLS_DISCONNECT(TLS_ALERT_CLOSE_NOTIFY, 0, "Closing session");
@@ -2800,6 +2809,7 @@ const char *tls_handshake_state_to_str(enum tls_handshake_state state)
static char buf[100];
switch (state) {
+ SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_START)
SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_HELLO)
SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_CERTIFICATE)
SWITCH_ENUM_TO_STR(TLS_HANDSHAKE_WAIT_KEY_EXCHANGE)
diff --git a/ell/tls.h b/ell/tls.h
index 505f0e0..fb33404 100644
--- a/ell/tls.h
+++ b/ell/tls.h
@@ -77,6 +77,9 @@ struct l_tls *l_tls_new(bool server, l_tls_write_cb_t app_data_handler,
void l_tls_free(struct l_tls *tls);
+/* Begin sending connection setup messages to the server */
+bool l_tls_start(struct l_tls *tls);
+
/* Properly disconnect a connected session */
void l_tls_close(struct l_tls *tls);
--
2.19.1
3 years, 5 months
[PATCH] gpio: add simple get/set helpers for GPIO lines
by Martin Hundebøll
The Linux kernel GPIO api operates with chips, lines, handles, and
events.
The chip and line structures represent info about gpio chips, and
gpio lines, respectively. They are used to e.g. lookup a line with a
certain name, and/or line flags.
The handle structure is used to "obtain" a handle to one or more gpio
lines on a chip. Until the file descriptor in this handle is closed, the
gpio lines cannot be used by others. The same file descriptor is used
when setting or getting the line values (one can also set the initial
value when obtaining handles for output lines).
The event structure is used to get a file descriptor that can be used
with select/poll to wait for changes in line levels.
This commit add simple support for setting and getting the value for a
single gpio line. It does so by obtaining a line handle to get/set the
value, and then release the handle immediately again.
Functionality that could be implemented, but is postponed until the need
arises includes:
* looking up a gpio line by its name
* setting/getting multiple gpio lines with a single function
* waiting for events
* holding on to handles
Some of the above probably require adding structures to represent gpio
lines and events, while handles should be private to the class.
---
Changes since RFC:
* added gpio.h to ell.h
* changed copyright to Geanix
* open gpiochip in l_gpio_chip_new()
* open gpiochip read-only
* added input checks
* clear ioctl structs with memset instead of = {0}
* reorder error-paths
Makefile.am | 6 ++-
ell/ell.h | 1 +
ell/ell.sym | 5 ++
ell/gpio.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/gpio.h | 47 ++++++++++++++++++
5 files changed, 192 insertions(+), 2 deletions(-)
create mode 100644 ell/gpio.c
create mode 100644 ell/gpio.h
diff --git a/Makefile.am b/Makefile.am
index 8401972..0ecb9a1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,7 +51,8 @@ pkginclude_HEADERS = ell/ell.h \
ell/dhcp.h \
ell/cert.h \
ell/ecc.h \
- ell/ecdh.h
+ ell/ecdh.h \
+ ell/gpio.h
lib_LTLIBRARIES = ell/libell.la
@@ -119,7 +120,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/ecc.h \
ell/ecc-external.c \
ell/ecc.c \
- ell/ecdh.c
+ ell/ecdh.c \
+ ell/gpio.c
ell_libell_la_LDFLAGS = -no-undefined \
-Wl,--version-script=$(top_srcdir)/ell/ell.sym \
diff --git a/ell/ell.h b/ell/ell.h
index aab6417..fb1dd79 100644
--- a/ell/ell.h
+++ b/ell/ell.h
@@ -59,3 +59,4 @@
#include <ell/cert.h>
#include <ell/ecc.h>
#include <ell/ecdh.h>
+#include <ell/gpio.h>
diff --git a/ell/ell.sym b/ell/ell.sym
index 841bc49..c8fe5b5 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -463,6 +463,11 @@ global:
/* ecdh */
l_ecdh_generate_key_pair;
l_ecdh_generate_shared_secret;
+ /* gpio */
+ l_gpio_chip_new;
+ l_gpio_chip_free;
+ l_gpio_chip_get_line_value;
+ l_gpio_chip_set_line_value;
local:
*;
};
diff --git a/ell/gpio.c b/ell/gpio.c
new file mode 100644
index 0000000..5dc3440
--- /dev/null
+++ b/ell/gpio.c
@@ -0,0 +1,135 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2018 Geanix. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/gpio.h>
+
+#include "util.h"
+#include "gpio.h"
+#include "private.h"
+
+struct l_gpio_chip {
+ int fd;
+};
+
+LIB_EXPORT struct l_gpio_chip *l_gpio_chip_new(const char *name)
+{
+ struct l_gpio_chip *chip;
+ char *path;
+
+ if (!name)
+ return NULL;
+
+ chip = l_new(struct l_gpio_chip, 1);
+
+ path = l_strdup_printf("/dev/%s", name);
+ chip->fd = open(path, O_RDONLY | O_CLOEXEC);
+ l_free(path);
+
+ if (chip->fd < 0) {
+ l_free(chip);
+ return NULL;
+ }
+
+ return chip;
+}
+
+LIB_EXPORT void l_gpio_chip_free(struct l_gpio_chip *chip)
+{
+ if (!chip)
+ return;
+
+ if (chip->fd >= 0)
+ close(chip->fd);
+
+ l_free(chip);
+}
+
+LIB_EXPORT bool l_gpio_chip_get_line_value(struct l_gpio_chip *chip,
+ uint32_t line, bool *value)
+{
+ struct gpiohandle_request req;
+ struct gpiohandle_data data;
+ int ret;
+
+ if (!chip)
+ return false;
+
+ if (chip->fd < 0)
+ return false;
+
+ memset(&req, 0, sizeof(req));
+ req.lineoffsets[0] = line;
+ req.lines = 1;
+ req.flags = GPIOHANDLE_REQUEST_INPUT;
+
+ ret = ioctl(chip->fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
+ if (ret < 0 || req.fd <= 0)
+ return false;
+
+ memset(&data, 0, sizeof(data));
+
+ ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
+
+ close(req.fd);
+
+ if (ret < 0)
+ return false;
+
+ if (value)
+ *value = !!data.values[0];
+
+ return true;
+}
+
+LIB_EXPORT bool l_gpio_chip_set_line_value(struct l_gpio_chip *chip,
+ uint32_t line, bool value)
+{
+ struct gpiohandle_request req;
+ int ret;
+
+ if (!chip)
+ return false;
+
+ if (chip->fd < 0)
+ return false;
+
+ memset(&req, 0, sizeof(req));
+ req.lineoffsets[0] = line;
+ req.lines = 1;
+ req.flags = GPIOHANDLE_REQUEST_OUTPUT;
+ req.default_values[0] = value;
+
+ ret = ioctl(chip->fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
+ if (ret < 0 || req.fd <= 0)
+ return false;
+
+ close(req.fd);
+
+ return true;
+}
diff --git a/ell/gpio.h b/ell/gpio.h
new file mode 100644
index 0000000..06abc77
--- /dev/null
+++ b/ell/gpio.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2011-2018 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ELL_GPIO_H
+#define __ELL_GPIO_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_gpio_chip;
+
+struct l_gpio_chip *l_gpio_chip_new(const char *name);
+void l_gpio_chip_free(struct l_gpio_chip *chip);
+
+bool l_gpio_chip_get_line_value(struct l_gpio_chip *chip, uint32_t line,
+ bool *value);
+bool l_gpio_chip_set_line_value(struct l_gpio_chip *chip, uint32_t line,
+ bool value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_GPIO_H */
--
2.20.0
3 years, 5 months
ECC API proposal (for EAP-PWD/SAE)
by James Prestwood
Hi All,
I thought this may be an easier medium for disussion about the new ECC
API's required for PWD/SAE rather than a full patch set. Since OWE only
needs ECDH, the ELL ECDH/ECC API's were reletively limited, mostly
creation of points/scalars and getting the data back out into a buffer.
PWD/SAE are a bit more involved. Here is my API proposal for adding the
functionailty we need for PWD/SAE (plus some explanation). Note these
are in addition to what was just merged.
Both PWD/SAE require adding two scalar values together, to produce
another scalar. In both cases this addition is mod N (order). We could
hide this by having a single API that created two scalars, and added
them together to create the added scalar, where all three scalars would
be out parameters. I decided to not go this route because the code
itself is easier to follow next to the RFC when we have a simpler 'add'
function.
bool l_ecc_scalar_add(struct l_ecc_scalar *ret, struct l_ecc_scalar *a,
struct l_ecc_scalar *b);
Point multiply/add/inverse are needed for both PWD/SAE.
bool l_ecc_point_multiply(struct l_ecc_point *ret,
struct l_ecc_scalar *scalar,
struct l_ecc_point *point);
bool l_ecc_point_add(struct l_ecc_point *ret, struct l_ecc_point *a,
struct l_ecc_point *b);
bool l_ecc_point_inverse(struct l_ecc_point *p);
This is all that is needed for EAP-PWD. If this is more or less ok I
can go ahead and submit this portion of the patch for review.
====== Below are operations ONLY required for SAE ========
SAE has a "blinding" technique when computing the X/Y coordinate for
the password element . Without going into details, it requires creating
two special scalars (residue/non-residue). These scalars are then
inputted into an algorithm which decides if the X value is valid. Per
the spec, these two scalars must be created outside the 'blinding'
loop. This is why we need this scalar constructor ('residue' would be
true/false for residue/non-residue).
struct l_ecc_scalar *l_ecc_scalar_new_residue(const struct l_ecc_curve
*curve,
bool residue);
This simply verifies that the calculated X 'value' is a quadradic
residue, aka it is a valid X coordinate. EAP-PWD achieves the same
affect by just solving for the Y coordinate, but the SAE spec requires
this technique specifically.
bool l_ecc_scalar_is_quadradic_residue(struct l_ecc_scalar *value,
struct l_ecc_scalar *qr,
struct l_ecc_scalar *qnr);
The SAE spec requires using the curve prime as an input into a KDF.
ssize_t l_ecc_curve_get_prime(const struct l_ecc_curve *curve, void
*buf,
size_t len);
These two could actually be benefitial in PWD as well. SAE says that
any received scalar/point from the other peer must be checked that they
do not match our own scalar/point. This prevents replay attacks. EAP-
PWD may also benefit from the same checks.
bool l_ecc_scalars_are_equal(struct l_ecc_scalar *a, struct
l_ecc_scalar *b);
bool l_ecc_points_are_equal(struct l_ecc_point *a, struct l_ecc_point
*b);
I will admit the SAE API's are pretty special purpose to SAE, but I do
this this is the better of the 2 options. The other option is moving
the entire 'blinding' loop into ELL, which would avoid the need for
l_ecc_scalar_new_residue/l_ecc_scalar_is_quadradic_residue, but would
also require moving 2 separate KDFs into ELL, both of which are used
commonly in IWD. In the end it would remove 2 SAE specific API's, in
favor of a single SAE specific algorithm, plus additional API's to
expose the two KDF's.
Your thoughts/ideas are welcome.
Thanks,
James
3 years, 5 months
[PATCH 0/3] Implement P384 curve
by James Prestwood
Now that ECC has been merged into ELL we can add the P384 curve definition.
TLS will eventually use this for some ECDSA cipher suites.
James Prestwood (3):
ecc: implement P384 fast modulus
ecc: added P384 curve definition
unit: added P384 unit tests
ell/ecc-external.c | 129 +++++++++++++++++++++++++++++++++++++++++++++
ell/ecc.c | 30 +++++++++++
ell/ecc.h | 2 +-
unit/test-ecdh.c | 66 +++++++++++++++++++++++
4 files changed, 226 insertions(+), 1 deletion(-)
--
2.17.1
3 years, 5 months
[RFC] gpio: add simple get/set helpers for GPIO lines
by Martin Hundebøll
The Linux kernel GPIO api operates with chips, lines, handles, and
events.
The chip and line structures represent info about gpio chips, and
gpio lines, respectively. They are used to e.g. lookup a line with a
certain name, and/or line flags.
The handle structure is used to "obtain" a handle to one or more gpio
lines on a chip. Until the file descriptor in this handle is closed, the
gpio lines cannot be used by others. The same file descriptor is used
when setting or getting the line values (one can also set the initial
value when obtaining handles for output lines).
The event structure is used to get a file descriptor that can be used
with select/poll to wait for changes in line levels.
This commit add simple support for setting and getting the value for a
single gpio line. It does so by obtaining a line handle to get/set the
value, and then release the handle immediately again.
Functionality that could be implemented, but is postponed until the need
arises includes:
* looking up a gpio line by its name
* setting/getting multiple gpio lines with a single function
* waiting for events
* holding on to handles
Some of the above probably require adding structures to represent gpio
lines and events, while handles should be private to the class.
---
Makefile.am | 6 ++-
ell/ell.sym | 7 +++
ell/gpio.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/gpio.h | 50 +++++++++++++++++
4 files changed, 212 insertions(+), 2 deletions(-)
create mode 100644 ell/gpio.c
create mode 100644 ell/gpio.h
diff --git a/Makefile.am b/Makefile.am
index 8401972..0ecb9a1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,7 +51,8 @@ pkginclude_HEADERS = ell/ell.h \
ell/dhcp.h \
ell/cert.h \
ell/ecc.h \
- ell/ecdh.h
+ ell/ecdh.h \
+ ell/gpio.h
lib_LTLIBRARIES = ell/libell.la
@@ -119,7 +120,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/ecc.h \
ell/ecc-external.c \
ell/ecc.c \
- ell/ecdh.c
+ ell/ecdh.c \
+ ell/gpio.c
ell_libell_la_LDFLAGS = -no-undefined \
-Wl,--version-script=$(top_srcdir)/ell/ell.sym \
diff --git a/ell/ell.sym b/ell/ell.sym
index 841bc49..d6b12f1 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -463,6 +463,13 @@ global:
/* ecdh */
l_ecdh_generate_key_pair;
l_ecdh_generate_shared_secret;
+ /* gpio */
+ l_gpio_chip_new;
+ l_gpio_chip_free;
+ l_gpio_chip_open;
+ l_gpio_chip_open_name;
+ l_gpio_chip_get_line_value;
+ l_gpio_chip_set_line_value;
local:
*;
};
diff --git a/ell/gpio.c b/ell/gpio.c
new file mode 100644
index 0000000..1398594
--- /dev/null
+++ b/ell/gpio.c
@@ -0,0 +1,151 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2011-2018 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/gpio.h>
+
+#include "util.h"
+#include "gpio.h"
+#include "private.h"
+
+struct l_gpio_chip {
+ int fd;
+};
+
+LIB_EXPORT struct l_gpio_chip *l_gpio_chip_new(void)
+{
+ struct l_gpio_chip *chip = l_new(struct l_gpio_chip, 1);
+
+ chip->fd = -1;
+
+ return chip;
+}
+
+LIB_EXPORT void l_gpio_chip_free(struct l_gpio_chip *chip)
+{
+ if (chip && chip->fd >= 0)
+ close(chip->fd);
+
+ l_free(chip);
+}
+
+static bool gpio_chip_open(struct l_gpio_chip *chip, const char *path)
+{
+ if (chip->fd >= 0)
+ close(chip->fd);
+
+ chip->fd = open(path, O_RDWR | O_CLOEXEC);
+ if (chip->fd < 0)
+ return false;
+
+ return true;
+}
+
+LIB_EXPORT bool l_gpio_chip_open(struct l_gpio_chip *chip, uint32_t num)
+{
+ char *path = l_strdup_printf("/dev/gpiochip%u", num);
+ bool ret = gpio_chip_open(chip, path);
+
+ l_free(path);
+
+ return ret;
+}
+
+LIB_EXPORT bool l_gpio_chip_open_name(struct l_gpio_chip *chip,
+ const char *name)
+{
+ char *path;
+ bool ret;
+
+ if (!name)
+ return false;
+
+ if (l_str_has_prefix(name, "/dev/"))
+ path = l_strdup(name);
+ else
+ path = l_strdup_printf("/dev/%s", name);
+
+ ret = gpio_chip_open(chip, path);
+
+ l_free(path);
+
+ return ret;
+}
+
+LIB_EXPORT bool l_gpio_chip_get_line_value(struct l_gpio_chip *chip,
+ uint32_t line, bool *value)
+{
+ struct gpiohandle_request req = {0};
+ struct gpiohandle_data data = {0};
+ int ret;
+
+ if (chip->fd < 0)
+ return false;
+
+ req.lineoffsets[0] = line;
+ req.lines = 1;
+ req.flags = GPIOHANDLE_REQUEST_INPUT;
+
+ ret = ioctl(chip->fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
+ if (ret < 0 || req.fd <= 0)
+ return false;
+
+ ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
+ if (ret < 0)
+ goto error;
+
+ *value = data.values[0];
+
+error:
+ close(req.fd);
+
+ return ret == 0;
+}
+
+LIB_EXPORT bool l_gpio_chip_set_line_value(struct l_gpio_chip *chip,
+ uint32_t line, bool value)
+{
+ struct gpiohandle_request req = {0};
+ int ret;
+
+ if (chip->fd < 0)
+ return false;
+
+ req.lineoffsets[0] = line;
+ req.lines = 1;
+ req.flags = GPIOHANDLE_REQUEST_OUTPUT;
+ req.default_values[0] = value;
+
+ ret = ioctl(chip->fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
+ if (ret < 0 || req.fd <= 0)
+ return false;
+
+ close(req.fd);
+
+ return true;
+}
diff --git a/ell/gpio.h b/ell/gpio.h
new file mode 100644
index 0000000..c4dab5a
--- /dev/null
+++ b/ell/gpio.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2011-2018 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __ELL_GPIO_H
+#define __ELL_GPIO_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_gpio_chip;
+
+struct l_gpio_chip *l_gpio_chip_new(void);
+void l_gpio_chip_free(struct l_gpio_chip *chip);
+
+bool l_gpio_chip_open(struct l_gpio_chip *chip, uint32_t num);
+bool l_gpio_chip_open_name(struct l_gpio_chip *chip, const char *name);
+
+bool l_gpio_chip_get_line_value(struct l_gpio_chip *chip, uint32_t line,
+ bool *value);
+bool l_gpio_chip_set_line_value(struct l_gpio_chip *chip, uint32_t line,
+ bool value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_GPIO_H */
--
2.20.0
3 years, 5 months