11f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/*
21f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * TLS PRF P_SHA256
31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2011, Jouni Malinen <j@w1.fi>
41f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
71f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */
81f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
91f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "includes.h"
101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common.h"
121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "sha256.h"
131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/**
161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * tls_prf_sha256 - Pseudo-Random Function for TLS v1.2 (P_SHA256, RFC 5246)
171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @secret: Key for PRF
181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @secret_len: Length of the key in bytes
191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @label: A unique label for each purpose of the PRF
201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @seed: Seed value to bind into the key
211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @seed_len: Length of the seed
221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @out: Buffer for the generated pseudo-random key
231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @outlen: Number of bytes of key to generate
241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Returns: 0 on success, -1 on failure.
251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *
261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This function is used to derive new, cryptographically separate keys from a
271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * given key in TLS. This PRF is defined in RFC 2246, Chapter 5.
281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */
291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid tls_prf_sha256(const u8 *secret, size_t secret_len, const char *label,
301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t clen;
331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 A[SHA256_MAC_LEN];
341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 P[SHA256_MAC_LEN];
351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t pos;
361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	const unsigned char *addr[3];
371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t len[3];
381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	addr[0] = A;
401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	len[0] = SHA256_MAC_LEN;
411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	addr[1] = (unsigned char *) label;
421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	len[1] = os_strlen(label);
431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	addr[2] = seed;
441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	len[2] = seed_len;
451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/*
471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 * RFC 5246, Chapter 5
481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 * A(0) = seed, A(i) = HMAC(secret, A(i-1))
491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + ..
501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 * PRF(secret, label, seed) = P_SHA256(secret, label + seed)
511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 */
521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	hmac_sha256_vector(secret, secret_len, 2, &addr[1], &len[1], A);
541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	pos = 0;
561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	while (pos < outlen) {
571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		hmac_sha256_vector(secret, secret_len, 3, addr, len, P);
581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		hmac_sha256(secret, secret_len, A, SHA256_MAC_LEN, A);
591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		clen = outlen - pos;
611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (clen > SHA256_MAC_LEN)
621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			clen = SHA256_MAC_LEN;
631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		os_memcpy(out + pos, P, clen);
641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		pos += clen;
651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
67