LoginSignup
1
1

More than 1 year has passed since last update.

セキュアエレメントによるWireGuard保護

Last updated at Posted at 2023-02-05

きっかけ

WireGuardを軽量なVPNとして利用している。
センサー、カメラなどの多数の処理ができ、比較的能力が高いLinux搭載デバイスを、安全に配置するにはどうしたらいいか考えてみた。

WireGuardとは

公式サイトではWireGuard は、最先端の暗号化を利用する、非常にシンプルでありながら高速で最新の VPN と紹介されている。
概要としては以下の通りとなる。

  • 鍵共有:Curve 25519
  • 鍵導出: HKDF
  • 認証暗号:Chacha20-Poly1305
  • ハッシュ:BLAKE2s

WireGuardの構造

Raspberry Pi OS bullseyeでWireGuradの構成を確認したところ、下記のようになるようだ。

image.png

OSに組み込まれたカーネルモジュールが本体となり、設定はユーザー空間のwireguard-toolsがnetlinkインターフェースを介して行う。

設定ファイルを/etc/wireguard/wg0.confとし、

$ sudo wg-quick up /etc/wireguard/wg0.conf

とすることでwg0ネットワークデバイスが作成され、wireguardモジュールが起動する。

WireGuardの接続プロトコル

公式サイトの記載に、Noise Protocol Frameworkの記載がある。
image.png

Noise Protocol Frameworkについて公式Webサイトをもとに概要を調べた。
2つの鍵ペアを使い、DH(Diffie-Hellman)計算を行いながらハンドシェイク通信を行い接続を確立する。

image.png

課題

下記はwg0.conf設定ファイルの例となるが、秘密鍵が直接記載されている形式となる。
これを保護できないかと考えた。

[Interface]
PrivateKey = FA2qtPQO3XsjOSR06Sx9Eg/rR8pw2B5cSgdOXKpa8Gs=
Address = 10.0.0.112/32

[Peer]
PublicKey = ty5vAu...KfMBw=
Endpoint = XXX.XXX.XXX.XXX:XXXXX
AllowedIPs = 10.0.0.0/24
PersistentKeepalive = 25

セキュアエレメントについて

セキュアエレメントの機能の主要なものとして、秘密鍵を隠して、なりすましを防ぐという機能がある。

image.png

具体的には、

  • 秘密鍵を読みだすコマンドがなく、公開鍵を読めるコマンドのみある。
  • セキュアエレメント内の秘密鍵に値(ハッシュ)を与えて署名、DH計算など行い結果を返すコマンドがある。

今回この機能をWireGuardに組み込んで、秘密鍵を守れるか実装してみた。

WireGuardが利用するCurve25519に対応する、NXP社SE050(C)を利用して実装していく。

環境準備

Raspberry Pi 3b+ bullseye 環境を用意
NXP SE050 C1をI2C接続。(市販品ではMIKROE Plug&Trust clickが利用可能)
image.png

$ sudo raspi-configでI2Cを有効
$ i2cdetect –y 1 コマンドで0x48認識を確認
image.png

実装方針

WireGuardの静的秘密鍵とのDH計算を行うステップをターゲットとする。

image.png

実装のポイント

1,Linuxユーザー空間のwireguard-toolsの変更

wg genkeyコマンド
出力される秘密鍵を隠すため、SE050の内部の鍵の保管番号であるオブジェクトIDを
代わりに出力する。この値自体は漏れても問題ない

wg pubkeyコマンド
上記オブジェクトIDを引数として、SE050から公開鍵を出力する。 

2,Linuxカーネルモジュールのwireguard本体

noise.c
ハンドシェイクを行うコード内で、wg->static_identity.static_private 構造体の中身をSE050の内部の鍵の保管番号であるオブジェクトIDに変更し、ECDH計算のためこれを呼び出す関数をSE050のAPIに置き換える。
NXPのPlug&Trustミドルウェアはユーザー空間用なため、カーネルモジュール用にHAL(Hardware Abstraction Layer)の作成が必要。
ミドルウェアコードもカーネル空間用にリライトが必要。

実装後

1,Linuxユーザー空間のwireguard-toolsの変更

NXP SE050の内部鍵のオブジェクトIDである0x10000009をBase64にした数値になり、秘密鍵を隠せた。
出力される公開鍵は相手側で従来通り登録し、準備する。

$ wg genkey 0x10000009
CQAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=


$ wg genkey 0x10000009 | wg pubkey
Yh3rhVp7LfvPC4YWjB7L8mJO2hk2VXMh9sZ9B6tLm2c=

2,Linuxカーネルモジュールのwireguard本体

NXP SE050の内部鍵のオブジェクトIDである0x10000009をBase64にした数値を鍵の値として渡し、SE050の関数でDH計算を行う。

$ sudo cat /etc/wireguard/wg0.conf
[Interface]
PrivateKey = CQAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
Address = 10.0.0.110/32

[Peer]
PublicKey = XXXXX=
Endpoint = XXX.XXX.XXX.XXX:XXXXX
AllowedIPs = 10.0.0.0/24
PersistentKeepalive = 25

ネットワークパフォーマンス

セキュアエレメントの追加がネットワークパフォーマンスに影響があるか確認した。

iperf3 5回実行平均

標準のwireguard
39.28Mbit/sec

セキュアエレメント対応wireguard
39.38Mbit/sec

となり、有意な差はなさそうなことが分かった。

キーローテーションを試す

クライアント側で新しいキー番号で秘密鍵 、公開鍵を作成する。

$ wg genkey 0x10000006
BgAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
$ wg genkey 0x10000006 | wg pubkey
9oGFAiGUSMIzg2gzwwEBasjfKxkULebTwzOEjn7K4Rk=

サーバー側でIPはそのまま、新しい公開鍵を登録。

$ sudo wg set wg0 peer "9oGFAiGUSMIzg2gzwwEBasjfKxkULebTwzOEjn7K4Rk=" allowed-ips 10.0.0.111/32

実行直後に接続が切れる。
続けて下記を実行して古い公開鍵を消す。

$ sudo wg set wg0 peer "ChgKBqwSnkov+rcC2KKUQKMgPH9pfrnWXzLpMzfKpg4=" remove

クライアント側に戻り、wg0.confの秘密鍵の番号を変更する。

$ sudo wg-quick down /etc/wireguard/wg0.conf
$ sudo vi /etc/wireguard/wg0.conf

[Interface]
PrivateKey = BgAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
Address = 10.0.0.111/32
 
[Peer]
PublicKey = XXXX=
Endpoint = XXX.XXX.XXX.XXX:XXXXX
AllowedIPs = 10.0.0.0/24
PersistentKeepalive = 25

$ sudo wg-quick up /etc/wireguard/wg0.conf

これで鍵が変わった状態で再度リンクアップする。

まとめ

クラウド接続が増加してくるIoTデバイスでのWireguardセキュアエレメントの実装は

  • IoTデバイスのメンテナンスネットワーク
  • 既存のMQTTなどのプロトコル保護
    など、ネットワーク、扱うデータ、デバイスをより信頼できるようになるため、活用の幅が広まるのではないかと思う。

関連コードは下記に配置した。
wireguard-se(github)
wireguard-tools-se(github)

参考資料

作って理解するWireGuard
https://speakerdeck.com/fadis/zuo-tuteli-jie-suruwireguard

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1