Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,8 @@
"symmetric-key": [
{
"name": "wifi",
"infix-keystore:symmetric-key": "infixinfix",
"infix-keystore:key-format": "infix-crypto-types:wifi-preshared-key-format"
"cleartext-symmetric-key": "aW5maXhpbmZpeA==",
"key-format": "infix-crypto-types:passphrase-key-format"
}
]
}
Expand Down
6 changes: 4 additions & 2 deletions board/aarch64/raspberrypi-rpi64/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,10 @@ To configure WiFi as a client, first store your WiFi password in the keystore:
```
admin@infix:/> configure
admin@infix:/config/> edit keystore symmetric-key mywifi
admin@infix:/config/keystore/…/mywifi/> set key-format wifi-preshared-key-format
admin@infix:/config/keystore/…/mywifi/> set symmetric-key YourWiFiPassword
admin@infix:/config/keystore/…/mywifi/> set key-format passphrase-key-format
admin@infix:/config/keystore/…/mywifi/> change cleartext-symmetric-key
Passphrase: ************
Retype passphrase: ************
admin@infix:/config/keystore/…/mywifi/> leave
```

Expand Down
44 changes: 35 additions & 9 deletions board/common/rootfs/usr/bin/askpass
Original file line number Diff line number Diff line change
@@ -1,23 +1,49 @@
#!/bin/sh
# Prompt for a secret with confirmation, then encode and output it.
#
# Default mode: hash with mkpasswd (for system passwords)
# askpass [OUTPUT]
#
# Base64 mode (-b): base64-encode (for keystore passphrases)
# askpass -b [OUTPUT]
#
# If OUTPUT is given, result is written to the file.
# If omitted, result is written to stdout.
# shellcheck disable=SC3045

LABEL="New password"
MODE=hash
if [ "$1" = "-b" ]; then
LABEL="Passphrase"
MODE=base64
shift
fi
OUTPUT=$1

read -r -s -p "New password: " password
read -r -s -p "$LABEL: " secret
>&2 echo
read -r -s -p "Retype password: " password_again
read -r -s -p "Retype $LABEL: " secret_again
>&2 echo

if [ "$password" != "$password_again" ]; then
echo "Passwords do not match, try again."
if [ "$secret" != "$secret_again" ]; then
echo "${LABEL}s do not match, try again."
exit 1
fi

if [ -z "$OUTPUT" ]; then
echo "$password"
exit 0
if [ -z "$secret" ]; then
echo "Empty $LABEL, try again."
exit 1
fi

if [ "$MODE" = "base64" ]; then
encoded=$(printf '%s' "$secret" | base64 -w 0)
else
encoded=$(printf '%s\n' "$secret" | mkpasswd -s)
fi

umask 0177
echo "$password" | mkpasswd -s > "$OUTPUT"
exit 0
if [ -z "$OUTPUT" ]; then
echo "$encoded"
else
printf '%s' "$encoded" > "$OUTPUT"
fi
5 changes: 4 additions & 1 deletion doc/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ All notable changes to the project are documented in this file.

Noteworthy changes and additions in this release are marked below in bold text.

- Upgrade Linux kernel to 6.18.8 (LTS)
- **Upgrade Linux kernel from 6.12.65 to 6.18.8 (LTS)**
- Upgrade Buildroot to 2025.02.10 (LTS)
- Upgrade libyang to 4.2.2
- Upgrade sysrepo to 4.2.10
Expand Down Expand Up @@ -53,6 +53,9 @@ Noteworthy changes and additions in this release are marked below in bold text.
removed during upgrade (for the rest of the configuration to apply) and you
need to reconfigure them again. See the [WiFi][] documentation for details
- Add support for **WireGuard VPN tunnels**.
- Updated CLI `change` command to also support `cleartext-symmetric-key` which
is `type binary` and shared (using different `key-format`) between Wireguard
and WiFi applications for both keys and passphrases
- New default NACM privilege levels (user levels) in `factory-config`:
`operator` (network & container manager) and `guest` (read-only). For
details, see the updated system configuration documentation, as well as a
Expand Down
164 changes: 164 additions & 0 deletions doc/keystore.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Keystore

The Infix keystore is a centralized storage system for cryptographic keys
used throughout the system. It is based on the IETF standards [RFC 9641][1]
(Keystore) and [RFC 9640][2] (Cryptographic Types), with Infix extensions
for WiFi and WireGuard key formats.

## Overview

The keystore supports two types of cryptographic keys:

1. **Asymmetric Keys** — public/private key pairs used for:
- SSH host authentication (RSA keys)
- WireGuard VPN tunnels (X25519 keys)

2. **Symmetric Keys** — shared secrets used for:
- WiFi authentication (WPA2/WPA3 pre-shared keys)
- WireGuard VPN pre-shared keys

All keys are stored under the `ietf-keystore` configuration path and can be
managed via CLI, NETCONF, or RESTCONF.

