summaryrefslogtreecommitdiffstats
path: root/ncr-key.c
diff options
context:
space:
mode:
Diffstat (limited to 'ncr-key.c')
-rw-r--r--ncr-key.c237
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;
+}
+