2020年3月31日火曜日

2019年度未踏&研究体験記(BI-SGX)

2019年度未踏IT人材発掘・育成事業に「生命情報解析向けインタプリタを搭載した秘密計算用クラウド」のテーマで採択されておりましたaosでございます。


私はこのプロジェクトにおいて、Intel SGXという技術を用いて、主に生命情報解析向けの秘密計算クラウド「BI-SGX」を開発しました。BI-SGXの詳細については、以下の記事を御覧下さい。



本記事では、未踏に採択され9ヶ月間開発を行っての所感や、同時に研究室において展開された指導教員との熾烈なバトル非常に有意義なやり取りについて書き散らそうと思います。


未踏申し込み~採用まで

元々、未踏に申し込んだのは所属している研究室の指導教員からの勧めがきっかけでした。というのも、実は私自身非常に逆張りといいますか、悪い意味で極度に保守的な性格で、「どうせ俺の開発なんて採択されないだろ」「そういう環境は概してITイキリオタク(SNS等でひたすら恣意的にIT知識をひけらかして自己満足している人種)が多そうだから嫌だ」くらいの印象を抱いていました(荒唐無稽すぎる偏見)。


よって、M1終盤までは大学院の研究としてBI-SGXの開発を進めるつもりでした。しかし、ありがたいことに相当BI-SGXに可能性を見出してくれたのか、未踏への申込みをかなり推されたので、ちょっくら申し込みしてみるか、と考えた次第です。


1次審査(書類審査)向けの書類の作成

それまであくまでも生命情報解析や秘密計算といった分野の人間に対する発表や説明を行っていたため、より広い分野の方々を対象としたこの書類は大分骨が折れました。そもそも、Intel SGXとか言うカスを万人にわかるように説明するのが極めて困難なのもあって、正直最終的に仕上がった書類もわかりやすいものとはかけ離れた出来だったと思います(笑)。


しかし、その時点でRAによるホスト間認証及び鍵交換を実行する部分や、Enclave内で駆動可能なインタプリタを実装済みだったため、かなり系統立った、かつ高めの実現性を匂わせられる書類にはなっていたと思います。


当然、書類には書いたけれども実装しなかった(これは合理的判断に基づき棄却したものです)要素や、逆に書類には書いていないけれどもゴリゴリに実装したものもあるので、ガチガチに辿るべきロードマップを記載しなければならない、とは考えなくて良いと思います(雑なのは当然良くないと思いますが)。


また、自己紹介的な項目では割と個を出す感じで書きました。例えば趣味の欄では、たまに触っているMOS6502アセンブリ(いわゆるファミコンプログラミング)の話や、ファミコン上で直接再生できる音楽の作曲とかを書いた気がします。何と言いますか、あまり参考にはならないかも知れませんが、未踏の場合堅すぎない事も重要なのかな、とは感じました。


ちなみに、指導教員に書類を見せた所、落合陽一さんの学振かなんかの申請書類を引き合いに出されボロカスに叩かれましたが、ほぼそのまま提出しました(笑)。


2次審査

指導教員にはボロクソに言われましたが、ありがたい事に無事1次審査を突破しました。


次は2次審査でプレゼン審査をしなければならないので、当然綿密に発表資料を作成しました。私の場合特異かも知れませんが、私はあくまでも「2次審査で専門的な質問をされても対応できる事」は全く念頭に入れておらず、「如何に提案するシステムを凄そうに見せるか」に全力を注いでいました(笑)。


というのも、Intel SGXという技術に関しては、唐突のイキリですが少なくとも日本中のどの大学院生よりも自分が精通している、と自負していたので、審査で言い負かされる気がしなかったからです。


しかも、私の指導教員による日頃の詰めが苛烈そのものであり、1ミリでも分からない部分があれば些末な部分であっても猛攻を受け、納得させるまでひたすらに答えていかなければならない、という非常にストイックな環境におかれていました。SGXのRAについて説明した時は、3時間くらいひたすら問答を繰り返して最終的にしぶしぶ納得してもらった経験もあります。ですので、未踏とは言えこれ以上に苛烈な質疑応答は課してこないだろ、と確信していたので、より「詰め」に対する警戒感は持っていませんでした。


反面、「如何に凄そうに見せるか」については大分苦心しました。生命情報解析という情報科としてはニッチな分野をメインターゲットにし、更にSGXという日本人でやってる人間いるのか?みたいな技術を使っていたので、PMの方々に未踏として意義のある提案であると示せるか、という不安はありました。


ここで、「如何に凄そうに見せるか」は、「如何にわかりやすく説明するか」とは決して等価ではありません。SGXがニッチすぎるという一見欠点にしか見えない要素は、上手く使えばより効果的に凄いことを目指していそう、と見せつけられるという利点にもなり得るのです。


よって、最初は生命情報解析における秘密計算の必要性や、既存技術の実用性の欠如をわかりやすく説明した後は、ある程度専門的にSGXを説明しました。その中でも、Enclaveにインタプリタを載せる世界初の試みをする、など、直感的にわかりやすいフレーズも加える事で、わかりやすさのギャップを利用して効果的に印象を高められるようにしたつもりです(とはいえPMの方々にはとうに見破られていそうですが笑)。


質疑応答は、やはり指導教員によるものとは正直遠く及ばないレベルで、全て自分の知識や経験で余裕を持って回答できる、ある意味ベタなものが多かったです。また、特にこの時点から竹内統括PMからはかなりの絶賛を頂いており、非常に心強かったのを鮮烈に覚えています。


未踏における開発作業

ある日、未踏事務局さんからメールが届いたので確認した所、無事未踏プロジェクトとして採択して頂きました。その喜びようと言ったら凄まじく、下の階にいる母親に「お前大丈夫か?」と心配されるレベルの奇声を上げていました。正直、第一志望の内定が決まった時よりも断然喜んでいたと思います(笑)。


未踏での開発は、週毎に作業した分の報告をしなければならないので、怠惰な性分の私には非常に相性が良かったです。サボればそれだけ予定していた進捗から遠ざかるので、凄くいい形で開発を継続できていたと思います。ただ、当然開発のロードマップは自分で自分自身の限界と照らし合わせながら組み立てたものなので、首が絞められるような事は一切ありません。あくまでも、怠惰な人間が正常な人間らしく開発を進める為のいい手助けとして働いてくれた、と自分は感じております。


開発は、ひたすら家で一人でしていました。研究室のマシンにリモートで接続し、CUI上で無限にコーディングやデバッグ、テストを繰り返しまくるイメージです。


未踏で享受できる恩恵の使い方

未踏で採択してくれるPMは、必ずしも自分の分野に精通している人間とは限りません。寧ろ、そのような制約が仮に存在すれば、未踏はかなり狭苦しいものになってしまうでしょう。


よって、必然的に、私は未踏に対して開発において用いる技術を使いこなす・理解する為の補助としての役割は一切要求していませんでした。何故ならば、SGXについては絶対的な自信があったからです。BI-SGXの構成要素である言語処理系などについての知識は未熟でしたが、それをSGXに組み込むというステージに踏み込む人間はまあそうそういないので、あくまでも開発に使用する技術の知識については全て今までの自分の知見と独学を頼りにしていました。


反対に、開発手法に関してはかなりお世話になりました。特に、私を担当してくださいました藤井PMはIT系ビジネスのプロ中のプロで、当然開発手法についても精通しているので、今まで野生児同然な開発をしていた所を、垢抜けたアジャイル開発を出来るようになる為にとても丁寧にご指導頂けました。


人によって特に享受できる部分は大きく異なるとは思いますが、特に私のように野生児じみた開発者に足りていないスキルを成長させてくれる基盤は非常に充実しているな、と未踏を経験して強く感じました。


進捗報告会や会議

未踏では、おおよそ月ごとに開催される小規模な「進捗報告会」と、OBや外部の方々も呼んでの「会議」が存在します。


成果報告会に関しては、主にPMによる質問が(私の場合は)多かったです。やはり、ビジネス展開を考えた時の展望について聞かれる事が多く、「BI-SGXのペルソナはどういう人なのか」「開発できている部分とそうでない部分をより明確化に視覚化すべき(ユーザストーリーマッピングの利用)」と言った指摘をPMから受ける事が多かったです。


反面、SGXを始めとした技術や、BI-SGXについては正直並外れた知識を固めていたので、開発技術面ではほとんど質問される事はありませんでした(あってもインタプリタのパフォーマンスについての質問が殆ど)。


「会議」では、藤井PMのように開発手法について緻密にアドバイスして下さる方がOBや来客、及び同期には少ないため、より独壇場感が強まっていました。しかし、オーディエンスが多い分より専門性の高い方がいらっしゃる確率は増えるわけで、現に医療系・バイオ系の方からは踏み込んでおりかつ非常にありがたいご指摘を頂けました。特に、7月のブースト会議でバイオインフォマティクス系のOBの方から頂いた指摘は、秘密計算クラウドとして根源的な存在意義を果たす上で当時のBI-SGXの機能が致命的に欠如していた事を示して下さっており、後にGWAS機能を実装する事を決定する大きな手助けとなりました。


