summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/ncr.c85
-rw-r--r--ncr-int.h4
-rw-r--r--ncr-key.c54
-rw-r--r--ncr.c21
-rw-r--r--ncr.h17
-rw-r--r--utils.c2
6 files changed, 157 insertions, 26 deletions
diff --git a/examples/ncr.c b/examples/ncr.c
index 568b63c..b999003 100644
--- a/examples/ncr.c
+++ b/examples/ncr.c
@@ -46,10 +46,22 @@ test_ncr_key(int cfd)
struct nlattr bits_head ALIGN_NL;
uint32_t bits ALIGN_NL;
} kgen;
+ struct __attribute__((packed)) {
+ struct ncr_key_get_info f;
+ /* This union is only here to stop gcc from complaining about
+ aliasing. */
+ union {
+ unsigned char __reserve[DATA_SIZE];
+ struct nlattr first_header;
+ } u ALIGN_NL;
+ } kinfo;
+ struct nlattr *nla;
ncr_key_t key;
struct ncr_key_data_st keydata;
uint8_t data[KEY_DATA_SIZE];
uint8_t data_bak[KEY_DATA_SIZE];
+ uint16_t *attr_p;
+ int got_algo, got_flags, got_type;
fprintf(stdout, "Tests on Keys:\n");
@@ -174,6 +186,79 @@ test_ncr_key(int cfd)
return 1;
}
+ memset(&kinfo.f, 0, sizeof(kinfo.f));
+ kinfo.f.output_size = sizeof(kinfo);
+ kinfo.f.key = key;
+ nla = &kinfo.u.first_header;
+ nla->nla_type = NCR_ATTR_WANTED_ATTRS;
+ attr_p = (uint16_t *)((char *)nla + NLA_HDRLEN);
+ *attr_p++ = NCR_ATTR_ALGORITHM;
+ *attr_p++ = NCR_ATTR_KEY_FLAGS;
+ *attr_p++ = NCR_ATTR_KEY_TYPE;
+ nla->nla_len = (char *)attr_p - (char *)nla;
+ kinfo.f.input_size = (char *)attr_p - (char *)&kinfo;
+
+ if (ioctl(cfd, NCRIO_KEY_GET_INFO, &kinfo)) {
+ fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
+ perror("ioctl(NCRIO_KEY_GET_INFO)");
+ return 1;
+ }
+
+ got_algo = got_flags = got_type = 0;
+ if (kinfo.f.output_size <
+ (char *)&kinfo.u.first_header - (char *)&kinfo) {
+ fprintf(stderr, "No nlattr returned\n");
+ return 1;
+ }
+ nla = &kinfo.u.first_header;
+ for (;;) {
+ void *data;
+
+ if (nla->nla_len < NLA_HDRLEN + sizeof(uint32_t)) {
+ fprintf(stderr, "Attribute too small\n");
+ return 1;
+ }
+ if (nla->nla_len >
+ kinfo.f.output_size - ((char *)nla - (char *)&kinfo)) {
+ fprintf(stderr, "Attributes overflow\n");
+ return 1;
+ }
+ data = (char *)nla + NLA_HDRLEN;
+ switch (nla->nla_type) {
+ case NCR_ATTR_ALGORITHM:
+ if (*(uint32_t *)data != NCR_ALG_AES_CBC) {
+ fprintf(stderr, "Unexpected algorithm\n");
+ return 1;
+ }
+ got_algo++;
+ break;
+ case NCR_ATTR_KEY_FLAGS:
+ if (*(uint32_t *)data != NCR_KEY_FLAG_EXPORTABLE) {
+ fprintf(stderr, "Unexpected key flags\n");
+ return 1;
+ }
+ got_flags++;
+ break;
+ case NCR_ATTR_KEY_TYPE:
+ if (*(uint32_t *)data != NCR_KEY_TYPE_SECRET) {
+ fprintf(stderr, "Unexpected key type\n");
+ return 1;
+ }
+ got_type++;
+ break;
+ }
+
+ if (NLA_ALIGN(nla->nla_len) + NLA_HDRLEN >
+ kinfo.f.output_size - ((char *)nla - (char *)&kinfo))
+ break;
+ nla = (struct nlattr *)((char *)nla + NLA_ALIGN(nla->nla_len));
+ }
+ if (got_algo != 1 || got_flags != 1 || got_type != 1) {
+ fprintf(stderr, "Unexpected attrs - %d, %d, %d\n", got_algo,
+ got_flags, got_type);
+ return 1;
+ }
+
if (ioctl(cfd, NCRIO_KEY_DEINIT, &key)) {
fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__);
perror("ioctl(NCRIO_KEY_DEINIT)");
diff --git a/ncr-int.h b/ncr-int.h
index 0ae042b..9330abf 100644
--- a/ncr-int.h
+++ b/ncr-int.h
@@ -15,6 +15,7 @@
#define err() printk(KERN_DEBUG"ncr: %s: %s: %d\n", __FILE__, __func__, __LINE__)
struct nlattr;
+struct ncr_out;
struct algo_properties_st {
ncr_algorithm_t algo;
@@ -125,7 +126,8 @@ int ncr_key_import(struct ncr_lists *lst, void __user* arg);
void ncr_key_list_deinit(struct ncr_lists *lst);
int ncr_key_generate(struct ncr_lists *lst, const struct ncr_key_generate *gen,
struct nlattr *tb[]);
-int ncr_key_info(struct ncr_lists *lst, void __user* arg);
+int ncr_key_get_info(struct ncr_lists *lst, struct ncr_out *out,
+ const struct ncr_key_get_info *info, struct nlattr *tb[]);
int ncr_key_generate_pair(struct ncr_lists *lst,
const struct ncr_key_generate_pair *gen,
diff --git a/ncr-key.c b/ncr-key.c
index 15e90fe..b0e8a97 100644
--- a/ncr-key.c
+++ b/ncr-key.c
@@ -31,6 +31,7 @@
#include <net/netlink.h>
#include "ncr.h"
#include "ncr-int.h"
+#include "utils.h"
static int key_list_deinit_fn(int id, void *item, void *unused)
{
@@ -599,18 +600,15 @@ int bits;
}
}
-int ncr_key_info(struct ncr_lists *lst, void __user* arg)
+int ncr_key_get_info(struct ncr_lists *lst, struct ncr_out *out,
+ const struct ncr_key_get_info *info, struct nlattr *tb[])
{
-struct ncr_key_info_st info;
+const struct nlattr *nla;
+const u16 *attr, *attr_end;
struct key_item_st* item = NULL;
int ret;
- if (unlikely(copy_from_user(&info, arg, sizeof(info)))) {
- err();
- return -EFAULT;
- }
-
- ret = ncr_key_item_get_read(&item, lst, info.key);
+ ret = ncr_key_item_get_read(&item, lst, info->key);
if (ret < 0) {
err();
return ret;
@@ -622,11 +620,41 @@ int ret;
goto fail;
}
- info.flags = item->flags;
- info.type = item->type;
- info.algorithm = item->algorithm->algo;
-
- ret = 0;
+ nla = tb[NCR_ATTR_WANTED_ATTRS];
+ if (nla == NULL || nla_len(nla) % sizeof(u16) != 0) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ attr = nla_data(nla);
+ attr_end = attr + nla_len(nla) / sizeof(u16);
+ while (attr < attr_end) {
+ switch (*attr) {
+ case NCR_ATTR_KEY_FLAGS:
+ ret = ncr_out_put_u32(out, *attr, item->flags);
+ break;
+ case NCR_ATTR_KEY_TYPE:
+ ret = ncr_out_put_u32(out, *attr, item->type);
+ break;
+ case NCR_ATTR_ALGORITHM:
+ ret = ncr_out_put_u32(out, *attr,
+ item->algorithm->algo);
+ break;
+ default:
+ break; /* Silently ignore */
+ }
+ if (ret != 0) {
+ err();
+ goto fail;
+ }
+ attr++;
+ }
+
+ ret = ncr_out_finish(out);
+ if (ret != 0) {
+ err();
+ goto fail;
+ }
fail:
_ncr_key_item_put( item);
diff --git a/ncr.c b/ncr.c
index 7f905f2..796ca32 100644
--- a/ncr.c
+++ b/ncr.c
@@ -148,14 +148,30 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_)
CASE_NO_OUTPUT(NCRIO_KEY_GENERATE_PAIR, ncr_key_generate_pair,
ncr_key_generate_pair);
CASE_NO_OUTPUT(NCRIO_KEY_DERIVE, ncr_key_derive, ncr_key_derive);
+ case NCRIO_KEY_GET_INFO: {
+ struct ncr_key_get_info data;
+ struct ncr_out out;
+
+ attr_buf = NCR_GET_INPUT_ARGS(&data, tb, arg);
+ if (IS_ERR(attr_buf)) {
+ err();
+ return PTR_ERR(attr_buf);
+ }
+ ret = NCR_OUT_INIT(&out, &data, arg);
+ if (ret != 0) {
+ err();
+ break;
+ }
+ ret = ncr_key_get_info(lst, &out, &data, tb);
+ ncr_out_free(&out);
+ break;
+ }
case NCRIO_KEY_DEINIT:
return ncr_key_deinit(lst, arg);
case NCRIO_KEY_EXPORT:
return ncr_key_export(lst, arg);
case NCRIO_KEY_IMPORT:
return ncr_key_import(lst, arg);
- case NCRIO_KEY_GET_INFO:
- return ncr_key_info(lst, arg);
case NCRIO_KEY_WRAP:
return ncr_key_wrap(lst, arg);
case NCRIO_KEY_UNWRAP:
@@ -195,6 +211,7 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_)
case NCRIO_KEY_GENERATE:
case NCRIO_KEY_GENERATE_PAIR:
case NCRIO_KEY_DERIVE:
+ case NCRIO_KEY_GET_INFO:
return ncr_ioctl(lst, cmd, arg_);
default:
return -EINVAL;
diff --git a/ncr.h b/ncr.h
index 34caa61..d4d1d6a 100644
--- a/ncr.h
+++ b/ncr.h
@@ -34,6 +34,7 @@ enum {
NCR_ATTR_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */
NCR_ATTR_DERIVATION_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */
NCR_ATTR_KEY_FLAGS, /* NLA_U32 - NCR_KEY_FLAG_* */
+ NCR_ATTR_KEY_TYPE, /* NLA_U32 - ncr_key_type_t */
NCR_ATTR_SECRET_KEY_BITS, /* NLA_U32 */
NCR_ATTR_RSA_MODULUS_BITS, /* NLA_U32 */
NCR_ATTR_RSA_E, /* NLA_BINARY */
@@ -42,6 +43,7 @@ enum {
NCR_ATTR_DH_PRIME, /* NLA_BINARY */
NCR_ATTR_DH_BASE, /* NLA_BINARY */
NCR_ATTR_DH_PUBLIC, /* NLA_BINARY */
+ NCR_ATTR_WANTED_ATTRS, /* NLA_BINARY - array of u16 IDs */
/* Add new attributes here */
@@ -174,15 +176,10 @@ struct ncr_key_derive {
#define MAX_KEY_ID_SIZE 20
-struct ncr_key_info_st {
- ncr_key_t key; /* input */
-
- unsigned int flags;
- ncr_key_type_t type;
- ncr_algorithm_t algorithm; /* valid for public/private keys */
-
- __u8 key_id[MAX_KEY_ID_SIZE];
- __kernel_size_t key_id_size;
+struct ncr_key_get_info {
+ __u32 input_size, output_size;
+ ncr_key_t key;
+ __NL_ATTRIBUTES;
};
struct ncr_key_data_st {
@@ -207,7 +204,7 @@ struct ncr_key_data_st {
/* derive a new key from an old one */
#define NCRIO_KEY_DERIVE _IOWR('c', 207, struct ncr_key_derive)
/* return information on a key */
-#define NCRIO_KEY_GET_INFO _IOWR('c', 208, struct ncr_key_info_st)
+#define NCRIO_KEY_GET_INFO _IOWR('c', 208, struct ncr_key_get_info)
/* export a secret key */
#define NCRIO_KEY_EXPORT _IOWR('c', 209, struct ncr_key_data_st)
diff --git a/utils.c b/utils.c
index e96c72c..655dc82 100644
--- a/utils.c
+++ b/utils.c
@@ -32,6 +32,7 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = {
[NCR_ATTR_ALGORITHM] = { NLA_U32, 0 },
[NCR_ATTR_DERIVATION_ALGORITHM] = { NLA_U32, 0 },
[NCR_ATTR_KEY_FLAGS] = { NLA_U32, 0 },
+ [NCR_ATTR_KEY_TYPE] = { NLA_U32, 0 },
[NCR_ATTR_SECRET_KEY_BITS] = { NLA_U32, 0 },
[NCR_ATTR_RSA_MODULUS_BITS] = { NLA_U32, 0 },
[NCR_ATTR_RSA_E] = { NLA_BINARY, 0 },
@@ -40,6 +41,7 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = {
[NCR_ATTR_DH_PRIME] = { NLA_BINARY, 0 },
[NCR_ATTR_DH_BASE] = { NLA_BINARY, 0 },
[NCR_ATTR_DH_PUBLIC] = { NLA_BINARY, 0 },
+ [NCR_ATTR_WANTED_ATTRS] = { NLA_BINARY, 0 },
};
void *__ncr_get_input_args(void *fixed, struct nlattr *tb[], size_t fixed_size,