mirror of
https://github.com/CovidBraceletPrj/CovidBracelet.git
synced 2024-12-12 20:26:27 +01:00
222 lines
7.8 KiB
C++
222 lines
7.8 KiB
C++
|
#include <unity.h>
|
||
|
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "exposure-notification.h"
|
||
|
|
||
|
#define TEST_ASSERT_EQUAL_KEY(k1, k2) TEST_ASSERT_EQUAL(0, memcmp(k1.b, k2.b, sizeof(k1.b)))
|
||
|
#define TEST_ASSERT_NOT_EQUAL_KEY(k1, k2) TEST_ASSERT_NOT_EQUAL(0, memcmp(k1.b, k2.b, sizeof(k1.b)))
|
||
|
|
||
|
|
||
|
void test_init(void) {
|
||
|
int ret = en_init(NULL);
|
||
|
TEST_ASSERT_EQUAL(0, ret);
|
||
|
}
|
||
|
|
||
|
void test_get_interval_number(void) {
|
||
|
TEST_ASSERT_EQUAL(0, en_get_interval_number(0));
|
||
|
TEST_ASSERT_EQUAL(0, en_get_interval_number(EN_INTERVAL_LENGTH-1));
|
||
|
TEST_ASSERT_EQUAL(1, en_get_interval_number(EN_INTERVAL_LENGTH));
|
||
|
TEST_ASSERT_EQUAL(42, en_get_interval_number(EN_INTERVAL_LENGTH*42));
|
||
|
}
|
||
|
|
||
|
void test_get_interval_number_at_period_start(void) {
|
||
|
TEST_ASSERT_EQUAL(0, en_get_interval_number_at_period_start(0));
|
||
|
TEST_ASSERT_EQUAL(0, en_get_interval_number_at_period_start(EN_INTERVAL_LENGTH-1));
|
||
|
TEST_ASSERT_EQUAL(0, en_get_interval_number_at_period_start(EN_INTERVAL_LENGTH));
|
||
|
TEST_ASSERT_EQUAL(0, en_get_interval_number_at_period_start(EN_INTERVAL_LENGTH*42));
|
||
|
TEST_ASSERT_EQUAL(EN_TEK_ROLLING_PERIOD, en_get_interval_number_at_period_start(EN_INTERVAL_LENGTH*EN_TEK_ROLLING_PERIOD));
|
||
|
TEST_ASSERT_EQUAL(EN_TEK_ROLLING_PERIOD, en_get_interval_number_at_period_start(EN_INTERVAL_LENGTH*EN_TEK_ROLLING_PERIOD+1));
|
||
|
}
|
||
|
|
||
|
void test_generate_period_key(void) {
|
||
|
ENPeriodKey p1, p2;
|
||
|
en_generate_period_key(&p1);
|
||
|
en_generate_period_key(&p2);
|
||
|
// yes there is a minimal chance that both are the same ;)
|
||
|
TEST_ASSERT_NOT_EQUAL_KEY(p1, p2);
|
||
|
}
|
||
|
|
||
|
void test_get_period_identifier_key(void) {
|
||
|
|
||
|
ENPeriodKey pk;
|
||
|
en_generate_period_key(&pk);
|
||
|
|
||
|
ENPeriodIdentifierKey k1, k2;
|
||
|
en_derive_period_identifier_key(&k1, &pk);
|
||
|
en_derive_period_identifier_key(&k2, &pk);
|
||
|
|
||
|
// This time both should be the same key as the depent on the period key
|
||
|
TEST_ASSERT_EQUAL_KEY(k1, k2);
|
||
|
|
||
|
// BUT: they should be different than the period key itself
|
||
|
TEST_ASSERT_NOT_EQUAL_KEY(k1, pk);
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_get_interval_identifier(void) {
|
||
|
|
||
|
ENPeriodKey pk;
|
||
|
en_generate_period_key(&pk);
|
||
|
|
||
|
ENIntervalNumber iv = en_get_interval_number(0);
|
||
|
|
||
|
ENIntervalIdentifier id1, id2;
|
||
|
en_derive_interval_identifier(&id1, &pk, iv);
|
||
|
en_derive_interval_identifier(&id2, &pk, iv);
|
||
|
|
||
|
// identities should be the same for the same intervalnumber and period key
|
||
|
|
||
|
TEST_ASSERT_EQUAL_KEY(id1, id2);
|
||
|
|
||
|
iv = en_get_interval_number(EN_INTERVAL_LENGTH);
|
||
|
en_derive_interval_identifier(&id2, &pk, iv);
|
||
|
|
||
|
// BUT: they should be different when we are using another interval number
|
||
|
TEST_ASSERT_NOT_EQUAL_KEY(id1, id2);
|
||
|
|
||
|
// They should also be different for another period key but the the same interval number
|
||
|
en_generate_period_key(&pk);
|
||
|
en_derive_interval_identifier(&id1, &pk, iv);
|
||
|
|
||
|
en_generate_period_key(&pk);
|
||
|
en_derive_interval_identifier(&id2, &pk, iv);
|
||
|
|
||
|
TEST_ASSERT_NOT_EQUAL_KEY(id1, id2);
|
||
|
}
|
||
|
|
||
|
void test_get_period_metadata_encryption_key(void) {
|
||
|
|
||
|
ENPeriodKey pk;
|
||
|
en_generate_period_key(&pk);
|
||
|
ENPeriodMetadataEncryptionKey k1, k2;
|
||
|
en_derive_period_metadata_encryption_key(&k1, &pk);
|
||
|
en_derive_period_metadata_encryption_key(&k2, &pk);
|
||
|
|
||
|
// This time both should be the same key as the depent on the period key
|
||
|
TEST_ASSERT_EQUAL_KEY(k1, k2);
|
||
|
|
||
|
// BUT: they should be different than the period key itself
|
||
|
TEST_ASSERT_NOT_EQUAL_KEY(k1, pk);
|
||
|
|
||
|
// and they should also be different than the periodIdentifierKey
|
||
|
ENPeriodIdentifierKey pik;
|
||
|
en_derive_period_identifier_key(&pik, &pk);
|
||
|
TEST_ASSERT_NOT_EQUAL_KEY(k1, pik);
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_en_encrypt_interval_metadata(void) {
|
||
|
|
||
|
ENPeriodKey pk;
|
||
|
en_generate_period_key(&pk);
|
||
|
ENPeriodMetadataEncryptionKey k1;
|
||
|
en_derive_period_metadata_encryption_key(&k1, &pk);
|
||
|
|
||
|
ENIntervalNumber iv = en_get_interval_number(0);
|
||
|
ENIntervalIdentifier id;
|
||
|
en_derive_interval_identifier(&id, &pk, iv);
|
||
|
|
||
|
unsigned char testData[42] = "This is some test data :)";
|
||
|
unsigned char encryptedData[42] = "";
|
||
|
|
||
|
en_encrypt_interval_metadata(&k1, &id, testData, encryptedData, sizeof(testData));
|
||
|
|
||
|
// the original data should not be changed
|
||
|
TEST_ASSERT_EQUAL_CHAR_ARRAY("This is some test data :)", testData, sizeof("This is some test data :)")-1);
|
||
|
|
||
|
// but the encrypted one should be changed
|
||
|
TEST_ASSERT_NOT_EQUAL(0, memcmp(testData, encryptedData, sizeof(testData)));
|
||
|
|
||
|
unsigned char decryptedData[42] = "";
|
||
|
en_decrypt_interval_metadata(&k1, &id, encryptedData, decryptedData, sizeof(testData));
|
||
|
|
||
|
// the decrypted metadata should be the same as the testData
|
||
|
TEST_ASSERT_EQUAL_CHAR_ARRAY(testData, decryptedData, sizeof(testData));
|
||
|
}
|
||
|
|
||
|
void test_identifier_generation_performance(void) {
|
||
|
|
||
|
int runs = 1000000;
|
||
|
|
||
|
for(int i = 0; i < runs; i++) {
|
||
|
ENPeriodKey pk;
|
||
|
en_generate_period_key(&pk);
|
||
|
ENPeriodIdentifierKey ik;
|
||
|
en_derive_period_identifier_key(&ik, &pk);
|
||
|
|
||
|
for(int iv = 0; iv < EN_TEK_ROLLING_PERIOD; iv++) {
|
||
|
ENIntervalNumber intervalNumber = en_get_interval_number(iv);
|
||
|
ENIntervalIdentifier id;
|
||
|
en_derive_interval_identifier(&id, &ik, intervalNumber);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void test_generate_and_derive_period_keys(void) {
|
||
|
// Test multiple generation
|
||
|
ENPeriodKey periodKey;
|
||
|
ENPeriodIdentifierKey periodIdentifierKey;
|
||
|
ENPeriodMetadataEncryptionKey periodMetadaEncryptionKey;
|
||
|
for(int i = 0; i < 10; i++) {
|
||
|
en_generate_and_derive_period_keys(&periodKey, &periodIdentifierKey, &periodMetadaEncryptionKey);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_against_fixtures(void) {
|
||
|
// First define base values
|
||
|
ENIntervalNumber intervalNumber = 2642976;
|
||
|
ENPeriodKey periodKey = {.b = {0x75, 0xc7, 0x34, 0xc6, 0xdd, 0x1a, 0x78, 0x2d, 0xe7, 0xa9, 0x65, 0xda, 0x5e, 0xb9, 0x31, 0x25}};
|
||
|
unsigned char metadata[4] = {0x40, 0x08, 0x00, 0x00};
|
||
|
|
||
|
// define the expected values
|
||
|
ENPeriodIdentifierKey expectedPIK = {.b = {0x18, 0x5a, 0xd9, 0x1d, 0xb6, 0x9e, 0xc7, 0xdd, 0x04, 0x89, 0x60, 0xf1, 0xf3, 0xba, 0x61, 0x75}};
|
||
|
ENPeriodMetadataEncryptionKey expectedPMEK = {.b = {0xd5, 0x7c, 0x46, 0xaf, 0x7a, 0x1d, 0x83, 0x96, 0x5b, 0x9b, 0xed, 0x8b, 0xd1, 0x52, 0x93, 0x6a}};
|
||
|
|
||
|
ENIntervalIdentifier expectedIntervalIdentifier = {.b = {0x8b, 0xe6, 0xcd, 0x37, 0x1c, 0x5c, 0x89, 0x16, 0x04, 0xbf, 0xbe, 0x49, 0xdf, 0x84, 0x50, 0x96}};
|
||
|
unsigned char expectedEncryptedMetadata[4] = {0x72, 0x03, 0x38, 0x74};
|
||
|
|
||
|
|
||
|
ENPeriodIdentifierKey pik;
|
||
|
en_derive_period_identifier_key(&pik, &periodKey);
|
||
|
TEST_ASSERT_EQUAL_KEY(expectedPIK, pik);
|
||
|
|
||
|
ENPeriodMetadataEncryptionKey pmek;
|
||
|
en_derive_period_metadata_encryption_key(&pmek, &periodKey);
|
||
|
TEST_ASSERT_EQUAL_KEY(expectedPMEK, pmek);
|
||
|
|
||
|
ENIntervalIdentifier intervalIdentifier;
|
||
|
en_derive_interval_identifier(&intervalIdentifier, &pik, intervalNumber);
|
||
|
TEST_ASSERT_EQUAL_KEY(expectedIntervalIdentifier, intervalIdentifier);
|
||
|
|
||
|
|
||
|
unsigned char encryptedMetadata[sizeof(metadata)] = {0};
|
||
|
en_encrypt_interval_metadata(&pmek, &intervalIdentifier, metadata, encryptedMetadata, sizeof(metadata));
|
||
|
TEST_ASSERT_EQUAL_CHAR_ARRAY(expectedEncryptedMetadata, encryptedMetadata, sizeof(expectedEncryptedMetadata));
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_exposure_notification() {
|
||
|
UNITY_BEGIN();
|
||
|
RUN_TEST(test_init);
|
||
|
RUN_TEST(test_get_interval_number);
|
||
|
RUN_TEST(test_get_interval_number_at_period_start);
|
||
|
RUN_TEST(test_generate_period_key);
|
||
|
RUN_TEST(test_get_period_identifier_key);
|
||
|
RUN_TEST(test_get_interval_identifier);
|
||
|
RUN_TEST(test_get_period_metadata_encryption_key);
|
||
|
RUN_TEST(test_en_encrypt_interval_metadata);
|
||
|
RUN_TEST(test_generate_and_derive_period_keys);
|
||
|
RUN_TEST(test_against_fixtures);
|
||
|
//RUN_TEST(test_identifier_generation_performance);
|
||
|
UNITY_END();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
int main(int argc, char **argv) {
|
||
|
test_exposure_notification();
|
||
|
return 0;
|
||
|
}
|