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_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_skcipher(gk5e
->encrypt_name
, 0,
164 if (crypto_skcipher_setkey(cipher
, inkey
->data
, inkey
->len
))
167 /* allocate and set up buffers */
170 inblockdata
= kmalloc(blocksize
, gfp_mask
);
171 if (inblockdata
== NULL
)
172 goto err_free_cipher
;
174 outblockdata
= kmalloc(blocksize
, gfp_mask
);
175 if (outblockdata
== NULL
)
178 rawkey
= kmalloc(keybytes
, gfp_mask
);
182 inblock
.data
= (char *) inblockdata
;
183 inblock
.len
= blocksize
;
185 outblock
.data
= (char *) outblockdata
;
186 outblock
.len
= blocksize
;
188 /* initialize the input block */
190 if (in_constant
->len
== inblock
.len
) {
191 memcpy(inblock
.data
, in_constant
->data
, inblock
.len
);
193 krb5_nfold(in_constant
->len
* 8, in_constant
->data
,
194 inblock
.len
* 8, inblock
.data
);
197 /* loop encrypting the blocks until enough key bytes are generated */
200 while (n
< keybytes
) {
201 (*(gk5e
->encrypt
))(cipher
, NULL
, inblock
.data
,
202 outblock
.data
, inblock
.len
);
204 if ((keybytes
- n
) <= outblock
.len
) {
205 memcpy(rawkey
+ n
, outblock
.data
, (keybytes
- n
));
209 memcpy(rawkey
+ n
, outblock
.data
, outblock
.len
);
210 memcpy(inblock
.data
, outblock
.data
, outblock
.len
);
214 /* postprocess the key */
216 inblock
.data
= (char *) rawkey
;
217 inblock
.len
= keybytes
;
219 BUG_ON(gk5e
->mk_key
== NULL
);
220 ret
= (*(gk5e
->mk_key
))(gk5e
, &inblock
, outkey
);
222 dprintk("%s: got %d from mk_key function for '%s'\n",
223 __func__
, ret
, gk5e
->encrypt_name
);
227 /* clean memory, free resources and exit */
232 memset(rawkey
, 0, keybytes
);
235 memset(outblockdata
, 0, blocksize
);
238 memset(inblockdata
, 0, blocksize
);
241 crypto_free_skcipher(cipher
);
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)
250 static void mit_des_fixup_key_parity(u8 key
[8])
253 for (i
= 0; i
< 8; i
++) {
255 key
[i
] |= 1^parity_char(key
[i
]);
260 * This is the des3 key derivation postprocess function
262 u32
gss_krb5_des3_make_key(const struct gss_krb5_enctype
*gk5e
,
263 struct xdr_netobj
*randombits
,
264 struct xdr_netobj
*key
)
269 if (key
->len
!= 24) {
270 dprintk("%s: key->len is %d\n", __func__
, key
->len
);
273 if (randombits
->len
!= 21) {
274 dprintk("%s: randombits->len is %d\n",
275 __func__
, randombits
->len
);
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. */
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));
292 mit_des_fixup_key_parity(key
->data
+ i
*8);
300 * This is the aes key derivation postprocess function
302 u32
gss_krb5_aes_make_key(const struct gss_krb5_enctype
*gk5e
,
303 struct xdr_netobj
*randombits
,
304 struct xdr_netobj
*key
)
308 if (key
->len
!= 16 && key
->len
!= 32) {
309 dprintk("%s: key->len is %d\n", __func__
, key
->len
);
312 if (randombits
->len
!= 16 && randombits
->len
!= 32) {
313 dprintk("%s: randombits->len is %d\n",
314 __func__
, randombits
->len
);
317 if (randombits
->len
!= key
->len
) {
318 dprintk("%s: randombits->len is %d, key->len is %d\n",
319 __func__
, randombits
->len
, key
->len
);
322 memcpy(key
->data
, randombits
->data
, key
->len
);