From d9e70b09a19108e68de551c60fdc5fd40b3410cf Mon Sep 17 00:00:00 2001 From: "Clay Kaiser (via linuxptp-devel Mailing List)" Date: Fri, 24 May 2024 16:05:07 -0400 Subject: [PATCH] sad: introduce sad_append_auth_tlv() and sad_generate_icv() 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 Reviewed-by: Erez Geva Reviewed-by: Miroslav Lichvar --- port.c | 17 ++++++++-- sad.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sad.h | 13 ++++++++ 3 files changed, 127 insertions(+), 3 deletions(-) diff --git a/port.c b/port.c index 91702c29..754c9f0a 100644 --- a/port.c +++ b/port.c @@ -677,7 +677,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)) { @@ -3293,8 +3299,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)) { diff --git a/sad.c b/sad.c index 43ee92fc..c30ef0c0 100644 --- a/sad.c +++ b/sad.c @@ -67,6 +67,98 @@ static inline size_t sad_get_auth_tlv_len(struct security_association *sa, icv_len; /* size of icv (defined by key) */ } +/** + * generate and append icv to an outbound message. + * when mutable is set, set correction to zero before hash and + * replace when done. + */ +static int sad_generate_icv(struct security_association *sa, + struct security_association_key *key, + struct ptp_message *msg, void *icv) +{ + size_t 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->digest_len); + + if (correction != 0) { + msg->header.correction = correction; + } + + return icv_len; +} + +/** + * append auth tlv to outbound messages. This includes: + * 1. retrieve security association, key + * 2. append tlv aind fill in all values besides icv + * 3. run msg_pre_send to format message to send on wire + * 4. generate icv and attach to message + */ +int sad_append_auth_tlv(struct config *cfg, int spp, + size_t 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) { + return -1; + } + /* retrieve key specified by key_id */ + key = sad_get_key(sa, key_id); + if (!key) { + return -1; + } + /* populate tlv fields */ + extra = msg_tlv_append(msg, sad_get_auth_tlv_len(sa, key->icv->digest_len)); + if (!extra) { + return -1; + } + auth = (struct authentication_tlv *) extra->tlv; + auth->type = TLV_AUTHENTICATION; + auth->length = sad_get_auth_tlv_len(sa, key->icv->digest_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; +} + /** * update the last received seqid */ @@ -134,6 +226,14 @@ static int sad_check_seqid(struct ptp_message *msg, return 0; } +/** + * iterate through attached tlvs on inbound messages and process any auth tlvs + * this includes: + * 1. confirm received spp, secParamIndictor and key match our expectations + * 2. zero mutable fields (correction field) if mutable is set + * 3. generate icv of inbound message using key from sa with matching key id + * 4. compare our icv with icv attached to message + */ static int sad_check_auth_tlv(struct security_association *sa, struct ptp_message *msg, struct ptp_message *raw) diff --git a/sad.h b/sad.h index 4b797e81..3ee27b7a 100644 --- a/sad.h +++ b/sad.h @@ -25,6 +25,19 @@ struct security_association { Integer32 last_seqid; }; +/** + * Append authentication tlv to outbound messages. 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 + * @return -1 if sa/key is unknown, otherwise 0 + */ +int sad_append_auth_tlv(struct config *cfg, int spp, + size_t key_id, struct ptp_message *msg); + /** * Set the last received sequence id for SYNC/FOLLOW_UP * @param cfg pointer to config that contains sad