From 6d5efccc55df7519c4b1b9d83cbef32384627b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Thu, 16 Jul 2015 16:03:18 -0300 Subject: [PATCH] finishes SrpSetPassword(), SrpSetVerifier(), SrpGetVerifier(); updates client_proof during SrpSetParams(); --- tests/srp.c | 11 +-- wolfcrypt/src/srp.c | 186 +++++++++++++++++++++++++++------------- wolfssl/wolfcrypt/srp.h | 11 ++- 3 files changed, 141 insertions(+), 67 deletions(-) diff --git a/tests/srp.c b/tests/srp.c index a2d59c829..765d8f81f 100644 --- a/tests/srp.c +++ b/tests/srp.c @@ -30,7 +30,7 @@ #ifdef WOLFCRYPT_HAVE_SRP -static char username[] = "username"; +static char user[] = "user"; static byte N[] = { 0x00, 0xc0, 0x37, 0xc3, 0x75, 0x88, 0xb4, 0x32, 0x98, 0x87, 0xe6, 0x1c, @@ -76,13 +76,13 @@ static void test_SrpSetUsername(void) AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); /* invalid params */ - AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(NULL, username)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(NULL, user)); AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(&srp, NULL)); /* success */ - AssertIntEQ(0, wc_SrpSetUsername(&srp, username)); - AssertIntEQ((int) XSTRLEN(username), srp.usernameSz); - AssertIntEQ(0, XMEMCMP(srp.username, username, srp.usernameSz)); + AssertIntEQ(0, wc_SrpSetUsername(&srp, user)); + AssertIntEQ((int) XSTRLEN(user), srp.userSz); + AssertIntEQ(0, XMEMCMP(srp.user, user, srp.userSz)); wc_SrpTerm(&srp); } @@ -92,6 +92,7 @@ static void test_SrpSetParams(void) Srp srp; AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + AssertIntEQ(0, wc_SrpSetUsername(&srp, user)); /* invalid params */ AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(NULL, N, sizeof(N), diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 555f3172c..73d79ad4f 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -60,7 +60,7 @@ static int SrpHashInit(SrpHash* hash, int type) } } -static int SrpHashUpdate(SrpHash* hash, byte* data, word32 size) +static int SrpHashUpdate(SrpHash* hash, const byte* data, word32 size) { switch (hash->type) { #ifndef NO_SHA @@ -146,10 +146,9 @@ static word32 SrpHashSize(byte type) int wc_SrpInit(Srp* srp, byte type, byte side) { - int ret = 0; + int r; /* validating params */ - if (!srp) return BAD_FUNC_ARG; @@ -161,64 +160,51 @@ int wc_SrpInit(Srp* srp, byte type, byte side) return BAD_FUNC_ARG; /* initializing common data */ - - srp->side = side; srp->type = type; - srp->salt = NULL; srp->saltSz = 0; - srp->username = NULL; srp->usernameSz = 0; + 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 (srp->side == SRP_CLIENT_SIDE) { - ret = SrpHashInit(&srp->specific.client.proof, type); - - if (ret == 0 && mp_init_multi(&srp->specific.client.a, - &srp->specific.client.A, - &srp->specific.client.B, - &srp->specific.client.x, - 0, 0) != MP_OKAY) - ret = MP_INIT_E; - } + 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 (srp->side == SRP_SERVER_SIDE) { - if (mp_init_multi(&srp->specific.server.b, - &srp->specific.server.B, - &srp->specific.server.A, - &srp->specific.server.v, 0, 0) != MP_OKAY) - ret = MP_INIT_E; - } + 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 (ret != 0) { + if (r != 0) { mp_clear(&srp->N); mp_clear(&srp->g); mp_clear(&srp->s); mp_clear(&srp->u); } - return ret; + return r; } -void wc_SrpTerm(Srp* srp) { +void wc_SrpTerm(Srp* srp) +{ if (srp) { mp_clear(&srp->N); mp_clear(&srp->g); mp_clear(&srp->s); mp_clear(&srp->u); XMEMSET(srp->salt, 0, srp->saltSz); XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); - XMEMSET(srp->username, 0, srp->usernameSz); - XFREE(srp->username, 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); - - XMEMSET(&srp->specific.client.proof, 0, sizeof(SrpHash)); } if (srp->side == SRP_SERVER_SIDE) { @@ -227,19 +213,22 @@ void wc_SrpTerm(Srp* srp) { mp_clear(&srp->specific.server.A); mp_clear(&srp->specific.server.v); } + + XMEMSET(srp, 0, sizeof(Srp)); } } -int wc_SrpSetUsername(Srp* srp, const char* username) { - if (!srp || !username) +int wc_SrpSetUsername(Srp* srp, const char* user) +{ + if (!srp || !user) return BAD_FUNC_ARG; - srp->username = (byte*)XMALLOC(XSTRLEN(username), NULL, DYNAMIC_TYPE_SRP); - if (srp->username == NULL) + srp->user = (byte*)XMALLOC(XSTRLEN(user), NULL, DYNAMIC_TYPE_SRP); + if (srp->user == NULL) return MEMORY_E; - srp->usernameSz = (word32) XSTRLEN(username); - XMEMCPY(srp->username, username, srp->usernameSz); + srp->userSz = (word32) XSTRLEN(user); + XMEMCPY(srp->user, user, srp->userSz); return 0; } @@ -249,28 +238,26 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, const byte* salt, word32 saltSz) { SrpHash hash; - int ret = 0; + byte digest1[SRP_MAX_DIGEST_SIZE]; + byte digest2[SRP_MAX_DIGEST_SIZE]; + int i, j, r; - if (!srp || !N || !g || !salt) + if (!srp || !srp->user || !N || !g || !salt) return BAD_FUNC_ARG; + /* Set N */ if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) return MP_READ_E; + /* Set g */ if (mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) return MP_READ_E; - if ((ret = SrpHashInit(&hash, srp->type)) != 0) - return ret; - - if ((ret = SrpHashUpdate(&hash, (byte*) N, nSz)) != 0) - return ret; - - if ((ret = SrpHashUpdate(&hash, (byte*) g, gSz)) != 0) - return ret; - - if ((ret = SrpHashFinal(&hash, srp->k)) != 0) - return ret; + /* Set salt */ + if (srp->salt) { + XMEMSET(srp->salt, 0, srp->saltSz); + XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); + } srp->salt = (byte*)XMALLOC(saltSz, NULL, DYNAMIC_TYPE_SRP); if (srp->salt == NULL) @@ -279,20 +266,101 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, XMEMCPY(srp->salt, salt, saltSz); srp->saltSz = saltSz; - return 0; + /* Set k = H(N, g) */ + r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); + if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); + if (!r) r = SrpHashFinal(&hash, srp->k); + + /* Update client proof */ + + /* digest1 = H(N) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); + if (!r) r = SrpHashFinal(&hash, digest1); + + /* digest2 = H(g) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); + if (!r) r = SrpHashFinal(&hash, digest2); + + /* digest1 = H(N) ^ H(g) */ + for (i = 0, j = SrpHashSize(srp->type); i < j; i++) + digest1[i] ^= digest2[i]; + + /* digest2 = H(user) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); + if (!r) r = SrpHashFinal(&hash, digest2); + + /* Client proof = H( H(N) ^ H(g) | H(user) | salt) */ + if (!r) r = SrpHashUpdate(&srp->client_proof, digest1, j); + if (!r) r = SrpHashUpdate(&srp->client_proof, digest2, j); + if (!r) r = SrpHashUpdate(&srp->client_proof, salt, saltSz); + + return r; } -int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) { +int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) +{ + SrpHash hash; byte digest[SRP_MAX_DIGEST_SIZE]; + int r; - if (!srp || !password || srp->side != SRP_CLIENT_SIDE) + if (!srp || !srp->user || !password || srp->side != SRP_CLIENT_SIDE) return BAD_FUNC_ARG; - (void) size; - /* TODO: calculate digest. */ + /* digest = H(username | ':' | password) */ + r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); + if (!r) r = SrpHashUpdate(&hash, (const byte*) ":", 1); + if (!r) r = SrpHashUpdate(&hash, password, size); + if (!r) r = SrpHashFinal(&hash, digest); - if (mp_read_unsigned_bin(&srp->specific.client.x, digest, + /* 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 = 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; + + XMEMSET(digest, 0, SRP_MAX_DIGEST_SIZE); + + return r; +} + +int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size) +{ + mp_int v; + int r; + + if (!srp || !verifier || !size || srp->side != SRP_CLIENT_SIDE) + return BAD_FUNC_ARG; + + 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 = (int)*size < 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(&srp->specific.server.v); + + mp_clear(&v); + + return r; +} + +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; diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index b75ac547a..b89733847 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -87,7 +87,6 @@ typedef struct { 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)) */ - SrpHash proof; /**< Client proof. Sent to Server. */ } SrpClient; typedef struct { @@ -105,10 +104,12 @@ typedef struct { mp_int s; /**< Session key. */ byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ mp_int u; /**< Random scrambling parameeter. */ - byte* username; /**< Username, login. */ - word32 usernameSz; /**< Username length. */ + byte* user; /**< Username, login. */ + word32 userSz; /**< Username length. */ byte* salt; /**< Small salt. */ word32 saltSz; /**< Salt length. */ + SrpHash client_proof; /**< Client proof. Sent to Server. */ + SrpHash server_proof; /**< Server proof. Sent to Client. */ union { SrpClient client; SrpServer server; @@ -126,6 +127,10 @@ WOLFSSL_API int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, WOLFSSL_API int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size); +WOLFSSL_API int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size); + +WOLFSSL_API int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size); + #ifdef __cplusplus } /* extern "C" */ #endif