11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/net/sunrpc/gss_krb5_seal.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5seal.c 51da177e4SLinus Torvalds * 681d4a433SKevin Coffman * Copyright (c) 2000-2008 The Regents of the University of Michigan. 71da177e4SLinus Torvalds * All rights reserved. 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * Andy Adamson <andros@umich.edu> 101da177e4SLinus Torvalds * J. Bruce Fields <bfields@umich.edu> 111da177e4SLinus Torvalds */ 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds /* 141da177e4SLinus Torvalds * Copyright 1993 by OpenVision Technologies, Inc. 151da177e4SLinus Torvalds * 161da177e4SLinus Torvalds * Permission to use, copy, modify, distribute, and sell this software 171da177e4SLinus Torvalds * and its documentation for any purpose is hereby granted without fee, 181da177e4SLinus Torvalds * provided that the above copyright notice appears in all copies and 191da177e4SLinus Torvalds * that both that copyright notice and this permission notice appear in 201da177e4SLinus Torvalds * supporting documentation, and that the name of OpenVision not be used 211da177e4SLinus Torvalds * in advertising or publicity pertaining to distribution of the software 221da177e4SLinus Torvalds * without specific, written prior permission. OpenVision makes no 231da177e4SLinus Torvalds * representations about the suitability of this software for any 241da177e4SLinus Torvalds * purpose. It is provided "as is" without express or implied warranty. 251da177e4SLinus Torvalds * 261da177e4SLinus Torvalds * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 271da177e4SLinus Torvalds * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 281da177e4SLinus Torvalds * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR 291da177e4SLinus Torvalds * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 301da177e4SLinus Torvalds * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 311da177e4SLinus Torvalds * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 321da177e4SLinus Torvalds * PERFORMANCE OF THIS SOFTWARE. 331da177e4SLinus Torvalds */ 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds /* 361da177e4SLinus Torvalds * Copyright (C) 1998 by the FundsXpress, INC. 371da177e4SLinus Torvalds * 381da177e4SLinus Torvalds * All rights reserved. 391da177e4SLinus Torvalds * 401da177e4SLinus Torvalds * Export of this software from the United States of America may require 411da177e4SLinus Torvalds * a specific license from the United States Government. It is the 421da177e4SLinus Torvalds * responsibility of any person or organization contemplating export to 431da177e4SLinus Torvalds * obtain such a license before exporting. 441da177e4SLinus Torvalds * 451da177e4SLinus Torvalds * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 461da177e4SLinus Torvalds * distribute this software and its documentation for any purpose and 471da177e4SLinus Torvalds * without fee is hereby granted, provided that the above copyright 481da177e4SLinus Torvalds * notice appear in all copies and that both that copyright notice and 491da177e4SLinus Torvalds * this permission notice appear in supporting documentation, and that 501da177e4SLinus Torvalds * the name of FundsXpress. not be used in advertising or publicity pertaining 511da177e4SLinus Torvalds * to distribution of the software without specific, written prior 521da177e4SLinus Torvalds * permission. FundsXpress makes no representations about the suitability of 531da177e4SLinus Torvalds * this software for any purpose. It is provided "as is" without express 541da177e4SLinus Torvalds * or implied warranty. 551da177e4SLinus Torvalds * 561da177e4SLinus Torvalds * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 571da177e4SLinus Torvalds * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 581da177e4SLinus Torvalds * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 591da177e4SLinus Torvalds */ 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds #include <linux/types.h> 621da177e4SLinus Torvalds #include <linux/jiffies.h> 631da177e4SLinus Torvalds #include <linux/sunrpc/gss_krb5.h> 641da177e4SLinus Torvalds #include <linux/random.h> 651da177e4SLinus Torvalds #include <linux/crypto.h> 66e732f448STrond Myklebust #include <linux/atomic.h> 671da177e4SLinus Torvalds 682dbe0cacSChuck Lever #include "gss_krb5_internal.h" 692dbe0cacSChuck Lever 70f895b252SJeff Layton #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 711da177e4SLinus Torvalds # define RPCDBG_FACILITY RPCDBG_AUTH 721da177e4SLinus Torvalds #endif 731da177e4SLinus Torvalds 74*dfe9a123SChuck Lever #if defined(CONFIG_RPCSEC_GSS_KRB5_SIMPLIFIED) 75*dfe9a123SChuck Lever 766ac0fbbfSJeff Layton static void * 7781d4a433SKevin Coffman setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token) 7881d4a433SKevin Coffman { 796ac0fbbfSJeff Layton u16 *ptr; 806ac0fbbfSJeff Layton void *krb5_hdr; 8181d4a433SKevin Coffman int body_size = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength; 8281d4a433SKevin Coffman 8381d4a433SKevin Coffman token->len = g_token_size(&ctx->mech_used, body_size); 8481d4a433SKevin Coffman 856ac0fbbfSJeff Layton ptr = (u16 *)token->data; 8681d4a433SKevin Coffman g_make_token_header(&ctx->mech_used, body_size, (unsigned char **)&ptr); 8781d4a433SKevin Coffman 8881d4a433SKevin Coffman /* ptr now at start of header described in rfc 1964, section 1.2.1: */ 8981d4a433SKevin Coffman krb5_hdr = ptr; 9081d4a433SKevin Coffman *ptr++ = KG_TOK_MIC_MSG; 916ac0fbbfSJeff Layton /* 926ac0fbbfSJeff Layton * signalg is stored as if it were converted from LE to host endian, even 936ac0fbbfSJeff Layton * though it's an opaque pair of bytes according to the RFC. 946ac0fbbfSJeff Layton */ 956ac0fbbfSJeff Layton *ptr++ = (__force u16)cpu_to_le16(ctx->gk5e->signalg); 9681d4a433SKevin Coffman *ptr++ = SEAL_ALG_NONE; 976ac0fbbfSJeff Layton *ptr = 0xffff; 9881d4a433SKevin Coffman 996ac0fbbfSJeff Layton return krb5_hdr; 10081d4a433SKevin Coffman } 10181d4a433SKevin Coffman 102e01b2c79SChuck Lever u32 103e01b2c79SChuck Lever gss_krb5_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, 104a0857d03SJ. Bruce Fields struct xdr_netobj *token) 1051da177e4SLinus Torvalds { 10681d4a433SKevin Coffman char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; 10781d4a433SKevin Coffman struct xdr_netobj md5cksum = {.len = sizeof(cksumdata), 10881d4a433SKevin Coffman .data = cksumdata}; 10981d4a433SKevin Coffman void *ptr; 110294ec5b8SArnd Bergmann time64_t now; 111eaa82edfSJ. Bruce Fields u32 seq_send; 112e1f6c07bSKevin Coffman u8 *cksumkey; 1131da177e4SLinus Torvalds 11481d4a433SKevin Coffman dprintk("RPC: %s\n", __func__); 115ef338beeSKevin Coffman BUG_ON(ctx == NULL); 1161da177e4SLinus Torvalds 117294ec5b8SArnd Bergmann now = ktime_get_real_seconds(); 1181da177e4SLinus Torvalds 11981d4a433SKevin Coffman ptr = setup_token(ctx, token); 1201da177e4SLinus Torvalds 121e1f6c07bSKevin Coffman if (ctx->gk5e->keyed_cksum) 122e1f6c07bSKevin Coffman cksumkey = ctx->cksum; 123e1f6c07bSKevin Coffman else 124e1f6c07bSKevin Coffman cksumkey = NULL; 125e1f6c07bSKevin Coffman 1268b237076SKevin Coffman if (make_checksum(ctx, ptr, 8, text, 0, cksumkey, 1278b237076SKevin Coffman KG_USAGE_SIGN, &md5cksum)) 12839a21dd1SJ. Bruce Fields return GSS_S_FAILURE; 1291da177e4SLinus Torvalds 130e1f6c07bSKevin Coffman memcpy(ptr + GSS_KRB5_TOK_HDR_LEN, md5cksum.data, md5cksum.len); 1311da177e4SLinus Torvalds 132c3be6577SPaul Burton seq_send = atomic_fetch_inc(&ctx->seq_send); 1331da177e4SLinus Torvalds 1341dbd9029SKevin Coffman if (krb5_make_seq_num(ctx, ctx->seq, ctx->initiate ? 0 : 0xff, 1351dbd9029SKevin Coffman seq_send, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8)) 13639a21dd1SJ. Bruce Fields return GSS_S_FAILURE; 1371da177e4SLinus Torvalds 13894efa934SJ. Bruce Fields return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; 1391da177e4SLinus Torvalds } 1401ac3719aSKevin Coffman 141*dfe9a123SChuck Lever #endif 142*dfe9a123SChuck Lever 143*dfe9a123SChuck Lever static void * 144*dfe9a123SChuck Lever setup_token_v2(struct krb5_ctx *ctx, struct xdr_netobj *token) 145*dfe9a123SChuck Lever { 146*dfe9a123SChuck Lever u16 *ptr; 147*dfe9a123SChuck Lever void *krb5_hdr; 148*dfe9a123SChuck Lever u8 *p, flags = 0x00; 149*dfe9a123SChuck Lever 150*dfe9a123SChuck Lever if ((ctx->flags & KRB5_CTX_FLAG_INITIATOR) == 0) 151*dfe9a123SChuck Lever flags |= 0x01; 152*dfe9a123SChuck Lever if (ctx->flags & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY) 153*dfe9a123SChuck Lever flags |= 0x04; 154*dfe9a123SChuck Lever 155*dfe9a123SChuck Lever /* Per rfc 4121, sec 4.2.6.1, there is no header, 156*dfe9a123SChuck Lever * just start the token. 157*dfe9a123SChuck Lever */ 158*dfe9a123SChuck Lever krb5_hdr = (u16 *)token->data; 159*dfe9a123SChuck Lever ptr = krb5_hdr; 160*dfe9a123SChuck Lever 161*dfe9a123SChuck Lever *ptr++ = KG2_TOK_MIC; 162*dfe9a123SChuck Lever p = (u8 *)ptr; 163*dfe9a123SChuck Lever *p++ = flags; 164*dfe9a123SChuck Lever *p++ = 0xff; 165*dfe9a123SChuck Lever ptr = (u16 *)p; 166*dfe9a123SChuck Lever *ptr++ = 0xffff; 167*dfe9a123SChuck Lever *ptr = 0xffff; 168*dfe9a123SChuck Lever 169*dfe9a123SChuck Lever token->len = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength; 170*dfe9a123SChuck Lever return krb5_hdr; 171*dfe9a123SChuck Lever } 172*dfe9a123SChuck Lever 173e01b2c79SChuck Lever u32 174e01b2c79SChuck Lever gss_krb5_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, 175de9c17ebSKevin Coffman struct xdr_netobj *token) 176de9c17ebSKevin Coffman { 1772dbe0cacSChuck Lever struct crypto_ahash *tfm = ctx->initiate ? 1782dbe0cacSChuck Lever ctx->initiator_sign : ctx->acceptor_sign; 1792dbe0cacSChuck Lever struct xdr_netobj cksumobj = { 1802dbe0cacSChuck Lever .len = ctx->gk5e->cksumlength, 1812dbe0cacSChuck Lever }; 1822dbe0cacSChuck Lever __be64 seq_send_be64; 183de9c17ebSKevin Coffman void *krb5_hdr; 184294ec5b8SArnd Bergmann time64_t now; 185de9c17ebSKevin Coffman 186de9c17ebSKevin Coffman dprintk("RPC: %s\n", __func__); 187de9c17ebSKevin Coffman 188de9c17ebSKevin Coffman krb5_hdr = setup_token_v2(ctx, token); 189de9c17ebSKevin Coffman 190de9c17ebSKevin Coffman /* Set up the sequence number. Now 64-bits in clear 191de9c17ebSKevin Coffman * text and w/o direction indicator */ 192c3be6577SPaul Burton seq_send_be64 = cpu_to_be64(atomic64_fetch_inc(&ctx->seq_send64)); 19390a9b147SJames Ettle memcpy(krb5_hdr + 8, (char *) &seq_send_be64, 8); 194de9c17ebSKevin Coffman 1952dbe0cacSChuck Lever cksumobj.data = krb5_hdr + GSS_KRB5_TOK_HDR_LEN; 1962dbe0cacSChuck Lever if (gss_krb5_checksum(tfm, krb5_hdr, GSS_KRB5_TOK_HDR_LEN, 1972dbe0cacSChuck Lever text, 0, &cksumobj)) 198de9c17ebSKevin Coffman return GSS_S_FAILURE; 199de9c17ebSKevin Coffman 200294ec5b8SArnd Bergmann now = ktime_get_real_seconds(); 201de9c17ebSKevin Coffman return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; 202de9c17ebSKevin Coffman } 203