| /* |
| * Copyright (c) 1997-2007 The Stanford SRP Authentication Project |
| * All Rights Reserved. |
| * |
| * 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" AND WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY |
| * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. |
| * |
| * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL, |
| * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER |
| * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF |
| * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT |
| * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| * |
| * Redistributions in source or binary form must retain an intact copy |
| * of this copyright notice. |
| */ |
| |
| #include "t_defines.h" |
| //#include "t_pwd.h" |
| #include "srp.h" |
| |
| static int library_initialized = 0; |
| |
| _TYPE( SRP_RESULT ) |
| SRP_initialize_library() |
| { |
| if(library_initialized == 0) { |
| BigIntegerInitialize(); |
| t_stronginitrand(); |
| library_initialized = 1; |
| } |
| return SRP_SUCCESS; |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_finalize_library() |
| { |
| if(library_initialized > 0) { |
| library_initialized = 0; |
| BigIntegerFinalize(); |
| } |
| return SRP_SUCCESS; |
| } |
| |
| static int srp_modulus_min_bits = SRP_DEFAULT_MIN_BITS; |
| |
| _TYPE( SRP_RESULT ) |
| SRP_set_modulus_min_bits(int minbits) |
| { |
| srp_modulus_min_bits = minbits; |
| return SRP_SUCCESS; |
| } |
| |
| _TYPE( int ) |
| SRP_get_modulus_min_bits() |
| { |
| return srp_modulus_min_bits; |
| } |
| |
| static int |
| default_secret_bits_cb(int modsize) |
| { |
| return 256; |
| /*return modsize;*/ /* Warning: Very Slow */ |
| } |
| |
| static SRP_SECRET_BITS_CB srp_sb_cb = default_secret_bits_cb; |
| |
| _TYPE( SRP_RESULT ) |
| SRP_set_secret_bits_cb(SRP_SECRET_BITS_CB cb) |
| { |
| srp_sb_cb = cb; |
| return SRP_SUCCESS; |
| } |
| |
| _TYPE( int ) |
| SRP_get_secret_bits(int modsize) |
| { |
| return (*srp_sb_cb)(modsize); |
| } |
| |
| #if 0 |
| _TYPE( SRP_SERVER_LOOKUP * ) |
| SRP_SERVER_LOOKUP_new(SRP_SERVER_LOOKUP_METHOD * meth) |
| { |
| SRP_SERVER_LOOKUP * slu = (SRP_SERVER_LOOKUP *) malloc(sizeof(SRP_SERVER_LOOKUP)); |
| if(slu == NULL) |
| return NULL; |
| |
| slu->meth = meth; |
| slu->data = NULL; |
| if(slu->meth->init == NULL || (*slu->meth->init)(slu) == SRP_SUCCESS) |
| return slu; |
| free(slu); |
| return NULL; |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_SERVER_LOOKUP_free(SRP_SERVER_LOOKUP * slu) |
| { |
| if(slu->meth->finish) |
| (*slu->meth->finish)(slu); |
| free(slu); |
| return SRP_SUCCESS; |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_SERVER_do_lookup(SRP_SERVER_LOOKUP * slu, SRP * srp, cstr * username) |
| { |
| return (*slu->meth->lookup)(slu, srp, username); |
| } |
| #endif |
| |
| _TYPE( SRP * ) |
| SRP_new(SRP_METHOD * meth) |
| { |
| SRP * srp = (SRP *) malloc(sizeof(SRP)); |
| |
| if(srp == NULL) |
| return NULL; |
| |
| srp->flags = 0; |
| srp->username = cstr_new(); |
| srp->bctx = BigIntegerCtxNew(); |
| srp->modulus = NULL; |
| srp->accel = NULL; |
| srp->generator = NULL; |
| srp->salt = NULL; |
| srp->verifier = NULL; |
| srp->password = NULL; |
| srp->pubkey = NULL; |
| srp->secret = NULL; |
| srp->u = NULL; |
| srp->key = NULL; |
| srp->ex_data = cstr_new(); |
| srp->param_cb = NULL; |
| srp->meth = meth; |
| srp->meth_data = NULL; |
| //srp->slu = NULL; |
| if(srp->meth->init == NULL || (*srp->meth->init)(srp) == SRP_SUCCESS) |
| return srp; |
| free(srp); |
| return NULL; |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_free(SRP * srp) |
| { |
| if(srp->meth->finish) |
| (*srp->meth->finish)(srp); |
| |
| if(srp->username) |
| cstr_clear_free(srp->username); |
| if(srp->modulus) |
| BigIntegerFree(srp->modulus); |
| if(srp->accel) |
| BigIntegerModAccelFree(srp->accel); |
| if(srp->generator) |
| BigIntegerFree(srp->generator); |
| if(srp->salt) |
| cstr_clear_free(srp->salt); |
| if(srp->verifier) |
| BigIntegerClearFree(srp->verifier); |
| if(srp->password) |
| BigIntegerClearFree(srp->password); |
| if(srp->pubkey) |
| BigIntegerFree(srp->pubkey); |
| if(srp->secret) |
| BigIntegerClearFree(srp->secret); |
| if(srp->u) |
| BigIntegerFree(srp->u); |
| if(srp->key) |
| BigIntegerClearFree(srp->key); |
| if(srp->bctx) |
| BigIntegerCtxFree(srp->bctx); |
| if(srp->ex_data) |
| cstr_clear_free(srp->ex_data); |
| free(srp); |
| return SRP_SUCCESS; |
| } |
| |
| #if 0 |
| _TYPE( SRP_RESULT ) |
| SRP_set_server_lookup(SRP * srp, SRP_SERVER_LOOKUP * lookup) |
| { |
| srp->slu = lookup; |
| return SRP_SUCCESS; |
| } |
| #endif |
| |
| _TYPE( SRP_RESULT ) |
| SRP_set_client_param_verify_cb(SRP * srp, SRP_CLIENT_PARAM_VERIFY_CB cb) |
| { |
| srp->param_cb = cb; |
| return SRP_SUCCESS; |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_set_username(SRP * srp, const char * username) |
| { |
| cstr_set(srp->username, username); |
| #if 0 |
| if(srp->slu) |
| return SRP_SERVER_do_lookup(srp->slu, srp, srp->username); |
| else |
| #endif |
| return SRP_SUCCESS; |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_set_user_raw(SRP * srp, const unsigned char * user, int userlen) |
| { |
| cstr_setn(srp->username, (const char*)user, userlen); |
| #if 0 |
| if(srp->slu) |
| return SRP_SERVER_do_lookup(srp->slu, srp, srp->username); |
| else |
| #endif |
| return SRP_SUCCESS; |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_set_params(SRP * srp, const unsigned char * modulus, int modlen, |
| const unsigned char * generator, int genlen, |
| const unsigned char * salt, int saltlen) |
| { |
| SRP_RESULT rc; |
| |
| if(modulus == NULL || generator == NULL || salt == NULL) |
| return SRP_ERROR; |
| |
| /* Set fields in SRP context */ |
| srp->modulus = BigIntegerFromBytes(modulus, modlen); |
| if(srp->flags & SRP_FLAG_MOD_ACCEL) |
| srp->accel = BigIntegerModAccelNew(srp->modulus, srp->bctx); |
| srp->generator = BigIntegerFromBytes(generator, genlen); |
| if(srp->salt == NULL) |
| srp->salt = cstr_new(); |
| cstr_setn(srp->salt, (const char*)salt, saltlen); |
| |
| /* Now attempt to validate parameters */ |
| if(BigIntegerBitLen(srp->modulus) < SRP_get_modulus_min_bits()) |
| return SRP_ERROR; |
| |
| if(srp->param_cb) { |
| rc = (*srp->param_cb)(srp, modulus, modlen, generator, genlen); |
| if(!SRP_OK(rc)) |
| return rc; |
| } |
| |
| return (*srp->meth->params)(srp, modulus, modlen, generator, genlen, |
| salt, saltlen); |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_set_authenticator(SRP * srp, const unsigned char * a, int alen) |
| { |
| return (*srp->meth->auth)(srp, a, alen); |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_set_auth_password(SRP * srp, const char * password) |
| { |
| return (*srp->meth->passwd)(srp, (const unsigned char *)password, |
| strlen(password)); |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_set_auth_password_raw(SRP * srp, |
| const unsigned char * password, int passlen) |
| { |
| return (*srp->meth->passwd)(srp, password, passlen); |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_gen_pub(SRP * srp, cstr ** result) |
| { |
| return (*srp->meth->genpub)(srp, result); |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_add_ex_data(SRP * srp, const unsigned char * data, int datalen) |
| { |
| cstr_appendn(srp->ex_data, (const char*)data, datalen); |
| return SRP_SUCCESS; |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_compute_key(SRP * srp, cstr ** result, |
| const unsigned char * pubkey, int pubkeylen) |
| { |
| return (*srp->meth->key)(srp, result, pubkey, pubkeylen); |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_verify(SRP * srp, const unsigned char * proof, int prooflen) |
| { |
| return (*srp->meth->verify)(srp, proof, prooflen); |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_respond(SRP * srp, cstr ** proof) |
| { |
| return (*srp->meth->respond)(srp, proof); |
| } |
| |
| #if 0 |
| #include "t_pwd.h" |
| |
| /* Convenience functions - currently depend on classic EPS API */ |
| |
| _TYPE( SRP_RESULT ) |
| SRP_server_init_user(SRP * srp, const char * username) |
| { |
| SRP_set_server_lookup(srp, SRP_SERVER_system_lookup()); |
| return SRP_set_username(srp, username); |
| } |
| |
| static SRP_RESULT |
| slu_nop(SRP_SERVER_LOOKUP * slu) |
| { |
| return SRP_SUCCESS; |
| } |
| |
| static SRP_RESULT |
| slu_sys_lookup(SRP_SERVER_LOOKUP * slu, SRP * srp, cstr * username) |
| { |
| struct t_passwd * p; |
| |
| p = gettpnam(username->data); |
| if(p == NULL) |
| return SRP_ERROR; |
| if(!SRP_OK(SRP_set_params(srp, p->tc.modulus.data, p->tc.modulus.len, |
| p->tc.generator.data, p->tc.generator.len, |
| p->tp.salt.data, p->tp.salt.len))) |
| return SRP_ERROR; |
| if(!SRP_OK(SRP_set_authenticator(srp, |
| p->tp.password.data, p->tp.password.len))) |
| return SRP_ERROR; |
| |
| return SRP_SUCCESS; |
| } |
| |
| static struct srp_s_lu_meth_st srp_s_lu_sys_meth = { |
| "SRP/EPS system lookup", |
| slu_nop, |
| slu_nop, |
| slu_sys_lookup, |
| NULL |
| }; |
| |
| static struct srp_server_lu_st srp_s_sys_lookup = { |
| &srp_s_lu_sys_meth, |
| NULL |
| }; |
| |
| _TYPE( SRP_SERVER_LOOKUP * ) |
| SRP_SERVER_system_lookup() |
| { |
| return &srp_s_sys_lookup; |
| } |
| #endif |
| |
| //extern int t_isprime(BigInteger); |
| |
| #if 0 |
| _TYPE( SRP_RESULT ) |
| SRP_CLIENT_builtin_param_verify_cb(SRP * srp, const unsigned char * mod, int modlen, const unsigned char * gen, int genlen) |
| { |
| struct t_preconf * tpc; |
| int i; |
| |
| for(i = 0; i < t_getprecount(); ++i) { |
| tpc = t_getpreparam(i); |
| if(tpc->modulus.len == modlen && tpc->generator.len == genlen && |
| memcmp(tpc->modulus.data, mod, modlen) == 0 && |
| memcmp(tpc->generator.data, gen, genlen) == 0) { |
| return SRP_SUCCESS; /* Match found, done */ |
| } |
| } |
| return SRP_ERROR; |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_CLIENT_compat_param_verify_cb(SRP * srp, const unsigned char * mod, int modlen, const unsigned char * gen, int genlen) |
| { |
| SRP_RESULT rc; |
| BigInteger q, r; |
| |
| rc = SRP_CLIENT_builtin_param_verify_cb(srp, mod, modlen, gen, genlen); |
| if(SRP_OK(rc)) |
| return rc; |
| |
| /* Now do a safe-primality and generator test */ |
| if(!t_isprime(srp->modulus)) |
| return SRP_ERROR; |
| |
| rc = SRP_ERROR; |
| /* q = (n-1)/2 */ |
| q = BigIntegerFromInt(0); |
| BigIntegerSubInt(q, srp->modulus, 1); |
| BigIntegerDivInt(q, q, 2, srp->bctx); |
| if(t_isprime(q) && BigIntegerCmp(srp->modulus, srp->generator) > 0) { |
| r = BigIntegerFromInt(0); /* Check g^q == -1 (mod n) */ |
| BigIntegerModExp(r, srp->generator, q, srp->modulus, srp->bctx, srp->accel); |
| BigIntegerAddInt(r, r, 1); |
| if(BigIntegerCmp(r, srp->modulus) == 0) { |
| BigIntegerAddInt(r, srp->generator, 1); |
| if(BigIntegerCmp(r, srp->modulus) != 0) |
| rc = SRP_SUCCESS; |
| } |
| BigIntegerFree(r); |
| } |
| BigIntegerFree(q); |
| return rc; |
| } |
| |
| _TYPE( SRP_RESULT ) |
| SRP_CLIENT_default_param_verify_cb(SRP * srp, const unsigned char * mod, int modlen, const unsigned char * gen, int genlen) |
| { |
| return SRP_CLIENT_builtin_param_verify_cb(srp, mod, modlen, gen, genlen); |
| } |
| #endif |
| |
| _TYPE( SRP_RESULT ) |
| SRP_use_engine(const char * engine) |
| { |
| if(BigIntegerOK(BigIntegerUseEngine(engine))) |
| return SRP_SUCCESS; |
| else |
| return SRP_ERROR; |
| } |