// Encode into PKCS#8 DER
ByteString BotanRSAPrivateKey::PKCS8Encode()
{
	ByteString der;
	createBotanKey();
	if (rsa == NULL) return der;
#if BOTAN_VERSION_MINOR == 11
	const Botan::secure_vector<Botan::byte> ber = Botan::PKCS8::BER_encode(*rsa);
#else
	const Botan::SecureVector<Botan::byte> ber = Botan::PKCS8::BER_encode(*rsa);
#endif
	der.resize(ber.size());
	memcpy(&der[0], &ber[0], ber.size());
	return der;
}
// Decode from PKCS#8 BER
bool BotanECDHPrivateKey::PKCS8Decode(const ByteString& ber)
{
	Botan::DataSource_Memory source(ber.const_byte_str(), ber.size());
	if (source.end_of_data()) return false;
#if BOTAN_VERSION_MINOR == 11
	Botan::secure_vector<Botan::byte> keydata;
#else
	Botan::SecureVector<Botan::byte> keydata;
#endif
	Botan::AlgorithmIdentifier alg_id;
	const Botan::OID oid("1.2.840.10045.2.1");
	Botan::ECDH_PrivateKey* key = NULL;
	try
	{
		Botan::BER_Decoder(source)
		.start_cons(Botan::SEQUENCE)
			.decode_and_check<size_t>(0, "Unknown PKCS #8 version number")
			.decode(alg_id)
			.decode(keydata, Botan::OCTET_STRING)
			.discard_remaining()
		.end_cons();
		if (keydata.empty())
			throw Botan::Decoding_Error("PKCS #8 private key decoding failed");
		// Botan defines == but not != ?!
		if (!(alg_id.oid == oid))
		{
			ERROR_MSG("Decoded private key not ECDH");

			return false;
		}
		key = new Botan::ECDH_PrivateKey(alg_id, keydata);
		if (key == NULL) return false;

		setFromBotan(key);

		delete key;
	}
	catch (std::exception& e)
	{
		ERROR_MSG("Decode failed on %s", e.what());

		return false;
	}

	return true;
}
// Decode from PKCS#8 BER
bool BotanRSAPrivateKey::PKCS8Decode(const ByteString& ber)
{
	Botan::DataSource_Memory source(ber.const_byte_str(), ber.size());
	if (source.end_of_data()) return false;
#if BOTAN_VERSION_MINOR == 11
	Botan::secure_vector<Botan::byte> keydata;
#else
	Botan::SecureVector<Botan::byte> keydata;
#endif
	Botan::AlgorithmIdentifier alg_id;
	Botan::RSA_PrivateKey* key = NULL;
	try
	{

		Botan::BER_Decoder(source)
		.start_cons(Botan::SEQUENCE)
			.decode_and_check<size_t>(0, "Unknown PKCS #8 version number")
			.decode(alg_id)
			.decode(keydata, Botan::OCTET_STRING)
			.discard_remaining()
		.end_cons();
		if (keydata.empty())
			throw Botan::Decoding_Error("PKCS #8 private key decoding failed");
		if (Botan::OIDS::lookup(alg_id.oid).compare("RSA"))
		{
			ERROR_MSG("Decoded private key not RSA");

			return false;
		}
		BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
		key = new Botan::RSA_PrivateKey(alg_id, keydata, *rng->getRNG());
		if (key == NULL) return false;

		setFromBotan(key);

		delete key;
	}
	catch (std::exception& e)
	{
		ERROR_MSG("Decode failed on %s", e.what());

		return false;
	}

	return true;
}
// Encode into PKCS#8 DER
ByteString BotanGOSTPrivateKey::PKCS8Encode()
{
	ByteString der;
	createBotanKey();
	if (eckey == NULL) return der;
	// Force EC_DOMPAR_ENC_OID
	const size_t PKCS8_VERSION = 0;
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
	const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
	const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters);
	const Botan::secure_vector<Botan::byte> ber =
		Botan::DER_Encoder()
		.start_cons(Botan::SEQUENCE)
		    .encode(PKCS8_VERSION)
		    .encode(alg_id)
		    .encode(eckey->private_key_bits(), Botan::OCTET_STRING)
		.end_cons()
	    .get_contents();
#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
	const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
	const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters);
	const Botan::secure_vector<Botan::byte> ber =
		Botan::DER_Encoder()
		.start_cons(Botan::SEQUENCE)
		    .encode(PKCS8_VERSION)
		    .encode(alg_id)
		    .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING)
		.end_cons()
	    .get_contents();
#else
	const Botan::MemoryVector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
	const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters);
	const Botan::SecureVector<Botan::byte> ber =
		Botan::DER_Encoder()
		.start_cons(Botan::SEQUENCE)
		.encode(PKCS8_VERSION)
		    .encode(alg_id)
		    .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING)
		.end_cons()
	    .get_contents();
