Skip to content

Commit

Permalink
pmc: add authentication tlv for pmc
Browse files Browse the repository at this point in the history
add sad_process_auth() and sad_append_auth_tlv() to the pmc_recv() and
pmc_send() functions. In addition, add a config pointer & spp to the
pmc structure and add sad_create() & sad_destroy() to functions.

Signed-off-by: Clay Kaiser <Clay.Kaiser@ibm.com>
Reviewed-by: Erez Geva <ErezGeva2@gmail.com>
Reviewed-by: Miroslav Lichvar <mlichvar@redhat.com>
  • Loading branch information
Clay Kaiser (via linuxptp-devel Mailing List) authored and richardcochran committed Jun 4, 2024
1 parent 0aef576 commit cbb23a6
Show file tree
Hide file tree
Showing 14 changed files with 230 additions and 24 deletions.
1 change: 1 addition & 0 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ static struct config_enum bmca_enu[] = {

struct config_item config_tab[] = {
PORT_ITEM_UIN("active_key_id", 0, 0, UINT32_MAX),
PORT_ITEM_INT("allow_unauth", 0, 0, 2),
PORT_ITEM_INT("allowedLostResponses", 3, 1, 255),
PORT_ITEM_INT("announceReceiptTimeout", 3, 2, UINT8_MAX),
PORT_ITEM_ENU("asCapable", AS_CAPABLE_AUTO, as_capable_enu),
Expand Down
14 changes: 7 additions & 7 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ ptp4l: $(OBJ)
nsm: config.o $(FILTERS) hash.o interface.o msg.o nsm.o phc.o print.o \
rtnl.o sk.o $(TRANSP) tlv.o tsproc.o util.o version.o

pmc: config.o hash.o interface.o msg.o phc.o pmc.o pmc_common.o print.o sk.o \
tlv.o $(TRANSP) util.o version.o
pmc: config.o hash.o interface.o msg.o phc.o pmc.o pmc_common.o print.o \
$(SECURITY) sk.o tlv.o $(TRANSP) util.o version.o

phc2sys: clockadj.o clockcheck.o config.o hash.o interface.o msg.o \
phc.o phc2sys.o pmc_agent.o pmc_common.o print.o $(SERVOS) sk.o stats.o \
sysoff.o tlv.o $(TRANSP) util.o version.o
phc.o phc2sys.o pmc_agent.o pmc_common.o print.o $(SECURITY) $(SERVOS) \
sk.o stats.o sysoff.o tlv.o $(TRANSP) util.o version.o

hwstamp_ctl: hwstamp_ctl.o version.o

Expand All @@ -88,11 +88,11 @@ phc_ctl: phc_ctl.o phc.o sk.o util.o clockadj.o sysoff.o print.o version.o
timemaster: phc.o print.o rtnl.o sk.o timemaster.o util.o version.o

ts2phc: config.o clockadj.o hash.o interface.o msg.o phc.o pmc_agent.o \
pmc_common.o print.o $(SERVOS) sk.o $(TS2PHC) tlv.o transport.o raw.o \
udp.o udp6.o uds.o util.o version.o
pmc_common.o print.o $(SECURITY) $(SERVOS) sk.o $(TS2PHC) tlv.o transport.o \
raw.o udp.o udp6.o uds.o util.o version.o

tz2alt: config.o hash.o interface.o lstab.o msg.o phc.o pmc_common.o print.o \
sk.o tlv.o $(TRANSP) tz2alt.o util.o version.o
$(SECURITY) sk.o tlv.o $(TRANSP) tz2alt.o util.o version.o

version.o: .version version.sh $(filter-out version.d,$(DEPEND))

Expand Down
28 changes: 27 additions & 1 deletion phc2sys.8
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH PHC2SYS 8 "February 2023" "linuxptp"
.TH PHC2SYS 8 "March 2024" "linuxptp"
.SH NAME
phc2sys \- synchronize two or more clocks

Expand Down Expand Up @@ -270,6 +270,15 @@ sets the program options. This is the only used option.

.SH FILE OPTIONS

.TP
.B active_key_id
Used in conjunction with \fBspp\fR and \fBsa_file\fR directives to
specify which key from the \fBspp\fR defined Security Association
should be used for outbound icv calculations. All Security Assocations
are read from the file specified by \fBsa_file\fR. Requires \fBspp\fR
and \fBsa_file\fR directives. Must be in the range of 1 to 2^32-1,
inclusive. The default is 0 (disabled).

.TP
.B clock_servo
The servo which is used to synchronize the local clock. Valid values
Expand Down Expand Up @@ -357,6 +366,14 @@ Same as option
The address of the UNIX domain socket to be used by the refclock_sock servo.
The default is /var/run/refclock.ptp.sock.

.TP
.B sa_file
Specifies the location of the file containing Security Associations used
for immediate security processing of the Authentication TLV in support of
the optional security mechanism defined in ieee1588-2019 ch 14.16. See
\fBSECURITY ASSOCIATION OPTIONS\fR for more info on file contents.
The default is an empty string. (disabled).

.TP
.B sanity_freq_limit
The maximum allowed frequency offset between uncorrected clock and the
Expand All @@ -380,6 +397,15 @@ Same as option
.B \-S
(see above).

.TP
.B spp
Specifies the security parameters pointer for the desired security association
to be used for authentication tlv support. If specified, the port owning the
spp will attempt to attach (outbound) and check (inbound) authentication tlvs
for all messages in accordance to the corresponding security association
sourced via the \fBsa_file\fR directive. Not compatible with one step ports.
Must be in the range of -1 to 255, inclusive. The default is -1 (disabled).

.TP
.B transportSpecific
The transport specific field. Must be in the range 0 to 255.
Expand Down
5 changes: 5 additions & 0 deletions phc2sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "pi.h"
#include "pmc_agent.h"
#include "print.h"
#include "sad.h"
#include "servo.h"
#include "sk.h"
#include "stats.h"
Expand Down Expand Up @@ -1447,6 +1448,10 @@ int main(int argc, char *argv[])
n_domains = 1;
}

if (sad_create(cfg)) {
goto end;
}

for (i = 0; i < n_domains; i++) {
domains[i] = settings;
domains[i].agent = pmc_agent_create();
Expand Down
46 changes: 45 additions & 1 deletion pmc.8
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH PMC 8 "February 2023" "linuxptp"
.TH PMC 8 "March 2024" "linuxptp"
.SH NAME
pmc \- PTP management client

Expand Down Expand Up @@ -144,8 +144,38 @@ options. The name of the section is the name of the configured port (e.g.
.B domainNumber
The domain attribute of the local clock. The default is 0.

.TP
.B sa_file
Specifies the location of the file containing Security Associations
used for immediate security processing of the Authentication TLV in
support of the optional security mechanism defined in ieee1588-2019
ch 14.16. See \fBSECURITY ASSOCIATION OPTIONS\fR for information on how
this file should be formatted. \fBspp\fR and \fBactive_key_id\fR should
be specifed for each port to indicate which Security Association from
the /fBsa_file/fR should be used. The default is an empty string.

.SH PORT OPTIONS

.TP
.B active_key_id
Used in conjunction with \fBspp\fR and \fBsa_file\fR directives to
specify which key from the \fBspp\fR defined Security Association
should be used for outbound icv calculations. All Security Assocations
are read from the file specified by \fBsa_file\fR. Requires \fBspp\fR
and \fBsa_file\fR directives. Must be in the range of 1 to 2^32-1,
inclusive. The default is 0 (disabled).

.TP
.B allow_unauth
Allows for pmc to accept unauthenticated management response and
signaling messages when authentication is enabled and \fBspp\fR,
\fBactive_key_id\fR and \fBsa_file\fR are set. Possible values are:
0: normal receiving
1: accept mgmt resp/signaling without Authentication TLV
2: accept mgmt resp/signaling without Authentication TLV or with wrong
Authentication TLV
The default is 0 (disabled).

.TP
.B network_transport
Select the network transport. Possible values are UDPv4, UDPv6 and L2. The default
Expand All @@ -155,6 +185,20 @@ is UDPv4.
.B ptp_dst_mac
The MAC address to which PTP management messages should be sent. Relevant only with L2 transport. The default is 01:1B:19:00:00:00.

.TP
.B spp
Specifies the Security Parameters Pointer of the desired Security
Association to be used for Authentication TLV support for a given port.
Any port with an assigned spp will attach Authentication TLVs to all
outbound messages and check for Authentication TLVs on all inbound
messages in accordance to the corresponding security association
sourced via the \fBsa_file\fR directive. Outbound Authentication TLVs
are generated using the key specified by \fBactive_key_id\fR. Not
compatible with one step ports or advertised versions less then
PTPv2.1. Requires \fBsa_file\fR and \fBactive_key_id\fR directives.
Must be in the range of 0 to 255, inclusive.
The default is -1 (disabled).

.TP
.B transportSpecific
The transport specific field. Must be in the range 0 to 255.
Expand Down
11 changes: 9 additions & 2 deletions pmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "notification.h"
#include "pmc_common.h"
#include "print.h"
#include "sad.h"
#include "tlv.h"
#include "uds.h"
#include "util.h"
Expand Down Expand Up @@ -712,7 +713,7 @@ int main(int argc, char *argv[])
int ret = 0;
char line[1024], *command = NULL, uds_local[MAX_IFNAME_SIZE + 1];
enum transport_type transport_type = TRANS_UDP_IPV4;
UInteger8 boundary_hops = 1, domain_number = 0, transport_specific = 0;
UInteger8 boundary_hops = 1, domain_number = 0, transport_specific = 0, allow_unauth = 0;
struct ptp_message *msg;
struct option *opts;
struct config *cfg;
Expand Down Expand Up @@ -826,6 +827,11 @@ int main(int argc, char *argv[])
transport_type = config_get_int(cfg, NULL, "network_transport");
transport_specific = config_get_int(cfg, NULL, "transportSpecific") << 4;
domain_number = config_get_int(cfg, NULL, "domainNumber");
allow_unauth = config_get_int(cfg, NULL, "allow_unauth");

if (sad_create(cfg)) {
goto out;
}

if (!iface_name) {
if (transport_type == TRANS_UDS) {
Expand All @@ -847,7 +853,7 @@ int main(int argc, char *argv[])
pmc = pmc_create(cfg, transport_type, iface_name,
config_get_string(cfg, NULL, "uds_address"),
boundary_hops, domain_number, transport_specific,
zero_datalen);
allow_unauth, zero_datalen);
if (!pmc) {
fprintf(stderr, "failed to create pmc\n");
config_destroy(cfg);
Expand Down Expand Up @@ -928,6 +934,7 @@ int main(int argc, char *argv[])
msg_cleanup();

out:
sad_destroy(cfg);
config_destroy(cfg);
return ret;
}
2 changes: 1 addition & 1 deletion pmc_agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ int init_pmc_node(struct config *cfg, struct pmc_agent *node, const char *uds,
node->pmc = pmc_create(cfg, TRANS_UDS, uds,
config_get_string(cfg, NULL, "uds_address"), 0,
config_get_int(cfg, NULL, "domainNumber"),
config_get_int(cfg, NULL, "transportSpecific") << 4, 1);
config_get_int(cfg, NULL, "transportSpecific") << 4, 0, 1);
if (!node->pmc) {
pr_err("failed to create pmc");
return -1;
Expand Down
66 changes: 61 additions & 5 deletions pmc_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include "notification.h"
#include "print.h"
#include "sad.h"
#include "tlv.h"
#include "transport.h"
#include "pmc_common.h"
Expand Down Expand Up @@ -481,6 +482,7 @@ static void print_help(FILE *fp)
}

struct pmc {
struct config *cfg;
UInteger16 sequence_id;
UInteger8 boundary_hops;
UInteger8 domain_number;
Expand All @@ -492,12 +494,16 @@ struct pmc {
struct interface *iface;
struct fdarray fdarray;
int zero_length_gets;
int spp;
UInteger32 active_key_id;
UInteger8 allow_unauth;
};

struct pmc *pmc_create(struct config *cfg, enum transport_type transport_type,
const char *iface_name, const char *remote_address,
UInteger8 boundary_hops, UInteger8 domain_number,
UInteger8 transport_specific, int zero_datalen)
UInteger8 transport_specific, UInteger8 allow_unauth,
int zero_datalen)
{
struct pmc *pmc;
UInteger32 proc_id;
Expand All @@ -524,6 +530,14 @@ struct pmc *pmc_create(struct config *cfg, enum transport_type transport_type,
pmc->boundary_hops = boundary_hops;
pmc->domain_number = domain_number;
pmc->transport_specific = transport_specific;
pmc->cfg = cfg;
pmc->spp = config_get_int(cfg, NULL, "spp");
pmc->active_key_id = config_get_uint(cfg, NULL, "active_key_id");
pmc->allow_unauth = allow_unauth;

if (sad_readiness_check(pmc->spp, pmc->active_key_id, pmc->cfg)) {
goto failed;
}

pmc->transport = transport_create(cfg, transport_type);
if (!pmc->transport) {
Expand Down Expand Up @@ -595,7 +609,12 @@ static int pmc_send(struct pmc *pmc, struct ptp_message *msg)
{
int err;

err = msg_pre_send(msg);
if (pmc->spp >= 0) {
err = sad_append_auth_tlv(pmc->cfg, pmc->spp,
pmc->active_key_id, msg);
} else {
err = msg_pre_send(msg);
}
if (err) {
pr_err("msg_pre_send failed");
return -1;
Expand Down Expand Up @@ -815,8 +834,9 @@ int pmc_send_set_aton(struct pmc *pmc, int id, uint8_t key, const char *name)

struct ptp_message *pmc_recv(struct pmc *pmc)
{
struct ptp_message *msg;
int cnt, err;
struct ptp_message *msg, *dup = NULL;
int cnt, err, spp = pmc->spp;
struct tlv_extra *extra;

msg = msg_allocate();
if (!msg) {
Expand All @@ -829,6 +849,12 @@ struct ptp_message *pmc_recv(struct pmc *pmc)
pr_err("recv message failed");
goto failed;
}
if (spp >= 0) {
dup = msg_duplicate(msg, 0);
if (!dup) {
goto failed;
}
}
err = msg_post_recv(msg, cnt);
if (err) {
switch (err) {
Expand All @@ -846,10 +872,40 @@ struct ptp_message *pmc_recv(struct pmc *pmc)
msg_type_string(msg_type(msg)));
goto failed;
}

if (pmc->allow_unauth && (msg_type(msg) == SIGNALING ||
(msg_type(msg) == MANAGEMENT && management_action(msg) == RESPONSE))) {
spp = -1;
TAILQ_FOREACH(extra, &msg->tlv_list, list) {
if (extra->tlv->type == TLV_AUTHENTICATION) {
spp = pmc->spp;
}
}
}
err = sad_process_auth(pmc->cfg, spp, msg, dup);
if (err) {
if (pmc->allow_unauth == 2) {
pr_notice("auth failed but allow_unauth set");
} else {
switch (err) {
case -EBADMSG:
pr_err("auth: bad message");
break;
case -EPROTO:
pr_debug("auth: ignoring message");
break;
}
goto failed;
}
}
if (dup) {
msg_put(dup);
}
return msg;
failed:
msg_put(msg);
if (dup) {
msg_put(dup);
}
return NULL;
}

Expand Down
3 changes: 2 additions & 1 deletion pmc_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ struct pmc;
struct pmc *pmc_create(struct config *cfg, enum transport_type transport_type,
const char *iface_name, const char *remote_address,
UInteger8 boundary_hops, UInteger8 domain_number,
UInteger8 transport_specific, int zero_datalen);
UInteger8 transport_specific, UInteger8 allow_unauth,
int zero_datalen);

void pmc_destroy(struct pmc *pmc);

Expand Down
2 changes: 1 addition & 1 deletion port.c
Original file line number Diff line number Diff line change
Expand Up @@ -1956,7 +1956,7 @@ static int port_cmlds_initialize(struct port *p)
hops,
config_get_int(cfg, p->name, "cmlds.domainNumber"),
config_get_int(cfg, p->name, "cmlds.majorSdoId") << 4,
zero_datalen);
0, zero_datalen);
if (!p->cmlds.pmc) {
return -1;
}
Expand Down
Loading

0 comments on commit cbb23a6

Please sign in to comment.