From 2a80de4aef35b42545650f0abc4ff5f5ca8bbd12 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil.sutter@viprinet.com>
Date: Tue, 28 Feb 2012 18:27:43 +0100
Subject: [PATCH 197/291] cryptodev: tests:

Signed-off-by: Phil Sutter <phil.sutter@viprinet.com>
Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
---
 drivers/staging/crypto/cryptodev/.gitignore        |   3 +
 drivers/staging/crypto/cryptodev/tests/Makefile    |   8 +-
 .../staging/crypto/cryptodev/tests/cipher_comp.c   | 159 ++++++++++++++++++
 drivers/staging/crypto/cryptodev/tests/hash_comp.c | 150 +++++++++++++++++
 drivers/staging/crypto/cryptodev/tests/hmac_comp.c | 180 +++++++++++++++++++++
 5 files changed, 499 insertions(+), 1 deletion(-)
 create mode 100644 drivers/staging/crypto/cryptodev/tests/cipher_comp.c
 create mode 100644 drivers/staging/crypto/cryptodev/tests/hash_comp.c
 create mode 100644 drivers/staging/crypto/cryptodev/tests/hmac_comp.c

diff --git a/drivers/staging/crypto/cryptodev/.gitignore b/drivers/staging/crypto/cryptodev/.gitignore
index 2728950eb757..685e8ebfeb47 100644
--- a/drivers/staging/crypto/cryptodev/.gitignore
+++ b/drivers/staging/crypto/cryptodev/.gitignore
@@ -11,9 +11,12 @@ tests/async_cipher
 tests/async_hmac
 tests/async_speed
 tests/cipher
+tests/cipher_comp
 tests/hmac
+tests/hmac_comp
 tests/speed
 tests/sha_speed
+tests/hash_comp
 tests/hashcrypt_speed
 releases
 scripts
diff --git a/drivers/staging/crypto/cryptodev/tests/Makefile b/drivers/staging/crypto/cryptodev/tests/Makefile
index baefbd706de4..87ca3c7b46cb 100644
--- a/drivers/staging/crypto/cryptodev/tests/Makefile
+++ b/drivers/staging/crypto/cryptodev/tests/Makefile
@@ -1,9 +1,12 @@
 KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build
 KBUILD_CFLAGS += -I..
+CFLAGS += -I..
+
+comp_progs := cipher_comp hash_comp hmac_comp
 
 hostprogs := cipher cipher-aead hmac speed async_cipher async_hmac \
 	async_speed sha_speed hashcrypt_speed fullspeed cipher-gcm \
-	cipher-aead-srtp
+	cipher-aead-srtp ${comp_progs}
 
 example-cipher-objs := cipher.o
 example-cipher-aead-objs := cipher-aead.o
@@ -27,3 +30,6 @@ check: $(hostprogs)
 
 clean:
 	rm -f *.o *~ $(hostprogs)
