1189251Ssam/* 2189251Ssam * EAP-PEAP common routines 3252726Srpaulo * Copyright (c) 2008-2011, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam */ 8189251Ssam 9189251Ssam#include "includes.h" 10189251Ssam 11189251Ssam#include "common.h" 12214734Srpaulo#include "crypto/sha1.h" 13189251Ssam#include "eap_peap_common.h" 14189251Ssam 15252726Srpauloint peap_prfplus(int version, const u8 *key, size_t key_len, 16252726Srpaulo const char *label, const u8 *seed, size_t seed_len, 17252726Srpaulo u8 *buf, size_t buf_len) 18189251Ssam{ 19189251Ssam unsigned char counter = 0; 20189251Ssam size_t pos, plen; 21189251Ssam u8 hash[SHA1_MAC_LEN]; 22189251Ssam size_t label_len = os_strlen(label); 23189251Ssam u8 extra[2]; 24189251Ssam const unsigned char *addr[5]; 25189251Ssam size_t len[5]; 26189251Ssam 27189251Ssam addr[0] = hash; 28189251Ssam len[0] = 0; 29189251Ssam addr[1] = (unsigned char *) label; 30189251Ssam len[1] = label_len; 31189251Ssam addr[2] = seed; 32189251Ssam len[2] = seed_len; 33189251Ssam 34189251Ssam if (version == 0) { 35189251Ssam /* 36189251Ssam * PRF+(K, S, LEN) = T1 | T2 | ... | Tn 37189251Ssam * T1 = HMAC-SHA1(K, S | 0x01 | 0x00 | 0x00) 38189251Ssam * T2 = HMAC-SHA1(K, T1 | S | 0x02 | 0x00 | 0x00) 39189251Ssam * ... 40189251Ssam * Tn = HMAC-SHA1(K, Tn-1 | S | n | 0x00 | 0x00) 41189251Ssam */ 42189251Ssam 43189251Ssam extra[0] = 0; 44189251Ssam extra[1] = 0; 45189251Ssam 46189251Ssam addr[3] = &counter; 47189251Ssam len[3] = 1; 48189251Ssam addr[4] = extra; 49189251Ssam len[4] = 2; 50189251Ssam } else { 51189251Ssam /* 52189251Ssam * PRF (K,S,LEN) = T1 | T2 | T3 | T4 | ... where: 53189251Ssam * T1 = HMAC-SHA1(K, S | LEN | 0x01) 54189251Ssam * T2 = HMAC-SHA1 (K, T1 | S | LEN | 0x02) 55189251Ssam * T3 = HMAC-SHA1 (K, T2 | S | LEN | 0x03) 56189251Ssam * T4 = HMAC-SHA1 (K, T3 | S | LEN | 0x04) 57189251Ssam * ... 58189251Ssam */ 59189251Ssam 60189251Ssam extra[0] = buf_len & 0xff; 61189251Ssam 62189251Ssam addr[3] = extra; 63189251Ssam len[3] = 1; 64189251Ssam addr[4] = &counter; 65189251Ssam len[4] = 1; 66189251Ssam } 67189251Ssam 68189251Ssam pos = 0; 69189251Ssam while (pos < buf_len) { 70189251Ssam counter++; 71189251Ssam plen = buf_len - pos; 72252726Srpaulo if (hmac_sha1_vector(key, key_len, 5, addr, len, hash) < 0) 73252726Srpaulo return -1; 74189251Ssam if (plen >= SHA1_MAC_LEN) { 75189251Ssam os_memcpy(&buf[pos], hash, SHA1_MAC_LEN); 76189251Ssam pos += SHA1_MAC_LEN; 77189251Ssam } else { 78189251Ssam os_memcpy(&buf[pos], hash, plen); 79189251Ssam break; 80189251Ssam } 81189251Ssam len[0] = SHA1_MAC_LEN; 82189251Ssam } 83252726Srpaulo 84252726Srpaulo return 0; 85189251Ssam} 86