From 9e10677165758d1cb79b5ad684f2939e063ea010 Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Thu, 27 Aug 2020 19:27:46 +0200 Subject: [PATCH] ADded helper extension toPtr instead of addressOf(0), implemented jvm and native secret stream --- .../XChaCha20Poly1305Delegated.kt | 11 +-- .../crypto/hash/blake2b/Blake2bDelegated.kt | 5 +- .../kotlin/crypto/hash/sha/Sha256Delegated.kt | 5 +- .../kotlin/crypto/hash/sha/Sha512Delegated.kt | 5 +- .../kotlin/crypto/util/ConversionUtil.kt | 13 +++ .../com/ionspin/kotlin/crypto/HelperTest.kt | 5 +- .../crypto/secretstream/SecretStream.kt | 37 ++++++-- .../kotlin/crypto/generichash/GenericHash.kt | 13 +-- .../crypto/secretstream/SecretStream.kt | 86 ++++++++++++++++++- .../kotlin/crypto/util/ConversionUtil.kt | 13 +++ 10 files changed, 165 insertions(+), 28 deletions(-) create mode 100644 multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/ConversionUtil.kt create mode 100644 multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/ConversionUtil.kt diff --git a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt index 0d60110..e83dd43 100644 --- a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt +++ b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt @@ -2,6 +2,7 @@ package com.ionspin.kotlin.crypto.authenticated import com.ionspin.kotlin.bignum.integer.util.hexColumsPrint import com.ionspin.kotlin.crypto.InvalidTagException +import com.ionspin.kotlin.crypto.util.toPtr import kotlinx.cinterop.* import libsodium.* @@ -22,7 +23,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() { val ciphertext = UByteArray(ciphertextLength) val ciphertextPinned = ciphertext.pin() crypto_aead_xchacha20poly1305_ietf_encrypt( - ciphertextPinned.addressOf(0), + ciphertextPinned.toPtr(), ulongArrayOf(ciphertextLength.convert()).toCValues(), message.toCValues(), message.size.convert(), @@ -46,7 +47,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() { val message = UByteArray(messageLength) val messagePinned = message.pin() crypto_aead_xchacha20poly1305_ietf_decrypt( - messagePinned.addressOf(0), + messagePinned.toPtr(), ulongArrayOf(messageLength.convert()).toCValues(), null, ciphertext.toCValues(), @@ -95,7 +96,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() { actual fun initializeForEncryption(key: UByteArray) : UByteArray { val pinnedHeader = header.pin() - crypto_secretstream_xchacha20poly1305_init_push(state.ptr, pinnedHeader.addressOf(0), key.toCValues()) + crypto_secretstream_xchacha20poly1305_init_push(state.ptr, pinnedHeader.toPtr(), key.toCValues()) println("state-----------") state.ptr.readBytes(crypto_secretstream_xchacha20poly1305_state.size.toInt()).asUByteArray().hexColumsPrint() println("state-----------") @@ -116,7 +117,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() { val ciphertextWithTagPinned = ciphertextWithTag.pin() crypto_secretstream_xchacha20poly1305_push( state.ptr, - ciphertextWithTagPinned.addressOf(0), + ciphertextWithTagPinned.toPtr(), null, data.toCValues(), data.size.convert(), @@ -136,7 +137,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() { val plaintextPinned = plaintext.pin() val validTag = crypto_secretstream_xchacha20poly1305_pull( state.ptr, - plaintextPinned.addressOf(0), + plaintextPinned.toPtr(), null, null, data.toCValues(), diff --git a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bDelegated.kt b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bDelegated.kt index a72383b..d819606 100644 --- a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bDelegated.kt +++ b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bDelegated.kt @@ -1,5 +1,6 @@ package com.ionspin.kotlin.crypto.hash.blake2b import com.ionspin.kotlin.crypto.util.toHexString +import com.ionspin.kotlin.crypto.util.toPtr import kotlinx.cinterop.* import libsodium.* import platform.posix.free @@ -30,7 +31,7 @@ actual class Blake2bDelegated actual constructor(key: UByteArray?, hashLength: I override fun digest(): UByteArray { val hashResult = UByteArray(requestedHashLength) val hashResultPinned = hashResult.pin() - crypto_generichash_final(state.ptr, hashResultPinned.addressOf(0), requestedHashLength.convert()) + crypto_generichash_final(state.ptr, hashResultPinned.toPtr(), requestedHashLength.convert()) free(state.ptr) return hashResult } @@ -44,7 +45,7 @@ actual object Blake2bDelegatedStateless : Blake2b { val hashResult = UByteArray(MAX_HASH_BYTES) val hashResultPinned = hashResult.pin() crypto_generichash( - hashResultPinned.addressOf(0), + hashResultPinned.toPtr(), hashLength.convert(), inputMessage.toCValues(), inputMessage.size.convert(), diff --git a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt index 0663629..32c1e5d 100644 --- a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt +++ b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt @@ -1,6 +1,7 @@ package com.ionspin.kotlin.crypto.hash.sha import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bDelegatedStateless +import com.ionspin.kotlin.crypto.util.toPtr import kotlinx.cinterop.* import libsodium.* import platform.posix.free @@ -32,7 +33,7 @@ actual class Sha256Delegated : Sha256 { override fun digest(): UByteArray { val hashResult = UByteArray(Sha256Properties.MAX_HASH_BYTES) val hashResultPinned = hashResult.pin() - crypto_hash_sha256_final(state.ptr, hashResultPinned.addressOf(0)) + crypto_hash_sha256_final(state.ptr, hashResultPinned.toPtr()) sodium_free(state.ptr) return hashResult } @@ -46,7 +47,7 @@ actual object Sha256StatelessDelegated : StatelessSha256 { override fun digest(inputMessage: UByteArray): UByteArray { val hashResult = UByteArray(MAX_HASH_BYTES) val hashResultPinned = hashResult.pin() - crypto_hash_sha256(hashResultPinned.addressOf(0), inputMessage.toCValues(), inputMessage.size.convert()) + crypto_hash_sha256(hashResultPinned.toPtr(), inputMessage.toCValues(), inputMessage.size.convert()) hashResultPinned.unpin() return hashResult } diff --git a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt index f4b80a6..a700b04 100644 --- a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt +++ b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt @@ -1,5 +1,6 @@ package com.ionspin.kotlin.crypto.hash.sha +import com.ionspin.kotlin.crypto.util.toPtr import kotlinx.cinterop.* import libsodium.* import platform.posix.free @@ -30,7 +31,7 @@ actual class Sha512Delegated : Sha512Multipart { override fun digest(): UByteArray { val hashResult = UByteArray(Sha512Properties.MAX_HASH_BYTES) val hashResultPinned = hashResult.pin() - crypto_hash_sha512_final(state.ptr, hashResultPinned.addressOf(0)) + crypto_hash_sha512_final(state.ptr, hashResultPinned.toPtr()) free(state.ptr) return hashResult } @@ -42,7 +43,7 @@ actual object Sha512StatelessDelegated : Sha512 { override fun digest(inputMessage: UByteArray): UByteArray { val hashResult = UByteArray(Sha512StatelessDelegated.MAX_HASH_BYTES) val hashResultPinned = hashResult.pin() - crypto_hash_sha512(hashResultPinned.addressOf(0), inputMessage.toCValues(), inputMessage.size.convert()) + crypto_hash_sha512(hashResultPinned.toPtr(), inputMessage.toCValues(), inputMessage.size.convert()) hashResultPinned.unpin() return hashResult } diff --git a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/ConversionUtil.kt b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/ConversionUtil.kt new file mode 100644 index 0000000..7a0d892 --- /dev/null +++ b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/ConversionUtil.kt @@ -0,0 +1,13 @@ +package com.ionspin.kotlin.crypto.util + +import kotlinx.cinterop.CPointer +import kotlinx.cinterop.Pinned +import kotlinx.cinterop.UByteVar +import kotlinx.cinterop.addressOf + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 27-Aug-2020 + */ +fun Pinned.toPtr() : CPointer = addressOf(0) diff --git a/multiplatform-crypto-delegated/src/nativeTest/kotlin/com/ionspin/kotlin/crypto/HelperTest.kt b/multiplatform-crypto-delegated/src/nativeTest/kotlin/com/ionspin/kotlin/crypto/HelperTest.kt index fd6827e..4bc8bcd 100644 --- a/multiplatform-crypto-delegated/src/nativeTest/kotlin/com/ionspin/kotlin/crypto/HelperTest.kt +++ b/multiplatform-crypto-delegated/src/nativeTest/kotlin/com/ionspin/kotlin/crypto/HelperTest.kt @@ -2,6 +2,7 @@ package com.ionspin.kotlin.crypto import com.ionspin.kotlin.crypto.hash.encodeToUByteArray import com.ionspin.kotlin.crypto.util.toHexString +import com.ionspin.kotlin.crypto.util.toPtr import kotlinx.cinterop.* import libsodium.* import platform.posix.free @@ -39,7 +40,7 @@ class HelperTest { } val result = UByteArray(32) val resultPinned = result.pin() - crypto_hash_sha256_final(state, resultPinned.addressOf(0)) + crypto_hash_sha256_final(state, resultPinned.toPtr()) println("$target to \"${result.toHexString()}\",") free(state) } @@ -69,7 +70,7 @@ class HelperTest { } val result = UByteArray(32) val resultPinned = result.pin() - crypto_hash_sha512_final(state, resultPinned.addressOf(0)) + crypto_hash_sha512_final(state, resultPinned.toPtr()) println("$target to \"${result.toHexString()}\",") free(state) } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/secretstream/SecretStream.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/secretstream/SecretStream.kt index e03d3ad..b92eb63 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/secretstream/SecretStream.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/secretstream/SecretStream.kt @@ -7,8 +7,10 @@ actual typealias SecretStreamState = SecretStream.State actual object SecretStream { actual fun xChaCha20Poly1305InitPush(key: UByteArray): SecretStreamStateAndHeader { - TODO("not implemented yet") -// sodium.crypto_secretstream_xchacha20poly1305_init_push() + val state = SecretStreamState() + val header = UByteArray(sodium.crypto_secretstream_xchacha20poly1305_headerbytes()) + sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header.asByteArray(), key.asByteArray()) + return SecretStreamStateAndHeader(state, header) } actual fun xChaCha20Poly1305Push( @@ -17,14 +19,27 @@ actual object SecretStream { additionalData: UByteArray, tag: UByte ): UByteArray { - TODO("not implemented yet") + val ciphertext = UByteArray(message.size) + sodium.crypto_secretstream_xchacha20poly1305_push( + state, + ciphertext.asByteArray(), + null, + message.asByteArray(), + message.size.toLong(), + additionalData.asByteArray(), + additionalData.size.toLong(), + tag.toByte() + ) + return ciphertext } actual fun xChaCha20Poly1305InitPull( key: UByteArray, header: UByteArray ): SecretStreamStateAndHeader { - TODO("not implemented yet") + val state = SecretStreamState() + sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header.asByteArray(), key.asByteArray()) + return SecretStreamStateAndHeader(state, header) } actual fun xChaCha20Poly1305Pull( @@ -32,7 +47,19 @@ actual object SecretStream { ciphertext: UByteArray, additionalData: UByteArray ): DecryptedDataAndTag { - TODO("not implemented yet") + val result = UByteArray(ciphertext.size) + val tagArray = UByteArray(1) { 0U } + sodium.crypto_secretstream_xchacha20poly1305_pull( + state, + result.asByteArray(), + null, + tagArray.asByteArray(), + ciphertext.asByteArray(), + ciphertext.size.toLong(), + additionalData.asByteArray(), + additionalData.size.toLong() + ) + return DecryptedDataAndTag(result, tagArray[0]) } } diff --git a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/generichash/GenericHash.kt b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/generichash/GenericHash.kt index c10ac4f..e8c9742 100644 --- a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/generichash/GenericHash.kt +++ b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/generichash/GenericHash.kt @@ -1,5 +1,6 @@ package com.ionspin.kotlin.crypto.generichash +import com.ionspin.kotlin.crypto.util.toPtr import kotlinx.cinterop.addressOf import kotlinx.cinterop.convert import kotlinx.cinterop.pin @@ -32,11 +33,11 @@ actual object GenericHash { val pinnedKey = key?.pin() val pinnedMessage = message.pin() crypto_generichash( - pinnedHash.addressOf(0), + pinnedHash.toPtr(), requestedHashLength.convert(), - pinnedMessage.addressOf(0), + pinnedMessage.toPtr(), message.size.convert(), - pinnedKey?.addressOf(0), + pinnedKey?.toPtr(), (key?.size ?: 0).convert() ) pinnedHash.unpin() @@ -54,7 +55,7 @@ actual object GenericHash { val pinnedKey = key?.pin() crypto_generichash_init( statePointed.ptr, - pinnedKey?.addressOf(0), + pinnedKey?.toPtr(), (key?.size ?: 0).convert(), requestedHashLength.convert() ) @@ -69,7 +70,7 @@ actual object GenericHash { val pinnedMessage = messagePart.pin() crypto_generichash_update( state.internalState.ptr, - pinnedMessage.addressOf(0), + pinnedMessage.toPtr(), messagePart.size.convert() ) pinnedMessage.unpin() @@ -80,7 +81,7 @@ actual object GenericHash { val hashResultPinned = hashResult.pin() crypto_generichash_final( state.internalState.ptr, - hashResultPinned.addressOf(0), + hashResultPinned.toPtr(), state.hashLength.convert() ) hashResultPinned.unpin() diff --git a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/secretstream/SecretStream.kt b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/secretstream/SecretStream.kt index 3b38152..11e15ba 100644 --- a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/secretstream/SecretStream.kt +++ b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/secretstream/SecretStream.kt @@ -1,10 +1,39 @@ package com.ionspin.kotlin.crypto.secretstream +import com.ionspin.kotlin.crypto.util.toPtr +import kotlinx.cinterop.UByteVar +import kotlinx.cinterop.convert +import kotlinx.cinterop.pin +import kotlinx.cinterop.pointed +import kotlinx.cinterop.ptr +import kotlinx.cinterop.reinterpret +import kotlinx.cinterop.toCPointer +import libsodium.crypto_secretstream_xchacha20poly1305_headerbytes +import libsodium.crypto_secretstream_xchacha20poly1305_init_pull +import libsodium.crypto_secretstream_xchacha20poly1305_init_push +import libsodium.crypto_secretstream_xchacha20poly1305_pull +import libsodium.crypto_secretstream_xchacha20poly1305_push +import platform.posix.malloc + actual typealias SecretStreamState = libsodium.crypto_secretstream_xchacha20poly1305_state actual object SecretStream { actual fun xChaCha20Poly1305InitPush(key: UByteArray): SecretStreamStateAndHeader { - TODO("not implemented yet") + val stateAllocated = malloc(SecretStreamState.size.convert()) + val statePointed = stateAllocated!!.reinterpret().pointed + + val header = UByteArray(crypto_secretstream_xchacha20poly1305_headerbytes().convert()) { 0U } + val headerPinned = header.pin() + val keyPinned = key.pin() + crypto_secretstream_xchacha20poly1305_init_push( + statePointed.ptr, + headerPinned.toPtr(), + keyPinned.toPtr() + ) + headerPinned.unpin() + keyPinned.unpin() + return SecretStreamStateAndHeader(statePointed, header) + } actual fun xChaCha20Poly1305Push( @@ -13,14 +42,42 @@ actual object SecretStream { additionalData: UByteArray, tag: UByte ): UByteArray { - TODO("not implemented yet") + val ciphertext = UByteArray(message.size) + val ciphertextPinned = ciphertext.pin() + val messagePinned = message.pin() + val additionalDataPinned = additionalData.pin() + crypto_secretstream_xchacha20poly1305_push( + state.ptr, + ciphertextPinned.toPtr(), + null, + messagePinned.toPtr(), + message.size.convert(), + additionalDataPinned.toPtr(), + additionalData.size.convert(), + tag + ) + ciphertextPinned.unpin() + messagePinned.unpin() + additionalDataPinned.unpin() + return ciphertext } actual fun xChaCha20Poly1305InitPull( key: UByteArray, header: UByteArray ): SecretStreamStateAndHeader { - TODO("not implemented yet") + val stateAllocated = malloc(SecretStreamState.size.convert()) + val statePointed = stateAllocated!!.reinterpret().pointed + val keyPinned = key.pin() + val headerPinned = header.pin() + crypto_secretstream_xchacha20poly1305_init_pull( + statePointed.ptr, + headerPinned.toPtr(), + keyPinned.toPtr() + ) + headerPinned.unpin() + keyPinned.unpin() + return SecretStreamStateAndHeader(statePointed, header) } actual fun xChaCha20Poly1305Pull( @@ -28,7 +85,28 @@ actual object SecretStream { ciphertext: UByteArray, additionalData: UByteArray ): DecryptedDataAndTag { - TODO("not implemented yet") + val message = UByteArray(ciphertext.size) + val messagePinned = message.pin() + val ciphertextPinned = ciphertext.pin() + val additionalDataPinned = additionalData.pin() + val tag = UByteArray(1) { 0U } + val tagPinned = tag.pin() + crypto_secretstream_xchacha20poly1305_pull( + state.ptr, + messagePinned.toPtr(), + null, + tagPinned.toPtr(), + ciphertextPinned.toPtr(), + ciphertext.size.convert(), + additionalDataPinned.toPtr(), + additionalData.size.convert(), + + ) + ciphertextPinned.unpin() + messagePinned.unpin() + additionalDataPinned.unpin() + tagPinned.unpin() + return DecryptedDataAndTag(message, tag[0]) } } 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 new file mode 100644 index 0000000..7a0d892 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/util/ConversionUtil.kt @@ -0,0 +1,13 @@ +package com.ionspin.kotlin.crypto.util + +import kotlinx.cinterop.CPointer +import kotlinx.cinterop.Pinned +import kotlinx.cinterop.UByteVar +import kotlinx.cinterop.addressOf + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 27-Aug-2020 + */ +fun Pinned.toPtr() : CPointer = addressOf(0)