Merge pull request #33 from jimsch/master

Change how static static keys are added for sending
diff --git a/src/Cose.c b/src/Cose.c
index 612f761..382a4ce 100644
--- a/src/Cose.c
+++ b/src/Cose.c
@@ -281,6 +281,9 @@
 	if ((pcose->m_dontSendMap != NULL) && ((flags & COSE_DONT_SEND) != 0)) {
 		p = cn_cbor_mapget_int(pcose->m_dontSendMap, key);
 	}
+
+	if ((p == NULL) && (perror != NULL)) perror->err = COSE_ERR_INVALID_PARAMETER;
+
 	return p;
 }
 
@@ -313,6 +316,7 @@
 #endif
 	cn_cbor_errback error;
 	bool f = false;
+	CHECK_CONDITION(value != NULL, COSE_ERR_INVALID_PARAMETER);
 
 	CHECK_CONDITION(cn_cbor_mapget_int(pCose->m_protectedMap, key) == NULL, COSE_ERR_INVALID_PARAMETER);
 	CHECK_CONDITION(cn_cbor_mapget_int(pCose->m_unprotectMap, key) == NULL, COSE_ERR_INVALID_PARAMETER);
@@ -328,10 +332,6 @@
 		break;
 
 	case COSE_DONT_SEND:
-		if (pCose->m_dontSendMap == NULL) {
-			pCose->m_dontSendMap = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &error);
-			CHECK_CONDITION(pCose->m_dontSendMap != NULL, COSE_ERR_OUT_OF_MEMORY);
-		}
 		f = cn_cbor_mapput_int(pCose->m_dontSendMap, key, value, CBOR_CONTEXT_PARAM_COMMA &error);
 		break;
 
diff --git a/src/Encrypt.c b/src/Encrypt.c
index 48cb54e..6c39d06 100644
--- a/src/Encrypt.c
+++ b/src/Encrypt.c
@@ -513,6 +513,18 @@
 	return true;
 }
 
