Create and validate the signature test cases
diff --git a/src/Sign.c b/src/Sign.c
index 8417ee8..fbf97bd 100644
--- a/src/Sign.c
+++ b/src/Sign.c
@@ -47,7 +47,7 @@
 		goto errorReturn;
 	}
 
-	pSigners = _COSE_arrayget_int(&pobj->m_message, INDEX_SIGNATURES);
+	pSigners = _COSE_arrayget_int(&pobj->m_message, INDEX_SIGNERS);
 	CHECK_CONDITION(pSigners != NULL, COSE_ERR_INVALID_PARAMETER);
 	CHECK_CONDITION(pSigners->type == CN_CBOR_ARRAY, COSE_ERR_INVALID_PARAMETER);
 
@@ -116,11 +116,7 @@
 	p = cn_cbor_data_create(rgb, (int) cb, CBOR_CONTEXT_PARAM_COMMA NULL);
 	CHECK_CONDITION(p != NULL, COSE_ERR_OUT_OF_MEMORY);
 
-#ifdef USE_ARRAY
 	CHECK_CONDITION(_COSE_array_replace(&pMessage->m_message, p, INDEX_BODY, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_OUT_OF_MEMORY);
-#else
-	CHECK_CONDITION(cn_cbor_mapput_int(pMessage->m_message.m_cbor, COSE_Header_Ciphertext, p, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_OUT_OF_MEMORY);
-#endif
 
 	return true;
 }
@@ -177,25 +173,15 @@
 	pSigner->m_signerNext = pMessage->m_signerFirst;
 	pMessage->m_signerFirst = pSigner;
 
-#ifdef USE_ARRAY
-	cn_cbor * pSigners = cn_cbor_index(pMessage->m_message.m_cbor, INDEX_SIGNATURES+1);   // M00BUG
-#else
-	cn_cbor * pSigners = (cn_cbor *)cn_cbor_mapget_int(pMessage->m_message.m_cbor, COSE_Header_Signers);
-#endif
+	cn_cbor * pSigners = cn_cbor_index(pMessage->m_message.m_cbor, INDEX_SIGNERS);   // M00BUG
+
 	if (pSigners == NULL) {
 		pSigners = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
 		CHECK_CONDITION(pSigners != NULL, COSE_ERR_OUT_OF_MEMORY);
-#ifdef USE_ARRAY
-		if (!_COSE_array_replace(&pMessage->m_message, pSigners, INDEX_SIGNATURES, CBOR_CONTEXT_PARAM_COMMA NULL)) {
+		if (!_COSE_array_replace(&pMessage->m_message, pSigners, INDEX_SIGNERS, CBOR_CONTEXT_PARAM_COMMA NULL)) {
 			CN_CBOR_FREE(pSigners, context);
 			CHECK_CONDITION(false, COSE_ERR_CBOR);
 		}
-#else
-		if (!cn_cbor_mapput_int(pMessage->m_message.m_cbor, COSE_Header_Signers, pSigners, CBOR_CONTEXT_PARAM_COMMA NULL)) {
-			CN_CBOR_FREE(pSigners, context);
-			CHECK_CONDITION(false, COSE_ERR_CBOR);
-		}
-#endif
 	}
 
 	CHECK_CONDITION(cn_cbor_array_append(pSigners, pSigner->m_message.m_cbor, NULL), COSE_ERR_CBOR);
@@ -222,14 +208,8 @@
 	//	context = &pMessage->m_message.m_allocContext;
 #endif
 
-#ifdef USE_ARRAY
 	pcborBody = _COSE_arrayget_int(&pMessage->m_message, INDEX_BODY);
 	CHECK_CONDITION((pcborBody != NULL) && (pcborBody->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
-#else
-	//  From this layer we use the protected fields and the body
-	pcborBody = cn_cbor_mapget_int(pMessage->m_message.m_cbor, COSE_Header_Ciphertext);
-	CHECK_CONDITION(pcborBody != NULL, COSE_ERR_INVALID_PARAMETER);
-#endif
 
 	pcborProtected = _COSE_encode_protected(&pMessage->m_message, perr);
 	if (pcborProtected == NULL) goto errorReturn;
@@ -268,3 +248,69 @@
 errorReturn:
 	return false;
 }
+
+
+bool COSE_Sign_AddSigner(HCOSE_SIGN hSign, HCOSE_SIGNER hSigner, cose_errback * perr)
+{
+	COSE_SignerInfo * pSigner;
+	COSE_SignMessage * pSign;
+	cn_cbor * pSigners = NULL;
+	cn_cbor * pSignersT = NULL;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context = NULL;
+#endif
+	cn_cbor_errback cbor_error;
+
+	CHECK_CONDITION(IsValidSignHandle(hSign), COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(IsValidSignerHandle(hSigner), COSE_ERR_INVALID_PARAMETER);
+
+	pSign = (COSE_SignMessage *)hSign;
+	pSigner = (COSE_SignerInfo *)hSigner;
+
+	pSigner->m_signerNext = pSign->m_signerFirst;
+	pSign->m_signerFirst = pSigner;
+
+#ifdef USE_CBOR_CONTEXT
+	context = &pSign->m_message.m_allocContext;
+#endif // USE_CBOR_CONTEXT
+
+	pSigners = _COSE_arrayget_int(&pSign->m_message, INDEX_SIGNERS);
+	if (pSigners == NULL) {
+		pSignersT = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(pSignersT != NULL, cbor_error);
+
+		CHECK_CONDITION_CBOR(_COSE_array_replace(&pSign->m_message, pSignersT, INDEX_SIGNERS, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
+		pSigners = pSignersT;
+		pSignersT = NULL;
+	}
+
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pSigners, pSigner->m_message.m_cbor, &cbor_error), cbor_error);
+
+
+	return true;
+
+errorReturn:
+	if (pSignersT == NULL) CN_CBOR_FREE(pSignersT, context);
+	return false;
+}
+
+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;
+		return NULL;
+	}
+
+	return _COSE_map_get_int(&((COSE_SignMessage *)h)->m_message, key, flags, perror);
+}
+
+bool COSE_Sign_map_put(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;
+		return false;
+	}
+
+	return _COSE_map_put(&((COSE_SignMessage *)h)->m_message, key, value, flags, perror);
+}
+
diff --git a/src/SignerInfo.c b/src/SignerInfo.c
index 8a5079a..5c763ea 100644
--- a/src/SignerInfo.c
+++ b/src/SignerInfo.c
@@ -14,6 +14,34 @@
 	return true;
 }
 
