summaryrefslogtreecommitdiffstats
path: root/ncr-key-wrap.c
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2010-06-16 12:11:01 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2010-06-17 20:49:05 +0200
commitfac33709478cfbd1657aa502ea6ea1acb12ecc2d (patch)
tree429a26482407e34e4ac3e1873e63557cc048e21e /ncr-key-wrap.c
parenta1e2f414b46deb9d746ba03fb337ef0c95d46f7a (diff)
downloadcryptodev-linux-fac33709478cfbd1657aa502ea6ea1acb12ecc2d.tar.gz
cryptodev-linux-fac33709478cfbd1657aa502ea6ea1acb12ecc2d.tar.xz
cryptodev-linux-fac33709478cfbd1657aa502ea6ea1acb12ecc2d.zip
Initial attempts to allow wrapping keys with out of band data such as flags, key ids etc.
Diffstat (limited to 'ncr-key-wrap.c')
-rw-r--r--ncr-key-wrap.c149
1 files changed, 145 insertions, 4 deletions
diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c
index b6987af..db0374e 100644
--- a/ncr-key-wrap.c
+++ b/ncr-key-wrap.c
@@ -34,12 +34,43 @@ typedef uint8_t val64_t[8];
static const val64_t initA = "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6";
-void val64_zero( val64_t * val)
+static int key_from_storage_data(struct key_item_st* key, const void* data, size_t data_size);
+static int key_to_storage_data( uint8_t** data, size_t * data_size, const struct key_item_st *key);
+
+static int _wrap_aes_rfc5649(void* kdata, size_t kdata_size, struct key_item_st* key,
+ struct data_item_st* data, const void* iv, size_t iv_size);
+static int _unwrap_aes_rfc5649(void* kdata, size_t *kdata_size, struct key_item_st* key,
+ struct data_item_st *data, const void* iv, size_t iv_size);
+
+
+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)
+{
+ if (tobewrapped->type != NCR_KEY_TYPE_SECRET) {
+ err();
+ return -EINVAL;
+ }
+
+ return _wrap_aes_rfc5649(tobewrapped->key.secret.data, tobewrapped->key.secret.size,
+ kek, output, 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)
+{
+ output->type = NCR_KEY_TYPE_SECRET;
+
+ return _unwrap_aes_rfc5649(output->key.secret.data, &output->key.secret.size, kek, wrapped, iv, iv_size);
+}
+
+
+static void val64_zero( val64_t * val)
{
memset(val, 0, sizeof(*val));
}
-void val64_xor( val64_t * val, uint32_t x)
+static void val64_xor( val64_t * val, uint32_t x)
{
(*val)[7] ^= x & 0xff;
(*val)[6] ^= (x >> 8) & 0xff;
@@ -257,7 +288,6 @@ int ret;
return -EPERM;
}
- /* FIXME: allow alternative IV */
key = ncr_key_item_get( key_lst, wrap.key.key);
if (key == NULL) {
err();
@@ -278,6 +308,9 @@ int ret;
case NCR_WALG_AES_RFC3394:
ret = wrap_aes(wkey, key, data, wrap.key.params.cipher.iv, wrap.key.params.cipher.iv_size);
break;
+ case NCR_WALG_AES_RFC5649:
+ ret = wrap_aes_rfc5649(wkey, key, data, wrap.key.params.cipher.iv, wrap.key.params.cipher.iv_size);
+ break;
default:
err();
ret = -EINVAL;
@@ -324,12 +357,15 @@ int ret;
goto fail;
}
- wkey->flags = data_flags_to_key(wkey->flags) | NCR_KEY_FLAG_WRAPPABLE;
+ wkey->flags = data_flags_to_key(data->flags) | NCR_KEY_FLAG_WRAPPABLE;
switch(wrap.algorithm) {
case NCR_WALG_AES_RFC3394:
ret = unwrap_aes(wkey, key, data, wrap.key.params.cipher.iv, wrap.key.params.cipher.iv_size);
break;
+ case NCR_WALG_AES_RFC5649:
+ ret = unwrap_aes_rfc5649(wkey, key, data, wrap.key.params.cipher.iv, wrap.key.params.cipher.iv_size);
+ break;
default:
err();
ret = -EINVAL;
@@ -342,3 +378,108 @@ fail:
return ret;
}
+
+int ncr_key_storage_wrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg)
+{
+struct ncr_key_storage_wrap_st wrap;
+struct key_item_st* wkey = NULL;
+struct data_item_st * data = NULL;
+uint8_t * sdata = NULL;
+size_t sdata_size = 0;
+int ret;
+
+ copy_from_user( &wrap, arg, sizeof(wrap));
+
+ wkey = ncr_key_item_get( key_lst, wrap.keytowrap);
+ if (wkey == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ if (!(wkey->flags & NCR_KEY_FLAG_WRAPPABLE)) {
+ err();
+ return -EPERM;
+ }
+
+ data = ncr_data_item_get(data_lst, wrap.data);
+ if (data == NULL) {
+ err();
+ ret = -EINVAL;
+ 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);
+
+fail:
+ if (wkey != NULL) _ncr_key_item_put(wkey);
+ if (data != NULL) _ncr_data_item_put(data);
+ if (sdata != NULL) kfree(sdata);
+
+ return ret;
+}
+
+/* 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)
+{
+struct ncr_key_wrap_st wrap;
+struct key_item_st* wkey = NULL;
+struct data_item_st * data = NULL;
+uint8_t * sdata = NULL;
+size_t sdata_size = 0;
+int ret;
+
+ copy_from_user( &wrap, arg, sizeof(wrap));
+
+ wkey = ncr_key_item_get( key_lst, wrap.keytowrap);
+ if (wkey == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ data = ncr_data_item_get(data_lst, wrap.data);
+ if (data == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ sdata_size = data->data_size;
+ sdata = kmalloc(sdata_size, GFP_KERNEL);
+ if (sdata == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ wkey->flags = data_flags_to_key(data->flags) | NCR_KEY_FLAG_WRAPPABLE;
+
+ ret = _unwrap_aes_rfc5649(sdata, &sdata_size, &master_key, data, NULL, 0);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = key_from_storage_data(wkey, sdata, sdata_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+
+fail:
+ if (wkey != NULL) _ncr_key_item_put(wkey);
+ if (data != NULL) _ncr_data_item_put(data);
+ if (sdata != NULL) kfree(sdata);
+
+ return ret;
+}