Merge tag 'landlock-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic...
[sfrench/cifs-2.6.git] / net / sunrpc / auth_gss / gss_krb5_mech.c
1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  *  linux/net/sunrpc/gss_krb5_mech.c
4  *
5  *  Copyright (c) 2001-2008 The Regents of the University of Michigan.
6  *  All rights reserved.
7  *
8  *  Andy Adamson <andros@umich.edu>
9  *  J. Bruce Fields <bfields@umich.edu>
10  */
11
12 #include <crypto/hash.h>
13 #include <crypto/skcipher.h>
14 #include <linux/err.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/types.h>
18 #include <linux/slab.h>
19 #include <linux/sunrpc/auth.h>
20 #include <linux/sunrpc/gss_krb5.h>
21 #include <linux/sunrpc/xdr.h>
22 #include <kunit/visibility.h>
23
24 #include "auth_gss_internal.h"
25 #include "gss_krb5_internal.h"
26
27 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
28 # define RPCDBG_FACILITY        RPCDBG_AUTH
29 #endif
30
31 static struct gss_api_mech gss_kerberos_mech;
32
33 static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
34 #if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1)
35         /*
36          * AES-128 with SHA-1 (RFC 3962)
37          */
38         {
39           .etype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
40           .ctype = CKSUMTYPE_HMAC_SHA1_96_AES128,
41           .name = "aes128-cts",
42           .encrypt_name = "cts(cbc(aes))",
43           .aux_cipher = "cbc(aes)",
44           .cksum_name = "hmac(sha1)",
45           .derive_key = krb5_derive_key_v2,
46           .encrypt = gss_krb5_aes_encrypt,
47           .decrypt = gss_krb5_aes_decrypt,
48
49           .get_mic = gss_krb5_get_mic_v2,
50           .verify_mic = gss_krb5_verify_mic_v2,
51           .wrap = gss_krb5_wrap_v2,
52           .unwrap = gss_krb5_unwrap_v2,
53
54           .signalg = -1,
55           .sealalg = -1,
56           .keybytes = 16,
57           .keylength = BITS2OCTETS(128),
58           .Kc_length = BITS2OCTETS(128),
59           .Ke_length = BITS2OCTETS(128),
60           .Ki_length = BITS2OCTETS(128),
61           .cksumlength = BITS2OCTETS(96),
62           .keyed_cksum = 1,
63         },
64         /*
65          * AES-256 with SHA-1 (RFC 3962)
66          */
67         {
68           .etype = ENCTYPE_AES256_CTS_HMAC_SHA1_96,
69           .ctype = CKSUMTYPE_HMAC_SHA1_96_AES256,
70           .name = "aes256-cts",
71           .encrypt_name = "cts(cbc(aes))",
72           .aux_cipher = "cbc(aes)",
73           .cksum_name = "hmac(sha1)",
74           .derive_key = krb5_derive_key_v2,
75           .encrypt = gss_krb5_aes_encrypt,
76           .decrypt = gss_krb5_aes_decrypt,
77
78           .get_mic = gss_krb5_get_mic_v2,
79           .verify_mic = gss_krb5_verify_mic_v2,
80           .wrap = gss_krb5_wrap_v2,
81           .unwrap = gss_krb5_unwrap_v2,
82
83           .signalg = -1,
84           .sealalg = -1,
85           .keybytes = 32,
86           .keylength = BITS2OCTETS(256),
87           .Kc_length = BITS2OCTETS(256),
88           .Ke_length = BITS2OCTETS(256),
89           .Ki_length = BITS2OCTETS(256),
90           .cksumlength = BITS2OCTETS(96),
91           .keyed_cksum = 1,
92         },
93 #endif
94
95 #if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA)
96         /*
97          * Camellia-128 with CMAC (RFC 6803)
98          */
99         {
100                 .etype          = ENCTYPE_CAMELLIA128_CTS_CMAC,
101                 .ctype          = CKSUMTYPE_CMAC_CAMELLIA128,
102                 .name           = "camellia128-cts-cmac",
103                 .encrypt_name   = "cts(cbc(camellia))",
104                 .aux_cipher     = "cbc(camellia)",
105                 .cksum_name     = "cmac(camellia)",
106                 .cksumlength    = BITS2OCTETS(128),
107                 .keyed_cksum    = 1,
108                 .keylength      = BITS2OCTETS(128),
109                 .Kc_length      = BITS2OCTETS(128),
110                 .Ke_length      = BITS2OCTETS(128),
111                 .Ki_length      = BITS2OCTETS(128),
112
113                 .derive_key     = krb5_kdf_feedback_cmac,
114                 .encrypt        = gss_krb5_aes_encrypt,
115                 .decrypt        = gss_krb5_aes_decrypt,
116
117                 .get_mic        = gss_krb5_get_mic_v2,
118                 .verify_mic     = gss_krb5_verify_mic_v2,
119                 .wrap           = gss_krb5_wrap_v2,
120                 .unwrap         = gss_krb5_unwrap_v2,
121         },
122         /*
123          * Camellia-256 with CMAC (RFC 6803)
124          */
125         {
126                 .etype          = ENCTYPE_CAMELLIA256_CTS_CMAC,
127                 .ctype          = CKSUMTYPE_CMAC_CAMELLIA256,
128                 .name           = "camellia256-cts-cmac",
129                 .encrypt_name   = "cts(cbc(camellia))",
130                 .aux_cipher     = "cbc(camellia)",
131                 .cksum_name     = "cmac(camellia)",
132                 .cksumlength    = BITS2OCTETS(128),
133                 .keyed_cksum    = 1,
134                 .keylength      = BITS2OCTETS(256),
135                 .Kc_length      = BITS2OCTETS(256),
136                 .Ke_length      = BITS2OCTETS(256),
137                 .Ki_length      = BITS2OCTETS(256),
138
139                 .derive_key     = krb5_kdf_feedback_cmac,
140                 .encrypt        = gss_krb5_aes_encrypt,
141                 .decrypt        = gss_krb5_aes_decrypt,
142
143                 .get_mic        = gss_krb5_get_mic_v2,
144                 .verify_mic     = gss_krb5_verify_mic_v2,
145                 .wrap           = gss_krb5_wrap_v2,
146                 .unwrap         = gss_krb5_unwrap_v2,
147         },
148 #endif
149
150 #if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2)
151         /*
152          * AES-128 with SHA-256 (RFC 8009)
153          */
154         {
155                 .etype          = ENCTYPE_AES128_CTS_HMAC_SHA256_128,
156                 .ctype          = CKSUMTYPE_HMAC_SHA256_128_AES128,
157                 .name           = "aes128-cts-hmac-sha256-128",
158                 .encrypt_name   = "cts(cbc(aes))",
159                 .aux_cipher     = "cbc(aes)",
160                 .cksum_name     = "hmac(sha256)",
161                 .cksumlength    = BITS2OCTETS(128),
162                 .keyed_cksum    = 1,
163                 .keylength      = BITS2OCTETS(128),
164                 .Kc_length      = BITS2OCTETS(128),
165                 .Ke_length      = BITS2OCTETS(128),
166                 .Ki_length      = BITS2OCTETS(128),
167
168                 .derive_key     = krb5_kdf_hmac_sha2,
169                 .encrypt        = krb5_etm_encrypt,
170                 .decrypt        = krb5_etm_decrypt,
171
172                 .get_mic        = gss_krb5_get_mic_v2,
173                 .verify_mic     = gss_krb5_verify_mic_v2,
174                 .wrap           = gss_krb5_wrap_v2,
175                 .unwrap         = gss_krb5_unwrap_v2,
176         },
177         /*
178          * AES-256 with SHA-384 (RFC 8009)
179          */
180         {
181                 .etype          = ENCTYPE_AES256_CTS_HMAC_SHA384_192,
182                 .ctype          = CKSUMTYPE_HMAC_SHA384_192_AES256,
183                 .name           = "aes256-cts-hmac-sha384-192",
184                 .encrypt_name   = "cts(cbc(aes))",
185                 .aux_cipher     = "cbc(aes)",
186                 .cksum_name     = "hmac(sha384)",
187                 .cksumlength    = BITS2OCTETS(192),
188                 .keyed_cksum    = 1,
189                 .keylength      = BITS2OCTETS(256),
190                 .Kc_length      = BITS2OCTETS(192),
191                 .Ke_length      = BITS2OCTETS(256),
192                 .Ki_length      = BITS2OCTETS(192),
193
194                 .derive_key     = krb5_kdf_hmac_sha2,
195                 .encrypt        = krb5_etm_encrypt,
196                 .decrypt        = krb5_etm_decrypt,
197
198                 .get_mic        = gss_krb5_get_mic_v2,
199                 .verify_mic     = gss_krb5_verify_mic_v2,
200                 .wrap           = gss_krb5_wrap_v2,
201                 .unwrap         = gss_krb5_unwrap_v2,
202         },
203 #endif
204 };
205
206 /*
207  * The list of advertised enctypes is specified in order of most
208  * preferred to least.
209  */
210 static char gss_krb5_enctype_priority_list[64];
211
212 static void gss_krb5_prepare_enctype_priority_list(void)
213 {
214         static const u32 gss_krb5_enctypes[] = {
215 #if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2)
216                 ENCTYPE_AES256_CTS_HMAC_SHA384_192,
217                 ENCTYPE_AES128_CTS_HMAC_SHA256_128,
218 #endif
219 #if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA)
220                 ENCTYPE_CAMELLIA256_CTS_CMAC,
221                 ENCTYPE_CAMELLIA128_CTS_CMAC,
222 #endif
223 #if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1)
224                 ENCTYPE_AES256_CTS_HMAC_SHA1_96,
225                 ENCTYPE_AES128_CTS_HMAC_SHA1_96,
226 #endif
227         };
228         size_t total, i;
229         char buf[16];
230         char *sep;
231         int n;
232
233         sep = "";
234         gss_krb5_enctype_priority_list[0] = '\0';
235         for (total = 0, i = 0; i < ARRAY_SIZE(gss_krb5_enctypes); i++) {
236                 n = sprintf(buf, "%s%u", sep, gss_krb5_enctypes[i]);
237                 if (n < 0)
238                         break;
239                 if (total + n >= sizeof(gss_krb5_enctype_priority_list))
240                         break;
241                 strcat(gss_krb5_enctype_priority_list, buf);
242                 sep = ",";
243                 total += n;
244         }
245 }
246
247 /**
248  * gss_krb5_lookup_enctype - Retrieve profile information for a given enctype
249  * @etype: ENCTYPE value
250  *
251  * Returns a pointer to a gss_krb5_enctype structure, or NULL if no
252  * matching etype is found.
253  */
254 VISIBLE_IF_KUNIT
255 const struct gss_krb5_enctype *gss_krb5_lookup_enctype(u32 etype)
256 {
257         size_t i;
258
259         for (i = 0; i < ARRAY_SIZE(supported_gss_krb5_enctypes); i++)
260                 if (supported_gss_krb5_enctypes[i].etype == etype)
261                         return &supported_gss_krb5_enctypes[i];
262         return NULL;
263 }
264 EXPORT_SYMBOL_IF_KUNIT(gss_krb5_lookup_enctype);
265
266 static struct crypto_sync_skcipher *
267 gss_krb5_alloc_cipher_v2(const char *cname, const struct xdr_netobj *key)
268 {
269         struct crypto_sync_skcipher *tfm;
270
271         tfm = crypto_alloc_sync_skcipher(cname, 0, 0);
272         if (IS_ERR(tfm))
273                 return NULL;
274         if (crypto_sync_skcipher_setkey(tfm, key->data, key->len)) {
275                 crypto_free_sync_skcipher(tfm);
276                 return NULL;
277         }
278         return tfm;
279 }
280
281 static struct crypto_ahash *
282 gss_krb5_alloc_hash_v2(struct krb5_ctx *kctx, const struct xdr_netobj *key)
283 {
284         struct crypto_ahash *tfm;
285
286         tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
287         if (IS_ERR(tfm))
288                 return NULL;
289         if (crypto_ahash_setkey(tfm, key->data, key->len)) {
290                 crypto_free_ahash(tfm);
291                 return NULL;
292         }
293         return tfm;
294 }
295
296 static int
297 gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask)
298 {
299         struct xdr_netobj keyin = {
300                 .len    = ctx->gk5e->keylength,
301                 .data   = ctx->Ksess,
302         };
303         struct xdr_netobj keyout;
304         int ret = -EINVAL;
305
306         keyout.data = kmalloc(GSS_KRB5_MAX_KEYLEN, gfp_mask);
307         if (!keyout.data)
308                 return -ENOMEM;
309
310         /* initiator seal encryption */
311         keyout.len = ctx->gk5e->Ke_length;
312         if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_INITIATOR_SEAL,
313                             KEY_USAGE_SEED_ENCRYPTION, gfp_mask))
314                 goto out;
315         ctx->initiator_enc = gss_krb5_alloc_cipher_v2(ctx->gk5e->encrypt_name,
316                                                       &keyout);
317         if (ctx->initiator_enc == NULL)
318                 goto out;
319         if (ctx->gk5e->aux_cipher) {
320                 ctx->initiator_enc_aux =
321                         gss_krb5_alloc_cipher_v2(ctx->gk5e->aux_cipher,
322                                                  &keyout);
323                 if (ctx->initiator_enc_aux == NULL)
324                         goto out_free;
325         }
326
327         /* acceptor seal encryption */
328         if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_ACCEPTOR_SEAL,
329                             KEY_USAGE_SEED_ENCRYPTION, gfp_mask))
330                 goto out_free;
331         ctx->acceptor_enc = gss_krb5_alloc_cipher_v2(ctx->gk5e->encrypt_name,
332                                                      &keyout);
333         if (ctx->acceptor_enc == NULL)
334                 goto out_free;
335         if (ctx->gk5e->aux_cipher) {
336                 ctx->acceptor_enc_aux =
337                         gss_krb5_alloc_cipher_v2(ctx->gk5e->aux_cipher,
338                                                  &keyout);
339                 if (ctx->acceptor_enc_aux == NULL)
340                         goto out_free;
341         }
342
343         /* initiator sign checksum */
344         keyout.len = ctx->gk5e->Kc_length;
345         if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_INITIATOR_SIGN,
346                             KEY_USAGE_SEED_CHECKSUM, gfp_mask))
347                 goto out_free;
348         ctx->initiator_sign = gss_krb5_alloc_hash_v2(ctx, &keyout);
349         if (ctx->initiator_sign == NULL)
350                 goto out_free;
351
352         /* acceptor sign checksum */
353         if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_ACCEPTOR_SIGN,
354                             KEY_USAGE_SEED_CHECKSUM, gfp_mask))
355                 goto out_free;
356         ctx->acceptor_sign = gss_krb5_alloc_hash_v2(ctx, &keyout);
357         if (ctx->acceptor_sign == NULL)
358                 goto out_free;
359
360         /* initiator seal integrity */
361         keyout.len = ctx->gk5e->Ki_length;
362         if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_INITIATOR_SEAL,
363                             KEY_USAGE_SEED_INTEGRITY, gfp_mask))
364                 goto out_free;
365         ctx->initiator_integ = gss_krb5_alloc_hash_v2(ctx, &keyout);
366         if (ctx->initiator_integ == NULL)
367                 goto out_free;
368
369         /* acceptor seal integrity */
370         if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_ACCEPTOR_SEAL,
371                             KEY_USAGE_SEED_INTEGRITY, gfp_mask))
372                 goto out_free;
373         ctx->acceptor_integ = gss_krb5_alloc_hash_v2(ctx, &keyout);
374         if (ctx->acceptor_integ == NULL)
375                 goto out_free;
376
377         ret = 0;
378 out:
379         kfree_sensitive(keyout.data);
380         return ret;
381
382 out_free:
383         crypto_free_ahash(ctx->acceptor_integ);
384         crypto_free_ahash(ctx->initiator_integ);
385         crypto_free_ahash(ctx->acceptor_sign);
386         crypto_free_ahash(ctx->initiator_sign);
387         crypto_free_sync_skcipher(ctx->acceptor_enc_aux);
388         crypto_free_sync_skcipher(ctx->acceptor_enc);
389         crypto_free_sync_skcipher(ctx->initiator_enc_aux);
390         crypto_free_sync_skcipher(ctx->initiator_enc);
391         goto out;
392 }
393
394 static int
395 gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
396                 gfp_t gfp_mask)
397 {
398         u64 seq_send64;
399         int keylen;
400         u32 time32;
401
402         p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
403         if (IS_ERR(p))
404                 goto out_err;
405         ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;
406
407         p = simple_get_bytes(p, end, &time32, sizeof(time32));
408         if (IS_ERR(p))
409                 goto out_err;
410         /* unsigned 32-bit time overflows in year 2106 */
411         ctx->endtime = (time64_t)time32;
412         p = simple_get_bytes(p, end, &seq_send64, sizeof(seq_send64));
413         if (IS_ERR(p))
414                 goto out_err;
415         atomic64_set(&ctx->seq_send64, seq_send64);
416         /* set seq_send for use by "older" enctypes */
417         atomic_set(&ctx->seq_send, seq_send64);
418         if (seq_send64 != atomic_read(&ctx->seq_send)) {
419                 dprintk("%s: seq_send64 %llx, seq_send %x overflow?\n", __func__,
420                         seq_send64, atomic_read(&ctx->seq_send));
421                 p = ERR_PTR(-EINVAL);
422                 goto out_err;
423         }
424         p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
425         if (IS_ERR(p))
426                 goto out_err;
427         ctx->gk5e = gss_krb5_lookup_enctype(ctx->enctype);
428         if (ctx->gk5e == NULL) {
429                 dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
430                         ctx->enctype);
431                 p = ERR_PTR(-EINVAL);
432                 goto out_err;
433         }
434         keylen = ctx->gk5e->keylength;
435
436         p = simple_get_bytes(p, end, ctx->Ksess, keylen);
437         if (IS_ERR(p))
438                 goto out_err;
439
440         if (p != end) {
441                 p = ERR_PTR(-EINVAL);
442                 goto out_err;
443         }
444
445         ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,
446                                       gss_kerberos_mech.gm_oid.len, gfp_mask);
447         if (unlikely(ctx->mech_used.data == NULL)) {
448                 p = ERR_PTR(-ENOMEM);
449                 goto out_err;
450         }
451         ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;
452
453         return gss_krb5_import_ctx_v2(ctx, gfp_mask);
454
455 out_err:
456         return PTR_ERR(p);
457 }
458
459 static int
460 gss_krb5_import_sec_context(const void *p, size_t len, struct gss_ctx *ctx_id,
461                             time64_t *endtime, gfp_t gfp_mask)
462 {
463         const void *end = (const void *)((const char *)p + len);
464         struct  krb5_ctx *ctx;
465         int ret;
466
467         ctx = kzalloc(sizeof(*ctx), gfp_mask);
468         if (ctx == NULL)
469                 return -ENOMEM;
470
471         ret = gss_import_v2_context(p, end, ctx, gfp_mask);
472         memzero_explicit(&ctx->Ksess, sizeof(ctx->Ksess));
473         if (ret) {
474                 kfree(ctx);
475                 return ret;
476         }
477
478         ctx_id->internal_ctx_id = ctx;
479         if (endtime)
480                 *endtime = ctx->endtime;
481         return 0;
482 }
483
484 static void
485 gss_krb5_delete_sec_context(void *internal_ctx)
486 {
487         struct krb5_ctx *kctx = internal_ctx;
488
489         crypto_free_sync_skcipher(kctx->seq);
490         crypto_free_sync_skcipher(kctx->enc);
491         crypto_free_sync_skcipher(kctx->acceptor_enc);
492         crypto_free_sync_skcipher(kctx->initiator_enc);
493         crypto_free_sync_skcipher(kctx->acceptor_enc_aux);
494         crypto_free_sync_skcipher(kctx->initiator_enc_aux);
495         crypto_free_ahash(kctx->acceptor_sign);
496         crypto_free_ahash(kctx->initiator_sign);
497         crypto_free_ahash(kctx->acceptor_integ);
498         crypto_free_ahash(kctx->initiator_integ);
499         kfree(kctx->mech_used.data);
500         kfree(kctx);
501 }
502
503 /**
504  * gss_krb5_get_mic - get_mic for the Kerberos GSS mechanism
505  * @gctx: GSS context
506  * @text: plaintext to checksum
507  * @token: buffer into which to write the computed checksum
508  *
509  * Return values:
510  *    %GSS_S_COMPLETE - success, and @token is filled in
511  *    %GSS_S_FAILURE - checksum could not be generated
512  *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
513  */
514 static u32 gss_krb5_get_mic(struct gss_ctx *gctx, struct xdr_buf *text,
515                             struct xdr_netobj *token)
516 {
517         struct krb5_ctx *kctx = gctx->internal_ctx_id;
518
519         return kctx->gk5e->get_mic(kctx, text, token);
520 }
521
522 /**
523  * gss_krb5_verify_mic - verify_mic for the Kerberos GSS mechanism
524  * @gctx: GSS context
525  * @message_buffer: plaintext to check
526  * @read_token: received checksum to check
527  *
528  * Return values:
529  *    %GSS_S_COMPLETE - computed and received checksums match
530  *    %GSS_S_DEFECTIVE_TOKEN - received checksum is not valid
531  *    %GSS_S_BAD_SIG - computed and received checksums do not match
532  *    %GSS_S_FAILURE - received checksum could not be checked
533  *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
534  */
535 static u32 gss_krb5_verify_mic(struct gss_ctx *gctx,
536                                struct xdr_buf *message_buffer,
537                                struct xdr_netobj *read_token)
538 {
539         struct krb5_ctx *kctx = gctx->internal_ctx_id;
540
541         return kctx->gk5e->verify_mic(kctx, message_buffer, read_token);
542 }
543
544 /**
545  * gss_krb5_wrap - gss_wrap for the Kerberos GSS mechanism
546  * @gctx: initialized GSS context
547  * @offset: byte offset in @buf to start writing the cipher text
548  * @buf: OUT: send buffer
549  * @pages: plaintext to wrap
550  *
551  * Return values:
552  *    %GSS_S_COMPLETE - success, @buf has been updated
553  *    %GSS_S_FAILURE - @buf could not be wrapped
554  *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
555  */
556 static u32 gss_krb5_wrap(struct gss_ctx *gctx, int offset,
557                          struct xdr_buf *buf, struct page **pages)
558 {
559         struct krb5_ctx *kctx = gctx->internal_ctx_id;
560
561         return kctx->gk5e->wrap(kctx, offset, buf, pages);
562 }
563
564 /**
565  * gss_krb5_unwrap - gss_unwrap for the Kerberos GSS mechanism
566  * @gctx: initialized GSS context
567  * @offset: starting byte offset into @buf
568  * @len: size of ciphertext to unwrap
569  * @buf: ciphertext to unwrap
570  *
571  * Return values:
572  *    %GSS_S_COMPLETE - success, @buf has been updated
573  *    %GSS_S_DEFECTIVE_TOKEN - received blob is not valid
574  *    %GSS_S_BAD_SIG - computed and received checksums do not match
575  *    %GSS_S_FAILURE - @buf could not be unwrapped
576  *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
577  */
578 static u32 gss_krb5_unwrap(struct gss_ctx *gctx, int offset,
579                            int len, struct xdr_buf *buf)
580 {
581         struct krb5_ctx *kctx = gctx->internal_ctx_id;
582
583         return kctx->gk5e->unwrap(kctx, offset, len, buf,
584                                   &gctx->slack, &gctx->align);
585 }
586
587 static const struct gss_api_ops gss_kerberos_ops = {
588         .gss_import_sec_context = gss_krb5_import_sec_context,
589         .gss_get_mic            = gss_krb5_get_mic,
590         .gss_verify_mic         = gss_krb5_verify_mic,
591         .gss_wrap               = gss_krb5_wrap,
592         .gss_unwrap             = gss_krb5_unwrap,
593         .gss_delete_sec_context = gss_krb5_delete_sec_context,
594 };
595
596 static struct pf_desc gss_kerberos_pfs[] = {
597         [0] = {
598                 .pseudoflavor = RPC_AUTH_GSS_KRB5,
599                 .qop = GSS_C_QOP_DEFAULT,
600                 .service = RPC_GSS_SVC_NONE,
601                 .name = "krb5",
602         },
603         [1] = {
604                 .pseudoflavor = RPC_AUTH_GSS_KRB5I,
605                 .qop = GSS_C_QOP_DEFAULT,
606                 .service = RPC_GSS_SVC_INTEGRITY,
607                 .name = "krb5i",
608                 .datatouch = true,
609         },
610         [2] = {
611                 .pseudoflavor = RPC_AUTH_GSS_KRB5P,
612                 .qop = GSS_C_QOP_DEFAULT,
613                 .service = RPC_GSS_SVC_PRIVACY,
614                 .name = "krb5p",
615                 .datatouch = true,
616         },
617 };
618
619 MODULE_ALIAS("rpc-auth-gss-krb5");
620 MODULE_ALIAS("rpc-auth-gss-krb5i");
621 MODULE_ALIAS("rpc-auth-gss-krb5p");
622 MODULE_ALIAS("rpc-auth-gss-390003");
623 MODULE_ALIAS("rpc-auth-gss-390004");
624 MODULE_ALIAS("rpc-auth-gss-390005");
625 MODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");
626
627 static struct gss_api_mech gss_kerberos_mech = {
628         .gm_name        = "krb5",
629         .gm_owner       = THIS_MODULE,
630         .gm_oid         = { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },
631         .gm_ops         = &gss_kerberos_ops,
632         .gm_pf_num      = ARRAY_SIZE(gss_kerberos_pfs),
633         .gm_pfs         = gss_kerberos_pfs,
634         .gm_upcall_enctypes = gss_krb5_enctype_priority_list,
635 };
636
637 static int __init init_kerberos_module(void)
638 {
639         int status;
640
641         gss_krb5_prepare_enctype_priority_list();
642         status = gss_mech_register(&gss_kerberos_mech);
643         if (status)
644                 printk("Failed to register kerberos gss mechanism!\n");
645         return status;
646 }
647
648 static void __exit cleanup_kerberos_module(void)
649 {
650         gss_mech_unregister(&gss_kerberos_mech);
651 }
652
653 MODULE_LICENSE("GPL");
654 module_init(init_kerberos_module);
655 module_exit(cleanup_kerberos_module);