ぼちぼち日記

おそらくプロトコルネタを書いていることが多いんじゃないかと思います。

「SSL/TLS暗号設定ガイドライン 第2.0版」を読んで

1. はじめに

昨日「SSL/TLS暗号設定ガイドライン 第2.0版」が公開されました。 前回から約3年経って今回はCRYPTREC暗号技術活用委員会で検討作業が行われたようです。

普段、TLS/HTTPSの記事を書いたり発表したりしている立場上、これを見逃すわけにはいけません。

本文冒頭では、

「本ガイドラインは、2018 年 3 月時点における、SSL/TLS 通信での安全性と可用性(相互接続性)のバランスを踏まえた SSL/TLS サーバの設定方法を示すものである。」

ということなので、できたてほっかほっかの最新ガイドラインを読ませていただきました。

読み進めてみるとChangelogが細かく書いてなく、以前のバージョンとどこがどう変わったのかよくわかりません。TLS1.3とかは絶対に新しく入った内容なんですが、細かいところはどうだろう… それでも全部(SSL-VPNを除く)をざっと読み通したので、いくつか気になった部分があったのでコメントしてみたいと思います。

このガイドラインの大きな特徴は、「高セキュリティ型」、「推奨セキュリティ型」、「セキュリティ例外型」の3つの基準に別れていることにあります。ですがこの分類方法や要求設定の違いに関しては、コメントしないことにします。個人的にはいろいろ思うところはありますが、結局はサービス提供範囲とリスク見合いになり、あまり技術的にはっきりした主張や議論になりにくいなと思うからです。

2. TLS1.3の説明について

SSL/TLSの概要説明のところでTLS1.3の説明が書いてありました。記述内容(図)がおかしそうなところが2点ほどありましたので書きます。

2.1 鍵スケジュール (TLS1.3の概要 (7) 鍵スケジュールの図)

TLS1.2では、暗号やMAC鍵の元となる MasterSecret は、鍵交換で生成したPreMasterSecretとサーバ・クライアントの乱数をPRF(擬似乱数関数)にかけて導出していました。

ただこのような生成方法だと Triple Handshake攻撃 を受ける恐れがあり、セッションハッシュを使う 「RFC7627-Extended Master Secret 」が、対策として出されています。

TLS1.3では、さらにHMAC方式など暗号技術で超有名な Hugo Krawczyk 氏が考案した OPTLS をベースとした鍵スケジュール方式が採用 されています。 これは、「RFC5869-HKDF」というKDF(鍵導出関数)を使い、用途別(0-RTT用、ハンドシェイク用、アプリデータ用等)に鍵を生成していく手法です。

ガイドラインでは、

f:id:jovi0608:20180509135609p:plain
SSL/TLS暗号設定ガイドライン p14より引用
と書かれており。上図の通りHKDFを使って、3種類に色分けされた計9個の鍵が導出されているのがわかります。

で、

EarlySecret(ES) = HKDF-Extract(PSK, 0)
HandshakeSecret(HS) = HKDF-Extract((EC)DHE, x)
MasterSecret(MS) = HKDF-Extract(0, x)

の部分ですが、RFC5869では、

HKDF-Extract(salt, IKM) -> PRK

と定義されています。HKDF-Expand関数にsalt, IKM(入力鍵) を引数に入れると、PRK(疑似乱数鍵)が出力されるということです。

一方、TLS1.3仕様の該当箇所では、

HKDF-Extract is drawn as taking the Salt argument from the top and the IKM argument from the left

HKDF-Extractは、Salt引数は上から、IKM引数は左から取るように書かれている。

と記載されています。そうなると上から来てる0とかxとかの方がsalt になります。なのでガイドライン記載の引数が逆で、

EarlySecret(ES) = HKDF-Extract(0, PSK)
HandshakeSecret(HS) = HKDF-Extract(x, (EC)DHE)
MasterSecret(MS) = HKDF-Extract(x, 0)

が正解じゃないかと思います。これ間違うと鍵交換後にエラーって、めちゃハマります(体験談)。

2.2 ハンドシェイクの暗号化開始個所 (TLS1.3の概要 (8) TLS1.3の暗号化開始個所)

次に、下図の「TLS1.3でここから暗号化する」の部分ですが、一番初めに入るEncryptedExtensins が抜けています。

