Added signature calculation and verification for ECDSA 26/11726/1
authorDevel <[email protected]>
Thu, 12 Apr 2018 16:07:08 +0000 (18:07 +0200)
committerDevel <[email protected]>
Thu, 12 Apr 2018 16:07:08 +0000 (18:07 +0200)
Change-Id: I946e146b9a6ae33ee294a09417e8366853faa502
Signed-off-by: Devel <[email protected]>
51 files changed:
libparc/parc/security/command-line/parc-publickey.c
libparc/parc/security/parc_CertificateFactory.c
libparc/parc/security/parc_CertificateFactory.h
libparc/parc/security/parc_CryptoSuite.c
libparc/parc/security/parc_CryptoSuite.h
libparc/parc/security/parc_Identity.c
libparc/parc/security/parc_Identity.h
libparc/parc/security/parc_IdentityFile.c
libparc/parc/security/parc_IdentityFile.h
libparc/parc/security/parc_InMemoryVerifier.c
libparc/parc/security/parc_InMemoryVerifier.h
libparc/parc/security/parc_Key.c
libparc/parc/security/parc_KeyStore.c
libparc/parc/security/parc_KeyStore.h
libparc/parc/security/parc_KeyType.c [new file with mode: 0644]
libparc/parc/security/parc_KeyType.h [new file with mode: 0644]
libparc/parc/security/parc_Pkcs12KeyStore.c
libparc/parc/security/parc_Pkcs12KeyStore.h
libparc/parc/security/parc_PublicKeySigner.c
libparc/parc/security/parc_PublicKeySigner.h
libparc/parc/security/parc_Signer.h
libparc/parc/security/parc_SigningAlgorithm.c
libparc/parc/security/parc_SigningAlgorithm.h
libparc/parc/security/parc_X509Certificate.c
libparc/parc/security/parc_X509Certificate.h
libparc/parc/security/test/CMakeLists.txt
libparc/parc/security/test/README.keystore
libparc/parc/security/test/test_ec.crt [new file with mode: 0644]
libparc/parc/security/test/test_ec.csr [new file with mode: 0644]
libparc/parc/security/test/test_ec.p12 [new file with mode: 0644]
libparc/parc/security/test/test_ec_crt.der [new file with mode: 0644]
libparc/parc/security/test/test_ec_crt_sha256.bin [new file with mode: 0644]
libparc/parc/security/test/test_ec_key.der [new file with mode: 0644]
libparc/parc/security/test/test_ec_key.pem [new file with mode: 0644]
libparc/parc/security/test/test_ec_pub.der [new file with mode: 0644]
libparc/parc/security/test/test_ec_pub.pem [new file with mode: 0644]
libparc/parc/security/test/test_ec_pub_sha256.bin [new file with mode: 0644]
libparc/parc/security/test/test_ec_pub_sha256.bin.sig [new file with mode: 0644]
libparc/parc/security/test/test_parc_CryptoSuite.c
libparc/parc/security/test/test_parc_Identity.c
libparc/parc/security/test/test_parc_IdentityFile.c
libparc/parc/security/test/test_parc_InMemoryVerifier.c
libparc/parc/security/test/test_parc_InMemoryVerifierECDSA.c [new file with mode: 0644]
libparc/parc/security/test/test_parc_Pkcs12KeyStore.c
libparc/parc/security/test/test_parc_Pkcs12KeyStoreECDSA.c [new file with mode: 0644]
libparc/parc/security/test/test_parc_PublicKeyECSigner.c [new file with mode: 0644]
libparc/parc/security/test/test_parc_PublicKeySigner.c
libparc/parc/security/test/test_parc_Signature.c
libparc/parc/security/test/test_parc_SignerEC.c [new file with mode: 0644]
libparc/parc/security/test/test_parc_X509Certificate.c
libparc/parc/security/test/test_random_bytes.sig_ec [new file with mode: 0644]

index 3073311..e88e94b 100644 (file)
@@ -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);
index 3825ae0..3a758c5 100644 (file)
@@ -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) {
index 5f49ac2..de034d1 100755 (executable)
@@ -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.
index 9f4506e..c807f9a 100755 (executable)
@@ -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);
+    }
+}
index b9c138e..a8e07f0 100755 (executable)
@@ -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
index 0afef9f..a132964 100755 (executable)
@@ -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
index d581b97..32b9b17 100755 (executable)
@@ -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.
index f5f6d06..972c8d0 100644 (file)
@@ -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);
index c5ee4ac..c125ffb 100644 (file)
@@ -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.
index e5a9ba0..e5946d3 100644 (file)
@@ -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;
         }
     }
