diff --git a/tests/srp.c b/tests/srp.c index 02e97d0f4..0e3af9c4a 100644 --- a/tests/srp.c +++ b/tests/srp.c @@ -99,6 +99,16 @@ static byte key[] = { 0x13, 0x6C, 0x88, 0x55 }; +static byte client_proof[] = { + 0x0D, 0x49, 0xE1, 0x9C, 0x3A, 0x88, 0x43, 0x15, 0x45, 0xA8, 0xAC, 0xAB, + 0xEA, 0x15, 0x1A, 0xEE, 0xF9, 0x38, 0x4D, 0x21 +}; + +static byte server_proof[] = { + 0xBD, 0xB1, 0x20, 0x70, 0x46, 0xC9, 0xD6, 0xCC, 0xE2, 0x1D, 0x75, 0xA2, + 0xD0, 0xAF, 0xC5, 0xBC, 0xAE, 0x12, 0xFC, 0x75 +}; + static void test_SrpInit(void) { Srp srp; @@ -345,6 +355,77 @@ static void test_SrpComputeKey(void) wc_SrpTerm(&srv); } +static void test_SrpGetProofAndVerify(void) +{ + Srp cli, srv; + byte clientPubKey[64]; + byte serverPubKey[64]; + word32 clientPubKeySz = 64; + word32 serverPubKeySz = 64; + byte clientProof[SRP_MAX_DIGEST_SIZE]; + byte serverProof[SRP_MAX_DIGEST_SIZE]; + word32 clientProofSz = SRP_MAX_DIGEST_SIZE; + word32 serverProofSz = SRP_MAX_DIGEST_SIZE; + + AssertIntEQ(0, wc_SrpInit(&cli, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + AssertIntEQ(0, wc_SrpInit(&srv, SRP_TYPE_SHA, SRP_SERVER_SIDE)); + + AssertIntEQ(0, wc_SrpSetUsername(&cli, username, usernameSz)); + AssertIntEQ(0, wc_SrpSetUsername(&srv, username, usernameSz)); + + AssertIntEQ(0, wc_SrpSetParams(&cli, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + AssertIntEQ(0, wc_SrpSetParams(&srv, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + + AssertIntEQ(0, wc_SrpSetPassword(&cli, password, passwordSz)); + AssertIntEQ(0, wc_SrpSetVerifier(&srv, verifier, sizeof(verifier))); + + AssertIntEQ(0, wc_SrpSetPrivate(&cli, a, sizeof(a))); + AssertIntEQ(0, wc_SrpGetPublic(&cli, clientPubKey, &clientPubKeySz)); + AssertIntEQ(0, XMEMCMP(clientPubKey, A, clientPubKeySz)); + + AssertIntEQ(0, wc_SrpSetPrivate(&srv, b, sizeof(b))); + AssertIntEQ(0, wc_SrpGetPublic(&srv, serverPubKey, &serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(serverPubKey, B, serverPubKeySz)); + + AssertIntEQ(0, wc_SrpComputeKey(&cli, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(cli.key, key, sizeof(key))); + + AssertIntEQ(0, wc_SrpComputeKey(&srv, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(srv.key, key, sizeof(key))); + + /* invalid params */ + serverProofSz = 0; + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetProof(NULL, clientProof,&clientProofSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetProof(&cli, NULL, &clientProofSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetProof(&cli, clientProof,NULL)); + AssertIntEQ(BUFFER_E, wc_SrpGetProof(&srv, serverProof,&serverProofSz)); + + AssertIntEQ(BAD_FUNC_ARG, + wc_SrpVerifyPeersProof(NULL, clientProof, clientProofSz)); + AssertIntEQ(BAD_FUNC_ARG, + wc_SrpVerifyPeersProof(&cli, NULL, clientProofSz)); + AssertIntEQ(BUFFER_E, + wc_SrpVerifyPeersProof(&srv, serverProof, serverProofSz)); + serverProofSz = SRP_MAX_DIGEST_SIZE; + + /* success */ + AssertIntEQ(0, wc_SrpGetProof(&cli, clientProof, &clientProofSz)); + AssertIntEQ(0, XMEMCMP(clientProof, client_proof, sizeof(client_proof))); + AssertIntEQ(0, wc_SrpVerifyPeersProof(&srv, clientProof, clientProofSz)); + AssertIntEQ(0, wc_SrpGetProof(&srv, serverProof, &serverProofSz)); + AssertIntEQ(0, XMEMCMP(serverProof, server_proof, sizeof(server_proof))); + AssertIntEQ(0, wc_SrpVerifyPeersProof(&cli, serverProof, serverProofSz)); + + wc_SrpTerm(&cli); + wc_SrpTerm(&srv); +} + #endif void SrpTest(void) @@ -356,5 +437,6 @@ void SrpTest(void) test_SrpSetPassword(); test_SrpGetPublic(); test_SrpComputeKey(); + test_SrpGetProofAndVerify(); #endif } diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index a41c43109..95881b9c9 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -163,6 +163,8 @@ int wc_SrpInit(Srp* srp, byte type, byte side) /* initializing variables */ + XMEMSET(srp, 0, sizeof(Srp)); + if ((r = SrpHashInit(&srp->client_proof, type)) != 0) return r; @@ -498,11 +500,11 @@ static int wc_SrpSetK(Srp* srp, byte* secret, word32 size) return r; } -WOLFSSL_API int wc_SrpComputeKey(Srp* srp, - byte* clientPubKey, word32 clientPubKeySz, - byte* serverPubKey, word32 serverPubKeySz) +int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, + byte* serverPubKey, word32 serverPubKeySz) { byte* secret; + word32 digestSz; word32 secretSz; mp_int i, j, s; int r; @@ -524,12 +526,14 @@ WOLFSSL_API int wc_SrpComputeKey(Srp* srp, return MEMORY_E; } + digestSz = SrpHashSize(srp->type); + r = wc_SrpSetU(srp, clientPubKey, clientPubKeySz, serverPubKey, serverPubKeySz); if (!r && srp->side == SRP_CLIENT_SIDE) { /* i = B - k * v */ - r = mp_read_unsigned_bin(&i, srp->k, SrpHashSize(srp->type)); + r = mp_read_unsigned_bin(&i, srp->k, digestSz); if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &j); if (!r) r = mp_mulmod(&i, &j, &srp->N, &s); if (!r) r = mp_read_unsigned_bin(&j, serverPubKey, serverPubKeySz); @@ -558,7 +562,7 @@ WOLFSSL_API int wc_SrpComputeKey(Srp* srp, if (!r) r = wc_SrpSetK(srp, secret, mp_unsigned_bin_size(&s)); /* client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */ - if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, sizeof(srp->key)); + if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, digestSz * 2); XFREE(secret, NULL, DYNAMIC_TYPE_SRP); mp_clear(&i); mp_clear(&j); mp_clear(&s); @@ -566,4 +570,56 @@ WOLFSSL_API int wc_SrpComputeKey(Srp* srp, return r; } +int wc_SrpGetProof(Srp* srp, byte* proof, word32* size) +{ + int r; + + if (!srp || !proof || !size) + return BAD_FUNC_ARG; + + if (*size < SrpHashSize(srp->type)) + return BUFFER_E; + + if ((r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE + ? &srp->client_proof + : &srp->server_proof, proof)) != 0) + return r; + + *size = SrpHashSize(srp->type); + + if (srp->side == SRP_CLIENT_SIDE) { + /* server proof = H( A | client proof | K) */ + if (!r) r = SrpHashUpdate(&srp->server_proof, proof, *size); + if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, (*size) * 2); + } + + return r; +} + +int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size) +{ + byte digest[SRP_MAX_DIGEST_SIZE]; + int r; + + if (!srp || !proof) + return BAD_FUNC_ARG; + + if (size != SrpHashSize(srp->type)) + return BUFFER_E; + + r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE ? &srp->server_proof + : &srp->client_proof, digest); + + if (srp->side == SRP_SERVER_SIDE) { + /* server proof = H( A | client proof | K) */ + if (!r) r = SrpHashUpdate(&srp->server_proof, proof, size); + if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, size * 2); + } + + if (!r && XMEMCMP(proof, digest, size) != 0) + r = SRP_VERIFY_E; + + return r; +} + #endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 31847de9c..84714e462 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -152,6 +152,7 @@ enum { ECC_PRIV_KEY_E = -216, /* ECC private key not valid error */ SRP_CALL_ORDER_E = -217, /* SRP function called in the wrong order. */ + SRP_VERIFY_E = -218, /* SRP proof verification failed. */ MIN_CODE_E = -300 /* errors -101 - -299 */ }; diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index 9b76de8b4..56cf41329 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -123,6 +123,10 @@ WOLFSSL_API int wc_SrpGetPublic(Srp* srp, byte* public, word32* size); WOLFSSL_API int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, byte* serverPubKey, word32 serverPubKeySz); +WOLFSSL_API int wc_SrpGetProof(Srp* srp, byte* proof, word32* size); + +WOLFSSL_API int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size); + #ifdef __cplusplus } /* extern "C" */ #endif