diff --git a/tests/api.c b/tests/api.c index 78e6b5b11..f9362532f 100644 --- a/tests/api.c +++ b/tests/api.c @@ -16259,7 +16259,7 @@ static int test_wc_ChaCha20Poly1305_aead (void) sizeof(plaintext), generatedCiphertext, generatedAuthTag); AssertIntEQ(ret, BAD_FUNC_ARG); ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), - plaintext, 0, generatedCiphertext, generatedAuthTag); + NULL, sizeof(plaintext), generatedCiphertext, generatedAuthTag); AssertIntEQ(ret, BAD_FUNC_ARG); ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), plaintext, sizeof(plaintext), NULL, generatedAuthTag); @@ -16298,8 +16298,8 @@ static int test_wc_ChaCha20Poly1305_aead (void) ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, sizeof(cipher), authTag, NULL); AssertIntEQ(ret, BAD_FUNC_ARG); - ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, - 0, authTag, generatedPlaintext); + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), NULL, + sizeof(cipher), authTag, generatedPlaintext); AssertIntEQ(ret, BAD_FUNC_ARG); if (ret == BAD_FUNC_ARG) { ret = 0; diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 7844043d0..ab00c8ff5 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -11993,13 +11993,16 @@ static WARN_UNUSED_RESULT int S2V( } } - if (ret == 0) { + if ((ret == 0) && (nonceSz > 0)) { ShiftAndXorRb(tmp[0], tmp[1]); ret = wc_AesCmacGenerate(tmp[1], &macSz, nonce, nonceSz, key, keySz); if (ret == 0) { xorbuf(tmp[0], tmp[1], AES_BLOCK_SIZE); } } + else { + XMEMCPY(tmp[0], tmp[1], AES_BLOCK_SIZE); + } if (ret == 0) { if (dataSz >= AES_BLOCK_SIZE) { diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index bfb3bb92a..1f2c73383 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -2089,6 +2089,19 @@ int GetLength_ex(const byte* input, word32* inOutIdx, int* len, word32 maxIdx, * Note: 0 indicates indefinte length encoding *not* 0 bytes of length. */ word32 bytes = b & 0x7F; + int minLen; + + /* Calculate minimum length to be encoded with bytes. */ + if (b == 0x80) { + /* Indefinite length encoding - no length bytes. */ + minLen = 0; + } + else if (bytes == 1) { + minLen = 0x80; + } + else { + minLen = 1 << ((bytes - 1) * 8); + } /* Check the number of bytes required are available. */ if ((idx + bytes) > maxIdx) { @@ -2109,6 +2122,10 @@ int GetLength_ex(const byte* input, word32* inOutIdx, int* len, word32 maxIdx, if (length < 0) { return ASN_PARSE_E; } + /* Don't allow lengths that are longer than strictly required. */ + if (length < minLen) { + return ASN_PARSE_E; + } } else { /* Length in first byte. */ @@ -3122,6 +3139,42 @@ int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, word32 maxIdx) #endif } +#if (defined(HAVE_ECC) || !defined(NO_DSA)) && !defined(WOLFSSL_ASN_TEMPLATE) +static int GetIntPositive(mp_int* mpi, const byte* input, word32* inOutIdx, + word32 maxIdx) +{ + word32 idx = *inOutIdx; + int ret; + int length; + + ret = GetASNInt(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; + + if (((input[idx] & 0x80) == 0x80) && (input[idx - 1] != 0x00)) + return MP_INIT_E; + + if (mp_init(mpi) != MP_OKAY) + return MP_INIT_E; + + if (mp_read_unsigned_bin(mpi, input + idx, length) != 0) { + mp_clear(mpi); + return ASN_GETINT_E; + } + +#ifdef HAVE_WOLF_BIGINT + if (wc_bigint_from_unsigned_bin(&mpi->raw, input + idx, length) != 0) { + mp_clear(mpi); + return ASN_GETINT_E; + } +#endif /* HAVE_WOLF_BIGINT */ + + *inOutIdx = idx + length; + + return 0; +} +#endif /* (ECC || !NO_DSA) && !WOLFSSL_ASN_TEMPLATE */ + #ifndef WOLFSSL_ASN_TEMPLATE #if (!defined(WOLFSSL_KEY_GEN) && !defined(OPENSSL_EXTRA) && defined(RSA_LOW_MEM)) \ || defined(WOLFSSL_RSA_PUBLIC_ONLY) || (!defined(NO_DSA)) @@ -3737,6 +3790,12 @@ static word32 SetBitString16Bit(word16 val, byte* output) #endif #ifdef WOLFSSL_SHA512 static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3}; + #ifndef WOLFSSL_NOSHA512_224 + static const byte hashSha512_224hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 5}; + #endif + #ifndef WOLFSSL_NOSHA512_256 + static const byte hashSha512_256hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 6}; + #endif #endif #ifdef WOLFSSL_SHA3 #ifndef WOLFSSL_NOSHA3_224 @@ -4130,6 +4189,18 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) break; #endif #ifdef WOLFSSL_SHA512 + #ifndef WOLFSSL_NOSHA512_224 + case SHA512_224h: + oid = hashSha512_224hOid; + *oidSz = sizeof(hashSha512_224hOid); + break; + #endif + #ifndef WOLFSSL_NOSHA512_256 + case SHA512_256h: + oid = hashSha512_256hOid; + *oidSz = sizeof(hashSha512_256hOid); + break; + #endif case SHA512h: oid = hashSha512hOid; *oidSz = sizeof(hashSha512hOid); @@ -27119,11 +27190,11 @@ int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s) } #endif - if (GetInt(r, sig, &idx, sigLen) < 0) { + if (GetIntPositive(r, sig, &idx, sigLen) < 0) { return ASN_ECC_KEY_E; } - if (GetInt(s, sig, &idx, sigLen) < 0) { + if (GetIntPositive(s, sig, &idx, sigLen) < 0) { mp_clear(r); return ASN_ECC_KEY_E; } @@ -27142,6 +27213,7 @@ int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s) #else ASNGetData dataASN[dsaSigASN_Length]; word32 idx = 0; + int ret; /* Clear dynamic data and set mp_ints to put r and s into. */ XMEMSET(dataASN, 0, sizeof(dataASN)); @@ -27149,8 +27221,19 @@ int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s) GetASN_MP(&dataASN[DSASIGASN_IDX_S], s); /* Decode the DSA signature. */ - return GetASN_Items(dsaSigASN, dataASN, dsaSigASN_Length, 1, sig, &idx, - sigLen); + ret = GetASN_Items(dsaSigASN, dataASN, dsaSigASN_Length, 1, sig, &idx, + sigLen); +#ifndef NO_STRICT_ECDSA_LEN + /* sanity check that the index has been advanced all the way to the end of + * the buffer */ + if ((ret == 0) && (idx != sigLen)) { + mp_clear(r); + mp_clear(s); + ret = ASN_ECC_KEY_E; + } + + return ret; +#endif #endif /* WOLFSSL_ASN_TEMPLATE */ } #endif diff --git a/wolfcrypt/src/chacha20_poly1305.c b/wolfcrypt/src/chacha20_poly1305.c index 417b3e226..5ec856e99 100644 --- a/wolfcrypt/src/chacha20_poly1305.c +++ b/wolfcrypt/src/chacha20_poly1305.c @@ -60,7 +60,7 @@ int wc_ChaCha20Poly1305_Encrypt( /* Validate function arguments */ if (!inKey || !inIV || - !inPlaintext || !inPlaintextLen || + (inPlaintextLen > 0 && inPlaintext == NULL) || !outCiphertext || !outAuthTag) { @@ -93,7 +93,7 @@ int wc_ChaCha20Poly1305_Decrypt( /* Validate function arguments */ if (!inKey || !inIV || - !inCiphertext || !inCiphertextLen || + (inCiphertextLen > 0 && inCiphertext == NULL) || !inAuthTag || !outPlaintext) { diff --git a/wolfcrypt/src/curve25519.c b/wolfcrypt/src/curve25519.c index f4ba3fe49..16d6074e0 100644 --- a/wolfcrypt/src/curve25519.c +++ b/wolfcrypt/src/curve25519.c @@ -312,6 +312,18 @@ int wc_curve25519_shared_secret_ex(curve25519_key* private_key, RESTORE_VECTOR_REGISTERS(); } +#endif +#ifdef WOLFSSL_ECDHX_SHARED_NOT_ZERO + if (ret == 0) { + int i; + byte t = 0; + for (i = 0; i < CURVE25519_KEYSIZE; i++) { + t |= o.point[i]; + } + if (t == 0) { + ret = ECC_OUT_OF_RANGE_E; + } + } #endif if (ret != 0) { ForceZero(&o, sizeof(o)); @@ -444,7 +456,7 @@ int wc_curve25519_check_public(const byte* pub, word32 pubSz, int endian) if (endian == EC25519_LITTLE_ENDIAN) { /* Check for value of zero or one */ - for (i = pubSz - 1; i > 0; i--) { + for (i = CURVE25519_KEYSIZE - 1; i > 0; i--) { if (pub[i] != 0) break; } @@ -452,21 +464,41 @@ int wc_curve25519_check_public(const byte* pub, word32 pubSz, int endian) return ECC_BAD_ARG_E; /* Check high bit set */ - if (pub[CURVE25519_KEYSIZE-1] & 0x80) + if (pub[CURVE25519_KEYSIZE - 1] & 0x80) return ECC_OUT_OF_RANGE_E; + + /* Check for order-1 or higher. */ + if (pub[CURVE25519_KEYSIZE - 1] == 0x7f) { + for (i = CURVE25519_KEYSIZE - 2; i > 0; i--) { + if (pub[i] != 0xff) + break; + } + if (i == 0 && (pub[0] >= 0xec)) + return ECC_BAD_ARG_E; + } } else { /* Check for value of zero or one */ - for (i = 0; i < pubSz-1; i++) { + for (i = 0; i < CURVE25519_KEYSIZE - 1; i++) { if (pub[i] != 0) break; } - if (i == pubSz - 1 && (pub[i] == 0 || pub[i] == 1)) + if (i == CURVE25519_KEYSIZE - 1 && (pub[i] == 0 || pub[i] == 1)) return ECC_BAD_ARG_E; /* Check high bit set */ if (pub[0] & 0x80) return ECC_OUT_OF_RANGE_E; + + /* Check for order-1 or higher. */ + if (pub[0] == 0x7f) { + for (i = 1; i < CURVE25519_KEYSIZE - 1; i++) { + if (pub[i] != 0) + break; + } + if (i == CURVE25519_KEYSIZE - 1 && (pub[i] >= 0xec)) + return ECC_BAD_ARG_E; + } } return 0; diff --git a/wolfcrypt/src/curve448.c b/wolfcrypt/src/curve448.c index 43c8dd83a..6a084f134 100644 --- a/wolfcrypt/src/curve448.c +++ b/wolfcrypt/src/curve448.c @@ -170,6 +170,17 @@ int wc_curve448_shared_secret_ex(curve448_key* private_key, if (ret == 0) { ret = curve448(o, private_key->k, public_key->p); } +#ifdef WOLFSSL_ECDHX_SHARED_NOT_ZERO + if (ret == 0) { + byte t = 0; + for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) { + t |= o[i]; + } + if (t == 0) { + ret = ECC_OUT_OF_RANGE_E; + } + } +#endif if (ret == 0) { if (endian == EC448_BIG_ENDIAN) { /* put shared secret key in Big Endian format */ @@ -353,7 +364,7 @@ int wc_curve448_check_public(const byte* pub, word32 pubSz, int endian) if (ret == 0) { if (endian == EC448_LITTLE_ENDIAN) { /* Check for value of zero or one */ - for (i = pubSz - 1; i > 0; i--) { + for (i = CURVE448_PUB_KEY_SIZE - 1; i > 0; i--) { if (pub[i] != 0) { break; } @@ -361,17 +372,56 @@ int wc_curve448_check_public(const byte* pub, word32 pubSz, int endian) if ((i == 0) && (pub[0] == 0 || pub[0] == 1)) { return ECC_BAD_ARG_E; } + /* Check for order-1 or higher */ + for (i = CURVE448_PUB_KEY_SIZE - 1; i > 28; i--) { + if (pub[i] != 0xff) { + break; + } + } + if ((i == 28) && (pub[i] == 0xff)) { + return ECC_BAD_ARG_E; + } + if ((i == 28) && (pub[i] == 0xfe)) { + for (--i; i > 0; i--) { + if (pub[i] != 0xff) { + break; + } + } + if ((i == 0) && (pub[i] >= 0xfe)) { + return ECC_BAD_ARG_E; + } + } } else { /* Check for value of zero or one */ - for (i = 0; i < pubSz-1; i++) { + for (i = 0; i < CURVE448_PUB_KEY_SIZE-1; i++) { if (pub[i] != 0) { break; } } - if ((i == pubSz - 1) && (pub[i] == 0 || pub[i] == 1)) { + if ((i == CURVE448_PUB_KEY_SIZE - 1) && + (pub[i] == 0 || pub[i] == 1)) { ret = ECC_BAD_ARG_E; } + /* Check for order-1 or higher */ + for (i = 0; i < 27; i++) { + if (pub[i] != 0xff) { + break; + } + } + if ((i == 27) && (pub[i] == 0xff)) { + return ECC_BAD_ARG_E; + } + if ((i == 27) && (pub[i] == 0xfe)) { + for (++i; i < CURVE448_PUB_KEY_SIZE - 1; i--) { + if (pub[i] != 0xff) { + break; + } + } + if ((i == CURVE448_PUB_KEY_SIZE) && (pub[i] >= 0xfe)) { + return ECC_BAD_ARG_E; + } + } } } diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index fa5eb0ac0..28e8013eb 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -10011,7 +10011,7 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, err = mp_read_unsigned_bin(key->pubkey.x, (const byte*)qx, key->dp->size); - if (mp_iszero(key->pubkey.x) || mp_isneg(key->pubkey.x)) { + if (mp_isneg(key->pubkey.x)) { WOLFSSL_MSG("Invalid Qx"); err = BAD_FUNC_ARG; } @@ -10025,12 +10025,19 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, err = mp_read_unsigned_bin(key->pubkey.y, (const byte*)qy, key->dp->size); - if (mp_iszero(key->pubkey.y) || mp_isneg(key->pubkey.y)) { + if (mp_isneg(key->pubkey.y)) { WOLFSSL_MSG("Invalid Qy"); err = BAD_FUNC_ARG; } } + if (err == MP_OKAY) { + if (mp_iszero(key->pubkey.x) && mp_iszero(key->pubkey.y)) { + WOLFSSL_MSG("Invalid Qx and Qy"); + err = BAD_FUNC_ARG; + } + } + if (err == MP_OKAY) err = mp_set(key->pubkey.z, 1); diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index 628394774..9c5e55bf8 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -572,6 +572,15 @@ static int ed25519_verify_msg_update_with_sha(const byte* msgSegment, return ed25519_hash_update(key, sha, msgSegment, msgSegmentLen); } +/* Low part of order in big endian. */ +static const byte ed25519_low_order[] = { + 0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7, 0x9c, 0xd6, + 0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed +}; + +#define ED25519_SIG_LOW_ORDER_IDX \ + ((int)(ED25519_SIG_SIZE/2 + sizeof(ed25519_low_order) - 1)) + /* sig is array of bytes containing the signature sigLen is the length of sig byte array @@ -599,8 +608,39 @@ static int ed25519_verify_msg_final_with_sha(const byte* sig, word32 sigLen, *res = 0; /* check on basics needed to verify signature */ - if (sigLen != ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224)) + if (sigLen != ED25519_SIG_SIZE) return BAD_FUNC_ARG; + /* S is not larger or equal to the order: + * 2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed + * = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed + */ + if (sig[ED25519_SIG_SIZE-1] > 0x10) + return BAD_FUNC_ARG; + if (sig[ED25519_SIG_SIZE-1] == 0x10) { + int i = ED25519_SIG_SIZE-1; + int j; + + /* Check high zeros. */ + for (--i; i > ED25519_SIG_LOW_ORDER_IDX; i--) { + if (sig[i] > 0x00) + break; + } + /* Did we see all zeros up to lower order index? */ + if (i == ED25519_SIG_LOW_ORDER_IDX) { + /* Check lower part. */ + for (j = 0; j < (int)sizeof(ed25519_low_order); j++, i--) { + /* Check smaller. */ + if (sig[i] < ed25519_low_order[j]) + break; + /* Check bigger. */ + if (sig[i] > ed25519_low_order[j]) + return BAD_FUNC_ARG; + } + /* Check equal - all bytes match. */ + if (i == ED25519_SIG_SIZE/2 - 1) + return BAD_FUNC_ARG; + } + } /* uncompress A (public key), test if valid, and negate it */ #ifndef FREESCALE_LTC_ECC diff --git a/wolfcrypt/src/ed448.c b/wolfcrypt/src/ed448.c index cdbb3111b..2a2c41e59 100644 --- a/wolfcrypt/src/ed448.c +++ b/wolfcrypt/src/ed448.c @@ -547,6 +547,18 @@ static int ed448_verify_msg_update_with_sha(const byte* msgSegment, return ed448_hash_update(key, sha, msgSegment, msgSegmentLen); } +/* Order of the ed448 curve - little endian. */ +static const byte ed448_order[] = { + 0xf3, 0x44, 0x58, 0xab, 0x92, 0xc2, 0x78, 0x23, + 0x55, 0x8f, 0xc5, 0x8d, 0x72, 0xc2, 0x6c, 0x21, + 0x90, 0x36, 0xd6, 0xae, 0x49, 0xdb, 0x4e, 0xc4, + 0xe9, 0x23, 0xca, 0x7c, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x00 +}; + /* Verify the message using the ed448 public key. * * sig [in] Signature to verify. @@ -566,6 +578,7 @@ static int ed448_verify_msg_final_with_sha(const byte* sig, word32 sigLen, ge448_p2 A; ge448_p2 R; int ret; + int i; /* sanity check on arguments */ if ((sig == NULL) || (res == NULL) || (key == NULL)) @@ -577,6 +590,18 @@ static int ed448_verify_msg_final_with_sha(const byte* sig, word32 sigLen, /* check on basics needed to verify signature */ if (sigLen != ED448_SIG_SIZE) return BAD_FUNC_ARG; + /* Check S is not larger than or equal to order. */ + for (i = (int)sizeof(ed448_order) - 1; i >= 0; i--) { + /* Bigger than order. */ + if (sig[ED448_SIG_SIZE/2 + i] > ed448_order[i]) + return BAD_FUNC_ARG; + /* Less than order. */ + if (sig[ED448_SIG_SIZE/2 + i] < ed448_order[i]) + break; + } + /* Same value as order. */ + if (i == -1) + return BAD_FUNC_ARG; /* uncompress A (public key), test if valid, and negate it */ if (ge448_from_bytes_negate_vartime(&A, key->p) != 0) diff --git a/wolfcrypt/src/ge_operations.c b/wolfcrypt/src/ge_operations.c index aedfc53ac..379bd8fd7 100644 --- a/wolfcrypt/src/ge_operations.c +++ b/wolfcrypt/src/ge_operations.c @@ -59,8 +59,8 @@ static void ge_p2_0(ge_p2 *h); #ifndef CURVED25519_ASM static void ge_precomp_0(ge_precomp *h); -#endif static void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p); +#endif static WC_INLINE void ge_p3_to_cached(ge_cached *r,const ge_p3 *p); static void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p); static WC_INLINE void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p); @@ -9725,9 +9725,13 @@ r = 2 * p static void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p) { - ge_p2 q; - ge_p3_to_p2(&q,p); - ge_p2_dbl(r,&q); +#ifndef CURVED25519_ASM + ge_p2 q; + ge_p3_to_p2(&q,p); + ge_p2_dbl(r,&q); +#else + fe_ge_dbl(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z); +#endif } @@ -9772,12 +9776,14 @@ static WC_INLINE void ge_p3_to_cached(ge_cached *r,const ge_p3 *p) r = p */ +#ifndef CURVED25519_ASM static void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p) { fe_copy(r->X,p->X); fe_copy(r->Y,p->Y); fe_copy(r->Z,p->Z); } +#endif /* ge p3 tobytes */ diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index cbdd3f661..0dda84250 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -4905,6 +4905,7 @@ int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng) mp_int b, c; int ix, err, res; byte* base = NULL; + word32 bitSz = 0; word32 baseSz = 0; /* default to no */ @@ -4915,6 +4916,10 @@ int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng) return MP_VAL; } + if (a->sign == MP_NEG) { + return MP_VAL; + } + if (mp_isone(a)) { *result = MP_NO; return MP_OKAY; @@ -4947,8 +4952,9 @@ int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng) return err; } - baseSz = mp_count_bits(a); - baseSz = (baseSz / 8) + ((baseSz % 8) ? 1 : 0); + bitSz = mp_count_bits(a); + baseSz = (bitSz / 8) + ((bitSz % 8) ? 1 : 0); + bitSz %= 8; base = (byte*)XMALLOC(baseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (base == NULL) { @@ -4968,6 +4974,11 @@ int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng) goto LBL_B; } + /* Clear bits higher than those in a. */ + if (bitSz > 0) { + base[0] &= (1 << bitSz) - 1; + } + if ((err = mp_read_unsigned_bin(&b, base, baseSz)) != MP_OKAY) { goto LBL_B; } diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 7e6e3cdda..6da4c740d 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -986,6 +986,18 @@ static int RsaMGF(int type, byte* seed, word32 seedSz, byte* out, case WC_MGF1SHA512: ret = RsaMGF1(WC_HASH_TYPE_SHA512, seed, seedSz, out, outSz, heap); break; + #ifndef WOLFSSL_NOSHA512_224 + case WC_MGF1SHA512_224: + ret = RsaMGF1(WC_HASH_TYPE_SHA512_224, seed, seedSz, out, outSz, + heap); + break; + #endif + #ifndef WOLFSSL_NOSHA512_256 + case WC_MGF1SHA512_256: + ret = RsaMGF1(WC_HASH_TYPE_SHA512_256, seed, seedSz, out, outSz, + heap); + break; + #endif #endif default: WOLFSSL_MSG("Unknown MGF type: check build options"); @@ -1770,7 +1782,7 @@ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, invalid |= ctMaskNotEq(pkcsBlock[1], padValue); *output = (byte *)(pkcsBlock + i); - ret = ((int)(byte)~invalid) & (pkcsBlockLen - i); + ret = ((int)-1 + (int)(invalid >> 7)) & (pkcsBlockLen - i); } #endif @@ -2277,8 +2289,13 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, #endif #endif int ret = 0; - word32 keyLen = 0; #endif + word32 keyLen = wc_RsaEncryptSize(key); + + if (inLen > keyLen) { + WOLFSSL_MSG("Expected that inLen be no longer RSA key length"); + return BAD_FUNC_ARG; + } if (mp_iseven(&key->n)) { return MP_VAL; @@ -2578,7 +2595,6 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, } if (ret == 0) { - keyLen = wc_RsaEncryptSize(key); if (keyLen > *outLen) ret = RSA_BUFFER_E; } @@ -2591,7 +2607,6 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, #else (void)type; (void)key; - (void)keyLen; XMEMCPY(out, in, inLen); *outLen = inLen; #endif @@ -2885,8 +2900,9 @@ int cc310_RsaSSL_Verify(const byte* in, word32 inLen, byte* sig, } #endif /* WOLFSSL_CRYPTOCELL */ -int wc_RsaFunction(const byte* in, word32 inLen, byte* out, - word32* outLen, int type, RsaKey* key, WC_RNG* rng) +static int wc_RsaFunction_ex(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng, + int checkSmallCt) { int ret = 0; @@ -2944,7 +2960,7 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, } if (ret == 0) { /* check c > 1 */ - if (mp_cmp_d(c, 1) != MP_GT) + if (checkSmallCt && (mp_cmp_d(c, 1) != MP_GT)) ret = RSA_OUT_OF_RANGE_E; } if (ret == 0) { @@ -2971,6 +2987,8 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, } #endif /* NO_RSA_BOUNDS_CHECK */ #endif +#else + (void)checkSmallCt; #endif #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) @@ -3012,6 +3030,12 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, #endif /* WOLF_CRYPTO_CB_ONLY_RSA */ } +int wc_RsaFunction(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + /* Always check for ciphertext of 0 or 1. (Should't for OAEP decrypt.) */ + return wc_RsaFunction_ex(in, inLen, out, outLen, type, key, rng, 1); +} #ifndef WOLFSSL_RSA_VERIFY_ONLY /* Internal Wrappers */ @@ -3260,10 +3284,12 @@ static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out, case RSA_STATE_DECRYPT_EXPTMOD: #if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE) - ret = wc_RsaFunction(key->data, inLen, key->data, &key->dataLen, - rsa_type, key, rng); + ret = wc_RsaFunction_ex(key->data, inLen, key->data, &key->dataLen, + rsa_type, key, rng, + pad_type != WC_RSA_OAEP_PAD); #else - ret = wc_RsaFunction(in, inLen, out, &key->dataLen, rsa_type, key, rng); + ret = wc_RsaFunction_ex(in, inLen, out, &key->dataLen, rsa_type, key, + rng, pad_type != WC_RSA_OAEP_PAD); #endif if (ret >= 0 || ret == WC_PENDING_E) { @@ -3319,7 +3345,9 @@ static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out, #if !defined(WOLFSSL_RSA_VERIFY_ONLY) ret = ctMaskSelInt(ctMaskLTE(ret, outLen), ret, RSA_BUFFER_E); + #ifndef WOLFSSL_RSA_DECRYPT_TO_0_LEN ret = ctMaskSelInt(ctMaskNotEq(ret, 0), ret, RSA_BUFFER_E); + #endif #else if (outLen < (word32)ret) ret = RSA_BUFFER_E; diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index 72bd0eb3c..284b6bc6a 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -6712,8 +6712,13 @@ int sp_div(sp_int* a, sp_int* d, sp_int* r, sp_int* rem) if ((err == MP_OKAY) && (r != NULL) && (r->size < a->used - d->used + 2)) { err = MP_VAL; } - if ((err == MP_OKAY) && (rem != NULL) && (rem->size < a->used + 1)) { - err = MP_VAL; + if ((err == MP_OKAY) && (rem != NULL)) { + if ((a->used <= d->used) && (rem->size < a->used + 1)) { + err = MP_VAL; + } + else if ((a->used > d->used) && (rem->size < d->used + 1)) { + err = MP_VAL; + } } /* May need to shift number being divided left into a new word. */ if ((err == MP_OKAY) && (a->used == SP_INT_DIGITS)) { @@ -11528,6 +11533,9 @@ int sp_mod_2d(sp_int* a, int e, sp_int* r) if (a != r) { XMEMCPY(r->dp, a->dp, digits * sizeof(sp_int_digit)); r->used = a->used; + #ifdef WOLFSSL_SP_INT_NEGATIVE + r->sign = a->sign; + #endif } #ifndef WOLFSSL_SP_INT_NEGATIVE if (digits <= a->used) @@ -15632,6 +15640,12 @@ int sp_prime_is_prime_ex(sp_int* a, int t, int* result, WC_RNG* rng) err = MP_VAL; } +#ifdef WOLFSSL_SP_INT_NEGATIVE + if ((err == MP_OKAY) && (a->sign == MP_NEG)) { + err = MP_VAL; + } +#endif + if ((err == MP_OKAY) && sp_isone(a)) { ret = MP_NO; haveRes = 1; @@ -15700,6 +15714,7 @@ int sp_prime_is_prime_ex(sp_int* a, int t, int* result, WC_RNG* rng) /* Ensure the top word has no more bits than necessary. */ if (bits > 0) { b->dp[b->used - 1] &= ((sp_digit)1 << bits) - 1; + sp_clamp(b); } if ((sp_cmp_d(b, 2) != MP_GT) || (_sp_cmp(b, c) != MP_LT)) { diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 22fe61dca..c9a557b9b 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -5069,6 +5069,8 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) if (a == NULL || result == NULL || rng == NULL) return FP_VAL; + if (a->sign == FP_NEG) + return FP_VAL; if (fp_isone(a)) { *result = FP_NO; @@ -5107,12 +5109,14 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) byte* base; #endif word32 baseSz; + word32 bitSz; int err; - baseSz = fp_count_bits(a); + bitSz = fp_count_bits(a); /* The base size is the number of bits / 8. One is added if the number * of bits isn't an even 8. */ - baseSz = (baseSz / 8) + ((baseSz % 8) ? 1 : 0); + baseSz = (bitSz / 8) + ((bitSz % 8) ? 1 : 0); + bitSz %= 8; #ifndef WOLFSSL_SMALL_STACK if (baseSz > sizeof(base)) @@ -5153,6 +5157,9 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) return err; } + if (bitSz != 0) + base[0] &= (1 << bitSz) - 1; + err = fp_read_unsigned_bin(b, base, baseSz); if (err != FP_OKAY) { #ifdef WOLFSSL_SMALL_STACK diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 04c6b5838..be79698c3 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -5860,8 +5860,8 @@ WOLFSSL_TEST_SUBROUTINE int chacha20_poly1305_aead_test(void) sizeof(plaintext1), generatedCiphertext, NULL); if (err != BAD_FUNC_ARG) return -4904; - err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), plaintext1, - 0, generatedCiphertext, generatedAuthTag); + err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), NULL, + sizeof(plaintext1), generatedCiphertext, generatedAuthTag); if (err != BAD_FUNC_ARG) return -4905; /* Decrypt */ @@ -5885,8 +5885,8 @@ WOLFSSL_TEST_SUBROUTINE int chacha20_poly1305_aead_test(void) sizeof(cipher2), authTag2, NULL); if (err != BAD_FUNC_ARG) return -4910; - err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), cipher2, - 0, authTag2, generatedPlaintext); + err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), NULL, + sizeof(cipher2), authTag2, generatedPlaintext); if (err != BAD_FUNC_ARG) return -4911; diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 70697f5a5..8d3c243a8 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -329,12 +329,14 @@ WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, */ /* Mask Generation Function Identifiers */ -#define WC_MGF1NONE 0 -#define WC_MGF1SHA1 26 -#define WC_MGF1SHA224 4 -#define WC_MGF1SHA256 1 -#define WC_MGF1SHA384 2 -#define WC_MGF1SHA512 3 +#define WC_MGF1NONE 0 +#define WC_MGF1SHA1 26 +#define WC_MGF1SHA224 4 +#define WC_MGF1SHA256 1 +#define WC_MGF1SHA384 2 +#define WC_MGF1SHA512 3 +#define WC_MGF1SHA512_224 5 +#define WC_MGF1SHA512_256 6 /* Padding types */ #define WC_RSA_PKCSV15_PAD 0