diff --git a/src/ssl.c b/src/ssl.c index ad0dc49d1..fd4f376d6 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -31579,7 +31579,7 @@ int wolfSSL_DSA_SIG_set0(WOLFSSL_DSA_SIG *sig, WOLFSSL_BIGNUM *r, int wolfSSL_i2d_DSA_SIG(const WOLFSSL_DSA_SIG *sig, byte **out) { /* Space for sequence + two asn ints */ - byte buf[MAX_SEQ_SZ + 2*(ASN_TAG_SZ + MAX_LENGTH_SZ + DSA_HALF_SIZE)]; + byte buf[MAX_SEQ_SZ + 2*(ASN_TAG_SZ + MAX_LENGTH_SZ + DSA_MAX_HALF_SIZE)]; word32 bufLen = sizeof(buf); WOLFSSL_ENTER("wolfSSL_i2d_DSA_SIG"); @@ -31615,8 +31615,8 @@ int wolfSSL_i2d_DSA_SIG(const WOLFSSL_DSA_SIG *sig, byte **out) * ASN1_SEQUENCE * ASN1_INTEGER (DSA r) * ASN1_INTEGER (DSA s) - * Alternatively, if the input is DSA_SIG_SIZE in length then this - * API interprets this as two unsigned binary numbers. + * Alternatively, if the input is DSA_160_SIG_SIZE or DSA_256_SIG_SIZE in + * length then this API interprets this as two unsigned binary numbers. * @param sig If non-null then free'd first and then newly created * WOLFSSL_DSA_SIG is assigned * @param pp Input buffer that is moved forward on success @@ -31645,28 +31645,31 @@ WOLFSSL_DSA_SIG* wolfSSL_d2i_DSA_SIG(WOLFSSL_DSA_SIG **sig, r = (mp_int*)ret->r->internal; s = (mp_int*)ret->s->internal; - if (length == DSA_SIG_SIZE) { - /* Two raw numbers of DSA_HALF_SIZE size each */ - if (mp_read_unsigned_bin(r, *pp, DSA_HALF_SIZE) != 0) { - WOLFSSL_MSG("r mp_read_unsigned_bin error"); - wolfSSL_DSA_SIG_free(ret); - return NULL; - } + if (DecodeECC_DSA_Sig(*pp, length, r, s) != 0) { + if (length == DSA_160_SIG_SIZE || length == DSA_256_SIG_SIZE) { + /* Two raw numbers of length/2 size each */ + if (mp_read_unsigned_bin(r, *pp, length/2) != 0) { + WOLFSSL_MSG("r mp_read_unsigned_bin error"); + wolfSSL_DSA_SIG_free(ret); + return NULL; + } - if (mp_read_unsigned_bin(s, *pp + DSA_HALF_SIZE, DSA_HALF_SIZE) != 0) { - WOLFSSL_MSG("s mp_read_unsigned_bin error"); - wolfSSL_DSA_SIG_free(ret); - return NULL; - } + if (mp_read_unsigned_bin(s, *pp + (length/2), length/2) != 0) { + WOLFSSL_MSG("s mp_read_unsigned_bin error"); + wolfSSL_DSA_SIG_free(ret); + return NULL; + } - *pp += DSA_SIG_SIZE; - } - else { - if (DecodeECC_DSA_Sig(*pp, length, r, s) != 0) { + *pp += length; + } + else { WOLFSSL_MSG("DecodeECC_DSA_Sig error"); wolfSSL_DSA_SIG_free(ret); return NULL; } + } + else { + /* DecodeECC_DSA_Sig success move pointer forward */ #ifndef NO_STRICT_ECDSA_LEN *pp += length; #else @@ -31684,7 +31687,6 @@ WOLFSSL_DSA_SIG* wolfSSL_d2i_DSA_SIG(WOLFSSL_DSA_SIG **sig, #endif } - if (sig != NULL) { if (*sig != NULL) wolfSSL_DSA_SIG_free(*sig); @@ -31714,10 +31716,8 @@ int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, return ret; } - if (dsa->inSet == 0) - { + if (dsa->inSet == 0) { WOLFSSL_MSG("No DSA internal set, do it"); - if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetDsaInternal failed"); return ret; @@ -31762,8 +31762,9 @@ int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest, int inLen, WOLFSSL_DSA* dsa) { - WOLFSSL_DSA_SIG* sig = NULL; - byte sigBin[DSA_SIG_SIZE]; + byte sigBin[DSA_MAX_SIG_SIZE]; + const byte *tmp = sigBin; + int sigLen; WOLFSSL_ENTER("wolfSSL_DSA_do_sign_ex"); @@ -31773,27 +31774,23 @@ WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest, } if (wolfSSL_DSA_do_sign(digest, sigBin, dsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_DSA_do_sign error"); return NULL; } - if (!(sig = wolfSSL_DSA_SIG_new())) { - goto error; + if (dsa->internal == NULL) { + WOLFSSL_MSG("dsa->internal is null"); + return NULL; } - if (!(sig->r = wolfSSL_BN_bin2bn(sigBin, DSA_HALF_SIZE, NULL))) { - goto error; + sigLen = mp_unsigned_bin_size(&((DsaKey*)dsa->internal)->q); + if (sigLen <= 0) { + WOLFSSL_MSG("mp_unsigned_bin_size error"); + return NULL; } - if (!(sig->s = wolfSSL_BN_bin2bn(sigBin + DSA_HALF_SIZE, DSA_HALF_SIZE, NULL))) { - goto error; - } - - return sig; -error: - if (sig) { - wolfSSL_DSA_SIG_free(sig); - } - return NULL; + /* 2 * sigLen for the two points r and s */ + return wolfSSL_d2i_DSA_SIG(NULL, &tmp, 2 * sigLen); } #endif /* !HAVE_SELFTEST && !HAVE_FIPS */ @@ -31842,8 +31839,10 @@ int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len, WOLFSSL_DSA_SIG* sig, WOLFSSL_DSA* dsa) { int dsacheck, sz; - byte sigBin[DSA_SIG_SIZE]; + byte sigBin[DSA_MAX_SIG_SIZE]; byte* sigBinPtr = sigBin; + DsaKey* key; + int qSz; WOLFSSL_ENTER("wolfSSL_DSA_do_verify_ex"); @@ -31857,37 +31856,51 @@ int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len, return WOLFSSL_FAILURE; } - /* front pad with zeros */ - if (!(sz = wolfSSL_BN_num_bytes(sig->r))) { - return WOLFSSL_FAILURE; - } - while (sz++ < DSA_HALF_SIZE) { - *sigBinPtr++ = 0; + if (dsa->inSet == 0) { + WOLFSSL_MSG("No DSA internal set, do it"); + if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return WOLFSSL_FAILURE; + } } - if (wolfSSL_BN_bn2bin(sig->r, sigBinPtr) == WOLFSSL_FATAL_ERROR) { + key = dsa->internal; + + if (key == NULL) { + WOLFSSL_MSG("dsa->internal is null"); return WOLFSSL_FAILURE; } + qSz = mp_unsigned_bin_size(&key->q); + if (qSz < 0 || qSz > DSA_MAX_HALF_SIZE) { + WOLFSSL_MSG("mp_unsigned_bin_size error"); + return WOLFSSL_FAILURE; + } + + /* read r */ + /* front pad with zeros */ + if ((sz = wolfSSL_BN_num_bytes(sig->r)) < 0 || sz > DSA_MAX_HALF_SIZE) + return WOLFSSL_FAILURE; + while (sz++ < qSz) + *sigBinPtr++ = 0; + if (wolfSSL_BN_bn2bin(sig->r, sigBinPtr) == WOLFSSL_FATAL_ERROR) + return WOLFSSL_FAILURE; + /* Move to s */ - sigBinPtr = sigBin + DSA_HALF_SIZE; + sigBinPtr = sigBin + qSz; + /* read s */ /* front pad with zeros */ - if (!(sz = wolfSSL_BN_num_bytes(sig->s))) { + if ((sz = wolfSSL_BN_num_bytes(sig->s)) < 0 || sz > DSA_MAX_HALF_SIZE) return WOLFSSL_FAILURE; - } - while (sz++ < DSA_HALF_SIZE) { + while (sz++ < qSz) *sigBinPtr++ = 0; - } - - if (wolfSSL_BN_bn2bin(sig->s, sigBinPtr) == WOLFSSL_FATAL_ERROR) { + if (wolfSSL_BN_bn2bin(sig->s, sigBinPtr) == WOLFSSL_FATAL_ERROR) return WOLFSSL_FAILURE; - } if (wolfSSL_DSA_do_verify(digest, sigBin, dsa, &dsacheck) != WOLFSSL_SUCCESS || - dsacheck != 1) { + dsacheck != 1) return WOLFSSL_FAILURE; - } return WOLFSSL_SUCCESS; } diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 330c85e61..70d8509a0 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -7709,7 +7709,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx, { word32 idx = 0; - if (sigSz < DSA_SIG_SIZE) { + if (sigSz < DSA_MIN_SIG_SIZE) { WOLFSSL_MSG("Verify Signature is too small"); ERROR_OUT(BUFFER_E, exit_cs); } @@ -7729,10 +7729,12 @@ static int ConfirmSignature(SignatureCtx* sigCtx, WOLFSSL_MSG("ASN Key decode error DSA"); goto exit_cs; } - if (sigSz != DSA_SIG_SIZE) { - #ifdef HAVE_ECC + if (sigSz != DSA_160_SIG_SIZE && + sigSz != DSA_256_SIG_SIZE) { /* Try to parse it as the contents of a bitstring */ mp_int r, s; + int rSz; + int sSz; idx = 0; if (DecodeECC_DSA_Sig(sig + idx, sigSz - idx, &r, &s) != 0) { @@ -7740,25 +7742,25 @@ static int ConfirmSignature(SignatureCtx* sigCtx, "incorrect format"); ERROR_OUT(ASN_SIG_CONFIRM_E, exit_cs); } - if (mp_to_unsigned_bin_len(&r, sigCtx->sigCpy, - DSA_HALF_SIZE) != MP_OKAY || - mp_to_unsigned_bin_len(&s, - sigCtx->sigCpy + DSA_HALF_SIZE, - DSA_HALF_SIZE) != MP_OKAY) { + rSz = mp_unsigned_bin_size(&r); + sSz = mp_unsigned_bin_size(&s); + if (rSz + sSz > (int)sigSz) { + WOLFSSL_MSG("DSA Sig is in unrecognized or " + "incorrect format"); + ERROR_OUT(ASN_SIG_CONFIRM_E, exit_cs); + } + if (mp_to_unsigned_bin(&r, sigCtx->sigCpy) != MP_OKAY || + mp_to_unsigned_bin(&s, + sigCtx->sigCpy + rSz) != MP_OKAY) { WOLFSSL_MSG("DSA Sig is in unrecognized or " "incorrect format"); ERROR_OUT(ASN_SIG_CONFIRM_E, exit_cs); } mp_free(&r); mp_free(&s); - #else - WOLFSSL_MSG("DSA Sig is in unrecognized or " - "incorrect format"); - ERROR_OUT(ASN_SIG_CONFIRM_E, exit_cs); - #endif } else { - XMEMCPY(sigCtx->sigCpy, sig, DSA_SIG_SIZE); + XMEMCPY(sigCtx->sigCpy, sig, sigSz); } break; } diff --git a/wolfcrypt/src/dsa.c b/wolfcrypt/src/dsa.c index 3ea7e67aa..c6d1a3519 100644 --- a/wolfcrypt/src/dsa.c +++ b/wolfcrypt/src/dsa.c @@ -241,6 +241,7 @@ int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa) */ switch (modulus_size) { #ifdef WOLFSSL_DSA_768_MODULUS + /* This key length is unsecure and only included for bind 9 testing */ case 768: #endif case 1024: @@ -685,10 +686,10 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) #ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME mp_int b[1]; #endif - byte buffer[DSA_HALF_SIZE]; + byte buffer[DSA_MAX_HALF_SIZE]; #endif mp_int* qMinus1; - int ret = 0, sz = 0; + int ret = 0, halfSz = 0; byte* tmp; /* initial output pointer */ do { @@ -707,7 +708,7 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) #ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME b = (mp_int *)XMALLOC(sizeof *b, key->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - buffer = (byte *)XMALLOC(DSA_HALF_SIZE, key->heap, + buffer = (byte *)XMALLOC(DSA_MAX_HALF_SIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER); if ((k == NULL) || @@ -734,7 +735,7 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) break; } - sz = min(DSA_HALF_SIZE, mp_unsigned_bin_size(&key->q)); + halfSz = min(DSA_MAX_HALF_SIZE, mp_unsigned_bin_size(&key->q)); tmp = out; qMinus1 = kInv; @@ -751,12 +752,12 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) do { /* Step 4: generate k */ - if ((ret = wc_RNG_GenerateBlock(rng, buffer, sz))) { + if ((ret = wc_RNG_GenerateBlock(rng, buffer, halfSz))) { break; } /* Step 5 */ - if (mp_read_unsigned_bin(k, buffer, sz) != MP_OKAY) { + if (mp_read_unsigned_bin(k, buffer, halfSz) != MP_OKAY) { ret = MP_READ_E; break; } @@ -820,10 +821,10 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) * Generate b in range [1, q-1]. */ do { - if ((ret = wc_RNG_GenerateBlock(rng, buffer, sz))) { + if ((ret = wc_RNG_GenerateBlock(rng, buffer, halfSz))) { break; } - if (mp_read_unsigned_bin(b, buffer, sz) != MP_OKAY) { + if (mp_read_unsigned_bin(b, buffer, halfSz) != MP_OKAY) { ret = MP_READ_E; break; } @@ -916,15 +917,15 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) int rSz = mp_unsigned_bin_size(r); int sSz = mp_unsigned_bin_size(s); - while (rSz++ < DSA_HALF_SIZE) { + while (rSz++ < halfSz) { *out++ = 0x00; /* pad front with zeros */ } 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 = tmp + halfSz; /* advance to s in output */ + while (sSz++ < halfSz) { *out++ = 0x00; /* pad front with zeros */ } ret = mp_to_unsigned_bin(s, out); @@ -971,7 +972,7 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) } #else /* !WOLFSSL_SMALL_STACK */ if (ret != MP_INIT_E) { - ForceZero(buffer, sz); + ForceZero(buffer, halfSz); mp_forcezero(kInv); mp_forcezero(k); #ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME @@ -1000,6 +1001,7 @@ int wc_DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer) mp_int w[1], u1[1], u2[1], v[1], r[1], s[1]; #endif int ret = 0; + int qSz; do { if (digest == NULL || sig == NULL || key == NULL || answer == NULL) { @@ -1031,9 +1033,15 @@ int wc_DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer) break; } + qSz = mp_unsigned_bin_size(&key->q); + if (qSz <= 0) { + ret = BAD_FUNC_ARG; + break; + } + /* 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, qSz) != MP_OKAY || + mp_read_unsigned_bin(s, sig + qSz, qSz) != MP_OKAY) { ret = MP_READ_E; break; } diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index ec2bdc362..f723b5467 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -1940,7 +1940,11 @@ int wolfSSL_EVP_PKEY_size(WOLFSSL_EVP_PKEY *pkey) #ifndef NO_DSA case EVP_PKEY_DSA: - return DSA_SIG_SIZE; + if (pkey->dsa == NULL || + (!pkey->dsa->exSet && + SetDsaExternal(pkey->dsa) != WOLFSSL_SUCCESS)) + return WOLFSSL_FAILURE; + return wolfSSL_BN_num_bytes(pkey->dsa->p); #endif #ifdef HAVE_ECC @@ -2417,7 +2421,7 @@ int wolfSSL_EVP_SignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sigret, #ifndef NO_DSA case EVP_PKEY_DSA: if (wolfSSL_DSA_do_sign(md, sigret, pkey->dsa) == WOLFSSL_SUCCESS) { - *siglen = DSA_SIG_SIZE; + *siglen = wolfSSL_BN_num_bytes(pkey->dsa->q); return WOLFSSL_SUCCESS; } else { diff --git a/wolfssl/wolfcrypt/dsa.h b/wolfssl/wolfcrypt/dsa.h index 0bb00fbfe..523e08ad0 100644 --- a/wolfssl/wolfcrypt/dsa.h +++ b/wolfssl/wolfcrypt/dsa.h @@ -53,8 +53,20 @@ enum { }; enum { - DSA_HALF_SIZE = 20, /* r and s size */ - DSA_SIG_SIZE = 40 /* signature size */ + /* 160 bit q length */ + DSA_160_HALF_SIZE = 20, /* r and s size */ + DSA_160_SIG_SIZE = 40, /* signature size */ + DSA_HALF_SIZE = DSA_160_HALF_SIZE, /* kept for compatiblity */ + DSA_SIG_SIZE = DSA_160_SIG_SIZE, /* kept for compatiblity */ + /* 256 bit q length */ + DSA_256_HALF_SIZE = 32, /* r and s size */ + DSA_256_SIG_SIZE = 64, /* signature size */ + + DSA_MIN_HALF_SIZE = DSA_160_HALF_SIZE, + DSA_MIN_SIG_SIZE = DSA_160_SIG_SIZE, + + DSA_MAX_HALF_SIZE = DSA_256_HALF_SIZE, + DSA_MAX_SIG_SIZE = DSA_256_SIG_SIZE, }; /* DSA */