+/*! brief Retrieve header parameter from an enveloped message structure
+*
+* Retrieve a header parameter from the message.
+* Retrieved object is the same as the one in the message - do not delete it
+*
+* @param[in]	h	Handle of recipient object
+* @param[in]    key	Key to look for
+* @param[in]	flags	What buckets should we look for the message
+* @param[out]	perror	Location to return error codes
+* @return	Object which is found or NULL
+*/
+
 cn_cbor * COSE_Enveloped_map_get_int(HCOSE_ENVELOPED h, int key, int flags, cose_errback * perror)
 {
 	if (!IsValidEnvelopedHandle(h)) {
diff --git a/src/Recipient.c b/src/Recipient.c
index 63b659b..c8e524a 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -128,7 +128,8 @@
 *
 * @param[in]	COSE *		Pointer to COSE Encryption context object
 * @param[in]	int			Alorithm key is being generated for
-* @param[in]	cn_cbor *	Key used for operation
+* @param[in]	cn_cbor *	Private key
+* @param[in]	cn_cbor *	Public Key
 * @param[out]	byte *		Buffer to return new key in	
 * @param[in]	size_t       Size of key to create in bits
 * @param[in]    size_t		Size of digest function
@@ -137,7 +138,7 @@
 * @return                   Did the function succeed?
 */
 
-static bool HKDF_X(COSE * pCose, bool fHMAC, bool fECDH, bool fStatic, bool fSend, int algResult, const cn_cbor * pKey, byte * pbKey, size_t cbitKey, size_t cbitHash, CBOR_CONTEXT_COMMA cose_errback * perr)
+static bool HKDF_X(COSE * pCose, bool fHMAC, bool fECDH, bool fStatic, bool fSend, int algResult, const cn_cbor * pKeyPrivate, const cn_cbor * pKeyPublic, byte * pbKey, size_t cbitKey, size_t cbitHash, CBOR_CONTEXT_COMMA cose_errback * perr)
 {
 	byte * pbContext = NULL;
 	size_t cbContext;
@@ -150,30 +151,50 @@
 
 	if (!BuildContextBytes(pCose, algResult, cbitKey, &pbContext, &cbContext, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
-	cn = cn_cbor_mapget_int(pKey, COSE_Key_Type);
-	CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_UINT), COSE_ERR_INVALID_PARAMETER);
 
 	if (fECDH) {
 		cn_cbor * pkeyMessage;
 
-		pkeyMessage = _COSE_map_get_int(pCose, fStatic ? COSE_Header_ECDH_STATIC : COSE_Header_ECDH_EPHEMERAL, COSE_BOTH, perr);
+		if (pKeyPrivate != NULL) {
+			cn = cn_cbor_mapget_int(pKeyPrivate, COSE_Key_Type);
+			CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_UINT), COSE_ERR_INVALID_PARAMETER);
+			CHECK_CONDITION(cn->v.uint == COSE_Key_Type_EC2, COSE_ERR_INVALID_PARAMETER);
+		}
 
-		CHECK_CONDITION(pKey != NULL, COSE_ERR_INVALID_PARAMETER);
+		if (pKeyPublic != NULL) {
+			cn = cn_cbor_mapget_int(pKeyPublic, COSE_Key_Type);
+			CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_UINT), COSE_ERR_INVALID_PARAMETER);
+			CHECK_CONDITION(cn->v.uint == COSE_Key_Type_EC2, COSE_ERR_INVALID_PARAMETER);
+		}
+
 		if (fSend) {
-			if (!ECDH_ComputeSecret(pCose, &pkeyMessage, pKey, &pbSecret, &cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+			CHECK_CONDITION(pKeyPublic != NULL, COSE_ERR_INVALID_PARAMETER);
+			pkeyMessage = (cn_cbor *) pKeyPrivate;
+
+			if (!ECDH_ComputeSecret(pCose, &pkeyMessage, pKeyPublic, &pbSecret, &cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 			if (pkeyMessage->parent == NULL) {
 				if (!_COSE_map_put(pCose, COSE_Header_ECDH_EPHEMERAL, pkeyMessage, COSE_UNPROTECT_ONLY, perr)) goto errorReturn;
 			}
 		}
 		else {
+
+			pkeyMessage = _COSE_map_get_int(pCose, fStatic ? COSE_Header_ECDH_STATIC : COSE_Header_ECDH_EPHEMERAL, COSE_BOTH, perr);
+
 			CHECK_CONDITION(pkeyMessage != NULL, COSE_ERR_INVALID_PARAMETER);
-			if (!ECDH_ComputeSecret(pCose, (cn_cbor **)&pKey, pkeyMessage, &pbSecret, &cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+			CHECK_CONDITION(pKeyPrivate != NULL, COSE_ERR_INVALID_PARAMETER);
+
+			if (!ECDH_ComputeSecret(pCose, (cn_cbor **)&pKeyPrivate, pkeyMessage, &pbSecret, &cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		}
 	}
 	else {
+		CHECK_CONDITION(pKeyPrivate != NULL, COSE_ERR_INVALID_PARAMETER);
+			cn = cn_cbor_mapget_int(pKeyPrivate, COSE_Key_Type);
+			CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_UINT), COSE_ERR_INVALID_PARAMETER);
+			CHECK_CONDITION(cn->v.uint == COSE_Key_Type_OCTET, COSE_ERR_INVALID_PARAMETER);
+
 		CHECK_CONDITION(cn->v.sint == 4, COSE_ERR_INVALID_PARAMETER);
 
-		cn = cn_cbor_mapget_int(pKey, -1);
+		cn = cn_cbor_mapget_int(pKeyPrivate, -1);
 		CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
 		pbSecret = (byte *) cn->v.bytes;
 		cbSecret = cn->length;
@@ -299,74 +320,74 @@
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_256:
-		if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_512:
-		if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_AES_128:
-		if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 128, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 128, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_AES_256:
-		if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_HKDF_256:
-		if (!HKDF_X(&pcose->m_message, true, true, false, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_HKDF_512:
-		if (!HKDF_X(&pcose->m_message, true, true, false, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_HKDF_256:
-		if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_HKDF_512:
-		if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_A128KW:
-		if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_128, pRecip->m_pkey, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_128, pRecip->m_pkey, NULL, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 128, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
 
 		break;
 
 	case COSE_Algorithm_ECDH_ES_A192KW:
-		if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_192, pRecip->m_pkey, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_192, pRecip->m_pkey, NULL, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 192, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
 
 		break;
 
 	case COSE_Algorithm_ECDH_ES_A256KW:
-		if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_256, pRecip->m_pkey, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_256, pRecip->m_pkey, NULL, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 256, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
 
 		break;
 
 	case COSE_Algorithm_ECDH_SS_A128KW:
-		if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_128, pRecip->m_pkey, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_128, pRecip->m_pkey, NULL, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 128, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
 
 		break;
 
 	case COSE_Algorithm_ECDH_SS_A192KW:
-		if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_192, pRecip->m_pkey, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_192, pRecip->m_pkey, NULL, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 192, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
 
 		break;
 
 	case COSE_Algorithm_ECDH_SS_A256KW:
-		if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_256, pRecip->m_pkey, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_256, pRecip->m_pkey, NULL, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 256, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
 
@@ -518,32 +539,32 @@
 		break;
 
 	case COSE_Algorithm_ECDH_ES_A128KW:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, COSE_Algorithm_AES_KW_128, pRecipient->m_pkey, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, COSE_Algorithm_AES_KW_128, NULL, pRecipient->m_pkey, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		if (!AES_KW_Encrypt(pRecipient, rgbKey, 128, pbContent, (int)cbContent, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_A192KW:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, COSE_Algorithm_AES_KW_192, pRecipient->m_pkey, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, COSE_Algorithm_AES_KW_192, NULL, pRecipient->m_pkey, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		if (!AES_KW_Encrypt(pRecipient, rgbKey, 192, pbContent, (int)cbContent, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_A256KW:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, COSE_Algorithm_AES_KW_256, pRecipient->m_pkey, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, COSE_Algorithm_AES_KW_256, NULL, pRecipient->m_pkey, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		if (!AES_KW_Encrypt(pRecipient, rgbKey, 256, pbContent, (int)cbContent, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_A128KW:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, COSE_Algorithm_AES_KW_128, pRecipient->m_pkey, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, COSE_Algorithm_AES_KW_128, pRecipient->m_pkeyStatic, pRecipient->m_pkey, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		if (!AES_KW_Encrypt(pRecipient, rgbKey, 128, pbContent, (int)cbContent, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_A192KW:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, COSE_Algorithm_AES_KW_192, pRecipient->m_pkey, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, COSE_Algorithm_AES_KW_192, pRecipient->m_pkeyStatic, pRecipient->m_pkey, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		if (!AES_KW_Encrypt(pRecipient, rgbKey, 192, pbContent, (int)cbContent, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_A256KW:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, COSE_Algorithm_AES_KW_256, pRecipient->m_pkey, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, COSE_Algorithm_AES_KW_256, pRecipient->m_pkeyStatic, pRecipient->m_pkey, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		if (!AES_KW_Encrypt(pRecipient, rgbKey, 256, pbContent, (int)cbContent, perr)) goto errorReturn;
 		break;
 
@@ -603,35 +624,35 @@
 	break;
 
 	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_256:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, false, false, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, false, false, true, algIn, pRecipient->m_pkey, NULL, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_512:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, false, false, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, false, false, true, algIn, pRecipient->m_pkey, NULL, pb, cbitKeySize, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_AES_128:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, false, false, false, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 128, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, false, false, false, true, algIn, pRecipient->m_pkey, NULL, pb, cbitKeySize, 128, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_AES_256:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, false, false, false, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, false, false, false, true, algIn, pRecipient->m_pkey, NULL, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_HKDF_256:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, algIn, NULL, pRecipient->m_pkey, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_HKDF_512:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, algIn, NULL, pRecipient->m_pkey, pb, cbitKeySize, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_HKDF_256:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, algIn, pRecipient->m_pkeyStatic, pRecipient->m_pkey, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_HKDF_512:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, algIn, pRecipient->m_pkeyStatic, pRecipient->m_pkey, pb, cbitKeySize, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	default:
@@ -659,13 +680,11 @@
 	byte * pbTemp = NULL;
 	byte * pbKey = NULL;
 #ifdef USE_CBOR_CONTEXT
-	cn_cbor_context * context;
+	cn_cbor_context * context = NULL;
 #endif
 
-	if (!IsValidRecipientHandle(hRecipient) || (rgbKey == NULL)) {
-		if (perr != NULL) perr->err = COSE_ERR_CBOR;
-		return false;
-	}
+	CHECK_CONDITION(IsValidRecipientHandle(hRecipient), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(rgbKey != NULL, COSE_ERR_INVALID_PARAMETER);
 
 	p = (COSE_RecipientInfo *)hRecipient;
 
@@ -680,7 +699,7 @@
 	else {
 		cn_Temp = cn_cbor_int_create(COSE_Algorithm_Direct, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
 		CHECK_CONDITION_CBOR(cn_Temp != NULL, cbor_error);
-		if (!COSE_Recipient_map_put(hRecipient, COSE_Header_Algorithm, cn_Temp, COSE_UNPROTECT_ONLY, perr)) goto errorReturn;
+		if (!COSE_Recipient_map_put_int(hRecipient, COSE_Header_Algorithm, cn_Temp, COSE_UNPROTECT_ONLY, perr)) goto errorReturn;
 		cn_Temp = NULL;
 	}
 
@@ -693,7 +712,7 @@
 		CHECK_CONDITION_CBOR(cnTemp != NULL, cbor_error);
 		pbTemp = NULL;
 
-		if (!COSE_Recipient_map_put(hRecipient, COSE_Header_KID, cnTemp, COSE_UNPROTECT_ONLY, perr)) goto errorReturn;
+		if (!COSE_Recipient_map_put_int(hRecipient, COSE_Header_KID, cnTemp, COSE_UNPROTECT_ONLY, perr)) goto errorReturn;
 	}
 
 	pbKey = (byte *)COSE_CALLOC(cbKey, 1, context);
@@ -728,21 +747,111 @@
 	return false;
 }
 
-bool COSE_Recipient_SetKey(HCOSE_RECIPIENT h, const cn_cbor * pKey, cose_errback * perror)
+bool COSE_Recipient_SetKey(HCOSE_RECIPIENT h, const cn_cbor * pKey, cose_errback * perr)
 {
 	COSE_RecipientInfo * p;
 
-	if (!IsValidRecipientHandle(h) || (pKey == NULL)) {
-		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
-		return false;
-	}
-
-
+	CHECK_CONDITION(IsValidRecipientHandle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pKey != NULL, COSE_ERR_INVALID_PARAMETER);
 
 	p = (COSE_RecipientInfo *)h;
 	p->m_pkey = pKey;
 
 	return true;
+
+errorReturn:
+	return false;
+}
+
+/*!
+* @brief Set the senders static key for ECDH key agreement algorithms
+*
+* Set the Static private key to be used in computing ECDH key agreement
+* operation.  
+*
+* Private portion of the key is not zeroed when the recipient object is
+* released.
+*
+* @param h  Handle to the recipient object
+* @param pKey pointer to COSE key structure contiaing the private key
+* @param destination 0 - set nothing, 1 - set spk_kid, 2 - set spk
+* @param perr location for return of error code
+* @return true on success
+*/
+
+bool COSE_Recipient_SetSenderKey(HCOSE_RECIPIENT h, const cn_cbor * pKey, int destination, cose_errback * perr)
+{
+	COSE_RecipientInfo * p;
+	bool f = false;
+	cn_cbor * cn;
+	cn_cbor * cn2 = NULL;
+	cn_cbor * cn3 = NULL;
+	cn_cbor_errback cbor_err;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = NULL;
+#endif
+
+	CHECK_CONDITION(IsValidRecipientHandle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pKey != NULL, COSE_ERR_INVALID_PARAMETER);
+
+	p = (COSE_RecipientInfo *)h;
+
+#ifdef USE_CBOR_CONTEXT
+	context = &p->m_encrypt.m_message.m_allocContext;
+#endif
+
+	switch (destination) {
+	case 0:
+		break;
+
+	case 1:
+		cn = cn_cbor_mapget_int(pKey, COSE_Key_ID);
+		CHECK_CONDITION(cn != NULL, COSE_ERR_INVALID_PARAMETER);
+		cn2 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(cn2 != NULL, cbor_err);
+		CHECK_CONDITION(_COSE_map_put(&p->m_encrypt.m_message, COSE_Header_ECDH_SPK_KID, cn2, COSE_UNPROTECT_ONLY, perr), perr->err);
+		cn2 = NULL;
+		break;
+
+	case 2:
+		cn2 = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(cn2 != NULL, cbor_err);
+		cn = cn_cbor_mapget_int(pKey, COSE_Key_Type);
+		CHECK_CONDITION(cn != NULL, COSE_ERR_INVALID_PARAMETER);
+		cn3 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(cn3 != NULL, cbor_err);
+		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(cn2, COSE_Key_Type, cn3, CBOR_CONTEXT_PARAM_COMMA &cbor_err), cbor_err);
+		cn3 = NULL;
+		cn = cn_cbor_mapget_int(pKey, COSE_Key_EC2_Curve);
+		cn3 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(cn3 != NULL, cbor_err);
+		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(cn2, COSE_Key_EC2_Curve, cn3, CBOR_CONTEXT_PARAM_COMMA &cbor_err), cbor_err);
+		cn3 = NULL;
+		cn = cn_cbor_mapget_int(pKey, COSE_Key_EC2_X);
+		cn3 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(cn3 != NULL, cbor_err);
+		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(cn2, COSE_Key_EC2_X, cn3, CBOR_CONTEXT_PARAM_COMMA &cbor_err), cbor_err);
+		cn3 = NULL;
+		cn = cn_cbor_mapget_int(pKey, COSE_Key_EC2_Y);
+		cn3 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(cn3 != NULL, cbor_err);
+		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(cn2, COSE_Key_EC2_Y, cn3, CBOR_CONTEXT_PARAM_COMMA &cbor_err), cbor_err);
+		cn3 = NULL;
+		CHECK_CONDITION(_COSE_map_put(&p->m_encrypt.m_message, COSE_Header_ECDH_SPK, cn2, COSE_UNPROTECT_ONLY, perr), perr->err);
+		cn2 = NULL;
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
+
+	p->m_pkeyStatic = pKey;
+
+	f = true;
+errorReturn:
+	if (cn2 != NULL) CN_CBOR_FREE(cn2, context);
+	if (cn3 != NULL) CN_CBOR_FREE(cn3, context);
+	return f;
 }
 
 /*!
@@ -763,7 +872,7 @@
 bool COSE_Recipient_SetExternal(HCOSE_RECIPIENT hcose, const byte * pbExternalData, size_t cbExternalData, cose_errback * perr)
 {
 	if (!IsValidRecipientHandle(hcose)) {
-		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+		if (perr != NULL) perr->err = COSE_ERR_INVALID_HANDLE;
 		return false;
 	}
 
@@ -771,14 +880,12 @@
 }
 
 
-bool COSE_Recipient_map_put(HCOSE_RECIPIENT h, int key, cn_cbor * value, int flags, cose_errback * perror)
+bool COSE_Recipient_map_put_int(HCOSE_RECIPIENT h, int key, cn_cbor * value, int flags, cose_errback * perr)
 {
-	if (!IsValidRecipientHandle(h) || (value == NULL)) {
-		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
-		return false;
-	}
+	CHECK_CONDITION(IsValidRecipientHandle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(value != NULL, COSE_ERR_INVALID_PARAMETER);
 
-	if (!_COSE_map_put(&((COSE_RecipientInfo *)h)->m_encrypt.m_message, key, value, flags, perror)) return false;
+	if (!_COSE_map_put(&((COSE_RecipientInfo *)h)->m_encrypt.m_message, key, value, flags, perr)) return false;
 
 	if (key == COSE_Header_Algorithm) {
 		if (value->type == CN_CBOR_INT) {
@@ -806,6 +913,9 @@
 	}
 
 	return true;
+
+errorReturn:
+	return false;
 }
 
 
@@ -958,3 +1068,24 @@
 	goto returnHere;
 }
 
+/*! brief Retrieve header parameter from a recipient structure
+*
+* Retrieve a header parameter from the message.
+* Retrieved object is the same as the one in the message - do not delete it
+*
+* @param[in]	h	Handle of recipient object
+* @param[in]    key	Key to look for
+* @param[in]	flags	What buckets should we look for the message
+* @param[out]	perror	Location to return error codes
+* @return	Object which is found or NULL
+*/
+
+cn_cbor * COSE_Recipient_map_get_int(HCOSE_RECIPIENT h, int key, int flags, cose_errback * perror)
+{
+	if (!IsValidRecipientHandle(h)) {
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_HANDLE;
+		return NULL;
+	}
+
+	return _COSE_map_get_int(&((COSE_RecipientInfo *)h)->m_encrypt.m_message, key, flags, perror);
+}
diff --git a/src/Sign.c b/src/Sign.c
index 6a72d21..9466f85 100644
--- a/src/Sign.c
+++ b/src/Sign.c
@@ -150,13 +150,10 @@
 #endif
 	cn_cbor * p = NULL;
 	COSE_SignMessage * pMessage = (COSE_SignMessage *)h;
+	bool f = false;
 
-	if (!IsValidSignHandle(h) || (rgb == NULL)) {
-		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
-	errorReturn:
-		if (p != NULL) CN_CBOR_FREE(p, context);
-		return false;
-	}
+	CHECK_CONDITION(IsValidSignHandle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(rgb != NULL, COSE_ERR_INVALID_PARAMETER);
 
 #ifdef USE_CBOR_CONTEXT
 	context = &pMessage->m_message.m_allocContext;
@@ -166,8 +163,13 @@
 	CHECK_CONDITION(p != NULL, COSE_ERR_OUT_OF_MEMORY);
 
 	CHECK_CONDITION(_COSE_array_replace(&pMessage->m_message, p, INDEX_BODY, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_OUT_OF_MEMORY);
+	p = NULL;
 
-	return true;
+	f = true;
+errorReturn:
+	if (p != NULL) CN_CBOR_FREE(p, context);
+
+	return f;
 }
 
 HCOSE_SIGNER COSE_Sign_add_signer(HCOSE_SIGN hSign, const cn_cbor * pkey, int algId, cose_errback * perr)
@@ -181,13 +183,8 @@
 	HCOSE_SIGNER hSigner = NULL;
 	cn_cbor_errback cbor_error;
 
-	if (!IsValidSignHandle(hSign) || (pkey == NULL)) {
-		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
-	errorReturn:
-		if (cbor2 != NULL) CN_CBOR_FREE((void *) cbor2, context);
-		if (hSigner != NULL) COSE_Signer_Free(hSigner);
-		return NULL;
-	}
+	CHECK_CONDITION(IsValidSignHandle(hSign), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pkey != NULL, COSE_ERR_INVALID_PARAMETER);
 
 #ifdef USE_CBOR_CONTEXT
 	context = &pMessage->m_message.m_allocContext;
@@ -216,6 +213,11 @@
 	if (!COSE_Sign_AddSigner(hSign, hSigner, perr)) goto errorReturn;
 
 	return hSigner;
+
+errorReturn:
+	if (cbor2 != NULL) CN_CBOR_FREE((void *)cbor2, context);
+	if (hSigner != NULL) COSE_Signer_Free(hSigner);
+	return NULL;
 }
 
 bool COSE_Sign_Sign(HCOSE_SIGN h, cose_errback * perr)
@@ -229,7 +231,7 @@
 	const cn_cbor * pcborProtected;
 
 	if (!IsValidSignHandle(h)) {
-		CHECK_CONDITION(false, COSE_ERR_INVALID_PARAMETER);
+		CHECK_CONDITION(false, COSE_ERR_INVALID_HANDLE);
 	errorReturn:
 		return false;
 	}
@@ -258,8 +260,8 @@
 	const cn_cbor * cnContent;
 	const cn_cbor * cnProtected;
 
-	CHECK_CONDITION(IsValidSignHandle(hSign), COSE_ERR_INVALID_PARAMETER);
-	CHECK_CONDITION(IsValidSignerHandle(hSigner), COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(IsValidSignHandle(hSign), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(IsValidSignerHandle(hSigner), COSE_ERR_INVALID_HANDLE);
 
 	pSign = (COSE_SignMessage *)hSign;
 	pSigner = (COSE_SignerInfo *)hSigner;
@@ -290,8 +292,8 @@
 #endif
 	cn_cbor_errback cbor_error;
 
-	CHECK_CONDITION(IsValidSignHandle(hSign), COSE_ERR_INVALID_PARAMETER);
-	CHECK_CONDITION(IsValidSignerHandle(hSigner), COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(IsValidSignHandle(hSign), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(IsValidSignerHandle(hSigner), COSE_ERR_INVALID_HANDLE);
 
 	pSign = (COSE_SignMessage *)hSign;
 	pSigner = (COSE_SignerInfo *)hSigner;
@@ -326,7 +328,7 @@
 cn_cbor * COSE_Sign_map_get_int(HCOSE_SIGN h, int key, int flags, cose_errback * perror)
 {
 	if (!IsValidSignHandle(h)) {
-		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_HANDLE;
 		return NULL;
 	}
 
@@ -335,8 +337,8 @@
 
 bool COSE_Sign_map_put_int(HCOSE_SIGN h, int key, cn_cbor * value, int flags, cose_errback * perror)
 {
-	if (!IsValidSignHandle(h) || (value == NULL)) {
-		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+	if (!IsValidSignHandle(h)){
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_HANDLE;
 		return false;
 	}
 
@@ -349,7 +351,7 @@
 	COSE_SignerInfo * p;
 
 	if (!IsValidSignHandle(cose)) {
-		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+		if (perr != NULL) perr->err = COSE_ERR_INVALID_HANDLE;
 		return NULL;
 	}
 
diff --git a/src/Sign0.c b/src/Sign0.c
index 1b8528f..4d273ea 100644
--- a/src/Sign0.c
+++ b/src/Sign0.c
@@ -126,13 +126,10 @@
 #endif
 	cn_cbor * p = NULL;
 	COSE_Sign0Message * pMessage = (COSE_Sign0Message *)h;
+	bool fRet = false;
 
-	if (!IsValidSign0Handle(h) || (rgb == NULL)) {
-		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
-	errorReturn:
-		if (p != NULL) CN_CBOR_FREE(p, context);
-		return false;
-	}
+	CHECK_CONDITION(IsValidSign0Handle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(rgb != NULL, COSE_ERR_INVALID_PARAMETER);
 
 #ifdef USE_CBOR_CONTEXT
 	context = &pMessage->m_message.m_allocContext;
@@ -142,8 +139,13 @@
 	CHECK_CONDITION(p != NULL, COSE_ERR_OUT_OF_MEMORY);
 
 	CHECK_CONDITION(_COSE_array_replace(&pMessage->m_message, p, INDEX_BODY, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_OUT_OF_MEMORY);
+	p = NULL;
 
-	return true;
+	fRet = true;
+
+errorReturn:
+	if (p != NULL) CN_CBOR_FREE(p, context);
+	return fRet;
 }
 
 /*!
@@ -164,7 +166,7 @@
 bool COSE_Sign0_SetExternal(HCOSE_SIGN0 hcose, const byte * pbExternalData, size_t cbExternalData, cose_errback * perr)
 {
 	if (!IsValidSign0Handle(hcose)) {
-		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+		if (perr != NULL) perr->err = COSE_ERR_INVALID_HANDLE;
 		return false;
 	}
 
@@ -180,7 +182,7 @@
 	const cn_cbor * pcborProtected;
 
 	if (!IsValidSign0Handle(h)) {
-		CHECK_CONDITION(false, COSE_ERR_INVALID_PARAMETER);
+		CHECK_CONDITION(false, COSE_ERR_INVALID_HANDLE);
 	errorReturn:
 		return false;
 	}
@@ -203,7 +205,7 @@
 	const cn_cbor * cnContent;
 	const cn_cbor * cnProtected;
 
-	CHECK_CONDITION(IsValidSign0Handle(hSign), COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(IsValidSign0Handle(hSign), COSE_ERR_INVALID_HANDLE);
 
 	pSign = (COSE_Sign0Message *)hSign;
 
@@ -225,21 +227,22 @@
 cn_cbor * COSE_Sign0_map_get_int(HCOSE_SIGN0 h, int key, int flags, cose_errback * perror)
 {
 	if (!IsValidSign0Handle(h)) {
-		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_HANDLE;
 		return NULL;
 	}
 
 	return _COSE_map_get_int(&((COSE_Sign0Message *)h)->m_message, key, flags, perror);
 }
 
-bool COSE_Sign0_map_put_int(HCOSE_SIGN0 h, int key, cn_cbor * value, int flags, cose_errback * perror)
+bool COSE_Sign0_map_put_int(HCOSE_SIGN0 h, int key, cn_cbor * value, int flags, cose_errback * perr)
 {
-	if (!IsValidSign0Handle(h) || (value == NULL)) {
-		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
-		return false;
-	}
+	CHECK_CONDITION(IsValidSign0Handle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(value != NULL, COSE_ERR_INVALID_PARAMETER);
 
-	return _COSE_map_put(&((COSE_Sign0Message *)h)->m_message, key, value, flags, perror);
+	return _COSE_map_put(&((COSE_Sign0Message *)h)->m_message, key, value, flags, perr);
+
+errorReturn:
+	return false;
 }
 
 
diff --git a/src/SignerInfo.c b/src/SignerInfo.c
index 24f34c8..dd75531 100644
--- a/src/SignerInfo.c
+++ b/src/SignerInfo.c
@@ -223,19 +223,20 @@
 	return fRet;
 }
 
-bool COSE_Signer_SetKey(HCOSE_SIGNER h, const cn_cbor * pKey, cose_errback * perror)
+bool COSE_Signer_SetKey(HCOSE_SIGNER h, const cn_cbor * pKey, cose_errback * perr)
 {
 	COSE_SignerInfo * p;
+	bool fRet = false;
 
-	if (!IsValidSignerHandle(h) || (pKey == NULL)) {
-		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
-		return false;
-	}
+	CHECK_CONDITION(IsValidSignerHandle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pKey != NULL, COSE_ERR_INVALID_PARAMETER);
 
 	p = (COSE_SignerInfo *)h;
 	p->m_pkey = pKey;
 
-	return true;
+	fRet = true;
+errorReturn:
+	return fRet;
 }
 
 /*!
@@ -256,7 +257,7 @@
 bool COSE_Signer_SetExternal(HCOSE_SIGNER hcose, const byte * pbExternalData, size_t cbExternalData, cose_errback * perr)
 {
 	if (!IsValidSignerHandle(hcose)) {
-		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+		if (perr != NULL) perr->err = COSE_ERR_INVALID_HANDLE;
 		return false;
 	}
 
@@ -332,19 +333,22 @@
 cn_cbor * COSE_Signer_map_get_int(HCOSE_SIGNER h, int key, int flags, cose_errback * perr)
 {
 	if (!IsValidSignerHandle(h)) {
-		if (perr != NULL) perr->err = COSE_ERR_INVALID_PARAMETER;
+		if (perr != NULL) perr->err = COSE_ERR_INVALID_HANDLE;
 		return NULL;
 	}
 
 	return _COSE_map_get_int((COSE *)h, key, flags, perr);
 }
 
-bool COSE_Signer_map_put_int(HCOSE_SIGNER h, int key, cn_cbor * value, int flags, cose_errback * perror)
+bool COSE_Signer_map_put_int(HCOSE_SIGNER h, int key, cn_cbor * value, int flags, cose_errback * perr)
 {
-	if (!IsValidSignerHandle(h) || (value == NULL)) {
-		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
-		return false;
-	}
+	bool fRet = false;
 
-	return _COSE_map_put(&((COSE_SignerInfo *)h)->m_message, key, value, flags, perror);
+	CHECK_CONDITION(IsValidSignerHandle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(value != NULL, COSE_ERR_INVALID_PARAMETER);
+
+	return _COSE_map_put(&((COSE_SignerInfo *)h)->m_message, key, value, flags, perr);
+
+errorReturn:
+	return fRet;
 }
diff --git a/src/cose.h b/src/cose.h
index 7232bb6..dceed1c 100644
--- a/src/cose.h
+++ b/src/cose.h
@@ -153,15 +153,22 @@
 	COSE_Header_UseCompressedECDH = -997,
 
 	COSE_Header_ECDH_EPHEMERAL = -1,
-	COSE_Header_ECDH_STATIC = -2
+	COSE_Header_ECDH_STATIC = -2,
+	COSE_Header_ECDH_EPK = -1,
+	COSE_Header_ECDH_SPK = -2,
+	COSE_Header_ECDH_SPK_KID = -2,
 
 } COSE_Header;
 
 typedef enum {
 	COSE_Key_Type_EC2 = 2,
+	COSE_Key_Type_OCTET = 4,
 	COSE_Key_Type = 1,
 	COSE_Key_ID = 2,
 	COSE_Parameter_KID = 4,
+	COSE_Key_EC2_Curve=-1,
+	COSE_Key_EC2_X = -2,
+	COSE_Key_EC2_Y = -3
 } COSE_Constants;
 
 
@@ -197,9 +204,10 @@
 
 bool COSE_Recipient_SetKey_secret(HCOSE_RECIPIENT h, const byte * rgb, int cb, const byte * rgbKid, int cbKid, cose_errback * perr);
 bool COSE_Recipient_SetKey(HCOSE_RECIPIENT h, const cn_cbor * pKey, cose_errback * perror);
+bool COSE_Recipient_SetSenderKey(HCOSE_RECIPIENT h, const cn_cbor * pKey, int destination, cose_errback * perror);
 bool COSE_Recipient_SetExternal(HCOSE_RECIPIENT hcose, const byte * pbExternalData, size_t cbExternalData, cose_errback * perr);
 
-bool COSE_Recipient_map_put(HCOSE_RECIPIENT h, int key, cn_cbor * value, int flags, cose_errback * perror);
+bool COSE_Recipient_map_put_int(HCOSE_RECIPIENT h, int key, cn_cbor * value, int flags, cose_errback * perror);
 cn_cbor * COSE_Recipient_map_get_string(HCOSE_RECIPIENT cose, const char * key, int flags, cose_errback * errp);
 cn_cbor * COSE_Recipient_map_get_int(HCOSE_RECIPIENT cose, int key, int flags, cose_errback * errp);
 
@@ -303,4 +311,4 @@
 
 extern cn_cbor * cn_cbor_clone(const cn_cbor * pIn, CBOR_CONTEXT_COMMA cn_cbor_errback * perr);
 extern cn_cbor * cn_cbor_tag_create(int tag, cn_cbor * child, CBOR_CONTEXT_COMMA cn_cbor_errback * perr);
-extern cn_cbor * cn_cbor_bool_create(int boolValue, CBOR_CONTEXT_COMMA cn_cbor_errback * errp);
\ No newline at end of file
+extern cn_cbor * cn_cbor_bool_create(int boolValue, CBOR_CONTEXT_COMMA cn_cbor_errback * errp);
diff --git a/src/cose_int.h b/src/cose_int.h
index ead32c2..5940398 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -60,6 +60,7 @@
 	COSE_Enveloped m_encrypt;
 	COSE_RecipientInfo * m_recipientNext;
 	const cn_cbor * m_pkey;
+	const cn_cbor * m_pkeyStatic;
 };
 
 typedef struct {
diff --git a/src/openssl.c b/src/openssl.c
index 9ce333f..9a88a7d 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -16,6 +16,8 @@
 #include <openssl/ecdh.h>
 #include <openssl/rand.h>
 
+bool FUseCompressed = true;
+
 #define MIN(A, B) ((A) < (B) ? (A) : (B))
 
 bool AES_CCM_Decrypt(COSE_Enveloped * pcose, int TSize, int LSize, const byte * pbKey, size_t cbKey, const byte * pbCrypto, size_t cbCrypto, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr)
@@ -803,16 +805,25 @@
 	CHECK_CONDITION(ecgroup != NULL, COSE_ERR_INVALID_PARAMETER);
 	CHECK_CONDITION(EC_KEY_set_group(pNewKey, ecgroup) == 1, COSE_ERR_CRYPTO_FAIL);
 
-	rgbKey[0] = POINT_CONVERSION_UNCOMPRESSED;
 	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_X);
 	CHECK_CONDITION((p != NULL) && (p->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
 	CHECK_CONDITION(p->length == *cbGroup, COSE_ERR_INVALID_PARAMETER);
 	memcpy(rgbKey+1, p->v.str, p->length);
 
 	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_Y);
-	CHECK_CONDITION((p != NULL) && (p->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
-	CHECK_CONDITION(p->length == *cbGroup, COSE_ERR_INVALID_PARAMETER);
-	memcpy(rgbKey + p->length+1, p->v.str, p->length);
+	CHECK_CONDITION((p != NULL), COSE_ERR_INVALID_PARAMETER);
+	if (p->type == CN_CBOR_BYTES) {
+		rgbKey[0] = POINT_CONVERSION_UNCOMPRESSED;
+		CHECK_CONDITION(p->length == *cbGroup, COSE_ERR_INVALID_PARAMETER);
+		memcpy(rgbKey + p->length + 1, p->v.str, p->length);
+	}
+	else if (p->type == CN_CBOR_TRUE) {
+		rgbKey[0] = POINT_CONVERSION_COMPRESSED + 1;
+	}
+	else if (p->type == CN_CBOR_FALSE) {
+		rgbKey[0] = POINT_CONVERSION_COMPRESSED;
+	}
+	else FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
 
 	pPoint = EC_POINT_new(ecgroup);
 	CHECK_CONDITION(pPoint != NULL, COSE_ERR_CRYPTO_FAIL);
@@ -869,21 +880,42 @@
 	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);
-
+	if (FUseCompressed) {
+		cbSize = EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_COMPRESSED, 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_COMPRESSED, pbOut, cbSize, NULL) == cbSize, COSE_ERR_CRYPTO_FAIL);
+	}
+	else {
+		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.
+	if (FUseCompressed) {
+		p = cn_cbor_bool_create(pbOut[0] & 1, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		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;
+	}
+	else {
+		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;
+	}
+
+	p = cn_cbor_int_create(COSE_Key_Type_EC2, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
 	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);
+	CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_Type, p, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
 	p = NULL;
 
 returnHere:
@@ -1078,51 +1110,65 @@
 	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)
+/*!
+*
+* @param[in] pRecipent	Pointer to the message object
+* @param[in] ppKeyPrivate	Address of key with private portion
+* @param[in] pKeyPublic	Address of the key w/o a private portion
+* @param[in/out] ppbSecret	pointer to buffer to hold the computed secret
+* @param[in/out] pcbSecret	size of the computed secret
+* @param[in] context		cbor allocation context structure
+* @param[out] perr			location to return error information
+* @returns		success of the function
+*/
+
+bool ECDH_ComputeSecret(COSE * pRecipient, cn_cbor ** ppKeyPrivate, const cn_cbor * pKeyPublic, byte ** ppbSecret, size_t * pcbSecret, CBOR_CONTEXT_COMMA cose_errback *perr)
 {
-	EC_KEY * pkeyMe = NULL;
-	EC_KEY * pkeyYou = NULL;
+	EC_KEY * peckeyPrivate = NULL;
+	EC_KEY * peckeyPublic = NULL;
 	int cbGroup;
 	int cbsecret;
 	byte * pbsecret = NULL;
+	bool fRet = false;
 
-	pkeyYou = ECKey_From(pKeyYou, &cbGroup, perr);
-	if (pkeyYou == NULL) goto errorReturn;
+	peckeyPublic = ECKey_From(pKeyPublic, &cbGroup, perr);
+	if (peckeyPublic == 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;
+	if (*ppKeyPrivate == NULL) {
+		{
+			cn_cbor * pCompress = _COSE_map_get_int(pRecipient, COSE_Header_UseCompressedECDH, COSE_BOTH, perr);
+			if (pCompress == NULL) FUseCompressed = false;
+			else FUseCompressed = (pCompress->type == CN_CBOR_TRUE);
+		}
+		peckeyPrivate = EC_KEY_new();
+		EC_KEY_set_group(peckeyPrivate, EC_KEY_get0_group(peckeyPublic));
+		CHECK_CONDITION(EC_KEY_generate_key(peckeyPrivate) == 1, COSE_ERR_CRYPTO_FAIL);
+		*ppKeyPrivate = EC_FromKey(peckeyPrivate, CBOR_CONTEXT_PARAM_COMMA perr);
+		if (*ppKeyPrivate == NULL) goto errorReturn;
 	}
 	else {
-		pkeyMe = ECKey_From(*ppKeyMe, &cbGroup, perr);
-		if (pkeyMe == NULL) goto errorReturn;
+		peckeyPrivate = ECKey_From(*ppKeyPrivate, &cbGroup, perr);
+		if (peckeyPrivate == 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);
+	cbsecret = ECDH_compute_key(pbsecret, cbGroup, EC_KEY_get0_public_key(peckeyPublic), peckeyPrivate, 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;
+	fRet = true;
 
 errorReturn:
 	if (pbsecret != NULL) COSE_FREE(pbsecret, context);
-	if (pkeyMe != NULL) EC_KEY_free(pkeyMe);
-	if (pkeyYou != NULL) EC_KEY_free(pkeyYou);
+	if (peckeyPublic != NULL) EC_KEY_free(peckeyPublic);
+	if (peckeyPrivate != NULL) EC_KEY_free(peckeyPrivate);
 
-	return false;
-
+	return fRet;
 }
 
 #endif // USE_OPEN_SSL
diff --git a/test/context.c b/test/context.c
index 3546f04..dbdea88 100644
--- a/test/context.c
+++ b/test/context.c
@@ -1,4 +1,6 @@
 #include <stdlib.h>
+#ifdef _MSC_VER
+#endif
 #include <stdio.h>
 #include <memory.h>
 #include <assert.h>
diff --git a/test/encrypt.c b/test/encrypt.c
index 0cf8193..a7072ba 100644
--- a/test/encrypt.c
+++ b/test/encrypt.c
@@ -12,6 +12,10 @@
 #include "test.h"
 #include "context.h"
 
+#ifdef _MSC_VER
+#pragma warning (disable: 4127)
+#endif
+
 
 int _ValidateEnveloped(const cn_cbor * pControl, const byte * pbEncoded, size_t cbEncoded)
 {
@@ -65,6 +69,13 @@
 
 		if (!SetReceivingAttributes((HCOSE) hRecip, pRecipients, Attributes_Recipient_protected)) goto errorReturn;
 
+		cn_cbor * cnStatic = cn_cbor_mapget_string(pRecipients, "sender_key");
+		if (cnStatic != NULL) {
+			if (COSE_Recipient_map_get_int(hRecip, COSE_Header_ECDH_SPK, COSE_BOTH, NULL) == 0) {
+				COSE_Recipient_map_put_int(hRecip, COSE_Header_ECDH_SPK, BuildKey(cnStatic, true), COSE_DONT_SEND, NULL);
+			}
+		}
+
 		pFail = cn_cbor_mapget_string(pRecipients, "fail");
 		if (COSE_Enveloped_decrypt(hEnc, hRecip, NULL)) {
 			if ((pFail != NULL) && (pFail->type != CN_CBOR_TRUE)) fFail = true;
@@ -141,6 +152,12 @@
 
 		if (!COSE_Enveloped_AddRecipient(hEncObj, hRecip, NULL)) goto returnError;
 
+		cn_cbor * pSenderKey = cn_cbor_mapget_string(pRecipients, "sender_key");
+		if (pSenderKey != NULL) {
+			cn_cbor * pSendKey = BuildKey(pSenderKey, false);
+			if (!COSE_Recipient_SetSenderKey(hRecip, pSendKey, 2, NULL)) goto returnError;
+		}
+
 		COSE_Recipient_Free(hRecip);
 	}
 
@@ -383,57 +400,57 @@
 	cn_cbor * cn = cn_cbor_int_create(5, CBOR_CONTEXT_PARAM_COMMA NULL);
 	cose_errback cose_error;
 
-        hEncrypt = COSE_Enveloped_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
-        hEncryptBad = (HCOSE_ENVELOPED) COSE_Mac_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
-        hRecipient = COSE_Recipient_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
-        hRecipientBad = (HCOSE_RECIPIENT) COSE_Mac_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+	hEncrypt = COSE_Enveloped_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+	hEncryptBad = (HCOSE_ENVELOPED)COSE_Mac_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+	hRecipient = COSE_Recipient_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+	hRecipientBad = (HCOSE_RECIPIENT)COSE_Mac_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	//  Missing case - addref then release on item
 
 
-        //
-        //  Do parameter checks
-        //      - NULL handle
-        //      - Incorrect handle
-        //      - NULL pointer
-        //
+		//
+		//  Do parameter checks
+		//      - NULL handle
+		//      - Incorrect handle
+		//      - NULL pointer
+		//
 
-        CHECK_FAILURE(COSE_Enveloped_SetContent(hEncryptNULL, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
-        CHECK_FAILURE(COSE_Enveloped_SetContent(hEncryptBad, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
-        CHECK_FAILURE(COSE_Enveloped_SetContent(hEncrypt, NULL, 10, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_SetContent(hEncryptNULL, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_SetContent(hEncryptBad, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_SetContent(hEncrypt, NULL, 10, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
 
 
 	CHECK_FAILURE(COSE_Enveloped_map_put_int(hEncryptNULL, 1, cn, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
 	CHECK_FAILURE(COSE_Enveloped_map_put_int(hEncryptBad, 1, cn, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
 	CHECK_FAILURE(COSE_Enveloped_map_put_int(hEncrypt, 1, cn, COSE_PROTECT_ONLY | COSE_UNPROTECT_ONLY, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
 	CHECK_FAILURE(COSE_Enveloped_map_put_int(hEncrypt, 1, NULL, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
-        
-
-        CHECK_FAILURE(COSE_Enveloped_map_get_int(hEncryptNULL, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
-        CHECK_FAILURE(COSE_Enveloped_map_get_int(hEncryptBad, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
 
 
-        CHECK_FAILURE(COSE_Enveloped_encrypt(hEncryptNULL, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
-        CHECK_FAILURE(COSE_Enveloped_encrypt(hEncryptBad, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_map_get_int(hEncryptNULL, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_map_get_int(hEncryptBad, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
 
-        CHECK_FAILURE(COSE_Enveloped_decrypt(hEncryptNULL, hRecipient, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
-        CHECK_FAILURE(COSE_Enveloped_decrypt(hEncryptBad, hRecipient, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
-        CHECK_FAILURE(COSE_Enveloped_decrypt(hEncrypt, hRecipientNULL, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
-        CHECK_FAILURE(COSE_Enveloped_decrypt(hEncrypt, hRecipientBad, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+
+	CHECK_FAILURE(COSE_Enveloped_encrypt(hEncryptNULL, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_encrypt(hEncryptBad, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+
+	CHECK_FAILURE(COSE_Enveloped_decrypt(hEncryptNULL, hRecipient, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_decrypt(hEncryptBad, hRecipient, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_decrypt(hEncrypt, hRecipientNULL, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Enveloped_decrypt(hEncrypt, hRecipientBad, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
 
 
 	CHECK_FAILURE(COSE_Enveloped_AddRecipient(hEncryptNULL, hRecipient, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
 	CHECK_FAILURE(COSE_Enveloped_AddRecipient(hEncryptBad, hRecipient, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
 	CHECK_FAILURE(COSE_Enveloped_AddRecipient(hEncrypt, hRecipientNULL, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
 	CHECK_FAILURE(COSE_Enveloped_AddRecipient(hEncrypt, hRecipientBad, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
-        
+
 	CHECK_FAILURE_PTR(COSE_Enveloped_GetRecipient(hEncryptNULL, 0, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
 	CHECK_FAILURE_PTR(COSE_Enveloped_GetRecipient(hEncryptBad, 0, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
-            
+
 	CHECK_FAILURE(COSE_Enveloped_SetExternal(hEncryptNULL, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
 	CHECK_FAILURE(COSE_Enveloped_SetExternal(hEncryptBad, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
 	CHECK_FAILURE(COSE_Enveloped_SetExternal(hEncrypt, NULL, 10, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
-            
+
 	if (!COSE_Enveloped_Free(hEncrypt)) CFails++;
 	if (!COSE_Recipient_Free(hRecipient)) CFails++;
 
@@ -464,14 +481,14 @@
 	CHECK_RETURN(COSE_Enveloped_AddRecipient(hEncrypt, hRecipient, &cose_error), COSE_ERR_NONE, CFails++);
 	CHECK_FAILURE(COSE_Enveloped_encrypt(hEncrypt, &cose_error), COSE_ERR_UNKNOWN_ALGORITHM, CFails++);
 
-        //
-        //  Over shoot the recipients
-        
-        CHECK_FAILURE_PTR(COSE_Enveloped_GetRecipient(hEncrypt, -1, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
-        CHECK_FAILURE_PTR(COSE_Enveloped_GetRecipient(hEncrypt, 9, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+	//
+	//  Over shoot the recipients
 
-		COSE_Enveloped_Free(hEncrypt);
-		COSE_Recipient_Free(hRecipient);
+	CHECK_FAILURE_PTR(COSE_Enveloped_GetRecipient(hEncrypt, -1, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+	CHECK_FAILURE_PTR(COSE_Enveloped_GetRecipient(hEncrypt, 9, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+
+	COSE_Enveloped_Free(hEncrypt);
+	COSE_Recipient_Free(hRecipient);
 
 	return;
 }
@@ -526,3 +543,45 @@
 
 	return;
 }
+
+void Recipient_Corners()
+{
+	HCOSE_RECIPIENT hRecip;
+	HCOSE_RECIPIENT hRecipNULL = NULL;
+	HCOSE_RECIPIENT hRecipBad;
+	cose_errback cose_error;
+	byte rgb[10];
+	cn_cbor * cn = cn_cbor_int_create(1, CBOR_CONTEXT_PARAM_COMMA NULL);
+
+	hRecip = COSE_Recipient_Init(0, CBOR_CONTEXT_PARAM_COMMA &cose_error);
+	hRecipBad = (HCOSE_RECIPIENT)COSE_Signer_Init(CBOR_CONTEXT_PARAM_COMMA &cose_error);
+
+	//  Check for invalid parameters
+
+	CHECK_FAILURE_PTR(COSE_Recipient_from_shared_secret(NULL, 0, NULL, 0, CBOR_CONTEXT_PARAM_COMMA &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+
+	CHECK_FAILURE(COSE_Recipient_SetKey_secret(hRecipNULL, rgb, sizeof(rgb), NULL, 0, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Recipient_SetKey_secret(hRecipBad, rgb, sizeof(rgb), NULL, 0, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Recipient_SetKey_secret(hRecip, NULL, sizeof(rgb), NULL, 0, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+
+	CHECK_FAILURE(COSE_Recipient_SetKey(hRecipNULL, cn, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Recipient_SetKey(hRecipBad, cn, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Recipient_SetKey(hRecip, NULL, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+
+	CHECK_FAILURE(COSE_Recipient_SetSenderKey(hRecipNULL, cn, 0, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Recipient_SetSenderKey(hRecipBad, cn, 0, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Recipient_SetSenderKey(hRecip, NULL, 0, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+	CHECK_FAILURE(COSE_Recipient_SetSenderKey(hRecip, cn, 3, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+
+	CHECK_FAILURE(COSE_Recipient_SetExternal(hRecipNULL, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Recipient_SetExternal(hRecipBad, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+
+	CHECK_FAILURE(COSE_Recipient_map_get_int(hRecipNULL, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Recipient_map_get_int(hRecipBad, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Recipient_map_get_int(hRecip, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+
+	CHECK_FAILURE(COSE_Recipient_map_put_int(hRecipNULL, 1, cn, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Recipient_map_put_int(hRecipBad, 1, cn, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Recipient_map_put_int(hRecip, 1, NULL, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+	CHECK_FAILURE(COSE_Recipient_map_put_int(hRecip, 1, cn, COSE_PROTECT_ONLY | COSE_UNPROTECT_ONLY, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+}
\ No newline at end of file
diff --git a/test/mac_test.c b/test/mac_test.c
index dc8ef1c..455a395 100644
--- a/test/mac_test.c
+++ b/test/mac_test.c
@@ -10,6 +10,11 @@
 #include "test.h"
 #include "context.h"
 
+#ifdef _MSC_VER
+#pragma warning (disable: 4127)
+#endif
+
+
 int _ValidateMAC(const cn_cbor * pControl, const byte * pbEncoded, size_t cbEncoded)
 {
 	const cn_cbor * pInput = cn_cbor_mapget_string(pControl, "input");
@@ -61,6 +66,13 @@
 			continue;
 		}
 
+		cn_cbor * cnStatic = cn_cbor_mapget_string(pRecipients, "sender_key");
+		if (cnStatic != NULL) {
+			if (COSE_Recipient_map_get_int(hRecip, COSE_Header_ECDH_SPK, COSE_BOTH, NULL) == 0) {
+				COSE_Recipient_map_put_int(hRecip, COSE_Header_ECDH_SPK, BuildKey(cnStatic, true), COSE_DONT_SEND, NULL);
+			}
+		}
+
 		pFail = cn_cbor_mapget_string(pRecipients, "fail");
 		if (COSE_Mac_validate(hMAC, hRecip, NULL)) {
 			if ((pFail != NULL) && (pFail->type != CN_CBOR_TRUE)) fFail = true;
@@ -135,6 +147,12 @@
 
 		if (!COSE_Recipient_SetKey(hRecip, pkey, NULL))goto returnError;
 
+		cn_cbor * pSenderKey = cn_cbor_mapget_string(pRecipients, "sender_key");
+		if (pSenderKey != NULL) {
+			cn_cbor * pSendKey = BuildKey(pSenderKey, false);
+			if (!COSE_Recipient_SetSenderKey(hRecip, pSendKey, 2, NULL)) goto returnError;
+		}
+
 		if (!COSE_Mac_AddRecipient(hMacObj, hRecip, NULL)) goto returnError;
 
 		COSE_Recipient_Free(hRecip);
diff --git a/test/sign.c b/test/sign.c
index d9d86aa..6bb1e6b 100644
--- a/test/sign.c
+++ b/test/sign.c
@@ -12,6 +12,10 @@
 #include "test.h"
 #include "context.h"
 
+#ifdef _MSC_VER
+#pragma warning (disable: 4127)
+#endif
+
 int _ValidateSigned(const cn_cbor * pControl, const byte * pbEncoded, size_t cbEncoded)
 {
 	const cn_cbor * pInput = cn_cbor_mapget_string(pControl, "input");
@@ -349,60 +353,82 @@
 void Sign_Corners()
 {
 	HCOSE_SIGN hSign = NULL;
-	HCOSE_SIGN hSign2;
+	HCOSE_SIGN hSignBad;
+	HCOSE_SIGN hSignNULL = NULL;
 	HCOSE_SIGNER hSigner = NULL;
-	HCOSE_SIGNER hSigner2;
+	HCOSE_SIGNER hSignerBad;
+	HCOSE_SIGNER hSignerNULL = NULL;
 	byte rgb[10];
 	cn_cbor * cn = cn_cbor_int_create(5, CBOR_CONTEXT_PARAM_COMMA NULL);
 	cose_errback cose_error;
 
-	hSign2 = COSE_Sign_Init(0, CBOR_CONTEXT_PARAM_COMMA  NULL);
-	hSigner2 = COSE_Signer_Init(CBOR_CONTEXT_PARAM_COMMA  NULL);
+	hSign = COSE_Sign_Init(0, CBOR_CONTEXT_PARAM_COMMA  NULL);
+	hSignBad = (HCOSE_SIGN)COSE_Sign0_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+
+	hSigner = COSE_Signer_Init(CBOR_CONTEXT_PARAM_COMMA  NULL);
+	hSignerBad = (HCOSE_SIGNER)COSE_Recipient_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
 	//  Missing case - addref then release on item
-
 	//  Incorrect algorithm
 
+	//  bad handle checks
+	//      null handle
+	//      wrong type of handle
 	//  Null handle checks
 
-	if (COSE_Sign_SetContent(hSign, rgb, 10, NULL)) CFails++;
-	if (COSE_Sign_map_get_int(hSign, 1, COSE_BOTH, NULL)) CFails++;
-	if (COSE_Sign_map_put_int(hSign, 1, cn, COSE_PROTECT_ONLY, NULL)) CFails++;
-	if (COSE_Sign_AddSigner(hSign, hSigner, NULL)) CFails++;
-	if (COSE_Sign_AddSigner(hSign2, hSigner, NULL)) CFails++;
-	if (COSE_Sign_GetSigner(hSign, 2, NULL)) CFails++;
-	if (COSE_Sign_Sign(hSign, NULL)) CFails++;
-	if (COSE_Sign_validate(hSign, hSigner, NULL)) CFails++;
-	if (COSE_Sign_validate(hSign2, hSigner, NULL)) CFails++;
+	CHECK_FAILURE(COSE_Sign_SetContent(hSignNULL, rgb, sizeof(rgb), &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_SetContent(hSignBad, rgb, sizeof(rgb), &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_SetContent(hSign, NULL, sizeof(rgb), &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
 
-	if (COSE_Signer_SetKey(hSigner, NULL, NULL)) CFails++;
-	if (COSE_Signer_SetKey(hSigner2, NULL, NULL)) CFails++;
-	if (COSE_Signer_map_put_int(hSigner, 1, cn, COSE_BOTH, NULL)) CFails++;
-	if (COSE_Signer_map_put_int(hSigner2, 1, NULL, COSE_BOTH, NULL)) CFails++;
-	if (COSE_Signer_map_get_int(hSigner, 1, COSE_BOTH, NULL)) CFails++;
-	if (COSE_Signer_SetExternal(hSigner, rgb, sizeof(rgb), NULL)) CFails++;
+	CHECK_FAILURE(COSE_Sign_map_get_int(hSignNULL, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_map_get_int(hSignBad, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_map_get_int(hSign, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
 
+	CHECK_FAILURE(COSE_Sign_map_put_int(hSignNULL, 1, cn, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_map_put_int(hSignBad, 1, cn, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_map_put_int(hSign, 1, NULL, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+	CHECK_FAILURE(COSE_Sign_map_put_int(hSign, 1, cn, COSE_PROTECT_ONLY | COSE_UNPROTECT_ONLY, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
 
-	hSign = (HCOSE_SIGN) COSE_Encrypt_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
-	hSigner = (HCOSE_SIGNER) COSE_Recipient_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+	CHECK_FAILURE(COSE_Sign_AddSigner(hSignNULL, hSigner, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_AddSigner(hSignBad, hSigner, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_AddSigner(hSign, hSignerNULL, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_AddSigner(hSign, hSignerBad, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_RETURN(COSE_Sign_AddSigner(hSign, hSigner, &cose_error), COSE_ERR_NONE, CFails++);
 
-	if (COSE_Sign_SetContent(hSign, rgb, 10, NULL)) CFails++;
-	if (COSE_Sign_map_get_int(hSign, 1, COSE_BOTH, NULL)) CFails++;
-	if (COSE_Sign_map_put_int(hSign, 1, cn, COSE_PROTECT_ONLY, NULL)) CFails++;
-	if (COSE_Sign_AddSigner(hSign, hSigner, NULL)) CFails++;
-	if (COSE_Sign_AddSigner(hSign2, hSigner, NULL)) CFails++;
-	if (COSE_Sign_GetSigner(hSign, 2, NULL)) CFails++;
-	if (COSE_Sign_Sign(hSign, NULL)) CFails++;
-	if (COSE_Sign_validate(hSign, hSigner, NULL)) CFails++;
-	if (COSE_Sign_validate(hSign2, hSigner, NULL)) CFails++;
+	CHECK_FAILURE(COSE_Sign_add_signer(hSignNULL, cn, 0, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_add_signer(hSignBad, cn, 0, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_add_signer(hSign, NULL, 0, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
 
-	if (COSE_Signer_SetKey(hSigner, NULL, NULL)) CFails++;
-	if (COSE_Signer_SetKey(hSigner2, NULL, NULL)) CFails++;
-	if (COSE_Signer_map_put_int(hSigner, 1, cn, COSE_BOTH, NULL)) CFails++;
-	if (COSE_Signer_map_put_int(hSigner2, 1, NULL, COSE_BOTH, NULL)) CFails++;
-	if (COSE_Signer_map_get_int(hSigner, 1, COSE_BOTH, NULL)) CFails++;
-	if (COSE_Signer_SetExternal(hSigner, rgb, sizeof(rgb), NULL)) CFails++;
+	CHECK_FAILURE(COSE_Sign_GetSigner(hSignNULL, 1, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_GetSigner(hSignBad, 1, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_GetSigner(hSign, 2, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
 
+	CHECK_FAILURE(COSE_Sign_Sign(hSignNULL, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_Sign(hSignBad, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+
+	CHECK_FAILURE(COSE_Sign_validate(hSignNULL, hSigner, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_validate(hSignBad, hSigner, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_validate(hSign, hSignerNULL, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign_validate(hSign, hSignerBad, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+
+	CHECK_FAILURE(COSE_Signer_SetKey(hSignerNULL, cn, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Signer_SetKey(hSignerBad, cn, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Signer_SetKey(hSigner, NULL, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+
+	CHECK_FAILURE(COSE_Signer_map_get_int(hSignerNULL, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Signer_map_get_int(hSignerBad, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Signer_map_get_int(hSigner, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+
+	CHECK_FAILURE(COSE_Signer_map_put_int(hSignerNULL, 1, cn, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Signer_map_put_int(hSignerBad, 1, cn, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Signer_map_put_int(hSigner, 1, NULL, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+	CHECK_FAILURE(COSE_Signer_map_put_int(hSigner, 1, cn, COSE_PROTECT_ONLY | COSE_UNPROTECT_ONLY, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+
+	CHECK_FAILURE(COSE_Signer_SetExternal(hSignerNULL, rgb, sizeof(rgb), &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Signer_SetExternal(hSignerBad, rgb, sizeof(rgb), &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+
+	COSE_Sign_Free(hSign);
+	COSE_Signer_Free(hSigner);
 	//
 	//  Unsupported algorithm
 
@@ -442,35 +468,47 @@
 void Sign0_Corners()
 {
 	HCOSE_SIGN0 hSign = NULL;
-	HCOSE_SIGN0 hSign2;
+	HCOSE_SIGN0 hSignNULL = NULL;
+	HCOSE_SIGN0 hSignBad;
+
 	byte rgb[10];
 	cn_cbor * cn = cn_cbor_int_create(5, CBOR_CONTEXT_PARAM_COMMA NULL);
 	cose_errback cose_error;
 
-	hSign2 = COSE_Sign0_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
-	//  Missing case - addref then release on item
+	hSign = COSE_Sign0_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+	hSignBad = (HCOSE_SIGN0)COSE_Sign_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 
-	//  Incorrect algorithm
 
-	//  Null handle checks
+	//  Look for invalid parameter
+	//		Null handle checks
+	//		bad handle checks
+	//		null pointers
 
-	if (COSE_Sign0_SetContent(hSign, rgb, 10, NULL)) CFails++;
-	if (COSE_Sign0_map_get_int(hSign, 1, COSE_BOTH, NULL)) CFails++;
-	if (COSE_Sign0_map_put_int(hSign, 1, cn, COSE_PROTECT_ONLY, NULL)) CFails++;
-	if (COSE_Sign0_Sign(hSign, cn, NULL)) CFails++;
-	if (COSE_Sign0_Sign(hSign2, NULL, NULL)) CFails++;
-	if (COSE_Sign0_validate(hSign, cn, NULL)) CFails++;
-	if (COSE_Sign0_validate(hSign2, NULL, NULL)) CFails++;
-	if (COSE_Sign0_SetExternal(hSign, rgb, sizeof(rgb), NULL)) CFails++;
+	CHECK_FAILURE(COSE_Sign0_SetContent(hSignNULL, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign0_SetContent(hSignBad, rgb, 10, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign0_SetContent(hSign, NULL, 10, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
 
-	hSign = (HCOSE_SIGN0)COSE_Encrypt_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
+	CHECK_FAILURE(COSE_Sign0_map_get_int(hSignNULL, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign0_map_get_int(hSignBad, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign0_map_get_int(hSign, 1, COSE_BOTH, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
 
-	if (COSE_Sign0_SetContent(hSign, rgb, 10, NULL)) CFails++;
-	if (COSE_Sign0_map_get_int(hSign, 1, COSE_BOTH, NULL)) CFails++;
-	if (COSE_Sign0_map_put_int(hSign, 1, cn, COSE_PROTECT_ONLY, NULL)) CFails++;
-	if (COSE_Sign0_Sign(hSign, cn, NULL)) CFails++;
-	if (COSE_Sign0_validate(hSign, cn, NULL)) CFails++;
-	if (COSE_Sign0_SetExternal(hSign, rgb, sizeof(rgb), NULL)) CFails++;
+	CHECK_FAILURE(COSE_Sign0_map_put_int(hSignNULL, 1, cn, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign0_map_put_int(hSignBad, 1, cn, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign0_map_put_int(hSign, 1, NULL, COSE_PROTECT_ONLY, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+	CHECK_FAILURE(COSE_Sign0_map_put_int(hSign, 1, cn, COSE_PROTECT_ONLY | COSE_UNPROTECT_ONLY, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+
+	CHECK_FAILURE(COSE_Sign0_Sign(hSignNULL, cn, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign0_Sign(hSignBad, cn, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign0_Sign(hSign, NULL, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+
+	CHECK_FAILURE(COSE_Sign0_validate(hSignNULL, cn, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign0_validate(hSignBad, cn, &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign0_validate(hSign, NULL, &cose_error), COSE_ERR_INVALID_PARAMETER, CFails++);
+
+	CHECK_FAILURE(COSE_Sign0_SetExternal(hSignNULL, rgb, sizeof(rgb), &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_Sign0_SetExternal(hSignBad, rgb, sizeof(rgb), &cose_error), COSE_ERR_INVALID_HANDLE, CFails++);
+
+	COSE_Sign0_Free(hSign);
 
 	//
 	//  Unsupported algorithm
@@ -478,6 +516,7 @@
 	hSign = COSE_Sign0_Init(0, CBOR_CONTEXT_PARAM_COMMA NULL);
 	if (hSign == NULL) CFails++;
 
+	cn = cn_cbor_int_create(15, CBOR_CONTEXT_PARAM_COMMA NULL);
 	if (!COSE_Sign0_SetContent(hSign, (byte *) "Message", 7, NULL)) CFails++;
 	if (!COSE_Sign0_map_put_int(hSign, COSE_Header_Algorithm, cn_cbor_int_create(-99, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_PROTECT_ONLY, NULL)) CFails++;
 	CHECK_FAILURE(COSE_Sign0_Sign(hSign, cn, &cose_error), COSE_ERR_UNKNOWN_ALGORITHM, CFails++);
diff --git a/test/test.c b/test/test.c
index 37bc301..d288a5c 100644
--- a/test/test.c
+++ b/test/test.c
@@ -28,7 +28,7 @@
 	int    i;
 } NameMap;
 
-NameMap RgAlgorithmNames[46] = {
+NameMap RgAlgorithmNames[47] = {
 	{"HS256", COSE_Algorithm_HMAC_256_256},
 	{"HS256/64", COSE_Algorithm_HMAC_256_64},
 	{"HS384", COSE_Algorithm_HMAC_384_384},
@@ -62,6 +62,7 @@
 	{"ECDH-ES", COSE_Algorithm_ECDH_ES_HKDF_256},
 {"ECDH-ES-512",COSE_Algorithm_ECDH_ES_HKDF_512},
 { "ECDH-SS", COSE_Algorithm_ECDH_SS_HKDF_256 },
+{ "ECDH-SS-256", COSE_Algorithm_ECDH_SS_HKDF_256}, 
 { "ECDH-SS-512",COSE_Algorithm_ECDH_SS_HKDF_512 },
 { "ECDH-ES+A128KW", COSE_Algorithm_ECDH_ES_A128KW },
 { "ECDH-ES+A192KW", COSE_Algorithm_ECDH_ES_A192KW },
@@ -246,7 +247,7 @@
 			break;
 
 		case Attributes_Recipient_protected:
-			f = COSE_Recipient_map_put((HCOSE_RECIPIENT)hHandle, keyNew, pValueNew, which, NULL);
+			f = COSE_Recipient_map_put_int((HCOSE_RECIPIENT)hHandle, keyNew, pValueNew, which, NULL);
 			break;
 
 		case Attributes_Enveloped_protected:
@@ -473,6 +474,7 @@
 	Enveloped_Corners();
 	Sign_Corners();
 	Sign0_Corners();
+	Recipient_Corners();
 }
 
 void RunMemoryTest(const char * szFileName)
diff --git a/test/test.h b/test/test.h
index 34d832b..3612b9d 100644
--- a/test/test.h
+++ b/test/test.h
@@ -21,6 +21,7 @@
 int BuildEncryptMessage(const cn_cbor * pControl);
 void Enveloped_Corners();
 void Encrypt_Corners();
+void Recipient_Corners();
 
 
 //  sign.c