mirror of
https://github.com/esphome/esphome.git
synced 2026-10-19 04:32:50 +00:00
[wifi] Hand the DPP bootstrapping key to the supplicant DER encoded
This commit is contained in:
@@ -259,6 +259,22 @@ WiFiConfigureAction = wifi_ns.class_(
|
||||
)
|
||||
|
||||
|
||||
# The supplicant parses the bootstrapping key as a DER encoded P-256 private key in hex; these wrap the
|
||||
# 32 byte key the way the ESP-IDF enrollee example does
|
||||
DPP_KEY_DER_PREFIX = "30310201010420"
|
||||
DPP_KEY_DER_SUFFIX = "a00a06082a8648ce3d030107"
|
||||
|
||||
|
||||
def _validate_dpp_private_key(value: object) -> str:
|
||||
"""The key is 32 bytes written as 64 hexadecimal characters."""
|
||||
value = cv.string_strict(value)
|
||||
if len(value) != 64 or any(c not in "0123456789abcdefABCDEF" for c in value):
|
||||
raise cv.Invalid(
|
||||
"private_key must be 32 bytes written as 64 hexadecimal characters"
|
||||
)
|
||||
return value.lower()
|
||||
|
||||
|
||||
def _validate_dpp_device_info(value: object) -> str:
|
||||
"""The supplicant puts the text on a space separated command line and reads it up to the next space."""
|
||||
value = cv.string_strict(value)
|
||||
@@ -336,7 +352,7 @@ EAP_AUTH_SCHEMA = cv.All(
|
||||
# Wi-Fi Easy Connect (DPP) enrollee; the ESP-IDF supplicant supports the QR code method
|
||||
DPP_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_PRIVATE_KEY): cv.sensitive(cv.string_strict),
|
||||
cv.Optional(CONF_PRIVATE_KEY): cv.sensitive(_validate_dpp_private_key),
|
||||
cv.Optional(CONF_DEVICE_INFO): _validate_dpp_device_info,
|
||||
cv.Optional(CONF_CHANNELS, default=[6]): cv.ensure_list(
|
||||
cv.int_range(min=1, max=14)
|
||||
@@ -853,7 +869,7 @@ async def to_code(config):
|
||||
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_DPP_SUPPORT", True)
|
||||
add_idf_sdkconfig_option("CONFIG_ESP_HOSTED_ENABLE_DPP", True)
|
||||
if (key := dpp.get(CONF_PRIVATE_KEY)) is not None:
|
||||
cg.add(var.set_dpp_key(key))
|
||||
cg.add(var.set_dpp_key(f"{DPP_KEY_DER_PREFIX}{key}{DPP_KEY_DER_SUFFIX}"))
|
||||
if (info := dpp.get(CONF_DEVICE_INFO)) is not None:
|
||||
cg.add(var.set_dpp_device_info(info))
|
||||
cg.add(var.set_dpp_channels(",".join(str(c) for c in dpp[CONF_CHANNELS])))
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
esp32:
|
||||
board: esp32dev
|
||||
framework:
|
||||
type: esp-idf
|
||||
|
||||
wifi:
|
||||
dpp:
|
||||
private_key: 00112233445566778899AABBCCDDEEFF00112233445566778899aabbccddeeff
|
||||
@@ -0,0 +1,42 @@
|
||||
"""The DPP bootstrapping key is given as 32 raw bytes in hex and handed to the supplicant DER encoded."""
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome.components import wifi
|
||||
import esphome.config_validation as cv
|
||||
|
||||
RAW_KEY = "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"value",
|
||||
[
|
||||
RAW_KEY[:-2],
|
||||
RAW_KEY + "00",
|
||||
"zz" + RAW_KEY[2:],
|
||||
wifi.DPP_KEY_DER_PREFIX + RAW_KEY + wifi.DPP_KEY_DER_SUFFIX,
|
||||
],
|
||||
)
|
||||
def test_key_must_be_64_hex_digits(value: str) -> None:
|
||||
with pytest.raises(cv.Invalid, match="64 hexadecimal characters"):
|
||||
wifi._validate_dpp_private_key(value)
|
||||
|
||||
|
||||
def test_key_is_lower_cased() -> None:
|
||||
assert wifi._validate_dpp_private_key(RAW_KEY.upper()) == RAW_KEY
|
||||
|
||||
|
||||
def test_generated_key_is_der_encoded(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
component_config_path: Callable[[str], Path],
|
||||
) -> None:
|
||||
"""The ESP-IDF supplicant expects the P-256 DER header around the raw key."""
|
||||
main_cpp = generate_main(component_config_path("dpp_key.yaml"))
|
||||
|
||||
assert (
|
||||
f'set_dpp_key("{wifi.DPP_KEY_DER_PREFIX}{RAW_KEY}{wifi.DPP_KEY_DER_SUFFIX}")'
|
||||
in main_cpp
|
||||
)
|
||||
@@ -2,6 +2,7 @@ wifi:
|
||||
dpp:
|
||||
channels: [1, 6, 11]
|
||||
device_info: ESPHome
|
||||
private_key: 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff
|
||||
timeout: 30s
|
||||
on_dpp_uri:
|
||||
- logger.log:
|
||||
|
||||
Reference in New Issue
Block a user