/src/hostap/src/crypto/sha256-prf.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * SHA256-based PRF (IEEE 802.11r) |
3 | | * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> |
4 | | * |
5 | | * This software may be distributed under the terms of the BSD license. |
6 | | * See README for more details. |
7 | | */ |
8 | | |
9 | | #include "includes.h" |
10 | | |
11 | | #include "common.h" |
12 | | #include "sha256.h" |
13 | | #include "crypto.h" |
14 | | |
15 | | |
16 | | /** |
17 | | * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2) |
18 | | * @key: Key for PRF |
19 | | * @key_len: Length of the key in bytes |
20 | | * @label: A unique label for each purpose of the PRF |
21 | | * @data: Extra data to bind into the key |
22 | | * @data_len: Length of the data |
23 | | * @buf: Buffer for the generated pseudo-random key |
24 | | * @buf_len: Number of bytes of key to generate |
25 | | * Returns: 0 on success, -1 on failure |
26 | | * |
27 | | * This function is used to derive new, cryptographically separate keys from a |
28 | | * given key. |
29 | | */ |
30 | | int sha256_prf(const u8 *key, size_t key_len, const char *label, |
31 | | const u8 *data, size_t data_len, u8 *buf, size_t buf_len) |
32 | 0 | { |
33 | 0 | return sha256_prf_bits(key, key_len, label, data, data_len, buf, |
34 | 0 | buf_len * 8); |
35 | 0 | } |
36 | | |
37 | | |
38 | | /** |
39 | | * sha256_prf_bits - IEEE Std 802.11-2012, 11.6.1.7.2 Key derivation function |
40 | | * @key: Key for KDF |
41 | | * @key_len: Length of the key in bytes |
42 | | * @label: A unique label for each purpose of the PRF |
43 | | * @data: Extra data to bind into the key |
44 | | * @data_len: Length of the data |
45 | | * @buf: Buffer for the generated pseudo-random key |
46 | | * @buf_len: Number of bits of key to generate |
47 | | * Returns: 0 on success, -1 on failure |
48 | | * |
49 | | * This function is used to derive new, cryptographically separate keys from a |
50 | | * given key. If the requested buf_len is not divisible by eight, the least |
51 | | * significant 1-7 bits of the last octet in the output are not part of the |
52 | | * requested output. |
53 | | */ |
54 | | int sha256_prf_bits(const u8 *key, size_t key_len, const char *label, |
55 | | const u8 *data, size_t data_len, u8 *buf, |
56 | | size_t buf_len_bits) |
57 | 0 | { |
58 | 0 | u16 counter = 1; |
59 | 0 | size_t pos, plen; |
60 | 0 | u8 hash[SHA256_MAC_LEN]; |
61 | 0 | const u8 *addr[4]; |
62 | 0 | size_t len[4]; |
63 | 0 | u8 counter_le[2], length_le[2]; |
64 | 0 | size_t buf_len = (buf_len_bits + 7) / 8; |
65 | |
|
66 | 0 | addr[0] = counter_le; |
67 | 0 | len[0] = 2; |
68 | 0 | addr[1] = (u8 *) label; |
69 | 0 | len[1] = os_strlen(label); |
70 | 0 | addr[2] = data; |
71 | 0 | len[2] = data_len; |
72 | 0 | addr[3] = length_le; |
73 | 0 | len[3] = sizeof(length_le); |
74 | |
|
75 | 0 | WPA_PUT_LE16(length_le, buf_len_bits); |
76 | 0 | pos = 0; |
77 | 0 | while (pos < buf_len) { |
78 | 0 | plen = buf_len - pos; |
79 | 0 | WPA_PUT_LE16(counter_le, counter); |
80 | 0 | if (plen >= SHA256_MAC_LEN) { |
81 | 0 | if (hmac_sha256_vector(key, key_len, 4, addr, len, |
82 | 0 | &buf[pos]) < 0) |
83 | 0 | return -1; |
84 | 0 | pos += SHA256_MAC_LEN; |
85 | 0 | } else { |
86 | 0 | if (hmac_sha256_vector(key, key_len, 4, addr, len, |
87 | 0 | hash) < 0) |
88 | 0 | return -1; |
89 | 0 | os_memcpy(&buf[pos], hash, plen); |
90 | 0 | pos += plen; |
91 | 0 | break; |
92 | 0 | } |
93 | 0 | counter++; |
94 | 0 | } |
95 | | |
96 | | /* |
97 | | * Mask out unused bits in the last octet if it does not use all the |
98 | | * bits. |
99 | | */ |
100 | 0 | if (pos > 0 && (buf_len_bits % 8)) { |
101 | 0 | u8 mask = 0xff << (8 - buf_len_bits % 8); |
102 | 0 | buf[pos - 1] &= mask; |
103 | 0 | } |
104 | |
|
105 | 0 | forced_memzero(hash, sizeof(hash)); |
106 | |
|
107 | 0 | return 0; |
108 | 0 | } |