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..5fe9c9dd2195b5a6b4929617f923f8ec6c1f59c0 |
--- /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) { |
bsy
2012/02/22 01:43:35
either "void* TestHashCreate" or "void *TestHashCr
Nick Bray (chromium)
2012/02/22 03:07:28
Done.
|
+ 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 TestHashEnd(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->end = &TestHashEnd; |
+} |
+ |
+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(); |
+} |