### Supported Formats

| Asymmetric Key Format | Use Case | Key Type |
|----------------------------------------------------------|---------------|------------|
| `rsa-private-key-format` / `ssh-public-key-format` | SSH host keys | RSA |
| `x25519-private-key-format` / `x25519-public-key-format` | WireGuard VPN | Curve25519 |

| Symmetric Key Format | Use Case |
|-----------------------------|-----------------------------------|
| `passphrase-key-format` | Human-readable passphrases (WiFi) |
| `octet-string-key-format` | Raw symmetric keys (WireGuard) |

## Asymmetric Keys

Asymmetric keys consist of a public/private key pair. The public key can be
shared freely, while the private key must be kept secure.

### SSH Host Keys

SSH host keys identify the system during SSH and NETCONF connections. The
default host key is automatically generated on first boot and stored in the
keystore with the name `genkey`.

See [SSH Management](management.md) for details on generating and importing
custom SSH host keys.

### WireGuard Keys

WireGuard uses X25519 elliptic curve cryptography for key exchange. Each
WireGuard interface requires a public/private key pair stored as an asymmetric
key in the keystore. Key pairs can be generated directly from the CLI:

<pre class="cli"><code>admin@example:/> <b>wireguard genkey</b>
Private: aMqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP=
Public: bN1CwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP=
</code></pre>

See [WireGuard VPN](vpn-wireguard.md) for key generation and configuration
examples.

## Symmetric Keys

Symmetric keys are shared secrets where the same key must be configured on
all systems that need to communicate.

### WiFi Pre-Shared Keys

WiFi networks secured with WPA2 or WPA3 use pre-shared keys stored as
symmetric keys in the keystore with `passphrase-key-format`. The
passphrase must be 8-63 printable ASCII characters.

Since symmetric keys are stored as binary (base64-encoded), the CLI
provides the `change` command to enter passphrases interactively:

<pre class="cli"><code>admin@example:/config/keystore/…/my-wifi-key/> <b>change cleartext-symmetric-key</b>
Passphrase: ************
Retype passphrase: ************
</code></pre>

See [WiFi](wifi.md) for complete configuration examples.

### WireGuard Pre-Shared Keys

WireGuard supports optional pre-shared keys (PSK) that add a layer of
symmetric encryption alongside Curve25519. PSKs use the standard IETF
`octet-string-key-format` (32 random bytes). This provides defense-in-depth
against future quantum computers that might break elliptic curve cryptography.
Note that peer authentication still relies on Curve25519, so PSKs alone do
not provide complete post-quantum security.

PSKs can be generated directly from the CLI:

<pre class="cli"><code>admin@example:/> <b>wireguard genpsk</b>
cO2DxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2m=
</code></pre>

See [WireGuard VPN](vpn-wireguard.md) for PSK generation and usage examples.

## Viewing Keys

<pre class="cli"><code>admin@example:/> <b>configure</b>
admin@example:/config/> <b>show keystore</b>
asymmetric-keys {
asymmetric-key genkey {
public-key-format ssh-public-key-format;
public-key MIIBCgKCAQEAm6uCENSafz7mIfIJ8O.... AQAB;
private-key-format rsa-private-key-format;
cleartext-private-key MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYw...b7dyPr4mpHg==;
}
}
</code></pre>

> [!WARNING]
> The `show keystore` command displays private keys in cleartext. Be careful
> when viewing keys on shared screens or in logged sessions.

To list only asymmetric or symmetric keys:

<pre class="cli"><code>admin@example:/config/> <b>show keystore asymmetric-keys</b>
admin@example:/config/> <b>show keystore symmetric-keys</b>
</code></pre>

## Deleting Keys

<pre class="cli"><code>admin@example:/> <b>configure</b>
admin@example:/config/> <b>delete keystore asymmetric-key mykey</b>
admin@example:/config/> <b>leave</b>
</code></pre>

> [!CAUTION]
> Deleting a key that is referenced by a service (SSH, WireGuard, WiFi) will
> cause that service to fail. Verify the key is not in use before deletion.

## Security Considerations

The keystore is protected by NACM (Network Access Control Model) rules.
Only users in the `admin` group can view or modify cryptographic keys.
See [NACM](nacm.md) for details on access control.

Private keys are stored in cleartext in the configuration database.
Configuration files and backups containing the keystore should be treated
as sensitive and protected accordingly.

### Key Validation

Symmetric key values are stored as binary (base64-encoded). The backend
validates decoded key values based on their declared format:

- **WiFi passphrase** (`passphrase-key-format`): Must decode to 8-63 ASCII characters
- **WireGuard PSK** (`octet-string-key-format`): Must decode to exactly 32 bytes

## References

- [RFC 9641 - A YANG Data Model for a Keystore][1]
- [RFC 9640 - YANG Data Types and Groupings for Cryptography][2]
- [WiFi Documentation](wifi.md)
- [WireGuard VPN Documentation](vpn-wireguard.md)
- [SSH Management](management.md)
- [NACM Access Control](nacm.md)

