139beb93cSSam Leffler /* 239beb93cSSam Leffler * EAP-PEAP common routines 3*f05cddf9SRui Paulo * Copyright (c) 2008-2011, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 5*f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6*f05cddf9SRui Paulo * See README for more details. 739beb93cSSam Leffler */ 839beb93cSSam Leffler 939beb93cSSam Leffler #include "includes.h" 1039beb93cSSam Leffler 1139beb93cSSam Leffler #include "common.h" 12e28a4053SRui Paulo #include "crypto/sha1.h" 1339beb93cSSam Leffler #include "eap_peap_common.h" 1439beb93cSSam Leffler 15*f05cddf9SRui Paulo int peap_prfplus(int version, const u8 *key, size_t key_len, 1639beb93cSSam Leffler const char *label, const u8 *seed, size_t seed_len, 1739beb93cSSam Leffler u8 *buf, size_t buf_len) 1839beb93cSSam Leffler { 1939beb93cSSam Leffler unsigned char counter = 0; 2039beb93cSSam Leffler size_t pos, plen; 2139beb93cSSam Leffler u8 hash[SHA1_MAC_LEN]; 2239beb93cSSam Leffler size_t label_len = os_strlen(label); 2339beb93cSSam Leffler u8 extra[2]; 2439beb93cSSam Leffler const unsigned char *addr[5]; 2539beb93cSSam Leffler size_t len[5]; 2639beb93cSSam Leffler 2739beb93cSSam Leffler addr[0] = hash; 2839beb93cSSam Leffler len[0] = 0; 2939beb93cSSam Leffler addr[1] = (unsigned char *) label; 3039beb93cSSam Leffler len[1] = label_len; 3139beb93cSSam Leffler addr[2] = seed; 3239beb93cSSam Leffler len[2] = seed_len; 3339beb93cSSam Leffler 3439beb93cSSam Leffler if (version == 0) { 3539beb93cSSam Leffler /* 3639beb93cSSam Leffler * PRF+(K, S, LEN) = T1 | T2 | ... | Tn 3739beb93cSSam Leffler * T1 = HMAC-SHA1(K, S | 0x01 | 0x00 | 0x00) 3839beb93cSSam Leffler * T2 = HMAC-SHA1(K, T1 | S | 0x02 | 0x00 | 0x00) 3939beb93cSSam Leffler * ... 4039beb93cSSam Leffler * Tn = HMAC-SHA1(K, Tn-1 | S | n | 0x00 | 0x00) 4139beb93cSSam Leffler */ 4239beb93cSSam Leffler 4339beb93cSSam Leffler extra[0] = 0; 4439beb93cSSam Leffler extra[1] = 0; 4539beb93cSSam Leffler 4639beb93cSSam Leffler addr[3] = &counter; 4739beb93cSSam Leffler len[3] = 1; 4839beb93cSSam Leffler addr[4] = extra; 4939beb93cSSam Leffler len[4] = 2; 5039beb93cSSam Leffler } else { 5139beb93cSSam Leffler /* 5239beb93cSSam Leffler * PRF (K,S,LEN) = T1 | T2 | T3 | T4 | ... where: 5339beb93cSSam Leffler * T1 = HMAC-SHA1(K, S | LEN | 0x01) 5439beb93cSSam Leffler * T2 = HMAC-SHA1 (K, T1 | S | LEN | 0x02) 5539beb93cSSam Leffler * T3 = HMAC-SHA1 (K, T2 | S | LEN | 0x03) 5639beb93cSSam Leffler * T4 = HMAC-SHA1 (K, T3 | S | LEN | 0x04) 5739beb93cSSam Leffler * ... 5839beb93cSSam Leffler */ 5939beb93cSSam Leffler 6039beb93cSSam Leffler extra[0] = buf_len & 0xff; 6139beb93cSSam Leffler 6239beb93cSSam Leffler addr[3] = extra; 6339beb93cSSam Leffler len[3] = 1; 6439beb93cSSam Leffler addr[4] = &counter; 6539beb93cSSam Leffler len[4] = 1; 6639beb93cSSam Leffler } 6739beb93cSSam Leffler 6839beb93cSSam Leffler pos = 0; 6939beb93cSSam Leffler while (pos < buf_len) { 7039beb93cSSam Leffler counter++; 7139beb93cSSam Leffler plen = buf_len - pos; 72*f05cddf9SRui Paulo if (hmac_sha1_vector(key, key_len, 5, addr, len, hash) < 0) 73*f05cddf9SRui Paulo return -1; 7439beb93cSSam Leffler if (plen >= SHA1_MAC_LEN) { 7539beb93cSSam Leffler os_memcpy(&buf[pos], hash, SHA1_MAC_LEN); 7639beb93cSSam Leffler pos += SHA1_MAC_LEN; 7739beb93cSSam Leffler } else { 7839beb93cSSam Leffler os_memcpy(&buf[pos], hash, plen); 7939beb93cSSam Leffler break; 8039beb93cSSam Leffler } 8139beb93cSSam Leffler len[0] = SHA1_MAC_LEN; 8239beb93cSSam Leffler } 83*f05cddf9SRui Paulo 84*f05cddf9SRui Paulo return 0; 8539beb93cSSam Leffler } 86