forked from mirrors/linux
		
	hwrng: core - start hwrng kthread also for untrusted sources
Start the hwrng kthread even if the hwrng source has a quality setting of zero. Then, every crng reseed interval, one batch of data from this zero-quality hwrng source will be mixed into the CRNG pool. This patch is based on the assumption that data from a hwrng source will not actively harm the CRNG state. Instead, many hwrng sources (such as TPM devices), even though they are assigend a quality level of zero, actually provide some entropy, which is good enough to mix into the CRNG pool every once in a while. Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: Jason A. Donenfeld <Jason@zx2c4.com> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
		
							parent
							
								
									4edff849f7
								
							
						
					
					
						commit
						b006c439d5
					
				
					 1 changed files with 10 additions and 26 deletions
				
			
		|  | @ -52,7 +52,7 @@ MODULE_PARM_DESC(default_quality, | ||||||
| 
 | 
 | ||||||
| static void drop_current_rng(void); | static void drop_current_rng(void); | ||||||
| static int hwrng_init(struct hwrng *rng); | static int hwrng_init(struct hwrng *rng); | ||||||
| static void hwrng_manage_rngd(struct hwrng *rng); | static int hwrng_fillfn(void *unused); | ||||||
| 
 | 
 | ||||||
| static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size, | static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size, | ||||||
| 			       int wait); | 			       int wait); | ||||||
|  | @ -96,6 +96,15 @@ static int set_current_rng(struct hwrng *rng) | ||||||
| 	drop_current_rng(); | 	drop_current_rng(); | ||||||
| 	current_rng = rng; | 	current_rng = rng; | ||||||
| 
 | 
 | ||||||
|  | 	/* if necessary, start hwrng thread */ | ||||||
|  | 	if (!hwrng_fill) { | ||||||
|  | 		hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng"); | ||||||
|  | 		if (IS_ERR(hwrng_fill)) { | ||||||
|  | 			pr_err("hwrng_fill thread creation failed\n"); | ||||||
|  | 			hwrng_fill = NULL; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -167,8 +176,6 @@ static int hwrng_init(struct hwrng *rng) | ||||||
| 		rng->quality = 1024; | 		rng->quality = 1024; | ||||||
| 	current_quality = rng->quality; /* obsolete */ | 	current_quality = rng->quality; /* obsolete */ | ||||||
| 
 | 
 | ||||||
| 	hwrng_manage_rngd(rng); |  | ||||||
| 
 |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -454,10 +461,6 @@ static ssize_t rng_quality_store(struct device *dev, | ||||||
| 	/* the best available RNG may have changed */ | 	/* the best available RNG may have changed */ | ||||||
| 	ret = enable_best_rng(); | 	ret = enable_best_rng(); | ||||||
| 
 | 
 | ||||||
| 	/* start/stop rngd if necessary */ |  | ||||||
| 	if (current_rng) |  | ||||||
| 		hwrng_manage_rngd(current_rng); |  | ||||||
| 
 |  | ||||||
| out: | out: | ||||||
| 	mutex_unlock(&rng_mutex); | 	mutex_unlock(&rng_mutex); | ||||||
| 	return ret ? ret : len; | 	return ret ? ret : len; | ||||||
|  | @ -513,9 +516,6 @@ static int hwrng_fillfn(void *unused) | ||||||
| 
 | 
 | ||||||
| 		put_rng(rng); | 		put_rng(rng); | ||||||
| 
 | 
 | ||||||
| 		if (!quality) |  | ||||||
| 			break; |  | ||||||
| 
 |  | ||||||
| 		if (rc <= 0) | 		if (rc <= 0) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
|  | @ -534,22 +534,6 @@ static int hwrng_fillfn(void *unused) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void hwrng_manage_rngd(struct hwrng *rng) |  | ||||||
| { |  | ||||||
| 	if (WARN_ON(!mutex_is_locked(&rng_mutex))) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	if (rng->quality == 0 && hwrng_fill) |  | ||||||
| 		kthread_stop(hwrng_fill); |  | ||||||
| 	if (rng->quality > 0 && !hwrng_fill) { |  | ||||||
| 		hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng"); |  | ||||||
| 		if (IS_ERR(hwrng_fill)) { |  | ||||||
| 			pr_err("hwrng_fill thread creation failed\n"); |  | ||||||
| 			hwrng_fill = NULL; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int hwrng_register(struct hwrng *rng) | int hwrng_register(struct hwrng *rng) | ||||||
| { | { | ||||||
| 	int err = -EINVAL; | 	int err = -EINVAL; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Dominik Brodowski
						Dominik Brodowski