diff options
Diffstat (limited to 'botan/src/pubkey/dl_group')
-rw-r--r-- | botan/src/pubkey/dl_group/dl_group.cpp | 333 | ||||
-rw-r--r-- | botan/src/pubkey/dl_group/dl_group.h | 162 | ||||
-rw-r--r-- | botan/src/pubkey/dl_group/info.txt | 19 |
3 files changed, 514 insertions, 0 deletions
diff --git a/botan/src/pubkey/dl_group/dl_group.cpp b/botan/src/pubkey/dl_group/dl_group.cpp new file mode 100644 index 0000000..81c5d5e --- /dev/null +++ b/botan/src/pubkey/dl_group/dl_group.cpp @@ -0,0 +1,333 @@ +/* +* Discrete Logarithm Parameters +* (C) 1999-2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/dl_group.h> +#include <botan/libstate.h> +#include <botan/parsing.h> +#include <botan/numthry.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> +#include <botan/pipe.h> +#include <botan/util.h> +#include <botan/pem.h> + +namespace Botan { + +/* +* DL_Group Constructor +*/ +DL_Group::DL_Group() + { + initialized = false; + } + +/* +* DL_Group Constructor +*/ +DL_Group::DL_Group(const std::string& type) + { + std::string grp_contents = global_state().get("dl", type); + + if(grp_contents == "") + throw Invalid_Argument("DL_Group: Unknown group " + type); + + DataSource_Memory pem(grp_contents); + PEM_decode(pem); + } + +/* +* DL_Group Constructor +*/ +DL_Group::DL_Group(RandomNumberGenerator& rng, + PrimeType type, u32bit pbits, u32bit qbits) + { + if(pbits < 512) + throw Invalid_Argument("DL_Group: prime size " + to_string(pbits) + + " is too small"); + + if(type == Strong) + { + p = random_safe_prime(rng, pbits); + q = (p - 1) / 2; + g = 2; + } + else if(type == Prime_Subgroup || type == DSA_Kosherizer) + { + if(type == Prime_Subgroup) + { + if(!qbits) + qbits = 2 * dl_work_factor(pbits); + + q = random_prime(rng, qbits); + BigInt X; + while(p.bits() != pbits || !is_prime(p, rng)) + { + X.randomize(rng, pbits); + p = X - (X % (2*q) - 1); + } + } + else + { + qbits = qbits ? qbits : ((pbits == 1024) ? 160 : 256); + generate_dsa_primes(rng, + global_state().algorithm_factory(), + p, q, pbits, qbits); + } + + g = make_dsa_generator(p, q); + } + + initialized = true; + } + +/* +* DL_Group Constructor +*/ +DL_Group::DL_Group(RandomNumberGenerator& rng, + const MemoryRegion<byte>& seed, u32bit pbits, u32bit qbits) + { + if(!generate_dsa_primes(rng, + global_state().algorithm_factory(), + p, q, pbits, qbits, seed)) + throw Invalid_Argument("DL_Group: The seed given does not " + "generate a DSA group"); + + g = make_dsa_generator(p, q); + + initialized = true; + } + +/* +* DL_Group Constructor +*/ +DL_Group::DL_Group(const BigInt& p1, const BigInt& g1) + { + initialize(p1, 0, g1); + } + +/* +* DL_Group Constructor +*/ +DL_Group::DL_Group(const BigInt& p1, const BigInt& q1, const BigInt& g1) + { + initialize(p1, q1, g1); + } + +/* +* DL_Group Initializer +*/ +void DL_Group::initialize(const BigInt& p1, const BigInt& q1, const BigInt& g1) + { + if(p1 < 3) + throw Invalid_Argument("DL_Group: Prime invalid"); + if(g1 < 2 || g1 >= p1) + throw Invalid_Argument("DL_Group: Generator invalid"); + if(q1 < 0 || q1 >= p1) + throw Invalid_Argument("DL_Group: Subgroup invalid"); + + p = p1; + g = g1; + q = q1; + + initialized = true; + } + +/* +* Verify that the group has been set +*/ +void DL_Group::init_check() const + { + if(!initialized) + throw Invalid_State("DLP group cannot be used uninitialized"); + } + +/* +* Verify the parameters +*/ +bool DL_Group::verify_group(RandomNumberGenerator& rng, + bool strong) const + { + init_check(); + + if(g < 2 || p < 3 || q < 0) + return false; + if((q != 0) && ((p - 1) % q != 0)) + return false; + + if(!strong) + return true; + + if(!check_prime(p, rng)) + return false; + if((q > 0) && !check_prime(q, rng)) + return false; + return true; + } + +/* +* Return the prime +*/ +const BigInt& DL_Group::get_p() const + { + init_check(); + return p; + } + +/* +* Return the generator +*/ +const BigInt& DL_Group::get_g() const + { + init_check(); + return g; + } + +/* +* Return the subgroup +*/ +const BigInt& DL_Group::get_q() const + { + init_check(); + if(q == 0) + throw Format_Error("DLP group has no q prime specified"); + return q; + } + +/* +* DER encode the parameters +*/ +SecureVector<byte> DL_Group::DER_encode(Format format) const + { + init_check(); + + if((q == 0) && (format != PKCS_3)) + throw Encoding_Error("The ANSI DL parameter formats require a subgroup"); + + if(format == ANSI_X9_57) + { + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(p) + .encode(q) + .encode(g) + .end_cons() + .get_contents(); + } + else if(format == ANSI_X9_42) + { + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(p) + .encode(g) + .encode(q) + .end_cons() + .get_contents(); + } + else if(format == PKCS_3) + { + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(p) + .encode(g) + .end_cons() + .get_contents(); + } + + throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format)); + } + +/* +* PEM encode the parameters +*/ +std::string DL_Group::PEM_encode(Format format) const + { + SecureVector<byte> encoding = DER_encode(format); + if(format == PKCS_3) + return PEM_Code::encode(encoding, "DH PARAMETERS"); + else if(format == ANSI_X9_57) + return PEM_Code::encode(encoding, "DSA PARAMETERS"); + else if(format == ANSI_X9_42) + return PEM_Code::encode(encoding, "X942 DH PARAMETERS"); + else + throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format)); + } + +/* +* Decode BER encoded parameters +*/ +void DL_Group::BER_decode(DataSource& source, Format format) + { + BigInt new_p, new_q, new_g; + + BER_Decoder decoder(source); + BER_Decoder ber = decoder.start_cons(SEQUENCE); + + if(format == ANSI_X9_57) + { + ber.decode(new_p) + .decode(new_q) + .decode(new_g) + .verify_end(); + } + else if(format == ANSI_X9_42) + { + ber.decode(new_p) + .decode(new_g) + .decode(new_q) + .discard_remaining(); + } + else if(format == PKCS_3) + { + ber.decode(new_p) + .decode(new_g) + .discard_remaining(); + } + else + throw Invalid_Argument("Unknown DL_Group encoding " + to_string(format)); + + initialize(new_p, new_q, new_g); + } + +/* +* Decode PEM encoded parameters +*/ +void DL_Group::PEM_decode(DataSource& source) + { + std::string label; + DataSource_Memory ber(PEM_Code::decode(source, label)); + + if(label == "DH PARAMETERS") + BER_decode(ber, PKCS_3); + else if(label == "DSA PARAMETERS") + BER_decode(ber, ANSI_X9_57); + else if(label == "X942 DH PARAMETERS") + BER_decode(ber, ANSI_X9_42); + else + throw Decoding_Error("DL_Group: Invalid PEM label " + label); + } + +/* +* Create a random DSA-style generator +*/ +BigInt DL_Group::make_dsa_generator(const BigInt& p, const BigInt& q) + { + BigInt g, e = (p - 1) / q; + + for(u32bit j = 0; j != PRIME_TABLE_SIZE; ++j) + { + g = power_mod(PRIMES[j], e, p); + if(g != 1) + break; + } + + if(g == 1) + throw Exception("DL_Group: Couldn't create a suitable generator"); + + return g; + } + +} diff --git a/botan/src/pubkey/dl_group/dl_group.h b/botan/src/pubkey/dl_group/dl_group.h new file mode 100644 index 0000000..a84a85f --- /dev/null +++ b/botan/src/pubkey/dl_group/dl_group.h @@ -0,0 +1,162 @@ +/* +* Discrete Logarithm Group +* (C) 1999-2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_DL_PARAM_H__ +#define BOTAN_DL_PARAM_H__ + +#include <botan/bigint.h> +#include <botan/data_src.h> + +namespace Botan { + +/** +* This class represents discrete logarithm groups. It holds a prime p, +* a prime q = (p-1)/2 and g = x^((p-1)/q) mod p. +*/ +class BOTAN_DLL DL_Group + { + public: + /** + * Get the prime p. + * @return the prime p + */ + const BigInt& get_p() const; + + /** + * Get the prime q. + * @return the prime q + */ + const BigInt& get_q() const; + + /** + * Get the base g. + * @return the base g + */ + const BigInt& get_g() const; + + /** + * The DL group encoding format variants. + */ + enum Format { + ANSI_X9_42, + ANSI_X9_57, + PKCS_3, + + DSA_PARAMETERS = ANSI_X9_57, + DH_PARAMETERS = ANSI_X9_42, + X942_DH_PARAMETERS = ANSI_X9_42, + PKCS3_DH_PARAMETERS = PKCS_3 + }; + + /** + * Determine the prime creation for DL groups. + */ + enum PrimeType { Strong, Prime_Subgroup, DSA_Kosherizer }; + + /** + * Perform validity checks on the group. + * @param rng the rng to use + * @param strong whether to perform stronger by lengthier tests + * @return true if the object is consistent, false otherwise + */ + bool verify_group(RandomNumberGenerator& rng, bool strong) const; + + /** + * Encode this group into a string using PEM encoding. + * @param format the encoding format + * @return the string holding the PEM encoded group + */ + std::string PEM_encode(Format format) const; + + /** + * Encode this group into a string using DER encoding. + * @param format the encoding format + * @return the string holding the DER encoded group + */ + SecureVector<byte> DER_encode(Format format) const; + + /** + * Decode a DER/BER encoded group into this instance. + * @param src a DataSource providing the encoded group + * @param format the format of the encoded group + */ + void BER_decode(DataSource& src, Format format); + + /** + * Decode a PEM encoded group into this instance. + * @param src a DataSource providing the encoded group + */ + void PEM_decode(DataSource& src); + + /** + * Construct a DL group with uninitialized internal value. + * Use this constructor is you wish to set the groups values + * from a DER or PEM encoded group. + */ + DL_Group(); + + /** + * Construct a DL group that is registered in the configuration. + * @param name the name that is configured in the global configuration + * for the desired group. If no configuration file is specified, + * the default values from the file policy.cpp will be used. For instance, + * use "modp/ietf/768" as name. + */ + DL_Group(const std::string& name); + + /** + * Create a new group randomly. + * @param rng the random number generator to use + * @param type specifies how the creation of primes p and q shall + * be performed. If type=Strong, then p will be determined as a + * safe prime, and q will be chosen as (p-1)/2. If + * type=Prime_Subgroup and qbits = 0, then the size of q will be + * determined according to the estimated difficulty of the DL + * problem. If type=DSA_Kosherizer, DSA primes will be created. + * @param pbits the number of bits of p + * @param qbits the number of bits of q. Leave it as 0 to have + * the value determined according to pbits. + */ + DL_Group(RandomNumberGenerator& rng, PrimeType type, + u32bit pbits, u32bit qbits = 0); + + /** + * Create a DSA group with a given seed. + * @param rng the random number generator to use + * @param seed the seed to use to create the random primes + * @param pbits the desired bit size of the prime p + * @param qbits the desired bit size of the prime q. + */ + DL_Group(RandomNumberGenerator& rng, const MemoryRegion<byte>& seed, + u32bit pbits = 1024, u32bit qbits = 0); + + /** + * Create a DL group. The prime q will be determined according to p. + * @param p the prime p + * @param g the base g + */ + DL_Group(const BigInt& p, const BigInt& g); + + /** + * Create a DL group. + * @param p the prime p + * @param q the prime q + * @param g the base g + */ + DL_Group(const BigInt& p, const BigInt& q, const BigInt& g); + private: + static BigInt make_dsa_generator(const BigInt&, const BigInt&); + + void init_check() const; + void initialize(const BigInt&, const BigInt&, const BigInt&); + bool initialized; + BigInt p, q, g; + }; + +} + +#endif diff --git a/botan/src/pubkey/dl_group/info.txt b/botan/src/pubkey/dl_group/info.txt new file mode 100644 index 0000000..6b9884a --- /dev/null +++ b/botan/src/pubkey/dl_group/info.txt @@ -0,0 +1,19 @@ +realname "DL Group" + +load_on auto + +define DL_GROUP + +<add> +dl_group.cpp +dl_group.h +</add> + +<requires> +asn1 +bigint +filters +libstate +numbertheory +pem +</requires> |