設定 - MOK
概要
MOK (Machine Owner Key) は、Linuxシステムにおけるセキュアブートの拡張機能として重要な役割を持つ。
セキュアブートは、元々、UEFIファームウェアがブートローダの署名を検証して、信頼できるソフトウェアのみが起動できるようにする仕組みであった。
しかし、この仕組みではユーザが自身のカーネルモジュールを署名して使用することが困難であった。
そこで登場したのがMOKである。
MOKは、ユーザや組織が独自の暗号鍵を使用してカーネルモジュールに署名して、それをシステムに登録できるようにする仕組みである。
これにより、Microsoft等の大手ベンダーの鍵に依存せずに、自作やサードパーティ製のカーネルモジュールを安全に使用できるようになった。
MOKの仕組みは、以下に示す手順で機能する。
- まず、ユーザは自身の公開鍵と秘密鍵のペアを生成する。
- 秘密鍵を使用してカーネルモジュールに署名して、公開鍵をシステムのMOKリストに登録する。
- システムの起動時にて、shim (特殊なブートローダ) がMOKリストを参照して、登録された公開鍵を使用してカーネルモジュールの署名を検証する。
MOKの管理には、主にmokutilというツールを使用して、新しい鍵の登録、既存の鍵の削除、現在のMOKリストの表示等を行うことができる。
ただし、セキュリティ上の理由から、MOKリストの変更は次回の起動時にMOKマネージャーのGUIで確認する必要がある。
MOKのメリットは、セキュアブートの恩恵を受けつつ、システムの柔軟性を維持できることである。
例えば、カスタムドライバやサードパーティ製のカーネルモジュールを使用する必要がある場合でも、MOKを使用することで安全に導入できる。
一方で、MOKの使用には注意点もある。
不適切な管理は、システムのセキュリティを脅かす可能性がある。
また、MOKの操作には技術的な知識が必要であり、誤った操作によってシステムが起動できなくなる可能性もある。
鍵ペア (秘密鍵 / DER)
秘密鍵ファイル (.priv) および DERファイル (.der) は、公開鍵暗号方式における鍵ペアを表現するファイルである。
これらのファイルは、カーネルモジュールの署名と検証に重要な役割を持つ。
- 秘密鍵ファイル (.priv)
- 秘密鍵は非常に重要で機密性の高い情報である。
- 主にモジュールへの署名に使用する。
- 秘密鍵の特徴
- 署名の生成に使用する。
- 厳重に保護する必要があり、決して公開してはならない。
- 一般的に、暗号化されたフォーマットで保存される。
- DERファイル (.der)
- このファイルは公開鍵を含んでいる。
- 公開鍵は広く共有され、署名の検証に使用する。
- DER (Distinguished Encoding Rules) ファイルは、公開鍵証明書のエンコーディング形式を指す。
- 公開鍵の特徴
- 署名の検証に使用する。
- システムのMOKリストに登録される。
- 自由に配布可能であり、セキュリティ上の問題はない。
これらのファイルの生成プロセスは、以下に示すようになる。
- 鍵ペアの生成
- OpenSSL等のツールを使用して、秘密鍵と公開鍵のペアを生成する。
- モジュールの署名時には.privファイルを使用する。
- 秘密鍵の保存
- 生成された秘密鍵を.privファイルとして保存する。
- 公開鍵の抽出とエンコード
- 秘密鍵から公開鍵を抽出およびDER形式でエンコードした後、.derファイルとして保存する。
- 署名の検証やMOKへの登録時には.derファイルを使用する。
※注意
不正アクセスされると、攻撃者がモジュールに偽の署名を行える可能性があるため、.privファイルの管理には特に注意を払う必要がある。
一方、.derファイルは公開情報であるため、厳重な管理は不要である。
これらのファイルを適切に使用することにより、MOKシステムはセキュアブート環境下でもカスタムモジュールの安全な使用を可能にしている。
設定ファイル
鍵ペア (秘密鍵 / DER) を生成する場合、OpenSSL等を使用して証明書要求 (CSR) と自己署名証明書を生成するための設定を定義する必要がある。
この定義を使用することにより、MOKシステムで使用するための属性と拡張機能を持つ鍵ペアと証明書を生成することができる。
生成された.privファイルは秘密鍵、.derファイルは公開鍵証明書をDERフォーマットで含むことになる。
以下に示す設定ファイルの定義は、セキュアブート環境でカーネルモジュールの署名に使用される証明書の要件を満たすように調整されている。
特に、keyUsage
がdigitalSignature
に設定されているため、この鍵がモジュール署名専用であることを示している。
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = myexts
[ req_distinguished_name ]
O = SUSE Linux Products GmbH # 任意の名前
CN = SUSE Linux Enterprise Secure Boot # 任意の名前
emailAddress = suse@localhost # 任意のメールアドレス
[ myexts ]
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
- [req]セクション
- default_bits
- 鍵のビット長を指定する。
- 上記の例に記述されている4096とは、強力な暗号化を提供する。
- distinguished_name
- 証明書要求 (CSR) や証明書に含める識別名 (Distinguished Name, DN) 情報を定義するセクションを指定する。
- 任意の文字列が使用できる。
- ※注意
- 値を変更する場合、その値と同じ名前のセクションを設定ファイル内に作成する必要がある。
- prompt
no
を指定する場合、対話的なプロンプトを無効にして、ファイルから直接情報を読み取る。
- string_mask
utf8only
を指定する場合、文字列をUTF-8エンコーディングに制限する。
- x509_extensions
- 生成されるX.509証明書に追加する拡張機能を定義するセクションを指定する。
- 任意の文字列が使用できる。
- 省略も可能である。(省略時は拡張機能が追加されない)
- ※注意
- 値を変更する場合、その値と同じ名前のセクションを設定ファイル内に作成して、そこで拡張機能を定義する必要がある。
- default_bits
- [req_distinguished_name]セクション ※ユーザ定義のセクション名
- O
- 組織 (Organization) 名を指定する。
- CN
- 共通名 (Common Name) を指定する。
- 一般的には、証明書の主要な識別子として使用する。
- emailAddress
- 連絡先のメールアドレスを指定する。
- O
- [myexts]セクション (X.509証明書拡張) ※ユーザ定義のセクション名
- basicConstraints
critical,CA:FALSE
を指定する場合、この証明書が認証局 (CA) でないことを示し、このフィールドを重要 (critical) とマークする。
- keyUsage
digitalSignature
を指定する場合、この鍵のの使用目的がデジタル署名であることを指定する。
- subjectKeyIdentifier
hash
を指定する場合、証明書の公開鍵のハッシュを含む識別子を追加する。
- authorityKeyIdentifier
- 証明書の発行者 (自己署名の場合はユーザ自身) の公開鍵を識別するための方法を指定する。
keyid
を指定する場合、発行者の公開鍵のハッシュを使用することを意味する。- keyid, issuer : 発行者の公開鍵のハッシュと発行者の名前を両方含める。
- issuer: 発行者の名前のみを含める。
- 省略することができる。(省略時はこの拡張機能が追加されない)
- ※注意
- 自己署名証明書の場合、
keyid
が最も一般的な選択肢である。 issuer
を含める場合、自己参照的な情報になる可能性がある。
- basicConstraints
鍵ペア (秘密鍵 / DER) の生成
OpenSSL等を使用して、鍵ペア (秘密鍵 / DER) を生成する。
以下の例では、自己署名証明書と対応する秘密鍵を生成する。
このコマンドは、MOKシステムで使用するための形式と属性を持つ証明書と鍵ペアを生成する。
生成された.derファイルは公開鍵証明書、.privファイルは対応する秘密鍵を含む。
特に、-addext
オプションを指定することにより、この証明書がコード署名 (カーネルモジュールの署名等) に使用できることが明示できる。
これは、セキュアブート環境でモジュールを署名する場合に必要な属性である。
以下の例では、-days 36500のように長期の有効期限を設定しているが、セキュリティの観点からは、より短い期間で定期的に更新することが推奨される場合もある。
openssl req -x509 -new -nodes -utf8 -sha256 \ -days 36500 \ -batch \ -config <上記で作成した設定ファイルのパス> \ -outform DER \ -out <生成するDERファイルのパス> \ -keyout <生成する.privファイルのパス> \ -addext "extendedKeyUsage=codeSigning"
- -reqオプション
- 証明書要求 (CSR) の処理や証明書の生成を行うOpenSSLのサブコマンドである。
- -x509
- CSRではなく、自己署名X.509証明書を直接生成することを指定する。
- -new
- 新しい証明書要求を生成する。
- -x509オプションと組み合わせることにより、新しい自己署名証明書を生成する。
- -nodes
- 秘密鍵を暗号化せずに生成する。
- -utf8
- 証明書のフィールドにUTF-8エンコーディングを使用する。
- -sha256
- 証明書の署名にSHA-256ハッシュアルゴリズムを使用する。
- -days <日数>
- 証明書の有効期限を指定する。
- 36500と指定する場合、証明書の有効期限は36500日 (約100年) となる。
- -batch
- 対話的なプロンプトを無効にして、設定ファイルから全ての情報を読み取る。
- -config <使用する設定ファイル>
- 使用する設定ファイルを指定する。
- -outform DER
- 出力形式をDER (Distinguished Encoding Rules) に設定する。
- -out <DERファイルのパス>
- 生成された証明書 (公開鍵部分) の出力先を指定する。
- -keyout <.privファイルのパス>
- 生成された秘密鍵の出力先を指定する。
- -addext "extendedKeyUsage=codeSigning"
- 証明書に拡張キー使用法を追加して、コード署名用であることを示す。
MOKキーの登録
以下に示すコマンドを実行して、MOKにキーをインポートする。
sudo mokutil --import <DERファイルのパス> # または sudo mokutil --import <DERファイルのパス> --root-pw
PCを再起動して、Linuxブートローダ起動前にキーをインポートする。
sudo systemctl reboot
署名
カーネルモジュールの署名
カーネルモジュールをMOKに署名する。
sudo /lib/modules/$(uname -r)/build/scripts/sign-file sha256 \ <.privファイルのパス> \ <.derファイルのパス> \ <署名するカーネルモジュールのパス 例: /lib/modules/$(uname -r)/kernel/fs/f2fs/f2fs.ko>
署名の解除
MOKの署名はカーネルモジュールに適用された暗号学的な署名であり、1度適用されると、その署名自体を「解除」することはできない。
しかし、運用上では以下に示すような対応が可能である。
- カーネルモジュールの削除
- 署名されたモジュールファイルを削除すれば、そのモジュールはもう使用されない。
- ただし、これは署名を「解除」するのではなく、署名されたファイルを除去するだけである。
- MOKリストからの鍵の削除
- MOKリストから署名に使用した公開鍵を削除することにより、その鍵で署名された全てのモジュールが無効になる。
- これは、mokutilコマンドを使用して行うことができる。
sudo mokutil --delete <DERファイル名>.der
- このコマンドを実行した後、次回の起動時にMOKマネージャーのGUIで削除を確認する必要がある。
※注意
単にカーネルモジュールを削除しても、MOKリストから署名鍵が削除されるわけではない。
これらの操作は、システムのセキュリティに影響を与える可能性があるため、十分に注意して行う必要がある。
MOKの署名自体を解除することはできないが、上記の方法を使用して署名されたモジュールの使用を防いだり、システム全体でMOK検証を無効にすることが可能である。