00001
00002
00003
00004
00005
00006
00007
00008 #include <botan/numthry.h>
00009 #include <botan/algo_factory.h>
00010 #include <botan/hash.h>
00011 #include <botan/parsing.h>
00012 #include <algorithm>
00013 #include <memory>
00014
00015 namespace Botan {
00016
00017 namespace {
00018
00019
00020
00021
00022 bool fips186_3_valid_size(u32bit pbits, u32bit qbits)
00023 {
00024 if(qbits == 160)
00025 return (pbits == 512 || pbits == 768 || pbits == 1024);
00026
00027 if(qbits == 224)
00028 return (pbits == 2048);
00029
00030 if(qbits == 256)
00031 return (pbits == 2048 || pbits == 3072);
00032
00033 return false;
00034 }
00035
00036 }
00037
00038
00039
00040
00041 bool generate_dsa_primes(RandomNumberGenerator& rng,
00042 Algorithm_Factory& af,
00043 BigInt& p, BigInt& q,
00044 u32bit pbits, u32bit qbits,
00045 const MemoryRegion<byte>& seed_c)
00046 {
00047 if(!fips186_3_valid_size(pbits, qbits))
00048 throw Invalid_Argument(
00049 "FIPS 186-3 does not allow DSA domain parameters of " +
00050 to_string(pbits) + "/" + to_string(qbits) + " bits long");
00051
00052 if(seed_c.size() * 8 < qbits)
00053 throw Invalid_Argument(
00054 "Generating a DSA parameter set with a " + to_string(qbits) +
00055 "long q requires a seed at least as many bits long");
00056
00057 std::auto_ptr<HashFunction> hash(
00058 af.make_hash_function("SHA-" + to_string(qbits)));
00059
00060 const u32bit HASH_SIZE = hash->OUTPUT_LENGTH;
00061
00062 class Seed
00063 {
00064 public:
00065 Seed(const MemoryRegion<byte>& s) : seed(s) {}
00066
00067 operator MemoryRegion<byte>& () { return seed; }
00068
00069 Seed& operator++()
00070 {
00071 for(u32bit j = seed.size(); j > 0; --j)
00072 if(++seed[j-1])
00073 break;
00074 return (*this);
00075 }
00076 private:
00077 SecureVector<byte> seed;
00078 };
00079
00080 Seed seed(seed_c);
00081
00082 q.binary_decode(hash->process(seed));
00083 q.set_bit(qbits-1);
00084 q.set_bit(0);
00085
00086 if(!check_prime(q, rng))
00087 return false;
00088
00089 const u32bit n = (pbits-1) / (HASH_SIZE * 8),
00090 b = (pbits-1) % (HASH_SIZE * 8);
00091
00092 BigInt X;
00093 SecureVector<byte> V(HASH_SIZE * (n+1));
00094
00095 for(u32bit j = 0; j != 4096; ++j)
00096 {
00097 for(u32bit k = 0; k <= n; ++k)
00098 {
00099 ++seed;
00100 hash->update(seed);
00101 hash->final(V + HASH_SIZE * (n-k));
00102 }
00103
00104 X.binary_decode(V + (HASH_SIZE - 1 - b/8),
00105 V.size() - (HASH_SIZE - 1 - b/8));
00106 X.set_bit(pbits-1);
00107
00108 p = X - (X % (2*q) - 1);
00109
00110 if(p.bits() == pbits && check_prime(p, rng))
00111 return true;
00112 }
00113 return false;
00114 }
00115
00116
00117
00118
00119 SecureVector<byte> generate_dsa_primes(RandomNumberGenerator& rng,
00120 Algorithm_Factory& af,
00121 BigInt& p, BigInt& q,
00122 u32bit pbits, u32bit qbits)
00123 {
00124 SecureVector<byte> seed(qbits/8);
00125
00126 while(true)
00127 {
00128 rng.randomize(seed, seed.size());
00129
00130 if(generate_dsa_primes(rng, af, p, q, pbits, qbits, seed))
00131 return seed;
00132 }
00133 }
00134
00135 }