gss_krb5_keys.c 8.9 KB

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