内核硬件随机数/dev/hwrng的一些规则

不管是否支持hwrng 都可以看到/dev/hwrng 这个字符设备,如果有真正的hwrng,则只是增加这个hwrng的随机性而已,同一个hwrng不能重复注册,而且会根据每个hwrng的quality 来选择一个质量最好的hwrng。
这里举例如下:drivers\crypto\hisilicon\trng.c
probe 中的核心代码如下:
trng->rng.name = pdev->name;
#这里提供的读取硬件随机数的方法
	trng->rng.read = hisi_trng_read;
#这里设置质量,在下面的函数中会选择质量高的,也就是越随机的作为当前的hwrng
	trng->rng.quality = HISI_TRNG_QUALITY;
	ret = devm_hwrng_register(&pdev->dev, &trng->rng);
	if (ret) {
		dev_err(&pdev->dev, "failed to register hwrng: %d!\n", ret);
		goto err_crypto_unregister;
	}

int devm_hwrng_register(struct device *dev, struct hwrng *rng)
{
	struct hwrng **ptr;
	int error;

	ptr = devres_alloc(devm_hwrng_release, sizeof(*ptr), GFP_KERNEL);
	if (!ptr)
		return -ENOMEM;
#核心函数,想系统中/dev/hwrng 提供真随机数
	error = hwrng_register(rng);
	if (error) {
		devres_free(ptr);
		return error;
	}

	*ptr = rng;
#将这个设备增加到一个list中
	devres_add(dev, ptr);
	return 0;
}

int hwrng_register(struct hwrng *rng)
{
	int err = -EINVAL;
	struct hwrng *tmp;
	struct list_head *rng_list_ptr;
	bool is_new_current = false;
#注册的随机数生成器必须有name和提供读取随机数的方法
	if (!rng->name || (!rng->data_read && !rng->read))
		goto out;

	mutex_lock(&rng_mutex);

	/* Must not register two RNGs with the same name. */
	err = -EEXIST;
#检查这个名字的随机数生成器是否已经注册过,所以前面一定要检查这个随机数要有名字,这里用名字来判断
#一个随机数是否注册过
	list_for_each_entry(tmp, &rng_list, list) {
		if (strcmp(tmp->name, rng->name) == 0)
			goto out_unlock;
	}

	init_completion(&rng->cleanup_done);
	complete(&rng->cleanup_done);
#更加qulity 对目前已有的随机数生成器进行排序,qulity越大说明产生的随机数越随机。
	/* rng_list is sorted by decreasing quality */
	list_for_each(rng_list_ptr, &rng_list) {
		tmp = list_entry(rng_list_ptr, struct hwrng, list);
		if (tmp->quality < rng->quality)
			break;
	}
	list_add_tail(&rng->list, rng_list_ptr);
#设置当前的随机数生成器
	if (!current_rng ||
	    (!cur_rng_set_by_user && rng->quality > current_rng->quality)) {
		/*
		 * Set new rng as current as the new rng source
		 * provides better entropy quality and was not
		 * chosen by userspace.
		 */
		err = set_current_rng(rng);
		if (err)
			goto out_unlock;
		/* to use current_rng in add_early_randomness() we need
		 * to take a ref
		 */
		is_new_current = true;
		kref_get(&rng->ref);
	}
	mutex_unlock(&rng_mutex);
	if (is_new_current || !rng->init) {
		/*
		 * Use a new device's input to add some randomness to
		 * the system.  If this rng device isn't going to be
		 * used right away, its init function hasn't been
		 * called yet by set_current_rng(); so only use the
		 * randomness from devices that don't need an init callback
		 */
#第一次增加随机数
		add_early_randomness(rng);
	}
	if (is_new_current)
		put_rng(rng);
	return 0;
out_unlock:
	mutex_unlock(&rng_mutex);
out:
	return err;
}

猜你喜欢

转载自blog.csdn.net/tiantao2012/article/details/113539495
今日推荐