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
476 lines
15 KiB
C++
476 lines
15 KiB
C++
// Copyright 2015 The Chromium 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 "parse_values.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
BSSL_NAMESPACE_BEGIN
|
|
namespace der::test {
|
|
|
|
namespace {
|
|
|
|
template <size_t N>
|
|
Input FromStringLiteral(const char (&data)[N]) {
|
|
// Strings are null-terminated. The null terminating byte shouldn't be
|
|
// included in the Input, so the size is N - 1 instead of N.
|
|
return Input(reinterpret_cast<const uint8_t *>(data), N - 1);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST(ParseValuesTest, ParseBool) {
|
|
uint8_t buf[] = {0xFF, 0x00};
|
|
Input value(buf, 1);
|
|
bool out;
|
|
EXPECT_TRUE(ParseBool(value, &out));
|
|
EXPECT_TRUE(out);
|
|
|
|
buf[0] = 0;
|
|
EXPECT_TRUE(ParseBool(value, &out));
|
|
EXPECT_FALSE(out);
|
|
|
|
buf[0] = 1;
|
|
EXPECT_FALSE(ParseBool(value, &out));
|
|
EXPECT_TRUE(ParseBoolRelaxed(value, &out));
|
|
EXPECT_TRUE(out);
|
|
|
|
buf[0] = 0xFF;
|
|
value = Input(buf, 2);
|
|
EXPECT_FALSE(ParseBool(value, &out));
|
|
value = Input(buf, 0);
|
|
EXPECT_FALSE(ParseBool(value, &out));
|
|
}
|
|
|
|
TEST(ParseValuesTest, ParseTimes) {
|
|
GeneralizedTime out;
|
|
|
|
EXPECT_TRUE(ParseUTCTime(FromStringLiteral("140218161200Z"), &out));
|
|
|
|
// DER-encoded UTCTime must end with 'Z'.
|
|
EXPECT_FALSE(ParseUTCTime(FromStringLiteral("140218161200X"), &out));
|
|
|
|
// Check that a negative number (-4 in this case) doesn't get parsed as
|
|
// a 2-digit number.
|
|
EXPECT_FALSE(ParseUTCTime(FromStringLiteral("-40218161200Z"), &out));
|
|
|
|
// Check that numbers with a leading 0 don't get parsed in octal by making
|
|
// the second digit an invalid octal digit (e.g. 09).
|
|
EXPECT_TRUE(ParseUTCTime(FromStringLiteral("090218161200Z"), &out));
|
|
|
|
// Check that the length is validated.
|
|
EXPECT_FALSE(ParseUTCTime(FromStringLiteral("140218161200"), &out));
|
|
EXPECT_FALSE(ParseUTCTime(FromStringLiteral("140218161200Z0"), &out));
|
|
|
|
// Check strictness of UTCTime parsers.
|
|
EXPECT_FALSE(ParseUTCTime(FromStringLiteral("1402181612Z"), &out));
|
|
|
|
// Check format of GeneralizedTime.
|
|
|
|
// Years 0 and 9999 are allowed.
|
|
EXPECT_TRUE(ParseGeneralizedTime(FromStringLiteral("00000101000000Z"), &out));
|
|
EXPECT_EQ(0, out.year);
|
|
EXPECT_TRUE(ParseGeneralizedTime(FromStringLiteral("99991231235960Z"), &out));
|
|
EXPECT_EQ(9999, out.year);
|
|
|
|
// Leap seconds are allowed.
|
|
EXPECT_TRUE(ParseGeneralizedTime(FromStringLiteral("20140218161260Z"), &out));
|
|
|
|
// But nothing larger than a leap second.
|
|
EXPECT_FALSE(
|
|
ParseGeneralizedTime(FromStringLiteral("20140218161261Z"), &out));
|
|
|
|
// Minutes only go up to 59.
|
|
EXPECT_FALSE(
|
|
ParseGeneralizedTime(FromStringLiteral("20140218166000Z"), &out));
|
|
|
|
// Hours only go up to 23.
|
|
EXPECT_FALSE(
|
|
ParseGeneralizedTime(FromStringLiteral("20140218240000Z"), &out));
|
|
// The 0th day of a month is invalid.
|
|
EXPECT_FALSE(
|
|
ParseGeneralizedTime(FromStringLiteral("20140200161200Z"), &out));
|
|
// The 0th month is invalid.
|
|
EXPECT_FALSE(
|
|
ParseGeneralizedTime(FromStringLiteral("20140018161200Z"), &out));
|
|
// Months greater than 12 are invalid.
|
|
EXPECT_FALSE(
|
|
ParseGeneralizedTime(FromStringLiteral("20141318161200Z"), &out));
|
|
|
|
// Some months have 31 days.
|
|
EXPECT_TRUE(ParseGeneralizedTime(FromStringLiteral("20140131000000Z"), &out));
|
|
|
|
// September has only 30 days.
|
|
EXPECT_FALSE(
|
|
ParseGeneralizedTime(FromStringLiteral("20140931000000Z"), &out));
|
|
|
|
// February has only 28 days...
|
|
EXPECT_FALSE(
|
|
ParseGeneralizedTime(FromStringLiteral("20140229000000Z"), &out));
|
|
|
|
// ... unless it's a leap year.
|
|
EXPECT_TRUE(ParseGeneralizedTime(FromStringLiteral("20160229000000Z"), &out));
|
|
|
|
// There aren't any leap days in years divisible by 100...
|
|
EXPECT_FALSE(
|
|
ParseGeneralizedTime(FromStringLiteral("21000229000000Z"), &out));
|
|
|
|
// ...unless it's also divisible by 400.
|
|
EXPECT_TRUE(ParseGeneralizedTime(FromStringLiteral("20000229000000Z"), &out));
|
|
|
|
// Check more perverse invalid inputs.
|
|
|
|
// Check that trailing null bytes are not ignored.
|
|
EXPECT_FALSE(
|
|
ParseGeneralizedTime(FromStringLiteral("20001231010203Z\0"), &out));
|
|
|
|
// Check what happens when a null byte is in the middle of the input.
|
|
EXPECT_FALSE(ParseGeneralizedTime(FromStringLiteral("200\0"
|
|
"1231010203Z"),
|
|
&out));
|
|
|
|
// The year can't be in hex.
|
|
EXPECT_FALSE(
|
|
ParseGeneralizedTime(FromStringLiteral("0x201231000000Z"), &out));
|
|
|
|
// The last byte must be 'Z'.
|
|
EXPECT_FALSE(
|
|
ParseGeneralizedTime(FromStringLiteral("20001231000000X"), &out));
|
|
|
|
// Check that the length is validated.
|
|
EXPECT_FALSE(ParseGeneralizedTime(FromStringLiteral("20140218161200"), &out));
|
|
EXPECT_FALSE(
|
|
ParseGeneralizedTime(FromStringLiteral("20140218161200Z0"), &out));
|
|
}
|
|
|
|
TEST(ParseValuesTest, TimesCompare) {
|
|
GeneralizedTime time1;
|
|
GeneralizedTime time2;
|
|
GeneralizedTime time3;
|
|
|
|
ASSERT_TRUE(
|
|
ParseGeneralizedTime(FromStringLiteral("20140218161200Z"), &time1));
|
|
// Test that ParseUTCTime correctly normalizes the year.
|
|
ASSERT_TRUE(ParseUTCTime(FromStringLiteral("150218161200Z"), &time2));
|
|
ASSERT_TRUE(
|
|
ParseGeneralizedTime(FromStringLiteral("20160218161200Z"), &time3));
|
|
EXPECT_TRUE(time1 < time2);
|
|
EXPECT_TRUE(time2 < time3);
|
|
|
|
EXPECT_TRUE(time2 > time1);
|
|
EXPECT_TRUE(time2 >= time1);
|
|
EXPECT_TRUE(time2 <= time3);
|
|
EXPECT_TRUE(time1 <= time1);
|
|
EXPECT_TRUE(time1 >= time1);
|
|
}
|
|
|
|
TEST(ParseValuesTest, UTCTimeRange) {
|
|
GeneralizedTime time;
|
|
ASSERT_TRUE(
|
|
ParseGeneralizedTime(FromStringLiteral("20140218161200Z"), &time));
|
|
EXPECT_TRUE(time.InUTCTimeRange());
|
|
|
|
time.year = 1950;
|
|
EXPECT_TRUE(time.InUTCTimeRange());
|
|
|
|
time.year = 1949;
|
|
EXPECT_FALSE(time.InUTCTimeRange());
|
|
|
|
time.year = 2049;
|
|
EXPECT_TRUE(time.InUTCTimeRange());
|
|
|
|
time.year = 2050;
|
|
EXPECT_FALSE(time.InUTCTimeRange());
|
|
}
|
|
|
|
struct Uint64TestData {
|
|
bool should_pass;
|
|
const uint8_t input[9];
|
|
size_t length;
|
|
uint64_t expected_value = 0;
|
|
};
|
|
|
|
const Uint64TestData kUint64TestData[] = {
|
|
{true, {0x00}, 1, 0},
|
|
// This number fails because it is not a minimal representation.
|
|
{false, {0x00, 0x00}, 2},
|
|
{true, {0x01}, 1, 1},
|
|
{false, {0xFF}, 1},
|
|
{true, {0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 8, INT64_MAX},
|
|
{true,
|
|
{0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
9,
|
|
UINT64_MAX},
|
|
// This number fails because it is negative.
|
|
{false, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 8},
|
|
{false, {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 8},
|
|
{false, {0x00, 0x01}, 2},
|
|
{false, {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}, 9},
|
|
{false, {0}, 0},
|
|
};
|
|
|
|
TEST(ParseValuesTest, ParseUint64) {
|
|
for (size_t i = 0; i < std::size(kUint64TestData); i++) {
|
|
const Uint64TestData &test_case = kUint64TestData[i];
|
|
SCOPED_TRACE(i);
|
|
|
|
uint64_t result;
|
|
EXPECT_EQ(test_case.should_pass,
|
|
ParseUint64(Input(test_case.input, test_case.length), &result));
|
|
if (test_case.should_pass) {
|
|
EXPECT_EQ(test_case.expected_value, result);
|
|
}
|
|
}
|
|
}
|
|
|
|
struct Uint8TestData {
|
|
bool should_pass;
|
|
const uint8_t input[9];
|
|
size_t length;
|
|
uint8_t expected_value = 0;
|
|
};
|
|
|
|
const Uint8TestData kUint8TestData[] = {
|
|
{true, {0x00}, 1, 0},
|
|
// This number fails because it is not a minimal representation.
|
|
{false, {0x00, 0x00}, 2},
|
|
{true, {0x01}, 1, 1},
|
|
{false, {0x01, 0xFF}, 2},
|
|
{false, {0x03, 0x83}, 2},
|
|
{true, {0x7F}, 1, 0x7F},
|
|
{true, {0x00, 0xFF}, 2, 0xFF},
|
|
// This number fails because it is negative.
|
|
{false, {0xFF}, 1},
|
|
{false, {0x80}, 1},
|
|
{false, {0x00, 0x01}, 2},
|
|
{false, {0}, 0},
|
|
};
|
|
|
|
TEST(ParseValuesTest, ParseUint8) {
|
|
for (size_t i = 0; i < std::size(kUint8TestData); i++) {
|
|
const Uint8TestData &test_case = kUint8TestData[i];
|
|
SCOPED_TRACE(i);
|
|
|
|
uint8_t result;
|
|
EXPECT_EQ(test_case.should_pass,
|
|
ParseUint8(Input(test_case.input, test_case.length), &result));
|
|
if (test_case.should_pass) {
|
|
EXPECT_EQ(test_case.expected_value, result);
|
|
}
|
|
}
|
|
}
|
|
|
|
struct IsValidIntegerTestData {
|
|
bool should_pass;
|
|
const uint8_t input[2];
|
|
size_t length;
|
|
bool negative = false;
|
|
};
|
|
|
|
const IsValidIntegerTestData kIsValidIntegerTestData[] = {
|
|
// Empty input (invalid DER).
|
|
{false, {0x00}, 0},
|
|
|
|
// The correct encoding for zero.
|
|
{true, {0x00}, 1, false},
|
|
|
|
// Invalid representation of zero (not minimal)
|
|
{false, {0x00, 0x00}, 2},
|
|
|
|
// Valid single byte negative numbers.
|
|
{true, {0x80}, 1, true},
|
|
{true, {0xFF}, 1, true},
|
|
|
|
// Non-minimal negative number.
|
|
{false, {0xFF, 0x80}, 2},
|
|
|
|
// Positive number with a legitimate leading zero.
|
|
{true, {0x00, 0x80}, 2, false},
|
|
|
|
// A legitimate negative number that starts with FF (MSB of second byte is
|
|
// 0 so OK).
|
|
{true, {0xFF, 0x7F}, 2, true},
|
|
};
|
|
|
|
TEST(ParseValuesTest, IsValidInteger) {
|
|
for (size_t i = 0; i < std::size(kIsValidIntegerTestData); i++) {
|
|
const auto &test_case = kIsValidIntegerTestData[i];
|
|
SCOPED_TRACE(i);
|
|
|
|
bool negative;
|
|
EXPECT_EQ(
|
|
test_case.should_pass,
|
|
IsValidInteger(Input(test_case.input, test_case.length), &negative));
|
|
if (test_case.should_pass) {
|
|
EXPECT_EQ(test_case.negative, negative);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Tests parsing an empty BIT STRING.
|
|
TEST(ParseValuesTest, ParseBitStringEmptyNoUnusedBits) {
|
|
const uint8_t kData[] = {0x00};
|
|
|
|
std::optional<BitString> bit_string = ParseBitString(Input(kData));
|
|
ASSERT_TRUE(bit_string.has_value());
|
|
|
|
EXPECT_EQ(0u, bit_string->unused_bits());
|
|
EXPECT_EQ(0u, bit_string->bytes().size());
|
|
|
|
EXPECT_FALSE(bit_string->AssertsBit(0));
|
|
EXPECT_FALSE(bit_string->AssertsBit(1));
|
|
EXPECT_FALSE(bit_string->AssertsBit(3));
|
|
}
|
|
|
|
// Tests parsing an empty BIT STRING that incorrectly claims one unused bit.
|
|
TEST(ParseValuesTest, ParseBitStringEmptyOneUnusedBit) {
|
|
const uint8_t kData[] = {0x01};
|
|
|
|
std::optional<BitString> bit_string = ParseBitString(Input(kData));
|
|
EXPECT_FALSE(bit_string.has_value());
|
|
}
|
|
|
|
// Tests parsing an empty BIT STRING that is not minmally encoded (the entire
|
|
// last byte is comprised of unused bits).
|
|
TEST(ParseValuesTest, ParseBitStringNonEmptyTooManyUnusedBits) {
|
|
const uint8_t kData[] = {0x08, 0x00};
|
|
|
|
std::optional<BitString> bit_string = ParseBitString(Input(kData));
|
|
EXPECT_FALSE(bit_string.has_value());
|
|
}
|
|
|
|
// Tests parsing a BIT STRING of 7 bits each of which are 1.
|
|
TEST(ParseValuesTest, ParseBitStringSevenOneBits) {
|
|
const uint8_t kData[] = {0x01, 0xFE};
|
|
|
|
std::optional<BitString> bit_string = ParseBitString(Input(kData));
|
|
ASSERT_TRUE(bit_string.has_value());
|
|
|
|
EXPECT_EQ(1u, bit_string->unused_bits());
|
|
EXPECT_EQ(1u, bit_string->bytes().size());
|
|
EXPECT_EQ(0xFE, bit_string->bytes()[0]);
|
|
|
|
EXPECT_TRUE(bit_string->AssertsBit(0));
|
|
EXPECT_TRUE(bit_string->AssertsBit(1));
|
|
EXPECT_TRUE(bit_string->AssertsBit(2));
|
|
EXPECT_TRUE(bit_string->AssertsBit(3));
|
|
EXPECT_TRUE(bit_string->AssertsBit(4));
|
|
EXPECT_TRUE(bit_string->AssertsBit(5));
|
|
EXPECT_TRUE(bit_string->AssertsBit(6));
|
|
EXPECT_FALSE(bit_string->AssertsBit(7));
|
|
EXPECT_FALSE(bit_string->AssertsBit(8));
|
|
}
|
|
|
|
// Tests parsing a BIT STRING of 7 bits each of which are 1. The unused bit
|
|
// however is set to 1, which is an invalid encoding.
|
|
TEST(ParseValuesTest, ParseBitStringSevenOneBitsUnusedBitIsOne) {
|
|
const uint8_t kData[] = {0x01, 0xFF};
|
|
|
|
std::optional<BitString> bit_string = ParseBitString(Input(kData));
|
|
EXPECT_FALSE(bit_string.has_value());
|
|
}
|
|
|
|
TEST(ParseValuesTest, ParseIA5String) {
|
|
const uint8_t valid_der[] = {0x46, 0x6f, 0x6f, 0x20, 0x62,
|
|
0x61, 0x72, 0x01, 0x7f};
|
|
std::string s;
|
|
EXPECT_TRUE(ParseIA5String(der::Input(valid_der), &s));
|
|
EXPECT_EQ("Foo bar\x01\x7f", s);
|
|
|
|
// 0x80 is not a valid character in IA5String.
|
|
const uint8_t invalid_der[] = {0x46, 0x6f, 0x80, 0x20, 0x62, 0x61, 0x72};
|
|
EXPECT_FALSE(ParseIA5String(der::Input(invalid_der), &s));
|
|
}
|
|
|
|
TEST(ParseValuesTest, ParseVisibleString) {
|
|
const uint8_t valid_der[] = {0x46, 0x6f, 0x6f, 0x20, 0x62, 0x61, 0x72, 0x7e};
|
|
std::string s;
|
|
EXPECT_TRUE(ParseVisibleString(der::Input(valid_der), &s));
|
|
EXPECT_EQ("Foo bar\x7e", s);
|
|
|
|
// 0x7f is not a valid character in VisibleString
|
|
const uint8_t invalid_der[] = {0x46, 0x6f, 0x7f, 0x20, 0x62, 0x61, 0x72};
|
|
EXPECT_FALSE(ParseVisibleString(der::Input(invalid_der), &s));
|
|
|
|
// 0x1f is not a valid character in VisibleString
|
|
const uint8_t invalid_der2[] = {0x46, 0x6f, 0x1f, 0x20, 0x62, 0x61, 0x72};
|
|
EXPECT_FALSE(ParseVisibleString(der::Input(invalid_der2), &s));
|
|
}
|
|
|
|
TEST(ParseValuesTest, ParsePrintableString) {
|
|
const uint8_t valid_der[] = {0x46, 0x6f, 0x6f, 0x20, 0x62, 0x61, 0x72};
|
|
std::string s;
|
|
EXPECT_TRUE(ParsePrintableString(der::Input(valid_der), &s));
|
|
EXPECT_EQ("Foo bar", s);
|
|
|
|
// 0x5f '_' is not a valid character in PrintableString.
|
|
const uint8_t invalid_der[] = {0x46, 0x6f, 0x5f, 0x20, 0x62, 0x61, 0x72};
|
|
EXPECT_FALSE(ParsePrintableString(der::Input(invalid_der), &s));
|
|
}
|
|
|
|
TEST(ParseValuesTest, ParseTeletexStringAsLatin1) {
|
|
const uint8_t valid_der[] = {0x46, 0x6f, 0xd6, 0x20, 0x62, 0x61, 0x72};
|
|
std::string s;
|
|
EXPECT_TRUE(ParseTeletexStringAsLatin1(der::Input(valid_der), &s));
|
|
EXPECT_EQ("FoÖ bar", s);
|
|
}
|
|
|
|
TEST(ParseValuesTest, ParseBmpString) {
|
|
const uint8_t valid_der[] = {0x00, 0x66, 0x00, 0x6f, 0x00, 0x6f,
|
|
0x00, 0x62, 0x00, 0x61, 0x00, 0x72};
|
|
std::string s;
|
|
EXPECT_TRUE(ParseBmpString(der::Input(valid_der), &s));
|
|
EXPECT_EQ("foobar", s);
|
|
|
|
const uint8_t valid_nonascii_der[] = {0x27, 0x28, 0x26, 0xa1, 0x2b, 0x50};
|
|
EXPECT_TRUE(ParseBmpString(der::Input(valid_nonascii_der), &s));
|
|
EXPECT_EQ("✨⚡⭐", s);
|
|
|
|
// BmpString must encode characters in pairs of 2 bytes.
|
|
const uint8_t invalid_odd_der[] = {0x00, 0x66, 0x00, 0x6f, 0x00};
|
|
EXPECT_FALSE(ParseBmpString(der::Input(invalid_odd_der), &s));
|
|
|
|
// UTF-16BE encoding of U+1D11E, MUSICAL SYMBOL G CLEF, which is not valid in
|
|
// UCS-2.
|
|
const uint8_t invalid_bmp_valid_utf16_with_surrogate[] = {0xd8, 0x34, 0xdd,
|
|
0x1e};
|
|
EXPECT_FALSE(
|
|
ParseBmpString(der::Input(invalid_bmp_valid_utf16_with_surrogate), &s));
|
|
}
|
|
|
|
TEST(ParseValuesTest, ParseUniversalString) {
|
|
const uint8_t valid_der[] = {0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x6f,
|
|
0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x62,
|
|
0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x72};
|
|
std::string s;
|
|
EXPECT_TRUE(ParseUniversalString(der::Input(valid_der), &s));
|
|
EXPECT_EQ("foobar", s);
|
|
|
|
const uint8_t valid_non_ascii_der[] = {0x0, 0x1, 0xf4, 0xe, 0x0, 0x0, 0x0,
|
|
0x20, 0x0, 0x1, 0xd1, 0x1e, 0x0, 0x0,
|
|
0x26, 0x69, 0x0, 0x0, 0x26, 0x6b};
|
|
EXPECT_TRUE(ParseUniversalString(der::Input(valid_non_ascii_der), &s));
|
|
EXPECT_EQ("🐎 𝄞♩♫", s);
|
|
|
|
// UniversalString must encode characters in groups of 4 bytes.
|
|
const uint8_t invalid_non_4_multiple_der[] = {0x00, 0x00, 0x00,
|
|
0x66, 0x00, 0x00};
|
|
EXPECT_FALSE(
|
|
ParseUniversalString(der::Input(invalid_non_4_multiple_der), &s));
|
|
}
|
|
|
|
} // namespace der::test
|
|
BSSL_NAMESPACE_END
|