diff options
Diffstat (limited to 'net/rxrpc')
-rw-r--r-- | net/rxrpc/ar-internal.h | 11 | ||||
-rw-r--r-- | net/rxrpc/rxkad.c | 47 | ||||
-rw-r--r-- | net/rxrpc/security.c | 2 | ||||
-rw-r--r-- | net/rxrpc/server_key.c | 56 |
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) |