blob: f3fa2b63edc802f2f9f96b152ba9ffada275980d [file] [log] [blame]
/*
* 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;
}