Files
wolfssl/tests/api/test_srp.c
T
Daniele Lacamera 45a98467e4 tests: MC/DC decision coverage for remaining wolfCrypt primitives
Add DecisionCoverage/FeatureCoverage tests and tests/unit-mcdc white-box
supplements for the remaining reachable wolfCrypt primitive sources in the
ISO 26262 per-module MC/DC campaign (excluding asn* and the EVP/OpenSSL
compat layer, which are out of the MC/DC boundary).

tests/api:
- legacy ciphers / digests: des3, camellia, ascon, blake2, siphash
- niche PK: srp, eccsi, sakke, hpke
- native PQC KEM: frodokem
- math: wolfmath

tests/unit-mcdc white-box drivers (#include the .c to reach file-static
helpers and impl-selected paths, standalone main()/WB_NOTE harness):
- blake2b, blake2s
- eccsi, sakke, hpke
- SP host backends: sp_x86_64, sp_c64, sp_c32
- infra: cryptocb (dev && dev->cb dispatch three-vector, 127/127),
  logging (per-thread + global error-queue impls, 19/19),
  memory (static-pool allocator, 46/48)

Registrations in tests/api.c, tests/api/include.am and CMakeLists.txt.
2026-07-31 12:56:51 +02:00

907 lines
37 KiB
C

