Coverage Report

Created: 2025-10-28 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hostap/src/crypto/sha256-kdf.c
Line
Count
Source
1
/*
2
 * HMAC-SHA256 KDF (RFC 5295) and HKDF-Expand(SHA256) (RFC 5869)
3
 * Copyright (c) 2014-2017, 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
14
15
/**
16
 * hmac_sha256_kdf - HMAC-SHA256 based KDF (RFC 5295)
17
 * @secret: Key for KDF
18
 * @secret_len: Length of the key in bytes
19
 * @label: A unique label for each purpose of the KDF or %NULL to select
20
 *  RFC 5869 HKDF-Expand() with arbitrary seed (= info)
21
 * @seed: Seed value to bind into the key
22
 * @seed_len: Length of the seed
23
 * @out: Buffer for the generated pseudo-random key
24
 * @outlen: 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 in ERP. This KDF is defined in RFC 5295, Chapter 3.1.2. When used
29
 * with label = NULL and seed = info, this matches HKDF-Expand() defined in
30
 * RFC 5869, Chapter 2.3.
31
 */
32
int hmac_sha256_kdf(const u8 *secret, size_t secret_len,
33
        const char *label, const u8 *seed, size_t seed_len,
34
        u8 *out, size_t outlen)
35
0
{
36
0
  u8 T[SHA256_MAC_LEN];
37
0
  u8 iter = 1;
38
0
  const unsigned char *addr[4];
39
0
  size_t len[4];
40
0
  size_t pos, clen;
41
42
0
  addr[0] = T;
43
0
  len[0] = SHA256_MAC_LEN;
44
0
  if (label) {
45
0
    addr[1] = (const unsigned char *) label;
46
0
    len[1] = os_strlen(label) + 1;
47
0
  } else {
48
0
    addr[1] = (const u8 *) "";
49
0
    len[1] = 0;
50
0
  }
51
0
  addr[2] = seed;
52
0
  len[2] = seed_len;
53
0
  addr[3] = &iter;
54
0
  len[3] = 1;
55
56
0
  if (hmac_sha256_vector(secret, secret_len, 3, &addr[1], &len[1], T) < 0)
57
0
    return -1;
58
59
0
  pos = 0;
60
0
  for (;;) {
61
0
    clen = outlen - pos;
62
0
    if (clen > SHA256_MAC_LEN)
63
0
      clen = SHA256_MAC_LEN;
64
0
    os_memcpy(out + pos, T, clen);
65
0
    pos += clen;
66
67
0
    if (pos == outlen)
68
0
      break;
69
70
0
    if (iter == 255) {
71
0
      os_memset(out, 0, outlen);
72
0
      forced_memzero(T, SHA256_MAC_LEN);
73
0
      return -1;
74
0
    }
75
0
    iter++;
76
77
0
    if (hmac_sha256_vector(secret, secret_len, 4, addr, len, T) < 0)
78
0
    {
79
0
      os_memset(out, 0, outlen);
80
0
      forced_memzero(T, SHA256_MAC_LEN);
81
0
      return -1;
82
0
    }
83
0
  }
84
85
0
  forced_memzero(T, SHA256_MAC_LEN);
86
0
  return 0;
87
0
}