confd: restore IETF standard keystore leaf types and NACM rules

Infix key format identities now derive from the IETF bases, so the standard
identityref accepts them without any need for deviations.  This also preserves
the nacm default rules, which were inadvertently dropped before.

Also rename format identities for generality:

 - wifi-preshared-key-format      -> renamed: 'passphrase-key-format'
 - wireguard-symmetric-key-format -> use IETF 'octet-string-key-format'

Since cleartext-symmetric-key is now type binary (base64-encoded), the
WiFi backends (station and AP) decode values before passing them to
wpa_supplicant and hostapd.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2026-02-02 17:50:07 +01:00
parent 683f696e19
commit 5ceda4569e
7 changed files with 82 additions and 104 deletions
@@ -1,5 +1,13 @@
#!/bin/sh
# Rename cleartext-key to symmetric-key
# Migrate symmetric keys from v1.6 (v25.11) to IETF standard format.
#
# v1.6 had WiFi keys stored as:
# - infix-keystore:cleartext-key (type string, plaintext)
# - infix-keystore:key-format wifi-preshared-key-format
#
# v1.7 uses the IETF standard leaf and updated format names:
# - cleartext-symmetric-key (type binary, base64-encoded)
# - key-format passphrase-key-format
file=$1
temp=${file}.tmp
@@ -7,12 +15,17 @@ temp=${file}.tmp
jq '
if .["ietf-keystore:keystore"]?."symmetric-keys"?."symmetric-key" then
.["ietf-keystore:keystore"]."symmetric-keys"."symmetric-key" |= map(
if ."infix-keystore:key-format" then
del(."infix-keystore:key-format") |
. + { "key-format": "infix-crypto-types:passphrase-key-format" }
else
.
end |
if ."infix-keystore:cleartext-key" then
# Rename cleartext-key to symmetric-key
."infix-keystore:cleartext-key" as $key_value |
del(."infix-keystore:cleartext-key") | . + {
"infix-keystore:symmetric-key": $key_value
}
."infix-keystore:cleartext-key" as $val |
del(."infix-keystore:cleartext-key") |
. + { "cleartext-symmetric-key": ($val | @base64) }
else
.
end
+13 -5
View File
@@ -12,6 +12,7 @@
#include "core.h"
#include "interfaces.h"
#include "dagger.h"
#include "base64.h"
#define XPATH_BASE_ "/ietf-hardware:hardware"
#define HOSTAPD_CONF "/etc/hostapd-%s.conf"
@@ -235,8 +236,9 @@ static int wifi_find_radio_aps(struct lyd_node *cifs, const char *radio_name,
/* Helper: Write SSID and security configuration (shared between primary and BSS) */
static void wifi_gen_ssid_config(FILE *hostapd, struct lyd_node *cif, struct lyd_node *config, bool is_bss)
{
const char *ssid, *hidden, *security_mode, *secret_name, *secret;
const char *ssid, *hidden, *security_mode, *secret_name;
struct lyd_node *wifi, *ap, *security, *secret_node;
unsigned char *secret = NULL;
const char *ifname;
char bssid[18];
@@ -282,15 +284,19 @@ static void wifi_gen_ssid_config(FILE *hostapd, struct lyd_node *cif, struct lyd
security_mode = "open";
/* Get secret from keystore if needed */
secret = NULL;
if (strcmp(security_mode, "open") != 0) {
secret_name = lydx_get_cattr(security, "secret");
if (secret_name) {
const char *b64;
secret_node = lydx_get_xpathf(config,
"/keystore/symmetric-keys/symmetric-key[name='%s']/symmetric-key",
"/keystore/symmetric-keys/symmetric-key[name='%s']/cleartext-symmetric-key",
secret_name);
if (secret_node)
secret = lyd_get_value(secret_node);
if (secret_node) {
b64 = lyd_get_value(secret_node);
if (b64)
secret = base64_decode((const unsigned char *)b64, strlen(b64), NULL);
}
}
}
@@ -329,6 +335,8 @@ static void wifi_gen_ssid_config(FILE *hostapd, struct lyd_node *cif, struct lyd
/* ieee80211w=1: MFP capable but optional, for WPA2 client compatibility */
fprintf(hostapd, "ieee80211w=1\n");
}
free(secret);
}
/* Helper: Write radio-specific configuration */
+15 -8
View File
@@ -11,6 +11,7 @@
#include <srx/srx_val.h>
#include "interfaces.h"
#include "base64.h"
#define WPA_SUPPLICANT_CONF "/etc/wpa_supplicant-%s.conf"
@@ -59,8 +60,9 @@ int wifi_mode_changed(struct lyd_node *wifi)
*/
int wifi_gen_station(struct lyd_node *cif)
{
const char *ifname, *ssid, *secret_name, *secret, *security_mode, *radio;
const char *ifname, *ssid, *secret_name, *security_mode, *radio;
struct lyd_node *security, *secret_node, *radio_node, *station, *wifi;
unsigned char *secret = NULL;
FILE *wpa_supplicant = NULL;
char *security_str = NULL;
const char *country;
@@ -91,12 +93,14 @@ int wifi_gen_station(struct lyd_node *cif)
country = lydx_get_cattr(radio_node, "country-code");
if (secret_name && strcmp(security_mode, "disabled") != 0) {
const char *b64;
secret_node = lydx_get_xpathf(cif,
"../../keystore/symmetric-keys/symmetric-key[name='%s']",
secret_name);
secret = lydx_get_cattr(secret_node, "symmetric-key");
} else {
secret = NULL;
b64 = lydx_get_cattr(secret_node, "cleartext-symmetric-key");
if (b64)
secret = base64_decode((const unsigned char *)b64, strlen(b64), NULL);
}
oldmask = umask(0077);
@@ -121,11 +125,13 @@ int wifi_gen_station(struct lyd_node *cif)
/* If SSID is present, create network block. Otherwise, scan-only mode */
if (ssid) {
/* Station mode with network configured */
if (!strcmp(security_mode, "disabled")) {
if (!strcmp(security_mode, "disabled"))
asprintf(&security_str, "key_mgmt=NONE");
} else if (secret) {
asprintf(&security_str, "key_mgmt=SAE WPA-PSK\npsk=\"%s\"", secret);
}
else if (secret)
asprintf(&security_str,
"key_mgmt=SAE WPA-PSK\n"
" psk=\"%s\"", secret);
fprintf(wpa_supplicant,
"network={\n"
" bgscan=\"simple: 30:-45:300\"\n"
@@ -152,6 +158,7 @@ int wifi_gen_station(struct lyd_node *cif)
}
out:
free(secret);
if (wpa_supplicant)
fclose(wpa_supplicant);
umask(oldmask);
+21 -16
View File
@@ -15,32 +15,46 @@ module infix-crypto-types {
revision 2025-02-04 {
description "Initial";
}
identity private-key-format {
base ct:private-key-format;
description
"Base key-format identity for private keys.";
"Base for Infix private key format extensions.";
}
identity public-key-format {
base ct:public-key-format;
description
"Base key-format identity for public keys.";
"Base for Infix public key format extensions.";
}
identity rsa-private-key-format {
base private-key-format;
base ct:rsa-private-key-format;
description
"RSA private key in PKCS#1 format (RFC 8017).
Used for SSH host keys.";
}
identity ssh-public-key-format {
base public-key-format;
base ct:ssh-public-key-format;
description
"SSH public key format (RFC 4253, Section 6.6).
Used for SSH host keys.";
}
identity symmetric-key-format {
base ct:symmetric-key-format;
description
"Base for symmetric key format";
"Base for Infix symmetric key format extensions.";
}
identity wifi-preshared-key-format {
identity passphrase-key-format {
base ct:symmetric-key-format;
base symmetric-key-format;
description
"WiFi secret key";
"Human-readable passphrase, e.g., WiFi WPA2/WPA3 passwords.";
}
identity x25519-public-key-format {
@@ -48,7 +62,7 @@ module infix-crypto-types {
base ct:public-key-format;
description
"X25519 (Curve25519) public key format for Diffie-Hellman key exchange.
This is the format used by WireGuard.";
This format is used by network protocols such as WireGuard VPN.";
}
identity x25519-private-key-format {
@@ -56,15 +70,6 @@ module infix-crypto-types {
base ct:private-key-format;
description
"X25519 (Curve25519) private key format for Diffie-Hellman key exchange.
This is the format used by WireGuard.";
}
identity wireguard-symmetric-key-format {
base ct:symmetric-key-format;
base symmetric-key-format;
description
"WireGuard pre-shared key format.
32-byte base64-encoded key used as an optional additional layer
of symmetric encryption for post-quantum resistance.";
This format is used by network protocols such as WireGuard VPN.";
}
}
+5 -2
View File
@@ -10,6 +10,9 @@ submodule infix-if-wireguard {
import ietf-inet-types {
prefix inet;
}
import ietf-crypto-types {
prefix ct;
}
import infix-crypto-types {
prefix ixct;
}
@@ -75,8 +78,8 @@ submodule infix-if-wireguard {
This provides post-quantum resistance as an attacker would need
to break both the Curve25519 key exchange and this symmetric key.";
must "derived-from-or-self(deref(.)/../infix-ks:key-format, 'ixct:wireguard-symmetric-key-format')" {
error-message "Preshared key must be in wireguard-symmetric-key-format";
must "derived-from-or-self(deref(.)/../ks:key-format, 'ct:octet-string-key-format')" {
error-message "Preshared key must be in octet-string-key-format";
}
}
+1 -59
View File
@@ -5,15 +5,12 @@ module infix-keystore {
import ietf-keystore {
prefix ks;
}
import ietf-crypto-types {
prefix ct;
}
import infix-crypto-types {
prefix infix-ct;
}
revision 2025-12-17 {
description "Add WireGuard support";
description "Add WireGuard support, see infix-crypto-types.yang";
}
revision 2025-12-10 {
description "Adapt to changes in final version of ietf-keystore";
@@ -24,59 +21,4 @@ module infix-keystore {
revision 2025-02-04 {
description "Initial";
}
deviation "/ks:keystore/ks:asymmetric-keys/ks:asymmetric-key/ks:public-key-format" {
deviate replace {
type identityref {
base infix-ct:public-key-format;
}
}
}
deviation "/ks:keystore/ks:asymmetric-keys/ks:asymmetric-key/ks:private-key-format" {
deviate replace {
type identityref {
base infix-ct:private-key-format;
}
}
}
deviation "/ks:keystore/ks:symmetric-keys/ks:symmetric-key/ks:key-format" {
deviate not-supported;
}
augment "/ks:keystore/ks:symmetric-keys/ks:symmetric-key" {
leaf key-format {
type identityref {
base infix-ct:symmetric-key-format;
}
description
"Identifies the symmetric key's format
Valid symmetric key formats are:
wifi-preshared-key-format - WiFi preshared key
wireguard-symmetric-key-format - WireGuard preshared key";
}
}
deviation "/ks:keystore/ks:symmetric-keys/ks:symmetric-key/ks:key-type/ks:cleartext-symmetric-key" {
deviate not-supported;
}
augment "/ks:keystore/ks:symmetric-keys/ks:symmetric-key/ks:key-type" {
case cleartext-symmetric-key {
leaf symmetric-key {
type string;
must "../infix-ks:key-format != 'infix-ct:wifi-preshared-key-format' or " +
"(string-length(.) >= 8 and string-length(.) <= 63)" {
error-message "WiFi pre-shared key must be 8-63 characters long";
}
must "../infix-ks:key-format != 'infix-ct:wireguard-symmetric-key-format' or " +
"string-length(.) = 44" {
error-message "WireGuard pre-shared key must be 44 characters (32-byte base64-encoded)";
}
description
"Cleartext symmetric key value.
Format depends on key-format:
- WiFi pre-shared key: 8-63 printable ASCII characters
- WireGuard pre-shared key: 32-byte base64-encoded key (44 chars with padding)";
}
}
}
}
@@ -75,12 +75,12 @@ def configure_server(dut):
"symmetric-keys": {
"symmetric-key": [{
"name": "psk-client1",
"infix-keystore:symmetric-key": psk_client1,
"infix-keystore:key-format": "infix-crypto-types:wireguard-symmetric-key-format"
"cleartext-symmetric-key": psk_client1,
"key-format": "ietf-crypto-types:octet-string-key-format"
}, {
"name": "psk-client2",
"infix-keystore:symmetric-key": psk_client2,
"infix-keystore:key-format": "infix-crypto-types:wireguard-symmetric-key-format"
"cleartext-symmetric-key": psk_client2,
"key-format": "ietf-crypto-types:octet-string-key-format"
}]
}
}
@@ -226,8 +226,8 @@ def configure_client1(dut):
"symmetric-keys": {
"symmetric-key": [{
"name": "psk-server",
"infix-keystore:symmetric-key": psk_client1,
"infix-keystore:key-format": "infix-crypto-types:wireguard-symmetric-key-format"
"cleartext-symmetric-key": psk_client1,
"key-format": "ietf-crypto-types:octet-string-key-format"
}]
}
}
@@ -360,8 +360,8 @@ def configure_client2(dut):
"symmetric-keys": {
"symmetric-key": [{
"name": "psk-server",
"infix-keystore:symmetric-key": psk_client2,
"infix-keystore:key-format": "infix-crypto-types:wireguard-symmetric-key-format"
"cleartext-symmetric-key": psk_client2,
"key-format": "ietf-crypto-types:octet-string-key-format"
}]
}
}