#endif
	der.resize(ber.size());
	memcpy(&der[0], &ber[0], ber.size());
        return der;
}
Example #5
0
    // Returns # of bytes of compressed message
    size_t run_compression(size_t level,
                           Botan::Compression_Algorithm &c,
                           Botan::Decompression_Algorithm &d,
                           const Botan::secure_vector<uint8_t> &msg)
    {
        Botan::secure_vector<uint8_t> compressed = msg;

        c.start(level);
        c.finish(compressed);

        const size_t c_size = compressed.size();

        Botan::secure_vector<uint8_t> decompressed = compressed;
        d.start();
        d.finish(decompressed);

        EXPECT_EQ(msg, decompressed) << "compression round tripped";
        return c_size;
    }
// Encode into PKCS#8 DER
ByteString BotanECDHPrivateKey::PKCS8Encode()
{
	ByteString der;
	createBotanKey();
	if (eckey == NULL) return der;
	const size_t PKCS8_VERSION = 0;
	// No OID for ECDH
	const Botan::OID oid("1.2.840.10045.2.1");
	// Force EC_DOMPAR_ENC_OID
#if BOTAN_VERSION_MINOR == 11
	const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
	const Botan::AlgorithmIdentifier alg_id(oid, parameters);
	const Botan::secure_vector<Botan::byte> ber =
		Botan::DER_Encoder()
		.start_cons(Botan::SEQUENCE)
		    .encode(PKCS8_VERSION)
		    .encode(alg_id)
		    .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING)
		.end_cons()
	    .get_contents();
#else
	const Botan::MemoryVector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
	const Botan::AlgorithmIdentifier alg_id(oid, parameters);
	const Botan::SecureVector<Botan::byte> ber =
		Botan::DER_Encoder()
		.start_cons(Botan::SEQUENCE)
		    .encode(PKCS8_VERSION)
		    .encode(alg_id)
		    .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING)
		.end_cons()
	    .get_contents();
#endif
	der.resize(ber.size());
	memcpy(&der[0], &ber[0], ber.size());
	return der;
}
Example #7
0
      void go() override
         {
         const std::string comp_type = get_arg("type");
         const size_t buf_size = get_arg_sz("buf-size");
         const size_t comp_level = get_arg_sz("level");

         std::unique_ptr<Botan::Compression_Algorithm> compress;

         compress.reset(Botan::make_compressor(comp_type));

         if(!compress)
            {
            throw CLI_Error_Unsupported("Compression", comp_type);
            }

         const std::string in_file = get_arg("file");
         std::ifstream in(in_file, std::ios::binary);

         if(!in.good())
            {
            throw CLI_IO_Error("reading", in_file);
            }

         const std::string out_file = output_filename(in_file, comp_type);
         std::ofstream out(out_file, std::ios::binary);
         if(!in.good())
            {
            throw CLI_IO_Error("writing", out_file);
            }

         Botan::secure_vector<uint8_t> buf;

         compress->start(comp_level);

         while(in.good())
            {
            buf.resize(buf_size);
            in.read(reinterpret_cast<char*>(&buf[0]), buf.size());
            buf.resize(in.gcount());

            compress->update(buf);

            out.write(reinterpret_cast<const char*>(&buf[0]), buf.size());
            }

         buf.clear();
         compress->finish(buf);
         out.write(reinterpret_cast<const char*>(&buf[0]), buf.size());
         out.close();
         }
Example #8
0
      void go() override
         {
         const size_t buf_size = get_arg_sz("buf-size");
         const std::string in_file = get_arg("file");
         std::string out_file, suffix;
         parse_extension(in_file, out_file, suffix);

         std::ifstream in(in_file, std::ios::binary);

         if(!in.good())
            {
            throw CLI_IO_Error("reading", in_file);
            }

         std::unique_ptr<Botan::Decompression_Algorithm> decompress;

         decompress.reset(Botan::make_decompressor(suffix));

         if(!decompress)
            {
            throw CLI_Error_Unsupported("Decompression", suffix);
            }

         std::ofstream out(out_file, std::ios::binary);
         if(!out.good())
            {
            throw CLI_IO_Error("writing", out_file);
            }

         Botan::secure_vector<uint8_t> buf;

         decompress->start();

         while(in.good())
            {
            buf.resize(buf_size);
            in.read(reinterpret_cast<char*>(&buf[0]), buf.size());
            buf.resize(in.gcount());

            decompress->update(buf);

            out.write(reinterpret_cast<const char*>(&buf[0]), buf.size());
            }

         buf.clear();
         decompress->finish(buf);
         out.write(reinterpret_cast<const char*>(&buf[0]), buf.size());
         out.close();
         }
