diff --git a/jni/jni_rsa.c b/jni/jni_rsa.c index fce01c72..52c12682 100644 --- a/jni/jni_rsa.c +++ b/jni/jni_rsa.c @@ -46,6 +46,11 @@ #define RNG WC_RNG #endif +/* RSA_PSS_SALT_LEN_DEFAULT not in FIPSv2 */ +#ifndef RSA_PSS_SALT_LEN_DEFAULT + #define RSA_PSS_SALT_LEN_DEFAULT (-1) +#endif + JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Rsa_mallocNativeStruct( JNIEnv* env, jobject this) @@ -1717,11 +1722,29 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPSS_1VerifyCheck( if (ret == 0) { XMEMSET(output, 0, outputSz); - ret = wc_RsaPSS_VerifyCheck(signature, signatureSz, output, outputSz, - digest, digestSz, (enum wc_HashType)hashType, mgf, key); - } - if (ret > 0) { - result = JNI_TRUE; + if ((saltLen == RSA_PSS_SALT_LEN_DEFAULT) || + (saltLen == (int)digestSz)) { + + ret = wc_RsaPSS_VerifyCheck(signature, signatureSz, output, + outputSz, digest, digestSz, (enum wc_HashType)hashType, + mgf, key); + if (ret > 0) { + result = JNI_TRUE; + } + } + else { + /* Non-default salt length */ + ret = wc_RsaPSS_Verify_ex(signature, signatureSz, output, + outputSz, (enum wc_HashType)hashType, mgf, saltLen, key); + if (ret > 0) { + /* Verify PSS padding against the provided digest */ + ret = wc_RsaPSS_CheckPadding_ex(digest, digestSz, output, + (word32)ret, (enum wc_HashType)hashType, saltLen, 0); + if (ret == 0) { + result = JNI_TRUE; + } + } + } } LogStr("wc_RsaPSS_VerifyCheck(sig, sigSz, out, outSz, digest, " diff --git a/src/test/java/com/wolfssl/wolfcrypt/test/RsaTest.java b/src/test/java/com/wolfssl/wolfcrypt/test/RsaTest.java index 86aebf6c..29303e82 100644 --- a/src/test/java/com/wolfssl/wolfcrypt/test/RsaTest.java +++ b/src/test/java/com/wolfssl/wolfcrypt/test/RsaTest.java @@ -1261,6 +1261,44 @@ public class RsaTest { digest, WolfCrypt.WC_HASH_TYPE_SHA256, Rsa.WC_MGF1SHA256, 32); assertTrue("RSA-PSS check verification failed", verified); + /* Test with non-default salt length, + * saltLen != digest length must be honored on verify */ + signature = key.rsaPssSign(digest, + WolfCrypt.WC_HASH_TYPE_SHA256, Rsa.WC_MGF1SHA256, 16, rng); + assertNotNull(signature); + assertTrue(signature.length > 0); + + verified = key.rsaPssVerifyWithDigest(signature, message, + digest, WolfCrypt.WC_HASH_TYPE_SHA256, Rsa.WC_MGF1SHA256, 16); + assertTrue("RSA-PSS check verification failed with " + + "non-default salt length", verified); + + /* Verification with wrong salt length should fail */ + try { + verified = key.rsaPssVerifyWithDigest(signature, message, + digest, WolfCrypt.WC_HASH_TYPE_SHA256, + Rsa.WC_MGF1SHA256, 32); + } catch (WolfCryptException e) { + /* native error acceptable here, treat as not verified */ + verified = false; + } + assertFalse("RSA-PSS check verification passed with " + + "mismatched salt length", verified); + + /* Test special value RSA_PSS_SALT_LEN_DEFAULT, sign uses + * salt length equal to digest length */ + signature = key.rsaPssSign(digest, + WolfCrypt.WC_HASH_TYPE_SHA256, Rsa.WC_MGF1SHA256, + Rsa.RSA_PSS_SALT_LEN_DEFAULT, rng); + assertNotNull(signature); + assertTrue(signature.length > 0); + + verified = key.rsaPssVerifyWithDigest(signature, message, + digest, WolfCrypt.WC_HASH_TYPE_SHA256, Rsa.WC_MGF1SHA256, + Rsa.RSA_PSS_SALT_LEN_DEFAULT); + assertTrue("RSA-PSS check verification failed with " + + "RSA_PSS_SALT_LEN_DEFAULT", verified); + } catch (Exception e) { fail("RSA-PSS check verification test failed: " + e.getMessage()); }