The standard specifies that the header sequence id should be checked to
confirm the message has not been replayed. It specifies a seqid check for
each message that has it's own sequence id pool but this is most relevant
for sync/followup messages for which slaves do not confirm seqid currently.

The standard also mentioned a seqid window, for this patch, the seqid window
specifies how far the seqid can advance from the last know seqid before it
is considered a replay attack from before a seqid rollover.

This patch introduces sad_check_seqid() in sad.c to check the seqid and
sad_set_last_seqid() which is updates the last seqid  upon successful sync
in port_synchronize() and reset upon state transition in port_e2e_transition()
and port_p2p_transition.

Signed-off-by: Clay Kaiser <clay.kai...@ibm.com>
---
 port.c |  8 ++++++++
 sad.c  | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 sad.h  |  9 ++++++++
 3 files changed, 82 insertions(+)

diff --git a/port.c b/port.c
index 82ef73f..d7e5ec0 100644
--- a/port.c
+++ b/port.c
@@ -1380,6 +1380,8 @@ static void port_synchronize(struct port *p,
                break;
        }
 
+       sad_set_last_seqid(clock_config(p->clock), p->spp, seqid);
+
        last_state = clock_servo_state(p->clock);
        state = clock_synchronize(p->clock, t2, t1c);
        switch (state) {
@@ -2658,6 +2660,7 @@ static void port_e2e_transition(struct port *p, enum 
port_state next)
        case PS_FAULTY:
        case PS_DISABLED:
                port_disable(p);
+               sad_set_last_seqid(clock_config(p->clock), p->spp, 0);
                break;
        case PS_LISTENING:
                port_set_announce_tmo(p);
@@ -2671,6 +2674,7 @@ static void port_e2e_transition(struct port *p, enum 
port_state next)
                        set_tmo_log(p->fda.fd[FD_MANNO_TIMER], 1, -10); /*~1ms*/
                }
                port_set_sync_tx_tmo(p);
+               sad_set_last_seqid(clock_config(p->clock), p->spp, 0);
                break;
        case PS_PASSIVE:
                port_set_announce_tmo(p);
@@ -2678,6 +2682,7 @@ static void port_e2e_transition(struct port *p, enum 
port_state next)
        case PS_UNCALIBRATED:
                flush_last_sync(p);
                flush_delay_req(p);
+               sad_set_last_seqid(clock_config(p->clock), p->spp, 0);
                /* fall through */
        case PS_SLAVE:
                port_set_announce_tmo(p);
@@ -2702,6 +2707,7 @@ static void port_p2p_transition(struct port *p, enum 
port_state next)
        case PS_FAULTY:
        case PS_DISABLED:
                port_disable(p);
+               sad_set_last_seqid(clock_config(p->clock), p->spp, 0);
                break;
        case PS_LISTENING:
                port_set_announce_tmo(p);
@@ -2716,6 +2722,7 @@ static void port_p2p_transition(struct port *p, enum 
port_state next)
                        set_tmo_log(p->fda.fd[FD_MANNO_TIMER], 1, -10); /*~1ms*/
                }
                port_set_sync_tx_tmo(p);
+               sad_set_last_seqid(clock_config(p->clock), p->spp, 0);
                break;
        case PS_PASSIVE:
                port_set_announce_tmo(p);
@@ -2723,6 +2730,7 @@ static void port_p2p_transition(struct port *p, enum 
port_state next)
        case PS_UNCALIBRATED:
                flush_last_sync(p);
                flush_peer_delay(p);
+               sad_set_last_seqid(clock_config(p->clock), p->spp, 0);
                /* fall through */
        case PS_SLAVE:
                port_set_announce_tmo(p);
diff --git a/sad.c b/sad.c
index 62c56d4..5129675 100644
--- a/sad.c
+++ b/sad.c
@@ -73,6 +73,66 @@ static inline int sad_get_auth_tlv_len(struct 
security_association *sa,
               icv_len; /* size of icv (defined by key) */
 }
 
+void sad_set_last_seqid(struct config *cfg,
+                       int spp, UInteger16 seqid)
+{
+       struct security_association* sa;
+       /* immediately return if security is not configured */
+       if (spp < 0) {
+               return;
+       }
+       /* retrieve sa specified by spp */
+       sa = sad_get_association(cfg, spp);
+       if (sa == NULL) {
+               return;
+       }
+
+       sa->last_seqid = seqid;
+}
+
+static int sad_check_seqid(struct ptp_message *msg,
+                          UInteger16 last_seqid,
+                          UInteger16 seqid_window)
+{
+       UInteger16 new_seqid;
+       /* do not check seqid if seqid_window is zero */
+       if (seqid_window < 1) {
+               return 0;
+       }
+
+       /* (for now) only check seqid on sync/followup msgs */
+       switch (msg_type(msg)) {
+       case SYNC:
+       case FOLLOW_UP:
+               new_seqid = msg->header.sequenceId;
+               /* verify received seqid is greater than last */
+               /* use mod(uint16) to handle wrap within window */
+               if (new_seqid < (UInteger16)(last_seqid + 1) &&
+                   (UInteger16)(new_seqid + seqid_window) <
+                   (UInteger16)(last_seqid + 1 + seqid_window) &&
+                   last_seqid != 0) {
+                       pr_debug("replayed seqid: received seqid %u "
+                                "smaller than last %u",
+                                new_seqid, last_seqid);
+                       return -EBADMSG;
+               /* verify received seqid is less than seqid window */
+               /* use mod(uint16) to handle wrap within window */
+               } else if (new_seqid > (UInteger16)(last_seqid + seqid_window) 
&&
+                          (UInteger16)(new_seqid + seqid_window) >
+                          (UInteger16)(last_seqid + 2 * seqid_window) &&
+                          last_seqid != 0) {
+                       pr_debug("replayed seqid: received seqid %u "
+                                "beyond seqid_window %u + %d",
+                                new_seqid, last_seqid, seqid_window);
+                       return -EBADMSG;
+               }
+               break;
+       default:
+               break;
+       }
+       return 0;
+}
+
 static int sad_check_auth_tlv(struct security_association *sa,
                              struct ptp_message *msg,
                              struct ptp_message *raw)
@@ -169,6 +229,11 @@ int sad_process_auth(struct config *cfg, int spp,
        if (sa == NULL) {
                return -EPROTO;
        }
+       /* check seqid in header first (sync/followup only) */
+       err = sad_check_seqid(msg, sa->last_seqid, sa->seqid_window);
+       if (err) {
+               return err;
+       }
        /* detect and process any auth tlvs  */
        err = sad_check_auth_tlv(sa, msg, raw);
        if (err) {
diff --git a/sad.h b/sad.h
index 9540b4d..4ab4ea2 100644
--- a/sad.h
+++ b/sad.h
@@ -37,6 +37,15 @@ struct security_association {
        UInteger16      last_seqid;
 };
 
+/**
+ * Check the sequence id on header
+ * @param cfg    pointer to config that contains sad
+ * @param spp    security parameters pointer for desired sa
+ * @param seqid  sequence id to store in SA
+*/
+void sad_set_last_seqid(struct config *cfg, int spp,
+                       UInteger16 seqid);
+
 /**
  * authentication processing:
  *  1. check seqid (on sync/followup)
-- 
2.42.1



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

Reply via email to