summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2010-08-21 12:41:23 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2010-08-21 12:41:23 +0200
commit659f7452456f4fa5cee8694f808d61da6f840b32 (patch)
treeb6c2e29683c2a6ddfe897884316ff53618736800
parent3c7ca7cc92736ff56ec241b1c3da890b7496e5cc (diff)
downloadkernel-crypto-659f7452456f4fa5cee8694f808d61da6f840b32.tar.gz
kernel-crypto-659f7452456f4fa5cee8694f808d61da6f840b32.tar.xz
kernel-crypto-659f7452456f4fa5cee8694f808d61da6f840b32.zip
Improvements in key wrapping. Allowed symmetric keys to wrap assymetric ones.
-rw-r--r--examples/pk.c31
-rw-r--r--ncr-int.h1
-rw-r--r--ncr-key-wrap.c155
-rw-r--r--ncr-key.c17
-rw-r--r--ncr.h8
5 files changed, 188 insertions, 24 deletions
diff --git a/examples/pk.c b/examples/pk.c
index 5f7c72a3e00..629ca6adfde 100644
--- a/examples/pk.c
+++ b/examples/pk.c
@@ -531,6 +531,7 @@ test_ncr_wrap_key3(int cfd)
{
int ret, i;
ncr_key_t key;
+ size_t data_size;
struct ncr_key_data_st keydata;
struct ncr_key_wrap_st kwrap;
struct ncr_key_generate_st kgen;
@@ -539,7 +540,7 @@ test_ncr_wrap_key3(int cfd)
/* only the first two should be allowed to be wrapped */
const int sizes[] = {1024, 3248, 5200};
- fprintf(stdout, "Tests on key wrapping: ");
+ fprintf(stdout, "Tests on key wrapping (might take long): ");
fflush(stdout);
/* convert it to key */
@@ -585,6 +586,10 @@ test_ncr_wrap_key3(int cfd)
}
for (i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
+
+ fprintf(stdout, ".");
+ fflush(stdout);
+
memset(&kgen, 0, sizeof(kgen));
kgen.desc = privkey;
kgen.desc2 = pubkey;
@@ -593,7 +598,7 @@ test_ncr_wrap_key3(int cfd)
kgen.params.params.rsa.bits = sizes[i];
if (ioctl(cfd, NCRIO_KEY_GENERATE_PAIR, &kgen)) {
- fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ fprintf(stderr, "Error[%d-%d]: %s:%d\n", i, sizes[i], __func__, __LINE__);
perror("ioctl(NCRIO_KEY_GENERATE_PAIR)");
return 1;
}
@@ -631,6 +636,28 @@ test_ncr_wrap_key3(int cfd)
/* wrapping shouldn't have been allowed */
return 1;
}
+
+ if (ret == 0) {
+ data_size = kwrap.io_size;
+
+ /* try unwrapping */
+ memset(&kwrap, 0, sizeof(kwrap));
+ kwrap.algorithm = NCR_WALG_AES_RFC5649;
+ kwrap.wrapped_key_algorithm = NCR_ALG_RSA;
+ kwrap.keytowrap = privkey;
+ kwrap.key = key;
+ kwrap.io = data;
+ kwrap.io_size = data_size;
+
+ ret = ioctl(cfd, NCRIO_KEY_UNWRAP, &kwrap);
+ if (ret) {
+ fprintf(stderr, "Error[%d-%d]: %s:%d\n", i, sizes[i], __func__, __LINE__);
+ return 1;
+ }
+ }
+ fprintf(stdout, "*");
+ fflush(stdout);
+
}
fprintf(stdout, " Success\n");
diff --git a/ncr-int.h b/ncr-int.h
index 9f7ee0ded64..4694cdae054 100644
--- a/ncr-int.h
+++ b/ncr-int.h
@@ -111,6 +111,7 @@ int ncr_ioctl(struct ncr_lists*, struct file *filp,
int ncr_key_derive(struct ncr_lists *lst, void __user* arg);
void ncr_key_clear(struct key_item_st* item);
+void ncr_key_assign_flags(struct key_item_st* item, unsigned int flags);
/* key handling */
int ncr_key_init(struct ncr_lists *lst, void __user* arg);
diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c
index eb68d92de05..93103b5a9a5 100644
--- a/ncr-key-wrap.c
+++ b/ncr-key-wrap.c
@@ -38,6 +38,10 @@ 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, unsigned int flags,
+ struct key_item_st* key, const void* data, size_t data_size);
+
static void val64_xor( val64_t val, uint32_t x)
{
@@ -259,23 +263,59 @@ cleanup:
static int wrap_aes_rfc5649(struct key_item_st* tobewrapped, struct key_item_st *kek,
void* output, size_t* output_size, const void* iv, size_t iv_size)
{
- if (tobewrapped->type != NCR_KEY_TYPE_SECRET) {
+int ret;
+uint8_t* sdata;
+size_t sdata_size = 0;
+
+ ret = key_to_packed_data(&sdata, &sdata_size, tobewrapped);
+ if (ret < 0) {
err();
- return -EINVAL;
+ return ret;
}
- return _wrap_aes_rfc5649(tobewrapped->key.secret.data, tobewrapped->key.secret.size,
+ ret = _wrap_aes_rfc5649(sdata, sdata_size,
kek, output, output_size, iv, iv_size);
+
+ kfree(sdata);
+ return ret;
}
static int unwrap_aes_rfc5649(struct key_item_st* output, struct key_item_st *kek,
- void* wrapped, size_t wrapped_size, const void* iv, size_t iv_size)
+ void* wrapped, size_t wrapped_size,
+ struct ncr_key_wrap_st* wrap_st)
{
- output->type = NCR_KEY_TYPE_SECRET;
+int ret;
+void * sdata;
+size_t sdata_size = KEY_DATA_MAX_SIZE;
+
+ sdata = kmalloc(sdata_size, GFP_KERNEL);
+ if (sdata == NULL) {
+ err();
+ return -ENOMEM;
+ }
+
+ ret = _unwrap_aes_rfc5649(sdata, &sdata_size, kek,
+ wrapped, wrapped_size,
+ wrap_st->params.params.cipher.iv, wrap_st->params.params.cipher.iv_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = key_from_packed_data(wrap_st->wrapped_key_algorithm, wrap_st->wrapped_key_flags,
+ output, sdata, sdata_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ kfree(sdata);
+ return ret;
- return _unwrap_aes_rfc5649(output->key.secret.data, &output->key.secret.size, kek,
- wrapped, wrapped_size, iv, iv_size);
}
@@ -358,14 +398,16 @@ void print_val64(char* str, val64_t val)
}
#endif
-static int unwrap_aes(struct key_item_st* output, struct key_item_st *kek,
- void* wrapped_key, size_t wrapped_key_size, const void* iv, size_t iv_size)
+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)
{
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;
if (iv_size < sizeof(initA)) {
iv_size = sizeof(initA);
@@ -418,7 +460,7 @@ val64_t * R = NULL;
memcpy(&output->key.secret.data[i*8], R[i], sizeof(R[i]));
}
output->key.secret.size = n*8;
- output->flags = NCR_KEY_FLAG_WRAPPABLE;
+ ncr_key_assign_flags(output, wrap_st->wrapped_key_flags);
output->type = NCR_KEY_TYPE_SECRET;
ret = 0;
@@ -601,15 +643,17 @@ int ret;
ret = -EFAULT;
goto fail;
}
+
+ ncr_key_clear(wkey);
switch(wrap.algorithm) {
case NCR_WALG_AES_RFC3394:
- ret = unwrap_aes(wkey, key, data, data_size,
- wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size);
+ 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.params.params.cipher.iv, wrap.params.params.cipher.iv_size);
+ ret = unwrap_aes_rfc5649(wkey, key,
+ data, data_size, &wrap);
break;
default:
err();
@@ -747,6 +791,8 @@ int ret;
goto fail;
}
+ ncr_key_clear(wkey);
+
ret = key_from_storage_data(wkey, sdata, sdata_size);
if (ret < 0) {
err();
@@ -761,3 +807,84 @@ fail:
return ret;
}
+
+static int key_to_packed_data( uint8_t** sdata, size_t * sdata_size, const struct key_item_st *key)
+{
+ uint8_t * pkey;
+ uint32_t usize;
+ int ret;
+
+ *sdata_size = KEY_DATA_MAX_SIZE;
+ pkey = kmalloc(*sdata_size, GFP_KERNEL);
+ if (pkey == NULL) {
+ err();
+ return -ENOMEM;
+ }
+
+ if (key->type == NCR_KEY_TYPE_SECRET) {
+ memcpy(pkey, key->key.secret.data, key->key.secret.size);
+ *sdata_size = key->key.secret.size;
+ } else if (key->type == NCR_KEY_TYPE_PRIVATE || key->type == NCR_KEY_TYPE_PUBLIC) {
+ usize = *sdata_size;
+ ret = ncr_pk_pack( key, pkey, &usize);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ *sdata_size = usize;
+ } else {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ *sdata = (void*)pkey;
+
+ return 0;
+fail:
+ kfree(pkey);
+
+ return ret;
+}
+
+static int key_from_packed_data(ncr_algorithm_t algorithm, unsigned int flags,
+ struct key_item_st* key, const void* data, size_t data_size)
+{
+ int ret;
+
+ if (data_size > KEY_DATA_MAX_SIZE) {
+ err();
+ return -EINVAL;
+ }
+
+ key->algorithm = _ncr_algo_to_properties(algorithm);
+ if (key->algorithm == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ key->type = key->algorithm->key_type;
+ ncr_key_assign_flags(key, flags);
+
+ if (key->type == NCR_KEY_TYPE_SECRET) {
+ if (data_size > NCR_CIPHER_MAX_KEY_LEN) {
+ err();
+ return -EINVAL;
+ }
+ key->key.secret.size = data_size;
+ memcpy(key->key.secret.data, data, data_size);
+ } else if (key->type == NCR_KEY_TYPE_PUBLIC
+ || key->type == NCR_KEY_TYPE_PRIVATE) {
+
+ ret = ncr_pk_unpack( key, data, data_size);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ } else {
+ err();
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/ncr-key.c b/ncr-key.c
index 4b9b26ff659..37e78542b24 100644
--- a/ncr-key.c
+++ b/ncr-key.c
@@ -309,12 +309,12 @@ fail:
}
-unsigned int assign_key_flags(unsigned int flags)
+void ncr_key_assign_flags(struct key_item_st* item, unsigned int flags)
{
if (current_euid()==0) {
- return flags;
+ item->flags = flags;
} else {
- return flags & (~(NCR_KEY_FLAG_WRAPPING));
+ item->flags = flags & (~(NCR_KEY_FLAG_WRAPPING));
}
}
@@ -363,7 +363,7 @@ size_t tmp_size;
ret = -EINVAL;
goto fail;
}
- item->flags = assign_key_flags(data.flags);
+ ncr_key_assign_flags(item, data.flags);
if (data.key_id_size > MAX_KEY_ID_SIZE) {
err();
@@ -451,7 +451,7 @@ size_t size;
ncr_key_clear(item);
/* we generate only secret keys */
- item->flags = assign_key_flags(gen.params.keyflags);
+ ncr_key_assign_flags(item, gen.params.keyflags);
algo = _ncr_algo_to_properties(gen.params.algorithm);
if (algo == NULL) {
@@ -656,8 +656,6 @@ int ret;
ncr_key_clear(private);
/* we generate only secret keys */
- private->flags = public->flags = assign_key_flags(gen.params.keyflags);
-
private->algorithm = public->algorithm = _ncr_algo_to_properties(gen.params.algorithm);
if (private->algorithm == NULL) {
err();
@@ -666,6 +664,9 @@ int ret;
}
public->type = public->algorithm->key_type;
private->type = NCR_KEY_TYPE_PRIVATE;
+ ncr_key_assign_flags(private, gen.params.keyflags);
+ ncr_key_assign_flags(public, gen.params.keyflags);
+
public->flags |= (NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE);
if (public->type == NCR_KEY_TYPE_PUBLIC) {
@@ -730,7 +731,7 @@ struct key_item_st* newkey = NULL;
ncr_key_clear(newkey);
- newkey->flags = assign_key_flags(data.keyflags);
+ ncr_key_assign_flags(newkey, data.keyflags);
switch (key->type) {
case NCR_KEY_TYPE_PUBLIC:
diff --git a/ncr.h b/ncr.h
index cddde078f1e..af4c279b630 100644
--- a/ncr.h
+++ b/ncr.h
@@ -199,6 +199,7 @@ struct ncr_key_data_st {
#define NCRIO_KEY_DERIVE _IOR ('c', 207, struct ncr_key_derivation_params_st)
/* return information on a key */
#define NCRIO_KEY_GET_INFO _IOWR('c', 208, struct ncr_key_info_st)
+
/* export a secret key */
#define NCRIO_KEY_EXPORT _IOWR('c', 209, struct ncr_key_data_st)
/* import a secret key */
@@ -210,6 +211,13 @@ struct ncr_key_data_st {
*/
struct ncr_key_wrap_st {
ncr_wrap_algorithm_t algorithm;
+
+ /* when unwrapping the algorithm of the wrapped key.
+ * For symmetric ciphers AES would do.
+ */
+ ncr_algorithm_t wrapped_key_algorithm;
+ unsigned int wrapped_key_flags; /* flags for the newly unwrapped key */
+
ncr_key_t keytowrap;
ncr_key_t key;