Coverage Report

Created: 2025-07-18 06:03

/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
}