From f49e9bf954c6871ca8e95283bbe783a14648f715 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 1 Dec 2020 18:35:57 -0600 Subject: [PATCH] dsa.c, srp.c, wolfcrypt/test/test.c: smallstack refactors: wc_DsaExportKeyRaw(), wc_DsaSign(), wc_SrpSetKey(), ecc_test_cdh_vectors(), ecc_test_custom_curves(). --- wolfcrypt/src/dsa.c | 438 +++++++++++++++++++++++++++++++----------- wolfcrypt/src/srp.c | 232 ++++++++++++++++------ wolfcrypt/test/test.c | 124 ++++++++---- 3 files changed, 584 insertions(+), 210 deletions(-) diff --git a/wolfcrypt/src/dsa.c b/wolfcrypt/src/dsa.c index 4b83a571d..310961e16 100644 --- a/wolfcrypt/src/dsa.c +++ b/wolfcrypt/src/dsa.c @@ -654,32 +654,67 @@ int wc_DsaExportKeyRaw(DsaKey* dsa, byte* x, word32* xSz, byte* y, word32* ySz) int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) { - mp_int k, kInv, r, s, H; +#ifdef WOLFSSL_SMALL_STACK + mp_int *k = (mp_int *)XMALLOC(sizeof *k, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + mp_int *kInv = (mp_int *)XMALLOC(sizeof *kInv, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + mp_int *r = (mp_int *)XMALLOC(sizeof *r, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + mp_int *s = (mp_int *)XMALLOC(sizeof *s, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + mp_int *H = (mp_int *)XMALLOC(sizeof *H, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); #ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME - mp_int b; + mp_int *b = (mp_int *)XMALLOC(sizeof *b, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + byte *buffer = (byte *)XMALLOC(DSA_HALF_SIZE, key->heap, + DYNAMIC_TYPE_TMP_BUFFER); +#else + mp_int k[1], kInv[1], r[1], s[1], H[1]; +#ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME + mp_int b[1]; +#endif + byte buffer[DSA_HALF_SIZE]; #endif mp_int* qMinus1; - int ret = 0, sz; - byte buffer[DSA_HALF_SIZE]; + int ret = 0, sz = 0; byte* tmp; /* initial output pointer */ - if (digest == NULL || out == NULL || key == NULL || rng == NULL) { - return BAD_FUNC_ARG; - } - - tmp = out; - - sz = min((int)sizeof(buffer), mp_unsigned_bin_size(&key->q)); - #ifdef WOLFSSL_MP_INVMOD_CONSTANT_TIME - if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY) + if (mp_init_multi(k, kInv, r, s, H, 0) != MP_OKAY) #else - if (mp_init_multi(&k, &kInv, &r, &s, &H, &b) != MP_OKAY) + if (mp_init_multi(k, kInv, r, s, H, b) != MP_OKAY) #endif { - return MP_INIT_E; + ret = MP_INIT_E; + goto out; } - qMinus1 = &kInv; + +#ifdef WOLFSSL_SMALL_STACK + if ((k == NULL) || + (kInv == NULL) || + (r == NULL) || + (s == NULL) || + (H == NULL) +#ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME + || (b == NULL) +#endif + || (buffer == NULL)) { + ret = MEMORY_E; + goto out; + } +#endif + + if (digest == NULL || out == NULL || key == NULL || rng == NULL) { + ret = BAD_FUNC_ARG; + goto out; + } + + sz = min(DSA_HALF_SIZE, mp_unsigned_bin_size(&key->q)); + tmp = out; + qMinus1 = kInv; /* NIST FIPS 186-4: B.2.2 * Per-Message Secret Number Generation by Testing Candidates @@ -687,159 +722,248 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) * Check that k is less than q-1: range [0, q-2]. * Add 1 to k: range [1, q-1]. */ - if (mp_sub_d(&key->q, 1, qMinus1)) + if (mp_sub_d(&key->q, 1, qMinus1)) { ret = MP_SUB_E; - - if (ret == 0) { - do { - /* Step 4: generate k */ - ret = wc_RNG_GenerateBlock(rng, buffer, sz); - - /* Step 5 */ - if (ret == 0 && mp_read_unsigned_bin(&k, buffer, sz) != MP_OKAY) - ret = MP_READ_E; - - /* k is a random numnber and it should be less than q-1 - * if k greater than repeat - */ - /* Step 6 */ - } while (ret == 0 && mp_cmp(&k, qMinus1) != MP_LT); + goto out; } + + do { + /* Step 4: generate k */ + if ((ret = wc_RNG_GenerateBlock(rng, buffer, sz))) { + goto out; + } + + /* Step 5 */ + if (mp_read_unsigned_bin(k, buffer, sz) != MP_OKAY) { + ret = MP_READ_E; + goto out; + } + + /* k is a random numnber and it should be less than q-1 + * if k greater than repeat + */ + /* Step 6 */ + } while (mp_cmp(k, qMinus1) != MP_LT); + /* Step 7 */ - if (ret == 0 && mp_add_d(&k, 1, &k) != MP_OKAY) + if (mp_add_d(k, 1, k) != MP_OKAY) { ret = MP_MOD_E; + goto out; + } #ifdef WOLFSSL_MP_INVMOD_CONSTANT_TIME /* inverse k mod q */ - if (ret == 0 && mp_invmod(&k, &key->q, &kInv) != MP_OKAY) + if (mp_invmod(k, &key->q, kInv) != MP_OKAY) { ret = MP_INVMOD_E; - - /* generate r, r = (g exp k mod p) mod q */ - if (ret == 0 && mp_exptmod_ex(&key->g, &k, key->q.used, &key->p, - &r) != MP_OKAY) { - ret = MP_EXPTMOD_E; + goto out; } - if (ret == 0 && mp_mod(&r, &key->q, &r) != MP_OKAY) + /* generate r, r = (g exp k mod p) mod q */ + if (mp_exptmod_ex(&key->g, k, key->q.used, &key->p, r) != MP_OKAY) { + ret = MP_EXPTMOD_E; + goto out; + } + + if (mp_mod(r, &key->q, r) != MP_OKAY) { ret = MP_MOD_E; + goto out; + } /* generate H from sha digest */ - if (ret == 0 && mp_read_unsigned_bin(&H, digest,WC_SHA_DIGEST_SIZE) != MP_OKAY) + if (mp_read_unsigned_bin(H, digest,WC_SHA_DIGEST_SIZE) != MP_OKAY) { ret = MP_READ_E; + goto out; + } /* generate s, s = (kInv * (H + x*r)) % q */ - if (ret == 0 && mp_mul(&key->x, &r, &s) != MP_OKAY) + if (mp_mul(&key->x, r, s) != MP_OKAY) { ret = MP_MUL_E; + goto out; + } - if (ret == 0 && mp_add(&s, &H, &s) != MP_OKAY) + if (mp_add(s, H, s) != MP_OKAY) { ret = MP_ADD_E; + goto out; + } - if (ret == 0 && mp_mulmod(&s, &kInv, &key->q, &s) != MP_OKAY) + if (mp_mulmod(s, kInv, &key->q, s) != MP_OKAY) { ret = MP_MULMOD_E; + goto out; + } #else /* Blinding value * Generate b in range [1, q-1]. */ - if (ret == 0) { - do { - ret = wc_RNG_GenerateBlock(rng, buffer, sz); - if (ret == 0 && mp_read_unsigned_bin(&b, buffer, sz) != MP_OKAY) - ret = MP_READ_E; - } while (ret == 0 && mp_cmp(&b, qMinus1) != MP_LT); - } - if (ret == 0 && mp_add_d(&b, 1, &b) != MP_OKAY) + do { + if ((ret = wc_RNG_GenerateBlock(rng, buffer, sz))) { + goto out; + } + if (mp_read_unsigned_bin(b, buffer, sz) != MP_OKAY) { + ret = MP_READ_E; + goto out; + } + } while (mp_cmp(b, qMinus1) != MP_LT); + + if (mp_add_d(b, 1, b) != MP_OKAY) { ret = MP_MOD_E; + goto out; + } /* set H from sha digest */ - if (ret == 0 && mp_read_unsigned_bin(&H, digest, - WC_SHA_DIGEST_SIZE) != MP_OKAY) { + if (mp_read_unsigned_bin(H, digest, WC_SHA_DIGEST_SIZE) != MP_OKAY) { ret = MP_READ_E; + goto out; } /* generate r, r = (g exp k mod p) mod q */ - if (ret == 0 && mp_exptmod_ex(&key->g, &k, key->q.used, &key->p, - &r) != MP_OKAY) { + if (mp_exptmod_ex(&key->g, k, key->q.used, &key->p, r) != MP_OKAY) { ret = MP_EXPTMOD_E; + goto out; } - /* calculate s = (H + xr)/k - = b.(H/k.b + x.r/k.b) */ + /* calculate s = (H + xr)/k = b.(H/k.b + x.r/k.b) */ /* k = k.b */ - if (ret == 0 && mp_mulmod(&k, &b, &key->q, &k) != MP_OKAY) + if (mp_mulmod(k, b, &key->q, k) != MP_OKAY) { ret = MP_MULMOD_E; + goto out; + } /* kInv = 1/k.b mod q */ - if (ret == 0 && mp_invmod(&k, &key->q, &kInv) != MP_OKAY) + if (mp_invmod(k, &key->q, kInv) != MP_OKAY) { ret = MP_INVMOD_E; + goto out; + } - if (ret == 0 && mp_mod(&r, &key->q, &r) != MP_OKAY) + if (mp_mod(r, &key->q, r) != MP_OKAY) { ret = MP_MOD_E; + goto out; + } /* s = x.r */ - if (ret == 0 && mp_mul(&key->x, &r, &s) != MP_OKAY) + if (mp_mul(&key->x, r, s) != MP_OKAY) { ret = MP_MUL_E; + goto out; + } /* s = x.r/k.b */ - if (ret == 0 && mp_mulmod(&s, &kInv, &key->q, &s) != MP_OKAY) + if (mp_mulmod(s, kInv, &key->q, s) != MP_OKAY) { ret = MP_MULMOD_E; + goto out; + } /* H = H/k.b */ - if (ret == 0 && mp_mulmod(&H, &kInv, &key->q, &H) != MP_OKAY) + if (mp_mulmod(H, kInv, &key->q, H) != MP_OKAY) { ret = MP_MULMOD_E; + goto out; + } - /* s = H/k.b + x.r/k.b - = (H + x.r)/k.b */ - if (ret == 0 && mp_add(&s, &H, &s) != MP_OKAY) + /* s = H/k.b + x.r/k.b = (H + x.r)/k.b */ + if (mp_add(s, H, s) != MP_OKAY) { ret = MP_ADD_E; + goto out; + } - /* s = b.(e + x.r)/k.b - = (e + x.r)/k */ - if (ret == 0 && mp_mulmod(&s, &b, &key->q, &s) != MP_OKAY) + /* s = b.(e + x.r)/k.b = (e + x.r)/k */ + if (mp_mulmod(s, b, &key->q, s) != MP_OKAY) { ret = MP_MULMOD_E; + goto out; + } /* s = (e + x.r)/k */ - if (ret == 0 && mp_mod(&s, &key->q, &s) != MP_OKAY) + if (mp_mod(s, &key->q, s) != MP_OKAY) { ret = MP_MOD_E; + goto out; + } #endif /* detect zero r or s */ - if (ret == 0 && (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES)) + if ((mp_iszero(r) == MP_YES) || (mp_iszero(s) == MP_YES)) { ret = MP_ZERO_E; + goto out; + } /* write out */ - if (ret == 0) { - int rSz = mp_unsigned_bin_size(&r); - int sSz = mp_unsigned_bin_size(&s); + { + int rSz = mp_unsigned_bin_size(r); + int sSz = mp_unsigned_bin_size(s); while (rSz++ < DSA_HALF_SIZE) { *out++ = 0x00; /* pad front with zeros */ } - if (mp_to_unsigned_bin(&r, out) != MP_OKAY) + if (mp_to_unsigned_bin(r, out) != MP_OKAY) ret = MP_TO_E; else { out = tmp + DSA_HALF_SIZE; /* advance to s in output */ while (sSz++ < DSA_HALF_SIZE) { *out++ = 0x00; /* pad front with zeros */ } - ret = mp_to_unsigned_bin(&s, out); + ret = mp_to_unsigned_bin(s, out); } } - ForceZero(buffer, sz); - mp_forcezero(&kInv); - mp_forcezero(&k); -#ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME - mp_forcezero(&b); + out: - mp_clear(&b); +#ifdef WOLFSSL_SMALL_STACK + if (k) { + if (ret != MP_INIT_E) { + mp_forcezero(k); + mp_clear(k); + } + XFREE(k, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (kInv) { + if (ret != MP_INIT_E) { + mp_forcezero(kInv); + mp_clear(kInv); + } + XFREE(kInv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (r) { + if (ret != MP_INIT_E) + mp_clear(r); + XFREE(r, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (s) { + if (ret != MP_INIT_E) + mp_clear(s); + XFREE(s, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (H) { + if (ret != MP_INIT_E) + mp_clear(H); + XFREE(H, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME + if (b) { + if (ret != MP_INIT_E) { + mp_forcezero(b); + mp_clear(b); + } + XFREE(b, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + if (buffer) { + ForceZero(buffer, sz); + XFREE(buffer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#else /* !WOLFSSL_SMALL_STACK */ + if (ret != MP_INIT_E) { + ForceZero(buffer, sz); + mp_forcezero(kInv); + mp_forcezero(k); +#ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME + mp_forcezero(b); + mp_clear(b); +#endif + mp_clear(H); + mp_clear(s); + mp_clear(r); + mp_clear(kInv); + mp_clear(k); + } #endif - mp_clear(&H); - mp_clear(&s); - mp_clear(&r); - mp_clear(&kInv); - mp_clear(&k); return ret; } @@ -847,70 +971,154 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) int wc_DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer) { - mp_int w, u1, u2, v, r, s; +#ifdef WOLFSSL_SMALL_STACK + mp_int *w = (mp_int *)XMALLOC(sizeof *w, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + mp_int *u1 = (mp_int *)XMALLOC(sizeof *u1, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + mp_int *u2 = (mp_int *)XMALLOC(sizeof *u2, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + mp_int *v = (mp_int *)XMALLOC(sizeof *v, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + mp_int *r = (mp_int *)XMALLOC(sizeof *r, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + mp_int *s = (mp_int *)XMALLOC(sizeof *s, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#else + mp_int w[1], u1[1], u2[1], v[1], r[1], s[1]; +#endif int ret = 0; - if (digest == NULL || sig == NULL || key == NULL || answer == NULL) { - return BAD_FUNC_ARG; + if (mp_init_multi(w, u1, u2, v, r, s) != MP_OKAY) { + ret = MP_INIT_E; + goto out; } - if (mp_init_multi(&w, &u1, &u2, &v, &r, &s) != MP_OKAY) - return MP_INIT_E; + if (digest == NULL || sig == NULL || key == NULL || answer == NULL) { + ret = BAD_FUNC_ARG; + goto out; + } + +#ifdef WOLFSSL_SMALL_STACK + if ((w == NULL) || + (u1 == NULL) || + (u2 == NULL) || + (v == NULL) || + (r == NULL) || + (s == NULL)) { + ret = MEMORY_E; + goto out; + } +#endif /* set r and s from signature */ - if (mp_read_unsigned_bin(&r, sig, DSA_HALF_SIZE) != MP_OKAY || - mp_read_unsigned_bin(&s, sig + DSA_HALF_SIZE, DSA_HALF_SIZE) != MP_OKAY) + if (mp_read_unsigned_bin(r, sig, DSA_HALF_SIZE) != MP_OKAY || + mp_read_unsigned_bin(s, sig + DSA_HALF_SIZE, DSA_HALF_SIZE) != MP_OKAY) { ret = MP_READ_E; + goto out; + } /* sanity checks */ - if (ret == 0) { - if (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES || - mp_cmp(&r, &key->q) != MP_LT || mp_cmp(&s, &key->q) != MP_LT) { - ret = MP_ZERO_E; - } + if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES || + mp_cmp(r, &key->q) != MP_LT || mp_cmp(s, &key->q) != MP_LT) { + ret = MP_ZERO_E; + goto out; } /* put H into u1 from sha digest */ - if (ret == 0 && mp_read_unsigned_bin(&u1,digest,WC_SHA_DIGEST_SIZE) != MP_OKAY) + if (mp_read_unsigned_bin(u1,digest,WC_SHA_DIGEST_SIZE) != MP_OKAY) { ret = MP_READ_E; + goto out; + } /* w = s invmod q */ - if (ret == 0 && mp_invmod(&s, &key->q, &w) != MP_OKAY) + if (mp_invmod(s, &key->q, w) != MP_OKAY) { ret = MP_INVMOD_E; + goto out; + } /* u1 = (H * w) % q */ - if (ret == 0 && mp_mulmod(&u1, &w, &key->q, &u1) != MP_OKAY) + if (mp_mulmod(u1, w, &key->q, u1) != MP_OKAY) { ret = MP_MULMOD_E; + goto out; + } /* u2 = (r * w) % q */ - if (ret == 0 && mp_mulmod(&r, &w, &key->q, &u2) != MP_OKAY) + if (mp_mulmod(r, w, &key->q, u2) != MP_OKAY) { ret = MP_MULMOD_E; + goto out; + } /* verify v = ((g^u1 * y^u2) mod p) mod q */ - if (ret == 0 && mp_exptmod(&key->g, &u1, &key->p, &u1) != MP_OKAY) + if (mp_exptmod(&key->g, u1, &key->p, u1) != MP_OKAY) { ret = MP_EXPTMOD_E; + goto out; + } - if (ret == 0 && mp_exptmod(&key->y, &u2, &key->p, &u2) != MP_OKAY) + if (mp_exptmod(&key->y, u2, &key->p, u2) != MP_OKAY) { ret = MP_EXPTMOD_E; + goto out; + } - if (ret == 0 && mp_mulmod(&u1, &u2, &key->p, &v) != MP_OKAY) + if (mp_mulmod(u1, u2, &key->p, v) != MP_OKAY) { ret = MP_MULMOD_E; + goto out; + } - if (ret == 0 && mp_mod(&v, &key->q, &v) != MP_OKAY) + if (mp_mod(v, &key->q, v) != MP_OKAY) { ret = MP_MULMOD_E; + goto out; + } /* do they match */ - if (ret == 0 && mp_cmp(&r, &v) == MP_EQ) + if (mp_cmp(r, v) == MP_EQ) *answer = 1; else *answer = 0; - mp_clear(&s); - mp_clear(&r); - mp_clear(&u1); - mp_clear(&u2); - mp_clear(&w); - mp_clear(&v); + out: + +#ifdef WOLFSSL_SMALL_STACK + if (s) { + if (ret != MP_INIT_E) + mp_clear(s); + XFREE(s, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (r) { + if (ret != MP_INIT_E) + mp_clear(r); + XFREE(r, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (u1) { + if (ret != MP_INIT_E) + mp_clear(u1); + XFREE(u1, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (u2) { + if (ret != MP_INIT_E) + mp_clear(u2); + XFREE(u2, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (w) { + if (ret != MP_INIT_E) + mp_clear(w); + XFREE(w, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (v) { + if (ret != MP_INIT_E) + mp_clear(v); + XFREE(v, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#else + if (ret != MP_INIT_E) { + mp_clear(s); + mp_clear(r); + mp_clear(u1); + mp_clear(u2); + mp_clear(w); + mp_clear(v); + } +#endif return ret; } diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index d8cf27bed..6d1d053b5 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -631,117 +631,233 @@ static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size) int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, byte* serverPubKey, word32 serverPubKeySz) { - SrpHash hash; - byte *secret; +#ifdef WOLFSSL_SMALL_STACK + SrpHash *hash = (SrpHash *)XMALLOC(sizeof *hash, srp->heap, DYNAMIC_TYPE_SRP); + byte *digest = (byte *)XMALLOC(SRP_MAX_DIGEST_SIZE, srp->heap, DYNAMIC_TYPE_SRP); + mp_int *u = (mp_int *)XMALLOC(sizeof *u, srp->heap, DYNAMIC_TYPE_SRP); + mp_int *s = (mp_int *)XMALLOC(sizeof *s, srp->heap, DYNAMIC_TYPE_SRP); + mp_int *temp1 = (mp_int *)XMALLOC(sizeof *temp1, srp->heap, DYNAMIC_TYPE_SRP); + mp_int *temp2 = (mp_int *)XMALLOC(sizeof *temp2, srp->heap, DYNAMIC_TYPE_SRP); +#else + SrpHash hash[1]; byte digest[SRP_MAX_DIGEST_SIZE]; + mp_int u[1], s[1], temp1[1], temp2[1]; +#endif + byte *secret = NULL; word32 i, secretSz, digestSz; - mp_int u, s, temp1, temp2; byte pad = 0; int r; /* validating params */ - if (!srp || !clientPubKey || clientPubKeySz == 0 - || !serverPubKey || serverPubKeySz == 0) - return BAD_FUNC_ARG; + if ((r = mp_init_multi(u, s, temp1, temp2, 0, 0)) != MP_OKAY) { + r = MP_INIT_E; + goto out; + } - if (mp_iszero(&srp->priv) == MP_YES) - return SRP_CALL_ORDER_E; + if (!srp || !clientPubKey || clientPubKeySz == 0 + || !serverPubKey || serverPubKeySz == 0) { + r = BAD_FUNC_ARG; + goto out; + } + +#ifdef WOLFSSL_SMALL_STACK + if ((hash == NULL) || + (digest == NULL) || + (u == NULL) || + (s == NULL) || + (temp1 == NULL) || + (temp2 == NULL)) { + r = MEMORY_E; + goto out; + } +#endif + + if (mp_iszero(&srp->priv) == MP_YES) { + r = SRP_CALL_ORDER_E; + goto out; + } /* initializing variables */ - if ((r = SrpHashInit(&hash, srp->type)) != 0) - return r; + if ((r = SrpHashInit(hash, srp->type)) != 0) + goto out; digestSz = SrpHashSize(srp->type); secretSz = mp_unsigned_bin_size(&srp->N); - if ((secretSz < clientPubKeySz) || (secretSz < serverPubKeySz)) - return BAD_FUNC_ARG; + if ((secretSz < clientPubKeySz) || (secretSz < serverPubKeySz)) { + r = BAD_FUNC_ARG; + goto out; + } - if ((secret = (byte*)XMALLOC(secretSz, srp->heap, DYNAMIC_TYPE_SRP)) ==NULL) - return MEMORY_E; - - if ((r = mp_init_multi(&u, &s, &temp1, &temp2, 0, 0)) != MP_OKAY) { - XFREE(secret, srp->heap, DYNAMIC_TYPE_SRP); - return r; + if ((secret = (byte*)XMALLOC(secretSz, srp->heap, DYNAMIC_TYPE_SRP)) == NULL) { + r = MEMORY_E; + goto out; } /* building u (random scrambling parameter) */ /* H(A) */ - for (i = 0; !r && i < secretSz - clientPubKeySz; i++) - r = SrpHashUpdate(&hash, &pad, 1); - if (!r) r = SrpHashUpdate(&hash, clientPubKey, clientPubKeySz); + for (i = 0; i < secretSz - clientPubKeySz; i++) { + if ((r = SrpHashUpdate(hash, &pad, 1))) + goto out; + } + + if ((r = SrpHashUpdate(hash, clientPubKey, clientPubKeySz))) + goto out; /* H(A | B) */ - for (i = 0; !r && i < secretSz - serverPubKeySz; i++) - r = SrpHashUpdate(&hash, &pad, 1); - if (!r) r = SrpHashUpdate(&hash, serverPubKey, serverPubKeySz); + for (i = 0; i < secretSz - serverPubKeySz; i++) { + if ((r = SrpHashUpdate(hash, &pad, 1))) + goto out; + } + if ((r = SrpHashUpdate(hash, serverPubKey, serverPubKeySz))) + goto out; /* set u */ - if (!r) r = SrpHashFinal(&hash, digest); - if (!r) r = mp_read_unsigned_bin(&u, digest, SrpHashSize(srp->type)); - SrpHashFree(&hash); + if ((r = SrpHashFinal(hash, digest))) + goto out; + if ((r = mp_read_unsigned_bin(u, digest, SrpHashSize(srp->type)))) + goto out; + SrpHashFree(hash); /* building s (secret) */ - if (!r && srp->side == SRP_CLIENT_SIDE) { + if (srp->side == SRP_CLIENT_SIDE) { /* temp1 = B - k * v; rejects k == 0, B == 0 and B >= N. */ - r = mp_read_unsigned_bin(&temp1, srp->k, digestSz); - if (!r) r = mp_iszero(&temp1) == MP_YES ? SRP_BAD_KEY_E : 0; - if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &temp2); - if (!r) r = mp_mulmod(&temp1, &temp2, &srp->N, &s); - if (!r) r = mp_read_unsigned_bin(&temp2, serverPubKey, serverPubKeySz); - if (!r) r = mp_iszero(&temp2) == MP_YES ? SRP_BAD_KEY_E : 0; - if (!r) r = mp_cmp(&temp2, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; - if (!r) r = mp_submod(&temp2, &s, &srp->N, &temp1); + if ((r = mp_read_unsigned_bin(temp1, srp->k, digestSz))) + goto out; + if (mp_iszero(temp1) == MP_YES) { + r = SRP_BAD_KEY_E; + goto out; + } + if ((r = mp_exptmod(&srp->g, &srp->auth, &srp->N, temp2))) + goto out; + if ((r = mp_mulmod(temp1, temp2, &srp->N, s))) + goto out; + if ((r = mp_read_unsigned_bin(temp2, serverPubKey, serverPubKeySz))) + goto out; + if (mp_iszero(temp2) == MP_YES) { + r = SRP_BAD_KEY_E; + goto out; + } + if (mp_cmp(temp2, &srp->N) != MP_LT) { + r = SRP_BAD_KEY_E; + goto out; + } + if ((r = mp_submod(temp2, s, &srp->N, temp1))) + goto out; /* temp2 = a + u * x */ - if (!r) r = mp_mulmod(&u, &srp->auth, &srp->N, &s); - if (!r) r = mp_add(&srp->priv, &s, &temp2); + if ((r = mp_mulmod(u, &srp->auth, &srp->N, s))) + goto out; + if ((r = mp_add(&srp->priv, s, temp2))) + goto out; /* secret = temp1 ^ temp2 % N */ - if (!r) r = mp_exptmod(&temp1, &temp2, &srp->N, &s); + if ((r = mp_exptmod(temp1, temp2, &srp->N, s))) + goto out; - } else if (!r && srp->side == SRP_SERVER_SIDE) { + } else if (srp->side == SRP_SERVER_SIDE) { /* temp1 = v ^ u % N */ - r = mp_exptmod(&srp->auth, &u, &srp->N, &temp1); + if ((r = mp_exptmod(&srp->auth, u, &srp->N, temp1))) + goto out; /* temp2 = A * temp1 % N; rejects A == 0, A >= N */ - if (!r) r = mp_read_unsigned_bin(&s, clientPubKey, clientPubKeySz); - if (!r) r = mp_iszero(&s) == MP_YES ? SRP_BAD_KEY_E : 0; - if (!r) r = mp_cmp(&s, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; - if (!r) r = mp_mulmod(&s, &temp1, &srp->N, &temp2); + if ((r = mp_read_unsigned_bin(s, clientPubKey, clientPubKeySz))) + goto out; + if (mp_iszero(s) == MP_YES) { + r = SRP_BAD_KEY_E; + goto out; + } + if (mp_cmp(s, &srp->N) != MP_LT) { + r = SRP_BAD_KEY_E; + goto out; + } + if ((r = mp_mulmod(s, temp1, &srp->N, temp2))) + goto out; /* rejects A * v ^ u % N >= 1, A * v ^ u % N == -1 % N */ - if (!r) r = mp_read_unsigned_bin(&temp1, (const byte*)"\001", 1); - if (!r) r = mp_cmp(&temp2, &temp1) != MP_GT ? SRP_BAD_KEY_E : 0; - if (!r) r = mp_sub(&srp->N, &temp1, &s); - if (!r) r = mp_cmp(&temp2, &s) == MP_EQ ? SRP_BAD_KEY_E : 0; + if ((r = mp_read_unsigned_bin(temp1, (const byte*)"\001", 1))) + goto out; + if (mp_cmp(temp2, temp1) != MP_GT) { + r = SRP_BAD_KEY_E; + goto out; + } + if ((r = mp_sub(&srp->N, temp1, s))) + goto out; + if (mp_cmp(temp2, s) == MP_EQ) { + r = SRP_BAD_KEY_E; + goto out; + } /* secret = temp2 * b % N */ - if (!r) r = mp_exptmod(&temp2, &srp->priv, &srp->N, &s); + if ((r = mp_exptmod(temp2, &srp->priv, &srp->N, s))) + goto out; } /* building session key from secret */ - if (!r) r = mp_to_unsigned_bin(&s, secret); - if (!r) r = srp->keyGenFunc_cb(srp, secret, mp_unsigned_bin_size(&s)); + if ((r = mp_to_unsigned_bin(s, secret))) + goto out; + if ((r = srp->keyGenFunc_cb(srp, secret, mp_unsigned_bin_size(s)))) + goto out; /* updating client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */ - if (!r) r = SrpHashUpdate(&srp->client_proof, clientPubKey, clientPubKeySz); - if (!r) r = SrpHashUpdate(&srp->client_proof, serverPubKey, serverPubKeySz); - if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, srp->keySz); + if ((r = SrpHashUpdate(&srp->client_proof, clientPubKey, clientPubKeySz))) + goto out; + if ((r = SrpHashUpdate(&srp->client_proof, serverPubKey, serverPubKeySz))) + goto out; + if ((r = SrpHashUpdate(&srp->client_proof, srp->key, srp->keySz))) + goto out; /* updating server proof = H(A) */ - if (!r) r = SrpHashUpdate(&srp->server_proof, clientPubKey, clientPubKeySz); + r = SrpHashUpdate(&srp->server_proof, clientPubKey, clientPubKeySz); - XFREE(secret, srp->heap, DYNAMIC_TYPE_SRP); - mp_clear(&u); mp_clear(&s); mp_clear(&temp1); mp_clear(&temp2); + out: + + if (secret) { + ForceZero(secret, secretSz); + XFREE(secret, srp->heap, DYNAMIC_TYPE_SRP); + } + +#ifdef WOLFSSL_SMALL_STACK + if (hash) + XFREE(hash, srp->heap, DYNAMIC_TYPE_SRP); + if (digest) + XFREE(digest, srp->heap, DYNAMIC_TYPE_SRP); + if (u) { + if (r != MP_INIT_E) + mp_clear(u); + XFREE(u, srp->heap, DYNAMIC_TYPE_SRP); + } + if (s) { + if (r != MP_INIT_E) + mp_clear(s); + XFREE(s, srp->heap, DYNAMIC_TYPE_SRP); + } + if (temp1) { + if (r != MP_INIT_E) + mp_clear(temp1); + XFREE(temp1, srp->heap, DYNAMIC_TYPE_SRP); + } + if (temp2) { + if (r != MP_INIT_E) + mp_clear(temp2); + XFREE(temp2, srp->heap, DYNAMIC_TYPE_SRP); + } +#else + if (r != MP_INIT_E) { + mp_clear(u); + mp_clear(s); + mp_clear(temp1); + mp_clear(temp2); + } +#endif return r; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 27732af5a..24999041a 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19408,39 +19408,53 @@ done: static int ecc_test_cdh_vectors(WC_RNG* rng) { int ret; - ecc_key pub_key, priv_key; +#ifdef WOLFSSL_SMALL_STACK + ecc_key *pub_key = (ecc_key *)XMALLOC(sizeof *pub_key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + ecc_key *priv_key = (ecc_key *)XMALLOC(sizeof *priv_key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#else + ecc_key pub_key[1], priv_key[1]; +#endif byte sharedA[32] = {0}, sharedB[32] = {0}; word32 x, z; - const char* QCAVSx = "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287"; - const char* QCAVSy = "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac"; - const char* dIUT = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534"; - const char* QIUTx = "ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b230"; - const char* QIUTy = "28af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141"; - const char* ZIUT = "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b"; + static const char* QCAVSx = "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287"; + static const char* QCAVSy = "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac"; + static const char* dIUT = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534"; + static const char* QIUTx = "ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b230"; + static const char* QIUTy = "28af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141"; + static const char* ZIUT = "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b"; + +#ifdef WOLFSSL_SMALL_STACK + if ((pub_key == NULL) || + (priv_key == NULL)) { + ret = MEMORY_E; + goto done; + } +#endif + + XMEMSET(pub_key, 0, sizeof *pub_key); + XMEMSET(priv_key, 0, sizeof *priv_key); /* setup private and public keys */ - ret = wc_ecc_init_ex(&pub_key, HEAP_HINT, devId); - if (ret != 0) - return ret; - ret = wc_ecc_init_ex(&priv_key, HEAP_HINT, devId); - if (ret != 0) { - wc_ecc_free(&pub_key); - return ret; - } - wc_ecc_set_flags(&pub_key, WC_ECC_FLAG_COFACTOR); - wc_ecc_set_flags(&priv_key, WC_ECC_FLAG_COFACTOR); - ret = wc_ecc_import_raw(&pub_key, QCAVSx, QCAVSy, NULL, "SECP256R1"); + ret = wc_ecc_init_ex(pub_key, HEAP_HINT, devId); if (ret != 0) goto done; - ret = wc_ecc_import_raw(&priv_key, QIUTx, QIUTy, dIUT, "SECP256R1"); + ret = wc_ecc_init_ex(priv_key, HEAP_HINT, devId); + if (ret != 0) + goto done; + wc_ecc_set_flags(pub_key, WC_ECC_FLAG_COFACTOR); + wc_ecc_set_flags(priv_key, WC_ECC_FLAG_COFACTOR); + ret = wc_ecc_import_raw(pub_key, QCAVSx, QCAVSy, NULL, "SECP256R1"); + if (ret != 0) + goto done; + ret = wc_ecc_import_raw(priv_key, QIUTx, QIUTy, dIUT, "SECP256R1"); if (ret != 0) goto done; #if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \ (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \ !defined(HAVE_SELFTEST) - ret = wc_ecc_set_rng(&priv_key, rng); + ret = wc_ecc_set_rng(priv_key, rng); if (ret != 0) goto done; #else @@ -19451,10 +19465,10 @@ static int ecc_test_cdh_vectors(WC_RNG* rng) x = sizeof(sharedA); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_AsyncWait(ret, &priv_key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + ret = wc_AsyncWait(ret, priv_key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret == 0) - ret = wc_ecc_shared_secret(&priv_key, &pub_key, sharedA, &x); + ret = wc_ecc_shared_secret(priv_key, pub_key, sharedA, &x); } while (ret == WC_PENDING_E); if (ret != 0) { goto done; @@ -19473,8 +19487,21 @@ static int ecc_test_cdh_vectors(WC_RNG* rng) } done: - wc_ecc_free(&priv_key); - wc_ecc_free(&pub_key); + +#ifdef WOLFSSL_SMALL_STACK + if (priv_key) { + wc_ecc_free(priv_key); + XFREE(priv_key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + if (pub_key) { + wc_ecc_free(pub_key); + XFREE(pub_key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } +#else + wc_ecc_free(priv_key); + wc_ecc_free(pub_key); +#endif + return ret; } #endif /* HAVE_ECC_CDH */ @@ -21230,24 +21257,28 @@ static int ecc_test_custom_curves(WC_RNG* rng) { int ret; word32 inOutIdx; - ecc_key key; +#ifdef WOLFSSL_SMALL_STACK + ecc_key *key = (ecc_key *)XMALLOC(sizeof *key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#else + ecc_key key[1]; +#endif /* test use of custom curve - using BRAINPOOLP256R1 for test */ #ifndef WOLFSSL_ECC_CURVE_STATIC - const ecc_oid_t ecc_oid_brainpoolp256r1[] = { + static const ecc_oid_t ecc_oid_brainpoolp256r1[] = { 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07 }; - const word32 ecc_oid_brainpoolp256r1_sz = - sizeof(ecc_oid_brainpoolp256r1) / sizeof(ecc_oid_t); + #define ecc_oid_brainpoolp256r1_sz \ + (sizeof(ecc_oid_brainpoolp256r1) / sizeof(ecc_oid_t)) #else #define ecc_oid_brainpoolp256r1 { \ 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07 \ } #define ecc_oid_brainpoolp256r1_sz 9 #endif - const word32 ecc_oid_brainpoolp256r1_sum = 104; + #define ecc_oid_brainpoolp256r1_sum 104 - const ecc_set_type ecc_dp_brainpool256r1 = { + static const ecc_set_type ecc_dp_brainpool256r1 = { 32, /* size/bytes */ ECC_CURVE_CUSTOM, /* ID */ "BRAINPOOLP256R1", /* curve name */ @@ -21263,11 +21294,20 @@ static int ecc_test_custom_curves(WC_RNG* rng) 1, /* cofactor */ }; +#ifdef WOLFSSL_SMALL_STACK + if (! key) { + ret = MEMORY_E; + goto done; + } +#endif + + XMEMSET(key, 0, sizeof *key); + ret = ecc_test_curve_size(rng, 0, ECC_TEST_VERIFY_COUNT, ECC_CURVE_DEF, &ecc_dp_brainpool256r1); if (ret != 0) { printf("ECC test for custom curve failed! %d\n", ret); - return ret; + goto done; } #if defined(HAVE_ECC_BRAINPOOL) || defined(HAVE_ECC_KOBLITZ) @@ -21282,23 +21322,33 @@ static int ecc_test_custom_curves(WC_RNG* rng) ret = ecc_test_curve_size(rng, 0, ECC_TEST_VERIFY_COUNT, curve_id, NULL); if (ret < 0) { printf("ECC test for curve_id %d failed! %d\n", curve_id, ret); - return ret; + goto done; } } #endif - ret = wc_ecc_init_ex(&key, HEAP_HINT, devId); + ret = wc_ecc_init_ex(key, HEAP_HINT, devId); if (ret != 0) { - return -10120; + ret = -10120; + goto done; } inOutIdx = 0; - ret = wc_EccPublicKeyDecode(eccKeyExplicitCurve, &inOutIdx, &key, + ret = wc_EccPublicKeyDecode(eccKeyExplicitCurve, &inOutIdx, key, sizeof(eccKeyExplicitCurve)); if (ret != 0) - return -10121; + ret = -10121; - wc_ecc_free(&key); + done: + +#ifdef WOLFSSL_SMALL_STACK + if (key) { + wc_ecc_free(key); + XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } +#else + wc_ecc_free(key); +#endif return ret; }