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