aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/auth_gss/gss_krb5_keys.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/auth_gss/gss_krb5_keys.c')
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_keys.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c
index 253b4149584a..d54668790f0c 100644
--- a/net/sunrpc/auth_gss/gss_krb5_keys.c
+++ b/net/sunrpc/auth_gss/gss_krb5_keys.c
@@ -250,3 +250,56 @@ err_free_cipher:
250err_return: 250err_return:
251 return ret; 251 return ret;
252} 252}
253
254#define smask(step) ((1<<step)-1)
255#define pstep(x, step) (((x)&smask(step))^(((x)>>step)&smask(step)))
256#define parity_char(x) pstep(pstep(pstep((x), 4), 2), 1)
257
258static void mit_des_fixup_key_parity(u8 key[8])
259{
260 int i;
261 for (i = 0; i < 8; i++) {
262 key[i] &= 0xfe;
263 key[i] |= 1^parity_char(key[i]);
264 }
265}
266
267/*
268 * This is the des3 key derivation postprocess function
269 */
270u32 gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e,
271 struct xdr_netobj *randombits,
272 struct xdr_netobj *key)
273{
274 int i;
275 u32 ret = EINVAL;
276
277 if (key->len != 24) {
278 dprintk("%s: key->len is %d\n", __func__, key->len);
279 goto err_out;
280 }
281 if (randombits->len != 21) {
282 dprintk("%s: randombits->len is %d\n",
283 __func__, randombits->len);
284 goto err_out;
285 }
286
287 /* take the seven bytes, move them around into the top 7 bits of the
288 8 key bytes, then compute the parity bits. Do this three times. */
289
290 for (i = 0; i < 3; i++) {
291 memcpy(key->data + i*8, randombits->data + i*7, 7);
292 key->data[i*8+7] = (((key->data[i*8]&1)<<1) |
293 ((key->data[i*8+1]&1)<<2) |
294 ((key->data[i*8+2]&1)<<3) |
295 ((key->data[i*8+3]&1)<<4) |
296 ((key->data[i*8+4]&1)<<5) |
297 ((key->data[i*8+5]&1)<<6) |
298 ((key->data[i*8+6]&1)<<7));
299
300 mit_des_fixup_key_parity(key->data + i*8);
301 }
302 ret = 0;
303err_out:
304 return ret;
305}