f:id:jovi0608:20180509135615p:plain
SSL/TLS暗号設定ガイドライン p14より引用
TLS1.3仕様の該当箇所では、

In all handshakes, the server MUST send the EncryptedExtensions message immediately after the ServerHello message. This is the first message that is encrypted under keys derived from the server_handshake_traffic_secret.

全てのハンドシェイクでは、サーバはSeverHelloメッセージの直後にEncryptedExtensionsを送らなければならない(MUST)。これは、 server_handshake-traffic_secretから生成した鍵で暗号化される最初のメッセージである。

なのでMUSTです。TLS1.3仕様の図でEncryptedExtensionsに (*) Optionalが付いてなかったのを見落としちゃったのかもしれません。

2018年5月13日追記: よく見たら左側TLS1.2の図もおかしいです。TLS1.2ではChangeCipherSpecが暗号化開始の合図なので Finished も暗号化されています。Finishedも赤字にするのが正確でしょう。

3. ECDHEの要求仕様について(X25519 253bitが適応外になる!)

今回一番声を大にして言いたいのはここです。

高セキュリティ型、推奨セキュリティ型、セキュリティ例外型の全て要求仕様において、以下の通り「鍵長256ビット以上のECDHE」が求められています。

f:id:jovi0608:20180509135624p:plain
SSL/TLS暗号設定ガイドライン p24より引用
これは、本文中で例示してあるようにNIST P-256(secp256r1)の導入を前提としているかと思われます。

ここで昨年秋 Internet Week 2017で私がプレゼンした「運用の観点から見たTLSプロトコルの動き」の資料とくらべてみましょう。 f:id:jovi0608:20180509155408p:plain ガイドラインで要求仕様に入っているDHEは、私の資料では黄色(注意)にしています(理由は後述)。また青色の部分はガイドラインに入っていません。 CRYPTRECはNISTと異なり推奨楕円曲線を規定していません。ガイドライン中でもNIST-P256は一例として書いてあり、鍵長条件を満たすECDH方式なら楕円曲線の種類は問わないように読めます(少なくともこのガイドラインでは、NIST curveに限ると明確に書いていません)。256bit以上という条件では、253bitのX25519が適応外になってしまいます。

思わず、

とつぶやいちゃいました。換算が曖昧なセキュリティレベルでの規定(128bit相当)ならいざしらず、ちゃんと計算できる鍵長で、たかが3bitだからといい加減にできないのではないかと思います。

RFC7540-HTTP/2仕様では、「利用するEC鍵長は224bits以上でなければならない」と規定しました。これは当時仕様策定中のX25519が使えることを考慮して決めた値です。 (Re: ECDHE security level)

また、RFC7525-Recommendations for Secure Use of TLS and DTLSでも192bits以下は使うべきではないとの規定です。ガイドラインが求める鍵長256bit以上ではX25519を使えず、同程度のセキュリティレベルのRSA2048やDHE2048が使えるのに比べて、少し厳しいのではないかというのが自分の意見です。

これからの事を考えるとやっぱりアカンと思い、X25519がどういう経緯で作られ、現在どうなっているのか、少し解説したいと思います。 (書いてみたら膨大になってしまったので最後の節に回します。)

4.「サーバ証明書で考慮すべきこと」について

Sigh.. 思いっきり footgun になってます。

ちなみに文中の www.cryptrec.go.jp へのリンク先は全て http:// で記載されています。

5. DHEについて

DHEの取り扱いについては、先に書いた通りガイドラインと私の評価が少しずれています。よくよく読んでみると少し記述がおかしい部分も見られますので、そこをコメントさせていただきます。

5.1 明示的に鍵長を指定できない代表例のアップデート

以下に2例が示されていますが、最新の状況では条件によりますが、DHE鍵長の指定ができるようです。実際に試して検証をしていないのでポインターだけになります。

f:id:jovi0608:20180509135644p:plain
SSL/TLS暗号設定ガイドライン p46より引用

http://tomcat.apache.org/tomcat-8.0-doc/ssl-howto.html#Troubleshooting

If you are using the APR/native connector, starting with version 1.1.34 it will determine the strength of ephemeral DH keys from the key size of your RSA certificate. For example a 2048 bit RSA key will result in using a 2048 bit prime for the DH keys.

APR/native connector を使えばRSAの鍵長に合わせてDH鍵長も変えられる。

https://support.microsoft.com/en-us/help/3174644/microsoft-security-advisory-updated-support-for-diffie-hellman-key-exc

