Based on Nekogram. Key additions: - Rebrand to FoxiGram (app name, APK name, applicationId com.foxigram.app) - Embedded Xray (VLESS+Reality) proxy client via JNI libxray.so - Bundled hidden one-tap proxies (LTE + WiFi), read-only in UI - Auto-restore proxy on restart, rebind to active network (LTE/WiFi) - Server credentials externalized to git-ignored XrayServers.java (+ template) - libxray Go source included; compiled .so, keystore, google-services.json ignored
178 lines
5.5 KiB
C++
178 lines
5.5 KiB
C++
// Copyright 2020 The BoringSSL Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <openssl/ctrdrbg.h>
|
|
|
|
#include "../bcm_support.h"
|
|
#include "../fipsmodule/bcm_interface.h"
|
|
#include "../internal.h"
|
|
|
|
#if defined(BORINGSSL_FIPS)
|
|
|
|
#include <atomic>
|
|
|
|
// passive_get_seed_entropy writes |out_entropy_len| bytes of entropy, suitable
|
|
// for seeding a DRBG, to |out_entropy|. It sets |*out_used_cpu| to one if the
|
|
// entropy came directly from the CPU and zero if it came from the OS. It
|
|
// actively obtains entropy from the CPU/OS
|
|
static void passive_get_seed_entropy(uint8_t *out_entropy,
|
|
size_t out_entropy_len,
|
|
int *out_want_additional_input) {
|
|
*out_want_additional_input = 0;
|
|
if (bcm_success(BCM_rand_bytes_hwrng(out_entropy, out_entropy_len))) {
|
|
*out_want_additional_input = 1;
|
|
} else {
|
|
CRYPTO_sysrand_for_seed(out_entropy, out_entropy_len);
|
|
}
|
|
}
|
|
|
|
#define ENTROPY_READ_LEN \
|
|
(/* last_block size */ 16 + CTR_DRBG_ENTROPY_LEN * BORINGSSL_FIPS_OVERREAD)
|
|
|
|
#if defined(OPENSSL_ANDROID)
|
|
|
|
#include <errno.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
#include <sys/un.h>
|
|
#include <unistd.h>
|
|
|
|
// socket_history_t enumerates whether the entropy daemon should be contacted
|
|
// for a given entropy request. Values other than socket_not_yet_attempted are
|
|
// sticky so if the first attempt to read from the daemon fails it's assumed
|
|
// that the daemon is not present and no more attempts will be made. If the
|
|
// first attempt is successful then attempts will be made forever more.
|
|
enum class socket_history_t {
|
|
// initial value, no connections to the entropy daemon have been made yet.
|
|
socket_not_yet_attempted = 0,
|
|
// reading from the entropy daemon was successful
|
|
socket_success,
|
|
// reading from the entropy daemon failed.
|
|
socket_failed,
|
|
};
|
|
|
|
static std::atomic<socket_history_t> g_socket_history{
|
|
socket_history_t::socket_not_yet_attempted};
|
|
|
|
// DAEMON_RESPONSE_LEN is the number of bytes that the entropy daemon replies
|
|
// with.
|
|
#define DAEMON_RESPONSE_LEN 496
|
|
|
|
static_assert(ENTROPY_READ_LEN == DAEMON_RESPONSE_LEN,
|
|
"entropy daemon response length mismatch");
|
|
|
|
static int get_seed_from_daemon(uint8_t *out_entropy, size_t out_entropy_len) {
|
|
// |RAND_need_entropy| should never call this function for more than
|
|
// |DAEMON_RESPONSE_LEN| bytes.
|
|
if (out_entropy_len > DAEMON_RESPONSE_LEN) {
|
|
abort();
|
|
}
|
|
|
|
const socket_history_t socket_history =
|
|
g_socket_history.load(std::memory_order_acquire);
|
|
if (socket_history == socket_history_t::socket_failed) {
|
|
return 0;
|
|
}
|
|
|
|
int ret = 0;
|
|
static const char kSocketPath[] = "/dev/socket/prng_seeder";
|
|
struct sockaddr_un sun;
|
|
uint8_t buffer[DAEMON_RESPONSE_LEN];
|
|
size_t done = 0;
|
|
const int sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
if (sock < 0) {
|
|
goto out;
|
|
}
|
|
|
|
memset(&sun, 0, sizeof(sun));
|
|
sun.sun_family = AF_UNIX;
|
|
static_assert(sizeof(kSocketPath) <= UNIX_PATH_MAX, "kSocketPath too long");
|
|
OPENSSL_memcpy(sun.sun_path, kSocketPath, sizeof(kSocketPath));
|
|
|
|
if (connect(sock, (struct sockaddr *)&sun, sizeof(sun))) {
|
|
goto out;
|
|
}
|
|
|
|
while (done < sizeof(buffer)) {
|
|
ssize_t n;
|
|
do {
|
|
n = read(sock, buffer + done, sizeof(buffer) - done);
|
|
} while (n == -1 && errno == EINTR);
|
|
|
|
if (n < 1) {
|
|
goto out;
|
|
}
|
|
done += n;
|
|
}
|
|
|
|
if (done != DAEMON_RESPONSE_LEN) {
|
|
// The daemon should always write |DAEMON_RESPONSE_LEN| bytes on every
|
|
// connection.
|
|
goto out;
|
|
}
|
|
|
|
assert(out_entropy_len <= DAEMON_RESPONSE_LEN);
|
|
OPENSSL_memcpy(out_entropy, buffer, out_entropy_len);
|
|
ret = 1;
|
|
|
|
out:
|
|
if (socket_history == socket_history_t::socket_not_yet_attempted) {
|
|
socket_history_t expected = socket_history_t::socket_not_yet_attempted;
|
|
// If another thread has already updated |g_socket_history| then we defer
|
|
// to their value.
|
|
g_socket_history.compare_exchange_strong(
|
|
expected,
|
|
(ret == 0) ? socket_history_t::socket_failed
|
|
: socket_history_t::socket_success,
|
|
std::memory_order_release, std::memory_order_relaxed);
|
|
}
|
|
|
|
close(sock);
|
|
return ret;
|
|
}
|
|
|
|
#else
|
|
|
|
static int get_seed_from_daemon(uint8_t *out_entropy, size_t out_entropy_len) {
|
|
return 0;
|
|
}
|
|
|
|
#endif // OPENSSL_ANDROID
|
|
|
|
// RAND_need_entropy is called by the FIPS module when it has blocked because of
|
|
// a lack of entropy. This signal is used as an indication to feed it more.
|
|
void RAND_need_entropy(size_t bytes_needed) {
|
|
uint8_t buf[ENTROPY_READ_LEN];
|
|
size_t todo = sizeof(buf);
|
|
if (todo > bytes_needed) {
|
|
todo = bytes_needed;
|
|
}
|
|
|
|
int want_additional_input;
|
|
if (get_seed_from_daemon(buf, todo)) {
|
|
want_additional_input = 1;
|
|
} else {
|
|
passive_get_seed_entropy(buf, todo, &want_additional_input);
|
|
}
|
|
|
|
if (boringssl_fips_break_test("CRNG")) {
|
|
// This breaks the "continuous random number generator test" defined in FIPS
|
|
// 140-2, section 4.9.2, and implemented in |rand_get_seed|.
|
|
OPENSSL_memset(buf, 0, todo);
|
|
}
|
|
|
|
BCM_rand_load_entropy(buf, todo, want_additional_input);
|
|
}
|
|
|
|
#endif // FIPS
|