また、発表手法に関しては可能な限りオーディエンスの笑いを取れるようにしました。SGXのゴミカスさに対し皮肉じみた罵倒をしながら面白おかしく説明したり、様々なパロディネタを取り入れたデモ動画を流したり(詳細は前回記事参照)、オーディエンスを笑わせられたモン勝ちだなとは思います。

v.s. 指導教員

未踏への申込みを勧めてくれ、研究室において恩人である指導教員ですが、実は少なからずいざこざがありました。というのも、未踏における開発作業は全く苦ではなかったのですが、研究室での研究作業がひたすらに苦行であった為です。


ここで先に断っておくのは、指導教員は決して悪意があったわけではないという事です。ただし、指導教員が教授なだけあって生来の天才である事、そして極限状態に置かれた私が苛まれたパラノイアに起因して、最悪な形で軋轢が生じてしまったのです。


未踏に採択された為、未踏の開発内容を研究室での研究に流用する形を取っていましたが、正直情弱な自分にとっては指導教員によるタスクの要求は苛烈でした。この軋轢には2フェーズ存在するので、それぞれ紹介しようと思います。


第1フェーズ

まずは、8月・9月です。この時、指導教員はNDSSというカンファレンスに出せるように、BI-SGXにおけるGWAS機能の実装を早く済ませるように強く求めていました。


しかし、前回・前々回の記事を読んだ方はご存知の通り、SGXプログラムの開発は鬼のような難易度を誇ります。Enclave上でGWASを動作させる事は勿論、GWASに利用するデータを適切な形でロード・整形する事ですら、血反吐を吐くような労力が要求されます(寧ろ後者の方がしんどい)。


しかし、指導教員はSGXの専門家ではないので、「この程度のGWASくらい簡単に出来るでしょ」くらいの感覚で締め切りを念押ししてきます。


いや、無理です。


そう言えればよかったものの、私にはそう発言する勇気はありませんでした。相手は天才の教授だし、そもそも私は意見をするほど気の強い人間ではありません。なので、私は言われるがままに、未踏では到底要求されないようなペースで開発を進めました。


結果、SSHクライアントを見るだけで吐くようになりました。


でも、それでも指導教員に言い出す勇気はありません。なので、私はプログラムを開発する時は胃を完全に空にした状態で作業する事で、少しでも嘔吐による弊害を軽減するように努めました。


しかし、人間限界があり、ついに指導教員に期日までの実装が無理である事を伝え、NDSSは残念ながら見送りになりました。


第2フェーズ

私という人間は極めて気が弱い人間で、上記のような経験を経ても無理に我慢する癖を直せずにいました。NDSSが流れた後、指導教員は10月頃にUSENIXへの投稿を勧めてきました。この時、私はBI-SGXへのGWAS関数の実装は終えていた(一部に関しては、研究テーマに困っていた同期にBI-SGXの共同開発を無理矢理教授に提案され、その同期が非SGXでも動くようなGWASアルゴリズムを記述し、私がSGXで動くように最適化した)ので、提出は英字論文さえ書けば容易だと最初は思っていました。


しかし、指導教員はBI-SGXに対して「このままでは足りないね」と宣います。


いや知らねぇよ


指導教員は、セキュリティ施策上BI-SGXがVCFチャンクを全走査で読み込んでいる部分(オーダにしてO(n)というなかなかの好成績である)にイチャモンをつけ、Oblivious RAM(ORAM)というどう考えても実装コストに見合わない高速化手法を要求してきたのです。


ORAMは、ファイルへのアクセスパターンを秘匿するような技術ですが、USENIXに提出するにあたってBI-SGXにはこれが必要であると言い寄ってきました。故に、BI-SGXに寄生協力していた同期がEnclave上で動作するSGXSDKによる縛りを比較的受けないアルゴリズム部分、そして私がORAMアルゴリズムを動作させる為の低レイヤな部分を担当しました。




おわかりでしょうか?指導教員はSGXSDKの残虐さを理解していません。特にSGXSDKが牙を剥く分野がファイル入出力・整形や通信、暗号処理、パースといった低いレイヤである事は当然知りません。よって、何が起きたかというと、


教授「同期はちゃんとORAMを実装してるのに、お前は全然進んでいないよね」


というニュアンスを醸し出した議論をしてきたのです。


しかし、私はこれにも耐えようとしました。同期が乗っかってきて私が提案したBI-SGXが乗っ取られすらしかねない中、咳が止まらないほど体調が悪くても、週7で朝4時までひたすらにSGXコーディングをしました。


その結果、今度はSSHクライアントを前にしただけで手が震え、涙が出てくるようになりました。これを唯一解決できるのがでした。毎日9%の酒を1L飲み、苦痛を麻痺させる事で、何とか未踏では本来要求されていない苛烈なタスクをこなそうと試みていました。


しかしながら、ある日真の限界を迎えました。デバッグしていてバグの原因がEnclave及びソースコードの境界を10回ほど超えた所に存在する事が分かった途端、脳内でプツンと切れる物がありました。「これ以上は無理だ」と感じました。すぐさま同期にはこれ以上無理である旨を伝え、藤井PMに救援を求めました。


当時の私は完全な極限状態であり、「教授が同期を持ち上げようとしており、私を散々にこき使った上に蔑ろにしようとしている」という重度のパラノイアに迫られていました。よって、私は藤井PMに藤井PMから指導教員にストップをかけて貰うように懇願しました。


恥ずかしい話ですが、未踏の他のクリエータの前では決して表さなかったものの、当時藤井PMとビデオ会議して懇願する際、顔面丸写りなのにも関わらず号泣するくらいには精神的にやられていました。泣きじゃくりながら心境を打ち明け、藤井PMに慰めてもらった記憶は色濃く残っています。もし未踏に受かっておらず、藤井PMの支援を受けられずに同じ状況にいれば、恐らく自害していたレベルに追い込まれていました。故に、藤井PMは命の恩人であり、今でもこの上なく感謝しています。


とりあえず、教授に連絡するので一旦休息を得るべきという事、そしてこういった過度な使命感への対処の仕方を藤井PMに助言いただき、ある意味ドクターストップという形でUSENIXへのタスクは中止させてもらいました。


この時、自分の二枚舌じみた側面や我慢しすぎる部分についてのカウンセリングまでしてもらったので、藤井PMには本当に感謝しております。一方で、前述の通り指導教員も全く悪気はなかった模様です。前述の通り限界を迎えた時、割と慇懃無礼な言葉でSlackで教授に心境をぶち撒けてしまった為、ちょっと後悔しています。コミュ障オタクだとろくな事がありませんね(笑)。


最終的に、藤井PMのおかげで、その後は無理のない範囲(未踏で達成すべきタスクとして予定していたロードマップ通り)で、大学院の研究も進めて完了できました。また、大学の保健センターでの臨床心理士によるカウンセリングも受け、今ではピンピンしています。ちなみに修論はSGXのせいで86ページになっています笑


私が伝えたいのは、マジで研究無理をすると死にかねないので、皆さんも十分気をつけて下さい、という事です(笑)。

成果報告会&フィニッシュ

元々大きなイベントの前は理由なく滅茶苦茶に緊張する(それこそ会議でもそうでした)のですが、成果報告会(未踏で最後の発表)では頂点でした。しかし、誰よりもSGXをしばいてきた事、そして研究で並ならぬ苦痛を味わってきた事を糧にし、自分の中では及第点な発表を出来たと思います。


成果報告会では、今までのどのフェーズにも増して「如何に凄そうに見せるか」「如何にわかりやすく説明するか」の両立に苦心しました。成果報告会では今まで以上により広い分野の方々に説明する必要があるので、後者に関してもある程度考慮しなければならないからです。もっとコミュ力が高い人はより上手いプレゼンが出来たと思いますが、コミュ障の私としましては最大限死力を尽くして発表致しました(笑)。


成果報告会で使用したデモ動画を以下に掲載しますので、興味のある方は是非ご覧ください。



多くの闘いを経て来ましたが、少なくとも個人的にはいい形で未踏を終えることが出来たと思います(というか未踏は全く苦ではなかったので、どちらかというと完全に大学院の研究とのバトルでしたが)。BI-SGXもまだまだ未熟なシステムですが、Switchless Callの導入やインタプリタの性能強化などの余地も数多く残されているので、将来性のあるシステムを提供できたかな、とは思っています。


ただし、最近滅茶苦茶に心臓に悪いリーク情報がありまして、


SGXが2020年末のIntel CPU(Rocket Lake-Sアーキテクチャ)から廃止される


という話が流れ込んできたので、正直滅茶苦茶に焦りました。ただ、実際は廃止されたとしても一部モデルでのみ廃止されるにとどまるらしいので、今後の動向次第ですね。正直集中治療室の患者の容態を眺めている気分です。


未踏コミュニティ

未踏には未踏を経験した人間、あるいは未踏関係者(PM等含む)による独自のコミュニティがある、という話があるようですが、私はあまりそれに関しては気にしていませんでした。


何度も言う通り、SGXに関してはありえないほどの自信を持っているので、例えコミュニティが何らかのバイアスを持って質疑応答して来ようが、全て俺様の知識でブチのめしてやろう、くらいの意気込みでした(性格悪いw)


ただ、私は未踏コミュニティという意味では、ひたすらオタク友達を同期のクリエータから見つけて仲良くなり、ひたすら飲み散らかして夜中には散策したり、一生モノの仲間を得る非常に有効な使い方しかしていないと思います。同時に、その中には幸運なことに同期に私と同じく秘密計算をテーマとしていたプロジェクト(準同型暗号によるバーチャルセキュアプラットフォーム(VSP))に取り組んでいた方々もいたので、技術的な意味でも非常に切磋琢磨できました(根本的には同一の思想である秘密計算同士とは言え、達成すべきゴールについてはお互いに宗教が微妙に異なるので割と期間中はプロレスしていましたが笑)


一方で、高レイヤな人たちへの当たりは会議にしろ成果報告会にしろ強めだな、とは感じました。私などは比較的レイヤが低く、SGXとか言うカスなど知ってる人間もいないので「詰め」は受けなかったのですが、高レイヤなプロジェクトをしている人はより質問攻めにあっていたイメージです。


これはもう人間の性だと思うんですが、質疑応答権あるいは発言権を持つオーディエンスとして発表を聞いた場合、より「口を出しやすい」のは高レイヤ、あるいは目的を理解しやすいプロジェクトで、ついついそういった対象に質問をぶつけがちになると思うんです。それでも進捗報告会や会議ではそこまで的外れな質問や意見は出ないんですが、問題は「成果報告会」の「ニコ生コメント」です笑。


私の成果報告会のニコ生でコメントを見ていましたが、炎上覚悟で言わせて頂きますと、まあ酷い事(笑)。私のような秘密計算や同期のVSP、ファジングのような一般的に「理解が難しい」プロジェクトにはへこたれて全然コメント付けないくせに、高レイヤを始めとした少しでもわかりやすいプロジェクトになった瞬間、コメントする側は匿名なのをいい事にまあ酷い。そのプロジェクトが想定している背景や哲学も考慮せず(それどころか内容すらろくに理解せず)、叩きたいだけの人間がナンセンスなコメントをぶち撒け、正直傍から見ていて非常に不快でした。


同期として各人の達成すべき哲学や背景を少なくとも最低限は理解していたつもりなだけあって、不快感甚だしいの一言です。理解のある方によるアドバイスはFacebook Groupにて受けられるので、今後はコメント不可能な形の配信に限定すべきだと私は強く思いました。「ニコ生のコメントはより一般的な人間による意見だ」という意見はあるかも知れませんが、私にはどうにもそうは思えず、叩きたいだけの輩でしかない、という印象です(勿論ちゃんとしたコメントをしてくれる方もいますが)。未踏事務局さん、ここだけは改善して頂ければと思います。


未踏に望むにあたっての心構え

あまりエラそうな事は言えませんが、「自分が絶対的に強い」と思える武器を持つ事が、未踏で上手くやっていく秘訣だと思います。私の場合はそれがSGXでした。これがあるだけで、審査の段階から進捗報告会や会議のような発表の段階まで、大分有利に進められると思います。


勿論オールマイティに強い、という形も全然有りだとは思いますが、私は未踏と研究の経験上、ある程度分野を絞った上で(SGXだったり生命情報解析だったり)、プロジェクトを展開・進捗していくのがより効果的なような気がしました。


冴えないオタクの戯言ですが、未踏を目指している方は是非「弱みを補完する」事よりも、「強みを最強に仕上げていく」事に力を注いでみて下さい。あなたの弱みは付け焼き刃で補完しなくても、担当して下さる経験豊かなPMが必ず教育して下さると思います。



まとめ

私は、未踏を経験して割とかなり満足感を得たと思っています。元々非常に自己肯定感の低い(SGX以外)人間なので、未踏に採択された中で開発を進められたのはかなり精神的な支えになりました。


最後に謝辞ですが、PMの方々や未踏事務局の方々、同期のクリエイタにはとてもお世話になりました。特にVSPのクリエイタの方々には何度もヒントを頂けたので、感謝の限りです。


SGXの経過観察含め、随時Twitter(@dd_cliffford)で発信しておりますので、興味のある方は是非フォロー頂ければと思います。

2020年3月22日日曜日

BI-SGX開発&SGXとの戦闘記録(後編)

こちらは前回記事の続きです。


さて、前回記事ではIntel SGXに対して猛烈な怒りをぶち撒け、SGXを制圧する為にBI-SGXの開発に踏み込んだ、という話をしました。


BI-SGXは、「Bioinformatic Interpreter on SGX-based Secure Computing Cloud」の略で、名前の通り特に生命情報解析に特化したSGXベースの秘密計算クラウドです。何故生命情報をターゲットにしたかというと、所属していた研究室柄というのもありますが、遺伝子情報を始めとした生命情報が「特にバレるとヤバい情報」だから、という理由があります。


いや、折角SGXをブチのめして誰でも使いやすいクラウドを作るなら、最も苛烈な条件のデータを保護してみたくなるじゃないですか。


という事で、BI-SGXでは、BI-SGXに自分のデータをストアする、つまりBI-SGXをクラウドストレージとして利用するデータ所有者」と、そのデータを用いて秘密計算(厳密な「秘密計算」の定義とはわずかに異なる可能性もありますが)を行い、匿名化された統計情報を得ようとする研究者」の2つのタイプのユーザを想定し、それぞれに見合ったセキュアクラウドとしての機能を提供します。


以下に、BI-SGXの概要図を掲載します。


BI-SGXですが、前編で散々SGXをぶっ叩いた通り、「SGX特有の異常な難易度を解決する」事を非常に大きな目的としています。そこで考えたのは、「Enclave内インタプリタを駆動させれば、SGXSDKとか言うカスを使わずにユーザが簡単にSGXのセキュリティを利用できるのでは?」という事です。


何故インタプリタを選択したかについては、ちゃんと理由があります。まず、Enclave(厳密にはEPC)には96MBという苛烈なサイズ制限があるので、あまり重いコンポネントをEnclave内に積みたくない、という理由です。よって、BI-SGXでは、インタプリタの中でもコンパイル結果をメモリ上に直接展開して通訳系ルーチンを介して実行するタイプではなく、直接メモリ上の内部コードに対して再帰的下向き構文解析をかけて実行する、スタックマシンベースの可能な限り軽量なタイプを採用しています。


また、インタプリタ方式を採用する事により、SGXの最大の弱点である「サイドチャネル攻撃」の中でも極めて強力な攻撃である、「Controlled-Channel Attack」(私は勝手に制御チャネル攻撃、と呼んでいます)から防御する事も目的としています。こちらの詳細は後述します。


後は、身も蓋もない話ですが、私自身言語処理系はズブの素人だったので、その上でEnclave内に言語処理系を搭載するという、当時からすれば「本当にこんな事できるのか?」というまさしく「未踏」な状態であったので、複雑すぎる言語処理系は実装できなさそう、と考えたというのもあります笑


インタプリタの実装に際しては、「明快入門 インタプリタ開発」という参考書に非常にお世話になりました。物理的な本は絶版ですが、電子版はまだ買えますので、気になる方は是非買ってみて下さい。


インタプリタを採用した理由の最後に、スクリプトコード(つまりEnclave内の言語処理系が解釈するコード)も保護したい、というものがありました。実は、これは前述の制御チャネル攻撃対策にも直結します。コンパイラを採用すると、コードが保護出来ないため、制御チャネル攻撃を回避するには非常に複雑かつユーザに不便を強いる機構を採用しなければなりません(その最たる例がSGX-BigMatrixというシステムです)。


さて、BI-SGXのインタプリタでは、独自に開発した(厳密には上述の書籍で実装されていた言語をSGX最適化しBI-SGXの目的に合うよう魔改造した)「Qliphoth」という言語を提供しています。以下がパワポで突貫工事で作成したQliphothのロゴです。

Qliphothはヘブライ語で「殻」という意味で、Enclaveが防護する殻っぽいから、って言うのが表向きの理由です。じゃあ裏は何だ、というと、個人的に好きなSCP財団というフィクションサイト繋がりの名前にしたかったからなんですね。


本当は最初、SCP-2000に出てくる「手順ラザルス-01」から取って「Lazarus」って名前にしようとしたんですが(Lazarus自体は聖書に出てくる人物の名前です)、あろうことかまさかのこの名前を使ったシステムが存在していたので、Lazarusの採用は見送ったわけです。


SCPにおける各記事は「ヤバいオブジェクトを収容するための特別収容プロトコルや概要を記載したデータベース」という形を取っており(何の話をしているんだ……)、そのオブジェクトのヤバさ具合に応じてクラスが付与されています(例:Safe, Euclid, Keter)。


その中で、SCP財団が切り札として使えるオブジェクトのクラスが「Thaumiel」なのですが、これをそのままつけても面白くない(し、Thaumielは悪魔の名前なので縁起も良くない)ので、悪魔Thaumielを構成要員としている「クリフォトの樹」から名前を取る事にしました。そう、この「クリフォト」こそが「Qliphoth」です。Qliphothなら、表向きには「殻の意」と言えたので、非常に都合が良かったですね。


