From 28995c065fd7310adb69b2aff3a2f1e4ff6267d4 Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Fri, 14 Aug 2020 16:00:30 +0200 Subject: [PATCH] Adding secretstream push definition and neccessary changes --- .../libsodium/definitions/DefinitionTypes.kt | 10 ++- .../LibsodiumSecretStreamDefinitions.kt | 65 +++++++++++++++---- .../generator/JsLibsodiumGenerator.kt | 12 +++- .../generator/JvmLibsodiumGenerator.kt | 16 ++++- .../generator/NativeLibsodiumGenerator.kt | 19 ++++-- .../commonMain/kotlin/debug/test/DebugTest.kt | 17 ++++- .../src/jsMain/kotlin/debug/test/DebugTest.kt | 19 ++++++ .../jvmMain/kotlin/debug/test/DebugTest.kt | 24 ++++++- .../nativeMain/kotlin/debug/test/DebugTest.kt | 44 +++++++++++-- 9 files changed, 195 insertions(+), 31 deletions(-) diff --git a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/definitions/DefinitionTypes.kt b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/definitions/DefinitionTypes.kt index 9e1c9ed..a27533b 100644 --- a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/definitions/DefinitionTypes.kt +++ b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/definitions/DefinitionTypes.kt @@ -85,6 +85,13 @@ class FunctionDefinition( } } +/** + * + * isActuallyAnOutputParam - drop this parameter from the generated param list and provide it as output. Param + * will be automatically generated inside function body block + * isStateType - provides special handling when type is a non-primitive state type + * dropParameterFromDefinition - don't show this parameter in method definition + */ class ParameterDefinition( val parameterName: String, val parameterType: GeneralTypeDefinition, @@ -118,7 +125,8 @@ enum class TypeDefinition(override val typeName: TypeName) : GeneralTypeDefiniti LONG(Long::class.asTypeName()), INT(Int::class.asTypeName()), STRING(String::class.asTypeName()), - UNIT(Unit::class.asTypeName()) + UNIT(Unit::class.asTypeName()), + UBYTE(UByte::class.asTypeName()) } enum class TargetPlatform { diff --git a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/definitions/LibsodiumSecretStreamDefinitions.kt b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/definitions/LibsodiumSecretStreamDefinitions.kt index 4f3b10b..c4f16b1 100644 --- a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/definitions/LibsodiumSecretStreamDefinitions.kt +++ b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/definitions/LibsodiumSecretStreamDefinitions.kt @@ -10,7 +10,7 @@ fun ClassDefinition.defineSecretStreamFunctions() { "SecretStreamState", "com.goterl.lazycode.lazysodium.interfaces.SecretStream.State", "SecretStreamState", - "crypto_hash_sha256_state" + "crypto_secretstream_xchacha20poly1305_state" ) +dataClassDef( "SecretStreamStateAndHeader", @@ -42,30 +42,35 @@ fun ClassDefinition.defineSecretStreamFunctions() { val jvmSecretStreamInit = CodeBlockDefinition( """ - val header = UByteArray(24) - val state = SecretStream.State() - sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header.asByteArray(), key.asByteArray()) - return SecretStreamStateAndHeader(state, header) + val header = UByteArray(24) + val state = SecretStream.State() + sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header.asByteArray(), key.asByteArray()) + return SecretStreamStateAndHeader(state, header) """.trimIndent(), setOf(TargetPlatform.JVM) ) val nativeSecretStreamInit = CodeBlockDefinition( """ - val state = libsodium.sodium_malloc(libsodium.crypto_secretstream_xchacha20poly1305_state.size.convert())!! - .reinterpret() - .pointed - val header = UByteArray(crypto_secretstream_xchacha20poly1305_HEADERBYTES.toInt()) { 0U } - val pinnedHeader = header.pin() - libsodium.crypto_secretstream_xchacha20poly1305_init_push(state.ptr, pinnedHeader.addressOf(0), key.toCValues()) - pinnedHeader.unpin() - return SecretStreamStateAndHeader(state, header) + val pinnedKey = key.pin() + val state = sodium_malloc(libsodium.crypto_secretstream_xchacha20poly1305_state.size.convert())!! + .reinterpret() + .pointed + val header = UByteArray(libsodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES.toInt()) { 0U } + val pinnedHeader = header.pin() + libsodium.crypto_secretstream_xchacha20poly1305_init_push(state.ptr, pinnedHeader.addressOf(0), pinnedKey.addressOf(0)) + pinnedHeader.unpin() + pinnedKey.unpin() + return SecretStreamStateAndHeader(state, header) """.trimIndent(), setOf(TargetPlatform.NATIVE) ) +funcDef( "crypto_secretstream_xchacha20poly1305_init_push", - returnType = TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE, + codeDocumentation = """ + Initialize a state and generate a random header. Both are returned inside `SecretStreamStateAndHeader` object + """.trimIndent(), + returnType = CustomTypeDefinition(withPackageName("SecretStreamStateAndHeader")), dynamicJsReturn = true, isStateCreationFunction = true, customCodeBlockReplacesFunctionBody = listOf(jsSecretStreamInit, jvmSecretStreamInit, nativeSecretStreamInit) @@ -76,5 +81,37 @@ fun ClassDefinition.defineSecretStreamFunctions() { ) } + +funcDef( + name = "crypto_secretstream_xchacha20poly1305_push", + codeDocumentation = """ + Encrypt next block of data using the previously initialized state. Returns encrypted block. + """.trimIndent(), + returnType = TypeDefinition.ARRAY_OF_UBYTES + ) { + +ParameterDefinition( + "state", + CustomTypeDefinition(withPackageName("SecretStreamState")) + ) + +ParameterDefinition( + "c", + TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE, + isActuallyAnOutputParam = true, + dropParameterFromDefinition = true + ) + +ParameterDefinition( + "m", + TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE, + modifiesReturn = true + ) + +ParameterDefinition( + "ad", + TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE + ) + +ParameterDefinition( + "tag", + TypeDefinition.UBYTE + ) + } + } diff --git a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/JsLibsodiumGenerator.kt b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/JsLibsodiumGenerator.kt index b474068..9901e0d 100644 --- a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/JsLibsodiumGenerator.kt +++ b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/JsLibsodiumGenerator.kt @@ -77,7 +77,14 @@ object JsLibsodiumGenerator { throw RuntimeException("Return modifier already found") } returnModifierFound = true - returnModifierName = paramDefinition.parameterName + when (paramDefinition.parameterType) { + TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> { + returnModifierName = "${paramDefinition.parameterName}.size" + } + TypeDefinition.INT -> { + returnModifierName = paramDefinition.parameterName + } + } } if (paramDefinition.isActuallyAnOutputParam) { actualReturnTypeFound = true @@ -165,6 +172,9 @@ object JsLibsodiumGenerator { TypeDefinition.STRING -> { paramsBuilder.append(paramDefinition.parameterName + separator) } + TypeDefinition.UBYTE -> { + paramsBuilder.append(paramDefinition.parameterName + separator) + } } } diff --git a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/JvmLibsodiumGenerator.kt b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/JvmLibsodiumGenerator.kt index 9e9304a..06708bc 100644 --- a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/JvmLibsodiumGenerator.kt +++ b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/JvmLibsodiumGenerator.kt @@ -72,7 +72,14 @@ object JvmLibsodiumGenerator { throw RuntimeException("Return modifier already found") } returnModifierFound = true - returnModifierName = paramDefinition.parameterName + when (paramDefinition.parameterType) { + TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> { + returnModifierName = "${paramDefinition.parameterName}.size" + } + TypeDefinition.INT -> { + returnModifierName = paramDefinition.parameterName + } + } } if (paramDefinition.isActuallyAnOutputParam) { actualReturnParameterDefinition = paramDefinition @@ -114,7 +121,7 @@ object JvmLibsodiumGenerator { constructJvmCall.append("sodium.${methodDefinition.nativeName}") constructJvmCall.append(paramsToString(methodDefinition)) methodBuilder.addStatement(constructJvmCall.toString()) - methodBuilder.addStatement("return out") + methodBuilder.addStatement("return ${actualReturnParameterDefinition.parameterName}") } else { when (methodDefinition.returnType) { TypeDefinition.ARRAY_OF_UBYTES -> { @@ -155,7 +162,7 @@ object JvmLibsodiumGenerator { */ when (outputParam.parameterType) { TypeDefinition.ARRAY_OF_UBYTES, TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE, TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> { - methodBuilder.addStatement("val out = UByteArray($length)") + methodBuilder.addStatement("val ${outputParam.parameterName} = UByteArray($length)") } else -> { throw RuntimeException("Unhandled native output param type: ${outputParam.parameterType.typeName}") @@ -205,6 +212,9 @@ object JvmLibsodiumGenerator { TypeDefinition.STRING -> { paramsBuilder.append(paramDefinition.parameterName + separator) } + TypeDefinition.UBYTE -> { + paramsBuilder.append(paramDefinition.parameterName + separator) + } } } diff --git a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/NativeLibsodiumGenerator.kt b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/NativeLibsodiumGenerator.kt index 56a865a..98261b6 100644 --- a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/NativeLibsodiumGenerator.kt +++ b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/NativeLibsodiumGenerator.kt @@ -87,7 +87,15 @@ object NativeLibsodiumGenerator { throw RuntimeException("Return modifier already found") } returnModifierFound = true - returnModifierName = paramDefinition.parameterName + when (paramDefinition.parameterType) { + TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> { + returnModifierName = "${paramDefinition.parameterName}.size" + } + TypeDefinition.INT -> { + returnModifierName = paramDefinition.parameterName + } + } + } if (paramDefinition.isActuallyAnOutputParam) { actualReturnParameterDefinition = paramDefinition @@ -105,7 +113,6 @@ object NativeLibsodiumGenerator { } } methodBuilder.addStatement("println(\"Debug ${methodDefinition.name}\")") - pinParams(methodDefinition, methodBuilder) val constructNativeCall = StringBuilder() if (methodDefinition.customCodeBlockReplacesFunctionBody != null) { for (codeBlock in methodDefinition.customCodeBlockReplacesFunctionBody.filter { it.applyOnTargets.contains(TargetPlatform.NATIVE) }) { @@ -113,6 +120,7 @@ object NativeLibsodiumGenerator { methodBuilder.addStatement(constructNativeCall.toString()) } } else { + pinParams(methodDefinition, methodBuilder) if (methodDefinition.isStateCreationFunction) { constructNativeCall.append("libsodium.${methodDefinition.nativeName}") constructNativeCall.append(paramsToString(methodDefinition)) @@ -124,7 +132,7 @@ object NativeLibsodiumGenerator { constructNativeCall.append(paramsToString(methodDefinition)) methodBuilder.addStatement(constructNativeCall.toString()) unpinParams(methodDefinition, methodBuilder) - methodBuilder.addStatement("return out") + methodBuilder.addStatement("return ${actualReturnParameterDefinition.parameterName}") } else { when (methodDefinition.returnType) { TypeDefinition.ARRAY_OF_UBYTES -> { @@ -184,7 +192,7 @@ object NativeLibsodiumGenerator { */ when (outputParam.parameterType) { TypeDefinition.ARRAY_OF_UBYTES, TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE, TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> { - methodBuilder.addStatement("val out = UByteArray($length)") + methodBuilder.addStatement("val ${outputParam.parameterName} = UByteArray($length)") } else -> { throw RuntimeException("Unhandled native output param type: ${outputParam.parameterType.typeName}") @@ -282,6 +290,9 @@ object NativeLibsodiumGenerator { TypeDefinition.STRING -> { paramsBuilder.append(paramDefinition.parameterName + separator) } + TypeDefinition.UBYTE -> { + paramsBuilder.append(paramDefinition.parameterName + separator) + } } } diff --git a/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/debug/test/DebugTest.kt b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/debug/test/DebugTest.kt index 91fe139..791885d 100644 --- a/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/debug/test/DebugTest.kt +++ b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/debug/test/DebugTest.kt @@ -1,6 +1,7 @@ package debug.test import kotlin.Int +import kotlin.UByte import kotlin.UByteArray expect class Sha256State @@ -35,5 +36,19 @@ expect class Crypto internal constructor() { fun crypto_generichash_init(key: UByteArray, outlen: Int): GenericHashState - fun crypto_secretstream_xchacha20poly1305_init_push(key: UByteArray): UByteArray + /** + * Initialize a state and generate a random header. Both are returned inside + * `SecretStreamStateAndHeader` object + */ + fun crypto_secretstream_xchacha20poly1305_init_push(key: UByteArray): SecretStreamStateAndHeader + + /** + * Encrypt next block of data using the previously initialized state. Returns encrypted block. + */ + fun crypto_secretstream_xchacha20poly1305_push( + state: SecretStreamState, + m: UByteArray, + ad: UByteArray, + tag: UByte + ): UByteArray } diff --git a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/debug/test/DebugTest.kt b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/debug/test/DebugTest.kt index 9ad22de..a3ebf86 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/debug/test/DebugTest.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/debug/test/DebugTest.kt @@ -5,6 +5,7 @@ import ext.libsodium.com.ionspin.kotlin.crypto.toUByteArray import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array import kotlin.Any import kotlin.Int +import kotlin.UByte import kotlin.UByteArray import org.khronos.webgl.Uint8Array @@ -58,6 +59,10 @@ actual class Crypto internal actual constructor() { return getSodium().crypto_generichash_init(key.toUInt8Array(), outlen) } + /** + * Initialize a state and generate a random header. Both are returned inside + * `SecretStreamStateAndHeader` object + */ actual fun crypto_secretstream_xchacha20poly1305_init_push(key: UByteArray): dynamic { println("Debug crypto_secretstream_xchacha20poly1305_init_push") val stateAndHeader = @@ -66,4 +71,18 @@ actual class Crypto internal actual constructor() { val header = (stateAndHeader.header as Uint8Array).toUByteArray() return SecretStreamStateAndHeader(state, header) } + + /** + * Encrypt next block of data using the previously initialized state. Returns encrypted block. + */ + actual fun crypto_secretstream_xchacha20poly1305_push( + state: SecretStreamState, + m: UByteArray, + ad: UByteArray, + tag: UByte + ): UByteArray { + println("Debug crypto_secretstream_xchacha20poly1305_push") + return getSodium().crypto_secretstream_xchacha20poly1305_push(state, m.toUInt8Array(), , + ad.toUInt8Array(), , tag).toUByteArray() + } } diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/debug/test/DebugTest.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/debug/test/DebugTest.kt index 5b917e5..efffbf4 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/debug/test/DebugTest.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/debug/test/DebugTest.kt @@ -5,6 +5,7 @@ import com.goterl.lazycode.lazysodium.interfaces.Hash import com.goterl.lazycode.lazysodium.interfaces.SecretStream import kotlin.ByteArray import kotlin.Int +import kotlin.UByte import kotlin.UByteArray val sodium: SodiumJava = SodiumJava() @@ -67,7 +68,12 @@ actual class Crypto internal actual constructor() { return state } - actual fun crypto_secretstream_xchacha20poly1305_init_push(key: UByteArray): UByteArray { + /** + * Initialize a state and generate a random header. Both are returned inside + * `SecretStreamStateAndHeader` object + */ + actual fun crypto_secretstream_xchacha20poly1305_init_push(key: UByteArray): + SecretStreamStateAndHeader { println("Debug crypto_secretstream_xchacha20poly1305_init_push") val header = UByteArray(24) val state = SecretStream.State() @@ -75,4 +81,20 @@ actual class Crypto internal actual constructor() { key.asByteArray()) return SecretStreamStateAndHeader(state, header) } + + /** + * Encrypt next block of data using the previously initialized state. Returns encrypted block. + */ + actual fun crypto_secretstream_xchacha20poly1305_push( + state: SecretStreamState, + m: UByteArray, + ad: UByteArray, + tag: UByte + ): UByteArray { + val c = UByteArray(m.size) + println("Debug crypto_secretstream_xchacha20poly1305_push") + sodium.crypto_secretstream_xchacha20poly1305_push(state, c.asByteArray(), c.size.toLong(), + m.asByteArray(), m.size.toLong(), ad.asByteArray(), ad.size.toLong(), tag) + return c + } } diff --git a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/debug/test/DebugTest.kt b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/debug/test/DebugTest.kt index 1d2dc33..933270f 100644 --- a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/debug/test/DebugTest.kt +++ b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/debug/test/DebugTest.kt @@ -3,6 +3,7 @@ package debug.test import kotlin.Byte import kotlin.ByteArray import kotlin.Int +import kotlin.UByte import kotlin.UByteArray import kotlinx.cinterop.addressOf import kotlinx.cinterop.convert @@ -14,6 +15,7 @@ import kotlinx.cinterop.toCValues import libsodium.crypto_generichash_blake2b_state import libsodium.crypto_hash_sha256_state import libsodium.crypto_hash_sha512_state +import libsodium.crypto_secretstream_xchacha20poly1305_state import libsodium.sodium_malloc actual typealias Sha256State = crypto_hash_sha256_state @@ -22,7 +24,7 @@ actual typealias Sha512State = crypto_hash_sha512_state actual typealias GenericHashState = crypto_generichash_blake2b_state -actual typealias SecretStreamState = crypto_hash_sha256_state +actual typealias SecretStreamState = crypto_secretstream_xchacha20poly1305_state actual class Crypto internal actual constructor() { val _emitByte: Byte = 0 @@ -92,18 +94,48 @@ actual class Crypto internal actual constructor() { return state } - actual fun crypto_secretstream_xchacha20poly1305_init_push(key: UByteArray): UByteArray { + /** + * Initialize a state and generate a random header. Both are returned inside + * `SecretStreamStateAndHeader` object + */ + actual fun crypto_secretstream_xchacha20poly1305_init_push(key: UByteArray): + SecretStreamStateAndHeader { println("Debug crypto_secretstream_xchacha20poly1305_init_push") val pinnedKey = key.pin() - val state = - libsodium.sodium_malloc(libsodium.crypto_secretstream_xchacha20poly1305_state.size.convert())!! + val state = + sodium_malloc(libsodium.crypto_secretstream_xchacha20poly1305_state.size.convert())!! .reinterpret() .pointed - val header = UByteArray(crypto_secretstream_xchacha20poly1305_HEADERBYTES.toInt()) { 0U } + val header = UByteArray(libsodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES.toInt()) + { 0U } val pinnedHeader = header.pin() libsodium.crypto_secretstream_xchacha20poly1305_init_push(state.ptr, - pinnedHeader.addressOf(0), key.toCValues()) + pinnedHeader.addressOf(0), pinnedKey.addressOf(0)) pinnedHeader.unpin() + pinnedKey.unpin() return SecretStreamStateAndHeader(state, header) } + + /** + * Encrypt next block of data using the previously initialized state. Returns encrypted block. + */ + actual fun crypto_secretstream_xchacha20poly1305_push( + state: SecretStreamState, + m: UByteArray, + ad: UByteArray, + tag: UByte + ): UByteArray { + val c = UByteArray(m.size) + println("Debug crypto_secretstream_xchacha20poly1305_push") + val pinnedC = c.pin() + val pinnedM = m.pin() + val pinnedAd = ad.pin() + libsodium.crypto_secretstream_xchacha20poly1305_push(state.ptr, pinnedC.addressOf(0), + c.size.convert(), pinnedM.addressOf(0), m.size.convert(), pinnedAd.addressOf(0), + ad.size.convert(), tag) + pinnedC.unpin() + pinnedM.unpin() + pinnedAd.unpin() + return c + } }