162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  linux/net/sunrpc/gss_krb5_mech.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (c) 2001-2008 The Regents of the University of Michigan.
662306a36Sopenharmony_ci *  All rights reserved.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *  Andy Adamson <andros@umich.edu>
962306a36Sopenharmony_ci *  J. Bruce Fields <bfields@umich.edu>
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <crypto/hash.h>
1362306a36Sopenharmony_ci#include <crypto/skcipher.h>
1462306a36Sopenharmony_ci#include <linux/err.h>
1562306a36Sopenharmony_ci#include <linux/module.h>
1662306a36Sopenharmony_ci#include <linux/init.h>
1762306a36Sopenharmony_ci#include <linux/types.h>
1862306a36Sopenharmony_ci#include <linux/slab.h>
1962306a36Sopenharmony_ci#include <linux/sunrpc/auth.h>
2062306a36Sopenharmony_ci#include <linux/sunrpc/gss_krb5.h>
2162306a36Sopenharmony_ci#include <linux/sunrpc/xdr.h>
2262306a36Sopenharmony_ci#include <kunit/visibility.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#include "auth_gss_internal.h"
2562306a36Sopenharmony_ci#include "gss_krb5_internal.h"
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
2862306a36Sopenharmony_ci# define RPCDBG_FACILITY	RPCDBG_AUTH
2962306a36Sopenharmony_ci#endif
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic struct gss_api_mech gss_kerberos_mech;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistatic const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
3462306a36Sopenharmony_ci#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1)
3562306a36Sopenharmony_ci	/*
3662306a36Sopenharmony_ci	 * AES-128 with SHA-1 (RFC 3962)
3762306a36Sopenharmony_ci	 */
3862306a36Sopenharmony_ci	{
3962306a36Sopenharmony_ci	  .etype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
4062306a36Sopenharmony_ci	  .ctype = CKSUMTYPE_HMAC_SHA1_96_AES128,
4162306a36Sopenharmony_ci	  .name = "aes128-cts",
4262306a36Sopenharmony_ci	  .encrypt_name = "cts(cbc(aes))",
4362306a36Sopenharmony_ci	  .aux_cipher = "cbc(aes)",
4462306a36Sopenharmony_ci	  .cksum_name = "hmac(sha1)",
4562306a36Sopenharmony_ci	  .derive_key = krb5_derive_key_v2,
4662306a36Sopenharmony_ci	  .encrypt = gss_krb5_aes_encrypt,
4762306a36Sopenharmony_ci	  .decrypt = gss_krb5_aes_decrypt,
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	  .get_mic = gss_krb5_get_mic_v2,
5062306a36Sopenharmony_ci	  .verify_mic = gss_krb5_verify_mic_v2,
5162306a36Sopenharmony_ci	  .wrap = gss_krb5_wrap_v2,
5262306a36Sopenharmony_ci	  .unwrap = gss_krb5_unwrap_v2,
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	  .signalg = -1,
5562306a36Sopenharmony_ci	  .sealalg = -1,
5662306a36Sopenharmony_ci	  .keybytes = 16,
5762306a36Sopenharmony_ci	  .keylength = BITS2OCTETS(128),
5862306a36Sopenharmony_ci	  .Kc_length = BITS2OCTETS(128),
5962306a36Sopenharmony_ci	  .Ke_length = BITS2OCTETS(128),
6062306a36Sopenharmony_ci	  .Ki_length = BITS2OCTETS(128),
6162306a36Sopenharmony_ci	  .cksumlength = BITS2OCTETS(96),
6262306a36Sopenharmony_ci	  .keyed_cksum = 1,
6362306a36Sopenharmony_ci	},
6462306a36Sopenharmony_ci	/*
6562306a36Sopenharmony_ci	 * AES-256 with SHA-1 (RFC 3962)
6662306a36Sopenharmony_ci	 */
6762306a36Sopenharmony_ci	{
6862306a36Sopenharmony_ci	  .etype = ENCTYPE_AES256_CTS_HMAC_SHA1_96,
6962306a36Sopenharmony_ci	  .ctype = CKSUMTYPE_HMAC_SHA1_96_AES256,
7062306a36Sopenharmony_ci	  .name = "aes256-cts",
7162306a36Sopenharmony_ci	  .encrypt_name = "cts(cbc(aes))",
7262306a36Sopenharmony_ci	  .aux_cipher = "cbc(aes)",
7362306a36Sopenharmony_ci	  .cksum_name = "hmac(sha1)",
7462306a36Sopenharmony_ci	  .derive_key = krb5_derive_key_v2,
7562306a36Sopenharmony_ci	  .encrypt = gss_krb5_aes_encrypt,
7662306a36Sopenharmony_ci	  .decrypt = gss_krb5_aes_decrypt,
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	  .get_mic = gss_krb5_get_mic_v2,
7962306a36Sopenharmony_ci	  .verify_mic = gss_krb5_verify_mic_v2,
8062306a36Sopenharmony_ci	  .wrap = gss_krb5_wrap_v2,
8162306a36Sopenharmony_ci	  .unwrap = gss_krb5_unwrap_v2,
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	  .signalg = -1,
8462306a36Sopenharmony_ci	  .sealalg = -1,
8562306a36Sopenharmony_ci	  .keybytes = 32,
8662306a36Sopenharmony_ci	  .keylength = BITS2OCTETS(256),
8762306a36Sopenharmony_ci	  .Kc_length = BITS2OCTETS(256),
8862306a36Sopenharmony_ci	  .Ke_length = BITS2OCTETS(256),
8962306a36Sopenharmony_ci	  .Ki_length = BITS2OCTETS(256),
9062306a36Sopenharmony_ci	  .cksumlength = BITS2OCTETS(96),
9162306a36Sopenharmony_ci	  .keyed_cksum = 1,
9262306a36Sopenharmony_ci	},
9362306a36Sopenharmony_ci#endif
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA)
9662306a36Sopenharmony_ci	/*
9762306a36Sopenharmony_ci	 * Camellia-128 with CMAC (RFC 6803)
9862306a36Sopenharmony_ci	 */
9962306a36Sopenharmony_ci	{
10062306a36Sopenharmony_ci		.etype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
10162306a36Sopenharmony_ci		.ctype		= CKSUMTYPE_CMAC_CAMELLIA128,
10262306a36Sopenharmony_ci		.name		= "camellia128-cts-cmac",
10362306a36Sopenharmony_ci		.encrypt_name	= "cts(cbc(camellia))",
10462306a36Sopenharmony_ci		.aux_cipher	= "cbc(camellia)",
10562306a36Sopenharmony_ci		.cksum_name	= "cmac(camellia)",
10662306a36Sopenharmony_ci		.cksumlength	= BITS2OCTETS(128),
10762306a36Sopenharmony_ci		.keyed_cksum	= 1,
10862306a36Sopenharmony_ci		.keylength	= BITS2OCTETS(128),
10962306a36Sopenharmony_ci		.Kc_length	= BITS2OCTETS(128),
11062306a36Sopenharmony_ci		.Ke_length	= BITS2OCTETS(128),
11162306a36Sopenharmony_ci		.Ki_length	= BITS2OCTETS(128),
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci		.derive_key	= krb5_kdf_feedback_cmac,
11462306a36Sopenharmony_ci		.encrypt	= gss_krb5_aes_encrypt,
11562306a36Sopenharmony_ci		.decrypt	= gss_krb5_aes_decrypt,
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci		.get_mic	= gss_krb5_get_mic_v2,
11862306a36Sopenharmony_ci		.verify_mic	= gss_krb5_verify_mic_v2,
11962306a36Sopenharmony_ci		.wrap		= gss_krb5_wrap_v2,
12062306a36Sopenharmony_ci		.unwrap		= gss_krb5_unwrap_v2,
12162306a36Sopenharmony_ci	},
12262306a36Sopenharmony_ci	/*
12362306a36Sopenharmony_ci	 * Camellia-256 with CMAC (RFC 6803)
12462306a36Sopenharmony_ci	 */
12562306a36Sopenharmony_ci	{
12662306a36Sopenharmony_ci		.etype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
12762306a36Sopenharmony_ci		.ctype		= CKSUMTYPE_CMAC_CAMELLIA256,
12862306a36Sopenharmony_ci		.name		= "camellia256-cts-cmac",
12962306a36Sopenharmony_ci		.encrypt_name	= "cts(cbc(camellia))",
13062306a36Sopenharmony_ci		.aux_cipher	= "cbc(camellia)",
13162306a36Sopenharmony_ci		.cksum_name	= "cmac(camellia)",
13262306a36Sopenharmony_ci		.cksumlength	= BITS2OCTETS(128),
13362306a36Sopenharmony_ci		.keyed_cksum	= 1,
13462306a36Sopenharmony_ci		.keylength	= BITS2OCTETS(256),
13562306a36Sopenharmony_ci		.Kc_length	= BITS2OCTETS(256),
13662306a36Sopenharmony_ci		.Ke_length	= BITS2OCTETS(256),
13762306a36Sopenharmony_ci		.Ki_length	= BITS2OCTETS(256),
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci		.derive_key	= krb5_kdf_feedback_cmac,
14062306a36Sopenharmony_ci		.encrypt	= gss_krb5_aes_encrypt,
14162306a36Sopenharmony_ci		.decrypt	= gss_krb5_aes_decrypt,
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci		.get_mic	= gss_krb5_get_mic_v2,
14462306a36Sopenharmony_ci		.verify_mic	= gss_krb5_verify_mic_v2,
14562306a36Sopenharmony_ci		.wrap		= gss_krb5_wrap_v2,
14662306a36Sopenharmony_ci		.unwrap		= gss_krb5_unwrap_v2,
14762306a36Sopenharmony_ci	},
14862306a36Sopenharmony_ci#endif
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2)
15162306a36Sopenharmony_ci	/*
15262306a36Sopenharmony_ci	 * AES-128 with SHA-256 (RFC 8009)
15362306a36Sopenharmony_ci	 */
15462306a36Sopenharmony_ci	{
15562306a36Sopenharmony_ci		.etype		= ENCTYPE_AES128_CTS_HMAC_SHA256_128,
15662306a36Sopenharmony_ci		.ctype		= CKSUMTYPE_HMAC_SHA256_128_AES128,
15762306a36Sopenharmony_ci		.name		= "aes128-cts-hmac-sha256-128",
15862306a36Sopenharmony_ci		.encrypt_name	= "cts(cbc(aes))",
15962306a36Sopenharmony_ci		.aux_cipher	= "cbc(aes)",
16062306a36Sopenharmony_ci		.cksum_name	= "hmac(sha256)",
16162306a36Sopenharmony_ci		.cksumlength	= BITS2OCTETS(128),
16262306a36Sopenharmony_ci		.keyed_cksum	= 1,
16362306a36Sopenharmony_ci		.keylength	= BITS2OCTETS(128),
16462306a36Sopenharmony_ci		.Kc_length	= BITS2OCTETS(128),
16562306a36Sopenharmony_ci		.Ke_length	= BITS2OCTETS(128),
16662306a36Sopenharmony_ci		.Ki_length	= BITS2OCTETS(128),
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci		.derive_key	= krb5_kdf_hmac_sha2,
16962306a36Sopenharmony_ci		.encrypt	= krb5_etm_encrypt,
17062306a36Sopenharmony_ci		.decrypt	= krb5_etm_decrypt,
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci		.get_mic	= gss_krb5_get_mic_v2,
17362306a36Sopenharmony_ci		.verify_mic	= gss_krb5_verify_mic_v2,
17462306a36Sopenharmony_ci		.wrap		= gss_krb5_wrap_v2,
17562306a36Sopenharmony_ci		.unwrap		= gss_krb5_unwrap_v2,
17662306a36Sopenharmony_ci	},
17762306a36Sopenharmony_ci	/*
17862306a36Sopenharmony_ci	 * AES-256 with SHA-384 (RFC 8009)
17962306a36Sopenharmony_ci	 */
18062306a36Sopenharmony_ci	{
18162306a36Sopenharmony_ci		.etype		= ENCTYPE_AES256_CTS_HMAC_SHA384_192,
18262306a36Sopenharmony_ci		.ctype		= CKSUMTYPE_HMAC_SHA384_192_AES256,
18362306a36Sopenharmony_ci		.name		= "aes256-cts-hmac-sha384-192",
18462306a36Sopenharmony_ci		.encrypt_name	= "cts(cbc(aes))",
18562306a36Sopenharmony_ci		.aux_cipher	= "cbc(aes)",
18662306a36Sopenharmony_ci		.cksum_name	= "hmac(sha384)",
18762306a36Sopenharmony_ci		.cksumlength	= BITS2OCTETS(192),
18862306a36Sopenharmony_ci		.keyed_cksum	= 1,
18962306a36Sopenharmony_ci		.keylength	= BITS2OCTETS(256),
19062306a36Sopenharmony_ci		.Kc_length	= BITS2OCTETS(192),
19162306a36Sopenharmony_ci		.Ke_length	= BITS2OCTETS(256),
19262306a36Sopenharmony_ci		.Ki_length	= BITS2OCTETS(192),
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci		.derive_key	= krb5_kdf_hmac_sha2,
19562306a36Sopenharmony_ci		.encrypt	= krb5_etm_encrypt,
19662306a36Sopenharmony_ci		.decrypt	= krb5_etm_decrypt,
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci		.get_mic	= gss_krb5_get_mic_v2,
19962306a36Sopenharmony_ci		.verify_mic	= gss_krb5_verify_mic_v2,
20062306a36Sopenharmony_ci		.wrap		= gss_krb5_wrap_v2,
20162306a36Sopenharmony_ci		.unwrap		= gss_krb5_unwrap_v2,
20262306a36Sopenharmony_ci	},
20362306a36Sopenharmony_ci#endif
20462306a36Sopenharmony_ci};
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci/*
20762306a36Sopenharmony_ci * The list of advertised enctypes is specified in order of most
20862306a36Sopenharmony_ci * preferred to least.
20962306a36Sopenharmony_ci */
21062306a36Sopenharmony_cistatic char gss_krb5_enctype_priority_list[64];
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistatic void gss_krb5_prepare_enctype_priority_list(void)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	static const u32 gss_krb5_enctypes[] = {
21562306a36Sopenharmony_ci#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2)
21662306a36Sopenharmony_ci		ENCTYPE_AES256_CTS_HMAC_SHA384_192,
21762306a36Sopenharmony_ci		ENCTYPE_AES128_CTS_HMAC_SHA256_128,
21862306a36Sopenharmony_ci#endif
21962306a36Sopenharmony_ci#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA)
22062306a36Sopenharmony_ci		ENCTYPE_CAMELLIA256_CTS_CMAC,
22162306a36Sopenharmony_ci		ENCTYPE_CAMELLIA128_CTS_CMAC,
22262306a36Sopenharmony_ci#endif
22362306a36Sopenharmony_ci#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1)
22462306a36Sopenharmony_ci		ENCTYPE_AES256_CTS_HMAC_SHA1_96,
22562306a36Sopenharmony_ci		ENCTYPE_AES128_CTS_HMAC_SHA1_96,
22662306a36Sopenharmony_ci#endif
22762306a36Sopenharmony_ci	};
22862306a36Sopenharmony_ci	size_t total, i;
22962306a36Sopenharmony_ci	char buf[16];
23062306a36Sopenharmony_ci	char *sep;
23162306a36Sopenharmony_ci	int n;
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	sep = "";
23462306a36Sopenharmony_ci	gss_krb5_enctype_priority_list[0] = '\0';
23562306a36Sopenharmony_ci	for (total = 0, i = 0; i < ARRAY_SIZE(gss_krb5_enctypes); i++) {
23662306a36Sopenharmony_ci		n = sprintf(buf, "%s%u", sep, gss_krb5_enctypes[i]);
23762306a36Sopenharmony_ci		if (n < 0)
23862306a36Sopenharmony_ci			break;
23962306a36Sopenharmony_ci		if (total + n >= sizeof(gss_krb5_enctype_priority_list))
24062306a36Sopenharmony_ci			break;
24162306a36Sopenharmony_ci		strcat(gss_krb5_enctype_priority_list, buf);
24262306a36Sopenharmony_ci		sep = ",";
24362306a36Sopenharmony_ci		total += n;
24462306a36Sopenharmony_ci	}
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci/**
24862306a36Sopenharmony_ci * gss_krb5_lookup_enctype - Retrieve profile information for a given enctype
24962306a36Sopenharmony_ci * @etype: ENCTYPE value
25062306a36Sopenharmony_ci *
25162306a36Sopenharmony_ci * Returns a pointer to a gss_krb5_enctype structure, or NULL if no
25262306a36Sopenharmony_ci * matching etype is found.
25362306a36Sopenharmony_ci */
25462306a36Sopenharmony_ciVISIBLE_IF_KUNIT
25562306a36Sopenharmony_ciconst struct gss_krb5_enctype *gss_krb5_lookup_enctype(u32 etype)
25662306a36Sopenharmony_ci{
25762306a36Sopenharmony_ci	size_t i;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(supported_gss_krb5_enctypes); i++)
26062306a36Sopenharmony_ci		if (supported_gss_krb5_enctypes[i].etype == etype)
26162306a36Sopenharmony_ci			return &supported_gss_krb5_enctypes[i];
26262306a36Sopenharmony_ci	return NULL;
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ciEXPORT_SYMBOL_IF_KUNIT(gss_krb5_lookup_enctype);
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cistatic struct crypto_sync_skcipher *
26762306a36Sopenharmony_cigss_krb5_alloc_cipher_v2(const char *cname, const struct xdr_netobj *key)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	struct crypto_sync_skcipher *tfm;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	tfm = crypto_alloc_sync_skcipher(cname, 0, 0);
27262306a36Sopenharmony_ci	if (IS_ERR(tfm))
27362306a36Sopenharmony_ci		return NULL;
27462306a36Sopenharmony_ci	if (crypto_sync_skcipher_setkey(tfm, key->data, key->len)) {
27562306a36Sopenharmony_ci		crypto_free_sync_skcipher(tfm);
27662306a36Sopenharmony_ci		return NULL;
27762306a36Sopenharmony_ci	}
27862306a36Sopenharmony_ci	return tfm;
27962306a36Sopenharmony_ci}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_cistatic struct crypto_ahash *
28262306a36Sopenharmony_cigss_krb5_alloc_hash_v2(struct krb5_ctx *kctx, const struct xdr_netobj *key)
28362306a36Sopenharmony_ci{
28462306a36Sopenharmony_ci	struct crypto_ahash *tfm;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
28762306a36Sopenharmony_ci	if (IS_ERR(tfm))
28862306a36Sopenharmony_ci		return NULL;
28962306a36Sopenharmony_ci	if (crypto_ahash_setkey(tfm, key->data, key->len)) {
29062306a36Sopenharmony_ci		crypto_free_ahash(tfm);
29162306a36Sopenharmony_ci		return NULL;
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci	return tfm;
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic int
29762306a36Sopenharmony_cigss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask)
29862306a36Sopenharmony_ci{
29962306a36Sopenharmony_ci	struct xdr_netobj keyin = {
30062306a36Sopenharmony_ci		.len	= ctx->gk5e->keylength,
30162306a36Sopenharmony_ci		.data	= ctx->Ksess,
30262306a36Sopenharmony_ci	};
30362306a36Sopenharmony_ci	struct xdr_netobj keyout;
30462306a36Sopenharmony_ci	int ret = -EINVAL;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	keyout.data = kmalloc(GSS_KRB5_MAX_KEYLEN, gfp_mask);
30762306a36Sopenharmony_ci	if (!keyout.data)
30862306a36Sopenharmony_ci		return -ENOMEM;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	/* initiator seal encryption */
31162306a36Sopenharmony_ci	keyout.len = ctx->gk5e->Ke_length;
31262306a36Sopenharmony_ci	if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_INITIATOR_SEAL,
31362306a36Sopenharmony_ci			    KEY_USAGE_SEED_ENCRYPTION, gfp_mask))
31462306a36Sopenharmony_ci		goto out;
31562306a36Sopenharmony_ci	ctx->initiator_enc = gss_krb5_alloc_cipher_v2(ctx->gk5e->encrypt_name,
31662306a36Sopenharmony_ci						      &keyout);
31762306a36Sopenharmony_ci	if (ctx->initiator_enc == NULL)
31862306a36Sopenharmony_ci		goto out;
31962306a36Sopenharmony_ci	if (ctx->gk5e->aux_cipher) {
32062306a36Sopenharmony_ci		ctx->initiator_enc_aux =
32162306a36Sopenharmony_ci			gss_krb5_alloc_cipher_v2(ctx->gk5e->aux_cipher,
32262306a36Sopenharmony_ci						 &keyout);
32362306a36Sopenharmony_ci		if (ctx->initiator_enc_aux == NULL)
32462306a36Sopenharmony_ci			goto out_free;
32562306a36Sopenharmony_ci	}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	/* acceptor seal encryption */
32862306a36Sopenharmony_ci	if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_ACCEPTOR_SEAL,
32962306a36Sopenharmony_ci			    KEY_USAGE_SEED_ENCRYPTION, gfp_mask))
33062306a36Sopenharmony_ci		goto out_free;
33162306a36Sopenharmony_ci	ctx->acceptor_enc = gss_krb5_alloc_cipher_v2(ctx->gk5e->encrypt_name,
33262306a36Sopenharmony_ci						     &keyout);
33362306a36Sopenharmony_ci	if (ctx->acceptor_enc == NULL)
33462306a36Sopenharmony_ci		goto out_free;
33562306a36Sopenharmony_ci	if (ctx->gk5e->aux_cipher) {
33662306a36Sopenharmony_ci		ctx->acceptor_enc_aux =
33762306a36Sopenharmony_ci			gss_krb5_alloc_cipher_v2(ctx->gk5e->aux_cipher,
33862306a36Sopenharmony_ci						 &keyout);
33962306a36Sopenharmony_ci		if (ctx->acceptor_enc_aux == NULL)
34062306a36Sopenharmony_ci			goto out_free;
34162306a36Sopenharmony_ci	}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	/* initiator sign checksum */
34462306a36Sopenharmony_ci	keyout.len = ctx->gk5e->Kc_length;
34562306a36Sopenharmony_ci	if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_INITIATOR_SIGN,
34662306a36Sopenharmony_ci			    KEY_USAGE_SEED_CHECKSUM, gfp_mask))
34762306a36Sopenharmony_ci		goto out_free;
34862306a36Sopenharmony_ci	ctx->initiator_sign = gss_krb5_alloc_hash_v2(ctx, &keyout);
34962306a36Sopenharmony_ci	if (ctx->initiator_sign == NULL)
35062306a36Sopenharmony_ci		goto out_free;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	/* acceptor sign checksum */
35362306a36Sopenharmony_ci	if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_ACCEPTOR_SIGN,
35462306a36Sopenharmony_ci			    KEY_USAGE_SEED_CHECKSUM, gfp_mask))
35562306a36Sopenharmony_ci		goto out_free;
35662306a36Sopenharmony_ci	ctx->acceptor_sign = gss_krb5_alloc_hash_v2(ctx, &keyout);
35762306a36Sopenharmony_ci	if (ctx->acceptor_sign == NULL)
35862306a36Sopenharmony_ci		goto out_free;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	/* initiator seal integrity */
36162306a36Sopenharmony_ci	keyout.len = ctx->gk5e->Ki_length;
36262306a36Sopenharmony_ci	if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_INITIATOR_SEAL,
36362306a36Sopenharmony_ci			    KEY_USAGE_SEED_INTEGRITY, gfp_mask))
36462306a36Sopenharmony_ci		goto out_free;
36562306a36Sopenharmony_ci	ctx->initiator_integ = gss_krb5_alloc_hash_v2(ctx, &keyout);
36662306a36Sopenharmony_ci	if (ctx->initiator_integ == NULL)
36762306a36Sopenharmony_ci		goto out_free;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	/* acceptor seal integrity */
37062306a36Sopenharmony_ci	if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_ACCEPTOR_SEAL,
37162306a36Sopenharmony_ci			    KEY_USAGE_SEED_INTEGRITY, gfp_mask))
37262306a36Sopenharmony_ci		goto out_free;
37362306a36Sopenharmony_ci	ctx->acceptor_integ = gss_krb5_alloc_hash_v2(ctx, &keyout);
37462306a36Sopenharmony_ci	if (ctx->acceptor_integ == NULL)
37562306a36Sopenharmony_ci		goto out_free;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	ret = 0;
37862306a36Sopenharmony_ciout:
37962306a36Sopenharmony_ci	kfree_sensitive(keyout.data);
38062306a36Sopenharmony_ci	return ret;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ciout_free:
38362306a36Sopenharmony_ci	crypto_free_ahash(ctx->acceptor_integ);
38462306a36Sopenharmony_ci	crypto_free_ahash(ctx->initiator_integ);
38562306a36Sopenharmony_ci	crypto_free_ahash(ctx->acceptor_sign);
38662306a36Sopenharmony_ci	crypto_free_ahash(ctx->initiator_sign);
38762306a36Sopenharmony_ci	crypto_free_sync_skcipher(ctx->acceptor_enc_aux);
38862306a36Sopenharmony_ci	crypto_free_sync_skcipher(ctx->acceptor_enc);
38962306a36Sopenharmony_ci	crypto_free_sync_skcipher(ctx->initiator_enc_aux);
39062306a36Sopenharmony_ci	crypto_free_sync_skcipher(ctx->initiator_enc);
39162306a36Sopenharmony_ci	goto out;
39262306a36Sopenharmony_ci}
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_cistatic int
39562306a36Sopenharmony_cigss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
39662306a36Sopenharmony_ci		gfp_t gfp_mask)
39762306a36Sopenharmony_ci{
39862306a36Sopenharmony_ci	u64 seq_send64;
39962306a36Sopenharmony_ci	int keylen;
40062306a36Sopenharmony_ci	u32 time32;
40162306a36Sopenharmony_ci	int ret;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
40462306a36Sopenharmony_ci	if (IS_ERR(p))
40562306a36Sopenharmony_ci		goto out_err;
40662306a36Sopenharmony_ci	ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	p = simple_get_bytes(p, end, &time32, sizeof(time32));
40962306a36Sopenharmony_ci	if (IS_ERR(p))
41062306a36Sopenharmony_ci		goto out_err;
41162306a36Sopenharmony_ci	/* unsigned 32-bit time overflows in year 2106 */
41262306a36Sopenharmony_ci	ctx->endtime = (time64_t)time32;
41362306a36Sopenharmony_ci	p = simple_get_bytes(p, end, &seq_send64, sizeof(seq_send64));
41462306a36Sopenharmony_ci	if (IS_ERR(p))
41562306a36Sopenharmony_ci		goto out_err;
41662306a36Sopenharmony_ci	atomic64_set(&ctx->seq_send64, seq_send64);
41762306a36Sopenharmony_ci	/* set seq_send for use by "older" enctypes */
41862306a36Sopenharmony_ci	atomic_set(&ctx->seq_send, seq_send64);
41962306a36Sopenharmony_ci	if (seq_send64 != atomic_read(&ctx->seq_send)) {
42062306a36Sopenharmony_ci		dprintk("%s: seq_send64 %llx, seq_send %x overflow?\n", __func__,
42162306a36Sopenharmony_ci			seq_send64, atomic_read(&ctx->seq_send));
42262306a36Sopenharmony_ci		p = ERR_PTR(-EINVAL);
42362306a36Sopenharmony_ci		goto out_err;
42462306a36Sopenharmony_ci	}
42562306a36Sopenharmony_ci	p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
42662306a36Sopenharmony_ci	if (IS_ERR(p))
42762306a36Sopenharmony_ci		goto out_err;
42862306a36Sopenharmony_ci	ctx->gk5e = gss_krb5_lookup_enctype(ctx->enctype);
42962306a36Sopenharmony_ci	if (ctx->gk5e == NULL) {
43062306a36Sopenharmony_ci		dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
43162306a36Sopenharmony_ci			ctx->enctype);
43262306a36Sopenharmony_ci		p = ERR_PTR(-EINVAL);
43362306a36Sopenharmony_ci		goto out_err;
43462306a36Sopenharmony_ci	}
43562306a36Sopenharmony_ci	keylen = ctx->gk5e->keylength;
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	p = simple_get_bytes(p, end, ctx->Ksess, keylen);
43862306a36Sopenharmony_ci	if (IS_ERR(p))
43962306a36Sopenharmony_ci		goto out_err;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	if (p != end) {
44262306a36Sopenharmony_ci		p = ERR_PTR(-EINVAL);
44362306a36Sopenharmony_ci		goto out_err;
44462306a36Sopenharmony_ci	}
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,
44762306a36Sopenharmony_ci				      gss_kerberos_mech.gm_oid.len, gfp_mask);
44862306a36Sopenharmony_ci	if (unlikely(ctx->mech_used.data == NULL)) {
44962306a36Sopenharmony_ci		p = ERR_PTR(-ENOMEM);
45062306a36Sopenharmony_ci		goto out_err;
45162306a36Sopenharmony_ci	}
45262306a36Sopenharmony_ci	ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	ret = gss_krb5_import_ctx_v2(ctx, gfp_mask);
45562306a36Sopenharmony_ci	if (ret) {
45662306a36Sopenharmony_ci		p = ERR_PTR(ret);
45762306a36Sopenharmony_ci		goto out_free;
45862306a36Sopenharmony_ci	}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	return 0;
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ciout_free:
46362306a36Sopenharmony_ci	kfree(ctx->mech_used.data);
46462306a36Sopenharmony_ciout_err:
46562306a36Sopenharmony_ci	return PTR_ERR(p);
46662306a36Sopenharmony_ci}
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_cistatic int
46962306a36Sopenharmony_cigss_krb5_import_sec_context(const void *p, size_t len, struct gss_ctx *ctx_id,
47062306a36Sopenharmony_ci			    time64_t *endtime, gfp_t gfp_mask)
47162306a36Sopenharmony_ci{
47262306a36Sopenharmony_ci	const void *end = (const void *)((const char *)p + len);
47362306a36Sopenharmony_ci	struct  krb5_ctx *ctx;
47462306a36Sopenharmony_ci	int ret;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	ctx = kzalloc(sizeof(*ctx), gfp_mask);
47762306a36Sopenharmony_ci	if (ctx == NULL)
47862306a36Sopenharmony_ci		return -ENOMEM;
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	ret = gss_import_v2_context(p, end, ctx, gfp_mask);
48162306a36Sopenharmony_ci	memzero_explicit(&ctx->Ksess, sizeof(ctx->Ksess));
48262306a36Sopenharmony_ci	if (ret) {
48362306a36Sopenharmony_ci		kfree(ctx);
48462306a36Sopenharmony_ci		return ret;
48562306a36Sopenharmony_ci	}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	ctx_id->internal_ctx_id = ctx;
48862306a36Sopenharmony_ci	if (endtime)
48962306a36Sopenharmony_ci		*endtime = ctx->endtime;
49062306a36Sopenharmony_ci	return 0;
49162306a36Sopenharmony_ci}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_cistatic void
49462306a36Sopenharmony_cigss_krb5_delete_sec_context(void *internal_ctx)
49562306a36Sopenharmony_ci{
49662306a36Sopenharmony_ci	struct krb5_ctx *kctx = internal_ctx;
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	crypto_free_sync_skcipher(kctx->seq);
49962306a36Sopenharmony_ci	crypto_free_sync_skcipher(kctx->enc);
50062306a36Sopenharmony_ci	crypto_free_sync_skcipher(kctx->acceptor_enc);
50162306a36Sopenharmony_ci	crypto_free_sync_skcipher(kctx->initiator_enc);
50262306a36Sopenharmony_ci	crypto_free_sync_skcipher(kctx->acceptor_enc_aux);
50362306a36Sopenharmony_ci	crypto_free_sync_skcipher(kctx->initiator_enc_aux);
50462306a36Sopenharmony_ci	crypto_free_ahash(kctx->acceptor_sign);
50562306a36Sopenharmony_ci	crypto_free_ahash(kctx->initiator_sign);
50662306a36Sopenharmony_ci	crypto_free_ahash(kctx->acceptor_integ);
50762306a36Sopenharmony_ci	crypto_free_ahash(kctx->initiator_integ);
50862306a36Sopenharmony_ci	kfree(kctx->mech_used.data);
50962306a36Sopenharmony_ci	kfree(kctx);
51062306a36Sopenharmony_ci}
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci/**
51362306a36Sopenharmony_ci * gss_krb5_get_mic - get_mic for the Kerberos GSS mechanism
51462306a36Sopenharmony_ci * @gctx: GSS context
51562306a36Sopenharmony_ci * @text: plaintext to checksum
51662306a36Sopenharmony_ci * @token: buffer into which to write the computed checksum
51762306a36Sopenharmony_ci *
51862306a36Sopenharmony_ci * Return values:
51962306a36Sopenharmony_ci *    %GSS_S_COMPLETE - success, and @token is filled in
52062306a36Sopenharmony_ci *    %GSS_S_FAILURE - checksum could not be generated
52162306a36Sopenharmony_ci *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
52262306a36Sopenharmony_ci */
52362306a36Sopenharmony_cistatic u32 gss_krb5_get_mic(struct gss_ctx *gctx, struct xdr_buf *text,
52462306a36Sopenharmony_ci			    struct xdr_netobj *token)
52562306a36Sopenharmony_ci{
52662306a36Sopenharmony_ci	struct krb5_ctx *kctx = gctx->internal_ctx_id;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	return kctx->gk5e->get_mic(kctx, text, token);
52962306a36Sopenharmony_ci}
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci/**
53262306a36Sopenharmony_ci * gss_krb5_verify_mic - verify_mic for the Kerberos GSS mechanism
53362306a36Sopenharmony_ci * @gctx: GSS context
53462306a36Sopenharmony_ci * @message_buffer: plaintext to check
53562306a36Sopenharmony_ci * @read_token: received checksum to check
53662306a36Sopenharmony_ci *
53762306a36Sopenharmony_ci * Return values:
53862306a36Sopenharmony_ci *    %GSS_S_COMPLETE - computed and received checksums match
53962306a36Sopenharmony_ci *    %GSS_S_DEFECTIVE_TOKEN - received checksum is not valid
54062306a36Sopenharmony_ci *    %GSS_S_BAD_SIG - computed and received checksums do not match
54162306a36Sopenharmony_ci *    %GSS_S_FAILURE - received checksum could not be checked
54262306a36Sopenharmony_ci *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
54362306a36Sopenharmony_ci */
54462306a36Sopenharmony_cistatic u32 gss_krb5_verify_mic(struct gss_ctx *gctx,
54562306a36Sopenharmony_ci			       struct xdr_buf *message_buffer,
54662306a36Sopenharmony_ci			       struct xdr_netobj *read_token)
54762306a36Sopenharmony_ci{
54862306a36Sopenharmony_ci	struct krb5_ctx *kctx = gctx->internal_ctx_id;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	return kctx->gk5e->verify_mic(kctx, message_buffer, read_token);
55162306a36Sopenharmony_ci}
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci/**
55462306a36Sopenharmony_ci * gss_krb5_wrap - gss_wrap for the Kerberos GSS mechanism
55562306a36Sopenharmony_ci * @gctx: initialized GSS context
55662306a36Sopenharmony_ci * @offset: byte offset in @buf to start writing the cipher text
55762306a36Sopenharmony_ci * @buf: OUT: send buffer
55862306a36Sopenharmony_ci * @pages: plaintext to wrap
55962306a36Sopenharmony_ci *
56062306a36Sopenharmony_ci * Return values:
56162306a36Sopenharmony_ci *    %GSS_S_COMPLETE - success, @buf has been updated
56262306a36Sopenharmony_ci *    %GSS_S_FAILURE - @buf could not be wrapped
56362306a36Sopenharmony_ci *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
56462306a36Sopenharmony_ci */
56562306a36Sopenharmony_cistatic u32 gss_krb5_wrap(struct gss_ctx *gctx, int offset,
56662306a36Sopenharmony_ci			 struct xdr_buf *buf, struct page **pages)
56762306a36Sopenharmony_ci{
56862306a36Sopenharmony_ci	struct krb5_ctx	*kctx = gctx->internal_ctx_id;
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	return kctx->gk5e->wrap(kctx, offset, buf, pages);
57162306a36Sopenharmony_ci}
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci/**
57462306a36Sopenharmony_ci * gss_krb5_unwrap - gss_unwrap for the Kerberos GSS mechanism
57562306a36Sopenharmony_ci * @gctx: initialized GSS context
57662306a36Sopenharmony_ci * @offset: starting byte offset into @buf
57762306a36Sopenharmony_ci * @len: size of ciphertext to unwrap
57862306a36Sopenharmony_ci * @buf: ciphertext to unwrap
57962306a36Sopenharmony_ci *
58062306a36Sopenharmony_ci * Return values:
58162306a36Sopenharmony_ci *    %GSS_S_COMPLETE - success, @buf has been updated
58262306a36Sopenharmony_ci *    %GSS_S_DEFECTIVE_TOKEN - received blob is not valid
58362306a36Sopenharmony_ci *    %GSS_S_BAD_SIG - computed and received checksums do not match
58462306a36Sopenharmony_ci *    %GSS_S_FAILURE - @buf could not be unwrapped
58562306a36Sopenharmony_ci *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
58662306a36Sopenharmony_ci */
58762306a36Sopenharmony_cistatic u32 gss_krb5_unwrap(struct gss_ctx *gctx, int offset,
58862306a36Sopenharmony_ci			   int len, struct xdr_buf *buf)
58962306a36Sopenharmony_ci{
59062306a36Sopenharmony_ci	struct krb5_ctx	*kctx = gctx->internal_ctx_id;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	return kctx->gk5e->unwrap(kctx, offset, len, buf,
59362306a36Sopenharmony_ci				  &gctx->slack, &gctx->align);
59462306a36Sopenharmony_ci}
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_cistatic const struct gss_api_ops gss_kerberos_ops = {
59762306a36Sopenharmony_ci	.gss_import_sec_context	= gss_krb5_import_sec_context,
59862306a36Sopenharmony_ci	.gss_get_mic		= gss_krb5_get_mic,
59962306a36Sopenharmony_ci	.gss_verify_mic		= gss_krb5_verify_mic,
60062306a36Sopenharmony_ci	.gss_wrap		= gss_krb5_wrap,
60162306a36Sopenharmony_ci	.gss_unwrap		= gss_krb5_unwrap,
60262306a36Sopenharmony_ci	.gss_delete_sec_context	= gss_krb5_delete_sec_context,
60362306a36Sopenharmony_ci};
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_cistatic struct pf_desc gss_kerberos_pfs[] = {
60662306a36Sopenharmony_ci	[0] = {
60762306a36Sopenharmony_ci		.pseudoflavor = RPC_AUTH_GSS_KRB5,
60862306a36Sopenharmony_ci		.qop = GSS_C_QOP_DEFAULT,
60962306a36Sopenharmony_ci		.service = RPC_GSS_SVC_NONE,
61062306a36Sopenharmony_ci		.name = "krb5",
61162306a36Sopenharmony_ci	},
61262306a36Sopenharmony_ci	[1] = {
61362306a36Sopenharmony_ci		.pseudoflavor = RPC_AUTH_GSS_KRB5I,
61462306a36Sopenharmony_ci		.qop = GSS_C_QOP_DEFAULT,
61562306a36Sopenharmony_ci		.service = RPC_GSS_SVC_INTEGRITY,
61662306a36Sopenharmony_ci		.name = "krb5i",
61762306a36Sopenharmony_ci		.datatouch = true,
61862306a36Sopenharmony_ci	},
61962306a36Sopenharmony_ci	[2] = {
62062306a36Sopenharmony_ci		.pseudoflavor = RPC_AUTH_GSS_KRB5P,
62162306a36Sopenharmony_ci		.qop = GSS_C_QOP_DEFAULT,
62262306a36Sopenharmony_ci		.service = RPC_GSS_SVC_PRIVACY,
62362306a36Sopenharmony_ci		.name = "krb5p",
62462306a36Sopenharmony_ci		.datatouch = true,
62562306a36Sopenharmony_ci	},
62662306a36Sopenharmony_ci};
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-krb5");
62962306a36Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-krb5i");
63062306a36Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-krb5p");
63162306a36Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-390003");
63262306a36Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-390004");
63362306a36Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-390005");
63462306a36Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_cistatic struct gss_api_mech gss_kerberos_mech = {
63762306a36Sopenharmony_ci	.gm_name	= "krb5",
63862306a36Sopenharmony_ci	.gm_owner	= THIS_MODULE,
63962306a36Sopenharmony_ci	.gm_oid		= { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },
64062306a36Sopenharmony_ci	.gm_ops		= &gss_kerberos_ops,
64162306a36Sopenharmony_ci	.gm_pf_num	= ARRAY_SIZE(gss_kerberos_pfs),
64262306a36Sopenharmony_ci	.gm_pfs		= gss_kerberos_pfs,
64362306a36Sopenharmony_ci	.gm_upcall_enctypes = gss_krb5_enctype_priority_list,
64462306a36Sopenharmony_ci};
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_cistatic int __init init_kerberos_module(void)
64762306a36Sopenharmony_ci{
64862306a36Sopenharmony_ci	int status;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	gss_krb5_prepare_enctype_priority_list();
65162306a36Sopenharmony_ci	status = gss_mech_register(&gss_kerberos_mech);
65262306a36Sopenharmony_ci	if (status)
65362306a36Sopenharmony_ci		printk("Failed to register kerberos gss mechanism!\n");
65462306a36Sopenharmony_ci	return status;
65562306a36Sopenharmony_ci}
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_cistatic void __exit cleanup_kerberos_module(void)
65862306a36Sopenharmony_ci{
65962306a36Sopenharmony_ci	gss_mech_unregister(&gss_kerberos_mech);
66062306a36Sopenharmony_ci}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ciMODULE_LICENSE("GPL");
66362306a36Sopenharmony_cimodule_init(init_kerberos_module);
66462306a36Sopenharmony_cimodule_exit(cleanup_kerberos_module);
665