diff options
Diffstat (limited to 'crypto/testmgr.c')
-rw-r--r-- | crypto/testmgr.c | 197 |
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 | */ | ||
2132 | static 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); | ||
2169 | done: | ||
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 | */ | ||
2178 | static 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; | ||
2288 | out: | ||
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 */ | ||
2298 | static 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 | |||
2127 | static int test_skcipher(const char *driver, int enc, | 2307 | static 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); | ||
2186 | out: | 2371 | out: |
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, | |||
3164 | static const struct alg_test_desc alg_test_descs[] = { | 3349 | static 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) |