diff --git a/hostapd/Makefile b/hostapd/Makefile index a43e93a5d..1e7390620 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -165,6 +165,7 @@ endif ifdef CONFIG_EAP_PEAP CFLAGS += -DEAP_PEAP OBJS += ../src/eap_server/eap_peap.o +OBJS += ../src/eap_common/eap_peap_common.o TLS_FUNCS=y CONFIG_EAP_MSCHAPV2=y endif diff --git a/src/eap_common/eap_peap_common.c b/src/eap_common/eap_peap_common.c new file mode 100644 index 000000000..2bf295c7d --- /dev/null +++ b/src/eap_common/eap_peap_common.c @@ -0,0 +1,87 @@ +/* + * EAP-PEAP common routines + * Copyright (c) 2008, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "sha1.h" + +void peap_prfplus(int version, const u8 *key, size_t key_len, + const char *label, const u8 *seed, size_t seed_len, + u8 *buf, size_t buf_len) +{ + unsigned char counter = 0; + size_t pos, plen; + u8 hash[SHA1_MAC_LEN]; + size_t label_len = os_strlen(label); + u8 extra[2]; + const unsigned char *addr[5]; + size_t len[5]; + + addr[0] = hash; + len[0] = 0; + addr[1] = (unsigned char *) label; + len[1] = label_len; + addr[2] = seed; + len[2] = seed_len; + + if (version == 0) { + /* + * PRF+(K, S, LEN) = T1 | T2 | ... | Tn + * T1 = HMAC-SHA1(K, S | 0x01 | 0x00 | 0x00) + * T2 = HMAC-SHA1(K, T1 | S | 0x02 | 0x00 | 0x00) + * ... + * Tn = HMAC-SHA1(K, Tn-1 | S | n | 0x00 | 0x00) + */ + + extra[0] = 0; + extra[1] = 0; + + addr[3] = &counter; + len[3] = 1; + addr[4] = extra; + len[4] = 2; + } else { + /* + * PRF (K,S,LEN) = T1 | T2 | T3 | T4 | ... where: + * T1 = HMAC-SHA1(K, S | LEN | 0x01) + * T2 = HMAC-SHA1 (K, T1 | S | LEN | 0x02) + * T3 = HMAC-SHA1 (K, T2 | S | LEN | 0x03) + * T4 = HMAC-SHA1 (K, T3 | S | LEN | 0x04) + * ... + */ + + extra[0] = buf_len & 0xff; + + addr[3] = extra; + len[3] = 1; + addr[4] = &counter; + len[4] = 1; + } + + pos = 0; + while (pos < buf_len) { + counter++; + plen = buf_len - pos; + hmac_sha1_vector(key, key_len, 5, addr, len, hash); + if (plen >= SHA1_MAC_LEN) { + os_memcpy(&buf[pos], hash, SHA1_MAC_LEN); + pos += SHA1_MAC_LEN; + } else { + os_memcpy(&buf[pos], hash, plen); + break; + } + len[0] = SHA1_MAC_LEN; + } +} diff --git a/src/eap_common/eap_peap_common.h b/src/eap_common/eap_peap_common.h new file mode 100644 index 000000000..f59afb07d --- /dev/null +++ b/src/eap_common/eap_peap_common.h @@ -0,0 +1,22 @@ +/* + * EAP-PEAP common routines + * Copyright (c) 2008, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef EAP_PEAP_COMMON_H +#define EAP_PEAP_COMMON_H + +void peap_prfplus(int version, const u8 *key, size_t key_len, + const char *label, const u8 *seed, size_t seed_len, + u8 *buf, size_t buf_len); + +#endif /* EAP_PEAP_COMMON_H */ diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c index 44c619d62..954ecf131 100644 --- a/src/eap_peer/eap_peap.c +++ b/src/eap_peer/eap_peap.c @@ -21,6 +21,7 @@ #include "eap_config.h" #include "tls.h" #include "eap_common/eap_tlv_common.h" +#include "eap_common/eap_peap_common.h" #include "tncc.h" @@ -253,76 +254,6 @@ static int eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data, } -void peap_prfplus(int version, const u8 *key, size_t key_len, - const char *label, const u8 *seed, size_t seed_len, - u8 *buf, size_t buf_len) -{ - unsigned char counter = 0; - size_t pos, plen; - u8 hash[SHA1_MAC_LEN]; - size_t label_len = os_strlen(label); - u8 extra[2]; - const unsigned char *addr[5]; - size_t len[5]; - - addr[0] = hash; - len[0] = 0; - addr[1] = (unsigned char *) label; - len[1] = label_len; - addr[2] = seed; - len[2] = seed_len; - - if (version == 0) { - /* - * PRF+(K, S, LEN) = T1 | T2 | ... | Tn - * T1 = HMAC-SHA1(K, S | 0x01 | 0x00 | 0x00) - * T2 = HMAC-SHA1(K, T1 | S | 0x02 | 0x00 | 0x00) - * ... - * Tn = HMAC-SHA1(K, Tn-1 | S | n | 0x00 | 0x00) - */ - - extra[0] = 0; - extra[1] = 0; - - addr[3] = &counter; - len[3] = 1; - addr[4] = extra; - len[4] = 2; - } else { - /* - * PRF (K,S,LEN) = T1 | T2 | T3 | T4 | ... where: - * T1 = HMAC-SHA1(K, S | LEN | 0x01) - * T2 = HMAC-SHA1 (K, T1 | S | LEN | 0x02) - * T3 = HMAC-SHA1 (K, T2 | S | LEN | 0x03) - * T4 = HMAC-SHA1 (K, T3 | S | LEN | 0x04) - * ... - */ - - extra[0] = buf_len & 0xff; - - addr[3] = extra; - len[3] = 1; - addr[4] = &counter; - len[4] = 1; - } - - pos = 0; - while (pos < buf_len) { - counter++; - plen = buf_len - pos; - hmac_sha1_vector(key, key_len, 5, addr, len, hash); - if (plen >= SHA1_MAC_LEN) { - os_memcpy(&buf[pos], hash, SHA1_MAC_LEN); - pos += SHA1_MAC_LEN; - } else { - os_memcpy(&buf[pos], hash, plen); - break; - } - len[0] = SHA1_MAC_LEN; - } -} - - static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) { u8 *tk; diff --git a/src/eap_server/eap_peap.c b/src/eap_server/eap_peap.c index da73e02a6..5007d87e9 100644 --- a/src/eap_server/eap_peap.c +++ b/src/eap_server/eap_peap.c @@ -19,6 +19,7 @@ #include "eap_i.h" #include "eap_tls_common.h" #include "eap_common/eap_tlv_common.h" +#include "eap_common/eap_peap_common.h" #include "tls.h" #include "tncs.h" @@ -321,76 +322,6 @@ static void eap_peap_get_isk(struct eap_peap_data *data, } -void peap_prfplus(int version, const u8 *key, size_t key_len, - const char *label, const u8 *seed, size_t seed_len, - u8 *buf, size_t buf_len) -{ - unsigned char counter = 0; - size_t pos, plen; - u8 hash[SHA1_MAC_LEN]; - size_t label_len = os_strlen(label); - u8 extra[2]; - const unsigned char *addr[5]; - size_t len[5]; - - addr[0] = hash; - len[0] = 0; - addr[1] = (unsigned char *) label; - len[1] = label_len; - addr[2] = seed; - len[2] = seed_len; - - if (version == 0) { - /* - * PRF+(K, S, LEN) = T1 | T2 | ... | Tn - * T1 = HMAC-SHA1(K, S | 0x01 | 0x00 | 0x00) - * T2 = HMAC-SHA1(K, T1 | S | 0x02 | 0x00 | 0x00) - * ... - * Tn = HMAC-SHA1(K, Tn-1 | S | n | 0x00 | 0x00) - */ - - extra[0] = 0; - extra[1] = 0; - - addr[3] = &counter; - len[3] = 1; - addr[4] = extra; - len[4] = 2; - } else { - /* - * PRF (K,S,LEN) = T1 | T2 | T3 | T4 | ... where: - * T1 = HMAC-SHA1(K, S | LEN | 0x01) - * T2 = HMAC-SHA1 (K, T1 | S | LEN | 0x02) - * T3 = HMAC-SHA1 (K, T2 | S | LEN | 0x03) - * T4 = HMAC-SHA1 (K, T3 | S | LEN | 0x04) - * ... - */ - - extra[0] = buf_len & 0xff; - - addr[3] = extra; - len[3] = 1; - addr[4] = &counter; - len[4] = 1; - } - - pos = 0; - while (pos < buf_len) { - counter++; - plen = buf_len - pos; - hmac_sha1_vector(key, key_len, 5, addr, len, hash); - if (plen >= SHA1_MAC_LEN) { - os_memcpy(&buf[pos], hash, SHA1_MAC_LEN); - pos += SHA1_MAC_LEN; - } else { - os_memcpy(&buf[pos], hash, plen); - break; - } - len[0] = SHA1_MAC_LEN; - } -} - - static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) { u8 *tk; diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index c206f3391..33b0c4f95 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -276,6 +276,7 @@ EAPDYN += ../src/eap_peer/eap_peap.so else CFLAGS += -DEAP_PEAP OBJS += ../src/eap_peer/eap_peap.o +OBJS += ../src/eap_common/eap_peap_common.o OBJS_h += ../src/eap_server/eap_peap.o endif TLS_FUNCS=y