独自の言語とした理由は、「アウトプットプライバシの保護」をより系統的に行えるようにするため、です。アウトプットプライバシの保護とは、例えば平均を計算すると言いながら、データ1つのみの平均を計算すると、普通に生データをぶっこ抜けてしまう、といったような、「プロトコルには従ってるけど結果としてまずい情報が抜き出せてしまう」、更に暗号分野的な言い方をすれば「セミオネストな攻撃」からデータを保護する、というものです。


例えば、BI-SGXではデータの集合体であるデータセットの単位よりも細かい粒度では、計算に使用するデータ所有者のデータを指定する事ができません。「これとこれの内積を取れば……」とか、「言語において完璧に阻止っていうのは難しい」というご意見もあったりするのですが、少なくとも現段階ではそのような処理は根本的に出来ないように仕上がっています(これに関しては実際にBI-SGXのコードを読んだり利用して頂くのが一番早い気はします)。


このインタプリタを主軸に、BI-SGXは「Simple, fast, secure」な秘密計算クラウドを実現すべく、「Analyzing, only better.」をモットーに開発されています。以下がよく未踏の発表で使っていたBI-SGXのパッケージデザインです。


これ、如何にもよく出来ているように見えますが、実はこれも結構なオマージュなんです笑


私、あまり聞こえはよくありませんが、Grand Theft Auto Online(GTAO)というゲームが滅茶苦茶に好きで、実に3500時間以上プレイしているくらいにはハマっています。で、
そのGTAOの要素として「The Doomsday Heist」というPvEモードがあります。


このモードは、主人公たちを裏切った、暴走するAIとその開発者から世界を救うストーリーなのですが、そのAI「Cliffford」のパッケージデザインがこれです:



そっくりやんけ


いやまあ、似せたので当たり前です。何回か発表してて気づく人いるかなぁ、思ったのですが、終ぞ確認している限りではClifffordのオマージュである事はバレなかった模様です。ちなみに、TwitterのID(@dd_cliffford)はDoomsDay_Clifffordの意味ですし、アイコンもClifffordのスクリーン上での姿になってます。


また、成果報告会やその他未踏における大きな会議で発表していたデモ動画のBGMも、クレジットを条件に使用できるDoomsday Heistの劇中曲でした。


小ネタはここまでにして、各コンポネントの説明に入りましょう。


遠隔認証・通信部分

BI-SGXでは、前編でも紹介しました、sgx-ra-sampleというIntelによって公開されているRemote Attestation(RA)のサンプルコードを魔改造して、フレームワークのベースとしています。


実は、SGXはBI-SGXの想定するモデルとは真逆で、クライアント側SGXマシンを有しサーバ非SGX側、というモデルを想定しています。


何故かというと、SGXは元々DRM保護のような使い方を想定されていたからです。つまり、例えばビデオ配信サービス(サーバ)が、SGXマシンを有するクライアントのEnclaveに映像を送り込んだり、そのEnclave内でDRM処理をさせる、といったような使い方がデフォルトなのです。


当然、sgx-ra-sampleもこのデフォルトのモデルに準じていますので、BI-SGXのようにサーバ側にSGXを置くモデルに応用するには、通信関係の部分をsgx-ra-sampleから完全に真逆にする必要があります。


これがPythonならいざ知らず、いつの時代やねんみたいな古代のライブラリを使い、しかも前編で紹介した通り鬼のようなクソさを誇る「msgio」が通信を司っているわけですから、ひっくり返すだけでも一苦労でした。


ひっくり返しさえすれば、クライアント(データ所有者や研究者)がクラウドサーバ(SGXマシン)をRAに則って検証し、また鍵交換を済ませる事で、TLS通信の準備を整えます。ちなみに、RAの詳細はこちらの自著記事を御覧下さい。


なお、RAの方向を逆にすると、ちょっとしたセキュリティ上の懸念点が出てきます。そちらに関しては、簡単な説明と対応策を後述します。


しかしIntel、このまま上手くやり過ごしてくれるわけがありません。


ある日、いつも通り開発をしデバッグをすると、RAの途中でエラーを起こすようになりました。HTTPのエラーコードを見ると、どうやらフォーマットエラーらしいのですが、何故急にそうなったのか全くわからないので、sgx-ra-sampleのissueでIntelの研究者に質問しました。


すると、RAを利用するにあたってAPI方式を採用したのに乗じて、無告知で受理するデータのフォーマットを変えやがったのです。


当該部分を直そうとするのですが、sgx-ra-sampleはIntelの書いたコードです。おわかりですよね。目で追って原因部分を修正できるような生易しい仕上がりにはなっていません。


で、どうしたかって?


全部ベースから書き直しだよ
ブッ○すぞIntel!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!



データ所有者用機能

データ所有者用の機能と言えば、言うまでもなくユーザ自身のデータのアップロードとダウンロード機能を提供する、セキュアクラウドストレージとしての機能です。ここでは、msgio.cppの提供するsend関数とread関数を自力で修正した関数を用いて通信を行います(RAではもはや手を出すのも面倒臭いので、元のゴミみたいなsendとreadを使っています)。


クライアント側では、交換したセッション鍵を用いてOpenSSLで128bit AES/GCM暗号化し、サーバに鍵・初期化ベクトル・GCMタグ・Base64化した暗号文(Base64化しないとmsgioのせいで厄介な事になります)・Base64化する前の暗号文長(これもmsgioの魔の手から回避する為の手段です)を送信します。


サーバは、受信したらそれらをEnclave内に入れ、sgx_rijndael128GCM_decrypt()関数を用いて復号します。その後、シーリングという、暗号化に使う暗号コンテキスト、つまり暗号鍵や初期化ベクトル・GCMタグをCPUの回路素子(e-fuse)にストアでき、その暗号コンテキストは署名鍵またはEnclave固有のハッシュ値から導出される、という暗号化機能を使って暗号化します。


シーリングをしたら、Enclaveの外に出し、MySQLにストアしてアップロード完了です。署名鍵に固有なハッシュ値から暗号コンテキストを導出するポリシでシーリングを使う事により、Enclaveがデストラクト、あるいはセッションを切断してセッション鍵が消滅しても、無事に次回接続時以降でもデータを復号(アンシーリング)出来るようにしているのです。


ちなみに、新規登録・ログイン機能でも同様の手段を取っています。つまり、Enclaveにセッション鍵を使った暗号文の状態でユーザ情報を送り、新規登録あるいはログインの照合をします。この時はシーリングは用いておらず、パスワードにのみSHA-256ハッシュをかけてMySQLに保存しています。




……と、ここまでは序の口です


以上の議論は、十分小さいデータを処理する場合のみ当てはまります。何故かと言えば、EPCページは上限が96MBだからです。実際に生命情報解析でよく使われるVCF(Variant Call Format)ファイルは、1データで非圧縮で15.5GBにまで上る事も珍しくありません。実際に、BI-SGXのテストで用いた1000ゲノムプロジェクトの21番染色体のデータは、非圧縮でこのサイズがあります。


Enclaveに入るわけ無いですよね?


幸い、VCFは遺伝子上の1ポジションが1行に対応し、そのポジションについての各情報がタブで区切られています。この「各情報」には、そのポジションについての基本情報は勿論、遺伝子を提供した方の遺伝子情報(SNP)についての情報も含まれています。


1000ゲノムプロジェクトは公開前提に収集され提供されているデータですが、これがもしある大学機関が患者のゲノムデータを集めてアップロードしたものだったら?漏れて良いわけがありませんね。


結局、このバカでかいデータをEnclaveで扱うには、より小さい塊に分割するしかありません。BI-SGXでは、このEnclaveに収まり、十分統計計算も出来るサイズのデータの塊を「チャンク」と呼んでいます。Enclaveの中でチャンク分割するのは現実的ではないので、BI-SGXでは以下の手段を取っています:

  1. VCFを行単位で読み進めていき、所定のチャンクサイズ(BI-SGXでは20MB)に達したら読み込んだ分をVCFチャンクとし、セッション鍵により128bit AES/GCMで暗号化して吐き出す
  2. VCFを全て読み込むまで繰り返す
  3. 出来上がったチャンク群をtarアーカイブしたもの、そしてチャンクそれぞれに対する初期化ベクトル及びGCMタグを格納したバイナリ配列をサーバに送信する
図に表すと以下のような感じです。



サーバは受信したら、tarボール化されたVCFチャンクは展開して保存します。そして、初期化ベクトルとGCMタグのバイナリ配列やチャンク分割数、そしてデータ所有者が任意で登録できる遺伝子情報のメタデータ(人種や疾患情報等)をMySQL上のチャンク管理用テーブルにストアします。また、当然セッション鍵はサーバとクライアントで交換済みですので、サーバのEnclave側でセッション鍵をシーリングし、ファイルシステムに書き出して保存します。


また、チャンク群やセッション鍵は乱数的に生成された16文字の同じ接頭辞を持っており、かつその接頭辞は前述のMySQL上の管理テーブルにストアされるので、リンクが途切れてしまう事はありません。


このデータの読み出しについては、次の研究者用機能の項目で説明します。


研究者用機能

さて、いよいよ研究者用機能の説明ですが、これこそがBI-SGXの目玉であるインタプリタの部分です。


研究者は、Qliphothのスクリプトコードを、データ所有者が(小規模)データを上げるのと同等の手段でサーバにアップロードします。


