PSA APIs 17 · 実践パターン — よくある要件を PSA の呼び出し列に翻訳する

Chapter 17

実践パターン — よくある要件を PSA の呼び出し列に翻訳する

この章のゴール.

「装置を認証したい」「設定を暗号化して保存したい」「更新イメージを検証したい」といった要件を、 どの章のどの関数を、どの順で呼ぶかに翻訳できるようになること。 各パターンについて、鍵の属性・寿命・保存場所まで含めて決められること。

この章で使う既出の用語(定義は各リンク先). PSA(01 章 1 節)、algorithm(03 章 11 節)、type(03 章 11 節)、usage(03 章 11 節)、公開鍵だけ(03 章 3 節)、場所(03 章 7 節)、持続性(03 章 7 節)、generate(04 章 10 節)、import(04 章 10 節)、ハッシュ(05 章 1 節)、乱数(05 章 1 節)、HMAC-SHA256(06 章 1 節)、AES(07 章 1 節)、カウンタ(08 章 4 節)、ノンス(08 章 1 節)、チャレンジ(09 章 5 節)、否認防止(09 章 1 節)、認証(09 章 1 節)、HKDF(10 章)、info(10 章 3 節)、salt(10 章 3 節)、パスワード(10 章 2 節)、ECDH(11 章 1 節)、共有秘密(11 章 1 節)、前方秘匿性(11 章 5 節)、ITS(13 章 1 節)、IAK(14 章 4 節)、Nonce(14 章 3 節)、アテステーション(14 章 1 節)、トークン(14 章)

1. パターンの見取り図

要件主役の関数鍵章
A. 装置の認証(クラウド接続)psa_sign_hash / mbedtls_pk_setup_opaque永続 ECDSA P-256 鍵ペア、装置内生成04・09・15
B. 設定・資格情報の暗号化保存psa_aead_encrypt/decrypt + ITS永続 AES-256-GCM 鍵、装置内生成。または HUK からの導出08・12・13
C. OTA イメージの検証分割ハッシュ + psa_verify_hash公開鍵(WRITE_ONCE ITS または read-only 鍵)05・09・13
D. 装置間の暗号化通信ECDH + HKDF + AEAD、署名で認証一時 ECDH 鍵、長期署名鍵09・10・11
E. センサーデータの改ざん防止psa_mac_compute永続 HMAC 鍵、または導出鍵06・10
F. 製造時の鍵注入と個体化psa_import_key + psa_key_derivation_*マスター鍵から装置鍵を導出04・10・12
G. 健全性の証明psa_initial_attest_get_tokenIAK(TF-M が管理)14
7 つのパターンと主役の関数A. 装置の認証psa_sign_hash / pk_setup_opaque — 永続 ECDSA 鍵、装置内生成B. 設定の暗号化保存psa_aead_* + ITS — 永続 AES-GCM 鍵C. OTA イメージ検証分割ハッシュ + psa_verify_hash — 公開鍵は WRITE_ONCED. 装置間の暗号化通信ECDH + HKDF + AEAD + 署名 — 一時鍵と長期鍵E. データの改ざん防止psa_mac_compute — HMAC 鍵、チェーンF. 製造時の鍵注入psa_import_key + 導出 — マスター鍵から装置鍵G. 健全性の証明psa_initial_attest_get_token — IAK共通鍵の一覧・ノンス管理・失敗時動作・更新手順・保存場所を紙に書く要件は「鍵の属性 + 関数の呼び出し列 + 保存場所」に翻訳する
各パターンが本編のどの関数を組み合わせるかの見取り図

2. パターン A — 装置の認証

要件: クラウド(AWS IoT、Azure IoT Hub、自社サーバ)に TLS で接続し、装置が本物であることを証明する。

設計:

  1. 初回起動時、装置内で ECDSA P-256 鍵ペアを永続鍵として生成する(SIGN_HASH、EXPORT なし)
  2. 公開鍵をエクスポートし、CSR(証明書署名要求)を作って製造ラインの CA(認証局)に送り、装置証明書を受け取って PS に保存する。または公開鍵だけをサーバに登録する
  3. 実運用では、TLS クライアント認証の秘密鍵として mbedtls_pk_setup_opaque() で PSA 鍵を指す
/* 初回のみ */
psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attr, 256);
psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH);
psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH));   /* TLS はハッシュを交渉する */
psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_id(&attr, KEY_ID_DEVICE_SIGN);
PSA_CHECK(psa_generate_key(&attr, &key));

