mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-24 09:23:46 +00:00
Replace nonce cache with a ping-pong bloom filter (#1282)
* Add Ping-Pong bloom filter * Refine bloom filter insertion * Reduce the error rate to 0.00001 * Avoid alignment issue in murmurhash2 * Fix a memory leak * Fix build on non-GPU targets * Detect get_current_dir_name in configure * Update README.md * Remove redudant bfree() * Reduce the memory usage for local client * Fix #1275 * Refine #1275 * Use IP when bypassing SNI domains * Also apply replay detector on UDP traffic * Update deb build script Now build script is able to auto detect system and choose libraries necessary to build. Also update the README accordingly. * Update build script to enable jessie/stretch etc Also include a few cleanup that simplified pkg installation from backports repository.
This commit is contained in:
@@ -6,3 +6,7 @@
|
||||
path = libipset
|
||||
url = https://github.com/shadowsocks/ipset.git
|
||||
ignore = dirty
|
||||
[submodule "libbloom"]
|
||||
path = libbloom
|
||||
url = https://github.com/shadowsocks/libbloom.git
|
||||
ignore = dirty
|
||||
|
||||
+3
-2
@@ -1,7 +1,7 @@
|
||||
if USE_SYSTEM_SHARED_LIB
|
||||
SUBDIRS = src
|
||||
SUBDIRS = src libbloom
|
||||
else
|
||||
SUBDIRS = libcork libipset src
|
||||
SUBDIRS = libcork libipset libbloom src
|
||||
endif
|
||||
|
||||
if ENABLE_DOCUMENTATION
|
||||
@@ -14,6 +14,7 @@ pkgconfiglibdir = $(libdir)/pkgconfig
|
||||
pkgconfiglib_DATA = shadowsocks-libev.pc
|
||||
|
||||
EXTRA_DIST = acl Changes completions debian docker rpm README.md
|
||||
EXTRA_DIST += libbloom
|
||||
EXTRA_DIST += libcork/include libipset/include
|
||||
EXTRA_DIST += libipset/src/libipset/map/inspection-template.c.in
|
||||
EXTRA_DIST += libipset/src/libipset/set/inspection-template.c.in
|
||||
|
||||
+2
-1
@@ -230,7 +230,8 @@ AC_CHECK_LIB([ev], [ev_loop_destroy], [LIBS="-lev $LIBS"], [AC_MSG_ERROR([Couldn
|
||||
|
||||
AC_CONFIG_FILES([shadowsocks-libev.pc
|
||||
Makefile
|
||||
src/Makefile])
|
||||
src/Makefile
|
||||
libbloom/Makefile])
|
||||
|
||||
AM_COND_IF([USE_SYSTEM_SHARED_LIB],
|
||||
[AC_DEFINE([USE_SYSTEM_SHARED_LIB], [1], [Define if use system shared lib.])],
|
||||
|
||||
Submodule
+1
Submodule libbloom added at f6e53fe648
+4
-1
@@ -2,6 +2,7 @@ VERSION_INFO = 2:0:0
|
||||
|
||||
AM_CFLAGS = -g -O2 -Wall -Werror -Wno-deprecated-declarations -fno-strict-aliasing -std=gnu99 -D_GNU_SOURCE
|
||||
AM_CFLAGS += $(PTHREAD_CFLAGS)
|
||||
AM_CFLAGS += -I$(top_srcdir)/libbloom
|
||||
if !USE_SYSTEM_SHARED_LIB
|
||||
AM_CFLAGS += -I$(top_srcdir)/libipset/include
|
||||
AM_CFLAGS += -I$(top_srcdir)/libcork/include
|
||||
@@ -9,6 +10,7 @@ endif
|
||||
AM_CFLAGS += $(LIBPCRE_CFLAGS)
|
||||
|
||||
SS_COMMON_LIBS = $(INET_NTOP_LIB) $(LIBPCRE_LIBS)
|
||||
SS_COMMON_LIBS += $(top_builddir)/libbloom/libbloom.la
|
||||
if !USE_SYSTEM_SHARED_LIB
|
||||
SS_COMMON_LIBS += $(top_builddir)/libipset/libipset.la \
|
||||
$(top_builddir)/libcork/libcork.la
|
||||
@@ -26,6 +28,7 @@ sni_src = http.c \
|
||||
crypto_src = crypto.c \
|
||||
aead.c \
|
||||
stream.c \
|
||||
ppbloom.c \
|
||||
base64.c
|
||||
|
||||
plugin_src = plugin.c
|
||||
@@ -112,6 +115,6 @@ libshadowsocks_libev_la_LIBADD = $(ss_local_LDADD)
|
||||
include_HEADERS = shadowsocks.h
|
||||
|
||||
noinst_HEADERS = acl.h crypto.h stream.h aead.h json.h netutils.h redir.h server.h tls.h uthash.h \
|
||||
cache.h http.h local.h plugin.h resolv.h tunnel.h utils.h base64.h \
|
||||
cache.h http.h local.h plugin.h resolv.h tunnel.h utils.h base64.h ppbloom.h \
|
||||
common.h jconf.h manager.h protocol.h rule.h socks5.h udprelay.h
|
||||
EXTRA_DIST = ss-nat
|
||||
|
||||
+22
-20
@@ -33,7 +33,7 @@
|
||||
#include <sodium.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "cache.h"
|
||||
#include "ppbloom.h"
|
||||
#include "aead.h"
|
||||
#include "utils.h"
|
||||
|
||||
@@ -405,13 +405,11 @@ aead_encrypt_all(buffer_t *plaintext, cipher_t *cipher, size_t capacity)
|
||||
(uint8_t *)plaintext->data, plaintext->len,
|
||||
NULL, 0, cipher_ctx.nonce, cipher_ctx.skey);
|
||||
|
||||
if (err) {
|
||||
bfree(plaintext);
|
||||
aead_ctx_release(&cipher_ctx);
|
||||
return CRYPTO_ERROR;
|
||||
}
|
||||
|
||||
aead_ctx_release(&cipher_ctx);
|
||||
|
||||
if (err)
|
||||
return CRYPTO_ERROR;
|
||||
|
||||
assert(ciphertext->len == clen);
|
||||
|
||||
brealloc(plaintext, salt_len + ciphertext->len, capacity);
|
||||
@@ -444,6 +442,11 @@ aead_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity)
|
||||
uint8_t *salt = cipher_ctx.salt;
|
||||
memcpy(salt, ciphertext->data, salt_len);
|
||||
|
||||
if (ppbloom_check((void *)salt, salt_len) == 1) {
|
||||
LOGE("crypto: AEAD: repeat salt detected");
|
||||
return CRYPTO_ERROR;
|
||||
}
|
||||
|
||||
aead_cipher_ctx_set_key(&cipher_ctx, 0);
|
||||
|
||||
size_t plen = plaintext->len;
|
||||
@@ -453,14 +456,13 @@ aead_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity)
|
||||
ciphertext->len - salt_len, NULL, 0,
|
||||
cipher_ctx.nonce, cipher_ctx.skey);
|
||||
|
||||
if (err) {
|
||||
bfree(ciphertext);
|
||||
aead_ctx_release(&cipher_ctx);
|
||||
return CRYPTO_ERROR;
|
||||
}
|
||||
|
||||
aead_ctx_release(&cipher_ctx);
|
||||
|
||||
if (err)
|
||||
return CRYPTO_ERROR;
|
||||
|
||||
ppbloom_add((void *)salt, salt_len);
|
||||
|
||||
brealloc(ciphertext, plaintext->len, capacity);
|
||||
memcpy(ciphertext->data, plaintext->data, plaintext->len);
|
||||
ciphertext->len = plaintext->len;
|
||||
@@ -488,6 +490,7 @@ aead_chunk_encrypt(cipher_ctx_t *ctx, uint8_t *p, uint8_t *c,
|
||||
NULL, 0, n, ctx->skey);
|
||||
if (err)
|
||||
return CRYPTO_ERROR;
|
||||
|
||||
assert(clen == CHUNK_SIZE_LEN + tlen);
|
||||
|
||||
sodium_increment(n, nlen);
|
||||
@@ -497,6 +500,7 @@ aead_chunk_encrypt(cipher_ctx_t *ctx, uint8_t *p, uint8_t *c,
|
||||
NULL, 0, n, ctx->skey);
|
||||
if (err)
|
||||
return CRYPTO_ERROR;
|
||||
|
||||
assert(clen == plen + tlen);
|
||||
|
||||
sodium_increment(n, nlen);
|
||||
@@ -634,12 +638,9 @@ aead_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)
|
||||
|
||||
aead_cipher_ctx_set_key(cipher_ctx, 0);
|
||||
|
||||
if (cache_key_exist(nonce_cache, (char *)cipher_ctx->salt, salt_len)) {
|
||||
if (ppbloom_check((void *)cipher_ctx->salt, salt_len) == 1) {
|
||||
LOGE("crypto: AEAD: repeat salt detected");
|
||||
bfree(ciphertext);
|
||||
return CRYPTO_ERROR;
|
||||
} else {
|
||||
cache_insert(nonce_cache, (char *)cipher_ctx->salt, salt_len, NULL);
|
||||
}
|
||||
|
||||
memmove(cipher_ctx->chunk->data, cipher_ctx->chunk->data + salt_len,
|
||||
@@ -647,6 +648,10 @@ aead_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)
|
||||
cipher_ctx->chunk->len -= salt_len;
|
||||
|
||||
cipher_ctx->init = 1;
|
||||
|
||||
} else if (cipher_ctx->init == 1) {
|
||||
ppbloom_add((void *)cipher_ctx->salt, salt_len);
|
||||
cipher_ctx->init = 2;
|
||||
}
|
||||
|
||||
size_t plen = 0;
|
||||
@@ -685,9 +690,6 @@ aead_key_init(int method, const char *pass, const char *key)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Initialize cache
|
||||
cache_create(&nonce_cache, 1024, NULL);
|
||||
|
||||
cipher_t *cipher = (cipher_t *)ss_malloc(sizeof(cipher_t));
|
||||
memset(cipher, 0, sizeof(cipher_t));
|
||||
|
||||
|
||||
+7
-5
@@ -29,13 +29,11 @@
|
||||
#include <mbedtls/md5.h>
|
||||
|
||||
#include "base64.h"
|
||||
#include "cache.h"
|
||||
#include "crypto.h"
|
||||
#include "stream.h"
|
||||
#include "aead.h"
|
||||
#include "utils.h"
|
||||
|
||||
struct cache *nonce_cache;
|
||||
#include "ppbloom.h"
|
||||
|
||||
int
|
||||
balloc(buffer_t *ptr, size_t capacity)
|
||||
@@ -111,8 +109,12 @@ crypto_init(const char *password, const char *key, const char *method)
|
||||
FATAL("Failed to initialize sodium");
|
||||
}
|
||||
|
||||
// Initialize NONCE cache
|
||||
cache_create(&nonce_cache, 1024, NULL);
|
||||
// Initialize NONCE bloom filter
|
||||
#ifdef MODULE_REMOTE
|
||||
ppbloom_init(1000000, 0.00001);
|
||||
#else
|
||||
ppbloom_init(100000, 0.0000001);
|
||||
#endif
|
||||
|
||||
if (method != NULL) {
|
||||
for (i = 0; i < STREAM_CIPHER_NUM; i++)
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ typedef struct {
|
||||
} cipher_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t init;
|
||||
uint32_t init;
|
||||
uint64_t counter;
|
||||
cipher_evp_t *evp;
|
||||
cipher_t *cipher;
|
||||
|
||||
+1
-3
@@ -223,9 +223,7 @@ read_jconf(const char *file)
|
||||
"invalid config file: option 'reuse_port' must be a boolean");
|
||||
conf.reuse_port = value->u.boolean;
|
||||
} else if (strcmp(name, "auth") == 0) {
|
||||
check_json_value_type(value, json_boolean,
|
||||
"invalid config file: option 'auth' must be a boolean");
|
||||
conf.auth = value->u.boolean;
|
||||
FATAL("One time auth has been deprecated. Try AEAD ciphers instead.");
|
||||
} else if (strcmp(name, "nofile") == 0) {
|
||||
check_json_value_type(value, json_integer,
|
||||
"invalid config file: option 'nofile' must be an integer");
|
||||
|
||||
@@ -59,7 +59,6 @@ typedef struct {
|
||||
char *user;
|
||||
char *plugin;
|
||||
char *plugin_opts;
|
||||
int auth;
|
||||
int fast_open;
|
||||
int reuse_port;
|
||||
int nofile;
|
||||
|
||||
+6
-3
@@ -676,7 +676,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
struct sockaddr_storage storage;
|
||||
memset(&storage, 0, sizeof(struct sockaddr_storage));
|
||||
#ifndef ANDROID
|
||||
if (sni_detected || atyp == 3)
|
||||
if (atyp == 3)
|
||||
err = get_sockaddr(host, port, &storage, 0, ipv6first);
|
||||
else
|
||||
#endif
|
||||
@@ -1211,10 +1211,10 @@ main(int argc, char **argv)
|
||||
USE_TTY();
|
||||
|
||||
#ifdef ANDROID
|
||||
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:n:huUvV6",
|
||||
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:n:huUvV6A",
|
||||
long_options, NULL)) != -1) {
|
||||
#else
|
||||
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:n:huUv6",
|
||||
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:n:huUv6A",
|
||||
long_options, NULL)) != -1) {
|
||||
#endif
|
||||
switch (c) {
|
||||
@@ -1309,6 +1309,9 @@ main(int argc, char **argv)
|
||||
vpn = 1;
|
||||
break;
|
||||
#endif
|
||||
case 'A':
|
||||
FATAL("One time auth has been deprecated. Try AEAD ciphers instead.");
|
||||
break;
|
||||
case '?':
|
||||
// The option character is not recognized.
|
||||
LOGE("Unrecognized option: %s", optarg);
|
||||
|
||||
+3
-16
@@ -151,10 +151,6 @@ construct_command_line(struct manager_ctx *manager, struct server *server)
|
||||
int len = strlen(cmd);
|
||||
snprintf(cmd + len, BUF_SIZE - len, " -u");
|
||||
}
|
||||
if (manager->auth) {
|
||||
int len = strlen(cmd);
|
||||
snprintf(cmd + len, BUF_SIZE - len, " -A");
|
||||
}
|
||||
if (manager->fast_open) {
|
||||
int len = strlen(cmd);
|
||||
snprintf(cmd + len, BUF_SIZE - len, " --fast-open");
|
||||
@@ -884,7 +880,6 @@ main(int argc, char **argv)
|
||||
char *plugin = NULL;
|
||||
char *plugin_opts = NULL;
|
||||
|
||||
int auth = 0;
|
||||
int fast_open = 0;
|
||||
int reuse_port = 0;
|
||||
int mode = TCP_ONLY;
|
||||
@@ -999,14 +994,14 @@ main(int argc, char **argv)
|
||||
case 'h':
|
||||
usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'A':
|
||||
auth = 1;
|
||||
break;
|
||||
#ifdef HAVE_SETRLIMIT
|
||||
case 'n':
|
||||
nofile = atoi(optarg);
|
||||
break;
|
||||
#endif
|
||||
case 'A':
|
||||
FATAL("One time auth has been deprecated. Try AEAD ciphers instead.");
|
||||
break;
|
||||
case '?':
|
||||
// The option character is not recognized.
|
||||
LOGE("Unrecognized option: %s", optarg);
|
||||
@@ -1047,9 +1042,6 @@ main(int argc, char **argv)
|
||||
if (conf->nameserver != NULL) {
|
||||
nameservers[nameserver_num++] = conf->nameserver;
|
||||
}
|
||||
if (auth == 0) {
|
||||
auth = conf->auth;
|
||||
}
|
||||
if (mode == TCP_ONLY) {
|
||||
mode = conf->mode;
|
||||
}
|
||||
@@ -1107,10 +1099,6 @@ main(int argc, char **argv)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (auth) {
|
||||
LOGI("onetime authentication enabled");
|
||||
}
|
||||
|
||||
// ignore SIGPIPE
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
@@ -1130,7 +1118,6 @@ main(int argc, char **argv)
|
||||
manager.fast_open = fast_open;
|
||||
manager.verbose = verbose;
|
||||
manager.mode = mode;
|
||||
manager.auth = auth;
|
||||
manager.password = password;
|
||||
manager.timeout = timeout;
|
||||
manager.method = method;
|
||||
|
||||
@@ -38,7 +38,6 @@ struct manager_ctx {
|
||||
int reuse_port;
|
||||
int verbose;
|
||||
int mode;
|
||||
int auth;
|
||||
char *password;
|
||||
char *key;
|
||||
char *timeout;
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* ppbloom.c - Ping-Pong Bloom Filter for nonce reuse detection
|
||||
*
|
||||
* Copyright (C) 2013 - 2017, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
*
|
||||
* shadowsocks-libev 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev 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 shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bloom.h"
|
||||
#include "ppbloom.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define PING 0
|
||||
#define PONG 1
|
||||
|
||||
static struct bloom ppbloom[2];
|
||||
static int bloom_count[2];
|
||||
static int current;
|
||||
static int entries;
|
||||
static double error;
|
||||
|
||||
int
|
||||
ppbloom_init(int n, double e)
|
||||
{
|
||||
int err;
|
||||
entries = n / 2;
|
||||
error = e;
|
||||
|
||||
err = bloom_init(ppbloom + PING, entries, error);
|
||||
if (err) return err;
|
||||
|
||||
err = bloom_init(ppbloom + PONG, entries, error);
|
||||
if (err) return err;
|
||||
|
||||
bloom_count[PING] = 0;
|
||||
bloom_count[PONG] = 0;
|
||||
|
||||
current = PING;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ppbloom_check(const void *buffer, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bloom_check(ppbloom + PING, buffer, len);
|
||||
if (ret) return ret;
|
||||
|
||||
ret = bloom_check(ppbloom + PONG, buffer, len);
|
||||
if (ret) return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ppbloom_add(const void *buffer, int len)
|
||||
{
|
||||
int err;
|
||||
err = bloom_add(ppbloom + current, buffer, len);
|
||||
if (err == -1) return err;
|
||||
|
||||
bloom_count[current]++;
|
||||
|
||||
if (bloom_count[current] >= entries) {
|
||||
bloom_count[current] = 0;
|
||||
current = current == PING ? PONG : PING;
|
||||
bloom_free(ppbloom + current);
|
||||
bloom_init(ppbloom + current, entries, error);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ppbloom_free()
|
||||
{
|
||||
bloom_free(ppbloom + PING);
|
||||
bloom_free(ppbloom + PONG);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* ppbloom.h - Define the Ping-Pong Bloom Filter interface
|
||||
*
|
||||
* Copyright (C) 2013 - 2017, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
*
|
||||
* shadowsocks-libev 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev 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 shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _PPBLOOM_
|
||||
#define _PPBLOOM_
|
||||
|
||||
int ppbloom_init(int entries, double error);
|
||||
int ppbloom_check(const void * buffer, int len);
|
||||
int ppbloom_add(const void * buffer, int len);
|
||||
void ppbloom_free(void);
|
||||
|
||||
#endif
|
||||
+4
-1
@@ -818,7 +818,7 @@ main(int argc, char **argv)
|
||||
|
||||
USE_TTY();
|
||||
|
||||
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUv6",
|
||||
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUv6A",
|
||||
long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case GETOPT_VAL_MTU:
|
||||
@@ -897,6 +897,9 @@ main(int argc, char **argv)
|
||||
case '6':
|
||||
ipv6first = 1;
|
||||
break;
|
||||
case 'A':
|
||||
FATAL("One time auth has been deprecated. Try AEAD ciphers instead.");
|
||||
break;
|
||||
case '?':
|
||||
// The option character is not recognized.
|
||||
LOGE("Unrecognized option: %s", optarg);
|
||||
|
||||
+4
-1
@@ -1384,7 +1384,7 @@ main(int argc, char **argv)
|
||||
|
||||
USE_TTY();
|
||||
|
||||
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:b:c:i:d:a:n:huUv6",
|
||||
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:b:c:i:d:a:n:huUv6A",
|
||||
long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case GETOPT_VAL_FAST_OPEN:
|
||||
@@ -1477,6 +1477,9 @@ main(int argc, char **argv)
|
||||
case '6':
|
||||
ipv6first = 1;
|
||||
break;
|
||||
case 'A':
|
||||
FATAL("One time auth has been deprecated. Try AEAD ciphers instead.");
|
||||
break;
|
||||
case '?':
|
||||
// The option character is not recognized.
|
||||
LOGE("Unrecognized option: %s", optarg);
|
||||
|
||||
+23
-21
@@ -31,7 +31,7 @@
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
#include "cache.h"
|
||||
#include "ppbloom.h"
|
||||
#include "stream.h"
|
||||
#include "utils.h"
|
||||
|
||||
@@ -321,11 +321,10 @@ stream_encrypt_all(buffer_t *plaintext, cipher_t *cipher, size_t capacity)
|
||||
plaintext->len);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
bfree(plaintext);
|
||||
stream_ctx_release(&cipher_ctx);
|
||||
stream_ctx_release(&cipher_ctx);
|
||||
|
||||
if (err)
|
||||
return CRYPTO_ERROR;
|
||||
}
|
||||
|
||||
#ifdef SS_DEBUG
|
||||
dump("PLAIN", plaintext->data, plaintext->len);
|
||||
@@ -333,8 +332,6 @@ stream_encrypt_all(buffer_t *plaintext, cipher_t *cipher, size_t capacity)
|
||||
dump("NONCE", ciphertext->data, nonce_len);
|
||||
#endif
|
||||
|
||||
stream_ctx_release(&cipher_ctx);
|
||||
|
||||
brealloc(plaintext, nonce_len + ciphertext->len, capacity);
|
||||
memcpy(plaintext->data, ciphertext->data, nonce_len + ciphertext->len);
|
||||
plaintext->len = nonce_len + ciphertext->len;
|
||||
@@ -430,6 +427,12 @@ stream_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity)
|
||||
|
||||
uint8_t *nonce = cipher_ctx.nonce;
|
||||
memcpy(nonce, ciphertext->data, nonce_len);
|
||||
|
||||
if (ppbloom_check((void *)nonce, nonce_len) == 1) {
|
||||
LOGE("crypto: stream: repeat IV detected");
|
||||
return CRYPTO_ERROR;
|
||||
}
|
||||
|
||||
cipher_ctx_set_nonce(&cipher_ctx, nonce, nonce_len, 0);
|
||||
|
||||
if (cipher->method >= SALSA20) {
|
||||
@@ -443,11 +446,10 @@ stream_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity)
|
||||
ciphertext->len - nonce_len);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
bfree(ciphertext);
|
||||
stream_ctx_release(&cipher_ctx);
|
||||
stream_ctx_release(&cipher_ctx);
|
||||
|
||||
if (err)
|
||||
return CRYPTO_ERROR;
|
||||
}
|
||||
|
||||
#ifdef SS_DEBUG
|
||||
dump("PLAIN", plaintext->data, plaintext->len);
|
||||
@@ -455,7 +457,7 @@ stream_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity)
|
||||
dump("NONCE", ciphertext->data, nonce_len);
|
||||
#endif
|
||||
|
||||
stream_ctx_release(&cipher_ctx);
|
||||
ppbloom_add((void *)nonce, nonce_len);
|
||||
|
||||
brealloc(ciphertext, plaintext->len, capacity);
|
||||
memcpy(ciphertext->data, plaintext->data, plaintext->len);
|
||||
@@ -468,7 +470,7 @@ int
|
||||
stream_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)
|
||||
{
|
||||
if (cipher_ctx == NULL)
|
||||
return -1;
|
||||
return CRYPTO_ERROR;
|
||||
|
||||
cipher_t *cipher = cipher_ctx->cipher;
|
||||
|
||||
@@ -511,14 +513,16 @@ stream_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)
|
||||
cipher_ctx->init = 1;
|
||||
|
||||
if (cipher->method >= RC4_MD5) {
|
||||
if (cache_key_exist(nonce_cache, (char *)nonce, nonce_len)) {
|
||||
if (ppbloom_check((void *)nonce, nonce_len) == 1) {
|
||||
LOGE("crypto: stream: repeat IV detected");
|
||||
bfree(ciphertext);
|
||||
return -1;
|
||||
} else {
|
||||
cache_insert(nonce_cache, (char *)nonce, nonce_len, NULL);
|
||||
return CRYPTO_ERROR;
|
||||
}
|
||||
}
|
||||
} else if (cipher_ctx->init == 1) {
|
||||
if (cipher->method >= RC4_MD5) {
|
||||
ppbloom_add((void *)cipher_ctx->nonce, cipher->nonce_len);
|
||||
cipher_ctx->init = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (ciphertext->len <= 0)
|
||||
@@ -550,10 +554,8 @@ stream_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)
|
||||
ciphertext->len);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
bfree(ciphertext);
|
||||
if (err)
|
||||
return CRYPTO_ERROR;
|
||||
}
|
||||
|
||||
#ifdef SS_DEBUG
|
||||
dump("PLAIN", plaintext->data, plaintext->len);
|
||||
|
||||
+5
-2
@@ -766,10 +766,10 @@ main(int argc, char **argv)
|
||||
USE_TTY();
|
||||
|
||||
#ifdef ANDROID
|
||||
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:n:huUvV6",
|
||||
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:n:huUvV6A",
|
||||
long_options, NULL)) != -1) {
|
||||
#else
|
||||
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:n:huUv6",
|
||||
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:n:huUv6A",
|
||||
long_options, NULL)) != -1) {
|
||||
#endif
|
||||
switch (c) {
|
||||
@@ -860,6 +860,9 @@ main(int argc, char **argv)
|
||||
vpn = 1;
|
||||
break;
|
||||
#endif
|
||||
case 'A':
|
||||
FATAL("One time auth has been deprecated. Try AEAD ciphers instead.");
|
||||
break;
|
||||
case '?':
|
||||
// The option character is not recognized.
|
||||
LOGE("Unrecognized option: %s", optarg);
|
||||
|
||||
Reference in New Issue
Block a user