Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <dhowells@redhat.com>

+86 -30
+11
net/rxrpc/ar-internal.h
··· 35 35 #define rxrpc_queue_delayed_work(WS,D) \ 36 36 queue_delayed_work(rxrpc_workqueue, (WS), (D)) 37 37 38 + struct key_preparsed_payload; 38 39 struct rxrpc_connection; 39 40 40 41 /* ··· 217 216 218 217 /* Clean up a security service */ 219 218 void (*exit)(void); 219 + 220 + /* Parse the information from a server key */ 221 + int (*preparse_server_key)(struct key_preparsed_payload *); 222 + 223 + /* Clean up the preparse buffer after parsing a server key */ 224 + void (*free_preparse_server_key)(struct key_preparsed_payload *); 225 + 226 + /* Destroy the payload of a server key */ 227 + void (*destroy_server_key)(struct key *); 220 228 221 229 /* initialise a connection's security */ 222 230 int (*init_connection_security)(struct rxrpc_connection *, ··· 1060 1050 * security.c 1061 1051 */ 1062 1052 int __init rxrpc_init_security(void); 1053 + const struct rxrpc_security *rxrpc_security_lookup(u8); 1063 1054 void rxrpc_exit_security(void); 1064 1055 int rxrpc_init_client_conn_security(struct rxrpc_connection *); 1065 1056 const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *,
+47
net/rxrpc/rxkad.c
··· 15 15 #include <linux/scatterlist.h> 16 16 #include <linux/ctype.h> 17 17 #include <linux/slab.h> 18 + #include <linux/key-type.h> 18 19 #include <net/sock.h> 19 20 #include <net/af_rxrpc.h> 20 21 #include <keys/rxrpc-type.h> ··· 46 45 static struct crypto_sync_skcipher *rxkad_ci; 47 46 static struct skcipher_request *rxkad_ci_req; 48 47 static DEFINE_MUTEX(rxkad_ci_mutex); 48 + 49 + /* 50 + * Parse the information from a server key 51 + * 52 + * The data should be the 8-byte secret key. 53 + */ 54 + static int rxkad_preparse_server_key(struct key_preparsed_payload *prep) 55 + { 56 + struct crypto_skcipher *ci; 57 + 58 + if (prep->datalen != 8) 59 + return -EINVAL; 60 + 61 + memcpy(&prep->payload.data[2], prep->data, 8); 62 + 63 + ci = crypto_alloc_skcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); 64 + if (IS_ERR(ci)) { 65 + _leave(" = %ld", PTR_ERR(ci)); 66 + return PTR_ERR(ci); 67 + } 68 + 69 + if (crypto_skcipher_setkey(ci, prep->data, 8) < 0) 70 + BUG(); 71 + 72 + prep->payload.data[0] = ci; 73 + _leave(" = 0"); 74 + return 0; 75 + } 76 + 77 + static void rxkad_free_preparse_server_key(struct key_preparsed_payload *prep) 78 + { 79 + 80 + if (prep->payload.data[0]) 81 + crypto_free_skcipher(prep->payload.data[0]); 82 + } 83 + 84 + static void rxkad_destroy_server_key(struct key *key) 85 + { 86 + if (key->payload.data[0]) { 87 + crypto_free_skcipher(key->payload.data[0]); 88 + key->payload.data[0] = NULL; 89 + } 90 + } 49 91 50 92 /* 51 93 * initialise connection security ··· 1346 1302 .no_key_abort = RXKADUNKNOWNKEY, 1347 1303 .init = rxkad_init, 1348 1304 .exit = rxkad_exit, 1305 + .preparse_server_key = rxkad_preparse_server_key, 1306 + .free_preparse_server_key = rxkad_free_preparse_server_key, 1307 + .destroy_server_key = rxkad_destroy_server_key, 1349 1308 .init_connection_security = rxkad_init_connection_security, 1350 1309 .prime_packet_security = rxkad_prime_packet_security, 1351 1310 .secure_packet = rxkad_secure_packet,
+1 -1
net/rxrpc/security.c
··· 55 55 /* 56 56 * look up an rxrpc security module 57 57 */ 58 - static const struct rxrpc_security *rxrpc_security_lookup(u8 security_index) 58 + const struct rxrpc_security *rxrpc_security_lookup(u8 security_index) 59 59 { 60 60 if (security_index >= ARRAY_SIZE(rxrpc_security_types)) 61 61 return NULL;
+27 -29
net/rxrpc/server_key.c
··· 30 30 static void rxrpc_describe_s(const struct key *, struct seq_file *); 31 31 32 32 /* 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. 35 35 */ 36 36 struct key_type key_type_rxrpc_s = { 37 37 .name = "rxrpc_s", ··· 45 45 }; 46 46 47 47 /* 48 - * Vet the description for an RxRPC server key 48 + * Vet the description for an RxRPC server key. 49 49 */ 50 50 static int rxrpc_vet_description_s(const char *desc) 51 51 { 52 - unsigned long num; 52 + unsigned long service, sec_class; 53 53 char *p; 54 54 55 - num = simple_strtoul(desc, &p, 10); 56 - if (*p != ':' || num > 65535) 55 + service = simple_strtoul(desc, &p, 10); 56 + if (*p != ':' || service > 65535) 57 57 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) 60 60 return -EINVAL; 61 61 return 0; 62 62 } 63 63 64 64 /* 65 65 * Preparse a server secret key. 66 - * 67 - * The data should be the 8-byte secret key. 68 66 */ 69 67 static int rxrpc_preparse_s(struct key_preparsed_payload *prep) 70 68 { 71 - struct crypto_skcipher *ci; 69 + const struct rxrpc_security *sec; 70 + unsigned int service, sec_class; 71 + int n; 72 72 73 73 _enter("%zu", prep->datalen); 74 74 75 - if (prep->datalen != 8) 75 + if (!prep->orig_description) 76 76 return -EINVAL; 77 77 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; 79 80 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; 85 84 86 - if (crypto_skcipher_setkey(ci, prep->data, 8) < 0) 87 - BUG(); 85 + prep->payload.data[1] = (struct rxrpc_security *)sec; 88 86 89 - prep->payload.data[0] = ci; 90 - _leave(" = 0"); 91 - return 0; 87 + return sec->preparse_server_key(prep); 92 88 } 93 89 94 90 static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep) 95 91 { 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); 98 96 } 99 97 100 98 static void rxrpc_destroy_s(struct key *key) 101 99 { 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); 106 104 } 107 105 108 106 static void rxrpc_describe_s(const struct key *key, struct seq_file *m)