entropy_availが減少して安定するのはなぜですか?

entropy_availが減少して安定するのはなぜですか?

私はMIPSELを持っていますCI20開発ボードそれはエントロピー枯渇に苦しむ。このボードには、ハードウェアrng(アドレス0x100000DCにマップされたレジスタ)を持つJZ4780 SoCがあります。これIngenicドライバに問題がありますだから、レジスタを読んでプールを補うためのユーザーエリアプログラムを書いています。

プログラムを実行した後、私は以下を観察しました。

$ sudo ./ci20-rng.exe && for((i=1;i<=20;i+=1)); do (cat /proc/sys/kernel/random/entropy_avail; sleep 5); done
3968
3712
3456
3200
2944
2688
2432
2176
1920
1664
1408
1152
896
640
384
128
128
...

同様の質問はエントロピーを消費することは何ですか?ガターの説明は基本的に意味があります。こういった説明を考えると、早すぎたことだと思います。しかし、変位は160または128の周りに固定されるのではなく、ゼロに保たれる必要があるようです。

なぜentropy_avail160または128付近で安定しているのですか?


次のプログラムはioctl(fd, RNDADDENTROPY, &entropy)is記述子fdを使用します/dev/randomentropy予想される構造は次のとおりです。

typedef struct {
    int bit_count;
    int byte_count;
    unsigned char buf[4096];
} entropy_t;

制御レジスタ(*ctrl = 0x00および*ctrl = 0x01)の切り替えおよび読み出しによる後続の遅延JZ4780 プログラマズマニュアル。アイデアはSC-ROMコントローラに書きますが、1秒未満の間押し上げることです。「...VDDQの最大2.5V電源時間は1秒以内に厳密に制御する必要があります。」。あまりにも真剣に受け入れたり誤解していないことを願っています。

手順は次のとおりです。

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/random.h>

typedef struct {
    int bit_count;               /* number of bits of entropy in data */
    int byte_count;              /* number of bytes of data in array */
    unsigned char buf[4096];
} entropy_t;

static int print_only;

/* gcc -g2 -O2 -std=c99 ci20-rng.c -o ci20-rng.exe */
int main(int argc, char* argv[])
{
    int ret = 1, fd1 = -1, fd2 = -1, fd3 = -1;
    void *map1 = MAP_FAILED, *map2 = MAP_FAILED;

    const int PAGE_SIZE = sysconf(_SC_PAGESIZE);
    const int PAGE_MASK = ~(PAGE_SIZE - 1);

    #define CTRL_ADDR 0x100000D8
    #define DATA_ADDR 0x100000DC

    if(argc >= 2)
    {
        if(0 == strcmp(argv[1], "-p") || 0 == strcmp(argv[1], "/p") || 0 == strcmp(argv[1], "--print"))
            print_only = 1;
    }

    fd1 = open("/dev/mem", O_RDWR | O_SYNC);
    if(fd1 == -1)
    {
        fprintf(stderr, "Failed to open /dev/mem for reading and writing (error %d)\n", errno);
        goto cleanup;
    }

    fd2 = open("/dev/mem", O_RDONLY | O_SYNC);
    if(fd2 == -1)
    {
        fprintf(stderr, "Failed to open /dev/mem for reading (error %d)\n", errno);
        goto cleanup;
    }

    fd3 = open("/dev/random", O_RDWR);
    if(fd3 == -1)
    {
        fprintf(stderr, "Failed to open /dev/random for writing (error %d)\n", errno);
        goto cleanup;
    }

    map1 = mmap (NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, CTRL_ADDR & PAGE_MASK);
    if(map1 == MAP_FAILED)
    {
        fprintf(stderr, "Failed to map 0x100000D8 for control (error %d)\n", errno);
        goto cleanup;
    }

    map2 = mmap (NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, fd2, DATA_ADDR & PAGE_MASK);
    if(map2 == MAP_FAILED)
    {
        fprintf(stderr, "Failed to map 0x100000DC for data (error %d)\n", errno);
        goto cleanup;
    }

    const int off1 = CTRL_ADDR % PAGE_SIZE;
    volatile uint32_t* volatile ctrl = (uint32_t*)((uint8_t*)map1+off1);

    const int off2 = DATA_ADDR % PAGE_SIZE;
    volatile uint32_t* volatile data = (uint32_t*)((uint8_t*)map2+off2);

    entropy_t entropy = { .bit_count = 4096*8, .byte_count = 4096 };
    int count = 4096/4, idx = 0;

    while(count--)
    {
        /* If the delay from the loop drops too low, then we */
        /*  can watch the random values being shifted in.    */
        #define DELAY 5000

        *ctrl = 0x01;        
        for(unsigned int i = 0; i < DELAY; i++) {
            volatile uint32_t unused = *ctrl;
        }

        if(!print_only)
        {
            memcpy(entropy.buf+idx, (const void *)data, 4);
            idx += 4;
        }
        else
        {
            if(isatty(fileno(stdout)))
                fprintf(stdout, "0x%08x\n", *data);
            else
                write(fileno(stdout), (const void *)data, 4);
        }

        *ctrl = 0x00;
        for(unsigned int i = 0; i < DELAY; i++) {
            volatile uint32_t unused = *ctrl;
        }
    }

    if(!print_only)
    {
        int rc = ioctl(fd3, RNDADDENTROPY, &entropy);
        if(rc != 0)
        {
            fprintf(stderr, "Failed to add entropy (error %d)\n", errno);
            goto cleanup;
        }
    }

    ret = 0;

  cleanup:

    if(map2 != MAP_FAILED) { munmap(map2, PAGE_SIZE); }
    if(map1 != MAP_FAILED) { munmap(map1, PAGE_SIZE); }

    if(fd3 != -1) { close(fd3); }
    if(fd2 != -1) { close(fd2); }
    if(fd1 != -1) { close(fd1); }

    return ret;
}

ベストアンサー1

私は、デバイスが「ランダム」データを生成するアルゴリズムを変更(弱める?)して完全に使い果たされないと推測します。つまり、「実際の」ランダムデータを無視し、CSPNRGに依存します。

私はちょうど関連する質問をし、マニュアルページで答えを見つけましたrngd

サービスrnd-toolsはプログラムを呼び出します/usr/sbin/rngd。探すUbuntuドキュメントパラメータがあることがわかります。

-W n, --fill-watermark=nnn

      この作業を開始したら、エントロピーを提供してください。ランダム機器少なくとも透かしを埋める エントロピープールには使用可能なエントロピービットがあります(デフォルト:2048)。高すぎると rngdエントロピープールの内容を制御します。低い値は、エントロピー欠損期間中にシステム性能を低下させる可能性がある。未設定 透かしを埋めるエントロピープールのサイズ(通常は4096ビット)より大きい。

私の質問/回答ここにあります。

おすすめ記事