sha512-kdf.c revision 341618
11556Srgrimes/* 21556Srgrimes * HMAC-SHA512 KDF (RFC 5295) and HKDF-Expand(SHA512) (RFC 5869) 31556Srgrimes * Copyright (c) 2014-2017, Jouni Malinen <j@w1.fi> 41556Srgrimes * 51556Srgrimes * This software may be distributed under the terms of the BSD license. 61556Srgrimes * See README for more details. 71556Srgrimes */ 81556Srgrimes 91556Srgrimes#include "includes.h" 101556Srgrimes 111556Srgrimes#include "common.h" 121556Srgrimes#include "sha512.h" 131556Srgrimes 141556Srgrimes 151556Srgrimes/** 161556Srgrimes * hmac_sha512_kdf - HMAC-SHA512 based KDF (RFC 5295) 171556Srgrimes * @secret: Key for KDF 181556Srgrimes * @secret_len: Length of the key in bytes 191556Srgrimes * @label: A unique label for each purpose of the KDF or %NULL to select 201556Srgrimes * RFC 5869 HKDF-Expand() with arbitrary seed (= info) 211556Srgrimes * @seed: Seed value to bind into the key 221556Srgrimes * @seed_len: Length of the seed 231556Srgrimes * @out: Buffer for the generated pseudo-random key 241556Srgrimes * @outlen: Number of bytes of key to generate 251556Srgrimes * Returns: 0 on success, -1 on failure. 261556Srgrimes * 271556Srgrimes * This function is used to derive new, cryptographically separate keys from a 281556Srgrimes * given key in ERP. This KDF is defined in RFC 5295, Chapter 3.1.2. When used 291556Srgrimes * with label = NULL and seed = info, this matches HKDF-Expand() defined in 301556Srgrimes * RFC 5869, Chapter 2.3. 311556Srgrimes */ 321556Srgrimesint hmac_sha512_kdf(const u8 *secret, size_t secret_len, 331556Srgrimes const char *label, const u8 *seed, size_t seed_len, 341556Srgrimes u8 *out, size_t outlen) 351556Srgrimes{ 361556Srgrimes u8 T[SHA512_MAC_LEN]; 371556Srgrimes u8 iter = 1; 3836150Scharnier const unsigned char *addr[4]; 3936150Scharnier size_t len[4]; 4036150Scharnier size_t pos, clen; 4136150Scharnier 4245916Scracauer addr[0] = T; 431556Srgrimes len[0] = SHA512_MAC_LEN; 441556Srgrimes if (label) { 4517987Speter addr[1] = (const unsigned char *) label; 4617987Speter len[1] = os_strlen(label) + 1; 4717987Speter } else { 4817987Speter addr[1] = (const u8 *) ""; 4917987Speter len[1] = 0; 5017987Speter } 5117987Speter addr[2] = seed; 5217987Speter len[2] = seed_len; 5319281Sache addr[3] = &iter; 5438887Stegge len[3] = 1; 5517987Speter 561556Srgrimes if (hmac_sha512_vector(secret, secret_len, 3, &addr[1], &len[1], T) < 0) 571556Srgrimes return -1; 581556Srgrimes 591556Srgrimes pos = 0; 601556Srgrimes for (;;) { 611556Srgrimes clen = outlen - pos; 621556Srgrimes if (clen > SHA512_MAC_LEN) 631556Srgrimes clen = SHA512_MAC_LEN; 641556Srgrimes os_memcpy(out + pos, T, clen); 651556Srgrimes pos += clen; 661556Srgrimes 671556Srgrimes if (pos == outlen) 681556Srgrimes break; 691556Srgrimes 701556Srgrimes if (iter == 255) { 711556Srgrimes os_memset(out, 0, outlen); 721556Srgrimes os_memset(T, 0, SHA512_MAC_LEN); 731556Srgrimes return -1; 741556Srgrimes } 751556Srgrimes iter++; 7617987Speter 7717987Speter if (hmac_sha512_vector(secret, secret_len, 4, addr, len, T) < 0) 781556Srgrimes { 791556Srgrimes os_memset(out, 0, outlen); 801556Srgrimes os_memset(T, 0, SHA512_MAC_LEN); 811556Srgrimes return -1; 821556Srgrimes } 831556Srgrimes } 841556Srgrimes 851556Srgrimes os_memset(T, 0, SHA512_MAC_LEN); 861556Srgrimes return 0; 871556Srgrimes} 881556Srgrimes