SHE(Secure Hardware Extensions)を理解しよう
業務にて、SHE(Secure Hardware Extensions)の理解が必要となっているため勉強してみました。
今回は以下で公開されている規格書をメインに、確認をしていきます。
初めに
SHEはAUTOSARによって標準化されているセキュリティ規格であり、任意のマイクロコントローラに対してオンチップで設計するものです。
そのため、複数のベンダからSHEに準拠したチップが提供されています。
SHEは車載ECUにおけるHSMとしての役割を担います。
HSMに関しては以下で触れているので合わせて参考にしてみてください。
規格書ではSHEによる目的は以下とされています。
- ソフトウェアによる攻撃から暗号鍵を保護する
- 安全なソフトウェア環境を提供する
- システムにおけるセキュリティ強度が、基礎となるアルゴリズムの強さと鍵の機密性にのみ依存するようにする
- 鍵の機密性
- 鍵の所有者の分散
- 柔軟性を高く、コストを低く抑える
SHEの構成
SHEは基本的にメモリ、ブロック暗号(AES)、制御ロジックの3つのブロックから構成されています。
SHEへのアクセスは必ずSHEに規定されている制御ロジック経由で行われます。
上記以外のSHEに対するアクセスに対し保護機能を設けることで、鍵情報などの機密情報が外部に漏れないような設計とする必要があります。
このような設計思想は、SHEに限らずHSM全般共通の設計方針とも言えます。
ブロック | 概要 |
---|---|
メモリ | 暗号鍵や対応する追加情報を管理する。 |
AES | 任意の暗号演算処理を実施する。乱数生成も本ブロックに含む。 |
制御ロジック | マイコンのCPUからの要求に応じて、任意の処理を動作させる。 |
AES
SHEで対応が必要とされている暗号方式はAES-128です。
また、AESの中でもECBとCBC、CMACのサポートが必須とされています。
圧縮処理
SHEでは宮口・プレネルという圧縮処理を使用します。
SHEの圧縮処理で使用される暗号利用モードはAES-ECBです。
圧縮処理や宮口・プレネルについては以前取り上げているためこちらを参照してください。
パディング方式
SHEの圧縮処理では、AES-128のECBを使用して圧縮処理を行うため、128bitのブロック長へパディングを行う必要があります。
単純なパディングではなく、メッセージの末尾に任意のパラメータを複数付与することでパディングを実施します。
データの内訳は以下の通りです。
データ種別 | サイズ(bit) | 概要 |
---|---|---|
メッセージ | 任意 (l) | 圧縮処理を実施するおおもとのメッセージ。 |
1bit付加データ | 1 | メッセージの末尾に1ビットだけ付与する値「1」のbit。 |
任意bit付加データ | 任意 (k) | 1bit付加データの後に付与する任意bit長の値「0」のパディングデータ。 サイズは l + 1 + k + 40 がブロック(128bit)単位となる最小の値を設定する。 |
ブロック長 | 40 | メッセージのbit長である l を本値として設定する。 |
実際には圧縮処理使用時のパラメータ長が各コマンドで決まり切っているため、上記パディング方式に則った定数がSHEでは提示されています。
圧縮処理の流れ
事前にパディングを実施したデータを128bit単位のブロック(m1、m2、m3…)に分割。
① Hi-1(前回の算出結果)を鍵として、メッセージブロックmiを暗号化
(初回メッセージブロックm1を暗号化するときの鍵値H0はALL0の値を使用)
② 出力された暗号文とHi-1をXOR
③ ②の出力値とメッセージブロックmiをさらにXORすることでHiを生成
①~③をブロック数分繰り返す。
KDF
SHEでは、処理シーケンス中で一時的に使われる鍵値を生成するKDF(key derivation function)と呼ばれる処理を実施します。
一般的なKDFの方法は様々なものがあります。
SHEにおいては前述の圧縮処理をKDFとして利用します。
メモリ
SHEでは揮発と不揮発のメモリ管理を行います。
不揮発性メモリは、マイコンの電源再投入やリセット後も利用可能な情報を格納します。
一方で揮発性メモリには、一時的な情報を保存します。本情報はマイコンのリセットやパワーサイクルの際に内容が失われる可能性があります。
前述の通り、SHE の制御ロジック経由以外で外部からSHEの管理するメモリへのアクセスは出来ません。
メモリの種類
管理するメモリは主にROM、フラッシュメモリ、RAMの三種類に分けられます。
メモリ | 揮発/不揮発 | 更新 | 主な管理情報 |
---|---|---|---|
ROM | 不揮発 | 無 | SECRET_KEY、UID |
フラシュメモリ | 不揮発 | 有 | MASTER_ECU_KEY、BOOT_MAC_KEY、BOOT_MAC、KEY_<n>、PRNG_SEED |
RAM | 揮発 | 有 | RAM_KEY、PRNG_KEY、PRNG_STATE |
メモリスロット
SHEで保持する鍵情報とセキュアブート用MAC値は、メモリスロットと呼ばれる論理ブロックに分けて管理されています。
各メモリスロットにはKEY_IDと呼ばれる4bitの識別子が割り振られており、鍵使用時は主にKEY_IDから使用する鍵を指定します。
スロット | メモリ | KEY_ID | 概要 |
---|---|---|---|
SECRET_KEY | ROM | 0x0 | チップ固有の秘密鍵。 メーカーがチップ製造時に書き込む必要があり、SHE以外に保存してはならない。 |
MASTER_ECU_KEY | フラッシュメモリ | 0x 1 | SHE 内の他のメモリスロットの更新にのみ使用される鍵。 |
BOOT_MAC_KEY | フラッシュメモリ | 0x2 | セキュアブートで使用する鍵。 |
BOOT_MAC | フラッシュメモリ | 0x3 | セキュアブートで使用するMAC値。 |
KEY_1 | フラッシュメモリ | 0x4 | 任意のアプリケーションが暗号演算に使用する鍵。 SHEは少なくとも3つ、最大で10個のキーを任意に使用できるように実装する必要がある。 |
KEY_2 | フラッシュメモリ | 0x5 | 同上。 |
KEY_3 | フラッシュメモリ | 0x6 | 同上。 |
KEY_4 | フラッシュメモリ | 0x7 | 同上。 |
KEY_5 | フラッシュメモリ | 0x8 | 同上。 |
KEY_6 | フラッシュメモリ | 0x9 | 同上。 |
KEY_7 | フラッシュメモリ | 0xa | 同上。 |
KEY_8 | フラッシュメモリ | 0xb | 同上。 |
KEY_9 | フラッシュメモリ | 0xc | 同上。 |
KEY_10 | フラッシュメモリ | 0xd | 同上。 |
RAM_KEY | RAM | 0xe | 任意のアプリケーションが暗号演算に使用する鍵。 事前にアプリケーションが鍵値をSHEへ渡す必要がある。 本鍵の使用時には、リプレイ攻撃やサービ ス拒否攻撃などの攻撃に対して脆弱であることの考慮が必要。 |
メモリスロットの付加情報について
各メモリスロットごとに付加情報を持っており、任意のタイミングで読み出しと更新を実施します。
付加情報は大きく分けてフラグとカウンタの二種類があります。
鍵データとフラグ、カウンタそれぞれのセグメントは別々に書き込み/消去できるようにする必要があります。
フラグは6種類のセキュリティビットが存在し、"0 “はフラグが設定されていないことを意味、"1 “はフラグが設定されていることを意味します。
カウンタはフラッシュメモリで管理するデータの更新回数を意味し、サイズは28bitとなります。
メモリスロットごとに実装が必要な付加情報と、実装が不要な付加情報が存在します。
管理情報 | データ種別 | 概要 | 実装する メモリスロット |
---|---|---|---|
Write-protection | フラグ | 設定することでメモリスロットへの書き込みを禁止にする。 本フラグはSHEのみがアクセス可能な不揮発性メモリに保存され、 ライトアクセス時にSHEを制御するステートマシンが評価する。 | MASTER_ECU_KEY BOOT_MAC_KEY BOOT_MAC KEY_<n> |
Secure boot failure | フラグ | セキュアブート失敗時に鍵の使用を禁止する。 リセット後にセキュアブート成功した場合、本フラグ設定もクリアされる。 | SECRET_KEY MASTER_ECU_KEY KEY_<n> |
Debugger activation | フラグ | デバッガ起動時に鍵の使用を禁止する。 | SECRET_KEY MASTER_ECU_KEY BOOT_MAC_KEY BOOT_MAC KEY_<n> |
Wildcard UID | フラグ | UIDを指定せずに鍵を更新可能にする。 | MASTER_ECU_KEY BOOT_MAC_KEY BOOT_MAC KEY_<n> |
Key usage | フラグ | 鍵の用途を指定する。 0:暗号化/復号化 1:MAC生成/検証用 | KEY_<n> |
Plain key | フラグ | RAM_KEYに対してのみ実装するフラグ。 CPUからRAM_KEYをインポートした場合、本フラグを設定する。 | RAM_KEY |
カウンタ | カウンタ | フラッシュメモリで管理するデータの更新回数を意味する。 サイズは28bitとなる。 | MASTER_ECU_KEY BOOT_MAC_KEY BOOT_MAC KEY_<n> |
メモリスロット以外の管理情報
メモリスロット以外にも各種SHEで管理している情報が存在します。
管理情報 | メモリ | サイズ | 概要 |
---|---|---|---|
UID | ROM | 120bit | 120ビットのシリアル番号。 この識別子は、半導体メーカーがチップを製造する際に書き込む。 |
PRNG_SEED | フラッシュメモリ | 128bit | 疑似乱数生成で使用するシード値。 |
PRNG_KEY | RAM | 128bit | 疑似乱数生成で使用する鍵値。 |
PRNG_STATE | RAM | 128bit | 疑似乱数発生器の状態。 |
ステータスレジスタ | RAM | 8bit | SHEの内部状態。 |
ステータスレジスタについては、各bitごとに8つのステータスを管理しています。
ビットがセットされるとその値は’1’となり、クリアされるとその値は’0’となります。
名称 | bit位置 | 概要 |
---|---|---|
BUSY | 0 | SHEがコマンド処理中の場合、このビットは設定される。 |
SECURE_BOOT | 1 | セキュアブートが有効な場合、このビットは設定される。 |
BOOT_INIT | 2 | ブートシーケンス中にセキュアブートが実行された場合、このビットが設定される。 |
BOOT_FINISHED | 3 | CMD_BOOT_FAILUREまたはCMD_BOOT_OKを呼び出してセキュアブートを終了した場合、 またはCMD_SECURE_BOOTでBOOT_MACの確認に失敗した場合、このビットは設定されます。 |
BOOT_OK | 4 | セキュアブート(CMD_SECURE_BOOT)が成功した場合、このビットが設定される。 CMD_BOOT_FAILUREが呼び出された場合、ビットはクリアされる。 |
RND_INIT | 5 | 乱数発生器が初期化(CMD_INIT_RNG)された場合、このビットは設定される。 |
EXT_DEBUGGER | 6 | 外部デバッガがチップに接続されている場合、このビットが設定されます。 |
INT_DEBUGGER | 7 | SHEの内部デバッギング機構が作動している場合、このビットは設定されます |
制御ロジック
制御ロジックは大きく分けて二つです。
一つはCPUからの要求取得と応答通知のための通信制御。
もう一つが要求処理をSHE内で実行するためのシーケンス制御です。
要求と応答
CPUからSHEに対する要求と、SHEからCPUに対する応答はSHEで規定されているパラメータに則って行われます。
ただしCPU-SHE間の通信方法、要求データと応答データの受け渡し方法についてはSHEでは厳密に規定されておりません。
そのため、各ハードに合わせたデータの受け渡し方法を検討する必要があります。
また要求取得から応答までの処理は非同期で行われます。そのため、SHEはノンブロッキングI/Oである必要があります。
コマンド
CPUは任意のコマンドとパラメータをSHEへ通知することで、SHEに対し処理を要求します。
コマンド | 概要 | 入力 (bit単位) | 出力 (bit単位) |
---|---|---|---|
CMD_ENC_ECB | 平文の暗号化(AES_ECB)を要求。 要求可能なサイズは128bit固定。 | KEY_ID:4 平文:128 | 暗号文:128 |
CMD_ENC_CBC | 平文の暗号化(AES_CBC)を要求。 128bit単位であれば任意のデータ長の要求が可能。 | KEY_ID:4 IV:128 平文:n*128 | 暗号文:n*128 |
CMD_DEC_ECB | 暗号文の復号化(AES_ECB)を要求。 要求可能なサイズは128bit固定。 | KEY_ID:4 暗号文:128 | 平文:128 |
CMD_DEC_CBC | 暗号文の復号化(AES_CBC)を要求。 128bit単位であれば任意のデータ長の要求が可能。 | KEY_ID:4 IV:128 暗号文:n*128 | 平文:n*128 |
CMD_GENERATE_MAC | 任意のメッセージに対しMAC生成を要求。 サイズはメッセージのbit長を意味する。 | KEY_ID:4 サイズ:64 メッセージ:n*128 | MAC:128 |
CMD_VERIFY_MAC | 任意のメッセージに対しMAC値の検証を要求。 サイズはメッセージのbit長を意味する。 MACサイズは比較するMAC値のビット数(左端のビットから始まる)を指定。 MAC値が一致した場合、検証結果は"0″を通知。 | KEY_ID:4 サイズ:64 メッセージ:n*128 MAC:128 MACサイズ:7 | 検証結果:1 |
CMD_LOAD_KEY | SHE の鍵を更新する。 | M1:128 M2:256 M3:128 | M4:256 M5:128 |
CMD_LOAD_PLAIN_KEY | SHE のRAM_KEYを更新する。 | 平文:128 | – |
CMD_EXPORT_RAM_KEY | SHE のRAM_KEYを取得する。 | – | M1:128 M2:256 M3:128 M4:256 M5:128 |
CMD_INIT_RNG | SHEの乱数生成で使用するシード値を初期化する。 本コマンドは電源再投入のたびに必ず実施しなければCMD_RNDは使用できない。 | – | – |
CMD_EXTEND_SEED | SHEが乱数生成で使用するシード値の更新を要求する。 なおSHEは、本コマンドで渡すシード値と、もともとSHEで保持していたシード値の圧縮値を、新たなシード値として扱う。 本コマンド使用前にCMD_INIT_RNG で初期化する必要がある。 | SEED:128 | – |
CMD_RND | 128ビットの乱数を要求する。 本コマンド使用前にCMD_INIT_RNG で初期化する必要がある。 | – | RND:128 |
CMD_SECURE_BOOT | SHEへセキュアブートの実施を要求する。 本コマンドは電源再投入のたびに一度しか使用できない。 | サイズ:32 データ: サイズ * 8 | – |
CMD_BOOT_FAILURE | SHEのブートステータスを失敗へ設定する。 | – | – |
CMD_BOOT_OK | SHEのブートステータスを成功へ設定する。 | – | – |
CMD_GET_STATUS | ステータスレジスタ(SREG)の値を取得する。 | – | SREG:8 |
CMD_GET_ID | UIDとステータスレジスタの値を取得する。 このとき取得するUIDとステータスレジスタの値は、MASTER_ECU_KEYによるチャレンジレスポンス処理により、完全性が保証されている。 | チャレンジ:128 | UID:120 SREG:8 MAC:128 |
CMD_CANCEL | SHEが行っている任意の処理を中断し、すべての計算と結果を破棄する。 | – | – |
CMD_DEBUG | SHEの内部デバッグ機能を有効可する。 | 認証子:128 | チャレンジ: 128 |
レスポンス
SHEは任意のコマンドに対応したエラーコードとパラメータをCPUへ渡すことで、処理結果を通知します。
エラーコード | 概要 |
---|---|
ERC_NO_ERROR | 要求処理を正常に完了した。 |
ERC_SEQUENCE_ERROR | シーケンス不正。 |
ERC_KEY_NOT_AVAILABLE | メモリスロットの管理情報におけるSecure boot failure、またはDebugger activationにて使用が禁止されている鍵を指定。 |
ERC_KEY_INVALID | 与えられた操作に対して許可されていない鍵を指定。 |
ERC_KEY_EMPTY | 鍵が格納されていないメモリスロットを指定。 |
ERC_NO_SECURE_BOOT | CMD_SECURE_BOOT実行時、実行条件を満たさない。 |
ERC_KEY_WRITE_PROTECTED | 書き込み保護(Write-protection)されているメモリースロットに対し、鍵更新を実施。 |
ERC_KEY_UPDATE_ERROR | 鍵の更新シーケンスにおけるメッセージ検証に失敗。 |
ERC_RNG_SEED | シード値の初期化(CMD_INIT_RNG)前に、CMD_RNDまたはCMD_DEBUGを実行。 |
ERC_NO_DEBUGGING | CMD_DEBUGにおける、チャレンジレスポンスプロトコルによる認証が失敗。 |
ERC_BUSY | 他の関数が処理中(ステータスレジスタのBUSY = 1の場合)にSHEの関数を呼び出した。 |
ERC_MEMORY_FAILURE | メモリの読み取りまたは書き込み操作中に、ビット反転などの物理エラーを検出。 |
ERC_GENERAL_ERROR | 上記のエラーコードに該当しないエラーをSHE内部で検出。 |
鍵管理(CMD_LOAD_KEY)
SHEはコマンドCMD_LOAD_KEYを使用し前述のメモリスロットを更新することで、鍵更新を行います。
このとき行われる操作は機密性、完全性、真正性が保証されていなければなりません。
そのための操作が次で説明する鍵更新プロトコルになります。
なお、CMD_LOAD_PLAIN_KEYというRAM上の鍵を更新する操作もありますが、あくまでも一時的な鍵の使用時にのみ本コマンドは使用します。
鍵更新パラメータ
鍵更新で使用するパラメータは以下の通り。
パラメータ | サイズ(bit) | 概要 |
---|---|---|
KEY | 128 | 更新予定の鍵値 |
KEY_ID | 4 | 更新予定の鍵のKEY_ID |
AuthKEY | 128 | 鍵更新時に認証処理のため使用する鍵 |
AuthID | 4 | 鍵更新時に認証処理のため使用する鍵のKEY_ID |
UID | 120 | SHRで規定されるシリアル番号 |
CID | 28 | データの更新回数 |
FID | 5 | 更新対象のメモリスロットに対する設定を示すbit 以下の連結値 WRITE_PROTECTION |BOOT_PROTECTION |DEBUGGER_PROTECTION|KEY_USAGE |WILDCARD |
鍵更新の過程で各種鍵生成を行います。
前述の通り鍵生成は圧縮処理を用いて行うのですが、付加パラメータとパディング値は定数としてSHEにて記載があります。
鍵 | 鍵生成パラメータ | 用途 | 定数値 |
---|---|---|---|
KDF_KEY1 | AuthKEY | KEY_UPDATE_ENC_C | M2生成 | 0x01015348 45008000 00000000 000000B0 |
KDF_KEY2 | AuthKEY | KEY_UPDATE_MAC_C | M3生成 | 0x01025348 45008000 00000000 000000B0 |
KDF_KEY3 | KEY | KEY_UPDATE_ENC_C | M4生成 | 0x01015348 45008000 00000000 000000B0 |
KDF_KEY4 | KEY | KEY_UPDATE_MAC_C | M5生成 | 0x01025348 45008000 00000000 000000B0 |
実際にSHE間でやり取りを行う値は以下のM1からM5になります。
本値を用いて取得値の検証を相互に行い、鍵更新が正常に行われていることを確認します、
パラメータ | サイズ(bit) | IN/OUT | 設定値 |
---|---|---|---|
M1 | 128 | IN | 以下連結値 UID | KEY_ID | AuthID |
M2 | 256 | IN | 以下連結値を、KDF_KEY1でCBC暗号化した値(IV = 0) CID | FID| 0パディング(95bit) | KEY |
M3 | 128 | IN | 以下連結値から、KDF_KEY2で生成されたMAC値 M1 | M2 |
M4 | 256 | OUT | CIDに対し最初に1、以降は0の値でパディングした値(128bit)とKDF_KEY3でECB暗号化をおこなう CID | 0b1000…… 上記出力値(OUT0)を以下のように連結させた値 UID | KEY_ID | AuthID | OUT0 |
M5 | 128 | OUT | M4から、KDF_KEY4で生成されたMAC値 |
簡単な鍵更新処理の流れになります。
STEP | SHE実施処理 | 判定NGレスポンス (鍵更新不可) |
---|---|---|
1 | コマンド"CMD_LOAD_KEY"にてM1、M2、M3を取得 | – |
2 | KEY_IDで指定されるメモリスロットの、WRITE_PROTECTIONが無効であることを確認 | ERC_WRITE_PROTECTED |
3 | KDF_KEY2’生成 | – |
4 | 取得したM1 | M2と、生成したKDF_KEY2’からM3’を生成 | – |
5 | 生成したM3’と取得したM3が一致することを確認 | ERC_KEYUPDATE_ERROR |
6 | 以下のいずれかであることを確認 ・M1のUIDが0、かつ更新対象メモリスロットのWildcard UIDが有効 ・M1のUIDが一致している | ERC_KEYUPDATE_ERROR |
7 | KDF_KEY1’生成 | – |
8 | M2をKDF_KEY1’を用いてCBC復号化 | – |
9 | STEP7で復号した値からCIDを取得 更新対象のメモリスロットのCIDよりも取得したCIDの方が値が大きいことを確認 | ERC_KEYUPDATE_ERROR |
10 | 取得したパラメータ(KEY、CID、FID)をメモリスロットへ反映させる。 | – |
11 | KDF_KEY3’生成 | – |
12 | M4生成 | – |
13 | KDF_KEY4’生成 | – |
14 | M5生成 | – |
15 | M4、M5とともにERC_NO_ERRORを応答 | – |
最後に
SHEの内容についてざっくりとまとめてみました。
車載向けのセキュリティ規格書ということで身構えていましたが、ちゃんと読んでみるとそこまで難しい内容ではないのが意外でした。
また、pythonを使って鍵更新の処理を実装してみようかとも思いましたが、すでに取り組んでいた方がいたため紹介します。
非常にコードが整理されていて見やすいので、鍵更新の理解を深める上でもお勧めです。