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
177 lines
5.9 KiB
C++
177 lines
5.9 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 <algorithm>
|
|
|
|
#include <gtest/gtest.h>
|
|
#include "extended_key_usage.h"
|
|
#include "input.h"
|
|
|
|
BSSL_NAMESPACE_BEGIN
|
|
|
|
namespace {
|
|
|
|
// Helper method to check if an EKU is present in a std::vector of EKUs.
|
|
bool HasEKU(const std::vector<der::Input> &list, der::Input eku) {
|
|
for (const auto &oid : list) {
|
|
if (oid == eku) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Check that we can read multiple EKUs from an extension.
|
|
TEST(ExtendedKeyUsageTest, ParseEKUExtension) {
|
|
// clang-format off
|
|
const uint8_t raw_extension_value[] = {
|
|
0x30, 0x14, // SEQUENCE (20 bytes)
|
|
0x06, 0x08, // OBJECT IDENTIFIER (8 bytes)
|
|
0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, // 1.3.6.1.5.5.7.3.1
|
|
0x06, 0x08, // OBJECT IDENTIFIER (8 bytes)
|
|
0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02 // 1.3.6.1.5.5.7.3.2
|
|
// end of SEQUENCE
|
|
};
|
|
// clang-format on
|
|
der::Input extension_value(raw_extension_value);
|
|
|
|
std::vector<der::Input> ekus;
|
|
EXPECT_TRUE(ParseEKUExtension(extension_value, &ekus));
|
|
|
|
EXPECT_EQ(2u, ekus.size());
|
|
EXPECT_TRUE(HasEKU(ekus, der::Input(kServerAuth)));
|
|
EXPECT_TRUE(HasEKU(ekus, der::Input(kClientAuth)));
|
|
}
|
|
|
|
// Check that an extension with the same OID present multiple times doesn't
|
|
// cause an error.
|
|
TEST(ExtendedKeyUsageTest, RepeatedOid) {
|
|
// clang-format off
|
|
const uint8_t extension_bytes[] = {
|
|
0x30, 0x14, // SEQUENCE (20 bytes)
|
|
0x06, 0x08, // OBJECT IDENTIFIER (8 bytes)
|
|
0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, // 1.3.6.1.5.5.7.3.1
|
|
0x06, 0x08, // OBJECT IDENTIFIER (8 bytes)
|
|
0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01 // 1.3.6.1.5.5.7.3.1
|
|
};
|
|
// clang-format on
|
|
der::Input extension(extension_bytes);
|
|
|
|
std::vector<der::Input> ekus;
|
|
EXPECT_TRUE(ParseEKUExtension(extension, &ekus));
|
|
EXPECT_EQ(2u, ekus.size());
|
|
for (const auto &eku : ekus) {
|
|
EXPECT_EQ(der::Input(kServerAuth), eku);
|
|
}
|
|
}
|
|
|
|
// Check that parsing an EKU extension which contains a private OID doesn't
|
|
// cause an error.
|
|
TEST(ExtendedKeyUsageTest, ParseEKUExtensionGracefullyHandlesPrivateOids) {
|
|
// clang-format off
|
|
const uint8_t extension_bytes[] = {
|
|
0x30, 0x13, // SEQUENCE (19 bytes)
|
|
0x06, 0x08, // OBJECT IDENTIFIER (8 bytes)
|
|
0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, // 1.3.6.1.5.5.7.3.1
|
|
0x06, 0x07, // OBJECT IDENTIFIER (7 bytes)
|
|
0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79 // 1.3.6.1.4.1.11129
|
|
};
|
|
// clang-format on
|
|
der::Input extension(extension_bytes);
|
|
|
|
std::vector<der::Input> ekus;
|
|
EXPECT_TRUE(ParseEKUExtension(extension, &ekus));
|
|
EXPECT_EQ(2u, ekus.size());
|
|
EXPECT_TRUE(HasEKU(ekus, der::Input(kServerAuth)));
|
|
|
|
const uint8_t google_oid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79};
|
|
der::Input google(google_oid);
|
|
EXPECT_TRUE(HasEKU(ekus, google));
|
|
}
|
|
|
|
// Test a variety of bad inputs.
|
|
|
|
// If the extension value has data following the sequence of oids, parsing it
|
|
// should fail.
|
|
TEST(ExtendedKeyUsageTest, ExtraData) {
|
|
// clang-format off
|
|
const uint8_t extra_data[] = {
|
|
0x30, 0x14, // SEQUENCE (20 bytes)
|
|
0x06, 0x08, // OBJECT IDENTIFIER (8 bytes)
|
|
0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, // 1.3.6.1.5.5.7.3.1
|
|
0x06, 0x08, // OBJECT IDENTIFIER (8 bytes)
|
|
0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, // 1.3.6.1.5.5.7.3.2
|
|
// end of SEQUENCE
|
|
0x02, 0x01, // INTEGER (1 byte)
|
|
0x01 // 1
|
|
};
|
|
// clang-format on
|
|
|
|
std::vector<der::Input> ekus;
|
|
EXPECT_FALSE(ParseEKUExtension(der::Input(extra_data), &ekus));
|
|
}
|
|
|
|
// Check that ParseEKUExtension only accepts a sequence containing only oids.
|
|
// This test case has an integer in the sequence (which should fail). A key
|
|
// difference between this test case and ExtendedKeyUsageTest.ExtraData is where
|
|
// the sequence ends - in this test case the integer is still part of the
|
|
// sequence, while in ExtendedKeyUsageTest.ExtraData the integer is after the
|
|
// sequence.
|
|
TEST(ExtendedKeyUsageTest, NotAnOid) {
|
|
// clang-format off
|
|
const uint8_t not_an_oid[] = {
|
|
0x30, 0x0d, // SEQUENCE (13 bytes)
|
|
0x06, 0x08, // OBJECT IDENTIFIER (8 bytes)
|
|
0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, // 1.3.6.1.5.5.7.3.1
|
|
0x02, 0x01, // INTEGER (1 byte)
|
|
0x01 // 1
|
|
// end of SEQUENCE
|
|
};
|
|
// clang-format on
|
|
|
|
std::vector<der::Input> ekus;
|
|
EXPECT_FALSE(ParseEKUExtension(der::Input(not_an_oid), &ekus));
|
|
}
|
|
|
|
// Checks that the list of oids passed to ParseEKUExtension are in a sequence,
|
|
// instead of one or more oid tag-length-values concatenated together.
|
|
TEST(ExtendedKeyUsageTest, NotASequence) {
|
|
// clang-format off
|
|
const uint8_t not_a_sequence[] = {
|
|
0x06, 0x08, // OBJECT IDENTIFIER (8 bytes)
|
|
0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01 // 1.3.6.1.5.5.7.3.1
|
|
};
|
|
// clang-format on
|
|
|
|
std::vector<der::Input> ekus;
|
|
EXPECT_FALSE(ParseEKUExtension(der::Input(not_a_sequence), &ekus));
|
|
}
|
|
|
|
// A sequence passed into ParseEKUExtension must have at least one oid in it.
|
|
TEST(ExtendedKeyUsageTest, EmptySequence) {
|
|
const uint8_t empty_sequence[] = {0x30, 0x00}; // SEQUENCE (0 bytes)
|
|
|
|
std::vector<der::Input> ekus;
|
|
EXPECT_FALSE(ParseEKUExtension(der::Input(empty_sequence), &ekus));
|
|
}
|
|
|
|
// The extension value must not be empty.
|
|
TEST(ExtendedKeyUsageTest, EmptyExtension) {
|
|
std::vector<der::Input> ekus;
|
|
EXPECT_FALSE(ParseEKUExtension(der::Input(), &ekus));
|
|
}
|
|
|
|
} // namespace
|
|
|
|
BSSL_NAMESPACE_END
|