Skip to content

Commit 12da59f

Browse files
committed
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: David Howells <[email protected]>
1 parent ca7fb10 commit 12da59f

File tree

4 files changed

+86
-30
lines changed

4 files changed

+86
-30
lines changed

net/rxrpc/ar-internal.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ struct rxrpc_crypt {
3535
#define rxrpc_queue_delayed_work(WS,D) \
3636
queue_delayed_work(rxrpc_workqueue, (WS), (D))
3737

38+
struct key_preparsed_payload;
3839
struct rxrpc_connection;
3940

4041
/*
@@ -217,6 +218,15 @@ struct rxrpc_security {
217218
/* Clean up a security service */
218219
void (*exit)(void);
219220

221+
/* Parse the information from a server key */
222+
int (*preparse_server_key)(struct key_preparsed_payload *);
223+
224+
/* Clean up the preparse buffer after parsing a server key */
225+
void (*free_preparse_server_key)(struct key_preparsed_payload *);
226+
227+
/* Destroy the payload of a server key */
228+
void (*destroy_server_key)(struct key *);
229+
220230
/* initialise a connection's security */
221231
int (*init_connection_security)(struct rxrpc_connection *,
222232
struct rxrpc_key_token *);
@@ -1050,6 +1060,7 @@ extern const struct rxrpc_security rxkad;
10501060
* security.c
10511061
*/
10521062
int __init rxrpc_init_security(void);
1063+
const struct rxrpc_security *rxrpc_security_lookup(u8);
10531064
void rxrpc_exit_security(void);
10541065
int rxrpc_init_client_conn_security(struct rxrpc_connection *);
10551066
const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *,

net/rxrpc/rxkad.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/scatterlist.h>
1616
#include <linux/ctype.h>
1717
#include <linux/slab.h>
18+
#include <linux/key-type.h>
1819
#include <net/sock.h>
1920
#include <net/af_rxrpc.h>
2021
#include <keys/rxrpc-type.h>
@@ -46,6 +47,49 @@ static struct crypto_sync_skcipher *rxkad_ci;
4647
static struct skcipher_request *rxkad_ci_req;
4748
static DEFINE_MUTEX(rxkad_ci_mutex);
4849

50+
/*
51+
* Parse the information from a server key
52+
*
53+
* The data should be the 8-byte secret key.
54+
*/
55+
static int rxkad_preparse_server_key(struct key_preparsed_payload *prep)
56+
{
57+
struct crypto_skcipher *ci;
58+
59+
if (prep->datalen != 8)
60+
return -EINVAL;
61+
62+
memcpy(&prep->payload.data[2], prep->data, 8);
63+
64+
ci = crypto_alloc_skcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
65+
if (IS_ERR(ci)) {
66+
_leave(" = %ld", PTR_ERR(ci));
67+
return PTR_ERR(ci);
68+
}
69+
70+
if (crypto_skcipher_setkey(ci, prep->data, 8) < 0)
71+
BUG();
72+
73+
prep->payload.data[0] = ci;
74+
_leave(" = 0");
75+
return 0;
76+
}
77+
78+
static void rxkad_free_preparse_server_key(struct key_preparsed_payload *prep)
79+
{
80+
81+
if (prep->payload.data[0])
82+
crypto_free_skcipher(prep->payload.data[0]);
83+
}
84+
85+
static void rxkad_destroy_server_key(struct key *key)
86+
{
87+
if (key->payload.data[0]) {
88+
crypto_free_skcipher(key->payload.data[0]);
89+
key->payload.data[0] = NULL;
90+
}
91+
}
92+
4993
/*
5094
* initialise connection security
5195
*/
@@ -1302,6 +1346,9 @@ const struct rxrpc_security rxkad = {
13021346
.no_key_abort = RXKADUNKNOWNKEY,
13031347
.init = rxkad_init,
13041348
.exit = rxkad_exit,
1349+
.preparse_server_key = rxkad_preparse_server_key,
1350+
.free_preparse_server_key = rxkad_free_preparse_server_key,
1351+
.destroy_server_key = rxkad_destroy_server_key,
13051352
.init_connection_security = rxkad_init_connection_security,
13061353
.prime_packet_security = rxkad_prime_packet_security,
13071354
.secure_packet = rxkad_secure_packet,

net/rxrpc/security.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ void rxrpc_exit_security(void)
5555
/*
5656
* look up an rxrpc security module
5757
*/
58-
static const struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
58+
const struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
5959
{
6060
if (security_index >= ARRAY_SIZE(rxrpc_security_types))
6161
return NULL;

net/rxrpc/server_key.c

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ static void rxrpc_destroy_s(struct key *);
3030
static void rxrpc_describe_s(const struct key *, struct seq_file *);
3131

3232
/*
33-
* rxrpc server defined keys take "<serviceId>:<securityIndex>" as the
34-
* description and an 8-byte decryption key as the payload
33+
* rxrpc server keys take "<serviceId>:<securityIndex>[:<sec-specific>]" as the
34+
* description and the key material as the payload.
3535
*/
3636
struct key_type key_type_rxrpc_s = {
3737
.name = "rxrpc_s",
@@ -45,64 +45,62 @@ struct key_type key_type_rxrpc_s = {
4545
};
4646

4747
/*
48-
* Vet the description for an RxRPC server key
48+
* Vet the description for an RxRPC server key.
4949
*/
5050
static int rxrpc_vet_description_s(const char *desc)
5151
{
52-
unsigned long num;
52+
unsigned long service, sec_class;
5353
char *p;
5454

55-
num = simple_strtoul(desc, &p, 10);
56-
if (*p != ':' || num > 65535)
55+
service = simple_strtoul(desc, &p, 10);
56+
if (*p != ':' || service > 65535)
5757
return -EINVAL;
58-
num = simple_strtoul(p + 1, &p, 10);
59-
if (*p || num < 1 || num > 255)
58+
sec_class = simple_strtoul(p + 1, &p, 10);
59+
if ((*p && *p != ':') || sec_class < 1 || sec_class > 255)
6060
return -EINVAL;
6161
return 0;
6262
}
6363

6464
/*
6565
* Preparse a server secret key.
66-
*
67-
* The data should be the 8-byte secret key.
6866
*/
6967
static int rxrpc_preparse_s(struct key_preparsed_payload *prep)
7068
{
71-
struct crypto_skcipher *ci;
69+
const struct rxrpc_security *sec;
70+
unsigned int service, sec_class;
71+
int n;
7272

7373
_enter("%zu", prep->datalen);
7474

75-
if (prep->datalen != 8)
75+
if (!prep->orig_description)
7676
return -EINVAL;
7777

78-
memcpy(&prep->payload.data[2], prep->data, 8);
78+
if (sscanf(prep->orig_description, "%u:%u%n", &service, &sec_class, &n) != 2)
79+
return -EINVAL;
7980

80-
ci = crypto_alloc_skcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
81-
if (IS_ERR(ci)) {
82-
_leave(" = %ld", PTR_ERR(ci));
83-
return PTR_ERR(ci);
84-
}
81+
sec = rxrpc_security_lookup(sec_class);
82+
if (!sec)
83+
return -ENOPKG;
8584

86-
if (crypto_skcipher_setkey(ci, prep->data, 8) < 0)
87-
BUG();
85+
prep->payload.data[1] = (struct rxrpc_security *)sec;
8886

89-
prep->payload.data[0] = ci;
90-
_leave(" = 0");
91-
return 0;
87+
return sec->preparse_server_key(prep);
9288
}
9389

9490
static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
9591
{
96-
if (prep->payload.data[0])
97-
crypto_free_skcipher(prep->payload.data[0]);
92+
const struct rxrpc_security *sec = prep->payload.data[1];
93+
94+
if (sec)
95+
sec->free_preparse_server_key(prep);
9896
}
9997

10098
static void rxrpc_destroy_s(struct key *key)
10199
{
102-
if (key->payload.data[0]) {
103-
crypto_free_skcipher(key->payload.data[0]);
104-
key->payload.data[0] = NULL;
105-
}
100+
const struct rxrpc_security *sec = key->payload.data[1];
101+
102+
if (sec)
103+
sec->destroy_server_key(key);
106104
}
107105

108106
static void rxrpc_describe_s(const struct key *key, struct seq_file *m)

0 commit comments

Comments
 (0)