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 fe7b003..9e1c9ed 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 @@ -78,7 +78,7 @@ class FunctionDefinition( val dynamicJsReturn: Boolean = false, val isStateCreationFunction: Boolean = false, val outputLengthWhenArray: Int = -1, - val customCodeBlockReplacesFunctionBody: CodeBlockDefinition? = null + val customCodeBlockReplacesFunctionBody: List? = null ) { operator fun ParameterDefinition.unaryPlus() { parameterList.add(this) @@ -186,7 +186,7 @@ fun funcDef( dynamicJsReturn: Boolean = false, isStateCreationFunction: Boolean = false, outputLengthWhenArray: Int = -1, - customCodeBlockReplacesFunctionBody: CodeBlockDefinition? = null, + customCodeBlockReplacesFunctionBody: List? = null, body: FunctionDefinition.() -> Unit ): FunctionDefinition { val function = FunctionDefinition( @@ -212,7 +212,7 @@ fun funcDef( dynamicJsReturn: Boolean = false, isStateCreationFunction: Boolean = false, outputLengthWhenArray: Int = -1, - customCodeBlockReplacesFunctionBody: CodeBlockDefinition? = null, + customCodeBlockReplacesFunctionBody: List? = null, body: FunctionDefinition.() -> Unit ): FunctionDefinition { val function = 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 e4c8935..4f3b10b 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 @@ -30,11 +30,45 @@ fun ClassDefinition.defineSecretStreamFunctions() { ) ) + val jsSecretStreamInit = CodeBlockDefinition( + """ + val stateAndHeader = getSodium().crypto_secretstream_xchacha20poly1305_init_push(key.toUInt8Array()) + val state = stateAndHeader.state + val header = (stateAndHeader.header as Uint8Array).toUByteArray() + return SecretStreamStateAndHeader(state, header) + """.trimIndent(), + setOf(TargetPlatform.JS) + ) + + 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) + """.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) + """.trimIndent(), + setOf(TargetPlatform.NATIVE) + ) +funcDef( "crypto_secretstream_xchacha20poly1305_init_push", returnType = TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE, dynamicJsReturn = true, - isStateCreationFunction = true + isStateCreationFunction = true, + customCodeBlockReplacesFunctionBody = listOf(jsSecretStreamInit, jvmSecretStreamInit, nativeSecretStreamInit) ) { +ParameterDefinition( "key", diff --git a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/CommonLibsodiumGenerator.kt b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/CommonLibsodiumGenerator.kt index ea5af64..d2142b8 100644 --- a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/CommonLibsodiumGenerator.kt +++ b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/CommonLibsodiumGenerator.kt @@ -28,6 +28,7 @@ object CommonLibsodiumGenerator { } val commonClassSpec = createClass( + fileBuilder, commonClassDefinition, MultiplatformModifier.EXPECT, ::createCommonMethodSpec 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 c2985b7..b474068 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 @@ -18,6 +18,7 @@ object JsLibsodiumGenerator { fileBuilder.addImport("ext.libsodium.com.ionspin.kotlin.crypto", "toUInt8Array") fileBuilder.addImport("ext.libsodium.com.ionspin.kotlin.crypto", "toUByteArray") fileBuilder.addImport("com.ionspin.kotlin.crypto", "getSodium") + fileBuilder.addImport("org.khronos.webgl", "Uint8Array") for (commonClassDefinition in fileDefinition.commonClassList) { //Create type-aliases commonClassDefinition.innerClasses.forEach { @@ -25,6 +26,7 @@ object JsLibsodiumGenerator { } val commonClassSpec = createClass( + fileBuilder, commonClassDefinition, MultiplatformModifier.ACTUAL, ::createJsFunctionImplementation @@ -97,9 +99,10 @@ object JsLibsodiumGenerator { methodBuilder.modifiers += MultiplatformModifier.ACTUAL.modifierList methodBuilder.addStatement("println(\"Debug ${methodDefinition.name}\")") val constructJsCall = StringBuilder() - if (methodDefinition.customCodeBlockReplacesFunctionBody != null && - methodDefinition.customCodeBlockReplacesFunctionBody.applyOnTargets.contains(TargetPlatform.JS)) { - constructJsCall.append(methodDefinition.customCodeBlockReplacesFunctionBody.codeBlock) + if (methodDefinition.customCodeBlockReplacesFunctionBody != null) { + for (codeBlock in methodDefinition.customCodeBlockReplacesFunctionBody.filter { it.applyOnTargets.contains(TargetPlatform.JS) }) { + constructJsCall.append(codeBlock.codeBlock) + } } else { when (methodDefinition.returnType) { TypeDefinition.ARRAY_OF_UBYTES -> { 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 bad4c91..9e9304a 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 @@ -29,6 +29,7 @@ object JvmLibsodiumGenerator { } val commonClassSpec = createClass( + fileBuilder, commonClassDefinition, MultiplatformModifier.ACTUAL, ::createJvmFunctionImplementation @@ -98,9 +99,11 @@ object JvmLibsodiumGenerator { } methodBuilder.addStatement("println(\"Debug ${methodDefinition.name}\")") val constructJvmCall = StringBuilder() - if (methodDefinition.customCodeBlockReplacesFunctionBody != null && - methodDefinition.customCodeBlockReplacesFunctionBody.applyOnTargets.contains(TargetPlatform.JVM)) { - constructJvmCall.append(methodDefinition.customCodeBlockReplacesFunctionBody.codeBlock) + if (methodDefinition.customCodeBlockReplacesFunctionBody != null) { + for (codeBlock in methodDefinition.customCodeBlockReplacesFunctionBody.filter { it.applyOnTargets.contains(TargetPlatform.JVM) }) { + constructJvmCall.append(codeBlock.codeBlock) + } + methodBuilder.addStatement(constructJvmCall.toString()) } else { if (methodDefinition.isStateCreationFunction) { constructJvmCall.append("sodium.${methodDefinition.nativeName}") 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 3f22726..56a865a 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 @@ -36,6 +36,7 @@ object NativeLibsodiumGenerator { } val commonClassSpec = createClass( + fileBuilder, commonClassDefinition, MultiplatformModifier.ACTUAL, ::createNativeFunctionImplementation @@ -106,9 +107,11 @@ object NativeLibsodiumGenerator { methodBuilder.addStatement("println(\"Debug ${methodDefinition.name}\")") pinParams(methodDefinition, methodBuilder) val constructNativeCall = StringBuilder() - if (methodDefinition.customCodeBlockReplacesFunctionBody != null && - methodDefinition.customCodeBlockReplacesFunctionBody.applyOnTargets.contains(TargetPlatform.JS)) { - constructNativeCall.append(methodDefinition.customCodeBlockReplacesFunctionBody.codeBlock) + if (methodDefinition.customCodeBlockReplacesFunctionBody != null) { + for (codeBlock in methodDefinition.customCodeBlockReplacesFunctionBody.filter { it.applyOnTargets.contains(TargetPlatform.NATIVE) }) { + constructNativeCall.append(codeBlock.codeBlock) + methodBuilder.addStatement(constructNativeCall.toString()) + } } else { if (methodDefinition.isStateCreationFunction) { constructNativeCall.append("libsodium.${methodDefinition.nativeName}") diff --git a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/SharedCreators.kt b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/SharedCreators.kt index 3236be4..e35df01 100644 --- a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/SharedCreators.kt +++ b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/SharedCreators.kt @@ -12,6 +12,7 @@ import com.squareup.kotlinpoet.* * on 31-Jul-2020 */ fun createClass( + fileBuilder: FileSpec.Builder, classDefinition: ClassDefinition, multiplatformModifier: MultiplatformModifier, methodCreator: (FunctionDefinition) -> FunSpec.Builder @@ -22,7 +23,7 @@ fun createClass( if (multiplatformModifier == MultiplatformModifier.EXPECT) { primaryConstructor.addModifiers(KModifier.INTERNAL) for (dataClassDefinition in classDefinition.dataClasses) { - generateDataClass(commonClassBuilder, dataClassDefinition) + generateDataClass(fileBuilder, dataClassDefinition) } } else { primaryConstructor.addModifiers(KModifier.INTERNAL, KModifier.ACTUAL) @@ -38,7 +39,7 @@ fun createClass( return commonClassBuilder } -fun generateDataClass(classBuilder: TypeSpec.Builder, dataClassDefinition: DataClassDefinition) { +fun generateDataClass(fileBuilder: FileSpec.Builder, dataClassDefinition: DataClassDefinition) { val dataClassBuilder = TypeSpec.classBuilder(dataClassDefinition.name) dataClassBuilder.addModifiers(KModifier.DATA) val dataClassConstructor = FunSpec.constructorBuilder() @@ -54,7 +55,7 @@ fun generateDataClass(classBuilder: TypeSpec.Builder, dataClassDefinition: DataC .build() ) } - classBuilder.addType(dataClassBuilder.build()) + fileBuilder.addType(dataClassBuilder.build()) } fun generateDocumentationForMethod(builder: FunSpec.Builder, methodSpec: FunctionDefinition) { 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 06ba9e5..91fe139 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 @@ -11,6 +11,11 @@ expect class GenericHashState expect class SecretStreamState +data class SecretStreamStateAndHeader( + val state: SecretStreamState, + val header: UByteArray +) + expect class Crypto internal constructor() { /** * Initialize the SHA256 hash @@ -31,9 +36,4 @@ expect class Crypto internal constructor() { fun crypto_generichash_init(key: UByteArray, outlen: Int): GenericHashState fun crypto_secretstream_xchacha20poly1305_init_push(key: UByteArray): UByteArray - - data class SecretStreamStateAndHeader( - val state: SecretStreamState, - val header: 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 6585ac4..9ad22de 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 @@ -6,6 +6,7 @@ import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array import kotlin.Any import kotlin.Int import kotlin.UByteArray +import org.khronos.webgl.Uint8Array actual typealias Sha256State = Any @@ -59,6 +60,10 @@ actual class Crypto internal actual constructor() { actual fun crypto_secretstream_xchacha20poly1305_init_push(key: UByteArray): dynamic { println("Debug crypto_secretstream_xchacha20poly1305_init_push") - + val stateAndHeader = + getSodium().crypto_secretstream_xchacha20poly1305_init_push(key.toUInt8Array()) + val state = stateAndHeader.state + val header = (stateAndHeader.header as Uint8Array).toUByteArray() + return SecretStreamStateAndHeader(state, header) } } 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 7d5c0a2..5b917e5 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 @@ -69,7 +69,10 @@ actual class Crypto internal actual constructor() { actual fun crypto_secretstream_xchacha20poly1305_init_push(key: UByteArray): UByteArray { println("Debug crypto_secretstream_xchacha20poly1305_init_push") - sodium.crypto_secretstream_xchacha20poly1305_init_push(key.asByteArray()) - return state + val header = UByteArray(24) + val state = SecretStream.State() + sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header.asByteArray(), + key.asByteArray()) + return SecretStreamStateAndHeader(state, header) } } 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 24ee29e..1d2dc33 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 @@ -95,8 +95,15 @@ actual class Crypto internal actual constructor() { actual fun crypto_secretstream_xchacha20poly1305_init_push(key: UByteArray): UByteArray { println("Debug crypto_secretstream_xchacha20poly1305_init_push") val pinnedKey = key.pin() - libsodium.crypto_secretstream_xchacha20poly1305_init_push(pinnedKey.addressOf(0)) - pinnedKey.unpin() - return state + 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) } }