(訂正: 2018/5/10:18:30) リンクが間違っていました。正しくはこちらです。ご指摘いただいた @ さんありがとうございました。

https://technet.microsoft.com/ja-jp/library/security/3174644.aspx

https://docs.microsoft.com/ja-jp/windows-server/security/tls/tls-registry-settings#keyexchangealgorithm---diffie-hellman-key-sizes

レジストリを変更すればDH鍵長も変えられる。

5.2 DHEの鍵長の決まり方

DHEで利用する鍵長の決定方法についての記載が、非常におかしく思います。

f:id:jovi0608:20180509135650p:plain
SSL/TLS暗号設定ガイドライン p46より引用
の部分ですが、TLS1.2(RFC5246)の範囲では、DHEでは鍵長を交換する仕組み自体がありません。 f:id:jovi0608:20180509141107p:plain 上図の通り、サーバ側が勝手にDHのパラメータをクライアントに投げるだけです。クライアントがサポートされていない鍵長だとハンドシェイクエラーになります。

プロフェッショナルSSL/TLSから該当部分を一部引用してみましょう。

f:id:jovi0608:20180509204129p:plain
プロフェッショナルSSL/TLS p38より引用

この問題を解決するために、FFDHEと呼ばれる新しい仕様 RFC7919-Negotiated Finite Field Diffie-Hellman Ephemeral Parameters for Transport Layer Security (TLS) が策定され、TLS1.3にも取り込まれています。

それは、ECDHEと同様にDHEのパラメータを名前付けし、ClientHelloのExtensionでECDHE/DHEともにサポートするDHEグループリストをサーバに伝える方法です。 f:id:jovi0608:20180509141121p:plain これですと、サーバはクライアントがサポートされているDHグループを判断し、鍵交換を行うことができます。 しかしRFC7919をサポートしているブラウザは私の知る限りまだ見ていません(誰が知っていたら教えてください)。

5.3 結局DHEを推奨すべきかどうか

このように現状のDHEは、鍵長交換ができないと言った大きな欠点があります。またDHEの演算性能や必要となるデータ量などECDHEに比べて全くメリットがない状況です。以前はECDHEのパテントリスクを避けるため、Foward Secrecyを実現するためにDHEの需要がありました。既に幾つかのパテントがexpireし、X25519の利用も見えてきました。現在ChromeFirefoxでは DHEのサポートを取りやめています。

かと言って全くDHEを捨て去っていいかというわけではなく、ECDHEのバックアップとして必要です。TLS1.3ではFFDHEが取り込まれているので、ECDHEに何かあった時用に緊急避難用のアルゴリズムとして残しておく必要性があると思います。

従ってFFDHEが使えない現状で、TLS1.2でのDHE利用には、私の評価は黄色(注意)を付けています。

6. X25519はどうなのか

X25519ができるまでの経緯を書いてみます。

6.1 Dual_EC_DRGBのバックドアとNIST P-256の闇

NIST-P曲線は1999年にNISTによって規定されました。規定にはNSAが関わったという話です。

少し後(2000年)に楕円曲線を利用した疑似乱数生成仕様 Dual_EC_DRBGNSAの協力の元でNISTを策定を進め、2005年に規定されました。しかし2006,7年頃にこの乱数生成仕様にはバックドアがあるのではないという研究発表が出てきました。

Dual_EC_DRBGは、ある特定の2つの楕円曲線上の点を元に疑似乱数を生成していく仕組みです。 バックドアとみなされていたのは、この2つの楕円曲線上の点の関係が計算できていれば、表に出ている乱数から生成器の内部状態を再現でき、次の乱数が予測できるというものでした。

TLSでは内部の秘密鍵の生成にも疑似乱数を使用します。これが外部から予測できればアウトです。実際にNSAが本当にバックドアを狙って仕込んだのかは、わかりません。でもこの2つの楕円曲線の点はNSAの技術者からNISTへ提案を受けたものだという証言が残っています。

また、2004年にNSAから1000万ドルかけてRSA社のライブラリにこの擬似乱数生成を入れ込み、実際に販売してたことも判明しました。2013年のスノーデン事件で明るみになった情報の中にも、NSAが標準化作業に入り込み、バックドアの仕込みをやっていたことを匂わすような記述が見受けられたそうです。まぁ、状況証拠的には真っ黒です。ほどなくDual_EC_DRBGは廃止され、使われることはなくなりました。

