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