Linux 6.10-rc2
[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         int ret;
402
403         p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
404         if (IS_ERR(p))
405                 goto out_err;
406         ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;
407
408         p = simple_get_bytes(p, end, &time32, sizeof(time32));
409         if (IS_ERR(p))
410                 goto out_err;
411         /* unsigned 32-bit time overflows in year 2106 */
412         ctx->endtime = (time64_t)time32;
413         p = simple_get_bytes(p, end, &seq_send64, sizeof(seq_send64));
414         if (IS_ERR(p))
415                 goto out_err;
416         atomic64_set(&ctx->seq_send64, seq_send64);
417         /* set seq_send for use by "older" enctypes */
418         atomic_set(&ctx->seq_send, seq_send64);
419         if (seq_send64 != atomic_read(&ctx->seq_send)) {
420                 dprintk("%s: seq_send64 %llx, seq_send %x overflow?\n", __func__,
421                         seq_send64, atomic_read(&ctx->seq_send));
422                 p = ERR_PTR(-EINVAL);
423                 goto out_err;
424         }
425         p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
426         if (IS_ERR(p))
427                 goto out_err;
428         ctx->gk5e = gss_krb5_lookup_enctype(ctx->enctype);
429         if (ctx->gk5e == NULL) {
430                 dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
431                         ctx->enctype);
432                 p = ERR_PTR(-EINVAL);
433                 goto out_err;
434         }
435         keylen = ctx->gk5e->keylength;
436
437         p = simple_get_bytes(p, end, ctx->Ksess, keylen);
438         if (IS_ERR(p))
439                 goto out_err;
440
441         if (p != end) {
442                 p = ERR_PTR(-EINVAL);
443                 goto out_err;
444         }
445
446         ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,
447                                       gss_kerberos_mech.gm_oid.len, gfp_mask);
448         if (unlikely(ctx->mech_used.data == NULL)) {
449                 p = ERR_PTR(-ENOMEM);
450                 goto out_err;
451         }
452         ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;
453
454         ret = gss_krb5_import_ctx_v2(ctx, gfp_mask);
455         if (ret) {
456                 p = ERR_PTR(ret);
457                 goto out_free;
458         }
459
460         return 0;
461
462 out_free:
463         kfree(ctx->mech_used.data);
464 out_err:
465         return PTR_ERR(p);
466 }
467
468 static int
469 gss_krb5_import_sec_context(const void *p, size_t len, struct gss_ctx *ctx_id,
470                             time64_t *endtime, gfp_t gfp_mask)
471 {
472         const void *end = (const void *)((const char *)p + len);
473         struct  krb5_ctx *ctx;
474         int ret;
475
476         ctx = kzalloc(sizeof(*ctx), gfp_mask);
477         if (ctx == NULL)
478                 return -ENOMEM;
479
480         ret = gss_import_v2_context(p, end, ctx, gfp_mask);
481         memzero_explicit(&ctx->Ksess, sizeof(ctx->Ksess));
482         if (ret) {
483                 kfree(ctx);
484                 return ret;
485         }
486
487         ctx_id->internal_ctx_id = ctx;
488         if (endtime)
489                 *endtime = ctx->endtime;
490         return 0;
491 }
492
493 static void
494 gss_krb5_delete_sec_context(void *internal_ctx)
495 {
496         struct krb5_ctx *kctx = internal_ctx;
497
498         crypto_free_sync_skcipher(kctx->seq);
499         crypto_free_sync_skcipher(kctx->enc);
500         crypto_free_sync_skcipher(kctx->acceptor_enc);
501         crypto_free_sync_skcipher(kctx->initiator_enc);
502         crypto_free_sync_skcipher(kctx->acceptor_enc_aux);
503         crypto_free_sync_skcipher(kctx->initiator_enc_aux);
504         crypto_free_ahash(kctx->acceptor_sign);
505         crypto_free_ahash(kctx->initiator_sign);
506         crypto_free_ahash(kctx->acceptor_integ);
507         crypto_free_ahash(kctx->initiator_integ);
508         kfree(kctx->mech_used.data);
509         kfree(kctx);
510 }
511
512 /**
513  * gss_krb5_get_mic - get_mic for the Kerberos GSS mechanism
514  * @gctx: GSS context
515  * @text: plaintext to checksum
516  * @token: buffer into which to write the computed checksum
517  *
518  * Return values:
519  *    %GSS_S_COMPLETE - success, and @token is filled in
520  *    %GSS_S_FAILURE - checksum could not be generated
521  *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
522  */
523 static u32 gss_krb5_get_mic(struct gss_ctx *gctx, struct xdr_buf *text,
524                             struct xdr_netobj *token)
525 {
526         struct krb5_ctx *kctx = gctx->internal_ctx_id;
527
528         return kctx->gk5e->get_mic(kctx, text, token);
529 }
530
531 /**
532  * gss_krb5_verify_mic - verify_mic for the Kerberos GSS mechanism
533  * @gctx: GSS context
534  * @message_buffer: plaintext to check
535  * @read_token: received checksum to check
536  *
537  * Return values:
538  *    %GSS_S_COMPLETE - computed and received checksums match
539  *    %GSS_S_DEFECTIVE_TOKEN - received checksum is not valid
540  *    %GSS_S_BAD_SIG - computed and received checksums do not match
541  *    %GSS_S_FAILURE - received checksum could not be checked
542  *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
543  */
544 static u32 gss_krb5_verify_mic(struct gss_ctx *gctx,
545                                struct xdr_buf *message_buffer,
546                                struct xdr_netobj *read_token)
547 {
548         struct krb5_ctx *kctx = gctx->internal_ctx_id;
549
550         return kctx->gk5e->verify_mic(kctx, message_buffer, read_token);
551 }
552
553 /**
554  * gss_krb5_wrap - gss_wrap for the Kerberos GSS mechanism
555  * @gctx: initialized GSS context
556  * @offset: byte offset in @buf to start writing the cipher text
557  * @buf: OUT: send buffer
558  * @pages: plaintext to wrap
559  *
560  * Return values:
561  *    %GSS_S_COMPLETE - success, @buf has been updated
562  *    %GSS_S_FAILURE - @buf could not be wrapped
563  *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
564  */
565 static u32 gss_krb5_wrap(struct gss_ctx *gctx, int offset,
566                          struct xdr_buf *buf, struct page **pages)
567 {
568         struct krb5_ctx *kctx = gctx->internal_ctx_id;
569
570         return kctx->gk5e->wrap(kctx, offset, buf, pages);
571 }
572
573 /**
574  * gss_krb5_unwrap - gss_unwrap for the Kerberos GSS mechanism
575  * @gctx: initialized GSS context
576  * @offset: starting byte offset into @buf
577  * @len: size of ciphertext to unwrap
578  * @buf: ciphertext to unwrap
579  *
580  * Return values:
581  *    %GSS_S_COMPLETE - success, @buf has been updated
582  *    %GSS_S_DEFECTIVE_TOKEN - received blob is not valid
583  *    %GSS_S_BAD_SIG - computed and received checksums do not match
584  *    %GSS_S_FAILURE - @buf could not be unwrapped
585  *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
586  */
587 static u32 gss_krb5_unwrap(struct gss_ctx *gctx, int offset,
588                            int len, struct xdr_buf *buf)
589 {
590         struct krb5_ctx *kctx = gctx->internal_ctx_id;
591
592         return kctx->gk5e->unwrap(kctx, offset, len, buf,
593                                   &gctx->slack, &gctx->align);
594 }
595
596 static const struct gss_api_ops gss_kerberos_ops = {
597         .gss_import_sec_context = gss_krb5_import_sec_context,
598         .gss_get_mic            = gss_krb5_get_mic,
599         .gss_verify_mic         = gss_krb5_verify_mic,
600         .gss_wrap               = gss_krb5_wrap,
601         .gss_unwrap             = gss_krb5_unwrap,
602         .gss_delete_sec_context = gss_krb5_delete_sec_context,
603 };
604
605 static struct pf_desc gss_kerberos_pfs[] = {
606         [0] = {
607                 .pseudoflavor = RPC_AUTH_GSS_KRB5,
608                 .qop = GSS_C_QOP_DEFAULT,
609                 .service = RPC_GSS_SVC_NONE,
610                 .name = "krb5",
611         },
612         [1] = {
613                 .pseudoflavor = RPC_AUTH_GSS_KRB5I,
614                 .qop = GSS_C_QOP_DEFAULT,
615                 .service = RPC_GSS_SVC_INTEGRITY,
616                 .name = "krb5i",
617                 .datatouch = true,
618         },
619         [2] = {
620                 .pseudoflavor = RPC_AUTH_GSS_KRB5P,
621                 .qop = GSS_C_QOP_DEFAULT,
622                 .service = RPC_GSS_SVC_PRIVACY,
623                 .name = "krb5p",
624                 .datatouch = true,
625         },
626 };
627
628 MODULE_ALIAS("rpc-auth-gss-krb5");
629 MODULE_ALIAS("rpc-auth-gss-krb5i");
630 MODULE_ALIAS("rpc-auth-gss-krb5p");
631 MODULE_ALIAS("rpc-auth-gss-390003");
632 MODULE_ALIAS("rpc-auth-gss-390004");
633 MODULE_ALIAS("rpc-auth-gss-390005");
634 MODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");
635
636 static struct gss_api_mech gss_kerberos_mech = {
637         .gm_name        = "krb5",
638         .gm_owner       = THIS_MODULE,
639         .gm_oid         = { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },
640         .gm_ops         = &gss_kerberos_ops,
641         .gm_pf_num      = ARRAY_SIZE(gss_kerberos_pfs),
642         .gm_pfs         = gss_kerberos_pfs,
643         .gm_upcall_enctypes = gss_krb5_enctype_priority_list,
644 };
645
646 static int __init init_kerberos_module(void)
647 {
648         int status;
649
650         gss_krb5_prepare_enctype_priority_list();
651         status = gss_mech_register(&gss_kerberos_mech);
652         if (status)
653                 printk("Failed to register kerberos gss mechanism!\n");
654         return status;
655 }
656
657 static void __exit cleanup_kerberos_module(void)
658 {
659         gss_mech_unregister(&gss_kerberos_mech);
660 }
661
662 MODULE_DESCRIPTION("Sun RPC Kerberos 5 module");
663 MODULE_LICENSE("GPL");
664 module_init(init_kerberos_module);
665 module_exit(cleanup_kerberos_module);