Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/sunrpc/auth_gss/gss_krb5_mech.c
15112 views
1
/*
2
* linux/net/sunrpc/gss_krb5_mech.c
3
*
4
* Copyright (c) 2001-2008 The Regents of the University of Michigan.
5
* All rights reserved.
6
*
7
* Andy Adamson <[email protected]>
8
* J. Bruce Fields <[email protected]>
9
*
10
* Redistribution and use in source and binary forms, with or without
11
* modification, are permitted provided that the following conditions
12
* are met:
13
*
14
* 1. Redistributions of source code must retain the above copyright
15
* notice, this list of conditions and the following disclaimer.
16
* 2. Redistributions in binary form must reproduce the above copyright
17
* notice, this list of conditions and the following disclaimer in the
18
* documentation and/or other materials provided with the distribution.
19
* 3. Neither the name of the University nor the names of its
20
* contributors may be used to endorse or promote products derived
21
* from this software without specific prior written permission.
22
*
23
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
24
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
*
35
*/
36
37
#include <linux/err.h>
38
#include <linux/module.h>
39
#include <linux/init.h>
40
#include <linux/types.h>
41
#include <linux/slab.h>
42
#include <linux/sunrpc/auth.h>
43
#include <linux/sunrpc/gss_krb5.h>
44
#include <linux/sunrpc/xdr.h>
45
#include <linux/crypto.h>
46
#include <linux/sunrpc/gss_krb5_enctypes.h>
47
48
#ifdef RPC_DEBUG
49
# define RPCDBG_FACILITY RPCDBG_AUTH
50
#endif
51
52
static struct gss_api_mech gss_kerberos_mech; /* forward declaration */
53
54
static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
55
/*
56
* DES (All DES enctypes are mapped to the same gss functionality)
57
*/
58
{
59
.etype = ENCTYPE_DES_CBC_RAW,
60
.ctype = CKSUMTYPE_RSA_MD5,
61
.name = "des-cbc-crc",
62
.encrypt_name = "cbc(des)",
63
.cksum_name = "md5",
64
.encrypt = krb5_encrypt,
65
.decrypt = krb5_decrypt,
66
.mk_key = NULL,
67
.signalg = SGN_ALG_DES_MAC_MD5,
68
.sealalg = SEAL_ALG_DES,
69
.keybytes = 7,
70
.keylength = 8,
71
.blocksize = 8,
72
.conflen = 8,
73
.cksumlength = 8,
74
.keyed_cksum = 0,
75
},
76
/*
77
* RC4-HMAC
78
*/
79
{
80
.etype = ENCTYPE_ARCFOUR_HMAC,
81
.ctype = CKSUMTYPE_HMAC_MD5_ARCFOUR,
82
.name = "rc4-hmac",
83
.encrypt_name = "ecb(arc4)",
84
.cksum_name = "hmac(md5)",
85
.encrypt = krb5_encrypt,
86
.decrypt = krb5_decrypt,
87
.mk_key = NULL,
88
.signalg = SGN_ALG_HMAC_MD5,
89
.sealalg = SEAL_ALG_MICROSOFT_RC4,
90
.keybytes = 16,
91
.keylength = 16,
92
.blocksize = 1,
93
.conflen = 8,
94
.cksumlength = 8,
95
.keyed_cksum = 1,
96
},
97
/*
98
* 3DES
99
*/
100
{
101
.etype = ENCTYPE_DES3_CBC_RAW,
102
.ctype = CKSUMTYPE_HMAC_SHA1_DES3,
103
.name = "des3-hmac-sha1",
104
.encrypt_name = "cbc(des3_ede)",
105
.cksum_name = "hmac(sha1)",
106
.encrypt = krb5_encrypt,
107
.decrypt = krb5_decrypt,
108
.mk_key = gss_krb5_des3_make_key,
109
.signalg = SGN_ALG_HMAC_SHA1_DES3_KD,
110
.sealalg = SEAL_ALG_DES3KD,
111
.keybytes = 21,
112
.keylength = 24,
113
.blocksize = 8,
114
.conflen = 8,
115
.cksumlength = 20,
116
.keyed_cksum = 1,
117
},
118
/*
119
* AES128
120
*/
121
{
122
.etype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
123
.ctype = CKSUMTYPE_HMAC_SHA1_96_AES128,
124
.name = "aes128-cts",
125
.encrypt_name = "cts(cbc(aes))",
126
.cksum_name = "hmac(sha1)",
127
.encrypt = krb5_encrypt,
128
.decrypt = krb5_decrypt,
129
.mk_key = gss_krb5_aes_make_key,
130
.encrypt_v2 = gss_krb5_aes_encrypt,
131
.decrypt_v2 = gss_krb5_aes_decrypt,
132
.signalg = -1,
133
.sealalg = -1,
134
.keybytes = 16,
135
.keylength = 16,
136
.blocksize = 16,
137
.conflen = 16,
138
.cksumlength = 12,
139
.keyed_cksum = 1,
140
},
141
/*
142
* AES256
143
*/
144
{
145
.etype = ENCTYPE_AES256_CTS_HMAC_SHA1_96,
146
.ctype = CKSUMTYPE_HMAC_SHA1_96_AES256,
147
.name = "aes256-cts",
148
.encrypt_name = "cts(cbc(aes))",
149
.cksum_name = "hmac(sha1)",
150
.encrypt = krb5_encrypt,
151
.decrypt = krb5_decrypt,
152
.mk_key = gss_krb5_aes_make_key,
153
.encrypt_v2 = gss_krb5_aes_encrypt,
154
.decrypt_v2 = gss_krb5_aes_decrypt,
155
.signalg = -1,
156
.sealalg = -1,
157
.keybytes = 32,
158
.keylength = 32,
159
.blocksize = 16,
160
.conflen = 16,
161
.cksumlength = 12,
162
.keyed_cksum = 1,
163
},
164
};
165
166
static const int num_supported_enctypes =
167
ARRAY_SIZE(supported_gss_krb5_enctypes);
168
169
static int
170
supported_gss_krb5_enctype(int etype)
171
{
172
int i;
173
for (i = 0; i < num_supported_enctypes; i++)
174
if (supported_gss_krb5_enctypes[i].etype == etype)
175
return 1;
176
return 0;
177
}
178
179
static const struct gss_krb5_enctype *
180
get_gss_krb5_enctype(int etype)
181
{
182
int i;
183
for (i = 0; i < num_supported_enctypes; i++)
184
if (supported_gss_krb5_enctypes[i].etype == etype)
185
return &supported_gss_krb5_enctypes[i];
186
return NULL;
187
}
188
189
static const void *
190
simple_get_bytes(const void *p, const void *end, void *res, int len)
191
{
192
const void *q = (const void *)((const char *)p + len);
193
if (unlikely(q > end || q < p))
194
return ERR_PTR(-EFAULT);
195
memcpy(res, p, len);
196
return q;
197
}
198
199
static const void *
200
simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
201
{
202
const void *q;
203
unsigned int len;
204
205
p = simple_get_bytes(p, end, &len, sizeof(len));
206
if (IS_ERR(p))
207
return p;
208
q = (const void *)((const char *)p + len);
209
if (unlikely(q > end || q < p))
210
return ERR_PTR(-EFAULT);
211
res->data = kmemdup(p, len, GFP_NOFS);
212
if (unlikely(res->data == NULL))
213
return ERR_PTR(-ENOMEM);
214
res->len = len;
215
return q;
216
}
217
218
static inline const void *
219
get_key(const void *p, const void *end,
220
struct krb5_ctx *ctx, struct crypto_blkcipher **res)
221
{
222
struct xdr_netobj key;
223
int alg;
224
225
p = simple_get_bytes(p, end, &alg, sizeof(alg));
226
if (IS_ERR(p))
227
goto out_err;
228
229
switch (alg) {
230
case ENCTYPE_DES_CBC_CRC:
231
case ENCTYPE_DES_CBC_MD4:
232
case ENCTYPE_DES_CBC_MD5:
233
/* Map all these key types to ENCTYPE_DES_CBC_RAW */
234
alg = ENCTYPE_DES_CBC_RAW;
235
break;
236
}
237
238
if (!supported_gss_krb5_enctype(alg)) {
239
printk(KERN_WARNING "gss_kerberos_mech: unsupported "
240
"encryption key algorithm %d\n", alg);
241
p = ERR_PTR(-EINVAL);
242
goto out_err;
243
}
244
p = simple_get_netobj(p, end, &key);
245
if (IS_ERR(p))
246
goto out_err;
247
248
*res = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,
249
CRYPTO_ALG_ASYNC);
250
if (IS_ERR(*res)) {
251
printk(KERN_WARNING "gss_kerberos_mech: unable to initialize "
252
"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
253
*res = NULL;
254
goto out_err_free_key;
255
}
256
if (crypto_blkcipher_setkey(*res, key.data, key.len)) {
257
printk(KERN_WARNING "gss_kerberos_mech: error setting key for "
258
"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
259
goto out_err_free_tfm;
260
}
261
262
kfree(key.data);
263
return p;
264
265
out_err_free_tfm:
266
crypto_free_blkcipher(*res);
267
out_err_free_key:
268
kfree(key.data);
269
p = ERR_PTR(-EINVAL);
270
out_err:
271
return p;
272
}
273
274
static int
275
gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
276
{
277
int tmp;
278
279
p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
280
if (IS_ERR(p))
281
goto out_err;
282
283
/* Old format supports only DES! Any other enctype uses new format */
284
ctx->enctype = ENCTYPE_DES_CBC_RAW;
285
286
ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
287
if (ctx->gk5e == NULL) {
288
p = ERR_PTR(-EINVAL);
289
goto out_err;
290
}
291
292
/* The downcall format was designed before we completely understood
293
* the uses of the context fields; so it includes some stuff we
294
* just give some minimal sanity-checking, and some we ignore
295
* completely (like the next twenty bytes): */
296
if (unlikely(p + 20 > end || p + 20 < p)) {
297
p = ERR_PTR(-EFAULT);
298
goto out_err;
299
}
300
p += 20;
301
p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
302
if (IS_ERR(p))
303
goto out_err;
304
if (tmp != SGN_ALG_DES_MAC_MD5) {
305
p = ERR_PTR(-ENOSYS);
306
goto out_err;
307
}
308
p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
309
if (IS_ERR(p))
310
goto out_err;
311
if (tmp != SEAL_ALG_DES) {
312
p = ERR_PTR(-ENOSYS);
313
goto out_err;
314
}
315
p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
316
if (IS_ERR(p))
317
goto out_err;
318
p = simple_get_bytes(p, end, &ctx->seq_send, sizeof(ctx->seq_send));
319
if (IS_ERR(p))
320
goto out_err;
321
p = simple_get_netobj(p, end, &ctx->mech_used);
322
if (IS_ERR(p))
323
goto out_err;
324
p = get_key(p, end, ctx, &ctx->enc);
325
if (IS_ERR(p))
326
goto out_err_free_mech;
327
p = get_key(p, end, ctx, &ctx->seq);
328
if (IS_ERR(p))
329
goto out_err_free_key1;
330
if (p != end) {
331
p = ERR_PTR(-EFAULT);
332
goto out_err_free_key2;
333
}
334
335
return 0;
336
337
out_err_free_key2:
338
crypto_free_blkcipher(ctx->seq);
339
out_err_free_key1:
340
crypto_free_blkcipher(ctx->enc);
341
out_err_free_mech:
342
kfree(ctx->mech_used.data);
343
out_err:
344
return PTR_ERR(p);
345
}
346
347
struct crypto_blkcipher *
348
context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key)
349
{
350
struct crypto_blkcipher *cp;
351
352
cp = crypto_alloc_blkcipher(cname, 0, CRYPTO_ALG_ASYNC);
353
if (IS_ERR(cp)) {
354
dprintk("gss_kerberos_mech: unable to initialize "
355
"crypto algorithm %s\n", cname);
356
return NULL;
357
}
358
if (crypto_blkcipher_setkey(cp, key, ctx->gk5e->keylength)) {
359
dprintk("gss_kerberos_mech: error setting key for "
360
"crypto algorithm %s\n", cname);
361
crypto_free_blkcipher(cp);
362
return NULL;
363
}
364
return cp;
365
}
366
367
static inline void
368
set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed)
369
{
370
cdata[0] = (usage>>24)&0xff;
371
cdata[1] = (usage>>16)&0xff;
372
cdata[2] = (usage>>8)&0xff;
373
cdata[3] = usage&0xff;
374
cdata[4] = seed;
375
}
376
377
static int
378
context_derive_keys_des3(struct krb5_ctx *ctx, gfp_t gfp_mask)
379
{
380
struct xdr_netobj c, keyin, keyout;
381
u8 cdata[GSS_KRB5_K5CLENGTH];
382
u32 err;
383
384
c.len = GSS_KRB5_K5CLENGTH;
385
c.data = cdata;
386
387
keyin.data = ctx->Ksess;
388
keyin.len = ctx->gk5e->keylength;
389
keyout.len = ctx->gk5e->keylength;
390
391
/* seq uses the raw key */
392
ctx->seq = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
393
ctx->Ksess);
394
if (ctx->seq == NULL)
395
goto out_err;
396
397
ctx->enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
398
ctx->Ksess);
399
if (ctx->enc == NULL)
400
goto out_free_seq;
401
402
/* derive cksum */
403
set_cdata(cdata, KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM);
404
keyout.data = ctx->cksum;
405
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
406
if (err) {
407
dprintk("%s: Error %d deriving cksum key\n",
408
__func__, err);
409
goto out_free_enc;
410
}
411
412
return 0;
413
414
out_free_enc:
415
crypto_free_blkcipher(ctx->enc);
416
out_free_seq:
417
crypto_free_blkcipher(ctx->seq);
418
out_err:
419
return -EINVAL;
420
}
421
422
/*
423
* Note that RC4 depends on deriving keys using the sequence
424
* number or the checksum of a token. Therefore, the final keys
425
* cannot be calculated until the token is being constructed!
426
*/
427
static int
428
context_derive_keys_rc4(struct krb5_ctx *ctx)
429
{
430
struct crypto_hash *hmac;
431
char sigkeyconstant[] = "signaturekey";
432
int slen = strlen(sigkeyconstant) + 1; /* include null terminator */
433
struct hash_desc desc;
434
struct scatterlist sg[1];
435
int err;
436
437
dprintk("RPC: %s: entered\n", __func__);
438
/*
439
* derive cksum (aka Ksign) key
440
*/
441
hmac = crypto_alloc_hash(ctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
442
if (IS_ERR(hmac)) {
443
dprintk("%s: error %ld allocating hash '%s'\n",
444
__func__, PTR_ERR(hmac), ctx->gk5e->cksum_name);
445
err = PTR_ERR(hmac);
446
goto out_err;
447
}
448
449
err = crypto_hash_setkey(hmac, ctx->Ksess, ctx->gk5e->keylength);
450
if (err)
451
goto out_err_free_hmac;
452
453
sg_init_table(sg, 1);
454
sg_set_buf(sg, sigkeyconstant, slen);
455
456
desc.tfm = hmac;
457
desc.flags = 0;
458
459
err = crypto_hash_init(&desc);
460
if (err)
461
goto out_err_free_hmac;
462
463
err = crypto_hash_digest(&desc, sg, slen, ctx->cksum);
464
if (err)
465
goto out_err_free_hmac;
466
/*
467
* allocate hash, and blkciphers for data and seqnum encryption
468
*/
469
ctx->enc = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,
470
CRYPTO_ALG_ASYNC);
471
if (IS_ERR(ctx->enc)) {
472
err = PTR_ERR(ctx->enc);
473
goto out_err_free_hmac;
474
}
475
476
ctx->seq = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,
477
CRYPTO_ALG_ASYNC);
478
if (IS_ERR(ctx->seq)) {
479
crypto_free_blkcipher(ctx->enc);
480
err = PTR_ERR(ctx->seq);
481
goto out_err_free_hmac;
482
}
483
484
dprintk("RPC: %s: returning success\n", __func__);
485
486
err = 0;
487
488
out_err_free_hmac:
489
crypto_free_hash(hmac);
490
out_err:
491
dprintk("RPC: %s: returning %d\n", __func__, err);
492
return err;
493
}
494
495
static int
496
context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask)
497
{
498
struct xdr_netobj c, keyin, keyout;
499
u8 cdata[GSS_KRB5_K5CLENGTH];
500
u32 err;
501
502
c.len = GSS_KRB5_K5CLENGTH;
503
c.data = cdata;
504
505
keyin.data = ctx->Ksess;
506
keyin.len = ctx->gk5e->keylength;
507
keyout.len = ctx->gk5e->keylength;
508
509
/* initiator seal encryption */
510
set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
511
keyout.data = ctx->initiator_seal;
512
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
513
if (err) {
514
dprintk("%s: Error %d deriving initiator_seal key\n",
515
__func__, err);
516
goto out_err;
517
}
518
ctx->initiator_enc = context_v2_alloc_cipher(ctx,
519
ctx->gk5e->encrypt_name,
520
ctx->initiator_seal);
521
if (ctx->initiator_enc == NULL)
522
goto out_err;
523
524
/* acceptor seal encryption */
525
set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
526
keyout.data = ctx->acceptor_seal;
527
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
528
if (err) {
529
dprintk("%s: Error %d deriving acceptor_seal key\n",
530
__func__, err);
531
goto out_free_initiator_enc;
532
}
533
ctx->acceptor_enc = context_v2_alloc_cipher(ctx,
534
ctx->gk5e->encrypt_name,
535
ctx->acceptor_seal);
536
if (ctx->acceptor_enc == NULL)
537
goto out_free_initiator_enc;
538
539
/* initiator sign checksum */
540
set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
541
keyout.data = ctx->initiator_sign;
542
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
543
if (err) {
544
dprintk("%s: Error %d deriving initiator_sign key\n",
545
__func__, err);
546
goto out_free_acceptor_enc;
547
}
548
549
/* acceptor sign checksum */
550
set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
551
keyout.data = ctx->acceptor_sign;
552
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
553
if (err) {
554
dprintk("%s: Error %d deriving acceptor_sign key\n",
555
__func__, err);
556
goto out_free_acceptor_enc;
557
}
558
559
/* initiator seal integrity */
560
set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
561
keyout.data = ctx->initiator_integ;
562
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
563
if (err) {
564
dprintk("%s: Error %d deriving initiator_integ key\n",
565
__func__, err);
566
goto out_free_acceptor_enc;
567
}
568
569
/* acceptor seal integrity */
570
set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
571
keyout.data = ctx->acceptor_integ;
572
err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
573
if (err) {
574
dprintk("%s: Error %d deriving acceptor_integ key\n",
575
__func__, err);
576
goto out_free_acceptor_enc;
577
}
578
579
switch (ctx->enctype) {
580
case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
581
case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
582
ctx->initiator_enc_aux =
583
context_v2_alloc_cipher(ctx, "cbc(aes)",
584
ctx->initiator_seal);
585
if (ctx->initiator_enc_aux == NULL)
586
goto out_free_acceptor_enc;
587
ctx->acceptor_enc_aux =
588
context_v2_alloc_cipher(ctx, "cbc(aes)",
589
ctx->acceptor_seal);
590
if (ctx->acceptor_enc_aux == NULL) {
591
crypto_free_blkcipher(ctx->initiator_enc_aux);
592
goto out_free_acceptor_enc;
593
}
594
}
595
596
return 0;
597
598
out_free_acceptor_enc:
599
crypto_free_blkcipher(ctx->acceptor_enc);
600
out_free_initiator_enc:
601
crypto_free_blkcipher(ctx->initiator_enc);
602
out_err:
603
return -EINVAL;
604
}
605
606
static int
607
gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
608
gfp_t gfp_mask)
609
{
610
int keylen;
611
612
p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
613
if (IS_ERR(p))
614
goto out_err;
615
ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;
616
617
p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
618
if (IS_ERR(p))
619
goto out_err;
620
p = simple_get_bytes(p, end, &ctx->seq_send64, sizeof(ctx->seq_send64));
621
if (IS_ERR(p))
622
goto out_err;
623
/* set seq_send for use by "older" enctypes */
624
ctx->seq_send = ctx->seq_send64;
625
if (ctx->seq_send64 != ctx->seq_send) {
626
dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__,
627
(long unsigned)ctx->seq_send64, ctx->seq_send);
628
p = ERR_PTR(-EINVAL);
629
goto out_err;
630
}
631
p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
632
if (IS_ERR(p))
633
goto out_err;
634
/* Map ENCTYPE_DES3_CBC_SHA1 to ENCTYPE_DES3_CBC_RAW */
635
if (ctx->enctype == ENCTYPE_DES3_CBC_SHA1)
636
ctx->enctype = ENCTYPE_DES3_CBC_RAW;
637
ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
638
if (ctx->gk5e == NULL) {
639
dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
640
ctx->enctype);
641
p = ERR_PTR(-EINVAL);
642
goto out_err;
643
}
644
keylen = ctx->gk5e->keylength;
645
646
p = simple_get_bytes(p, end, ctx->Ksess, keylen);
647
if (IS_ERR(p))
648
goto out_err;
649
650
if (p != end) {
651
p = ERR_PTR(-EINVAL);
652
goto out_err;
653
}
654
655
ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,
656
gss_kerberos_mech.gm_oid.len, gfp_mask);
657
if (unlikely(ctx->mech_used.data == NULL)) {
658
p = ERR_PTR(-ENOMEM);
659
goto out_err;
660
}
661
ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;
662
663
switch (ctx->enctype) {
664
case ENCTYPE_DES3_CBC_RAW:
665
return context_derive_keys_des3(ctx, gfp_mask);
666
case ENCTYPE_ARCFOUR_HMAC:
667
return context_derive_keys_rc4(ctx);
668
case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
669
case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
670
return context_derive_keys_new(ctx, gfp_mask);
671
default:
672
return -EINVAL;
673
}
674
675
out_err:
676
return PTR_ERR(p);
677
}
678
679
static int
680
gss_import_sec_context_kerberos(const void *p, size_t len,
681
struct gss_ctx *ctx_id,
682
gfp_t gfp_mask)
683
{
684
const void *end = (const void *)((const char *)p + len);
685
struct krb5_ctx *ctx;
686
int ret;
687
688
ctx = kzalloc(sizeof(*ctx), gfp_mask);
689
if (ctx == NULL)
690
return -ENOMEM;
691
692
if (len == 85)
693
ret = gss_import_v1_context(p, end, ctx);
694
else
695
ret = gss_import_v2_context(p, end, ctx, gfp_mask);
696
697
if (ret == 0)
698
ctx_id->internal_ctx_id = ctx;
699
else
700
kfree(ctx);
701
702
dprintk("RPC: %s: returning %d\n", __func__, ret);
703
return ret;
704
}
705
706
static void
707
gss_delete_sec_context_kerberos(void *internal_ctx) {
708
struct krb5_ctx *kctx = internal_ctx;
709
710
crypto_free_blkcipher(kctx->seq);
711
crypto_free_blkcipher(kctx->enc);
712
crypto_free_blkcipher(kctx->acceptor_enc);
713
crypto_free_blkcipher(kctx->initiator_enc);
714
crypto_free_blkcipher(kctx->acceptor_enc_aux);
715
crypto_free_blkcipher(kctx->initiator_enc_aux);
716
kfree(kctx->mech_used.data);
717
kfree(kctx);
718
}
719
720
static const struct gss_api_ops gss_kerberos_ops = {
721
.gss_import_sec_context = gss_import_sec_context_kerberos,
722
.gss_get_mic = gss_get_mic_kerberos,
723
.gss_verify_mic = gss_verify_mic_kerberos,
724
.gss_wrap = gss_wrap_kerberos,
725
.gss_unwrap = gss_unwrap_kerberos,
726
.gss_delete_sec_context = gss_delete_sec_context_kerberos,
727
};
728
729
static struct pf_desc gss_kerberos_pfs[] = {
730
[0] = {
731
.pseudoflavor = RPC_AUTH_GSS_KRB5,
732
.service = RPC_GSS_SVC_NONE,
733
.name = "krb5",
734
},
735
[1] = {
736
.pseudoflavor = RPC_AUTH_GSS_KRB5I,
737
.service = RPC_GSS_SVC_INTEGRITY,
738
.name = "krb5i",
739
},
740
[2] = {
741
.pseudoflavor = RPC_AUTH_GSS_KRB5P,
742
.service = RPC_GSS_SVC_PRIVACY,
743
.name = "krb5p",
744
},
745
};
746
747
static struct gss_api_mech gss_kerberos_mech = {
748
.gm_name = "krb5",
749
.gm_owner = THIS_MODULE,
750
.gm_oid = {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"},
751
.gm_ops = &gss_kerberos_ops,
752
.gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs),
753
.gm_pfs = gss_kerberos_pfs,
754
.gm_upcall_enctypes = KRB5_SUPPORTED_ENCTYPES,
755
};
756
757
static int __init init_kerberos_module(void)
758
{
759
int status;
760
761
status = gss_mech_register(&gss_kerberos_mech);
762
if (status)
763
printk("Failed to register kerberos gss mechanism!\n");
764
return status;
765
}
766
767
static void __exit cleanup_kerberos_module(void)
768
{
769
gss_mech_unregister(&gss_kerberos_mech);
770
}
771
772
MODULE_LICENSE("GPL");
773
module_init(init_kerberos_module);
774
module_exit(cleanup_kerberos_module);
775
776