sad_append_auth_tlv() will append an authentication tlv as specified by the
security association corresponding to the passed spp. After attached,
msg_pre_send() is called to put message in network byte order and
sad_generate_icv() is called to populate the icv field in the tlv.

the allow_mutable flag will set the correction field to 0 before generating
the icv to allow for configurations where on path auth tlv support is not
present.

Signed-off-by: Clay Kaiser <clay.kai...@ibm.com>
---
 config.c       |  1 +
 port.c         | 18 ++++++++++--
 port_private.h |  1 +
 sad.c          | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++
 sad.h          | 12 ++++++++
 5 files changed, 106 insertions(+), 3 deletions(-)

diff --git a/config.c b/config.c
index c483920..c631460 100644
--- a/config.c
+++ b/config.c
@@ -365,6 +365,7 @@ struct config_item config_tab[] = {
        GLOB_ITEM_INT("verbose", 0, 0, 1),
        GLOB_ITEM_INT("write_phase_mode", 0, 0, 1),
        PORT_ITEM_INT("spp", -1, -1, UINT8_MAX),
+       PORT_ITEM_INT("active_key_id", 0, 0, INT_MAX),
        GLOB_ITEM_STR("sa_file", NULL),
 };
 
diff --git a/port.c b/port.c
index d7e5ec0..d52a2a5 100644
--- a/port.c
+++ b/port.c
@@ -679,7 +679,13 @@ static int peer_prepare_and_send(struct port *p, struct 
ptp_message *msg,
                                 enum transport_event event)
 {
        int cnt;
-       if (msg_pre_send(msg)) {
+       if (port_has_security(p)) {
+               cnt = sad_append_auth_tlv(clock_config(p->clock), p->spp,
+                                         p->active_key_id, msg);
+       } else {
+               cnt = msg_pre_send(msg);
+       }
+       if (cnt) {
                return -1;
        }
        if (msg_unicast(msg)) {
@@ -3116,8 +3122,13 @@ int port_prepare_and_send(struct port *p, struct 
ptp_message *msg,
                          enum transport_event event)
 {
        int cnt;
-
-       if (msg_pre_send(msg)) {
+       if (port_has_security(p)) {
+               cnt = sad_append_auth_tlv(clock_config(p->clock), p->spp,
+                                         p->active_key_id, msg);
+       } else {
+               cnt = msg_pre_send(msg);
+       }
+       if (cnt) {
                return -1;
        }
        if (msg_unicast(msg)) {
@@ -3456,6 +3467,7 @@ struct port *port_open(const char *phc_device,
                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");
+       p->active_key_id = config_get_int(cfg, p->name, "active_key_id");
 
        if (!port_is_uds(p) && unicast_client_initialize(p)) {
                goto err_transport;
diff --git a/port_private.h b/port_private.h
index 8ef9593..3933d07 100644
--- a/port_private.h
+++ b/port_private.h
@@ -165,6 +165,7 @@ struct port {
        struct monitor *slave_event_monitor;
        bool unicast_state_dirty;
        int spp;
+       UInteger32 active_key_id;
 };
 
 #define portnum(p) (p->portIdentity.portNumber)
diff --git a/sad.c b/sad.c
index 5129675..ee8ead4 100644
--- a/sad.c
+++ b/sad.c
@@ -73,6 +73,83 @@ static inline int sad_get_auth_tlv_len(struct 
security_association *sa,
               icv_len; /* size of icv (defined by key) */
 }
 
+static int sad_generate_icv(struct security_association *sa,
+                           struct security_association_key *key,
+                           struct ptp_message *msg, void *icv)
+{
+       int data_len, icv_len = 0;
+       Integer64 correction = 0;
+
+       /* msg length to start of icv */
+       data_len = (char *) icv - (char *) msg;
+
+       /* set correction to zero if mutable fields are allowed */
+       if (sa->mutable && msg->header.correction != 0) {
+               correction = msg->header.correction;
+               msg->header.correction = 0;
+       }
+
+       /* generate digest */
+       icv_len = sad_hash(key->data, msg, data_len,
+                          icv, key->icv.len);
+
+       if (correction != 0) {
+               msg->header.correction = correction;
+       }
+
+       return icv_len;
+}
+
+int sad_append_auth_tlv(struct config *cfg, int spp,
+                       UInteger32 key_id, struct ptp_message *msg)
+{
+       struct tlv_extra *extra;
+       struct authentication_tlv *auth;
+       struct security_association *sa;
+       struct security_association_key *key;
+       void *sequenceNo, *res, *icv;
+       /* immediately return if security is not configured */
+       if (spp < 0 || key_id < 1) {
+               return -1;
+       }
+       /* retrieve sa specified by spp */
+       sa = sad_get_association(cfg, spp);
+       if (sa == NULL) {
+               return -1;
+       }
+       /* retrieve key specified by key_id */
+       key = sad_get_key(sa, key_id);
+       if (key == NULL) {
+               return -1;
+       }
+       /* populate tlv fields */
+       extra = msg_tlv_append(msg, sad_get_auth_tlv_len(sa, key->icv.len));
+       auth = (struct authentication_tlv *) extra->tlv;
+       auth->type = TLV_AUTHENTICATION;
+       auth->length = sad_get_auth_tlv_len(sa, key->icv.len) - 4;
+       auth->spp = sa->spp;
+       auth->secParamIndicator = 0;
+       if (sa->res_ind) {
+               auth->secParamIndicator += 0x1;
+       }
+       if (sa->seqnum_ind) {
+               auth->secParamIndicator += 0x2;
+       }
+       auth->keyID = key->key_id;
+       /* set pointers to extra data used for icv generation */
+       sequenceNo = auth->data;
+       res = sequenceNo + (sa->seqnum_ind ? sa->seqnum_len : 0);
+       icv = res + (sa->res_ind ? sa->res_len : 0);
+       if (msg_pre_send(msg)) {
+               return -1;
+       }
+       if (!sad_generate_icv(sa, key, msg, icv)) {
+               return -1;
+       }
+
+       return 0;
+}
+
 void sad_set_last_seqid(struct config *cfg,
                        int spp, UInteger16 seqid)
 {
diff --git a/sad.h b/sad.h
index 4ab4ea2..7a5051d 100644
--- a/sad.h
+++ b/sad.h
@@ -37,6 +37,18 @@ struct security_association {
        UInteger16      last_seqid;
 };
 
+/**
+ * Append authentication tlv. Includes msg_pre_send() to put message in
+ * network byte order so the icv can be calculated.
+ * @param cfg     pointer to config that contains sad
+ * @param spp     security parameters pointer for desired sa
+ * @param key_id  key_id from sa to be used for icv calculation
+ * @param msg     msg that the authentication tlv should be attached too
+ * @return        -1 if sa/key is unknown, otherwise 0
+ */
+int sad_append_auth_tlv(struct config *cfg, int spp,
+                       UInteger32 key_id, struct ptp_message *msg);
+
 /**
  * Check the sequence id on header
  * @param cfg    pointer to config that contains sad
-- 
2.42.1



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

Reply via email to