blob: dbb109da18358cbf2cd36b0abc5521cd1e7f0cb1 [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];
226 struct sk_buff *trailer;
Eric Dumazet95c96172012-04-15 05:58:06 +0000227 unsigned int len;
David Howells17926a72007-04-26 15:48:28 -0700228 u16 check;
229 int nsg;
Herbert Xu1afe5932016-01-24 21:19:01 +0800230 int err;
David Howells17926a72007-04-26 15:48:28 -0700231
232 sp = rxrpc_skb(skb);
233
234 _enter("");
235
David Howells5a924b82016-09-22 00:29:31 +0100236 check = sp->hdr.seq ^ call->call_id;
David Howells17926a72007-04-26 15:48:28 -0700237
David Howells0d12f8a2016-03-04 15:53:46 +0000238 rxkhdr.data_size = htonl(data_size | (u32)check << 16);
David Howells17926a72007-04-26 15:48:28 -0700239 rxkhdr.checksum = 0;
Herbert Xua2636292016-06-26 14:55:24 -0700240 memcpy(sechdr, &rxkhdr, sizeof(rxkhdr));
David Howells17926a72007-04-26 15:48:28 -0700241
242 /* encrypt from the session key */
David Howells19ffa012016-04-04 14:00:36 +0100243 token = call->conn->params.key->payload.data[0];
David Howells33941282009-09-14 01:17:35 +0000244 memcpy(&iv, token->kad->session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700245
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700246 sg_init_one(&sg[0], sechdr, sizeof(rxkhdr));
Kees Cook69d826f2018-09-18 19:10:47 -0700247 skcipher_request_set_sync_tfm(req, call->conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800248 skcipher_request_set_callback(req, 0, NULL, NULL);
Herbert Xua2636292016-06-26 14:55:24 -0700249 skcipher_request_set_crypt(req, &sg[0], &sg[0], sizeof(rxkhdr), iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800250 crypto_skcipher_encrypt(req);
David Howells17926a72007-04-26 15:48:28 -0700251
252 /* we want to encrypt the skbuff in-place */
253 nsg = skb_cow_data(skb, 0, &trailer);
Herbert Xu1afe5932016-01-24 21:19:01 +0800254 err = -ENOMEM;
David Howells17926a72007-04-26 15:48:28 -0700255 if (nsg < 0 || nsg > 16)
Herbert Xu1afe5932016-01-24 21:19:01 +0800256 goto out;
David Howells17926a72007-04-26 15:48:28 -0700257
258 len = data_size + call->conn->size_align - 1;
259 len &= ~(call->conn->size_align - 1);
260
David S. Miller51c739d2007-10-30 21:29:29 -0700261 sg_init_table(sg, nsg);
Jason A. Donenfeld89a5ea92017-06-04 04:16:24 +0200262 err = skb_to_sgvec(skb, sg, 0, len);
263 if (unlikely(err < 0))
264 goto out;
Herbert Xu1afe5932016-01-24 21:19:01 +0800265 skcipher_request_set_crypt(req, sg, sg, len, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800266 crypto_skcipher_encrypt(req);
David Howells17926a72007-04-26 15:48:28 -0700267
268 _leave(" = 0");
Herbert Xu1afe5932016-01-24 21:19:01 +0800269 err = 0;
270
271out:
272 skcipher_request_zero(req);
273 return err;
David Howells17926a72007-04-26 15:48:28 -0700274}
275
276/*
277 * checksum an RxRPC packet header
278 */
Herbert Xua2636292016-06-26 14:55:24 -0700279static int rxkad_secure_packet(struct rxrpc_call *call,
David Howellsb4f13422016-03-04 15:56:19 +0000280 struct sk_buff *skb,
281 size_t data_size,
282 void *sechdr)
David Howells17926a72007-04-26 15:48:28 -0700283{
284 struct rxrpc_skb_priv *sp;
David Howells1db88c52019-07-30 15:56:57 +0100285 struct skcipher_request *req;
David Howells17926a72007-04-26 15:48:28 -0700286 struct rxrpc_crypt iv;
Herbert Xua2636292016-06-26 14:55:24 -0700287 struct scatterlist sg;
David Howells0d12f8a2016-03-04 15:53:46 +0000288 u32 x, y;
David Howells17926a72007-04-26 15:48:28 -0700289 int ret;
290
291 sp = rxrpc_skb(skb);
292
293 _enter("{%d{%x}},{#%u},%zu,",
David Howells19ffa012016-04-04 14:00:36 +0100294 call->debug_id, key_serial(call->conn->params.key),
295 sp->hdr.seq, data_size);
David Howells17926a72007-04-26 15:48:28 -0700296
297 if (!call->conn->cipher)
298 return 0;
299
David Howells19ffa012016-04-04 14:00:36 +0100300 ret = key_validate(call->conn->params.key);
David Howells17926a72007-04-26 15:48:28 -0700301 if (ret < 0)
302 return ret;
303
David Howells1db88c52019-07-30 15:56:57 +0100304 req = rxkad_get_call_crypto(call);
305 if (!req)
306 return -ENOMEM;
307
David Howells17926a72007-04-26 15:48:28 -0700308 /* continue encrypting from where we left off */
309 memcpy(&iv, call->conn->csum_iv.x, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700310
311 /* calculate the security checksum */
David Howells01a90a42016-08-23 15:27:24 +0100312 x = (call->cid & RXRPC_CHANNELMASK) << (32 - RXRPC_CIDSHIFT);
David Howells0d12f8a2016-03-04 15:53:46 +0000313 x |= sp->hdr.seq & 0x3fffffff;
David Howells5a924b82016-09-22 00:29:31 +0100314 call->crypto_buf[0] = htonl(call->call_id);
Herbert Xua2636292016-06-26 14:55:24 -0700315 call->crypto_buf[1] = htonl(x);
David Howells17926a72007-04-26 15:48:28 -0700316
Herbert Xua2636292016-06-26 14:55:24 -0700317 sg_init_one(&sg, call->crypto_buf, 8);
Kees Cook69d826f2018-09-18 19:10:47 -0700318 skcipher_request_set_sync_tfm(req, call->conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800319 skcipher_request_set_callback(req, 0, NULL, NULL);
Herbert Xua2636292016-06-26 14:55:24 -0700320 skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800321 crypto_skcipher_encrypt(req);
322 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700323
Herbert Xua2636292016-06-26 14:55:24 -0700324 y = ntohl(call->crypto_buf[1]);
Al Viro91e916c2008-03-29 03:08:38 +0000325 y = (y >> 16) & 0xffff;
326 if (y == 0)
327 y = 1; /* zero checksums are not permitted */
David Howells0d12f8a2016-03-04 15:53:46 +0000328 sp->hdr.cksum = y;
David Howells17926a72007-04-26 15:48:28 -0700329
David Howells19ffa012016-04-04 14:00:36 +0100330 switch (call->conn->params.security_level) {
David Howells17926a72007-04-26 15:48:28 -0700331 case RXRPC_SECURITY_PLAIN:
332 ret = 0;
333 break;
334 case RXRPC_SECURITY_AUTH:
Kees Cook54424d32018-08-03 10:15:25 +0100335 ret = rxkad_secure_packet_auth(call, skb, data_size, sechdr,
336 req);
David Howells17926a72007-04-26 15:48:28 -0700337 break;
338 case RXRPC_SECURITY_ENCRYPT:
339 ret = rxkad_secure_packet_encrypt(call, skb, data_size,
Kees Cook54424d32018-08-03 10:15:25 +0100340 sechdr, req);
David Howells17926a72007-04-26 15:48:28 -0700341 break;
342 default:
343 ret = -EPERM;
344 break;
345 }
346
Al Viro91e916c2008-03-29 03:08:38 +0000347 _leave(" = %d [set %hx]", ret, y);
David Howells17926a72007-04-26 15:48:28 -0700348 return ret;
349}
350
351/*
352 * decrypt partial encryption on a packet (level 1 security)
353 */
David Howells5a429762016-09-06 22:19:51 +0100354static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
David Howells248f2192016-09-08 11:10:12 +0100355 unsigned int offset, unsigned int len,
Kees Cook54424d32018-08-03 10:15:25 +0100356 rxrpc_seq_t seq,
357 struct skcipher_request *req)
David Howells17926a72007-04-26 15:48:28 -0700358{
359 struct rxkad_level1_hdr sechdr;
David Howells17926a72007-04-26 15:48:28 -0700360 struct rxrpc_crypt iv;
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700361 struct scatterlist sg[16];
David Howells17926a72007-04-26 15:48:28 -0700362 struct sk_buff *trailer;
David Howellsfb46f6e2017-04-06 10:12:00 +0100363 bool aborted;
David Howells17926a72007-04-26 15:48:28 -0700364 u32 data_size, buf;
365 u16 check;
Jason A. Donenfeld89a5ea92017-06-04 04:16:24 +0200366 int nsg, ret;
David Howells17926a72007-04-26 15:48:28 -0700367
368 _enter("");
369
David Howells248f2192016-09-08 11:10:12 +0100370 if (len < 8) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100371 aborted = rxrpc_abort_eproto(call, skb, "rxkad_1_hdr", "V1H",
372 RXKADSEALEDINCON);
David Howells5a429762016-09-06 22:19:51 +0100373 goto protocol_error;
374 }
David Howells17926a72007-04-26 15:48:28 -0700375
David Howells248f2192016-09-08 11:10:12 +0100376 /* Decrypt the skbuff in-place. TODO: We really want to decrypt
377 * directly into the target buffer.
378 */
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700379 nsg = skb_cow_data(skb, 0, &trailer);
380 if (nsg < 0 || nsg > 16)
David Howells17926a72007-04-26 15:48:28 -0700381 goto nomem;
382
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700383 sg_init_table(sg, nsg);
Jason A. Donenfeld89a5ea92017-06-04 04:16:24 +0200384 ret = skb_to_sgvec(skb, sg, offset, 8);
385 if (unlikely(ret < 0))
386 return ret;
David Howells17926a72007-04-26 15:48:28 -0700387
388 /* start the decryption afresh */
389 memset(&iv, 0, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700390
Kees Cook69d826f2018-09-18 19:10:47 -0700391 skcipher_request_set_sync_tfm(req, call->conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800392 skcipher_request_set_callback(req, 0, NULL, NULL);
393 skcipher_request_set_crypt(req, sg, sg, 8, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800394 crypto_skcipher_decrypt(req);
395 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700396
David Howells5a429762016-09-06 22:19:51 +0100397 /* Extract the decrypted packet length */
David Howells248f2192016-09-08 11:10:12 +0100398 if (skb_copy_bits(skb, offset, &sechdr, sizeof(sechdr)) < 0) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100399 aborted = rxrpc_abort_eproto(call, skb, "rxkad_1_len", "XV1",
400 RXKADDATALEN);
David Howells5a429762016-09-06 22:19:51 +0100401 goto protocol_error;
402 }
David Howells248f2192016-09-08 11:10:12 +0100403 offset += sizeof(sechdr);
404 len -= sizeof(sechdr);
David Howells17926a72007-04-26 15:48:28 -0700405
406 buf = ntohl(sechdr.data_size);
407 data_size = buf & 0xffff;
408
409 check = buf >> 16;
David Howells5a429762016-09-06 22:19:51 +0100410 check ^= seq ^ call->call_id;
David Howells17926a72007-04-26 15:48:28 -0700411 check &= 0xffff;
412 if (check != 0) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100413 aborted = rxrpc_abort_eproto(call, skb, "rxkad_1_check", "V1C",
414 RXKADSEALEDINCON);
David Howells17926a72007-04-26 15:48:28 -0700415 goto protocol_error;
416 }
417
David Howells248f2192016-09-08 11:10:12 +0100418 if (data_size > len) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100419 aborted = rxrpc_abort_eproto(call, skb, "rxkad_1_datalen", "V1L",
420 RXKADDATALEN);
David Howells5a429762016-09-06 22:19:51 +0100421 goto protocol_error;
422 }
David Howells17926a72007-04-26 15:48:28 -0700423
424 _leave(" = 0 [dlen=%x]", data_size);
425 return 0;
426
David Howells17926a72007-04-26 15:48:28 -0700427protocol_error:
David Howellsfb46f6e2017-04-06 10:12:00 +0100428 if (aborted)
429 rxrpc_send_abort_packet(call);
David Howells17926a72007-04-26 15:48:28 -0700430 return -EPROTO;
431
432nomem:
433 _leave(" = -ENOMEM");
434 return -ENOMEM;
435}
436
437/*
438 * wholly decrypt a packet (level 2 security)
439 */
David Howells5a429762016-09-06 22:19:51 +0100440static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
David Howells248f2192016-09-08 11:10:12 +0100441 unsigned int offset, unsigned int len,
Kees Cook54424d32018-08-03 10:15:25 +0100442 rxrpc_seq_t seq,
443 struct skcipher_request *req)
David Howells17926a72007-04-26 15:48:28 -0700444{
David Howells33941282009-09-14 01:17:35 +0000445 const struct rxrpc_key_token *token;
David Howells17926a72007-04-26 15:48:28 -0700446 struct rxkad_level2_hdr sechdr;
David Howells17926a72007-04-26 15:48:28 -0700447 struct rxrpc_crypt iv;
448 struct scatterlist _sg[4], *sg;
449 struct sk_buff *trailer;
David Howellsfb46f6e2017-04-06 10:12:00 +0100450 bool aborted;
David Howells17926a72007-04-26 15:48:28 -0700451 u32 data_size, buf;
452 u16 check;
Jason A. Donenfeld89a5ea92017-06-04 04:16:24 +0200453 int nsg, ret;
David Howells17926a72007-04-26 15:48:28 -0700454
455 _enter(",{%d}", skb->len);
456
David Howells248f2192016-09-08 11:10:12 +0100457 if (len < 8) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100458 aborted = rxrpc_abort_eproto(call, skb, "rxkad_2_hdr", "V2H",
459 RXKADSEALEDINCON);
David Howells5a429762016-09-06 22:19:51 +0100460 goto protocol_error;
461 }
David Howells17926a72007-04-26 15:48:28 -0700462
David Howells248f2192016-09-08 11:10:12 +0100463 /* Decrypt the skbuff in-place. TODO: We really want to decrypt
464 * directly into the target buffer.
465 */
David Howells17926a72007-04-26 15:48:28 -0700466 nsg = skb_cow_data(skb, 0, &trailer);
467 if (nsg < 0)
468 goto nomem;
469
470 sg = _sg;
471 if (unlikely(nsg > 4)) {
Kees Cook6da2ec52018-06-12 13:55:00 -0700472 sg = kmalloc_array(nsg, sizeof(*sg), GFP_NOIO);
David Howells17926a72007-04-26 15:48:28 -0700473 if (!sg)
474 goto nomem;
475 }
476
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700477 sg_init_table(sg, nsg);
Jason A. Donenfeld89a5ea92017-06-04 04:16:24 +0200478 ret = skb_to_sgvec(skb, sg, offset, len);
479 if (unlikely(ret < 0)) {
480 if (sg != _sg)
481 kfree(sg);
482 return ret;
483 }
David Howells17926a72007-04-26 15:48:28 -0700484
485 /* decrypt from the session key */
David Howells19ffa012016-04-04 14:00:36 +0100486 token = call->conn->params.key->payload.data[0];
David Howells33941282009-09-14 01:17:35 +0000487 memcpy(&iv, token->kad->session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700488
Kees Cook69d826f2018-09-18 19:10:47 -0700489 skcipher_request_set_sync_tfm(req, call->conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800490 skcipher_request_set_callback(req, 0, NULL, NULL);
David Howells248f2192016-09-08 11:10:12 +0100491 skcipher_request_set_crypt(req, sg, sg, len, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800492 crypto_skcipher_decrypt(req);
493 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700494 if (sg != _sg)
495 kfree(sg);
496
David Howells5a429762016-09-06 22:19:51 +0100497 /* Extract the decrypted packet length */
David Howells248f2192016-09-08 11:10:12 +0100498 if (skb_copy_bits(skb, offset, &sechdr, sizeof(sechdr)) < 0) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100499 aborted = rxrpc_abort_eproto(call, skb, "rxkad_2_len", "XV2",
500 RXKADDATALEN);
David Howells5a429762016-09-06 22:19:51 +0100501 goto protocol_error;
502 }
David Howells248f2192016-09-08 11:10:12 +0100503 offset += sizeof(sechdr);
504 len -= sizeof(sechdr);
David Howells17926a72007-04-26 15:48:28 -0700505
506 buf = ntohl(sechdr.data_size);
507 data_size = buf & 0xffff;
508
509 check = buf >> 16;
David Howells5a429762016-09-06 22:19:51 +0100510 check ^= seq ^ call->call_id;
David Howells17926a72007-04-26 15:48:28 -0700511 check &= 0xffff;
512 if (check != 0) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100513 aborted = rxrpc_abort_eproto(call, skb, "rxkad_2_check", "V2C",
514 RXKADSEALEDINCON);
David Howells17926a72007-04-26 15:48:28 -0700515 goto protocol_error;
516 }
517
David Howells248f2192016-09-08 11:10:12 +0100518 if (data_size > len) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100519 aborted = rxrpc_abort_eproto(call, skb, "rxkad_2_datalen", "V2L",
520 RXKADDATALEN);
David Howells5a429762016-09-06 22:19:51 +0100521 goto protocol_error;
522 }
David Howells17926a72007-04-26 15:48:28 -0700523
524 _leave(" = 0 [dlen=%x]", data_size);
525 return 0;
526
David Howells17926a72007-04-26 15:48:28 -0700527protocol_error:
David Howellsfb46f6e2017-04-06 10:12:00 +0100528 if (aborted)
529 rxrpc_send_abort_packet(call);
David Howells17926a72007-04-26 15:48:28 -0700530 return -EPROTO;
531
532nomem:
533 _leave(" = -ENOMEM");
534 return -ENOMEM;
535}
536
537/*
David Howells5a429762016-09-06 22:19:51 +0100538 * Verify the security on a received packet or subpacket (if part of a
539 * jumbo packet).
David Howells17926a72007-04-26 15:48:28 -0700540 */
David Howells5a429762016-09-06 22:19:51 +0100541static int rxkad_verify_packet(struct rxrpc_call *call, struct sk_buff *skb,
David Howells248f2192016-09-08 11:10:12 +0100542 unsigned int offset, unsigned int len,
David Howells5a429762016-09-06 22:19:51 +0100543 rxrpc_seq_t seq, u16 expected_cksum)
David Howells17926a72007-04-26 15:48:28 -0700544{
David Howells1db88c52019-07-30 15:56:57 +0100545 struct skcipher_request *req;
David Howells17926a72007-04-26 15:48:28 -0700546 struct rxrpc_crypt iv;
Herbert Xua2636292016-06-26 14:55:24 -0700547 struct scatterlist sg;
David Howellsfb46f6e2017-04-06 10:12:00 +0100548 bool aborted;
David Howells0d12f8a2016-03-04 15:53:46 +0000549 u16 cksum;
550 u32 x, y;
David Howells17926a72007-04-26 15:48:28 -0700551
552 _enter("{%d{%x}},{#%u}",
David Howells5a429762016-09-06 22:19:51 +0100553 call->debug_id, key_serial(call->conn->params.key), seq);
David Howells17926a72007-04-26 15:48:28 -0700554
555 if (!call->conn->cipher)
556 return 0;
557
David Howells1db88c52019-07-30 15:56:57 +0100558 req = rxkad_get_call_crypto(call);
559 if (!req)
560 return -ENOMEM;
561
David Howells17926a72007-04-26 15:48:28 -0700562 /* continue encrypting from where we left off */
563 memcpy(&iv, call->conn->csum_iv.x, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700564
565 /* validate the security checksum */
David Howells01a90a42016-08-23 15:27:24 +0100566 x = (call->cid & RXRPC_CHANNELMASK) << (32 - RXRPC_CIDSHIFT);
David Howells5a429762016-09-06 22:19:51 +0100567 x |= seq & 0x3fffffff;
Herbert Xua2636292016-06-26 14:55:24 -0700568 call->crypto_buf[0] = htonl(call->call_id);
569 call->crypto_buf[1] = htonl(x);
David Howells17926a72007-04-26 15:48:28 -0700570
Herbert Xua2636292016-06-26 14:55:24 -0700571 sg_init_one(&sg, call->crypto_buf, 8);
Kees Cook69d826f2018-09-18 19:10:47 -0700572 skcipher_request_set_sync_tfm(req, call->conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800573 skcipher_request_set_callback(req, 0, NULL, NULL);
Herbert Xua2636292016-06-26 14:55:24 -0700574 skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800575 crypto_skcipher_encrypt(req);
576 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700577
Herbert Xua2636292016-06-26 14:55:24 -0700578 y = ntohl(call->crypto_buf[1]);
David Howells0d12f8a2016-03-04 15:53:46 +0000579 cksum = (y >> 16) & 0xffff;
580 if (cksum == 0)
581 cksum = 1; /* zero checksums are not permitted */
David Howells17926a72007-04-26 15:48:28 -0700582
David Howells5a429762016-09-06 22:19:51 +0100583 if (cksum != expected_cksum) {
David Howellsfb46f6e2017-04-06 10:12:00 +0100584 aborted = rxrpc_abort_eproto(call, skb, "rxkad_csum", "VCK",
585 RXKADSEALEDINCON);
586 goto protocol_error;
David Howells17926a72007-04-26 15:48:28 -0700587 }
588
David Howells19ffa012016-04-04 14:00:36 +0100589 switch (call->conn->params.security_level) {
David Howells17926a72007-04-26 15:48:28 -0700590 case RXRPC_SECURITY_PLAIN:
David Howells5a429762016-09-06 22:19:51 +0100591 return 0;
David Howells17926a72007-04-26 15:48:28 -0700592 case RXRPC_SECURITY_AUTH:
Kees Cook54424d32018-08-03 10:15:25 +0100593 return rxkad_verify_packet_1(call, skb, offset, len, seq, req);
David Howells17926a72007-04-26 15:48:28 -0700594 case RXRPC_SECURITY_ENCRYPT:
Kees Cook54424d32018-08-03 10:15:25 +0100595 return rxkad_verify_packet_2(call, skb, offset, len, seq, req);
David Howells17926a72007-04-26 15:48:28 -0700596 default:
David Howells5a429762016-09-06 22:19:51 +0100597 return -ENOANO;
David Howells17926a72007-04-26 15:48:28 -0700598 }
David Howellsfb46f6e2017-04-06 10:12:00 +0100599
600protocol_error:
601 if (aborted)
602 rxrpc_send_abort_packet(call);
603 return -EPROTO;
David Howells17926a72007-04-26 15:48:28 -0700604}
605
606/*
David Howells248f2192016-09-08 11:10:12 +0100607 * Locate the data contained in a packet that was partially encrypted.
608 */
609static void rxkad_locate_data_1(struct rxrpc_call *call, struct sk_buff *skb,
610 unsigned int *_offset, unsigned int *_len)
611{
612 struct rxkad_level1_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 a packet that was completely encrypted.
622 */
623static void rxkad_locate_data_2(struct rxrpc_call *call, struct sk_buff *skb,
624 unsigned int *_offset, unsigned int *_len)
625{
626 struct rxkad_level2_hdr sechdr;
627
628 if (skb_copy_bits(skb, *_offset, &sechdr, sizeof(sechdr)) < 0)
629 BUG();
630 *_offset += sizeof(sechdr);
631 *_len = ntohl(sechdr.data_size) & 0xffff;
632}
633
634/*
635 * Locate the data contained in an already decrypted packet.
636 */
637static void rxkad_locate_data(struct rxrpc_call *call, struct sk_buff *skb,
638 unsigned int *_offset, unsigned int *_len)
639{
640 switch (call->conn->params.security_level) {
641 case RXRPC_SECURITY_AUTH:
642 rxkad_locate_data_1(call, skb, _offset, _len);
643 return;
644 case RXRPC_SECURITY_ENCRYPT:
645 rxkad_locate_data_2(call, skb, _offset, _len);
646 return;
647 default:
648 return;
649 }
650}
651
652/*
David Howells17926a72007-04-26 15:48:28 -0700653 * issue a challenge
654 */
655static int rxkad_issue_challenge(struct rxrpc_connection *conn)
656{
657 struct rxkad_challenge challenge;
David Howells0d12f8a2016-03-04 15:53:46 +0000658 struct rxrpc_wire_header whdr;
David Howells17926a72007-04-26 15:48:28 -0700659 struct msghdr msg;
660 struct kvec iov[2];
661 size_t len;
David Howells0d12f8a2016-03-04 15:53:46 +0000662 u32 serial;
David Howells17926a72007-04-26 15:48:28 -0700663 int ret;
664
David Howells19ffa012016-04-04 14:00:36 +0100665 _enter("{%d,%x}", conn->debug_id, key_serial(conn->params.key));
David Howells17926a72007-04-26 15:48:28 -0700666
David Howells19ffa012016-04-04 14:00:36 +0100667 ret = key_validate(conn->params.key);
David Howells17926a72007-04-26 15:48:28 -0700668 if (ret < 0)
669 return ret;
670
671 get_random_bytes(&conn->security_nonce, sizeof(conn->security_nonce));
672
673 challenge.version = htonl(2);
674 challenge.nonce = htonl(conn->security_nonce);
675 challenge.min_level = htonl(0);
676 challenge.__padding = 0;
677
David Howells7b674e32017-08-29 10:18:37 +0100678 msg.msg_name = &conn->params.peer->srx.transport;
679 msg.msg_namelen = conn->params.peer->srx.transport_len;
David Howells17926a72007-04-26 15:48:28 -0700680 msg.msg_control = NULL;
681 msg.msg_controllen = 0;
682 msg.msg_flags = 0;
683
David Howells19ffa012016-04-04 14:00:36 +0100684 whdr.epoch = htonl(conn->proto.epoch);
685 whdr.cid = htonl(conn->proto.cid);
David Howells0d12f8a2016-03-04 15:53:46 +0000686 whdr.callNumber = 0;
687 whdr.seq = 0;
688 whdr.type = RXRPC_PACKET_TYPE_CHALLENGE;
689 whdr.flags = conn->out_clientflag;
690 whdr.userStatus = 0;
691 whdr.securityIndex = conn->security_ix;
692 whdr._rsvd = 0;
David Howells68d6d1a2017-06-05 14:30:49 +0100693 whdr.serviceId = htons(conn->service_id);
David Howells17926a72007-04-26 15:48:28 -0700694
David Howells0d12f8a2016-03-04 15:53:46 +0000695 iov[0].iov_base = &whdr;
696 iov[0].iov_len = sizeof(whdr);
David Howells17926a72007-04-26 15:48:28 -0700697 iov[1].iov_base = &challenge;
698 iov[1].iov_len = sizeof(challenge);
699
700 len = iov[0].iov_len + iov[1].iov_len;
701
David Howells0d12f8a2016-03-04 15:53:46 +0000702 serial = atomic_inc_return(&conn->serial);
703 whdr.serial = htonl(serial);
704 _proto("Tx CHALLENGE %%%u", serial);
David Howells17926a72007-04-26 15:48:28 -0700705
David Howells85f32272016-04-04 14:00:36 +0100706 ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
David Howells17926a72007-04-26 15:48:28 -0700707 if (ret < 0) {
David Howells6b47fe12018-05-10 23:26:01 +0100708 trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
David Howells4764c0d2018-07-23 17:18:37 +0100709 rxrpc_tx_point_rxkad_challenge);
David Howells17926a72007-04-26 15:48:28 -0700710 return -EAGAIN;
711 }
712
David Howells330bdcf2018-08-08 11:30:02 +0100713 conn->params.peer->last_tx_at = ktime_get_seconds();
David Howells4764c0d2018-07-23 17:18:37 +0100714 trace_rxrpc_tx_packet(conn->debug_id, &whdr,
715 rxrpc_tx_point_rxkad_challenge);
David Howells17926a72007-04-26 15:48:28 -0700716 _leave(" = 0");
717 return 0;
718}
719
720/*
721 * send a Kerberos security response
722 */
723static int rxkad_send_response(struct rxrpc_connection *conn,
David Howells0d12f8a2016-03-04 15:53:46 +0000724 struct rxrpc_host_header *hdr,
David Howells17926a72007-04-26 15:48:28 -0700725 struct rxkad_response *resp,
726 const struct rxkad_key *s2)
727{
David Howells0d12f8a2016-03-04 15:53:46 +0000728 struct rxrpc_wire_header whdr;
David Howells17926a72007-04-26 15:48:28 -0700729 struct msghdr msg;
730 struct kvec iov[3];
731 size_t len;
David Howells0d12f8a2016-03-04 15:53:46 +0000732 u32 serial;
David Howells17926a72007-04-26 15:48:28 -0700733 int ret;
734
735 _enter("");
736
David Howells7b674e32017-08-29 10:18:37 +0100737 msg.msg_name = &conn->params.peer->srx.transport;
738 msg.msg_namelen = conn->params.peer->srx.transport_len;
David Howells17926a72007-04-26 15:48:28 -0700739 msg.msg_control = NULL;
740 msg.msg_controllen = 0;
741 msg.msg_flags = 0;
742
David Howells0d12f8a2016-03-04 15:53:46 +0000743 memset(&whdr, 0, sizeof(whdr));
744 whdr.epoch = htonl(hdr->epoch);
745 whdr.cid = htonl(hdr->cid);
746 whdr.type = RXRPC_PACKET_TYPE_RESPONSE;
747 whdr.flags = conn->out_clientflag;
748 whdr.securityIndex = hdr->securityIndex;
749 whdr.serviceId = htons(hdr->serviceId);
David Howells17926a72007-04-26 15:48:28 -0700750
David Howells0d12f8a2016-03-04 15:53:46 +0000751 iov[0].iov_base = &whdr;
752 iov[0].iov_len = sizeof(whdr);
David Howells17926a72007-04-26 15:48:28 -0700753 iov[1].iov_base = resp;
754 iov[1].iov_len = sizeof(*resp);
David Howells0d12f8a2016-03-04 15:53:46 +0000755 iov[2].iov_base = (void *)s2->ticket;
David Howells17926a72007-04-26 15:48:28 -0700756 iov[2].iov_len = s2->ticket_len;
757
758 len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
759
David Howells0d12f8a2016-03-04 15:53:46 +0000760 serial = atomic_inc_return(&conn->serial);
761 whdr.serial = htonl(serial);
762 _proto("Tx RESPONSE %%%u", serial);
David Howells17926a72007-04-26 15:48:28 -0700763
David Howells85f32272016-04-04 14:00:36 +0100764 ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 3, len);
David Howells17926a72007-04-26 15:48:28 -0700765 if (ret < 0) {
David Howells6b47fe12018-05-10 23:26:01 +0100766 trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
David Howells4764c0d2018-07-23 17:18:37 +0100767 rxrpc_tx_point_rxkad_response);
David Howells17926a72007-04-26 15:48:28 -0700768 return -EAGAIN;
769 }
770
David Howells330bdcf2018-08-08 11:30:02 +0100771 conn->params.peer->last_tx_at = ktime_get_seconds();
David Howells17926a72007-04-26 15:48:28 -0700772 _leave(" = 0");
773 return 0;
774}
775
776/*
777 * calculate the response checksum
778 */
779static void rxkad_calc_response_checksum(struct rxkad_response *response)
780{
781 u32 csum = 1000003;
782 int loop;
783 u8 *p = (u8 *) response;
784
785 for (loop = sizeof(*response); loop > 0; loop--)
786 csum = csum * 0x10204081 + *p++;
787
788 response->encrypted.checksum = htonl(csum);
789}
790
791/*
David Howells17926a72007-04-26 15:48:28 -0700792 * encrypt the response packet
793 */
David Howells1db88c52019-07-30 15:56:57 +0100794static int rxkad_encrypt_response(struct rxrpc_connection *conn,
795 struct rxkad_response *resp,
796 const struct rxkad_key *s2)
David Howells17926a72007-04-26 15:48:28 -0700797{
David Howells1db88c52019-07-30 15:56:57 +0100798 struct skcipher_request *req;
David Howells17926a72007-04-26 15:48:28 -0700799 struct rxrpc_crypt iv;
Herbert Xua2636292016-06-26 14:55:24 -0700800 struct scatterlist sg[1];
David Howells17926a72007-04-26 15:48:28 -0700801
David Howells1db88c52019-07-30 15:56:57 +0100802 req = skcipher_request_alloc(&conn->cipher->base, GFP_NOFS);
803 if (!req)
804 return -ENOMEM;
805
David Howells17926a72007-04-26 15:48:28 -0700806 /* continue encrypting from where we left off */
807 memcpy(&iv, s2->session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700808
Herbert Xua2636292016-06-26 14:55:24 -0700809 sg_init_table(sg, 1);
810 sg_set_buf(sg, &resp->encrypted, sizeof(resp->encrypted));
Kees Cook69d826f2018-09-18 19:10:47 -0700811 skcipher_request_set_sync_tfm(req, conn->cipher);
Herbert Xu1afe5932016-01-24 21:19:01 +0800812 skcipher_request_set_callback(req, 0, NULL, NULL);
813 skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800814 crypto_skcipher_encrypt(req);
David Howells1db88c52019-07-30 15:56:57 +0100815 skcipher_request_free(req);
816 return 0;
David Howells17926a72007-04-26 15:48:28 -0700817}
818
819/*
820 * respond to a challenge packet
821 */
822static int rxkad_respond_to_challenge(struct rxrpc_connection *conn,
823 struct sk_buff *skb,
824 u32 *_abort_code)
825{
David Howells33941282009-09-14 01:17:35 +0000826 const struct rxrpc_key_token *token;
David Howells17926a72007-04-26 15:48:28 -0700827 struct rxkad_challenge challenge;
David Howells8c2f8262018-02-08 15:59:07 +0000828 struct rxkad_response *resp;
David Howells248f2192016-09-08 11:10:12 +0100829 struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
David Howellsfb46f6e2017-04-06 10:12:00 +0100830 const char *eproto;
David Howells17926a72007-04-26 15:48:28 -0700831 u32 version, nonce, min_level, abort_code;
832 int ret;
833
David Howells19ffa012016-04-04 14:00:36 +0100834 _enter("{%d,%x}", conn->debug_id, key_serial(conn->params.key));
David Howells17926a72007-04-26 15:48:28 -0700835
David Howellsfb46f6e2017-04-06 10:12:00 +0100836 eproto = tracepoint_string("chall_no_key");
David Howellsef686222017-04-06 10:11:59 +0100837 abort_code = RX_PROTOCOL_ERROR;
838 if (!conn->params.key)
839 goto protocol_error;
David Howells17926a72007-04-26 15:48:28 -0700840
David Howellsef686222017-04-06 10:11:59 +0100841 abort_code = RXKADEXPIRED;
David Howells19ffa012016-04-04 14:00:36 +0100842 ret = key_validate(conn->params.key);
David Howellsef686222017-04-06 10:11:59 +0100843 if (ret < 0)
844 goto other_error;
David Howells17926a72007-04-26 15:48:28 -0700845
David Howellsfb46f6e2017-04-06 10:12:00 +0100846 eproto = tracepoint_string("chall_short");
David Howells17926a72007-04-26 15:48:28 -0700847 abort_code = RXKADPACKETSHORT;
David Howells775e5b72016-09-30 13:26:03 +0100848 if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
849 &challenge, sizeof(challenge)) < 0)
David Howells17926a72007-04-26 15:48:28 -0700850 goto protocol_error;
851
852 version = ntohl(challenge.version);
853 nonce = ntohl(challenge.nonce);
854 min_level = ntohl(challenge.min_level);
855
856 _proto("Rx CHALLENGE %%%u { v=%u n=%u ml=%u }",
David Howells0d12f8a2016-03-04 15:53:46 +0000857 sp->hdr.serial, version, nonce, min_level);
David Howells17926a72007-04-26 15:48:28 -0700858
David Howellsfb46f6e2017-04-06 10:12:00 +0100859 eproto = tracepoint_string("chall_ver");
David Howells17926a72007-04-26 15:48:28 -0700860 abort_code = RXKADINCONSISTENCY;
861 if (version != RXKAD_VERSION)
862 goto protocol_error;
863
864 abort_code = RXKADLEVELFAIL;
David Howellsef686222017-04-06 10:11:59 +0100865 ret = -EACCES;
David Howells19ffa012016-04-04 14:00:36 +0100866 if (conn->params.security_level < min_level)
David Howellsef686222017-04-06 10:11:59 +0100867 goto other_error;
David Howells17926a72007-04-26 15:48:28 -0700868
David Howells19ffa012016-04-04 14:00:36 +0100869 token = conn->params.key->payload.data[0];
David Howells17926a72007-04-26 15:48:28 -0700870
871 /* build the response packet */
David Howells8c2f8262018-02-08 15:59:07 +0000872 resp = kzalloc(sizeof(struct rxkad_response), GFP_NOFS);
873 if (!resp)
874 return -ENOMEM;
David Howells17926a72007-04-26 15:48:28 -0700875
David Howells8c2f8262018-02-08 15:59:07 +0000876 resp->version = htonl(RXKAD_VERSION);
877 resp->encrypted.epoch = htonl(conn->proto.epoch);
878 resp->encrypted.cid = htonl(conn->proto.cid);
879 resp->encrypted.securityIndex = htonl(conn->security_ix);
880 resp->encrypted.inc_nonce = htonl(nonce + 1);
881 resp->encrypted.level = htonl(conn->params.security_level);
882 resp->kvno = htonl(token->kad->kvno);
883 resp->ticket_len = htonl(token->kad->ticket_len);
884 resp->encrypted.call_id[0] = htonl(conn->channels[0].call_counter);
885 resp->encrypted.call_id[1] = htonl(conn->channels[1].call_counter);
886 resp->encrypted.call_id[2] = htonl(conn->channels[2].call_counter);
887 resp->encrypted.call_id[3] = htonl(conn->channels[3].call_counter);
David Howells17926a72007-04-26 15:48:28 -0700888
889 /* calculate the response checksum and then do the encryption */
David Howells8c2f8262018-02-08 15:59:07 +0000890 rxkad_calc_response_checksum(resp);
David Howells1db88c52019-07-30 15:56:57 +0100891 ret = rxkad_encrypt_response(conn, resp, token->kad);
892 if (ret == 0)
893 ret = rxkad_send_response(conn, &sp->hdr, resp, token->kad);
David Howells8c2f8262018-02-08 15:59:07 +0000894 kfree(resp);
895 return ret;
David Howells17926a72007-04-26 15:48:28 -0700896
897protocol_error:
David Howellsfb46f6e2017-04-06 10:12:00 +0100898 trace_rxrpc_rx_eproto(NULL, sp->hdr.serial, eproto);
David Howellsef686222017-04-06 10:11:59 +0100899 ret = -EPROTO;
900other_error:
David Howells17926a72007-04-26 15:48:28 -0700901 *_abort_code = abort_code;
David Howellsef686222017-04-06 10:11:59 +0100902 return ret;
David Howells17926a72007-04-26 15:48:28 -0700903}
904
905/*
906 * decrypt the kerberos IV ticket in the response
907 */
908static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
David Howellsfb46f6e2017-04-06 10:12:00 +0100909 struct sk_buff *skb,
David Howells17926a72007-04-26 15:48:28 -0700910 void *ticket, size_t ticket_len,
911 struct rxrpc_crypt *_session_key,
Baolin Wang10674a02017-08-29 10:15:40 +0100912 time64_t *_expiry,
David Howells17926a72007-04-26 15:48:28 -0700913 u32 *_abort_code)
914{
Herbert Xu1afe5932016-01-24 21:19:01 +0800915 struct skcipher_request *req;
David Howellsfb46f6e2017-04-06 10:12:00 +0100916 struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
David Howells17926a72007-04-26 15:48:28 -0700917 struct rxrpc_crypt iv, key;
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700918 struct scatterlist sg[1];
David Howells17926a72007-04-26 15:48:28 -0700919 struct in_addr addr;
Eric Dumazet95c96172012-04-15 05:58:06 +0000920 unsigned int life;
David Howellsfb46f6e2017-04-06 10:12:00 +0100921 const char *eproto;
Baolin Wang10674a02017-08-29 10:15:40 +0100922 time64_t issue, now;
David Howells17926a72007-04-26 15:48:28 -0700923 bool little_endian;
924 int ret;
David Howellsfb46f6e2017-04-06 10:12:00 +0100925 u32 abort_code;
David Howells17926a72007-04-26 15:48:28 -0700926 u8 *p, *q, *name, *end;
927
928 _enter("{%d},{%x}", conn->debug_id, key_serial(conn->server_key));
929
930 *_expiry = 0;
931
932 ret = key_validate(conn->server_key);
933 if (ret < 0) {
934 switch (ret) {
935 case -EKEYEXPIRED:
David Howellsfb46f6e2017-04-06 10:12:00 +0100936 abort_code = RXKADEXPIRED;
David Howellsef686222017-04-06 10:11:59 +0100937 goto other_error;
David Howells17926a72007-04-26 15:48:28 -0700938 default:
David Howellsfb46f6e2017-04-06 10:12:00 +0100939 abort_code = RXKADNOAUTH;
David Howellsef686222017-04-06 10:11:59 +0100940 goto other_error;
David Howells17926a72007-04-26 15:48:28 -0700941 }
942 }
943
David Howells146aa8b2015-10-21 14:04:48 +0100944 ASSERT(conn->server_key->payload.data[0] != NULL);
David Howells17926a72007-04-26 15:48:28 -0700945 ASSERTCMP((unsigned long) ticket & 7UL, ==, 0);
946
David Howells146aa8b2015-10-21 14:04:48 +0100947 memcpy(&iv, &conn->server_key->payload.data[2], sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700948
David Howellsef686222017-04-06 10:11:59 +0100949 ret = -ENOMEM;
Herbert Xu1afe5932016-01-24 21:19:01 +0800950 req = skcipher_request_alloc(conn->server_key->payload.data[0],
951 GFP_NOFS);
David Howellsef686222017-04-06 10:11:59 +0100952 if (!req)
953 goto temporary_error;
David Howells17926a72007-04-26 15:48:28 -0700954
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700955 sg_init_one(&sg[0], ticket, ticket_len);
Herbert Xu1afe5932016-01-24 21:19:01 +0800956 skcipher_request_set_callback(req, 0, NULL, NULL);
957 skcipher_request_set_crypt(req, sg, sg, ticket_len, iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +0800958 crypto_skcipher_decrypt(req);
959 skcipher_request_free(req);
David Howells17926a72007-04-26 15:48:28 -0700960
961 p = ticket;
962 end = p + ticket_len;
963
David Howellsfb46f6e2017-04-06 10:12:00 +0100964#define Z(field) \
David Howells17926a72007-04-26 15:48:28 -0700965 ({ \
966 u8 *__str = p; \
David Howellsfb46f6e2017-04-06 10:12:00 +0100967 eproto = tracepoint_string("rxkad_bad_"#field); \
David Howells17926a72007-04-26 15:48:28 -0700968 q = memchr(p, 0, end - p); \
David Howellsfb46f6e2017-04-06 10:12:00 +0100969 if (!q || q - p > (field##_SZ)) \
David Howells17926a72007-04-26 15:48:28 -0700970 goto bad_ticket; \
971 for (; p < q; p++) \
972 if (!isprint(*p)) \
973 goto bad_ticket; \
974 p++; \
975 __str; \
976 })
977
978 /* extract the ticket flags */
979 _debug("KIV FLAGS: %x", *p);
980 little_endian = *p & 1;
981 p++;
982
983 /* extract the authentication name */
David Howellsfb46f6e2017-04-06 10:12:00 +0100984 name = Z(ANAME);
David Howells17926a72007-04-26 15:48:28 -0700985 _debug("KIV ANAME: %s", name);
986
987 /* extract the principal's instance */
David Howellsfb46f6e2017-04-06 10:12:00 +0100988 name = Z(INST);
David Howells17926a72007-04-26 15:48:28 -0700989 _debug("KIV INST : %s", name);
990
991 /* extract the principal's authentication domain */
David Howellsfb46f6e2017-04-06 10:12:00 +0100992 name = Z(REALM);
David Howells17926a72007-04-26 15:48:28 -0700993 _debug("KIV REALM: %s", name);
994
David Howellsfb46f6e2017-04-06 10:12:00 +0100995 eproto = tracepoint_string("rxkad_bad_len");
David Howells17926a72007-04-26 15:48:28 -0700996 if (end - p < 4 + 8 + 4 + 2)
997 goto bad_ticket;
998
999 /* get the IPv4 address of the entity that requested the ticket */
1000 memcpy(&addr, p, sizeof(addr));
1001 p += 4;
Harvey Harrison21454aa2008-10-31 00:54:56 -07001002 _debug("KIV ADDR : %pI4", &addr);
David Howells17926a72007-04-26 15:48:28 -07001003
1004 /* get the session key from the ticket */
1005 memcpy(&key, p, sizeof(key));
1006 p += 8;
1007 _debug("KIV KEY : %08x %08x", ntohl(key.n[0]), ntohl(key.n[1]));
1008 memcpy(_session_key, &key, sizeof(key));
1009
1010 /* get the ticket's lifetime */
1011 life = *p++ * 5 * 60;
1012 _debug("KIV LIFE : %u", life);
1013
1014 /* get the issue time of the ticket */
1015 if (little_endian) {
1016 __le32 stamp;
1017 memcpy(&stamp, p, 4);
Baolin Wang10674a02017-08-29 10:15:40 +01001018 issue = rxrpc_u32_to_time64(le32_to_cpu(stamp));
David Howells17926a72007-04-26 15:48:28 -07001019 } else {
1020 __be32 stamp;
1021 memcpy(&stamp, p, 4);
Baolin Wang10674a02017-08-29 10:15:40 +01001022 issue = rxrpc_u32_to_time64(be32_to_cpu(stamp));
David Howells17926a72007-04-26 15:48:28 -07001023 }
1024 p += 4;
Baolin Wang10674a02017-08-29 10:15:40 +01001025 now = ktime_get_real_seconds();
1026 _debug("KIV ISSUE: %llx [%llx]", issue, now);
David Howells17926a72007-04-26 15:48:28 -07001027
1028 /* check the ticket is in date */
1029 if (issue > now) {
David Howellsfb46f6e2017-04-06 10:12:00 +01001030 abort_code = RXKADNOAUTH;
David Howells17926a72007-04-26 15:48:28 -07001031 ret = -EKEYREJECTED;
David Howellsef686222017-04-06 10:11:59 +01001032 goto other_error;
David Howells17926a72007-04-26 15:48:28 -07001033 }
1034
1035 if (issue < now - life) {
David Howellsfb46f6e2017-04-06 10:12:00 +01001036 abort_code = RXKADEXPIRED;
David Howells17926a72007-04-26 15:48:28 -07001037 ret = -EKEYEXPIRED;
David Howellsef686222017-04-06 10:11:59 +01001038 goto other_error;
David Howells17926a72007-04-26 15:48:28 -07001039 }
1040
1041 *_expiry = issue + life;
1042
1043 /* get the service name */
David Howellsfb46f6e2017-04-06 10:12:00 +01001044 name = Z(SNAME);
David Howells17926a72007-04-26 15:48:28 -07001045 _debug("KIV SNAME: %s", name);
1046
1047 /* get the service instance name */
David Howellsfb46f6e2017-04-06 10:12:00 +01001048 name = Z(INST);
David Howells17926a72007-04-26 15:48:28 -07001049 _debug("KIV SINST: %s", name);
David Howellsef686222017-04-06 10:11:59 +01001050 return 0;
David Howells17926a72007-04-26 15:48:28 -07001051
1052bad_ticket:
David Howellsfb46f6e2017-04-06 10:12:00 +01001053 trace_rxrpc_rx_eproto(NULL, sp->hdr.serial, eproto);
1054 abort_code = RXKADBADTICKET;
David Howellsef686222017-04-06 10:11:59 +01001055 ret = -EPROTO;
1056other_error:
David Howellsfb46f6e2017-04-06 10:12:00 +01001057 *_abort_code = abort_code;
David Howellsef686222017-04-06 10:11:59 +01001058 return ret;
1059temporary_error:
1060 return ret;
David Howells17926a72007-04-26 15:48:28 -07001061}
1062
1063/*
1064 * decrypt the response packet
1065 */
1066static void rxkad_decrypt_response(struct rxrpc_connection *conn,
1067 struct rxkad_response *resp,
1068 const struct rxrpc_crypt *session_key)
1069{
David Howells1db88c52019-07-30 15:56:57 +01001070 struct skcipher_request *req = rxkad_ci_req;
Herbert Xua2636292016-06-26 14:55:24 -07001071 struct scatterlist sg[1];
David Howells17926a72007-04-26 15:48:28 -07001072 struct rxrpc_crypt iv;
1073
1074 _enter(",,%08x%08x",
1075 ntohl(session_key->n[0]), ntohl(session_key->n[1]));
1076
David Howells17926a72007-04-26 15:48:28 -07001077 mutex_lock(&rxkad_ci_mutex);
Kees Cook69d826f2018-09-18 19:10:47 -07001078 if (crypto_sync_skcipher_setkey(rxkad_ci, session_key->x,
David Howells1db88c52019-07-30 15:56:57 +01001079 sizeof(*session_key)) < 0)
David Howells17926a72007-04-26 15:48:28 -07001080 BUG();
1081
1082 memcpy(&iv, session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -07001083
Herbert Xua2636292016-06-26 14:55:24 -07001084 sg_init_table(sg, 1);
1085 sg_set_buf(sg, &resp->encrypted, sizeof(resp->encrypted));
Kees Cook69d826f2018-09-18 19:10:47 -07001086 skcipher_request_set_sync_tfm(req, rxkad_ci);
Herbert Xu1afe5932016-01-24 21:19:01 +08001087 skcipher_request_set_callback(req, 0, NULL, NULL);
1088 skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x);
Herbert Xu1afe5932016-01-24 21:19:01 +08001089 crypto_skcipher_decrypt(req);
1090 skcipher_request_zero(req);
1091
David Howells17926a72007-04-26 15:48:28 -07001092 mutex_unlock(&rxkad_ci_mutex);
1093
1094 _leave("");
1095}
1096
1097/*
1098 * verify a response
1099 */
1100static int rxkad_verify_response(struct rxrpc_connection *conn,
1101 struct sk_buff *skb,
1102 u32 *_abort_code)
1103{
David Howells8c2f8262018-02-08 15:59:07 +00001104 struct rxkad_response *response;
David Howells248f2192016-09-08 11:10:12 +01001105 struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
David Howells17926a72007-04-26 15:48:28 -07001106 struct rxrpc_crypt session_key;
David Howellsfb46f6e2017-04-06 10:12:00 +01001107 const char *eproto;
Baolin Wang10674a02017-08-29 10:15:40 +01001108 time64_t expiry;
David Howells17926a72007-04-26 15:48:28 -07001109 void *ticket;
Al Viro91e916c2008-03-29 03:08:38 +00001110 u32 abort_code, version, kvno, ticket_len, level;
1111 __be32 csum;
David Howellsa1399f82016-06-27 14:39:44 +01001112 int ret, i;
David Howells17926a72007-04-26 15:48:28 -07001113
1114 _enter("{%d,%x}", conn->debug_id, key_serial(conn->server_key));
1115
David Howells8c2f8262018-02-08 15:59:07 +00001116 ret = -ENOMEM;
1117 response = kzalloc(sizeof(struct rxkad_response), GFP_NOFS);
1118 if (!response)
1119 goto temporary_error;
1120
David Howellsfb46f6e2017-04-06 10:12:00 +01001121 eproto = tracepoint_string("rxkad_rsp_short");
David Howells17926a72007-04-26 15:48:28 -07001122 abort_code = RXKADPACKETSHORT;
David Howells775e5b72016-09-30 13:26:03 +01001123 if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
David Howells8c2f8262018-02-08 15:59:07 +00001124 response, sizeof(*response)) < 0)
David Howells17926a72007-04-26 15:48:28 -07001125 goto protocol_error;
David Howells8c2f8262018-02-08 15:59:07 +00001126 if (!pskb_pull(skb, sizeof(*response)))
David Howells17926a72007-04-26 15:48:28 -07001127 BUG();
1128
David Howells8c2f8262018-02-08 15:59:07 +00001129 version = ntohl(response->version);
1130 ticket_len = ntohl(response->ticket_len);
1131 kvno = ntohl(response->kvno);
David Howells17926a72007-04-26 15:48:28 -07001132 _proto("Rx RESPONSE %%%u { v=%u kv=%u tl=%u }",
David Howells0d12f8a2016-03-04 15:53:46 +00001133 sp->hdr.serial, version, kvno, ticket_len);
David Howells17926a72007-04-26 15:48:28 -07001134
David Howellsfb46f6e2017-04-06 10:12:00 +01001135 eproto = tracepoint_string("rxkad_rsp_ver");
David Howells17926a72007-04-26 15:48:28 -07001136 abort_code = RXKADINCONSISTENCY;
1137 if (version != RXKAD_VERSION)
David Howells4aa9cb32007-12-07 04:31:47 -08001138 goto protocol_error;
David Howells17926a72007-04-26 15:48:28 -07001139
David Howellsfb46f6e2017-04-06 10:12:00 +01001140 eproto = tracepoint_string("rxkad_rsp_tktlen");
David Howells17926a72007-04-26 15:48:28 -07001141 abort_code = RXKADTICKETLEN;
1142 if (ticket_len < 4 || ticket_len > MAXKRB5TICKETLEN)
1143 goto protocol_error;
1144
David Howellsfb46f6e2017-04-06 10:12:00 +01001145 eproto = tracepoint_string("rxkad_rsp_unkkey");
David Howells17926a72007-04-26 15:48:28 -07001146 abort_code = RXKADUNKNOWNKEY;
1147 if (kvno >= RXKAD_TKT_TYPE_KERBEROS_V5)
1148 goto protocol_error;
1149
1150 /* extract the kerberos ticket and decrypt and decode it */
David Howellsef686222017-04-06 10:11:59 +01001151 ret = -ENOMEM;
David Howells17926a72007-04-26 15:48:28 -07001152 ticket = kmalloc(ticket_len, GFP_NOFS);
1153 if (!ticket)
David Howellsef686222017-04-06 10:11:59 +01001154 goto temporary_error;
David Howells17926a72007-04-26 15:48:28 -07001155
David Howellsfb46f6e2017-04-06 10:12:00 +01001156 eproto = tracepoint_string("rxkad_tkt_short");
David Howells17926a72007-04-26 15:48:28 -07001157 abort_code = RXKADPACKETSHORT;
David Howells775e5b72016-09-30 13:26:03 +01001158 if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
1159 ticket, ticket_len) < 0)
David Howells17926a72007-04-26 15:48:28 -07001160 goto protocol_error_free;
1161
David Howellsfb46f6e2017-04-06 10:12:00 +01001162 ret = rxkad_decrypt_ticket(conn, skb, ticket, ticket_len, &session_key,
David Howellsef686222017-04-06 10:11:59 +01001163 &expiry, _abort_code);
1164 if (ret < 0)
David Howells8c2f8262018-02-08 15:59:07 +00001165 goto temporary_error_free_resp;
David Howells17926a72007-04-26 15:48:28 -07001166
1167 /* use the session key from inside the ticket to decrypt the
1168 * response */
David Howells8c2f8262018-02-08 15:59:07 +00001169 rxkad_decrypt_response(conn, response, &session_key);
David Howells17926a72007-04-26 15:48:28 -07001170
David Howellsfb46f6e2017-04-06 10:12:00 +01001171 eproto = tracepoint_string("rxkad_rsp_param");
David Howells17926a72007-04-26 15:48:28 -07001172 abort_code = RXKADSEALEDINCON;
David Howells8c2f8262018-02-08 15:59:07 +00001173 if (ntohl(response->encrypted.epoch) != conn->proto.epoch)
David Howells17926a72007-04-26 15:48:28 -07001174 goto protocol_error_free;
David Howells8c2f8262018-02-08 15:59:07 +00001175 if (ntohl(response->encrypted.cid) != conn->proto.cid)
David Howells17926a72007-04-26 15:48:28 -07001176 goto protocol_error_free;
David Howells8c2f8262018-02-08 15:59:07 +00001177 if (ntohl(response->encrypted.securityIndex) != conn->security_ix)
David Howells17926a72007-04-26 15:48:28 -07001178 goto protocol_error_free;
David Howells8c2f8262018-02-08 15:59:07 +00001179 csum = response->encrypted.checksum;
1180 response->encrypted.checksum = 0;
1181 rxkad_calc_response_checksum(response);
David Howellsfb46f6e2017-04-06 10:12:00 +01001182 eproto = tracepoint_string("rxkad_rsp_csum");
David Howells8c2f8262018-02-08 15:59:07 +00001183 if (response->encrypted.checksum != csum)
David Howells17926a72007-04-26 15:48:28 -07001184 goto protocol_error_free;
1185
David Howellsa1399f82016-06-27 14:39:44 +01001186 spin_lock(&conn->channel_lock);
1187 for (i = 0; i < RXRPC_MAXCALLS; i++) {
1188 struct rxrpc_call *call;
David Howells8c2f8262018-02-08 15:59:07 +00001189 u32 call_id = ntohl(response->encrypted.call_id[i]);
David Howellsa1399f82016-06-27 14:39:44 +01001190
David Howellsfb46f6e2017-04-06 10:12:00 +01001191 eproto = tracepoint_string("rxkad_rsp_callid");
David Howellsa1399f82016-06-27 14:39:44 +01001192 if (call_id > INT_MAX)
1193 goto protocol_error_unlock;
1194
David Howellsfb46f6e2017-04-06 10:12:00 +01001195 eproto = tracepoint_string("rxkad_rsp_callctr");
David Howellsa1399f82016-06-27 14:39:44 +01001196 if (call_id < conn->channels[i].call_counter)
1197 goto protocol_error_unlock;
David Howellsfb46f6e2017-04-06 10:12:00 +01001198
1199 eproto = tracepoint_string("rxkad_rsp_callst");
David Howellsa1399f82016-06-27 14:39:44 +01001200 if (call_id > conn->channels[i].call_counter) {
1201 call = rcu_dereference_protected(
1202 conn->channels[i].call,
1203 lockdep_is_held(&conn->channel_lock));
1204 if (call && call->state < RXRPC_CALL_COMPLETE)
1205 goto protocol_error_unlock;
1206 conn->channels[i].call_counter = call_id;
1207 }
1208 }
1209 spin_unlock(&conn->channel_lock);
David Howells17926a72007-04-26 15:48:28 -07001210
David Howellsfb46f6e2017-04-06 10:12:00 +01001211 eproto = tracepoint_string("rxkad_rsp_seq");
David Howells17926a72007-04-26 15:48:28 -07001212 abort_code = RXKADOUTOFSEQUENCE;
David Howells8c2f8262018-02-08 15:59:07 +00001213 if (ntohl(response->encrypted.inc_nonce) != conn->security_nonce + 1)
David Howells17926a72007-04-26 15:48:28 -07001214 goto protocol_error_free;
1215
David Howellsfb46f6e2017-04-06 10:12:00 +01001216 eproto = tracepoint_string("rxkad_rsp_level");
David Howells17926a72007-04-26 15:48:28 -07001217 abort_code = RXKADLEVELFAIL;
David Howells8c2f8262018-02-08 15:59:07 +00001218 level = ntohl(response->encrypted.level);
David Howells17926a72007-04-26 15:48:28 -07001219 if (level > RXRPC_SECURITY_ENCRYPT)
1220 goto protocol_error_free;
David Howells19ffa012016-04-04 14:00:36 +01001221 conn->params.security_level = level;
David Howells17926a72007-04-26 15:48:28 -07001222
1223 /* create a key to hold the security data and expiration time - after
1224 * this the connection security can be handled in exactly the same way
1225 * as for a client connection */
1226 ret = rxrpc_get_server_data_key(conn, &session_key, expiry, kvno);
David Howellsef686222017-04-06 10:11:59 +01001227 if (ret < 0)
David Howells8c2f8262018-02-08 15:59:07 +00001228 goto temporary_error_free_ticket;
David Howells17926a72007-04-26 15:48:28 -07001229
1230 kfree(ticket);
David Howells8c2f8262018-02-08 15:59:07 +00001231 kfree(response);
David Howells17926a72007-04-26 15:48:28 -07001232 _leave(" = 0");
1233 return 0;
1234
David Howellsa1399f82016-06-27 14:39:44 +01001235protocol_error_unlock:
1236 spin_unlock(&conn->channel_lock);
David Howells17926a72007-04-26 15:48:28 -07001237protocol_error_free:
1238 kfree(ticket);
1239protocol_error:
David Howells8c2f8262018-02-08 15:59:07 +00001240 kfree(response);
David Howellsfb46f6e2017-04-06 10:12:00 +01001241 trace_rxrpc_rx_eproto(NULL, sp->hdr.serial, eproto);
David Howells17926a72007-04-26 15:48:28 -07001242 *_abort_code = abort_code;
David Howells17926a72007-04-26 15:48:28 -07001243 return -EPROTO;
David Howellsef686222017-04-06 10:11:59 +01001244
David Howells8c2f8262018-02-08 15:59:07 +00001245temporary_error_free_ticket:
David Howellsef686222017-04-06 10:11:59 +01001246 kfree(ticket);
David Howells8c2f8262018-02-08 15:59:07 +00001247temporary_error_free_resp:
1248 kfree(response);
David Howellsef686222017-04-06 10:11:59 +01001249temporary_error:
1250 /* Ignore the response packet if we got a temporary error such as
1251 * ENOMEM. We just want to send the challenge again. Note that we
1252 * also come out this way if the ticket decryption fails.
1253 */
1254 return ret;
David Howells17926a72007-04-26 15:48:28 -07001255}
1256
1257/*
1258 * clear the connection security
1259 */
1260static void rxkad_clear(struct rxrpc_connection *conn)
1261{
1262 _enter("");
1263
1264 if (conn->cipher)
Kees Cook69d826f2018-09-18 19:10:47 -07001265 crypto_free_sync_skcipher(conn->cipher);
David Howells17926a72007-04-26 15:48:28 -07001266}
1267
1268/*
David Howells648af7f2016-04-07 17:23:51 +01001269 * Initialise the rxkad security service.
1270 */
1271static int rxkad_init(void)
1272{
David Howells1db88c52019-07-30 15:56:57 +01001273 struct crypto_sync_skcipher *tfm;
1274 struct skcipher_request *req;
1275
David Howells648af7f2016-04-07 17:23:51 +01001276 /* pin the cipher we need so that the crypto layer doesn't invoke
1277 * keventd to go get it */
David Howells1db88c52019-07-30 15:56:57 +01001278 tfm = crypto_alloc_sync_skcipher("pcbc(fcrypt)", 0, 0);
1279 if (IS_ERR(tfm))
1280 return PTR_ERR(tfm);
1281
1282 req = skcipher_request_alloc(&tfm->base, GFP_KERNEL);
1283 if (!req)
1284 goto nomem_tfm;
1285
1286 rxkad_ci_req = req;
1287 rxkad_ci = tfm;
1288 return 0;
1289
1290nomem_tfm:
1291 crypto_free_sync_skcipher(tfm);
1292 return -ENOMEM;
David Howells648af7f2016-04-07 17:23:51 +01001293}
1294
1295/*
1296 * Clean up the rxkad security service.
1297 */
1298static void rxkad_exit(void)
1299{
David Howells1db88c52019-07-30 15:56:57 +01001300 crypto_free_sync_skcipher(rxkad_ci);
1301 skcipher_request_free(rxkad_ci_req);
David Howells648af7f2016-04-07 17:23:51 +01001302}
1303
1304/*
David Howells17926a72007-04-26 15:48:28 -07001305 * RxRPC Kerberos-based security
1306 */
David Howells648af7f2016-04-07 17:23:51 +01001307const struct rxrpc_security rxkad = {
David Howells17926a72007-04-26 15:48:28 -07001308 .name = "rxkad",
David Howells8b815472009-09-14 01:17:30 +00001309 .security_index = RXRPC_SECURITY_RXKAD,
David Howells648af7f2016-04-07 17:23:51 +01001310 .init = rxkad_init,
1311 .exit = rxkad_exit,
David Howells17926a72007-04-26 15:48:28 -07001312 .init_connection_security = rxkad_init_connection_security,
1313 .prime_packet_security = rxkad_prime_packet_security,
1314 .secure_packet = rxkad_secure_packet,
1315 .verify_packet = rxkad_verify_packet,
David Howells1db88c52019-07-30 15:56:57 +01001316 .free_call_crypto = rxkad_free_call_crypto,
David Howells248f2192016-09-08 11:10:12 +01001317 .locate_data = rxkad_locate_data,
David Howells17926a72007-04-26 15:48:28 -07001318 .issue_challenge = rxkad_issue_challenge,
1319 .respond_to_challenge = rxkad_respond_to_challenge,
1320 .verify_response = rxkad_verify_response,
1321 .clear = rxkad_clear,
1322};