すると、サーバはそのスクリプトコードを用いて、インタプリタの駆動を開始します。インタプリタの概要図は以下の通りです。


まず、構文解析器が、字句解析器を用いてトークン(自然言語における「単語」に相当する単位で、例えばif文なら「If」、変数なら「Ident」と言った感じで抽出します)を抽出し、より解釈しやすい「内部コード」を構築します。この時、トークン種別だけでは不十分な情報(例えば変数ならその格納されている値)や、関数のアドレス等を、内部テーブルに登録していきます。


内部コードが完成したら、コード実行部分が内部コードに対し再帰的下向き構文解析をかけて実行に移します。


再帰的下向き構文解析というと仰々しいですが、図に表すと以下のような感じです。


コードを文・式/項・因子という階層別の単位で再帰的に考え、トレースバックするイメージで解を取得するイメージです。


Qliphothの文法仕様や組み込み関数はこちらに記載しておりますので、気になる方は是非御覧下さい。


Qliphothの売りの一つとして、(個人で突貫工事で作った割には)多彩な組み込み関数を提供している、という点があります。例えば基本的な数学関数だったり、あるいはEnclave内では封印され、クソみたいな専用APIでしか提供されていない乱数生成機能をユーザフレンドリに提供する関数、そしてデータ所有者が上げたデータを用いた秘密計算を行う関数があります。


小規模データを用いた秘密計算には、現在の所
  • 整数データを用いた平均計算
  • 文字列(ゲノム列)を用いた編集距離計算
  • FASTAデータを用いたアラインメント計算
を提供しています。(まあこれらは正直実用性に乏しいですが……)


これらの処理は、条件に合うデータセットをMySQLから持ってきて、アンシーリングして計算し、匿名化された統計情報をリターンする、というごくシンプルな仕組みに従っています(これでも実装はSGXSDKのせいで相当大変でしたが)。


で、問題はデータ所有者の項目でも上げた通り、デカいデータを扱う関数の場合の話です。データ所有者がバカでかいVCFデータをアップロードしたので、当然研究者はそれを使って秘密計算を行いたいですよね。


そこで、生命情報解析向け組み込み関数として、ゲノムワイド関連解析(GWAS)関数をQliphothでは提供しています:
  • アノテーション検索
  • アリル頻度分析
  • フィッシャーの正確確率検定(FET)
  • ロジスティック回帰(LR)
  • 主成分分析(PCA)
アノテーション検索は、要するに求める遺伝子上のポジションに関する基本情報を照会するものですので、秘密情報は用いません。よって、dbSNPとClinvarという公開DBをダウンロードし、そこから照会する形を取っています。


その他のVCF秘密情報を用いたGWAS関数の動作の流れは以下の通りです。



アップロード時に既にチャンク分割をしているので、条件に当てはまるチャンク(データ所有者が任意で登録したメタデータで判断します)をひたすら逐次Enclaveに読み込んで行きます。


同時に、全てのチャンクの初期化ベクトルやGCMタグが詰まっているバイナリ配列から、対象のチャンクに対応するそれらを抽出し、Enclave内で復号します。そして、strtok_r()という古代兵器を用いて、VCFをパースしていきます。


VCFは前述の通り改行とタブで区切られているので、外側を改行をデリミタとしたstrtok_r()、内側をタブをデリミタとしたstrtok_r()として二重ループをぶん回す事で、各ポジションの各情報を抽出する事が出来ます(前編で述べた通り、streamがEnclave内では一切禁止されているので、これが考えうる限りでの最も効率的な方法でした)。


これにより、各GWAS処理に必要なデータを抽出し、目当ての統計計算を実現します(簡単に言っていますが、このそれぞれのGWASに対応したデータの抽出の実装は、本当に血の涙を流しながら実装していました)。



以上で、大まかなBI-SGXの説明が出来たと思います。より厳密な話は修論で書いているのですが、もし機会があればそちらも公開しようとは考えています。


また、Qliphothにはイースターエッグとして極秘の組み込み関数が存在するので、気になる方は是非ソースコードを読んで探してみて下さい(SGXSDKとか言うカスを使って実装しているので、絶対にオススメはしません)。



余談 - BI-SGXにおけるRA

本来、RAというのは非SGX側がビルドした(ビルドしている時点で非SGX側と言いながらSGXの環境は整っているんですが)Enclave用共有ライブラリをSGX側に配備し、RAにてちゃんと渡した共有ライブラリを駆動しているか、を検証するプロトコルです。


しかし、このモデルはSGX側が秘密情報を持っていない場合のみ有効です。何故ならば、本来のRAでは上記の通り、非SGX側がデプロイしてきた共有ライブラリをSGX側が検証する手立てが無いからです。


あくまでSGXはデータを保護する仕組みであり、コードのバグや悪意のあるコードを打ち消してくれる機能なんてものはありませんから、下手をすればSGX側のデータが悪意のある非SGX側の提供した共有ライブラリにより悪さをされるかも知れません。


ただ、BI-SGXではサーバ、つまりSGX側が秘密情報を持っています。よって、BI-SGXではSGX側、つまりサーバに共有ライブラリのビルドをさせ自分自身に配備させる方式を取っています。


こうなると、「非SGX側がコードを検証できないじゃん!」という意見が出ます。ごもっともです。そこで、現バージョンのBI-SGXではまだ対応しきれていないのですが、クライアントにサーバのイメージをDockerで与える事で、全く同じ環境でビルドする事を可能にし、検証可能性を実現します(RAにおいて正当性の判断基準とするMRENCLAVEという値は、同じソースから同じ環境でビルドすれば同値となるからです)。


このDockerを使うアイデアは、後で紹介する、未踏で同期で「準同型暗号によるバーチャルセキュアプラットフォーム」を開発されていた方によるアドバイスで確立されたものです。感謝。



余談 - BI-SGX v.s. 制御チャネル攻撃

ここで、高い火力を誇ると説明してきた「Controlled-Channel Attack(制御チャネル攻撃)」の説明をします。


まず、制御チャネル攻撃では第1段階として、対象とする保護システムを利用したアプリケーション(SGXアプリケーションが最たる例です)をオフライン解析(要するに攻撃者の手元で実験的に攻撃対象のアプリケーションを動作させる解析)します。そして、条件分岐先のどの変数や関数がどのページアドレスに乗るかを把握します。


次に、実際に攻撃対象が実行されたら、オフライン解析で得たページアドレスのページにアクセスされた瞬間、強制的にページフォルトが発生するように工作します。具体的には、例えば対象のページテーブルエントリの第51bit目を立てる事によって、これを実現します。


この状況で条件分岐が発生すると、当然当該ページアドレスにてページフォルトが発生します。こうなると、攻撃者は予め条件分岐先の変数や関数とページアドレスの対応を知っているため、どの関数や変数がアクセスされたかが分かります。


そうなると、条件分岐の方向を見ることで、条件分岐の判断基準となった秘密情報すらも抜き出せてしまう、というのが、制御チャネル攻撃の恐ろしい事です。


しかし、BI-SGXではインタプリタを採用している事により、この攻撃に対するある程度の耐性を備えています。何故ならば、「インタプリタはトークンの粒度でしか条件分岐処理を行わない」から、なのです。よって、仮にBI-SGXに制御チャネル攻撃を仕掛けても、攻撃者には以下のようにしか見えません。


こうなると、攻撃者は「何らかの変数が何らかの閾値と比較され、どちらかの方向にジャンプし何らかの変数/関数アクセスが行われている」、としかわからないのです。よって、BI-SGXは制御チャネル攻撃に対する一定以上に強固な防護性能を発揮できるのです。


ただ、コードの大まかな構成や、呼び出した組み込み関数の種類はバレてしまうので、それも守りたいのであればSGX-PCLというIntelによって公開されている拡張機能を使うのが良いでしょう。(Intel製なので私は絶対に手を出したくないですが)



まとめ

これで、BI-SGXの大まかな説明は出来たと思います。本当に地獄を見ながら開発していましたが、何とかまともな形に仕上げる事ができ、自分自身が一番安心しております。


SGXSDKとか言う悪魔の手にかからずSGXのハイパフォーマンスなセキュリティ機能を利用できるシステムとしてBI-SGXは我ながら優秀だと思うのですが、如何せん宣伝の仕方がわからないので、興味のある方は是非ご連絡いただきますと幸いです (手っ取り早いのはTwitterでの私のアカウントであります、@dd_clifffordへの連絡であると思います)。


