示例#1
0
// 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;
}
示例#2
0
// Decrypt the supplied data
bool SecureDataManager::decrypt(const ByteString& encrypted, ByteString& plaintext)
{
	// Check the object logged in state
	if ((!userLoggedIn && !soLoggedIn) || (maskedKey.size() != 32))
	{
		return false;
	}

	// Do not attempt decryption of empty byte strings
	if (encrypted.size() == 0)
	{
		plaintext = ByteString("");
		return true;
	}

	AESKey theKey(256);
	ByteString unmaskedKey;

	{
		MutexLocker lock(dataMgrMutex);

		unmask(unmaskedKey);

		theKey.setKeyBits(unmaskedKey);

		remask(unmaskedKey);
	}

	// Take the IV from the input data
	ByteString IV = encrypted.substr(0, aes->getBlockSize());

	if (IV.size() != aes->getBlockSize())
	{
		ERROR_MSG("Invalid IV in encrypted data");

		return false;
	}

	ByteString finalBlock;

	if (!aes->decryptInit(&theKey, SymMode::CBC, IV) ||
	    !aes->decryptUpdate(encrypted.substr(aes->getBlockSize()), plaintext) ||
	    !aes->decryptFinal(finalBlock))
	{
		return false;
	}

	plaintext += finalBlock;

	return true;
}
void GOSTTests::testHash()
{
	// Get an RNG and GOST R 34.11-94 hash instance
	CPPUNIT_ASSERT((rng = CryptoFactory::i()->getRNG()) != NULL);
	CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm("gost")) != NULL);

	// Generate some random input data
	ByteString b;
	ByteString osslHash, gostHash;

	CPPUNIT_ASSERT(rng->generateRandom(b, 53287));

	// Write it to file
	writeTmpFile(b);

	// Use OpenSSL externally to hash it
#ifndef _WIN32
	CPPUNIT_ASSERT(system("openssl dgst -engine gost -md_gost94 -binary < gost-hashtest.tmp > gost-hashtest-out.tmp 2> /dev/null") == 0);
#else
	CPPUNIT_ASSERT(system("openssl dgst -engine gost -md_gost94 -binary < gost-hashtest.tmp > gost-hashtest-out.tmp 2> nul") == 0);
