summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-08-31 00:19:06 +0200
committerMiloslav Trmač <mitr@redhat.com>2010-09-07 00:02:05 +0200
commit9cf934e1a057a8dc4f36a1ad8d2822fb116374dd (patch)
tree4f66b07f3e56787d4d44c0ba536259e94914e434
parent71cf9b0659c55ad0e695e98190c742ae39bcee23 (diff)
downloadkernel-crypto-9cf934e1a057a8dc4f36a1ad8d2822fb116374dd.tar.gz
kernel-crypto-9cf934e1a057a8dc4f36a1ad8d2822fb116374dd.tar.xz
kernel-crypto-9cf934e1a057a8dc4f36a1ad8d2822fb116374dd.zip
Implement AUDIT_CRYPTO_KEY_VALUEncr-audit
-rw-r--r--crypto/userspace/ncr-key.c8
-rw-r--r--crypto/userspace/ncr-pk.c64
-rw-r--r--crypto/userspace/ncr-pk.h5
-rw-r--r--include/linux/audit.h18
-rw-r--r--kernel/auditsc.c116
5 files changed, 197 insertions, 14 deletions
diff --git a/crypto/userspace/ncr-key.c b/crypto/userspace/ncr-key.c
index e614f687075..e6f7f025848 100644
--- a/crypto/userspace/ncr-key.c
+++ b/crypto/userspace/ncr-key.c
@@ -415,6 +415,9 @@ void ncr_key_clear(struct key_item_st* item)
NULL, ncr_algorithm_name(item->algorithm),
item->desc, item->key_id, item->key_id_size, -1,
NULL, 0);
+ if (item->type == NCR_KEY_TYPE_PRIVATE ||
+ item->type == NCR_KEY_TYPE_PUBLIC)
+ ncr_pk_audit_values(item);
/* clears any previously allocated parameters */
if (item->type == NCR_KEY_TYPE_PRIVATE ||
@@ -500,6 +503,9 @@ fail:
audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_GEN, lst->id, -1, NULL,
ncr_algorithm_name(algo), item->desc, item->key_id,
item->key_id_size, -1, NULL, 0);
+ if (item->type == NCR_KEY_TYPE_PUBLIC
+ || item->type == NCR_KEY_TYPE_PRIVATE)
+ ncr_pk_audit_values(item);
if (ret < 0) item->type = NCR_KEY_TYPE_INVALID;
_ncr_key_item_put(item);
@@ -746,6 +752,8 @@ fail:
public != NULL ? public->desc : -1,
public != NULL ? public->key_id : NULL,
public != NULL ? public->key_id_size : 0);
+ if (public != NULL && ret >= 0)
+ ncr_pk_audit_values(public);
if (public) {
if (ret < 0) public->type = NCR_KEY_TYPE_INVALID;
diff --git a/crypto/userspace/ncr-pk.c b/crypto/userspace/ncr-pk.c
index 3dc589a6a05..c858c2aeb18 100644
--- a/crypto/userspace/ncr-pk.c
+++ b/crypto/userspace/ncr-pk.c
@@ -22,6 +22,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include <linux/audit.h>
#include <linux/ioctl.h>
#include <linux/mm.h>
#include <linux/ncr.h>
@@ -338,6 +339,69 @@ fail:
return 0;
}
+#ifdef CONFIG_AUDIT
+static int
+set_crypto_value(struct audit_crypto_value *dst, char name, mp_int *src)
+{
+ int cret;
+
+ dst->name = name;
+ dst->value_size = mp_unsigned_bin_size(src);
+ dst->value = kmalloc(dst->value_size, GFP_KERNEL);
+ cret = mp_to_unsigned_bin(src, dst->value);
+ if (cret != CRYPT_OK) {
+ kfree(dst->value);
+ return _ncr_tomerr(cret);
+ }
+ return 0;
+}
+
+void ncr_pk_audit_values(struct key_item_st *key)
+{
+ struct audit_crypto_value v[4];
+ size_t i;
+
+ i = 0;
+ switch (key->algorithm->algo) {
+#define VALUE(NAME, MPI) \
+ do { \
+ if (set_crypto_value(v + i, (NAME), (MPI)) != 0) \
+ goto free_it; \
+ i++; \
+ } while (0)
+
+ case NCR_ALG_RSA:
+ VALUE('n', &key->key.pk.rsa.N);
+ VALUE('e', &key->key.pk.rsa.e);
+ break;
+
+ case NCR_ALG_DSA:
+ VALUE('p', &key->key.pk.dsa.p);
+ VALUE('q', &key->key.pk.dsa.q);
+ VALUE('g', &key->key.pk.dsa.g);
+ VALUE('y', &key->key.pk.dsa.y);
+ break;
+
+ case NCR_ALG_DH:
+ VALUE('y', &key->key.pk.dh.y);
+ break;
+
+ default:
+ return;
+#undef VALUE
+ }
+ audit_log_crypto_values(v, i);
+ return;
+
+free_it:
+ while (i != 0) {
+ i--;
+ kfree(v[i].value);
+ }
+}
+#endif
+
+
/* Encryption/Decryption
*/
diff --git a/crypto/userspace/ncr-pk.h b/crypto/userspace/ncr-pk.h
index fb9aba5b5ee..1d4b8067d36 100644
--- a/crypto/userspace/ncr-pk.h
+++ b/crypto/userspace/ncr-pk.h
@@ -25,6 +25,11 @@ int ncr_pk_generate(const struct algo_properties_st *algo, struct nlattr *tb[],
struct key_item_st* private, struct key_item_st* public);
int ncr_pk_pack( const struct key_item_st * key, uint8_t * packed, uint32_t * packed_size);
int ncr_pk_unpack( struct key_item_st * key, const void * packed, size_t packed_size);
+#ifdef CONFIG_AUDIT
+void ncr_pk_audit_values(struct key_item_st *key);
+#else
+#define ncr_pk_audit_values(key) ((void)0)
+#endif
/* encryption/decryption */
int ncr_pk_cipher_init(const struct algo_properties_st *algo,
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 54cb007e340..cfb33639566 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -124,6 +124,8 @@
#define AUDIT_CRYPTO_STORAGE_KEY 1600 /* Key storage key configured */
#define AUDIT_CRYPTO_USERSPACE_OP 1601 /* User-space crypto operation */
+#define AUDIT_CRYPTO_KEY_VALUE 1602 /* Public values of a key, immediatelly
+ follows USERSPACE_OP. */
#define AUDIT_FIRST_KERN_ANOM_MSG 1700
#define AUDIT_LAST_KERN_ANOM_MSG 1799
@@ -422,6 +424,12 @@ struct audit_field {
void *lsm_rule;
};
+struct audit_crypto_value {
+ char name;
+ void *value;
+ size_t value_size;
+};
+
#define AUDITSC_INVALID 0
#define AUDITSC_SUCCESS 1
#define AUDITSC_FAILURE 2
@@ -501,6 +509,8 @@ extern int __audit_log_crypto_op(int op, int context, int session,
const char *operation, const char *algorithm,
int key1, void *key1_id, size_t key1_id_size,
int key2, void *key2_id, size_t key2_id_size);
+extern void __audit_log_crypto_values(const struct audit_crypto_value *values,
+ size_t num_values);
static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
{
@@ -568,6 +578,13 @@ static inline int audit_log_crypto_op(int op, int context, int session,
key2_id_size);
}
+static inline void audit_log_crypto_values(const struct audit_crypto_value *a,
+ size_t num_values)
+{
+ if (unlikely(!audit_dummy_context()))
+ __audit_log_crypto_values(a, num_values);
+}
+
extern int audit_n_rules;
extern int audit_signals;
#else
@@ -602,6 +619,7 @@ extern int audit_signals;
#define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; })
#define audit_log_capset(pid, ncr, ocr) ((void)0)
#define audit_log_crypto_op(op, ctx, sess, k1, id1, size1, k2, id2, size2) (0)
+#define audit_log_crypto_values(a, values, num_values) ((void)0)
#define audit_ptrace(t) ((void)0)
#define audit_n_rules 0
#define audit_signals 0
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index fcd6d2e7ab9..30853986ab9 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -81,6 +81,9 @@
/* no execve audit message should be longer than this (userspace limits) */
#define MAX_EXECVE_AUDIT_LEN 7500
+/* Number of public key values that can be audited */
+#define AUDIT_MAX_CRYPTO_KEY_VALUES 4
+
/* number of audit rules */
int audit_n_rules;
@@ -158,9 +161,14 @@ struct audit_aux_data_capset {
struct audit_cap_data cap;
};
-struct audit_crypto_op {
+#define AUDIT_CRYPTO_OP_KEY_VALUE -1
+struct audit_crypto_header {
struct list_head list;
- int op;
+ int op; /* AUDIT_CRYPTO_OP_KEY_VALUE for key values */
+};
+
+struct audit_crypto_op {
+ struct audit_crypto_header hdr;
int context;
int session;
const char *operation;
@@ -173,6 +181,12 @@ struct audit_crypto_op {
size_t key2_id_size;
};
+struct audit_crypto_values {
+ struct audit_crypto_header hdr;
+ size_t num_values;
+ struct audit_crypto_value values[AUDIT_MAX_CRYPTO_KEY_VALUES];
+};
+
struct audit_tree_refs {
struct audit_tree_refs *next;
struct audit_chunk *c[31];
@@ -650,11 +664,13 @@ static int audit_filter_rules(struct task_struct *tsk,
result = audit_match_filetype(ctx, f->val);
break;
case AUDIT_CRYPTO_OP: {
- struct audit_crypto_op *ax;
+ struct audit_crypto_header *ax;
if (!ctx)
break;
list_for_each_entry(ax, &ctx->crypto, list) {
+ if (ax->op == AUDIT_CRYPTO_OP_KEY_VALUE)
+ continue;
result = audit_comparator(ax->op, f->op,
f->val);
if (result)
@@ -854,10 +870,23 @@ static inline void audit_free_names(struct audit_context *context)
context->pwd.mnt = NULL;
}
+static void audit_free_crypto_op(struct audit_crypto_header *crypto)
+{
+ if (crypto->op == AUDIT_CRYPTO_OP_KEY_VALUE) {
+ struct audit_crypto_values *val;
+ size_t i;
+
+ val = (struct audit_crypto_values *)crypto;
+ for (i = 0; i < val->num_values; i++)
+ kfree(val->values[i].value);
+ }
+ kfree(crypto);
+}
+
static inline void audit_free_aux(struct audit_context *context)
{
struct audit_aux_data *aux;
- struct audit_crypto_op *crypto, *tmp;
+ struct audit_crypto_header *crypto, *tmp;
while ((aux = context->aux)) {
context->aux = aux->next;
@@ -869,7 +898,7 @@ static inline void audit_free_aux(struct audit_context *context)
}
list_for_each_entry_safe(crypto, tmp, &context->crypto, list) {
list_del(&crypto->list);
- kfree(crypto);
+ audit_free_crypto_op(crypto);
}
}
@@ -1347,7 +1376,7 @@ static void show_special(struct audit_context *context, int *call_panic)
}
static void log_crypto_op(struct audit_context *context,
- struct audit_crypto_op *crypto)
+ const struct audit_crypto_header *header)
{
static const char *const ops[] = {
[AUDIT_CRYPTO_OP_CONTEXT_NEW] = "context_new",
@@ -1365,15 +1394,17 @@ static void log_crypto_op(struct audit_context *context,
[AUDIT_CRYPTO_OP_KEY_GET_INFO] = "key_get_info",
};
+ const struct audit_crypto_op *crypto;
struct audit_buffer *ab;
+ crypto = (struct audit_crypto_op *)header;
ab = audit_log_start(context, GFP_KERNEL, AUDIT_CRYPTO_USERSPACE_OP);
if (!ab)
return;
- if (crypto->op < ARRAY_SIZE(ops) && ops[crypto->op] != NULL)
- audit_log_format(ab, "crypto_op=%s", ops[crypto->op]);
+ if (header->op < ARRAY_SIZE(ops) && ops[header->op] != NULL)
+ audit_log_format(ab, "crypto_op=%s", ops[header->op]);
else
- audit_log_format(ab, "crypto_op=%d", crypto->op);
+ audit_log_format(ab, "crypto_op=%d", header->op);
audit_log_format(ab, " ctx=%d", crypto->context);
if (crypto->session != -1)
audit_log_format(ab, " session=%d", crypto->session);
@@ -1404,13 +1435,31 @@ static void log_crypto_op(struct audit_context *context,
audit_log_end(ab);
}
+static void log_crypto_values(struct audit_context *context,
+ const struct audit_crypto_header *header)
+{
+ struct audit_buffer *ab;
+ const struct audit_crypto_values *crypto;
+ const struct audit_crypto_value *v;
+
+ crypto = (struct audit_crypto_values *)header;
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_CRYPTO_KEY_VALUE);
+ if (!ab)
+ return;
+ for (v = crypto->values; v < crypto->values + crypto->num_values; v++) {
+ audit_log_format(ab, " key_value_%c=", v->name);
+ audit_log_n_hex(ab, v->value, v->value_size);
+ }
+ audit_log_end(ab);
+}
+
static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
{
const struct cred *cred;
int i, call_panic = 0;
struct audit_buffer *ab;
struct audit_aux_data *aux;
- struct audit_crypto_op *crypto;
+ struct audit_crypto_header *crypto;
const char *tty;
/* tsk == current */
@@ -1537,8 +1586,12 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
call_panic = 1;
}
- list_for_each_entry(crypto, &context->crypto, list)
- log_crypto_op(context, crypto);
+ list_for_each_entry(crypto, &context->crypto, list) {
+ if (crypto->op != AUDIT_CRYPTO_OP_KEY_VALUE)
+ log_crypto_op(context, crypto);
+ else
+ log_crypto_values(context, crypto);
+ }
if (context->target_pid &&
audit_log_pid_context(context, context->target_pid,
@@ -2609,7 +2662,7 @@ int __audit_log_crypto_op(int op, int context, int session,
if (!ax)
return -ENOMEM;
- ax->op = op;
+ ax->hdr.op = op;
ax->context = context;
ax->session = session;
ax->operation = operation;
@@ -2626,12 +2679,47 @@ int __audit_log_crypto_op(int op, int context, int session,
memcpy(ax->key2_id, key2_id, ax->key2_id_size);
} else
ax->key2_id_size = 0;
- list_add_tail(&ax->list, &ctx->crypto);
+ list_add_tail(&ax->hdr.list, &ctx->crypto);
return 0;
}
EXPORT_SYMBOL_GPL(__audit_log_crypto_op);
/**
+ * __audit_log_crypto_op - store information about values of crypto keys
+ * @values: individual byte arrays describing the key. The "value" members
+ * must be allocated using kmalloc(), this function will take care of freeing
+ * them.
+ * @num_values: number of elements in @values
+ */
+void __audit_log_crypto_values(const struct audit_crypto_value *values,
+ size_t num_values)
+{
+ struct audit_crypto_values *ax;
+ struct audit_context *ctx = current->audit_context;
+ size_t i;
+
+ ax = kmalloc(sizeof(*ax), GFP_KERNEL);
+ if (!ax)
+ goto free_values;
+
+ ax->hdr.op = AUDIT_CRYPTO_OP_KEY_VALUE;
+ BUG_ON(num_values > ARRAY_SIZE(ax->values));
+ ax->num_values = num_values;
+ for (i = 0; i < num_values; i++) {
+ ax->values[i].name = values[i].name;
+ ax->values[i].value = values[i].value;
+ ax->values[i].value_size = values[i].value_size;
+ }
+ list_add_tail(&ax->hdr.list, &ctx->crypto);
+ return;
+
+free_values:
+ for (i = 0; i < num_values; i++)
+ kfree(values[i].value);
+}
+EXPORT_SYMBOL_GPL(__audit_log_crypto_values);
+
+/**
* audit_core_dumps - record information about processes that end abnormally
* @signr: signal value
*