最後に、同じ年度の未踏プロジェクトで、秘密計算という分野で共闘したプロジェクトをご紹介します。前述の通り、「準同型暗号によるバーチャルセキュアプラットフォーム」(KVSP)です。(スライドリンク:https://speakerdeck.com/nindanaoto/development-of-virtual-secure-platform


準同型暗号暗号とSGX、どうしても仲が悪いみたいな印象を受けがちなのですが、実はそもそも目指している領域が違う(準同型暗号は環境に左右されない絶対的な安全性、SGXはある程度シチュエーションを妥協した上でより現時点での技術という制約下での実用性を目指している)ので、根本的に敵対はしないのですが、何だかんだプロレス的に小競り合いを楽しませて頂きました笑


皆さん、突然ですが「エミュレータ」をご存知でしょうか。例えばPCでファミコンやプレステのゲームをプレイできるアレです。エミュレータは、当該ゲーム機のプロセッサを模擬してソフトウェア的に実装し、実際にゲームを動作させています。


KVSPの恐ろしいのは、そのエミュレータを「全て準同型暗号上で動かしてしまっている」所なんです。エミュレート対象はゲーム機ではなく、より一般的なコンピュータのCPUです。勿論、現代の技術が準同型暗号に追いついていないのでSGXほどの速度は出ませんが、準同型暗号は既存の暗号技術に対する脅威である「量子コンピュータ」に対抗できる格子暗号の一種らしいので、抜群の将来性を誇っているわけです。


私自身、実はこのKVSPのような準同型暗号ベースの技術がデファクトスタンダードになってくれる事を強く望んでいます。


何故ならば、このような準同型暗号ベースのシステムが実用的に普及すれば、SGXSDKみたいな悪魔に泣かされる人間が発生し得ないからです。

2020年3月21日土曜日

BI-SGX開発&SGXとの戦闘記録(前編)

2019年度未踏IT人材発掘・育成事業に「生命情報解析向けインタプリタを搭載した秘密計算用クラウド」のテーマで採択されておりましたaosでございます。


未踏の元でプロジェクトを進めて行った時の所感は別の記事に譲るとして、本記事ではプロジェクトにて開発したプロダクト「BI-SGX」のカジュアルな説明や、因縁の宿敵頼もしいハードウェア支援セキュリティ技術であるIntel SGXとの戦闘履歴を書き連ねていきます。


BI-SGX開発の背景と目的

最近では当たり前のようにクラウドが普及しており、かつ特に大手の提供するクラウドは各企業が十二分に厳重なセキュリティを担保した状態で提供してくれています。しかし、それらはあくまでもブラックボックス的なものであり、より客観的にセキュリティを担保出来る手法を用いて、機密性の高いデータを使用しながらの計算を行いたい、というニーズがあります。


この、「データを保護したまま計算を行い、使用した各データを特定できない形の結果を得る」、ような技術を「秘密計算」と呼びます。


最も有名かつ直感的にわかりやすい秘密計算技術が「準同型暗号」です。準同型暗号とは、暗号化された状態で加算や乗算に相当する演算を行い、復号するとちゃんと実行した加算や乗算の結果が取り出せる、という凄い暗号です。特に、準同型暗号の中でもより強力な「完全準同型暗号」は、加算と乗算両方を行う事が出来ます。


この完全準同型暗号は非常に魅力的で、これさえあれば様々な秘密計算モデルに応用する事の出来る夢のような技術です。しかし、完全準同型暗号には致命的な欠点があります。それは、あまりにも重すぎるという点です。


通常のCプログラムで1+1を1億回繰り返すと、(当方の環境では)0.1秒ほどかかりますが、HElibという完全準同型暗号を用いると、1+1を100万回で110秒ほどかかります。


流石に遅すぎる


この通り、私の生まれた時代のコンピュータサイエンスは、準同型暗号の持つ偉大な力を活かしきれる段階には到底及んでいない、という壁にブチ当たり、泣く泣く準同型暗号の活用をまずは諦めました(ちなみに、他の秘密計算技術である「秘密分散」と準同型暗号を組み合わせた「Homomorphic Secret Sharing」という技術は、両者の欠点を打ち消し合い大分速いので、興味のある方は検索してみて下さい)。


この状況で目をつけたのが、「Trusted Execution Environment(TEE;信頼可能な実行環境)」という技術です。TEEは、ハードウェア支援によりRAM上に保護領域を生成し、そこにデータを置くことで、データを保護しながらプログラムを実行する事を可能にする技術です。このTEEを実現したプロダクトとして、天下のCPUメーカーであるIntel社が、Skylakeアーキテクチャ以降のCPUにある拡張機能を搭載しました。


そう、それこそが


あのクソ忌々しい
正気の設計とは思えない
設計開発者を3000時間くらい拷問したくなるような

我らが天啓・Intel SGX(Software Guard Extension)


だったわけです。


SGXの詳細な説明は、自著のQiita記事をお読み頂ければと思いますが、要するにCPU内の「MEE(Memory Encryption Engine;メモリ暗号化エンジン)」というメモリコントローラを拡張したユニットによって、「Enclave」と呼ばれる保護領域をRAM上に生成する事で、TEEの要件を満たす事の出来るような仕組みです。


SGXはAESベースで動いている為、準同型暗号とは異なり平文同等の速度で演算する事ができ、かつ完全性検証や再生攻撃対策等も実現している為、理論的には非常に高セキュリティかつ高速なTEEを実現する事が出来ます。


なので、「SGXをクラウド上で動かせば、(Intelのハードウェアさえ信じれば)十分客観的にセキュリティを担保できる秘密計算と同等の機能を提供できるクラウドを開発できるのでは?」と考える人間が出てくるわけです。その一つが、川崎病という難病の原因遺伝子を特定する為に、患者やその近縁者の遺伝子情報を用いて演算を行うクラウドシステム「PRINCESS」です。


私もこれを受けて、より汎用的な用途・利用方法でSGXの保護機能を利用できるクラウドシステムを開発したい、と考えました。これが実にM0の時でした。しかし、ここで私は以降3年近く地獄の底に突き落とされ精神をズタボロにされながら開発を進める羽目に遭うSGXの真の恐ろしさに直面するわけです……(ここからしばらくBI-SGXから脱線してひたすらSGXに暴言を吐きます)


導入の時点で漂う「嫌な予感」

早速SGXを利用するべく、Ubuntu環境にSGXを構築しようとするのですが、その時点で尋常とは思えない「不親切さ」を感じるわけです。Readmeの手順通りやれば面倒臭いものの一応詰まらずには導入を進められるのですが、一つかなり躓いた部分がありました。それは、今では廃止されましたが、当時(SGXのバージョンが1.xだった時代)は、iCLS Clientというものをインストールする必要があり、そのインストーラをダウンロードページとしてIntelに提示されていたリンクがリンク切れを起こしていました。


更に、結局Google検索で当該ページを見つけても、やたらに長ったらしい入力を要求され、悪戦苦闘の果てにやっと導入に成功した、という感じです。


これが例えば個人が提供しているサイトなら良いんですが、あの大手も大手のIntelがこの調子とか、「え、大丈夫か?」と素直に思ったのは今でも覚えています。


脆すぎるSGXドライバ&無能すぎる公式フォーラムのアドバイザ

SGXを利用するにあたっては、SGXドライバと言うものを導入する必要があります。この導入自体は簡単なのですが、問題は導入後にあります。


ある日、SGXプログラムをビルドまたは実行しようとすると、「0x2006」というエラーコードが表示され、異常終了しました。一体何事だ?と思い、すぐ検索するのですが、Intelの公式フォーラムでは「SGXSDK(コイツへの暴言は後でたっぷり書きます)が導入されていない可能性があります」「BIOSで有効化していますか?」という回答が書かれているにとどまっていました。


やってるに決まってんだろボケ


では結局何故このような不具合が起きるかと言うと、どうもArchitectural EnclaveというSGXが内部で利用する特殊なEnclaveを司るaesmdというサービスが、再起動するとブッ壊れて再起不能になる、という、80億年前のコンピュータもビックリ仰天なわけのわからん不具合を抱えているせいなのでした。


これを直すには、この現象が発生する度にドライバをリインストールする必要があります。かつ、何故かビルドしてから一定期間経ったSGXドライバのインストーラは、途中でエラーを吐いてインストールに失敗するので、結局その度に
  1. SGXドライバをアンインストール
  2. SGXドライバのインストーラをビルド
  3. SGXドライバをインストール
する必要があるわけです。Intelさぁ……


これは自分の勝手な憶測なんですが、これに関してはIntel側がセキュリティ面か何かに過剰に警戒して、インストールしてから一定期間経ったSGXドライバを意図的に消し飛ばす自爆装置を搭載しているのではないか、と考えています。再起動すると毎回不能になるわけではなく、ある程度インストールから時間が経ってからこの不具合が発生するので、私はこのような見解を持っています。メンテナンス面倒臭すぎんだろこの糞システム


Enclaveのサイズ制限

これはSGXに手を出す段階で分かっていたのですが、Enclaveは上限96MBという苛烈なサイズ制限を要求してきます。後発のSGX2では、現実的でないレベルにごく一部のマシンのみが動的にEnclave(正確にはEnclaveの中核であるEPCのページ)を拡張していく機能があったりしますが、現実問題を考えると、まあやむを得ずこれには従うしか無いわけです。


で、「何で96MBなの?」って疑問が浮かぶんですが、唯一発見できたIntelによる見解が「TCB(Trusted Computing Base;信頼可能な計算ベース。TEEよりもより狭義な意味合いで使われる印象があり、SGXならEnclaveそのもの)の面積は大きいとセキュリティ上のリスクが増えます(根拠となる理由の説明無し)」


なぜ???


Intel「我々の研究により、96MBがセキュリティ上最適なサイズだと結論されました」


は???


いや技術屋ならその論拠示せよ、とマジで思うんですが、恐ろしいのはこの事実は公式フォーラムにしか書かれていない、という点なのです。Intelから発行されている、Intel SGX explainedという、最も原理に近い所を説明してくれている文献にすらこれらの論拠は書かれていません。マジで大丈夫かよSGX……


この点、準同型暗号が素晴らしいのは、この手の不信感を一切抱かずに秘密計算が出来る事なんですね。SGXも既存のクラウドよりはホワイトボックス的なセキュリティを実現できるとは言え、当然IntelやIntelのハードウェアは信用しなければなりません。しかも、ハードウェアに関してはSGXpectureのように、普通にヤバいレベルまで陥落しかけた事もあります。また、民間企業であるIntelを信用しなければならない以上、例えばSGXの軍事利用は到底厳しいでしょう。


なので、本当に出来れば準同型暗号を使いたかったし、ここまでに挙げたSGXのヤバい側面の時点で割と後悔していたのですが、実用性を選んでしまった以上もう突き進むしかありません。


SGX公式開発ライブラリ(SGXSDK)とSGXの裏仕様



お前だよお前


私がSGXプログラムを開発する上で地獄を見た最たる原因の一つがこれです。ちなみにもう一つは後述のIntelが提供しやがったてくれたコードの怪奇極まりない設計です。


SGXの機能を利用したプログラムを開発する上では、SGXSDKと呼ばれる公式の開発ライブラリを利用しなければなりません。で、この厳しい制限の付いたゲテモノC/C++を駆使してSGXプログラムを開発する為のSGXSDKなのですが、とにかくマジで酷いです。どれくらいかと言うと、SGXを利用したシステムの論文で公然と罵倒されるレベルに酷いんです。より詳しく言うと、SGXSDKが課してくる地獄のような制限と、C/C++という今の時代お世辞にも高級とは言えない(であろう)言語が組み合わさる事により、開発者に猛烈な負担をかけてくるのです。


例えばSGXElideというシステムの論文では、元々412行の普通のプログラムをSGXSDKを用いてSGX化した所、3523行にまで肥大化したと報告しています。また、同論文では「最もクソみたいに面倒な作業は、我々のSGXElideの導入ではなく、SGXSDKを用いたプログラムの開発そのものである(The most tedious work lies in creating the SGX programs themselves.)」とまで言及されており、どれだけSGXSDKがヤバいのか少しは想像が付いたと思います。


では、SGXSDKのクソな部分をそれぞれ見ていきましょう。



サンプルの意味を為していないサンプルコード

まずSGX初心者が躓くのはこれではないでしょうか。この内、SampleEnclaveという最も初歩的なものは、開発者リファレンスを片手に解読すればまあ分かるのですが、問題はそれ以外です。


例えば、SGXにはLocal Attestation(LA)という手続きが存在し、これは同一マシン上のEnclave同士でお互いにお互いの正当性・完全性を検証して、鍵交換の後にデータをやり取りするプロトコルです。


で、これのサンプルコードも存在するのですが、例えばmsg3というコンテキスト(マニアックな話をすると、LAのチャレンジリクエストを受理した側のEnclaveのREPORT構造体)を処理する1関数だけを見ても、
  • sgx_dh_initiator_proc_msg3()という形で呼ばれている
  • 実はsgx_dh_initiator_proc_msg3()は#defineによってマクロ付けされたものであり、実体はsgx_LAv2_initiator_proc_msg3()である
  • 更に、sgx_LAv2_initiator_proc_msg3()は何とdh_initiator_proc_msg3()のラッパー関数なので、真の実体はdh_initiator_proc_msg3()に存在する
という感じです。


テメェサンプルコードだよな???


何と言うんでしょう、普通サンプルコードっていうと、初心者でも実装や設計の仕方がわかりやすいように書くものだと思っていたのですが、流石シリコンバレー、凡人とは格が違いますね笑笑


ふざけんじゃねぇぞCPU野郎


という感じで、まだ触れていないSGXの機能に触れようとする度に、HPを99%削られる凶悪な敷居の高さが、SGXが敬遠される大きな理由の一つだと私は強く信じております。



ヤバすぎるMakefile

SGXに手を付けた人間が、自作のSGXプログラムを作りたい!と考えた場合に次に躓くのが恐らくここです。そう、SGXのMakefile、かなりヤバいです。勿論、SGXでない他のシステムにももっとヤバいのはあるのでしょうが、少なくとも準同型暗号ライブラリであるHElibはこんな恐ろしいMakefileの記述は要求してきません。


SGXアプリケーションは、非信頼部分(Enclave外で動作する部分)と信頼部分(Enclave内で動作する部分)から成り立っており、まずこの時点で少なくとも2つのビルドが発生します。


更に、Enclave内で動作するプログラムは、
  1. edger8rというツールでEnclave境界を跨ぐ関数の関数宣言をSGX語(Cのガワを被った怪文書です)に翻訳
  2. SGXライブラリも交えながらオブジェクトファイルを生成(Enclave.o等)
  3. オブジェクトファイルをリンクし共有ライブラリを生成(Enclave.so)
  4. sgx_signツールを使用し、共有ライブラリにRSA 3072bit秘密鍵で署名(Enclave.signed.so)
のように、デプロイ可能な形にするまでかなり手間がかかります。ですので、これを全て実行するMakefileを書くと、以下のようになります(Makefileのごく一部です):


キモ……(素)


勿論この世の中凄い開発者が多いですし、私はそんなにプログラム強くないので、こんなん余裕でしょ、って人もいると思います。ただ、少なくとも私はこんなん絶対書きたくありません


なので、皆さんがSGXプログラムを作る時は、IntelのSampleEnclaveのMakefileを丸ごとパクって下さい。もし追加でソースファイルやライブラリが必要になっても、追記くらいならMakefileの書き方さえ少し解読すれば出来るのでオススメです。また、後述のRemote Attestationを利用するSGXプログラムを作る上で、Intelのソースコードを流用する場合は、Autotoolsを利用してMakefileに定めたい要件を簡単に記述できるので、大分楽になります。なお、Makefileの書き方全く詳しくないのは完全に私の落ち度です。


OSを信頼していないSGXの宿命

SGXは、OSやハイパーバイザからもデータを保護出来る、という頑強さを売りにしています。一見かなり聞こえは良いんですが、実はこの仕様が開発者に酷い負担を強いるのです。


OSを信用しない、という事は、Enclave内ではOSに権限のある操作を一切使用できない事を意味します。つまり、Enclave内ではシステムコールが発行される関数が軒並み使えない事になります(例:fork, exec, printf, scanf, exit, fopen, rand, time, setlocale)。


また、これだけではなく、C++でファイルや文字列等の操作をする上での生命線であるstreamは全て使えませんし、またメルセンヌ・ツイスタ等の乱数生成器を用いた一様分布乱数を生成する為の関数uniform_real_distribution<>()関数のように、何故使えないのかよくわからない関数が無効化されていたりと、とにかくカオスです(ちなみにC++11に対応していないだけかと思ったら、vectorのemplace_back()は使えたり、本当に謎です)。


なので、開発者は常に開発者リファレンスのC/C++非対応関数リストと穴が空くまで睨み合い、常に「この関数は使えないかも知れない……」という恐怖に追われつつ、手探りでプログラムを開発していかねばならないのです。


これを軽減する為に、Enclave内からEnclave外の関数を呼び出すOCALLという機能が提供されていますが、これも実は後述のEDLという形で開発者に牙を剥いてきます。


無駄すぎる独自のtypedef

突然ですが、以下の仰々しい文字列を御覧下さい。
  • sgx_isv_svn_t
  • sgx_prod_id_t
  • sgx_spinlock_t
  • sgx_misc_select_t
  • sgx_ra_context_t
  • sgx_enclave_id_t
  • sgx_time_t
これらは、SGXがtypedefで定義している独自の型なのですが、ここで問題です:この内、整数型である型はどれでしょうか?



答え:全部



いや、分かりますよ、「それぞれ特定の部分において使われるので識別しておく意味がある」、という意見もあります。しかも整数と言っても、厳密にはshortだったりlongだったりするのもあります。


しかしですよ、このクソみたいに見慣れない型の実体を操作しなければならない状況に開発者が陥って、「この型何なんだろうなぁ」思って350ページ以上もあるリファレンスを漁って調べたら、「typedef int sgx_ra_context_t;」と出てきた時の気持ちを考えてみて下さい。


ブチのめすぞCPU野郎


他にも、sgx_ra_key_128_tとsgx_key_128bit_tという、どっちも実体がuint8_t[16]である本当に分ける意味のわからない型も存在して(そんなにRA向けである事を厳格に宣言する必要があんのか!おいIntel!お前に聞いてんだよ!)、疲弊し尽くす事間違いないでしょう。


気が狂ってるとしか思えないSGXAPI

出ました。最凶最悪の問題児です。


例えばEnclaveを生成したり、Enclave内で暗号処理したり、といったSGXに密接に関わる処理は、SGXSDKの提供するAPIを使用して定義する必要があります。


もう何もかも酷すぎて、全部列挙するとGoogleが保有する全てのストレージを埋め尽くしてしまうレベルで書き散らせてしまうのですが、ここでは掻い摘んで説明しましょう。


まず、Enclaveを生成する際には、sgx_create_enclave()というAPIを使用します。この時、起動トークンと呼ばれる、sgx_launch_token_tと型付けされたuint8_tの塊を与えるように指定されます。


これ、Launching Enclave(LE)と呼ばれるArchitectural Enclaveを経由し、しかもEINITTOKEN構造体と呼ばれる形で如何にもEnclaveの重要な構成要素として使命を果たしているように見えるんです。


しかしこれ、マジでいらないんです


ええ、Intel曰く「起動トークンはある署名済みEnclave共有ライブラリから初めて生成された時に保存して、次回同じ共有ライブラリから起動する時に高速化出来る」、と書かれているのですが、


マジで全く変わりません。


なので、全くいらねぇ要素の為に、0で埋め尽くしたダミーのsgx_launch_token_tを渡し、毎回起動トークンを生成させてそれを破棄する、という、マジでバカみたいな処理をしなければなりません。


極めつけは、SGXが出て割と初期に書かれたIntel SGX explainedのホワイトペーパーにおいて、「LEはシステムソフトウェアで十分代替可能なので、そもそも起動トークンどころかLEがいらねぇ」と書いてあるんです。


だったら何故初期に直さなかった


もうここまで年数経ってしまったら後の祭りです。互換性問題が出てくるので二度と修正できないでしょう。バーカ笑


2つ目に、とんでもないものをお見せしましょう。



画像の示す通り、シーリング(Enclaveまたは署名鍵固有のハッシュ値によって生成されたコンテキストを用いた暗号化処理)とアンシーリング(同じく復号処理)の利用例なんですが、赤い四角と青い四角を見て下さい。これ、青がAES/GCMにおける任意で指定できるMAC(メッセージ認証符号)で、赤がそのサイズなんです。お気付きですか?


当たり前のように順序が逆


私、最初これを見た時は衝撃を受けました。というかそもそも、シーリングでは追加のMAC情報群(赤と青の四角)が先頭に来ているのに、アンシーリングでは暗号文が先頭に来ています。


Intel、本当に大丈夫ですか???設計者、ヤクでもキメながら設計しませんでしたか???また、この正気を疑う設計チェックする人間社内に一人たりともいなかったのですか???


と、アメリカの闇を感じられる恐ろしいSGXAPIのご紹介でした。


最後に、純粋に使う頻度が高い割に面倒臭い関数として、sgx_rijndael128GCM_encrypt()関数とsgx_rijndael128GCM_decrypt()関数をご紹介しましょう。まず命名へのツッコミですが、何故rijndaelにしたのでしょうか?rijndaelって呼び方はAES暗号の古い呼び方なので、SGXの時代にはとうにAESとして普及しているはずなんですが、マジでIntelに何が起きたんでしょうか???


それは別として、この関数は鍵・初期化ベクトル・GCMタグ(MAC)・暗号文・平文全てuint8_tの配列で全て操作しなければならない(GCMタグに関してはsgx_aes_gcm_128bit_tag_tと、またいりもしねぇ型付けがされていますが)ので、純粋にハゲます。どっかでミスって1バイトずれただけで終わるので、結構シビアです。それが送信側での処理に問題があった、なんてなると、もうデバッグだけで全身が痙攣し始めてしまいます。


CIAの拷問に利用されていると有名な境界定義言語(EDL)

さて、SGXではEnclaveの境界を跨ぐ関数呼び出し(即ちECALL及びOCALL)には、EDLという形式で別個追加情報を設定する必要があります。


EDLは、C/C++の関数宣言を拡張したみたいな書き方で記述し、渡すバッファのポインタ方向(渡した先へ渡すのか、あるいは渡した先から持ってくるのか)や、渡すバッファの厳密なサイズの指定等を行います。ここで、実際にBI-SGXの開発において記述したEDLのごく一部をお見せ致します。


キモ……(2回目)


このように、たかだかEnclave外のDBに暗号データをストアするだけで、恐ろしい量の引数と追加設定の記述を強いられるのです。しかも、受け渡しするバッファのサイズは厳密に指定されていなければならないので、例えばEnclave外のDBからデータを持ってくる場合、一度別の関数でDBからフェッチしたデータのサイズを取得してからそのサイズを指定して実データを持ってくる、といったような気が狂った作業を要求されます。


char型の配列であり、ヌル終端されている場合のみstringというオプションで自動的に長さを決定できますが、SGXでは大体乱雑な暗号文を扱う為ほぼ役に立ちません


境界を跨いだデータ受け渡しにおける「裏仕様」

普通、ヒープは当然スタックとは別物ですので、ヒープでスタックサイズ上限(通常初期状態では約8MB)を超えるサイズを関数呼び出し時に渡しても、勿論エラーは出ません。よって、私も20MBの暗号化したデータをEnclaveに入れようとするんですが、どうも関数呼び出しのごく直後にクラッシュするみたいです。


ここで知った恐ろしい事実なのですが、実はSGX、ヒープであろうが内部で特殊なスタック強制で上限約8MB)を経由してEnclave境界を跨ぐので、ヒープであろうとこのスタックサイズ上限を突破できない、という気が狂った裏仕様が存在するのです。