/* test_srp.c
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <tests/unit.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/wolfcrypt/srp.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <tests/api/api.h>
#include <tests/api/test_srp.h>
#if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256)
/* RFC 5054-style 1024-bit test group: small enough to build under every
* math backend/configuration while comfortably exceeding
* SRP_MODULUS_MIN_BITS (512). Generator is 2, as in wolfcrypt/test/test.c's
* srp_test_digest(). */
static const byte srpN[] = {
0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6,
0x9C, 0x33, 0xF8, 0x0A, 0xFA, 0x8F, 0xC5, 0xE8,
0x60, 0x72, 0x61, 0x87, 0x75, 0xFF, 0x3C, 0x0B,
0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76,
0xD6, 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3,
0x38, 0x3B, 0x48, 0x13, 0xD6, 0x92, 0xC6, 0xE0,
0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B, 0xE4,
0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1,
0x5D, 0xC7, 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6,
0xCE, 0x8E, 0xF4, 0xAD, 0x69, 0xB1, 0x5D, 0x49,
0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85,
0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC,
0x68, 0xED, 0xBC, 0x3C, 0x05, 0x72, 0x6C, 0xC0,
0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E, 0xAA, 0x9A,
0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B,
0x9F, 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3
};
static const byte srpG[] = { 0x02 };
static const byte srpSalt[] = {
0xBE, 0xB2, 0x53, 0x79, 0xD1, 0xA8, 0x58, 0x1E,
0xB5, 0xA7
};
static const byte srpUser[] = "user";
static const byte srpPass[] = "password";
#define SRP_N_SZ ((word32)sizeof(srpN))
#define SRP_USER_SZ ((word32)4)
#define SRP_PASS_SZ ((word32)8)
#define SRP_SALT_SZ ((word32)sizeof(srpSalt))
#endif /* WOLFCRYPT_HAVE_SRP && !NO_SHA256 */
/*
* MC/DC: argument/state-validation decisions in wolfcrypt/src/srp.c.
*
* wc_SrpInit()/wc_SrpInit_ex() (srp.c:214-293; wc_SrpInit() is a thin
* wrapper that forwards to wc_SrpInit_ex(), so exercising it through
* wc_SrpInit() covers the same decisions):
* srp.c:220-221 !srp -> BAD_FUNC_ARG
* srp.c:223-224 side != SRP_CLIENT_SIDE && side != SRP_SERVER_SIDE
* -> BAD_FUNC_ARG
* c0 = side != CLIENT, c1 = side != SERVER. Only 3 value
* classes exist (CLIENT/SERVER/invalid); side=CLIENT
* (c0=F,c1=T) vs side=invalid (c0=T,c1=T) isolates c0
* (c1 held true); side=SERVER (c0=T,c1=F) vs side=invalid
* isolates c1 (c0 held true).
* srp.c:226-257 switch(type) default -> BAD_FUNC_ARG
*
* wc_SrpTerm() (srp.c:300-322):
* srp.c:302 if (srp) -- NULL is a legitimate no-op.
*
* wc_SrpSetUsername() (srp.c:324-339):
* srp.c:326-327 !srp || !username -> BAD_FUNC_ARG
*
* wc_SrpSetParams() (srp.c:341-434):
* srp.c:353-354 !srp || !N || !g || !salt || (nSz < gSz) -> BAD_FUNC_ARG
* srp.c:356-357 !srp->user -> SRP_CALL_ORDER_E
* srp.c:359-361 hashSize < 0 -> return hashSize (ALGO_ID_E)
* srp.c:367-368 mp_count_bits(N) < SRP_MODULUS_MIN_BITS -> BAD_FUNC_ARG
* srp.c:374-375 mp_cmp(N, g) != MP_GT -> BAD_FUNC_ARG
* srp.c:378-383 if (srp->salt) -- re-set/free-then-realloc branch
* srp.c:364-365 and 371-372 (mp_read_unsigned_bin() != MP_OKAY ->
* MP_READ_E for N and g) are NOT exercised: with a
* properly-sized byte buffer this call effectively cannot
* fail through the public API; forcing it needs a
* build-specific oversized N/g tuned past the compiled
* math backend's limit (SP_INT_BITS/FP_MAX_BITS), or a
* whitebox mock of mp_read_unsigned_bin().
*
* wc_SrpSetPassword() (srp.c:436-474):
* srp.c:443-444 !srp || !password || side != CLIENT -> BAD_FUNC_ARG
* srp.c:446-447 !srp->salt -> SRP_CALL_ORDER_E
* srp.c:449-451 digestSz < 0 -> return digestSz (ALGO_ID_E)
*
* wc_SrpGetVerifier() (srp.c:476-505):
* srp.c:481-482 !srp || !verifier || !size || side != CLIENT
* -> BAD_FUNC_ARG
* srp.c:484-485 mp_iszero(auth) == MP_YES -> SRP_CALL_ORDER_E
* srp.c:497 *size < verifier size -> BUFFER_E
*
* wc_SrpSetVerifier() (srp.c:507-513):
* srp.c:509 !srp || !verifier || side != SERVER -> BAD_FUNC_ARG
*
* wc_SrpSetPrivate() (srp.c:515-542):
* srp.c:520-521 !srp || !priv || !size -> BAD_FUNC_ARG
* srp.c:523-524 mp_iszero(auth) == MP_YES -> SRP_CALL_ORDER_E
* srp.c:536 mp_iszero(priv mod N) == MP_YES -> SRP_BAD_KEY_E
*
* wc_SrpGetPublic() (srp.c:561-647):
* srp.c:568-569 !srp || !pub || !size -> BAD_FUNC_ARG
* srp.c:571-573 hashSize < 0 -> return hashSize (ALGO_ID_E)
* srp.c:575-576 mp_iszero(auth) == MP_YES -> SRP_CALL_ORDER_E
* srp.c:579-580 *size < modulus size -> BUFFER_E
* srp.c:595/599 client-side vs server-side branch
* srp.c:616 server-side: mp_iszero(k-as-int) == MP_YES
* -> SRP_BAD_KEY_E (forced by zeroing the public srp->k
* field directly, then restored via a fresh
* wc_SrpSetParams() call to exercise the false side)
*
* wc_SrpComputeKey() (srp.c:703-951):
* srp.c:727-728 !srp || !clientPubKey || clientPubKeySz==0 ||
* !serverPubKey || serverPubKeySz==0 -> BAD_FUNC_ARG
* srp.c:756-758 mp_iszero(priv) == MP_YES -> SRP_CALL_ORDER_E
* srp.c:775-778 secretSz < clientPubKeySz || secretSz < serverPubKeySz
* -> BAD_FUNC_ARG
* client-side (srp.c:814-849):
* srp.c:819-822 mp_iszero(k-as-int) == MP_YES -> SRP_BAD_KEY_E
* srp.c:829-832 mp_iszero(serverPubKey-as-int) == MP_YES
* -> SRP_BAD_KEY_E
* srp.c:833-836 serverPubKey >= N -> SRP_BAD_KEY_E
* server-side (srp.c:850-886):
* srp.c:858-861 mp_iszero(clientPubKey-as-int) == MP_YES
* -> SRP_BAD_KEY_E
* srp.c:862-865 clientPubKey >= N -> SRP_BAD_KEY_E
* srp.c:872-875 and 878-881 (temp2 <= 1, temp2 == N-1 -> SRP_BAD_KEY_E)
* are NOT exercised: temp2 = A * v^u % N is a live modular
* arithmetic result, so landing it on 0/1/N-1 needs a
* clientPubKey solved against the concrete v/u/N values in
* play, not a fixed byte pattern; a whitebox able to drive
* the same modmath (or mock mp_mulmod/mp_exptmod) would be
* needed to hit these two directly.
*
* wc_SrpGetProof() (srp.c:953-982):
* srp.c:958-959 !srp || !proof || !size -> BAD_FUNC_ARG
* srp.c:961-963 hashSize < 0 -> ALGO_ID_E
* srp.c:965-966 *size < hashSize -> BUFFER_E
* srp.c:968-970/975 client-side vs server-side branch
*
* wc_SrpVerifyPeersProof() (srp.c:984-1015):
* srp.c:990-991 !srp || !proof -> BAD_FUNC_ARG
* srp.c:993-995 hashSize < 0 -> ALGO_ID_E
* srp.c:997-998 size != hashSize || size > INT_MAX -> BUFFER_E
* The second operand cannot be exercised independently:
* whenever size == hashSize is false, hashSize is one of
* the small fixed digest sizes, so "size > INT_MAX" can
* never simultaneously be true in a way that changes the
* outcome -- this half of the decision is structurally
* masked through the public API, not merely untested.
* srp.c:1000-1001/1003 client-side vs server-side branch
* srp.c:1009 ConstantCompare(proof, digest) != 0 -> SRP_VERIFY_E
* (the mismatch direction is covered here; the matching
* direction is exercised, along with the full handshake,
* in test_wc_Srp_FeatureCoverage())
*/
int test_wc_Srp_DecisionCoverage(void)
{
EXPECT_DECLS;
#ifdef WOLFCRYPT_HAVE_SRP
#ifndef NO_SHA256
Srp srp;
XMEMSET(&srp, 0, sizeof(srp));
/* --- wc_SrpInit() / wc_SrpInit_ex() --- */
/* c0: !srp (srp.c:220-221) */
ExpectIntEQ(wc_SrpInit(NULL, SRP_TYPE_SHA256, SRP_CLIENT_SIDE),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* side guard (srp.c:223-224): see the header comment above for the
* 3-way (CLIENT/SERVER/invalid) independence-pair reasoning. */
ExpectIntEQ(wc_SrpInit(&srp, SRP_TYPE_SHA256, SRP_CLIENT_SIDE), 0);
wc_SrpTerm(&srp);
ExpectIntEQ(wc_SrpInit(&srp, SRP_TYPE_SHA256, SRP_SERVER_SIDE), 0);
wc_SrpTerm(&srp);
ExpectIntEQ(wc_SrpInit(&srp, SRP_TYPE_SHA256, (SrpSide)99),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* type switch default (srp.c:255-256): SRP_TYPE_SHA256 above already
* exercises a recognized case; an out-of-range type falls to
* default. */
ExpectIntEQ(wc_SrpInit(&srp, (SrpType)0, SRP_CLIENT_SIDE),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* --- wc_SrpTerm() --- */
/* srp.c:302: NULL is a legitimate silent no-op. */
wc_SrpTerm(NULL);
ExpectIntEQ(wc_SrpInit(&srp, SRP_TYPE_SHA256, SRP_CLIENT_SIDE), 0);
wc_SrpTerm(&srp); /* true branch: valid pointer, resources released. */
/* --- wc_SrpSetUsername() --- */
ExpectIntEQ(wc_SrpInit(&srp, SRP_TYPE_SHA256, SRP_CLIENT_SIDE), 0);
/* c0: !srp (srp.c:326) */
ExpectIntEQ(wc_SrpSetUsername(NULL, srpUser, SRP_USER_SZ),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c1: !username, c0 false */
ExpectIntEQ(wc_SrpSetUsername(&srp, NULL, SRP_USER_SZ),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* baseline: both valid -> success */
ExpectIntEQ(wc_SrpSetUsername(&srp, srpUser, SRP_USER_SZ), 0);
/* --- wc_SrpSetParams() --- */
/* Top guard (srp.c:353-354): isolate each operand true individually
* against the all-false baseline established further below. */
ExpectIntEQ(wc_SrpSetParams(NULL, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ),
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* c0: !srp */
ExpectIntEQ(wc_SrpSetParams(&srp, NULL, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ),
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* c1: !N */
ExpectIntEQ(wc_SrpSetParams(&srp, srpN, SRP_N_SZ, NULL,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ),
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* c2: !g */
ExpectIntEQ(wc_SrpSetParams(&srp, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), NULL, SRP_SALT_SZ),
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* c3: !salt */
/* c4: nSz < gSz -- swap which buffer plays N vs g so nSz(1) < gSz(128)
* while both pointers remain valid. */
ExpectIntEQ(wc_SrpSetParams(&srp, srpG, (word32)sizeof(srpG), srpN,
SRP_N_SZ, srpSalt, SRP_SALT_SZ), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* !srp->user -> SRP_CALL_ORDER_E (srp.c:356-357): top guard all
* false, but SetUsername was never called on this fresh instance. */
{
Srp srpNoUser;
XMEMSET(&srpNoUser, 0, sizeof(srpNoUser));
ExpectIntEQ(wc_SrpInit(&srpNoUser, SRP_TYPE_SHA256,
SRP_CLIENT_SIDE), 0);
ExpectIntEQ(wc_SrpSetParams(&srpNoUser, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ),
WC_NO_ERR_TRACE(SRP_CALL_ORDER_E));
wc_SrpTerm(&srpNoUser);
}
/* hashSize < 0 -> ALGO_ID_E (srp.c:359-361): corrupt srp->type to an
* unrecognized value right after SetUsername succeeds, so
* SrpHashSize() falls to its default case. */
srp.type = (SrpType)0;
ExpectIntEQ(wc_SrpSetParams(&srp, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ),
WC_NO_ERR_TRACE(ALGO_ID_E));
srp.type = SRP_TYPE_SHA256;
/* modulus-too-small -> BAD_FUNC_ARG (srp.c:367-368): N with far fewer
* than SRP_MODULUS_MIN_BITS (512) bits. */
ExpectIntEQ(wc_SrpSetParams(&srp, srpG, (word32)sizeof(srpG), srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* g >= N -> BAD_FUNC_ARG (srp.c:374-375): valid-size N, but g == N so
* mp_cmp() yields MP_EQ, not MP_GT. */
ExpectIntEQ(wc_SrpSetParams(&srp, srpN, SRP_N_SZ, srpN, SRP_N_SZ,
srpSalt, SRP_SALT_SZ), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* Baseline + salt re-set branch (srp.c:378-383): first call finds
* srp->salt NULL (false branch, first allocation); the second call on
* the same instance finds a previously-allocated salt (true branch,
* freed then re-allocated). Both calls also complete the top guard,
* call-order, hashSize, bits and cmp checks with every operand false,
* establishing their all-false baseline. */
ExpectIntEQ(wc_SrpSetParams(&srp, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ), 0);
ExpectIntEQ(wc_SrpSetParams(&srp, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ), 0);
wc_SrpTerm(&srp);
/* --- wc_SrpSetPassword() --- */
{
Srp cli;
Srp srv;
XMEMSET(&cli, 0, sizeof(cli));
XMEMSET(&srv, 0, sizeof(srv));
/* c0: !srp (srp.c:443) */
ExpectIntEQ(wc_SrpSetPassword(NULL, srpPass, SRP_PASS_SZ),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_SrpInit(&cli, SRP_TYPE_SHA256, SRP_CLIENT_SIDE), 0);
ExpectIntEQ(wc_SrpSetUsername(&cli, srpUser, SRP_USER_SZ), 0);
/* c1: !password, c0/c2 false */
ExpectIntEQ(wc_SrpSetPassword(&cli, NULL, SRP_PASS_SZ),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c2: side != CLIENT, c0/c1 false (use a server-side instance;
* this guard runs before any call-order check). */
ExpectIntEQ(wc_SrpInit(&srv, SRP_TYPE_SHA256, SRP_SERVER_SIDE), 0);
ExpectIntEQ(wc_SrpSetUsername(&srv, srpUser, SRP_USER_SZ), 0);
ExpectIntEQ(wc_SrpSetPassword(&srv, srpPass, SRP_PASS_SZ),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* !srp->salt -> SRP_CALL_ORDER_E (srp.c:446-447): top guard all
* false, but SetParams not yet called. */
ExpectIntEQ(wc_SrpSetPassword(&cli, srpPass, SRP_PASS_SZ),
WC_NO_ERR_TRACE(SRP_CALL_ORDER_E));
ExpectIntEQ(wc_SrpSetParams(&cli, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ), 0);
/* digestSz < 0 -> ALGO_ID_E (srp.c:449-451) */
cli.type = (SrpType)0;
ExpectIntEQ(wc_SrpSetPassword(&cli, srpPass, SRP_PASS_SZ),
WC_NO_ERR_TRACE(ALGO_ID_E));
cli.type = SRP_TYPE_SHA256;
/* baseline: all guards false, salt set, valid type -> success. */
ExpectIntEQ(wc_SrpSetPassword(&cli, srpPass, SRP_PASS_SZ), 0);
wc_SrpTerm(&cli);
wc_SrpTerm(&srv);
}
/* --- wc_SrpSetVerifier() --- */
{
Srp cli;
Srp srv;
XMEMSET(&cli, 0, sizeof(cli));
XMEMSET(&srv, 0, sizeof(srv));
ExpectIntEQ(wc_SrpInit(&cli, SRP_TYPE_SHA256, SRP_CLIENT_SIDE), 0);
ExpectIntEQ(wc_SrpInit(&srv, SRP_TYPE_SHA256, SRP_SERVER_SIDE), 0);
/* c0: !srp (srp.c:509) */
ExpectIntEQ(wc_SrpSetVerifier(NULL, srpG, (word32)sizeof(srpG)),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c1: !verifier, c0/c2 false (server side) */
ExpectIntEQ(wc_SrpSetVerifier(&srv, NULL, (word32)sizeof(srpG)),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c2: side != SERVER, c0/c1 false (client side) */
ExpectIntEQ(wc_SrpSetVerifier(&cli, srpG, (word32)sizeof(srpG)),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* baseline: all false -> success */
ExpectIntEQ(wc_SrpSetVerifier(&srv, srpG, (word32)sizeof(srpG)), 0);
wc_SrpTerm(&cli);
wc_SrpTerm(&srv);
}
/* --- wc_SrpGetVerifier() --- */
{
Srp cli;
Srp srv;
byte verifier[SRP_N_SZ];
word32 vSz;
XMEMSET(&cli, 0, sizeof(cli));
XMEMSET(&srv, 0, sizeof(srv));
XMEMSET(verifier, 0, sizeof(verifier));
ExpectIntEQ(wc_SrpInit(&cli, SRP_TYPE_SHA256, SRP_CLIENT_SIDE), 0);
ExpectIntEQ(wc_SrpInit(&srv, SRP_TYPE_SHA256, SRP_SERVER_SIDE), 0);
vSz = SRP_N_SZ;
/* c0: !srp (srp.c:481) */
ExpectIntEQ(wc_SrpGetVerifier(NULL, verifier, &vSz),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c1: !verifier */
ExpectIntEQ(wc_SrpGetVerifier(&cli, NULL, &vSz),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c2: !size */
ExpectIntEQ(wc_SrpGetVerifier(&cli, verifier, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c3: side != CLIENT (server side) */
vSz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetVerifier(&srv, verifier, &vSz),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* auth == 0 -> SRP_CALL_ORDER_E (srp.c:484-485): client side,
* before SetPassword. */
vSz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetVerifier(&cli, verifier, &vSz),
WC_NO_ERR_TRACE(SRP_CALL_ORDER_E));
ExpectIntEQ(wc_SrpSetUsername(&cli, srpUser, SRP_USER_SZ), 0);
ExpectIntEQ(wc_SrpSetParams(&cli, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ), 0);
ExpectIntEQ(wc_SrpSetPassword(&cli, srpPass, SRP_PASS_SZ), 0);
/* buffer too small -> BUFFER_E (srp.c:497) */
vSz = 1;
ExpectIntEQ(wc_SrpGetVerifier(&cli, verifier, &vSz),
WC_NO_ERR_TRACE(BUFFER_E));
/* baseline: all guards false, buffer big enough -> success. */
vSz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetVerifier(&cli, verifier, &vSz), 0);
wc_SrpTerm(&cli);
wc_SrpTerm(&srv);
}
/* --- wc_SrpSetPrivate() --- */
{
Srp cli;
byte privBuf[8];
XMEMSET(&cli, 0, sizeof(cli));
XMEMSET(privBuf, 0, sizeof(privBuf));
privBuf[0] = 0x05;
ExpectIntEQ(wc_SrpInit(&cli, SRP_TYPE_SHA256, SRP_CLIENT_SIDE), 0);
/* c0: !srp (srp.c:520) */
ExpectIntEQ(wc_SrpSetPrivate(NULL, privBuf, (word32)sizeof(privBuf)),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c1: !priv */
ExpectIntEQ(wc_SrpSetPrivate(&cli, NULL, (word32)sizeof(privBuf)),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c2: !size */
ExpectIntEQ(wc_SrpSetPrivate(&cli, privBuf, 0),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* auth == 0 -> SRP_CALL_ORDER_E (srp.c:523-524): before
* SetParams/SetPassword. */
ExpectIntEQ(wc_SrpSetPrivate(&cli, privBuf, (word32)sizeof(privBuf)),
WC_NO_ERR_TRACE(SRP_CALL_ORDER_E));
ExpectIntEQ(wc_SrpSetUsername(&cli, srpUser, SRP_USER_SZ), 0);
ExpectIntEQ(wc_SrpSetParams(&cli, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ), 0);
ExpectIntEQ(wc_SrpSetPassword(&cli, srpPass, SRP_PASS_SZ), 0);
/* priv mod N == 0 -> SRP_BAD_KEY_E (srp.c:536): pass N itself as
* the private value so priv mod N == 0. */
ExpectIntEQ(wc_SrpSetPrivate(&cli, srpN, SRP_N_SZ),
WC_NO_ERR_TRACE(SRP_BAD_KEY_E));
/* baseline: all guards false, priv mod N != 0 -> success. */
ExpectIntEQ(wc_SrpSetPrivate(&cli, privBuf, (word32)sizeof(privBuf)),
0);
wc_SrpTerm(&cli);
}
/* --- wc_SrpGetPublic() --- */
{
Srp cli;
Srp srv;
byte pub[SRP_N_SZ];
word32 pubSz;
static const byte tinyVerifier[1] = { 0x07 };
XMEMSET(&cli, 0, sizeof(cli));
XMEMSET(&srv, 0, sizeof(srv));
XMEMSET(pub, 0, sizeof(pub));
ExpectIntEQ(wc_SrpInit(&cli, SRP_TYPE_SHA256, SRP_CLIENT_SIDE), 0);
pubSz = SRP_N_SZ;
/* c0: !srp (srp.c:568) */
ExpectIntEQ(wc_SrpGetPublic(NULL, pub, &pubSz),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c1: !pub */
ExpectIntEQ(wc_SrpGetPublic(&cli, NULL, &pubSz),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c2: !size */
ExpectIntEQ(wc_SrpGetPublic(&cli, pub, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* hashSize < 0 -> ALGO_ID_E (srp.c:571-573) */
cli.type = (SrpType)0;
pubSz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetPublic(&cli, pub, &pubSz),
WC_NO_ERR_TRACE(ALGO_ID_E));
cli.type = SRP_TYPE_SHA256;
/* auth == 0 -> SRP_CALL_ORDER_E (srp.c:575-576): before
* SetPassword. */
pubSz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetPublic(&cli, pub, &pubSz),
WC_NO_ERR_TRACE(SRP_CALL_ORDER_E));
ExpectIntEQ(wc_SrpSetUsername(&cli, srpUser, SRP_USER_SZ), 0);
ExpectIntEQ(wc_SrpSetParams(&cli, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ), 0);
ExpectIntEQ(wc_SrpSetPassword(&cli, srpPass, SRP_PASS_SZ), 0);
/* buffer too small -> BUFFER_E (srp.c:579-580) */
pubSz = 4;
ExpectIntEQ(wc_SrpGetPublic(&cli, pub, &pubSz),
WC_NO_ERR_TRACE(BUFFER_E));
/* baseline: client-side branch (srp.c:595-596). */
pubSz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetPublic(&cli, pub, &pubSz), 0);
wc_SrpTerm(&cli);
/* server-side branch (srp.c:599-634) + k==0 bad-key path
* (srp.c:616). */
ExpectIntEQ(wc_SrpInit(&srv, SRP_TYPE_SHA256, SRP_SERVER_SIDE), 0);
ExpectIntEQ(wc_SrpSetUsername(&srv, srpUser, SRP_USER_SZ), 0);
ExpectIntEQ(wc_SrpSetParams(&srv, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ), 0);
ExpectIntEQ(wc_SrpSetVerifier(&srv, tinyVerifier,
(word32)sizeof(tinyVerifier)), 0);
/* Directly zero the public srp->k field to force the
* multiplier-as-zero bad-key branch. */
XMEMSET(srv.k, 0, sizeof(srv.k));
pubSz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetPublic(&srv, pub, &pubSz),
WC_NO_ERR_TRACE(SRP_BAD_KEY_E));
/* Re-derive k (a fresh SetParams() recomputes k = H(N, g)) to
* exercise the false direction of the same check. */
ExpectIntEQ(wc_SrpSetParams(&srv, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ), 0);
pubSz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetPublic(&srv, pub, &pubSz), 0);
wc_SrpTerm(&srv);
}
/* --- wc_SrpComputeKey() --- */
{
Srp cli;
Srp srv;
byte pubBuf[SRP_N_SZ];
byte bigBuf[SRP_N_SZ + 8];
byte nCopy[SRP_N_SZ];
byte zeroByte[1] = { 0x00 };
byte oneByte[1] = { 0x01 };
word32 pubSz;
/* wc_SrpComputeKey() takes non-const byte* peer-key arguments
* (it only reads them), so a mutable copy of srpN is needed
* wherever N's bytes are reused as a bad-key test value. */
XMEMCPY(nCopy, srpN, sizeof(nCopy));
XMEMSET(&cli, 0, sizeof(cli));
XMEMSET(&srv, 0, sizeof(srv));
XMEMSET(pubBuf, 0, sizeof(pubBuf));
XMEMSET(bigBuf, 0, sizeof(bigBuf));
ExpectIntEQ(wc_SrpInit(&cli, SRP_TYPE_SHA256, SRP_CLIENT_SIDE), 0);
/* Top guard (srp.c:727-728): isolate each operand true
* individually. */
ExpectIntEQ(wc_SrpComputeKey(NULL, oneByte, 1, oneByte, 1),
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* c0: !srp */
ExpectIntEQ(wc_SrpComputeKey(&cli, NULL, 1, oneByte, 1),
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* c1: !clientPubKey */
ExpectIntEQ(wc_SrpComputeKey(&cli, oneByte, 0, oneByte, 1),
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* c2: clientPubKeySz==0 */
ExpectIntEQ(wc_SrpComputeKey(&cli, oneByte, 1, NULL, 1),
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* c3: !serverPubKey */
ExpectIntEQ(wc_SrpComputeKey(&cli, oneByte, 1, oneByte, 0),
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* c4: serverPubKeySz==0 */
ExpectIntEQ(wc_SrpSetUsername(&cli, srpUser, SRP_USER_SZ), 0);
ExpectIntEQ(wc_SrpSetParams(&cli, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ), 0);
ExpectIntEQ(wc_SrpSetPassword(&cli, srpPass, SRP_PASS_SZ), 0);
/* priv == 0 -> SRP_CALL_ORDER_E (srp.c:756-758): before
* SetPrivate/GetPublic. */
ExpectIntEQ(wc_SrpComputeKey(&cli, oneByte, 1, oneByte, 1),
WC_NO_ERR_TRACE(SRP_CALL_ORDER_E));
pubSz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetPublic(&cli, pubBuf, &pubSz), 0);
/* secretSz < clientPubKeySz / < serverPubKeySz (srp.c:775-778):
* isolate each operand with an oversized peer buffer. */
ExpectIntEQ(wc_SrpComputeKey(&cli, bigBuf, (word32)sizeof(bigBuf),
oneByte, 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_SrpComputeKey(&cli, oneByte, 1, bigBuf,
(word32)sizeof(bigBuf)), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* client-side bad-key branches: */
/* temp1 (k) == 0 -> SRP_BAD_KEY_E (srp.c:819-822) */
{
byte savedK[SRP_MAX_DIGEST_SIZE];
XMEMCPY(savedK, cli.k, sizeof(savedK));
XMEMSET(cli.k, 0, sizeof(cli.k));
ExpectIntEQ(wc_SrpComputeKey(&cli, pubBuf, pubSz, pubBuf, pubSz),
WC_NO_ERR_TRACE(SRP_BAD_KEY_E));
XMEMCPY(cli.k, savedK, sizeof(savedK));
}
/* serverPubKey == 0 -> SRP_BAD_KEY_E (srp.c:829-832) */
ExpectIntEQ(wc_SrpComputeKey(&cli, pubBuf, pubSz, zeroByte, 1),
WC_NO_ERR_TRACE(SRP_BAD_KEY_E));
/* serverPubKey >= N -> SRP_BAD_KEY_E (srp.c:833-836) */
ExpectIntEQ(wc_SrpComputeKey(&cli, pubBuf, pubSz, nCopy, SRP_N_SZ),
WC_NO_ERR_TRACE(SRP_BAD_KEY_E));
/* The false direction of all three client-side bad-key checks,
* plus the true (all guards false) baseline of the top guard and
* secretSz check, is exercised by the two-party handshake in
* test_wc_Srp_FeatureCoverage() instead of repeating it here. */
wc_SrpTerm(&cli);
/* server-side bad-key branches: */
ExpectIntEQ(wc_SrpInit(&srv, SRP_TYPE_SHA256, SRP_SERVER_SIDE), 0);
ExpectIntEQ(wc_SrpSetUsername(&srv, srpUser, SRP_USER_SZ), 0);
ExpectIntEQ(wc_SrpSetParams(&srv, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ), 0);
ExpectIntEQ(wc_SrpSetVerifier(&srv, oneByte, 1), 0);
pubSz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetPublic(&srv, pubBuf, &pubSz), 0);
/* s (clientPubKey) == 0 -> SRP_BAD_KEY_E (srp.c:858-861) */
ExpectIntEQ(wc_SrpComputeKey(&srv, zeroByte, 1, pubBuf, pubSz),
WC_NO_ERR_TRACE(SRP_BAD_KEY_E));
/* s >= N -> SRP_BAD_KEY_E (srp.c:862-865) */
ExpectIntEQ(wc_SrpComputeKey(&srv, nCopy, SRP_N_SZ, pubBuf, pubSz),
WC_NO_ERR_TRACE(SRP_BAD_KEY_E));
wc_SrpTerm(&srv);
}
/* --- wc_SrpGetProof() --- */
{
Srp cli;
Srp srv;
byte proof[SRP_MAX_DIGEST_SIZE];
word32 proofSz;
XMEMSET(&cli, 0, sizeof(cli));
XMEMSET(&srv, 0, sizeof(srv));
XMEMSET(proof, 0, sizeof(proof));
ExpectIntEQ(wc_SrpInit(&cli, SRP_TYPE_SHA256, SRP_CLIENT_SIDE), 0);
proofSz = SRP_MAX_DIGEST_SIZE;
/* c0: !srp (srp.c:958) */
ExpectIntEQ(wc_SrpGetProof(NULL, proof, &proofSz),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c1: !proof */
ExpectIntEQ(wc_SrpGetProof(&cli, NULL, &proofSz),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c2: !size */
ExpectIntEQ(wc_SrpGetProof(&cli, proof, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* hashSize < 0 -> ALGO_ID_E (srp.c:961-963) */
cli.type = (SrpType)0;
proofSz = SRP_MAX_DIGEST_SIZE;
ExpectIntEQ(wc_SrpGetProof(&cli, proof, &proofSz),
WC_NO_ERR_TRACE(ALGO_ID_E));
cli.type = SRP_TYPE_SHA256;
/* buffer too small -> BUFFER_E (srp.c:965-966) */
proofSz = 1;
ExpectIntEQ(wc_SrpGetProof(&cli, proof, &proofSz),
WC_NO_ERR_TRACE(BUFFER_E));
/* baseline + client-side branch (srp.c:968-970, 975). */
proofSz = SRP_MAX_DIGEST_SIZE;
ExpectIntEQ(wc_SrpGetProof(&cli, proof, &proofSz), 0);
wc_SrpTerm(&cli);
/* server-side branch: the "update server_proof" step under
* "if (srp->side == SRP_CLIENT_SIDE)" (srp.c:975) is skipped. */
ExpectIntEQ(wc_SrpInit(&srv, SRP_TYPE_SHA256, SRP_SERVER_SIDE), 0);
proofSz = SRP_MAX_DIGEST_SIZE;
ExpectIntEQ(wc_SrpGetProof(&srv, proof, &proofSz), 0);
wc_SrpTerm(&srv);
}
/* --- wc_SrpVerifyPeersProof() --- */
{
Srp cli;
byte proof[SRP_MAX_DIGEST_SIZE];
XMEMSET(&cli, 0, sizeof(cli));
XMEMSET(proof, 0, sizeof(proof));
ExpectIntEQ(wc_SrpInit(&cli, SRP_TYPE_SHA256, SRP_CLIENT_SIDE), 0);
/* c0: !srp (srp.c:990) */
ExpectIntEQ(wc_SrpVerifyPeersProof(NULL, proof,
WC_SHA256_DIGEST_SIZE), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* c1: !proof */
ExpectIntEQ(wc_SrpVerifyPeersProof(&cli, NULL,
WC_SHA256_DIGEST_SIZE), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* hashSize < 0 -> ALGO_ID_E (srp.c:993-995) */
cli.type = (SrpType)0;
ExpectIntEQ(wc_SrpVerifyPeersProof(&cli, proof,
WC_SHA256_DIGEST_SIZE), WC_NO_ERR_TRACE(ALGO_ID_E));
cli.type = SRP_TYPE_SHA256;
/* size != hashSize -> BUFFER_E (srp.c:997-998). The second OR
* operand (size > INT_MAX) is structurally masked here -- see the
* header comment above. */
ExpectIntEQ(wc_SrpVerifyPeersProof(&cli, proof,
(word32)(WC_SHA256_DIGEST_SIZE - 1)),
WC_NO_ERR_TRACE(BUFFER_E));
/* baseline (size == hashSize) + ConstantCompare mismatch ->
* SRP_VERIFY_E (srp.c:1009): a freshly Init'd client's
* server_proof hash context has not been fed the expected
* transcript, so any candidate proof legitimately fails
* verification. The matching/verified direction is covered by
* the full handshake in test_wc_Srp_FeatureCoverage(). */
ExpectIntEQ(wc_SrpVerifyPeersProof(&cli, proof,
WC_SHA256_DIGEST_SIZE), WC_NO_ERR_TRACE(SRP_VERIFY_E));
wc_SrpTerm(&cli);
}
#endif /* !NO_SHA256 */
#endif /* WOLFCRYPT_HAVE_SRP */
return EXPECT_RESULT();
}
/*
* Positive/feature coverage: a full client+server SRP-6a handshake using
* SHA-256, modeled on wolfcrypt/test/test.c's srp_test_digest(). Both
* sides use a fixed (non-random) private ephemeral value via
* wc_SrpSetPrivate() so the exchange is deterministic:
* wc_SrpInit -> wc_SrpSetUsername -> wc_SrpSetParams ->
* wc_SrpSetPassword (client) / wc_SrpSetVerifier (server, fed by the
* client's wc_SrpGetVerifier) -> wc_SrpSetPrivate -> wc_SrpGetPublic
* (both sides) -> wc_SrpComputeKey (both sides) -> wc_SrpGetProof /
* wc_SrpVerifyPeersProof (both directions) -> wc_SrpTerm.
* A second client instance then repeats the exchange and demonstrates that
* a corrupted server proof is rejected with SRP_VERIFY_E, mirroring the
* negative check at the end of srp_test_digest().
*/
int test_wc_Srp_FeatureCoverage(void)
{
EXPECT_DECLS;
#ifdef WOLFCRYPT_HAVE_SRP
#ifndef NO_SHA256
Srp cli;
Srp srv;
byte clientPubKey[SRP_N_SZ];
byte serverPubKey[SRP_N_SZ];
word32 clientPubKeySz;
word32 serverPubKeySz;
byte verifier[SRP_N_SZ];
word32 verifierSz;
byte clientProof[SRP_MAX_DIGEST_SIZE];
byte serverProof[SRP_MAX_DIGEST_SIZE];
word32 clientProofSz;
word32 serverProofSz;
static const byte clientPriv[] = {
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x01,
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x12
};
static const byte serverPriv[] = {
0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98,
0xA9, 0xBA, 0xCB, 0xDC, 0xED, 0xFE, 0x0F, 0x1A,
0x2B, 0x3C, 0x4D, 0x5E, 0x6F, 0x70, 0x81, 0x92,
0xA3, 0xB4, 0xC5, 0xD6, 0xE7, 0xF8, 0x09, 0x1B
};
XMEMSET(&cli, 0, sizeof(cli));
XMEMSET(&srv, 0, sizeof(srv));
XMEMSET(clientPubKey, 0, sizeof(clientPubKey));
XMEMSET(serverPubKey, 0, sizeof(serverPubKey));
XMEMSET(verifier, 0, sizeof(verifier));
XMEMSET(clientProof, 0, sizeof(clientProof));
XMEMSET(serverProof, 0, sizeof(serverProof));
/* Client knows username + password; derives the verifier to hand to
* the server out-of-band. */
ExpectIntEQ(wc_SrpInit(&cli, SRP_TYPE_SHA256, SRP_CLIENT_SIDE), 0);
ExpectIntEQ(wc_SrpSetUsername(&cli, srpUser, SRP_USER_SZ), 0);
ExpectIntEQ(wc_SrpSetParams(&cli, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ), 0);
ExpectIntEQ(wc_SrpSetPassword(&cli, srpPass, SRP_PASS_SZ), 0);
verifierSz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetVerifier(&cli, verifier, &verifierSz), 0);
/* Client sends its username to the server; the server already knows
* N/g/salt and stores the verifier. */
ExpectIntEQ(wc_SrpInit(&srv, SRP_TYPE_SHA256, SRP_SERVER_SIDE), 0);
ExpectIntEQ(wc_SrpSetUsername(&srv, srpUser, SRP_USER_SZ), 0);
ExpectIntEQ(wc_SrpSetParams(&srv, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ), 0);
ExpectIntEQ(wc_SrpSetVerifier(&srv, verifier, verifierSz), 0);
/* Both sides pin a fixed private ephemeral value for a deterministic
* exchange, then derive their public ephemeral values. */
ExpectIntEQ(wc_SrpSetPrivate(&cli, clientPriv,
(word32)sizeof(clientPriv)), 0);
ExpectIntEQ(wc_SrpSetPrivate(&srv, serverPriv,
(word32)sizeof(serverPriv)), 0);
clientPubKeySz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetPublic(&cli, clientPubKey, &clientPubKeySz), 0);
serverPubKeySz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetPublic(&srv, serverPubKey, &serverPubKeySz), 0);
/* Server sends N/g/salt/B to the client; client computes the shared
* session key and its own proof. */
clientProofSz = SRP_MAX_DIGEST_SIZE;
ExpectIntEQ(wc_SrpComputeKey(&cli, clientPubKey, clientPubKeySz,
serverPubKey, serverPubKeySz), 0);
ExpectIntEQ(wc_SrpGetProof(&cli, clientProof, &clientProofSz), 0);
/* Client sends A and M1 to the server; the server computes the same
* session key, verifies the client's proof, and replies with its
* own. */
serverProofSz = SRP_MAX_DIGEST_SIZE;
ExpectIntEQ(wc_SrpComputeKey(&srv, clientPubKey, clientPubKeySz,
serverPubKey, serverPubKeySz), 0);
ExpectIntEQ(wc_SrpVerifyPeersProof(&srv, clientProof, clientProofSz), 0);
ExpectIntEQ(wc_SrpGetProof(&srv, serverProof, &serverProofSz), 0);
/* Server sends M2 to the client; client verifies it. */
ExpectIntEQ(wc_SrpVerifyPeersProof(&cli, serverProof, serverProofSz), 0);
/* Negative check mirroring wolfcrypt/test/test.c's srp_test_digest():
* a corrupted server proof must be rejected with SRP_VERIFY_E, on a
* second client instance that repeats the same exchange against the
* same server public key/private auth material. */
{
Srp cli2;
byte clientPubKey2[SRP_N_SZ];
word32 clientPubKey2Sz;
byte clientProof2[SRP_MAX_DIGEST_SIZE];
word32 clientProof2Sz;
byte badServerProof[SRP_MAX_DIGEST_SIZE];
XMEMSET(&cli2, 0, sizeof(cli2));
XMEMSET(clientPubKey2, 0, sizeof(clientPubKey2));
XMEMSET(clientProof2, 0, sizeof(clientProof2));
XMEMCPY(badServerProof, serverProof, sizeof(badServerProof));
badServerProof[0] = (byte)(badServerProof[0] ^ 0x01);
ExpectIntEQ(wc_SrpInit(&cli2, SRP_TYPE_SHA256, SRP_CLIENT_SIDE), 0);
ExpectIntEQ(wc_SrpSetUsername(&cli2, srpUser, SRP_USER_SZ), 0);
ExpectIntEQ(wc_SrpSetParams(&cli2, srpN, SRP_N_SZ, srpG,
(word32)sizeof(srpG), srpSalt, SRP_SALT_SZ), 0);
ExpectIntEQ(wc_SrpSetPassword(&cli2, srpPass, SRP_PASS_SZ), 0);
ExpectIntEQ(wc_SrpSetPrivate(&cli2, clientPriv,
(word32)sizeof(clientPriv)), 0);
clientPubKey2Sz = SRP_N_SZ;
ExpectIntEQ(wc_SrpGetPublic(&cli2, clientPubKey2, &clientPubKey2Sz),
0);
ExpectIntEQ(wc_SrpComputeKey(&cli2, clientPubKey2, clientPubKey2Sz,
serverPubKey, serverPubKeySz), 0);
clientProof2Sz = SRP_MAX_DIGEST_SIZE;
ExpectIntEQ(wc_SrpGetProof(&cli2, clientProof2, &clientProof2Sz), 0);
ExpectIntEQ(wc_SrpVerifyPeersProof(&cli2, badServerProof,
serverProofSz), WC_NO_ERR_TRACE(SRP_VERIFY_E));
wc_SrpTerm(&cli2);
}
wc_SrpTerm(&cli);
wc_SrpTerm(&srv);
#endif /* !NO_SHA256 */
#endif /* WOLFCRYPT_HAVE_SRP */
return EXPECT_RESULT();
}