Skip to content

Commit

Permalink
Add BuildVersion and RuntimeVersion functions (Issue 371)
Browse files Browse the repository at this point in the history
These function are intended to catch mining and matching of library versions. BuildVersion provides CRYPTOPP_VERSION when the shared object was built. RuntimeVersion provides CRYPTOPP_VERSION the app compiled against, which could be different than the shared object's version
  • Loading branch information
noloader committed Jan 28, 2017
1 parent e757fad commit 6f7339c
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 2 deletions.
11 changes: 10 additions & 1 deletion cryptlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ word32 RandomNumberGenerator::GenerateWord32(word32 min, word32 max)

// Stack recursion below... GenerateIntoBufferedTransformation calls GenerateBlock,
// and GenerateBlock calls GenerateIntoBufferedTransformation. Ad infinitum. Also
// see https://github.com/weidai11/cryptopp/issues/38.
// see http://github.com/weidai11/cryptopp/issues/38.
//
// According to Wei, RandomNumberGenerator is an interface, and it should not
// be instantiable. Its now spilt milk, and we are going to CRYPTOPP_ASSERT it in Debug
Expand Down Expand Up @@ -945,6 +945,15 @@ void AuthenticatedKeyAgreementDomain::GenerateEphemeralKeyPair(RandomNumberGener
GenerateEphemeralPublicKey(rng, privateKey, publicKey);
}

// Allow a distro or packager to override the build-time version
// http://github.com/weidai11/cryptopp/issues/371
#ifndef CRYPTOPP_BUILD_VERSION
# define CRYPTOPP_BUILD_VERSION CRYPTOPP_VERSION
#endif
int BuildVersion()
{
return CRYPTOPP_BUILD_VERSION;
}
NAMESPACE_END

#endif
70 changes: 70 additions & 0 deletions cryptlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -2914,6 +2914,76 @@ class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1Object
virtual void BEREncode(BufferedTransformation &bt) const {DEREncode(bt);}
};

//! \brief Specifies the build-time version of the library
//! \returns integer representing the build-time version
//! \details BuildVersion can help detect inadvertent mixing and matching of library
//! versions. When using Crypto++ distributed by a third party, BuildVersion()
//! records the version of the shared object that was built by the third party.
//! The BuildVersion() record resides in <tt>cryptlib.o</tt> on Unix compatibles
//! and <tt>cryptlib.obj</tt> on Windows. It does not change when an app links
//! to the library.
//! \details BuildVersion() is declared with C linkage (<tt>extern "C"</tt>) within the
//! CryptoPP namespace to help programs locate the symbol. If the symbol is present, then
//! the library version is 5.7 or above. If it is missing, then the library version is
//! 5.6.5 or below.
//! \details The function could be used as shown below.
//! <pre>
//! if (BuildVersion() != RuntimeVersion())
//! {
//! cout << "Potential version mismatch" << endl;
//!
//! const int bmaj = (BuildVersion() / 100U) % 10;
//! const int bmin = (BuildVersion() / 10U) % 10;
//! const int rmaj = (RuntimeVersion() / 100U) % 10;
//! const int rmin = (RuntimeVersion() / 10U) % 10;
//!
//! if(bmaj != rmaj)
//! cout << "Major version mismatch" << endl;
//! else if(bmin != rmin)
//! cout << "Minor version mismatch" << endl;
//! }
//! </pre>
//! \sa RuntimeVersion(), <A HREF="http://github.com/weidai11/cryptopp/issues/371">GitHub Issue 371</A>.
//! \since Crypto++ 5.7
extern "C" {
int BuildVersion();
} // C linkage

//! \brief Specifies the runtime version of the library
//! \returns integer representing the runtime version
//! \details RuntimeVersion() can help detect inadvertent mixing and matching of library
//! versions. When using Crypto++ distributed by a third party, RuntimeVersion()
//! records the version of the headers used by the app when the app is compiled.
//! \details RuntimeVersion() is declared with C linkage (<tt>extern "C"</tt>) within the
//! CryptoPP namespace to help programs locate the symbol. If the symbol is present, then
//! the library version is 5.7 or above. If it is missing, then the library version is
//! 5.6.5 or below.
//! \details The function could be used as shown below.
//! <pre>
//! if (BuildVersion() != RuntimeVersion())
//! {
//! cout << "Potential version mismatch" << endl;
//!
//! const int bmaj = (BuildVersion() / 100U) % 10;
//! const int bmin = (BuildVersion() / 10U) % 10;
//! const int rmaj = (RuntimeVersion() / 100U) % 10;
//! const int rmin = (RuntimeVersion() / 10U) % 10;
//!
//! if(bmaj != rmaj)
//! cout << "Major version mismatch" << endl;
//! else if(bmin != rmin)
//! cout << "Minor version mismatch" << endl;
//! }
//! </pre>
//! \sa BuildVersion(), <A HREF="http://github.com/weidai11/cryptopp/issues/371">GitHub Issue 371</A>.
//! \since Crypto++ 5.7
extern "C" {
inline int RuntimeVersion()
{
return CRYPTOPP_VERSION;
}
} // C linkage

NAMESPACE_END

#if CRYPTOPP_MSC_VERSION
Expand Down
2 changes: 1 addition & 1 deletion gfpcrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ class DL_Algorithm_DSA_RFC6979 : public DL_Algorithm_GDSA<T>, public Determinist
//! \tparam T FieldElement type or class
//! \details The Digital Signature Scheme ECGDSA does not define the algorithm over integers. Rather, the
//! signature algorithm is only defined over elliptic curves. However, The library design is such that the
//! generic algorithm reside in \header gfpcrypt.h.
//! generic algorithm reside in <tt>gfpcrypt.h</tt>.
//! \sa Erwin Hess, Marcus Schafheutle, and Pascale Serf <A HREF="http://www.teletrust.de/fileadmin/files/oid/ecgdsa_final.pdf">
//! The Digital Signature Scheme ECGDSA (October 24, 2006)</A>
template <class T>
Expand Down
12 changes: 12 additions & 0 deletions validat1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,18 @@ bool TestSettings()
pass = false;
}

// App and library versions, http://github.com/weidai11/cryptopp/issues/371
const int bver = BuildVersion();
const int rver = RuntimeVersion();
if(bver/10 == rver/10)
cout << "passed: ";
else
{
cout << "FAILED: ";
pass = false;
}
cout << "Build version (library): " << bver << ", runtime version (app): " << rver << "\n";

#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
// Don't assert the alignment of testvals. That's what this test is for.
byte testvals[10] = {1,2,2,3,3,3,3,2,2,1};
Expand Down

1 comment on commit 6f7339c

@noloader
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also see Issue 371.

Please sign in to comment.