[1]: https://datatracker.ietf.org/doc/html/rfc9641
[2]: https://datatracker.ietf.org/doc/html/rfc9640
5 changes: 5 additions & 0 deletions doc/management.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ RSA for now, thus the private key must be
`ietf-crypto-types:rsa-private-key-format` and the public key
`ietf-crypto-types:ssh-public-key-format`

> [!TIP]
> For comprehensive information about the keystore, including key management,
> security considerations, and examples for different key types, see the
> [Keystore documentation](keystore.md).

### Use your own SSH hostkeys

Hostkeys can be generated with OpenSSL:
Expand Down
45 changes: 17 additions & 28 deletions doc/vpn-wireguard.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,25 @@ Key features of WireGuard:
WireGuard uses public-key cryptography similar to SSH. Each WireGuard interface
requires a private key, and each peer is identified by its public key.

**Generate a WireGuard key pair using the `wg` command:**

```bash
admin@example:~$ wg genkey | tee privatekey | wg pubkey > publickey
admin@example:~$ cat privatekey
aMqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP=
admin@example:~$ cat publickey
bN1CwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP=
```

This generates a private key, saves it to `privatekey`, derives the public key,
and saves it to `publickey`.

**Import the private key into the keystore:**
**Import the key pair into the keystore:**

<pre class="cli"><code>admin@example:/> <b>configure</b>
admin@example:/config/> <b>edit keystore asymmetric-key wg-site-a</b>
admin@example:/config/keystore/asymmetric-key/wg-site-a/> <b>do wireguard genkey</b>
Private: aMqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP=
Public: bN1CwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP=
admin@example:/config/keystore/asymmetric-key/wg-site-a/> <b>set public-key-format x25519-public-key-format</b>
admin@example:/config/keystore/asymmetric-key/wg-site-a/> <b>set private-key-format x25519-private-key-format</b>
admin@example:/config/keystore/asymmetric-key/wg-site-a/> <b>set public-key bN1CwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP=</b>
admin@example:/config/keystore/asymmetric-key/wg-site-a/> <b>set private-key aMqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP=</b>
admin@example:/config/keystore/asymmetric-key/wg-site-a/> <b>set cleartext-private-key aMqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP=</b>
admin@example:/config/keystore/asymmetric-key/wg-site-a/> <b>leave</b>
admin@example:/>
</code></pre>

> [!TIP]
> The `do` prefix allows running admin-exec commands from configure context.
> Use the base for `wireguard genkey` when in admin-exec context.

**Import peer public keys into the truststore:**

<pre class="cli"><code>admin@example:/> <b>configure</b>
Expand All @@ -63,8 +57,7 @@ admin@example:/>

> [!IMPORTANT]
> Keep private keys secure! Never share your private key. Only exchange
> public keys with peers. Delete the `privatekey` file after importing it
> into the keystore.
> public keys with peers.

## Point-to-Point Configuration

Expand Down Expand Up @@ -394,20 +387,17 @@ recording traffic today would still need the PSK even if they break Curve25519
later. However, peer authentication still relies on Curve25519, so PSKs don't
provide complete post-quantum security.

**Generate a preshared key using `wg genpsk`:**
**Generate a preshared key:**

```bash
admin@example:~$ wg genpsk > preshared.key
admin@example:~$ cat preshared.key
<pre class="cli"><code>admin@example:/config/> <b>do wireguard genpsk</b>
cO2DxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2m=
```
</code></pre>

**Import the preshared key into the keystore:**

<pre class="cli"><code>admin@example:/> <b>configure</b>
admin@example:/config/> <b>edit keystore symmetric-key wg-psk</b>
admin@example:/config/keystore/symmetric-key/wg-psk/> <b>set key-format wireguard-symmetric-key-format</b>
admin@example:/config/keystore/symmetric-key/wg-psk/> <b>set key cO2DxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2m=</b>
<pre class="cli"><code>admin@example:/config/> <b>edit keystore symmetric-key wg-psk</b>
admin@example:/config/keystore/symmetric-key/wg-psk/> <b>set key-format octet-string-key-format</b>
admin@example:/config/keystore/symmetric-key/wg-psk/> <b>set cleartext-symmetric-key cO2DxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2m=</b>
admin@example:/config/keystore/symmetric-key/wg-psk/> <b>end</b>
admin@example:/config/interface/wg0/> <b>edit wireguard peers wg-peers peer remote</b>
admin@example:/config/interface/…/wg-peers/peer/remote/> <b>set preshared-key wg-psk</b>
Expand All @@ -420,5 +410,4 @@ on both sides.

> [!IMPORTANT]
> Preshared keys must be kept secret and exchanged through a secure channel,
> just like passwords. Delete the `preshared.key` file after importing it
> into both peer keystores.
> just like passwords.
Loading