Currently, DEFAUT_CHANNEL and AAD_CHANNEL are strings allocated in 
cryptlib.cpp and subject to all the translation unit rules regarding static 
initialization. Its been pain point for me in the past, and I think Bizyaev 
is experiencing it now.

I'd like to propose two subtle changes to help manage that initialization 
issue without breaking user code. First is a static inline function that 
creates a local static to force early initialization:

//***** cryptlib.h *****//

//! the default channel for BufferedTransformation, equal to the empty 
string.
//  New code should call the DefaultChannel() function.
extern CRYPTOPP_DLL const std::string DEFAULT_CHANNEL;
inline static const std::string& DefaultChannel() {
    static const std::string ch = "";
    return ch;
}

//! channel for additional authenticated data, equal to the string "AAD".
//  New code should call AadChannel() function.
extern CRYPTOPP_DLL const std::string AAD_CHANNEL;
inline static const std::string& AadChannel() {
    static const std::string ch = "AAD";
    return ch;
}

The multiple copies should be folded into one by the optimizer (if multiple 
copies are present).

And second:

//***** cryptlib.cpp *****//

const std::string DEFAULT_CHANNEL = DefaultChannel();
const std::string AAD_CHANNEL = AadChannel();

Finally, I'd like to try and get this into 5.6.3 since its one of those 
annoying and hard to track down issues.

A patch for testing is below (and attached). It only modified 
cryptlib.{h|cpp}, *test.cpp, and validat?.cpp.

Any comments or objections?

Jeff

********************

$ cat channels.diff 
diff --git a/cryptlib.cpp b/cryptlib.cpp
index 43df08b..2ded98c 100644
--- a/cryptlib.cpp
+++ b/cryptlib.cpp
@@ -32,9 +32,8 @@ CRYPTOPP_COMPILE_ASSERT(sizeof(word64) == 8);
 CRYPTOPP_COMPILE_ASSERT(sizeof(dword) == 2*sizeof(word));
 #endif
 
-const std::string DEFAULT_CHANNEL;
-const std::string AAD_CHANNEL = "AAD";
-const std::string &BufferedTransformation::NULL_CHANNEL = DEFAULT_CHANNEL;
+const std::string DEFAULT_CHANNEL = DefaultChannel();
+const std::string AAD_CHANNEL = AadChannel();
 
 class NullNameValuePairs : public NameValuePairs
 {
diff --git a/cryptlib.h b/cryptlib.h
index 207b1e6..dd52511 100644
--- a/cryptlib.h
+++ b/cryptlib.h
@@ -768,11 +768,21 @@ public:
        bool Wait(unsigned long milliseconds, CallStack const& callStack);
 };
 
-//! the default channel for BufferedTransformation, equal to the empty 
std::string
+//! the default channel for BufferedTransformation, equal to the empty 
string.
+//  New code should call the DefaultChannel() function.
 extern CRYPTOPP_DLL const std::string DEFAULT_CHANNEL;
+inline static const std::string& DefaultChannel() {
+       static const std::string ch = "";
+       return ch;
+}
 
-//! channel for additional authenticated data, equal to "AAD"
+//! channel for additional authenticated data, equal to the string "AAD".
+//  New code should call AadChannel() function.
 extern CRYPTOPP_DLL const std::string AAD_CHANNEL;
+inline static const std::string& AadChannel() {
+       static const std::string ch = "AAD";
+       return ch;
+}
 
 //! interface for buffered transformations
 
