16d49e1aeSJan Lentfer /*
26d49e1aeSJan Lentfer * EAP server/peer: EAP-PSK shared routines
36d49e1aeSJan Lentfer * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer *
5*3ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license.
6*3ff40c12SJohn Marino * See README for more details.
76d49e1aeSJan Lentfer */
86d49e1aeSJan Lentfer
96d49e1aeSJan Lentfer #include "includes.h"
106d49e1aeSJan Lentfer
116d49e1aeSJan Lentfer #include "common.h"
12*3ff40c12SJohn Marino #include "crypto/aes_wrap.h"
136d49e1aeSJan Lentfer #include "eap_defs.h"
146d49e1aeSJan Lentfer #include "eap_psk_common.h"
156d49e1aeSJan Lentfer
166d49e1aeSJan Lentfer #define aes_block_size 16
176d49e1aeSJan Lentfer
186d49e1aeSJan Lentfer
eap_psk_key_setup(const u8 * psk,u8 * ak,u8 * kdk)196d49e1aeSJan Lentfer int eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk)
206d49e1aeSJan Lentfer {
216d49e1aeSJan Lentfer os_memset(ak, 0, aes_block_size);
226d49e1aeSJan Lentfer if (aes_128_encrypt_block(psk, ak, ak))
236d49e1aeSJan Lentfer return -1;
246d49e1aeSJan Lentfer os_memcpy(kdk, ak, aes_block_size);
256d49e1aeSJan Lentfer ak[aes_block_size - 1] ^= 0x01;
266d49e1aeSJan Lentfer kdk[aes_block_size - 1] ^= 0x02;
276d49e1aeSJan Lentfer if (aes_128_encrypt_block(psk, ak, ak) ||
286d49e1aeSJan Lentfer aes_128_encrypt_block(psk, kdk, kdk))
296d49e1aeSJan Lentfer return -1;
306d49e1aeSJan Lentfer return 0;
316d49e1aeSJan Lentfer }
326d49e1aeSJan Lentfer
336d49e1aeSJan Lentfer
eap_psk_derive_keys(const u8 * kdk,const u8 * rand_p,u8 * tek,u8 * msk,u8 * emsk)346d49e1aeSJan Lentfer int eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, u8 *msk,
356d49e1aeSJan Lentfer u8 *emsk)
366d49e1aeSJan Lentfer {
376d49e1aeSJan Lentfer u8 hash[aes_block_size];
386d49e1aeSJan Lentfer u8 counter = 1;
396d49e1aeSJan Lentfer int i;
406d49e1aeSJan Lentfer
416d49e1aeSJan Lentfer if (aes_128_encrypt_block(kdk, rand_p, hash))
426d49e1aeSJan Lentfer return -1;
436d49e1aeSJan Lentfer
446d49e1aeSJan Lentfer hash[aes_block_size - 1] ^= counter;
456d49e1aeSJan Lentfer if (aes_128_encrypt_block(kdk, hash, tek))
466d49e1aeSJan Lentfer return -1;
476d49e1aeSJan Lentfer hash[aes_block_size - 1] ^= counter;
486d49e1aeSJan Lentfer counter++;
496d49e1aeSJan Lentfer
506d49e1aeSJan Lentfer for (i = 0; i < EAP_MSK_LEN / aes_block_size; i++) {
516d49e1aeSJan Lentfer hash[aes_block_size - 1] ^= counter;
526d49e1aeSJan Lentfer if (aes_128_encrypt_block(kdk, hash, &msk[i * aes_block_size]))
536d49e1aeSJan Lentfer return -1;
546d49e1aeSJan Lentfer hash[aes_block_size - 1] ^= counter;
556d49e1aeSJan Lentfer counter++;
566d49e1aeSJan Lentfer }
576d49e1aeSJan Lentfer
586d49e1aeSJan Lentfer for (i = 0; i < EAP_EMSK_LEN / aes_block_size; i++) {
596d49e1aeSJan Lentfer hash[aes_block_size - 1] ^= counter;
606d49e1aeSJan Lentfer if (aes_128_encrypt_block(kdk, hash,
616d49e1aeSJan Lentfer &emsk[i * aes_block_size]))
626d49e1aeSJan Lentfer return -1;
636d49e1aeSJan Lentfer hash[aes_block_size - 1] ^= counter;
646d49e1aeSJan Lentfer counter++;
656d49e1aeSJan Lentfer }
666d49e1aeSJan Lentfer
676d49e1aeSJan Lentfer return 0;
686d49e1aeSJan Lentfer }
69