1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * linux/net/sunrpc/gss_krb5_mech.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2001-2008 The Regents of the University of Michigan.
6*4882a593Smuzhiyun * All rights reserved.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Andy Adamson <andros@umich.edu>
9*4882a593Smuzhiyun * J. Bruce Fields <bfields@umich.edu>
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <crypto/hash.h>
13*4882a593Smuzhiyun #include <crypto/skcipher.h>
14*4882a593Smuzhiyun #include <linux/err.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/init.h>
17*4882a593Smuzhiyun #include <linux/types.h>
18*4882a593Smuzhiyun #include <linux/slab.h>
19*4882a593Smuzhiyun #include <linux/sunrpc/auth.h>
20*4882a593Smuzhiyun #include <linux/sunrpc/gss_krb5.h>
21*4882a593Smuzhiyun #include <linux/sunrpc/xdr.h>
22*4882a593Smuzhiyun #include <linux/sunrpc/gss_krb5_enctypes.h>
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #include "auth_gss_internal.h"
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
27*4882a593Smuzhiyun # define RPCDBG_FACILITY RPCDBG_AUTH
28*4882a593Smuzhiyun #endif
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static struct gss_api_mech gss_kerberos_mech; /* forward declaration */
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
33*4882a593Smuzhiyun #ifndef CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES
34*4882a593Smuzhiyun /*
35*4882a593Smuzhiyun * DES (All DES enctypes are mapped to the same gss functionality)
36*4882a593Smuzhiyun */
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun .etype = ENCTYPE_DES_CBC_RAW,
39*4882a593Smuzhiyun .ctype = CKSUMTYPE_RSA_MD5,
40*4882a593Smuzhiyun .name = "des-cbc-crc",
41*4882a593Smuzhiyun .encrypt_name = "cbc(des)",
42*4882a593Smuzhiyun .cksum_name = "md5",
43*4882a593Smuzhiyun .encrypt = krb5_encrypt,
44*4882a593Smuzhiyun .decrypt = krb5_decrypt,
45*4882a593Smuzhiyun .mk_key = NULL,
46*4882a593Smuzhiyun .signalg = SGN_ALG_DES_MAC_MD5,
47*4882a593Smuzhiyun .sealalg = SEAL_ALG_DES,
48*4882a593Smuzhiyun .keybytes = 7,
49*4882a593Smuzhiyun .keylength = 8,
50*4882a593Smuzhiyun .blocksize = 8,
51*4882a593Smuzhiyun .conflen = 8,
52*4882a593Smuzhiyun .cksumlength = 8,
53*4882a593Smuzhiyun .keyed_cksum = 0,
54*4882a593Smuzhiyun },
55*4882a593Smuzhiyun #endif /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */
56*4882a593Smuzhiyun /*
57*4882a593Smuzhiyun * 3DES
58*4882a593Smuzhiyun */
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun .etype = ENCTYPE_DES3_CBC_RAW,
61*4882a593Smuzhiyun .ctype = CKSUMTYPE_HMAC_SHA1_DES3,
62*4882a593Smuzhiyun .name = "des3-hmac-sha1",
63*4882a593Smuzhiyun .encrypt_name = "cbc(des3_ede)",
64*4882a593Smuzhiyun .cksum_name = "hmac(sha1)",
65*4882a593Smuzhiyun .encrypt = krb5_encrypt,
66*4882a593Smuzhiyun .decrypt = krb5_decrypt,
67*4882a593Smuzhiyun .mk_key = gss_krb5_des3_make_key,
68*4882a593Smuzhiyun .signalg = SGN_ALG_HMAC_SHA1_DES3_KD,
69*4882a593Smuzhiyun .sealalg = SEAL_ALG_DES3KD,
70*4882a593Smuzhiyun .keybytes = 21,
71*4882a593Smuzhiyun .keylength = 24,
72*4882a593Smuzhiyun .blocksize = 8,
73*4882a593Smuzhiyun .conflen = 8,
74*4882a593Smuzhiyun .cksumlength = 20,
75*4882a593Smuzhiyun .keyed_cksum = 1,
76*4882a593Smuzhiyun },
77*4882a593Smuzhiyun /*
78*4882a593Smuzhiyun * AES128
79*4882a593Smuzhiyun */
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun .etype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
82*4882a593Smuzhiyun .ctype = CKSUMTYPE_HMAC_SHA1_96_AES128,
83*4882a593Smuzhiyun .name = "aes128-cts",
84*4882a593Smuzhiyun .encrypt_name = "cts(cbc(aes))",
85*4882a593Smuzhiyun .cksum_name = "hmac(sha1)",
86*4882a593Smuzhiyun .encrypt = krb5_encrypt,
87*4882a593Smuzhiyun .decrypt = krb5_decrypt,
88*4882a593Smuzhiyun .mk_key = gss_krb5_aes_make_key,
89*4882a593Smuzhiyun .encrypt_v2 = gss_krb5_aes_encrypt,
90*4882a593Smuzhiyun .decrypt_v2 = gss_krb5_aes_decrypt,
91*4882a593Smuzhiyun .signalg = -1,
92*4882a593Smuzhiyun .sealalg = -1,
93*4882a593Smuzhiyun .keybytes = 16,
94*4882a593Smuzhiyun .keylength = 16,
95*4882a593Smuzhiyun .blocksize = 16,
96*4882a593Smuzhiyun .conflen = 16,
97*4882a593Smuzhiyun .cksumlength = 12,
98*4882a593Smuzhiyun .keyed_cksum = 1,
99*4882a593Smuzhiyun },
100*4882a593Smuzhiyun /*
101*4882a593Smuzhiyun * AES256
102*4882a593Smuzhiyun */
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun .etype = ENCTYPE_AES256_CTS_HMAC_SHA1_96,
105*4882a593Smuzhiyun .ctype = CKSUMTYPE_HMAC_SHA1_96_AES256,
106*4882a593Smuzhiyun .name = "aes256-cts",
107*4882a593Smuzhiyun .encrypt_name = "cts(cbc(aes))",
108*4882a593Smuzhiyun .cksum_name = "hmac(sha1)",
109*4882a593Smuzhiyun .encrypt = krb5_encrypt,
110*4882a593Smuzhiyun .decrypt = krb5_decrypt,
111*4882a593Smuzhiyun .mk_key = gss_krb5_aes_make_key,
112*4882a593Smuzhiyun .encrypt_v2 = gss_krb5_aes_encrypt,
113*4882a593Smuzhiyun .decrypt_v2 = gss_krb5_aes_decrypt,
114*4882a593Smuzhiyun .signalg = -1,
115*4882a593Smuzhiyun .sealalg = -1,
116*4882a593Smuzhiyun .keybytes = 32,
117*4882a593Smuzhiyun .keylength = 32,
118*4882a593Smuzhiyun .blocksize = 16,
119*4882a593Smuzhiyun .conflen = 16,
120*4882a593Smuzhiyun .cksumlength = 12,
121*4882a593Smuzhiyun .keyed_cksum = 1,
122*4882a593Smuzhiyun },
123*4882a593Smuzhiyun };
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun static const int num_supported_enctypes =
126*4882a593Smuzhiyun ARRAY_SIZE(supported_gss_krb5_enctypes);
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun static int
supported_gss_krb5_enctype(int etype)129*4882a593Smuzhiyun supported_gss_krb5_enctype(int etype)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun int i;
132*4882a593Smuzhiyun for (i = 0; i < num_supported_enctypes; i++)
133*4882a593Smuzhiyun if (supported_gss_krb5_enctypes[i].etype == etype)
134*4882a593Smuzhiyun return 1;
135*4882a593Smuzhiyun return 0;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun static const struct gss_krb5_enctype *
get_gss_krb5_enctype(int etype)139*4882a593Smuzhiyun get_gss_krb5_enctype(int etype)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun int i;
142*4882a593Smuzhiyun for (i = 0; i < num_supported_enctypes; i++)
143*4882a593Smuzhiyun if (supported_gss_krb5_enctypes[i].etype == etype)
144*4882a593Smuzhiyun return &supported_gss_krb5_enctypes[i];
145*4882a593Smuzhiyun return NULL;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun static inline const void *
get_key(const void * p,const void * end,struct krb5_ctx * ctx,struct crypto_sync_skcipher ** res)149*4882a593Smuzhiyun get_key(const void *p, const void *end,
150*4882a593Smuzhiyun struct krb5_ctx *ctx, struct crypto_sync_skcipher **res)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun struct xdr_netobj key;
153*4882a593Smuzhiyun int alg;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun p = simple_get_bytes(p, end, &alg, sizeof(alg));
156*4882a593Smuzhiyun if (IS_ERR(p))
157*4882a593Smuzhiyun goto out_err;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun switch (alg) {
160*4882a593Smuzhiyun case ENCTYPE_DES_CBC_CRC:
161*4882a593Smuzhiyun case ENCTYPE_DES_CBC_MD4:
162*4882a593Smuzhiyun case ENCTYPE_DES_CBC_MD5:
163*4882a593Smuzhiyun /* Map all these key types to ENCTYPE_DES_CBC_RAW */
164*4882a593Smuzhiyun alg = ENCTYPE_DES_CBC_RAW;
165*4882a593Smuzhiyun break;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun if (!supported_gss_krb5_enctype(alg)) {
169*4882a593Smuzhiyun printk(KERN_WARNING "gss_kerberos_mech: unsupported "
170*4882a593Smuzhiyun "encryption key algorithm %d\n", alg);
171*4882a593Smuzhiyun p = ERR_PTR(-EINVAL);
172*4882a593Smuzhiyun goto out_err;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun p = simple_get_netobj(p, end, &key);
175*4882a593Smuzhiyun if (IS_ERR(p))
176*4882a593Smuzhiyun goto out_err;
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun *res = crypto_alloc_sync_skcipher(ctx->gk5e->encrypt_name, 0, 0);
179*4882a593Smuzhiyun if (IS_ERR(*res)) {
180*4882a593Smuzhiyun printk(KERN_WARNING "gss_kerberos_mech: unable to initialize "
181*4882a593Smuzhiyun "crypto algorithm %s\n", ctx->gk5e->encrypt_name);
182*4882a593Smuzhiyun *res = NULL;
183*4882a593Smuzhiyun goto out_err_free_key;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun if (crypto_sync_skcipher_setkey(*res, key.data, key.len)) {
186*4882a593Smuzhiyun printk(KERN_WARNING "gss_kerberos_mech: error setting key for "
187*4882a593Smuzhiyun "crypto algorithm %s\n", ctx->gk5e->encrypt_name);
188*4882a593Smuzhiyun goto out_err_free_tfm;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun kfree(key.data);
192*4882a593Smuzhiyun return p;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun out_err_free_tfm:
195*4882a593Smuzhiyun crypto_free_sync_skcipher(*res);
196*4882a593Smuzhiyun out_err_free_key:
197*4882a593Smuzhiyun kfree(key.data);
198*4882a593Smuzhiyun p = ERR_PTR(-EINVAL);
199*4882a593Smuzhiyun out_err:
200*4882a593Smuzhiyun return p;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun static int
gss_import_v1_context(const void * p,const void * end,struct krb5_ctx * ctx)204*4882a593Smuzhiyun gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun u32 seq_send;
207*4882a593Smuzhiyun int tmp;
208*4882a593Smuzhiyun u32 time32;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
211*4882a593Smuzhiyun if (IS_ERR(p))
212*4882a593Smuzhiyun goto out_err;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun /* Old format supports only DES! Any other enctype uses new format */
215*4882a593Smuzhiyun ctx->enctype = ENCTYPE_DES_CBC_RAW;
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
218*4882a593Smuzhiyun if (ctx->gk5e == NULL) {
219*4882a593Smuzhiyun p = ERR_PTR(-EINVAL);
220*4882a593Smuzhiyun goto out_err;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun /* The downcall format was designed before we completely understood
224*4882a593Smuzhiyun * the uses of the context fields; so it includes some stuff we
225*4882a593Smuzhiyun * just give some minimal sanity-checking, and some we ignore
226*4882a593Smuzhiyun * completely (like the next twenty bytes): */
227*4882a593Smuzhiyun if (unlikely(p + 20 > end || p + 20 < p)) {
228*4882a593Smuzhiyun p = ERR_PTR(-EFAULT);
229*4882a593Smuzhiyun goto out_err;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun p += 20;
232*4882a593Smuzhiyun p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
233*4882a593Smuzhiyun if (IS_ERR(p))
234*4882a593Smuzhiyun goto out_err;
235*4882a593Smuzhiyun if (tmp != SGN_ALG_DES_MAC_MD5) {
236*4882a593Smuzhiyun p = ERR_PTR(-ENOSYS);
237*4882a593Smuzhiyun goto out_err;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
240*4882a593Smuzhiyun if (IS_ERR(p))
241*4882a593Smuzhiyun goto out_err;
242*4882a593Smuzhiyun if (tmp != SEAL_ALG_DES) {
243*4882a593Smuzhiyun p = ERR_PTR(-ENOSYS);
244*4882a593Smuzhiyun goto out_err;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun p = simple_get_bytes(p, end, &time32, sizeof(time32));
247*4882a593Smuzhiyun if (IS_ERR(p))
248*4882a593Smuzhiyun goto out_err;
249*4882a593Smuzhiyun /* unsigned 32-bit time overflows in year 2106 */
250*4882a593Smuzhiyun ctx->endtime = (time64_t)time32;
251*4882a593Smuzhiyun p = simple_get_bytes(p, end, &seq_send, sizeof(seq_send));
252*4882a593Smuzhiyun if (IS_ERR(p))
253*4882a593Smuzhiyun goto out_err;
254*4882a593Smuzhiyun atomic_set(&ctx->seq_send, seq_send);
255*4882a593Smuzhiyun p = simple_get_netobj(p, end, &ctx->mech_used);
256*4882a593Smuzhiyun if (IS_ERR(p))
257*4882a593Smuzhiyun goto out_err;
258*4882a593Smuzhiyun p = get_key(p, end, ctx, &ctx->enc);
259*4882a593Smuzhiyun if (IS_ERR(p))
260*4882a593Smuzhiyun goto out_err_free_mech;
261*4882a593Smuzhiyun p = get_key(p, end, ctx, &ctx->seq);
262*4882a593Smuzhiyun if (IS_ERR(p))
263*4882a593Smuzhiyun goto out_err_free_key1;
264*4882a593Smuzhiyun if (p != end) {
265*4882a593Smuzhiyun p = ERR_PTR(-EFAULT);
266*4882a593Smuzhiyun goto out_err_free_key2;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun return 0;
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun out_err_free_key2:
272*4882a593Smuzhiyun crypto_free_sync_skcipher(ctx->seq);
273*4882a593Smuzhiyun out_err_free_key1:
274*4882a593Smuzhiyun crypto_free_sync_skcipher(ctx->enc);
275*4882a593Smuzhiyun out_err_free_mech:
276*4882a593Smuzhiyun kfree(ctx->mech_used.data);
277*4882a593Smuzhiyun out_err:
278*4882a593Smuzhiyun return PTR_ERR(p);
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun static struct crypto_sync_skcipher *
context_v2_alloc_cipher(struct krb5_ctx * ctx,const char * cname,u8 * key)282*4882a593Smuzhiyun context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun struct crypto_sync_skcipher *cp;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun cp = crypto_alloc_sync_skcipher(cname, 0, 0);
287*4882a593Smuzhiyun if (IS_ERR(cp)) {
288*4882a593Smuzhiyun dprintk("gss_kerberos_mech: unable to initialize "
289*4882a593Smuzhiyun "crypto algorithm %s\n", cname);
290*4882a593Smuzhiyun return NULL;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun if (crypto_sync_skcipher_setkey(cp, key, ctx->gk5e->keylength)) {
293*4882a593Smuzhiyun dprintk("gss_kerberos_mech: error setting key for "
294*4882a593Smuzhiyun "crypto algorithm %s\n", cname);
295*4882a593Smuzhiyun crypto_free_sync_skcipher(cp);
296*4882a593Smuzhiyun return NULL;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun return cp;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun static inline void
set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH],u32 usage,u8 seed)302*4882a593Smuzhiyun set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun cdata[0] = (usage>>24)&0xff;
305*4882a593Smuzhiyun cdata[1] = (usage>>16)&0xff;
306*4882a593Smuzhiyun cdata[2] = (usage>>8)&0xff;
307*4882a593Smuzhiyun cdata[3] = usage&0xff;
308*4882a593Smuzhiyun cdata[4] = seed;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun static int
context_derive_keys_des3(struct krb5_ctx * ctx,gfp_t gfp_mask)312*4882a593Smuzhiyun context_derive_keys_des3(struct krb5_ctx *ctx, gfp_t gfp_mask)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun struct xdr_netobj c, keyin, keyout;
315*4882a593Smuzhiyun u8 cdata[GSS_KRB5_K5CLENGTH];
316*4882a593Smuzhiyun u32 err;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun c.len = GSS_KRB5_K5CLENGTH;
319*4882a593Smuzhiyun c.data = cdata;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun keyin.data = ctx->Ksess;
322*4882a593Smuzhiyun keyin.len = ctx->gk5e->keylength;
323*4882a593Smuzhiyun keyout.len = ctx->gk5e->keylength;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun /* seq uses the raw key */
326*4882a593Smuzhiyun ctx->seq = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
327*4882a593Smuzhiyun ctx->Ksess);
328*4882a593Smuzhiyun if (ctx->seq == NULL)
329*4882a593Smuzhiyun goto out_err;
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun ctx->enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,
332*4882a593Smuzhiyun ctx->Ksess);
333*4882a593Smuzhiyun if (ctx->enc == NULL)
334*4882a593Smuzhiyun goto out_free_seq;
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun /* derive cksum */
337*4882a593Smuzhiyun set_cdata(cdata, KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM);
338*4882a593Smuzhiyun keyout.data = ctx->cksum;
339*4882a593Smuzhiyun err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
340*4882a593Smuzhiyun if (err) {
341*4882a593Smuzhiyun dprintk("%s: Error %d deriving cksum key\n",
342*4882a593Smuzhiyun __func__, err);
343*4882a593Smuzhiyun goto out_free_enc;
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun return 0;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun out_free_enc:
349*4882a593Smuzhiyun crypto_free_sync_skcipher(ctx->enc);
350*4882a593Smuzhiyun out_free_seq:
351*4882a593Smuzhiyun crypto_free_sync_skcipher(ctx->seq);
352*4882a593Smuzhiyun out_err:
353*4882a593Smuzhiyun return -EINVAL;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun static int
context_derive_keys_new(struct krb5_ctx * ctx,gfp_t gfp_mask)357*4882a593Smuzhiyun context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun struct xdr_netobj c, keyin, keyout;
360*4882a593Smuzhiyun u8 cdata[GSS_KRB5_K5CLENGTH];
361*4882a593Smuzhiyun u32 err;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun c.len = GSS_KRB5_K5CLENGTH;
364*4882a593Smuzhiyun c.data = cdata;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun keyin.data = ctx->Ksess;
367*4882a593Smuzhiyun keyin.len = ctx->gk5e->keylength;
368*4882a593Smuzhiyun keyout.len = ctx->gk5e->keylength;
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun /* initiator seal encryption */
371*4882a593Smuzhiyun set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
372*4882a593Smuzhiyun keyout.data = ctx->initiator_seal;
373*4882a593Smuzhiyun err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
374*4882a593Smuzhiyun if (err) {
375*4882a593Smuzhiyun dprintk("%s: Error %d deriving initiator_seal key\n",
376*4882a593Smuzhiyun __func__, err);
377*4882a593Smuzhiyun goto out_err;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun ctx->initiator_enc = context_v2_alloc_cipher(ctx,
380*4882a593Smuzhiyun ctx->gk5e->encrypt_name,
381*4882a593Smuzhiyun ctx->initiator_seal);
382*4882a593Smuzhiyun if (ctx->initiator_enc == NULL)
383*4882a593Smuzhiyun goto out_err;
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun /* acceptor seal encryption */
386*4882a593Smuzhiyun set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);
387*4882a593Smuzhiyun keyout.data = ctx->acceptor_seal;
388*4882a593Smuzhiyun err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
389*4882a593Smuzhiyun if (err) {
390*4882a593Smuzhiyun dprintk("%s: Error %d deriving acceptor_seal key\n",
391*4882a593Smuzhiyun __func__, err);
392*4882a593Smuzhiyun goto out_free_initiator_enc;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun ctx->acceptor_enc = context_v2_alloc_cipher(ctx,
395*4882a593Smuzhiyun ctx->gk5e->encrypt_name,
396*4882a593Smuzhiyun ctx->acceptor_seal);
397*4882a593Smuzhiyun if (ctx->acceptor_enc == NULL)
398*4882a593Smuzhiyun goto out_free_initiator_enc;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun /* initiator sign checksum */
401*4882a593Smuzhiyun set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
402*4882a593Smuzhiyun keyout.data = ctx->initiator_sign;
403*4882a593Smuzhiyun err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
404*4882a593Smuzhiyun if (err) {
405*4882a593Smuzhiyun dprintk("%s: Error %d deriving initiator_sign key\n",
406*4882a593Smuzhiyun __func__, err);
407*4882a593Smuzhiyun goto out_free_acceptor_enc;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun /* acceptor sign checksum */
411*4882a593Smuzhiyun set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM);
412*4882a593Smuzhiyun keyout.data = ctx->acceptor_sign;
413*4882a593Smuzhiyun err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
414*4882a593Smuzhiyun if (err) {
415*4882a593Smuzhiyun dprintk("%s: Error %d deriving acceptor_sign key\n",
416*4882a593Smuzhiyun __func__, err);
417*4882a593Smuzhiyun goto out_free_acceptor_enc;
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun /* initiator seal integrity */
421*4882a593Smuzhiyun set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
422*4882a593Smuzhiyun keyout.data = ctx->initiator_integ;
423*4882a593Smuzhiyun err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
424*4882a593Smuzhiyun if (err) {
425*4882a593Smuzhiyun dprintk("%s: Error %d deriving initiator_integ key\n",
426*4882a593Smuzhiyun __func__, err);
427*4882a593Smuzhiyun goto out_free_acceptor_enc;
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun /* acceptor seal integrity */
431*4882a593Smuzhiyun set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY);
432*4882a593Smuzhiyun keyout.data = ctx->acceptor_integ;
433*4882a593Smuzhiyun err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);
434*4882a593Smuzhiyun if (err) {
435*4882a593Smuzhiyun dprintk("%s: Error %d deriving acceptor_integ key\n",
436*4882a593Smuzhiyun __func__, err);
437*4882a593Smuzhiyun goto out_free_acceptor_enc;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun switch (ctx->enctype) {
441*4882a593Smuzhiyun case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
442*4882a593Smuzhiyun case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
443*4882a593Smuzhiyun ctx->initiator_enc_aux =
444*4882a593Smuzhiyun context_v2_alloc_cipher(ctx, "cbc(aes)",
445*4882a593Smuzhiyun ctx->initiator_seal);
446*4882a593Smuzhiyun if (ctx->initiator_enc_aux == NULL)
447*4882a593Smuzhiyun goto out_free_acceptor_enc;
448*4882a593Smuzhiyun ctx->acceptor_enc_aux =
449*4882a593Smuzhiyun context_v2_alloc_cipher(ctx, "cbc(aes)",
450*4882a593Smuzhiyun ctx->acceptor_seal);
451*4882a593Smuzhiyun if (ctx->acceptor_enc_aux == NULL) {
452*4882a593Smuzhiyun crypto_free_sync_skcipher(ctx->initiator_enc_aux);
453*4882a593Smuzhiyun goto out_free_acceptor_enc;
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun return 0;
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun out_free_acceptor_enc:
460*4882a593Smuzhiyun crypto_free_sync_skcipher(ctx->acceptor_enc);
461*4882a593Smuzhiyun out_free_initiator_enc:
462*4882a593Smuzhiyun crypto_free_sync_skcipher(ctx->initiator_enc);
463*4882a593Smuzhiyun out_err:
464*4882a593Smuzhiyun return -EINVAL;
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun static int
gss_import_v2_context(const void * p,const void * end,struct krb5_ctx * ctx,gfp_t gfp_mask)468*4882a593Smuzhiyun gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
469*4882a593Smuzhiyun gfp_t gfp_mask)
470*4882a593Smuzhiyun {
471*4882a593Smuzhiyun u64 seq_send64;
472*4882a593Smuzhiyun int keylen;
473*4882a593Smuzhiyun u32 time32;
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
476*4882a593Smuzhiyun if (IS_ERR(p))
477*4882a593Smuzhiyun goto out_err;
478*4882a593Smuzhiyun ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun p = simple_get_bytes(p, end, &time32, sizeof(time32));
481*4882a593Smuzhiyun if (IS_ERR(p))
482*4882a593Smuzhiyun goto out_err;
483*4882a593Smuzhiyun /* unsigned 32-bit time overflows in year 2106 */
484*4882a593Smuzhiyun ctx->endtime = (time64_t)time32;
485*4882a593Smuzhiyun p = simple_get_bytes(p, end, &seq_send64, sizeof(seq_send64));
486*4882a593Smuzhiyun if (IS_ERR(p))
487*4882a593Smuzhiyun goto out_err;
488*4882a593Smuzhiyun atomic64_set(&ctx->seq_send64, seq_send64);
489*4882a593Smuzhiyun /* set seq_send for use by "older" enctypes */
490*4882a593Smuzhiyun atomic_set(&ctx->seq_send, seq_send64);
491*4882a593Smuzhiyun if (seq_send64 != atomic_read(&ctx->seq_send)) {
492*4882a593Smuzhiyun dprintk("%s: seq_send64 %llx, seq_send %x overflow?\n", __func__,
493*4882a593Smuzhiyun seq_send64, atomic_read(&ctx->seq_send));
494*4882a593Smuzhiyun p = ERR_PTR(-EINVAL);
495*4882a593Smuzhiyun goto out_err;
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
498*4882a593Smuzhiyun if (IS_ERR(p))
499*4882a593Smuzhiyun goto out_err;
500*4882a593Smuzhiyun /* Map ENCTYPE_DES3_CBC_SHA1 to ENCTYPE_DES3_CBC_RAW */
501*4882a593Smuzhiyun if (ctx->enctype == ENCTYPE_DES3_CBC_SHA1)
502*4882a593Smuzhiyun ctx->enctype = ENCTYPE_DES3_CBC_RAW;
503*4882a593Smuzhiyun ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
504*4882a593Smuzhiyun if (ctx->gk5e == NULL) {
505*4882a593Smuzhiyun dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
506*4882a593Smuzhiyun ctx->enctype);
507*4882a593Smuzhiyun p = ERR_PTR(-EINVAL);
508*4882a593Smuzhiyun goto out_err;
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun keylen = ctx->gk5e->keylength;
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun p = simple_get_bytes(p, end, ctx->Ksess, keylen);
513*4882a593Smuzhiyun if (IS_ERR(p))
514*4882a593Smuzhiyun goto out_err;
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun if (p != end) {
517*4882a593Smuzhiyun p = ERR_PTR(-EINVAL);
518*4882a593Smuzhiyun goto out_err;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,
522*4882a593Smuzhiyun gss_kerberos_mech.gm_oid.len, gfp_mask);
523*4882a593Smuzhiyun if (unlikely(ctx->mech_used.data == NULL)) {
524*4882a593Smuzhiyun p = ERR_PTR(-ENOMEM);
525*4882a593Smuzhiyun goto out_err;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun switch (ctx->enctype) {
530*4882a593Smuzhiyun case ENCTYPE_DES3_CBC_RAW:
531*4882a593Smuzhiyun return context_derive_keys_des3(ctx, gfp_mask);
532*4882a593Smuzhiyun case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
533*4882a593Smuzhiyun case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
534*4882a593Smuzhiyun return context_derive_keys_new(ctx, gfp_mask);
535*4882a593Smuzhiyun default:
536*4882a593Smuzhiyun return -EINVAL;
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun out_err:
540*4882a593Smuzhiyun return PTR_ERR(p);
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun static int
gss_import_sec_context_kerberos(const void * p,size_t len,struct gss_ctx * ctx_id,time64_t * endtime,gfp_t gfp_mask)544*4882a593Smuzhiyun gss_import_sec_context_kerberos(const void *p, size_t len,
545*4882a593Smuzhiyun struct gss_ctx *ctx_id,
546*4882a593Smuzhiyun time64_t *endtime,
547*4882a593Smuzhiyun gfp_t gfp_mask)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun const void *end = (const void *)((const char *)p + len);
550*4882a593Smuzhiyun struct krb5_ctx *ctx;
551*4882a593Smuzhiyun int ret;
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun ctx = kzalloc(sizeof(*ctx), gfp_mask);
554*4882a593Smuzhiyun if (ctx == NULL)
555*4882a593Smuzhiyun return -ENOMEM;
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun if (len == 85)
558*4882a593Smuzhiyun ret = gss_import_v1_context(p, end, ctx);
559*4882a593Smuzhiyun else
560*4882a593Smuzhiyun ret = gss_import_v2_context(p, end, ctx, gfp_mask);
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun if (ret == 0) {
563*4882a593Smuzhiyun ctx_id->internal_ctx_id = ctx;
564*4882a593Smuzhiyun if (endtime)
565*4882a593Smuzhiyun *endtime = ctx->endtime;
566*4882a593Smuzhiyun } else
567*4882a593Smuzhiyun kfree(ctx);
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun dprintk("RPC: %s: returning %d\n", __func__, ret);
570*4882a593Smuzhiyun return ret;
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun static void
gss_delete_sec_context_kerberos(void * internal_ctx)574*4882a593Smuzhiyun gss_delete_sec_context_kerberos(void *internal_ctx) {
575*4882a593Smuzhiyun struct krb5_ctx *kctx = internal_ctx;
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun crypto_free_sync_skcipher(kctx->seq);
578*4882a593Smuzhiyun crypto_free_sync_skcipher(kctx->enc);
579*4882a593Smuzhiyun crypto_free_sync_skcipher(kctx->acceptor_enc);
580*4882a593Smuzhiyun crypto_free_sync_skcipher(kctx->initiator_enc);
581*4882a593Smuzhiyun crypto_free_sync_skcipher(kctx->acceptor_enc_aux);
582*4882a593Smuzhiyun crypto_free_sync_skcipher(kctx->initiator_enc_aux);
583*4882a593Smuzhiyun kfree(kctx->mech_used.data);
584*4882a593Smuzhiyun kfree(kctx);
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun static const struct gss_api_ops gss_kerberos_ops = {
588*4882a593Smuzhiyun .gss_import_sec_context = gss_import_sec_context_kerberos,
589*4882a593Smuzhiyun .gss_get_mic = gss_get_mic_kerberos,
590*4882a593Smuzhiyun .gss_verify_mic = gss_verify_mic_kerberos,
591*4882a593Smuzhiyun .gss_wrap = gss_wrap_kerberos,
592*4882a593Smuzhiyun .gss_unwrap = gss_unwrap_kerberos,
593*4882a593Smuzhiyun .gss_delete_sec_context = gss_delete_sec_context_kerberos,
594*4882a593Smuzhiyun };
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun static struct pf_desc gss_kerberos_pfs[] = {
597*4882a593Smuzhiyun [0] = {
598*4882a593Smuzhiyun .pseudoflavor = RPC_AUTH_GSS_KRB5,
599*4882a593Smuzhiyun .qop = GSS_C_QOP_DEFAULT,
600*4882a593Smuzhiyun .service = RPC_GSS_SVC_NONE,
601*4882a593Smuzhiyun .name = "krb5",
602*4882a593Smuzhiyun },
603*4882a593Smuzhiyun [1] = {
604*4882a593Smuzhiyun .pseudoflavor = RPC_AUTH_GSS_KRB5I,
605*4882a593Smuzhiyun .qop = GSS_C_QOP_DEFAULT,
606*4882a593Smuzhiyun .service = RPC_GSS_SVC_INTEGRITY,
607*4882a593Smuzhiyun .name = "krb5i",
608*4882a593Smuzhiyun .datatouch = true,
609*4882a593Smuzhiyun },
610*4882a593Smuzhiyun [2] = {
611*4882a593Smuzhiyun .pseudoflavor = RPC_AUTH_GSS_KRB5P,
612*4882a593Smuzhiyun .qop = GSS_C_QOP_DEFAULT,
613*4882a593Smuzhiyun .service = RPC_GSS_SVC_PRIVACY,
614*4882a593Smuzhiyun .name = "krb5p",
615*4882a593Smuzhiyun .datatouch = true,
616*4882a593Smuzhiyun },
617*4882a593Smuzhiyun };
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun MODULE_ALIAS("rpc-auth-gss-krb5");
620*4882a593Smuzhiyun MODULE_ALIAS("rpc-auth-gss-krb5i");
621*4882a593Smuzhiyun MODULE_ALIAS("rpc-auth-gss-krb5p");
622*4882a593Smuzhiyun MODULE_ALIAS("rpc-auth-gss-390003");
623*4882a593Smuzhiyun MODULE_ALIAS("rpc-auth-gss-390004");
624*4882a593Smuzhiyun MODULE_ALIAS("rpc-auth-gss-390005");
625*4882a593Smuzhiyun MODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun static struct gss_api_mech gss_kerberos_mech = {
628*4882a593Smuzhiyun .gm_name = "krb5",
629*4882a593Smuzhiyun .gm_owner = THIS_MODULE,
630*4882a593Smuzhiyun .gm_oid = { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },
631*4882a593Smuzhiyun .gm_ops = &gss_kerberos_ops,
632*4882a593Smuzhiyun .gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs),
633*4882a593Smuzhiyun .gm_pfs = gss_kerberos_pfs,
634*4882a593Smuzhiyun .gm_upcall_enctypes = KRB5_SUPPORTED_ENCTYPES,
635*4882a593Smuzhiyun };
636*4882a593Smuzhiyun
init_kerberos_module(void)637*4882a593Smuzhiyun static int __init init_kerberos_module(void)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun int status;
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun status = gss_mech_register(&gss_kerberos_mech);
642*4882a593Smuzhiyun if (status)
643*4882a593Smuzhiyun printk("Failed to register kerberos gss mechanism!\n");
644*4882a593Smuzhiyun return status;
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun
cleanup_kerberos_module(void)647*4882a593Smuzhiyun static void __exit cleanup_kerberos_module(void)
648*4882a593Smuzhiyun {
649*4882a593Smuzhiyun gss_mech_unregister(&gss_kerberos_mech);
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun MODULE_LICENSE("GPL");
653*4882a593Smuzhiyun module_init(init_kerberos_module);
654*4882a593Smuzhiyun module_exit(cleanup_kerberos_module);
655