cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gss_krb5_keys.c (8996B)


      1/*
      2 * COPYRIGHT (c) 2008
      3 * The Regents of the University of Michigan
      4 * ALL RIGHTS RESERVED
      5 *
      6 * Permission is granted to use, copy, create derivative works
      7 * and redistribute this software and such derivative works
      8 * for any purpose, so long as the name of The University of
      9 * Michigan is not used in any advertising or publicity
     10 * pertaining to the use of distribution of this software
     11 * without specific, written prior authorization.  If the
     12 * above copyright notice or any other identification of the
     13 * University of Michigan is included in any copy of any
     14 * portion of this software, then the disclaimer below must
     15 * also be included.
     16 *
     17 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
     18 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
     19 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
     20 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
     21 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
     22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
     23 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
     24 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
     25 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
     26 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
     27 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
     28 * SUCH DAMAGES.
     29 */
     30
     31/*
     32 * Copyright (C) 1998 by the FundsXpress, INC.
     33 *
     34 * All rights reserved.
     35 *
     36 * Export of this software from the United States of America may require
     37 * a specific license from the United States Government.  It is the
     38 * responsibility of any person or organization contemplating export to
     39 * obtain such a license before exporting.
     40 *
     41 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
     42 * distribute this software and its documentation for any purpose and
     43 * without fee is hereby granted, provided that the above copyright
     44 * notice appear in all copies and that both that copyright notice and
     45 * this permission notice appear in supporting documentation, and that
     46 * the name of FundsXpress. not be used in advertising or publicity pertaining
     47 * to distribution of the software without specific, written prior
     48 * permission.  FundsXpress makes no representations about the suitability of
     49 * this software for any purpose.  It is provided "as is" without express
     50 * or implied warranty.
     51 *
     52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     53 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     54 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     55 */
     56
     57#include <crypto/skcipher.h>
     58#include <linux/err.h>
     59#include <linux/types.h>
     60#include <linux/sunrpc/gss_krb5.h>
     61#include <linux/sunrpc/xdr.h>
     62#include <linux/lcm.h>
     63
     64#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
     65# define RPCDBG_FACILITY        RPCDBG_AUTH
     66#endif
     67
     68/*
     69 * This is the n-fold function as described in rfc3961, sec 5.1
     70 * Taken from MIT Kerberos and modified.
     71 */
     72
     73static void krb5_nfold(u32 inbits, const u8 *in,
     74		       u32 outbits, u8 *out)
     75{
     76	unsigned long ulcm;
     77	int byte, i, msbit;
     78
     79	/* the code below is more readable if I make these bytes
     80	   instead of bits */
     81
     82	inbits >>= 3;
     83	outbits >>= 3;
     84
     85	/* first compute lcm(n,k) */
     86	ulcm = lcm(inbits, outbits);
     87
     88	/* now do the real work */
     89
     90	memset(out, 0, outbits);
     91	byte = 0;
     92
     93	/* this will end up cycling through k lcm(k,n)/k times, which
     94	   is correct */
     95	for (i = ulcm-1; i >= 0; i--) {
     96		/* compute the msbit in k which gets added into this byte */
     97		msbit = (
     98			/* first, start with the msbit in the first,
     99			 * unrotated byte */
    100			 ((inbits << 3) - 1)
    101			 /* then, for each byte, shift to the right
    102			  * for each repetition */
    103			 + (((inbits << 3) + 13) * (i/inbits))
    104			 /* last, pick out the correct byte within
    105			  * that shifted repetition */
    106			 + ((inbits - (i % inbits)) << 3)
    107			 ) % (inbits << 3);
    108
    109		/* pull out the byte value itself */
    110		byte += (((in[((inbits - 1) - (msbit >> 3)) % inbits] << 8)|
    111				  (in[((inbits) - (msbit >> 3)) % inbits]))
    112				 >> ((msbit & 7) + 1)) & 0xff;
    113
    114		/* do the addition */
    115		byte += out[i % outbits];
    116		out[i % outbits] = byte & 0xff;
    117
    118		/* keep around the carry bit, if any */
    119		byte >>= 8;
    120
    121	}
    122
    123	/* if there's a carry bit left over, add it back in */
    124	if (byte) {
    125		for (i = outbits - 1; i >= 0; i--) {
    126			/* do the addition */
    127			byte += out[i];
    128			out[i] = byte & 0xff;
    129
    130			/* keep around the carry bit, if any */
    131			byte >>= 8;
    132		}
    133	}
    134}
    135
    136/*
    137 * This is the DK (derive_key) function as described in rfc3961, sec 5.1
    138 * Taken from MIT Kerberos and modified.
    139 */
    140
    141u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e,
    142		    const struct xdr_netobj *inkey,
    143		    struct xdr_netobj *outkey,
    144		    const struct xdr_netobj *in_constant,
    145		    gfp_t gfp_mask)
    146{
    147	size_t blocksize, keybytes, keylength, n;
    148	unsigned char *inblockdata, *outblockdata, *rawkey;
    149	struct xdr_netobj inblock, outblock;
    150	struct crypto_sync_skcipher *cipher;
    151	u32 ret = EINVAL;
    152
    153	blocksize = gk5e->blocksize;
    154	keybytes = gk5e->keybytes;
    155	keylength = gk5e->keylength;
    156
    157	if ((inkey->len != keylength) || (outkey->len != keylength))
    158		goto err_return;
    159
    160	cipher = crypto_alloc_sync_skcipher(gk5e->encrypt_name, 0, 0);
    161	if (IS_ERR(cipher))
    162		goto err_return;
    163	if (crypto_sync_skcipher_setkey(cipher, inkey->data, inkey->len))
    164		goto err_return;
    165
    166	/* allocate and set up buffers */
    167
    168	ret = ENOMEM;
    169	inblockdata = kmalloc(blocksize, gfp_mask);
    170	if (inblockdata == NULL)
    171		goto err_free_cipher;
    172
    173	outblockdata = kmalloc(blocksize, gfp_mask);
    174	if (outblockdata == NULL)
    175		goto err_free_in;
    176
    177	rawkey = kmalloc(keybytes, gfp_mask);
    178	if (rawkey == NULL)
    179		goto err_free_out;
    180
    181	inblock.data = (char *) inblockdata;
    182	inblock.len = blocksize;
    183
    184	outblock.data = (char *) outblockdata;
    185	outblock.len = blocksize;
    186
    187	/* initialize the input block */
    188
    189	if (in_constant->len == inblock.len) {
    190		memcpy(inblock.data, in_constant->data, inblock.len);
    191	} else {
    192		krb5_nfold(in_constant->len * 8, in_constant->data,
    193			   inblock.len * 8, inblock.data);
    194	}
    195
    196	/* loop encrypting the blocks until enough key bytes are generated */
    197
    198	n = 0;
    199	while (n < keybytes) {
    200		(*(gk5e->encrypt))(cipher, NULL, inblock.data,
    201				   outblock.data, inblock.len);
    202
    203		if ((keybytes - n) <= outblock.len) {
    204			memcpy(rawkey + n, outblock.data, (keybytes - n));
    205			break;
    206		}
    207
    208		memcpy(rawkey + n, outblock.data, outblock.len);
    209		memcpy(inblock.data, outblock.data, outblock.len);
    210		n += outblock.len;
    211	}
    212
    213	/* postprocess the key */
    214
    215	inblock.data = (char *) rawkey;
    216	inblock.len = keybytes;
    217
    218	BUG_ON(gk5e->mk_key == NULL);
    219	ret = (*(gk5e->mk_key))(gk5e, &inblock, outkey);
    220	if (ret) {
    221		dprintk("%s: got %d from mk_key function for '%s'\n",
    222			__func__, ret, gk5e->encrypt_name);
    223		goto err_free_raw;
    224	}
    225
    226	/* clean memory, free resources and exit */
    227
    228	ret = 0;
    229
    230err_free_raw:
    231	kfree_sensitive(rawkey);
    232err_free_out:
    233	kfree_sensitive(outblockdata);
    234err_free_in:
    235	kfree_sensitive(inblockdata);
    236err_free_cipher:
    237	crypto_free_sync_skcipher(cipher);
    238err_return:
    239	return ret;
    240}
    241
    242#define smask(step) ((1<<step)-1)
    243#define pstep(x, step) (((x)&smask(step))^(((x)>>step)&smask(step)))
    244#define parity_char(x) pstep(pstep(pstep((x), 4), 2), 1)
    245
    246static void mit_des_fixup_key_parity(u8 key[8])
    247{
    248	int i;
    249	for (i = 0; i < 8; i++) {
    250		key[i] &= 0xfe;
    251		key[i] |= 1^parity_char(key[i]);
    252	}
    253}
    254
    255/*
    256 * This is the des3 key derivation postprocess function
    257 */
    258u32 gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e,
    259			   struct xdr_netobj *randombits,
    260			   struct xdr_netobj *key)
    261{
    262	int i;
    263	u32 ret = EINVAL;
    264
    265	if (key->len != 24) {
    266		dprintk("%s: key->len is %d\n", __func__, key->len);
    267		goto err_out;
    268	}
    269	if (randombits->len != 21) {
    270		dprintk("%s: randombits->len is %d\n",
    271			__func__, randombits->len);
    272		goto err_out;
    273	}
    274
    275	/* take the seven bytes, move them around into the top 7 bits of the
    276	   8 key bytes, then compute the parity bits.  Do this three times. */
    277
    278	for (i = 0; i < 3; i++) {
    279		memcpy(key->data + i*8, randombits->data + i*7, 7);
    280		key->data[i*8+7] = (((key->data[i*8]&1)<<1) |
    281				    ((key->data[i*8+1]&1)<<2) |
    282				    ((key->data[i*8+2]&1)<<3) |
    283				    ((key->data[i*8+3]&1)<<4) |
    284				    ((key->data[i*8+4]&1)<<5) |
    285				    ((key->data[i*8+5]&1)<<6) |
    286				    ((key->data[i*8+6]&1)<<7));
    287
    288		mit_des_fixup_key_parity(key->data + i*8);
    289	}
    290	ret = 0;
    291err_out:
    292	return ret;
    293}
    294
    295/*
    296 * This is the aes key derivation postprocess function
    297 */
    298u32 gss_krb5_aes_make_key(const struct gss_krb5_enctype *gk5e,
    299			  struct xdr_netobj *randombits,
    300			  struct xdr_netobj *key)
    301{
    302	u32 ret = EINVAL;
    303
    304	if (key->len != 16 && key->len != 32) {
    305		dprintk("%s: key->len is %d\n", __func__, key->len);
    306		goto err_out;
    307	}
    308	if (randombits->len != 16 && randombits->len != 32) {
    309		dprintk("%s: randombits->len is %d\n",
    310			__func__, randombits->len);
    311		goto err_out;
    312	}
    313	if (randombits->len != key->len) {
    314		dprintk("%s: randombits->len is %d, key->len is %d\n",
    315			__func__, randombits->len, key->len);
    316		goto err_out;
    317	}
    318	memcpy(key->data, randombits->data, key->len);
    319	ret = 0;
    320err_out:
    321	return ret;
    322}