mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	crypto: testmgr - add helpers for fuzzing against generic implementation
Add some helper functions in preparation for fuzz testing algorithms against their generic implementation. Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
		
							parent
							
								
									951d13328a
								
							
						
					
					
						commit
						f2bb770ae8
					
				
					 1 changed files with 128 additions and 0 deletions
				
			
		
							
								
								
									
										128
									
								
								crypto/testmgr.c
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								crypto/testmgr.c
									
									
									
									
									
								
							| 
						 | 
					@ -128,6 +128,7 @@ struct kpp_test_suite {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct alg_test_desc {
 | 
					struct alg_test_desc {
 | 
				
			||||||
	const char *alg;
 | 
						const char *alg;
 | 
				
			||||||
 | 
						const char *generic_driver;
 | 
				
			||||||
	int (*test)(const struct alg_test_desc *desc, const char *driver,
 | 
						int (*test)(const struct alg_test_desc *desc, const char *driver,
 | 
				
			||||||
		    u32 type, u32 mask);
 | 
							    u32 type, u32 mask);
 | 
				
			||||||
	int fips_allowed;	/* set if alg is allowed in fips mode */
 | 
						int fips_allowed;	/* set if alg is allowed in fips mode */
 | 
				
			||||||
| 
						 | 
					@ -745,6 +746,91 @@ static int build_cipher_test_sglists(struct cipher_test_sglists *tsgls,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
 | 
					#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Generate a random length in range [0, max_len], but prefer smaller values */
 | 
				
			||||||
 | 
					static unsigned int generate_random_length(unsigned int max_len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int len = prandom_u32() % (max_len + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (prandom_u32() % 4) {
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							return len % 64;
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							return len % 256;
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
							return len % 1024;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return len;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Sometimes make some random changes to the given data buffer */
 | 
				
			||||||
 | 
					static void mutate_buffer(u8 *buf, size_t count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						size_t num_flips;
 | 
				
			||||||
 | 
						size_t i;
 | 
				
			||||||
 | 
						size_t pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Sometimes flip some bits */
 | 
				
			||||||
 | 
						if (prandom_u32() % 4 == 0) {
 | 
				
			||||||
 | 
							num_flips = min_t(size_t, 1 << (prandom_u32() % 8), count * 8);
 | 
				
			||||||
 | 
							for (i = 0; i < num_flips; i++) {
 | 
				
			||||||
 | 
								pos = prandom_u32() % (count * 8);
 | 
				
			||||||
 | 
								buf[pos / 8] ^= 1 << (pos % 8);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Sometimes flip some bytes */
 | 
				
			||||||
 | 
						if (prandom_u32() % 4 == 0) {
 | 
				
			||||||
 | 
							num_flips = min_t(size_t, 1 << (prandom_u32() % 8), count);
 | 
				
			||||||
 | 
							for (i = 0; i < num_flips; i++)
 | 
				
			||||||
 | 
								buf[prandom_u32() % count] ^= 0xff;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Randomly generate 'count' bytes, but sometimes make them "interesting" */
 | 
				
			||||||
 | 
					static void generate_random_bytes(u8 *buf, size_t count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u8 b;
 | 
				
			||||||
 | 
						u8 increment;
 | 
				
			||||||
 | 
						size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (count == 0)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (prandom_u32() % 8) { /* Choose a generation strategy */
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							/* All the same byte, plus optional mutations */
 | 
				
			||||||
 | 
							switch (prandom_u32() % 4) {
 | 
				
			||||||
 | 
							case 0:
 | 
				
			||||||
 | 
								b = 0x00;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								b = 0xff;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								b = (u8)prandom_u32();
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							memset(buf, b, count);
 | 
				
			||||||
 | 
							mutate_buffer(buf, count);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
							/* Ascending or descending bytes, plus optional mutations */
 | 
				
			||||||
 | 
							increment = (u8)prandom_u32();
 | 
				
			||||||
 | 
							b = (u8)prandom_u32();
 | 
				
			||||||
 | 
							for (i = 0; i < count; i++, b += increment)
 | 
				
			||||||
 | 
								buf[i] = b;
 | 
				
			||||||
 | 
							mutate_buffer(buf, count);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							/* Fully random bytes */
 | 
				
			||||||
 | 
							for (i = 0; i < count; i++)
 | 
				
			||||||
 | 
								buf[i] = (u8)prandom_u32();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char *generate_random_sgl_divisions(struct test_sg_division *divs,
 | 
					static char *generate_random_sgl_divisions(struct test_sg_division *divs,
 | 
				
			||||||
					   size_t max_divs, char *p, char *end,
 | 
										   size_t max_divs, char *p, char *end,
 | 
				
			||||||
					   bool gen_flushes, u32 req_flags)
 | 
										   bool gen_flushes, u32 req_flags)
 | 
				
			||||||
| 
						 | 
					@ -899,6 +985,48 @@ static void crypto_reenable_simd_for_test(void)
 | 
				
			||||||
	__this_cpu_write(crypto_simd_disabled_for_test, false);
 | 
						__this_cpu_write(crypto_simd_disabled_for_test, false);
 | 
				
			||||||
	preempt_enable();
 | 
						preempt_enable();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Given an algorithm name, build the name of the generic implementation of that
 | 
				
			||||||
 | 
					 * algorithm, assuming the usual naming convention.  Specifically, this appends
 | 
				
			||||||
 | 
					 * "-generic" to every part of the name that is not a template name.  Examples:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	aes => aes-generic
 | 
				
			||||||
 | 
					 *	cbc(aes) => cbc(aes-generic)
 | 
				
			||||||
 | 
					 *	cts(cbc(aes)) => cts(cbc(aes-generic))
 | 
				
			||||||
 | 
					 *	rfc7539(chacha20,poly1305) => rfc7539(chacha20-generic,poly1305-generic)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: 0 on success, or -ENAMETOOLONG if the generic name would be too long
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int build_generic_driver_name(const char *algname,
 | 
				
			||||||
 | 
									     char driver_name[CRYPTO_MAX_ALG_NAME])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char *in = algname;
 | 
				
			||||||
 | 
						char *out = driver_name;
 | 
				
			||||||
 | 
						size_t len = strlen(algname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (len >= CRYPTO_MAX_ALG_NAME)
 | 
				
			||||||
 | 
							goto too_long;
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							const char *in_saved = in;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							while (*in && *in != '(' && *in != ')' && *in != ',')
 | 
				
			||||||
 | 
								*out++ = *in++;
 | 
				
			||||||
 | 
							if (*in != '(' && in > in_saved) {
 | 
				
			||||||
 | 
								len += 8;
 | 
				
			||||||
 | 
								if (len >= CRYPTO_MAX_ALG_NAME)
 | 
				
			||||||
 | 
									goto too_long;
 | 
				
			||||||
 | 
								memcpy(out, "-generic", 8);
 | 
				
			||||||
 | 
								out += 8;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} while ((*out++ = *in++) != '\0');
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					too_long:
 | 
				
			||||||
 | 
						pr_err("alg: generic driver name for \"%s\" would be too long\n",
 | 
				
			||||||
 | 
						       algname);
 | 
				
			||||||
 | 
						return -ENAMETOOLONG;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
 | 
					#else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
 | 
				
			||||||
static void crypto_disable_simd_for_test(void)
 | 
					static void crypto_disable_simd_for_test(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue