/* * PKCS1 Pad Operation */ secure_vector<byte> EME_PKCS1v15::pad(const byte in[], size_t inlen, size_t olen, RandomNumberGenerator& rng) const { olen /= 8; if(olen < 10) throw Encoding_Error("PKCS1: Output space too small"); if(inlen > olen - 10) throw Encoding_Error("PKCS1: Input is too large"); secure_vector<byte> out(olen); out[0] = 0x02; for(size_t j = 1; j != olen - inlen - 1; ++j) while(out[j] == 0) out[j] = rng.next_byte(); buffer_insert(out, olen - inlen, in, inlen); return out; }
/* * Generate a random prime */ BigInt random_prime(RandomNumberGenerator& rng, u32bit bits, const BigInt& coprime, u32bit equiv, u32bit modulo) { if(bits <= 1) throw Invalid_Argument("random_prime: Can't make a prime of " + to_string(bits) + " bits"); else if(bits == 2) return ((rng.next_byte() % 2) ? 2 : 3); else if(bits == 3) return ((rng.next_byte() % 2) ? 5 : 7); else if(bits == 4) return ((rng.next_byte() % 2) ? 11 : 13); if(coprime <= 0) throw Invalid_Argument("random_prime: coprime must be > 0"); if(modulo % 2 == 1 || modulo == 0) throw Invalid_Argument("random_prime: Invalid modulo value"); if(equiv >= modulo || equiv % 2 == 0) throw Invalid_Argument("random_prime: equiv must be < modulo, and odd"); while(true) { BigInt p(rng, bits); p.set_bit(bits - 2); p.set_bit(0); if(p % modulo != equiv) p += (modulo - p % modulo) + equiv; const u32bit sieve_size = std::min(bits / 2, PRIME_TABLE_SIZE); SecureVector<u32bit> sieve(sieve_size); for(u32bit j = 0; j != sieve.size(); ++j) sieve[j] = p % PRIMES[j]; u32bit counter = 0; while(true) { if(counter == 4096 || p.bits() > bits) break; bool passes_sieve = true; ++counter; p += modulo; if(p.bits() > bits) break; for(u32bit j = 0; j != sieve.size(); ++j) { sieve[j] = (sieve[j] + modulo) % PRIMES[j]; if(sieve[j] == 0) passes_sieve = false; } if(!passes_sieve || gcd(p - 1, coprime) != 1) continue; if(passes_mr_tests(rng, p)) return p; } } }
PointGFp Blinded_Point_Multiply::blinded_multiply(const BigInt& scalar_in, RandomNumberGenerator& rng) { if(scalar_in.is_negative()) throw std::invalid_argument("Blinded_Point_Multiply scalar must be positive"); #if BOTAN_POINTGFP_SCALAR_BLINDING_BITS > 0 // Choose a small mask m and use k' = k + m*order (Coron's 1st countermeasure) const BigInt mask(rng, BOTAN_POINTGFP_SCALAR_BLINDING_BITS, false); const BigInt scalar = scalar_in + m_order * mask; #else const BigInt& scalar = scalar_in; #endif const size_t scalar_bits = scalar.bits(); // Randomize each point representation (Coron's 3rd countermeasure) for(size_t i = 0; i != m_U.size(); ++i) m_U[i].randomize_repr(rng); #if BOTAN_POINTGFP_BLINDED_MULTIPLY_USE_MONTGOMERY_LADDER PointGFp R = m_U.at(3*m_h + 2); // base point int32_t alpha = 0; R.randomize_repr(rng); /* Algorithm 7 from "Randomizing the Montgomery Powering Ladder" Duc-Phong Le, Chik How Tan and Michael Tunstall http://eprint.iacr.org/2015/657 It takes a random walk through (a subset of) the set of addition chains that end in k. */ for(size_t i = scalar_bits; i > 0; i--) { const int32_t ki = scalar.get_bit(i); // choose gamma from -h,...,h const int32_t gamma = static_cast<int32_t>((rng.next_byte() % (2*m_h))) - m_h; const int32_t l = gamma - 2*alpha + ki - (ki ^ 1); R.mult2(m_ws); R.add(m_U.at(3*m_h + 1 + l), m_ws); alpha = gamma; } const int32_t k0 = scalar.get_bit(0); R.add(m_U[3*m_h + 1 - alpha - (k0 ^ 1)], m_ws); #else // N-bit windowing exponentiation: size_t windows = round_up(scalar_bits, m_h) / m_h; PointGFp R = m_U[0]; if(windows > 0) { windows--; const u32bit nibble = scalar.get_substring(windows*m_h, m_h); R.add(m_U[nibble], m_ws); /* Randomize after adding the first nibble as before the addition R is zero, and we cannot effectively randomize the point representation of the zero point. */ R.randomize_repr(rng); while(windows) { for(size_t i = 0; i != m_h; ++i) R.mult2(m_ws); const u32bit nibble = scalar.get_substring((windows-1)*m_h, m_h); R.add(m_U[nibble], m_ws); windows--; } } #endif //BOTAN_ASSERT(R.on_the_curve(), "Output is on the curve"); return R; }