summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--cryptodev_cipher.c8
-rw-r--r--cryptodev_int.h16
-rw-r--r--cryptodev_main.c11
-rw-r--r--examples/Makefile8
-rw-r--r--examples/ncr-direct.c443
-rw-r--r--examples/ncr.c15
-rw-r--r--examples/pk.c30
-rw-r--r--examples/speed.c5
-rw-r--r--ncr-data.c2
-rw-r--r--ncr-pk.c210
-rw-r--r--ncr-pk.h22
-rw-r--r--ncr-sessions.c667
-rw-r--r--ncr.c1
-rw-r--r--ncr.h26
-rw-r--r--ncr_int.h9
16 files changed, 1246 insertions, 228 deletions
diff --git a/.gitignore b/.gitignore
index 4379d92..e3f0923 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@ modules.order
examples/cipher
examples/hmac
examples/ncr
+examples/ncr-direct
examples/pk
examples/speed
releases
diff --git a/cryptodev_cipher.c b/cryptodev_cipher.c
index fa5aab2..0dd0db7 100644
--- a/cryptodev_cipher.c
+++ b/cryptodev_cipher.c
@@ -188,24 +188,24 @@ struct scatterlist sg, sg2;
}
-ssize_t cryptodev_cipher_encrypt( struct cipher_data* cdata, struct scatterlist *sg1, struct scatterlist *sg2, size_t len)
+ssize_t cryptodev_cipher_encrypt( struct cipher_data* cdata, const struct scatterlist *sg1, struct scatterlist *sg2, size_t len)
{
int ret;
INIT_COMPLETION(cdata->async.result->completion);
- ablkcipher_request_set_crypt(cdata->async.request, sg1, sg2,
+ ablkcipher_request_set_crypt(cdata->async.request, (struct scatterlist*)sg1, sg2,
len, cdata->async.iv);
ret = crypto_ablkcipher_encrypt(cdata->async.request);
return waitfor(cdata->async.result,ret);
}
-ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, struct scatterlist *sg1, struct scatterlist *sg2, size_t len)
+ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, const struct scatterlist *sg1, struct scatterlist *sg2, size_t len)
{
int ret;
INIT_COMPLETION(cdata->async.result->completion);
- ablkcipher_request_set_crypt(cdata->async.request, sg1, sg2,
+ ablkcipher_request_set_crypt(cdata->async.request, (struct scatterlist*)sg1, sg2,
len, cdata->async.iv);
ret = crypto_ablkcipher_decrypt(cdata->async.request);
diff --git a/cryptodev_int.h b/cryptodev_int.h
index a0d3073..3c6eca4 100644
--- a/cryptodev_int.h
+++ b/cryptodev_int.h
@@ -24,6 +24,18 @@
extern int cryptodev_verbosity;
+/* For zero copy */
+int __get_userbuf(uint8_t *addr, uint32_t len, int write,
+ int pgcount, struct page **pg, struct scatterlist *sg);
+void release_user_pages(struct page **pg, int pagecount);
+
+/* last page - first page + 1 */
+#define PAGECOUNT(buf, buflen) \
+ ((((unsigned long)(buf + buflen - 1) & PAGE_MASK) >> PAGE_SHIFT) - \
+ (((unsigned long) buf & PAGE_MASK) >> PAGE_SHIFT) + 1)
+
+#define DEFAULT_PREALLOC_PAGES 32
+
struct cipher_data
{
int init; /* 0 uninitialized */
@@ -39,8 +51,8 @@ struct cipher_data
int cryptodev_cipher_init(struct cipher_data* out, const char* alg_name, uint8_t * key, size_t keylen);
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);
+ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, const struct scatterlist *sg1, struct scatterlist *sg2, size_t len);
+ssize_t cryptodev_cipher_encrypt( struct cipher_data* cdata, const struct scatterlist *sg1, struct scatterlist *sg2, size_t len);
void 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,
diff --git a/cryptodev_main.c b/cryptodev_main.c
index 0316a74..89b9a02 100644
--- a/cryptodev_main.c
+++ b/cryptodev_main.c
@@ -65,8 +65,6 @@ module_param(enable_stats, int, 0644);
MODULE_PARM_DESC(enable_stats, "collect statictics about cryptodev usage");
#endif
-#define DEFAULT_PREALLOC_PAGES 16
-
/* ====== CryptoAPI ====== */
struct fcrypt {
struct list_head list;
@@ -495,7 +493,7 @@ __crypto_run_std(struct csession *ses_ptr, struct crypt_op *cop)
#ifndef DISABLE_ZCOPY
-static void release_user_pages(struct page **pg, int pagecount)
+void release_user_pages(struct page **pg, int pagecount)
{
while (pagecount--) {
if (!PageReserved(pg[pagecount]))
@@ -504,16 +502,11 @@ static void release_user_pages(struct page **pg, int pagecount)
}
}
-/* last page - first page + 1 */
-#define PAGECOUNT(buf, buflen) \
- ((((unsigned long)(buf + buflen - 1) & PAGE_MASK) >> PAGE_SHIFT) - \
- (((unsigned long) buf & PAGE_MASK) >> PAGE_SHIFT) + 1)
-
/* offset of buf in it's first page */
#define PAGEOFFSET(buf) ((unsigned long)buf & ~PAGE_MASK)
/* fetch the pages addr resides in into pg and initialise sg with them */
-static int __get_userbuf(uint8_t *addr, uint32_t len, int write,
+int __get_userbuf(uint8_t *addr, uint32_t len, int write,
int pgcount, struct page **pg, struct scatterlist *sg)
{
int ret, pglen, i = 0;
diff --git a/examples/Makefile b/examples/Makefile
index c65297f..f482649 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -1,7 +1,7 @@
CC = gcc
CFLAGS = -Wall -g -O2
-progs := cipher hmac ncr pk speed
+progs := cipher hmac ncr pk speed ncr-direct
all: $(progs)
@@ -17,15 +17,19 @@ hmac: hmac.c
ncr: ncr.c
$(CC) $(CFLAGS) $< -o $@
+ncr-direct: ncr-direct.c
+ $(CC) $(CFLAGS) $< -o $@
+
pk: pk.c
$(CC) $(CFLAGS) $< -o $@ -L/usr/local/lib -lgnutls
check: $(progs)
./ncr
+ ./ncr-direct
./pk
./cipher
./hmac
./speed
clean:
- rm -f *.o *~ hmac cipher ncr pk speed
+ rm -f *.o *~ hmac cipher ncr pk speed ncr-direct
diff --git a/examples/ncr-direct.c b/examples/ncr-direct.c
new file mode 100644
index 0000000..0908e2c
--- /dev/null
+++ b/examples/ncr-direct.c
@@ -0,0 +1,443 @@
+/*
+ * Demo on how to use /dev/crypto device for HMAC.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "../ncr.h"
+#include <stdlib.h>
+
+#define DATA_SIZE 4096
+#define KEY_DATA_SIZE 16
+
+
+struct aes_vectors_st {
+ const uint8_t* key;
+ const uint8_t* plaintext;
+ const uint8_t* ciphertext;
+} aes_vectors[] = {
+ {
+ .key = (uint8_t*)"\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ .plaintext = (uint8_t*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ciphertext = (uint8_t*)"\x4b\xc3\xf8\x83\x45\x0c\x11\x3c\x64\xca\x42\xe1\x11\x2a\x9e\x87",
+ },
+ {
+ .key = (uint8_t*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ .plaintext = (uint8_t*)"\xf3\x44\x81\xec\x3c\xc6\x27\xba\xcd\x5d\xc3\xfb\x08\xf2\x73\xe6",
+ .ciphertext = (uint8_t*)"\x03\x36\x76\x3e\x96\x6d\x92\x59\x5a\x56\x7c\xc9\xce\x53\x7f\x5e",
+ },
+ {
+ .key = (uint8_t*)"\x10\xa5\x88\x69\xd7\x4b\xe5\xa3\x74\xcf\x86\x7c\xfb\x47\x38\x59",
+ .plaintext = (uint8_t*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ciphertext = (uint8_t*)"\x6d\x25\x1e\x69\x44\xb0\x51\xe0\x4e\xaa\x6f\xb4\xdb\xf7\x84\x65",
+ },
+ {
+ .key = (uint8_t*)"\xca\xea\x65\xcd\xbb\x75\xe9\x16\x9e\xcd\x22\xeb\xe6\xe5\x46\x75",
+ .plaintext = (uint8_t*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ciphertext = (uint8_t*)"\x6e\x29\x20\x11\x90\x15\x2d\xf4\xee\x05\x81\x39\xde\xf6\x10\xbb",
+ },
+ {
+ .key = (uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe",
+ .plaintext = (uint8_t*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ciphertext = (uint8_t*)"\x9b\xa4\xa9\x14\x3f\x4e\x5d\x40\x48\x52\x1c\x4f\x88\x77\xd8\x8e",
+ },
+};
+
+/* AES cipher */
+static int
+test_ncr_aes(int cfd)
+{
+ struct ncr_data_init_st dinit;
+ ncr_key_t key;
+ struct ncr_key_data_st keydata;
+ struct ncr_data_st kdata;
+ ncr_data_t dd, dd2;
+ uint8_t data[KEY_DATA_SIZE];
+ int i, j;
+ struct ncr_session_once_op_st nop;
+
+ dinit.max_object_size = KEY_DATA_SIZE;
+ dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
+ dinit.initial_data = NULL;
+ dinit.initial_data_size = 0;
+
+ if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_DATA_INIT)");
+ return 1;
+ }
+
+ dd = dinit.desc;
+
+ if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_DATA_INIT)");
+ return 1;
+ }
+
+ dd2 = dinit.desc;
+
+ /* convert it to key */
+ if (ioctl(cfd, NCRIO_KEY_INIT, &key)) {
+ perror("ioctl(NCRIO_KEY_INIT)");
+ return 1;
+ }
+
+ keydata.key_id[0] = 'a';
+ keydata.key_id[2] = 'b';
+ keydata.key_id_size = 2;
+ keydata.type = NCR_KEY_TYPE_SECRET;
+ keydata.algorithm = NCR_ALG_AES_CBC;
+ keydata.flags = NCR_KEY_FLAG_EXPORTABLE;
+
+
+ fprintf(stdout, "Tests on AES Encryption\n");
+ for (i=0;i<sizeof(aes_vectors)/sizeof(aes_vectors[0]);i++) {
+
+ /* import key */
+ kdata.data = (void*)aes_vectors[i].key;
+ kdata.data_size = 16;
+ kdata.desc = dd;
+
+ if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_DATA_SET)");
+ return 1;
+ }
+
+ keydata.key = key;
+ keydata.data = dd;
+ if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_KEY_IMPORT)");
+ return 1;
+ }
+
+ /* encrypt */
+ memset(&nop, 0, sizeof(nop));
+ nop.init.algorithm = NCR_ALG_AES_ECB;
+ nop.init.key = key;
+ nop.init.op = NCR_OP_ENCRYPT;
+ nop.op.data.udata.input = (void*)aes_vectors[i].plaintext;
+ nop.op.data.udata.input_size = 16;
+ nop.op.data.udata.output = data;
+ nop.op.data.udata.output_size = sizeof(data);
+ nop.op.type = NCR_DIRECT_DATA;
+
+ if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_SESSION_ONCE)");
+ return 1;
+ }
+
+ /* verify */
+
+ if (nop.op.data.udata.output_size != 16 || memcmp(data, aes_vectors[i].ciphertext, 16) != 0) {
+ fprintf(stderr, "AES test vector %d failed!\n", i);
+
+ fprintf(stderr, "Cipher[%d]: ", (int)nop.op.data.udata.output_size);
+ for(j=0;j<nop.op.data.udata.output_size;j++)
+ fprintf(stderr, "%.2x:", (int)data[j]);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Expected[%d]: ", 16);
+ for(j=0;j<16;j++)
+ fprintf(stderr, "%.2x:", (int)aes_vectors[i].ciphertext[j]);
+ fprintf(stderr, "\n");
+ return 1;
+ }
+ }
+
+ fprintf(stdout, "Tests on AES Decryption\n");
+ for (i=0;i<sizeof(aes_vectors)/sizeof(aes_vectors[0]);i++) {
+
+ /* import key */
+ kdata.data = (void*)aes_vectors[i].key;
+ kdata.data_size = 16;
+ kdata.desc = dd;
+
+ if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_DATA_SET)");
+ return 1;
+ }
+
+ keydata.key = key;
+ keydata.data = dd;
+ if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_KEY_IMPORT)");
+ return 1;
+ }
+
+
+ /* decrypt */
+ memset(&nop, 0, sizeof(nop));
+ nop.init.algorithm = NCR_ALG_AES_ECB;
+ nop.init.key = key;
+ nop.init.op = NCR_OP_DECRYPT;
+ nop.op.data.udata.input = (void*)aes_vectors[i].ciphertext;
+ nop.op.data.udata.input_size = 16;
+ nop.op.data.udata.output = data;
+ nop.op.data.udata.output_size = sizeof(data);
+ nop.op.type = NCR_DIRECT_DATA;
+
+ if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_SESSION_ONCE)");
+ return 1;
+ }
+
+ if (nop.op.data.udata.output_size != 16 || memcmp(data, aes_vectors[i].plaintext, 16) != 0) {
+ fprintf(stderr, "AES test vector %d failed!\n", i);
+
+ fprintf(stderr, "Plain[%d]: ", (int)nop.op.data.udata.output_size);
+ for(j=0;j<nop.op.data.udata.output_size;j++)
+ fprintf(stderr, "%.2x:", (int)data[j]);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Expected[%d]: ", 16);
+ for(j=0;j<16;j++)
+ fprintf(stderr, "%.2x:", (int)aes_vectors[i].plaintext[j]);
+ fprintf(stderr, "\n");
+ return 1;
+ }
+ }
+
+
+ fprintf(stdout, "\n");
+
+ return 0;
+
+}
+
+struct hash_vectors_st {
+ const char* name;
+ ncr_algorithm_t algorithm;
+ const uint8_t* key; /* if hmac */
+ int key_size;
+ const uint8_t* plaintext;
+ int plaintext_size;
+ const uint8_t* output;
+ int output_size;
+ ncr_crypto_op_t op;
+} hash_vectors[] = {
+ {
+ .name = "SHA1",
+ .algorithm = NCR_ALG_SHA1,
+ .key = NULL,
+ .plaintext = (uint8_t*)"what do ya want for nothing?",
+ .plaintext_size = sizeof("what do ya want for nothing?")-1,
+ .output = (uint8_t*)"\x8f\x82\x03\x94\xf9\x53\x35\x18\x20\x45\xda\x24\xf3\x4d\xe5\x2b\xf8\xbc\x34\x32",
+ .output_size = 20,
+ .op = NCR_OP_SIGN,
+ },
+ {
+ .name = "HMAC-MD5",
+ .algorithm = NCR_ALG_HMAC_MD5,
+ .key = (uint8_t*)"Jefe",
+ .key_size = 4,
+ .plaintext = (uint8_t*)"what do ya want for nothing?",
+ .plaintext_size = sizeof("what do ya want for nothing?")-1,
+ .output = (uint8_t*)"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38",
+ .output_size = 16,
+ .op = NCR_OP_SIGN,
+ },
+ /* from rfc4231 */
+ {
+ .name = "HMAC-SHA224",
+ .algorithm = NCR_ALG_HMAC_SHA2_224,
+ .key = (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+ .key_size = 20,
+ .plaintext = (uint8_t*)"Hi There",
+ .plaintext_size = sizeof("Hi There")-1,
+ .output = (uint8_t*)"\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3\x3f\x47\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22",
+ .output_size = 28,
+ .op = NCR_OP_SIGN,
+ },
+ {
+ .name = "HMAC-SHA256",
+ .algorithm = NCR_ALG_HMAC_SHA2_256,
+ .key = (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+ .key_size = 20,
+ .plaintext = (uint8_t*)"Hi There",
+ .plaintext_size = sizeof("Hi There")-1,
+ .output = (uint8_t*)"\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7",
+ .output_size = 32,
+ .op = NCR_OP_SIGN,
+ },
+ {
+ .name = "HMAC-SHA384",
+ .algorithm = NCR_ALG_HMAC_SHA2_384,
+ .key = (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+ .key_size = 20,
+ .plaintext = (uint8_t*)"Hi There",
+ .plaintext_size = sizeof("Hi There")-1,
+ .output = (uint8_t*)"\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90\x7f\x15\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c\xfa\xea\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6",
+ .output_size = 48,
+ .op = NCR_OP_SIGN,
+ },
+ {
+ .name = "HMAC-SHA512",
+ .algorithm = NCR_ALG_HMAC_SHA2_512,
+ .key = (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+ .key_size = 20,
+ .plaintext = (uint8_t*)"Hi There",
+ .plaintext_size = sizeof("Hi There")-1,
+ .output = (uint8_t*)"\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54",
+ .output_size = 64,
+ .op = NCR_OP_SIGN,
+ },
+};
+
+#define HASH_DATA_SIZE 64
+
+/* SHA1 and other hashes */
+static int
+test_ncr_hash(int cfd)
+{
+ struct ncr_data_init_st dinit;
+ ncr_key_t key;
+ struct ncr_key_data_st keydata;
+ struct ncr_data_st kdata;
+ ncr_data_t dd, dd2;
+ uint8_t data[HASH_DATA_SIZE];
+ int i, j;
+ struct ncr_session_once_op_st nop;
+
+ dinit.max_object_size = HASH_DATA_SIZE;
+ dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
+ dinit.initial_data = NULL;
+ dinit.initial_data_size = 0;
+
+ if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_DATA_INIT)");
+ return 1;
+ }
+
+ dd = dinit.desc;
+
+ if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_DATA_INIT)");
+ return 1;
+ }
+
+ dd2 = dinit.desc;
+
+ /* convert it to key */
+ if (ioctl(cfd, NCRIO_KEY_INIT, &key)) {
+ perror("ioctl(NCRIO_KEY_INIT)");
+ return 1;
+ }
+
+ keydata.key_id[0] = 'a';
+ keydata.key_id[2] = 'b';
+ keydata.key_id_size = 2;
+ keydata.type = NCR_KEY_TYPE_SECRET;
+ keydata.algorithm = NCR_ALG_AES_CBC;
+ keydata.flags = NCR_KEY_FLAG_EXPORTABLE;
+
+
+ fprintf(stdout, "Tests on Hashes\n");
+ for (i=0;i<sizeof(hash_vectors)/sizeof(hash_vectors[0]);i++) {
+
+ fprintf(stdout, "\t%s:\n", hash_vectors[i].name);
+ /* import key */
+ if (hash_vectors[i].key != NULL) {
+ kdata.data = (void*)hash_vectors[i].key;
+ kdata.data_size = hash_vectors[i].key_size;
+ kdata.desc = dd;
+
+ if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_DATA_SET)");
+ return 1;
+ }
+
+ keydata.key = key;
+ keydata.data = dd;
+ if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_KEY_IMPORT)");
+ return 1;
+ }
+ }
+
+ /* encrypt */
+ memset(&nop, 0, sizeof(nop));
+ nop.init.algorithm = hash_vectors[i].algorithm;
+ if (hash_vectors[i].key != NULL)
+ nop.init.key = key;
+ nop.init.op = hash_vectors[i].op;
+ nop.op.data.udata.input = (void*)hash_vectors[i].plaintext;
+ nop.op.data.udata.input_size = hash_vectors[i].plaintext_size;
+ nop.op.data.udata.output = data;
+ nop.op.data.udata.output_size = sizeof(data);
+ nop.op.type = NCR_DIRECT_DATA;
+
+ if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_SESSION_ONCE)");
+ return 1;
+ }
+
+ if (nop.op.data.udata.output_size != hash_vectors[i].output_size ||
+ memcmp(data, hash_vectors[i].output, hash_vectors[i].output_size) != 0) {
+ fprintf(stderr, "HASH test vector %d failed!\n", i);
+
+ fprintf(stderr, "Output[%d]: ", (int)nop.op.data.udata.output_size);
+ for(j=0;j<nop.op.data.udata.output_size;j++)
+ fprintf(stderr, "%.2x:", (int)data[j]);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Expected[%d]: ", hash_vectors[i].output_size);
+ for(j=0;j<hash_vectors[i].output_size;j++)
+ fprintf(stderr, "%.2x:", (int)hash_vectors[i].output[j]);
+ fprintf(stderr, "\n");
+ return 1;
+ }
+ }
+
+ fprintf(stdout, "\n");
+
+ return 0;
+
+}
+
+
+int
+main()
+{
+ int fd = -1;
+
+ /* Open the crypto device */
+ fd = open("/dev/crypto", O_RDWR, 0);
+ if (fd < 0) {
+ perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ if (test_ncr_aes(fd))
+ return 1;
+
+ if (test_ncr_hash(fd))
+ return 1;
+
+ /* Close the original descriptor */
+ if (close(fd)) {
+ perror("close(fd)");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/examples/ncr.c b/examples/ncr.c
index d9870e0..bd5779c 100644
--- a/examples/ncr.c
+++ b/examples/ncr.c
@@ -809,8 +809,9 @@ test_ncr_aes(int cfd)
nop.init.algorithm = NCR_ALG_AES_ECB;
nop.init.key = key;
nop.init.op = NCR_OP_ENCRYPT;
- nop.op.input = dd;
- nop.op.output = dd2;
+ nop.op.data.ndata.input = dd;
+ nop.op.data.ndata.output = dd2;
+ nop.op.type = NCR_DATA;
if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -884,8 +885,9 @@ test_ncr_aes(int cfd)
nop.init.algorithm = NCR_ALG_AES_ECB;
nop.init.key = key;
nop.init.op = NCR_OP_DECRYPT;
- nop.op.input = dd;
- nop.op.output = dd2;
+ nop.op.data.ndata.input = dd;
+ nop.op.data.ndata.output = dd2;
+ nop.op.type = NCR_DATA;
if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -1098,8 +1100,9 @@ test_ncr_hash(int cfd)
if (hash_vectors[i].key != NULL)
nop.init.key = key;
nop.init.op = hash_vectors[i].op;
- nop.op.input = dd;
- nop.op.output = dd2;
+ nop.op.data.ndata.input = dd;
+ nop.op.data.ndata.output = dd2;
+ nop.op.type = NCR_DATA;
if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
diff --git a/examples/pk.c b/examples/pk.c
index ce9dff8..287e9f3 100644
--- a/examples/pk.c
+++ b/examples/pk.c
@@ -371,8 +371,9 @@ static int rsa_key_encrypt(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int oae
nop.init.params.params.rsa.type = RSA_PKCS1_V1_5;
}
nop.init.op = NCR_OP_ENCRYPT;
- nop.op.input = datad;
- nop.op.output = encd;
+ nop.op.data.ndata.input = datad;
+ nop.op.data.ndata.output = encd;
+ nop.op.type = NCR_DATA;
if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -391,8 +392,9 @@ static int rsa_key_encrypt(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int oae
} else {
nop.init.params.params.rsa.type = RSA_PKCS1_V1_5;
}
- nop.op.input = encd;
- nop.op.output = encd;
+ nop.op.data.ndata.input = encd;
+ nop.op.data.ndata.output = encd;
+ nop.op.type = NCR_DATA;
if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -466,8 +468,9 @@ static int rsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int
nop.init.params.params.rsa.sign_hash = NCR_ALG_SHA1;
nop.init.op = NCR_OP_SIGN;
- nop.op.input = datad;
- nop.op.output = signd;
+ nop.op.data.ndata.input = datad;
+ nop.op.data.ndata.output = signd;
+ nop.op.type = NCR_DATA;
if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -483,8 +486,9 @@ static int rsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int
nop.init.params.params.rsa.sign_hash = NCR_ALG_SHA1;
nop.init.op = NCR_OP_VERIFY;
- nop.op.input = datad;
- nop.op.output = signd;
+ nop.op.data.ndata.input = datad;
+ nop.op.data.ndata.output = signd;
+ nop.op.type = NCR_DATA;
if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -545,8 +549,9 @@ static int dsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey)
nop.init.params.params.dsa.sign_hash = NCR_ALG_SHA1;
nop.init.op = NCR_OP_SIGN;
- nop.op.input = datad;
- nop.op.output = signd;
+ nop.op.data.ndata.input = datad;
+ nop.op.data.ndata.output = signd;
+ nop.op.type = NCR_DATA;
if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -561,8 +566,9 @@ static int dsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey)
nop.init.params.params.dsa.sign_hash = NCR_ALG_SHA1;
nop.init.op = NCR_OP_VERIFY;
- nop.op.input = datad;
- nop.op.output = signd;
+ nop.op.data.ndata.input = datad;
+ nop.op.data.ndata.output = signd;
+ nop.op.type = NCR_DATA;
if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
diff --git a/examples/speed.c b/examples/speed.c
index d3cf04a..1416411 100644
--- a/examples/speed.c
+++ b/examples/speed.c
@@ -189,8 +189,9 @@ int encrypt_data_ncr(int cfd, int algo, int chunksize)
nop.init.algorithm = algo;
nop.init.key = key;
nop.init.op = NCR_OP_ENCRYPT;
- nop.op.input = dd;
- nop.op.output = dd;
+ nop.op.data.ndata.input = dd;
+ nop.op.data.ndata.output = dd;
+ nop.op.type = NCR_DATA;
if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
diff --git a/ncr-data.c b/ncr-data.c
index 21aabe4..73c62c6 100644
--- a/ncr-data.c
+++ b/ncr-data.c
@@ -146,6 +146,8 @@ int ncr_data_init(struct list_sem_st* lst, void __user* arg)
goto err_data;
}
data->max_data_size = init.max_object_size;
+
+ sg_init_one(&data->sg, data->data, data->max_data_size);
if (init.initial_data != NULL) {
if (unlikely(copy_from_user(data->data, init.initial_data,
diff --git a/ncr-pk.c b/ncr-pk.c
index bfe575d..8d85a92 100644
--- a/ncr-pk.c
+++ b/ncr-pk.c
@@ -377,129 +377,230 @@ int ncr_pk_cipher_init(const struct algo_properties_st *algo,
}
int ncr_pk_cipher_encrypt(const struct ncr_pk_ctx* ctx,
- const void* input, size_t input_size,
- void* output, size_t *output_size)
+ const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size,
+ struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size)
{
-int cret;
-unsigned long osize = *output_size;
+int cret, ret;
+unsigned long osize = *osg_size;
+uint8_t* tmp;
+void * input, *output;
+
+ tmp = kmalloc(isg_size + *osg_size, GFP_KERNEL);
+ if (tmp == NULL) {
+ err();
+ return -ENOMEM;
+ }
+
+ ret = sg_copy_to_buffer((struct scatterlist*)isg, isg_cnt, tmp, isg_size);
+ if (ret != isg_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ input = tmp;
+ output = &tmp[isg_size];
+
switch(ctx->algorithm->algo) {
case NCR_ALG_RSA:
- cret = rsa_encrypt_key_ex( input, input_size, output, &osize,
+ cret = rsa_encrypt_key_ex( input, isg_size, output, &osize,
NULL, 0, ctx->oaep_hash, ctx->type, &ctx->key->key.pk.rsa);
if (cret != CRYPT_OK) {
- printk("cret: %d type: %d\n", cret, ctx->type);
err();
- return tomerr(cret);
+ ret = tomerr(cret);
+ goto fail;
}
- *output_size = osize;
+ *osg_size = osize;
+
break;
case NCR_ALG_DSA:
- return -EINVAL;
- break;
+ ret = -EINVAL;
+ goto fail;
default:
err();
- return -EINVAL;
+ ret = -EINVAL;
+ goto fail;
}
-
- return 0;
+
+ ret = sg_copy_from_buffer(osg, osg_cnt, output, *osg_size);
+ if (ret != *osg_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ kfree(tmp);
+ return ret;
}
-int ncr_pk_cipher_decrypt(const struct ncr_pk_ctx* ctx, const void* input, size_t input_size,
- void* output, size_t *output_size)
+int ncr_pk_cipher_decrypt(const struct ncr_pk_ctx* ctx,
+ const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size,
+ struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size)
{
-int cret;
-unsigned long osize = *output_size;
+int cret, ret;
int stat;
+unsigned long osize = *osg_size;
+uint8_t* tmp;
+void * input, *output;
+
+ tmp = kmalloc(isg_size + *osg_size, GFP_KERNEL);
+ if (tmp == NULL) {
+ err();
+ return -ENOMEM;
+ }
+
+ input = tmp;
+ output = &tmp[isg_size];
+
+ ret = sg_copy_to_buffer((struct scatterlist*)isg, isg_cnt, input, isg_size);
+ if (ret != isg_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
switch(ctx->algorithm->algo) {
case NCR_ALG_RSA:
- cret = rsa_decrypt_key_ex( input, input_size, output, &osize,
+ cret = rsa_decrypt_key_ex( input, isg_size, output, &osize,
NULL, 0, ctx->oaep_hash, ctx->type, &stat, &ctx->key->key.pk.rsa);
if (cret != CRYPT_OK) {
err();
- return tomerr(cret);
+ ret = tomerr(cret);
+ goto fail;
}
if (stat==0) {
err();
- return -EINVAL;
+ ret = -EINVAL;
+ goto fail;
}
- *output_size = osize;
+ *osg_size = osize;
break;
case NCR_ALG_DSA:
- return -EINVAL;
- break;
+ ret = -EINVAL;
+ goto fail;
default:
err();
- return -EINVAL;
+ ret = -EINVAL;
+ goto fail;
}
+
+ ret = sg_copy_from_buffer(osg, osg_cnt, output, *osg_size);
+ if (ret != *osg_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+fail:
+ kfree(tmp);
- return 0;
+ return ret;
}
int ncr_pk_cipher_sign(const struct ncr_pk_ctx* ctx,
- const void* input, size_t input_size,
- void* output, size_t *output_size)
+ const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size,
+ struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size)
{
-int cret;
-unsigned long osize = *output_size;
+int cret, ret;
+unsigned long osize = *osg_size;
+uint8_t* tmp;
+void * input, *output;
+
+ tmp = kmalloc(isg_size + *osg_size, GFP_KERNEL);
+ if (tmp == NULL) {
+ err();
+ return -ENOMEM;
+ }
+
+ input = tmp;
+ output = &tmp[isg_size];
+
+ ret = sg_copy_to_buffer((struct scatterlist*)isg, isg_cnt, input, isg_size);
+ if (ret != isg_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
switch(ctx->algorithm->algo) {
case NCR_ALG_RSA:
- if (ctx->sign_hash == NULL) {
- err();
- return -EINVAL;
- }
- cret = rsa_sign_hash_ex( input, input_size, output, &osize,
+ cret = rsa_sign_hash_ex( input, isg_size, output, &osize,
ctx->type, ctx->sign_hash, ctx->salt_len, &ctx->key->key.pk.rsa);
if (cret != CRYPT_OK) {
err();
return tomerr(cret);
}
- *output_size = osize;
+ *osg_size = osize;
break;
case NCR_ALG_DSA:
- cret = dsa_sign_hash( input, input_size, output, &osize,
+ cret = dsa_sign_hash( input, isg_size, output, &osize,
&ctx->key->key.pk.dsa);
if (cret != CRYPT_OK) {
err();
return tomerr(cret);
}
- *output_size = osize;
+ *osg_size = osize;
break;
default:
err();
- return -EINVAL;
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = sg_copy_from_buffer(osg, osg_cnt, output, *osg_size);
+ if (ret != *osg_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
}
+ ret = 0;
+fail:
+ kfree(tmp);
- return 0;
+ return ret;
}
int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx,
- const void* signature, size_t signature_size,
+ const struct scatterlist* sign_sg, unsigned int sign_sg_cnt, size_t sign_sg_size,
const void* hash, size_t hash_size, ncr_error_t* err)
{
-int cret;
+int cret, ret;
int stat;
+uint8_t* sig;
+
+ sig = kmalloc(sign_sg_size, GFP_KERNEL);
+ if (sig == NULL) {
+ err();
+ return -ENOMEM;
+ }
+
+ ret = sg_copy_to_buffer((struct scatterlist*)sign_sg, sign_sg_cnt, sig, sign_sg_size);
+ if (ret != sign_sg_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
switch(ctx->algorithm->algo) {
case NCR_ALG_RSA:
- if (ctx->sign_hash == NULL) {
- err();
- return -EINVAL;
- }
- cret = rsa_verify_hash_ex( signature, signature_size,
+ cret = rsa_verify_hash_ex( sig, sign_sg_size,
hash, hash_size, ctx->type, ctx->sign_hash,
ctx->salt_len, &stat, &ctx->key->key.pk.rsa);
if (cret != CRYPT_OK) {
err();
- return tomerr(cret);
+ ret = tomerr(cret);
+ goto fail;
}
if (stat == 1)
@@ -509,11 +610,12 @@ int stat;
break;
case NCR_ALG_DSA:
- cret = dsa_verify_hash( signature, signature_size,
+ cret = dsa_verify_hash( sig, sign_sg_size,
hash, hash_size, &stat, &ctx->key->key.pk.dsa);
if (cret != CRYPT_OK) {
err();
- return tomerr(cret);
+ ret = tomerr(cret);
+ goto fail;
}
if (stat == 1)
@@ -524,8 +626,12 @@ int stat;
break;
default:
err();
- return -EINVAL;
+ ret = -EINVAL;
+ goto fail;
}
-
- return 0;
+
+ ret = 0;
+fail:
+ kfree(sig);
+ return ret;
}
diff --git a/ncr-pk.h b/ncr-pk.h
index 873ee83..fdc5e1c 100644
--- a/ncr-pk.h
+++ b/ncr-pk.h
@@ -34,15 +34,21 @@ int ncr_pk_cipher_init(const struct algo_properties_st *algo,
struct ncr_pk_ctx* ctx, struct ncr_key_params_st* params,
struct key_item_st *key, const struct algo_properties_st *sign_hash);
void ncr_pk_cipher_deinit(struct ncr_pk_ctx* ctx);
-int ncr_pk_cipher_encrypt(const struct ncr_pk_ctx* ctx, const void* input,
- size_t input_size, void* output, size_t *output_size);
-int ncr_pk_cipher_decrypt(const struct ncr_pk_ctx* ctx, const void* input,
- size_t input_size, void* output, size_t *output_size);
-int ncr_pk_cipher_sign(const struct ncr_pk_ctx* ctx, const void* input,
- size_t input_size, void* output, size_t *output_size);
+int ncr_pk_cipher_encrypt(const struct ncr_pk_ctx* ctx,
+ const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size,
+ struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size);
+
+int ncr_pk_cipher_decrypt(const struct ncr_pk_ctx* ctx,
+ const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size,
+ struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size);
+
+int ncr_pk_cipher_sign(const struct ncr_pk_ctx* ctx,
+ const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size,
+ struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size);
+
int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx,
- const void* signature, size_t signature_size,
- const void* hash, size_t hash_size, ncr_error_t*);
+ const struct scatterlist* sign_sg, unsigned int sign_sg_cnt, size_t sign_sg_size,
+ const void* hash, size_t hash_size, ncr_error_t* err);
#endif
diff --git a/ncr-sessions.c b/ncr-sessions.c
index b8eabdd..fb9fe4f 100644
--- a/ncr-sessions.c
+++ b/ncr-sessions.c
@@ -23,6 +23,8 @@
#include "cryptodev.h"
#include "ncr.h"
#include "ncr_int.h"
+#include <linux/mm_types.h>
+#include <linux/scatterlist.h>
static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc);
@@ -84,6 +86,8 @@ void _ncr_sessions_item_put( struct session_item_st* item)
cryptodev_hash_deinit(&item->hash);
if (item->key)
_ncr_key_item_put(item->key);
+ kfree(item->sg);
+ kfree(item->pages);
kfree(item);
}
}
@@ -92,13 +96,25 @@ struct session_item_st* ncr_session_new(struct list_sem_st* lst)
{
struct session_item_st* sess;
- sess = kmalloc(sizeof(*sess), GFP_KERNEL);
+ sess = kzalloc(sizeof(*sess), GFP_KERNEL);
if (sess == NULL) {
err();
return NULL;
}
- memset(sess, 0, sizeof(*sess));
+ sess->array_size = DEFAULT_PREALLOC_PAGES;
+ sess->pages = kzalloc(sess->array_size *
+ sizeof(struct page *), GFP_KERNEL);
+ sess->sg = kzalloc(sess->array_size *
+ sizeof(struct scatterlist), GFP_KERNEL);
+ if (sess->sg == NULL || sess->pages == NULL) {
+ err();
+ kfree(sess->sg);
+ kfree(sess->pages);
+ kfree(sess);
+ return NULL;
+ }
+ init_MUTEX(&sess->mem_mutex);
atomic_set(&sess->refcnt, 1);
@@ -216,6 +232,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses
ret = -EINVAL;
goto fail;
}
+
switch(session->op) {
case NCR_OP_ENCRYPT:
case NCR_OP_DECRYPT:
@@ -395,6 +412,63 @@ int ncr_session_init(struct ncr_lists* lists, void __user* arg)
return ret;
}
+int _ncr_session_encrypt(struct session_item_st* sess, const struct scatterlist* input, unsigned input_cnt,
+ size_t input_size, void *output, unsigned output_cnt, size_t *output_size)
+{
+int ret;
+
+ if (sess->algorithm->is_symmetric) {
+ /* read key */
+ ret = cryptodev_cipher_encrypt(&sess->cipher, input,
+ output, input_size);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ /* FIXME: handle ciphers that do not require that */
+
+ } else { /* public key */
+ ret = ncr_pk_cipher_encrypt(&sess->pk, input, input_cnt, input_size,
+ output, output_cnt, output_size);
+
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int _ncr_session_decrypt(struct session_item_st* sess, const struct scatterlist* input,
+ unsigned input_cnt, size_t input_size,
+ struct scatterlist *output, unsigned output_cnt, size_t *output_size)
+{
+int ret;
+
+ if (sess->algorithm->is_symmetric) {
+ /* read key */
+ ret = cryptodev_cipher_decrypt(&sess->cipher, input,
+ output, input_size);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ /* FIXME: handle ciphers that do not require equality */
+
+ } else { /* public key */
+ ret = ncr_pk_cipher_decrypt(&sess->pk, input, input_cnt, input_size,
+ output, output_cnt, output_size);
+
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
/* Main update function
*/
static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op)
@@ -403,6 +477,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
struct session_item_st* sess;
struct data_item_st* data = NULL;
struct data_item_st* odata = NULL;
+ size_t new_size;
sess = ncr_sessions_item_get( &lists->sessions, op->ses);
if (sess == NULL) {
@@ -410,17 +485,17 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
return -EINVAL;
}
+ /* obtain data item */
+ data = ncr_data_item_get( &lists->data, op->data.ndata.input);
+ if (data == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
switch(sess->op) {
case NCR_OP_ENCRYPT:
- /* obtain data item */
- data = ncr_data_item_get( &lists->data, op->input);
- if (data == NULL) {
- err();
- ret = -EINVAL;
- goto fail;
- }
-
- odata = ncr_data_item_get( &lists->data, op->output);
+ odata = ncr_data_item_get( &lists->data, op->data.ndata.output);
if (odata == NULL) {
err();
ret = -EINVAL;
@@ -433,39 +508,16 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
goto fail;
}
- if (sess->algorithm->is_symmetric) {
- /* read key */
- ret = _cryptodev_cipher_encrypt(&sess->cipher, data->data,
- data->data_size, odata->data, data->data_size);
- if (ret < 0) {
- err();
- goto fail;
- }
- /* FIXME: handle ciphers that do not require that */
- odata->data_size = data->data_size;
- } else { /* public key */
- size_t new_size = odata->max_data_size;
- ret = ncr_pk_cipher_encrypt(&sess->pk, data->data, data->data_size,
- odata->data, &new_size);
-
- odata->data_size = new_size;
-
- if (ret < 0) {
- err();
- goto fail;
- }
- }
- break;
- case NCR_OP_DECRYPT:
- /* obtain data item */
- data = ncr_data_item_get( &lists->data, op->input);
- if (data == NULL) {
+ odata->data_size = odata->max_data_size;
+ ret = _ncr_session_encrypt(sess, &data->sg, 1, data->data_size,
+ &odata->sg, 1, &odata->data_size);
+ if (ret < 0) {
err();
- ret = -EINVAL;
goto fail;
}
-
- odata = ncr_data_item_get( &lists->data, op->output);
+ break;
+ case NCR_OP_DECRYPT:
+ odata = ncr_data_item_get( &lists->data, op->data.ndata.output);
if (odata == NULL) {
err();
ret = -EINVAL;
@@ -477,63 +529,26 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
ret = -EINVAL;
goto fail;
}
-
- /* read key */
- if (sess->algorithm->is_symmetric) {
- ret = _cryptodev_cipher_decrypt(&sess->cipher, data->data, data->data_size, odata->data, data->data_size);
- if (ret < 0) {
- err();
- goto fail;
- }
- /* FIXME: handle ciphers that do not require that */
- odata->data_size = data->data_size;
- } else { /* public key */
- size_t new_size = odata->max_data_size;
- ret = ncr_pk_cipher_decrypt(&sess->pk, data->data, data->data_size,
- odata->data, &new_size);
-
- odata->data_size = new_size;
-
- if (ret < 0) {
- err();
- goto fail;
- }
- }
-
- break;
-
- case NCR_OP_SIGN:
- /* obtain data item */
- data = ncr_data_item_get( &lists->data, op->input);
- if (data == NULL) {
- err();
- ret = -EINVAL;
- goto fail;
- }
- ret = _cryptodev_hash_update(&sess->hash, data->data, data->data_size);
+ new_size = odata->max_data_size;
+ ret = _ncr_session_decrypt(sess, &data->sg, 1, data->data_size,
+ &odata->sg, 1, &new_size);
if (ret < 0) {
err();
goto fail;
}
+ odata->data_size = new_size;
+
break;
+ case NCR_OP_SIGN:
case NCR_OP_VERIFY:
- /* obtain data item */
- data = ncr_data_item_get( &lists->data, op->input);
- if (data == NULL) {
- err();
- ret = -EINVAL;
- goto fail;
- }
-
- ret = _cryptodev_hash_update(&sess->hash, data->data, data->data_size);
+ ret = cryptodev_hash_update(&sess->hash, &data->sg, data->data_size);
if (ret < 0) {
err();
goto fail;
}
break;
-
default:
err();
ret = -EINVAL;
@@ -550,16 +565,117 @@ fail:
return ret;
}
-int ncr_session_update(struct ncr_lists* lists, void __user* arg)
+/* Only the output buffer is given as scatterlist */
+static int get_userbuf1(struct session_item_st* ses,
+ struct ncr_session_op_st* op, struct scatterlist **dst_sg, unsigned *dst_cnt)
{
- struct ncr_session_op_st op;
+ int pagecount = 0;
- if (unlikely(copy_from_user( &op, arg, sizeof(op)))) {
- err();
- return -EFAULT;
+ if (op->data.udata.output == NULL) {
+ return -EINVAL;
}
-
- return _ncr_session_update(lists, &op);
+
+ pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size);
+
+
+ ses->available_pages = pagecount;
+
+ if (pagecount > ses->array_size) {
+ while (ses->array_size < pagecount)
+ ses->array_size *= 2;
+
+ dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n",
+ __func__, ses->array_size);
+ ses->pages = krealloc(ses->pages, ses->array_size *
+ sizeof(struct page *), GFP_KERNEL);
+ ses->sg = krealloc(ses->sg, ses->array_size *
+ sizeof(struct scatterlist), GFP_KERNEL);
+
+ if (ses->sg == NULL || ses->pages == NULL) {
+ return -ENOMEM;
+ }
+ }
+
+ if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1,
+ pagecount, ses->pages, ses->sg)) {
+ dprintk(1, KERN_ERR, "failed to get user pages for data input\n");
+ return -EINVAL;
+ }
+ (*dst_sg) = ses->sg;
+ *dst_cnt = pagecount;
+
+ return 0;
+}
+
+/* make op->data.udata.input and op->data.udata.output available in scatterlists */
+static int get_userbuf2(struct session_item_st* ses,
+ struct ncr_session_op_st* op, struct scatterlist **src_sg,
+ unsigned *src_cnt, struct scatterlist **dst_sg, unsigned *dst_cnt)
+{
+ int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1;
+
+ if (op->data.udata.input == NULL) {
+ return -EINVAL;
+ }
+
+ src_pagecount = PAGECOUNT(op->data.udata.input, op->data.udata.input_size);
+
+ if (op->data.udata.input != op->data.udata.output) { /* non-in-situ transformation */
+ if (op->data.udata.output != NULL) {
+ dst_pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size);
+ write_src = 0;
+ } else {
+ dst_pagecount = 0;
+ }
+ }
+
+ ses->available_pages = pagecount = src_pagecount + dst_pagecount;
+
+ if (pagecount > ses->array_size) {
+ while (ses->array_size < pagecount)
+ ses->array_size *= 2;
+
+ dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n",
+ __func__, ses->array_size);
+ ses->pages = krealloc(ses->pages, ses->array_size *
+ sizeof(struct page *), GFP_KERNEL);
+ ses->sg = krealloc(ses->sg, ses->array_size *
+ sizeof(struct scatterlist), GFP_KERNEL);
+
+ if (ses->sg == NULL || ses->pages == NULL) {
+ return -ENOMEM;
+ }
+ }
+
+ if (__get_userbuf(op->data.udata.input, op->data.udata.input_size, write_src,
+ src_pagecount, ses->pages, ses->sg)) {
+ dprintk(1, KERN_ERR, "failed to get user pages for data input\n");
+ return -EINVAL;
+ }
+ (*src_sg) = ses->sg;
+ *src_cnt = src_pagecount;
+
+ if (dst_pagecount) {
+ *dst_cnt = dst_pagecount;
+ (*dst_sg) = ses->sg + src_pagecount;
+
+ if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, dst_pagecount,
+ ses->pages + src_pagecount, *dst_sg)) {
+ dprintk(1, KERN_ERR, "failed to get user pages for data output\n");
+ release_user_pages(ses->pages, src_pagecount);
+ return -EINVAL;
+ }
+ } else {
+ if (op->data.udata.output != NULL) {
+ *dst_cnt = src_pagecount;
+ (*dst_sg) = (*src_sg);
+ } else {
+ *dst_cnt = 0;
+ *dst_sg = NULL;
+ }
+ }
+
+ return 0;
}
static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc)
@@ -581,6 +697,15 @@ static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc)
return;
}
+static int try_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op)
+{
+ if (op->data.ndata.input != NCR_DATA_INVALID) {
+ return _ncr_session_update(lists, op);
+ }
+
+ return 0;
+}
+
static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* op)
{
int ret;
@@ -595,33 +720,260 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st*
return -EINVAL;
}
+ ret = try_session_update(lists, op);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
switch(sess->op) {
case NCR_OP_ENCRYPT:
case NCR_OP_DECRYPT:
- /* obtain data item */
- if (op->input != NCR_DATA_INVALID &&
- op->output != NCR_DATA_INVALID) {
- ret = _ncr_session_update(lists, op);
- if (ret < 0)
+ break;
+
+ case NCR_OP_VERIFY:
+ digest_size = sess->hash.digestsize;
+ if (digest_size == 0 || sizeof(digest) < digest_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ ret = cryptodev_hash_final(&sess->hash, digest);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ odata = ncr_data_item_get( &lists->data, op->data.ndata.output);
+ if (odata == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (sess->algorithm->is_hmac) {
+ if (digest_size != odata->data_size ||
+ memcmp(odata->data, digest, digest_size) != 0) {
+
+ op->err = NCR_VERIFICATION_FAILED;
+ } else {
+ op->err = NCR_SUCCESS;
+ }
+ } else {
+ /* PK signature */
+ ret = ncr_pk_cipher_verify(&sess->pk, &odata->sg, 1, odata->data_size,
+ digest, digest_size, &op->err);
+ if (ret < 0) {
+ err();
goto fail;
+ }
}
break;
- case NCR_OP_VERIFY:
- /* obtain data item */
- if (op->input != NCR_DATA_INVALID) {
- ret = _ncr_session_update(lists, op);
- if (ret < 0)
+ case NCR_OP_SIGN:
+ odata = ncr_data_item_get( &lists->data, op->data.ndata.output);
+ if (odata == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ digest_size = sess->hash.digestsize;
+ if (digest_size == 0 || odata->max_data_size < digest_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ ret = cryptodev_hash_final(&sess->hash, odata->data);
+ odata->data_size = digest_size;
+
+ cryptodev_hash_deinit(&sess->hash);
+
+ if (sess->algorithm->is_pk) {
+ /* PK signature */
+ size_t new_size = odata->max_data_size;
+ ret = ncr_pk_cipher_sign(&sess->pk, &odata->sg, 1, odata->data_size,
+ &odata->sg, 1, &new_size);
+ if (ret < 0) {
+ err();
goto fail;
+ }
+ odata->data_size = new_size;
+ }
+ break;
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ if (odata) _ncr_data_item_put(odata);
+ cryptodev_hash_deinit(&sess->hash);
+ if (sess->algorithm->is_symmetric) {
+ cryptodev_cipher_deinit(&sess->cipher);
+ } else {
+ ncr_pk_cipher_deinit(&sess->pk);
+ }
+
+ _ncr_sessions_item_put(sess);
+ _ncr_session_remove(&lists->sessions, op->ses);
+
+ return ret;
+}
+
+/* Called when userspace buffers are used */
+static int _ncr_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op)
+{
+ int ret;
+ struct session_item_st* sess;
+ struct scatterlist *isg;
+ struct scatterlist *osg;
+ unsigned osg_cnt=0, isg_cnt=0;
+ size_t isg_size, osg_size;
+
+ sess = ncr_sessions_item_get( &lists->sessions, op->ses);
+ if (sess == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ if (down_interruptible(&sess->mem_mutex)) {
+ err();
+ _ncr_sessions_item_put(sess);
+ return -ERESTARTSYS;
+ }
+
+ ret = get_userbuf2(sess, op, &isg, &isg_cnt, &osg, &osg_cnt);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ isg_size = op->data.udata.input_size;
+ osg_size = op->data.udata.output_size;
+
+ switch(sess->op) {
+ case NCR_OP_ENCRYPT:
+ if (osg == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
}
- odata = ncr_data_item_get( &lists->data, op->output);
- if (odata == NULL) {
+ ret = _ncr_session_encrypt(sess, isg, isg_cnt, isg_size,
+ osg, osg_cnt, &osg_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ op->data.udata.output_size = osg_size;
+
+ break;
+ case NCR_OP_DECRYPT:
+ if (osg == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (osg_size < isg_size) {
err();
ret = -EINVAL;
goto fail;
}
+ ret = _ncr_session_decrypt(sess, isg, isg_cnt, isg_size,
+ osg, osg_cnt, &osg_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ op->data.udata.output_size = osg_size;
+
+ break;
+
+ case NCR_OP_SIGN:
+ case NCR_OP_VERIFY:
+ ret = cryptodev_hash_update(&sess->hash, isg, isg_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ break;
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ if (sess->available_pages) {
+ release_user_pages(sess->pages, sess->available_pages);
+ sess->available_pages = 0;
+ }
+ up(&sess->mem_mutex);
+ _ncr_sessions_item_put(sess);
+
+ return ret;
+}
+
+static int try_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op)
+{
+ if (op->data.udata.input != NULL) {
+ return _ncr_session_direct_update(lists, op);
+ }
+
+ return 0;
+}
+
+static int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* op)
+{
+ int ret;
+ struct session_item_st* sess;
+ struct data_item_st* odata = NULL;
+ int digest_size;
+ uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE];
+ uint8_t vdigest[NCR_HASH_MAX_OUTPUT_SIZE];
+ struct scatterlist *osg;
+ unsigned osg_cnt=0;
+ size_t osg_size = 0;
+ size_t orig_osg_size;
+
+ sess = ncr_sessions_item_get( &lists->sessions, op->ses);
+ if (sess == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ ret = try_session_direct_update(lists, op);
+ if (ret < 0) {
+ err();
+ _ncr_sessions_item_put(sess);
+ return ret;
+ }
+
+ if (down_interruptible(&sess->mem_mutex)) {
+ err();
+ _ncr_sessions_item_put(sess);
+ return -ERESTARTSYS;
+ }
+
+ switch(sess->op) {
+ case NCR_OP_ENCRYPT:
+ case NCR_OP_DECRYPT:
+ break;
+ case NCR_OP_VERIFY:
+ ret = get_userbuf1(sess, op, &osg, &osg_cnt);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ orig_osg_size = osg_size = op->data.udata.output_size;
+
digest_size = sess->hash.digestsize;
if (digest_size == 0 || sizeof(digest) < digest_size) {
err();
@@ -633,11 +985,17 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st*
err();
goto fail;
}
-
if (sess->algorithm->is_hmac) {
+ ret = sg_copy_to_buffer(osg, osg_cnt, vdigest, digest_size);
+ if (ret != digest_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
if (digest_size != odata->data_size ||
- memcmp(odata->data, digest, digest_size) != 0) {
+ memcmp(vdigest, digest, digest_size) != 0) {
op->err = NCR_VERIFICATION_FAILED;
} else {
@@ -645,7 +1003,7 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st*
}
} else {
/* PK signature */
- ret = ncr_pk_cipher_verify(&sess->pk, odata->data, odata->data_size,
+ ret = ncr_pk_cipher_verify(&sess->pk, osg, osg_cnt, osg_size,
digest, digest_size, &op->err);
if (ret < 0) {
err();
@@ -655,40 +1013,46 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st*
break;
case NCR_OP_SIGN:
- /* obtain data item */
- if (op->input != NCR_DATA_INVALID) {
- ret = _ncr_session_update(lists, op);
- if (ret < 0)
- goto fail;
+ ret = get_userbuf1(sess, op, &osg, &osg_cnt);
+ if (ret < 0) {
+ err();
+ goto fail;
}
- odata = ncr_data_item_get( &lists->data, op->output);
- if (odata == NULL) {
+ orig_osg_size = osg_size = op->data.udata.output_size;
+
+ digest_size = sess->hash.digestsize;
+ if (digest_size == 0 || osg_size < digest_size) {
err();
ret = -EINVAL;
goto fail;
}
- digest_size = sess->hash.digestsize;
- if (digest_size == 0 || odata->max_data_size < digest_size) {
+ ret = cryptodev_hash_final(&sess->hash, digest);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = sg_copy_from_buffer(osg, osg_cnt, digest, digest_size);
+ if (ret != digest_size) {
err();
ret = -EINVAL;
goto fail;
}
- ret = cryptodev_hash_final(&sess->hash, odata->data);
- odata->data_size = digest_size;
+ osg_size = digest_size;
cryptodev_hash_deinit(&sess->hash);
if (sess->algorithm->is_pk) {
/* PK signature */
- size_t new_size = odata->max_data_size;
- ret = ncr_pk_cipher_sign(&sess->pk, odata->data, odata->data_size,
- odata->data, &new_size);
+
+ ret = ncr_pk_cipher_sign(&sess->pk, osg, osg_cnt, osg_size,
+ osg, osg_cnt, &orig_osg_size);
if (ret < 0) {
err();
goto fail;
}
- odata->data_size = new_size;
+ osg_size = orig_osg_size;
}
break;
default:
@@ -697,10 +1061,18 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st*
goto fail;
}
+ if (osg_size > 0)
+ op->data.udata.output_size = osg_size;
+
ret = 0;
fail:
- if (odata) _ncr_data_item_put(odata);
+ if (sess->available_pages) {
+ release_user_pages(sess->pages, sess->available_pages);
+ sess->available_pages = 0;
+ }
+ up(&sess->mem_mutex);
+
cryptodev_hash_deinit(&sess->hash);
if (sess->algorithm->is_symmetric) {
cryptodev_cipher_deinit(&sess->cipher);
@@ -714,6 +1086,37 @@ fail:
return ret;
}
+
+int ncr_session_update(struct ncr_lists* lists, void __user* arg)
+{
+ struct ncr_session_op_st op;
+ int ret;
+
+ if (unlikely(copy_from_user( &op, arg, sizeof(op)))) {
+ err();
+ return -EFAULT;
+ }
+
+ if (op.type == NCR_DIRECT_DATA)
+ ret = _ncr_session_direct_update(lists, &op);
+ else if (op.type == NCR_DATA)
+ ret = _ncr_session_update(lists, &op);
+ else
+ ret = -EINVAL;
+
+ if (unlikely(ret)) {
+ err();
+ return ret;
+ }
+
+ if (unlikely(copy_to_user(arg, &op, sizeof(op)))) {
+ err();
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
int ncr_session_final(struct ncr_lists* lists, void __user* arg)
{
struct ncr_session_op_st op;
@@ -724,7 +1127,14 @@ int ncr_session_final(struct ncr_lists* lists, void __user* arg)
return -EFAULT;
}
- ret = _ncr_session_final(lists, &op);
+ if (op.type == NCR_DATA) {
+ ret = _ncr_session_final(lists, &op);
+ } else if (op.type == NCR_DIRECT_DATA) {
+ ret = _ncr_session_direct_final(lists, &op);
+ } else {
+ ret = -EINVAL;
+ }
+
if (unlikely(ret)) {
err();
return ret;
@@ -754,7 +1164,13 @@ int ncr_session_once(struct ncr_lists* lists, void __user* arg)
}
kop.op.ses = kop.init.ses;
- ret = _ncr_session_final(lists, &kop.op);
+ if (kop.op.type == NCR_DIRECT_DATA)
+ ret = _ncr_session_direct_final(lists, &kop.op);
+ else if (kop.op.type == NCR_DATA)
+ ret = _ncr_session_final(lists, &kop.op);
+ else
+ ret = -EINVAL;
+
if (ret < 0) {
err();
return ret;
@@ -764,4 +1180,3 @@ int ncr_session_once(struct ncr_lists* lists, void __user* arg)
return -EFAULT;
return 0;
}
-
diff --git a/ncr.c b/ncr.c
index 7014a30..4cc7ef3 100644
--- a/ncr.c
+++ b/ncr.c
@@ -161,6 +161,7 @@ ncr_ioctl(struct ncr_lists* lst, struct file *filp,
return ncr_session_final(lst, arg);
case NCRIO_SESSION_ONCE:
return ncr_session_once(lst, arg);
+
case NCRIO_MASTER_KEY_SET:
return ncr_master_key_set(arg);
case NCRIO_KEY_GENERATE_PAIR:
diff --git a/ncr.h b/ncr.h
index d3f4813..d666628 100644
--- a/ncr.h
+++ b/ncr.h
@@ -276,14 +276,30 @@ typedef enum {
NCR_VERIFICATION_FAILED = -2,
} ncr_error_t;
+typedef enum {
+ NCR_DATA,
+ NCR_DIRECT_DATA,
+} ncr_data_type_t;
+
struct ncr_session_op_st {
/* input */
ncr_session_t ses;
- ncr_data_t input;
- ncr_data_t output; /* when verifying signature this is
- * the place of the signature.
- */
+ union {
+ struct {
+ ncr_data_t input;
+ ncr_data_t output; /* when verifying signature this is
+ * the place of the signature.
+ */
+ } ndata;
+ struct {
+ void* input;
+ size_t input_size;
+ void* output;
+ size_t output_size;
+ } udata;
+ } data;
+ ncr_data_type_t type;
/* output of verification */
ncr_error_t err;
@@ -296,7 +312,7 @@ struct ncr_session_once_op_st {
#define NCRIO_SESSION_INIT _IOR ('c', 300, struct ncr_session_st)
#define NCRIO_SESSION_UPDATE _IOWR ('c', 301, struct ncr_session_op_st)
-#define NCRIO_SESSION_FINAL _IOR ('c', 302, struct ncr_session_op_st)
+#define NCRIO_SESSION_FINAL _IOWR ('c', 302, struct ncr_session_op_st)
/* everything in one call */
#define NCRIO_SESSION_ONCE _IOWR ('c', 303, struct ncr_session_once_op_st)
diff --git a/ncr_int.h b/ncr_int.h
index fadb46e..cbfe58a 100644
--- a/ncr_int.h
+++ b/ncr_int.h
@@ -41,6 +41,14 @@ struct session_item_st {
struct ncr_pk_ctx pk;
struct hash_data hash;
+ struct scatterlist *sg;
+ struct page **pages;
+ unsigned array_size;
+ unsigned available_pages;
+ struct semaphore mem_mutex; /* down when the
+ * values above are changed.
+ */
+
struct key_item_st* key;
atomic_t refcnt;
@@ -53,6 +61,7 @@ struct data_item_st {
* I see no reason to allow concurrent writes (reads are
* not an issue).
*/
+ struct scatterlist sg; /* points to data */
uint8_t* data;
size_t data_size;