+
+HCOSE_SIGNER COSE_Signer_Init(CBOR_CONTEXT_COMMA cose_errback * perror)
+{
+	COSE_SignerInfo * pobj = (COSE_SignerInfo *)COSE_CALLOC(1, sizeof(COSE_SignerInfo), context);
+	if (pobj == NULL) {
+		if (perror != NULL) perror->err = COSE_ERR_OUT_OF_MEMORY;
+		return NULL;
+	}
+
+	if (!_COSE_Init(&pobj->m_message, COSE_recipient_object, CBOR_CONTEXT_PARAM_COMMA perror)) {
+		COSE_Signer_Free((HCOSE_SIGNER)pobj);
+		return NULL;
+	}
+
+	return (HCOSE_SIGNER)pobj;
+}
+
+bool COSE_Signer_Free(HCOSE_SIGNER hSigner)
+{
+	if (IsValidSignerHandle(hSigner)) {
+
+		_COSE_Signer_Free((COSE_SignerInfo *)hSigner);
+		return true;
+	}
+
+	return false;
+}
+
 void _COSE_Signer_Free(COSE_SignerInfo * pSigner)
 {
 	COSE_FREE(pSigner, &pSigner->m_message.m_allocContext);
@@ -74,16 +102,19 @@
 	cn_cbor * pcborBody2 = NULL;
 	cn_cbor * pcborProtected2 = NULL;
 	cn_cbor * pcborProtectedSign = NULL;
-	cn_cbor * pcborProtectedSign2 = NULL;
 	cn_cbor * pArray = NULL;
+	cn_cbor * cn = NULL;
+	cn_cbor_errback cbor_error;
 	size_t cbToSign;
 	byte * pbToSign = NULL;
 	bool f;
+	int alg;
 
 	pArray = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
 	if (pArray == NULL) {
 		if (perr != NULL) perr->err = COSE_ERR_OUT_OF_MEMORY;
 	errorReturn:
+		if (cn != NULL) CN_CBOR_FREE(cn, context);
 		if (pcborBody2 != NULL) CN_CBOR_FREE(pcborBody2, context);
 		if (pcborProtected2 != NULL) CN_CBOR_FREE(pcborProtected2, context);
 		if (pArray != NULL) COSE_FREE(pArray, context);
@@ -91,22 +122,50 @@
 		return false;
 	}
 
+	cn = _COSE_map_get_int(&pSigner->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;
+	}
+
+
+	pArray = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(pArray != NULL, cbor_error);
+
+	cn = cn_cbor_string_create("Signature", CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cn != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pArray, cn, &cbor_error), cbor_error);
+	cn = NULL;
+
+	cn = cn_cbor_data_create(pcborProtected->v.bytes, (int) pcborProtected->length, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cn != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pArray, cn, &cbor_error), cbor_error);
+	cn = NULL;
+
 	pcborProtectedSign = _COSE_encode_protected(&pSigner->m_message, perr);
 	if (pcborProtectedSign == NULL) goto errorReturn;
 
