diff options
-rw-r--r-- | cryptodev_int.h | 11 | ||||
-rw-r--r-- | cryptodev_main.c | 9 | ||||
-rw-r--r-- | examples/ncr.c | 50 | ||||
-rw-r--r-- | examples/pk.c | 11 | ||||
-rw-r--r-- | examples/speed.c | 106 | ||||
-rw-r--r-- | ncr-data.c | 225 | ||||
-rw-r--r-- | ncr-key-storage.c | 21 | ||||
-rw-r--r-- | ncr-key-wrap.c | 61 | ||||
-rw-r--r-- | ncr-key.c | 55 | ||||
-rw-r--r-- | ncr-pk.c | 209 | ||||
-rw-r--r-- | ncr-pk.h | 21 | ||||
-rw-r--r-- | ncr-sessions.c | 143 | ||||
-rw-r--r-- | ncr.h | 13 | ||||
-rw-r--r-- | ncr_int.h | 22 |
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); @@ -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; @@ -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) @@ -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; } @@ -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); @@ -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; @@ -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, |