/* 毎回 */
mbedtls_pk_setup_opaque(&pk, KEY_ID_DEVICE_SIGN);
mbedtls_ssl_conf_own_cert(&conf, &crt, &pk);

要点: アルゴリズムに PSA_ALG_ANY_HASH を使うのは、TLS 1.2/1.3 でサーバが SHA-256 以外を要求することがあるためである。 自社プロトコルなら PSA_ALG_SHA_256 に固定する。 TF-M 環境では、この鍵は Crypto パーティションの所有であり、非セキュア側が乗っ取られても署名を「依頼」することしかできない。 アテステーション(パターン G)を組み合わせると、乗っ取られた状態での依頼を検証側で拒否できる。

パターン A — 装置の認証初回起動psa_generate_key: ECC P-256、SIGN_HASH、永続、EXPORT なし公開鍵を登録psa_export_public_key → CSR → 装置証明書を PS に毎回mbedtls_pk_setup_opaque(&pk, KEY_ID) → TLS クライアント認証algorithm は PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)TLS はサーバとハッシュを交渉するため。自社プロトコルなら SHA_256 に固定するTF-M では鍵は Crypto パーティションの所有。乗っ取られた NSPE は「署名の依頼」しかできない
秘密鍵は装置内で生まれ、一度も外に出ない

3. パターン B — 設定・資格情報の暗号化保存

要件: Wi-Fi パスワードやクラウドのトークンを、外部フラッシュや通常のファイルシステムに保存したい。

設計:

/* 鍵: 初回起動で生成、永続、AES-256-GCM、装置固有 */
psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attr, 256);
psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attr, PSA_ALG_GCM);
psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_id(&attr, KEY_ID_CONFIG_AEAD);

/* 保存: [version(4)] [nonce(12)] [ciphertext+tag] を書く。version と "config" ラベルを AD に */
uint8_t ad[10] = "config"; put_be32(ad + 6, version);
psa_generate_random(nonce, 12);
psa_aead_encrypt(KEY_ID_CONFIG_AEAD, PSA_ALG_GCM, nonce, 12, ad, 10, plain, plen, ct, sizeof ct, &ct_len);

/* 読み出し: version を AD に含めて復号。失敗したら「壊れている/改ざん」として工場出荷状態へ */

要点:

4. パターン C — OTA イメージの検証

要件: 無線で受け取ったファームウェアが、正規の署名者によるものか確認してから書き込む・起動する。

設計(MCUboot を使う場合は、MCUboot がこれを行う。以下は自前で行う場合):

  1. サーバは、イメージの SHA-256 に ECDSA で署名し、[image] [manifest: version, size, hash, signature] を配布する
  2. 装置は、受信しながら分割ハッシュを取り(05 章)、受信完了後に psa_verify_hash() で署名を検証する
  3. 検証成功後、バージョンが現在より新しいことを確認してから(ロールバック防止)、スロットを切り替える
/* 検証用公開鍵: 差し替えられない場所に */
/* TF-M: read-only の組み込み鍵 / MCUboot: ブートローダのコードに埋め込み / 単体: ITS WRITE_ONCE */

要点:

パターン C — OTA イメージの検証受信しながらpsa_hash_update をチャンクごとに。フラッシュに書いてよい受信完了psa_hash_finish → psa_verify_hash(pub, ECDSA(SHA_256), hash, sig)バージョン比較ITS の番号より新しいときだけ切替。古ければ拒否切替スロットを有効化、番号を ITS に更新検証用公開鍵は差し替えられない場所にTF-M: read-only の組み込み鍵 / MCUboot: ブートローダに埋め込み / 単体: ITS WRITE_ONCE署名が正しくても古いイメージなら拒否する(ロールバック防止)
受信しながらハッシュ、検証、バージョン比較、切替の順

5. パターン D — 装置間の暗号化通信

要件: ゲートウェイとセンサー間で、盗聴・改ざん・なりすましを防いだ通信を自前プロトコルで行う(TLS を使えない無線など)。