+
+${comp_progs}: LDFLAGS += -lssl -lcrypto
+${comp_progs}: %: %.o openssl_wrapper.o
diff --git a/drivers/staging/crypto/cryptodev/tests/cipher_comp.c b/drivers/staging/crypto/cryptodev/tests/cipher_comp.c
new file mode 100644
index 000000000000..b2bc5afc1988
--- /dev/null
+++ b/drivers/staging/crypto/cryptodev/tests/cipher_comp.c
@@ -0,0 +1,159 @@
+/*
+ * Compare encryption results with ones from openssl.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+
+#include "openssl_wrapper.h"
+
+#define	BLOCK_SIZE	16
+#define	KEY_SIZE	16
+#define MAX_DATALEN	(64 * 1024)
+
+
+static int
+test_crypto(int cfd, struct session_op *sess, int datalen)
+{
+	char *data, *encrypted;
+	char *encrypted_comp;
+
+	char iv_in[BLOCK_SIZE];
+	char iv[BLOCK_SIZE];
+	char iv_comp[BLOCK_SIZE];
+
+	struct crypt_op cryp;
+
+	int ret = 0, fail = 0;
+
+	data = malloc(datalen);
+	encrypted = malloc(datalen);
+	encrypted_comp = malloc(datalen);
+	memset(data, datalen & 0xff, datalen);
+	memset(encrypted, 0x27, datalen);
+	memset(encrypted_comp, 0x41, datalen);
+
+	memset(iv_in, 0x23, sizeof(iv_in));
+	memcpy(iv, iv_in, sizeof(iv));
+	memcpy(iv_comp, iv_in, sizeof(iv_comp));
+
+	memset(&cryp, 0, sizeof(cryp));
+
+	/* Encrypt data.in to data.encrypted */
+	cryp.ses = sess->ses;
+	cryp.len = datalen;
+	cryp.src = data;
+	cryp.dst = encrypted;
+	cryp.iv = iv;
+	cryp.op = COP_ENCRYPT;
+	cryp.flags = COP_FLAG_WRITE_IV;
+	if ((ret = ioctl(cfd, CIOCCRYPT, &cryp))) {
+		perror("ioctl(CIOCCRYPT)");
+		goto out;
+	}
+
+	cryp.dst = encrypted_comp;
+	cryp.iv = iv_comp;
+
+	if ((ret = openssl_cioccrypt(sess, &cryp))) {
+		fprintf(stderr, "openssl_cioccrypt() failed!\n");
+		goto out;
+	}
+
+	if ((ret = memcmp(encrypted, encrypted_comp, cryp.len))) {
+		printf("fail for datalen %d, cipher texts do not match!\n", datalen);
+	}
+	if ((ret = memcmp(iv, iv_comp, BLOCK_SIZE))) {
+		printf("fail for datalen %d, IVs do not match!\n", datalen);
+	}
+out:
+	free(data);
+	free(encrypted);
+	free(encrypted_comp);
+	return ret;
+}
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+int
+main(int argc, char **argv)
+{
+	int fd;
+	struct session_op sess;
+	unsigned char key[KEY_SIZE];
+	int datalen = BLOCK_SIZE;
+	int datalen_end = MAX_DATALEN;
+	int i;
+
+	if (argc > 1) {
+		datalen = min(max(atoi(argv[1]), BLOCK_SIZE), MAX_DATALEN);
+		datalen_end = datalen;
+	}
+	if (argc > 2) {
+		datalen_end = min(atoi(argv[2]), MAX_DATALEN);
+		if (datalen_end < datalen)
+			datalen_end = datalen;
+	}
+
+	/* Open the crypto device */
+	fd = open("/dev/crypto", O_RDWR, 0);
+	if (fd < 0) {
+		perror("open(/dev/crypto)");
+		return 1;
+	}
+
+	for (i = 0; i < KEY_SIZE; i++)
+		key[i] = i & 0xff;
+	memset(&sess, 0, sizeof(sess));
+
+	/* encryption test */
+	sess.cipher = CRYPTO_AES_CBC;
+	sess.keylen = KEY_SIZE;
+	sess.key = key;
+	if (ioctl(fd, CIOCGSESSION, &sess)) {
+		perror("ioctl(CIOCGSESSION)");
+		return 1;
+	}
+
+#ifdef CIOCGSESSINFO
+	{
+		struct session_info_op siop = {
+			.ses = sess.ses,
+		};
+
+		if (ioctl(fd, CIOCGSESSINFO, &siop)) {
+			perror("ioctl(CIOCGSESSINFO)");
+		} else {
+			printf("requested cipher CRYPTO_AES_CBC and mac CRYPTO_SHA1_HMAC,"
+			       " got cipher %s with driver %s and hash %s with driver %s\n",
+					siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name,
+					siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+		}
+	}
+#endif
+
+	for (; datalen <= datalen_end; datalen += BLOCK_SIZE) {
+		if (test_crypto(fd, &sess, datalen)) {
+			printf("test_crypto() failed for datalen of %d\n", datalen);
+			return 1;
+		}
+	}
+
+	/* Finish crypto session */
+	if (ioctl(fd, CIOCFSESSION, &sess.ses)) {
+		perror("ioctl(CIOCFSESSION)");
+	}
+
+	close(fd);
+	return 0;
+}
diff --git a/drivers/staging/crypto/cryptodev/tests/hash_comp.c b/drivers/staging/crypto/cryptodev/tests/hash_comp.c
new file mode 100644
index 000000000000..9e700a1b2182
--- /dev/null
+++ b/drivers/staging/crypto/cryptodev/tests/hash_comp.c
@@ -0,0 +1,150 @@
+/*
+ * Compare digest results with ones from openssl.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+
+#include "openssl_wrapper.h"
+
+#define	BLOCK_SIZE	16
+#define MAX_DATALEN	(64 * 1024)
+
+static void printhex(unsigned char *buf, int buflen)
+{
+	while (buflen-- > 0) {
+		printf("\\x%.2x", *(buf++));
+	}
+	printf("\n");
+}
+
+static int
+test_crypto(int cfd, struct session_op *sess, int datalen)
+{
+	unsigned char *data;
+
+	unsigned char mac[AALG_MAX_RESULT_LEN];
+
+	unsigned char mac_comp[AALG_MAX_RESULT_LEN];
+
+	struct crypt_op cryp;
+
+	int ret = 0, fail = 0;
+
+	data = malloc(datalen);
+	memset(data, datalen & 0xff, datalen);
+
+	memset(mac, 0, sizeof(mac));
+	memset(mac_comp, 0, sizeof(mac_comp));
+
+	memset(&cryp, 0, sizeof(cryp));
+
+	/* Encrypt data.in to data.encrypted */
+	cryp.ses = sess->ses;
+	cryp.len = datalen;
+	cryp.src = data;
+	cryp.mac = mac;
+	cryp.op = COP_ENCRYPT;
+	if ((ret = ioctl(cfd, CIOCCRYPT, &cryp))) {
+		perror("ioctl(CIOCCRYPT)");
+		goto out;
+	}
+
+	cryp.mac = mac_comp;
+
+	if ((ret = openssl_cioccrypt(sess, &cryp))) {
+		fprintf(stderr, "openssl_cioccrypt() failed!\n");
+		goto out;
+	}
+
+	if (memcmp(mac, mac_comp, AALG_MAX_RESULT_LEN)) {
+		printf("fail for datalen %d, MACs do not match!\n", datalen);
+		fail = 1;
+		printf("wrong mac: ");
+		printhex(mac, 20);
+		printf("right mac: ");
+		printhex(mac_comp, 20);
+	}
+
+out:
+	free(data);
+	return ret;
+}
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+int
+main(int argc, char **argv)
+{
+	int fd;
+	struct session_op sess;
+	int datalen = BLOCK_SIZE;
+	int datalen_end = MAX_DATALEN;
+	int i;
+
+	if (argc > 1) {
+		datalen = min(max(atoi(argv[1]), BLOCK_SIZE), MAX_DATALEN);
+		datalen_end = datalen;
+	}
+	if (argc > 2) {
+		datalen_end = min(atoi(argv[2]), MAX_DATALEN);
+		if (datalen_end < datalen)
+			datalen_end = datalen;
+	}
+
+	/* Open the crypto device */
+	fd = open("/dev/crypto", O_RDWR, 0);
+	if (fd < 0) {
+		perror("open(/dev/crypto)");
+		return 1;
+	}
+
+	memset(&sess, 0, sizeof(sess));
+
+	/* Hash test */
+	sess.mac = CRYPTO_SHA1;
+	if (ioctl(fd, CIOCGSESSION, &sess)) {
+		perror("ioctl(CIOCGSESSION)");
+		return 1;
+	}
+
+#ifdef CIOCGSESSINFO
+	{
+		struct session_info_op siop = {
+			.ses = sess.ses,
+		};
+
+		if (ioctl(fd, CIOCGSESSINFO, &siop)) {
+			perror("ioctl(CIOCGSESSINFO)");
+		} else {
+			printf("requested mac CRYPTO_SHA1, got hash %s with driver %s\n",
+					siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+		}
+	}
+#endif
+
+	for (; datalen <= datalen_end; datalen += BLOCK_SIZE) {
+		if (test_crypto(fd, &sess, datalen)) {
+			printf("test_crypto() failed for datalen of %d\n", datalen);
+			return 1;
+		}
+	}
+
+	/* Finish crypto session */
+	if (ioctl(fd, CIOCFSESSION, &sess.ses)) {
+		perror("ioctl(CIOCFSESSION)");
+	}
+
+	close(fd);
+	return 0;
+}
diff --git a/drivers/staging/crypto/cryptodev/tests/hmac_comp.c b/drivers/staging/crypto/cryptodev/tests/hmac_comp.c
new file mode 100644
index 000000000000..451bedbbef6e
--- /dev/null
+++ b/drivers/staging/crypto/cryptodev/tests/hmac_comp.c
@@ -0,0 +1,180 @@
+/*
+ * Compare HMAC results with ones from openssl.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+
+#include "openssl_wrapper.h"
+
+#define	BLOCK_SIZE	16
+#define	KEY_SIZE	16
+#define MACKEY_SIZE	20
+#define MAX_DATALEN	(64 * 1024)
+
+static void printhex(unsigned char *buf, int buflen)
+{
+	while (buflen-- > 0) {
+		printf("\\x%.2x", *(buf++));
+	}
+	printf("\n");
+}
+
+static int
+test_crypto(int cfd, struct session_op *sess, int datalen)
+{
+	unsigned char *data, *encrypted;
+	unsigned char *encrypted_comp;
+
+	unsigned char iv[BLOCK_SIZE];
+	unsigned char mac[AALG_MAX_RESULT_LEN];
+
+	unsigned char mac_comp[AALG_MAX_RESULT_LEN];
+
+	struct crypt_op cryp;
+
+	int ret = 0;
+
+	data = malloc(datalen);
+	encrypted = malloc(datalen);
+	encrypted_comp = malloc(datalen);
+	memset(data, datalen & 0xff, datalen);
+	memset(encrypted, 0x27, datalen);
+	memset(encrypted_comp, 0x27, datalen);
+
+	memset(iv, 0x23, sizeof(iv));
+	memset(mac, 0, sizeof(mac));
+	memset(mac_comp, 0, sizeof(mac_comp));
+
+	memset(&cryp, 0, sizeof(cryp));
+
+	/* Encrypt data.in to data.encrypted */
+	cryp.ses = sess->ses;
+	cryp.len = datalen;
+	cryp.src = data;
+	cryp.dst = encrypted;
+	cryp.iv = iv;
+	cryp.mac = mac;
+	cryp.op = COP_ENCRYPT;
+	if ((ret = ioctl(cfd, CIOCCRYPT, &cryp))) {
+		perror("ioctl(CIOCCRYPT)");
+		goto out;
+	}
+
+	cryp.dst = encrypted_comp;
+	cryp.mac = mac_comp;
+
+	if ((ret = openssl_cioccrypt(sess, &cryp))) {
+		fprintf(stderr, "openssl_cioccrypt() failed!\n");
+		goto out;
+	}
+
+	if ((ret = memcmp(encrypted, encrypted_comp, cryp.len))) {
+		printf("fail for datalen %d, cipher texts do not match!\n", datalen);
+	}
+	if ((ret = memcmp(mac, mac_comp, AALG_MAX_RESULT_LEN))) {
+		printf("fail for datalen 0x%x, MACs do not match!\n", datalen);
+		printf("wrong mac: ");
+		printhex(mac, 20);
+		printf("right mac: ");
+		printhex(mac_comp, 20);
+
+	}
+
+out:
+	free(data);
+	free(encrypted);
+	free(encrypted_comp);
+	return ret;
+}
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+int
+main(int argc, char **argv)
+{
+	int fd;
+	struct session_op sess;
+	unsigned char key[KEY_SIZE], mackey[MACKEY_SIZE];
+	int datalen = BLOCK_SIZE;
+	int datalen_end = MAX_DATALEN;
+	int i;
+
+	if (argc > 1) {
+		datalen = min(max(atoi(argv[1]), BLOCK_SIZE), MAX_DATALEN);
+		datalen_end = datalen;
+	}
+	if (argc > 2) {
+		datalen_end = min(atoi(argv[2]), MAX_DATALEN);
+		if (datalen_end < datalen)
+			datalen_end = datalen;
+	}
+
+	/* Open the crypto device */
+	fd = open("/dev/crypto", O_RDWR, 0);
+	if (fd < 0) {
+		perror("open(/dev/crypto)");
+		return 1;
+	}
+
+	for (i = 0; i < KEY_SIZE; i++)
+		key[i] = i & 0xff;
+	for (i = 0; i < MACKEY_SIZE; i++)
+		mackey[i] = i & 0xff;
+
+	memset(&sess, 0, sizeof(sess));
+
+	/* Hash and encryption in one step test */
+	sess.cipher = CRYPTO_AES_CBC;
+	sess.mac = CRYPTO_SHA1_HMAC;
+	sess.keylen = KEY_SIZE;
+	sess.key = key;
+	sess.mackeylen = MACKEY_SIZE;
+	sess.mackey = mackey;
+	if (ioctl(fd, CIOCGSESSION, &sess)) {
+		perror("ioctl(CIOCGSESSION)");
+		return 1;
+	}
+
+#ifdef CIOCGSESSINFO
+	{
+		struct session_info_op siop = {
+			.ses = sess.ses,
+		};
+
+		if (ioctl(fd, CIOCGSESSINFO, &siop)) {
+			perror("ioctl(CIOCGSESSINFO)");
+		} else {
+			printf("requested cipher CRYPTO_AES_CBC and mac CRYPTO_SHA1_HMAC,"
+			       " got cipher %s with driver %s and hash %s with driver %s\n",
+					siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name,
+					siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+		}
+	}
+#endif
+
+	for (; datalen <= datalen_end; datalen += BLOCK_SIZE) {
+		if (test_crypto(fd, &sess, datalen)) {
+			printf("test_crypto() failed for datalen of %d\n", datalen);
+			return 1;
+		}
+	}
+
+	/* Finish crypto session */
+	if (ioctl(fd, CIOCFSESSION, &sess.ses)) {
+		perror("ioctl(CIOCFSESSION)");
+	}
+
+	close(fd);
+	return 0;
+}
-- 
2.1.0

