} comp, decomp;
};
+struct pcomp_test_suite {
+ struct {
+ struct pcomp_testvec *vecs;
+ unsigned int count;
+ } comp, decomp;
+};
+
struct hash_test_suite {
struct hash_testvec *vecs;
unsigned int count;
struct aead_test_suite aead;
struct cipher_test_suite cipher;
struct comp_test_suite comp;
+ struct pcomp_test_suite pcomp;
struct hash_test_suite hash;
} suite;
};
return ret;
}
-static int test_cipher(struct crypto_ablkcipher *tfm, int enc,
+static int test_cipher(struct crypto_cipher *tfm, int enc,
struct cipher_testvec *template, unsigned int tcount)
{
+ const char *algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm));
+ unsigned int i, j, k;
+ int ret;
+ char *q;
+ const char *e;
+ void *data;
+
+ if (enc == ENCRYPT)
+ e = "encryption";
+ else
+ e = "decryption";
+
+ j = 0;
+ for (i = 0; i < tcount; i++) {
+ if (template[i].np)
+ continue;
+
+ j++;
+
+ data = xbuf[0];
+ memcpy(data, template[i].input, template[i].ilen);
+
+ crypto_cipher_clear_flags(tfm, ~0);
+ if (template[i].wk)
+ crypto_cipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+
+ ret = crypto_cipher_setkey(tfm, template[i].key,
+ template[i].klen);
+ if (!ret == template[i].fail) {
+ printk(KERN_ERR "alg: cipher: setkey failed "
+ "on test %d for %s: flags=%x\n", j,
+ algo, crypto_cipher_get_flags(tfm));
+ goto out;
+ } else if (ret)
+ continue;
+
+ for (k = 0; k < template[i].ilen;
+ k += crypto_cipher_blocksize(tfm)) {
+ if (enc)
+ crypto_cipher_encrypt_one(tfm, data + k,
+ data + k);
+ else
+ crypto_cipher_decrypt_one(tfm, data + k,
+ data + k);
+ }
+
+ q = data;
+ if (memcmp(q, template[i].result, template[i].rlen)) {
+ printk(KERN_ERR "alg: cipher: Test %d failed "
+ "on %s for %s\n", j, e, algo);
+ hexdump(q, template[i].rlen);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,
+ struct cipher_testvec *template, unsigned int tcount)
+{
const char *algo =
crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
unsigned int i, j, k, n, temp;
req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
if (!req) {
- printk(KERN_ERR "alg: cipher: Failed to allocate request for "
- "%s\n", algo);
+ printk(KERN_ERR "alg: skcipher: Failed to allocate request "
+ "for %s\n", algo);
ret = -ENOMEM;
goto out;
}
ret = crypto_ablkcipher_setkey(tfm, template[i].key,
template[i].klen);
if (!ret == template[i].fail) {
- printk(KERN_ERR "alg: cipher: setkey failed "
+ printk(KERN_ERR "alg: skcipher: setkey failed "
"on test %d for %s: flags=%x\n", j,
algo, crypto_ablkcipher_get_flags(tfm));
goto out;
}
/* fall through */
default:
- printk(KERN_ERR "alg: cipher: %s failed on "
+ printk(KERN_ERR "alg: skcipher: %s failed on "
"test %d for %s: ret=%d\n", e, j, algo,
-ret);
goto out;
q = data;
if (memcmp(q, template[i].result, template[i].rlen)) {
- printk(KERN_ERR "alg: cipher: Test %d failed "
- "on %s for %s\n", j, e, algo);
+ printk(KERN_ERR "alg: skcipher: Test %d "
+ "failed on %s for %s\n", j, e, algo);
hexdump(q, template[i].rlen);
ret = -EINVAL;
goto out;
ret = crypto_ablkcipher_setkey(tfm, template[i].key,
template[i].klen);
if (!ret == template[i].fail) {
- printk(KERN_ERR "alg: cipher: setkey failed "
+ printk(KERN_ERR "alg: skcipher: setkey failed "
"on chunk test %d for %s: flags=%x\n",
j, algo,
crypto_ablkcipher_get_flags(tfm));
}
/* fall through */
default:
- printk(KERN_ERR "alg: cipher: %s failed on "
+ printk(KERN_ERR "alg: skcipher: %s failed on "
"chunk test %d for %s: ret=%d\n", e, j,
algo, -ret);
goto out;
if (memcmp(q, template[i].result + temp,
template[i].tap[k])) {
- printk(KERN_ERR "alg: cipher: Chunk "
+ printk(KERN_ERR "alg: skcipher: Chunk "
"test %d failed on %s at page "
"%u for %s\n", j, e, k, algo);
hexdump(q, template[i].tap[k]);
for (n = 0; offset_in_page(q + n) && q[n]; n++)
;
if (n) {
- printk(KERN_ERR "alg: cipher: "
+ printk(KERN_ERR "alg: skcipher: "
"Result buffer corruption in "
"chunk test %d on %s at page "
"%u for %s: %u bytes:\n", j, e,
goto out;
}
+ if (dlen != ctemplate[i].outlen) {
+ printk(KERN_ERR "alg: comp: Compression test %d "
+ "failed for %s: output len = %d\n", i + 1, algo,
+ dlen);
+ ret = -EINVAL;
+ goto out;
+ }
+
if (memcmp(result, ctemplate[i].output, dlen)) {
printk(KERN_ERR "alg: comp: Compression test %d "
"failed for %s\n", i + 1, algo);
}
for (i = 0; i < dtcount; i++) {
- int ilen, ret, dlen = COMP_BUF_SIZE;
+ int ilen, dlen = COMP_BUF_SIZE;
memset(result, 0, sizeof (result));
goto out;
}
+ if (dlen != dtemplate[i].outlen) {
+ printk(KERN_ERR "alg: comp: Decompression test %d "
+ "failed for %s: output len = %d\n", i + 1, algo,
+ dlen);
+ ret = -EINVAL;
+ goto out;
+ }
+
if (memcmp(result, dtemplate[i].output, dlen)) {
printk(KERN_ERR "alg: comp: Decompression test %d "
"failed for %s\n", i + 1, algo);
return ret;
}
+static int test_pcomp(struct crypto_pcomp *tfm,
+ struct pcomp_testvec *ctemplate,
+ struct pcomp_testvec *dtemplate, int ctcount,
+ int dtcount)
+{
+ const char *algo = crypto_tfm_alg_driver_name(crypto_pcomp_tfm(tfm));
+ unsigned int i;
+ char result[COMP_BUF_SIZE];
+ int error;
+
+ for (i = 0; i < ctcount; i++) {
+ struct comp_request req;
+
+ error = crypto_compress_setup(tfm, ctemplate[i].params,
+ ctemplate[i].paramsize);
+ if (error) {
+ pr_err("alg: pcomp: compression setup failed on test "
+ "%d for %s: error=%d\n", i + 1, algo, error);
+ return error;
+ }
+
+ error = crypto_compress_init(tfm);
+ if (error) {
+ pr_err("alg: pcomp: compression init failed on test "
+ "%d for %s: error=%d\n", i + 1, algo, error);
+ return error;
+ }
+
+ memset(result, 0, sizeof(result));
+
+ req.next_in = ctemplate[i].input;
+ req.avail_in = ctemplate[i].inlen / 2;
+ req.next_out = result;
+ req.avail_out = ctemplate[i].outlen / 2;
+
+ error = crypto_compress_update(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_err("alg: pcomp: compression update failed on test "
+ "%d for %s: error=%d\n", i + 1, algo, error);
+ return error;
+ }
+
+ /* Add remaining input data */
+ req.avail_in += (ctemplate[i].inlen + 1) / 2;
+
+ error = crypto_compress_update(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_err("alg: pcomp: compression update failed on test "
+ "%d for %s: error=%d\n", i + 1, algo, error);
+ return error;
+ }
+
+ /* Provide remaining output space */
+ req.avail_out += COMP_BUF_SIZE - ctemplate[i].outlen / 2;
+
+ error = crypto_compress_final(tfm, &req);
+ if (error) {
+ pr_err("alg: pcomp: compression final failed on test "
+ "%d for %s: error=%d\n", i + 1, algo, error);
+ return error;
+ }
+
+ if (COMP_BUF_SIZE - req.avail_out != ctemplate[i].outlen) {
+ pr_err("alg: comp: Compression test %d failed for %s: "
+ "output len = %d (expected %d)\n", i + 1, algo,
+ COMP_BUF_SIZE - req.avail_out,
+ ctemplate[i].outlen);
+ return -EINVAL;
+ }
+
+ if (memcmp(result, ctemplate[i].output, ctemplate[i].outlen)) {
+ pr_err("alg: pcomp: Compression test %d failed for "
+ "%s\n", i + 1, algo);
+ hexdump(result, ctemplate[i].outlen);
+ return -EINVAL;
+ }
+ }
+
+ for (i = 0; i < dtcount; i++) {
+ struct comp_request req;
+
+ error = crypto_decompress_setup(tfm, dtemplate[i].params,
+ dtemplate[i].paramsize);
+ if (error) {
+ pr_err("alg: pcomp: decompression setup failed on "
+ "test %d for %s: error=%d\n", i + 1, algo,
+ error);
+ return error;
+ }
+
+ error = crypto_decompress_init(tfm);
+ if (error) {
+ pr_err("alg: pcomp: decompression init failed on test "
+ "%d for %s: error=%d\n", i + 1, algo, error);
+ return error;
+ }
+
+ memset(result, 0, sizeof(result));
+
+ req.next_in = dtemplate[i].input;
+ req.avail_in = dtemplate[i].inlen / 2;
+ req.next_out = result;
+ req.avail_out = dtemplate[i].outlen / 2;
+
+ error = crypto_decompress_update(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_err("alg: pcomp: decompression update failed on "
+ "test %d for %s: error=%d\n", i + 1, algo,
+ error);
+ return error;
+ }
+
+ /* Add remaining input data */
+ req.avail_in += (dtemplate[i].inlen + 1) / 2;
+
+ error = crypto_decompress_update(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_err("alg: pcomp: decompression update failed on "
+ "test %d for %s: error=%d\n", i + 1, algo,
+ error);
+ return error;
+ }
+
+ /* Provide remaining output space */
+ req.avail_out += COMP_BUF_SIZE - dtemplate[i].outlen / 2;
+
+ error = crypto_decompress_final(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_err("alg: pcomp: decompression final failed on "
+ "test %d for %s: error=%d\n", i + 1, algo,
+ error);
+ return error;
+ }
+
+ if (COMP_BUF_SIZE - req.avail_out != dtemplate[i].outlen) {
+ pr_err("alg: comp: Decompression test %d failed for "
+ "%s: output len = %d (expected %d)\n", i + 1,
+ algo, COMP_BUF_SIZE - req.avail_out,
+ dtemplate[i].outlen);
+ return -EINVAL;
+ }
+
+ if (memcmp(result, dtemplate[i].output, dtemplate[i].outlen)) {
+ pr_err("alg: pcomp: Decompression test %d failed for "
+ "%s\n", i + 1, algo);
+ hexdump(result, dtemplate[i].outlen);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
u32 type, u32 mask)
{
static int alg_test_cipher(const struct alg_test_desc *desc,
const char *driver, u32 type, u32 mask)
{
- struct crypto_ablkcipher *tfm;
+ struct crypto_cipher *tfm;
int err = 0;
- tfm = crypto_alloc_ablkcipher(driver, type, mask);
+ tfm = crypto_alloc_cipher(driver, type, mask);
if (IS_ERR(tfm)) {
printk(KERN_ERR "alg: cipher: Failed to load transform for "
"%s: %ld\n", driver, PTR_ERR(tfm));
desc->suite.cipher.dec.count);
out:
+ crypto_free_cipher(tfm);
+ return err;
+}
+
+static int alg_test_skcipher(const struct alg_test_desc *desc,
+ const char *driver, u32 type, u32 mask)
+{
+ struct crypto_ablkcipher *tfm;
+ int err = 0;
+
+ tfm = crypto_alloc_ablkcipher(driver, type, mask);
+ if (IS_ERR(tfm)) {
+ printk(KERN_ERR "alg: skcipher: Failed to load transform for "
+ "%s: %ld\n", driver, PTR_ERR(tfm));
+ return PTR_ERR(tfm);
+ }
+
+ if (desc->suite.cipher.enc.vecs) {
+ err = test_skcipher(tfm, ENCRYPT, desc->suite.cipher.enc.vecs,
+ desc->suite.cipher.enc.count);
+ if (err)
+ goto out;
+ }
+
+ if (desc->suite.cipher.dec.vecs)
+ err = test_skcipher(tfm, DECRYPT, desc->suite.cipher.dec.vecs,
+ desc->suite.cipher.dec.count);
+
+out:
crypto_free_ablkcipher(tfm);
return err;
}
return err;
}
+static int alg_test_pcomp(const struct alg_test_desc *desc, const char *driver,
+ u32 type, u32 mask)
+{
+ struct crypto_pcomp *tfm;
+ int err;
+
+ tfm = crypto_alloc_pcomp(driver, type, mask);
+ if (IS_ERR(tfm)) {
+ pr_err("alg: pcomp: Failed to load transform for %s: %ld\n",
+ driver, PTR_ERR(tfm));
+ return PTR_ERR(tfm);
+ }
+
+ err = test_pcomp(tfm, desc->suite.pcomp.comp.vecs,
+ desc->suite.pcomp.decomp.vecs,
+ desc->suite.pcomp.comp.count,
+ desc->suite.pcomp.decomp.count);
+
+ crypto_free_pcomp(tfm);
+ return err;
+}
+
static int alg_test_hash(const struct alg_test_desc *desc, const char *driver,
u32 type, u32 mask)
{
return err;
}
+static int alg_test_crc32c(const struct alg_test_desc *desc,
+ const char *driver, u32 type, u32 mask)
+{
+ struct crypto_shash *tfm;
+ u32 val;
+ int err;
+
+ err = alg_test_hash(desc, driver, type, mask);
+ if (err)
+ goto out;
+
+ tfm = crypto_alloc_shash(driver, type, mask);
+ if (IS_ERR(tfm)) {
+ printk(KERN_ERR "alg: crc32c: Failed to load transform for %s: "
+ "%ld\n", driver, PTR_ERR(tfm));
+ err = PTR_ERR(tfm);
+ goto out;
+ }
+
+ do {
+ struct {
+ struct shash_desc shash;
+ char ctx[crypto_shash_descsize(tfm)];
+ } sdesc;
+
+ sdesc.shash.tfm = tfm;
+ sdesc.shash.flags = 0;
+
+ *(u32 *)sdesc.ctx = le32_to_cpu(420553207);
+ err = crypto_shash_final(&sdesc.shash, (u8 *)&val);
+ if (err) {
+ printk(KERN_ERR "alg: crc32c: Operation failed for "
+ "%s: %d\n", driver, err);
+ break;
+ }
+
+ if (val != ~420553207) {
+ printk(KERN_ERR "alg: crc32c: Test failed for %s: "
+ "%d\n", driver, val);
+ err = -EINVAL;
+ }
+ } while (0);
+
+ crypto_free_shash(tfm);
+
+out:
+ return err;
+}
+
/* Please keep this list sorted by algorithm name. */
static const struct alg_test_desc alg_test_descs[] = {
{
.alg = "cbc(aes)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "cbc(anubis)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "cbc(blowfish)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "cbc(camellia)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "cbc(des)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "cbc(des3_ede)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "cbc(twofish)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "crc32c",
- .test = alg_test_hash,
+ .test = alg_test_crc32c,
.suite = {
.hash = {
.vecs = crc32c_tv_template,
}
}, {
.alg = "cts(cbc(aes))",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(aes)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(anubis)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(arc4)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(blowfish)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(camellia)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(cast5)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(cast6)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(des)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(des3_ede)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(khazad)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(seed)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(serpent)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(tea)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(tnepres)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(twofish)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(xeta)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "ecb(xtea)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "lrw(aes)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "pcbc(fcrypt)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "rfc3686(ctr(aes))",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "salsa20",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}, {
.alg = "xts(aes)",
- .test = alg_test_cipher,
+ .test = alg_test_skcipher,
.suite = {
.cipher = {
.enc = {
}
}
}
+ }, {
+ .alg = "zlib",
+ .test = alg_test_pcomp,
+ .suite = {
+ .pcomp = {
+ .comp = {
+ .vecs = zlib_comp_tv_template,
+ .count = ZLIB_COMP_TEST_VECTORS
+ },
+ .decomp = {
+ .vecs = zlib_decomp_tv_template,
+ .count = ZLIB_DECOMP_TEST_VECTORS
+ }
+ }
+ }
}
};
-int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
+static int alg_find_test(const char *alg)
{
int start = 0;
int end = ARRAY_SIZE(alg_test_descs);
continue;
}
- return alg_test_descs[i].test(alg_test_descs + i, driver,
- type, mask);
+ return i;
+ }
+
+ return -1;
+}
+
+int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
+{
+ int i;
+ int rc;
+
+ if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) {
+ char nalg[CRYPTO_MAX_ALG_NAME];
+
+ if (snprintf(nalg, sizeof(nalg), "ecb(%s)", alg) >=
+ sizeof(nalg))
+ return -ENAMETOOLONG;
+
+ i = alg_find_test(nalg);
+ if (i < 0)
+ goto notest;
+
+ return alg_test_cipher(alg_test_descs + i, driver, type, mask);
}
+ i = alg_find_test(alg);
+ if (i < 0)
+ goto notest;
+
+ rc = alg_test_descs[i].test(alg_test_descs + i, driver,
+ type, mask);
+ if (fips_enabled && rc)
+ panic("%s: %s alg self test failed in fips mode!\n", driver, alg);
+
+ return rc;
+
+notest:
printk(KERN_INFO "alg: No test for %s (%s)\n", alg, driver);
return 0;
}