From 9f11aa8af938c184d15253f872cca7278e310c64 Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Tue, 27 Jul 2021 11:46:39 +0200 Subject: [PATCH 1/2] Fix out of bounds when trying to get a pointer to empty array --- CHANGELOG.md | 1 + ...ticatedEncryptionWithAssociatedDataTest.kt | 153 ++++++++++++++++++ .../kotlin/crypto/util/ConversionUtil.kt | 8 +- 3 files changed, 161 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08eb558..44fd029 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ (All dates are DD.MM.YYYY) #### 0.8.5-SNAPSHOT +- Fix array out of bounds on native when trying to get a pointer to empty array. Return null instead. #### 0.8.4 - 19.7.2021 - Bump to kotlin 1.5.21 diff --git a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/aead/AuthenticatedEncryptionWithAssociatedDataTest.kt b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/aead/AuthenticatedEncryptionWithAssociatedDataTest.kt index 38ebae3..7e1dbf1 100644 --- a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/aead/AuthenticatedEncryptionWithAssociatedDataTest.kt +++ b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/aead/AuthenticatedEncryptionWithAssociatedDataTest.kt @@ -66,6 +66,159 @@ class AuthenticatedEncryptionWithAssociatedDataTest { } } + @Test + fun testEmptyAssociatedData() { + val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " + + "only one tip for the future, sunscreen would be it.").encodeToUByteArray() + + val associatedData = ubyteArrayOf() + + val key = ubyteArrayOf( + 0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U, + 0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU, + 0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U, + 0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU, + ) + + val nonce = ubyteArrayOf( + 0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, + 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, + 0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, + ) + + val encrypted = AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfEncrypt( + message, + associatedData, + nonce, + key + ) + val decrypted = AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfDecrypt( + encrypted, + associatedData, + nonce, + key + ) + assertTrue { + message.contentEquals(decrypted) + } + + assertFailsWith(AeadCorrupedOrTamperedDataException::class) { + val tamperedTag = encrypted.copyOf() + tamperedTag[3] = 0U + tamperedTag[1] = 0U + tamperedTag[0] = 0U + AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfDecrypt( + tamperedTag, + associatedData, + nonce, + key + ) + } + } + + @Test + fun testEmptyMessage() = runTest { + LibsodiumInitializer.initializeWithCallback { + val message = ubyteArrayOf() + + val associatedData = ubyteArrayOf( + 0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U + ) + val key = ubyteArrayOf( + 0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U, + 0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU, + 0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U, + 0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU, + ) + + val nonce = ubyteArrayOf( + 0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, + 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, + 0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, + ) + + val encrypted = AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfEncrypt( + message, + associatedData, + nonce, + key + ) + val decrypted = AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfDecrypt( + encrypted, + associatedData, + nonce, + key + ) + assertTrue { + message.contentEquals(decrypted) + } + + assertFailsWith(AeadCorrupedOrTamperedDataException::class) { + val tamperedTag = encrypted.copyOf() + tamperedTag[3] = 0U + tamperedTag[1] = 0U + tamperedTag[0] = 0U + AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfDecrypt( + tamperedTag, + associatedData, + nonce, + key + ) + } + } + } + + @Test + fun testEmptyCombination() = runTest { + LibsodiumInitializer.initializeWithCallback { + val message = ubyteArrayOf() + + val associatedData = ubyteArrayOf() + + val key = ubyteArrayOf( + 0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U, + 0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU, + 0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U, + 0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU, + ) + + val nonce = ubyteArrayOf( + 0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, + 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, + 0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, + ) + + val encrypted = AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfEncrypt( + message, + associatedData, + nonce, + key + ) + val decrypted = AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfDecrypt( + encrypted, + associatedData, + nonce, + key + ) + assertTrue { + message.contentEquals(decrypted) + } + + assertFailsWith(AeadCorrupedOrTamperedDataException::class) { + val tamperedTag = encrypted.copyOf() + tamperedTag[3] = 0U + tamperedTag[1] = 0U + tamperedTag[0] = 0U + AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfDecrypt( + tamperedTag, + associatedData, + nonce, + key + ) + } + } + } + @Test fun testXChaCha20Poly1305IeftDetached() = runTest { LibsodiumInitializer.initializeWithCallback { diff --git a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/ConversionUtil.kt b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/ConversionUtil.kt index 8964c2b..360c7d7 100644 --- a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/ConversionUtil.kt +++ b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/ConversionUtil.kt @@ -11,4 +11,10 @@ import kotlinx.cinterop.toCPointer * ugljesa.jovanovic@ionspin.com * on 27-Aug-2020 */ -fun Pinned.toPtr() : CPointer? = addressOf(0) +fun Pinned.toPtr() : CPointer? { + return try { + addressOf(0) + } catch (outOfBounds : ArrayIndexOutOfBoundsException) { + null + } +} From 65af7143fcb473f729f18f0d29ec5cd3bf77f875 Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Tue, 27 Jul 2021 12:33:22 +0200 Subject: [PATCH 2/2] Missing initializer in test --- ...ticatedEncryptionWithAssociatedDataTest.kt | 78 ++++++++++--------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/aead/AuthenticatedEncryptionWithAssociatedDataTest.kt b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/aead/AuthenticatedEncryptionWithAssociatedDataTest.kt index 7e1dbf1..d8a9eba 100644 --- a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/aead/AuthenticatedEncryptionWithAssociatedDataTest.kt +++ b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/aead/AuthenticatedEncryptionWithAssociatedDataTest.kt @@ -67,52 +67,54 @@ class AuthenticatedEncryptionWithAssociatedDataTest { } @Test - fun testEmptyAssociatedData() { - val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " + - "only one tip for the future, sunscreen would be it.").encodeToUByteArray() + fun testEmptyAssociatedData() = runTest { + LibsodiumInitializer.initializeWithCallback { + val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " + + "only one tip for the future, sunscreen would be it.").encodeToUByteArray() - val associatedData = ubyteArrayOf() + val associatedData = ubyteArrayOf() - val key = ubyteArrayOf( - 0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U, - 0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU, - 0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U, - 0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU, - ) + val key = ubyteArrayOf( + 0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U, + 0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU, + 0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U, + 0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU, + ) - val nonce = ubyteArrayOf( - 0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, - 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, - 0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, - ) + val nonce = ubyteArrayOf( + 0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, + 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, + 0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, + ) - val encrypted = AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfEncrypt( - message, - associatedData, - nonce, - key - ) - val decrypted = AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfDecrypt( - encrypted, - associatedData, - nonce, - key - ) - assertTrue { - message.contentEquals(decrypted) - } - - assertFailsWith(AeadCorrupedOrTamperedDataException::class) { - val tamperedTag = encrypted.copyOf() - tamperedTag[3] = 0U - tamperedTag[1] = 0U - tamperedTag[0] = 0U - AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfDecrypt( - tamperedTag, + val encrypted = AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfEncrypt( + message, associatedData, nonce, key ) + val decrypted = AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfDecrypt( + encrypted, + associatedData, + nonce, + key + ) + assertTrue { + message.contentEquals(decrypted) + } + + assertFailsWith(AeadCorrupedOrTamperedDataException::class) { + val tamperedTag = encrypted.copyOf() + tamperedTag[3] = 0U + tamperedTag[1] = 0U + tamperedTag[0] = 0U + AuthenticatedEncryptionWithAssociatedData.xChaCha20Poly1305IetfDecrypt( + tamperedTag, + associatedData, + nonce, + key + ) + } } }