00001
00002
00003
00004
00005
00006
00007
00008 #include <botan/dl_group.h>
00009 #include <botan/libstate.h>
00010 #include <botan/parsing.h>
00011 #include <botan/numthry.h>
00012 #include <botan/der_enc.h>
00013 #include <botan/ber_dec.h>
00014 #include <botan/pipe.h>
00015 #include <botan/pem.h>
00016 #include <botan/internal/workfactor.h>
00017
00018 namespace Botan {
00019
00020
00021
00022
00023 DL_Group::DL_Group()
00024 {
00025 initialized = false;
00026 }
00027
00028
00029
00030
00031 DL_Group::DL_Group(const std::string& type)
00032 {
00033 std::string grp_contents = global_state().get("dl", type);
00034
00035 if(grp_contents == "")
00036 throw Invalid_Argument("DL_Group: Unknown group " + type);
00037
00038 DataSource_Memory pem(grp_contents);
00039 PEM_decode(pem);
00040 }
00041
00042
00043
00044
00045 DL_Group::DL_Group(RandomNumberGenerator& rng,
00046 PrimeType type, u32bit pbits, u32bit qbits)
00047 {
00048 if(pbits < 512)
00049 throw Invalid_Argument("DL_Group: prime size " + to_string(pbits) +
00050 " is too small");
00051
00052 if(type == Strong)
00053 {
00054 p = random_safe_prime(rng, pbits);
00055 q = (p - 1) / 2;
00056 g = 2;
00057 }
00058 else if(type == Prime_Subgroup)
00059 {
00060 if(!qbits)
00061 qbits = 2 * dl_work_factor(pbits);
00062
00063 q = random_prime(rng, qbits);
00064 BigInt X;
00065 while(p.bits() != pbits || !check_prime(p, rng))
00066 {
00067 X.randomize(rng, pbits);
00068 p = X - (X % (2*q) - 1);
00069 }
00070
00071 g = make_dsa_generator(p, q);
00072 }
00073 else if(type == DSA_Kosherizer)
00074 {
00075 qbits = qbits ? qbits : ((pbits <= 1024) ? 160 : 256);
00076
00077 generate_dsa_primes(rng,
00078 global_state().algorithm_factory(),
00079 p, q,
00080 pbits, qbits);
00081
00082 g = make_dsa_generator(p, q);
00083 }
00084
00085 initialized = true;
00086 }
00087
00088
00089
00090
00091 DL_Group::DL_Group(RandomNumberGenerator& rng,
00092 const MemoryRegion<byte>& seed, u32bit pbits, u32bit qbits)
00093 {
00094 if(!generate_dsa_primes(rng,
00095 global_state().algorithm_factory(),
00096 p, q, pbits, qbits, seed))
00097 throw Invalid_Argument("DL_Group: The seed given does not "
00098 "generate a DSA group");
00099
00100 g = make_dsa_generator(p, q);
00101
00102 initialized = true;
00103 }
00104
00105
00106
00107
00108 DL_Group::DL_Group(const BigInt& p1, const BigInt& g1)
00109 {
00110 initialize(p1, 0, g1);
00111 }
00112
00113
00114
00115
00116 DL_Group::DL_Group(const BigInt& p1, const BigInt& q1, const BigInt& g1)
00117 {
00118 initialize(p1, q1, g1);
00119 }
00120
00121
00122
00123
00124 void DL_Group::initialize(const BigInt& p1, const BigInt& q1, const BigInt& g1)
00125 {
00126 if(p1 < 3)
00127 throw Invalid_Argument("DL_Group: Prime invalid");
00128 if(g1 < 2 || g1 >= p1)
00129 throw Invalid_Argument("DL_Group: Generator invalid");
00130 if(q1 < 0 || q1 >= p1)
00131 throw Invalid_Argument("DL_Group: Subgroup invalid");
00132
00133 p = p1;
00134 g = g1;
00135 q = q1;
00136
00137 initialized = true;
00138 }
00139
00140
00141
00142
00143 void DL_Group::init_check() const
00144 {
00145 if(!initialized)
00146 throw Invalid_State("DLP group cannot be used uninitialized");
00147 }
00148
00149
00150
00151
00152 bool DL_Group::verify_group(RandomNumberGenerator& rng,
00153 bool strong) const
00154 {
00155 init_check();
00156
00157 if(g < 2 || p < 3 || q < 0)
00158 return false;
00159 if((q != 0) && ((p - 1) % q != 0))
00160 return false;
00161
00162 if(!strong)
00163 return true;
00164
00165 if(!check_prime(p, rng))
00166 return false;
00167 if((q > 0) && !check_prime(q, rng))
00168 return false;
00169 return true;
00170 }
00171
00172
00173
00174
00175 const BigInt& DL_Group::get_p() const
00176 {
00177 init_check();
00178 return p;
00179 }
00180
00181
00182
00183
00184 const BigInt& DL_Group::get_g() const
00185 {
00186 init_check();
00187 return g;
00188 }
00189
00190
00191
00192
00193 const BigInt& DL_Group::get_q() const
00194 {
00195 init_check();
00196 if(q == 0)
00197 throw Invalid_State("DLP group has no q prime specified");
00198 return q;
00199 }
00200
00201
00202
00203
00204 SecureVector<byte> DL_Group::DER_encode(Format format) const
00205 {
00206 init_check();
00207
00208 if((q == 0) && (format != PKCS_3))
00209 throw Encoding_Error("The ANSI DL parameter formats require a subgroup");
00210
00211 if(format == ANSI_X9_57)
00212 {
00213 return DER_Encoder()
00214 .start_cons(SEQUENCE)
00215 .encode(p)
00216 .encode(q)
00217 .encode(g)
00218 .end_cons()
00219 .get_contents();
00220 }
00221 else if(format == ANSI_X9_42)
00222 {
00223 return DER_Encoder()
00224 .start_cons(SEQUENCE)
00225 .encode(p)
00226 .encode(g)
00227 .encode(q)
00228 .end_cons()
00229 .get_contents();
00230 }
00231 else if(format == PKCS_3)
00232 {
00233 return DER_Encoder()
00234 .start_cons(SEQUENCE)
00235 .encode(p)
00236 .encode(g)
00237 .end_cons()
00238 .get_contents();
00239 }
00240
00241 throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
00242 }
00243
00244
00245
00246
00247 std::string DL_Group::PEM_encode(Format format) const
00248 {
00249 SecureVector<byte> encoding = DER_encode(format);
00250 if(format == PKCS_3)
00251 return PEM_Code::encode(encoding, "DH PARAMETERS");
00252 else if(format == ANSI_X9_57)
00253 return PEM_Code::encode(encoding, "DSA PARAMETERS");
00254 else if(format == ANSI_X9_42)
00255 return PEM_Code::encode(encoding, "X942 DH PARAMETERS");
00256 else
00257 throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
00258 }
00259
00260
00261
00262
00263 void DL_Group::BER_decode(DataSource& source, Format format)
00264 {
00265 BigInt new_p, new_q, new_g;
00266
00267 BER_Decoder decoder(source);
00268 BER_Decoder ber = decoder.start_cons(SEQUENCE);
00269
00270 if(format == ANSI_X9_57)
00271 {
00272 ber.decode(new_p)
00273 .decode(new_q)
00274 .decode(new_g)
00275 .verify_end();
00276 }
00277 else if(format == ANSI_X9_42)
00278 {
00279 ber.decode(new_p)
00280 .decode(new_g)
00281 .decode(new_q)
00282 .discard_remaining();
00283 }
00284 else if(format == PKCS_3)
00285 {
00286 ber.decode(new_p)
00287 .decode(new_g)
00288 .discard_remaining();
00289 }
00290 else
00291 throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format));
00292
00293 initialize(new_p, new_q, new_g);
00294 }
00295
00296
00297
00298
00299 void DL_Group::PEM_decode(DataSource& source)
00300 {
00301 std::string label;
00302 DataSource_Memory ber(PEM_Code::decode(source, label));
00303
00304 if(label == "DH PARAMETERS")
00305 BER_decode(ber, PKCS_3);
00306 else if(label == "DSA PARAMETERS")
00307 BER_decode(ber, ANSI_X9_57);
00308 else if(label == "X942 DH PARAMETERS")
00309 BER_decode(ber, ANSI_X9_42);
00310 else
00311 throw Decoding_Error("DL_Group: Invalid PEM label " + label);
00312 }
00313
00314
00315
00316
00317 BigInt DL_Group::make_dsa_generator(const BigInt& p, const BigInt& q)
00318 {
00319 BigInt g, e = (p - 1) / q;
00320
00321 for(u32bit j = 0; j != PRIME_TABLE_SIZE; ++j)
00322 {
00323 g = power_mod(PRIMES[j], e, p);
00324 if(g != 1)
00325 break;
00326 }
00327
00328 if(g == 1)
00329 throw Internal_Error("DL_Group: Couldn't create a suitable generator");
00330
00331 return g;
00332 }
00333
00334 }