Zephyrのセキュア通信を試す
Zephyrとは
開発環境
システム構成要素
|
詳細
|
ホストOS
|
Ubuntu 23.10
|
ターゲットOS
|
Zephyr v4.1.0-4540-gf77e258cb9c2
|
ターゲットボード
|
ZYNQ-7000 EPP ZC702 Evalution Kit REV 1.1
|
Zephyrのビルド
- https://docs.zephyrproject.org/latest/develop/getting_started/index.html
- https://docs.zephyrproject.org/latest/hardware/porting/board_porting.html
ホストOSのアップデート
$ sudo apt update -y
$ sudo apt upgrade -y
依存関係のインストール
$ sudo apt install --no-install-recommends -y git cmake ninja-build gperf \
ccache dfu-util device-tree-compiler wget \
python3-dev python3-pip python3-setuptools python3-tk python3-wheel xz-utils file \
make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1
$ cmake --version
$ python3 --version
$ dtc --version
Zephyrの入手とPython依存関係のインストール
$ cd ~
$ mkdir zephyrproject
$ cd zephyrproject
$ sudo apt install python3-venv
$ python3 -m venv ~/zephyrproject/.venv
$ source ~/zephyrproject/.venv/bin/activate
$ pip install west
$ west init ~/zephyrproject
$ west update
$ west zephyr-export
$ west packages pip --install
Zephyr SDKのインストール
$ cd ~/zephyrproject/zephyr
$ west sdk install
ボードディレクトリの作成
$ mkdir -p boards/xilinx
$ cp -r boards/digilent/zybo boards/xilinx/zc702
$ cd boards/xilinx/zc702
$ mv Kconfig.zybo Kconfig.zc702
$ mv zybo.dts zc702.dts
$ mv zybo.yaml zc702.yaml
$ mv zybo_defconfig zc702_defconfig
$ mv zybo-pinctrl.dtsi zc702-pinctrl.dtsi
$ find . -type f -exec sed -i 's/digilent/xilinx/g' {} +
$ find . -type f -exec sed -i 's/Digilent/Xilinx/g' {} +
$ find . -type f -exec sed -i 's/DIGILENT/XILINX/g' {} +
$ find . -type f -exec sed -i 's/zybo/zc702/g' {} +
$ find . -type f -exec sed -i 's/Zybo/ZC702/g' {} +
$ find . -type f -exec sed -i 's/ZYBO/ZC702/g' {} +
DTSの変更
変更前 :
leds {
compatible = "gpio-leds";
ld_mio: led_mio {
gpios = <&psgpio_bank0 7 GPIO_ACTIVE_HIGH>;
label = "LD_MIO";
};
};
&uart1 {
status = "okay";
current-speed = <115200>;
clock-frequency = <100000000>;
pinctrl-0 = <&pinctrl_uart1_default>;
pinctrl-names = "default";
};
leds {
compatible = "gpio-leds";
ld_mio: led_mio {
gpios = <&psgpio_bank0 10 GPIO_ACTIVE_HIGH>; /* <- ここを変えた */
label = "LD_MIO";
};
};
&uart1 {
status = "okay";
current-speed = <115200>;
clock-frequency = <50000000>; /* <- ここを変えた */
pinctrl-0 = <&pinctrl_uart1_default>;
pinctrl-names = "default";
};
サンプルのビルド
$ cd ~/zephyrproject/zephyr
$ west build -p always -b zc702 samples/hello_world
$ ls ~/zephyrproject/zephyr/build/zephyr/
U-Bootの準備
$ cd ~
$ wget https://xilinx-wiki.atlassian.net/wiki/download/attachments/18841732/zynq-ubuntu-core-12.10-core-armhf-boot.tar.xz
$ tar Jxfv zynq-ubuntu-core-12.10-core-armhf-boot.tar.xz
$ ls boot
SDカードの準備
boot.bin
zephyr.bin
Zephyrの起動
zynq-uboot> fatload mmc 0 0x0 zephyr.bin
zynq-uboot> go 0x0
*** Booting Zephyr OS build v4.1.0-5075-gcf6170cbe605 ***
Hello World! zc702/xc7z010
Ethernet
GEMのドライバ (eth_xlnx_gem.c)
(1) eth_xlnx_gem_configure_clocks() の分周比計算処理を変更します。
div0 = 8;
div1 = 5;
(2) eth_xlnx_gem_configure_clocks() のレジスタ書込の処理を変更します。
// CLK_CTRL READ
{
mem_addr_t phys_addr = 0xF8000140;
mem_addr_t addr = 0;
device_map((mm_reg_t *)&addr, phys_addr, 0x100, K_MEM_CACHE_NONE);
clk_ctrl_reg = sys_read32(addr);
}
clk_ctrl_reg &= ~((ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR_MASK <<
ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR0_SHIFT) |
(ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR_MASK <<
ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR1_SHIFT));
clk_ctrl_reg |= ((div0 & ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR_MASK) <<
ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR0_SHIFT) |
((div1 & ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR_MASK) <<
ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR1_SHIFT);
// SLCR UNLOCK
{
mem_addr_t phys_addr = 0xF8000008;
mem_addr_t addr = 0;
device_map((mm_reg_t *)&addr, phys_addr, 0x100, K_MEM_CACHE_NONE);
sys_write32(0xDF0D, addr);
}
// CLK_CTRL WRITE
{
mem_addr_t phys_addr = 0xF8000140;
mem_addr_t addr = 0;
device_map((mm_reg_t *)&addr, phys_addr, 0x100, K_MEM_CACHE_NONE);
sys_write32(clk_ctrl_reg, addr);
}
// SLCR LOCK
{
mem_addr_t phys_addr = 0xF8000004;
mem_addr_t addr = 0;
device_map((mm_reg_t *)&addr, phys_addr, 0x100, K_MEM_CACHE_NONE);
sys_write32(0x767B, addr);
}
PHYのドライバ (phy_xlnx_gem.c)
(1) phy_xlnx_gem_supported_devs配列に88E1116Rの要素を追加します。
{
.phy_id = 0x01410e40,
.phy_id_mask = PHY_MRVL_PHY_ID_MODEL_MASK,
.api = &phy_xlnx_gem_marvell_alaska_api,
.identifier = "Marvell Alaska 88E1116R"
},
// Change to page 2: Configure RGMII TX/RX delay
phy_xlnx_gem_mdio_write(dev_conf->base_addr, dev_data->phy_addr, PHY_MRVL_COPPER_PAGE_SWITCH_REGISTER, 0x0002);
phy_xlnx_gem_mdio_write(dev_conf->base_addr, dev_data->phy_addr,0x15, 0x1070);
// Change to page 3: Configure LED control (optional)
phy_xlnx_gem_mdio_write(dev_conf->base_addr, dev_data->phy_addr, PHY_MRVL_COPPER_PAGE_SWITCH_REGISTER, 0x0003);
phy_xlnx_gem_mdio_write(dev_conf->base_addr, dev_data->phy_addr,0x10, 0x021e);
// Return to default page 0
phy_xlnx_gem_mdio_write(dev_conf->base_addr, dev_data->phy_addr, PHY_MRVL_COPPER_PAGE_SWITCH_REGISTER, 0x0000);
DTS
&gem0 {
status = "okay";
clock-frequency = <100000000>;
mdc-divider = <XLNX_GEM_MDC_DIVIDER_32>;
local-mac-address = [da 13 7a 1f 39 ac];
init-mdio-phy;
/delete-property/ discard-rx-fcs;
/delete-property/ unicast-hash;
/delete-property/ full-duplex;
// amba-ahb-burst-length = <XLNX_GEM_AMBA_AHB_BURST_INCR4>;
};
カーネルコンフィグ
CONFIG_ETH_DRIVER=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NETWORKING=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_IPV4=y
CONFIG_NET_IPV6=n
CONFIG_NET_ARP=y
CONFIG_NET_TCP=y
CONFIG_NET_UDP=y
CONFIG_NET_DHCPV4=y
CONFIG_NET_DHCPV4_OPTION_CALLBACKS=y
CONFIG_DNS_RESOLVER=y
CONFIG_LOG=y
CONFIG_NET_LOG=y
CONFIG_SHELL=y
CONFIG_NET_SHELL=y
リンクアップ
[00:00:03.012,000] <inf> eth_xlnx_gem: ethernet@e000b000 link up, 100 MBit/s
ICMP
$ net ipv4 gateway 1 192.168.13.1
$ net ipv4 add 1 192.168.13.47 255.255.255.0
$ net ping 192.168.13.1
PING 192.168.13.1
28 bytes from 192.168.13.1 to 192.168.13.47: icmp_seq=1 ttl=64 time=0 ms
28 bytes from 192.168.13.1 to 192.168.13.47: icmp_seq=2 ttl=64 time=0 ms
28 bytes from 192.168.13.1 to 192.168.13.47: icmp_seq=3 ttl=64 time=0 ms
DHCP
$ net ipv4 del 1 192.168.13.47
$ net dhcpv4 client start 1
$ net iface
[00:00:45.867,000] <wrn> net_dhcpv4: DHCP server provided more DNS servers than can be saved
[00:00:45.867,000] <wrn> net_dhcpv4: DHCP server provided more DNS servers than can be saved
[00:00:45.867,000] <inf> net_dhcpv4: Received: 192.168.13.215
Default interface: 1
Interface eth0 (0x39560) (Ethernet) [1]
===================================
Link addr : DA:13:7A:1F:39:AC
MTU : 1500
Flags : AUTO_START,IPv4
Device : ethernet@e000b000 (0x310d4)
Status : oper=UP, admin=UP, carrier=ON
Ethernet capabilities supported:
100 Mbits
Promiscuous mode
Ethernet PHY device: <none> (0)
IPv4 unicast addresses (max 1):
192.168.13.215/255.255.255.0 DHCP preferred
IPv4 multicast addresses (max 2):
224.0.0.1
IPv4 gateway : 192.168.13.1
DHCPv4 lease time : 172800
DHCPv4 renew time : 86400
DHCPv4 server : 192.168.13.1
DHCPv4 requested : 192.168.13.215
DHCPv4 state : bound
DHCPv4 attempts : 1
DHCPv4 state : bound
TLS
カーネルコンフィグ
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_POSIX_API=y
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_NEED_IPV4=y
CONFIG_NET_CONFIG_NEED_IPV6=n
CONFIG_NET_CONFIG_MY_IPV4_GW="192.168.13.1"
CONFIG_NET_SOCKETS_SOCKOPT_TLS=y
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED=y
CONFIG_MBEDTLS=y
CONFIG_MBEDTLS_BUILTIN=y
CONFIG_MBEDTLS_ENABLE_HEAP=y
CONFIG_MBEDTLS_HEAP_SIZE=60000
CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=2048
アプリケーションソースコード
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/net/socket.h>
#include <zephyr/net/tls_credentials.h>
LOG_MODULE_REGISTER(simple_tls, LOG_LEVEL_DBG);
int main(void)
{
int ok = 0;
int socket_ = -1;
// ソケットを作成する
{
socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
if (socket_ < 0)
{
LOG_ERR("ERROR : socket : %d\n", errno);
goto EXIT;
}
// 自己署名証明書のサーバーに接続する
int verify = TLS_PEER_VERIFY_NONE;
if (setsockopt(socket_, SOL_TLS, TLS_PEER_VERIFY, &verify, sizeof(verify)) < 0)
{
LOG_ERR("ERROR : setsockopt TLS_PEER_VERIFY : %d\n", errno);
goto EXIT;
}
}
// 接続する
{
struct sockaddr_in server = { 0 };
server.sin_family = AF_INET;
server.sin_port = htons(12345);
inet_pton(AF_INET, "192.168.13.48", &server.sin_addr);
if (connect(socket_, (struct sockaddr *)&server, sizeof(server)) < 0)
{
LOG_ERR("ERROR : connect : %d\n", errno);
goto EXIT;
}
}
// 送信する
{
char const * const message = "Hello from client";
if (send(socket_, message, strlen(message) + 1, 0) < 0)
{
LOG_ERR("ERROR : send : %d\n", errno);
goto EXIT;
}
}
// 受信する
while (1)
{
char message[128] = { 0 };
int const return_value = recv(socket_, message, sizeof(message) - 1, 0);
if (return_value < 0)
{
LOG_ERR("ERROR : recv : %d\n", errno);
goto EXIT;
}
if (return_value == 0)
{
break;
}
else
{
LOG_INF("%s", message);
continue;
}
}
ok = 1;
EXIT:
// ソケットをクローズする
if (socket_ != -1)
{
if (close(socket_) < 0)
{
LOG_ERR("ERROR : close : %d\n", errno);
goto EXIT;
}
}
LOG_INF("%s\n", ok ? "OK" : "NG");
return 0;
}
実行
*** Booting Zephyr OS build v4.1.0-5075-gcf6170cbe605 ***
[00:00:00.011,000] <wrn> net_sock_tls: No entropy device on the system, TLS communication is insecure!
[00:00:00.011,000] <inf> net_config: Initializing network
[00:00:00.011,000] <inf> net_config: Waiting interface 1 (0x51930) to be up...
[00:00:03.012,000] <inf> eth_xlnx_gem: ethernet@e000b000 link up, 100 MBit/s
[00:00:03.012,000] <inf> net_config: Interface 1 (0x51930) coming up
[00:00:03.012,000] <inf> net_config: Running dhcpv4 client...
[00:00:05.013,000] <wrn> net_dhcpv4: DHCP server provided more DNS servers than can be saved
[00:00:05.014,000] <wrn> net_dhcpv4: DHCP server provided more DNS servers than can be saved
[00:00:05.014,000] <inf> net_dhcpv4: Received: 192.168.13.215
[00:00:05.014,000] <inf> net_config: IPv4 address: 192.168.13.215
[00:00:05.014,000] <inf> net_config: Lease time: 172800 seconds
[00:00:05.014,000] <inf> net_config: Subnet: 255.255.255.0
[00:00:05.014,000] <inf> net_config: Router: 192.168.13.1
[00:00:05.072,000] <inf> simple_tls: Hello from server
[00:00:05.072,000] <inf> simple_tls: OK