設計(簡略化した TLS 1.3 の形):

  1. 両者は相手の長期署名公開鍵を事前に持つ(製造時登録、または証明書)
  2. 接続開始: 各自が一時 ECDH 鍵ペアを生成し、(一時公開鍵 ∥ 乱数) に長期鍵で署名して送る
  3. 受信した署名を検証し、psa_key_derivation_key_agreement() で共有秘密を KDF に入れ、両者の乱数を salt に、方向を info にして送信鍵・受信鍵を導出する
  4. 以後、AEAD でカウンタノンスを使って通信する。カウンタは方向ごとに独立
  5. 一定回数ごとに 2 からやり直す(鍵の更新)

要点:

パターン D — 装置間の暗号化通信(簡略化した TLS 1.3)① 一時 ECDH 鍵ペアを生成し、(一時公開鍵 ∥ 乱数) に長期鍵で署名して交換② 相手の署名を検証(登録済み公開鍵)中間者の排除③ key_derivation_key_agreement → HKDF(salt = 両者の乱数、info = 方向)→ tx 鍵 / rx 鍵④ AEAD でカウンタノンス通信。一時鍵は destroy。一定回数で①へ前方秘匿性と鍵の更新可能なら DTLS / Noise の既存実装を使い、PSA 鍵は mbedtls_pk_setup_opaque で渡す
一時鍵で秘密を作り、長期鍵で相手を確かめ、KDF で方向別の鍵にし、AEAD で運ぶ

6. パターン E — センサーデータの改ざん防止

要件: 暗号化は不要だが、記録されたデータが後から書き換えられていないことを保証したい。

設計:

「否認防止」(装置が「そんな記録は出していない」と言えないようにする)が要件なら、MAC ではなく署名(09 章)を使う。ただし署名は 1 レコードあたり数 ms かかるので、まとめて(1 分分のレコードのハッシュに)署名する。

7. パターン F — 製造時の鍵注入と個体化

要件: 何万台もの装置に、装置ごとに違う秘密を安全に持たせたい。

設計 — 2 つの方式:

方式手順長所短所
装置内生成初回起動で鍵ペアを生成し、公開鍵だけ取り出して登録秘密鍵が装置の外に一度も存在しない公開鍵の回収と登録のラインが要る。対称鍵には使えない
導出注入製造ラインの HSM がマスター鍵から HKDF(master, info=シリアル番号) で装置鍵を計算し、psa_import_key() で永続鍵として書き込むサーバはマスター鍵とシリアル番号だけで全装置の鍵を再現でき、鍵データベースが要らないマスター鍵の管理が要(HSM)。注入経路(治具と装置の間)の盗聴対策が要る

要点:

パターン F — 製造時の鍵注入装置内生成(非対称)初回起動で psa_generate_key。公開鍵だけ取り出して登録。秘密鍵は装置の外に一度も存在しない。対称鍵には使えない導出注入(対称)製造ラインの HSM が HKDF(master, info="dev-key/v1/"∥serial) を計算し、psa_import_key で永続鍵に。サーバは同じ計算で再現できる注入コードは製品ファームウェアから外す。注入した鍵は EXPORT なし。info に用途と世代を入れる
非対称は装置内で生み、対称はマスター鍵から導出して注入する

8. パターン G — 健全性の証明

要件: サーバが「乗っ取られていない、正規ファームウェアの装置」だけを受け入れたい。

設計: パターン A の TLS 接続後、サーバがチャレンジを送り、装置は psa_initial_attest_get_token() の結果を返す(14 章)。 サーバは署名・Nonce・ライフサイクル・ソフトウェア構成要素を検証し、合格した接続だけにデータや鍵を渡す。

TLS の認証(パターン A)が「鍵を持っているか」、アテステーションが「何を動かしているか」——2 つは補完関係であり、両方あって初めて「正規の装置が正規のソフトで動いている」と言える。

9. 共通の設計チェック

どのパターンでも、実装前に次を紙に書き出す。

  1. 鍵の一覧: 名前、type、bits、usage、algorithm、lifetime、ID、生成方法(generate / import / derive)、誰が公開鍵を持つか
  2. ノンス・カウンタの管理: 誰が作り、どこに保存し、再起動でどうなるか
  3. 失敗時の動作: 復号失敗・検証失敗で何をするか(工場出荷状態、ログ、拒否)
  4. 鍵の更新: 更新の手順と、更新中に電源が切れたときの状態
  5. ストレージの位置: ITS / PS / 通常のフラッシュのどれに何が乗っているか。フラッシュを丸ごと読まれたとき何が漏れるか

10. 手を動かす

要件から呼び出し列を組み立てる


この章のポイント