summaryrefslogtreecommitdiffstats
path: root/ncr-cipher.c
diff options
context:
space:
mode:
Diffstat (limited to 'ncr-cipher.c')
-rw-r--r--ncr-cipher.c236
1 files changed, 236 insertions, 0 deletions
diff --git a/ncr-cipher.c b/ncr-cipher.c
new file mode 100644
index 0000000..d0fc320
--- /dev/null
+++ b/ncr-cipher.c
@@ -0,0 +1,236 @@
+/*
+ * Driver for /dev/crypto device (aka CryptoDev)
+ *
+ * Copyright (c) 2010 Nikos Mavrogiannopoulos <nmav@gnutls.org>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * cryptodev 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * cryptodev is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/random.h>
+#include <asm/uaccess.h>
+#include <asm/ioctl.h>
+#include <crypto/algapi.h>
+#include <crypto/hash.h>
+#include "cryptodev.h"
+#include "cryptodev_int.h"
+#include "ncr_int.h"
+
+static inline const char* algo2str(ncr_algorithm_t algo)
+{
+ switch(algo) {
+ case NCR_ALG_AES_ECB:
+ return "ecb(aes)";
+ case NCR_ALG_3DES_CBC:
+ return "cbc(des3_ede)";
+ case NCR_ALG_AES_CBC:
+ return "cbc(aes)";
+ case NCR_ALG_CAMELLIA_CBC:
+ return "cbc(camelia)";
+ case NCR_ALG_SHA1:
+ return "sha1";
+ case NCR_ALG_MD5:
+ return "md5";
+ case NCR_ALG_SHA2_224:
+ return "sha224";
+ case NCR_ALG_SHA2_256:
+ return "sha256";
+ case NCR_ALG_SHA2_384:
+ return "sha384";
+ case NCR_ALG_SHA2_512:
+ return "sha512";
+ case NCR_ALG_HMAC_SHA1:
+ return "hmac(sha1)";
+ case NCR_ALG_HMAC_MD5:
+ return "hmac(md5)";
+ case NCR_ALG_HMAC_SHA2_224:
+ return "hmac(sha224)";
+ case NCR_ALG_HMAC_SHA2_256:
+ return "hmac(sha256)";
+ case NCR_ALG_HMAC_SHA2_384:
+ return "hmac(sha384)";
+ case NCR_ALG_HMAC_SHA2_512:
+ return "hmac(sha512)";
+ default:
+ return NULL;
+ }
+}
+
+ncr_session_t ncr_cipher_init(struct list_sem_st* sess_lst, ncr_algorithm_t algorithm, struct key_item_st *key, void* iv, size_t iv_size);
+void ncr_cipher_deinit(struct list_sem_st* sess_lst, ncr_session_t session);
+int ncr_cipher_encrypt(struct list_sem_st* sess_lst, ncr_session_t session, const struct data_item_st * plaintext, struct data_item_st* ciphertext);
+int ncr_cipher_decrypt(struct list_sem_st* sess_lst, ncr_session_t session, const struct data_item_st * ciphertext, struct data_item_st* plaintext);
+
+ncr_session_t ncr_cipher_init(struct list_sem_st* sess_lst, ncr_algorithm_t algorithm, struct key_item_st *key, void* iv, size_t iv_size)
+{
+struct session_item_st* sess;
+int ret;
+const char* str;
+
+ if (key->type != NCR_KEY_TYPE_SECRET) {
+ err();
+ return NCR_SESSION_INVALID;
+ }
+
+ sess = ncr_session_new(sess_lst);
+ if (sess == NULL) {
+ err();
+ return NCR_SESSION_INVALID;
+ }
+
+ str = algo2str(algorithm);
+ if (str == NULL) {
+ err();
+ return NCR_SESSION_INVALID;
+ }
+
+ ret = cryptodev_cipher_init(&sess->ctx, str, key->key.secret.data, key->key.secret.size);
+ if (ret < 0) {
+ err();
+ _ncr_sessions_item_put(sess);
+ return NCR_SESSION_INVALID;
+ }
+
+ return sess->desc;
+}
+
+int ncr_cipher_encrypt(struct list_sem_st* sess_lst, ncr_session_t session, const struct data_item_st * plaintext, struct data_item_st* ciphertext)
+{
+ssize_t output;
+struct scatterlist sg, sgo;
+struct session_item_st* sess;
+
+ sess = ncr_sessions_item_get( sess_lst, session);
+ if (sess == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ sg_init_one(&sg, plaintext->data, plaintext->data_size);
+
+ sg_init_one(&sgo, ciphertext->data, ciphertext->data_size);
+
+ output = cryptodev_cipher_encrypt( &sess->ctx, &sg, &sgo, plaintext->data_size);
+ _ncr_sessions_item_put(sess);
+
+ if (output < 0) {
+ err();
+ return output;
+ }
+
+ return 0;
+}
+
+/* inplace encryption */
+int _ncr_cipher_encrypt(struct list_sem_st* sess_lst, ncr_session_t session, void* plaintext, size_t plaintext_size)
+{
+ssize_t output;
+struct scatterlist sg;
+struct session_item_st* sess;
+
+ sess = ncr_sessions_item_get( sess_lst, session);
+ if (sess == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ sg_init_one(&sg, plaintext, plaintext_size);
+
+ output = cryptodev_cipher_encrypt( &sess->ctx, &sg, &sg, plaintext_size);
+ _ncr_sessions_item_put(sess);
+
+ if (output < 0) {
+ err();
+ return output;
+ }
+
+ return 0;
+}
+
+/* inplace encryption */
+int _ncr_cipher_decrypt(struct list_sem_st* sess_lst, ncr_session_t session, void* ciphertext, size_t ciphertext_size)
+{
+ssize_t output;
+struct scatterlist sg;
+struct session_item_st* sess;
+
+ sess = ncr_sessions_item_get( sess_lst, session);
+ if (sess == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ sg_init_one(&sg, ciphertext, ciphertext_size);
+
+ output = cryptodev_cipher_encrypt( &sess->ctx, &sg, &sg, ciphertext_size);
+ _ncr_sessions_item_put(sess);
+
+ if (output < 0) {
+ err();
+ return output;
+ }
+
+ return 0;
+}
+
+int ncr_cipher_decrypt(struct list_sem_st* sess_lst, ncr_session_t session, const struct data_item_st * ciphertext, struct data_item_st* plaintext)
+{
+ssize_t output;
+struct scatterlist sg, sgo;
+struct session_item_st* sess;
+
+ sess = ncr_sessions_item_get( sess_lst, session);
+ if (sess == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ sg_init_one(&sgo, plaintext->data, plaintext->data_size);
+
+ sg_init_one(&sg, ciphertext->data, ciphertext->data_size);
+
+ output = cryptodev_cipher_decrypt( &sess->ctx, &sg, &sgo, ciphertext->data_size);
+ _ncr_sessions_item_put(sess);
+
+ if (output < 0) {
+ err();
+ return output;
+ }
+
+ return 0;
+}
+
+void ncr_cipher_deinit(struct list_sem_st* lst, ncr_session_t session)
+{
+ struct session_item_st * item, *tmp;
+
+ down(&lst->sem);
+
+ list_for_each_entry_safe(item, tmp, &lst->list, list) {
+ if(item->desc == session) {
+ list_del(&item->list);
+ cryptodev_cipher_deinit(&item->ctx);
+ _ncr_sessions_item_put( item); /* decrement ref count */
+ break;
+ }
+ }
+
+ up(&lst->sem);
+
+ return;
+}