static void PollVMStat(Skein &pool) { const char *PATH = "vmstat -s"; fd_set fds; FD_ZERO(&fds); if (!access(PATH, F_OK)) return; FILE *fp = popen(PATH, "r"); if (!fp) return; int fd = fileno(fp); if (fd < 0) return; FD_SET(fd, &fds); timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; int r; while ((r = select(1 + fd, &fds, 0, 0, &tv))) { if (r == -1 || !FD_ISSET(fd, &fds)) break; static u8 buffer[4096]; int count = read(fd, buffer, sizeof(buffer)); if (count > 0) pool.Crunch(buffer, count); else break; } pclose(fp); FD_CLR(fd, &fds); }
bool KeyAgreementResponder::Sign(TunnelTLS *tls, const u8 *message, int message_bytes, u8 *signature, int signature_bytes) { CAT_DEBUG_ENFORCE(tls && tls->Valid() && signature_bytes == KeyBytes*2 && message_bytes >= 0); BigTwistedEdwards *math = tls->Math(); Leg *k = math->Get(0); Leg *K = math->Get(1); Leg *e = math->Get(5); Leg *s = math->Get(6); do { do { // k = ephemeral key GenerateKey(tls, k); // K = k * G math->PtMultiply(G_MultPrecomp, 8, k, 0, K); math->SaveAffineX(K, K); // e = H(M || K) Skein H; if (!H.BeginKey(KeyBits)) return false; H.Crunch(message, message_bytes); H.Crunch(K, KeyBytes); H.End(); H.Generate(signature, KeyBytes); math->Load(signature, KeyBytes, e); // e = e (mod q), for checking if it is congruent to q while (!math->Less(e, math->GetCurveQ())) math->Subtract(e, math->GetCurveQ(), e); } while (math->IsZero(e)); // s = b * e (mod q) math->MulMod(b, e, math->GetCurveQ(), s); // s = -s (mod q) if (!math->IsZero(s)) math->Subtract(math->GetCurveQ(), s, s); // s = s + k (mod q) if (math->Add(s, k, s)) while (!math->Subtract(s, math->GetCurveQ(), s)); while (!math->Less(s, math->GetCurveQ())) math->Subtract(s, math->GetCurveQ(), s); } while (math->IsZero(s)); math->Save(s, signature + KeyBytes, KeyBytes); // Erase the ephemeral secret from memory math->CopyX(0, k); return true; }
bool KeyAgreementResponder::VerifyInitiatorIdentity(TunnelTLS *tls, const u8 *responder_answer, int answer_bytes, const u8 *proof, int proof_bytes, u8 *public_key, int public_bytes) { CAT_DEBUG_ENFORCE(tls && tls->Valid() && proof_bytes == KeyBytes*5 && answer_bytes == KeyBytes*4 && public_bytes == KeyBytes*2); BigTwistedEdwards *math = tls->Math(); /* Format of identity buffer: 256-bit security: [Initiator Public Key] (64) || [Initiator Random Number] (32) || [Signature] (64) */ // Copied from Verify() in KeyAgreementInitiator.cpp Leg *e = math->Get(0); Leg *s = math->Get(1); Leg *Kp = math->Get(2); Leg *ep = math->Get(6); Leg *I_public = math->Get(7); // Load e, s from proof math->Load(proof + KeyBytes * 3, KeyBytes, e); math->Load(proof + KeyBytes * 4, KeyBytes, s); // e = e (mod q), for checking if it is congruent to q while (!math->Less(e, math->GetCurveQ())) math->Subtract(e, math->GetCurveQ(), e); // Check e, s are in the range [1,q-1] if (math->IsZero(e) || math->IsZero(s) || !math->Less(e, math->GetCurveQ()) || !math->Less(s, math->GetCurveQ())) { return false; } // Unpack the initiator's public key if (!math->LoadVerifyAffineXY(proof, proof + KeyBytes, I_public)) return false; // Verify public point is not identity element if (math->IsAffineIdentity(I_public)) return false; // Precompute a table for multiplication Leg *I_MultPrecomp = math->PtMultiplyPrecompAlloc(8); if (!I_MultPrecomp) return false; math->PtUnpack(I_public); math->PtMultiplyPrecomp(I_public, 8, I_MultPrecomp); // K' = s*G + e*I_public math->PtSiMultiply(G_MultPrecomp, I_MultPrecomp, 8, s, 0, e, 0, Kp); math->SaveAffineX(Kp, Kp); AlignedAllocator::ref()->Delete(I_MultPrecomp); // e' = H(IRN || RRN || K') Skein H; if (!H.BeginKey(KeyBits)) return false; H.Crunch(proof + KeyBytes * 2, KeyBytes); // client random number H.Crunch(responder_answer + KeyBytes * 2, KeyBytes); // server random number H.Crunch(Kp, KeyBytes); H.End(); H.Generate(ep, KeyBytes); // Verify that e' == e bool success = SecureEqual(proof + KeyBytes * 3, ep, KeyBytes); // On successful identity verification, copy the public key to the destination if (success) memcpy(public_key, proof, KeyBytes*2); return success; }