
Clean up Configure.in for autoheader Static declarations where sensible Check/handle no fork() for no-MMU client systems (eg blackfin)
767 lines
19 KiB
C
767 lines
19 KiB
C
/*
|
|
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 <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <syslog.h>
|
|
#include <strings.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
#include "vtun.h"
|
|
#include "linkfd.h"
|
|
#include "lib.h"
|
|
|
|
#ifdef HAVE_SSL
|
|
|
|
/* OpenSSL includes */
|
|
#include <openssl/evp.h>
|
|
#include <openssl/md5.h>
|
|
#include <openssl/blowfish.h>
|
|
#include <openssl/rand.h>
|
|
|
|
/*
|
|
* #define LFD_ENCRYPT_DEBUG
|
|
*/
|
|
|
|
#define ENC_BUF_SIZE VTUN_FRAME_SIZE + 128
|
|
#define ENC_KEY_SIZE 16
|
|
|
|
static BF_KEY key;
|
|
static char * enc_buf;
|
|
static char * dec_buf;
|
|
|
|
#define CIPHER_INIT 0
|
|
#define CIPHER_CODE 1
|
|
#define CIPHER_SEQUENCE 2
|
|
#define CIPHER_REQ_INIT 3
|
|
|
|
static struct vtun_host *phost;
|
|
|
|
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;
|
|
char *hashkey;
|
|
|
|
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)
|
|
{
|
|
free(key);
|
|
}
|
|
|
|
static int alloc_encrypt(struct vtun_host *host)
|
|
{
|
|
int sb_init = 0;
|
|
int var_key = 0;
|
|
const EVP_CIPHER *cipher_type;
|
|
char tmpstr[64];
|
|
char cipher_name[32];
|
|
EVP_CIPHER_CTX *pctx_enc;
|
|
EVP_CIPHER_CTX *pctx_dec;
|
|
|
|
enc_init_first_time = 1;
|
|
dec_init_first_time = 1;
|
|
|
|
if( !(enc_buf = lfd_alloc(ENC_BUF_SIZE)) ){
|
|
vtun_syslog(LOG_ERR,"Can't allocate buffer for encryptor");
|
|
return -1;
|
|
}
|
|
if( !(dec_buf = lfd_alloc(ENC_BUF_SIZE)) ){
|
|
vtun_syslog(LOG_ERR,"Can't allocate buffer for decryptor");
|
|
return -1;
|
|
}
|
|
|
|
RAND_bytes((char *)&sequence_num, 4);
|
|
gibberish = 0;
|
|
gib_time_start = 0;
|
|
phost = host;
|
|
cipher = host->cipher;
|
|
switch(cipher)
|
|
{
|
|
case VTUN_ENC_AES256OFB:
|
|
case VTUN_ENC_AES256CFB:
|
|
case VTUN_ENC_AES256CBC:
|
|
blocksize = 16;
|
|
keysize = 32;
|
|
sb_init = 1;
|
|
cipher_type = EVP_aes_256_ecb();
|
|
pctx_enc = &ctx_enc_ecb;
|
|
pctx_dec = &ctx_dec_ecb;
|
|
break;
|
|
|
|
case VTUN_ENC_AES256ECB:
|
|
blocksize = 16;
|
|
keysize = 32;
|
|
pctx_enc = &ctx_enc;
|
|
pctx_dec = &ctx_dec;
|
|
cipher_type = EVP_aes_256_ecb();
|
|
strcpy(cipher_name,"AES-256-ECB");
|
|
break;
|
|
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_AES128ECB:
|
|
blocksize = 16;
|
|
keysize = 16;
|
|
pctx_enc = &ctx_enc;
|
|
pctx_dec = &ctx_dec;
|
|
cipher_type = EVP_aes_128_ecb();
|
|
strcpy(cipher_name,"AES-128-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_BF256ECB:
|
|
blocksize = 8;
|
|
keysize = 32;
|
|
var_key = 1;
|
|
pctx_enc = &ctx_enc;
|
|
pctx_dec = &ctx_dec;
|
|
cipher_type = EVP_bf_ecb();
|
|
strcpy(cipher_name,"Blowfish-256-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_BF128ECB: /* blowfish 128 ecb is the default */
|
|
default:
|
|
blocksize = 8;
|
|
keysize = 16;
|
|
var_key = 1;
|
|
pctx_enc = &ctx_enc;
|
|
pctx_dec = &ctx_dec;
|
|
cipher_type = EVP_bf_ecb();
|
|
strcpy(cipher_name,"Blowfish-128-ECB");
|
|
break;
|
|
} /* 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()
|
|
{
|
|
free_key(pkey); pkey = NULL;
|
|
|
|
lfd_free(enc_buf); enc_buf = NULL;
|
|
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)
|
|
{
|
|
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;
|
|
char *tmp_ptr, *in_ptr, *out_ptr = dec_buf;
|
|
int outlen;
|
|
|
|
len = recv_msg(len, in, out);
|
|
in = *out;
|
|
in_ptr = in;
|
|
|
|
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)
|
|
{
|
|
int var_key = 0;
|
|
const EVP_CIPHER *cipher_type;
|
|
char tmpstr[64];
|
|
char cipher_name[32];
|
|
|
|
switch(cipher)
|
|
{
|
|
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)
|
|
{
|
|
int var_key = 0;
|
|
const EVP_CIPHER *cipher_type;
|
|
char tmpstr[64];
|
|
char cipher_name[32];
|
|
|
|
switch(cipher)
|
|
{
|
|
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 = {
|
|
"Encryptor",
|
|
alloc_encrypt,
|
|
encrypt_buf,
|
|
NULL,
|
|
decrypt_buf,
|
|
NULL,
|
|
free_encrypt,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
#else /* HAVE_SSL */
|
|
|
|
static int no_encrypt(struct vtun_host *host)
|
|
{
|
|
vtun_syslog(LOG_INFO, "Encryption is not supported");
|
|
return -1;
|
|
}
|
|
|
|
struct lfd_mod lfd_encrypt = {
|
|
"Encryptor",
|
|
no_encrypt, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
|
};
|
|
|
|
#endif /* HAVE_SSL */
|