]>
Commit | Line | Data |
---|---|---|
77f273c8 JM |
1 | /* |
2 | * HMAC-SHA384 KDF (RFC 5295) and HKDF-Expand(SHA384) (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 "sha384.h" | |
13 | ||
14 | ||
15 | /** | |
16 | * hmac_sha384_kdf - HMAC-SHA384 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_sha384_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 | { | |
36 | u8 T[SHA384_MAC_LEN]; | |
37 | u8 iter = 1; | |
38 | const unsigned char *addr[4]; | |
39 | size_t len[4]; | |
40 | size_t pos, clen; | |
41 | ||
42 | addr[0] = T; | |
43 | len[0] = SHA384_MAC_LEN; | |
44 | if (label) { | |
45 | addr[1] = (const unsigned char *) label; | |
46 | len[1] = os_strlen(label) + 1; | |
47 | } else { | |
48 | addr[1] = (const u8 *) ""; | |
49 | len[1] = 0; | |
50 | } | |
51 | addr[2] = seed; | |
52 | len[2] = seed_len; | |
53 | addr[3] = &iter; | |
54 | len[3] = 1; | |
55 | ||
56 | if (hmac_sha384_vector(secret, secret_len, 3, &addr[1], &len[1], T) < 0) | |
57 | return -1; | |
58 | ||
59 | pos = 0; | |
60 | for (;;) { | |
61 | clen = outlen - pos; | |
62 | if (clen > SHA384_MAC_LEN) | |
63 | clen = SHA384_MAC_LEN; | |
64 | os_memcpy(out + pos, T, clen); | |
65 | pos += clen; | |
66 | ||
67 | if (pos == outlen) | |
68 | break; | |
69 | ||
70 | if (iter == 255) { | |
71 | os_memset(out, 0, outlen); | |
31bc66e4 | 72 | forced_memzero(T, SHA384_MAC_LEN); |
77f273c8 JM |
73 | return -1; |
74 | } | |
75 | iter++; | |
76 | ||
77 | if (hmac_sha384_vector(secret, secret_len, 4, addr, len, T) < 0) | |
78 | { | |
79 | os_memset(out, 0, outlen); | |
31bc66e4 | 80 | forced_memzero(T, SHA384_MAC_LEN); |
77f273c8 JM |
81 | return -1; |
82 | } | |
83 | } | |
84 | ||
31bc66e4 | 85 | forced_memzero(T, SHA384_MAC_LEN); |
77f273c8 JM |
86 | return 0; |
87 | } |