aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDevel <acompagn+fdio@cisco.com>2018-04-12 18:07:08 +0200
committerDevel <acompagn+fdio@cisco.com>2018-04-12 18:07:08 +0200
commit75a923f0ee362a039b51a141a719ce50597ca233 (patch)
treedf1b4e1d70db7fada07861dab3eb42c12edb70cb
parentabf52b860efb2cc0a247ab498cc962851e72c1ee (diff)
Added signature calculation and verification for ECDSA
Change-Id: I946e146b9a6ae33ee294a09417e8366853faa502 Signed-off-by: Devel <acompagn+fdio@cisco.com>
-rw-r--r--libparc/parc/security/command-line/parc-publickey.c11
-rw-r--r--libparc/parc/security/parc_CertificateFactory.c14
-rwxr-xr-xlibparc/parc/security/parc_CertificateFactory.h2
-rwxr-xr-xlibparc/parc/security/parc_CryptoSuite.c51
-rwxr-xr-xlibparc/parc/security/parc_CryptoSuite.h37
-rwxr-xr-xlibparc/parc/security/parc_Identity.c4
-rwxr-xr-xlibparc/parc/security/parc_Identity.h5
-rw-r--r--libparc/parc/security/parc_IdentityFile.c11
-rw-r--r--libparc/parc/security/parc_IdentityFile.h2
-rw-r--r--libparc/parc/security/parc_InMemoryVerifier.c82
-rwxr-xr-xlibparc/parc/security/parc_InMemoryVerifier.h1
-rwxr-xr-xlibparc/parc/security/parc_Key.c1
-rwxr-xr-xlibparc/parc/security/parc_KeyStore.c9
-rwxr-xr-xlibparc/parc/security/parc_KeyStore.h30
-rw-r--r--libparc/parc/security/parc_KeyType.c56
-rw-r--r--libparc/parc/security/parc_KeyType.h66
-rw-r--r--libparc/parc/security/parc_Pkcs12KeyStore.c136
-rw-r--r--libparc/parc/security/parc_Pkcs12KeyStore.h20
-rw-r--r--libparc/parc/security/parc_PublicKeySigner.c96
-rw-r--r--libparc/parc/security/parc_PublicKeySigner.h2
-rwxr-xr-xlibparc/parc/security/parc_Signer.h24
-rwxr-xr-xlibparc/parc/security/parc_SigningAlgorithm.c3
-rw-r--r--libparc/parc/security/parc_SigningAlgorithm.h3
-rw-r--r--libparc/parc/security/parc_X509Certificate.c253
-rwxr-xr-xlibparc/parc/security/parc_X509Certificate.h5
-rw-r--r--libparc/parc/security/test/CMakeLists.txt13
-rw-r--r--libparc/parc/security/test/README.keystore28
-rw-r--r--libparc/parc/security/test/test_ec.crt12
-rw-r--r--libparc/parc/security/test/test_ec.csr8
-rw-r--r--libparc/parc/security/test/test_ec.p12bin0 -> 1011 bytes
-rw-r--r--libparc/parc/security/test/test_ec_crt.derbin0 -> 438 bytes
-rw-r--r--libparc/parc/security/test/test_ec_crt_sha256.bin1
-rw-r--r--libparc/parc/security/test/test_ec_key.derbin0 -> 118 bytes
-rw-r--r--libparc/parc/security/test/test_ec_key.pem5
-rw-r--r--libparc/parc/security/test/test_ec_pub.derbin0 -> 88 bytes
-rw-r--r--libparc/parc/security/test/test_ec_pub.pem4
-rw-r--r--libparc/parc/security/test/test_ec_pub_sha256.bin1
-rw-r--r--libparc/parc/security/test/test_ec_pub_sha256.bin.sigbin0 -> 70 bytes
-rwxr-xr-xlibparc/parc/security/test/test_parc_CryptoSuite.c2
-rw-r--r--libparc/parc/security/test/test_parc_Identity.c2
-rw-r--r--libparc/parc/security/test/test_parc_IdentityFile.c2
-rwxr-xr-xlibparc/parc/security/test/test_parc_InMemoryVerifier.c6
-rw-r--r--libparc/parc/security/test/test_parc_InMemoryVerifierECDSA.c417
-rwxr-xr-xlibparc/parc/security/test/test_parc_Pkcs12KeyStore.c36
-rw-r--r--libparc/parc/security/test/test_parc_Pkcs12KeyStoreECDSA.c470
-rw-r--r--libparc/parc/security/test/test_parc_PublicKeyECSigner.c495
-rw-r--r--libparc/parc/security/test/test_parc_PublicKeySigner.c24
-rwxr-xr-xlibparc/parc/security/test/test_parc_Signature.c24
-rw-r--r--libparc/parc/security/test/test_parc_SignerEC.c312
-rwxr-xr-xlibparc/parc/security/test/test_parc_X509Certificate.c20
-rw-r--r--libparc/parc/security/test/test_random_bytes.sig_ecbin0 -> 71 bytes
51 files changed, 2597 insertions, 209 deletions
diff --git a/libparc/parc/security/command-line/parc-publickey.c b/libparc/parc/security/command-line/parc-publickey.c
index 30733113..e88e94b6 100644
--- a/libparc/parc/security/command-line/parc-publickey.c
+++ b/libparc/parc/security/command-line/parc-publickey.c
@@ -36,16 +36,17 @@ parcPublicKey_Create(PARCArrayList *args)
char *fileName = parcArrayList_Get(args, 2);
char *password = parcArrayList_Get(args, 3);
char *subjectName = parcArrayList_Get(args, 4);
-
+ PARCSigningAlgorithm signAlgo = *(int *)parcArrayList_Get(args, 5);
+
if (parcArrayList_Size(args) > 5) {
- keyLength = (unsigned int) strtoul(parcArrayList_Get(args, 5), NULL, 10);
+ keyLength = (unsigned int) strtoul(parcArrayList_Get(args, 6), NULL, 10);
}
if (parcArrayList_Size(args) > 6) {
- validityDays = (unsigned int) strtoul(parcArrayList_Get(args, 6), NULL, 10);
+ validityDays = (unsigned int) strtoul(parcArrayList_Get(args, 7), NULL, 10);
}
- bool result = parcPkcs12KeyStore_CreateFile(fileName, password, subjectName, keyLength, validityDays);
+ bool result = parcPkcs12KeyStore_CreateFile(fileName, password, subjectName, keyLength, validityDays, signAlgo);
if (!result) {
printf("Error: %s %s", fileName, strerror(errno));
return;
@@ -62,7 +63,7 @@ parcPublicKey_Validate(PARCArrayList *args)
PARCPkcs12KeyStore *keyStore = parcPkcs12KeyStore_Open(fileName, password, PARCCryptoHashType_SHA256);
PARCKeyStore *publicKeyStore = parcKeyStore_Create(keyStore, PARCPkcs12KeyStoreAsKeyStore);
- PARCPublicKeySigner *signer = parcPublicKeySigner_Create(publicKeyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256);
+ PARCPublicKeySigner *signer = parcPublicKeySigner_Create(publicKeyStore, PARCCryptoSuite_RSA_SHA256);
PARCSigner *pkSigner = parcSigner_Create(signer, PARCPublicKeySignerAsSigner);
parcKeyStore_Release(&publicKeyStore);
diff --git a/libparc/parc/security/parc_CertificateFactory.c b/libparc/parc/security/parc_CertificateFactory.c
index 3825ae04..3a758c53 100644
--- a/libparc/parc/security/parc_CertificateFactory.c
+++ b/libparc/parc/security/parc_CertificateFactory.c
@@ -78,10 +78,20 @@ parcCertificateFactory_CreateCertificateFromBuffer(PARCCertificateFactory *facto
PARCCertificate *
parcCertificateFactory_CreateSelfSignedCertificate(PARCCertificateFactory *factory, PARCBuffer **privateKey,
- char *subjectName, size_t keyLength, size_t valdityDays)
+ char *subjectName, PARCSigningAlgorithm signAlgo,
+ size_t keyLength, size_t valdityDays)
{
if (factory->type == PARCCertificateType_X509 && factory->encoding == PARCContainerEncoding_DER) {
- PARCX509Certificate *certificate = parcX509Certificate_CreateSelfSignedCertificate(privateKey, subjectName, (int) keyLength, valdityDays);
+ PARCX509Certificate *certificate = NULL;
+ switch (signAlgo)
+ {
+ case PARCSigningAlgorithm_RSA:
+ certificate = parcX509Certificate_CreateSelfSignedCertificate(privateKey, subjectName, (int) keyLength, valdityDays, PARCKeyType_RSA);
+ break;
+ case PARCSigningAlgorithm_ECDSA:
+ certificate = parcX509Certificate_CreateSelfSignedCertificate(privateKey, subjectName, (int) keyLength, valdityDays, PARCKeyType_EC);
+ break;
+ }
// This may fail.
if (certificate == NULL) {
diff --git a/libparc/parc/security/parc_CertificateFactory.h b/libparc/parc/security/parc_CertificateFactory.h
index 5f49ac23..de034d1b 100755
--- a/libparc/parc/security/parc_CertificateFactory.h
+++ b/libparc/parc/security/parc_CertificateFactory.h
@@ -114,7 +114,7 @@ PARCCertificate *parcCertificateFactory_CreateCertificateFromBuffer(PARCCertific
* }
* @endcode
*/
-PARCCertificate *parcCertificateFactory_CreateSelfSignedCertificate(PARCCertificateFactory *factort, PARCBuffer **privateKey, char *subjectName, size_t keyLength, size_t valdityDays);
+PARCCertificate *parcCertificateFactory_CreateSelfSignedCertificate(PARCCertificateFactory *factort, PARCBuffer **privateKey, char *subjectName, PARCSigningAlgorithm signAlgo, size_t keyLength, size_t valdityDays);
/**
* Increase the number of references to a `PARCCertificateFactory` instance.
diff --git a/libparc/parc/security/parc_CryptoSuite.c b/libparc/parc/security/parc_CryptoSuite.c
index 9f4506e7..c807f9aa 100755
--- a/libparc/parc/security/parc_CryptoSuite.c
+++ b/libparc/parc/security/parc_CryptoSuite.c
@@ -28,7 +28,7 @@ parcCryptoSuite_GetCryptoHash(PARCCryptoSuite suite)
case PARCCryptoSuite_DSA_SHA256: // fallthrough
case PARCCryptoSuite_HMAC_SHA256: // fallthrough
case PARCCryptoSuite_RSA_SHA256: // fallthrough
- case PARCCryptoSuite_EC_SECP_256K1:
+ case PARCCryptoSuite_ECDSA_SHA256:
return PARCCryptoHashType_SHA256;
case PARCCryptoSuite_HMAC_SHA512: // fallthrough
@@ -42,3 +42,52 @@ parcCryptoSuite_GetCryptoHash(PARCCryptoSuite suite)
trapIllegalValue(suite, "Unknown crypto suite: %d", suite);
}
}
+
+int
+parcCryptoSuite_GetSignatureSizeBits(PARCCryptoSuite suite, int keyLengthBits)
+{
+ switch (suite) {
+ case PARCCryptoSuite_DSA_SHA256: // fallthrough
+ case PARCCryptoSuite_RSA_SHA256: // fallthrough
+ case PARCCryptoSuite_RSA_SHA512:
+ return keyLengthBits;
+
+ case PARCCryptoSuite_ECDSA_SHA256:
+ return keyLengthBits*2 + 64; //Overhead added by ECDSA
+
+ case PARCCryptoSuite_HMAC_SHA256: // fallthrough
+ case PARCCryptoSuite_HMAC_SHA512: // fallthrough
+ return 512;
+
+ case PARCCryptoSuite_NULL_CRC32C:
+ return 32;
+
+ default:
+ trapIllegalValue(suite, "Unknown crypto suite: %d", suite);
+ }
+}
+
+int
+parcCryptoSuite_GetSignatureSizeBytes(PARCCryptoSuite suite, int keyLengthBits)
+{
+ int keyLengthBytes = keyLengthBits >> 3;
+ switch (suite) {
+ case PARCCryptoSuite_DSA_SHA256: // fallthrough
+ case PARCCryptoSuite_RSA_SHA256: // fallthrough
+ case PARCCryptoSuite_RSA_SHA512:
+ return keyLengthBytes;
+
+ case PARCCryptoSuite_ECDSA_SHA256:
+ return keyLengthBytes*2 + 8; //Overhead added by ECDSA
+
+ case PARCCryptoSuite_HMAC_SHA256: // fallthrough
+ case PARCCryptoSuite_HMAC_SHA512: // fallthrough
+ return 64;
+
+ case PARCCryptoSuite_NULL_CRC32C:
+ return 4;
+
+ default:
+ trapIllegalValue(suite, "Unknown crypto suite: %d", suite);
+ }
+}
diff --git a/libparc/parc/security/parc_CryptoSuite.h b/libparc/parc/security/parc_CryptoSuite.h
index b9c138e2..a8e07f02 100755
--- a/libparc/parc/security/parc_CryptoSuite.h
+++ b/libparc/parc/security/parc_CryptoSuite.h
@@ -36,7 +36,7 @@ typedef enum {
PARCCryptoSuite_HMAC_SHA256,
PARCCryptoSuite_HMAC_SHA512,
PARCCryptoSuite_NULL_CRC32C,
- PARCCryptoSuite_EC_SECP_256K1,
+ PARCCryptoSuite_ECDSA_SHA256,
PARCCryptoSuite_UNKNOWN
} PARCCryptoSuite;
@@ -55,4 +55,39 @@ typedef enum {
* @endcode
*/
PARCCryptoHashType parcCryptoSuite_GetCryptoHash(PARCCryptoSuite suite);
+
+/**
+ * Given a PARCCryptoSuite value and the key length, return the expected length in bits of the signature.
+ * For ECDSA the result is the maximum length
+ *
+ * @param [in] suite A PARCCryptoSuite value.
+ *
+ * @return A PARCCryptoHashType value
+ *
+ * Example:
+ * @code
+ * {
+ * int bits = parcCryptoSuite_GetSignatureSizeBits(PARCCryptoSuite_RSA_SHA256, 1024);
+ * }
+ * @endcode
+ */
+int parcCryptoSuite_GetSignatureSizeBits(PARCCryptoSuite suite, int keyLengthBits);
+
+/**
+ * Given a PARCCryptoSuite value and the key length, return the expected length in bytes of the signature.
+ * For ECDSA the result is the maximum length
+ *
+ * @param [in] suite A PARCCryptoSuite value.
+ *
+ * @return A PARCCryptoHashType value
+ *
+ * Example:
+ * @code
+ * {
+ * int bytes = parcCryptoSuite_GetSignatureSizeBits(PARCCryptoSuite_RSA_SHA256, 1024);
+ * }
+ * @endcode
+ */
+int parcCryptoSuite_GetSignatureSizeBytes(PARCCryptoSuite suite, int keyLengthBits);
+
#endif // libparc_parc_CryptoSuite_h
diff --git a/libparc/parc/security/parc_Identity.c b/libparc/parc/security/parc_Identity.c
index 0afef9f7..a132964a 100755
--- a/libparc/parc/security/parc_Identity.c
+++ b/libparc/parc/security/parc_Identity.c
@@ -99,9 +99,9 @@ parcIdentity_GetPassWord(const PARCIdentity *identity)
}
PARCSigner *
-parcIdentity_CreateSigner(const PARCIdentity *identity)
+parcIdentity_CreateSigner(const PARCIdentity *identity, PARCCryptoSuite suite)
{
- return identity->interface->GetSigner(identity->instance);
+ return identity->interface->GetSigner(identity->instance, suite);
}
void
diff --git a/libparc/parc/security/parc_Identity.h b/libparc/parc/security/parc_Identity.h
index d581b97d..32b9b179 100755
--- a/libparc/parc/security/parc_Identity.h
+++ b/libparc/parc/security/parc_Identity.h
@@ -45,6 +45,7 @@
#include <parc/algol/parc_Object.h>
#include <parc/security/parc_Signer.h>
+#include <parc/security/parc_CryptoSuite.h>
struct parc_identity;
typedef struct parc_identity PARCIdentity;
@@ -73,7 +74,7 @@ typedef struct parc_identity_interface {
/**
* @see parcIdentity_CreateSigner
*/
- PARCSigner *(*GetSigner)(const void *identity);
+ PARCSigner *(*GetSigner)(const void *identity, PARCCryptoSuite suite);
/**
* @see parcIdentity_Equals
@@ -278,7 +279,7 @@ const char *parcIdentity_GetPassWord(const PARCIdentity *identity);
* }
* @endcode
*/
-PARCSigner *parcIdentity_CreateSigner(const PARCIdentity *identity);
+PARCSigner *parcIdentity_CreateSigner(const PARCIdentity *identity, PARCCryptoSuite suite);
/**
* Determine if two PARCIdentity are equal.
diff --git a/libparc/parc/security/parc_IdentityFile.c b/libparc/parc/security/parc_IdentityFile.c
index f5f6d067..972c8d05 100644
--- a/libparc/parc/security/parc_IdentityFile.c
+++ b/libparc/parc/security/parc_IdentityFile.c
@@ -42,7 +42,7 @@ PARCIdentityInterface *PARCIdentityFileAsPARCIdentity = &(PARCIdentityInterface)
.Release = (void (*)(void **))parcIdentityFile_Release,
.GetPassWord = (void *(*)(const void *))parcIdentityFile_GetPassWord,
.GetFileName = (void *(*)(const void *))parcIdentityFile_GetFileName,
- .GetSigner = (PARCSigner * (*)(const void *))parcIdentityFile_CreateSigner,
+ .GetSigner = (PARCSigner * (*)(const void *, PARCCryptoSuite))parcIdentityFile_CreateSigner,
.Equals = (bool (*)(const void *, const void *))parcIdentityFile_Equals,
.Display = (void (*)(const void *, size_t))parcIdentityFile_Display
};
@@ -104,13 +104,18 @@ parcIdentityFile_GetPassWord(const PARCIdentityFile *identity)
}
PARCSigner *
-parcIdentityFile_CreateSigner(const PARCIdentityFile *identity)
+parcIdentityFile_CreateSigner(const PARCIdentityFile *identity, PARCCryptoSuite suite)
{
PARCPkcs12KeyStore *keyStore = parcPkcs12KeyStore_Open(identity->fileName, identity->passWord, PARCCryptoHashType_SHA256);
PARCKeyStore *publicKeyStore = parcKeyStore_Create(keyStore, PARCPkcs12KeyStoreAsKeyStore);
parcPkcs12KeyStore_Release(&keyStore);
- PARCPublicKeySigner *signer = parcPublicKeySigner_Create(publicKeyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256);
+ PARCSigningAlgorithm signAlgo = parcKeyStore_getSigningAlgorithm(publicKeyStore);
+
+ if (signAlgo != parcSigningAlgorithm_GetSigningAlgorithm(suite))
+ return NULL;
+
+ PARCPublicKeySigner *signer = parcPublicKeySigner_Create(publicKeyStore, suite);
PARCSigner *pkSigner = parcSigner_Create(signer, PARCPublicKeySignerAsSigner);
parcPublicKeySigner_Release(&signer);
parcKeyStore_Release(&publicKeyStore);
diff --git a/libparc/parc/security/parc_IdentityFile.h b/libparc/parc/security/parc_IdentityFile.h
index c5ee4ac5..c125ffb2 100644
--- a/libparc/parc/security/parc_IdentityFile.h
+++ b/libparc/parc/security/parc_IdentityFile.h
@@ -205,7 +205,7 @@ const char *parcIdentityFile_GetPassWord(const PARCIdentityFile *identity);
* }
* @endcode
*/
-PARCSigner *parcIdentityFile_CreateSigner(const PARCIdentityFile *identity);
+PARCSigner *parcIdentityFile_CreateSigner(const PARCIdentityFile *identity, PARCCryptoSuite suite);
/**
* Determine if two PARCIdentityFiles are equal.
diff --git a/libparc/parc/security/parc_InMemoryVerifier.c b/libparc/parc/security/parc_InMemoryVerifier.c
index e5a9ba06..e5946d33 100644
--- a/libparc/parc/security/parc_InMemoryVerifier.c
+++ b/libparc/parc/security/parc_InMemoryVerifier.c
@@ -34,6 +34,8 @@
#include <parc/algol/parc_Memory.h>
#include <openssl/x509v3.h>
+#include <openssl/ecdsa.h>
+
struct parc_inmemory_verifier {
PARCCryptoHasher *hasher_sha256;
@@ -124,6 +126,17 @@ _parcInMemoryVerifier_AllowedCryptoSuite(void *interfaceContext, PARCKeyId *keyi
}
break;
+ case PARCSigningAlgorithm_ECDSA:
+ switch (suite) {
+ case PARCCryptoSuite_ECDSA_SHA256:
+ return true;
+
+ default:
+ return false;
+ }
+ break;
+
+
case PARCSigningAlgorithm_DSA:
switch (suite) {
default:
@@ -152,6 +165,8 @@ _parcInMemoryVerifier_AllowedCryptoSuite(void *interfaceContext, PARCKeyId *keyi
static bool _parcInMemoryVerifier_RSAKey_Verify(PARCInMemoryVerifier *verifier, PARCCryptoHash *localHash,
PARCSignature *signatureToVerify, PARCBuffer *derEncodedKey);
+static bool _parcInMemoryVerifier_ECDSAKey_Verify(PARCInMemoryVerifier *verifier, PARCCryptoHash *localHash,
+ PARCSignature *signatureToVerify, PARCBuffer *derEncodedKey);
/**
* The signature verifies if:
* 0) we know the key for keyid
@@ -195,6 +210,9 @@ _parcInMemoryVerifier_VerifyDigest(void *interfaceContext, PARCKeyId *keyid, PAR
case PARCSigningAlgorithm_RSA:
return _parcInMemoryVerifier_RSAKey_Verify(verifier, locallyComputedHash, objectSignature, parcKey_GetKey(key));
+ case PARCSigningAlgorithm_ECDSA:
+ return _parcInMemoryVerifier_ECDSAKey_Verify(verifier, locallyComputedHash, objectSignature, parcKey_GetKey(key));
+
case PARCSigningAlgorithm_DSA:
trapNotImplemented("DSA not supported");
break;
@@ -295,7 +313,69 @@ _parcInMemoryVerifier_RSAKey_Verify(PARCInMemoryVerifier *verifier, PARCCryptoHa
}
EVP_PKEY_free(unwrapped_key);
- if (success) {
+ if (success == 1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Return if the signature and key verify with the local hash.
+ *
+ * PRECONDITION:
+ * - You know the signature and key are ECDSA.
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+static bool
+_parcInMemoryVerifier_ECDSAKey_Verify(PARCInMemoryVerifier *verifier, PARCCryptoHash *localHash,
+ PARCSignature *signatureToVerify, PARCBuffer *derEncodedKey)
+{
+ const uint8_t *der_bytes = parcByteArray_Array(parcBuffer_Array(derEncodedKey));
+
+ long der_length = parcBuffer_Remaining(derEncodedKey);
+ EVP_PKEY *unwrapped_key = d2i_PUBKEY(NULL, &der_bytes, der_length);
+
+ if (unwrapped_key != NULL) {
+ int success = 0;
+ EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(unwrapped_key);
+
+ if (ec_key != NULL) {
+ int openssl_digest_type;
+
+ switch (parcCryptoHash_GetDigestType(localHash)) {
+ case PARCCryptoHashType_SHA256:
+ openssl_digest_type = NID_sha256;
+ break;
+ case PARCCryptoHashType_SHA512:
+ openssl_digest_type = NID_sha512;
+ break;
+ default:
+ trapUnexpectedState("Unknown digest type: %s",
+ parcCryptoHashType_ToString(parcCryptoHash_GetDigestType(localHash)));
+ }
+
+ PARCBuffer *sigbits = parcSignature_GetSignature(signatureToVerify);
+ PARCByteArray *bytearray = parcBuffer_Array(sigbits);
+ unsigned signatureLength = (unsigned) parcBuffer_Remaining(sigbits);
+ uint8_t *sigbuffer = parcByteArray_Array(bytearray);
+ size_t signatureOffset = parcBuffer_ArrayOffset(sigbits);
+
+ success = ECDSA_verify(openssl_digest_type,
+ (unsigned char *) parcByteArray_Array(parcBuffer_Array(parcCryptoHash_GetDigest(localHash))),
+ (unsigned) parcBuffer_Remaining(parcCryptoHash_GetDigest(localHash)),
+ sigbuffer + signatureOffset,
+ signatureLength,
+ ec_key);
+ EC_KEY_free(ec_key);
+ }
+ EVP_PKEY_free(unwrapped_key);
+
+ if (success == 1) {
return true;
}
}
diff --git a/libparc/parc/security/parc_InMemoryVerifier.h b/libparc/parc/security/parc_InMemoryVerifier.h
index d9f1cf98..bbec8130 100755
--- a/libparc/parc/security/parc_InMemoryVerifier.h
+++ b/libparc/parc/security/parc_InMemoryVerifier.h
@@ -27,6 +27,7 @@
struct parc_inmemory_verifier;
typedef struct parc_inmemory_verifier PARCInMemoryVerifier;
+
extern PARCVerifierInterface *PARCInMemoryVerifierAsVerifier;
/**
* Create an empty verifier. It's destroyed via the PARCVerifierInterface->Destroy call.
diff --git a/libparc/parc/security/parc_Key.c b/libparc/parc/security/parc_Key.c
index 06b85420..3802549e 100755
--- a/libparc/parc/security/parc_Key.c
+++ b/libparc/parc/security/parc_Key.c
@@ -69,6 +69,7 @@ parcKey_CreateFromDerEncodedPublicKey(PARCKeyId *keyid, PARCSigningAlgorithm sig
switch (signingAlg) {
case PARCSigningAlgorithm_RSA: // fallthrough
case PARCSigningAlgorithm_DSA:
+ case PARCSigningAlgorithm_ECDSA:
break;
default:
diff --git a/libparc/parc/security/parc_KeyStore.c b/libparc/parc/security/parc_KeyStore.c
index 912861d1..00fac015 100755
--- a/libparc/parc/security/parc_KeyStore.c
+++ b/libparc/parc/security/parc_KeyStore.c
@@ -102,3 +102,12 @@ parcKeyStore_GetDEREncodedPrivateKey(const PARCKeyStore *interfaceContext)
}
return NULL;
}
+
+PARCSigningAlgorithm
+parcKeyStore_getSigningAlgorithm(const PARCKeyStore *interfaceContext)
+{
+ if (interfaceContext->interface != NULL) {
+ return interfaceContext->interface->getSigningAlgorithm(interfaceContext->instance);
+ }
+ return PARCSigningAlgortihm_NULL;
+}
diff --git a/libparc/parc/security/parc_KeyStore.h b/libparc/parc/security/parc_KeyStore.h
index 03be78af..253505d5 100755
--- a/libparc/parc/security/parc_KeyStore.h
+++ b/libparc/parc/security/parc_KeyStore.h
@@ -30,6 +30,7 @@
#include <parc/algol/parc_Object.h>
#include <parc/algol/parc_Buffer.h>
#include <parc/security/parc_CryptoHash.h>
+#include <parc/security/parc_SigningAlgorithm.h>
struct parc_key_store;
typedef struct parc_key_store PARCKeyStore;
@@ -105,6 +106,15 @@ typedef PARCBuffer *(PARCKeyStoreGetDEREncodedPublicKey)(const void *interfaceCo
*/
typedef PARCBuffer *(PARCKeyStoreGetDEREncodedPrivateKey)(const void *interfaceContext);
+/**
+ * Returns the signing algorithm from the key type store in the keystore
+ *
+ *
+ * @param [in] interfaceContextPtr A pointer to a concrete PARCKeyStore instance.
+ *
+ * @return A pointer to a PARCBuffer containing the encoded private key.
+ */
+typedef PARCSigningAlgorithm (PARCKeyStoreGetSigningAlgorithm)(const void *interfaceContext);
typedef struct parc_keystore_interface {
/**
@@ -177,6 +187,16 @@ typedef struct parc_keystore_interface {
* @return A pointer to a PARCBuffer containing the encoded private key.
*/
PARCKeyStoreGetDEREncodedPrivateKey *getDEREncodedPrivateKey;
+
+ /**
+ * Returns the signing algorithm from the key type store in the keystore
+ *
+ *
+ * @param [in] interfaceContextPtr A pointer to a concrete PARCKeyStore instance.
+ *
+ * @return A pointer to a PARCBuffer containing the encoded private key.
+ */
+ PARCKeyStoreGetSigningAlgorithm *getSigningAlgorithm;
} PARCKeyStoreInterface;
/**
@@ -345,4 +365,14 @@ PARCBuffer *parcKeyStore_GetDEREncodedPublicKey(const PARCKeyStore *interfaceCon
* @endcode
*/
PARCBuffer *parcKeyStore_GetDEREncodedPrivateKey(const PARCKeyStore *interfaceContext);
+
+/**
+ * Returns the signing algorithm from the key type store in the keystore
+ *
+ *
+ * @param [in] interfaceContextPtr A pointer to a concrete PARCKeyStore instance.
+ *
+ * @return A pointer to a PARCBuffer containing the encoded private key.
+ */
+PARCSigningAlgorithm parcKeyStore_getSigningAlgorithm(const PARCKeyStore *interfaceContext);
#endif // libparc_parc_KeyStore_h
diff --git a/libparc/parc/security/parc_KeyType.c b/libparc/parc/security/parc_KeyType.c
new file mode 100644
index 00000000..62fc0000
--- /dev/null
+++ b/libparc/parc/security/parc_KeyType.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <LongBow/runtime.h>
+
+#include <parc/security/parc_KeyType.h>
+
+static struct {
+ PARCKeyType type;
+ char *name;
+} _keyType_ToString[] = {
+ { PARCKeyType_RSA, "PARCKeyType_RSA" },
+ { PARCKeyType_EC, "PARCKeyType_EC" },
+ { 0, NULL }
+};
+
+const char *
+parcKeyType_ToString(PARCKeyType type)
+{
+ for (int i = 0; _keyType_ToString[i].name != NULL; i++) {
+ if (_keyType_ToString[i].type == type) {
+ return _keyType_ToString[i].name;
+ }
+ }
+ return NULL;
+}
+
+PARCKeyType
+parcKeyType_FromString(const char *name)
+{
+ for (int i = 0; _keyType_ToString[i].name != NULL; i++) {
+ if (strcmp(_keyType_ToString[i].name, name) == 0) {
+ return _keyType_ToString[i].type;
+ }
+ }
+ return PARCKeyType_Invalid;
+}
diff --git a/libparc/parc/security/parc_KeyType.h b/libparc/parc/security/parc_KeyType.h
new file mode 100644
index 00000000..92d58ed4
--- /dev/null
+++ b/libparc/parc/security/parc_KeyType.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file parc_KeyType.h
+ * @ingroup security
+ * @brief A type specifying a key.
+ *
+ */
+#ifndef libparc_parc_KeyType_h
+#define libparc_parc_KeyType_h
+
+typedef enum {
+ PARCKeyType_RSA,
+ PARCKeyType_EC,
+ PARCKeyType_Invalid
+} PARCKeyType;
+
+/**
+ * Convert the `PARCKeyType` value to a human-readable string representation.
+ *
+ * @param [in] type A `PARCKeyType` value
+ *
+ * @return A static, null-terminated string.
+ *
+ * Example:
+ * @code
+ * {
+ * PARCKeyType type = PARCKeyType_RSA;
+ * const char *stringRep = parcKeyType_ToString(type);
+ * // use stringRep as necessary, and then free
+ * }
+ * @endcode
+ */
+const char *parcKeyType_ToString(PARCKeyType type);
+
+/**
+ * Convert a string representation value of a `PARCKeyType` to an actual value.
+ *
+ * @param [in] name A string representation of a `PARCKeyType` value.
+ *
+ * @return A `PARCKeyType` value.
+ *
+ * Example:
+ * @code
+ * {
+ * const char stringRep[17] = "PARCKeyType_RSA";
+ * PARCKeyType type = parcKeyType_FromString(stringRep);
+ * // use stringRep as necessary, and then free
+ * }
+ * @endcode
+ */
+PARCKeyType parcKeyType_FromString(const char *name);
+#endif // libparc_parc_KeyType_h
diff --git a/libparc/parc/security/parc_Pkcs12KeyStore.c b/libparc/parc/security/parc_Pkcs12KeyStore.c
index 4b9693b5..fd12c56f 100644
--- a/libparc/parc/security/parc_Pkcs12KeyStore.c
+++ b/libparc/parc/security/parc_Pkcs12KeyStore.c
@@ -37,6 +37,7 @@
#include <parc/security/parc_CertificateFactory.h>
#include <parc/security/parc_CertificateType.h>
#include <parc/security/parc_ContainerEncoding.h>
+#include <parc/security/parc_KeyType.h>
#include <parc/security/parc_Pkcs12KeyStore.h>
@@ -48,6 +49,7 @@ struct parc_pkcs12_keystore {
EVP_PKEY *private_key;
EVP_PKEY *public_key;
X509 *x509_cert;
+ PARCSigningAlgorithm signAlgo;
// These will be 0 length until asked for
PARCBuffer *public_key_digest;
@@ -63,7 +65,7 @@ struct parc_pkcs12_keystore {
static bool
_parcPkcs12KeyStore_Finalize(PARCPkcs12KeyStore **instancePtr)
{
- assertNotNull(instancePtr, "Parameter must be a non-null pointer to a PARCPublicKeySigner pointer.");
+ assertNotNull(instancePtr, "Parameter must be a non-null pointer to a PARCPkcs12KeyStore pointer.");
PARCPkcs12KeyStore *keystore = *instancePtr;
EVP_PKEY_free(keystore->private_key);
@@ -124,6 +126,22 @@ _parcPkcs12KeyStore_ParseFile(PARCPkcs12KeyStore *keystore, const char *filename
}
keystore->public_key = X509_get_pubkey(keystore->x509_cert);
+ if (keystore->public_key) {
+ switch (keystore->public_key->type) {
+ case EVP_PKEY_RSA:
+ keystore->signAlgo = PARCSigningAlgorithm_RSA;
+ break;
+ case EVP_PKEY_DSA:
+ keystore->signAlgo = PARCSigningAlgorithm_DSA;
+ break;
+ case EVP_PKEY_EC:
+ keystore->signAlgo = PARCSigningAlgorithm_ECDSA;
+ break;
+ default:
+ fprintf(stderr, "%d bit unknown Key type\n\n", EVP_PKEY_bits(keystore->public_key));
+ break;
+ }
+ }
return 0;
}
@@ -131,11 +149,80 @@ _parcPkcs12KeyStore_ParseFile(PARCPkcs12KeyStore *keystore, const char *filename
LONGBOW_STOP_DEPRECATED_WARNINGS
// =============================================================
+PKCS12 *_createPkcs12KeyStore_RSA(
+ PARCBuffer *privateKeyBuffer,
+ PARCCertificate *certificate,
+ const char *password)
+{
+ // Extract the private key
+ EVP_PKEY *privateKey = NULL;
+ uint8_t *privateKeyBytes = parcBuffer_Overlay(privateKeyBuffer, parcBuffer_Limit(privateKeyBuffer));
+ d2i_PrivateKey(EVP_PKEY_RSA, &privateKey, (const unsigned char **) &privateKeyBytes, parcBuffer_Limit(privateKeyBuffer));
+ parcBuffer_Release(&privateKeyBuffer);
+
+ // Extract the certificate
+ PARCBuffer *certBuffer = parcCertificate_GetDEREncodedCertificate(certificate);
+ uint8_t *certBytes = parcBuffer_Overlay(certBuffer, parcBuffer_Limit(certBuffer));
+ X509 *cert = NULL;
+ d2i_X509(&cert, (const unsigned char **) &certBytes, parcBuffer_Limit(certBuffer));
+
+ parcCertificate_Release(&certificate);
+
+ PKCS12 *pkcs12 = PKCS12_create((char *) password,
+ "ccnxuser",
+ privateKey,
+ cert,
+ NULL,
+ 0,
+ 0,
+ 0 /*default iter*/,
+ PKCS12_DEFAULT_ITER /*mac_iter*/,
+ 0);
+ X509_free(cert);
+ EVP_PKEY_free(privateKey);
+ return pkcs12;
+}
+
+PKCS12 *_createPkcs12KeyStore_ECDSA(
+ PARCBuffer *privateKeyBuffer,
+ PARCCertificate *certificate,
+ const char *password)
+{
+ // Extract the private key
+ EVP_PKEY *privateKey = NULL;
+ uint8_t *privateKeyBytes = parcBuffer_Overlay(privateKeyBuffer, parcBuffer_Limit(privateKeyBuffer));
+ d2i_PrivateKey(EVP_PKEY_EC, &privateKey, (const unsigned char **) &privateKeyBytes, parcBuffer_Limit(privateKeyBuffer));
+ parcBuffer_Release(&privateKeyBuffer);
+
+ // Extract the certificate
+ PARCBuffer *certBuffer = parcCertificate_GetDEREncodedCertificate(certificate);
+ uint8_t *certBytes = parcBuffer_Overlay(certBuffer, parcBuffer_Limit(certBuffer));
+ X509 *cert = NULL;
+ d2i_X509(&cert, (const unsigned char **) &certBytes, parcBuffer_Limit(certBuffer));
+
+ parcCertificate_Release(&certificate);
+
+ PKCS12 *pkcs12 = PKCS12_create((char *) password,
+ "ccnxuser",
+ privateKey,
+ cert,
+ NULL,
+ 0,
+ 0,
+ 0 /*default iter*/,
+ PKCS12_DEFAULT_ITER /*mac_iter*/,
+ 0);
+ X509_free(cert);
+ EVP_PKEY_free(privateKey);
+ return pkcs12;
+}
+
bool
parcPkcs12KeyStore_CreateFile(
const char *filename,
const char *password,
const char *subjectName,
+ PARCSigningAlgorithm signAlgo,
unsigned keyLength,
unsigned validityDays)
{
@@ -146,38 +233,24 @@ parcPkcs12KeyStore_CreateFile(
PARCCertificateFactory *factory = parcCertificateFactory_Create(PARCCertificateType_X509, PARCContainerEncoding_DER);
PARCBuffer *privateKeyBuffer;
- PARCCertificate *certificate = parcCertificateFactory_CreateSelfSignedCertificate(factory, &privateKeyBuffer, (char *) subjectName, keyLength, validityDays);
+ PARCCertificate *certificate = parcCertificateFactory_CreateSelfSignedCertificate(factory, &privateKeyBuffer, (char *) subjectName,signAlgo, keyLength, validityDays);
parcCertificateFactory_Release(&factory);
if (certificate != NULL) {
- // construct the full PKCS12 keystore to hold the certificate and private key
-
- // Extract the private key
- EVP_PKEY *privateKey = NULL;
- uint8_t *privateKeyBytes = parcBuffer_Overlay(privateKeyBuffer, parcBuffer_Limit(privateKeyBuffer));
- d2i_PrivateKey(EVP_PKEY_RSA, &privateKey, (const unsigned char **) &privateKeyBytes, parcBuffer_Limit(privateKeyBuffer));
- parcBuffer_Release(&privateKeyBuffer);
-
- // Extract the certificate
- PARCBuffer *certBuffer = parcCertificate_GetDEREncodedCertificate(certificate);
- uint8_t *certBytes = parcBuffer_Overlay(certBuffer, parcBuffer_Limit(certBuffer));
- X509 *cert = NULL;
- d2i_X509(&cert, (const unsigned char **) &certBytes, parcBuffer_Limit(certBuffer));
-
- parcCertificate_Release(&certificate);
-
- PKCS12 *pkcs12 = PKCS12_create((char *) password,
- "ccnxuser",
- privateKey,
- cert,
- NULL,
- 0,
- 0,
- 0 /*default iter*/,
- PKCS12_DEFAULT_ITER /*mac_iter*/,
- 0);
+ PKCS12 *pkcs12;
+ switch (signAlgo){
+ case PARCSigningAlgorithm_RSA:
+ pkcs12 = _createPkcs12KeyStore_RSA(privateKeyBuffer, certificate, password);
+ break;
+ case PARCSigningAlgorithm_ECDSA:
+ pkcs12 = _createPkcs12KeyStore_ECDSA(privateKeyBuffer, certificate, password);
+ break;
+ default:
+ return result;
+ }
+
if (pkcs12 != NULL) {
int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0600);
if (fd != -1) {
@@ -194,8 +267,6 @@ parcPkcs12KeyStore_CreateFile(
trapUnrecoverableState("Cannot open(2) the file '%s': %s", filename, strerror(errno));
}
PKCS12_free(pkcs12);
- X509_free(cert);
- EVP_PKEY_free(privateKey);
} else {
unsigned long errcode;
while ((errcode = ERR_get_error()) != 0) {
@@ -228,6 +299,10 @@ parcPkcs12KeyStore_Open(const char *filename, const char *password, PARCCryptoHa
return keyStore;
}
+PARCSigningAlgorithm _GetSigningAlgorithm(PARCPkcs12KeyStore *keystore)
+{
+ return keystore->signAlgo;
+}
static PARCCryptoHash *
_GetPublickKeyDigest(PARCPkcs12KeyStore *keystore)
@@ -365,6 +440,7 @@ PARCKeyStoreInterface *PARCPkcs12KeyStoreAsKeyStore = &(PARCKeyStoreInterface) {
.getDEREncodedCertificate = (PARCKeyStoreGetDEREncodedCertificate *) _GetDEREncodedCertificate,
.getDEREncodedPublicKey = (PARCKeyStoreGetDEREncodedPublicKey *) _GetDEREncodedPublicKey,
.getDEREncodedPrivateKey = (PARCKeyStoreGetDEREncodedPrivateKey *) _GetDEREncodedPrivateKey,
+ .getSigningAlgorithm = (PARCKeyStoreGetSigningAlgorithm *) _GetSigningAlgorithm,
};
// =============================================================
diff --git a/libparc/parc/security/parc_Pkcs12KeyStore.h b/libparc/parc/security/parc_Pkcs12KeyStore.h
index ed04c702..950284ea 100644
--- a/libparc/parc/security/parc_Pkcs12KeyStore.h
+++ b/libparc/parc/security/parc_Pkcs12KeyStore.h
@@ -24,6 +24,7 @@
#include <parc/security/parc_KeyStore.h>
#include <parc/security/parc_Signer.h>
+#include <parc/security/parc_SigningAlgorithm.h>
struct parc_pkcs12_keystore;
typedef struct parc_pkcs12_keystore PARCPkcs12KeyStore;
@@ -31,13 +32,13 @@ typedef struct parc_pkcs12_keystore PARCPkcs12KeyStore;
extern PARCKeyStoreInterface *PARCPkcs12KeyStoreAsKeyStore;
/**
- * Increase the number of references to a `PARCPublicKeySigner` instance.
+ * Increase the number of references to a `PARCPkcs12KeyStore` instance.
*
- * Note that new `PARCPublicKeySigner` is not created,
- * only that the given `PARCPublicKeySigner` reference count is incremented.
- * Discard the reference by invoking `parcPublicKeySigner_Release`.
+ * Note that new `PARCPkcs12KeyStore` is not created,
+ * only that the given `PARCPkcs12KeyStore` reference count is incremented.
+ * Discard the reference by invoking `parcPkcs12KeyStore_Release`.
*
- * @param [in] instance A pointer to a valid PARCPublicKeySigner instance.
+ * @param [in] instance A pointer to a valid PARCPkcs12KeyStore instance.
*
* @return The same value as @p instance.
*
@@ -97,12 +98,12 @@ void parcPkcs12KeyStore_Release(PARCPkcs12KeyStore **instancePtr);
* const char *filename = "/tmp/ccnxFileKeyStore_Pkcs12Open_CreateAndOpen.p12";
* const char *password = "12345";
* const char *subject = "alice";
- * bool result = parcPkcs12KeyStore_CreateFile(filename, password, subject, 1024, 32);
+ * bool result = parcPkcs12KeyStore_CreateFile(filename, password, subject, PARCSigningAlgorithm_RSA, 1024, 32);
* }
* @endcode
*/
bool parcPkcs12KeyStore_CreateFile(const char *filename, const char *password, const char *subjectName,
- unsigned keyLength, unsigned validityDays);
+ PARCSigningAlgorithm signAlgo, unsigned keyLength, unsigned validityDays);
/**
* Create a `PARCPkcs12KeyStore` instance.
@@ -123,12 +124,11 @@ bool parcPkcs12KeyStore_CreateFile(const char *filename, const char *password, c
*
* ...
*
- * PARCSigningInterface *interface = parcPublicKeySignerPkcs12Store_Open(filename, password, PARCCryptoHashType_SHA256);
+ * PARCSigningInterface *interface = parcPkcs12Store_Open(filename, password, PARCCryptoHashType_SHA256);
*
* ...
* }
* @endcode
*/
PARCPkcs12KeyStore *parcPkcs12KeyStore_Open(const char *filename, const char *password, PARCCryptoHashType hashType);
-
-#endif // libparc_parc_PublicKeySignerPkcs12Store_h
+#endif // libparc_parc_Pkcs12Store_h
diff --git a/libparc/parc/security/parc_PublicKeySigner.c b/libparc/parc/security/parc_PublicKeySigner.c
index 6411f075..0f11b957 100644
--- a/libparc/parc/security/parc_PublicKeySigner.c
+++ b/libparc/parc/security/parc_PublicKeySigner.c
@@ -118,13 +118,17 @@ parcObject_Override(PARCPublicKeySigner, PARCObject,
.hashCode = (PARCObjectHashCode *) parcPublicKeySigner_HashCode);
PARCPublicKeySigner *
-parcPublicKeySigner_Create(PARCKeyStore *keyStore, PARCSigningAlgorithm signingAlgorithm, PARCCryptoHashType hashType)
+parcPublicKeySigner_Create(PARCKeyStore *keyStore, PARCCryptoSuite suite)
{
PARCPublicKeySigner *result = parcObject_CreateInstance(PARCPublicKeySigner);
+ PARCSigningAlgorithm signAlgo = parcSigningAlgorithm_GetSigningAlgorithm(suite);
+ PARCCryptoHashType hashType = parcCryptoSuite_GetCryptoHash(suite);
+
+
if (result != NULL) {
result->keyStore = parcKeyStore_Acquire(keyStore);
- result->signingAlgorithm = signingAlgorithm;
+ result->signingAlgorithm = signAlgo;
result->hashType = hashType;
result->hasher = parcCryptoHasher_Create(hashType);
}
@@ -133,9 +137,10 @@ parcPublicKeySigner_Create(PARCKeyStore *keyStore, PARCSigningAlgorithm signingA
}
static PARCSigningAlgorithm
-_GetSigningAlgorithm(PARCPublicKeySigner *interfaceContext)
+_GetSigningAlgorithm(PARCPublicKeySigner *signer)
{
- return PARCSigningAlgorithm_RSA;
+ assertNotNull(signer, "Parameter must be non-null PARCCryptoHasher");
+ return signer->signingAlgorithm;
}
static PARCCryptoHashType
@@ -159,6 +164,56 @@ _GetKeyStore(PARCPublicKeySigner *signer)
return signer->keyStore;
}
+static inline int _SignDigestRSA(const PARCCryptoHash *digestToSign, PARCBuffer *privateKeyBuffer, int opensslDigestType, uint8_t ** sig, unsigned * sigLength)
+{
+ EVP_PKEY *privateKey = NULL;
+ size_t keySize = parcBuffer_Remaining(privateKeyBuffer);
+ uint8_t *bytes = parcBuffer_Overlay(privateKeyBuffer, keySize);
+ privateKey = d2i_PrivateKey(EVP_PKEY_RSA, &privateKey, (const unsigned char **) &bytes, keySize);
+
+ RSA *rsa = EVP_PKEY_get1_RSA(privateKey);
+ *sig = parcMemory_Allocate(RSA_size(rsa));
+
+ assertNotNull(*sig, "parcMemory_Allocate(%u) returned NULL", RSA_size(rsa));
+
+ *sigLength = 0;
+ PARCBuffer *bb_digest = parcCryptoHash_GetDigest(digestToSign);
+ int result = RSA_sign(opensslDigestType,
+ (unsigned char *) parcByteArray_Array(parcBuffer_Array(bb_digest)),
+ (int) parcBuffer_Remaining(bb_digest),
+ *sig,
+ sigLength,
+ rsa);
+ assertTrue(result == 1, "Got error from RSA_sign: %d", result);
+ RSA_free(rsa);
+ return result;
+}
+
+static inline int _SignDigestECDSA(const PARCCryptoHash *digestToSign, PARCBuffer *privateKeyBuffer, int opensslDigestType, uint8_t ** sig, unsigned * sigLength)
+{
+ EVP_PKEY *privateKey = NULL;
+ size_t keySize = parcBuffer_Remaining(privateKeyBuffer);
+ uint8_t *bytes = parcBuffer_Overlay(privateKeyBuffer, keySize);
+ privateKey = d2i_PrivateKey(EVP_PKEY_EC, &privateKey, (const unsigned char **) &bytes, keySize);
+
+ EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(privateKey);
+
+ *sig = parcMemory_Allocate(ECDSA_size(ec_key));
+ assertNotNull(sig, "parcMemory_Allocate(%u) returned NULL", ECDSA_size(ec_key));
+
+ *sigLength = 0;
+ PARCBuffer *bb_digest = parcCryptoHash_GetDigest(digestToSign);
+ int result = ECDSA_sign(opensslDigestType,
+ (unsigned char *) parcByteArray_Array(parcBuffer_Array(bb_digest)),
+ (int) parcBuffer_Remaining(bb_digest),
+ *sig,
+ sigLength,
+ ec_key);
+ assertTrue(result == 1, "Got error from ECDSA_sign: %d", result);
+ EC_KEY_free(ec_key);
+
+}
+
static PARCSignature *
_SignDigest(PARCPublicKeySigner *signer, const PARCCryptoHash *digestToSign)
{
@@ -170,15 +225,10 @@ _SignDigest(PARCPublicKeySigner *signer, const PARCCryptoHash *digestToSign)
// TODO: what is the best way to expose this?
PARCKeyStore *keyStore = signer->keyStore;
PARCBuffer *privateKeyBuffer = parcKeyStore_GetDEREncodedPrivateKey(keyStore);
- EVP_PKEY *privateKey = NULL;
- size_t keySize = parcBuffer_Remaining(privateKeyBuffer);
- uint8_t *bytes = parcBuffer_Overlay(privateKeyBuffer, keySize);
- privateKey = d2i_PrivateKey(EVP_PKEY_RSA, &privateKey, (const unsigned char **) &bytes, keySize);
- parcBuffer_Release(&privateKeyBuffer);
-
- RSA *rsa = EVP_PKEY_get1_RSA(privateKey);
int opensslDigestType;
+ uint8_t *sig;
+ unsigned sigLength;
switch (parcCryptoHash_GetDigestType(digestToSign)) {
case PARCCryptoHashType_SHA256:
@@ -192,19 +242,16 @@ _SignDigest(PARCPublicKeySigner *signer, const PARCCryptoHash *digestToSign)
parcCryptoHashType_ToString(parcCryptoHash_GetDigestType(digestToSign)));
}
- uint8_t *sig = parcMemory_Allocate(RSA_size(rsa));
- assertNotNull(sig, "parcMemory_Allocate(%u) returned NULL", RSA_size(rsa));
-
- unsigned sigLength = 0;
- PARCBuffer *bb_digest = parcCryptoHash_GetDigest(digestToSign);
- int result = RSA_sign(opensslDigestType,
- (unsigned char *) parcByteArray_Array(parcBuffer_Array(bb_digest)),
- (int) parcBuffer_Remaining(bb_digest),
- sig,
- &sigLength,
- rsa);
- assertTrue(result == 1, "Got error from RSA_sign: %d", result);
- RSA_free(rsa);
+ switch (signer->signingAlgorithm) {
+ case PARCSigningAlgorithm_RSA:
+ _SignDigestRSA(digestToSign, privateKeyBuffer, opensslDigestType, &sig, &sigLength);
+ break;
+ case PARCSigningAlgorithm_ECDSA:
+ _SignDigestECDSA(digestToSign, privateKeyBuffer, opensslDigestType, &sig, &sigLength);
+ break;
+ default:
+ return NULL;
+ }
PARCBuffer *bbSign = parcBuffer_Allocate(sigLength);
parcBuffer_Flip(parcBuffer_PutArray(bbSign, sigLength, sig));
@@ -216,6 +263,7 @@ _SignDigest(PARCPublicKeySigner *signer, const PARCCryptoHash *digestToSign)
bbSign
);
parcBuffer_Release(&bbSign);
+ parcBuffer_Release(&privateKeyBuffer);
return signature;
}
diff --git a/libparc/parc/security/parc_PublicKeySigner.h b/libparc/parc/security/parc_PublicKeySigner.h
index d2803418..99aa14fa 100644
--- a/libparc/parc/security/parc_PublicKeySigner.h
+++ b/libparc/parc/security/parc_PublicKeySigner.h
@@ -104,7 +104,7 @@ void parcPublicKeySigner_AssertValid(const PARCPublicKeySigner *instance);
* }
* @endcode
*/
-PARCPublicKeySigner *parcPublicKeySigner_Create(PARCKeyStore *keyStore, PARCSigningAlgorithm signingAlgorithm, PARCCryptoHashType hashType);
+PARCPublicKeySigner *parcPublicKeySigner_Create(PARCKeyStore *keyStore, PARCCryptoSuite suite);
/**
* Compares @p instance with @p other for order.
diff --git a/libparc/parc/security/parc_Signer.h b/libparc/parc/security/parc_Signer.h
index c6d49480..1c967b75 100755
--- a/libparc/parc/security/parc_Signer.h
+++ b/libparc/parc/security/parc_Signer.h
@@ -130,7 +130,7 @@ typedef struct parc_signer_interface {
* Example
* @code
* {
- * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner);
+ * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCRSASignerAsSigner);
*
* parcSigner_AssertValid(signer);
* }
@@ -150,7 +150,7 @@ void parcSigner_AssertValid(const PARCSigner *signer);
* Example:
* @code
* {
- * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner);
+ * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCRSASignerAsSigner);
* }
* @endcode
*/
@@ -171,7 +171,7 @@ PARCSigner *parcSigner_Create(PARCObject *instance, PARCSigningInterface *interf
* Example:
* @code
* {
- * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner);
+ * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCRSASignerAsSigner);
* PARCSigner *handle = parcSigner_Acquire(signer);
* // use the handle instance as needed
* }
@@ -197,7 +197,7 @@ PARCSigner *parcSigner_Acquire(const PARCSigner *signer);
* Example:
* @code
* {
- * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner);
+ * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCRSASignerAsSigner);
*
* parcSigner_Release(&signer);
* }
@@ -215,7 +215,7 @@ void parcSigner_Release(PARCSigner **signerPtr);
* Example:
* @code
* {
- * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner);
+ * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCRSASignerAsSigner);
*
* PARCKeyId *keyId = parcSigner_CreateKeyId(signer);
* }
@@ -233,7 +233,7 @@ PARCKeyId *parcSigner_CreateKeyId(const PARCSigner *signer);
* Example:
* @code
* {
- * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner);
+ * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCRSASignerAsSigner);
*
* PARCKey *publicKey = parcSigner_CreatePublicKey(signer);
* }
@@ -257,7 +257,7 @@ PARCKey *parcSigner_CreatePublicKey(PARCSigner *signer);
* Example:
* @code
* {
- * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner);
+ * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCRSASignerAsSigner);
*
* PARCCryptoHasher hasher = parcSigner_GetCryptoHasher(signer);
* }
@@ -279,7 +279,7 @@ PARCCryptoHasher *parcSigner_GetCryptoHasher(const PARCSigner *signer);
* Example:
* @code
* {
- * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner);
+ * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCRSASignerAsSigner);
*
* PARCCryptoHasher *hasher = parcSigner_GetCryptoHasher(signer);
* parcCryptoHasher_Init(hasher);
@@ -303,7 +303,7 @@ PARCSignature *parcSigner_SignDigest(const PARCSigner *signer, const PARCCryptoH
* Example:
* @code
* {
- * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner);
+ * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCRSASignerAsSigner);
* PARCBuffer *inputBuffer = ...
*
* PARCSignature signature = parcSigner_SignBuffer(signer, inputBuffer);
@@ -322,7 +322,7 @@ PARCSignature *parcSigner_SignBuffer(const PARCSigner *signer, const PARCBuffer
* Example:
* @code
* {
- * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner);
+ * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCRSASignerAsSigner);
*
* PARCSigningAlgorithm suite = parcSigner_GetSigningAlgorithm(signer);
* }
@@ -340,7 +340,7 @@ PARCSigningAlgorithm parcSigner_GetSigningAlgorithm(PARCSigner *signer);
* Example:
* @code
* {
- * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner);
+ * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCRSASignerAsSigner);
*
* PARCCryptoHashType suite = parcSigner_GetCryptoHashType(signer);
* }
@@ -358,7 +358,7 @@ PARCCryptoHashType parcSigner_GetCryptoHashType(const PARCSigner *signer);
* Example:
* @code
* {
- * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner);
+ * PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCRSASignerAsSigner);
*
* PARCKeyStore *keyStore = parcSigner_GetKeyStore(signer);
* }
diff --git a/libparc/parc/security/parc_SigningAlgorithm.c b/libparc/parc/security/parc_SigningAlgorithm.c
index d0dadd4a..1e800a6a 100755
--- a/libparc/parc/security/parc_SigningAlgorithm.c
+++ b/libparc/parc/security/parc_SigningAlgorithm.c
@@ -32,6 +32,7 @@ static struct {
{ PARCSigningAlgorithm_RSA, "PARCSigningAlgorithm_RSA" },
{ PARCSigningAlgorithm_DSA, "PARCSigningAlgorithm_DSA" },
{ PARCSigningAlgorithm_HMAC, "PARCSigningAlgorithm_HMAC" },
+ { PARCSigningAlgorithm_ECDSA,"PARCSigningAlgorithm_ECDSA"},
{ 0, NULL }
};
@@ -72,6 +73,8 @@ parcSigningAlgorithm_GetSigningAlgorithm(PARCCryptoSuite suite)
case PARCCryptoSuite_HMAC_SHA512:
return PARCSigningAlgorithm_HMAC;
+ case PARCCryptoSuite_ECDSA_SHA256:
+ return PARCSigningAlgorithm_ECDSA;
case PARCCryptoSuite_NULL_CRC32C:
return PARCSigningAlgortihm_NULL;
diff --git a/libparc/parc/security/parc_SigningAlgorithm.h b/libparc/parc/security/parc_SigningAlgorithm.h
index 02f7c946..ae5fc252 100644
--- a/libparc/parc/security/parc_SigningAlgorithm.h
+++ b/libparc/parc/security/parc_SigningAlgorithm.h
@@ -34,7 +34,8 @@ typedef enum {
PARCSigningAlgorithm_RSA = 1,
PARCSigningAlgorithm_DSA = 2,
PARCSigningAlgorithm_HMAC = 3,
- PARCSigningAlgortihm_NULL = 4,
+ PARCSigningAlgorithm_ECDSA = 4,
+ PARCSigningAlgortihm_NULL = 5,
} PARCSigningAlgorithm;
/**
diff --git a/libparc/parc/security/parc_X509Certificate.c b/libparc/parc/security/parc_X509Certificate.c
index 8cc4b0b7..67ee6b2b 100644
--- a/libparc/parc/security/parc_X509Certificate.c
+++ b/libparc/parc/security/parc_X509Certificate.c
@@ -29,6 +29,7 @@
#include <parc/algol/parc_Buffer.h>
#include <parc/algol/parc_Object.h>
#include <parc/algol/parc_Memory.h>
+#include <parc/security/parc_KeyType.h>
#include <openssl/bio.h>
#include <openssl/err.h>
@@ -398,91 +399,219 @@ parcX509Certificate_CreateFromDERBuffer(const PARCBuffer *buffer)
return cert;
}
-PARCX509Certificate *
-parcX509Certificate_CreateSelfSignedCertificate(PARCBuffer **privateKeyBuffer, char *subjectName, int keyLength, size_t validityDays)
+PARCX509Certificate * _createSelfSignedCertificate_RSA(PARCBuffer **privateKeyBuffer, char *subjectName, int keyLength, size_t validityDays)
{
- parcSecurity_AssertIsInitialized();
+ parcSecurity_AssertIsInitialized();
- RSA *rsa = RSA_new();
- assertNotNull(rsa, "RSA_new failed.");
+ RSA *rsa = RSA_new();
+ assertNotNull(rsa, "RSA_new failed.");
- EVP_PKEY *privateKey = EVP_PKEY_new();
- assertNotNull(privateKey, "EVP_PKEY_new() failed.");
+ EVP_PKEY *privateKey = EVP_PKEY_new();
+ assertNotNull(privateKey, "EVP_PKEY_new() failed.");
- X509 *cert = X509_new();
- assertNotNull(cert, "X509_new() failed.");
+ X509 *cert = X509_new();
+ assertNotNull(cert, "X509_new() failed.");
- int res;
- BIGNUM *pub_exp;
+ int res;
+ BIGNUM *pub_exp;
- pub_exp = BN_new();
+ pub_exp = BN_new();
- BN_set_word(pub_exp, RSA_F4);
- res = 1;
- bool result = false;
- if (RSA_generate_key_ex(rsa, keyLength, pub_exp, NULL)) {
- if (EVP_PKEY_set1_RSA(privateKey, rsa)) {
- if (X509_set_version(cert, 2)) { // 2 => X509v3
- result = true;
- }
- }
+ BN_set_word(pub_exp, RSA_F4);
+ res = 1;
+ bool result = false;
+ if (RSA_generate_key_ex(rsa, keyLength, pub_exp, NULL)) {
+ if (EVP_PKEY_set1_RSA(privateKey, rsa)) {
+ if (X509_set_version(cert, 2)) { // 2 => X509v3
+ result = true;
+ }
}
- if (result) {
- // add serial number
- if (_addRandomSerial(cert) == true) {
- if (_addValidityPeriod(cert, validityDays) == true) {
- if (X509_set_pubkey(cert, privateKey) == 1) {
- if (_addSubjectName(cert, subjectName) == true) {
- if (_addExtensions(cert) == true) {
- if (_addKeyIdentifier(cert) == true) {
- // The certificate is complete, sign it.
- if (X509_sign(cert, privateKey, EVP_sha256())) {
- result = true;
- } else {
- printf("error: (%d) %s\n", res, ERR_lib_error_string(res));
- }
- }
- }
- }
+ }
+ if (result) {
+ // add serial number
+ if (_addRandomSerial(cert) == true) {
+ if (_addValidityPeriod(cert, validityDays) == true) {
+ if (X509_set_pubkey(cert, privateKey) == 1) {
+ if (_addSubjectName(cert, subjectName) == true) {
+ if (_addExtensions(cert) == true) {
+ if (_addKeyIdentifier(cert) == true) {
+ // The certificate is complete, sign it.
+ if (X509_sign(cert, privateKey, EVP_sha256())) {
+ result = true;
+ } else {
+ printf("error: (%d) %s\n", res, ERR_lib_error_string(res));
}
+ }
}
+ }
}
+ }
}
+ }
- ERR_print_errors_fp(stdout);
+ ERR_print_errors_fp(stdout);
- BN_free(pub_exp);
+ BN_free(pub_exp);
- uint8_t *certificateDerEncoding = NULL;
- int numBytes = i2d_X509(cert, &certificateDerEncoding);
- if (numBytes < 0) {
- EVP_PKEY_free(privateKey);
- RSA_free(rsa);
- X509_free(cert);
+ uint8_t *certificateDerEncoding = NULL;
+ int numBytes = i2d_X509(cert, &certificateDerEncoding);
+ if (numBytes < 0) {
+ EVP_PKEY_free(privateKey);
+ RSA_free(rsa);
+ X509_free(cert);
- return NULL;
- }
+ return NULL;
+ }
- PARCBuffer *derBuffer = parcBuffer_Allocate(numBytes);
- parcBuffer_Flip(parcBuffer_PutArray(derBuffer, numBytes, certificateDerEncoding));
+ PARCBuffer *derBuffer = parcBuffer_Allocate(numBytes);
+ parcBuffer_Flip(parcBuffer_PutArray(derBuffer, numBytes, certificateDerEncoding));
- PARCX509Certificate *certificate = parcX509Certificate_CreateFromDERBuffer(derBuffer);
- parcBuffer_Release(&derBuffer);
+ PARCX509Certificate *certificate = parcX509Certificate_CreateFromDERBuffer(derBuffer);
+ parcBuffer_Release(&derBuffer);
- uint8_t *privateKeyBytes = NULL;
- int privateKeyByteCount = i2d_PrivateKey(privateKey, &privateKeyBytes);
- if (privateKeyByteCount < 0) {
- EVP_PKEY_free(privateKey);
- RSA_free(rsa);
- X509_free(cert);
+ uint8_t *privateKeyBytes = NULL;
+ int privateKeyByteCount = i2d_PrivateKey(privateKey, &privateKeyBytes);
+ if (privateKeyByteCount < 0) {
+ EVP_PKEY_free(privateKey);
+ RSA_free(rsa);
+ X509_free(cert);
- return NULL;
+ return NULL;
+ }
+
+ *privateKeyBuffer = parcBuffer_Allocate(privateKeyByteCount);
+ parcBuffer_Flip(parcBuffer_PutArray(*privateKeyBuffer, privateKeyByteCount, privateKeyBytes));
+
+ EVP_PKEY_free(privateKey);
+ RSA_free(rsa);
+ X509_free(cert);
+
+ return certificate;
+}
+
+static inline int _get_EC_params_from_lenght(int keyLength)
+{
+ //For the moment only support 256bit key length
+ switch (keyLength)
+ {
+ case 160:
+ return NID_secp160k1;
+ case 192:
+ return NID_secp192k1;
+ case 224:
+ return NID_secp224k1;
+ case 256:
+ return NID_secp256k1;
+ default:
+ return -1;
+ }
+
+}
+
+PARCX509Certificate * _createSelfSignedCertificate_EC(PARCBuffer **privateKeyBuffer, char *subjectName, int keyLength, size_t validityDays)
+{
+ parcSecurity_AssertIsInitialized();
+ int curve_params = _get_EC_params_from_lenght(keyLength);
+ bool result = false;
+
+ if (curve_params == -1)
+ return NULL;
+
+ EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve_params);
+ assertNotNull(ec_key, "EC key creation failed.");
+
+ EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE);
+
+ EVP_PKEY *pkey = EVP_PKEY_new();
+ assertNotNull(pkey, "EVP_PKEY_new() failed.");
+
+ X509 *cert = X509_new();
+ assertNotNull(cert, "X509_new() failed.");
+
+ int res;
+
+
+ if((res = (EC_KEY_generate_key(ec_key))) < 0 )
+ printf("error: (%d) %s\n", res, ERR_lib_error_string(res));
+ else if((res = (EVP_PKEY_set1_EC_KEY(pkey, ec_key))) < 0 )
+ printf("error: (%d) %s\n", res, ERR_lib_error_string(res));
+ else if (X509_set_version(cert, 2)) { // 2 => X509v3
+ result = true;
+ }
+
+ if (result) {
+ // add serial number
+ if (_addRandomSerial(cert) == true) {
+ if (_addValidityPeriod(cert, validityDays) == true) {
+ if (X509_set_pubkey(cert, pkey) == 1) {
+ if (_addSubjectName(cert, subjectName) == true) {
+ if (_addExtensions(cert) == true) {
+ if (_addKeyIdentifier(cert) == true) {
+ // The certificate is complete, sign it.
+ if (X509_sign(cert, pkey, EVP_sha256())) {
+ result = true;
+ } else {
+ printf("error: (%d) %s\n", res, ERR_lib_error_string(res));
+ }
+ }
+ }
+ }
+ }
+ }
}
+ }
- *privateKeyBuffer = parcBuffer_Allocate(privateKeyByteCount);
- parcBuffer_Flip(parcBuffer_PutArray(*privateKeyBuffer, privateKeyByteCount, privateKeyBytes));
+ ERR_print_errors_fp(stdout);
- return certificate;
+
+
+ uint8_t *certificateDerEncoding = NULL;
+ int numBytes = i2d_X509(cert, &certificateDerEncoding);
+ if (numBytes < 0) {
+ EVP_PKEY_free(pkey);
+ EC_KEY_free(ec_key);
+ X509_free(cert);
+
+ return NULL;
+ }
+
+ PARCBuffer *derBuffer = parcBuffer_Allocate(numBytes);
+ parcBuffer_Flip(parcBuffer_PutArray(derBuffer, numBytes, certificateDerEncoding));
+
+ PARCX509Certificate *certificate = parcX509Certificate_CreateFromDERBuffer(derBuffer);
+ parcBuffer_Release(&derBuffer);
+
+ uint8_t *pkeyBytes = NULL;
+ int pkeyByteCount = i2d_PrivateKey(pkey, &pkeyBytes);
+ if (pkeyByteCount < 0) {
+ EVP_PKEY_free(pkey);
+ EC_KEY_free(ec_key);
+ X509_free(cert);
+
+ return NULL;
+ }
+
+ *privateKeyBuffer = parcBuffer_Allocate(pkeyByteCount);
+ parcBuffer_Flip(parcBuffer_PutArray(*privateKeyBuffer, pkeyByteCount, pkeyBytes));
+
+ EVP_PKEY_free(pkey);
+ EC_KEY_free(ec_key);
+ X509_free(cert);
+
+ return certificate;
+}
+
+PARCX509Certificate *
+parcX509Certificate_CreateSelfSignedCertificate(PARCBuffer **privateKeyBuffer, char *subjectName, int keyLength, size_t validityDays, PARCKeyType keyType)
+{
+ switch(keyType) {
+ case PARCKeyType_RSA:
+ return _createSelfSignedCertificate_RSA(privateKeyBuffer, subjectName, keyLength, validityDays);
+ case PARCKeyType_EC:
+ return _createSelfSignedCertificate_EC(privateKeyBuffer, subjectName, keyLength, validityDays);
+ }
+
+ return NULL;
}
diff --git a/libparc/parc/security/parc_X509Certificate.h b/libparc/parc/security/parc_X509Certificate.h
index 037d6aac..c6ca8247 100755
--- a/libparc/parc/security/parc_X509Certificate.h
+++ b/libparc/parc/security/parc_X509Certificate.h
@@ -23,7 +23,8 @@
#ifndef libparc_parc_X509Certificate_h
#define libparc_parc_X509Certificate_h
-#include <parc/security//parc_Certificate.h>
+#include <parc/security/parc_Certificate.h>
+#include <parc/security/parc_KeyType.h>
struct parc_X509_certificate;
typedef struct parc_X509_certificate PARCX509Certificate;
@@ -67,7 +68,7 @@ PARCX509Certificate *parcX509Certificate_CreateFromPEMFile(const char *filename)
PARCX509Certificate *parcX509Certificate_CreateFromDERBuffer(const PARCBuffer *buffer);
// TODO
-PARCX509Certificate *parcX509Certificate_CreateSelfSignedCertificate(PARCBuffer **privateKey, char *subjectName, int keyLength, size_t valdityDays);
+PARCX509Certificate *parcX509Certificate_CreateSelfSignedCertificate(PARCBuffer **privateKey, char *subjectName, int keyLength, size_t valdityDays, PARCKeyType ketType);
/**
* Increase the number of references to a `PARCX509Certificate` instance.
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
new file mode 100644
index 00000000..5fb44d05
--- /dev/null
+++ b/libparc/parc/security/test/test_ec.p12
Binary files differ
diff --git a/libparc/parc/security/test/test_ec_crt.der b/libparc/parc/security/test/test_ec_crt.der
new file mode 100644
index 00000000..d3294e20
--- /dev/null
+++ b/libparc/parc/security/test/test_ec_crt.der
Binary files differ
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
new file mode 100644
index 00000000..28fbd5a5
--- /dev/null
+++ b/libparc/parc/security/test/test_ec_key.der
Binary files differ
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
new file mode 100644
index 00000000..e9150405
--- /dev/null
+++ b/libparc/parc/security/test/test_ec_pub.der
Binary files differ
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
new file mode 100644
index 00000000..787f8b3a
--- /dev/null
+++ b/libparc/parc/security/test/test_ec_pub_sha256.bin.sig
Binary files differ
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
new file mode 100644
index 00000000..92b210a1
--- /dev/null
+++ b/libparc/parc/security/test/test_random_bytes.sig_ec
Binary files differ