blob: d4da538b3d3c608055a9577cc2e2480b12ef7c5e [file] [log] [blame]
David Howells17926a72007-04-26 15:48:28 -07001/* Kerberos-based RxRPC security
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
Joe Perches9b6d5392016-06-02 12:08:52 -070012#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
Herbert Xu1afe5932016-01-24 21:19:01 +080014#include <crypto/skcipher.h>
David Howells17926a72007-04-26 15:48:28 -070015#include <linux/module.h>
16#include <linux/net.h>
17#include <linux/skbuff.h>
18#include <linux/udp.h>
David Howells17926a72007-04-26 15:48:28 -070019#include <linux/scatterlist.h>
20#include <linux/ctype.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090021#include <linux/slab.h>
David Howells17926a72007-04-26 15:48:28 -070022#include <net/sock.h>
23#include <net/af_rxrpc.h>
David Howells33941282009-09-14 01:17:35 +000024#include <keys/rxrpc-type.h>
David Howells17926a72007-04-26 15:48:28 -070025#include "ar-internal.h"
26
27#define RXKAD_VERSION 2
28#define MAXKRB5TICKETLEN 1024
29#define RXKAD_TKT_TYPE_KERBEROS_V5 256
30#define ANAME_SZ 40 /* size of authentication name */
31#define INST_SZ 40 /* size of principal's instance */
32#define REALM_SZ 40 /* size of principal's auth domain */
33#define SNAME_SZ 40 /* size of service name */
34
David Howells17926a72007-04-26 15:48:28 -070035struct rxkad_level1_hdr {
36 __be32 data_size; /* true data size (excluding padding) */
37};
38
39struct rxkad_level2_hdr {
40 __be32 data_size; /* true data size (excluding padding) */
41 __be32 checksum; /* decrypted data checksum */
42};
43
David Howells17926a72007-04-26 15:48:28 -070044/*
45 * this holds a pinned cipher so that keventd doesn't get called by the cipher
46 * alloc routine, but since we have it to hand, we use it to decrypt RESPONSE
47 * packets
48 */
Herbert Xu1afe5932016-01-24 21:19:01 +080049static struct crypto_skcipher *rxkad_ci;
David Howells17926a72007-04-26 15:48:28 -070050static DEFINE_MUTEX(rxkad_ci_mutex);
51
52/*
53 * initialise connection security
54 */
55static int rxkad_init_connection_security(struct rxrpc_connection *conn)
56{
Herbert Xu1afe5932016-01-24 21:19:01 +080057 struct crypto_skcipher *ci;
David Howells33941282009-09-14 01:17:35 +000058 struct rxrpc_key_token *token;
David Howells17926a72007-04-26 15:48:28 -070059 int ret;
60
61 _enter("{%d},{%x}", conn->debug_id, key_serial(conn->key));
62
David Howells146aa8b2015-10-21 14:04:48 +010063 token = conn->key->payload.data[0];
David Howells33941282009-09-14 01:17:35 +000064 conn->security_ix = token->security_index;
David Howells17926a72007-04-26 15:48:28 -070065
Herbert Xu1afe5932016-01-24 21:19:01 +080066 ci = crypto_alloc_skcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC);
David Howells17926a72007-04-26 15:48:28 -070067 if (IS_ERR(ci)) {
68 _debug("no cipher");
69 ret = PTR_ERR(ci);
70 goto error;
71 }
72
Herbert Xu1afe5932016-01-24 21:19:01 +080073 if (crypto_skcipher_setkey(ci, token->kad->session_key,
74 sizeof(token->kad->session_key)) < 0)
David Howells17926a72007-04-26 15:48:28 -070075 BUG();
76
77 switch (conn->security_level) {
78 case RXRPC_SECURITY_PLAIN:
79 break;
80 case RXRPC_SECURITY_AUTH:
81 conn->size_align = 8;
82 conn->security_size = sizeof(struct rxkad_level1_hdr);
83 conn->header_size += sizeof(struct rxkad_level1_hdr);
84 break;
85 case RXRPC_SECURITY_ENCRYPT:
86 conn->size_align = 8;
87 conn->security_size = sizeof(struct rxkad_level2_hdr);
88 conn->header_size += sizeof(struct rxkad_level2_hdr);
89 break;
90 default:
91 ret = -EKEYREJECTED;
92 goto error;
93 }
94
95 conn->cipher = ci;
96 ret = 0;
97error:
98 _leave(" = %d", ret);
99 return ret;
100}
101
102/*
103 * prime the encryption state with the invariant parts of a connection's
104 * description
105 */
106static void rxkad_prime_packet_security(struct rxrpc_connection *conn)
107{
David Howells33941282009-09-14 01:17:35 +0000108 struct rxrpc_key_token *token;
Herbert Xu1afe5932016-01-24 21:19:01 +0800109 SKCIPHER_REQUEST_ON_STACK(req, conn->cipher);
David Howells17926a72007-04-26 15:48:28 -0700110 struct scatterlist sg[2];
111 struct rxrpc_crypt iv;
112 struct {
113 __be32 x[4];
114 } tmpbuf __attribute__((aligned(16))); /* must all be in same page */
115
116 _enter("");
117
118 if (!conn->key)
119 return;
120
David Howells146aa8b2015-10-21 14:04:48 +0100121 token = conn->key->payload.data[0];
David Howells33941282009-09-14 01:17:35 +0000122 memcpy(&iv, token->kad->session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700123
David Howells0d12f8a2016-03-04 15:53:46 +0000124 tmpbuf.x[0] = htonl(conn->epoch);
125 tmpbuf.x[1] = htonl(conn->cid);
David Howells17926a72007-04-26 15:48:28 -0700126 tmpbuf.x[2] = 0;
127 tmpbuf.x[3] = htonl(conn->security_ix);
128
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700129 sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf));
130 sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf));
Herbert Xu1afe5932016-01-24 21:19:01 +0800131
132 skcipher_request_set_tfm(req, conn->cipher);
133 skcipher_request_set_callback(req, 0, NULL, NULL);
134 skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x);
135
136 crypto_skcipher_encrypt(req);
137 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700138
139 memcpy(&conn->csum_iv, &tmpbuf.x[2], sizeof(conn->csum_iv));
David Howells2b15ef12016-03-04 15:59:13 +0000140 ASSERTCMP((u32 __force)conn->csum_iv.n[0], ==, (u32 __force)tmpbuf.x[2]);
David Howells17926a72007-04-26 15:48:28 -0700141
142 _leave("");
143}
144
145/*
146 * partially encrypt a packet (level 1 security)
147 */
148static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
149 struct sk_buff *skb,
150 u32 data_size,
151 void *sechdr)
152{
153 struct rxrpc_skb_priv *sp;
Herbert Xu1afe5932016-01-24 21:19:01 +0800154 SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher);
David Howells17926a72007-04-26 15:48:28 -0700155 struct rxrpc_crypt iv;
156 struct scatterlist sg[2];
157 struct {
158 struct rxkad_level1_hdr hdr;
159 __be32 first; /* first four bytes of data and padding */
160 } tmpbuf __attribute__((aligned(8))); /* must all be in same page */
161 u16 check;
162
163 sp = rxrpc_skb(skb);
164
165 _enter("");
166
David Howells0d12f8a2016-03-04 15:53:46 +0000167 check = sp->hdr.seq ^ sp->hdr.callNumber;
168 data_size |= (u32)check << 16;
David Howells17926a72007-04-26 15:48:28 -0700169
170 tmpbuf.hdr.data_size = htonl(data_size);
171 memcpy(&tmpbuf.first, sechdr + 4, sizeof(tmpbuf.first));
172
173 /* start the encryption afresh */
174 memset(&iv, 0, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700175
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700176 sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf));
177 sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf));
Herbert Xu1afe5932016-01-24 21:19:01 +0800178
179 skcipher_request_set_tfm(req, call->conn->cipher);
180 skcipher_request_set_callback(req, 0, NULL, NULL);
181 skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x);
182
183 crypto_skcipher_encrypt(req);
184 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700185
186 memcpy(sechdr, &tmpbuf, sizeof(tmpbuf));
187
188 _leave(" = 0");
189 return 0;
190}
191
192/*
193 * wholly encrypt a packet (level 2 security)
194 */
195static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
David Howellsb4f13422016-03-04 15:56:19 +0000196 struct sk_buff *skb,
197 u32 data_size,
198 void *sechdr)
David Howells17926a72007-04-26 15:48:28 -0700199{
David Howells33941282009-09-14 01:17:35 +0000200 const struct rxrpc_key_token *token;
David Howells17926a72007-04-26 15:48:28 -0700201 struct rxkad_level2_hdr rxkhdr
202 __attribute__((aligned(8))); /* must be all on one page */
203 struct rxrpc_skb_priv *sp;
Herbert Xu1afe5932016-01-24 21:19:01 +0800204 SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher);
David Howells17926a72007-04-26 15:48:28 -0700205 struct rxrpc_crypt iv;
206 struct scatterlist sg[16];
207 struct sk_buff *trailer;
Eric Dumazet95c96172012-04-15 05:58:06 +0000208 unsigned int len;
David Howells17926a72007-04-26 15:48:28 -0700209 u16 check;
210 int nsg;
Herbert Xu1afe5932016-01-24 21:19:01 +0800211 int err;
David Howells17926a72007-04-26 15:48:28 -0700212
213 sp = rxrpc_skb(skb);
214
215 _enter("");
216
David Howells0d12f8a2016-03-04 15:53:46 +0000217 check = sp->hdr.seq ^ sp->hdr.callNumber;
David Howells17926a72007-04-26 15:48:28 -0700218
David Howells0d12f8a2016-03-04 15:53:46 +0000219 rxkhdr.data_size = htonl(data_size | (u32)check << 16);
David Howells17926a72007-04-26 15:48:28 -0700220 rxkhdr.checksum = 0;
221
222 /* encrypt from the session key */
David Howells146aa8b2015-10-21 14:04:48 +0100223 token = call->conn->key->payload.data[0];
David Howells33941282009-09-14 01:17:35 +0000224 memcpy(&iv, token->kad->session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700225
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700226 sg_init_one(&sg[0], sechdr, sizeof(rxkhdr));
227 sg_init_one(&sg[1], &rxkhdr, sizeof(rxkhdr));
Herbert Xu1afe5932016-01-24 21:19:01 +0800228
229 skcipher_request_set_tfm(req, call->conn->cipher);
230 skcipher_request_set_callback(req, 0, NULL, NULL);
231 skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(rxkhdr), iv.x);
232
233 crypto_skcipher_encrypt(req);
David Howells17926a72007-04-26 15:48:28 -0700234
235 /* we want to encrypt the skbuff in-place */
236 nsg = skb_cow_data(skb, 0, &trailer);
Herbert Xu1afe5932016-01-24 21:19:01 +0800237 err = -ENOMEM;
David Howells17926a72007-04-26 15:48:28 -0700238 if (nsg < 0 || nsg > 16)
Herbert Xu1afe5932016-01-24 21:19:01 +0800239 goto out;
David Howells17926a72007-04-26 15:48:28 -0700240
241 len = data_size + call->conn->size_align - 1;
242 len &= ~(call->conn->size_align - 1);
243
David S. Miller51c739d2007-10-30 21:29:29 -0700244 sg_init_table(sg, nsg);
245 skb_to_sgvec(skb, sg, 0, len);
Herbert Xu1afe5932016-01-24 21:19:01 +0800246
247 skcipher_request_set_crypt(req, sg, sg, len, iv.x);
248
249 crypto_skcipher_encrypt(req);
David Howells17926a72007-04-26 15:48:28 -0700250
251 _leave(" = 0");
Herbert Xu1afe5932016-01-24 21:19:01 +0800252 err = 0;
253
254out:
255 skcipher_request_zero(req);
256 return err;
David Howells17926a72007-04-26 15:48:28 -0700257}
258
259/*
260 * checksum an RxRPC packet header
261 */
262static int rxkad_secure_packet(const struct rxrpc_call *call,
David Howellsb4f13422016-03-04 15:56:19 +0000263 struct sk_buff *skb,
264 size_t data_size,
265 void *sechdr)
David Howells17926a72007-04-26 15:48:28 -0700266{
267 struct rxrpc_skb_priv *sp;
Herbert Xu1afe5932016-01-24 21:19:01 +0800268 SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher);
David Howells17926a72007-04-26 15:48:28 -0700269 struct rxrpc_crypt iv;
270 struct scatterlist sg[2];
271 struct {
272 __be32 x[2];
273 } tmpbuf __attribute__((aligned(8))); /* must all be in same page */
David Howells0d12f8a2016-03-04 15:53:46 +0000274 u32 x, y;
David Howells17926a72007-04-26 15:48:28 -0700275 int ret;
276
277 sp = rxrpc_skb(skb);
278
279 _enter("{%d{%x}},{#%u},%zu,",
David Howells0d12f8a2016-03-04 15:53:46 +0000280 call->debug_id, key_serial(call->conn->key), sp->hdr.seq,
David Howells17926a72007-04-26 15:48:28 -0700281 data_size);
282
283 if (!call->conn->cipher)
284 return 0;
285
286 ret = key_validate(call->conn->key);
287 if (ret < 0)
288 return ret;
289
290 /* continue encrypting from where we left off */
291 memcpy(&iv, call->conn->csum_iv.x, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700292
293 /* calculate the security checksum */
David Howells0d12f8a2016-03-04 15:53:46 +0000294 x = call->channel << (32 - RXRPC_CIDSHIFT);
295 x |= sp->hdr.seq & 0x3fffffff;
296 tmpbuf.x[0] = htonl(sp->hdr.callNumber);
297 tmpbuf.x[1] = htonl(x);
David Howells17926a72007-04-26 15:48:28 -0700298
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700299 sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf));
300 sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf));
Herbert Xu1afe5932016-01-24 21:19:01 +0800301
302 skcipher_request_set_tfm(req, call->conn->cipher);
303 skcipher_request_set_callback(req, 0, NULL, NULL);
304 skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x);
305
306 crypto_skcipher_encrypt(req);
307 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700308
Al Viro91e916c2008-03-29 03:08:38 +0000309 y = ntohl(tmpbuf.x[1]);
310 y = (y >> 16) & 0xffff;
311 if (y == 0)
312 y = 1; /* zero checksums are not permitted */
David Howells0d12f8a2016-03-04 15:53:46 +0000313 sp->hdr.cksum = y;
David Howells17926a72007-04-26 15:48:28 -0700314
315 switch (call->conn->security_level) {
316 case RXRPC_SECURITY_PLAIN:
317 ret = 0;
318 break;
319 case RXRPC_SECURITY_AUTH:
320 ret = rxkad_secure_packet_auth(call, skb, data_size, sechdr);
321 break;
322 case RXRPC_SECURITY_ENCRYPT:
323 ret = rxkad_secure_packet_encrypt(call, skb, data_size,
324 sechdr);
325 break;
326 default:
327 ret = -EPERM;
328 break;
329 }
330
Al Viro91e916c2008-03-29 03:08:38 +0000331 _leave(" = %d [set %hx]", ret, y);
David Howells17926a72007-04-26 15:48:28 -0700332 return ret;
333}
334
335/*
336 * decrypt partial encryption on a packet (level 1 security)
337 */
338static int rxkad_verify_packet_auth(const struct rxrpc_call *call,
339 struct sk_buff *skb,
340 u32 *_abort_code)
341{
342 struct rxkad_level1_hdr sechdr;
343 struct rxrpc_skb_priv *sp;
Herbert Xu1afe5932016-01-24 21:19:01 +0800344 SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher);
David Howells17926a72007-04-26 15:48:28 -0700345 struct rxrpc_crypt iv;
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700346 struct scatterlist sg[16];
David Howells17926a72007-04-26 15:48:28 -0700347 struct sk_buff *trailer;
348 u32 data_size, buf;
349 u16 check;
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700350 int nsg;
David Howells17926a72007-04-26 15:48:28 -0700351
352 _enter("");
353
354 sp = rxrpc_skb(skb);
355
356 /* we want to decrypt the skbuff in-place */
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700357 nsg = skb_cow_data(skb, 0, &trailer);
358 if (nsg < 0 || nsg > 16)
David Howells17926a72007-04-26 15:48:28 -0700359 goto nomem;
360
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700361 sg_init_table(sg, nsg);
David S. Miller51c739d2007-10-30 21:29:29 -0700362 skb_to_sgvec(skb, sg, 0, 8);
David Howells17926a72007-04-26 15:48:28 -0700363
364 /* start the decryption afresh */
365 memset(&iv, 0, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700366
Herbert Xu1afe5932016-01-24 21:19:01 +0800367 skcipher_request_set_tfm(req, call->conn->cipher);
368 skcipher_request_set_callback(req, 0, NULL, NULL);
369 skcipher_request_set_crypt(req, sg, sg, 8, iv.x);
370
371 crypto_skcipher_decrypt(req);
372 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700373
374 /* remove the decrypted packet length */
375 if (skb_copy_bits(skb, 0, &sechdr, sizeof(sechdr)) < 0)
376 goto datalen_error;
377 if (!skb_pull(skb, sizeof(sechdr)))
378 BUG();
379
380 buf = ntohl(sechdr.data_size);
381 data_size = buf & 0xffff;
382
383 check = buf >> 16;
David Howells0d12f8a2016-03-04 15:53:46 +0000384 check ^= sp->hdr.seq ^ sp->hdr.callNumber;
David Howells17926a72007-04-26 15:48:28 -0700385 check &= 0xffff;
386 if (check != 0) {
387 *_abort_code = RXKADSEALEDINCON;
388 goto protocol_error;
389 }
390
391 /* shorten the packet to remove the padding */
392 if (data_size > skb->len)
393 goto datalen_error;
394 else if (data_size < skb->len)
395 skb->len = data_size;
396
397 _leave(" = 0 [dlen=%x]", data_size);
398 return 0;
399
400datalen_error:
401 *_abort_code = RXKADDATALEN;
402protocol_error:
403 _leave(" = -EPROTO");
404 return -EPROTO;
405
406nomem:
407 _leave(" = -ENOMEM");
408 return -ENOMEM;
409}
410
411/*
412 * wholly decrypt a packet (level 2 security)
413 */
414static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call,
415 struct sk_buff *skb,
416 u32 *_abort_code)
417{
David Howells33941282009-09-14 01:17:35 +0000418 const struct rxrpc_key_token *token;
David Howells17926a72007-04-26 15:48:28 -0700419 struct rxkad_level2_hdr sechdr;
420 struct rxrpc_skb_priv *sp;
Herbert Xu1afe5932016-01-24 21:19:01 +0800421 SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher);
David Howells17926a72007-04-26 15:48:28 -0700422 struct rxrpc_crypt iv;
423 struct scatterlist _sg[4], *sg;
424 struct sk_buff *trailer;
425 u32 data_size, buf;
426 u16 check;
427 int nsg;
428
429 _enter(",{%d}", skb->len);
430
431 sp = rxrpc_skb(skb);
432
433 /* we want to decrypt the skbuff in-place */
434 nsg = skb_cow_data(skb, 0, &trailer);
435 if (nsg < 0)
436 goto nomem;
437
438 sg = _sg;
439 if (unlikely(nsg > 4)) {
440 sg = kmalloc(sizeof(*sg) * nsg, GFP_NOIO);
441 if (!sg)
442 goto nomem;
443 }
444
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700445 sg_init_table(sg, nsg);
David S. Miller51c739d2007-10-30 21:29:29 -0700446 skb_to_sgvec(skb, sg, 0, skb->len);
David Howells17926a72007-04-26 15:48:28 -0700447
448 /* decrypt from the session key */
David Howells146aa8b2015-10-21 14:04:48 +0100449 token = call->conn->key->payload.data[0];
David Howells33941282009-09-14 01:17:35 +0000450 memcpy(&iv, token->kad->session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700451
Herbert Xu1afe5932016-01-24 21:19:01 +0800452 skcipher_request_set_tfm(req, call->conn->cipher);
453 skcipher_request_set_callback(req, 0, NULL, NULL);
454 skcipher_request_set_crypt(req, sg, sg, skb->len, iv.x);
455
456 crypto_skcipher_decrypt(req);
457 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700458 if (sg != _sg)
459 kfree(sg);
460
461 /* remove the decrypted packet length */
462 if (skb_copy_bits(skb, 0, &sechdr, sizeof(sechdr)) < 0)
463 goto datalen_error;
464 if (!skb_pull(skb, sizeof(sechdr)))
465 BUG();
466
467 buf = ntohl(sechdr.data_size);
468 data_size = buf & 0xffff;
469
470 check = buf >> 16;
David Howells0d12f8a2016-03-04 15:53:46 +0000471 check ^= sp->hdr.seq ^ sp->hdr.callNumber;
David Howells17926a72007-04-26 15:48:28 -0700472 check &= 0xffff;
473 if (check != 0) {
474 *_abort_code = RXKADSEALEDINCON;
475 goto protocol_error;
476 }
477
478 /* shorten the packet to remove the padding */
479 if (data_size > skb->len)
480 goto datalen_error;
481 else if (data_size < skb->len)
482 skb->len = data_size;
483
484 _leave(" = 0 [dlen=%x]", data_size);
485 return 0;
486
487datalen_error:
488 *_abort_code = RXKADDATALEN;
489protocol_error:
490 _leave(" = -EPROTO");
491 return -EPROTO;
492
493nomem:
494 _leave(" = -ENOMEM");
495 return -ENOMEM;
496}
497
498/*
499 * verify the security on a received packet
500 */
501static int rxkad_verify_packet(const struct rxrpc_call *call,
502 struct sk_buff *skb,
503 u32 *_abort_code)
504{
Herbert Xu1afe5932016-01-24 21:19:01 +0800505 SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher);
David Howells17926a72007-04-26 15:48:28 -0700506 struct rxrpc_skb_priv *sp;
507 struct rxrpc_crypt iv;
508 struct scatterlist sg[2];
509 struct {
510 __be32 x[2];
511 } tmpbuf __attribute__((aligned(8))); /* must all be in same page */
David Howells0d12f8a2016-03-04 15:53:46 +0000512 u16 cksum;
513 u32 x, y;
David Howells17926a72007-04-26 15:48:28 -0700514 int ret;
515
516 sp = rxrpc_skb(skb);
517
518 _enter("{%d{%x}},{#%u}",
David Howells0d12f8a2016-03-04 15:53:46 +0000519 call->debug_id, key_serial(call->conn->key), sp->hdr.seq);
David Howells17926a72007-04-26 15:48:28 -0700520
521 if (!call->conn->cipher)
522 return 0;
523
David Howells8b815472009-09-14 01:17:30 +0000524 if (sp->hdr.securityIndex != RXRPC_SECURITY_RXKAD) {
David Howells17926a72007-04-26 15:48:28 -0700525 *_abort_code = RXKADINCONSISTENCY;
526 _leave(" = -EPROTO [not rxkad]");
527 return -EPROTO;
528 }
529
530 /* continue encrypting from where we left off */
531 memcpy(&iv, call->conn->csum_iv.x, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700532
533 /* validate the security checksum */
David Howells0d12f8a2016-03-04 15:53:46 +0000534 x = call->channel << (32 - RXRPC_CIDSHIFT);
535 x |= sp->hdr.seq & 0x3fffffff;
536 tmpbuf.x[0] = htonl(call->call_id);
537 tmpbuf.x[1] = htonl(x);
David Howells17926a72007-04-26 15:48:28 -0700538
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700539 sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf));
540 sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf));
Herbert Xu1afe5932016-01-24 21:19:01 +0800541
542 skcipher_request_set_tfm(req, call->conn->cipher);
543 skcipher_request_set_callback(req, 0, NULL, NULL);
544 skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x);
545
546 crypto_skcipher_encrypt(req);
547 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700548
Al Viro91e916c2008-03-29 03:08:38 +0000549 y = ntohl(tmpbuf.x[1]);
David Howells0d12f8a2016-03-04 15:53:46 +0000550 cksum = (y >> 16) & 0xffff;
551 if (cksum == 0)
552 cksum = 1; /* zero checksums are not permitted */
David Howells17926a72007-04-26 15:48:28 -0700553
David Howells17926a72007-04-26 15:48:28 -0700554 if (sp->hdr.cksum != cksum) {
555 *_abort_code = RXKADSEALEDINCON;
556 _leave(" = -EPROTO [csum failed]");
557 return -EPROTO;
558 }
559
560 switch (call->conn->security_level) {
561 case RXRPC_SECURITY_PLAIN:
562 ret = 0;
563 break;
564 case RXRPC_SECURITY_AUTH:
565 ret = rxkad_verify_packet_auth(call, skb, _abort_code);
566 break;
567 case RXRPC_SECURITY_ENCRYPT:
568 ret = rxkad_verify_packet_encrypt(call, skb, _abort_code);
569 break;
570 default:
571 ret = -ENOANO;
572 break;
573 }
574
575 _leave(" = %d", ret);
576 return ret;
577}
578
579/*
580 * issue a challenge
581 */
582static int rxkad_issue_challenge(struct rxrpc_connection *conn)
583{
584 struct rxkad_challenge challenge;
David Howells0d12f8a2016-03-04 15:53:46 +0000585 struct rxrpc_wire_header whdr;
David Howells17926a72007-04-26 15:48:28 -0700586 struct msghdr msg;
587 struct kvec iov[2];
588 size_t len;
David Howells0d12f8a2016-03-04 15:53:46 +0000589 u32 serial;
David Howells17926a72007-04-26 15:48:28 -0700590 int ret;
591
592 _enter("{%d,%x}", conn->debug_id, key_serial(conn->key));
593
594 ret = key_validate(conn->key);
595 if (ret < 0)
596 return ret;
597
598 get_random_bytes(&conn->security_nonce, sizeof(conn->security_nonce));
599
600 challenge.version = htonl(2);
601 challenge.nonce = htonl(conn->security_nonce);
602 challenge.min_level = htonl(0);
603 challenge.__padding = 0;
604
605 msg.msg_name = &conn->trans->peer->srx.transport.sin;
606 msg.msg_namelen = sizeof(conn->trans->peer->srx.transport.sin);
607 msg.msg_control = NULL;
608 msg.msg_controllen = 0;
609 msg.msg_flags = 0;
610
David Howells0d12f8a2016-03-04 15:53:46 +0000611 whdr.epoch = htonl(conn->epoch);
612 whdr.cid = htonl(conn->cid);
613 whdr.callNumber = 0;
614 whdr.seq = 0;
615 whdr.type = RXRPC_PACKET_TYPE_CHALLENGE;
616 whdr.flags = conn->out_clientflag;
617 whdr.userStatus = 0;
618 whdr.securityIndex = conn->security_ix;
619 whdr._rsvd = 0;
620 whdr.serviceId = htons(conn->service_id);
David Howells17926a72007-04-26 15:48:28 -0700621
David Howells0d12f8a2016-03-04 15:53:46 +0000622 iov[0].iov_base = &whdr;
623 iov[0].iov_len = sizeof(whdr);
David Howells17926a72007-04-26 15:48:28 -0700624 iov[1].iov_base = &challenge;
625 iov[1].iov_len = sizeof(challenge);
626
627 len = iov[0].iov_len + iov[1].iov_len;
628
David Howells0d12f8a2016-03-04 15:53:46 +0000629 serial = atomic_inc_return(&conn->serial);
630 whdr.serial = htonl(serial);
631 _proto("Tx CHALLENGE %%%u", serial);
David Howells17926a72007-04-26 15:48:28 -0700632
633 ret = kernel_sendmsg(conn->trans->local->socket, &msg, iov, 2, len);
634 if (ret < 0) {
635 _debug("sendmsg failed: %d", ret);
636 return -EAGAIN;
637 }
638
639 _leave(" = 0");
640 return 0;
641}
642
643/*
644 * send a Kerberos security response
645 */
646static int rxkad_send_response(struct rxrpc_connection *conn,
David Howells0d12f8a2016-03-04 15:53:46 +0000647 struct rxrpc_host_header *hdr,
David Howells17926a72007-04-26 15:48:28 -0700648 struct rxkad_response *resp,
649 const struct rxkad_key *s2)
650{
David Howells0d12f8a2016-03-04 15:53:46 +0000651 struct rxrpc_wire_header whdr;
David Howells17926a72007-04-26 15:48:28 -0700652 struct msghdr msg;
653 struct kvec iov[3];
654 size_t len;
David Howells0d12f8a2016-03-04 15:53:46 +0000655 u32 serial;
David Howells17926a72007-04-26 15:48:28 -0700656 int ret;
657
658 _enter("");
659
660 msg.msg_name = &conn->trans->peer->srx.transport.sin;
661 msg.msg_namelen = sizeof(conn->trans->peer->srx.transport.sin);
662 msg.msg_control = NULL;
663 msg.msg_controllen = 0;
664 msg.msg_flags = 0;
665
David Howells0d12f8a2016-03-04 15:53:46 +0000666 memset(&whdr, 0, sizeof(whdr));
667 whdr.epoch = htonl(hdr->epoch);
668 whdr.cid = htonl(hdr->cid);
669 whdr.type = RXRPC_PACKET_TYPE_RESPONSE;
670 whdr.flags = conn->out_clientflag;
671 whdr.securityIndex = hdr->securityIndex;
672 whdr.serviceId = htons(hdr->serviceId);
David Howells17926a72007-04-26 15:48:28 -0700673
David Howells0d12f8a2016-03-04 15:53:46 +0000674 iov[0].iov_base = &whdr;
675 iov[0].iov_len = sizeof(whdr);
David Howells17926a72007-04-26 15:48:28 -0700676 iov[1].iov_base = resp;
677 iov[1].iov_len = sizeof(*resp);
David Howells0d12f8a2016-03-04 15:53:46 +0000678 iov[2].iov_base = (void *)s2->ticket;
David Howells17926a72007-04-26 15:48:28 -0700679 iov[2].iov_len = s2->ticket_len;
680
681 len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
682
David Howells0d12f8a2016-03-04 15:53:46 +0000683 serial = atomic_inc_return(&conn->serial);
684 whdr.serial = htonl(serial);
685 _proto("Tx RESPONSE %%%u", serial);
David Howells17926a72007-04-26 15:48:28 -0700686
687 ret = kernel_sendmsg(conn->trans->local->socket, &msg, iov, 3, len);
688 if (ret < 0) {
689 _debug("sendmsg failed: %d", ret);
690 return -EAGAIN;
691 }
692
693 _leave(" = 0");
694 return 0;
695}
696
697/*
698 * calculate the response checksum
699 */
700static void rxkad_calc_response_checksum(struct rxkad_response *response)
701{
702 u32 csum = 1000003;
703 int loop;
704 u8 *p = (u8 *) response;
705
706 for (loop = sizeof(*response); loop > 0; loop--)
707 csum = csum * 0x10204081 + *p++;
708
709 response->encrypted.checksum = htonl(csum);
710}
711
712/*
713 * load a scatterlist with a potentially split-page buffer
714 */
715static void rxkad_sg_set_buf2(struct scatterlist sg[2],
716 void *buf, size_t buflen)
717{
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700718 int nsg = 1;
David Howells17926a72007-04-26 15:48:28 -0700719
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700720 sg_init_table(sg, 2);
David Howells17926a72007-04-26 15:48:28 -0700721
722 sg_set_buf(&sg[0], buf, buflen);
723 if (sg[0].offset + buflen > PAGE_SIZE) {
724 /* the buffer was split over two pages */
725 sg[0].length = PAGE_SIZE - sg[0].offset;
726 sg_set_buf(&sg[1], buf + sg[0].length, buflen - sg[0].length);
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700727 nsg++;
David Howells17926a72007-04-26 15:48:28 -0700728 }
729
Jens Axboec46f2332007-10-31 12:06:37 +0100730 sg_mark_end(&sg[nsg - 1]);
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700731
David Howells17926a72007-04-26 15:48:28 -0700732 ASSERTCMP(sg[0].length + sg[1].length, ==, buflen);
733}
734
735/*
736 * encrypt the response packet
737 */
738static void rxkad_encrypt_response(struct rxrpc_connection *conn,
739 struct rxkad_response *resp,
740 const struct rxkad_key *s2)
741{
Herbert Xu1afe5932016-01-24 21:19:01 +0800742 SKCIPHER_REQUEST_ON_STACK(req, conn->cipher);
David Howells17926a72007-04-26 15:48:28 -0700743 struct rxrpc_crypt iv;
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700744 struct scatterlist sg[2];
David Howells17926a72007-04-26 15:48:28 -0700745
746 /* continue encrypting from where we left off */
747 memcpy(&iv, s2->session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700748
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700749 rxkad_sg_set_buf2(sg, &resp->encrypted, sizeof(resp->encrypted));
Herbert Xu1afe5932016-01-24 21:19:01 +0800750
751 skcipher_request_set_tfm(req, conn->cipher);
752 skcipher_request_set_callback(req, 0, NULL, NULL);
753 skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x);
754
755 crypto_skcipher_encrypt(req);
756 skcipher_request_zero(req);
David Howells17926a72007-04-26 15:48:28 -0700757}
758
759/*
760 * respond to a challenge packet
761 */
762static int rxkad_respond_to_challenge(struct rxrpc_connection *conn,
763 struct sk_buff *skb,
764 u32 *_abort_code)
765{
David Howells33941282009-09-14 01:17:35 +0000766 const struct rxrpc_key_token *token;
David Howells17926a72007-04-26 15:48:28 -0700767 struct rxkad_challenge challenge;
768 struct rxkad_response resp
769 __attribute__((aligned(8))); /* must be aligned for crypto */
770 struct rxrpc_skb_priv *sp;
771 u32 version, nonce, min_level, abort_code;
772 int ret;
773
774 _enter("{%d,%x}", conn->debug_id, key_serial(conn->key));
775
776 if (!conn->key) {
777 _leave(" = -EPROTO [no key]");
778 return -EPROTO;
779 }
780
781 ret = key_validate(conn->key);
782 if (ret < 0) {
783 *_abort_code = RXKADEXPIRED;
784 return ret;
785 }
786
787 abort_code = RXKADPACKETSHORT;
788 sp = rxrpc_skb(skb);
789 if (skb_copy_bits(skb, 0, &challenge, sizeof(challenge)) < 0)
790 goto protocol_error;
791
792 version = ntohl(challenge.version);
793 nonce = ntohl(challenge.nonce);
794 min_level = ntohl(challenge.min_level);
795
796 _proto("Rx CHALLENGE %%%u { v=%u n=%u ml=%u }",
David Howells0d12f8a2016-03-04 15:53:46 +0000797 sp->hdr.serial, version, nonce, min_level);
David Howells17926a72007-04-26 15:48:28 -0700798
799 abort_code = RXKADINCONSISTENCY;
800 if (version != RXKAD_VERSION)
801 goto protocol_error;
802
803 abort_code = RXKADLEVELFAIL;
804 if (conn->security_level < min_level)
805 goto protocol_error;
806
David Howells146aa8b2015-10-21 14:04:48 +0100807 token = conn->key->payload.data[0];
David Howells17926a72007-04-26 15:48:28 -0700808
809 /* build the response packet */
810 memset(&resp, 0, sizeof(resp));
811
David Howells098a2092016-03-04 15:59:00 +0000812 resp.version = htonl(RXKAD_VERSION);
813 resp.encrypted.epoch = htonl(conn->epoch);
814 resp.encrypted.cid = htonl(conn->cid);
815 resp.encrypted.securityIndex = htonl(conn->security_ix);
816 resp.encrypted.inc_nonce = htonl(nonce + 1);
817 resp.encrypted.level = htonl(conn->security_level);
818 resp.kvno = htonl(token->kad->kvno);
819 resp.ticket_len = htonl(token->kad->ticket_len);
820
David Howells17926a72007-04-26 15:48:28 -0700821 resp.encrypted.call_id[0] =
David Howells0d12f8a2016-03-04 15:53:46 +0000822 htonl(conn->channels[0] ? conn->channels[0]->call_id : 0);
David Howells17926a72007-04-26 15:48:28 -0700823 resp.encrypted.call_id[1] =
David Howells0d12f8a2016-03-04 15:53:46 +0000824 htonl(conn->channels[1] ? conn->channels[1]->call_id : 0);
David Howells17926a72007-04-26 15:48:28 -0700825 resp.encrypted.call_id[2] =
David Howells0d12f8a2016-03-04 15:53:46 +0000826 htonl(conn->channels[2] ? conn->channels[2]->call_id : 0);
David Howells17926a72007-04-26 15:48:28 -0700827 resp.encrypted.call_id[3] =
David Howells0d12f8a2016-03-04 15:53:46 +0000828 htonl(conn->channels[3] ? conn->channels[3]->call_id : 0);
David Howells17926a72007-04-26 15:48:28 -0700829
830 /* calculate the response checksum and then do the encryption */
831 rxkad_calc_response_checksum(&resp);
David Howells33941282009-09-14 01:17:35 +0000832 rxkad_encrypt_response(conn, &resp, token->kad);
833 return rxkad_send_response(conn, &sp->hdr, &resp, token->kad);
David Howells17926a72007-04-26 15:48:28 -0700834
835protocol_error:
836 *_abort_code = abort_code;
837 _leave(" = -EPROTO [%d]", abort_code);
838 return -EPROTO;
839}
840
841/*
842 * decrypt the kerberos IV ticket in the response
843 */
844static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
845 void *ticket, size_t ticket_len,
846 struct rxrpc_crypt *_session_key,
847 time_t *_expiry,
848 u32 *_abort_code)
849{
Herbert Xu1afe5932016-01-24 21:19:01 +0800850 struct skcipher_request *req;
David Howells17926a72007-04-26 15:48:28 -0700851 struct rxrpc_crypt iv, key;
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700852 struct scatterlist sg[1];
David Howells17926a72007-04-26 15:48:28 -0700853 struct in_addr addr;
Eric Dumazet95c96172012-04-15 05:58:06 +0000854 unsigned int life;
David Howells17926a72007-04-26 15:48:28 -0700855 time_t issue, now;
856 bool little_endian;
857 int ret;
858 u8 *p, *q, *name, *end;
859
860 _enter("{%d},{%x}", conn->debug_id, key_serial(conn->server_key));
861
862 *_expiry = 0;
863
864 ret = key_validate(conn->server_key);
865 if (ret < 0) {
866 switch (ret) {
867 case -EKEYEXPIRED:
868 *_abort_code = RXKADEXPIRED;
869 goto error;
870 default:
871 *_abort_code = RXKADNOAUTH;
872 goto error;
873 }
874 }
875
David Howells146aa8b2015-10-21 14:04:48 +0100876 ASSERT(conn->server_key->payload.data[0] != NULL);
David Howells17926a72007-04-26 15:48:28 -0700877 ASSERTCMP((unsigned long) ticket & 7UL, ==, 0);
878
David Howells146aa8b2015-10-21 14:04:48 +0100879 memcpy(&iv, &conn->server_key->payload.data[2], sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -0700880
Herbert Xu1afe5932016-01-24 21:19:01 +0800881 req = skcipher_request_alloc(conn->server_key->payload.data[0],
882 GFP_NOFS);
883 if (!req) {
884 *_abort_code = RXKADNOAUTH;
885 ret = -ENOMEM;
886 goto error;
887 }
David Howells17926a72007-04-26 15:48:28 -0700888
Herbert Xu68e3f5d2007-10-27 00:52:07 -0700889 sg_init_one(&sg[0], ticket, ticket_len);
Herbert Xu1afe5932016-01-24 21:19:01 +0800890
891 skcipher_request_set_callback(req, 0, NULL, NULL);
892 skcipher_request_set_crypt(req, sg, sg, ticket_len, iv.x);
893
894 crypto_skcipher_decrypt(req);
895 skcipher_request_free(req);
David Howells17926a72007-04-26 15:48:28 -0700896
897 p = ticket;
898 end = p + ticket_len;
899
900#define Z(size) \
901 ({ \
902 u8 *__str = p; \
903 q = memchr(p, 0, end - p); \
904 if (!q || q - p > (size)) \
905 goto bad_ticket; \
906 for (; p < q; p++) \
907 if (!isprint(*p)) \
908 goto bad_ticket; \
909 p++; \
910 __str; \
911 })
912
913 /* extract the ticket flags */
914 _debug("KIV FLAGS: %x", *p);
915 little_endian = *p & 1;
916 p++;
917
918 /* extract the authentication name */
919 name = Z(ANAME_SZ);
920 _debug("KIV ANAME: %s", name);
921
922 /* extract the principal's instance */
923 name = Z(INST_SZ);
924 _debug("KIV INST : %s", name);
925
926 /* extract the principal's authentication domain */
927 name = Z(REALM_SZ);
928 _debug("KIV REALM: %s", name);
929
930 if (end - p < 4 + 8 + 4 + 2)
931 goto bad_ticket;
932
933 /* get the IPv4 address of the entity that requested the ticket */
934 memcpy(&addr, p, sizeof(addr));
935 p += 4;
Harvey Harrison21454aa2008-10-31 00:54:56 -0700936 _debug("KIV ADDR : %pI4", &addr);
David Howells17926a72007-04-26 15:48:28 -0700937
938 /* get the session key from the ticket */
939 memcpy(&key, p, sizeof(key));
940 p += 8;
941 _debug("KIV KEY : %08x %08x", ntohl(key.n[0]), ntohl(key.n[1]));
942 memcpy(_session_key, &key, sizeof(key));
943
944 /* get the ticket's lifetime */
945 life = *p++ * 5 * 60;
946 _debug("KIV LIFE : %u", life);
947
948 /* get the issue time of the ticket */
949 if (little_endian) {
950 __le32 stamp;
951 memcpy(&stamp, p, 4);
952 issue = le32_to_cpu(stamp);
953 } else {
954 __be32 stamp;
955 memcpy(&stamp, p, 4);
956 issue = be32_to_cpu(stamp);
957 }
958 p += 4;
john stultz2c6b47d2007-07-24 17:47:43 -0700959 now = get_seconds();
David Howells17926a72007-04-26 15:48:28 -0700960 _debug("KIV ISSUE: %lx [%lx]", issue, now);
961
962 /* check the ticket is in date */
963 if (issue > now) {
964 *_abort_code = RXKADNOAUTH;
965 ret = -EKEYREJECTED;
966 goto error;
967 }
968
969 if (issue < now - life) {
970 *_abort_code = RXKADEXPIRED;
971 ret = -EKEYEXPIRED;
972 goto error;
973 }
974
975 *_expiry = issue + life;
976
977 /* get the service name */
978 name = Z(SNAME_SZ);
979 _debug("KIV SNAME: %s", name);
980
981 /* get the service instance name */
982 name = Z(INST_SZ);
983 _debug("KIV SINST: %s", name);
984
985 ret = 0;
986error:
987 _leave(" = %d", ret);
988 return ret;
989
990bad_ticket:
991 *_abort_code = RXKADBADTICKET;
992 ret = -EBADMSG;
993 goto error;
994}
995
996/*
997 * decrypt the response packet
998 */
999static void rxkad_decrypt_response(struct rxrpc_connection *conn,
1000 struct rxkad_response *resp,
1001 const struct rxrpc_crypt *session_key)
1002{
Herbert Xu1afe5932016-01-24 21:19:01 +08001003 SKCIPHER_REQUEST_ON_STACK(req, rxkad_ci);
Herbert Xu68e3f5d2007-10-27 00:52:07 -07001004 struct scatterlist sg[2];
David Howells17926a72007-04-26 15:48:28 -07001005 struct rxrpc_crypt iv;
1006
1007 _enter(",,%08x%08x",
1008 ntohl(session_key->n[0]), ntohl(session_key->n[1]));
1009
1010 ASSERT(rxkad_ci != NULL);
1011
1012 mutex_lock(&rxkad_ci_mutex);
Herbert Xu1afe5932016-01-24 21:19:01 +08001013 if (crypto_skcipher_setkey(rxkad_ci, session_key->x,
1014 sizeof(*session_key)) < 0)
David Howells17926a72007-04-26 15:48:28 -07001015 BUG();
1016
1017 memcpy(&iv, session_key, sizeof(iv));
David Howells17926a72007-04-26 15:48:28 -07001018
Herbert Xu68e3f5d2007-10-27 00:52:07 -07001019 rxkad_sg_set_buf2(sg, &resp->encrypted, sizeof(resp->encrypted));
Herbert Xu1afe5932016-01-24 21:19:01 +08001020
1021 skcipher_request_set_tfm(req, rxkad_ci);
1022 skcipher_request_set_callback(req, 0, NULL, NULL);
1023 skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x);
1024
1025 crypto_skcipher_decrypt(req);
1026 skcipher_request_zero(req);
1027
David Howells17926a72007-04-26 15:48:28 -07001028 mutex_unlock(&rxkad_ci_mutex);
1029
1030 _leave("");
1031}
1032
1033/*
1034 * verify a response
1035 */
1036static int rxkad_verify_response(struct rxrpc_connection *conn,
1037 struct sk_buff *skb,
1038 u32 *_abort_code)
1039{
1040 struct rxkad_response response
1041 __attribute__((aligned(8))); /* must be aligned for crypto */
1042 struct rxrpc_skb_priv *sp;
1043 struct rxrpc_crypt session_key;
1044 time_t expiry;
1045 void *ticket;
Al Viro91e916c2008-03-29 03:08:38 +00001046 u32 abort_code, version, kvno, ticket_len, level;
1047 __be32 csum;
David Howells17926a72007-04-26 15:48:28 -07001048 int ret;
1049
1050 _enter("{%d,%x}", conn->debug_id, key_serial(conn->server_key));
1051
1052 abort_code = RXKADPACKETSHORT;
1053 if (skb_copy_bits(skb, 0, &response, sizeof(response)) < 0)
1054 goto protocol_error;
1055 if (!pskb_pull(skb, sizeof(response)))
1056 BUG();
1057
1058 version = ntohl(response.version);
1059 ticket_len = ntohl(response.ticket_len);
1060 kvno = ntohl(response.kvno);
1061 sp = rxrpc_skb(skb);
1062 _proto("Rx RESPONSE %%%u { v=%u kv=%u tl=%u }",
David Howells0d12f8a2016-03-04 15:53:46 +00001063 sp->hdr.serial, version, kvno, ticket_len);
David Howells17926a72007-04-26 15:48:28 -07001064
1065 abort_code = RXKADINCONSISTENCY;
1066 if (version != RXKAD_VERSION)
David Howells4aa9cb32007-12-07 04:31:47 -08001067 goto protocol_error;
David Howells17926a72007-04-26 15:48:28 -07001068
1069 abort_code = RXKADTICKETLEN;
1070 if (ticket_len < 4 || ticket_len > MAXKRB5TICKETLEN)
1071 goto protocol_error;
1072
1073 abort_code = RXKADUNKNOWNKEY;
1074 if (kvno >= RXKAD_TKT_TYPE_KERBEROS_V5)
1075 goto protocol_error;
1076
1077 /* extract the kerberos ticket and decrypt and decode it */
1078 ticket = kmalloc(ticket_len, GFP_NOFS);
1079 if (!ticket)
1080 return -ENOMEM;
1081
1082 abort_code = RXKADPACKETSHORT;
1083 if (skb_copy_bits(skb, 0, ticket, ticket_len) < 0)
1084 goto protocol_error_free;
1085
1086 ret = rxkad_decrypt_ticket(conn, ticket, ticket_len, &session_key,
1087 &expiry, &abort_code);
1088 if (ret < 0) {
1089 *_abort_code = abort_code;
1090 kfree(ticket);
1091 return ret;
1092 }
1093
1094 /* use the session key from inside the ticket to decrypt the
1095 * response */
1096 rxkad_decrypt_response(conn, &response, &session_key);
1097
1098 abort_code = RXKADSEALEDINCON;
David Howells0d12f8a2016-03-04 15:53:46 +00001099 if (ntohl(response.encrypted.epoch) != conn->epoch)
David Howells17926a72007-04-26 15:48:28 -07001100 goto protocol_error_free;
David Howells0d12f8a2016-03-04 15:53:46 +00001101 if (ntohl(response.encrypted.cid) != conn->cid)
David Howells17926a72007-04-26 15:48:28 -07001102 goto protocol_error_free;
1103 if (ntohl(response.encrypted.securityIndex) != conn->security_ix)
1104 goto protocol_error_free;
1105 csum = response.encrypted.checksum;
1106 response.encrypted.checksum = 0;
1107 rxkad_calc_response_checksum(&response);
1108 if (response.encrypted.checksum != csum)
1109 goto protocol_error_free;
1110
1111 if (ntohl(response.encrypted.call_id[0]) > INT_MAX ||
1112 ntohl(response.encrypted.call_id[1]) > INT_MAX ||
1113 ntohl(response.encrypted.call_id[2]) > INT_MAX ||
1114 ntohl(response.encrypted.call_id[3]) > INT_MAX)
1115 goto protocol_error_free;
1116
1117 abort_code = RXKADOUTOFSEQUENCE;
David Howells0d12f8a2016-03-04 15:53:46 +00001118 if (ntohl(response.encrypted.inc_nonce) != conn->security_nonce + 1)
David Howells17926a72007-04-26 15:48:28 -07001119 goto protocol_error_free;
1120
1121 abort_code = RXKADLEVELFAIL;
1122 level = ntohl(response.encrypted.level);
1123 if (level > RXRPC_SECURITY_ENCRYPT)
1124 goto protocol_error_free;
1125 conn->security_level = level;
1126
1127 /* create a key to hold the security data and expiration time - after
1128 * this the connection security can be handled in exactly the same way
1129 * as for a client connection */
1130 ret = rxrpc_get_server_data_key(conn, &session_key, expiry, kvno);
1131 if (ret < 0) {
1132 kfree(ticket);
1133 return ret;
1134 }
1135
1136 kfree(ticket);
1137 _leave(" = 0");
1138 return 0;
1139
1140protocol_error_free:
1141 kfree(ticket);
1142protocol_error:
1143 *_abort_code = abort_code;
1144 _leave(" = -EPROTO [%d]", abort_code);
1145 return -EPROTO;
1146}
1147
1148/*
1149 * clear the connection security
1150 */
1151static void rxkad_clear(struct rxrpc_connection *conn)
1152{
1153 _enter("");
1154
1155 if (conn->cipher)
Herbert Xu1afe5932016-01-24 21:19:01 +08001156 crypto_free_skcipher(conn->cipher);
David Howells17926a72007-04-26 15:48:28 -07001157}
1158
1159/*
David Howells648af7f2016-04-07 17:23:51 +01001160 * Initialise the rxkad security service.
1161 */
1162static int rxkad_init(void)
1163{
1164 /* pin the cipher we need so that the crypto layer doesn't invoke
1165 * keventd to go get it */
1166 rxkad_ci = crypto_alloc_skcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC);
1167 if (IS_ERR(rxkad_ci))
1168 return PTR_ERR(rxkad_ci);
1169 return 0;
1170}
1171
1172/*
1173 * Clean up the rxkad security service.
1174 */
1175static void rxkad_exit(void)
1176{
1177 if (rxkad_ci)
1178 crypto_free_skcipher(rxkad_ci);
1179}
1180
1181/*
David Howells17926a72007-04-26 15:48:28 -07001182 * RxRPC Kerberos-based security
1183 */
David Howells648af7f2016-04-07 17:23:51 +01001184const struct rxrpc_security rxkad = {
David Howells17926a72007-04-26 15:48:28 -07001185 .name = "rxkad",
David Howells8b815472009-09-14 01:17:30 +00001186 .security_index = RXRPC_SECURITY_RXKAD,
David Howells648af7f2016-04-07 17:23:51 +01001187 .init = rxkad_init,
1188 .exit = rxkad_exit,
David Howells17926a72007-04-26 15:48:28 -07001189 .init_connection_security = rxkad_init_connection_security,
1190 .prime_packet_security = rxkad_prime_packet_security,
1191 .secure_packet = rxkad_secure_packet,
1192 .verify_packet = rxkad_verify_packet,
1193 .issue_challenge = rxkad_issue_challenge,
1194 .respond_to_challenge = rxkad_respond_to_challenge,
1195 .verify_response = rxkad_verify_response,
1196 .clear = rxkad_clear,
1197};