aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-04-12 00:57:41 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2019-04-18 10:15:03 -0400
commit40153b10d91c9e25f912344ba6ce1f0874400659 (patch)
tree04b0d981b8010545897fbd90a8765b15d11f2f84 /crypto
parentd435e10e67be0a0df70502aee434cb62a9d65b10 (diff)
crypto: testmgr - fuzz AEADs against their generic implementation
When the extra crypto self-tests are enabled, test each AEAD 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. Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/testmgr.c229
1 files changed, 229 insertions, 0 deletions
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index fe0cdf162d99..87abfd1ce232 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1767,6 +1767,226 @@ static int test_aead_vec(const char *driver, int enc,
1767 return 0; 1767 return 0;
1768} 1768}
1769 1769
1770#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
1771/*
1772 * Generate an AEAD test vector from the given implementation.
1773 * Assumes the buffers in 'vec' were already allocated.
1774 */
1775static void generate_random_aead_testvec(struct aead_request *req,
1776 struct aead_testvec *vec,
1777 unsigned int maxkeysize,
1778 unsigned int maxdatasize,
1779 char *name, size_t max_namelen)
1780{
1781 struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1782 const unsigned int ivsize = crypto_aead_ivsize(tfm);
1783 unsigned int maxauthsize = crypto_aead_alg(tfm)->maxauthsize;
1784 unsigned int authsize;
1785 unsigned int total_len;
1786 int i;
1787 struct scatterlist src[2], dst;
1788 u8 iv[MAX_IVLEN];
1789 DECLARE_CRYPTO_WAIT(wait);
1790
1791 /* Key: length in [0, maxkeysize], but usually choose maxkeysize */
1792 vec->klen = maxkeysize;
1793 if (prandom_u32() % 4 == 0)
1794 vec->klen = prandom_u32() % (maxkeysize + 1);
1795 generate_random_bytes((u8 *)vec->key, vec->klen);
1796 vec->setkey_error = crypto_aead_setkey(tfm, vec->key, vec->klen);
1797
1798 /* IV */
1799 generate_random_bytes((u8 *)vec->iv, ivsize);
1800
1801 /* Tag length: in [0, maxauthsize], but usually choose maxauthsize */
1802 authsize = maxauthsize;
1803 if (prandom_u32() % 4 == 0)
1804 authsize = prandom_u32() % (maxauthsize + 1);
1805 if (WARN_ON(authsize > maxdatasize))
1806 authsize = maxdatasize;
1807 maxdatasize -= authsize;
1808 vec->setauthsize_error = crypto_aead_setauthsize(tfm, authsize);
1809
1810 /* Plaintext and associated data */
1811 total_len = generate_random_length(maxdatasize);
1812 if (prandom_u32() % 4 == 0)
1813 vec->alen = 0;
1814 else
1815 vec->alen = generate_random_length(total_len);
1816 vec->plen = total_len - vec->alen;
1817 generate_random_bytes((u8 *)vec->assoc, vec->alen);
1818 generate_random_bytes((u8 *)vec->ptext, vec->plen);
1819
1820 vec->clen = vec->plen + authsize;
1821
1822 /*
1823 * If the key or authentication tag size couldn't be set, no need to
1824 * continue to encrypt.
1825 */
1826 if (vec->setkey_error || vec->setauthsize_error)
1827 goto done;
1828
1829 /* Ciphertext */
1830 sg_init_table(src, 2);
1831 i = 0;
1832 if (vec->alen)
1833 sg_set_buf(&src[i++], vec->assoc, vec->alen);
1834 if (vec->plen)
1835 sg_set_buf(&src[i++], vec->ptext, vec->plen);
1836 sg_init_one(&dst, vec->ctext, vec->alen + vec->clen);
1837 memcpy(iv, vec->iv, ivsize);
1838 aead_request_set_callback(req, 0, crypto_req_done, &wait);
1839 aead_request_set_crypt(req, src, &dst, vec->plen, iv);
1840 aead_request_set_ad(req, vec->alen);
1841 vec->crypt_error = crypto_wait_req(crypto_aead_encrypt(req), &wait);
1842 if (vec->crypt_error == 0)
1843 memmove((u8 *)vec->ctext, vec->ctext + vec->alen, vec->clen);
1844done:
1845 snprintf(name, max_namelen,
1846 "\"random: alen=%u plen=%u authsize=%u klen=%u\"",
1847 vec->alen, vec->plen, authsize, vec->klen);
1848}
1849
1850/*
1851 * Test the AEAD algorithm represented by @req against the corresponding generic
1852 * implementation, if one is available.
1853 */
1854static int test_aead_vs_generic_impl(const char *driver,
1855 const struct alg_test_desc *test_desc,
1856 struct aead_request *req,
1857 struct cipher_test_sglists *tsgls)
1858{
1859 struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1860 const unsigned int ivsize = crypto_aead_ivsize(tfm);
1861 const unsigned int maxauthsize = crypto_aead_alg(tfm)->maxauthsize;
1862 const unsigned int blocksize = crypto_aead_blocksize(tfm);
1863 const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN;
1864 const char *algname = crypto_aead_alg(tfm)->base.cra_name;
1865 const char *generic_driver = test_desc->generic_driver;
1866 char _generic_driver[CRYPTO_MAX_ALG_NAME];
1867 struct crypto_aead *generic_tfm = NULL;
1868 struct aead_request *generic_req = NULL;
1869 unsigned int maxkeysize;
1870 unsigned int i;
1871 struct aead_testvec vec = { 0 };
1872 char vec_name[64];
1873 struct testvec_config cfg;
1874 char cfgname[TESTVEC_CONFIG_NAMELEN];
1875 int err;
1876
1877 if (noextratests)
1878 return 0;
1879
1880 if (!generic_driver) { /* Use default naming convention? */
1881 err = build_generic_driver_name(algname, _generic_driver);
1882 if (err)
1883 return err;
1884 generic_driver = _generic_driver;
1885 }
1886
1887 if (strcmp(generic_driver, driver) == 0) /* Already the generic impl? */
1888 return 0;
1889
1890 generic_tfm = crypto_alloc_aead(generic_driver, 0, 0);
1891 if (IS_ERR(generic_tfm)) {
1892 err = PTR_ERR(generic_tfm);
1893 if (err == -ENOENT) {
1894 pr_warn("alg: aead: skipping comparison tests for %s because %s is unavailable\n",
1895 driver, generic_driver);
1896 return 0;
1897 }
1898 pr_err("alg: aead: error allocating %s (generic impl of %s): %d\n",
1899 generic_driver, algname, err);
1900 return err;
1901 }
1902
1903 generic_req = aead_request_alloc(generic_tfm, GFP_KERNEL);
1904 if (!generic_req) {
1905 err = -ENOMEM;
1906 goto out;
1907 }
1908
1909 /* Check the algorithm properties for consistency. */
1910
1911 if (maxauthsize != crypto_aead_alg(generic_tfm)->maxauthsize) {
1912 pr_err("alg: aead: maxauthsize for %s (%u) doesn't match generic impl (%u)\n",
1913 driver, maxauthsize,
1914 crypto_aead_alg(generic_tfm)->maxauthsize);
1915 err = -EINVAL;
1916 goto out;
1917 }
1918
1919 if (ivsize != crypto_aead_ivsize(generic_tfm)) {
1920 pr_err("alg: aead: ivsize for %s (%u) doesn't match generic impl (%u)\n",
1921 driver, ivsize, crypto_aead_ivsize(generic_tfm));
1922 err = -EINVAL;
1923 goto out;
1924 }
1925
1926 if (blocksize != crypto_aead_blocksize(generic_tfm)) {
1927 pr_err("alg: aead: blocksize for %s (%u) doesn't match generic impl (%u)\n",
1928 driver, blocksize, crypto_aead_blocksize(generic_tfm));
1929 err = -EINVAL;
1930 goto out;
1931 }
1932
1933 /*
1934 * Now generate test vectors using the generic implementation, and test
1935 * the other implementation against them.
1936 */
1937
1938 maxkeysize = 0;
1939 for (i = 0; i < test_desc->suite.aead.count; i++)
1940 maxkeysize = max_t(unsigned int, maxkeysize,
1941 test_desc->suite.aead.vecs[i].klen);
1942
1943 vec.key = kmalloc(maxkeysize, GFP_KERNEL);
1944 vec.iv = kmalloc(ivsize, GFP_KERNEL);
1945 vec.assoc = kmalloc(maxdatasize, GFP_KERNEL);
1946 vec.ptext = kmalloc(maxdatasize, GFP_KERNEL);
1947 vec.ctext = kmalloc(maxdatasize, GFP_KERNEL);
1948 if (!vec.key || !vec.iv || !vec.assoc || !vec.ptext || !vec.ctext) {
1949 err = -ENOMEM;
1950 goto out;
1951 }
1952
1953 for (i = 0; i < fuzz_iterations * 8; i++) {
1954 generate_random_aead_testvec(generic_req, &vec,
1955 maxkeysize, maxdatasize,
1956 vec_name, sizeof(vec_name));
1957 generate_random_testvec_config(&cfg, cfgname, sizeof(cfgname));
1958
1959 err = test_aead_vec_cfg(driver, ENCRYPT, &vec, vec_name, &cfg,
1960 req, tsgls);
1961 if (err)
1962 goto out;
1963 err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name, &cfg,
1964 req, tsgls);
1965 if (err)
1966 goto out;
1967 cond_resched();
1968 }
1969 err = 0;
1970out:
1971 kfree(vec.key);
1972 kfree(vec.iv);
1973 kfree(vec.assoc);
1974 kfree(vec.ptext);
1975 kfree(vec.ctext);
1976 crypto_free_aead(generic_tfm);
1977 aead_request_free(generic_req);
1978 return err;
1979}
1980#else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
1981static int test_aead_vs_generic_impl(const char *driver,
1982 const struct alg_test_desc *test_desc,
1983 struct aead_request *req,
1984 struct cipher_test_sglists *tsgls)
1985{
1986 return 0;
1987}
1988#endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
1989
1770static int test_aead(const char *driver, int enc, 1990static int test_aead(const char *driver, int enc,
1771 const struct aead_test_suite *suite, 1991 const struct aead_test_suite *suite,
1772 struct aead_request *req, 1992 struct aead_request *req,
@@ -1826,6 +2046,10 @@ static int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
1826 goto out; 2046 goto out;
1827 2047
1828 err = test_aead(driver, DECRYPT, suite, req, tsgls); 2048 err = test_aead(driver, DECRYPT, suite, req, tsgls);
2049 if (err)
2050 goto out;
2051
2052 err = test_aead_vs_generic_impl(driver, desc, req, tsgls);
1829out: 2053out:
1830 free_cipher_test_sglists(tsgls); 2054 free_cipher_test_sglists(tsgls);
1831 aead_request_free(req); 2055 aead_request_free(req);
@@ -3599,6 +3823,7 @@ static const struct alg_test_desc alg_test_descs[] = {
3599 } 3823 }
3600 }, { 3824 }, {
3601 .alg = "ccm(aes)", 3825 .alg = "ccm(aes)",
3826 .generic_driver = "ccm_base(ctr(aes-generic),cbcmac(aes-generic))",
3602 .test = alg_test_aead, 3827 .test = alg_test_aead,
3603 .fips_allowed = 1, 3828 .fips_allowed = 1,
3604 .suite = { 3829 .suite = {
@@ -4017,6 +4242,7 @@ static const struct alg_test_desc alg_test_descs[] = {
4017 } 4242 }
4018 }, { 4243 }, {
4019 .alg = "gcm(aes)", 4244 .alg = "gcm(aes)",
4245 .generic_driver = "gcm_base(ctr(aes-generic),ghash-generic)",
4020 .test = alg_test_aead, 4246 .test = alg_test_aead,
4021 .fips_allowed = 1, 4247 .fips_allowed = 1,
4022 .suite = { 4248 .suite = {
@@ -4288,6 +4514,7 @@ static const struct alg_test_desc alg_test_descs[] = {
4288 } 4514 }
4289 }, { 4515 }, {
4290 .alg = "rfc4106(gcm(aes))", 4516 .alg = "rfc4106(gcm(aes))",
4517 .generic_driver = "rfc4106(gcm_base(ctr(aes-generic),ghash-generic))",
4291 .test = alg_test_aead, 4518 .test = alg_test_aead,
4292 .fips_allowed = 1, 4519 .fips_allowed = 1,
4293 .suite = { 4520 .suite = {
@@ -4295,6 +4522,7 @@ static const struct alg_test_desc alg_test_descs[] = {
4295 } 4522 }
4296 }, { 4523 }, {
4297 .alg = "rfc4309(ccm(aes))", 4524 .alg = "rfc4309(ccm(aes))",
4525 .generic_driver = "rfc4309(ccm_base(ctr(aes-generic),cbcmac(aes-generic)))",
4298 .test = alg_test_aead, 4526 .test = alg_test_aead,
4299 .fips_allowed = 1, 4527 .fips_allowed = 1,
4300 .suite = { 4528 .suite = {
@@ -4302,6 +4530,7 @@ static const struct alg_test_desc alg_test_descs[] = {
4302 } 4530 }
4303 }, { 4531 }, {
4304 .alg = "rfc4543(gcm(aes))", 4532 .alg = "rfc4543(gcm(aes))",
4533 .generic_driver = "rfc4543(gcm_base(ctr(aes-generic),ghash-generic))",
4305 .test = alg_test_aead, 4534 .test = alg_test_aead,
4306 .suite = { 4535 .suite = {
4307 .aead = __VECS(aes_gcm_rfc4543_tv_template) 4536 .aead = __VECS(aes_gcm_rfc4543_tv_template)