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