話は変わって NIST-P256。これも楕円曲線のある一つの変数が、出どころのわからない数値にSHA-1ハッシュをかけて生成したものでした。果たしてこれがバックドアにつながるのか? 現在これ以上のことはまだわかっていません。でも、Dual_EC_DRBGの例を見れば、非常に疑わしいのは明らかです。

6.2 IETF curve(curve25519/curve448)の策定

このような状況から、2014年7月にIETFではTLS WGからCFRGにNIST標準によらない鍵交換とデジタル署名用の楕円曲線暗号を選定するよう依頼が行われました。[Cfrg] Formal request from TLS WG to CFRG for new elliptic curves

当初2ヶ月程度で選定を終わらせる予定が、様々な要望や提案が入り混じり、案の定大議論が沸き起こりました。すったもんだの末に半年かかってdjb氏が考案した curve25519 が最初の候補として採用されることになりました。 (Adoption of draft-agl-cfrgcurve-00 as a RG document) これが今のX25519につながります。

djb氏が考案したためパテントに対するリスクも小さく、係数も数学的判断を元に決定されています。ソフトウェア処理でもそこそこ高速できるように工夫され、できるだけ簡潔な演算ができるようになっています。NIST-P256は複雑で、サイドチャネル攻撃を回避して高速化をするためには、非常に苦労します。それとは、大きく性質が異なります。

名前は、

と区別する関係になっています。

最終的により大きな鍵長をもつ curve448(Goldilocks)を加え、2016年1月にRFC7748-Elliptic Curves for Security として無事 curve25519/curve448と鍵交換のX25519/X448が仕様化されました。デジタル署名の仕様も Edwards-Curve Digital Signature Algorithm (EdDSA)として仕様化が完了しました。これでTLS1.3に向けてIETFが選定した楕円曲線が使える環境が整いました。

ざっと比べてみるとこんな感じです。 f:id:jovi0608:20180509155535p:plain

6.3 X25519の普及度

X25519は、Chrome, Firefox, Opera, Edgeで既に使えるようになっています。ブラウザベンダーの危機感は大きく、クライアント側の普及は早いです。

サーバは、OpenSSL-1.1.0系から使えるようになっています。X448はOpenSSL-1.1.1が必要です。

現在、X25519がどの程度使われているのか、最近の計測結果を見つけましたので紹介します。 Chasing X25519 Usage of insecure curves still common では Alaxa Top 100 でなんと38%対応済。Alaxa Top 1万で8.73%程度です。Top 100 の方はGoogle系のサイトが多いからだと思われます。

In search of CurveSwap: Measuring elliptic curve implementations in the wild の統計だと2017/08の時点でX25519が2.6%, NIST P-256が86.9%の割合でした。来年末OpenSSL-1.0.2のEoLなので、OpenSSL-1.1.x系に入れ替えが進むと一気にサーバ側の普及が進むものと思われます。

現在、Google系以外の比較的規模が大きなサイトでは、wikpedia やMS系のサービスがX25519が優先されるようにサービスを提供しています。 f:id:jovi0608:20180509195629p:plain

6.4 X25519の性能

気になるX25519の性能ですが、他の楕円曲線暗号の鍵交換とくらべてどうでしょうか?

今月リリース予定のOpenSSL-1.1.1のpre6版で比較してみます(AVX/AVX2入りCPUです)。 f:id:jovi0608:20180509135656p:plain おぉ! X25519の方がNIST P-256より約1.5倍近く速いです。X25519は、OpenSSL-1.1.1でかなり高速化されているので、適切なセキュリティ強度で申し分ない性能が得られると思います。

6.5 NISTの推奨楕円曲線

NISTじゃない楕円曲線暗号を策定したのですが、なんとこの成功を受けNISTがcurve25519/curve448を推奨楕円曲線として採用する予定であることを明らかにしました。 Transition Plans for Key Establishment Schemes using Public Key Cryptography 近いうちにNIST SP 800-186が発行されるでしょう。

今後も NIST-P256 を信じるか、信じないか、あなた次第です。

TLS1.3ではNIST P-256がMUST、X25519がSHOULDの実装になっています。高性能で程よい安全と、そして大きな安心を得られ、今後普及が見込まれるX25519を入れられないガイドラインは非常にもったいないなと個人的に思うのです。