Merge common encryption/decryption routine

Merge to have a single routine for encryption for both versions.
diff --git a/src/Encrypt.c b/src/Encrypt.c
index bd6f25a..f7f7059 100644
--- a/src/Encrypt.c
+++ b/src/Encrypt.c
@@ -164,42 +164,41 @@
 {
 	COSE_Enveloped * pcose = (COSE_Enveloped *)h;
 	COSE_RecipientInfo * pRecip = (COSE_RecipientInfo *)hRecip;
-	cose_errback error = { 0 };
 	bool f = false;
 
 	CHECK_CONDITION(IsValidEnvelopedHandle(h), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(IsValidRecipientHandle(hRecip), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pcose->m_recipientFirst != NULL, COSE_ERR_INVALID_PARAMETER);
 
-	f = _COSE_Enveloped_decrypt(pcose, pRecip, 0, NULL, &error);
-	if (perr != NULL) *perr = error;
+	f = _COSE_Enveloped_decrypt(pcose, pRecip, NULL, 0, "Enveloped", perr);
 
 	errorReturn:
 	return f;
 }
 
-bool _COSE_Enveloped_decrypt(COSE_Enveloped * pcose, COSE_RecipientInfo * pRecip, int cbitKey, byte *pbKeyIn, cose_errback * perr)
+bool _COSE_Enveloped_decrypt(COSE_Enveloped * pcose, COSE_RecipientInfo * pRecip, byte *pbKeyIn, size_t cbKeyIn, const char * szContext, cose_errback * perr)
 {
 	int alg;
 	const cn_cbor * cn = NULL;
 
 	byte * pbKey = pbKeyIn;
+	size_t cbitKey = cbKeyIn * 8;
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context * context;
 #endif
 	byte * pbAuthData = NULL;
 	size_t cbAuthData;
-	byte * pbProtected = NULL;
-	ssize_t cbProtected;
 
 #ifdef USE_CBOR_CONTEXT
 	context = &pcose->m_message.m_allocContext;
 #endif
 
+	CHECK_CONDITION(!((pRecip != NULL) && (pbKeyIn != NULL)), COSE_ERR_INTERNAL);
+
 	cn = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
 	if (cn == NULL) {
 	error:
 	errorReturn:
-		if (pbProtected != NULL) COSE_FREE(pbProtected, context);
 		if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
 		if ((pbKey != NULL) && (pbKeyIn == NULL)) {
 			memset(pbKey, 0xff, cbitKey / 8);
@@ -282,36 +281,45 @@
 		break;
 	}
 
-	//  Allocate the key if we have not already done so
+	//
+	//  We are doing the enveloped item - so look for the passed in recipient
+	//
 
-	if (pbKey == NULL) {
-		pbKey = COSE_CALLOC(cbitKey / 8, 1, context);
-		CHECK_CONDITION(pbKey != NULL, COSE_ERR_OUT_OF_MEMORY);
-	}
+	if (pbKeyIn == NULL) {
+		//  Allocate the key if we have not already done so
 
-	//  If there is a recipient - ask it for the key
+		if (pbKey == NULL) {
+			pbKey = COSE_CALLOC(cbitKey / 8, 1, context);
+			CHECK_CONDITION(pbKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+		}
 
-	for (pRecip = pcose->m_recipientFirst; pRecip != NULL; pRecip = pRecip->m_recipientNext) {
-		if (_COSE_Recipient_decrypt(pRecip, alg, cbitKey, pbKey, perr)) break;
-	}
+		//  If there is a recipient - ask it for the key
 
-	//  Build protected headers
+		if (pRecip != NULL) {
+			COSE_RecipientInfo * pRecipX;
 
-	CHECK_CONDITION(pcose->m_message.m_protectedMap != NULL, COSE_ERR_INVALID_PARAMETER);
-	if ((pcose->m_message.m_protectedMap != NULL) && (pcose->m_message.m_protectedMap->first_child != NULL)) {
-		cbProtected = cn_cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pcose->m_message.m_protectedMap);
-		pbProtected = (byte *)COSE_CALLOC(cbProtected, 1, context);
-		if (pbProtected == NULL) goto error;
-		if (cn_cbor_encoder_write(pbProtected, 0, cbProtected, pcose->m_message.m_protectedMap) != cbProtected) goto error;
-	}
-	else {
-		pbProtected = NULL;
-		cbProtected = 0;
+			for (pRecipX = pcose->m_recipientFirst; pRecipX != NULL; pRecipX = pRecipX->m_recipientNext) {
+				if (pRecipX == pRecip) {
+					if (!_COSE_Recipient_decrypt(pRecipX, pRecip, alg, cbitKey, pbKey, perr)) goto errorReturn;
+					break;
+				}
+				else if (pRecipX->m_recipientNext != NULL) {
+					if (_COSE_Recipient_decrypt(pRecipX, pRecip, alg, cbitKey, pbKey, perr)) break;
+				}
+			}
+			CHECK_CONDITION(pRecipX != NULL, COSE_ERR_NO_RECIPIENT_FOUND);
+		}
+		else {
+			for (pRecip = pcose->m_recipientFirst; pRecip != NULL; pRecip = pRecip->m_recipientNext) {
+				if (_COSE_Recipient_decrypt(pRecip, NULL, alg, cbitKey, pbKey, perr)) break;
+			}
+			CHECK_CONDITION(pRecip != NULL, COSE_ERR_NO_RECIPIENT_FOUND);
+		}
 	}
 
 	//  Build authenticated data
 
-	if (!_COSE_Encrypt_Build_AAD(&pcose->m_message, &pbAuthData, &cbAuthData, "Enveloped", perr)) goto errorReturn;
+	if (!_COSE_Encrypt_Build_AAD(&pcose->m_message, &pbAuthData, &cbAuthData, szContext, perr)) goto errorReturn;
 
 	cn = _COSE_arrayget_int(&pcose->m_message, INDEX_BODY);
 	CHECK_CONDITION(cn != NULL, COSE_ERR_INVALID_PARAMETER);
@@ -388,7 +396,6 @@
 		break;
 	}
 
-	if (pbProtected != NULL) COSE_FREE(pbProtected, context);
 	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
 	if ((pbKey != NULL) && (pbKeyIn == NULL)) COSE_FREE(pbKey, context);
 	if (perr != NULL) perr->err = COSE_ERR_NONE;
@@ -398,6 +405,19 @@
 
 bool COSE_Enveloped_encrypt(HCOSE_ENVELOPED h, cose_errback * perr)
 {
+	COSE_Enveloped * pcose = (COSE_Enveloped *)h;
+
+	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);
+
+errorReturn:
+	return false;
+}
+
+bool _COSE_Enveloped_encrypt(COSE_Enveloped * pcose, const byte * pbKeyIn, size_t cbKeyIn, const char * szContext, cose_errback * perr)
+{
 	int alg;
 	int t;
 	COSE_RecipientInfo * pri;
@@ -405,19 +425,12 @@
 	byte * pbAuthData = NULL;
 	size_t cbitKey;
 #ifdef USE_CBOR_CONTEXT
-	cn_cbor_context * context = NULL;
+	cn_cbor_context * context = &pcose->m_message.m_allocContext;
 #endif
-	COSE_Enveloped * pcose = (COSE_Enveloped *) h;
 	bool fRet = false;
 	byte * pbKey = NULL;
 	size_t cbKey = 0;
 
-	CHECK_CONDITION(IsValidEnvelopedHandle(h), COSE_ERR_INVALID_HANDLE);
-
-#ifdef USE_CBOR_CONTEXT
-	context = &pcose->m_message.m_allocContext;
-#endif // USE_CBOR_CONTEXT
-
 	cn_Alg = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
 	if (cn_Alg == NULL) goto errorReturn;
 
@@ -477,25 +490,42 @@
 #endif
 
 #ifdef USE_AES_GCM_128
-	case COSE_Algorithm_AES_GCM_128: cbitKey = 128; break;
+	case COSE_Algorithm_AES_GCM_128: 
+		cbitKey = 128; 
+		break;
 #endif
+
 #ifdef USE_AES_GCM_192
-	case COSE_Algorithm_AES_GCM_192: cbitKey = 192; break;
+	case COSE_Algorithm_AES_GCM_192: 
+		cbitKey = 192; 
+		break;
 #endif
+
 #ifdef USE_AES_GCM_256
-	case COSE_Algorithm_AES_GCM_256: cbitKey = 256; break;
+	case COSE_Algorithm_AES_GCM_256: 
+		cbitKey = 256; 
+		break;
 #endif
 
 	default:
 		FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
 	}
 
-	//  If we are doing direct encryption - then recipient generates the key
+	//  Enveloped or Encrypted?
 
-	if (pbKey == NULL) {
+	if (pbKeyIn != NULL) {
+		CHECK_CONDITION(cbKeyIn == cbitKey / 8, COSE_ERR_INVALID_PARAMETER);
+		pbKey = pbKeyIn;
+		cbKey = cbKeyIn;
+	}
+	else {
+		//  If we are doing direct encryption - then recipient generates the key
+
 		t = 0;
 		for (pri = pcose->m_recipientFirst; pri != NULL; pri = pri->m_recipientNext) {
 			if (pri->m_encrypt.m_message.m_flags & 1) {
+				CHECK_CONDITION(pbKey == NULL, COSE_ERR_INVALID_PARAMETER);
+
 				t |= 1;
 				pbKey = _COSE_RecipientInfo_generateKey(pri, alg, cbitKey, perr);
 				cbKey = cbitKey / 8;
@@ -506,13 +536,13 @@
 			}
 		}
 		CHECK_CONDITION(t != 3, COSE_ERR_INVALID_PARAMETER);
-	}
 
-	if (pbKey == NULL) {
-		pbKey = (byte *) COSE_CALLOC(cbitKey/8, 1, context);
-		CHECK_CONDITION(pbKey != NULL, COSE_ERR_OUT_OF_MEMORY);
-		cbKey = cbitKey / 8;
-		rand_bytes(pbKey, cbKey);
+		if (t == 2) {
+			pbKey = (byte *)COSE_CALLOC(cbitKey / 8, 1, context);
+			CHECK_CONDITION(pbKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+			cbKey = cbitKey / 8;
+			rand_bytes(pbKey, cbKey);
+		}
 	}
 
 	//  Build protected headers
@@ -523,7 +553,7 @@
 	//  Build authenticated data
 
 	size_t cbAuthData = 0;
-	if (!_COSE_Encrypt_Build_AAD(&pcose->m_message, &pbAuthData, &cbAuthData, "Enveloped", perr)) goto errorReturn;
+	if (!_COSE_Encrypt_Build_AAD(&pcose->m_message, &pbAuthData, &cbAuthData, szContext, perr)) goto errorReturn;
 
 	switch (alg) {
 #ifdef USE_AES_CCM_16_64_128
@@ -606,7 +636,7 @@
 
 errorReturn:
 	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-	if (pbKey != NULL) {
+	if ((pbKey != NULL) && (pbKey != pbKeyIn)) {
 		memset(pbKey, 0, cbKey);
 		COSE_FREE(pbKey, context);
 	}
diff --git a/src/Encrypt0.c b/src/Encrypt0.c
index bca0487..b24fdf2 100644
--- a/src/Encrypt0.c
+++ b/src/Encrypt0.c
@@ -121,7 +121,6 @@
 bool COSE_Encrypt_decrypt(HCOSE_ENCRYPT h, const byte * pbKey, size_t cbKey, cose_errback * perr)
 {
 	COSE_Encrypt * pcose = (COSE_Encrypt *)h;
-	cose_errback error = { 0 };
 	bool f;
 
 	if (!IsValidEncryptHandle(h)) {
@@ -129,389 +128,19 @@
 		return false;
 	}
 
-	f = _COSE_Encrypt_decrypt(pcose, pbKey, cbKey, &error);
-	if (perr != NULL) *perr = error;
+	f = _COSE_Enveloped_decrypt(pcose, NULL, pbKey, cbKey, "Encrypted", perr);
 	return f;
 }
 
-bool _COSE_Encrypt_decrypt(COSE_Encrypt * pcose, const byte * pbKey, size_t cbKey, cose_errback * perr)
-{
-	int alg;
-	const cn_cbor * cn = NULL;
-	size_t cbitKey;
-
-#ifdef USE_CBOR_CONTEXT
-	cn_cbor_context * context;
-#endif
-	byte * pbAuthData = NULL;
-	size_t cbAuthData;
-	byte * pbProtected = NULL;
-	ssize_t cbProtected;
-
-#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) {
-	error:
-	errorReturn:
-		if (pbProtected != NULL) COSE_FREE(pbProtected, context);
-		if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-		return false;
-	}
-	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_CCM_16_64_128
-	case COSE_Algorithm_AES_CCM_16_64_128:
-		cbitKey = 128;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_16_128_128
-	case COSE_Algorithm_AES_CCM_16_128_128:
-		cbitKey = 128;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_64_128
-	case COSE_Algorithm_AES_CCM_64_64_128:
-		cbitKey = 128;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_128_128
-	case COSE_Algorithm_AES_CCM_64_128_128:
-		cbitKey = 128;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_64_256
-	case COSE_Algorithm_AES_CCM_64_64_256:
-		cbitKey = 256;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_16_128_256
-	case COSE_Algorithm_AES_CCM_16_128_256:
-		cbitKey = 256;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_128_256
-	case COSE_Algorithm_AES_CCM_64_128_256:
-		cbitKey = 256;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_16_64_256
-	case COSE_Algorithm_AES_CCM_16_64_256:
-		cbitKey = 256;
-		break;
-#endif
-
-#ifdef USE_AES_GCM_128
-	case COSE_Algorithm_AES_GCM_128:
-		cbitKey = 128;
-		break;
-#endif
-
-#ifdef USE_AES_GCM_192
-	case COSE_Algorithm_AES_GCM_192:
-		cbitKey = 192;
-		break;
-#endif
-
-#ifdef USE_AES_GCM_256
-	case COSE_Algorithm_AES_GCM_256:
-		cbitKey = 256;
-		break;
-#endif
-
-	default:
-		FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
-		break;
-	}
-
-	CHECK_CONDITION(cbitKey / 8 == cbKey, COSE_ERR_INVALID_PARAMETER);
-
-	//  Build protected headers
-
-	CHECK_CONDITION(pcose->m_message.m_protectedMap != NULL, COSE_ERR_INVALID_PARAMETER);
-	if ((pcose->m_message.m_protectedMap != NULL) && (pcose->m_message.m_protectedMap->first_child != NULL)) {
-		cbProtected = cn_cbor_encoder_write(RgbDontUse, 0, sizeof(RgbDontUse), pcose->m_message.m_protectedMap);
-		pbProtected = (byte *)COSE_CALLOC(cbProtected, 1, context);
-		if (pbProtected == NULL) goto error;
-		if (cn_cbor_encoder_write(pbProtected, 0, cbProtected, pcose->m_message.m_protectedMap) != cbProtected) goto error;
-	}
-	else {
-		pbProtected = NULL;
-		cbProtected = 0;
-	}
-
-	//  Build authenticated data
-	if (!_COSE_Encrypt_Build_AAD(&pcose->m_message, &pbAuthData, &cbAuthData, "Encrypted", perr)) goto errorReturn;
-
-	cn = _COSE_arrayget_int(&pcose->m_message, INDEX_BODY);
-	CHECK_CONDITION(cn != NULL, COSE_ERR_INVALID_PARAMETER);
-
-	switch (alg) {
-#ifdef USE_AES_CCM_16_64_128
-	case COSE_Algorithm_AES_CCM_16_64_128:
-		if (!AES_CCM_Decrypt((COSE_Enveloped *)pcose, 64, 16, pbKey, cbitKey / 8, cn->v.bytes, cn->length, pbAuthData, cbAuthData, perr)) goto error;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_16_64_256
-	case COSE_Algorithm_AES_CCM_16_64_256:
-		if (!AES_CCM_Decrypt((COSE_Enveloped *)pcose, 64, 16, pbKey, cbitKey / 8, cn->v.bytes, cn->length, pbAuthData, cbAuthData, perr)) goto error;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_16_128_128
-	case COSE_Algorithm_AES_CCM_16_128_128:
-		if (!AES_CCM_Decrypt((COSE_Enveloped *)pcose, 128, 16, pbKey, cbitKey / 8, cn->v.bytes, cn->length, pbAuthData, cbAuthData, perr)) goto error;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_16_128_256
-	case COSE_Algorithm_AES_CCM_16_128_256:
-		if (!AES_CCM_Decrypt((COSE_Enveloped *)pcose, 128, 16, pbKey, cbitKey / 8, cn->v.bytes, cn->length, pbAuthData, cbAuthData, perr)) goto error;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_64_128
-	case COSE_Algorithm_AES_CCM_64_64_128:
-		if (!AES_CCM_Decrypt((COSE_Enveloped *)pcose, 64, 64, pbKey, cbitKey / 8, cn->v.bytes, cn->length, pbAuthData, cbAuthData, perr)) goto error;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_64_256
-	case COSE_Algorithm_AES_CCM_64_64_256:
-		if (!AES_CCM_Decrypt((COSE_Enveloped *)pcose, 64, 64, pbKey, cbitKey / 8, cn->v.bytes, cn->length, pbAuthData, cbAuthData, perr)) goto error;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_128_128
-	case COSE_Algorithm_AES_CCM_64_128_128:
-		if (!AES_CCM_Decrypt((COSE_Enveloped *)pcose, 128, 64, pbKey, cbitKey / 8, cn->v.bytes, cn->length, pbAuthData, cbAuthData, perr)) goto error;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_128_256
-	case COSE_Algorithm_AES_CCM_64_128_256:
-		if (!AES_CCM_Decrypt((COSE_Enveloped *)pcose, 128, 64, pbKey, cbitKey / 8, cn->v.bytes, cn->length, pbAuthData, cbAuthData, perr)) goto error;
-		break;
-#endif
-
-#ifdef USE_AES_GCM_128
-	case COSE_Algorithm_AES_GCM_128:
-		if (!AES_GCM_Decrypt((COSE_Enveloped *)pcose, pbKey, cbitKey / 8, cn->v.bytes, cn->length, pbAuthData, cbAuthData, perr)) goto error;
-		break;
-#endif 
-
-#ifdef USE_AES_GCM_192
-	case COSE_Algorithm_AES_GCM_192:
-		if (!AES_GCM_Decrypt((COSE_Enveloped *)pcose, pbKey, cbitKey / 8, cn->v.bytes, cn->length, pbAuthData, cbAuthData, perr)) goto error;
-		break;
-#endif
-
-#ifdef USE_AES_GCM_256
-	case COSE_Algorithm_AES_GCM_256:
-		if (!AES_GCM_Decrypt((COSE_Enveloped *)pcose, pbKey, cbitKey / 8, cn->v.bytes, cn->length, pbAuthData, cbAuthData, perr)) goto error;
-		break;
-#endif
-
-	default:
-		FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
-		break;
-	}
-
-	if (pbProtected != NULL) COSE_FREE(pbProtected, context);
-	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-	if (perr != NULL) perr->err = COSE_ERR_NONE;
-
-	return true;
-}
-
 bool COSE_Encrypt_encrypt(HCOSE_ENCRYPT h, const byte * pbKey, size_t cbKey, cose_errback * perr)
 {
-	int alg;
-	const cn_cbor * cn_Alg = NULL;
-	byte * pbAuthData = NULL;
-	size_t cbitKey;
-#ifdef USE_CBOR_CONTEXT
-	cn_cbor_context * context = NULL;
-#endif
-	COSE_Encrypt * pcose = (COSE_Encrypt *) h;
-	bool fRet = false;
+	CHECK_CONDITION(IsValidEncryptHandle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pbKey != NULL, COSE_ERR_INVALID_PARAMETER);
 
-	CHECK_CONDITION(IsValidEncryptHandle(h), COSE_ERR_INVALID_PARAMETER);
-
-#ifdef USE_CBOR_CONTEXT
-	context = &pcose->m_message.m_allocContext;
-#endif // USE_CBOR_CONTEXT
-
-	cn_Alg = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
-	if (cn_Alg == NULL) goto errorReturn;
-
-	CHECK_CONDITION(cn_Alg->type != CN_CBOR_TEXT, COSE_ERR_UNKNOWN_ALGORITHM);
-	CHECK_CONDITION((cn_Alg->type == CN_CBOR_UINT) || (cn_Alg->type == CN_CBOR_INT), COSE_ERR_INVALID_PARAMETER);
-	alg = (int) cn_Alg->v.uint;
-
-	//  Get the key size
-
-	switch (alg) {
-#ifdef USE_AES_CCM_64_64_128
-	case COSE_Algorithm_AES_CCM_64_64_128:
-		cbitKey = 128;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_16_128_128
-	case COSE_Algorithm_AES_CCM_16_128_128:
-		cbitKey = 128;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_128_128
-	case COSE_Algorithm_AES_CCM_64_128_128:
-		cbitKey = 128;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_16_64_128
-	case COSE_Algorithm_AES_CCM_16_64_128:
-		cbitKey = 128;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_64_256
-	case COSE_Algorithm_AES_CCM_64_64_256:
-		cbitKey = 256;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_16_128_256
-	case COSE_Algorithm_AES_CCM_16_128_256:
-		cbitKey = 256;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_128_256
-	case COSE_Algorithm_AES_CCM_64_128_256:
-		cbitKey = 256;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_16_64_256
-	case COSE_Algorithm_AES_CCM_16_64_256:
-		cbitKey = 256;
-		break;
-#endif
-
-#ifdef USE_AES_GCM_128
-	case COSE_Algorithm_AES_GCM_128: cbitKey = 128; break;
-#endif
-
-#ifdef USE_AES_GCM_192
-	case COSE_Algorithm_AES_GCM_192: cbitKey = 192; break;
-#endif
-
-#ifdef USE_AES_GCM_256
-	case COSE_Algorithm_AES_GCM_256: cbitKey = 256; break;
-#endif
-
-	default:
-		FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
-	}
-
-	//  Build protected headers
-
-	const cn_cbor * cbProtected = _COSE_encode_protected(&pcose->m_message, perr);
-	if (cbProtected == NULL) goto errorReturn;
-
-	//  Build authenticated data
-	size_t cbAuthData = 0;
-
-	if (!_COSE_Encrypt_Build_AAD(&pcose->m_message, &pbAuthData, &cbAuthData, "Encrypted", perr)) goto errorReturn;
-
-	switch (alg) {
-#ifdef USE_AES_CCM_16_64_128
-	case COSE_Algorithm_AES_CCM_16_64_128:
-		if (!AES_CCM_Encrypt((COSE_Enveloped *)pcose, 64, 16, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_16_64_256
-	case COSE_Algorithm_AES_CCM_16_64_256:
-		if (!AES_CCM_Encrypt((COSE_Enveloped *)pcose, 64, 16, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_16_128_128
-	case COSE_Algorithm_AES_CCM_16_128_128:
-		if (!AES_CCM_Encrypt((COSE_Enveloped *)pcose, 128, 16, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_16_128_256
-	case COSE_Algorithm_AES_CCM_16_128_256:
-		if (!AES_CCM_Encrypt((COSE_Enveloped *)pcose, 128, 16, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_64_128
-	case COSE_Algorithm_AES_CCM_64_64_128:
-		if (!AES_CCM_Encrypt((COSE_Enveloped *)pcose, 64, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_64_256
-	case COSE_Algorithm_AES_CCM_64_64_256:
-		if (!AES_CCM_Encrypt((COSE_Enveloped *)pcose, 64, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_128_128
-	case COSE_Algorithm_AES_CCM_64_128_128:
-		if (!AES_CCM_Encrypt((COSE_Enveloped *)pcose, 128, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_CCM_64_128_256
-	case COSE_Algorithm_AES_CCM_64_128_256:
-		if (!AES_CCM_Encrypt((COSE_Enveloped *)pcose, 128, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-#ifdef USE_AES_GCM
-#ifdef USE_AES_GCM_128
-	case COSE_Algorithm_AES_GCM_128:
-#endif
-#ifdef USE_AES_GCM_192
-	case COSE_Algorithm_AES_GCM_192:
-#endif
-#ifdef USE_AES_GCM_256
-	case COSE_Algorithm_AES_GCM_256:
-#endif
-		if (!AES_GCM_Encrypt((COSE_Enveloped *)pcose, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn;
-		break;
-#endif
-
-	default:
-		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
-	}
-
-	//  Figure out the clean up
-
-	fRet = true;
+	return _COSE_Enveloped_encrypt((COSE_Encrypt *)h, pbKey, cbKey, "Encrypted", perr);
 
 errorReturn:
-	if (pbAuthData != NULL) COSE_FREE(pbAuthData, context);
-	return fRet;
+	return false;
 }
 
 bool COSE_Encrypt_SetContent(HCOSE_ENCRYPT h, const byte * rgb, size_t cb, cose_errback * perror)
diff --git a/src/MacMessage.c b/src/MacMessage.c
index a6a9008..d67f63f 100644
--- a/src/MacMessage.c
+++ b/src/MacMessage.c
@@ -585,7 +585,7 @@
 	//  If there is a recipient - ask it for the key
 
 	for (pRecip = pcose->m_recipientFirst; pRecip != NULL; pRecip = pRecip->m_recipientNext) {
-		if (_COSE_Recipient_decrypt(pRecip, alg, cbitKey, pbKey, perr)) break;
+		if (_COSE_Recipient_decrypt(pRecip, NULL, alg, cbitKey, pbKey, perr)) break;
 	}
 	CHECK_CONDITION(pRecip != NULL, COSE_ERR_NO_RECIPIENT_FOUND);
 
diff --git a/src/Recipient.c b/src/Recipient.c
index a40bef5..ff6cc02 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -220,7 +220,7 @@
 	return fRet;
 }
 
-bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, int algIn, int cbitKeyOut, byte * pbKeyOut, cose_errback * perr)
+bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, COSE_RecipientInfo * pRecipUse, int algIn, int cbitKeyOut, byte * pbKeyOut, cose_errback * perr)
 {
 	int alg;
 	const cn_cbor * cn = NULL;
@@ -366,7 +366,7 @@
 		CHECK_CONDITION(pbKeyX != NULL, COSE_ERR_OUT_OF_MEMORY);
 
 		for (pRecip2 = pcose->m_recipientFirst; pRecip2 != NULL; pRecip2 = pRecip->m_recipientNext) {
-			if (_COSE_Recipient_decrypt(pRecip2, alg, cbitKeyX, pbKeyX, perr)) break;
+			if (_COSE_Recipient_decrypt(pRecip2, NULL, alg, cbitKeyX, pbKeyX, perr)) break;
 		}
 		CHECK_CONDITION(pRecip2 != NULL, COSE_ERR_NO_RECIPIENT_FOUND);
 	}
diff --git a/src/cose.h b/src/cose.h
index 8add444..ab4c19c 100644
--- a/src/cose.h
+++ b/src/cose.h
@@ -32,7 +32,9 @@
 	/** Decryption operation failed */
 	COSE_ERR_DECRYPT_FAILED,
 	/** Cryptographic failure */
-	COSE_ERR_CRYPTO_FAIL
+	COSE_ERR_CRYPTO_FAIL,
+	/** Internal Error */
+	COSE_ERR_INTERNAL
 } cose_error;
 
 typedef enum cose_init_flags {
diff --git a/src/cose_int.h b/src/cose_int.h
index 5940398..367c7c8 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -43,11 +43,13 @@
 struct _RecipientInfo;
 typedef struct _RecipientInfo COSE_RecipientInfo;
 
+#if 0
 typedef struct {
 	COSE m_message;		// The message object
 	const byte * pbContent;
 	size_t cbContent;
 } COSE_Encrypt;
+#endif 
 
 typedef struct {
 	COSE m_message;		// The message object
@@ -56,6 +58,8 @@
 	COSE_RecipientInfo * m_recipientFirst;
 } COSE_Enveloped;
 
+typedef COSE_Enveloped COSE_Encrypt;
+
 struct _RecipientInfo {
 	COSE_Enveloped m_encrypt;
 	COSE_RecipientInfo * m_recipientNext;
@@ -155,19 +159,19 @@
 
 extern HCOSE_ENVELOPED _COSE_Enveloped_Init_From_Object(cn_cbor *, COSE_Enveloped * pIn, CBOR_CONTEXT_COMMA cose_errback * errp);
 extern void _COSE_Enveloped_Release(COSE_Enveloped * p);
-extern bool _COSE_Enveloped_decrypt(COSE_Enveloped * pcose, COSE_RecipientInfo * pRecip, int cbitKey, byte *pbKeyIn, cose_errback * perr);
+extern bool _COSE_Enveloped_decrypt(COSE_Enveloped * pcose, COSE_RecipientInfo * pRecip, const byte *pbKeyIn, size_t cbKeyIn, const char * szContext, cose_errback * perr);
+extern bool _COSE_Enveloped_encrypt(COSE_Enveloped * pcose, const byte * pbKeyIn, size_t cbKeyIn, const char * szContext, cose_errback * perr);
 extern bool _COSE_Enveloped_SetContent(COSE_Enveloped * cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
 
 extern HCOSE_ENCRYPT _COSE_Encrypt_Init_From_Object(cn_cbor *, COSE_Encrypt * pIn, CBOR_CONTEXT_COMMA cose_errback * errp);
 extern void _COSE_Encrypt_Release(COSE_Encrypt * p);
-extern bool _COSE_Encrypt_decrypt(COSE_Encrypt * pcose, const byte * pbKey, size_t cbKey, cose_errback * perr);
 extern bool _COSE_Encrypt_SetContent(COSE_Encrypt * cose, const byte * rgbContent, size_t cbContent, cose_errback * errp);
 extern bool _COSE_Encrypt_Build_AAD(COSE * pMessage, byte ** ppbAAD, size_t * pcbAAD, const char * szContext, cose_errback * perr);
 
 
 extern COSE_RecipientInfo * _COSE_Recipient_Init_From_Object(cn_cbor *, CBOR_CONTEXT_COMMA cose_errback * errp);
 extern void _COSE_Recipient_Free(COSE_RecipientInfo *);
-extern bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, int algIn, int cbitKey, byte * pbKey, cose_errback * errp);
+extern bool _COSE_Recipient_decrypt(COSE_RecipientInfo * pRecip, COSE_RecipientInfo * pRecipUse, int algIn, int cbitKey, byte * pbKey, cose_errback * errp);
 extern bool _COSE_Recipient_encrypt(COSE_RecipientInfo * pRecipient, const byte * pbContent, size_t cbContent, cose_errback * perr);
 extern byte * _COSE_RecipientInfo_generateKey(COSE_RecipientInfo * pRecipient, int algIn, size_t cbitKeySize, cose_errback * perr);
 
diff --git a/src/openssl.c b/src/openssl.c
index ef53f19..82d5296 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -34,7 +34,6 @@
 	cn_cbor_context * context = &pcose->m_message.m_allocContext;
 #endif
 
-	assert(perr != NULL);
 	EVP_CIPHER_CTX_init(&ctx);
 
 	//  Setup the IV/Nonce and put it into the message
@@ -214,7 +213,6 @@
 #endif
 	int TSize = 128 / 8;
 
-	assert(perr != NULL);
 	EVP_CIPHER_CTX_init(&ctx);
 
 	//  Setup the IV/Nonce and put it into the message