Port to libsodium, switch to AES256-GCM, revamp authentication
This commit is contained in:
parent
9aac84a0ce
commit
ed49289d7b
97
auth.c
97
auth.c
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -56,66 +57,44 @@
|
|||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
|
|
||||||
/* Encryption and Decryption of the challenge key */
|
/* Encryption and Decryption of the challenge key */
|
||||||
#ifdef HAVE_SSL
|
#include <sodium.h>
|
||||||
|
|
||||||
#include <openssl/md5.h>
|
static int derive_key(struct vtun_host *host)
|
||||||
#include <openssl/blowfish.h>
|
|
||||||
#include <openssl/rand.h>
|
|
||||||
|
|
||||||
static void gen_chal(char *buf)
|
|
||||||
{
|
{
|
||||||
RAND_bytes(buf, VTUN_CHAL_SIZE);
|
unsigned char salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (host->key != NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ((host->key = sodium_malloc(HOST_KEYBYTES)) == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(salt, 0xd1, sizeof salt);
|
||||||
|
if (crypto_pwhash_scryptsalsa208sha256
|
||||||
|
(host->key, HOST_KEYBYTES, host->passwd, strlen(host->passwd), salt,
|
||||||
|
crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE,
|
||||||
|
crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) == 0) {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
sodium_memzero(host->passwd, strlen(host->passwd));
|
||||||
|
free(host->passwd);
|
||||||
|
host->passwd = NULL;
|
||||||
|
vtun_syslog(LOG_DEBUG,"Key ready for host %s.", host->host);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void encrypt_chal(char *chal, char *pwd)
|
static void gen_chal(char *chal)
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
BF_KEY key;
|
|
||||||
|
|
||||||
BF_set_key(&key, 16, MD5(pwd,strlen(pwd),NULL));
|
|
||||||
|
|
||||||
for(i=0; i < VTUN_CHAL_SIZE; i += 8 )
|
|
||||||
BF_ecb_encrypt(chal + i, chal + i, &key, BF_ENCRYPT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void decrypt_chal(char *chal, char *pwd)
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
BF_KEY key;
|
|
||||||
|
|
||||||
BF_set_key(&key, 16, MD5(pwd,strlen(pwd),NULL));
|
|
||||||
|
|
||||||
for(i=0; i < VTUN_CHAL_SIZE; i += 8 )
|
|
||||||
BF_ecb_encrypt(chal + i, chal + i, &key, BF_DECRYPT);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* HAVE_SSL */
|
|
||||||
|
|
||||||
static void encrypt_chal(char *chal, char *pwd)
|
|
||||||
{
|
|
||||||
char * xor_msk = pwd;
|
|
||||||
register int i, xor_len = strlen(xor_msk);
|
|
||||||
|
|
||||||
for(i=0; i < VTUN_CHAL_SIZE; i++)
|
|
||||||
chal[i] ^= xor_msk[i%xor_len];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void inline decrypt_chal(char *chal, char *pwd)
|
|
||||||
{
|
|
||||||
encrypt_chal(chal, pwd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generate PSEUDO random challenge key. */
|
|
||||||
static void gen_chal(char *buf)
|
|
||||||
{
|
{
|
||||||
register int i;
|
randombytes_buf((unsigned char *) chal, VTUN_CHAL_SIZE);
|
||||||
|
}
|
||||||
srand(time(NULL));
|
|
||||||
|
static void auth_chal(char *chal, const struct vtun_host *host)
|
||||||
for(i=0; i < VTUN_CHAL_SIZE; i++)
|
{
|
||||||
buf[i] = (unsigned int)(255.0 * rand()/RAND_MAX);
|
crypto_generichash(chal, VTUN_CHAL_SIZE, chal, VTUN_CHAL_SIZE,
|
||||||
|
host->key, HOST_KEYBYTES);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_SSL */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Functions to convert binary flags to character string.
|
* Functions to convert binary flags to character string.
|
||||||
@ -348,10 +327,10 @@ struct vtun_host * auth_server(int fd)
|
|||||||
|
|
||||||
if( !(h = find_host(host)) )
|
if( !(h = find_host(host)) )
|
||||||
break;
|
break;
|
||||||
|
derive_key(h);
|
||||||
decrypt_chal(chal_res, h->passwd);
|
auth_chal(chal_req, h);
|
||||||
|
|
||||||
if( !memcmp(chal_req, chal_res, VTUN_CHAL_SIZE) ){
|
if( !sodium_memcmp(chal_req, chal_res, VTUN_CHAL_SIZE) ){
|
||||||
/* Auth successeful. */
|
/* Auth successeful. */
|
||||||
|
|
||||||
/* Lock host */
|
/* Lock host */
|
||||||
@ -400,8 +379,8 @@ int auth_client(int fd, struct vtun_host *host)
|
|||||||
case ST_HOST:
|
case ST_HOST:
|
||||||
if( !strncmp(buf,"OK",2) && cs2cl(buf,chal)){
|
if( !strncmp(buf,"OK",2) && cs2cl(buf,chal)){
|
||||||
stage = ST_CHAL;
|
stage = ST_CHAL;
|
||||||
|
derive_key(host);
|
||||||
encrypt_chal(chal,host->passwd);
|
auth_chal(chal, host);
|
||||||
print_p(fd,"CHAL: %s\n", cl2cs(chal));
|
print_p(fd,"CHAL: %s\n", cl2cs(chal));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
2
auth.h
2
auth.h
@ -20,7 +20,7 @@
|
|||||||
* $Id: auth.h,v 1.3.2.2 2008/01/07 22:35:19 mtbishop Exp $
|
* $Id: auth.h,v 1.3.2.2 2008/01/07 22:35:19 mtbishop Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VTUN_CHAL_SIZE 16
|
#define VTUN_CHAL_SIZE 16
|
||||||
|
|
||||||
#define ST_INIT 0
|
#define ST_INIT 0
|
||||||
#define ST_HOST 1
|
#define ST_HOST 1
|
||||||
|
@ -107,6 +107,7 @@ statement: '\n'
|
|||||||
memcpy(parse_host, &default_host, sizeof(struct vtun_host));
|
memcpy(parse_host, &default_host, sizeof(struct vtun_host));
|
||||||
parse_host->host = strdup($1);
|
parse_host->host = strdup($1);
|
||||||
parse_host->passwd = NULL;
|
parse_host->passwd = NULL;
|
||||||
|
parse_host->key = NULL;
|
||||||
parse_host->sopt.host = strdup($1);
|
parse_host->sopt.host = strdup($1);
|
||||||
|
|
||||||
/* Copy local address */
|
/* Copy local address */
|
||||||
|
13
cfg_kwords.h
13
cfg_kwords.h
@ -86,17 +86,6 @@ struct kword cfg_param[] = {
|
|||||||
{ "inetd", VTUN_INETD },
|
{ "inetd", VTUN_INETD },
|
||||||
{ "stand", VTUN_STAND_ALONE },
|
{ "stand", VTUN_STAND_ALONE },
|
||||||
{ "keep", VTUN_PERSIST_KEEPIF },
|
{ "keep", VTUN_PERSIST_KEEPIF },
|
||||||
{ "blowfish128cbc", VTUN_ENC_BF128CBC },
|
{ "aes256gcm",VTUN_ENC_AES256GCM },
|
||||||
{ "blowfish128cfb", VTUN_ENC_BF128CFB },
|
|
||||||
{ "blowfish128ofb", VTUN_ENC_BF128OFB },
|
|
||||||
{ "blowfish256cbc", VTUN_ENC_BF256CBC },
|
|
||||||
{ "blowfish256cfb", VTUN_ENC_BF256CFB },
|
|
||||||
{ "blowfish256ofb", VTUN_ENC_BF256OFB },
|
|
||||||
{ "aes128cbc", VTUN_ENC_AES128CBC },
|
|
||||||
{ "aes128cfb", VTUN_ENC_AES128CFB },
|
|
||||||
{ "aes128ofb", VTUN_ENC_AES128OFB },
|
|
||||||
{ "aes256cbc", VTUN_ENC_AES256CBC },
|
|
||||||
{ "aes256cfb", VTUN_ENC_AES256CFB },
|
|
||||||
{ "aes256ofb", VTUN_ENC_AES256OFB },
|
|
||||||
{ NULL , 0 }
|
{ NULL , 0 }
|
||||||
};
|
};
|
||||||
|
78
configure.ac
78
configure.ac
@ -17,10 +17,10 @@ AC_ARG_ENABLE(shaper,
|
|||||||
SHAPER=yes
|
SHAPER=yes
|
||||||
)
|
)
|
||||||
dnl Encryption support
|
dnl Encryption support
|
||||||
AC_ARG_ENABLE(ssl,
|
AC_ARG_ENABLE(sodium,
|
||||||
--disable-ssl Don not compile encryption module,
|
--disable-sodium Don not compile encryption module,
|
||||||
SSL=$enableval,
|
SODIUM=$enableval,
|
||||||
SSL=yes
|
SODIUM=yes
|
||||||
)
|
)
|
||||||
dnl ZLIB support
|
dnl ZLIB support
|
||||||
AC_ARG_ENABLE(zlib,
|
AC_ARG_ENABLE(zlib,
|
||||||
@ -48,13 +48,13 @@ AC_ARG_ENABLE(nathack,
|
|||||||
NATHACK=yes
|
NATHACK=yes
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_ARG_WITH(ssl-headers,
|
AC_ARG_WITH(sodium-headers,
|
||||||
--with-ssl-headers=DIR Crypto Include files location,
|
--with-sodium-headers=DIR Crypto Include files location,
|
||||||
SSL_HDR_DIR="$withval"
|
SODIUM_HDR_DIR="$withval"
|
||||||
CPPFLAGS="$CPPFLAGS -I$withval"
|
CPPFLAGS="$CPPFLAGS -I$withval"
|
||||||
)
|
)
|
||||||
AC_ARG_WITH(ssl-lib,
|
AC_ARG_WITH(sodium-lib,
|
||||||
--with-ssl-lib=DIR Crypto Library location,
|
--with-sodium-lib=DIR Crypto Library location,
|
||||||
LIBS="$LIBS -L$withval"
|
LIBS="$LIBS -L$withval"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -165,60 +165,16 @@ if test "$LZO" = "yes"; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$SSL" = "yes"; then
|
if test "$SODIUM" = "yes"; then
|
||||||
AC_MSG_RESULT()
|
AC_MSG_RESULT()
|
||||||
AC_CHECKING( for md5 Library and Header files ... )
|
AC_CHECKING( for Sodium Library and Header files ... )
|
||||||
AC_SEARCH_HEADERS(md5.h,
|
AC_SEARCH_LIBS(crypto_aead_aes256gcm_aesni_encrypt, [sodium],
|
||||||
$SSL_HDR_DIR /usr/include/openssl "" /usr/include /usr/include/ssl /usr/local/include /usr/local/ssl/include /usr/include/sys,
|
[AC_DEFINE(HAVE_SODIUM, [1], [Define to 1 if you have Sodium])],
|
||||||
|
AC_ERROR([libsodium with crypto_aead_aes256gcm_aesni_encrypt not found]))
|
||||||
|
AC_SEARCH_HEADERS(sodium.h,
|
||||||
|
$SSL_HDR_DIR /usr/include /usr/local/include /opt/include,
|
||||||
,
|
,
|
||||||
AC_MSG_ERROR( SSL headers not found. )
|
AC_MSG_ERROR( Sodium headers not found. )
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$SSL" = "yes"; then
|
|
||||||
AC_MSG_RESULT()
|
|
||||||
AC_CHECKING( for blowfish Library and Header files ... )
|
|
||||||
AC_SEARCH_HEADERS(blowfish.h,
|
|
||||||
$BLOWFISH_HDR_DIR /usr/include/ssl /usr/include/openssl /usr/include /usr/local/include /usr/local/ssl/include /usr/include/crypto,
|
|
||||||
AC_CHECK_LIB(crypto, BF_set_key,
|
|
||||||
[
|
|
||||||
LIBS="$LIBS -lcrypto"
|
|
||||||
AC_DEFINE(HAVE_SSL, [1], [Define to 1 if you have openssl])
|
|
||||||
AC_DEFINE(HAVE_SSL_BLOWFISH, [1], [Define to 1 if you have blowfish in openssl])
|
|
||||||
],
|
|
||||||
AC_MSG_ERROR( SSL library not found. )
|
|
||||||
),
|
|
||||||
AC_MSG_ERROR( SSL headers not found. )
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$SSL" = "yes"; then
|
|
||||||
AC_MSG_RESULT()
|
|
||||||
AC_CHECKING( for AES Library and Header files ... )
|
|
||||||
AC_SEARCH_HEADERS(aes.h,
|
|
||||||
$SSL_HDR_DIR /usr/include/ssl /usr/include/openssl /usr/include /usr/local/include /usr/local/ssl/include /usr/include/crypto,
|
|
||||||
AC_CHECK_LIB(crypto, AES_set_encrypt_key,
|
|
||||||
[
|
|
||||||
AC_DEFINE(HAVE_SSL_AES, [1], [Define to 1 if you have AES in openssl])
|
|
||||||
],
|
|
||||||
AC_MSG_ERROR( AES library not found. )
|
|
||||||
),
|
|
||||||
AC_MSG_ERROR( AES headers not found. )
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$SSL" = "yes"; then
|
|
||||||
AC_MSG_RESULT()
|
|
||||||
AC_CHECKING( for EVP Library and Header files ... )
|
|
||||||
AC_SEARCH_HEADERS(evp.h,
|
|
||||||
$SSL_HDR_DIR /usr/include/ssl /usr/include/openssl /usr/include /usr/local/include /usr/local/ssl/include /usr/include/crypto,
|
|
||||||
AC_CHECK_LIB(crypto, EVP_EncryptInit,
|
|
||||||
[
|
|
||||||
AC_DEFINE(HAVE_SSL_EVP, [1], [Define to 1 if you have EVP in openssl])
|
|
||||||
],
|
|
||||||
AC_MSG_ERROR( EVP library not found. )
|
|
||||||
),
|
|
||||||
AC_MSG_ERROR( EVP headers not found. )
|
|
||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
806
lfd_encrypt.c
806
lfd_encrypt.c
@ -1,707 +1,172 @@
|
|||||||
/*
|
|
||||||
VTun - Virtual Tunnel over TCP/IP network.
|
|
||||||
|
|
||||||
Copyright (C) 1998-2008 Maxim Krasnyansky <max_mk@yahoo.com>
|
|
||||||
|
|
||||||
VTun has been derived from VPPP package by Maxim Krasnyansky.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Encryption module uses software developed by the OpenSSL Project
|
|
||||||
for use in the OpenSSL Toolkit. (http://www.openssl.org/)
|
|
||||||
Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This lfd_encrypt module uses MD5 to create 128 bits encryption
|
|
||||||
* keys and BlowFish for actual data encryption.
|
|
||||||
* It is based on code written by Chris Todd<christ@insynq.com> with
|
|
||||||
* several improvements and modifications by me.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The current lfd_encrypt module is based on code attributed above and
|
|
||||||
* uses new code written by Dale Fountain <dpf-vtun@fountainbay.com> to
|
|
||||||
* allow multiple ciphers, modes, and key sizes. Feb 2004.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <syslog.h>
|
#include <stdlib.h>
|
||||||
#include <strings.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "vtun.h"
|
#include "vtun.h"
|
||||||
#include "linkfd.h"
|
#include "linkfd.h"
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SODIUM
|
||||||
|
#include <sodium.h>
|
||||||
|
|
||||||
/* OpenSSL includes */
|
#define crypto_aead_NPUBBYTES crypto_aead_aes256gcm_NPUBBYTES
|
||||||
#include <openssl/evp.h>
|
#define crypto_aead_ABYTES crypto_aead_aes256gcm_ABYTES
|
||||||
#include <openssl/md5.h>
|
#define crypto_aead_KEYBYTES crypto_aead_aes256gcm_KEYBYTES
|
||||||
#include <openssl/blowfish.h>
|
|
||||||
#include <openssl/rand.h>
|
|
||||||
|
|
||||||
/*
|
#define MESSAGE_MAX_SIZE VTUN_FRAME_SIZE
|
||||||
* #define LFD_ENCRYPT_DEBUG
|
#define CIPHERTEXT_ABYTES (crypto_aead_ABYTES + crypto_aead_NPUBBYTES)
|
||||||
*/
|
#define CIPHERTEXT_MAX_SIZE MESSAGE_MAX_SIZE
|
||||||
|
#define CIPHERTEXT_MAX_TOTAL_SIZE (CIPHERTEXT_MAX_SIZE + CIPHERTEXT_ABYTES)
|
||||||
|
|
||||||
#define ENC_BUF_SIZE VTUN_FRAME_SIZE + 128
|
#define MINIMUM_DATE 1444341043UL
|
||||||
#define ENC_KEY_SIZE 16
|
#define SLEEP_WHEN_CLOCK_IS_OFF 10
|
||||||
|
|
||||||
static BF_KEY key;
|
typedef struct CryptoCtx {
|
||||||
static char * enc_buf;
|
crypto_aead_aes256gcm_aesni_state *state;
|
||||||
static char * dec_buf;
|
unsigned char *ciphertext;
|
||||||
|
unsigned char *key;
|
||||||
|
unsigned char *message;
|
||||||
|
unsigned char *nonce;
|
||||||
|
unsigned char *previous_decrypted_nonce;
|
||||||
|
} CryptoCtx;
|
||||||
|
|
||||||
#define CIPHER_INIT 0
|
static CryptoCtx ctx;
|
||||||
#define CIPHER_CODE 1
|
|
||||||
#define CIPHER_SEQUENCE 2
|
|
||||||
#define CIPHER_REQ_INIT 3
|
|
||||||
|
|
||||||
static struct vtun_host *phost;
|
static int
|
||||||
|
derive_key(unsigned char *key, size_t key_size, struct vtun_host *host)
|
||||||
extern int send_a_packet;
|
|
||||||
|
|
||||||
/* out of sync packet threshold before forcing a re-init */
|
|
||||||
#define MAX_GIBBERISH 10
|
|
||||||
#define MIN_GIBBERISH 1
|
|
||||||
#define MAX_GIBBERISH_TIME 2
|
|
||||||
static int gibberish;
|
|
||||||
static time_t gib_time_start;
|
|
||||||
|
|
||||||
static int cipher_enc_state;
|
|
||||||
static int cipher_dec_state;
|
|
||||||
static int cipher;
|
|
||||||
static int blocksize;
|
|
||||||
static int keysize;
|
|
||||||
static int enc_init_first_time;
|
|
||||||
static int dec_init_first_time;
|
|
||||||
static unsigned long sequence_num;
|
|
||||||
static char * pkey;
|
|
||||||
static char * iv_buf;
|
|
||||||
|
|
||||||
static EVP_CIPHER_CTX ctx_enc; /* encrypt */
|
|
||||||
static EVP_CIPHER_CTX ctx_dec; /* decrypt */
|
|
||||||
|
|
||||||
static EVP_CIPHER_CTX ctx_enc_ecb; /* sideband ecb encrypt */
|
|
||||||
static EVP_CIPHER_CTX ctx_dec_ecb; /* sideband ecb decrypt */
|
|
||||||
|
|
||||||
static int send_msg(int len, char *in, char **out);
|
|
||||||
static int recv_msg(int len, char *in, char **out);
|
|
||||||
static int send_ib_mesg(int *len, char **in);
|
|
||||||
static int recv_ib_mesg(int *len, char **in);
|
|
||||||
|
|
||||||
static int prep_key(char **key, int size, struct vtun_host *host)
|
|
||||||
{
|
{
|
||||||
int tmplen, halflen;
|
crypto_generichash(key, key_size, host->key, HOST_KEYBYTES, NULL, 0U);
|
||||||
char *hashkey;
|
sodium_free(host->key);
|
||||||
|
host->key = NULL;
|
||||||
if ( !(hashkey = malloc(size)) )
|
|
||||||
{
|
|
||||||
vtun_syslog(LOG_ERR,"Can't allocate buffer for key hash");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memset(hashkey,0,size);
|
|
||||||
|
|
||||||
if (size == 32)
|
|
||||||
{
|
|
||||||
tmplen = strlen(host->passwd);
|
|
||||||
if (tmplen != 0) halflen = tmplen>>1;
|
|
||||||
else halflen = 0;
|
|
||||||
MD5(host->passwd, halflen, hashkey);
|
|
||||||
MD5((host->passwd)+halflen, tmplen-halflen, hashkey+16);
|
|
||||||
}
|
|
||||||
else if (size == 16)
|
|
||||||
{
|
|
||||||
MD5(host->passwd,strlen(host->passwd), hashkey);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* don't know what to do */
|
|
||||||
free(hashkey);
|
|
||||||
*key = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*key = hashkey;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_key (char *key)
|
static int
|
||||||
|
init_nonce(unsigned char *nonce, size_t nonce_size)
|
||||||
{
|
{
|
||||||
free(key);
|
time_t now;
|
||||||
|
|
||||||
|
if (nonce_size < 5) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
time(&now);
|
||||||
|
if (now < MINIMUM_DATE) {
|
||||||
|
sleep(SLEEP_WHEN_CLOCK_IS_OFF);
|
||||||
|
randombytes_buf(nonce, nonce_size);
|
||||||
|
} else {
|
||||||
|
randombytes_buf(nonce + 4, nonce_size - 4);
|
||||||
|
now <<= 2;
|
||||||
|
memcpy(nonce, &now, 3);
|
||||||
|
nonce[3] = (nonce[3] & 0x3) ^ *(((unsigned char *) &now) + 3);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alloc_encrypt(struct vtun_host *host)
|
static int
|
||||||
|
alloc_encrypt(struct vtun_host *host)
|
||||||
{
|
{
|
||||||
int sb_init = 0;
|
if (sodium_init() < 0) {
|
||||||
int var_key = 0;
|
return -1;
|
||||||
const EVP_CIPHER *cipher_type;
|
}
|
||||||
char tmpstr[64];
|
ctx.state = sodium_malloc(sizeof *ctx.state);
|
||||||
char cipher_name[32];
|
ctx.key = sodium_malloc(crypto_aead_KEYBYTES);
|
||||||
EVP_CIPHER_CTX *pctx_enc;
|
ctx.message = sodium_malloc(MESSAGE_MAX_SIZE);
|
||||||
EVP_CIPHER_CTX *pctx_dec;
|
ctx.ciphertext = sodium_malloc(CIPHERTEXT_MAX_TOTAL_SIZE);
|
||||||
|
ctx.nonce = sodium_malloc(crypto_aead_NPUBBYTES);
|
||||||
enc_init_first_time = 1;
|
ctx.previous_decrypted_nonce = sodium_malloc(crypto_aead_NPUBBYTES);
|
||||||
dec_init_first_time = 1;
|
if (ctx.state == NULL || ctx.key == NULL || ctx.message == NULL ||
|
||||||
|
ctx.ciphertext == NULL || ctx.ciphertext == NULL || ctx.nonce == NULL ||
|
||||||
if( !(enc_buf = lfd_alloc(ENC_BUF_SIZE)) ){
|
ctx.previous_decrypted_nonce == NULL) {
|
||||||
vtun_syslog(LOG_ERR,"Can't allocate buffer for encryptor");
|
abort();
|
||||||
return -1;
|
}
|
||||||
}
|
if (init_nonce(ctx.nonce, crypto_aead_NPUBBYTES) != 0) {
|
||||||
if( !(dec_buf = lfd_alloc(ENC_BUF_SIZE)) ){
|
return -1;
|
||||||
vtun_syslog(LOG_ERR,"Can't allocate buffer for decryptor");
|
}
|
||||||
return -1;
|
if (derive_key(ctx.key, crypto_aead_KEYBYTES, host) != 0) {
|
||||||
}
|
return -1;
|
||||||
|
}
|
||||||
RAND_bytes((char *)&sequence_num, 4);
|
crypto_aead_aes256gcm_aesni_beforenm(ctx.state, ctx.key);
|
||||||
gibberish = 0;
|
sodium_free(ctx.key);
|
||||||
gib_time_start = 0;
|
ctx.key = NULL;
|
||||||
phost = host;
|
return 0;
|
||||||
cipher = host->cipher;
|
|
||||||
switch(cipher)
|
|
||||||
{
|
|
||||||
case VTUN_ENC_AES128OFB:
|
|
||||||
case VTUN_ENC_AES128CFB:
|
|
||||||
case VTUN_ENC_AES128CBC:
|
|
||||||
blocksize = 16;
|
|
||||||
keysize = 16;
|
|
||||||
sb_init=1;
|
|
||||||
cipher_type = EVP_aes_128_ecb();
|
|
||||||
pctx_enc = &ctx_enc_ecb;
|
|
||||||
pctx_dec = &ctx_dec_ecb;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VTUN_ENC_BF256OFB:
|
|
||||||
case VTUN_ENC_BF256CFB:
|
|
||||||
case VTUN_ENC_BF256CBC:
|
|
||||||
blocksize = 8;
|
|
||||||
keysize = 32;
|
|
||||||
var_key = 1;
|
|
||||||
sb_init = 1;
|
|
||||||
cipher_type = EVP_bf_ecb();
|
|
||||||
pctx_enc = &ctx_enc_ecb;
|
|
||||||
pctx_dec = &ctx_dec_ecb;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VTUN_ENC_BF128OFB:
|
|
||||||
case VTUN_ENC_BF128CFB:
|
|
||||||
case VTUN_ENC_BF128CBC:
|
|
||||||
blocksize = 8;
|
|
||||||
keysize = 16;
|
|
||||||
var_key = 1;
|
|
||||||
sb_init = 1;
|
|
||||||
cipher_type = EVP_bf_ecb();
|
|
||||||
pctx_enc = &ctx_enc_ecb;
|
|
||||||
pctx_dec = &ctx_dec_ecb;
|
|
||||||
break;
|
|
||||||
case VTUN_ENC_AES256OFB:
|
|
||||||
case VTUN_ENC_AES256CFB:
|
|
||||||
case VTUN_ENC_AES256CBC:
|
|
||||||
default:
|
|
||||||
blocksize = 16;
|
|
||||||
keysize = 32;
|
|
||||||
sb_init = 1;
|
|
||||||
cipher_type = EVP_aes_256_ecb();
|
|
||||||
pctx_enc = &ctx_enc_ecb;
|
|
||||||
pctx_dec = &ctx_dec_ecb;
|
|
||||||
strcpy(cipher_name,"AES-256-CBC");
|
|
||||||
} /* switch(host->cipher) */
|
|
||||||
|
|
||||||
if (prep_key(&pkey, keysize, host) != 0) return -1;
|
|
||||||
EVP_CIPHER_CTX_init(pctx_enc);
|
|
||||||
EVP_CIPHER_CTX_init(pctx_dec);
|
|
||||||
EVP_EncryptInit_ex(pctx_enc, cipher_type, NULL, NULL, NULL);
|
|
||||||
EVP_DecryptInit_ex(pctx_dec, cipher_type, NULL, NULL, NULL);
|
|
||||||
if (var_key)
|
|
||||||
{
|
|
||||||
EVP_CIPHER_CTX_set_key_length(pctx_enc, keysize);
|
|
||||||
EVP_CIPHER_CTX_set_key_length(pctx_dec, keysize);
|
|
||||||
}
|
|
||||||
EVP_EncryptInit_ex(pctx_enc, NULL, NULL, pkey, NULL);
|
|
||||||
EVP_DecryptInit_ex(pctx_dec, NULL, NULL, pkey, NULL);
|
|
||||||
EVP_CIPHER_CTX_set_padding(pctx_enc, 0);
|
|
||||||
EVP_CIPHER_CTX_set_padding(pctx_dec, 0);
|
|
||||||
if (sb_init)
|
|
||||||
{
|
|
||||||
cipher_enc_state=CIPHER_INIT;
|
|
||||||
cipher_dec_state=CIPHER_INIT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cipher_enc_state=CIPHER_CODE;
|
|
||||||
cipher_dec_state=CIPHER_CODE;
|
|
||||||
sprintf(tmpstr,"%s encryption initialized", cipher_name);
|
|
||||||
vtun_syslog(LOG_INFO, tmpstr);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int free_encrypt()
|
static int
|
||||||
|
free_encrypt(void)
|
||||||
{
|
{
|
||||||
free_key(pkey); pkey = NULL;
|
sodium_free(ctx.key);
|
||||||
|
sodium_free(ctx.message);
|
||||||
|
sodium_free(ctx.ciphertext);
|
||||||
|
sodium_free(ctx.nonce);
|
||||||
|
sodium_free(ctx.previous_decrypted_nonce);
|
||||||
|
|
||||||
lfd_free(enc_buf); enc_buf = NULL;
|
return 0;
|
||||||
lfd_free(dec_buf); dec_buf = NULL;
|
|
||||||
|
|
||||||
EVP_CIPHER_CTX_cleanup(&ctx_enc);
|
|
||||||
EVP_CIPHER_CTX_cleanup(&ctx_dec);
|
|
||||||
EVP_CIPHER_CTX_cleanup(&ctx_enc_ecb);
|
|
||||||
EVP_CIPHER_CTX_cleanup(&ctx_dec_ecb);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int encrypt_buf(int len, char *in, char **out)
|
static int
|
||||||
{
|
is_lower_or_equal(const unsigned char *a, const unsigned char *b, size_t size)
|
||||||
register int pad, p, msg_len;
|
|
||||||
int outlen;
|
|
||||||
char *in_ptr, *out_ptr = enc_buf;
|
|
||||||
|
|
||||||
msg_len = send_msg(len, in, out);
|
|
||||||
in = *out;
|
|
||||||
in_ptr = in+msg_len;
|
|
||||||
memcpy(out_ptr,in,msg_len);
|
|
||||||
out_ptr += msg_len;
|
|
||||||
|
|
||||||
send_ib_mesg(&len, &in_ptr);
|
|
||||||
if (!len) return 0;
|
|
||||||
/* ( len % blocksize ) */
|
|
||||||
p = (len & (blocksize-1)); pad = blocksize - p;
|
|
||||||
|
|
||||||
memset(in_ptr+len, pad, pad);
|
|
||||||
outlen=len+pad;
|
|
||||||
if (pad == blocksize)
|
|
||||||
RAND_bytes(in_ptr+len, blocksize-1);
|
|
||||||
EVP_EncryptUpdate(&ctx_enc, out_ptr, &outlen, in_ptr, len+pad);
|
|
||||||
*out = enc_buf;
|
|
||||||
|
|
||||||
sequence_num++;
|
|
||||||
|
|
||||||
return outlen+msg_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int decrypt_buf(int len, char *in, char **out)
|
|
||||||
{
|
{
|
||||||
register int pad;
|
size_t i;
|
||||||
char *tmp_ptr, *in_ptr, *out_ptr = dec_buf;
|
|
||||||
int outlen;
|
for (i = 0U; i < size; i++) {
|
||||||
|
if (a[i] > b[i]) {
|
||||||
len = recv_msg(len, in, out);
|
return 0;
|
||||||
in = *out;
|
}
|
||||||
in_ptr = in;
|
}
|
||||||
|
return 1;
|
||||||
outlen=len;
|
|
||||||
if (!len) return 0;
|
|
||||||
EVP_DecryptUpdate(&ctx_dec, out_ptr, &outlen, in_ptr, len);
|
|
||||||
recv_ib_mesg(&outlen, &out_ptr);
|
|
||||||
if (!outlen) return 0;
|
|
||||||
tmp_ptr = out_ptr + outlen; tmp_ptr--;
|
|
||||||
pad = *tmp_ptr;
|
|
||||||
if (pad < 1 || pad > blocksize) {
|
|
||||||
vtun_syslog(LOG_INFO, "decrypt_buf: bad pad length");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*out = out_ptr;
|
|
||||||
return outlen - pad;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cipher_enc_init(char * iv)
|
static int
|
||||||
{
|
encrypt_buf(int message_len_, char *message_, char ** const ciphertext_p)
|
||||||
int var_key = 0;
|
{
|
||||||
const EVP_CIPHER *cipher_type;
|
const unsigned char *message = (const unsigned char *) message_;
|
||||||
char tmpstr[64];
|
const size_t message_len = (size_t) message_len_;
|
||||||
char cipher_name[32];
|
unsigned long long ciphertext_len;
|
||||||
|
|
||||||
|
if (message_len_ < 0 || message_len > MESSAGE_MAX_SIZE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
crypto_aead_aes256gcm_aesni_encrypt_afternm(ctx.ciphertext, &ciphertext_len,
|
||||||
|
message, message_len,
|
||||||
|
NULL, 0ULL,
|
||||||
|
NULL, ctx.nonce, ctx.state);
|
||||||
|
memcpy(ctx.ciphertext + message_len + crypto_aead_ABYTES,
|
||||||
|
ctx.nonce, crypto_aead_NPUBBYTES);
|
||||||
|
sodium_increment(ctx.nonce, crypto_aead_NPUBBYTES);
|
||||||
|
*ciphertext_p = ctx.ciphertext;
|
||||||
|
|
||||||
switch(cipher)
|
return (int) ciphertext_len + crypto_aead_NPUBBYTES;
|
||||||
{
|
|
||||||
case VTUN_ENC_AES256OFB:
|
|
||||||
cipher_type = EVP_aes_256_ofb();
|
|
||||||
strcpy(cipher_name, "AES-256-OFB");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VTUN_ENC_AES256CFB:
|
|
||||||
cipher_type = EVP_aes_256_cfb();
|
|
||||||
strcpy(cipher_name, "AES-256-CFB");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VTUN_ENC_AES256CBC:
|
|
||||||
cipher_type = EVP_aes_256_cbc();
|
|
||||||
strcpy(cipher_name, "AES-256-CBC");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VTUN_ENC_AES128OFB:
|
|
||||||
cipher_type = EVP_aes_128_ofb();
|
|
||||||
strcpy(cipher_name, "AES-128-OFB");
|
|
||||||
break;
|
|
||||||
case VTUN_ENC_AES128CFB:
|
|
||||||
cipher_type = EVP_aes_128_cfb();
|
|
||||||
strcpy(cipher_name, "AES-128-CFB");
|
|
||||||
break;
|
|
||||||
case VTUN_ENC_AES128CBC:
|
|
||||||
cipher_type = EVP_aes_128_cbc();
|
|
||||||
strcpy(cipher_name, "AES-128-CBC");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VTUN_ENC_BF256OFB:
|
|
||||||
var_key = 1;
|
|
||||||
cipher_type = EVP_bf_ofb();
|
|
||||||
strcpy(cipher_name, "Blowfish-256-OFB");
|
|
||||||
break;
|
|
||||||
case VTUN_ENC_BF256CFB:
|
|
||||||
var_key = 1;
|
|
||||||
cipher_type = EVP_bf_cfb();
|
|
||||||
strcpy(cipher_name, "Blowfish-256-CFB");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VTUN_ENC_BF256CBC:
|
|
||||||
var_key = 1;
|
|
||||||
cipher_type = EVP_bf_cbc();
|
|
||||||
strcpy(cipher_name, "Blowfish-256-CBC");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VTUN_ENC_BF128OFB:
|
|
||||||
var_key = 1;
|
|
||||||
cipher_type = EVP_bf_ofb();
|
|
||||||
strcpy(cipher_name, "Blowfish-128-OFB");
|
|
||||||
break;
|
|
||||||
case VTUN_ENC_BF128CFB:
|
|
||||||
var_key = 1;
|
|
||||||
cipher_type = EVP_bf_cfb();
|
|
||||||
strcpy(cipher_name, "Blowfish-128-CFB");
|
|
||||||
break;
|
|
||||||
case VTUN_ENC_BF128CBC:
|
|
||||||
var_key = 1;
|
|
||||||
cipher_type = EVP_bf_cbc();
|
|
||||||
strcpy(cipher_name, "Blowfish-128-CBC");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* if we're here, something weird's going on */
|
|
||||||
return -1;
|
|
||||||
break;
|
|
||||||
} /* switch(cipher) */
|
|
||||||
|
|
||||||
EVP_CIPHER_CTX_init(&ctx_enc);
|
|
||||||
EVP_EncryptInit_ex(&ctx_enc, cipher_type, NULL, NULL, NULL);
|
|
||||||
if (var_key)
|
|
||||||
EVP_CIPHER_CTX_set_key_length(&ctx_enc, keysize);
|
|
||||||
EVP_EncryptInit_ex(&ctx_enc, NULL, NULL, pkey, NULL);
|
|
||||||
EVP_EncryptInit_ex(&ctx_enc, NULL, NULL, NULL, iv);
|
|
||||||
EVP_CIPHER_CTX_set_padding(&ctx_enc, 0);
|
|
||||||
if (enc_init_first_time)
|
|
||||||
{
|
|
||||||
sprintf(tmpstr,"%s encryption initialized", cipher_name);
|
|
||||||
vtun_syslog(LOG_INFO, tmpstr);
|
|
||||||
enc_init_first_time = 0;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cipher_dec_init(char * iv)
|
static int
|
||||||
{
|
decrypt_buf(int ciphertext_len_, char *ciphertext_, char ** const message_p)
|
||||||
int var_key = 0;
|
{
|
||||||
const EVP_CIPHER *cipher_type;
|
const unsigned char *ciphertext = (const unsigned char *) ciphertext_;
|
||||||
char tmpstr[64];
|
const unsigned char *nonce;
|
||||||
char cipher_name[32];
|
size_t ciphertext_len = (size_t) ciphertext_len_;
|
||||||
|
unsigned long long message_len;
|
||||||
|
|
||||||
|
if (ciphertext_len_ < CIPHERTEXT_ABYTES ||
|
||||||
|
ciphertext_len > CIPHERTEXT_MAX_SIZE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ciphertext_len -= crypto_aead_NPUBBYTES;
|
||||||
|
nonce = ciphertext + ciphertext_len;
|
||||||
|
if (is_lower_or_equal(nonce, ctx.previous_decrypted_nonce, crypto_aead_NPUBBYTES) ||
|
||||||
|
crypto_aead_aes256gcm_aesni_decrypt_afternm(ctx.message, &message_len, NULL,
|
||||||
|
ciphertext, ciphertext_len,
|
||||||
|
NULL, 0ULL, nonce, ctx.state) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(ctx.previous_decrypted_nonce, nonce, crypto_aead_NPUBBYTES);
|
||||||
|
*message_p = ctx.message;
|
||||||
|
|
||||||
switch(cipher)
|
return (int) message_len;
|
||||||
{
|
|
||||||
case VTUN_ENC_AES256OFB:
|
|
||||||
cipher_type = EVP_aes_256_ofb();
|
|
||||||
strcpy(cipher_name, "AES-256-OFB");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VTUN_ENC_AES256CFB:
|
|
||||||
cipher_type = EVP_aes_256_cfb();
|
|
||||||
strcpy(cipher_name, "AES-256-CFB");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VTUN_ENC_AES256CBC:
|
|
||||||
cipher_type = EVP_aes_256_cbc();
|
|
||||||
strcpy(cipher_name, "AES-256-CBC");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VTUN_ENC_AES128OFB:
|
|
||||||
cipher_type = EVP_aes_128_ofb();
|
|
||||||
strcpy(cipher_name, "AES-128-OFB");
|
|
||||||
break;
|
|
||||||
case VTUN_ENC_AES128CFB:
|
|
||||||
cipher_type = EVP_aes_128_cfb();
|
|
||||||
strcpy(cipher_name, "AES-128-CFB");
|
|
||||||
break;
|
|
||||||
case VTUN_ENC_AES128CBC:
|
|
||||||
cipher_type = EVP_aes_128_cbc();
|
|
||||||
strcpy(cipher_name, "AES-128-CBC");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VTUN_ENC_BF256OFB:
|
|
||||||
var_key = 1;
|
|
||||||
cipher_type = EVP_bf_ofb();
|
|
||||||
strcpy(cipher_name, "Blowfish-256-OFB");
|
|
||||||
break;
|
|
||||||
case VTUN_ENC_BF256CFB:
|
|
||||||
var_key = 1;
|
|
||||||
cipher_type = EVP_bf_cfb();
|
|
||||||
strcpy(cipher_name, "Blowfish-256-CFB");
|
|
||||||
break;
|
|
||||||
case VTUN_ENC_BF256CBC:
|
|
||||||
var_key = 1;
|
|
||||||
cipher_type = EVP_bf_cbc();
|
|
||||||
strcpy(cipher_name, "Blowfish-256-CBC");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VTUN_ENC_BF128OFB:
|
|
||||||
var_key = 1;
|
|
||||||
cipher_type = EVP_bf_ofb();
|
|
||||||
strcpy(cipher_name, "Blowfish-128-OFB");
|
|
||||||
break;
|
|
||||||
case VTUN_ENC_BF128CFB:
|
|
||||||
var_key = 1;
|
|
||||||
cipher_type = EVP_bf_cfb();
|
|
||||||
strcpy(cipher_name, "Blowfish-128-CFB");
|
|
||||||
break;
|
|
||||||
case VTUN_ENC_BF128CBC:
|
|
||||||
var_key = 1;
|
|
||||||
cipher_type = EVP_bf_cbc();
|
|
||||||
strcpy(cipher_name, "Blowfish-128-CBC");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* if we're here, something weird's going on */
|
|
||||||
return -1;
|
|
||||||
break;
|
|
||||||
} /* switch(cipher) */
|
|
||||||
|
|
||||||
EVP_CIPHER_CTX_init(&ctx_dec);
|
|
||||||
EVP_DecryptInit_ex(&ctx_dec, cipher_type, NULL, NULL, NULL);
|
|
||||||
if (var_key)
|
|
||||||
EVP_CIPHER_CTX_set_key_length(&ctx_dec, keysize);
|
|
||||||
EVP_DecryptInit_ex(&ctx_dec, NULL, NULL, pkey, NULL);
|
|
||||||
EVP_DecryptInit_ex(&ctx_dec, NULL, NULL, NULL, iv);
|
|
||||||
EVP_CIPHER_CTX_set_padding(&ctx_dec, 0);
|
|
||||||
if (dec_init_first_time)
|
|
||||||
{
|
|
||||||
sprintf(tmpstr,"%s decryption initialized", cipher_name);
|
|
||||||
vtun_syslog(LOG_INFO, tmpstr);
|
|
||||||
dec_init_first_time = 0;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_msg(int len, char *in, char **out)
|
|
||||||
{
|
|
||||||
char * iv; char * in_ptr;
|
|
||||||
int outlen;
|
|
||||||
|
|
||||||
switch(cipher_enc_state)
|
|
||||||
{
|
|
||||||
case CIPHER_INIT:
|
|
||||||
in_ptr = in - blocksize*2;
|
|
||||||
iv = malloc(blocksize);
|
|
||||||
RAND_bytes(iv, blocksize);
|
|
||||||
strncpy(in_ptr,"ivec",4);
|
|
||||||
in_ptr += 4;
|
|
||||||
memcpy(in_ptr,iv,blocksize);
|
|
||||||
in_ptr += blocksize;
|
|
||||||
cipher_enc_init(iv);
|
|
||||||
|
|
||||||
memset(iv,0,blocksize); free(iv); iv = NULL;
|
|
||||||
RAND_bytes(in_ptr, in - in_ptr);
|
|
||||||
|
|
||||||
in_ptr = in - blocksize*2;
|
|
||||||
outlen = blocksize*2;
|
|
||||||
EVP_EncryptUpdate(&ctx_enc_ecb, in_ptr,
|
|
||||||
&outlen, in_ptr, blocksize*2);
|
|
||||||
*out = in_ptr;
|
|
||||||
len = outlen;
|
|
||||||
cipher_enc_state = CIPHER_SEQUENCE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CIPHER_CODE:
|
|
||||||
default:
|
|
||||||
*out = in;
|
|
||||||
len = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int recv_msg(int len, char *in, char **out)
|
|
||||||
{
|
|
||||||
char * iv; char * in_ptr;
|
|
||||||
int outlen;
|
|
||||||
|
|
||||||
switch(cipher_dec_state)
|
|
||||||
{
|
|
||||||
case CIPHER_INIT:
|
|
||||||
in_ptr = in;
|
|
||||||
iv = malloc(blocksize);
|
|
||||||
outlen = blocksize*2;
|
|
||||||
EVP_DecryptUpdate(&ctx_dec_ecb, in_ptr, &outlen, in_ptr, blocksize*2);
|
|
||||||
|
|
||||||
if ( !strncmp(in_ptr, "ivec", 4) )
|
|
||||||
{
|
|
||||||
memcpy(iv, in_ptr+4, blocksize);
|
|
||||||
cipher_dec_init(iv);
|
|
||||||
|
|
||||||
*out = in_ptr + blocksize*2;
|
|
||||||
len -= blocksize*2;
|
|
||||||
cipher_dec_state = CIPHER_SEQUENCE;
|
|
||||||
gibberish = 0;
|
|
||||||
gib_time_start = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
len = 0;
|
|
||||||
*out = in;
|
|
||||||
gibberish++;
|
|
||||||
if (gibberish == 1) gib_time_start = time(NULL);
|
|
||||||
|
|
||||||
if (gibberish == MIN_GIBBERISH)
|
|
||||||
{
|
|
||||||
cipher_enc_state = CIPHER_REQ_INIT;
|
|
||||||
send_a_packet = 1;
|
|
||||||
#ifdef LFD_ENCRYPT_DEBUG
|
|
||||||
vtun_syslog(LOG_INFO,
|
|
||||||
"Min. gibberish threshold reached");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (gibberish >= MAX_GIBBERISH ||
|
|
||||||
difftime(time(NULL), gib_time_start) >= MAX_GIBBERISH_TIME)
|
|
||||||
{
|
|
||||||
gibberish = 0;
|
|
||||||
gib_time_start = 0;
|
|
||||||
send_a_packet = 1;
|
|
||||||
|
|
||||||
#ifdef LFD_ENCRYPT_DEBUG
|
|
||||||
vtun_syslog(LOG_INFO,
|
|
||||||
"Max. gibberish threshold reached");
|
|
||||||
#endif
|
|
||||||
if (cipher_enc_state != CIPHER_INIT)
|
|
||||||
{
|
|
||||||
cipher_enc_state = CIPHER_INIT;
|
|
||||||
EVP_CIPHER_CTX_cleanup(&ctx_enc);
|
|
||||||
#ifdef LFD_ENCRYPT_DEBUG
|
|
||||||
vtun_syslog(LOG_INFO,
|
|
||||||
"Forcing local encryptor re-init");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memset(iv,0,blocksize); free(iv); iv = NULL;
|
|
||||||
memset(in_ptr,0,blocksize*2);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CIPHER_CODE:
|
|
||||||
default:
|
|
||||||
*out = in;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send In-Band Message */
|
|
||||||
static int send_ib_mesg(int *len, char **in)
|
|
||||||
{
|
|
||||||
char *in_ptr = *in;
|
|
||||||
|
|
||||||
/* To simplify matters, I assume that blocksize
|
|
||||||
will not be less than 8 bytes */
|
|
||||||
if (cipher_enc_state == CIPHER_SEQUENCE)
|
|
||||||
{
|
|
||||||
in_ptr -= blocksize;
|
|
||||||
memset(in_ptr,0,blocksize);
|
|
||||||
strncpy(in_ptr,"seq#",4);
|
|
||||||
in_ptr+=4;
|
|
||||||
*((unsigned long *)in_ptr) = htonl(sequence_num);
|
|
||||||
in_ptr-=4;
|
|
||||||
|
|
||||||
*in = in_ptr;
|
|
||||||
*len += blocksize;
|
|
||||||
}
|
|
||||||
else if (cipher_enc_state == CIPHER_REQ_INIT)
|
|
||||||
{
|
|
||||||
in_ptr -= blocksize;
|
|
||||||
memset(in_ptr,0,blocksize);
|
|
||||||
strncpy(in_ptr,"rsyn",4);
|
|
||||||
in_ptr+=4;
|
|
||||||
*((unsigned long *)in_ptr) = htonl(sequence_num);
|
|
||||||
in_ptr-=4;
|
|
||||||
|
|
||||||
*in = in_ptr;
|
|
||||||
*len += blocksize;
|
|
||||||
#ifdef LFD_ENCRYPT_DEBUG
|
|
||||||
vtun_syslog(LOG_INFO, "Requesting remote encryptor re-init");
|
|
||||||
#endif
|
|
||||||
cipher_enc_state = CIPHER_SEQUENCE;
|
|
||||||
send_a_packet = 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Receive In-Band Message */
|
|
||||||
static int recv_ib_mesg(int *len, char **in)
|
|
||||||
{
|
|
||||||
char *in_ptr = *in;
|
|
||||||
|
|
||||||
if (cipher_dec_state == CIPHER_SEQUENCE)
|
|
||||||
{
|
|
||||||
/* To simplify matters, I assume that blocksize
|
|
||||||
will not be less than 8 bytes */
|
|
||||||
if ( !strncmp(in_ptr, "seq#", 4) )
|
|
||||||
{
|
|
||||||
*in += blocksize;
|
|
||||||
*len -= blocksize;
|
|
||||||
}
|
|
||||||
else if ( !strncmp(in_ptr, "rsyn", 4) )
|
|
||||||
{
|
|
||||||
*in += blocksize;
|
|
||||||
*len -= blocksize;
|
|
||||||
|
|
||||||
if (cipher_enc_state != CIPHER_INIT)
|
|
||||||
{
|
|
||||||
cipher_enc_state = CIPHER_INIT;
|
|
||||||
EVP_CIPHER_CTX_cleanup(&ctx_enc);
|
|
||||||
}
|
|
||||||
#ifdef LFD_ENCRYPT_DEBUG
|
|
||||||
vtun_syslog(LOG_INFO, "Remote requests encryptor re-init");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*len = 0;
|
|
||||||
|
|
||||||
if (cipher_dec_state != CIPHER_INIT &&
|
|
||||||
cipher_enc_state != CIPHER_REQ_INIT &&
|
|
||||||
cipher_enc_state != CIPHER_INIT)
|
|
||||||
{
|
|
||||||
EVP_CIPHER_CTX_cleanup (&ctx_dec);
|
|
||||||
cipher_dec_state = CIPHER_INIT;
|
|
||||||
cipher_enc_state = CIPHER_REQ_INIT;
|
|
||||||
}
|
|
||||||
#ifdef LFD_ENCRYPT_DEBUG
|
|
||||||
vtun_syslog(LOG_INFO, "Local decryptor out of sync");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Module structure.
|
|
||||||
*/
|
|
||||||
struct lfd_mod lfd_encrypt = {
|
struct lfd_mod lfd_encrypt = {
|
||||||
"Encryptor",
|
"Encryptor",
|
||||||
alloc_encrypt,
|
alloc_encrypt,
|
||||||
@ -714,9 +179,10 @@ struct lfd_mod lfd_encrypt = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
#else /* HAVE_SSL */
|
#else /* HAVE_SODIUM */
|
||||||
|
|
||||||
static int no_encrypt(struct vtun_host *host)
|
static int
|
||||||
|
no_encrypt(struct vtun_host *host)
|
||||||
{
|
{
|
||||||
vtun_syslog(LOG_INFO, "Encryption is not supported");
|
vtun_syslog(LOG_INFO, "Encryption is not supported");
|
||||||
return -1;
|
return -1;
|
||||||
@ -727,4 +193,4 @@ struct lfd_mod lfd_encrypt = {
|
|||||||
no_encrypt, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
no_encrypt, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HAVE_SSL */
|
#endif
|
||||||
|
10
main.c
10
main.c
@ -35,6 +35,10 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SODIUM
|
||||||
|
#include <sodium.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "vtun.h"
|
#include "vtun.h"
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
@ -193,6 +197,12 @@ int main(int argc, char *argv[], char *env[])
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SODIUM
|
||||||
|
if (sodium_init() != 0) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if( daemon ){
|
if( daemon ){
|
||||||
#ifdef HAVE_WORKING_FORK
|
#ifdef HAVE_WORKING_FORK
|
||||||
|
17
vtun.h
17
vtun.h
@ -82,9 +82,12 @@ struct vtun_addr {
|
|||||||
#define VTUN_ADDR_IFACE 0x01
|
#define VTUN_ADDR_IFACE 0x01
|
||||||
#define VTUN_ADDR_NAME 0x02
|
#define VTUN_ADDR_NAME 0x02
|
||||||
|
|
||||||
|
#define HOST_KEYBYTES 32
|
||||||
|
|
||||||
struct vtun_host {
|
struct vtun_host {
|
||||||
char *host;
|
char *host;
|
||||||
char *passwd;
|
char *passwd;
|
||||||
|
unsigned char *key;
|
||||||
char *dev;
|
char *dev;
|
||||||
|
|
||||||
llist up;
|
llist up;
|
||||||
@ -138,19 +141,7 @@ extern llist host_list;
|
|||||||
#define VTUN_ENCRYPT 0x0008
|
#define VTUN_ENCRYPT 0x0008
|
||||||
|
|
||||||
/* Cipher options */
|
/* Cipher options */
|
||||||
#define VTUN_ENC_BF128CBC 2
|
#define VTUN_ENC_AES256GCM 17
|
||||||
#define VTUN_ENC_BF128CFB 3
|
|
||||||
#define VTUN_ENC_BF128OFB 4
|
|
||||||
#define VTUN_ENC_BF256CBC 6
|
|
||||||
#define VTUN_ENC_BF256CFB 7
|
|
||||||
#define VTUN_ENC_BF256OFB 8
|
|
||||||
|
|
||||||
#define VTUN_ENC_AES128CBC 10
|
|
||||||
#define VTUN_ENC_AES128CFB 11
|
|
||||||
#define VTUN_ENC_AES128OFB 12
|
|
||||||
#define VTUN_ENC_AES256CBC 14
|
|
||||||
#define VTUN_ENC_AES256CFB 15
|
|
||||||
#define VTUN_ENC_AES256OFB 16
|
|
||||||
|
|
||||||
/* Mask to drop the flags which will be supplied by the server */
|
/* Mask to drop the flags which will be supplied by the server */
|
||||||
#define VTUN_CLNT_MASK 0xf000
|
#define VTUN_CLNT_MASK 0xf000
|
||||||
|
13
vtund.conf
13
vtund.conf
@ -150,18 +150,7 @@
|
|||||||
# -----------
|
# -----------
|
||||||
# encrypt - Enable 'yes' or disable 'no' encryption.
|
# encrypt - Enable 'yes' or disable 'no' encryption.
|
||||||
# It is also possible to specify a method:
|
# It is also possible to specify a method:
|
||||||
# 'blowfish128cbc' - Blowfish cipher, 128 bit key, mode CBC
|
# 'aes256gcm' - AES cipher, 256 bit key, mode GCM
|
||||||
# 'blowfish128cfb' - Blowfish cipher, 128 bit key, mode CFB
|
|
||||||
# 'blowfish128ofb' - Blowfish cipher, 128 bit key, mode OFB
|
|
||||||
# 'blowfish256cbc' - Blowfish cipher, 256 bit key, mode CBC
|
|
||||||
# 'blowfish256cfb' - Blowfish cipher, 256 bit key, mode CFB
|
|
||||||
# 'blowfish256ofb' - Blowfish cipher, 256 bit key, mode OFB
|
|
||||||
# 'aes128cbc' - AES cipher, 128 bit key, mode CBC
|
|
||||||
# 'aes128cfb' - AES cipher, 128 bit key, mode CFB
|
|
||||||
# 'aes128ofb' - AES cipher, 128 bit key, mode OFB
|
|
||||||
# 'aes256cbc' - AES cipher, 256 bit key, mode CBC
|
|
||||||
# 'aes256cfb' - AES cipher, 256 bit key, mode CFB
|
|
||||||
# 'aes256ofb' - AES cipher, 256 bit key, mode OFB
|
|
||||||
#
|
#
|
||||||
# Ignored by the client.
|
# Ignored by the client.
|
||||||
#
|
#
|
||||||
|
26
vtund.conf.5
26
vtund.conf.5
@ -199,30 +199,8 @@ specifies encryption method to use. Encryption \fImethod\fRs include:
|
|||||||
no encryption
|
no encryption
|
||||||
.IP \fByes\fR
|
.IP \fByes\fR
|
||||||
default encryption method
|
default encryption method
|
||||||
.IP \fBblowfish128cbc\fR
|
.IP \fBaes256gcm\fR
|
||||||
Blowfish cipher, 128 bit key, mode CBC
|
AES cipher, 256 bit key, mode GCM
|
||||||
.IP \fBblowfish128cfb\fR
|
|
||||||
Blowfish cipher, 128 bit key, mode CFB
|
|
||||||
.IP \fBblowfish128ofb\fR
|
|
||||||
Blowfish cipher, 128 bit key, mode OFB
|
|
||||||
.IP \fBblowfish256cbc\fR
|
|
||||||
Blowfish cipher, 256 bit key, mode CBC
|
|
||||||
.IP \fBblowfish256cfb\fR
|
|
||||||
Blowfish cipher, 256 bit key, mode CFB
|
|
||||||
.IP \fBblowfish256ofb\fR
|
|
||||||
Blowfish cipher, 256 bit key, mode OFB
|
|
||||||
.IP \fBaes128cbc\fR
|
|
||||||
AES cipher, 128 bit key, mode CBC
|
|
||||||
.IP \fBaes128cfb\fR
|
|
||||||
AES cipher, 128 bit key, mode CFB
|
|
||||||
.IP \fBaes128ofb\fR
|
|
||||||
AES cipher, 128 bit key, mode OFB
|
|
||||||
.IP \fBaes256cbc\fR
|
|
||||||
AES cipher, 256 bit key, mode CBC
|
|
||||||
.IP \fBaes256cfb\fR
|
|
||||||
AES cipher, 256 bit key, mode CFB
|
|
||||||
.IP \fBaes256ofb\fR
|
|
||||||
AES cipher, 256 bit key, mode OFB
|
|
||||||
.RE
|
.RE
|
||||||
.IP
|
.IP
|
||||||
This option is ignored by the client.
|
This option is ignored by the client.
|
||||||
|
Loading…
Reference in New Issue
Block a user