Coverity & ECDSA

Fix one pass of issues discovered by Coverity
Add the support for Direct ECDSA w/ HKDF SHA-256
diff --git a/dumper/dumper.c b/dumper/dumper.c
index 6128856..2f822dd 100644
--- a/dumper/dumper.c
+++ b/dumper/dumper.c
@@ -269,8 +269,14 @@
 
 		fprintf(fp, "%s", t);
 		fprintf(fp, "\n");
+		if (strlen(OutputBuffer) + strlen(iRet + 1) >= sizeof(OutputBuffer)-1) {
+			fprintf(stderr, "Internal buffer too small for dumpping");
+			exit(1);
+		}
 		strcpy(OutputBuffer, iRet + 1);
 	}
+
+	va_end(args);
 }
 
 
diff --git a/src/Encrypt.c b/src/Encrypt.c
index e74c077..6e37da6 100644
--- a/src/Encrypt.c
+++ b/src/Encrypt.c
@@ -232,7 +232,6 @@
 #endif
 	byte * pbAuthData = NULL;
 	size_t cbAuthData;
-	cn_cbor * pAuthData = NULL;
 	byte * pbProtected = NULL;
 	ssize_t cbProtected;
 
@@ -246,7 +245,6 @@
 	errorReturn:
 		if (pbProtected != NULL) COSE_FREE(pbProtected, context);
 		if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-		if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
 		if ((pbKey != NULL) && (pbKeyIn == NULL)) {
 			memset(pbKey, 0xff, cbitKey / 8);
 			COSE_FREE(pbKey, context);
@@ -360,7 +358,6 @@
 
 	if (pbProtected != NULL) COSE_FREE(pbProtected, context);
 	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
 	if ((pbKey != NULL) && (pbKeyIn == NULL)) COSE_FREE(pbKey, context);
 	if (perr != NULL) perr->err = COSE_ERR_NONE;
 
@@ -374,13 +371,13 @@
 	COSE_RecipientInfo * pri;
 	const cn_cbor * cn_Alg = NULL;
 	byte * pbAuthData = NULL;
-	cn_cbor * pAuthData = NULL;
 	cn_cbor * ptmp = NULL;
 	size_t cbitKey;
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context * context = NULL;
 #endif
 	COSE_Enveloped * pcose = (COSE_Enveloped *) h;
+	bool fRet = false;
 
 	CHECK_CONDITION(IsValidEnvelopedHandle(h), COSE_ERR_INVALID_PARAMETER);
 
@@ -495,16 +492,12 @@
 
 	//  Figure out the clean up
 
-	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
-
-	return true;
+	fRet = true;
 
 errorReturn:
 	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
 	if (ptmp != NULL) cn_cbor_free(ptmp CBOR_CONTEXT_PARAM);
-	return false;
+	return fRet;
 }
 
 bool COSE_Enveloped_SetContent(HCOSE_ENVELOPED h, const byte * rgb, size_t cb, cose_errback * perror)
diff --git a/src/MacMessage.c b/src/MacMessage.c
index b00f6df..30c9199 100644
--- a/src/MacMessage.c
+++ b/src/MacMessage.c
@@ -277,6 +277,7 @@
 #endif
 	COSE_MacMessage * pcose = (COSE_MacMessage *)h;
 	cn_cbor_errback cbor_error;
+	bool fRet = false;
 
 	CHECK_CONDITION(IsValidMacHandle(h), COSE_ERR_INVALID_PARAMETER);
 
@@ -426,16 +427,13 @@
 
 	//  Figure out the clean up
 
-	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
-	if (ptmp != NULL) cn_cbor_free(ptmp CBOR_CONTEXT_PARAM);
-	return true;
+	fRet = true;
 
 errorReturn:
 	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
 	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
 	if (ptmp != NULL) cn_cbor_free(ptmp CBOR_CONTEXT_PARAM);
-	return false;
+	return fRet;
 }
 
 byte RgbDontUseMac[1024];
diff --git a/src/Recipient.c b/src/Recipient.c
index ddbdf9a..9ce9f05 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -133,6 +133,9 @@
 	size_t cbContext;
 	byte rgbDigest[512 / 8];
 	size_t cbDigest;
+	cn_cbor * pkey = NULL;
+	byte * pbSecret = NULL;
+	size_t cbSecret;
 
 #ifdef USE_CBOR_CONTEXT
 	context = &pcose->m_message.m_allocContext;
