summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-08-27 07:46:15 +0200
committerMiloslav Trmač <mitr@redhat.com>2010-08-27 07:46:15 +0200
commit9f0a6ce7f41043dad38b272cd6ad165f98827b8b (patch)
tree909f5dcc886a1ad32ab0a00bc0455c566e1037c2
parentc07dc584248074d16c371d2a478bc23520bef69f (diff)
parent1f30d575e5b413e522d6b3e95d3e348df9e9c69e (diff)
downloadkernel-crypto-9f0a6ce7f41043dad38b272cd6ad165f98827b8b.tar.gz
kernel-crypto-9f0a6ce7f41043dad38b272cd6ad165f98827b8b.tar.xz
kernel-crypto-9f0a6ce7f41043dad38b272cd6ad165f98827b8b.zip
Merge remote branch 'origin/newapi'
Conflicts: examples/ncr.c examples/pk.c ncr-key-wrap.c ncr-key.c ncr.h
-rw-r--r--crypto.44
-rw-r--r--examples/ncr.c14
-rw-r--r--examples/pk.c20
-rw-r--r--ncr-key-wrap.c201
-rw-r--r--ncr-key.c5
-rw-r--r--ncr-sessions.c4
-rw-r--r--ncr.h7
7 files changed, 194 insertions, 61 deletions
diff --git a/crypto.4 b/crypto.4
index c1b39e11221..23c4c2ba47a 100644
--- a/crypto.4
+++ b/crypto.4
@@ -431,14 +431,10 @@ members.
The following input attributes are recognized:
.RS
-.IP \fBNCR_ATTR_ALGORITHM\fP
-Mandatory.
.IP \fBNCR_ATTR_IV\fP
Optional, an empty IV is used if not present.
.IP \fBNCR_ATTR_KEY_FLAGS\fP
Optional, flags are unchanged if not present.
-.IP \fBNCR_ATTR_KEY_TYPE\fP
-Mandatory.
.IP \fBNCR_ATTR_WRAPPING_ALGORITHM\fP
Mandatory.
.RE
diff --git a/examples/ncr.c b/examples/ncr.c
index 203951646fa..9691fea5dc1 100644
--- a/examples/ncr.c
+++ b/examples/ncr.c
@@ -375,10 +375,6 @@ test_ncr_wrap_key(int cfd)
struct ncr_key_unwrap f;
struct nlattr wrap_algo_head ALIGN_NL;
char wrap_algo[sizeof(NCR_WALG_AES_RFC3394)] ALIGN_NL;
- struct nlattr algo_head ALIGN_NL;
- char algo[sizeof(ALG_AES_CBC)] ALIGN_NL;
- struct nlattr type_head ALIGN_NL;
- uint32_t type ALIGN_NL;
struct nlattr flags_head ALIGN_NL;
uint32_t flags ALIGN_NL;
} kunwrap;
@@ -417,7 +413,7 @@ test_ncr_wrap_key(int cfd)
strcpy(kimport.algo, ALG_AES_CBC);
kimport.flags_head.nla_len = NLA_HDRLEN + sizeof(kimport.flags);
kimport.flags_head.nla_type = NCR_ATTR_KEY_FLAGS;
- kimport.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING;
+ kimport.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING|NCR_KEY_FLAG_UNWRAPPING;
ret = ioctl(cfd, NCRIO_KEY_IMPORT, &kimport);
if (geteuid() == 0 && ret) {
@@ -518,12 +514,6 @@ test_ncr_wrap_key(int cfd)
kunwrap.wrap_algo_head.nla_len = NLA_HDRLEN + sizeof(kunwrap.wrap_algo);
kunwrap.wrap_algo_head.nla_type = NCR_ATTR_WRAPPING_ALGORITHM;
strcpy(kunwrap.wrap_algo, NCR_WALG_AES_RFC3394);
- kunwrap.algo_head.nla_len = NLA_HDRLEN + sizeof(kunwrap.algo);
- kunwrap.algo_head.nla_type = NCR_ATTR_ALGORITHM;
- strcpy(kunwrap.algo, ALG_AES_CBC);
- kunwrap.type_head.nla_len = NLA_HDRLEN + sizeof(kunwrap.type);
- kunwrap.type_head.nla_type = NCR_ATTR_KEY_TYPE;
- kunwrap.type = NCR_KEY_TYPE_SECRET;
kunwrap.flags_head.nla_len = NLA_HDRLEN + sizeof(kunwrap.flags);
kunwrap.flags_head.nla_type = NCR_ATTR_KEY_FLAGS;
kunwrap.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE;
@@ -629,7 +619,7 @@ test_ncr_wrap_key2(int cfd)
strcpy(kimport.algo, ALG_AES_CBC);
kimport.flags_head.nla_len = NLA_HDRLEN + sizeof(kimport.flags);
kimport.flags_head.nla_type = NCR_ATTR_KEY_FLAGS;
- kimport.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING;
+ kimport.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING|NCR_KEY_FLAG_UNWRAPPING;
if (ioctl(cfd, NCRIO_KEY_IMPORT, &kimport)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
diff --git a/examples/pk.c b/examples/pk.c
index 6acbadf12b0..81c5b49263d 100644
--- a/examples/pk.c
+++ b/examples/pk.c
@@ -624,10 +624,8 @@ test_ncr_wrap_key3(int cfd)
struct ncr_key_unwrap f;
struct nlattr wrap_algo_head ALIGN_NL;
char wrap_algo[sizeof(NCR_WALG_AES_RFC5649)] ALIGN_NL;
- struct nlattr algo_head ALIGN_NL;
- char algo[sizeof(ALG_RSA)] ALIGN_NL;
- struct nlattr type_head ALIGN_NL;
- uint32_t type ALIGN_NL;
+ struct nlattr flags_head ALIGN_NL;
+ uint32_t flags ALIGN_NL;
} kunwrap;
struct __attribute__((packed)) {
struct ncr_key_generate_pair f;
@@ -694,7 +692,7 @@ test_ncr_wrap_key3(int cfd)
strcpy(kimport.algo, ALG_AES_CBC);
kimport.flags_head.nla_len = NLA_HDRLEN + sizeof(kimport.flags);
kimport.flags_head.nla_type = NCR_ATTR_KEY_FLAGS;
- kimport.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING;
+ kimport.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING|NCR_KEY_FLAG_UNWRAPPING;
if (ioctl(cfd, NCRIO_KEY_IMPORT, &kimport)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
@@ -782,14 +780,10 @@ test_ncr_wrap_key3(int cfd)
kunwrap.wrap_algo_head.nla_type
= NCR_ATTR_WRAPPING_ALGORITHM;
strcpy(kunwrap.wrap_algo, NCR_WALG_AES_RFC5649);
- kunwrap.algo_head.nla_len
- = NLA_HDRLEN + sizeof(kunwrap.algo);
- kunwrap.algo_head.nla_type = NCR_ATTR_ALGORITHM;
- strcpy(kunwrap.algo, ALG_RSA);
- kunwrap.type_head.nla_len
- = NLA_HDRLEN + sizeof(kunwrap.type);
- kunwrap.type_head.nla_type = NCR_ATTR_KEY_TYPE;
- kunwrap.type = NCR_KEY_TYPE_PRIVATE;
+ kunwrap.flags_head.nla_len
+ = NLA_HDRLEN + sizeof(kunwrap.flags);
+ kunwrap.flags_head.nla_type = NCR_ATTR_KEY_FLAGS;
+ kunwrap.flags = 0;
ret = ioctl(cfd, NCRIO_KEY_UNWRAP, &kunwrap);
if (ret) {
diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c
index 25bd9e10686..7ea70cfc847 100644
--- a/ncr-key-wrap.c
+++ b/ncr-key-wrap.c
@@ -34,6 +34,8 @@
#include "ncr-int.h"
#include "cryptodev_int.h"
+#define KEY_WRAP_VERSION 0
+
typedef uint8_t val64_t[8];
static const val64_t initA = "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6";
@@ -264,7 +266,7 @@ static int wrap_aes_rfc5649(struct key_item_st* tobewrapped, struct key_item_st
void* output, size_t* output_size, const void* iv, size_t iv_size)
{
int ret;
-uint8_t* sdata;
+uint8_t* sdata = NULL;
size_t sdata_size = 0;
ret = key_to_packed_data(&sdata, &sdata_size, tobewrapped);
@@ -329,7 +331,7 @@ fail:
/* Wraps using the RFC3394 way.
*/
-static int wrap_aes(struct key_item_st* tobewrapped, struct key_item_st *kek,
+static int wrap_aes_rfc3394(struct key_item_st* tobewrapped, struct key_item_st *kek,
void* output, size_t *output_size, const void* iv, size_t iv_size)
{
size_t key_size, n;
@@ -594,7 +596,8 @@ int ret;
goto fail;
}
if (nla_strcmp(nla, NCR_WALG_AES_RFC3394) == 0)
- ret = wrap_aes(wkey, key, data, &data_size, iv, iv_size);
+ ret = wrap_aes_rfc3394(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);
@@ -649,7 +652,7 @@ int ret;
goto fail;
}
- if (!(key->flags & NCR_KEY_FLAG_WRAPPING)) {
+ if (!(key->flags & NCR_KEY_FLAG_UNWRAPPING)) {
err();
ret = -EPERM;
goto fail;
@@ -823,11 +826,27 @@ fail:
return ret;
}
+#define DER_KEY_MAX_SIZE (KEY_DATA_MAX_SIZE+16)
+
+/* Packed data are DER encoded:
+ * PackedData ::= SEQUENCE {
+ * version INTEGER { v1(0) }
+ * type INTEGER { secret_key(0), rsa_privkey(1), rsa_pubkey(2), dsa_privkey(3), dsa_pubkey(4),
+ * dh_privkey(5), dh_pubkey(6) },
+ * data OCTET STRING
+ * }
+ *
+ * This allows distinguishing types of wrapped keys.
+ */
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;
+ uint8_t * pkey = NULL;
+ uint8_t * derkey = NULL;
+ uint32_t pkey_size;
+ int ret, err;
+ unsigned long version = KEY_WRAP_VERSION;
+ unsigned long type;
+ unsigned long derlen;
*sdata_size = KEY_DATA_MAX_SIZE;
pkey = kmalloc(*sdata_size, GFP_KERNEL);
@@ -836,55 +855,180 @@ static int key_to_packed_data( uint8_t** sdata, size_t * sdata_size, const struc
return -ENOMEM;
}
+ derlen = DER_KEY_MAX_SIZE;
+ derkey = kmalloc(derlen, GFP_KERNEL);
+ if (derkey == NULL) {
+ err();
+ goto fail;
+ }
+
if (key->type == NCR_KEY_TYPE_SECRET) {
memcpy(pkey, key->key.secret.data, key->key.secret.size);
- *sdata_size = key->key.secret.size;
+ pkey_size = key->key.secret.size;
+
+ type = 0;
} else if (key->type == NCR_KEY_TYPE_PRIVATE || key->type == NCR_KEY_TYPE_PUBLIC) {
- usize = *sdata_size;
- ret = ncr_pk_pack( key, pkey, &usize);
+ pkey_size = *sdata_size;
+ ret = ncr_pk_pack( key, pkey, &pkey_size);
if (ret < 0) {
err();
goto fail;
}
- *sdata_size = usize;
+
+ switch (key->algorithm->algo) {
+ case NCR_ALG_RSA:
+ if (key->type == NCR_KEY_TYPE_PUBLIC)
+ type = 2;
+ else type = 1;
+ break;
+ case NCR_ALG_DSA:
+ if (key->type == NCR_KEY_TYPE_PUBLIC)
+ type = 4;
+ else type = 3;
+ break;
+ case NCR_ALG_DH:
+ if (key->type == NCR_KEY_TYPE_PUBLIC)
+ type = 6;
+ else type = 5;
+ break;
+ default:
+ /* unsupported yet */
+ ret = -EINVAL;
+ err();
+ goto fail;
+ }
+
} else {
err();
ret = -EINVAL;
goto fail;
}
- *sdata = (void*)pkey;
+ err = der_encode_sequence_multi(derkey, &derlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &version,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &type,
+ LTC_ASN1_OCTET_STRING, (unsigned long)pkey_size, pkey,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+ kfree(pkey);
+
+ if (err != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(err);
+ goto fail;
+ }
+
+ *sdata = (void*)derkey;
+ *sdata_size = derlen;
return 0;
fail:
kfree(pkey);
+ kfree(derkey);
return ret;
}
+inline static int packed_type_to_key_type(unsigned long type, struct key_item_st* key)
+{
+ switch(type) {
+ case 0:
+ key->type = NCR_KEY_TYPE_SECRET;
+ key->algorithm = _ncr_algo_to_properties("cbc(aes)");
+ break;
+ case 1:
+ key->type = NCR_KEY_TYPE_PRIVATE;
+ key->algorithm = _ncr_algo_to_properties("rsa");
+ break;
+ case 2:
+ key->type = NCR_KEY_TYPE_PUBLIC;
+ key->algorithm = _ncr_algo_to_properties("rsa");
+ break;
+ case 3:
+ key->type = NCR_KEY_TYPE_PRIVATE;
+ key->algorithm = _ncr_algo_to_properties("dsa");
+ break;
+ case 4:
+ key->type = NCR_KEY_TYPE_PUBLIC;
+ key->algorithm = _ncr_algo_to_properties("dsa");
+ break;
+ case 5:
+ key->type = NCR_KEY_TYPE_PRIVATE;
+ key->algorithm = _ncr_algo_to_properties("dh");
+ break;
+ case 6:
+ key->type = NCR_KEY_TYPE_PUBLIC;
+ key->algorithm = _ncr_algo_to_properties("dh");
+ break;
+ default:
+ err();
+ return -EINVAL;
+ }
+
+ if (key->algorithm == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+
+/* Unpack, or better decode the DER data
+ */
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;
+ ltc_asn1_list list[6];
+ int ret, i = 0, pkey_size, err;
+ unsigned long version, type;
+ uint8_t * pkey = NULL;
- if (data_size > KEY_DATA_MAX_SIZE) {
+ if (data_size > DER_KEY_MAX_SIZE) {
err();
return -EINVAL;
}
- key->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]);
- if (key->algorithm == NULL) {
+ pkey_size = KEY_DATA_MAX_SIZE;
+ pkey = kmalloc(pkey_size, GFP_KERNEL);
+ if (pkey == NULL) {
err();
- return -EINVAL;
+ return -ENOMEM;
}
- nla = tb[NCR_ATTR_KEY_TYPE];
- if (tb == NULL) {
+ list[i].type = LTC_ASN1_SHORT_INTEGER;
+ list[i].size = 1;
+ list[i++].data = &version;
+
+ list[i].type = LTC_ASN1_SHORT_INTEGER;
+ list[i].size = 1;
+ list[i++].data = &type;
+
+ list[i].type = LTC_ASN1_OCTET_STRING;
+ list[i].size = pkey_size;
+ list[i++].data = pkey;
+
+ err = der_decode_sequence(data, data_size, list, i);
+ if (err != CRYPT_OK) {
err();
- return -EINVAL;
+ ret = _ncr_tomerr(err);
+ goto fail;
+ }
+
+ if (version != KEY_WRAP_VERSION) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ pkey_size = list[2].size;
+
+ ret = packed_type_to_key_type(type, key);
+ if (ret < 0) {
+ err();
+ goto fail;
}
- key->type = nla_get_u32(nla);
ret = ncr_key_update_flags(key, tb[NCR_ATTR_KEY_FLAGS]);
if (ret != 0) {
@@ -897,12 +1041,12 @@ static int key_from_packed_data(struct nlattr *tb[], struct key_item_st *key,
err();
return -EINVAL;
}
- key->key.secret.size = data_size;
- memcpy(key->key.secret.data, data, data_size);
+ key->key.secret.size = pkey_size;
+ memcpy(key->key.secret.data, pkey, pkey_size);
} else if (key->type == NCR_KEY_TYPE_PUBLIC
|| key->type == NCR_KEY_TYPE_PRIVATE) {
- ret = ncr_pk_unpack( key, data, data_size);
+ ret = ncr_pk_unpack( key, pkey, pkey_size);
if (ret < 0) {
err();
return ret;
@@ -912,5 +1056,10 @@ static int key_from_packed_data(struct nlattr *tb[], struct key_item_st *key,
return -EINVAL;
}
- return 0;
+ ret = 0;
+
+fail:
+ kfree(pkey);
+
+ return ret;
}
diff --git a/ncr-key.c b/ncr-key.c
index ca8ab5f80de..406e03299c3 100644
--- a/ncr-key.c
+++ b/ncr-key.c
@@ -294,7 +294,8 @@ int ncr_key_update_flags(struct key_item_st* item, const struct nlattr *nla)
if (nla == NULL)
return 0;
flags = nla_get_u32(nla);
- if (!capable(CAP_SYS_ADMIN) && (flags & NCR_KEY_FLAG_WRAPPING) != 0)
+ if (!capable(CAP_SYS_ADMIN)
+ && (flags & (NCR_KEY_FLAG_WRAPPING | NCR_KEY_FLAG_UNWRAPPING)) != 0)
return -EPERM;
item->flags = flags;
return 0;
@@ -743,7 +744,7 @@ struct key_item_st* newkey = NULL;
/* wrapping keys cannot be used for anything except wrapping.
*/
- if (key->flags & NCR_KEY_FLAG_WRAPPING) {
+ if (key->flags & NCR_KEY_FLAG_WRAPPING || key->flags & NCR_KEY_FLAG_UNWRAPPING) {
err();
ret = -EINVAL;
goto fail;
diff --git a/ncr-sessions.c b/ncr-sessions.c
index aa9026d32e9..0e48865c599 100644
--- a/ncr-sessions.c
+++ b/ncr-sessions.c
@@ -429,7 +429,7 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists,
/* wrapping keys cannot be used for encryption or decryption
*/
- if (ns->key->flags & NCR_KEY_FLAG_WRAPPING) {
+ if (ns->key->flags & NCR_KEY_FLAG_WRAPPING || ns->key->flags & NCR_KEY_FLAG_UNWRAPPING) {
err();
ret = -EINVAL;
goto fail;
@@ -519,7 +519,7 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists,
/* wrapping keys cannot be used for anything except wrapping.
*/
- if (ns->key->flags & NCR_KEY_FLAG_WRAPPING) {
+ if (ns->key->flags & NCR_KEY_FLAG_WRAPPING || ns->key->flags & NCR_KEY_FLAG_UNWRAPPING) {
err();
ret = -EINVAL;
goto fail;
diff --git a/ncr.h b/ncr.h
index 3c416ebe1a6..c248c6c87f1 100644
--- a/ncr.h
+++ b/ncr.h
@@ -95,10 +95,13 @@ typedef __s32 ncr_key_t;
*/
#define NCR_KEY_FLAG_DECRYPT (1<<2)
#define NCR_KEY_FLAG_SIGN (1<<3)
-/* This flag can only be set by administrator, to prevent
+#define NCR_KEY_FLAG_ENCRYPT (1<<4)
+#define NCR_KEY_FLAG_VERIFY (1<<5)
+/* These flags can only be set by administrator, to prevent
* adversaries exporting wrappable keys with random ones.
*/
-#define NCR_KEY_FLAG_WRAPPING (1<<4)
+#define NCR_KEY_FLAG_WRAPPING (1<<6)
+#define NCR_KEY_FLAG_UNWRAPPING (1<<7)
struct ncr_key_generate {
__u32 input_size, output_size;