diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index 10397402a46..1836b5fe00e 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -1241,7 +1241,7 @@
PrivateKeyFile=
- Takes a absolute path to a file which contains the Base64 encoded private key for the interface.
+ Takes an absolute path to a file which contains the Base64 encoded private key for the interface.
When this option is specified, then PrivateKey= is ignored.
Note that the file must be readable by the user systemd-network, so it
should be, e.g., owned by root:systemd-network with a
@@ -1296,6 +1296,16 @@
with a 0640 file mode.
+
+ PresharedKeyFile=
+
+ Takes an absolute path to a file which contains the Base64 encoded preshared key for the
+ peer. When this option is specified, then PresharedKey= is ignored.
+ Note that the file must be readable by the user systemd-network, so it
+ should be, e.g., owned by root:systemd-network with a
+ 0640 file mode.
+
+
AllowedIPs=
diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf
index fcd2ec2097b..1a3d6caeb9f 100644
--- a/src/network/netdev/netdev-gperf.gperf
+++ b/src/network/netdev/netdev-gperf.gperf
@@ -187,4 +187,5 @@ WireGuardPeer.AllowedIPs, config_parse_wireguard_allowed_ips, 0,
WireGuardPeer.Endpoint, config_parse_wireguard_endpoint, 0, 0
WireGuardPeer.PublicKey, config_parse_wireguard_public_key, 0, 0
WireGuardPeer.PresharedKey, config_parse_wireguard_preshared_key, 0, 0
+WireGuardPeer.PresharedKeyFile, config_parse_wireguard_preshared_key_file, 0, 0
WireGuardPeer.PersistentKeepalive, config_parse_wireguard_keepalive, 0, 0
diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c
index d897090f722..0b618962015 100644
--- a/src/network/netdev/wireguard.c
+++ b/src/network/netdev/wireguard.c
@@ -53,6 +53,7 @@ static void wireguard_peer_free(WireguardPeer *peer) {
free(peer->endpoint_host);
free(peer->endpoint_port);
+ free(peer->preshared_key_file);
explicit_bzero_safe(peer->preshared_key, WG_KEY_LEN);
free(peer);
@@ -602,6 +603,49 @@ int config_parse_wireguard_preshared_key(
return 0;
}
+int config_parse_wireguard_preshared_key_file(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL;
+ _cleanup_free_ char *path = NULL;
+ Wireguard *w;
+ int r;
+
+ assert(data);
+ w = WIREGUARD(data);
+ assert(w);
+
+ r = wireguard_peer_new_static(w, filename, section_line, &peer);
+ if (r < 0)
+ return r;
+
+ if (isempty(rvalue)) {
+ peer->preshared_key_file = mfree(peer->preshared_key_file);
+ TAKE_PTR(peer);
+ return 0;
+ }
+
+ path = strdup(rvalue);
+ if (!path)
+ return log_oom();
+
+ if (path_simplify_and_warn(path, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue) < 0)
+ return 0;
+
+ free_and_replace(peer->preshared_key_file, path);
+ TAKE_PTR(peer);
+ return 0;
+}
+
int config_parse_wireguard_public_key(
const char *unit,
const char *filename,
@@ -879,6 +923,7 @@ finalize:
static int wireguard_peer_verify(WireguardPeer *peer) {
NetDev *netdev = NETDEV(peer->wireguard);
+ int r;
if (section_is_invalid(peer->section))
return -EINVAL;
@@ -889,6 +934,14 @@ static int wireguard_peer_verify(WireguardPeer *peer) {
"Ignoring [WireGuardPeer] section from line %u.",
peer->section->filename, peer->section->line);
+ r = wireguard_read_key_file(peer->preshared_key_file, peer->preshared_key);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r,
+ "%s: Failed to read preshared key from '%s'. "
+ "Ignoring [WireGuardPeer] section from line %u.",
+ peer->section->filename, peer->preshared_key_file,
+ peer->section->line);
+
return 0;
}
diff --git a/src/network/netdev/wireguard.h b/src/network/netdev/wireguard.h
index 6cf6eec14db..4ae520c52ba 100644
--- a/src/network/netdev/wireguard.h
+++ b/src/network/netdev/wireguard.h
@@ -21,6 +21,7 @@ typedef struct WireguardPeer {
uint8_t public_key[WG_KEY_LEN];
uint8_t preshared_key[WG_KEY_LEN];
+ char *preshared_key_file;
uint32_t flags;
uint16_t persistent_keepalive_interval;
@@ -63,4 +64,5 @@ CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_public_key);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_private_key);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_private_key_file);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_preshared_key);
+CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_preshared_key_file);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_keepalive);
diff --git a/test/fuzz/fuzz-netdev-parser/directives.netdev b/test/fuzz/fuzz-netdev-parser/directives.netdev
index e0756dc7554..7da3955af6b 100644
--- a/test/fuzz/fuzz-netdev-parser/directives.netdev
+++ b/test/fuzz/fuzz-netdev-parser/directives.netdev
@@ -52,6 +52,7 @@ Name=
[WireGuardPeer]
Endpoint=
PresharedKey=
+PresharedKeyFile=
PersistentKeepalive=
PublicKey=
AllowedIPs=