このスタックサイズ上限は、Enclave設定用XMLや、勿論ulimit等でも変更不可能なので、折角のヒープなのに細々とした受け渡ししか出来ない事になります。しかもこれ、開発者リファレンスには一切書かれていません


おいIntel!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


流石にこれは当時ブチギレてた記憶があります。こういう事を平気で出来てしまうのが我々のIntel、天下のIntel。いやぁ、脱帽です笑


このクソIntel野郎!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


リモート・アテステーションとIntelの書いたコード

SGXアプリケーションを作る上でのラスボスと言いますと、やはりRemote Attestation(RA)でしょう。詳しくはこちらのQiita記事で解説していますが、これがまたとんでもない実装難易度をしております。


軽くRAの概要を説明すると、遠隔からEnclaveを利用する時に、その遠隔のユーザが
  • 相手とするSGXマシンのCPUはIntelに正式に認められた正当なCPUなのか?
  • 相手とするEnclaveの完全性と正当性は保たれているか?
を検証し、同時にTLS通信用の鍵交換を行うプロトコルです。


で、普通の神経をしていたら、接続情報を指定して特定のAPIを呼び出したら、後は勝手に完了してくれるような設計をするはずです。しかし皆さん、忘れてはいけません。


Intelはまともではないのです


あろう事か、IntelはRAでやり取りされる情報msg0, msg1, msg2, msg3, msg4用全てそれぞれバラバラにAPIを用意し、しかもAPIを利用した上で半分以上自前でRAのプロトコル要件を満たす為の実装をしなければならない、という、人類が誕生して以来この世に存在してきたあらゆる暴君ですら泣いて逃げ出すような残虐な仕打ちを強制してきます。


