-static void hexdump(unsigned char *buf, unsigned int len)
-{
- print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
- 16, 1,
- buf, len, false);
-}
-
-static void tcrypt_complete(struct crypto_async_request *req, int err)
-{
- struct tcrypt_result *res = req->data;
-
- if (err == -EINPROGRESS)
- return;
-
- res->err = err;
- complete(&res->completion);
-}
-
-static int test_hash(char *algo, struct hash_testvec *template,
- unsigned int tcount)
-{
- unsigned int i, j, k, temp;
- struct scatterlist sg[8];
- char result[64];
- struct crypto_ahash *tfm;
- struct ahash_request *req;
- struct tcrypt_result tresult;
- int ret;
- void *hash_buff;
-
- init_completion(&tresult.completion);
-
- tfm = crypto_alloc_ahash(algo, 0, 0);
- if (IS_ERR(tfm)) {
- printk(KERN_ERR "alg: hash: Failed to load transform for %s: "
- "%ld\n", algo, PTR_ERR(tfm));
- return PTR_ERR(tfm);
- }
-
- req = ahash_request_alloc(tfm, GFP_KERNEL);
- if (!req) {
- printk(KERN_ERR "alg: hash: Failed to allocate request for "
- "%s\n", algo);
- ret = -ENOMEM;
- goto out_noreq;
- }
- ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
- tcrypt_complete, &tresult);
-
- for (i = 0; i < tcount; i++) {
- memset(result, 0, 64);
-
- hash_buff = xbuf[0];
-
- memcpy(hash_buff, template[i].plaintext, template[i].psize);
- sg_init_one(&sg[0], hash_buff, template[i].psize);
-
- if (template[i].ksize) {
- crypto_ahash_clear_flags(tfm, ~0);
- ret = crypto_ahash_setkey(tfm, template[i].key,
- template[i].ksize);
- if (ret) {
- printk(KERN_ERR "alg: hash: setkey failed on "
- "test %d for %s: ret=%d\n", i + 1, algo,
- -ret);
- goto out;
- }
- }
-
- ahash_request_set_crypt(req, sg, result, template[i].psize);
- ret = crypto_ahash_digest(req);
- switch (ret) {
- case 0:
- break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &tresult.completion);
- if (!ret && !(ret = tresult.err)) {
- INIT_COMPLETION(tresult.completion);
- break;
- }
- /* fall through */
- default:
- printk(KERN_ERR "alg: hash: digest failed on test %d "
- "for %s: ret=%d\n", i + 1, algo, -ret);
- goto out;
- }
-
- if (memcmp(result, template[i].digest,
- crypto_ahash_digestsize(tfm))) {
- printk(KERN_ERR "alg: hash: Test %d failed for %s\n",
- i + 1, algo);
- hexdump(result, crypto_ahash_digestsize(tfm));
- ret = -EINVAL;
- goto out;
- }
- }
-
- j = 0;
- for (i = 0; i < tcount; i++) {
- if (template[i].np) {
- j++;
- memset(result, 0, 64);
-
- temp = 0;
- sg_init_table(sg, template[i].np);
- for (k = 0; k < template[i].np; k++) {
- sg_set_buf(&sg[k],
- memcpy(xbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]),
- template[i].plaintext + temp,
- template[i].tap[k]),
- template[i].tap[k]);
- temp += template[i].tap[k];
- }
-
- if (template[i].ksize) {
- crypto_ahash_clear_flags(tfm, ~0);
- ret = crypto_ahash_setkey(tfm, template[i].key,
- template[i].ksize);
-
- if (ret) {
- printk(KERN_ERR "alg: hash: setkey "
- "failed on chunking test %d "
- "for %s: ret=%d\n", j, algo,
- -ret);
- goto out;
- }
- }
-
- ahash_request_set_crypt(req, sg, result,
- template[i].psize);
- ret = crypto_ahash_digest(req);
- switch (ret) {
- case 0:
- break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &tresult.completion);
- if (!ret && !(ret = tresult.err)) {
- INIT_COMPLETION(tresult.completion);
- break;
- }
- /* fall through */
- default:
- printk(KERN_ERR "alg: hash: digest failed "
- "on chunking test %d for %s: "
- "ret=%d\n", j, algo, -ret);
- goto out;
- }
-
- if (memcmp(result, template[i].digest,
- crypto_ahash_digestsize(tfm))) {
- printk(KERN_ERR "alg: hash: Chunking test %d "
- "failed for %s\n", j, algo);
- hexdump(result, crypto_ahash_digestsize(tfm));
- ret = -EINVAL;
- goto out;
- }
- }
- }
-
- ret = 0;
-
-out:
- ahash_request_free(req);
-out_noreq:
- crypto_free_ahash(tfm);
- return ret;
-}
-
-static int test_aead(char *algo, int enc, struct aead_testvec *template,
- unsigned int tcount)
-{
- unsigned int i, j, k, n, temp;
- int ret = 0;
- char *q;
- struct crypto_aead *tfm;
- char *key;
- struct aead_request *req;
- struct scatterlist sg[8];
- struct scatterlist asg[8];
- const char *e;
- struct tcrypt_result result;
- unsigned int authsize;
- void *input;
- void *assoc;
- char iv[MAX_IVLEN];
-
- if (enc == ENCRYPT)
- e = "encryption";
- else
- e = "decryption";
-
- init_completion(&result.completion);
-
- tfm = crypto_alloc_aead(algo, 0, 0);
-
- if (IS_ERR(tfm)) {
- printk(KERN_ERR "alg: aead: Failed to load transform for %s: "
- "%ld\n", algo, PTR_ERR(tfm));
- return PTR_ERR(tfm);
- }
-
- req = aead_request_alloc(tfm, GFP_KERNEL);
- if (!req) {
- printk(KERN_ERR "alg: aead: Failed to allocate request for "
- "%s\n", algo);
- ret = -ENOMEM;
- goto out;
- }
-
- aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
- tcrypt_complete, &result);
-
- for (i = 0, j = 0; i < tcount; i++) {
- if (!template[i].np) {
- j++;
-
- /* some tepmplates have no input data but they will
- * touch input
- */
- input = xbuf[0];
- assoc = axbuf[0];
-
- memcpy(input, template[i].input, template[i].ilen);
- memcpy(assoc, template[i].assoc, template[i].alen);
- if (template[i].iv)
- memcpy(iv, template[i].iv, MAX_IVLEN);
- else
- memset(iv, 0, MAX_IVLEN);
-
- crypto_aead_clear_flags(tfm, ~0);
- if (template[i].wk)
- crypto_aead_set_flags(
- tfm, CRYPTO_TFM_REQ_WEAK_KEY);
-
- key = template[i].key;
-
- ret = crypto_aead_setkey(tfm, key,
- template[i].klen);
- if (!ret == template[i].fail) {
- printk(KERN_ERR "alg: aead: setkey failed on "
- "test %d for %s: flags=%x\n", j, algo,
- crypto_aead_get_flags(tfm));
- goto out;
- } else if (ret)
- continue;
-
- authsize = abs(template[i].rlen - template[i].ilen);
- ret = crypto_aead_setauthsize(tfm, authsize);
- if (ret) {
- printk(KERN_ERR "alg: aead: Failed to set "
- "authsize to %u on test %d for %s\n",
- authsize, j, algo);
- goto out;
- }
-
- sg_init_one(&sg[0], input,
- template[i].ilen + (enc ? authsize : 0));
-
- sg_init_one(&asg[0], assoc, template[i].alen);
-
- aead_request_set_crypt(req, sg, sg,
- template[i].ilen, iv);
-
- aead_request_set_assoc(req, asg, template[i].alen);
-
- ret = enc ?
- crypto_aead_encrypt(req) :
- crypto_aead_decrypt(req);
-
- switch (ret) {
- case 0:
- break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &result.completion);
- if (!ret && !(ret = result.err)) {
- INIT_COMPLETION(result.completion);
- break;
- }
- /* fall through */
- default:
- printk(KERN_ERR "alg: aead: %s failed on test "
- "%d for %s: ret=%d\n", e, j, algo, -ret);
- goto out;
- }
-
- q = input;
- if (memcmp(q, template[i].result, template[i].rlen)) {
- printk(KERN_ERR "alg: aead: Test %d failed on "
- "%s for %s\n", j, e, algo);
- hexdump(q, template[i].rlen);
- ret = -EINVAL;
- goto out;
- }
- }
- }
-
- for (i = 0, j = 0; i < tcount; i++) {
- if (template[i].np) {
- j++;
-
- if (template[i].iv)
- memcpy(iv, template[i].iv, MAX_IVLEN);
- else
- memset(iv, 0, MAX_IVLEN);
-
- crypto_aead_clear_flags(tfm, ~0);
- if (template[i].wk)
- crypto_aead_set_flags(
- tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- key = template[i].key;
-
- ret = crypto_aead_setkey(tfm, key, template[i].klen);
- if (!ret == template[i].fail) {
- printk(KERN_ERR "alg: aead: setkey failed on "
- "chunk test %d for %s: flags=%x\n", j,
- algo, crypto_aead_get_flags(tfm));
- goto out;
- } else if (ret)
- continue;
-
- authsize = abs(template[i].rlen - template[i].ilen);
-
- ret = -EINVAL;
- sg_init_table(sg, template[i].np);
- for (k = 0, temp = 0; k < template[i].np; k++) {
- if (WARN_ON(offset_in_page(IDX[k]) +
- template[i].tap[k] > PAGE_SIZE))
- goto out;
-
- q = xbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
-
- memcpy(q, template[i].input + temp,
- template[i].tap[k]);
-
- n = template[i].tap[k];
- if (k == template[i].np - 1 && enc)
- n += authsize;
- if (offset_in_page(q) + n < PAGE_SIZE)
- q[n] = 0;
-
- sg_set_buf(&sg[k], q, template[i].tap[k]);
- temp += template[i].tap[k];
- }
-
- ret = crypto_aead_setauthsize(tfm, authsize);
- if (ret) {
- printk(KERN_ERR "alg: aead: Failed to set "
- "authsize to %u on chunk test %d for "
- "%s\n", authsize, j, algo);
- goto out;
- }
-
- if (enc) {
- if (WARN_ON(sg[k - 1].offset +
- sg[k - 1].length + authsize >
- PAGE_SIZE)) {
- ret = -EINVAL;
- goto out;
- }
-
- sg[k - 1].length += authsize;
- }
-
- sg_init_table(asg, template[i].anp);
- for (k = 0, temp = 0; k < template[i].anp; k++) {
- sg_set_buf(&asg[k],
- memcpy(axbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]),
- template[i].assoc + temp,
- template[i].atap[k]),
- template[i].atap[k]);
- temp += template[i].atap[k];
- }
-
- aead_request_set_crypt(req, sg, sg,
- template[i].ilen,
- iv);
-
- aead_request_set_assoc(req, asg, template[i].alen);
-
- ret = enc ?
- crypto_aead_encrypt(req) :
- crypto_aead_decrypt(req);
-
- switch (ret) {
- case 0:
- break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &result.completion);
- if (!ret && !(ret = result.err)) {
- INIT_COMPLETION(result.completion);
- break;
- }
- /* fall through */
- default:
- printk(KERN_ERR "alg: aead: %s failed on "
- "chunk test %d for %s: ret=%d\n", e, j,
- algo, -ret);
- goto out;
- }
-
- ret = -EINVAL;
- for (k = 0, temp = 0; k < template[i].np; k++) {
- q = xbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
-
- n = template[i].tap[k];
- if (k == template[i].np - 1)
- n += enc ? authsize : -authsize;
-
- if (memcmp(q, template[i].result + temp, n)) {
- printk(KERN_ERR "alg: aead: Chunk "
- "test %d failed on %s at page "
- "%u for %s\n", j, e, k, algo);
- hexdump(q, n);
- goto out;
- }
-
- q += n;
- if (k == template[i].np - 1 && !enc) {
- if (memcmp(q, template[i].input +
- temp + n, authsize))
- n = authsize;
- else
- n = 0;
- } else {
- for (n = 0; offset_in_page(q + n) &&
- q[n]; n++)
- ;
- }
- if (n) {
- printk(KERN_ERR "alg: aead: Result "
- "buffer corruption in chunk "
- "test %d on %s at page %u for "
- "%s: %u bytes:\n", j, e, k,
- algo, n);
- hexdump(q, n);
- goto out;
- }
-
- temp += template[i].tap[k];
- }
- }
- }
-
- ret = 0;
-
-out:
- crypto_free_aead(tfm);
- aead_request_free(req);
- return ret;
-}
-
-static int test_cipher(char *algo, int enc,
- struct cipher_testvec *template, unsigned int tcount)
-{
- unsigned int i, j, k, n, temp;
- int ret;
- char *q;
- struct crypto_ablkcipher *tfm;
- struct ablkcipher_request *req;
- struct scatterlist sg[8];
- const char *e;
- struct tcrypt_result result;
- void *data;
- char iv[MAX_IVLEN];
-
- if (enc == ENCRYPT)
- e = "encryption";
- else
- e = "decryption";
-
- init_completion(&result.completion);
- tfm = crypto_alloc_ablkcipher(algo, 0, 0);
-
- if (IS_ERR(tfm)) {
- printk(KERN_ERR "alg: cipher: Failed to load transform for "
- "%s: %ld\n", algo, PTR_ERR(tfm));
- return PTR_ERR(tfm);
- }
-
- req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
- if (!req) {
- printk(KERN_ERR "alg: cipher: Failed to allocate request for "
- "%s\n", algo);
- ret = -ENOMEM;
- goto out;
- }
-
- ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
- tcrypt_complete, &result);
-
- j = 0;
- for (i = 0; i < tcount; i++) {
- if (template[i].iv)
- memcpy(iv, template[i].iv, MAX_IVLEN);
- else
- memset(iv, 0, MAX_IVLEN);
-
- if (!(template[i].np)) {
- j++;
-
- data = xbuf[0];
- memcpy(data, template[i].input, template[i].ilen);
-
- crypto_ablkcipher_clear_flags(tfm, ~0);
- if (template[i].wk)
- crypto_ablkcipher_set_flags(
- tfm, CRYPTO_TFM_REQ_WEAK_KEY);
-
- ret = crypto_ablkcipher_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_ablkcipher_get_flags(tfm));
- goto out;
- } else if (ret)
- continue;
-
- sg_init_one(&sg[0], data, template[i].ilen);
-
- ablkcipher_request_set_crypt(req, sg, sg,
- template[i].ilen, iv);
- ret = enc ?
- crypto_ablkcipher_encrypt(req) :
- crypto_ablkcipher_decrypt(req);
-
- switch (ret) {
- case 0:
- break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &result.completion);
- if (!ret && !((ret = result.err))) {
- INIT_COMPLETION(result.completion);
- break;
- }
- /* fall through */
- default:
- printk(KERN_ERR "alg: cipher: %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);
- hexdump(q, template[i].rlen);
- ret = -EINVAL;
- goto out;
- }
- }
- }
-
- j = 0;
- for (i = 0; i < tcount; i++) {
-
- if (template[i].iv)
- memcpy(iv, template[i].iv, MAX_IVLEN);
- else
- memset(iv, 0, MAX_IVLEN);
-
- if (template[i].np) {
- j++;
-
- crypto_ablkcipher_clear_flags(tfm, ~0);
- if (template[i].wk)
- crypto_ablkcipher_set_flags(
- tfm, CRYPTO_TFM_REQ_WEAK_KEY);
-
- ret = crypto_ablkcipher_setkey(tfm, template[i].key,
- template[i].klen);
- if (!ret == template[i].fail) {
- printk(KERN_ERR "alg: cipher: setkey failed "
- "on chunk test %d for %s: flags=%x\n",
- j, algo,
- crypto_ablkcipher_get_flags(tfm));
- goto out;
- } else if (ret)
- continue;
-
- temp = 0;
- ret = -EINVAL;
- sg_init_table(sg, template[i].np);
- for (k = 0; k < template[i].np; k++) {
- if (WARN_ON(offset_in_page(IDX[k]) +
- template[i].tap[k] > PAGE_SIZE))
- goto out;
-
- q = xbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
-
- memcpy(q, template[i].input + temp,
- template[i].tap[k]);
-
- if (offset_in_page(q) + template[i].tap[k] <
- PAGE_SIZE)
- q[template[i].tap[k]] = 0;
-
- sg_set_buf(&sg[k], q, template[i].tap[k]);
-
- temp += template[i].tap[k];
- }
-
- ablkcipher_request_set_crypt(req, sg, sg,
- template[i].ilen, iv);
-
- ret = enc ?
- crypto_ablkcipher_encrypt(req) :
- crypto_ablkcipher_decrypt(req);
-
- switch (ret) {
- case 0:
- break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &result.completion);
- if (!ret && !((ret = result.err))) {
- INIT_COMPLETION(result.completion);
- break;
- }
- /* fall through */
- default:
- printk(KERN_ERR "alg: cipher: %s failed on "
- "chunk test %d for %s: ret=%d\n", e, j,
- algo, -ret);
- goto out;
- }
-
- temp = 0;
- ret = -EINVAL;
- for (k = 0; k < template[i].np; k++) {
- q = xbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
-
- if (memcmp(q, template[i].result + temp,
- template[i].tap[k])) {
- printk(KERN_ERR "alg: cipher: Chunk "
- "test %d failed on %s at page "
- "%u for %s\n", j, e, k, algo);
- hexdump(q, template[i].tap[k]);
- goto out;
- }
-
- q += template[i].tap[k];
- for (n = 0; offset_in_page(q + n) && q[n]; n++)
- ;
- if (n) {
- printk(KERN_ERR "alg: cipher: "
- "Result buffer corruption in "
- "chunk test %d on %s at page "
- "%u for %s: %u bytes:\n", j, e,
- k, algo, n);
- hexdump(q, n);
- goto out;
- }
- temp += template[i].tap[k];
- }
- }
- }
-
- ret = 0;
-
-out:
- crypto_free_ablkcipher(tfm);
- ablkcipher_request_free(req);
- return ret;
-}
-