/* * Quick & dirty crypto testing module. * * This will only exist until we have a better testing mechanism * (e.g. a char device). * * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk@vantronix.net>) * 2003-09-14 Rewritten by Kartikey Mahendra Bhatt * */ #include <linux/init.h>#include <linux/module.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/scatterlist.h>#include <linux/string.h>#include <linux/crypto.h>#include <linux/highmem.h>#include <linux/moduleparam.h>#include <linux/jiffies.h>#include <linux/timex.h>#include <linux/interrupt.h>#include "tcrypt.h" /* * Need to kmalloc() memory for testing kmap(). */#define TVMEMSIZE 16384#define XBUFSIZE 32768 /* * Indexes into the xbuf to simulate cross-page access. */#define IDX1 37#define IDX2 32400#define IDX3 1#define IDX4 8193#define IDX5 22222#define IDX6 17101#define IDX7 27333#define IDX8 3000 /** Used by test_cipher()*/#define ENCRYPT 1#define DECRYPT 0#define MODE_ECB 1#define MODE_CBC 0 static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 }; /* * Used by test_cipher_speed() */static unsigned int sec; static int mode;static char *xbuf;static char *tvmem; static char *check[] = { "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", NULL}; static void hexdump(unsigned char *buf, unsigned int len){ while (len--) printk("%02x", *buf++); printk("\n");} static void 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_tfm *tfm; struct hash_testvec *hash_tv; unsigned int tsize; printk("\ntesting %s\n", algo); tsize = sizeof(struct hash_testvec); tsize *= tcount; if (tsize > TVMEMSIZE) { printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE); return; } memcpy(tvmem, template, tsize); hash_tv = (void *)tvmem; tfm = crypto_alloc_tfm(algo, 0); if (tfm == NULL) { printk("failed to load transform for %s\n", algo); return; } for (i = 0; i < tcount; i++) { printk("test %u:\n", i + 1); memset(result, 0, 64); sg_set_buf(&sg[0], hash_tv[i].plaintext, hash_tv[i].psize); crypto_digest_init(tfm); if (tfm->crt_u.digest.dit_setkey) { crypto_digest_setkey(tfm, hash_tv[i].key, hash_tv[i].ksize); } crypto_digest_update(tfm, sg, 1); crypto_digest_final(tfm, result); hexdump(result, crypto_tfm_alg_digestsize(tfm)); printk("%s\n", memcmp(result, hash_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); } printk("testing %s across pages\n", algo); /* setup the dummy buffer first */ memset(xbuf, 0, XBUFSIZE); j = 0; for (i = 0; i < tcount; i++) { if (hash_tv[i].np) { j++; printk("test %u:\n", j); memset(result, 0, 64); temp = 0; for (k = 0; k < hash_tv[i].np; k++) { memcpy(&xbuf[IDX[k]], hash_tv[i].plaintext + temp, hash_tv[i].tap[k]); temp += hash_tv[i].tap[k]; sg_set_buf(&sg[k], &xbuf[IDX[k]], hash_tv[i].tap[k]); } crypto_digest_digest(tfm, sg, hash_tv[i].np, result); hexdump(result, crypto_tfm_alg_digestsize(tfm)); printk("%s\n", memcmp(result, hash_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); } } crypto_free_tfm(tfm);} #ifdef CONFIG_CRYPTO_HMAC static void test_hmac(char *algo, struct hmac_testvec *template, unsigned int tcount){ unsigned int i, j, k, temp; struct scatterlist sg[8]; char result[64]; struct crypto_tfm *tfm; struct hmac_testvec *hmac_tv; unsigned int tsize, klen; tfm = crypto_alloc_tfm(algo, 0); if (tfm == NULL) { printk("failed to load transform for %s\n", algo); return; } printk("\ntesting hmac_%s\n", algo); tsize = sizeof(struct hmac_testvec); tsize *= tcount; if (tsize > TVMEMSIZE) { printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE); goto out; } memcpy(tvmem, template, tsize); hmac_tv = (void *)tvmem; for (i = 0; i < tcount; i++) { printk("test %u:\n", i + 1); memset(result, 0, sizeof (result)); klen = hmac_tv[i].ksize; sg_set_buf(&sg[0], hmac_tv[i].plaintext, hmac_tv[i].psize); crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, 1, result); hexdump(result, crypto_tfm_alg_digestsize(tfm)); printk("%s\n", memcmp(result, hmac_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); } printk("\ntesting hmac_%s across pages\n", algo); memset(xbuf, 0, XBUFSIZE); j = 0; for (i = 0; i < tcount; i++) { if (hmac_tv[i].np) { j++; printk("test %u:\n",j); memset(result, 0, 64); temp = 0; klen = hmac_tv[i].ksize; for (k = 0; k < hmac_tv[i].np; k++) { memcpy(&xbuf[IDX[k]], hmac_tv[i].plaintext + temp, hmac_tv[i].tap[k]); temp += hmac_tv[i].tap[k]; sg_set_buf(&sg[k], &xbuf[IDX[k]], hmac_tv[i].tap[k]); } crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, hmac_tv[i].np, result); hexdump(result, crypto_tfm_alg_digestsize(tfm)); printk("%s\n", memcmp(result, hmac_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); } }out: crypto_free_tfm(tfm);} #endif /* CONFIG_CRYPTO_HMAC */ static void test_cipher(char *algo, int mode, int enc, struct cipher_testvec *template, unsigned int tcount){ unsigned int ret, i, j, k, temp; unsigned int tsize; char *q; struct crypto_tfm *tfm; char *key; struct cipher_testvec *cipher_tv; struct scatterlist sg[8]; const char *e, *m; if (enc == ENCRYPT) e = "encryption"; else e = "decryption"; if (mode == MODE_ECB) m = "ECB"; else m = "CBC"; printk("\ntesting %s %s %s\n", algo, m, e); tsize = sizeof (struct cipher_testvec); tsize *= tcount; if (tsize > TVMEMSIZE) { printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE); return; } memcpy(tvmem, template, tsize); cipher_tv = (void *)tvmem; if (mode) tfm = crypto_alloc_tfm(algo, 0); else tfm = crypto_alloc_tfm(algo, CRYPTO_TFM_MODE_CBC); if (tfm == NULL) { printk("failed to load transform for %s %s\n", algo, m); return; } j = 0; for (i = 0; i < tcount; i++) { if (!(cipher_tv[i].np)) { j++; printk("test %u (%d bit key):\n", j, cipher_tv[i].klen * 8); tfm->crt_flags = 0; if (cipher_tv[i].wk) tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY; key = cipher_tv[i].key; ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen); if (ret) { printk("setkey() failed flags=%x\n", tfm->crt_flags); if (!cipher_tv[i].fail) goto out; } sg_set_buf(&sg[0], cipher_tv[i].input, cipher_tv[i].ilen); if (!mode) { crypto_cipher_set_iv(tfm, cipher_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); } if (enc) ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen); else ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen); if (ret) { printk("%s () failed flags=%x\n", e, tfm->crt_flags); goto out; } q = kmap(sg[0].page) + sg[0].offset; hexdump(q, cipher_tv[i].rlen); printk("%s\n", memcmp(q, cipher_tv[i].result, cipher_tv[i].rlen) ? "fail" : "pass"); } } printk("\ntesting %s %s %s across pages (chunking)\n", algo, m, e); memset(xbuf, 0, XBUFSIZE); j = 0; for (i = 0; i < tcount; i++) { if (cipher_tv[i].np) { j++; printk("test %u (%d bit key):\n", j, cipher_tv[i].klen * 8); tfm->crt_flags = 0; if (cipher_tv[i].wk) tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY; key = cipher_tv[i].key; ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen); if (ret) { printk("setkey() failed flags=%x\n", tfm->crt_flags); if (!cipher_tv[i].fail) goto out; } temp = 0; for (k = 0; k < cipher_tv[i].np; k++) { memcpy(&xbuf[IDX[k]], cipher_tv[i].input + temp, cipher_tv[i].tap[k]); temp += cipher_tv[i].tap[k]; sg_set_buf(&sg[k], &xbuf[IDX[k]], cipher_tv[i].tap[k]); } if (!mode) { crypto_cipher_set_iv(tfm, cipher_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); } if (enc) ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen); else ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen); if (ret) { printk("%s () failed flags=%x\n", e, tfm->crt_flags); goto out; } temp = 0; for (k = 0; k < cipher_tv[i].np; k++) { printk("page %u\n", k); q = kmap(sg[k].page) + sg[k].offset; hexdump(q, cipher_tv[i].tap[k]); printk("%s\n", memcmp(q, cipher_tv[i].result + temp, cipher_tv[i].tap[k]) ? "fail" : "pass"); temp += cipher_tv[i].tap[k]; } } } out: crypto_free_tfm(tfm);} static int test_cipher_jiffies(struct crypto_tfm *tfm, int enc, char *p, int blen, int sec){ struct scatterlist sg[1]; unsigned long start, end; int bcount; int ret; sg_set_buf(sg, p, blen); for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { if (enc) ret = crypto_cipher_encrypt(tfm, sg, sg, blen); else ret = crypto_cipher_decrypt(tfm, sg, sg, blen); if (ret) return ret; } printk("%d operations in %d seconds (%ld bytes)\n", bcount, sec, (long)bcount * blen); return 0;} static int test_cipher_cycles(struct crypto_tfm *tfm, int enc, char *p, int blen){ struct scatterlist sg[1]; unsigned long cycles = 0; int ret = 0; int i; sg_set_buf(sg, p, blen); local_bh_disable(); local_irq_disable(); /* Warm-up run. */ for (i = 0; i < 4; i++) { if (enc) ret = crypto_cipher_encrypt(tfm, sg, sg, blen); else ret = crypto_cipher_decrypt(tfm, sg, sg, blen); if (ret) goto out; } /* The real thing. */ for (i = 0; i < 8; i++) { cycles_t start, end; start = get_cycles(); if (enc) ret = crypto_cipher_encrypt(tfm, sg, sg, blen); else ret = crypto_cipher_decrypt(tfm, sg, sg, blen); end = get_cycles(); if (ret) goto out; cycles += end - start; } out: local_irq_enable(); local_bh_enable(); if (ret == 0) printk("1 operation in %lu cycles (%d bytes)\n", (cycles + 4) / 8, blen); return ret;} static void test_cipher_speed(char *algo, int mode, int enc, unsigned int sec, struct cipher_testvec *template, unsigned int tcount, struct cipher_speed *speed){ unsigned int ret, i, j, iv_len; unsigned char *key, *p, iv[128]; struct crypto_tfm *tfm; const char *e, *m;Lines 1–500 of 1135. Load more
/* * Quick & dirty crypto testing module. * * This will only exist until we have a better testing mechanism * (e.g. a char device). * * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk@vantronix.net>) * 2003-09-14 Rewritten by Kartikey Mahendra Bhatt * */ #include <linux/init.h> #include <linux/module.h> #include <linux/mm.h> #include <linux/slab.h> #include <linux/scatterlist.h> #include <linux/string.h> #include <linux/crypto.h> #include <linux/highmem.h> #include <linux/moduleparam.h> #include <linux/jiffies.h> #include <linux/timex.h> #include <linux/interrupt.h> #include "tcrypt.h" /* * Need to kmalloc() memory for testing kmap(). */ #define TVMEMSIZE 16384 #define XBUFSIZE 32768 /* * Indexes into the xbuf to simulate cross-page access. */ #define IDX1 37 #define IDX2 32400 #define IDX3 1 #define IDX4 8193 #define IDX5 22222 #define IDX6 17101 #define IDX7 27333 #define IDX8 3000 /* * Used by test_cipher() */ #define ENCRYPT 1 #define DECRYPT 0 #define MODE_ECB 1 #define MODE_CBC 0 static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 }; /* * Used by test_cipher_speed() */ static unsigned int sec; static int mode; static char *xbuf; static char *tvmem; static char *check[] = { "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", NULL }; static void hexdump(unsigned char *buf, unsigned int len) { while (len--) printk("%02x", *buf++); printk("\n"); } static void 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_tfm *tfm; struct hash_testvec *hash_tv; unsigned int tsize; printk("\ntesting %s\n", algo); tsize = sizeof(struct hash_testvec); tsize *= tcount; if (tsize > TVMEMSIZE) { printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE); return; } memcpy(tvmem, template, tsize); hash_tv = (void *)tvmem; tfm = crypto_alloc_tfm(algo, 0); if (tfm == NULL) { printk("failed to load transform for %s\n", algo); return; } for (i = 0; i < tcount; i++) { printk("test %u:\n", i + 1); memset(result, 0, 64); sg_set_buf(&sg[0], hash_tv[i].plaintext, hash_tv[i].psize); crypto_digest_init(tfm); if (tfm->crt_u.digest.dit_setkey) { crypto_digest_setkey(tfm, hash_tv[i].key, hash_tv[i].ksize); } crypto_digest_update(tfm, sg, 1); crypto_digest_final(tfm, result); hexdump(result, crypto_tfm_alg_digestsize(tfm)); printk("%s\n", memcmp(result, hash_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); } printk("testing %s across pages\n", algo); /* setup the dummy buffer first */ memset(xbuf, 0, XBUFSIZE); j = 0; for (i = 0; i < tcount; i++) { if (hash_tv[i].np) { j++; printk("test %u:\n", j); memset(result, 0, 64); temp = 0; for (k = 0; k < hash_tv[i].np; k++) { memcpy(&xbuf[IDX[k]], hash_tv[i].plaintext + temp, hash_tv[i].tap[k]); temp += hash_tv[i].tap[k]; sg_set_buf(&sg[k], &xbuf[IDX[k]], hash_tv[i].tap[k]); } crypto_digest_digest(tfm, sg, hash_tv[i].np, result); hexdump(result, crypto_tfm_alg_digestsize(tfm)); printk("%s\n", memcmp(result, hash_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); } } crypto_free_tfm(tfm); } #ifdef CONFIG_CRYPTO_HMAC static void test_hmac(char *algo, struct hmac_testvec *template, unsigned int tcount) { unsigned int i, j, k, temp; struct scatterlist sg[8]; char result[64]; struct crypto_tfm *tfm; struct hmac_testvec *hmac_tv; unsigned int tsize, klen; tfm = crypto_alloc_tfm(algo, 0); if (tfm == NULL) { printk("failed to load transform for %s\n", algo); return; } printk("\ntesting hmac_%s\n", algo); tsize = sizeof(struct hmac_testvec); tsize *= tcount; if (tsize > TVMEMSIZE) { printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE); goto out; } memcpy(tvmem, template, tsize); hmac_tv = (void *)tvmem; for (i = 0; i < tcount; i++) { printk("test %u:\n", i + 1); memset(result, 0, sizeof (result)); klen = hmac_tv[i].ksize; sg_set_buf(&sg[0], hmac_tv[i].plaintext, hmac_tv[i].psize); crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, 1, result); hexdump(result, crypto_tfm_alg_digestsize(tfm)); printk("%s\n", memcmp(result, hmac_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); } printk("\ntesting hmac_%s across pages\n", algo); memset(xbuf, 0, XBUFSIZE); j = 0; for (i = 0; i < tcount; i++) { if (hmac_tv[i].np) { j++; printk("test %u:\n",j); memset(result, 0, 64); temp = 0; klen = hmac_tv[i].ksize; for (k = 0; k < hmac_tv[i].np; k++) { memcpy(&xbuf[IDX[k]], hmac_tv[i].plaintext + temp, hmac_tv[i].tap[k]); temp += hmac_tv[i].tap[k]; sg_set_buf(&sg[k], &xbuf[IDX[k]], hmac_tv[i].tap[k]); } crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, hmac_tv[i].np, result); hexdump(result, crypto_tfm_alg_digestsize(tfm)); printk("%s\n", memcmp(result, hmac_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); } } out: crypto_free_tfm(tfm); } #endif /* CONFIG_CRYPTO_HMAC */ static void test_cipher(char *algo, int mode, int enc, struct cipher_testvec *template, unsigned int tcount) { unsigned int ret, i, j, k, temp; unsigned int tsize; char *q; struct crypto_tfm *tfm; char *key; struct cipher_testvec *cipher_tv; struct scatterlist sg[8]; const char *e, *m; if (enc == ENCRYPT) e = "encryption"; else e = "decryption"; if (mode == MODE_ECB) m = "ECB"; else m = "CBC"; printk("\ntesting %s %s %s\n", algo, m, e); tsize = sizeof (struct cipher_testvec); tsize *= tcount; if (tsize > TVMEMSIZE) { printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE); return; } memcpy(tvmem, template, tsize); cipher_tv = (void *)tvmem; if (mode) tfm = crypto_alloc_tfm(algo, 0); else tfm = crypto_alloc_tfm(algo, CRYPTO_TFM_MODE_CBC); if (tfm == NULL) { printk("failed to load transform for %s %s\n", algo, m); return; } j = 0; for (i = 0; i < tcount; i++) { if (!(cipher_tv[i].np)) { j++; printk("test %u (%d bit key):\n", j, cipher_tv[i].klen * 8); tfm->crt_flags = 0; if (cipher_tv[i].wk) tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY; key = cipher_tv[i].key; ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen); if (ret) { printk("setkey() failed flags=%x\n", tfm->crt_flags); if (!cipher_tv[i].fail) goto out; } sg_set_buf(&sg[0], cipher_tv[i].input, cipher_tv[i].ilen); if (!mode) { crypto_cipher_set_iv(tfm, cipher_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); } if (enc) ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen); else ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen); if (ret) { printk("%s () failed flags=%x\n", e, tfm->crt_flags); goto out; } q = kmap(sg[0].page) + sg[0].offset; hexdump(q, cipher_tv[i].rlen); printk("%s\n", memcmp(q, cipher_tv[i].result, cipher_tv[i].rlen) ? "fail" : "pass"); } } printk("\ntesting %s %s %s across pages (chunking)\n", algo, m, e); memset(xbuf, 0, XBUFSIZE); j = 0; for (i = 0; i < tcount; i++) { if (cipher_tv[i].np) { j++; printk("test %u (%d bit key):\n", j, cipher_tv[i].klen * 8); tfm->crt_flags = 0; if (cipher_tv[i].wk) tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY; key = cipher_tv[i].key; ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen); if (ret) { printk("setkey() failed flags=%x\n", tfm->crt_flags); if (!cipher_tv[i].fail) goto out; } temp = 0; for (k = 0; k < cipher_tv[i].np; k++) { memcpy(&xbuf[IDX[k]], cipher_tv[i].input + temp, cipher_tv[i].tap[k]); temp += cipher_tv[i].tap[k]; sg_set_buf(&sg[k], &xbuf[IDX[k]], cipher_tv[i].tap[k]); } if (!mode) { crypto_cipher_set_iv(tfm, cipher_tv[i].iv, crypto_tfm_alg_ivsize(tfm)); } if (enc) ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen); else ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen); if (ret) { printk("%s () failed flags=%x\n", e, tfm->crt_flags); goto out; } temp = 0; for (k = 0; k < cipher_tv[i].np; k++) { printk("page %u\n", k); q = kmap(sg[k].page) + sg[k].offset; hexdump(q, cipher_tv[i].tap[k]); printk("%s\n", memcmp(q, cipher_tv[i].result + temp, cipher_tv[i].tap[k]) ? "fail" : "pass"); temp += cipher_tv[i].tap[k]; } } } out: crypto_free_tfm(tfm); } static int test_cipher_jiffies(struct crypto_tfm *tfm, int enc, char *p, int blen, int sec) { struct scatterlist sg[1]; unsigned long start, end; int bcount; int ret; sg_set_buf(sg, p, blen); for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { if (enc) ret = crypto_cipher_encrypt(tfm, sg, sg, blen); else ret = crypto_cipher_decrypt(tfm, sg, sg, blen); if (ret) return ret; } printk("%d operations in %d seconds (%ld bytes)\n", bcount, sec, (long)bcount * blen); return 0; } static int test_cipher_cycles(struct crypto_tfm *tfm, int enc, char *p, int blen) { struct scatterlist sg[1]; unsigned long cycles = 0; int ret = 0; int i; sg_set_buf(sg, p, blen); local_bh_disable(); local_irq_disable(); /* Warm-up run. */ for (i = 0; i < 4; i++) { if (enc) ret = crypto_cipher_encrypt(tfm, sg, sg, blen); else ret = crypto_cipher_decrypt(tfm, sg, sg, blen); if (ret) goto out; } /* The real thing. */ for (i = 0; i < 8; i++) { cycles_t start, end; start = get_cycles(); if (enc) ret = crypto_cipher_encrypt(tfm, sg, sg, blen); else ret = crypto_cipher_decrypt(tfm, sg, sg, blen); end = get_cycles(); if (ret) goto out; cycles += end - start; } out: local_irq_enable(); local_bh_enable(); if (ret == 0) printk("1 operation in %lu cycles (%d bytes)\n", (cycles + 4) / 8, blen); return ret; } static void test_cipher_speed(char *algo, int mode, int enc, unsigned int sec, struct cipher_testvec *template, unsigned int tcount, struct cipher_speed *speed) { unsigned int ret, i, j, iv_len; unsigned char *key, *p, iv[128]; struct crypto_tfm *tfm; const char *e, *m;