@@ -803,8 +813,6 @@ extern CRYPTOPP_DLL const std::string AAD_CHANNEL;
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BufferedTransformation : public 
Algorithm, public Waitable
 {
 public:
-       // placed up here for CW8
-       static const std::string &NULL_CHANNEL; // same as DEFAULT_CHANNEL, 
for backwards compatibility
 
        BufferedTransformation() : Algorithm(false) {}
 
@@ -929,18 +937,18 @@ public:
                size_t PeekWord32(word32 &value, ByteOrder 
order=BIG_ENDIAN_ORDER) const;
 
                //! move transferMax bytes of the buffered output to target 
as input
-               lword TransferTo(BufferedTransformation &target, lword 
transferMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL)
+               lword TransferTo(BufferedTransformation &target, lword 
transferMax=LWORD_MAX, const std::string &channel=DefaultChannel())
                        {TransferTo2(target, transferMax, channel); return 
transferMax;}
 
                //! discard skipMax bytes from the output buffer
                virtual lword Skip(lword skipMax=LWORD_MAX);
 
                //! copy copyMax bytes of the buffered output to target as 
input
-               lword CopyTo(BufferedTransformation &target, lword 
copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const
+               lword CopyTo(BufferedTransformation &target, lword 
copyMax=LWORD_MAX, const std::string &channel=DefaultChannel()) const
                        {return CopyRangeTo(target, 0, copyMax, channel);}
 
                //! copy copyMax bytes of the buffered output, starting at 
position (relative to current position), to target as input
-               lword CopyRangeTo(BufferedTransformation &target, lword 
position, lword copyMax=LWORD_MAX, const std::string 
&channel=DEFAULT_CHANNEL) const
+               lword CopyRangeTo(BufferedTransformation &target, lword 
position, lword copyMax=LWORD_MAX, const std::string 
&channel=DefaultChannel()) const
                        {lword i = position; CopyRangeTo2(target, i, 
i+copyMax, channel); return i-position;}
 
 #ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
@@ -965,18 +973,18 @@ public:
                //! skip count number of messages
                virtual unsigned int SkipMessages(unsigned int 
count=UINT_MAX);
                //!
-               unsigned int TransferMessagesTo(BufferedTransformation 
&target, unsigned int count=UINT_MAX, const std::string 
&channel=DEFAULT_CHANNEL)
+               unsigned int TransferMessagesTo(BufferedTransformation 
&target, unsigned int count=UINT_MAX, const std::string 
&channel=DefaultChannel())
                        {TransferMessagesTo2(target, count, channel); 
return count;}
                //!
-               unsigned int CopyMessagesTo(BufferedTransformation &target, 
unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) 
const;
+               unsigned int CopyMessagesTo(BufferedTransformation &target, 
unsigned int count=UINT_MAX, const std::string &channel=DefaultChannel()) 
const;
 
                //!
                virtual void SkipAll();
                //!
-               void TransferAllTo(BufferedTransformation &target, const 
std::string &channel=DEFAULT_CHANNEL)
+               void TransferAllTo(BufferedTransformation &target, const 
std::string &channel=DefaultChannel())
                        {TransferAllTo2(target, channel);}
                //!
-               void CopyAllTo(BufferedTransformation &target, const 
std::string &channel=DEFAULT_CHANNEL) const;
+               void CopyAllTo(BufferedTransformation &target, const 
std::string &channel=DefaultChannel()) const;
 
                virtual bool GetNextMessageSeries() {return false;}
                virtual unsigned int NumberOfMessagesInThisSeries() const 
{return NumberOfMessages();}
@@ -986,13 +994,13 @@ public:
        //!     \name NON-BLOCKING TRANSFER OF OUTPUT
        //@{
                //! upon return, byteCount contains number of bytes that 
have finished being transfered, and returns the number of bytes left in the 
current transfer block
-               virtual size_t TransferTo2(BufferedTransformation &target, 
lword &byteCount, const std::string &channel=DEFAULT_CHANNEL, bool 
blocking=true) =0;
+               virtual size_t TransferTo2(BufferedTransformation &target, 
lword &byteCount, const std::string &channel=DefaultChannel(), bool 
blocking=true) =0;
                //! upon return, begin contains the start position of data 
yet to be finished copying, and returns the number of bytes left in the 
current transfer block
-               virtual size_t CopyRangeTo2(BufferedTransformation &target, 
lword &begin, lword end=LWORD_MAX, const std::string 
&channel=DEFAULT_CHANNEL, bool blocking=true) const =0;
+               virtual size_t CopyRangeTo2(BufferedTransformation &target, 
lword &begin, lword end=LWORD_MAX, const std::string 
&channel=DefaultChannel(), bool blocking=true) const =0;
                //! upon return, messageCount contains number of messages 
that have finished being transfered, and returns the number of bytes left 
in the current transfer block
-               size_t TransferMessagesTo2(BufferedTransformation &target, 
unsigned int &messageCount, const std::string &channel=DEFAULT_CHANNEL, 
bool blocking=true);
+               size_t TransferMessagesTo2(BufferedTransformation &target, 
unsigned int &messageCount, const std::string &channel=DefaultChannel(), 
bool blocking=true);
                //! returns the number of bytes left in the current 
transfer block
-               size_t TransferAllTo2(BufferedTransformation &target, const 
std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+               size_t TransferAllTo2(BufferedTransformation &target, const 
std::string &channel=DefaultChannel(), bool blocking=true);
        //@}
 
        //!     \name CHANNELS
diff --git a/datatest.cpp b/datatest.cpp
index d0f69c6..5595c4a 100644
--- a/datatest.cpp
+++ b/datatest.cpp
@@ -61,7 +61,7 @@ const std::string & GetRequiredDatum(const TestData 
&data, const char *name)
        return i->second;
 }
 
-void RandomizedTransfer(BufferedTransformation &source, 
BufferedTransformation &target, bool finish, const std::string 
&channel=DEFAULT_CHANNEL)
+void RandomizedTransfer(BufferedTransformation &source, 
BufferedTransformation &target, bool finish, const std::string 
&channel=DefaultChannel())
 {
        while (source.MaxRetrievable() > (finish ? 0 : 4096))
        {
@@ -492,16 +492,16 @@ void TestAuthenticatedSymmetricCipher(TestData &v, 
const NameValuePairs &overrid
 
                if (macAtBegin)
                        RandomizedTransfer(sm, df, true);
-               sh.CopyTo(df, LWORD_MAX, AAD_CHANNEL);
+               sh.CopyTo(df, LWORD_MAX, AadChannel());
                RandomizedTransfer(sc, df, true);
-               sf.CopyTo(df, LWORD_MAX, AAD_CHANNEL);
+               sf.CopyTo(df, LWORD_MAX, AadChannel());
                if (!macAtBegin)
                        RandomizedTransfer(sm, df, true);
                df.MessageEnd();
 
-               RandomizedTransfer(sh, ef, true, AAD_CHANNEL);
+               RandomizedTransfer(sh, ef, true, AadChannel());
                RandomizedTransfer(sp, ef, true);
-               RandomizedTransfer(sf, ef, true, AAD_CHANNEL);
+               RandomizedTransfer(sf, ef, true, AadChannel());
                ef.MessageEnd();
 
                if (test == "Encrypt" && encrypted != ciphertext+mac)
diff --git a/gfpcrypt.h b/gfpcrypt.h
index 0590254..1537b31 100644
--- a/gfpcrypt.h
+++ b/gfpcrypt.h
@@ -454,7 +454,7 @@ public:
                if (DHAES_MODE)
                {
                        byte L[8] = {0,0,0,0};
-                       PutWord(false, BIG_ENDIAN_ORDER, L+4, 
word32(encodingParameters.size()));
+                       PutWord(false, BIG_ENDIAN_ORDER, L, word64(8 * 
encodingParameters.size()));
                        mac.Update(L, 8);
                }
                mac.Final(ciphertext + plaintextLength);
@@ -483,7 +483,7 @@ public:
                if (DHAES_MODE)
                {
                        byte L[8] = {0,0,0,0};
-                       PutWord(false, BIG_ENDIAN_ORDER, L+4, 
word32(encodingParameters.size()));
+                       PutWord(false, BIG_ENDIAN_ORDER, L, word64(8 * 
encodingParameters.size()));
                        mac.Update(L, 8);
                }
                if (!mac.Verify(ciphertext + plaintextLength))
diff --git a/test.cpp b/test.cpp
index b357119..7ad18d3 100644
--- a/test.cpp
+++ b/test.cpp
@@ -621,7 +621,7 @@ void SecretShareFile(int threshold, int nShares, const 
char *filename, const cha
 
                channel = WordToString<word32>(i);
                fileSinks[i]->Put((byte *)channel.data(), 4);
-               channelSwitch->AddRoute(channel, *fileSinks[i], 
DEFAULT_CHANNEL);
+               channelSwitch->AddRoute(channel, *fileSinks[i], 
DefaultChannel());
        }
 
        source.PumpAll();
@@ -671,7 +671,7 @@ void InformationDisperseFile(int threshold, int 
nShares, const char *filename)
 
                channel = WordToString<word32>(i);
                fileSinks[i]->Put((byte *)channel.data(), 4);
-               channelSwitch->AddRoute(channel, *fileSinks[i], 
DEFAULT_CHANNEL);
+               channelSwitch->AddRoute(channel, *fileSinks[i], 
DefaultChannel());
        }
 
        source.PumpAll();



-- 
-- 
You received this message because you are subscribed to the "Crypto++ Users" 
Google Group.
To unsubscribe, send an email to [email protected].
More information about Crypto++ and this group is available at 
http://www.cryptopp.com.
--- 
You received this message because you are subscribed to the Google Groups 
"Crypto++ Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff --git a/cryptlib.cpp b/cryptlib.cpp
index 43df08b..2ded98c 100644
--- a/cryptlib.cpp
+++ b/cryptlib.cpp
@@ -32,9 +32,8 @@ CRYPTOPP_COMPILE_ASSERT(sizeof(word64) == 8);
 CRYPTOPP_COMPILE_ASSERT(sizeof(dword) == 2*sizeof(word));
 #endif
 
-const std::string DEFAULT_CHANNEL;
-const std::string AAD_CHANNEL = "AAD";
-const std::string &BufferedTransformation::NULL_CHANNEL = DEFAULT_CHANNEL;
+const std::string DEFAULT_CHANNEL = DefaultChannel();
+const std::string AAD_CHANNEL = AadChannel();
 
 class NullNameValuePairs : public NameValuePairs
 {
diff --git a/cryptlib.h b/cryptlib.h
index 207b1e6..dd52511 100644
--- a/cryptlib.h
+++ b/cryptlib.h
@@ -768,11 +768,21 @@ public:
 	bool Wait(unsigned long milliseconds, CallStack const& callStack);
 };
 
-//! the default channel for BufferedTransformation, equal to the empty std::string
+//! the default channel for BufferedTransformation, equal to the empty string.
+//  New code should call the DefaultChannel() function.
 extern CRYPTOPP_DLL const std::string DEFAULT_CHANNEL;
+inline static const std::string& DefaultChannel() {
+	static const std::string ch = "";
+	return ch;
+}
 
-//! channel for additional authenticated data, equal to "AAD"
+//! channel for additional authenticated data, equal to the string "AAD".
+//  New code should call AadChannel() function.
 extern CRYPTOPP_DLL const std::string AAD_CHANNEL;
+inline static const std::string& AadChannel() {
+	static const std::string ch = "AAD";
+	return ch;
+}
 
 //! interface for buffered transformations
 
@@ -803,8 +813,6 @@ extern CRYPTOPP_DLL const std::string AAD_CHANNEL;
 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BufferedTransformation : public Algorithm, public Waitable
 {
 public:
-	// placed up here for CW8
-	static const std::string &NULL_CHANNEL;	// same as DEFAULT_CHANNEL, for backwards compatibility
 
 	BufferedTransformation() : Algorithm(false) {}
 
@@ -929,18 +937,18 @@ public:
 		size_t PeekWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER) const;
 
 		//! move transferMax bytes of the buffered output to target as input
-		lword TransferTo(BufferedTransformation &target, lword transferMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL)
+		lword TransferTo(BufferedTransformation &target, lword transferMax=LWORD_MAX, const std::string &channel=DefaultChannel())
 			{TransferTo2(target, transferMax, channel); return transferMax;}
 
 		//! discard skipMax bytes from the output buffer
 		virtual lword Skip(lword skipMax=LWORD_MAX);
 
 		//! copy copyMax bytes of the buffered output to target as input
-		lword CopyTo(BufferedTransformation &target, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const
+		lword CopyTo(BufferedTransformation &target, lword copyMax=LWORD_MAX, const std::string &channel=DefaultChannel()) const
 			{return CopyRangeTo(target, 0, copyMax, channel);}
 
 		//! copy copyMax bytes of the buffered output, starting at position (relative to current position), to target as input
-		lword CopyRangeTo(BufferedTransformation &target, lword position, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const
+		lword CopyRangeTo(BufferedTransformation &target, lword position, lword copyMax=LWORD_MAX, const std::string &channel=DefaultChannel()) const
 			{lword i = position; CopyRangeTo2(target, i, i+copyMax, channel); return i-position;}
 
 #ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
@@ -965,18 +973,18 @@ public:
 		//! skip count number of messages
 		virtual unsigned int SkipMessages(unsigned int count=UINT_MAX);
 		//!
-		unsigned int TransferMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL)
+		unsigned int TransferMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DefaultChannel())
 			{TransferMessagesTo2(target, count, channel); return count;}
 		//!
-		unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const;
+		unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DefaultChannel()) const;
 
 		//!
 		virtual void SkipAll();
 		//!
-		void TransferAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL)
+		void TransferAllTo(BufferedTransformation &target, const std::string &channel=DefaultChannel())
 			{TransferAllTo2(target, channel);}
 		//!
-		void CopyAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const;
+		void CopyAllTo(BufferedTransformation &target, const std::string &channel=DefaultChannel()) const;
 
 		virtual bool GetNextMessageSeries() {return false;}
 		virtual unsigned int NumberOfMessagesInThisSeries() const {return NumberOfMessages();}
@@ -986,13 +994,13 @@ public:
 	//!	\name NON-BLOCKING TRANSFER OF OUTPUT
 	//@{
 		//! upon return, byteCount contains number of bytes that have finished being transfered, and returns the number of bytes left in the current transfer block
-		virtual size_t TransferTo2(BufferedTransformation &target, lword &byteCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) =0;
+		virtual size_t TransferTo2(BufferedTransformation &target, lword &byteCount, const std::string &channel=DefaultChannel(), bool blocking=true) =0;
 		//! upon return, begin contains the start position of data yet to be finished copying, and returns the number of bytes left in the current transfer block
-		virtual size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const =0;
+		virtual size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DefaultChannel(), bool blocking=true) const =0;
 		//! upon return, messageCount contains number of messages that have finished being transfered, and returns the number of bytes left in the current transfer block
-		size_t TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+		size_t TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel=DefaultChannel(), bool blocking=true);
 		//! returns the number of bytes left in the current transfer block