M0の時代にRAを実装しようとして、あまりの難易度の高さに絶望し、その上指導教員に「君のシステムには合理性がないね」と言われ、夜寝ている間に金縛りに遭って目の前にEnclaveを模した四角とデータが現れ、データに「俺をEnclaveに入れろ……」とひたすら脅迫されまくったのは今でも鮮烈に記憶しています(※マジです)。


ただ、sgx-ra-sampleというIntelによって公開されているRAのサンプルコードを用いると、大分楽になります。というか、これをベースにせずに自前でRAを実装するのは超人レベルじゃないと不可能だと思います。


また、このsgx-ra-sampleで通信関数として用意されているmsgio、マジモンのポンコツです。


まず、全く必要ないのに送受信時に何故かhexエンコード/デコードをしているせいで、たった8MBの受信に10分かかるとか言う、小1のガキ時代の私(※50m走13.7秒)も驚愕凄まじい低パフォーマンスを記録してくれます。


また、工夫をしないと発生するはずのないノイズランダムに受信データの末尾に付着し受信したファイルが復号できない、といったアクシデントも多発します。これに関しては、BI-SGXのリポジトリで修正したものを提供していますので、こんなヤバい仕様に直面したくない方は是非ご利用下さい。


BI-SGXの開発の決意

いかがでしたか?(クソバイラルメディア風)


これまでに無いレベルでSGXのヤベー所をぶち撒けましたが、これを読んで「あ、私もSGX開発してみたい!」とお考えになった方はいらっしゃるでしょうか?


もしいたら病的なドMです


私はこのSGXという、「便利な技術」の皮を被ったド畜生の残虐さを目の当たりにして、強い憤りを覚えました。実用性という意味では性能としてはかなりのポテンシャルを秘めているのに、あまりにも難解すぎて全く普及しない。そんなクソみたいな技術目の前にしたら


ブチのめしたくなりません?


という事で、私はSGXの高パフォーマンスなセキュリティ機能の恩恵は受けつつも、上述のクソみたいなSGXSDKの仕様・制約に縛られず、誰でも簡単にデータを保護しながらの処理が出来るクラウドを作る事にしました。BI-SGXの開発はそのまま大学院の研究としても流用していたので、建前上は専攻分野である生命情報解析の為の安全なクラウドの実現、も謳っていましたが、このSGXに対する怒りがBI-SGXの開発を始めた最も大きな理由です。



次回の後編では、BI-SGXの各コンポネントを、開発日記じみたのを交えながらご紹介したり、BI-SGXの小ネタを披露しようと思います。