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