sha1-prf.c revision 61d9df3e62aaa0e87ad05452fcb95142159a17b6
161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt/*
261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * SHA1-based PRF
361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *
561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * See README for more details.
761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */
861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "includes.h"
1061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "common.h"
1261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "sha1.h"
1361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "crypto.h"
1461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt/**
1761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1)
1861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @key: Key for PRF
1961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @key_len: Length of the key in bytes
2061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @label: A unique label for each purpose of the PRF
2161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @data: Extra data to bind into the key
2261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @data_len: Length of the data
2361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @buf: Buffer for the generated pseudo-random key
2461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @buf_len: Number of bytes of key to generate
2561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Returns: 0 on success, -1 of failure
2661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *
2761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * This function is used to derive new, cryptographically separate keys from a
2861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * given key (e.g., PMK in IEEE 802.11i).
2961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */
3061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint sha1_prf(const u8 *key, size_t key_len, const char *label,
3161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	     const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
3261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
3361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 counter = 0;
3461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t pos, plen;
3561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 hash[SHA1_MAC_LEN];
3661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t label_len = os_strlen(label) + 1;
3761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const unsigned char *addr[3];
3861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t len[3];
3961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
4061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	addr[0] = (u8 *) label;
4161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len[0] = label_len;
4261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	addr[1] = data;
4361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len[1] = data_len;
4461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	addr[2] = &counter;
4561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len[2] = 1;
4661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
4761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = 0;
4861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	while (pos < buf_len) {
4961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		plen = buf_len - pos;
5061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (plen >= SHA1_MAC_LEN) {
5161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (hmac_sha1_vector(key, key_len, 3, addr, len,
5261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					     &buf[pos]))
5361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				return -1;
5461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			pos += SHA1_MAC_LEN;
5561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		} else {
5661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (hmac_sha1_vector(key, key_len, 3, addr, len,
5761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					     hash))
5861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				return -1;
5961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			os_memcpy(&buf[pos], hash, plen);
6061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
6161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
6261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		counter++;
6361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
6461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
6661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
67