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