diff options
Diffstat (limited to 'ncr-key-wrap.c')
-rw-r--r-- | ncr-key-wrap.c | 233 |
1 files changed, 125 insertions, 108 deletions
diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 0f9f0fe..c409bb9 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -28,8 +28,8 @@ #include <linux/highmem.h> #include <linux/random.h> #include <linux/uaccess.h> -#include "cryptodev.h" #include <linux/scatterlist.h> +#include <net/netlink.h> #include "ncr.h" #include "ncr-int.h" #include "cryptodev_int.h" @@ -39,10 +39,8 @@ typedef uint8_t val64_t[8]; static const val64_t initA = "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6"; static int key_to_packed_data( uint8_t** sdata, size_t * sdata_size, const struct key_item_st *key); -static int key_from_packed_data(ncr_algorithm_t algorithm, - ncr_key_type_t key_type, unsigned int flags, - struct key_item_st* key, const void* data, - size_t data_size); +static int key_from_packed_data(struct nlattr *tb[], struct key_item_st* key, + const void* data, size_t data_size); static void val64_xor( val64_t val, uint32_t x) @@ -62,7 +60,7 @@ int i,j; if (*output_size < (n+1)*8) { err(); - return -EINVAL; + return -ERANGE; } memcpy(A, iv, 8); @@ -284,12 +282,13 @@ size_t sdata_size = 0; } static int unwrap_aes_rfc5649(struct key_item_st* output, struct key_item_st *kek, - void* wrapped, size_t wrapped_size, - struct ncr_key_wrap_st* wrap_st) + void *wrapped, size_t wrapped_size, struct nlattr *tb[]) { -int ret; +const struct nlattr *nla; +int ret, iv_size; void * sdata; size_t sdata_size = KEY_DATA_MAX_SIZE; +const uint8_t *iv; sdata = kmalloc(sdata_size, GFP_KERNEL); if (sdata == NULL) { @@ -297,18 +296,23 @@ size_t sdata_size = KEY_DATA_MAX_SIZE; return -ENOMEM; } + nla = tb[NCR_ATTR_IV]; + if (nla != NULL) { + iv = nla_data(nla); + iv_size = nla_len(nla); + } else { + iv = NULL; + iv_size = 0; + } + ret = _unwrap_aes_rfc5649(sdata, &sdata_size, kek, - wrapped, wrapped_size, - wrap_st->params.params.cipher.iv, wrap_st->params.params.cipher.iv_size); + wrapped, wrapped_size, iv, iv_size); if (ret < 0) { err(); goto fail; } - ret = key_from_packed_data(wrap_st->wrapped_key_algorithm, - wrap_st->wrapped_key_type, - wrap_st->wrapped_key_flags, output, sdata, - sdata_size); + ret = key_from_packed_data(tb, output, sdata, sdata_size); if (ret < 0) { err(); goto fail; @@ -403,16 +407,24 @@ void print_val64(char* str, val64_t val) #endif static int unwrap_aes_rfc3394(struct key_item_st* output, struct key_item_st *kek, - void* wrapped_key, size_t wrapped_key_size, struct ncr_key_wrap_st *wrap_st) + void* wrapped_key, size_t wrapped_key_size, + struct nlattr *tb[]) { +const struct nlattr *nla; size_t n; val64_t A; int i, ret; struct cipher_data ctx; val64_t * R = NULL; -int iv_size = wrap_st->params.params.cipher.iv_size; -const uint8_t * iv = wrap_st->params.params.cipher.iv; - +int iv_size; +const uint8_t *iv; + + nla = tb[NCR_ATTR_IV]; + if (nla != NULL) { + iv = nla_data(nla); + iv_size = nla_len(nla); + } else + iv_size = 0; if (iv_size < sizeof(initA)) { iv_size = sizeof(initA); iv = initA; @@ -459,10 +471,13 @@ const uint8_t * iv = wrap_st->params.params.cipher.iv; goto cleanup; } - ret = ncr_key_assign_flags(output, wrap_st->wrapped_key_flags); - if (ret != 0) { - err(); - goto cleanup; + nla = tb[NCR_ATTR_KEY_FLAGS]; + if (nla != NULL) { + ret = ncr_key_assign_flags(output, nla_get_u32(nla)); + if (ret != 0) { + err(); + goto cleanup; + } } memset(&output->key, 0, sizeof(output->key)); @@ -512,21 +527,23 @@ int kek_level, wkey_level; return 0; } -int ncr_key_wrap(struct ncr_lists *lst, void __user* arg) +int ncr_key_wrap(struct ncr_lists *lst, const struct ncr_key_wrap *wrap, + struct nlattr *tb[]) { -struct ncr_key_wrap_st wrap; +const struct nlattr *nla; struct key_item_st* wkey = NULL; struct key_item_st* key = NULL; void* data = NULL; -size_t data_size; +const void *iv; +size_t data_size, iv_size; int ret; - if (unlikely(copy_from_user(&wrap, arg, sizeof(wrap)))) { + if (wrap->buffer_size < 0) { err(); - return -EFAULT; + return -EINVAL; } - ret = ncr_key_item_get_read( &wkey, lst, wrap.keytowrap); + ret = ncr_key_item_get_read(&wkey, lst, wrap->source_key); if (ret < 0) { err(); return ret; @@ -538,7 +555,7 @@ int ret; goto fail; } - ret = ncr_key_item_get_read( &key, lst, wrap.key); + ret = ncr_key_item_get_read(&key, lst, wrap->wrapping_key); if (ret < 0) { err(); goto fail; @@ -556,7 +573,7 @@ int ret; goto fail; } - data_size = wrap.io_size; + data_size = wrap->buffer_size; data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); @@ -564,18 +581,29 @@ int ret; goto fail; } - switch(wrap.algorithm) { - case NCR_WALG_AES_RFC3394: - 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, &data_size, - wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); - break; - default: - err(); - ret = -EINVAL; + nla = tb[NCR_ATTR_IV]; + if (nla != NULL) { + iv = nla_data(nla); + iv_size = nla_len(nla); + } else { + iv = NULL; + iv_size = 0; + } + + nla = tb[NCR_ATTR_WRAPPING_ALGORITHM]; + if (nla == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + if (nla_strcmp(nla, NCR_WALG_AES_RFC3394) == 0) + ret = wrap_aes(wkey, key, data, &data_size, iv, iv_size); + else if (nla_strcmp(nla, NCR_WALG_AES_RFC5649) == 0) + ret = wrap_aes_rfc5649(wkey, key, data, &data_size, iv, + iv_size); + else { + err(); + ret = -EINVAL; } if (ret < 0) { @@ -583,18 +611,13 @@ int ret; goto fail; } - ret = copy_to_user(wrap.io, data, data_size); + ret = copy_to_user(wrap->buffer, 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; - } + ret = data_size; fail: if (wkey != NULL) _ncr_key_item_put(wkey); @@ -607,27 +630,23 @@ fail: /* Unwraps keys. All keys unwrapped are not accessible by * userspace. */ -int ncr_key_unwrap(struct ncr_lists *lst, void __user* arg) +int ncr_key_unwrap(struct ncr_lists *lst, const struct ncr_key_unwrap *wrap, + struct nlattr *tb[]) { -struct ncr_key_wrap_st wrap; +const struct nlattr *nla; struct key_item_st* wkey = NULL; struct key_item_st* key = NULL; void* data = NULL; size_t data_size; int ret; - if (unlikely(copy_from_user(&wrap, arg, sizeof(wrap)))) { - err(); - return -EFAULT; - } - - ret = ncr_key_item_get_write( &wkey, lst, wrap.keytowrap); + ret = ncr_key_item_get_write(&wkey, lst, wrap->dest_key); if (ret < 0) { err(); return ret; } - ret = ncr_key_item_get_read( &key, lst, wrap.key); + ret = ncr_key_item_get_read(&key, lst, wrap->wrapping_key); if (ret < 0) { err(); goto fail; @@ -639,7 +658,7 @@ int ret; goto fail; } - data_size = wrap.io_size; + data_size = wrap->data_size; data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); @@ -647,7 +666,7 @@ int ret; goto fail; } - if (unlikely(copy_from_user(data, wrap.io, data_size))) { + if (unlikely(copy_from_user(data, wrap->data, data_size))) { err(); ret = -EFAULT; goto fail; @@ -655,18 +674,19 @@ int ret; ncr_key_clear(wkey); - switch(wrap.algorithm) { - case NCR_WALG_AES_RFC3394: - ret = unwrap_aes_rfc3394(wkey, key, data, data_size, - &wrap); - break; - case NCR_WALG_AES_RFC5649: - ret = unwrap_aes_rfc5649(wkey, key, - data, data_size, &wrap); - break; - default: - err(); - ret = -EINVAL; + nla = tb[NCR_ATTR_WRAPPING_ALGORITHM]; + if (nla == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + if (nla_strcmp(nla, NCR_WALG_AES_RFC3394) == 0) + ret = unwrap_aes_rfc3394(wkey, key, data, data_size, tb); + else if (nla_strcmp(nla, NCR_WALG_AES_RFC5649) == 0) + ret = unwrap_aes_rfc5649(wkey, key, data, data_size, tb); + else { + err(); + ret = -EINVAL; } fail: @@ -677,9 +697,10 @@ fail: return ret; } -int ncr_key_storage_wrap(struct ncr_lists *lst, void __user* arg) +int ncr_key_storage_wrap(struct ncr_lists *lst, + const struct ncr_key_storage_wrap *wrap, + struct nlattr *tb[]) { -struct ncr_key_storage_wrap_st wrap; struct key_item_st* wkey = NULL; void* data = NULL; size_t data_size; @@ -692,18 +713,18 @@ int ret; return -ENOKEY; } - if (unlikely(copy_from_user(&wrap, arg, sizeof(wrap)))) { + if (wrap->buffer_size < 0) { err(); - return -EFAULT; + return -EINVAL; } - ret = ncr_key_item_get_read( &wkey, lst, wrap.keytowrap); + ret = ncr_key_item_get_read(&wkey, lst, wrap->key); if (ret < 0) { err(); return ret; } - data_size = wrap.io_size; + data_size = wrap->buffer_size; data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); @@ -723,18 +744,13 @@ int ret; goto fail; } - ret = copy_to_user(wrap.io, data, data_size); + ret = copy_to_user(wrap->buffer, 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; - } + ret = data_size; fail: if (wkey != NULL) _ncr_key_item_put(wkey); @@ -744,12 +760,10 @@ fail: return ret; } -/* Unwraps keys. All keys unwrapped are not accessible by - * userspace. - */ -int ncr_key_storage_unwrap(struct ncr_lists *lst, void __user* arg) +int ncr_key_storage_unwrap(struct ncr_lists *lst, + const struct ncr_key_storage_unwrap *wrap, + struct nlattr *tb[]) { -struct ncr_key_storage_wrap_st wrap; struct key_item_st* wkey = NULL; void* data = NULL; uint8_t * sdata = NULL; @@ -761,18 +775,13 @@ int ret; return -ENOKEY; } - if (unlikely(copy_from_user(&wrap, arg, sizeof(wrap)))) { - err(); - return -EFAULT; - } - - ret = ncr_key_item_get_write( &wkey, lst, wrap.keytowrap); + ret = ncr_key_item_get_write(&wkey, lst, wrap->key); if (ret < 0) { err(); return ret; } - data_size = wrap.io_size; + data_size = wrap->data_size; data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); @@ -780,7 +789,7 @@ int ret; goto fail; } - if (unlikely(copy_from_user(data, wrap.io, data_size))) { + if (unlikely(copy_from_user(data, wrap->data, data_size))) { err(); ret = -EFAULT; goto fail; @@ -856,11 +865,10 @@ fail: return ret; } -static int key_from_packed_data(ncr_algorithm_t algorithm, - ncr_key_type_t key_type, unsigned int flags, - struct key_item_st* key, const void* data, - size_t data_size) +static int key_from_packed_data(struct nlattr *tb[], struct key_item_st *key, + const void *data, size_t data_size) { + const struct nlattr *nla; int ret; if (data_size > KEY_DATA_MAX_SIZE) { @@ -868,17 +876,26 @@ static int key_from_packed_data(ncr_algorithm_t algorithm, return -EINVAL; } - key->algorithm = _ncr_algo_to_properties(algorithm); + key->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); if (key->algorithm == NULL) { err(); return -EINVAL; } - key->type = key_type; - ret = ncr_key_assign_flags(key, flags); - if (ret != 0) { + nla = tb[NCR_ATTR_KEY_TYPE]; + if (tb == NULL) { err(); - return ret; + return -EINVAL; + } + key->type = nla_get_u32(nla); + + nla = tb[NCR_ATTR_KEY_FLAGS]; + if (nla != NULL) { + ret = ncr_key_assign_flags(key, nla_get_u32(nla)); + if (ret != 0) { + err(); + return ret; + } } if (key->type == NCR_KEY_TYPE_SECRET) { |