3 * The Regents of the University of Michigan
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
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
32 * Copyright (C) 1998 by the FundsXpress, INC.
34 * All rights reserved.
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.
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.
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.
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>
64 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
65 # define RPCDBG_FACILITY RPCDBG_AUTH
69 * This is the n-fold function as described in rfc3961, sec 5.1
70 * Taken from MIT Kerberos and modified.
73 static void krb5_nfold(u32 inbits
, const u8
*in
,
79 /* the code below is more readable if I make these bytes
85 /* first compute lcm(n,k) */
86 ulcm
= lcm(inbits
, outbits
);
88 /* now do the real work */
90 memset(out
, 0, outbits
);
93 /* this will end up cycling through k lcm(k,n)/k times, which
95 for (i
= ulcm
-1; i
>= 0; i
--) {
96 /* compute the msbit in k which gets added into this byte */
98 /* first, start with the msbit in the first,
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)
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;
114 /* do the addition */
115 byte
+= out
[i
% outbits
];
116 out
[i
% outbits
] = byte
& 0xff;
118 /* keep around the carry bit, if any */
123 /* if there's a carry bit left over, add it back in */
125 for (i
= outbits
- 1; i
>= 0; i
--) {
126 /* do the addition */
128 out
[i
] = byte
& 0xff;
130 /* keep around the carry bit, if any */
137 * This is the DK (derive_key) function as described in rfc3961, sec 5.1
138 * Taken from MIT Kerberos and modified.
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
,
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
;
153 blocksize
= gk5e
->blocksize
;
154 keybytes
= gk5e
->keybytes
;
155 keylength
= gk5e
->keylength
;
157 if ((inkey
->len
!= keylength
) || (outkey
->len
!= keylength
))
160 cipher
= crypto_alloc_sync_skcipher(gk5e
->encrypt_name
, 0, 0);
163 if (crypto_sync_skcipher_setkey(cipher
, inkey
->data
, inkey
->len
))
166 /* allocate and set up buffers */
169 inblockdata
= kmalloc(blocksize
, gfp_mask
);
170 if (inblockdata
== NULL
)
171 goto err_free_cipher
;
173 outblockdata
= kmalloc(blocksize
, gfp_mask
);
174 if (outblockdata
== NULL
)
177 rawkey
= kmalloc(keybytes
, gfp_mask
);
181 inblock
.data
= (char *) inblockdata
;
182 inblock
.len
= blocksize
;
184 outblock
.data
= (char *) outblockdata
;
185 outblock
.len
= blocksize
;
187 /* initialize the input block */
189 if (in_constant
->len
== inblock
.len
) {
190 memcpy(inblock
.data
, in_constant
->data
, inblock
.len
);
192 krb5_nfold(in_constant
->len
* 8, in_constant
->data
,
193 inblock
.len
* 8, inblock
.data
);
196 /* loop encrypting the blocks until enough key bytes are generated */
199 while (n
< keybytes
) {
200 (*(gk5e
->encrypt
))(cipher
, NULL
, inblock
.data
,
201 outblock
.data
, inblock
.len
);
203 if ((keybytes
- n
) <= outblock
.len
) {
204 memcpy(rawkey
+ n
, outblock
.data
, (keybytes
- n
));
208 memcpy(rawkey
+ n
, outblock
.data
, outblock
.len
);
209 memcpy(inblock
.data
, outblock
.data
, outblock
.len
);
213 /* postprocess the key */
215 inblock
.data
= (char *) rawkey
;
216 inblock
.len
= keybytes
;
218 BUG_ON(gk5e
->mk_key
== NULL
);
219 ret
= (*(gk5e
->mk_key
))(gk5e
, &inblock
, outkey
);
221 dprintk("%s: got %d from mk_key function for '%s'\n",
222 __func__
, ret
, gk5e
->encrypt_name
);
226 /* clean memory, free resources and exit */
231 kfree_sensitive(rawkey
);
233 kfree_sensitive(outblockdata
);
235 kfree_sensitive(inblockdata
);
237 crypto_free_sync_skcipher(cipher
);
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)
246 static void mit_des_fixup_key_parity(u8 key
[8])
249 for (i
= 0; i
< 8; i
++) {
251 key
[i
] |= 1^parity_char(key
[i
]);
256 * This is the des3 key derivation postprocess function
258 u32
gss_krb5_des3_make_key(const struct gss_krb5_enctype
*gk5e
,
259 struct xdr_netobj
*randombits
,
260 struct xdr_netobj
*key
)
265 if (key
->len
!= 24) {
266 dprintk("%s: key->len is %d\n", __func__
, key
->len
);
269 if (randombits
->len
!= 21) {
270 dprintk("%s: randombits->len is %d\n",
271 __func__
, randombits
->len
);
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. */
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));
288 mit_des_fixup_key_parity(key
->data
+ i
*8);
296 * This is the aes key derivation postprocess function
298 u32
gss_krb5_aes_make_key(const struct gss_krb5_enctype
*gk5e
,
299 struct xdr_netobj
*randombits
,
300 struct xdr_netobj
*key
)
304 if (key
->len
!= 16 && key
->len
!= 32) {
305 dprintk("%s: key->len is %d\n", __func__
, key
->len
);
308 if (randombits
->len
!= 16 && randombits
->len
!= 32) {
309 dprintk("%s: randombits->len is %d\n",
310 __func__
, randombits
->len
);
313 if (randombits
->len
!= key
->len
) {
314 dprintk("%s: randombits->len is %d, key->len is %d\n",
315 __func__
, randombits
->len
, key
->len
);
318 memcpy(key
->data
, randombits
->data
, key
->len
);