18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  linux/net/sunrpc/gss_krb5_mech.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Copyright (c) 2001-2008 The Regents of the University of Michigan.
68c2ecf20Sopenharmony_ci *  All rights reserved.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci *  Andy Adamson <andros@umich.edu>
98c2ecf20Sopenharmony_ci *  J. Bruce Fields <bfields@umich.edu>
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <crypto/hash.h>
138c2ecf20Sopenharmony_ci#include <crypto/skcipher.h>
148c2ecf20Sopenharmony_ci#include <linux/err.h>
158c2ecf20Sopenharmony_ci#include <linux/module.h>
168c2ecf20Sopenharmony_ci#include <linux/init.h>
178c2ecf20Sopenharmony_ci#include <linux/types.h>
188c2ecf20Sopenharmony_ci#include <linux/slab.h>
198c2ecf20Sopenharmony_ci#include <linux/sunrpc/auth.h>
208c2ecf20Sopenharmony_ci#include <linux/sunrpc/gss_krb5.h>
218c2ecf20Sopenharmony_ci#include <linux/sunrpc/xdr.h>
228c2ecf20Sopenharmony_ci#include <linux/sunrpc/gss_krb5_enctypes.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include "auth_gss_internal.h"
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
278c2ecf20Sopenharmony_ci# define RPCDBG_FACILITY	RPCDBG_AUTH
288c2ecf20Sopenharmony_ci#endif
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic struct gss_api_mech gss_kerberos_mech;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic int gss_krb5_import_ctx_des(struct krb5_ctx *ctx, gfp_t gfp_mask);
338c2ecf20Sopenharmony_cistatic int gss_krb5_import_ctx_v1(struct krb5_ctx *ctx, gfp_t gfp_mask);
348c2ecf20Sopenharmony_cistatic int gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask);
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cistatic const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
378c2ecf20Sopenharmony_ci#ifndef CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES
388c2ecf20Sopenharmony_ci	/*
398c2ecf20Sopenharmony_ci	 * DES (All DES enctypes are mapped to the same gss functionality)
408c2ecf20Sopenharmony_ci	 */
418c2ecf20Sopenharmony_ci	{
428c2ecf20Sopenharmony_ci	  .etype = ENCTYPE_DES_CBC_RAW,
438c2ecf20Sopenharmony_ci	  .ctype = CKSUMTYPE_RSA_MD5,
448c2ecf20Sopenharmony_ci	  .name = "des-cbc-crc",
458c2ecf20Sopenharmony_ci	  .encrypt_name = "cbc(des)",
468c2ecf20Sopenharmony_ci	  .cksum_name = "md5",
478c2ecf20Sopenharmony_ci	  .encrypt = krb5_encrypt,
488c2ecf20Sopenharmony_ci	  .decrypt = krb5_decrypt,
498c2ecf20Sopenharmony_ci	  .import_ctx = gss_krb5_import_ctx_des,
508c2ecf20Sopenharmony_ci	  .mk_key = NULL,
518c2ecf20Sopenharmony_ci	  .signalg = SGN_ALG_DES_MAC_MD5,
528c2ecf20Sopenharmony_ci	  .sealalg = SEAL_ALG_DES,
538c2ecf20Sopenharmony_ci	  .keybytes = 7,
548c2ecf20Sopenharmony_ci	  .keylength = 8,
558c2ecf20Sopenharmony_ci	  .blocksize = 8,
568c2ecf20Sopenharmony_ci	  .conflen = 8,
578c2ecf20Sopenharmony_ci	  .cksumlength = 8,
588c2ecf20Sopenharmony_ci	  .keyed_cksum = 0,
598c2ecf20Sopenharmony_ci	},
608c2ecf20Sopenharmony_ci#endif	/* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */
618c2ecf20Sopenharmony_ci	/*
628c2ecf20Sopenharmony_ci	 * 3DES
638c2ecf20Sopenharmony_ci	 */
648c2ecf20Sopenharmony_ci	{
658c2ecf20Sopenharmony_ci	  .etype = ENCTYPE_DES3_CBC_RAW,
668c2ecf20Sopenharmony_ci	  .ctype = CKSUMTYPE_HMAC_SHA1_DES3,
678c2ecf20Sopenharmony_ci	  .name = "des3-hmac-sha1",
688c2ecf20Sopenharmony_ci	  .encrypt_name = "cbc(des3_ede)",
698c2ecf20Sopenharmony_ci	  .cksum_name = "hmac(sha1)",
708c2ecf20Sopenharmony_ci	  .encrypt = krb5_encrypt,
718c2ecf20Sopenharmony_ci	  .decrypt = krb5_decrypt,
728c2ecf20Sopenharmony_ci	  .import_ctx = gss_krb5_import_ctx_v1,
738c2ecf20Sopenharmony_ci	  .mk_key = gss_krb5_des3_make_key,
748c2ecf20Sopenharmony_ci	  .signalg = SGN_ALG_HMAC_SHA1_DES3_KD,
758c2ecf20Sopenharmony_ci	  .sealalg = SEAL_ALG_DES3KD,
768c2ecf20Sopenharmony_ci	  .keybytes = 21,
778c2ecf20Sopenharmony_ci	  .keylength = 24,
788c2ecf20Sopenharmony_ci	  .blocksize = 8,
798c2ecf20Sopenharmony_ci	  .conflen = 8,
808c2ecf20Sopenharmony_ci	  .cksumlength = 20,
818c2ecf20Sopenharmony_ci	  .keyed_cksum = 1,
828c2ecf20Sopenharmony_ci	},
838c2ecf20Sopenharmony_ci	/*
848c2ecf20Sopenharmony_ci	 * AES128
858c2ecf20Sopenharmony_ci	 */
868c2ecf20Sopenharmony_ci	{
878c2ecf20Sopenharmony_ci	  .etype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
888c2ecf20Sopenharmony_ci	  .ctype = CKSUMTYPE_HMAC_SHA1_96_AES128,
898c2ecf20Sopenharmony_ci	  .name = "aes128-cts",
908c2ecf20Sopenharmony_ci	  .encrypt_name = "cts(cbc(aes))",
918c2ecf20Sopenharmony_ci	  .cksum_name = "hmac(sha1)",
928c2ecf20Sopenharmony_ci	  .encrypt = krb5_encrypt,
938c2ecf20Sopenharmony_ci	  .decrypt = krb5_decrypt,
948c2ecf20Sopenharmony_ci	  .import_ctx = gss_krb5_import_ctx_v2,
958c2ecf20Sopenharmony_ci	  .mk_key = gss_krb5_aes_make_key,
968c2ecf20Sopenharmony_ci	  .encrypt_v2 = gss_krb5_aes_encrypt,
978c2ecf20Sopenharmony_ci	  .decrypt_v2 = gss_krb5_aes_decrypt,
988c2ecf20Sopenharmony_ci	  .signalg = -1,
998c2ecf20Sopenharmony_ci	  .sealalg = -1,
1008c2ecf20Sopenharmony_ci	  .keybytes = 16,
1018c2ecf20Sopenharmony_ci	  .keylength = 16,
1028c2ecf20Sopenharmony_ci	  .blocksize = 16,
1038c2ecf20Sopenharmony_ci	  .conflen = 16,
1048c2ecf20Sopenharmony_ci	  .cksumlength = 12,
1058c2ecf20Sopenharmony_ci	  .keyed_cksum = 1,
1068c2ecf20Sopenharmony_ci	},
1078c2ecf20Sopenharmony_ci	/*
1088c2ecf20Sopenharmony_ci	 * AES256
1098c2ecf20Sopenharmony_ci	 */
1108c2ecf20Sopenharmony_ci	{
1118c2ecf20Sopenharmony_ci	  .etype = ENCTYPE_AES256_CTS_HMAC_SHA1_96,
1128c2ecf20Sopenharmony_ci	  .ctype = CKSUMTYPE_HMAC_SHA1_96_AES256,
1138c2ecf20Sopenharmony_ci	  .name = "aes256-cts",
1148c2ecf20Sopenharmony_ci	  .encrypt_name = "cts(cbc(aes))",
1158c2ecf20Sopenharmony_ci	  .cksum_name = "hmac(sha1)",
1168c2ecf20Sopenharmony_ci	  .encrypt = krb5_encrypt,
1178c2ecf20Sopenharmony_ci	  .decrypt = krb5_decrypt,
1188c2ecf20Sopenharmony_ci	  .import_ctx = gss_krb5_import_ctx_v2,
1198c2ecf20Sopenharmony_ci	  .mk_key = gss_krb5_aes_make_key,
1208c2ecf20Sopenharmony_ci	  .encrypt_v2 = gss_krb5_aes_encrypt,
1218c2ecf20Sopenharmony_ci	  .decrypt_v2 = gss_krb5_aes_decrypt,
1228c2ecf20Sopenharmony_ci	  .signalg = -1,
1238c2ecf20Sopenharmony_ci	  .sealalg = -1,
1248c2ecf20Sopenharmony_ci	  .keybytes = 32,
1258c2ecf20Sopenharmony_ci	  .keylength = 32,
1268c2ecf20Sopenharmony_ci	  .blocksize = 16,
1278c2ecf20Sopenharmony_ci	  .conflen = 16,
1288c2ecf20Sopenharmony_ci	  .cksumlength = 12,
1298c2ecf20Sopenharmony_ci	  .keyed_cksum = 1,
1308c2ecf20Sopenharmony_ci	},
1318c2ecf20Sopenharmony_ci};
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistatic const int num_supported_enctypes =
1348c2ecf20Sopenharmony_ci	ARRAY_SIZE(supported_gss_krb5_enctypes);
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistatic int
1378c2ecf20Sopenharmony_cisupported_gss_krb5_enctype(int etype)
1388c2ecf20Sopenharmony_ci{
1398c2ecf20Sopenharmony_ci	int i;
1408c2ecf20Sopenharmony_ci	for (i = 0; i < num_supported_enctypes; i++)
1418c2ecf20Sopenharmony_ci		if (supported_gss_krb5_enctypes[i].etype == etype)
1428c2ecf20Sopenharmony_ci			return 1;
1438c2ecf20Sopenharmony_ci	return 0;
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic const struct gss_krb5_enctype *
1478c2ecf20Sopenharmony_ciget_gss_krb5_enctype(int etype)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	int i;
1508c2ecf20Sopenharmony_ci	for (i = 0; i < num_supported_enctypes; i++)
1518c2ecf20Sopenharmony_ci		if (supported_gss_krb5_enctypes[i].etype == etype)
1528c2ecf20Sopenharmony_ci			return &supported_gss_krb5_enctypes[i];
1538c2ecf20Sopenharmony_ci	return NULL;
1548c2ecf20Sopenharmony_ci}
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_cistatic inline const void *
1578c2ecf20Sopenharmony_ciget_key(const void *p, const void *end,
1588c2ecf20Sopenharmony_ci	struct krb5_ctx *ctx, struct crypto_sync_skcipher **res)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	struct xdr_netobj	key;
1618c2ecf20Sopenharmony_ci	int			alg;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	p = simple_get_bytes(p, end, &alg, sizeof(alg));
1648c2ecf20Sopenharmony_ci	if (IS_ERR(p))
1658c2ecf20Sopenharmony_ci		goto out_err;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	switch (alg) {
1688c2ecf20Sopenharmony_ci	case ENCTYPE_DES_CBC_CRC:
1698c2ecf20Sopenharmony_ci	case ENCTYPE_DES_CBC_MD4:
1708c2ecf20Sopenharmony_ci	case ENCTYPE_DES_CBC_MD5:
1718c2ecf20Sopenharmony_ci		/* Map all these key types to ENCTYPE_DES_CBC_RAW */
1728c2ecf20Sopenharmony_ci		alg = ENCTYPE_DES_CBC_RAW;
1738c2ecf20Sopenharmony_ci		break;
1748c2ecf20Sopenharmony_ci	}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	if (!supported_gss_krb5_enctype(alg)) {
1778c2ecf20Sopenharmony_ci		printk(KERN_WARNING "gss_kerberos_mech: unsupported "
1788c2ecf20Sopenharmony_ci			"encryption key algorithm %d\n", alg);
1798c2ecf20Sopenharmony_ci		p = ERR_PTR(-EINVAL);
1808c2ecf20Sopenharmony_ci		goto out_err;
1818c2ecf20Sopenharmony_ci	}
1828c2ecf20Sopenharmony_ci	p = simple_get_netobj(p, end, &key);
1838c2ecf20Sopenharmony_ci	if (IS_ERR(p))
1848c2ecf20Sopenharmony_ci		goto out_err;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	*res = crypto_alloc_sync_skcipher(ctx->gk5e->encrypt_name, 0, 0);
1878c2ecf20Sopenharmony_ci	if (IS_ERR(*res)) {
1888c2ecf20Sopenharmony_ci		printk(KERN_WARNING "gss_kerberos_mech: unable to initialize "
1898c2ecf20Sopenharmony_ci			"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
1908c2ecf20Sopenharmony_ci		*res = NULL;
1918c2ecf20Sopenharmony_ci		goto out_err_free_key;
1928c2ecf20Sopenharmony_ci	}
1938c2ecf20Sopenharmony_ci	if (crypto_sync_skcipher_setkey(*res, key.data, key.len)) {
1948c2ecf20Sopenharmony_ci		printk(KERN_WARNING "gss_kerberos_mech: error setting key for "
1958c2ecf20Sopenharmony_ci			"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
1968c2ecf20Sopenharmony_ci		goto out_err_free_tfm;
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	kfree(key.data);
2008c2ecf20Sopenharmony_ci	return p;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ciout_err_free_tfm:
2038c2ecf20Sopenharmony_ci	crypto_free_sync_skcipher(*res);
2048c2ecf20Sopenharmony_ciout_err_free_key:
2058c2ecf20Sopenharmony_ci	kfree(key.data);
2068c2ecf20Sopenharmony_ci	p = ERR_PTR(-EINVAL);
2078c2ecf20Sopenharmony_ciout_err:
2088c2ecf20Sopenharmony_ci	return p;
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_cistatic int
2128c2ecf20Sopenharmony_cigss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
2138c2ecf20Sopenharmony_ci{
2148c2ecf20Sopenharmony_ci	u32 seq_send;
2158c2ecf20Sopenharmony_ci	int tmp;
2168c2ecf20Sopenharmony_ci	u32 time32;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
2198c2ecf20Sopenharmony_ci	if (IS_ERR(p))
2208c2ecf20Sopenharmony_ci		goto out_err;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	/* Old format supports only DES!  Any other enctype uses new format */
2238c2ecf20Sopenharmony_ci	ctx->enctype = ENCTYPE_DES_CBC_RAW;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
2268c2ecf20Sopenharmony_ci	if (ctx->gk5e == NULL) {
2278c2ecf20Sopenharmony_ci		p = ERR_PTR(-EINVAL);
2288c2ecf20Sopenharmony_ci		goto out_err;
2298c2ecf20Sopenharmony_ci	}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/* The downcall format was designed before we completely understood
2328c2ecf20Sopenharmony_ci	 * the uses of the context fields; so it includes some stuff we
2338c2ecf20Sopenharmony_ci	 * just give some minimal sanity-checking, and some we ignore
2348c2ecf20Sopenharmony_ci	 * completely (like the next twenty bytes): */
2358c2ecf20Sopenharmony_ci	if (unlikely(p + 20 > end || p + 20 < p)) {
2368c2ecf20Sopenharmony_ci		p = ERR_PTR(-EFAULT);
2378c2ecf20Sopenharmony_ci		goto out_err;
2388c2ecf20Sopenharmony_ci	}
2398c2ecf20Sopenharmony_ci	p += 20;
2408c2ecf20Sopenharmony_ci	p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
2418c2ecf20Sopenharmony_ci	if (IS_ERR(p))
2428c2ecf20Sopenharmony_ci		goto out_err;
2438c2ecf20Sopenharmony_ci	if (tmp != SGN_ALG_DES_MAC_MD5) {
2448c2ecf20Sopenharmony_ci		p = ERR_PTR(-ENOSYS);
2458c2ecf20Sopenharmony_ci		goto out_err;
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci	p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
2488c2ecf20Sopenharmony_ci	if (IS_ERR(p))
2498c2ecf20Sopenharmony_ci		goto out_err;
2508c2ecf20Sopenharmony_ci	if (tmp != SEAL_ALG_DES) {
2518c2ecf20Sopenharmony_ci		p = ERR_PTR(-ENOSYS);
2528c2ecf20Sopenharmony_ci		goto out_err;
2538c2ecf20Sopenharmony_ci	}
2548c2ecf20Sopenharmony_ci	p = simple_get_bytes(p, end, &time32, sizeof(time32));
2558c2ecf20Sopenharmony_ci	if (IS_ERR(p))
2568c2ecf20Sopenharmony_ci		goto out_err;
2578c2ecf20Sopenharmony_ci	/* unsigned 32-bit time overflows in year 2106 */
2588c2ecf20Sopenharmony_ci	ctx->endtime = (time64_t)time32;
2598c2ecf20Sopenharmony_ci	p = simple_get_bytes(p, end, &seq_send, sizeof(seq_send));
2608c2ecf20Sopenharmony_ci	if (IS_ERR(p))
2618c2ecf20Sopenharmony_ci		goto out_err;
2628c2ecf20Sopenharmony_ci	atomic_set(&ctx->seq_send, seq_send);
2638c2ecf20Sopenharmony_ci	p = simple_get_netobj(p, end, &ctx->mech_used);
2648c2ecf20Sopenharmony_ci	if (IS_ERR(p))
2658c2ecf20Sopenharmony_ci		goto out_err;
2668c2ecf20Sopenharmony_ci	p = get_key(p, end, ctx, &ctx->enc);
2678c2ecf20Sopenharmony_ci	if (IS_ERR(p))
2688c2ecf20Sopenharmony_ci		goto out_err_free_mech;
2698c2ecf20Sopenharmony_ci	p = get_key(p, end, ctx, &ctx->seq);
2708c2ecf20Sopenharmony_ci	if (IS_ERR(p))
2718c2ecf20Sopenharmony_ci		goto out_err_free_key1;
2728c2ecf20Sopenharmony_ci	if (p != end) {
2738c2ecf20Sopenharmony_ci		p = ERR_PTR(-EFAULT);
2748c2ecf20Sopenharmony_ci		goto out_err_free_key2;
2758c2ecf20Sopenharmony_ci	}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	return 0;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ciout_err_free_key2:
2808c2ecf20Sopenharmony_ci	crypto_free_sync_skcipher(ctx->seq);
2818c2ecf20Sopenharmony_ciout_err_free_key1:
2828c2ecf20Sopenharmony_ci	crypto_free_sync_skcipher(ctx->enc);
2838c2ecf20Sopenharmony_ciout_err_free_mech:
2848c2ecf20Sopenharmony_ci	kfree(ctx->mech_used.data);
2858c2ecf20Sopenharmony_ciout_err:
2868c2ecf20Sopenharmony_ci	return PTR_ERR(p);
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_cistatic struct crypto_sync_skcipher *
2908c2ecf20Sopenharmony_cicontext_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	struct crypto_sync_skcipher *cp;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	cp = crypto_alloc_sync_skcipher(cname, 0, 0);
2958c2ecf20Sopenharmony_ci	if (IS_ERR(cp)) {
2968c2ecf20Sopenharmony_ci		dprintk("gss_kerberos_mech: unable to initialize "
2978c2ecf20Sopenharmony_ci			"crypto algorithm %s\n", cname);
2988c2ecf20Sopenharmony_ci		return NULL;
2998c2ecf20Sopenharmony_ci	}
3008c2ecf20Sopenharmony_ci	if (crypto_sync_skcipher_setkey(cp, key, ctx->gk5e->keylength)) {
3018c2ecf20Sopenharmony_ci		dprintk("gss_kerberos_mech: error setting key for "
3028c2ecf20Sopenharmony_ci			"crypto algorithm %s\n", cname);
3038c2ecf20Sopenharmony_ci		crypto_free_sync_skcipher(cp);
3048c2ecf20Sopenharmony_ci		return NULL;
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci	return cp;
3078c2ecf20Sopenharmony_ci}
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_cistatic inline void
3108c2ecf20Sopenharmony_ciset_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed)
3118c2ecf20Sopenharmony_ci{
3128c2ecf20Sopenharmony_ci	cdata[0] = (usage>>24)&0xff;
3138c2ecf20Sopenharmony_ci	cdata[1] = (usage>>16)&0xff;
3148c2ecf20Sopenharmony_ci	cdata[2] = (usage>>8)&0xff;
3158c2ecf20Sopenharmony_ci	cdata[3] = usage&0xff;
3168c2ecf20Sopenharmony_ci	cdata[4] = seed;
3178c2ecf20Sopenharmony_ci}
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_cistatic int
3208c2ecf20Sopenharmony_cigss_krb5_import_ctx_des(struct krb5_ctx *ctx, gfp_t gfp_mask)
3218c2ecf20Sopenharmony_ci{
3228c2ecf20Sopenharmony_ci	return -EINVAL;
3238c2ecf20Sopenharmony_ci}
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_cistatic int
3268c2ecf20Sopenharmony_cigss_krb5_import_ctx_v1(struct krb5_ctx *ctx, gfp_t gfp_mask)
3278c2ecf20Sopenharmony_ci{
3288c2ecf20Sopenharmony_ci	struct xdr_netobj c, keyin, keyout;
3298c2ecf20Sopenharmony_ci	u8 cdata[GSS_KRB5_K5CLENGTH];
3308c2ecf20Sopenharmony_ci	u32 err;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	c.len = GSS_KRB5_K5CLENGTH;
3338c2ecf20Sopenharmony_ci	c.data = cdata;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	keyin.data = ctx->Ksess;
3368c2ecf20Sopenharmony_ci	keyin.len = ctx->gk5e->keylength;
3378c2ecf20Sopenharmony_ci	keyout.len = ctx->gk5e->keylength;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	/* seq uses the raw key */
3408c2ecf20Sopenharmony_ci	ctx->seq = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
3418c2ecf20Sopenharmony_ci					   ctx->Ksess);
3428c2ecf20Sopenharmony_ci	if (ctx->seq == NULL)
3438c2ecf20Sopenharmony_ci		goto out_err;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	ctx->enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
3468c2ecf20Sopenharmony_ci					   ctx->Ksess);
3478c2ecf20Sopenharmony_ci	if (ctx->enc == NULL)
3488c2ecf20Sopenharmony_ci		goto out_free_seq;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	/* derive cksum */
3518c2ecf20Sopenharmony_ci	set_cdata(cdata, KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM);
3528c2ecf20Sopenharmony_ci	keyout.data = ctx->cksum;
3538c2ecf20Sopenharmony_ci	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
3548c2ecf20Sopenharmony_ci	if (err) {
3558c2ecf20Sopenharmony_ci		dprintk("%s: Error %d deriving cksum key\n",
3568c2ecf20Sopenharmony_ci			__func__, err);
3578c2ecf20Sopenharmony_ci		goto out_free_enc;
3588c2ecf20Sopenharmony_ci	}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	return 0;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ciout_free_enc:
3638c2ecf20Sopenharmony_ci	crypto_free_sync_skcipher(ctx->enc);
3648c2ecf20Sopenharmony_ciout_free_seq:
3658c2ecf20Sopenharmony_ci	crypto_free_sync_skcipher(ctx->seq);
3668c2ecf20Sopenharmony_ciout_err:
3678c2ecf20Sopenharmony_ci	return -EINVAL;
3688c2ecf20Sopenharmony_ci}
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_cistatic int
3718c2ecf20Sopenharmony_cigss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask)
3728c2ecf20Sopenharmony_ci{
3738c2ecf20Sopenharmony_ci	struct xdr_netobj c, keyin, keyout;
3748c2ecf20Sopenharmony_ci	u8 cdata[GSS_KRB5_K5CLENGTH];
3758c2ecf20Sopenharmony_ci	u32 err;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	c.len = GSS_KRB5_K5CLENGTH;
3788c2ecf20Sopenharmony_ci	c.data = cdata;
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	keyin.data = ctx->Ksess;
3818c2ecf20Sopenharmony_ci	keyin.len = ctx->gk5e->keylength;
3828c2ecf20Sopenharmony_ci	keyout.len = ctx->gk5e->keylength;
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	/* initiator seal encryption */
3858c2ecf20Sopenharmony_ci	set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
3868c2ecf20Sopenharmony_ci	keyout.data = ctx->initiator_seal;
3878c2ecf20Sopenharmony_ci	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
3888c2ecf20Sopenharmony_ci	if (err) {
3898c2ecf20Sopenharmony_ci		dprintk("%s: Error %d deriving initiator_seal key\n",
3908c2ecf20Sopenharmony_ci			__func__, err);
3918c2ecf20Sopenharmony_ci		goto out_err;
3928c2ecf20Sopenharmony_ci	}
3938c2ecf20Sopenharmony_ci	ctx->initiator_enc = context_v2_alloc_cipher(ctx,
3948c2ecf20Sopenharmony_ci						     ctx->gk5e->encrypt_name,
3958c2ecf20Sopenharmony_ci						     ctx->initiator_seal);
3968c2ecf20Sopenharmony_ci	if (ctx->initiator_enc == NULL)
3978c2ecf20Sopenharmony_ci		goto out_err;
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	/* acceptor seal encryption */
4008c2ecf20Sopenharmony_ci	set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
4018c2ecf20Sopenharmony_ci	keyout.data = ctx->acceptor_seal;
4028c2ecf20Sopenharmony_ci	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
4038c2ecf20Sopenharmony_ci	if (err) {
4048c2ecf20Sopenharmony_ci		dprintk("%s: Error %d deriving acceptor_seal key\n",
4058c2ecf20Sopenharmony_ci			__func__, err);
4068c2ecf20Sopenharmony_ci		goto out_free_initiator_enc;
4078c2ecf20Sopenharmony_ci	}
4088c2ecf20Sopenharmony_ci	ctx->acceptor_enc = context_v2_alloc_cipher(ctx,
4098c2ecf20Sopenharmony_ci						    ctx->gk5e->encrypt_name,
4108c2ecf20Sopenharmony_ci						    ctx->acceptor_seal);
4118c2ecf20Sopenharmony_ci	if (ctx->acceptor_enc == NULL)
4128c2ecf20Sopenharmony_ci		goto out_free_initiator_enc;
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	/* initiator sign checksum */
4158c2ecf20Sopenharmony_ci	set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
4168c2ecf20Sopenharmony_ci	keyout.data = ctx->initiator_sign;
4178c2ecf20Sopenharmony_ci	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
4188c2ecf20Sopenharmony_ci	if (err) {
4198c2ecf20Sopenharmony_ci		dprintk("%s: Error %d deriving initiator_sign key\n",
4208c2ecf20Sopenharmony_ci			__func__, err);
4218c2ecf20Sopenharmony_ci		goto out_free_acceptor_enc;
4228c2ecf20Sopenharmony_ci	}
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	/* acceptor sign checksum */
4258c2ecf20Sopenharmony_ci	set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
4268c2ecf20Sopenharmony_ci	keyout.data = ctx->acceptor_sign;
4278c2ecf20Sopenharmony_ci	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
4288c2ecf20Sopenharmony_ci	if (err) {
4298c2ecf20Sopenharmony_ci		dprintk("%s: Error %d deriving acceptor_sign key\n",
4308c2ecf20Sopenharmony_ci			__func__, err);
4318c2ecf20Sopenharmony_ci		goto out_free_acceptor_enc;
4328c2ecf20Sopenharmony_ci	}
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	/* initiator seal integrity */
4358c2ecf20Sopenharmony_ci	set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
4368c2ecf20Sopenharmony_ci	keyout.data = ctx->initiator_integ;
4378c2ecf20Sopenharmony_ci	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
4388c2ecf20Sopenharmony_ci	if (err) {
4398c2ecf20Sopenharmony_ci		dprintk("%s: Error %d deriving initiator_integ key\n",
4408c2ecf20Sopenharmony_ci			__func__, err);
4418c2ecf20Sopenharmony_ci		goto out_free_acceptor_enc;
4428c2ecf20Sopenharmony_ci	}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	/* acceptor seal integrity */
4458c2ecf20Sopenharmony_ci	set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
4468c2ecf20Sopenharmony_ci	keyout.data = ctx->acceptor_integ;
4478c2ecf20Sopenharmony_ci	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
4488c2ecf20Sopenharmony_ci	if (err) {
4498c2ecf20Sopenharmony_ci		dprintk("%s: Error %d deriving acceptor_integ key\n",
4508c2ecf20Sopenharmony_ci			__func__, err);
4518c2ecf20Sopenharmony_ci		goto out_free_acceptor_enc;
4528c2ecf20Sopenharmony_ci	}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	switch (ctx->enctype) {
4558c2ecf20Sopenharmony_ci	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
4568c2ecf20Sopenharmony_ci	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
4578c2ecf20Sopenharmony_ci		ctx->initiator_enc_aux =
4588c2ecf20Sopenharmony_ci			context_v2_alloc_cipher(ctx, "cbc(aes)",
4598c2ecf20Sopenharmony_ci						ctx->initiator_seal);
4608c2ecf20Sopenharmony_ci		if (ctx->initiator_enc_aux == NULL)
4618c2ecf20Sopenharmony_ci			goto out_free_acceptor_enc;
4628c2ecf20Sopenharmony_ci		ctx->acceptor_enc_aux =
4638c2ecf20Sopenharmony_ci			context_v2_alloc_cipher(ctx, "cbc(aes)",
4648c2ecf20Sopenharmony_ci						ctx->acceptor_seal);
4658c2ecf20Sopenharmony_ci		if (ctx->acceptor_enc_aux == NULL) {
4668c2ecf20Sopenharmony_ci			crypto_free_sync_skcipher(ctx->initiator_enc_aux);
4678c2ecf20Sopenharmony_ci			goto out_free_acceptor_enc;
4688c2ecf20Sopenharmony_ci		}
4698c2ecf20Sopenharmony_ci	}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	return 0;
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ciout_free_acceptor_enc:
4748c2ecf20Sopenharmony_ci	crypto_free_sync_skcipher(ctx->acceptor_enc);
4758c2ecf20Sopenharmony_ciout_free_initiator_enc:
4768c2ecf20Sopenharmony_ci	crypto_free_sync_skcipher(ctx->initiator_enc);
4778c2ecf20Sopenharmony_ciout_err:
4788c2ecf20Sopenharmony_ci	return -EINVAL;
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cistatic int
4828c2ecf20Sopenharmony_cigss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
4838c2ecf20Sopenharmony_ci		gfp_t gfp_mask)
4848c2ecf20Sopenharmony_ci{
4858c2ecf20Sopenharmony_ci	u64 seq_send64;
4868c2ecf20Sopenharmony_ci	int keylen;
4878c2ecf20Sopenharmony_ci	u32 time32;
4888c2ecf20Sopenharmony_ci	int ret;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
4918c2ecf20Sopenharmony_ci	if (IS_ERR(p))
4928c2ecf20Sopenharmony_ci		goto out_err;
4938c2ecf20Sopenharmony_ci	ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	p = simple_get_bytes(p, end, &time32, sizeof(time32));
4968c2ecf20Sopenharmony_ci	if (IS_ERR(p))
4978c2ecf20Sopenharmony_ci		goto out_err;
4988c2ecf20Sopenharmony_ci	/* unsigned 32-bit time overflows in year 2106 */
4998c2ecf20Sopenharmony_ci	ctx->endtime = (time64_t)time32;
5008c2ecf20Sopenharmony_ci	p = simple_get_bytes(p, end, &seq_send64, sizeof(seq_send64));
5018c2ecf20Sopenharmony_ci	if (IS_ERR(p))
5028c2ecf20Sopenharmony_ci		goto out_err;
5038c2ecf20Sopenharmony_ci	atomic64_set(&ctx->seq_send64, seq_send64);
5048c2ecf20Sopenharmony_ci	/* set seq_send for use by "older" enctypes */
5058c2ecf20Sopenharmony_ci	atomic_set(&ctx->seq_send, seq_send64);
5068c2ecf20Sopenharmony_ci	if (seq_send64 != atomic_read(&ctx->seq_send)) {
5078c2ecf20Sopenharmony_ci		dprintk("%s: seq_send64 %llx, seq_send %x overflow?\n", __func__,
5088c2ecf20Sopenharmony_ci			seq_send64, atomic_read(&ctx->seq_send));
5098c2ecf20Sopenharmony_ci		p = ERR_PTR(-EINVAL);
5108c2ecf20Sopenharmony_ci		goto out_err;
5118c2ecf20Sopenharmony_ci	}
5128c2ecf20Sopenharmony_ci	p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
5138c2ecf20Sopenharmony_ci	if (IS_ERR(p))
5148c2ecf20Sopenharmony_ci		goto out_err;
5158c2ecf20Sopenharmony_ci	/* Map ENCTYPE_DES3_CBC_SHA1 to ENCTYPE_DES3_CBC_RAW */
5168c2ecf20Sopenharmony_ci	if (ctx->enctype == ENCTYPE_DES3_CBC_SHA1)
5178c2ecf20Sopenharmony_ci		ctx->enctype = ENCTYPE_DES3_CBC_RAW;
5188c2ecf20Sopenharmony_ci	ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
5198c2ecf20Sopenharmony_ci	if (ctx->gk5e == NULL) {
5208c2ecf20Sopenharmony_ci		dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
5218c2ecf20Sopenharmony_ci			ctx->enctype);
5228c2ecf20Sopenharmony_ci		p = ERR_PTR(-EINVAL);
5238c2ecf20Sopenharmony_ci		goto out_err;
5248c2ecf20Sopenharmony_ci	}
5258c2ecf20Sopenharmony_ci	keylen = ctx->gk5e->keylength;
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	p = simple_get_bytes(p, end, ctx->Ksess, keylen);
5288c2ecf20Sopenharmony_ci	if (IS_ERR(p))
5298c2ecf20Sopenharmony_ci		goto out_err;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	if (p != end) {
5328c2ecf20Sopenharmony_ci		p = ERR_PTR(-EINVAL);
5338c2ecf20Sopenharmony_ci		goto out_err;
5348c2ecf20Sopenharmony_ci	}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,
5378c2ecf20Sopenharmony_ci				      gss_kerberos_mech.gm_oid.len, gfp_mask);
5388c2ecf20Sopenharmony_ci	if (unlikely(ctx->mech_used.data == NULL)) {
5398c2ecf20Sopenharmony_ci		p = ERR_PTR(-ENOMEM);
5408c2ecf20Sopenharmony_ci		goto out_err;
5418c2ecf20Sopenharmony_ci	}
5428c2ecf20Sopenharmony_ci	ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	ret = gss_krb5_import_ctx_v2(ctx, gfp_mask);
5458c2ecf20Sopenharmony_ci	if (ret) {
5468c2ecf20Sopenharmony_ci		p = ERR_PTR(ret);
5478c2ecf20Sopenharmony_ci		goto out_free;
5488c2ecf20Sopenharmony_ci	}
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	return 0;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ciout_free:
5538c2ecf20Sopenharmony_ci	kfree(ctx->mech_used.data);
5548c2ecf20Sopenharmony_ciout_err:
5558c2ecf20Sopenharmony_ci	return PTR_ERR(p);
5568c2ecf20Sopenharmony_ci}
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_cistatic int
5598c2ecf20Sopenharmony_cigss_import_sec_context_kerberos(const void *p, size_t len,
5608c2ecf20Sopenharmony_ci				struct gss_ctx *ctx_id,
5618c2ecf20Sopenharmony_ci				time64_t *endtime,
5628c2ecf20Sopenharmony_ci				gfp_t gfp_mask)
5638c2ecf20Sopenharmony_ci{
5648c2ecf20Sopenharmony_ci	const void *end = (const void *)((const char *)p + len);
5658c2ecf20Sopenharmony_ci	struct  krb5_ctx *ctx;
5668c2ecf20Sopenharmony_ci	int ret;
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	ctx = kzalloc(sizeof(*ctx), gfp_mask);
5698c2ecf20Sopenharmony_ci	if (ctx == NULL)
5708c2ecf20Sopenharmony_ci		return -ENOMEM;
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	if (len == 85)
5738c2ecf20Sopenharmony_ci		ret = gss_import_v1_context(p, end, ctx);
5748c2ecf20Sopenharmony_ci	else
5758c2ecf20Sopenharmony_ci		ret = gss_import_v2_context(p, end, ctx, gfp_mask);
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	if (ret == 0) {
5788c2ecf20Sopenharmony_ci		ctx_id->internal_ctx_id = ctx;
5798c2ecf20Sopenharmony_ci		if (endtime)
5808c2ecf20Sopenharmony_ci			*endtime = ctx->endtime;
5818c2ecf20Sopenharmony_ci	} else
5828c2ecf20Sopenharmony_ci		kfree(ctx);
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	dprintk("RPC:       %s: returning %d\n", __func__, ret);
5858c2ecf20Sopenharmony_ci	return ret;
5868c2ecf20Sopenharmony_ci}
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_cistatic void
5898c2ecf20Sopenharmony_cigss_delete_sec_context_kerberos(void *internal_ctx) {
5908c2ecf20Sopenharmony_ci	struct krb5_ctx *kctx = internal_ctx;
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci	crypto_free_sync_skcipher(kctx->seq);
5938c2ecf20Sopenharmony_ci	crypto_free_sync_skcipher(kctx->enc);
5948c2ecf20Sopenharmony_ci	crypto_free_sync_skcipher(kctx->acceptor_enc);
5958c2ecf20Sopenharmony_ci	crypto_free_sync_skcipher(kctx->initiator_enc);
5968c2ecf20Sopenharmony_ci	crypto_free_sync_skcipher(kctx->acceptor_enc_aux);
5978c2ecf20Sopenharmony_ci	crypto_free_sync_skcipher(kctx->initiator_enc_aux);
5988c2ecf20Sopenharmony_ci	kfree(kctx->mech_used.data);
5998c2ecf20Sopenharmony_ci	kfree(kctx);
6008c2ecf20Sopenharmony_ci}
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_cistatic const struct gss_api_ops gss_kerberos_ops = {
6038c2ecf20Sopenharmony_ci	.gss_import_sec_context	= gss_import_sec_context_kerberos,
6048c2ecf20Sopenharmony_ci	.gss_get_mic		= gss_get_mic_kerberos,
6058c2ecf20Sopenharmony_ci	.gss_verify_mic		= gss_verify_mic_kerberos,
6068c2ecf20Sopenharmony_ci	.gss_wrap		= gss_wrap_kerberos,
6078c2ecf20Sopenharmony_ci	.gss_unwrap		= gss_unwrap_kerberos,
6088c2ecf20Sopenharmony_ci	.gss_delete_sec_context	= gss_delete_sec_context_kerberos,
6098c2ecf20Sopenharmony_ci};
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_cistatic struct pf_desc gss_kerberos_pfs[] = {
6128c2ecf20Sopenharmony_ci	[0] = {
6138c2ecf20Sopenharmony_ci		.pseudoflavor = RPC_AUTH_GSS_KRB5,
6148c2ecf20Sopenharmony_ci		.qop = GSS_C_QOP_DEFAULT,
6158c2ecf20Sopenharmony_ci		.service = RPC_GSS_SVC_NONE,
6168c2ecf20Sopenharmony_ci		.name = "krb5",
6178c2ecf20Sopenharmony_ci	},
6188c2ecf20Sopenharmony_ci	[1] = {
6198c2ecf20Sopenharmony_ci		.pseudoflavor = RPC_AUTH_GSS_KRB5I,
6208c2ecf20Sopenharmony_ci		.qop = GSS_C_QOP_DEFAULT,
6218c2ecf20Sopenharmony_ci		.service = RPC_GSS_SVC_INTEGRITY,
6228c2ecf20Sopenharmony_ci		.name = "krb5i",
6238c2ecf20Sopenharmony_ci		.datatouch = true,
6248c2ecf20Sopenharmony_ci	},
6258c2ecf20Sopenharmony_ci	[2] = {
6268c2ecf20Sopenharmony_ci		.pseudoflavor = RPC_AUTH_GSS_KRB5P,
6278c2ecf20Sopenharmony_ci		.qop = GSS_C_QOP_DEFAULT,
6288c2ecf20Sopenharmony_ci		.service = RPC_GSS_SVC_PRIVACY,
6298c2ecf20Sopenharmony_ci		.name = "krb5p",
6308c2ecf20Sopenharmony_ci		.datatouch = true,
6318c2ecf20Sopenharmony_ci	},
6328c2ecf20Sopenharmony_ci};
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-krb5");
6358c2ecf20Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-krb5i");
6368c2ecf20Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-krb5p");
6378c2ecf20Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-390003");
6388c2ecf20Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-390004");
6398c2ecf20Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-390005");
6408c2ecf20Sopenharmony_ciMODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_cistatic struct gss_api_mech gss_kerberos_mech = {
6438c2ecf20Sopenharmony_ci	.gm_name	= "krb5",
6448c2ecf20Sopenharmony_ci	.gm_owner	= THIS_MODULE,
6458c2ecf20Sopenharmony_ci	.gm_oid		= { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },
6468c2ecf20Sopenharmony_ci	.gm_ops		= &gss_kerberos_ops,
6478c2ecf20Sopenharmony_ci	.gm_pf_num	= ARRAY_SIZE(gss_kerberos_pfs),
6488c2ecf20Sopenharmony_ci	.gm_pfs		= gss_kerberos_pfs,
6498c2ecf20Sopenharmony_ci	.gm_upcall_enctypes = KRB5_SUPPORTED_ENCTYPES,
6508c2ecf20Sopenharmony_ci};
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_cistatic int __init init_kerberos_module(void)
6538c2ecf20Sopenharmony_ci{
6548c2ecf20Sopenharmony_ci	int status;
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	status = gss_mech_register(&gss_kerberos_mech);
6578c2ecf20Sopenharmony_ci	if (status)
6588c2ecf20Sopenharmony_ci		printk("Failed to register kerberos gss mechanism!\n");
6598c2ecf20Sopenharmony_ci	return status;
6608c2ecf20Sopenharmony_ci}
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_cistatic void __exit cleanup_kerberos_module(void)
6638c2ecf20Sopenharmony_ci{
6648c2ecf20Sopenharmony_ci	gss_mech_unregister(&gss_kerberos_mech);
6658c2ecf20Sopenharmony_ci}
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
6688c2ecf20Sopenharmony_cimodule_init(init_kerberos_module);
6698c2ecf20Sopenharmony_cimodule_exit(cleanup_kerberos_module);
670