protocol_key.c protocol_subnet.c route.c subnet.c tincd.c
nodist_tincd_SOURCES = \
- device.c cipher.c crypto.c ecdh.c digest.c rsa.c
+ device.c cipher.c crypto.c ecdh.c digest.c prf.c rsa.c
tincctl_SOURCES = \
utils.c getopt.c getopt1.c dropin.c \
noinst_HEADERS = \
xalloc.h utils.h getopt.h list.h splay_tree.h dropin.h fake-getaddrinfo.h fake-getnameinfo.h fake-gai-errnos.h ipv6.h ipv4.h ethernet.h \
- buffer.h cipher.h conf.h connection.h control.h control_common.h crypto.h device.h ecdh.h digest.h edge.h graph.h logger.h meta.h net.h netutl.h node.h process.h \
+ buffer.h cipher.h conf.h connection.h control.h control_common.h crypto.h device.h ecdh.h digest.h edge.h graph.h logger.h meta.h net.h netutl.h node.h prf.h process.h \
protocol.h route.h rsa.h rsagen.h subnet.h tincctl.h top.h bsd/tunemu.h
LIBS = @LIBS@ @LIBGCRYPT_LIBS@
--- /dev/null
+/*
+ prf.c -- Pseudo-Random Function for key material generation
+ Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "system.h"
+
+#include "digest.h"
+#include "prf.h"
+
+/* Generate key material from a master secret and a seed, based on RFC 2246.
+ We use SHA512 and Whirlpool instead of MD5 and SHA1.
+ */
+
+static bool prf_xor(int nid, char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, ssize_t outlen) {
+ digest_t digest;
+
+ if(!digest_open_by_nid(&digest, nid, 0))
+ return false;
+
+ if(!digest_set_key(&digest, secret, secretlen))
+ return false;
+
+ size_t len = digest_length(&digest);
+
+ /* Data is what the "inner" HMAC function processes.
+ It consists of the previous HMAC result plus the seed.
+ */
+
+ char data[len + seedlen];
+ memset(data, 0, len);
+ memcpy(data + len, seed, seedlen);
+
+ char hash[len];
+
+ while(outlen > 0) {
+ /* Inner HMAC */
+ digest_create(&digest, data, len + seedlen, data);
+
+ /* Outer HMAC */
+ digest_create(&digest, data, len + seedlen, hash);
+
+ /* XOR the results of the outer HMAC into the out buffer */
+ for(int i = 0; i < len && i < outlen; i++)
+ *out++ ^= hash[i];
+
+ outlen -= len;
+ }
+
+ digest_close(&digest);
+ return true;
+}
+
+bool prf(char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) {
+ /* Split secret in half, generate outlen bits with two different hash algorithms,
+ and XOR the results. */
+
+ memset(out, 0, outlen);
+
+ return prf_xor(NID_sha512, secret, secretlen / 2, seed, seedlen, out, outlen)
+ && prf_xor(NID_whirlpool, secret, secretlen / 2, seed, seedlen, out, outlen);
+}
--- /dev/null
+/*
+ prf.h -- header file for prf.c
+ Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef __TINC_PRF_H__
+#define __TINC_PRF_H__
+
+extern bool prf(char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen);
+
+#endif