aboutsummaryrefslogtreecommitdiffstats
path: root/libparc/parc/security/test/test_parc_InMemoryVerifier.c
diff options
context:
space:
mode:
Diffstat (limited to 'libparc/parc/security/test/test_parc_InMemoryVerifier.c')
-rwxr-xr-xlibparc/parc/security/test/test_parc_InMemoryVerifier.c417
1 files changed, 417 insertions, 0 deletions
diff --git a/libparc/parc/security/test/test_parc_InMemoryVerifier.c b/libparc/parc/security/test/test_parc_InMemoryVerifier.c
new file mode 100755
index 00000000..81baebc7
--- /dev/null
+++ b/libparc/parc/security/test/test_parc_InMemoryVerifier.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * 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:
+ *
+ * http://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 the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../parc_InMemoryVerifier.c"
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_BufferComposer.h>
+#include <parc/security/parc_Security.h>
+
+#include <parc/security/parc_Pkcs12KeyStore.h>
+#include <parc/security/parc_KeyStore.h>
+#include <parc/security/parc_PublicKeySigner.h>
+#include <parc/security/parc_Signer.h>
+
+#include <fcntl.h>
+#include <LongBow/unit-test.h>
+
+LONGBOW_TEST_RUNNER(parc_InMemoryVerifier)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_InMemoryVerifier)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_InMemoryVerifier)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ parcSecurity_Init();
+ LONGBOW_RUN_TEST_CASE(Global, parcInMemoryVerifier_Create);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ parcSecurity_Fini();
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, parcInMemoryVerifier_Create)
+{
+ PARCInMemoryVerifier *verifier = parcInMemoryVerifier_Create();
+
+ assertNotNull(verifier, "Got null result from parcInMemoryVerifier_Create");
+
+ parcInMemoryVerifier_Release(&verifier);
+}
+
+// ===========
+// We use the known keys on disk for these tests
+
+typedef struct test_data {
+ PARCSigner *signer;
+ PARCInMemoryVerifier *inMemoryInterface;
+} TestData;
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, parcInMemoryVerifier_AddKeyId);
+ LONGBOW_RUN_TEST_CASE(Local, parcInMemoryVerifier_GetCryptoHasher);
+ LONGBOW_RUN_TEST_CASE(Local, parcInMemoryVerifier_AllowedCryptoSuite_RSA);
+
+ LONGBOW_RUN_TEST_CASE(Local, parcInMemoryVerifier_RemoveKeyId);
+ LONGBOW_RUN_TEST_CASE(Local, parcInMemoryVerifier_VerifySignature);
+ LONGBOW_RUN_TEST_CASE(Local, parcInMemoryVerifier_VerifySignature_BadHashAlg);
+ LONGBOW_RUN_TEST_CASE(Local, parcInMemoryVerifier_VerifySignature_BadSigAlg);
+ LONGBOW_RUN_TEST_CASE(Local, parcInMemoryVerifier_VerifySignature_BadHash);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ parcSecurity_Init();
+
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open("test_rsa.p12", "blueberry", PARCCryptoHashType_SHA256);
+ PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore);
+ parcPkcs12KeyStore_Release(&publicKeyStore);
+
+ PARCPublicKeySigner *signer = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_RSA_SHA256);
+ parcKeyStore_Release(&keyStore);
+
+ data->signer = parcSigner_Create(signer, PARCPublicKeySignerAsSigner);
+ parcPublicKeySigner_Release(&signer);
+ assertNotNull(data->signer, "Got null result from opening openssl pkcs12 file");
+
+ data->inMemoryInterface = parcInMemoryVerifier_Create();
+
+ longBowTestCase_SetClipBoardData(testCase, data);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ parcInMemoryVerifier_Release(&data->inMemoryInterface);
+ parcSigner_Release(&data->signer);
+ parcMemory_Deallocate((void **) &data);
+
+ parcSecurity_Fini();
+
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Local, parcInMemoryVerifier_GetCryptoHasher)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCKey *key = parcSigner_CreatePublicKey(data->signer);
+ _parcInMemoryVerifier_AddKey(data->inMemoryInterface, key);
+
+ PARCCryptoHasher *hasher = _parcInMemoryVerifier_GetCryptoHasher(data->inMemoryInterface, parcKey_GetKeyId(key), PARCCryptoHashType_SHA256);
+ parcKey_Release(&key);
+ assertNotNull(hasher, "Got a null hasher");
+}
+
+LONGBOW_TEST_CASE(Local, parcInMemoryVerifier_AddKeyId)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ // create the key with copies of the byte buffers
+ PARCKey *key = parcSigner_CreatePublicKey(data->signer);
+
+ _parcInMemoryVerifier_AddKey(data->inMemoryInterface, key);
+
+ // now do something that uses the key
+ bool success = _parcInMemoryVerifier_AllowedCryptoSuite(data->inMemoryInterface, parcKey_GetKeyId(key), PARCCryptoSuite_RSA_SHA256);
+ parcKey_Release(&key);
+ assertTrue(success, "Should have allowed PARCCryptoSuite_RSA_SHA256 for an RSA keystore");
+}
+
+LONGBOW_TEST_CASE(Local, parcInMemoryVerifier_AllowedCryptoSuite_RSA)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCKey *key = parcSigner_CreatePublicKey(data->signer);
+ _parcInMemoryVerifier_AddKey(data->inMemoryInterface, key);
+
+ // now do something that uses the key
+ bool success = _parcInMemoryVerifier_AllowedCryptoSuite(data->inMemoryInterface, parcKey_GetKeyId(key), PARCCryptoSuite_RSA_SHA256);
+ parcKey_Release(&key);
+ assertTrue(success, "Should have allowed PARCCryptoSuite_RSA_SHA256 for an RSA keystore");
+}
+
+LONGBOW_TEST_CASE(Local, parcInMemoryVerifier_RemoveKeyId)
+{
+ testUnimplemented("This test is unimplemented");
+}
+
+/**
+ * Verify the openssl signature using the public key and our locally computed hash
+ */
+LONGBOW_TEST_CASE(Local, parcInMemoryVerifier_VerifySignature)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ // Setup the key in the verifier
+
+ PARCKey *key = parcSigner_CreatePublicKey(data->signer);
+
+ _parcInMemoryVerifier_AddKey(data->inMemoryInterface, key);
+
+ // read the buffer to sign
+ int fd = open("test_random_bytes", O_RDONLY);
+ uint8_t buffer_to_sign[2048];
+ ssize_t read_bytes = read(fd, buffer_to_sign, 2048);
+ close(fd);
+
+ // Digest it
+ PARCCryptoHasher *digester = _parcInMemoryVerifier_GetCryptoHasher(data->inMemoryInterface, parcKey_GetKeyId(key), PARCCryptoHashType_SHA256);
+ assertNotNull(digester, "got null cryptohasher from inmemory verifier");
+
+ parcCryptoHasher_Init(digester);
+ parcCryptoHasher_UpdateBytes(digester, buffer_to_sign, read_bytes);
+ PARCCryptoHash *localHash = parcCryptoHasher_Finalize(digester);
+
+ // now read the "true" signature
+ uint8_t scratch_buffer[1024];
+ fd = open("test_random_bytes.sig", O_RDONLY);
+ read_bytes = read(fd, scratch_buffer, 1024);
+ assertTrue(read_bytes == 128,
+ "read incorrect size signature from disk: %zu", read_bytes);
+ close(fd);
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcBufferComposer_PutArray(composer, scratch_buffer, read_bytes);
+ PARCBuffer *bb_sig = parcBufferComposer_ProduceBuffer(composer);
+
+ PARCSignature *signatureToVerify = parcSignature_Create(PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256, bb_sig);
+ parcBuffer_Release(&bb_sig);
+ parcBufferComposer_Release(&composer);
+
+ bool success = _parcInMemoryVerifier_VerifyDigest(data->inMemoryInterface, parcKey_GetKeyId(key), localHash, PARCCryptoSuite_RSA_SHA256, signatureToVerify);
+
+ parcSignature_Release(&signatureToVerify);
+ parcCryptoHash_Release(&localHash);
+ parcKey_Release(&key);
+
+ assertTrue(success, "Could not validate signature");
+}
+
+/**
+ * Same as the "good" code above, but calculate the hash with the wrong hash algorithm. This is
+ * what would happen if the signer and the verifier did not use the same hash algorithym.
+ */
+LONGBOW_TEST_CASE(Local, parcInMemoryVerifier_VerifySignature_BadHashAlg)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success;
+
+ // Setup the key in the verifier
+
+ PARCKey *key = parcSigner_CreatePublicKey(data->signer);
+
+ _parcInMemoryVerifier_AddKey(data->inMemoryInterface, key);
+
+ // read the buffer to sign
+ int fd = open("test_random_bytes", O_RDONLY);
+ uint8_t buffer_to_sign[2048];
+ ssize_t read_bytes = read(fd, buffer_to_sign, 2048);
+ close(fd);
+
+ // Digest it WITH THE WRONG HASH
+ PARCCryptoHasher *digester = _parcInMemoryVerifier_GetCryptoHasher(data->inMemoryInterface, parcKey_GetKeyId(key), PARCCryptoHashType_SHA512);
+ assertNotNull(digester, "got null cryptohasher from inmemory verifier");
+
+ parcCryptoHasher_Init(digester);
+ parcCryptoHasher_UpdateBytes(digester, buffer_to_sign, read_bytes);
+ PARCCryptoHash *localHash = parcCryptoHasher_Finalize(digester);
+
+ // now read the "true" signature
+ uint8_t scratch_buffer[1024];
+ fd = open("test_random_bytes.sig", O_RDONLY);
+ read_bytes = read(fd, scratch_buffer, 1024);
+ assertTrue(read_bytes == 128, "read incorrect size signature from disk: %zu", read_bytes);
+ close(fd);
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcBufferComposer_PutArray(composer, scratch_buffer, read_bytes);
+ PARCBuffer *bb_sig = parcBufferComposer_ProduceBuffer(composer);
+
+ PARCSignature *signatureToVerify = parcSignature_Create(PARCSigningAlgorithm_RSA,
+ PARCCryptoHashType_SHA256,
+ bb_sig);
+ parcBuffer_Release(&bb_sig);
+ parcBufferComposer_Release(&composer);
+
+ success = _parcInMemoryVerifier_VerifyDigest(data->inMemoryInterface, parcKey_GetKeyId(key), localHash, PARCCryptoSuite_RSA_SHA256, signatureToVerify);
+
+ parcSignature_Release(&signatureToVerify);
+ parcCryptoHash_Release(&localHash);
+ parcKey_Release(&key);
+
+ assertFalse(success, "Signatures should not have verified! Wrong hash types!");
+}
+
+
+/**
+ * Same as the "good" code, but tell the verifier the wrong key type. This is what would
+ * happen if the verifier somehow picked the wrong cryptosuite.
+ */
+LONGBOW_TEST_CASE(Local, parcInMemoryVerifier_VerifySignature_BadSigAlg)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ // Setup the key in the verifier
+ PARCKey *key = parcSigner_CreatePublicKey(data->signer);
+
+ _parcInMemoryVerifier_AddKey(data->inMemoryInterface, key);
+
+ // read the buffer to sign
+ int fd = open("test_random_bytes", O_RDONLY);
+ uint8_t buffer_to_sign[2048];
+ ssize_t read_bytes = read(fd, buffer_to_sign, 2048);
+ close(fd);
+
+ // Digest it
+ PARCCryptoHasher *digester = _parcInMemoryVerifier_GetCryptoHasher(data->inMemoryInterface, parcKey_GetKeyId(key), PARCCryptoHashType_SHA256);
+ assertNotNull(digester, "got null cryptohasher from inmemory verifier");
+
+ parcCryptoHasher_Init(digester);
+ parcCryptoHasher_UpdateBytes(digester, buffer_to_sign, read_bytes);
+ PARCCryptoHash *localHash = parcCryptoHasher_Finalize(digester);
+
+ // now read the "true" signature
+ uint8_t scratch_buffer[1024];
+ fd = open("test_random_bytes.sig", O_RDONLY);
+ read_bytes = read(fd, scratch_buffer, 1024);
+ assertTrue(read_bytes == 128, "read incorrect size signature from disk: %zu", read_bytes);
+ close(fd);
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcBufferComposer_PutArray(composer, scratch_buffer, read_bytes);
+ PARCBuffer *bb_sig = parcBufferComposer_ProduceBuffer(composer);
+
+ // HERE WE TELL IT DSA, NOT RSA
+ PARCSignature *signatureToVerify = parcSignature_Create(PARCSigningAlgorithm_DSA,
+ PARCCryptoHashType_SHA256,
+ bb_sig);
+ parcBuffer_Release(&bb_sig);
+ parcBufferComposer_Release(&composer);
+
+ bool success = _parcInMemoryVerifier_VerifyDigest(data->inMemoryInterface, parcKey_GetKeyId(key), localHash, PARCCryptoSuite_RSA_SHA256, signatureToVerify);
+
+ parcSignature_Release(&signatureToVerify);
+ parcCryptoHash_Release(&localHash);
+ parcKey_Release(&key);
+
+ assertFalse(success, "Signatures should not have verified! Wrong hash types!");
+}
+
+/**
+ * THis tests the locally computed digest not matching te digest used for the signature.
+ */
+LONGBOW_TEST_CASE(Local, parcInMemoryVerifier_VerifySignature_BadHash)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ // Setup the key in the verifier
+
+ PARCKey *key = parcSigner_CreatePublicKey(data->signer);
+
+ _parcInMemoryVerifier_AddKey(data->inMemoryInterface, key);
+
+ // read the buffer to sign
+ int fd = open("test_random_bytes", O_RDONLY);
+ uint8_t buffer_to_sign[2048];
+ ssize_t read_bytes = read(fd, buffer_to_sign, 2048);
+ close(fd);
+
+ // Digest it
+ PARCCryptoHasher *digester = _parcInMemoryVerifier_GetCryptoHasher(data->inMemoryInterface, parcKey_GetKeyId(key), PARCCryptoHashType_SHA256);
+ assertNotNull(digester, "got null cryptohasher from inmemory verifier");
+
+ // DIGEST THE BYTES TWICE TO GIVE WRONG HASH
+ parcCryptoHasher_Init(digester);
+ parcCryptoHasher_UpdateBytes(digester, buffer_to_sign, read_bytes);
+ parcCryptoHasher_UpdateBytes(digester, buffer_to_sign, read_bytes);
+ PARCCryptoHash *localHash = parcCryptoHasher_Finalize(digester);
+
+ // now read the "true" signature
+ uint8_t scratch_buffer[1024];
+ fd = open("test_random_bytes.sig", O_RDONLY);
+ read_bytes = read(fd, scratch_buffer, 1024);
+ assertTrue(read_bytes == 128, "read incorrect size signature from disk: %zu", read_bytes);
+ close(fd);
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcBufferComposer_PutArray(composer, scratch_buffer, read_bytes);
+ PARCBuffer *bb_sig = parcBufferComposer_ProduceBuffer(composer);
+
+ PARCSignature *signatureToVerify = parcSignature_Create(PARCSigningAlgorithm_RSA,
+ PARCCryptoHashType_SHA256,
+ bb_sig);
+ parcBuffer_Release(&bb_sig);
+ parcBufferComposer_Release(&composer);
+
+ bool success = _parcInMemoryVerifier_VerifyDigest(data->inMemoryInterface, parcKey_GetKeyId(key), localHash, PARCCryptoSuite_RSA_SHA256, signatureToVerify);
+
+ parcSignature_Release(&signatureToVerify);
+ parcCryptoHash_Release(&localHash);
+ parcKey_Release(&key);
+
+ assertFalse(success, "Signature verified even with wrong hash");
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_InMemoryVerifier);
+ int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}