blob: 52a24d4ef5d8a841a6e0f1ad58c14873ae03e666 [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001// SPDX-License-Identifier: GPL-2.0-or-later
David Howells17926a72007-04-26 15:48:28 -07002/* Kerberos-based RxRPC security
3 *
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
David Howells17926a72007-04-26 15:48:28 -07006 */
7
Joe Perches9b6d5392016-06-02 12:08:52 -07008#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9
Herbert Xu1afe5932016-01-24 21:19:01 +080010#include <crypto/skcipher.h>
David Howells17926a72007-04-26 15:48:28 -070011#include <linux/module.h>
12#include <linux/net.h>
13#include <linux/skbuff.h>
14#include <linux/udp.h>
David Howells17926a72007-04-26 15:48:28 -070015#include <linux/scatterlist.h>
16#include <linux/ctype.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090017#include <linux/slab.h>
David Howells17926a72007-04-26 15:48:28 -070018#include <net/sock.h>
19#include <net/af_rxrpc.h>
David Howells33941282009-09-14 01:17:35 +000020#include <keys/rxrpc-type.h>
David Howells17926a72007-04-26 15:48:28 -070021#include "ar-internal.h"
22
23#define RXKAD_VERSION 2
24#define MAXKRB5TICKETLEN 1024
25#define RXKAD_TKT_TYPE_KERBEROS_V5 256
26#define ANAME_SZ 40 /* size of authentication name */
27#define INST_SZ 40 /* size of principal's instance */
28#define REALM_SZ 40 /* size of principal's auth domain */
29#define SNAME_SZ 40 /* size of service name */
30
David Howells17926a72007-04-26 15:48:28 -070031struct rxkad_level1_hdr {
32 __be32 data_size; /* true data size (excluding padding) */
33};
34
35struct rxkad_level2_hdr {
36 __be32 data_size; /* true data size (excluding padding) */
37 __be32 checksum; /* decrypted data checksum */
38};
39
David Howells17926a72007-04-26 15:48:28 -070040/*
41 * this holds a pinned cipher so that keventd doesn't get called by the cipher
42 * alloc routine, but since we have it to hand, we use it to decrypt RESPONSE
43 * packets
44 */
Kees Cook69d826f2018-09-18 19:10:47 -070045static struct crypto_sync_skcipher *rxkad_ci;
David Howells1db88c52019-07-30 15:56:57 +010046static struct skcipher_request *rxkad_ci_req;
David Howells17926a72007-04-26 15:48:28 -070047static DEFINE_MUTEX(rxkad_ci_mutex);
48
49/*
50 * initialise connection security
51 */
52static int rxkad_init_connection_security(struct rxrpc_connection *conn)
53{
Kees Cook69d826f2018-09-18 19:10:47 -070054 struct crypto_sync_skcipher *ci;
David Howells33941282009-09-14 01:17:35 +000055 struct rxrpc_key_token *token;
David Howells17926a72007-04-26 15:48:28 -070056 int ret;
57
David Howells19ffa012016-04-04 14:00:36 +010058 _enter("{%d},{%x}", conn->debug_id, key_serial(conn->params.key));
David Howells17926a72007-04-26 15:48:28 -070059
David Howells19ffa012016-04-04 14:00:36 +010060 token = conn->params.key->payload.data[0];
David Howells33941282009-09-14 01:17:35 +000061 conn->security_ix = token->security_index;
David Howells17926a72007-04-26 15:48:28 -070062
Kees Cook69d826f2018-09-18 19:10:47 -070063 ci = crypto_alloc_sync_skcipher("pcbc(fcrypt)", 0, 0);
David Howells17926a72007-04-26 15:48:28 -070064 if (IS_ERR(ci)) {
65 _debug("no cipher");
66 ret = PTR_ERR(ci);
67 goto error;
68 }
69
Kees Cook69d826f2018-09-18 19:10:47 -070070 if (crypto_sync_skcipher_setkey(ci, token->kad->session_key,
Herbert Xu1afe5932016-01-24 21:19:01 +080071 sizeof(token->kad->session_key)) < 0)
David Howells17926a72007-04-26 15:48:28 -070072 BUG();
73
David Howells19ffa012016-04-04 14:00:36 +010074 switch (conn->params.security_level) {
David Howells17926a72007-04-26 15:48:28 -070075 case RXRPC_SECURITY_PLAIN:
76 break;
77 case RXRPC_SECURITY_AUTH:
78 conn->size_align = 8;
79 conn->security_size = sizeof(struct rxkad_level1_hdr);
David Howells17926a72007-04-26 15:48:28 -070080 break;
81 case RXRPC_SECURITY_ENCRYPT:
82 conn->size_align = 8;
83 conn->security_size = sizeof(struct rxkad_level2_hdr);
David Howells17926a72007-04-26 15:48:28 -070084 break;
85 default:
86 ret = -EKEYREJECTED;
87 goto error;
88 }
89
90 conn->cipher = ci;
91 ret = 0;
92error:
93 _leave(" = %d", ret);
94 return ret;
95}
96
97/*
98 * prime the encryption state with the invariant parts of a connection's
99 * description
100 */
Herbert Xua2636292016-06-26 14:55:24 -0700101static int rxkad_prime_packet_security(struct rxrpc_connection *conn)
David Howells17926a72007-04-26 15:48:28 -0700102{
David Howells1db88c52019-07-30 15:56:57 +0100103 struct skcipher_request *req;
David Howells33941282009-09-14 01:17:35 +0000104 struct rxrpc_key_token *token;
Herbert Xua2636292016-06-26 14:55:24 -0700105 struct scatterlist sg;
David Howells17926a72007-04-26 15:48:28 -0700106 struct rxrpc_crypt iv;
Herbert Xua2636292016-06-26 14:55:24 -0700107 __be32 *tmpbuf;
108 size_t tmpsize = 4 * sizeof(__be32);
David Howells17926a72007-04-26 15:48:28 -0700109
110 _enter("");
111
David Howells19ffa012016-04-04 14:00:36 +0100112 if (!conn->params.key)
Herbert Xua2636292016-06-26 14:55:24 -0700113 return 0;
114
115 tmpbuf = kmalloc(tmpsize, GFP_KERNEL);
116 if (!tmpbuf)
117 return -ENOMEM;
David Howells17926a72007-04-26 15:48:28 -0700118
David Howells1db88c52019-07-30 15:56:57 +0100119 req = skcipher_request_alloc(&conn->cipher->base, GFP_NOFS);
120 if (!req) {
121 kfree(tmpbuf);
122 return -ENOMEM;
123 }
124
David Howells19ffa012016-04-04 14:00:36 +0100125 token = conn->params.key->payload.data[0];
David Howells33941282009-09-14 01:17:35 +0000126 memcpy(&iv, token->kad->session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700127
Herbert Xua2636292016-06-26 14:55:24 -0700128 tmpbuf[0] = htonl(conn->proto.epoch);
129 tmpbuf[1] = htonl(conn->proto.cid);
130 tmpbuf[2] = 0;
131 tmpbuf[3] = htonl(conn->security_ix);
David Howells17926a72007-04-26 15:48:28 -0700132
Herbert Xua2636292016-06-26 14:55:24 -0700133 sg_init_one(&sg, tmpbuf, tmpsize);
Kees Cook69d826f2018-09-18 19:10:47 -0700134 skcipher_request_set_sync_tfm(req, conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800135 skcipher_request_set_callback(req, 0, NULL, NULL);
Herbert Xua2636292016-06-26 14:55:24 -0700136 skcipher_request_set_crypt(req, &sg, &sg, tmpsize, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800137 crypto_skcipher_encrypt(req);
David Howells1db88c52019-07-30 15:56:57 +0100138 skcipher_request_free(req);
David Howells17926a72007-04-26 15:48:28 -0700139
Herbert Xua2636292016-06-26 14:55:24 -0700140 memcpy(&conn->csum_iv, tmpbuf + 2, sizeof(conn->csum_iv));
141 kfree(tmpbuf);
142 _leave(" = 0");
143 return 0;
David Howells17926a72007-04-26 15:48:28 -0700144}
145
146/*
David Howells1db88c52019-07-30 15:56:57 +0100147 * Allocate and prepare the crypto request on a call. For any particular call,
148 * this is called serially for the packets, so no lock should be necessary.
149 */
150static struct skcipher_request *rxkad_get_call_crypto(struct rxrpc_call *call)
151{
152 struct crypto_skcipher *tfm = &call->conn->cipher->base;
153 struct skcipher_request *cipher_req = call->cipher_req;
154
155 if (!cipher_req) {
156 cipher_req = skcipher_request_alloc(tfm, GFP_NOFS);
157 if (!cipher_req)
158 return NULL;
159 call->cipher_req = cipher_req;
160 }
161
162 return cipher_req;
163}
164
165/*
166 * Clean up the crypto on a call.
167 */
168static void rxkad_free_call_crypto(struct rxrpc_call *call)
169{
170 if (call->cipher_req)
171 skcipher_request_free(call->cipher_req);
172 call->cipher_req = NULL;
173}
174
175/*
David Howells17926a72007-04-26 15:48:28 -0700176 * partially encrypt a packet (level 1 security)
177 */
178static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
179 struct sk_buff *skb,
180 u32 data_size,
Kees Cook54424d32018-08-03 10:15:25 +0100181 void *sechdr,
182 struct skcipher_request *req)
David Howells17926a72007-04-26 15:48:28 -0700183{
David Howellsfb46f6e2017-04-06 10:12:00 +0100184 struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
Herbert Xua2636292016-06-26 14:55:24 -0700185 struct rxkad_level1_hdr hdr;
David Howells17926a72007-04-26 15:48:28 -0700186 struct rxrpc_crypt iv;
Herbert Xua2636292016-06-26 14:55:24 -0700187 struct scatterlist sg;
David Howells17926a72007-04-26 15:48:28 -0700188 u16 check;
189
David Howells17926a72007-04-26 15:48:28 -0700190 _enter("");
191
David Howells5a924b82016-09-22 00:29:31 +0100192 check = sp->hdr.seq ^ call->call_id;
David Howells0d12f8a2016-03-04 15:53:46 +0000193 data_size |= (u32)check << 16;
David Howells17926a72007-04-26 15:48:28 -0700194
Herbert Xua2636292016-06-26 14:55:24 -0700195 hdr.data_size = htonl(data_size);
196 memcpy(sechdr, &hdr, sizeof(hdr));
David Howells17926a72007-04-26 15:48:28 -0700197
198 /* start the encryption afresh */
199 memset(&iv, 0, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700200
Herbert Xua2636292016-06-26 14:55:24 -0700201 sg_init_one(&sg, sechdr, 8);
Kees Cook69d826f2018-09-18 19:10:47 -0700202 skcipher_request_set_sync_tfm(req, call->conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800203 skcipher_request_set_callback(req, 0, NULL, NULL);
Herbert Xua2636292016-06-26 14:55:24 -0700204 skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800205 crypto_skcipher_encrypt(req);
206 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700207
David Howells17926a72007-04-26 15:48:28 -0700208 _leave(" = 0");
209 return 0;
210}
211
212/*
213 * wholly encrypt a packet (level 2 security)
214 */
215static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
David Howellsb4f13422016-03-04 15:56:19 +0000216 struct sk_buff *skb,
217 u32 data_size,
Kees Cook54424d32018-08-03 10:15:25 +0100218 void *sechdr,
219 struct skcipher_request *req)
David Howells17926a72007-04-26 15:48:28 -0700220{
David Howells33941282009-09-14 01:17:35 +0000221 const struct rxrpc_key_token *token;
Herbert Xua2636292016-06-26 14:55:24 -0700222 struct rxkad_level2_hdr rxkhdr;
David Howells17926a72007-04-26 15:48:28 -0700223 struct rxrpc_skb_priv *sp;
David Howells17926a72007-04-26 15:48:28 -0700224 struct rxrpc_crypt iv;
225 struct scatterlist sg[16];
Eric Dumazet95c96172012-04-15 05:58:06 +0000226 unsigned int len;
David Howells17926a72007-04-26 15:48:28 -0700227 u16 check;
Herbert Xu1afe5932016-01-24 21:19:01 +0800228 int err;
David Howells17926a72007-04-26 15:48:28 -0700229
230 sp = rxrpc_skb(skb);
231
232 _enter("");
233
David Howells5a924b82016-09-22 00:29:31 +0100234 check = sp->hdr.seq ^ call->call_id;
David Howells17926a72007-04-26 15:48:28 -0700235
David Howells0d12f8a2016-03-04 15:53:46 +0000236 rxkhdr.data_size = htonl(data_size | (u32)check << 16);
David Howells17926a72007-04-26 15:48:28 -0700237 rxkhdr.checksum = 0;
Herbert Xua2636292016-06-26 14:55:24 -0700238 memcpy(sechdr, &rxkhdr, sizeof(rxkhdr));
David Howells17926a72007-04-26 15:48:28 -0700239
240 /* encrypt from the session key */
David Howells19ffa012016-04-04 14:00:36 +0100241 token = call->conn->params.key->payload.data[0];
David Howells33941282009-09-14 01:17:35 +0000242 memcpy(&iv, token->kad->session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700243
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700244 sg_init_one(&sg[0], sechdr, sizeof(rxkhdr));
Kees Cook69d826f2018-09-18 19:10:47 -0700245 skcipher_request_set_sync_tfm(req, call->conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800246 skcipher_request_set_callback(req, 0, NULL, NULL);
Herbert Xua2636292016-06-26 14:55:24 -0700247 skcipher_request_set_crypt(req, &sg[0], &sg[0], sizeof(rxkhdr), iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800248 crypto_skcipher_encrypt(req);
David Howells17926a72007-04-26 15:48:28 -0700249
250 /* we want to encrypt the skbuff in-place */
David Howellsd0d5c0c2019-08-27 10:13:46 +0100251 err = -EMSGSIZE;
252 if (skb_shinfo(skb)->nr_frags > 16)
Herbert Xu1afe5932016-01-24 21:19:01 +0800253 goto out;
David Howells17926a72007-04-26 15:48:28 -0700254
255 len = data_size + call->conn->size_align - 1;
256 len &= ~(call->conn->size_align - 1);
257
David Howellsd0d5c0c2019-08-27 10:13:46 +0100258 sg_init_table(sg, ARRAY_SIZE(sg));
Jason A. Donenfeld89a5ea92017-06-04 04:16:24 +0200259 err = skb_to_sgvec(skb, sg, 0, len);
260 if (unlikely(err < 0))
261 goto out;
Herbert Xu1afe5932016-01-24 21:19:01 +0800262 skcipher_request_set_crypt(req, sg, sg, len, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800263 crypto_skcipher_encrypt(req);
David Howells17926a72007-04-26 15:48:28 -0700264
265 _leave(" = 0");
Herbert Xu1afe5932016-01-24 21:19:01 +0800266 err = 0;
267
268out:
269 skcipher_request_zero(req);
270 return err;
David Howells17926a72007-04-26 15:48:28 -0700271}
272
273/*
274 * checksum an RxRPC packet header
275 */
Herbert Xua2636292016-06-26 14:55:24 -0700276static int rxkad_secure_packet(struct rxrpc_call *call,
David Howellsb4f13422016-03-04 15:56:19 +0000277 struct sk_buff *skb,
278 size_t data_size,
279 void *sechdr)
David Howells17926a72007-04-26 15:48:28 -0700280{
281 struct rxrpc_skb_priv *sp;
David Howells1db88c52019-07-30 15:56:57 +0100282 struct skcipher_request *req;
David Howells17926a72007-04-26 15:48:28 -0700283 struct rxrpc_crypt iv;
Herbert Xua2636292016-06-26 14:55:24 -0700284 struct scatterlist sg;
David Howells0d12f8a2016-03-04 15:53:46 +0000285 u32 x, y;
David Howells17926a72007-04-26 15:48:28 -0700286 int ret;
287
288 sp = rxrpc_skb(skb);
289
290 _enter("{%d{%x}},{#%u},%zu,",
David Howells19ffa012016-04-04 14:00:36 +0100291 call->debug_id, key_serial(call->conn->params.key),
292 sp->hdr.seq, data_size);
David Howells17926a72007-04-26 15:48:28 -0700293
294 if (!call->conn->cipher)
295 return 0;
296
David Howells19ffa012016-04-04 14:00:36 +0100297 ret = key_validate(call->conn->params.key);
David Howells17926a72007-04-26 15:48:28 -0700298 if (ret < 0)
299 return ret;
300
David Howells1db88c52019-07-30 15:56:57 +0100301 req = rxkad_get_call_crypto(call);
302 if (!req)
303 return -ENOMEM;
304
David Howells17926a72007-04-26 15:48:28 -0700305 /* continue encrypting from where we left off */
306 memcpy(&iv, call->conn->csum_iv.x, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700307
308 /* calculate the security checksum */
David Howells01a90a42016-08-23 15:27:24 +0100309 x = (call->cid & RXRPC_CHANNELMASK) << (32 - RXRPC_CIDSHIFT);
David Howells0d12f8a2016-03-04 15:53:46 +0000310 x |= sp->hdr.seq & 0x3fffffff;
David Howells5a924b82016-09-22 00:29:31 +0100311 call->crypto_buf[0] = htonl(call->call_id);
Herbert Xua2636292016-06-26 14:55:24 -0700312 call->crypto_buf[1] = htonl(x);
David Howells17926a72007-04-26 15:48:28 -0700313
Herbert Xua2636292016-06-26 14:55:24 -0700314 sg_init_one(&sg, call->crypto_buf, 8);
Kees Cook69d826f2018-09-18 19:10:47 -0700315 skcipher_request_set_sync_tfm(req, call->conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800316 skcipher_request_set_callback(req, 0, NULL, NULL);
Herbert Xua2636292016-06-26 14:55:24 -0700317 skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800318 crypto_skcipher_encrypt(req);
319 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700320
Herbert Xua2636292016-06-26 14:55:24 -0700321 y = ntohl(call->crypto_buf[1]);
Al Viro91e916c2008-03-29 03:08:38 +0000322 y = (y >> 16) & 0xffff;
323 if (y == 0)
324 y = 1; /* zero checksums are not permitted */
David Howells0d12f8a2016-03-04 15:53:46 +0000325 sp->hdr.cksum = y;
David Howells17926a72007-04-26 15:48:28 -0700326
David Howells19ffa012016-04-04 14:00:36 +0100327 switch (call->conn->params.security_level) {
David Howells17926a72007-04-26 15:48:28 -0700328 case RXRPC_SECURITY_PLAIN:
329 ret = 0;
330 break;
331 case RXRPC_SECURITY_AUTH:
Kees Cook54424d32018-08-03 10:15:25 +0100332 ret = rxkad_secure_packet_auth(call, skb, data_size, sechdr,
333 req);
David Howells17926a72007-04-26 15:48:28 -0700334 break;
335 case RXRPC_SECURITY_ENCRYPT:
336 ret = rxkad_secure_packet_encrypt(call, skb, data_size,
Kees Cook54424d32018-08-03 10:15:25 +0100337 sechdr, req);
David Howells17926a72007-04-26 15:48:28 -0700338 break;
339 default:
340 ret = -EPERM;
341 break;
342 }
343
Al Viro91e916c2008-03-29 03:08:38 +0000344 _leave(" = %d [set %hx]", ret, y);
David Howells17926a72007-04-26 15:48:28 -0700345 return ret;
346}
347
348/*
349 * decrypt partial encryption on a packet (level 1 security)
350 */
David Howells5a429762016-09-06 22:19:51 +0100351static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
David Howells248f2192016-09-08 11:10:12 +0100352 unsigned int offset, unsigned int len,
Kees Cook54424d32018-08-03 10:15:25 +0100353 rxrpc_seq_t seq,
354 struct skcipher_request *req)
David Howells17926a72007-04-26 15:48:28 -0700355{
356 struct rxkad_level1_hdr sechdr;
David Howells17926a72007-04-26 15:48:28 -0700357 struct rxrpc_crypt iv;
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700358 struct scatterlist sg[16];
David Howellsfb46f6e2017-04-06 10:12:00 +0100359 bool aborted;
David Howells17926a72007-04-26 15:48:28 -0700360 u32 data_size, buf;
361 u16 check;
David Howellsd0d5c0c2019-08-27 10:13:46 +0100362 int ret;
David Howells17926a72007-04-26 15:48:28 -0700363
364 _enter("");
365
David Howells248f2192016-09-08 11:10:12 +0100366 if (len < 8) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100367 aborted = rxrpc_abort_eproto(call, skb, "rxkad_1_hdr", "V1H",
368 RXKADSEALEDINCON);
David Howells5a429762016-09-06 22:19:51 +0100369 goto protocol_error;
370 }
David Howells17926a72007-04-26 15:48:28 -0700371
David Howells248f2192016-09-08 11:10:12 +0100372 /* Decrypt the skbuff in-place. TODO: We really want to decrypt
373 * directly into the target buffer.
374 */
David Howellsd0d5c0c2019-08-27 10:13:46 +0100375 sg_init_table(sg, ARRAY_SIZE(sg));
Jason A. Donenfeld89a5ea92017-06-04 04:16:24 +0200376 ret = skb_to_sgvec(skb, sg, offset, 8);
377 if (unlikely(ret < 0))
378 return ret;
David Howells17926a72007-04-26 15:48:28 -0700379
380 /* start the decryption afresh */
381 memset(&iv, 0, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700382
Kees Cook69d826f2018-09-18 19:10:47 -0700383 skcipher_request_set_sync_tfm(req, call->conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800384 skcipher_request_set_callback(req, 0, NULL, NULL);
385 skcipher_request_set_crypt(req, sg, sg, 8, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800386 crypto_skcipher_decrypt(req);
387 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700388
David Howells5a429762016-09-06 22:19:51 +0100389 /* Extract the decrypted packet length */
David Howells248f2192016-09-08 11:10:12 +0100390 if (skb_copy_bits(skb, offset, &sechdr, sizeof(sechdr)) < 0) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100391 aborted = rxrpc_abort_eproto(call, skb, "rxkad_1_len", "XV1",
392 RXKADDATALEN);
David Howells5a429762016-09-06 22:19:51 +0100393 goto protocol_error;
394 }
David Howells248f2192016-09-08 11:10:12 +0100395 offset += sizeof(sechdr);
396 len -= sizeof(sechdr);
David Howells17926a72007-04-26 15:48:28 -0700397
398 buf = ntohl(sechdr.data_size);
399 data_size = buf & 0xffff;
400
401 check = buf >> 16;
David Howells5a429762016-09-06 22:19:51 +0100402 check ^= seq ^ call->call_id;
David Howells17926a72007-04-26 15:48:28 -0700403 check &= 0xffff;
404 if (check != 0) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100405 aborted = rxrpc_abort_eproto(call, skb, "rxkad_1_check", "V1C",
406 RXKADSEALEDINCON);
David Howells17926a72007-04-26 15:48:28 -0700407 goto protocol_error;
408 }
409
David Howells248f2192016-09-08 11:10:12 +0100410 if (data_size > len) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100411 aborted = rxrpc_abort_eproto(call, skb, "rxkad_1_datalen", "V1L",
412 RXKADDATALEN);
David Howells5a429762016-09-06 22:19:51 +0100413 goto protocol_error;
414 }
David Howells17926a72007-04-26 15:48:28 -0700415
416 _leave(" = 0 [dlen=%x]", data_size);
417 return 0;
418
David Howells17926a72007-04-26 15:48:28 -0700419protocol_error:
David Howellsfb46f6e2017-04-06 10:12:00 +0100420 if (aborted)
421 rxrpc_send_abort_packet(call);
David Howells17926a72007-04-26 15:48:28 -0700422 return -EPROTO;
David Howells17926a72007-04-26 15:48:28 -0700423}
424
425/*
426 * wholly decrypt a packet (level 2 security)
427 */
David Howells5a429762016-09-06 22:19:51 +0100428static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
David Howells248f2192016-09-08 11:10:12 +0100429 unsigned int offset, unsigned int len,
Kees Cook54424d32018-08-03 10:15:25 +0100430 rxrpc_seq_t seq,
431 struct skcipher_request *req)
David Howells17926a72007-04-26 15:48:28 -0700432{
David Howells33941282009-09-14 01:17:35 +0000433 const struct rxrpc_key_token *token;
David Howells17926a72007-04-26 15:48:28 -0700434 struct rxkad_level2_hdr sechdr;
David Howells17926a72007-04-26 15:48:28 -0700435 struct rxrpc_crypt iv;
436 struct scatterlist _sg[4], *sg;
David Howellsfb46f6e2017-04-06 10:12:00 +0100437 bool aborted;
David Howells17926a72007-04-26 15:48:28 -0700438 u32 data_size, buf;
439 u16 check;
Jason A. Donenfeld89a5ea92017-06-04 04:16:24 +0200440 int nsg, ret;
David Howells17926a72007-04-26 15:48:28 -0700441
442 _enter(",{%d}", skb->len);
443
David Howells248f2192016-09-08 11:10:12 +0100444 if (len < 8) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100445 aborted = rxrpc_abort_eproto(call, skb, "rxkad_2_hdr", "V2H",
446 RXKADSEALEDINCON);
David Howells5a429762016-09-06 22:19:51 +0100447 goto protocol_error;
448 }
David Howells17926a72007-04-26 15:48:28 -0700449
David Howells248f2192016-09-08 11:10:12 +0100450 /* Decrypt the skbuff in-place. TODO: We really want to decrypt
451 * directly into the target buffer.
452 */
David Howells17926a72007-04-26 15:48:28 -0700453 sg = _sg;
David Howellsd0d5c0c2019-08-27 10:13:46 +0100454 nsg = skb_shinfo(skb)->nr_frags;
455 if (nsg <= 4) {
456 nsg = 4;
457 } else {
Kees Cook6da2ec52018-06-12 13:55:00 -0700458 sg = kmalloc_array(nsg, sizeof(*sg), GFP_NOIO);
David Howells17926a72007-04-26 15:48:28 -0700459 if (!sg)
460 goto nomem;
461 }
462
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700463 sg_init_table(sg, nsg);
Jason A. Donenfeld89a5ea92017-06-04 04:16:24 +0200464 ret = skb_to_sgvec(skb, sg, offset, len);
465 if (unlikely(ret < 0)) {
466 if (sg != _sg)
467 kfree(sg);
468 return ret;
469 }
David Howells17926a72007-04-26 15:48:28 -0700470
471 /* decrypt from the session key */
David Howells19ffa012016-04-04 14:00:36 +0100472 token = call->conn->params.key->payload.data[0];
David Howells33941282009-09-14 01:17:35 +0000473 memcpy(&iv, token->kad->session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700474
Kees Cook69d826f2018-09-18 19:10:47 -0700475 skcipher_request_set_sync_tfm(req, call->conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800476 skcipher_request_set_callback(req, 0, NULL, NULL);
David Howells248f2192016-09-08 11:10:12 +0100477 skcipher_request_set_crypt(req, sg, sg, len, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800478 crypto_skcipher_decrypt(req);
479 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700480 if (sg != _sg)
481 kfree(sg);
482
David Howells5a429762016-09-06 22:19:51 +0100483 /* Extract the decrypted packet length */
David Howells248f2192016-09-08 11:10:12 +0100484 if (skb_copy_bits(skb, offset, &sechdr, sizeof(sechdr)) < 0) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100485 aborted = rxrpc_abort_eproto(call, skb, "rxkad_2_len", "XV2",
486 RXKADDATALEN);
David Howells5a429762016-09-06 22:19:51 +0100487 goto protocol_error;
488 }
David Howells248f2192016-09-08 11:10:12 +0100489 offset += sizeof(sechdr);
490 len -= sizeof(sechdr);
David Howells17926a72007-04-26 15:48:28 -0700491
492 buf = ntohl(sechdr.data_size);
493 data_size = buf & 0xffff;
494
495 check = buf >> 16;
David Howells5a429762016-09-06 22:19:51 +0100496 check ^= seq ^ call->call_id;
David Howells17926a72007-04-26 15:48:28 -0700497 check &= 0xffff;
498 if (check != 0) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100499 aborted = rxrpc_abort_eproto(call, skb, "rxkad_2_check", "V2C",
500 RXKADSEALEDINCON);
David Howells17926a72007-04-26 15:48:28 -0700501 goto protocol_error;
502 }
503
David Howells248f2192016-09-08 11:10:12 +0100504 if (data_size > len) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100505 aborted = rxrpc_abort_eproto(call, skb, "rxkad_2_datalen", "V2L",
506 RXKADDATALEN);
David Howells5a429762016-09-06 22:19:51 +0100507 goto protocol_error;
508 }
David Howells17926a72007-04-26 15:48:28 -0700509
510 _leave(" = 0 [dlen=%x]", data_size);
511 return 0;
512
David Howells17926a72007-04-26 15:48:28 -0700513protocol_error:
David Howellsfb46f6e2017-04-06 10:12:00 +0100514 if (aborted)
515 rxrpc_send_abort_packet(call);
David Howells17926a72007-04-26 15:48:28 -0700516 return -EPROTO;
517
518nomem:
519 _leave(" = -ENOMEM");
520 return -ENOMEM;
521}
522
523/*
David Howells5a429762016-09-06 22:19:51 +0100524 * Verify the security on a received packet or subpacket (if part of a
525 * jumbo packet).
David Howells17926a72007-04-26 15:48:28 -0700526 */
David Howells5a429762016-09-06 22:19:51 +0100527static int rxkad_verify_packet(struct rxrpc_call *call, struct sk_buff *skb,
David Howells248f2192016-09-08 11:10:12 +0100528 unsigned int offset, unsigned int len,
David Howells5a429762016-09-06 22:19:51 +0100529 rxrpc_seq_t seq, u16 expected_cksum)
David Howells17926a72007-04-26 15:48:28 -0700530{
David Howells1db88c52019-07-30 15:56:57 +0100531 struct skcipher_request *req;
David Howells17926a72007-04-26 15:48:28 -0700532 struct rxrpc_crypt iv;
Herbert Xua2636292016-06-26 14:55:24 -0700533 struct scatterlist sg;
David Howellsfb46f6e2017-04-06 10:12:00 +0100534 bool aborted;
David Howells0d12f8a2016-03-04 15:53:46 +0000535 u16 cksum;
536 u32 x, y;
David Howells17926a72007-04-26 15:48:28 -0700537
538 _enter("{%d{%x}},{#%u}",
David Howells5a429762016-09-06 22:19:51 +0100539 call->debug_id, key_serial(call->conn->params.key), seq);
David Howells17926a72007-04-26 15:48:28 -0700540
541 if (!call->conn->cipher)
542 return 0;
543
David Howells1db88c52019-07-30 15:56:57 +0100544 req = rxkad_get_call_crypto(call);
545 if (!req)
546 return -ENOMEM;
547
David Howells17926a72007-04-26 15:48:28 -0700548 /* continue encrypting from where we left off */
549 memcpy(&iv, call->conn->csum_iv.x, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700550
551 /* validate the security checksum */
David Howells01a90a42016-08-23 15:27:24 +0100552 x = (call->cid & RXRPC_CHANNELMASK) << (32 - RXRPC_CIDSHIFT);
David Howells5a429762016-09-06 22:19:51 +0100553 x |= seq & 0x3fffffff;
Herbert Xua2636292016-06-26 14:55:24 -0700554 call->crypto_buf[0] = htonl(call->call_id);
555 call->crypto_buf[1] = htonl(x);
David Howells17926a72007-04-26 15:48:28 -0700556
Herbert Xua2636292016-06-26 14:55:24 -0700557 sg_init_one(&sg, call->crypto_buf, 8);
Kees Cook69d826f2018-09-18 19:10:47 -0700558 skcipher_request_set_sync_tfm(req, call->conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800559 skcipher_request_set_callback(req, 0, NULL, NULL);
Herbert Xua2636292016-06-26 14:55:24 -0700560 skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800561 crypto_skcipher_encrypt(req);
562 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700563
Herbert Xua2636292016-06-26 14:55:24 -0700564 y = ntohl(call->crypto_buf[1]);
David Howells0d12f8a2016-03-04 15:53:46 +0000565 cksum = (y >> 16) & 0xffff;
566 if (cksum == 0)
567 cksum = 1; /* zero checksums are not permitted */
David Howells17926a72007-04-26 15:48:28 -0700568
David Howells5a429762016-09-06 22:19:51 +0100569 if (cksum != expected_cksum) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100570 aborted = rxrpc_abort_eproto(call, skb, "rxkad_csum", "VCK",
571 RXKADSEALEDINCON);
572 goto protocol_error;
David Howells17926a72007-04-26 15:48:28 -0700573 }
574
David Howells19ffa012016-04-04 14:00:36 +0100575 switch (call->conn->params.security_level) {
David Howells17926a72007-04-26 15:48:28 -0700576 case RXRPC_SECURITY_PLAIN:
David Howells5a429762016-09-06 22:19:51 +0100577 return 0;
David Howells17926a72007-04-26 15:48:28 -0700578 case RXRPC_SECURITY_AUTH:
Kees Cook54424d32018-08-03 10:15:25 +0100579 return rxkad_verify_packet_1(call, skb, offset, len, seq, req);
David Howells17926a72007-04-26 15:48:28 -0700580 case RXRPC_SECURITY_ENCRYPT:
Kees Cook54424d32018-08-03 10:15:25 +0100581 return rxkad_verify_packet_2(call, skb, offset, len, seq, req);
David Howells17926a72007-04-26 15:48:28 -0700582 default:
David Howells5a429762016-09-06 22:19:51 +0100583 return -ENOANO;
David Howells17926a72007-04-26 15:48:28 -0700584 }
David Howellsfb46f6e2017-04-06 10:12:00 +0100585
586protocol_error:
587 if (aborted)
588 rxrpc_send_abort_packet(call);
589 return -EPROTO;
David Howells17926a72007-04-26 15:48:28 -0700590}
591
592/*
David Howells248f2192016-09-08 11:10:12 +0100593 * Locate the data contained in a packet that was partially encrypted.
594 */
595static void rxkad_locate_data_1(struct rxrpc_call *call, struct sk_buff *skb,
596 unsigned int *_offset, unsigned int *_len)
597{
598 struct rxkad_level1_hdr sechdr;
599
600 if (skb_copy_bits(skb, *_offset, &sechdr, sizeof(sechdr)) < 0)
601 BUG();
602 *_offset += sizeof(sechdr);
603 *_len = ntohl(sechdr.data_size) & 0xffff;
604}
605
606/*
607 * Locate the data contained in a packet that was completely encrypted.
608 */
609static void rxkad_locate_data_2(struct rxrpc_call *call, struct sk_buff *skb,
610 unsigned int *_offset, unsigned int *_len)
611{
612 struct rxkad_level2_hdr sechdr;
613
614 if (skb_copy_bits(skb, *_offset, &sechdr, sizeof(sechdr)) < 0)
615 BUG();
616 *_offset += sizeof(sechdr);
617 *_len = ntohl(sechdr.data_size) & 0xffff;
618}
619
620/*
621 * Locate the data contained in an already decrypted packet.
622 */
623static void rxkad_locate_data(struct rxrpc_call *call, struct sk_buff *skb,
624 unsigned int *_offset, unsigned int *_len)
625{
626 switch (call->conn->params.security_level) {
627 case RXRPC_SECURITY_AUTH:
628 rxkad_locate_data_1(call, skb, _offset, _len);
629 return;
630 case RXRPC_SECURITY_ENCRYPT:
631 rxkad_locate_data_2(call, skb, _offset, _len);
632 return;
633 default:
634 return;
635 }
636}
637
638/*
David Howells17926a72007-04-26 15:48:28 -0700639 * issue a challenge
640 */
641static int rxkad_issue_challenge(struct rxrpc_connection *conn)
642{
643 struct rxkad_challenge challenge;
David Howells0d12f8a2016-03-04 15:53:46 +0000644 struct rxrpc_wire_header whdr;
David Howells17926a72007-04-26 15:48:28 -0700645 struct msghdr msg;
646 struct kvec iov[2];
647 size_t len;
David Howells0d12f8a2016-03-04 15:53:46 +0000648 u32 serial;
David Howells17926a72007-04-26 15:48:28 -0700649 int ret;
650
David Howells063c60d2019-12-20 16:17:16 +0000651 _enter("{%d,%x}", conn->debug_id, key_serial(conn->server_key));
David Howells17926a72007-04-26 15:48:28 -0700652
David Howells063c60d2019-12-20 16:17:16 +0000653 ret = key_validate(conn->server_key);
David Howells17926a72007-04-26 15:48:28 -0700654 if (ret < 0)
655 return ret;
656
657 get_random_bytes(&conn->security_nonce, sizeof(conn->security_nonce));
658
659 challenge.version = htonl(2);
660 challenge.nonce = htonl(conn->security_nonce);
661 challenge.min_level = htonl(0);
662 challenge.__padding = 0;
663
David Howells7b674e32017-08-29 10:18:37 +0100664 msg.msg_name = &conn->params.peer->srx.transport;
665 msg.msg_namelen = conn->params.peer->srx.transport_len;
David Howells17926a72007-04-26 15:48:28 -0700666 msg.msg_control = NULL;
667 msg.msg_controllen = 0;
668 msg.msg_flags = 0;
669
David Howells19ffa012016-04-04 14:00:36 +0100670 whdr.epoch = htonl(conn->proto.epoch);
671 whdr.cid = htonl(conn->proto.cid);
David Howells0d12f8a2016-03-04 15:53:46 +0000672 whdr.callNumber = 0;
673 whdr.seq = 0;
674 whdr.type = RXRPC_PACKET_TYPE_CHALLENGE;
675 whdr.flags = conn->out_clientflag;
676 whdr.userStatus = 0;
677 whdr.securityIndex = conn->security_ix;
678 whdr._rsvd = 0;
David Howells68d6d1a2017-06-05 14:30:49 +0100679 whdr.serviceId = htons(conn->service_id);
David Howells17926a72007-04-26 15:48:28 -0700680
David Howells0d12f8a2016-03-04 15:53:46 +0000681 iov[0].iov_base = &whdr;
682 iov[0].iov_len = sizeof(whdr);
David Howells17926a72007-04-26 15:48:28 -0700683 iov[1].iov_base = &challenge;
684 iov[1].iov_len = sizeof(challenge);
685
686 len = iov[0].iov_len + iov[1].iov_len;
687
David Howells0d12f8a2016-03-04 15:53:46 +0000688 serial = atomic_inc_return(&conn->serial);
689 whdr.serial = htonl(serial);
690 _proto("Tx CHALLENGE %%%u", serial);
David Howells17926a72007-04-26 15:48:28 -0700691
David Howells85f32272016-04-04 14:00:36 +0100692 ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
David Howells17926a72007-04-26 15:48:28 -0700693 if (ret < 0) {
David Howells6b47fe12018-05-10 23:26:01 +0100694 trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
David Howells4764c0d2018-07-23 17:18:37 +0100695 rxrpc_tx_point_rxkad_challenge);
David Howells17926a72007-04-26 15:48:28 -0700696 return -EAGAIN;
697 }
698
David Howells330bdcf2018-08-08 11:30:02 +0100699 conn->params.peer->last_tx_at = ktime_get_seconds();
David Howells4764c0d2018-07-23 17:18:37 +0100700 trace_rxrpc_tx_packet(conn->debug_id, &whdr,
701 rxrpc_tx_point_rxkad_challenge);
David Howells17926a72007-04-26 15:48:28 -0700702 _leave(" = 0");
703 return 0;
704}
705
706/*
707 * send a Kerberos security response
708 */
709static int rxkad_send_response(struct rxrpc_connection *conn,
David Howells0d12f8a2016-03-04 15:53:46 +0000710 struct rxrpc_host_header *hdr,
David Howells17926a72007-04-26 15:48:28 -0700711 struct rxkad_response *resp,
712 const struct rxkad_key *s2)
713{
David Howells0d12f8a2016-03-04 15:53:46 +0000714 struct rxrpc_wire_header whdr;
David Howells17926a72007-04-26 15:48:28 -0700715 struct msghdr msg;
716 struct kvec iov[3];
717 size_t len;
David Howells0d12f8a2016-03-04 15:53:46 +0000718 u32 serial;
David Howells17926a72007-04-26 15:48:28 -0700719 int ret;
720
721 _enter("");
722
David Howells7b674e32017-08-29 10:18:37 +0100723 msg.msg_name = &conn->params.peer->srx.transport;
724 msg.msg_namelen = conn->params.peer->srx.transport_len;
David Howells17926a72007-04-26 15:48:28 -0700725 msg.msg_control = NULL;
726 msg.msg_controllen = 0;
727 msg.msg_flags = 0;
728
David Howells0d12f8a2016-03-04 15:53:46 +0000729 memset(&whdr, 0, sizeof(whdr));
730 whdr.epoch = htonl(hdr->epoch);
731 whdr.cid = htonl(hdr->cid);
732 whdr.type = RXRPC_PACKET_TYPE_RESPONSE;
733 whdr.flags = conn->out_clientflag;
734 whdr.securityIndex = hdr->securityIndex;
735 whdr.serviceId = htons(hdr->serviceId);
David Howells17926a72007-04-26 15:48:28 -0700736
David Howells0d12f8a2016-03-04 15:53:46 +0000737 iov[0].iov_base = &whdr;
738 iov[0].iov_len = sizeof(whdr);
David Howells17926a72007-04-26 15:48:28 -0700739 iov[1].iov_base = resp;
740 iov[1].iov_len = sizeof(*resp);
David Howells0d12f8a2016-03-04 15:53:46 +0000741 iov[2].iov_base = (void *)s2->ticket;
David Howells17926a72007-04-26 15:48:28 -0700742 iov[2].iov_len = s2->ticket_len;
743
744 len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
745
David Howells0d12f8a2016-03-04 15:53:46 +0000746 serial = atomic_inc_return(&conn->serial);
747 whdr.serial = htonl(serial);
748 _proto("Tx RESPONSE %%%u", serial);
David Howells17926a72007-04-26 15:48:28 -0700749
David Howells85f32272016-04-04 14:00:36 +0100750 ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 3, len);
David Howells17926a72007-04-26 15:48:28 -0700751 if (ret < 0) {
David Howells6b47fe12018-05-10 23:26:01 +0100752 trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
David Howells4764c0d2018-07-23 17:18:37 +0100753 rxrpc_tx_point_rxkad_response);
David Howells17926a72007-04-26 15:48:28 -0700754 return -EAGAIN;
755 }
756
David Howells330bdcf2018-08-08 11:30:02 +0100757 conn->params.peer->last_tx_at = ktime_get_seconds();
David Howells17926a72007-04-26 15:48:28 -0700758 _leave(" = 0");
759 return 0;
760}
761
762/*
763 * calculate the response checksum
764 */
765static void rxkad_calc_response_checksum(struct rxkad_response *response)
766{
767 u32 csum = 1000003;
768 int loop;
769 u8 *p = (u8 *) response;
770
771 for (loop = sizeof(*response); loop > 0; loop--)
772 csum = csum * 0x10204081 + *p++;
773
774 response->encrypted.checksum = htonl(csum);
775}
776
777/*
David Howells17926a72007-04-26 15:48:28 -0700778 * encrypt the response packet
779 */
David Howells1db88c52019-07-30 15:56:57 +0100780static int rxkad_encrypt_response(struct rxrpc_connection *conn,
781 struct rxkad_response *resp,
782 const struct rxkad_key *s2)
David Howells17926a72007-04-26 15:48:28 -0700783{
David Howells1db88c52019-07-30 15:56:57 +0100784 struct skcipher_request *req;
David Howells17926a72007-04-26 15:48:28 -0700785 struct rxrpc_crypt iv;
Herbert Xua2636292016-06-26 14:55:24 -0700786 struct scatterlist sg[1];
David Howells17926a72007-04-26 15:48:28 -0700787
David Howells1db88c52019-07-30 15:56:57 +0100788 req = skcipher_request_alloc(&conn->cipher->base, GFP_NOFS);
789 if (!req)
790 return -ENOMEM;
791
David Howells17926a72007-04-26 15:48:28 -0700792 /* continue encrypting from where we left off */
793 memcpy(&iv, s2->session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700794
Herbert Xua2636292016-06-26 14:55:24 -0700795 sg_init_table(sg, 1);
796 sg_set_buf(sg, &resp->encrypted, sizeof(resp->encrypted));
Kees Cook69d826f2018-09-18 19:10:47 -0700797 skcipher_request_set_sync_tfm(req, conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800798 skcipher_request_set_callback(req, 0, NULL, NULL);
799 skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800800 crypto_skcipher_encrypt(req);
David Howells1db88c52019-07-30 15:56:57 +0100801 skcipher_request_free(req);
802 return 0;
David Howells17926a72007-04-26 15:48:28 -0700803}
804
805/*
806 * respond to a challenge packet
807 */
808static int rxkad_respond_to_challenge(struct rxrpc_connection *conn,
809 struct sk_buff *skb,
810 u32 *_abort_code)
811{
David Howells33941282009-09-14 01:17:35 +0000812 const struct rxrpc_key_token *token;
David Howells17926a72007-04-26 15:48:28 -0700813 struct rxkad_challenge challenge;
David Howells8c2f8262018-02-08 15:59:07 +0000814 struct rxkad_response *resp;
David Howells248f2192016-09-08 11:10:12 +0100815 struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
David Howellsfb46f6e2017-04-06 10:12:00 +0100816 const char *eproto;
David Howells17926a72007-04-26 15:48:28 -0700817 u32 version, nonce, min_level, abort_code;
818 int ret;
819
David Howells19ffa012016-04-04 14:00:36 +0100820 _enter("{%d,%x}", conn->debug_id, key_serial(conn->params.key));
David Howells17926a72007-04-26 15:48:28 -0700821
David Howellsfb46f6e2017-04-06 10:12:00 +0100822 eproto = tracepoint_string("chall_no_key");
David Howellsef686222017-04-06 10:11:59 +0100823 abort_code = RX_PROTOCOL_ERROR;
824 if (!conn->params.key)
825 goto protocol_error;
David Howells17926a72007-04-26 15:48:28 -0700826
David Howellsef686222017-04-06 10:11:59 +0100827 abort_code = RXKADEXPIRED;
David Howells19ffa012016-04-04 14:00:36 +0100828 ret = key_validate(conn->params.key);
David Howellsef686222017-04-06 10:11:59 +0100829 if (ret < 0)
830 goto other_error;
David Howells17926a72007-04-26 15:48:28 -0700831
David Howellsfb46f6e2017-04-06 10:12:00 +0100832 eproto = tracepoint_string("chall_short");
David Howells17926a72007-04-26 15:48:28 -0700833 abort_code = RXKADPACKETSHORT;
David Howells775e5b72016-09-30 13:26:03 +0100834 if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
835 &challenge, sizeof(challenge)) < 0)
David Howells17926a72007-04-26 15:48:28 -0700836 goto protocol_error;
837
838 version = ntohl(challenge.version);
839 nonce = ntohl(challenge.nonce);
840 min_level = ntohl(challenge.min_level);
841
842 _proto("Rx CHALLENGE %%%u { v=%u n=%u ml=%u }",
David Howells0d12f8a2016-03-04 15:53:46 +0000843 sp->hdr.serial, version, nonce, min_level);
David Howells17926a72007-04-26 15:48:28 -0700844
David Howellsfb46f6e2017-04-06 10:12:00 +0100845 eproto = tracepoint_string("chall_ver");
David Howells17926a72007-04-26 15:48:28 -0700846 abort_code = RXKADINCONSISTENCY;
847 if (version != RXKAD_VERSION)
848 goto protocol_error;
849
850 abort_code = RXKADLEVELFAIL;
David Howellsef686222017-04-06 10:11:59 +0100851 ret = -EACCES;
David Howells19ffa012016-04-04 14:00:36 +0100852 if (conn->params.security_level < min_level)
David Howellsef686222017-04-06 10:11:59 +0100853 goto other_error;
David Howells17926a72007-04-26 15:48:28 -0700854
David Howells19ffa012016-04-04 14:00:36 +0100855 token = conn->params.key->payload.data[0];
David Howells17926a72007-04-26 15:48:28 -0700856
857 /* build the response packet */
David Howells8c2f8262018-02-08 15:59:07 +0000858 resp = kzalloc(sizeof(struct rxkad_response), GFP_NOFS);
859 if (!resp)
860 return -ENOMEM;
David Howells17926a72007-04-26 15:48:28 -0700861
David Howells8c2f8262018-02-08 15:59:07 +0000862 resp->version = htonl(RXKAD_VERSION);
863 resp->encrypted.epoch = htonl(conn->proto.epoch);
864 resp->encrypted.cid = htonl(conn->proto.cid);
865 resp->encrypted.securityIndex = htonl(conn->security_ix);
866 resp->encrypted.inc_nonce = htonl(nonce + 1);
867 resp->encrypted.level = htonl(conn->params.security_level);
868 resp->kvno = htonl(token->kad->kvno);
869 resp->ticket_len = htonl(token->kad->ticket_len);
870 resp->encrypted.call_id[0] = htonl(conn->channels[0].call_counter);
871 resp->encrypted.call_id[1] = htonl(conn->channels[1].call_counter);
872 resp->encrypted.call_id[2] = htonl(conn->channels[2].call_counter);
873 resp->encrypted.call_id[3] = htonl(conn->channels[3].call_counter);
David Howells17926a72007-04-26 15:48:28 -0700874
875 /* calculate the response checksum and then do the encryption */
David Howells8c2f8262018-02-08 15:59:07 +0000876 rxkad_calc_response_checksum(resp);
David Howells1db88c52019-07-30 15:56:57 +0100877 ret = rxkad_encrypt_response(conn, resp, token->kad);
878 if (ret == 0)
879 ret = rxkad_send_response(conn, &sp->hdr, resp, token->kad);
David Howells8c2f8262018-02-08 15:59:07 +0000880 kfree(resp);
881 return ret;
David Howells17926a72007-04-26 15:48:28 -0700882
883protocol_error:
David Howellsfb46f6e2017-04-06 10:12:00 +0100884 trace_rxrpc_rx_eproto(NULL, sp->hdr.serial, eproto);
David Howellsef686222017-04-06 10:11:59 +0100885 ret = -EPROTO;
886other_error:
David Howells17926a72007-04-26 15:48:28 -0700887 *_abort_code = abort_code;
David Howellsef686222017-04-06 10:11:59 +0100888 return ret;
David Howells17926a72007-04-26 15:48:28 -0700889}
890
891/*
892 * decrypt the kerberos IV ticket in the response
893 */
894static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
David Howellsfb46f6e2017-04-06 10:12:00 +0100895 struct sk_buff *skb,
David Howells17926a72007-04-26 15:48:28 -0700896 void *ticket, size_t ticket_len,
897 struct rxrpc_crypt *_session_key,
Baolin Wang10674a02017-08-29 10:15:40 +0100898 time64_t *_expiry,
David Howells17926a72007-04-26 15:48:28 -0700899 u32 *_abort_code)
900{
Herbert Xu1afe5932016-01-24 21:19:01 +0800901 struct skcipher_request *req;
David Howellsfb46f6e2017-04-06 10:12:00 +0100902 struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
David Howells17926a72007-04-26 15:48:28 -0700903 struct rxrpc_crypt iv, key;
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700904 struct scatterlist sg[1];
David Howells17926a72007-04-26 15:48:28 -0700905 struct in_addr addr;
Eric Dumazet95c96172012-04-15 05:58:06 +0000906 unsigned int life;
David Howellsfb46f6e2017-04-06 10:12:00 +0100907 const char *eproto;
Baolin Wang10674a02017-08-29 10:15:40 +0100908 time64_t issue, now;
David Howells17926a72007-04-26 15:48:28 -0700909 bool little_endian;
910 int ret;
David Howellsfb46f6e2017-04-06 10:12:00 +0100911 u32 abort_code;
David Howells17926a72007-04-26 15:48:28 -0700912 u8 *p, *q, *name, *end;
913
914 _enter("{%d},{%x}", conn->debug_id, key_serial(conn->server_key));
915
916 *_expiry = 0;
917
918 ret = key_validate(conn->server_key);
919 if (ret < 0) {
920 switch (ret) {
921 case -EKEYEXPIRED:
David Howellsfb46f6e2017-04-06 10:12:00 +0100922 abort_code = RXKADEXPIRED;
David Howellsef686222017-04-06 10:11:59 +0100923 goto other_error;
David Howells17926a72007-04-26 15:48:28 -0700924 default:
David Howellsfb46f6e2017-04-06 10:12:00 +0100925 abort_code = RXKADNOAUTH;
David Howellsef686222017-04-06 10:11:59 +0100926 goto other_error;
David Howells17926a72007-04-26 15:48:28 -0700927 }
928 }
929
David Howells146aa8b2015-10-21 14:04:48 +0100930 ASSERT(conn->server_key->payload.data[0] != NULL);
David Howells17926a72007-04-26 15:48:28 -0700931 ASSERTCMP((unsigned long) ticket & 7UL, ==, 0);
932
David Howells146aa8b2015-10-21 14:04:48 +0100933 memcpy(&iv, &conn->server_key->payload.data[2], sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700934
David Howellsef686222017-04-06 10:11:59 +0100935 ret = -ENOMEM;
Herbert Xu1afe5932016-01-24 21:19:01 +0800936 req = skcipher_request_alloc(conn->server_key->payload.data[0],
937 GFP_NOFS);
David Howellsef686222017-04-06 10:11:59 +0100938 if (!req)
939 goto temporary_error;
David Howells17926a72007-04-26 15:48:28 -0700940
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700941 sg_init_one(&sg[0], ticket, ticket_len);
Herbert Xu1afe5932016-01-24 21:19:01 +0800942 skcipher_request_set_callback(req, 0, NULL, NULL);
943 skcipher_request_set_crypt(req, sg, sg, ticket_len, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800944 crypto_skcipher_decrypt(req);
945 skcipher_request_free(req);
David Howells17926a72007-04-26 15:48:28 -0700946
947 p = ticket;
948 end = p + ticket_len;
949
David Howellsfb46f6e2017-04-06 10:12:00 +0100950#define Z(field) \
David Howells17926a72007-04-26 15:48:28 -0700951 ({ \
952 u8 *__str = p; \
David Howellsfb46f6e2017-04-06 10:12:00 +0100953 eproto = tracepoint_string("rxkad_bad_"#field); \
David Howells17926a72007-04-26 15:48:28 -0700954 q = memchr(p, 0, end - p); \
David Howellsfb46f6e2017-04-06 10:12:00 +0100955 if (!q || q - p > (field##_SZ)) \
David Howells17926a72007-04-26 15:48:28 -0700956 goto bad_ticket; \
957 for (; p < q; p++) \
958 if (!isprint(*p)) \
959 goto bad_ticket; \
960 p++; \
961 __str; \
962 })
963
964 /* extract the ticket flags */
965 _debug("KIV FLAGS: %x", *p);
966 little_endian = *p & 1;
967 p++;
968
969 /* extract the authentication name */
David Howellsfb46f6e2017-04-06 10:12:00 +0100970 name = Z(ANAME);
David Howells17926a72007-04-26 15:48:28 -0700971 _debug("KIV ANAME: %s", name);
972
973 /* extract the principal's instance */
David Howellsfb46f6e2017-04-06 10:12:00 +0100974 name = Z(INST);
David Howells17926a72007-04-26 15:48:28 -0700975 _debug("KIV INST : %s", name);
976
977 /* extract the principal's authentication domain */
David Howellsfb46f6e2017-04-06 10:12:00 +0100978 name = Z(REALM);
David Howells17926a72007-04-26 15:48:28 -0700979 _debug("KIV REALM: %s", name);
980
David Howellsfb46f6e2017-04-06 10:12:00 +0100981 eproto = tracepoint_string("rxkad_bad_len");
David Howells17926a72007-04-26 15:48:28 -0700982 if (end - p < 4 + 8 + 4 + 2)
983 goto bad_ticket;
984
985 /* get the IPv4 address of the entity that requested the ticket */
986 memcpy(&addr, p, sizeof(addr));
987 p += 4;
Harvey Harrison21454aa2008-10-31 00:54:56 -0700988 _debug("KIV ADDR : %pI4", &addr);
David Howells17926a72007-04-26 15:48:28 -0700989
990 /* get the session key from the ticket */
991 memcpy(&key, p, sizeof(key));
992 p += 8;
993 _debug("KIV KEY : %08x %08x", ntohl(key.n[0]), ntohl(key.n[1]));
994 memcpy(_session_key, &key, sizeof(key));
995
996 /* get the ticket's lifetime */
997 life = *p++ * 5 * 60;
998 _debug("KIV LIFE : %u", life);
999
1000 /* get the issue time of the ticket */
1001 if (little_endian) {
1002 __le32 stamp;
1003 memcpy(&stamp, p, 4);
Baolin Wang10674a02017-08-29 10:15:40 +01001004 issue = rxrpc_u32_to_time64(le32_to_cpu(stamp));
David Howells17926a72007-04-26 15:48:28 -07001005 } else {
1006 __be32 stamp;
1007 memcpy(&stamp, p, 4);
Baolin Wang10674a02017-08-29 10:15:40 +01001008 issue = rxrpc_u32_to_time64(be32_to_cpu(stamp));
David Howells17926a72007-04-26 15:48:28 -07001009 }
1010 p += 4;
Baolin Wang10674a02017-08-29 10:15:40 +01001011 now = ktime_get_real_seconds();
1012 _debug("KIV ISSUE: %llx [%llx]", issue, now);
David Howells17926a72007-04-26 15:48:28 -07001013
1014 /* check the ticket is in date */
1015 if (issue > now) {
David Howellsfb46f6e2017-04-06 10:12:00 +01001016 abort_code = RXKADNOAUTH;
David Howells17926a72007-04-26 15:48:28 -07001017 ret = -EKEYREJECTED;
David Howellsef686222017-04-06 10:11:59 +01001018 goto other_error;
David Howells17926a72007-04-26 15:48:28 -07001019 }
1020
1021 if (issue < now - life) {
David Howellsfb46f6e2017-04-06 10:12:00 +01001022 abort_code = RXKADEXPIRED;
David Howells17926a72007-04-26 15:48:28 -07001023 ret = -EKEYEXPIRED;
David Howellsef686222017-04-06 10:11:59 +01001024 goto other_error;
David Howells17926a72007-04-26 15:48:28 -07001025 }
1026
1027 *_expiry = issue + life;
1028
1029 /* get the service name */
David Howellsfb46f6e2017-04-06 10:12:00 +01001030 name = Z(SNAME);
David Howells17926a72007-04-26 15:48:28 -07001031 _debug("KIV SNAME: %s", name);
1032
1033 /* get the service instance name */
David Howellsfb46f6e2017-04-06 10:12:00 +01001034 name = Z(INST);
David Howells17926a72007-04-26 15:48:28 -07001035 _debug("KIV SINST: %s", name);
David Howellsef686222017-04-06 10:11:59 +01001036 return 0;
David Howells17926a72007-04-26 15:48:28 -07001037
1038bad_ticket:
David Howellsfb46f6e2017-04-06 10:12:00 +01001039 trace_rxrpc_rx_eproto(NULL, sp->hdr.serial, eproto);
1040 abort_code = RXKADBADTICKET;
David Howellsef686222017-04-06 10:11:59 +01001041 ret = -EPROTO;
1042other_error:
David Howellsfb46f6e2017-04-06 10:12:00 +01001043 *_abort_code = abort_code;
David Howellsef686222017-04-06 10:11:59 +01001044 return ret;
1045temporary_error:
1046 return ret;
David Howells17926a72007-04-26 15:48:28 -07001047}
1048
1049/*
1050 * decrypt the response packet
1051 */
1052static void rxkad_decrypt_response(struct rxrpc_connection *conn,
1053 struct rxkad_response *resp,
1054 const struct rxrpc_crypt *session_key)
1055{
David Howells1db88c52019-07-30 15:56:57 +01001056 struct skcipher_request *req = rxkad_ci_req;
Herbert Xua2636292016-06-26 14:55:24 -07001057 struct scatterlist sg[1];
David Howells17926a72007-04-26 15:48:28 -07001058 struct rxrpc_crypt iv;
1059
1060 _enter(",,%08x%08x",
1061 ntohl(session_key->n[0]), ntohl(session_key->n[1]));
1062
David Howells17926a72007-04-26 15:48:28 -07001063 mutex_lock(&rxkad_ci_mutex);
Kees Cook69d826f2018-09-18 19:10:47 -07001064 if (crypto_sync_skcipher_setkey(rxkad_ci, session_key->x,
David Howells1db88c52019-07-30 15:56:57 +01001065 sizeof(*session_key)) < 0)
David Howells17926a72007-04-26 15:48:28 -07001066 BUG();
1067
1068 memcpy(&iv, session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -07001069
Herbert Xua2636292016-06-26 14:55:24 -07001070 sg_init_table(sg, 1);
1071 sg_set_buf(sg, &resp->encrypted, sizeof(resp->encrypted));
Kees Cook69d826f2018-09-18 19:10:47 -07001072 skcipher_request_set_sync_tfm(req, rxkad_ci);
Herbert Xu1afe5932016-01-24 21:19:01 +08001073 skcipher_request_set_callback(req, 0, NULL, NULL);
1074 skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +08001075 crypto_skcipher_decrypt(req);
1076 skcipher_request_zero(req);
1077
David Howells17926a72007-04-26 15:48:28 -07001078 mutex_unlock(&rxkad_ci_mutex);
1079
1080 _leave("");
1081}
1082
1083/*
1084 * verify a response
1085 */
1086static int rxkad_verify_response(struct rxrpc_connection *conn,
1087 struct sk_buff *skb,
1088 u32 *_abort_code)
1089{
David Howells8c2f8262018-02-08 15:59:07 +00001090 struct rxkad_response *response;
David Howells248f2192016-09-08 11:10:12 +01001091 struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
David Howells17926a72007-04-26 15:48:28 -07001092 struct rxrpc_crypt session_key;
David Howellsfb46f6e2017-04-06 10:12:00 +01001093 const char *eproto;
Baolin Wang10674a02017-08-29 10:15:40 +01001094 time64_t expiry;
David Howells17926a72007-04-26 15:48:28 -07001095 void *ticket;
Al Viro91e916c2008-03-29 03:08:38 +00001096 u32 abort_code, version, kvno, ticket_len, level;
1097 __be32 csum;
David Howellsa1399f82016-06-27 14:39:44 +01001098 int ret, i;
David Howells17926a72007-04-26 15:48:28 -07001099
1100 _enter("{%d,%x}", conn->debug_id, key_serial(conn->server_key));
1101
David Howells8c2f8262018-02-08 15:59:07 +00001102 ret = -ENOMEM;
1103 response = kzalloc(sizeof(struct rxkad_response), GFP_NOFS);
1104 if (!response)
1105 goto temporary_error;
1106
David Howellsfb46f6e2017-04-06 10:12:00 +01001107 eproto = tracepoint_string("rxkad_rsp_short");
David Howells17926a72007-04-26 15:48:28 -07001108 abort_code = RXKADPACKETSHORT;
David Howells775e5b72016-09-30 13:26:03 +01001109 if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
David Howells8c2f8262018-02-08 15:59:07 +00001110 response, sizeof(*response)) < 0)
David Howells17926a72007-04-26 15:48:28 -07001111 goto protocol_error;
David Howells8c2f8262018-02-08 15:59:07 +00001112 if (!pskb_pull(skb, sizeof(*response)))
David Howells17926a72007-04-26 15:48:28 -07001113 BUG();
1114
David Howells8c2f8262018-02-08 15:59:07 +00001115 version = ntohl(response->version);
1116 ticket_len = ntohl(response->ticket_len);
1117 kvno = ntohl(response->kvno);
David Howells17926a72007-04-26 15:48:28 -07001118 _proto("Rx RESPONSE %%%u { v=%u kv=%u tl=%u }",
David Howells0d12f8a2016-03-04 15:53:46 +00001119 sp->hdr.serial, version, kvno, ticket_len);
David Howells17926a72007-04-26 15:48:28 -07001120
David Howellsfb46f6e2017-04-06 10:12:00 +01001121 eproto = tracepoint_string("rxkad_rsp_ver");
David Howells17926a72007-04-26 15:48:28 -07001122 abort_code = RXKADINCONSISTENCY;
1123 if (version != RXKAD_VERSION)
David Howells4aa9cb32007-12-07 04:31:47 -08001124 goto protocol_error;
David Howells17926a72007-04-26 15:48:28 -07001125
David Howellsfb46f6e2017-04-06 10:12:00 +01001126 eproto = tracepoint_string("rxkad_rsp_tktlen");
David Howells17926a72007-04-26 15:48:28 -07001127 abort_code = RXKADTICKETLEN;
1128 if (ticket_len < 4 || ticket_len > MAXKRB5TICKETLEN)
1129 goto protocol_error;
1130
David Howellsfb46f6e2017-04-06 10:12:00 +01001131 eproto = tracepoint_string("rxkad_rsp_unkkey");
David Howells17926a72007-04-26 15:48:28 -07001132 abort_code = RXKADUNKNOWNKEY;
1133 if (kvno >= RXKAD_TKT_TYPE_KERBEROS_V5)
1134 goto protocol_error;
1135
1136 /* extract the kerberos ticket and decrypt and decode it */
David Howellsef686222017-04-06 10:11:59 +01001137 ret = -ENOMEM;
David Howells17926a72007-04-26 15:48:28 -07001138 ticket = kmalloc(ticket_len, GFP_NOFS);
1139 if (!ticket)
David Howellsef686222017-04-06 10:11:59 +01001140 goto temporary_error;
David Howells17926a72007-04-26 15:48:28 -07001141
David Howellsfb46f6e2017-04-06 10:12:00 +01001142 eproto = tracepoint_string("rxkad_tkt_short");
David Howells17926a72007-04-26 15:48:28 -07001143 abort_code = RXKADPACKETSHORT;
David Howells775e5b72016-09-30 13:26:03 +01001144 if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
1145 ticket, ticket_len) < 0)
David Howells17926a72007-04-26 15:48:28 -07001146 goto protocol_error_free;
1147
David Howellsfb46f6e2017-04-06 10:12:00 +01001148 ret = rxkad_decrypt_ticket(conn, skb, ticket, ticket_len, &session_key,
David Howellsef686222017-04-06 10:11:59 +01001149 &expiry, _abort_code);
1150 if (ret < 0)
Qiushi Wuf45d01f2020-05-22 13:45:18 -05001151 goto temporary_error_free_ticket;
David Howells17926a72007-04-26 15:48:28 -07001152
1153 /* use the session key from inside the ticket to decrypt the
1154 * response */
David Howells8c2f8262018-02-08 15:59:07 +00001155 rxkad_decrypt_response(conn, response, &session_key);
David Howells17926a72007-04-26 15:48:28 -07001156
David Howellsfb46f6e2017-04-06 10:12:00 +01001157 eproto = tracepoint_string("rxkad_rsp_param");
David Howells17926a72007-04-26 15:48:28 -07001158 abort_code = RXKADSEALEDINCON;
David Howells8c2f8262018-02-08 15:59:07 +00001159 if (ntohl(response->encrypted.epoch) != conn->proto.epoch)
David Howells17926a72007-04-26 15:48:28 -07001160 goto protocol_error_free;
David Howells8c2f8262018-02-08 15:59:07 +00001161 if (ntohl(response->encrypted.cid) != conn->proto.cid)
David Howells17926a72007-04-26 15:48:28 -07001162 goto protocol_error_free;
David Howells8c2f8262018-02-08 15:59:07 +00001163 if (ntohl(response->encrypted.securityIndex) != conn->security_ix)
David Howells17926a72007-04-26 15:48:28 -07001164 goto protocol_error_free;
David Howells8c2f8262018-02-08 15:59:07 +00001165 csum = response->encrypted.checksum;
1166 response->encrypted.checksum = 0;
1167 rxkad_calc_response_checksum(response);
David Howellsfb46f6e2017-04-06 10:12:00 +01001168 eproto = tracepoint_string("rxkad_rsp_csum");
David Howells8c2f8262018-02-08 15:59:07 +00001169 if (response->encrypted.checksum != csum)
David Howells17926a72007-04-26 15:48:28 -07001170 goto protocol_error_free;
1171
David Howellsa1399f82016-06-27 14:39:44 +01001172 spin_lock(&conn->channel_lock);
1173 for (i = 0; i < RXRPC_MAXCALLS; i++) {
1174 struct rxrpc_call *call;
David Howells8c2f8262018-02-08 15:59:07 +00001175 u32 call_id = ntohl(response->encrypted.call_id[i]);
David Howellsa1399f82016-06-27 14:39:44 +01001176
David Howellsfb46f6e2017-04-06 10:12:00 +01001177 eproto = tracepoint_string("rxkad_rsp_callid");
David Howellsa1399f82016-06-27 14:39:44 +01001178 if (call_id > INT_MAX)
1179 goto protocol_error_unlock;
1180
David Howellsfb46f6e2017-04-06 10:12:00 +01001181 eproto = tracepoint_string("rxkad_rsp_callctr");
David Howellsa1399f82016-06-27 14:39:44 +01001182 if (call_id < conn->channels[i].call_counter)
1183 goto protocol_error_unlock;
David Howellsfb46f6e2017-04-06 10:12:00 +01001184
1185 eproto = tracepoint_string("rxkad_rsp_callst");
David Howellsa1399f82016-06-27 14:39:44 +01001186 if (call_id > conn->channels[i].call_counter) {
1187 call = rcu_dereference_protected(
1188 conn->channels[i].call,
1189 lockdep_is_held(&conn->channel_lock));
1190 if (call && call->state < RXRPC_CALL_COMPLETE)
1191 goto protocol_error_unlock;
1192 conn->channels[i].call_counter = call_id;
1193 }
1194 }
1195 spin_unlock(&conn->channel_lock);
David Howells17926a72007-04-26 15:48:28 -07001196
David Howellsfb46f6e2017-04-06 10:12:00 +01001197 eproto = tracepoint_string("rxkad_rsp_seq");
David Howells17926a72007-04-26 15:48:28 -07001198 abort_code = RXKADOUTOFSEQUENCE;
David Howells8c2f8262018-02-08 15:59:07 +00001199 if (ntohl(response->encrypted.inc_nonce) != conn->security_nonce + 1)
David Howells17926a72007-04-26 15:48:28 -07001200 goto protocol_error_free;
1201
David Howellsfb46f6e2017-04-06 10:12:00 +01001202 eproto = tracepoint_string("rxkad_rsp_level");
David Howells17926a72007-04-26 15:48:28 -07001203 abort_code = RXKADLEVELFAIL;
David Howells8c2f8262018-02-08 15:59:07 +00001204 level = ntohl(response->encrypted.level);
David Howells17926a72007-04-26 15:48:28 -07001205 if (level > RXRPC_SECURITY_ENCRYPT)
1206 goto protocol_error_free;
David Howells19ffa012016-04-04 14:00:36 +01001207 conn->params.security_level = level;
David Howells17926a72007-04-26 15:48:28 -07001208
1209 /* create a key to hold the security data and expiration time - after
1210 * this the connection security can be handled in exactly the same way
1211 * as for a client connection */
1212 ret = rxrpc_get_server_data_key(conn, &session_key, expiry, kvno);
David Howellsef686222017-04-06 10:11:59 +01001213 if (ret < 0)
David Howells8c2f8262018-02-08 15:59:07 +00001214 goto temporary_error_free_ticket;
David Howells17926a72007-04-26 15:48:28 -07001215
1216 kfree(ticket);
David Howells8c2f8262018-02-08 15:59:07 +00001217 kfree(response);
David Howells17926a72007-04-26 15:48:28 -07001218 _leave(" = 0");
1219 return 0;
1220
David Howellsa1399f82016-06-27 14:39:44 +01001221protocol_error_unlock:
1222 spin_unlock(&conn->channel_lock);
David Howells17926a72007-04-26 15:48:28 -07001223protocol_error_free:
1224 kfree(ticket);
1225protocol_error:
David Howells8c2f8262018-02-08 15:59:07 +00001226 kfree(response);
David Howellsfb46f6e2017-04-06 10:12:00 +01001227 trace_rxrpc_rx_eproto(NULL, sp->hdr.serial, eproto);
David Howells17926a72007-04-26 15:48:28 -07001228 *_abort_code = abort_code;
David Howells17926a72007-04-26 15:48:28 -07001229 return -EPROTO;
David Howellsef686222017-04-06 10:11:59 +01001230
David Howells8c2f8262018-02-08 15:59:07 +00001231temporary_error_free_ticket:
David Howellsef686222017-04-06 10:11:59 +01001232 kfree(ticket);
David Howells8c2f8262018-02-08 15:59:07 +00001233 kfree(response);
David Howellsef686222017-04-06 10:11:59 +01001234temporary_error:
1235 /* Ignore the response packet if we got a temporary error such as
1236 * ENOMEM. We just want to send the challenge again. Note that we
1237 * also come out this way if the ticket decryption fails.
1238 */
1239 return ret;
David Howells17926a72007-04-26 15:48:28 -07001240}
1241
1242/*
1243 * clear the connection security
1244 */
1245static void rxkad_clear(struct rxrpc_connection *conn)
1246{
1247 _enter("");
1248
1249 if (conn->cipher)
Kees Cook69d826f2018-09-18 19:10:47 -07001250 crypto_free_sync_skcipher(conn->cipher);
David Howells17926a72007-04-26 15:48:28 -07001251}
1252
1253/*
David Howells648af7f2016-04-07 17:23:51 +01001254 * Initialise the rxkad security service.
1255 */
1256static int rxkad_init(void)
1257{
David Howells1db88c52019-07-30 15:56:57 +01001258 struct crypto_sync_skcipher *tfm;
1259 struct skcipher_request *req;
1260
David Howells648af7f2016-04-07 17:23:51 +01001261 /* pin the cipher we need so that the crypto layer doesn't invoke
1262 * keventd to go get it */
David Howells1db88c52019-07-30 15:56:57 +01001263 tfm = crypto_alloc_sync_skcipher("pcbc(fcrypt)", 0, 0);
1264 if (IS_ERR(tfm))
1265 return PTR_ERR(tfm);
1266
1267 req = skcipher_request_alloc(&tfm->base, GFP_KERNEL);
1268 if (!req)
1269 goto nomem_tfm;
1270
1271 rxkad_ci_req = req;
1272 rxkad_ci = tfm;
1273 return 0;
1274
1275nomem_tfm:
1276 crypto_free_sync_skcipher(tfm);
1277 return -ENOMEM;
David Howells648af7f2016-04-07 17:23:51 +01001278}
1279
1280/*
1281 * Clean up the rxkad security service.
1282 */
1283static void rxkad_exit(void)
1284{
David Howells1db88c52019-07-30 15:56:57 +01001285 crypto_free_sync_skcipher(rxkad_ci);
1286 skcipher_request_free(rxkad_ci_req);
David Howells648af7f2016-04-07 17:23:51 +01001287}
1288
1289/*
David Howells17926a72007-04-26 15:48:28 -07001290 * RxRPC Kerberos-based security
1291 */
David Howells648af7f2016-04-07 17:23:51 +01001292const struct rxrpc_security rxkad = {
David Howells17926a72007-04-26 15:48:28 -07001293 .name = "rxkad",
David Howells8b815472009-09-14 01:17:30 +00001294 .security_index = RXRPC_SECURITY_RXKAD,
David Howells063c60d2019-12-20 16:17:16 +00001295 .no_key_abort = RXKADUNKNOWNKEY,
David Howells648af7f2016-04-07 17:23:51 +01001296 .init = rxkad_init,
1297 .exit = rxkad_exit,
David Howells17926a72007-04-26 15:48:28 -07001298 .init_connection_security = rxkad_init_connection_security,
1299 .prime_packet_security = rxkad_prime_packet_security,
1300 .secure_packet = rxkad_secure_packet,
1301 .verify_packet = rxkad_verify_packet,
David Howells1db88c52019-07-30 15:56:57 +01001302 .free_call_crypto = rxkad_free_call_crypto,
David Howells248f2192016-09-08 11:10:12 +01001303 .locate_data = rxkad_locate_data,
David Howells17926a72007-04-26 15:48:28 -07001304 .issue_challenge = rxkad_issue_challenge,
1305 .respond_to_challenge = rxkad_respond_to_challenge,
1306 .verify_response = rxkad_verify_response,
1307 .clear = rxkad_clear,
1308};