diff options
author | Devel <acompagn+fdio@cisco.com> | 2018-04-12 18:07:08 +0200 |
---|---|---|
committer | Devel <acompagn+fdio@cisco.com> | 2018-04-12 18:07:08 +0200 |
commit | 75a923f0ee362a039b51a141a719ce50597ca233 (patch) | |
tree | df1b4e1d70db7fada07861dab3eb42c12edb70cb /libparc/parc/security/test | |
parent | abf52b860efb2cc0a247ab498cc962851e72c1ee (diff) |
Added signature calculation and verification for ECDSA
Change-Id: I946e146b9a6ae33ee294a09417e8366853faa502
Signed-off-by: Devel <acompagn+fdio@cisco.com>
Diffstat (limited to 'libparc/parc/security/test')
26 files changed, 1834 insertions, 48 deletions
diff --git a/libparc/parc/security/test/CMakeLists.txt b/libparc/parc/security/test/CMakeLists.txt index 189bc7ca..40a5eb70 100644 --- a/libparc/parc/security/test/CMakeLists.txt +++ b/libparc/parc/security/test/CMakeLists.txt @@ -13,17 +13,21 @@ set(TestsExpectedToPass test_parc_Identity test_parc_IdentityFile test_parc_InMemoryVerifier + test_parc_InMemoryVerifierECDSA test_parc_Key test_parc_KeyId test_parc_KeyStore test_parc_SecureRandom test_parc_Pkcs12KeyStore + test_parc_Pkcs12KeyStoreECDSA test_parc_PublicKeySigner + test_parc_PublicKeyECSigner test_parc_SymmetricKeySigner test_parc_SymmetricKeyStore test_parc_Security test_parc_Signature test_parc_Signer + test_parc_SignerEC test_parc_SigningAlgorithm test_parc_Verifier test_parc_X509Certificate @@ -46,6 +50,7 @@ set(EXTRA_DATA_FILES test_pubkey.pem test_random_bytes test_random_bytes.sig + test_random_bytes.sig_ec test_random_bytes.hmac_sha256 test_random_bytes.hmac_sha512 test_rsa.p12 @@ -58,6 +63,14 @@ set(EXTRA_DATA_FILES test_rsa_pub_sha256.bin test_symmetric_key.bin test_symmetric_key.sha256 + test_ec.p12 + test_ec_crt.der + test_ec_crt_sha256.bin + test_ec_key.der + test_ec_key.pem + test_ec_pub.der + test_ec_pub.pem + test_ec_pub_sha256.bin ) foreach(data_file ${EXTRA_DATA_FILES}) diff --git a/libparc/parc/security/test/README.keystore b/libparc/parc/security/test/README.keystore index 70227d33..0c9c3a58 100644 --- a/libparc/parc/security/test/README.keystore +++ b/libparc/parc/security/test/README.keystore @@ -33,3 +33,31 @@ openssl sha -sha256 -sign test_rsa_key.pem -out test_random_bytes.sig < test_ran # 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 + +#EC +openssl ecparam -name secp256k1 -genkey -noout -out test_ec_key.pem +openssl ec -pubout -in test_ec_key.pem -out test_ec_pub.pem +openssl req -new -key test_ec_key.pem -out test_ec.csr +openssl x509 -req -days 365 -in test_ec.csr -signkey test_ec_key.pem -out test_ec.crt +openssl pkcs12 -export -in test_ec.crt -inkey test_ec_key.pem -out test_ec.p12 -name ccnxuser -CAfile test_ec.crt -caname root -chain -passout pass:blueberry + +# saves the public key in DER form so we can calculate the sha256 of it +openssl ec -in test_ec_key.pem -outform DER -pubout -out test_ec_pub.der + +# save the private key in DER form so we can compare in code +openssl ec -in test_ec_key.pem -outform DER -out test_ec_key.der + +# computes the sha256 and saves it in binary form +openssl sha256 -out test_ec_pub_sha256.bin -sha256 -binary < test_ec_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_ec_crt.der -in test_ec.crt +openssl sha256 -out test_ec_crt_sha256.bin -sha256 -binary < test_ec_crt.der + +# To verify signing, we create a random buffer, then sign with a SHA256 digest + +openssl sha -sha256 -sign test_ec_key.pem -out test_random_bytes.sig_ec < test_random_bytes + +# the "-in test_rsa_pub_sha256.bin" is the binary digest we will sign. +openssl rsautl -sign -inkey test_ec_key.pem -in test_ec_pub_sha256.bin -out test_ec_pub_sha256.bin.sig
\ No newline at end of file diff --git a/libparc/parc/security/test/test_ec.crt b/libparc/parc/security/test/test_ec.crt new file mode 100644 index 00000000..69c446c2 --- /dev/null +++ b/libparc/parc/security/test/test_ec.crt @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBsjCCAVkCCQDTJPDkG9R7gjAKBggqhkjOPQQDAjBjMQswCQYDVQQGEwJGUjEP +MA0GA1UECAwGRnJhbmNlMRwwGgYDVQQHDBNJc3N5LWxlcy1tb3VsaW5lYXV4MRYw +FAYDVQQKDA1DaXNjbyBTeXN0ZW1zMQ0wCwYDVQQLDARDVEFPMB4XDTE4MDQxMTEw +MDYzNVoXDTE5MDQxMTEwMDYzNVowYzELMAkGA1UEBhMCRlIxDzANBgNVBAgMBkZy +YW5jZTEcMBoGA1UEBwwTSXNzeS1sZXMtbW91bGluZWF1eDEWMBQGA1UECgwNQ2lz +Y28gU3lzdGVtczENMAsGA1UECwwEQ1RBTzBWMBAGByqGSM49AgEGBSuBBAAKA0IA +BKl0iUeCpxrOueZrbZLiWMhs7PAGgNYt+x4koWPJ0wELrbs7oNIqys8mJXQM9oTw +I1b4IIgloT7/VcPanz66NgcwCgYIKoZIzj0EAwIDRwAwRAIgSc4s8ZKkEmuyV8wO +08C58dN3dxXVYdW1v1zt3lq88dwCICf64KpJok1MGSX/t/QldOiVqPtPAv6l4lq2 +9EiLK+m9 +-----END CERTIFICATE----- diff --git a/libparc/parc/security/test/test_ec.csr b/libparc/parc/security/test/test_ec.csr new file mode 100644 index 00000000..49247a4e --- /dev/null +++ b/libparc/parc/security/test/test_ec.csr @@ -0,0 +1,8 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBGzCBwgIBADBjMQswCQYDVQQGEwJGUjEPMA0GA1UECAwGRnJhbmNlMRwwGgYD +VQQHDBNJc3N5LWxlcy1tb3VsaW5lYXV4MRYwFAYDVQQKDA1DaXNjbyBTeXN0ZW1z +MQ0wCwYDVQQLDARDVEFPMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEqXSJR4KnGs65 +5mttkuJYyGzs8AaA1i37HiShY8nTAQutuzug0irKzyYldAz2hPAjVvggiCWhPv9V +w9qfPro2B6AAMAoGCCqGSM49BAMCA0gAMEUCIQCCQ5E36YNPG5LV2Q8i9flCPWk+ +4MjtioNV2I+NSf/6XgIgUjEeA54lw5dS8yqAkH8TDvw6ROe90rzBAfjsI1X2Y0k= +-----END CERTIFICATE REQUEST----- diff --git a/libparc/parc/security/test/test_ec.p12 b/libparc/parc/security/test/test_ec.p12 Binary files differnew file mode 100644 index 00000000..5fb44d05 --- /dev/null +++ b/libparc/parc/security/test/test_ec.p12 diff --git a/libparc/parc/security/test/test_ec_crt.der b/libparc/parc/security/test/test_ec_crt.der Binary files differnew file mode 100644 index 00000000..d3294e20 --- /dev/null +++ b/libparc/parc/security/test/test_ec_crt.der diff --git a/libparc/parc/security/test/test_ec_crt_sha256.bin b/libparc/parc/security/test/test_ec_crt_sha256.bin new file mode 100644 index 00000000..22d1e2c4 --- /dev/null +++ b/libparc/parc/security/test/test_ec_crt_sha256.bin @@ -0,0 +1 @@ +Ý!bL?åœ'Âkàçllýã!çT°ƒh é~ï–z~p`
\ No newline at end of file diff --git a/libparc/parc/security/test/test_ec_key.der b/libparc/parc/security/test/test_ec_key.der Binary files differnew file mode 100644 index 00000000..28fbd5a5 --- /dev/null +++ b/libparc/parc/security/test/test_ec_key.der diff --git a/libparc/parc/security/test/test_ec_key.pem b/libparc/parc/security/test/test_ec_key.pem new file mode 100644 index 00000000..6b0e1941 --- /dev/null +++ b/libparc/parc/security/test/test_ec_key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHQCAQEEIJXMLfUwhGUPNiXdmfpvWtfLzRSTL2fm9s+lTLCBGRdVoAcGBSuBBAAK +oUQDQgAEqXSJR4KnGs655mttkuJYyGzs8AaA1i37HiShY8nTAQutuzug0irKzyYl +dAz2hPAjVvggiCWhPv9Vw9qfPro2Bw== +-----END EC PRIVATE KEY----- diff --git a/libparc/parc/security/test/test_ec_pub.der b/libparc/parc/security/test/test_ec_pub.der Binary files differnew file mode 100644 index 00000000..e9150405 --- /dev/null +++ b/libparc/parc/security/test/test_ec_pub.der diff --git a/libparc/parc/security/test/test_ec_pub.pem b/libparc/parc/security/test/test_ec_pub.pem new file mode 100644 index 00000000..2ab68ff8 --- /dev/null +++ b/libparc/parc/security/test/test_ec_pub.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEqXSJR4KnGs655mttkuJYyGzs8AaA1i37 +HiShY8nTAQutuzug0irKzyYldAz2hPAjVvggiCWhPv9Vw9qfPro2Bw== +-----END PUBLIC KEY----- diff --git a/libparc/parc/security/test/test_ec_pub_sha256.bin b/libparc/parc/security/test/test_ec_pub_sha256.bin new file mode 100644 index 00000000..c0dd0fac --- /dev/null +++ b/libparc/parc/security/test/test_ec_pub_sha256.bin @@ -0,0 +1 @@ +1&,@‡‰nÈå š„t©¢-DÔ|Œ¶>%—õžz`
\ No newline at end of file diff --git a/libparc/parc/security/test/test_ec_pub_sha256.bin.sig b/libparc/parc/security/test/test_ec_pub_sha256.bin.sig Binary files differnew file mode 100644 index 00000000..787f8b3a --- /dev/null +++ b/libparc/parc/security/test/test_ec_pub_sha256.bin.sig diff --git a/libparc/parc/security/test/test_parc_CryptoSuite.c b/libparc/parc/security/test/test_parc_CryptoSuite.c index f210fd79..42007617 100755 --- a/libparc/parc/security/test/test_parc_CryptoSuite.c +++ b/libparc/parc/security/test/test_parc_CryptoSuite.c @@ -64,7 +64,7 @@ LONGBOW_TEST_CASE(Global, parcCryptoSuite_GetCryptoHash) 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"); + assertTrue(PARCCryptoHashType_SHA256 == parcCryptoSuite_GetCryptoHash(PARCCryptoSuite_ECDSA_SHA256), "Expected to be true"); } LONGBOW_TEST_CASE_EXPECTS(Global, parcCryptoSuite_GetCryptoHash_IllegalValue, .event = &LongBowTrapIllegalValue) diff --git a/libparc/parc/security/test/test_parc_Identity.c b/libparc/parc/security/test/test_parc_Identity.c index 4177cc98..3208efcb 100644 --- a/libparc/parc/security/test/test_parc_Identity.c +++ b/libparc/parc/security/test/test_parc_Identity.c @@ -162,7 +162,7 @@ LONGBOW_TEST_CASE(Global, parcIdentity_CreateSigner) assertEqualStrings(keystorePassword, parcIdentity_GetPassWord(identity)); - PARCSigner *signer = parcIdentity_CreateSigner(identity); + PARCSigner *signer = parcIdentity_CreateSigner(identity, PARCCryptoSuite_RSA_SHA256); assertNotNull(signer, "Expected non-null"); diff --git a/libparc/parc/security/test/test_parc_IdentityFile.c b/libparc/parc/security/test/test_parc_IdentityFile.c index cbc877f2..5bcc5570 100644 --- a/libparc/parc/security/test/test_parc_IdentityFile.c +++ b/libparc/parc/security/test/test_parc_IdentityFile.c @@ -176,7 +176,7 @@ LONGBOW_TEST_CASE(Global, parcIdentityFile_CreateSigner) } else { perror("getcwd() error"); } - PARCSigner *signer = parcIdentityFile_CreateSigner(identityFile); + PARCSigner *signer = parcIdentityFile_CreateSigner(identityFile, PARCCryptoSuite_RSA_SHA256); assertNotNull(signer, "Expected non-null"); diff --git a/libparc/parc/security/test/test_parc_InMemoryVerifier.c b/libparc/parc/security/test/test_parc_InMemoryVerifier.c index 1d8c9b0f..81baebc7 100755 --- a/libparc/parc/security/test/test_parc_InMemoryVerifier.c +++ b/libparc/parc/security/test/test_parc_InMemoryVerifier.c @@ -114,11 +114,11 @@ LONGBOW_TEST_FIXTURE_SETUP(Local) PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); parcPkcs12KeyStore_Release(&publicKeyStore); - PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + PARCPublicKeySigner *signer = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_RSA_SHA256); parcKeyStore_Release(&keyStore); - data->signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); - parcPublicKeySigner_Release(&publicKeySigner); + data->signer = parcSigner_Create(signer, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&signer); assertNotNull(data->signer, "Got null result from opening openssl pkcs12 file"); data->inMemoryInterface = parcInMemoryVerifier_Create(); diff --git a/libparc/parc/security/test/test_parc_InMemoryVerifierECDSA.c b/libparc/parc/security/test/test_parc_InMemoryVerifierECDSA.c new file mode 100644 index 00000000..c007c176 --- /dev/null +++ b/libparc/parc/security/test/test_parc_InMemoryVerifierECDSA.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_ECDSA); + + 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_ec.p12", "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *ecSigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_ECDSA_SHA256); + parcKeyStore_Release(&keyStore); + + data->signer = parcSigner_Create(ecSigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&ecSigner); + 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_ECDSA_SHA256); + parcKey_Release(&key); + assertTrue(success, "Should have allowed PARCCryptoSuite_ECDSA_SHA256 for an ECDSA keystore"); +} + +LONGBOW_TEST_CASE(Local, parcInMemoryVerifier_AllowedCryptoSuite_ECDSA) +{ + 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_ECDSA_SHA256); + parcKey_Release(&key); + assertTrue(success, "Should have allowed PARCCryptoSuite_ECDSA_SHA256 for an ECDSA 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_ec", O_RDONLY); + read_bytes = read(fd, scratch_buffer, 1024); + assertTrue(read_bytes <= 72, + "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_ECDSA, PARCCryptoHashType_SHA256, bb_sig); + parcBuffer_Release(&bb_sig); + parcBufferComposer_Release(&composer); + + bool success = _parcInMemoryVerifier_VerifyDigest(data->inMemoryInterface, parcKey_GetKeyId(key), localHash, PARCCryptoSuite_ECDSA_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_ec", O_RDONLY); + read_bytes = read(fd, scratch_buffer, 1024); + assertTrue(read_bytes <= 72, "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_ECDSA, + PARCCryptoHashType_SHA256, + bb_sig); + parcBuffer_Release(&bb_sig); + parcBufferComposer_Release(&composer); + + success = _parcInMemoryVerifier_VerifyDigest(data->inMemoryInterface, parcKey_GetKeyId(key), localHash, PARCCryptoSuite_ECDSA_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_ec", O_RDONLY); + read_bytes = read(fd, scratch_buffer, 1024); + assertTrue(read_bytes <= 72, "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_ECDSA_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_ec", O_RDONLY); + read_bytes = read(fd, scratch_buffer, 1024); + assertTrue(read_bytes <= 72, "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_ECDSA, + PARCCryptoHashType_SHA256, + bb_sig); + parcBuffer_Release(&bb_sig); + parcBufferComposer_Release(&composer); + + bool success = _parcInMemoryVerifier_VerifyDigest(data->inMemoryInterface, parcKey_GetKeyId(key), localHash, PARCCryptoSuite_ECDSA_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_Pkcs12KeyStore.c b/libparc/parc/security/test/test_parc_Pkcs12KeyStore.c index 1cd004cd..17a5b60f 100755 --- a/libparc/parc/security/test/test_parc_Pkcs12KeyStore.c +++ b/libparc/parc/security/test/test_parc_Pkcs12KeyStore.c @@ -109,7 +109,7 @@ LONGBOW_TEST_CASE(Global, parcPkcs12KeyStore_CreateAndOpen) const char *subject = "alice"; bool result; - result = parcPkcs12KeyStore_CreateFile(filename, password, subject, 1024, 32); + result = parcPkcs12KeyStore_CreateFile(filename, password, subject, PARCSigningAlgorithm_RSA, 1024, 32); assertTrue(result, "got error from parcPkcs12KeyStore_CreatePkcs12File"); PARCPkcs12KeyStore *keyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); @@ -128,7 +128,7 @@ LONGBOW_TEST_CASE(Global, parcPkcs12KeyStore_CreateFile_Fail) const char *subject = "alice"; bool result; - result = parcPkcs12KeyStore_CreateFile(filename, password, subject, -1, 32); + result = parcPkcs12KeyStore_CreateFile(filename, password, subject, PARCSigningAlgorithm_RSA, -1, 32); assertFalse(result, "Expected false result from parcPkcs12KeyStore_CreateFile()"); unlink(filename); @@ -170,7 +170,7 @@ LONGBOW_TEST_CASE(ccnx_internal, parcPkcs12KeyStore_GetCertificateDigest) const char *subject = "alice"; bool result; - result = parcPkcs12KeyStore_CreateFile(filename, password, subject, 1024, 32); + result = parcPkcs12KeyStore_CreateFile(filename, password, subject, PARCSigningAlgorithm_RSA, 1024, 32); assertTrue(result, "got error from parcPkcs12KeyStore_CreatePkcs12File"); PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); @@ -199,7 +199,7 @@ LONGBOW_TEST_CASE(ccnx_internal, parcPkcs12KeyStore_GetPublicKeyDigest) const char *subject = "alice"; bool result; - result = parcPkcs12KeyStore_CreateFile(filename, password, subject, 1024, 32); + result = parcPkcs12KeyStore_CreateFile(filename, password, subject, PARCSigningAlgorithm_RSA, 1024, 32); assertTrue(result, "got error from parcPkcs12KeyStore_CreatePkcs12File"); PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); @@ -225,7 +225,7 @@ LONGBOW_TEST_CASE(ccnx_internal, parcPkcs12KeyStore_GetEncodedCertificate) const char *subject = "alice"; bool result; - result = parcPkcs12KeyStore_CreateFile(filename, password, subject, 1024, 32); + result = parcPkcs12KeyStore_CreateFile(filename, password, subject, PARCSigningAlgorithm_RSA, 1024, 32); assertTrue(result, "got error from parcPkcs12KeyStore_CreatePkcs12File"); PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); @@ -255,7 +255,7 @@ LONGBOW_TEST_CASE(ccnx_internal, parcPkcs12KeyStore_GetEncodedPublicKey) const char *subject = "alice"; bool result; - result = parcPkcs12KeyStore_CreateFile(filename, password, subject, 1024, 32); + result = parcPkcs12KeyStore_CreateFile(filename, password, subject, PARCSigningAlgorithm_RSA, 1024, 32); assertTrue(result, "got error from parcPkcs12KeyStore_CreatePkcs12File"); PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open(filename, password, PARCCryptoHashType_SHA256); @@ -310,10 +310,10 @@ LONGBOW_TEST_CASE(openssl_commandline, parcPkcs12KeyStore_GetPublicKeyDigest) PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); parcPkcs12KeyStore_Release(&publicKeyStore); - PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + PARCPublicKeySigner *PublicKeySigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_RSA_SHA256); parcKeyStore_Release(&keyStore); - PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); - parcPublicKeySigner_Release(&publicKeySigner); + PARCSigner *signer = parcSigner_Create(PublicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&PublicKeySigner); assertNotNull(signer, "parcPkcs12KeyStore_Open(\"test_rsa.p12\", \"blueberry\", PARCCryptoHashType_SHA256) returned NULL"); @@ -351,10 +351,10 @@ LONGBOW_TEST_CASE(openssl_commandline, parcPkcs12KeyStore_GetCertificateDigest) PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); parcPkcs12KeyStore_Release(&publicKeyStore); - PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + PARCPublicKeySigner *PublicKeySigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_RSA_SHA256); parcKeyStore_Release(&keyStore); - PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); - parcPublicKeySigner_Release(&publicKeySigner); + PARCSigner *signer = parcSigner_Create(PublicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&PublicKeySigner); assertNotNull(signer, "Got null result from opening openssl pkcs12 file"); @@ -387,10 +387,10 @@ LONGBOW_TEST_CASE(openssl_commandline, parcPkcs12KeyStore_GetEncodedCertificate) PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); parcPkcs12KeyStore_Release(&publicKeyStore); - PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + PARCPublicKeySigner *PublicKeySigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_RSA_SHA256); parcKeyStore_Release(&keyStore); - PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); - parcPublicKeySigner_Release(&publicKeySigner); + PARCSigner *signer = parcSigner_Create(PublicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&PublicKeySigner); assertNotNull(signer, "Got null result from opening openssl pkcs12 file"); @@ -427,10 +427,10 @@ LONGBOW_TEST_CASE(openssl_commandline, parcPkcs12KeyStore_GetEncodedPublicKey) PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); parcPkcs12KeyStore_Release(&publicKeyStore); - PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + PARCPublicKeySigner *PublicKeySigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_RSA_SHA256); parcKeyStore_Release(&keyStore); - PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); - parcPublicKeySigner_Release(&publicKeySigner); + PARCSigner *signer = parcSigner_Create(PublicKeySigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&PublicKeySigner); assertNotNull(signer, "Got null result from opening openssl pkcs12 file"); diff --git a/libparc/parc/security/test/test_parc_Pkcs12KeyStoreECDSA.c b/libparc/parc/security/test/test_parc_Pkcs12KeyStoreECDSA.c new file mode 100644 index 00000000..f6b19593 --- /dev/null +++ b/libparc/parc/security/test/test_parc_Pkcs12KeyStoreECDSA.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_ec.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_ec.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, PARCSigningAlgorithm_ECDSA, 256, 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, PARCSigningAlgorithm_ECDSA, -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, PARCSigningAlgorithm_ECDSA, 256, 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, PARCSigningAlgorithm_ECDSA, 256, 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, PARCSigningAlgorithm_ECDSA, 256, 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 = 400; + 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, PARCSigningAlgorithm_ECDSA, 256, 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_ec.p12", "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *ecSigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_ECDSA_SHA256); + parcKeyStore_Release(&keyStore); + PARCSigner *signer = parcSigner_Create(ecSigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&ecSigner); + + assertNotNull(signer, "parcPkcs12KeyStore_Open(\"test_ec.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_ec_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_ec_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_ec.p12", "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *ecSigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_ECDSA_SHA256); + parcKeyStore_Release(&keyStore); + PARCSigner *signer = parcSigner_Create(ecSigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&ecSigner); + + 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_ec_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_ec_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_ec.p12", "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *ecSigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_ECDSA_SHA256); + parcKeyStore_Release(&keyStore); + PARCSigner *signer = parcSigner_Create(ecSigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&ecSigner); + + 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_ec_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_ec_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_ec.p12", "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *ecSigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_ECDSA_SHA256); + parcKeyStore_Release(&keyStore); + PARCSigner *signer = parcSigner_Create(ecSigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&ecSigner); + + 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_ec_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_ec_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_PublicKeyECSigner.c b/libparc/parc/security/test/test_parc_PublicKeyECSigner.c new file mode 100644 index 00000000..417282a0 --- /dev/null +++ b/libparc/parc/security/test/test_parc_PublicKeyECSigner.c @@ -0,0 +1,495 @@ +/* + * 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 "../parc_InMemoryVerifier.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> +#include <parc/security/parc_PublicKeySigner.h> + +typedef struct test_data { + PARCSigner *signer; + PARCInMemoryVerifier *inMemoryInterface; +} TestData; + + +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_ec.p12", "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *instance = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_ECDSA_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", PARCSigningAlgorithm_ECDSA, 256, 365); + PARCPkcs12KeyStore *keyStore = parcPkcs12KeyStore_Open(filename, "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *publicKeyStore = parcKeyStore_Create(keyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&keyStore); + PARCPublicKeySigner *pksigner = parcPublicKeySigner_Create(publicKeyStore, PARCCryptoSuite_ECDSA_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) +{ + 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_ec.p12", "blueberry", PARCCryptoHashType_SHA256); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *ecSigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_ECDSA_SHA256); + parcKeyStore_Release(&keyStore); + + data->signer = parcSigner_Create(ecSigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&ecSigner); + 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(Specialization) +{ + 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(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) +{ + TestData *data = longBowTestCase_GetClipBoardData(testCase); + + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open("test_ec.p12", "blueberry", PARCCryptoHashType_SHA256); + assertNotNull(publicKeyStore, "Got null result from opening openssl pkcs12 file"); + PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); + parcPkcs12KeyStore_Release(&publicKeyStore); + + PARCPublicKeySigner *ecSigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_ECDSA_SHA256); + parcKeyStore_Release(&keyStore); + PARCSigner *signer = parcSigner_Create(ecSigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&ecSigner); + + PARCKey *key = parcSigner_CreatePublicKey(data->signer); + _parcInMemoryVerifier_AddKey(data->inMemoryInterface, key); + + 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); + + assertTrue(read_bytes > 0, + "Buffer to sign null: %zu", + read_bytes); + + // Digest it + PARCCryptoHasher *digester = parcSigner_GetCryptoHasher(signer); + parcCryptoHasher_Init(digester); + parcCryptoHasher_UpdateBytes(digester, buffer_to_sign, read_bytes); + PARCCryptoHash *parcDigest = parcCryptoHasher_Finalize(digester); + + assertTrue(parcBuffer_Remaining(parcCryptoHash_GetDigest(parcDigest)) >0, + "Incorrect signaturedigest size: %zu", + parcBuffer_Remaining(parcCryptoHash_GetDigest(parcDigest))); + + + 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)) <= 72, + "Incorrect signature size: %zu", + parcBuffer_Remaining(parcSignature_GetSignature(bb_test_sign))); + + bool success = _parcInMemoryVerifier_VerifyDigest(data->inMemoryInterface, parcKey_GetKeyId(key), parcDigest, PARCCryptoSuite_ECDSA_SHA256, bb_test_sign); + + parcSigner_Release(&signer); + parcSignature_Release(&bb_test_sign); + parcCryptoHash_Release(&parcDigest); + parcKey_Release(&key); + + assertTrue(success, "signatures did not match"); +} + +LONGBOW_TEST_CASE(Global, parcSigner_GetCertificateDigest) +{ + char dirname[] = "pubkeystore_XXXXXX"; + char filename[MAXPATHLEN]; + const char *password = "flumox"; + unsigned key_bits = 256; + 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", PARCSigningAlgorithm_ECDSA, 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 *ecSigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_ECDSA_SHA256); + PARCSigner *signer = parcSigner_Create(ecSigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&ecSigner); + + 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 = 256; + 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", PARCSigningAlgorithm_ECDSA, 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 *ecSigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_ECDSA_SHA256); + PARCSigner *signer = parcSigner_Create(ecSigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&ecSigner); + + 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 = 256; + 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", PARCSigningAlgorithm_ECDSA, 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 *ecSigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_ECDSA_SHA256); + PARCSigner *signer = parcSigner_Create(ecSigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&ecSigner); + + 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 = 256; + 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", PARCSigningAlgorithm_ECDSA, 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 *ecSigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_ECDSA_SHA256); + PARCSigner *signer = parcSigner_Create(ecSigner, PARCPublicKeySignerAsSigner); + parcPublicKeySigner_Release(&ecSigner); + + 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_PublicKeySigner.c b/libparc/parc/security/test/test_parc_PublicKeySigner.c index 0af1aca8..49fd42c7 100644 --- a/libparc/parc/security/test/test_parc_PublicKeySigner.c +++ b/libparc/parc/security/test/test_parc_PublicKeySigner.c @@ -81,7 +81,7 @@ LONGBOW_TEST_CASE(CreateAcquireRelease, CreateRelease) PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); parcPkcs12KeyStore_Release(&publicKeyStore); - PARCPublicKeySigner *instance = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + PARCPublicKeySigner *instance = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_RSA_SHA256); parcKeyStore_Release(&keyStore); assertNotNull(instance, "Expected non-null result from parcPublicKeySigner_Create();"); @@ -125,11 +125,11 @@ _createSigner(char *path) assertNotNull(temporaryDirectory, "tmp_dirname should not be null"); sprintf(filename, "%s/%s", temporaryDirectory, path); - parcPkcs12KeyStore_CreateFile(filename, "blueberry", "person", 1024, 365); + parcPkcs12KeyStore_CreateFile(filename, "blueberry", "person", PARCSigningAlgorithm_RSA, 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); + PARCPublicKeySigner *pksigner = parcPublicKeySigner_Create(publicKeyStore, PARCCryptoSuite_RSA_SHA256); parcKeyStore_Release(&publicKeyStore); return pksigner; @@ -216,7 +216,7 @@ LONGBOW_TEST_CASE(Specialization, parcPkcs12KeyStore_SignBuffer) PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore); parcPkcs12KeyStore_Release(&publicKeyStore); - PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256); + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_RSA_SHA256); parcKeyStore_Release(&keyStore); PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); parcPublicKeySigner_Release(&publicKeySigner); @@ -276,14 +276,14 @@ LONGBOW_TEST_CASE(Global, parcSigner_GetCertificateDigest) sprintf(filename, "%s/pubkeystore.p12", tmp_dirname); // create the file - parcPkcs12KeyStore_CreateFile(filename, password, "alice", key_bits, valid_days); + parcPkcs12KeyStore_CreateFile(filename, password, "alice", PARCSigningAlgorithm_RSA, 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); + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_RSA_SHA256); PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); parcPublicKeySigner_Release(&publicKeySigner); @@ -326,14 +326,14 @@ LONGBOW_TEST_CASE(Global, parcSigner_GetDEREncodedCertificate) sprintf(filename, "%s/pubkeystore.p12", tmp_dirname); // create the file - parcPkcs12KeyStore_CreateFile(filename, password, "alice", key_bits, valid_days); + parcPkcs12KeyStore_CreateFile(filename, password, "alice", PARCSigningAlgorithm_RSA, 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); + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_RSA_SHA256); PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); parcPublicKeySigner_Release(&publicKeySigner); @@ -374,14 +374,14 @@ LONGBOW_TEST_CASE(Global, parcSigner_CreatePublicKey) sprintf(filename, "%s/pubkeystore.p12", tmp_dirname); // create the file - parcPkcs12KeyStore_CreateFile(filename, password, "alice", key_bits, valid_days); + parcPkcs12KeyStore_CreateFile(filename, password, "alice", PARCSigningAlgorithm_RSA, 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); + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_RSA_SHA256); PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); parcPublicKeySigner_Release(&publicKeySigner); @@ -408,14 +408,14 @@ LONGBOW_TEST_CASE(Global, parcSigner_CreateKeyId) sprintf(filename, "%s/pubkeystore.p12", tmp_dirname); // create the file - parcPkcs12KeyStore_CreateFile(filename, password, "alice", key_bits, valid_days); + parcPkcs12KeyStore_CreateFile(filename, password, "alice", PARCSigningAlgorithm_RSA, 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); + PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCCryptoSuite_RSA_SHA256); PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner); parcPublicKeySigner_Release(&publicKeySigner); diff --git a/libparc/parc/security/test/test_parc_Signature.c b/libparc/parc/security/test/test_parc_Signature.c index 9f54da37..4c57d5a9 100755 --- a/libparc/parc/security/test/test_parc_Signature.c +++ b/libparc/parc/security/test/test_parc_Signature.c @@ -73,7 +73,7 @@ LONGBOW_TEST_FIXTURE_TEARDOWN(Global) 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); + PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_ECDSA, PARCCryptoHashType_SHA256, bits); parcBuffer_Release(&bits); assertNotNull(signature, "Expected non-NULL PARCSignature"); @@ -88,7 +88,7 @@ LONGBOW_TEST_CASE(Global, parcSignature_Create) 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 *signature = parcSignature_Create(PARCSigningAlgorithm_ECDSA, PARCCryptoHashType_SHA256, bits); PARCSignature *handle = parcSignature_Acquire(signature); parcBuffer_Release(&bits); @@ -106,7 +106,7 @@ LONGBOW_TEST_CASE(Global, parcSignature_Acquire) 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 *signature = parcSignature_Create(PARCSigningAlgorithm_ECDSA, PARCCryptoHashType_SHA256, bits); PARCSignature *handle = parcSignature_Acquire(signature); parcBuffer_Release(&bits); @@ -129,12 +129,12 @@ LONGBOW_TEST_CASE(Global, parcSignature_Equals) 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 *x = parcSignature_Create(PARCSigningAlgorithm_ECDSA, PARCCryptoHashType_SHA256, bits); + PARCSignature *y = parcSignature_Create(PARCSigningAlgorithm_ECDSA, PARCCryptoHashType_SHA256, bits); + PARCSignature *z = parcSignature_Create(PARCSigningAlgorithm_ECDSA, 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); + PARCSignature *unequal2 = parcSignature_Create(PARCSigningAlgorithm_ECDSA, PARCCryptoHashType_CRC32C, bits); + PARCSignature *unequal3 = parcSignature_Create(PARCSigningAlgorithm_ECDSA, PARCCryptoHashType_SHA256, otherBits); parcObjectTesting_AssertEqualsFunction(parcSignature_Equals, x, y, z, unequal1, unequal2, unequal3, NULL); @@ -154,7 +154,7 @@ 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); + PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_ECDSA, expected, bits); parcBuffer_Release(&bits); PARCCryptoHashType actual = parcSignature_GetHashType(signature); @@ -167,7 +167,7 @@ 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); + PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_ECDSA, PARCCryptoHashType_SHA256, expected); PARCBuffer *actual = parcSignature_GetSignature(signature); @@ -180,7 +180,7 @@ LONGBOW_TEST_CASE(Global, parcSignature_GetSigningAlgorithm) { PARCBuffer *signatureBits = parcBuffer_Allocate(strlen("Hello")); parcBuffer_PutArray(signatureBits, strlen("Hello"), (uint8_t *) "Hello"); - PARCSigningAlgorithm expected = PARCSigningAlgorithm_DSA; + PARCSigningAlgorithm expected = PARCSigningAlgorithm_ECDSA; PARCSignature *signature = parcSignature_Create(expected, PARCCryptoHashType_SHA256, signatureBits); PARCSigningAlgorithm actual = parcSignature_GetSigningAlgorithm(signature); @@ -194,7 +194,7 @@ LONGBOW_TEST_CASE(Global, parcSignature_ToString) { PARCBuffer *signatureBits = parcBuffer_Allocate(strlen("Hello")); parcBuffer_PutArray(signatureBits, strlen("Hello"), (uint8_t *) "Hello"); - PARCSigningAlgorithm expected = PARCSigningAlgorithm_DSA; + PARCSigningAlgorithm expected = PARCSigningAlgorithm_ECDSA; PARCSignature *signature = parcSignature_Create(expected, PARCCryptoHashType_SHA256, signatureBits); char *string = parcSignature_ToString(signature); diff --git a/libparc/parc/security/test/test_parc_SignerEC.c b/libparc/parc/security/test/test_parc_SignerEC.c new file mode 100644 index 00000000..2b6fc577 --- /dev/null +++ b/libparc/parc/security/test/test_parc_SignerEC.c @@ -0,0 +1,312 @@ +/* + * 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_ECDSA, PARCCryptoHashType_SHA256, buffer); + parcBuffer_Release(&buffer); + return signature; +} + +static PARCSigningAlgorithm +_GetSigningAlgorithm(PARCSigner *interfaceContext) +{ + return PARCSigningAlgorithm_ECDSA; +} + +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() +{ + const char *filename = "/tmp/test_ecdsa.p12"; + const char *password = "12345"; + const char *subject = "alice"; + _MockSigner *signer = parcObject_CreateInstance(_MockSigner); + + signer->hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256); + + bool res = parcPkcs12KeyStore_CreateFile(filename, password, subject, PARCSigningAlgorithm_ECDSA, 256, 180); + assertTrue(res, "Unable to create an ECDSA key"); + + PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open("test_ec.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_ECDSA == alg, "Expected PARCSigningAlgorithm_ECDSA 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_X509Certificate.c b/libparc/parc/security/test/test_parc_X509Certificate.c index 3ddb8220..dda9a9ff 100755 --- a/libparc/parc/security/test/test_parc_X509Certificate.c +++ b/libparc/parc/security/test/test_parc_X509Certificate.c @@ -53,6 +53,8 @@ LONGBOW_TEST_FIXTURE(Global) 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_RUN_TEST_CASE(Global, parc_X509Certificate_CreateSelfSignedCertificate_RSA); + LONGBOW_RUN_TEST_CASE(Global, parc_X509Certificate_CreateSelfSignedCertificate_EC); } LONGBOW_TEST_FIXTURE_SETUP(Global) @@ -98,6 +100,24 @@ LONGBOW_TEST_CASE(Global, parc_X509Certificate_Create) assertNull(certificate, "Expected NULL certificate with non-existent file"); } +LONGBOW_TEST_CASE(Global, parc_X509Certificate_CreateSelfSignedCertificate_EC) +{ + PARCBuffer *privateKeyBuffer = NULL; + PARCX509Certificate *certificate = _createSelfSignedCertificate_EC(&privateKeyBuffer, "TEST", 256, 180); + assertNotNull(certificate, "Expected non-NULL EC certificate"); + parcBuffer_Release(&privateKeyBuffer); + parcX509Certificate_Release(&certificate); +} + +LONGBOW_TEST_CASE(Global, parc_X509Certificate_CreateSelfSignedCertificate_RSA) +{ + PARCBuffer *privateKeyBuffer = NULL; + PARCX509Certificate *certificate = _createSelfSignedCertificate_RSA(&privateKeyBuffer, "TEST", 1024, 180); + assertNotNull(certificate, "Expected non-NULL RSA certificate"); + parcBuffer_Release(&privateKeyBuffer); + parcX509Certificate_Release(&certificate); +} + LONGBOW_TEST_CASE(Global, parc_X509Certificate_CreateFromDERBuffer) { char *fileName = "test.pem"; diff --git a/libparc/parc/security/test/test_random_bytes.sig_ec b/libparc/parc/security/test/test_random_bytes.sig_ec Binary files differnew file mode 100644 index 00000000..92b210a1 --- /dev/null +++ b/libparc/parc/security/test/test_random_bytes.sig_ec |