| Index: src/trusted/validator/caching/validation_caching_test.cc
|
| diff --git a/src/trusted/validator/caching/validation_caching_test.cc b/src/trusted/validator/caching/validation_caching_test.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3d09a12ff00f5f319866c5eb0fb6d1ec65796fa2
|
| --- /dev/null
|
| +++ b/src/trusted/validator/caching/validation_caching_test.cc
|
| @@ -0,0 +1,194 @@
|
| +/*
|
| + * Copyright (c) 2012 The Native Client Authors. All rights reserved.
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| +#include "gtest/gtest.h"
|
| +
|
| +#include <openssl/crypto/sha/sha.h>
|
| +#include "native_client/src/trusted/validator/caching/hashing_interface.h"
|
| +#include "native_client/src/trusted/validator/caching/validation_signature.h"
|
| +
|
| +void *TestHashCreate(const unsigned char *key, const unsigned int length) {
|
| + SHA256_CTX * ctx = (SHA256_CTX *) malloc(sizeof(SHA256_CTX));
|
| + SHA256_Init(ctx);
|
| + // Peturb the hash with the key - unique keys ensure unique signatures.
|
| + // TODO(ncbray) full HMAC
|
| + SHA256_Update(ctx, key, length);
|
| + return ctx;
|
| +}
|
| +
|
| +void TestHashUpdate(void *ctx, const unsigned char *data,
|
| + const unsigned int length) {
|
| + SHA256_Update((SHA256_CTX *) ctx, data, length);
|
| +}
|
| +
|
| +void TestHashDigest(void *ctx, unsigned char *data, unsigned int *length,
|
| + const unsigned int max_length) {
|
| + unsigned char buffer[SHA256_DIGEST_LENGTH];
|
| + unsigned int actual_length = SHA256_DIGEST_LENGTH;
|
| + if (max_length < actual_length)
|
| + actual_length = max_length;
|
| + SHA256_Final(buffer, (SHA256_CTX *) ctx);
|
| + memcpy(data, buffer, actual_length);
|
| + *length = actual_length;
|
| + free((SHA256_CTX *) ctx);
|
| +}
|
| +
|
| +void InitTestHashingInterface(HashingInterface *hashing) {
|
| + hashing->create = &TestHashCreate;
|
| + hashing->update = &TestHashUpdate;
|
| + hashing->digest = &TestHashDigest;
|
| +}
|
| +
|
| +const unsigned char *code = (const unsigned char*) "foo bar!";
|
| +const unsigned char *code_alt = (const unsigned char*) "barred!!";
|
| +unsigned int code_length = 8;
|
| +
|
| +class ValidationCachingTests : public ::testing::Test {
|
| + protected:
|
| + HashingInterface hashing;
|
| + ValidationInfo info1;
|
| + ValidationInfo info2;
|
| + NaClCPUFeatures cpu_features1;
|
| + NaClCPUFeatures cpu_features2;
|
| + ValidationSignature sig1;
|
| + ValidationSignature sig2;
|
| +
|
| + void SetUp() {
|
| + InitTestHashingInterface(&hashing);
|
| + initInfo(&info1, &cpu_features1);
|
| + initInfo(&info2, &cpu_features2);
|
| + memset(&sig1, 0, sizeof(ValidationSignature));
|
| + memset(&sig2, 0, sizeof(ValidationSignature));
|
| + }
|
| +
|
| + void initInfo(ValidationInfo *info, NaClCPUFeatures *cpu_features) {
|
| + info->key = (unsigned char *) "a man a plan a canal panama";
|
| + info->key_length = 27;
|
| + info->isa = "x86-32";
|
| + info->version = "hello";
|
| + info->cpu_features = cpu_features;
|
| + NaClSetAllCPUFeatures(cpu_features);
|
| + }
|
| +
|
| + void GetSig(ValidationInfo *info, const unsigned char *code,
|
| + unsigned int code_length, ValidationSignature *sig) {
|
| + GetValidationSignature(&hashing, info, code, code_length, sig);
|
| + }
|
| +
|
| + // For debugging.
|
| + void printSig(ValidationSignature *sig) {
|
| + for (unsigned int i = 0; i < sig->length; i++) {
|
| + printf("%2.2x ", sig->data[i]);
|
| + }
|
| + printf("\n");
|
| + }
|
| +
|
| + void checkSanity(ValidationSignature *sig1, ValidationSignature *sig2) {
|
| + // printSig(sig1);
|
| + // printSig(sig2);
|
| + EXPECT_GE(sig1->length, (unsigned int) 16);
|
| + EXPECT_LE(sig1->length, (unsigned int) VALIDATION_SIGNATURE_MAX_LENGTH);
|
| + ASSERT_EQ(sig1->length, sig2->length);
|
| + }
|
| +
|
| + void expectDifferent(ValidationSignature *sig1, ValidationSignature *sig2) {
|
| + checkSanity(sig1, sig2);
|
| + ASSERT_NE(0, memcmp(sig1->data, sig2->data, sig1->length));
|
| + }
|
| +
|
| + void expectSame(ValidationSignature *sig1, ValidationSignature *sig2) {
|
| + checkSanity(sig1, sig2);
|
| + ASSERT_EQ(0, memcmp(sig1->data, sig2->data, sig1->length));
|
| + }
|
| +};
|
| +
|
| +TEST_F(ValidationCachingTests, SetupSanity) {
|
| + ASSERT_EQ(0, memcmp(&sig1, &sig2, sizeof(ValidationSignature)));
|
| +}
|
| +
|
| +// Make sure the signature is repeatable.
|
| +TEST_F(ValidationCachingTests, Identical) {
|
| + GetSig(&info1, code, code_length, &sig1);
|
| + GetSig(&info2, code, code_length, &sig2);
|
| + expectSame(&sig1, &sig2);
|
| +}
|
| +
|
| +// Make sure every byte of the signature is written.
|
| +TEST_F(ValidationCachingTests, TotalOverwrite) {
|
| + memset(&sig1, 0x33, sizeof(ValidationSignature));
|
| + memset(&sig2, 0x55, sizeof(ValidationSignature));
|
| + GetSig(&info1, code, code_length, &sig1);
|
| + GetSig(&info2, code, code_length, &sig2);
|
| + expectSame(&sig1, &sig2);
|
| +}
|
| +
|
| +// Make sure the signature generation obeys null termination for strings.
|
| +TEST_F(ValidationCachingTests, VersionStringTermination) {
|
| + info1.version = "a\0b";
|
| + info2.version = "a\0c";
|
| + GetSig(&info1, code, code_length, &sig1);
|
| + GetSig(&info2, code, code_length, &sig2);
|
| + expectSame(&sig1, &sig2);
|
| +}
|
| +
|
| +// Make sure changing a single input byte changes the signature.
|
| +TEST_F(ValidationCachingTests, PeturbVersion) {
|
| + info2.version = "hell!";
|
| + GetSig(&info1, code, code_length, &sig1);
|
| + GetSig(&info2, code, code_length, &sig2);
|
| + expectDifferent(&sig1, &sig2);
|
| +
|
| + info2.version = "yello";
|
| + GetSig(&info1, code, code_length, &sig1);
|
| + GetSig(&info2, code, code_length, &sig2);
|
| + expectDifferent(&sig1, &sig2);
|
| +}
|
| +
|
| +TEST_F(ValidationCachingTests, PeturbISA) {
|
| + info2.isa = "x86-64";
|
| + GetSig(&info1, code, code_length, &sig1);
|
| + GetSig(&info2, code, code_length, &sig2);
|
| + expectDifferent(&sig1, &sig2);
|
| +}
|
| +
|
| +TEST_F(ValidationCachingTests, PeturbCode) {
|
| + GetSig(&info1, code, code_length, &sig1);
|
| + GetSig(&info2, code_alt, code_length, &sig2);
|
| + expectDifferent(&sig1, &sig2);
|
| +}
|
| +
|
| +TEST_F(ValidationCachingTests, PeturbCodeLength) {
|
| + GetSig(&info1, code, code_length, &sig1);
|
| + GetSig(&info2, code, code_length-1, &sig2);
|
| + expectDifferent(&sig1, &sig2);
|
| +}
|
| +
|
| +TEST_F(ValidationCachingTests, PeturbKey) {
|
| + info2.key = (unsigned char *) "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
| + GetSig(&info1, code, code_length, &sig1);
|
| + GetSig(&info2, code, code_length, &sig2);
|
| + expectDifferent(&sig1, &sig2);
|
| +}
|
| +
|
| +TEST_F(ValidationCachingTests, PeturbKeyLength) {
|
| + info2.key_length -= 1;
|
| + GetSig(&info1, code, code_length, &sig1);
|
| + GetSig(&info2, code, code_length, &sig2);
|
| + expectDifferent(&sig1, &sig2);
|
| +}
|
| +
|
| +TEST_F(ValidationCachingTests, PeturbCPUFeatures) {
|
| + NaClClearCPUFeatures(info2.cpu_features);
|
| + GetSig(&info1, code, code_length, &sig1);
|
| + GetSig(&info2, code, code_length, &sig2);
|
| + expectDifferent(&sig1, &sig2);
|
| +}
|
| +
|
| +// Test driver function.
|
| +int main(int argc, char *argv[]) {
|
| + testing::InitGoogleTest(&argc, argv);
|
| + return RUN_ALL_TESTS();
|
| +}
|
|
|