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 <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>
64 # define RPCDBG_FACILITY RPCDBG_AUTH
68 * This is the n-fold function as described in rfc3961, sec 5.1
69 * Taken from MIT Kerberos and modified.
72 static void krb5_nfold(u32 inbits
, const u8
*in
,
78 /* the code below is more readable if I make these bytes
84 /* first compute lcm(n,k) */
95 lcm
= outbits
*inbits
/a
;
97 /* now do the real work */
99 memset(out
, 0, outbits
);
102 /* this will end up cycling through k lcm(k,n)/k times, which
104 for (i
= lcm
-1; i
>= 0; i
--) {
105 /* compute the msbit in k which gets added into this byte */
107 /* first, start with the msbit in the first,
110 /* then, for each byte, shift to the right
111 * for each repetition */
112 + (((inbits
<< 3) + 13) * (i
/inbits
))
113 /* last, pick out the correct byte within
114 * that shifted repetition */
115 + ((inbits
- (i
% inbits
)) << 3)
118 /* pull out the byte value itself */
119 byte
+= (((in
[((inbits
- 1) - (msbit
>> 3)) % inbits
] << 8)|
120 (in
[((inbits
) - (msbit
>> 3)) % inbits
]))
121 >> ((msbit
& 7) + 1)) & 0xff;
123 /* do the addition */
124 byte
+= out
[i
% outbits
];
125 out
[i
% outbits
] = byte
& 0xff;
127 /* keep around the carry bit, if any */
132 /* if there's a carry bit left over, add it back in */
134 for (i
= outbits
- 1; i
>= 0; i
--) {
135 /* do the addition */
137 out
[i
] = byte
& 0xff;
139 /* keep around the carry bit, if any */
146 * This is the DK (derive_key) function as described in rfc3961, sec 5.1
147 * Taken from MIT Kerberos and modified.
150 u32
krb5_derive_key(const struct gss_krb5_enctype
*gk5e
,
151 const struct xdr_netobj
*inkey
,
152 struct xdr_netobj
*outkey
,
153 const struct xdr_netobj
*in_constant
,
156 size_t blocksize
, keybytes
, keylength
, n
;
157 unsigned char *inblockdata
, *outblockdata
, *rawkey
;
158 struct xdr_netobj inblock
, outblock
;
159 struct crypto_blkcipher
*cipher
;
162 blocksize
= gk5e
->blocksize
;
163 keybytes
= gk5e
->keybytes
;
164 keylength
= gk5e
->keylength
;
166 if ((inkey
->len
!= keylength
) || (outkey
->len
!= keylength
))
169 cipher
= crypto_alloc_blkcipher(gk5e
->encrypt_name
, 0,
173 if (crypto_blkcipher_setkey(cipher
, inkey
->data
, inkey
->len
))
176 /* allocate and set up buffers */
179 inblockdata
= kmalloc(blocksize
, gfp_mask
);
180 if (inblockdata
== NULL
)
181 goto err_free_cipher
;
183 outblockdata
= kmalloc(blocksize
, gfp_mask
);
184 if (outblockdata
== NULL
)
187 rawkey
= kmalloc(keybytes
, gfp_mask
);
191 inblock
.data
= (char *) inblockdata
;
192 inblock
.len
= blocksize
;
194 outblock
.data
= (char *) outblockdata
;
195 outblock
.len
= blocksize
;
197 /* initialize the input block */
199 if (in_constant
->len
== inblock
.len
) {
200 memcpy(inblock
.data
, in_constant
->data
, inblock
.len
);
202 krb5_nfold(in_constant
->len
* 8, in_constant
->data
,
203 inblock
.len
* 8, inblock
.data
);
206 /* loop encrypting the blocks until enough key bytes are generated */
209 while (n
< keybytes
) {
210 (*(gk5e
->encrypt
))(cipher
, NULL
, inblock
.data
,
211 outblock
.data
, inblock
.len
);
213 if ((keybytes
- n
) <= outblock
.len
) {
214 memcpy(rawkey
+ n
, outblock
.data
, (keybytes
- n
));
218 memcpy(rawkey
+ n
, outblock
.data
, outblock
.len
);
219 memcpy(inblock
.data
, outblock
.data
, outblock
.len
);
223 /* postprocess the key */
225 inblock
.data
= (char *) rawkey
;
226 inblock
.len
= keybytes
;
228 BUG_ON(gk5e
->mk_key
== NULL
);
229 ret
= (*(gk5e
->mk_key
))(gk5e
, &inblock
, outkey
);
231 dprintk("%s: got %d from mk_key function for '%s'\n",
232 __func__
, ret
, gk5e
->encrypt_name
);
236 /* clean memory, free resources and exit */
241 memset(rawkey
, 0, keybytes
);
244 memset(outblockdata
, 0, blocksize
);
247 memset(inblockdata
, 0, blocksize
);
250 crypto_free_blkcipher(cipher
);
255 #define smask(step) ((1<<step)-1)
256 #define pstep(x, step) (((x)&smask(step))^(((x)>>step)&smask(step)))
257 #define parity_char(x) pstep(pstep(pstep((x), 4), 2), 1)
259 static void mit_des_fixup_key_parity(u8 key
[8])
262 for (i
= 0; i
< 8; i
++) {
264 key
[i
] |= 1^parity_char(key
[i
]);
269 * This is the des3 key derivation postprocess function
271 u32
gss_krb5_des3_make_key(const struct gss_krb5_enctype
*gk5e
,
272 struct xdr_netobj
*randombits
,
273 struct xdr_netobj
*key
)
278 if (key
->len
!= 24) {
279 dprintk("%s: key->len is %d\n", __func__
, key
->len
);
282 if (randombits
->len
!= 21) {
283 dprintk("%s: randombits->len is %d\n",
284 __func__
, randombits
->len
);
288 /* take the seven bytes, move them around into the top 7 bits of the
289 8 key bytes, then compute the parity bits. Do this three times. */
291 for (i
= 0; i
< 3; i
++) {
292 memcpy(key
->data
+ i
*8, randombits
->data
+ i
*7, 7);
293 key
->data
[i
*8+7] = (((key
->data
[i
*8]&1)<<1) |
294 ((key
->data
[i
*8+1]&1)<<2) |
295 ((key
->data
[i
*8+2]&1)<<3) |
296 ((key
->data
[i
*8+3]&1)<<4) |
297 ((key
->data
[i
*8+4]&1)<<5) |
298 ((key
->data
[i
*8+5]&1)<<6) |
299 ((key
->data
[i
*8+6]&1)<<7));
301 mit_des_fixup_key_parity(key
->data
+ i
*8);
309 * This is the aes key derivation postprocess function
311 u32
gss_krb5_aes_make_key(const struct gss_krb5_enctype
*gk5e
,
312 struct xdr_netobj
*randombits
,
313 struct xdr_netobj
*key
)
317 if (key
->len
!= 16 && key
->len
!= 32) {
318 dprintk("%s: key->len is %d\n", __func__
, key
->len
);
321 if (randombits
->len
!= 16 && randombits
->len
!= 32) {
322 dprintk("%s: randombits->len is %d\n",
323 __func__
, randombits
->len
);
326 if (randombits
->len
!= key
->len
) {
327 dprintk("%s: randombits->len is %d, key->len is %d\n",
328 __func__
, randombits
->len
, key
->len
);
331 memcpy(key
->data
, randombits
->data
, key
->len
);