summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cryptodev_int.h11
-rw-r--r--cryptodev_main.c9
-rw-r--r--examples/ncr.c50
-rw-r--r--examples/pk.c11
-rw-r--r--examples/speed.c106
-rw-r--r--ncr-data.c225
-rw-r--r--ncr-key-storage.c21
-rw-r--r--ncr-key-wrap.c61
-rw-r--r--ncr-key.c55
-rw-r--r--ncr-pk.c209
-rw-r--r--ncr-pk.h21
-rw-r--r--ncr-sessions.c143
-rw-r--r--ncr.h13
-rw-r--r--ncr_int.h22
14 files changed, 770 insertions, 187 deletions
diff --git a/cryptodev_int.h b/cryptodev_int.h
index a0d3073..d12fd4f 100644
--- a/cryptodev_int.h
+++ b/cryptodev_int.h
@@ -24,6 +24,17 @@
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)
+
+
struct cipher_data
{
int init; /* 0 uninitialized */
diff --git a/cryptodev_main.c b/cryptodev_main.c
index 21642e6..2390f78 100644
--- a/cryptodev_main.c
+++ b/cryptodev_main.c
@@ -493,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]))
@@ -502,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/ncr.c b/examples/ncr.c
index 69e699a..d5d3e20 100644
--- a/examples/ncr.c
+++ b/examples/ncr.c
@@ -55,6 +55,7 @@ test_ncr_key(int cfd)
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
dinit.initial_data = data;
dinit.initial_data_size = sizeof(data);
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -96,6 +97,7 @@ test_ncr_key(int cfd)
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
dinit.initial_data = NULL;
dinit.initial_data_size = 0;
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -114,12 +116,10 @@ test_ncr_key(int cfd)
}
/* now read data */
- memset(data, 0, sizeof(data));
-
+ memset(&kdata, 0, sizeof(kdata));
kdata.desc = dinit.desc;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -129,7 +129,7 @@ test_ncr_key(int cfd)
if (memcmp(data, data_bak, sizeof(data))!=0) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
- fprintf(stderr, "data returned but differ!\n");
+ fprintf(stderr, "data returned but differ (%d, %d)!\n", (int)kdata.data_size, sizeof(data));
return 1;
}
@@ -179,7 +179,6 @@ test_ncr_key(int cfd)
kdata.desc = dinit.desc;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -237,7 +236,6 @@ test_ncr_key(int cfd)
kdata.desc = dinit.desc;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)==0) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -272,6 +270,7 @@ static int test_ncr_data(int cfd)
init.flags = NCR_DATA_FLAG_EXPORTABLE;
init.initial_data = data;
init.initial_data_size = sizeof(data);
+ init.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &init)) {
perror("ioctl(NCRIO_DATA_INIT)");
@@ -285,7 +284,6 @@ static int test_ncr_data(int cfd)
kdata.desc = init.desc;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) {
perror("ioctl(NCRIO_DATA_GET)");
@@ -305,7 +303,6 @@ static int test_ncr_data(int cfd)
kdata.desc = init.desc;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
perror("ioctl(NCRIO_DATA_SET)");
@@ -318,7 +315,6 @@ static int test_ncr_data(int cfd)
kdata.desc = init.desc;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) {
perror("ioctl(NCRIO_DATA_GET)");
@@ -345,6 +341,7 @@ static int test_ncr_data(int cfd)
init.flags = 0;
init.initial_data = data;
init.initial_data_size = sizeof(data);
+ init.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &init)) {
perror("ioctl(NCRIO_DATA_INIT)");
@@ -354,7 +351,6 @@ static int test_ncr_data(int cfd)
kdata.desc = init.desc;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)==0) {
fprintf(stderr, "Unexportable data were exported!?\n");
@@ -367,6 +363,7 @@ static int test_ncr_data(int cfd)
init.flags = 0;
init.initial_data = data;
init.initial_data_size = sizeof(data);
+ init.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &init)) {
//fprintf(stderr, "Reached maximum limit at: %d data items\n", i);
@@ -404,6 +401,7 @@ test_ncr_wrap_key(int cfd)
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
dinit.initial_data = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
dinit.initial_data_size = 16;
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -438,11 +436,10 @@ test_ncr_wrap_key(int cfd)
kdata.data = DKEY;
kdata.data_size = 16;
kdata.desc = dinit.desc;
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
- perror("ioctl(NCRIO_DATA_INIT)");
+ perror("ioctl(NCRIO_DATA_SET)");
return 1;
}
@@ -483,7 +480,6 @@ test_ncr_wrap_key(int cfd)
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -589,6 +585,7 @@ test_ncr_store_wrap_key(int cfd)
memset(&dinit, 0, sizeof(dinit));
dinit.max_object_size = DATA_SIZE;
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -603,11 +600,10 @@ test_ncr_store_wrap_key(int cfd)
kdata.data = DKEY;
kdata.data_size = 16;
kdata.desc = dd;
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
- perror("ioctl(NCRIO_DATA_INIT)");
+ perror("ioctl(NCRIO_DATA_SET)");
return 1;
}
@@ -750,6 +746,7 @@ test_ncr_aes(int cfd)
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
dinit.initial_data = NULL;
dinit.initial_data_size = 0;
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -788,11 +785,10 @@ test_ncr_aes(int cfd)
kdata.data = (void*)aes_vectors[i].key;
kdata.data_size = 16;
kdata.desc = dd;
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
- perror("ioctl(NCRIO_DATA_INIT)");
+ perror("ioctl(NCRIO_DATA_SET)");
return 1;
}
@@ -808,11 +804,10 @@ test_ncr_aes(int cfd)
kdata.data = (void*)aes_vectors[i].plaintext;
kdata.data_size = 16;
kdata.desc = dd;
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
- perror("ioctl(NCRIO_DATA_INIT)");
+ perror("ioctl(NCRIO_DATA_SET)");
return 1;
}
@@ -834,7 +829,6 @@ test_ncr_aes(int cfd)
kdata.desc = dd2;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -865,11 +859,10 @@ test_ncr_aes(int cfd)
kdata.data = (void*)aes_vectors[i].key;
kdata.data_size = 16;
kdata.desc = dd;
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
- perror("ioctl(NCRIO_DATA_INIT)");
+ perror("ioctl(NCRIO_DATA_SET)");
return 1;
}
@@ -886,11 +879,10 @@ test_ncr_aes(int cfd)
kdata.data = (void*)aes_vectors[i].ciphertext;
kdata.data_size = 16;
kdata.desc = dd;
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
- perror("ioctl(NCRIO_DATA_INIT)");
+ perror("ioctl(NCRIO_DATA_SET)");
return 1;
}
@@ -912,7 +904,6 @@ test_ncr_aes(int cfd)
kdata.desc = dd2;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -1041,6 +1032,7 @@ test_ncr_hash(int cfd)
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
dinit.initial_data = NULL;
dinit.initial_data_size = 0;
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -1081,11 +1073,10 @@ test_ncr_hash(int cfd)
kdata.data = (void*)hash_vectors[i].key;
kdata.data_size = hash_vectors[i].key_size;
kdata.desc = dd;
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
- perror("ioctl(NCRIO_DATA_INIT)");
+ perror("ioctl(NCRIO_DATA_SET)");
return 1;
}
@@ -1102,11 +1093,10 @@ test_ncr_hash(int cfd)
kdata.data = (void*)hash_vectors[i].plaintext;
kdata.data_size = hash_vectors[i].plaintext_size;
kdata.desc = dd;
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
- perror("ioctl(NCRIO_DATA_INIT)");
+ perror("ioctl(NCRIO_DATA_SET)");
return 1;
}
@@ -1126,10 +1116,10 @@ test_ncr_hash(int cfd)
}
/* verify */
+ memset(&kdata, 0, sizeof(kdata));
kdata.desc = dd2;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
diff --git a/examples/pk.c b/examples/pk.c
index 0765638..edae150 100644
--- a/examples/pk.c
+++ b/examples/pk.c
@@ -339,6 +339,7 @@ static int rsa_key_encrypt(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int oae
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
dinit.initial_data = data;
dinit.initial_data_size = RSA_ENCRYPT_SIZE;
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -351,6 +352,7 @@ static int rsa_key_encrypt(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int oae
memset(&dinit, 0, sizeof(dinit));
dinit.max_object_size = DATA_SIZE;
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -437,6 +439,7 @@ static int rsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
dinit.initial_data = data;
dinit.initial_data_size = sizeof(data);
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -449,6 +452,7 @@ static int rsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int
memset(&dinit, 0, sizeof(dinit));
dinit.max_object_size = DATA_SIZE;
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -529,6 +533,7 @@ static int dsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey)
memset(&dinit, 0, sizeof(dinit));
dinit.max_object_size = DATA_SIZE;
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -621,6 +626,7 @@ static int test_ncr_rsa(int cfd)
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
dinit.initial_data = NULL;
dinit.initial_data_size = 0;
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -644,7 +650,6 @@ static int test_ncr_rsa(int cfd)
kdata.desc = dinit.desc;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -676,7 +681,6 @@ static int test_ncr_rsa(int cfd)
kdata.desc = dinit.desc;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -765,6 +769,7 @@ static int test_ncr_dsa(int cfd)
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
dinit.initial_data = NULL;
dinit.initial_data_size = 0;
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -788,7 +793,6 @@ static int test_ncr_dsa(int cfd)
kdata.desc = dinit.desc;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -820,7 +824,6 @@ static int test_ncr_dsa(int cfd)
kdata.desc = dinit.desc;
kdata.data = data;
kdata.data_size = sizeof(data);
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
diff --git a/examples/speed.c b/examples/speed.c
index 99dc09e..25bf08b 100644
--- a/examples/speed.c
+++ b/examples/speed.c
@@ -152,10 +152,12 @@ int encrypt_data_ncr(int cfd, int algo, int chunksize)
buffer = malloc(chunksize);
memset(iv, 0x23, 32);
+ memset(&dinit, 0, sizeof(dinit));
dinit.max_object_size = chunksize;
dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
dinit.initial_data = buffer;
dinit.initial_data_size = chunksize;
+ dinit.type = NCR_DATA_KERNEL;
if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -177,7 +179,6 @@ int encrypt_data_ncr(int cfd, int algo, int chunksize)
kdata.data = buffer;
kdata.data_size = chunksize;
kdata.desc = dd;
- kdata.append_flag = 0;
if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -217,6 +218,97 @@ int encrypt_data_ncr(int cfd, int algo, int chunksize)
return 0;
}
+int encrypt_data_ncr_user(int cfd, int algo, int chunksize)
+{
+ char *buffer, iv[32];
+ static int val = 23;
+ struct timeval start, end;
+ double total = 0;
+ double secs, ddata, dspeed;
+ char metric[16];
+ ncr_key_t key;
+ struct ncr_key_generate_st kgen;
+ struct ncr_data_init_st dinit;
+ struct ncr_session_once_op_st nop;
+ ncr_data_t dd;
+
+ if (ioctl(cfd, NCRIO_KEY_INIT, &key)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_KEY_INIT)");
+ return 1;
+ }
+
+ kgen.desc = key;
+ kgen.params.algorithm = NCR_ALG_AES_CBC;
+ kgen.params.keyflags = NCR_KEY_FLAG_EXPORTABLE;
+ kgen.params.params.secret.bits = 128; /* 16 bytes */
+
+ if (ioctl(cfd, NCRIO_KEY_GENERATE, &kgen)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_KEY_IMPORT)");
+ return 1;
+ }
+
+
+ buffer = malloc(chunksize);
+ memset(iv, 0x23, 32);
+
+ /* now data are just a mirror of userspace data */
+ memset(&dinit, 0, sizeof(dinit));
+ dinit.flags = NCR_DATA_FLAG_EXPORTABLE;
+ dinit.initial_data = buffer;
+ dinit.initial_data_size = chunksize;
+ dinit.type = NCR_DATA_USER;
+
+ 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;
+
+ printf("\tEncrypting in chunks of %d bytes: ", chunksize);
+ fflush(stdout);
+
+ memset(buffer, val++, chunksize);
+
+ must_finish = 0;
+ alarm(5);
+
+ gettimeofday(&start, NULL);
+ do {
+ memset(&nop, 0, sizeof(nop));
+ nop.init.algorithm = algo;
+ nop.init.params.key = key;
+ nop.init.op = NCR_OP_ENCRYPT;
+ nop.op.data.cipher.plaintext = dd;
+ nop.op.data.cipher.ciphertext = dd;
+
+ if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_SESSION_ONCE)");
+ return 1;
+ }
+
+ total+=chunksize;
+ } while(must_finish==0);
+ gettimeofday(&end, NULL);
+
+ if (ioctl(cfd, NCRIO_DATA_DEINIT, &dd)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_DATA_INIT)");
+ return 1;
+ }
+
+ secs = udifftimeval(start, end)/ 1000000.0;
+
+ value2human(total, secs, &ddata, &dspeed, metric);
+ printf ("done. %.2f %s in %.2f secs: ", ddata, metric, secs);
+ printf ("%.2f %s/sec\n", dspeed, metric);
+
+ return 0;
+}
+
int main(void)
{
int fd, i, fdc = -1;
@@ -277,6 +369,18 @@ int main(void)
break;
}
+ fprintf(stderr, "\nTesting NCR-USER with NULL cipher: \n");
+ for (i = 256; i <= (64 * 1024); i *= 2) {
+ if (encrypt_data_ncr_user(fdc, NCR_ALG_NULL, i))
+ break;
+ }
+
+ fprintf(stderr, "\nTesting NCR-USER with AES-128-CBC cipher: \n");
+ for (i = 256; i <= (64 * 1024); i *= 2) {
+ if (encrypt_data_ncr_user(fdc, NCR_ALG_AES_CBC, i))
+ break;
+ }
+
close(fdc);
close(fd);
diff --git a/ncr-data.c b/ncr-data.c
index 8763234..d0ff5b9 100644
--- a/ncr-data.c
+++ b/ncr-data.c
@@ -101,11 +101,143 @@ void _ncr_data_item_put( struct data_item_st* item)
{
if (atomic_dec_and_test(&item->refcnt)) {
ncr_limits_remove(item->uid, item->pid, LIMIT_TYPE_DATA);
- kfree(item->data);
+ if (item->type == NCR_DATA_KERNEL)
+ kfree(item->data.kernel);
+ else if (item->type == NCR_DATA_USER)
+ ncr_data_item_put_sg(item); /* just in case */
kfree(item);
}
}
+int ncr_data_item_get_sg( struct data_item_st* item, struct scatterlist** sg,
+ unsigned int *sg_cnt, size_t *data_size, size_t* max_data_size, unsigned int data_flags, int write)
+{
+ if (item->type == NCR_DATA_KERNEL) {
+ item->flags = data_flags;
+
+ sg_init_one(item->_sg, item->data.kernel, item->max_data_size);
+
+ if (data_size) *data_size = item->data_size;
+ if (max_data_size) *max_data_size = item->max_data_size;
+ *sg_cnt = 1;
+ *sg = item->_sg;
+
+ } else if (item->type == NCR_DATA_USER) {
+ int ret;
+ size_t pagecount = PAGECOUNT(item->data.user.ptr, item->data_size);
+
+ if (atomic_add_unless(&item->data.user.pg_used, 1, 1) == 0) {
+ err();
+ return -EBUSY;
+ }
+
+ if (!(data_flags & NCR_DATA_FLAG_EXPORTABLE)) {
+ err();
+ return -EPERM;
+ }
+
+ if (pagecount > MAX_DATA_PAGES) {
+ err();
+ return -EOVERFLOW;
+ }
+
+ ret = __get_userbuf(item->data.user.ptr, item->data_size, write,
+ pagecount, item->data.user.pg, item->_sg);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ if (max_data_size) *max_data_size = item->data_size;
+ if (data_size) *data_size = item->data_size;
+ *sg = item->_sg;
+ *sg_cnt = item->data.user.pg_cnt = pagecount;
+ } else {
+ err();
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void ncr_data_item_put_sg( struct data_item_st* item)
+{
+ if (item->type == NCR_DATA_USER && atomic_read(&item->data.user.pg_used) > 0) {
+ if (item->data.user.pg_cnt > 0) {
+ release_user_pages(item->data.user.pg, item->data.user.pg_cnt);
+ item->data.user.pg_cnt = 0;
+ }
+ atomic_dec(&item->data.user.pg_used);
+ }
+
+ return;
+}
+
+int ncr_data_item_setd( struct data_item_st* item, const void* data, size_t data_size, unsigned int data_flags)
+{
+struct scatterlist* sg;
+size_t sg_max_size;
+unsigned int sg_cnt;
+int ret;
+
+ ret = ncr_data_item_get_sg(item, &sg, &sg_cnt, NULL, &sg_max_size, data_flags, 1);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ if (data_size > sg_max_size) {
+ err();
+ ret = -EOVERFLOW;
+ goto fail;
+ }
+
+ ret = sg_copy_from_buffer(sg, sg_cnt, (void*)data, data_size);
+ if (ret != data_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ item->data_size = data_size;
+
+ ret = 0;
+fail:
+ ncr_data_item_put_sg(item);
+ return ret;
+}
+
+int ncr_data_item_getd( struct data_item_st* item, void* data, size_t data_size, unsigned int data_flags)
+{
+struct scatterlist* sg;
+size_t sg_size;
+unsigned int sg_cnt;
+int ret;
+
+ ret = ncr_data_item_get_sg(item, &sg, &sg_cnt, &sg_size, NULL, data_flags, 0);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ if (data_size < sg_size) {
+ err();
+ ret = -EOVERFLOW;
+ goto fail;
+ }
+
+ ret = sg_copy_to_buffer(sg, sg_cnt, data, data_size);
+ if (ret != data_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+fail:
+ ncr_data_item_put_sg(item);
+ return ret;
+}
+
int ncr_data_init(struct list_sem_st* lst, void __user* arg)
{
struct ncr_data_init_st init;
@@ -139,22 +271,33 @@ int ncr_data_init(struct list_sem_st* lst, void __user* arg)
atomic_set(&data->refcnt, 1);
- data->data = data_alloc(init.max_object_size);
- if (data->data == NULL) {
- err();
- ret = -ENOMEM;
- goto err_data;
- }
- data->max_data_size = init.max_object_size;
+ data->type = init.type;
- if (init.initial_data != NULL) {
- if (unlikely(copy_from_user(data->data, init.initial_data,
- init.initial_data_size))) {
+ if (init.type == NCR_DATA_KERNEL) {
+ data->data.kernel = data_alloc(init.max_object_size);
+ if (data->data.kernel == NULL) {
err();
- _ncr_data_item_put(data);
- return -EFAULT;
+ ret = -ENOMEM;
+ goto err_data;
}
- data->data_size = init.initial_data_size;
+ data->max_data_size = init.max_object_size;
+
+ if (init.initial_data != NULL) {
+ if (unlikely(copy_from_user(data->data.kernel, init.initial_data,
+ init.initial_data_size))) {
+ err();
+ _ncr_data_item_put(data);
+ return -EFAULT;
+ }
+ data->data_size = init.initial_data_size;
+ }
+ } else if (init.type == NCR_DATA_USER) {
+ data->data.user.ptr = init.initial_data;
+ data->max_data_size = data->data_size = init.initial_data_size;
+ atomic_set(&data->data.user.pg_used, 0);
+ } else {
+ err();
+ goto err_data;
}
down(&lst->sem);
@@ -218,14 +361,19 @@ int ncr_data_get(struct list_sem_st* lst, void __user* arg)
err();
return -EFAULT;
}
-
+
data = ncr_data_item_get( lst, get.desc);
-
if (data == NULL) {
err();
return -EINVAL;
}
+ if (data->type == NCR_DATA_USER) {
+ err();
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
if (!(data->flags & NCR_DATA_FLAG_EXPORTABLE)) {
err();
ret = -EPERM;
@@ -233,10 +381,9 @@ int ncr_data_get(struct list_sem_st* lst, void __user* arg)
}
len = min(get.data_size, data->data_size);
-
/* update length */
get.data_size = len;
-
+
ret = copy_to_user(arg, &get, sizeof(get));
if (unlikely(ret)) {
err();
@@ -244,7 +391,7 @@ int ncr_data_get(struct list_sem_st* lst, void __user* arg)
}
if (ret == 0 && len > 0) {
- ret = copy_to_user(get.data, data->data, len);
+ ret = copy_to_user(get.data, data->data.kernel, len);
if (unlikely(ret)) {
err();
ret = -EFAULT;
@@ -269,12 +416,17 @@ int ncr_data_set(struct list_sem_st* lst, void __user* arg)
}
data = ncr_data_item_get( lst, get.desc);
-
if (data == NULL) {
err();
return -EINVAL;
}
+ if (data->type == NCR_DATA_USER) {
+ err();
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
if ((get.data_size > data->max_data_size) ||
(get.data == NULL && get.data_size != 0)) {
err();
@@ -282,37 +434,16 @@ int ncr_data_set(struct list_sem_st* lst, void __user* arg)
goto cleanup;
}
- if (!get.append_flag) {
- if (get.data != NULL) {
- if (unlikely(copy_from_user(data->data, get.data,
- get.data_size))) {
- err();
- ret = -EFAULT;
- goto cleanup;
- }
- }
- data->data_size = get.data_size;
- } else {
- size_t offset;
-
- offset = data->data_size;
- /* get.data_size <= data->max_data_size, which is limited in
- data_alloc(), so there is no integer overflow. */
- if (get.data_size+offset > data->max_data_size) {
+ if (get.data != NULL) {
+ if (unlikely(copy_from_user(data->data.kernel, get.data,
+ get.data_size))) {
err();
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
- if (get.data != NULL) {
- if (unlikely(copy_from_user(&data->data[offset],
- get.data, get.data_size))) {
- err();
- ret = -EFAULT;
- goto cleanup;
- }
- }
- data->data_size = offset + get.data_size;
}
+ data->data_size = get.data_size;
+
ret = 0;
cleanup:
diff --git a/ncr-key-storage.c b/ncr-key-storage.c
index 69e1c50..ca96ddb 100644
--- a/ncr-key-storage.c
+++ b/ncr-key-storage.c
@@ -39,6 +39,17 @@ struct packed_key {
uint32_t raw_size;
} __attribute__((__packed__));
+/**
+ * key_to_storage_data:
+ * @key: The key to pack
+ * @sdata: Output data
+ * @sdata_size: Output data size
+ *
+ * This function will pack the given key and return allocated data with the packed
+ * key.
+ *
+ * Returns: 0 or errno.
+ **/
int key_to_storage_data( uint8_t** sdata, size_t * sdata_size, const struct key_item_st *key)
{
struct packed_key * pkey;
@@ -82,6 +93,16 @@ fail:
return ret;
}
+/**
+ * key_from_storage_data:
+ * @key: The key to unpack on
+ * @data: input data
+ * @data_size: Input data size
+ *
+ * This function will unpack the given packed key and store it into the key item.
+ *
+ * Returns: 0 or errno.
+ **/
int key_from_storage_data(struct key_item_st* key, const void* data, size_t data_size)
{
const struct packed_key * pkey = data;
diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c
index f9c019d..d38edca 100644
--- a/ncr-key-wrap.c
+++ b/ncr-key-wrap.c
@@ -44,16 +44,24 @@ static void val64_xor( val64_t val, uint32_t x)
}
static int rfc3394_wrap(val64_t R[], unsigned int n, struct cipher_data* ctx,
- struct data_item_st* output, const uint8_t iv[8])
+ struct data_item_st* odata, const uint8_t iv[8])
{
val64_t A;
uint8_t aes_block[16];
-int i,j;
+int i,j, ret;
+uint8_t * output;
+size_t output_size = (n+1)*8;
- if (output->max_data_size < (n+1)*8) {
+ if (odata->max_data_size < output_size) {
err();
return -EINVAL;
}
+
+ output = kmalloc(output_size, GFP_KERNEL);
+ if (output == NULL) {
+ err();
+ return -ENOMEM;
+ }
memcpy(A, iv, 8);
@@ -72,12 +80,14 @@ int i,j;
memcpy(R[n-1], &aes_block[8], 8); /* R[n-1] = LSB64(AES(A^{t-1}|R_{1}^{t-1})) */
}
- memcpy(output->data, A, sizeof(A));
+ memcpy(output, A, sizeof(A));
for (j=0;j<n;j++)
- memcpy(&output->data[(j+1)*8], R[j], 8);
- output->data_size = (n+1)*8;
-
- return 0;
+ memcpy(&output[(j+1)*8], R[j], 8);
+
+ ret = ncr_data_item_setd( odata, output, output_size, odata->flags);
+ kfree(output);
+
+ return ret;
}
static int rfc3394_unwrap(uint8_t *wrapped_key, val64_t R[], unsigned int n, val64_t A, struct cipher_data *ctx)
@@ -177,7 +187,7 @@ static int _unwrap_aes_rfc5649(void* kdata, size_t *kdata_size, struct key_item_
struct data_item_st *wrapped, const void* _iv, size_t iv_size)
{
size_t wrapped_key_size, n;
-uint8_t *wrapped_key;
+uint8_t *wrapped_key = NULL;
int i, ret;
struct cipher_data ctx;
uint8_t iv[4];
@@ -196,8 +206,20 @@ size_t size;
return ret;
}
- wrapped_key = wrapped->data;
+ wrapped_key = kmalloc(wrapped->data_size, GFP_KERNEL);
+ if (wrapped_key == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
wrapped_key_size = wrapped->data_size;
+
+ ret = ncr_data_item_getd( wrapped, wrapped_key, wrapped->data_size, wrapped->flags);
+ if (ret < 0) {
+ err();
+ goto cleanup;
+ }
if (wrapped_key_size % 8 != 0) {
err();
@@ -256,6 +278,7 @@ size_t size;
ret = 0;
cleanup:
+ kfree(wrapped_key);
cryptodev_cipher_deinit(&ctx);
return ret;
@@ -362,7 +385,7 @@ static int unwrap_aes(struct key_item_st* output, struct key_item_st *kek,
struct data_item_st* wrapped, const void* iv, size_t iv_size)
{
size_t wrapped_key_size, n;
-uint8_t *wrapped_key;
+uint8_t *wrapped_key = NULL;
val64_t A;
int i, ret;
struct cipher_data ctx;
@@ -380,8 +403,20 @@ struct cipher_data ctx;
output->type = NCR_KEY_TYPE_SECRET;
- wrapped_key = wrapped->data;
+ wrapped_key = kmalloc(wrapped->data_size, GFP_KERNEL);
+ if (wrapped_key == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
wrapped_key_size = wrapped->data_size;
+
+ ret = ncr_data_item_getd( wrapped, wrapped_key, wrapped_key_size, wrapped->flags);
+ if (ret < 0) {
+ err();
+ goto cleanup;
+ }
if (wrapped_key_size % 8 != 0) {
err();
@@ -419,13 +454,13 @@ struct cipher_data ctx;
output->key.secret.size = n*8;
output->flags = NCR_KEY_FLAG_WRAPPABLE;
output->type = NCR_KEY_TYPE_SECRET;
-
}
ret = 0;
cleanup:
+ kfree(wrapped_key);
cryptodev_cipher_deinit(&ctx);
return ret;
diff --git a/ncr-key.c b/ncr-key.c
index 134831e..c6ce932 100644
--- a/ncr-key.c
+++ b/ncr-key.c
@@ -238,7 +238,9 @@ struct ncr_key_data_st data;
struct key_item_st* item = NULL;
struct data_item_st* ditem = NULL;
uint32_t size;
+uint32_t data_flags;
int ret;
+uint8_t* tmp = NULL;
if (unlikely(copy_from_user(&data, arg, sizeof(data)))) {
err();
@@ -258,7 +260,7 @@ int ret;
goto fail;
}
- ditem->flags = key_flags_to_data(item->flags);
+ data_flags = key_flags_to_data(item->flags);
switch (item->type) {
case NCR_KEY_TYPE_SECRET:
@@ -270,15 +272,27 @@ int ret;
/* found */
if (item->key.secret.size > 0) {
- memcpy(ditem->data, item->key.secret.data, item->key.secret.size);
+ ret = ncr_data_item_setd( ditem,
+ item->key.secret.data, item->key.secret.size,
+ data_flags);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
}
- ditem->data_size = item->key.secret.size;
break;
case NCR_KEY_TYPE_PUBLIC:
case NCR_KEY_TYPE_PRIVATE:
size = ditem->max_data_size;
- ret = ncr_pk_pack(item, ditem->data, &size);
+ tmp = kmalloc(size, GFP_KERNEL);
+ if (tmp == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ ret = ncr_pk_pack(item, tmp, &size);
ditem->data_size = size;
if (ret < 0) {
@@ -286,6 +300,14 @@ int ret;
goto fail;
}
+ ret = ncr_data_item_setd( ditem, tmp, size, data_flags);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ kfree(tmp);
+
break;
default:
err();
@@ -299,6 +321,7 @@ int ret;
return 0;
fail:
+ kfree(tmp);
if (item)
_ncr_key_item_put(item);
if (ditem)
@@ -316,6 +339,7 @@ int ncr_key_import(struct list_sem_st* data_lst,
struct ncr_key_data_st data;
struct key_item_st* item = NULL;
struct data_item_st* ditem = NULL;
+uint8_t *tmp = NULL;
int ret;
if (unlikely(copy_from_user(&data, arg, sizeof(data)))) {
@@ -357,23 +381,39 @@ int ret;
switch(item->type) {
case NCR_KEY_TYPE_SECRET:
-
if (ditem->data_size > NCR_CIPHER_MAX_KEY_LEN) {
err();
ret = -EINVAL;
goto fail;
}
- memcpy(item->key.secret.data, ditem->data, ditem->data_size);
+ ret = ncr_data_item_getd(ditem, item->key.secret.data, ditem->data_size, item->flags);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
item->key.secret.size = ditem->data_size;
break;
case NCR_KEY_TYPE_PRIVATE:
case NCR_KEY_TYPE_PUBLIC:
- ret = ncr_pk_unpack( item, ditem->data, ditem->data_size);
+ tmp = kmalloc(ditem->data_size, GFP_KERNEL);
+ if (tmp == NULL) {
+ err();
+ return -ENOMEM;
+ }
+
+ ret = ncr_data_item_getd(ditem, tmp, ditem->data_size, item->flags);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = ncr_pk_unpack( item, tmp, ditem->data_size);
if (ret < 0) {
err();
goto fail;
}
+ kfree(tmp);
break;
default:
@@ -388,6 +428,7 @@ int ret;
return 0;
fail:
+ kfree(tmp);
if (item)
_ncr_key_item_put(item);
if (ditem)
diff --git a/ncr-pk.c b/ncr-pk.c
index 2bc5a35..6b304bb 100644
--- a/ncr-pk.c
+++ b/ncr-pk.c
@@ -354,121 +354,237 @@ int ncr_pk_cipher_init(ncr_algorithm_t 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) {
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;
+
+ ret = sg_copy_from_buffer(osg, osg_cnt, output, osize);
+ if (ret != osize) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
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) {
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) {
case NCR_ALG_RSA:
- 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) {
case NCR_ALG_RSA:
- 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)
@@ -478,11 +594,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)
@@ -493,8 +610,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 1180017..aebc430 100644
--- a/ncr-pk.h
+++ b/ncr-pk.h
@@ -34,15 +34,20 @@ int ncr_pk_cipher_init(ncr_algorithm_t algo,
struct ncr_pk_ctx* ctx, struct ncr_key_params_st* params,
struct key_item_st *key);
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 d8a9b4f..dc03367 100644
--- a/ncr-sessions.c
+++ b/ncr-sessions.c
@@ -487,6 +487,10 @@ 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;
+ struct scatterlist *osg;
+ struct scatterlist *isg;
+ size_t osg_size, isg_size;
+ unsigned int osg_cnt, isg_cnt;
sess = ncr_sessions_item_get( &lists->sessions, op->ses);
if (sess == NULL) {
@@ -511,6 +515,25 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
goto fail;
}
+ /* output data will have the same status as input data */
+ ret = ncr_data_item_get_sg(odata, &osg, &osg_cnt, NULL, &osg_size, data->flags, 1);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ if (odata != data) {
+ ret = ncr_data_item_get_sg(data, &isg, &isg_cnt, &isg_size, NULL, data->flags, 0);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ } else {
+ isg = osg;
+ isg_cnt = osg_cnt;
+ isg_size = osg_size;
+ }
+
if (odata->max_data_size < data->data_size) {
err();
ret = -EINVAL;
@@ -519,18 +542,18 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
if (algo_is_symmetric(sess->algorithm)) {
/* read key */
- ret = _cryptodev_cipher_encrypt(&sess->cipher, data->data,
- data->data_size, odata->data, data->data_size);
+ ret = cryptodev_cipher_encrypt(&sess->cipher, isg, osg, isg_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);
+ size_t new_size = osg_size;
+ ret = ncr_pk_cipher_encrypt(&sess->pk, isg, isg_cnt, isg_size,
+ osg, osg_cnt, &new_size);
odata->data_size = new_size;
@@ -556,6 +579,24 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
goto fail;
}
+ ret = ncr_data_item_get_sg(odata, &osg, &osg_cnt, NULL, &osg_size, data->flags, 1);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ if (odata != data) {
+ ret = ncr_data_item_get_sg(data, &isg, &isg_cnt, NULL, &isg_size, data->flags, 0);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ } else {
+ isg = osg;
+ isg_cnt = osg_cnt;
+ isg_size = osg_size;
+ }
+
if (odata->max_data_size < data->data_size) {
err();
ret = -EINVAL;
@@ -564,7 +605,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
/* read key */
if (algo_is_symmetric(sess->algorithm)) {
- ret = _cryptodev_cipher_decrypt(&sess->cipher, data->data, data->data_size, odata->data, data->data_size);
+ ret = cryptodev_cipher_decrypt(&sess->cipher, isg, osg, isg_size);
if (ret < 0) {
err();
goto fail;
@@ -572,9 +613,9 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
/* 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);
+ size_t new_size = osg_size;
+ ret = ncr_pk_cipher_decrypt(&sess->pk, isg, isg_cnt, isg_size,
+ osg, osg_cnt, &new_size);
odata->data_size = new_size;
@@ -596,7 +637,13 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
goto fail;
}
- ret = _cryptodev_hash_update(&sess->hash, data->data, data->data_size);
+ ret = ncr_data_item_get_sg(data, &isg, &isg_cnt, &isg_size, NULL, data->flags, 0);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = cryptodev_hash_update(&sess->hash, isg, isg_size);
if (ret < 0) {
err();
goto fail;
@@ -612,7 +659,13 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
goto fail;
}
- ret = _cryptodev_hash_update(&sess->hash, data->data, data->data_size);
+ ret = ncr_data_item_get_sg(data, &isg, &isg_cnt, &isg_size, NULL, data->flags, 0);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = cryptodev_hash_update(&sess->hash, isg, isg_size);
if (ret < 0) {
err();
goto fail;
@@ -628,8 +681,14 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
ret = 0;
fail:
- if (odata) _ncr_data_item_put(odata);
- if (data) _ncr_data_item_put(data);
+ if (odata) {
+ ncr_data_item_put_sg(odata);
+ _ncr_data_item_put(odata);
+ }
+ if (data) {
+ ncr_data_item_put_sg(data);
+ _ncr_data_item_put(data);
+ }
_ncr_sessions_item_put(sess);
return ret;
@@ -673,6 +732,9 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st*
struct data_item_st* odata = NULL;
int digest_size;
uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE];
+ struct scatterlist *osg;
+ size_t osg_size;
+ unsigned int osg_cnt;
sess = ncr_sessions_item_get( &lists->sessions, op->ses);
if (sess == NULL) {
@@ -718,19 +780,32 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st*
err();
goto fail;
}
-
if (algo_is_hmac(sess->algorithm)) {
+ uint8_t vdigest[digest_size];
+
+ ret = ncr_data_item_getd( odata, vdigest, sizeof(vdigest), odata->flags);
+ if (ret < 0) {
+ err();
+ 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 {
op->err = NCR_SUCCESS;
}
} else {
/* PK signature */
- ret = ncr_pk_cipher_verify(&sess->pk, odata->data, odata->data_size,
+ ret = ncr_data_item_get_sg(odata, &osg, &osg_cnt, NULL, &osg_size, odata->flags, 0);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = ncr_pk_cipher_verify(&sess->pk, osg, osg_cnt, osg_size,
digest, digest_size, &op->err);
if (ret < 0) {
err();
@@ -760,22 +835,41 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st*
ret = -EINVAL;
goto fail;
}
- ret = cryptodev_hash_final(&sess->hash, odata->data);
- odata->data_size = digest_size;
+ ret = cryptodev_hash_final(&sess->hash, digest);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ ret = ncr_data_item_setd( odata, digest, digest_size, odata->flags);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
cryptodev_hash_deinit(&sess->hash);
if (sess->op != NCR_OP_DIGEST && !algo_is_hmac(sess->algorithm)) {
+ size_t new_size;
+
+ ret = ncr_data_item_get_sg(odata, &osg, &osg_cnt, NULL, &osg_size, odata->flags, 1);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ new_size = osg_size;
+
/* 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, digest_size,
+ osg, osg_cnt, &new_size);
if (ret < 0) {
err();
goto fail;
}
odata->data_size = new_size;
}
+
break;
default:
err();
@@ -786,7 +880,10 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st*
ret = 0;
fail:
- if (odata) _ncr_data_item_put(odata);
+ if (odata) {
+ ncr_data_item_put_sg(odata);
+ _ncr_data_item_put(odata);
+ }
cryptodev_hash_deinit(&sess->hash);
if (algo_is_symmetric(sess->algorithm)) {
cryptodev_cipher_deinit(&sess->cipher);
diff --git a/ncr.h b/ncr.h
index 184ef56..844cddb 100644
--- a/ncr.h
+++ b/ncr.h
@@ -63,8 +63,17 @@ typedef enum {
typedef int ncr_data_t;
#define NCR_DATA_INVALID (ncr_data_t)(0)
+typedef enum {
+ NCR_DATA_KERNEL,
+ NCR_DATA_USER,
+} ncr_data_type_t;
+
+/* When initializing a data_t we can initialize it as a kernel data object
+ * or as an object that points to userspace data.
+ */
struct ncr_data_init_st {
ncr_data_t desc;
+ ncr_data_type_t type;
size_t max_object_size;
unsigned int flags;
void __user *initial_data; /* can be null */
@@ -75,7 +84,6 @@ struct ncr_data_st {
ncr_data_t desc;
void __user* data;
size_t data_size; /* rw in get */
- unsigned int append_flag; /* only when used with NCRIO_DATA_SET */
};
#define NCRIO_DATA_INIT _IOWR('c', 200, struct ncr_data_init_st)
@@ -183,6 +191,7 @@ struct ncr_key_info_st {
struct ncr_key_data_st {
ncr_key_t key;
ncr_data_t data;
+
/* in case of import this will be used as key id */
uint8_t key_id[MAX_KEY_ID_SIZE];
size_t key_id_size;
@@ -207,7 +216,7 @@ struct ncr_key_data_st {
#define NCRIO_KEY_DEINIT _IOR ('c', 215, ncr_key_t)
-/* FIXME key wrap ioctls
+/* Key wrap ioctls
*/
struct ncr_key_wrap_st {
ncr_wrap_algorithm_t algorithm;
diff --git a/ncr_int.h b/ncr_int.h
index 111f23c..185b3a3 100644
--- a/ncr_int.h
+++ b/ncr_int.h
@@ -30,6 +30,7 @@ struct session_item_st {
ncr_session_t desc;
};
+#define MAX_DATA_PAGES 64
struct data_item_st {
struct list_head list;
/* This object is not protected from concurrent access.
@@ -37,9 +38,21 @@ struct data_item_st {
* not an issue).
*/
- uint8_t* data;
size_t data_size;
size_t max_data_size;
+
+ struct scatterlist _sg[MAX_DATA_PAGES]; /* do not access directly */
+ union {
+ uint8_t* kernel;
+ struct {
+ uint8_t* __user ptr;
+ struct page *pg[MAX_DATA_PAGES];
+ size_t pg_cnt;
+ atomic_t pg_used;
+ } user;
+ } data;
+ ncr_data_type_t type;
+
unsigned int flags;
atomic_t refcnt;
@@ -111,6 +124,13 @@ void ncr_data_list_deinit(struct list_sem_st*);
struct data_item_st* ncr_data_item_get( struct list_sem_st* lst, ncr_data_t desc);
void _ncr_data_item_put( struct data_item_st* item);
+int ncr_data_item_get_sg( struct data_item_st* item, struct scatterlist** sg,
+ unsigned int *sg_cnt, size_t *data_size, size_t* max_data_size, unsigned int data_flags, int write);
+void ncr_data_item_put_sg( struct data_item_st* item);
+int ncr_data_item_setd( struct data_item_st* item, const void* data, size_t data_size, unsigned int data_flags);
+int ncr_data_item_getd( struct data_item_st* item, void* data, size_t data_size, unsigned int data_flags);
+
+
int ncr_key_init(struct list_sem_st*, void __user* arg);
int ncr_key_deinit(struct list_sem_st*, void __user* arg);
int ncr_key_export(struct list_sem_st* data_lst,