| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,14 @@ | ||
| set(UTIL_SRCS | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/auth.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/base64.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/serialize.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/sha1.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/sha256.c | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/string.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/srp.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/timetaker.cpp | ||
| PARENT_SCOPE) | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| /* | ||
| Minetest | ||
| Copyright (C) 2015 est31 <MTest31@outlook.com> | ||
| This program is free software; you can redistribute it and/or modify | ||
| it under the terms of the GNU Lesser General Public License as published by | ||
| the Free Software Foundation; either version 2.1 of the License, or | ||
| (at your option) any later version. | ||
| This program is distributed in the hope that it will be useful, | ||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| GNU Lesser General Public License for more details. | ||
| You should have received a copy of the GNU Lesser General Public License along | ||
| with this program; if not, write to the Free Software Foundation, Inc., | ||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| */ | ||
|
|
||
| #include <algorithm> | ||
| #include <string> | ||
| #include "auth.h" | ||
| #include "base64.h" | ||
| #include "sha1.h" | ||
| #include "srp.h" | ||
| #include "string.h" | ||
|
|
||
| // Get an sha-1 hash of the player's name combined with | ||
| // the password entered. That's what the server uses as | ||
| // their password. (Exception : if the password field is | ||
| // blank, we send a blank password - this is for backwards | ||
| // compatibility with password-less players). | ||
| std::string translatePassword(const std::string &name, | ||
| const std::string &password) | ||
| { | ||
| if (password.length() == 0) | ||
| return ""; | ||
|
|
||
| std::string slt = name + password; | ||
| SHA1 sha1; | ||
| sha1.addBytes(slt.c_str(), slt.length()); | ||
| unsigned char *digest = sha1.getDigest(); | ||
| std::string pwd = base64_encode(digest, 20); | ||
| free(digest); | ||
| return pwd; | ||
| } | ||
|
|
||
| void getSRPVerifier(const std::string &name, | ||
| const std::string &password, char **salt, size_t *salt_len, | ||
| char **bytes_v, size_t *len_v) | ||
| { | ||
| std::string n_name = lowercase(name); | ||
| srp_create_salted_verification_key(SRP_SHA256, SRP_NG_2048, | ||
| n_name.c_str(), (const unsigned char *)password.c_str(), | ||
| password.size(), (unsigned char **)salt, salt_len, | ||
| (unsigned char **)bytes_v, len_v, NULL, NULL); | ||
| } | ||
|
|
||
| // Get a db-ready SRP verifier | ||
| // The salt param is only modifyable by this method so that you can free it | ||
| // if it was allocated. You shouldn't use it for other purposes, as you will | ||
| // need the contents of salt_len too. | ||
| inline static std::string getSRPVerifier(const std::string &name, | ||
| const std::string &password, char ** salt, size_t salt_len) | ||
| { | ||
| char * bytes_v = NULL; | ||
| size_t len_v; | ||
| getSRPVerifier(name, password, salt, &salt_len, | ||
| &bytes_v, &len_v); | ||
| std::string ret_val = encodeSRPVerifier(std::string(bytes_v, len_v), | ||
| std::string(*salt, salt_len)); | ||
| free(bytes_v); | ||
| return ret_val; | ||
| } | ||
|
|
||
| // Get a db-ready SRP verifier | ||
| std::string getSRPVerifier(const std::string &name, | ||
| const std::string &password) | ||
| { | ||
| char * salt = NULL; | ||
| std::string ret_val = getSRPVerifier(name, | ||
| password, &salt, 0); | ||
| free(salt); | ||
| return ret_val; | ||
| } | ||
|
|
||
| // Get a db-ready SRP verifier | ||
| std::string getSRPVerifier(const std::string &name, | ||
| const std::string &password, const std::string &salt) | ||
| { | ||
| // The implementation won't change the salt if its set, | ||
| // therefore we can cast. | ||
| char *salt_cstr = (char *)salt.c_str(); | ||
| return getSRPVerifier(name, password, | ||
| &salt_cstr, salt.size()); | ||
| } | ||
|
|
||
| // Make a SRP verifier db-ready | ||
| std::string encodeSRPVerifier(const std::string &verifier, | ||
| const std::string &salt) | ||
| { | ||
| std::ostringstream ret_str; | ||
| ret_str << "#1#" | ||
| << base64_encode((unsigned char*) salt.c_str(), salt.size()) << "#" | ||
| << base64_encode((unsigned char*) verifier.c_str(), verifier.size()); | ||
| return ret_str.str(); | ||
| } | ||
|
|
||
| bool decodeSRPVerifier(const std::string &enc_pwd, | ||
| std::string *salt, std::string *bytes_v) | ||
| { | ||
| std::vector<std::string> pwd_components = str_split(enc_pwd, '#'); | ||
|
|
||
| if ((pwd_components.size() != 4) | ||
| || (pwd_components[1] != "1") // 1 means srp | ||
| || !base64_is_valid(pwd_components[2]) | ||
| || !base64_is_valid(pwd_components[3])) | ||
| return false; | ||
|
|
||
| std::string salt_str = base64_decode(pwd_components[2]); | ||
| std::string bytes_v_str = base64_decode(pwd_components[3]); | ||
| *salt = salt_str; | ||
| *bytes_v = bytes_v_str; | ||
| return true; | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| /* | ||
| Minetest | ||
| Copyright (C) 2015 est31 <MTest31@outlook.com> | ||
| This program is free software; you can redistribute it and/or modify | ||
| it under the terms of the GNU Lesser General Public License as published by | ||
| the Free Software Foundation; either version 2.1 of the License, or | ||
| (at your option) any later version. | ||
| This program is distributed in the hope that it will be useful, | ||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| GNU Lesser General Public License for more details. | ||
| You should have received a copy of the GNU Lesser General Public License along | ||
| with this program; if not, write to the Free Software Foundation, Inc., | ||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| */ | ||
|
|
||
| #ifndef AUTH_H | ||
| #define AUTH_H | ||
|
|
||
| std::string translatePassword(const std::string &name, | ||
| const std::string &password); | ||
| void getSRPVerifier(const std::string &name, | ||
| const std::string &password, char **salt, size_t *salt_len, | ||
| char **bytes_v, size_t *len_v); | ||
| std::string getSRPVerifier(const std::string &name, | ||
| const std::string &password); | ||
| std::string getSRPVerifier(const std::string &name, | ||
| const std::string &password, const std::string &salt); | ||
| std::string encodeSRPVerifier(const std::string &verifier, | ||
| const std::string &salt); | ||
| bool decodeSRPVerifier(const std::string &enc_pwd, | ||
| std::string *salt, std::string *bytes_v); | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,154 @@ | ||
| /* crypto/sha/sha.h */ | ||
| /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | ||
| * All rights reserved. | ||
| * | ||
| * This package is an SSL implementation written | ||
| * by Eric Young (eay@cryptsoft.com). | ||
| * The implementation was written so as to conform with Netscapes SSL. | ||
| * | ||
| * This library is free for commercial and non-commercial use as long as | ||
| * the following conditions are aheared to. The following conditions | ||
| * apply to all code found in this distribution, be it the RC4, RSA, | ||
| * lhash, DES, etc., code; not just the SSL code. The SSL documentation | ||
| * included with this distribution is covered by the same copyright terms | ||
| * except that the holder is Tim Hudson (tjh@cryptsoft.com). | ||
| * | ||
| * Copyright remains Eric Young's, and as such any Copyright notices in | ||
| * the code are not to be removed. | ||
| * If this package is used in a product, Eric Young should be given attribution | ||
| * as the author of the parts of the library used. | ||
| * This can be in the form of a textual message at program startup or | ||
| * in documentation (online or textual) provided with the package. | ||
| * | ||
| * Redistribution and use in source and binary forms, with or without | ||
| * modification, are permitted provided that the following conditions | ||
| * are met: | ||
| * 1. Redistributions of source code must retain the copyright | ||
| * notice, this list of conditions and the following disclaimer. | ||
| * 2. Redistributions in binary form must reproduce the above copyright | ||
| * notice, this list of conditions and the following disclaimer in the | ||
| * documentation and/or other materials provided with the distribution. | ||
| * 3. All advertising materials mentioning features or use of this software | ||
| * must display the following acknowledgement: | ||
| * "This product includes cryptographic software written by | ||
| * Eric Young (eay@cryptsoft.com)" | ||
| * The word 'cryptographic' can be left out if the rouines from the library | ||
| * being used are not cryptographic related :-). | ||
| * 4. If you include any Windows specific code (or a derivative thereof) from | ||
| * the apps directory (application code) you must include an acknowledgement: | ||
| * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | ||
| * | ||
| * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND | ||
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | ||
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| * SUCH DAMAGE. | ||
| * | ||
| * The licence and distribution terms for any publically available version or | ||
| * derivative of this code cannot be changed. i.e. this code cannot simply be | ||
| * copied and put under another distribution licence | ||
| * [including the GNU Public Licence.] | ||
| */ | ||
|
|
||
| #ifndef HEADER_SHA_H | ||
| # define HEADER_SHA_H | ||
|
|
||
| # include <stddef.h> | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| # if defined(OPENSSL_NO_SHA) || (defined(OPENSSL_NO_SHA0) && defined(OPENSSL_NO_SHA1)) | ||
| # error SHA is disabled. | ||
| # endif | ||
|
|
||
| # if defined(OPENSSL_FIPS) | ||
| # define FIPS_SHA_SIZE_T size_t | ||
| # endif | ||
|
|
||
| /* | ||
| Compat stuff from OpenSSL land | ||
| */ | ||
|
|
||
| /* crypto.h */ | ||
|
|
||
| # define fips_md_init(alg) fips_md_init_ctx(alg, alg) | ||
|
|
||
| # define fips_md_init_ctx(alg, cx) \ | ||
| int alg##_Init(cx##_CTX *c) | ||
| # define fips_cipher_abort(alg) while(0) | ||
|
|
||
| /*- | ||
| * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
| * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then ! | ||
| * ! SHA_LONG_LOG2 has to be defined along. ! | ||
| * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
| */ | ||
|
|
||
| # if defined(__LP32__) | ||
| # define SHA_LONG unsigned long | ||
| # elif defined(__ILP64__) | ||
| # define SHA_LONG unsigned long | ||
| # define SHA_LONG_LOG2 3 | ||
| # else | ||
| # define SHA_LONG unsigned int | ||
| # endif | ||
|
|
||
| # define SHA_LBLOCK 16 | ||
| # define SHA_CBLOCK (SHA_LBLOCK*4)/* SHA treats input data as a | ||
| * contiguous array of 32 bit wide | ||
| * big-endian values. */ | ||
| # define SHA_LAST_BLOCK (SHA_CBLOCK-8) | ||
| # define SHA_DIGEST_LENGTH 20 | ||
|
|
||
| typedef struct SHAstate_st { | ||
| SHA_LONG h0, h1, h2, h3, h4; | ||
| SHA_LONG Nl, Nh; | ||
| SHA_LONG data[SHA_LBLOCK]; | ||
| unsigned int num; | ||
| } SHA_CTX; | ||
|
|
||
| # define SHA256_CBLOCK (SHA_LBLOCK*4)/* SHA-256 treats input data as a | ||
| * contiguous array of 32 bit wide | ||
| * big-endian values. */ | ||
| # define SHA224_DIGEST_LENGTH 28 | ||
| # define SHA256_DIGEST_LENGTH 32 | ||
|
|
||
| typedef struct SHA256state_st { | ||
| SHA_LONG h[8]; | ||
| SHA_LONG Nl, Nh; | ||
| SHA_LONG data[SHA_LBLOCK]; | ||
| unsigned int num, md_len; | ||
| } SHA256_CTX; | ||
|
|
||
| # ifndef OPENSSL_NO_SHA256 | ||
| # ifdef OPENSSL_FIPS | ||
| int private_SHA224_Init(SHA256_CTX *c); | ||
| int private_SHA256_Init(SHA256_CTX *c); | ||
| # endif | ||
| int SHA224_Init(SHA256_CTX *c); | ||
| int SHA224_Update(SHA256_CTX *c, const void *data, size_t len); | ||
| int SHA224_Final(unsigned char *md, SHA256_CTX *c); | ||
| unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md); | ||
| int SHA256_Init(SHA256_CTX *c); | ||
| int SHA256_Update(SHA256_CTX *c, const void *data, size_t len); | ||
| int SHA256_Final(unsigned char *md, SHA256_CTX *c); | ||
| unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md); | ||
| void SHA256_Transform(SHA256_CTX *c, const unsigned char *data); | ||
| # endif | ||
|
|
||
| # define SHA384_DIGEST_LENGTH 48 | ||
| # define SHA512_DIGEST_LENGTH 64 | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,171 @@ | ||
| /* | ||
| * Secure Remote Password 6a implementation | ||
| * https://github.com/est31/csrp-gmp | ||
| * | ||
| * The MIT License (MIT) | ||
| * | ||
| * Copyright (c) 2010, 2013 Tom Cocagne, 2015 est31 <MTest31@outlook.com> | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
| * this software and associated documentation files (the "Software"), to deal in | ||
| * the Software without restriction, including without limitation the rights to | ||
| * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||
| * of the Software, and to permit persons to whom the Software is furnished to do | ||
| * so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in all | ||
| * copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| * SOFTWARE. | ||
| * | ||
| */ | ||
|
|
||
| /* | ||
| * | ||
| * Purpose: This is a direct implementation of the Secure Remote Password | ||
| * Protocol version 6a as described by | ||
| * http://srp.stanford.edu/design.html | ||
| * | ||
| * Author: tom.cocagne@gmail.com (Tom Cocagne) | ||
| * | ||
| * Dependencies: LibGMP | ||
| * | ||
| * Usage: Refer to test_srp.c for a demonstration | ||
| * | ||
| * Notes: | ||
| * This library allows multiple combinations of hashing algorithms and | ||
| * prime number constants. For authentication to succeed, the hash and | ||
| * prime number constants must match between | ||
| * srp_create_salted_verification_key(), srp_user_new(), | ||
| * and srp_verifier_new(). A recommended approach is to determine the | ||
| * desired level of security for an application and globally define the | ||
| * hash and prime number constants to the predetermined values. | ||
| * | ||
| * As one might suspect, more bits means more security. As one might also | ||
| * suspect, more bits also means more processing time. The test_srp.c | ||
| * program can be easily modified to profile various combinations of | ||
| * hash & prime number pairings. | ||
| */ | ||
|
|
||
| #ifndef SRP_H | ||
| #define SRP_H | ||
|
|
||
|
|
||
| struct SRPVerifier; | ||
| struct SRPUser; | ||
|
|
||
| typedef enum | ||
| { | ||
| SRP_NG_1024, | ||
| SRP_NG_2048, | ||
| SRP_NG_4096, | ||
| SRP_NG_8192, | ||
| SRP_NG_CUSTOM | ||
| } SRP_NGType; | ||
|
|
||
| typedef enum | ||
| { | ||
| /*SRP_SHA1,*/ | ||
| /*SRP_SHA224,*/ | ||
| SRP_SHA256, | ||
| /*SRP_SHA384, | ||
| SRP_SHA512*/ | ||
| } SRP_HashAlgorithm; | ||
|
|
||
| /* Out: bytes_v, len_v | ||
| * | ||
| * The caller is responsible for freeing the memory allocated for bytes_v | ||
| * | ||
| * The n_hex and g_hex parameters should be 0 unless SRP_NG_CUSTOM is used for ng_type. | ||
| * If provided, they must contain ASCII text of the hexidecimal notation. | ||
| * | ||
| * If bytes_s == NULL, it is filled with random data. The caller is responsible for freeing. | ||
| */ | ||
| void srp_create_salted_verification_key( SRP_HashAlgorithm alg, | ||
| SRP_NGType ng_type, const char *username_for_verifier, | ||
| const unsigned char *password, size_t len_password, | ||
| unsigned char **bytes_s, size_t *len_s, | ||
| unsigned char **bytes_v, size_t *len_v, | ||
| const char * n_hex, const char *g_hex ); | ||
|
|
||
| /* Out: bytes_B, len_B. | ||
| * | ||
| * On failure, bytes_B will be set to NULL and len_B will be set to 0 | ||
| * | ||
| * The n_hex and g_hex parameters should be 0 unless SRP_NG_CUSTOM is used for ng_type | ||
| * | ||
| * If bytes_b == NULL, random data is used for b. | ||
| */ | ||
| struct SRPVerifier* srp_verifier_new(SRP_HashAlgorithm alg, SRP_NGType ng_type, | ||
| const char *username, | ||
| const unsigned char *bytes_s, size_t len_s, | ||
| const unsigned char *bytes_v, size_t len_v, | ||
| const unsigned char *bytes_A, size_t len_A, | ||
| const unsigned char *bytes_b, size_t len_b, | ||
| unsigned char** bytes_B, size_t *len_B, | ||
| const char* n_hex, const char* g_hex); | ||
|
|
||
|
|
||
| void srp_verifier_delete( struct SRPVerifier* ver ); | ||
|
|
||
|
|
||
| int srp_verifier_is_authenticated( struct SRPVerifier* ver ); | ||
|
|
||
|
|
||
| const char * srp_verifier_get_username( struct SRPVerifier* ver ); | ||
|
|
||
| /* key_length may be null */ | ||
| const unsigned char* srp_verifier_get_session_key( struct SRPVerifier* ver, | ||
| size_t *key_length ); | ||
|
|
||
|
|
||
| size_t srp_verifier_get_session_key_length(struct SRPVerifier* ver); | ||
|
|
||
|
|
||
| /* user_M must be exactly srp_verifier_get_session_key_length() bytes in size */ | ||
| void srp_verifier_verify_session( struct SRPVerifier* ver, | ||
| const unsigned char* user_M, unsigned char** bytes_HAMK ); | ||
|
|
||
| /*******************************************************************************/ | ||
|
|
||
| /* The n_hex and g_hex parameters should be 0 unless SRP_NG_CUSTOM is used for ng_type */ | ||
| struct SRPUser *srp_user_new(SRP_HashAlgorithm alg, SRP_NGType ng_type, | ||
| const char *username, const char *username_for_verifier, | ||
| const unsigned char *bytes_password, size_t len_password, | ||
| const char *n_hex, const char *g_hex); | ||
|
|
||
| void srp_user_delete(struct SRPUser * usr); | ||
|
|
||
| int srp_user_is_authenticated(struct SRPUser * usr); | ||
|
|
||
|
|
||
| const char* srp_user_get_username(struct SRPUser * usr); | ||
|
|
||
| /* key_length may be null */ | ||
| const unsigned char* srp_user_get_session_key(struct SRPUser* usr, size_t* key_length); | ||
|
|
||
| size_t srp_user_get_session_key_length(struct SRPUser* usr); | ||
|
|
||
| /* Output: username, bytes_A, len_A. If you don't want it get written, set username to NULL. | ||
| * If bytes_a == NULL, random data is used for a. */ | ||
| void srp_user_start_authentication(struct SRPUser* usr, char** username, | ||
| const unsigned char* bytes_a, size_t len_a, | ||
| unsigned char** bytes_A, size_t* len_A); | ||
|
|
||
| /* Output: bytes_M, len_M (len_M may be null and will always be | ||
| * srp_user_get_session_key_length() bytes in size) */ | ||
| void srp_user_process_challenge(struct SRPUser *usr, | ||
| const unsigned char *bytes_s, size_t len_s, | ||
| const unsigned char *bytes_B, size_t len_B, | ||
| unsigned char **bytes_M, size_t *len_M); | ||
|
|
||
| /* bytes_HAMK must be exactly srp_user_get_session_key_length() bytes in size */ | ||
| void srp_user_verify_session(struct SRPUser* usr, const unsigned char* bytes_HAMK); | ||
|
|
||
| #endif /* Include Guard */ |