2007年05月17日

USBNIXの構想

はじめに

作ってみようと思っている装置の記事で

UNIX もどき USB Key
実はUSB910では、オリジナルのAVR-CDCに手を入れて getc/putc でプログラミングできるようにしていて、USB シリアル装置を手軽に作れるようにしている。で、なにか便利(そう)なものを作ってみようと考えていて思いついたもの。
この装置をUSBにつないでターミナルソフトを立ち上げ、ENTER を入力すると login: なんて出る。本当に login できて、いくつかのコマンドが使える。使えるコマンドは、ls と cat ファイル名と cat > ファイル名。あと rm ファイル名 は必要か。なんに使えるかというと、(他の)パスワードとか忘れそうだけれども秘密にしたいものの覚書。ファイルデータは、1件 1KB 以内で、32件までにして、I2C ROM に入れる。I2C ROM だけ抜かれたりしたときの対策に暗号化が必要で、暗号化のキーは本体のEEPROMに覚えさせてロックビットで保護する。最大の問題はコードのサイズ。 4KB に入れるのは無理そうだが、8KB には収めたい。装置単体でのパスワードの変更は無理だろう。で、どうするかというと、データをいったん全部吸い出して、あらためて パスワードと暗号化キーデータを生成して、EEPROM に書き込みデータを書き戻す...そういうホストプログラムがあれば問題ない。

と書いた。これを実際に作ってみることにする。USB Key ではなにのことかわからないので、USB + UNIX の意味で USBNIX と名前をつけた。超々簡易版ではあるが、UNIX のコマンドを使って操作する。説明なしにデモすれば、UNIX or Linux が動いているように見えて驚かれるかもしれない。

暗号化のコードをどうするか

DES や AES といったものを移植するという方法はコードが大きくなりすぎる(はずな)ので、最初からあきらめている。実は、UNIX V7 のコード usr/src/cmd/crypt.c を使おうと思っていた。で、(ライセンスにしたがって)このプログラムは、UNIX のコードを使用しています...なんてシャレで書こうと思っていたのだが、実際にコードを見てみると、char の配列が256x3 もあることがわかった。これでは tinyシリーズでは無理だし、mega88 とかでも厳しいので、それもあきらめて、自作することにした。eeprom にkeyを入れて ロックビットを設定してやれば、弱い(てきとうな)アルゴリズムでもまぁ大丈夫に違いない。

ところで、UNIX V7 の crypt.c のコメントが興味深かったので紹介。
A one-rotor machine designed along the lines of Enigma but considrably trivialized.

だそうだ。要するに有名なエニグマ(第二次世界大戦のときのドイツの暗号装置)の簡易版ということらしい。

構造とかAPIとか

md5 などと同じように、コンテキストを持っていて入力ストリームによって状態を変化させていく。で、コンテキストと入力ストリームの XOR を取ってエンコードする。デコードもほとんど同じで、状態を再現して、XOR で元に戻す。md5 とかは、コンテキストを変化させる部分が非常に複雑になっているけども、ここを思いっきり簡単化すれば、8KBのAVRで使えるものになりそう。

具体的には、


typedef union mc_context {
struct {
uint32_t A;
uint32_t B;
uint32_t C;
uint32_t D;
};
uint8_t buf[16];
} mc_context_t;

mc_context_t mc_context;

static void mc_rotate(uint32_t *x) {
/* pseudo random generator */
*x <<= 1;
if ( (!(*x & (1L<<31)) && (*x & (1L<<28)) )
|| ((*x & (1L<<31)) && !(*x & (1L<<28))) ) {
*x |= 1;
}
/* netbsd rand() algorism */
*x = *x * 1103515245 + 12345;
}

static void mc_xor(uint8_t *dst, uint8_t *src) {
uint8_t i;
for (i=0; i< 16; i++) {
*dst = *dst ^ *src;
dst++;
src++;
}
}

oid mc_encrypt(uint8_t *block) {
mc_xor(block,mc_context.buf);
mc_rotate(&mc_context.A);
mc_rotate(&mc_context.B);
mc_rotate(&mc_context.C);
mc_rotate(&mc_context.D);
mc_xor(mc_context.buf, block);
}

void mc_decrypt(uint8_t *block) {
uint8_t tmp[16];
memcpy(tmp, block, 16);
mc_xor(block,mc_context.buf);
mc_rotate(&mc_context.A);
mc_rotate(&mc_context.B);
mc_rotate(&mc_context.C);
mc_rotate(&mc_context.D);
mc_xor(mc_context.buf, tmp);
}


こんな風にしようとしている。mc という prefix は mini crypt の略。mc_rotateの上の部分は、ホワイトノイズ生成とかで使われている 擬似乱数(pseudo random)ジェネレータ 。下の部分は、netbsd の rand() のアルゴリズム。最初は下の部分だけでよいと思ったが逆関数がつくれてしまいそうなので、上の部分もあわせて使うことにした。これでかき混ぜておいて 入力データとの XOR で新たな 状態を作る。コンテキストの初期状態は、

void mc_setkey(const uint8_t *key);

で設定することにする。eeprom に 16 バイト x 8 の乱数を格納しておいて、
ファイル毎に Key を変える。

これぐらいしておけば、素人みえには他の暗号化アルゴリズムと遜色なさそうなデータになるのではないかと思う。ただし、アルゴリズムを知っている上でまじめに解析されればわりと簡単に解けてしまうかもしれない。

パスワード

UNIX もどきなので、user と password を入力させようと思う。ただし、user という概念はないので、user と password をくっつけたデータをパスワードとみなす。格納するデータは、平文ではなく、暗号化したデータでもない。一方向関数によって生成したダイジェストである。これを mc_setkey と mc_encrypt を使って生成することにする。

mc_setkey(line_buf);
for (pos=0; pos<128; pos+=16) {
eeprom_read_block(line_buf, (void *)pos, 16);
mc_encrypt(line_buf);
}

ようするに、パスワードを初期状態にし、乱数テーブルでかきまわしたデータ。これを eeprom に格納しておく。同じ処理をおこなって同じデータになれば、login を許すことにする。ちなみに、パスワードデータを PCで生成する予定だったが、それはやめて、実機で行うようにするつもり。

おわりに

このシステムで、暗号化をどうするかが最大のポイントだった。全体で8KBに入る見込みがなければ、作るのをあきらめようとさえ思っていた。
いまいち不安ではあるものの、次のように 474 バイトとコンパクトな暗号化モジュールができた。


text data bss dec hex filename
474 0 0 474 1da minicrypt.o


これさえ目処が立てば、あとはプログラムを作るのみである。USB910A と 実験ボードその1

を使って評価できるので、ボードも作る必要はない。

といっても、最初から実機でテストするつもりはない。Linux でプロトタイプを動かして満足できるものに仕上げてから、実機に移植する予定。次回は、その製作をレポートしたいと思う。

追記

つれづれ日記からコメントをいただいた。更新を久しくしていなかったのに、すかさずコメントをもらえて嬉しい限り。

コメントではじめて知ったのだが、Crypto-avr-libというのがあって、各種暗号化アルゴリズムを AVR に移植しているそうだ。はっきりはわからないが、 メモリが厳しいものの MD5 とか SHA とか載らないわけでもないかも知れない。
posted by すz at 16:55| Comment(0) | TrackBack(0) | USBNIX
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス: [必須入力]

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/30760387
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック