adds secret computation.

This commit is contained in:
Moisés Guimarães
2015-07-28 14:55:46 -03:00
parent 6ee788277f
commit ba0c75011b
2 changed files with 193 additions and 124 deletions

View File

@ -150,6 +150,7 @@ int wc_SrpInit(Srp* srp, byte type, byte side)
int r;
/* validating params */
if (!srp)
return BAD_FUNC_ARG;
@ -160,61 +161,46 @@ int wc_SrpInit(Srp* srp, byte type, byte side)
type != SRP_TYPE_SHA384 && type != SRP_TYPE_SHA512)
return BAD_FUNC_ARG;
/* initializing common data */
/* initializing variables */
if ((r = SrpHashInit(&srp->client_proof, type)) != 0)
return r;
if ((r = SrpHashInit(&srp->server_proof, type)) != 0)
return r;
if ((r = mp_init_multi(&srp->N, &srp->g, &srp->s, &srp->u, 0, 0)) != 0)
return r;
if ((r = mp_init_multi(&srp->auth, &srp->peer, &srp->priv, &srp->pub,
0, 0)) != 0) {
/* undo previous initializations on error */
mp_clear(&srp->N); mp_clear(&srp->g);
mp_clear(&srp->s); mp_clear(&srp->u);
return r;
}
srp->side = side; srp->type = type;
srp->salt = NULL; srp->saltSz = 0;
srp->user = NULL; srp->userSz = 0;
if (mp_init_multi(&srp->N, &srp->g, &srp->s, &srp->u, 0, 0) != MP_OKAY)
return MP_INIT_E;
r = SrpHashInit(&srp->client_proof, type);
if (!r) r = SrpHashInit(&srp->server_proof, type);
/* initializing client specific data */
if (!r && srp->side == SRP_CLIENT_SIDE)
r = mp_init_multi(&srp->specific.client.a, &srp->specific.client.A,
&srp->specific.client.B, &srp->specific.client.x,0,0);
/* initializing server specific data */
if (!r && srp->side == SRP_SERVER_SIDE)
r = mp_init_multi(&srp->specific.server.b, &srp->specific.server.B,
&srp->specific.server.A, &srp->specific.server.v,0,0);
/* undo initializations on error */
if (r != 0) {
mp_clear(&srp->N); mp_clear(&srp->g);
mp_clear(&srp->s); mp_clear(&srp->u);
}
return r;
return 0;
}
void wc_SrpTerm(Srp* srp)
{
if (srp) {
mp_clear(&srp->N); mp_clear(&srp->g);
mp_clear(&srp->s); mp_clear(&srp->u);
mp_clear(&srp->N); mp_clear(&srp->g);
mp_clear(&srp->s); mp_clear(&srp->u);
mp_clear(&srp->auth); mp_clear(&srp->peer);
mp_clear(&srp->priv); mp_clear(&srp->pub);
XMEMSET(srp->salt, 0, srp->saltSz);
XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP);
XMEMSET(srp->user, 0, srp->userSz);
XFREE(srp->user, NULL, DYNAMIC_TYPE_SRP);
if (srp->side == SRP_CLIENT_SIDE) {
mp_clear(&srp->specific.client.a);
mp_clear(&srp->specific.client.A);
mp_clear(&srp->specific.client.B);
mp_clear(&srp->specific.client.x);
}
if (srp->side == SRP_SERVER_SIDE) {
mp_clear(&srp->specific.server.b);
mp_clear(&srp->specific.server.B);
mp_clear(&srp->specific.server.A);
mp_clear(&srp->specific.server.v);
}
XMEMSET(srp, 0, sizeof(Srp));
}
}
@ -233,6 +219,7 @@ int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size)
return 0;
}
int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz,
const byte* g, word32 gSz,
const byte* salt, word32 saltSz)
@ -311,6 +298,7 @@ int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size)
{
SrpHash hash;
byte digest[SRP_MAX_DIGEST_SIZE];
word32 digestSz;
int r;
if (!srp || !password || srp->side != SRP_CLIENT_SIDE)
@ -319,6 +307,8 @@ int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size)
if (!srp->salt)
return SRP_CALL_ORDER_E;
digestSz = SrpHashSize(srp->type);
/* digest = H(username | ':' | password) */
r = SrpHashInit(&hash, srp->type);
if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz);
@ -329,13 +319,11 @@ int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size)
/* digest = H(salt | H(username | ':' | password)) */
if (!r) r = SrpHashInit(&hash, srp->type);
if (!r) r = SrpHashUpdate(&hash, srp->salt, srp->saltSz);
if (!r) r = SrpHashUpdate(&hash, digest, SrpHashSize(srp->type));
if (!r) r = SrpHashUpdate(&hash, digest, digestSz);
if (!r) r = SrpHashFinal(&hash, digest);
/* Set x (private key) */
if (!r && mp_read_unsigned_bin(&srp->specific.client.x, digest,
SrpHashSize(srp->type)) != MP_OKAY)
r = MP_READ_E;
if (!r) r = mp_read_unsigned_bin(&srp->auth, digest, digestSz);
XMEMSET(digest, 0, SRP_MAX_DIGEST_SIZE);
@ -350,13 +338,13 @@ int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size)
if (!srp || !verifier || !size || srp->side != SRP_CLIENT_SIDE)
return BAD_FUNC_ARG;
if (mp_iszero(&srp->specific.client.x))
if (mp_iszero(&srp->auth))
return SRP_CALL_ORDER_E;
r = mp_init(&v);
/* v = g ^ x % N */
if (!r) r = mp_exptmod(&srp->g, &srp->specific.client.x, &srp->N, &v);
if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &v);
if (!r) r = *size < (word32)mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY;
if (!r) r = mp_to_unsigned_bin(&v, verifier);
if (!r) *size = mp_unsigned_bin_size(&v);
@ -371,23 +359,19 @@ int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size)
if (!srp || !verifier || srp->side != SRP_SERVER_SIDE)
return BAD_FUNC_ARG;
if (mp_read_unsigned_bin(&srp->specific.server.v, verifier, size)
!= MP_OKAY)
return MP_READ_E;
return 0;
return mp_read_unsigned_bin(&srp->auth, verifier, size);
}
int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) {
int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size)
{
if (!srp || !private || !size)
return BAD_FUNC_ARG;
return mp_read_unsigned_bin(srp->type == SRP_CLIENT_SIDE
? &srp->specific.client.a
: &srp->specific.server.b, private, size);
return mp_read_unsigned_bin(&srp->priv, private, size);
}
static int wc_SrpGenPrivate(Srp* srp, byte* private, word32 size) {
static int wc_SrpGenPrivate(Srp* srp, byte* private, word32 size)
{
RNG rng;
int r = wc_InitRng(&rng);
@ -407,11 +391,10 @@ int wc_SrpGenPublic(Srp* srp, byte* public, word32* size)
if (!srp || (!public && size) || (public && !size))
return BAD_FUNC_ARG;
if (srp->side == SRP_CLIENT_SIDE && mp_iszero(&srp->N))
if (mp_iszero(&srp->N))
return SRP_CALL_ORDER_E;
if (srp->side == SRP_SERVER_SIDE && (mp_iszero(&srp->N) ||
mp_iszero(&srp->specific.server.v)))
if (srp->side == SRP_SERVER_SIDE && mp_iszero(&srp->auth))
return SRP_CALL_ORDER_E;
len = mp_unsigned_bin_size(&srp->N);
@ -422,55 +405,44 @@ int wc_SrpGenPublic(Srp* srp, byte* public, word32* size)
if (!buf)
return MEMORY_E;
/* priv = random() */
if (mp_iszero(&srp->priv))
r = wc_SrpGenPrivate(srp, buf, len);
/* client side: A = g ^ a % N */
if (srp->side == SRP_CLIENT_SIDE) {
/* a = random() */
if (mp_iszero(&srp->specific.client.a))
r = wc_SrpGenPrivate(srp, buf, len);
/* A = g ^ a % N */
if (!r) r = mp_exptmod(&srp->g, &srp->specific.client.a,
&srp->N, &srp->specific.client.A);
if (!r) r = mp_exptmod(&srp->g, &srp->priv,
&srp->N, &srp->pub);
/* extract public key to buffer */
XMEMSET(buf, 0, len);
if (!r) r = mp_to_unsigned_bin(&srp->specific.client.A, buf);
if (!r) len = mp_unsigned_bin_size(&srp->specific.client.A);
/* server side: B = (k * v + (g ^ b % N)) % N */
} else {
mp_int i, j;
if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) {
if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type));
if (!r) r = mp_exptmod(&srp->g, &srp->priv,
&srp->N, &srp->pub);
if (!r) r = mp_mulmod(&i, &srp->auth, &srp->N, &j);
if (!r) r = mp_add(&j, &srp->pub, &i);
if (!r) r = mp_mod(&i, &srp->N, &srp->pub);
mp_clear(&i); mp_clear(&j);
}
}
/* extract public key to buffer */
XMEMSET(buf, 0, len);
if (!r) r = mp_to_unsigned_bin(&srp->pub, buf);
if (!r) len = mp_unsigned_bin_size(&srp->pub);
/* update proofs */
if (srp->side == SRP_CLIENT_SIDE) {
/* Client proof = H( H(N) ^ H(g) | H(user) | salt | A) */
if (!r) r = SrpHashUpdate(&srp->client_proof, buf, len);
/* Server proof = H(A) */
if (!r) r = SrpHashUpdate(&srp->server_proof, buf, len);
} else {
mp_int i, j;
if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) {
/* b = random() */
if (mp_iszero(&srp->specific.server.b))
r = wc_SrpGenPrivate(srp, buf, len);
/* B = (k * v + (g ^ b % N)) % N */
if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type));
if (!r) r = mp_exptmod(&srp->g, &srp->specific.server.b,
&srp->N, &srp->specific.server.B);
if (!r) r = mp_mul(&i, &srp->specific.server.v, &j);
if (!r) r = mp_add(&j, &srp->specific.server.B, &i);
if (!r) r = mp_mod(&i, &srp->N, &srp->specific.server.B);
/* extract public key to buffer */
XMEMSET(buf, 0, len);
if (!r) r = mp_to_unsigned_bin(&srp->specific.server.B, buf);
if (!r) len = mp_unsigned_bin_size(&srp->specific.server.B);
/* Client proof = H( H(N) ^ H(g) | H(user) | salt | A) */
if (!r) r = SrpHashUpdate(&srp->client_proof, buf, len);
/* Server proof = H(A) */
if (!r) r = SrpHashUpdate(&srp->server_proof, buf, len);
mp_clear(&i); mp_clear(&j);
}
}
if (public)
@ -481,4 +453,112 @@ int wc_SrpGenPublic(Srp* srp, byte* public, word32* size)
return r;
}
static int wc_SrpSetU(Srp* srp, byte* peersKey, word32 peersKeySz)
{
SrpHash hash;
byte digest[SRP_MAX_DIGEST_SIZE];
byte* public = NULL;
word32 publicSz = 0;
word32 modulusSz = mp_unsigned_bin_size(&srp->N);
byte pad = 0;
word32 i;
int r = SrpHashInit(&hash, srp->type);
if (!r && srp->side == SRP_CLIENT_SIDE) {
publicSz = mp_unsigned_bin_size(&srp->pub);
public = (byte*)XMALLOC(publicSz, NULL, DYNAMIC_TYPE_SRP);
if (public == NULL)
r = MEMORY_E;
/* H(A) */
if (!r) r = mp_to_unsigned_bin(&srp->pub, public);
for (i = 0; i < modulusSz - publicSz; i++)
SrpHashUpdate(&hash, &pad, 1);
if (!r) r = SrpHashUpdate(&hash, public, publicSz);
/* H(A | B) */
if (!r) r = mp_read_unsigned_bin(&srp->peer,
peersKey, peersKeySz);
for (i = 0; i < modulusSz - peersKeySz; i++)
SrpHashUpdate(&hash, &pad, 1);
if (!r) r = SrpHashUpdate(&hash, peersKey, peersKeySz);
/* Client proof = H( H(N) ^ H(g) | H(user) | salt | A | B) */
if (!r) r = SrpHashUpdate(&srp->client_proof, peersKey, peersKeySz);
} else if (!r && srp->side == SRP_SERVER_SIDE) {
publicSz = mp_unsigned_bin_size(&srp->pub);
public = (byte*)XMALLOC(publicSz, NULL, DYNAMIC_TYPE_SRP);
if (public == NULL)
r = MEMORY_E;
/* H(A) */
if (!r) r = mp_read_unsigned_bin(&srp->peer,
peersKey, peersKeySz);
for (i = 0; i < modulusSz - peersKeySz; i++)
SrpHashUpdate(&hash, &pad, 1);
if (!r) r = SrpHashUpdate(&hash, peersKey, peersKeySz);
/* H(A | B) */
if (!r) r = mp_to_unsigned_bin(&srp->pub, public);
for (i = 0; i < modulusSz - publicSz; i++)
SrpHashUpdate(&hash, &pad, 1);
if (!r) r = SrpHashUpdate(&hash, public, publicSz);
}
if (!r) r = SrpHashFinal(&hash, digest);
if (!r) r = mp_read_unsigned_bin(&srp->u, digest, SrpHashSize(srp->type));
XFREE(public, NULL, DYNAMIC_TYPE_SRP);
return r;
}
WOLFSSL_API int wc_SrpComputeKey(Srp* srp, byte* peersKey, word32 peersKeySz)
{
mp_int i, j;
int r;
if (!srp || !peersKey || peersKeySz == 0)
return BAD_FUNC_ARG;
if ((r = mp_init_multi(&i, &j, 0, 0, 0, 0)) != MP_OKAY)
return r;
r = wc_SrpSetU(srp, peersKey, peersKeySz);
if (!r && srp->side == SRP_CLIENT_SIDE) {
r = mp_read_unsigned_bin(&i, srp->k, SrpHashSize(srp->type));
/* i = B - k * v */
if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &j);
if (!r) r = mp_mulmod(&i, &j, &srp->N, &srp->s);
if (!r) r = mp_sub(&srp->peer, &srp->s, &i);
/* j = a + u * x */
if (!r) r = mp_mulmod(&srp->u, &srp->auth, &srp->N, &srp->s);
if (!r) r = mp_add(&srp->priv, &srp->s, &j);
/* s = i ^ j % N */
if (!r) r = mp_exptmod(&i, &j, &srp->N, &srp->s);
} else if (!r && srp->side == SRP_SERVER_SIDE) {
/* i = v ^ u % N */
if (!r) r = mp_exptmod(&srp->auth, &srp->u, &srp->N, &i);
/* j = A * i % N */
if (!r) r = mp_mulmod(&srp->peer, &i, &srp->N, &j);
/* s = j * b % N */
if (!r) r = mp_exptmod(&j, &srp->priv, &srp->N, &srp->s);
}
mp_clear(&i);
mp_clear(&j);
return r;
}
#endif /* WOLFCRYPT_HAVE_SRP */

View File

@ -83,40 +83,27 @@ typedef struct {
} SrpHash;
typedef struct {
mp_int a; /**< Private ephemeral value. Random. */
mp_int A; /**< Public ephemeral value. pow(g, a, N) */
mp_int B; /**< Server's public ephemeral value. */
mp_int x; /**< Priv key. H(salt, H(user, ":", pswd)) */
} SrpClient;
typedef struct {
mp_int b; /**< Private ephemeral value. */
mp_int B; /**< Public ephemeral value. */
mp_int A; /**< Client's public ephemeral value. */
mp_int v; /**< Verifier. v = pow(g, x, N) */
} SrpServer;
typedef struct {
byte side; /**< Client or Server side. */
byte type; /**< Hash type, SHA[1:256:384:512] */
mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes. */
mp_int g; /**< Generator. A generator modulo N. */
mp_int s; /**< Session key. */
byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */
mp_int u; /**< Random scrambling parameeter. */
byte side; /**< SRP_CLIENT_SIDE or SRP_SERVER_SIDE */
byte type; /**< Hash type, one of SRP_TYPE_SHA[|256|384|512] */
byte* user; /**< Username, login. */
word32 userSz; /**< Username length. */
byte* salt; /**< Small salt. */
word32 saltSz; /**< Salt length. */
mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes. */
mp_int g; /**< Generator. A generator modulo N. */
byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */
mp_int auth; /**< Priv key. H(salt, H(user, ":", pswd)) */
mp_int priv; /**< Private ephemeral value. */
mp_int pub; /**< Public ephemeral value. */
mp_int peer; /**< Peer's public ephemeral value. */
mp_int u; /**< Random scrambling parameeter. */
SrpHash client_proof; /**< Client proof. Sent to Server. */
SrpHash server_proof; /**< Server proof. Sent to Client. */
union {
SrpClient client;
SrpServer server;
} specific;
mp_int s; /**< Session key. */
} Srp;
WOLFSSL_API int wc_SrpInit(Srp* srp, byte type, byte side);
WOLFSSL_API void wc_SrpTerm(Srp* srp);
WOLFSSL_API int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size);
@ -135,6 +122,8 @@ WOLFSSL_API int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size);
WOLFSSL_API int wc_SrpGenPublic(Srp* srp, byte* public, word32* size);
WOLFSSL_API int wc_SrpComputeKey(Srp* srp, byte* peersKey, word32 peersKeySz);
#ifdef __cplusplus
} /* extern "C" */
#endif