diff options
Diffstat (limited to 'comm/third_party/botan/src/lib/misc/srp6')
-rw-r--r-- | comm/third_party/botan/src/lib/misc/srp6/info.txt | 8 | ||||
-rw-r--r-- | comm/third_party/botan/src/lib/misc/srp6/srp6.cpp | 193 | ||||
-rw-r--r-- | comm/third_party/botan/src/lib/misc/srp6/srp6.h | 155 |
3 files changed, 356 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/misc/srp6/info.txt b/comm/third_party/botan/src/lib/misc/srp6/info.txt new file mode 100644 index 0000000000..27b7848f5b --- /dev/null +++ b/comm/third_party/botan/src/lib/misc/srp6/info.txt @@ -0,0 +1,8 @@ +<defines> +SRP6 -> 20161017 +</defines> + +<requires> +bigint +dl_group +</requires> diff --git a/comm/third_party/botan/src/lib/misc/srp6/srp6.cpp b/comm/third_party/botan/src/lib/misc/srp6/srp6.cpp new file mode 100644 index 0000000000..0bd9b192ae --- /dev/null +++ b/comm/third_party/botan/src/lib/misc/srp6/srp6.cpp @@ -0,0 +1,193 @@ +/* +* SRP-6a (RFC 5054 compatatible) +* (C) 2011,2012,2019 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/srp6.h> +#include <botan/hash.h> +#include <botan/dl_group.h> +#include <botan/numthry.h> + +namespace Botan { + +namespace { + +BigInt hash_seq(const std::string& hash_id, + size_t pad_to, + const BigInt& in1, + const BigInt& in2) + { + std::unique_ptr<HashFunction> hash_fn(HashFunction::create_or_throw(hash_id)); + + hash_fn->update(BigInt::encode_1363(in1, pad_to)); + hash_fn->update(BigInt::encode_1363(in2, pad_to)); + + return BigInt::decode(hash_fn->final()); + } + +BigInt compute_x(const std::string& hash_id, + const std::string& identifier, + const std::string& password, + const std::vector<uint8_t>& salt) + { + std::unique_ptr<HashFunction> hash_fn(HashFunction::create_or_throw(hash_id)); + + hash_fn->update(identifier); + hash_fn->update(":"); + hash_fn->update(password); + + secure_vector<uint8_t> inner_h = hash_fn->final(); + + hash_fn->update(salt); + hash_fn->update(inner_h); + + secure_vector<uint8_t> outer_h = hash_fn->final(); + + return BigInt::decode(outer_h); + } + +} + +std::string srp6_group_identifier(const BigInt& N, const BigInt& g) + { + /* + This function assumes that only one 'standard' SRP parameter set has + been defined for a particular bitsize. As of this writing that is the case. + */ + try + { + const std::string group_name = "modp/srp/" + std::to_string(N.bits()); + + DL_Group group(group_name); + + if(group.get_p() == N && group.get_g() == g) + return group_name; + } + catch(...) + { + } + + // If we didn't return, the group was unknown or did not match + throw Invalid_Argument("Invalid or unknown SRP group parameters"); + } + +std::pair<BigInt, SymmetricKey> +srp6_client_agree(const std::string& identifier, + const std::string& password, + const std::string& group_id, + const std::string& hash_id, + const std::vector<uint8_t>& salt, + const BigInt& B, + RandomNumberGenerator& rng) + { + DL_Group group(group_id); + const size_t a_bits = group.exponent_bits(); + + return srp6_client_agree(identifier, password, group, hash_id, salt, B, a_bits, rng); + } + +std::pair<BigInt, SymmetricKey> +srp6_client_agree(const std::string& identifier, + const std::string& password, + const DL_Group& group, + const std::string& hash_id, + const std::vector<uint8_t>& salt, + const BigInt& B, + const size_t a_bits, + RandomNumberGenerator& rng) + { + const BigInt& g = group.get_g(); + const BigInt& p = group.get_p(); + + const size_t p_bytes = group.p_bytes(); + + if(B <= 0 || B >= p) + throw Decoding_Error("Invalid SRP parameter from server"); + + const BigInt k = hash_seq(hash_id, p_bytes, p, g); + + const BigInt a(rng, a_bits); + + const BigInt A = group.power_g_p(a, a_bits); + + const BigInt u = hash_seq(hash_id, p_bytes, A, B); + + const BigInt x = compute_x(hash_id, identifier, password, salt); + + const BigInt S = power_mod(group.mod_p(B - (k * power_mod(g, x, p))), + group.mod_p(a + (u * x)), p); + + const SymmetricKey Sk(BigInt::encode_1363(S, p_bytes)); + + return std::make_pair(A, Sk); + } + +BigInt generate_srp6_verifier(const std::string& identifier, + const std::string& password, + const std::vector<uint8_t>& salt, + const std::string& group_id, + const std::string& hash_id) + { + DL_Group group(group_id); + return generate_srp6_verifier(identifier, password, salt, group, hash_id); + } + +BigInt generate_srp6_verifier(const std::string& identifier, + const std::string& password, + const std::vector<uint8_t>& salt, + const DL_Group& group, + const std::string& hash_id) + { + const BigInt x = compute_x(hash_id, identifier, password, salt); + // FIXME: x should be size of hash fn so avoid computing x.bits() here + return group.power_g_p(x, x.bits()); + } + +BigInt SRP6_Server_Session::step1(const BigInt& v, + const std::string& group_id, + const std::string& hash_id, + RandomNumberGenerator& rng) + { + DL_Group group(group_id); + const size_t b_bits = group.exponent_bits(); + + return this->step1(v, group, hash_id, b_bits, rng); + } + +BigInt SRP6_Server_Session::step1(const BigInt& v, + const DL_Group& group, + const std::string& hash_id, + size_t b_bits, + RandomNumberGenerator& rng) + { + const BigInt& g = group.get_g(); + const BigInt& p = group.get_p(); + + m_p_bytes = p.bytes(); + m_v = v; + m_b = BigInt(rng, b_bits); + m_p = p; + m_hash_id = hash_id; + + const BigInt k = hash_seq(hash_id, m_p_bytes, p, g); + + m_B = group.mod_p(v*k + group.power_g_p(m_b, b_bits)); + + return m_B; + } + +SymmetricKey SRP6_Server_Session::step2(const BigInt& A) + { + if(A <= 0 || A >= m_p) + throw Decoding_Error("Invalid SRP parameter from client"); + + const BigInt u = hash_seq(m_hash_id, m_p_bytes, A, m_B); + + const BigInt S = power_mod(A * power_mod(m_v, u, m_p), m_b, m_p); + + return BigInt::encode_1363(S, m_p_bytes); + } + +} diff --git a/comm/third_party/botan/src/lib/misc/srp6/srp6.h b/comm/third_party/botan/src/lib/misc/srp6/srp6.h new file mode 100644 index 0000000000..6bb4b7e7c5 --- /dev/null +++ b/comm/third_party/botan/src/lib/misc/srp6/srp6.h @@ -0,0 +1,155 @@ +/* +* SRP-6a (RFC 5054 compatatible) +* (C) 2011,2012,2019 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_RFC5054_SRP6_H_ +#define BOTAN_RFC5054_SRP6_H_ + +#include <botan/bigint.h> +#include <botan/symkey.h> +#include <string> + +namespace Botan { + +class DL_Group; +class RandomNumberGenerator; + +/** +* SRP6a Client side +* @param username the username we are attempting login for +* @param password the password we are attempting to use +* @param group_id specifies the shared SRP group +* @param hash_id specifies a secure hash function +* @param salt is the salt value sent by the server +* @param B is the server's public value +* @param rng is a random number generator +* +* @return (A,K) the client public key and the shared secret key +*/ +std::pair<BigInt,SymmetricKey> +BOTAN_PUBLIC_API(2,0) srp6_client_agree(const std::string& username, + const std::string& password, + const std::string& group_id, + const std::string& hash_id, + const std::vector<uint8_t>& salt, + const BigInt& B, + RandomNumberGenerator& rng); + + +/** +* SRP6a Client side +* @param username the username we are attempting login for +* @param password the password we are attempting to use +* @param group specifies the shared SRP group +* @param hash_id specifies a secure hash function +* @param salt is the salt value sent by the server +* @param B is the server's public value +* @param a_bits size of secret exponent in bits +* @param rng is a random number generator +* +* @return (A,K) the client public key and the shared secret key +*/ +std::pair<BigInt,SymmetricKey> BOTAN_PUBLIC_API(2,11) + srp6_client_agree(const std::string& username, + const std::string& password, + const DL_Group& group, + const std::string& hash_id, + const std::vector<uint8_t>& salt, + const BigInt& B, + size_t a_bits, + RandomNumberGenerator& rng); + +/** +* Generate a new SRP-6 verifier +* @param identifier a username or other client identifier +* @param password the secret used to authenticate user +* @param salt a randomly chosen value, at least 128 bits long +* @param group_id specifies the shared SRP group +* @param hash_id specifies a secure hash function +*/ +BigInt BOTAN_PUBLIC_API(2,0) + generate_srp6_verifier(const std::string& identifier, + const std::string& password, + const std::vector<uint8_t>& salt, + const std::string& group_id, + const std::string& hash_id); + +/** +* Generate a new SRP-6 verifier +* @param identifier a username or other client identifier +* @param password the secret used to authenticate user +* @param salt a randomly chosen value, at least 128 bits long +* @param group specifies the shared SRP group +* @param hash_id specifies a secure hash function +*/ +BigInt BOTAN_PUBLIC_API(2,11) + generate_srp6_verifier(const std::string& identifier, + const std::string& password, + const std::vector<uint8_t>& salt, + const DL_Group& group, + const std::string& hash_id); + +/** +* Return the group id for this SRP param set, or else thrown an +* exception +* @param N the group modulus +* @param g the group generator +* @return group identifier +*/ +std::string BOTAN_PUBLIC_API(2,0) srp6_group_identifier(const BigInt& N, const BigInt& g); + +/** +* Represents a SRP-6a server session +*/ +class BOTAN_PUBLIC_API(2,0) SRP6_Server_Session final + { + public: + /** + * Server side step 1 + * @param v the verification value saved from client registration + * @param group_id the SRP group id + * @param hash_id the SRP hash in use + * @param rng a random number generator + * @return SRP-6 B value + */ + BigInt step1(const BigInt& v, + const std::string& group_id, + const std::string& hash_id, + RandomNumberGenerator& rng); + + /** + * Server side step 1 + * This version of step1 added in 2.11 + * + * @param v the verification value saved from client registration + * @param group the SRP group + * @param hash_id the SRP hash in use + * @param rng a random number generator + * @param b_bits size of secret exponent in bits + * @return SRP-6 B value + */ + BigInt step1(const BigInt& v, + const DL_Group& group, + const std::string& hash_id, + const size_t b_bits, + RandomNumberGenerator& rng); + + /** + * Server side step 2 + * @param A the client's value + * @return shared symmetric key + */ + SymmetricKey step2(const BigInt& A); + + private: + std::string m_hash_id; + BigInt m_B, m_b, m_v, m_S, m_p; + size_t m_p_bytes = 0; + }; + +} + +#endif |