1*5b9c547cSRui Paulo /* 2*5b9c547cSRui Paulo * HMAC-SHA256 KDF (RFC 5295) 3*5b9c547cSRui Paulo * Copyright (c) 2014, Jouni Malinen <j@w1.fi> 4*5b9c547cSRui Paulo * 5*5b9c547cSRui Paulo * This software may be distributed under the terms of the BSD license. 6*5b9c547cSRui Paulo * See README for more details. 7*5b9c547cSRui Paulo */ 8*5b9c547cSRui Paulo 9*5b9c547cSRui Paulo #include "includes.h" 10*5b9c547cSRui Paulo 11*5b9c547cSRui Paulo #include "common.h" 12*5b9c547cSRui Paulo #include "sha256.h" 13*5b9c547cSRui Paulo 14*5b9c547cSRui Paulo 15*5b9c547cSRui Paulo /** 16*5b9c547cSRui Paulo * hmac_sha256_kdf - HMAC-SHA256 based KDF (RFC 5295) 17*5b9c547cSRui Paulo * @secret: Key for KDF 18*5b9c547cSRui Paulo * @secret_len: Length of the key in bytes 19*5b9c547cSRui Paulo * @label: A unique label for each purpose of the KDF 20*5b9c547cSRui Paulo * @seed: Seed value to bind into the key 21*5b9c547cSRui Paulo * @seed_len: Length of the seed 22*5b9c547cSRui Paulo * @out: Buffer for the generated pseudo-random key 23*5b9c547cSRui Paulo * @outlen: Number of bytes of key to generate 24*5b9c547cSRui Paulo * Returns: 0 on success, -1 on failure. 25*5b9c547cSRui Paulo * 26*5b9c547cSRui Paulo * This function is used to derive new, cryptographically separate keys from a 27*5b9c547cSRui Paulo * given key in ERP. This KDF is defined in RFC 5295, Chapter 3.1.2. 28*5b9c547cSRui Paulo */ 29*5b9c547cSRui Paulo int hmac_sha256_kdf(const u8 *secret, size_t secret_len, 30*5b9c547cSRui Paulo const char *label, const u8 *seed, size_t seed_len, 31*5b9c547cSRui Paulo u8 *out, size_t outlen) 32*5b9c547cSRui Paulo { 33*5b9c547cSRui Paulo u8 T[SHA256_MAC_LEN]; 34*5b9c547cSRui Paulo u8 iter = 1; 35*5b9c547cSRui Paulo const unsigned char *addr[4]; 36*5b9c547cSRui Paulo size_t len[4]; 37*5b9c547cSRui Paulo size_t pos, clen; 38*5b9c547cSRui Paulo 39*5b9c547cSRui Paulo addr[0] = T; 40*5b9c547cSRui Paulo len[0] = SHA256_MAC_LEN; 41*5b9c547cSRui Paulo addr[1] = (const unsigned char *) label; 42*5b9c547cSRui Paulo len[1] = os_strlen(label) + 1; 43*5b9c547cSRui Paulo addr[2] = seed; 44*5b9c547cSRui Paulo len[2] = seed_len; 45*5b9c547cSRui Paulo addr[3] = &iter; 46*5b9c547cSRui Paulo len[3] = 1; 47*5b9c547cSRui Paulo 48*5b9c547cSRui Paulo if (hmac_sha256_vector(secret, secret_len, 3, &addr[1], &len[1], T) < 0) 49*5b9c547cSRui Paulo return -1; 50*5b9c547cSRui Paulo 51*5b9c547cSRui Paulo pos = 0; 52*5b9c547cSRui Paulo for (;;) { 53*5b9c547cSRui Paulo clen = outlen - pos; 54*5b9c547cSRui Paulo if (clen > SHA256_MAC_LEN) 55*5b9c547cSRui Paulo clen = SHA256_MAC_LEN; 56*5b9c547cSRui Paulo os_memcpy(out + pos, T, clen); 57*5b9c547cSRui Paulo pos += clen; 58*5b9c547cSRui Paulo 59*5b9c547cSRui Paulo if (pos == outlen) 60*5b9c547cSRui Paulo break; 61*5b9c547cSRui Paulo 62*5b9c547cSRui Paulo if (iter == 255) { 63*5b9c547cSRui Paulo os_memset(out, 0, outlen); 64*5b9c547cSRui Paulo return -1; 65*5b9c547cSRui Paulo } 66*5b9c547cSRui Paulo iter++; 67*5b9c547cSRui Paulo 68*5b9c547cSRui Paulo if (hmac_sha256_vector(secret, secret_len, 4, addr, len, T) < 0) 69*5b9c547cSRui Paulo { 70*5b9c547cSRui Paulo os_memset(out, 0, outlen); 71*5b9c547cSRui Paulo return -1; 72*5b9c547cSRui Paulo } 73*5b9c547cSRui Paulo } 74*5b9c547cSRui Paulo 75*5b9c547cSRui Paulo return 0; 76*5b9c547cSRui Paulo } 77