noise: redesign preshared key mode

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2017-04-27 11:10:50 +02:00
parent 13db708a0f
commit fabb6eca2b
10 changed files with 73 additions and 64 deletions

View file

@ -37,16 +37,17 @@ func ipChecksum(buf []byte) uint16 {
func main() { func main() {
ourPrivate, _ := base64.StdEncoding.DecodeString("WAmgVYXkbT2bCtdcDwolI88/iVi/aV3/PHcUBTQSYmo=") ourPrivate, _ := base64.StdEncoding.DecodeString("WAmgVYXkbT2bCtdcDwolI88/iVi/aV3/PHcUBTQSYmo=")
ourPublic, _ := base64.StdEncoding.DecodeString("K5sF9yESrSBsOXPd6TcpKNgqoy1Ik3ZFKl4FolzrRyI=") ourPublic, _ := base64.StdEncoding.DecodeString("K5sF9yESrSBsOXPd6TcpKNgqoy1Ik3ZFKl4FolzrRyI=")
preshared, _ := base64.StdEncoding.DecodeString("FpCyhws9cxwWoV4xELtfJvjJN+zQVRPISllRWgeopVE=")
theirPublic, _ := base64.StdEncoding.DecodeString("qRCwZSKInrMAq5sepfCdaCsRJaoLe5jhtzfiw7CjbwM=") theirPublic, _ := base64.StdEncoding.DecodeString("qRCwZSKInrMAq5sepfCdaCsRJaoLe5jhtzfiw7CjbwM=")
preshared, _ := base64.StdEncoding.DecodeString("FpCyhws9cxwWoV4xELtfJvjJN+zQVRPISllRWgeopVE=")
cs := noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashBLAKE2s) cs := noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashBLAKE2s)
hs := noise.NewHandshakeState(noise.Config{ hs := noise.NewHandshakeState(noise.Config{
CipherSuite: cs, CipherSuite: cs,
Random: rand.Reader, Random: rand.Reader,
Pattern: noise.HandshakeIK, Pattern: noise.HandshakeIK,
Initiator: true, Initiator: true,
Prologue: []byte("WireGuard v0 zx2c4 Jason@zx2c4.com"), Prologue: []byte("WireGuard v1 zx2c4 Jason@zx2c4.com"),
PresharedKey: preshared, PresharedKey: preshared,
PresharedKeyPlacement: 2,
StaticKeypair: noise.DHKey{Private: ourPrivate, Public: ourPublic}, StaticKeypair: noise.DHKey{Private: ourPrivate, Public: ourPublic},
PeerStatic: theirPublic, PeerStatic: theirPublic,
}) })
@ -68,8 +69,10 @@ func main() {
initiationPacket[3] = 0 // Reserved initiationPacket[3] = 0 // Reserved
binary.LittleEndian.PutUint32(initiationPacket[4:], 28) // Sender index: 28 (arbitrary) binary.LittleEndian.PutUint32(initiationPacket[4:], 28) // Sender index: 28 (arbitrary)
initiationPacket, _, _ = hs.WriteMessage(initiationPacket, tai64n) initiationPacket, _, _ = hs.WriteMessage(initiationPacket, tai64n)
hasher, _ := blake2s.New(&blake2s.Config{Size: 16, Key: preshared}) hasher, _ := blake2s.New(&blake2s.Config{Size: 32})
hasher.Write([]byte("mac1----"))
hasher.Write(theirPublic) hasher.Write(theirPublic)
hasher, _ = blake2s.New(&blake2s.Config{Size: 16, Key: hasher.Sum(nil)})
hasher.Write(initiationPacket) hasher.Write(initiationPacket)
initiationPacket = append(initiationPacket, hasher.Sum(nil)[:16]...) initiationPacket = append(initiationPacket, hasher.Sum(nil)[:16]...)
initiationPacket = append(initiationPacket, make([]byte, 16)...) initiationPacket = append(initiationPacket, make([]byte, 16)...)

View file

@ -34,7 +34,7 @@ w :: PublicKey Curve25519
-> IO () -> IO ()
w theirPub (Plaintext myPSK) sock addr msg = do w theirPub (Plaintext myPSK) sock addr msg = do
let x = "\x01\x00\x00\x00\x00\x00" `mappend` msg let x = "\x01\x00\x00\x00\x00\x00" `mappend` msg
mac = hash 16 myPSK (sbToBS' (curvePubToBytes theirPub) `mappend` sbToBS' x) mac = hash 16 myPSK (sbToBS' (curvePubToBytes theirPub) `mappend` sbToBS' x) -- TODO: this should actually be blake2s(key=blake2s("mac1----" || theirPub), payload=blah)
void $ NBS.sendTo sock (x `mappend` mac `mappend` replicate 16 '\0') addr void $ NBS.sendTo sock (x `mappend` mac `mappend` replicate 16 '\0') addr
r :: MVar ByteString -> Socket -> IO ByteString r :: MVar ByteString -> Socket -> IO ByteString
@ -63,8 +63,8 @@ main = do
serverkey' = curveBytesToPub . bsToSB' . either undefined id . B64.decode . pack $ serverkey :: PublicKey Curve25519 serverkey' = curveBytesToPub . bsToSB' . either undefined id . B64.decode . pack $ serverkey :: PublicKey Curve25519
psk' = Plaintext . bsToSB' . either undefined id . B64.decode . pack $ psk psk' = Plaintext . bsToSB' . either undefined id . B64.decode . pack $ psk
hs = handshakeState $ HandshakeStateParams hs = handshakeState $ HandshakeStateParams
noiseIK noiseIK -- TODO: specify psk2 mode
"WireGuard v0 zx2c4 Jason@zx2c4.com" "WireGuard v1 zx2c4 Jason@zx2c4.com"
(Just psk') (Just psk')
(Just mykey') (Just mykey')
Nothing Nothing

View file

@ -39,11 +39,12 @@ fn main() {
owner.set_rs(&their_public); owner.set_rs(&their_public);
let mut cipherstate1 : CipherState<CipherChaChaPoly> = Default::default(); let mut cipherstate1 : CipherState<CipherChaChaPoly> = Default::default();
let mut cipherstate2 : CipherState<CipherChaChaPoly> = Default::default(); let mut cipherstate2 : CipherState<CipherChaChaPoly> = Default::default();
let mut handshake = HandshakeState::new_from_owner(&mut owner, true, HandshakePattern::IK, "WireGuard v0 zx2c4 Jason@zx2c4.com".as_bytes(), Some(&my_preshared[..]), &mut cipherstate1, &mut cipherstate2); //TODO: specify psk2 mode
let mut handshake = HandshakeState::new_from_owner(&mut owner, true, HandshakePattern::IK, "WireGuard v1 zx2c4 Jason@zx2c4.com".as_bytes(), Some(&my_preshared[..]), &mut cipherstate1, &mut cipherstate2);
let now = time::get_time(); let now = time::get_time();
let mut tai64n = [0; 12]; let mut tai64n = [0; 12];
BigEndian::write_i64(&mut tai64n[0..], 4611686018427387914ULL + now.sec); BigEndian::write_i64(&mut tai64n[0..], 4611686018427387914 + now.sec);
BigEndian::write_i32(&mut tai64n[8..], now.nsec); BigEndian::write_i32(&mut tai64n[8..], now.nsec);
let mut initiation_packet = [0; 148]; let mut initiation_packet = [0; 148];
initiation_packet[0] = 1; /* Type: Initiation */ initiation_packet[0] = 1; /* Type: Initiation */
@ -52,11 +53,13 @@ fn main() {
initiation_packet[3] = 0; /* Reserved */ initiation_packet[3] = 0; /* Reserved */
LittleEndian::write_u32(&mut initiation_packet[4..], 28); /* Sender index: 28 (arbitrary) */ LittleEndian::write_u32(&mut initiation_packet[4..], 28); /* Sender index: 28 (arbitrary) */
handshake.write_message(&tai64n, &mut initiation_packet[8..]); handshake.write_message(&tai64n, &mut initiation_packet[8..]);
let mut mac_material = [0; 148]; let mut mac_key_input = [0; 40];
memcpy(&mut mac_material, &their_public); let mut mac_key = [0; 32];
memcpy(&mut mac_material[32..], &initiation_packet[0..116]); memcpy(&mut mac_key_input, b"mac1----");
memcpy(&mut mac_key_input[8..], &their_public);
Blake2s::blake2s(&mut mac_key, &mac_key_input, &[0; 0]);
let mut mac = [0; 16]; let mut mac = [0; 16];
Blake2s::blake2s(&mut mac, &mac_material, &my_preshared); Blake2s::blake2s(&mut mac, &initiation_packet[0..116], &mac_key);
memcpy(&mut initiation_packet[116..], &mac); memcpy(&mut initiation_packet[116..], &mac);
socket.send_to(&initiation_packet, &send_addr).unwrap(); socket.send_to(&initiation_packet, &send_addr).unwrap();

View file

@ -9,20 +9,20 @@ while read -r -d $'\t' device; do
if [[ $device != "$last_device" ]]; then if [[ $device != "$last_device" ]]; then
[[ -z $last_device ]] && printf '\n' || printf '%s,\n' "$end" [[ -z $last_device ]] && printf '\n' || printf '%s,\n' "$end"
last_device="$device" last_device="$device"
read -r private_key public_key preshared_key listen_port fwmark read -r private_key public_key listen_port fwmark
printf '\t"%s": {' "$device" printf '\t"%s": {' "$device"
delim=$'\n' delim=$'\n'
[[ $private_key == "(none)" ]] || { printf '%s\t\t"privateKey": "%s"' "$delim" "$private_key"; delim=$',\n'; } [[ $private_key == "(none)" ]] || { printf '%s\t\t"privateKey": "%s"' "$delim" "$private_key"; delim=$',\n'; }
[[ $public_key == "(none)" ]] || { printf '%s\t\t"publicKey": "%s"' "$delim" "$public_key"; delim=$',\n'; } [[ $public_key == "(none)" ]] || { printf '%s\t\t"publicKey": "%s"' "$delim" "$public_key"; delim=$',\n'; }
[[ $preshared_key == "(none)" ]] || { printf '%s\t\t"presharedKey": "%s"' "$delim" "$preshared_key"; delim=$',\n'; }
[[ $listen_port == "0" ]] || { printf '%s\t\t"listenPort": %u' "$delim" $(( $listen_port )); delim=$',\n'; } [[ $listen_port == "0" ]] || { printf '%s\t\t"listenPort": %u' "$delim" $(( $listen_port )); delim=$',\n'; }
[[ $fwmark == "off" ]] || { printf '%s\t\t"fwmark": %u' "$delim" $(( $fwmark )); delim=$',\n'; } [[ $fwmark == "off" ]] || { printf '%s\t\t"fwmark": %u' "$delim" $(( $fwmark )); delim=$',\n'; }
printf '%s\t\t"peers": {' "$delim"; end=$'\n\t\t}\n\t}' printf '%s\t\t"peers": {' "$delim"; end=$'\n\t\t}\n\t}'
delim=$'\n' delim=$'\n'
else else
read -r public_key endpoint allowed_ips latest_handshake transfer_rx transfer_tx persistent_keepalive read -r public_key preshared_key endpoint allowed_ips latest_handshake transfer_rx transfer_tx persistent_keepalive
printf '%s\t\t\t"%s": {' "$delim" "$public_key" printf '%s\t\t\t"%s": {' "$delim" "$public_key"
delim=$'\n' delim=$'\n'
[[ $preshared_key == "(none)" ]] || { printf '%s\t\t\t\t"presharedKey": "%s"' "$delim" "$preshared_key"; delim=$',\n'; }
[[ $endpoint == "(none)" ]] || { printf '%s\t\t\t\t"endpoint": "%s"' "$delim" "$endpoint"; delim=$',\n'; } [[ $endpoint == "(none)" ]] || { printf '%s\t\t\t\t"endpoint": "%s"' "$delim" "$endpoint"; delim=$',\n'; }
[[ $latest_handshake == "0" ]] || { printf '%s\t\t\t\t"latestHandshake": %u' "$delim" $(( $latest_handshake )); delim=$',\n'; } [[ $latest_handshake == "0" ]] || { printf '%s\t\t\t\t"latestHandshake": %u' "$delim" $(( $latest_handshake )); delim=$',\n'; }
[[ $transfer_rx == "0" ]] || { printf '%s\t\t\t\t"transferRx": %u' "$delim" $(( $transfer_rx )); delim=$',\n'; } [[ $transfer_rx == "0" ]] || { printf '%s\t\t\t\t"transferRx": %u' "$delim" $(( $transfer_rx )); delim=$',\n'; }

View file

@ -21,7 +21,7 @@ _wg_completion() {
fi fi
if [[ $COMP_CWORD -eq 3 && ${COMP_WORDS[1]} == show && ${COMP_WORDS[2]} != interfaces ]]; then if [[ $COMP_CWORD -eq 3 && ${COMP_WORDS[1]} == show && ${COMP_WORDS[2]} != interfaces ]]; then
COMPREPLY+=( $(compgen -W "public-key private-key preshared-key listen-port peers endpoints allowed-ips fwmark latest-handshakes persistent-keepalive transfer dump" -- "${COMP_WORDS[3]}") ) COMPREPLY+=( $(compgen -W "public-key private-key listen-port peers preshared-keys endpoints allowed-ips fwmark latest-handshakes persistent-keepalive transfer dump" -- "${COMP_WORDS[3]}") )
return return
fi fi
@ -39,7 +39,6 @@ _wg_completion() {
[[ ${COMP_WORDS[i]} == listen-port ]] && has_listen_port=1 [[ ${COMP_WORDS[i]} == listen-port ]] && has_listen_port=1
[[ ${COMP_WORDS[i]} == fwmark ]] && has_fwmark=1 [[ ${COMP_WORDS[i]} == fwmark ]] && has_fwmark=1
[[ ${COMP_WORDS[i]} == private-key ]] && has_private_key=1 [[ ${COMP_WORDS[i]} == private-key ]] && has_private_key=1
[[ ${COMP_WORDS[i]} == preshared-key ]] && has_preshared_key=1
[[ ${COMP_WORDS[i]} == peer ]] && { has_peer=$i; break; } [[ ${COMP_WORDS[i]} == peer ]] && { has_peer=$i; break; }
done done
if [[ $has_peer -eq 0 ]]; then if [[ $has_peer -eq 0 ]]; then
@ -47,7 +46,6 @@ _wg_completion() {
[[ $has_listen_port -eq 1 ]] || words+=( listen-port ) [[ $has_listen_port -eq 1 ]] || words+=( listen-port )
[[ $has_fwmark -eq 1 ]] || words+=( fwmark ) [[ $has_fwmark -eq 1 ]] || words+=( fwmark )
[[ $has_private_key -eq 1 ]] || words+=( private-key ) [[ $has_private_key -eq 1 ]] || words+=( private-key )
[[ $has_preshared_key -eq 1 ]] || words+=( preshared-key )
words+=( peer ) words+=( peer )
COMPREPLY+=( $(compgen -W "${words[*]}" -- "${COMP_WORDS[COMP_CWORD]}") ) COMPREPLY+=( $(compgen -W "${words[*]}" -- "${COMP_WORDS[COMP_CWORD]}") )
elif [[ ${COMP_WORDS[COMP_CWORD-1]} == *-key ]]; then elif [[ ${COMP_WORDS[COMP_CWORD-1]} == *-key ]]; then
@ -70,6 +68,7 @@ _wg_completion() {
has_endpoint=0 has_endpoint=0
has_persistent_keepalive=0 has_persistent_keepalive=0
has_allowed_ips=0 has_allowed_ips=0
has_preshared_key=0
[[ ${COMP_WORDS[i+2]} == = ]] && ((i+=2)) || ((i++)) [[ ${COMP_WORDS[i+2]} == = ]] && ((i+=2)) || ((i++))
continue continue
fi fi
@ -77,6 +76,7 @@ _wg_completion() {
[[ ${COMP_WORDS[i]} == endpoint ]] && has_endpoint=1 [[ ${COMP_WORDS[i]} == endpoint ]] && has_endpoint=1
[[ ${COMP_WORDS[i]} == persistent-keepalive ]] && has_persistent_keepalive=1 [[ ${COMP_WORDS[i]} == persistent-keepalive ]] && has_persistent_keepalive=1
[[ ${COMP_WORDS[i]} == allowed-ips ]] && has_allowed_ips=1 [[ ${COMP_WORDS[i]} == allowed-ips ]] && has_allowed_ips=1
[[ ${COMP_WORDS[i]} == preshared-key ]] && has_preshared_key=1
[[ ${COMP_WORDS[i]} == remove ]] || ((i++)) [[ ${COMP_WORDS[i]} == remove ]] || ((i++))
done done
@ -84,6 +84,7 @@ _wg_completion() {
((COMP_CWORD == j)) || return ((COMP_CWORD == j)) || return
if [[ $has_remove -ne 1 ]]; then if [[ $has_remove -ne 1 ]]; then
[[ $has_preshared_key -eq 1 ]] || words+=( preshared-key )
[[ $has_endpoint -eq 1 ]] || words+=( endpoint ) [[ $has_endpoint -eq 1 ]] || words+=( endpoint )
[[ $has_allowed_ips -eq 1 ]] || words+=( allowed-ips ) [[ $has_allowed_ips -eq 1 ]] || words+=( allowed-ips )
[[ $has_persistent_keepalive -eq 1 ]] || words+=( persistent-keepalive ) [[ $has_persistent_keepalive -eq 1 ]] || words+=( persistent-keepalive )

View file

@ -323,10 +323,6 @@ static bool process_line(struct config_ctx *ctx, const char *line)
ret = parse_key(ctx->buf.dev->private_key, value); ret = parse_key(ctx->buf.dev->private_key, value);
if (!ret) if (!ret)
memset(ctx->buf.dev->private_key, 0, WG_KEY_LEN); memset(ctx->buf.dev->private_key, 0, WG_KEY_LEN);
} else if (key_match("PresharedKey")) {
ret = parse_key(ctx->buf.dev->preshared_key, value);
if (!ret)
memset(ctx->buf.dev->preshared_key, 0, WG_KEY_LEN);
} else } else
goto error; goto error;
} else if (ctx->is_peer_section) { } else if (ctx->is_peer_section) {
@ -338,7 +334,11 @@ static bool process_line(struct config_ctx *ctx, const char *line)
ret = parse_ipmasks(&ctx->buf, ctx->peer_offset, value); ret = parse_ipmasks(&ctx->buf, ctx->peer_offset, value);
else if (key_match("PersistentKeepalive")) else if (key_match("PersistentKeepalive"))
ret = parse_persistent_keepalive(&peer_from_offset(ctx->buf.dev, ctx->peer_offset)->persistent_keepalive_interval, value); ret = parse_persistent_keepalive(&peer_from_offset(ctx->buf.dev, ctx->peer_offset)->persistent_keepalive_interval, value);
else else if (key_match("PresharedKey")) {
ret = parse_key(peer_from_offset(ctx->buf.dev, ctx->peer_offset)->preshared_key, value);
if (!ret)
memset(peer_from_offset(ctx->buf.dev, ctx->peer_offset)->preshared_key, 0, WG_KEY_LEN);
} else
goto error; goto error;
} else } else
goto error; goto error;
@ -408,8 +408,6 @@ bool config_read_finish(struct config_ctx *ctx)
fprintf(stderr, "No private key configured\n"); fprintf(stderr, "No private key configured\n");
goto err; goto err;
} }
if (ctx->buf.dev->flags & WGDEVICE_REPLACE_PEERS && !key_is_valid(ctx->buf.dev->preshared_key))
ctx->buf.dev->flags |= WGDEVICE_REMOVE_PRESHARED_KEY;
if (ctx->buf.dev->flags & WGDEVICE_REPLACE_PEERS && !ctx->buf.dev->fwmark) if (ctx->buf.dev->flags & WGDEVICE_REPLACE_PEERS && !ctx->buf.dev->fwmark)
ctx->buf.dev->flags |= WGDEVICE_REMOVE_FWMARK; ctx->buf.dev->flags |= WGDEVICE_REMOVE_FWMARK;
@ -508,21 +506,6 @@ bool config_read_cmd(struct wgdevice **device, char *argv[], int argc)
goto error; goto error;
argv += 2; argv += 2;
argc -= 2; argc -= 2;
} else if (!strcmp(argv[0], "preshared-key") && argc >= 2 && !buf.dev->num_peers) {
char *line;
int ret = read_line(&line, argv[1]);
if (ret == 0) {
if (!parse_key(buf.dev->preshared_key, line)) {
free(line);
goto error;
}
free(line);
} else if (ret == 1)
buf.dev->flags |= WGDEVICE_REMOVE_PRESHARED_KEY;
else
goto error;
argv += 2;
argc -= 2;
} else if (!strcmp(argv[0], "peer") && argc >= 2) { } else if (!strcmp(argv[0], "peer") && argc >= 2) {
peer_offset = buf.pos; peer_offset = buf.pos;
if (use_space(&buf, sizeof(struct wgpeer)) < 0) { if (use_space(&buf, sizeof(struct wgpeer)) < 0) {
@ -560,6 +543,22 @@ bool config_read_cmd(struct wgdevice **device, char *argv[], int argc)
goto error; goto error;
argv += 2; argv += 2;
argc -= 2; argc -= 2;
} else if (!strcmp(argv[0], "preshared-key") && argc >= 2 && buf.dev->num_peers) {
char *line;
int ret = read_line(&line, argv[1]);
if (ret == 0) {
if (!parse_key(peer_from_offset(buf.dev, peer_offset)->preshared_key, line)) {
free(line);
goto error;
}
free(line);
} else if (ret == 1) {
free(line);
buf.dev->flags |= WGPEER_REMOVE_PRESHARED_KEY;
} else
goto error;
argv += 2;
argc -= 2;
} else { } else {
fprintf(stderr, "Invalid argument: %s\n", argv[0]); fprintf(stderr, "Invalid argument: %s\n", argv[0]);
goto error; goto error;

View file

@ -13,7 +13,7 @@ int set_main(int argc, char *argv[])
int ret = 1; int ret = 1;
if (argc < 3) { if (argc < 3) {
fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [peer <base64 public key> [remove] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>]...] ]...\n", PROG_NAME, argv[0]); fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [peer <base64 public key> [remove] [preshared-key <file path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>]...] ]...\n", PROG_NAME, argv[0]);
return 1; return 1;
} }

View file

@ -201,7 +201,7 @@ static char *bytes(uint64_t b)
static const char *COMMAND_NAME = NULL; static const char *COMMAND_NAME = NULL;
static void show_usage(void) static void show_usage(void)
{ {
fprintf(stderr, "Usage: %s %s { <interface> | all | interfaces } [public-key | private-key | preshared-key | listen-port | fwmark | peers | endpoints | allowed-ips | latest-handshakes | transfer | persistent-keepalive | dump]\n", PROG_NAME, COMMAND_NAME); fprintf(stderr, "Usage: %s %s { <interface> | all | interfaces } [public-key | private-key | listen-port | fwmark | peers | preshared-keys | endpoints | allowed-ips | latest-handshakes | transfer | persistent-keepalive | dump]\n", PROG_NAME, COMMAND_NAME);
} }
static void pretty_print(struct wgdevice *device) static void pretty_print(struct wgdevice *device)
@ -216,8 +216,6 @@ static void pretty_print(struct wgdevice *device)
terminal_printf(" " TERMINAL_BOLD "public key" TERMINAL_RESET ": %s\n", key(device->public_key)); terminal_printf(" " TERMINAL_BOLD "public key" TERMINAL_RESET ": %s\n", key(device->public_key));
if (memcmp(device->private_key, zero, WG_KEY_LEN)) if (memcmp(device->private_key, zero, WG_KEY_LEN))
terminal_printf(" " TERMINAL_BOLD "private key" TERMINAL_RESET ": %s\n", masked_key(device->private_key)); terminal_printf(" " TERMINAL_BOLD "private key" TERMINAL_RESET ": %s\n", masked_key(device->private_key));
if (memcmp(device->preshared_key, zero, WG_KEY_LEN))
terminal_printf(" " TERMINAL_BOLD "preshared key" TERMINAL_RESET ": %s\n", masked_key(device->preshared_key));
if (device->port) if (device->port)
terminal_printf(" " TERMINAL_BOLD "listening port" TERMINAL_RESET ": %u\n", device->port); terminal_printf(" " TERMINAL_BOLD "listening port" TERMINAL_RESET ": %u\n", device->port);
if (device->fwmark) if (device->fwmark)
@ -228,6 +226,8 @@ static void pretty_print(struct wgdevice *device)
} }
for_each_wgpeer(device, peer, i) { for_each_wgpeer(device, peer, i) {
terminal_printf(TERMINAL_FG_YELLOW TERMINAL_BOLD "peer" TERMINAL_RESET ": " TERMINAL_FG_YELLOW "%s" TERMINAL_RESET "\n", key(peer->public_key)); terminal_printf(TERMINAL_FG_YELLOW TERMINAL_BOLD "peer" TERMINAL_RESET ": " TERMINAL_FG_YELLOW "%s" TERMINAL_RESET "\n", key(peer->public_key));
if (memcmp(peer->preshared_key, zero, WG_KEY_LEN))
terminal_printf(" " TERMINAL_BOLD "preshared key" TERMINAL_RESET ": %s\n", masked_key(peer->preshared_key));
if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6)
terminal_printf(" " TERMINAL_BOLD "endpoint" TERMINAL_RESET ": %s\n", endpoint(&peer->endpoint.addr)); terminal_printf(" " TERMINAL_BOLD "endpoint" TERMINAL_RESET ": %s\n", endpoint(&peer->endpoint.addr));
terminal_printf(" " TERMINAL_BOLD "allowed ips" TERMINAL_RESET ": "); terminal_printf(" " TERMINAL_BOLD "allowed ips" TERMINAL_RESET ": ");
@ -260,7 +260,6 @@ static void dump_print(struct wgdevice *device, bool with_interface)
printf("%s\t", device->interface); printf("%s\t", device->interface);
printf("%s\t", key(device->private_key)); printf("%s\t", key(device->private_key));
printf("%s\t", key(device->public_key)); printf("%s\t", key(device->public_key));
printf("%s\t", key(device->preshared_key));
printf("%u\t", device->port); printf("%u\t", device->port);
if (device->fwmark) if (device->fwmark)
printf("0x%x\n", device->fwmark); printf("0x%x\n", device->fwmark);
@ -270,6 +269,7 @@ static void dump_print(struct wgdevice *device, bool with_interface)
if (with_interface) if (with_interface)
printf("%s\t", device->interface); printf("%s\t", device->interface);
printf("%s\t", key(peer->public_key)); printf("%s\t", key(peer->public_key));
printf("%s\t", key(peer->preshared_key));
if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6)
printf("%s\t", endpoint(&peer->endpoint.addr)); printf("%s\t", endpoint(&peer->endpoint.addr));
else else
@ -301,10 +301,6 @@ static bool ugly_print(struct wgdevice *device, const char *param, bool with_int
if (with_interface) if (with_interface)
printf("%s\t", device->interface); printf("%s\t", device->interface);
printf("%s\n", key(device->private_key)); printf("%s\n", key(device->private_key));
} else if (!strcmp(param, "preshared-key")) {
if (with_interface)
printf("%s\t", device->interface);
printf("%s\n", key(device->preshared_key));
} else if (!strcmp(param, "listen-port")) { } else if (!strcmp(param, "listen-port")) {
if (with_interface) if (with_interface)
printf("%s\t", device->interface); printf("%s\t", device->interface);
@ -358,6 +354,13 @@ static bool ugly_print(struct wgdevice *device, const char *param, bool with_int
else else
printf("%s\toff\n", key(peer->public_key)); printf("%s\toff\n", key(peer->public_key));
} }
} else if (!strcmp(param, "preshared-keys")) {
for_each_wgpeer(device, peer, i) {
if (with_interface)
printf("%s\t", device->interface);
printf("%s\t", key(peer->public_key));
printf("%s\n", key(peer->preshared_key));
}
} else if (!strcmp(param, "peers")) { } else if (!strcmp(param, "peers")) {
for_each_wgpeer(device, peer, i) { for_each_wgpeer(device, peer, i) {
if (with_interface) if (with_interface)

View file

@ -50,14 +50,14 @@ int showconf_main(int argc, char *argv[])
key_to_base64(base64, device->private_key); key_to_base64(base64, device->private_key);
printf("PrivateKey = %s\n", base64); printf("PrivateKey = %s\n", base64);
} }
if (memcmp(device->preshared_key, zero, WG_KEY_LEN)) {
key_to_base64(base64, device->preshared_key);
printf("PresharedKey = %s\n", base64);
}
printf("\n"); printf("\n");
for_each_wgpeer(device, peer, i) { for_each_wgpeer(device, peer, i) {
key_to_base64(base64, peer->public_key); key_to_base64(base64, peer->public_key);
printf("[Peer]\nPublicKey = %s\n", base64); printf("[Peer]\nPublicKey = %s\n", base64);
if (memcmp(peer->preshared_key, zero, WG_KEY_LEN)) {
key_to_base64(base64, peer->preshared_key);
printf("PresharedKey = %s\n", base64);
}
if (peer->num_ipmasks) if (peer->num_ipmasks)
printf("AllowedIPs = "); printf("AllowedIPs = ");
for_each_wgipmask(peer, ipmask, j) { for_each_wgipmask(peer, ipmask, j) {

View file

@ -36,7 +36,7 @@ Sub-commands that take an INTERFACE must be passed a WireGuard interface.
.SH COMMANDS .SH COMMANDS
.TP .TP
\fBshow\fP { \fI<interface>\fP | \fIall\fP | \fIinterfaces\fP } [\fIpublic-key\fP | \fIprivate-key\fP | \fIpreshared-key\fP | \fIlisten-port\fP | \fIfwmark\fP | \fIpeers\fP | \fIendpoints\fP | \fIallowed-ips\fP | \fIlatest-handshakes\fP | \fIpersistent-keepalive\fP | \fItransfer\fP | \fIdump\fP] \fBshow\fP { \fI<interface>\fP | \fIall\fP | \fIinterfaces\fP } [\fIpublic-key\fP | \fIprivate-key\fP | \fIlisten-port\fP | \fIfwmark\fP | \fIpeers\fP | \fIpreshared-keys\fP | \fIendpoints\fP | \fIallowed-ips\fP | \fIlatest-handshakes\fP | \fIpersistent-keepalive\fP | \fItransfer\fP | \fIdump\fP]
Shows current WireGuard configuration of specified \fI<interface>\fP. Shows current WireGuard configuration of specified \fI<interface>\fP.
If no \fI<interface>\fP is specified, \fI<interface>\fP defaults to \fIall\fP. If no \fI<interface>\fP is specified, \fI<interface>\fP defaults to \fIall\fP.
If \fIinterfaces\fP is specified, prints a list of all WireGuard interfaces, If \fIinterfaces\fP is specified, prints a list of all WireGuard interfaces,
@ -46,16 +46,16 @@ meant for the terminal. Otherwise, prints specified information grouped by
newlines and tabs, meant to be used in scripts. For this script-friendly display, newlines and tabs, meant to be used in scripts. For this script-friendly display,
if \fIall\fP is specified, then the first field for all categories of information if \fIall\fP is specified, then the first field for all categories of information
is the interface name. If \fPdump\fP is specified, then several lines are printed; is the interface name. If \fPdump\fP is specified, then several lines are printed;
the first contains in order separated by tab: private-key, public-key, preshared-key, the first contains in order separated by tab: private-key, public-key, listen-port,
listen-port, fwmark. Subsequent lines are printed for each peer and contain in order fwmark. Subsequent lines are printed for each peer and contain in order separated
separated by tab: public-key, endpoint, allowed-ips, latest-handshake, transfer-rx, by tab: public-key, preshared-key, endpoint, allowed-ips, latest-handshake,
transfer-tx, persistent-keepalive. transfer-rx, transfer-tx, persistent-keepalive.
.TP .TP
\fBshowconf\fP \fI<interface>\fP \fBshowconf\fP \fI<interface>\fP
Shows the current configuration of \fI<interface>\fP in the format described Shows the current configuration of \fI<interface>\fP in the format described
by \fICONFIGURATION FILE FORMAT\fP below. by \fICONFIGURATION FILE FORMAT\fP below.
.TP .TP
\fBset\fP \fI<interface>\fP [\fIlisten-port\fP \fI<port>\fP] [\fIfwmark\fP \fI<fwmark>\fP] [\fIprivate-key\fP \fI<file-path>\fP] [\fIpreshared-key\fP \fI<file-path>\fP] [\fIpeer\fP \fI<base64-public-key>\fP [\fIremove\fP] [\fIendpoint\fP \fI<ip>:<port>\fP] [\fIpersistent-keepalive\fP \fI<interval seconds>\fP] [\fIallowed-ips\fP \fI<ip1>/<cidr1>\fP[,\fI<ip2>/<cidr2>\fP]...] ]... \fBset\fP \fI<interface>\fP [\fIlisten-port\fP \fI<port>\fP] [\fIfwmark\fP \fI<fwmark>\fP] [\fIprivate-key\fP \fI<file-path>\fP] [\fIpeer\fP \fI<base64-public-key>\fP [\fIremove\fP] [\fIpreshared-key\fP \fI<file-path>\fP] [\fIendpoint\fP \fI<ip>:<port>\fP] [\fIpersistent-keepalive\fP \fI<interval seconds>\fP] [\fIallowed-ips\fP \fI<ip1>/<cidr1>\fP[,\fI<ip2>/<cidr2>\fP]...] ]...
Sets configuration values for the specified \fI<interface>\fP. Multiple Sets configuration values for the specified \fI<interface>\fP. Multiple
\fIpeer\fPs may be specified, and if the \fIremove\fP argument is given \fIpeer\fPs may be specified, and if the \fIremove\fP argument is given
for a peer, that peer is removed, not configured. If \fIlisten-port\fP for a peer, that peer is removed, not configured. If \fIlisten-port\fP
@ -126,11 +126,6 @@ The \fIInterface\fP section may contain the following fields:
.IP \(bu .IP \(bu
PrivateKey \(em a base64 private key generated by \fIwg genkey\fP. Required. PrivateKey \(em a base64 private key generated by \fIwg genkey\fP. Required.
.IP \(bu .IP \(bu
PresharedKey \(em a base64 preshared key generated by \fIwg genpsk\fP. Optional,
and may be omitted. This option adds an additional layer of symmetric-key
cryptography to be mixed into the already existing public-key cryptography,
for post-quantum resistance.
.IP \(bu
ListenPort \(em a 16-bit port for listening. Optional; if not specified, chosen ListenPort \(em a 16-bit port for listening. Optional; if not specified, chosen
randomly. randomly.
.IP \(bu .IP \(bu
@ -143,6 +138,11 @@ PublicKey \(em a base64 public key calculated by \fIwg pubkey\fP from a
private key, and usually transmitted out of band to the author of the private key, and usually transmitted out of band to the author of the
configuration file. Required. configuration file. Required.
.IP \(bu .IP \(bu
PresharedKey \(em a base64 preshared key generated by \fIwg genpsk\fP. Optional,
and may be omitted. This option adds an additional layer of symmetric-key
cryptography to be mixed into the already existing public-key cryptography,
for post-quantum resistance.
.IP \(bu
AllowedIPs \(em a comma-separated list of ip (v4 or v6) addresses with AllowedIPs \(em a comma-separated list of ip (v4 or v6) addresses with
CIDR masks from which this peer is allowed to send incoming traffic and CIDR masks from which this peer is allowed to send incoming traffic and
to which outgoing traffic for this peer is directed. The catch-all to which outgoing traffic for this peer is directed. The catch-all