1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * TLS PRF P_SHA384
3e5b75505Sopenharmony_ci * Copyright (c) 2011-2019, Jouni Malinen <j@w1.fi>
4e5b75505Sopenharmony_ci *
5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
6e5b75505Sopenharmony_ci * See README for more details.
7e5b75505Sopenharmony_ci */
8e5b75505Sopenharmony_ci
9e5b75505Sopenharmony_ci#include "includes.h"
10e5b75505Sopenharmony_ci
11e5b75505Sopenharmony_ci#include "common.h"
12e5b75505Sopenharmony_ci#include "sha384.h"
13e5b75505Sopenharmony_ci
14e5b75505Sopenharmony_ci
15e5b75505Sopenharmony_ci/**
16e5b75505Sopenharmony_ci * tls_prf_sha384 - Pseudo-Random Function for TLS v1.2 (P_SHA384, RFC 5246)
17e5b75505Sopenharmony_ci * @secret: Key for PRF
18e5b75505Sopenharmony_ci * @secret_len: Length of the key in bytes
19e5b75505Sopenharmony_ci * @label: A unique label for each purpose of the PRF
20e5b75505Sopenharmony_ci * @seed: Seed value to bind into the key
21e5b75505Sopenharmony_ci * @seed_len: Length of the seed
22e5b75505Sopenharmony_ci * @out: Buffer for the generated pseudo-random key
23e5b75505Sopenharmony_ci * @outlen: Number of bytes of key to generate
24e5b75505Sopenharmony_ci * Returns: 0 on success, -1 on failure.
25e5b75505Sopenharmony_ci *
26e5b75505Sopenharmony_ci * This function is used to derive new, cryptographically separate keys from a
27e5b75505Sopenharmony_ci * given key in TLS. This PRF is defined in RFC 5246, Chapter 5.
28e5b75505Sopenharmony_ci */
29e5b75505Sopenharmony_ciint tls_prf_sha384(const u8 *secret, size_t secret_len, const char *label,
30e5b75505Sopenharmony_ci		   const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
31e5b75505Sopenharmony_ci{
32e5b75505Sopenharmony_ci	size_t clen;
33e5b75505Sopenharmony_ci	u8 A[SHA384_MAC_LEN];
34e5b75505Sopenharmony_ci	u8 P[SHA384_MAC_LEN];
35e5b75505Sopenharmony_ci	size_t pos;
36e5b75505Sopenharmony_ci	const unsigned char *addr[3];
37e5b75505Sopenharmony_ci	size_t len[3];
38e5b75505Sopenharmony_ci
39e5b75505Sopenharmony_ci	addr[0] = A;
40e5b75505Sopenharmony_ci	len[0] = SHA384_MAC_LEN;
41e5b75505Sopenharmony_ci	addr[1] = (unsigned char *) label;
42e5b75505Sopenharmony_ci	len[1] = os_strlen(label);
43e5b75505Sopenharmony_ci	addr[2] = seed;
44e5b75505Sopenharmony_ci	len[2] = seed_len;
45e5b75505Sopenharmony_ci
46e5b75505Sopenharmony_ci	/*
47e5b75505Sopenharmony_ci	 * RFC 5246, Chapter 5
48e5b75505Sopenharmony_ci	 * A(0) = seed, A(i) = HMAC(secret, A(i-1))
49e5b75505Sopenharmony_ci	 * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + ..
50e5b75505Sopenharmony_ci	 * PRF(secret, label, seed) = P_SHA384(secret, label + seed)
51e5b75505Sopenharmony_ci	 */
52e5b75505Sopenharmony_ci
53e5b75505Sopenharmony_ci	if (hmac_sha384_vector(secret, secret_len, 2, &addr[1], &len[1], A) < 0)
54e5b75505Sopenharmony_ci		return -1;
55e5b75505Sopenharmony_ci
56e5b75505Sopenharmony_ci	pos = 0;
57e5b75505Sopenharmony_ci	while (pos < outlen) {
58e5b75505Sopenharmony_ci		if (hmac_sha384_vector(secret, secret_len, 3, addr, len, P) <
59e5b75505Sopenharmony_ci		    0 ||
60e5b75505Sopenharmony_ci		    hmac_sha384(secret, secret_len, A, SHA384_MAC_LEN, A) < 0)
61e5b75505Sopenharmony_ci			return -1;
62e5b75505Sopenharmony_ci
63e5b75505Sopenharmony_ci		clen = outlen - pos;
64e5b75505Sopenharmony_ci		if (clen > SHA384_MAC_LEN)
65e5b75505Sopenharmony_ci			clen = SHA384_MAC_LEN;
66e5b75505Sopenharmony_ci		os_memcpy(out + pos, P, clen);
67e5b75505Sopenharmony_ci		pos += clen;
68e5b75505Sopenharmony_ci	}
69e5b75505Sopenharmony_ci
70e5b75505Sopenharmony_ci	return 0;
71e5b75505Sopenharmony_ci}
72