Example #9
0
// Decryption functions
bool BotanRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData,
		       ByteString& data, const AsymMech::Type padding)
{
	// Check if the private key is the right type
	if (!privateKey->isOfType(BotanRSAPrivateKey::type))
	{
		ERROR_MSG("Invalid key type supplied");

		return false;
	}

	std::string eme;

	switch (padding)
	{
		case AsymMech::RSA_PKCS:
			eme = "PKCS1v15";
			break;
		case AsymMech::RSA_PKCS_OAEP:
			eme = "EME1(SHA-160)";
			break;
		case AsymMech::RSA:
			eme = "Raw";
			break;
		default:
			ERROR_MSG("Invalid padding mechanism supplied (%i)", padding);

			return false;
	}

	BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) privateKey;
	Botan::RSA_PrivateKey* botanKey = pk->getBotanKey();

	if (!botanKey)
	{
		ERROR_MSG("Could not get the Botan private key");

		return false;
	}

	Botan::PK_Decryptor_EME* decryptor = NULL;
	try
	{
		decryptor = new Botan::PK_Decryptor_EME(*botanKey, eme);
	}
	catch (...)
	{
		ERROR_MSG("Could not create the decryptor token");

		return false;
	}

	// Perform the decryption operation
#if BOTAN_VERSION_MINOR == 11
	Botan::secure_vector<Botan::byte> decResult;
#else
	Botan::SecureVector<Botan::byte> decResult;
#endif
	try
	{
		decResult = decryptor->decrypt(encryptedData.const_byte_str(), encryptedData.size());
	}
	catch (...)
	{
		ERROR_MSG("Could not decrypt the data");

		delete decryptor;

		return false;
	}

	// Return the result
	if (padding == AsymMech::RSA)
	{
		// We compensate that Botan removes leading zeros
		int modSize = pk->getN().size();
		int decSize = decResult.size();
		data.resize(modSize);
#if BOTAN_VERSION_MINOR == 11
		memcpy(&data[0] + modSize - decSize, decResult.data(), decSize);
#else
		memcpy(&data[0] + modSize - decSize, decResult.begin(), decSize);
#endif
	}
	else
	{
		data.resize(decResult.size());
#if BOTAN_VERSION_MINOR == 11
		memcpy(&data[0], decResult.data(), decResult.size());
#else
		memcpy(&data[0], decResult.begin(), decResult.size());
#endif
	}

	delete decryptor;

	return true;
}
Example #10
0
std::vector<unsigned char> Base64::decode(const std::string &str)
{
    bool ignore_ws = true;
    Botan::secure_vector<Botan::byte> output = Botan::base64_decode(str, ignore_ws);
    return std::vector<unsigned char>(output.cbegin(), output.cend());
}
// Wrap/Unwrap keys
bool BotanAES::wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out)
{
	// Check key bit length; AES only supports 128, 192 or 256 bit keys
	if ((key->getBitLen() != 128) &&
	    (key->getBitLen() != 192) &&
	    (key->getBitLen() != 256))
	{
		ERROR_MSG("Invalid AES key length (%d bits)", key->getBitLen());

		return false;
	}

	// Determine the wrapping mode
	if (mode == SymWrap::AES_KEYWRAP)
	{
		// RFC 3394 AES key wrap
		if (in.size() < 16)
		{
			ERROR_MSG("key data to wrap too small");

			return false;
		}
		if ((in.size() % 8) != 0)
		{
			ERROR_MSG("key data to wrap not aligned");

			return false;
		}

#if BOTAN_VERSION_MINOR == 11
		Botan::secure_vector<Botan::byte> data(in.size());
		memcpy(data.data(), in.const_byte_str(), in.size());
		Botan::secure_vector<Botan::byte> wrapped;
#else
		Botan::MemoryVector<Botan::byte> data(in.size());
		memcpy(data.begin(), in.const_byte_str(), in.size());
		Botan::SecureVector<Botan::byte> wrapped;
#endif
		Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
		Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
		try
		{
			wrapped = Botan::rfc3394_keywrap(data, botanKey, af);
		}
		catch (...)
		{
			ERROR_MSG("AES key wrap failed");

			return false;
		}
		out.resize(wrapped.size());
#if BOTAN_VERSION_MINOR == 11
		memcpy(&out[0], wrapped.data(), out.size());
#else
		memcpy(&out[0], wrapped.begin(), out.size());
#endif

		return  true;
	}
#ifdef HAVE_AES_KEY_WRAP_PAD
	else if (mode == SymWrap::AES_KEYWRAP_PAD)
	{
		// RFC 5649 AES key wrap with pad
#if BOTAN_VERSION_MINOR == 11
		Botan::secure_vector<Botan::byte> data(in.size());
		memcpy(data.data(), in.const_byte_str(), in.size());
		Botan::secure_vector<Botan::byte> wrapped;
#else
		Botan::MemoryVector<Botan::byte> data(in.size());
		memcpy(data.begin(), in.const_byte_str(), in.size());
		Botan::SecureVector<Botan::byte> wrapped;
#endif
		Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
		Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
		try
		{
			wrapped = Botan::rfc5649_keywrap(data, botanKey, af);
		}
		catch (...)
		{
			ERROR_MSG("AES key wrap failed");

			return false;
		}
		out.resize(wrapped.size());
#if BOTAN_VERSION_MINOR == 11
		memcpy(&out[0], wrapped.data(), out.size());
#else
		memcpy(&out[0], wrapped.begin(), out.size());
#endif

		return  true;
	}
#endif
	else
	{
		ERROR_MSG("unknown AES key wrap mode %i", mode);

		return false;
	}
}