#endif

	// Read the hash from file
	readTmpFile(osslHash);

	// Now recreate the hash using our implementation in a single operation
	CPPUNIT_ASSERT(hash->hashInit());
	CPPUNIT_ASSERT(hash->hashUpdate(b));
	CPPUNIT_ASSERT(hash->hashFinal(gostHash));

	CPPUNIT_ASSERT(osslHash == gostHash);

	// Now recreate the hash in a single part operation
	gostHash.wipe();

	CPPUNIT_ASSERT(hash->hashInit());
	CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
	CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
	CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
	CPPUNIT_ASSERT(hash->hashFinal(gostHash));

	CPPUNIT_ASSERT(osslHash == gostHash);

	CryptoFactory::i()->recycleHashAlgorithm(hash);

	hash = NULL;
	rng = NULL;
}
示例#4
0
void HashTests::testMD5()
{
	// Get an RNG and MD5 hash instance
	CPPUNIT_ASSERT((rng = CryptoFactory::i()->getRNG()) != NULL);
	CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm("md5")) != NULL);

	// Generate some random input data
	ByteString b;
	ByteString osslHash, shsmHash;

	CPPUNIT_ASSERT(rng->generateRandom(b, 52237));

	// Write it to file
	writeTmpFile(b);

	// Use OpenSSL externally to hash it
	CPPUNIT_ASSERT(system("cat shsmv2-hashtest.tmp | openssl md5 -binary > shsmv2-hashtest-out.tmp") == 0);

	// Read the hash from file
	readTmpFile(osslHash);

	// Now recreate the hash using our implementation in a single operation
	CPPUNIT_ASSERT(hash->hashInit());
	CPPUNIT_ASSERT(hash->hashUpdate(b));
	CPPUNIT_ASSERT(hash->hashFinal(shsmHash));

	CPPUNIT_ASSERT(osslHash == shsmHash);

	// Now recreate the hash in a multiple part operation
	shsmHash.wipe();

	CPPUNIT_ASSERT(hash->hashInit());
	CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
	CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
	CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
	CPPUNIT_ASSERT(hash->hashFinal(shsmHash));

	CPPUNIT_ASSERT(osslHash == shsmHash);

	CryptoFactory::i()->recycleHashAlgorithm(hash);

	hash = NULL;
	rng = NULL;
}
void GOSTTests::testHmac()
{
	// Get an RNG and HMAC GOST R34.11-94 instance
	CPPUNIT_ASSERT((rng = CryptoFactory::i()->getRNG()) != NULL);
	CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm("hmac-gost")) != NULL);

	// Key
	char pk[] = "a_key_for_HMAC-GOST_R-34.11-94_test";
	ByteString k((unsigned char *)pk, sizeof(pk));
	SymmetricKey key;
	CPPUNIT_ASSERT(key.setKeyBits(k));

	// Generate some random input data
	ByteString b;

	CPPUNIT_ASSERT(rng->generateRandom(b, 53287));

	// Sign the MAC using our implementation in a single operation
	ByteString mResult1;

	CPPUNIT_ASSERT(mac->signInit(&key));
	CPPUNIT_ASSERT(mac->signUpdate(b));
	CPPUNIT_ASSERT(mac->signFinal(mResult1));

	// Sign the MAC in a multiple part operation
	ByteString mResult2;

	CPPUNIT_ASSERT(mac->signInit(&key));
	CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567)));
	CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989)));
	CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989)));
	CPPUNIT_ASSERT(mac->signFinal(mResult2));

	// Now verify the MAC using our implementation in a single operation
	CPPUNIT_ASSERT(mac->verifyInit(&key));
	CPPUNIT_ASSERT(mac->verifyUpdate(b));
	CPPUNIT_ASSERT(mac->verifyFinal(mResult2));

	// Now verify the MAC in a multiple part operation
	CPPUNIT_ASSERT(mac->verifyInit(&key));
	CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567)));
	CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989)));
	CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989)));
	CPPUNIT_ASSERT(mac->verifyFinal(mResult1));

	// Check if bad key is refused
	mResult1[10] ^= 0x11;
	CPPUNIT_ASSERT(mac->verifyInit(&key));
	CPPUNIT_ASSERT(mac->verifyUpdate(b));
	CPPUNIT_ASSERT(!mac->verifyFinal(mResult1));

	CryptoFactory::i()->recycleMacAlgorithm(mac);

	mac = NULL;
	rng = NULL;
}
示例#6
0
// Set from OpenSSL representation
void OSSLGOSTPublicKey::setFromOSSL(const EVP_PKEY* pkey)
{
	ByteString der;
	int len = i2d_PUBKEY((EVP_PKEY*) pkey, NULL);
	if (len != 37 + 64)
	{
		ERROR_MSG("bad GOST public key encoding length %d", len);
		return;
	}
	der.resize(len);
	unsigned char *p = &der[0];
	i2d_PUBKEY((EVP_PKEY*) pkey, &p);
	// can check: der is prefix + 64 bytes
	setQ(der.substr(37));

	ByteString inEC;
	const EC_KEY* eckey = (const EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey);
	int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
	inEC.resize(i2d_ASN1_OBJECT(OBJ_nid2obj(nid), NULL));
	p = &inEC[0];
	i2d_ASN1_OBJECT(OBJ_nid2obj(nid), &p);
	setEC(inEC);
}
示例#7
0
void DSATests::testSigningVerifying()
{
	AsymmetricKeyPair* kp;

	// Key sizes to test
	std::vector<size_t> keySizes;
#ifndef WITH_FIPS
	keySizes.push_back(512);
	keySizes.push_back(768);
	keySizes.push_back(1024);
	keySizes.push_back(1536);
#else
	keySizes.push_back(1024);
#endif
#ifndef WITH_BOTAN
	keySizes.push_back(2048);
#endif

	// Mechanisms to test
	std::vector<AsymMech::Type> mechanisms;
	mechanisms.push_back(AsymMech::DSA_SHA1);
	mechanisms.push_back(AsymMech::DSA_SHA224);
	mechanisms.push_back(AsymMech::DSA_SHA256);

	for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
	{
		// Generate parameters
		AsymmetricParameters* p;

		CPPUNIT_ASSERT(dsa->generateParameters(&p, (void*) *k));

		// Generate key-pair
		CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p));

		// Generate some data to sign
		ByteString dataToSign;

		RNG* rng = CryptoFactory::i()->getRNG();

		CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567));

		// Test mechanisms that perform internal hashing
		for (std::vector<AsymMech::Type>::iterator m = mechanisms.begin(); m != mechanisms.end(); m++)
		{
			ByteString blockSignature, singlePartSignature;

			// Sign the data in blocks
			CPPUNIT_ASSERT(dsa->signInit(kp->getPrivateKey(), *m));
			CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(0, 134)));
			CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(134, 289)));
			CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(134 + 289)));
			CPPUNIT_ASSERT(dsa->signFinal(blockSignature));

			// Sign the data in one pass
			CPPUNIT_ASSERT(dsa->sign(kp->getPrivateKey(), dataToSign, singlePartSignature, *m));

			// Now perform multi-pass verification
			CPPUNIT_ASSERT(dsa->verifyInit(kp->getPublicKey(), *m));
			CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(0, 125)));
			CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(125, 247)));
			CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(125 + 247)));
			CPPUNIT_ASSERT(dsa->verifyFinal(blockSignature));

			// And single-pass verification
			CPPUNIT_ASSERT(dsa->verify(kp->getPublicKey(), dataToSign, singlePartSignature, *m));
		}

		// Test mechanisms that do not perform internal hashing
		CPPUNIT_ASSERT(rng->generateRandom(dataToSign, *k >= 2048 ? 32 : 20));

		// Sign the data
		ByteString signature;
		CPPUNIT_ASSERT(dsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::DSA));

		// Verify the signature
		CPPUNIT_ASSERT(dsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::DSA));

		dsa->recycleKeyPair(kp);
		dsa->recycleParameters(p);
	}
}
示例#8
0
void RSATests::testSigningVerifying()
{
	AsymmetricKeyPair* kp;
	RSAParameters p;

	// Public exponents to test
	std::vector<ByteString> exponents;
	exponents.push_back("010001");
	exponents.push_back("03");
	exponents.push_back("0B");
	exponents.push_back("11");

	// Key sizes to test
	std::vector<size_t> keySizes;
	keySizes.push_back(1024);
	keySizes.push_back(1280);
	keySizes.push_back(2048);
	//keySizes.push_back(4096);

	// Mechanisms to test
	std::vector<AsymMech::Type> mechanisms;
#ifndef WITH_FIPS
	mechanisms.push_back(AsymMech::RSA_MD5_PKCS);
#endif
	mechanisms.push_back(AsymMech::RSA_SHA1_PKCS);
	mechanisms.push_back(AsymMech::RSA_SHA224_PKCS);
	mechanisms.push_back(AsymMech::RSA_SHA256_PKCS);
	mechanisms.push_back(AsymMech::RSA_SHA384_PKCS);
	mechanisms.push_back(AsymMech::RSA_SHA512_PKCS);
	mechanisms.push_back(AsymMech::RSA_SHA1_PKCS_PSS);
	mechanisms.push_back(AsymMech::RSA_SHA224_PKCS_PSS);
	mechanisms.push_back(AsymMech::RSA_SHA256_PKCS_PSS);
	mechanisms.push_back(AsymMech::RSA_SHA384_PKCS_PSS);
	mechanisms.push_back(AsymMech::RSA_SHA512_PKCS_PSS);
#ifndef WITH_FIPS
	mechanisms.push_back(AsymMech::RSA_SSL);
#endif

	/* Max salt length for SHA512 and 1024-bit RSA is 62 bytes */
	RSA_PKCS_PSS_PARAMS pssParams[] = {
		{ HashAlgo::SHA1,   AsymRSAMGF::MGF1_SHA1,   20 },
		{ HashAlgo::SHA224, AsymRSAMGF::MGF1_SHA224, 0  },
		{ HashAlgo::SHA256, AsymRSAMGF::MGF1_SHA256, 0  },
		{ HashAlgo::SHA384, AsymRSAMGF::MGF1_SHA384, 48 },
		{ HashAlgo::SHA512, AsymRSAMGF::MGF1_SHA512, 62 }
	};

	for (std::vector<ByteString>::iterator e = exponents.begin(); e != exponents.end(); e++)
	{
		for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
		{
			p.setE(*e);
			p.setBitLength(*k);

			// Generate key-pair
			CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p));

			// Generate some data to sign
			ByteString dataToSign;

			RNG* rng = CryptoFactory::i()->getRNG();

			CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567));

			// Test mechanisms that perform internal hashing
			for (std::vector<AsymMech::Type>::iterator m = mechanisms.begin(); m != mechanisms.end(); m++)
			{
				ByteString blockSignature, singlePartSignature;
				void* param = NULL;
				size_t paramLen = 0;
				bool isPSS = false;

				switch (*m)
				{
					case AsymMech::RSA_SHA1_PKCS_PSS:
						param = &pssParams[0];
						paramLen = sizeof(pssParams[0]);
						isPSS = true;
						break;
					case AsymMech::RSA_SHA224_PKCS_PSS:
						param = &pssParams[1];
						paramLen = sizeof(pssParams[1]);
						isPSS = true;
						break;
					case AsymMech::RSA_SHA256_PKCS_PSS:
						param = &pssParams[2];
						paramLen = sizeof(pssParams[2]);
						isPSS = true;
						break;
					case AsymMech::RSA_SHA384_PKCS_PSS:
						param = &pssParams[3];
						paramLen = sizeof(pssParams[3]);
						isPSS = true;
						break;
					case AsymMech::RSA_SHA512_PKCS_PSS:
						param = &pssParams[4];
						paramLen = sizeof(pssParams[4]);
						isPSS = true;
						break;
					default:
						break;
				}

				// Sign the data in blocks
				CPPUNIT_ASSERT(rsa->signInit(kp->getPrivateKey(), *m, param, paramLen));
				CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(0, 134)));
				CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(134, 289)));
				CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(134 + 289)));
				CPPUNIT_ASSERT(rsa->signFinal(blockSignature));

				// Sign the data in one pass
				CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, singlePartSignature, *m, param, paramLen));

				// If it is not a PSS signature, check if the two signatures match
				if (!isPSS)
				{
					// Check if the two signatures match
					CPPUNIT_ASSERT(blockSignature == singlePartSignature);
				}

				// Now perform multi-pass verification
				CPPUNIT_ASSERT(rsa->verifyInit(kp->getPublicKey(), *m, param, paramLen));
				CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(0, 125)));
				CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(125, 247)));
				CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(125 + 247)));
				CPPUNIT_ASSERT(rsa->verifyFinal(blockSignature));

				// And single-pass verification
				CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, singlePartSignature, *m, param, paramLen));
			}

			// Test mechanisms that do not perform internal hashing

			// Test PKCS #1 signing
			CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 35));

			// Sign the data
			ByteString signature;
			CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS));

			// Verify the signature
			CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS));

			// Test raw RSA signing
			size_t byteSize = *k >> 3;

			CPPUNIT_ASSERT(rng->generateRandom(dataToSign, byteSize));

			// Strip the topmost bit
			dataToSign[0] &= 0x7F;

			// Sign the data
			CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA));

			// Verify the signature
			CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA));

#ifdef WITH_RAW_PSS
			// Test raw (SHA1) PKCS PSS signing
			CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 20));
			CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[0], sizeof(pssParams[0])));
			CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[0], sizeof(pssParams[0])));

			// Test raw (SHA224) PKCS PSS signing
			CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 28));
			CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[1], sizeof(pssParams[1])));
			CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[1], sizeof(pssParams[1])));

			// Test raw (SHA256) PKCS PSS signing
			CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 32));
			CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[2], sizeof(pssParams[2])));
			CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[2], sizeof(pssParams[2])));

			// Test raw (SHA384) PKCS PSS signing
			CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 48));
			CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[3], sizeof(pssParams[3])));
			CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[3], sizeof(pssParams[3])));

			// Test raw (SHA512) PKCS PSS signing
			CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 64));
			CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[4], sizeof(pssParams[4])));
			CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[4], sizeof(pssParams[4])));
#endif

			rsa->recycleKeyPair(kp);
		}
	}
}