index d9f1cf9..bbec813 100755 (executable)
@@ -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.
index 06b8542..3802549 100755 (executable)
@@ -69,6 +69,7 @@ parcKey_CreateFromDerEncodedPublicKey(PARCKeyId *keyid, PARCSigningAlgorithm sig
     switch (signingAlg) {
         case PARCSigningAlgorithm_RSA: // fallthrough
         case PARCSigningAlgorithm_DSA:
+        case PARCSigningAlgorithm_ECDSA:
             break;
 
         default:
index 912861d..00fac01 100755 (executable)
@@ -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;
+}
index 03be78a..253505d 100755 (executable)
@@ -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 (file)
index 0000000..62fc000
--- /dev/null
@@ -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 (file)
index 0000000..92d58ed
--- /dev/null
@@ -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
index 4b9693b..fd12c56 100644 (file)
@@ -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,
 };
 
 // =============================================================
index ed04c70..950284e 100644 (file)
@@ -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
index 6411f07..0f11b95 100644 (file)
@@ -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;
 }
 
index d280341..99aa14f 100644 (file)
@@ -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.
index c6d4948..1c967b7 100755 (executable)
@@ -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);
  * }
index d0dadd4..1e800a6 100755 (executable)
@@ -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;
 
index 02f7c94..ae5fc25 100644 (file)
@@ -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;
 
 /**
index 8cc4b0b..67ee6b2 100644 (file)
@@ -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;
 }
 
 
index 037d6aa..c6ca824 100755 (executable)
@@ -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.
index 189bc7c..40a5eb7 100644 (file)
@@ -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})
index 70227d3..0c9c3a5 100644 (file)
@@ -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 (file)
index 0000000..69c446c
--- /dev/null
@@ -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 (file)
index 0000000..49247a4
--- /dev/null
@@ -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 (file)
index 0000000..5fb44d0
Binary files /dev/null and b/libparc/parc/security/test/test_ec.p12 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 (file)
index 0000000..d3294e2
Binary files /dev/null and b/libparc/parc/security/test/test_ec_crt.der 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 (file)
index 0000000..22d1e2c
--- /dev/null
@@ -0,0 +1 @@
+Ý!bL?å\9c'Âkàçllýã!çT°\83\ 4h        é~ï\96z~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 (file)
index 0000000..28fbd5a
Binary files /dev/null and b/libparc/parc/security/test/test_ec_key.der 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 (file)
index 0000000..6b0e194
--- /dev/null
@@ -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 (file)
index 0000000..e915040
Binary files /dev/null and b/libparc/parc/security/test/test_ec_pub.der 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 (file)
index 0000000..2ab68ff
--- /dev/null
@@ -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 (file)
index 0000000..c0dd0fa
--- /dev/null
@@ -0,0 +1 @@
+1&,@\87\89\ f\vn\f\7fÈå \9a\84t©¢-DÔ|\8c¶>%\97õ\9ez`
\ 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 (file)
index 0000000..787f8b3
Binary files /dev/null and b/libparc/parc/security/test/test_ec_pub_sha256.bin.sig differ
index f210fd7..4200761 100755 (executable)
@@ -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)
index 4177cc9..3208efc 100644 (file)
@@ -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");
 
index cbc877f..5bcc557 100644 (file)
@@ -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");
 
index 1d8c9b0..81baebc 100755 (executable)
@@ -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 (file)
index 0000000..c007c17
--- /dev/null
@@ -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);
+}
index 1cd004c..17a5b60 100755 (executable)
@@ -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 (file)
index 0000000..f6b1959
--- /dev/null
@@ -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 (file)
index 0000000..417282a
--- /dev/null
@@ -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);
+}
index 0af1aca..49fd42c 100644 (file)
@@ -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);
 
index 9f54da3..4c57d5a 100755 (executable)
@@ -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 (file)
index 0000000..2b6fc57
--- /dev/null
@@ -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);
+}
index 3ddb822..dda9a9f 100755 (executable)
@@ -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 (file)
index 0000000..92b210a
Binary files /dev/null and b/libparc/parc/security/test/test_random_bytes.sig_ec differ