diff options
-rw-r--r-- | examples/ncr.c | 33 | ||||
-rw-r--r-- | ncr-key-wrap.c | 171 | ||||
-rw-r--r-- | ncr.c | 8 | ||||
-rw-r--r-- | ncr.h | 14 | ||||
-rw-r--r-- | ncr_int.h | 8 |
5 files changed, 141 insertions, 93 deletions
diff --git a/examples/ncr.c b/examples/ncr.c index bd5779c..be3dec9 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -383,7 +383,7 @@ test_ncr_wrap_key(int cfd) struct ncr_data_st kdata; struct ncr_key_wrap_st kwrap; uint8_t data[WRAPPED_KEY_DATA_SIZE]; - + int data_size; fprintf(stdout, "Tests on Keys:\n"); @@ -465,29 +465,23 @@ test_ncr_wrap_key(int cfd) kwrap.algorithm = NCR_WALG_AES_RFC3394; kwrap.keytowrap = key2; kwrap.key = key; - kwrap.data = kdata.desc; + kwrap.io = data; + kwrap.io_size = sizeof(data); if (ioctl(cfd, NCRIO_KEY_WRAP, &kwrap)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_WRAP)"); return 1; } + + data_size = kwrap.io_size; - kdata.data = data; - kdata.data_size = sizeof(data); - - if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) { - fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_DATA_GET)"); - return 1; - } - - if (kdata.data_size != 24 || memcmp(kdata.data, + if (kwrap.io_size != 24 || memcmp(data, "\x1F\xA6\x8B\x0A\x81\x12\xB4\x47\xAE\xF3\x4B\xD8\xFB\x5A\x7B\x82\x9D\x3E\x86\x23\x71\xD2\xCF\xE5", 24) != 0) { fprintf(stderr, "Wrapped data do not match.\n"); - fprintf(stderr, "Data[%d]: ",(int) kdata.data_size); - for(i=0;i<kdata.data_size;i++) + fprintf(stderr, "Data[%d]: ",(int) kwrap.io_size); + for(i=0;i<kwrap.io_size;i++) fprintf(stderr, "%.2x:", data[i]); fprintf(stderr, "\n"); return 1; @@ -514,7 +508,8 @@ test_ncr_wrap_key(int cfd) kwrap.algorithm = NCR_WALG_AES_RFC3394; kwrap.keytowrap = key2; kwrap.key = key; - kwrap.data = kdata.desc; + kwrap.io = data; + kwrap.io_size = data_size; if (ioctl(cfd, NCRIO_KEY_UNWRAP, &kwrap)) { perror("ioctl(NCRIO_KEY_UNWRAP)"); @@ -568,6 +563,7 @@ test_ncr_store_wrap_key(int cfd) struct ncr_key_storage_wrap_st kwrap; uint8_t data[DATA_SIZE]; int dd; + int data_size; fprintf(stdout, "Tests on Key storage:\n"); @@ -626,7 +622,8 @@ test_ncr_store_wrap_key(int cfd) /* now try wrapping key2 using key */ memset(&kwrap, 0, sizeof(kwrap)); kwrap.keytowrap = key2; - kwrap.data = dd; + kwrap.io = data; + kwrap.io_size = sizeof(data); if (ioctl(cfd, NCRIO_KEY_STORAGE_WRAP, &kwrap)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); @@ -635,6 +632,7 @@ test_ncr_store_wrap_key(int cfd) } /* test unwrapping */ + data_size = kwrap.io_size; fprintf(stdout, "\tKey Storage Unwrap test...\n"); /* reset key2 */ @@ -652,7 +650,8 @@ test_ncr_store_wrap_key(int cfd) memset(&kwrap, 0, sizeof(kwrap)); kwrap.keytowrap = key2; - kwrap.data = dd; + kwrap.io = data; + kwrap.io_size = data_size; if (ioctl(cfd, NCRIO_KEY_STORAGE_UNWRAP, &kwrap)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 939c136..149a8ff 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -44,13 +44,13 @@ 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]) + uint8_t* output, size_t *output_size, const uint8_t iv[8]) { val64_t A; uint8_t aes_block[16]; int i,j; - if (output->max_data_size < (n+1)*8) { + if (*output_size < (n+1)*8) { err(); return -EINVAL; } @@ -72,15 +72,15 @@ 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; + memcpy(&output[(j+1)*8], R[j], 8); + *output_size = (n+1)*8; return 0; } -static int rfc3394_unwrap(uint8_t *wrapped_key, val64_t R[], unsigned int n, val64_t A, struct cipher_data *ctx) +static int rfc3394_unwrap(const uint8_t *wrapped_key, val64_t R[], unsigned int n, val64_t A, struct cipher_data *ctx) { int i, j; uint8_t aes_block[16]; @@ -111,7 +111,7 @@ static int rfc3394_unwrap(uint8_t *wrapped_key, val64_t R[], unsigned int n, val #define RFC5649_IV "\xA6\x59\x59\xA6" static int _wrap_aes_rfc5649(void* kdata, size_t kdata_size, struct key_item_st* kek, - struct data_item_st* output, const void* _iv, size_t iv_size) + void* output, size_t* output_size, const void* _iv, size_t iv_size) { size_t n; int i, ret; @@ -157,7 +157,7 @@ uint8_t iv[8]; for (;i<n*8;i++) { R[i/8][i%8] = 0; } - ret = rfc3394_wrap( R, n, &ctx, output, iv); + ret = rfc3394_wrap( R, n, &ctx, output, output_size, iv); kfree(R); if (ret < 0) { err(); @@ -174,10 +174,9 @@ cleanup: } static int _unwrap_aes_rfc5649(void* kdata, size_t *kdata_size, struct key_item_st* kek, - struct data_item_st *wrapped, const void* _iv, size_t iv_size) + const void *wrapped_key, size_t wrapped_key_size, const void* _iv, size_t iv_size) { -size_t wrapped_key_size, n; -uint8_t *wrapped_key; +size_t n; int i, ret; struct cipher_data ctx; uint8_t iv[4]; @@ -196,9 +195,6 @@ size_t size; return ret; } - wrapped_key = wrapped->data; - wrapped_key_size = wrapped->data_size; - if (wrapped_key_size % 8 != 0) { err(); ret = -EINVAL; @@ -263,7 +259,7 @@ cleanup: static int wrap_aes_rfc5649(struct key_item_st* tobewrapped, struct key_item_st *kek, - struct data_item_st* output, const void* iv, size_t iv_size) + void* output, size_t* output_size, const void* iv, size_t iv_size) { if (tobewrapped->type != NCR_KEY_TYPE_SECRET) { err(); @@ -271,23 +267,24 @@ static int wrap_aes_rfc5649(struct key_item_st* tobewrapped, struct key_item_st } return _wrap_aes_rfc5649(tobewrapped->key.secret.data, tobewrapped->key.secret.size, - kek, output, iv, iv_size); + kek, output, output_size, iv, iv_size); } static int unwrap_aes_rfc5649(struct key_item_st* output, struct key_item_st *kek, - struct data_item_st* wrapped, const void* iv, size_t iv_size) + void* wrapped, size_t wrapped_size, const void* iv, size_t iv_size) { output->type = NCR_KEY_TYPE_SECRET; - return _unwrap_aes_rfc5649(output->key.secret.data, &output->key.secret.size, kek, wrapped, iv, iv_size); + return _unwrap_aes_rfc5649(output->key.secret.data, &output->key.secret.size, kek, + wrapped, wrapped_size, iv, iv_size); } /* Wraps using the RFC3394 way. */ static int wrap_aes(struct key_item_st* tobewrapped, struct key_item_st *kek, - struct data_item_st* output, const void* iv, size_t iv_size) + void* output, size_t *output_size, const void* iv, size_t iv_size) { size_t key_size, n; uint8_t *raw_key; @@ -330,7 +327,7 @@ struct cipher_data ctx; memcpy(R[i], &raw_key[i*8], 8); } - ret = rfc3394_wrap( R, n, &ctx, output, iv); + ret = rfc3394_wrap( R, n, &ctx, output, output_size, iv); if (ret < 0) { err(); goto cleanup; @@ -359,10 +356,9 @@ void print_val64(char* str, val64_t val) #endif 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) + void* wrapped_key, size_t wrapped_key_size, const void* iv, size_t iv_size) { -size_t wrapped_key_size, n; -uint8_t *wrapped_key; +size_t n; val64_t A; int i, ret; struct cipher_data ctx; @@ -380,9 +376,6 @@ struct cipher_data ctx; output->type = NCR_KEY_TYPE_SECRET; - wrapped_key = wrapped->data; - wrapped_key_size = wrapped->data_size; - if (wrapped_key_size % 8 != 0) { err(); ret = -EINVAL; @@ -431,12 +424,13 @@ cleanup: return ret; } -int ncr_key_wrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg) +int ncr_key_wrap(struct list_sem_st* key_lst, void __user* arg) { struct ncr_key_wrap_st wrap; struct key_item_st* wkey = NULL; struct key_item_st* key = NULL; -struct data_item_st * data = NULL; +void* data = NULL; +size_t data_size; int ret; if (unlikely(copy_from_user(&wrap, arg, sizeof(wrap)))) { @@ -462,31 +456,50 @@ int ret; goto fail; } - data = ncr_data_item_get(data_lst, wrap.data); + data_size = wrap.io_size; + data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); - ret = -EINVAL; + ret = -ENOMEM; goto fail; } - - data->flags = key_flags_to_data(wkey->flags) | NCR_DATA_FLAG_EXPORTABLE; - + switch(wrap.algorithm) { case NCR_WALG_AES_RFC3394: - ret = wrap_aes(wkey, key, data, wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); + ret = wrap_aes(wkey, key, data, &data_size, + wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); break; case NCR_WALG_AES_RFC5649: - ret = wrap_aes_rfc5649(wkey, key, data, wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); + ret = wrap_aes_rfc5649(wkey, key, data, &data_size, + wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); break; default: err(); ret = -EINVAL; } + + if (ret < 0) { + err(); + goto fail; + } + + ret = copy_to_user(wrap.io, data, data_size); + if (unlikely(ret)) { + ret = -EFAULT; + goto fail; + } + + wrap.io_size = data_size; + + ret = copy_to_user(arg, &wrap, sizeof(wrap)); + if (unlikely(ret)) { + ret = -EFAULT; + } fail: if (wkey != NULL) _ncr_key_item_put(wkey); if (key != NULL) _ncr_key_item_put(key); - if (data != NULL) _ncr_data_item_put(data); + kfree(data); return ret; } @@ -494,12 +507,13 @@ fail: /* Unwraps keys. All keys unwrapped are not accessible by * userspace. */ -int ncr_key_unwrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg) +int ncr_key_unwrap(struct list_sem_st* key_lst, void __user* arg) { struct ncr_key_wrap_st wrap; struct key_item_st* wkey = NULL; struct key_item_st* key = NULL; -struct data_item_st * data = NULL; +void* data = NULL; +size_t data_size; int ret; if (unlikely(copy_from_user(&wrap, arg, sizeof(wrap)))) { @@ -519,40 +533,48 @@ int ret; goto fail; } - data = ncr_data_item_get(data_lst, wrap.data); + data_size = wrap.io_size; + data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); - ret = -EINVAL; + ret = -ENOMEM; goto fail; } - wkey->flags = data_flags_to_key(data->flags) | NCR_KEY_FLAG_WRAPPABLE; + if (unlikely(copy_from_user(data, wrap.io, data_size))) { + err(); + ret = -EFAULT; + goto fail; + } switch(wrap.algorithm) { case NCR_WALG_AES_RFC3394: - ret = unwrap_aes(wkey, key, data, wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); + ret = unwrap_aes(wkey, key, data, data_size, + wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); break; case NCR_WALG_AES_RFC5649: - ret = unwrap_aes_rfc5649(wkey, key, data, wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); + ret = unwrap_aes_rfc5649(wkey, key, data, data_size, + wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); break; default: err(); ret = -EINVAL; } - + fail: if (wkey != NULL) _ncr_key_item_put(wkey); if (key != NULL) _ncr_key_item_put(key); - if (data != NULL) _ncr_data_item_put(data); + if (data != NULL) kfree(data); return ret; } -int ncr_key_storage_wrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg) +int ncr_key_storage_wrap(struct list_sem_st* key_lst, void __user* arg) { struct ncr_key_storage_wrap_st wrap; struct key_item_st* wkey = NULL; -struct data_item_st * data = NULL; +void* data = NULL; +size_t data_size; uint8_t * sdata = NULL; size_t sdata_size = 0; int ret; @@ -579,26 +601,42 @@ int ret; goto fail; } - data = ncr_data_item_get(data_lst, wrap.data); + data_size = wrap.io_size; + data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); - ret = -EINVAL; + ret = -ENOMEM; goto fail; } - - data->flags = key_flags_to_data(wkey->flags) | NCR_DATA_FLAG_EXPORTABLE; - + ret = key_to_storage_data(&sdata, &sdata_size, wkey); if (ret < 0) { err(); goto fail; } - ret = _wrap_aes_rfc5649(sdata, sdata_size, &master_key, data, NULL, 0); + ret = _wrap_aes_rfc5649(sdata, sdata_size, &master_key, data, &data_size, NULL, 0); + if (ret < 0) { + err(); + goto fail; + } + + ret = copy_to_user(wrap.io, data, data_size); + if (unlikely(ret)) { + ret = -EFAULT; + goto fail; + } + + wrap.io_size = data_size; + + ret = copy_to_user(arg, &wrap, sizeof(wrap)); + if (unlikely(ret)) { + ret = -EFAULT; + } fail: if (wkey != NULL) _ncr_key_item_put(wkey); - if (data != NULL) _ncr_data_item_put(data); + if (data != NULL) kfree(data); if (sdata != NULL) kfree(sdata); return ret; @@ -607,13 +645,13 @@ fail: /* Unwraps keys. All keys unwrapped are not accessible by * userspace. */ -int ncr_key_storage_unwrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg) +int ncr_key_storage_unwrap(struct list_sem_st* key_lst, void __user* arg) { struct ncr_key_storage_wrap_st wrap; struct key_item_st* wkey = NULL; -struct data_item_st * data = NULL; +void* data = NULL; uint8_t * sdata = NULL; -size_t sdata_size = 0; +size_t sdata_size = 0, data_size; int ret; if (master_key.type != NCR_KEY_TYPE_SECRET) { @@ -632,14 +670,21 @@ int ret; return ret; } - data = ncr_data_item_get(data_lst, wrap.data); + data_size = wrap.io_size; + data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); - ret = -EINVAL; + ret = -ENOMEM; + goto fail; + } + + if (unlikely(copy_from_user(data, wrap.io, data_size))) { + err(); + ret = -EFAULT; goto fail; } - sdata_size = data->data_size; + sdata_size = data_size; sdata = kmalloc(sdata_size, GFP_KERNEL); if (sdata == NULL) { err(); @@ -647,9 +692,9 @@ int ret; goto fail; } - wkey->flags = data_flags_to_key(data->flags) | NCR_KEY_FLAG_WRAPPABLE; + wkey->flags = NCR_KEY_FLAG_WRAPPABLE; - ret = _unwrap_aes_rfc5649(sdata, &sdata_size, &master_key, data, NULL, 0); + ret = _unwrap_aes_rfc5649(sdata, &sdata_size, &master_key, data, data_size, NULL, 0); if (ret < 0) { err(); goto fail; @@ -664,7 +709,7 @@ int ret; fail: if (wkey != NULL) _ncr_key_item_put(wkey); - if (data != NULL) _ncr_data_item_put(data); + if (data != NULL) kfree(data); if (sdata != NULL) kfree(sdata); return ret; @@ -146,13 +146,13 @@ ncr_ioctl(struct ncr_lists* lst, struct file *filp, case NCRIO_KEY_GET_INFO: return ncr_key_info(&lst->key, arg); case NCRIO_KEY_WRAP: - return ncr_key_wrap(&lst->key, &lst->data, arg); + return ncr_key_wrap(&lst->key, arg); case NCRIO_KEY_UNWRAP: - return ncr_key_unwrap(&lst->key, &lst->data, arg); + return ncr_key_unwrap(&lst->key, arg); case NCRIO_KEY_STORAGE_WRAP: - return ncr_key_storage_wrap(&lst->key, &lst->data, arg); + return ncr_key_storage_wrap(&lst->key, arg); case NCRIO_KEY_STORAGE_UNWRAP: - return ncr_key_storage_unwrap(&lst->key, &lst->data, arg); + return ncr_key_storage_unwrap(&lst->key, arg); case NCRIO_SESSION_INIT: return ncr_session_init(lst, arg); case NCRIO_SESSION_UPDATE: @@ -212,7 +212,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; @@ -220,10 +220,12 @@ struct ncr_key_wrap_st { ncr_key_t key; struct ncr_key_params_st params; - ncr_data_t data; /* encrypted keytowrap */ + + void* io; /* encrypted keytowrap */ + size_t io_size; /* this will be updated by the actual size on wrap */ }; -#define NCRIO_KEY_WRAP _IOR ('c', 250, struct ncr_key_wrap_st) +#define NCRIO_KEY_WRAP _IOWR ('c', 250, struct ncr_key_wrap_st) #define NCRIO_KEY_UNWRAP _IOR ('c', 251, struct ncr_key_wrap_st) /* Internal ops */ @@ -238,10 +240,12 @@ struct ncr_master_key_st { * fields to be able to recover a key */ struct ncr_key_storage_wrap_st { ncr_key_t keytowrap; - ncr_data_t data; /* encrypted keytowrap */ + + void* io; /* encrypted keytowrap */ + size_t io_size; /* this will be updated by the actual size on wrap */ }; -#define NCRIO_KEY_STORAGE_WRAP _IOR ('c', 261, struct ncr_key_storage_wrap_st) +#define NCRIO_KEY_STORAGE_WRAP _IOWR ('c', 261, struct ncr_key_storage_wrap_st) #define NCRIO_KEY_STORAGE_UNWRAP _IOR ('c', 262, struct ncr_key_storage_wrap_st) /* Crypto Operations ioctls @@ -168,10 +168,10 @@ int ncr_limits_add_and_check(uid_t uid, pid_t pid, limits_type_t type); void ncr_limits_init(void); void ncr_limits_deinit(void); -int ncr_key_wrap(struct list_sem_st* keys, struct list_sem_st* data, void __user* arg); -int ncr_key_unwrap(struct list_sem_st*, struct list_sem_st* data, void __user* arg); -int ncr_key_storage_wrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg); -int ncr_key_storage_unwrap(struct list_sem_st*, struct list_sem_st* data, void __user* arg); +int ncr_key_wrap(struct list_sem_st* keys, void __user* arg); +int ncr_key_unwrap(struct list_sem_st*, void __user* arg); +int ncr_key_storage_wrap(struct list_sem_st* key_lst, void __user* arg); +int ncr_key_storage_unwrap(struct list_sem_st*, void __user* arg); /* sessions */ struct session_item_st* ncr_session_new(struct list_sem_st* lst); |