summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--cryptodev_cipher.c32
-rw-r--r--cryptodev_int.h6
-rw-r--r--ncr-cipher.c236
-rw-r--r--ncr-cipher.h20
-rw-r--r--ncr-key-wrap.c47
-rw-r--r--ncr-sessions.c376
-rw-r--r--ncr.c12
-rw-r--r--ncr.h13
-rw-r--r--ncr_int.h13
10 files changed, 465 insertions, 292 deletions
diff --git a/Makefile b/Makefile
index b427b3f0aa0..8dafd60f859 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build
VERSION = 0.1
cryptodev-objs = cryptodev_main.o cryptodev_cipher.o ncr.o \
- ncr-data.o ncr-key.o ncr-limits.o ncr-sessions.o ncr-cipher.o \
+ ncr-data.o ncr-key.o ncr-limits.o ncr-sessions.o \
ncr-key-wrap.o
obj-m += cryptodev.o
diff --git a/cryptodev_cipher.c b/cryptodev_cipher.c
index 7c1db6a39dd..58fcba20869 100644
--- a/cryptodev_cipher.c
+++ b/cryptodev_cipher.c
@@ -159,6 +159,30 @@ static inline int waitfor (struct cryptodev_result* cr, ssize_t ret)
return 0;
}
+
+int _cryptodev_cipher_encrypt(struct cipher_data* cdata, const void* plaintext,
+ size_t plaintext_size, void* ciphertext, size_t ciphertext_size)
+{
+struct scatterlist sg, sg2;
+
+ sg_init_one(&sg, plaintext, plaintext_size);
+ sg_init_one(&sg2, ciphertext, ciphertext_size);
+
+ return cryptodev_cipher_encrypt( cdata, &sg, &sg2, plaintext_size);
+}
+
+int _cryptodev_cipher_decrypt(struct cipher_data* cdata, const void* ciphertext,
+ size_t ciphertext_size, void* plaintext, size_t plaintext_size)
+{
+struct scatterlist sg, sg2;
+
+ sg_init_one(&sg, ciphertext, ciphertext_size);
+ sg_init_one(&sg2, plaintext, plaintext_size);
+
+ return cryptodev_cipher_encrypt( cdata, &sg, &sg2, ciphertext_size);
+}
+
+
ssize_t cryptodev_cipher_encrypt( struct cipher_data* cdata, struct scatterlist *sg1, struct scatterlist *sg2, size_t len)
{
int ret;
@@ -272,6 +296,14 @@ ssize_t cryptodev_hash_update( struct hash_data* hdata, struct scatterlist *sg,
return waitfor(hdata->async.result,ret);
}
+ssize_t _cryptodev_hash_update( struct hash_data* hdata, const void* data, size_t len)
+{
+struct scatterlist sg;
+
+ sg_init_one(&sg, data, len);
+
+ return cryptodev_hash_update( hdata, &sg, len);
+}
int cryptodev_hash_final( struct hash_data* hdata, void* output)
{
diff --git a/cryptodev_int.h b/cryptodev_int.h
index 5d4ebfefc2b..7d2e83f7104 100644
--- a/cryptodev_int.h
+++ b/cryptodev_int.h
@@ -40,7 +40,12 @@ int cryptodev_cipher_init(struct cipher_data* out, const char* alg_name, uint8_t
void cryptodev_cipher_deinit(struct cipher_data* cdata);
ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, struct scatterlist *sg1, struct scatterlist *sg2, size_t len);
ssize_t cryptodev_cipher_encrypt( struct cipher_data* cdata, struct scatterlist *sg1, struct scatterlist *sg2, size_t len);
+
int cryptodev_cipher_set_iv(struct cipher_data* cdata, void* iv, size_t iv_size);
+int _cryptodev_cipher_decrypt(struct cipher_data* cdata, const void* ciphertext,
+ size_t ciphertext_size, void* plaintext, size_t plaintext_size);
+int _cryptodev_cipher_encrypt(struct cipher_data* cdata, const void* plaintext,
+ size_t plaintext_size, void* ciphertext, size_t ciphertext_size);
/* hash stuff */
struct hash_data
@@ -56,6 +61,7 @@ struct hash_data
int cryptodev_hash_final( struct hash_data* hdata, void* output);
ssize_t cryptodev_hash_update( struct hash_data* hdata, struct scatterlist *sg, size_t len);
+ssize_t _cryptodev_hash_update( struct hash_data* hdata, const void* data, size_t len);
int cryptodev_hash_reset( struct hash_data* hdata);
void cryptodev_hash_deinit(struct hash_data* hdata);
int cryptodev_hash_init( struct hash_data* hdata, const char* alg_name, int hmac_mode, void* mackey, size_t mackeylen);
diff --git a/ncr-cipher.c b/ncr-cipher.c
deleted file mode 100644
index d0fc3202f6f..00000000000
--- a/ncr-cipher.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * 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;
-}
diff --git a/ncr-cipher.h b/ncr-cipher.h
deleted file mode 100644
index a582fc61609..00000000000
--- a/ncr-cipher.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* cipher stuff */
-
-#ifndef NCR_CIPHER_H
-# define NCR_CIPHER_H
-
-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);
-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);
-void ncr_cipher_deinit(struct list_sem_st* lst, ncr_session_t session);
-
-int _ncr_cipher_encrypt(struct list_sem_st* sess_lst,
- ncr_session_t session, void* plaintext, size_t plaintext_size);
-
-int _ncr_cipher_decrypt(struct list_sem_st* sess_lst,
- ncr_session_t session, void* plaintext, size_t plaintext_size);
-
-#endif /* NCR_CIPHER_H */
diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c
index e9cd884b495..00bc3dc2498 100644
--- a/ncr-key-wrap.c
+++ b/ncr-key-wrap.c
@@ -28,7 +28,7 @@
#include <linux/scatterlist.h>
#include "ncr.h"
#include "ncr_int.h"
-#include "ncr-cipher.h"
+#include "cryptodev_int.h"
typedef uint8_t val64_t[8];
@@ -49,8 +49,7 @@ void val64_xor( val64_t * val, uint32_t x)
/* Wraps using the RFC3394 way.
*/
-static int wrap_aes(struct list_sem_st* sess_lst,
- struct key_item_st* tobewrapped, struct key_item_st *kek,
+static int wrap_aes(struct key_item_st* tobewrapped, struct key_item_st *kek,
struct data_item_st* output)
{
size_t key_size, n;
@@ -58,18 +57,17 @@ uint8_t *raw_key;
val64_t A;
int i, j, ret;
uint8_t aes_block[16];
-ncr_session_t kd;
+struct cipher_data ctx;
- kd = ncr_cipher_init(sess_lst, NCR_ALG_AES_ECB, kek, NULL, 0);
- if (kd == NCR_SESSION_INVALID) {
+ if (tobewrapped->type != NCR_KEY_TYPE_SECRET) {
err();
- return -ENOMEM;
+ return -EINVAL;
}
- if (tobewrapped->type != NCR_KEY_TYPE_SECRET) {
+ ret = cryptodev_cipher_init(&ctx, "ecb(aes)", kek->key.secret.data, kek->key.secret.size);
+ if (ret < 0) {
err();
- ret = -EINVAL;
- goto cleanup;
+ return ret;
}
raw_key = tobewrapped->key.secret.data;
@@ -104,7 +102,8 @@ ncr_session_t kd;
memcpy(aes_block, A, 8);
memcpy(&aes_block[8], R[0], 8);
- _ncr_cipher_encrypt(sess_lst, kd, aes_block, sizeof(aes_block));
+ _cryptodev_cipher_encrypt(&ctx, aes_block, sizeof(aes_block),
+ aes_block, sizeof(aes_block));
memcpy(A, aes_block, 8); /* A = MSB64(AES(A^{t-1}|R_{1}^{t-1})) */
val64_xor(&A, i+1); /* A ^= t */
@@ -124,13 +123,12 @@ ncr_session_t kd;
ret = 0;
cleanup:
- ncr_cipher_deinit(sess_lst, kd);
+ cryptodev_cipher_deinit(&ctx);
return ret;
}
-static int unwrap_aes(struct list_sem_st* sess_lst,
- struct key_item_st* output, struct key_item_st *kek,
+static int unwrap_aes(struct key_item_st* output, struct key_item_st *kek,
struct data_item_st* wrapped)
{
size_t key_size, n;
@@ -138,12 +136,12 @@ uint8_t *raw_key;
val64_t A;
int i, j, ret;
uint8_t aes_block[16];
-ncr_session_t kd;
+struct cipher_data ctx;
- kd = ncr_cipher_init(sess_lst, NCR_ALG_AES_ECB, kek, NULL, 0);
- if (kd == NCR_SESSION_INVALID) {
+ ret = cryptodev_cipher_init(&ctx, "ecb(aes)", kek->key.secret.data, kek->key.secret.size);
+ if (ret < 0) {
err();
- return -ENOMEM;
+ return ret;
}
output->type = NCR_KEY_TYPE_SECRET;
@@ -178,7 +176,8 @@ ncr_session_t kd;
memcpy(aes_block, A, 8);
memcpy(&aes_block[8], R[n-1], 8);
- _ncr_cipher_decrypt(sess_lst, kd, aes_block, sizeof(aes_block));
+ _cryptodev_cipher_decrypt(&ctx, aes_block, sizeof(aes_block),
+ aes_block, sizeof(aes_block));
memcpy(A, aes_block, 8);
memcpy(R[0], &aes_block[8], 8);
@@ -204,12 +203,12 @@ ncr_session_t kd;
ret = 0;
cleanup:
- ncr_cipher_deinit(sess_lst, kd);
+ cryptodev_cipher_deinit(&ctx);
return ret;
}
-int ncr_key_wrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, struct list_sem_st* sess_lst, void __user* arg)
+int ncr_key_wrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg)
{
struct ncr_key_wrap_st wrap;
struct key_item_st* wkey = NULL;
@@ -248,7 +247,7 @@ int ret;
switch(wrap.algorithm) {
case NCR_WALG_AES_RFC3394:
- ret = wrap_aes(sess_lst, wkey, key, data);
+ ret = wrap_aes(wkey, key, data);
default:
ret = -EINVAL;
}
@@ -261,7 +260,7 @@ fail:
return ret;
}
-int ncr_key_unwrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, struct list_sem_st* sess_lst, void __user* arg)
+int ncr_key_unwrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg)
{
struct ncr_key_wrap_st wrap;
struct key_item_st* wkey = NULL;
@@ -295,7 +294,7 @@ int ret;
switch(wrap.algorithm) {
case NCR_WALG_AES_RFC3394:
- ret = unwrap_aes(sess_lst, wkey, key, data);
+ ret = unwrap_aes(wkey, key, data);
default:
ret = -EINVAL;
}
diff --git a/ncr-sessions.c b/ncr-sessions.c
index a69258845ef..1edeb0172a2 100644
--- a/ncr-sessions.c
+++ b/ncr-sessions.c
@@ -45,7 +45,7 @@ void ncr_sessions_list_deinit(struct list_sem_st* lst)
static ncr_session_t _ncr_sessions_get_new_desc( struct list_sem_st* lst)
{
struct session_item_st* item;
-int mx = 0;
+int mx = 1;
list_for_each_entry(item, &lst->list, list) {
mx = max(mx, item->desc);
@@ -105,7 +105,291 @@ struct session_item_st* ncr_session_new(struct list_sem_st* lst)
return sess;
}
-void ncr_session_deinit(struct list_sem_st* lst, ncr_session_t desc)
+static const struct algo_properties_st {
+ ncr_algorithm_t algo;
+ const char* kstr;
+ int needs_iv;
+ int digest_size;
+} algo_properties[] = {
+ { .algo = NCR_ALG_3DES_CBC, .kstr = "cbc(des3_ede)", .needs_iv = 1 },
+ { .algo = NCR_ALG_AES_CBC, .kstr = "cbc(aes)", .needs_iv = 1 },
+ { .algo = NCR_ALG_CAMELLIA_CBC, .kstr = "ecb(camelia)", .needs_iv = 1 },
+ { .algo = NCR_ALG_ARCFOUR, .kstr = NULL, .needs_iv = 0 },
+ { .algo = NCR_ALG_AES_ECB, .kstr = "ecb(aes)", .needs_iv = 0 },
+ { .algo = NCR_ALG_SHA1, .kstr = "sha1", .needs_iv = 0, .digest_size = 20 },
+ { .algo = NCR_ALG_MD5, .kstr = "md5", .needs_iv = 0, .digest_size = 16 },
+ { .algo = NCR_ALG_SHA2_224, .kstr = "sha224", .needs_iv = 0, .digest_size = 24 },
+ { .algo = NCR_ALG_SHA2_256, .kstr = "sha256", .needs_iv = 0, .digest_size = 32 },
+ { .algo = NCR_ALG_SHA2_384, .kstr = "sha384", .needs_iv = 0, .digest_size = 48 },
+ { .algo = NCR_ALG_SHA2_512, .kstr = "sha512", .needs_iv = 0, .digest_size = 64 },
+ { .algo = NCR_ALG_HMAC_SHA1, .kstr = "hmac(sha1)", .needs_iv = 0, .digest_size = 20 },
+ { .algo = NCR_ALG_HMAC_MD5, .kstr = "hmac(md5)", .needs_iv = 0, .digest_size = 16 },
+ { .algo = NCR_ALG_HMAC_SHA2_224, .kstr = "hmac(sha224)", .needs_iv = 0, .digest_size = 24 },
+ { .algo = NCR_ALG_HMAC_SHA2_256, .kstr = "hmac(sha256)", .needs_iv = 0, .digest_size = 32 },
+ { .algo = NCR_ALG_HMAC_SHA2_384, .kstr = "hmac(sha384)", .needs_iv = 0, .digest_size = 48 },
+ { .algo = NCR_ALG_HMAC_SHA2_512, .kstr = "hmac(sha512)", .needs_iv = 0, .digest_size = 64 },
+ { .algo = NCR_ALG_RSA, .kstr = NULL, .needs_iv = 0 },
+ { .algo = NCR_ALG_DSA, .kstr = NULL, .needs_iv = 0 },
+ { .algo = NCR_ALG_NONE }
+};
+
+static inline const char* algo2str(ncr_algorithm_t algo)
+{
+ncr_algorithm_t a;
+int i = 0;
+
+ while((a=algo_properties[i].algo)!=NCR_ALG_NONE) {
+ if (a == algo)
+ return algo_properties[i].kstr;
+ i++;
+ }
+
+ return NULL;
+}
+
+static int algo_needs_iv(ncr_algorithm_t algo)
+{
+ncr_algorithm_t a;
+int i = 0;
+
+ while((a=algo_properties[i].algo)!=NCR_ALG_NONE) {
+ if (a == algo)
+ return algo_properties[i].needs_iv;
+ i++;
+ }
+
+ return 0;
+}
+
+static int algo_digest_size(ncr_algorithm_t algo)
+{
+ncr_algorithm_t a;
+int i = 0;
+
+ while((a=algo_properties[i].algo)!=NCR_ALG_NONE) {
+ if (a == algo)
+ return algo_properties[i].digest_size;
+ i++;
+ }
+
+ return 0;
+}
+
+int ncr_session_init(struct ncr_lists* lists, void __user* arg)
+{
+ struct ncr_session_st session;
+ struct session_item_st* ns;
+ struct key_item_st *key = NULL;
+ int ret;
+ const char* str;
+
+ copy_from_user( &session, arg, sizeof(session));
+
+ str = algo2str(session.algorithm);
+ if (str == NULL) {
+ err();
+ return NCR_SESSION_INVALID;
+ }
+
+ ns = ncr_session_new(&lists->sessions);
+ if (ns == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ ns->op = session.op;
+ ns->algo = session.algorithm;
+ switch(session.op) {
+ case NCR_OP_ENCRYPT:
+ case NCR_OP_DECRYPT:
+ /* read key */
+ key = ncr_key_item_get( &lists->key, session.params.key);
+ if (key == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (key->type != NCR_KEY_TYPE_SECRET) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = cryptodev_cipher_init(&ns->ctx, str, key->key.secret.data, key->key.secret.size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ if (algo_needs_iv(session.algorithm)) {
+ if (session.params.params.cipher.iv_size > sizeof(session.params.params.cipher.iv)) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ cryptodev_cipher_set_iv(&ns->ctx, session.params.params.cipher.iv, session.params.params.cipher.iv_size);
+ }
+ break;
+
+ case NCR_OP_MAC:
+ /* read key */
+ key = ncr_key_item_get( &lists->key, session.params.key);
+ if (key == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (key->type != NCR_KEY_TYPE_SECRET) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = cryptodev_hash_init(&ns->hctx, str, 1, key->key.secret.data, key->key.secret.size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ break;
+
+ case NCR_OP_DIGEST:
+ ret = cryptodev_hash_init(&ns->hctx, str, 0, NULL, 0);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ break;
+
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ if (key) _ncr_key_item_put(key);
+ if (ret < 0)
+ _ncr_sessions_item_put(ns);
+
+ return ret;
+}
+
+int ncr_session_update(struct ncr_lists* lists, void __user* arg)
+{
+ struct ncr_session_op_st op;
+ struct key_item_st *key = NULL;
+ int ret;
+ struct session_item_st* sess;
+ struct data_item_st* data = NULL;
+ struct data_item_st* odata = NULL;
+
+ copy_from_user( &op, arg, sizeof(op));
+
+ sess = ncr_sessions_item_get( &lists->sessions, op.ses);
+ if (sess == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ switch(sess->op) {
+ case NCR_OP_ENCRYPT:
+ /* obtain data item */
+ data = ncr_data_item_get( &lists->data, op.data.cipher.plaintext);
+ if (data == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ odata = ncr_data_item_get( &lists->data, op.data.cipher.ciphertext);
+ if (odata == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (odata->max_data_size < data->data_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ /* read key */
+ ret = _cryptodev_cipher_encrypt(&sess->ctx, data->data, data->data_size, odata->data, data->data_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ break;
+ case NCR_OP_DECRYPT:
+ /* obtain data item */
+ data = ncr_data_item_get( &lists->data, op.data.cipher.ciphertext);
+ if (data == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ odata = ncr_data_item_get( &lists->data, op.data.cipher.plaintext);
+ if (odata == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (odata->max_data_size < data->data_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ /* read key */
+ ret = _cryptodev_cipher_decrypt(&sess->ctx, data->data, data->data_size, odata->data, data->data_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ break;
+
+ case NCR_OP_MAC:
+ case NCR_OP_DIGEST:
+ /* obtain data item */
+ data = ncr_data_item_get( &lists->data, op.data.digest.text);
+ if (data == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = _cryptodev_hash_update(&sess->hctx, data->data, data->data_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ break;
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ if (key) _ncr_key_item_put(key);
+ if (odata) _ncr_data_item_put(odata);
+ if (data) _ncr_data_item_put(data);
+ _ncr_sessions_item_put(sess);
+
+ return ret;
+}
+
+static void _ncr_session_deinit(struct list_sem_st* lst, ncr_session_t desc)
{
struct session_item_st * item, *tmp;
@@ -123,3 +407,91 @@ void ncr_session_deinit(struct list_sem_st* lst, ncr_session_t desc)
return;
}
+
+int ncr_session_final(struct ncr_lists* lists, void __user* arg)
+{
+ struct ncr_session_op_st op;
+ struct key_item_st *key = NULL;
+ int ret;
+ struct session_item_st* sess;
+ struct data_item_st* data = NULL;
+ struct data_item_st* odata = NULL;
+ int digest_size;
+
+ copy_from_user( &op, arg, sizeof(op));
+
+ sess = ncr_sessions_item_get( &lists->sessions, op.ses);
+ if (sess == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ switch(sess->op) {
+ case NCR_OP_ENCRYPT:
+ case NCR_OP_DECRYPT:
+ /* obtain data item */
+ if (op.data.cipher.plaintext != NCR_DATA_INVALID &&
+ op.data.cipher.ciphertext != NCR_DATA_INVALID) {
+ ncr_session_update(lists, arg);
+ }
+ cryptodev_cipher_deinit(&sess->ctx);
+ break;
+ case NCR_OP_MAC:
+ case NCR_OP_DIGEST:
+ /* obtain data item */
+ if (op.data.digest.text != NCR_DATA_INVALID) {
+ ncr_session_update(lists, arg);
+ }
+ odata = ncr_data_item_get( &lists->data, op.data.digest.output);
+ if (odata == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ digest_size = algo_digest_size(sess->algo);
+ if (digest_size == 0 || odata->data_size < digest_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ ret = cryptodev_hash_final(&sess->hctx, odata->data);
+ break;
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ if (key) _ncr_key_item_put(key);
+ if (odata) _ncr_data_item_put(odata);
+ if (data) _ncr_data_item_put(data);
+ _ncr_sessions_item_put(sess);
+ _ncr_session_deinit(&lists->sessions, op.ses);
+
+ return ret;
+}
+
+int ncr_session_once(struct ncr_lists* lists, void __user* arg)
+{
+ struct __user ncr_session_once_op_st* op = arg;
+ int ret;
+
+ ret = ncr_session_init(lists, &op->init);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ ret = ncr_session_final(lists, &op->op);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ return 0;
+}
+
diff --git a/ncr.c b/ncr.c
index 1736abb82c1..3e246ba2dd6 100644
--- a/ncr.c
+++ b/ncr.c
@@ -95,9 +95,17 @@ ncr_ioctl(struct ncr_lists* lst, struct file *filp,
case NCRIO_KEY_GET_INFO:
return ncr_key_info(&lst->key, (void*)arg);
case NCRIO_KEY_WRAP:
- return ncr_key_wrap(&lst->key, &lst->data, &lst->sessions, (void*)arg);
+ return ncr_key_wrap(&lst->key, &lst->data, (void*)arg);
case NCRIO_KEY_UNWRAP:
- return ncr_key_unwrap(&lst->key, &lst->data, &lst->sessions, (void*)arg);
+ return ncr_key_unwrap(&lst->key, &lst->data, (void*)arg);
+ case NCRIO_SESSION_INIT:
+ return ncr_session_init(lst, (void*)arg);
+ case NCRIO_SESSION_UPDATE:
+ return ncr_session_update(lst, (void*)arg);
+ case NCRIO_SESSION_FINAL:
+ return ncr_session_final(lst, (void*)arg);
+ case NCRIO_SESSION_ONCE:
+ return ncr_session_once(lst, (void*)arg);
#if 0
case NCRIO_KEY_GENERATE_PAIR:
return ncr_key_generate_pair(&lst->key, (void*)arg);
diff --git a/ncr.h b/ncr.h
index b9a38d584a9..aa7f3c1a18f 100644
--- a/ncr.h
+++ b/ncr.h
@@ -5,7 +5,10 @@
#include <inttypes.h>
#endif
+#define NCR_CIPHER_MAX_BLOCK_LEN 32
+#define NCR_HASH_MAX_OUTPUT_SIZE 64
typedef enum {
+ NCR_ALG_NONE,
NCR_ALG_3DES_CBC=2,
NCR_ALG_AES_CBC,
NCR_ALG_CAMELLIA_CBC,
@@ -31,6 +34,8 @@ typedef enum {
NCR_ALG_DSA,
} ncr_algorithm_t;
+
+
typedef enum {
NCR_WALG_AES_RFC3394,
} ncr_wrap_algorithm_t;
@@ -48,7 +53,7 @@ typedef enum {
#define NCR_DATA_FLAG_SIGN_ONLY 2 /* this object can only be used with hash/sign operations */
typedef int ncr_data_t;
-#define NCR_DATA_INVALID (ncr_data_t)(-1)
+#define NCR_DATA_INVALID (ncr_data_t)(0)
struct ncr_data_init_st {
ncr_data_t desc;
@@ -75,7 +80,7 @@ struct ncr_data_st {
typedef int ncr_key_t;
-#define NCR_KEY_INVALID (ncr_key_t)(-1)
+#define NCR_KEY_INVALID (ncr_key_t)(0)
#define NCR_KEY_FLAG_EXPORTABLE 1
#define NCR_KEY_FLAG_WRAPPABLE (1<<1)
@@ -125,7 +130,7 @@ struct ncr_key_params_st {
union {
struct {
- void* iv;
+ uint8_t iv[NCR_CIPHER_MAX_BLOCK_LEN];
size_t iv_size;
} cipher;
struct {
@@ -288,7 +293,7 @@ typedef enum {
} ncr_crypto_op_t;
typedef int ncr_session_t;
-#define NCR_SESSION_INVALID (ncr_session_t)-1
+#define NCR_SESSION_INVALID (ncr_session_t)0
/* input of CIOCGSESSION */
struct ncr_session_st {
diff --git a/ncr_int.h b/ncr_int.h
index e96e4980e2f..ec4aac17d26 100644
--- a/ncr_int.h
+++ b/ncr_int.h
@@ -10,7 +10,10 @@
struct session_item_st {
struct list_head list;
+ ncr_algorithm_t algo;
+ ncr_crypto_op_t op;
struct cipher_data ctx;
+ struct hash_data hctx;
atomic_t refcnt;
ncr_session_t desc;
@@ -117,15 +120,19 @@ void ncr_limits_deinit(void);
ncr_key_type_t ncr_algorithm_to_key_type(ncr_algorithm_t algo);
-int ncr_key_wrap(struct list_sem_st* keys, struct list_sem_st* data, struct list_sem_st* sess_lst, void __user* arg);
-int ncr_key_unwrap(struct list_sem_st*, struct list_sem_st* data, struct list_sem_st* sess_lst, void __user* arg);
+int ncr_key_wrap(struct list_sem_st* keys, struct list_sem_st* data, void __user* arg);
+int ncr_key_unwrap(struct list_sem_st*, struct list_sem_st* data, void __user* arg);
/* sessions */
struct session_item_st* ncr_session_new(struct list_sem_st* lst);
void _ncr_sessions_item_put( struct session_item_st* item);
struct session_item_st* ncr_sessions_item_get( struct list_sem_st* lst, ncr_session_t desc);
void ncr_sessions_list_deinit(struct list_sem_st* lst);
-void ncr_session_deinit(struct list_sem_st* lst, ncr_session_t desc);
+
+int ncr_session_init(struct ncr_lists* lists, void __user* arg);
+int ncr_session_update(struct ncr_lists* lists, void __user* arg);
+int ncr_session_final(struct ncr_lists* lists, void __user* arg);
+int ncr_session_once(struct ncr_lists* lists, void __user* arg);
/* misc helper macros */
inline static unsigned int key_flags_to_data(unsigned int key_flags)