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 73 static 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 141 u32 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 230 err_free_raw: 231 kfree_sensitive(rawkey); 232 err_free_out: 233 kfree_sensitive(outblockdata); 234 err_free_in: 235 kfree_sensitive(inblockdata); 236 err_free_cipher: 237 crypto_free_sync_skcipher(cipher); 238 err_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 246 static 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 */ 258 u32 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; 291 err_out: 292 return ret; 293 } 294 295 /* 296 * This is the aes key derivation postprocess function 297 */ 298 u32 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; 320 err_out: 321 return ret; 322 } 323