diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c033cbb..14512ac1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,11 +98,12 @@ if(APPLE) find_library(BOTAN ${BOTAN_VERSION} $ENV{BOTAN_DIR}/release NO_DEFAULT_PATH) find_library(BOTAN_D ${BOTAN_VERSION} $ENV{BOTAN_DIR}/debug NO_DEFAULT_PATH) elseif(UNIX) - find_library(BOTAN ${BOTAN_VERSION} "${EXTERNAL_BUILD}/botan" NO_DEFAULT_PATH) + find_library(BOTAN ${BOTAN_VERSION} "${BOTAN_DIR}") else() find_library(BOTAN botan "$ENV{BOTAN_DIR}/release") find_library(BOTAN_D botan "$ENV{BOTAN_DIR}/debug") endif() +message(STATUS "botanversion: ${BOTAN}") if(${BOTAN} STREQUAL "BOTAN-NOTFOUND") message(FATAL_ERROR "Botan not found") @@ -111,9 +112,15 @@ else() endif() if(UNIX AND NOT APPLE) - set(BOTAN_INCLUDE_DIR "${EXTERNAL_BUILD}/botan") + find_path(BOTAN_INCLUDE_DIR NAMES botan/botan.h + PATH_SUFFIXES ${BOTAN_VERSION} + DOC "The Botan include directory") else() - set(BOTAN_INCLUDE_DIR "$ENV{BOTAN_DIR}") + set(BOTAN_INCLUDE_DIR "$ENV{BOTAN_DIR}/build/include") +endif() + +if(NOT BOTAN_INCLUDE_DIR) + message(FATAL_ERROR "Botan include dir not found") endif() diff --git a/README.md b/README.md index 762620e0..80c68616 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ * Valgrind 3.9.0 (linux) * Clang & LLVM 3.8 (doesnt quite work for windows, use unix setup below and skip all the ninja stuff)(installation guide http://clang.llvm.org/docs/LibASTMatchersTutorial.html) * Boost 1.59 -* Botan 1.11.24 +* Botan 1.11.34 #### Environment Variables @@ -18,7 +18,7 @@ * CXX_TEST_DIR - .../cxxtest-4.3 * CLANG_DIR - .../clang-llvm * BOOST_159_DIR - .../boost_1_59_0 -* BOTAN_DIR - .../Botan-1.11.24 +* BOTAN_DIR - .../Botan-1.11.34 For Win32: * VLD_DIR - .../Visual Leak Detector @@ -32,13 +32,13 @@ Build release lib in ${BOTAN_DIR}/release Build debug lib in ${BOTAN_DIR}/debug for Windows release build: -$ python configure.py --cc=msvc --cpu=x86_32 --via-amalgamation --disable-shared +$ python configure.py --cc=msvc --cpu=x86_32 --disable-shared for Windows debug build: -python configure.py --cc=msvc --cpu=x86_32 --via-amalgamation --disable-shared --no-optimizations --with-debug-info +python configure.py --cc=msvc --cpu=x86_32 --disable-shared --no-optimizations --with-debug-info for other: -$ python configure.py --via-amalgamation --disable-shared +$ python configure.py --disable-shared #### Settings diff --git a/src/lib_license/Generator.cpp b/src/lib_license/Generator.cpp index c793b30e..7000435c 100644 --- a/src/lib_license/Generator.cpp +++ b/src/lib_license/Generator.cpp @@ -4,9 +4,11 @@ #include #include -#include "botan_all.h" #include "boost/filesystem.hpp" #include "boost/date_time/gregorian/gregorian.hpp" +#include "botan/pk_keys.h" +#include "botan/pkcs8.h" +#include "botan/rsa.h" #include "License.h" diff --git a/src/lib_license/Generator.h b/src/lib_license/Generator.h index 18772bde..318221a4 100644 --- a/src/lib_license/Generator.h +++ b/src/lib_license/Generator.h @@ -3,7 +3,13 @@ #include -#include "botan_all.h" +//#include "botan_all.h" +#include "botan/auto_rng.h" + +namespace Botan +{ + class RSA_PrivateKey; +} class Generator { diff --git a/src/lib_license/License.cpp b/src/lib_license/License.cpp index ac02e123..0a1d5172 100644 --- a/src/lib_license/License.cpp +++ b/src/lib_license/License.cpp @@ -7,18 +7,26 @@ #include #include -#include "botan_all.h" +//#include "botan_all.h" #include "boost/date_time.hpp" #include "boost/filesystem.hpp" +#include "botan/rsa.h" +#include "botan/cryptobox.h" +#include "botan/passhash9.h" +#include "botan/base64.h" +#include "botan/pubkey.h" +#include "botan/pk_keys.h" +#include "botan/auto_rng.h" +#include "botan/pbkdf.h" namespace { - std::string trim(const std::string &str) - { - auto wsfront = std::find_if_not(str.begin(), str.end(), [](int c){ return std::isspace(c); }); - auto wsback = std::find_if_not(str.rbegin(), str.rend(), [](int c){ return std::isspace(c); }).base(); - return (wsback <= wsfront ? std::string() : std::string(wsfront, wsback)); - } + std::string trim(const std::string &str) + { + auto wsfront = std::find_if_not(str.begin(), str.end(), [](int c){ return std::isspace(c); }); + auto wsback = std::find_if_not(str.rbegin(), str.rend(), [](int c){ return std::isspace(c); }).base(); + return (wsback <= wsfront ? std::string() : std::string(wsfront, wsback)); + } } License::License() @@ -32,42 +40,42 @@ License::~License() std::string License::getHashLine() const { - return lines[4]; + return lines[4]; } std::string License::getMessage() const { - std::string message = ""; - for(int i = 1; i < 5; ++i) - { - message += lines[i]; - } - return message; + std::string message = ""; + for(int i = 1; i < 5; ++i) + { + message += lines[i]; + } + return message; } std::string License::getSignature() const { - std::string signatue = ""; - for(int i = 5; i < 12; ++i) - { - signatue += lines[i]; - } - return signatue; + std::string signatue = ""; + for(int i = 5; i < 12; ++i) + { + signatue += lines[i]; + } + return signatue; } std::string License::getVersionLine() const { - return lines[3]; + return lines[3]; } std::string License::getOwnerLine() const { - return lines[1]; + return lines[1]; } std::string License::getLicenseTypeLine() const { - return lines[2]; + return lines[2]; } int License::getTimeLeft() const @@ -76,8 +84,8 @@ int License::getTimeLeft() const if(getLicenseTypeLine().substr(0, testText.length()) == testText) { boost::gregorian::date expireDate( - boost::gregorian::from_simple_string(getLicenseTypeLine().substr(testText.length(),11)) - ); + boost::gregorian::from_simple_string(getLicenseTypeLine().substr(testText.length(),11)) + ); boost::gregorian::date today = boost::gregorian::day_clock::local_day(); boost::gregorian::days daysLeft = expireDate - today; return (daysLeft.days() < 0 ? -1 : daysLeft.days()); @@ -92,125 +100,125 @@ void License::create( const std::string& user, const std::string& version, Botan::RSA_PrivateKey* privateKey, const std::string& type) { - m_version = version; - createMessage(user, version, type); + m_version = version; + createMessage(user, version, type); - //encode message - Botan::PK_Signer signer(*privateKey, "EMSA4(SHA-256)"); - Botan::DataSource_Memory in(getMessage()); - Botan::byte buf[4096] = {0}; - while (size_t got = in.read(buf, sizeof(buf))) { - signer.update(buf, got); - } + //encode message + Botan::PK_Signer signer(*privateKey, "EMSA4(SHA-256)"); + Botan::DataSource_Memory in(getMessage()); + Botan::byte buf[4096] = {0}; + while (size_t got = in.read(buf, sizeof(buf))) { + signer.update(buf, got); + } std::string signature = Botan::base64_encode(signer.signature(*(m_rng.get()))); - addSignature(signature); + addSignature(signature); } void License::createMessage(const std::string& user, const std::string& version, const std::string& type) { - lines.clear(); - lines.push_back(BEGIN_LICENSE); - lines.push_back(user); - lines.push_back(type); - std::string versionstring = "Coati " + getVersion(); - lines.push_back(versionstring); + lines.clear(); + lines.push_back(BEGIN_LICENSE); + lines.push_back(user); + lines.push_back(type); + std::string versionstring = "Coati " + getVersion(); + lines.push_back(versionstring); std::string pass9 = Botan::generate_passhash9(versionstring, *(m_rng.get())); - lines.push_back(pass9); + lines.push_back(pass9); } void License::writeToFile(const std::string& filename) { - std::ofstream licenseFile(filename); - for(std::string line : lines) - { - licenseFile << line << std::endl; - } + std::ofstream licenseFile(filename); + for(std::string line : lines) + { + licenseFile << line << std::endl; + } } bool License::loadFromString(const std::string& licenseText) { - lines.clear(); - std::istringstream license(licenseText); - return load(license); + lines.clear(); + std::istringstream license(licenseText); + return load(license); } bool License::load(std::istream& stream) { - lines.clear(); - std::string line; + lines.clear(); + std::string line; - while (getline(stream, line, '\n')) - { - std::string l = trim(line); - if (l.size()) - { - lines.push_back(l); - } - } + while (getline(stream, line, '\n')) + { + std::string l = trim(line); + if (l.size()) + { + lines.push_back(l); + } + } - if (lines.front() != BEGIN_LICENSE) - { - std::cout << "No License Header" << std::endl; - lines.insert(lines.begin(), BEGIN_LICENSE); - } + if (lines.front() != BEGIN_LICENSE) + { + std::cout << "No License Header" << std::endl; + lines.insert(lines.begin(), BEGIN_LICENSE); + } - if (lines.back() != END_LICENSE) - { - std::cout << "No License Footer" << std::endl; - lines.push_back(END_LICENSE); - } + if (lines.back() != END_LICENSE) + { + std::cout << "No License Footer" << std::endl; + lines.push_back(END_LICENSE); + } - if (lines.size() != 13) - { - return false; - } + if (lines.size() != 13) + { + return false; + } - return true; + return true; } bool License::loadFromFile(const std::string& filename) { - lines.clear(); - std::ifstream sigfile(filename); - return load(sigfile); + lines.clear(); + std::ifstream sigfile(filename); + return load(sigfile); } void License::print() { - std::cout << getLicenseString(); + std::cout << getLicenseString(); } void License::addSignature(const std::string& signature) { - if(lines.size() > 5) - { - std::cout << "signature already there" << std::endl; - return; - } - if (!signature.size()) { - std::cout << "signature is empty." << std::endl; - return; - } - std::stringstream ss; - for (size_t i = 0; i < signature.size(); i++) { - if(i % 55 == 0 && i != 0) - { - lines.push_back(ss.str()); - ss.str(""); - } - ss << signature[i]; - } - lines.push_back(ss.str()); - lines.push_back(END_LICENSE); + if(lines.size() > 5) + { + std::cout << "signature already there" << std::endl; + return; + } + if (!signature.size()) { + std::cout << "signature is empty." << std::endl; + return; + } + std::stringstream ss; + for (size_t i = 0; i < signature.size(); i++) { + if(i % 55 == 0 && i != 0) + { + lines.push_back(ss.str()); + ss.str(""); + } + ss << signature[i]; + } + lines.push_back(ss.str()); + lines.push_back(END_LICENSE); } bool License::isValid() const { - if(!m_publicKey) - { - std::cout << "No public key loaded" << std::endl; - return false; - } + if(!m_publicKey) + { + std::cout << "No public key loaded" << std::endl; + return false; + } try { @@ -251,68 +259,68 @@ bool License::isExpired() const std::string License::getPublicKeyFilename() const { - if(m_publicKeyFilename.empty()) - { - return "public-" + getVersion() + KEY_FILEENDING; - } - return m_publicKeyFilename; + if(m_publicKeyFilename.empty()) + { + return "public-" + getVersion() + KEY_FILEENDING; + } + return m_publicKeyFilename; } std::string License::getVersion() const { - if(m_version.empty()) - { - return "x"; - } - return m_version; + if(m_version.empty()) + { + return "x"; + } + return m_version; } bool License::loadPublicKeyFromFile(const std::string& filename) { - if (!filename.empty()) { - m_publicKeyFilename = filename; - } - if(boost::filesystem::exists(getPublicKeyFilename())) - { - Botan::RSA_PublicKey *rsaPublicKey = dynamic_cast(Botan::X509::load_key(getPublicKeyFilename())); - if (!rsaPublicKey) { - std::cout << "The loaded key is not a RSA key" << std::endl; - return false; - } - m_publicKey = std::shared_ptr(rsaPublicKey); - return true; - } - return false; + if (!filename.empty()) { + m_publicKeyFilename = filename; + } + if(boost::filesystem::exists(getPublicKeyFilename())) + { + Botan::RSA_PublicKey *rsaPublicKey = dynamic_cast(Botan::X509::load_key(getPublicKeyFilename())); + if (!rsaPublicKey) { + std::cout << "The loaded key is not a RSA key" << std::endl; + return false; + } + m_publicKey = std::shared_ptr(rsaPublicKey); + return true; + } + return false; } bool License::loadPublicKeyFromString(const std::string& publicKey) { - Botan::DataSource_Memory in(publicKey); - Botan::RSA_PublicKey *rsaPublicKey = dynamic_cast(Botan::X509::load_key(in)); - if (!rsaPublicKey) { - std::cout << "The loaded key is not a RSA key" << std::endl; - return false; - } - m_publicKey = std::shared_ptr(rsaPublicKey); - return true; + Botan::DataSource_Memory in(publicKey); + Botan::RSA_PublicKey *rsaPublicKey = dynamic_cast(Botan::X509::load_key(in)); + if (!rsaPublicKey) { + std::cout << "The loaded key is not a RSA key" << std::endl; + return false; + } + m_publicKey = std::shared_ptr(rsaPublicKey); + return true; } void License::setVersion(const std::string& version) { - if(!version.empty()) - { - m_version = version; - } + if(!version.empty()) + { + m_version = version; + } } std::string License::getLicenseString() const { - std::stringstream license; - for(std::string line : lines) - { - license << line << std::endl; - } - return license.str(); + std::stringstream license; + for(std::string line : lines) + { + license << line << std::endl; + } + return license.str(); } std::string License::hashLocation(const std::string& location) @@ -322,57 +330,57 @@ std::string License::hashLocation(const std::string& location) bool License::checkLocation(const std::string& location, const std::string& hash) { - return Botan::check_passhash9(location, hash); + return Botan::check_passhash9(location, hash); } std::string License::getLicenseEncodedString(const std::string& applicationLocation) const { - Botan::AutoSeeded_RNG rng; - std::vector file_contents; - std::stringstream input(getLicenseString()); + Botan::AutoSeeded_RNG rng; + std::vector file_contents; + std::stringstream input(getLicenseString()); - //prepare the license string to work with the botan cryptobox - while(input.good()) - { - Botan::byte filebuf[4096] = { 0 }; - input.read((char*)filebuf, sizeof(filebuf)); - size_t got = input.gcount(); + //prepare the license string to work with the botan cryptobox + while(input.good()) + { + Botan::byte filebuf[4096] = { 0 }; + input.read((char*)filebuf, sizeof(filebuf)); + size_t got = input.gcount(); - file_contents.insert(file_contents.end(), filebuf, filebuf+got); - } + file_contents.insert(file_contents.end(), filebuf, filebuf+got); + } - std::string ret = Botan::CryptoBox::encrypt(&file_contents[0], file_contents.size(),getEncodeKey(applicationLocation),rng); + std::string ret = Botan::CryptoBox::encrypt(&file_contents[0], file_contents.size(),getEncodeKey(applicationLocation),rng); - //remove Botan Cryptobox begin and end - //should not be in the application settings - ret = ret.substr(40,ret.length()-78); + //remove Botan Cryptobox begin and end + //should not be in the application settings + ret = ret.substr(40,ret.length()-78); - return ret; + return ret; } bool License::loadFromEncodedString(const std::string& encodedLicense, const std::string& applicationLocation) { - try { - //add cryptobox begin and end to loaded string - std::string crypbobxInput = "-----BEGIN BOTAN CRYPTOBOX MESSAGE-----\n"; - crypbobxInput += encodedLicense; - crypbobxInput += "-----END BOTAN CRYPTOBOX MESSAGE-----"; + try { + //add cryptobox begin and end to loaded string + std::string crypbobxInput = "-----BEGIN BOTAN CRYPTOBOX MESSAGE-----\n"; + crypbobxInput += encodedLicense; + crypbobxInput += "-----END BOTAN CRYPTOBOX MESSAGE-----"; - //decrypt license - loadFromString(Botan::CryptoBox::decrypt(crypbobxInput,getEncodeKey(applicationLocation))); - } - catch(...) - { - //loaded string from application settings is invalid - return false; - } - return true; + //decrypt license + loadFromString(Botan::CryptoBox::decrypt(crypbobxInput,getEncodeKey(applicationLocation))); + } + catch(...) + { + //loaded string from application settings is invalid + return false; + } + return true; } std::string License::getEncodeKey(const std::string applicationLocation) const { - Botan::PBKDF *pbkdf = Botan::get_pbkdf("PBKDF2(SHA-256)"); - Botan::secure_vector salt = Botan::base64_decode("34zA54n60v4CxjY5n20k3J40c976n690", 32); - Botan::AutoSeeded_RNG rng; - return pbkdf->derive_key(32, applicationLocation, &salt[0], salt.size(), 10000).as_string(); + Botan::PBKDF *pbkdf = Botan::get_pbkdf("PBKDF2(SHA-256)"); + Botan::secure_vector salt = Botan::base64_decode("34zA54n60v4CxjY5n20k3J40c976n690", 32); + Botan::AutoSeeded_RNG rng; + return pbkdf->derive_key(32, applicationLocation, &salt[0], salt.size(), 10000).as_string(); } diff --git a/src/test/GeneratorTestSuite.h b/src/test/GeneratorTestSuite.h index 8d85194e..d24e6d7a 100644 --- a/src/test/GeneratorTestSuite.h +++ b/src/test/GeneratorTestSuite.h @@ -5,8 +5,6 @@ #include "License.h" #include "Generator.h" -#include "botan_all.h" - class GeneratorTestSuite : public CxxTest::TestSuite { public: