/* * 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> * Copyright (c) 2007 Nokia Siemens Networks * * Updated RFC4106 AES-GCM testing. * Authors: Aidan O'Mahony (aidan.o.mahony@intel.com) * Adrian Hoban <adrian.hoban@intel.com> * Gabriele Paoloni <gabriele.paoloni@intel.com> * Tadeusz Struk (tadeusz.struk@intel.com) * Copyright (c) 2010, Intel Corporation. * * 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. * */ #include <crypto/hash.h>#include <linux/err.h>#include <linux/init.h>#include <linux/gfp.h>#include <linux/module.h>#include <linux/scatterlist.h>#include <linux/string.h>#include <linux/moduleparam.h>#include <linux/jiffies.h>#include <linux/timex.h>#include <linux/interrupt.h>#include "tcrypt.h"#include "internal.h" /* * Need slab memory for testing (size in number of pages). */#define TVMEMSIZE 4 /** Used by test_cipher_speed()*/#define ENCRYPT 1#define DECRYPT 0 /* * Used by test_cipher_speed() */static unsigned int sec; static char *alg = NULL;static u32 type;static u32 mask;static int mode;static char *tvmem[TVMEMSIZE]; static char *check[] = { "des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256", "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt", "camellia", "seed", "salsa20", "rmd128", "rmd160", "rmd256", "rmd320", "lzo", "cts", "zlib", NULL}; static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, struct scatterlist *sg, int blen, int sec){ unsigned long start, end; int bcount; int ret; for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { if (enc) ret = crypto_blkcipher_encrypt(desc, sg, sg, blen); else ret = crypto_blkcipher_decrypt(desc, 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 blkcipher_desc *desc, int enc, struct scatterlist *sg, int blen){ unsigned long cycles = 0; int ret = 0; int i; local_irq_disable(); /* Warm-up run. */ for (i = 0; i < 4; i++) { if (enc) ret = crypto_blkcipher_encrypt(desc, sg, sg, blen); else ret = crypto_blkcipher_decrypt(desc, 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_blkcipher_encrypt(desc, sg, sg, blen); else ret = crypto_blkcipher_decrypt(desc, sg, sg, blen); end = get_cycles(); if (ret) goto out; cycles += end - start; } out: local_irq_enable(); if (ret == 0) printk("1 operation in %lu cycles (%d bytes)\n", (cycles + 4) / 8, blen); return ret;} static u32 block_sizes[] = { 16, 64, 256, 1024, 8192, 0 }; static void test_cipher_speed(const char *algo, int enc, unsigned int sec, struct cipher_speed_template *template, unsigned int tcount, u8 *keysize){ unsigned int ret, i, j, iv_len; const char *key; char iv[128]; struct crypto_blkcipher *tfm; struct blkcipher_desc desc; const char *e; u32 *b_size; if (enc == ENCRYPT) e = "encryption"; else e = "decryption"; printk("\ntesting speed of %s %s\n", algo, e); tfm = crypto_alloc_blkcipher(algo, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { printk("failed to load transform for %s: %ld\n", algo, PTR_ERR(tfm)); return; } desc.tfm = tfm; desc.flags = 0; i = 0; do { b_size = block_sizes; do { struct scatterlist sg[TVMEMSIZE]; if ((*keysize + *b_size) > TVMEMSIZE * PAGE_SIZE) { printk("template (%u) too big for " "tvmem (%lu)\n", *keysize + *b_size, TVMEMSIZE * PAGE_SIZE); goto out; } printk("test %u (%d bit key, %d byte blocks): ", i, *keysize * 8, *b_size); memset(tvmem[0], 0xff, PAGE_SIZE); /* set key, plain text and IV */ key = tvmem[0]; for (j = 0; j < tcount; j++) { if (template[j].klen == *keysize) { key = template[j].key; break; } } ret = crypto_blkcipher_setkey(tfm, key, *keysize); if (ret) { printk("setkey() failed flags=%x\n", crypto_blkcipher_get_flags(tfm)); goto out; } sg_init_table(sg, TVMEMSIZE); sg_set_buf(sg, tvmem[0] + *keysize, PAGE_SIZE - *keysize); for (j = 1; j < TVMEMSIZE; j++) { sg_set_buf(sg + j, tvmem[j], PAGE_SIZE); memset (tvmem[j], 0xff, PAGE_SIZE); } iv_len = crypto_blkcipher_ivsize(tfm); if (iv_len) { memset(&iv, 0xff, iv_len); crypto_blkcipher_set_iv(tfm, iv, iv_len); } if (sec) ret = test_cipher_jiffies(&desc, enc, sg, *b_size, sec); else ret = test_cipher_cycles(&desc, enc, sg, *b_size); if (ret) { printk("%s() failed flags=%x\n", e, desc.flags); break; } b_size++; i++; } while (*b_size); keysize++; } while (*keysize); out: crypto_free_blkcipher(tfm);} static int test_hash_jiffies_digest(struct hash_desc *desc, struct scatterlist *sg, int blen, char *out, int sec){ unsigned long start, end; int bcount; int ret; for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { ret = crypto_hash_digest(desc, sg, blen, out); if (ret) return ret; } printk("%6u opers/sec, %9lu bytes/sec\n", bcount / sec, ((long)bcount * blen) / sec); return 0;} static int test_hash_jiffies(struct hash_desc *desc, struct scatterlist *sg, int blen, int plen, char *out, int sec){ unsigned long start, end; int bcount, pcount; int ret; if (plen == blen) return test_hash_jiffies_digest(desc, sg, blen, out, sec); for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { ret = crypto_hash_init(desc); if (ret) return ret; for (pcount = 0; pcount < blen; pcount += plen) { ret = crypto_hash_update(desc, sg, plen); if (ret) return ret; } /* we assume there is enough space in 'out' for the result */ ret = crypto_hash_final(desc, out); if (ret) return ret; } printk("%6u opers/sec, %9lu bytes/sec\n", bcount / sec, ((long)bcount * blen) / sec); return 0;} static int test_hash_cycles_digest(struct hash_desc *desc, struct scatterlist *sg, int blen, char *out){ unsigned long cycles = 0; int i; int ret; local_irq_disable(); /* Warm-up run. */ for (i = 0; i < 4; i++) { ret = crypto_hash_digest(desc, sg, blen, out); if (ret) goto out; } /* The real thing. */ for (i = 0; i < 8; i++) { cycles_t start, end; start = get_cycles(); ret = crypto_hash_digest(desc, sg, blen, out); if (ret) goto out; end = get_cycles(); cycles += end - start; } out: local_irq_enable(); if (ret) return ret; printk("%6lu cycles/operation, %4lu cycles/byte\n", cycles / 8, cycles / (8 * blen)); return 0;} static int test_hash_cycles(struct hash_desc *desc, struct scatterlist *sg, int blen, int plen, char *out){ unsigned long cycles = 0; int i, pcount; int ret; if (plen == blen) return test_hash_cycles_digest(desc, sg, blen, out); local_irq_disable(); /* Warm-up run. */ for (i = 0; i < 4; i++) { ret = crypto_hash_init(desc); if (ret) goto out; for (pcount = 0; pcount < blen; pcount += plen) { ret = crypto_hash_update(desc, sg, plen); if (ret) goto out; } ret = crypto_hash_final(desc, out); if (ret) goto out; } /* The real thing. */ for (i = 0; i < 8; i++) { cycles_t start, end; start = get_cycles(); ret = crypto_hash_init(desc); if (ret) goto out; for (pcount = 0; pcount < blen; pcount += plen) { ret = crypto_hash_update(desc, sg, plen); if (ret) goto out; } ret = crypto_hash_final(desc, out); if (ret) goto out; end = get_cycles(); cycles += end - start; } out: local_irq_enable(); if (ret) return ret; printk("%6lu cycles/operation, %4lu cycles/byte\n", cycles / 8, cycles / (8 * blen)); return 0;} static void test_hash_sg_init(struct scatterlist *sg){ int i; sg_init_table(sg, TVMEMSIZE); for (i = 0; i < TVMEMSIZE; i++) { sg_set_buf(sg + i, tvmem[i], PAGE_SIZE); memset(tvmem[i], 0xff, PAGE_SIZE); }} static void test_hash_speed(const char *algo, unsigned int sec, struct hash_speed *speed){ struct scatterlist sg[TVMEMSIZE]; struct crypto_hash *tfm; struct hash_desc desc; static char output[1024]; int i; int ret; printk(KERN_INFO "\ntesting speed of %s\n", algo); tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { printk(KERN_ERR "failed to load transform for %s: %ld\n", algo, PTR_ERR(tfm)); return; } desc.tfm = tfm; desc.flags = 0; if (crypto_hash_digestsize(tfm) > sizeof(output)) { printk(KERN_ERR "digestsize(%u) > outputbuffer(%zu)\n", crypto_hash_digestsize(tfm), sizeof(output)); goto out; } test_hash_sg_init(sg); for (i = 0; speed[i].blen != 0; i++) { if (speed[i].blen > TVMEMSIZE * PAGE_SIZE) { printk(KERN_ERR "template (%u) too big for tvmem (%lu)\n", speed[i].blen, TVMEMSIZE * PAGE_SIZE); goto out; } if (speed[i].klen) crypto_hash_setkey(tfm, tvmem[0], speed[i].klen); printk(KERN_INFO "test%3u " "(%5u byte blocks,%5u bytes per update,%4u updates): ", i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen); if (sec) ret = test_hash_jiffies(&desc, sg, speed[i].blen, speed[i].plen, output, sec); else ret = test_hash_cycles(&desc, sg, speed[i].blen, speed[i].plen, output); if (ret) { printk(KERN_ERR "hashing failed ret=%d\n", ret); break; } } out: crypto_free_hash(tfm);} struct tcrypt_result { struct completion completion; int err;}; 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 inline int do_one_ahash_op(struct ahash_request *req, int ret){ if (ret == -EINPROGRESS || ret == -EBUSY) { struct tcrypt_result *tr = req->base.data; ret = wait_for_completion_interruptible(&tr->completion); if (!ret) ret = tr->err; reinit_completion(&tr->completion); } return ret;} Lines 1–500 of 1869. 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> * Copyright (c) 2007 Nokia Siemens Networks * * Updated RFC4106 AES-GCM testing. * Authors: Aidan O'Mahony (aidan.o.mahony@intel.com) * Adrian Hoban <adrian.hoban@intel.com> * Gabriele Paoloni <gabriele.paoloni@intel.com> * Tadeusz Struk (tadeusz.struk@intel.com) * Copyright (c) 2010, Intel Corporation. * * 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. * */ #include <crypto/hash.h> #include <linux/err.h> #include <linux/init.h> #include <linux/gfp.h> #include <linux/module.h> #include <linux/scatterlist.h> #include <linux/string.h> #include <linux/moduleparam.h> #include <linux/jiffies.h> #include <linux/timex.h> #include <linux/interrupt.h> #include "tcrypt.h" #include "internal.h" /* * Need slab memory for testing (size in number of pages). */ #define TVMEMSIZE 4 /* * Used by test_cipher_speed() */ #define ENCRYPT 1 #define DECRYPT 0 /* * Used by test_cipher_speed() */ static unsigned int sec; static char *alg = NULL; static u32 type; static u32 mask; static int mode; static char *tvmem[TVMEMSIZE]; static char *check[] = { "des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256", "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt", "camellia", "seed", "salsa20", "rmd128", "rmd160", "rmd256", "rmd320", "lzo", "cts", "zlib", NULL }; static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, struct scatterlist *sg, int blen, int sec) { unsigned long start, end; int bcount; int ret; for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { if (enc) ret = crypto_blkcipher_encrypt(desc, sg, sg, blen); else ret = crypto_blkcipher_decrypt(desc, 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 blkcipher_desc *desc, int enc, struct scatterlist *sg, int blen) { unsigned long cycles = 0; int ret = 0; int i; local_irq_disable(); /* Warm-up run. */ for (i = 0; i < 4; i++) { if (enc) ret = crypto_blkcipher_encrypt(desc, sg, sg, blen); else ret = crypto_blkcipher_decrypt(desc, 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_blkcipher_encrypt(desc, sg, sg, blen); else ret = crypto_blkcipher_decrypt(desc, sg, sg, blen); end = get_cycles(); if (ret) goto out; cycles += end - start; } out: local_irq_enable(); if (ret == 0) printk("1 operation in %lu cycles (%d bytes)\n", (cycles + 4) / 8, blen); return ret; } static u32 block_sizes[] = { 16, 64, 256, 1024, 8192, 0 }; static void test_cipher_speed(const char *algo, int enc, unsigned int sec, struct cipher_speed_template *template, unsigned int tcount, u8 *keysize) { unsigned int ret, i, j, iv_len; const char *key; char iv[128]; struct crypto_blkcipher *tfm; struct blkcipher_desc desc; const char *e; u32 *b_size; if (enc == ENCRYPT) e = "encryption"; else e = "decryption"; printk("\ntesting speed of %s %s\n", algo, e); tfm = crypto_alloc_blkcipher(algo, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { printk("failed to load transform for %s: %ld\n", algo, PTR_ERR(tfm)); return; } desc.tfm = tfm; desc.flags = 0; i = 0; do { b_size = block_sizes; do { struct scatterlist sg[TVMEMSIZE]; if ((*keysize + *b_size) > TVMEMSIZE * PAGE_SIZE) { printk("template (%u) too big for " "tvmem (%lu)\n", *keysize + *b_size, TVMEMSIZE * PAGE_SIZE); goto out; } printk("test %u (%d bit key, %d byte blocks): ", i, *keysize * 8, *b_size); memset(tvmem[0], 0xff, PAGE_SIZE); /* set key, plain text and IV */ key = tvmem[0]; for (j = 0; j < tcount; j++) { if (template[j].klen == *keysize) { key = template[j].key; break; } } ret = crypto_blkcipher_setkey(tfm, key, *keysize); if (ret) { printk("setkey() failed flags=%x\n", crypto_blkcipher_get_flags(tfm)); goto out; } sg_init_table(sg, TVMEMSIZE); sg_set_buf(sg, tvmem[0] + *keysize, PAGE_SIZE - *keysize); for (j = 1; j < TVMEMSIZE; j++) { sg_set_buf(sg + j, tvmem[j], PAGE_SIZE); memset (tvmem[j], 0xff, PAGE_SIZE); } iv_len = crypto_blkcipher_ivsize(tfm); if (iv_len) { memset(&iv, 0xff, iv_len); crypto_blkcipher_set_iv(tfm, iv, iv_len); } if (sec) ret = test_cipher_jiffies(&desc, enc, sg, *b_size, sec); else ret = test_cipher_cycles(&desc, enc, sg, *b_size); if (ret) { printk("%s() failed flags=%x\n", e, desc.flags); break; } b_size++; i++; } while (*b_size); keysize++; } while (*keysize); out: crypto_free_blkcipher(tfm); } static int test_hash_jiffies_digest(struct hash_desc *desc, struct scatterlist *sg, int blen, char *out, int sec) { unsigned long start, end; int bcount; int ret; for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { ret = crypto_hash_digest(desc, sg, blen, out); if (ret) return ret; } printk("%6u opers/sec, %9lu bytes/sec\n", bcount / sec, ((long)bcount * blen) / sec); return 0; } static int test_hash_jiffies(struct hash_desc *desc, struct scatterlist *sg, int blen, int plen, char *out, int sec) { unsigned long start, end; int bcount, pcount; int ret; if (plen == blen) return test_hash_jiffies_digest(desc, sg, blen, out, sec); for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { ret = crypto_hash_init(desc); if (ret) return ret; for (pcount = 0; pcount < blen; pcount += plen) { ret = crypto_hash_update(desc, sg, plen); if (ret) return ret; } /* we assume there is enough space in 'out' for the result */ ret = crypto_hash_final(desc, out); if (ret) return ret; } printk("%6u opers/sec, %9lu bytes/sec\n", bcount / sec, ((long)bcount * blen) / sec); return 0; } static int test_hash_cycles_digest(struct hash_desc *desc, struct scatterlist *sg, int blen, char *out) { unsigned long cycles = 0; int i; int ret; local_irq_disable(); /* Warm-up run. */ for (i = 0; i < 4; i++) { ret = crypto_hash_digest(desc, sg, blen, out); if (ret) goto out; } /* The real thing. */ for (i = 0; i < 8; i++) { cycles_t start, end; start = get_cycles(); ret = crypto_hash_digest(desc, sg, blen, out); if (ret) goto out; end = get_cycles(); cycles += end - start; } out: local_irq_enable(); if (ret) return ret; printk("%6lu cycles/operation, %4lu cycles/byte\n", cycles / 8, cycles / (8 * blen)); return 0; } static int test_hash_cycles(struct hash_desc *desc, struct scatterlist *sg, int blen, int plen, char *out) { unsigned long cycles = 0; int i, pcount; int ret; if (plen == blen) return test_hash_cycles_digest(desc, sg, blen, out); local_irq_disable(); /* Warm-up run. */ for (i = 0; i < 4; i++) { ret = crypto_hash_init(desc); if (ret) goto out; for (pcount = 0; pcount < blen; pcount += plen) { ret = crypto_hash_update(desc, sg, plen); if (ret) goto out; } ret = crypto_hash_final(desc, out); if (ret) goto out; } /* The real thing. */ for (i = 0; i < 8; i++) { cycles_t start, end; start = get_cycles(); ret = crypto_hash_init(desc); if (ret) goto out; for (pcount = 0; pcount < blen; pcount += plen) { ret = crypto_hash_update(desc, sg, plen); if (ret) goto out; } ret = crypto_hash_final(desc, out); if (ret) goto out; end = get_cycles(); cycles += end - start; } out: local_irq_enable(); if (ret) return ret; printk("%6lu cycles/operation, %4lu cycles/byte\n", cycles / 8, cycles / (8 * blen)); return 0; } static void test_hash_sg_init(struct scatterlist *sg) { int i; sg_init_table(sg, TVMEMSIZE); for (i = 0; i < TVMEMSIZE; i++) { sg_set_buf(sg + i, tvmem[i], PAGE_SIZE); memset(tvmem[i], 0xff, PAGE_SIZE); } } static void test_hash_speed(const char *algo, unsigned int sec, struct hash_speed *speed) { struct scatterlist sg[TVMEMSIZE]; struct crypto_hash *tfm; struct hash_desc desc; static char output[1024]; int i; int ret; printk(KERN_INFO "\ntesting speed of %s\n", algo); tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { printk(KERN_ERR "failed to load transform for %s: %ld\n", algo, PTR_ERR(tfm)); return; } desc.tfm = tfm; desc.flags = 0; if (crypto_hash_digestsize(tfm) > sizeof(output)) { printk(KERN_ERR "digestsize(%u) > outputbuffer(%zu)\n", crypto_hash_digestsize(tfm), sizeof(output)); goto out; } test_hash_sg_init(sg); for (i = 0; speed[i].blen != 0; i++) { if (speed[i].blen > TVMEMSIZE * PAGE_SIZE) { printk(KERN_ERR "template (%u) too big for tvmem (%lu)\n", speed[i].blen, TVMEMSIZE * PAGE_SIZE); goto out; } if (speed[i].klen) crypto_hash_setkey(tfm, tvmem[0], speed[i].klen); printk(KERN_INFO "test%3u " "(%5u byte blocks,%5u bytes per update,%4u updates): ", i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen); if (sec) ret = test_hash_jiffies(&desc, sg, speed[i].blen, speed[i].plen, output, sec); else ret = test_hash_cycles(&desc, sg, speed[i].blen, speed[i].plen, output); if (ret) { printk(KERN_ERR "hashing failed ret=%d\n", ret); break; } } out: crypto_free_hash(tfm); } struct tcrypt_result { struct completion completion; int err; }; 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 inline int do_one_ahash_op(struct ahash_request *req, int ret) { if (ret == -EINPROGRESS || ret == -EBUSY) { struct tcrypt_result *tr = req->base.data; ret = wait_for_completion_interruptible(&tr->completion); if (!ret) ret = tr->err; reinit_completion(&tr->completion); } return ret; }