• Linux - 驱动开发 - RNG框架


    说明

    • 公司SOC上有一个新思的真随机数(TRNG)模块,Linux平台上需要提供接口给外部使用。
    • 早期方式是提供一个独立的TRNG驱动,实现比较简单的,但是使用方式不open,为了加入Linux生态环境,对接linux原生的随机数框架。

    硬件随机数框架(hwrng)

    • 目录结构
    drivers/char/hw_random/  // 框架根目录
    core.c  //框架核心代码
    omap-rng.c  // 各种类型的rng驱动
    hisi-trng-v2.c 
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5

    驱动适配

    • 驱动结构体和需要实现接口定义如下:
    // file: include/linux/hw_random.h
    /**
     * struct hwrng - Hardware Random Number Generator driver
     * @name:       Unique RNG name.
     * @init:       Initialization callback (can be NULL).
     * @cleanup:        Cleanup callback (can be NULL).
     * @data_present:   Callback to determine if data is available
     *          on the RNG. If NULL, it is assumed that
     *          there is always data available.  *OBSOLETE*
     * @data_read:      Read data from the RNG device.
     *          Returns the number of lower random bytes in "data".
     *          Must not be NULL.    *OBSOLETE*
     * @read:       New API. drivers can fill up to max bytes of data
     *          into the buffer. The buffer is aligned for any type
     *          and max is a multiple of 4 and >= 32 bytes.
     * @priv:       Private data, for use by the RNG driver.
     * @quality:        Estimation of true entropy in RNG's bitstream
     *          (in bits of entropy per 1024 bits of input;
     *          valid values: 1 to 1024, or 0 for unknown).
     */
    struct hwrng {
        const char *name;
        int (*init)(struct hwrng *rng);
        void (*cleanup)(struct hwrng *rng);
        int (*data_present)(struct hwrng *rng, int wait);
        int (*data_read)(struct hwrng *rng, u32 *data);
        int (*read)(struct hwrng *rng, void *data, size_t max, bool wait);
        unsigned long priv;
        unsigned short quality;
        
        /* internal. */
        struct list_head list;
        struct kref ref;
        struct completion cleanup_done;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 驱动实现需要在probe中定义一个struct hwrng对象,并按需实现相关接口,最后使用以下接口,向框架注册该驱动。
    // file: include/linux/hw_random.h
    /** Register a new Hardware Random Number Generator driver. */
    extern int hwrng_register(struct hwrng *rng);
    extern int devm_hwrng_register(struct device *dev, struct hwrng *rng);
    /** Unregister a Hardware Random Number Generator driver. */
    extern void hwrng_unregister(struct hwrng *rng);
    extern void devm_hwrng_unregister(struct device *dve, struct hwrng *rng);
    /** Feed random bits into the pool. */
    extern void add_hwgenerator_randomness(const char *buffer, size_t count, size_t entropy);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 具体实现比较简单,可以看下 hisi-trng-v2.c 实现。
    • 接口说明:
    1. init:初始化接口,可以为NULL
    2. cleanup:清理接口,可以为NULL
    3. data_present/data_read: 获取数据接口(已过时),根据core.c rng_get_data函数可知早期使用先调用data_present做些处理确认是否可以获取随机数,可以再调用data_read获取随机数。
    4. read:获取数据新接口。
    • 属性说明:
    1. name:设备名称(如果有多个,不能重复)
    2. priv:驱动私有数据,
    3. quality:返回随机数的质量评值,0表示未知;1~1024越大表示越随机。

    框架核心(core.c)

    • 框架module init时会创建缓存和注册misc设备节点(/dev/hwrng)。
    • 设备节点(/dev/hwrng)一直存在,但是没有当前rng(current_rng)是不可用的。

    hwrng注册

    1. 遍历rng链表(rng_list),如果rng name重复直接退出。
    2. 根据rng的quality值插入到的降序链表(rng_list)对应的位置。
    3. 若当前rng(current_rng)为空或者当前rng不为空(非用户设定),并且注册的rng quality大于当前rng,则将rng设置为current_rng, 并调用其init接口,做初始化等。
    • 详细请看hwrng_register实现。

    用户操作

    • 用户可以通过以下文件节点,做些配置
    ~# ls -l /sys/devices/virtual/misc/hw_random/
    total 0
    -r--r--r--    1 root     root          4096 Jan  1 16:05 dev
    -r--r--r--    1 root     root          4096 Jan  1 16:05 rng_available // 可选的rng,即rng list
    -rw-r--r--    1 root     root          4096 Jan  1 16:05 rng_current // 当前rng设备名称,可以写入名称来选择指定rng设备
    -r--r--r--    1 root     root          4096 Jan  1 16:05 rng_selected //是否由用户空间选择rng设备,1表示是
    lrwxrwxrwx    1 root     root             0 Jan  1 16:05 subsystem -> ../../../../class/misc
    -rw-r--r--    1 root     root          4096 Jan  1 16:05 uevent
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 用户可以通过设备节点(/dev/hwrng)获取生成的随机数,如果当前rng为空,会返回错误(设备不存在)。

    hwrng 初始化

    • hwrng注册或者用户选择rng时,会做hwrng初始化(hwrng init),启动一个内核线程(hwrng),每隔10s读取当前hwrng生成的随机数,保存到缓存中,通过函数(add_hwgenerator_randomness)将硬件产生的随机数添加到inpu_pool熵池中,给/dev/random和/dev/urandom使用。

    /dev/random和/dev/urandom

    • 由于hwrng不一定可用,Linux提供了另外两个随机数发生器。

    两者区别

    • 熵是一种可以体现随机性的值,充当生成随机数时使用的种子,熵越随机越好,hwrng添加到inpu_pool熵池中的随机数就是给/dev/random和/dev/urandom使用,当然还有别的熵来源(如硬件噪声),这两个设备文件都使用熵池(entropy pool)来收集熵。
    • /dev/random和/dev/urandom的区别主要在于它们如何收集并使用熵(entropy)。
    • /dev/random 使用一个阻塞式的熵池,当熵池的熵耗尽时,它会阻塞读取操作,直到收集到足够的熵。这种行为使得 /dev/random 更适合生成高质量的随机数,如密钥、证书等。
    • /dev/urandom 使用一个非阻塞式的熵池,当熵耗尽时,它不会阻塞,而是使用内部的伪随机数生成器(PRNG)继续生成随机数,这使得 /dev/urandom 在熵耗尽时仍能提供随机数,但生成的随机数可能没有 /dev/random 那么高的质量。

    系统调用 getrandom()

    • 默认是返回 /dev/urandom 中的 entropy。
  • 相关阅读:
    上海亚商投顾:沪指高开高走 锂电等新能源赛道大反攻
    学好MySQL增删查改,争取不做CURD程序员【下篇(六个小时肝MySQL万字大总结)】
    刚入职新公司,代码看懵逼了咋办?
    Netty核心源码剖析(四)
    find /root -type f -mtime +30 -exec rm {} ;的含义
    【OpenCV实现图像的几何变换】
    Unity-IOS证书和描述文件配置
    mysql安装完全排坑指南
    MongoDB 开源“可查询加密”系统 Queryable Encryption
    如何在USGS下载Landsat 8-9影像(2022年版)
  • 原文地址:https://blog.csdn.net/qazw9600/article/details/134484376