1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * EAP server/peer: EAP-PSK shared routines
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify
6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as
7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation.
8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license.
11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details.
13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h"
16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
18b349ef9e9f3f5399bf96b3c1c663cb9e547f50a1Dmitry Shmidt#include "crypto/aes_wrap.h"
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_defs.h"
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_psk_common.h"
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define aes_block_size 16
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk)
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(ak, 0, aes_block_size);
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (aes_128_encrypt_block(psk, ak, ak))
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(kdk, ak, aes_block_size);
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ak[aes_block_size - 1] ^= 0x01;
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	kdk[aes_block_size - 1] ^= 0x02;
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (aes_128_encrypt_block(psk, ak, ak) ||
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    aes_128_encrypt_block(psk, kdk, kdk))
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, u8 *msk,
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			u8 *emsk)
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 hash[aes_block_size];
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 counter = 1;
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int i;
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (aes_128_encrypt_block(kdk, rand_p, hash))
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hash[aes_block_size - 1] ^= counter;
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (aes_128_encrypt_block(kdk, hash, tek))
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hash[aes_block_size - 1] ^= counter;
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	counter++;
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; i < EAP_MSK_LEN / aes_block_size; i++) {
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hash[aes_block_size - 1] ^= counter;
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (aes_128_encrypt_block(kdk, hash, &msk[i * aes_block_size]))
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hash[aes_block_size - 1] ^= counter;
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		counter++;
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; i < EAP_EMSK_LEN / aes_block_size; i++) {
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hash[aes_block_size - 1] ^= counter;
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (aes_128_encrypt_block(kdk, hash,
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  &emsk[i * aes_block_size]))
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hash[aes_block_size - 1] ^= counter;
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		counter++;
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
75