From 75a923f0ee362a039b51a141a719ce50597ca233 Mon Sep 17 00:00:00 2001 From: Devel Date: Thu, 12 Apr 2018 18:07:08 +0200 Subject: Added signature calculation and verification for ECDSA Change-Id: I946e146b9a6ae33ee294a09417e8366853faa502 Signed-off-by: Devel --- .../security/test/test_parc_Pkcs12KeyStoreECDSA.c | 470 +++++++++++++++++++++ 1 file changed, 470 insertions(+) create mode 100644 libparc/parc/security/test/test_parc_Pkcs12KeyStoreECDSA.c (limited to 'libparc/parc/security/test/test_parc_Pkcs12KeyStoreECDSA.c') 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 + +#include + +// 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 +#include +#include + +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); +} -- cgit 1.2.3-korg