@@ -145,10 +148,7 @@
 		if (pbProtected != NULL) COSE_FREE(pbProtected, context);
 		if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
 		if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
-		if ((pbKey != NULL) && (pbKeyIn == NULL)) {
-			memset(pbKey, 0xff, cbitKey / 8);
-			COSE_FREE(pbKey, context);
-		}
+		if (pbSecret != NULL) COSE_FREE(pbSecret, context);
 		return false;
 	}
 	CHECK_CONDITION((cn->type == CN_CBOR_UINT) || (cn->type == CN_CBOR_INT), COSE_ERR_INVALID_PARAMETER);
@@ -182,18 +182,14 @@
 	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_512:
 		break;
 
+	case COSE_Algorithm_ECDH_ES_HKDF_256:
+		break;
+
 	default:
 		FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
 		break;
 	}
 
-	//  Allocate the key if we have not already done so
-
-	if (pbKey == NULL) {
-		pbKey = COSE_CALLOC(cbitKey / 8, 1, context);
-		CHECK_CONDITION(pbKey != NULL, COSE_ERR_OUT_OF_MEMORY);
-	}
-
 	//  If there is a recipient - ask it for the key
 
 	for (pRecip2 = pcose->m_recipientFirst; pRecip2 != NULL; pRecip2 = pRecip->m_recipientNext) {
@@ -263,6 +259,21 @@
 		if (!HKDF_AES_Expand(&pcose->m_message, 256, cn->v.bytes, cn->length, pbContext, cbContext, pbKey, cbitKey / 8, perr)) goto errorReturn;
 		break;
 
+	case COSE_Algorithm_ECDH_ES_HKDF_256:
+		if (!BuildContextBytes(&pcose->m_message, algIn, cbitKey, &pbContext, &cbContext, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+
+		pkey = _COSE_map_get_int(&pcose->m_message, COSE_Header_ECDH_EPHEMERAL, COSE_BOTH, perr);
+		if (pkey == NULL) goto errorReturn;
+
+		CHECK_CONDITION(pRecip->m_pkey != NULL, COSE_ERR_INVALID_PARAMETER);
+		if (!ECDH_ComputeSecret(&pcose->m_message, (cn_cbor **) &pRecip->m_pkey, pkey, &pbSecret, &cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+
+		if (!HKDF_Extract(&pcose->m_message, pbSecret, cbSecret, 256, rgbDigest, &cbDigest, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+
+		if (!HKDF_Expand(&pcose->m_message, 256, rgbDigest, cbDigest, pbContext, cbContext, pbKey, cbitKey / 8, perr)) goto errorReturn;
+
+		break;
+
 	default:
 		FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
 		break;
@@ -278,13 +289,13 @@
 	COSE_RecipientInfo * pri;
 	const cn_cbor * cn_Alg = NULL;
 	byte * pbAuthData = NULL;
-	cn_cbor * pAuthData = NULL;
 	cn_cbor * ptmp = NULL;
 	size_t cbitKey;
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context * context = NULL;
 #endif
 	cn_cbor_errback cbor_error;
+	bool fRet = false;
 
 #ifdef USE_CBOR_CONTEXT
 	context = &pRecipient->m_encrypt.m_message.m_allocContext;
@@ -304,6 +315,8 @@
 	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_512:
 	case COSE_Algorithm_Direct_HKDF_AES_128:
 	case COSE_Algorithm_Direct_HKDF_AES_256:
+	case COSE_Algorithm_ECDH_ES_HKDF_256:
+	case COSE_Algorithm_ECDH_ES_HKDF_512:
 		//  This is a NOOP
 		cbitKey = 0;
 		CHECK_CONDITION(pRecipient->m_encrypt.m_recipientFirst == NULL, COSE_ERR_INVALID_PARAMETER);
@@ -369,9 +382,12 @@
 	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_512:
 	case COSE_Algorithm_Direct_HKDF_AES_128:
 	case COSE_Algorithm_Direct_HKDF_AES_256:
+	case COSE_Algorithm_ECDH_ES_HKDF_256:
+	case COSE_Algorithm_ECDH_ES_HKDF_512:
 		ptmp = cn_cbor_data_create(NULL, 0, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
 		CHECK_CONDITION_CBOR(ptmp != NULL, cbor_error);
 		CHECK_CONDITION_CBOR(_COSE_array_replace(&pRecipient->m_encrypt.m_message, ptmp, INDEX_BODY, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
+		ptmp = NULL;
 		break;
 
 
@@ -398,16 +414,12 @@
 
 	//  Figure out the clean up
 
-	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
-
-	return true;
+	fRet = true;
 
 errorReturn:
 	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
 	if (ptmp != NULL) cn_cbor_free(ptmp CBOR_CONTEXT_PARAM);
-	return false;
+	return fRet;
 }
 
 byte * _COSE_RecipientInfo_generateKey(COSE_RecipientInfo * pRecipient, int algIn, size_t cbitKeySize, cose_errback * perr)
@@ -423,6 +435,9 @@
 	const cn_cbor * pK;
 	byte rgbDigest[512 / 8];
 	size_t cbDigest;
+	cn_cbor * pkey;
+	byte *pbSecret = NULL;
+	size_t cbSecret;
 
 	CHECK_CONDITION(cn_Alg != NULL, COSE_ERR_INVALID_PARAMETER);
 	CHECK_CONDITION((cn_Alg->type == CN_CBOR_UINT) || (cn_Alg->type == CN_CBOR_INT), COSE_ERR_INVALID_PARAMETER);
@@ -504,6 +519,26 @@
 
 		break;
 
+	case COSE_Algorithm_ECDH_ES_HKDF_256:
+		if (!BuildContextBytes(&pRecipient->m_encrypt.m_message, algIn, cbitKeySize, &pbContext, &cbContext, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+
+		pkey = _COSE_map_get_int(&pRecipient->m_encrypt.m_message, COSE_Header_ECDH_EPHEMERAL, COSE_BOTH, perr);
+
+		if (!ECDH_ComputeSecret(&pRecipient->m_encrypt.m_message, &pkey, pRecipient->m_pkey, &pbSecret, &cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+
+		if (pkey->parent == NULL) {
+			if (!_COSE_map_put(&pRecipient->m_encrypt.m_message, COSE_Header_ECDH_EPHEMERAL, pkey, COSE_UNPROTECT_ONLY, perr)) goto errorReturn;
+		}
+
+		pb = COSE_CALLOC(cbitKeySize / 8, 1, context);
+		CHECK_CONDITION(pb != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+		if (!HKDF_Extract(&pRecipient->m_encrypt.m_message, pbSecret, cbSecret, 256, rgbDigest, &cbDigest, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+
+		if (!HKDF_Expand(&pRecipient->m_encrypt.m_message, 256, rgbDigest, cbDigest, pbContext, cbContext, pb, cbitKeySize / 8, perr)) goto errorReturn;
+
+		break;
+
 	case COSE_Algorithm_ECDH_SS_HKDF_256: {
 		//  Need to have a key and it needs to be the correct type of key.
 		if ((pRecipient->m_pkey == NULL) || (cn_cbor_mapget_int(pRecipient->m_pkey, 1)->v.uint != 2)) return NULL;
@@ -511,14 +546,16 @@
 	}
 
 	default:
-		return NULL;
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
 	}
 
+	if (pbSecret != NULL) COSE_FREE(pbSecret, context);
 	if (pbContext != NULL) COSE_FREE(pbContext, context);
 	return pb;
 
 errorReturn:
 
+	if (pbSecret != NULL) COSE_FREE(pbSecret, context);
 	if (pbContext != NULL) COSE_FREE(pbContext, context);
 	if (pb != NULL) COSE_FREE(pb, context);
 	return NULL;
diff --git a/src/Sign.c b/src/Sign.c
index 450a17a..d2c3d98 100644
--- a/src/Sign.c
+++ b/src/Sign.c
@@ -242,7 +242,7 @@
 	CHECK_CONDITION(cnContent != NULL && cnContent->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
 
 	cnProtected = _COSE_arrayget_int(&pSign->m_message, INDEX_PROTECTED);
-	CHECK_CONDITION(cnProtected != NULL && cnContent->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(cnProtected != NULL && cnProtected->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
 
 	f = _COSE_Signer_validate(pSign, pSigner, cnContent, cnProtected, perr);
 
diff --git a/src/Sign0.c b/src/Sign0.c
index 6749ef4..109fd25 100644
--- a/src/Sign0.c
+++ b/src/Sign0.c
@@ -164,7 +164,7 @@
 	CHECK_CONDITION(cnContent != NULL && cnContent->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
 
 	cnProtected = _COSE_arrayget_int(&pSign->m_message, INDEX_PROTECTED);
-	CHECK_CONDITION(cnProtected != NULL && cnContent->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(cnProtected != NULL && cnProtected->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
 
 	f = _COSE_Signer0_validate(pSign, pKey,  perr);
 
@@ -331,8 +331,8 @@
 	cn_cbor_context * context = NULL;
 #endif
 	size_t cbToSign;
-	cn_cbor * pAuthData = NULL;
 	cn_cbor * cnSignature = NULL;
+	bool fRet = false;
 
 #ifdef USE_CBOR_CONTEXT
 	context = &pSign->m_message.m_allocContext;
@@ -374,14 +374,10 @@
 		break;
 	}
 
-	if (pbToSign != NULL) COSE_FREE(pbToSign, context);
-	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
-
-	return true;
+	fRet = true;
 
 errorReturn:
 	if (pbToSign != NULL) COSE_FREE(pbToSign, context);
-	if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM);
 
-	return false;
+	return fRet;
 }
diff --git a/src/cose.h b/src/cose.h
index d3aa969..d7c814e 100644
--- a/src/cose.h
+++ b/src/cose.h
@@ -147,6 +147,10 @@
 
 	COSE_Header_KDF_PUB_other = -999,
 	COSE_Header_KDF_PRIV = -998,
+
+	COSE_Header_ECDH_EPHEMERAL = -1,
+	COSE_Header_ECDH_STATIC = -2
+
 } COSE_Header;
 
 typedef enum {
diff --git a/src/crypto.h b/src/crypto.h
index d5a8f46..232a927 100644
--- a/src/crypto.h
+++ b/src/crypto.h
@@ -63,6 +63,8 @@
 bool ECDSA_Sign(COSE * pSigner, int index, const cn_cbor * pKey, int cbitsDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr);
 bool ECDSA_Verify(COSE * pSigner, int index, const cn_cbor * pKey, int cbitsDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr);
 
+bool ECDH_ComputeSecret(COSE * pReciient, cn_cbor ** ppKeyMe, const cn_cbor * pKeyYou, byte ** ppbSecret, size_t * pcbSecret, CBOR_CONTEXT_COMMA cose_errback *perr);
+
 /**
 *  Generate random bytes in a buffer
 *
diff --git a/src/openssl.c b/src/openssl.c
index 351b76e..d441d2c 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -13,6 +13,7 @@
 #include <openssl/cmac.h>
 #include <openssl/hmac.h>
 #include <openssl/ecdsa.h>
+#include <openssl/ecdh.h>
 #include <openssl/rand.h>
 
 #define MIN(A, B) ((A) < (B) ? (A) : (B))
@@ -825,6 +826,67 @@
 	return NULL;
 }
 
+cn_cbor * EC_FromKey(const EC_KEY * pKey, CBOR_CONTEXT_COMMA cose_errback * perr)
+{
+	cn_cbor * pkey = NULL;
+	const EC_GROUP * pgroup;
+	int cose_group;
+	cn_cbor * p = NULL;
+	cn_cbor_errback cbor_error;
+	const EC_POINT * pPoint;
+	size_t cbSize;
+	byte * pbOut = NULL;
+
+	pgroup = EC_KEY_get0_group(pKey);
+
+	switch (EC_GROUP_get_curve_name(pgroup)) {
+	case NID_X9_62_prime256v1:
+		cose_group = 1;
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
+
+	pkey = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(pkey != NULL, cbor_error);
+
+	p = cn_cbor_int_create(cose_group, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(p != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_EC_Curve, p, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
+	p = NULL;
+
+	pPoint = EC_KEY_get0_public_key(pKey);
+	CHECK_CONDITION(pPoint != NULL, COSE_ERR_INVALID_PARAMETER);
+
+	cbSize = EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
+	CHECK_CONDITION(cbSize > 0, COSE_ERR_CRYPTO_FAIL);
+	pbOut = COSE_CALLOC(cbSize, 1, context);
+	CHECK_CONDITION(pbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+	CHECK_CONDITION(EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_UNCOMPRESSED, pbOut, cbSize, NULL) == cbSize, COSE_ERR_CRYPTO_FAIL);
+
+	p = cn_cbor_data_create(pbOut+1, (int) (cbSize / 2), CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(p != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_EC_X, p, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
+	p = NULL;
+
+	p = cn_cbor_data_create(pbOut + cbSize / 2+1, (int) (cbSize / 2), CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	pbOut = NULL;   // It is already part of the other one.
+	CHECK_CONDITION_CBOR(p != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_EC_Y, p, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
+	p = NULL;
+
+returnHere:
+	if (pbOut != NULL) COSE_FREE(pbOut, context);
+	if (p != NULL) CN_CBOR_FREE(p, context);
+	return pkey;
+
+errorReturn:
+	CN_CBOR_FREE(pkey, context);
+	pkey = NULL;
+	goto returnHere;
+}
+
 /*
 bool ECDSA_Sign(const cn_cbor * pKey)
 {
@@ -860,6 +922,7 @@
 	eckey = ECKey_From(pKey, &cbR, perr);
 	if (eckey == NULL) {
 	errorReturn:
+		if (pbSig != NULL) COSE_FREE(pbSig, context);
 		if (p != NULL) CN_CBOR_FREE(p, context);
 		if (eckey != NULL) EC_KEY_free(eckey);
 		return false;
@@ -894,6 +957,10 @@
 
 	CHECK_CONDITION(_COSE_array_replace(pSigner, p, index, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
 	
+	pbSig = NULL;
+
+	if (eckey != NULL) EC_KEY_free(eckey);
+
 	return true;
 }
 
@@ -1000,4 +1067,51 @@
 	RAND_bytes(pb, (int) cb);
 }
 
+bool ECDH_ComputeSecret(COSE * pRecipient, cn_cbor ** ppKeyMe, const cn_cbor * pKeyYou, byte ** ppbSecret, size_t * pcbSecret, CBOR_CONTEXT_COMMA cose_errback *perr)
+{
+	EC_KEY * pkeyMe = NULL;
+	EC_KEY * pkeyYou = NULL;
+	int cbGroup;
+	int cbsecret;
+	byte * pbsecret = NULL;
+
+	pkeyYou = ECKey_From(pKeyYou, &cbGroup, perr);
+	if (pkeyYou == NULL) goto errorReturn;
+
+	if (*ppKeyMe == NULL) {
+		pkeyMe = EC_KEY_new();
+		EC_KEY_set_group(pkeyMe, EC_KEY_get0_group(pkeyYou));
+		CHECK_CONDITION(EC_KEY_generate_key(pkeyMe) == 1, COSE_ERR_CRYPTO_FAIL);
+		*ppKeyMe = EC_FromKey(pkeyMe, CBOR_CONTEXT_PARAM_COMMA perr);
+		if (*ppKeyMe == NULL) goto errorReturn;
+	}
+	else {
+		pkeyMe = ECKey_From(*ppKeyMe, &cbGroup, perr);
+		if (pkeyMe == NULL) goto errorReturn;
+	}
+
+	pbsecret = COSE_CALLOC(cbGroup, 1, context);
+	CHECK_CONDITION(pbsecret != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	cbsecret = ECDH_compute_key(pbsecret, cbGroup, EC_KEY_get0_public_key(pkeyYou), pkeyMe, NULL);
+	CHECK_CONDITION(cbsecret != 0, COSE_ERR_CRYPTO_FAIL);
+
+	*ppbSecret = pbsecret;
+	*pcbSecret = cbsecret;
+	pbsecret = NULL;
+
+	if (pkeyMe != NULL) EC_KEY_free(pkeyMe);
+	if (pkeyYou != NULL) EC_KEY_free(pkeyYou);
+
+	return true;
+
+errorReturn:
+	if (pbsecret != NULL) COSE_FREE(pbsecret, context);
+	if (pkeyMe != NULL) EC_KEY_free(pkeyMe);
+	if (pkeyYou != NULL) EC_KEY_free(pkeyYou);
+
+	return false;
+
+}
+
 #endif // USE_OPEN_SSL
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index ecd4054..1a4c22f 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -38,6 +38,7 @@
 add_test ( NAME sig-03 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/spec-examples/Sig-03.json )
 add_test ( NAME sig-04 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/spec-examples/Sig-04.json )
 
+add_test ( NAME enc-01 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/spec-examples/Enc-01.json )
 add_test ( NAME enc-02 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/spec-examples/Enc-02.json )
 add_test ( NAME enc-04 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/spec-examples/Enc-04.json )
 add_test ( NAME enc-05 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test Examples/spec-examples/Enc-05.json )
diff --git a/test/json.c b/test/json.c
index 184614e..975b2d7 100644
--- a/test/json.c
+++ b/test/json.c
@@ -34,15 +34,16 @@
 			node = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA NULL);
 			break;
 
-		case '}':
-			parent = parent->parent;
-			break;
-
 		case '[':
 			node = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
 			break;
 
+		case '}':
 		case ']':
+			if (parent == NULL) {
+				fprintf(stderr, "Parse failure @ '%s'\n", &rgch[ib]);
+				return NULL;
+			}
 			parent = parent->parent;
 			break;
 
@@ -93,7 +94,7 @@
 		default:
 			error:
 			fprintf(stderr, "Parse failure @ '%s'\n", &rgch[ib]);
-			break;
+			return NULL;
 		}
 
 		if ((node != NULL) && (parent != NULL)) {
@@ -124,14 +125,16 @@
 const cn_cbor * ParseJson(const char * fileName)
 {
 	int     cch;
-	char *	rgch = malloc(8 * 1024);
+	char *	rgch;
     FILE * fp = fopen(fileName, "r");
 
 	if (fp == NULL) {
 		fprintf(stderr, "Cannot open file '%s'\n", fileName);
+		
 		return NULL;
 	}
 
+	rgch = malloc(8 * 1024);
 	cch = (int) fread(rgch, 1, 8*1024, fp);
 	fclose(fp);
 
@@ -205,7 +208,10 @@
 	if (data[input_length - 2] == '=') (*output_length)--;
 
 	unsigned char *decoded_data = malloc(*output_length);
-	if (decoded_data == NULL) return NULL;
+	if (decoded_data == NULL) {
+		if (p != NULL) free(p);
+		return NULL;
+	}
 
 	for (unsigned int i = 0, j = 0; i < input_length;) {
 
diff --git a/test/test.c b/test/test.c
index 2395be7..d706217 100644
--- a/test/test.c
+++ b/test/test.c
@@ -28,7 +28,7 @@
 	int    i;
 } NameMap;
 
-NameMap RgAlgorithmNames[30] = {
+NameMap RgAlgorithmNames[31] = {
 	{"HS256", COSE_Algorithm_HMAC_256_256},
 	{"HS256/64", COSE_Algorithm_HMAC_256_64},
 	{"HS384", COSE_Algorithm_HMAC_384_384},
@@ -59,6 +59,7 @@
 	{"HKDF-HMAC-SHA-512", COSE_Algorithm_Direct_HKDF_HMAC_SHA_512},
 	{"HKDF-AES-128", COSE_Algorithm_Direct_HKDF_AES_128},
 	{"HKDF-AES-256", COSE_Algorithm_Direct_HKDF_AES_256},
+	{"ECDH-ES", COSE_Algorithm_ECDH_ES_HKDF_256}
 };
 
 
@@ -609,6 +610,10 @@
 	HANDLE hFind;
 	char rgchFullName[2 * 1024];
 
+	if (strlen(szDir) + 7 >= sizeof(rgchFullName)) {
+		fprintf(stderr, "Buffer overflow error\n");
+		exit(1);
+	}
 	strcpy(rgchFullName, szDir);
 	strcat(rgchFullName, "\\");
 	size_t ich = strlen(rgchFullName);
@@ -623,6 +628,10 @@
 
 	do {
 		rgchFullName[ich] = 0;
+		if (ich + strlen(FindFileData.cFileName) >= sizeof(rgchFullName)) {
+			fprintf(stderr, "Buffer overflow problem\n");
+			exit(1);
+		}
 		strcat(rgchFullName, FindFileData.cFileName);
 		printf("Run test '%s'", rgchFullName);
 
@@ -645,7 +654,6 @@
 	DIR * dirp = opendir(szDir);
 	struct dirent * dp;
 	char rgchFullName[2 * 1024];
-	strcpy(rgchFullName, szDir);
 	int ich;
 	int cFailTotal = 0;
 
@@ -653,6 +661,11 @@
 		fprintf(stderr, "Cannot open directory '%s'\n", szDir);
 		exit(1);
 	}
+	if (strlen(szDir) >= sizeof(rgchFullName) - 3) {
+		fprintf(stderr, "Buffer overflow problem\n");
+		exit(1);
+	}
+	strcpy(rgchFullName, szDir);
 	strcat(rgchFullName, "/");
 	ich = strlen(rgchFullName);
 
@@ -660,6 +673,10 @@
 		int cch = strlen(dp->d_name);
 		if (cch < 4) continue;
 		rgchFullName[ich] = 0;
+		if (ich + strlen(dp->d_name) >= sizeof(rgchFullName) - 2) {
+			fprintf(stderr, "Buffer overflow problem\n");
+			exit(1);
+		}
 		strcat(rgchFullName, dp->d_name);
 		printf("Run test '%s'", rgchFullName);
 		CFails = 0;