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