月別アーカイブ: 2014年12月

CAT68701にNetBSDを移植したときの思い出

これはNetBSD Advent Calendar 2014の12日目の記事です。

かつてCAT68710というsh3ベースのワンボードコンピュータがシリコンリナックスから販売されていました。標準OSはLinuxだったのですが、それをNetBSDに移植したときの思い出を記憶から掘り起こしてみます。もう10年以上前のことになりますが…

まずCQREEKSH3をベースとすることを考えました。これは多分CQ RISC評価キット/SH3のコードです。組み込みsh3ボードは他にも複数あったのですが、なぜこれを選択したのかはよく覚えていません。confの差分を見ると相当いろんなものを削っていたのでどれをベースにしても大差なかったかもしれません。

CAT68710にはシリアルポートがあり、ブートローダーが最初から入っていて制御可能だったので、最初はとにかくシリアルからなにかしらの出力をさせるために、locore.Sをいじってシリアルに文字を出してみるところから始めました。シリアルコントローラはsh3内蔵のものをそのまま使っていたので、ブートローダーが既に初期化をしてる状態からシリアル出力をさせるのは簡単でした。

各種I/OデバイスのアドレスをCAT68710に合わせて起動させると、動いているっぽい感じはあったのですが出力がなにもなかったので困りました。先の「既に初期化されているシリアルポート」であることを利用してputcharに手をいれて、とにかくコンソール出力をさせてみたらpanicに至るメッセージが出力できて、ようやく手がかりをつかんだことが当時の日記に記録されています。

シリアルコントローラは初期化パラメータが間違っていたようで、それを修正して小細工なしにシリアルコンソールが出るようになりました(当時の記録)。さらにpcmciaのコードをmmeyeから持ってきて、CFスロットが認識できるようになりました。

ネットワークはCS8900を使っていて、幸いなことにNetBSD側にMIなドライバーがあったのでそれを組み込みました(記録)。割り込みベクタ番号を適切な値にすることで最終的にちゃんと動くようになりました。適切な値、というのはLinuxの方で設定しているirq番号を参考に適当に何かを足し引きしてたまたま動くやつがわかった、というような経緯だった記憶があります。この時にsh3 Linuxのデバイスドライバは基本x86のISAバスのセマンティックに無理やり合わせて動かしている、ということを学びました。今時のデバイスでは変わっているだろうと思います。

最終的にnfs rootでmulti user modeで動くところまでは持ってゆけました。作業はここで力尽きて止まったようです。

思い返してみると、NetBSDのMIドライバはよくできていたなと思います。既に複数の組み込みボードの移植コードが存在していたことも、自分がポーティングできた成功要因の一つだと思います。多分自分で書いたコード量は3ケタ行ぐらいだったと思います。しかし当時gitがなかったのが残念です。手元に残っていたコードは2つのtarballだけでした。

GData ClientのSpreadsheet ListFeed

個人的にはまったので記録に残しておこうと思います。

GoogleのAPIには2つの種類があります。一つはGoogle APIと呼ばれるもので、APIs Explorerにて確認できるものです。もう一つ、微妙に違うGoogle Data APIsというものがあります。GoogleはこれらのAPIを操作するためのライブラリを各種言語向け(Java, .NET, Python, ruby, PHP等)に用意しています。前者はgoogle-api-clientというような名前、後者はgdataというような名前を付けています。

この2つは微妙にセマンティックが違うのですが、OAuth2で認証できる点は同じで、認証ポイントも同一です。しかしそれぞれ個別にOAuth2認証クラスを持っていたりして、両方をまたいで(たとえばgmailとcalenderの組み合わせ等)使おうとするときは結構面倒です。両方をカバーするscopeでどちらかのライブラリで認証し、もう片方のOAuth2認証クラスに各種情報をコピーする必要があります。

それはともかく、今回はまったのは以前くらった「GData.SpreadsheetsライブラリのListFeedに潜む罠」の続きです。一行目に書かれた文字列がフィールドのキーとなるわけですが、さらにこの値は「API上は小文字しか受け付けない」という罠です。

たとえばA1に「Firstname」という値があったとして、ListEntry.CustomのLocalNameプロパティに”Firstname”としているとAPIレベルでエラーが帰ってきます。ここは”firstname”としなければなりません。

StackOverflowの“Cannot add a row to Google Spreadsheet”という記事でこのことが説明されていました。Google Sheets API version 3.0にはそのことは触れられていません…

毎度StackOverflowにはお世話になりっぱなしです。

Linuxで扱う乱数に関する話

これはLinux Advent Calendar4日目の記事です。

Unix系OSには、カーネルに乱数生成器を持つ実装が多くあります。乱数は暗号分野でも利用され、非常に重要な位置を占めています。Linuxにおける乱数に関する話題を取りあげてみます。

エントロピープール

一般的に、特別なハードウェアを持たない限り、真の乱数を計算機が生成することは困難です。Linuxでは、質の良い乱数を生成するためにエントロピープールと呼ばれる領域を持っています。エントロピープールには、キーボードの入力タイミングやストレージ、ネットワークなどで発生するハードウェア割り込みなどをもとにした推測の困難な情報(環境ノイズ)が蓄積されます。乱数の生成時には、このエントロピープールの内容を消費、加工します。

エントロピープールにどの程度情報がたまっているかを調べるには、/proc/sys/kernel/random/entropy_availを見ます。エントロピープールの上限値は/proc/sys/kernel/random/poolsizeをcatした出力値です(デフォルト値は4096) 。OpenPGPやSSLの鍵などを生成する際には、この値を確認した方がよいかもしれません。

// drivers/char/random.c
/*
 * Configuration information
 */
#define INPUT_POOL_WORDS 128
#define OUTPUT_POOL_WORDS 32
#define SEC_XFER_SIZE 512
#define EXTRACT_SIZE 10

// 途中略

static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
ctl_table random_table[] = {
        {
                .procname       = "poolsize",
                .data           = &sysctl_poolsize,
                .maxlen         = sizeof(int),
                .mode           = 0444,
                .proc_handler   = proc_dointvec,
        },
        {
                .procname       = "entropy_avail",
                .maxlen         = sizeof(int),
                .mode           = 0444,
                .proc_handler   = proc_dointvec,
                .data           = &input_pool.entropy_count,
        },

スペシャルデバイス

乱数を生成する特別なデバイスファイルには、/dev/randomと/dev/urandomの2種類があります。

/dev/randomは全ての乱数をエントロピープールから生成します。エントロピーが不足した場合は新たにたまるまでブロッキングされるため、あまり速度が出ません。乱数の質よりも速度に重点を置く場合には、/dev/urandomを使います。urandomを使う場合、エントロピープールを再利用して乱数を生成します。

havege

havegedを動かすことで、より多くの環境ノイズ(主にCPUの情報)をもとにしてエントロピープールを常に多い状態へと保つことができます。エントロピープールへの情報の追加は/dev/randomのioctrlインターフェースを用いています。また、havagedは単独の乱数生成アプリケーションとしても利用できます。

NeuG

g新部さんによるハードウェア乱数生成実装として、NeuGがあります。NeuGはSTM32F103上で動作し、チップに搭載されているA/Dコンバーターからの入力の量子化誤差を乱数生成に利用します。NueGの動作するハードウェアとしてFST-01があります。この記事を書いている2014年12月初頭では品切れ中ですが、今後追加生産・販売を予定しているそうです。

仮想化の問題

エントロピープールの情報は、予測が困難であるハードウェアからの情報に大きく依存しています。仮想マシンの場合、多くのハードウェアは仮想化されており、ハイパーバイザ等の配下にあります。したがって、物理マシンと比較すると質の良い乱数を生成させることがより困難となっています。セキュリティに十分な注意を払う必要がある場合には、信頼できない仮想マシン上での暗号鍵の生成などは控えた方が良いでしょう。

訂正

コメントでg新部さんからいくつかご指摘を頂きましたので修正・追記しました。FST-01はhttp://www.seeedstudio.com/より購入可能とのことです。詳細はコメントをご覧ください。

宣伝

この記事はFSIJ勉強会での解説をもとに得た知見を自分なりに記録したものです。FSIJでは定期的に勉強会を開催しています。GnuPGの開発者の一人であるg新部さんもいらっしゃるので、興味のある方はぜひお越しください。

 

第120回東京エリアDebian勉強会、2014年11月勉強会参加

先日「第120回東京エリアDebian勉強会、2014年11月勉強会」に参加してきました。

rroonga関連のパッケージをどうにかしようと考えていたのですが、Jornada 720にDebianを入れようとしていた人が来ていたので、そのお手伝いをしました。私自身はJornada 680を持っていて、過去にDebianを入れて使った経験があったので、それが多少役に立ちました。

Jornadaは、今は亡き「ハンドヘルドPC」と呼ばれるカテゴリのデバイスで、キーボードとディスプレイのついた小型PC的なものです。680はsh3が、780はStrongARMが搭載されています。標準OSとしてWindows CEが入っています。

基本的には「Lenny on j720」にあるカーネル、ブートローダー(CE用実行バイナリ)をCFに入れて、適切なカーネルパラメータを設定して起動するだけです。

任意のアプリケーションをインストールできるようにしたかったのですが、その場にあったPCMCIAネットワークカード(Corega PCC-TD)の認識がうまくゆかず、そこまではたどり着けませんでした。

一応、最近のkernelにもjornada 780向けのコード自体は入っていますが、パッケージとして用意されているarm用カーネルでその設定を有効にしたものは現状ありませんでした。コンパイルして動くかどうかもあやしい気がします。

この時代のunstableはLennyだったようで、userlandはLennyのものでした。このころはhotplug周りの仕組みが変化していた時期でしたが、Lennyは既にudevで動いていたようです。/etc/pcmcia/config*にCorega PCC-TDの設定を追加してやればNICも動いたかもしれません。

しかしLennyの頃はアーキテクチャarmとarmelが用意されていたのに対して、それ以降ではarmel/armhfに変わっています。ABIも変わってしまっているので、直接的なアップグレードはおそらくうまくいかなかったことでしょう。

Jornada 780は探せば1万円を切る程度の価格で入手できるようですが、さすがに今から使おうという気にはちょっとなれませんでした。