aboutsummaryrefslogtreecommitdiffstats
path: root/libparc/parc/security/test
diff options
context:
space:
mode:
Diffstat (limited to 'libparc/parc/security/test')
-rw-r--r--libparc/parc/security/test/.gitignore24
-rw-r--r--libparc/parc/security/test/CMakeLists.txt75
-rw-r--r--libparc/parc/security/test/README.digests12
-rw-r--r--libparc/parc/security/test/README.keystore35
-rw-r--r--libparc/parc/security/test/README.symmetric9
-rw-r--r--libparc/parc/security/test/test.crt.derbin0 -> 559 bytes
-rw-r--r--libparc/parc/security/test/test.crt.der.sha256.bin1
-rw-r--r--libparc/parc/security/test/test.derbin0 -> 162 bytes
-rw-r--r--libparc/parc/security/test/test.pem13
-rw-r--r--libparc/parc/security/test/test.pkcs12bin0 -> 1646 bytes
-rw-r--r--libparc/parc/security/test/test_crt.derbin0 -> 517 bytes
-rw-r--r--libparc/parc/security/test/test_crt_der.binbin0 -> 517 bytes
-rw-r--r--libparc/parc/security/test/test_crt_sha256.bin1
-rw-r--r--libparc/parc/security/test/test_der.binbin0 -> 162 bytes
-rw-r--r--libparc/parc/security/test/test_digest_bytes_128.bin1
-rw-r--r--libparc/parc/security/test/test_digest_bytes_128.sha2561
-rw-r--r--libparc/parc/security/test/test_digest_bytes_128.sha5121
-rw-r--r--libparc/parc/security/test/test_key.pem6
-rw-r--r--libparc/parc/security/test/test_parc_Certificate.c258
-rwxr-xr-xlibparc/parc/security/test/test_parc_CertificateFactory.c160
-rwxr-xr-xlibparc/parc/security/test/test_parc_CertificateType.c90
-rwxr-xr-xlibparc/parc/security/test/test_parc_ContainerEncoding.c90
-rwxr-xr-xlibparc/parc/security/test/test_parc_CryptoCache.c228
-rwxr-xr-xlibparc/parc/security/test/test_parc_CryptoHash.c184
-rw-r--r--libparc/parc/security/test/test_parc_CryptoHashType.c92
-rwxr-xr-xlibparc/parc/security/test/test_parc_CryptoHasher.c407
-rwxr-xr-xlibparc/parc/security/test/test_parc_CryptoSuite.c82
-rwxr-xr-xlibparc/parc/security/test/test_parc_DiffieHellman.c93
-rwxr-xr-xlibparc/parc/security/test/test_parc_DiffieHellmanKeyShare.c229
-rw-r--r--libparc/parc/security/test/test_parc_Identity.c232
-rw-r--r--libparc/parc/security/test/test_parc_IdentityFile.c242
-rwxr-xr-xlibparc/parc/security/test/test_parc_InMemoryVerifier.c417
-rwxr-xr-xlibparc/parc/security/test/test_parc_Key.c357
-rw-r--r--libparc/parc/security/test/test_parc_KeyId.c216
-rwxr-xr-xlibparc/parc/security/test/test_parc_KeyStore.c137
-rwxr-xr-xlibparc/parc/security/test/test_parc_Pkcs12KeyStore.c470
-rw-r--r--libparc/parc/security/test/test_parc_PublicKeySigner.c453
-rwxr-xr-xlibparc/parc/security/test/test_parc_SecureRandom.c241
-rwxr-xr-xlibparc/parc/security/test/test_parc_Security.c109
-rwxr-xr-xlibparc/parc/security/test/test_parc_Signature.c230
-rw-r--r--libparc/parc/security/test/test_parc_Signer.c305
-rwxr-xr-xlibparc/parc/security/test/test_parc_SigningAlgorithm.c125
-rw-r--r--libparc/parc/security/test/test_parc_SymmetricKeySigner.c247
-rwxr-xr-xlibparc/parc/security/test/test_parc_SymmetricKeyStore.c351
-rwxr-xr-xlibparc/parc/security/test/test_parc_Verifier.c121
-rwxr-xr-xlibparc/parc/security/test/test_parc_X509Certificate.c224
-rw-r--r--libparc/parc/security/test/test_pubkey.bin1
-rw-r--r--libparc/parc/security/test/test_pubkey.der6
-rw-r--r--libparc/parc/security/test/test_pubkey.pem6
-rw-r--r--libparc/parc/security/test/test_random_bytesbin0 -> 512 bytes
-rw-r--r--libparc/parc/security/test/test_random_bytes.hmac_sha256bin0 -> 32 bytes
-rw-r--r--libparc/parc/security/test/test_random_bytes.hmac_sha512bin0 -> 64 bytes
-rw-r--r--libparc/parc/security/test/test_random_bytes.sigbin0 -> 128 bytes
-rw-r--r--libparc/parc/security/test/test_rsa.crt13
-rw-r--r--libparc/parc/security/test/test_rsa.csr11
-rw-r--r--libparc/parc/security/test/test_rsa.p12bin0 -> 1598 bytes
-rw-r--r--libparc/parc/security/test/test_rsa_crt.derbin0 -> 517 bytes
-rw-r--r--libparc/parc/security/test/test_rsa_crt_sha256.bin2
-rw-r--r--libparc/parc/security/test/test_rsa_key.derbin0 -> 608 bytes
-rw-r--r--libparc/parc/security/test/test_rsa_key.pem15
-rw-r--r--libparc/parc/security/test/test_rsa_pub.derbin0 -> 162 bytes
-rw-r--r--libparc/parc/security/test/test_rsa_pub.pem6
-rw-r--r--libparc/parc/security/test/test_rsa_pub_sha256.bin1
-rw-r--r--libparc/parc/security/test/test_symmetric_key.binbin0 -> 32 bytes
-rw-r--r--libparc/parc/security/test/test_symmetric_key.sha2561
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
new file mode 100644
index 00000000..8b2e12ca
--- /dev/null
+++ b/libparc/parc/security/test/test.crt.der
Binary files differ
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
new file mode 100644
index 00000000..db368b72
--- /dev/null
+++ b/libparc/parc/security/test/test.der
Binary files differ
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
new file mode 100644
index 00000000..4b032263
--- /dev/null
+++ b/libparc/parc/security/test/test.pkcs12
Binary files differ
diff --git a/libparc/parc/security/test/test_crt.der b/libparc/parc/security/test/test_crt.der
new file mode 100644
index 00000000..42a829ee
--- /dev/null
+++ b/libparc/parc/security/test/test_crt.der
Binary files differ
diff --git a/libparc/parc/security/test/test_crt_der.bin b/libparc/parc/security/test/test_crt_der.bin
new file mode 100644
index 00000000..42a829ee
--- /dev/null
+++ b/libparc/parc/security/test/test_crt_der.bin
Binary files differ
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
new file mode 100644
index 00000000..db368b72
--- /dev/null
+++ b/libparc/parc/security/test/test_der.bin
Binary files differ
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 @@
+W Juie>]ϲ 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(&copy);
+ 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(&copy);
+ 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(&copy);
+ 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(&copy);
+ 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(&copy);
+ 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
new file mode 100644
index 00000000..33a80af5
--- /dev/null
+++ b/libparc/parc/security/test/test_random_bytes
Binary files differ
diff --git a/libparc/parc/security/test/test_random_bytes.hmac_sha256 b/libparc/parc/security/test/test_random_bytes.hmac_sha256
new file mode 100644
index 00000000..ee066075
--- /dev/null
+++ b/libparc/parc/security/test/test_random_bytes.hmac_sha256
Binary files differ
diff --git a/libparc/parc/security/test/test_random_bytes.hmac_sha512 b/libparc/parc/security/test/test_random_bytes.hmac_sha512
new file mode 100644
index 00000000..fcd110b2
--- /dev/null
+++ b/libparc/parc/security/test/test_random_bytes.hmac_sha512
Binary files differ
diff --git a/libparc/parc/security/test/test_random_bytes.sig b/libparc/parc/security/test/test_random_bytes.sig
new file mode 100644
index 00000000..9c395ce0
--- /dev/null
+++ b/libparc/parc/security/test/test_random_bytes.sig
Binary files differ
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
new file mode 100644
index 00000000..471c4006
--- /dev/null
+++ b/libparc/parc/security/test/test_rsa.p12
Binary files differ
diff --git a/libparc/parc/security/test/test_rsa_crt.der b/libparc/parc/security/test/test_rsa_crt.der
new file mode 100644
index 00000000..d79f4b47
--- /dev/null
+++ b/libparc/parc/security/test/test_rsa_crt.der
Binary files differ
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
new file mode 100644
index 00000000..a88e8e94
--- /dev/null
+++ b/libparc/parc/security/test/test_rsa_key.der
Binary files differ
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
new file mode 100644
index 00000000..7c931999
--- /dev/null
+++ b/libparc/parc/security/test/test_rsa_pub.der
Binary files differ
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
new file mode 100644
index 00000000..2ad3409d
--- /dev/null
+++ b/libparc/parc/security/test/test_symmetric_key.bin
Binary files differ
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