Is DER format supported in 802-1x.private-key?
Hello there!
Background: We are developing a project that, for managing the network, interfaces with NetworkManager over DBus. In our company we also develop our own OS (Yocto-based) in addition to targeting standard Debian-like distros (Raspberry Pi OS, Ubuntu...). We recently added the possibility to connect to a WPA2 Enterprise Access Point in our project levereging NetworkManager but we're observing a diverging behaviour between our Yocto-based and Debian distros.
Minimal Reproducible Example
Here's the Python code that triggers the behaviour. You can find a complete example here which also provides the keys we used for testing.
import dbus, uuid
PRIVATE_KEY = open("./test_key.der", "rb").read()
CLIENT_CERT = open("./toshiba.der", "rb").read()
s_con = dbus.Dictionary(
{"type": "802-11-wireless", "uuid": str(uuid.uuid4()), "id": "WPAEnterpriseTest"}
)
s_wifi = dbus.Dictionary(
{
"ssid": dbus.ByteArray("homewifi".encode("utf-8")),
"security": "802-11-wireless-security",
}
)
s_wsec = dbus.Dictionary({"key-mgmt": "wpa-eap"})
s_8021x = dbus.Dictionary(
{
"eap": ["tls"],
"identity": "John Smith",
"client-cert": dbus.ByteArray(CLIENT_CERT),
"private-key": dbus.ByteArray(PRIVATE_KEY),
"private-key-password-flags": 4,
}
)
s_ip4 = dbus.Dictionary({"method": "auto"})
s_ip6 = dbus.Dictionary({"method": "ignore"})
con = dbus.Dictionary(
{
"connection": s_con,
"802-11-wireless": s_wifi,
"802-11-wireless-security": s_wsec,
"802-1x": s_8021x,
"ipv4": s_ip4,
"ipv6": s_ip6,
}
)
print("Creating connection:", s_con["id"], "-", s_con["uuid"])
bus = dbus.SystemBus()
proxy = bus.get_object(
"org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager/Settings"
)
settings = dbus.Interface(proxy, "org.freedesktop.NetworkManager.Settings")
settings.AddConnection(con)
In summary: we're using the blob scheme for passing a DER format unencrypted private key.
Testing results
On Debian distros running this code will result in:
Creating connection: WPAEnterpriseTest - a5fea7a1-e358-4473-8bce-15da07312bd3
and we can successfully connect to the WPA Enterprise Access Point.
On our Yocto-based distros we get:
Creating connection: WPAEnterpriseTest - cf19cc7b-4b3d-46b3-8c48-54fb662db0d3
Traceback (most recent call last):
File "main.py", line 59, in <module>
settings.AddConnection(con)
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 72, in __call__
return self._proxy_method(*args, **keywords)
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 141, in __call__
return self._connection.call_blocking(self._named_service,
File "/usr/lib/python3/dist-packages/dbus/connection.py", line 652, in call_blocking
reply_message = self.send_message_with_reply_and_block(
dbus.exceptions.DBusException: org.freedesktop.NetworkManager.Settings.Connection.InvalidProperty: 802-1x.client-cert: has to match 'private-key' property for PKCS#12
Which is kinda weird since the key is supposed to be in PKCS#8 format.
This behaviour seems to be independent on the NetworkManager version. Here's a summary of our tests:
- RPi OS (Bullseye) NM 1.30.4 -> no issue
- RPi OS (Bookworm) -> NM 1.42 -> no issue
- RPi OS (Ubuntu Server 22.04) -> NM 1.30 -> no issue
- Yocto-based (v3.3) OS ARM64 -> NM 1.30.6 -> issue
- Yocto-based (v4.0) OS ARM64 -> NM 1.36.2 -> issue
- Yocto-based (v2.7) OS x86-64 → NM 1.18.4 → issue
Final question
I don't think I can share more info on our Yocto-based setup but for now I'd like to focus on the following question: Is the DER format supported for the 802-1x.private-key
parameter?
When, instead of passing the key in the DER format I pass the PEM one, the Yocto-based setup starts working.
Python code for PEM
import dbus, uuid
PRIVATE_KEY = """
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAxVl2MUdc3586Xjte+9UqLIAkYc8gDaqsR+tNIi2oycMPqNUH
ikeZ9PCDSgQTUUVumwiaTzQOVzS5fbnJ7vwZdgiGfzXgMhR7WrvvJGK5E+cKf4Nh
QiiD6jQDlIpNje6xDwehT5tBU1o5QVM9qkSEO0s3am8OmV4CtmZ9eTD2/gi47ptm
4qr9WD8WhZ6z4RztgD1UrvsWBAfdG8hYBlhHy/KmPgQMnFZjcT86uAty0XScLwlL
7DIXJzYaTdGR4NLowBRHkC2V5t0l2RrwEGreSAGSx8SEG1EniY7dR9slsJMazaEj
KcDhsgIlE4jwCsKX09mm9XCWVyC1hdfkJjQt7QIDAQABAoIBAAQk+whzKg4lPcvS
gDZdRyH8HNT1pOjkkMpJ3SrS5jr3VMfpHFU3aCaC6X0+pe3WsC5f149yC3jy1z90
k+o40VWKZfpfaKT4ztPZFeX3gkO5DT/qL5J82M5AvxIUrKBGwFqhm4xE9hpZfjAC
LHYW1QIuZoQNzW+HGjYByMsbEzFx4nZfwcGsZC8r+EVjoj8UDwNVxQkxl/W9ynCA
7XvIUbxLiu5g+lelSjJtAK8SYCV7TkP3YR+CYa2v0R92NzY7M4D9jltfM+9f2Hrn
dfMpDTYM619hJFwGF7pX2vTuGH4v5N07bT90MSLW0Q/lXrWQr0I94x2htS8t3SUR
oQtsWjkCgYEA/ke4PBR8Y4oaSbd20mTQpX7UZd22P+I0VezAVzQu1wPc498zaeUe
iQlfTwCOQsmNZYTqvqR3w4ILn3EGZUguoeJ+m9K4/m9r8WzQcvHn0FA7YEMO0H7p
zxmLPjhz6TSuyRmFHs2yMND1e2ocYg+p3Bug4m5zSJxHsgQuQCfNNy8CgYEAxq8q
9cDhNeUP5R/lzz3/nHJQwv7yqadxZuG7c0lqzskFofssShneXZnkZNIdnA6fdozg
BzYy1QNHo73EFCMHsPg2EZ1yXv2A7zooxVlviw0XZv6D3KrY863xXdUTkEUnhAdE
fwReJtRA3C5YoLNzd6VogRFrPx2HSbiEYStj5aMCgYA4eADoBryg9lhkKoQOsSjM
t9+/R39jrH5m3o7QTtxgD5GMYVLvn1wqnpQ13S+6kTv/YYcoEyotlsGyBM2gzGje
tofbXu6KQoA8OygHfsU2M7sb44h0sNqHjWqoxKypC3QNYMd5UcDSqnT5lVT8SfI0
2UXfQxwC8gHR/K+wu6YNLQKBgQCSHNf3CvWUcPQTiDW1Bt8n6lnCTUOfyGf5RSBZ
VDCcCfF+gfy8MfH52+a+zlbAIXDb+hX2t8ECLftNS40bUfeiCaeZpLQrbzqWs6qw
F2mUVPhU4e+PJIWQDudmHgDZJEI/MikJT+j9nTJluh+rbs0HvDjyUiEQtWJ8sJmJ
7CL3CQKBgBy6IpPPvXo+M3BZztsU73unLxMpv7CEp5RORiwtrGKJhunMQ5zKuA1i
97VQWwZzgpGp8vqdKFroUhrG5xFlQx7wN1qN7rmOzXS94kz4SB22ftAJIIx0/fS2
GR6+JYUyT/F1OlCk9eWgycpY70Rblq3Byq0NfFUoiMDkKEM2wFQH
-----END RSA PRIVATE KEY-----
"""
CLIENT_CERT = open("./toshiba.der", "rb").read()
s_con = dbus.Dictionary(
{"type": "802-11-wireless", "uuid": str(uuid.uuid4()), "id": "WPAEnterpriseTest"}
)
s_wifi = dbus.Dictionary(
{
"ssid": dbus.ByteArray("homewifi".encode("utf-8")),
"security": "802-11-wireless-security",
}
)
s_wsec = dbus.Dictionary({"key-mgmt": "wpa-eap"})
s_8021x = dbus.Dictionary(
{
"eap": ["tls"],
"identity": "John Smith",
"client-cert": dbus.ByteArray(CLIENT_CERT),
"private-key": dbus.ByteArray(PRIVATE_KEY.encode("utf-8")),
"private-key-password-flags": 4,
}
)
s_ip4 = dbus.Dictionary({"method": "auto"})
s_ip6 = dbus.Dictionary({"method": "ignore"})
con = dbus.Dictionary(
{
"connection": s_con,
"802-11-wireless": s_wifi,
"802-11-wireless-security": s_wsec,
"802-1x": s_8021x,
"ipv4": s_ip4,
"ipv6": s_ip6,
}
)
print("Creating connection:", s_con["id"], "-", s_con["uuid"])
bus = dbus.SystemBus()
proxy = bus.get_object(
"org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager/Settings"
)
settings = dbus.Interface(proxy, "org.freedesktop.NetworkManager.Settings")
settings.AddConnection(con)
On Debian, if I look inside /etc/NetworkManager/system-connections
I find that the private-key
is saved in a file with the .pem
extensions even though the content is in DER format.
In your documentation I only find this sentence about the expected format:
When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data.
But on Raspberry Pi it works with the DER keys! (i.e. I can connect to the WPA Enterprise endpoint)
P.S. Don't worry about the keys beings shared here: they were generated with the sole purpose of testing and debugging.