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