-		size_t TransferAllTo2(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+		size_t TransferAllTo2(BufferedTransformation &target, const std::string &channel=DefaultChannel(), bool blocking=true);
 	//@}
 
 	//!	\name CHANNELS
diff --git a/datatest.cpp b/datatest.cpp
index d0f69c6..5595c4a 100644
--- a/datatest.cpp
+++ b/datatest.cpp
@@ -61,7 +61,7 @@ const std::string & GetRequiredDatum(const TestData &data, const char *name)
 	return i->second;
 }
 
-void RandomizedTransfer(BufferedTransformation &source, BufferedTransformation &target, bool finish, const std::string &channel=DEFAULT_CHANNEL)
+void RandomizedTransfer(BufferedTransformation &source, BufferedTransformation &target, bool finish, const std::string &channel=DefaultChannel())
 {
 	while (source.MaxRetrievable() > (finish ? 0 : 4096))
 	{
@@ -492,16 +492,16 @@ void TestAuthenticatedSymmetricCipher(TestData &v, const NameValuePairs &overrid
 
 		if (macAtBegin)
 			RandomizedTransfer(sm, df, true);
-		sh.CopyTo(df, LWORD_MAX, AAD_CHANNEL);
+		sh.CopyTo(df, LWORD_MAX, AadChannel());
 		RandomizedTransfer(sc, df, true);
-		sf.CopyTo(df, LWORD_MAX, AAD_CHANNEL);
+		sf.CopyTo(df, LWORD_MAX, AadChannel());
 		if (!macAtBegin)
 			RandomizedTransfer(sm, df, true);
 		df.MessageEnd();
 
-		RandomizedTransfer(sh, ef, true, AAD_CHANNEL);
+		RandomizedTransfer(sh, ef, true, AadChannel());
 		RandomizedTransfer(sp, ef, true);
-		RandomizedTransfer(sf, ef, true, AAD_CHANNEL);
+		RandomizedTransfer(sf, ef, true, AadChannel());
 		ef.MessageEnd();
 
 		if (test == "Encrypt" && encrypted != ciphertext+mac)
diff --git a/gfpcrypt.h b/gfpcrypt.h
index 0590254..1537b31 100644
--- a/gfpcrypt.h
+++ b/gfpcrypt.h
@@ -454,7 +454,7 @@ public:
 		if (DHAES_MODE)
 		{
 			byte L[8] = {0,0,0,0};
-			PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size()));
+			PutWord(false, BIG_ENDIAN_ORDER, L, word64(8 * encodingParameters.size()));
 			mac.Update(L, 8);
 		}
 		mac.Final(ciphertext + plaintextLength);
@@ -483,7 +483,7 @@ public:
 		if (DHAES_MODE)
 		{
 			byte L[8] = {0,0,0,0};
-			PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size()));
+			PutWord(false, BIG_ENDIAN_ORDER, L, word64(8 * encodingParameters.size()));
 			mac.Update(L, 8);
 		}
 		if (!mac.Verify(ciphertext + plaintextLength))
diff --git a/test.cpp b/test.cpp
index b357119..7ad18d3 100644
--- a/test.cpp
+++ b/test.cpp
@@ -621,7 +621,7 @@ void SecretShareFile(int threshold, int nShares, const char *filename, const cha
 
 		channel = WordToString<word32>(i);
 		fileSinks[i]->Put((byte *)channel.data(), 4);
-		channelSwitch->AddRoute(channel, *fileSinks[i], DEFAULT_CHANNEL);
+		channelSwitch->AddRoute(channel, *fileSinks[i], DefaultChannel());
 	}
 
 	source.PumpAll();
@@ -671,7 +671,7 @@ void InformationDisperseFile(int threshold, int nShares, const char *filename)
 
 		channel = WordToString<word32>(i);
 		fileSinks[i]->Put((byte *)channel.data(), 4);
-		channelSwitch->AddRoute(channel, *fileSinks[i], DEFAULT_CHANNEL);
+		channelSwitch->AddRoute(channel, *fileSinks[i], DefaultChannel());
 	}
 
 	source.PumpAll();

Reply via email to