diff options
Diffstat (limited to 'ncr-key.c')
-rw-r--r-- | ncr-key.c | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/ncr-key.c b/ncr-key.c index 65a5525894b..56d88f7c470 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -152,3 +152,240 @@ int ncr_key_deinit(struct list_sem_st* lst, void __user* arg) return 0; } + +/* "exports" a key to a data item. If the key is not exportable + * to userspace then the data item will also not be. + */ +int ncr_key_export(struct list_sem_st* data_lst, + struct list_sem_st* key_lst, void __user* arg) +{ +struct ncr_key_data_st data; +struct key_item* item = NULL; +struct data_item* ditem = NULL; +int ret; + + copy_from_user( &data, arg, sizeof(data)); + + item = ncr_key_item_get( key_lst, data.key); + if (item == NULL) { + err(); + return -EINVAL; + } + + ditem = ncr_data_item_get( data_lst, data.data); + if (ditem == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + + switch (item->type) { + case NCR_KEY_TYPE_SECRET: + if (item->key.secret.size > ditem->max_data_size) { + err(); + ret = -EINVAL; + goto fail; + } + + /* found */ + ditem->flags = 0; + if ((item->flags & NCR_KEY_FLAG_EXPORTABLE)) { + ditem->flags |= NCR_DATA_FLAG_EXPORTABLE; + } + + if (item->key.secret.size > 0) { + memcpy(ditem->data, item->key.secret.data, item->key.secret.size); + } + ditem->data_size = item->key.secret.size; + break; + case NCR_KEY_TYPE_PUBLIC: /* FIXME: export in a blob -ASN.1? */ + case NCR_KEY_TYPE_PRIVATE: /* FIXME export in a blob -ASN.1? */ + default: + err(); + ret = -EINVAL; + goto fail; + } + + _ncr_key_item_put( item); + _ncr_data_item_put( ditem); + + return 0; + +fail: + if (item) + _ncr_key_item_put(item); + if (ditem) + _ncr_data_item_put(ditem); + return ret; + +} + +/* "imports" a key from a data item. If the key is not exportable + * to userspace then the key item will also not be. + */ +int ncr_key_import(struct list_sem_st* data_lst, + struct list_sem_st* key_lst, void __user* arg) +{ +struct ncr_key_data_st data; +struct key_item* item = NULL; +struct data_item* ditem = NULL; +int ret; + + copy_from_user( &data, arg, sizeof(data)); + + item = ncr_key_item_get( key_lst, data.key); + if (item == NULL) { + err(); + return -EINVAL; + } + + ditem = ncr_data_item_get( data_lst, data.data); + if (ditem == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + + item->type = data.type; + item->algorithm = data.algorithm; + item->flags = data.flags; + /* if data cannot be exported then the flags above + * should be overriden */ + if ((ditem->flags & NCR_DATA_FLAG_EXPORTABLE)) { + item->flags |= NCR_KEY_FLAG_EXPORTABLE; + } + + switch(item->type) { + case NCR_KEY_TYPE_SECRET: + + if (data.key_id_size > MAX_KEY_ID_SIZE) { + err(); + ret = -EINVAL; + goto fail; + } + item->key_id_size = data.key_id_size; + if (data.key_id_size > 0) + memcpy(item->key_id, data.key_id, data.key_id_size); + + + if (ditem->data_size > MAX_KEY_SIZE) { + err(); + ret = -EINVAL; + goto fail; + } + + memcpy(item->key.secret.data, ditem->data, ditem->data_size); + item->key.secret.size = ditem->data_size; + break; + case NCR_KEY_TYPE_PRIVATE: /* FIXME */ + case NCR_KEY_TYPE_PUBLIC: /* FIXME */ + default: + err(); + ret = -EINVAL; + goto fail; + } + + _ncr_key_item_put( item); + _ncr_data_item_put( ditem); + + return 0; + +fail: + if (item) + _ncr_key_item_put(item); + if (ditem) + _ncr_data_item_put(ditem); + return ret; +} + +/* Generate a secret key + */ +int ncr_key_generate(struct list_sem_st* lst, void __user* arg) +{ +struct ncr_key_generate_st gen; +struct key_item* item = NULL; +int ret; +size_t size; + + copy_from_user( &gen, arg, sizeof(gen)); + + item = ncr_key_item_get( lst, gen.desc); + if (item == NULL) { + err(); + return -EINVAL; + } + + /* we generate only secret keys */ + item->type = ncr_algorithm_to_key_type(gen.params.algorithm); + if (item->type != NCR_KEY_TYPE_SECRET) { + err(); + ret = -EINVAL; + goto fail; + } + + item->flags = gen.params.keyflags; + item->algorithm = /* arbitrary */ NCR_ALG_AES_CBC; + + size = gen.params.params.secret.bits/8; + if ((gen.params.params.secret.bits % 8 != 0) || + (size > MAX_KEY_SIZE)) { + err(); + ret = -EINVAL; + goto fail; + } + + get_random_bytes(item->key.secret.data, size); + item->key.secret.size = size; + + /* generate random key id */ + item->key_id_size = 5; + get_random_bytes(item->key_id, item->key_id_size); + + _ncr_key_item_put( item); + + return 0; + +fail: + if (item) + _ncr_key_item_put(item); + return ret; +} + +int ncr_key_info(struct list_sem_st* lst, void __user* arg) +{ +struct ncr_key_info_st info; +struct key_item* item = NULL; + + copy_from_user( &info, arg, sizeof(info)); + + item = ncr_key_item_get( lst, info.key); + if (item == NULL) { + err(); + return -EINVAL; + } + + info.flags = item->flags; + info.type = item->type; + info.algorithm = item->algorithm; + + _ncr_key_item_put( item); + + return 0; +} + +/* FIXME those require public key subsystem */ +int ncr_key_generate_pair(struct list_sem_st* lst, void __user* arg) +{ + return -EINVAL; +} + +int ncr_key_derive(struct list_sem_st* lst, void __user* arg) +{ + return -EINVAL; +} + +int ncr_key_get_public(struct list_sem_st* lst, void __user* arg) +{ + return -EINVAL; +} + |