summaryrefslogtreecommitdiffstats
path: root/net/rxrpc
diff options
context:
space:
mode:
Diffstat (limited to 'net/rxrpc')
-rw-r--r--net/rxrpc/ar-internal.h11
-rw-r--r--net/rxrpc/rxkad.c47
-rw-r--r--net/rxrpc/security.c2
-rw-r--r--net/rxrpc/server_key.c56
4 files changed, 86 insertions, 30 deletions
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 6427bcfb4df5..6682c797b878 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -35,6 +35,7 @@ struct rxrpc_crypt {
#define rxrpc_queue_delayed_work(WS,D) \
queue_delayed_work(rxrpc_workqueue, (WS), (D))
+struct key_preparsed_payload;
struct rxrpc_connection;
/*
@@ -217,6 +218,15 @@ struct rxrpc_security {
/* Clean up a security service */
void (*exit)(void);
+ /* Parse the information from a server key */
+ int (*preparse_server_key)(struct key_preparsed_payload *);
+
+ /* Clean up the preparse buffer after parsing a server key */
+ void (*free_preparse_server_key)(struct key_preparsed_payload *);
+
+ /* Destroy the payload of a server key */
+ void (*destroy_server_key)(struct key *);
+
/* initialise a connection's security */
int (*init_connection_security)(struct rxrpc_connection *,
struct rxrpc_key_token *);
@@ -1050,6 +1060,7 @@ extern const struct rxrpc_security rxkad;
* security.c
*/
int __init rxrpc_init_security(void);
+const struct rxrpc_security *rxrpc_security_lookup(u8);
void rxrpc_exit_security(void);
int rxrpc_init_client_conn_security(struct rxrpc_connection *);
const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *,
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index 0d21935dac27..3057f00a6978 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -15,6 +15,7 @@
#include <linux/scatterlist.h>
#include <linux/ctype.h>
#include <linux/slab.h>
+#include <linux/key-type.h>
#include <net/sock.h>
#include <net/af_rxrpc.h>
#include <keys/rxrpc-type.h>
@@ -47,6 +48,49 @@ static struct skcipher_request *rxkad_ci_req;
static DEFINE_MUTEX(rxkad_ci_mutex);
/*
+ * Parse the information from a server key
+ *
+ * The data should be the 8-byte secret key.
+ */
+static int rxkad_preparse_server_key(struct key_preparsed_payload *prep)
+{
+ struct crypto_skcipher *ci;
+
+ if (prep->datalen != 8)
+ return -EINVAL;
+
+ memcpy(&prep->payload.data[2], prep->data, 8);
+
+ ci = crypto_alloc_skcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(ci)) {
+ _leave(" = %ld", PTR_ERR(ci));
+ return PTR_ERR(ci);
+ }
+
+ if (crypto_skcipher_setkey(ci, prep->data, 8) < 0)
+ BUG();
+
+ prep->payload.data[0] = ci;
+ _leave(" = 0");
+ return 0;
+}
+
+static void rxkad_free_preparse_server_key(struct key_preparsed_payload *prep)
+{
+
+ if (prep->payload.data[0])
+ crypto_free_skcipher(prep->payload.data[0]);
+}
+
+static void rxkad_destroy_server_key(struct key *key)
+{
+ if (key->payload.data[0]) {
+ crypto_free_skcipher(key->payload.data[0]);
+ key->payload.data[0] = NULL;
+ }
+}
+
+/*
* initialise connection security
*/
static int rxkad_init_connection_security(struct rxrpc_connection *conn,
@@ -1302,6 +1346,9 @@ const struct rxrpc_security rxkad = {
.no_key_abort = RXKADUNKNOWNKEY,
.init = rxkad_init,
.exit = rxkad_exit,
+ .preparse_server_key = rxkad_preparse_server_key,
+ .free_preparse_server_key = rxkad_free_preparse_server_key,
+ .destroy_server_key = rxkad_destroy_server_key,
.init_connection_security = rxkad_init_connection_security,
.prime_packet_security = rxkad_prime_packet_security,
.secure_packet = rxkad_secure_packet,
diff --git a/net/rxrpc/security.c b/net/rxrpc/security.c
index bef9971e15cd..50cb5f1ee0c0 100644
--- a/net/rxrpc/security.c
+++ b/net/rxrpc/security.c
@@ -55,7 +55,7 @@ void rxrpc_exit_security(void)
/*
* look up an rxrpc security module
*/
-static const struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
+const struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
{
if (security_index >= ARRAY_SIZE(rxrpc_security_types))
return NULL;
diff --git a/net/rxrpc/server_key.c b/net/rxrpc/server_key.c
index b75bda05120d..1a2f0b63ee1d 100644
--- a/net/rxrpc/server_key.c
+++ b/net/rxrpc/server_key.c
@@ -30,8 +30,8 @@ static void rxrpc_destroy_s(struct key *);
static void rxrpc_describe_s(const struct key *, struct seq_file *);
/*
- * rxrpc server defined keys take "<serviceId>:<securityIndex>" as the
- * description and an 8-byte decryption key as the payload
+ * rxrpc server keys take "<serviceId>:<securityIndex>[:<sec-specific>]" as the
+ * description and the key material as the payload.
*/
struct key_type key_type_rxrpc_s = {
.name = "rxrpc_s",
@@ -45,64 +45,62 @@ struct key_type key_type_rxrpc_s = {
};
/*
- * Vet the description for an RxRPC server key
+ * Vet the description for an RxRPC server key.
*/
static int rxrpc_vet_description_s(const char *desc)
{
- unsigned long num;
+ unsigned long service, sec_class;
char *p;
- num = simple_strtoul(desc, &p, 10);
- if (*p != ':' || num > 65535)
+ service = simple_strtoul(desc, &p, 10);
+ if (*p != ':' || service > 65535)
return -EINVAL;
- num = simple_strtoul(p + 1, &p, 10);
- if (*p || num < 1 || num > 255)
+ sec_class = simple_strtoul(p + 1, &p, 10);
+ if ((*p && *p != ':') || sec_class < 1 || sec_class > 255)
return -EINVAL;
return 0;
}
/*
* Preparse a server secret key.
- *
- * The data should be the 8-byte secret key.
*/
static int rxrpc_preparse_s(struct key_preparsed_payload *prep)
{
- struct crypto_skcipher *ci;
+ const struct rxrpc_security *sec;
+ unsigned int service, sec_class;
+ int n;
_enter("%zu", prep->datalen);
- if (prep->datalen != 8)
+ if (!prep->orig_description)
return -EINVAL;
- memcpy(&prep->payload.data[2], prep->data, 8);
+ if (sscanf(prep->orig_description, "%u:%u%n", &service, &sec_class, &n) != 2)
+ return -EINVAL;
- ci = crypto_alloc_skcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(ci)) {
- _leave(" = %ld", PTR_ERR(ci));
- return PTR_ERR(ci);
- }
+ sec = rxrpc_security_lookup(sec_class);
+ if (!sec)
+ return -ENOPKG;
- if (crypto_skcipher_setkey(ci, prep->data, 8) < 0)
- BUG();
+ prep->payload.data[1] = (struct rxrpc_security *)sec;
- prep->payload.data[0] = ci;
- _leave(" = 0");
- return 0;
+ return sec->preparse_server_key(prep);
}
static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
{
- if (prep->payload.data[0])
- crypto_free_skcipher(prep->payload.data[0]);
+ const struct rxrpc_security *sec = prep->payload.data[1];
+
+ if (sec)
+ sec->free_preparse_server_key(prep);
}
static void rxrpc_destroy_s(struct key *key)
{
- if (key->payload.data[0]) {
- crypto_free_skcipher(key->payload.data[0]);
- key->payload.data[0] = NULL;
- }
+ const struct rxrpc_security *sec = key->payload.data[1];
+
+ if (sec)
+ sec->destroy_server_key(key);
}
static void rxrpc_describe_s(const struct key *key, struct seq_file *m)