示例#1
0
void LoginAdminClient::PostCreateAccount()
{
	FortunaOutput *csprng = FortunaFactory::ii->Create();
	if (!csprng)
	{
		WARN("AdminClient") << "Out of memory: Unable to create CSPRNG";
		on_disconnect();
		return;
	}

	u8 create_request[8+32];
	csprng->Generate(create_request, 8);

	GeneratePasswordHash(_username, create_request, 8, _password.c_str(), _password_hash, 32);
	memcpy(create_request + 8, _password_hash, 32);

	WriteReliable(STREAM_1, LS_CREATE_ACCOUNT, create_request, sizeof(create_request));

	delete csprng;
}
// Generates an unbiased random key in the range 1 < key < q
void KeyAgreementCommon::GenerateKey(TunnelTLS *tls, Leg *key)
{
	BigTwistedEdwards *math = tls->Math();
	FortunaOutput *csprng = tls->CSPRNG();

	do
	{
		csprng->Generate(key, KeyBytes);

		// Turn off the high bit(s) to speed up unbiased key generation
		// NOTE: Only works for the values of q above
#if defined(CAT_DETERMINISTIC_KEY_GENERATION)
		key[KeyLegs-1] &= ~(CAT_LEG_MSB | (CAT_LEG_MSB >> 1));
#else
		key[KeyLegs-1] &= ~CAT_LEG_MSB;
#endif
	}
	while (!math->Less(key, math->GetCurveQ()) ||
		   !math->GreaterX(key, 1));
}
bool KeyAgreementResponder::ProcessChallenge(TunnelTLS *tls,
											 const u8 *initiator_challenge, int challenge_bytes,
                                             u8 *responder_answer, int answer_bytes, Skein *key_hash)
{
	CAT_DEBUG_ENFORCE(tls && tls->Valid() && challenge_bytes == KeyBytes*2 && answer_bytes == KeyBytes*4);

	BigTwistedEdwards *math = tls->Math();
	FortunaOutput *csprng = tls->CSPRNG();

    Leg *A = math->Get(0);
    Leg *S = math->Get(8);
    Leg *T = math->Get(12);
    Leg *hA = math->Get(16);

    // Unpack the initiator's A into registers
    if (!math->LoadVerifyAffineXY(initiator_challenge, initiator_challenge + KeyBytes, A))
        return false;

	// Verify the point is not the additive identity (should never happen unless being attacked)
	if (math->IsAffineIdentity(A))
		return false;

    // hA = h * A for small subgroup attack resistance
    math->PtDoubleZ1(A, hA);
    math->PtEDouble(hA, hA);

#if defined(CAT_NO_ATOMIC_RESPONDER)

	bool time_to_rekey = false;

	m_thread_id_mutex.Enter();

	// Check if it is time to rekey
	if (ChallengeCount++ == 100)
		time_to_rekey = true;

	m_thread_id_mutex.Leave();

	if (time_to_rekey)
		Rekey(math, csprng);

#else // CAT_NO_ATOMIC_RESPONDER

	// Check if it is time to rekey
	if (Atomic::Add(&ChallengeCount, 1) == 100)
		Rekey(tls);

#endif // CAT_NO_ATOMIC_RESPONDER

	// Copy the current endian neutral Y to the responder answer
	u32 ThisY = ActiveY;
	memcpy(responder_answer, Y_neutral[ThisY], KeyBytes*2);

	do
	{
		// random n-bit number r
		csprng->Generate(responder_answer + KeyBytes*2, KeyBytes);

		// S = H(A,B,Y,r)
		if (!key_hash->BeginKey(KeyBits))
			return false;
		key_hash->Crunch(initiator_challenge, KeyBytes*2); // A
		key_hash->Crunch(B_neutral, KeyBytes*2); // B
		key_hash->Crunch(responder_answer, KeyBytes*3); // Y,r
		key_hash->End();
		key_hash->Generate(S, KeyBytes);
		math->Load(S, KeyBytes, S);

		// Repeat while S is small
	} while (math->LessX(S, 1000));

	// T = S*y + b (mod q)
	math->MulMod(S, y[ThisY], math->GetCurveQ(), T); // Should use Barrett reduction here
	if (math->Add(T, b, T))
		math->Subtract(T, math->GetCurveQ(), T);
	while (!math->Less(T, math->GetCurveQ()))
		math->Subtract(T, math->GetCurveQ(), T);

	// T = AffineX(T * hA)
	math->PtMultiply(hA, T, 0, S);
    math->SaveAffineX(S, T);

	// k = H(d,T)
	if (!key_hash->BeginKDF())
		return false;
	key_hash->Crunch(T, KeyBytes);
	key_hash->End();

	// Generate responder proof of key
	Skein mac;

	if (!mac.SetKey(key_hash) || !mac.BeginMAC()) return false;
	mac.CrunchString("shfolder.dll");
	mac.End();

	mac.Generate(responder_answer + KeyBytes*3, KeyBytes);

	return true;
}