1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * SHA1 T-PRF for EAP-FAST
3e5b75505Sopenharmony_ci * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
4e5b75505Sopenharmony_ci *
5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
6e5b75505Sopenharmony_ci * See README for more details.
7e5b75505Sopenharmony_ci */
8e5b75505Sopenharmony_ci
9e5b75505Sopenharmony_ci#include "includes.h"
10e5b75505Sopenharmony_ci
11e5b75505Sopenharmony_ci#include "common.h"
12e5b75505Sopenharmony_ci#include "sha1.h"
13e5b75505Sopenharmony_ci#include "crypto.h"
14e5b75505Sopenharmony_ci
15e5b75505Sopenharmony_ci/**
16e5b75505Sopenharmony_ci * sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF)
17e5b75505Sopenharmony_ci * @key: Key for PRF
18e5b75505Sopenharmony_ci * @key_len: Length of the key in bytes
19e5b75505Sopenharmony_ci * @label: A unique label for each purpose of the PRF
20e5b75505Sopenharmony_ci * @seed: Seed value to bind into the key
21e5b75505Sopenharmony_ci * @seed_len: Length of the seed
22e5b75505Sopenharmony_ci * @buf: Buffer for the generated pseudo-random key
23e5b75505Sopenharmony_ci * @buf_len: Number of bytes of key to generate
24e5b75505Sopenharmony_ci * Returns: 0 on success, -1 of failure
25e5b75505Sopenharmony_ci *
26e5b75505Sopenharmony_ci * This function is used to derive new, cryptographically separate keys from a
27e5b75505Sopenharmony_ci * given key for EAP-FAST. T-PRF is defined in RFC 4851, Section 5.5.
28e5b75505Sopenharmony_ci */
29e5b75505Sopenharmony_ciint sha1_t_prf(const u8 *key, size_t key_len, const char *label,
30e5b75505Sopenharmony_ci	       const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len)
31e5b75505Sopenharmony_ci{
32e5b75505Sopenharmony_ci	unsigned char counter = 0;
33e5b75505Sopenharmony_ci	size_t pos, plen;
34e5b75505Sopenharmony_ci	u8 hash[SHA1_MAC_LEN];
35e5b75505Sopenharmony_ci	size_t label_len = os_strlen(label);
36e5b75505Sopenharmony_ci	u8 output_len[2];
37e5b75505Sopenharmony_ci	const unsigned char *addr[5];
38e5b75505Sopenharmony_ci	size_t len[5];
39e5b75505Sopenharmony_ci
40e5b75505Sopenharmony_ci	addr[0] = hash;
41e5b75505Sopenharmony_ci	len[0] = 0;
42e5b75505Sopenharmony_ci	addr[1] = (unsigned char *) label;
43e5b75505Sopenharmony_ci	len[1] = label_len + 1;
44e5b75505Sopenharmony_ci	addr[2] = seed;
45e5b75505Sopenharmony_ci	len[2] = seed_len;
46e5b75505Sopenharmony_ci	addr[3] = output_len;
47e5b75505Sopenharmony_ci	len[3] = 2;
48e5b75505Sopenharmony_ci	addr[4] = &counter;
49e5b75505Sopenharmony_ci	len[4] = 1;
50e5b75505Sopenharmony_ci
51e5b75505Sopenharmony_ci	output_len[0] = (buf_len >> 8) & 0xff;
52e5b75505Sopenharmony_ci	output_len[1] = buf_len & 0xff;
53e5b75505Sopenharmony_ci	pos = 0;
54e5b75505Sopenharmony_ci	while (pos < buf_len) {
55e5b75505Sopenharmony_ci		counter++;
56e5b75505Sopenharmony_ci		plen = buf_len - pos;
57e5b75505Sopenharmony_ci		if (hmac_sha1_vector(key, key_len, 5, addr, len, hash))
58e5b75505Sopenharmony_ci			return -1;
59e5b75505Sopenharmony_ci		if (plen >= SHA1_MAC_LEN) {
60e5b75505Sopenharmony_ci			os_memcpy(&buf[pos], hash, SHA1_MAC_LEN);
61e5b75505Sopenharmony_ci			pos += SHA1_MAC_LEN;
62e5b75505Sopenharmony_ci		} else {
63e5b75505Sopenharmony_ci			os_memcpy(&buf[pos], hash, plen);
64e5b75505Sopenharmony_ci			break;
65e5b75505Sopenharmony_ci		}
66e5b75505Sopenharmony_ci		len[0] = SHA1_MAC_LEN;
67e5b75505Sopenharmony_ci	}
68e5b75505Sopenharmony_ci
69e5b75505Sopenharmony_ci	forced_memzero(hash, SHA1_MAC_LEN);
70e5b75505Sopenharmony_ci
71e5b75505Sopenharmony_ci	return 0;
72e5b75505Sopenharmony_ci}
73