@@ -7,6 +7,7 @@
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org>
* Copyright (c) 2007 Nokia Siemens Networks
+ * Copyright (c) 2017 NVIDIA Corporation
*
* Updated RFC4106 AES-GCM testing.
* Authors: Aidan O'Mahony (aidan.o.mahony@intel.com)
@@ -27,6 +28,7 @@
#include <crypto/aead.h>
#include <crypto/hash.h>
#include <crypto/skcipher.h>
+#include <crypto/akcipher.h>
#include <linux/err.h>
#include <linux/fips.h>
#include <linux/init.h>
@@ -46,10 +48,12 @@
#define TVMEMSIZE 4
/*
-* Used by test_cipher_speed()
-*/
-#define ENCRYPT 1
-#define DECRYPT 0
+ * Used by test_cipher_speed()
+ */
+#define DECRYPT 0
+#define ENCRYPT 1
+#define SIGN 2
+#define VERIFY 3
#define MAX_DIGEST_SIZE 64
@@ -996,6 +1000,223 @@ static void test_cipher_speed(const char *algo, int enc, unsigned int secs,
false);
}
+static inline int do_one_akcipher_op(struct akcipher_request *r, int ret)
+{
+ if (ret == -EINPROGRESS || ret == -EBUSY) {
+ struct tcrypt_result *tr = r->base.data;
+
+ wait_for_completion(&tr->completion);
+ reinit_completion(&tr->completion);
+ ret = tr->err;
+ }
+ return ret;
+}
+
+static int test_akcipher_jiffies(struct akcipher_request *r, int op, int secs)
+{
+ unsigned long start, end;
+ int count, ret;
+
+ for (start = jiffies, end = start + secs * HZ, count = 0;
+ time_before(jiffies, end); count++) {
+
+ switch (op) {
+ case SIGN:
+ ret = do_one_akcipher_op(r, crypto_akcipher_sign(r));
+ break;
+ case VERIFY:
+ ret = do_one_akcipher_op(r, crypto_akcipher_verify(r));
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ if (ret)
+ return ret;
+ }
+
+ pr_info("%d operations in %d seconds\n", count, secs);
+ return 0;
+}
+
+static int test_akcipher_cycles(struct akcipher_request *r, int op)
+{
+ unsigned long cycles = 0;
+ int ret = 0;
+ int i;
+
+ /* Warm-up run. */
+ for (i = 0; i < 4; i++) {
+ switch (op) {
+ case SIGN:
+ ret = do_one_akcipher_op(r, crypto_akcipher_sign(r));
+ break;
+ case VERIFY:
+ ret = do_one_akcipher_op(r, crypto_akcipher_verify(r));
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ if (ret)
+ goto out;
+ }
+
+ /* The real thing. */
+ for (i = 0; i < 8; i++) {
+ cycles_t start, end;
+
+ start = get_cycles();
+ switch (op) {
+ case SIGN:
+ ret = do_one_akcipher_op(r, crypto_akcipher_sign(r));
+ break;
+ case VERIFY:
+ ret = do_one_akcipher_op(r, crypto_akcipher_verify(r));
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ end = get_cycles();
+
+ if (ret)
+ goto out;
+
+ cycles += end - start;
+ }
+out:
+ if (ret == 0)
+ pr_info("1 operation in %lu cycles\n", (cycles + 4) / 8);
+
+ return ret;
+}
+
+static void test_akcipher_speed(const char *algo, int op, unsigned int secs,
+ struct akcipher_speed_template *template,
+ unsigned int tcount, u8 *keysize)
+{
+ unsigned int ret, i, j;
+ struct tcrypt_result tresult;
+ const char *key;
+ struct akcipher_request *req;
+ struct crypto_akcipher *tfm;
+ unsigned int m_size = 0;
+ unsigned int nbytes = 0;
+ const char *o;
+
+ if (op == SIGN)
+ o = "sign";
+ else if (op == VERIFY)
+ o = "verify";
+ else
+ return;
+
+ tfm = crypto_alloc_akcipher(algo, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_err("failed to load transform for %s: %ld\n", algo,
+ PTR_ERR(tfm));
+ return;
+ }
+
+ req = akcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ pr_err("tcrypt: akcipher: Failed to allocate request for %s\n",
+ algo);
+ goto out;
+ }
+
+ init_completion(&tresult.completion);
+ akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &tresult);
+
+ i = 0;
+ do {
+ struct scatterlist sg[TVMEMSIZE];
+
+ memset(tvmem[0], 0xff, PAGE_SIZE);
+
+ /* set key */
+ key = tvmem[0];
+ for (j = 0; j < tcount; j++) {
+ if (template[j].key_len == *keysize) {
+ key = template[j].key;
+ break;
+ }
+ }
+
+ ret = crypto_akcipher_set_pub_key(tfm, key, *keysize);
+ if (ret) {
+ pr_err("set_pub_key() failed\n");
+ goto out_free_req;
+ }
+
+ ret = crypto_akcipher_set_priv_key(tfm, key, *keysize);
+ if (ret) {
+ pr_err("set_priv_key() failed\n");
+ goto out_free_req;
+ }
+
+ /* set up src/dst buffs */
+ sg_init_table(sg, TVMEMSIZE);
+ if (op == SIGN) {
+ m_size = template[j].m_size;
+ nbytes = template[j].c_size / 3;
+
+ memcpy(tvmem[0], template[j].m, m_size);
+
+ sg_set_buf(&sg[0], tvmem[0], m_size);
+ akcipher_request_set_crypt(req, sg, sg,
+ m_size, PAGE_SIZE);
+ } else if (op == VERIFY) {
+ m_size = template[j].m_size;
+ nbytes = template[j].c_size / 3;
+
+ memcpy(tvmem[0], template[j].m, m_size);
+ memcpy(tvmem[1], (u8 *)(template[j].c) + nbytes,
+ nbytes);
+ memcpy(tvmem[2], (u8 *)(template[j].c) + 2 * nbytes,
+ nbytes);
+
+ sg_set_buf(&sg[0], tvmem[0], m_size);
+ sg_set_buf(&sg[1], tvmem[1], nbytes);
+ sg_set_buf(&sg[2], tvmem[2], nbytes);
+
+ akcipher_request_set_crypt(req, sg, sg,
+ m_size + 2 * nbytes,
+ PAGE_SIZE);
+ } else {
+ pr_err("invalid op\n");
+ ret = -EINVAL;
+ goto out_free_req;
+ }
+
+
+ pr_info("\ntesting speed of %s (%s) %s with keysize %d\n",
+ algo, get_driver_name(crypto_akcipher, tfm), o,
+ nbytes * 8);
+
+ if (secs)
+ ret = test_akcipher_jiffies(req, op, secs);
+ else
+ ret = test_akcipher_cycles(req, op);
+
+ if (ret) {
+ pr_err("%s() failed\n", o);
+ break;
+ }
+
+ i++;
+ keysize++;
+
+ } while (*keysize);
+
+out_free_req:
+ akcipher_request_free(req);
+out:
+ crypto_free_akcipher(tfm);
+}
+
static void test_available(void)
{
char **name = check;
@@ -2039,6 +2260,27 @@ static int do_test(const char *alg, u32 type, u32 mask, int m)
speed_template_8_32);
break;
+ case 560:
+ ret += tcrypt_test("ecdsa");
+ break;
+
+ case 561:
+#ifndef CONFIG_CRYPTO_FIPS
+ test_akcipher_speed("ecdsa", SIGN, sec,
+ ecdsa_speed_template, ECDSA_SPEED_VECTORS,
+ akc_speed_template_P192);
+ test_akcipher_speed("ecdsa", VERIFY, sec,
+ ecdsa_speed_template, ECDSA_SPEED_VECTORS,
+ akc_speed_template_P192);
+#endif
+ test_akcipher_speed("ecdsa", SIGN, sec,
+ ecdsa_speed_template, ECDSA_SPEED_VECTORS,
+ akc_speed_template_P256);
+ test_akcipher_speed("ecdsa", VERIFY, sec,
+ ecdsa_speed_template, ECDSA_SPEED_VECTORS,
+ akc_speed_template_P256);
+ break;
+
case 1000:
test_available();
break;
@@ -7,6 +7,7 @@
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org>
* Copyright (c) 2007 Nokia Siemens Networks
+ * Copyright (c) 2017 NVIDIA 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
@@ -17,6 +18,16 @@
#ifndef _CRYPTO_TCRYPT_H
#define _CRYPTO_TCRYPT_H
+struct akcipher_speed_template {
+ unsigned char *key;
+ unsigned char *m;
+ unsigned char *c;
+ unsigned int key_len;
+ unsigned int m_size;
+ unsigned int c_size;
+ bool public_key_vec;
+};
+
struct cipher_speed_template {
const char *key;
unsigned int klen;
@@ -48,6 +59,117 @@ struct hash_speed {
};
/*
+ * ECDSA test vectors.
+ */
+#ifdef CONFIG_CRYPTO_FIPS
+#define ECDSA_SPEED_VECTORS 1
+#else
+#define ECDSA_SPEED_VECTORS 2
+#endif
+
+static struct akcipher_speed_template ecdsa_speed_template[] = {
+ {
+#ifndef CONFIG_CRYPTO_FIPS
+ /* [P-192,SHA-256] */
+ .m =
+ /* Msg / Hash */
+ "\xd0\xd8\xc0\x99\xe0\xe2\xf7\xf8"
+ "\x87\xe1\x6d\x11\xe1\xcc\x20\x43"
+ "\xaf\xc0\x80\xdb\x47\x72\xfa\xe3"
+ "\x95\xe5\xd1\x34\x7d\x31\xe8\x5a",
+ .m_size = 32,
+ .key =
+ /* version */
+ "\x01"
+ /* curve_id */
+ "\x01"
+ /* d */
+ "\x47\x7a\xf2\x5c\x86\xef\x09\x08"
+ "\xa4\x9a\x47\x53\x06\xfc\x61\xbc"
+ "\xa5\x6f\xdd\x7d\x2f\xd2\xed\x24"
+ /* Qx */
+ "\xdc\x14\xd4\xd8\x2e\x1e\x25\x2f"
+ "\x66\x28\xaa\x80\xbc\x38\x6a\x07"
+ "\x8a\x70\xb7\x74\x71\x2d\xf1\x9b"
+ /* Qy */
+ "\x98\x34\x57\x11\xb0\xdc\x3d\xff"
+ "\xfc\xdc\xfe\xa2\x1c\x47\x9e\x4e"
+ "\x82\x08\xfc\x7d\xd0\xc8\x54\x48",
+ .key_len = 74,
+ .c =
+ /* k */
+ "\x3e\x70\xc7\x86\xaf\xaa\x71\x7c"
+ "\x68\x96\xc5\xc3\xec\xb8\x29\xa3"
+ "\xfa\xf7\xa5\x36\xa2\x17\xc8\xa5"
+ /* R */
+ "\xf8\xef\x13\xa8\x86\xe6\x73\x85"
+ "\xdf\x2e\x88\x99\x91\x9b\xc2\x90"
+ "\xea\x1f\x36\xf4\xec\xba\x4a\x35"
+ /* S */
+ "\xc1\x82\x9e\x94\xb7\x58\x2c\x63"
+ "\x8e\xd7\x15\x5a\x38\x47\x30\x9b"
+ "\x1c\x11\x86\xac\x00\x00\xf5\x80",
+ .c_size = 72,
+ }, {
+#endif
+ /* [P-256,SHA-256] */
+ .m =
+ /* Msg / Hash */
+ "\x56\xec\x33\xa1\xa6\xe7\xc4\xdb"
+ "\x77\x03\x90\x1a\xfb\x2e\x1e\x4e"
+ "\x50\x09\xfe\x04\x72\x89\xc5\xc2"
+ "\x42\x13\x6c\xe3\xb7\xf6\xac\x44",
+ .m_size = 32,
+ .key =
+ /* version */
+ "\x01"
+ /* curve_id */
+ "\x02"
+ /* d */
+ "\x64\xb4\x72\xda\x6d\xa5\x54\xca"
+ "\xac\x3e\x4e\x0b\x13\xc8\x44\x5b"
+ "\x1a\x77\xf4\x59\xee\xa8\x4f\x1f"
+ "\x58\x8b\x5f\x71\x3d\x42\x9b\x51"
+ /* Qx */
+ "\x83\xbf\x71\xc2\x46\xff\x59\x3c"
+ "\x2f\xb1\xbf\x4b\xe9\x5d\x56\xd3"
+ "\xcc\x8f\xdb\x48\xa2\xbf\x33\xf0"
+ "\xf4\xc7\x5f\x07\x1c\xe9\xcb\x1c"
+ /* Qy */
+ "\xa9\x4c\x9a\xa8\x5c\xcd\x7c\xdc"
+ "\x78\x4e\x40\xb7\x93\xca\xb7\x6d"
+ "\xe0\x13\x61\x0e\x2c\xdb\x1f\x1a"
+ "\xa2\xf9\x11\x88\xc6\x14\x40\xce",
+ .key_len = 98,
+ .c =
+ /* k */
+ "\xde\x68\x2a\x64\x87\x07\x67\xb9"
+ "\x33\x5d\x4f\x82\x47\x62\x4a\x3b"
+ "\x7f\x3c\xe9\xf9\x45\xf2\x80\xa2"
+ "\x61\x6a\x90\x4b\xb1\xbb\xa1\x94"
+ /* R */
+ "\xac\xc2\xc8\x79\x6f\x5e\xbb\xca"
+ "\x7a\x5a\x55\x6a\x1f\x6b\xfd\x2a"
+ "\xed\x27\x95\x62\xd6\xe3\x43\x88"
+ "\x5b\x79\x14\xb5\x61\x80\xac\xf3"
+ /* S */
+ "\x03\x89\x05\xcc\x2a\xda\xcd\x3c"
+ "\x5a\x17\x6f\xe9\x18\xb2\x97\xef"
+ "\x1c\x37\xf7\x2b\x26\x76\x6c\x78"
+ "\xb2\xa6\x05\xca\x19\x78\xf7\x8b",
+ .c_size = 96,
+ },
+};
+
+/*
+ * AKCipher speed tests
+ */
+#ifndef CONFIG_CRYPTO_FIPS
+static u8 akc_speed_template_P192[] = {74, 0};
+#endif
+static u8 akc_speed_template_P256[] = {98, 0};
+
+/*
* Cipher speed tests
*/
static u8 speed_template_8[] = {8, 0};
Update tcrypt module to include a new ECDSA test modes. It includes: tcrypt.ko mode=560 for ECDSA sign/verify validation. tcrypt.ko mode=561 for ECDSA sign/verify op perf in cycles. tcrypt.ko mode=561 sec=<seconds> for number of ECDSA sign verify ops in given time. Signed-off-by: Nitin Kumbhar <nkumbhar@nvidia.com> --- crypto/tcrypt.c | 250 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- crypto/tcrypt.h | 122 +++++++++++++++++++++++++++ 2 files changed, 368 insertions(+), 4 deletions(-)