add sad_process_auth() to bc_event() to check for authentication tlvs on
incoming messages. This processing happens after msg_post_recv(). However,
if security is active, a duplicate message is allocated and kept in network
byte order to be used for icv calculation.

The standard proposes a security parameters database (SPD) to specify policy
limiting attributes as to which messages should authenticated but this is a
lot of overhead for a something that isn't too helpful. For this patch, the
only policy limiting attribute is the port. That is to say, you can specify
a spp (and corresponding Security Association) for each port. When spp is set
to -1 (default), no security processing is done.

Signed-off-by: Clay Kaiser <clay.kai...@ibm.com>
---
 config.c       |  1 +
 msg.c          |  4 ++++
 msg.h          |  3 ++-
 port.c         | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
 port_private.h |  1 +
 5 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/config.c b/config.c
index 8150dc7..c483920 100644
--- a/config.c
+++ b/config.c
@@ -364,6 +364,7 @@ struct config_item config_tab[] = {
        GLOB_ITEM_INT("utc_offset", CURRENT_UTC_OFFSET, 0, INT_MAX),
        GLOB_ITEM_INT("verbose", 0, 0, 1),
        GLOB_ITEM_INT("write_phase_mode", 0, 0, 1),
+       PORT_ITEM_INT("spp", -1, -1, UINT8_MAX),
        GLOB_ITEM_STR("sa_file", NULL),
 };
 
diff --git a/msg.c b/msg.c
index ab841f0..c82a5cb 100644
--- a/msg.c
+++ b/msg.c
@@ -307,6 +307,10 @@ struct ptp_message *msg_duplicate(struct ptp_message *msg, 
int cnt)
        dup->refcnt = 1;
        TAILQ_INIT(&dup->tlv_list);
 
+       if (!cnt) {
+               return dup;
+       }
+
        err = msg_post_recv(dup, cnt);
        if (err) {
                switch (err) {
diff --git a/msg.h b/msg.h
index 484435d..044b92b 100644
--- a/msg.h
+++ b/msg.h
@@ -366,7 +366,8 @@ void msg_cleanup(void);
  * @param msg  A message obtained using @ref msg_allocate().
  *             The passed message must be in network byte order, not
  *             having been passed to @ref msg_post_recv().
- *
+ * @param cnt  The size of 'msg' in bytes. set to zero when
+ *             @ref msg_post_recv() is not required (icv calculation)
  * @return     Pointer to a message on success, NULL otherwise.
  *             The returned message will be in host byte order, having
  *             been passed to @ref msg_post_recv().
diff --git a/port.c b/port.c
index 5803cd3..82ef73f 100644
--- a/port.c
+++ b/port.c
@@ -36,6 +36,7 @@
 #include "port_private.h"
 #include "print.h"
 #include "rtnl.h"
+#include "sad.h"
 #include "sk.h"
 #include "tc.h"
 #include "tlv.h"
@@ -57,6 +58,7 @@ enum syfu_event {
 
 static int port_is_ieee8021as(struct port *p);
 static int port_is_uds(struct port *p);
+static int port_has_security(struct port *p);
 static void port_nrate_initialize(struct port *p);
 
 static int announce_compare(struct ptp_message *m1, struct ptp_message *m2)
@@ -862,6 +864,11 @@ static int port_is_uds(struct port *p)
        return transport_type(p->trp) == TRANS_UDS;
 }
 
+static int port_has_security(struct port *p)
+{
+       return p->spp < 0 ? 0 : 1;
+}
+
 static void port_management_send_error(struct port *p, struct port *ingress,
                                       struct ptp_message *msg, int error_id)
 {
@@ -2844,7 +2851,7 @@ enum fsm_event port_event(struct port *p, int fd_index)
 static enum fsm_event bc_event(struct port *p, int fd_index)
 {
        enum fsm_event event = EV_NONE;
-       struct ptp_message *msg;
+       struct ptp_message *msg, *dup = NULL;
        int cnt, fd = p->fda.fd[fd_index], err;
 
        switch (fd_index) {
@@ -2961,6 +2968,13 @@ static enum fsm_event bc_event(struct port *p, int 
fd_index)
                msg_put(msg);
                return EV_FAULT_DETECTED;
        }
+       if (port_has_security(p)) {
+               dup = msg_duplicate(msg, 0);
+               if (!dup) {
+                       msg_put(msg);
+                       return EV_NONE;
+               }
+       }
        err = msg_post_recv(msg, cnt);
        if (err) {
                switch (err) {
@@ -2972,11 +2986,17 @@ static enum fsm_event bc_event(struct port *p, int 
fd_index)
                        break;
                }
                msg_put(msg);
+               if (dup) {
+                       msg_put(dup);
+               }
                return EV_NONE;
        }
        port_stats_inc_rx(p, msg);
        if (port_ignore(p, msg)) {
                msg_put(msg);
+               if (dup) {
+                       msg_put(dup);
+               }
                return EV_NONE;
        }
        if (msg_sots_missing(msg) &&
@@ -2984,6 +3004,25 @@ static enum fsm_event bc_event(struct port *p, int 
fd_index)
                pr_err("%s: received %s without timestamp",
                       p->log_name, msg_type_string(msg_type(msg)));
                msg_put(msg);
+               if (dup) {
+                       msg_put(dup);
+               }
+               return EV_NONE;
+       }
+       err = sad_process_auth(clock_config(p->clock), p->spp, msg, dup);
+       if (err) {
+               switch (err) {
+               case -EBADMSG:
+                       pr_err("%s: bad message", p->log_name);
+                       break;
+               case -EPROTO:
+                       pr_debug("%s: ignoring message", p->log_name);
+                       break;
+               }
+               msg_put(msg);
+               if (dup) {
+                       msg_put(dup);
+               }
                return EV_NONE;
        }
        if (msg_sots_valid(msg)) {
@@ -3035,6 +3074,9 @@ static enum fsm_event bc_event(struct port *p, int 
fd_index)
        }
 
        msg_put(msg);
+       if (dup) {
+               msg_put(dup);
+       }
        return event;
 }
 
@@ -3405,6 +3447,7 @@ struct port *port_open(const char *phc_device,
        p->pwr.totalTimeInaccuracy =
                config_get_int(cfg, p->name, 
"power_profile.2017.totalTimeInaccuracy");
        p->slave_event_monitor = clock_slave_monitor(clock);
+       p->spp = config_get_int(cfg, p->name, "spp");
 
        if (!port_is_uds(p) && unicast_client_initialize(p)) {
                goto err_transport;
@@ -3434,6 +3477,11 @@ struct port *port_open(const char *phc_device,
        if (p->net_sync_monitor && !p->hybrid_e2e) {
                pr_warning("%s: net_sync_monitor needs hybrid_e2e", 
p->log_name);
        }
+       if (port_has_security(p) && (p->timestamping == TS_ONESTEP || 
+                                    p->timestamping == TS_P2P1STEP)) {
+               pr_err("%s: spp not supported on one step ports", p->log_name);
+               p->spp = -1;
+       }
 
        /* Set fault timeouts to a default value */
        for (i = 0; i < FT_CNT; i++) {
diff --git a/port_private.h b/port_private.h
index 3b02d2f..8ef9593 100644
--- a/port_private.h
+++ b/port_private.h
@@ -164,6 +164,7 @@ struct port {
        /* slave event monitoring */
        struct monitor *slave_event_monitor;
        bool unicast_state_dirty;
+       int spp;
 };
 
 #define portnum(p) (p->portIdentity.portNumber)
-- 
2.42.1



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to