Merge pull request #256 from cconlon/fenrirAug13
Fenrir fixes for AES-GCM/GMAC and RSA-PSS JNI wrapperspull/278/head
commit
a969ccbeea
|
|
@ -200,6 +200,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_AesGcm_wc_1AesGcmEncrypt
|
|||
|
||||
/* in may be null, users might only pass in AAD to generate tag */
|
||||
if (authTagSz > AES_BLOCK_SIZE || iv == NULL || ivSz == 0 ||
|
||||
(inLen != 0 && in == NULL) ||
|
||||
((authTagSz > 0) && (authTag == NULL)) ||
|
||||
((authInSz > 0) && (authIn == NULL))) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_AesGmac_wc_1Gmac(
|
|||
byte* iv = NULL;
|
||||
byte* authIn = NULL;
|
||||
byte* authTag = NULL;
|
||||
word32 keySz, ivSz, authInSz, authTagSz;
|
||||
word32 keySz = 0, ivSz = 0, authInSz = 0, authTagSz = 0;
|
||||
|
||||
key = getByteArray(env, key_object);
|
||||
iv = getByteArray(env, iv_object);
|
||||
|
|
@ -294,7 +294,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_AesGmac_wc_1GmacVerify(
|
|||
byte* iv = NULL;
|
||||
byte* authIn = NULL;
|
||||
byte* authTag = NULL;
|
||||
word32 keySz, ivSz, authInSz, authTagSz;
|
||||
word32 keySz = 0, ivSz = 0, authInSz = 0, authTagSz = 0;
|
||||
|
||||
key = getByteArray(env, key_object);
|
||||
iv = getByteArray(env, iv_object);
|
||||
|
|
|
|||
|
|
@ -1725,6 +1725,10 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPSS_1VerifyCheck(
|
|||
}
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
throwWolfCryptExceptionFromError(env, ret);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
XMEMSET(output, 0, outputSz);
|
||||
|
||||
|
|
@ -1737,6 +1741,11 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPSS_1VerifyCheck(
|
|||
if (ret > 0) {
|
||||
result = JNI_TRUE;
|
||||
}
|
||||
/* PSS decode of a bad signature fails with data dependent
|
||||
* error codes, all map to false, only MEMORY_E throws */
|
||||
else if (ret == MEMORY_E) {
|
||||
throwWolfCryptExceptionFromError(env, ret);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Non-default salt length */
|
||||
|
|
@ -1749,6 +1758,12 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPSS_1VerifyCheck(
|
|||
if (ret == 0) {
|
||||
result = JNI_TRUE;
|
||||
}
|
||||
else if (ret == MEMORY_E) {
|
||||
throwWolfCryptExceptionFromError(env, ret);
|
||||
}
|
||||
}
|
||||
else if (ret == MEMORY_E) {
|
||||
throwWolfCryptExceptionFromError(env, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,15 +206,21 @@ public class AesGmac extends NativeStruct {
|
|||
* @param authIn data that was authenticated
|
||||
* @param authTag authentication tag to verify
|
||||
*
|
||||
* @return true if verification succeeds, false otherwise
|
||||
* @return true if verification succeeds, false if the authentication
|
||||
* tag does not match
|
||||
*
|
||||
* @throws WolfCryptException if native operation fails
|
||||
* @throws WolfCryptException if the native operation fails for any
|
||||
* reason other than authentication tag mismatch
|
||||
*/
|
||||
public static synchronized boolean verify(byte[] key, byte[] iv,
|
||||
byte[] authIn, byte[] authTag) throws WolfCryptException {
|
||||
|
||||
int ret = wc_GmacVerify(key, iv, authIn, authTag);
|
||||
|
||||
if ((ret != 0) && (ret != WolfCryptError.AES_GCM_AUTH_E.getCode())) {
|
||||
throw new WolfCryptException(ret);
|
||||
}
|
||||
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -921,9 +921,11 @@ public class Rsa extends NativeStruct {
|
|||
* @param mgf mask generation function (WC_MGF1SHA256 for MGF1 with SHA-256)
|
||||
* @param saltLen salt length in bytes, or special value
|
||||
*
|
||||
* @return true if signature is valid, false otherwise
|
||||
* @return true if signature is valid, false if the signature does not
|
||||
* verify against the provided digest
|
||||
*
|
||||
* @throws WolfCryptException if native operation fails
|
||||
* @throws WolfCryptException on invalid arguments or memory
|
||||
* allocation failure
|
||||
* @throws IllegalStateException if public key has not been set, if object
|
||||
* fails to initialize, or if releaseNativeStruct() has been
|
||||
* called and object has been released.
|
||||
|
|
|
|||
|
|
@ -133,6 +133,34 @@ public class AesGmacTest {
|
|||
assertFalse(shouldFail);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVerifyInvalidArgsShouldThrow() {
|
||||
if (!FeatureDetect.AesGmacEnabled()) {
|
||||
/* skip test if AES-GMAC is not compiled in native wolfCrypt */
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] iv = new byte[12];
|
||||
byte[] authIn = new byte[16];
|
||||
byte[] authTag = new byte[Aes.BLOCK_SIZE];
|
||||
|
||||
/* null key is an operational error, not a tag mismatch */
|
||||
try {
|
||||
AesGmac.verify(null, iv, authIn, authTag);
|
||||
fail("verify() should have thrown for null key");
|
||||
} catch (WolfCryptException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
/* invalid key length is an operational error, not a tag mismatch */
|
||||
try {
|
||||
AesGmac.verify(new byte[5], iv, authIn, authTag);
|
||||
fail("verify() should have thrown for invalid key length");
|
||||
} catch (WolfCryptException e) {
|
||||
/* expected */
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAes128GmacTestVector2() {
|
||||
if (!FeatureDetect.AesGmacEnabled()) {
|
||||
|
|
|
|||
|
|
@ -1379,6 +1379,44 @@ public class RsaTest {
|
|||
assertTrue("RSA-PSS check verification failed with " +
|
||||
"RSA_PSS_SALT_LEN_DEFAULT", verified);
|
||||
|
||||
/* Operational errors must throw, not report false */
|
||||
try {
|
||||
key.rsaPssVerifyWithDigest(null, message, digest,
|
||||
WolfCrypt.WC_HASH_TYPE_SHA256, Rsa.WC_MGF1SHA256, 32);
|
||||
fail("rsaPssVerifyWithDigest should have thrown for " +
|
||||
"null signature");
|
||||
} catch (WolfCryptException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
/* Corrupted signatures must report false, not throw. PSS
|
||||
* decode of garbage fails with position dependent error
|
||||
* codes, exercise first, middle and last bytes */
|
||||
signature = key.rsaPssSign(digest,
|
||||
WolfCrypt.WC_HASH_TYPE_SHA256, Rsa.WC_MGF1SHA256, 32, rng);
|
||||
int[] flipPos = new int[] { 0, signature.length / 2,
|
||||
signature.length - 1 };
|
||||
for (int pos : flipPos) {
|
||||
byte[] badSig = signature.clone();
|
||||
badSig[pos] ^= (byte)0x80;
|
||||
verified = key.rsaPssVerifyWithDigest(badSig, message,
|
||||
digest, WolfCrypt.WC_HASH_TYPE_SHA256,
|
||||
Rsa.WC_MGF1SHA256, 32);
|
||||
assertFalse("corrupted RSA-PSS signature verified, " +
|
||||
"flipped byte " + pos, verified);
|
||||
}
|
||||
|
||||
/* Mismatched digest must report false, not throw */
|
||||
signature = key.rsaPssSign(digest,
|
||||
WolfCrypt.WC_HASH_TYPE_SHA256, Rsa.WC_MGF1SHA256, 32, rng);
|
||||
byte[] wrongDigest = digest.clone();
|
||||
wrongDigest[0] ^= 1;
|
||||
verified = key.rsaPssVerifyWithDigest(signature, message,
|
||||
wrongDigest, WolfCrypt.WC_HASH_TYPE_SHA256,
|
||||
Rsa.WC_MGF1SHA256, 32);
|
||||
assertFalse("RSA-PSS signature verified with wrong digest",
|
||||
verified);
|
||||
|
||||
} catch (Exception e) {
|
||||
fail("RSA-PSS check verification test failed: " + e.getMessage());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue