162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* RxRPC key management 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 562306a36Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * RxRPC keys should have a description of describing their purpose: 862306a36Sopenharmony_ci * "afs@CAMBRIDGE.REDHAT.COM> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <crypto/skcipher.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/net.h> 1662306a36Sopenharmony_ci#include <linux/skbuff.h> 1762306a36Sopenharmony_ci#include <linux/key-type.h> 1862306a36Sopenharmony_ci#include <linux/ctype.h> 1962306a36Sopenharmony_ci#include <linux/slab.h> 2062306a36Sopenharmony_ci#include <net/sock.h> 2162306a36Sopenharmony_ci#include <net/af_rxrpc.h> 2262306a36Sopenharmony_ci#include <keys/rxrpc-type.h> 2362306a36Sopenharmony_ci#include <keys/user-type.h> 2462306a36Sopenharmony_ci#include "ar-internal.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic int rxrpc_vet_description_s(const char *); 2762306a36Sopenharmony_cistatic int rxrpc_preparse_s(struct key_preparsed_payload *); 2862306a36Sopenharmony_cistatic void rxrpc_free_preparse_s(struct key_preparsed_payload *); 2962306a36Sopenharmony_cistatic void rxrpc_destroy_s(struct key *); 3062306a36Sopenharmony_cistatic void rxrpc_describe_s(const struct key *, struct seq_file *); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* 3362306a36Sopenharmony_ci * rxrpc server keys take "<serviceId>:<securityIndex>[:<sec-specific>]" as the 3462306a36Sopenharmony_ci * description and the key material as the payload. 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_cistruct key_type key_type_rxrpc_s = { 3762306a36Sopenharmony_ci .name = "rxrpc_s", 3862306a36Sopenharmony_ci .flags = KEY_TYPE_NET_DOMAIN, 3962306a36Sopenharmony_ci .vet_description = rxrpc_vet_description_s, 4062306a36Sopenharmony_ci .preparse = rxrpc_preparse_s, 4162306a36Sopenharmony_ci .free_preparse = rxrpc_free_preparse_s, 4262306a36Sopenharmony_ci .instantiate = generic_key_instantiate, 4362306a36Sopenharmony_ci .destroy = rxrpc_destroy_s, 4462306a36Sopenharmony_ci .describe = rxrpc_describe_s, 4562306a36Sopenharmony_ci}; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* 4862306a36Sopenharmony_ci * Vet the description for an RxRPC server key. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_cistatic int rxrpc_vet_description_s(const char *desc) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci unsigned long service, sec_class; 5362306a36Sopenharmony_ci char *p; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci service = simple_strtoul(desc, &p, 10); 5662306a36Sopenharmony_ci if (*p != ':' || service > 65535) 5762306a36Sopenharmony_ci return -EINVAL; 5862306a36Sopenharmony_ci sec_class = simple_strtoul(p + 1, &p, 10); 5962306a36Sopenharmony_ci if ((*p && *p != ':') || sec_class < 1 || sec_class > 255) 6062306a36Sopenharmony_ci return -EINVAL; 6162306a36Sopenharmony_ci return 0; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* 6562306a36Sopenharmony_ci * Preparse a server secret key. 6662306a36Sopenharmony_ci */ 6762306a36Sopenharmony_cistatic int rxrpc_preparse_s(struct key_preparsed_payload *prep) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci const struct rxrpc_security *sec; 7062306a36Sopenharmony_ci unsigned int service, sec_class; 7162306a36Sopenharmony_ci int n; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci _enter("%zu", prep->datalen); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci if (!prep->orig_description) 7662306a36Sopenharmony_ci return -EINVAL; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci if (sscanf(prep->orig_description, "%u:%u%n", &service, &sec_class, &n) != 2) 7962306a36Sopenharmony_ci return -EINVAL; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci sec = rxrpc_security_lookup(sec_class); 8262306a36Sopenharmony_ci if (!sec) 8362306a36Sopenharmony_ci return -ENOPKG; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci prep->payload.data[1] = (struct rxrpc_security *)sec; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (!sec->preparse_server_key) 8862306a36Sopenharmony_ci return -EINVAL; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci return sec->preparse_server_key(prep); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic void rxrpc_free_preparse_s(struct key_preparsed_payload *prep) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci const struct rxrpc_security *sec = prep->payload.data[1]; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci if (sec && sec->free_preparse_server_key) 9862306a36Sopenharmony_ci sec->free_preparse_server_key(prep); 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic void rxrpc_destroy_s(struct key *key) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci const struct rxrpc_security *sec = key->payload.data[1]; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci if (sec && sec->destroy_server_key) 10662306a36Sopenharmony_ci sec->destroy_server_key(key); 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic void rxrpc_describe_s(const struct key *key, struct seq_file *m) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci const struct rxrpc_security *sec = key->payload.data[1]; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci seq_puts(m, key->description); 11462306a36Sopenharmony_ci if (sec && sec->describe_server_key) 11562306a36Sopenharmony_ci sec->describe_server_key(key, m); 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci/* 11962306a36Sopenharmony_ci * grab the security keyring for a server socket 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ciint rxrpc_server_keyring(struct rxrpc_sock *rx, sockptr_t optval, int optlen) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci struct key *key; 12462306a36Sopenharmony_ci char *description; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci _enter(""); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci if (optlen <= 0 || optlen > PAGE_SIZE - 1) 12962306a36Sopenharmony_ci return -EINVAL; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci description = memdup_sockptr_nul(optval, optlen); 13262306a36Sopenharmony_ci if (IS_ERR(description)) 13362306a36Sopenharmony_ci return PTR_ERR(description); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci key = request_key(&key_type_keyring, description, NULL); 13662306a36Sopenharmony_ci if (IS_ERR(key)) { 13762306a36Sopenharmony_ci kfree(description); 13862306a36Sopenharmony_ci _leave(" = %ld", PTR_ERR(key)); 13962306a36Sopenharmony_ci return PTR_ERR(key); 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci rx->securities = key; 14362306a36Sopenharmony_ci kfree(description); 14462306a36Sopenharmony_ci _leave(" = 0 [key %x]", key->serial); 14562306a36Sopenharmony_ci return 0; 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/** 14962306a36Sopenharmony_ci * rxrpc_sock_set_security_keyring - Set the security keyring for a kernel service 15062306a36Sopenharmony_ci * @sk: The socket to set the keyring on 15162306a36Sopenharmony_ci * @keyring: The keyring to set 15262306a36Sopenharmony_ci * 15362306a36Sopenharmony_ci * Set the server security keyring on an rxrpc socket. This is used to provide 15462306a36Sopenharmony_ci * the encryption keys for a kernel service. 15562306a36Sopenharmony_ci */ 15662306a36Sopenharmony_ciint rxrpc_sock_set_security_keyring(struct sock *sk, struct key *keyring) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci struct rxrpc_sock *rx = rxrpc_sk(sk); 15962306a36Sopenharmony_ci int ret = 0; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci lock_sock(sk); 16262306a36Sopenharmony_ci if (rx->securities) 16362306a36Sopenharmony_ci ret = -EINVAL; 16462306a36Sopenharmony_ci else if (rx->sk.sk_state != RXRPC_UNBOUND) 16562306a36Sopenharmony_ci ret = -EISCONN; 16662306a36Sopenharmony_ci else 16762306a36Sopenharmony_ci rx->securities = key_get(keyring); 16862306a36Sopenharmony_ci release_sock(sk); 16962306a36Sopenharmony_ci return ret; 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ciEXPORT_SYMBOL(rxrpc_sock_set_security_keyring); 172