-	pcborBody2 = cn_cbor_data_create(pcborBody->v.bytes, (int) pcborBody->length, CBOR_CONTEXT_PARAM_COMMA NULL);
-	CHECK_CONDITION(pcborBody2 != NULL, COSE_ERR_OUT_OF_MEMORY);
+	cn = cn_cbor_data_create(pcborProtectedSign->v.bytes, (int) pcborProtectedSign->length, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cn != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pArray, cn, &cbor_error), cbor_error);
+	cn = NULL;
 
-	pcborProtected2 = cn_cbor_data_create(pcborProtected->v.bytes, (int) pcborProtected->length, CBOR_CONTEXT_PARAM_COMMA NULL);
-	CHECK_CONDITION(pcborProtected2 != NULL, COSE_ERR_OUT_OF_MEMORY);
+	cn = cn_cbor_data_create(NULL, 0, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cn != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pArray, cn, &cbor_error), cbor_error);
+	cn = NULL;
 
-	pcborProtectedSign2 = cn_cbor_data_create(pcborProtectedSign->v.bytes, (int) pcborProtectedSign->length, CBOR_CONTEXT_PARAM_COMMA NULL);
-	CHECK_CONDITION(pcborProtectedSign2 != NULL, COSE_ERR_OUT_OF_MEMORY);
+	cn = cn_cbor_data_create(pcborBody->v.bytes, (int)pcborBody->length, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(cn != NULL, cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_array_append(pArray, cn, &cbor_error), cbor_error);
+	cn = NULL;
 
-	CHECK_CONDITION(cn_cbor_array_append(pArray, pcborProtected2, NULL), COSE_ERR_CBOR);
-	CHECK_CONDITION(cn_cbor_array_append(pArray, pcborProtectedSign2, NULL), COSE_ERR_CBOR);
-	CHECK_CONDITION(cn_cbor_array_append(pArray, cn_cbor_data_create(NULL, 0, CBOR_CONTEXT_PARAM_COMMA NULL), NULL), COSE_ERR_CBOR);
-	CHECK_CONDITION(cn_cbor_array_append(pArray, pcborBody2, NULL), COSE_ERR_CBOR);
 
 	cbToSign = cn_cbor_encoder_write(RgbDontUse4, 0, sizeof(RgbDontUse4), pArray);
 	CHECK_CONDITION(cbToSign > 0, COSE_ERR_CBOR);
@@ -114,7 +173,22 @@
 	CHECK_CONDITION(pbToSign != NULL, COSE_ERR_OUT_OF_MEMORY);
 	CHECK_CONDITION(cn_cbor_encoder_write(pbToSign, 0, cbToSign, pArray), COSE_ERR_CBOR);
 
-	f = ECDSA_Sign(pSigner, pbToSign, cbToSign, perr);
+	switch (alg) {
+	case COSE_Algorithm_ECDSA_SHA_256:
+		f = ECDSA_Sign(pSigner, 256, pbToSign, cbToSign, perr);
+		break;
+
+	case COSE_Algorithm_ECDSA_SHA_384:
+		f = ECDSA_Sign(pSigner, 384, pbToSign, cbToSign, perr);
+		break;
+
+	case COSE_Algorithm_ECDSA_SHA_512:
+		f = ECDSA_Sign(pSigner, 512, pbToSign, cbToSign, perr);
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
 
 	COSE_FREE(pbToSign, context);
 	CN_CBOR_FREE(pArray, context);
@@ -248,3 +322,13 @@
 
 	return false;
 }
+
+bool COSE_Signer_map_put(HCOSE_SIGNER h, int key, cn_cbor * value, int flags, cose_errback * perror)
+{
+	if (!IsValidSignerHandle(h) || (value == NULL)) {
+		if (perror != NULL) perror->err = COSE_ERR_INVALID_PARAMETER;
+		return false;
+	}
+
+	return _COSE_map_put(&((COSE_SignerInfo *)h)->m_message, key, value, flags, perror);
+}
diff --git a/src/cose.h b/src/cose.h
index 907f1c8..609c4c6 100644
--- a/src/cose.h
+++ b/src/cose.h
@@ -187,7 +187,15 @@
 
 bool COSE_Sign_SetContent(HCOSE_SIGN cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
 HCOSE_SIGNER COSE_Sign_add_signer(HCOSE_SIGN cose, const cn_cbor * pkey, int algId, cose_errback * perr);
+extern bool COSE_Sign_AddSigner(HCOSE_SIGN hSign, HCOSE_SIGNER hSigner, cose_errback * perr);
 bool COSE_Sign_Sign(HCOSE_SIGN h, cose_errback * perr);
 HCOSE_SIGNER COSE_Sign_GetSigner(HCOSE_SIGN cose, int iSigner, cose_errback * perr);
 bool COSE_Sign_validate(HCOSE_SIGN hSign, HCOSE_SIGNER hSigner, cose_errback * perr);
+cn_cbor * COSE_Sign_map_get_int(HCOSE_SIGN h, int key, int flags, cose_errback * perror);
+bool COSE_Sign_map_put(HCOSE_SIGN cose, int key, cn_cbor * value, int flags, cose_errback * errp);
+
+
+HCOSE_SIGNER COSE_Signer_Init(CBOR_CONTEXT_COMMA cose_errback * perror);
+bool COSE_Signer_Free(HCOSE_SIGNER cose);
 bool COSE_Signer_SetKey(HCOSE_SIGNER hSigner, const cn_cbor * pkey, cose_errback * perr);
+bool COSE_Signer_map_put(HCOSE_SIGNER cose, int key, cn_cbor * value, int flags, cose_errback * errp);
diff --git a/src/cose_int.h b/src/cose_int.h
index 1ca34fe..b993449 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -165,7 +165,7 @@
 #define INDEX_PROTECTED 0
 #define INDEX_UNPROTECTED 1
 #define INDEX_BODY 2
-#define INDEX_SIGNATURES 3
+#define INDEX_SIGNERS 3
 #define INDEX_RECIPIENTS 3
 #define INDEX_MAC_TAG 3
 #define INDEX_MAC_RECIPIENTS 4
diff --git a/src/crypto.h b/src/crypto.h
index 52f84f1..5eb16d9 100644
--- a/src/crypto.h
+++ b/src/crypto.h
@@ -55,7 +55,7 @@
 * @param[in]	cose_errback *	Error return location
 * @return						Did the function succeed?
 */
-bool ECDSA_Sign(COSE_SignerInfo * pSigner, const byte * rgbToSign, size_t cbToSign, cose_errback * perr);
+bool ECDSA_Sign(COSE_SignerInfo * pSigner, int cbitsDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr);
 bool ECDSA_Verify(COSE_SignerInfo * pSigner, int cbitsDigest, const byte * rgbToSign, size_t cbToSign, const byte * rgbSig, size_t cbSig, cose_errback * perr);
 
 /**
diff --git a/src/openssl.c b/src/openssl.c
index 560d766..214214d 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -625,7 +625,7 @@
 #define COSE_Key_EC_Y -3
 #define COSE_Key_EC_d -4
 
-EC_KEY * ECKey_From(const cn_cbor * pKey, cose_errback * perr)
+EC_KEY * ECKey_From(const cn_cbor * pKey, int * cbGroup, cose_errback * perr)
 {
 	EC_KEY * pNewKey = EC_KEY_new();
 	byte  rgbKey[512+1];
@@ -639,14 +639,17 @@
 	switch (p->v.sint) {
 	case 1: // P-256
 		nidGroup = NID_X9_62_prime256v1;
+		*cbGroup = 256 / 8;
 		break;
 
 	case 2: // P-384
 		nidGroup = NID_secp384r1;
+		*cbGroup = 384 / 8;
 		break;
 
 	case 3: // P-521
 		nidGroup = NID_secp521r1;
+		*cbGroup = (521 + 7) / 8;
 		break;
 
 	default:
@@ -700,19 +703,25 @@
 }
 */
 
-bool ECDSA_Sign(COSE_SignerInfo * pSigner, const byte * rgbToSign, size_t cbToSign, cose_errback * perr)
+bool ECDSA_Sign(COSE_SignerInfo * pSigner, int cbitDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr)
 {
 	EC_KEY * eckey = NULL;
 	byte rgbDigest[EVP_MAX_MD_SIZE];
 	unsigned int cbDigest = sizeof(rgbDigest);
 	byte  * pbSig = NULL;
 	unsigned int cbSig;
+	const EVP_MD * digest;
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context * context = &pSigner->m_message.m_allocContext;
 #endif
 	cn_cbor * p = NULL;
+	ECDSA_SIG * psig = NULL;
+	cn_cbor_errback cbor_error;
+	int cbR;
+	byte rgbSig[66];
+	int cb;
 	
-	eckey = ECKey_From(pSigner->m_pkey, perr);
+	eckey = ECKey_From(pSigner->m_pkey, &cbR, perr);
 	if (eckey == NULL) {
 	errorReturn:
 		if (p != NULL) CN_CBOR_FREE(p, context);
@@ -720,16 +729,34 @@
 		return false;
 	}
 
-	EVP_Digest(rgbToSign, cbToSign, rgbDigest, &cbDigest, EVP_sha256(), NULL);
+	switch (cbitDigest) {
+	case 256: digest = EVP_sha256(); break;
+	case 512: digest = EVP_sha512(); break;
+	case 384: digest = EVP_sha384(); break;
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
 
-	cbSig = ECDSA_size(eckey);
-	pbSig = COSE_CALLOC(cbSig, 1, context);
+	EVP_Digest(rgbToSign, cbToSign, rgbDigest, &cbDigest, digest, NULL);
+
+	psig = ECDSA_do_sign(rgbDigest, cbDigest, eckey);
+	CHECK_CONDITION(psig != NULL, COSE_ERR_CRYPTO_FAIL);
+
+	pbSig = COSE_CALLOC(cbR, 2, context);
 	CHECK_CONDITION(pbSig != NULL, COSE_ERR_OUT_OF_MEMORY);
 
-	CHECK_CONDITION(ECDSA_sign(0, rgbDigest, cbDigest, pbSig, &cbSig, eckey), COSE_ERR_CRYPTO_FAIL);
 
-	p = cn_cbor_data_create(pbSig, cbSig, CBOR_CONTEXT_PARAM_COMMA NULL);
-	CHECK_CONDITION(p != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	cb = BN_bn2bin(psig->r, rgbSig);
+	CHECK_CONDITION(cb <= cbR, COSE_ERR_INVALID_PARAMETER);
+	memcpy(pbSig + cbR - cb, rgbSig, cb);
+
+	cb = BN_bn2bin(psig->s, rgbSig);
+	CHECK_CONDITION(cb <= cbR, COSE_ERR_INVALID_PARAMETER);
+	memcpy(pbSig + 2*cbR - cb, rgbSig, cb);
+
+	p = cn_cbor_data_create(pbSig, cbR*2, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+	CHECK_CONDITION_CBOR(p != NULL, cbor_error);
 
 	CHECK_CONDITION(_COSE_array_replace(&pSigner->m_message, p, INDEX_SIGNATURE, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
 	
@@ -747,8 +774,9 @@
 #endif
 	cn_cbor * p = NULL;
 	ECDSA_SIG sig = { NULL, NULL };
+	int cbR;
 
-	eckey = ECKey_From(pSigner->m_pkey, perr);
+	eckey = ECKey_From(pSigner->m_pkey, &cbR, perr);
 	if (eckey == NULL) {
 	errorReturn:
 		if (sig.r != NULL) BN_free(sig.r);
@@ -767,6 +795,7 @@
 	}
 	EVP_Digest(rgbToSign, cbToSign, rgbDigest, &cbDigest, digest, NULL);
 
+	CHECK_CONDITION(cbSignature / 2 == cbR, COSE_ERR_INVALID_PARAMETER);
 	sig.r = BN_bin2bn(rgbSignature,(int) cbSignature/2, NULL);
 	sig.s = BN_bin2bn(rgbSignature+cbSignature/2, (int) cbSignature/2, NULL);
 
diff --git a/test/sign.c b/test/sign.c
index ab0507c..cb12920 100644
--- a/test/sign.c
+++ b/test/sign.c
@@ -12,7 +12,7 @@
 #include "test.h"
 #include "context.h"
 
-int _ValidateSigned(const cn_cbor * pControl, const byte * pbEncoded, int cbEncoded)
+int _ValidateSigned(const cn_cbor * pControl, const byte * pbEncoded, size_t cbEncoded)
 {
 	const cn_cbor * pInput = cn_cbor_mapget_string(pControl, "input");
 	const cn_cbor * pFail;
@@ -40,7 +40,7 @@
 	pSigners = cn_cbor_mapget_string(pSign, "signers");
 	if ((pSigners == NULL) || (pSigners->type != CN_CBOR_ARRAY)) exit(1);
 
-	iSigner = pSigners->length - 1;
+	iSigner = (int) pSigners->length - 1;
 	pSigners = pSigners->first_child;
 	for (; pSigners != NULL; iSigner--, pSigners = pSigners->next) {
 
@@ -98,6 +98,69 @@
 	return _ValidateSigned(pControl, pbEncoded, cbEncoded);
 }
 
+int BuildSignedMessage(const cn_cbor * pControl)
+{
+	int iSigner;
+
+	//
+	//  We don't run this for all control sequences - skip those marked fail.
+	//
+
+	const cn_cbor * pFail = cn_cbor_mapget_string(pControl, "fail");
+	if ((pFail != NULL) && (pFail->type == CN_CBOR_TRUE)) return 0;
+
+	HCOSE_SIGN hSignObj = COSE_Sign_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+
+	const cn_cbor * pInputs = cn_cbor_mapget_string(pControl, "input");
+	if (pInputs == NULL) exit(1);
+	const cn_cbor * pSign = cn_cbor_mapget_string(pInputs, "sign");
+	if (pSign == NULL) exit(1);
+
+	const cn_cbor * pContent = cn_cbor_mapget_string(pInputs, "plaintext");
+	if (!COSE_Sign_SetContent(hSignObj, pContent->v.bytes, pContent->length, NULL)) goto returnError;
+
+	if (!SetAttributes((HCOSE)hSignObj, cn_cbor_mapget_string(pSign, "protected"), Attributes_Sign_protected)) goto returnError;
+	if (!SetAttributes((HCOSE)hSignObj, cn_cbor_mapget_string(pSign, "unprotected"), Attributes_Sign_unprotected)) goto returnError;
+	if (!SetAttributes((HCOSE)hSignObj, cn_cbor_mapget_string(pSign, "unsent"), Attributes_Sign_unsent)) goto returnError;
+
+	const cn_cbor * pAlg = COSE_Sign_map_get_int(hSignObj, 1, COSE_BOTH, NULL);
+
+	const cn_cbor * pSigners = cn_cbor_mapget_string(pSign, "signers");
+	if ((pSigners == NULL) || (pSigners->type != CN_CBOR_ARRAY)) exit(1);
+
+	pSigners = pSigners->first_child;
+	for (iSigner = 0; pSigners != NULL; iSigner++, pSigners = pSigners->next) {
+		cn_cbor * pkey = BuildKey(cn_cbor_mapget_string(pSigners, "key"));
+		if (pkey == NULL) exit(1);
+
+		HCOSE_SIGNER hSigner = COSE_Signer_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+		if (hSigner == NULL) exit(1);
+
+		if (!SetAttributes((HCOSE)hSigner, cn_cbor_mapget_string(pSigners, "protected"), Attributes_Signer_protected)) goto returnError;
+		if (!SetAttributes((HCOSE)hSigner, cn_cbor_mapget_string(pSigners, "unprotected"), Attributes_Signer_unprotected)) goto returnError;
+		if (!SetAttributes((HCOSE)hSigner, cn_cbor_mapget_string(pSigners, "unsent"), Attributes_Signer_unsent)) goto returnError;
+
+		if (!COSE_Signer_SetKey(hSigner, pkey, NULL)) exit(1);
+
+		if (!COSE_Sign_AddSigner(hSignObj, hSigner, NULL)) exit(1);
+	}
+
+	if (!COSE_Sign_Sign(hSignObj, NULL)) exit(1);
+
+	size_t cb = COSE_Encode((HCOSE)hSignObj, NULL, 0, 0) + 1;
+	byte * rgb = (byte *)malloc(cb);
+	cb = COSE_Encode((HCOSE)hSignObj, rgb, 0, cb);
+
+	int f = _ValidateSigned(pControl, rgb, cb);
+
+	free(rgb);
+	return f;
+
+returnError:
+	CFails += 1;
+	return 1;
+}
+
 
 int SignMessage()
 {
diff --git a/test/test.c b/test/test.c
index c86ffc4..2d56925 100644
--- a/test/test.c
+++ b/test/test.c
@@ -25,7 +25,7 @@
 	int    i;
 } NameMap;
 
-NameMap RgAlgorithmNames[23] = {
+NameMap RgAlgorithmNames[26] = {
 	{"HS256", COSE_Algorithm_HMAC_256_256},
 	{"HS256/64", COSE_Algorithm_HMAC_256_64},
 	{"HS384", COSE_Algorithm_HMAC_384_384},
@@ -48,7 +48,10 @@
 	{"AES-CCM-64-128/64", COSE_Algorithm_AES_CCM_64_64_128},
 	{"AES-CCM-64-256/64", COSE_Algorithm_AES_CCM_64_64_256},
 	{"AES-CCM-64-128/128", COSE_Algorithm_AES_CCM_64_128_128},
-	{"AES-CCM-64-256/128", COSE_Algorithm_AES_CCM_64_128_256}
+	{"AES-CCM-64-256/128", COSE_Algorithm_AES_CCM_64_128_256},
+	{"ES256", COSE_Algorithm_ECDSA_SHA_256},
+	{"ES384", COSE_Algorithm_ECDSA_SHA_384},
+	{"ES512", COSE_Algorithm_ECDSA_SHA_512},
 };
 
 
@@ -209,6 +212,30 @@
 		case Attributes_Enveloped_unsent:
 			COSE_Encrypt_map_put((HCOSE_ENCRYPT)hHandle, keyNew, pValueNew, COSE_DONT_SEND, NULL);
 			break;
+
+		case Attributes_Sign_protected:
+			COSE_Sign_map_put((HCOSE_SIGN)hHandle, keyNew, pValueNew, COSE_PROTECT_ONLY, NULL);
+			break;
+
+		case Attributes_Sign_unprotected:
+			COSE_Sign_map_put((HCOSE_SIGN)hHandle, keyNew, pValueNew, COSE_UNPROTECT_ONLY, NULL);
+			break;
+
+		case Attributes_Sign_unsent:
+			COSE_Sign_map_put((HCOSE_SIGN)hHandle, keyNew, pValueNew, COSE_DONT_SEND, NULL);
+			break;
+
+		case Attributes_Signer_protected:
+			COSE_Signer_map_put((HCOSE_SIGNER)hHandle, keyNew, pValueNew, COSE_PROTECT_ONLY, NULL);
+			break;
+
+		case Attributes_Signer_unprotected:
+			COSE_Signer_map_put((HCOSE_SIGNER)hHandle, keyNew, pValueNew, COSE_UNPROTECT_ONLY, NULL);
+			break;
+
+		case Attributes_Signer_unsent:
+			COSE_Signer_map_put((HCOSE_SIGNER)hHandle, keyNew, pValueNew, COSE_DONT_SEND, NULL);
+			break;
 		}
 	}
 
@@ -537,6 +564,7 @@
 		}
 		else if (cn_cbor_mapget_string(pInput, "sign") != NULL) {
 			ValidateSigned(pControl);
+			BuildSignedMessage(pControl);
 		}
 	}
 	else {
diff --git a/test/test.h b/test/test.h
index 5150c75..0a4ecd4 100644
--- a/test/test.h
+++ b/test/test.h
@@ -34,6 +34,12 @@
 	Attributes_Enveloped_protected,
 	Attributes_Enveloped_unprotected,
 	Attributes_Enveloped_unsent,
+	Attributes_Sign_protected,
+	Attributes_Sign_unprotected,
+	Attributes_Sign_unsent,
+	Attributes_Signer_protected,
+	Attributes_Signer_unprotected,
+	Attributes_Signer_unsent,
 } whichSet;
 
 extern int CFails;