// Generic login function
bool SecureDataManager::login(const ByteString& passphrase, const ByteString& encryptedKey)
{
	// Log out first
	this->logout();

	// First, take the salt from the encrypted key
	ByteString salt = encryptedKey.substr(0,8);

	// Then, take the IV from the encrypted key
	ByteString IV = encryptedKey.substr(8, aes->getBlockSize());

	// Now, take the encrypted data from the encrypted key
	ByteString encryptedKeyData = encryptedKey.substr(8 + aes->getBlockSize());

	// Derive the PBE key
	AESKey* pbeKey = NULL;

	if (!RFC4880::PBEDeriveKey(passphrase, salt, &pbeKey))
	{
		return false;
	}

	// Decrypt the key data
	ByteString decryptedKeyData;
	ByteString finalBlock;

	// NOTE: The login will fail here if incorrect passphrase is supplied
	if (!aes->decryptInit(pbeKey, SymMode::CBC, IV) ||
	    !aes->decryptUpdate(encryptedKeyData, decryptedKeyData) ||
	    !aes->decryptFinal(finalBlock))
	{
		delete pbeKey;

		return false;
	}

	delete pbeKey;

	decryptedKeyData += finalBlock;

	// Check the magic
	if (decryptedKeyData.substr(0, 3) != magic)
	{
		// The passphrase was incorrect
		DEBUG_MSG("Incorrect passphrase supplied");

		return false;
	}

	// Strip off the magic
	ByteString key = decryptedKeyData.substr(3);

	// And mask the key
	decryptedKeyData.wipe();

	MutexLocker lock(dataMgrMutex);
	remask(key);

	return true;
}
// Encode into PKCS#8 DER
ByteString OSSLECPrivateKey::PKCS8Encode()
{
	ByteString der;
	if (eckey == NULL) return der;
	EVP_PKEY* pkey = EVP_PKEY_new();
	if (pkey == NULL) return der;
	if (!EVP_PKEY_set1_EC_KEY(pkey, eckey))
	{
		EVP_PKEY_free(pkey);
		return der;
	}
	PKCS8_PRIV_KEY_INFO* p8inf = EVP_PKEY2PKCS8(pkey);
	EVP_PKEY_free(pkey);
	if (p8inf == NULL) return der;
	int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf, NULL);
	if (len < 0)
	{
		PKCS8_PRIV_KEY_INFO_free(p8inf);
		return der;
	}
	der.resize(len);
	unsigned char* priv = &der[0];
	int len2 = i2d_PKCS8_PRIV_KEY_INFO(p8inf, &priv);
	PKCS8_PRIV_KEY_INFO_free(p8inf);
	if (len2 != len) der.wipe();
	return der;
}
void GOSTTests::readTmpFile(ByteString& data)
{
	unsigned char buf[256];

	data.wipe();

#ifdef _WIN32
	FILE* in = fopen("gost-hashtest-out.tmp", "r");
#else
	FILE* in = fopen("gost-hashtest-out.tmp", "rb");
#endif
	CPPUNIT_ASSERT(in != NULL);

	int read = 0;

	do
	{
		read = fread(buf, 1, 256, in);

		data += ByteString(buf, read);
	}
	while (read > 0);

	CPPUNIT_ASSERT(read == 0);
	CPPUNIT_ASSERT(!fclose(in));
}
Exemple #4
0
// Generate random data
bool BotanRNG::generateRandom(ByteString& data, const size_t len)
{
	data.wipe(len);

	if (len > 0)
		rng->randomize(&data[0], len);

	return true;
}
// Encrypt the supplied data
bool SecureDataManager::encrypt(const ByteString& plaintext, ByteString& encrypted)
{
	// Check the object logged in state
	if ((!userLoggedIn && !soLoggedIn) || (maskedKey.size() != 32))
	{
		return false;
	}

	AESKey theKey(256);
	ByteString unmaskedKey;

	{
		MutexLocker lock(dataMgrMutex);

		unmask(unmaskedKey);

		theKey.setKeyBits(unmaskedKey);

		remask(unmaskedKey);
	}

	// Wipe encrypted data block
	encrypted.wipe();

	// Generate random IV
	ByteString IV;

	if (!rng->generateRandom(IV, aes->getBlockSize())) return false;

	ByteString finalBlock;

	if (!aes->encryptInit(&theKey, SymMode::CBC, IV) ||
	    !aes->encryptUpdate(plaintext, encrypted) ||
	    !aes->encryptFinal(finalBlock))
	{
		return false;
	}

	encrypted += finalBlock;

	// Add IV to output data
	encrypted = IV + encrypted;

	return true;
}
Exemple #6
0
void HashTests::readTmpFile(ByteString& data)
{
	unsigned char buf[256];

	data.wipe();

	FILE* in = fopen("shsmv2-hashtest-out.tmp", "r");
	CPPUNIT_ASSERT(in != NULL);

	int read = 0;

	do
	{
		read = fread(buf, 1, 256, in);

		data += ByteString(buf, read);
	}
	while (read > 0);

	CPPUNIT_ASSERT(read == 0);
	CPPUNIT_ASSERT(!fclose(in));
}
// Encryption functions
bool BotanSymmetricAlgorithm::encryptInit(const SymmetricKey* key, const std::string mode /* = "cbc" */, const ByteString& IV /* = ByteString()*/, bool padding /* = true */)
{
	// Call the superclass initialiser
	if (!SymmetricAlgorithm::encryptInit(key, mode, IV, padding))
	{
		return false;
	}

	// Check the IV
	if ((IV.size() > 0) && (IV.size() != getBlockSize()))
	{
		ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize());

		ByteString dummy;
		SymmetricAlgorithm::encryptFinal(dummy);

		return false;
	}

	ByteString iv;

	if (IV.size() > 0)
	{
		iv = IV;
	}
	else
	{
		iv.wipe(getBlockSize());
	}

	// Set the padding mode (PCKS7 or NoPadding)
	if (padding)
	{
		currentPaddingMode = "PKCS7";
	}
	else
	{
		currentPaddingMode = "NoPadding";
	}

	// Determine the cipher
	std::string cipherName = getCipher();

	if (cipherName == "")
	{
		ERROR_MSG("Invalid encryption cipher");

		ByteString dummy;
		SymmetricAlgorithm::encryptFinal(dummy);

		return false;
	}

	// Allocate the context
	try
	{
		Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
		Botan::InitializationVector botanIV = Botan::InitializationVector(IV.const_byte_str(), IV.size());
		if (mode == "ecb")
		{
			cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, Botan::ENCRYPTION));
		}
		else
		{
			cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, botanIV, Botan::ENCRYPTION));
		}
		cryption->start_msg();
	}
	catch (...)
	{
		ERROR_MSG("Failed to create the encryption token");

		ByteString dummy;
		SymmetricAlgorithm::encryptFinal(dummy);

		delete cryption;
		cryption = NULL;

		return false;
	}

	return true;
}
Exemple #8
0
// Generate random data
bool OSSLRNG::generateRandom(ByteString& data, const size_t len)
{
	data.wipe(len);

	return RAND_bytes(&data[0], len);
}
// Generic function for creating an encrypted version of the key from the specified passphrase
bool SecureDataManager::pbeEncryptKey(const ByteString& passphrase, ByteString& encryptedKey)
{
	// Generate salt
	ByteString salt;

	if (!rng->generateRandom(salt, 8)) return false;

	// Derive the key using RFC4880 PBE
	AESKey* pbeKey = NULL;

	if (!RFC4880::PBEDeriveKey(passphrase, salt, &pbeKey))
	{
		return false;
	}

	// Add the salt
	encryptedKey.wipe();
	encryptedKey += salt;

	// Generate random IV
	ByteString IV;

	if (!rng->generateRandom(IV, aes->getBlockSize())) return false;

	// Add the IV
	encryptedKey += IV;

	// Encrypt the data
	ByteString block;

	if (!aes->encryptInit(pbeKey, SymMode::CBC, IV))
	{
		delete pbeKey;

		return false;
	}

	// First, add the magic
	if (!aes->encryptUpdate(magic, block))
	{
		delete pbeKey;

		return false;
	}

	encryptedKey += block;

	// Then, add the key itself
	ByteString key;

	{
		MutexLocker lock(dataMgrMutex);

		unmask(key);

		bool rv = aes->encryptUpdate(key, block);

		remask(key);

		if (!rv)
		{
			delete pbeKey;

			return false;
		}
	}

	encryptedKey += block;

	// And finalise encryption
	if (!aes->encryptFinal(block))
	{
		delete pbeKey;

		return false;
	}

	encryptedKey += block;

	delete pbeKey;

	return true;
}
Exemple #10
0
bool BotanDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey)
{
	// Check parameters
	if ((ppSymmetricKey == NULL) ||
	    (publicKey == NULL) ||
	    (privateKey == NULL))
	{
		return false;
	}

	// Get keys
	Botan::DH_PublicKey* pub = ((BotanDHPublicKey*) publicKey)->getBotanKey();
	BotanDH_PrivateKey* priv = ((BotanDHPrivateKey*) privateKey)->getBotanKey();
	if (pub == NULL || priv == NULL || priv->impl == NULL)
	{
		ERROR_MSG("Failed to get Botan DH keys");

		return false;
	}

	// Derive the secret
	Botan::SymmetricKey sk;
	try
	{
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33)
		BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
		Botan::PK_Key_Agreement ka(*priv->impl, *rng->getRNG(), "Raw");
#else
		Botan::PK_Key_Agreement ka(*priv->impl, "Raw");
#endif
		sk = ka.derive_key(0, pub->public_value());
	}
	catch (std::exception& e)
	{
		ERROR_MSG("Botan DH key agreement failed: %s", e.what());

		return false;
	}

	ByteString secret;

	// We compensate that Botan removes leading zeros
	int size = ((BotanDHPublicKey*) publicKey)->getOutputLength();
	int keySize = sk.length();
	secret.wipe(size);
	memcpy(&secret[0] + size - keySize, sk.begin(), keySize);

	*ppSymmetricKey = new SymmetricKey(secret.size() * 8);
	if (*ppSymmetricKey == NULL)
	{
		ERROR_MSG("Can't create DH secret");

		return false;
	}
	if (!(*ppSymmetricKey)->setKeyBits(secret))
	{
		delete *ppSymmetricKey;
		*ppSymmetricKey = NULL;
		return false;
	}

	return true;
}