X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=blobdiff_plain;f=libeap%2Fsrc%2Fcrypto%2Fsha256-kdf.c;fp=libeap%2Fsrc%2Fcrypto%2Fsha256-kdf.c;h=e7509ce41aba4dd13601b42fc6a62936281a0bfc;hp=0000000000000000000000000000000000000000;hb=f3746d009c6d7f50025af1f58a85e5fee9680be6;hpb=244f18d04aaf29e68495b5ffeb40ef5cca50942f diff --git a/libeap/src/crypto/sha256-kdf.c b/libeap/src/crypto/sha256-kdf.c new file mode 100644 index 0000000..e7509ce --- /dev/null +++ b/libeap/src/crypto/sha256-kdf.c @@ -0,0 +1,79 @@ +/* + * HMAC-SHA256 KDF (RFC 5295) + * Copyright (c) 2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "sha256.h" + + +/** + * hmac_sha256_kdf - HMAC-SHA256 based KDF (RFC 5295) + * @secret: Key for KDF + * @secret_len: Length of the key in bytes + * @label: A unique label for each purpose of the KDF + * @seed: Seed value to bind into the key + * @seed_len: Length of the seed + * @out: Buffer for the generated pseudo-random key + * @outlen: Number of bytes of key to generate + * Returns: 0 on success, -1 on failure. + * + * This function is used to derive new, cryptographically separate keys from a + * given key in ERP. This KDF is defined in RFC 5295, Chapter 3.1.2. + */ +int hmac_sha256_kdf(const u8 *secret, size_t secret_len, + const char *label, const u8 *seed, size_t seed_len, + u8 *out, size_t outlen) +{ + u8 T[SHA256_MAC_LEN]; + u8 iter = 1; + const unsigned char *addr[4]; + size_t len[4]; + size_t pos, clen; + + addr[0] = T; + len[0] = SHA256_MAC_LEN; + addr[1] = (const unsigned char *) label; + len[1] = os_strlen(label) + 1; + addr[2] = seed; + len[2] = seed_len; + addr[3] = &iter; + len[3] = 1; + + if (hmac_sha256_vector(secret, secret_len, 3, &addr[1], &len[1], T) < 0) + return -1; + + pos = 0; + for (;;) { + clen = outlen - pos; + if (clen > SHA256_MAC_LEN) + clen = SHA256_MAC_LEN; + os_memcpy(out + pos, T, clen); + pos += clen; + + if (pos == outlen) + break; + + if (iter == 255) { + os_memset(out, 0, outlen); + os_memset(T, 0, SHA256_MAC_LEN); + return -1; + } + iter++; + + if (hmac_sha256_vector(secret, secret_len, 4, addr, len, T) < 0) + { + os_memset(out, 0, outlen); + os_memset(T, 0, SHA256_MAC_LEN); + return -1; + } + } + + os_memset(T, 0, SHA256_MAC_LEN); + return 0; +}