TLSが難しい?RustとLinuxカーネルで実装しよう!

FUJITA Tomonori
nttlabs
Published in
Dec 29, 2022

TLS(Transport Layer Security)が難しすぎると、お嘆きのセキュリティファースト世代の皆様、RustでLinuxカーネルを実装しながら学んでみましょう!

カーネルモジュールの実装は難しい?それは誤解です。TLSをアプリケーションとして実装しようとすると、各種のライブラリを検索していたつもりが、SNSを眺めていて、一日が終わっていることありますよね。カーネルモジュールを実装するために使えるのはカーネルの機能だけです。検索する必要はなく、雑念が生じる余地はありません。その集中力があれば、カーネル開発は難しくありません。

TLSとLinuxカーネル

皆様の中には、LinuxカーネルはTLSをサポートしているのでは?と思っている方がいるかもしれません。TLSは実際のデータの送受信の前に、ハンドシェイクと呼ばれる、暗号鍵の合意や相手の認証を実施します。ハンドシェイク後、Linuxカーネルはデータの暗号・復号、送受信する機能を提供しますが、ハンドシェイクは、アプリケーションが実行する必要があります。

Linuxカーネル内には、TLSを必要とするが、ユーザ空間のアプリケーションとの連携が難しいソフトウェアコンポーネントがあり、それらソフトウェアのためのTLSの実装方法は議論中です。TLSのハンドシェイクは複雑で、バグによるセキュリティ問題のリスクが高いため、カーネルに入れるのは望ましくないという意見もあります。

今回は、バグが少ないコードを実装できそうな気がするので、Cではなく、Rustでカーネルモジュールを実装してみます。今月リリースされた最新のLinuxカーネルは、前回の記事で紹介したRustでカーネルを実装する機能をサポートしました。

Rustからカーネルの暗号機能を利用する

LinuxカーネルはRustをサポートしましたが、Rustから使えるCの関数やデータ構造体は限定的です。TLSが必要とする暗号機能も使えるようになっていないため、bindings_helper.hに必要な関数や構造体のヘッダファイルを追加して、カーネルを再コンパイルしましょう。

Linuxカーネルが多用するインライン関数も、Rustから利用できません。必要なインライン関数をラップするCの関数を定義して、この問題を解決します。

暗号機能が利用できるようになれば、TLSのメッセージを解釈し、適切な暗号機能を呼び、メッセージを組み立てる機能を実装するだけです。

QUICで試験

TLSの実装が終わったら、OpenSSLなどのライブラリと接続試験ができますが、インターネットで暗号化といえばTLS、基本技術すぎて、いまさら試験をしたところで、セキュリティファースト人材としてのアピールが弱いですよね。

今回は、TLSを使うQUICプロトコルを実装して、試験してみました。サーバ側のハンドシェイクを実行してQUICコネクションを確立する部分まで実装し、Rustのユーザ空間のQUIC実装であるQuinnとの接続に成功しました!

実装したRustカーネルモジュールのQUIC通信

実装したコードはこちらに置いておきます。

まとめ

ついに、LinuxカーネルがRustをサポートして、いろいろな機能がRustで実装できるようになりました。「LinuxカーネルをRustで置き換える!」という見果てぬ夢を見るみなさま、NTTでは仲間を募集中です。

--

--

FUJITA Tomonori
nttlabs

Janitor at the 34th floor of NTT Tamachi office, had worked on Linux kernel, founded GoBGP, TGT, Ryu, RustyBGP, etc. https://twitter.com/brewaddict