diff options
Diffstat (limited to 'libparc/parc/security/test')
65 files changed, 6631 insertions, 0 deletions
diff --git a/libparc/parc/security/test/.gitignore b/libparc/parc/security/test/.gitignore new file mode 100644 index 00000000..bda8c802 --- /dev/null +++ b/libparc/parc/security/test/.gitignore @@ -0,0 +1,24 @@ +test_parc_AesSignerFileStore +test_parc_CryptoCache +test_parc_InMemoryVerifier +test_parc_KeyId +test_parc_PublicKeySignerPkcs12Store +test_parc_SelfSignedCertificate +test_parc_Signature +test_parc_Signer +test_parc_SymmetricSignerFileStore +test_parc_Security +test_parc_CryptoHash +test_parc_CryptoHashType +test_parc_CryptoSuite +test_parc_Identity +test_parc_IdentityFile +test_parc_Key +test_parc_KeyStore +test_parc_Verifier +test_parc_SigningAlgorithm +test_parc_Certificate +test_parc_CertificateFactory +test_parc_ContainerEncoding +test_parc_CertificateType +test_parc_X509Certificate diff --git a/libparc/parc/security/test/CMakeLists.txt b/libparc/parc/security/test/CMakeLists.txt new file mode 100644 index 00000000..189bc7ca --- /dev/null +++ b/libparc/parc/security/test/CMakeLists.txt @@ -0,0 +1,75 @@ +set(TestsExpectedToPass + test_parc_Certificate + test_parc_CertificateFactory + test_parc_CertificateType + test_parc_ContainerEncoding + test_parc_CryptoCache + test_parc_CryptoHash + test_parc_CryptoHashType + test_parc_CryptoHasher + test_parc_CryptoSuite + test_parc_DiffieHellman + test_parc_DiffieHellmanKeyShare + test_parc_Identity + test_parc_IdentityFile + test_parc_InMemoryVerifier + test_parc_Key + test_parc_KeyId + test_parc_KeyStore + test_parc_SecureRandom + test_parc_Pkcs12KeyStore + test_parc_PublicKeySigner + test_parc_SymmetricKeySigner + test_parc_SymmetricKeyStore + test_parc_Security + test_parc_Signature + test_parc_Signer + test_parc_SigningAlgorithm + test_parc_Verifier + test_parc_X509Certificate + ) + +set(EXTRA_DATA_FILES + README.digests + README.keystore + README.symmetric + test_crt.der + test_crt_der.bin + test_crt_sha256.bin + test_der.bin + test_digest_bytes_128.bin + test_digest_bytes_128.sha256 + test_digest_bytes_128.sha512 + test.pem + test_pubkey.bin + test_pubkey.der + test_pubkey.pem + test_random_bytes + test_random_bytes.sig + test_random_bytes.hmac_sha256 + test_random_bytes.hmac_sha512 + test_rsa.p12 + test_rsa_crt.der + test_rsa_crt_sha256.bin + test_rsa_key.der + test_rsa_key.pem + test_rsa_pub.der + test_rsa_pub.pem + test_rsa_pub_sha256.bin + test_symmetric_key.bin + test_symmetric_key.sha256 + ) + +foreach(data_file ${EXTRA_DATA_FILES}) + configure_file(${data_file} ${data_file} COPYONLY) +endforeach() + + +# Enable gcov output for the tests +add_definitions(--coverage) +set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage") + + +foreach(test ${TestsExpectedToPass}) + AddTest(${test}) +endforeach() diff --git a/libparc/parc/security/test/README.digests b/libparc/parc/security/test/README.digests new file mode 100644 index 00000000..4abfa940 --- /dev/null +++ b/libparc/parc/security/test/README.digests @@ -0,0 +1,12 @@ +# +# Generate some blocks of bytes to digest, then calculate the "truth" via openssl + +dd if=/dev/urandom of=test_digest_bytes_128.bin bs=128 count=1 + +openssl dgst -sha256 -binary < test_digest_bytes_128.bin > test_digest_bytes_128.sha256 +openssl dgst -sha512 -binary < test_digest_bytes_128.bin > test_digest_bytes_128.sha512 + +# these are for the symmetric key tests +openssl sha256 -hmac 'apple_pie_is_good' -binary < test_random_bytes > test_random_bytes.hmac_sha256 +openssl sha512 -hmac 'apple_pie_is_good' -binary < test_random_bytes > test_random_bytes.hmac_sha512 + diff --git a/libparc/parc/security/test/README.keystore b/libparc/parc/security/test/README.keystore new file mode 100644 index 00000000..70227d33 --- /dev/null +++ b/libparc/parc/security/test/README.keystore @@ -0,0 +1,35 @@ + +# This set of commands creates an RSA public/private key pair, +# self-signs it, then puts it all in a pkcs12 container with +# the password "blueberry" +# +# We use these files in the test_ccnx_FileKeystore tests. + +openssl genrsa -out test_rsa_key.pem +openssl rsa -pubout -in test_rsa_key.pem -out test_rsa_pub.pem +openssl req -new -key test_rsa_key.pem -out test_rsa.csr +openssl x509 -req -days 365 -in test_rsa.csr -signkey test_rsa_key.pem -out test_rsa.crt +openssl pkcs12 -export -in test_rsa.crt -inkey test_rsa_key.pem -out test_rsa.p12 -name ccnxuser -CAfile test_rsa.crt -caname root -chain -passout pass:blueberry + +# saves the public key in DER form so we can calculate the sha256 of it +openssl rsa -in test_rsa_key.pem -outform DER -pubout -out test_rsa_pub.der + +# save the private key in DER form so we can compare in code +openssl rsa -in test_rsa_key.pem -outform DER -out test_rsa_key.der + +# computes the sha256 and saves it in binary form +openssl sha256 -out test_rsa_pub_sha256.bin -sha256 -binary < test_rsa_pub.der + +# Save the certificate in DER form, then get the SHA256 hash of it +# These are similar to doing "openssl x509 -in test_rsa.crt -fingerprint -sha256" +openssl x509 -outform DER -out test_rsa_crt.der -in test_rsa.crt +openssl sha256 -out test_rsa_crt_sha256.bin -sha256 -binary < test_rsa_crt.der + +# To verify signing, we create a random buffer, then sign with a SHA256 digest + +dd if=/dev/urandom of=test_random_bytes bs=512 count=1 +openssl sha -sha256 -sign test_rsa_key.pem -out test_random_bytes.sig < test_random_bytes + +# the "-in test_rsa_pub_sha256.bin" is the binary digest we will sign. +openssl rsautl -sign -inkey test_rsa_key.pem -in test_rsa_pub_sha256.bin -out test_rsa_pub_sha256.bin.sig + diff --git a/libparc/parc/security/test/README.symmetric b/libparc/parc/security/test/README.symmetric new file mode 100644 index 00000000..ce09fe85 --- /dev/null +++ b/libparc/parc/security/test/README.symmetric @@ -0,0 +1,9 @@ + +# random bytes as a 32-byte (256-bit) key + +dd if=/dev/random of=test_symmetric_key.bin bs=32 count=1 + +# compute its sha-256 hash +openssl sha256 -binary -out test_symmetric_key.sha256 < test_symmetric_key.bin + + diff --git a/libparc/parc/security/test/test.crt.der b/libparc/parc/security/test/test.crt.der Binary files differnew file mode 100644 index 00000000..8b2e12ca --- /dev/null +++ b/libparc/parc/security/test/test.crt.der diff --git a/libparc/parc/security/test/test.crt.der.sha256.bin b/libparc/parc/security/test/test.crt.der.sha256.bin new file mode 100644 index 00000000..1d19a81c --- /dev/null +++ b/libparc/parc/security/test/test.crt.der.sha256.bin @@ -0,0 +1 @@ +>
Թ/ͩp :),
\ No newline at end of file diff --git a/libparc/parc/security/test/test.der b/libparc/parc/security/test/test.der Binary files differnew file mode 100644 index 00000000..db368b72 --- /dev/null +++ b/libparc/parc/security/test/test.der diff --git a/libparc/parc/security/test/test.pem b/libparc/parc/security/test/test.pem new file mode 100644 index 00000000..d9593bac --- /dev/null +++ b/libparc/parc/security/test/test.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICATCCAWoCCQDCCG74+EassjANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTE1MDkwMzIxMDYxNloXDTE2MDkwMjIxMDYxNlowRTELMAkG +A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvp5L +B7ccwPfBooRduHvQHgJo5gvDIXX5dFz/8oRDgyAnvtvCoQXkfSj5oO+6WpaKIG2k +RxO+2VEKknY1GyWT3qqHVfSgp33n/AKBsedVb5ZUVAhy4FAOq3BCF8wpfKrkfadQ +ltmBNYP0DH4YdIvS7+HL5yaKXF1ZnUwWo2WFcucCAwEAATANBgkqhkiG9w0BAQUF +AAOBgQAt8Op2KgQ6cREBVS6xOWvSeNr7/EXEW8T19BsUkYZeZ596oEJVjT2CrT0P +s2ADuzfN0w19aGM25UczlBcg/CtkrTZEoXubbIoPGwwZv+taM+v455DhJY1chd0j +Jq6XeRDokTFvn9qcZmoCX2CVKEMigatTpz4zenATUQmmRwdIVg== +-----END CERTIFICATE----- diff --git a/libparc/parc/security/test/test.pkcs12 b/libparc/parc/security/test/test.pkcs12 Binary files differnew file mode 100644 index 00000000..4b032263 --- /dev/null +++ b/libparc/parc/security/test/test.pkcs12 diff --git a/libparc/parc/security/test/test_crt.der b/libparc/parc/security/test/test_crt.der Binary files differnew file mode 100644 index 00000000..42a829ee --- /dev/null +++ b/libparc/parc/security/test/test_crt.der diff --git a/libparc/parc/security/test/test_crt_der.bin b/libparc/parc/security/test/test_crt_der.bin Binary files differnew file mode 100644 index 00000000..42a829ee --- /dev/null +++ b/libparc/parc/security/test/test_crt_der.bin diff --git a/libparc/parc/security/test/test_crt_sha256.bin b/libparc/parc/security/test/test_crt_sha256.bin new file mode 100644 index 00000000..77d41680 --- /dev/null +++ b/libparc/parc/security/test/test_crt_sha256.bin @@ -0,0 +1 @@ +5#LG4%uENlna,*V<w
\ No newline at end of file diff --git a/libparc/parc/security/test/test_der.bin b/libparc/parc/security/test/test_der.bin Binary files differnew file mode 100644 index 00000000..db368b72 --- /dev/null +++ b/libparc/parc/security/test/test_der.bin diff --git a/libparc/parc/security/test/test_digest_bytes_128.bin b/libparc/parc/security/test/test_digest_bytes_128.bin new file mode 100644 index 00000000..b6939de1 --- /dev/null +++ b/libparc/parc/security/test/test_digest_bytes_128.bin @@ -0,0 +1 @@ +}/W9^Y(Αv|}wλ^K3qh%anĝEvu.cCj'Dv\hE6$][lB}DS
\ No newline at end of file diff --git a/libparc/parc/security/test/test_digest_bytes_128.sha256 b/libparc/parc/security/test/test_digest_bytes_128.sha256 new file mode 100644 index 00000000..6e93005d --- /dev/null +++ b/libparc/parc/security/test/test_digest_bytes_128.sha256 @@ -0,0 +1 @@ +NL.T`+۪]
\ No newline at end of file diff --git a/libparc/parc/security/test/test_digest_bytes_128.sha512 b/libparc/parc/security/test/test_digest_bytes_128.sha512 new file mode 100644 index 00000000..88db6953 --- /dev/null +++ b/libparc/parc/security/test/test_digest_bytes_128.sha512 @@ -0,0 +1 @@ +WJuie>]ϲ OC>4G
KNEEop9~kML
\ No newline at end of file diff --git a/libparc/parc/security/test/test_key.pem b/libparc/parc/security/test/test_key.pem new file mode 100644 index 00000000..bdc42c1e --- /dev/null +++ b/libparc/parc/security/test/test_key.pem @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+nksHtxzA98GihF24e9AeAmjm +C8Mhdfl0XP/yhEODICe+28KhBeR9KPmg77paloogbaRHE77ZUQqSdjUbJZPeqodV +9KCnfef8AoGx51VvllRUCHLgUA6rcEIXzCl8quR9p1CW2YE1g/QMfhh0i9Lv4cvn +JopcXVmdTBajZYVy5wIDAQAB +-----END PUBLIC KEY----- diff --git a/libparc/parc/security/test/test_parc_Certificate.c b/libparc/parc/security/test/test_parc_Certificate.c new file mode 100644 index 00000000..24f46f86 --- /dev/null +++ b/libparc/parc/security/test/test_parc_Certificate.c @@ -0,0 +1,258 @@ +/* + * 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 <config.h> +#include <stdio.h> +#include <LongBow/unit-test.h> + +#include "../parc_Certificate.c" +#include <parc/algol/parc_SafeMemory.h> +#include <parc/security/parc_Security.h> +#include <parc/security/parc_CryptoHashType.h> +#include <parc/security/parc_Key.h> +#include <parc/algol/parc_Buffer.h> + +PARCCryptoHash * +_mockGetPublicKeyDigest(void *instance) +{ + PARCBuffer *buffer = parcBuffer_Allocate(10); + PARCCryptoHash *hash = parcCryptoHash_Create(PARCCryptoHashType_SHA256, buffer); + parcBuffer_Release(&buffer); + return hash; +} + +PARCCryptoHash * +_mockGetCertificateDigest(void *instance) +{ + PARCBuffer *buffer = parcBuffer_Allocate(20); + PARCCryptoHash *hash = parcCryptoHash_Create(PARCCryptoHashType_SHA256, buffer); + parcBuffer_Release(&buffer); + return hash; +} + +PARCBuffer * +_mockGetDEREncodedCertificate(void *instance) +{ + return parcBuffer_Allocate(30); +} + +PARCBuffer * +_mockGetDEREncodedPublicKey(void *instance) +{ + return parcBuffer_Allocate(40); +} + +PARCCertificateType +_mockGetCertificateType(const void *instance) +{ + return PARCCertificateType_X509; +} + +PARCContainerEncoding +_mockGetContainerEncoding(const void *instance) +{ + return PARCContainerEncoding_PEM; +} + +PARCKey * +_mockGetPublicKey(void *instance) +{ + PARCBuffer *realKey = parcBuffer_Allocate(256); + PARCBuffer *keyId = parcBuffer_Allocate(256); + PARCKeyId *id = parcKeyId_Create(keyId); + + PARCKey *key = parcKey_CreateFromDerEncodedPublicKey(id, PARCSigningAlgorithm_RSA, realKey); + + parcBuffer_Release(&keyId); + parcKeyId_Release(&id); + parcBuffer_Release(&realKey); + + return key; +} + +PARCCertificateInterface *_mockCertificate = &(PARCCertificateInterface) { + .GetPublicKeyDigest = _mockGetPublicKeyDigest, + .GetCertificateDigest = _mockGetCertificateDigest, + .GetDEREncodedCertificate = _mockGetDEREncodedCertificate, + .GetDEREncodedPublicKey = _mockGetDEREncodedPublicKey, + .GetCertificateType = _mockGetCertificateType, + .GetContainerEncoding = _mockGetContainerEncoding +}; + +LONGBOW_TEST_RUNNER(parc_Certificate) +{ + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +LONGBOW_TEST_RUNNER_SETUP(parc_Certificate) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_Certificate) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parc_Certificate_AcquireRelease); + LONGBOW_RUN_TEST_CASE(Global, parc_Certificate_Create); + LONGBOW_RUN_TEST_CASE(Global, parc_Certificate_GetContainerEncoding); + LONGBOW_RUN_TEST_CASE(Global, parc_Certificate_GetCertificateType); + LONGBOW_RUN_TEST_CASE(Global, parc_Certificate_GetPublicKeyDigest); + LONGBOW_RUN_TEST_CASE(Global, parc_Certificate_GetCertificateDigest); + LONGBOW_RUN_TEST_CASE(Global, parc_Certificate_GetDEREncodedCertificate); + LONGBOW_RUN_TEST_CASE(Global, parc_Certificate_GetDEREncodedPublicKey); + LONGBOW_RUN_TEST_CASE(Global, parc_Certificate_GetPublicKey); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + 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(Global, parc_Certificate_AcquireRelease) +{ + PARCCertificate *certificate = parcCertificate_CreateFromInstance(_mockCertificate, NULL); + assertNotNull(certificate, "Expected non-NULL certificate"); + + PARCReferenceCount firstCount = parcObject_GetReferenceCount(certificate); + PARCCertificate *copy = parcCertificate_Acquire(certificate); + PARCReferenceCount secondCount = parcObject_GetReferenceCount(copy); + + assertTrue(firstCount == (secondCount - 1), "Expected incremented reference count after Acquire"); + + parcCertificate_Release(©); + PARCReferenceCount thirdCount = parcObject_GetReferenceCount(certificate); + + assertTrue(firstCount == thirdCount, "Expected equal reference counts after Release"); + + parcCertificate_Release(&certificate); +} + +LONGBOW_TEST_CASE(Global, parc_Certificate_Create) +{ + PARCCertificate *certificate = parcCertificate_CreateFromInstance(_mockCertificate, NULL); + + assertNotNull(certificate, "Expected non-NULL certificate"); + + parcCertificate_Release(&certificate); +} + +LONGBOW_TEST_CASE(Global, parc_Certificate_GetContainerEncoding) +{ + PARCCertificate *certificate = parcCertificate_CreateFromInstance(_mockCertificate, NULL); + PARCContainerEncoding encoding = parcCertificate_GetContainerEncoding(certificate); + assertTrue(encoding == PARCContainerEncoding_PEM, "Expected %d, got %d", PARCContainerEncoding_PEM, encoding); + parcCertificate_Release(&certificate); +} + +LONGBOW_TEST_CASE(Global, parc_Certificate_GetCertificateType) +{ + PARCCertificate *certificate = parcCertificate_CreateFromInstance(_mockCertificate, NULL); + PARCCertificateType type = parcCertificate_GetCertificateType(certificate); + assertTrue(type == PARCCertificateType_X509, "Expected %d, got %d", PARCCertificateType_X509, type); + parcCertificate_Release(&certificate); +} + +LONGBOW_TEST_CASE(Global, parc_Certificate_GetPublicKeyDigest) +{ + PARCCertificate *certificate = parcCertificate_CreateFromInstance(_mockCertificate, NULL); + + PARCCryptoHash *hash = parcCertificate_GetPublicKeyDigest(certificate); + size_t length = parcBuffer_Remaining(parcCryptoHash_GetDigest(hash)); + size_t expected = 10; + assertTrue(length == expected, "Expected length of %zu, got %zu", expected, length); + + parcCryptoHash_Release(&hash); + parcCertificate_Release(&certificate); +} + +LONGBOW_TEST_CASE(Global, parc_Certificate_GetCertificateDigest) +{ + PARCCertificate *certificate = parcCertificate_CreateFromInstance(_mockCertificate, NULL); + + PARCCryptoHash *hash = parcCertificate_GetCertificateDigest(certificate); + size_t length = parcBuffer_Remaining(parcCryptoHash_GetDigest(hash)); + size_t expected = 20; + assertTrue(length == expected, "Expected length of %zu, got %zu", expected, length); + + parcCryptoHash_Release(&hash); + parcCertificate_Release(&certificate); +} + +LONGBOW_TEST_CASE(Global, parc_Certificate_GetDEREncodedCertificate) +{ + PARCCertificate *certificate = parcCertificate_CreateFromInstance(_mockCertificate, NULL); + + PARCBuffer *buffer = parcCertificate_GetDEREncodedCertificate(certificate); + size_t length = parcBuffer_Remaining(buffer); + size_t expected = 30; + assertTrue(length == expected, "Expected length of %zu, got %zu", expected, length); + + parcBuffer_Release(&buffer); + parcCertificate_Release(&certificate); +} + +LONGBOW_TEST_CASE(Global, parc_Certificate_GetDEREncodedPublicKey) +{ + PARCCertificate *certificate = parcCertificate_CreateFromInstance(_mockCertificate, NULL); + + PARCBuffer *buffer = parcCertificate_GetDEREncodedPublicKey(certificate); + size_t length = parcBuffer_Remaining(buffer); + size_t expected = 40; + assertTrue(length == expected, "Expected length of %zu, got %zu", expected, length); + + parcBuffer_Release(&buffer); + parcCertificate_Release(&certificate); +} + +LONGBOW_TEST_CASE(Global, parc_Certificate_GetPublicKey) +{ + PARCCertificate *certificate = parcCertificate_CreateFromInstance(_mockCertificate, NULL); + + PARCKey *actual = parcCertificate_GetPublicKey(certificate); + assertTrue(parcBuffer_Remaining(parcKey_GetKey(actual)) == 40, + "Expected PARCKey size to be 40, got %zu", + parcBuffer_Remaining(parcKey_GetKey(actual))); + assertTrue(parcBuffer_Remaining(parcKeyId_GetKeyId(parcKey_GetKeyId(actual))) == 10, + "Expected PARCKey keyId size to be 10, got %zu", + parcBuffer_Remaining(parcKeyId_GetKeyId(parcKey_GetKeyId(actual)))); + + parcKey_Release(&actual); + parcCertificate_Release(&certificate); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Certificate); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_CertificateFactory.c b/libparc/parc/security/test/test_parc_CertificateFactory.c new file mode 100755 index 00000000..29675f94 --- /dev/null +++ b/libparc/parc/security/test/test_parc_CertificateFactory.c @@ -0,0 +1,160 @@ +/* + * 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 <config.h> +#include <stdio.h> +#include <LongBow/unit-test.h> + +#include "../parc_CertificateFactory.c" +#include <parc/security/parc_X509Certificate.h> +#include <parc/algol/parc_SafeMemory.h> +#include <parc/security/parc_Security.h> +#include <parc/security/parc_CryptoHashType.h> +#include <parc/algol/parc_Buffer.h> + +LONGBOW_TEST_RUNNER(parc_CertificateFactory) +{ + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +LONGBOW_TEST_RUNNER_SETUP(parc_CertificateFactory) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_CertificateFactory) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parc_CertificateFactory_AcquireRelease); + LONGBOW_RUN_TEST_CASE(Global, parc_CertificateFactory_Create); + LONGBOW_RUN_TEST_CASE(Global, parc_CertificateFactory_CreateFromFile); + LONGBOW_RUN_TEST_CASE(Global, parc_CertificateFactory_CreateFromBuffer); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + 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(Global, parc_CertificateFactory_AcquireRelease) +{ + PARCCertificateFactory *factory = parcCertificateFactory_Create(PARCCertificateType_X509, PARCContainerEncoding_PEM); + assertNotNull(factory, "Expected non-NULL factory"); + + PARCReferenceCount firstCount = parcObject_GetReferenceCount(factory); + PARCCertificateFactory *copy = parcCertificateFactory_Acquire(factory); + PARCReferenceCount secondCount = parcObject_GetReferenceCount(copy); + + assertTrue(firstCount == (secondCount - 1), "Expected incremented reference count after Acquire"); + + parcCertificateFactory_Release(©); + PARCReferenceCount thirdCount = parcObject_GetReferenceCount(factory); + + assertTrue(firstCount == thirdCount, "Expected equal reference counts after Release"); + + parcCertificateFactory_Release(&factory); +} + +LONGBOW_TEST_CASE(Global, parc_CertificateFactory_Create) +{ + PARCCertificateFactory *factory = parcCertificateFactory_Create(PARCCertificateType_X509, PARCContainerEncoding_PEM); + assertNotNull(factory, "Expected non-NULL factory"); + assertTrue(factory->encoding == PARCContainerEncoding_PEM, "Expected PARCContainerEncoding_PEM (%d) encoding, got %d", + PARCContainerEncoding_PEM, factory->encoding); + assertTrue(factory->type == PARCCertificateType_X509, "Expected PARCCertificateType_X509 (%d) type, got %d", + PARCCertificateType_X509, factory->type); + parcCertificateFactory_Release(&factory); +} + +LONGBOW_TEST_CASE(Global, parc_CertificateFactory_CreateFromFile) +{ + PARCCertificateFactory *factory = parcCertificateFactory_Create(PARCCertificateType_X509, PARCContainerEncoding_PEM); + assertNotNull(factory, "Expected non-NULL factory"); + + char *filename = "test.pem"; + PARCCertificate *certificate = parcCertificateFactory_CreateCertificateFromFile(factory, filename, NULL); + + assertNotNull(certificate, "Expected non-NULL certificate"); + assertTrue(parcCertificate_GetContainerEncoding(certificate) == PARCContainerEncoding_PEM, + "Expected PARCContainerEncoding_PEM encoding, got %d", parcCertificate_GetContainerEncoding(certificate)); + assertTrue(parcCertificate_GetCertificateType(certificate) == PARCCertificateType_X509, + "Expected PARCCertificateType_X509 type, got %d", parcCertificate_GetCertificateType(certificate)); + + parcCertificate_Release(&certificate); + parcCertificateFactory_Release(&factory); + + factory = parcCertificateFactory_Create(PARCCertificateType_Invalid, PARCContainerEncoding_PEM); + + PARCCertificate *nullCertificate = parcCertificateFactory_CreateCertificateFromFile(factory, filename, NULL); + assertNull(nullCertificate, "Expected NULL certificate to be returned from factory with an unsupported configuration"); + + parcCertificateFactory_Release(&factory); +} + +LONGBOW_TEST_CASE(Global, parc_CertificateFactory_CreateFromBuffer) +{ + PARCCertificateFactory *factory = parcCertificateFactory_Create(PARCCertificateType_X509, PARCContainerEncoding_DER); + assertNotNull(factory, "Expected non-NULL factory"); + + char *filename = "test.pem"; + PARCX509Certificate *realCertificate = parcX509Certificate_CreateFromPEMFile(filename); + PARCBuffer *certificateBuffer = parcX509Certificate_GetDEREncodedCertificate(realCertificate); + + PARCCertificate *certificate = parcCertificateFactory_CreateCertificateFromBuffer(factory, certificateBuffer); + + assertNotNull(certificate, "Expected non-NULL certificate"); + assertTrue(parcCertificate_GetContainerEncoding(certificate) == PARCContainerEncoding_DER, + "Expected PARCContainerEncoding_DER encoding, got %d", parcCertificate_GetContainerEncoding(certificate)); + assertTrue(parcCertificate_GetCertificateType(certificate) == PARCCertificateType_X509, + "Expected PARCCertificateType_X509 type, got %d", parcCertificate_GetCertificateType(certificate)); + + parcCertificate_Release(&certificate); + parcCertificateFactory_Release(&factory); + parcX509Certificate_Release(&realCertificate); + + factory = parcCertificateFactory_Create(PARCCertificateType_Invalid, PARCContainerEncoding_PEM); + + PARCBuffer *invalid = parcBuffer_Allocate(10); + PARCCertificate *nullCertificate = parcCertificateFactory_CreateCertificateFromBuffer(factory, invalid); + assertNull(nullCertificate, "Expected NULL certificate to be returned from factory with an unsupported configuration"); + + parcBuffer_Release(&invalid); + parcCertificateFactory_Release(&factory); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_CertificateFactory); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_CertificateType.c b/libparc/parc/security/test/test_parc_CertificateType.c new file mode 100755 index 00000000..67ce5e87 --- /dev/null +++ b/libparc/parc/security/test/test_parc_CertificateType.c @@ -0,0 +1,90 @@ +/* + * 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 <config.h> +#include <stdio.h> +#include <LongBow/unit-test.h> + +#include "../parc_CertificateType.c" +#include <parc/algol/parc_SafeMemory.h> +#include <parc/security/parc_CryptoHashType.h> +#include <parc/algol/parc_Buffer.h> + +LONGBOW_TEST_RUNNER(parc_CertificateType) +{ + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +LONGBOW_TEST_RUNNER_SETUP(parc_CertificateType) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_CertificateType) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parc_CertificateType_FromString); + LONGBOW_RUN_TEST_CASE(Global, parc_CertificateType_ToString); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + 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, parc_CertificateType_FromString) +{ + char *inputString = "PARCCertificateType_X509"; + PARCCertificateType encoding = parcCertificateType_FromString(inputString); + assertTrue(encoding == PARCCertificateType_X509, "Expected PARCCertificateType_X509 (%d), for %d", PARCCertificateType_X509, encoding); + + inputString = "the cake is a lie"; + encoding = parcCertificateType_FromString(inputString); + assertTrue(encoding == PARCCertificateType_Invalid, "Expected PARCCertificateType_Invalid (%d), for %d", PARCCertificateType_Invalid, encoding); +} + +LONGBOW_TEST_CASE(Global, parc_CertificateType_ToString) +{ + char *expected = "PARCCertificateType_X509"; + PARCCertificateType encoding = PARCCertificateType_X509; + const char *actual = parcCertificateType_ToString(encoding); + assertTrue(strcmp(actual, expected) == 0, "Expected %s, got %s", expected, actual); + + actual = parcCertificateType_ToString(PARCCertificateType_Invalid); + assertNull(actual, "Expected NULL string to be returned with invalid certificate type"); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_CertificateType); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_ContainerEncoding.c b/libparc/parc/security/test/test_parc_ContainerEncoding.c new file mode 100755 index 00000000..01cafa50 --- /dev/null +++ b/libparc/parc/security/test/test_parc_ContainerEncoding.c @@ -0,0 +1,90 @@ +/* + * 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 <config.h> +#include <stdio.h> +#include <LongBow/unit-test.h> + +#include "../parc_ContainerEncoding.c" +#include <parc/algol/parc_SafeMemory.h> +#include <parc/security/parc_CryptoHashType.h> +#include <parc/algol/parc_Buffer.h> + +LONGBOW_TEST_RUNNER(parc_ContainerEncoding) +{ + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +LONGBOW_TEST_RUNNER_SETUP(parc_ContainerEncoding) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_ContainerEncoding) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parc_ContainerEncoding_FromString); + LONGBOW_RUN_TEST_CASE(Global, parc_ContainerEncoding_ToString); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + 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, parc_ContainerEncoding_FromString) +{ + char *inputString = "PARCContainerEncoding_PEM"; + PARCContainerEncoding encoding = parcContainerEncoding_FromString(inputString); + assertTrue(encoding == PARCContainerEncoding_PEM, "Expected PARCContainerEncoding_PEM (%d), for %d", PARCContainerEncoding_PEM, encoding); + + inputString = "the cake is a lie"; + encoding = parcContainerEncoding_FromString(inputString); + assertTrue(encoding == PARCContainerEncoding_Invalid, "Expected PARCContainerEncoding_Invalid (%d), for %d", PARCContainerEncoding_Invalid, encoding); +} + +LONGBOW_TEST_CASE(Global, parc_ContainerEncoding_ToString) +{ + char *expected = "PARCContainerEncoding_PEM"; + PARCContainerEncoding encoding = PARCContainerEncoding_PEM; + const char *actual = parcContainerEncoding_ToString(encoding); + assertTrue(strcmp(actual, expected) == 0, "Expected %s, got %s", expected, actual); + + actual = parcContainerEncoding_ToString(PARCContainerEncoding_Invalid); + assertNull(actual, "Expected NULL string to be returned with invalid encoding type"); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_ContainerEncoding); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_CryptoCache.c b/libparc/parc/security/test/test_parc_CryptoCache.c new file mode 100755 index 00000000..8613808d --- /dev/null +++ b/libparc/parc/security/test/test_parc_CryptoCache.c @@ -0,0 +1,228 @@ +/* + * 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 <config.h> +#include <LongBow/unit-test.h> + +// Include the file(s) containing the functions to be tested. +// This permits internal static functions to be visible to this Test Framework. +#include "../parc_CryptoCache.c" +#include <parc/algol/parc_SafeMemory.h> +#include <parc/algol/parc_BufferComposer.h> +#include <parc/security/parc_CryptoHashType.h> + +LONGBOW_TEST_RUNNER(parc_CryptoCache) +{ + // 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(Allocate); + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_CryptoCache) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_CryptoCache) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Allocate) +{ + LONGBOW_RUN_TEST_CASE(Allocate, parcCryptoCache_Create_Destroy); +} + +LONGBOW_TEST_FIXTURE_SETUP(Allocate) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Allocate) +{ + 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(Allocate, parcCryptoCache_Create_Destroy) +{ + PARCCryptoCache *cache = parcCryptoCache_Create(); + parcCryptoCache_Destroy(&cache); +} + +static PARCCryptoCache *cache_under_test; + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcCryptoCache_AddGetKey); + LONGBOW_RUN_TEST_CASE(Global, parcCryptoCache_GetMissingKey); + LONGBOW_RUN_TEST_CASE(Global, parcCryptoCache_GetWrongKey); + LONGBOW_RUN_TEST_CASE(Global, parcCryptoCache_RemoveKey); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + cache_under_test = parcCryptoCache_Create(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + parcCryptoCache_Destroy(&cache_under_test); + + 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, parcCryptoCache_AddGetKey) +{ + PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid = parcKeyId_Create(bb_id); + parcBuffer_Release(&bb_id); + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer, "quack quack"); + PARCBuffer *bb_key = parcBufferComposer_ProduceBuffer(composer); + PARCKey *key = parcKey_CreateFromDerEncodedPublicKey(keyid, PARCSigningAlgorithm_RSA, bb_key); + + parcCryptoCache_AddKey(cache_under_test, key); + + const PARCKey *test = parcCryptoCache_GetKey(cache_under_test, keyid); + + parcBuffer_Release(&bb_key); + parcBufferComposer_Release(&composer); + parcKeyId_Release(&keyid); + + assertTrue(parcKey_Equals(key, test), "did not return expected key from cache"); + parcKey_Release(&key); +} + +LONGBOW_TEST_CASE(Global, parcCryptoCache_GetMissingKey) +{ + PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid = parcKeyId_Create(bb_id); + parcBuffer_Release(&bb_id); + + const PARCKey *test = parcCryptoCache_GetKey(cache_under_test, keyid); + + assertNull(test, "Get missing key returned something!"); + + parcKeyId_Release(&keyid); +} + +LONGBOW_TEST_CASE(Global, parcCryptoCache_GetWrongKey) +{ + PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCBuffer *bb_id2 = parcBuffer_Wrap("not here!", 9, 0, 9); + + PARCKeyId *keyid = parcKeyId_Create(bb_id); + parcBuffer_Release(&bb_id); + + PARCKeyId *keyid2 = parcKeyId_Create(bb_id2); + parcBuffer_Release(&bb_id2); + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer, "quack quack"); + PARCBuffer *bb_key = parcBufferComposer_ProduceBuffer(composer); + PARCKey *key = parcKey_CreateFromDerEncodedPublicKey(keyid, PARCSigningAlgorithm_RSA, bb_key); + + parcCryptoCache_AddKey(cache_under_test, key); + + const PARCKey *test = parcCryptoCache_GetKey(cache_under_test, keyid2); + assertNull(test, "Get missing key returned something!"); + + parcKey_Release(&key); + parcBuffer_Release(&bb_key); + parcBufferComposer_Release(&composer); + parcKeyId_Release(&keyid); + parcKeyId_Release(&keyid2); +} + +/** + * Add in 2 keys, remove 1, fetch the other + */ +LONGBOW_TEST_CASE(Global, parcCryptoCache_RemoveKey) +{ + PARCBufferComposer *composer1 = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer1, "quack quack"); + PARCBuffer *bb_key1 = parcBufferComposer_ProduceBuffer(composer1); + + PARCBufferComposer *composer2 = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer2, "Come with me and you'll be"); + PARCBuffer *bb_key2 = parcBufferComposer_ProduceBuffer(composer2); + + PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCBuffer *bb_id2 = parcBuffer_Wrap("not here!", 9, 0, 9); + + PARCKeyId *keyid1 = parcKeyId_Create(bb_id); + parcBuffer_Release(&bb_id); + PARCKeyId *keyid2 = parcKeyId_Create(bb_id2); + parcBuffer_Release(&bb_id2); + + PARCKey *key1 = parcKey_CreateFromDerEncodedPublicKey(keyid1, PARCSigningAlgorithm_RSA, bb_key1); + PARCKey *key2 = parcKey_CreateFromDerEncodedPublicKey(keyid2, PARCSigningAlgorithm_RSA, bb_key2); + const PARCKey *test; + + parcCryptoCache_AddKey(cache_under_test, key1); + parcCryptoCache_AddKey(cache_under_test, key2); + + test = parcCryptoCache_GetKey(cache_under_test, keyid1); + assertTrue(parcKey_Equals(key1, test), "Got wrong key"); + + test = parcCryptoCache_GetKey(cache_under_test, keyid2); + assertTrue(parcKey_Equals(key2, test), "Got wrong key"); + + // remove will free the key, so make a copy of it before removing + PARCKeyId *keyid1_copy = parcKeyId_Copy(keyid1); + parcCryptoCache_RemoveKey(cache_under_test, keyid1); + + test = parcCryptoCache_GetKey(cache_under_test, keyid1_copy); + assertNull(test, "Get of deleted key returned non-null"); + + test = parcCryptoCache_GetKey(cache_under_test, keyid2); + assertTrue(parcKey_Equals(key2, test), "Got wrong key"); + + + parcKey_Release(&key1); + parcKey_Release(&key2); + + parcBuffer_Release(&bb_key1); + parcBufferComposer_Release(&composer1); + parcKeyId_Release(&keyid1); + parcBuffer_Release(&bb_key2); + parcBufferComposer_Release(&composer2); + parcKeyId_Release(&keyid2); + + parcKeyId_Release(&keyid1_copy); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_CryptoCache); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_CryptoHash.c b/libparc/parc/security/test/test_parc_CryptoHash.c new file mode 100755 index 00000000..df5409b2 --- /dev/null +++ b/libparc/parc/security/test/test_parc_CryptoHash.c @@ -0,0 +1,184 @@ +/* + * 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_CryptoHash.c" +#include "../parc_CryptoHasher.h" + +#include <LongBow/unit-test.h> +#include <parc/testing/parc_ObjectTesting.h> +#include <fcntl.h> +#include <errno.h> + +const int bufferLength = 1024; + +LONGBOW_TEST_RUNNER(parc_CryptoHash) +{ + // 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); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_CryptoHash) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_CryptoHash) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHash_CreateFromArray); + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHash_Release); + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHash_Equals); + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHash_GetDigest); + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHash_GetDigestType); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, parcCryptoHash_CreateFromArray) +{ + int fd = open("test_digest_bytes_128.sha256", O_RDONLY); + assertFalse(fd < 0, "Could not open %s: %s", "test_digest_bytes_128.sha256", strerror(errno)); + + uint8_t scratch[bufferLength]; + ssize_t read_length = read(fd, scratch, bufferLength); + + PARCCryptoHash *hash = parcCryptoHash_CreateFromArray(PARCCryptoHashType_SHA256, scratch, read_length); + assertNotNull(hash, "Expected to be non null"); + + parcCryptoHash_Release(&hash); + close(fd); +} + +LONGBOW_TEST_CASE(Global, parcCryptoHash_Release) +{ + int fd = open("test_digest_bytes_128.sha256", O_RDONLY); + assertFalse(fd < 0, "Could not open %s: %s", "test_digest_bytes_128.sha256", strerror(errno)); + + uint8_t scratch[bufferLength]; + ssize_t read_length = read(fd, scratch, bufferLength); + + PARCCryptoHash *hash = parcCryptoHash_CreateFromArray(PARCCryptoHashType_SHA256, scratch, read_length); + assertNotNull(hash, "Expected to be non null"); + + parcCryptoHash_Release(&hash); + assertNull(hash, "Expected to be null"); + close(fd); +} + +LONGBOW_TEST_CASE(Global, parcCryptoHash_Equals) +{ + int fd1 = open("test_digest_bytes_128.sha256", O_RDONLY); + assertFalse(fd1 < 0, "Could not open %s: %s", "test_digest_bytes_128.sha256", strerror(errno)); + + uint8_t scratch1[bufferLength]; + ssize_t read_length = read(fd1, scratch1, bufferLength); + + PARCCryptoHash *hash1 = parcCryptoHash_CreateFromArray(PARCCryptoHashType_SHA256, scratch1, read_length); + PARCCryptoHash *hash2 = parcCryptoHash_CreateFromArray(PARCCryptoHashType_SHA256, scratch1, read_length); + PARCCryptoHash *hash3 = parcCryptoHash_CreateFromArray(PARCCryptoHashType_SHA256, scratch1, read_length); + + int fd2 = open("test_digest_bytes_128.sha512", O_RDONLY); + assertFalse(fd2 < 0, "Could not open %s: %s", "test_digest_bytes_128.sha512", strerror(errno)); + + uint8_t scratch2[bufferLength]; + read_length = read(fd2, scratch2, bufferLength); + + PARCCryptoHash *unequalhash = parcCryptoHash_CreateFromArray(PARCCryptoHashType_SHA256, scratch2, read_length); + + parcObjectTesting_AssertEqualsFunction(parcObject_Equals, hash1, hash2, hash3, unequalhash); + + parcCryptoHash_Release(&hash1); + parcCryptoHash_Release(&hash2); + parcCryptoHash_Release(&hash3); + parcCryptoHash_Release(&unequalhash); + + close(fd1); + close(fd2); +} + +LONGBOW_TEST_CASE(Global, parcCryptoHash_GetDigest) +{ + int fd_buffer = open("test_digest_bytes_128.bin", O_RDONLY); + int fd_truth = open("test_digest_bytes_128.sha256", O_RDONLY); + assertFalse(fd_buffer < 0, "Could not open %s: %s", "test_digest_bytes_128.bin", strerror(errno)); + assertFalse(fd_truth < 0, "Could not open %s: %s", "test_digest_bytes_128.sha256", strerror(errno)); + + uint8_t scratch[bufferLength]; + ssize_t read_length = read(fd_truth, scratch, bufferLength); + + PARCCryptoHash *hashTruth = parcCryptoHash_CreateFromArray(PARCCryptoHashType_SHA256, scratch, read_length); + + read_length = read(fd_buffer, scratch, bufferLength); + + PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256); + parcCryptoHasher_Init(hasher); + parcCryptoHasher_UpdateBytes(hasher, scratch, read_length); + + PARCCryptoHash *hashTest = parcCryptoHasher_Finalize(hasher); + + assertTrue(parcBuffer_Equals(parcCryptoHash_GetDigest(hashTruth), parcCryptoHash_GetDigest(hashTest)), "Expected to be true"); + + parcCryptoHasher_Release(&hasher); + parcCryptoHash_Release(&hashTruth); + parcCryptoHash_Release(&hashTest); + + close(fd_buffer); + close(fd_truth); +} + +LONGBOW_TEST_CASE(Global, parcCryptoHash_GetDigestType) +{ + int fd = open("test_digest_bytes_128.sha256", O_RDONLY); + assertFalse(fd < 0, "Could not open %s: %s", "test_digest_bytes_128.sha256", strerror(errno)); + + uint8_t scratch[bufferLength]; + ssize_t read_length = read(fd, scratch, bufferLength); + + PARCCryptoHash *hash = parcCryptoHash_CreateFromArray(PARCCryptoHashType_SHA256, scratch, read_length); + assertNotNull(hash, "Expected to be non null"); + + assertTrue(PARCCryptoHashType_SHA256 == parcCryptoHash_GetDigestType(hash), "Expected to be true"); + + parcCryptoHash_Release(&hash); + close(fd); +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_CryptoHash); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_CryptoHashType.c b/libparc/parc/security/test/test_parc_CryptoHashType.c new file mode 100644 index 00000000..1e1cc68b --- /dev/null +++ b/libparc/parc/security/test/test_parc_CryptoHashType.c @@ -0,0 +1,92 @@ +/* + * 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_CryptoHashType.c" + +#include <LongBow/unit-test.h> + +LONGBOW_TEST_RUNNER(parc_CryptoHashType) +{ + // 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); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_CryptoHashType) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_CryptoHashType) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHashType_FromString); + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHashType_ToString); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, parcCryptoHashType_FromString) +{ + assertTrue(PARCCryptoHashType_SHA256 == parcCryptoHashType_FromString("PARCCryptoHashType_SHA256"), "Expected true"); + + assertTrue(PARCCryptoHashType_SHA512 == parcCryptoHashType_FromString("PARCCryptoHashType_SHA512"), "Expected true"); + + assertTrue(PARCCryptoHashType_CRC32C == parcCryptoHashType_FromString("PARCCryptoHashType_CRC32C"), "Expected true"); + + assertTrue(PARCCryptoHashType_NULL == parcCryptoHashType_FromString("NULL"), "Expected true"); +} + +LONGBOW_TEST_CASE(Global, parcCryptoHashType_ToString) +{ + const char *string1 = parcCryptoHashType_ToString(PARCCryptoHashType_SHA256); + assertNotNull(string1, "Expected non-null result."); + + const char *string2 = parcCryptoHashType_ToString(PARCCryptoHashType_SHA512); + assertNotNull(string2, "Expected non-null result."); + + const char *string3 = parcCryptoHashType_ToString(PARCCryptoHashType_CRC32C); + assertNotNull(string3, "Expected non-null result."); + + const char *string4 = parcCryptoHashType_ToString(PARCCryptoHashType_NULL); + assertNull(string4, "Expected to be null"); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_CryptoHashType); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_CryptoHasher.c b/libparc/parc/security/test/test_parc_CryptoHasher.c new file mode 100755 index 00000000..33a3f6bc --- /dev/null +++ b/libparc/parc/security/test/test_parc_CryptoHasher.c @@ -0,0 +1,407 @@ +/* + * 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 <config.h> +#include <stdio.h> +#include <LongBow/unit-test.h> + +#include <parc/algol/parc_SafeMemory.h> +#include <parc/algol/parc_BufferComposer.h> +#include <parc/security/parc_Security.h> + +// Include the file(s) containing the functions to be tested. +// This permits internal static functions to be visible to this Test Framework. +#include "../parc_CryptoHasher.c" + +#include <fcntl.h> +#include <errno.h> +#include <sys/time.h> + +const int bufferLength = 1024; + +/* + * Ground truth set derived from CRC RevEng http://reveng.sourceforge.net + * e.g. reveng -c -m CRC-32C 313233343536373839 gives the canonical check value 0xe306928e + * + * You can also calcaulate them online at http://www.zorc.breitbandkatze.de/crc.html using + * CRC polynomial 0x1EDC6F41, init 0xFFFFFFFF, final 0xFFFFFFFF, reverse data bytes (check), + * and reverse CRC result before final XOR (check). + * + */ +struct test_vector { + uint32_t crc32c; + int length; + uint8_t *buffer; +} vectors[] = { + { .crc32c = 0xe3069283, .length = 9, .buffer = (uint8_t []) { '1', '2', '3', '4', '5', '6', '7', '8', '9' } }, + { .crc32c = 0xddb65633, .length = 1, .buffer = (uint8_t []) { 0x3D } }, + { .crc32c = 0xc203c1fd, .length = 2, .buffer = (uint8_t []) { 0x3D, 0x41 } }, + { .crc32c = 0x80a9d169, .length = 3, .buffer = (uint8_t []) { 'b', 'e', 'e' } }, + { .crc32c = 0xa099f534, .length = 4, .buffer = (uint8_t []) { 'h', 'e', 'l', 'l' } }, + { .crc32c = 0x9a71bb4c, .length = 5, .buffer = (uint8_t []) { 'h', 'e', 'l', 'l', 'o' } }, + { .crc32c = 0x2976E503, .length = 6, .buffer = (uint8_t []) { 'g', 'r', 'u', 'm', 'p', 'y' } }, + { .crc32c = 0xe627f441, .length = 7, .buffer = (uint8_t []) { 'a', 'b', 'c', 'd', 'e', 'f', 'g' } }, + { .crc32c = 0x2d265c1d, .length = 13, .buffer = (uint8_t []) { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'c', 'd', 'e', 'f'} }, + { .crc32c = 0, .length = 0, .buffer = NULL } +}; + + +LONGBOW_TEST_RUNNER(parc_CryptoHasher) +{ + // 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); +// LONGBOW_RUN_TEST_FIXTURE(Performance); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_CryptoHasher) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_CryptoHasher) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHasher_Create); + + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHasher_Bytes_256); + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHasher_Buffer_256); + + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHasher_Bytes_512); + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHasher_Buffer_512); + + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHasher_CRC32); + + LONGBOW_RUN_TEST_CASE(Global, parcCryptoHasher_CustomHasher); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + 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(Global, parcCryptoHasher_Create) +{ + PARCCryptoHasher *hasher; + + hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256); + parcCryptoHasher_Release(&hasher); + + hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA512); + PARCCryptoHasher *handle = parcCryptoHasher_Acquire(hasher); + + assertTrue(parcObject_GetReferenceCount(handle) == 2, "Expected 2 references"); + + parcCryptoHasher_Release(&hasher); + parcCryptoHasher_Release(&handle); +} + +LONGBOW_TEST_CASE(Global, parcCryptoHasher_Bytes_256) +{ + int fd_buffer = open("test_digest_bytes_128.bin", O_RDONLY); + int fd_truth = open("test_digest_bytes_128.sha256", O_RDONLY); + assertFalse(fd_buffer < 0, "Could not open %s: %s", "test_digest_bytes_128.bin", strerror(errno)); + assertFalse(fd_truth < 0, "Could not open %s: %s", "test_digest_bytes_128.sha256", strerror(errno)); + + uint8_t scratch[bufferLength]; + ssize_t read_length; + + read_length = read(fd_truth, scratch, bufferLength); + + PARCCryptoHash *digestTruth = parcCryptoHash_CreateFromArray(PARCCryptoHashType_SHA256, scratch, read_length); + + read_length = read(fd_buffer, scratch, bufferLength); + + PARCCryptoHasher *digester = parcCryptoHasher_Create(PARCCryptoHashType_SHA256); + parcCryptoHasher_Init(digester); + parcCryptoHasher_UpdateBytes(digester, scratch, read_length); + + PARCCryptoHash *digestTest = parcCryptoHasher_Finalize(digester); + + assertTrue(parcCryptoHash_Equals(digestTruth, digestTest), + "sha256 digest of 128-byte buffer using Update_Buffer does not match"); + + parcCryptoHasher_Release(&digester); + parcCryptoHash_Release(&digestTruth); + parcCryptoHash_Release(&digestTest); + + close(fd_buffer); + close(fd_truth); +} + +LONGBOW_TEST_CASE(Global, parcCryptoHasher_Buffer_256) +{ + int fd_buffer = open("test_digest_bytes_128.bin", O_RDONLY); + int fd_truth = open("test_digest_bytes_128.sha256", O_RDONLY); + assertFalse(fd_buffer < 0, "Could not open %s: %s", "test_digest_bytes_128.bin", strerror(errno)); + assertFalse(fd_truth < 0, "Could not open %s: %s", "test_digest_bytes_128.sha256", strerror(errno)); + + uint8_t scratch[bufferLength]; + + ssize_t read_length = read(fd_buffer, scratch, bufferLength); + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutArray(composer, scratch, read_length); + PARCBuffer *bb_to_digest = parcBufferComposer_ProduceBuffer(composer); + + read_length = read(fd_truth, scratch, bufferLength); + PARCCryptoHash *digestTruth = parcCryptoHash_CreateFromArray(PARCCryptoHashType_SHA256, scratch, read_length); + + PARCCryptoHasher *digester = parcCryptoHasher_Create(PARCCryptoHashType_SHA256); + parcCryptoHasher_Init(digester); + parcCryptoHasher_UpdateBuffer(digester, bb_to_digest); + PARCCryptoHash *digestTest = parcCryptoHasher_Finalize(digester); + + assertTrue(parcCryptoHash_Equals(digestTruth, digestTest), + "sha256 digest of 128-byte buffer using Update_Buffer does not match"); + + parcCryptoHasher_Release(&digester); + parcBuffer_Release(&bb_to_digest); + parcBufferComposer_Release(&composer); + parcCryptoHash_Release(&digestTruth); + parcCryptoHash_Release(&digestTest); + + close(fd_buffer); + close(fd_truth); +} + +// ==== 512 + +LONGBOW_TEST_CASE(Global, parcCryptoHasher_Bytes_512) +{ + PARCCryptoHasher *digester; + + int fd_buffer = open("test_digest_bytes_128.bin", O_RDONLY); + int fd_truth = open("test_digest_bytes_128.sha512", O_RDONLY); + assertFalse(fd_buffer < 0, "Could not open %s: %s", "test_digest_bytes_128.bin", strerror(errno)); + assertFalse(fd_truth < 0, "Could not open %s: %s", "test_digest_bytes_128.sha512", strerror(errno)); + + uint8_t scratch[bufferLength]; + ssize_t read_length; + + read_length = read(fd_truth, scratch, bufferLength); + PARCCryptoHash *digestTruth = parcCryptoHash_CreateFromArray(PARCCryptoHashType_SHA512, scratch, read_length); + + read_length = read(fd_buffer, scratch, bufferLength); + + + digester = parcCryptoHasher_Create(PARCCryptoHashType_SHA512); + parcCryptoHasher_Init(digester); + parcCryptoHasher_UpdateBytes(digester, scratch, read_length); + PARCCryptoHash *digestTest = parcCryptoHasher_Finalize(digester); + + assertTrue(parcCryptoHash_Equals(digestTruth, digestTest), "sha512 digest of 128-byte buffer using Update_Buffer does not match"); + + parcCryptoHasher_Release(&digester); + parcCryptoHash_Release(&digestTruth); + parcCryptoHash_Release(&digestTest); + + close(fd_buffer); + close(fd_truth); +} + +LONGBOW_TEST_CASE(Global, parcCryptoHasher_Buffer_512) +{ + int fd_buffer = open("test_digest_bytes_128.bin", O_RDONLY); + int fd_truth = open("test_digest_bytes_128.sha512", O_RDONLY); + assertFalse(fd_buffer < 0, "Could not open %s: %s", "test_digest_bytes_128.bin", strerror(errno)); + assertFalse(fd_truth < 0, "Could not open %s: %s", "test_digest_bytes_128.sha512", strerror(errno)); + + uint8_t scratch[bufferLength]; + ssize_t read_length; + + read_length = read(fd_buffer, scratch, bufferLength); + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutArray(composer, scratch, read_length); + PARCBuffer *bb_to_digest = parcBufferComposer_ProduceBuffer(composer); + + read_length = read(fd_truth, scratch, bufferLength); + PARCCryptoHash *digestTruth = parcCryptoHash_CreateFromArray(PARCCryptoHashType_SHA512, scratch, read_length); + + PARCCryptoHasher *digester = parcCryptoHasher_Create(PARCCryptoHashType_SHA512); + parcCryptoHasher_Init(digester); + parcCryptoHasher_UpdateBuffer(digester, bb_to_digest); + PARCCryptoHash *digestTest = parcCryptoHasher_Finalize(digester); + + assertTrue(parcCryptoHash_Equals(digestTruth, digestTest), + "sha512 digest of 128-byte buffer using Update_Buffer does not match"); + + parcCryptoHasher_Release(&digester); + parcBuffer_Release(&bb_to_digest); + parcBufferComposer_Release(&composer); + parcCryptoHash_Release(&digestTruth); + parcCryptoHash_Release(&digestTest); + + close(fd_buffer); + close(fd_truth); +} + +LONGBOW_TEST_CASE(Global, parcCryptoHasher_CRC32) +{ + for (int i = 0; vectors[i].buffer != NULL; i++) { + PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_CRC32C); + parcCryptoHasher_Init(hasher); + parcCryptoHasher_UpdateBytes(hasher, vectors[i].buffer, vectors[i].length); + PARCCryptoHash *output = parcCryptoHasher_Finalize(hasher); + PARCBuffer *buffer = parcCryptoHash_GetDigest(output); + uint32_t testCrc = parcBuffer_GetUint32(buffer); + parcCryptoHash_Release(&output); + + assertTrue(testCrc == vectors[i].crc32c, + "CRC32C values wrong, index %d got 0x%08x expected 0x%08x\n", + i, testCrc, vectors[i].crc32c); + parcCryptoHasher_Release(&hasher); + } +} + +LONGBOW_TEST_CASE(Global, parcCryptoHasher_CustomHasher) +{ + PARCCryptoHasher *hasher = parcCryptoHasher_CustomHasher(PARCCryptoHashType_SHA512, functor_sha256); + assertNotNull(hasher, "Expected to be non null"); + + parcCryptoHasher_Release(&hasher); +} + +// ================================================ + +LONGBOW_TEST_FIXTURE(Local) +{ + LONGBOW_RUN_TEST_CASE(Local, computeCrc32C_Software); +} + +LONGBOW_TEST_FIXTURE_SETUP(Local) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Local) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Local, computeCrc32C_Software) +{ + for (int i = 0; vectors[i].buffer != NULL; i++) { + uint32_t testCrc = _crc32c_Init(); + testCrc = _crc32c_UpdateSoftware(testCrc, vectors[i].length, vectors[i].buffer); + testCrc = _crc32c_Finalize(testCrc); + + assertTrue(testCrc == vectors[i].crc32c, + "CRC32C values wrong, index %d got 0x%08x expected 0x%08x\n", + i, testCrc, vectors[i].crc32c); + } +} + +// ======================================================= + +LONGBOW_TEST_FIXTURE(Performance) +{ + LONGBOW_RUN_TEST_CASE(Performance, computeCrc32C); + LONGBOW_RUN_TEST_CASE(Performance, computeCrc32C_Software); +} + +LONGBOW_TEST_FIXTURE_SETUP(Performance) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Performance) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +static double +runPerformance(int maxreps, uint32_t (*update)(uint32_t crc, size_t len, uint8_t p[len])) +{ + int reps = maxreps; + int length = 100; + + uint8_t buffer[length]; + for (int i = 0; i < length; i++) { + buffer[i] = i * 33; + } + + // initial value doesnt really matter + + struct timeval t0, t1; + gettimeofday(&t0, NULL); + while (--reps) { + uint32_t crc = _crc32c_Init(); + update(crc, length, buffer); + crc = _crc32c_Finalize(crc); + } + + gettimeofday(&t1, NULL); + + timersub(&t1, &t0, &t1); + + double seconds = t1.tv_sec + t1.tv_usec * 1E-6; + return seconds; +} + +LONGBOW_TEST_CASE(Performance, computeCrc32C) +{ + int maxreps = 1000000; + double seconds = runPerformance(maxreps, _crc32c_Update); + double rate = maxreps / seconds; + + printf("Best rate = %.3f for %d iterations\n", rate, maxreps); +} + +LONGBOW_TEST_CASE(Performance, computeCrc32C_Software) +{ + int maxreps = 1000000; + double seconds = runPerformance(maxreps, _crc32c_UpdateSoftware); + double rate = maxreps / seconds; + + printf("Best rate = %.3f for %d iterations\n", rate, maxreps); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_CryptoHasher); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_CryptoSuite.c b/libparc/parc/security/test/test_parc_CryptoSuite.c new file mode 100755 index 00000000..f210fd79 --- /dev/null +++ b/libparc/parc/security/test/test_parc_CryptoSuite.c @@ -0,0 +1,82 @@ +/* + * 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_CryptoSuite.c" + +#include <LongBow/unit-test.h> + +LONGBOW_TEST_RUNNER(parc_CryptoSuite) +{ + // 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); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_CryptoSuite) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_CryptoSuite) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcCryptoSuite_GetCryptoHash); + LONGBOW_RUN_TEST_CASE(Global, parcCryptoSuite_GetCryptoHash_IllegalValue); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, parcCryptoSuite_GetCryptoHash) +{ + assertTrue(PARCCryptoHashType_SHA256 == parcCryptoSuite_GetCryptoHash(PARCCryptoSuite_RSA_SHA256), "Expected to be true"); + assertTrue(PARCCryptoHashType_SHA256 == parcCryptoSuite_GetCryptoHash(PARCCryptoSuite_DSA_SHA256), "Expected to be true"); + assertTrue(PARCCryptoHashType_SHA512 == parcCryptoSuite_GetCryptoHash(PARCCryptoSuite_RSA_SHA512), "Expected to be true"); + assertTrue(PARCCryptoHashType_SHA256 == parcCryptoSuite_GetCryptoHash(PARCCryptoSuite_HMAC_SHA256), "Expected to be true"); + assertTrue(PARCCryptoHashType_SHA512 == parcCryptoSuite_GetCryptoHash(PARCCryptoSuite_HMAC_SHA512), "Expected to be true"); + assertTrue(PARCCryptoHashType_CRC32C == parcCryptoSuite_GetCryptoHash(PARCCryptoSuite_NULL_CRC32C), "Expected to be true"); + assertTrue(PARCCryptoHashType_SHA256 == parcCryptoSuite_GetCryptoHash(PARCCryptoSuite_EC_SECP_256K1), "Expected to be true"); +} + +LONGBOW_TEST_CASE_EXPECTS(Global, parcCryptoSuite_GetCryptoHash_IllegalValue, .event = &LongBowTrapIllegalValue) +{ + parcCryptoSuite_GetCryptoHash(PARCCryptoSuite_UNKNOWN); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_CryptoSuite); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_DiffieHellman.c b/libparc/parc/security/test/test_parc_DiffieHellman.c new file mode 100755 index 00000000..69bc109b --- /dev/null +++ b/libparc/parc/security/test/test_parc_DiffieHellman.c @@ -0,0 +1,93 @@ +/* + * 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 <config.h> +#include <stdio.h> +#include <LongBow/unit-test.h> +#include <parc/testing/parc_ObjectTesting.h> + +#include "../parc_DiffieHellman.c" +#include <parc/algol/parc_SafeMemory.h> +#include <parc/security/parc_CryptoHashType.h> +#include <parc/algol/parc_Buffer.h> + +LONGBOW_TEST_RUNNER(parc_DiffieHellman) +{ + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +LONGBOW_TEST_RUNNER_SETUP(parc_DiffieHellman) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_DiffieHellman) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcDiffieHellman_AcquireRelease); + LONGBOW_RUN_TEST_CASE(Global, parcDiffieHellman_Create); + LONGBOW_RUN_TEST_CASE(Global, parcDiffieHellman_GenerateKeyShare); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + 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, parcDiffieHellman_Create) +{ + PARCDiffieHellman *dh = parcDiffieHellman_Create(PARCDiffieHellmanGroup_Secp521r1); + assertNotNull(dh, "Expected a non-NULL PARCDiffieHellman instance"); + parcDiffieHellman_Release(&dh); +} + +LONGBOW_TEST_CASE(Global, parcDiffieHellman_AcquireRelease) +{ + PARCDiffieHellman *dh = parcDiffieHellman_Create(PARCDiffieHellmanGroup_Secp521r1); + parcObjectTesting_AssertAcquireReleaseContract(parcDiffieHellman_Acquire, dh); + parcDiffieHellman_Release(&dh); +} + +LONGBOW_TEST_CASE(Global, parcDiffieHellman_GenerateKeyShare) +{ + PARCDiffieHellman *dh = parcDiffieHellman_Create(PARCDiffieHellmanGroup_Secp521r1); + PARCDiffieHellmanKeyShare *keyShare = parcDiffieHellman_GenerateKeyShare(dh); + assertNotNull(keyShare, "Expected a non-NULL PARCDiffieHellmanKeyShare instance"); + parcDiffieHellmanKeyShare_Release(&keyShare); + parcDiffieHellman_Release(&dh); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_DiffieHellman); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_DiffieHellmanKeyShare.c b/libparc/parc/security/test/test_parc_DiffieHellmanKeyShare.c new file mode 100755 index 00000000..e8a2eeca --- /dev/null +++ b/libparc/parc/security/test/test_parc_DiffieHellmanKeyShare.c @@ -0,0 +1,229 @@ +/* + * 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 <config.h> +#include <stdio.h> +#include <LongBow/unit-test.h> +#include <parc/testing/parc_ObjectTesting.h> + +#include "../parc_DiffieHellmanKeyShare.c" +#include <parc/algol/parc_SafeMemory.h> +#include <parc/security/parc_CryptoHashType.h> +#include <parc/algol/parc_Buffer.h> + +LONGBOW_TEST_RUNNER(parc_DiffieHellmanKeyShare) +{ + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +LONGBOW_TEST_RUNNER_SETUP(parc_DiffieHellmanKeyShare) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_DiffieHellmanKeyShare) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcDiffieHellmanKeyShare_AcquireRelease); + LONGBOW_RUN_TEST_CASE(Global, parcDiffieHellmanKeyShare_Create); + LONGBOW_RUN_TEST_CASE(Global, parcDiffieHellmanKeyShare_SerializePublicKey); + LONGBOW_RUN_TEST_CASE(Global, parcDiffieHellmanKeyShare_SerializeDeserializePublicKey); + LONGBOW_RUN_TEST_CASE(Global, parcDiffieHellmanKeyShare_DeserializePublicKey_ErrorWrongGroup); + LONGBOW_RUN_TEST_CASE(Global, parcDiffieHellmanKeyShare_DeserializePublicKey_ErrorInvalidEncoding); + LONGBOW_RUN_TEST_CASE(Global, parcDiffieHellmanKeyShare_Combine); + LONGBOW_RUN_TEST_CASE(Global, parcDiffieHellmanKeyShare_Combine_Error_PublicKeyDeserializationFail); + LONGBOW_RUN_TEST_CASE(Global, _parcDiffieHellmanKeyShare_HashSharedSecret); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + 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, parcDiffieHellmanKeyShare_AcquireRelease) +{ + PARCDiffieHellmanKeyShare *dh = parcDiffieHellmanKeyShare_Create(PARCDiffieHellmanGroup_Secp521r1); + parcObjectTesting_AssertAcquireReleaseContract(parcDiffieHellmanKeyShare_Acquire, dh); + parcDiffieHellmanKeyShare_Release(&dh); +} + +LONGBOW_TEST_CASE(Global, parcDiffieHellmanKeyShare_Create) +{ + PARCDiffieHellmanKeyShare *dh = parcDiffieHellmanKeyShare_Create(PARCDiffieHellmanGroup_Secp521r1); + assertNotNull(dh, "Expected a non-NULL PARCDiffieHellmanKeyShare instance"); + parcDiffieHellmanKeyShare_Release(&dh); +} + +LONGBOW_TEST_CASE(Global, parcDiffieHellmanKeyShare_SerializePublicKey) +{ + PARCDiffieHellmanKeyShare *keyShare = parcDiffieHellmanKeyShare_Create(PARCDiffieHellmanGroup_Secp521r1); + assertNotNull(keyShare, "Expected a non-NULL PARCDiffieHellmanKeyShare instance"); + + PARCBuffer *publicKey = parcDiffieHellmanKeyShare_SerializePublicKey(keyShare); + assertNotNull(publicKey, "Expected the public key to be serialized to a non-NULL PARCBuffer"); + + const size_t sec521r1KeySize = 266; + assertTrue(parcBuffer_Remaining(publicKey) == sec521r1KeySize, "Expected the public key size to be %zu, got %zu", sec521r1KeySize, parcBuffer_Remaining(publicKey)); + + parcBuffer_Release(&publicKey); + parcDiffieHellmanKeyShare_Release(&keyShare); +} + +LONGBOW_TEST_CASE(Global, parcDiffieHellmanKeyShare_SerializeDeserializePublicKey) +{ + PARCDiffieHellmanKeyShare *keyShare = parcDiffieHellmanKeyShare_Create(PARCDiffieHellmanGroup_Secp521r1); + assertNotNull(keyShare, "Expected a non-NULL PARCDiffieHellmanKeyShare instance"); + + PARCBuffer *publicKey = parcDiffieHellmanKeyShare_SerializePublicKey(keyShare); + assertNotNull(publicKey, "Expected the public key to be serialized to a non-NULL PARCBuffer"); + + const size_t sec521r1KeySize = 266; + assertTrue(parcBuffer_Remaining(publicKey) == sec521r1KeySize, "Expected the public key size to be %zu, got %zu", sec521r1KeySize, parcBuffer_Remaining(publicKey)); + + // Deserialize the public key to get the OpenSSL EVP_PKEY type + EVP_PKEY *rawPublicKey = _parcDiffieHellman_DeserializePublicKeyShare(keyShare, publicKey); + assertNotNull(rawPublicKey, "Expected the raw public key to be deserialized"); + + // Extract the public portions of the private key share and public key share + EC_KEY *publicEcKey = EVP_PKEY_get1_EC_KEY(rawPublicKey); + const EC_POINT *publicPoint = EC_KEY_get0_public_key(publicEcKey); + + EC_KEY *privateEcKey = EVP_PKEY_get1_EC_KEY(keyShare->privateKey); + const EC_POINT *privatePoint = EC_KEY_get0_public_key(privateEcKey); + + // Compare the public portions of the key shares + const EC_GROUP *group = EC_KEY_get0_group(publicEcKey); + BN_CTX *bigNumberContext = BN_CTX_new(); + int equalResult = EC_POINT_cmp(group, publicPoint, privatePoint, bigNumberContext); + assertTrue(equalResult == 0, "Expected the two public points to be equal."); + + BN_CTX_free(bigNumberContext); + EVP_PKEY_free(rawPublicKey); + parcBuffer_Release(&publicKey); + parcDiffieHellmanKeyShare_Release(&keyShare); +} + +LONGBOW_TEST_CASE(Global, parcDiffieHellmanKeyShare_DeserializePublicKey_ErrorWrongGroup) +{ + PARCDiffieHellmanKeyShare *keyShare = parcDiffieHellmanKeyShare_Create(PARCDiffieHellmanGroup_Secp521r1); + assertNotNull(keyShare, "Expected a non-NULL PARCDiffieHellmanKeyShare instance"); + + PARCBuffer *publicKey = parcDiffieHellmanKeyShare_SerializePublicKey(keyShare); + assertNotNull(publicKey, "Expected the public key to be serialized to a non-NULL PARCBuffer"); + + PARCDiffieHellmanKeyShare *alternateKeyShare = parcDiffieHellmanKeyShare_Create(PARCDiffieHellmanGroup_Prime256v1); + + // Deserialize the public key with a different group and hit the failure + EVP_PKEY *rawPublicKey = _parcDiffieHellman_DeserializePublicKeyShare(alternateKeyShare, publicKey); + assertNull(rawPublicKey, "Expected the raw public key to not be deserialized"); + + parcBuffer_Release(&publicKey); + parcDiffieHellmanKeyShare_Release(&keyShare); + parcDiffieHellmanKeyShare_Release(&alternateKeyShare); +} + +LONGBOW_TEST_CASE(Global, parcDiffieHellmanKeyShare_DeserializePublicKey_ErrorInvalidEncoding) +{ + PARCDiffieHellmanKeyShare *keyShare = parcDiffieHellmanKeyShare_Create(PARCDiffieHellmanGroup_Secp521r1); + assertNotNull(keyShare, "Expected a non-NULL PARCDiffieHellmanKeyShare instance"); + + // Deserialize the public key with a different group + PARCBuffer *publicKey = parcBuffer_Allocate(32); + EVP_PKEY *rawPublicKey = _parcDiffieHellman_DeserializePublicKeyShare(keyShare, publicKey); + assertNull(rawPublicKey, "Expected the raw public key to not be deserialized"); + + parcBuffer_Release(&publicKey); + parcDiffieHellmanKeyShare_Release(&keyShare); +} + +LONGBOW_TEST_CASE(Global, parcDiffieHellmanKeyShare_Combine) +{ + PARCDiffieHellmanKeyShare *keyShare = parcDiffieHellmanKeyShare_Create(PARCDiffieHellmanGroup_Secp521r1); + assertNotNull(keyShare, "Expected a non-NULL PARCDiffieHellmanKeyShare instance"); + + PARCBuffer *publicKey = parcDiffieHellmanKeyShare_SerializePublicKey(keyShare); + assertNotNull(publicKey, "Expected the public key to be serialized to a non-NULL PARCBuffer"); + + PARCBuffer *sharedSecret = parcDiffieHellmanKeyShare_Combine(keyShare, publicKey); + assertNotNull(sharedSecret, "Expected the shared secret to be non-NULL"); + + const size_t secretSize = 32; // = 256 / 8 bytes + assertTrue(parcBuffer_Remaining(sharedSecret) == secretSize, "invalid size"); + + parcBuffer_Release(&sharedSecret); + parcBuffer_Release(&publicKey); + parcDiffieHellmanKeyShare_Release(&keyShare); +} + +LONGBOW_TEST_CASE(Global, parcDiffieHellmanKeyShare_Combine_Error_PublicKeyDeserializationFail) +{ + PARCDiffieHellmanKeyShare *keyShare = parcDiffieHellmanKeyShare_Create(PARCDiffieHellmanGroup_Secp521r1); + assertNotNull(keyShare, "Expected a non-NULL PARCDiffieHellmanKeyShare instance"); + + PARCBuffer *publicKey = parcBuffer_Allocate(32); + PARCBuffer *sharedSecret = parcDiffieHellmanKeyShare_Combine(keyShare, publicKey); + assertNull(sharedSecret, "Expected the shared secret to be non-NULL"); + + parcBuffer_Release(&publicKey); + parcDiffieHellmanKeyShare_Release(&keyShare); +} + +LONGBOW_TEST_CASE(Global, _parcDiffieHellmanKeyShare_HashSharedSecret) +{ + PARCBuffer *input = parcBuffer_Allocate(1024); + PARCBuffer *digestValue = _parcDiffieHellmanKeyShare_HashSharedSecret(input); + size_t digestLength = parcBuffer_Remaining(digestValue); + size_t expectedLength = 32; // 256 bits for PARCCryptoHashType_SHA256 + assertTrue(digestLength == 32, "Expected a %zu byte digest, got %zu", expectedLength, digestLength); + + PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256); + parcCryptoHasher_Init(hasher); + parcCryptoHasher_UpdateBuffer(hasher, input); + PARCCryptoHash *digest = parcCryptoHasher_Finalize(hasher); + + PARCBuffer *computedDigest = parcBuffer_Acquire(parcCryptoHash_GetDigest(digest)); + + parcCryptoHash_Release(&digest); + parcCryptoHasher_Release(&hasher); + + assertTrue(parcBuffer_Equals(digestValue, computedDigest), "Expected the secret input to be hashed correctly."); + + parcBuffer_Release(&input); + parcBuffer_Release(&digestValue); + parcBuffer_Release(&computedDigest); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_DiffieHellmanKeyShare); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_Identity.c b/libparc/parc/security/test/test_parc_Identity.c new file mode 100644 index 00000000..4177cc98 --- /dev/null +++ b/libparc/parc/security/test/test_parc_Identity.c @@ -0,0 +1,232 @@ +/* + * 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. + */ + +/** + * @header <#Headline Name#> + * @abstract <#Abstract#> + * @discussion + * <#Discussion#> + * + */ +// Include the file(s) containing the functions to be tested. +// This permits internal static functions to be visible to this Test Framework. +#include "../parc_Identity.c" +#include "../parc_IdentityFile.h" +#include "../parc_Security.h" + +#include <stdio.h> +#include <fcntl.h> +#include <inttypes.h> + +#include <LongBow/unit-test.h> + +#include <parc/algol/parc_SafeMemory.h> +#include <parc/testing/parc_ObjectTesting.h> + +LONGBOW_TEST_RUNNER(test_parc_Identity) +{ + // 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); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(test_parc_Identity) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(test_parc_Identity) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcIdentity_Create); + LONGBOW_RUN_TEST_CASE(Global, parcIdentity_Acquire); + LONGBOW_RUN_TEST_CASE(Global, parcIdentity_GetFileName); + LONGBOW_RUN_TEST_CASE(Global, parcIdentity_GetPassWord); + LONGBOW_RUN_TEST_CASE(Global, parcIdentity_CreateSigner); + LONGBOW_RUN_TEST_CASE(Global, parcIdentity_Equals); + LONGBOW_RUN_TEST_CASE(Global, parcIdentity_Display); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO); + if (outstandingAllocations != 0) { + printf("Tests leak memory by %d allocations\n", outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, parcIdentity_Create) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + assertNotNull(identityFile, "Expected non-null"); + + PARCIdentity *identity = parcIdentity_Create(identityFile, PARCIdentityFileAsPARCIdentity); + assertNotNull(identity, "Expected non-null"); + parcIdentityFile_Release(&identityFile); + + parcIdentity_Release(&identity); +} + +LONGBOW_TEST_CASE(Global, parcIdentity_Acquire) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + assertNotNull(identityFile, "Expected non-null"); + + PARCIdentity *identity = parcIdentity_Create(identityFile, PARCIdentityFileAsPARCIdentity); + assertNotNull(identity, "Expected non-null"); + + parcObjectTesting_AssertAcquireReleaseContract(parcIdentity_Acquire, identity); + + parcIdentityFile_Release(&identityFile); + parcIdentity_Release(&identity); +} + +LONGBOW_TEST_CASE(Global, parcIdentity_GetFileName) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + assertNotNull(identityFile, "Expected non-null"); + + PARCIdentity *identity = parcIdentity_Create(identityFile, PARCIdentityFileAsPARCIdentity); + assertNotNull(identity, "Expected non-null"); + + assertEqualStrings(keystoreName, parcIdentity_GetFileName(identity)); + + parcIdentityFile_Release(&identityFile); + parcIdentity_Release(&identity); +} + +LONGBOW_TEST_CASE(Global, parcIdentity_GetPassWord) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + assertNotNull(identityFile, "Expected non-null"); + + PARCIdentity *identity = parcIdentity_Create(identityFile, PARCIdentityFileAsPARCIdentity); + assertNotNull(identity, "Expected non-null"); + + assertEqualStrings(keystorePassword, parcIdentity_GetPassWord(identity)); + + parcIdentityFile_Release(&identityFile); + parcIdentity_Release(&identity); +} + +LONGBOW_TEST_CASE(Global, parcIdentity_CreateSigner) +{ + parcSecurity_Init(); + + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + assertNotNull(identityFile, "Expected non-null"); + + PARCIdentity *identity = parcIdentity_Create(identityFile, PARCIdentityFileAsPARCIdentity); + assertNotNull(identity, "Expected non-null"); + + assertEqualStrings(keystorePassword, parcIdentity_GetPassWord(identity)); + + PARCSigner *signer = parcIdentity_CreateSigner(identity); + + assertNotNull(signer, "Expected non-null"); + + parcIdentityFile_Release(&identityFile); + parcIdentity_Release(&identity); + parcSigner_Release(&signer); + + parcSecurity_Fini(); +} + +LONGBOW_TEST_CASE(Global, parcIdentity_Equals) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFileX = parcIdentityFile_Create(keystoreName, keystorePassword); + PARCIdentity *x = parcIdentity_Create(identityFileX, PARCIdentityFileAsPARCIdentity); + PARCIdentityFile *identityFileY = parcIdentityFile_Create(keystoreName, keystorePassword); + PARCIdentity *y = parcIdentity_Create(identityFileY, PARCIdentityFileAsPARCIdentity); + PARCIdentityFile *identityFileZ = parcIdentityFile_Create(keystoreName, keystorePassword); + PARCIdentity *z = parcIdentity_Create(identityFileZ, PARCIdentityFileAsPARCIdentity); + + PARCIdentityFile *identityFile1 = parcIdentityFile_Create("foo", keystorePassword); + PARCIdentityFile *identityFile2 = parcIdentityFile_Create(keystoreName, "bar"); + PARCIdentity *u1 = parcIdentity_Create(identityFile1, PARCIdentityFileAsPARCIdentity); + PARCIdentity *u2 = parcIdentity_Create(identityFile2, PARCIdentityFileAsPARCIdentity); + + parcObjectTesting_AssertEqualsFunction(parcIdentity_Equals, x, y, z, u1, u2); + + parcIdentityFile_Release(&identityFileX); + parcIdentityFile_Release(&identityFileY); + parcIdentityFile_Release(&identityFileZ); + parcIdentityFile_Release(&identityFile1); + parcIdentityFile_Release(&identityFile2); + + parcIdentity_Release(&x); + parcIdentity_Release(&y); + parcIdentity_Release(&z); + parcIdentity_Release(&u1); + parcIdentity_Release(&u2); +} + +LONGBOW_TEST_CASE(Global, parcIdentity_Display) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + assertNotNull(identityFile, "Expected non-null"); + + PARCIdentity *identity = parcIdentity_Create(identityFile, PARCIdentityFileAsPARCIdentity); + assertNotNull(identity, "Expected non-null"); + + parcIdentity_Display(identity, 0); + + parcIdentityFile_Release(&identityFile); + parcIdentity_Release(&identity); +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(test_parc_Identity); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_IdentityFile.c b/libparc/parc/security/test/test_parc_IdentityFile.c new file mode 100644 index 00000000..cbc877f2 --- /dev/null +++ b/libparc/parc/security/test/test_parc_IdentityFile.c @@ -0,0 +1,242 @@ +/* + * 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_IdentityFile.c" +#include "../parc_Security.h" + +#include <stdio.h> +#include <fcntl.h> +#include <inttypes.h> + +#include <LongBow/unit-test.h> + +#include <parc/algol/parc_SafeMemory.h> +#include <parc/testing/parc_ObjectTesting.h> + +LONGBOW_TEST_RUNNER(parc_IdentityFile) +{ + // 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); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_IdentityFile) +{ + parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_IdentityFile) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcIdentityFile_Create); + LONGBOW_RUN_TEST_CASE(Global, parcIdentityFile_Release); + LONGBOW_RUN_TEST_CASE(Global, parcIdentityFile_Acquire); + LONGBOW_RUN_TEST_CASE(Global, parcIdentityFile_Equals); + LONGBOW_RUN_TEST_CASE(Global, parcIdentityFile_GetFileName); + LONGBOW_RUN_TEST_CASE(Global, parcIdentityFile_GetPassWord); + LONGBOW_RUN_TEST_CASE(Global, parcIdentityFile_CreateSigner); +// LONGBOW_RUN_TEST_CASE(Global, parcIdentityFile_Display); +// LONGBOW_RUN_TEST_CASE(Global, parcIdentityFile_Exists_True); +// LONGBOW_RUN_TEST_CASE(Global, parcIdentityFile_Exists_False); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + 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, parcIdentityFile_Acquire) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + + assertNotNull(identityFile, "Expected non-null"); + + parcObjectTesting_AssertAcquireReleaseContract(parcIdentityFile_Acquire, identityFile); + + parcIdentityFile_Release(&identityFile); +} + +LONGBOW_TEST_CASE(Global, parcIdentityFile_Create) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + + assertNotNull(identityFile, "Expected non-null"); + + parcIdentityFile_Release(&identityFile); +} + +LONGBOW_TEST_CASE(Global, parcIdentityFile_GetFileName) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + + assertNotNull(identityFile, "Expected non-null"); + + assertEqualStrings(keystoreName, parcIdentityFile_GetFileName(identityFile)); + + parcIdentityFile_Release(&identityFile); +} + +LONGBOW_TEST_CASE(Global, parcIdentityFile_GetPassWord) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + + assertNotNull(identityFile, "Expected non-null"); + + assertEqualStrings(keystorePassword, parcIdentityFile_GetPassWord(identityFile)); + + parcIdentityFile_Release(&identityFile); +} + +LONGBOW_TEST_CASE(Global, parcIdentityFile_Exists_True) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + + bool actual = parcIdentityFile_Exists(identityFile); + + assertTrue(actual, "Expected %s to exist.", parcIdentityFile_GetFileName(identityFile)); + + parcIdentityFile_Release(&identityFile); +} + +LONGBOW_TEST_CASE(Global, parcIdentityFile_Exists_False) +{ + const char *keystoreName = "/dev/notgoingtoexist"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + + bool actual = parcIdentityFile_Exists(identityFile); + + assertFalse(actual, "Expected %s to not exist.", parcIdentityFile_GetFileName(identityFile)); + + parcIdentityFile_Release(&identityFile); +} + +LONGBOW_TEST_CASE(Global, parcIdentityFile_CreateSigner) +{ + parcSecurity_Init(); + + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + + assertNotNull(identityFile, "Expected non-null"); + + char cwd[1024]; + if (getcwd(cwd, sizeof(cwd)) != NULL) { + fprintf(stdout, "Current working dir: %s\n", cwd); + } else { + perror("getcwd() error"); + } + PARCSigner *signer = parcIdentityFile_CreateSigner(identityFile); + + assertNotNull(signer, "Expected non-null"); + + parcIdentityFile_Release(&identityFile); + parcSigner_Release(&signer); + + parcSecurity_Fini(); +} + +LONGBOW_TEST_CASE(Global, parcIdentityFile_Release) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + + assertNotNull(identityFile, "Expected non-null"); + + parcIdentityFile_Release(&identityFile); + assertNull(identityFile, "Identity File was not nulled out after Release()"); +} + +LONGBOW_TEST_CASE(Global, parcIdentityFile_Equals) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *x = parcIdentityFile_Create(keystoreName, keystorePassword); + PARCIdentityFile *y = parcIdentityFile_Create(keystoreName, keystorePassword); + PARCIdentityFile *z = parcIdentityFile_Create(keystoreName, keystorePassword); + PARCIdentityFile *u1 = parcIdentityFile_Create("foo", keystorePassword); + PARCIdentityFile *u2 = parcIdentityFile_Create(keystoreName, "bar"); + + parcObjectTesting_AssertEqualsFunction(parcIdentityFile_Equals, x, y, z, u1, u2); + + parcIdentityFile_Release(&x); + parcIdentityFile_Release(&y); + parcIdentityFile_Release(&z); + parcIdentityFile_Release(&u1); + parcIdentityFile_Release(&u2); +} + +LONGBOW_TEST_CASE(Global, parcIdentityFile_Display) +{ + const char *keystoreName = "test_rsa.p12"; + const char *keystorePassword = "blueberry"; + + PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); + assertNotNull(identityFile, "Expected non-null"); + + parcIdentityFile_Display(identityFile, 0); + + parcIdentityFile_Release(&identityFile); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_IdentityFile); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} 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..1d8c9b0f --- /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 *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + parcKeyStore_Release(&keyStore); + + data->signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&publicKeySigner); + 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); +} diff --git a/libparc/parc/security/test/test_parc_Key.c b/libparc/parc/security/test/test_parc_Key.c new file mode 100755 index 00000000..d22362b0 --- /dev/null +++ b/libparc/parc/security/test/test_parc_Key.c @@ -0,0 +1,357 @@ +/* + * 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_Key.c" + +#include <LongBow/unit-test.h> +#include <parc/testing/parc_ObjectTesting.h> + +LONGBOW_TEST_RUNNER(parc_Key) +{ + LONGBOW_RUN_TEST_FIXTURE(Global); + LONGBOW_RUN_TEST_FIXTURE(Errors); +} + +LONGBOW_TEST_RUNNER_SETUP(parc_Key) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_RUNNER_TEARDOWN(parc_Key) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcKey_CreateFromDerEncodedPublicKey); + LONGBOW_RUN_TEST_CASE(Global, parcKey_CreateFromSymmetricKey); + LONGBOW_RUN_TEST_CASE(Global, parcKey_Equals); + LONGBOW_RUN_TEST_CASE(Global, parcKey_Copy); + LONGBOW_RUN_TEST_CASE(Global, parcKey_GetKey); + LONGBOW_RUN_TEST_CASE(Global, parcKey_GetKeyId); + LONGBOW_RUN_TEST_CASE(Global, parcKey_GetSigningAlgorithm); + LONGBOW_RUN_TEST_CASE(Global, parcKey_Acquire); + LONGBOW_RUN_TEST_CASE(Global, parcKey_ToString); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, parcKey_Copy) +{ + PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid = parcKeyId_Create(bb_id); + parcBuffer_Release(&bb_id); + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer, "quack quack"); + PARCBuffer *bb_key = parcBufferComposer_ProduceBuffer(composer); + + PARCKey *key = parcKey_CreateFromDerEncodedPublicKey(keyid, PARCSigningAlgorithm_RSA, bb_key); + parcKey_AssertValid(key); + + PARCKey *copy = parcKey_Copy(key); + parcKey_AssertValid(copy); + + assertTrue(parcKey_Equals(key, copy), "Expected the original key instance and its copy to be equal"); + + parcKey_Release(©); + parcKey_Release(&key); + parcBuffer_Release(&bb_key); + parcBufferComposer_Release(&composer); + parcKeyId_Release(&keyid); +} + +LONGBOW_TEST_CASE(Global, parcKey_CreateFromDerEncodedPublicKey) +{ + PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid = parcKeyId_Create(bb_id); + parcBuffer_Release(&bb_id); + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer, "quack quack"); + PARCBuffer *bb_key = parcBufferComposer_ProduceBuffer(composer); + + PARCKey *key = parcKey_CreateFromDerEncodedPublicKey(keyid, PARCSigningAlgorithm_RSA, bb_key); + + parcKey_AssertValid(key); + + parcKey_Release(&key); + parcBuffer_Release(&bb_key); + parcBufferComposer_Release(&composer); + parcKeyId_Release(&keyid); +} + +LONGBOW_TEST_CASE(Global, parcKey_CreateFromSymmetricKey) +{ + PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid = parcKeyId_Create(bb_id); + parcBuffer_Release(&bb_id); + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer, "quack quack"); + PARCBuffer *bb_key = parcBufferComposer_ProduceBuffer(composer); + PARCKey *key = parcKey_CreateFromSymmetricKey(keyid, PARCSigningAlgorithm_HMAC, bb_key); + + parcKey_AssertValid(key); + + parcKey_Release(&key); + parcBuffer_Release(&bb_key); + parcBufferComposer_Release(&composer); + parcKeyId_Release(&keyid); +} + +LONGBOW_TEST_CASE(Global, parcKey_Equals) +{ + PARCBuffer *bb_id_1 = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid_1 = parcKeyId_Create(bb_id_1); + parcBuffer_Release(&bb_id_1); + + PARCBuffer *bb_id_2 = parcBuffer_Wrap("chugga chugga", 13, 0, 13); + PARCKeyId *keyid_2 = parcKeyId_Create(bb_id_2); + parcBuffer_Release(&bb_id_2); + + PARCBufferComposer *composer1 = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer1, "quack quack"); + PARCBuffer *bb_key_1 = parcBufferComposer_ProduceBuffer(composer1); + + PARCKey *x = parcKey_CreateFromDerEncodedPublicKey(keyid_1, PARCSigningAlgorithm_RSA, bb_key_1); + PARCKey *y = parcKey_CreateFromDerEncodedPublicKey(keyid_1, PARCSigningAlgorithm_RSA, bb_key_1); + PARCKey *z = parcKey_CreateFromDerEncodedPublicKey(keyid_1, PARCSigningAlgorithm_RSA, bb_key_1); + + PARCBufferComposer *composer2 = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer2, "mew mew"); + PARCBuffer *bb_key_2 = parcBufferComposer_ProduceBuffer(composer2); + PARCKey *u1 = parcKey_CreateFromDerEncodedPublicKey(keyid_1, PARCSigningAlgorithm_RSA, bb_key_2); + PARCKey *u2 = parcKey_CreateFromDerEncodedPublicKey(keyid_2, PARCSigningAlgorithm_RSA, bb_key_1); + + parcObjectTesting_AssertEqualsFunction(parcKey_Equals, x, y, z, u1, u2); + + parcBuffer_Release(&bb_key_1); + parcBufferComposer_Release(&composer1); + parcBuffer_Release(&bb_key_2); + parcBufferComposer_Release(&composer2); + parcKeyId_Release(&keyid_1); + parcKeyId_Release(&keyid_2); + + parcKey_Release(&x); + parcKey_Release(&y); + parcKey_Release(&z); + parcKey_Release(&u1); + parcKey_Release(&u2); +} + +LONGBOW_TEST_CASE(Global, parcKey_GetKey) +{ + PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid = parcKeyId_Create(bb_id); + parcBuffer_Release(&bb_id); + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer, "quack quack"); + PARCBuffer *bb_key = parcBufferComposer_ProduceBuffer(composer); + PARCKey *key = parcKey_CreateFromDerEncodedPublicKey(keyid, PARCSigningAlgorithm_RSA, bb_key); + + parcKey_AssertValid(key); + + PARCBuffer *rawKey = parcKey_GetKey(key); // reference count is not incremented + assertTrue(parcBuffer_Equals(rawKey, bb_key), "Expected the raw key buffers to be equal"); + + parcKey_Release(&key); + parcBuffer_Release(&bb_key); + parcBufferComposer_Release(&composer); + parcKeyId_Release(&keyid); +} + +LONGBOW_TEST_CASE(Global, parcKey_GetKeyId) +{ + PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid = parcKeyId_Create(bb_id); + parcBuffer_Release(&bb_id); + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer, "quack quack"); + PARCBuffer *bb_key = parcBufferComposer_ProduceBuffer(composer); + PARCKey *key = parcKey_CreateFromDerEncodedPublicKey(keyid, PARCSigningAlgorithm_RSA, bb_key); + + parcKey_AssertValid(key); + + PARCKeyId *rawKeyId = parcKey_GetKeyId(key); // reference count is not incremented + assertTrue(parcKeyId_Equals(rawKeyId, keyid), "Expected the raw KeyID buffers to be equal"); + + parcKey_Release(&key); + parcBuffer_Release(&bb_key); + parcBufferComposer_Release(&composer); + parcKeyId_Release(&keyid); +} + +LONGBOW_TEST_CASE(Global, parcKey_GetSigningAlgorithm) +{ + // Check for PARCSigningAlgorithm_RSA value + PARCBuffer *bb_id_1 = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid_1 = parcKeyId_Create(bb_id_1); + parcBuffer_Release(&bb_id_1); + + PARCBufferComposer *composer1 = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer1, "quack quack"); + PARCBuffer *bb_key_1 = parcBufferComposer_ProduceBuffer(composer1); + PARCKey *key_1 = parcKey_CreateFromDerEncodedPublicKey(keyid_1, PARCSigningAlgorithm_RSA, bb_key_1); + + parcKey_AssertValid(key_1); + + assertTrue((parcKey_GetSigningAlgorithm(key_1) == PARCSigningAlgorithm_RSA), "Signing Algorithms don't match"); + + parcBuffer_Release(&bb_key_1); + parcBufferComposer_Release(&composer1); + parcKeyId_Release(&keyid_1); + parcKey_Release(&key_1); + + // Check for PARCSigningAlgorithm_HMAC value + PARCBuffer *bb_id_2 = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid_2 = parcKeyId_Create(bb_id_2); + parcBuffer_Release(&bb_id_2); + + PARCBufferComposer *composer2 = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer2, "quack quack"); + PARCBuffer *bb_key_2 = parcBufferComposer_ProduceBuffer(composer2); + PARCKey *key_2 = parcKey_CreateFromSymmetricKey(keyid_2, PARCSigningAlgorithm_HMAC, bb_key_2); + + parcKey_AssertValid(key_2); + + assertTrue((parcKey_GetSigningAlgorithm(key_2) == PARCSigningAlgorithm_HMAC), "Signing Algorithms don't match"); + + parcBuffer_Release(&bb_key_2); + parcBufferComposer_Release(&composer2); + parcKeyId_Release(&keyid_2); + parcKey_Release(&key_2); +} + +LONGBOW_TEST_CASE(Global, parcKey_Acquire) +{ + PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid = parcKeyId_Create(bb_id); + parcBuffer_Release(&bb_id); + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer, "quack quack"); + PARCBuffer *bb_key = parcBufferComposer_ProduceBuffer(composer); + PARCKey *key = parcKey_CreateFromDerEncodedPublicKey(keyid, PARCSigningAlgorithm_RSA, bb_key); + + parcKey_AssertValid(key); + + parcObjectTesting_AssertAcquireReleaseContract(parcKey_Acquire, key); + parcKey_Release(&key); + parcBuffer_Release(&bb_key); + parcBufferComposer_Release(&composer); + parcKeyId_Release(&keyid); +} + +LONGBOW_TEST_CASE(Global, parcKey_ToString) +{ + PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid = parcKeyId_Create(bb_id); + parcBuffer_Release(&bb_id); + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer, "quack quack"); + PARCBuffer *bb_key = parcBufferComposer_ProduceBuffer(composer); + PARCKey *key = parcKey_CreateFromDerEncodedPublicKey(keyid, PARCSigningAlgorithm_RSA, bb_key); + + char *keyString = parcKey_ToString(key); + + assertNotNull(keyString, "Expected non-null key representation string"); + assertTrue(strlen(keyString) > 0, "Expected non-null key representation string"); + + parcKey_Release(&key); + parcBuffer_Release(&bb_key); + parcBufferComposer_Release(&composer); + parcKeyId_Release(&keyid); +} + +LONGBOW_TEST_FIXTURE(Errors) +{ + LONGBOW_RUN_TEST_CASE(Errors, parcKey_CreateFromDerEncodedPublicKey_InvalidAlgorithm); + LONGBOW_RUN_TEST_CASE(Errors, parcKey_CreateFromSymmetricKey_InvalidAlgorithm); +} + +LONGBOW_TEST_FIXTURE_SETUP(Errors) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Errors) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE_EXPECTS(Errors, parcKey_CreateFromDerEncodedPublicKey_InvalidAlgorithm, .event = &LongBowTrapIllegalValue) +{ + PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid = parcKeyId_Create(bb_id); + parcBuffer_Release(&bb_id); + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer, "quack quack"); + PARCBuffer *bb_key = parcBufferComposer_ProduceBuffer(composer); + PARCKey *key = parcKey_CreateFromDerEncodedPublicKey(keyid, PARCSigningAlgorithm_HMAC, bb_key); + + assertNull(key, "This should not be reached"); //To avoid a warning + + // HMAC is an illegal value for this constructor + + parcBuffer_Release(&bb_key); + parcBufferComposer_Release(&composer); + parcKeyId_Release(&keyid); +} + +LONGBOW_TEST_CASE_EXPECTS(Errors, parcKey_CreateFromSymmetricKey_InvalidAlgorithm, .event = &LongBowTrapIllegalValue) +{ + PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); + PARCKeyId *keyid = parcKeyId_Create(bb_id); + parcBuffer_Release(&bb_id); + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer, "quack quack"); + PARCBuffer *bb_key = parcBufferComposer_ProduceBuffer(composer); + PARCKey *key = parcKey_CreateFromSymmetricKey(keyid, PARCSigningAlgorithm_RSA, bb_key); + + assertNull(key, "This should not be reached"); //To avoid a warning + + // RSA/DSA are illegal values for this constructor + + parcBuffer_Release(&bb_key); + parcBufferComposer_Release(&composer); + parcKeyId_Release(&keyid); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Key); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_KeyId.c b/libparc/parc/security/test/test_parc_KeyId.c new file mode 100644 index 00000000..1b14486d --- /dev/null +++ b/libparc/parc/security/test/test_parc_KeyId.c @@ -0,0 +1,216 @@ +/* + * 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/security/parc_KeyId.c> + +#include <LongBow/unit-test.h> +#include <LongBow/debugging.h> + +#include <parc/algol/parc_SafeMemory.h> +#include <parc/security/parc_Security.h> +#include <parc/testing/parc_ObjectTesting.h> + +const char *testStr = "hello world"; + +LONGBOW_TEST_RUNNER(test_parc_KeyId) +{ + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +LONGBOW_TEST_RUNNER_SETUP(test_parc_KeyId) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_RUNNER_TEARDOWN(test_parc_KeyId) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcKeyId_Create); + LONGBOW_RUN_TEST_CASE(Global, parcKeyId_Acquire); + LONGBOW_RUN_TEST_CASE(Global, parcKeyId_Copy); + LONGBOW_RUN_TEST_CASE(Global, parcKeyId_Equals); + LONGBOW_RUN_TEST_CASE(Global, parcKeyId_HashCode); + LONGBOW_RUN_TEST_CASE(Global, parcKeyId_HashCodeFromVoid); + LONGBOW_RUN_TEST_CASE(Global, parcKeyId_GetKeyId); + LONGBOW_RUN_TEST_CASE(Global, parcKeyId_ToString); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + 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, parcKeyId_Create) +{ + PARCBuffer *buffer = parcBuffer_Wrap((void *) testStr, strlen(testStr), 0, strlen(testStr)); + PARCKeyId *keyId = parcKeyId_Create(buffer); + parcBuffer_Release(&buffer); + + assertNotNull(keyId, "Expected non-null"); + + parcKeyId_Release(&keyId); + assertNull(keyId, "Release did not null the pointer."); +} + +LONGBOW_TEST_CASE(Global, parcKeyId_Acquire) +{ + PARCBuffer *buffer = parcBuffer_Wrap((void *) testStr, strlen(testStr), 0, strlen(testStr)); + PARCKeyId *keyId = parcKeyId_Create(buffer); + parcBuffer_Release(&buffer); + + assertNotNull(keyId, "Expected non-null"); + parcObjectTesting_AssertAcquireReleaseContract(parcKeyId_Acquire, keyId); + + parcKeyId_Release(&keyId); + assertNull(keyId, "Release did not null the pointer."); +} + +LONGBOW_TEST_CASE(Global, parcKeyId_Copy) +{ + PARCBuffer *buffer = parcBuffer_Wrap((void *) testStr, strlen(testStr), 0, strlen(testStr)); + PARCKeyId *keyId = parcKeyId_Create(buffer); + parcBuffer_Release(&buffer); + + assertNotNull(keyId, "Expected non-null"); + + PARCKeyId *copy = parcKeyId_Copy(keyId); + parcKeyId_AssertValid(keyId); + parcKeyId_AssertValid(copy); + + parcKeyId_Release(&keyId); + assertNull(keyId, "parcKeyId_Release did not null the keyId pointer."); + + parcKeyId_AssertValid(copy); + parcKeyId_Release(©); + assertNull(keyId, "parcKeyId_Release did not null the keyId copy pointer."); +} + +LONGBOW_TEST_CASE(Global, parcKeyId_Equals) +{ + PARCBuffer *buffer1 = parcBuffer_Wrap((void *) testStr, strlen(testStr), 0, strlen(testStr)); + PARCKeyId *x = parcKeyId_Create(buffer1); + parcBuffer_Release(&buffer1); + + PARCBuffer *buffer2 = parcBuffer_Wrap((void *) testStr, strlen(testStr), 0, strlen(testStr)); + PARCKeyId *y = parcKeyId_Create(buffer2); + parcBuffer_Release(&buffer2); + + PARCBuffer *buffer3 = parcBuffer_Wrap((void *) testStr, strlen(testStr), 0, strlen(testStr)); + PARCKeyId *z = parcKeyId_Create(buffer3); + parcBuffer_Release(&buffer3); + + PARCBuffer *buffer4 = parcBuffer_Wrap("hello worlx", 11, 0, 11); + PARCKeyId *u1 = parcKeyId_Create(buffer4); + parcBuffer_Release(&buffer4); + + parcObjectTesting_AssertEqualsFunction(parcKeyId_Equals, x, y, z, u1); + + parcKeyId_Release(&x); + parcKeyId_Release(&y); + parcKeyId_Release(&z); + parcKeyId_Release(&u1); + + assertNull(x, "Release did not null the pointer."); + assertNull(y, "Release did not null the pointer."); + assertNull(z, "Release did not null the pointer."); + assertNull(u1, "Release did not null the pointer."); +} + +LONGBOW_TEST_CASE(Global, parcKeyId_HashCode) +{ + PARCBuffer *buffer = parcBuffer_Wrap((void *) testStr, strlen(testStr), 0, strlen(testStr)); + PARCKeyId *keyId = parcKeyId_Create(buffer); + + assertNotNull(keyId, "Expected non-null"); + + assertTrue(parcKeyId_HashCode(keyId) == parcBuffer_HashCode(buffer), "Expected hash codes to be equal"); + + parcBuffer_Release(&buffer); + parcKeyId_Release(&keyId); + assertNull(keyId, "Release did not null the pointer."); +} + + +LONGBOW_TEST_CASE(Global, parcKeyId_HashCodeFromVoid) +{ + PARCBuffer *buffer = parcBuffer_Wrap((void *) testStr, strlen(testStr), 0, strlen(testStr)); + PARCKeyId *keyId = parcKeyId_Create(buffer); + + assertNotNull(keyId, "Expected non-null"); + + assertTrue(parcKeyId_HashCodeFromVoid((void *) keyId) == parcBuffer_HashCode(buffer), "Expected hash codes to be equal"); + + parcBuffer_Release(&buffer); + parcKeyId_Release(&keyId); + assertNull(keyId, "Release did not null the pointer."); +} + +LONGBOW_TEST_CASE(Global, parcKeyId_GetKeyId) +{ + PARCBuffer *buffer = parcBuffer_Wrap((void *) testStr, strlen(testStr), 0, strlen(testStr)); + PARCKeyId *keyId = parcKeyId_Create(buffer); + + assertNotNull(keyId, "Expected non-null"); + + PARCBuffer *rawBuffer = (PARCBuffer *) parcKeyId_GetKeyId(keyId); + assertTrue(parcBuffer_Equals(rawBuffer, buffer), "Expected the raw key buffers to be equal"); + + parcBuffer_Release(&buffer); + parcKeyId_Release(&keyId); + assertNull(keyId, "Release did not null the pointer."); +} + +LONGBOW_TEST_CASE(Global, parcKeyId_ToString) +{ + PARCBuffer *buffer = parcBuffer_Wrap((void *) testStr, strlen(testStr), 0, strlen(testStr)); + PARCKeyId *keyId = parcKeyId_Create(buffer); + + parcBuffer_Release(&buffer); + + assertNotNull(keyId, "Expected non-null"); + + char *string = parcKeyId_ToString(keyId); + printf("Hello: %s\n", string); + parcMemory_Deallocate((void **) &string); + + parcKeyId_Release(&keyId); + assertNull(keyId, "Release did not null the pointer."); +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(test_parc_KeyId); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_KeyStore.c b/libparc/parc/security/test/test_parc_KeyStore.c new file mode 100755 index 00000000..b48099cb --- /dev/null +++ b/libparc/parc/security/test/test_parc_KeyStore.c @@ -0,0 +1,137 @@ +/* + * 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_KeyStore.c" +#include <parc/testing/parc_ObjectTesting.h> + +#include <LongBow/unit-test.h> + +LONGBOW_TEST_RUNNER(parc_KeyStore) +{ + // 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); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_KeyStore) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_KeyStore) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ +// LONGBOW_RUN_TEST_CASE(Global, parcKeyStore_Acquire); +// LONGBOW_RUN_TEST_CASE(Global, parcKeyStore_CreateFile); +// LONGBOW_RUN_TEST_CASE(Global, parcKeyStore_GetFileName); +// LONGBOW_RUN_TEST_CASE(Global, parcKeyStore_GetPassWord); +// LONGBOW_RUN_TEST_CASE(Global, parcKeyStore_Release); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +//LONGBOW_TEST_CASE(Global, parcKeyStore_Acquire) +//{ +// const char *keystoreName = "test_rsa.p12"; +// const char *keystorePassword = "blueberry"; +// +// PARCKeyStore *keyStoreFile = parcKeyStore_CreateFile(keystoreName, keystorePassword); +// +// assertNotNull(keyStoreFile, "Expected non-null"); +// +// parcObjectTesting_AssertAcquireReleaseContract(parcKeyStore_Acquire, keyStoreFile); +// +// parcKeyStore_Release(&keyStoreFile); +//} +// +//LONGBOW_TEST_CASE(Global, parcKeyStore_CreateFile) +//{ +// const char *keystoreName = "test_rsa.p12"; +// const char *keystorePassword = "blueberry"; +// +// PARCKeyStore *keyStoreFile = parcKeyStore_CreateFile(keystoreName, keystorePassword); +// +// assertNotNull(keyStoreFile, "Expected non-null"); +// +// parcKeyStore_Release(&keyStoreFile); +//} +// +//LONGBOW_TEST_CASE(Global, parcKeyStore_GetFileName) +//{ +// const char *keystoreName = "test_rsa.p12"; +// const char *keystorePassword = "blueberry"; +// +// PARCKeyStore *keyStoreFile = parcKeyStore_CreateFile(keystoreName, keystorePassword); +// +// assertNotNull(keyStoreFile, "Expected non-null"); +// +// assertEqualStrings(keystoreName, parcKeyStore_GetFileName(keyStoreFile)); +// +// parcKeyStore_Release(&keyStoreFile); +//} +// +//LONGBOW_TEST_CASE(Global, parcKeyStore_GetPassWord) +//{ +// const char *keystoreName = "test_rsa.p12"; +// const char *keystorePassword = "blueberry"; +// +// PARCKeyStore *keyStoreFile = parcKeyStore_CreateFile(keystoreName, keystorePassword); +// +// assertNotNull(keyStoreFile, "Expected non-null"); +// +// assertEqualStrings(keystorePassword, parcKeyStore_GetPassWord(keyStoreFile)); +// +// parcKeyStore_Release(&keyStoreFile); +//} +// +//LONGBOW_TEST_CASE(Global, parcKeyStore_Release) +//{ +// const char *keystoreName = "test_rsa.p12"; +// const char *keystorePassword = "blueberry"; +// +// PARCKeyStore *keyStoreFile = parcKeyStore_CreateFile(keystoreName, keystorePassword); +// +// assertNotNull(keyStoreFile, "Expected non-null"); +// +// parcKeyStore_Release(&keyStoreFile); +// assertNull(keyStoreFile, "Key store File was not nulled out after Release()"); +//} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_KeyStore); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_Pkcs12KeyStore.c b/libparc/parc/security/test/test_parc_Pkcs12KeyStore.c new file mode 100755 index 00000000..1cd004cd --- /dev/null +++ b/libparc/parc/security/test/test_parc_Pkcs12KeyStore.c @@ -0,0 +1,470 @@ +/* + * 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 <config.h> + +#include <LongBow/testing.h> + +// Include the file(s) containing the functions to be tested. +// This permits internal static functions to be visible to this Test Framework. +#include "../parc_Pkcs12KeyStore.c" + +#include <parc/algol/parc_SafeMemory.h> +#include <parc/security/parc_Security.h> +#include <parc/security/parc_PublicKeySigner.h> + +const char *filename = "/tmp/filekeystore.p12"; + +LONGBOW_TEST_RUNNER(ccnx_FileKeystore) +{ + // 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(openssl_commandline); + LONGBOW_RUN_TEST_FIXTURE(ccnx_internal); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(ccnx_FileKeystore) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(ccnx_FileKeystore) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcPkcs12KeyStore_Open); + LONGBOW_RUN_TEST_CASE(Global, parcPkcs12KeyStore_badpass); + LONGBOW_RUN_TEST_CASE(Global, parcPkcs12KeyStore_CreateAndOpen); + LONGBOW_RUN_TEST_CASE(Global, parcPkcs12KeyStore_CreateFile_Fail); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + unlink(filename); + 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(Global, parcPkcs12KeyStore_Open) +{ + // open our test p12 file created with openssl + parcSecurity_Init(); + + PARCPkcs12KeyStore *keyStore = parcPkcs12KeyStore_Open("test_rsa.p12", "blueberry", PARCCryptoHashType_SHA256); + + assertNotNull(keyStore, "Got null result from opening openssl pkcs12 file"); + + parcPkcs12KeyStore_Release(&keyStore); + parcSecurity_Fini(); +} + +LONGBOW_TEST_CASE(Global, parcPkcs12KeyStore_badpass) +{ + // open our test p12 file created with openssl + + fprintf(stderr, "The next openssl error is expected, we're using the wrong password\n"); + PARCPkcs12KeyStore *keyStore = parcPkcs12KeyStore_Open("test_rsa.p12", "orange", PARCCryptoHashType_SHA256); + + assertNull(keyStore, "Got null result from opening openssl pkcs12 file"); +} + +LONGBOW_TEST_CASE(Global, parcPkcs12KeyStore_CreateAndOpen) +{ + // create a file and open it + const char *filename = "/tmp/parcPkcs12KeyStore_CreateAndOpen.p12"; + const char *password = "12345"; + const char *subject = "alice"; + bool result; + + result = parcPkcs12KeyStore_CreateFile(filename, password, subject, 1024, 32); + assertTrue(result, "got error from parcPkcs12KeyStore_CreatePkcs12File"); + + PARCPkcs12KeyStore *keyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); + + assertNotNull(keyStore, "Got null result from opening openssl pkcs12 file"); + + parcPkcs12KeyStore_Release(&keyStore); + unlink(filename); +} + +LONGBOW_TEST_CASE(Global, parcPkcs12KeyStore_CreateFile_Fail) +{ + // create a file and open it + const char *filename = "/tmp/parcPkcs12KeyStore_CreateAndOpen.p12"; + const char *password = "12345"; + const char *subject = "alice"; + bool result; + + result = parcPkcs12KeyStore_CreateFile(filename, password, subject, -1, 32); + assertFalse(result, "Expected false result from parcPkcs12KeyStore_CreateFile()"); + + unlink(filename); +} + + +// ===================================================== +// These are tests based on internally-generated pkcs12 + +LONGBOW_TEST_FIXTURE(ccnx_internal) +{ + LONGBOW_RUN_TEST_CASE(ccnx_internal, parcPkcs12KeyStore_GetCertificateDigest); + LONGBOW_RUN_TEST_CASE(ccnx_internal, parcPkcs12KeyStore_GetPublicKeyDigest); + LONGBOW_RUN_TEST_CASE(ccnx_internal, parcPkcs12KeyStore_GetEncodedCertificate); + LONGBOW_RUN_TEST_CASE(ccnx_internal, parcPkcs12KeyStore_GetEncodedPublicKey); +} + +LONGBOW_TEST_FIXTURE_SETUP(ccnx_internal) +{ + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(ccnx_internal) +{ + unlink(filename); + 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(ccnx_internal, parcPkcs12KeyStore_GetCertificateDigest) +{ + // create a file and open it + const char *password = "12345"; + const char *subject = "alice"; + bool result; + + result = parcPkcs12KeyStore_CreateFile(filename, password, subject, 1024, 32); + assertTrue(result, "got error from parcPkcs12KeyStore_CreatePkcs12File"); + + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); + assertNotNull(publicKeyStore, "Got null result from opening openssl pkcs12 file"); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCCryptoHash *cert_digest = parcKeyStore_GetCertificateDigest(keyStore); + assertNotNull(cert_digest, "got null public key digest for external pkcs12"); + + size_t bb_length = parcBuffer_Remaining(parcCryptoHash_GetDigest(cert_digest)); + assertTrue(bb_length == SHA256_DIGEST_LENGTH, + "Incorrect digest length returned from GetPublicKeyDigest: %zu", bb_length); + + parcKeyStore_Release(&keyStore); + parcCryptoHash_Release(&cert_digest); +} + +/** + * Use a ccnx-generated pkcs12 file + */ +LONGBOW_TEST_CASE(ccnx_internal, parcPkcs12KeyStore_GetPublicKeyDigest) +{ + // create a file and open it + const char *password = "12345"; + const char *subject = "alice"; + bool result; + + result = parcPkcs12KeyStore_CreateFile(filename, password, subject, 1024, 32); + assertTrue(result, "got error from parcPkcs12KeyStore_CreatePkcs12File"); + + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); + assertNotNull(publicKeyStore, "Got null result from opening openssl pkcs12 file"); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCCryptoHash *pkd = parcKeyStore_GetVerifierKeyDigest(keyStore); + assertNotNull(pkd, "got null public key digest for external pkcs12"); + + size_t bb_length = parcBuffer_Remaining(parcCryptoHash_GetDigest(pkd)); + assertTrue(bb_length == SHA256_DIGEST_LENGTH, "Incorrect digest length returned from GetPublicKeyDigest: %zu", bb_length); + + parcKeyStore_Release(&keyStore); + parcCryptoHash_Release(&pkd); +} + + +LONGBOW_TEST_CASE(ccnx_internal, parcPkcs12KeyStore_GetEncodedCertificate) +{ + // create a file and open it + const char *password = "12345"; + const char *subject = "alice"; + bool result; + + result = parcPkcs12KeyStore_CreateFile(filename, password, subject, 1024, 32); + assertTrue(result, "got error from parcPkcs12KeyStore_CreatePkcs12File"); + + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); + assertNotNull(publicKeyStore, "Got null result from opening openssl pkcs12 file"); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCBuffer *certificate_der = parcKeyStore_GetDEREncodedCertificate(keyStore); + assertNotNull(certificate_der, "got null public key digest for external pkcs12"); + + // 557 (64-bit) and 553 (32-bit) are pre-etermined sizes of how big a DER encoded + // certificate with a 1024-bit key should be + size_t expectedMinimumLength = 545; + size_t expectedMaximumLength = 560; + size_t bb_length = parcBuffer_Remaining(certificate_der); + assertTrue(expectedMinimumLength <= bb_length && bb_length <= expectedMaximumLength, + "Digest unexpected size: got %zu expected %zu - %zu", bb_length, expectedMinimumLength, expectedMaximumLength); + + parcKeyStore_Release(&keyStore); + parcBuffer_Release(&certificate_der); +} + +LONGBOW_TEST_CASE(ccnx_internal, parcPkcs12KeyStore_GetEncodedPublicKey) +{ + // create a file and open it + const char *password = "12345"; + const char *subject = "alice"; + bool result; + + result = parcPkcs12KeyStore_CreateFile(filename, password, subject, 1024, 32); + assertTrue(result, "got error from parcPkcs12KeyStore_CreatePkcs12File"); + + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); + assertNotNull(publicKeyStore, "Got null result from opening openssl pkcs12 file"); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCBuffer *pubkey_der = parcKeyStore_GetDEREncodedPublicKey(keyStore); + assertNotNull(pubkey_der, "got null public key digest for external pkcs12"); + + size_t bb_length = parcBuffer_Remaining(pubkey_der); + assertTrue(bb_length == 162, "Incorrect digest length returned from GetPublicKeyDigest: %zu", bb_length); + + parcKeyStore_Release(&keyStore); + parcBuffer_Release(&pubkey_der); +} + +// ===================================================== +// These are tests based on pre-generated material from the openssl command line + +LONGBOW_TEST_FIXTURE(openssl_commandline) +{ + LONGBOW_RUN_TEST_CASE(openssl_commandline, parcPkcs12KeyStore_GetCertificateDigest); + LONGBOW_RUN_TEST_CASE(openssl_commandline, parcPkcs12KeyStore_GetPublicKeyDigest); + LONGBOW_RUN_TEST_CASE(openssl_commandline, parcPkcs12KeyStore_GetEncodedCertificate); + LONGBOW_RUN_TEST_CASE(openssl_commandline, parcPkcs12KeyStore_GetEncodedPublicKey); +} + +LONGBOW_TEST_FIXTURE_SETUP(openssl_commandline) +{ + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(openssl_commandline) +{ + unlink(filename); + 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; +} + +/** + * read in the openssl command-line generated pkcs12 file + */ +LONGBOW_TEST_CASE(openssl_commandline, parcPkcs12KeyStore_GetPublicKeyDigest) +{ + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open("test_rsa.p12", "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + parcKeyStore_Release(&keyStore); + PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&publicKeySigner); + + assertNotNull(signer, "parcPkcs12KeyStore_Open(\"test_rsa.p12\", \"blueberry\", PARCCryptoHashType_SHA256) returned NULL"); + + PARCCryptoHash *pkd = parcKeyStore_GetVerifierKeyDigest(parcSigner_GetKeyStore(signer)); + assertNotNull(pkd, "got null public key digest for external pkcs12"); + + // read in the "truth" from the command line utilities + + int fd = open("test_rsa_pub_sha256.bin", O_RDONLY); + uint8_t true_digest[SHA256_DIGEST_LENGTH]; + ssize_t read_bytes = read(fd, true_digest, SHA256_DIGEST_LENGTH); + close(fd); + + assertTrue(read_bytes == SHA256_DIGEST_LENGTH, "could not read %d byte digest from test_rsa_pub_sha256.bin", SHA256_DIGEST_LENGTH); + + PARCBuffer *digest = parcCryptoHash_GetDigest(pkd); + const uint8_t *bb_buffer = parcByteArray_Array(parcBuffer_Array(digest)); + size_t bb_length = parcBuffer_Remaining(digest); + assertTrue(bb_length == SHA256_DIGEST_LENGTH, + "Incorrect digest length returned from GetPublicKeyDigest: %zu", bb_length); + + assertTrue(memcmp(bb_buffer, true_digest, SHA256_DIGEST_LENGTH) == 0, "digests did not match"); + + + parcSigner_Release(&signer); + parcCryptoHash_Release(&pkd); +} + +/** + * Get the certificate digest from the openssl command line pkcs12 + */ +LONGBOW_TEST_CASE(openssl_commandline, parcPkcs12KeyStore_GetCertificateDigest) +{ + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open("test_rsa.p12", "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + parcKeyStore_Release(&keyStore); + PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&publicKeySigner); + + assertNotNull(signer, "Got null result from opening openssl pkcs12 file"); + + PARCCryptoHash *cert_digest = parcKeyStore_GetCertificateDigest(parcSigner_GetKeyStore(signer)); + assertNotNull(cert_digest, "got null public key digest for external pkcs12"); + + // read in the "truth" from the command line utilities + + int fd = open("test_rsa_crt_sha256.bin", O_RDONLY); + uint8_t true_digest[SHA256_DIGEST_LENGTH]; + ssize_t read_bytes = read(fd, true_digest, SHA256_DIGEST_LENGTH); + close(fd); + + assertTrue(read_bytes == SHA256_DIGEST_LENGTH, "could not read %d byte digest from test_rsa_pub_sha256.bin", SHA256_DIGEST_LENGTH); + + const uint8_t *bb_buffer = parcByteArray_Array(parcBuffer_Array(parcCryptoHash_GetDigest(cert_digest))); + size_t bb_length = parcBuffer_Remaining(parcCryptoHash_GetDigest(cert_digest)); + assertTrue(bb_length == SHA256_DIGEST_LENGTH, + "Incorrect digest length returned from GetCertificateDigest: %zu", bb_length); + + assertTrue(memcmp(bb_buffer, true_digest, SHA256_DIGEST_LENGTH) == 0, "digests did not match"); + + parcSigner_Release(&signer); + parcCryptoHash_Release(&cert_digest); +} + +LONGBOW_TEST_CASE(openssl_commandline, parcPkcs12KeyStore_GetEncodedCertificate) +{ + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open("test_rsa.p12", "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + parcKeyStore_Release(&keyStore); + PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&publicKeySigner); + + assertNotNull(signer, "Got null result from opening openssl pkcs12 file"); + + PARCBuffer *certificate_der = parcKeyStore_GetDEREncodedCertificate(parcSigner_GetKeyStore(signer)); + assertNotNull(certificate_der, "got null der certificate for external pkcs12"); + + // read in the "truth" from the command line utilities + + int fd = open("test_rsa_crt.der", O_RDONLY); + uint8_t true_der[1024]; + ssize_t read_bytes = read(fd, true_der, 1024); + close(fd); + + assertTrue(read_bytes == 517, + "could not read %d byte digest from test_rsa_pub_sha256.bin", 517); + + const uint8_t *bb_buffer = parcByteArray_Array(parcBuffer_Array(certificate_der)); + size_t bb_length = parcBuffer_Remaining(certificate_der); + assertTrue(bb_length == read_bytes, + "Incorrect digest length returned from GetCertificateDigest: %zu", bb_length); + + assertTrue(memcmp(bb_buffer, true_der, read_bytes) == 0, "digests did not match"); + + parcSigner_Release(&signer); + parcBuffer_Release(&certificate_der); +} + +/** + * Gets the DER encoded public key + */ +LONGBOW_TEST_CASE(openssl_commandline, parcPkcs12KeyStore_GetEncodedPublicKey) +{ + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open("test_rsa.p12", "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + parcKeyStore_Release(&keyStore); + PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&publicKeySigner); + + assertNotNull(signer, "Got null result from opening openssl pkcs12 file"); + + PARCBuffer *pubkey_der = parcKeyStore_GetDEREncodedPublicKey(parcSigner_GetKeyStore(signer)); + assertNotNull(pubkey_der, "got null public key der for external pkcs12"); + + // read in the "truth" from the command line utilities + + int fd = open("test_rsa_pub.der", O_RDONLY); + uint8_t true_der[1024]; + ssize_t read_bytes = read(fd, true_der, 1024); + close(fd); + + assertTrue(read_bytes == 162, "could not read %d byte digest from test_rsa_pub_sha256.bin", 162); + + const uint8_t *bb_buffer = parcByteArray_Array(parcBuffer_Array(pubkey_der)); + size_t bb_length = parcBuffer_Remaining(pubkey_der); + assertTrue(bb_length == read_bytes, "Incorrect digest length returned from GetCertificateDigest: %zu", bb_length); + assertTrue(memcmp(bb_buffer, true_der, read_bytes) == 0, "digests did not match"); + + parcSigner_Release(&signer); + parcBuffer_Release(&pubkey_der); +} + +LONGBOW_TEST_CASE(openssl_commandline, parcPkcs12KeyStore_VerifySignature_Cert) +{ + testUnimplemented("Not Implemented"); +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_FileKeystore); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_PublicKeySigner.c b/libparc/parc/security/test/test_parc_PublicKeySigner.c new file mode 100644 index 00000000..0af1aca8 --- /dev/null +++ b/libparc/parc/security/test/test_parc_PublicKeySigner.c @@ -0,0 +1,453 @@ +/* + * 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 "../parc_PublicKeySigner.c" +#include <sys/param.h> + +#include <fcntl.h> + +#include <LongBow/testing.h> +#include <LongBow/debugging.h> + +#include <parc/algol/parc_Memory.h> +#include <parc/algol/parc_SafeMemory.h> + +#include <parc/testing/parc_MemoryTesting.h> +#include <parc/testing/parc_ObjectTesting.h> + +#include <parc/security/parc_Pkcs12KeyStore.h> + +LONGBOW_TEST_RUNNER(parc_PublicKeySigner) +{ + // 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(CreateAcquireRelease); + LONGBOW_RUN_TEST_FIXTURE(Object); + LONGBOW_RUN_TEST_FIXTURE(Specialization); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_PublicKeySigner) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_PublicKeySigner) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(CreateAcquireRelease) +{ + LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease); +} + +LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease) +{ + parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease) +{ + parcSecurity_Fini(); + if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) { + return LONGBOW_STATUS_MEMORYLEAK; + } + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease) +{ + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open("test_rsa.p12", "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *instance = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + parcKeyStore_Release(&keyStore); + assertNotNull(instance, "Expected non-null result from parcPublicKeySigner_Create();"); + + parcObjectTesting_AssertAcquireReleaseContract(parcPublicKeySigner_Acquire, instance); + + parcPublicKeySigner_Release(&instance); + assertNull(instance, "Expected null result from parcPublicKeySigner_Release();"); +} + +LONGBOW_TEST_FIXTURE(Object) +{ + LONGBOW_RUN_TEST_CASE(Object, parcPublicKeySigner_Equals); + LONGBOW_RUN_TEST_CASE(Object, parcPublicKeySigner_HashCode); + LONGBOW_RUN_TEST_CASE(Object, parcPublicKeySigner_IsValid); + LONGBOW_RUN_TEST_CASE(Object, parcPublicKeySigner_ToString); +} + +LONGBOW_TEST_FIXTURE_SETUP(Object) +{ + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Object) +{ + parcSecurity_Fini(); + if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) { + return LONGBOW_STATUS_MEMORYLEAK; + } + + return LONGBOW_STATUS_SUCCEEDED; +} + +static PARCPublicKeySigner * +_createSigner(char *path) +{ + char dirname[] = "/tmp/pubkeystore_XXXXXX"; + char filename[MAXPATHLEN]; + + char *temporaryDirectory = mkdtemp(dirname); + assertNotNull(temporaryDirectory, "tmp_dirname should not be null"); + sprintf(filename, "%s/%s", temporaryDirectory, path); + + parcPkcs12KeyStore_CreateFile(filename, "blueberry", "person", 1024, 365); + PARCPkcs12KeyStore *keyStore = parcPkcs12KeyStore_Open(filename, "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *publicKeyStore = parcKeyStore_Create(keyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&keyStore); + PARCPublicKeySigner *pksigner = parcPublicKeySigner_Create(publicKeyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + parcKeyStore_Release(&publicKeyStore); + + return pksigner; +} + +LONGBOW_TEST_CASE(Object, parcPublicKeySigner_Equals) +{ + PARCPublicKeySigner *x = _createSigner("bananasA"); + PARCPublicKeySigner *y = _createSigner("bananasB"); + PARCPublicKeySigner *z = _createSigner("bananasC"); + + parcObjectTesting_AssertEquals(x, y, z, NULL); + + parcPublicKeySigner_Release(&x); + parcPublicKeySigner_Release(&y); + parcPublicKeySigner_Release(&z); +} + +LONGBOW_TEST_CASE(Object, parcPublicKeySigner_HashCode) +{ + PARCPublicKeySigner *x = _createSigner("bananasX"); + PARCPublicKeySigner *y = _createSigner("bananasY"); + + parcObjectTesting_AssertHashCode(x, y); + + parcPublicKeySigner_Release(&x); + parcPublicKeySigner_Release(&y); +} + +LONGBOW_TEST_CASE(Object, parcPublicKeySigner_IsValid) +{ + PARCPublicKeySigner *instance = _createSigner("bananas"); + assertTrue(parcPublicKeySigner_IsValid(instance), "Expected parcPublicKeySigner_Create to result in a valid instance."); + + parcPublicKeySigner_Release(&instance); + assertFalse(parcPublicKeySigner_IsValid(instance), "Expected parcPublicKeySigner_Release to result in an invalid instance."); +} + +LONGBOW_TEST_CASE(Object, parcPublicKeySigner_ToString) +{ + PARCPublicKeySigner *instance = _createSigner("bananas"); + + char *string = parcPublicKeySigner_ToString(instance); + + assertNotNull(string, "Expected non-NULL result from parcPublicKeySigner_ToString"); + + parcMemory_Deallocate((void **) &string); + parcPublicKeySigner_Release(&instance); +} + +LONGBOW_TEST_FIXTURE(Specialization) +{ + LONGBOW_RUN_TEST_CASE(Specialization, parcPkcs12KeyStore_VerifySignature_Cert); + LONGBOW_RUN_TEST_CASE(Specialization, parcPkcs12KeyStore_SignBuffer); +} + +LONGBOW_TEST_FIXTURE_SETUP(Specialization) +{ + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Specialization) +{ + parcSecurity_Fini(); + if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) { + return LONGBOW_STATUS_MEMORYLEAK; + } + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Specialization, parcPkcs12KeyStore_VerifySignature_Cert) +{ +} + +/** + * Sign the file "test_rsa_pub_sha256.bin" using the test_rsa.p12 private key. + */ +LONGBOW_TEST_CASE(Specialization, parcPkcs12KeyStore_SignBuffer) +{ + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open("test_rsa.p12", "blueberry", PARCCryptoHashType_SHA256); + assertNotNull(publicKeyStore, "Got null result from opening openssl pkcs12 file"); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + parcKeyStore_Release(&keyStore); + PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&publicKeySigner); + + assertNotNull(signer, "Got null result from opening openssl pkcs12 file"); + + // read the buffer to sign + int fd = open("test_random_bytes", O_RDONLY); + assertTrue(fd != -1, "Cannot open test_random_bytes file."); + uint8_t buffer_to_sign[2048]; + ssize_t read_bytes = read(fd, buffer_to_sign, 2048); + close(fd); + + // Digest it + PARCCryptoHasher *digester = parcSigner_GetCryptoHasher(signer); + parcCryptoHasher_Init(digester); + parcCryptoHasher_UpdateBytes(digester, buffer_to_sign, read_bytes); + PARCCryptoHash *parcDigest = parcCryptoHasher_Finalize(digester); + + PARCSignature *bb_test_sign = parcSigner_SignDigest(signer, parcDigest); + + assertNotNull(bb_test_sign, "Got null byte buffer from SignBuffer"); + assertTrue(parcBuffer_Remaining(parcSignature_GetSignature(bb_test_sign)) == 128, + "Incorrect signature size: %zu", + parcBuffer_Position(parcSignature_GetSignature(bb_test_sign))); + + // now read the "true" signature + uint8_t scratch_buffer[1024]; + fd = open("test_random_bytes.sig", O_RDONLY); + assertTrue(fd != -1, "Cannot open test_random_bytes.sig file."); + read_bytes = read(fd, scratch_buffer, 1024); + assertTrue(read_bytes == 128, "read incorrect size signature from disk: %zu", read_bytes); + close(fd); + + const unsigned char *actual = parcByteArray_Array(parcBuffer_Array(parcSignature_GetSignature(bb_test_sign))); + + assertTrue(memcmp(scratch_buffer, actual, read_bytes) == 0, + "signatures did not match"); + + parcSigner_Release(&signer); + parcSignature_Release(&bb_test_sign); + parcCryptoHash_Release(&parcDigest); +} + +LONGBOW_TEST_CASE(Global, parcSigner_GetCertificateDigest) +{ + char dirname[] = "pubkeystore_XXXXXX"; + char filename[MAXPATHLEN]; + const char *password = "flumox"; + unsigned key_bits = 1024; + unsigned valid_days = 30; + + const char to_sign[] = "it was a dark and stormy night, and all through the house not a digest was creeping"; + + char *tmp_dirname = mkdtemp(dirname); + assertNotNull(tmp_dirname, "tmp_dirname should not be null"); + sprintf(filename, "%s/pubkeystore.p12", tmp_dirname); + + // create the file + parcPkcs12KeyStore_CreateFile(filename, password, "alice", key_bits, valid_days); + + // open it as an RSA provider for the signer + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&publicKeySigner); + + PARCCryptoHasher *hasher = parcSigner_GetCryptoHasher(signer); + parcCryptoHasher_Init(hasher); + parcCryptoHasher_UpdateBytes(hasher, to_sign, sizeof(to_sign)); + PARCCryptoHash *hash = parcCryptoHasher_Finalize(hasher); + PARCSignature *sig = parcSigner_SignDigest(signer, hash); + + unlink(filename); + int rc = rmdir(tmp_dirname); + assertTrue(rc == 0, "directory cleanup failed"); + + char *s = parcSignature_ToString(sig); + printf("Signature: %s\n", s); + parcMemory_Deallocate((void **) &s); + + PARCCryptoHash *certDigest = parcKeyStore_GetCertificateDigest(parcSigner_GetKeyStore(signer)); + assertNotNull(certDigest, "Expected a non NULL value"); + parcCryptoHash_Release(&certDigest); + + parcKeyStore_Release(&keyStore); + parcCryptoHash_Release(&hash); + parcSignature_Release(&sig); + parcSigner_Release(&signer); +} + +LONGBOW_TEST_CASE(Global, parcSigner_GetDEREncodedCertificate) +{ + char dirname[] = "pubkeystore_XXXXXX"; + char filename[MAXPATHLEN]; + const char *password = "flumox"; + unsigned key_bits = 1024; + unsigned valid_days = 30; + + const char to_sign[] = "it was a dark and stormy night, and all through the house not a digest was creeping"; + + char *tmp_dirname = mkdtemp(dirname); + assertNotNull(tmp_dirname, "tmp_dirname should not be null"); + sprintf(filename, "%s/pubkeystore.p12", tmp_dirname); + + // create the file + parcPkcs12KeyStore_CreateFile(filename, password, "alice", key_bits, valid_days); + + // open it as an RSA provider for the signer + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&publicKeySigner); + + PARCCryptoHasher *hasher = parcSigner_GetCryptoHasher(signer); + parcCryptoHasher_Init(hasher); + parcCryptoHasher_UpdateBytes(hasher, to_sign, sizeof(to_sign)); + PARCCryptoHash *hash = parcCryptoHasher_Finalize(hasher); + PARCSignature *sig = parcSigner_SignDigest(signer, hash); + + unlink(filename); + int rc = rmdir(tmp_dirname); + assertTrue(rc == 0, "directory cleanup failed"); + + char *s = parcSignature_ToString(sig); + printf("Signature: %s\n", s); + parcMemory_Deallocate((void **) &s); + + PARCBuffer *certificate_der = parcKeyStore_GetDEREncodedCertificate(parcSigner_GetKeyStore(signer)); + assertNotNull(certificate_der, "Expected a non NULL value"); + parcBuffer_Release(&certificate_der); + + parcKeyStore_Release(&keyStore); + parcCryptoHash_Release(&hash); + parcSignature_Release(&sig); + parcSigner_Release(&signer); +} + +LONGBOW_TEST_CASE(Global, parcSigner_CreatePublicKey) +{ + char dirname[] = "pubkeystore_XXXXXX"; + char filename[MAXPATHLEN]; + const char *password = "flumox"; + unsigned key_bits = 1024; + unsigned valid_days = 30; + + char *tmp_dirname = mkdtemp(dirname); + assertNotNull(tmp_dirname, "tmp_dirname should not be null"); + sprintf(filename, "%s/pubkeystore.p12", tmp_dirname); + + // create the file + parcPkcs12KeyStore_CreateFile(filename, password, "alice", key_bits, valid_days); + + // open it as an RSA provider for the signer + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&publicKeySigner); + + PARCKey *key = parcSigner_CreatePublicKey(signer); + assertNotNull(key, "Expected a non NULL value"); + parcKey_Release(&key); + parcKeyStore_Release(&keyStore); + + parcSigner_Release(&signer); +} + +LONGBOW_TEST_CASE(Global, parcSigner_CreateKeyId) +{ + char dirname[] = "pubkeystore_XXXXXX"; + char filename[MAXPATHLEN]; + const char *password = "flumox"; + unsigned key_bits = 1024; + unsigned valid_days = 30; + + const char to_sign[] = "it was a dark and stormy night, and all through the house not a digest was creeping"; + + char *tmp_dirname = mkdtemp(dirname); + assertNotNull(tmp_dirname, "tmp_dirname should not be null"); + sprintf(filename, "%s/pubkeystore.p12", tmp_dirname); + + // create the file + parcPkcs12KeyStore_CreateFile(filename, password, "alice", key_bits, valid_days); + + // open it as an RSA provider for the signer + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&publicKeySigner); + + PARCCryptoHasher *hasher = parcSigner_GetCryptoHasher(signer); + parcCryptoHasher_Init(hasher); + parcCryptoHasher_UpdateBytes(hasher, to_sign, sizeof(to_sign)); + PARCCryptoHash *hash = parcCryptoHasher_Finalize(hasher); + PARCSignature *sig = parcSigner_SignDigest(signer, hash); + + unlink(filename); + int rc = rmdir(tmp_dirname); + assertTrue(rc == 0, "directory cleanup failed"); + + char *s = parcSignature_ToString(sig); + printf("Signature: %s\n", s); + parcMemory_Deallocate((void **) &s); + + PARCKeyId *keyId = parcSigner_CreateKeyId(signer); + assertNotNull(keyId, "Expected a non NULL value"); + parcKeyId_Release(&keyId); + + parcKeyStore_Release(&keyStore); + parcCryptoHash_Release(&hash); + parcSignature_Release(&sig); + parcSigner_Release(&signer); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_PublicKeySigner); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_SecureRandom.c b/libparc/parc/security/test/test_parc_SecureRandom.c new file mode 100755 index 00000000..82359a70 --- /dev/null +++ b/libparc/parc/security/test/test_parc_SecureRandom.c @@ -0,0 +1,241 @@ +/* + * 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 "../parc_SecureRandom.c" +#include <sys/param.h> + +#include <fcntl.h> + +#include <LongBow/testing.h> +#include <LongBow/debugging.h> + +#include <parc/security/parc_Security.h> +#include <parc/algol/parc_Memory.h> +#include <parc/algol/parc_SafeMemory.h> +#include <parc/algol/parc_LinkedList.h> + +#include <parc/testing/parc_MemoryTesting.h> +#include <parc/testing/parc_ObjectTesting.h> + +#define NUM_TESTS 1000 +#define EPSILON 0.01 + +LONGBOW_TEST_RUNNER(parc_SecureRandom) +{ + // 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(CreateAcquireRelease); + LONGBOW_RUN_TEST_FIXTURE(Object); + LONGBOW_RUN_TEST_FIXTURE(Specialization); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_SecureRandom) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_SecureRandom) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(CreateAcquireRelease) +{ + LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease); +} + +LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease) +{ + parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease) +{ + parcSecurity_Fini(); + if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) { + return LONGBOW_STATUS_MEMORYLEAK; + } + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease) +{ + PARCSecureRandom *rng = parcSecureRandom_Create(); + assertNotNull(rng, "Expected non-null result from parcSecureRandom_Create();"); + + parcObjectTesting_AssertAcquireReleaseContract(parcSecureRandom_Acquire, rng); + + parcSecureRandom_Release(&rng); + assertNull(rng, "Expected null result from parcSecureRandom_Release();"); +} + +LONGBOW_TEST_FIXTURE(Object) +{ + LONGBOW_RUN_TEST_CASE(Object, parcSecureRandom_IsValid); +} + +LONGBOW_TEST_FIXTURE_SETUP(Object) +{ + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Object) +{ + parcSecurity_Fini(); + if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) { + return LONGBOW_STATUS_MEMORYLEAK; + } + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Object, parcSecureRandom_IsValid) +{ + PARCSecureRandom *rng = parcSecureRandom_Create(); + assertNotNull(rng, "Expected a non-NULL PARCSecureRandom"); + + assertTrue(parcSecureRandom_IsValid(rng), "Expected parcSecureRandom_Create to result in a valid instance."); + + parcSecureRandom_Release(&rng); + assertFalse(parcSecureRandom_IsValid(rng), "Expected parcSecureRandom_Release to result in an invalid instance."); +} + +LONGBOW_TEST_FIXTURE(Specialization) +{ + LONGBOW_RUN_TEST_CASE(Specialization, parcSecureRandom_Create); + LONGBOW_RUN_TEST_CASE(Specialization, parcSecureRandom_CreateWithSeed); + LONGBOW_RUN_TEST_CASE(Specialization, parcSecureRandom_Next); + LONGBOW_RUN_TEST_CASE(Specialization, parcSecureRandom_NextBytes); +} + +LONGBOW_TEST_FIXTURE_SETUP(Specialization) +{ + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Specialization) +{ + parcSecurity_Fini(); + if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) { + return LONGBOW_STATUS_MEMORYLEAK; + } + + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Specialization, parcSecureRandom_Create) +{ + PARCSecureRandom *rng = parcSecureRandom_Create(); + assertTrue(parcSecureRandom_IsValid(rng), "Expected parcSecureRandom_Create to result in a valid instance."); + parcSecureRandom_Release(&rng); +} + +LONGBOW_TEST_CASE(Specialization, parcSecureRandom_CreateWithSeed) +{ + PARCBuffer *seed = parcBuffer_Allocate(1024); + PARCSecureRandom *rng = parcSecureRandom_CreateWithSeed(seed); + + assertTrue(parcSecureRandom_IsValid(rng), "Expected parcSecureRandom_CreateWithSeed to result in a valid instance."); + + parcSecureRandom_Release(&rng); + parcBuffer_Release(&seed); +} + +static void +_stressTestNext(PARCSecureRandom *rng) +{ + PARCLinkedList *seen = parcLinkedList_Create(); + size_t duplicates = 0; + for (size_t i = 0; i < NUM_TESTS; i++) { + uint32_t next = parcSecureRandom_Next(rng); + PARCBuffer *buffer = parcBuffer_Allocate(sizeof(next)); + parcBuffer_Flip(parcBuffer_PutUint32(buffer, next)); + + if (parcLinkedList_Contains(seen, buffer)) { + duplicates++; + } else { + parcLinkedList_Append(seen, buffer); + } + + parcBuffer_Release(&buffer); + } + + assertFalse(duplicates > (NUM_TESTS * EPSILON), "The RNG failed to generate random values: saw %zu duplicates", duplicates); + parcLinkedList_Release(&seen); +} + +LONGBOW_TEST_CASE(Specialization, parcSecureRandom_Next) +{ + PARCSecureRandom *rng = parcSecureRandom_Create(); + assertTrue(parcSecureRandom_IsValid(rng), "Expected parcSecureRandom_Create to result in a valid instance"); + _stressTestNext(rng); + parcSecureRandom_Release(&rng); +} + +static void +_stressTestNextBytes(PARCSecureRandom *rng) +{ + PARCLinkedList *seen = parcLinkedList_Create(); + size_t duplicates = 0; + for (size_t i = 0; i < NUM_TESTS; i++) { + PARCBuffer *buffer = parcBuffer_Allocate(32); + + int numBytes = parcSecureRandom_NextBytes(rng, buffer); + assertTrue(numBytes == 32, "Expected 32 bytes from the RNG, got %d", numBytes); + + if (parcLinkedList_Contains(seen, buffer)) { + duplicates++; + } else { + parcLinkedList_Append(seen, buffer); + } + + parcBuffer_Release(&buffer); + } + + assertFalse(duplicates > (NUM_TESTS * EPSILON), "The RNG failed to generate random values: saw %zu duplicates", duplicates); + parcLinkedList_Release(&seen); +} + +LONGBOW_TEST_CASE(Specialization, parcSecureRandom_NextBytes) +{ + PARCBuffer *seed = parcBuffer_Allocate(1024); + PARCSecureRandom *rng = parcSecureRandom_CreateWithSeed(seed); + + assertTrue(parcSecureRandom_IsValid(rng), "Expected parcSecureRandom_CreateWithSeed to result in a valid instance."); + _stressTestNextBytes(rng); + + parcSecureRandom_Release(&rng); + parcBuffer_Release(&seed); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_SecureRandom); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_Security.c b/libparc/parc/security/test/test_parc_Security.c new file mode 100755 index 00000000..c2f2f33e --- /dev/null +++ b/libparc/parc/security/test/test_parc_Security.c @@ -0,0 +1,109 @@ +/* + * 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_Security.c" + +#include <LongBow/unit-test.h> +#include <parc/algol/parc_SafeMemory.h> + +LONGBOW_TEST_RUNNER(parc_Security) +{ + // 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); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_Security) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_Security) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcSecurity_Fini); + LONGBOW_RUN_TEST_CASE(Global, parcSecurity_Init); + LONGBOW_RUN_TEST_CASE(Global, parcSecurity_Init_Multiple); + LONGBOW_RUN_TEST_CASE(Global, parcSecurity_IsInitialized); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + 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, parcSecurity_Fini) +{ + parcSecurity_Init(); + parcSecurity_AssertIsInitialized(); + parcSecurity_Fini(); +} + +LONGBOW_TEST_CASE(Global, parcSecurity_Init) +{ + parcSecurity_Init(); + parcSecurity_AssertIsInitialized(); + parcSecurity_Fini(); +} + +LONGBOW_TEST_CASE(Global, parcSecurity_Init_Multiple) +{ + parcSecurity_Init(); + parcSecurity_Init(); + parcSecurity_Init(); + parcSecurity_Init(); + parcSecurity_AssertIsInitialized(); + parcSecurity_Fini(); + parcSecurity_Fini(); + parcSecurity_Fini(); + parcSecurity_Fini(); + assertFalse(parcSecurity_IsInitialized(), "parcSecurity_IsInitialized should be false now"); +} + +LONGBOW_TEST_CASE(Global, parcSecurity_IsInitialized) +{ + parcSecurity_Init(); + parcSecurity_AssertIsInitialized(); + parcSecurity_Fini(); + assertFalse(parcSecurity_IsInitialized(), "parcSecurity_IsInitialized should be false now"); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Security); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_Signature.c b/libparc/parc/security/test/test_parc_Signature.c new file mode 100755 index 00000000..9f54da37 --- /dev/null +++ b/libparc/parc/security/test/test_parc_Signature.c @@ -0,0 +1,230 @@ +/* + * 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_Signature.c" +#include <inttypes.h> + +#include <parc/algol/parc_SafeMemory.h> +#include <LongBow/unit-test.h> +#include <parc/testing/parc_ObjectTesting.h> + +LONGBOW_TEST_RUNNER(parc_Signature) +{ + // 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_Signature) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_Signature) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcSignature_Create); + LONGBOW_RUN_TEST_CASE(Global, parcSignature_Acquire); + LONGBOW_RUN_TEST_CASE(Global, parcSignature_Release); + LONGBOW_RUN_TEST_CASE(Global, parcSignature_Equals); + LONGBOW_RUN_TEST_CASE(Global, parcSignature_GetHashType); + LONGBOW_RUN_TEST_CASE(Global, parcSignature_GetSignature); + LONGBOW_RUN_TEST_CASE(Global, parcSignature_GetSigningAlgorithm); + LONGBOW_RUN_TEST_CASE(Global, parcSignature_ToString); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, parcSignature_Create) +{ + PARCBuffer *bits = parcBuffer_Allocate(10); // arbitrary buffer size -- not important + PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_DSA, PARCCryptoHashType_SHA256, bits); + parcBuffer_Release(&bits); + + assertNotNull(signature, "Expected non-NULL PARCSignature"); + PARCReferenceCount referenceCount = parcObject_GetReferenceCount(signature); + assertTrue(referenceCount == 1, + "Expected reference count to be equal to 1, got %" PRIu64 "", + referenceCount); + + parcSignature_Release(&signature); +} + +LONGBOW_TEST_CASE(Global, parcSignature_Acquire) +{ + PARCBuffer *bits = parcBuffer_Allocate(10); // arbitrary buffer size -- not important + PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_DSA, PARCCryptoHashType_SHA256, bits); + PARCSignature *handle = parcSignature_Acquire(signature); + parcBuffer_Release(&bits); + + assertNotNull(signature, "Expected non-NULL PARCSignature"); + assertNotNull(handle, "Expected non-NULL PARCSignature after acquisition"); + PARCReferenceCount referenceCount = parcObject_GetReferenceCount(handle); + assertTrue(referenceCount == 2, + "Expected reference count to be equal to 2, got %" PRIu64 "", + referenceCount); + + parcSignature_Release(&signature); + parcSignature_Release(&handle); +} + +LONGBOW_TEST_CASE(Global, parcSignature_Release) +{ + PARCBuffer *bits = parcBuffer_Allocate(10); // arbitrary bufer size -- not important + PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_DSA, PARCCryptoHashType_SHA256, bits); + PARCSignature *handle = parcSignature_Acquire(signature); + parcBuffer_Release(&bits); + + assertNotNull(signature, "Expected non-NULL PARCSignature"); + assertNotNull(handle, "Expected non-NULL PARCSignature after acquisition"); + PARCReferenceCount referenceCount = parcObject_GetReferenceCount(handle); + assertTrue(referenceCount == 2, + "Expected reference count to be equal to 2, got %" PRIu64 "", + referenceCount); + + parcSignature_Release(&signature); + parcSignature_Release(&handle); + + assertNull(signature, "Expected NULL PARCSignature"); +} + +LONGBOW_TEST_CASE(Global, parcSignature_Equals) +{ + PARCBuffer *bits = parcBuffer_Allocate(10); // arbitrary bufer size -- not important + PARCBuffer *otherBits = parcBuffer_Allocate(strlen("hello")); + parcBuffer_PutArray(otherBits, strlen("hello"), (uint8_t *) "hello"); + + PARCSignature *x = parcSignature_Create(PARCSigningAlgorithm_DSA, PARCCryptoHashType_SHA256, bits); + PARCSignature *y = parcSignature_Create(PARCSigningAlgorithm_DSA, PARCCryptoHashType_SHA256, bits); + PARCSignature *z = parcSignature_Create(PARCSigningAlgorithm_DSA, PARCCryptoHashType_SHA256, bits); + PARCSignature *unequal1 = parcSignature_Create(PARCSigningAlgorithm_HMAC, PARCCryptoHashType_SHA256, bits); + PARCSignature *unequal2 = parcSignature_Create(PARCSigningAlgorithm_DSA, PARCCryptoHashType_CRC32C, bits); + PARCSignature *unequal3 = parcSignature_Create(PARCSigningAlgorithm_DSA, PARCCryptoHashType_SHA256, otherBits); + + parcObjectTesting_AssertEqualsFunction(parcSignature_Equals, x, y, z, unequal1, unequal2, unequal3, NULL); + + parcSignature_Release(&x); + parcSignature_Release(&y); + parcSignature_Release(&z); + parcSignature_Release(&unequal1); + parcSignature_Release(&unequal2); + parcSignature_Release(&unequal3); + + parcBuffer_Release(&bits); + parcBuffer_Release(&otherBits); +} + +LONGBOW_TEST_CASE(Global, parcSignature_GetHashType) +{ + PARCBuffer *bits = parcBuffer_Allocate(strlen("Hello")); + parcBuffer_PutArray(bits, strlen("Hello"), (uint8_t *) "Hello"); + PARCCryptoHashType expected = PARCCryptoHashType_SHA256; + PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_DSA, expected, bits); + parcBuffer_Release(&bits); + + PARCCryptoHashType actual = parcSignature_GetHashType(signature); + + assertTrue(expected == actual, "Expected %d, actual %d", expected, actual); + parcSignature_Release(&signature); +} + +LONGBOW_TEST_CASE(Global, parcSignature_GetSignature) +{ + PARCBuffer *expected = parcBuffer_Allocate(strlen("Hello")); + parcBuffer_PutArray(expected, strlen("Hello"), (uint8_t *) "Hello"); + PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_DSA, PARCCryptoHashType_SHA256, expected); + + PARCBuffer *actual = parcSignature_GetSignature(signature); + + assertTrue(parcBuffer_Equals(expected, actual), "Expected the original signature bits to be equal to the actual bits"); + parcSignature_Release(&signature); + parcBuffer_Release(&expected); +} + +LONGBOW_TEST_CASE(Global, parcSignature_GetSigningAlgorithm) +{ + PARCBuffer *signatureBits = parcBuffer_Allocate(strlen("Hello")); + parcBuffer_PutArray(signatureBits, strlen("Hello"), (uint8_t *) "Hello"); + PARCSigningAlgorithm expected = PARCSigningAlgorithm_DSA; + PARCSignature *signature = parcSignature_Create(expected, PARCCryptoHashType_SHA256, signatureBits); + + PARCSigningAlgorithm actual = parcSignature_GetSigningAlgorithm(signature); + + assertTrue(expected == actual, "Expected %d, actual %d", expected, actual); + parcSignature_Release(&signature); + parcBuffer_Release(&signatureBits); +} + +LONGBOW_TEST_CASE(Global, parcSignature_ToString) +{ + PARCBuffer *signatureBits = parcBuffer_Allocate(strlen("Hello")); + parcBuffer_PutArray(signatureBits, strlen("Hello"), (uint8_t *) "Hello"); + PARCSigningAlgorithm expected = PARCSigningAlgorithm_DSA; + PARCSignature *signature = parcSignature_Create(expected, PARCCryptoHashType_SHA256, signatureBits); + + char *string = parcSignature_ToString(signature); + + assertNotNull(string, "Expected non-NULL result from parcSignature_ToString"); + + parcMemory_Deallocate((void **) &string); + parcSignature_Release(&signature); + parcBuffer_Release(&signatureBits); +} + +LONGBOW_TEST_FIXTURE(Local) +{ +} + +LONGBOW_TEST_FIXTURE_SETUP(Local) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Local) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Signature); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_Signer.c b/libparc/parc/security/test/test_parc_Signer.c new file mode 100644 index 00000000..b9605384 --- /dev/null +++ b/libparc/parc/security/test/test_parc_Signer.c @@ -0,0 +1,305 @@ +/* + * 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 <config.h> +#include <LongBow/unit-test.h> +#include <sys/param.h> +#include <errno.h> + +#include "../parc_Signer.c" + +#include <parc/algol/parc_SafeMemory.h> +#include <parc/security/parc_Security.h> +#include <parc/testing/parc_ObjectTesting.h> + +#include <parc/security/parc_Pkcs12KeyStore.h> +#include <parc/security/parc_KeyStore.h> +#include <parc/security/parc_PublicKeySigner.h> +#include <parc/security/parc_SymmetricKeySigner.h> + +#define FAKE_SIGNATURE "signature" + +typedef struct { + PARCCryptoHasher *hasher; + PARCKeyStore *keyStore; +} _MockSigner; + +static PARCSignature * +_SignDigest(PARCSigner *interfaceContext) +{ + PARCBuffer *buffer = parcBuffer_WrapCString(FAKE_SIGNATURE); + PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256, buffer); + parcBuffer_Release(&buffer); + return signature; +} + +static PARCSigningAlgorithm +_GetSigningAlgorithm(PARCSigner *interfaceContext) +{ + return PARCSigningAlgorithm_RSA; +} + +static PARCCryptoHashType +_GetCryptoHashType(PARCSigner *signer) +{ + return PARCCryptoHashType_SHA256; +} + +static PARCCryptoHasher * +_GetCryptoHasher(_MockSigner *signer) +{ + return signer->hasher; +} + +static PARCKeyStore * +_GetKeyStore(_MockSigner *signer) +{ + return signer->keyStore; +} + +static bool +_releaseSigner(_MockSigner **signer) +{ + parcCryptoHasher_Release(&((*signer)->hasher)); + parcKeyStore_Release(&((*signer)->keyStore)); + return true; +} + +parcObject_ImplementAcquire(_mockSigner, _MockSigner); +parcObject_ImplementRelease(_mockSigner, _MockSigner); + +parcObject_Override(_MockSigner, PARCObject, + .destructor = (PARCObjectDestructor *) _releaseSigner); + +static _MockSigner * +_createSigner() +{ + _MockSigner *signer = parcObject_CreateInstance(_MockSigner); + + signer->hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256); + + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open("test_rsa.p12", "blueberry", PARCCryptoHashType_SHA256); + assertNotNull(publicKeyStore, "Got null result from opening openssl pkcs12 file"); + + signer->keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + return signer; +} + +static PARCSigningInterface *_MockSignerInterface = &(PARCSigningInterface) { + .GetCryptoHasher = (PARCCryptoHasher * (*)(void *))_GetCryptoHasher, + .SignDigest = (PARCSignature * (*)(void *, const PARCCryptoHash *))_SignDigest, + .GetSigningAlgorithm = (PARCSigningAlgorithm (*)(void *))_GetSigningAlgorithm, + .GetCryptoHashType = (PARCCryptoHashType (*)(void *))_GetCryptoHashType, + .GetKeyStore = (PARCKeyStore * (*)(void *))_GetKeyStore, +}; + +LONGBOW_TEST_RUNNER(parc_Signer) +{ + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_Signer) +{ + parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_Signer) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcSigner_Create); + LONGBOW_RUN_TEST_CASE(Global, parcSigner_AcquireRelease); + LONGBOW_RUN_TEST_CASE(Global, parcSigner_CreateKeyId); + LONGBOW_RUN_TEST_CASE(Global, parcSigner_CreatePublicKey); + LONGBOW_RUN_TEST_CASE(Global, parcSigner_GetCryptoHasher); + LONGBOW_RUN_TEST_CASE(Global, parcSigner_SignDigest); + LONGBOW_RUN_TEST_CASE(Global, parcSigner_GetSigningAlgorithm); + LONGBOW_RUN_TEST_CASE(Global, parcSigner_GetCryptoHashType); + LONGBOW_RUN_TEST_CASE(Global, parcSigner_GetKeyStore); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + 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(Global, parcSigner_Create) +{ + _MockSigner *mock = _createSigner(); + PARCSigner *signer = parcSigner_Create(mock, _MockSignerInterface); + _mockSigner_Release(&mock); + + assertNotNull(signer, "Expected non-null signer"); + + parcSigner_Release(&signer); +} + +LONGBOW_TEST_CASE(Global, parcSigner_AcquireRelease) +{ + _MockSigner *mock = _createSigner(); + PARCSigner *signer = parcSigner_Create(mock, _MockSignerInterface); + _mockSigner_Release(&mock); + + assertNotNull(signer, "Expected non-null signer"); + + parcObjectTesting_AssertAcquireReleaseContract(parcSigner_Acquire, signer); + + parcSigner_Release(&signer); + assertNull(signer, "Expected null result from parcSigner_Release();"); +} + +LONGBOW_TEST_CASE(Global, parcSigner_CreateKeyId) +{ + _MockSigner *mock = _createSigner(); + PARCSigner *signer = parcSigner_Create(mock, _MockSignerInterface); + _mockSigner_Release(&mock); + + PARCKeyId *keyId = parcSigner_CreateKeyId(signer); + + assertNotNull(keyId, "Expected non-NULL PARCKeyId"); + + parcKeyId_Release(&keyId); + parcSigner_Release(&signer); +} + +LONGBOW_TEST_CASE(Global, parcSigner_CreatePublicKey) +{ + _MockSigner *mock = _createSigner(); + PARCSigner *signer = parcSigner_Create(mock, _MockSignerInterface); + + PARCKey *key = parcSigner_CreatePublicKey(signer); + + // Compute the real value + PARCCryptoHash *hash = parcKeyStore_GetVerifierKeyDigest(mock->keyStore); + PARCKeyId *keyid = parcKeyId_Create(parcCryptoHash_GetDigest(hash)); + PARCBuffer *derEncodedKey = parcKeyStore_GetDEREncodedPublicKey(mock->keyStore); + + PARCKey *expectedKey = parcKey_CreateFromDerEncodedPublicKey(keyid, + parcSigner_GetSigningAlgorithm(signer), + derEncodedKey); + + parcBuffer_Release(&derEncodedKey); + parcKeyId_Release(&keyid); + + parcCryptoHash_Release(&hash); + + assertTrue(parcKey_Equals(key, expectedKey), "Expected public keys to be computed equally."); + + parcKey_Release(&key); + parcKey_Release(&expectedKey); + parcSigner_Release(&signer); + _mockSigner_Release(&mock); +} + +LONGBOW_TEST_CASE(Global, parcSigner_GetCryptoHasher) +{ + _MockSigner *mock = _createSigner(); + PARCSigner *signer = parcSigner_Create(mock, _MockSignerInterface); + _mockSigner_Release(&mock); + + PARCCryptoHasher *hasher = parcSigner_GetCryptoHasher(signer); + + assertNotNull(hasher, "Expected non-NULL PARCCryptoHasher"); + + parcSigner_Release(&signer); +} + +LONGBOW_TEST_CASE(Global, parcSigner_SignDigest) +{ + _MockSigner *mock = _createSigner(); + PARCSigner *signer = parcSigner_Create(mock, _MockSignerInterface); + _mockSigner_Release(&mock); + + PARCBuffer *buffer = parcBuffer_Allocate(10); + PARCCryptoHash *hash = parcCryptoHash_Create(PARCCryptoHashType_SHA256, buffer); + PARCSignature *signature = parcSigner_SignDigest(signer, hash); + + assertNotNull(signature, "Expected non-NULL PARCSignature"); + + PARCBuffer *bits = parcSignature_GetSignature(signature); + char *bitstring = parcBuffer_ToString(bits); + char *expectedString = FAKE_SIGNATURE; + assertTrue(strcmp(bitstring, expectedString) == 0, "Expected the forced signature as output %s, got %s", expectedString, bitstring); + parcMemory_Deallocate(&bitstring); + + parcCryptoHash_Release(&hash); + parcBuffer_Release(&buffer); + parcSignature_Release(&signature); + parcSigner_Release(&signer); +} + +LONGBOW_TEST_CASE(Global, parcSigner_GetSigningAlgorithm) +{ + _MockSigner *mock = _createSigner(); + PARCSigner *signer = parcSigner_Create(mock, _MockSignerInterface); + _mockSigner_Release(&mock); + + PARCSigningAlgorithm alg = parcSigner_GetSigningAlgorithm(signer); + assertTrue(PARCSigningAlgorithm_RSA == alg, "Expected PARCSigningAlgorithm_RSA algorithm, got %d", alg); + + parcSigner_Release(&signer); +} + +LONGBOW_TEST_CASE(Global, parcSigner_GetCryptoHashType) +{ + _MockSigner *mock = _createSigner(); + PARCSigner *signer = parcSigner_Create(mock, _MockSignerInterface); + _mockSigner_Release(&mock); + + PARCCryptoHashType type = parcSigner_GetCryptoHashType(signer); + assertTrue(PARCCryptoHashType_SHA256 == type, "Expected PARCCryptoHashType_SHA256 algorithm, got %d", type); + + parcSigner_Release(&signer); +} + +LONGBOW_TEST_CASE(Global, parcSigner_GetKeyStore) +{ + _MockSigner *mock = _createSigner(); + PARCSigner *signer = parcSigner_Create(mock, _MockSignerInterface); + _mockSigner_Release(&mock); + + PARCKeyStore *keyStore = parcSigner_GetKeyStore(signer); + assertNotNull(keyStore, "Expected non-NULL PARCKeyStore"); + + parcSigner_Release(&signer); +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Signer); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_SigningAlgorithm.c b/libparc/parc/security/test/test_parc_SigningAlgorithm.c new file mode 100755 index 00000000..e8f8581a --- /dev/null +++ b/libparc/parc/security/test/test_parc_SigningAlgorithm.c @@ -0,0 +1,125 @@ +/* + * 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_SigningAlgorithm.c" + +#include <LongBow/testing.h> +#include <LongBow/debugging.h> + +LONGBOW_TEST_RUNNER(test_parc_SigningAlgorithm) +{ + // 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); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(test_parc_SigningAlgorithm) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(test_parc_SigningAlgorithm) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcSigningAlgorithm_ToFromString); + LONGBOW_RUN_TEST_CASE(Global, parcSigningAlgorithm_ToFromString_NotFound); + LONGBOW_RUN_TEST_CASE(Global, parcSigningAlgorithm_GetSigningAlgorithm); + LONGBOW_RUN_TEST_CASE(Global, parcSigningAlgorithm_FromString_NotFound); + LONGBOW_RUN_TEST_CASE(Global, parcSigningAlgorithm_GetSigningAlgorithm_BadAlgorithm); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, parcSigningAlgorithm_ToFromString) +{ + PARCSigningAlgorithm expected = PARCSigningAlgorithm_HMAC; + + const char *string = parcSigningAlgorithm_ToString(expected); + + PARCSigningAlgorithm actual = parcSigningAlgorithm_FromString(string); + + assertTrue(expected == actual, "Expected %d, actual %d", expected, actual); +} + +LONGBOW_TEST_CASE(Global, parcSigningAlgorithm_ToFromString_NotFound) +{ + PARCSigningAlgorithm expected = 123456; + + const char *string = parcSigningAlgorithm_ToString(expected); + + assertNull(string, "Expect parcSigningAlgorithm_ToString to return NULL"); +} + +LONGBOW_TEST_CASE(Global, parcSigningAlgorithm_FromString_NotFound) +{ + PARCSigningAlgorithm actual = parcSigningAlgorithm_FromString("garbage string of unknown stuff"); + + assertTrue(actual == PARCSigningAlgorithm_UNKNOWN, + "Expect parcSigningAlgorithm_FromString to return PARCSigningAlgorithm_UNKNOWN"); +} + +LONGBOW_TEST_CASE(Global, parcSigningAlgorithm_GetSigningAlgorithm) +{ + PARCSigningAlgorithm actual = parcSigningAlgorithm_GetSigningAlgorithm(PARCCryptoSuite_DSA_SHA256); + assertTrue(PARCSigningAlgorithm_DSA == actual, "Expected %d, actual %d", PARCSigningAlgorithm_DSA, actual); + + actual = parcSigningAlgorithm_GetSigningAlgorithm(PARCCryptoSuite_RSA_SHA256); + assertTrue(PARCSigningAlgorithm_RSA == actual, "Expected %d, actual %d", PARCSigningAlgorithm_RSA, actual); + + actual = parcSigningAlgorithm_GetSigningAlgorithm(PARCCryptoSuite_RSA_SHA512); + assertTrue(PARCSigningAlgorithm_RSA == actual, "Expected %d, actual %d", PARCSigningAlgorithm_RSA, actual); + + actual = parcSigningAlgorithm_GetSigningAlgorithm(PARCCryptoSuite_HMAC_SHA256); + assertTrue(PARCSigningAlgorithm_HMAC == actual, "Expected %d, actual %d", PARCSigningAlgorithm_HMAC, actual); + + actual = parcSigningAlgorithm_GetSigningAlgorithm(PARCCryptoSuite_HMAC_SHA512); + assertTrue(PARCSigningAlgorithm_HMAC == actual, "Expected %d, actual %d", PARCSigningAlgorithm_HMAC, actual); + + actual = parcSigningAlgorithm_GetSigningAlgorithm(PARCCryptoSuite_NULL_CRC32C); + assertTrue(PARCSigningAlgortihm_NULL == actual, "Expected %d, actual %d", PARCSigningAlgortihm_NULL, actual); +} + +LONGBOW_TEST_CASE_EXPECTS(Global, parcSigningAlgorithm_GetSigningAlgorithm_BadAlgorithm, .event = &LongBowTrapIllegalValue) +{ + parcSigningAlgorithm_GetSigningAlgorithm(-1); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(test_parc_SigningAlgorithm); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_SymmetricKeySigner.c b/libparc/parc/security/test/test_parc_SymmetricKeySigner.c new file mode 100644 index 00000000..562ba6c6 --- /dev/null +++ b/libparc/parc/security/test/test_parc_SymmetricKeySigner.c @@ -0,0 +1,247 @@ +/* + * 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 "../parc_SymmetricKeySigner.c" +#include <sys/param.h> + +#include <errno.h> +#include <config.h> +#include <fcntl.h> + +#include <LongBow/testing.h> +#include <LongBow/debugging.h> +#include <LongBow/longBow_Compiler.h> + +#include <parc/algol/parc_Memory.h> +#include <parc/algol/parc_SafeMemory.h> +#include <parc/algol/parc_DisplayIndented.h> + +#include <parc/testing/parc_MemoryTesting.h> +#include <parc/testing/parc_ObjectTesting.h> + +static PARCSymmetricKeySigner * +_createSigner() +{ + PARCBuffer *secret_key = parcSymmetricKeyStore_CreateKey(256); + + PARCSymmetricKeyStore *symmetricKeyStore = parcSymmetricKeyStore_Create(secret_key); + parcBuffer_Release(&secret_key); + + PARCSymmetricKeySigner *privateKeySigner = parcSymmetricKeySigner_Create(symmetricKeyStore, PARCCryptoHashType_SHA256); + parcSymmetricKeyStore_Release(&symmetricKeyStore); + + return privateKeySigner; +} + +LONGBOW_TEST_RUNNER(parc_SymmetricSigner) +{ + // 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(CreateAcquireRelease); + LONGBOW_RUN_TEST_FIXTURE(Specialization); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_SymmetricSigner) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_SymmetricSigner) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(CreateAcquireRelease) +{ + LONGBOW_RUN_TEST_CASE(CreateAcquireRelease, CreateRelease); +} + +LONGBOW_TEST_FIXTURE_SETUP(CreateAcquireRelease) +{ + parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(CreateAcquireRelease) +{ + if (!parcMemoryTesting_ExpectedOutstanding(0, "%s leaked memory.", longBowTestCase_GetFullName(testCase))) { + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease) +{ + PARCSymmetricKeySigner *instance = _createSigner(); + + assertNotNull(instance, "Expected non-null result from parcSymmetricKeySigner_Create();"); + + parcObjectTesting_AssertAcquireReleaseContract(parcSymmetricKeySigner_Acquire, instance); + + parcSymmetricKeySigner_Release(&instance); + assertNull(instance, "Expected null result from parcSymmetricKeySigner_Release();"); +} + +LONGBOW_TEST_FIXTURE(Specialization) +{ + LONGBOW_RUN_TEST_CASE(Specialization, test_hmac_sha256); + LONGBOW_RUN_TEST_CASE(Specialization, test_hmac_sha512); +} + +LONGBOW_TEST_FIXTURE_SETUP(Specialization) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Specialization) +{ + if (!parcMemoryTesting_ExpectedOutstanding(0, "%s mismanaged memory.", longBowTestCase_GetFullName(testCase))) { + return LONGBOW_STATUS_MEMORYLEAK; + } + + return LONGBOW_STATUS_SUCCEEDED; +} +LONGBOW_TEST_CASE(Specialization, test_hmac_sha256) +{ +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + HMAC_CTX *ctx = HMAC_CTX_new(); +#else + HMAC_CTX ctx; +#endif + char key[] = "apple_pie_is_good"; + int fd; + uint8_t to_digest_buffer[MAXPATHLEN]; + ssize_t to_digest_length; + + uint8_t true_hmac_buffer[MAXPATHLEN]; + ssize_t true_hmac_length; + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + HMAC_Init_ex(ctx, key, sizeof(key), EVP_sha256(), NULL); +#else + LONGBOW_STOP_DEPRECATED_WARNINGS + HMAC_CTX_init(&ctx); + HMAC_Init_ex(&ctx, key, sizeof(key), EVP_sha256(), NULL); + LONGBOW_START_DEPRECATED_WARNINGS +#endif + fd = open("test_random_bytes", O_RDONLY); + assertTrue(fd > 0, "Could not open input file: %s", strerror(errno)); + to_digest_length = read(fd, to_digest_buffer, sizeof(to_digest_buffer)); + assertTrue(to_digest_length > 0, "Could not read input file: %s", strerror(errno)); + close(fd); + + fd = open("test_random_bytes.hmac_sha256", O_RDONLY); + assertTrue(fd > 0, "Could not open input file: %s", strerror(errno)); + true_hmac_length = read(fd, true_hmac_buffer, sizeof(true_hmac_buffer)); + assertTrue(true_hmac_length > 0, "Could not read input file: %s", strerror(errno)); + close(fd); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + _hmacInit(ctx); + _hmacUpdate(ctx, to_digest_buffer, to_digest_length); +#else + _hmacInit(&ctx); + _hmacUpdate(&ctx, to_digest_buffer, to_digest_length); +#endif + PARCBuffer *output = _hmacFinalize(&ctx); + + assertTrue(parcBuffer_Position(output) == true_hmac_length, + "hmac wrong length, expected %zu got %zu", + true_hmac_length, + parcBuffer_Position(output)); + + assertTrue(memcmp(parcByteArray_Array(parcBuffer_Array(output)), true_hmac_buffer, true_hmac_length) == 0, + "hmac values did not match"); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + HMAC_CTX_free(ctx); +#else + LONGBOW_STOP_DEPRECATED_WARNINGS + HMAC_cleanup(&ctx); + LONGBOW_START_DEPRECATED_WARNINGS +#endif + parcBuffer_Release(&output); +} + +LONGBOW_TEST_CASE(Specialization, test_hmac_sha512) +{ +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + HMAC_CTX *ctx = HMAC_CTX_new(); +#else + HMAC_CTX ctx; +#endif + char key[] = "apple_pie_is_good"; + int fd; + uint8_t to_digest_buffer[MAXPATHLEN]; + ssize_t to_digest_length; + + uint8_t true_hmac_buffer[MAXPATHLEN]; + ssize_t true_hmac_length; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + HMAC_Init_ex(ctx, key, sizeof(key), EVP_sha512(), NULL); +#else + LONGBOW_STOP_DEPRECATED_WARNINGS + HMAC_CTX_init(&ctx); + HMAC_Init_ex(&ctx, key, sizeof(key), EVP_sha512(), NULL); + LONGBOW_START_DEPRECATED_WARNINGS +#endif + fd = open("test_random_bytes", O_RDONLY); + assertTrue(fd > 0, "Could not open input file: %s", strerror(errno)); + to_digest_length = read(fd, to_digest_buffer, sizeof(to_digest_buffer)); + assertTrue(to_digest_length > 0, "Could not read input file: %s", strerror(errno)); + close(fd); + + fd = open("test_random_bytes.hmac_sha512", O_RDONLY); + assertTrue(fd > 0, "Could not open input file: %s", strerror(errno)); + true_hmac_length = read(fd, true_hmac_buffer, sizeof(true_hmac_buffer)); + assertTrue(true_hmac_length > 0, "Could not read input file: %s", strerror(errno)); + close(fd); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + _hmacInit(ctx); + _hmacUpdate(ctx, to_digest_buffer, to_digest_length); +#else + _hmacInit(&ctx); + _hmacUpdate(&ctx, to_digest_buffer, to_digest_length); +#endif + PARCBuffer *output = _hmacFinalize(&ctx); + + assertTrue(parcBuffer_Position(output) == true_hmac_length, + "hmac wrong length, expected %zu got %zu", + true_hmac_length, + parcBuffer_Position(output)); + + assertTrue(memcmp(parcByteArray_Array(parcBuffer_Array(output)), true_hmac_buffer, true_hmac_length) == 0, + "hmac values did not match"); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + HMAC_CTX_free(ctx); +#else + LONGBOW_STOP_DEPRECATED_WARNINGS + HMAC_cleanup(&ctx); + LONGBOW_START_DEPRECATED_WARNINGS +#endif + parcBuffer_Release(&output); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_SymmetricSigner); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_SymmetricKeyStore.c b/libparc/parc/security/test/test_parc_SymmetricKeyStore.c new file mode 100755 index 00000000..ab9dfddb --- /dev/null +++ b/libparc/parc/security/test/test_parc_SymmetricKeyStore.c @@ -0,0 +1,351 @@ +/* + * 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_SymmetricKeyStore.c" +#include <parc/algol/parc_SafeMemory.h> + +#include <errno.h> +#include <sys/param.h> +#include <fcntl.h> + +#include <parc/security/parc_SymmetricKeySigner.h> + +#include <LongBow/unit-test.h> + +LONGBOW_TEST_RUNNER(parc_SymmetricSignerFileStore) +{ + // 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_SymmetricSignerFileStore) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_SymmetricSignerFileStore) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcSymmetricKeyStore_Create); + LONGBOW_RUN_TEST_CASE(Global, parcSymmetricKeyStore_CreateKey); +// LONGBOW_RUN_TEST_CASE(Global, parcSymmetricKeyStore_CreateFail); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + 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(Global, parcSymmetricKeyStore_Create) +{ + char dirname[] = "/tmp/pubkeystore_XXXXXX"; + char filename[MAXPATHLEN]; + + char *tmp_dirname = mkdtemp(dirname); + assertNotNull(tmp_dirname, "tmp_dirname should not be null"); + sprintf(filename, "%s/pubkeystore.p12", tmp_dirname); + + PARCBuffer *secret_key = parcSymmetricKeyStore_CreateKey(256); + + PARCSymmetricKeyStore *symmetricKeyStore = parcSymmetricKeyStore_Create(secret_key); + PARCSymmetricKeySigner *privateKeySigner = parcSymmetricKeySigner_Create(symmetricKeyStore, PARCCryptoHashType_SHA256); + PARCSigner *signer = parcSigner_Create(privateKeySigner, PARCSymmetricKeySignerAsSigner); + parcSymmetricKeySigner_Release(&privateKeySigner); + + parcSymmetricKeyStore_Release(&symmetricKeyStore); + parcSigner_Release(&signer); + parcBuffer_Release(&secret_key); +} + +LONGBOW_TEST_CASE(Global, parcSymmetricKeyStore_CreateKey) +{ + PARCBuffer *bb = parcSymmetricKeyStore_CreateKey(256); + assertTrue(parcBuffer_Remaining(bb) == 32, "Key wrong length expected %d got %zu", 32, parcBuffer_Position(bb)); + parcBuffer_Release(&bb); +} + +LONGBOW_TEST_CASE_EXPECTS(Global, parcSymmetricKeyStore_CreateFail, .event = &LongBowTrapIllegalValue) +{ + PARCBuffer *key = parcSymmetricKeyStore_CreateKey(256); + PARCSymmetricKeyStore *symmetricKeyStore = parcSymmetricKeyStore_Create(key); + PARCSymmetricKeySigner *privateKeySigner = parcSymmetricKeySigner_Create(symmetricKeyStore, PARCCryptoHashType_CRC32C); + + // fail. + + parcSymmetricKeyStore_Release(&symmetricKeyStore); + parcSymmetricKeySigner_Release(&privateKeySigner); + parcBuffer_Release(&key); +} + +// ========================================== + +LONGBOW_TEST_FIXTURE(Local) +{ + LONGBOW_RUN_TEST_CASE(Local, parcSymmetricKeyStore_GetCryptoHashType); + LONGBOW_RUN_TEST_CASE(Local, parcSymmetricKeyStore_GetSecretKeyDigest); + LONGBOW_RUN_TEST_CASE(Local, parcSymmetricKeyStore_GetSigningAlgorithm); + LONGBOW_RUN_TEST_CASE(Local, parcSymmetricKeyStore_SignDigest_sha256); + LONGBOW_RUN_TEST_CASE(Local, parcSymmetricKeyStore_SignDigest_sha512); +} + +LONGBOW_TEST_FIXTURE_SETUP(Local) +{ + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Local) +{ + 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, parcSymmetricKeyStore_GetCryptoHashType) +{ + PARCBuffer *secret_key = parcSymmetricKeyStore_CreateKey(256); + + PARCSymmetricKeyStore *symmetricKeyStore = parcSymmetricKeyStore_Create(secret_key); + PARCSymmetricKeySigner *privateKeySigner = parcSymmetricKeySigner_Create(symmetricKeyStore, PARCCryptoHashType_SHA256); + PARCSigner *signer = parcSigner_Create(privateKeySigner, PARCSymmetricKeySignerAsSigner); + parcSymmetricKeySigner_Release(&privateKeySigner); + + PARCCryptoHashType hashType = parcSigner_GetCryptoHashType(signer); + assertTrue(hashType == PARCCryptoHashType_SHA256, + "Got wrong hash Type, expected %d got %d", PARCCryptoHashType_SHA256, hashType); + + parcSymmetricKeyStore_Release(&symmetricKeyStore); + parcSigner_Release(&signer); + parcBuffer_Release(&secret_key); +} + +LONGBOW_TEST_CASE(Local, parcSymmetricKeyStore_GetSecretKeyDigest) +{ + int fd; + uint8_t key_buffer[128]; + uint8_t key_sha256[128]; + ssize_t read_len; + + fd = open("test_symmetric_key.bin", O_RDONLY); + read_len = read(fd, key_buffer, sizeof(key_buffer)); + assertTrue(read_len == 32, "read wrong size, expected 32, got %zd", read_len); + close(fd); + + fd = open("test_symmetric_key.sha256", O_RDONLY); + read_len = read(fd, key_sha256, sizeof(key_sha256)); + assertTrue(read_len == 32, "read wrong size, expected 32, got %zd", read_len); + close(fd); + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutArray(composer, key_buffer, 32); + PARCBuffer *secret_key = parcBufferComposer_ProduceBuffer(composer); + + PARCBufferComposer *composer2 = parcBufferComposer_Create(); + parcBufferComposer_PutArray(composer2, key_sha256, 32); + PARCBuffer *secret_sha = parcBufferComposer_ProduceBuffer(composer2); + + PARCSymmetricKeyStore *symmetricKeyStore = parcSymmetricKeyStore_Create(secret_key); + PARCSymmetricKeySigner *privateKeySigner = parcSymmetricKeySigner_Create(symmetricKeyStore, PARCCryptoHashType_SHA256); + PARCSigner *signer = parcSigner_Create(privateKeySigner, PARCSymmetricKeySignerAsSigner); + parcSymmetricKeySigner_Release(&privateKeySigner); + + PARCCryptoHash *key_hash = parcKeyStore_GetVerifierKeyDigest(parcSigner_GetKeyStore(signer)); + assertTrue(parcBuffer_Equals(parcCryptoHash_GetDigest(key_hash), secret_sha), + "sha256 digests of secret key did not match"); + parcCryptoHash_Release(&key_hash); + + parcSymmetricKeyStore_Release(&symmetricKeyStore); + parcBuffer_Release(&secret_sha); + parcBufferComposer_Release(&composer); + parcBuffer_Release(&secret_key); + parcBufferComposer_Release(&composer2); + parcSigner_Release(&signer); +} + +LONGBOW_TEST_CASE(Local, parcSymmetricKeyStore_GetSigningAlgorithm) +{ + PARCBuffer *secret_key = parcSymmetricKeyStore_CreateKey(256); + + PARCSymmetricKeyStore *symmetricKeyStore = parcSymmetricKeyStore_Create(secret_key); + PARCSymmetricKeySigner *privateKeySigner = parcSymmetricKeySigner_Create(symmetricKeyStore, PARCCryptoHashType_SHA256); + PARCSigner *signer = parcSigner_Create(privateKeySigner, PARCSymmetricKeySignerAsSigner); + parcSymmetricKeySigner_Release(&privateKeySigner); + + PARCSigningAlgorithm alg = parcSigner_GetSigningAlgorithm(signer); + assertTrue(alg == PARCSigningAlgorithm_HMAC, + "Got wrong signing algorithm, expected %d got %d", PARCSigningAlgorithm_HMAC, alg); + + parcSymmetricKeyStore_Release(&symmetricKeyStore); + parcSigner_Release(&signer); + parcBuffer_Release(&secret_key); +} + +LONGBOW_TEST_CASE(Local, parcSymmetricKeyStore_SignDigest_sha256) +{ + uint8_t to_digest_buffer[MAXPATHLEN]; + ssize_t to_digest_length; + uint8_t true_hmac_buffer[MAXPATHLEN]; + char key[] = "apple_pie_is_good"; + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer, key); + PARCBuffer *key_buffer = parcBufferComposer_ProduceBuffer(composer); + + int fd = open("test_random_bytes", O_RDONLY); + assertTrue(fd > 0, "Could not open input file: %s", strerror(errno)); + to_digest_length = read(fd, to_digest_buffer, sizeof(to_digest_buffer)); + assertTrue(to_digest_length > 0, "Could not read input file: %s", strerror(errno)); + close(fd); + + fd = open("test_random_bytes.hmac_sha256", O_RDONLY); + assertTrue(fd > 0, "Could not open input file: %s", strerror(errno)); + ssize_t true_hmac_length = read(fd, true_hmac_buffer, sizeof(true_hmac_buffer)); + assertTrue(true_hmac_length > 0, "Could not read input file: %s", strerror(errno)); + close(fd); + + PARCBufferComposer *composer2 = parcBufferComposer_Create(); + parcBufferComposer_PutArray(composer2, true_hmac_buffer, true_hmac_length); + PARCBuffer *true_hash = parcBufferComposer_ProduceBuffer(composer2); + + PARCSymmetricKeyStore *symmetricKeyStore = parcSymmetricKeyStore_Create(key_buffer); + PARCSymmetricKeySigner *privateKeySigner = parcSymmetricKeySigner_Create(symmetricKeyStore, PARCCryptoHashType_SHA256); + PARCSigner *signer = parcSigner_Create(privateKeySigner, PARCSymmetricKeySignerAsSigner); + parcSymmetricKeySigner_Release(&privateKeySigner); + + PARCCryptoHasher *hasher = parcSigner_GetCryptoHasher(signer); + parcCryptoHasher_Init(hasher); + parcCryptoHasher_UpdateBytes(hasher, to_digest_buffer, to_digest_length); + PARCCryptoHash *hash = parcCryptoHasher_Finalize(hasher); + PARCSignature *sig = parcSigner_SignDigest(signer, hash); + + assertTrue(parcBuffer_Equals(parcSignature_GetSignature(sig), parcCryptoHash_GetDigest(hash)), + "Hashes are not equal"); + assertTrue(parcBuffer_Equals(parcSignature_GetSignature(sig), true_hash), + "Hash does not match file"); + assertTrue(parcSignature_GetSigningAlgorithm(sig) == PARCSigningAlgorithm_HMAC, + "Signing alg incorrect, expected %d got %d", + PARCSigningAlgorithm_HMAC, parcSignature_GetSigningAlgorithm(sig)); + assertTrue(parcSignature_GetHashType(sig) == PARCCryptoHashType_SHA256, + "Digest alg incorrect, expected %d got %d", + PARCCryptoHashType_SHA256, parcSignature_GetSigningAlgorithm(sig)); + + parcSymmetricKeyStore_Release(&symmetricKeyStore); + parcSignature_Release(&sig); + parcCryptoHash_Release(&hash); + parcBuffer_Release(&true_hash); + parcBuffer_Release(&key_buffer); + parcBufferComposer_Release(&composer); + parcBufferComposer_Release(&composer2); + parcSigner_Release(&signer); +} + +LONGBOW_TEST_CASE(Local, parcSymmetricKeyStore_SignDigest_sha512) +{ + char key[] = "apple_pie_is_good"; + + PARCBufferComposer *composer = parcBufferComposer_Create(); + parcBufferComposer_PutString(composer, key); + PARCBuffer *key_buffer = parcBufferComposer_ProduceBuffer(composer); + + int fd; + uint8_t to_digest_buffer[MAXPATHLEN]; + ssize_t to_digest_length; + + uint8_t true_hmac_buffer[MAXPATHLEN]; + ssize_t true_hmac_length; + + fd = open("test_random_bytes", O_RDONLY); + assertTrue(fd > 0, "Could not open input file: %s", strerror(errno)); + to_digest_length = read(fd, to_digest_buffer, sizeof(to_digest_buffer)); + assertTrue(to_digest_length > 0, "Could not read input file: %s", strerror(errno)); + close(fd); + + fd = open("test_random_bytes.hmac_sha512", O_RDONLY); + assertTrue(fd > 0, "Could not open input file: %s", strerror(errno)); + true_hmac_length = read(fd, true_hmac_buffer, sizeof(true_hmac_buffer)); + assertTrue(true_hmac_length > 0, "Could not read input file: %s", strerror(errno)); + close(fd); + + PARCBufferComposer *composer2 = parcBufferComposer_Create(); + parcBufferComposer_PutArray(composer2, true_hmac_buffer, true_hmac_length); + PARCBuffer *true_hash = parcBufferComposer_ProduceBuffer(composer2); + + PARCSymmetricKeyStore *symmetricKeyStore = parcSymmetricKeyStore_Create(key_buffer); + PARCSymmetricKeySigner *privateKeySigner = parcSymmetricKeySigner_Create(symmetricKeyStore, PARCCryptoHashType_SHA512); + PARCSigner *signer = parcSigner_Create(privateKeySigner, PARCSymmetricKeySignerAsSigner); + parcSymmetricKeySigner_Release(&privateKeySigner); + + PARCCryptoHasher *hasher = parcSigner_GetCryptoHasher(signer); + parcCryptoHasher_Init(hasher); + parcCryptoHasher_UpdateBytes(hasher, to_digest_buffer, to_digest_length); + PARCCryptoHash *hash = parcCryptoHasher_Finalize(hasher); + PARCSignature *sig = parcSigner_SignDigest(signer, hash); + + assertTrue(parcBuffer_Equals(parcSignature_GetSignature(sig), parcCryptoHash_GetDigest(hash)), + "Hashes are not equal"); + assertTrue(parcBuffer_Equals(parcSignature_GetSignature(sig), true_hash), + "Hash does not match file"); + assertTrue(parcSignature_GetSigningAlgorithm(sig) == PARCSigningAlgorithm_HMAC, + "Signing alg incorrect, expected %d got %d", + PARCSigningAlgorithm_HMAC, parcSignature_GetSigningAlgorithm(sig)); + assertTrue(parcSignature_GetHashType(sig) == PARCCryptoHashType_SHA512, + "Digest alg incorrect, expected %d got %d", + PARCCryptoHashType_SHA512, parcSignature_GetSigningAlgorithm(sig)); + + parcSymmetricKeyStore_Release(&symmetricKeyStore); + parcSignature_Release(&sig); + parcCryptoHash_Release(&hash); + parcBuffer_Release(&true_hash); + parcBuffer_Release(&key_buffer); + parcBufferComposer_Release(&composer); + parcBufferComposer_Release(&composer2); + parcSigner_Release(&signer); +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_SymmetricSignerFileStore); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_Verifier.c b/libparc/parc/security/test/test_parc_Verifier.c new file mode 100755 index 00000000..fe382a9b --- /dev/null +++ b/libparc/parc/security/test/test_parc_Verifier.c @@ -0,0 +1,121 @@ +/* + * 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_Verifier.c" + +#include <LongBow/unit-test.h> + +LONGBOW_TEST_RUNNER(parc_Verifier) +{ + // 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_Verifier) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_Verifier) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parcVerifier_AddKey); + LONGBOW_RUN_TEST_CASE(Global, parcVerifier_AllowedCryptoSuite); + LONGBOW_RUN_TEST_CASE(Global, parcVerifier_Create); + LONGBOW_RUN_TEST_CASE(Global, parcVerifier_Destroy); + LONGBOW_RUN_TEST_CASE(Global, parcVerifier_GetCryptoHasher); + LONGBOW_RUN_TEST_CASE(Global, parcVerifier_RemoveKeyId); + LONGBOW_RUN_TEST_CASE(Global, parcVerifier_VerifySignature); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, parcVerifier_AddKey) +{ + testUnimplemented(""); +} + +LONGBOW_TEST_CASE(Global, parcVerifier_AllowedCryptoSuite) +{ + testUnimplemented(""); +} + +LONGBOW_TEST_CASE(Global, parcVerifier_Create) +{ + testUnimplemented(""); +} + +LONGBOW_TEST_CASE(Global, parcVerifier_Destroy) +{ + testUnimplemented(""); +} + +LONGBOW_TEST_CASE(Global, parcVerifier_GetCryptoHasher) +{ + testUnimplemented(""); +} + +LONGBOW_TEST_CASE(Global, parcVerifier_RemoveKeyId) +{ + testUnimplemented(""); +} + +LONGBOW_TEST_CASE(Global, parcVerifier_VerifySignature) +{ + testUnimplemented(""); +} + +LONGBOW_TEST_FIXTURE(Local) +{ +} + +LONGBOW_TEST_FIXTURE_SETUP(Local) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Local) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Verifier); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_parc_X509Certificate.c b/libparc/parc/security/test/test_parc_X509Certificate.c new file mode 100755 index 00000000..3ddb8220 --- /dev/null +++ b/libparc/parc/security/test/test_parc_X509Certificate.c @@ -0,0 +1,224 @@ +/* + * 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 <config.h> +#include <stdio.h> +#include <LongBow/unit-test.h> + +#include <unistd.h> +#include <fcntl.h> + +#include "../parc_X509Certificate.c" +#include <parc/algol/parc_SafeMemory.h> +#include <parc/security/parc_CryptoHashType.h> +#include <parc/algol/parc_Buffer.h> + +LONGBOW_TEST_RUNNER(parc_X509Certificate) +{ + // 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_TEST_RUNNER_SETUP(parc_X509Certificate) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_X509Certificate) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, parc_X509Certificate_AcquireRelease); + LONGBOW_RUN_TEST_CASE(Global, parc_X509Certificate_Create); + LONGBOW_RUN_TEST_CASE(Global, parc_X509Certificate_CreateFromDERBuffer); + LONGBOW_RUN_TEST_CASE(Global, parc_X509Certificate_GetPublicKeyDigest); + LONGBOW_RUN_TEST_CASE(Global, parc_X509Certificate_GetCertificateDigest); + LONGBOW_RUN_TEST_CASE(Global, parc_X509Certificate_GetDEREncodedCertificate); + LONGBOW_RUN_TEST_CASE(Global, parc_X509Certificate_GetDEREncodedPublicKey); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + parcSecurity_Init(); + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + 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(Global, parc_X509Certificate_AcquireRelease) +{ + char *fileName = "test.pem"; + PARCX509Certificate *certificate = parcX509Certificate_CreateFromPEMFile(fileName); + assertNotNull(certificate, "Expected non-NULL certificate"); + + PARCReferenceCount firstCount = parcObject_GetReferenceCount(certificate); + PARCX509Certificate *copy = parcX509Certificate_Acquire(certificate); + PARCReferenceCount secondCount = parcObject_GetReferenceCount(copy); + + assertTrue(firstCount == (secondCount - 1), "Expected incremented reference count after Acquire"); + + parcX509Certificate_Release(©); + PARCReferenceCount thirdCount = parcObject_GetReferenceCount(certificate); + + assertTrue(firstCount == thirdCount, "Expected equal reference counts after Release"); + + parcX509Certificate_Release(&certificate); +} + +LONGBOW_TEST_CASE(Global, parc_X509Certificate_Create) +{ + char *fileName = "bad.pem"; + PARCX509Certificate *certificate = _parcX509Certificate_CreateFromPEMFile(fileName); + assertNull(certificate, "Expected NULL certificate with non-existent file"); +} + +LONGBOW_TEST_CASE(Global, parc_X509Certificate_CreateFromDERBuffer) +{ + char *fileName = "test.pem"; + PARCX509Certificate *certificate = _parcX509Certificate_CreateFromPEMFile(fileName); + assertNotNull(certificate, "Expected non-NULL certificate"); + + PARCBuffer *certificateBuffer = _getDEREncodedCertificate(certificate); + PARCX509Certificate *realCertificate = parcX509Certificate_CreateFromDERBuffer(certificateBuffer); + assertNotNull(realCertificate, "Expected non-NULL certificate to be parsed from DER buffer"); + + parcX509Certificate_Release(&certificate); + parcX509Certificate_Release(&realCertificate); +} + +LONGBOW_TEST_CASE(Global, parc_X509Certificate_GetPublicKeyDigest) +{ + char *fileName = "test.pem"; + PARCX509Certificate *certificate = _parcX509Certificate_CreateFromPEMFile(fileName); + + PARCCryptoHash *digest = _getPublicKeyDigest(certificate); + PARCBuffer *digestBuffer = parcCryptoHash_GetDigest(digest); + + size_t expectedLength = SHA256_DIGEST_LENGTH; + size_t actualLength = parcBuffer_Remaining(digestBuffer); + assertTrue(actualLength == expectedLength, "Digest unexpected size: got %zu expected %zu", actualLength, expectedLength); + + int fd = open("test_pubkey.bin", O_RDONLY); + uint8_t rawDigest[SHA256_DIGEST_LENGTH]; + ssize_t numBytes = read(fd, rawDigest, SHA256_DIGEST_LENGTH); + assertTrue(numBytes == SHA256_DIGEST_LENGTH, "Expected to read %d bytes, got %zu", SHA256_DIGEST_LENGTH, numBytes); + close(fd); + + PARCBuffer *rawBuffer = parcBuffer_Flip(parcBuffer_CreateFromArray(rawDigest, SHA256_DIGEST_LENGTH)); + + assertTrue(parcBuffer_Remaining(rawBuffer) == SHA256_DIGEST_LENGTH, "Expected %d length buffer", SHA256_DIGEST_LENGTH); + + parcBuffer_Release(&rawBuffer); + parcX509Certificate_Release(&certificate); +} + +LONGBOW_TEST_CASE(Global, parc_X509Certificate_GetCertificateDigest) +{ + char *fileName = "test.pem"; + PARCX509Certificate *certificate = _parcX509Certificate_CreateFromPEMFile(fileName); + + PARCCryptoHash *digest = _getCertificateDigest(certificate); + PARCBuffer *digestBuffer = parcCryptoHash_GetDigest(digest); + + size_t expectedLength = SHA256_DIGEST_LENGTH; + size_t actualLength = parcBuffer_Remaining(digestBuffer); + assertTrue(actualLength == expectedLength, "Digest unexpected size: got %zu expected %zu", actualLength, expectedLength); + + int fd = open("test_crt_sha256.bin", O_RDONLY); + uint8_t rawDigest[SHA256_DIGEST_LENGTH]; + ssize_t numBytes = read(fd, rawDigest, SHA256_DIGEST_LENGTH); + assertTrue(numBytes == SHA256_DIGEST_LENGTH, "Expected to read %d bytes, got %zu", SHA256_DIGEST_LENGTH, numBytes); + close(fd); + + PARCBuffer *rawBuffer = parcBuffer_Flip(parcBuffer_CreateFromArray(rawDigest, SHA256_DIGEST_LENGTH)); + + assertTrue(parcBuffer_Equals(rawBuffer, digestBuffer), "Expected raw binary to equal the computed result."); + + parcBuffer_Release(&rawBuffer); + parcX509Certificate_Release(&certificate); +} + +LONGBOW_TEST_CASE(Global, parc_X509Certificate_GetDEREncodedCertificate) +{ + char *fileName = "test.pem"; + PARCX509Certificate *certificate = _parcX509Certificate_CreateFromPEMFile(fileName); + + PARCBuffer *digestBuffer = _getDEREncodedCertificate(certificate); + + size_t expectedLength = 517; + size_t actualLength = parcBuffer_Remaining(digestBuffer); + assertTrue(actualLength == expectedLength, "Digest unexpected size: got %zu expected %zu", actualLength, expectedLength); + + int fd = open("test_crt_der.bin", O_RDONLY); + uint8_t rawDigest[expectedLength]; + ssize_t numBytes = read(fd, rawDigest, expectedLength); + assertTrue(numBytes == expectedLength, "Expected to read %zu bytes, got %zu", expectedLength, numBytes); + close(fd); + + PARCBuffer *rawBuffer = parcBuffer_Flip(parcBuffer_CreateFromArray(rawDigest, expectedLength)); + + assertTrue(parcBuffer_Equals(rawBuffer, digestBuffer), "Expected raw binary to equal the computed result."); + + parcBuffer_Release(&rawBuffer); + parcX509Certificate_Release(&certificate); +} + +LONGBOW_TEST_CASE(Global, parc_X509Certificate_GetDEREncodedPublicKey) +{ + char *fileName = "test.pem"; + PARCX509Certificate *certificate = _parcX509Certificate_CreateFromPEMFile(fileName); + + PARCBuffer *digestBuffer = _getDEREncodedPublicKey(certificate); + + size_t expectedLength = 162; + size_t actualLength = parcBuffer_Remaining(digestBuffer); + assertTrue(actualLength == expectedLength, "Digest unexpected size: got %zu expected %zu", actualLength, expectedLength); + + int fd = open("test_der.bin", O_RDONLY); + uint8_t rawDigest[expectedLength]; + ssize_t numBytes = read(fd, rawDigest, expectedLength); + assertTrue(numBytes == expectedLength, "Expected to read %zu bytes, got %zu", expectedLength, numBytes); + close(fd); + + PARCBuffer *rawBuffer = parcBuffer_Flip(parcBuffer_CreateFromArray(rawDigest, expectedLength)); + + assertTrue(parcBuffer_Equals(rawBuffer, digestBuffer), "Expected raw binary to equal the computed result."); + + parcBuffer_Release(&rawBuffer); + parcX509Certificate_Release(&certificate); +} + +int +main(int argc, char *argv[argc]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_X509Certificate); + int exitStatus = LONGBOW_TEST_MAIN(argc, argv, testRunner); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libparc/parc/security/test/test_pubkey.bin b/libparc/parc/security/test/test_pubkey.bin new file mode 100644 index 00000000..1d426b87 --- /dev/null +++ b/libparc/parc/security/test/test_pubkey.bin @@ -0,0 +1 @@ +_.yWSfbQИ6u\ob
\ No newline at end of file diff --git a/libparc/parc/security/test/test_pubkey.der b/libparc/parc/security/test/test_pubkey.der new file mode 100644 index 00000000..eb75e987 --- /dev/null +++ b/libparc/parc/security/test/test_pubkey.der @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDR0t1wjPPlx/x3vMDN/yaClXmp +NqdIX31oejG4nFQrqH821a6vZjaEEk6jNUM9v4a5mDHdgXQCvSjoRVnfCPVi06j/ +h4oylHaANMSOfcP2AimGBT0R1mT8cBHsI1JmYfhS5jSCzxyyTtq0WVDqndGl0qZp +cRGONepOxn36uZso2QIDAQAB +-----END PUBLIC KEY----- diff --git a/libparc/parc/security/test/test_pubkey.pem b/libparc/parc/security/test/test_pubkey.pem new file mode 100644 index 00000000..eb75e987 --- /dev/null +++ b/libparc/parc/security/test/test_pubkey.pem @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDR0t1wjPPlx/x3vMDN/yaClXmp +NqdIX31oejG4nFQrqH821a6vZjaEEk6jNUM9v4a5mDHdgXQCvSjoRVnfCPVi06j/ +h4oylHaANMSOfcP2AimGBT0R1mT8cBHsI1JmYfhS5jSCzxyyTtq0WVDqndGl0qZp +cRGONepOxn36uZso2QIDAQAB +-----END PUBLIC KEY----- diff --git a/libparc/parc/security/test/test_random_bytes b/libparc/parc/security/test/test_random_bytes Binary files differnew file mode 100644 index 00000000..33a80af5 --- /dev/null +++ b/libparc/parc/security/test/test_random_bytes diff --git a/libparc/parc/security/test/test_random_bytes.hmac_sha256 b/libparc/parc/security/test/test_random_bytes.hmac_sha256 Binary files differnew file mode 100644 index 00000000..ee066075 --- /dev/null +++ b/libparc/parc/security/test/test_random_bytes.hmac_sha256 diff --git a/libparc/parc/security/test/test_random_bytes.hmac_sha512 b/libparc/parc/security/test/test_random_bytes.hmac_sha512 Binary files differnew file mode 100644 index 00000000..fcd110b2 --- /dev/null +++ b/libparc/parc/security/test/test_random_bytes.hmac_sha512 diff --git a/libparc/parc/security/test/test_random_bytes.sig b/libparc/parc/security/test/test_random_bytes.sig Binary files differnew file mode 100644 index 00000000..9c395ce0 --- /dev/null +++ b/libparc/parc/security/test/test_random_bytes.sig diff --git a/libparc/parc/security/test/test_rsa.crt b/libparc/parc/security/test/test_rsa.crt new file mode 100644 index 00000000..6f7ce9e6 --- /dev/null +++ b/libparc/parc/security/test/test_rsa.crt @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICATCCAWoCCQDE2fTij4zOkTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTEzMTAxNTIzMjUyNloXDTE0MTAxNTIzMjUyNlowRTELMAkG +A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAp9aT +xfFzxhK1+nnF7xiL76rNBAGPg3c/sWahWrk5KrI+MPsR/Ff8ndEvd/Crd61mLCbI +m1Fvab8mEAYp7suwLF6RDiRCjeZ1oE4EQww+TAZ0Z62Ew+j0xZRzxJ8lqEIGv0UZ +4pgcNqFDTZtxCOGC3+JPKjw9DzWSrnAn+9LkHicCAwEAATANBgkqhkiG9w0BAQUF +AAOBgQALNQ1/nNF/jMYijV+XI/IL0/zziaUu2GSyTQlGsmfLhMY0/Qx+8Pbaik+R +DVtNMZatJGSXgSvx6ETGpkXVdsZzZfDIYSIyKrbf7uV3GFfqCv4IqU2OI42ex7TE +Ry+xm2mioAYgcnAIxA4CmyTm+tWJ9MTJkCG/aPhhcPxP6XzjPA== +-----END CERTIFICATE----- diff --git a/libparc/parc/security/test/test_rsa.csr b/libparc/parc/security/test/test_rsa.csr new file mode 100644 index 00000000..1ff56fc4 --- /dev/null +++ b/libparc/parc/security/test/test_rsa.csr @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBhDCB7gIBADBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEh +MB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQCn1pPF8XPGErX6ecXvGIvvqs0EAY+Ddz+xZqFauTkqsj4w ++xH8V/yd0S938Kt3rWYsJsibUW9pvyYQBinuy7AsXpEOJEKN5nWgTgRDDD5MBnRn +rYTD6PTFlHPEnyWoQga/RRnimBw2oUNNm3EI4YLf4k8qPD0PNZKucCf70uQeJwID +AQABoAAwDQYJKoZIhvcNAQEFBQADgYEAEVdzGyNxqWTRSaBo8JybmHNuXiTLvGPR +GCegG3GwtTiptzwrtUhOmkWoPkWBwB/rLJyga7sPgg73D5aCz3PsagNSqLytCuW+ +qFJdODd6IXQrJ8fUHsV2SENNbkL+zsg1cYVB0T+8B6BP84hHaD3NResmMVjhuPIr +0uHYQ7e2ex8= +-----END CERTIFICATE REQUEST----- diff --git a/libparc/parc/security/test/test_rsa.p12 b/libparc/parc/security/test/test_rsa.p12 Binary files differnew file mode 100644 index 00000000..471c4006 --- /dev/null +++ b/libparc/parc/security/test/test_rsa.p12 diff --git a/libparc/parc/security/test/test_rsa_crt.der b/libparc/parc/security/test/test_rsa_crt.der Binary files differnew file mode 100644 index 00000000..d79f4b47 --- /dev/null +++ b/libparc/parc/security/test/test_rsa_crt.der diff --git a/libparc/parc/security/test/test_rsa_crt_sha256.bin b/libparc/parc/security/test/test_rsa_crt_sha256.bin new file mode 100644 index 00000000..7da092ff --- /dev/null +++ b/libparc/parc/security/test/test_rsa_crt_sha256.bin @@ -0,0 +1,2 @@ +VF,-x(SEl/ +:H&64M!:=)
\ No newline at end of file diff --git a/libparc/parc/security/test/test_rsa_key.der b/libparc/parc/security/test/test_rsa_key.der Binary files differnew file mode 100644 index 00000000..a88e8e94 --- /dev/null +++ b/libparc/parc/security/test/test_rsa_key.der diff --git a/libparc/parc/security/test/test_rsa_key.pem b/libparc/parc/security/test/test_rsa_key.pem new file mode 100644 index 00000000..6c502b15 --- /dev/null +++ b/libparc/parc/security/test/test_rsa_key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQCn1pPF8XPGErX6ecXvGIvvqs0EAY+Ddz+xZqFauTkqsj4w+xH8 +V/yd0S938Kt3rWYsJsibUW9pvyYQBinuy7AsXpEOJEKN5nWgTgRDDD5MBnRnrYTD +6PTFlHPEnyWoQga/RRnimBw2oUNNm3EI4YLf4k8qPD0PNZKucCf70uQeJwIDAQAB +AoGAVOYPA/7aIGSQlu4IOKTDDG3qnM8pSEgG+PbAQgMVrspQ+TfXZj0ftLj++P3N +zpDw8P6BVUfBQs2FNG/ZwEhaiZVgJAl7cIAxJ9Ac+1oZYSgGyJfb3u9iWvkbMOoj +83Inx5yyN+Qmk5zceH4pOC5D5cDAuGGZ740Euv4o2/2O3qECQQDTmWZw021PvEbA +r18O1YfZGxO3zFCwFXCpnHvtSMbP+MXAG5Gt47wZt4Vx1rX9k78beeCUitwqp3d3 +ZI+YlUu3AkEAyw5wssQsJty/n2FL8DbJN3UzUhkcaCFYrKz3RtFye9wu+Bw0TxPC +3jhFVcynm3nH3ZJN0JsnsPnHXuoQToShEQJATXC51hb6zZC5UDGel348fo9zUvP6 +n8bo+ZoknL3izSBdtyYf1cUgBUVuGDCdYFWfPn4HXDXJx+6MQWzTRON21wJBAMZL +U8M/z94jtP3wBjiPR/Dggz2pSBRofDAkuVZvM13BqByjbnHK2oIocY1YTlWGl6fJ +ODR/UEODqS8HZOVIoAECQANcuvVnqDixSIl2ySZvydQytv4DKTbvE0nYSRroYIlJ +PTOBPy8ynIUkJwc2E1BsLl7V8gO62a5O0ntTwBMnPSQ= +-----END RSA PRIVATE KEY----- diff --git a/libparc/parc/security/test/test_rsa_pub.der b/libparc/parc/security/test/test_rsa_pub.der Binary files differnew file mode 100644 index 00000000..7c931999 --- /dev/null +++ b/libparc/parc/security/test/test_rsa_pub.der diff --git a/libparc/parc/security/test/test_rsa_pub.pem b/libparc/parc/security/test/test_rsa_pub.pem new file mode 100644 index 00000000..7b8f29c2 --- /dev/null +++ b/libparc/parc/security/test/test_rsa_pub.pem @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCn1pPF8XPGErX6ecXvGIvvqs0E +AY+Ddz+xZqFauTkqsj4w+xH8V/yd0S938Kt3rWYsJsibUW9pvyYQBinuy7AsXpEO +JEKN5nWgTgRDDD5MBnRnrYTD6PTFlHPEnyWoQga/RRnimBw2oUNNm3EI4YLf4k8q +PD0PNZKucCf70uQeJwIDAQAB +-----END PUBLIC KEY----- diff --git a/libparc/parc/security/test/test_rsa_pub_sha256.bin b/libparc/parc/security/test/test_rsa_pub_sha256.bin new file mode 100644 index 00000000..c15478cf --- /dev/null +++ b/libparc/parc/security/test/test_rsa_pub_sha256.bin @@ -0,0 +1 @@ +\#L(P {%ba`v8IθY
\ No newline at end of file diff --git a/libparc/parc/security/test/test_symmetric_key.bin b/libparc/parc/security/test/test_symmetric_key.bin Binary files differnew file mode 100644 index 00000000..2ad3409d --- /dev/null +++ b/libparc/parc/security/test/test_symmetric_key.bin diff --git a/libparc/parc/security/test/test_symmetric_key.sha256 b/libparc/parc/security/test/test_symmetric_key.sha256 new file mode 100644 index 00000000..910397cf --- /dev/null +++ b/libparc/parc/security/test/test_symmetric_key.sha256 @@ -0,0 +1 @@ +A_ӻ-;Ȑn.1~072
\ No newline at end of file |