wolfcrypt/src/dsa.c: use do{}while(0) with break, rather than goto, for top level flow control in wc_DsaSign() and wc_DsaVerify() smallstack refactor.

pull/3534/head
Daniel Pouzzner 2020-12-10 18:04:23 -06:00
parent 53c6d33695
commit f2e1595eef
1 changed files with 262 additions and 256 deletions

View File

@ -682,228 +682,234 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng)
int ret = 0, sz = 0; int ret = 0, sz = 0;
byte* tmp; /* initial output pointer */ byte* tmp; /* initial output pointer */
do {
#ifdef WOLFSSL_MP_INVMOD_CONSTANT_TIME #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 #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 #endif
{ {
ret = MP_INIT_E; ret = MP_INIT_E;
goto out; break;
} }
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
if ((k == NULL) || if ((k == NULL) ||
(kInv == NULL) || (kInv == NULL) ||
(r == NULL) || (r == NULL) ||
(s == NULL) || (s == NULL) ||
(H == NULL) (H == NULL)
#ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME #ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME
|| (b == NULL) || (b == NULL)
#endif #endif
|| (buffer == NULL)) { || (buffer == NULL)) {
ret = MEMORY_E; ret = MEMORY_E;
goto out; break;
} }
#endif #endif
if (digest == NULL || out == NULL || key == NULL || rng == NULL) { if (digest == NULL || out == NULL || key == NULL || rng == NULL) {
ret = BAD_FUNC_ARG; ret = BAD_FUNC_ARG;
goto out; break;
}
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
* Generate k in range [1, q-1].
* 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)) {
ret = MP_SUB_E;
goto out;
}
do {
/* Step 4: generate k */
if ((ret = wc_RNG_GenerateBlock(rng, buffer, sz))) {
goto out;
} }
/* Step 5 */ sz = min(DSA_HALF_SIZE, mp_unsigned_bin_size(&key->q));
if (mp_read_unsigned_bin(k, buffer, sz) != MP_OKAY) { tmp = out;
ret = MP_READ_E; qMinus1 = kInv;
goto out;
}
/* k is a random numnber and it should be less than q-1 /* NIST FIPS 186-4: B.2.2
* if k greater than repeat * Per-Message Secret Number Generation by Testing Candidates
* Generate k in range [1, q-1].
* Check that k is less than q-1: range [0, q-2].
* Add 1 to k: range [1, q-1].
*/ */
/* Step 6 */ if (mp_sub_d(&key->q, 1, qMinus1)) {
} while (mp_cmp(k, qMinus1) != MP_LT); ret = MP_SUB_E;
break;
}
/* Step 7 */ do {
if (mp_add_d(k, 1, k) != MP_OKAY) { /* Step 4: generate k */
ret = MP_MOD_E; if ((ret = wc_RNG_GenerateBlock(rng, buffer, sz))) {
goto out; break;
} }
/* Step 5 */
if (mp_read_unsigned_bin(k, buffer, sz) != MP_OKAY) {
ret = MP_READ_E;
break;
}
/* 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);
if (ret != 0)
break;
/* Step 7 */
if (mp_add_d(k, 1, k) != MP_OKAY) {
ret = MP_MOD_E;
break;
}
#ifdef WOLFSSL_MP_INVMOD_CONSTANT_TIME #ifdef WOLFSSL_MP_INVMOD_CONSTANT_TIME
/* inverse k mod q */ /* inverse k mod q */
if (mp_invmod(k, &key->q, kInv) != MP_OKAY) { if (mp_invmod(k, &key->q, kInv) != MP_OKAY) {
ret = MP_INVMOD_E; ret = MP_INVMOD_E;
goto out; break;
}
/* 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 (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 (mp_mul(&key->x, r, s) != MP_OKAY) {
ret = MP_MUL_E;
goto out;
}
if (mp_add(s, H, s) != MP_OKAY) {
ret = MP_ADD_E;
goto out;
}
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].
*/
do {
if ((ret = wc_RNG_GenerateBlock(rng, buffer, sz))) {
goto out;
} }
if (mp_read_unsigned_bin(b, buffer, sz) != 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;
break;
}
if (mp_mod(r, &key->q, r) != MP_OKAY) {
ret = MP_MOD_E;
break;
}
/* generate H from sha digest */
if (mp_read_unsigned_bin(H, digest,WC_SHA_DIGEST_SIZE) != MP_OKAY) {
ret = MP_READ_E; ret = MP_READ_E;
goto out; break;
} }
} while (mp_cmp(b, qMinus1) != MP_LT);
if (mp_add_d(b, 1, b) != MP_OKAY) { /* generate s, s = (kInv * (H + x*r)) % q */
ret = MP_MOD_E; if (mp_mul(&key->x, r, s) != MP_OKAY) {
goto out; ret = MP_MUL_E;
} break;
}
/* set H from sha digest */ if (mp_add(s, H, s) != MP_OKAY) {
if (mp_read_unsigned_bin(H, digest, WC_SHA_DIGEST_SIZE) != MP_OKAY) { ret = MP_ADD_E;
ret = MP_READ_E; break;
goto out; }
}
/* generate r, r = (g exp k mod p) mod q */ if (mp_mulmod(s, kInv, &key->q, s) != MP_OKAY) {
if (mp_exptmod_ex(&key->g, k, key->q.used, &key->p, r) != MP_OKAY) { ret = MP_MULMOD_E;
ret = MP_EXPTMOD_E; break;
goto out; }
} #else
/* Blinding value
* Generate b in range [1, q-1].
*/
do {
if ((ret = wc_RNG_GenerateBlock(rng, buffer, sz))) {
break;
}
if (mp_read_unsigned_bin(b, buffer, sz) != MP_OKAY) {
ret = MP_READ_E;
break;
}
} while (mp_cmp(b, qMinus1) != MP_LT);
/* calculate s = (H + xr)/k = b.(H/k.b + x.r/k.b) */ if (ret != 0)
break;
/* k = k.b */ if (mp_add_d(b, 1, b) != MP_OKAY) {
if (mp_mulmod(k, b, &key->q, k) != MP_OKAY) { ret = MP_MOD_E;
ret = MP_MULMOD_E; break;
goto out; }
}
/* kInv = 1/k.b mod q */ /* set H from sha digest */
if (mp_invmod(k, &key->q, kInv) != MP_OKAY) { if (mp_read_unsigned_bin(H, digest, WC_SHA_DIGEST_SIZE) != MP_OKAY) {
ret = MP_INVMOD_E; ret = MP_READ_E;
goto out; break;
} }
if (mp_mod(r, &key->q, r) != MP_OKAY) { /* generate r, r = (g exp k mod p) mod q */
ret = MP_MOD_E; if (mp_exptmod_ex(&key->g, k, key->q.used, &key->p, r) != MP_OKAY) {
goto out; ret = MP_EXPTMOD_E;
} break;
}
/* s = x.r */ /* calculate s = (H + xr)/k = b.(H/k.b + x.r/k.b) */
if (mp_mul(&key->x, r, s) != MP_OKAY) {
ret = MP_MUL_E;
goto out;
}
/* s = x.r/k.b */ /* k = k.b */
if (mp_mulmod(s, kInv, &key->q, s) != MP_OKAY) { if (mp_mulmod(k, b, &key->q, k) != MP_OKAY) {
ret = MP_MULMOD_E; ret = MP_MULMOD_E;
goto out; break;
} }
/* H = H/k.b */ /* kInv = 1/k.b mod q */
if (mp_mulmod(H, kInv, &key->q, H) != MP_OKAY) { if (mp_invmod(k, &key->q, kInv) != MP_OKAY) {
ret = MP_MULMOD_E; ret = MP_INVMOD_E;
goto out; break;
} }
/* s = H/k.b + x.r/k.b = (H + x.r)/k.b */ if (mp_mod(r, &key->q, r) != MP_OKAY) {
if (mp_add(s, H, s) != MP_OKAY) { ret = MP_MOD_E;
ret = MP_ADD_E; break;
goto out; }
}
/* s = b.(e + x.r)/k.b = (e + x.r)/k */ /* s = x.r */
if (mp_mulmod(s, b, &key->q, s) != MP_OKAY) { if (mp_mul(&key->x, r, s) != MP_OKAY) {
ret = MP_MULMOD_E; ret = MP_MUL_E;
goto out; break;
} }
/* s = (e + x.r)/k */ /* s = x.r/k.b */
if (mp_mod(s, &key->q, s) != MP_OKAY) { if (mp_mulmod(s, kInv, &key->q, s) != MP_OKAY) {
ret = MP_MOD_E; ret = MP_MULMOD_E;
goto out; break;
} }
/* H = H/k.b */
if (mp_mulmod(H, kInv, &key->q, H) != MP_OKAY) {
ret = MP_MULMOD_E;
break;
}
/* 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;
break;
}
/* 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;
break;
}
/* s = (e + x.r)/k */
if (mp_mod(s, &key->q, s) != MP_OKAY) {
ret = MP_MOD_E;
break;
}
#endif #endif
/* detect zero r or s */ /* detect zero r or s */
if ((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; ret = MP_ZERO_E;
goto out; break;
}
/* write out */
{
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) /* write out */
ret = MP_TO_E; {
else { int rSz = mp_unsigned_bin_size(r);
out = tmp + DSA_HALF_SIZE; /* advance to s in output */ int sSz = mp_unsigned_bin_size(s);
while (sSz++ < DSA_HALF_SIZE) {
while (rSz++ < DSA_HALF_SIZE) {
*out++ = 0x00; /* pad front with zeros */ *out++ = 0x00; /* pad front with zeros */
} }
ret = mp_to_unsigned_bin(s, out);
}
}
out: 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);
}
}
} while (0);
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
if (k) { if (k) {
@ -980,94 +986,94 @@ int wc_DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer)
#endif #endif
int ret = 0; int ret = 0;
if (mp_init_multi(w, u1, u2, v, r, s) != MP_OKAY) { do {
ret = MP_INIT_E; if (mp_init_multi(w, u1, u2, v, r, s) != MP_OKAY) {
goto out; ret = MP_INIT_E;
} break;
}
if (digest == NULL || sig == NULL || key == NULL || answer == NULL) { if (digest == NULL || sig == NULL || key == NULL || answer == NULL) {
ret = BAD_FUNC_ARG; ret = BAD_FUNC_ARG;
goto out; break;
} }
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
if ((w == NULL) || if ((w == NULL) ||
(u1 == NULL) || (u1 == NULL) ||
(u2 == NULL) || (u2 == NULL) ||
(v == NULL) || (v == NULL) ||
(r == NULL) || (r == NULL) ||
(s == NULL)) { (s == NULL)) {
ret = MEMORY_E; ret = MEMORY_E;
goto out; break;
} }
#endif #endif
/* set r and s from signature */ /* set r and s from signature */
if (mp_read_unsigned_bin(r, sig, 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) { mp_read_unsigned_bin(s, sig + DSA_HALF_SIZE, DSA_HALF_SIZE) != MP_OKAY) {
ret = MP_READ_E; ret = MP_READ_E;
goto out; break;
} }
/* sanity checks */ /* sanity checks */
if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES || 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) { mp_cmp(r, &key->q) != MP_LT || mp_cmp(s, &key->q) != MP_LT) {
ret = MP_ZERO_E; ret = MP_ZERO_E;
goto out; break;
} }
/* put H into u1 from sha digest */ /* put H into u1 from sha digest */
if (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; ret = MP_READ_E;
goto out; break;
} }
/* w = s invmod q */ /* w = s invmod q */
if (mp_invmod(s, &key->q, w) != MP_OKAY) { if (mp_invmod(s, &key->q, w) != MP_OKAY) {
ret = MP_INVMOD_E; ret = MP_INVMOD_E;
goto out; break;
} }
/* u1 = (H * w) % q */ /* u1 = (H * w) % q */
if (mp_mulmod(u1, w, &key->q, u1) != MP_OKAY) { if (mp_mulmod(u1, w, &key->q, u1) != MP_OKAY) {
ret = MP_MULMOD_E; ret = MP_MULMOD_E;
goto out; break;
} }
/* u2 = (r * w) % q */ /* u2 = (r * w) % q */
if (mp_mulmod(r, w, &key->q, u2) != MP_OKAY) { if (mp_mulmod(r, w, &key->q, u2) != MP_OKAY) {
ret = MP_MULMOD_E; ret = MP_MULMOD_E;
goto out; break;
} }
/* verify v = ((g^u1 * y^u2) mod p) mod q */ /* verify v = ((g^u1 * y^u2) mod p) mod q */
if (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; ret = MP_EXPTMOD_E;
goto out; break;
} }
if (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; ret = MP_EXPTMOD_E;
goto out; break;
} }
if (mp_mulmod(u1, u2, &key->p, v) != MP_OKAY) { if (mp_mulmod(u1, u2, &key->p, v) != MP_OKAY) {
ret = MP_MULMOD_E; ret = MP_MULMOD_E;
goto out; break;
} }
if (mp_mod(v, &key->q, v) != MP_OKAY) { if (mp_mod(v, &key->q, v) != MP_OKAY) {
ret = MP_MULMOD_E; ret = MP_MULMOD_E;
goto out; break;
} }
/* do they match */ /* do they match */
if (mp_cmp(r, v) == MP_EQ) if (mp_cmp(r, v) == MP_EQ)
*answer = 1; *answer = 1;
else else
*answer = 0; *answer = 0;
} while (0);
out:
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
if (s) { if (s) {