diff --git a/tests/srp.c b/tests/srp.c index 4b8879b43..a2d59c829 100644 --- a/tests/srp.c +++ b/tests/srp.c @@ -30,55 +30,92 @@ #ifdef WOLFCRYPT_HAVE_SRP +static char username[] = "username"; + +static byte N[] = { + 0x00, 0xc0, 0x37, 0xc3, 0x75, 0x88, 0xb4, 0x32, 0x98, 0x87, 0xe6, 0x1c, + 0x2d, 0xa3, 0x32, 0x4b, 0x1b, 0xa4, 0xb8, 0x1a, 0x63, 0xf9, 0x74, 0x8f, + 0xed, 0x2d, 0x8a, 0x41, 0x0c, 0x2f, 0xc2, 0x1b, 0x12, 0x32, 0xf0, 0xd3, + 0xbf, 0xa0, 0x24, 0x27, 0x6c, 0xfd, 0x88, 0x44, 0x81, 0x97, 0xaa, 0xe4, + 0x86, 0xa6, 0x3b, 0xfc, 0xa7, 0xb8, 0xbf, 0x77, 0x54, 0xdf, 0xb3, 0x27, + 0xc7, 0x20, 0x1f, 0x6f, 0xd1, 0x7f, 0xd7, 0xfd, 0x74, 0x15, 0x8b, 0xd3, + 0x1c, 0xe7, 0x72, 0xc9, 0xf5, 0xf8, 0xab, 0x58, 0x45, 0x48, 0xa9, 0x9a, + 0x75, 0x9b, 0x5a, 0x2c, 0x05, 0x32, 0x16, 0x2b, 0x7b, 0x62, 0x18, 0xe8, + 0xf1, 0x42, 0xbc, 0xe2, 0xc3, 0x0d, 0x77, 0x84, 0x68, 0x9a, 0x48, 0x3e, + 0x09, 0x5e, 0x70, 0x16, 0x18, 0x43, 0x79, 0x13, 0xa8, 0xc3, 0x9c, 0x3d, + 0xd0, 0xd4, 0xca, 0x3c, 0x50, 0x0b, 0x88, 0x5f, 0xe3 +}; + +static byte g[] = { + 0x02 +}; + +static byte salt[] = { + 'r', 'a', 'n', 'd', 'o', 'm' +}; + static void test_SrpInit(void) { - byte N[] = { - 0x00, 0xc0, 0x37, 0xc3, 0x75, 0x88, 0xb4, 0x32, 0x98, 0x87, 0xe6, 0x1c, - 0x2d, 0xa3, 0x32, 0x4b, 0x1b, 0xa4, 0xb8, 0x1a, 0x63, 0xf9, 0x74, 0x8f, - 0xed, 0x2d, 0x8a, 0x41, 0x0c, 0x2f, 0xc2, 0x1b, 0x12, 0x32, 0xf0, 0xd3, - 0xbf, 0xa0, 0x24, 0x27, 0x6c, 0xfd, 0x88, 0x44, 0x81, 0x97, 0xaa, 0xe4, - 0x86, 0xa6, 0x3b, 0xfc, 0xa7, 0xb8, 0xbf, 0x77, 0x54, 0xdf, 0xb3, 0x27, - 0xc7, 0x20, 0x1f, 0x6f, 0xd1, 0x7f, 0xd7, 0xfd, 0x74, 0x15, 0x8b, 0xd3, - 0x1c, 0xe7, 0x72, 0xc9, 0xf5, 0xf8, 0xab, 0x58, 0x45, 0x48, 0xa9, 0x9a, - 0x75, 0x9b, 0x5a, 0x2c, 0x05, 0x32, 0x16, 0x2b, 0x7b, 0x62, 0x18, 0xe8, - 0xf1, 0x42, 0xbc, 0xe2, 0xc3, 0x0d, 0x77, 0x84, 0x68, 0x9a, 0x48, 0x3e, - 0x09, 0x5e, 0x70, 0x16, 0x18, 0x43, 0x79, 0x13, 0xa8, 0xc3, 0x9c, 0x3d, - 0xd0, 0xd4, 0xca, 0x3c, 0x50, 0x0b, 0x88, 0x5f, 0xe3 - }; - - byte g[] = { - 0x02 - }; - Srp srp; - AssertIntEQ(BAD_FUNC_ARG, - wc_SrpInit(NULL, SRP_TYPE_SHA, SRP_CLIENT_SIDE, N, sizeof(N), - g, sizeof(g))); + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(NULL, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, 255, SRP_CLIENT_SIDE)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, SRP_TYPE_SHA, 255 )); - AssertIntEQ(BAD_FUNC_ARG, - wc_SrpInit(&srp, 255, SRP_CLIENT_SIDE, N, sizeof(N), - g, sizeof(g))); + /* success */ + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); - AssertIntEQ(BAD_FUNC_ARG, - wc_SrpInit(&srp, SRP_TYPE_SHA, 255, N, sizeof(N), - g, sizeof(g))); + wc_SrpTerm(&srp); +} - AssertIntEQ(BAD_FUNC_ARG, - wc_SrpInit(&srp, SRP_TYPE_SHA, 255, N, sizeof(N), - g, sizeof(g))); +static void test_SrpSetUsername(void) +{ + Srp srp; - AssertIntEQ(BAD_FUNC_ARG, - wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE, NULL, sizeof(N), - g, sizeof(g))); + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); - AssertIntEQ(BAD_FUNC_ARG, - wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE, N, sizeof(N), - NULL, sizeof(g))); + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(NULL, username)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(&srp, NULL)); - AssertIntEQ(0, - wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE, N, sizeof(N), - g, sizeof(g))); + /* success */ + AssertIntEQ(0, wc_SrpSetUsername(&srp, username)); + AssertIntEQ((int) XSTRLEN(username), srp.usernameSz); + AssertIntEQ(0, XMEMCMP(srp.username, username, srp.usernameSz)); + + wc_SrpTerm(&srp); +} + +static void test_SrpSetParams(void) +{ + Srp srp; + + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(NULL, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(&srp, NULL, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(&srp, N, sizeof(N), + NULL, sizeof(g), + salt, sizeof(salt))); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(&srp, N, sizeof(N), + g, sizeof(g), + NULL, sizeof(salt))); + + /* success */ + AssertIntEQ(0, wc_SrpSetParams(&srp, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + + AssertIntEQ(sizeof(salt), srp.saltSz); + AssertIntEQ(0, XMEMCMP(srp.salt, salt, srp.saltSz)); + + wc_SrpTerm(&srp); } #endif @@ -87,5 +124,7 @@ void SrpTest(void) { #ifdef WOLFCRYPT_HAVE_SRP test_SrpInit(); + test_SrpSetUsername(); + test_SrpSetParams(); #endif } diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 19862ae66..780044017 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -111,39 +111,137 @@ static int SrpHashFinal(Srp* srp, byte* digest) } } -int wc_SrpInit(Srp* srp, byte type, byte side, byte* N, word32 nSz, - byte* g, word32 gSz) +int wc_SrpInit(Srp* srp, byte type, byte side) { int ret = 0; - if (!srp || !N || !g) + if (!srp) return BAD_FUNC_ARG; if (side != SRP_CLIENT_SIDE && side != SRP_SERVER_SIDE) return BAD_FUNC_ARG; - srp->side = side; - srp->type = type; /* a valid type is checked inside SrpHashXXX functions. */ + if (type != SRP_TYPE_SHA && type != SRP_TYPE_SHA256 && + type != SRP_TYPE_SHA384 && type != SRP_TYPE_SHA512) + return BAD_FUNC_ARG; - if (mp_init_multi(&srp->N, &srp->g, &srp->s, 0, 0, 0) != MP_OKAY) + srp->side = side; srp->type = type; + srp->salt = NULL; srp->saltSz = 0; + srp->username = NULL; srp->usernameSz = 0; + + if (mp_init_multi(&srp->N, &srp->g, &srp->s, &srp->u, 0, 0) != MP_OKAY) return MP_INIT_E; - if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) - ret = MP_READ_E; - - if (ret == 0 && mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) - ret = MP_READ_E; - - if (ret == 0) ret = SrpHashInit(srp); - if (ret == 0) ret = SrpHashUpdate(srp, N, nSz); - if (ret == 0) ret = SrpHashUpdate(srp, g, gSz); - if (ret == 0) ret = SrpHashFinal(srp, srp->k); + if (srp->side == SRP_CLIENT_SIDE) { + if (mp_init_multi(&srp->specific.client.a, + &srp->specific.client.A, + &srp->specific.client.B, + &srp->specific.client.password, 0, 0) != MP_OKAY) + ret = MP_INIT_E; + } + else { + if (mp_init_multi(&srp->specific.server.b, + &srp->specific.server.B, + &srp->specific.server.A, + &srp->specific.server.verifier, 0, 0) != MP_OKAY) + ret = MP_INIT_E; + } if (ret != 0) { - mp_clear(&srp->N); mp_clear(&srp->g); mp_clear(&srp->s); + mp_clear(&srp->N); mp_clear(&srp->g); + mp_clear(&srp->s); mp_clear(&srp->u); } return ret; } +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); + + 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.password); + + XMEMSET(srp->specific.client.x, 0, SRP_MAX_DIGEST_SIZE); + } + else { + mp_clear(&srp->specific.server.b); + mp_clear(&srp->specific.server.B); + mp_clear(&srp->specific.server.A); + mp_clear(&srp->specific.server.verifier); + } + } +} + +int wc_SrpSetUsername(Srp* srp, const char* username) { + if (!srp || !username) + return BAD_FUNC_ARG; + + srp->username = (byte*)XMALLOC(XSTRLEN(username), NULL, DYNAMIC_TYPE_SRP); + if (srp->username == NULL) + return MEMORY_E; + + srp->usernameSz = (word32) XSTRLEN(username); + XMEMCPY(srp->username, username, srp->usernameSz); + + return 0; +} + +int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, + const byte* g, word32 gSz, + const byte* salt, word32 saltSz) +{ + int ret = 0; + + if (!srp || !N || !g || !salt) + return BAD_FUNC_ARG; + + if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) + return MP_READ_E; + + if (mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) + return MP_READ_E; + + if ((ret = SrpHashInit(srp)) != 0) + return ret; + + if ((ret = SrpHashUpdate(srp, (byte*) N, nSz)) != 0) + return ret; + + if ((ret = SrpHashUpdate(srp, (byte*) g, gSz)) != 0) + return ret; + + if ((ret = SrpHashFinal(srp, srp->k)) != 0) + return ret; + + srp->salt = (byte*)XMALLOC(saltSz, NULL, DYNAMIC_TYPE_SRP); + if (srp->salt == NULL) + return MEMORY_E; + + XMEMCPY(srp->salt, salt, saltSz); + srp->saltSz = saltSz; + + return 0; +} + +int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) { + if (!srp || !password || srp->side != SRP_CLIENT_SIDE) + return BAD_FUNC_ARG; + + if (mp_read_unsigned_bin(&srp->specific.client.password, password, size) + != MP_OKAY) + return MP_READ_E; + + return 0; +} + #endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index b4ac77895..f79042b83 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -84,27 +84,26 @@ typedef struct { mp_int A; /**< Public ephemeral value. pow(g, a, N) */ mp_int B; /**< Server's public ephemeral value. */ byte x[SRP_MAX_DIGEST_SIZE]; /**< Priv key. H(salt, H(user, ":", pswd)) */ - byte* pswd; /**< Password. */ - word32 pswdSz; /**< Password length. */ + mp_int password; /**< Password. */ } 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) */ + mp_int verifier; /**< 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) */ - byte u[SRP_MAX_DIGEST_SIZE]; /**< Random scrambling parameeter. */ - byte type; /**< Hash type, SHA[1:256:384:512] */ - byte side; /**< Client or Server side. */ - byte* user; /**< Username, login. */ - word32 userSz; /**< Username length. */ + mp_int u; /**< Random scrambling parameeter. */ + byte* username; /**< Username, login. */ + word32 usernameSz; /**< Username length. */ byte* salt; /**< Small salt. */ word32 saltSz; /**< Salt length. */ union { @@ -114,8 +113,16 @@ typedef struct { SrpHash hash; /**< Hash object. */ } Srp; -WOLFSSL_API int wc_SrpInit(Srp* srp, byte type, byte side, byte* N, word32 nSz, - byte* g, word32 gSz); +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 char* user); + +WOLFSSL_API int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, + const byte* g, word32 gSz, + const byte* salt, word32 saltSz); + +WOLFSSL_API int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 795d2c9c5..060ed0239 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -271,7 +271,8 @@ DYNAMIC_TYPE_TLSX = 43, DYNAMIC_TYPE_OCSP = 44, DYNAMIC_TYPE_SIGNATURE = 45, - DYNAMIC_TYPE_HASHES = 46 + DYNAMIC_TYPE_HASHES = 46, + DYNAMIC_TYPE_SRP = 47, }; /* max error buffer string size */