Whamcloud - gitweb
bd52ff102d22fea8863b306434d2d307f76dd6ee
[fs/lustre-release.git] / lustre / ptlrpc / gss / gss_krb5_mech.c
1 /*
2  * Modifications for Lustre
3  *
4  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
5  *
6  * Copyright (c) 2011, 2015, Intel Corporation.
7  *
8  * Author: Eric Mei <ericm@clusterfs.com>
9  */
10
11 /*
12  *  linux/net/sunrpc/gss_krb5_mech.c
13  *  linux/net/sunrpc/gss_krb5_crypto.c
14  *  linux/net/sunrpc/gss_krb5_seal.c
15  *  linux/net/sunrpc/gss_krb5_seqnum.c
16  *  linux/net/sunrpc/gss_krb5_unseal.c
17  *
18  *  Copyright (c) 2001 The Regents of the University of Michigan.
19  *  All rights reserved.
20  *
21  *  Andy Adamson <andros@umich.edu>
22  *  J. Bruce Fields <bfields@umich.edu>
23  *
24  *  Redistribution and use in source and binary forms, with or without
25  *  modification, are permitted provided that the following conditions
26  *  are met:
27  *
28  *  1. Redistributions of source code must retain the above copyright
29  *     notice, this list of conditions and the following disclaimer.
30  *  2. Redistributions in binary form must reproduce the above copyright
31  *     notice, this list of conditions and the following disclaimer in the
32  *     documentation and/or other materials provided with the distribution.
33  *  3. Neither the name of the University nor the names of its
34  *     contributors may be used to endorse or promote products derived
35  *     from this software without specific prior written permission.
36  *
37  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
38  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
39  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
41  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44  *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
45  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
46  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
47  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  *
49  */
50
51 #define DEBUG_SUBSYSTEM S_SEC
52 #include <linux/init.h>
53 #include <linux/module.h>
54 #include <linux/slab.h>
55 #include <linux/crypto.h>
56 #include <linux/mutex.h>
57
58 #include <obd.h>
59 #include <obd_class.h>
60 #include <obd_support.h>
61 #include <lustre_net.h>
62 #include <lustre_import.h>
63 #include <lustre_sec.h>
64
65 #include "gss_err.h"
66 #include "gss_internal.h"
67 #include "gss_api.h"
68 #include "gss_asn1.h"
69 #include "gss_krb5.h"
70 #include "gss_crypto.h"
71
72 static spinlock_t krb5_seq_lock;
73
74 struct krb5_enctype {
75         char           *ke_dispname;
76         char           *ke_enc_name;            /* linux tfm name */
77         char           *ke_hash_name;           /* linux tfm name */
78         int             ke_enc_mode;            /* linux tfm mode */
79         int             ke_hash_size;           /* checksum size */
80         int             ke_conf_size;           /* confounder size */
81         unsigned int    ke_hash_hmac:1;         /* is hmac? */
82 };
83
84 /*
85  * NOTE: for aes128-cts and aes256-cts, MIT implementation use CTS encryption.
86  * but currently we simply CBC with padding, because linux doesn't support CTS
87  * yet. this need to be fixed in the future.
88  */
89 static struct krb5_enctype enctypes[] = {
90         [ENCTYPE_DES_CBC_RAW] = {               /* des-cbc-md5 */
91                 .ke_dispname    = "des-cbc-md5",
92                 .ke_enc_name    = "cbc(des)",
93                 .ke_hash_name   = "md5",
94                 .ke_hash_size   = 16,
95                 .ke_conf_size   = 8,
96         },
97         [ENCTYPE_DES3_CBC_RAW] = {              /* des3-hmac-sha1 */
98                 .ke_dispname    = "des3-hmac-sha1",
99                 .ke_enc_name    = "cbc(des3_ede)",
100                 .ke_hash_name   = "hmac(sha1)",
101                 .ke_hash_size   = 20,
102                 .ke_conf_size   = 8,
103                 .ke_hash_hmac   = 1,
104         },
105         [ENCTYPE_AES128_CTS_HMAC_SHA1_96] = {   /* aes128-cts */
106                 .ke_dispname    = "aes128-cts-hmac-sha1-96",
107                 .ke_enc_name    = "cbc(aes)",
108                 .ke_hash_name   = "hmac(sha1)",
109                 .ke_hash_size   = 12,
110                 .ke_conf_size   = 16,
111                 .ke_hash_hmac   = 1,
112         },
113         [ENCTYPE_AES256_CTS_HMAC_SHA1_96] = {   /* aes256-cts */
114                 .ke_dispname    = "aes256-cts-hmac-sha1-96",
115                 .ke_enc_name    = "cbc(aes)",
116                 .ke_hash_name   = "hmac(sha1)",
117                 .ke_hash_size   = 12,
118                 .ke_conf_size   = 16,
119                 .ke_hash_hmac   = 1,
120         },
121         [ENCTYPE_ARCFOUR_HMAC] = {              /* arcfour-hmac-md5 */
122                 .ke_dispname    = "arcfour-hmac-md5",
123                 .ke_enc_name    = "ecb(arc4)",
124                 .ke_hash_name   = "hmac(md5)",
125                 .ke_hash_size   = 16,
126                 .ke_conf_size   = 8,
127                 .ke_hash_hmac   = 1,
128         }
129 };
130
131 #define MAX_ENCTYPES    sizeof(enctypes)/sizeof(struct krb5_enctype)
132
133 static const char * enctype2str(__u32 enctype)
134 {
135         if (enctype < MAX_ENCTYPES && enctypes[enctype].ke_dispname)
136                 return enctypes[enctype].ke_dispname;
137
138         return "unknown";
139 }
140
141 static
142 int krb5_init_keys(struct krb5_ctx *kctx)
143 {
144         struct krb5_enctype *ke;
145
146         if (kctx->kc_enctype >= MAX_ENCTYPES ||
147             enctypes[kctx->kc_enctype].ke_hash_size == 0) {
148                 CERROR("unsupported enctype %x\n", kctx->kc_enctype);
149                 return -1;
150         }
151
152         ke = &enctypes[kctx->kc_enctype];
153
154         /* tfm arc4 is stateful, user should alloc-use-free by his own */
155         if (kctx->kc_enctype != ENCTYPE_ARCFOUR_HMAC &&
156             gss_keyblock_init(&kctx->kc_keye, ke->ke_enc_name, ke->ke_enc_mode))
157                 return -1;
158
159         /* tfm hmac is stateful, user should alloc-use-free by his own */
160         if (ke->ke_hash_hmac == 0 &&
161             gss_keyblock_init(&kctx->kc_keyi, ke->ke_enc_name, ke->ke_enc_mode))
162                 return -1;
163         if (ke->ke_hash_hmac == 0 &&
164             gss_keyblock_init(&kctx->kc_keyc, ke->ke_enc_name, ke->ke_enc_mode))
165                 return -1;
166
167         return 0;
168 }
169
170 static
171 void delete_context_kerberos(struct krb5_ctx *kctx)
172 {
173         rawobj_free(&kctx->kc_mech_used);
174
175         gss_keyblock_free(&kctx->kc_keye);
176         gss_keyblock_free(&kctx->kc_keyi);
177         gss_keyblock_free(&kctx->kc_keyc);
178 }
179
180 static
181 __u32 import_context_rfc1964(struct krb5_ctx *kctx, char *p, char *end)
182 {
183         unsigned int    tmp_uint, keysize;
184
185         /* seed_init flag */
186         if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
187                 goto out_err;
188         kctx->kc_seed_init = (tmp_uint != 0);
189
190         /* seed */
191         if (gss_get_bytes(&p, end, kctx->kc_seed, sizeof(kctx->kc_seed)))
192                 goto out_err;
193
194         /* sign/seal algorithm, not really used now */
195         if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) ||
196             gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
197                 goto out_err;
198
199         /* end time */
200         if (gss_get_bytes(&p, end, &kctx->kc_endtime, sizeof(kctx->kc_endtime)))
201                 goto out_err;
202
203         /* seq send */
204         if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
205                 goto out_err;
206         kctx->kc_seq_send = tmp_uint;
207
208         /* mech oid */
209         if (gss_get_rawobj(&p, end, &kctx->kc_mech_used))
210                 goto out_err;
211
212         /* old style enc/seq keys in format:
213          *   - enctype (u32)
214          *   - keysize (u32)
215          *   - keydata
216          * we decompose them to fit into the new context
217          */
218
219         /* enc key */
220         if (gss_get_bytes(&p, end, &kctx->kc_enctype, sizeof(kctx->kc_enctype)))
221                 goto out_err;
222
223         if (gss_get_bytes(&p, end, &keysize, sizeof(keysize)))
224                 goto out_err;
225
226         if (gss_get_keyblock(&p, end, &kctx->kc_keye, keysize))
227                 goto out_err;
228
229         /* seq key */
230         if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) ||
231             tmp_uint != kctx->kc_enctype)
232                 goto out_err;
233
234         if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) ||
235             tmp_uint != keysize)
236                 goto out_err;
237
238         if (gss_get_keyblock(&p, end, &kctx->kc_keyc, keysize))
239                 goto out_err;
240
241         /* old style fallback */
242         if (gss_keyblock_dup(&kctx->kc_keyi, &kctx->kc_keyc))
243                 goto out_err;
244
245         if (p != end)
246                 goto out_err;
247
248         CDEBUG(D_SEC, "successfully imported rfc1964 context\n");
249         return 0;
250 out_err:
251         return GSS_S_FAILURE;
252 }
253
254 /* Flags for version 2 context flags */
255 #define KRB5_CTX_FLAG_INITIATOR         0x00000001
256 #define KRB5_CTX_FLAG_CFX               0x00000002
257 #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY   0x00000004
258
259 static
260 __u32 import_context_rfc4121(struct krb5_ctx *kctx, char *p, char *end)
261 {
262         unsigned int    tmp_uint, keysize;
263
264         /* end time */
265         if (gss_get_bytes(&p, end, &kctx->kc_endtime, sizeof(kctx->kc_endtime)))
266                 goto out_err;
267
268         /* flags */
269         if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
270                 goto out_err;
271
272         if (tmp_uint & KRB5_CTX_FLAG_INITIATOR)
273                 kctx->kc_initiate = 1;
274         if (tmp_uint & KRB5_CTX_FLAG_CFX)
275                 kctx->kc_cfx = 1;
276         if (tmp_uint & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY)
277                 kctx->kc_have_acceptor_subkey = 1;
278
279         /* seq send */
280         if (gss_get_bytes(&p, end, &kctx->kc_seq_send,
281             sizeof(kctx->kc_seq_send)))
282                 goto out_err;
283
284         /* enctype */
285         if (gss_get_bytes(&p, end, &kctx->kc_enctype, sizeof(kctx->kc_enctype)))
286                 goto out_err;
287
288         /* size of each key */
289         if (gss_get_bytes(&p, end, &keysize, sizeof(keysize)))
290                 goto out_err;
291
292         /* number of keys - should always be 3 */
293         if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
294                 goto out_err;
295
296         if (tmp_uint != 3) {
297                 CERROR("Invalid number of keys: %u\n", tmp_uint);
298                 goto out_err;
299         }
300
301         /* ke */
302         if (gss_get_keyblock(&p, end, &kctx->kc_keye, keysize))
303                 goto out_err;
304         /* ki */
305         if (gss_get_keyblock(&p, end, &kctx->kc_keyi, keysize))
306                 goto out_err;
307         /* ki */
308         if (gss_get_keyblock(&p, end, &kctx->kc_keyc, keysize))
309                 goto out_err;
310
311         CDEBUG(D_SEC, "successfully imported v2 context\n");
312         return 0;
313 out_err:
314         return GSS_S_FAILURE;
315 }
316
317 /*
318  * The whole purpose here is trying to keep user level gss context parsing
319  * from nfs-utils unchanged as possible as we can, they are not quite mature
320  * yet, and many stuff still not clear, like heimdal etc.
321  */
322 static
323 __u32 gss_import_sec_context_kerberos(rawobj_t *inbuf,
324                                       struct gss_ctx *gctx)
325 {
326         struct krb5_ctx *kctx;
327         char *p = (char *)inbuf->data;
328         char *end = (char *)(inbuf->data + inbuf->len);
329         unsigned int tmp_uint, rc;
330
331         if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint))) {
332                 CERROR("Fail to read version\n");
333                 return GSS_S_FAILURE;
334         }
335
336         /* only support 0, 1 for the moment */
337         if (tmp_uint > 2) {
338                 CERROR("Invalid version %u\n", tmp_uint);
339                 return GSS_S_FAILURE;
340         }
341
342         OBD_ALLOC_PTR(kctx);
343         if (!kctx)
344                 return GSS_S_FAILURE;
345
346         if (tmp_uint == 0 || tmp_uint == 1) {
347                 kctx->kc_initiate = tmp_uint;
348                 rc = import_context_rfc1964(kctx, p, end);
349         } else {
350                 rc = import_context_rfc4121(kctx, p, end);
351         }
352
353         if (rc == 0)
354                 rc = krb5_init_keys(kctx);
355
356         if (rc) {
357                 delete_context_kerberos(kctx);
358                 OBD_FREE_PTR(kctx);
359
360                 return GSS_S_FAILURE;
361         }
362
363         gctx->internal_ctx_id = kctx;
364         return GSS_S_COMPLETE;
365 }
366
367 static
368 __u32 gss_copy_reverse_context_kerberos(struct gss_ctx *gctx,
369                                         struct gss_ctx *gctx_new)
370 {
371         struct krb5_ctx *kctx = gctx->internal_ctx_id;
372         struct krb5_ctx *knew;
373
374         OBD_ALLOC_PTR(knew);
375         if (!knew)
376                 return GSS_S_FAILURE;
377
378         knew->kc_initiate = kctx->kc_initiate ? 0 : 1;
379         knew->kc_cfx = kctx->kc_cfx;
380         knew->kc_seed_init = kctx->kc_seed_init;
381         knew->kc_have_acceptor_subkey = kctx->kc_have_acceptor_subkey;
382         knew->kc_endtime = kctx->kc_endtime;
383
384         memcpy(knew->kc_seed, kctx->kc_seed, sizeof(kctx->kc_seed));
385         knew->kc_seq_send = kctx->kc_seq_recv;
386         knew->kc_seq_recv = kctx->kc_seq_send;
387         knew->kc_enctype = kctx->kc_enctype;
388
389         if (rawobj_dup(&knew->kc_mech_used, &kctx->kc_mech_used))
390                 goto out_err;
391
392         if (gss_keyblock_dup(&knew->kc_keye, &kctx->kc_keye))
393                 goto out_err;
394         if (gss_keyblock_dup(&knew->kc_keyi, &kctx->kc_keyi))
395                 goto out_err;
396         if (gss_keyblock_dup(&knew->kc_keyc, &kctx->kc_keyc))
397                 goto out_err;
398         if (krb5_init_keys(knew))
399                 goto out_err;
400
401         gctx_new->internal_ctx_id = knew;
402         CDEBUG(D_SEC, "successfully copied reverse context\n");
403         return GSS_S_COMPLETE;
404
405 out_err:
406         delete_context_kerberos(knew);
407         OBD_FREE_PTR(knew);
408         return GSS_S_FAILURE;
409 }
410
411 static
412 __u32 gss_inquire_context_kerberos(struct gss_ctx *gctx,
413                                    unsigned long  *endtime)
414 {
415         struct krb5_ctx *kctx = gctx->internal_ctx_id;
416
417         *endtime = (unsigned long)((__u32) kctx->kc_endtime);
418         return GSS_S_COMPLETE;
419 }
420
421 static
422 void gss_delete_sec_context_kerberos(void *internal_ctx)
423 {
424         struct krb5_ctx *kctx = internal_ctx;
425
426         delete_context_kerberos(kctx);
427         OBD_FREE_PTR(kctx);
428 }
429
430 /*
431  * compute (keyed/keyless) checksum against the plain text which appended
432  * with krb5 wire token header.
433  */
434 static
435 __s32 krb5_make_checksum(__u32 enctype,
436                          struct gss_keyblock *kb,
437                          struct krb5_header *khdr,
438                          int msgcnt, rawobj_t *msgs,
439                          int iovcnt, lnet_kiov_t *iovs,
440                          rawobj_t *cksum)
441 {
442         struct krb5_enctype   *ke = &enctypes[enctype];
443         struct crypto_hash    *tfm;
444         rawobj_t               hdr;
445         __u32                  code = GSS_S_FAILURE;
446         int                    rc;
447
448         if (!(tfm = crypto_alloc_hash(ke->ke_hash_name, 0, 0))) {
449                 CERROR("failed to alloc TFM: %s\n", ke->ke_hash_name);
450                 return GSS_S_FAILURE;
451         }
452
453         cksum->len = crypto_hash_digestsize(tfm);
454         OBD_ALLOC_LARGE(cksum->data, cksum->len);
455         if (!cksum->data) {
456                 cksum->len = 0;
457                 goto out_tfm;
458         }
459
460         hdr.data = (__u8 *)khdr;
461         hdr.len = sizeof(*khdr);
462
463         if (ke->ke_hash_hmac)
464                 rc = gss_digest_hmac(tfm, &kb->kb_key,
465                                      &hdr, msgcnt, msgs, iovcnt, iovs, cksum);
466         else
467                 rc = gss_digest_norm(tfm, kb,
468                                      &hdr, msgcnt, msgs, iovcnt, iovs, cksum);
469
470         if (rc == 0)
471                 code = GSS_S_COMPLETE;
472 out_tfm:
473         crypto_free_hash(tfm);
474         return code;
475 }
476
477 static void fill_krb5_header(struct krb5_ctx *kctx,
478                              struct krb5_header *khdr,
479                              int privacy)
480 {
481         unsigned char acceptor_flag;
482
483         acceptor_flag = kctx->kc_initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR;
484
485         if (privacy) {
486                 khdr->kh_tok_id = cpu_to_be16(KG_TOK_WRAP_MSG);
487                 khdr->kh_flags = acceptor_flag | FLAG_WRAP_CONFIDENTIAL;
488                 khdr->kh_ec = cpu_to_be16(0);
489                 khdr->kh_rrc = cpu_to_be16(0);
490         } else {
491                 khdr->kh_tok_id = cpu_to_be16(KG_TOK_MIC_MSG);
492                 khdr->kh_flags = acceptor_flag;
493                 khdr->kh_ec = cpu_to_be16(0xffff);
494                 khdr->kh_rrc = cpu_to_be16(0xffff);
495         }
496
497         khdr->kh_filler = 0xff;
498         spin_lock(&krb5_seq_lock);
499         khdr->kh_seq = cpu_to_be64(kctx->kc_seq_send++);
500         spin_unlock(&krb5_seq_lock);
501 }
502
503 static __u32 verify_krb5_header(struct krb5_ctx *kctx,
504                                 struct krb5_header *khdr,
505                                 int privacy)
506 {
507         unsigned char acceptor_flag;
508         __u16         tok_id, ec_rrc;
509
510         acceptor_flag = kctx->kc_initiate ? FLAG_SENDER_IS_ACCEPTOR : 0;
511
512         if (privacy) {
513                 tok_id = KG_TOK_WRAP_MSG;
514                 ec_rrc = 0x0;
515         } else {
516                 tok_id = KG_TOK_MIC_MSG;
517                 ec_rrc = 0xffff;
518         }
519
520         /* sanity checks */
521         if (be16_to_cpu(khdr->kh_tok_id) != tok_id) {
522                 CERROR("bad token id\n");
523                 return GSS_S_DEFECTIVE_TOKEN;
524         }
525         if ((khdr->kh_flags & FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) {
526                 CERROR("bad direction flag\n");
527                 return GSS_S_BAD_SIG;
528         }
529         if (privacy && (khdr->kh_flags & FLAG_WRAP_CONFIDENTIAL) == 0) {
530                 CERROR("missing confidential flag\n");
531                 return GSS_S_BAD_SIG;
532         }
533         if (khdr->kh_filler != 0xff) {
534                 CERROR("bad filler\n");
535                 return GSS_S_DEFECTIVE_TOKEN;
536         }
537         if (be16_to_cpu(khdr->kh_ec) != ec_rrc ||
538             be16_to_cpu(khdr->kh_rrc) != ec_rrc) {
539                 CERROR("bad EC or RRC\n");
540                 return GSS_S_DEFECTIVE_TOKEN;
541         }
542         return GSS_S_COMPLETE;
543 }
544
545 static
546 __u32 gss_get_mic_kerberos(struct gss_ctx *gctx,
547                            int msgcnt,
548                            rawobj_t *msgs,
549                            int iovcnt,
550                            lnet_kiov_t *iovs,
551                            rawobj_t *token)
552 {
553         struct krb5_ctx     *kctx = gctx->internal_ctx_id;
554         struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
555         struct krb5_header  *khdr;
556         rawobj_t             cksum = RAWOBJ_EMPTY;
557
558         /* fill krb5 header */
559         LASSERT(token->len >= sizeof(*khdr));
560         khdr = (struct krb5_header *)token->data;
561         fill_krb5_header(kctx, khdr, 0);
562
563         /* checksum */
564         if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyc,
565                                khdr, msgcnt, msgs, iovcnt, iovs, &cksum))
566                 return GSS_S_FAILURE;
567
568         LASSERT(cksum.len >= ke->ke_hash_size);
569         LASSERT(token->len >= sizeof(*khdr) + ke->ke_hash_size);
570         memcpy(khdr + 1, cksum.data + cksum.len - ke->ke_hash_size,
571                ke->ke_hash_size);
572
573         token->len = sizeof(*khdr) + ke->ke_hash_size;
574         rawobj_free(&cksum);
575         return GSS_S_COMPLETE;
576 }
577
578 static
579 __u32 gss_verify_mic_kerberos(struct gss_ctx *gctx,
580                               int msgcnt,
581                               rawobj_t *msgs,
582                               int iovcnt,
583                               lnet_kiov_t *iovs,
584                               rawobj_t *token)
585 {
586         struct krb5_ctx     *kctx = gctx->internal_ctx_id;
587         struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
588         struct krb5_header  *khdr;
589         rawobj_t             cksum = RAWOBJ_EMPTY;
590         __u32                major;
591
592         if (token->len < sizeof(*khdr)) {
593                 CERROR("short signature: %u\n", token->len);
594                 return GSS_S_DEFECTIVE_TOKEN;
595         }
596
597         khdr = (struct krb5_header *)token->data;
598
599         major = verify_krb5_header(kctx, khdr, 0);
600         if (major != GSS_S_COMPLETE) {
601                 CERROR("bad krb5 header\n");
602                 return major;
603         }
604
605         if (token->len < sizeof(*khdr) + ke->ke_hash_size) {
606                 CERROR("short signature: %u, require %d\n",
607                        token->len, (int) sizeof(*khdr) + ke->ke_hash_size);
608                 return GSS_S_FAILURE;
609         }
610
611         if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyc,
612                                khdr, msgcnt, msgs, iovcnt, iovs, &cksum)) {
613                 CERROR("failed to make checksum\n");
614                 return GSS_S_FAILURE;
615         }
616
617         LASSERT(cksum.len >= ke->ke_hash_size);
618         if (memcmp(khdr + 1, cksum.data + cksum.len - ke->ke_hash_size,
619                    ke->ke_hash_size)) {
620                 CERROR("checksum mismatch\n");
621                 rawobj_free(&cksum);
622                 return GSS_S_BAD_SIG;
623         }
624
625         rawobj_free(&cksum);
626         return GSS_S_COMPLETE;
627 }
628
629 /*
630  * if adj_nob != 0, we adjust desc->bd_nob to the actual cipher text size.
631  */
632 static
633 int krb5_encrypt_bulk(struct crypto_blkcipher *tfm,
634                       struct krb5_header *khdr,
635                       char *confounder,
636                       struct ptlrpc_bulk_desc *desc,
637                       rawobj_t *cipher,
638                       int adj_nob)
639 {
640         struct blkcipher_desc   ciph_desc;
641         __u8                    local_iv[16] = {0};
642         struct scatterlist      src, dst;
643         struct sg_table         sg_src, sg_dst;
644         int                     blocksize, i, rc, nob = 0;
645
646         LASSERT(ptlrpc_is_bulk_desc_kiov(desc->bd_type));
647         LASSERT(desc->bd_iov_count);
648         LASSERT(GET_ENC_KIOV(desc));
649
650         blocksize = crypto_blkcipher_blocksize(tfm);
651         LASSERT(blocksize > 1);
652         LASSERT(cipher->len == blocksize + sizeof(*khdr));
653
654         ciph_desc.tfm  = tfm;
655         ciph_desc.info = local_iv;
656         ciph_desc.flags = 0;
657
658         /* encrypt confounder */
659         rc = gss_setup_sgtable(&sg_src, &src, confounder, blocksize);
660         if (rc != 0)
661                 return rc;
662
663         rc = gss_setup_sgtable(&sg_dst, &dst, cipher->data, blocksize);
664         if (rc != 0) {
665                 gss_teardown_sgtable(&sg_src);
666                 return rc;
667         }
668
669         rc = crypto_blkcipher_encrypt_iv(&ciph_desc, sg_dst.sgl,
670                                          sg_src.sgl, blocksize);
671
672         gss_teardown_sgtable(&sg_dst);
673         gss_teardown_sgtable(&sg_src);
674
675         if (rc) {
676                 CERROR("error to encrypt confounder: %d\n", rc);
677                 return rc;
678         }
679
680         /* encrypt clear pages */
681         for (i = 0; i < desc->bd_iov_count; i++) {
682                 sg_init_table(&src, 1);
683                 sg_set_page(&src, BD_GET_KIOV(desc, i).kiov_page,
684                             (BD_GET_KIOV(desc, i).kiov_len +
685                                 blocksize - 1) &
686                             (~(blocksize - 1)),
687                             BD_GET_KIOV(desc, i).kiov_offset);
688                 if (adj_nob)
689                         nob += src.length;
690                 sg_init_table(&dst, 1);
691                 sg_set_page(&dst, BD_GET_ENC_KIOV(desc, i).kiov_page,
692                             src.length, src.offset);
693
694                 BD_GET_ENC_KIOV(desc, i).kiov_offset = dst.offset;
695                 BD_GET_ENC_KIOV(desc, i).kiov_len = dst.length;
696
697                 rc = crypto_blkcipher_encrypt_iv(&ciph_desc, &dst, &src,
698                                                     src.length);
699                 if (rc) {
700                         CERROR("error to encrypt page: %d\n", rc);
701                         return rc;
702                 }
703         }
704
705         /* encrypt krb5 header */
706         rc = gss_setup_sgtable(&sg_src, &src, khdr, sizeof(*khdr));
707         if (rc != 0)
708                 return rc;
709
710         rc = gss_setup_sgtable(&sg_dst, &dst, cipher->data + blocksize,
711                            sizeof(*khdr));
712         if (rc != 0) {
713                 gss_teardown_sgtable(&sg_src);
714                 return rc;
715         }
716
717         rc = crypto_blkcipher_encrypt_iv(&ciph_desc, sg_dst.sgl, sg_src.sgl,
718                                          sizeof(*khdr));
719
720         gss_teardown_sgtable(&sg_dst);
721         gss_teardown_sgtable(&sg_src);
722
723         if (rc) {
724                 CERROR("error to encrypt krb5 header: %d\n", rc);
725                 return rc;
726         }
727
728         if (adj_nob)
729                 desc->bd_nob = nob;
730
731         return 0;
732 }
733
734 /*
735  * desc->bd_nob_transferred is the size of cipher text received.
736  * desc->bd_nob is the target size of plain text supposed to be.
737  *
738  * if adj_nob != 0, we adjust each page's kiov_len to the actual
739  * plain text size.
740  * - for client read: we don't know data size for each page, so
741  *   bd_iov[]->kiov_len is set to PAGE_SIZE, but actual data received might
742  *   be smaller, so we need to adjust it according to
743  *   bd_u.bd_kiov.bd_enc_vec[]->kiov_len.
744  *   this means we DO NOT support the situation that server send an odd size
745  *   data in a page which is not the last one.
746  * - for server write: we knows exactly data size for each page being expected,
747  *   thus kiov_len is accurate already, so we should not adjust it at all.
748  *   and bd_u.bd_kiov.bd_enc_vec[]->kiov_len should be
749  *   round_up(bd_iov[]->kiov_len) which
750  *   should have been done by prep_bulk().
751  */
752 static
753 int krb5_decrypt_bulk(struct crypto_blkcipher *tfm,
754                       struct krb5_header *khdr,
755                       struct ptlrpc_bulk_desc *desc,
756                       rawobj_t *cipher,
757                       rawobj_t *plain,
758                       int adj_nob)
759 {
760         struct blkcipher_desc   ciph_desc;
761         __u8                    local_iv[16] = {0};
762         struct scatterlist      src, dst;
763         struct sg_table         sg_src, sg_dst;
764         int                     ct_nob = 0, pt_nob = 0;
765         int                     blocksize, i, rc;
766
767         LASSERT(ptlrpc_is_bulk_desc_kiov(desc->bd_type));
768         LASSERT(desc->bd_iov_count);
769         LASSERT(GET_ENC_KIOV(desc));
770         LASSERT(desc->bd_nob_transferred);
771
772         blocksize = crypto_blkcipher_blocksize(tfm);
773         LASSERT(blocksize > 1);
774         LASSERT(cipher->len == blocksize + sizeof(*khdr));
775
776         ciph_desc.tfm  = tfm;
777         ciph_desc.info = local_iv;
778         ciph_desc.flags = 0;
779
780         if (desc->bd_nob_transferred % blocksize) {
781                 CERROR("odd transferred nob: %d\n", desc->bd_nob_transferred);
782                 return -EPROTO;
783         }
784
785         /* decrypt head (confounder) */
786         rc = gss_setup_sgtable(&sg_src, &src, cipher->data, blocksize);
787         if (rc != 0)
788                 return rc;
789
790         rc = gss_setup_sgtable(&sg_dst, &dst, plain->data, blocksize);
791         if (rc != 0) {
792                 gss_teardown_sgtable(&sg_src);
793                 return rc;
794         }
795
796         rc = crypto_blkcipher_decrypt_iv(&ciph_desc, sg_dst.sgl,
797                                          sg_src.sgl, blocksize);
798
799         gss_teardown_sgtable(&sg_dst);
800         gss_teardown_sgtable(&sg_src);
801
802         if (rc) {
803                 CERROR("error to decrypt confounder: %d\n", rc);
804                 return rc;
805         }
806
807         for (i = 0; i < desc->bd_iov_count && ct_nob < desc->bd_nob_transferred;
808              i++) {
809                 if (BD_GET_ENC_KIOV(desc, i).kiov_offset % blocksize
810                     != 0 ||
811                     BD_GET_ENC_KIOV(desc, i).kiov_len % blocksize
812                     != 0) {
813                         CERROR("page %d: odd offset %u len %u, blocksize %d\n",
814                                i, BD_GET_ENC_KIOV(desc, i).kiov_offset,
815                                BD_GET_ENC_KIOV(desc, i).kiov_len,
816                                blocksize);
817                         return -EFAULT;
818                 }
819
820                 if (adj_nob) {
821                         if (ct_nob + BD_GET_ENC_KIOV(desc, i).kiov_len >
822                             desc->bd_nob_transferred)
823                                 BD_GET_ENC_KIOV(desc, i).kiov_len =
824                                         desc->bd_nob_transferred - ct_nob;
825
826                         BD_GET_KIOV(desc, i).kiov_len =
827                           BD_GET_ENC_KIOV(desc, i).kiov_len;
828                         if (pt_nob + BD_GET_ENC_KIOV(desc, i).kiov_len >
829                             desc->bd_nob)
830                                 BD_GET_KIOV(desc, i).kiov_len =
831                                   desc->bd_nob - pt_nob;
832                 } else {
833                         /* this should be guaranteed by LNET */
834                         LASSERT(ct_nob + BD_GET_ENC_KIOV(desc, i).
835                                 kiov_len <=
836                                 desc->bd_nob_transferred);
837                         LASSERT(BD_GET_KIOV(desc, i).kiov_len <=
838                                 BD_GET_ENC_KIOV(desc, i).kiov_len);
839                 }
840
841                 if (BD_GET_ENC_KIOV(desc, i).kiov_len == 0)
842                         continue;
843
844                 sg_init_table(&src, 1);
845                 sg_set_page(&src, BD_GET_ENC_KIOV(desc, i).kiov_page,
846                             BD_GET_ENC_KIOV(desc, i).kiov_len,
847                             BD_GET_ENC_KIOV(desc, i).kiov_offset);
848                 dst = src;
849                 if (BD_GET_KIOV(desc, i).kiov_len % blocksize == 0)
850                         sg_assign_page(&dst,
851                                        BD_GET_KIOV(desc, i).kiov_page);
852
853                 rc = crypto_blkcipher_decrypt_iv(&ciph_desc, &dst, &src,
854                                                  src.length);
855                 if (rc) {
856                         CERROR("error to decrypt page: %d\n", rc);
857                         return rc;
858                 }
859
860                 if (BD_GET_KIOV(desc, i).kiov_len % blocksize != 0) {
861                         memcpy(page_address(BD_GET_KIOV(desc, i).kiov_page) +
862                                BD_GET_KIOV(desc, i).kiov_offset,
863                                page_address(BD_GET_ENC_KIOV(desc, i).
864                                             kiov_page) +
865                                BD_GET_KIOV(desc, i).kiov_offset,
866                                BD_GET_KIOV(desc, i).kiov_len);
867                 }
868
869                 ct_nob += BD_GET_ENC_KIOV(desc, i).kiov_len;
870                 pt_nob += BD_GET_KIOV(desc, i).kiov_len;
871         }
872
873         if (unlikely(ct_nob != desc->bd_nob_transferred)) {
874                 CERROR("%d cipher text transferred but only %d decrypted\n",
875                        desc->bd_nob_transferred, ct_nob);
876                 return -EFAULT;
877         }
878
879         if (unlikely(!adj_nob && pt_nob != desc->bd_nob)) {
880                 CERROR("%d plain text expected but only %d received\n",
881                        desc->bd_nob, pt_nob);
882                 return -EFAULT;
883         }
884
885         /* if needed, clear up the rest unused iovs */
886         if (adj_nob)
887                 while (i < desc->bd_iov_count)
888                         BD_GET_KIOV(desc, i++).kiov_len = 0;
889
890         /* decrypt tail (krb5 header) */
891         rc = gss_setup_sgtable(&sg_src, &src, cipher->data + blocksize,
892                                sizeof(*khdr));
893         if (rc != 0)
894                 return rc;
895
896         rc = gss_setup_sgtable(&sg_dst, &dst, cipher->data + blocksize,
897                                sizeof(*khdr));
898         if (rc != 0) {
899                 gss_teardown_sgtable(&sg_src);
900                 return rc;
901         }
902
903         rc = crypto_blkcipher_decrypt_iv(&ciph_desc, sg_dst.sgl, sg_src.sgl,
904                                          sizeof(*khdr));
905
906         gss_teardown_sgtable(&sg_src);
907         gss_teardown_sgtable(&sg_dst);
908
909         if (rc) {
910                 CERROR("error to decrypt tail: %d\n", rc);
911                 return rc;
912         }
913
914         if (memcmp(cipher->data + blocksize, khdr, sizeof(*khdr))) {
915                 CERROR("krb5 header doesn't match\n");
916                 return -EACCES;
917         }
918
919         return 0;
920 }
921
922 static
923 __u32 gss_wrap_kerberos(struct gss_ctx *gctx,
924                         rawobj_t *gsshdr,
925                         rawobj_t *msg,
926                         int msg_buflen,
927                         rawobj_t *token)
928 {
929         struct krb5_ctx     *kctx = gctx->internal_ctx_id;
930         struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
931         struct krb5_header  *khdr;
932         int                  blocksize;
933         rawobj_t             cksum = RAWOBJ_EMPTY;
934         rawobj_t             data_desc[3], cipher;
935         __u8                 conf[GSS_MAX_CIPHER_BLOCK];
936         __u8                 local_iv[16] = {0};
937         int                  rc = 0;
938
939         LASSERT(ke);
940         LASSERT(ke->ke_conf_size <= GSS_MAX_CIPHER_BLOCK);
941         LASSERT(kctx->kc_keye.kb_tfm == NULL ||
942                 ke->ke_conf_size >=
943                 crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm));
944
945         /*
946          * final token format:
947          * ---------------------------------------------------
948          * | krb5 header | cipher text | checksum (16 bytes) |
949          * ---------------------------------------------------
950          */
951
952         /* fill krb5 header */
953         LASSERT(token->len >= sizeof(*khdr));
954         khdr = (struct krb5_header *)token->data;
955         fill_krb5_header(kctx, khdr, 1);
956
957         /* generate confounder */
958         cfs_get_random_bytes(conf, ke->ke_conf_size);
959
960         /* get encryption blocksize. note kc_keye might not associated with
961          * a tfm, currently only for arcfour-hmac */
962         if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
963                 LASSERT(kctx->kc_keye.kb_tfm == NULL);
964                 blocksize = 1;
965         } else {
966                 LASSERT(kctx->kc_keye.kb_tfm);
967                 blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
968         }
969         LASSERT(blocksize <= ke->ke_conf_size);
970
971         /* padding the message */
972         if (gss_add_padding(msg, msg_buflen, blocksize))
973                 return GSS_S_FAILURE;
974
975         /*
976          * clear text layout for checksum:
977          * ------------------------------------------------------
978          * | confounder | gss header | clear msgs | krb5 header |
979          * ------------------------------------------------------
980          */
981         data_desc[0].data = conf;
982         data_desc[0].len = ke->ke_conf_size;
983         data_desc[1].data = gsshdr->data;
984         data_desc[1].len = gsshdr->len;
985         data_desc[2].data = msg->data;
986         data_desc[2].len = msg->len;
987
988         /* compute checksum */
989         if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi,
990                                khdr, 3, data_desc, 0, NULL, &cksum))
991                 return GSS_S_FAILURE;
992         LASSERT(cksum.len >= ke->ke_hash_size);
993
994         /*
995          * clear text layout for encryption:
996          * -----------------------------------------
997          * | confounder | clear msgs | krb5 header |
998          * -----------------------------------------
999          */
1000         data_desc[0].data = conf;
1001         data_desc[0].len = ke->ke_conf_size;
1002         data_desc[1].data = msg->data;
1003         data_desc[1].len = msg->len;
1004         data_desc[2].data = (__u8 *) khdr;
1005         data_desc[2].len = sizeof(*khdr);
1006
1007         /* cipher text will be directly inplace */
1008         cipher.data = (__u8 *)(khdr + 1);
1009         cipher.len = token->len - sizeof(*khdr);
1010         LASSERT(cipher.len >= ke->ke_conf_size + msg->len + sizeof(*khdr));
1011
1012         if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
1013                 rawobj_t                 arc4_keye;
1014                 struct crypto_blkcipher *arc4_tfm;
1015
1016                 if (krb5_make_checksum(ENCTYPE_ARCFOUR_HMAC, &kctx->kc_keyi,
1017                                        NULL, 1, &cksum, 0, NULL, &arc4_keye)) {
1018                         CERROR("failed to obtain arc4 enc key\n");
1019                         GOTO(arc4_out, rc = -EACCES);
1020                 }
1021
1022                 arc4_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, 0);
1023                 if (IS_ERR(arc4_tfm)) {
1024                         CERROR("failed to alloc tfm arc4 in ECB mode\n");
1025                         GOTO(arc4_out_key, rc = -EACCES);
1026                 }
1027
1028                 if (crypto_blkcipher_setkey(arc4_tfm, arc4_keye.data,
1029                                                arc4_keye.len)) {
1030                         CERROR("failed to set arc4 key, len %d\n",
1031                                arc4_keye.len);
1032                         GOTO(arc4_out_tfm, rc = -EACCES);
1033                 }
1034
1035                 rc = gss_crypt_rawobjs(arc4_tfm, NULL, 3, data_desc,
1036                                        &cipher, 1);
1037 arc4_out_tfm:
1038                 crypto_free_blkcipher(arc4_tfm);
1039 arc4_out_key:
1040                 rawobj_free(&arc4_keye);
1041 arc4_out:
1042                 do {} while(0); /* just to avoid compile warning */
1043         } else {
1044                 rc = gss_crypt_rawobjs(kctx->kc_keye.kb_tfm, local_iv, 3,
1045                                        data_desc, &cipher, 1);
1046         }
1047
1048         if (rc != 0) {
1049                 rawobj_free(&cksum);
1050                 return GSS_S_FAILURE;
1051         }
1052
1053         /* fill in checksum */
1054         LASSERT(token->len >= sizeof(*khdr) + cipher.len + ke->ke_hash_size);
1055         memcpy((char *)(khdr + 1) + cipher.len,
1056                cksum.data + cksum.len - ke->ke_hash_size,
1057                ke->ke_hash_size);
1058         rawobj_free(&cksum);
1059
1060         /* final token length */
1061         token->len = sizeof(*khdr) + cipher.len + ke->ke_hash_size;
1062         return GSS_S_COMPLETE;
1063 }
1064
1065 static
1066 __u32 gss_prep_bulk_kerberos(struct gss_ctx *gctx,
1067                              struct ptlrpc_bulk_desc *desc)
1068 {
1069         struct krb5_ctx     *kctx = gctx->internal_ctx_id;
1070         int                  blocksize, i;
1071
1072         LASSERT(ptlrpc_is_bulk_desc_kiov(desc->bd_type));
1073         LASSERT(desc->bd_iov_count);
1074         LASSERT(GET_ENC_KIOV(desc));
1075         LASSERT(kctx->kc_keye.kb_tfm);
1076
1077         blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
1078
1079         for (i = 0; i < desc->bd_iov_count; i++) {
1080                 LASSERT(BD_GET_ENC_KIOV(desc, i).kiov_page);
1081                 /*
1082                  * offset should always start at page boundary of either
1083                  * client or server side.
1084                  */
1085                 if (BD_GET_KIOV(desc, i).kiov_offset & blocksize) {
1086                         CERROR("odd offset %d in page %d\n",
1087                                BD_GET_KIOV(desc, i).kiov_offset, i);
1088                         return GSS_S_FAILURE;
1089                 }
1090
1091                 BD_GET_ENC_KIOV(desc, i).kiov_offset =
1092                         BD_GET_KIOV(desc, i).kiov_offset;
1093                 BD_GET_ENC_KIOV(desc, i).kiov_len =
1094                         (BD_GET_KIOV(desc, i).kiov_len +
1095                          blocksize - 1) & (~(blocksize - 1));
1096         }
1097
1098         return GSS_S_COMPLETE;
1099 }
1100
1101 static
1102 __u32 gss_wrap_bulk_kerberos(struct gss_ctx *gctx,
1103                              struct ptlrpc_bulk_desc *desc,
1104                              rawobj_t *token, int adj_nob)
1105 {
1106         struct krb5_ctx     *kctx = gctx->internal_ctx_id;
1107         struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
1108         struct krb5_header  *khdr;
1109         int                  blocksize;
1110         rawobj_t             cksum = RAWOBJ_EMPTY;
1111         rawobj_t             data_desc[1], cipher;
1112         __u8                 conf[GSS_MAX_CIPHER_BLOCK];
1113         int                  rc = 0;
1114
1115         LASSERT(ptlrpc_is_bulk_desc_kiov(desc->bd_type));
1116         LASSERT(ke);
1117         LASSERT(ke->ke_conf_size <= GSS_MAX_CIPHER_BLOCK);
1118
1119         /*
1120          * final token format:
1121          * --------------------------------------------------
1122          * | krb5 header | head/tail cipher text | checksum |
1123          * --------------------------------------------------
1124          */
1125
1126         /* fill krb5 header */
1127         LASSERT(token->len >= sizeof(*khdr));
1128         khdr = (struct krb5_header *)token->data;
1129         fill_krb5_header(kctx, khdr, 1);
1130
1131         /* generate confounder */
1132         cfs_get_random_bytes(conf, ke->ke_conf_size);
1133
1134         /* get encryption blocksize. note kc_keye might not associated with
1135          * a tfm, currently only for arcfour-hmac */
1136         if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
1137                 LASSERT(kctx->kc_keye.kb_tfm == NULL);
1138                 blocksize = 1;
1139         } else {
1140                 LASSERT(kctx->kc_keye.kb_tfm);
1141                 blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
1142         }
1143
1144         /*
1145          * we assume the size of krb5_header (16 bytes) must be n * blocksize.
1146          * the bulk token size would be exactly (sizeof(krb5_header) +
1147          * blocksize + sizeof(krb5_header) + hashsize)
1148          */
1149         LASSERT(blocksize <= ke->ke_conf_size);
1150         LASSERT(sizeof(*khdr) >= blocksize && sizeof(*khdr) % blocksize == 0);
1151         LASSERT(token->len >= sizeof(*khdr) + blocksize + sizeof(*khdr) + 16);
1152
1153         /*
1154          * clear text layout for checksum:
1155          * ------------------------------------------
1156          * | confounder | clear pages | krb5 header |
1157          * ------------------------------------------
1158          */
1159         data_desc[0].data = conf;
1160         data_desc[0].len = ke->ke_conf_size;
1161
1162         /* compute checksum */
1163         if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi,
1164                                khdr, 1, data_desc,
1165                                desc->bd_iov_count, GET_KIOV(desc),
1166                                &cksum))
1167                 return GSS_S_FAILURE;
1168         LASSERT(cksum.len >= ke->ke_hash_size);
1169
1170         /*
1171          * clear text layout for encryption:
1172          * ------------------------------------------
1173          * | confounder | clear pages | krb5 header |
1174          * ------------------------------------------
1175          *        |              |             |
1176          *        ----------  (cipher pages)   |
1177          * result token:   |                   |
1178          * -------------------------------------------
1179          * | krb5 header | cipher text | cipher text |
1180          * -------------------------------------------
1181          */
1182         data_desc[0].data = conf;
1183         data_desc[0].len = ke->ke_conf_size;
1184
1185         cipher.data = (__u8 *)(khdr + 1);
1186         cipher.len = blocksize + sizeof(*khdr);
1187
1188         if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
1189                 LBUG();
1190                 rc = 0;
1191         } else {
1192                 rc = krb5_encrypt_bulk(kctx->kc_keye.kb_tfm, khdr,
1193                                        conf, desc, &cipher, adj_nob);
1194         }
1195
1196         if (rc != 0) {
1197                 rawobj_free(&cksum);
1198                 return GSS_S_FAILURE;
1199         }
1200
1201         /* fill in checksum */
1202         LASSERT(token->len >= sizeof(*khdr) + cipher.len + ke->ke_hash_size);
1203         memcpy((char *)(khdr + 1) + cipher.len,
1204                cksum.data + cksum.len - ke->ke_hash_size,
1205                ke->ke_hash_size);
1206         rawobj_free(&cksum);
1207
1208         /* final token length */
1209         token->len = sizeof(*khdr) + cipher.len + ke->ke_hash_size;
1210         return GSS_S_COMPLETE;
1211 }
1212
1213 static
1214 __u32 gss_unwrap_kerberos(struct gss_ctx  *gctx,
1215                           rawobj_t        *gsshdr,
1216                           rawobj_t        *token,
1217                           rawobj_t        *msg)
1218 {
1219         struct krb5_ctx     *kctx = gctx->internal_ctx_id;
1220         struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
1221         struct krb5_header  *khdr;
1222         unsigned char       *tmpbuf;
1223         int                  blocksize, bodysize;
1224         rawobj_t             cksum = RAWOBJ_EMPTY;
1225         rawobj_t             cipher_in, plain_out;
1226         rawobj_t             hash_objs[3];
1227         int                  rc = 0;
1228         __u32                major;
1229         __u8                 local_iv[16] = {0};
1230
1231         LASSERT(ke);
1232
1233         if (token->len < sizeof(*khdr)) {
1234                 CERROR("short signature: %u\n", token->len);
1235                 return GSS_S_DEFECTIVE_TOKEN;
1236         }
1237
1238         khdr = (struct krb5_header *)token->data;
1239
1240         major = verify_krb5_header(kctx, khdr, 1);
1241         if (major != GSS_S_COMPLETE) {
1242                 CERROR("bad krb5 header\n");
1243                 return major;
1244         }
1245
1246         /* block size */
1247         if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
1248                 LASSERT(kctx->kc_keye.kb_tfm == NULL);
1249                 blocksize = 1;
1250         } else {
1251                 LASSERT(kctx->kc_keye.kb_tfm);
1252                 blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
1253         }
1254
1255         /* expected token layout:
1256          * ----------------------------------------
1257          * | krb5 header | cipher text | checksum |
1258          * ----------------------------------------
1259          */
1260         bodysize = token->len - sizeof(*khdr) - ke->ke_hash_size;
1261
1262         if (bodysize % blocksize) {
1263                 CERROR("odd bodysize %d\n", bodysize);
1264                 return GSS_S_DEFECTIVE_TOKEN;
1265         }
1266
1267         if (bodysize <= ke->ke_conf_size + sizeof(*khdr)) {
1268                 CERROR("incomplete token: bodysize %d\n", bodysize);
1269                 return GSS_S_DEFECTIVE_TOKEN;
1270         }
1271
1272         if (msg->len < bodysize - ke->ke_conf_size - sizeof(*khdr)) {
1273                 CERROR("buffer too small: %u, require %d\n",
1274                        msg->len, bodysize - ke->ke_conf_size);
1275                 return GSS_S_FAILURE;
1276         }
1277
1278         /* decrypting */
1279         OBD_ALLOC_LARGE(tmpbuf, bodysize);
1280         if (!tmpbuf)
1281                 return GSS_S_FAILURE;
1282
1283         major = GSS_S_FAILURE;
1284
1285         cipher_in.data = (__u8 *)(khdr + 1);
1286         cipher_in.len = bodysize;
1287         plain_out.data = tmpbuf;
1288         plain_out.len = bodysize;
1289
1290         if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
1291                 rawobj_t                 arc4_keye;
1292                 struct crypto_blkcipher *arc4_tfm;
1293
1294                 cksum.data = token->data + token->len - ke->ke_hash_size;
1295                 cksum.len = ke->ke_hash_size;
1296
1297                 if (krb5_make_checksum(ENCTYPE_ARCFOUR_HMAC, &kctx->kc_keyi,
1298                                        NULL, 1, &cksum, 0, NULL, &arc4_keye)) {
1299                         CERROR("failed to obtain arc4 enc key\n");
1300                         GOTO(arc4_out, rc = -EACCES);
1301                 }
1302
1303                 arc4_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, 0);
1304                 if (IS_ERR(arc4_tfm)) {
1305                         CERROR("failed to alloc tfm arc4 in ECB mode\n");
1306                         GOTO(arc4_out_key, rc = -EACCES);
1307                 }
1308
1309                 if (crypto_blkcipher_setkey(arc4_tfm,
1310                                          arc4_keye.data, arc4_keye.len)) {
1311                         CERROR("failed to set arc4 key, len %d\n",
1312                                arc4_keye.len);
1313                         GOTO(arc4_out_tfm, rc = -EACCES);
1314                 }
1315
1316                 rc = gss_crypt_rawobjs(arc4_tfm, NULL, 1, &cipher_in,
1317                                        &plain_out, 0);
1318 arc4_out_tfm:
1319                 crypto_free_blkcipher(arc4_tfm);
1320 arc4_out_key:
1321                 rawobj_free(&arc4_keye);
1322 arc4_out:
1323                 cksum = RAWOBJ_EMPTY;
1324         } else {
1325                 rc = gss_crypt_rawobjs(kctx->kc_keye.kb_tfm, local_iv, 1,
1326                                        &cipher_in, &plain_out, 0);
1327         }
1328
1329         if (rc != 0) {
1330                 CERROR("error decrypt\n");
1331                 goto out_free;
1332         }
1333         LASSERT(plain_out.len == bodysize);
1334
1335         /* expected clear text layout:
1336          * -----------------------------------------
1337          * | confounder | clear msgs | krb5 header |
1338          * -----------------------------------------
1339          */
1340
1341         /* verify krb5 header in token is not modified */
1342         if (memcmp(khdr, plain_out.data + plain_out.len - sizeof(*khdr),
1343                    sizeof(*khdr))) {
1344                 CERROR("decrypted krb5 header mismatch\n");
1345                 goto out_free;
1346         }
1347
1348         /* verify checksum, compose clear text as layout:
1349          * ------------------------------------------------------
1350          * | confounder | gss header | clear msgs | krb5 header |
1351          * ------------------------------------------------------
1352          */
1353         hash_objs[0].len = ke->ke_conf_size;
1354         hash_objs[0].data = plain_out.data;
1355         hash_objs[1].len = gsshdr->len;
1356         hash_objs[1].data = gsshdr->data;
1357         hash_objs[2].len = plain_out.len - ke->ke_conf_size - sizeof(*khdr);
1358         hash_objs[2].data = plain_out.data + ke->ke_conf_size;
1359         if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi,
1360                                khdr, 3, hash_objs, 0, NULL, &cksum))
1361                 goto out_free;
1362
1363         LASSERT(cksum.len >= ke->ke_hash_size);
1364         if (memcmp((char *)(khdr + 1) + bodysize,
1365                    cksum.data + cksum.len - ke->ke_hash_size,
1366                    ke->ke_hash_size)) {
1367                 CERROR("checksum mismatch\n");
1368                 goto out_free;
1369         }
1370
1371         msg->len =  bodysize - ke->ke_conf_size - sizeof(*khdr);
1372         memcpy(msg->data, tmpbuf + ke->ke_conf_size, msg->len);
1373
1374         major = GSS_S_COMPLETE;
1375 out_free:
1376         OBD_FREE_LARGE(tmpbuf, bodysize);
1377         rawobj_free(&cksum);
1378         return major;
1379 }
1380
1381 static
1382 __u32 gss_unwrap_bulk_kerberos(struct gss_ctx *gctx,
1383                                struct ptlrpc_bulk_desc *desc,
1384                                rawobj_t *token, int adj_nob)
1385 {
1386         struct krb5_ctx     *kctx = gctx->internal_ctx_id;
1387         struct krb5_enctype *ke = &enctypes[kctx->kc_enctype];
1388         struct krb5_header  *khdr;
1389         int                  blocksize;
1390         rawobj_t             cksum = RAWOBJ_EMPTY;
1391         rawobj_t             cipher, plain;
1392         rawobj_t             data_desc[1];
1393         int                  rc;
1394         __u32                major;
1395
1396         LASSERT(ptlrpc_is_bulk_desc_kiov(desc->bd_type));
1397         LASSERT(ke);
1398
1399         if (token->len < sizeof(*khdr)) {
1400                 CERROR("short signature: %u\n", token->len);
1401                 return GSS_S_DEFECTIVE_TOKEN;
1402         }
1403
1404         khdr = (struct krb5_header *)token->data;
1405
1406         major = verify_krb5_header(kctx, khdr, 1);
1407         if (major != GSS_S_COMPLETE) {
1408                 CERROR("bad krb5 header\n");
1409                 return major;
1410         }
1411
1412         /* block size */
1413         if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
1414                 LASSERT(kctx->kc_keye.kb_tfm == NULL);
1415                 blocksize = 1;
1416                 LBUG();
1417         } else {
1418                 LASSERT(kctx->kc_keye.kb_tfm);
1419                 blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm);
1420         }
1421         LASSERT(sizeof(*khdr) >= blocksize && sizeof(*khdr) % blocksize == 0);
1422
1423         /*
1424          * token format is expected as:
1425          * -----------------------------------------------
1426          * | krb5 header | head/tail cipher text | cksum |
1427          * -----------------------------------------------
1428          */
1429         if (token->len < sizeof(*khdr) + blocksize + sizeof(*khdr) +
1430                          ke->ke_hash_size) {
1431                 CERROR("short token size: %u\n", token->len);
1432                 return GSS_S_DEFECTIVE_TOKEN;
1433         }
1434
1435         cipher.data = (__u8 *) (khdr + 1);
1436         cipher.len = blocksize + sizeof(*khdr);
1437         plain.data = cipher.data;
1438         plain.len = cipher.len;
1439
1440         rc = krb5_decrypt_bulk(kctx->kc_keye.kb_tfm, khdr,
1441                                desc, &cipher, &plain, adj_nob);
1442         if (rc)
1443                 return GSS_S_DEFECTIVE_TOKEN;
1444
1445         /*
1446          * verify checksum, compose clear text as layout:
1447          * ------------------------------------------
1448          * | confounder | clear pages | krb5 header |
1449          * ------------------------------------------
1450          */
1451         data_desc[0].data = plain.data;
1452         data_desc[0].len = blocksize;
1453
1454         if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi,
1455                                khdr, 1, data_desc,
1456                                desc->bd_iov_count,
1457                                GET_KIOV(desc),
1458                                &cksum))
1459                 return GSS_S_FAILURE;
1460         LASSERT(cksum.len >= ke->ke_hash_size);
1461
1462         if (memcmp(plain.data + blocksize + sizeof(*khdr),
1463                    cksum.data + cksum.len - ke->ke_hash_size,
1464                    ke->ke_hash_size)) {
1465                 CERROR("checksum mismatch\n");
1466                 rawobj_free(&cksum);
1467                 return GSS_S_BAD_SIG;
1468         }
1469
1470         rawobj_free(&cksum);
1471         return GSS_S_COMPLETE;
1472 }
1473
1474 int gss_display_kerberos(struct gss_ctx        *ctx,
1475                          char                  *buf,
1476                          int                    bufsize)
1477 {
1478         struct krb5_ctx    *kctx = ctx->internal_ctx_id;
1479         int                 written;
1480
1481         written = snprintf(buf, bufsize, "krb5 (%s)",
1482                            enctype2str(kctx->kc_enctype));
1483         return written;
1484 }
1485
1486 static struct gss_api_ops gss_kerberos_ops = {
1487         .gss_import_sec_context     = gss_import_sec_context_kerberos,
1488         .gss_copy_reverse_context   = gss_copy_reverse_context_kerberos,
1489         .gss_inquire_context        = gss_inquire_context_kerberos,
1490         .gss_get_mic                = gss_get_mic_kerberos,
1491         .gss_verify_mic             = gss_verify_mic_kerberos,
1492         .gss_wrap                   = gss_wrap_kerberos,
1493         .gss_unwrap                 = gss_unwrap_kerberos,
1494         .gss_prep_bulk              = gss_prep_bulk_kerberos,
1495         .gss_wrap_bulk              = gss_wrap_bulk_kerberos,
1496         .gss_unwrap_bulk            = gss_unwrap_bulk_kerberos,
1497         .gss_delete_sec_context     = gss_delete_sec_context_kerberos,
1498         .gss_display                = gss_display_kerberos,
1499 };
1500
1501 static struct subflavor_desc gss_kerberos_sfs[] = {
1502         {
1503                 .sf_subflavor   = SPTLRPC_SUBFLVR_KRB5N,
1504                 .sf_qop         = 0,
1505                 .sf_service     = SPTLRPC_SVC_NULL,
1506                 .sf_name        = "krb5n"
1507         },
1508         {
1509                 .sf_subflavor   = SPTLRPC_SUBFLVR_KRB5A,
1510                 .sf_qop         = 0,
1511                 .sf_service     = SPTLRPC_SVC_AUTH,
1512                 .sf_name        = "krb5a"
1513         },
1514         {
1515                 .sf_subflavor   = SPTLRPC_SUBFLVR_KRB5I,
1516                 .sf_qop         = 0,
1517                 .sf_service     = SPTLRPC_SVC_INTG,
1518                 .sf_name        = "krb5i"
1519         },
1520         {
1521                 .sf_subflavor   = SPTLRPC_SUBFLVR_KRB5P,
1522                 .sf_qop         = 0,
1523                 .sf_service     = SPTLRPC_SVC_PRIV,
1524                 .sf_name        = "krb5p"
1525         },
1526 };
1527
1528 static struct gss_api_mech gss_kerberos_mech = {
1529         /* .gm_owner uses default NULL value for THIS_MODULE */
1530         .gm_name        = "krb5",
1531         .gm_oid         = (rawobj_t)
1532                                 {9, "\052\206\110\206\367\022\001\002\002"},
1533         .gm_ops         = &gss_kerberos_ops,
1534         .gm_sf_num      = 4,
1535         .gm_sfs         = gss_kerberos_sfs,
1536 };
1537
1538 int __init init_kerberos_module(void)
1539 {
1540         int status;
1541
1542         spin_lock_init(&krb5_seq_lock);
1543
1544         status = lgss_mech_register(&gss_kerberos_mech);
1545         if (status)
1546                 CERROR("Failed to register kerberos gss mechanism!\n");
1547         return status;
1548 }
1549
1550 void cleanup_kerberos_module(void)
1551 {
1552         lgss_mech_unregister(&gss_kerberos_mech);
1553 }