Commit 12da59fc authored by David Howells's avatar David Howells

rxrpc: Hand server key parsing off to the security class

Hand responsibility for parsing a server key off to the security class.  We
can determine which class from the description.  This is necessary as rxgk
server keys have different lookup requirements and different content
requirements (dependent on crypto type) to those of rxkad server keys.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent ca7fb100
...@@ -35,6 +35,7 @@ struct rxrpc_crypt { ...@@ -35,6 +35,7 @@ struct rxrpc_crypt {
#define rxrpc_queue_delayed_work(WS,D) \ #define rxrpc_queue_delayed_work(WS,D) \
queue_delayed_work(rxrpc_workqueue, (WS), (D)) queue_delayed_work(rxrpc_workqueue, (WS), (D))
struct key_preparsed_payload;
struct rxrpc_connection; struct rxrpc_connection;
/* /*
...@@ -217,6 +218,15 @@ struct rxrpc_security { ...@@ -217,6 +218,15 @@ struct rxrpc_security {
/* Clean up a security service */ /* Clean up a security service */
void (*exit)(void); 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 */ /* initialise a connection's security */
int (*init_connection_security)(struct rxrpc_connection *, int (*init_connection_security)(struct rxrpc_connection *,
struct rxrpc_key_token *); struct rxrpc_key_token *);
...@@ -1050,6 +1060,7 @@ extern const struct rxrpc_security rxkad; ...@@ -1050,6 +1060,7 @@ extern const struct rxrpc_security rxkad;
* security.c * security.c
*/ */
int __init rxrpc_init_security(void); int __init rxrpc_init_security(void);
const struct rxrpc_security *rxrpc_security_lookup(u8);
void rxrpc_exit_security(void); void rxrpc_exit_security(void);
int rxrpc_init_client_conn_security(struct rxrpc_connection *); int rxrpc_init_client_conn_security(struct rxrpc_connection *);
const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *, const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *,
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/key-type.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/af_rxrpc.h> #include <net/af_rxrpc.h>
#include <keys/rxrpc-type.h> #include <keys/rxrpc-type.h>
...@@ -46,6 +47,49 @@ static struct crypto_sync_skcipher *rxkad_ci; ...@@ -46,6 +47,49 @@ static struct crypto_sync_skcipher *rxkad_ci;
static struct skcipher_request *rxkad_ci_req; static struct skcipher_request *rxkad_ci_req;
static DEFINE_MUTEX(rxkad_ci_mutex); 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 * initialise connection security
*/ */
...@@ -1302,6 +1346,9 @@ const struct rxrpc_security rxkad = { ...@@ -1302,6 +1346,9 @@ const struct rxrpc_security rxkad = {
.no_key_abort = RXKADUNKNOWNKEY, .no_key_abort = RXKADUNKNOWNKEY,
.init = rxkad_init, .init = rxkad_init,
.exit = rxkad_exit, .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, .init_connection_security = rxkad_init_connection_security,
.prime_packet_security = rxkad_prime_packet_security, .prime_packet_security = rxkad_prime_packet_security,
.secure_packet = rxkad_secure_packet, .secure_packet = rxkad_secure_packet,
......
...@@ -55,7 +55,7 @@ void rxrpc_exit_security(void) ...@@ -55,7 +55,7 @@ void rxrpc_exit_security(void)
/* /*
* look up an rxrpc security module * 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)) if (security_index >= ARRAY_SIZE(rxrpc_security_types))
return NULL; return NULL;
......
...@@ -30,8 +30,8 @@ static void rxrpc_destroy_s(struct key *); ...@@ -30,8 +30,8 @@ static void rxrpc_destroy_s(struct key *);
static void rxrpc_describe_s(const struct key *, struct seq_file *); static void rxrpc_describe_s(const struct key *, struct seq_file *);
/* /*
* rxrpc server defined keys take "<serviceId>:<securityIndex>" as the * rxrpc server keys take "<serviceId>:<securityIndex>[:<sec-specific>]" as the
* description and an 8-byte decryption key as the payload * description and the key material as the payload.
*/ */
struct key_type key_type_rxrpc_s = { struct key_type key_type_rxrpc_s = {
.name = "rxrpc_s", .name = "rxrpc_s",
...@@ -45,64 +45,62 @@ struct key_type key_type_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) static int rxrpc_vet_description_s(const char *desc)
{ {
unsigned long num; unsigned long service, sec_class;
char *p; char *p;
num = simple_strtoul(desc, &p, 10); service = simple_strtoul(desc, &p, 10);
if (*p != ':' || num > 65535) if (*p != ':' || service > 65535)
return -EINVAL; return -EINVAL;
num = simple_strtoul(p + 1, &p, 10); sec_class = simple_strtoul(p + 1, &p, 10);
if (*p || num < 1 || num > 255) if ((*p && *p != ':') || sec_class < 1 || sec_class > 255)
return -EINVAL; return -EINVAL;
return 0; return 0;
} }
/* /*
* Preparse a server secret key. * Preparse a server secret key.
*
* The data should be the 8-byte secret key.
*/ */
static int rxrpc_preparse_s(struct key_preparsed_payload *prep) 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); _enter("%zu", prep->datalen);
if (prep->datalen != 8) if (!prep->orig_description)
return -EINVAL; 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); sec = rxrpc_security_lookup(sec_class);
if (IS_ERR(ci)) { if (!sec)
_leave(" = %ld", PTR_ERR(ci)); return -ENOPKG;
return PTR_ERR(ci);
}
if (crypto_skcipher_setkey(ci, prep->data, 8) < 0) prep->payload.data[1] = (struct rxrpc_security *)sec;
BUG();
prep->payload.data[0] = ci; return sec->preparse_server_key(prep);
_leave(" = 0");
return 0;
} }
static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep) static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
{ {
if (prep->payload.data[0]) const struct rxrpc_security *sec = prep->payload.data[1];
crypto_free_skcipher(prep->payload.data[0]);
if (sec)
sec->free_preparse_server_key(prep);
} }
static void rxrpc_destroy_s(struct key *key) static void rxrpc_destroy_s(struct key *key)
{ {
if (key->payload.data[0]) { const struct rxrpc_security *sec = key->payload.data[1];
crypto_free_skcipher(key->payload.data[0]);
key->payload.data[0] = NULL; if (sec)
} sec->destroy_server_key(key);
} }
static void rxrpc_describe_s(const struct key *key, struct seq_file *m) static void rxrpc_describe_s(const struct key *key, struct seq_file *m)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment