1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * HMAC-SHA384 KDF (RFC 5295) and HKDF-Expand(SHA384) (RFC 5869) 3e5b75505Sopenharmony_ci * Copyright (c) 2014-2017, 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 * hmac_sha384_kdf - HMAC-SHA384 based KDF (RFC 5295) 17e5b75505Sopenharmony_ci * @secret: Key for KDF 18e5b75505Sopenharmony_ci * @secret_len: Length of the key in bytes 19e5b75505Sopenharmony_ci * @label: A unique label for each purpose of the KDF or %NULL to select 20e5b75505Sopenharmony_ci * RFC 5869 HKDF-Expand() with arbitrary seed (= info) 21e5b75505Sopenharmony_ci * @seed: Seed value to bind into the key 22e5b75505Sopenharmony_ci * @seed_len: Length of the seed 23e5b75505Sopenharmony_ci * @out: Buffer for the generated pseudo-random key 24e5b75505Sopenharmony_ci * @outlen: Number of bytes of key to generate 25e5b75505Sopenharmony_ci * Returns: 0 on success, -1 on failure. 26e5b75505Sopenharmony_ci * 27e5b75505Sopenharmony_ci * This function is used to derive new, cryptographically separate keys from a 28e5b75505Sopenharmony_ci * given key in ERP. This KDF is defined in RFC 5295, Chapter 3.1.2. When used 29e5b75505Sopenharmony_ci * with label = NULL and seed = info, this matches HKDF-Expand() defined in 30e5b75505Sopenharmony_ci * RFC 5869, Chapter 2.3. 31e5b75505Sopenharmony_ci */ 32e5b75505Sopenharmony_ciint hmac_sha384_kdf(const u8 *secret, size_t secret_len, 33e5b75505Sopenharmony_ci const char *label, const u8 *seed, size_t seed_len, 34e5b75505Sopenharmony_ci u8 *out, size_t outlen) 35e5b75505Sopenharmony_ci{ 36e5b75505Sopenharmony_ci u8 T[SHA384_MAC_LEN]; 37e5b75505Sopenharmony_ci u8 iter = 1; 38e5b75505Sopenharmony_ci const unsigned char *addr[4]; 39e5b75505Sopenharmony_ci size_t len[4]; 40e5b75505Sopenharmony_ci size_t pos, clen; 41e5b75505Sopenharmony_ci 42e5b75505Sopenharmony_ci addr[0] = T; 43e5b75505Sopenharmony_ci len[0] = SHA384_MAC_LEN; 44e5b75505Sopenharmony_ci if (label) { 45e5b75505Sopenharmony_ci addr[1] = (const unsigned char *) label; 46e5b75505Sopenharmony_ci len[1] = os_strlen(label) + 1; 47e5b75505Sopenharmony_ci } else { 48e5b75505Sopenharmony_ci addr[1] = (const u8 *) ""; 49e5b75505Sopenharmony_ci len[1] = 0; 50e5b75505Sopenharmony_ci } 51e5b75505Sopenharmony_ci addr[2] = seed; 52e5b75505Sopenharmony_ci len[2] = seed_len; 53e5b75505Sopenharmony_ci addr[3] = &iter; 54e5b75505Sopenharmony_ci len[3] = 1; 55e5b75505Sopenharmony_ci 56e5b75505Sopenharmony_ci if (hmac_sha384_vector(secret, secret_len, 3, &addr[1], &len[1], T) < 0) 57e5b75505Sopenharmony_ci return -1; 58e5b75505Sopenharmony_ci 59e5b75505Sopenharmony_ci pos = 0; 60e5b75505Sopenharmony_ci for (;;) { 61e5b75505Sopenharmony_ci clen = outlen - pos; 62e5b75505Sopenharmony_ci if (clen > SHA384_MAC_LEN) 63e5b75505Sopenharmony_ci clen = SHA384_MAC_LEN; 64e5b75505Sopenharmony_ci os_memcpy(out + pos, T, clen); 65e5b75505Sopenharmony_ci pos += clen; 66e5b75505Sopenharmony_ci 67e5b75505Sopenharmony_ci if (pos == outlen) 68e5b75505Sopenharmony_ci break; 69e5b75505Sopenharmony_ci 70e5b75505Sopenharmony_ci if (iter == 255) { 71e5b75505Sopenharmony_ci os_memset(out, 0, outlen); 72e5b75505Sopenharmony_ci forced_memzero(T, SHA384_MAC_LEN); 73e5b75505Sopenharmony_ci return -1; 74e5b75505Sopenharmony_ci } 75e5b75505Sopenharmony_ci iter++; 76e5b75505Sopenharmony_ci 77e5b75505Sopenharmony_ci if (hmac_sha384_vector(secret, secret_len, 4, addr, len, T) < 0) 78e5b75505Sopenharmony_ci { 79e5b75505Sopenharmony_ci os_memset(out, 0, outlen); 80e5b75505Sopenharmony_ci forced_memzero(T, SHA384_MAC_LEN); 81e5b75505Sopenharmony_ci return -1; 82e5b75505Sopenharmony_ci } 83e5b75505Sopenharmony_ci } 84e5b75505Sopenharmony_ci 85e5b75505Sopenharmony_ci forced_memzero(T, SHA384_MAC_LEN); 86e5b75505Sopenharmony_ci return 0; 87e5b75505Sopenharmony_ci} 88