+++ /dev/null
-The following applies to MeshLink:
-
-This program is released under the GPL with the additional exemption that
-compiling, linking, and/or using OpenSSL is allowed. You may provide binary
-packages linked to the OpenSSL libraries, provided that all other requirements
-of the GPL are met.
Requirements
------------
-In order to compile MeshLink, you will need a GNU C compiler environment. Please
-ensure you have the latest stable versions of all the required libraries:
-
-- OpenSSL (http://www.openssl.org/) version 1.0.0 or later, with support for
- elliptic curve cryptography (ECC) and Galois counter mode (GCM) enabled.
+In order to compile MeshLink, you will need a GNU C compiler environment.
The following libraries are used by default, but can be disabled if necessary:
- IPv6 support
- NAT traversal (requires at least one node that is not behind a NAT)
- Ed25519 keys (TBD)
-- AES-256-GCM encryption and message authentication
+- ChaCha-Poly1305 encryption and message authentication
tar xfj android-ndk-r8b-linux-x86.tar.bz2
./android-ndk-r8b/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain
-- Download and cross-compile openSSL for ARM:
-wget http://www.openssl.org/source/openssl-1.0.1c.tar.gz
-tar xfz openssl-1.0.1c.tar.gz
-cd openssl-1.0.1c
-./Configure dist
-make CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc AR="/tmp/my-android-toolchain/bin/arm-linux-androideabi-ar r" RANLIB=/tmp/my-android-toolchain/bin/arm-linux-androideabi-ranlib
-
- Clone and cross-compile MeshLink:
git clone git://meshlink.io/meshlink
cd meshlink
autoreconf -fsi
-CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc ./configure --host=arm-linux --disable-lzo --with-openssl-lib=$HOME/android/openssl-1.0.1c --with-openssl-include=$HOME/android/openssl-1.0.1c/include/
+CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc ./configure --host=arm-linux
make -j5
Before you can start compiling MeshLink from a fresh git clone, you have
to install the very latest versions of the following packages:
-- OpenSSL
- zlib
- GCC
- automake
MeshLink_ZLIB
-MeshLink_OPENSSL
-
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile m4/Makefile test/Makefile])
AC_OUTPUT
+++ /dev/null
-dnl Check to find the OpenSSL headers/libraries
-
-AC_DEFUN([MeshLink_OPENSSL],
-[
- case $host_os in
- *mingw*)
- ;;
- *)
- AC_CHECK_FUNC(dlopen,
- [],
- [AC_CHECK_LIB(dl, dlopen,
- [LIBS="$LIBS -ldl"],
- [AC_MSG_ERROR([OpenSSL depends on libdl.]); break]
- )]
- )
- ;;
- esac
-
- AC_ARG_WITH(openssl,
- AS_HELP_STRING([--with-openssl=DIR], [OpenSSL base directory, or:]),
- [openssl="$withval"
- CPPFLAGS="$CPPFLAGS -I$withval/include"
- LDFLAGS="$LDFLAGS -L$withval/lib"]
- )
-
- AC_ARG_WITH(openssl-include,
- AS_HELP_STRING([--with-openssl-include=DIR], [OpenSSL headers directory (without trailing /openssl)]),
- [openssl_include="$withval"
- CPPFLAGS="$CPPFLAGS -I$withval"]
- )
-
- AC_ARG_WITH(openssl-lib,
- AS_HELP_STRING([--with-openssl-lib=DIR], [OpenSSL library directory]),
- [openssl_lib="$withval"
- LDFLAGS="$LDFLAGS -L$withval"]
- )
-
- AC_CHECK_HEADERS([openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h openssl/engine.h openssl/ecdh.h openssl/ec.h],
- [],
- [AC_MSG_ERROR([OpenSSL header files not found.]); break]
- )
-
- AC_CHECK_LIB(crypto, EVP_EncryptInit_ex,
- [LIBS="-lcrypto $LIBS"],
- [AC_MSG_ERROR([OpenSSL libraries not found.])]
- )
-
- AC_CHECK_FUNCS([RAND_pseudo_bytes EVP_EncryptInit_ex ECDH_compute_key ECDSA_verify], ,
- [AC_MSG_ERROR([Missing OpenSSL functionality, make sure you have installed the latest version.]); break],
- )
-
- AC_CHECK_DECLS([OpenSSL_add_all_algorithms, EVP_CTRL_GCM_GET_TAG], ,
- [AC_MSG_ERROR([Missing OpenSSL functionality, make sure you have installed the latest version.]); break],
- [#include <openssl/evp.h>]
- )
-])
chacha-poly1305/poly1305.c chacha-poly1305/poly1305.h
sptps_test_SOURCES = \
+ crypto.c crypto.h \
logger.c logger.h \
prf.c prf.h \
sptps.c sptps.h \
$(chacha_poly1305_SOURCES)
sptps_keypair_SOURCES = \
+ crypto.c crypto.h \
sptps_keypair.c \
utils.c utils.h \
$(ed25519_SOURCES)
sptps_speed_SOURCES = \
+ crypto.c crypto.h \
logger.c logger.h \
prf.c prf.h \
sptps.c sptps.h \
cipher.h \
conf.c conf.h \
connection.c connection.h \
- crypto.h \
+ crypto.c crypto.h \
dropin.c dropin.h \
ecdh.h \
ecdsa.h \
libmeshlink_la_LIBADD = -lpthread
libmeshlink_la_SOURCES += \
- openssl/crypto.c \
ed25519/ecdh.c \
ed25519/ecdsa.c \
ed25519/ecdsagen.c
sptps_test_SOURCES += \
- openssl/crypto.c \
ed25519/ecdh.c \
ed25519/ecdsa.c
sptps_keypair_SOURCES += \
- openssl/crypto.c \
ed25519/ecdsagen.c
sptps_speed_SOURCES += \
- openssl/crypto.c \
ed25519/ecdh.c \
ed25519/ecdsa.c \
ed25519/ecdsagen.c
+++ /dev/null
-/*
- cipher.c -- Symmetric block cipher handling
- Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
-
- 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 <openssl/rand.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-
-#include "../cipher.h"
-#include "../logger.h"
-#include "../xalloc.h"
-
-struct cipher {
- EVP_CIPHER_CTX ctx;
- const EVP_CIPHER *cipher;
- struct cipher_counter *counter;
-};
-
-typedef struct cipher_counter {
- unsigned char counter[CIPHER_MAX_IV_SIZE];
- unsigned char block[CIPHER_MAX_IV_SIZE];
- int n;
-} cipher_counter_t;
-
-static cipher_t *cipher_open(const EVP_CIPHER *evp_cipher) {
- cipher_t *cipher = xzalloc(sizeof *cipher);
- cipher->cipher = evp_cipher;
- EVP_CIPHER_CTX_init(&cipher->ctx);
-
- return cipher;
-}
-
-cipher_t *cipher_open_by_name(const char *name) {
- const EVP_CIPHER *evp_cipher = EVP_get_cipherbyname(name);
- if(!evp_cipher) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher name '%s'!", name);
- return NULL;
- }
-
- return cipher_open(evp_cipher);
-}
-
-cipher_t *cipher_open_by_nid(int nid) {
- const EVP_CIPHER *evp_cipher = EVP_get_cipherbynid(nid);
- if(!evp_cipher) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher nid %d!", nid);
- return NULL;
- }
-
- return cipher_open(evp_cipher);
-}
-
-cipher_t *cipher_open_blowfish_ofb(void) {
- return cipher_open(EVP_bf_ofb());
-}
-
-void cipher_close(cipher_t *cipher) {
- if(!cipher)
- return;
-
- EVP_CIPHER_CTX_cleanup(&cipher->ctx);
- free(cipher->counter);
- free(cipher);
-}
-
-size_t cipher_keylength(const cipher_t *cipher) {
- if(!cipher || !cipher->cipher)
- return 0;
-
- return cipher->cipher->key_len + cipher->cipher->iv_len;
-}
-
-bool cipher_set_key(cipher_t *cipher, void *key, bool encrypt) {
- bool result;
-
- if(encrypt)
- result = EVP_EncryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, (unsigned char *)key + cipher->cipher->key_len);
- else
- result = EVP_DecryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, (unsigned char *)key + cipher->cipher->key_len);
-
- if(result)
- return true;
-
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while setting key: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
-}
-
-bool cipher_set_key_from_rsa(cipher_t *cipher, void *key, size_t len, bool encrypt) {
- bool result;
-
- if(encrypt)
- result = EVP_EncryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key + len - cipher->cipher->key_len, (unsigned char *)key + len - cipher->cipher->iv_len - cipher->cipher->key_len);
- else
- result = EVP_DecryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key + len - cipher->cipher->key_len, (unsigned char *)key + len - cipher->cipher->iv_len - cipher->cipher->key_len);
-
- if(result)
- return true;
-
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while setting key: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
-}
-
-bool cipher_set_counter(cipher_t *cipher, const void *counter, size_t len) {
- if(len > cipher->cipher->iv_len - 4) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Counter too long");
- return false;
- }
-
- memcpy(cipher->counter->counter, counter, len);
- cipher->counter->n = 0;
-
- return true;
-}
-
-bool cipher_set_counter_key(cipher_t *cipher, void *key) {
- int result = EVP_EncryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, NULL);
- if(!result) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while setting key: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
-
- if(!cipher->counter)
- cipher->counter = xzalloc(sizeof *cipher->counter);
- else
- cipher->counter->n = 0;
-
- memcpy(cipher->counter->counter, (unsigned char *)key + cipher->cipher->key_len, cipher->cipher->iv_len);
-
- return true;
-}
-
-bool cipher_gcm_encrypt_start(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
- int len = 0;
- if(!EVP_EncryptInit_ex(&cipher->ctx, NULL, NULL, NULL, cipher->counter->counter)
- || (inlen && !EVP_EncryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, (unsigned char *)indata, inlen))) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
- if(outlen)
- *outlen = len;
- return true;
-}
-
-bool cipher_gcm_encrypt_finish(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
- int len = 0, pad = 0;
- if((inlen && !EVP_EncryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, (unsigned char *)indata, inlen))
- || !EVP_EncryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
- EVP_CIPHER_CTX_ctrl(&cipher->ctx, EVP_CTRL_GCM_GET_TAG, 16, (unsigned char *)outdata + len + pad);
- if(outlen)
- *outlen = len + pad + 16;
- return true;
-}
-
-bool cipher_gcm_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
- int len = 0, pad = 0;
- if(!EVP_EncryptInit_ex(&cipher->ctx, NULL, NULL, NULL, cipher->counter->counter) ||
- !EVP_EncryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, (unsigned char *)indata, inlen) ||
- !EVP_EncryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
- EVP_CIPHER_CTX_ctrl(&cipher->ctx, EVP_CTRL_GCM_GET_TAG, 16, (unsigned char *)outdata + len + pad);
- if(outlen)
- *outlen = len + pad + 16;
- return true;
-}
-
-bool cipher_gcm_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
- if(inlen < 16)
- return false;
-
- int len = 0, pad = 0;
- if(!EVP_DecryptInit_ex(&cipher->ctx, NULL, NULL, NULL, cipher->counter->counter)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
-
- EVP_CIPHER_CTX_ctrl(&cipher->ctx, EVP_CTRL_GCM_SET_TAG, 16, (unsigned char *)indata + inlen - 16);
-
- if(!EVP_DecryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, (unsigned char *)indata, inlen - 16) ||
- !EVP_DecryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
- if(outlen)
- *outlen = len;
- return true;
-}
-
-bool cipher_gcm_decrypt_start(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
- int len = 0;
- if(!EVP_DecryptInit_ex(&cipher->ctx, NULL, NULL, NULL, cipher->counter->counter)
- || (inlen && !EVP_DecryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, (unsigned char *)indata, inlen))) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
- if(outlen)
- *outlen = len;
- return true;
-}
-
-bool cipher_gcm_decrypt_finish(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
- if(inlen < 16)
- return false;
-
- EVP_CIPHER_CTX_ctrl(&cipher->ctx, EVP_CTRL_GCM_SET_TAG, 16, (unsigned char *)indata + inlen - 16);
-
- int len = 0, pad = 0;
- if((inlen > 16 && !EVP_DecryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, (unsigned char *)indata, inlen - 16))
- || !EVP_DecryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
- return true;
-}
-
-
-bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) {
- if(oneshot) {
- int len, pad;
- if(EVP_EncryptInit_ex(&cipher->ctx, NULL, NULL, NULL, NULL)
- && EVP_EncryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, indata, inlen)
- && EVP_EncryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) {
- if(outlen) *outlen = len + pad;
- return true;
- }
- } else {
- int len;
- if(EVP_EncryptUpdate(&cipher->ctx, outdata, &len, indata, inlen)) {
- if(outlen) *outlen = len;
- return true;
- }
- }
-
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
-}
-
-bool cipher_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) {
- if(oneshot) {
- int len, pad;
- if(EVP_DecryptInit_ex(&cipher->ctx, NULL, NULL, NULL, NULL)
- && EVP_DecryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, indata, inlen)
- && EVP_DecryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) {
- if(outlen) *outlen = len + pad;
- return true;
- }
- } else {
- int len;
- if(EVP_EncryptUpdate(&cipher->ctx, outdata, &len, indata, inlen)) {
- if(outlen) *outlen = len;
- return true;
- }
- }
-
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
-}
-
-int cipher_get_nid(const cipher_t *cipher) {
- if(!cipher || !cipher->cipher)
- return 0;
-
- return cipher->cipher->nid;
-}
-
-bool cipher_active(const cipher_t *cipher) {
- return cipher && cipher->cipher && cipher->cipher->nid != 0;
-}
+++ /dev/null
-/*
- crypto.c -- Cryptographic miscellaneous functions and initialisation
- Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
-
- 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 <openssl/rand.h>
-#include <openssl/evp.h>
-#include <openssl/engine.h>
-
-#include "../crypto.h"
-
-void crypto_init(void) {
- RAND_load_file("/dev/urandom", 1024);
-
- ENGINE_load_builtin_engines();
- ENGINE_register_all_complete();
-
- ERR_load_crypto_strings();
- OpenSSL_add_all_algorithms();
-
- if(!RAND_status()) {
- fprintf(stderr, "Not enough entropy for the PRNG!\n");
- abort();
- }
-}
-
-void crypto_exit(void) {
- EVP_cleanup();
-}
-
-void randomize(void *out, size_t outlen) {
- RAND_pseudo_bytes(out, outlen);
-}
+++ /dev/null
-/*
- digest.c -- Digest handling
- Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
-
- 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 "../utils.h"
-#include "../xalloc.h"
-
-#include <openssl/err.h>
-#include <openssl/hmac.h>
-
-#include "digest.h"
-#include "../digest.h"
-#include "../logger.h"
-
-static digest_t *digest_open(const EVP_MD *evp_md, int maclength) {
- digest_t *digest = xzalloc(sizeof *digest);
- digest->digest = evp_md;
-
- int digestlen = EVP_MD_size(digest->digest);
-
- if(maclength > digestlen || maclength < 0)
- digest->maclength = digestlen;
- else
- digest->maclength = maclength;
-
- return digest;
-}
-
-digest_t *digest_open_by_name(const char *name, int maclength) {
- const EVP_MD *evp_md = EVP_get_digestbyname(name);
-
- if(!evp_md) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown digest name '%s'!", name);
- return false;
- }
-
- return digest_open(evp_md, maclength);
-}
-
-digest_t *digest_open_by_nid(int nid, int maclength) {
- const EVP_MD *evp_md = EVP_get_digestbynid(nid);
-
- if(!evp_md) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown digest nid %d!", nid);
- return false;
- }
-
- return digest_open(evp_md, maclength);
-}
-
-digest_t *digest_open_sha1(int maclength) {
- return digest_open(EVP_sha1(), maclength);
-}
-
-bool digest_set_key(digest_t *digest, const void *key, size_t len) {
- digest->key = xrealloc(digest->key, len);
- memcpy(digest->key, key, len);
- digest->keylength = len;
- return true;
-}
-
-void digest_close(digest_t *digest) {
- if(!digest)
- return;
-
- free(digest->key);
- free(digest);
-}
-
-bool digest_create(digest_t *digest, const void *indata, size_t inlen, void *outdata) {
- size_t len = EVP_MD_size(digest->digest);
- unsigned char tmpdata[len];
-
- if(digest->key) {
- if(!HMAC(digest->digest, digest->key, digest->keylength, indata, inlen, tmpdata, NULL)) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Error creating digest: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
- } else {
- EVP_MD_CTX ctx;
-
- if(!EVP_DigestInit(&ctx, digest->digest)
- || !EVP_DigestUpdate(&ctx, indata, inlen)
- || !EVP_DigestFinal(&ctx, tmpdata, NULL)) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Error creating digest: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
- }
-
- memcpy(outdata, tmpdata, digest->maclength);
- return true;
-}
-
-bool digest_verify(digest_t *digest, const void *indata, size_t inlen, const void *cmpdata) {
- size_t len = digest->maclength;
- unsigned char outdata[len];
-
- return digest_create(digest, indata, inlen, outdata) && !memcmp(cmpdata, outdata, digest->maclength);
-}
-
-int digest_get_nid(const digest_t *digest) {
- if(!digest || !digest->digest)
- return 0;
-
- return digest->digest->type;
-}
-
-size_t digest_keylength(const digest_t *digest) {
- if(!digest || !digest->digest)
- return 0;
-
- return digest->digest->md_size;
-}
-
-size_t digest_length(const digest_t *digest) {
- if(!digest)
- return 0;
-
- return digest->maclength;
-}
-
-bool digest_active(const digest_t *digest) {
- return digest && digest->digest && digest->digest->type != 0;
-}
+++ /dev/null
-/*
- digest.h -- header file digest.c
- Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
-
- 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_OPENSSL_DIGEST_H__
-#define __TINC_OPENSSL_DIGEST_H__
-
-#include <openssl/evp.h>
-
-struct digest {
- const EVP_MD *digest;
- int maclength;
- int keylength;
- char *key;
-};
-
-#endif
+++ /dev/null
-/*
- ecdh.c -- Diffie-Hellman key exchange handling
- Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
-
- 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 <openssl/err.h>
-#include <openssl/ec.h>
-#include <openssl/ecdh.h>
-#include <openssl/obj_mac.h>
-
-#define __TINC_ECDH_INTERNAL__
-typedef EC_KEY ecdh_t;
-
-#include "../ecdh.h"
-#include "../logger.h"
-#include "../utils.h"
-#include "../xalloc.h"
-
-ecdh_t *ecdh_generate_public(void *pubkey) {
- ecdh_t *ecdh = EC_KEY_new_by_curve_name(NID_secp521r1);
- if(!ecdh) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Generating EC key_by_curve_name failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
-
- if(!EC_KEY_generate_key(ecdh)) {
- EC_KEY_free(ecdh);
- logger(DEBUG_ALWAYS, LOG_ERR, "Generating EC key failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return NULL;
- }
-
- const EC_POINT *point = EC_KEY_get0_public_key(ecdh);
- if(!point) {
- EC_KEY_free(ecdh);
- logger(DEBUG_ALWAYS, LOG_ERR, "Getting public key failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return NULL;
- }
-
- size_t result = EC_POINT_point2oct(EC_KEY_get0_group(ecdh), point, POINT_CONVERSION_COMPRESSED, pubkey, ECDH_SIZE, NULL);
- if(!result) {
- EC_KEY_free(ecdh);
- logger(DEBUG_ALWAYS, LOG_ERR, "Converting EC_POINT to binary failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return NULL;
- }
-
- return ecdh;
-}
-
-bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) {
- EC_POINT *point = EC_POINT_new(EC_KEY_get0_group(ecdh));
- if(!point) {
- logger(DEBUG_ALWAYS, LOG_ERR, "EC_POINT_new() failed: %s", ERR_error_string(ERR_get_error(), NULL));
- EC_KEY_free(ecdh);
- return false;
- }
-
- int result = EC_POINT_oct2point(EC_KEY_get0_group(ecdh), point, pubkey, ECDH_SIZE, NULL);
- if(!result) {
- EC_POINT_free(point);
- EC_KEY_free(ecdh);
- logger(DEBUG_ALWAYS, LOG_ERR, "Converting binary to EC_POINT failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
-
- result = ECDH_compute_key(shared, ECDH_SIZE, point, ecdh, NULL);
- EC_POINT_free(point);
- EC_KEY_free(ecdh);
-
- if(!result) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Computing Elliptic Curve Diffie-Hellman shared key failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
-
- return true;
-}
-
-void ecdh_free(ecdh_t *ecdh) {
- if(ecdh)
- EC_KEY_free(ecdh);
-}
+++ /dev/null
-/*
- ecdsa.c -- ECDSA key handling
- Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
-
- 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 <openssl/pem.h>
-#include <openssl/err.h>
-
-#define __TINC_ECDSA_INTERNAL__
-typedef EC_KEY ecdsa_t;
-
-#include "../logger.h"
-#include "../ecdsa.h"
-#include "../utils.h"
-#include "../xalloc.h"
-
-// Get and set ECDSA keys
-//
-ecdsa_t *ecdsa_set_base64_public_key(const char *p) {
- ecdsa_t *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1);
- if(!ecdsa) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "EC_KEY_new_by_curve_name failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return NULL;
- }
-
- int len = strlen(p);
- unsigned char pubkey[len / 4 * 3 + 3];
- const unsigned char *ppubkey = pubkey;
- len = b64decode(p, (char *)pubkey, len);
-
- if(!o2i_ECPublicKey(&ecdsa, &ppubkey, len)) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "o2i_ECPublicKey failed: %s", ERR_error_string(ERR_get_error(), NULL));
- EC_KEY_free(ecdsa);
- return NULL;
- }
-
- return ecdsa;
-}
-
-char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
- unsigned char *pubkey = NULL;
- int len = i2o_ECPublicKey(ecdsa, &pubkey);
-
- char *base64 = xmalloc(len * 4 / 3 + 5);
- b64encode((char *)pubkey, base64, len);
-
- free(pubkey);
-
- return base64;
-}
-
-// Read PEM ECDSA keys
-
-ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) {
- ecdsa_t *ecdsa = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL);
-
- if(!ecdsa)
- logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA public key: %s", ERR_error_string(ERR_get_error(), NULL));
-
- return ecdsa;
-}
-
-ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) {
- ecdsa_t *ecdsa = PEM_read_ECPrivateKey(fp, NULL, NULL, NULL);
-
- if(!ecdsa)
- logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA private key: %s", ERR_error_string(ERR_get_error(), NULL));
-
- return ecdsa;
-}
-
-size_t ecdsa_size(ecdsa_t *ecdsa) {
- return ECDSA_size(ecdsa);
-}
-
-// TODO: standardise output format?
-
-bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) {
- unsigned int siglen = ECDSA_size(ecdsa);
-
- unsigned char hash[SHA512_DIGEST_LENGTH];
- SHA512(in, len, hash);
-
- memset(sig, 0, siglen);
-
- if(!ECDSA_sign(0, hash, sizeof hash, sig, &siglen, ecdsa)) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "ECDSA_sign() failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
-
- return true;
-}
-
-bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) {
- unsigned int siglen = ECDSA_size(ecdsa);
-
- unsigned char hash[SHA512_DIGEST_LENGTH];
- SHA512(in, len, hash);
-
- if(!ECDSA_verify(0, hash, sizeof hash, sig, siglen, ecdsa)) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "ECDSA_verify() failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
- }
-
- return true;
-}
-
-bool ecdsa_active(ecdsa_t *ecdsa) {
- return ecdsa;
-}
-
-void ecdsa_free(ecdsa_t *ecdsa) {
- if(ecdsa)
- EC_KEY_free(ecdsa);
-}
+++ /dev/null
-/*
- ecdsagen.c -- ECDSA key generation and export
- Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
-
- 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 <openssl/pem.h>
-#include <openssl/err.h>
-#include <openssl/obj_mac.h>
-
-#define __TINC_ECDSA_INTERNAL__
-typedef EC_KEY ecdsa_t;
-
-#include "../ecdsagen.h"
-#include "../utils.h"
-#include "../xalloc.h"
-
-// Generate ECDSA key
-
-ecdsa_t *ecdsa_generate(void) {
- ecdsa_t *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1);
-
- if(!ecdsa || !EC_KEY_generate_key(ecdsa)) {
- fprintf(stderr, "Generating EC key failed: %s", ERR_error_string(ERR_get_error(), NULL));
- ecdsa_free(ecdsa);
- return false;
- }
-
- EC_KEY_set_asn1_flag(ecdsa, OPENSSL_EC_NAMED_CURVE);
- EC_KEY_set_conv_form(ecdsa, POINT_CONVERSION_COMPRESSED);
-
- return ecdsa;
-}
-
-// Write PEM ECDSA keys
-
-bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) {
- return PEM_write_EC_PUBKEY(fp, ecdsa);
-}
-
-bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) {
- return PEM_write_ECPrivateKey(fp, ecdsa, NULL, NULL, 0, NULL, NULL);
-}
+++ /dev/null
-/*
- prf.c -- Pseudo-Random Function for key material generation
- Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
-
- 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 <openssl/obj_mac.h>
-
-#include "digest.h"
-#include "../digest.h"
-#include "../prf.h"
-
-/* Generate key material from a master secret and a seed, based on RFC 4346 section 5.
- We use SHA512 instead of MD5 and SHA1.
- */
-
-static bool prf_xor(int nid, const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, ssize_t outlen) {
- digest_t *digest = digest_open_by_nid(nid, -1);
-
- if(!digest)
- return false;
-
- if(!digest_set_key(digest, secret, secretlen)) {
- digest_close(digest);
- 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 */
- if(!digest_create(digest, data, len + seedlen, data)) {
- digest_close(digest);
- return false;
- }
-
- /* Outer HMAC */
- if(!digest_create(digest, data, len + seedlen, hash)) {
- digest_close(digest);
- return false;
- }
-
- /* 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(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) {
- /* This construction allows us to easily switch back to a scheme where the PRF is calculated using two different digest algorithms. */
- memset(out, 0, outlen);
-
- return prf_xor(NID_sha512, secret, secretlen, seed, seedlen, out, outlen);
-}