rxrpc: Split the server key type (rxrpc_s) into its own file

Split the server private key type (rxrpc_s) out into its own file rather
than mingling it with the authentication/client key type (rxrpc) since they
don't really bear any relation.

Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
David Howells 2020-09-16 08:25:08 +01:00
parent ec832bd06d
commit ca7fb10059
4 changed files with 149 additions and 127 deletions

View File

@ -28,6 +28,7 @@ rxrpc-y := \
rtt.o \ rtt.o \
security.o \ security.o \
sendmsg.o \ sendmsg.o \
server_key.o \
skbuff.o \ skbuff.o \
utils.o utils.o

View File

@ -906,10 +906,8 @@ extern const struct rxrpc_security rxrpc_no_security;
* key.c * key.c
*/ */
extern struct key_type key_type_rxrpc; extern struct key_type key_type_rxrpc;
extern struct key_type key_type_rxrpc_s;
int rxrpc_request_key(struct rxrpc_sock *, sockptr_t , int); int rxrpc_request_key(struct rxrpc_sock *, sockptr_t , int);
int rxrpc_server_keyring(struct rxrpc_sock *, sockptr_t, int);
int rxrpc_get_server_data_key(struct rxrpc_connection *, const void *, time64_t, int rxrpc_get_server_data_key(struct rxrpc_connection *, const void *, time64_t,
u32); u32);
@ -1064,6 +1062,13 @@ struct key *rxrpc_look_up_server_security(struct rxrpc_connection *,
*/ */
int rxrpc_do_sendmsg(struct rxrpc_sock *, struct msghdr *, size_t); int rxrpc_do_sendmsg(struct rxrpc_sock *, struct msghdr *, size_t);
/*
* server_key.c
*/
extern struct key_type key_type_rxrpc_s;
int rxrpc_server_keyring(struct rxrpc_sock *, sockptr_t, int);
/* /*
* skbuff.c * skbuff.c
*/ */

View File

@ -23,15 +23,10 @@
#include <keys/user-type.h> #include <keys/user-type.h>
#include "ar-internal.h" #include "ar-internal.h"
static int rxrpc_vet_description_s(const char *);
static int rxrpc_preparse(struct key_preparsed_payload *); static int rxrpc_preparse(struct key_preparsed_payload *);
static int rxrpc_preparse_s(struct key_preparsed_payload *);
static void rxrpc_free_preparse(struct key_preparsed_payload *); static void rxrpc_free_preparse(struct key_preparsed_payload *);
static void rxrpc_free_preparse_s(struct key_preparsed_payload *);
static void rxrpc_destroy(struct key *); static void rxrpc_destroy(struct key *);
static void rxrpc_destroy_s(struct key *);
static void rxrpc_describe(const struct key *, struct seq_file *); static void rxrpc_describe(const struct key *, struct seq_file *);
static void rxrpc_describe_s(const struct key *, struct seq_file *);
static long rxrpc_read(const struct key *, char *, size_t); static long rxrpc_read(const struct key *, char *, size_t);
/* /*
@ -50,38 +45,6 @@ struct key_type key_type_rxrpc = {
}; };
EXPORT_SYMBOL(key_type_rxrpc); EXPORT_SYMBOL(key_type_rxrpc);
/*
* rxrpc server defined keys take "<serviceId>:<securityIndex>" as the
* description and an 8-byte decryption key as the payload
*/
struct key_type key_type_rxrpc_s = {
.name = "rxrpc_s",
.flags = KEY_TYPE_NET_DOMAIN,
.vet_description = rxrpc_vet_description_s,
.preparse = rxrpc_preparse_s,
.free_preparse = rxrpc_free_preparse_s,
.instantiate = generic_key_instantiate,
.destroy = rxrpc_destroy_s,
.describe = rxrpc_describe_s,
};
/*
* Vet the description for an RxRPC server key
*/
static int rxrpc_vet_description_s(const char *desc)
{
unsigned long num;
char *p;
num = simple_strtoul(desc, &p, 10);
if (*p != ':' || num > 65535)
return -EINVAL;
num = simple_strtoul(p + 1, &p, 10);
if (*p || num < 1 || num > 255)
return -EINVAL;
return 0;
}
/* /*
* parse an RxKAD type XDR format token * parse an RxKAD type XDR format token
* - the caller guarantees we have at least 4 words * - the caller guarantees we have at least 4 words
@ -433,45 +396,6 @@ static void rxrpc_free_preparse(struct key_preparsed_payload *prep)
rxrpc_free_token_list(prep->payload.data[0]); rxrpc_free_token_list(prep->payload.data[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;
_enter("%zu", prep->datalen);
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;
}
/*
* Clean up preparse data.
*/
static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
{
if (prep->payload.data[0])
crypto_free_skcipher(prep->payload.data[0]);
}
/* /*
* dispose of the data dangling from the corpse of a rxrpc key * dispose of the data dangling from the corpse of a rxrpc key
*/ */
@ -480,17 +404,6 @@ static void rxrpc_destroy(struct key *key)
rxrpc_free_token_list(key->payload.data[0]); rxrpc_free_token_list(key->payload.data[0]);
} }
/*
* dispose of the data dangling from the corpse of a rxrpc key
*/
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;
}
}
/* /*
* describe the rxrpc key * describe the rxrpc key
*/ */
@ -517,14 +430,6 @@ static void rxrpc_describe(const struct key *key, struct seq_file *m)
} }
} }
/*
* describe the rxrpc server key
*/
static void rxrpc_describe_s(const struct key *key, struct seq_file *m)
{
seq_puts(m, key->description);
}
/* /*
* grab the security key for a socket * grab the security key for a socket
*/ */
@ -555,36 +460,6 @@ int rxrpc_request_key(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
return 0; return 0;
} }
/*
* grab the security keyring for a server socket
*/
int rxrpc_server_keyring(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
{
struct key *key;
char *description;
_enter("");
if (optlen <= 0 || optlen > PAGE_SIZE - 1)
return -EINVAL;
description = memdup_sockptr_nul(optval, optlen);
if (IS_ERR(description))
return PTR_ERR(description);
key = request_key(&key_type_keyring, description, NULL);
if (IS_ERR(key)) {
kfree(description);
_leave(" = %ld", PTR_ERR(key));
return PTR_ERR(key);
}
rx->securities = key;
kfree(description);
_leave(" = 0 [key %x]", key->serial);
return 0;
}
/* /*
* generate a server data key * generate a server data key
*/ */

141
net/rxrpc/server_key.c Normal file
View File

@ -0,0 +1,141 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* RxRPC key management
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* RxRPC keys should have a description of describing their purpose:
* "afs@CAMBRIDGE.REDHAT.COM>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <crypto/skcipher.h>
#include <linux/module.h>
#include <linux/net.h>
#include <linux/skbuff.h>
#include <linux/key-type.h>
#include <linux/ctype.h>
#include <linux/slab.h>
#include <net/sock.h>
#include <net/af_rxrpc.h>
#include <keys/rxrpc-type.h>
#include <keys/user-type.h>
#include "ar-internal.h"
static int rxrpc_vet_description_s(const char *);
static int rxrpc_preparse_s(struct key_preparsed_payload *);
static void rxrpc_free_preparse_s(struct key_preparsed_payload *);
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
*/
struct key_type key_type_rxrpc_s = {
.name = "rxrpc_s",
.flags = KEY_TYPE_NET_DOMAIN,
.vet_description = rxrpc_vet_description_s,
.preparse = rxrpc_preparse_s,
.free_preparse = rxrpc_free_preparse_s,
.instantiate = generic_key_instantiate,
.destroy = rxrpc_destroy_s,
.describe = rxrpc_describe_s,
};
/*
* Vet the description for an RxRPC server key
*/
static int rxrpc_vet_description_s(const char *desc)
{
unsigned long num;
char *p;
num = simple_strtoul(desc, &p, 10);
if (*p != ':' || num > 65535)
return -EINVAL;
num = simple_strtoul(p + 1, &p, 10);
if (*p || num < 1 || num > 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;
_enter("%zu", prep->datalen);
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 rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
{
if (prep->payload.data[0])
crypto_free_skcipher(prep->payload.data[0]);
}
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;
}
}
static void rxrpc_describe_s(const struct key *key, struct seq_file *m)
{
seq_puts(m, key->description);
}
/*
* grab the security keyring for a server socket
*/
int rxrpc_server_keyring(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
{
struct key *key;
char *description;
_enter("");
if (optlen <= 0 || optlen > PAGE_SIZE - 1)
return -EINVAL;
description = memdup_sockptr_nul(optval, optlen);
if (IS_ERR(description))
return PTR_ERR(description);
key = request_key(&key_type_keyring, description, NULL);
if (IS_ERR(key)) {
kfree(description);
_leave(" = %ld", PTR_ERR(key));
return PTR_ERR(key);
}
rx->securities = key;
kfree(description);
_leave(" = 0 [key %x]", key->serial);
return 0;
}