nRF Connect SDK:乱数を使う


乱数

組み込み機器で乱数ってなんだかんだで使いたくなる、あるいは使わざるを得ない場面ってありますよね。えっ?ない?だって暗号化するのに必要ですし・・・。

nRF5xのハードウェアランダムは使えない

少なくとも今のところはnRF5xが持っているハードウェアでの乱数生成機能は使えないようです。nRF SDKでrandom_vector_generate()関数として提供されていたものです。代わりにOS(Zephyr)が乱数機能を提供しているようですが、コンフィグの説明には何やら不穏な記述が・・・。

This option signifies that the kernel's random number APIs are
permitted to return values that are not truly random.
This capability is provided for testing purposes, when a truly random
number generator is not available. The non-random number generator
should not be used in a production environment.

完全なランダムではない、という記載があり、テスト用途でのみ使ってねと書いてあります。うむむむ・・・。

とりあえず実装しよう

ということでとりあえず実装してみるに限ります。OSがサポートしているだけあって記述が非常に簡単です。

main.c
/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <random/rand32.h>
#include <string.h>
#include <sys/printk.h>

void main(void)
{
    uint32_t buf[10];

    // Initialize
    memset(buf, 0, sizeof(buf));

    for (int i = 0; i < 10; i++)
    {
        printk("Generating 32bit random value:%x\n", sys_rand32_get());
    }

    sys_rand_get((uint8_t *)(&buf[0]), sizeof(buf));
    for (int i = 0; i < 10; i++)
    {
        printk("Generating bulk fill random numbers %d:%x\n", i, buf[i]);
    }
}
prj.conf
CONFIG_TEST_RANDOM_GENERATOR=y

実行してみた

実装できたので実行してみました。

お、なんかそれっぽい乱数が生成されていますね。めでたしめでたし。
ところでよくある乱数のようで乱数でないというパターンとして、初期化ルーチンが同じなのでリセットすると似たような数字が出てくるというものがあります。さて、そこは大丈夫なのでしょうか。いざ、リセット!

・・・?
なんだかジーっと見ていると似ているような気がしませんか?しかも最初の32ビットの乱数なんて、また(?)上位16ビットが全部0ですし!!!
どうやらこれだけではダメそうです。さて、どうしたものか・・・と調べてみると追加でさらに乱数を激化(笑)させるコンフィギュレーションがあるようです。

prj.conf
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_ENTROPY_GENERATOR=y

これを追加すると乱数が激化するようです。ではさっそく追加して実行してみます。

まず明らかに違う点として最初の32ビットの乱数の上位16ビットが0ではありません!!!これだけでも期待が持てそうですが、念のためリセットして確かめてみましょう。

おお、どこからどう見ても全然(?)違いますね!!!
とりあえずこれで乱数は使えそうです。