aboutsummaryrefslogtreecommitdiff
path: root/src/faceauth_tests.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/faceauth_tests.cc')
-rw-r--r--src/faceauth_tests.cc1349
1 files changed, 1028 insertions, 321 deletions
diff --git a/src/faceauth_tests.cc b/src/faceauth_tests.cc
index 32088fa..14a01cb 100644
--- a/src/faceauth_tests.cc
+++ b/src/faceauth_tests.cc
@@ -16,49 +16,44 @@ using std::unique_ptr;
namespace {
+vector<uint8_t> EMBEDDING_VECTOR_NULL(128, 0);
+const vector<uint8_t> EMBEDDING_VECTOR_1(64, 16);
+const vector<uint8_t> EMBEDDING_VECTOR_2(64, (uint8_t)-16);
+
+const uint32_t PROFILE_1 = 1;
+const uint32_t PROFILE_2 = 2;
+const uint32_t PROFILE_3 = 3;
+const uint32_t PROFILE_4 = 4;
+const uint32_t PROFILE_5 = 5;
+const uint32_t PROFILE_6 = 6;
+
class FaceAuthTest: public testing::Test {
+ public:
+ static unique_ptr<nos::NuggetClientInterface> client;
+ static unique_ptr<test_harness::TestHarness> uart_printer;
+
protected:
void SetUp() override;
static void SetUpTestCase();
static void TearDownTestCase();
-
- static unique_ptr<nos::NuggetClientInterface> client;
- static unique_ptr<test_harness::TestHarness> uart_printer;
-
- static const fa_result_t RunTask(const fa_task_t task,
- const fa_embedding_t* embed = NULL,
- const fa_token_t* token = NULL);
- static void Run(const fa_result_t expected, const fa_task_t task,
- const fa_embedding_t* embed = NULL,
- const fa_token_t* token = NULL);
-
- static void LockProfileTest(uint32_t profile1);
- static void UnlockProfileTest(uint32_t profile1);
- static bool IsProfileLocked(uint32_t profile1);
- static void UnockProfileTest(uint32_t profile1);
- static void FullMatchMismatchTest(uint32_t profile1, uint32_t profile2,
- uint32_t slot1, uint32_t slot2);
- static fa_token_t MakeToken(uint32_t profile_id);
-
- static vector<uint64_t> user_ids;
+ static void DisengageGlobalLockout();
};
-vector<uint64_t> FaceAuthTest::user_ids;
-
unique_ptr<nos::NuggetClientInterface> FaceAuthTest::client;
unique_ptr<test_harness::TestHarness> FaceAuthTest::uart_printer;
void FaceAuthTest::SetUpTestCase() {
srand(time(NULL));
- for (int i = 0; i < MAX_NUM_PROFILES; ++i) {
- user_ids.push_back(rand());
- }
uart_printer = test_harness::TestHarness::MakeUnique();
client = nugget_tools::MakeNuggetClient();
client->Open();
EXPECT_TRUE(client->IsOpen()) << "Unable to connect";
+
+ /* We need any embedding vector to have magnitude of 128 */
+ EMBEDDING_VECTOR_NULL[127] = 128;
+ DisengageGlobalLockout();
}
void FaceAuthTest::TearDownTestCase() {
@@ -86,369 +81,1081 @@ uint8_t CalcCrc8(const uint8_t *data, int len)
return (uint8_t)(crc >> 8);
}
-static fa_task_t MakeTask(uint64_t session_id, uint32_t profile_id,
- uint32_t cmd, uint32_t input_data1 = 0,
- uint32_t input_data2 = 0,
- uint32_t version = FACEAUTH_MIN_ABH_VERSION) {
+class Task {
+ public:
+ Task(uint32_t profile_id, uint32_t cmd,
+ uint32_t version = FACEAUTH_MIN_ABH_VERSION) {
+ memset(&task, 0, sizeof(task));
+ task.version = version;
+ task.session_id = 0xFACEBEEFBEEFFACEull;
+ task.profile_id = profile_id;
+ task.cmd = cmd;
+ }
+
+ Task& SetFirst(uint64_t first) {
+ task.input.data.first = first;
+ return *this;
+ }
+
+ Task& SetChallenge(uint64_t challenge) {
+ memcpy(task.input.challenge, &challenge, sizeof(challenge));
+ return *this;
+ }
+
+ Task& Finalize() {
+ task.crc = CalcCrc8(reinterpret_cast<const uint8_t*>(&task),
+ offsetof(struct fa_task_t, crc));
+ return *this;
+ }
+
+ vector<uint8_t> ToBuffer() {
+ vector<uint8_t> buffer;
+ for (size_t i = 0; i < sizeof(fa_task_t); ++i) {
+ buffer.push_back(*(reinterpret_cast<const uint8_t*>(&task) + i));
+ }
+ return buffer;
+ }
+
+ private:
fa_task_t task;
- task.version = version;
- task.session_id = session_id;
- task.profile_id = profile_id;
- task.cmd = cmd;
- task.input.data.first = input_data1;
- task.input.data.second = input_data2;
- task.crc = CalcCrc8(reinterpret_cast<const uint8_t*>(&task),
- offsetof(struct fa_task_t, crc));
- return task;
-}
-
-static fa_embedding_t* MakeEmbedding(uint32_t base, uint32_t version = 1) {
- static fa_embedding_t embed;
- memset(&embed, base, sizeof(fa_embedding_t));
- embed.version = version;
- embed.valid = 0;
- embed.crc = CalcCrc8(reinterpret_cast<const uint8_t*>(&embed),
- offsetof(struct fa_embedding_t, crc));
- return &embed;
-}
-
-static fa_result_t MakeResult(uint64_t session_id, int32_t error,
- uint32_t output_data1 = 0,
- uint32_t output_data2 = 0,
- uint32_t lockout_event = FACEAUTH_LOCKOUT_NOP) {
- fa_result_t result;
- memset(&result, 0, sizeof(fa_result_t));
- result.version = 1;
- result.session_id = session_id;
- result.error = error;
- result.output.data.first = output_data1;
- result.output.data.second = output_data2;
- result.lockout_event = lockout_event;
- result.complete = 1;
- result.crc = CalcCrc8(reinterpret_cast<const uint8_t*>(&result),
- offsetof(struct fa_result_t, crc));
- return result;
-}
-
-fa_token_t FaceAuthTest::MakeToken(uint32_t profile_id) {
+};
+
+class Embedding {
+ public:
+ Embedding() { memset(&embed, 0, sizeof(embed)); }
+ Embedding(vector<uint8_t> base, uint32_t version = 1) {
+ memset(&embed, 0, sizeof(embed));
+ embed.version = version;
+ embed.valid = 0;
+ std::copy(base.begin(), base.end(), &embed.face_id[0]);
+ std::copy(base.begin(), base.end(), &embed.depth_id[0]);
+ }
+
+ void Finalize() {
+ embed.crc = CalcCrc8(reinterpret_cast<const uint8_t*>(&embed),
+ offsetof(struct fa_embedding_t, crc));
+ }
+
+ vector<uint8_t> ToBuffer() {
+ vector<uint8_t> buffer;
+ for (size_t i = 0; i < sizeof(fa_embedding_t); ++i) {
+ buffer.push_back(*(reinterpret_cast<const uint8_t*>(&embed) + i));
+ }
+ return buffer;
+ }
+
+ private:
+ fa_embedding_t embed;
+};
+
+class Token {
+ public:
+ Token() { memset(&token, 0, sizeof(token)); }
+
+ Token(fa_token_t token) : token(token) {}
+
+ Token(uint64_t challenge, uint64_t user_id, uint64_t auth_id) {
+ memset(&token, 0, sizeof(token));
+ token.challenge = challenge;
+ token.user_id = user_id;
+ token.authenticator_id = auth_id;
+ }
+
+ vector<uint8_t> ToBuffer() {
+ vector<uint8_t> buffer;
+ for (size_t i = 0; i < sizeof(fa_token_t); ++i) {
+ buffer.push_back(*(reinterpret_cast<const uint8_t*>(&token) + i));
+ }
+ return buffer;
+ }
+
+ fa_token_t GetRaw() { return token; }
+
+ private:
fa_token_t token;
- token.user_id = user_ids[profile_id];
- return token;
+};
+
+class Result {
+ public:
+ Result() { memset(&result, 0, sizeof(result)); }
+
+ Result(fa_result_t result) : result(result) {}
+
+ Result(int32_t error) {
+ memset(&result, 0, sizeof(result));
+ SetError(error);
+ }
+
+ fa_result_t GetRaw() {
+ Finalize();
+ return result;
+ }
+
+ Result& SetError(int32_t error) {
+ result.error = error;
+ return *this;
+ }
+
+ Result& SetChallenge(uint64_t challenge) {
+ memcpy(result.output.challenge, &challenge, sizeof(challenge));
+ return *this;
+ }
+
+ Result& SetSecond(uint32_t second) {
+ result.output.data.second = second;
+ return *this;
+ }
+
+ Result& SetThird(uint32_t third) {
+ result.output.data.third = third;
+ return *this;
+ }
+
+ uint64_t GetChallenge() {
+ uint64_t challenge;
+ memcpy(&challenge, result.output.challenge, sizeof(challenge));
+ return challenge;
+ }
+
+ uint32_t GetFirst() { return result.output.data.first; }
+ uint32_t GetSecond() { return result.output.data.second; }
+
+ Result& Finalize() {
+ result.version = 1;
+ result.session_id = 0xFACEBEEFBEEFFACEull;
+ result.complete = 1;
+ result.crc = CalcCrc8(reinterpret_cast<const uint8_t*>(&result),
+ offsetof(struct fa_result_t, crc));
+ return *this;
+ }
+
+ protected:
+ fa_result_t result;
+};
+
+static void EXPECT_REQ(Result r1, Result r2) {
+ fa_result_t observed = r1.GetRaw();
+ fa_result_t expected = r2.GetRaw();
+
+ EXPECT_EQ(observed.version, expected.version);
+ EXPECT_EQ(observed.session_id, expected.session_id);
+ EXPECT_EQ(observed.error, expected.error);
+ EXPECT_EQ(observed.output.data.first, expected.output.data.first);
+ EXPECT_EQ(observed.output.data.second, expected.output.data.second);
+ EXPECT_EQ(observed.output.data.third, expected.output.data.third);
+ EXPECT_EQ(observed.complete, expected.complete);
+ EXPECT_EQ(observed.crc, expected.crc);
+}
+
+class ResetLockoutResult : public Result {
+ public:
+ ResetLockoutResult(Result result) : Result(result) {}
+
+ ResetLockoutResult(int32_t error) : Result(error) {}
+
+ ResetLockoutResult& SetLockoutEvent(uint32_t lockout_event) {
+ result.output.data.third = lockout_event;
+ return *this;
+ }
+};
+
+class MigrateResult : public Result {
+ public:
+ MigrateResult(Result result) : Result(result) {}
+
+ MigrateResult(int32_t error) : Result(error) {}
+
+ MigrateResult& SetEmbeddingNum(uint32_t num) {
+ result.output.data.second = num;
+ return *this;
+ }
+
+ MigrateResult& SetMatch(bool m) {
+ result.output.data.third = m;
+ return *this;
+ }
+};
+
+class AuthenticateResult : public Result {
+ public:
+ AuthenticateResult(Result result, Token token)
+ : Result(result), token(token) {}
+
+ AuthenticateResult(int32_t error) : Result(error) {}
+
+ AuthenticateResult& SetMatch(bool m) {
+ result.output.data.first = m;
+ return *this;
+ }
+
+ AuthenticateResult& SetLockoutEvent(uint32_t lockout_event) {
+ result.output.data.third = lockout_event;
+ return *this;
+ }
+
+ Token GetToken() { return token; }
+
+ protected:
+ Token token;
+};
+
+static void EXPECT_AEQ(AuthenticateResult r1, AuthenticateResult r2) {
+ EXPECT_REQ(r1, r2);
+
+ fa_token_t observed = r1.GetToken().GetRaw();
+ fa_token_t expected = r2.GetToken().GetRaw();
+
+ EXPECT_EQ(observed.challenge, expected.challenge);
+ EXPECT_EQ(observed.user_id, expected.user_id);
+ EXPECT_EQ(observed.authenticator_id, expected.authenticator_id);
}
-vector<uint8_t> Task2Buffer(const fa_task_t task, const fa_embedding_t* embed,
- const fa_token_t* token) {
- vector<uint8_t> buffer;
- for (size_t i = 0; i < sizeof(fa_task_t); ++i) {
- buffer.push_back(*(reinterpret_cast<const uint8_t*>(&task) + i));
+class Transaction {
+ public:
+ Transaction(Task task, Embedding embed, Token token)
+ : input_task(task), input_embed(embed), input_token(token) {}
+
+ Transaction& Finalize() {
+ input_task.Finalize();
+ input_embed.Finalize();
+ return *this;
}
- for (size_t i = 0; i < sizeof(fa_embedding_t); ++i) {
- if (embed)
- buffer.push_back(*(reinterpret_cast<const uint8_t*>(embed) + i));
- else
- buffer.push_back(0);
+
+ Transaction& Run() {
+ vector<uint8_t> task = input_task.ToBuffer();
+ vector<uint8_t> embed = input_embed.ToBuffer();
+ vector<uint8_t> token = input_token.ToBuffer();
+
+ vector<uint8_t> buffer_rx;
+ buffer_rx.resize(512);
+
+ vector<uint8_t> buffer_tx;
+ buffer_tx.insert(buffer_tx.end(), task.begin(), task.end());
+ buffer_tx.insert(buffer_tx.end(), embed.begin(), embed.end());
+ buffer_tx.insert(buffer_tx.end(), token.begin(), token.end());
+
+ FaceAuthTest::client->CallApp(APP_ID_FACEAUTH_TEST, 1, buffer_tx,
+ &buffer_rx);
+
+ struct fa_output_t {
+ fa_result_t result;
+ fa_token_t token;
+ } __attribute__((packed));
+
+ fa_output_t output =
+ *(reinterpret_cast<struct fa_output_t*>(buffer_rx.data()));
+
+ output_result = output.result;
+ output_token = output.token;
+
+ return *this;
}
- for (size_t i = 0; i < sizeof(fa_token_t); ++i) {
- if (token)
- buffer.push_back(*(reinterpret_cast<const uint8_t*>(token) + i));
- else
- buffer.push_back(0);
+
+ Result GetResult() { return Result(output_result); }
+ Token GetToken() { return Token(output_token); }
+
+ private:
+ Task input_task;
+ Embedding input_embed;
+ Token input_token;
+ fa_result_t output_result;
+ fa_token_t output_token;
+};
+
+class Device {
+ public:
+ static Result Erase(uint32_t profile_id) {
+ return Transaction(Task(profile_id, FACEAUTH_CMD_ERASE), Embedding(),
+ Token())
+ .Finalize()
+ .Run()
+ .GetResult();
+ }
+
+ static Result GenerateChallenge() {
+ Result ret =
+ Transaction(Task(0, FACEAUTH_CMD_GET_CHALLENGE), Embedding(), Token())
+ .Finalize()
+ .Run()
+ .GetResult();
+ memcpy(&challenge, ret.GetRaw().output.challenge, sizeof(challenge));
+ return ret;
+ }
+
+ static Result RevokeChallenge() {
+ return Transaction(Task(0, FACEAUTH_CMD_REVOKE_CHALLENGE), Embedding(),
+ Token())
+ .Finalize()
+ .Run()
+ .GetResult();
}
- return buffer;
+ static uint64_t GetChallenge() { return challenge; }
+
+ private:
+ static uint64_t challenge;
+};
+
+uint64_t Device::challenge;
+
+void FaceAuthTest::SetUp() {
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i)
+ EXPECT_REQ(Device::Erase(i + 1), Result(FACEAUTH_SUCCESS));
}
-static const fa_result_t Buffer2Result(const vector<uint8_t>& buffer)
-{
- const fa_result_t result = *(reinterpret_cast<const fa_result_t*>(
- buffer.data()));
- return result;
+void FaceAuthTest::DisengageGlobalLockout() {
+ /* Send Auth Token */
+ Result generate_result = Device::GenerateChallenge();
+ EXPECT_REQ(generate_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(Device::GetChallenge()));
+ EXPECT_REQ(Transaction(Task(PROFILE_1, FACEAUTH_CMD_ENROLL).Finalize(),
+ Embedding(EMBEDDING_VECTOR_1, 1),
+ Token(Device::GetChallenge(), 0, 0))
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_CRC));
}
-static void EXPECT_RESULT_EQ(const fa_result_t& r1, const fa_result_t& r2)
-{
- EXPECT_EQ(r1.version, r2.version);
- EXPECT_EQ(r1.session_id, r2.session_id);
- EXPECT_EQ(r1.error, r2.error);
- EXPECT_EQ(r1.output.data.first, r2.output.data.first);
- EXPECT_EQ(r1.output.data.second, r2.output.data.second);
- EXPECT_EQ(r1.lockout_event, r2.lockout_event);
- EXPECT_EQ(r1.complete, r2.complete);
- EXPECT_EQ(r1.crc, r2.crc);
+TEST_F(FaceAuthTest, OldFirmwareVersionShouldError) {
+ EXPECT_REQ(Transaction(Task(PROFILE_1, FACEAUTH_CMD_ERASE,
+ FACEAUTH_MIN_ABH_VERSION - 0x100),
+ Embedding(), Token())
+ .Finalize()
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_VERSION));
}
-const fa_result_t FaceAuthTest::RunTask(const fa_task_t task,
- const fa_embedding_t* embed,
- const fa_token_t* token) {
- vector<uint8_t> buffer_rx;
- buffer_rx.resize(1024);
+TEST_F(FaceAuthTest, NewFirmwareVersionShouldNotError) {
+ EXPECT_REQ(Transaction(Task(PROFILE_1, FACEAUTH_CMD_ERASE,
+ FACEAUTH_MIN_ABH_VERSION + 0x100),
+ Embedding(), Token())
+ .Finalize()
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_SUCCESS));
+}
- vector<uint8_t> buffer_tx = Task2Buffer(task, embed, token);
- FaceAuthTest::client->CallApp(APP_ID_FACEAUTH_TEST, 1, buffer_tx, &buffer_rx);
+TEST_F(FaceAuthTest, TaskCRCErrorShouldBeDetected) {
+ EXPECT_REQ(
+ Transaction(Task(PROFILE_1, FACEAUTH_CMD_ERASE), Embedding(), Token())
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_CRC));
+}
- return Buffer2Result(buffer_rx);
+TEST_F(FaceAuthTest, ZeroChallengeShouldError) {
+ EXPECT_REQ(Transaction(Task(PROFILE_1, FACEAUTH_CMD_ENROLL),
+ Embedding(EMBEDDING_VECTOR_1, 1), Token())
+ .Finalize()
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_INVALID_CHALLENGE));
+ EXPECT_REQ(Transaction(Task(PROFILE_1, FACEAUTH_CMD_SET_FEATURE),
+ Embedding(EMBEDDING_VECTOR_1, 1), Token())
+ .Finalize()
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_INVALID_CHALLENGE));
+ EXPECT_REQ(Transaction(Task(PROFILE_1, FACEAUTH_CMD_CLR_FEATURE),
+ Embedding(EMBEDDING_VECTOR_1, 1), Token())
+ .Finalize()
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_INVALID_CHALLENGE));
}
-void FaceAuthTest::Run(const fa_result_t expected, const fa_task_t task,
- const fa_embedding_t* embed, const fa_token_t* token) {
- EXPECT_RESULT_EQ(expected, RunTask(task, embed, token));
+TEST_F(FaceAuthTest, InvalidChallengeShouldError) {
+ Result generate_result = Device::GenerateChallenge();
+ EXPECT_REQ(generate_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(Device::GetChallenge()));
+
+ EXPECT_REQ(Transaction(Task(PROFILE_1, FACEAUTH_CMD_ENROLL),
+ Embedding(EMBEDDING_VECTOR_1, 1), Token(rand(), 0, 0))
+ .Finalize()
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_INVALID_CHALLENGE));
+ EXPECT_REQ(Transaction(Task(PROFILE_1, FACEAUTH_CMD_SET_FEATURE),
+ Embedding(EMBEDDING_VECTOR_1, 1), Token(rand(), 0, 0))
+ .Finalize()
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_INVALID_CHALLENGE));
+ EXPECT_REQ(Transaction(Task(PROFILE_1, FACEAUTH_CMD_CLR_FEATURE),
+ Embedding(EMBEDDING_VECTOR_1, 1), Token(rand(), 0, 0))
+ .Finalize()
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_INVALID_CHALLENGE));
}
-void FaceAuthTest::SetUp() {
- for (int profiles = 1; profiles <= MAX_NUM_PROFILES; ++profiles) {
- Run(MakeResult(0x0, FACEAUTH_SUCCESS),
- MakeTask(0x0, profiles, FACEAUTH_CMD_ERASE));
+TEST_F(FaceAuthTest, EmbeddingCRCErrorShouldBeDetected) {
+ EXPECT_REQ(Transaction(Task(PROFILE_1, FACEAUTH_CMD_COMP).Finalize(),
+ Embedding(EMBEDDING_VECTOR_1, 1), Token())
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_CRC));
+ EXPECT_REQ(Transaction(Task(PROFILE_1, FACEAUTH_CMD_MIGRATE).Finalize(),
+ Embedding(EMBEDDING_VECTOR_1, 1), Token())
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_CRC));
+
+ Result generate_result = Device::GenerateChallenge();
+ EXPECT_REQ(generate_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(Device::GetChallenge()));
+ EXPECT_REQ(Transaction(Task(PROFILE_1, FACEAUTH_CMD_ENROLL).Finalize(),
+ Embedding(EMBEDDING_VECTOR_1, 1),
+ Token(Device::GetChallenge(), 0, 0))
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_CRC));
+}
+
+TEST_F(FaceAuthTest, InvalidCommandShouldError) {
+ Task task(PROFILE_1, 0);
+ Embedding embed;
+ Token token;
+
+ EXPECT_REQ(Transaction(task, embed, token).Finalize().Run().GetResult(),
+ Result(FACEAUTH_ERR_INVALID_ARGS));
+}
+
+TEST_F(FaceAuthTest, ValidProfileIDTest) {
+ Embedding embed;
+ Token token;
+
+ EXPECT_REQ(Transaction(Task(0, FACEAUTH_CMD_GET_USER_INFO), embed, token)
+ .Finalize()
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_INVALID_ARGS));
+
+ for (int i = 1; i <= MAX_NUM_PROFILES; ++i) {
+ EXPECT_REQ(Transaction(Task(i, FACEAUTH_CMD_GET_USER_INFO), embed, token)
+ .Finalize()
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_SUCCESS));
}
+
+ EXPECT_REQ(Transaction(Task(MAX_NUM_PROFILES + 1, FACEAUTH_CMD_GET_USER_INFO),
+ embed, token)
+ .Finalize()
+ .Run()
+ .GetResult(),
+ Result(FACEAUTH_ERR_INVALID_ARGS));
}
-TEST_F(FaceAuthTest, SimpleMatchMismatchTest) {
- uint64_t session_id = 0xFACE000011110000ull;
- session_id++;
-
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, FACEAUTH_NOMATCH),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_COMP), MakeEmbedding(0x11));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, 0x1),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_ENROLL), MakeEmbedding(0x11));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, FACEAUTH_MATCH),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_COMP), MakeEmbedding(0x11));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_ERASE));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, FACEAUTH_NOMATCH),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_COMP), MakeEmbedding(0x11));
-}
-
-void FaceAuthTest::FullMatchMismatchTest(uint32_t profile1, uint32_t profile2,
- uint32_t slot1, uint32_t slot2) {
- uint64_t session_id = 0xFACE000022220000ull;
- for (uint32_t i = 0; i < 20; ++i) {
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, profile1),
- MakeTask(session_id, profile1, FACEAUTH_CMD_ENROLL),
- MakeEmbedding((i == slot1) ? 0x11 : 0x0));
-
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, profile2),
- MakeTask(session_id, profile2, FACEAUTH_CMD_ENROLL),
- MakeEmbedding((i == slot2) ? 0xAA : 0x0));
- }
-
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, FACEAUTH_MATCH),
- MakeTask(session_id, profile1, FACEAUTH_CMD_COMP), MakeEmbedding(0x11));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, FACEAUTH_NOMATCH),
- MakeTask(session_id, profile1, FACEAUTH_CMD_COMP), MakeEmbedding(0xAA));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, FACEAUTH_NOMATCH),
- MakeTask(session_id, profile2, FACEAUTH_CMD_COMP), MakeEmbedding(0x11));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, FACEAUTH_MATCH),
- MakeTask(session_id, profile2, FACEAUTH_CMD_COMP), MakeEmbedding(0xAA));
+class User {
+ public:
+ User(vector<uint8_t> embed_base) : embed_base(embed_base) {
+ user_id = rand();
+ user_id <<= 32;
+ user_id += rand();
+ }
+
+ User& SetEmbeddingVersion(uint8_t version) {
+ embed_version = version;
+ return *this;
+ }
+
+ User& SetEmbeddingBase(vector<uint8_t> base) {
+ embed_base = base;
+ return *this;
+ }
+
+ User& SetUserID(uint64_t sid) {
+ user_id = sid;
+ return *this;
+ }
+
+ Result GetProfileInfo() {
+ return Transaction(Task(0, FACEAUTH_CMD_GET_PROFILE_INFO), Embedding(),
+ Token(0, user_id, 0))
+ .Finalize()
+ .Run()
+ .GetResult();
+ }
+
+ Result GetUserInfo(uint32_t profile_id) {
+ return Transaction(Task(profile_id, FACEAUTH_CMD_GET_USER_INFO),
+ Embedding(), Token())
+ .Finalize()
+ .Run()
+ .GetResult();
+ }
+
+ Result Enroll(uint32_t profile_id) {
+ Result generate_result = Device::GenerateChallenge();
+ EXPECT_REQ(generate_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(Device::GetChallenge()));
+
+ Result ret = Transaction(Task(profile_id, FACEAUTH_CMD_ENROLL),
+ Embedding(embed_base, embed_version),
+ Token(Device::GetChallenge(), user_id, 0))
+ .Finalize()
+ .Run()
+ .GetResult();
+
+ uint64_t auth_id_temp = ret.GetChallenge();
+ memcpy(&auth_id, &auth_id_temp, sizeof(auth_id));
+ EXPECT_REQ(Device::RevokeChallenge(), Result(FACEAUTH_SUCCESS));
+
+ return ret;
+ }
+
+ MigrateResult Migrate(uint32_t profile_id, bool should_migrate) {
+ return Transaction(
+ Task(profile_id, FACEAUTH_CMD_MIGRATE).SetFirst(should_migrate),
+ Embedding(embed_base, embed_version), Token(0, user_id, 0))
+ .Finalize()
+ .Run()
+ .GetResult();
+ }
+
+ AuthenticateResult Authenticate(uint32_t profile_id) {
+ operation_id = rand();
+ operation_id <<= 32;
+ operation_id += rand();
+
+ Transaction t =
+ Transaction(
+ Task(profile_id, FACEAUTH_CMD_COMP).SetChallenge(operation_id),
+ Embedding(embed_base, embed_version), Token())
+ .Finalize()
+ .Run();
+
+ return AuthenticateResult(t.GetResult(), t.GetToken());
+ }
+
+ ResetLockoutResult ResetLockout(uint32_t profile_id) {
+ Result generate_result = Device::GenerateChallenge();
+ EXPECT_REQ(generate_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(Device::GetChallenge()));
+
+ Result ret =
+ Transaction(Task(profile_id, FACEAUTH_CMD_RESET_LOCKOUT), Embedding(),
+ Token(Device::GetChallenge(), user_id, 0))
+ .Finalize()
+ .Run()
+ .GetResult();
+
+ EXPECT_REQ(Device::RevokeChallenge(), Result(FACEAUTH_SUCCESS));
+
+ return ret;
+ }
+
+ bool IsProfileLocked(uint32_t profile_id) {
+ return (GetUserInfo(profile_id).GetSecond() > 0);
+ }
+
+ void LockProfile(uint32_t profile_id) {
+ vector<uint8_t> original_embed_base = embed_base;
+ embed_base = EMBEDDING_VECTOR_NULL;
+ /* Fail Authentication 4 times */
+ for (int i = 0; i < 4; ++i) {
+ EXPECT_REQ(Authenticate(profile_id),
+ AuthenticateResult(FACEAUTH_SUCCESS).SetMatch(false));
+ }
+
+ /* Fifth Authentication failure should trigger lockout event */
+ EXPECT_REQ(Authenticate(profile_id),
+ AuthenticateResult(FACEAUTH_SUCCESS)
+ .SetMatch(false)
+ .SetLockoutEvent(FACEAUTH_LOCKOUT_ENFORCED));
+
+ embed_base = original_embed_base;
+ }
+
+ uint32_t GetFeature(uint32_t profile_id) {
+ return GetUserInfo(profile_id).GetFirst();
+ }
+
+ Result SetFeature(uint32_t profile_id, uint32_t feature) {
+ Result generate_result = Device::GenerateChallenge();
+ EXPECT_REQ(generate_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(Device::GetChallenge()));
+
+ Result ret =
+ Transaction(
+ Task(profile_id, FACEAUTH_CMD_SET_FEATURE).SetFirst(feature),
+ Embedding(), Token(Device::GetChallenge(), user_id, 0))
+ .Finalize()
+ .Run()
+ .GetResult();
+
+ EXPECT_REQ(Device::RevokeChallenge(), Result(FACEAUTH_SUCCESS));
+
+ return ret;
+ }
+
+ Result ClrFeature(uint32_t profile_id, uint32_t feature) {
+ Result generate_result = Device::GenerateChallenge();
+ EXPECT_REQ(generate_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(Device::GetChallenge()));
+
+ Result ret =
+ Transaction(
+ Task(profile_id, FACEAUTH_CMD_CLR_FEATURE).SetFirst(feature),
+ Embedding(), Token(Device::GetChallenge(), user_id, 0))
+ .Finalize()
+ .Run()
+ .GetResult();
+
+ EXPECT_REQ(Device::RevokeChallenge(), Result(FACEAUTH_SUCCESS));
+
+ return ret;
+ }
+
+ uint64_t GetOperationID() { return operation_id; }
+ uint64_t GetAuthID() { return auth_id; }
+ uint64_t GetUserID() { return user_id; }
+
+ private:
+ uint64_t operation_id;
+ uint64_t auth_id = 0;
+ uint64_t user_id;
+ vector<uint8_t> embed_base;
+ uint8_t embed_version;
+};
+
+class SuccessfulAuthenticateResult : public AuthenticateResult {
+ public:
+ SuccessfulAuthenticateResult(User u) : AuthenticateResult(FACEAUTH_SUCCESS) {
+ token = Token(u.GetOperationID(), u.GetUserID(), u.GetAuthID());
+ SetMatch(true);
+ }
+};
+
+TEST_F(FaceAuthTest, GetProfileInfoTest) {
+ vector<User> users;
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i) {
+ users.push_back(User(EMBEDDING_VECTOR_1));
+ users[i].SetEmbeddingVersion(1);
+ }
+
+ users[0].SetUserID(0x1122334455667788);
+ users[1].SetUserID(0x1122334455667788);
+ users[3].SetUserID(0x1122334455667788);
+
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i) users[i].Enroll(i + 1);
+
+ union {
+ uint8_t map[8] = {0};
+ uint64_t info;
+ };
+
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i) {
+ for (int j = 0; j < MAX_NUM_PROFILES; ++j) {
+ map[i] |= ((users[i].GetUserID() == users[j].GetUserID()) << j);
+ }
+ }
+
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i) {
+ map[MAX_NUM_PROFILES] = map[i];
+ EXPECT_REQ(users[i].GetProfileInfo(),
+ Result(FACEAUTH_SUCCESS).SetChallenge(info));
+ EXPECT_REQ(users[i].GetUserInfo(i + 1),
+ Result(FACEAUTH_SUCCESS).SetThird(map[i]));
+ }
+}
+
+TEST_F(FaceAuthTest, EnrollShouldOnlyAcceptSameUser) {
+ User user1(EMBEDDING_VECTOR_1);
+ user1.SetEmbeddingVersion(1);
+
+ User user2(EMBEDDING_VECTOR_NULL);
+ user2.SetEmbeddingVersion(1);
+
+ /* User 1 Enroll to Profile 1 */
+ Result enroll_result = user1.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
+
+ /* User 2 Enroll to Profile 1 should fail */
+ enroll_result = user2.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result, Result(FACEAUTH_ERR_INVALID_USER_ID));
+
+ /* User 1 Enroll to Profile 1 should be successful */
+ enroll_result = user1.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
+}
+
+TEST_F(FaceAuthTest, EnrollAfterWipeShouldBeSuccessful) {
+ User user1(EMBEDDING_VECTOR_1);
+ user1.SetEmbeddingVersion(1);
+
+ User user2(EMBEDDING_VECTOR_1);
+ user2.SetEmbeddingVersion(1);
+
+ /* Enroll to Profile 1 */
+ Result enroll_result = user1.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
+
+ /* Profile 1 Authentication should now pass */
+ AuthenticateResult auth_result = user1.Authenticate(PROFILE_1);
+ EXPECT_AEQ(auth_result, SuccessfulAuthenticateResult(user1));
+
+ ASSERT_TRUE(nugget_tools::WipeUserData(client.get()));
+
+ /* Enroll to Profile 1 */
+ enroll_result = user2.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user2.GetAuthID()));
+
+ /* Profile 1 Authentication should now pass */
+ auth_result = user2.Authenticate(PROFILE_1);
+ EXPECT_AEQ(auth_result, SuccessfulAuthenticateResult(user2));
+}
+
+TEST_F(FaceAuthTest, ValidUserIDCheck) {
+ User user1(EMBEDDING_VECTOR_1);
+ user1.SetEmbeddingVersion(1);
+
+ User user2(EMBEDDING_VECTOR_1);
+ user2.SetEmbeddingVersion(1);
+
+ /* User 1 Enroll to Profile 1 */
+ Result enroll_result = user1.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
+ /* Set Feature User ID Check */
+ EXPECT_REQ(user1.SetFeature(PROFILE_1, 0), Result(FACEAUTH_SUCCESS));
+ EXPECT_REQ(user2.SetFeature(PROFILE_1, 0),
+ Result(FACEAUTH_ERR_INVALID_USER_ID));
+ /* Clear Feature User ID Check */
+ EXPECT_REQ(user1.ClrFeature(PROFILE_1, 0), Result(FACEAUTH_SUCCESS));
+ EXPECT_REQ(user2.ClrFeature(PROFILE_1, 0),
+ Result(FACEAUTH_ERR_INVALID_USER_ID));
+}
+
+TEST_F(FaceAuthTest, EnrollMismatchVersionShouldFail) {
+ User user1(EMBEDDING_VECTOR_1);
+ user1.SetEmbeddingVersion(1);
+
+ /* Enroll using version 1 to profile 1 */
+ Result enroll_result = user1.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
+
+ /* Enroll using version 2 to the same profile slot should fail */
+ EXPECT_REQ(user1.SetEmbeddingVersion(2).Enroll(PROFILE_1),
+ Result(FACEAUTH_ERR_EMBEDDING_VERSION));
}
TEST_F(FaceAuthTest, SFSFullTest) {
- uint64_t session_id = 0xFACE000033330000ull;
+ User user1(EMBEDDING_VECTOR_1);
+ user1.SetEmbeddingVersion(1);
+
+ /* Enroll to Profile1 20 times */
for (int i = 0; i < 20; ++i) {
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, 0x1),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_ENROLL), MakeEmbedding(0x0));
+ Result enroll_result = user1.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
}
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_ERR_SFS_FULL, 0x1),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_ENROLL), MakeEmbedding(0x0));
+ /* Enrolling one more time should fail */
+ EXPECT_REQ(user1.Enroll(PROFILE_1), Result(FACEAUTH_ERR_SFS_FULL));
}
-void FaceAuthTest::LockProfileTest(uint32_t profile1) {
- uint64_t session_id = 0xFACE000044440000ull;
+TEST_F(FaceAuthTest, SimpleMatchMismatchTest) {
+ User user1(EMBEDDING_VECTOR_1);
+ user1.SetEmbeddingVersion(1);
- for (int i = 0; i < 4; ++i) {
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, FACEAUTH_NOMATCH),
- MakeTask(session_id, profile1, FACEAUTH_CMD_COMP), MakeEmbedding(0x0));
- }
+ /* Profile 1 is empty: authentication will fail */
+ EXPECT_REQ(user1.Authenticate(PROFILE_1),
+ AuthenticateResult(FACEAUTH_SUCCESS).SetMatch(false));
+
+ /* Enroll to Profile 1 */
+ Result enroll_result = user1.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
+
+ /* Profile 1 Authentication should now pass */
+ AuthenticateResult auth_result = user1.Authenticate(PROFILE_1);
+ EXPECT_AEQ(auth_result, SuccessfulAuthenticateResult(user1));
+
+ /* Erase Profile 1*/
+ EXPECT_REQ(Device::Erase(PROFILE_1), Result(FACEAUTH_SUCCESS));
+
+ /* Profile 1 is now empty again: authentication should fail */
+ EXPECT_REQ(user1.Authenticate(PROFILE_1),
+ AuthenticateResult(FACEAUTH_SUCCESS).SetMatch(false));
+}
+
+TEST_F(FaceAuthTest, EmbeddingMismatchVersionComparisonShouldError) {
+ User user1(EMBEDDING_VECTOR_1);
+ user1.SetEmbeddingVersion(1);
+
+ /* Enroll to Profile 1 */
+ Result enroll_result = user1.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
+
+ /* Upgrade Embedding Version for User 1 */
+ user1.SetEmbeddingVersion(2);
+
+ /* Authenticate should now return recalibration error */
+ EXPECT_REQ(user1.Authenticate(PROFILE_1), Result(FACEAUTH_ERR_RECALIBRATE));
+}
+
+TEST_F(FaceAuthTest, MigrateShouldPreventDowngrade) {
+ User user1(EMBEDDING_VECTOR_1);
+ user1.SetEmbeddingVersion(5);
+
+ /* User1: enroll to profile 1 */
+ Result enroll_result = user1.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, FACEAUTH_NOMATCH, 0,
- FACEAUTH_LOCKOUT_ENFORCED),
- MakeTask(session_id, profile1, FACEAUTH_CMD_COMP), MakeEmbedding(0x0));
+ /* User1: authenticate successfully to profile 1 */
+ AuthenticateResult auth_result = user1.Authenticate(PROFILE_1);
+ EXPECT_AEQ(auth_result, SuccessfulAuthenticateResult(user1));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_ERR_THROTTLE, FACEAUTH_NOMATCH),
- MakeTask(session_id, profile1, FACEAUTH_CMD_COMP), MakeEmbedding(0x0));
+ /* User1: downgrade and attempt to migrate to profile 3 */
+ EXPECT_REQ(user1.SetEmbeddingVersion(4).Migrate(PROFILE_3, 0),
+ Result(FACEAUTH_ERR_EMBEDDING_DOWNGRADE));
}
-bool FaceAuthTest::IsProfileLocked(uint32_t profile1) {
- uint64_t session_id = 0xFACE000066660000ull;
+TEST_F(FaceAuthTest, MigrateShouldPreventMismatchVersion) {
+ User user1(EMBEDDING_VECTOR_1);
+ user1.SetEmbeddingVersion(5);
- const fa_result_t observed =
- RunTask(MakeTask(session_id, profile1, FACEAUTH_CMD_GET_USER_INFO));
- const fa_result_t expected =
- MakeResult(session_id, FACEAUTH_SUCCESS, 0, observed.output.data.second);
- EXPECT_RESULT_EQ(expected, observed);
- return observed.output.data.second;
+ /* User1: enroll to profile 1 */
+ Result enroll_result = user1.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
+
+ /* User1: authenticate successfully to profile 1 */
+ AuthenticateResult auth_result = user1.Authenticate(PROFILE_1);
+ EXPECT_AEQ(auth_result, SuccessfulAuthenticateResult(user1));
+
+ /* User1: upgrade and migrate to profile 3 */
+ EXPECT_REQ(user1.SetEmbeddingVersion(6).Migrate(PROFILE_3, 1),
+ MigrateResult(FACEAUTH_SUCCESS).SetEmbeddingNum(1).SetMatch(true));
+ EXPECT_REQ(user1.SetEmbeddingVersion(7).Migrate(PROFILE_3, 0),
+ Result(FACEAUTH_ERR_EMBEDDING_VERSION));
+}
+
+TEST_F(FaceAuthTest, MigrateShouldCopyUserInfo) {
+ User user1(EMBEDDING_VECTOR_1);
+ user1.SetEmbeddingVersion(5);
+
+ /* User1: enroll to profile 1 */
+ Result enroll_result = user1.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
+
+ /* User1: set feature */
+ EXPECT_REQ(user1.SetFeature(PROFILE_1, 0xFACEDEAD), Result(FACEAUTH_SUCCESS));
+
+ /* User1: authenticate successfully to profile 1 */
+ AuthenticateResult auth_result = user1.Authenticate(PROFILE_1);
+ EXPECT_AEQ(auth_result, SuccessfulAuthenticateResult(user1));
+
+ /* User1: migrate to profile 3 */
+ EXPECT_REQ(user1.SetEmbeddingVersion(8).Migrate(PROFILE_3, 1),
+ MigrateResult(FACEAUTH_SUCCESS).SetEmbeddingNum(1).SetMatch(true));
+
+ EXPECT_EQ(0xFACEDEAD, user1.GetFeature(PROFILE_3));
+
+ /* User1: authenticate successfully using profile 3 */
+ auth_result = user1.Authenticate(PROFILE_3);
+ EXPECT_AEQ(auth_result, SuccessfulAuthenticateResult(user1));
}
-void FaceAuthTest::UnlockProfileTest(uint32_t profile1) {
- uint64_t session_id = 0xFACE000077770000ull;
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, 0, 0, FACEAUTH_LOCKOUT_REMOVED),
- MakeTask(session_id, profile1, FACEAUTH_CMD_RESET_LOCKOUT));
+TEST_F(FaceAuthTest, SimpleAuthenticateMigrateFlow) {
+ User user1(EMBEDDING_VECTOR_1);
+ user1.SetEmbeddingVersion(1);
+
+ User user2(EMBEDDING_VECTOR_1);
+ user2.SetEmbeddingVersion(1);
+
+ /* User1: enroll to profile 1 */
+ Result enroll_result = user1.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
+
+ /* User2: enroll to profile 2 */
+ enroll_result = user2.Enroll(PROFILE_2);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user2.GetAuthID()));
+
+ /* User1: authenticate successfully to profile 1 */
+ AuthenticateResult auth_result = user1.Authenticate(PROFILE_1);
+ EXPECT_AEQ(auth_result, SuccessfulAuthenticateResult(user1));
+
+ /* User1: migrate to profile 3 */
+ EXPECT_REQ(user1.Migrate(PROFILE_3, 0), MigrateResult(FACEAUTH_SUCCESS));
+
+ /* User2: authenticate successfully to profile 2 */
+ auth_result = user2.Authenticate(PROFILE_2);
+ EXPECT_AEQ(auth_result, SuccessfulAuthenticateResult(user2));
+
+ /* User2: migrate to profile 3 should fail */
+ EXPECT_REQ(user2.Migrate(PROFILE_3, 0),
+ MigrateResult(FACEAUTH_ERR_INVALID_USER_ID));
+
+ /* User2: migrate to profile 4 */
+ EXPECT_REQ(user2.Migrate(PROFILE_4, 1),
+ MigrateResult(FACEAUTH_SUCCESS).SetEmbeddingNum(1).SetMatch(true));
+ EXPECT_REQ(user2.Migrate(PROFILE_4, 1),
+ MigrateResult(FACEAUTH_SUCCESS).SetEmbeddingNum(2).SetMatch(true));
+}
+
+TEST_F(FaceAuthTest, FiveAuthenticationFailureSequenceTest) {
+ User user1(EMBEDDING_VECTOR_1);
+ user1.SetEmbeddingVersion(1);
+
+ User user2(EMBEDDING_VECTOR_NULL);
+ user2.SetEmbeddingVersion(1);
+
+ /* Enroll to Profile 1 */
+ Result enroll_result = user1.Enroll(PROFILE_1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
+
+ /* Fail Authentication 4 times */
+ for (int i = 0; i < 4; ++i) {
+ EXPECT_REQ(user2.Authenticate(PROFILE_1),
+ AuthenticateResult(FACEAUTH_SUCCESS).SetMatch(false));
+ }
+
+ /* Fifth Authentication failure should trigger lockout event */
+ EXPECT_REQ(user2.Authenticate(PROFILE_1),
+ AuthenticateResult(FACEAUTH_SUCCESS)
+ .SetMatch(false)
+ .SetLockoutEvent(FACEAUTH_LOCKOUT_ENFORCED));
+
+ /* User will be throttled for 30 seconds */
+ Result result = user2.GetUserInfo(PROFILE_1);
+ EXPECT_GE(result.GetSecond(), 25);
+ EXPECT_REQ(
+ result,
+ Result(FACEAUTH_SUCCESS).SetSecond(result.GetSecond()).SetThird(1));
+
+ /* Following Authentication attempt will be throttled */
+ EXPECT_REQ(user2.Authenticate(PROFILE_1),
+ AuthenticateResult(FACEAUTH_ERR_THROTTLE));
+
+ /* Reset Lockout should trigger lockout event */
+ EXPECT_REQ(user1.ResetLockout(PROFILE_1),
+ ResetLockoutResult(FACEAUTH_SUCCESS)
+ .SetLockoutEvent(FACEAUTH_LOCKOUT_REMOVED));
}
TEST_F(FaceAuthTest, ExhaustiveLockoutTest) {
- EXPECT_EQ(IsProfileLocked(1), false);
- EXPECT_EQ(IsProfileLocked(4), false);
- EXPECT_EQ(IsProfileLocked(5), false);
- EXPECT_EQ(IsProfileLocked(6), false);
+ vector<User> users;
- LockProfileTest(1);
- LockProfileTest(5);
- LockProfileTest(6);
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i) {
+ users.push_back(User(EMBEDDING_VECTOR_1).SetEmbeddingVersion(1));
+ Result enroll_result = users[i].Enroll(i + 1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(users[i].GetAuthID()));
+ EXPECT_EQ(users[i].IsProfileLocked(i + 1), false);
+ }
- EXPECT_EQ(IsProfileLocked(1), true);
- EXPECT_EQ(IsProfileLocked(4), false);
- EXPECT_EQ(IsProfileLocked(5), true);
- EXPECT_EQ(IsProfileLocked(6), true);
+ bool lock_test_vectors[6] = {true, false, false, false, true, true};
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i) {
+ if (lock_test_vectors[i]) {
+ users[i].LockProfile(i + 1);
+ }
+ }
- UnlockProfileTest(1);
- UnlockProfileTest(6);
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i) {
+ EXPECT_EQ(users[i].IsProfileLocked(i + 1), lock_test_vectors[i]);
+ }
- EXPECT_EQ(IsProfileLocked(1), false);
- EXPECT_EQ(IsProfileLocked(4), false);
- EXPECT_EQ(IsProfileLocked(5), true);
- EXPECT_EQ(IsProfileLocked(6), false);
+ bool unlock_test_vectors[6] = {true, false, false, false, true, false};
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i) {
+ if (unlock_test_vectors[i]) {
+ users[i].ResetLockout(i + 1);
+ }
+ }
+
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i) {
+ EXPECT_EQ(users[i].IsProfileLocked(i + 1),
+ lock_test_vectors[i] && !unlock_test_vectors[i]);
+ }
}
-TEST_F(FaceAuthTest, ValidProfileUserIDTest) {
- fa_token_t token;
- uint64_t session_id = 0xFACE000088880000ull;
- session_id++;
- token = MakeToken(1);
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, 1),
- MakeTask(session_id, 0, FACEAUTH_CMD_ENROLL), MakeEmbedding(0x0), &token);
-
- for (int i = 1; i <= 6; ++i) {
- session_id++;
- token = MakeToken(i);
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, i),
- MakeTask(session_id, (i % 2) ? i : 0, FACEAUTH_CMD_ENROLL),
- MakeEmbedding(0x0), &token);
- }
-
- session_id++;
- token = MakeToken(2);
- Run(MakeResult(session_id, FACEAUTH_ERR_INVALID_TOKEN),
- MakeTask(session_id, 3, FACEAUTH_CMD_ENROLL), MakeEmbedding(0x0), &token);
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_ERR_SFS_FULL),
- MakeTask(session_id, 0, FACEAUTH_CMD_ENROLL));
-}
-
-TEST_F(FaceAuthTest, InvalidCommandTest) {
- uint64_t session_id = 0xFACE000099990000ull;
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_ERR_INVALID_ARGS),
- MakeTask(session_id, 0x1, 0x0));
-}
-
-TEST_F(FaceAuthTest, SimpleFeatureTest) {
- uint64_t session_id = 0xFACE0000AAAA0000ull;
- uint32_t index = 0;
+TEST_F(FaceAuthTest, ExhaustiveFeatureTest) {
+ vector<User> users;
+
uint32_t feature_msk[MAX_NUM_PROFILES] = {0};
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i) {
+ users.push_back(User(EMBEDDING_VECTOR_NULL).SetEmbeddingVersion(1));
+ Result enroll_result = users[i].Enroll(i + 1);
+ EXPECT_REQ(enroll_result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(users[i].GetAuthID()));
+ }
+ uint32_t index = 0;
for (int k = 0; k < 5; ++k) {
- for (int i = 1; i <= MAX_NUM_PROFILES; ++i) {
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, feature_msk[i - 1]),
- MakeTask(session_id, i, FACEAUTH_CMD_GET_USER_INFO));
- }
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i)
+ EXPECT_EQ(users[i].GetFeature(i + 1), feature_msk[i]);
- for (int i = 1; i <= MAX_NUM_PROFILES; ++i) {
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS),
- MakeTask(session_id, i, FACEAUTH_CMD_SET_FEATURE, (1 << index)));
- feature_msk[i - 1] |= (1 << index);
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i) {
+ EXPECT_REQ(users[i].SetFeature(i + 1, 1 << index),
+ Result(FACEAUTH_SUCCESS));
+ feature_msk[i] |= (1 << index);
index++;
}
}
index = 0;
-
for (int k = 0; k < 5; ++k) {
- for (int i = 1; i <= MAX_NUM_PROFILES; ++i) {
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, feature_msk[i - 1]),
- MakeTask(session_id, i, FACEAUTH_CMD_GET_USER_INFO));
- }
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i)
+ EXPECT_EQ(users[i].GetFeature(i + 1), feature_msk[i]);
- for (int i = 1; i <= MAX_NUM_PROFILES; ++i) {
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS),
- MakeTask(session_id, i, FACEAUTH_CMD_CLR_FEATURE, (1 << index)));
- feature_msk[i - 1] &= ~(1 << index);
+ for (int i = 0; i < MAX_NUM_PROFILES; ++i) {
+ EXPECT_REQ(users[i].ClrFeature(i + 1, 1 << index),
+ Result(FACEAUTH_SUCCESS));
+ feature_msk[i] &= ~(1 << index);
index++;
}
}
}
-TEST_F(FaceAuthTest, EmbeddingVersionTest) {
- uint64_t session_id = 0xFACE0000BBBB0000ull;
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, 1),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_ENROLL), MakeEmbedding(0x11));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, FACEAUTH_MATCH),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_COMP), MakeEmbedding(0x11));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_ERR_RECALIBRATE, FACEAUTH_NOMATCH),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_COMP), MakeEmbedding(0x11, 0x2));
-}
-
-TEST_F(FaceAuthTest, FirmwareVersionTest) {
- uint64_t session_id = 0xFACE0000CCCC0000ull;
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, 1),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_ENROLL), MakeEmbedding(0x11));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_ERR_VERSION, FACEAUTH_NOMATCH),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_COMP, 0, 0, 0x1),
- MakeEmbedding(0x11));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_ERR_VERSION, FACEAUTH_NOMATCH),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_COMP, 0, 0,
- FACEAUTH_MIN_ABH_VERSION - 0x100),
- MakeEmbedding(0x11));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, FACEAUTH_MATCH),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_COMP, 0, 0,
- FACEAUTH_MIN_ABH_VERSION),
- MakeEmbedding(0x11));
- session_id++;
- Run(MakeResult(session_id, FACEAUTH_SUCCESS, FACEAUTH_MATCH),
- MakeTask(session_id, 0x1, FACEAUTH_CMD_COMP, 0, 0,
- FACEAUTH_MIN_ABH_VERSION + 0x100),
- MakeEmbedding(0x11));
+static void FullMatchMismatchTest(uint32_t profile_1, uint32_t profile_2) {
+ User user1(EMBEDDING_VECTOR_1);
+ user1.SetEmbeddingVersion(1);
+
+ User user2(EMBEDDING_VECTOR_NULL);
+ user2.SetEmbeddingVersion(1);
+
+ for (uint32_t i = 0; i < 20; ++i) {
+ Result result;
+ result = user1.SetEmbeddingBase(EMBEDDING_VECTOR_1).Enroll(profile_1);
+ EXPECT_REQ(result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user1.GetAuthID()));
+
+ result = user2.SetEmbeddingBase(EMBEDDING_VECTOR_2).Enroll(profile_2);
+ EXPECT_REQ(result,
+ Result(FACEAUTH_SUCCESS).SetChallenge(user2.GetAuthID()));
+ }
+
+ user1.SetEmbeddingBase(EMBEDDING_VECTOR_1);
+ user2.SetEmbeddingBase(EMBEDDING_VECTOR_2);
+
+ AuthenticateResult auth_result = user1.Authenticate(profile_1);
+ EXPECT_AEQ(auth_result, SuccessfulAuthenticateResult(user1));
+ auth_result = user2.Authenticate(profile_1);
+ EXPECT_REQ(auth_result, AuthenticateResult(FACEAUTH_SUCCESS).SetMatch(false));
+ auth_result = user1.Authenticate(profile_2);
+ EXPECT_REQ(auth_result, AuthenticateResult(FACEAUTH_SUCCESS).SetMatch(false));
+ auth_result = user2.Authenticate(profile_2);
+ EXPECT_AEQ(auth_result, SuccessfulAuthenticateResult(user2));
}
TEST_F(FaceAuthTest, ExhaustiveMatchMismatchTest) {
- FullMatchMismatchTest(1, 6, 0, 19);
- FullMatchMismatchTest(2, 5, 1, 18);
- FullMatchMismatchTest(3, 4, 2, 17);
- SetUp();
- FullMatchMismatchTest(2, 4, 3, 16);
- FullMatchMismatchTest(1, 5, 4, 15);
- FullMatchMismatchTest(3, 6, 5, 14);
- SetUp();
- FullMatchMismatchTest(3, 5, 6, 13);
- FullMatchMismatchTest(1, 4, 7, 12);
- FullMatchMismatchTest(2, 6, 8, 11);
- SetUp();
- FullMatchMismatchTest(3, 6, 9, 10);
+ FullMatchMismatchTest(PROFILE_1, PROFILE_6);
+ FullMatchMismatchTest(PROFILE_2, PROFILE_5);
+ FullMatchMismatchTest(PROFILE_3, PROFILE_4);
}
}