From fb9c0108926d3356ce49e08d03104023a99397ef Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@gnutls.org>
Date: Tue, 6 Dec 2011 10:40:37 +0100
Subject: [PATCH 165/291] cryptodev: Added

---
 .../staging/crypto/cryptodev/examples/aes-gcm.c    | 139 +++++++++++++++++++++
 .../staging/crypto/cryptodev/examples/aes-gcm.h    |  28 +++++
 2 files changed, 167 insertions(+)
 create mode 100644 drivers/staging/crypto/cryptodev/examples/aes-gcm.c
 create mode 100644 drivers/staging/crypto/cryptodev/examples/aes-gcm.h

diff --git a/drivers/staging/crypto/cryptodev/examples/aes-gcm.c b/drivers/staging/crypto/cryptodev/examples/aes-gcm.c
new file mode 100644
index 000000000000..8cdd3d24190b
--- /dev/null
+++ b/drivers/staging/crypto/cryptodev/examples/aes-gcm.c
@@ -0,0 +1,139 @@
+/*
+ * Demo on how to use /dev/crypto device for ciphering.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include "aes-gcm.h"
+
+#define	KEY_SIZE	16
+
+
+int aes_gcm_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t *key, unsigned int key_size)
+{
+#ifdef CIOCGSESSINFO
+	struct session_info_op siop;
+#endif
+
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->cfd = cfd;
+
+	ctx->sess.cipher = CRYPTO_AES_GCM;
+	ctx->sess.keylen = key_size;
+	ctx->sess.key = (void*)key;
+	if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) {
+		perror("ioctl(CIOCGSESSION)");
+		return -1;
+	}
+
+#ifdef CIOCGSESSINFO
+	siop.ses = ctx->sess.ses;
+	if (ioctl(ctx->cfd, CIOCGSESSINFO, &siop)) {
+		perror("ioctl(CIOCGSESSINFO)");
+		return -1;
+	}
+	printf("requested cipher CRYPTO_AES_GCM, got %s with driver %s\n",
+			siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+	/*printf("Alignmask is %x\n", (unsigned int)siop.alignmask); */
+	ctx->alignmask = siop.alignmask;
+#endif
+	return 0;
+}
+
+void aes_gcm_ctx_deinit(struct cryptodev_ctx* ctx) 
+{
+	if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) {
+		perror("ioctl(CIOCFSESSION)");
+	}
+}
+
+int
+aes_gcm_encrypt(struct cryptodev_ctx* ctx, const void* iv, 
+	const void* auth, size_t auth_size,
+	const void* plaintext, void* ciphertext, size_t size)
+{
+	struct crypt_auth_op cryp;
+	void* p;
+	
+	/* check plaintext and ciphertext alignment */
+	if (ctx->alignmask) {
+		p = (void*)(((unsigned long)plaintext + ctx->alignmask) & ~ctx->alignmask);
+		if (plaintext != p) {
+			fprintf(stderr, "plaintext is not aligned\n");
+			return -1;
+		}
+
+		p = (void*)(((unsigned long)ciphertext + ctx->alignmask) & ~ctx->alignmask);
+		if (ciphertext != p) {
+			fprintf(stderr, "ciphertext is not aligned\n");
+			return -1;
+		}
+	}
+
+	memset(&cryp, 0, sizeof(cryp));
+
+	/* Encrypt data.in to data.encrypted */
+	cryp.ses = ctx->sess.ses;
+	cryp.iv = (void*)iv;
+	cryp.op = COP_ENCRYPT;
+	cryp.auth_len = auth_size;
+	cryp.auth_src = (void*)auth;
+	cryp.len = size;
+	cryp.src = (void*)plaintext;
+	cryp.dst = ciphertext;
+	if (ioctl(ctx->cfd, CIOCAUTHCRYPT, &cryp)) {
+		perror("ioctl(CIOCAUTHCRYPT)");
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+aes_gcm_decrypt(struct cryptodev_ctx* ctx, const void* iv, 
+	const void* auth, size_t auth_size,
+	const void* ciphertext, void* plaintext, size_t size)
+{
+	struct crypt_auth_op cryp;
+	void* p;
+	
+	/* check plaintext and ciphertext alignment */
+	if (ctx->alignmask) {
+		p = (void*)(((unsigned long)plaintext + ctx->alignmask) & ~ctx->alignmask);
+		if (plaintext != p) {
+			fprintf(stderr, "plaintext is not aligned\n");
+			return -1;
+		}
+
+		p = (void*)(((unsigned long)ciphertext + ctx->alignmask) & ~ctx->alignmask);
+		if (ciphertext != p) {
+			fprintf(stderr, "ciphertext is not aligned\n");
+			return -1;
+		}
+	}
+
+	memset(&cryp, 0, sizeof(cryp));
+
+	/* Encrypt data.in to data.encrypted */
+	cryp.ses = ctx->sess.ses;
+	cryp.iv = (void*)iv;
+	cryp.op = COP_DECRYPT;
+	cryp.auth_len = auth_size;
+	cryp.auth_src = (void*)auth;
+	cryp.len = size;
+	cryp.src = (void*)ciphertext;
+	cryp.dst = plaintext;
+	if (ioctl(ctx->cfd, CIOCAUTHCRYPT, &cryp)) {
+		perror("ioctl(CIOCAUTHCRYPT)");
+		return -1;
+	}
+
+	return 0;
+}
+
diff --git a/drivers/staging/crypto/cryptodev/examples/aes-gcm.h b/drivers/staging/crypto/cryptodev/examples/aes-gcm.h
new file mode 100644
index 000000000000..1ddc5fe464fc
--- /dev/null
+++ b/drivers/staging/crypto/cryptodev/examples/aes-gcm.h
@@ -0,0 +1,28 @@
+#ifndef AES_H
+# define AES_H
+
+#include <stdint.h>
+
+struct cryptodev_ctx {
+	int cfd;
+	struct session_op sess;
+	uint16_t alignmask;
+};
+
+#define	AES_BLOCK_SIZE	16
+
+int aes_gcm_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t *key, unsigned int key_size);
+void aes_gcm_ctx_deinit();
+
+/* Note that encryption assumes that ciphertext has enough size
+ * for the tag to be appended. In decryption the tag is assumed
+ * to be the last bytes of ciphertext.
+ */
+int aes_gcm_encrypt(struct cryptodev_ctx* ctx, const void* iv, 
+	const void* auth, size_t auth_size,
+	const void* plaintext, void* ciphertext, size_t size);
+int aes_gcm_decrypt(struct cryptodev_ctx* ctx, const void* iv, 
+	const void* auth, size_t auth_size,
+	const void* ciphertext, void* plaintext, size_t size);
+
+#endif
-- 
2.1.0

