Add QCBOREncode_AddBytesLenOnly(), special for COSE sig verification
diff --git a/inc/qcbor.h b/inc/qcbor.h
index 157325d..eddf3fe 100644
--- a/inc/qcbor.h
+++ b/inc/qcbor.h
@@ -214,6 +214,7 @@
 // Must not conflict with any of the official CBOR types
 #define CBOR_MAJOR_NONE_TYPE_RAW  9
 #define CBOR_MAJOR_NONE_TAG_LABEL_REORDER 10
+#define CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY 11
 
 
 /* ===========================================================================
@@ -2198,6 +2199,35 @@
  */
 void  QCBOREncode_AddType7(QCBOREncodeContext *pCtx, size_t uSize, uint64_t uNum);
 
+    
+/**
+ @brief Semi-private method to add only the type and length of a byte string.
+ 
+ @param[in] pCtx    The context to initialize.
+ @param[in] Bytes   Pointer and length of the input data.
+ 
+ This is the same as QCBOREncode_AddBytes() except it only adds the
+ CBOR encoding for the type and the length. It doesn't actually add
+ the bytes. You can't actually produce correct CBOR with this and the
+ rest of this API. It is only used for a special case where
+ the valid CBOR is created manually by putting this type and length in
+ and then adding the actual bytes. In particular, when only a hash of
+ the encoded CBOR is needed, where the type and header are hashed
+ separately and then the bytes is hashed. This makes it possible to
+ implement COSE Sign1 with only one copy of the payload in the output
+ buffer, rather than two, roughly cutting memory use in half.
+ 
+ This is only used for this odd case, but this is a supported
+ tested function.
+*/
+static inline void QCBOREncode_AddBytesLenOnly(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
+
+static inline void QCBOREncode_AddBytesLenOnlyToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
+
+static inline void QCBOREncode_AddBytesLenOnlyToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
+
+
+   
 
 static inline void QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum)
 {
@@ -2312,6 +2342,22 @@
    QCBOREncode_AddBytes(pCtx, Bytes);
 }
 
+static inline void QCBOREncode_AddBytesLenOnly(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
+{
+    QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY, Bytes);
+}
+
+static inline void QCBOREncode_AddBytesLenOnlyToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
+{
+    QCBOREncode_AddSZString(pCtx, szLabel);
+    QCBOREncode_AddBytesLenOnly(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddBytesLenOnlyToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
+{
+    QCBOREncode_AddInt64(pCtx, nLabel);
+    QCBOREncode_AddBytesLenOnly(pCtx, Bytes);
+}
 
 static inline void QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
 {
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index ab30940..c652f79 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -393,26 +393,41 @@
 
 
 /*
- Semi-private function. It is exposed to user of the interface,
- but they will usually call one of the inline wrappers rather than this.
+ Semi-private function. It is exposed to user of the interface, but
+ they will usually call one of the inline wrappers rather than this.
 
  See header qcbor.h
 
- Does the work of adding some bytes to the CBOR output. Works for a
- byte and text strings, which are the same in in CBOR though they have
- different major types.  This is also used to insert raw
- pre-encoded CBOR.
+ Does the work of adding actual strings bytes to the CBOR output (as
+ opposed to numbers and opening / closing aggregate types).
+
+ There are four use cases:
+   CBOR_MAJOR_TYPE_BYTE_STRING -- Byte strings
+   CBOR_MAJOR_TYPE_TEXT_STRING -- Text strings
+   CBOR_MAJOR_NONE_TYPE_RAW -- Already-encoded CBOR
+   CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY -- Special case
+
+ The first two add the type and length plus the actual bytes. The
+ third just adds the bytes as the type and length are presumed to be
+ in the bytes. The fourth just adds the type and length for the very
+ special case of QCBOREncode_AddBytesLenOnly().
  */
 void QCBOREncode_AddBuffer(QCBOREncodeContext *me, uint8_t uMajorType, UsefulBufC Bytes)
 {
    if(me->uError == QCBOR_SUCCESS) {
       // If it is not Raw CBOR, add the type and the length
       if(uMajorType != CBOR_MAJOR_NONE_TYPE_RAW) {
-         AppendEncodedTypeAndNumber(me, uMajorType, Bytes.len);
+         uint8_t uRealMajorType = uMajorType;
+         if(uRealMajorType == CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY) {
+            uRealMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
+         }
+         AppendEncodedTypeAndNumber(me, uRealMajorType, Bytes.len);
       }
 
-      // Actually add the bytes
-      UsefulOutBuf_AppendUsefulBuf(&(me->OutBuf), Bytes);
+      if(uMajorType != CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY) {
+         // Actually add the bytes
+         UsefulOutBuf_AppendUsefulBuf(&(me->OutBuf), Bytes);
+      }
 
       // Update the array counting if there is any nesting at all
       me->uError = Nesting_Increment(&(me->nesting));
@@ -573,7 +588,7 @@
    }
 
    if(UsefulOutBuf_GetError(&(me->OutBuf))) {
-      // items didn't fit in the buffer.
+      // Items didn't fit in the buffer.
       // This check catches this condition for all the appends and inserts
       // so checks aren't needed when the appends and inserts are performed.
       // And of course UsefulBuf will never overrun the input buffer given
diff --git a/test/qcbor_encode_tests.c b/test/qcbor_encode_tests.c
index ad17feb..f08927c 100644
--- a/test/qcbor_encode_tests.c
+++ b/test/qcbor_encode_tests.c
@@ -1380,6 +1380,12 @@
 static const uint8_t spExpectedBstrWrap[] = {0x82, 0x19, 0x01, 0xC3, 0x43, 0x19, 0x01, 0xD2};
 
 /*
+ 81   #array(1)
+ 0x58  0x25  # string of length 37 (length of "This is longer than twenty four bytes")
+ */
+static const uint8_t spExpectedTypeAndLen[] = {0x81, 0x58, 0x25};
+
+/*
  Very basic bstr wrapping test
  */
 int BstrWrapTest()
@@ -1424,6 +1430,20 @@
    if(BStr.ptr != NULL || BStr.len != 3) {
       return -5;
    }
+   
+   // Third, test QCBOREncode_AddBytesLenOnly() here as it is part of the
+   // bstr wrapping use cases.
+   UsefulBuf_MAKE_STACK_UB(StuffBuf, 50);
+   QCBOREncode_Init(&EC, StuffBuf);
+   QCBOREncode_OpenArray(&EC);
+   QCBOREncode_AddBytesLenOnly(&EC, UsefulBuf_FROM_SZ_LITERAL("This is longer than twenty four bytes"));
+   QCBOREncode_CloseArray(&EC);
+   if(QCBOREncode_Finish(&EC, &Encoded)) {
+      return -6;
+   }
+   if(CheckResults(Encoded, spExpectedTypeAndLen)) {
+      return -7;
+   }
 
    return 0;
 }