Merge pull request #38 from jimsch/master

Testing Cleanup work
diff --git a/src/Cose.c b/src/Cose.c
index 382a4ce..2de060e 100644
--- a/src/Cose.c
+++ b/src/Cose.c
@@ -388,6 +388,90 @@
 	return pProtected;
 }
 
+#ifdef USE_COUNTER_SIGNATURES
+bool _COSE_CounterSign_add(COSE * pMessage, HCOSE_COUNTERSIGN hSigner, cose_errback * perr)
+{
+	COSE_CounterSign * pSigner = (COSE_CounterSign *)hSigner;
+
+	CHECK_CONDITION(IsValidCounterSignHandle(hSigner), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pSigner->m_signer.m_signerNext == NULL, COSE_ERR_INVALID_PARAMETER);
+
+	pSigner = pMessage->m_counterSigners;
+	pMessage->m_counterSigners = pSigner;
+	return true;
+
+errorReturn:
+	return false;
+}
+
+HCOSE_COUNTERSIGN _COSE_CounterSign_get(COSE * pMessage, int iSigner, cose_errback * perr)
+{
+	COSE_SignerInfo * pSigner = pMessage->m_counterSigners;
+	int i;
+
+	for (i = 0; i < iSigner; i++, pSigner = pSigner->m_signerNext) {
+		CHECK_CONDITION(pSigner != NULL, COSE_ERR_INVALID_PARAMETER);
+	}
+
+	return pSigner;
+
+errorReturn:
+	return false;
+}
+
+bool _COSE_CountSign_create(COSE * pMessage, cn_cbor * pcnBody, CBOR_CONTEXT_COMMA cose_errback * perr)
+{
+	cn_cbor * pArray = NULL;
+	cn_cbor_errback cbor_err;
+	COSE_CounterSign * pSigner = NULL;
+	cn_cbor * pcnProtected = NULL;
+	cn_cbor * pcn;
+	cn_cbor * pcn2;
+
+	if (pMessage->m_counterSigners == NULL) return true;
+
+	//  One or more than one?
+	if (pMessage->m_counterSigners->m_signer.m_signerNext != NULL) {
+		pArray = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(pArray != NULL, cbor_err);
+	}
+
+	pcnProtected = _COSE_arrayget_int(pMessage, INDEX_PROTECTED);
+	CHECK_CONDITION(pcnProtected != NULL, COSE_ERR_INTERNAL);
+
+	for (pSigner = pMessage->m_counterSigners; pSigner != NULL; pSigner = pSigner->m_signer.m_signerNext) {
+		pcn = cn_cbor_data_create(pcnProtected->v.bytes, pcnProtected->v.count, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(pcnProtected != NULL, cbor_err);
+
+		pcn2 = cn_cbor_clone(pcnBody, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(pcnBody != NULL, cbor_err);
+
+		if (!_COSE_Signer_sign(pSigner, pcnBody, pcn2, perr)) goto errorReturn;
+		pcn = NULL;
+		pcn2 = NULL;
+
+		if (pArray != NULL) {
+			bool f = cn_cbor_array_append(pArray, pSigner->m_signer.m_message.m_cborRoot, &cbor_err);
+			CHECK_CONDITION_CBOR(f, cbor_err);
+		}
+		else {
+			pArray = pSigner->m_signer.m_message.m_cborRoot;
+		}
+	}
+
+	if (!_COSE_map_put(pMessage, COSE_Header_CounterSign, pArray, COSE_UNPROTECT_ONLY, perr)) goto errorReturn;
+
+	return true;
+
+errorReturn:
+	if (pArray != NULL) CN_CBOR_FREE(pArray, context);
+	if ((pcn != NULL) && (pcn->parent != NULL)) CN_CBOR_FREE(pcn, context);
+	if ((pcn2 != NULL) && (pcn2->parent != NULL)) CN_CBOR_FREE(pcn2, context);
+	return false;
+}
+
+#endif
+
 bool _COSE_array_replace(COSE * pMessage, cn_cbor * cb_value, int index, CBOR_CONTEXT_COMMA cn_cbor_errback * errp)
 {
 #ifdef TAG_IN_ARRAY
diff --git a/src/Encrypt.c b/src/Encrypt.c
index 8132572..408bdcc 100644
--- a/src/Encrypt.c
+++ b/src/Encrypt.c
@@ -170,7 +170,7 @@
 	CHECK_CONDITION(IsValidRecipientHandle(hRecip), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(pcose->m_recipientFirst != NULL, COSE_ERR_INVALID_PARAMETER);
 
-	f = _COSE_Enveloped_decrypt(pcose, pRecip, NULL, 0, "Enveloped", perr);
+	f = _COSE_Enveloped_decrypt(pcose, pRecip, NULL, 0, "Encrypt", perr);
 
 	errorReturn:
 	return f;
@@ -181,8 +181,8 @@
 	int alg;
 	const cn_cbor * cn = NULL;
 
-	byte * pbKey = pbKeyIn;
-	size_t cbitKey = cbKeyIn * 8;
+	byte * pbKey = NULL;
+	size_t cbitKey = 0;
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context * context;
 #endif
@@ -285,7 +285,11 @@
 	//  We are doing the enveloped item - so look for the passed in recipient
 	//
 
-	if (pbKeyIn == NULL) {
+	if (pbKeyIn != NULL) {
+		CHECK_CONDITION(cbKeyIn == cbitKey / 8, COSE_ERR_INVALID_PARAMETER);
+		pbKey = pbKeyIn;
+	}
+	else {
 		//  Allocate the key if we have not already done so
 
 		if (pbKey == NULL) {
@@ -303,7 +307,7 @@
 					if (!_COSE_Recipient_decrypt(pRecipX, pRecip, alg, cbitKey, pbKey, perr)) goto errorReturn;
 					break;
 				}
-				else if (pRecipX->m_recipientNext != NULL) {
+				else if (pRecipX->m_encrypt.m_recipientFirst != NULL) {
 					if (_COSE_Recipient_decrypt(pRecipX, pRecip, alg, cbitKey, pbKey, perr)) break;
 				}
 			}
@@ -410,7 +414,7 @@
 	CHECK_CONDITION(IsValidEnvelopedHandle(h), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(pcose->m_recipientFirst != NULL, COSE_ERR_INVALID_HANDLE);
 
-	return _COSE_Enveloped_encrypt(pcose, NULL, 0, "Enveloped", perr);
+	return _COSE_Enveloped_encrypt(pcose, NULL, 0, "Encrypt", perr);
 
 errorReturn:
 	return false;
@@ -550,6 +554,13 @@
 	const cn_cbor * cbProtected = _COSE_encode_protected(&pcose->m_message, perr);
 	if (cbProtected == NULL) goto errorReturn;
 
+#ifdef USE_COUNTER_SIGNATURES
+	//  Setup Counter Signatures
+	if (!_COSE_CountSign_create(&pcose->m_message, NULL, CBOR_CONTEXT_PARAM_COMMA perr)) {
+		goto errorReturn;
+	}
+#endif
+
 	//  Build authenticated data
 
 	size_t cbAuthData = 0;
@@ -848,3 +859,23 @@
 errorReturn:
 	return (HCOSE_RECIPIENT)p;
 }
+
+#ifdef USE_COUNTER_SIGNATURES
+bool COSE_Enveloped_AddCounterSigner(HCOSE_ENCRYPT hEnv, HCOSE_COUNTERSIGN hSign, cose_errback * perr)
+{
+	CHECK_CONDITION(IsValidEncryptHandle(hEnv), COSE_ERR_INVALID_HANDLE);
+	return _COSE_CounterSign_add(&((COSE_Enveloped *)hEnv)->m_message, hSign, perr);
+
+errorReturn:
+	return false;
+}
+
+HCOSE_COUNTERSIGN COSE_Enveloped_GetCounterSigner(HCOSE_ENCRYPT h, int iSigner, cose_errback * perr)
+{
+	CHECK_CONDITION(IsValidEncryptHandle(h), COSE_ERR_INVALID_HANDLE);
+	return _COSE_CounterSign_get(&((COSE_Enveloped *)h)->m_message, iSigner, perr);
+
+errorReturn:
+	return NULL;
+}
+#endif
diff --git a/src/Encrypt0.c b/src/Encrypt0.c
index b24fdf2..4103292 100644
--- a/src/Encrypt0.c
+++ b/src/Encrypt0.c
@@ -128,7 +128,7 @@
 		return false;
 	}
 
-	f = _COSE_Enveloped_decrypt(pcose, NULL, pbKey, cbKey, "Encrypted", perr);
+	f = _COSE_Enveloped_decrypt(pcose, NULL, pbKey, cbKey, "Encrypt1", perr);
 	return f;
 }
 
@@ -137,7 +137,7 @@
 	CHECK_CONDITION(IsValidEncryptHandle(h), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(pbKey != NULL, COSE_ERR_INVALID_PARAMETER);
 
-	return _COSE_Enveloped_encrypt((COSE_Encrypt *)h, pbKey, cbKey, "Encrypted", perr);
+	return _COSE_Enveloped_encrypt((COSE_Encrypt *)h, pbKey, cbKey, "Encrypt1", perr);
 
 errorReturn:
 	return false;
diff --git a/src/MacMessage.c b/src/MacMessage.c
index df62f1e..0c085c7 100644
--- a/src/MacMessage.c
+++ b/src/MacMessage.c
@@ -617,7 +617,7 @@
 					if (!_COSE_Recipient_decrypt(pRecipX, pRecip, alg, cbitKey, pbKey, perr)) goto errorReturn;
 					break;
 				}
-				else if (pRecipX->m_recipientNext != NULL) {
+				else if (pRecipX->m_encrypt.m_recipientFirst != NULL) {
 					if (_COSE_Recipient_decrypt(pRecipX, pRecip, alg, cbitKey, pbKey, perr)) break;
 				}
 			}
diff --git a/src/MacMessage0.c b/src/MacMessage0.c
index 43df47b..2702985 100644
--- a/src/MacMessage0.c
+++ b/src/MacMessage0.c
@@ -222,161 +222,3 @@
 errorReturn:
 	return false;
 }
-
-#if 0
-	int foo() {
-		COSE_Mac0Message * pcose = (COSE_Mac0Message *)h;
-		byte * pbAuthData = NULL;
-		int cbitKey = 0;
-		bool fRet = false;
-		int alg;
-		const cn_cbor * cn = NULL;
-
-#ifdef USE_CBOR_CONTEXT
-		cn_cbor_context * context = NULL;
-#endif
-		size_t cbAuthData;
-
-		CHECK_CONDITION(IsValidMac0Handle(h), COSE_ERR_INVALID_PARAMETER);
-
-#ifdef USE_CBOR_CONTEXT
-		context = &pcose->m_message.m_allocContext;
-#endif
-
-		cn = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
-		if (cn == NULL) goto errorReturn;
-
-		if (cn->type == CN_CBOR_TEXT) {
-			FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
-		}
-		else {
-			CHECK_CONDITION((cn->type == CN_CBOR_UINT || cn->type == CN_CBOR_INT), COSE_ERR_INVALID_PARAMETER);
-
-			alg = (int)cn->v.uint;
-
-			switch (alg) {
-#ifdef USE_AES_CBC_MAC_128_64
-			case COSE_Algorithm_CBC_MAC_128_64:
-				cbitKey = 128;
-				break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_128_128
-			case COSE_Algorithm_CBC_MAC_128_128:
-				cbitKey = 128;
-				break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_256_64
-			case COSE_Algorithm_CBC_MAC_256_64:
-				cbitKey = 256;
-				break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_256_128
-			case COSE_Algorithm_CBC_MAC_256_128:
-				cbitKey = 256;
-				break;
-#endif
-
-#ifdef USE_HMAC_256_64
-			case COSE_Algorithm_HMAC_256_64:
-				cbitKey = 256;
-				break;
-#endif
-
-#ifdef USE_HMAC_256_256
-			case COSE_Algorithm_HMAC_256_256:
-				cbitKey = 256;
-				break;
-#endif
-
-#ifdef USE_HMAC_384_384
-			case COSE_Algorithm_HMAC_384_384:
-				cbitKey = 384;
-				break;
-#endif
-
-#ifdef USE_HMAC_512_512
-			case COSE_Algorithm_HMAC_512_512:
-				cbitKey = 512;
-				break;
-#endif
-
-			default:
-				FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
-				break;
-			}
-		}
-
-		//  Build protected headers
-
-		cn_cbor * cnProtected = _COSE_arrayget_int(&pcose->m_message, INDEX_PROTECTED);
-		CHECK_CONDITION((cnProtected != NULL) && (cnProtected->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
-
-		//  Build authenticated data
-		if (!_COSE_Mac_Build_AAD(&pcose->m_message, "MAC0", &pbAuthData, &cbAuthData, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
-
-		switch (alg) {
-#ifdef USE_HMAC_256_256
-		case COSE_Algorithm_HMAC_256_256:
-			if (!HMAC_Validate((COSE_MacMessage *)pcose, 256, 256, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-			break;
-#endif
-
-#ifdef USE_HMAC_256_64
-		case COSE_Algorithm_HMAC_256_64:
-			if (!HMAC_Validate((COSE_MacMessage *)pcose, 256, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-			break;
-#endif
-
-#ifdef USE_HMAC_384_384
-		case COSE_Algorithm_HMAC_384_384:
-			if (!HMAC_Validate((COSE_MacMessage *)pcose, 384, 384, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-			break;
-#endif
-
-#ifdef USE_HMAC_512_512
-		case COSE_Algorithm_HMAC_512_512:
-			if (!HMAC_Validate((COSE_MacMessage *)pcose, 512, 512, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-			break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_128_64
-		case COSE_Algorithm_CBC_MAC_128_64:
-			if (!AES_CBC_MAC_Validate((COSE_MacMessage *)pcose, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-			break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_256_64
-		case COSE_Algorithm_CBC_MAC_256_64:
-			if (!AES_CBC_MAC_Validate((COSE_MacMessage *)pcose, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-			break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_128_128
-		case COSE_Algorithm_CBC_MAC_128_128:
-			if (!AES_CBC_MAC_Validate((COSE_MacMessage *)pcose, 128, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-			break;
-#endif
-
-#ifdef USE_AES_CBC_MAC_256_128
-		case COSE_Algorithm_CBC_MAC_256_128:
-			if (!AES_CBC_MAC_Validate((COSE_MacMessage *)pcose, 128, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-			break;
-#endif
-
-		default:
-			FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
-			break;
-		}
-
-		fRet = true;
-
-	errorReturn:
-		if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-
-		return fRet;
-	}
-
-#endif
\ No newline at end of file
diff --git a/src/Recipient.c b/src/Recipient.c
index ff6cc02..3b21268 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -288,10 +288,12 @@
 
 #ifdef USE_Direct_HKDF_AES_128
 	case COSE_Algorithm_Direct_HKDF_AES_128:
+		break;
 #endif
 
 #ifdef USE_Direct_HKDF_AES_256
 	case COSE_Algorithm_Direct_HKDF_AES_256:
+		break;
 #endif
 
 #ifdef USE_Direct_HKDF_HMAC_SHA_256
diff --git a/src/SignerInfo.c b/src/SignerInfo.c
index dd21e33..55dc346 100644
--- a/src/SignerInfo.c
+++ b/src/SignerInfo.c
@@ -34,7 +34,6 @@
 	return true;
 }
 
-
 bool COSE_Signer_Free(HCOSE_SIGNER hSigner)
 {
 	COSE_SignerInfo * pSigner = (COSE_SignerInfo *)hSigner;
@@ -67,7 +66,7 @@
 		return NULL;
 	}
 
-	if (!_COSE_Init(COSE_INIT_FLAGS_NO_CBOR_TAG, &pobj->m_message, COSE_recipient_object, CBOR_CONTEXT_PARAM_COMMA perror)) {
+	if (!_COSE_SignerInfo_Init(COSE_INIT_FLAGS_NO_CBOR_TAG, pobj, COSE_recipient_object, CBOR_CONTEXT_PARAM_COMMA perror)) {
 		_COSE_SignerInfo_Free(pobj);
 		COSE_FREE(pobj, context);
 		return NULL;
@@ -77,6 +76,10 @@
 	return (HCOSE_SIGNER)pobj;
 }
 
+bool _COSE_SignerInfo_Init(COSE_INIT_FLAGS flags, COSE_SignerInfo * pobj, int msgType, CBOR_CONTEXT_COMMA cose_errback * errp)
+{
+	return _COSE_Init(flags, &pobj->m_message, msgType, CBOR_CONTEXT_PARAM_COMMA errp);
+}
 
 
 COSE_SignerInfo * _COSE_SignerInfo_Init_From_Object(cn_cbor * cbor, COSE_SignerInfo * pIn, CBOR_CONTEXT_COMMA cose_errback * perr)
diff --git a/src/configure.h b/src/configure.h
index e4706d4..183ca31 100644
--- a/src/configure.h
+++ b/src/configure.h
@@ -91,3 +91,5 @@
 
 #define USE_OPEN_SSL 1
 #define USE_BCRYPT 0
+
+//#define USE_COUNTER_SIGNATURES
diff --git a/src/cose.h b/src/cose.h
index ab4c19c..6d1cecd 100644
--- a/src/cose.h
+++ b/src/cose.h
@@ -11,6 +11,7 @@
 typedef struct _cose_recipient * HCOSE_RECIPIENT;
 typedef struct _cose_mac * HCOSE_MAC;
 typedef struct _cose_mac0 * HCOSE_MAC0;
+typedef struct _cose_counterSignature * HCOSE_COUNTERSIGN;
 
 /**
 * All of the different kinds of errors
@@ -138,9 +139,13 @@
 
 typedef enum {
 	COSE_Header_Algorithm = 1,
+	COSE_Header_Critical = 2,
 	COSE_Header_Content_Type = 3,
 	COSE_Header_KID = 4,
 	COSE_Header_IV = 5,
+	COSE_Header_Partial_IV = 6,
+	COSE_Header_CounterSign = 7,
+	COSE_Header_Operation_Time = 8,
 
 	COSE_Header_HKDF_salt = -20,
 	COSE_Header_KDF_U_nonce = -21,
@@ -197,6 +202,9 @@
 extern bool COSE_Enveloped_AddRecipient(HCOSE_ENVELOPED hMac, HCOSE_RECIPIENT hRecip, cose_errback * perr);
 HCOSE_RECIPIENT COSE_Enveloped_GetRecipient(HCOSE_ENVELOPED cose, int iRecipient, cose_errback * perr);
 
+extern bool COSE_Enveloped_AddCounterSigner(HCOSE_ENCRYPT hEnv, HCOSE_COUNTERSIGN hSign, cose_errback * perr);
+HCOSE_COUNTERSIGN COSE_Enveloped_GetCounterSigner(HCOSE_ENCRYPT, int iSigner, cose_errback * perr);
+
 /*
  */
 
@@ -310,6 +318,15 @@
 cn_cbor * COSE_Sign0_map_get_int(HCOSE_SIGN0 h, int key, int flags, cose_errback * perror);
 bool COSE_Sign0_map_put_int(HCOSE_SIGN0 cose, int key, cn_cbor * value, int flags, cose_errback * errp);
 
+/*
+ * Counter Signature Routines
+ */
+
+HCOSE_COUNTERSIGN COSE_CounterSign_Init(COSE_INIT_FLAGS flags, CBOR_CONTEXT_COMMA cose_errback * perr);
+bool COSE_CounterSign_Free(HCOSE_COUNTERSIGN cose);
+
+cn_cbor * COSE_CounterSign_map_get_int(HCOSE_COUNTERSIGN h, int key, int flags, cose_errback * perror);
+bool COSE_CounterSign_map_put_int(HCOSE_COUNTERSIGN cose, int key, cn_cbor * value, int flags, cose_errback * errp);
 
 /*
 */
diff --git a/src/cose_int.h b/src/cose_int.h
index 4fc9254..72a2bd5 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -3,6 +3,11 @@
 // These definitions are here because they aren't required for the public
 // interface, and they were quite confusing in cn-cbor.h
 
+#ifdef USE_COUNTER_SIGNATURES
+struct _COSE_COUNTER_SIGN;
+typedef struct _COSE_COUNTER_SIGN COSE_Counter_Sign;
+#endif
+
 typedef struct _COSE {
 	COSE_INIT_FLAGS m_flags;		//  Not sure what goes here yet
 	int m_ownMsg;		//  Do I own the pointer @ m_cbor?
@@ -20,6 +25,9 @@
 	cn_cbor_context m_allocContext;
 #endif
 	struct _COSE * m_handleList;
+#ifdef USE_COUNTER_SIGNATURES
+	COSE_Counter_Sign * m_counterSigners;
+#endif
 } COSE;
 
 struct _SignerInfo;
@@ -79,6 +87,12 @@
 #endif
 typedef COSE_MacMessage COSE_Mac0Message;
 
+#ifdef USE_COUNTER_SIGNATURES
+typedef struct _COSE_COUNTER_SIGN {
+	COSE_SignerInfo m_signer;
+} COSE_CounterSign;
+#endif
+
 #ifdef USE_CBOR_CONTEXT
 /**
 * Allocate enough space for 1 `cn_cbor` structure.
@@ -148,6 +162,7 @@
 extern bool IsValidEnvelopedHandle(HCOSE_ENVELOPED h);
 extern bool IsValidRecipientHandle(HCOSE_RECIPIENT h);
 extern bool IsValidSignerHandle(HCOSE_SIGNER h);
+extern bool IsValidCounterSignHandle(HCOSE_COUNTERSIGN h);
 
 extern bool _COSE_Init(COSE_INIT_FLAGS flags, COSE * pcose, int msgType, CBOR_CONTEXT_COMMA cose_errback * errp);
 extern bool _COSE_Init_From_Object(COSE* pobj, cn_cbor * pcbor, CBOR_CONTEXT_COMMA cose_errback * perror);
@@ -183,6 +198,9 @@
 extern HCOSE_SIGN _COSE_Sign_Init_From_Object(cn_cbor *, COSE_SignMessage * pIn, CBOR_CONTEXT_COMMA cose_errback * errp);
 extern void _COSE_Sign_Release(COSE_SignMessage * p);
 
+//  Signer items
+
+extern bool _COSE_SignerInfo_Init(COSE_INIT_FLAGS flags, COSE_SignerInfo * pcose, int msgType, CBOR_CONTEXT_COMMA cose_errback * errp);
 extern bool _COSE_Signer_sign(COSE_SignerInfo * pSigner, const cn_cbor * pcborBody, const cn_cbor * pcborProtected, cose_errback * perr);
 extern COSE_SignerInfo * _COSE_SignerInfo_Init_From_Object(cn_cbor * cbor, COSE_SignerInfo * pIn, CBOR_CONTEXT_COMMA cose_errback * perr);
 extern bool _COSE_SignerInfo_Free(COSE_SignerInfo * pSigner);
@@ -204,6 +222,11 @@
 extern HCOSE_MAC0 _COSE_Mac0_Init_From_Object(cn_cbor *, COSE_Mac0Message * pIn, CBOR_CONTEXT_COMMA cose_errback * errp);
 extern bool _COSE_Mac0_Release(COSE_Mac0Message * p);
 
+//  Counter Sign Items
+extern HCOSE_COUNTERSIGN _COSE_CounterSign_get(COSE * pMessage, int iSigner, cose_errback * perr);
+extern bool _COSE_CounterSign_add(COSE * pMessage, HCOSE_COUNTERSIGN hSigner, cose_errback * perr);
+extern bool _COSE_CountSign_create(COSE * pMessage, cn_cbor * pcnBody, CBOR_CONTEXT_COMMA cose_errback * perr);
+
 //
 //  Debugging Items
 
@@ -250,3 +273,6 @@
 enum {
 	COSE_Int_Alg_AES_CBC_MAC_256_64 = -22
 };
+
+
+#define COSE_CounterSign_object 1000
\ No newline at end of file
diff --git a/test/encrypt.c b/test/encrypt.c
index b3b9ff5..541fdec 100644
--- a/test/encrypt.c
+++ b/test/encrypt.c
@@ -20,6 +20,7 @@
 {
 	HCOSE_ENVELOPED hEnc = NULL;
 	HCOSE_RECIPIENT hRecip = NULL;
+	HCOSE_RECIPIENT hRecip1 = NULL;
 	HCOSE_RECIPIENT hRecip2 = NULL;
 	bool fRet = false;
 	int type;
@@ -34,42 +35,44 @@
 
 	if (!SetReceivingAttributes((HCOSE)hEnc, pEnveloped, Attributes_Enveloped_protected)) goto errorReturn;
 
-	hRecip = COSE_Enveloped_GetRecipient(hEnc, iRecipient1, NULL);
-	if (hRecip == NULL) goto errorReturn;
-	if (!SetReceivingAttributes((HCOSE)hRecip, pRecipient1, Attributes_Recipient_protected)) goto errorReturn;
+	hRecip1 = COSE_Enveloped_GetRecipient(hEnc, iRecipient1, NULL);
+	if (hRecip1 == NULL) goto errorReturn;
+	if (!SetReceivingAttributes((HCOSE)hRecip1, pRecipient1, Attributes_Recipient_protected)) goto errorReturn;
 
 	if (pRecipient2 != NULL) {
 		pkey = BuildKey(cn_cbor_mapget_string(pRecipient2, "key"), false);
 		if (pkey == NULL) goto errorReturn;
 
-		hRecip2 = COSE_Recipient_GetRecipient(hRecip, iRecipient2, NULL);
+		hRecip2 = COSE_Recipient_GetRecipient(hRecip1, iRecipient2, NULL);
 		if (hRecip2 == NULL) goto errorReturn;
 
 		if (!SetReceivingAttributes((HCOSE)hRecip2, pRecipient2, Attributes_Recipient_protected)) goto errorReturn;
 		if (!COSE_Recipient_SetKey(hRecip2, pkey, NULL)) goto errorReturn;
-	}
-	else {
-		pkey = BuildKey(cn_cbor_mapget_string(pRecipient1, "key"), false);
-		if (pkey == NULL) goto errorReturn;
-		if (!COSE_Recipient_SetKey(hRecip, pkey, NULL)) goto errorReturn;
-	}
 
-
-	cn_cbor * cnStatic = cn_cbor_mapget_string(pRecipient1, "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);
-		}
-	}
-
-	if (pRecipient2 != NULL) {
-		cnStatic = cn_cbor_mapget_string(pRecipient2, "sender_key");
+		cn_cbor * cnStatic = cn_cbor_mapget_string(pRecipient2, "sender_key");
 		if (cnStatic != NULL) {
 			if (COSE_Recipient_map_get_int(hRecip2, COSE_Header_ECDH_SPK, COSE_BOTH, NULL) == 0) {
 				COSE_Recipient_map_put_int(hRecip2, COSE_Header_ECDH_SPK, BuildKey(cnStatic, true), COSE_DONT_SEND, NULL);
 			}
 		}
+
+		hRecip = hRecip2;
 	}
+	else {
+		pkey = BuildKey(cn_cbor_mapget_string(pRecipient1, "key"), false);
+		if (pkey == NULL) goto errorReturn;
+		if (!COSE_Recipient_SetKey(hRecip1, pkey, NULL)) goto errorReturn;
+
+		cn_cbor * cnStatic = cn_cbor_mapget_string(pRecipient1, "sender_key");
+		if (cnStatic != NULL) {
+			if (COSE_Recipient_map_get_int(hRecip1, COSE_Header_ECDH_SPK, COSE_BOTH, NULL) == 0) {
+				COSE_Recipient_map_put_int(hRecip1, COSE_Header_ECDH_SPK, BuildKey(cnStatic, true), COSE_DONT_SEND, NULL);
+			}
+		}
+
+		hRecip = hRecip1;
+	}
+
 
 	if (!fFailBody) {
 		cn_cbor * cn = cn_cbor_mapget_string(pRecipient1, "fail");
@@ -89,7 +92,7 @@
 
 errorReturn:
 	if (hEnc != NULL) COSE_Enveloped_Free(hEnc);
-	if (hRecip != NULL) COSE_Recipient_Free(hRecip);
+	if (hRecip1 != NULL) COSE_Recipient_Free(hRecip1);
 	if (hRecip2 != NULL) COSE_Recipient_Free(hRecip2);