summaryrefslogtreecommitdiffstats
path: root/crypto/testmgr.c
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-04-12 00:57:40 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2019-04-18 10:15:03 -0400
commitd435e10e67be0a0df70502aee434cb62a9d65b10 (patch)
treef143ea66771eb39a29330f62211b3f23607df4de /crypto/testmgr.c
parent9a8a6b3f0950c0df220b684b686c26a902cfcf1a (diff)
crypto: testmgr - fuzz skciphers against their generic implementation
When the extra crypto self-tests are enabled, test each skcipher algorithm against its generic implementation when one is available. This involves: checking the algorithm properties for consistency, then randomly generating test vectors using the generic implementation and running them against the implementation under test. Both good and bad inputs are tested. This has already detected a bug in the skcipher_walk API, a bug in the LRW template, and an inconsistency in the cts implementations. Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/testmgr.c')
-rw-r--r--crypto/testmgr.c197
1 files changed, 197 insertions, 0 deletions
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index cafeba6ba16c..fe0cdf162d99 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -2124,6 +2124,186 @@ static int test_skcipher_vec(const char *driver, int enc,
2124 return 0; 2124 return 0;
2125} 2125}
2126 2126
2127#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
2128/*
2129 * Generate a symmetric cipher test vector from the given implementation.
2130 * Assumes the buffers in 'vec' were already allocated.
2131 */
2132static void generate_random_cipher_testvec(struct skcipher_request *req,
2133 struct cipher_testvec *vec,
2134 unsigned int maxdatasize,
2135 char *name, size_t max_namelen)
2136{
2137 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
2138 const unsigned int maxkeysize = tfm->keysize;
2139 const unsigned int ivsize = crypto_skcipher_ivsize(tfm);
2140 struct scatterlist src, dst;
2141 u8 iv[MAX_IVLEN];
2142 DECLARE_CRYPTO_WAIT(wait);
2143
2144 /* Key: length in [0, maxkeysize], but usually choose maxkeysize */
2145 vec->klen = maxkeysize;
2146 if (prandom_u32() % 4 == 0)
2147 vec->klen = prandom_u32() % (maxkeysize + 1);
2148 generate_random_bytes((u8 *)vec->key, vec->klen);
2149 vec->setkey_error = crypto_skcipher_setkey(tfm, vec->key, vec->klen);
2150
2151 /* IV */
2152 generate_random_bytes((u8 *)vec->iv, ivsize);
2153
2154 /* Plaintext */
2155 vec->len = generate_random_length(maxdatasize);
2156 generate_random_bytes((u8 *)vec->ptext, vec->len);
2157
2158 /* If the key couldn't be set, no need to continue to encrypt. */
2159 if (vec->setkey_error)
2160 goto done;
2161
2162 /* Ciphertext */
2163 sg_init_one(&src, vec->ptext, vec->len);
2164 sg_init_one(&dst, vec->ctext, vec->len);
2165 memcpy(iv, vec->iv, ivsize);
2166 skcipher_request_set_callback(req, 0, crypto_req_done, &wait);
2167 skcipher_request_set_crypt(req, &src, &dst, vec->len, iv);
2168 vec->crypt_error = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
2169done:
2170 snprintf(name, max_namelen, "\"random: len=%u klen=%u\"",
2171 vec->len, vec->klen);
2172}
2173
2174/*
2175 * Test the skcipher algorithm represented by @req against the corresponding
2176 * generic implementation, if one is available.
2177 */
2178static int test_skcipher_vs_generic_impl(const char *driver,
2179 const char *generic_driver,
2180 struct skcipher_request *req,
2181 struct cipher_test_sglists *tsgls)
2182{
2183 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
2184 const unsigned int ivsize = crypto_skcipher_ivsize(tfm);
2185 const unsigned int blocksize = crypto_skcipher_blocksize(tfm);
2186 const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN;
2187 const char *algname = crypto_skcipher_alg(tfm)->base.cra_name;
2188 char _generic_driver[CRYPTO_MAX_ALG_NAME];
2189 struct crypto_skcipher *generic_tfm = NULL;
2190 struct skcipher_request *generic_req = NULL;
2191 unsigned int i;
2192 struct cipher_testvec vec = { 0 };
2193 char vec_name[64];
2194 struct testvec_config cfg;
2195 char cfgname[TESTVEC_CONFIG_NAMELEN];
2196 int err;
2197
2198 if (noextratests)
2199 return 0;
2200
2201 /* Keywrap isn't supported here yet as it handles its IV differently. */
2202 if (strncmp(algname, "kw(", 3) == 0)
2203 return 0;
2204
2205 if (!generic_driver) { /* Use default naming convention? */
2206 err = build_generic_driver_name(algname, _generic_driver);
2207 if (err)
2208 return err;
2209 generic_driver = _generic_driver;
2210 }
2211
2212 if (strcmp(generic_driver, driver) == 0) /* Already the generic impl? */
2213 return 0;
2214
2215 generic_tfm = crypto_alloc_skcipher(generic_driver, 0, 0);
2216 if (IS_ERR(generic_tfm)) {
2217 err = PTR_ERR(generic_tfm);
2218 if (err == -ENOENT) {
2219 pr_warn("alg: skcipher: skipping comparison tests for %s because %s is unavailable\n",
2220 driver, generic_driver);
2221 return 0;
2222 }
2223 pr_err("alg: skcipher: error allocating %s (generic impl of %s): %d\n",
2224 generic_driver, algname, err);
2225 return err;
2226 }
2227
2228 generic_req = skcipher_request_alloc(generic_tfm, GFP_KERNEL);
2229 if (!generic_req) {
2230 err = -ENOMEM;
2231 goto out;
2232 }
2233
2234 /* Check the algorithm properties for consistency. */
2235
2236 if (tfm->keysize != generic_tfm->keysize) {
2237 pr_err("alg: skcipher: max keysize for %s (%u) doesn't match generic impl (%u)\n",
2238 driver, tfm->keysize, generic_tfm->keysize);
2239 err = -EINVAL;
2240 goto out;
2241 }
2242
2243 if (ivsize != crypto_skcipher_ivsize(generic_tfm)) {
2244 pr_err("alg: skcipher: ivsize for %s (%u) doesn't match generic impl (%u)\n",
2245 driver, ivsize, crypto_skcipher_ivsize(generic_tfm));
2246 err = -EINVAL;
2247 goto out;
2248 }
2249
2250 if (blocksize != crypto_skcipher_blocksize(generic_tfm)) {
2251 pr_err("alg: skcipher: blocksize for %s (%u) doesn't match generic impl (%u)\n",
2252 driver, blocksize,
2253 crypto_skcipher_blocksize(generic_tfm));
2254 err = -EINVAL;
2255 goto out;
2256 }
2257
2258 /*
2259 * Now generate test vectors using the generic implementation, and test
2260 * the other implementation against them.
2261 */
2262
2263 vec.key = kmalloc(tfm->keysize, GFP_KERNEL);
2264 vec.iv = kmalloc(ivsize, GFP_KERNEL);
2265 vec.ptext = kmalloc(maxdatasize, GFP_KERNEL);
2266 vec.ctext = kmalloc(maxdatasize, GFP_KERNEL);
2267 if (!vec.key || !vec.iv || !vec.ptext || !vec.ctext) {
2268 err = -ENOMEM;
2269 goto out;
2270 }
2271
2272 for (i = 0; i < fuzz_iterations * 8; i++) {
2273 generate_random_cipher_testvec(generic_req, &vec, maxdatasize,
2274 vec_name, sizeof(vec_name));
2275 generate_random_testvec_config(&cfg, cfgname, sizeof(cfgname));
2276
2277 err = test_skcipher_vec_cfg(driver, ENCRYPT, &vec, vec_name,
2278 &cfg, req, tsgls);
2279 if (err)
2280 goto out;
2281 err = test_skcipher_vec_cfg(driver, DECRYPT, &vec, vec_name,
2282 &cfg, req, tsgls);
2283 if (err)
2284 goto out;
2285 cond_resched();
2286 }
2287 err = 0;
2288out:
2289 kfree(vec.key);
2290 kfree(vec.iv);
2291 kfree(vec.ptext);
2292 kfree(vec.ctext);
2293 crypto_free_skcipher(generic_tfm);
2294 skcipher_request_free(generic_req);
2295 return err;
2296}
2297#else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
2298static int test_skcipher_vs_generic_impl(const char *driver,
2299 const char *generic_driver,
2300 struct skcipher_request *req,
2301 struct cipher_test_sglists *tsgls)
2302{
2303 return 0;
2304}
2305#endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
2306
2127static int test_skcipher(const char *driver, int enc, 2307static int test_skcipher(const char *driver, int enc,
2128 const struct cipher_test_suite *suite, 2308 const struct cipher_test_suite *suite,
2129 struct skcipher_request *req, 2309 struct skcipher_request *req,
@@ -2183,6 +2363,11 @@ static int alg_test_skcipher(const struct alg_test_desc *desc,
2183 goto out; 2363 goto out;
2184 2364
2185 err = test_skcipher(driver, DECRYPT, suite, req, tsgls); 2365 err = test_skcipher(driver, DECRYPT, suite, req, tsgls);
2366 if (err)
2367 goto out;
2368
2369 err = test_skcipher_vs_generic_impl(driver, desc->generic_driver, req,
2370 tsgls);
2186out: 2371out:
2187 free_cipher_test_sglists(tsgls); 2372 free_cipher_test_sglists(tsgls);
2188 skcipher_request_free(req); 2373 skcipher_request_free(req);
@@ -3164,12 +3349,14 @@ static int alg_test_null(const struct alg_test_desc *desc,
3164static const struct alg_test_desc alg_test_descs[] = { 3349static const struct alg_test_desc alg_test_descs[] = {
3165 { 3350 {
3166 .alg = "adiantum(xchacha12,aes)", 3351 .alg = "adiantum(xchacha12,aes)",
3352 .generic_driver = "adiantum(xchacha12-generic,aes-generic,nhpoly1305-generic)",
3167 .test = alg_test_skcipher, 3353 .test = alg_test_skcipher,
3168 .suite = { 3354 .suite = {
3169 .cipher = __VECS(adiantum_xchacha12_aes_tv_template) 3355 .cipher = __VECS(adiantum_xchacha12_aes_tv_template)
3170 }, 3356 },
3171 }, { 3357 }, {
3172 .alg = "adiantum(xchacha20,aes)", 3358 .alg = "adiantum(xchacha20,aes)",
3359 .generic_driver = "adiantum(xchacha20-generic,aes-generic,nhpoly1305-generic)",
3173 .test = alg_test_skcipher, 3360 .test = alg_test_skcipher,
3174 .suite = { 3361 .suite = {
3175 .cipher = __VECS(adiantum_xchacha20_aes_tv_template) 3362 .cipher = __VECS(adiantum_xchacha20_aes_tv_template)
@@ -3948,30 +4135,35 @@ static const struct alg_test_desc alg_test_descs[] = {
3948 } 4135 }
3949 }, { 4136 }, {
3950 .alg = "lrw(aes)", 4137 .alg = "lrw(aes)",
4138 .generic_driver = "lrw(ecb(aes-generic))",
3951 .test = alg_test_skcipher, 4139 .test = alg_test_skcipher,
3952 .suite = { 4140 .suite = {
3953 .cipher = __VECS(aes_lrw_tv_template) 4141 .cipher = __VECS(aes_lrw_tv_template)
3954 } 4142 }
3955 }, { 4143 }, {
3956 .alg = "lrw(camellia)", 4144 .alg = "lrw(camellia)",
4145 .generic_driver = "lrw(ecb(camellia-generic))",
3957 .test = alg_test_skcipher, 4146 .test = alg_test_skcipher,
3958 .suite = { 4147 .suite = {
3959 .cipher = __VECS(camellia_lrw_tv_template) 4148 .cipher = __VECS(camellia_lrw_tv_template)
3960 } 4149 }
3961 }, { 4150 }, {
3962 .alg = "lrw(cast6)", 4151 .alg = "lrw(cast6)",
4152 .generic_driver = "lrw(ecb(cast6-generic))",
3963 .test = alg_test_skcipher, 4153 .test = alg_test_skcipher,
3964 .suite = { 4154 .suite = {
3965 .cipher = __VECS(cast6_lrw_tv_template) 4155 .cipher = __VECS(cast6_lrw_tv_template)
3966 } 4156 }
3967 }, { 4157 }, {
3968 .alg = "lrw(serpent)", 4158 .alg = "lrw(serpent)",
4159 .generic_driver = "lrw(ecb(serpent-generic))",
3969 .test = alg_test_skcipher, 4160 .test = alg_test_skcipher,
3970 .suite = { 4161 .suite = {
3971 .cipher = __VECS(serpent_lrw_tv_template) 4162 .cipher = __VECS(serpent_lrw_tv_template)
3972 } 4163 }
3973 }, { 4164 }, {
3974 .alg = "lrw(twofish)", 4165 .alg = "lrw(twofish)",
4166 .generic_driver = "lrw(ecb(twofish-generic))",
3975 .test = alg_test_skcipher, 4167 .test = alg_test_skcipher,
3976 .suite = { 4168 .suite = {
3977 .cipher = __VECS(tf_lrw_tv_template) 4169 .cipher = __VECS(tf_lrw_tv_template)
@@ -4306,6 +4498,7 @@ static const struct alg_test_desc alg_test_descs[] = {
4306 }, 4498 },
4307 }, { 4499 }, {
4308 .alg = "xts(aes)", 4500 .alg = "xts(aes)",
4501 .generic_driver = "xts(ecb(aes-generic))",
4309 .test = alg_test_skcipher, 4502 .test = alg_test_skcipher,
4310 .fips_allowed = 1, 4503 .fips_allowed = 1,
4311 .suite = { 4504 .suite = {
@@ -4313,12 +4506,14 @@ static const struct alg_test_desc alg_test_descs[] = {
4313 } 4506 }
4314 }, { 4507 }, {
4315 .alg = "xts(camellia)", 4508 .alg = "xts(camellia)",
4509 .generic_driver = "xts(ecb(camellia-generic))",
4316 .test = alg_test_skcipher, 4510 .test = alg_test_skcipher,
4317 .suite = { 4511 .suite = {
4318 .cipher = __VECS(camellia_xts_tv_template) 4512 .cipher = __VECS(camellia_xts_tv_template)
4319 } 4513 }
4320 }, { 4514 }, {
4321 .alg = "xts(cast6)", 4515 .alg = "xts(cast6)",
4516 .generic_driver = "xts(ecb(cast6-generic))",
4322 .test = alg_test_skcipher, 4517 .test = alg_test_skcipher,
4323 .suite = { 4518 .suite = {
4324 .cipher = __VECS(cast6_xts_tv_template) 4519 .cipher = __VECS(cast6_xts_tv_template)
@@ -4332,12 +4527,14 @@ static const struct alg_test_desc alg_test_descs[] = {
4332 .fips_allowed = 1, 4527 .fips_allowed = 1,
4333 }, { 4528 }, {
4334 .alg = "xts(serpent)", 4529 .alg = "xts(serpent)",
4530 .generic_driver = "xts(ecb(serpent-generic))",
4335 .test = alg_test_skcipher, 4531 .test = alg_test_skcipher,
4336 .suite = { 4532 .suite = {
4337 .cipher = __VECS(serpent_xts_tv_template) 4533 .cipher = __VECS(serpent_xts_tv_template)
4338 } 4534 }
4339 }, { 4535 }, {
4340 .alg = "xts(twofish)", 4536 .alg = "xts(twofish)",
4537 .generic_driver = "xts(ecb(twofish-generic))",
4341 .test = alg_test_skcipher, 4538 .test = alg_test_skcipher,
4342 .suite = { 4539 .suite = {
4343 .cipher = __VECS(tf_xts_tv_template) 4540 .cipher = __VECS(tf_xts_tv_template)