Add CounterSign1 to code base (#117)

* Add CounterSign0 to code base

* Fix compiler errors

* Fix context compiler issues

* Fix testing errors

* Fix 2 compiler errors and a crash

* See if the crashes go away

* More bug fixes

* It would be nice if both compilers look at this the same

* Update SignerInfo.cpp

stupid gcc compiler.  does not actually do this right

* More memory leak checks

* Fix bug

correct free code

* Deal with counterisign1 issues

* Context needs to be ifdef dependent

* Remove unused function call

* Allocation failures

* Fix errors from new test cases

* Correct building COSE from EC key for OpenSSL

* Update build scripts

Build countersign1 on appveyor and github
Correct the path from the countersign1 rename in cmake.

* Increase coverage

* FIx apveyor build script
* Add countersign1 testing to Sign1
diff --git a/.appveyor.yml b/.appveyor.yml
index 90e8665..3bc14b3 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -32,7 +32,7 @@
   - cmake --version
   - mkdir build
   - cd build
-  - cmake -DCOSE_C_USE_CONTEXT=%USE_CONTEXT% -DCOSE_C_USE_MBEDTLS=%USE_EMBEDTLS% -DBUILD_SHARED_LIBS=OFF -G "Visual Studio 16 2019" ..
+  - cmake -DCOSE_C_USE_CONTEXT=%USE_CONTEXT% -DCOSE_C_USE_MBEDTLS=%USE_EMBEDTLS% -DBUILD_SHARED_LIBS=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON -G "Visual Studio 16 2019" ..
 
 build_script:
   - msbuild cose-c.sln
diff --git a/.clang-tidy b/.clang-tidy
index d3e1aa5..d0d5160 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -26,9 +26,7 @@
 -modernize-use-trailing-return-type,                    \
 -fuchsia-default-arguments-calls,                       \
 # TODO remove following lines,                          \
--readability-braces-around-statements,                  \
 -cppcoreguidelines-avoid-magic-numbers,                 \
--hicpp-braces-around-statements,                         \
 -readability-magic-numbers,             \
 -cppcoreguidelines-avoid-magic-numbers,         \
 -cppcoreguidelines-init-variables,          \
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 3387630..907265a 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -21,19 +21,19 @@
         COMPILER: ["gcc", "clang"]

         CMAKE_OPTIONS:

           [

-            "-DCOSE_C_INCLUDE_ENCRYPT=ON -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=OFF",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=ON -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=OFF",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=ON -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=OFF",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=ON -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=OFF",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=ON -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=OFF",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=ON -DCOSE_C_INCLUDE_COUNTERSIGN=OFF",

-            "-DCOSE_C_INCLUDE_ENCRYPT=ON -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=ON -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=ON -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=ON -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=ON -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON",

-            "-DCOSE_C_OPTIMIZE=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON"

+            "-DCOSE_C_INCLUDE_ENCRYPT=ON -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=OFF -DCOSE_C_INCLUDE_COUNTERSIGN1=OFF",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=ON -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=OFF -DCOSE_C_INCLUDE_COUNTERSIGN1=OFF",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=ON -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=OFF -DCOSE_C_INCLUDE_COUNTERSIGN1=OFF",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=ON -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=OFF -DCOSE_C_INCLUDE_COUNTERSIGN1=OFF",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=ON -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=OFF -DCOSE_C_INCLUDE_COUNTERSIGN1=OFF",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=ON -DCOSE_C_INCLUDE_COUNTERSIGN=OFF -DCOSE_C_INCLUDE_COUNTERSIGN1=OFF",

+            "-DCOSE_C_INCLUDE_ENCRYPT=ON -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=ON -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=ON -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=ON -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=ON -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON",

+            "-DCOSE_C_OPTIMIZE=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON"

           ]

         exclude:

           # this really just does VS not gcc or clang

@@ -125,12 +125,12 @@
             "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=ON -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=OFF",

             "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=ON -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=OFF",

             "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=ON -DCOSE_C_INCLUDE_COUNTERSIGN=OFF",

-            "-DCOSE_C_INCLUDE_ENCRYPT=ON -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=ON -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=ON -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=ON -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=ON -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON",

-            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON",

+            "-DCOSE_C_INCLUDE_ENCRYPT=ON -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=ON -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=ON -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=ON -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=ON -DCOSE_C_INCLUDE_SIGN1=OFF -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON",

+            "-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_ENCRYPT0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON",

           ]

 

     steps:

diff --git a/.gitignore b/.gitignore
index e5b428b..68c3d58 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,6 +47,7 @@
 CMakeCache.txt
 Makefile
 build
+build-*
 
 # Visual Studio files
 *.sdf
diff --git a/.travis.yml b/.travis.yml
index f0b70e6..50d7f94 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,20 +1,21 @@
 language: cpp
 compiler:
   - gcc
-sudo: false
+dist: xenial
+os: linux
 env:
   global:
     - OPENSSL_VERSION="1.1.1f"
       OPENSSL_INSTALL_DIR="${HOME}/opt"
   jobs:
     - USE_CONTEXT=ON
-      COVERALLS="-DCOSE_C_COVERALLS_SEND=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON"
+      COVERALLS="-DCOSE_C_COVERALLS_SEND=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON"
     - USE_CONTEXT=OFF
-      COVERALLS="-DCOSE_C_COVERALLS_SEND=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON"
+      COVERALLS="-DCOSE_C_COVERALLS_SEND=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON"
     - USE_CONTEXT=OFF USE_EMBEDTLS=ON
-      COVERALLS="-DCOSE_C_COVERALLS_SEND=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON"
+      COVERALLS="-DCOSE_C_COVERALLS_SEND=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON"
     - USE_CONTEXT=ON USE_EMBEDTLS=ON
-      COVERALLS="-DCOSE_C_COVERALLS_SEND=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON"
+      COVERALLS="-DCOSE_C_COVERALLS_SEND=ON -DCOSE_C_INCLUDE_COUNTERSIGN=ON -DCOSE_C_INCLUDE_COUNTERSIGN1=ON"
 
 addons:
   apt:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1b00bc5..b1eb816 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,6 +38,7 @@
 option(COSE_C_INCLUDE_SIGN "Include COSE_SIGN" ON)
 option(COSE_C_INCLUDE_SIGN1 "Include COSE_SIGN1" ON)
 option(COSE_C_INCLUDE_COUNTERSIGN "Include COSE_COUNTERSIGN" OFF)
+option(COSE_C_INCLUDE_COUNTERSIGN1 "Include COSE_COUNTERSIGN1" OFF)
 option(COSE_C_VALGRIND_MEMORY_CHECK "use Valgrind to check memory, \
   run `ctest -D ExperimentalMemCheck` then after build to run tests with valgrind" OFF)
 
@@ -133,6 +134,9 @@
 if(NOT COSE_C_INCLUDE_COUNTERSIGN)
   add_definitions(-DINCLUDE_COUNTERSIGN=0)
 endif()
+if(NOT COSE_C_INCLUDE_COUNTERSIGN1)
+  add_definitions(-DINCLUDE_COUNTERSIGN1=0)
+endif()
 if(COSE_C_USE_CONTEXT)
   add_definitions(-DUSE_CBOR_CONTEXT)
 endif()
@@ -306,6 +310,7 @@
 message(STATUS "COSE_C_INCLUDE_SIGN:.............${COSE_C_INCLUDE_SIGN}")
 message(STATUS "COSE_C_INCLUDE_SIGN1:............${COSE_C_INCLUDE_SIGN1}")
 message(STATUS "COSE_C_INCLUDE_COUNTERSIGN:......${COSE_C_INCLUDE_COUNTERSIGN}")
+message(STATUS "COSE_C_INCLUDE_COUNTERSIGN1:.....${COSE_C_INCLUDE_COUNTERSIGN1}")
 message(STATUS "COSE_C_USE_CONTEXT:..............${COSE_C_USE_CONTEXT}")
 message(STATUS "COSE_C_FATAL_WARNINGS:...........${COSE_C_FATAL_WARNINGS}")
 message(STATUS "COSE_C_BUILD_TESTS:..............${COSE_C_BUILD_TESTS}")
diff --git a/include/cose/cose.h b/include/cose/cose.h
index 57cb417..647b1b7 100644
--- a/include/cose/cose.h
+++ b/include/cose/cose.h
@@ -168,6 +168,7 @@
 	COSE_Header_Partial_IV = 6,
 	COSE_Header_CounterSign = 7,
 	COSE_Header_Operation_Time = 8,
+	COSE_Header_CounterSign1 = 9,
 
 	COSE_Header_HKDF_salt = -20,
 	COSE_Header_KDF_U_name = -21,
@@ -225,7 +226,7 @@
 	cn_cbor* pcborKey,
 	CBOR_CONTEXT_COMMA cose_errback* perror);
 #endif
-	
+
 /*
  *  messages dealing with the Enveloped message type
  */
@@ -284,6 +285,12 @@
 	int iSigner,
 	cose_errback* perr);
 
+bool COSE_Enveloped_AddCounterSigner1(HCOSE_ENCRYPT hEnv,
+	HCOSE_COUNTERSIGN1 hSign,
+	cose_errback* perr);
+HCOSE_COUNTERSIGN COSE_Enveloped_GetCounterSigner1(HCOSE_ENCRYPT,
+	cose_errback* perr);
+
 /*
  */
 
@@ -318,7 +325,7 @@
 	int destintion,
 	cose_errback* perror);
 
-	bool COSE_Recipient_SetExternal(HCOSE_RECIPIENT hcose,
+bool COSE_Recipient_SetExternal(HCOSE_RECIPIENT hcose,
 	const byte* pbExternalData,
 	size_t cbExternalData,
 	cose_errback* perr);
@@ -575,8 +582,7 @@
  * Counter Signature Routines
  */
 
-HCOSE_COUNTERSIGN COSE_CounterSign_Init(
-	CBOR_CONTEXT_COMMA cose_errback* perr);
+HCOSE_COUNTERSIGN COSE_CounterSign_Init(CBOR_CONTEXT_COMMA cose_errback* perr);
 bool COSE_CounterSign_Free(HCOSE_COUNTERSIGN cose);
 
 cn_cbor* COSE_CounterSign_map_get_int(HCOSE_COUNTERSIGN h,
@@ -589,7 +595,10 @@
 	int flags,
 	cose_errback* errp);
 
-bool COSE_CounterSign_SetExternal(HCOSE_COUNTERSIGN cose, const byte* pbExternalData, size_t cbExternalData, cose_errback* perr);
+bool COSE_CounterSign_SetExternal(HCOSE_COUNTERSIGN cose,
+	const byte* pbExternalData,
+	size_t cbExternalData,
+	cose_errback* perr);
 bool COSE_CounterSign_SetKey(HCOSE_COUNTERSIGN,
 	const cn_cbor* pkey,
 	cose_errback* perr);
@@ -597,8 +606,35 @@
 	HCOSE_KEY pkey,
 	cose_errback* perr);
 
-	
-HCOSE_COUNTERSIGN COSE_Signer_add_countersignature(HCOSE_SIGNER hSigner, HCOSE_COUNTERSIGN hCountersignature, cose_errback* perr);
+/*
+ * CounterSignature1 Routines
+ */
+
+HCOSE_COUNTERSIGN1 COSE_CounterSign1_Init(
+	CBOR_CONTEXT_COMMA cose_errback* perr);
+bool COSE_CounterSign1_Free(HCOSE_COUNTERSIGN1 cose);
+
+cn_cbor* COSE_CounterSign1_map_get_int(HCOSE_COUNTERSIGN1 h,
+	int key,
+	int flags,
+	cose_errback* perror);
+bool COSE_CounterSign1_map_put_int(HCOSE_COUNTERSIGN1 cose,
+	int key,
+	cn_cbor* value,
+	int flags,
+	cose_errback* errp);
+
+bool COSE_CounterSign1_SetExternal(HCOSE_COUNTERSIGN1 cose,
+	const byte* pbExternalData,
+	size_t cbExternalData,
+	cose_errback* perr);
+bool COSE_CounterSign1_SetKey(HCOSE_COUNTERSIGN1,
+	HCOSE_KEY pkey,
+	cose_errback* perr);
+
+HCOSE_COUNTERSIGN COSE_Signer_add_countersignature(HCOSE_SIGNER hSigner,
+	HCOSE_COUNTERSIGN hCountersignature,
+	cose_errback* perr);
 HCOSE_COUNTERSIGN COSE_Signer_get_countersignature(HCOSE_SIGNER hSigner,
 	int index,
 	cose_errback* perr);
@@ -606,6 +642,15 @@
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
 
+HCOSE_COUNTERSIGN1 COSE_Signer_add_countersignature1(HCOSE_SIGNER hSigner,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+HCOSE_COUNTERSIGN1 COSE_Signer_get_countersignature1(HCOSE_SIGNER hSigner,
+	cose_errback* perr);
+bool COSE_Signer_CounterSign1_validate(HCOSE_SIGNER hSigner,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+
 HCOSE_COUNTERSIGN COSE_Sign_add_countersignature(HCOSE_SIGN hSignMsg,
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
@@ -616,6 +661,15 @@
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
 
+HCOSE_COUNTERSIGN1 COSE_Sign_add_countersignature1(HCOSE_SIGN hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+HCOSE_COUNTERSIGN1 COSE_Sign_get_countersignature1(HCOSE_SIGN hSignMsg,
+	cose_errback* perr);
+bool COSE_Sign_CounterSign1_validate(HCOSE_SIGN hSigner,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+
 HCOSE_COUNTERSIGN COSE_Sign1_add_countersignature(HCOSE_SIGN1 hSignMsg,
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
@@ -626,6 +680,15 @@
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
 
+HCOSE_COUNTERSIGN1 COSE_Sign1_add_countersignature1(HCOSE_SIGN1 hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+HCOSE_COUNTERSIGN1 COSE_Sign1_get_countersignature1(HCOSE_SIGN1 hSignMsg,
+	cose_errback* perr);
+bool COSE_Sign1_CounterSign1_validate(HCOSE_SIGN1 hSigner,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+
 HCOSE_COUNTERSIGN COSE_Encrypt0_add_countersignature(HCOSE_ENCRYPT hSignMsg,
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
@@ -636,6 +699,15 @@
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
 
+HCOSE_COUNTERSIGN1 COSE_Encrypt0_add_countersignature1(HCOSE_ENCRYPT hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+HCOSE_COUNTERSIGN1 COSE_Encrypt0_get_countersignature1(HCOSE_ENCRYPT hSignMsg,
+	cose_errback* perr);
+bool COSE_Encrypt0_CounterSign1_validate(HCOSE_ENCRYPT hSigner,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+
 HCOSE_COUNTERSIGN COSE_Enveloped_add_countersignature(HCOSE_ENVELOPED hSignMsg,
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
@@ -646,6 +718,17 @@
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
 
+HCOSE_COUNTERSIGN1 COSE_Enveloped_add_countersignature1(
+	HCOSE_ENVELOPED hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+HCOSE_COUNTERSIGN1 COSE_Enveloped_get_countersignature1(
+	HCOSE_ENVELOPED hSignMsg,
+	cose_errback* perr);
+bool COSE_Enveloped_CounterSign1_validate(HCOSE_ENVELOPED hSigner,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+
 HCOSE_COUNTERSIGN COSE_Recipient_add_countersignature(HCOSE_RECIPIENT hSignMsg,
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
@@ -656,6 +739,17 @@
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
 
+HCOSE_COUNTERSIGN1 COSE_Recipient_add_countersignature1(
+	HCOSE_RECIPIENT hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+HCOSE_COUNTERSIGN1 COSE_Recipient_get_countersignature1(
+	HCOSE_RECIPIENT hSignMsg,
+	cose_errback* perr);
+bool COSE_Recipient_CounterSign1_validate(HCOSE_RECIPIENT hSigner,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+
 HCOSE_COUNTERSIGN COSE_Mac0_add_countersignature(HCOSE_MAC0 hSignMsg,
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
@@ -666,6 +760,15 @@
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
 
+HCOSE_COUNTERSIGN1 COSE_Mac0_add_countersignature1(HCOSE_MAC0 hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+HCOSE_COUNTERSIGN1 COSE_Mac0_get_countersignature1(HCOSE_MAC0 hSignMsg,
+	cose_errback* perr);
+bool COSE_Mac0_CounterSign1_validate(HCOSE_MAC0 hSigner,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+
 HCOSE_COUNTERSIGN COSE_Mac_add_countersignature(HCOSE_MAC hSignMsg,
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
@@ -675,8 +778,17 @@
 bool COSE_Mac_CounterSign_validate(HCOSE_MAC hSigner,
 	HCOSE_COUNTERSIGN hCountersignature,
 	cose_errback* perr);
-	
-	/*
+
+HCOSE_COUNTERSIGN1 COSE_Mac_add_countersignature1(HCOSE_MAC hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+HCOSE_COUNTERSIGN1 COSE_Mac_get_countersignature1(HCOSE_MAC hSignMsg,
+	cose_errback* perr);
+bool COSE_Mac_CounterSign1_validate(HCOSE_MAC hSigner,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr);
+
+/*
  */
 
 cn_cbor* cn_cbor_clone(const cn_cbor* pIn,
@@ -689,7 +801,7 @@
 	CBOR_CONTEXT_COMMA cn_cbor_errback* errp);
 cn_cbor* cn_cbor_null_create(CBOR_CONTEXT_COMMA cn_cbor_errback* errp);
 #endif
-	
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/cose/cose_configure.h.in b/include/cose/cose_configure.h.in
index 3f97ffd..4a367c7 100644
--- a/include/cose/cose_configure.h.in
+++ b/include/cose/cose_configure.h.in
@@ -80,7 +80,7 @@
 #define USE_AES_CBC_MAC_256_64
 #define USE_AES_CBC_MAC_256_128
 
-#endif  // !defined(COSE_C_USE_MBEDTLS)
+#endif	// !defined(COSE_C_USE_MBEDTLS)
 
 //
 //  Define which ECDH algorithms are to be used
@@ -109,7 +109,7 @@
 #define USE_ECDH 1
 #define USE_HKDF_AES 1
 #endif
-#endif  // !defined(COSE_C_USE_MBEDTLS)
+#endif	// !defined(COSE_C_USE_MBEDTLS)
 
 //
 //  Define which Key Wrap functions are to be used
@@ -119,7 +119,7 @@
 #define USE_AES_KW_128
 #define USE_AES_KW_192
 #define USE_AES_KW_256
-#endif  // !defined(COSE_C_USE_MBEDTLS)
+#endif	// !defined(COSE_C_USE_MBEDTLS)
 
 //
 //  Define which of the DIRECT + KDF algorithms are to be used
@@ -137,7 +137,7 @@
 #if defined(USE_Direct_HKDF_AES_128) || defined(USE_Direct_KDF_AES_256)
 #define USE_HKDF_AES 1
 #endif
-#endif  // !defined(COSE_C_USE_MBEDTLS)
+#endif	// !defined(COSE_C_USE_MBEDTLS)
 
 //
 //  Define which of the signature algorithms are to be used
@@ -156,7 +156,7 @@
 #define TOSTRING(x) STRINGIFY(x)
 #pragma message("OPENSSL VERSION IS " OPENSSL_VERSION_TEXT)
 #endif
-#endif  // defined (COSE_C_USE_OPENSSL)
+#endif	// defined (COSE_C_USE_OPENSSL)
 
 //
 //   Define which COSE objects are included
@@ -184,5 +184,5 @@
 #define INCLUDE_COUNTERSIGNATURE 1
 #endif
 #ifndef INCLUDE_COUNTERSIGNATURE1
-#define INCLUDE_COUNTERSIGNATURE1 0
+#define INCLUDE_COUNTERSIGNATURE1 1
 #endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 18788e6..5522b29 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -42,7 +42,7 @@
     utils.hpp
     CoseKey.cpp
     CounterSign.cpp
-    CounterSign0.cpp
+    CounterSign1.cpp
     MacMessage.cpp
     MacMessage0.cpp
     Sign.cpp
diff --git a/src/Cose.cpp b/src/Cose.cpp
index 03162ee..50f5c75 100644
--- a/src/Cose.cpp
+++ b/src/Cose.cpp
@@ -23,7 +23,6 @@
 	CBOR_CONTEXT_COMMA cose_errback *perr)
 {
 	cn_cbor_errback errState;
-	;
 
 #ifdef USE_CBOR_CONTEXT
 	if (context != nullptr) {
@@ -88,7 +87,7 @@
 
 	if (false) {
 	errorReturn:
-		return false;	
+		return false;
 	}
 
 #ifdef USE_CBOR_CONTEXT
@@ -96,6 +95,9 @@
 		pobj->m_allocContext = *context;
 	}
 #endif
+	if (pobj->m_cborRoot != nullptr && pobj->m_ownMsg) {
+		CN_CBOR_FREE(pobj->m_cborRoot, context);
+	}
 	pobj->m_cborRoot = pcbor;
 	pobj->m_cbor = pcbor;
 
@@ -124,6 +126,9 @@
 		}
 	}
 
+	if (pobj->m_unprotectMap != NULL) {
+		CN_CBOR_FREE(pobj->m_unprotectMap, context);
+	}
 	pobj->m_unprotectMap = _COSE_arrayget_int(pobj, INDEX_UNPROTECTED);
 	CHECK_CONDITION((pobj->m_unprotectMap != nullptr) &&
 						(pobj->m_unprotectMap->type == CN_CBOR_MAP),
@@ -158,11 +163,22 @@
 	}
 #endif
 
+#if INCLUDE_COUNTERSIGNATURE1
+	cn_cbor *pCounter1 =
+		cn_cbor_mapget_int(pobj->m_unprotectMap, COSE_Header_CounterSign1);
+	if (pCounter1 != NULL) {
+		CHECK_CONDITION(
+			pCounter1->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
+		COSE_CounterSign1 *cs = _COSE_CounterSign1_Init_From_Object(
+			pCounter1, NULL, CBOR_CONTEXT_PARAM_COMMA perr);
+		pobj->m_counterSign1 = cs;
+	}
+#endif
+
 	pobj->m_ownMsg = true;
 	pobj->m_refCount = 1;
 
 	return true;
-
 }
 
 void _COSE_Release(COSE *pcose)
@@ -197,7 +213,14 @@
 		}
 	}
 #endif
+
+	#if INCLUDE_COUNTERSIGNATURE1
+	if (pcose->m_counterSign1 != NULL) {
+		COSE_CounterSign1_Free((HCOSE_COUNTERSIGN1)pcose->m_counterSign1);
+	}
+#endif
 }
+	
 
 HCOSE COSE_Decode(const byte *rgbData,
 	size_t cbData,
@@ -211,11 +234,10 @@
 
 	if (false) {
 	errorReturn:
-		// M00TODO - break up the init and allocation below for memory tests.
 		CN_CBOR_FREE(cbor, context);
 		return nullptr;	
 	}
-	
+
 	CHECK_CONDITION(
 		(rgbData != nullptr) && (ptype != nullptr), COSE_ERR_INVALID_PARAMETER);
 
@@ -229,33 +251,27 @@
 				COSE_ERR_INVALID_PARAMETER);
 		}
 		else {
-			struct_type = (COSE_object_type) cbor->v.uint;
+			struct_type = (COSE_object_type)cbor->v.uint;
 		}
 		*ptype = struct_type;
-
-		cn_cbor *ptag = cbor;
-		cbor = ptag->first_child;
-		ptag->first_child = nullptr;
-		ptag->last_child = nullptr;
-		cbor->parent = nullptr;
-		CN_CBOR_FREE(ptag, context);
 	}
 	else {
 		*ptype = struct_type;
 	}
 
-	CHECK_CONDITION(cbor->type == CN_CBOR_ARRAY, COSE_ERR_INVALID_PARAMETER);
+	// CHECK_CONDITION(cbor->type == CN_CBOR_ARRAY, COSE_ERR_INVALID_PARAMETER);
 
-	cn_cbor *cbor2 = cbor;
-	cbor = nullptr;
 	switch (*ptype) {
 		case COSE_enveloped_object:
 #if INCLUDE_ENCRYPT
+		{
 			h = (HCOSE)_COSE_Enveloped_Init_From_Object(
-				cbor2, nullptr, CBOR_CONTEXT_PARAM_COMMA perr);
+				cbor, nullptr, CBOR_CONTEXT_PARAM_COMMA perr);
 			if (h == nullptr) {
 				goto errorReturn;
 			}
+			cbor = nullptr;
+		}
 #else
 			FAIL_CONDITION(COSE_ERR_UNSUPPORTED_COSE_TYPE);
 #endif
@@ -264,7 +280,7 @@
 		case COSE_sign_object:
 #if INCLUDE_SIGN
 			h = (HCOSE)_COSE_Sign_Init_From_Object(
-				cbor2, nullptr, CBOR_CONTEXT_PARAM_COMMA perr);
+				cbor, nullptr, CBOR_CONTEXT_PARAM_COMMA perr);
 			if (h == nullptr) {
 				goto errorReturn;
 			}
@@ -276,7 +292,7 @@
 		case COSE_sign1_object:
 #if INCLUDE_SIGN1
 			h = (HCOSE)_COSE_Sign1_Init_From_Object(
-				cbor2, nullptr, CBOR_CONTEXT_PARAM_COMMA perr);
+				cbor, nullptr, CBOR_CONTEXT_PARAM_COMMA perr);
 			if (h == nullptr) {
 				goto errorReturn;
 			}
@@ -288,7 +304,7 @@
 		case COSE_mac_object:
 #if INCLUDE_MAC
 			h = (HCOSE)_COSE_Mac_Init_From_Object(
-				cbor2, nullptr, CBOR_CONTEXT_PARAM_COMMA perr);
+				cbor, nullptr, CBOR_CONTEXT_PARAM_COMMA perr);
 			if (h == nullptr) {
 				goto errorReturn;
 			}
@@ -300,7 +316,7 @@
 		case COSE_mac0_object:
 #if INCLUDE_MAC0
 			h = (HCOSE)_COSE_Mac0_Init_From_Object(
-				cbor2, nullptr, CBOR_CONTEXT_PARAM_COMMA perr);
+				cbor, nullptr, CBOR_CONTEXT_PARAM_COMMA perr);
 			if (h == nullptr) {
 				goto errorReturn;
 			}
@@ -312,7 +328,7 @@
 		case COSE_encrypt_object:
 #if INCLUDE_ENCRYPT0
 			h = (HCOSE)_COSE_Encrypt_Init_From_Object(
-				cbor2, nullptr, CBOR_CONTEXT_PARAM_COMMA perr);
+				cbor, nullptr, CBOR_CONTEXT_PARAM_COMMA perr);
 			if (h == nullptr) {
 				goto errorReturn;
 			}
@@ -326,7 +342,6 @@
 	}
 
 	return h;
-
 }
 
 size_t COSE_Encode(HCOSE msg, byte *rgb, size_t ib, size_t cb)
@@ -474,7 +489,7 @@
 cn_cbor *_COSE_encode_protected(COSE *pMessage, cose_errback *perr)
 {
 	cn_cbor *pProtected;
-	int cbProtected;
+	size_t cbProtected;
 	byte *pbProtected = nullptr;
 #ifdef USE_CBOR_CONTEXT
 	cn_cbor_context *context = &pMessage->m_allocContext;
@@ -495,7 +510,7 @@
 		CHECK_CONDITION(pbProtected != nullptr, COSE_ERR_OUT_OF_MEMORY);
 
 		CHECK_CONDITION(cn_cbor_encoder_write(pbProtected, 0, cbProtected,
-							pMessage->m_protectedMap) == cbProtected,
+							pMessage->m_protectedMap) == static_cast<ssize_t>(cbProtected),
 			COSE_ERR_CBOR);
 	}
 	else {
@@ -592,6 +607,9 @@
 #if INCLUDE_COUNTERSIGNATURE
 extern COSE *CountersignRoot;
 #endif
+#if INCLUDE_COUNTERSIGNATURE1
+extern COSE *Countersign1Root;
+#endif
 #if INCLUDE_SIGN
 extern COSE *SignerRoot;
 extern COSE *SignRoot;
@@ -614,6 +632,7 @@
 #if INCLUDE_MAC0
 extern COSE *Mac0Root;
 #endif
+extern COSE_KEY *KeysRoot;
 
 bool AreListsEmpty()
 {
@@ -621,6 +640,9 @@
 #if INCLUDE_COUNTERSIGNATURE
 	fRet &= CountersignRoot == nullptr;
 #endif
+#if INCLUDE_COUNTERSIGNATURE1
+	fRet &= Countersign1Root == NULL;
+#endif
 #if INCLUDE_SIGN
 	fRet &= SignerRoot == nullptr && SignRoot == nullptr;
 #endif
@@ -642,6 +664,7 @@
 #if INCLUDE_MAC0
 	fRet &= Mac0Root == nullptr;
 #endif
+	fRet &= KeysRoot == nullptr;
 	return fRet;
 }
 
diff --git a/src/CoseKey.cpp b/src/CoseKey.cpp
index d22a84e..6663945 100644
--- a/src/CoseKey.cpp
+++ b/src/CoseKey.cpp
@@ -58,13 +58,13 @@
 		pkey->m_allocContext = *context;
 	}
 #endif
-	
+
 	pkey->m_refCount = 1;
 	pkey->m_cborKey = pcborKey;
 
 	pkey->m_nextKey = KeysRoot;
 	KeysRoot = pkey;
-	
+
 	return (HCOSE_KEY)pkey;
 }
 
@@ -72,14 +72,14 @@
 {
 	COSE_KEY *p = (COSE_KEY *)h;
 	if (!IsValidKeyHandle(h)) {
-		return false;	
+		return false;
 	}
 
 	if (p->m_refCount > 1) {
 		p->m_refCount--;
 		return true;
 	}
-	
+
 	if (KeysRoot == p) {
 		KeysRoot = p->m_nextKey;
 		p->m_nextKey = nullptr;;
@@ -94,14 +94,19 @@
 			}
 		}
 	}
-	
+	if (p->m_cborKey != nullptr && p->m_cborKey->parent == nullptr) {
+		CN_CBOR_FREE(p->m_cborKey, &p->m_allocContext);
+	}
+
 	COSE_FREE(p, &p->m_allocContext);
 
 	return true;
 }
 
 #if defined(COSE_C_USE_OPENSSL) && (OPENSSL_VERSION_NUMBER > 0x10100000L)
-HCOSE_KEY COSE_KEY_FromEVP(EVP_PKEY * opensslKey, cn_cbor * pcborKey, CBOR_CONTEXT_COMMA cose_errback* perror)
+HCOSE_KEY COSE_KEY_FromEVP(EVP_PKEY *opensslKey,
+	cn_cbor *pcborKey,
+	CBOR_CONTEXT_COMMA cose_errback *perror)
 {
 	COSE_KEY *pkey = nullptr;
 
diff --git a/src/CounterSign.cpp b/src/CounterSign.cpp
index 6b329c6..dbef207 100644
--- a/src/CounterSign.cpp
+++ b/src/CounterSign.cpp
@@ -248,7 +248,9 @@
 	return fRet;
 }
 
-bool COSE_CounterSign_SetKey2(HCOSE_COUNTERSIGN hSigner, HCOSE_KEY hKey, cose_errback* perr)
+bool COSE_CounterSign_SetKey2(HCOSE_COUNTERSIGN hSigner,
+	HCOSE_KEY hKey,
+	cose_errback* perr)
 {
 	bool fRet = false;
 	COSE_CounterSign* pSigner = (COSE_CounterSign*)hSigner;
@@ -260,14 +262,14 @@
 	if (pSigner->m_signer.m_pkey != nullptr) {
 		COSE_KEY_Free((HCOSE_KEY) pSigner->m_signer.m_pkey);
 	}
-	
+
 	pSigner->m_signer.m_pkey = pKey;
 	if (hKey != nullptr) {
 		pKey->m_refCount += 1;
 	}
 	fRet = true;
 
-	errorReturn:
+errorReturn:
 	return fRet;
 }
 
@@ -463,9 +465,9 @@
 {
 	if (false) {
 	errorReturn:
-		return false;	
+		return false;
 	}
-	
+
 	CHECK_CONDITION(IsValidSignerHandle(hSigner), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(
 		IsValidCounterSignHandle(hCountersignature), COSE_ERR_INVALID_HANDLE);
@@ -487,7 +489,6 @@
 		cnProtected, "CounterSignature", perr);
 
 	return f;
-
 }
 
 /***************************************************************************************************
@@ -534,9 +535,9 @@
 {
 	if (false) {
 	errorReturn:
-		return false;	
+		return false;
 	}
-	
+
 	CHECK_CONDITION(IsValidSignHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(
 		IsValidCounterSignHandle(hCountersignature), COSE_ERR_INVALID_HANDLE);
@@ -558,7 +559,6 @@
 		cnProtected, "CounterSignature", perr);
 
 	return f;
-
 }
 #endif
 
@@ -607,9 +607,9 @@
 {
 	if (false) {
 	errorReturn:
-		return false;		
+		return false;
 	}
-	
+
 	CHECK_CONDITION(IsValidSign1Handle(hSignMsg), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(
 		IsValidCounterSignHandle(hCountersignature), COSE_ERR_INVALID_HANDLE);
@@ -679,7 +679,7 @@
 {
 	if (false) {
 	errorReturn:
-		return false;		
+		return false;
 	}
 	CHECK_CONDITION(IsValidEnvelopedHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(
@@ -751,9 +751,9 @@
 {
 	if (false) {
 	errorReturn:
-		return false;		
+		return false;
 	}
-	
+
 	CHECK_CONDITION(IsValidRecipientHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(
 		IsValidCounterSignHandle(hCountersignature), COSE_ERR_INVALID_HANDLE);
@@ -823,9 +823,9 @@
 {
 	if (false) {
 	errorReturn:
-		return false;		
+		return false;
 	}
-	
+
 	CHECK_CONDITION(IsValidEncryptHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(
 		IsValidCounterSignHandle(hCountersignature), COSE_ERR_INVALID_HANDLE);
@@ -895,9 +895,9 @@
 {
 	if (false) {
 	errorReturn:
-		return false;		
+		return false;
 	}
-	
+
 	CHECK_CONDITION(IsValidMac0Handle(hSignMsg), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(
 		IsValidCounterSignHandle(hCountersignature), COSE_ERR_INVALID_HANDLE);
@@ -967,9 +967,9 @@
 {
 	if (false) {
 	errorReturn:
-		return false;		
+		return false;
 	}
-	
+
 	CHECK_CONDITION(IsValidMacHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(
 		IsValidCounterSignHandle(hCountersignature), COSE_ERR_INVALID_HANDLE);
diff --git a/src/CounterSign0.cpp b/src/CounterSign0.cpp
deleted file mode 100644
index 174d181..0000000
--- a/src/CounterSign0.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include <stdlib.h>
-#ifndef __MBED__
-#include <memory.h>
-#endif
-
-#include "cose/cose.h"
-#include "cose_int.h"
-#include "cose/cose_configure.h"
-#include "cose_crypto.h"
-
-#if USE_COUNTER_SIGNATURE1
-
-extern bool IsValidCounterSign1Handle(HCOSE_COUNTERSIGN1 h);
-
-bool _COSE_CounterSign1_add(COSE* pMessage,
-	HCOSE_COUNTERSIGN1 hSigner,
-	cose_errback* perr)
-{
-	COSE_CounterSign1* pSigner = (COSE_CounterSign1*)hSigner;
-
-	CHECK_CONDITION(
-		IsValidCounterSign1Handle(hSigner), COSE_ERR_INVALID_HANDLE);
-
-	pMessage->m_counterSign1 = pSigner;
-	return true;
-
-errorReturn:
-	return false;
-}
-
-HCOSE_COUNTERSIGN _COSE_CounterSign1_get(COSE* pMessage, cose_errback* perr)
-{
-	UNUSED(perr);
-
-	COSE_CounterSign1* pSigner = pMessage->m_counterSign1;
-
-	return (HCOSE_COUNTERSIGN)pSigner;
-}
-
-bool _COSE_CountSign_create(COSE* pMessage,
-	cn_cbor* pcnBody,
-	CBOR_CONTEXT_COMMA cose_errback* perr)
-{
-	cn_cbor* pArray = nullptr;
-	cn_cbor_errback cbor_err;
-	COSE_CounterSign1* pSigner = nullptr;
-	cn_cbor* pcnProtected = nullptr;
-	cn_cbor* pcn = nullptr;
-	cn_cbor* pcn2 = nullptr;
-
-	if (pMessage->m_counterSigners == nullptr)
-		return true;
-
-	//  One or more than one?
-	if (pMessage->m_counterSigners->m_signer.m_signerNext != nullptr) {
-		pArray = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA & cbor_err);
-		CHECK_CONDITION_CBOR(pArray != nullptr, cbor_err);
-	}
-
-	pcnProtected = _COSE_arrayget_int(pMessage, INDEX_PROTECTED);
-	CHECK_CONDITION(pcnProtected != nullptr, COSE_ERR_INTERNAL);
-
-	for (pSigner = pMessage->m_counterSigners; pSigner != nullptr;
-		 pSigner = pSigner->m_next) {
-		CHECK_CONDITION(
-			pSigner->m_signer.m_signerNext == nullptr, COSE_ERR_INTERNAL);
-
-		pcn = cn_cbor_data_create(pcnProtected->v.bytes, pcnProtected->v.count,
-			CBOR_CONTEXT_PARAM_COMMA & cbor_err);
-		CHECK_CONDITION_CBOR(pcnProtected != nullptr, cbor_err);
-
-		pcn2 = cn_cbor_clone(pcnBody, CBOR_CONTEXT_PARAM_COMMA & cbor_err);
-		CHECK_CONDITION_CBOR(pcnBody != nullptr, cbor_err);
-
-		if (!_COSE_Signer_sign(&pSigner->m_signer, pcnBody, pcn2, perr))
-			goto errorReturn;
-		pcn = nullptr;
-		pcn2 = nullptr;
-
-		if (pArray != nullptr) {
-			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 != nullptr)
-		CN_CBOR_FREE(pArray, context);
-	if ((pcn != nullptr) && (pcn->parent != nullptr))
-		CN_CBOR_FREE(pcn, context);
-	if ((pcn2 != nullptr) && (pcn2->parent != nullptr))
-		CN_CBOR_FREE(pcn2, context);
-	return false;
-}
-
-#endif
diff --git a/src/CounterSign1.cpp b/src/CounterSign1.cpp
new file mode 100644
index 0000000..3def09c
--- /dev/null
+++ b/src/CounterSign1.cpp
@@ -0,0 +1,1022 @@
+#include <stdlib.h>
+#ifndef __MBED__
+#include <memory.h>
+#endif
+
+#include "cose/cose.h"
+#include "cose_int.h"
+#include "cose/cose_configure.h"
+#include "cose_crypto.h"
+
+#if INCLUDE_COUNTERSIGNATURE1
+
+COSE* Countersign1Root = nullptr;
+
+bool IsValidCounterSign1Handle(HCOSE_COUNTERSIGN1 h)
+{
+	COSE_CounterSign1* p = (COSE_CounterSign1*)h;
+	return _COSE_IsInList(Countersign1Root, &p->m_signer.m_message);
+}
+
+bool _COSE_CounterSign1_Free(COSE_CounterSign1* pSigner)
+{
+	if (pSigner->m_signer.m_message.m_refCount > 1) {
+		pSigner->m_signer.m_message.m_refCount--;
+		return true;
+	}
+
+	_COSE_SignerInfo_Release(&pSigner->m_signer);
+
+	COSE_FREE(pSigner, &pSigner->m_signer.m_message.m_allocContext);
+
+	return true;
+}
+
+COSE_CounterSign1* _COSE_CounterSign1_Init_From_Object(cn_cbor* cbor,
+	COSE_CounterSign1* pIn,
+	CBOR_CONTEXT_COMMA cose_errback* perr)
+{
+	COSE_CounterSign1* pobj = pIn;
+	cn_cbor* newBody = nullptr;
+	cn_cbor* cn2 = nullptr;
+	cn_cbor_errback cborError;
+
+	cose_errback error = {COSE_ERR_NONE};
+	if (perr == nullptr) {
+		perr = &error;
+	}
+
+	if (false) {
+	errorReturn:
+		if (pobj != nullptr && pIn == nullptr) {
+			pobj->m_signer.m_message.m_ownMsg = false;
+			_COSE_CounterSign1_Free(pobj);
+		}
+		if (newBody != nullptr) {
+			CN_CBOR_FREE(newBody, context);
+		}
+		if (cn2 != nullptr) {
+			CN_CBOR_FREE(cn2, context);
+		}
+		return nullptr;		
+	}
+
+	CHECK_CONDITION(cbor->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
+
+	newBody = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA & cborError);
+	CHECK_CONDITION_CBOR(newBody != NULL, cborError);
+
+	cn2 = cn_cbor_data_create(nullptr, 0, CBOR_CONTEXT_PARAM_COMMA &cborError);	 // protected = bstr
+	CHECK_CONDITION_CBOR(cn2 != NULL, cborError);
+	CHECK_CONDITION_CBOR(
+		cn_cbor_array_append(newBody, cn2, &cborError), cborError);
+
+	cn2 = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &cborError);  // unprotected = map
+	CHECK_CONDITION_CBOR(cn2 != NULL, cborError);
+	CHECK_CONDITION_CBOR(
+		cn_cbor_array_append(newBody, cn2, &cborError), cborError);
+
+	cn2 = cn_cbor_clone(cbor, CBOR_CONTEXT_PARAM_COMMA &cborError);	// signature = bstr
+	CHECK_CONDITION_CBOR(
+		cn_cbor_array_append(newBody, cn2, &cborError), cborError);
+	cn2 = nullptr;
+
+	if (pobj == nullptr) {
+		pobj = (COSE_CounterSign1*)COSE_CALLOC(
+			1, sizeof(COSE_CounterSign1), context);
+		CHECK_CONDITION(pobj != NULL, COSE_ERR_OUT_OF_MEMORY);
+	}
+	
+	if (!_COSE_SignerInfo_Init_From_Object(
+			newBody, &pobj->m_signer, CBOR_CONTEXT_PARAM_COMMA perr)) {
+		goto errorReturn;
+	}
+	newBody = nullptr;
+
+	if (pIn == nullptr) {
+		_COSE_InsertInList(&Countersign1Root, &pobj->m_signer.m_message);
+	}
+
+	return pobj;
+}
+
+bool _COSE_CounterSign1_Init(COSE_CounterSign1* pobject,
+	CBOR_CONTEXT_COMMA cose_errback* perror)
+{
+	return _COSE_SignerInfo_Init(COSE_INIT_FLAGS_NO_CBOR_TAG,
+		&pobject->m_signer, COSE_CounterSign1_object,
+		CBOR_CONTEXT_PARAM_COMMA perror);
+}
+
+HCOSE_COUNTERSIGN1 COSE_CounterSign1_Init(
+	CBOR_CONTEXT_COMMA cose_errback* perror)
+{
+	COSE_CounterSign1* pobject =
+		(COSE_CounterSign1*)COSE_CALLOC(1, sizeof(COSE_CounterSign1), context);
+	if (pobject == nullptr) {
+		if (perror != nullptr) {
+			perror->err = COSE_ERR_OUT_OF_MEMORY;
+		}
+		return nullptr;
+	}
+
+	if (!_COSE_CounterSign1_Init(pobject, CBOR_CONTEXT_PARAM_COMMA perror)) {
+		_COSE_CounterSign1_Free(pobject);
+		return nullptr;
+	}
+
+	_COSE_InsertInList(&Countersign1Root, &pobject->m_signer.m_message);
+	return (HCOSE_COUNTERSIGN1)pobject;
+}
+
+bool COSE_CounterSign1_Free(HCOSE_COUNTERSIGN1 h)
+{
+	COSE_CounterSign1* p = (COSE_CounterSign1*)h;
+	bool fRet = false;
+
+	if (!IsValidCounterSign1Handle(h)) {
+		goto errorReturn;
+	}
+
+	if (p->m_signer.m_message.m_refCount > 1) {
+		p->m_signer.m_message.m_refCount--;
+		return true;
+	}
+
+	_COSE_RemoveFromList(&Countersign1Root, &p->m_signer.m_message);
+
+	fRet = _COSE_CounterSign1_Free(p);
+
+errorReturn:
+	return fRet;
+}
+
+///  Add a countersignature to the list used to create the attribute
+///
+bool _COSE_CounterSign1_add(COSE* pMessage,
+	HCOSE_COUNTERSIGN1 hSigner,
+	cose_errback* perr)
+{
+	COSE_CounterSign1* pSigner = (COSE_CounterSign1*)hSigner;
+
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hSigner), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pSigner->m_next == NULL, COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(
+		pMessage->m_counterSign1 == NULL, COSE_ERR_INVALID_PARAMETER);
+
+	pMessage->m_counterSign1 = pSigner;
+	pSigner->m_signer.m_message.m_refCount += 1;
+	return true;
+
+errorReturn:
+	return false;
+}
+
+#if 0
+I Don't remember why I wrote this and if I don't need it any more.
+Keep for a little while and then delete
+/// _COSE_CounterSign1_create
+///
+///	Create the CounterSign attribute based on the set of countersignatures added
+/// to the message.
+///
+
+bool _COSE_CounterSign1_create(COSE* pMessage,
+	cn_cbor* pcnBody,
+	CBOR_CONTEXT_COMMA cose_errback* perr)
+{
+	cn_cbor* pArray = NULL;
+	cn_cbor_errback cbor_err;
+	COSE_CounterSign1* pSigner = NULL;
+	cn_cbor* pcnProtected = NULL;
+	cn_cbor* pcn = NULL;
+	cn_cbor* pcn2 = NULL;
+
+	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_next) {
+		CHECK_CONDITION(
+			pSigner->m_signer.m_signerNext == NULL, COSE_ERR_INTERNAL);
+
+		pcn = cn_cbor_data_create(pcnProtected->v.bytes, pcnProtected->length,
+			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->m_signer, pcnBody, pcn2, "CounterSignature", 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_CounterSign1, 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
+
+#if 0
+bool COSE_CounterSign1_SetKey(HCOSE_COUNTERSIGN1 h,
+	const cn_cbor* pkey,
+	cose_errback* perr)
+{
+	bool fRet = false;
+	HCOSE_KEY coseKey = NULL;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context* context = NULL;
+#endif
+
+	CHECK_CONDITION(pkey != NULL, COSE_ERR_INVALID_PARAMETER);
+	coseKey = COSE_KEY_FromCbor((cn_cbor*)pkey, CBOR_CONTEXT_PARAM_COMMA perr);
+	CHECK_CONDITION(coseKey != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+	fRet = COSE_CounterSign1_SetKey(h, coseKey, perr);
+
+errorReturn:
+	if (coseKey != NULL) {
+		COSE_KEY_Free(coseKey);
+	}
+	return fRet;
+}
+#endif
+
+bool COSE_CounterSign1_SetKey(HCOSE_COUNTERSIGN1 hSigner,
+	HCOSE_KEY hKey,
+	cose_errback* perr)
+{
+	bool fRet = false;
+	COSE_CounterSign1* pSigner = (COSE_CounterSign1*)hSigner;
+	COSE_KEY* pKey = (COSE_KEY*)hKey;
+
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hSigner), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(IsValidKeyHandle(hKey), COSE_ERR_INVALID_HANDLE);
+
+	if (pSigner->m_signer.m_pkey != nullptr) {
+		COSE_KEY_Free((HCOSE_KEY)pSigner->m_signer.m_pkey);
+	}
+
+	pSigner->m_signer.m_pkey = pKey;
+	if (hKey != nullptr) {
+		pKey->m_refCount += 1;
+	}
+	fRet = true;
+
+errorReturn:
+	return fRet;
+}
+
+COSE_CounterSign1* _COSE_Message_get_countersignature1(COSE* pMessage,
+	cose_errback* perr)
+{
+	COSE_CounterSign1* pCounterSign = pMessage->m_counterSign1;
+	CHECK_CONDITION(
+		pMessage->m_counterSign1 != NULL, COSE_ERR_INVALID_PARAMETER);
+
+	if (pCounterSign != nullptr) {
+		pCounterSign->m_signer.m_message.m_refCount += 1;
+	}
+	return pCounterSign;
+
+errorReturn:
+	return nullptr;
+}
+
+bool COSE_CounterSign1_map_put_int(HCOSE_COUNTERSIGN1 h,
+	int key,
+	cn_cbor* value,
+	int flags,
+	cose_errback* perr)
+{
+	CHECK_CONDITION(IsValidCounterSign1Handle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(value != NULL, COSE_ERR_INVALID_PARAMETER);
+
+	return _COSE_map_put(
+		&((COSE_CounterSign1*)h)->m_signer.m_message, key, value, flags, perr);
+
+errorReturn:
+	return false;
+}
+
+/*!
+ * @brief Set the application external data for authentication
+ *
+ * Signer data objects support the authentication of external application
+ * supplied data.  This function is provided to supply that data to the library.
+ *
+ * The external data is not copied, nor will be it freed when the handle is
+ * released.
+ *
+ * @param hcose  Handle for the COSE MAC data object
+ * @param pbEternalData  point to the external data
+ * @param cbExternalData size of the external data
+ * @param perr  location to return errors
+ * @return result of the operation.
+ */
+
+bool COSE_CounterSign1_SetExternal(HCOSE_COUNTERSIGN1 hcose,
+	const byte* pbExternalData,
+	size_t cbExternalData,
+	cose_errback* perr)
+{
+	if (!IsValidCounterSign1Handle(hcose)) {
+		if (perr != nullptr) {
+			perr->err = COSE_ERR_INVALID_HANDLE;
+		}
+		return false;
+	}
+
+	return _COSE_SetExternal(&((COSE_CounterSign1*)hcose)->m_signer.m_message,
+		pbExternalData, cbExternalData, perr);
+}
+
+bool _COSE_CounterSign1_Sign(COSE* baseMessage,
+	CBOR_CONTEXT_COMMA cose_errback* perr)
+{
+	bool fRet = false;
+	cn_cbor* pcborProtectedSign = nullptr;
+	cn_cbor_errback cborerr;
+	byte* sigValue = nullptr;
+	cn_cbor* cn3 = nullptr;
+
+	if (false) {
+	errorReturn:
+		if (sigValue != nullptr) {
+			COSE_FREE(sigValue, context);
+		}
+		if (cn3 != nullptr) {
+			CN_CBOR_FREE(cn3, context);
+		}
+		return fRet;		
+	}
+
+	cn_cbor* pSignature = _COSE_arrayget_int(baseMessage, INDEX_SIGNATURE);
+
+	COSE_CounterSign1* pCountersign = baseMessage->m_counterSign1;
+	pcborProtectedSign = _COSE_encode_protected(baseMessage, perr);
+	if (pcborProtectedSign == nullptr) {
+		goto errorReturn;
+	}
+	if (!_COSE_Signer_sign(&pCountersign->m_signer, pSignature,
+			pcborProtectedSign, "CounterSignature0", perr)) {
+		goto errorReturn;
+	}
+
+	cn_cbor* cn = COSE_get_cbor((HCOSE)baseMessage->m_counterSign1);
+	cn = cn_cbor_index(cn, 2);
+	sigValue = (byte*)COSE_CALLOC(cn->length, 1, context);
+	CHECK_CONDITION(sigValue != NULL, COSE_ERR_OUT_OF_MEMORY);
+	memcpy(sigValue, cn->v.bytes, cn->length);
+	cn3 = cn_cbor_data_create2(sigValue, cn->length, 0, CBOR_CONTEXT_PARAM_COMMA &cborerr);
+	CHECK_CONDITION_CBOR(cn3 != NULL, cborerr);
+	sigValue = nullptr;
+
+	CHECK_CONDITION(_COSE_map_put(baseMessage, COSE_Header_CounterSign1, cn3,
+						COSE_UNPROTECT_ONLY, perr),
+		COSE_ERR_OUT_OF_MEMORY);
+	cn3 = nullptr;
+
+	fRet = true;
+	goto errorReturn;
+}
+
+/*! 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_CounterSign1_map_get_int(HCOSE_COUNTERSIGN1 h,
+	int key,
+	int flags,
+	cose_errback* perror)
+{
+	if (!IsValidCounterSign1Handle(h)) {
+		if (perror != nullptr) {
+			perror->err = COSE_ERR_INVALID_HANDLE;
+		}
+		return nullptr;
+	}
+
+	return _COSE_map_get_int(
+		&((COSE_CounterSign1*)h)->m_signer.m_message, key, flags, perror);
+}
+
+#if INCLUDE_SIGN
+/***************************************************************************************************
+ *
+ *   SIGNER
+ */
+HCOSE_COUNTERSIGN1 COSE_Signer_add_countersignature1(HCOSE_SIGNER hSigner,
+	HCOSE_COUNTERSIGN1 hCountersign,
+	cose_errback* perr)
+{
+	CHECK_CONDITION(IsValidSignerHandle(hSigner), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersign), COSE_ERR_INVALID_HANDLE);
+
+	if (!_COSE_CounterSign1_add(
+			&((COSE_SignerInfo*)hSigner)->m_message, hCountersign, perr)) {
+		goto errorReturn;
+	}
+
+	return hCountersign;
+
+errorReturn:
+	return nullptr;
+}
+
+HCOSE_COUNTERSIGN1 COSE_Signer_get_countersignature1(HCOSE_SIGNER hSigner,
+	cose_errback* perr)
+{
+	COSE_CounterSign1* p = nullptr;
+
+	CHECK_CONDITION(IsValidSignerHandle(hSigner), COSE_ERR_INVALID_HANDLE);
+
+	p = _COSE_Message_get_countersignature1(
+		&((COSE_SignerInfo*)hSigner)->m_message, perr);
+
+errorReturn:
+	return (HCOSE_COUNTERSIGN1)p;
+}
+
+bool COSE_Signer_CounterSign1_validate(HCOSE_SIGNER hSigner,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr)
+{
+	if (false) {
+	errorReturn:
+		return false;
+	}
+
+	CHECK_CONDITION(IsValidSignerHandle(hSigner), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersignature), COSE_ERR_INVALID_HANDLE);
+
+	COSE_SignerInfo* pSigner = (COSE_SignerInfo*)hSigner;
+	COSE_CounterSign1* pCountersign = (COSE_CounterSign1*)hCountersignature;
+
+	const cn_cbor* cnContent =
+		_COSE_arrayget_int(&pSigner->m_message, INDEX_BODY);
+	CHECK_CONDITION(cnContent != NULL && cnContent->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	const cn_cbor* cnProtected =
+		_COSE_arrayget_int(&pSigner->m_message, INDEX_PROTECTED);
+	CHECK_CONDITION(cnProtected != NULL && cnProtected->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	bool f = _COSE_Signer_validate(&pCountersign->m_signer, cnContent,
+		cnProtected, "CounterSignature0", perr);
+
+	return f;
+}
+
+/***************************************************************************************************
+ *
+ *   SIGN MESSAGE
+ */
+HCOSE_COUNTERSIGN1 COSE_Sign_add_countersignature1(HCOSE_SIGN hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersign,
+	cose_errback* perr)
+{
+	CHECK_CONDITION(IsValidSignHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersign), COSE_ERR_INVALID_HANDLE);
+
+	if (!_COSE_CounterSign1_add(
+			&((COSE_SignMessage*)hSignMsg)->m_message, hCountersign, perr)) {
+		goto errorReturn;
+	}
+
+	return hCountersign;
+
+errorReturn:
+	return nullptr;
+}
+
+HCOSE_COUNTERSIGN1 COSE_Sign_get_countersignature1(HCOSE_SIGN hSignMsg,
+	cose_errback* perr)
+{
+	COSE_CounterSign1* p = nullptr;
+
+	CHECK_CONDITION(IsValidSignHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+
+	p = _COSE_Message_get_countersignature1(
+		&((COSE_SignMessage*)hSignMsg)->m_message, perr);
+
+errorReturn:
+	return (HCOSE_COUNTERSIGN1)p;
+}
+
+bool COSE_Sign_CounterSign1_validate(HCOSE_SIGN hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr)
+{
+	if (false) {
+	errorReturn:
+		return false;
+	}
+
+	CHECK_CONDITION(IsValidSignHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersignature), COSE_ERR_INVALID_HANDLE);
+
+	COSE_SignMessage* pSignMsg = (COSE_SignMessage*)hSignMsg;
+	COSE_CounterSign1* pCountersign = (COSE_CounterSign1*)hCountersignature;
+
+	const cn_cbor* cnContent =
+		_COSE_arrayget_int(&pSignMsg->m_message, INDEX_BODY);
+	CHECK_CONDITION(cnContent != NULL && cnContent->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	const cn_cbor* cnProtected =
+		_COSE_arrayget_int(&pSignMsg->m_message, INDEX_PROTECTED);
+	CHECK_CONDITION(cnProtected != NULL && cnProtected->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	bool f = _COSE_Signer_validate(&pCountersign->m_signer, cnContent,
+		cnProtected, "CounterSignature0", perr);
+
+	return f;
+}
+#endif
+
+#if INCLUDE_SIGN1
+/***************************************************************************************************
+ *
+ *   SIGN1 MESSAGE
+ */
+HCOSE_COUNTERSIGN1 COSE_Sign1_add_countersignature1(HCOSE_SIGN1 hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersign,
+	cose_errback* perr)
+{
+	CHECK_CONDITION(IsValidSign1Handle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersign), COSE_ERR_INVALID_HANDLE);
+
+	if (!_COSE_CounterSign1_add(
+			&((COSE_SignMessage*)hSignMsg)->m_message, hCountersign, perr)) {
+		goto errorReturn;
+	}
+
+	return hCountersign;
+
+errorReturn:
+	return nullptr;
+}
+
+HCOSE_COUNTERSIGN1 COSE_Sign1_get_countersignature1(HCOSE_SIGN1 hSignMsg,
+	cose_errback* perr)
+{
+	COSE_CounterSign1* p = nullptr;
+
+	CHECK_CONDITION(IsValidSign1Handle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+
+	p = _COSE_Message_get_countersignature1(
+		&((COSE_SignMessage*)hSignMsg)->m_message, perr);
+
+errorReturn:
+	return (HCOSE_COUNTERSIGN1)p;
+}
+
+bool COSE_Sign1_CounterSign1_validate(HCOSE_SIGN1 hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr)
+{
+	if (false) {
+	errorReturn:
+		return false;
+	}
+
+	CHECK_CONDITION(IsValidSign1Handle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersignature), COSE_ERR_INVALID_HANDLE);
+
+	COSE_Sign1Message* pSignMsg = (COSE_Sign1Message*)hSignMsg;
+	COSE_CounterSign1* pCountersign = (COSE_CounterSign1*)hCountersignature;
+
+	const cn_cbor* cnContent =
+		_COSE_arrayget_int(&pSignMsg->m_message, INDEX_BODY);
+	CHECK_CONDITION(cnContent != NULL && cnContent->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	const cn_cbor* cnProtected =
+		_COSE_arrayget_int(&pSignMsg->m_message, INDEX_PROTECTED);
+	CHECK_CONDITION(cnProtected != NULL && cnProtected->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	bool f = _COSE_Signer_validate(&pCountersign->m_signer, cnContent,
+		cnProtected, "CounterSignature0", perr);
+
+	return f;
+}
+#endif
+
+#if INCLUDE_ENCRYPT
+/***************************************************************************************************
+ *
+ *   ENVELOPED MESSAGE
+ */
+HCOSE_COUNTERSIGN1 COSE_Enveloped_add_countersignature1(
+	HCOSE_ENVELOPED hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersign,
+	cose_errback* perr)
+{
+	CHECK_CONDITION(IsValidEnvelopedHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersign), COSE_ERR_INVALID_HANDLE);
+
+	if (!_COSE_CounterSign1_add(
+			&((COSE_Enveloped*)hSignMsg)->m_message, hCountersign, perr)) {
+		goto errorReturn;
+	}
+
+	return hCountersign;
+
+errorReturn:
+	return nullptr;
+}
+
+HCOSE_COUNTERSIGN1 COSE_Enveloped_get_countersignature1(
+	HCOSE_ENVELOPED hSignMsg,
+	cose_errback* perr)
+{
+	COSE_CounterSign1* p = nullptr;
+
+	CHECK_CONDITION(IsValidEnvelopedHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+
+	p = _COSE_Message_get_countersignature1(
+		&((COSE_Enveloped*)hSignMsg)->m_message, perr);
+
+errorReturn:
+	return (HCOSE_COUNTERSIGN1)p;
+}
+
+bool COSE_Enveloped_CounterSign1_validate(HCOSE_ENVELOPED hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr)
+{
+	if (false) {
+	errorReturn:
+		return false;
+	}
+	CHECK_CONDITION(IsValidEnvelopedHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersignature), COSE_ERR_INVALID_HANDLE);
+
+	COSE_Enveloped* pSignMsg = (COSE_Enveloped*)hSignMsg;
+	COSE_CounterSign1* pCountersign = (COSE_CounterSign1*)hCountersignature;
+
+	const cn_cbor* cnContent =
+		_COSE_arrayget_int(&pSignMsg->m_message, INDEX_BODY);
+	CHECK_CONDITION(cnContent != NULL && cnContent->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	const cn_cbor* cnProtected =
+		_COSE_arrayget_int(&pSignMsg->m_message, INDEX_PROTECTED);
+	CHECK_CONDITION(cnProtected != NULL && cnProtected->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	bool f = _COSE_Signer_validate(&pCountersign->m_signer, cnContent,
+		cnProtected, "CounterSignature0", perr);
+
+	return f;
+}
+#endif
+
+#if INCLUDE_ENCRYPT || INCLUDE_MAC
+/***************************************************************************************************
+ *
+ *   RECIPIENT MESSAGE
+ */
+HCOSE_COUNTERSIGN1 COSE_Recipient_add_countersignature1(
+	HCOSE_RECIPIENT hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersign,
+	cose_errback* perr)
+{
+	CHECK_CONDITION(IsValidRecipientHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersign), COSE_ERR_INVALID_HANDLE);
+
+	if (!_COSE_CounterSign1_add(
+			&((COSE_RecipientInfo*)hSignMsg)->m_encrypt.m_message, hCountersign,
+			perr)) {
+		goto errorReturn;
+	}
+
+	return hCountersign;
+
+errorReturn:
+	return nullptr;
+}
+
+HCOSE_COUNTERSIGN1 COSE_Recipient_get_countersignature1(
+	HCOSE_RECIPIENT hSignMsg,
+	cose_errback* perr)
+{
+	COSE_CounterSign1* p = nullptr;
+
+	CHECK_CONDITION(IsValidRecipientHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+
+	p = _COSE_Message_get_countersignature1(
+		&((COSE_RecipientInfo*)hSignMsg)->m_encrypt.m_message, perr);
+
+errorReturn:
+	return (HCOSE_COUNTERSIGN1)p;
+}
+
+bool COSE_Recipient_CounterSign1_validate(HCOSE_RECIPIENT hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr)
+{
+	if (false) {
+	errorReturn:
+		return false;
+	}
+
+	CHECK_CONDITION(IsValidRecipientHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersignature), COSE_ERR_INVALID_HANDLE);
+
+	COSE_RecipientInfo* pSignMsg = (COSE_RecipientInfo*)hSignMsg;
+	COSE_CounterSign1* pCountersign = (COSE_CounterSign1*)hCountersignature;
+
+	const cn_cbor* cnContent =
+		_COSE_arrayget_int(&pSignMsg->m_encrypt.m_message, INDEX_BODY);
+	CHECK_CONDITION(cnContent != NULL && cnContent->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	const cn_cbor* cnProtected =
+		_COSE_arrayget_int(&pSignMsg->m_encrypt.m_message, INDEX_PROTECTED);
+	CHECK_CONDITION(cnProtected != NULL && cnProtected->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	bool f = _COSE_Signer_validate(&pCountersign->m_signer, cnContent,
+		cnProtected, "CounterSignature0", perr);
+
+	return f;
+}
+#endif
+
+#if INCLUDE_ENCRYPT0
+/***************************************************************************************************
+ *
+ *   ENCRYPT0 MESSAGE
+ */
+HCOSE_COUNTERSIGN1 COSE_Encrypt0_add_countersignature1(HCOSE_ENCRYPT hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersign,
+	cose_errback* perr)
+{
+	CHECK_CONDITION(IsValidEncryptHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersign), COSE_ERR_INVALID_HANDLE);
+
+	if (!_COSE_CounterSign1_add(
+			&((COSE_SignMessage*)hSignMsg)->m_message, hCountersign, perr)) {
+		goto errorReturn;
+	}
+
+	return hCountersign;
+
+errorReturn:
+	return nullptr;
+}
+
+HCOSE_COUNTERSIGN1 COSE_Encrypt0_get_countersignature1(HCOSE_ENCRYPT hSignMsg,
+	cose_errback* perr)
+{
+	COSE_CounterSign1* p = nullptr;
+
+	CHECK_CONDITION(IsValidEncryptHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+
+	p = _COSE_Message_get_countersignature1(
+		&((COSE_SignMessage*)hSignMsg)->m_message, perr);
+
+errorReturn:
+	return (HCOSE_COUNTERSIGN1)p;
+}
+
+bool COSE_Encrypt0_CounterSign1_validate(HCOSE_ENCRYPT hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr)
+{
+	if (false) {
+	errorReturn:
+		return false;
+	}
+
+	CHECK_CONDITION(IsValidEncryptHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersignature), COSE_ERR_INVALID_HANDLE);
+
+	COSE_Encrypt* pSignMsg = (COSE_Encrypt*)hSignMsg;
+	COSE_CounterSign1* pCountersign = (COSE_CounterSign1*)hCountersignature;
+
+	const cn_cbor* cnContent =
+		_COSE_arrayget_int(&pSignMsg->m_message, INDEX_BODY);
+	CHECK_CONDITION(cnContent != NULL && cnContent->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	const cn_cbor* cnProtected =
+		_COSE_arrayget_int(&pSignMsg->m_message, INDEX_PROTECTED);
+	CHECK_CONDITION(cnProtected != NULL && cnProtected->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	bool f = _COSE_Signer_validate(&pCountersign->m_signer, cnContent,
+		cnProtected, "CounterSignature0", perr);
+
+	return f;
+}
+#endif
+
+#if INCLUDE_MAC0
+/***************************************************************************************************
+ *
+ *   MAC0 MESSAGE
+ */
+HCOSE_COUNTERSIGN1 COSE_Mac0_add_countersignature1(HCOSE_MAC0 hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersign,
+	cose_errback* perr)
+{
+	CHECK_CONDITION(IsValidMac0Handle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersign), COSE_ERR_INVALID_HANDLE);
+
+	if (!_COSE_CounterSign1_add(
+			&((COSE_SignMessage*)hSignMsg)->m_message, hCountersign, perr)) {
+		goto errorReturn;
+	}
+
+	return hCountersign;
+
+errorReturn:
+	return nullptr;
+}
+
+HCOSE_COUNTERSIGN1 COSE_Mac0_get_countersignature1(HCOSE_MAC0 hSignMsg,
+	cose_errback* perr)
+{
+	COSE_CounterSign1* p = nullptr;
+
+	CHECK_CONDITION(IsValidMac0Handle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+
+	p = _COSE_Message_get_countersignature1(
+		&((COSE_SignMessage*)hSignMsg)->m_message, perr);
+
+errorReturn:
+	return (HCOSE_COUNTERSIGN1)p;
+}
+
+bool COSE_Mac0_CounterSign1_validate(HCOSE_MAC0 hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr)
+{
+	if (false) {
+	errorReturn:
+		return false;
+	}
+
+	CHECK_CONDITION(IsValidMac0Handle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersignature), COSE_ERR_INVALID_HANDLE);
+
+	COSE_Mac0Message* pSignMsg = (COSE_Mac0Message*)hSignMsg;
+	COSE_CounterSign1* pCountersign = (COSE_CounterSign1*)hCountersignature;
+
+	const cn_cbor* cnContent =
+		_COSE_arrayget_int(&pSignMsg->m_message, INDEX_BODY);
+	CHECK_CONDITION(cnContent != NULL && cnContent->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	const cn_cbor* cnProtected =
+		_COSE_arrayget_int(&pSignMsg->m_message, INDEX_PROTECTED);
+	CHECK_CONDITION(cnProtected != NULL && cnProtected->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	bool f = _COSE_Signer_validate(&pCountersign->m_signer, cnContent,
+		cnProtected, "CounterSignature0", perr);
+
+	return f;
+}
+#endif
+
+#if INCLUDE_MAC
+/***************************************************************************************************
+ *
+ *   ENCRYPT0 MESSAGE
+ */
+HCOSE_COUNTERSIGN1 COSE_Mac_add_countersignature1(HCOSE_MAC hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersign,
+	cose_errback* perr)
+{
+	CHECK_CONDITION(IsValidMacHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersign), COSE_ERR_INVALID_HANDLE);
+
+	if (!_COSE_CounterSign1_add(
+			&((COSE_MacMessage*)hSignMsg)->m_message, hCountersign, perr)) {
+		goto errorReturn;
+	}
+
+	return hCountersign;
+
+errorReturn:
+	return nullptr;
+}
+
+HCOSE_COUNTERSIGN1 COSE_Mac_get_countersignature1(HCOSE_MAC hSignMsg,
+	cose_errback* perr)
+{
+	COSE_CounterSign1* p = nullptr;
+
+	CHECK_CONDITION(IsValidMacHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+
+	p = _COSE_Message_get_countersignature1(
+		&((COSE_MacMessage*)hSignMsg)->m_message, perr);
+
+errorReturn:
+	return (HCOSE_COUNTERSIGN1)p;
+}
+
+bool COSE_Mac_CounterSign1_validate(HCOSE_MAC hSignMsg,
+	HCOSE_COUNTERSIGN1 hCountersignature,
+	cose_errback* perr)
+{
+	if (false) {
+	errorReturn:
+		return false;
+	}
+
+	CHECK_CONDITION(IsValidMacHandle(hSignMsg), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(
+		IsValidCounterSign1Handle(hCountersignature), COSE_ERR_INVALID_HANDLE);
+
+	COSE_MacMessage* pSignMsg = (COSE_MacMessage*)hSignMsg;
+	COSE_CounterSign1* pCountersign = (COSE_CounterSign1*)hCountersignature;
+
+	const cn_cbor* cnContent =
+		_COSE_arrayget_int(&pSignMsg->m_message, INDEX_BODY);
+	CHECK_CONDITION(cnContent != NULL && cnContent->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	const cn_cbor* cnProtected =
+		_COSE_arrayget_int(&pSignMsg->m_message, INDEX_PROTECTED);
+	CHECK_CONDITION(cnProtected != NULL && cnProtected->type == CN_CBOR_BYTES,
+		COSE_ERR_INVALID_PARAMETER);
+
+	bool f = _COSE_Signer_validate(&pCountersign->m_signer, cnContent,
+		cnProtected, "CounterSignature0", perr);
+
+	return f;
+}
+#endif
+
+#endif
diff --git a/src/Encrypt.cpp b/src/Encrypt.cpp
index 79ef464..4105af1 100644
--- a/src/Encrypt.cpp
+++ b/src/Encrypt.cpp
@@ -103,6 +103,9 @@
 	if (pobj == nullptr) {
 		perr->err = COSE_ERR_OUT_OF_MEMORY;
 	errorReturn:
+		if (pobj != nullptr) {
+			pobj->m_message.m_ownMsg = false;
+		}
 		if (pIn == nullptr && pobj != nullptr) {
 			_COSE_Enveloped_Release(pobj);
 			COSE_FREE(pobj, context);
@@ -827,6 +830,15 @@
 	}
 #endif
 
+#if INCLUDE_COUNTERSIGNATURE1
+	if (pcose->m_message.m_counterSign1 != NULL) {
+		if (!_COSE_CounterSign1_Sign(
+				&pcose->m_message, CBOR_CONTEXT_PARAM_COMMA perr)) {
+			goto errorReturn;
+		}
+	}
+#endif
+
 	//  Figure out the clean up
 
 	fRet = true;
diff --git a/src/Encrypt0.cpp b/src/Encrypt0.cpp
index 604aafd..32f312b 100644
--- a/src/Encrypt0.cpp
+++ b/src/Encrypt0.cpp
@@ -52,7 +52,7 @@
 	errorReturn:
 		return nullptr;		
 	}
-	
+
 	CHECK_CONDITION(flags == COSE_INIT_FLAGS_NONE, COSE_ERR_INVALID_PARAMETER);
 	COSE_Encrypt *pobj =
 		(COSE_Encrypt *)COSE_CALLOC(1, sizeof(COSE_Encrypt), context);
@@ -123,6 +123,7 @@
 		perr->err = COSE_ERR_OUT_OF_MEMORY;
 	errorReturn:
 		if (pobj != nullptr) {
+			pobj->m_message.m_ownMsg = false;
 			_COSE_Encrypt_Release(pobj);
 			if (pIn == nullptr) {
 				COSE_FREE(pobj, context);
@@ -139,7 +140,9 @@
 	pRecipients = _COSE_arrayget_int(&pobj->m_message, INDEX_RECIPIENTS);
 	CHECK_CONDITION(pRecipients == nullptr, COSE_ERR_INVALID_PARAMETER);
 
-	_COSE_InsertInList(&EncryptRoot, &pobj->m_message);
+	if (pIn == nullptr) {
+		_COSE_InsertInList(&EncryptRoot, &pobj->m_message);
+	}
 
 	return (HCOSE_ENCRYPT)pobj;
 }
diff --git a/src/MacMessage.cpp b/src/MacMessage.cpp
index 304b665..db2a758 100644
--- a/src/MacMessage.cpp
+++ b/src/MacMessage.cpp
@@ -86,6 +86,7 @@
 		perr->err = COSE_ERR_OUT_OF_MEMORY;
 	errorReturn:
 		if (pobj != nullptr) {
+			pobj->m_message.m_ownMsg = false;
 			_COSE_Mac_Release(pobj);
 			if (pIn == nullptr) {
 				COSE_FREE(pobj, context);
@@ -409,9 +410,9 @@
 		if (pbAuthData != nullptr) {
 			COSE_FREE(pbAuthData, context);
 		}
-		return fRet;		
+		return fRet;
 	}
-	
+
 	cn_Alg = _COSE_map_get_int(
 		&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, perr);
 	if (cn_Alg == nullptr) {
@@ -623,6 +624,15 @@
 	}
 #endif
 
+#if INCLUDE_COUNTERSIGNATURE1
+	if (pcose->m_message.m_counterSign1 != NULL) {
+		if (!_COSE_CounterSign1_Sign(
+				&pcose->m_message, CBOR_CONTEXT_PARAM_COMMA perr)) {
+			goto errorReturn;
+		}
+	}
+#endif
+
 	//  Figure out the clean up
 
 	fRet = true;
@@ -916,6 +926,7 @@
 
 	pRecip->m_recipientNext = pMac->m_recipientFirst;
 	pMac->m_recipientFirst = pRecip;
+	pRecip->m_encrypt.m_message.m_refCount++;
 
 #ifdef USE_CBOR_CONTEXT
 	context = &pMac->m_message.m_allocContext;
@@ -938,12 +949,11 @@
 	CHECK_CONDITION_CBOR(cn_cbor_array_append(pRecipients,
 							 pRecip->m_encrypt.m_message.m_cbor, &cbor_error),
 		cbor_error);
-	pRecip->m_encrypt.m_message.m_refCount++;
 
 	return true;
 
 errorReturn:
-	if (pRecipientsT == nullptr) {
+	if (pRecipientsT != nullptr) {
 		CN_CBOR_FREE(pRecipientsT, context);
 	}
 	return false;
diff --git a/src/MacMessage0.cpp b/src/MacMessage0.cpp
index c3683d2..4375fad 100644
--- a/src/MacMessage0.cpp
+++ b/src/MacMessage0.cpp
@@ -88,6 +88,7 @@
 		perr->err = COSE_ERR_OUT_OF_MEMORY;
 	errorReturn:
 		if (pobj != nullptr) {
+			pobj->m_message.m_ownMsg = false;
 			_COSE_Mac0_Release(pobj);
 			if (pIn == nullptr) {
 				COSE_FREE(pobj, context);
diff --git a/src/Recipient.cpp b/src/Recipient.cpp
index e6f3147..871d1f6 100644
--- a/src/Recipient.cpp
+++ b/src/Recipient.cpp
@@ -52,15 +52,16 @@
 	errorReturn:
 		return nullptr;		
 	}
-	
+
 	CHECK_CONDITION(flags == COSE_INIT_FLAGS_NONE, COSE_ERR_INVALID_PARAMETER);
 	COSE_RecipientInfo *pobj = (COSE_RecipientInfo *)COSE_CALLOC(
 		1, sizeof(COSE_RecipientInfo), context);
 	CHECK_CONDITION(pobj != nullptr, COSE_ERR_OUT_OF_MEMORY);
 
-	if (!_COSE_Init(static_cast<COSE_INIT_FLAGS>(COSE_INIT_FLAGS_NO_CBOR_TAG | flags),
-	                &pobj->m_encrypt.m_message, COSE_recipient_object,
-	                CBOR_CONTEXT_PARAM_COMMA perr)) {
+	if (!_COSE_Init(
+			static_cast<COSE_INIT_FLAGS>(COSE_INIT_FLAGS_NO_CBOR_TAG | flags),
+			&pobj->m_encrypt.m_message, COSE_recipient_object,
+			CBOR_CONTEXT_PARAM_COMMA perr)) {
 		_COSE_Recipient_Free(pobj);
 		return nullptr;
 	}
@@ -200,6 +201,7 @@
 	size_t cbDigest;
 	byte *pbSecret = nullptr;
 	size_t cbSecret = 0;
+	COSE_KEY *pkeyMessage = NULL;
 
 	if (!BuildContextBytes(pCose, algResult, cbitKey, &pbContext, &cbContext,
 			CBOR_CONTEXT_PARAM_COMMA perr)) {
@@ -208,7 +210,6 @@
 
 	if (fECDH) {
 #ifdef USE_ECDH
-		COSE_KEY *pkeyMessage;
 
 		if (pKeyPrivate != nullptr) {
 			cn = cn_cbor_mapget_int(pKeyPrivate->m_cborKey, COSE_Key_Type);
@@ -232,33 +233,61 @@
 
 			if (!ECDH_ComputeSecret(pCose, &pkeyMessage, pKeyPublic, &pbSecret,
 					&cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) {
+				if (pkeyMessage != nullptr && pKeyPrivate == nullptr) {
+					COSE_KEY_Free((HCOSE_KEY)pkeyMessage);
+				}
 				goto errorReturn;
 			}
 			if (!fStatic && pkeyMessage->m_cborKey->parent == nullptr) {
+				cn_cbor_errback cborError;
+				cn_cbor *pdup = pkeyMessage->m_cborKey;
+				if (pKeyPrivate == nullptr) {
+					pkeyMessage->m_cborKey = nullptr;	
+				}
+				else {
+					pdup = cn_cbor_clone(pkeyMessage->m_cborKey, CBOR_CONTEXT_PARAM_COMMA &cborError);
+					CHECK_CONDITION_CBOR(pdup != nullptr, cborError);
+				}
+				if (pKeyPrivate == nullptr) {
+					COSE_KEY_Free((HCOSE_KEY)pkeyMessage);
+				}
 				if (!_COSE_map_put(pCose, COSE_Header_ECDH_EPHEMERAL,
-						pkeyMessage->m_cborKey, COSE_UNPROTECT_ONLY, perr)) {
+						pdup, COSE_UNPROTECT_ONLY, perr)) {
+					CN_CBOR_FREE(pdup, context);
 					goto errorReturn;
 				}
 			}
 		}
 		else {
-			cn_cbor * cborKey = _COSE_map_get_int(pCose,
-				fStatic ? COSE_Header_ECDH_STATIC : COSE_Header_ECDH_EPHEMERAL,
-				COSE_BOTH, perr);
-			CHECK_CONDITION(cborKey != nullptr, COSE_ERR_OUT_OF_MEMORY);
-			
-			pkeyMessage = (COSE_KEY *) COSE_KEY_FromCbor(cborKey, CBOR_CONTEXT_PARAM_COMMA perr);
-			if (pkeyMessage == nullptr) {
-				goto errorReturn;
+			CHECK_CONDITION(pKeyPrivate != nullptr, COSE_ERR_INVALID_PARAMETER);
+			pkeyMessage = pKeyPublic;
+
+			if (pKeyPublic == nullptr) {
+				cn_cbor *cborKey = _COSE_map_get_int(pCose,
+					fStatic ? COSE_Header_ECDH_STATIC
+							: COSE_Header_ECDH_EPHEMERAL,
+					COSE_BOTH, perr);
+				CHECK_CONDITION(cborKey != nullptr, COSE_ERR_OUT_OF_MEMORY);
+
+				pkeyMessage = (COSE_KEY *)COSE_KEY_FromCbor(
+					cborKey, CBOR_CONTEXT_PARAM_COMMA perr);
+				if (pkeyMessage == nullptr) {
+					goto errorReturn;
+				}
 			}
 
-			CHECK_CONDITION(pKeyPrivate != nullptr, COSE_ERR_INVALID_PARAMETER);
-
-			if (!ECDH_ComputeSecret(pCose, &pKeyPrivate,
-					pkeyMessage, &pbSecret, &cbSecret,
-					CBOR_CONTEXT_PARAM_COMMA perr)) {
+			if (!ECDH_ComputeSecret(pCose, &pKeyPrivate, pkeyMessage, &pbSecret,
+					&cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) {
+				if (pKeyPublic == nullptr) {
+					pkeyMessage->m_cborKey = nullptr;
+					COSE_KEY_Free((HCOSE_KEY)pkeyMessage);
+				}
 				goto errorReturn;
 			}
+			if (pKeyPublic == nullptr) {
+				pkeyMessage->m_cborKey = nullptr;
+				COSE_KEY_Free((HCOSE_KEY)pkeyMessage);
+			}
 		}
 #else
 		goto errorReturn;
@@ -341,7 +370,7 @@
 	cn_cbor *cnBody = nullptr;
 	byte *pbContext = nullptr;
 	byte *pbSecret = nullptr;
-	int cbKey2;
+	size_t cbKey2;
 	byte *pbKeyX = nullptr;
 	int cbitKeyX = 0;
 	byte rgbKey[256 / 8];
@@ -504,7 +533,7 @@
 				errorFound = error.err;
 			}
 		}
-		
+
 		if (errorFound != COSE_ERR_NONE) {
 			perr->err = errorFound;
 			goto errorReturn;
@@ -519,7 +548,7 @@
 #ifdef USE_AES_KW_128
 		case COSE_Algorithm_AES_KW_128:
 			if (pbKeyX != nullptr) {
-				int x = (int) (cbitKeyOut / 8);
+				size_t x = (int) (cbitKeyOut / 8);
 				if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, pbKeyX, cbitKeyX,
 						cnBody->v.bytes, cnBody->length, pbKeyOut, &x, perr)) {
 					goto errorReturn;
@@ -528,7 +557,7 @@
 			else {
 				CHECK_CONDITION(
 					pRecip->m_pkey != nullptr, COSE_ERR_INVALID_PARAMETER);
-				int x = cbitKeyOut / 8;
+				size_t x = cbitKeyOut / 8;
 				cn = cn_cbor_mapget_int(pRecip->m_pkey->m_cborKey, -1);
 				CHECK_CONDITION((cn != nullptr) && (cn->type == CN_CBOR_BYTES),
 					COSE_ERR_INVALID_PARAMETER);
@@ -545,7 +574,7 @@
 #ifdef USE_AES_KW_192
 		case COSE_Algorithm_AES_KW_192:
 			if (pbKeyX != nullptr) {
-				int x = cbitKeyOut / 8;
+				size_t x = cbitKeyOut / 8;
 				if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, pbKeyX, cbitKeyX,
 						cnBody->v.bytes, cnBody->length, pbKeyOut, &x, perr)) {
 					goto errorReturn;
@@ -554,7 +583,7 @@
 			else {
 				CHECK_CONDITION(
 					pRecip->m_pkey != nullptr, COSE_ERR_INVALID_PARAMETER);
-				int x = cbitKeyOut / 8;
+				size_t x = cbitKeyOut / 8;
 				cn = cn_cbor_mapget_int(pRecip->m_pkey->m_cborKey, -1);
 				CHECK_CONDITION((cn != nullptr) && (cn->type == CN_CBOR_BYTES),
 					COSE_ERR_INVALID_PARAMETER);
@@ -571,7 +600,7 @@
 #ifdef USE_AES_KW_256
 		case COSE_Algorithm_AES_KW_256:
 			if (pbKeyX != nullptr) {
-				int x = cbitKeyOut / 8;
+				size_t x = cbitKeyOut / 8;
 				if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, pbKeyX, cbitKeyX,
 						cnBody->v.bytes, cnBody->length, pbKeyOut, &x, perr)) {
 					goto errorReturn;
@@ -580,7 +609,7 @@
 			else {
 				CHECK_CONDITION(
 					pRecip->m_pkey != nullptr, COSE_ERR_INVALID_PARAMETER);
-				int x = cbitKeyOut / 8;
+				size_t x = cbitKeyOut / 8;
 				cn = cn_cbor_mapget_int(pRecip->m_pkey->m_cborKey, -1);
 				CHECK_CONDITION((cn != nullptr) && (cn->type == CN_CBOR_BYTES),
 					COSE_ERR_INVALID_PARAMETER);
@@ -597,7 +626,8 @@
 #ifdef USE_Direct_HKDF_HMAC_SHA_256
 		case COSE_Algorithm_Direct_HKDF_HMAC_SHA_256:
 			if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn,
-					pRecip->m_pkey, nullptr, pbKeyOut, cbitKeyOut, 256,
+					pRecip->m_pkey, pRecip->m_pkeyStatic, pbKeyOut, cbitKeyOut,
+					256,
 					CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
@@ -607,7 +637,8 @@
 #ifdef USE_Direct_HKDF_HMAC_SHA_512
 		case COSE_Algorithm_Direct_HKDF_HMAC_SHA_512:
 			if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn,
-					pRecip->m_pkey, nullptr, pbKeyOut, cbitKeyOut, 512,
+					pRecip->m_pkey, pRecip->m_pkeyStatic, pbKeyOut, cbitKeyOut,
+					512,
 					CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
@@ -617,7 +648,8 @@
 #ifdef USE_Direct_HKDF_AES_128
 		case COSE_Algorithm_Direct_HKDF_AES_128:
 			if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn,
-					pRecip->m_pkey, nullptr, pbKeyOut, cbitKeyOut, 128,
+					pRecip->m_pkey, pRecip->m_pkeyStatic, pbKeyOut, cbitKeyOut,
+					128,
 					CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
@@ -627,7 +659,8 @@
 #ifdef USE_Direct_HKDF_AES_256
 		case COSE_Algorithm_Direct_HKDF_AES_256:
 			if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn,
-					pRecip->m_pkey, nullptr, pbKeyOut, cbitKeyOut, 256,
+					pRecip->m_pkey, nullptr, pbKeyOut, cbitKeyOut,
+					256,
 					CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
@@ -647,7 +680,8 @@
 #ifdef USE_ECDH_ES_HKDF_512
 		case COSE_Algorithm_ECDH_ES_HKDF_512:
 			if (!HKDF_X(&pcose->m_message, true, true, false, false, algIn,
-					pRecip->m_pkey, nullptr, pbKeyOut, cbitKeyOut, 512,
+					pRecip->m_pkey, nullptr, pbKeyOut, cbitKeyOut,
+					512,
 					CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
@@ -657,7 +691,8 @@
 #ifdef USE_ECDH_SS_HKDF_256
 		case COSE_Algorithm_ECDH_SS_HKDF_256:
 			if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn,
-					pRecip->m_pkey, nullptr, pbKeyOut, cbitKeyOut, 256,
+					pRecip->m_pkey, pRecip->m_pkeyStatic, pbKeyOut, cbitKeyOut,
+					256,
 					CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
@@ -667,7 +702,8 @@
 #ifdef USE_ECDH_SS_HKDF_512
 		case COSE_Algorithm_ECDH_SS_HKDF_512:
 			if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn,
-					pRecip->m_pkey, nullptr, pbKeyOut, cbitKeyOut, 512,
+					pRecip->m_pkey, pRecip->m_pkeyStatic, pbKeyOut, cbitKeyOut,
+					512,
 					CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
@@ -677,7 +713,8 @@
 #ifdef USE_ECDH_ES_A128KW
 		case COSE_Algorithm_ECDH_ES_A128KW:
 			if (!HKDF_X(&pcose->m_message, true, true, false, false,
-					COSE_Algorithm_AES_KW_128, pRecip->m_pkey, nullptr, rgbKey,
+					COSE_Algorithm_AES_KW_128, pRecip->m_pkey,
+					nullptr, rgbKey,
 					128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
@@ -693,7 +730,8 @@
 #ifdef USE_ECDH_ES_A192KW
 		case COSE_Algorithm_ECDH_ES_A192KW:
 			if (!HKDF_X(&pcose->m_message, true, true, false, false,
-					COSE_Algorithm_AES_KW_192, pRecip->m_pkey, nullptr, rgbKey,
+					COSE_Algorithm_AES_KW_192, pRecip->m_pkey,
+					nullptr, rgbKey,
 					192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
@@ -709,7 +747,8 @@
 #ifdef USE_ECDH_ES_A256KW
 		case COSE_Algorithm_ECDH_ES_A256KW:
 			if (!HKDF_X(&pcose->m_message, true, true, false, false,
-					COSE_Algorithm_AES_KW_256, pRecip->m_pkey, nullptr, rgbKey,
+					COSE_Algorithm_AES_KW_256, pRecip->m_pkey,
+					nullptr, rgbKey,
 					256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
@@ -725,7 +764,7 @@
 #ifdef USE_ECDH_SS_A128KW
 		case COSE_Algorithm_ECDH_SS_A128KW:
 			if (!HKDF_X(&pcose->m_message, true, true, true, false,
-					COSE_Algorithm_AES_KW_128, pRecip->m_pkey, nullptr, rgbKey,
+					COSE_Algorithm_AES_KW_128, pRecip->m_pkey, pRecip->m_pkeyStatic, rgbKey,
 					128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
@@ -741,7 +780,8 @@
 #ifdef USE_ECDH_SS_A192KW
 		case COSE_Algorithm_ECDH_SS_A192KW:
 			if (!HKDF_X(&pcose->m_message, true, true, true, false,
-					COSE_Algorithm_AES_KW_192, pRecip->m_pkey, nullptr, rgbKey,
+					COSE_Algorithm_AES_KW_192, pRecip->m_pkey,
+					pRecip->m_pkeyStatic, rgbKey,
 					192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
@@ -757,7 +797,8 @@
 #ifdef USE_ECDH_SS_A256KW
 		case COSE_Algorithm_ECDH_SS_A256KW:
 			if (!HKDF_X(&pcose->m_message, true, true, true, false,
-					COSE_Algorithm_AES_KW_256, pRecip->m_pkey, nullptr, rgbKey,
+					COSE_Algorithm_AES_KW_256, pRecip->m_pkey,
+					pRecip->m_pkeyStatic, rgbKey,
 					256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) {
 				goto errorReturn;
 			}
@@ -1172,6 +1213,25 @@
 		}
 	}
 
+#if INCLUDE_COUNTERSIGNATURE
+	if (pRecipient->m_encrypt.m_message.m_counterSigners != nullptr) {
+		if (!_COSE_CounterSign_Sign(
+				&pRecipient->m_encrypt.m_message, CBOR_CONTEXT_PARAM_COMMA perr)) {
+			goto errorReturn;
+		}
+	}
+#endif
+
+#if INCLUDE_COUNTERSIGNATURE1
+	if (pRecipient->m_encrypt.m_message.m_counterSign1 != NULL) {
+		if (!_COSE_CounterSign1_Sign(
+				&pRecipient->m_encrypt.m_message, CBOR_CONTEXT_PARAM_COMMA perr)) {
+			goto errorReturn;
+		}
+	}
+#endif
+
+
 	//  Figure out the clean up
 
 	fRet = true;
@@ -1360,9 +1420,9 @@
 		if (pbKey != nullptr) {
 			COSE_FREE(pbKey, context);
 		}
-		return false;		
+		return false;
 	}
-	
+
 	CHECK_CONDITION(
 		IsValidRecipientHandle(hRecipient), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(rgbKey != nullptr, COSE_ERR_INVALID_PARAMETER);
@@ -1453,9 +1513,9 @@
 		if (hkey != nullptr) {
 			COSE_KEY_Free(hkey);
 		}
-		return false;		
+		return false;
 	}
-	
+
 	CHECK_CONDITION(IsValidRecipientHandle(h), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(pKey != nullptr, COSE_ERR_INVALID_PARAMETER);
 
@@ -1475,7 +1535,9 @@
 	return true;
 }
 
-bool COSE_Recipient_SetKey2(HCOSE_RECIPIENT h, HCOSE_KEY hKey, cose_errback * perr)
+bool COSE_Recipient_SetKey2(HCOSE_RECIPIENT h,
+	HCOSE_KEY hKey,
+	cose_errback *perr)
 {
 	COSE_RecipientInfo *p;
 
@@ -1485,7 +1547,7 @@
 	if (p->m_pkey != nullptr) {
 		COSE_KEY_Free((HCOSE_KEY) p->m_pkey);
 	}
-	
+
 	p->m_pkey = (COSE_KEY *)hKey;
 	if (p->m_pkey != nullptr) {
 		p->m_pkey->m_refCount += 1;
@@ -1526,16 +1588,17 @@
 		if (coseKey != nullptr) {
 			COSE_KEY_Free(coseKey);
 		}
-		return fRet;		
+		return fRet;
 	}
-	
+
 	CHECK_CONDITION(IsValidRecipientHandle(h), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(pKey != nullptr, COSE_ERR_INVALID_PARAMETER);
 
 	#ifdef USE_CBOR_CONTEXT
-	cn_cbor_context *context = nullptr;
+	COSE_RecipientInfo *pRecipient = (COSE_RecipientInfo *)h;
+	cn_cbor_context *context = &pRecipient->m_encrypt.m_message.m_allocContext;
 #endif
-	
+
 	coseKey = COSE_KEY_FromCbor((cn_cbor *)pKey, CBOR_CONTEXT_PARAM_COMMA perr);
 	CHECK_CONDITION(coseKey != nullptr, COSE_ERR_OUT_OF_MEMORY);
 
@@ -1566,14 +1629,14 @@
 		if (cn3 != nullptr) {
 			CN_CBOR_FREE(cn3, context);
 		}
-		return f;		
+		return f;
 	}
-	
+
 	CHECK_CONDITION(IsValidRecipientHandle(h), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(IsValidKeyHandle(hKey), COSE_ERR_INVALID_PARAMETER);
 
 	p = (COSE_RecipientInfo *)h;
-	COSE_KEY *pKey = (COSE_KEY *)hKey;	
+	COSE_KEY *pKey = (COSE_KEY *)hKey;
 
 #ifdef USE_CBOR_CONTEXT
 	context = &p->m_encrypt.m_message.m_allocContext;
@@ -1634,6 +1697,9 @@
 			cn2 = nullptr;
 			break;
 
+		case COSE_DONT_SEND:
+			break;
+		
 		default:
 			FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
 	}
@@ -1723,19 +1789,16 @@
 #ifdef USE_ECDH_SS_HKDF_512
 				case COSE_Algorithm_ECDH_SS_HKDF_512:
 #endif
-					((COSE_RecipientInfo *)h)->m_encrypt.m_message.m_flags =
-						(cose_init_flags)(
-						((COSE_RecipientInfo *)h)
-							->m_encrypt.m_message
-							.m_flags | COSE_INIT_FLAGS_DETACHED_CONTENT);
+					((COSE_RecipientInfo *)h)
+						->m_encrypt.m_message.m_flags = (cose_init_flags)(
+						((COSE_RecipientInfo *)h)->m_encrypt.m_message.m_flags |
+						COSE_INIT_FLAGS_DETACHED_CONTENT);
 					break;
 
 				default:
-					((COSE_RecipientInfo *)h)->m_encrypt.m_message.m_flags =
-						(cose_init_flags)(
-							((COSE_RecipientInfo *)h)
-								->m_encrypt.m_message
-								.m_flags &
+					((COSE_RecipientInfo *)h)
+						->m_encrypt.m_message.m_flags = (cose_init_flags)(
+						((COSE_RecipientInfo *)h)->m_encrypt.m_message.m_flags &
 						~COSE_INIT_FLAGS_DETACHED_CONTENT);
 					break;
 			}
@@ -1790,7 +1853,7 @@
 		}
 		return fReturn;
 	}
-	
+
 	pArray = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA & cbor_error);
 	CHECK_CONDITION_CBOR(pArray != nullptr, cbor_error);
 
@@ -1808,7 +1871,7 @@
 		cnT = cn_cbor_clone(cnParam, CBOR_CONTEXT_PARAM_COMMA & cbor_error);
 	}
 	else {
-		cnT = cn_cbor_null_create(CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		cnT = cn_cbor_null_create(CBOR_CONTEXT_PARAM_COMMA & cbor_error);
 	}
 	CHECK_CONDITION_CBOR(cnT != nullptr, cbor_error);
 	CHECK_CONDITION_CBOR(
@@ -2031,8 +2094,6 @@
 	context = &pEncrypt->m_message.m_allocContext;
 #endif	// USE_CBOR_CONTEXT
 
-	pRecip->m_recipientNext = pEncrypt->m_recipientFirst;
-	pEncrypt->m_recipientFirst = pRecip;
 
 	pRecipients = _COSE_arrayget_int(&pEncrypt->m_message, INDEX_RECIPIENTS);
 	if (pRecipients == nullptr) {
@@ -2054,6 +2115,8 @@
 							 pRecip->m_encrypt.m_message.m_cbor, &cbor_error),
 		cbor_error);
 
+	pRecip->m_recipientNext = pEncrypt->m_recipientFirst;
+	pEncrypt->m_recipientFirst = pRecip;
 	pRecip->m_encrypt.m_message.m_refCount++;
 
 	return true;
diff --git a/src/Sign.cpp b/src/Sign.cpp
index 8061c34..e8697e2 100644
--- a/src/Sign.cpp
+++ b/src/Sign.cpp
@@ -119,6 +119,7 @@
 
 errorReturn:
 	if (pobj != nullptr) {
+		pobj->m_message.m_ownMsg = false;
 		_COSE_Sign_Release(pobj);
 		if (pIn == nullptr) {
 			COSE_FREE(pobj, context);
@@ -319,6 +320,15 @@
 	}
 #endif
 
+#if INCLUDE_COUNTERSIGNATURE1
+	if (pMessage->m_message.m_counterSign1 != NULL) {
+		if (!_COSE_CounterSign1_Sign(
+				&pMessage->m_message, CBOR_CONTEXT_PARAM_COMMA perr)) {
+			goto errorReturn;
+		}
+	}
+#endif
+
 	return true;
 }
 
@@ -374,8 +384,6 @@
 	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;
@@ -397,6 +405,9 @@
 	CHECK_CONDITION_CBOR(
 		cn_cbor_array_append(pSigners, pSigner->m_message.m_cbor, &cbor_error),
 		cbor_error);
+
+	pSigner->m_signerNext = pSign->m_signerFirst;
+	pSign->m_signerFirst = pSigner;
 	pSigner->m_message.m_refCount++;
 
 	return true;
diff --git a/src/Sign1.cpp b/src/Sign1.cpp
index 7d9eefa..77a3595 100644
--- a/src/Sign1.cpp
+++ b/src/Sign1.cpp
@@ -52,7 +52,7 @@
 	errorReturn:
 		return nullptr;		
 	}
-	
+
 	CHECK_CONDITION(flags == COSE_INIT_FLAGS_NONE, COSE_ERR_INVALID_PARAMETER);
 	COSE_Sign1Message *pobj =
 		(COSE_Sign1Message *)COSE_CALLOC(1, sizeof(COSE_Sign1Message), context);
@@ -105,6 +105,7 @@
 
 errorReturn:
 	if (pobj != nullptr) {
+		pobj->m_message.m_ownMsg = false;
 		_COSE_Sign1_Release(pobj);
 		if (pIn == nullptr) {
 			COSE_FREE(pobj, context);
@@ -224,17 +225,21 @@
 	if (false) {
 	errorReturn:
 		if (cose != nullptr) {
+			//  Don't free the passed in key.
+			((COSE_KEY *)cose)->m_cborKey = nullptr;
 			COSE_KEY_Free(cose);
 		}
-		return fRet;		
+		return fRet;
 	}
 
 	CHECK_CONDITION(pKey != nullptr, COSE_ERR_INVALID_PARAMETER);
+	CHECK_CONDITION(IsValidSign1Handle(h), COSE_ERR_INVALID_HANDLE);
 
 #ifdef USE_CBOR_CONTEXT
-	cn_cbor_context *context = nullptr;
+	COSE_Sign1Message *pmessage = (COSE_Sign1Message *)h;
+	cn_cbor_context *context = &pmessage->m_message.m_allocContext;
 #endif
-	
+
 	cose = COSE_KEY_FromCbor((cn_cbor *)pKey, CBOR_CONTEXT_PARAM_COMMA perr);
 	if (cose == nullptr) {
 		goto errorReturn;
@@ -244,7 +249,6 @@
 	goto errorReturn;
 }
 
-
 bool COSE_Sign1_Sign2(HCOSE_SIGN1 h, HCOSE_KEY hKey, cose_errback *perr)
 {
 #ifdef USE_CBOR_CONTEXT
@@ -259,7 +263,7 @@
 		return false;
 	}
 	CHECK_CONDITION(IsValidKeyHandle(hKey), COSE_ERR_INVALID_HANDLE);
-	
+
 #ifdef USE_CBOR_CONTEXT
 	context = &pMessage->m_message.m_allocContext;
 #endif
@@ -269,7 +273,7 @@
 		goto errorReturn;
 	}
 
-	if (!_COSE_Signer1_sign(pMessage, (COSE_KEY*) hKey, perr)) {
+	if (!_COSE_Signer1_sign(pMessage, (COSE_KEY *)hKey, perr)) {
 		goto errorReturn;
 	}
 
@@ -281,18 +285,21 @@
 		}
 	}
 #endif
+#if INCLUDE_COUNTERSIGNATURE1
+	if (pMessage->m_message.m_counterSign1 != NULL) {
+		if (!_COSE_CounterSign1_Sign(
+				&pMessage->m_message, CBOR_CONTEXT_PARAM_COMMA perr)) {
+			goto errorReturn;
+		}
+	}
+#endif
 
 	return true;
 }
 
-bool COSE_Sign1_validate(HCOSE_SIGN1 hSign,
-	const cn_cbor *pKey,
-	cose_errback *perr)
+bool COSE_Sign1_validate2(HCOSE_SIGN1 hSign, HCOSE_KEY hKey, cose_errback *perr)
 {
 	bool f;
-	COSE_Sign1Message *pSign;
-	const cn_cbor *cnContent;
-	const cn_cbor *cnProtected;
 	COSE_KEY *pcose = nullptr;
 
 	if (false) {
@@ -304,27 +311,54 @@
 	}
 
 	CHECK_CONDITION(IsValidSign1Handle(hSign), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(IsValidKeyHandle(hKey), COSE_ERR_INVALID_HANDLE);
 
-	pSign = (COSE_Sign1Message *)hSign;
+	COSE_Sign1Message *pSign = (COSE_Sign1Message *)hSign;
 
-	cnContent = _COSE_arrayget_int(&pSign->m_message, INDEX_BODY);
+	const cn_cbor* cnContent =
+		_COSE_arrayget_int(&pSign->m_message, INDEX_BODY);
 	CHECK_CONDITION(cnContent != nullptr && cnContent->type == CN_CBOR_BYTES,
 		COSE_ERR_INVALID_PARAMETER);
 
-	cnProtected = _COSE_arrayget_int(&pSign->m_message, INDEX_PROTECTED);
+	const cn_cbor* cnProtected = _COSE_arrayget_int(
+		&pSign->m_message, INDEX_PROTECTED);
 	CHECK_CONDITION(cnProtected != nullptr && cnProtected->type == CN_CBOR_BYTES,
 		COSE_ERR_INVALID_PARAMETER);
 
+	pcose = (COSE_KEY *)hKey;
+	
+	f = _COSE_Signer1_validate(pSign, pcose, perr);
+
+	return f;
+}
+
+bool COSE_Sign1_validate(HCOSE_SIGN1 hSign,
+	const cn_cbor *pKey,
+	cose_errback *perr)
+{
+	if (false) {
+	errorReturn:
+		return false;
+	}
+
+	CHECK_CONDITION(IsValidSign1Handle(hSign), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pKey != NULL, COSE_ERR_INVALID_PARAMETER);
+	
 #ifdef USE_CBOR_CONTEXT
+	COSE_Sign1Message *pSign = (COSE_Sign1Message *)hSign;
+
 	cn_cbor_context *context = &pSign->m_message.m_allocContext;
 #endif
 
-	pcose = (COSE_KEY*) COSE_KEY_FromCbor((cn_cbor *)pKey, CBOR_CONTEXT_PARAM_COMMA perr);
-	CHECK_CONDITION(pKey != nullptr, COSE_ERR_OUT_OF_MEMORY);
+	HCOSE_KEY hcose =
+		COSE_KEY_FromCbor((cn_cbor *)pKey, CBOR_CONTEXT_PARAM_COMMA perr);
+	CHECK_CONDITION(pKey != NULL, COSE_ERR_OUT_OF_MEMORY);
 
-	f = _COSE_Signer1_validate(pSign, pcose, perr);
+	bool f = COSE_Sign1_validate2(hSign, hcose, perr);
 
-	COSE_KEY_Free((HCOSE_KEY)pcose);
+	((COSE_KEY *)hcose)->m_cborKey = nullptr;
+	COSE_KEY_Free(hcose);
+
 	return f;
 }
 
diff --git a/src/SignerInfo.cpp b/src/SignerInfo.cpp
index 55ac6f0..0874bc9 100644
--- a/src/SignerInfo.cpp
+++ b/src/SignerInfo.cpp
@@ -161,7 +161,7 @@
 		if (pbToSign != nullptr) {
 			COSE_FREE(pbToSign, context);
 		}
-		return f;		
+		return f;
 	}
 	pArray = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA & cbor_error);
 	CHECK_CONDITION_CBOR(pArray != nullptr, cbor_error);
@@ -228,7 +228,7 @@
 	*pcbToSign = cbToSign;
 	pbToSign = nullptr;
 	f = true;
-	goto errorReturn;	
+	goto errorReturn;
 }
 
 bool _COSE_Signer_sign(COSE_SignerInfo *pSigner,
@@ -330,6 +330,15 @@
 	}
 #endif
 
+#if INCLUDE_COUNTERSIGNATURE1
+	if (pSigner->m_message.m_counterSign1 != NULL) {
+		if (!_COSE_CounterSign1_Sign(
+				&pSigner->m_message, CBOR_CONTEXT_PARAM_COMMA perr)) {
+			goto errorReturn;
+		}
+	}
+#endif
+
 	fRet = true;
 
 errorReturn:
@@ -349,9 +358,9 @@
 
 	if (false) {
 	errorReturn:
-		return false;		
+		return false;
 	}
-	
+
 	CHECK_CONDITION(IsValidSignerHandle(h), COSE_ERR_INVALID_HANDLE);
 	CHECK_CONDITION(IsValidKeyHandle(pKey), COSE_ERR_INVALID_HANDLE);
 
@@ -372,21 +381,29 @@
 {
 	HCOSE_KEY cose = nullptr;
 	bool fRet = false;
-#ifdef USE_CBOR_CONTEXT
-	cn_cbor_context *context = nullptr;
-#endif
+
+	if (false) {
+	errorReturn:
+		if (cose != nullptr) {
+			COSE_KEY_Free(cose);
+		}
+		return fRet;		
+	}
 
 	CHECK_CONDITION(pKey != nullptr, COSE_ERR_INVALID_PARAMETER);
-	cose = COSE_KEY_FromCbor((cn_cbor*) pKey, CBOR_CONTEXT_PARAM_COMMA perr);
+	CHECK_CONDITION(IsValidSignerHandle(h), COSE_ERR_INVALID_HANDLE);
+	
+#ifdef USE_CBOR_CONTEXT
+	COSE_SignerInfo *p = (COSE_SignerInfo *)h;
+	cn_cbor_context *context = &p->m_message.m_allocContext;
+#endif
+
+	cose = COSE_KEY_FromCbor((cn_cbor *)pKey, CBOR_CONTEXT_PARAM_COMMA perr);
 	
 	CHECK_CONDITION(cose != nullptr, COSE_ERR_OUT_OF_MEMORY);
 
-	fRet =COSE_Signer_SetKey2(h, cose, perr);
+	fRet = COSE_Signer_SetKey2(h, cose, perr);
 
-errorReturn:
-	if (cose != nullptr) {
-		COSE_KEY_Free(cose);
-	}
 	return fRet;
 }
 
diff --git a/src/cbor.cpp b/src/cbor.cpp
index a28a154..25866b5 100644
--- a/src/cbor.cpp
+++ b/src/cbor.cpp
@@ -1,41 +1,53 @@
+#include <cassert>
+
 #include "cn-cbor/cn-cbor.h"
 #include <cose/cose.h>
 #include <stdlib.h>
+
 #ifdef __MBED__
 #include <string.h>
 #else
 #include <memory.h>
 #endif
 
-#define INIT_CB(v)                                 \
-	if (errp) {                                    \
-		errp->err = CN_CBOR_NO_ERROR;              \
-	}                                              \
-	(v) = static_cast<cn_cbor *> (CN_CALLOC_CONTEXT());  \
-	if (!(v)) {                                    \
-		if (errp) {                                \
-			errp->err = CN_CBOR_ERR_OUT_OF_MEMORY; \
-		}                                          \
-		return false;                              \
+#define INIT_CB(v)                                     \
+	if (errp) {                                        \
+		errp->err = CN_CBOR_NO_ERROR;                  \
+	}                                                  \
+	(v) = static_cast<cn_cbor *>(CN_CALLOC_CONTEXT()); \
+	if (!(v)) {                                        \
+		if (errp) {                                    \
+			errp->err = CN_CBOR_ERR_OUT_OF_MEMORY;     \
+		}                                              \
+		return false;                                  \
 	}
 
 #ifdef USE_CBOR_CONTEXT
 #define CBOR_CONTEXT_PARAM , context
+#define CBOR_CONTEXT_PARAM_COMMA context,
 
+#if 1
 #define CN_CALLOC(ctx)                                           \
 	((ctx) && (ctx)->calloc_func)                                \
 		? (ctx)->calloc_func(1, sizeof(cn_cbor), (ctx)->context) \
 		: calloc(1, sizeof(cn_cbor))
+#endif
 
 #define CN_CALLOC_CONTEXT() CN_CALLOC(context)
 #define CN_CBOR_CALLOC(c, i, ctx)                                            \
 	((ctx) && (ctx)->calloc_func) ? (ctx)->calloc_func(c, i, (ctx)->context) \
 								  : calloc(c, i)
+#define COSE_FREE(ptr, ctx)                                                    \
+	((((ctx) && (ctx)->free_func)) ? ((ctx)->free_func((ptr), (ctx)->context)) \
+								   : free((ptr)))
+
 #else
 #define CBOR_CONTEXT_PARAM
+#define CBOR_CONTEXT_PARAM_COMMA
 #define CN_CALLOC(ctx) calloc(1, sizeof(cn_cbor))
 #define CN_CALLOC_CONTEXT() CN_CALLOC(context)
 #define CN_CBOR_CALLOC(c, i, ctx) calloc(c, i)
+#define COSE_FREE(ptr, ctx) free(ptr)
 #endif
 
 /***
@@ -132,10 +144,13 @@
 cn_cbor *cn_cbor_clone(const cn_cbor *pIn,
 	CBOR_CONTEXT_COMMA cn_cbor_errback *pcn_cbor_error)
 {
-	cn_cbor *pOut = nullptr;
+	cn_cbor * pOut = nullptr;
 	char *sz;
 	unsigned char *pb;
-
+	cn_cbor *pTemp;
+	cn_cbor *pLast;
+	int count;
+	
 	switch (pIn->type) {
 		case CN_CBOR_TEXT:
 			sz = (char*)( CN_CBOR_CALLOC(pIn->length + 1, 1, context));
@@ -144,7 +159,11 @@
 			}
 			memcpy(sz, pIn->v.str, pIn->length);
 			sz[pIn->length] = 0;
-			pOut = cn_cbor_string_create2(sz, 0 CBOR_CONTEXT_PARAM, pcn_cbor_error);
+			pOut = cn_cbor_string_create2(
+				sz, 0 CBOR_CONTEXT_PARAM, pcn_cbor_error);
+			if (pOut == nullptr) {
+				COSE_FREE(sz, context);
+			}
 			break;
 
 		case CN_CBOR_UINT:
@@ -152,18 +171,67 @@
 				pIn->v.sint CBOR_CONTEXT_PARAM, pcn_cbor_error);
 			break;
 
+		case CN_CBOR_INT:
+			pOut = cn_cbor_int_create(
+				pIn->v.uint CBOR_CONTEXT_PARAM, pcn_cbor_error);
+			break;
+
+		case CN_CBOR_TRUE:
+			pOut = cn_cbor_bool_create(true CBOR_CONTEXT_PARAM, pcn_cbor_error);
+			break;
+
+		case CN_CBOR_FALSE:
+			pOut =
+				cn_cbor_bool_create(false CBOR_CONTEXT_PARAM, pcn_cbor_error);
+			break;
+
 		case CN_CBOR_BYTES:
-			pb = static_cast<unsigned char *> (CN_CBOR_CALLOC(
-				(int)pIn->length, 1, context));
+			pb = static_cast<unsigned char *>(
+				CN_CBOR_CALLOC((int)pIn->length, 1, context));
 			if (pb == nullptr) {
 				return nullptr;
 			}
 			memcpy(pb, pIn->v.bytes, pIn->length);
 			pOut = cn_cbor_data_create2(
 				pb, (int)pIn->length, 0 CBOR_CONTEXT_PARAM, pcn_cbor_error);
+			if (pOut == nullptr) {
+				COSE_FREE((cn_cbor *)pb, context);
+			}
+			break;
+
+		case CN_CBOR_MAP:
+			pOut = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA pcn_cbor_error);
+			if (pOut == nullptr) {
+				return nullptr;
+			}
+			pTemp = pIn->first_child;
+			pLast = nullptr;
+			count = 0;
+			while (pTemp != nullptr) {
+				cn_cbor *p = cn_cbor_clone(
+					pTemp, CBOR_CONTEXT_PARAM_COMMA pcn_cbor_error);
+				if (p == nullptr) {
+					cn_cbor_free(pOut CBOR_CONTEXT_PARAM);
+					return nullptr;
+				}
+				if (pLast == nullptr) {
+					pOut->first_child = p;
+					pLast = p;
+				}
+				else {
+					pLast->next = p;
+					pLast = p;
+				}
+				p->parent = pOut;
+				count += 1;
+				pTemp = pTemp->next;
+			}
+			pOut->last_child = pLast;
+			pOut->length = count;
 			break;
 
 		default:
+			assert(false);
 			break;
 	}
 
diff --git a/src/cose_crypto.h b/src/cose_crypto.h
index 27c0ff5..4081296 100644
--- a/src/cose_crypto.h
+++ b/src/cose_crypto.h
@@ -38,7 +38,7 @@
 	const byte* pbCipherText,
 	size_t cbCipherText,
 	byte* pbKeyOut,
-	int* pcbKeyOut,
+	size_t* pcbKeyOut,
 	cose_errback* perr);
 
 /**
@@ -175,8 +175,8 @@
 	cose_errback* perr);
 
 bool ECDH_ComputeSecret(COSE* pReciient,
-	COSE_KEY **ppKeyMe,
-	COSE_KEY *pKeyYou,
+	COSE_KEY** ppKeyMe,
+	COSE_KEY* pKeyYou,
 	byte** ppbSecret,
 	size_t* pcbSecret,
 	CBOR_CONTEXT_COMMA cose_errback* perr);
diff --git a/src/cose_int.h b/src/cose_int.h
index 2b69b48..3cb2f4f 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -83,14 +83,6 @@
 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
 	const byte *pbContent;
@@ -112,11 +104,6 @@
 	COSE_RecipientInfo *m_recipientFirst;
 } COSE_MacMessage;
 
-#if 0
-typedef struct {
-	COSE m_message;			// The message object
-} COSE_Mac0Message;
-#endif
 typedef COSE_MacMessage COSE_Mac0Message;
 
 struct CounterSign {
@@ -124,6 +111,11 @@
 	COSE_CounterSign *m_next;
 };
 
+struct CounterSign1 {
+	COSE_SignerInfo m_signer;
+	COSE_CounterSign1 *m_next;
+};
+
 #ifdef USE_CBOR_CONTEXT
 /**
  * Allocate enough space for 1 `cn_cbor` structure.
@@ -192,11 +184,11 @@
 bool IsValidSignerHandle(HCOSE_SIGNER h);
 bool IsValidSign1Handle(HCOSE_SIGN1 h);
 bool IsValidCounterSignHandle(HCOSE_COUNTERSIGN h);
+bool IsValidCounterSign1Handle(HCOSE_COUNTERSIGN1 h);
 bool IsValidMacHandle(HCOSE_MAC h);
 bool IsValidMac0Handle(HCOSE_MAC0 h);
 bool IsValidKeyHandle(HCOSE_KEY h);
 
-
 bool _COSE_Init(COSE_INIT_FLAGS flags,
 	COSE *pcose,
 	int msgType,
@@ -351,6 +343,19 @@
 bool _COSE_CounterSign_Sign(COSE *baseMessage,
 	CBOR_CONTEXT_COMMA cose_errback *perr);
 
+HCOSE_COUNTERSIGN1 _COSE_CounterSign1_get(COSE *pMessage, cose_errback *perr);
+bool _COSE_CounterSign1_add(COSE *pMessage,
+	HCOSE_COUNTERSIGN1 hSigner,
+	cose_errback *perr);
+bool _COSE_CountSign1_create(COSE *pMessage,
+	cn_cbor *pcnBody,
+	CBOR_CONTEXT_COMMA cose_errback *perr);
+COSE_CounterSign1 *_COSE_CounterSign1_Init_From_Object(cn_cbor *cbor,
+	COSE_CounterSign1 *,
+	CBOR_CONTEXT_COMMA cose_errback *perr);
+bool _COSE_CounterSign1_Sign(COSE *baseMessage,
+	CBOR_CONTEXT_COMMA cose_errback *perr);
+
 //
 //  Debugging Items
 
@@ -427,7 +432,9 @@
 ///  NEW CBOR FUNCTIONS
 
 #ifndef CN_CBOR_VERSION
-static inline cn_cbor * cn_cbor_string_create2(const char * sz, int flags, CBOR_CONTEXT_COMMA cn_cbor_errback * perr)
+static inline cn_cbor *cn_cbor_string_create2(const char *sz,
+	int flags,
+	CBOR_CONTEXT_COMMA cn_cbor_errback *perr)
 {
 	return cn_cbor_string_create(sz,
 #ifdef USE_CBOR_CONTEXT
@@ -436,7 +443,8 @@
 		perr);
 }
 
-static inline cn_cbor *cn_cbor_data_create2(const byte *pb, int cb,
+static inline cn_cbor *cn_cbor_data_create2(const byte *pb,
+	int cb,
 	int flags,
 	CBOR_CONTEXT_COMMA cn_cbor_errback *perr)
 {
@@ -459,3 +467,4 @@
 enum { COSE_Int_Alg_AES_CBC_MAC_256_64 = -22 };
 
 #define COSE_CounterSign_object 1000
+#define COSE_CounterSign1_object 1001
diff --git a/src/mbedtls.cpp b/src/mbedtls.cpp
index d22760b..b2d7c90 100644
--- a/src/mbedtls.cpp
+++ b/src/mbedtls.cpp
@@ -270,7 +270,7 @@
 	//  CHECK TAG HERE
 	bool f = false;
 	const byte *pb = pbCrypto + cbOut;
-	for (int i = 0; i < (unsigned int)TSize; i++) {
+	for (int i = 0; i < TSize; i++) {
 		f |= (pb[i] != tag[i]);
 	}
 	CHECK_CONDITION(!f, COSE_ERR_CRYPTO_FAIL);
@@ -313,9 +313,9 @@
 			COSE_FREE(rgbOut, context);
 		}
 		mbedtls_gcm_free(&ctx);
-		return false;		
+		return false;
 	}
-	
+
 	// Make it first so we can clean it up
 	mbedtls_gcm_init(&ctx);
 
@@ -610,10 +610,9 @@
 			COSE_FREE(rgbOut, context);
 		}
 		mbedtls_md_free(&contx);
-		return false;		
+		return false;
 	}
 
-
 	switch (HSize) {
 		case 256:
 			md_name = "SHA256";
@@ -1152,7 +1151,7 @@
 		mbedtls_ecp_group_free(&group);
 		mbedtls_ecp_keypair_free(&keypair);
 		mbedtls_ecdh_free(&ctx);
-		return fRet;		
+		return fRet;
 	}
 
 	p = cn_cbor_mapget_int(pKeyPublic->m_cborKey, COSE_Key_EC_Curve);
@@ -1208,7 +1207,7 @@
 			COSE_ERR_CRYPTO_FAIL);
 
 		cn_cbor_errback cbor_error;
-		int cbSize = (int) (olen - 1) / 2;
+		int cbSize = (int)(olen - 1) / 2;
 
 		pkey = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA & cbor_error);
 		CHECK_CONDITION_CBOR(pkey != nullptr, cbor_error);
@@ -1217,7 +1216,7 @@
 			cose_group, CBOR_CONTEXT_PARAM_COMMA & cbor_error);
 		CHECK_CONDITION_CBOR(p != nullptr, cbor_error);
 		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_EC_Curve, p,
-								 CBOR_CONTEXT_PARAM_COMMA &cbor_error),
+								 CBOR_CONTEXT_PARAM_COMMA & cbor_error),
 			cbor_error);
 		p = nullptr;
 
diff --git a/src/openssl.cpp b/src/openssl.cpp
index addf8d4..bc137d7 100644
--- a/src/openssl.cpp
+++ b/src/openssl.cpp
@@ -443,15 +443,15 @@
 			COSE_FREE(pbIV, context);
 		}
 		if (cbor_iv_t != nullptr) {
-			COSE_FREE(cbor_iv_t, context);
+			CN_CBOR_FREE(cbor_iv_t, context);
 		}
 		if (rgbOut != nullptr) {
 			COSE_FREE(rgbOut, context);
 		}
 		EVP_CIPHER_CTX_free(ctx);
-		return false;		
+		return false;
 	}
-	
+
 	// Make it first so we can clean it up
 	ctx = EVP_CIPHER_CTX_new();
 	CHECK_CONDITION(nullptr != ctx, COSE_ERR_OUT_OF_MEMORY);
@@ -643,7 +643,7 @@
 	if (false) {
 	errorReturn:
 		EVP_CIPHER_CTX_free(ctx);
-		return false;		
+		return false;
 	}
 	switch (cbKey * 8) {
 		case 128:
@@ -1030,7 +1030,7 @@
 			COSE_FREE(rgbOut, context);
 		}
 		HMAC_CTX_free(ctx);
-		return false;		
+		return false;
 	}
 	ctx = HMAC_CTX_new();
 	CHECK_CONDITION(ctx != nullptr, COSE_ERR_OUT_OF_MEMORY);
@@ -1096,7 +1096,7 @@
 		CHECK_CONDITION(pKeyNew != nullptr, COSE_ERR_INVALID_PARAMETER);
 		return pKeyNew;
 	}
-	
+
 	byte rgbKey[512 + 1];
 	int cbKey;
 	const cn_cbor *p;
@@ -1197,6 +1197,7 @@
 	size_t cbSize;
 	byte *pbOut = nullptr;
 	COSE_KEY *coseKey = nullptr;
+	size_t cbX;
 
 	pgroup = EC_KEY_get0_group(pKey);
 	CHECK_CONDITION(pgroup != nullptr, COSE_ERR_INVALID_PARAMETER);
@@ -1239,6 +1240,7 @@
 			EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_COMPRESSED,
 				pbPoint, cbSize, nullptr) == cbSize,
 			COSE_ERR_CRYPTO_FAIL);
+		cbX = cbSize - 1;
 	}
 	else {
 		cbSize = EC_POINT_point2oct(
@@ -1250,13 +1252,14 @@
 			EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_UNCOMPRESSED,
 				pbPoint, cbSize, nullptr) == cbSize,
 			COSE_ERR_CRYPTO_FAIL);
+		cbX = cbSize / 2;
 	}
 
-	pbOut = (byte *) COSE_CALLOC((int)(cbSize / 2), 1, context);
+	pbOut = (byte *) COSE_CALLOC((int)(cbX), 1, context);
 	CHECK_CONDITION(pbOut != nullptr, COSE_ERR_OUT_OF_MEMORY);
-	memcpy(pbOut, pbPoint + 1, (int)(cbSize / 2));
+	memcpy(pbOut, pbPoint + 1, (int)(cbX));
 	p = cn_cbor_data_create2(
-		pbOut, (int)(cbSize / 2), 0, CBOR_CONTEXT_PARAM_COMMA & cbor_error);
+		pbOut, (int)(cbX), 0, CBOR_CONTEXT_PARAM_COMMA & cbor_error);
 	CHECK_CONDITION_CBOR(p != nullptr, cbor_error);
 	pbOut = nullptr;
 	CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_EC_X, p,
@@ -1274,10 +1277,10 @@
 		p = nullptr;
 	}
 	else {
-		pbOut = (byte *) COSE_CALLOC((int)(cbSize / 2), 1, context);
+		pbOut = (byte *) COSE_CALLOC((int)(cbX), 1, context);
 		CHECK_CONDITION(pbOut != nullptr, COSE_ERR_OUT_OF_MEMORY);
-		memcpy(pbOut, pbPoint + cbSize / 2 + 1, (int)(cbSize / 2));
-		p = cn_cbor_data_create2(pbOut, (int)(cbSize / 2), 0,
+		memcpy(pbOut, pbPoint + cbSize / 2 + 1, (int)(cbX));
+		p = cn_cbor_data_create2(pbOut, (int)(cbX), 0,
 			CBOR_CONTEXT_PARAM_COMMA & cbor_error);
 		CHECK_CONDITION_CBOR(p != nullptr, cbor_error);
 		pbOut = nullptr; 
@@ -1309,6 +1312,9 @@
 	if (p != nullptr) {
 		CN_CBOR_FREE(p, context);
 	}
+	if (pkey != nullptr) {
+		CN_CBOR_FREE(pkey, context);
+	}
 	return coseKey;
 
 errorReturn:
@@ -1675,7 +1681,7 @@
 	const byte *pbCipherText,
 	size_t cbCipherText,
 	byte *pbKeyOut,
-	int *pcbKeyOut,
+	size_t *pcbKeyOut,
 	cose_errback *perr)
 {
 	byte rgbOut[512 / 8];
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 382ee14..aded8c8 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,6 +1,6 @@
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dist_dir}/test)
 
-add_executable(cose_test test.cpp json.cpp Encrypt_test.cpp Sign_test.cpp context.cpp Mac_test.cpp CounterSign_test.cpp)
+add_executable(cose_test test.cpp json.cpp Encrypt_test.cpp Sign_test.cpp context.cpp Mac_test.cpp CounterSign_test.cpp CounterSign1_test.cpp)
 
 target_link_libraries(cose_test PRIVATE cose-c::cose-c cn-cbor::cn-cbor)
 
@@ -119,6 +119,12 @@
     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
     COMMAND cose_test --dir Examples/countersign)
 endif()
+if(COSE_C_INCLUDE_COUNTERSIGN1)
+  add_test(
+    NAME Countersign1
+    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+    COMMAND cose_test --dir Examples/countersign1)
+endif()
 
 add_test(
   NAME corner-cases
@@ -183,3 +189,9 @@
     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
     COMMAND cose_test --memory Examples/countersign/mac0-01.json)
 endif()
+if(COSE_C_INCLUDE_COUNTERSIGN1)
+  add_test(
+    NAME Memory-Countersign1
+    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+    COMMAND cose_test --memory Examples/countersign1/mac0-01.json)
+endif()
diff --git a/test/CounterSign1_test.cpp b/test/CounterSign1_test.cpp
new file mode 100644
index 0000000..dddeec0
--- /dev/null
+++ b/test/CounterSign1_test.cpp
@@ -0,0 +1,93 @@
+//  encrypt.c
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cose/cose.h>
+#include <cose/cose_configure.h>
+#include <cn-cbor/cn-cbor.h>
+
+#if INCLUDE_COUNTERSIGNATURE1
+
+#include "test.h"
+#include "cose_int.h"
+
+void CounterSign1_Corners()
+{
+	HCOSE_COUNTERSIGN1 hCounterSign = NULL;
+	HCOSE_COUNTERSIGN1 hBadHandle = NULL;
+	HCOSE_COUNTERSIGN1 hNULL = NULL;
+	cose_errback cose_error;
+	byte rgb[10];
+
+	cn_cbor *cn = cn_cbor_int_create(5, CBOR_CONTEXT_PARAM_COMMA NULL);
+
+	hCounterSign = COSE_CounterSign1_Init(CBOR_CONTEXT_PARAM_COMMA NULL);
+	hBadHandle = (HCOSE_COUNTERSIGN1)COSE_CALLOC(1, sizeof(COSE), context);
+#if INCLUDE_SIGN1
+	HCOSE_SIGN1 hSign1 = COSE_Sign1_Init(
+		COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA & cose_error);
+#endif
+	//  Look for invalid parameter
+	//		Null handle checks
+	//		bad handle checks
+	//		null pointers
+
+	CHECK_FAILURE(
+		COSE_CounterSign1_map_get_int(hNULL, 1, COSE_BOTH, &cose_error),
+		COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(
+		COSE_CounterSign1_map_get_int(hNULL, 1, COSE_BOTH, &cose_error),
+		COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(
+		COSE_CounterSign1_map_get_int(hCounterSign, 1, COSE_BOTH, &cose_error),
+		COSE_ERR_INVALID_PARAMETER, CFails++);
+
+	CHECK_FAILURE(COSE_CounterSign1_map_put_int(
+					  hNULL, 1, cn, COSE_PROTECT_ONLY, &cose_error),
+		COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_CounterSign1_map_put_int(
+					  hNULL, 1, cn, COSE_PROTECT_ONLY, &cose_error),
+		COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_CounterSign1_map_put_int(
+					  hNULL, 1, NULL, COSE_PROTECT_ONLY, &cose_error),
+		COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_CounterSign1_map_put_int(hCounterSign, 1, cn,
+					  COSE_PROTECT_ONLY | COSE_UNPROTECT_ONLY, &cose_error),
+		COSE_ERR_INVALID_PARAMETER, CFails++);
+
+#if INCLUDE_SIGN1
+	CHECK_FAILURE(
+		COSE_Sign1_add_countersignature1(hSign1, hBadHandle, &cose_error),
+		COSE_ERR_INVALID_HANDLE, CFails++);
+	((COSE_CounterSign1 *)hCounterSign)->m_next =
+		(COSE_CounterSign1 *)hBadHandle;
+	CHECK_FAILURE(
+		COSE_Sign1_add_countersignature1(hSign1, hCounterSign, &cose_error),
+		COSE_ERR_INVALID_PARAMETER, CFails++);
+	CHECK_FAILURE(COSE_Sign1_get_countersignature1(hSign1, &cose_error),
+		COSE_ERR_INVALID_PARAMETER, CFails++);
+	((COSE_CounterSign1 *)hCounterSign)->m_next = NULL;
+	COSE_Sign1_add_countersignature1(hSign1, hCounterSign, &cose_error);
+	CHECK_FAILURE(COSE_Sign1_get_countersignature1(hSign1, &cose_error),
+		COSE_ERR_INVALID_PARAMETER, CFails++);
+#endif
+
+	CHECK_FAILURE(
+		COSE_CounterSign1_SetExternal(hNULL, rgb, sizeof(rgb), &cose_error),
+		COSE_ERR_INVALID_HANDLE, CFails++);
+	CHECK_FAILURE(COSE_CounterSign1_SetExternal(
+					  hBadHandle, rgb, sizeof(rgb), &cose_error),
+		COSE_ERR_INVALID_HANDLE, CFails++);
+	COSE_CounterSign1_SetExternal(hCounterSign, rgb, sizeof(rgb), &cose_error);
+
+	CHECK_RETURN(!COSE_CounterSign1_Free(hBadHandle), false, CFails++);
+
+	COSE_CounterSign1_Free(hCounterSign);
+#if INCLUDE_SIGN1
+	COSE_Sign1_Free(hSign1);
+#endif
+}
+#endif
diff --git a/test/Encrypt_test.cpp b/test/Encrypt_test.cpp
index 878e943..b32c710 100644
--- a/test/Encrypt_test.cpp
+++ b/test/Encrypt_test.cpp
@@ -3,6 +3,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <memory>
 #include <cose/cose.h>
 #include <cose/cose_configure.h>
 #include <cn-cbor/cn-cbor.h>
@@ -10,7 +11,6 @@
 	(!INCLUDE_MAC || !INCLUDE_SIGN)
 #include <cose_int.h>
 #endif
-#include "json.h"
 #include "test.h"
 #include "context.h"
 #include "cose_int.h"
@@ -23,7 +23,8 @@
 #endif
 
 #if INCLUDE_ENCRYPT
-bool DecryptMessage(const byte *pbEncoded,
+//  Return 1=expected failure, 0 = failure, 2 = success
+int DecryptMessage(const byte *pbEncoded,
 	size_t cbEncoded,
 	bool fFailBody,
 	const cn_cbor *pEnveloped,
@@ -32,43 +33,24 @@
 	const cn_cbor *pRecipient2,
 	int iRecipient2)
 {
-	HCOSE_ENVELOPED hEnc = nullptr;
-	HCOSE_RECIPIENT hRecip = nullptr;
-	HCOSE_RECIPIENT hRecip1 = nullptr;
-	HCOSE_RECIPIENT hRecip2 = nullptr;
-	bool fRet = false;
 	int type = 0;
 	cose_errback cose_err;
-	cn_cbor *pkey = nullptr;
 	bool fNoSupport = false;
+	int returnValue = 2;
 
-	if (false) {
-	errorReturn:
-		if (hEnc != nullptr) {
-			COSE_Enveloped_Free(hEnc);
-		}
-		if (hRecip1 != nullptr) {
-			COSE_Recipient_Free(hRecip1);
-		}
-		if (hRecip2 != nullptr) {
-			COSE_Recipient_Free(hRecip2);
-		}
-
-		return fRet;
-	}
-
-	hEnc = (HCOSE_ENVELOPED)COSE_Decode(pbEncoded, cbEncoded, &type,
-		COSE_enveloped_object, CBOR_CONTEXT_PARAM_COMMA & cose_err);
-	if (hEnc == nullptr) {
+	Safe_HCOSE_ENVELOPED hEnc =
+		reinterpret_cast<HCOSE_ENVELOPED>(COSE_Decode(pbEncoded, cbEncoded,
+			&type, COSE_enveloped_object, CBOR_CONTEXT_PARAM_COMMA & cose_err));
+	if (hEnc.IsNull()) {
 		if (fFailBody && (cose_err.err == COSE_ERR_INVALID_PARAMETER)) {
-			return true;
+			return 1;
 		}
-		goto errorReturn;
+		return 0;
 	}
 
 	if (!SetReceivingAttributes(
-			(HCOSE)hEnc, pEnveloped, Attributes_Enveloped_protected)) {
-		goto errorReturn;
+			hEnc, pEnveloped, Attributes_Enveloped_protected)) {
+		return 0;
 	}
 
 	cn_cbor *alg = COSE_Enveloped_map_get_int(
@@ -77,64 +59,78 @@
 		fNoSupport = true;
 	}
 
-	hRecip1 = COSE_Enveloped_GetRecipient(hEnc, iRecipient1, nullptr);
-	if (hRecip1 == nullptr) {
-		goto errorReturn;
+	Safe_HCOSE_RECIPIENT hRecip =
+		COSE_Enveloped_GetRecipient(hEnc, iRecipient1, nullptr);
+	if (hRecip.IsNull()) {
+		return 0;
 	}
 	if (!SetReceivingAttributes(
-			(HCOSE)hRecip1, pRecipient1, Attributes_Recipient_protected)) {
-		goto errorReturn;
+			hRecip, pRecipient1, Attributes_Recipient_protected)) {
+		return 0;
 	}
 
 	if (pRecipient2 != nullptr) {
-		pkey = BuildKey(cn_cbor_mapget_string(pRecipient2, "key"), false);
-		if (pkey == nullptr) {
-			goto errorReturn;
+		Safe_HCOSE_KEY hkey =
+			BuildKey(cn_cbor_mapget_string(pRecipient2, "key"), false);
+		if (hkey == nullptr) {
+			return 0;
 		}
 
-		hRecip2 = COSE_Recipient_GetRecipient(hRecip1, iRecipient2, nullptr);
-		if (hRecip2 == nullptr) {
-			goto errorReturn;
+		Safe_HCOSE_RECIPIENT hRecip2 =
+			COSE_Recipient_GetRecipient(hRecip, iRecipient2, nullptr);
+		if (hRecip2.IsNull()) {
+			return 0;
 		}
 
 		if (!SetReceivingAttributes(
-				(HCOSE)hRecip2, pRecipient2, Attributes_Recipient_protected)) {
-			goto errorReturn;
+				hRecip2, pRecipient2, Attributes_Recipient_protected)) {
+			return 0;
 		}
-		if (!COSE_Recipient_SetKey(hRecip2, pkey, nullptr)) {
-			goto errorReturn;
+		if (!COSE_Recipient_SetKey2(hRecip2, hkey, nullptr)) {
+			return 0;
 		}
 
 		cn_cbor *cnStatic = cn_cbor_mapget_string(pRecipient2, "sender_key");
 		if (cnStatic != nullptr) {
-			if (COSE_Recipient_map_get_int(
-					hRecip2, COSE_Header_ECDH_SPK, COSE_BOTH, nullptr) == 0) {
-				COSE_Recipient_map_put_int(hRecip2, COSE_Header_ECDH_SPK,
-					BuildKey(cnStatic, true), COSE_DONT_SEND, nullptr);
+			if (COSE_Recipient_map_get_int(hRecip2, COSE_Header_ECDH_SPK,
+					COSE_BOTH, nullptr) == nullptr) {
+				Safe_HCOSE_KEY senderKey = BuildKey(cnStatic, true);
+				if (senderKey == nullptr) {
+					return 0;
+				}
+				if (!COSE_Recipient_SetSenderKey2(
+						hRecip2, senderKey, COSE_DONT_SEND, nullptr)) {
+					return 0;
+				}
 			}
 		}
 
-		hRecip = hRecip2;
+		hRecip.Transfer(&hRecip2);
 	}
 	else {
-		pkey = BuildKey(cn_cbor_mapget_string(pRecipient1, "key"), false);
-		if (pkey == nullptr) {
-			goto errorReturn;
+		Safe_HCOSE_KEY hkey =
+			BuildKey(cn_cbor_mapget_string(pRecipient1, "key"), false);
+		if (hkey == nullptr) {
+			return 0;
 		}
-		if (!COSE_Recipient_SetKey(hRecip1, pkey, nullptr)) {
-			goto errorReturn;
+		if (!COSE_Recipient_SetKey2(hRecip, hkey, nullptr)) {
+			return 0;
 		}
 
 		cn_cbor *cnStatic = cn_cbor_mapget_string(pRecipient1, "sender_key");
 		if (cnStatic != nullptr) {
-			if (COSE_Recipient_map_get_int(
-					hRecip1, COSE_Header_ECDH_SPK, COSE_BOTH, nullptr) == 0) {
-				COSE_Recipient_map_put_int(hRecip1, COSE_Header_ECDH_SPK,
-					BuildKey(cnStatic, true), COSE_DONT_SEND, nullptr);
+			if (COSE_Recipient_map_get_int(hRecip, COSE_Header_ECDH_SPK,
+					COSE_BOTH, nullptr) == nullptr) {
+				Safe_HCOSE_KEY senderKey = BuildKey(cnStatic, true);
+				if (senderKey == nullptr) {
+					return 0;
+				}
+				if (!COSE_Recipient_SetSenderKey2(
+						hRecip, senderKey, COSE_DONT_SEND, nullptr)) {
+					return 0;
+				}
 			}
 		}
-
-		hRecip = hRecip1;
 	}
 
 	if (!fFailBody) {
@@ -148,377 +144,508 @@
 				fFailBody = true;
 			}
 		}
-
-		if (hRecip2 != nullptr) {
-			alg = COSE_Recipient_map_get_int(
-				hRecip2, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-			if (!IsAlgorithmSupported(alg)) {
-				fNoSupport = true;
-			}
-		}
-		alg = COSE_Recipient_map_get_int(
-			hRecip1, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-		if (!IsAlgorithmSupported(alg)) {
-			fNoSupport = true;
-		}
 	}
 
 	if (COSE_Enveloped_decrypt(hEnc, hRecip, &cose_err)) {
-		fRet = !fFailBody;
+		returnValue = COSE_MIN(fFailBody ? 1 : 2, returnValue);
 	}
 	else {
 		if (cose_err.err == COSE_ERR_NO_COMPRESSED_POINTS ||
 			cose_err.err == COSE_ERR_UNKNOWN_ALGORITHM) {
-			fRet = false;
-			fNoSupport = true;
+			returnValue = COSE_MIN(1, returnValue);
 		}
 		else if (fNoSupport) {
-			fRet = false;
+			returnValue = 0;
 		}
 		else {
-			fRet = fFailBody;
+			returnValue = COSE_MIN(fFailBody ? 1 : 0, returnValue);
 		}
 	}
 
 #if INCLUDE_COUNTERSIGNATURE
-	//  Countersign on Encrypt0 Body
+	{
+		//  Countersign on Recipient Body
 
-	//  Validate counter signatures on signers
-	cn_cbor *countersignList =
-		cn_cbor_mapget_string(pRecipient1, "countersign");
-	if (countersignList != nullptr) {
-		cn_cbor *countersigners =
-			cn_cbor_mapget_string(countersignList, "signers");
-		if (countersigners == nullptr) {
-			fRet = false;
-			goto errorReturn;
-		}
-		int count = countersigners->length;
-		bool forward = true;
+		//  Validate counter signatures on signers
+		cn_cbor *countersignList =
+			cn_cbor_mapget_string(pRecipient1, "countersign");
+		if (countersignList != nullptr) {
+			cn_cbor *countersigners =
+				cn_cbor_mapget_string(countersignList, "signers");
+			if (countersigners == nullptr) {
+				return 0;
+			}
+			const int count = (int)countersigners->length;
+			bool forward = true;
 
-		if (COSE_Recipient_map_get_int(hRecip1, COSE_Header_CounterSign,
-				COSE_UNPROTECT_ONLY, 0) == nullptr) {
-			goto errorReturn;
-		}
-
-		for (int counterNo = 0; counterNo < count; counterNo++) {
-			bool noSupportSign = false;
-
-			HCOSE_COUNTERSIGN h =
-				COSE_Recipient_get_countersignature(hRecip1, counterNo, 0);
-			if (h == nullptr) {
-				fRet = false;
-				continue;
+			if (COSE_Recipient_map_get_int(hRecip, COSE_Header_CounterSign,
+					COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+				return 0;
 			}
 
-			cn_cbor *counterSigner = cn_cbor_index(
-				countersigners, forward ? counterNo : count - counterNo - 1);
+			for (int counterNo = 0; counterNo < count; counterNo++) {
+				bool noSupportSign = false;
 
-			cn_cbor *pkeyCountersign =
+				Safe_HCOSE_COUNTERSIGN h = COSE_Recipient_get_countersignature(
+					hRecip, counterNo, nullptr);
+				if (h.IsNull()) {
+					returnValue = 0;
+					continue;
+				}
+
+				cn_cbor *counterSigner = cn_cbor_index(countersigners,
+					forward ? counterNo : count - counterNo - 1);
+
+				Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+					cn_cbor_mapget_string(counterSigner, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					returnValue = 0;
+					continue;
+				}
+
+				if (!COSE_CounterSign_SetKey2(h, hkeyCountersign, nullptr)) {
+					returnValue = 0;
+					continue;
+				}
+
+				cose_errback coseError;
+
+				if (COSE_Recipient_CounterSign_validate(
+						hRecip, h, &coseError)) {
+					//  I don't think we have any forced errors yet.
+				}
+				else {
+					if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+						returnValue = COSE_MIN(1, returnValue);
+						continue;
+					}
+
+					if (forward && counterNo == 0 && count > 1) {
+						forward = false;
+						counterNo -= 1;
+						continue;
+					}
+					returnValue = 0;
+				}
+			}
+		}
+	}
+#endif
+
+#if INCLUDE_COUNTERSIGNATURE1
+	{
+		//  Countersign1 on Recipient Body
+
+		//  Validate counter signatures on signers
+		const cn_cbor *countersignList =
+			cn_cbor_mapget_string(pRecipient1, "countersign0");
+		if (countersignList != nullptr) {
+			cn_cbor *countersigners =
+				cn_cbor_mapget_string(countersignList, "signers");
+			if (countersigners == nullptr) {
+				return 0;
+			}
+
+			if (COSE_Recipient_map_get_int(hRecip, COSE_Header_CounterSign1,
+					COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+				return 0;
+			}
+
+			Safe_HCOSE_COUNTERSIGN1 h(
+				COSE_Recipient_get_countersignature1(hRecip, nullptr));
+			if (h.IsNull()) {
+				return 0;
+			}
+
+			cn_cbor *counterSigner = cn_cbor_index(countersigners, 0);
+
+			Safe_HCOSE_KEY hkeyCountersign =
 				BuildKey(cn_cbor_mapget_string(counterSigner, "key"), false);
-			if (pkeyCountersign == nullptr) {
-				fRet = false;
-				COSE_CounterSign_Free(h);
-				continue;
+			if (hkeyCountersign == nullptr) {
+				return 0;
 			}
 
-			if (!COSE_CounterSign_SetKey(h, pkeyCountersign, 0)) {
-				fRet = false;
-				COSE_CounterSign_Free(h);
-				CN_CBOR_FREE(pkeyCountersign, context);
-				continue;
+			if (!COSE_CounterSign1_SetKey(h, hkeyCountersign, nullptr)) {
+				return 0;
 			}
 
-			alg = COSE_CounterSign_map_get_int(
-				h, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-			if (!IsAlgorithmSupported(alg)) {
-				noSupportSign = true;
-				fNoSupport = true;
+			if (!SetReceivingAttributes(h, counterSigner, Attributes_Countersign1_protected)) {
+				return 0;
 			}
 
-			if (COSE_Recipient_CounterSign_validate(hRecip1, h, 0)) {
+			cose_errback coseError;
+			if (COSE_Recipient_CounterSign1_validate(hRecip, h, &coseError)) {
 				//  I don't think we have any forced errors yet.
 			}
 			else {
-				if (forward && counterNo == 0 && count > 1) {
-					forward = false;
-					counterNo -= 1;
+				if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+					returnValue = COSE_MIN(1, returnValue);
 				}
 				else {
-					fRet = !noSupportSign;
+					returnValue = 0;
 				}
 			}
-
-			COSE_CounterSign_Free(h);
 		}
 	}
 #endif
 
 #if INCLUDE_COUNTERSIGNATURE
-	//  Countersign on Enveloped Body
+	{
+		//  Countersign on Enveloped Body
 
-	//  Validate counter signatures on signers
-	countersignList = cn_cbor_mapget_string(pEnveloped, "countersign");
-	if (countersignList != nullptr) {
-		cn_cbor *countersigners =
-			cn_cbor_mapget_string(countersignList, "signers");
-		if (countersigners == nullptr) {
-			fRet = false;
-			goto errorReturn;
-		}
-		int count = countersigners->length;
-		bool forward = true;
+		//  Validate counter signatures on signers
+		const cn_cbor *countersignList =
+			cn_cbor_mapget_string(pEnveloped, "countersign");
+		if (countersignList != nullptr) {
+			cn_cbor *countersigners =
+				cn_cbor_mapget_string(countersignList, "signers");
+			if (countersigners == nullptr) {
+				return 0;
+			}
+			const int count = (int)countersigners->length;
+			bool forward = true;
 
-		if (COSE_Enveloped_map_get_int(hEnc, COSE_Header_CounterSign,
-				COSE_UNPROTECT_ONLY, 0) == nullptr) {
-			fRet = false;
-			goto errorReturn;
-		}
-
-		for (int counterNo = 0; counterNo < count; counterNo++) {
-			bool noSupportSign = false;
-			HCOSE_COUNTERSIGN h =
-				COSE_Enveloped_get_countersignature(hEnc, counterNo, 0);
-			if (h == nullptr) {
-				fRet = false;
-				continue;
+			if (COSE_Enveloped_map_get_int(hEnc, COSE_Header_CounterSign,
+					COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+				return false;
 			}
 
-			cn_cbor *counterSigner = cn_cbor_index(
-				countersigners, forward ? counterNo : count - counterNo - 1);
+			for (int counterNo = 0; counterNo < count; counterNo++) {
+				Safe_HCOSE_COUNTERSIGN h = COSE_Enveloped_get_countersignature(
+					hEnc, counterNo, nullptr);
+				if (h == nullptr) {
+					return 0;
+				}
 
-			cn_cbor *pkeyCountersign =
-				BuildKey(cn_cbor_mapget_string(counterSigner, "key"), false);
-			if (pkeyCountersign == nullptr) {
-				fRet = false;
-				COSE_CounterSign_Free(h);
-				continue;
-			}
+				cn_cbor *counterSigner = cn_cbor_index(countersigners,
+					forward ? counterNo : count - counterNo - 1);
 
-			if (!COSE_CounterSign_SetKey(h, pkeyCountersign, 0)) {
-				fRet = false;
-				COSE_CounterSign_Free(h);
-				CN_CBOR_FREE(pkeyCountersign, context);
-				continue;
-			}
+				Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+					cn_cbor_mapget_string(counterSigner, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					returnValue = 0;
+					continue;
+				}
 
-			alg = COSE_CounterSign_map_get_int(
-				h, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-			if (!IsAlgorithmSupported(alg)) {
-				noSupportSign = true;
-				fNoSupport = true;
-			}
+				if (!COSE_CounterSign_SetKey2(h, hkeyCountersign, nullptr)) {
+					returnValue = 0;
+					continue;
+				}
 
-			if (COSE_Enveloped_CounterSign_validate(hEnc, h, 0)) {
-				//  I don't think we have any forced errors yet.
-			}
-			else {
-				if (forward && counterNo == 0 && count > 1) {
-					forward = false;
-					counterNo -= 1;
+				cose_errback coseError;
+
+				if (COSE_Enveloped_CounterSign_validate(hEnc, h, &coseError)) {
+					//  I don't think we have any forced errors yet.
 				}
 				else {
-					fRet = !noSupportSign;
+					if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+						returnValue = COSE_MIN(1, returnValue);
+						continue;
+					}
+
+					if (forward && counterNo == 0 && count > 1) {
+						forward = false;
+						counterNo -= 1;
+						continue;
+					}
+
+					returnValue = 0;
 				}
 			}
-
-			COSE_CounterSign_Free(h);
 		}
 	}
 #endif
 
-	if (!fRet && !fNoSupport) {
+#if INCLUDE_COUNTERSIGNATURE1
+	{
+		//  Countersign1 on Enveloped Body
+
+		//  Validate counter signatures on signers
+		const cn_cbor *countersignList =
+			cn_cbor_mapget_string(pEnveloped, "countersign0");
+		if (countersignList != nullptr) {
+			cn_cbor *countersigners =
+				cn_cbor_mapget_string(countersignList, "signers");
+			if (countersigners == nullptr) {
+				return 0;
+			}
+
+			if (COSE_Enveloped_map_get_int(hEnc, COSE_Header_CounterSign1,
+					COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+				return 0;
+			}
+
+			bool noSupportSign = false;
+			Safe_HCOSE_COUNTERSIGN1 h =
+				COSE_Enveloped_get_countersignature1(hEnc, nullptr);
+			if (h.IsNull()) {
+				return 0;
+			}
+
+			cn_cbor *counterSigner = cn_cbor_index(countersigners, 0);
+
+			Safe_HCOSE_KEY hkeyCountersign(
+				BuildKey(cn_cbor_mapget_string(counterSigner, "key"), false));
+			if (hkeyCountersign == nullptr) {
+				return 0;
+			}
+
+			if (!COSE_CounterSign1_SetKey(h, hkeyCountersign, nullptr)) {
+				return false;
+			}
+
+			if (!SetReceivingAttributes(
+					h, counterSigner, Attributes_Countersign1_protected)) {
+				return false;
+			}
+
+			cose_errback coseError;
+			if (COSE_Enveloped_CounterSign1_validate(hEnc, h, &coseError)) {
+				//  I don't think we have any forced errors yet.
+			}
+			else {
+				if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+					returnValue = COSE_MIN(1, returnValue);
+				}
+				else {
+					returnValue = 0;
+				}
+			}
+		}
+	}
+#endif
+
+	if (returnValue == 0) {
 		CFails++;
 	}
-	goto errorReturn;
+	return returnValue;
 }
 
+//  Return 1=expected failure, 0 = failure, 2 = success
 int _ValidateEnveloped(const cn_cbor *pControl,
 	const byte *pbEncoded,
 	size_t cbEncoded)
 {
 	const cn_cbor *pInput = cn_cbor_mapget_string(pControl, "input");
-	const cn_cbor *pFail;
-	const cn_cbor *pEnveloped;
-	const cn_cbor *pRecipients;
-	int iRecipient;
 	bool fFailBody = false;
 	int passCount = 0;
+	int returnValue = 2;
 
-	pFail = cn_cbor_mapget_string(pControl, "fail");
+	const cn_cbor *pFail = cn_cbor_mapget_string(pControl, "fail");
 	if ((pFail != nullptr) && (pFail->type == CN_CBOR_TRUE)) {
 		fFailBody = true;
 	}
 
 	if ((pInput == nullptr) || (pInput->type != CN_CBOR_MAP)) {
-		goto errorReturn;
+		return 0;
 	}
-	pEnveloped = cn_cbor_mapget_string(pInput, "enveloped");
+
+	const cn_cbor *pEnveloped = cn_cbor_mapget_string(pInput, "enveloped");
 	if ((pEnveloped == nullptr) || (pEnveloped->type != CN_CBOR_MAP)) {
-		goto errorReturn;
+		return 0;
 	}
 
-	pRecipients = cn_cbor_mapget_string(pEnveloped, "recipients");
+	const cn_cbor *pRecipients =
+		cn_cbor_mapget_string(pEnveloped, "recipients");
 	if ((pRecipients == nullptr) || (pRecipients->type != CN_CBOR_ARRAY)) {
-		goto errorReturn;
+		return 0;
 	}
 
-	iRecipient = (int)pRecipients->length - 1;
+	int iRecipient = static_cast<int>(pRecipients->length) - 1;
 	pRecipients = pRecipients->first_child;
-	for (; pRecipients != nullptr; iRecipient--, pRecipients = pRecipients->next) {
-		cn_cbor *pRecip2 = cn_cbor_mapget_string(pRecipients, "recipients");
+	for (; pRecipients != nullptr;
+		 iRecipient--, pRecipients = pRecipients->next) {
+		const cn_cbor *pRecip2 =
+			cn_cbor_mapget_string(pRecipients, "recipients");
 		if (pRecip2 == nullptr) {
-			if (DecryptMessage(pbEncoded, cbEncoded, fFailBody, pEnveloped,
-					pRecipients, iRecipient, nullptr, 0)) {
-				passCount++;
-			}
+			int value = DecryptMessage(pbEncoded, cbEncoded, fFailBody,
+				pEnveloped, pRecipients, iRecipient, nullptr, 0);
+			returnValue = COSE_MIN(value, returnValue);
 		}
 		else {
-			int iRecipient2 = (int)(pRecip2->length - 1);
+			int iRecipient2 = static_cast<int>(pRecip2->length - 1);
 			pRecip2 = pRecip2->first_child;
 			for (; pRecip2 != nullptr; pRecip2 = pRecip2->next, iRecipient2--) {
-				if (DecryptMessage(pbEncoded, cbEncoded, fFailBody, pEnveloped,
-						pRecipients, iRecipient, pRecip2, iRecipient2)) {
-					passCount++;
-				}
+				int value = DecryptMessage(pbEncoded, cbEncoded, fFailBody,
+					pEnveloped, pRecipients, iRecipient, pRecip2, iRecipient2);
+				returnValue = COSE_MIN(value, returnValue);
 			}
 		}
 	}
-	return passCount > 0;
-
-errorReturn:
-	CFails += 1;
-	return 0;
+	return returnValue;
 }
 
-int ValidateEnveloped(const cn_cbor *pControl)
+bool ValidateEnveloped(const cn_cbor *pControl)
 {
 	int cbEncoded;
 	byte *pbEncoded = GetCBOREncoding(pControl, &cbEncoded);
 
-	return _ValidateEnveloped(pControl, pbEncoded, cbEncoded);
+	int i = _ValidateEnveloped(pControl, pbEncoded, cbEncoded);
+	if (i == 0) {
+		CFails += 1;
+	}
+	return i == 2;
 }
 
 HCOSE_RECIPIENT BuildRecipient(const cn_cbor *pRecipient)
 {
-	HCOSE_RECIPIENT hRecip = COSE_Recipient_Init(
+	Safe_HCOSE_RECIPIENT hRecip = COSE_Recipient_Init(
 		COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	if (hRecip == nullptr) {
-	returnError:
-		COSE_Recipient_Free(hRecip);
 		return nullptr;
 	}
 
 	if (!SetSendingAttributes(
-			(HCOSE)hRecip, pRecipient, Attributes_Recipient_protected)) {
-		goto returnError;
+			hRecip, pRecipient, Attributes_Recipient_protected)) {
+		return nullptr;
 	}
 
 	cn_cbor *cnKey = cn_cbor_mapget_string(pRecipient, "key");
 	if (cnKey != nullptr) {
-		cn_cbor *pkey = BuildKey(cnKey, true);
-		if (pkey == nullptr) {
-			goto returnError;
+		Safe_HCOSE_KEY hkey = BuildKey(cnKey, true);
+		if (hkey == nullptr) {
+			return nullptr;
 		}
 
-		if (!COSE_Recipient_SetKey(hRecip, pkey, nullptr)) {
-			goto returnError;
+		if (!COSE_Recipient_SetKey2(hRecip, hkey, nullptr)) {
+			return nullptr;
 		}
 	}
 
 	cnKey = cn_cbor_mapget_string(pRecipient, "recipients");
 	if (cnKey != nullptr) {
-		for (cnKey = cnKey->first_child; cnKey != nullptr; cnKey = cnKey->next) {
-			HCOSE_RECIPIENT hRecip2 = BuildRecipient(cnKey);
+		for (cnKey = cnKey->first_child; cnKey != nullptr;
+			 cnKey = cnKey->next) {
+			Safe_HCOSE_RECIPIENT hRecip2 = BuildRecipient(cnKey);
 			if (hRecip2 == nullptr) {
-				goto returnError;
+				return nullptr;
 			}
 			if (!COSE_Recipient_AddRecipient(hRecip, hRecip2, nullptr)) {
-				goto returnError;
+				return nullptr;
 			}
-			COSE_Recipient_Free(hRecip2);
 		}
 	}
 
 	cn_cbor *pSenderKey = cn_cbor_mapget_string(pRecipient, "sender_key");
 	if (pSenderKey != nullptr) {
-		cn_cbor *pSendKey = BuildKey(pSenderKey, false);
+		Safe_HCOSE_KEY hSendKey = BuildKey(pSenderKey, false);
 		cn_cbor *pKid = cn_cbor_mapget_string(pSenderKey, "kid");
-		if (!COSE_Recipient_SetSenderKey(
-				hRecip, pSendKey, (pKid == nullptr) ? 2 : 1, nullptr)) {
-			goto returnError;
+		if (!COSE_Recipient_SetSenderKey2(
+				hRecip, hSendKey, (pKid == nullptr) ? 2 : 1, nullptr)) {
+			return nullptr;
 		}
 	}
 
 #if INCLUDE_COUNTERSIGNATURE
-	// On the Recipient
-	cn_cbor *countersigns1 = cn_cbor_mapget_string(pRecipient, "countersign");
-	if (countersigns1 != nullptr) {
-		countersigns1 = cn_cbor_mapget_string(countersigns1, "signers");
-		cn_cbor *countersign = countersigns1->first_child;
+	{
+		// On the Recipient
+		cn_cbor *countersigns1 =
+			cn_cbor_mapget_string(pRecipient, "countersign");
+		if (countersigns1 != nullptr) {
+			countersigns1 = cn_cbor_mapget_string(countersigns1, "signers");
+			cn_cbor *countersign = countersigns1->first_child;
 
-		for (; countersign != nullptr; countersign = countersign->next) {
-			cn_cbor *pkeyCountersign =
-				BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
-			if (pkeyCountersign == nullptr) {
-				goto returnError;
+			for (; countersign != nullptr; countersign = countersign->next) {
+				Safe_HCOSE_KEY hkeyCountersign =
+					BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					return nullptr;
+				}
+
+				Safe_HCOSE_COUNTERSIGN hCountersign =
+					COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+				if (hCountersign == nullptr) {
+					return nullptr;
+				}
+
+				if (!SetSendingAttributes(hCountersign, countersign,
+						Attributes_Countersign_protected)) {
+					return nullptr;
+				}
+
+				if (!COSE_CounterSign_SetKey2(
+						hCountersign, hkeyCountersign, nullptr)) {
+					return nullptr;
+				}
+
+				if (!COSE_Recipient_add_countersignature(
+						hRecip, hCountersign, nullptr)) {
+					return nullptr;
+				}
 			}
-
-			HCOSE_COUNTERSIGN hCountersign =
-				COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
-			if (hCountersign == nullptr) {
-				goto returnError;
-			}
-
-			if (!SetSendingAttributes((HCOSE)hCountersign, countersign,
-					Attributes_Countersign_protected)) {
-				goto returnError;
-			}
-
-			if (!COSE_CounterSign_SetKey(hCountersign, pkeyCountersign, nullptr)) {
-				goto returnError;
-			}
-
-			if (!COSE_Recipient_add_countersignature(
-					hRecip, hCountersign, nullptr)) {
-				goto returnError;
-			}
-
-			COSE_CounterSign_Free(hCountersign);
 		}
 	}
 
 #endif
 
-	return hRecip;
+#if INCLUDE_COUNTERSIGNATURE1
+	{
+		// On the Recipient
+		cn_cbor *countersigns2 =
+			cn_cbor_mapget_string(pRecipient, "countersign0");
+		if (countersigns2 != nullptr) {
+			countersigns2 = cn_cbor_mapget_string(countersigns2, "signers");
+			cn_cbor *countersign = countersigns2->first_child;
+
+			for (; countersign != nullptr; countersign = countersign->next) {
+				Safe_HCOSE_KEY hkeyCountersign =
+					BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					return nullptr;
+				}
+
+				Safe_HCOSE_COUNTERSIGN1 hCountersign1;
+				hCountersign1.Set(
+					COSE_CounterSign1_Init(CBOR_CONTEXT_PARAM_COMMA nullptr));
+				if (hCountersign1.IsNull()) {
+					return nullptr;
+				}
+
+				if (!SetSendingAttributes(hCountersign1, countersign,
+						Attributes_Countersign1_protected)) {
+					return nullptr;
+				}
+
+				if (!COSE_CounterSign1_SetKey(
+						hCountersign1, hkeyCountersign, nullptr)) {
+					return nullptr;
+				}
+
+				if (!COSE_Recipient_add_countersignature1(
+						hRecip, hCountersign1, nullptr)) {
+					return nullptr;
+				}
+			}
+		}
+	}
+#endif
+
+	HCOSE_RECIPIENT r = hRecip;
+	hRecip.Clear();
+	return r;
 }
 
-int BuildEnvelopedMessage(const cn_cbor *pControl)
+bool BuildEnvelopedMessage(const cn_cbor *pControl)
 {
-	int iRecipient;
-
 	//
 	//  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 != nullptr) && (pFail->type == CN_CBOR_TRUE)) {
-		return 0;
+	returnError:
+		CFails += 1;
+		return false;
 	}
 
-	HCOSE_ENVELOPED hEncObj = COSE_Enveloped_Init(
+	Safe_HCOSE_ENVELOPED hEncObj = COSE_Enveloped_Init(
 		COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
 	const cn_cbor *pInputs = cn_cbor_mapget_string(pControl, "input");
 	if (pInputs == nullptr) {
-	returnError:
-		if (hEncObj != nullptr) {
-			COSE_Enveloped_Free(hEncObj);
-		}
-
-		CFails += 1;
-		return 0;
+		goto returnError;
 	}
+
 	const cn_cbor *pEnveloped = cn_cbor_mapget_string(pInputs, "enveloped");
 	if (pEnveloped == nullptr) {
 		goto returnError;
@@ -531,13 +658,7 @@
 	}
 
 	if (!SetSendingAttributes(
-			(HCOSE)hEncObj, pEnveloped, Attributes_Enveloped_protected)) {
-		goto returnError;
-	}
-
-	const cn_cbor *pAlg =
-		COSE_Enveloped_map_get_int(hEncObj, 1, COSE_BOTH, nullptr);
-	if (pAlg == nullptr) {
+			hEncObj, pEnveloped, Attributes_Enveloped_protected)) {
 		goto returnError;
 	}
 
@@ -548,81 +669,119 @@
 	}
 
 	pRecipients = pRecipients->first_child;
-	for (iRecipient = 0; pRecipients != nullptr;
+	for (int iRecipient = 0; pRecipients != nullptr;
 		 iRecipient++, pRecipients = pRecipients->next) {
-		HCOSE_RECIPIENT hRecip = BuildRecipient(pRecipients);
+		Safe_HCOSE_RECIPIENT hRecip = BuildRecipient(pRecipients);
 		if (hRecip == nullptr) {
 			goto returnError;
 		}
 
 		if (!COSE_Enveloped_AddRecipient(hEncObj, hRecip, nullptr)) {
-			COSE_Recipient_Free(hRecip);
 			goto returnError;
 		}
 
-		COSE_Recipient_Free(hRecip);
+		
 	}
 
 #if INCLUDE_COUNTERSIGNATURE
-	// On the Evneloped body
-	cn_cbor *countersigns1 = cn_cbor_mapget_string(pEnveloped, "countersign");
-	if (countersigns1 != nullptr) {
-		countersigns1 = cn_cbor_mapget_string(countersigns1, "signers");
-		cn_cbor *countersign = countersigns1->first_child;
+	{
+		// On the Enveloped body
+		cn_cbor *countersigns1 =
+			cn_cbor_mapget_string(pEnveloped, "countersign");
+		if (countersigns1 != nullptr) {
+			countersigns1 = cn_cbor_mapget_string(countersigns1, "signers");
+			cn_cbor *countersign = countersigns1->first_child;
 
-		for (; countersign != nullptr; countersign = countersign->next) {
-			cn_cbor *pkeyCountersign =
-				BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
-			if (pkeyCountersign == nullptr) {
-				goto returnError;
+			for (; countersign != nullptr; countersign = countersign->next) {
+				Safe_HCOSE_KEY hkeyCountersign =
+					BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					goto returnError;
+				}
+
+				Safe_HCOSE_COUNTERSIGN hCountersign =
+					COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+
+				if (!SetSendingAttributes(hCountersign, countersign,
+						Attributes_Countersign_protected)) {
+					goto returnError;
+				}
+
+				if (!COSE_CounterSign_SetKey2(
+						hCountersign, hkeyCountersign, nullptr)) {
+					goto returnError;
+				}
+
+				if (!COSE_Enveloped_add_countersignature(
+						hEncObj, hCountersign, nullptr)) {
+					goto returnError;
+				}
 			}
-
-			HCOSE_COUNTERSIGN hCountersign =
-				COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
-			if (hCountersign == nullptr) {
-				goto returnError;
-			}
-
-			if (!SetSendingAttributes((HCOSE)hCountersign, countersign,
-					Attributes_Countersign_protected)) {
-				COSE_CounterSign_Free(hCountersign);
-				goto returnError;
-			}
-
-			if (!COSE_CounterSign_SetKey(hCountersign, pkeyCountersign, nullptr)) {
-				COSE_CounterSign_Free(hCountersign);
-				goto returnError;
-			}
-
-			if (!COSE_Enveloped_add_countersignature(
-					hEncObj, hCountersign, nullptr)) {
-				COSE_CounterSign_Free(hCountersign);
-				goto returnError;
-			}
-
-			COSE_CounterSign_Free(hCountersign);
 		}
 	}
+#endif
 
+#if INCLUDE_COUNTERSIGNATURE1
+	{
+		// On the Enveloped body
+		cn_cbor *countersigns2 =
+			cn_cbor_mapget_string(pEnveloped, "countersign0");
+		if (countersigns2 != nullptr) {
+			countersigns2 = cn_cbor_mapget_string(countersigns2, "signers");
+			cn_cbor *countersign = countersigns2->first_child;
+
+			for (; countersign != nullptr; countersign = countersign->next) {
+				Safe_HCOSE_KEY hkeyCountersign =
+					BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					goto returnError;
+				}
+
+				Safe_HCOSE_COUNTERSIGN1 hCountersign1 =
+					COSE_CounterSign1_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+				if (hCountersign1.IsNull()) {
+					goto returnError;
+				}
+
+				if (!SetSendingAttributes(hCountersign1, countersign,
+						Attributes_Countersign1_protected)) {
+					goto returnError;
+				}
+
+				if (!COSE_CounterSign1_SetKey(
+						hCountersign1, hkeyCountersign, nullptr)) {
+					goto returnError;
+				}
+
+				if (!COSE_Enveloped_add_countersignature1(
+						hEncObj, hCountersign1, nullptr)) {
+					goto returnError;
+				}
+			}
+		}
+	}
 #endif
 
 	if (!COSE_Enveloped_encrypt(hEncObj, nullptr)) {
 		goto returnError;
 	}
 
-	size_t cb = COSE_Encode((HCOSE)hEncObj, nullptr, 0, 0) + 1;
-	std::shared_ptr<byte> rgb = make_managed_array<byte>(cb);
-	cb = COSE_Encode((HCOSE)hEncObj, rgb.get(), 0, cb);
+	size_t cb = COSE_Encode(hEncObj.ToCOSE(), nullptr, 0, 0) + 1;
+	std::unique_ptr<byte> rgb(new byte[cb]);
+	cb = COSE_Encode(hEncObj.ToCOSE(), rgb.get(), 0, cb);
 
-	COSE_Enveloped_Free(hEncObj);
+	hEncObj = nullptr;
 
 	int f = _ValidateEnveloped(pControl, rgb.get(), cb);
-	return f;
+	if (f == 0) {
+		CFails += 1;
+	}
+	return f == 2;
 }
 
 int EncryptMessage()
 {
-	HCOSE_ENVELOPED hEncObj = COSE_Enveloped_Init(
+	Safe_HCOSE_ENVELOPED hEncObj = COSE_Enveloped_Init(
 		COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	byte rgbSecret[128 / 8] = {'a', 'b', 'c'};
 	int cbSecret = 128 / 8;
@@ -630,18 +789,10 @@
 		'm', 'n', 'o', 'p'};
 	int cbKid = 6;
 	size_t cb;
-	byte *rgb;
 	const char *sz = "This is the content to be used";
-	HCOSE_RECIPIENT hRecip = nullptr;
 
 	if (hEncObj == nullptr) {
 	errorReturn:
-		if (hEncObj != nullptr) {
-			COSE_Enveloped_Free(hEncObj);
-		}
-		if (hRecip != nullptr) {
-			COSE_Recipient_Free(hRecip);
-		}
 		CFails++;
 		return 0;
 	}
@@ -651,7 +802,8 @@
 			COSE_PROTECT_ONLY, nullptr)) {
 		goto errorReturn;
 	}
-	if (!COSE_Enveloped_SetContent(hEncObj, (byte *)sz, strlen(sz), nullptr)) {
+	if (!COSE_Enveloped_SetContent(
+			hEncObj, (const byte *)sz, strlen(sz), nullptr)) {
 		goto errorReturn;
 	}
 	if (!COSE_Enveloped_map_put_int(hEncObj, COSE_Header_IV,
@@ -660,7 +812,7 @@
 		goto errorReturn;
 	}
 
-	hRecip = COSE_Recipient_from_shared_secret(
+	Safe_HCOSE_RECIPIENT hRecip = COSE_Recipient_from_shared_secret(
 		rgbSecret, cbSecret, rgbKid, cbKid, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	if (hRecip == nullptr) {
 		goto errorReturn;
@@ -673,44 +825,23 @@
 		goto errorReturn;
 	}
 
-	cb = COSE_Encode((HCOSE)hEncObj, nullptr, 0, 0);
+	cb = COSE_Encode(hEncObj.ToCOSE(), nullptr, 0, 0);
 	if (cb < 1) {
 		goto errorReturn;
 	}
-	rgb = (byte *)malloc(cb);
-	if (rgb == nullptr) {
-		goto errorReturn;
-	}
-	cb = COSE_Encode((HCOSE)hEncObj, rgb, 0, cb);
+	std::unique_ptr<byte> rgb(new byte[cb]);
+	cb = COSE_Encode(hEncObj.ToCOSE(), rgb.get(), 0, cb);
 	if (cb < 1) {
 		goto errorReturn;
 	}
 
-	COSE_Recipient_Free(hRecip);
 	hRecip = nullptr;
-
-	FILE *fp = fopen("test.cbor", "wb");
-	fwrite(rgb, cb, 1, fp);
-	fclose(fp);
-
-#if 0
-	char * szX;
-	int cbPrint = 0;
-	cn_cbor * cbor = COSE_get_cbor((HCOSE) hEncObj);
-	cbPrint = cn_cbor_printer_write(nullptr, 0, cbor, "  ", "\r\n");
-	szX = malloc(cbPrint);
-	cn_cbor_printer_write(szX, cbPrint, cbor, "  ", "\r\n");
-	fprintf(stdout, "%s", szX);
-	fprintf(stdout, "\r\n");
-#endif
-
-	COSE_Enveloped_Free(hEncObj);
 	hEncObj = nullptr;
 
 	/* */
 
 	int typ;
-	hEncObj = (HCOSE_ENVELOPED)COSE_Decode(rgb, (int)cb, &typ,
+	hEncObj = (HCOSE_ENVELOPED)COSE_Decode(rgb.get(), (int)cb, &typ,
 		COSE_enveloped_object, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	if (hEncObj == nullptr) {
 		goto errorReturn;
@@ -732,14 +863,12 @@
 			goto errorReturn;
 		}
 
-		COSE_Recipient_Free(hRecip);
 		hRecip = nullptr;
 
 		iRecipient += 1;
 
 	} while (true);
 
-	COSE_Enveloped_Free(hEncObj);
 	return 1;
 }
 #endif
@@ -747,6 +876,7 @@
 /********************************************/
 #if INCLUDE_ENCRYPT0
 
+//  Return 1=expected failure, 0 = failure, 2 = success
 int _ValidateEncrypt(const cn_cbor *pControl,
 	const byte *pbEncoded,
 	size_t cbEncoded,
@@ -756,46 +886,14 @@
 	const cn_cbor *pFail = nullptr;
 	const cn_cbor *pEncrypt = nullptr;
 	const cn_cbor *pRecipients = nullptr;
-	cn_cbor *pkey = nullptr;	
-	HCOSE_ENCRYPT hEnc = nullptr;
 	int type;
 	bool fFail = false;
 	bool fFailBody = false;
 	bool fAlgSupport = true;
+	int returnValue = 2;
 
 	if (false) {
-	exitHere:
-		if (hEnc != nullptr) {
-			COSE_Encrypt_Free(hEnc);
-		}
-		if (pkey != nullptr) {
-			CN_CBOR_FREE(pkey, context);
-		}
-
-		if (fAlgSupport) {
-			if (fFailBody) {
-				if (!fFail) {
-					fFail = true;
-				}
-				else {
-					fFail = false;
-				}
-			}
-		}
-		else {
-			fFail = false;
-		}
-
-		if (fFail) {
-			CFails += 1;
-		}
-		return fAlgSupport ? 1 : 0;
-
 	returnError:
-		if (hEnc != nullptr) {
-			COSE_Encrypt_Free(hEnc);
-		}
-
 		CFails += 1;
 		return 0;
 	}
@@ -806,30 +904,30 @@
 	}
 
 	if ((pInput == nullptr) || (pInput->type != CN_CBOR_MAP)) {
-		goto returnError;
+		return 0;
 	}
 	pEncrypt = cn_cbor_mapget_string(pInput, "encrypted");
 	if ((pEncrypt == nullptr) || (pEncrypt->type != CN_CBOR_MAP)) {
-		goto returnError;
+		return 0;
 	}
 
 	pRecipients = cn_cbor_mapget_string(pEncrypt, "recipients");
 	if ((pRecipients == nullptr) || (pRecipients->type != CN_CBOR_ARRAY)) {
-		goto returnError;
+		return 0;
 	}
 
 	pRecipients = pRecipients->first_child;
 
+	Safe_HCOSE_ENCRYPT hEnc;
+
 	if (pcnEncoded == nullptr) {
 		hEnc = (HCOSE_ENCRYPT)COSE_Decode(pbEncoded, cbEncoded, &type,
 			COSE_encrypt_object, CBOR_CONTEXT_PARAM_COMMA nullptr);
 		if (hEnc == nullptr) {
 			if (fFailBody) {
-				return 0;
+				return 1;
 			}
-			else {
-				goto returnError;
-			}
+			return 0;
 		}
 	}
 	else {
@@ -837,148 +935,191 @@
 			pcnEncoded, CBOR_CONTEXT_PARAM_COMMA nullptr);
 		if (hEnc == nullptr) {
 			if (fFailBody) {
-				return 0;
+				return 1;
 			}
-			else {
-				goto returnError;
-			}
+			return 0;
 		}
 	}
 
-	if (!SetReceivingAttributes(
-			(HCOSE)hEnc, pEncrypt, Attributes_Encrypt_protected)) {
-		goto returnError;
+	if (!SetReceivingAttributes(hEnc, pEncrypt, Attributes_Encrypt_protected)) {
+		return 0;
 	}
 
-	pkey = BuildKey(cn_cbor_mapget_string(pRecipients, "key"), true);
+	Safe_CN_CBOR pkey =
+		BuildCborKey(cn_cbor_mapget_string(pRecipients, "key"), true);
 	if (pkey == nullptr) {
-		goto returnError;
+		return 0;
 	}
 
 	cn_cbor *k = cn_cbor_mapget_int(pkey, -1);
 	if (k == nullptr) {
-		fFail = true;
-		goto exitHere;
-	}
-
-	cn_cbor *alg =
-		COSE_Encrypt_map_get_int(hEnc, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-	if (!IsAlgorithmSupported(alg)) {
-		fAlgSupport = false;
-		fFail = false;
-		goto exitHere;
+		return 0;
 	}
 
 	pFail = cn_cbor_mapget_string(pRecipients, "fail");
-	if (COSE_Encrypt_decrypt(hEnc, k->v.bytes, k->length, nullptr)) {
-		if (!fAlgSupport) {
-			fFail = true;
-			fAlgSupport = false;
-		}
-		else if ((pFail != nullptr) && (pFail->type != CN_CBOR_TRUE)) {
-			fFail = true;
+	cose_errback coseError;
+	if (COSE_Encrypt_decrypt(hEnc, k->v.bytes, k->length, &coseError)) {
+		if ((pFail != nullptr) && (pFail->type != CN_CBOR_TRUE)) {
+			returnValue = 0;
 		}
 
 		size_t cb;
-		const byte *pb;
-		pb = COSE_Encrypt_GetContent(hEnc, &cb, nullptr);
+		const byte *pb = COSE_Encrypt_GetContent(hEnc, &cb, nullptr);
+		// M00TODO - compare content?
 	}
 	else {
-		if (fAlgSupport) {
-			fFail = true;
-			fAlgSupport = false;
+		if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+			returnValue = COSE_MIN(1, returnValue);
 		}
-		else if ((pFail == nullptr) || (pFail->type == CN_CBOR_FALSE)) {
-			fFail = true;
+		else if (fFailBody) {
+			returnValue = COSE_MIN(1, returnValue);
+		}
+		else if ((pFail != nullptr) && (pFail->type == CN_CBOR_FALSE)) {
+			returnValue = COSE_MIN(1, returnValue);
+		}
+		else {
+			returnValue = 0;
 		}
 	}
 
 #if INCLUDE_COUNTERSIGNATURE
-	//  Countersign on Encrypt0 Body
+	{
+		//  Countersign on Encrypt0 Body
 
-	//  Validate counter signatures on signers
-	cn_cbor *countersignList = cn_cbor_mapget_string(pEncrypt, "countersign");
-	if (countersignList != nullptr) {
-		cn_cbor *countersigners =
-			cn_cbor_mapget_string(countersignList, "signers");
-		if (countersigners == nullptr) {
-			fFail = true;
-			goto exitHere;
+		//  Validate counter signatures on signers
+		cn_cbor *countersignList =
+			cn_cbor_mapget_string(pEncrypt, "countersign");
+		if (countersignList != nullptr) {
+			cn_cbor *countersigners =
+				cn_cbor_mapget_string(countersignList, "signers");
+			if (countersigners == nullptr) {
+				return 0;
+			}
+			const int count = (int)countersigners->length;
+			bool forward = true;
+
+			if (COSE_Encrypt_map_get_int(hEnc, COSE_Header_CounterSign,
+					COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+				goto returnError;
+			}
+
+			for (int counterNo = 0; counterNo < count; counterNo++) {
+				bool noSupportSign = false;
+				bool failThis = false;
+
+				Safe_HCOSE_COUNTERSIGN h = COSE_Encrypt0_get_countersignature(
+					hEnc, counterNo, nullptr);
+				if (h == nullptr) {
+					fFail = true;
+					continue;
+				}
+
+				cn_cbor *counterSigner = cn_cbor_index(countersigners,
+					forward ? counterNo : count - counterNo - 1);
+
+				Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+					cn_cbor_mapget_string(counterSigner, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					returnValue = 0;
+					continue;
+				}
+
+				if (!COSE_CounterSign_SetKey2(h, hkeyCountersign, nullptr)) {
+					fFail = true;
+					continue;
+				}
+
+				if (COSE_Encrypt0_CounterSign_validate(hEnc, h, &coseError)) {
+					//  I don't think we have any forced errors yet.
+				}
+				else {
+					if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+						returnValue = COSE_MIN(1, returnValue);
+					}
+					else if (forward && counterNo == 0 && count > 1) {
+						forward = false;
+						counterNo -= 1;
+					}
+					else {
+						returnValue = 0;
+					}
+				}
+			}
 		}
-		int count = countersigners->length;
-		bool forward = true;
+	}
+#endif
+#if INCLUDE_COUNTERSIGNATURE1
+	{
+		//  Countersign1 on Enveloped Body
 
-		if (COSE_Encrypt_map_get_int(hEnc, COSE_Header_CounterSign,
-				COSE_UNPROTECT_ONLY, 0) == nullptr) {
-			goto returnError;
-		}
+		//  Validate counter signatures on signers
+		const cn_cbor *countersignList =
+			cn_cbor_mapget_string(pEncrypt, "countersign0");
+		if (countersignList != nullptr) {
+			cn_cbor *countersigners =
+				cn_cbor_mapget_string(countersignList, "signers");
+			if (countersigners == nullptr) {
+				return 0;
+			}
 
-		for (int counterNo = 0; counterNo < count; counterNo++) {
+			if (COSE_Encrypt_map_get_int(hEnc, COSE_Header_CounterSign1,
+					COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+				return 0;
+			}
+
 			bool noSupportSign = false;
-			bool failThis = false;
-
-			HCOSE_COUNTERSIGN h =
-				COSE_Encrypt0_get_countersignature(hEnc, counterNo, 0);
-			if (h == nullptr) {
-				fFail = true;
-				continue;
+			Safe_HCOSE_COUNTERSIGN1 h =
+				COSE_Encrypt0_get_countersignature1(hEnc, nullptr);
+			if (h.IsNull()) {
+				return 0;
 			}
 
-			cn_cbor *counterSigner = cn_cbor_index(
-				countersigners, forward ? counterNo : count - counterNo - 1);
+			cn_cbor *counterSigner = cn_cbor_index(countersigners, 0);
 
-			cn_cbor *pkeyCountersign =
-				BuildKey(cn_cbor_mapget_string(counterSigner, "key"), false);
-			if (pkeyCountersign == nullptr) {
-				fFail = true;
-				COSE_CounterSign_Free(h);
-				continue;
+			Safe_HCOSE_KEY hkeyCountersign(
+				BuildKey(cn_cbor_mapget_string(counterSigner, "key"), false));
+			if (hkeyCountersign == nullptr) {
+				return 0;
 			}
 
-			if (!COSE_CounterSign_SetKey(h, pkeyCountersign, 0)) {
-				fFail = true;
-				COSE_CounterSign_Free(h);
-				CN_CBOR_FREE(pkeyCountersign, context);
-				continue;
+			if (!COSE_CounterSign1_SetKey(h, hkeyCountersign, nullptr)) {
+				return false;
 			}
 
-			alg = COSE_CounterSign_map_get_int(
-				h, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-			if (!IsAlgorithmSupported(alg)) {
-				noSupportSign = true;
-				fAlgSupport = false;
+			if (!SetReceivingAttributes(
+					h, counterSigner, Attributes_Countersign1_protected)) {
+				return false;
 			}
 
-			if (COSE_Encrypt0_CounterSign_validate(hEnc, h, 0)) {
+			if (COSE_Encrypt0_CounterSign1_validate(hEnc, h, &coseError)) {
 				//  I don't think we have any forced errors yet.
 			}
 			else {
-				if (forward && counterNo == 0 && count > 1) {
-					forward = false;
-					counterNo -= 1;
+				if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+					returnValue = COSE_MIN(1, returnValue);
 				}
 				else {
-					fFail = true;
+					returnValue = 0;
 				}
 			}
-
-			COSE_CounterSign_Free(h);
 		}
 	}
 #endif
 
-	goto exitHere;
+	return returnValue;
 }
 
-int ValidateEncrypt(const cn_cbor *pControl)
+bool ValidateEncrypt(const cn_cbor *pControl)
 {
 	int cbEncoded;
 	byte *pbEncoded = GetCBOREncoding(pControl, &cbEncoded);
-	int fRet;
 
-	fRet = _ValidateEncrypt(pControl, pbEncoded, cbEncoded, nullptr);
-	if (!fRet) {
-		return fRet;
+	int fRet = _ValidateEncrypt(pControl, pbEncoded, cbEncoded, nullptr);
+	if (fRet == 0) {
+		CFails += 1;
+	}
+	if (fRet != 2) {
+		return false;
 	}
 
 	cn_cbor *cbor =
@@ -987,38 +1128,34 @@
 		return false;
 	}
 
-	return _ValidateEncrypt(pControl, nullptr, 0, cbor);
+	fRet = _ValidateEncrypt(pControl, nullptr, 0, cbor);
+	if (fRet == 0) {
+		CFails += 1;
+	}
+	return fRet == 2;
 }
 
-int BuildEncryptMessage(const cn_cbor *pControl)
+bool BuildEncryptMessage(const cn_cbor *pControl)
 {
-	cn_cbor *pkey = nullptr;
 	//
 	//  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 != nullptr) && (pFail->type == CN_CBOR_TRUE)) {
-		return 0;
+		return false;
 	}
 
-	HCOSE_ENCRYPT hEncObj =
-		COSE_Encrypt_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	Safe_HCOSE_ENCRYPT hEncObj = COSE_Encrypt_Init(
+		COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
 	const cn_cbor *pInputs = cn_cbor_mapget_string(pControl, "input");
 	if (pInputs == nullptr) {
 	returnError:
-		if (hEncObj != nullptr) {
-			COSE_Encrypt_Free(hEncObj);
-		}
-
-		if (pkey != nullptr) {
-			CN_CBOR_FREE(pkey, context);
-		}
-
 		CFails += 1;
-		return 1;
+		return false;
 	}
+
 	const cn_cbor *pEncrypt = cn_cbor_mapget_string(pInputs, "encrypted");
 	if (pEncrypt == nullptr) {
 		goto returnError;
@@ -1031,12 +1168,7 @@
 	}
 
 	if (!SetSendingAttributes(
-			(HCOSE)hEncObj, pEncrypt, Attributes_Encrypt_protected)) {
-		goto returnError;
-	}
-
-	const cn_cbor *pAlg = COSE_Encrypt_map_get_int(hEncObj, 1, COSE_BOTH, nullptr);
-	if (pAlg == nullptr) {
+			hEncObj, pEncrypt, Attributes_Encrypt_protected)) {
 		goto returnError;
 	}
 
@@ -1046,7 +1178,8 @@
 	}
 
 	pRecipients = pRecipients->first_child;
-	pkey = BuildKey(cn_cbor_mapget_string(pRecipients, "key"), false);
+	Safe_CN_CBOR pkey =
+		BuildCborKey(cn_cbor_mapget_string(pRecipients, "key"), false);
 	if (pkey == nullptr) {
 		goto returnError;
 	}
@@ -1054,66 +1187,98 @@
 	cn_cbor *k = cn_cbor_mapget_int(pkey, -1);
 
 #if INCLUDE_COUNTERSIGNATURE
-	// On the Encrypt0 body
-	cn_cbor *countersigns = cn_cbor_mapget_string(pEncrypt, "countersign");
-	if (countersigns != nullptr) {
-		countersigns = cn_cbor_mapget_string(countersigns, "signers");
-		cn_cbor *countersign = countersigns->first_child;
+	{
+		// On the Encrypt0 body
+		cn_cbor *countersigns = cn_cbor_mapget_string(pEncrypt, "countersign");
+		if (countersigns != nullptr) {
+			countersigns = cn_cbor_mapget_string(countersigns, "signers");
+			cn_cbor *countersign = countersigns->first_child;
 
-		for (; countersign != nullptr; countersign = countersign->next) {
-			cn_cbor *pkeyCountersign =
-				BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
-			if (pkeyCountersign == nullptr) {
-				goto returnError;
+			for (; countersign != nullptr; countersign = countersign->next) {
+				Safe_HCOSE_KEY hkeyCountersign =
+					BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					goto returnError;
+				}
+
+				Safe_HCOSE_COUNTERSIGN hCountersign =
+					COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+				if (hCountersign == nullptr) {
+					goto returnError;
+				}
+
+				if (!SetSendingAttributes(hCountersign, countersign,
+						Attributes_Countersign_protected)) {
+					goto returnError;
+				}
+
+				if (!COSE_CounterSign_SetKey2(
+						hCountersign, hkeyCountersign, nullptr)) {
+					goto returnError;
+				}
+
+				if (!COSE_Encrypt0_add_countersignature(
+						hEncObj, hCountersign, nullptr)) {
+					goto returnError;
+				}
 			}
-
-			HCOSE_COUNTERSIGN hCountersign =
-				COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
-			if (hCountersign == nullptr) {
-				goto returnError;
-			}
-
-			if (!SetSendingAttributes((HCOSE)hCountersign, countersign,
-					Attributes_Countersign_protected)) {
-				COSE_CounterSign_Free(hCountersign);
-				goto returnError;
-			}
-
-			if (!COSE_CounterSign_SetKey(hCountersign, pkeyCountersign, nullptr)) {
-				COSE_CounterSign_Free(hCountersign);
-				goto returnError;
-			}
-
-			if (!COSE_Encrypt0_add_countersignature(
-					hEncObj, hCountersign, nullptr)) {
-				COSE_CounterSign_Free(hCountersign);
-				goto returnError;
-			}
-
-			COSE_CounterSign_Free(hCountersign);
 		}
 	}
+#endif
 
+#if INCLUDE_COUNTERSIGNATURE1
+	{
+		// On the Encrypt0 body
+		cn_cbor *countersigns = cn_cbor_mapget_string(pEncrypt, "countersign0");
+		if (countersigns != nullptr) {
+			countersigns = cn_cbor_mapget_string(countersigns, "signers");
+			cn_cbor *countersign = countersigns->first_child;
+
+			for (; countersign != nullptr; countersign = countersign->next) {
+				Safe_HCOSE_KEY hkeyCountersign =
+					BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					goto returnError;
+				}
+
+				Safe_HCOSE_COUNTERSIGN1 hCountersign =
+					COSE_CounterSign1_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+				if (hCountersign == nullptr) {
+					goto returnError;
+				}
+
+				if (!SetSendingAttributes(hCountersign, countersign,
+						Attributes_Countersign1_protected)) {
+					goto returnError;
+				}
+
+				if (!COSE_CounterSign1_SetKey(
+						hCountersign, hkeyCountersign, nullptr)) {
+					goto returnError;
+				}
+
+				if (!COSE_Encrypt0_add_countersignature1(
+						hEncObj, hCountersign, nullptr)) {
+					goto returnError;
+				}
+			}
+		}
+	}
 #endif
 
 	if (!COSE_Encrypt_encrypt(hEncObj, k->v.bytes, k->length, nullptr)) {
 		goto returnError;
 	}
 
-	size_t cb = COSE_Encode((HCOSE)hEncObj, nullptr, 0, 0) + 1;
-	byte *rgb = (byte *)malloc(cb);
-	cb = COSE_Encode((HCOSE)hEncObj, rgb, 0, cb);
+	size_t cb = COSE_Encode(hEncObj.ToCOSE(), nullptr, 0, 0) + 1;
+	std::unique_ptr<byte> rgb(new byte[cb]);
+	cb = COSE_Encode(hEncObj.ToCOSE(), rgb.get(), 0, cb);
 
 	COSE_Encrypt_Free(hEncObj);
 
-	int f = _ValidateEncrypt(pControl, rgb, cb, nullptr);
+	int f = _ValidateEncrypt(pControl, rgb.get(), cb, nullptr);
 
-	if (pkey != nullptr) {
-		CN_CBOR_FREE(pkey, context);
-	}
-
-	free(rgb);
-	return f;
+	return f == 1;
 }
 #endif
 
@@ -1156,7 +1321,8 @@
 	//      - nullptr pointer
 	//
 
-	CHECK_FAILURE(COSE_Enveloped_SetContent(hEncryptNULL, rgb, 10, &cose_error),
+	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++);
@@ -1188,11 +1354,13 @@
 	CHECK_FAILURE(COSE_Enveloped_encrypt(hEncryptBad, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
 
-	CHECK_FAILURE(COSE_Enveloped_decrypt(hEncryptNULL, hRecipient, &cose_error),
+	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),
+	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++);
@@ -1210,7 +1378,8 @@
 		COSE_Enveloped_AddRecipient(hEncrypt, hRecipientBad, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
 
-	CHECK_FAILURE_PTR(COSE_Enveloped_GetRecipient(hEncryptNULL, 0, &cose_error),
+	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++);
@@ -1436,23 +1605,31 @@
 
 	CHECK_FAILURE(COSE_Recipient_SetKey(hRecipNULL, cn, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
+	cn = cn_cbor_int_create(1, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	CHECK_FAILURE(COSE_Recipient_SetKey(hRecipBad, cn, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
+	cn = cn_cbor_int_create(1, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	CHECK_FAILURE(COSE_Recipient_SetKey(hRecip, nullptr, &cose_error),
 		COSE_ERR_INVALID_PARAMETER, CFails++);
 
-	CHECK_FAILURE(COSE_Recipient_SetSenderKey(hRecipNULL, cn, 0, &cose_error),
+	CHECK_FAILURE(
+		COSE_Recipient_SetSenderKey(hRecipNULL, cn, 0, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
+	cn = cn_cbor_int_create(1, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	CHECK_FAILURE(COSE_Recipient_SetSenderKey(hRecipBad, cn, 0, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
+	cn = cn_cbor_int_create(1, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	CHECK_FAILURE(COSE_Recipient_SetSenderKey(hRecip, nullptr, 0, &cose_error),
 		COSE_ERR_INVALID_PARAMETER, CFails++);
 	CHECK_FAILURE(COSE_Recipient_SetSenderKey(hRecip, cn, 3, &cose_error),
 		COSE_ERR_INVALID_PARAMETER, CFails++);
+	cn = cn_cbor_int_create(1, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	CHECK_RETURN(COSE_Recipient_SetSenderKey(hRecip, cn, 0, &cose_error),
 		COSE_ERR_NONE, CFails++);
+	cn = cn_cbor_int_create(1, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
-	CHECK_FAILURE(COSE_Recipient_SetExternal(hRecipNULL, rgb, 10, &cose_error),
+	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++);
@@ -1469,9 +1646,11 @@
 	CHECK_FAILURE(COSE_Recipient_map_put_int(
 					  hRecipNULL, 1, cn, COSE_PROTECT_ONLY, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
+	cn = cn_cbor_int_create(1, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	CHECK_FAILURE(COSE_Recipient_map_put_int(
 					  hRecipBad, 1, cn, COSE_PROTECT_ONLY, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
+	cn = cn_cbor_int_create(1, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	CHECK_FAILURE(COSE_Recipient_map_put_int(
 					  hRecip, 1, nullptr, COSE_PROTECT_ONLY, &cose_error),
 		COSE_ERR_INVALID_PARAMETER, CFails++);
@@ -1479,11 +1658,13 @@
 					  COSE_PROTECT_ONLY | COSE_UNPROTECT_ONLY, &cose_error),
 		COSE_ERR_INVALID_PARAMETER, CFails++);
 
-	CHECK_FAILURE(COSE_Recipient_AddRecipient(hRecipNULL, hRecip, &cose_error),
+	CHECK_FAILURE(
+		COSE_Recipient_AddRecipient(hRecipNULL, hRecip, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
 	CHECK_FAILURE(COSE_Recipient_AddRecipient(hRecipBad, hRecip, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
-	CHECK_FAILURE(COSE_Recipient_AddRecipient(hRecip, hRecipNULL, &cose_error),
+	CHECK_FAILURE(
+		COSE_Recipient_AddRecipient(hRecip, hRecipNULL, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
 	CHECK_FAILURE(COSE_Recipient_AddRecipient(hRecip, hRecipBad, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
diff --git a/test/Mac_test.cpp b/test/Mac_test.cpp
index d3968a5..6707a37 100644
--- a/test/Mac_test.cpp
+++ b/test/Mac_test.cpp
@@ -1,5 +1,6 @@
 #define _CRT_SECURE_NO_WARNINGS
 
+#include <memory>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -17,6 +18,7 @@
 #endif
 
 #if INCLUDE_MAC
+// returns 0=fail;  1= expected fail; 2=success
 int _ValidateMAC(const cn_cbor *pControl,
 	const byte *pbEncoded,
 	size_t cbEncoded)
@@ -25,13 +27,13 @@
 	const cn_cbor *pFail;
 	const cn_cbor *pMac;
 	const cn_cbor *pRecipients;
-	HCOSE_MAC hMAC;
+	Safe_HCOSE_MAC hMAC;
 	int type;
 	int iRecipient;
 	bool fFail = false;
 	bool fFailBody = false;
 	bool fAlgNoSupport = false;
-	int returnCode = 1;
+	int returnCode = 2;
 	cose_errback error;
 
 	pFail = cn_cbor_mapget_string(pControl, "fail");
@@ -43,7 +45,7 @@
 		CBOR_CONTEXT_PARAM_COMMA nullptr);
 	if (hMAC == nullptr) {
 		if (fFailBody) {
-			return 0;
+			return 2;
 		}
 
 	failTest:
@@ -52,275 +54,360 @@
 	}
 
 	if ((pInput == nullptr) || (pInput->type != CN_CBOR_MAP)) {
-		goto failTest;
+		return 0;
 	}
 	pMac = cn_cbor_mapget_string(pInput, "mac");
 	if ((pMac == nullptr) || (pMac->type != CN_CBOR_MAP)) {
-		goto failTest;
+		return 0;
 	}
 
-	if (!SetReceivingAttributes((HCOSE)hMAC, pMac, Attributes_MAC_protected)) {
-		goto failTest;
+	if (!SetReceivingAttributes(hMAC, pMac, Attributes_MAC_protected)) {
+		return 0;
 	}
 
 	pRecipients = cn_cbor_mapget_string(pMac, "recipients");
 	if ((pRecipients == nullptr) || (pRecipients->type != CN_CBOR_ARRAY)) {
-		goto failTest;
+		return 0;
 	}
 
 	iRecipient = (int)pRecipients->length - 1;
 	pRecipients = pRecipients->first_child;
-	for (; pRecipients != nullptr; iRecipient--, pRecipients = pRecipients->next) {
+	for (; pRecipients != nullptr;
+		 iRecipient--, pRecipients = pRecipients->next) {
 		fAlgNoSupport = false;
-		cn_cbor *pkey =
+		Safe_HCOSE_KEY hkey =
 			BuildKey(cn_cbor_mapget_string(pRecipients, "key"), false);
-		if (pkey == nullptr) {
-			fFail = true;
+		if (hkey == nullptr) {
+			returnCode = 0;
 			continue;
 		}
 
-		HCOSE_RECIPIENT hRecip = COSE_Mac_GetRecipient(hMAC, iRecipient, nullptr);
+		Safe_HCOSE_RECIPIENT hRecip =
+			COSE_Mac_GetRecipient(hMAC, iRecipient, nullptr);
 		if (hRecip == nullptr) {
-			fFail = true;
+			returnCode = 0;
 			continue;
 		}
 
 		if (!SetReceivingAttributes(
-				(HCOSE)hRecip, pRecipients, Attributes_Recipient_protected)) {
-			COSE_Recipient_Free(hRecip);
+				hRecip, pRecipients, Attributes_Recipient_protected)) {
 			goto failTest;
 		}
 
-		if (!COSE_Recipient_SetKey(hRecip, pkey, nullptr)) {
-			fFail = true;
-			COSE_Recipient_Free(hRecip);
+		if (!COSE_Recipient_SetKey2(hRecip, hkey, nullptr)) {
+			returnCode = 0;
 			continue;
 		}
 
 		cn_cbor *cnStatic = cn_cbor_mapget_string(pRecipients, "sender_key");
 		if (cnStatic != nullptr) {
-			if (COSE_Recipient_map_get_int(
-					hRecip, COSE_Header_ECDH_SPK, COSE_BOTH, nullptr) == 0) {
-				COSE_Recipient_map_put_int(hRecip, COSE_Header_ECDH_SPK,
-					BuildKey(cnStatic, true), COSE_DONT_SEND, nullptr);
+			if (COSE_Recipient_map_get_int(hRecip, COSE_Header_ECDH_SPK,
+					COSE_BOTH, nullptr) == nullptr) {
+				Safe_HCOSE_KEY senderKey = BuildKey(cnStatic, true);
+				if (senderKey == nullptr) {
+					return 0;
+				}
+				if (!COSE_Recipient_SetSenderKey2(
+						hRecip, senderKey, COSE_DONT_SEND, nullptr)) {
+					return 0;
+				}
 			}
 		}
 
 		pFail = cn_cbor_mapget_string(pRecipients, "fail");
 
-		cn_cbor *alg =
-			COSE_Mac_map_get_int(hMAC, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-		if (!IsAlgorithmSupported(alg)) {
-			fAlgNoSupport = true;
-		}
-
-		alg = COSE_Recipient_map_get_int(
-			hRecip, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-		if (!IsAlgorithmSupported(alg)) {
-			fAlgNoSupport = true;
-		}
-
 		if (COSE_Mac_validate(hMAC, hRecip, &error)) {
-			if (fAlgNoSupport) {
-				fFail = true;
-			}
-			else if ((pFail != nullptr) && (pFail->type != CN_CBOR_TRUE)) {
-				fFail = true;
+			if ((pFail != nullptr) && (pFail->type != CN_CBOR_TRUE)) {
+				returnCode = 0;
 			}
 		}
 		else {
 			if (error.err == COSE_ERR_NO_COMPRESSED_POINTS ||
 				error.err == COSE_ERR_UNKNOWN_ALGORITHM) {
-				fAlgNoSupport = true;
-				returnCode = 0;
+				returnCode = COSE_MIN(1, returnCode);
 			}
-			else if (fAlgNoSupport) {
-				returnCode = 0;
+			else if (fFailBody) {
+				returnCode = COSE_MIN(1, returnCode);
 			}
 			else if ((pFail == nullptr) || (pFail->type == CN_CBOR_FALSE)) {
-				fFail = true;
+				returnCode = 0;
+			}
+			else {
+				returnCode = COSE_MIN(1, returnCode);
 			}
 		}
 
 #if INCLUDE_COUNTERSIGNATURE
-		//  Countersign on Encrypt0 Body
+		{
+			//  Countersign on Encrypt0 Body
+
+			//  Validate counter signatures on signers
+			cn_cbor *countersignList =
+				cn_cbor_mapget_string(pRecipients, "countersign");
+			if (countersignList != nullptr) {
+				cn_cbor *countersigners =
+					cn_cbor_mapget_string(countersignList, "signers");
+				if (countersigners == nullptr) {
+					return 0;
+				}
+				int count = static_cast<int>(countersigners->length);
+				bool forward = true;
+
+				if (COSE_Recipient_map_get_int(hRecip, COSE_Header_CounterSign,
+						COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+					return 0;
+				}
+
+				for (int counterNo = 0; counterNo < count; counterNo++) {
+					bool noSignSupport = false;
+					Safe_HCOSE_COUNTERSIGN h =
+						COSE_Recipient_get_countersignature(
+							hRecip, counterNo, nullptr);
+					if (h == nullptr) {
+						returnCode = 0;
+						continue;
+					}
+
+					cn_cbor *counterSigner = cn_cbor_index(countersigners,
+						forward ? counterNo : count - counterNo - 1);
+
+					Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+						cn_cbor_mapget_string(counterSigner, "key"), false);
+					if (hkeyCountersign == nullptr) {
+						returnCode = 0;
+						continue;
+					}
+
+					if (!COSE_CounterSign_SetKey2(
+							h, hkeyCountersign, nullptr)) {
+						returnCode = 0;
+						continue;
+					}
+
+					cose_errback coseError;
+					if (COSE_Recipient_CounterSign_validate(
+							hRecip, h, &coseError)) {
+						//  I don't think we have any forced errors yet.
+					}
+					else {
+						if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+							returnCode = COSE_MIN(returnCode, 1);
+							continue;
+						}
+						if (forward && counterNo == 0 && count > 1) {
+							forward = false;
+							counterNo -= 1;
+							continue;
+						}
+						returnCode = 0;
+					}
+				}
+			}
+		}
+#endif
+
+#if INCLUDE_COUNTERSIGNATURE1
+		{
+			//  Countersign1 on Recipient Body
+
+			//  Validate counter signatures on signers
+			const cn_cbor *countersignList =
+				cn_cbor_mapget_string(pRecipients, "countersign0");
+			if (countersignList != nullptr) {
+				cn_cbor *countersigners =
+					cn_cbor_mapget_string(countersignList, "signers");
+				if (countersigners == nullptr) {
+					return 0;
+				}
+
+				if (COSE_Recipient_map_get_int(hRecip, COSE_Header_CounterSign1,
+						COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+					return 0;
+				}
+
+				bool noSupportSign = false;
+
+				Safe_HCOSE_COUNTERSIGN1 h(
+					COSE_Recipient_get_countersignature1(hRecip, nullptr));
+				if (h.IsNull()) {
+					return 0;
+				}
+
+				cn_cbor *counterSigner = cn_cbor_index(countersigners, 0);
+
+				Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+					cn_cbor_mapget_string(counterSigner, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					return 0;
+				}
+
+				if (!COSE_CounterSign1_SetKey(h, hkeyCountersign, nullptr)) {
+					return 0;
+				}
+
+				cose_errback coseError;
+				if (COSE_Recipient_CounterSign1_validate(
+						hRecip, h, &coseError)) {
+					//  I don't think we have any forced errors yet.
+				}
+				else {
+					if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+						returnCode = COSE_MIN(1, returnCode);
+					}
+					else {
+						returnCode = 0;
+					}
+				}
+			}
+		}
+#endif
+	}
+
+#if INCLUDE_COUNTERSIGNATURE
+	{
+		//  Countersign on Signed Body
 
 		//  Validate counter signatures on signers
-		cn_cbor *countersignList =
-			cn_cbor_mapget_string(pRecipients, "countersign");
+		cn_cbor *countersignList = cn_cbor_mapget_string(pMac, "countersign");
 		if (countersignList != nullptr) {
 			cn_cbor *countersigners =
 				cn_cbor_mapget_string(countersignList, "signers");
 			if (countersigners == nullptr) {
-				COSE_Recipient_Free(hRecip);
-				goto failTest;
+				return 0;
 			}
-			int count = countersigners->length;
+			int count = static_cast<int>(countersigners->length);
 			bool forward = true;
 
-			if (COSE_Recipient_map_get_int(hRecip, COSE_Header_CounterSign,
-					COSE_UNPROTECT_ONLY, 0) == nullptr) {
-				COSE_Recipient_Free(hRecip);
-				goto failTest;
+			if (COSE_Mac_map_get_int(hMAC, COSE_Header_CounterSign,
+					COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+				return 0;
 			}
 
 			for (int counterNo = 0; counterNo < count; counterNo++) {
 				bool noSignSupport = false;
-				HCOSE_COUNTERSIGN h =
-					COSE_Recipient_get_countersignature(hRecip, counterNo, 0);
-				if (h == nullptr) {
-					continue;
-				}
 
-				alg = COSE_CounterSign_map_get_int(
-					h, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-				if (!IsAlgorithmSupported(alg)) {
-					fAlgNoSupport = true;
-					noSignSupport = true;
+				Safe_HCOSE_COUNTERSIGN h =
+					COSE_Mac_get_countersignature(hMAC, counterNo, nullptr);
+				if (h == nullptr) {
 					returnCode = 0;
+					continue;
 				}
 
 				cn_cbor *counterSigner = cn_cbor_index(countersigners,
 					forward ? counterNo : count - counterNo - 1);
 
-				cn_cbor *pkeyCountersign = BuildKey(
+				Safe_HCOSE_KEY hkeyCountersign = BuildKey(
 					cn_cbor_mapget_string(counterSigner, "key"), false);
-				if (pkeyCountersign == nullptr) {
-					fFail = true;
-					COSE_CounterSign_Free(h);
+				if (hkeyCountersign == nullptr) {
+					returnCode = 0;
 					continue;
 				}
 
-				if (!COSE_CounterSign_SetKey(h, pkeyCountersign, 0)) {
-					fFail = true;
-					CN_CBOR_FREE(pkeyCountersign, context);
-					COSE_CounterSign_Free(h);
+				if (!COSE_CounterSign_SetKey2(h, hkeyCountersign, nullptr)) {
+					returnCode = 0;
 					continue;
 				}
 
-				if (COSE_Recipient_CounterSign_validate(hRecip, h, 0)) {
+				cose_errback coseError;
+				if (COSE_Mac_CounterSign_validate(hMAC, h, &coseError)) {
 					//  I don't think we have any forced errors yet.
 				}
 				else {
+					if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+						returnCode = COSE_MIN(1, returnCode);
+						continue;
+					}
 					if (forward && counterNo == 0 && count > 1) {
 						forward = false;
 						counterNo -= 1;
+						continue;
 					}
-					else {
-						fFail |= !noSignSupport;
-					}
-				}
 
-				COSE_CounterSign_Free(h);
+					returnCode = 0;
+				}
 			}
 		}
+	}
 #endif
 
-		COSE_Recipient_Free(hRecip);
-	}
+#if INCLUDE_COUNTERSIGNATURE1
+	{
+		//  Countersign1 on Enveloped Body
 
-#if INCLUDE_COUNTERSIGNATURE
-	//  Countersign on Signed Body
-
-	//  Validate counter signatures on signers
-	cn_cbor *countersignList = cn_cbor_mapget_string(pMac, "countersign");
-	if (countersignList != nullptr) {
-		cn_cbor *countersigners =
-			cn_cbor_mapget_string(countersignList, "signers");
-		if (countersigners == nullptr) {
-			goto failTest;
-		}
-		int count = countersigners->length;
-		bool forward = true;
-
-		if (COSE_Mac_map_get_int(hMAC, COSE_Header_CounterSign,
-				COSE_UNPROTECT_ONLY, 0) == nullptr) {
-			goto failTest;
-		}
-
-		for (int counterNo = 0; counterNo < count; counterNo++) {
-			bool noSignSupport = false;
-
-			HCOSE_COUNTERSIGN h =
-				COSE_Mac_get_countersignature(hMAC, counterNo, 0);
-			if (h == nullptr) {
-				fFail = true;
-				continue;
+		//  Validate counter signatures on signers
+		const cn_cbor *countersignList =
+			cn_cbor_mapget_string(pMac, "countersign0");
+		if (countersignList != nullptr) {
+			cn_cbor *countersigners =
+				cn_cbor_mapget_string(countersignList, "signers");
+			if (countersigners == nullptr) {
+				return 0;
 			}
 
-			cn_cbor *counterSigner = cn_cbor_index(
-				countersigners, forward ? counterNo : count - counterNo - 1);
-
-			cn_cbor *pkeyCountersign =
-				BuildKey(cn_cbor_mapget_string(counterSigner, "key"), false);
-			if (pkeyCountersign == nullptr) {
-				fFail = true;
-				COSE_CounterSign_Free(h);
-				continue;
+			if (COSE_Mac_map_get_int(hMAC, COSE_Header_CounterSign1,
+					COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+				return 0;
 			}
 
-			if (!COSE_CounterSign_SetKey(h, pkeyCountersign, 0)) {
-				fFail = true;
-				COSE_CounterSign_Free(h);
-				CN_CBOR_FREE(pkeyCountersign, context);
-				continue;
+			bool noSupportSign = false;
+			Safe_HCOSE_COUNTERSIGN1 h =
+				COSE_Mac_get_countersignature1(hMAC, nullptr);
+			if (h.IsNull()) {
+				return 0;
 			}
 
-			cn_cbor *alg = COSE_CounterSign_map_get_int(
-				h, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-			if (!IsAlgorithmSupported(alg)) {
-				fAlgNoSupport = true;
-				noSignSupport = true;
-				returnCode = 0;
+			cn_cbor *counterSigner = cn_cbor_index(countersigners, 0);
+
+			Safe_HCOSE_KEY hkeyCountersign(
+				BuildKey(cn_cbor_mapget_string(counterSigner, "key"), false));
+			if (hkeyCountersign == nullptr) {
+				return 0;
 			}
 
-			if (COSE_Mac_CounterSign_validate(hMAC, h, 0)) {
+			if (!COSE_CounterSign1_SetKey(h, hkeyCountersign, nullptr)) {
+				return 0;
+				return false;
+			}
+
+			if (!SetReceivingAttributes(
+					h, counterSigner, Attributes_Countersign1_protected)) {
+				return 0;
+			}
+
+			cose_errback coseError;
+			if (COSE_Mac_CounterSign1_validate(hMAC, h, &coseError)) {
 				//  I don't think we have any forced errors yet.
 			}
 			else {
-				if (forward && counterNo == 0 && count > 1) {
-					forward = false;
-					counterNo -= 1;
+				if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+					returnCode = COSE_MIN(1, returnCode);
 				}
 				else {
-					fFail |= !noSignSupport;
+					returnCode = 0;
 				}
 			}
-
-			COSE_CounterSign_Free(h);
 		}
 	}
 #endif
 
-	COSE_Mac_Free(hMAC);
-
-	if (fFailBody) {
-		if (!fFail) {
-			fFail = true;
-		}
-		else {
-			fFail = false;
-		}
-	}
-
-	if (fFail && !fAlgNoSupport) {
-		CFails += 1;
-	}
 	return returnCode;
 }
 
-int ValidateMAC(const cn_cbor *pControl)
+bool ValidateMAC(const cn_cbor *pControl)
 {
 	int cbEncoded = 0;
 	byte *pbEncoded = GetCBOREncoding(pControl, &cbEncoded);
 
-	return _ValidateMAC(pControl, pbEncoded, cbEncoded);
+	int i = _ValidateMAC(pControl, pbEncoded, cbEncoded);
+	if (i == 0) {
+		CFails += 1;
+	}
+	return i == 2;
 }
 
-int BuildMacMessage(const cn_cbor *pControl)
+bool BuildMacMessage(const cn_cbor *pControl)
 {
 	int iRecipient = 0;
-	HCOSE_RECIPIENT hRecip = nullptr;
 
 	//
 	//  We don't run this for all control sequences - skip those marked fail.
@@ -328,23 +415,17 @@
 
 	const cn_cbor *pFail = cn_cbor_mapget_string(pControl, "fail");
 	if ((pFail != nullptr) && (pFail->type == CN_CBOR_TRUE)) {
-		return 0;
+		return false;
 	}
 
-	HCOSE_MAC hMacObj =
+	Safe_HCOSE_MAC hMacObj =
 		COSE_Mac_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
 	const cn_cbor *pInputs = cn_cbor_mapget_string(pControl, "input");
 	if (pInputs == nullptr) {
 	returnError:
-		if (hMacObj != nullptr) {
-			COSE_Mac_Free(hMacObj);
-		}
-		if (hRecip != nullptr) {
-			COSE_Recipient_Free(hRecip);
-		}
 		CFails += 1;
-		return 1;
+		return false;
 	}
 	const cn_cbor *pMac = cn_cbor_mapget_string(pInputs, "mac");
 	if (pMac == nullptr) {
@@ -357,7 +438,7 @@
 		goto returnError;
 	}
 
-	if (!SetSendingAttributes((HCOSE)hMacObj, pMac, Attributes_MAC_protected)) {
+	if (!SetSendingAttributes(hMacObj, pMac, Attributes_MAC_protected)) {
 		goto returnError;
 	}
 
@@ -369,31 +450,31 @@
 	pRecipients = pRecipients->first_child;
 	for (iRecipient = 0; pRecipients != nullptr;
 		 iRecipient++, pRecipients = pRecipients->next) {
-		cn_cbor *pkey =
+		Safe_HCOSE_KEY hkey =
 			BuildKey(cn_cbor_mapget_string(pRecipients, "key"), true);
-		if (pkey == nullptr) {
+		if (hkey == nullptr) {
 			goto returnError;
 		}
 
-		hRecip = COSE_Recipient_Init(
+		Safe_HCOSE_RECIPIENT hRecip = COSE_Recipient_Init(
 			COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 		if (hRecip == nullptr) {
 			goto returnError;
 		}
 
 		if (!SetSendingAttributes(
-				(HCOSE)hRecip, pRecipients, Attributes_Recipient_protected)) {
+				hRecip, pRecipients, Attributes_Recipient_protected)) {
 			goto returnError;
 		}
 
-		if (!COSE_Recipient_SetKey(hRecip, pkey, nullptr)) {
+		if (!COSE_Recipient_SetKey2(hRecip, hkey, nullptr)) {
 			goto returnError;
 		}
 
 		cn_cbor *pSenderKey = cn_cbor_mapget_string(pRecipients, "sender_key");
 		if (pSenderKey != nullptr) {
-			cn_cbor *pSendKey = BuildKey(pSenderKey, false);
-			if (!COSE_Recipient_SetSenderKey(hRecip, pSendKey, 2, nullptr)) {
+			Safe_HCOSE_KEY hSendKey = BuildKey(pSenderKey, false);
+			if (!COSE_Recipient_SetSenderKey2(hRecip, hSendKey, 2, nullptr)) {
 				goto returnError;
 			}
 		}
@@ -403,125 +484,211 @@
 		}
 
 #if INCLUDE_COUNTERSIGNATURE
-		// On the Recipient
-		cn_cbor *countersigns1 =
-			cn_cbor_mapget_string(pRecipients, "countersign");
+		{
+			// On the Recipient
+			cn_cbor *countersigns1 =
+				cn_cbor_mapget_string(pRecipients, "countersign");
+			if (countersigns1 != nullptr) {
+				countersigns1 = cn_cbor_mapget_string(countersigns1, "signers");
+				cn_cbor *countersign = countersigns1->first_child;
+
+				for (; countersign != nullptr;
+					 countersign = countersign->next) {
+					Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+						cn_cbor_mapget_string(countersign, "key"), false);
+					if (hkeyCountersign == nullptr) {
+						goto returnError;
+					}
+
+					Safe_HCOSE_COUNTERSIGN hCountersign =
+						COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+					if (hCountersign == nullptr) {
+						goto returnError;
+					}
+
+					if (!SetSendingAttributes(hCountersign, countersign,
+							Attributes_Countersign_protected)) {
+						goto returnError;
+					}
+
+					if (!COSE_CounterSign_SetKey2(
+							hCountersign, hkeyCountersign, nullptr)) {
+						goto returnError;
+					}
+
+					if (!COSE_Recipient_add_countersignature(
+							hRecip, hCountersign, nullptr)) {
+						goto returnError;
+					}
+				}
+			}
+		}
+#endif
+
+#if INCLUDE_COUNTERSIGNATURE1
+		{
+			//  Countersign1 on Recipient Body
+
+			//  Validate counter signatures on signers
+			cn_cbor *countersignList =
+				cn_cbor_mapget_string(pRecipients, "countersign0");
+			if (countersignList != nullptr) {
+				cn_cbor *countersigners =
+					cn_cbor_mapget_string(countersignList, "signers");
+				if (countersigners == nullptr) {
+					goto returnError;
+				}
+
+				if (COSE_Recipient_map_get_int(hRecip, COSE_Header_CounterSign1,
+						COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+					goto returnError;
+				}
+
+				bool noSupportSign = false;
+
+				Safe_HCOSE_COUNTERSIGN1 h(
+					COSE_Recipient_get_countersignature1(hRecip, nullptr));
+				if (h.IsNull()) {
+					goto returnError;
+				}
+
+				cn_cbor *counterSigner = cn_cbor_index(countersigners, 0);
+
+				Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+					cn_cbor_mapget_string(counterSigner, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					goto returnError;
+				}
+
+				if (!COSE_CounterSign1_SetKey(h, hkeyCountersign, nullptr)) {
+					goto returnError;
+				}
+
+				cose_errback coseError;
+				if (COSE_Recipient_CounterSign1_validate(
+						hRecip, h, &coseError)) {
+					//  I don't think we have any forced errors yet.
+				}
+				else {
+					if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+						return false;
+					}
+					goto returnError;
+				}
+			}
+		}
+#endif
+	}
+
+#if INCLUDE_COUNTERSIGNATURE
+	{
+		// On the Mac body
+		cn_cbor *countersigns1 = cn_cbor_mapget_string(pMac, "countersign");
 		if (countersigns1 != nullptr) {
 			countersigns1 = cn_cbor_mapget_string(countersigns1, "signers");
 			cn_cbor *countersign = countersigns1->first_child;
 
 			for (; countersign != nullptr; countersign = countersign->next) {
-				cn_cbor *pkeyCountersign =
+				Safe_HCOSE_KEY hkeyCountersign =
 					BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
-				if (pkeyCountersign == nullptr) {
+				if (hkeyCountersign == nullptr) {
 					goto returnError;
 				}
 
-				HCOSE_COUNTERSIGN hCountersign =
+				Safe_HCOSE_COUNTERSIGN hCountersign =
 					COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
 				if (hCountersign == nullptr) {
 					goto returnError;
 				}
 
-				if (!SetSendingAttributes((HCOSE)hCountersign, countersign,
+				if (!SetSendingAttributes(hCountersign, countersign,
 						Attributes_Countersign_protected)) {
 					goto returnError;
 				}
 
-				if (!COSE_CounterSign_SetKey(
-						hCountersign, pkeyCountersign, nullptr)) {
+				if (!COSE_CounterSign_SetKey2(
+						hCountersign, hkeyCountersign, nullptr)) {
 					goto returnError;
 				}
 
-				if (!COSE_Recipient_add_countersignature(
-						hRecip, hCountersign, nullptr)) {
+				if (!COSE_Mac_add_countersignature(
+						hMacObj, hCountersign, nullptr)) {
 					goto returnError;
 				}
-
-				COSE_CounterSign_Free(hCountersign);
 			}
 		}
-
+	}
 #endif
 
-		COSE_Recipient_Free(hRecip);
-		hRecip = nullptr;
-	}
+#if INCLUDE_COUNTERSIGNATURE1
+	{
+		// On the Mac body
+		cn_cbor *countersigns2 = cn_cbor_mapget_string(pMac, "countersign0");
+		if (countersigns2 != nullptr) {
+			countersigns2 = cn_cbor_mapget_string(countersigns2, "signers");
+			cn_cbor *countersign = countersigns2->first_child;
 
-#if INCLUDE_COUNTERSIGNATURE
-	// On the Evneloped body
-	cn_cbor *countersigns1 = cn_cbor_mapget_string(pMac, "countersign");
-	if (countersigns1 != nullptr) {
-		countersigns1 = cn_cbor_mapget_string(countersigns1, "signers");
-		cn_cbor *countersign = countersigns1->first_child;
+			for (; countersign != nullptr; countersign = countersign->next) {
+				Safe_HCOSE_KEY hkeyCountersign =
+					BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					goto returnError;
+				}
 
-		for (; countersign != nullptr; countersign = countersign->next) {
-			cn_cbor *pkeyCountersign =
-				BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
-			if (pkeyCountersign == nullptr) {
-				goto returnError;
+				Safe_HCOSE_COUNTERSIGN1 hCountersign1 =
+					COSE_CounterSign1_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+				if (hCountersign1.IsNull()) {
+					goto returnError;
+				}
+
+				if (!SetSendingAttributes(hCountersign1, countersign,
+						Attributes_Countersign1_protected)) {
+					goto returnError;
+				}
+
+				if (!COSE_CounterSign1_SetKey(
+						hCountersign1, hkeyCountersign, nullptr)) {
+					goto returnError;
+				}
+
+				if (!COSE_Mac_add_countersignature1(
+						hMacObj, hCountersign1, nullptr)) {
+					goto returnError;
+				}
 			}
-
-			HCOSE_COUNTERSIGN hCountersign =
-				COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
-			if (hCountersign == nullptr) {
-				goto returnError;
-			}
-
-			if (!SetSendingAttributes((HCOSE)hCountersign, countersign,
-					Attributes_Countersign_protected)) {
-				COSE_CounterSign_Free(hCountersign);
-				goto returnError;
-			}
-
-			if (!COSE_CounterSign_SetKey(hCountersign, pkeyCountersign, nullptr)) {
-				COSE_CounterSign_Free(hCountersign);
-				goto returnError;
-			}
-
-			if (!COSE_Mac_add_countersignature(hMacObj, hCountersign, nullptr)) {
-				COSE_CounterSign_Free(hCountersign);
-				goto returnError;
-			}
-
-			COSE_CounterSign_Free(hCountersign);
 		}
 	}
-
 #endif
 
 	if (!COSE_Mac_encrypt(hMacObj, nullptr)) {
 		goto returnError;
 	}
 
-	size_t cb = COSE_Encode((HCOSE)hMacObj, nullptr, 0, 0) + 1;
-	byte *rgb = (byte *)malloc(cb);
-	cb = COSE_Encode((HCOSE)hMacObj, rgb, 0, cb);
+	size_t cb = COSE_Encode(hMacObj.ToCOSE(), nullptr, 0, 0) + 1;
+	std::unique_ptr<byte> rgb(new byte[cb]);
+	cb = COSE_Encode(hMacObj.ToCOSE(), rgb.get(), 0, cb);
 
-	COSE_Mac_Free(hMacObj);
+	hMacObj = nullptr;
 
-	int f = _ValidateMAC(pControl, rgb, cb);
-
-	free(rgb);
-	return f;
+	int f = _ValidateMAC(pControl, rgb.get(), cb);
+	if (f == 0) {
+		CFails++;
+	}
+	return f == 2;
 }
 
 int MacMessage()
 {
-	HCOSE_MAC hEncObj =
+	Safe_HCOSE_MAC hEncObj =
 		COSE_Mac_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	const char *sz = "This is the content to be used";
 	byte rgbSecret[256 / 8] = {'a', 'b', 'c'};
 	byte rgbKid[6] = {'a', 'b', 'c', 'd', 'e', 'f'};
 	int cbKid = 6;
 	size_t cb = 0;
-	byte *rgb = nullptr;
 
 	if (hEncObj == nullptr) {
-		errorReturn:
-		if (hEncObj != nullptr) {
-			COSE_Mac_Free(hEncObj);
-		}
+	errorReturn:
 		CFails++;
 		return 0;
 	}
@@ -532,15 +699,18 @@
 			COSE_PROTECT_ONLY, nullptr)) {
 		goto errorReturn;
 	}
-	if (!COSE_Mac_SetContent(hEncObj, (byte *)sz, strlen(sz), nullptr)) {
+
+	if (!COSE_Mac_SetContent(
+			hEncObj, reinterpret_cast<const byte *>(sz), strlen(sz), nullptr)) {
 		goto errorReturn;
 	}
 
-	HCOSE_RECIPIENT hRecip = COSE_Recipient_from_shared_secret(rgbSecret,
+	Safe_HCOSE_RECIPIENT hRecip = COSE_Recipient_from_shared_secret(rgbSecret,
 		sizeof(rgbSecret), rgbKid, cbKid, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	if (hRecip == nullptr) {
 		goto errorReturn;
 	}
+
 	if (!COSE_Mac_AddRecipient(hEncObj, hRecip, nullptr)) {
 		goto errorReturn;
 	}
@@ -549,47 +719,30 @@
 		goto errorReturn;
 	}
 
-	cb = COSE_Encode((HCOSE)hEncObj, nullptr, 0, 0);
+	cb = COSE_Encode(hEncObj.ToCOSE(), nullptr, 0, 0);
 	if (cb == 0) {
 		goto errorReturn;
 	}
 
-	rgb = (byte *)malloc(cb);
+	std::unique_ptr<byte> rgb(new byte[cb]);
 	if (rgb == nullptr) {
 		goto errorReturn;
 	}
-	cb = COSE_Encode((HCOSE)hEncObj, rgb, 0, cb);
+	cb = COSE_Encode(hEncObj.ToCOSE(), rgb.get(), 0, cb);
 	if (cb == 0) {
 		goto errorReturn;
 	}
 
-	COSE_Mac_Free(hEncObj);
-
-	FILE *fp = fopen("test.mac.cbor", "wb");
-	fwrite(rgb, cb, 1, fp);
-	fclose(fp);
-
-#if 0
-	char * szX;
-	int cbPrint = 0;
-	cn_cbor * cbor = COSE_get_cbor((HCOSE)hEncObj);
-	cbPrint = cn_cbor_printer_write(nullptr, 0, cbor, "  ", "\r\n");
-	szX = malloc(cbPrint);
-	cn_cbor_printer_write(szX, cbPrint, cbor, "  ", "\r\n");
-	fprintf(stdout, "%s", szX);
-	fprintf(stdout, "\r\n");
-#endif
-
 	int typ;
-	hEncObj = (HCOSE_MAC)COSE_Decode(
-		rgb, (int)cb, &typ, COSE_mac_object, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	hEncObj = (HCOSE_MAC)COSE_Decode(rgb.get(), static_cast<int>(cb), &typ,
+		COSE_mac_object, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	if (hEncObj == nullptr) {
 		goto errorReturn;
 	}
 
 	int iRecipient = 0;
 	do {
-		HCOSE_RECIPIENT hRecip2;
+		Safe_HCOSE_RECIPIENT hRecip2;
 
 		hRecip2 = COSE_Mac_GetRecipient(hEncObj, iRecipient, nullptr);
 		if (hRecip2 == nullptr) {
@@ -606,9 +759,6 @@
 		}
 
 		iRecipient += 1;
-
-		COSE_Recipient_Free(hRecip2);
-
 	} while (true);
 
 	COSE_Mac_Free(hEncObj);
@@ -626,221 +776,230 @@
 	const cn_cbor *pFail = nullptr;
 	const cn_cbor *pMac = nullptr;
 	const cn_cbor *pRecipients = nullptr;
-	cn_cbor *pkey = nullptr;	
-	HCOSE_MAC0 hMAC = nullptr;
 	int type;
 	bool fFail = false;
 	bool fFailBody = false;
 	bool fUnsuportedAlg = false;
-
-	if (false) {
-	exitHere:
-		if (pkey != nullptr) {
-			CN_CBOR_FREE(pkey, context);
-		}
-		if (hMAC != nullptr) {
-			COSE_Mac0_Free(hMAC);
-		}
-
-		if (fFail) {
-			CFails += 1;
-		}
-		return fUnsuportedAlg ? 0 : 1;
-
-	errorReturn:
-		if (hMAC != nullptr) {
-			COSE_Mac0_Free(hMAC);
-		}
-		CFails += 1;
-		return (fFail || fUnsuportedAlg) ? 0 : 1;
-	}
+	int returnCode = 2;
 
 	pFail = cn_cbor_mapget_string(pControl, "fail");
 	if ((pFail != nullptr) && (pFail->type == CN_CBOR_TRUE)) {
 		fFailBody = true;
 	}
 
-	hMAC = (HCOSE_MAC0)COSE_Decode(pbEncoded, cbEncoded, &type,
+	Safe_HCOSE_MAC0 hMAC = (HCOSE_MAC0)COSE_Decode(pbEncoded, cbEncoded, &type,
 		COSE_mac0_object, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	if (hMAC == nullptr) {
 		if (fFailBody) {
-			return 0;
+			return 1;
 		}
-		else {
-			goto errorReturn;
-		}
+		return 0;
 	}
 
 	if ((pInput == nullptr) || (pInput->type != CN_CBOR_MAP)) {
-		goto errorReturn;
+		return 0;
 	}
 	pMac = cn_cbor_mapget_string(pInput, "mac0");
 	if ((pMac == nullptr) || (pMac->type != CN_CBOR_MAP)) {
-		goto errorReturn;
+		return 0;
 	}
 
-	if (!SetReceivingAttributes((HCOSE)hMAC, pMac, Attributes_MAC0_protected)) {
-		goto errorReturn;
+	if (!SetReceivingAttributes(hMAC, pMac, Attributes_MAC0_protected)) {
+		return 0;
 	}
 
 	pRecipients = cn_cbor_mapget_string(pMac, "recipients");
 	if ((pRecipients == nullptr) || (pRecipients->type != CN_CBOR_ARRAY)) {
-		goto errorReturn;
+		return 0;
 	}
 
 	pRecipients = pRecipients->first_child;
 
-	pkey = BuildKey(cn_cbor_mapget_string(pRecipients, "key"), true);
+	Safe_CN_CBOR pkey =
+		BuildCborKey(cn_cbor_mapget_string(pRecipients, "key"), true);
 	if (pkey == nullptr) {
-		fFail = true;
-		goto exitHere;
+		return 0;
 	}
 
 	cn_cbor *k = cn_cbor_mapget_int(pkey, -1);
 
-	cn_cbor *alg =
-		COSE_Mac0_map_get_int(hMAC, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-	if (!IsAlgorithmSupported(alg)) {
-		fUnsuportedAlg = true;
-	}
-
 	pFail = cn_cbor_mapget_string(pRecipients, "fail");
-	if (COSE_Mac0_validate(hMAC, k->v.bytes, k->length, nullptr)) {
-		if (fUnsuportedAlg) {
-			fFail = true;
-			fUnsuportedAlg = false;
-		}
-		else if ((pFail != nullptr) && (pFail->type != CN_CBOR_TRUE)) {
-			fFail = true;
+
+	cose_errback coseError;
+	if (COSE_Mac0_validate(hMAC, k->v.bytes, k->length, &coseError)) {
+		if ((pFail != nullptr) && (pFail->type != CN_CBOR_TRUE)) {
+			return 0;
 		}
 	}
 	else {
-		if ((pFail == nullptr) || (pFail->type == CN_CBOR_FALSE)) {
-			fFail = true;
+		if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+			returnCode = COSE_MIN(returnCode, 1);
 		}
-		if (fUnsuportedAlg) {
-			fFail = false;
+		else if (fFailBody) {
+			returnCode = COSE_MIN(returnCode, 1);
 		}
+		else if ((pFail == nullptr) || (pFail->type == CN_CBOR_FALSE)) {
+			return 0;
+		}
+		else {
+			returnCode = COSE_MIN(returnCode, 1);
+		}
+			
 	}
 
 #if INCLUDE_COUNTERSIGNATURE
-	//  Countersign on Mac0 Body
+	{
+		//  Countersign on Mac0 Body
 
-	//  Validate counter signatures on signers
-	cn_cbor *countersignList = cn_cbor_mapget_string(pMac, "countersign");
-	if (countersignList != nullptr) {
-		cn_cbor *countersigners =
-			cn_cbor_mapget_string(countersignList, "signers");
-		if (countersigners == nullptr) {
-			fFail = true;
-			goto exitHere;
-		}
-		int count = countersigners->length;
-		bool forward = true;
+		//  Validate counter signatures on signers
+		cn_cbor *countersignList = cn_cbor_mapget_string(pMac, "countersign");
+		if (countersignList != nullptr) {
+			cn_cbor *countersigners =
+				cn_cbor_mapget_string(countersignList, "signers");
+			if (countersigners == nullptr) {
+				return 0;
+			}
+			const int count = static_cast<int>(countersigners->length);
+			bool forward = true;
 
-		if (COSE_Mac0_map_get_int(hMAC, COSE_Header_CounterSign,
-				COSE_UNPROTECT_ONLY, 0) == nullptr) {
-			fFail = true;
-			goto exitHere;
-		}
-
-		for (int counterNo = 0; counterNo < count; counterNo++) {
-			bool noSignAlg = false;
-
-			HCOSE_COUNTERSIGN h =
-				COSE_Mac0_get_countersignature(hMAC, counterNo, 0);
-			if (h == nullptr) {
-				fFail = true;
-				continue;
+			if (COSE_Mac0_map_get_int(hMAC, COSE_Header_CounterSign,
+					COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+				return 0;
 			}
 
-			cn_cbor *counterSigner = cn_cbor_index(
-				countersigners, forward ? counterNo : count - counterNo - 1);
+			for (int counterNo = 0; counterNo < count; counterNo++) {
+				Safe_HCOSE_COUNTERSIGN h =
+					COSE_Mac0_get_countersignature(hMAC, counterNo, nullptr);
+				if (h == nullptr) {
+					returnCode = 0;
+					continue;
+				}
 
-			cn_cbor *pkeyCountersign =
-				BuildKey(cn_cbor_mapget_string(counterSigner, "key"), false);
-			if (pkeyCountersign == nullptr) {
-				fFail = true;
-				COSE_CounterSign_Free(h);
-				continue;
-			}
+				cn_cbor *counterSigner = cn_cbor_index(countersigners,
+					forward ? counterNo : count - counterNo - 1);
 
-			if (!COSE_CounterSign_SetKey(h, pkeyCountersign, 0)) {
-				fFail = true;
-				COSE_CounterSign_Free(h);
-				CN_CBOR_FREE(pkeyCountersign, context);
-				continue;
-			}
+				Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+					cn_cbor_mapget_string(counterSigner, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					returnCode = 0;
+					continue;
+				}
 
-			alg = COSE_CounterSign_map_get_int(
-				h, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-			if (!IsAlgorithmSupported(alg)) {
-				fUnsuportedAlg = true;
-				noSignAlg = true;
-			}
+				if (!COSE_CounterSign_SetKey2(h, hkeyCountersign, nullptr)) {
+					returnCode = 0;
+					continue;
+				}
 
-			if (COSE_Mac0_CounterSign_validate(hMAC, h, 0)) {
-				//  I don't think we have any forced errors yet.
-			}
-			else {
-				if (forward && counterNo == 0 && count > 1) {
-					forward = false;
-					counterNo -= 1;
+				if (COSE_Mac0_CounterSign_validate(hMAC, h, &coseError)) {
+					//  I don't think we have any forced errors yet.
 				}
 				else {
-					fFail |= !noSignAlg;
+					if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+						returnCode = COSE_MIN(returnCode, 1);
+						continue;
+					}
+
+					if (forward && counterNo == 0 && count > 1) {
+						forward = false;
+						counterNo -= 1;
+						continue;
+					}
+					returnCode = 0;
 				}
 			}
-
-			COSE_CounterSign_Free(h);
 		}
 	}
 #endif
 
-	if (fFailBody) {
-		if (!fFail) {
-			fFail = true;
-		}
-		else {
-			fFail = false;
+#ifdef INCLUDE_COUNTERSIGNATURE1
+	{
+		//  Countersign on Mac0 Body
+
+		//  Validate counter signatures on signers
+		cn_cbor *countersignList = cn_cbor_mapget_string(pMac, "countersign0");
+		if (countersignList != nullptr) {
+			cn_cbor *countersigners =
+				cn_cbor_mapget_string(countersignList, "signers");
+			if (countersigners == nullptr) {
+				return 0;
+			}
+			countersigners = countersigners->first_child;
+
+			if (COSE_Mac0_map_get_int(hMAC, COSE_Header_CounterSign1,
+					COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+				return 0;
+			}
+
+			Safe_HCOSE_COUNTERSIGN1 h =
+				COSE_Mac0_get_countersignature1(hMAC, nullptr);
+			if (h == nullptr) {
+				return 0;
+			}
+
+			Safe_HCOSE_KEY hkeyCountersign =
+				BuildKey(cn_cbor_mapget_string(countersigners, "key"), false);
+			if (hkeyCountersign == nullptr) {
+				return 0;
+			}
+
+			if (!COSE_CounterSign1_SetKey(h, hkeyCountersign, nullptr)) {
+				return 0;
+			}
+
+	if (!SetReceivingAttributes(
+					h, countersigners, Attributes_Countersign1_protected)) {
+				return 0;
+			}
+			
+			if (COSE_Mac0_CounterSign1_validate(hMAC, h, &coseError)) {
+				//  I don't think we have any forced errors yet.
+			}
+			else {
+				if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+					returnCode = COSE_MIN(1, returnCode);
+				}
+				else {
+					return 0;
+				}
+			}
 		}
 	}
-	goto exitHere;
+#endif
+
+	return returnCode;
 }
 
-int ValidateMac0(const cn_cbor *pControl)
+bool ValidateMac0(const cn_cbor *pControl)
 {
 	int cbEncoded;
 	byte *pbEncoded = GetCBOREncoding(pControl, &cbEncoded);
 
-	return _ValidateMac0(pControl, pbEncoded, cbEncoded);
+	int i = _ValidateMac0(pControl, pbEncoded, cbEncoded);
+	if (i == 0) {
+		CFails += 1;
+	}
+	return i == 2;
 }
 
-int BuildMac0Message(const cn_cbor *pControl)
+bool BuildMac0Message(const cn_cbor *pControl)
 {
-	cn_cbor *pkey = nullptr;
-
 	//
 	//  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 != nullptr) && (pFail->type == CN_CBOR_TRUE)) {
-		return 0;
+		return false;
 	}
 
-	HCOSE_MAC0 hMacObj =
+	Safe_HCOSE_MAC0 hMacObj =
 		COSE_Mac0_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
 	const cn_cbor *pInputs = cn_cbor_mapget_string(pControl, "input");
 	if (pInputs == nullptr) {
 	returnError:
-		if (pkey != nullptr) {
-			CN_CBOR_FREE(pkey, context);
-		}
-		COSE_Mac0_Free(hMacObj);
 		CFails += 1;
-		return 1;
+		return false;
 	}
 	const cn_cbor *pMac = cn_cbor_mapget_string(pInputs, "mac0");
 	if (pMac == nullptr) {
@@ -853,8 +1012,7 @@
 		goto returnError;
 	}
 
-	if (!SetSendingAttributes(
-			(HCOSE)hMacObj, pMac, Attributes_MAC0_protected)) {
+	if (!SetSendingAttributes(hMacObj, pMac, Attributes_MAC0_protected)) {
 		goto returnError;
 	}
 
@@ -865,7 +1023,8 @@
 
 	pRecipients = pRecipients->first_child;
 
-	pkey = BuildKey(cn_cbor_mapget_string(pRecipients, "key"), false);
+	Safe_CN_CBOR pkey =
+		BuildCborKey(cn_cbor_mapget_string(pRecipients, "key"), false);
 	if (pkey == nullptr) {
 		goto returnError;
 	}
@@ -873,42 +1032,79 @@
 	cn_cbor *k = cn_cbor_mapget_int(pkey, -1);
 
 #if INCLUDE_COUNTERSIGNATURE
-	// On the sign body
-	cn_cbor *countersigns = cn_cbor_mapget_string(pMac, "countersign");
-	if (countersigns != nullptr) {
-		countersigns = cn_cbor_mapget_string(countersigns, "signers");
-		cn_cbor *countersign = countersigns->first_child;
+	{
+		// On the sign body
+		cn_cbor *countersigns = cn_cbor_mapget_string(pMac, "countersign");
+		if (countersigns != nullptr) {
+			countersigns = cn_cbor_mapget_string(countersigns, "signers");
+			cn_cbor *countersign = countersigns->first_child;
 
-		for (; countersign != nullptr; countersign = countersign->next) {
-			cn_cbor *pkeyCountersign =
+			for (; countersign != nullptr; countersign = countersign->next) {
+				Safe_HCOSE_KEY hkeyCountersign =
+					BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					goto returnError;
+				}
+
+				Safe_HCOSE_COUNTERSIGN hCountersign =
+					COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+				if (hCountersign == nullptr) {
+					goto returnError;
+				}
+
+				if (!SetSendingAttributes(hCountersign, countersign,
+						Attributes_Countersign_protected)) {
+					goto returnError;
+				}
+
+				if (!COSE_CounterSign_SetKey2(
+						hCountersign, hkeyCountersign, nullptr)) {
+					goto returnError;
+				}
+
+				if (!COSE_Mac0_add_countersignature(
+						hMacObj, hCountersign, nullptr)) {
+					goto returnError;
+				}
+			}
+		}
+	}
+#endif
+
+#if INCLUDE_COUNTERSIGNATURE1
+	{
+		// On the sign body
+		cn_cbor *countersigns = cn_cbor_mapget_string(pMac, "countersign0");
+		if (countersigns != nullptr) {
+			countersigns = cn_cbor_mapget_string(countersigns, "signers");
+			cn_cbor *countersign = countersigns->first_child;
+
+			Safe_HCOSE_KEY hkeyCountersign =
 				BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
-			if (pkeyCountersign == nullptr) {
+			if (hkeyCountersign == nullptr) {
 				goto returnError;
 			}
 
-			HCOSE_COUNTERSIGN hCountersign =
-				COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+			Safe_HCOSE_COUNTERSIGN1 hCountersign =
+				COSE_CounterSign1_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
 			if (hCountersign == nullptr) {
 				goto returnError;
 			}
 
-			if (!SetSendingAttributes((HCOSE)hCountersign, countersign,
-					Attributes_Countersign_protected)) {
-				COSE_CounterSign_Free(hCountersign);
+			if (!SetSendingAttributes(hCountersign, countersign,
+					Attributes_Countersign1_protected)) {
 				goto returnError;
 			}
 
-			if (!COSE_CounterSign_SetKey(hCountersign, pkeyCountersign, nullptr)) {
-				COSE_CounterSign_Free(hCountersign);
+			if (!COSE_CounterSign1_SetKey(
+					hCountersign, hkeyCountersign, nullptr)) {
 				goto returnError;
 			}
 
-			if (!COSE_Mac0_add_countersignature(hMacObj, hCountersign, nullptr)) {
-				COSE_CounterSign_Free(hCountersign);
+			if (!COSE_Mac0_add_countersignature1(
+					hMacObj, hCountersign, nullptr)) {
 				goto returnError;
 			}
-
-			COSE_CounterSign_Free(hCountersign);
 		}
 	}
 
@@ -918,17 +1114,18 @@
 		goto returnError;
 	}
 
-	size_t cb = COSE_Encode((HCOSE)hMacObj, nullptr, 0, 0) + 1;
-	byte *rgb = (byte *)malloc(cb);
-	cb = COSE_Encode((HCOSE)hMacObj, rgb, 0, cb);
+	size_t cb = COSE_Encode(hMacObj.ToCOSE(), nullptr, 0, 0) + 1;
+	std::unique_ptr<byte> rgb(new byte[cb]);
+	cb = COSE_Encode(hMacObj.ToCOSE(), rgb.get(), 0, cb);
 
-	COSE_Mac0_Free(hMacObj);
-	CN_CBOR_FREE(pkey, context);
+	hMacObj = nullptr;
 
-	int f = _ValidateMac0(pControl, rgb, cb);
+	int f = _ValidateMac0(pControl, rgb.get(), cb);
+	if (f == 0) {
+		CFails++;
+	}
 
-	free(rgb);
-	return f;
+	return f == 2;
 }
 #endif
 
@@ -964,7 +1161,8 @@
 	if (COSE_Mac_encrypt((HCOSE_MAC)hEncrypt, nullptr)) {
 		CFails++;
 	}
-	if (COSE_Mac_validate((HCOSE_MAC)hEncrypt, (HCOSE_RECIPIENT)hMAC, nullptr)) {
+	if (COSE_Mac_validate(
+			(HCOSE_MAC)hEncrypt, (HCOSE_RECIPIENT)hMAC, nullptr)) {
 		CFails++;
 	}
 	if (COSE_Mac_AddRecipient(
@@ -982,8 +1180,8 @@
 	}
 
 #if INCLUDE_ENCRYPT0
-	hEncrypt =
-		COSE_Encrypt_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	hEncrypt = COSE_Encrypt_Init(
+		COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 #else
 	hEncrypt = (HCOSE_ENCRYPT)COSE_CALLOC(1, sizeof(COSE), context);
 #endif
@@ -1001,7 +1199,8 @@
 	if (COSE_Mac_encrypt((HCOSE_MAC)hEncrypt, nullptr)) {
 		CFails++;
 	}
-	if (COSE_Mac_validate((HCOSE_MAC)hEncrypt, (HCOSE_RECIPIENT)hMAC, nullptr)) {
+	if (COSE_Mac_validate(
+			(HCOSE_MAC)hEncrypt, (HCOSE_RECIPIENT)hMAC, nullptr)) {
 		CFails++;
 	}
 	if (COSE_Mac_AddRecipient(
@@ -1021,7 +1220,8 @@
 	//
 	//  Unsupported algorithm
 
-	hMAC = COSE_Mac_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	hMAC =
+		COSE_Mac_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	if (hMAC == nullptr) {
 		CFails++;
 	}
@@ -1046,7 +1246,8 @@
 	COSE_Mac_Free(hMAC);
 	COSE_Recipient_Free(hRecipient);
 
-	hMAC = COSE_Mac_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	hMAC =
+		COSE_Mac_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	if (hMAC == nullptr) {
 		CFails++;
 	}
@@ -1086,8 +1287,8 @@
 	cn_cbor *cn = cn_cbor_int_create(5, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	cose_errback cose_error;
 
-	hEncrypt =
-		COSE_Encrypt_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	hEncrypt = COSE_Encrypt_Init(
+		COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
 	//  Missing case - addref then release on item
 
@@ -1116,8 +1317,8 @@
 		CFails++;
 	}
 
-	hEncrypt =
-		COSE_Encrypt_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	hEncrypt = COSE_Encrypt_Init(
+		COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
 	if (COSE_Mac0_SetContent((HCOSE_MAC0)hEncrypt, rgb, 10, nullptr)) {
 		CFails++;
@@ -1146,7 +1347,8 @@
 	//
 	//  Unsupported algorithm
 
-	hMAC = COSE_Mac0_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	hMAC =
+		COSE_Mac0_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	if (hMAC == nullptr) {
 		CFails++;
 	}
@@ -1162,7 +1364,8 @@
 		COSE_ERR_UNKNOWN_ALGORITHM, CFails++);
 	COSE_Mac0_Free(hMAC);
 
-	hMAC = COSE_Mac0_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	hMAC =
+		COSE_Mac0_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	if (hMAC == nullptr) {
 		CFails++;
 	}
diff --git a/test/Sign_test.cpp b/test/Sign_test.cpp
index 14c5a87..2332ba9 100644
--- a/test/Sign_test.cpp
+++ b/test/Sign_test.cpp
@@ -13,7 +13,8 @@
 #include <cose_int.h>
 #endif
 
-#include "json.h"
+#include <memory>
+
 #include "test.h"
 #include "context.h"
 #include "cose_int.h"
@@ -23,315 +24,378 @@
 #endif
 
 #if INCLUDE_SIGN
+/***  Return:
+ *   2 - Success - run the build phase
+ *   0 - Failed - don't run the build phase
+ *   1 - Failed due to unknown algorithm or other expected failure
+ */
+
 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;
-	const cn_cbor *pSign;
-	const cn_cbor *pSigners;
-	HCOSE_SIGN hSig = nullptr;
-	HCOSE_SIGNER hSigner = nullptr;
 	int type;
-	int iSigner;
-	bool fFail = false;
 	bool fFailBody = false;
-	bool fNoSupportAlg = false;
-	HCOSE_COUNTERSIGN h = nullptr;
+	cose_errback coseError;
+	int returnCode = 2;
 
-	pFail = cn_cbor_mapget_string(pControl, "fail");
+	const cn_cbor *pFail = cn_cbor_mapget_string(pControl, "fail");
 	if ((pFail != nullptr) && (pFail->type == CN_CBOR_TRUE)) {
 		fFailBody = true;
 	}
 
 	if ((pInput == nullptr) || (pInput->type != CN_CBOR_MAP)) {
-		goto returnError;
+		return 0;
 	}
-	pSign = cn_cbor_mapget_string(pInput, "sign");
+	const cn_cbor *pSign = cn_cbor_mapget_string(pInput, "sign");
 	if ((pSign == nullptr) || (pSign->type != CN_CBOR_MAP)) {
-		goto returnError;
+		return 0;
 	}
 
-	pSigners = cn_cbor_mapget_string(pSign, "signers");
+	const cn_cbor *pSigners = cn_cbor_mapget_string(pSign, "signers");
 	if ((pSigners == nullptr) || (pSigners->type != CN_CBOR_ARRAY)) {
-		goto returnError;
+		return 0;
 	}
 
-	iSigner = (int)pSigners->length - 1;
+	size_t iSigner = pSigners->length - 1;
 	pSigners = pSigners->first_child;
+
 	for (; pSigners != nullptr; iSigner--, pSigners = pSigners->next) {
-		hSig = (HCOSE_SIGN)COSE_Decode(pbEncoded, cbEncoded, &type,
-			COSE_sign_object, CBOR_CONTEXT_PARAM_COMMA nullptr);
+		Safe_HCOSE_SIGN hSig = (HCOSE_SIGN)COSE_Decode(pbEncoded, cbEncoded,
+			&type, COSE_sign_object, CBOR_CONTEXT_PARAM_COMMA nullptr);
 		if (hSig == nullptr) {
-			if (fFailBody) {
-				return 0;
-			}
-			else {
-				goto returnError;
-			}
-		}
-		if (!SetReceivingAttributes(
-				(HCOSE)hSig, pSign, Attributes_Sign_protected)) {
-			goto returnError;
+			return fFailBody ? 1 : 0;
 		}
 
-		cn_cbor *pkey = BuildKey(cn_cbor_mapget_string(pSigners, "key"), false);
-		if (pkey == nullptr) {
-			goto returnError;
+		if (!SetReceivingAttributes(hSig, pSign, Attributes_Sign_protected)) {
+			return 0;
 		}
 
-		HCOSE_SIGNER hSigner = COSE_Sign_GetSigner(hSig, iSigner, nullptr);
+		Safe_HCOSE_KEY hkey =
+			BuildKey(cn_cbor_mapget_string(pSigners, "key"), false);
+		if (hkey == nullptr) {
+			return 0;
+		}
+
+		Safe_HCOSE_SIGNER hSigner =
+			COSE_Sign_GetSigner(hSig, static_cast<int>(iSigner), nullptr);
 		if (hSigner == nullptr) {
-			goto returnError;
+			return 0;
 		}
 		if (!SetReceivingAttributes(
-				(HCOSE)hSigner, pSigners, Attributes_Signer_protected)) {
-			goto returnError;
+				hSigner, pSigners, Attributes_Signer_protected)) {
+			return 0;
 		}
 
-		if (!COSE_Signer_SetKey(hSigner, pkey, nullptr)) {
-			goto returnError;
-		}
-
-		cn_cbor *alg = COSE_Signer_map_get_int(
-			hSigner, COSE_Header_Algorithm, COSE_BOTH, 0);
-		if (!IsAlgorithmSupported(alg)) {
-			fNoSupportAlg = true;
+		if (!COSE_Signer_SetKey2(hSigner, hkey, nullptr)) {
+			return 0;
 		}
 
 		pFail = cn_cbor_mapget_string(pSigners, "fail");
-		if (COSE_Sign_validate(hSig, hSigner, nullptr)) {
-			if (fNoSupportAlg) {
-				fFail = true;
-			}
-			else if ((pFail != nullptr) && (pFail->type != CN_CBOR_TRUE)) {
-				fFail = true;
+		if (COSE_Sign_validate(hSig, hSigner, &coseError)) {
+			if ((pFail != nullptr) && (pFail->type != CN_CBOR_TRUE)) {
+				returnCode = 0;
 			}
 		}
 		else {
-			if (fNoSupportAlg) {
-				fFailBody = false;
-				fFail = false;
+			if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+				returnCode = COSE_MIN(1, returnCode);
+			}
+			else if (fFailBody) {
+				returnCode = COSE_MIN(1, returnCode);
 			}
 			else if ((pFail == nullptr) || (pFail->type == CN_CBOR_FALSE)) {
-				fFail = true;
+				returnCode = 0;
+			}
+			else {
+				returnCode = COSE_MIN(1, returnCode);
 			}
 		}
 
 #if INCLUDE_COUNTERSIGNATURE
-		//  Validate counter signatures on signers
-		cn_cbor *countersignList =
-			cn_cbor_mapget_string(pSigners, "countersign");
-		if (countersignList != nullptr) {
-			cn_cbor *countersigners =
-				cn_cbor_mapget_string(countersignList, "signers");
-			if (countersigners == nullptr) {
-				fFail = true;
-				continue;
-			}
-			size_t count = countersigners->length;
-			bool forward = true;
-
-			if (COSE_Signer_map_get_int(hSigner, COSE_Header_CounterSign,
-					COSE_UNPROTECT_ONLY, 0) == nullptr) {
-				goto returnError;
-			}
-
-			for (size_t counterNo = 0; counterNo < count; counterNo++) {
-				bool noSignAlg = false;
-
-				h = COSE_Signer_get_countersignature(hSigner, counterNo, 0);
-				if (h == nullptr) {
-					fFail = true;
-					continue;
-				}
-
-				cn_cbor *counterSigner = cn_cbor_index(countersigners,
-					forward ? counterNo : count - counterNo - 1);
-
-				cn_cbor *pkeyCountersign = BuildKey(
-					cn_cbor_mapget_string(counterSigner, "key"), false);
-				if (pkeyCountersign == nullptr) {
-					fFail = true;
-					COSE_CounterSign_Free(h);
-					continue;
-				}
-
-				if (!COSE_CounterSign_SetKey(h, pkeyCountersign, 0)) {
-					fFail = true;
-					COSE_CounterSign_Free(h);
-					CN_CBOR_FREE(pkeyCountersign, context);
-					continue;
-				}
-
-				alg = COSE_CounterSign_map_get_int(
-					h, COSE_Header_Algorithm, COSE_BOTH, 0);
-				if (!IsAlgorithmSupported(alg)) {
-					fNoSupportAlg = true;
-					noSignAlg = true;
-				}
-
-				if (COSE_Signer_CounterSign_validate(hSigner, h, 0)) {
-					//  I don't think we have any forced errors yet.
-				}
-				else {
-					if (forward && counterNo == 0 && count > 1) {
-						forward = false;
-						counterNo -= 1;
-					}
-					else {
-						fFail |= !noSignAlg;
-					}
-				}
-
-				COSE_CounterSign_Free(h);
-			}
-		}
-#endif
-
-#if INCLUDE_COUNTERSIGNATURE
-		//  Countersign on Signed Body
-
-		if (iSigner == 0) {
+		{
 			//  Validate counter signatures on signers
-			countersignList = cn_cbor_mapget_string(pSign, "countersign");
+			cn_cbor *countersignList =
+				cn_cbor_mapget_string(pSigners, "countersign");
 			if (countersignList != nullptr) {
 				cn_cbor *countersigners =
 					cn_cbor_mapget_string(countersignList, "signers");
 				if (countersigners == nullptr) {
-					fFail = true;
-					continue;
+					return 0;
 				}
-				int count = countersigners->length;
+				const size_t count = countersigners->length;
 				bool forward = true;
 
-				if (COSE_Sign_map_get_int(hSig, COSE_Header_CounterSign,
-						COSE_UNPROTECT_ONLY, 0) == nullptr) {
-					goto returnError;
+				if (COSE_Signer_map_get_int(hSigner, COSE_Header_CounterSign,
+						COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+					return 0;
 				}
 
-				for (int counterNo = 0; counterNo < count; counterNo++) {
+				for (size_t counterNo = 0; counterNo < count; counterNo++) {
 					bool noSignAlg = false;
 
-					HCOSE_COUNTERSIGN h =
-						COSE_Sign_get_countersignature(hSig, counterNo, 0);
+					Safe_HCOSE_COUNTERSIGN h = COSE_Signer_get_countersignature(
+						hSigner, static_cast<int>(counterNo), nullptr);
 					if (h == nullptr) {
-						fFail = true;
-						continue;
+						return 0;
 					}
 
 					cn_cbor *counterSigner = cn_cbor_index(countersigners,
-						forward ? counterNo : count - counterNo - 1);
+						static_cast<int>(
+							forward ? counterNo : count - counterNo - 1));
 
-					cn_cbor *pkeyCountersign = BuildKey(
+					Safe_HCOSE_KEY hkeyCountersign = BuildKey(
 						cn_cbor_mapget_string(counterSigner, "key"), false);
-					if (pkeyCountersign == nullptr) {
-						fFail = true;
-						COSE_CounterSign_Free(h);
-						continue;
+					if (hkeyCountersign == nullptr) {
+						return 0;
 					}
 
-					if (!COSE_CounterSign_SetKey(h, pkeyCountersign, 0)) {
-						fFail = true;
-						COSE_CounterSign_Free(h);
-						CN_CBOR_FREE(pkeyCountersign, context);
-						continue;
+					if (!COSE_CounterSign_SetKey2(
+							h, hkeyCountersign, nullptr)) {
+						return 0;
 					}
 
-					alg = COSE_CounterSign_map_get_int(
-						h, COSE_Header_Algorithm, COSE_BOTH, 0);
-					if (!IsAlgorithmSupported(alg)) {
-						fNoSupportAlg = true;
-						noSignAlg = true;
-					}
-
-					if (COSE_Sign_CounterSign_validate(hSig, h, 0)) {
+					if (COSE_Signer_CounterSign_validate(
+							hSigner, h, &coseError)) {
 						//  I don't think we have any forced errors yet.
 					}
 					else {
-						if (forward && counterNo == 0 && count > 1) {
+						if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+							returnCode = COSE_MIN(1, returnCode);
+						}
+						else if (forward && counterNo == 0 && count > 1) {
 							forward = false;
 							counterNo -= 1;
 						}
 						else {
-							fFail |= !noSignAlg;
+							returnCode = 0;
 						}
 					}
-
-					COSE_CounterSign_Free(h);
 				}
 			}
 		}
 #endif
 
-		COSE_Sign_Free(hSig);
-		COSE_Signer_Free(hSigner);
-	}
+#if INCLUDE_COUNTERSIGNATURE1
+		{
+			//  Countersign1 on Signer Body
 
-	if (fFailBody) {
-		if (!fFail) {
-			fFail = true;
+			//  Validate counter signatures on signers
+			cn_cbor *countersignList =
+				cn_cbor_mapget_string(pSigners, "countersign0");
+			if (countersignList != nullptr) {
+				cn_cbor *countersigners =
+					cn_cbor_mapget_string(countersignList, "signers");
+				if (countersigners == nullptr) {
+					return 0;
+				}
+
+				if (COSE_Signer_map_get_int(hSigner, COSE_Header_CounterSign1,
+						COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+					return 0;
+				}
+
+				Safe_HCOSE_COUNTERSIGN1 h(
+					COSE_Signer_get_countersignature1(hSigner, nullptr));
+				if (h.IsNull()) {
+					return 0;
+				}
+
+				cn_cbor *counterSigner = cn_cbor_index(countersigners, 0);
+
+				Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+					cn_cbor_mapget_string(counterSigner, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					return 0;
+				}
+
+				if (!COSE_CounterSign1_SetKey(h, hkeyCountersign, nullptr)) {
+					return 0;
+				}
+
+	if (!SetReceivingAttributes(
+						h, counterSigner, Attributes_Countersign1_protected)) {
+					return 0;
+				}
+				
+				if (COSE_Signer_CounterSign1_validate(hSigner, h, &coseError)) {
+					//  I don't think we have any forced errors yet.
+				}
+				else {
+					if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+						returnCode = COSE_MIN(returnCode, 1);
+					}
+					else {
+						returnCode = 0;
+					}
+				}
+			}
 		}
-		else {
-			fFail = false;
+#endif
+
+#if INCLUDE_COUNTERSIGNATURE
+		{
+			//  Countersign on Signed Body
+
+			if (iSigner == 0) {
+				//  Validate counter signatures on signers
+				cn_cbor *countersignList =
+					cn_cbor_mapget_string(pSign, "countersign");
+				if (countersignList != nullptr) {
+					cn_cbor *countersigners =
+						cn_cbor_mapget_string(countersignList, "signers");
+					if (countersigners == nullptr) {
+						return 0;
+					}
+					int count = static_cast<int>(countersigners->length);
+					bool forward = true;
+
+					if (COSE_Sign_map_get_int(hSig, COSE_Header_CounterSign,
+							COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+						return 0;
+					}
+
+					for (int counterNo = 0; counterNo < count; counterNo++) {
+						Safe_HCOSE_COUNTERSIGN h =
+							COSE_Sign_get_countersignature(
+								hSig, counterNo, nullptr);
+						if (h == nullptr) {
+							returnCode = 0;
+							continue;
+						}
+
+						cn_cbor *counterSigner = cn_cbor_index(countersigners,
+							forward ? counterNo : count - counterNo - 1);
+
+						Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+							cn_cbor_mapget_string(counterSigner, "key"), false);
+						if (hkeyCountersign == nullptr) {
+							returnCode = 0;
+							continue;
+						}
+
+						if (!COSE_CounterSign_SetKey2(
+								h, hkeyCountersign, nullptr)) {
+							return 0;
+						}
+
+						if (COSE_Sign_CounterSign_validate(
+								hSig, h, &coseError)) {
+							//  I don't think we have any forced errors yet.
+						}
+						else {
+							if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+								return -1;
+							}
+
+							if (forward && counterNo == 0 && count > 1) {
+								forward = false;
+								counterNo -= 1;
+							}
+							else {
+								returnCode = 0;
+							}
+						}
+					}
+				}
+			}
 		}
+#endif
+
+#if INCLUDE_COUNTERSIGNATURE1
+		{
+			//  Countersign1 on Sign Body
+
+			//  Validate counter signatures on signers
+			cn_cbor *countersignList =
+				cn_cbor_mapget_string(pSign, "countersign0");
+			if (countersignList != nullptr) {
+				cn_cbor *countersigners =
+					cn_cbor_mapget_string(countersignList, "signers");
+				if (countersigners == nullptr) {
+					return 0;
+				}
+
+				if (COSE_Sign_map_get_int(hSig, COSE_Header_CounterSign1,
+						COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+					return 0;
+				}
+
+				bool noSupportSign = false;
+
+				Safe_HCOSE_COUNTERSIGN1 h(
+					COSE_Sign_get_countersignature1(hSig, nullptr));
+				if (h.IsNull()) {
+					return 0;
+				}
+
+				cn_cbor *counterSigner = cn_cbor_index(countersigners, 0);
+
+				Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+					cn_cbor_mapget_string(counterSigner, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					return 0;
+				}
+
+				if (!COSE_CounterSign1_SetKey(h, hkeyCountersign, nullptr)) {
+					return 0;
+				}
+				
+	if (!SetReceivingAttributes(
+						h, counterSigner, Attributes_Countersign1_protected)) {
+					return 0;
+				}
+
+				if (COSE_Sign_CounterSign1_validate(hSig, h, &coseError)) {
+					//  I don't think we have any forced errors yet.
+				}
+				else {
+					if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+						return 1;
+					}
+					return 0;
+				}
+			}
+		}
+
+#endif
 	}
 
-	if (fFail) {
-		CFails += 1;
-	}
-	return fNoSupportAlg ? 0 : 1;
-
-returnError:
-	if (hSigner != nullptr) {
-		COSE_Signer_Free(hSigner);
-	}
-	if (hSig != nullptr) {
-		COSE_Sign_Free(hSig);
-	}
-
-	CFails += 1;
-	return 0;
+	return returnCode;
 }
 
-int ValidateSigned(const cn_cbor *pControl)
+bool ValidateSigned(const cn_cbor *pControl)
 {
 	int cbEncoded;
 	byte *pbEncoded = GetCBOREncoding(pControl, &cbEncoded);
 
-	return _ValidateSigned(pControl, pbEncoded, cbEncoded);
+	int i = _ValidateSigned(pControl, pbEncoded, cbEncoded);
+	if (i == 0) {
+		CFails += 1;
+	}
+	return i == 2;
 }
 
-int BuildSignedMessage(const cn_cbor *pControl)
+bool BuildSignedMessage(const cn_cbor *pControl)
 {
-	int iSigner;
-	HCOSE_SIGNER hSigner = nullptr;
-
 	//
 	//  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 != nullptr) && (pFail->type == CN_CBOR_TRUE)) {
-		return 0;
+		return false;
 	}
 
-	HCOSE_SIGN hSignObj =
+	Safe_HCOSE_SIGN hSignObj =
 		COSE_Sign_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
 	const cn_cbor *pInputs = cn_cbor_mapget_string(pControl, "input");
 	if (pInputs == nullptr) {
 	returnError:
-		if (hSignObj != nullptr) {
-			COSE_Sign_Free(hSignObj);
-		}
-		if (hSigner != nullptr) {
-			COSE_Signer_Free(hSigner);
-		}
-
 		CFails += 1;
-		return 1;
+		return false;
 	}
 	const cn_cbor *pSign = cn_cbor_mapget_string(pInputs, "sign");
 	if (pSign == nullptr) {
@@ -344,8 +408,7 @@
 		goto returnError;
 	}
 
-	if (!SetSendingAttributes(
-			(HCOSE)hSignObj, pSign, Attributes_Sign_protected)) {
+	if (!SetSendingAttributes(hSignObj, pSign, Attributes_Sign_protected)) {
 		goto returnError;
 	}
 
@@ -355,23 +418,26 @@
 	}
 
 	pSigners = pSigners->first_child;
-	for (iSigner = 0; pSigners != nullptr; iSigner++, pSigners = pSigners->next) {
-		cn_cbor *pkey = BuildKey(cn_cbor_mapget_string(pSigners, "key"), false);
-		if (pkey == nullptr) {
+	for (int iSigner = 0; pSigners != nullptr;
+		 iSigner++, pSigners = pSigners->next) {
+		Safe_HCOSE_KEY hkey =
+			BuildKey(cn_cbor_mapget_string(pSigners, "key"), false);
+		if (hkey == nullptr) {
 			goto returnError;
 		}
 
-		hSigner = COSE_Signer_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+		Safe_HCOSE_SIGNER hSigner =
+			COSE_Signer_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
 		if (hSigner == nullptr) {
 			goto returnError;
 		}
 
 		if (!SetSendingAttributes(
-				(HCOSE)hSigner, pSigners, Attributes_Signer_protected)) {
+				hSigner, pSigners, Attributes_Signer_protected)) {
 			goto returnError;
 		}
 
-		if (!COSE_Signer_SetKey(hSigner, pkey, nullptr)) {
+		if (!COSE_Signer_SetKey2(hSigner, hkey, nullptr)) {
 			goto returnError;
 		}
 
@@ -380,48 +446,84 @@
 		}
 
 #if INCLUDE_COUNTERSIGNATURE
-		//  On the signer object
-		cn_cbor *countersigns = cn_cbor_mapget_string(pSigners, "countersign");
-		if (countersigns != nullptr) {
-			countersigns = cn_cbor_mapget_string(countersigns, "signers");
-			cn_cbor *countersign = countersigns->first_child;
+		{
+			//  On the signer object
+			cn_cbor *countersigns =
+				cn_cbor_mapget_string(pSigners, "countersign");
+			if (countersigns != nullptr) {
+				countersigns = cn_cbor_mapget_string(countersigns, "signers");
+				cn_cbor *countersign = countersigns->first_child;
 
-			for (; countersign != nullptr; countersign = countersign->next) {
-				cn_cbor *pkeyCountersign =
+				for (; countersign != nullptr;
+					 countersign = countersign->next) {
+					Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+						cn_cbor_mapget_string(countersign, "key"), false);
+					if (hkeyCountersign == nullptr) {
+						goto returnError;
+					}
+
+					Safe_HCOSE_COUNTERSIGN hCountersign =
+						COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+					if (hCountersign == nullptr) {
+						goto returnError;
+					}
+
+					if (!SetSendingAttributes(hCountersign, countersign,
+							Attributes_Countersign_protected)) {
+						goto returnError;
+					}
+
+					if (!COSE_CounterSign_SetKey2(
+							hCountersign, hkeyCountersign, nullptr)) {
+						goto returnError;
+					}
+
+					if (!COSE_Signer_add_countersignature(
+							hSigner, hCountersign, nullptr)) {
+						goto returnError;
+					}
+				}
+			}
+		}
+#endif
+#if INCLUDE_COUNTERSIGNATURE1
+		{
+			//  On the signer object
+			cn_cbor *countersigns =
+				cn_cbor_mapget_string(pSigners, "countersign0");
+			if (countersigns != nullptr) {
+				countersigns = cn_cbor_mapget_string(countersigns, "signers");
+				cn_cbor *countersign = countersigns->first_child;
+
+				Safe_HCOSE_KEY hkeyCountersign =
 					BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
-				if (pkeyCountersign == nullptr) {
+				if (hkeyCountersign == nullptr) {
 					goto returnError;
 				}
 
-				HCOSE_COUNTERSIGN hCountersign =
-					COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+				Safe_HCOSE_COUNTERSIGN1 hCountersign =
+					COSE_CounterSign1_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
 				if (hCountersign == nullptr) {
 					goto returnError;
 				}
 
-				if (!SetSendingAttributes((HCOSE)hCountersign, countersign,
-						Attributes_Countersign_protected)) {
-					COSE_CounterSign_Free(hCountersign);
+				if (!SetSendingAttributes(hCountersign, countersign,
+						Attributes_Countersign1_protected)) {
 					goto returnError;
 				}
 
-				if (!COSE_CounterSign_SetKey(
-						hCountersign, pkeyCountersign, nullptr)) {
-					COSE_CounterSign_Free(hCountersign);
+				if (!COSE_CounterSign1_SetKey(
+						hCountersign, hkeyCountersign, nullptr)) {
 					goto returnError;
 				}
 
-				if (!COSE_Signer_add_countersignature(
+				if (!COSE_Signer_add_countersignature1(
 						hSigner, hCountersign, nullptr)) {
-					COSE_CounterSign_Free(hCountersign);
 					goto returnError;
 				}
-
-				COSE_CounterSign_Free(hCountersign);
 			}
 		}
 #endif
-		COSE_Signer_Free(hSigner);
 	}
 #if INCLUDE_COUNTERSIGNATURE
 	// On the sign body
@@ -431,63 +533,98 @@
 		cn_cbor *countersign = countersigns1->first_child;
 
 		for (; countersign != nullptr; countersign = countersign->next) {
-			cn_cbor *pkeyCountersign =
+			Safe_HCOSE_KEY hkeyCountersign =
 				BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
-			if (pkeyCountersign == nullptr) {
+			if (hkeyCountersign == nullptr) {
 				goto returnError;
 			}
 
-			HCOSE_COUNTERSIGN hCountersign =
+			Safe_HCOSE_COUNTERSIGN hCountersign =
 				COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
 			if (hCountersign == nullptr) {
 				goto returnError;
 			}
 
-			if (!SetSendingAttributes((HCOSE)hCountersign, countersign,
+			if (!SetSendingAttributes(hCountersign, countersign,
 					Attributes_Countersign_protected)) {
-				COSE_CounterSign_Free(hCountersign);
 				goto returnError;
 			}
 
-			if (!COSE_CounterSign_SetKey(hCountersign, pkeyCountersign, nullptr)) {
-				COSE_CounterSign_Free(hCountersign);
+			if (!COSE_CounterSign_SetKey2(
+					hCountersign, hkeyCountersign, nullptr)) {
 				goto returnError;
 			}
 
-			if (!COSE_Sign_add_countersignature(hSignObj, hCountersign, nullptr)) {
-				COSE_CounterSign_Free(hCountersign);
+			if (!COSE_Sign_add_countersignature(
+					hSignObj, hCountersign, nullptr)) {
 				goto returnError;
 			}
-
-			COSE_CounterSign_Free(hCountersign);
 		}
 	}
+#endif
 
+#if INCLUDE_COUNTERSIGNATURE1
+	{
+		//  On the signer object
+		cn_cbor *countersigns = cn_cbor_mapget_string(pSign, "countersign0");
+		if (countersigns != nullptr) {
+			countersigns = cn_cbor_mapget_string(countersigns, "signers");
+			cn_cbor *countersign = countersigns->first_child;
+
+			Safe_HCOSE_KEY hkeyCountersign =
+				BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
+			if (hkeyCountersign == nullptr) {
+				goto returnError;
+			}
+
+			Safe_HCOSE_COUNTERSIGN1 hCountersign =
+				COSE_CounterSign1_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+			if (hCountersign == nullptr) {
+				goto returnError;
+			}
+
+			if (!SetSendingAttributes(hCountersign, countersign,
+					Attributes_Countersign1_protected)) {
+				goto returnError;
+			}
+
+			if (!COSE_CounterSign1_SetKey(
+					hCountersign, hkeyCountersign, nullptr)) {
+				goto returnError;
+			}
+
+			if (!COSE_Sign_add_countersignature1(
+					hSignObj, hCountersign, nullptr)) {
+				goto returnError;
+			}
+		}
+	}
 #endif
 
 	if (!COSE_Sign_Sign(hSignObj, nullptr)) {
 		goto returnError;
 	}
 
-	size_t cb = COSE_Encode((HCOSE)hSignObj, nullptr, 0, 0) + 1;
-	byte *rgb = (byte *)malloc(cb);
-	cb = COSE_Encode((HCOSE)hSignObj, rgb, 0, cb);
+	size_t cb = COSE_Encode(hSignObj.ToCOSE(), nullptr, 0, 0) + 1;
+	std::unique_ptr<byte> rgb(new byte[cb]);
+	cb = COSE_Encode(hSignObj.ToCOSE(), rgb.get(), 0, cb);
 
 	COSE_Sign_Free(hSignObj);
 
-	int f = _ValidateSigned(pControl, rgb, cb);
+	int f = _ValidateSigned(pControl, rgb.get(), cb);
+	if (f == 0) {
+		CFails += 1;
+	}
 
-	free(rgb);
-	return f;
+	return f == 2;
 }
 
 int SignMessage()
 {
-	HCOSE_SIGN hEncObj =
-		COSE_Sign_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	Safe_HCOSE_SIGN hEncObj =
+		(HCOSE_SIGN) COSE_Sign_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	const char *sz = "This is the content to be used";
 	size_t cb;
-	byte *rgb;
 
 	byte rgbX[] = {0x65, 0xed, 0xa5, 0xa1, 0x25, 0x77, 0xc2, 0xba, 0xe8, 0x29,
 		0x43, 0x7f, 0xe3, 0x38, 0x70, 0x1a, 0x10, 0xaa, 0xa3, 0x75, 0xe1, 0xbb,
@@ -511,50 +648,39 @@
 		cn_cbor_int_create(1, CBOR_CONTEXT_PARAM_COMMA nullptr),
 		CBOR_CONTEXT_PARAM_COMMA nullptr);
 	cn_cbor_mapput_int(pkey, -2,
-		cn_cbor_data_create(rgbX, sizeof(rgbX), CBOR_CONTEXT_PARAM_COMMA nullptr),
+		cn_cbor_data_create(
+			rgbX, sizeof(rgbX), CBOR_CONTEXT_PARAM_COMMA nullptr),
 		CBOR_CONTEXT_PARAM_COMMA nullptr);
 	cn_cbor_mapput_int(pkey, -3,
-		cn_cbor_data_create(rgbY, sizeof(rgbY), CBOR_CONTEXT_PARAM_COMMA nullptr),
+		cn_cbor_data_create(
+			rgbY, sizeof(rgbY), CBOR_CONTEXT_PARAM_COMMA nullptr),
 		CBOR_CONTEXT_PARAM_COMMA nullptr);
 	cn_cbor_mapput_int(pkey, COSE_Key_ID,
 		cn_cbor_data_create(kid, sizeof(kid), CBOR_CONTEXT_PARAM_COMMA nullptr),
 		CBOR_CONTEXT_PARAM_COMMA nullptr);
 	cn_cbor_mapput_int(pkey, -4,
-		cn_cbor_data_create(rgbD, sizeof(rgbD), CBOR_CONTEXT_PARAM_COMMA nullptr),
+		cn_cbor_data_create(
+			rgbD, sizeof(rgbD), CBOR_CONTEXT_PARAM_COMMA nullptr),
 		CBOR_CONTEXT_PARAM_COMMA nullptr);
 
-	COSE_Sign_SetContent(hEncObj, (byte *)sz, strlen(sz), nullptr);
+	COSE_Sign_SetContent(
+		hEncObj, reinterpret_cast<const byte *>(sz), strlen(sz), nullptr);
 	COSE_Signer_Free(COSE_Sign_add_signer(
 		hEncObj, pkey, COSE_Algorithm_ECDSA_SHA_256, nullptr));
 
 	COSE_Sign_Sign(hEncObj, nullptr);
 
-	cb = COSE_Encode((HCOSE)hEncObj, nullptr, 0, 0) + 1;
-	rgb = (byte *)malloc(cb);
-	cb = COSE_Encode((HCOSE)hEncObj, rgb, 0, cb);
+	cb = COSE_Encode(hEncObj.ToCOSE(), nullptr, 0, 0) + 1;
+	std::unique_ptr<byte> rgb(new byte[cb]);
+	cb = COSE_Encode(hEncObj.ToCOSE(), rgb.get(), 0, cb);
 
 	COSE_Sign_Free(hEncObj);
 
-	FILE *fp = fopen("test.mac.cbor", "wb");
-	fwrite(rgb, cb, 1, fp);
-	fclose(fp);
-
-#if 0
-	char * szX;
-	int cbPrint = 0;
-	cn_cbor * cbor = COSE_get_cbor((HCOSE)hEncObj);
-	cbPrint = cn_cbor_printer_write(nullptr, 0, cbor, "  ", "\r\n");
-	szX = malloc(cbPrint);
-	cn_cbor_printer_write(szX, cbPrint, cbor, "  ", "\r\n");
-	fprintf(stdout, "%s", szX);
-	fprintf(stdout, "\r\n");
-#endif
-
 	/* */
 
 	int typ;
-	hEncObj = (HCOSE_SIGN)COSE_Decode(
-		rgb, (int)cb, &typ, COSE_sign_object, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	hEncObj = (HCOSE_SIGN)COSE_Decode(rgb.get(), (int)cb, &typ,
+		COSE_sign_object, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
 #if 0
 	int iSigner = 0;
@@ -585,216 +711,230 @@
 	size_t cbEncoded)
 {
 	const cn_cbor *pInput = cn_cbor_mapget_string(pControl, "input");
-	const cn_cbor *pFail;
-	const cn_cbor *pSign;
-	HCOSE_SIGN1 hSig = nullptr;
-	cn_cbor *pkey = nullptr;
 	int type;
 	bool fFail = false;
 	bool fFailBody = false;
-	bool fNoAlgSupport = false;
+	int returnCode = 2;
 
-	if (false) {
-	exitHere:
-		if (hSig != nullptr) {
-			COSE_Sign1_Free(hSig);
-		}
-
-		if (fFail) {
-			CFails += 1;
-		}
-		if (pkey != nullptr) {
-			CN_CBOR_FREE(pkey, context);
-		}
-		return fNoAlgSupport ? 0 : 1;
-
-	returnError:
-		if (hSig != nullptr) {
-			COSE_Sign1_Free(hSig);
-		}
-
-		CFails += 1;
-		return 0;		
-	}
-
-	pFail = cn_cbor_mapget_string(pControl, "fail");
+	const cn_cbor *pFail = cn_cbor_mapget_string(pControl, "fail");
 	if ((pFail != nullptr) && (pFail->type == CN_CBOR_TRUE)) {
 		fFailBody = true;
 	}
 
 	if ((pInput == nullptr) || (pInput->type != CN_CBOR_MAP)) {
-		goto returnError;
+		return 0;
 	}
-	pSign = cn_cbor_mapget_string(pInput, "sign0");
+	const cn_cbor *pSign = cn_cbor_mapget_string(pInput, "sign0");
 	if ((pSign == nullptr) || (pSign->type != CN_CBOR_MAP)) {
-		goto returnError;
+		return 0;
 	}
 
-	hSig = (HCOSE_SIGN1)COSE_Decode(pbEncoded, cbEncoded, &type,
-		COSE_sign1_object, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	Safe_HCOSE_SIGN1 hSig = (HCOSE_SIGN1)COSE_Decode(pbEncoded, cbEncoded,
+		&type, COSE_sign1_object, CBOR_CONTEXT_PARAM_COMMA nullptr);
 	if (hSig == nullptr) {
 		if (fFailBody) {
-			return 0;
+			return 1;
 		}
-		else {
-			goto returnError;
-		}
+		return 0;
 	}
 
-	if (!SetReceivingAttributes(
-			(HCOSE)hSig, pSign, Attributes_Sign1_protected)) {
-		goto returnError;
+	if (!SetReceivingAttributes(hSig, pSign, Attributes_Sign1_protected)) {
+		return 0;
 	}
 
-	pkey = BuildKey(cn_cbor_mapget_string(pSign, "key"), false);
-	if (pkey == nullptr) {
-		fFail = true;
-		goto exitHere;
+	Safe_HCOSE_KEY hkey = BuildKey(cn_cbor_mapget_string(pSign, "key"), false);
+	if (hkey == nullptr) {
+		return 0;
 	}
 
-	cn_cbor *alg =
-		COSE_Sign1_map_get_int(hSig, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-	if (!IsAlgorithmSupported(alg)) {
-		fNoAlgSupport = true;
-	}
+	cose_errback coseError;
 
 	pFail = cn_cbor_mapget_string(pInput, "fail");
-	if (COSE_Sign1_validate(hSig, pkey, nullptr)) {
-		if (fNoAlgSupport) {
-			fFail = true;
-		}
-		else if ((pFail != nullptr) && (pFail->type != CN_CBOR_TRUE)) {
-			fFail = true;
+	if (COSE_Sign1_validate2(hSig, hkey, &coseError)) {
+		if ((pFail != nullptr) && (pFail->type != CN_CBOR_TRUE)) {
+			return 0;
 		}
 	}
 	else {
-		if (fNoAlgSupport) {
-			fFailBody = false;
-			fFail = false;
+		if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+			return 1;
 		}
-		else if ((pFail == nullptr) || (pFail->type == CN_CBOR_FALSE)) {
-			fFail = true;
+		if (fFailBody) {
+			return 1;
+		}
+
+		if ((pFail == nullptr) || (pFail->type == CN_CBOR_FALSE)) {
+			return 0;
 		}
 	}
 
 #if INCLUDE_COUNTERSIGNATURE
-	//  Countersign on Signed Body
+	{
+		//  Countersign on Signed Body
 
-	//  Validate counter signatures on signers
-	cn_cbor *countersignList = cn_cbor_mapget_string(pSign, "countersign");
-	if (countersignList != nullptr) {
-		cn_cbor *countersigners =
-			cn_cbor_mapget_string(countersignList, "signers");
-		if (countersigners == nullptr) {
-			fFail = true;
-			goto exitHere;
-		}
-		size_t count = countersigners->length;
-		bool forward = true;
+		//  Validate counter signatures on signers
+		cn_cbor *countersignList = cn_cbor_mapget_string(pSign, "countersign");
+		if (countersignList != nullptr) {
+			cn_cbor *countersigners =
+				cn_cbor_mapget_string(countersignList, "signers");
+			if (countersigners == nullptr) {
+				return 0;
+			}
+			size_t count = countersigners->length;
+			bool forward = true;
 
-		if (COSE_Sign1_map_get_int(hSig, COSE_Header_CounterSign,
-				COSE_UNPROTECT_ONLY, 0) == nullptr) {
-			goto returnError;
-		}
-
-		for (size_t counterNo = 0; counterNo < count; counterNo++) {
-			bool noSignAlg = false;
-
-			HCOSE_COUNTERSIGN h =
-				COSE_Sign1_get_countersignature(hSig, counterNo, 0);
-			if (h == nullptr) {
-				fFail = true;
-				continue;
+			if (COSE_Sign1_map_get_int(hSig, COSE_Header_CounterSign,
+					COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+				return 0;
 			}
 
-			cn_cbor *counterSigner = cn_cbor_index(
-				countersigners, forward ? counterNo : count - counterNo - 1);
+			for (size_t counterNo = 0; counterNo < count; counterNo++) {
+				bool noSignAlg = false;
 
-			cn_cbor *pkeyCountersign =
-				BuildKey(cn_cbor_mapget_string(counterSigner, "key"), false);
-			if (pkeyCountersign == nullptr) {
-				fFail = true;
-				COSE_CounterSign_Free(h);
-				continue;
-			}
+				Safe_HCOSE_COUNTERSIGN h = COSE_Sign1_get_countersignature(
+					hSig, static_cast<int>(counterNo), nullptr);
+				if (h == nullptr) {
+					return 0;
+				}
 
-			if (!COSE_CounterSign_SetKey(h, pkeyCountersign, 0)) {
-				fFail = true;
-				COSE_CounterSign_Free(h);
-				CN_CBOR_FREE(pkeyCountersign, context);
-				continue;
-			}
+				cn_cbor *counterSigner = cn_cbor_index(countersigners,
+					static_cast<int>(
+						forward ? counterNo : count - counterNo - 1));
 
-			alg = COSE_Sign1_map_get_int(
-				hSig, COSE_Header_Algorithm, COSE_BOTH, nullptr);
-			if (!IsAlgorithmSupported(alg)) {
-				fNoAlgSupport = true;
-				noSignAlg = true;
-			}
+				Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+					cn_cbor_mapget_string(counterSigner, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					return 0;
+				}
 
-			if (COSE_Sign1_CounterSign_validate(hSig, h, 0)) {
-				//  I don't think we have any forced errors yet.
-			}
-			else {
-				if (forward && counterNo == 0 && count > 1) {
-					forward = false;
-					counterNo -= 1;
+				if (!COSE_CounterSign_SetKey2(h, hkeyCountersign, nullptr)) {
+					return 0;
+				}
+
+				if (COSE_Sign1_CounterSign_validate(hSig, h, &coseError)) {
+					//  I don't think we have any forced errors yet.
 				}
 				else {
-					fFail |= !noSignAlg;
+					if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+						return 1;
+					}
+
+					if (forward && counterNo == 0 && count > 1) {
+						forward = false;
+						counterNo -= 1;
+					}
+					else {
+						return 0;
+					}
 				}
 			}
-
-			COSE_CounterSign_Free(h);
 		}
 	}
 #endif
 
-	if (fFailBody) {
-		if (!fFail) {
-			fFail = true;
-		}
-		else {
-			fFail = false;
+#if INCLUDE_COUNTERSIGNATURE1
+	{
+		//  Countersign on Signed Body
+
+		//  Validate counter signatures on signers
+		cn_cbor *countersignList = cn_cbor_mapget_string(pSign, "countersign0");
+		if (countersignList != nullptr) {
+			cn_cbor *countersigners =
+				cn_cbor_mapget_string(countersignList, "signers");
+			if (countersigners == nullptr) {
+				return 0;
+			}
+			size_t count = countersigners->length;
+			bool forward = true;
+
+			if (COSE_Sign1_map_get_int(hSig, COSE_Header_CounterSign1,
+					COSE_UNPROTECT_ONLY, nullptr) == nullptr) {
+				return 0;
+			}
+
+			for (size_t counterNo = 0; counterNo < count; counterNo++) {
+				bool noSignAlg = false;
+
+				Safe_HCOSE_COUNTERSIGN1 h = COSE_Sign1_get_countersignature1(
+					hSig, nullptr);
+				if (h == nullptr) {
+					return 0;
+				}
+
+				cn_cbor *counterSigner = cn_cbor_index(countersigners,
+					static_cast<int>(
+						forward ? counterNo : count - counterNo - 1));
+
+				Safe_HCOSE_KEY hkeyCountersign = BuildKey(
+					cn_cbor_mapget_string(counterSigner, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					return 0;
+				}
+
+				if (!COSE_CounterSign1_SetKey(h, hkeyCountersign, nullptr)) {
+					return 0;
+				}
+
+				if (!SetReceivingAttributes(h, counterSigner, Attributes_Countersign1_protected)) {
+					return 0;
+				}
+
+				if (COSE_Sign1_CounterSign1_validate(hSig, h, &coseError)) {
+					//  I don't think we have any forced errors yet.
+				}
+				else {
+					if (coseError.err == COSE_ERR_UNKNOWN_ALGORITHM) {
+						return 1;
+					}
+
+					if (forward && counterNo == 0 && count > 1) {
+						forward = false;
+						counterNo -= 1;
+					}
+					else {
+						return 0;
+					}
+				}
+			}
 		}
 	}
-	goto exitHere;
+#endif
+	
+	return returnCode;
 }
 
-int ValidateSign1(const cn_cbor *pControl)
+bool ValidateSign1(const cn_cbor *pControl)
 {
 	int cbEncoded = 0;
 	byte *pbEncoded = GetCBOREncoding(pControl, &cbEncoded);
 
-	return _ValidateSign1(pControl, pbEncoded, cbEncoded);
+	int i = _ValidateSign1(pControl, pbEncoded, cbEncoded);
+	if (i == 0) {
+		CFails += 1;
+	}
+
+	return i == 2;
 }
 
-int BuildSign1Message(const cn_cbor *pControl)
+bool BuildSign1Message(const cn_cbor *pControl)
 {
-	cn_cbor *pkey = nullptr;	
 	//
 	//  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 != nullptr) && (pFail->type == CN_CBOR_TRUE)) {
-		return 0;
+		return false;
 	}
 
-	HCOSE_SIGN1 hSignObj =
+	Safe_HCOSE_SIGN1 hSignObj =
 		COSE_Sign1_Init(COSE_INIT_FLAGS_NONE, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
 	const cn_cbor *pInputs = cn_cbor_mapget_string(pControl, "input");
 	if (pInputs == nullptr) {
 	returnError:
-		if (hSignObj != nullptr) {
-			COSE_Sign1_Free(hSignObj);
-		}
-		if (pkey != nullptr) {
-			CN_CBOR_FREE(pkey, context);
-		}
 		CFails += 1;
-		return 1;
+		return false;
 	}
 	const cn_cbor *pSign = cn_cbor_mapget_string(pInputs, "sign0");
 	if (pSign == nullptr) {
@@ -807,76 +947,109 @@
 		goto returnError;
 	}
 
-	if (!SetSendingAttributes(
-			(HCOSE)hSignObj, pSign, Attributes_Sign1_protected)) {
+	if (!SetSendingAttributes(hSignObj, pSign, Attributes_Sign1_protected)) {
 		goto returnError;
 	}
 
-	pkey = BuildKey(cn_cbor_mapget_string(pSign, "key"), false);
-	if (pkey == nullptr) {
+	Safe_HCOSE_KEY hkey = BuildKey(cn_cbor_mapget_string(pSign, "key"), false);
+	if (hkey == nullptr) {
 		goto returnError;
 	}
 
 #if INCLUDE_COUNTERSIGNATURE
-	// On the sign body
-	cn_cbor *countersigns = cn_cbor_mapget_string(pSign, "countersign");
-	if (countersigns != nullptr) {
-		countersigns = cn_cbor_mapget_string(countersigns, "signers");
-		cn_cbor *countersign = countersigns->first_child;
+	{
+		// On the sign body
+		cn_cbor *countersigns = cn_cbor_mapget_string(pSign, "countersign");
+		if (countersigns != nullptr) {
+			countersigns = cn_cbor_mapget_string(countersigns, "signers");
+			cn_cbor *countersign = countersigns->first_child;
 
-		for (; countersign != nullptr; countersign = countersign->next) {
-			cn_cbor *pkeyCountersign =
-				BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
-			if (pkeyCountersign == nullptr) {
-				goto returnError;
+			for (; countersign != nullptr; countersign = countersign->next) {
+				Safe_HCOSE_KEY hkeyCountersign =
+					BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					goto returnError;
+				}
+
+				Safe_HCOSE_COUNTERSIGN hCountersign =
+					COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+				if (hCountersign == nullptr) {
+					goto returnError;
+				}
+
+				if (!SetSendingAttributes(hCountersign, countersign,
+						Attributes_Countersign_protected)) {
+					goto returnError;
+				}
+
+				if (!COSE_CounterSign_SetKey2(
+						hCountersign, hkeyCountersign, nullptr)) {
+					goto returnError;
+				}
+
+				if (!COSE_Sign1_add_countersignature(
+						hSignObj, hCountersign, nullptr)) {
+					goto returnError;
+				}
 			}
-
-			HCOSE_COUNTERSIGN hCountersign =
-				COSE_CounterSign_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
-			if (hCountersign == nullptr) {
-				goto returnError;
-			}
-
-			if (!SetSendingAttributes((HCOSE)hCountersign, countersign,
-					Attributes_Countersign_protected)) {
-				COSE_CounterSign_Free(hCountersign);
-				goto returnError;
-			}
-
-			if (!COSE_CounterSign_SetKey(hCountersign, pkeyCountersign, nullptr)) {
-				COSE_CounterSign_Free(hCountersign);
-				goto returnError;
-			}
-
-			if (!COSE_Sign1_add_countersignature(
-					hSignObj, hCountersign, nullptr)) {
-				COSE_CounterSign_Free(hCountersign);
-				goto returnError;
-			}
-
-			COSE_CounterSign_Free(hCountersign);
 		}
 	}
-
 #endif
 
-	if (!COSE_Sign1_Sign(hSignObj, pkey, nullptr)) {
+#if INCLUDE_COUNTERSIGNATURE1
+	{
+		// On the sign body
+		cn_cbor *countersigns = cn_cbor_mapget_string(pSign, "countersign0");
+		if (countersigns != nullptr) {
+			countersigns = cn_cbor_mapget_string(countersigns, "signers");
+			cn_cbor *countersign = countersigns->first_child;
+
+			for (; countersign != nullptr; countersign = countersign->next) {
+				Safe_HCOSE_KEY hkeyCountersign =
+					BuildKey(cn_cbor_mapget_string(countersign, "key"), false);
+				if (hkeyCountersign == nullptr) {
+					goto returnError;
+				}
+
+				Safe_HCOSE_COUNTERSIGN1 hCountersign =
+					COSE_CounterSign1_Init(CBOR_CONTEXT_PARAM_COMMA nullptr);
+				if (hCountersign == nullptr) {
+					goto returnError;
+				}
+
+				if (!SetSendingAttributes(hCountersign, countersign,
+						Attributes_Countersign1_protected)) {
+					goto returnError;
+				}
+
+				if (!COSE_CounterSign1_SetKey(
+						hCountersign, hkeyCountersign, nullptr)) {
+					goto returnError;
+				}
+
+				if (!COSE_Sign1_add_countersignature1(
+						hSignObj, hCountersign, nullptr)) {
+					goto returnError;
+				}
+			}
+		}
+	}
+#endif
+
+	if (!COSE_Sign1_Sign2(hSignObj, hkey, nullptr)) {
 		goto returnError;
 	}
 
-	size_t cb = COSE_Encode((HCOSE)hSignObj, nullptr, 0, 0) + 1;
-	byte *rgb = (byte *)malloc(cb);
-	cb = COSE_Encode((HCOSE)hSignObj, rgb, 0, cb);
+	size_t cb = COSE_Encode(hSignObj.ToCOSE(), nullptr, 0, 0) + 1;
+	std::unique_ptr<byte> rgb(new byte[cb]);
+	cb = COSE_Encode(hSignObj.ToCOSE(), rgb.get(), 0, cb);
 
-	COSE_Sign1_Free(hSignObj);
-	if (pkey != nullptr) {
-		CN_CBOR_FREE(pkey, context);
+	int f = _ValidateSign1(pControl, rgb.get(), cb);
+	if (f == 0) {
+		CFails += 1;
 	}
 
-	int f = _ValidateSign1(pControl, rgb, cb);
-
-	free(rgb);
-	return f;
+	return f == 2;
 }
 #endif
 
@@ -913,9 +1086,9 @@
 	//  Incorrect algorithm
 
 	//  bad handle checks
-	//      null handle
+	//      nullptr handle
 	//      wrong type of handle
-	//  Null handle checks
+	//  nullptr handle checks
 
 	CHECK_FAILURE(
 		COSE_Sign_SetContent(hSignNULL, rgb, sizeof(rgb), &cose_error),
@@ -925,15 +1098,16 @@
 	CHECK_FAILURE(COSE_Sign_SetContent(hSign, nullptr, sizeof(rgb), &cose_error),
 		COSE_ERR_INVALID_PARAMETER, CFails++);
 
-	CHECK_FAILURE(COSE_Sign_map_get_int(hSignNULL, 1, COSE_BOTH, &cose_error),
+	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),
+	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),
@@ -1113,9 +1287,9 @@
 #endif
 
 	//  Look for invalid parameter
-	//		Null handle checks
+	//		nullptr handle checks
 	//		bad handle checks
-	//		null pointers
+	//		nullptr pointers
 
 	CHECK_FAILURE(COSE_Sign1_SetContent(hSignNULL, rgb, 10, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
@@ -1124,7 +1298,8 @@
 	CHECK_FAILURE(COSE_Sign1_SetContent(hSign, nullptr, 10, &cose_error),
 		COSE_ERR_INVALID_PARAMETER, CFails++);
 
-	CHECK_FAILURE(COSE_Sign1_map_get_int(hSignNULL, 1, COSE_BOTH, &cose_error),
+	CHECK_FAILURE(
+		COSE_Sign1_map_get_int(hSignNULL, 1, COSE_BOTH, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
 	CHECK_FAILURE(COSE_Sign1_map_get_int(hSignBad, 1, COSE_BOTH, &cose_error),
 		COSE_ERR_INVALID_HANDLE, CFails++);
diff --git a/test/context.cpp b/test/context.cpp
index a604612..14ce7c4 100644
--- a/test/context.cpp
+++ b/test/context.cpp
@@ -28,10 +28,10 @@
 
 bool CheckMemory(MyContext *pContext)
 {
-	MyItem *p = NULL;
+	MyItem *p = nullptr;
 	//  Walk memory and check every block
 
-	for (p = (MyItem *)pContext->pFirst; p != NULL; p = p->pNext) {
+	for (p = (MyItem *)pContext->pFirst; p != nullptr; p = p->pNext) {
 		if (p->pad[0] == (byte)0xab) {
 			//  Block has been freed
 			for (unsigned i = 0; i < p->size + 8; i++) {
@@ -61,14 +61,14 @@
 
 void *MyCalloc(size_t count, size_t size, void *context)
 {
-	MyItem *pb = NULL;
+	MyItem *pb = nullptr;
 	MyContext *myContext = (MyContext *)context;
 
 	CheckMemory(myContext);
 
 	if (myContext->iFailLeft != -1) {
 		if (myContext->iFailLeft == 0) {
-			return NULL;
+			return nullptr;
 		}
 		myContext->iFailLeft--;
 	}
@@ -90,23 +90,29 @@
 {
 	MyItem *pb = (MyItem *)((byte *)ptr - sizeof(MyItem) + 4);
 	MyContext *myContext = (MyContext *)context;
-	MyItem *pItem = NULL;
+	MyItem *pItem = nullptr;
 
 	CheckMemory(myContext);
-	if (ptr == NULL) {
+	if (ptr == nullptr) {
 		return;
 	}
 
-	for (pItem = (MyItem *)myContext->pFirst; pItem != NULL;
+	for (pItem = (MyItem *)myContext->pFirst; pItem != nullptr;
 		 pItem = pItem->pNext) {
 		if (pItem == pb) {
 			break;
 		}
 	}
 
-	if (pItem == NULL) {
+	if (pItem == nullptr) {
 		//  Not an item we allocated
 		assert(false);
+		return;
+	}
+
+	if (pItem->pad[0] == (byte) 0xab) {
+		//  already freed.
+		assert(false);
 	}
 
 	memset(&pb->pad, 0xab, pb->size + 8);
@@ -114,12 +120,12 @@
 
 cn_cbor_context *CreateContext(int iFailPoint)
 {
-	MyContext *p = (MyContext*) malloc(sizeof(MyContext));
+	MyContext *p = (MyContext *)malloc(sizeof(MyContext));
 
 	p->context.calloc_func = MyCalloc;
 	p->context.free_func = MyFree;
 	p->context.context = p;
-	p->pFirst = NULL;
+	p->pFirst = nullptr;
 	p->iFailLeft = iFailPoint;
 	p->allocCount = 0;
 
@@ -134,7 +140,7 @@
 
 	CheckMemory(myContext);
 
-	for (pItem = (MyItem *)myContext->pFirst; pItem != NULL; pItem = pItem2) {
+	for (pItem = (MyItem *)myContext->pFirst; pItem != nullptr; pItem = pItem2) {
 		pItem2 = pItem->pNext;
 		free(pItem);
 	}
@@ -149,7 +155,7 @@
 
 	//  Walk memory and check every block
 
-	for (MyItem *p = (MyItem *)myContext->pFirst; p != NULL; p = p->pNext) {
+	for (MyItem *p = (MyItem *)myContext->pFirst; p != nullptr; p = p->pNext) {
 		if (p->pad[0] == (byte)0xab) {
 			//  Block has been freed
 		}
diff --git a/test/json.cpp b/test/json.cpp
index d4ca613..24db8aa 100644
--- a/test/json.cpp
+++ b/test/json.cpp
@@ -152,7 +152,7 @@
 		return NULL;
 	}
 
-	rgch = (char*) malloc(8 * 1024);
+	rgch = (char *)malloc(8 * 1024);
 	cch = (int)fread(rgch, 1, 8 * 1024, fp);
 	fclose(fp);
 
@@ -175,7 +175,7 @@
 {
 	*output_length = 4 * ((input_length + 2) / 3);
 
-	char *encoded_data = (char*) malloc(*output_length);
+	char *encoded_data = (char *)malloc(*output_length);
 	if (encoded_data == NULL) {
 		return NULL;
 	}
@@ -212,7 +212,7 @@
 
 	if (input_length % 4 != 0) {
 		int c = 4 - (input_length % 4);
-		p = (char*) malloc(input_length + c);
+		p = (char *)malloc(input_length + c);
 		memcpy(p, data, input_length);
 		memcpy(p + input_length, "====", c);
 		input_length += c;
@@ -265,7 +265,7 @@
 
 static void build_decoding_table()
 {
-	decoding_table = (unsigned char *) malloc(256);
+	decoding_table = (unsigned char *)malloc(256);
 
 	for (int i = 0; i < 64; i++) {
 		decoding_table[(int)encoding_table[i]] = (unsigned char)i;
@@ -287,7 +287,7 @@
 
 	*output_length = input_length / 2;
 
-	unsigned char *decoded_data = (unsigned char *) malloc(*output_length);
+	unsigned char *decoded_data = (unsigned char *)malloc(*output_length);
 	if (decoded_data == NULL) {
 		return NULL;
 	}
diff --git a/test/test.cpp b/test/test.cpp
index c01e684..6c1c0f5 100644
--- a/test/test.cpp
+++ b/test/test.cpp
@@ -26,7 +26,7 @@
 #endif
 
 #ifdef USE_CBOR_CONTEXT
-cn_cbor_context * context;
+cn_cbor_context* context;
 #endif
 
 int CFails = 0;
@@ -126,7 +126,7 @@
 byte* FromHex(const char* rgch, int cch)
 {
 	// M00BUG - Why is this using malloc?  It does not get freed anyplace.
-	byte* pb = (byte*) malloc(cch / 2);
+	byte* pb = (byte*)malloc(cch / 2);
 	const char* pb2 = rgch;
 
 	for (int i = 0; i < cch; i += 2) {
@@ -277,17 +277,17 @@
 byte* GetCBOREncoding(const cn_cbor* pControl, int* pcbEncoded)
 {
 	const cn_cbor* pOutputs = cn_cbor_mapget_string(pControl, "output");
-	byte* pb = NULL;
+	byte* pb = nullptr;
 	const byte* pb2;
 	size_t i;
 
-	if ((pOutputs == NULL) || (pOutputs->type != CN_CBOR_MAP)) {
+	if ((pOutputs == nullptr) || (pOutputs->type != CN_CBOR_MAP)) {
 		fprintf(stderr, "Invalid output\n");
 		exit(1);
 	}
 
 	const cn_cbor* pCBOR = cn_cbor_mapget_string(pOutputs, "cbor");
-	if ((pCBOR == NULL) || (pCBOR->type != CN_CBOR_TEXT)) {
+	if ((pCBOR == nullptr) || (pCBOR->type != CN_CBOR_TEXT)) {
 		fprintf(stderr, "Invalid cbor object");
 		exit(1);
 	}
@@ -331,18 +331,18 @@
 	bool fPublicKey)
 {
 	int keyNew = 0;
-	cn_cbor* pValueNew = NULL;
 	bool fRet = true;
 
-	if (pAttributes == NULL) {
+	if (pAttributes == nullptr) {
 		return true;
 	}
 	if (pAttributes->type != CN_CBOR_MAP) {
 		return false;
 	}
 
-	for (const cn_cbor* pKey = pAttributes->first_child; pKey != NULL;
+	for (const cn_cbor* pKey = pAttributes->first_child; pKey != nullptr;
 		 pKey = pKey->next->next) {
+		Safe_CN_CBOR pValueNew = nullptr;
 		const cn_cbor* pValue = pKey->next;
 
 		if (pKey->type != CN_CBOR_TEXT) {
@@ -352,12 +352,12 @@
 		if (strcmp(pKey->v.str, "alg") == 0) {
 			keyNew = COSE_Header_Algorithm;
 			pValueNew = cn_cbor_int_create(
-				MapAlgorithmName(pValue), CBOR_CONTEXT_PARAM_COMMA NULL);
+				MapAlgorithmName(pValue), CBOR_CONTEXT_PARAM_COMMA nullptr);
 		}
 		else if (strcmp(pKey->v.str, "ctyp") == 0) {
 			keyNew = COSE_Header_Content_Type;
-			pValueNew = cn_cbor_clone(pValue, CBOR_CONTEXT_PARAM_COMMA NULL);
-			if (pValueNew == NULL) {
+			pValueNew = cn_cbor_clone(pValue, CBOR_CONTEXT_PARAM_COMMA nullptr);
+			if (pValueNew == nullptr) {
 				return false;
 			}
 		}
@@ -365,44 +365,53 @@
 			keyNew = COSE_Header_IV;
 			pValueNew =
 				cn_cbor_data_create(FromHex(pValue->v.str, (int)pValue->length),
-					(int)pValue->length / 2, CBOR_CONTEXT_PARAM_COMMA NULL);
+					(int)pValue->length / 2, CBOR_CONTEXT_PARAM_COMMA nullptr);
 		}
 		else if (strcmp(pKey->v.str, "apu_id") == 0) {
 			keyNew = COSE_Header_KDF_U_name;
 			pValueNew = cn_cbor_data_create(pValue->v.bytes,
-				(int)pValue->length, CBOR_CONTEXT_PARAM_COMMA NULL);
-			if (pValueNew == NULL) {
+				(int)pValue->length, CBOR_CONTEXT_PARAM_COMMA nullptr);
+			if (pValueNew == nullptr) {
 				return false;
 			}
 		}
 		else if (strcmp(pKey->v.str, "apv_id") == 0) {
 			keyNew = COSE_Header_KDF_V_name;
 			pValueNew = cn_cbor_data_create(pValue->v.bytes,
-				(int)pValue->length, CBOR_CONTEXT_PARAM_COMMA NULL);
-			if (pValueNew == NULL) {
+				(int)pValue->length, CBOR_CONTEXT_PARAM_COMMA nullptr);
+			if (pValueNew == nullptr) {
 				return false;
 			}
 		}
 		else if (strcmp(pKey->v.str, "pub_other") == 0) {
 			keyNew = COSE_Header_KDF_PUB_other;
 			pValueNew = cn_cbor_data_create(pValue->v.bytes,
-				(int)pValue->length, CBOR_CONTEXT_PARAM_COMMA NULL);
-			if (pValueNew == NULL) {
+				(int)pValue->length, CBOR_CONTEXT_PARAM_COMMA nullptr);
+			if (pValueNew == nullptr) {
 				return false;
 			}
 		}
 		else if (strcmp(pKey->v.str, "priv_other") == 0) {
 			keyNew = COSE_Header_KDF_PRIV;
 			pValueNew = cn_cbor_data_create(pValue->v.bytes,
-				(int)pValue->length, CBOR_CONTEXT_PARAM_COMMA NULL);
-			if (pValueNew == NULL) {
+				(int)pValue->length, CBOR_CONTEXT_PARAM_COMMA nullptr);
+			if (pValueNew == nullptr) {
 				return false;
 			}
 		}
 		else if (strcmp(pKey->v.str, "spk") == 0) {
 			keyNew = COSE_Header_ECDH_STATIC;
-			pValueNew = BuildKey(pValue, fPublicKey);
-			if (pValueNew == NULL) {
+			pValueNew = BuildCborKey(pValue, fPublicKey);
+			if (pValueNew == nullptr) {
+				return false;
+			}
+		}
+		else if (strcmp(pKey->v.str, "compressed") == 0) {
+			keyNew = COSE_Header_UseCompressedECDH;
+			pValueNew = cn_cbor_bool_create(
+				pValue->v.sint == 1 ? true
+									: false, CBOR_CONTEXT_PARAM_COMMA nullptr);
+			if (pValueNew == nullptr) {
 				return false;
 			}
 		}
@@ -414,70 +423,83 @@
 #if INCLUDE_MAC
 			case Attributes_MAC_protected:
 				fRet &= COSE_Mac_map_put_int(
-					(HCOSE_MAC)hHandle, keyNew, pValueNew, which, NULL);
+					(HCOSE_MAC)hHandle, keyNew, pValueNew, which, nullptr);
 				break;
 #endif
 
 #if INCLUDE_MAC0
 			case Attributes_MAC0_protected:
 				fRet &= COSE_Mac0_map_put_int(
-					(HCOSE_MAC0)hHandle, keyNew, pValueNew, which, NULL);
+					(HCOSE_MAC0)hHandle, keyNew, pValueNew, which, nullptr);
 				break;
 #endif
 
 #if INCLUDE_ENCRYPT || INCLUDE_MAC
 			case Attributes_Recipient_protected:
-				fRet &= COSE_Recipient_map_put_int(
-					(HCOSE_RECIPIENT)hHandle, keyNew, pValueNew, which, NULL);
+				fRet &= COSE_Recipient_map_put_int((HCOSE_RECIPIENT)hHandle,
+					keyNew, pValueNew, which, nullptr);
 				break;
 #endif
 
 #if INCLUDE_ENCRYPT
 			case Attributes_Enveloped_protected:
-				fRet &= COSE_Enveloped_map_put_int(
-					(HCOSE_ENVELOPED)hHandle, keyNew, pValueNew, which, NULL);
+				fRet &= COSE_Enveloped_map_put_int((HCOSE_ENVELOPED)hHandle,
+					keyNew, pValueNew, which, nullptr);
 				break;
 #endif
 
 #if INCLUDE_ENCRYPT0
 			case Attributes_Encrypt_protected:
 				fRet &= COSE_Encrypt_map_put_int(
-					(HCOSE_ENCRYPT)hHandle, keyNew, pValueNew, which, NULL);
+					(HCOSE_ENCRYPT)hHandle, keyNew, pValueNew, which, nullptr);
 				break;
 #endif
 
 #if INCLUDE_SIGN
 			case Attributes_Sign_protected:
 				fRet &= COSE_Sign_map_put_int(
-					(HCOSE_SIGN)hHandle, keyNew, pValueNew, which, NULL);
+					(HCOSE_SIGN)hHandle, keyNew, pValueNew, which, nullptr);
 				break;
 #endif
 
 #if INCLUDE_SIGN
 			case Attributes_Signer_protected:
 				fRet &= COSE_Signer_map_put_int(
-					(HCOSE_SIGNER)hHandle, keyNew, pValueNew, which, NULL);
+					(HCOSE_SIGNER)hHandle, keyNew, pValueNew, which, nullptr);
 				break;
 #endif
 
 #if INCLUDE_SIGN1
 			case Attributes_Sign1_protected:
 				fRet &= COSE_Sign1_map_put_int(
-					(HCOSE_SIGN1)hHandle, keyNew, pValueNew, which, NULL);
+					(HCOSE_SIGN1)hHandle, keyNew, pValueNew, which, nullptr);
 				break;
 #endif
 
 #if INCLUDE_COUNTERSIGNATURE
 			case Attributes_Countersign_protected:
-				fRet &= COSE_CounterSign_map_put_int(
-					(HCOSE_COUNTERSIGN)hHandle, keyNew, pValueNew, which, NULL);
+				fRet &= COSE_CounterSign_map_put_int((HCOSE_COUNTERSIGN)hHandle,
+					keyNew, pValueNew, which, nullptr);
+				break;
+#endif
+
+#if INCLUDE_COUNTERSIGNATURE1
+			case Attributes_Countersign1_protected:
+				fRet &=
+					COSE_CounterSign1_map_put_int((HCOSE_COUNTERSIGN1)hHandle,
+						keyNew, pValueNew, which, nullptr);
 				break;
 #endif
 
 			default:
+				fRet = false;
 				assert(false);
 				break;
 		}
+		
+		if (fRet) {
+			pValueNew.Clear();
+		}
 		//  If you uncomment this then the memory test will fail.
 		// assert(fRet);
 	}
@@ -485,9 +507,10 @@
 	return fRet;
 }
 
-bool SetSendingAttributes(HCOSE hMsg, const cn_cbor* pIn, int base)
+bool SetSendingAttributes(void* pMsg, const cn_cbor* pIn, int base)
 {
 	bool f = false;
+	const HCOSE hMsg = static_cast<HCOSE>(pMsg);
 
 	if (!SetAttributes(hMsg, cn_cbor_mapget_string(pIn, "protected"),
 			COSE_PROTECT_ONLY, base, true)) {
@@ -503,9 +526,9 @@
 	}
 
 	cn_cbor* pExternal = cn_cbor_mapget_string(pIn, "external");
-	if (pExternal != NULL) {
+	if (pExternal != nullptr) {
 		cn_cbor* pcn = pExternal;
-		if (pcn == NULL) {
+		if (pcn == nullptr) {
 			return false;
 		}
 		switch (base) {
@@ -513,7 +536,7 @@
 			case Attributes_Encrypt_protected:
 				if (!COSE_Encrypt_SetExternal((HCOSE_ENCRYPT)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -523,7 +546,7 @@
 			case Attributes_Enveloped_protected:
 				if (!COSE_Enveloped_SetExternal((HCOSE_ENVELOPED)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -533,7 +556,7 @@
 			case Attributes_MAC_protected:
 				if (!COSE_Mac_SetExternal((HCOSE_MAC)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -543,7 +566,7 @@
 			case Attributes_MAC0_protected:
 				if (!COSE_Mac0_SetExternal((HCOSE_MAC0)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -553,7 +576,7 @@
 			case Attributes_Signer_protected:
 				if (!COSE_Signer_SetExternal((HCOSE_SIGNER)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -563,7 +586,7 @@
 			case Attributes_Sign1_protected:
 				if (!COSE_Sign1_SetExternal((HCOSE_SIGN1)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -572,7 +595,7 @@
 			case Attributes_Countersign_protected:
 				if (!COSE_CounterSign_SetExternal((HCOSE_COUNTERSIGN)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -586,9 +609,10 @@
 	return true;
 }
 
-bool SetReceivingAttributes(HCOSE hMsg, const cn_cbor* pIn, int base)
+bool SetReceivingAttributes(void* pMsg, const cn_cbor* pIn, int base)
 {
 	bool f = false;
+	HCOSE hMsg = static_cast<HCOSE>(pMsg);
 
 	if (!SetAttributes(hMsg, cn_cbor_mapget_string(pIn, "unsent"),
 			COSE_DONT_SEND, base, true)) {
@@ -596,18 +620,17 @@
 	}
 
 	cn_cbor* pExternal = cn_cbor_mapget_string(pIn, "external");
-	if (pExternal != NULL) {
+	if (pExternal != nullptr) {
 		cn_cbor* pcn = pExternal;
-		if (pcn == NULL) {
+		if (pcn == nullptr) {
 			return false;
 		}
 		switch (base) {
-			
 #if INCLUDE_ENCRYPT0
 			case Attributes_Encrypt_protected:
 				if (!COSE_Encrypt_SetExternal((HCOSE_ENCRYPT)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -617,7 +640,7 @@
 			case Attributes_Enveloped_protected:
 				if (!COSE_Enveloped_SetExternal((HCOSE_ENVELOPED)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -627,7 +650,7 @@
 			case Attributes_MAC_protected:
 				if (!COSE_Mac_SetExternal((HCOSE_MAC)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -637,7 +660,7 @@
 			case Attributes_MAC0_protected:
 				if (!COSE_Mac0_SetExternal((HCOSE_MAC0)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -647,7 +670,7 @@
 			case Attributes_Signer_protected:
 				if (!COSE_Signer_SetExternal((HCOSE_SIGNER)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -657,7 +680,7 @@
 			case Attributes_Sign1_protected:
 				if (!COSE_Sign1_SetExternal((HCOSE_SIGN1)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -666,7 +689,16 @@
 			case Attributes_Countersign_protected:
 				if (!COSE_CounterSign_SetExternal((HCOSE_COUNTERSIGN)hMsg,
 						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
-						NULL)) {
+						nullptr)) {
+					return false;
+				}
+				break;
+#endif
+#if INCLUDE_COUNTERSIGNATURE1
+			case Attributes_Countersign1_protected:
+				if (!COSE_CounterSign1_SetExternal((HCOSE_COUNTERSIGN1)hMsg,
+						FromHex(pcn->v.str, (int)pcn->length), pcn->length / 2,
+						nullptr)) {
 					return false;
 				}
 				break;
@@ -677,31 +709,29 @@
 	return true;
 }
 
-cn_cbor* BuildKey(const cn_cbor* pKeyIn, bool fPublicKey)
+cn_cbor* BuildCborKey(const cn_cbor* pKeyIn, bool fPublicKey)
 {
-	cn_cbor* pKeyOut = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA NULL);
+	Safe_CN_CBOR pKeyOut = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA nullptr);
 	cn_cbor* pKty = cn_cbor_mapget_string(pKeyIn, "kty");
-	cn_cbor* p = NULL;
-	cn_cbor* pKey = NULL;
-	cn_cbor* pValue = NULL;
+	cn_cbor* pKey = nullptr;
 	size_t i;
 	int kty;
-	unsigned char* pb = NULL;
+	unsigned char* pb = nullptr;
 	size_t cb;
 
-	if (pKeyOut == NULL) {
-		return NULL;
+	if (pKeyOut == nullptr) {
+		return nullptr;
 	}
 
-	if ((pKty == NULL) || (pKty->type != CN_CBOR_TEXT)) {
-		return NULL;
+	if ((pKty == nullptr) || (pKty->type != CN_CBOR_TEXT)) {
+		return nullptr;
 	}
 	if (pKty->length == 2) {
 		if (strncmp(pKty->v.str, "EC", 2) == 0) {
 			kty = 2;
 		}
 		else {
-			return NULL;
+			return nullptr;
 		}
 	}
 	else if (pKty->length == 3) {
@@ -712,23 +742,24 @@
 			kty = COSE_Key_Type_OKP;
 		}
 		else {
-			return NULL;
+			return nullptr;
 		}
 	}
 	else {
-		return NULL;
+		return nullptr;
 	}
 
-	p = cn_cbor_int_create(kty, CBOR_CONTEXT_PARAM_COMMA NULL);
-	if (p == NULL) {
-		return NULL;
+	Safe_CN_CBOR p = cn_cbor_int_create(kty, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	if (p == nullptr) {
+		return nullptr;
 	}
-	if (!cn_cbor_mapput_int(pKeyOut, 1, p, CBOR_CONTEXT_PARAM_COMMA NULL)) {
-		return NULL;
+	if (!cn_cbor_mapput_int(pKeyOut, 1, p, CBOR_CONTEXT_PARAM_COMMA nullptr)) {
+		return nullptr;
 	}
+	p.Clear();
 
-	for (pKey = pKeyIn->first_child; pKey != NULL; pKey = pKey->next->next) {
-		pValue = pKey->next;
+	for (pKey = pKeyIn->first_child; pKey != nullptr; pKey = pKey->next->next) {
+		cn_cbor* pValue = pKey->next;
 
 		if (pKey->type == CN_CBOR_TEXT) {
 			for (i = 0; i < sizeof(RgStringKeys) / sizeof(RgStringKeys[0]);
@@ -738,17 +769,19 @@
 						 strlen(RgStringKeys[i].szKey)) == 0) &&
 					((RgStringKeys[i].kty == 0) ||
 						(RgStringKeys[i].kty == kty))) {
+					Safe_CN_CBOR pValueNew;
+					
 					switch (RgStringKeys[i].operation) {
 						case OPERATION_NONE:
-							p = cn_cbor_clone(
-								pValue, CBOR_CONTEXT_PARAM_COMMA NULL);
-							if (p == NULL) {
-								return NULL;
+							pValueNew = cn_cbor_clone(
+								pValue, CBOR_CONTEXT_PARAM_COMMA nullptr);
+							if (pValueNew == nullptr) {
+								return nullptr;
 							}
 							if (!cn_cbor_mapput_int(pKeyOut,
-									RgStringKeys[i].keyNew, p,
-									CBOR_CONTEXT_PARAM_COMMA NULL)) {
-								return NULL;
+									RgStringKeys[i].keyNew, pValueNew,
+									CBOR_CONTEXT_PARAM_COMMA nullptr)) {
+								return nullptr;
 							}
 							break;
 
@@ -759,29 +792,29 @@
 
 							pb = base64_decode(
 								pValue->v.str, pValue->length, &cb);
-							p = cn_cbor_data_create(
-								pb, (int)cb, CBOR_CONTEXT_PARAM_COMMA NULL);
-							if (p == NULL) {
-								return NULL;
+							pValueNew = cn_cbor_data_create(
+								pb, (int)cb, CBOR_CONTEXT_PARAM_COMMA nullptr);
+							if (pValueNew == nullptr) {
+								return nullptr;
 							}
 							if (!cn_cbor_mapput_int(pKeyOut,
-									RgStringKeys[i].keyNew, p,
-									CBOR_CONTEXT_PARAM_COMMA NULL)) {
-								return NULL;
+									RgStringKeys[i].keyNew, pValueNew,
+									CBOR_CONTEXT_PARAM_COMMA nullptr)) {
+								return nullptr;
 							}
 							break;
 
 						case OPERATION_STRING:
-							p = cn_cbor_int_create(MapName(pValue, RgCurveNames,
+							pValueNew = cn_cbor_int_create(MapName(pValue, RgCurveNames,
 													   _countof(RgCurveNames)),
-								CBOR_CONTEXT_PARAM_COMMA NULL);
-							if (p == NULL) {
-								return NULL;
+								CBOR_CONTEXT_PARAM_COMMA nullptr);
+							if (pValueNew == nullptr) {
+								return nullptr;
 							}
 							if (!cn_cbor_mapput_int(pKeyOut,
-									RgStringKeys[i].keyNew, p,
-									CBOR_CONTEXT_PARAM_COMMA NULL)) {
-								return NULL;
+									RgStringKeys[i].keyNew, pValueNew,
+									CBOR_CONTEXT_PARAM_COMMA nullptr)) {
+								return nullptr;
 							}
 							break;
 
@@ -791,25 +824,42 @@
 								continue;
 							}
 							pb = hex_decode(pValue->v.str, pValue->length, &cb);
-							p = cn_cbor_data_create(
-								pb, (int)cb, CBOR_CONTEXT_PARAM_COMMA NULL);
-							if (p == NULL) {
-								return NULL;
+							pValueNew = cn_cbor_data_create(
+								pb, (int)cb, CBOR_CONTEXT_PARAM_COMMA nullptr);
+							if (pValueNew == nullptr) {
+								return nullptr;
 							}
 							if (!cn_cbor_mapput_int(pKeyOut,
-									RgStringKeys[i].keyNew, p,
-									CBOR_CONTEXT_PARAM_COMMA NULL)) {
-								return NULL;
+									RgStringKeys[i].keyNew, pValueNew,
+									CBOR_CONTEXT_PARAM_COMMA nullptr)) {
+								return nullptr;
 							}
 							break;
 					}
+					pValueNew.Clear();
 					i = 99;
 				}
 			}
 		}
 	}
+	cn_cbor* pOut = pKeyOut;
+	pKeyOut.Clear();
+	return pOut;
+}
 
-	return pKeyOut;
+HCOSE_KEY BuildKey(const cn_cbor* pKeyIn, bool fPublicKey)
+{
+	cn_cbor* pKeyOut = BuildCborKey(pKeyIn, fPublicKey);
+	if (pKeyOut == nullptr) {
+		return nullptr;
+	}
+
+	cose_errback coseError;
+	HCOSE_KEY key = COSE_KEY_FromCbor(pKeyOut, CBOR_CONTEXT_PARAM_COMMA &coseError);
+	if (key == nullptr) {
+		CN_CBOR_FREE(pKeyOut, context);
+	}
+	return key;
 }
 
 bool Test_cn_cbor_array_replace()
@@ -820,23 +870,24 @@
 	//  Cases that are not currently covered
 	//  1.  Pass in invalid arguements
 
-	cn_cbor_array_replace(NULL, NULL, 0, CBOR_CONTEXT_PARAM_COMMA NULL);
+	cn_cbor_array_replace(
+		nullptr, nullptr, 0, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
 	//  2.  Insert 0 item with no items currently in the list
-	pRoot = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
-	pItem = cn_cbor_int_create(5, CBOR_CONTEXT_PARAM_COMMA NULL);
-	cn_cbor_array_replace(pRoot, pItem, 0, CBOR_CONTEXT_PARAM_COMMA NULL);
+	pRoot = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA nullptr);
+	pItem = cn_cbor_int_create(5, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	cn_cbor_array_replace(pRoot, pItem, 0, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
 	//  3. Insert 0 item w/ exactly one item in the list
-	pItem = cn_cbor_int_create(6, CBOR_CONTEXT_PARAM_COMMA NULL);
-	cn_cbor_array_replace(pRoot, pItem, 0, CBOR_CONTEXT_PARAM_COMMA NULL);
+	pItem = cn_cbor_int_create(6, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	cn_cbor_array_replace(pRoot, pItem, 0, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
 	//  4.  The last item in the array
-	pItem = cn_cbor_int_create(7, CBOR_CONTEXT_PARAM_COMMA NULL);
-	cn_cbor_array_replace(pRoot, pItem, 1, CBOR_CONTEXT_PARAM_COMMA NULL);
+	pItem = cn_cbor_int_create(7, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	cn_cbor_array_replace(pRoot, pItem, 1, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
-	pItem = cn_cbor_int_create(8, CBOR_CONTEXT_PARAM_COMMA NULL);
-	cn_cbor_array_replace(pRoot, pItem, 1, CBOR_CONTEXT_PARAM_COMMA NULL);
+	pItem = cn_cbor_int_create(8, CBOR_CONTEXT_PARAM_COMMA nullptr);
+	cn_cbor_array_replace(pRoot, pItem, 1, CBOR_CONTEXT_PARAM_COMMA nullptr);
 
 	return true;
 }
@@ -1171,7 +1222,7 @@
 #endif
 }
 
-typedef int (*ValidatePtr)(const cn_cbor* pControl);
+typedef bool (*ValidatePtr)(const cn_cbor* pControl);
 
 bool ProcessFile(const cn_cbor* pControl,
 	ValidatePtr validateFunction,
@@ -1220,13 +1271,13 @@
 
 static void RunFileTest(const char* szFileName)
 {
-	const cn_cbor*  pControl = ParseJson(szFileName);
+	const cn_cbor* pControl = ParseJson(szFileName);
 
 	//
 	//  If we are given a file name, then process the file name
 	//
 
-	if (pControl == NULL) {
+	if (pControl == nullptr) {
 		CFails += 1;
 		return;
 	}
@@ -1235,37 +1286,37 @@
 
 	const cn_cbor* pInput = cn_cbor_mapget_string(pControl, "input");
 
-	if ((pInput == NULL) || (pInput->type != CN_CBOR_MAP)) {
+	if ((pInput == nullptr) || (pInput->type != CN_CBOR_MAP)) {
 		fprintf(stderr, "No or bad input section");
 		exit(1);
 	}
 
-	if (cn_cbor_mapget_string(pInput, "mac") != NULL) {
+	if (cn_cbor_mapget_string(pInput, "mac") != nullptr) {
 #if INCLUDE_MAC
 		ProcessFile(pControl, ValidateMAC, BuildMacMessage);
 #endif
 	}
-	else if (cn_cbor_mapget_string(pInput, "mac0") != NULL) {
+	else if (cn_cbor_mapget_string(pInput, "mac0") != nullptr) {
 #if INCLUDE_MAC0
 		ProcessFile(pControl, ValidateMac0, BuildMac0Message);
 #endif
 	}
-	else if (cn_cbor_mapget_string(pInput, "enveloped") != NULL) {
+	else if (cn_cbor_mapget_string(pInput, "enveloped") != nullptr) {
 #if INCLUDE_ENCRYPT
 		ProcessFile(pControl, ValidateEnveloped, BuildEnvelopedMessage);
 #endif
 	}
-	else if (cn_cbor_mapget_string(pInput, "sign") != NULL) {
+	else if (cn_cbor_mapget_string(pInput, "sign") != nullptr) {
 #if INCLUDE_SIGN
 		ProcessFile(pControl, ValidateSigned, BuildSignedMessage);
 #endif
 	}
-	else if (cn_cbor_mapget_string(pInput, "sign0") != NULL) {
+	else if (cn_cbor_mapget_string(pInput, "sign0") != nullptr) {
 #if INCLUDE_SIGN1
 		ProcessFile(pControl, ValidateSign1, BuildSign1Message);
 #endif
 	}
-	else if (cn_cbor_mapget_string(pInput, "encrypted") != NULL) {
+	else if (cn_cbor_mapget_string(pInput, "encrypted") != nullptr) {
 #if INCLUDE_ENCRYPT0
 		ProcessFile(pControl, ValidateEncrypt, BuildEncryptMessage);
 #endif
@@ -1369,7 +1420,7 @@
 int main(int argc, char** argv)
 {
 	int i;
-	const char* szWhere = NULL;
+	const char* szWhere = nullptr;
 	bool fDir = false;
 	bool fCorners = false;
 	bool fMemory = false;
@@ -1402,14 +1453,14 @@
 	//
 
 	if (fMemory) {
-		if (szWhere == NULL) {
+		if (szWhere == nullptr) {
 			fprintf(stderr, "Must specify a file name\n");
 			exit(1);
 		}
 		RunMemoryTest(szWhere);
 	}
-	else if (szWhere != NULL) {
-		if (szWhere == NULL) {
+	else if (szWhere != nullptr) {
+		if (szWhere == nullptr) {
 			fprintf(stderr, "Must specify a file name\n");
 			exit(1);
 		}
@@ -1421,7 +1472,13 @@
 		}
 	}
 	else if (fCorners) {
+#ifdef USE_CBOR_CONTEXT
+		context = CreateContext(-1);
+#endif
 		RunCorners();
+#ifdef USE_CBOR_CONTEXT
+		FreeContext(context);
+#endif
 	}
 	else {
 #ifdef USE_CBOR_CONTEXT
diff --git a/test/test.h b/test/test.h
index 1da2d45..d756e38 100644
--- a/test/test.h
+++ b/test/test.h
@@ -4,6 +4,7 @@
 
 #include "cose/cose.h"
 #include "context.h"
+#include "cose_int.h"
 
 #ifdef USE_CBOR_CONTEXT
 extern cn_cbor_context* context;
@@ -16,11 +17,11 @@
 
 //  encrypt.c
 
-int ValidateEnveloped(const cn_cbor* pControl);
+bool ValidateEnveloped(const cn_cbor* pControl);
 int EncryptMessage();
-int BuildEnvelopedMessage(const cn_cbor* pControl);
-int ValidateEncrypt(const cn_cbor* pControl);
-int BuildEncryptMessage(const cn_cbor* pControl);
+bool BuildEnvelopedMessage(const cn_cbor* pControl);
+bool ValidateEncrypt(const cn_cbor* pControl);
+bool BuildEncryptMessage(const cn_cbor* pControl);
 void Enveloped_Corners();
 void Encrypt_Corners();
 void Recipient_Corners();
@@ -28,21 +29,21 @@
 
 //  sign.c
 
-int ValidateSigned(const cn_cbor* pControl);
+bool ValidateSigned(const cn_cbor* pControl);
 int SignMessage();
-int BuildSignedMessage(const cn_cbor* pControl);
-int ValidateSign1(const cn_cbor* pControl);
-int BuildSign1Message(const cn_cbor* pControl);
+bool BuildSignedMessage(const cn_cbor* pControl);
+bool ValidateSign1(const cn_cbor* pControl);
+bool BuildSign1Message(const cn_cbor* pControl);
 void Sign_Corners();
 void Sign1_Corners();
 
 // mac_testc
 
-int ValidateMAC(const cn_cbor* pControl);
+bool ValidateMAC(const cn_cbor* pControl);
 int MacMessage();
-int BuildMacMessage(const cn_cbor* pControl);
-int ValidateMac0(const cn_cbor* pControl);
-int BuildMac0Message(const cn_cbor* pControl);
+bool BuildMacMessage(const cn_cbor* pControl);
+bool ValidateMac0(const cn_cbor* pControl);
+bool BuildMac0Message(const cn_cbor* pControl);
 void MAC_Corners();
 void MAC0_Corners();
 
@@ -56,7 +57,8 @@
 	Attributes_Sign_protected,
 	Attributes_Signer_protected,
 	Attributes_Sign1_protected,
-	Attributes_Countersign_protected
+	Attributes_Countersign_protected,
+	Attributes_Countersign1_protected
 } whichSet;
 
 extern int CFails;
@@ -65,10 +67,11 @@
 byte* GetCBOREncoding(const cn_cbor* pControl, int* pcbEncoded);
 // bool SetAttributes(HCOSE hHandle, const cn_cbor * pAttributes, int which,
 // bool fPublicKey);
-cn_cbor* BuildKey(const cn_cbor* pKeyIn, bool fPublicKey);
+HCOSE_KEY BuildKey(const cn_cbor* pKeyIn, bool fPublicKey);
+cn_cbor* BuildCborKey(const cn_cbor* pKeyIn, bool fPublicKey);
 byte* FromHex(const char* rgch, int cch);
-bool SetSendingAttributes(HCOSE hMsg, const cn_cbor* pIn, int base);
-bool SetReceivingAttributes(HCOSE hMsg, const cn_cbor* pIn, int base);
+bool SetSendingAttributes(void* pMsg, const cn_cbor* pIn, int base);
+bool SetReceivingAttributes(void* pMsg, const cn_cbor* pIn, int base);
 int IsAlgorithmSupported(const cn_cbor* alg);
 
 //
@@ -102,3 +105,87 @@
 		else if (errorReturn != COSE_ERR_NONE)                  \
 			onFailure;                                          \
 	}
+
+#define Safe_Handle(handleName, freeFunction)          \
+	class Safe_##handleName {                          \
+		handleName h;                                  \
+                                                       \
+	   public:                                         \
+		Safe_##handleName() { h = NULL; }              \
+		Safe_##handleName(handleName hIn) { h = hIn; } \
+		~Safe_##handleName() { freeFunction(h); }      \
+		handleName Set(handleName hIn)                 \
+		{                                              \
+			if (h != NULL) {                           \
+				freeFunction(h);                       \
+			}                                          \
+			h = hIn;                                   \
+			return hIn;                                \
+		}                                              \
+		bool IsNull() { return h == NULL; }            \
+		HCOSE ToCOSE() { return (HCOSE)h; }            \
+		operator handleName() { return h; }            \
+		handleName operator=(handleName pIn)           \
+		{                                              \
+			Set(pIn);                                  \
+			return pIn;                                \
+		}                                              \
+		handleName Transfer(Safe_##handleName* hIn) \
+		{ \
+		if (h != NULL) { \
+freeFunction(h); \
+} \
+h = hIn->h; \
+hIn->h = NULL; \
+return h; \
+} \
+		handleName operator=(Safe_##handleName hIn) \
+		{ \
+		Set(hIn.h); \
+		return h; \
+		} \
+		void Clear() { h = NULL; }                     \
+		handleName Release() { \
+		handleName h2 = h; \
+		freeFunction(h); \
+		h = NULL; \
+		return h2; \
+		} \
+	};
+
+Safe_Handle(HCOSE_ENCRYPT, COSE_Encrypt_Free);
+Safe_Handle(HCOSE_ENVELOPED, COSE_Enveloped_Free);
+Safe_Handle(HCOSE_RECIPIENT, COSE_Recipient_Free);
+Safe_Handle(HCOSE_COUNTERSIGN, COSE_CounterSign_Free);
+Safe_Handle(HCOSE_COUNTERSIGN1, COSE_CounterSign1_Free);
+Safe_Handle(HCOSE_KEY, COSE_KEY_Free);
+Safe_Handle(HCOSE_MAC, COSE_Mac_Free);
+Safe_Handle(HCOSE_MAC0, COSE_Mac0_Free);
+Safe_Handle(HCOSE_SIGN, COSE_Sign_Free);
+Safe_Handle(HCOSE_SIGN1, COSE_Sign1_Free);
+Safe_Handle(HCOSE_SIGNER, COSE_Signer_Free);
+
+class Safe_CN_CBOR {
+	cn_cbor* p;
+
+   public:
+	Safe_CN_CBOR() { p = NULL; }
+	Safe_CN_CBOR(cn_cbor* pIn) { p = pIn; }
+	~Safe_CN_CBOR() { CN_CBOR_FREE(p, context); };
+	cn_cbor* Set(cn_cbor* pIn)
+	{
+		if (p != NULL) {
+			CN_CBOR_FREE(p, context);
+		}
+		p = pIn;
+		return pIn;
+	}
+	inline bool IsNull() { return p == NULL; }
+	inline operator cn_cbor*() { return p; }
+	inline void Clear() { p = NULL; }
+	inline cn_cbor* operator=(cn_cbor* pIn)
+	{
+		Set(pIn);
+		return pIn;
+	}
+};