xref: /linux/net/sunrpc/auth_gss/gss_krb5_mech.c (revision b2128290c29902315e632ea59e0504d6bc9e9b42)
1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  *  linux/net/sunrpc/gss_krb5_mech.c
4  *
5  *  Copyright (c) 2001-2008 The Regents of the University of Michigan.
6  *  All rights reserved.
7  *
8  *  Andy Adamson <andros@umich.edu>
9  *  J. Bruce Fields <bfields@umich.edu>
10  */
11 
12 #include <linux/err.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/types.h>
16 #include <linux/slab.h>
17 #include <linux/sunrpc/auth.h>
18 #include <linux/sunrpc/gss_krb5.h>
19 #include <linux/sunrpc/xdr.h>
20 
21 #include "auth_gss_internal.h"
22 #include "gss_krb5_internal.h"
23 
24 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
25 # define RPCDBG_FACILITY	RPCDBG_AUTH
26 #endif
27 
28 static struct gss_api_mech gss_kerberos_mech;
29 
30 /*
31  * Candidate enctypes in order of most preferred to least.
32  * Each is probed against crypto/krb5 at module init; only
33  * enctypes that crypto/krb5 supports are advertised.
34  */
35 static const u32 gss_krb5_enctypes[] = {
36 	KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192,
37 	KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128,
38 	KRB5_ENCTYPE_CAMELLIA256_CTS_CMAC,
39 	KRB5_ENCTYPE_CAMELLIA128_CTS_CMAC,
40 	KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96,
41 	KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96,
42 };
43 
44 static char gss_krb5_enctype_priority_list[64];
45 
46 static void gss_krb5_prepare_enctype_priority_list(void)
47 {
48 	size_t total, i;
49 	char buf[16];
50 	char *sep;
51 	int n;
52 
53 	sep = "";
54 	gss_krb5_enctype_priority_list[0] = '\0';
55 	for (total = 0, i = 0; i < ARRAY_SIZE(gss_krb5_enctypes); i++) {
56 		if (!crypto_krb5_find_enctype(gss_krb5_enctypes[i]))
57 			continue;
58 		n = sprintf(buf, "%s%u", sep, gss_krb5_enctypes[i]);
59 		if (n < 0)
60 			break;
61 		if (total + n >= sizeof(gss_krb5_enctype_priority_list))
62 			break;
63 		strcat(gss_krb5_enctype_priority_list, buf);
64 		sep = ",";
65 		total += n;
66 	}
67 }
68 
69 static int
70 gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask)
71 {
72 	struct krb5_buffer TK = {
73 		.len	= ctx->krb5e->key_len,
74 		.data	= ctx->Ksess,
75 	};
76 	int ret;
77 
78 	ctx->initiator_enc_aead =
79 		crypto_krb5_prepare_encryption(ctx->krb5e, &TK,
80 					       KG_USAGE_INITIATOR_SEAL,
81 					       gfp_mask);
82 	if (IS_ERR(ctx->initiator_enc_aead)) {
83 		ret = PTR_ERR(ctx->initiator_enc_aead);
84 		goto out_free;
85 	}
86 	ctx->acceptor_enc_aead =
87 		crypto_krb5_prepare_encryption(ctx->krb5e, &TK,
88 					       KG_USAGE_ACCEPTOR_SEAL,
89 					       gfp_mask);
90 	if (IS_ERR(ctx->acceptor_enc_aead)) {
91 		ret = PTR_ERR(ctx->acceptor_enc_aead);
92 		goto out_free;
93 	}
94 	ctx->initiator_sign_shash =
95 		crypto_krb5_prepare_checksum(ctx->krb5e, &TK,
96 					     KG_USAGE_INITIATOR_SIGN,
97 					     gfp_mask);
98 	if (IS_ERR(ctx->initiator_sign_shash)) {
99 		ret = PTR_ERR(ctx->initiator_sign_shash);
100 		goto out_free;
101 	}
102 	ctx->acceptor_sign_shash =
103 		crypto_krb5_prepare_checksum(ctx->krb5e, &TK,
104 					     KG_USAGE_ACCEPTOR_SIGN,
105 					     gfp_mask);
106 	if (IS_ERR(ctx->acceptor_sign_shash)) {
107 		ret = PTR_ERR(ctx->acceptor_sign_shash);
108 		goto out_free;
109 	}
110 
111 	return 0;
112 
113 out_free:
114 	crypto_free_shash(ctx->acceptor_sign_shash);
115 	crypto_free_shash(ctx->initiator_sign_shash);
116 	crypto_free_aead(ctx->acceptor_enc_aead);
117 	crypto_free_aead(ctx->initiator_enc_aead);
118 	return ret;
119 }
120 
121 static int
122 gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
123 		gfp_t gfp_mask)
124 {
125 	u64 seq_send64;
126 	int keylen;
127 	u32 time32;
128 	int ret;
129 
130 	p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
131 	if (IS_ERR(p))
132 		goto out_err;
133 	ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;
134 
135 	p = simple_get_bytes(p, end, &time32, sizeof(time32));
136 	if (IS_ERR(p))
137 		goto out_err;
138 	/* unsigned 32-bit time overflows in year 2106 */
139 	ctx->endtime = (time64_t)time32;
140 	p = simple_get_bytes(p, end, &seq_send64, sizeof(seq_send64));
141 	if (IS_ERR(p))
142 		goto out_err;
143 	atomic64_set(&ctx->seq_send64, seq_send64);
144 	p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
145 	if (IS_ERR(p))
146 		goto out_err;
147 	ctx->krb5e = crypto_krb5_find_enctype(ctx->enctype);
148 	if (!ctx->krb5e) {
149 		dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
150 			ctx->enctype);
151 		p = ERR_PTR(-EINVAL);
152 		goto out_err;
153 	}
154 	keylen = ctx->krb5e->key_len;
155 
156 	p = simple_get_bytes(p, end, ctx->Ksess, keylen);
157 	if (IS_ERR(p))
158 		goto out_err;
159 
160 	if (p != end) {
161 		p = ERR_PTR(-EINVAL);
162 		goto out_err;
163 	}
164 
165 	ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,
166 				      gss_kerberos_mech.gm_oid.len, gfp_mask);
167 	if (unlikely(ctx->mech_used.data == NULL)) {
168 		p = ERR_PTR(-ENOMEM);
169 		goto out_err;
170 	}
171 	ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;
172 
173 	ret = gss_krb5_import_ctx_v2(ctx, gfp_mask);
174 	if (ret) {
175 		p = ERR_PTR(ret);
176 		goto out_free;
177 	}
178 
179 	return 0;
180 
181 out_free:
182 	kfree(ctx->mech_used.data);
183 out_err:
184 	return PTR_ERR(p);
185 }
186 
187 static int
188 gss_krb5_import_sec_context(const void *p, size_t len, struct gss_ctx *ctx_id,
189 			    time64_t *endtime, gfp_t gfp_mask)
190 {
191 	const void *end = (const void *)((const char *)p + len);
192 	struct  krb5_ctx *ctx;
193 	int ret;
194 
195 	ctx = kzalloc_obj(*ctx, gfp_mask);
196 	if (ctx == NULL)
197 		return -ENOMEM;
198 
199 	ret = gss_import_v2_context(p, end, ctx, gfp_mask);
200 	memzero_explicit(&ctx->Ksess, sizeof(ctx->Ksess));
201 	if (ret) {
202 		kfree(ctx);
203 		return ret;
204 	}
205 
206 	ctx_id->internal_ctx_id = ctx;
207 	if (endtime)
208 		*endtime = ctx->endtime;
209 	return 0;
210 }
211 
212 static void
213 gss_krb5_delete_sec_context(void *internal_ctx)
214 {
215 	struct krb5_ctx *kctx = internal_ctx;
216 
217 	crypto_free_shash(kctx->acceptor_sign_shash);
218 	crypto_free_shash(kctx->initiator_sign_shash);
219 	crypto_free_aead(kctx->acceptor_enc_aead);
220 	crypto_free_aead(kctx->initiator_enc_aead);
221 	kfree(kctx->mech_used.data);
222 	kfree(kctx);
223 }
224 
225 /**
226  * gss_krb5_errno_to_status - Map a negative errno to a GSS major status
227  * @err: negative errno value, or zero
228  *
229  * Returns:
230  *   %GSS_S_COMPLETE if @err is zero
231  *   %GSS_S_BAD_SIG if @err is -EBADMSG (integrity check failure)
232  *   %GSS_S_DEFECTIVE_TOKEN if @err is -EPROTO (malformed token)
233  *   %GSS_S_FAILURE for all other negative values
234  */
235 u32 gss_krb5_errno_to_status(int err)
236 {
237 	switch (err) {
238 	case 0:
239 		return GSS_S_COMPLETE;
240 	case -EBADMSG:
241 		return GSS_S_BAD_SIG;
242 	case -EPROTO:
243 		return GSS_S_DEFECTIVE_TOKEN;
244 	default:
245 		return GSS_S_FAILURE;
246 	}
247 }
248 
249 /**
250  * gss_krb5_get_mic - get_mic for the Kerberos GSS mechanism
251  * @gctx: GSS context
252  * @text: plaintext to checksum
253  * @token: buffer into which to write the computed checksum
254  *
255  * Return values:
256  *    %GSS_S_COMPLETE - success, and @token is filled in
257  *    %GSS_S_FAILURE - checksum could not be generated
258  *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
259  */
260 static u32 gss_krb5_get_mic(struct gss_ctx *gctx, struct xdr_buf *text,
261 			    struct xdr_netobj *token)
262 {
263 	struct krb5_ctx *kctx = gctx->internal_ctx_id;
264 
265 	return gss_krb5_get_mic_v2(kctx, text, token);
266 }
267 
268 /**
269  * gss_krb5_verify_mic - verify_mic for the Kerberos GSS mechanism
270  * @gctx: GSS context
271  * @message_buffer: plaintext to check
272  * @read_token: received checksum to check
273  *
274  * Return values:
275  *    %GSS_S_COMPLETE - computed and received checksums match
276  *    %GSS_S_DEFECTIVE_TOKEN - received checksum is not valid
277  *    %GSS_S_BAD_SIG - computed and received checksums do not match
278  *    %GSS_S_FAILURE - received checksum could not be checked
279  *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
280  */
281 static u32 gss_krb5_verify_mic(struct gss_ctx *gctx,
282 			       struct xdr_buf *message_buffer,
283 			       struct xdr_netobj *read_token)
284 {
285 	struct krb5_ctx *kctx = gctx->internal_ctx_id;
286 
287 	return gss_krb5_verify_mic_v2(kctx, message_buffer, read_token);
288 }
289 
290 /**
291  * gss_krb5_wrap - gss_wrap for the Kerberos GSS mechanism
292  * @gctx: initialized GSS context
293  * @offset: byte offset in @buf to start writing the cipher text
294  * @buf: OUT: send buffer
295  * @pages: plaintext to wrap
296  *
297  * Return values:
298  *    %GSS_S_COMPLETE - success, @buf has been updated
299  *    %GSS_S_FAILURE - @buf could not be wrapped
300  *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
301  */
302 static u32 gss_krb5_wrap(struct gss_ctx *gctx, int offset,
303 			 struct xdr_buf *buf, struct page **pages)
304 {
305 	struct krb5_ctx	*kctx = gctx->internal_ctx_id;
306 
307 	return gss_krb5_wrap_v2(kctx, offset, buf, pages);
308 }
309 
310 /**
311  * gss_krb5_unwrap - gss_unwrap for the Kerberos GSS mechanism
312  * @gctx: initialized GSS context
313  * @offset: starting byte offset into @buf
314  * @len: size of ciphertext to unwrap
315  * @buf: ciphertext to unwrap
316  *
317  * Return values:
318  *    %GSS_S_COMPLETE - success, @buf has been updated
319  *    %GSS_S_DEFECTIVE_TOKEN - received blob is not valid
320  *    %GSS_S_BAD_SIG - computed and received checksums do not match
321  *    %GSS_S_FAILURE - @buf could not be unwrapped
322  *    %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid
323  */
324 static u32 gss_krb5_unwrap(struct gss_ctx *gctx, int offset,
325 			   int len, struct xdr_buf *buf)
326 {
327 	struct krb5_ctx	*kctx = gctx->internal_ctx_id;
328 
329 	return gss_krb5_unwrap_v2(kctx, offset, len, buf,
330 				  &gctx->slack, &gctx->align);
331 }
332 
333 static const struct gss_api_ops gss_kerberos_ops = {
334 	.gss_import_sec_context	= gss_krb5_import_sec_context,
335 	.gss_get_mic		= gss_krb5_get_mic,
336 	.gss_verify_mic		= gss_krb5_verify_mic,
337 	.gss_wrap		= gss_krb5_wrap,
338 	.gss_unwrap		= gss_krb5_unwrap,
339 	.gss_delete_sec_context	= gss_krb5_delete_sec_context,
340 };
341 
342 static struct pf_desc gss_kerberos_pfs[] = {
343 	[0] = {
344 		.pseudoflavor = RPC_AUTH_GSS_KRB5,
345 		.qop = GSS_C_QOP_DEFAULT,
346 		.service = RPC_GSS_SVC_NONE,
347 		.name = "krb5",
348 	},
349 	[1] = {
350 		.pseudoflavor = RPC_AUTH_GSS_KRB5I,
351 		.qop = GSS_C_QOP_DEFAULT,
352 		.service = RPC_GSS_SVC_INTEGRITY,
353 		.name = "krb5i",
354 		.datatouch = true,
355 	},
356 	[2] = {
357 		.pseudoflavor = RPC_AUTH_GSS_KRB5P,
358 		.qop = GSS_C_QOP_DEFAULT,
359 		.service = RPC_GSS_SVC_PRIVACY,
360 		.name = "krb5p",
361 		.datatouch = true,
362 	},
363 };
364 
365 MODULE_ALIAS("rpc-auth-gss-krb5");
366 MODULE_ALIAS("rpc-auth-gss-krb5i");
367 MODULE_ALIAS("rpc-auth-gss-krb5p");
368 MODULE_ALIAS("rpc-auth-gss-390003");
369 MODULE_ALIAS("rpc-auth-gss-390004");
370 MODULE_ALIAS("rpc-auth-gss-390005");
371 MODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");
372 
373 static struct gss_api_mech gss_kerberos_mech = {
374 	.gm_name	= "krb5",
375 	.gm_owner	= THIS_MODULE,
376 	.gm_oid		= { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },
377 	.gm_ops		= &gss_kerberos_ops,
378 	.gm_pf_num	= ARRAY_SIZE(gss_kerberos_pfs),
379 	.gm_pfs		= gss_kerberos_pfs,
380 	.gm_upcall_enctypes = gss_krb5_enctype_priority_list,
381 };
382 
383 static int __init init_kerberos_module(void)
384 {
385 	int status;
386 
387 	gss_krb5_prepare_enctype_priority_list();
388 	status = gss_mech_register(&gss_kerberos_mech);
389 	if (status)
390 		printk("Failed to register kerberos gss mechanism!\n");
391 	return status;
392 }
393 
394 static void __exit cleanup_kerberos_module(void)
395 {
396 	gss_mech_unregister(&gss_kerberos_mech);
397 }
398 
399 MODULE_DESCRIPTION("Sun RPC Kerberos 5 module");
400 MODULE_LICENSE("GPL");
401 module_init(init_kerberos_module);
402 module_exit(cleanup_kerberos_module);
403