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 <linux/err.h> 58 #include <linux/types.h> 59 #include <linux/crypto.h> 60 #include <linux/sunrpc/gss_krb5.h> 61 #include <linux/sunrpc/xdr.h> 62 #include <linux/lcm.h> 63 64 #ifdef RPC_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_blkcipher *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_blkcipher(gk5e->encrypt_name, 0, 161 CRYPTO_ALG_ASYNC); 162 if (IS_ERR(cipher)) 163 goto err_return; 164 if (crypto_blkcipher_setkey(cipher, inkey->data, inkey->len)) 165 goto err_return; 166 167 /* allocate and set up buffers */ 168 169 ret = ENOMEM; 170 inblockdata = kmalloc(blocksize, gfp_mask); 171 if (inblockdata == NULL) 172 goto err_free_cipher; 173 174 outblockdata = kmalloc(blocksize, gfp_mask); 175 if (outblockdata == NULL) 176 goto err_free_in; 177 178 rawkey = kmalloc(keybytes, gfp_mask); 179 if (rawkey == NULL) 180 goto err_free_out; 181 182 inblock.data = (char *) inblockdata; 183 inblock.len = blocksize; 184 185 outblock.data = (char *) outblockdata; 186 outblock.len = blocksize; 187 188 /* initialize the input block */ 189 190 if (in_constant->len == inblock.len) { 191 memcpy(inblock.data, in_constant->data, inblock.len); 192 } else { 193 krb5_nfold(in_constant->len * 8, in_constant->data, 194 inblock.len * 8, inblock.data); 195 } 196 197 /* loop encrypting the blocks until enough key bytes are generated */ 198 199 n = 0; 200 while (n < keybytes) { 201 (*(gk5e->encrypt))(cipher, NULL, inblock.data, 202 outblock.data, inblock.len); 203 204 if ((keybytes - n) <= outblock.len) { 205 memcpy(rawkey + n, outblock.data, (keybytes - n)); 206 break; 207 } 208 209 memcpy(rawkey + n, outblock.data, outblock.len); 210 memcpy(inblock.data, outblock.data, outblock.len); 211 n += outblock.len; 212 } 213 214 /* postprocess the key */ 215 216 inblock.data = (char *) rawkey; 217 inblock.len = keybytes; 218 219 BUG_ON(gk5e->mk_key == NULL); 220 ret = (*(gk5e->mk_key))(gk5e, &inblock, outkey); 221 if (ret) { 222 dprintk("%s: got %d from mk_key function for '%s'\n", 223 __func__, ret, gk5e->encrypt_name); 224 goto err_free_raw; 225 } 226 227 /* clean memory, free resources and exit */ 228 229 ret = 0; 230 231 err_free_raw: 232 memset(rawkey, 0, keybytes); 233 kfree(rawkey); 234 err_free_out: 235 memset(outblockdata, 0, blocksize); 236 kfree(outblockdata); 237 err_free_in: 238 memset(inblockdata, 0, blocksize); 239 kfree(inblockdata); 240 err_free_cipher: 241 crypto_free_blkcipher(cipher); 242 err_return: 243 return ret; 244 } 245 246 #define smask(step) ((1<<step)-1) 247 #define pstep(x, step) (((x)&smask(step))^(((x)>>step)&smask(step))) 248 #define parity_char(x) pstep(pstep(pstep((x), 4), 2), 1) 249 250 static void mit_des_fixup_key_parity(u8 key[8]) 251 { 252 int i; 253 for (i = 0; i < 8; i++) { 254 key[i] &= 0xfe; 255 key[i] |= 1^parity_char(key[i]); 256 } 257 } 258 259 /* 260 * This is the des3 key derivation postprocess function 261 */ 262 u32 gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e, 263 struct xdr_netobj *randombits, 264 struct xdr_netobj *key) 265 { 266 int i; 267 u32 ret = EINVAL; 268 269 if (key->len != 24) { 270 dprintk("%s: key->len is %d\n", __func__, key->len); 271 goto err_out; 272 } 273 if (randombits->len != 21) { 274 dprintk("%s: randombits->len is %d\n", 275 __func__, randombits->len); 276 goto err_out; 277 } 278 279 /* take the seven bytes, move them around into the top 7 bits of the 280 8 key bytes, then compute the parity bits. Do this three times. */ 281 282 for (i = 0; i < 3; i++) { 283 memcpy(key->data + i*8, randombits->data + i*7, 7); 284 key->data[i*8+7] = (((key->data[i*8]&1)<<1) | 285 ((key->data[i*8+1]&1)<<2) | 286 ((key->data[i*8+2]&1)<<3) | 287 ((key->data[i*8+3]&1)<<4) | 288 ((key->data[i*8+4]&1)<<5) | 289 ((key->data[i*8+5]&1)<<6) | 290 ((key->data[i*8+6]&1)<<7)); 291 292 mit_des_fixup_key_parity(key->data + i*8); 293 } 294 ret = 0; 295 err_out: 296 return ret; 297 } 298 299 /* 300 * This is the aes key derivation postprocess function 301 */ 302 u32 gss_krb5_aes_make_key(const struct gss_krb5_enctype *gk5e, 303 struct xdr_netobj *randombits, 304 struct xdr_netobj *key) 305 { 306 u32 ret = EINVAL; 307 308 if (key->len != 16 && key->len != 32) { 309 dprintk("%s: key->len is %d\n", __func__, key->len); 310 goto err_out; 311 } 312 if (randombits->len != 16 && randombits->len != 32) { 313 dprintk("%s: randombits->len is %d\n", 314 __func__, randombits->len); 315 goto err_out; 316 } 317 if (randombits->len != key->len) { 318 dprintk("%s: randombits->len is %d, key->len is %d\n", 319 __func__, randombits->len, key->len); 320 goto err_out; 321 } 322 memcpy(key->data, randombits->data, key->len); 323 ret = 0; 324 err_out: 325 return ret; 326 } 327 328